flak_m/zscript/translocator.zsc
Marisa Kirisame 2a9eb0e1b1 Various changes to feel closer to vanilla UT, mainly in terms of projectile gravity and velocity.
Reduced the smoke on the minigun and casings for better performance.
Corrected the number of chunks (was 6, should be 8) fired by the flak cannon.
Reduced flak chunk spread (should be ~5.5 degrees, was double of that) on the weapon and slugs.
Reduced the size of the shock rifle combo shockwave mesh to be closer to vanilla UT.
Misc. tweaks to health item textures.
Reduced the blur in the Redeemer view shader, it was too strong.
Fix expiration messages on powerups appearing on level changes.
Address complaints about how I change Kinsie's test map. Shouldn't be too dark now.
2019-01-24 22:33:09 +01:00

484 lines
10 KiB
Text

Class ModuleHitbox : Actor
{
Default
{
Radius 5;
Height 4;
+SHOOTABLE;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+NOBLOOD;
}
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
{
if ( target )
{
if ( inflictor ) target.vel += level.Vec3Diff(inflictor.pos,pos).unit()*damage*0.2;
else if ( source ) target.vel += level.Vec3Diff(source.pos,pos).unit()*damage*0.2;
target.vel.z = 5;
}
if ( !target || (target.target && ((target.target == source) || target.target.isTeammate(source))) ) return 0;
target.bAMBUSH = true;
return 0;
}
override void Tick()
{
Super.Tick();
if ( !target )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
if ( target.bMISSILE ) return;
let bi = BlockThingsIterator.Create(self,32);
while ( bi.Next() )
{
if ( !bi.Thing || (bi.Thing != target.target) ) continue;
if ( (Distance2D(bi.Thing)-bi.Thing.radius <= radius) && ((bi.Thing.pos.z <= pos.z+height) && (bi.Thing.pos.z+bi.Thing.height >= pos.z-height)) )
{
A_PlaySound("misc/i_pkup");
target.Destroy();
return;
}
}
}
States
{
Spawn:
TNT1 A 10 A_AlertMonsters(0,AMF_TARGETEMITTER);
Wait;
}
}
Class TranslocatorGlowLight : DynamicLight
{
Default
{
DynamicLight.Type "Point";
Args 255,255,255,40;
}
override void Tick()
{
Super.Tick();
if ( !target )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
}
}
Class TranslocatorGlow : Actor
{
override void PostBeginPlay()
{
Super.PostBeginPlay();
let l = Spawn("TranslocatorGlowLight",pos);
l.target = self;
l.args[0] = fillcolor.r;
l.args[1] = fillcolor.g;
l.args[2] = fillcolor.b;
}
override void Tick()
{
Super.Tick();
if ( !target )
{
Destroy();
return;
}
SetOrigin(target.Vec3Offset(0,0,10),true);
}
Default
{
Radius 0.1;
Height 0;
+NOCLIP;
+NOGRAVITY;
+DONTSPLASH;
+FORCEXYBILLBOARD;
RenderStyle "AddShaded";
StencilColor "FFFFFF";
Scale 0.5;
}
States
{
Spawn:
TGLO A -1 Bright;
Stop;
}
}
Class TranslocatorModule : Actor
{
Actor b;
bool alreadyhit;
Default
{
Radius 2;
Height 2;
Speed 16;
PROJECTILE;
-NOGRAVITY;
+USEBOUNCESTATE;
+SKYEXPLODE;
+HITTRACER;
+MOVEWITHSECTOR;
+CANBOUNCEWATER;
+BLOCKASPLAYER;
BounceType "Hexen";
BounceFactor 0.3;
WallBounceFactor 0.3;
Gravity 0.35;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
if ( !target )
{
Destroy();
return;
}
b = Spawn("ModuleHitbox",pos);
b.target = self;
A_PlaySound("transloc/hum",CHAN_VOICE,0.5,true,2.0);
}
override bool CanCollideWith( Actor other, bool passive )
{
return (other != tracer);
}
action void A_LightUp()
{
let l = Spawn("TranslocatorGlow",Vec3Offset(0,0,10));
l.target = self;
if ( !target || !target.player ) return;
Color gcol;
if ( deathmatch && (target.player.GetTeam() < teams.size()) ) gcol = teams[target.player.GetTeam()].mName;
else gcol = target.player.GetColor();
// maximize brightness
if ( (gcol.r+gcol.g+gcol.b) <= 0 ) gcol = "White";
else
{
int maxcomp = max(gcol.r,max(gcol.g,gcol.b));
int newr = int(gcol.r*(255./maxcomp));
int newg = int(gcol.g*(255./maxcomp));
int newb = int(gcol.b*(255./maxcomp));
gcol = Color(newr,newg,newb);
}
l.SetShade(gcol);
}
override void Tick()
{
Super.Tick();
if ( bAMBUSH && !Random[Transloc](0,40) )
{
A_PlaySound("transloc/spark");
int numpt = Random[Transloc](20,40);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Transloc](-1,1),FRandom[Transloc](-1,1),FRandom[Transloc](-1,1)).unit()*FRandom[Transloc](0.1,1.2);
let s = Spawn("UTSmoke",pos);
s.vel = pvel;
s.SetShade(Color(1,1,1)*Random[Transloc](128,192));
}
numpt = Random[Transloc](4,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Transloc](-1,1),FRandom[Transloc](-1,1),FRandom[Transloc](-1,1)).unit()*FRandom[Transloc](2,8);
let s = Spawn("UTSpark",pos);
s.vel = pvel;
}
}
}
States
{
Spawn:
TMOD A 1;
Wait;
Bounce:
TMOD A 0
{
if ( alreadyhit )
{
ClearBounce();
ExplodeMissile();
}
else
{
A_SetPitch(0);
A_PlaySound("transloc/bounce");
if ( BlockingFloor ) alreadyhit = true;
}
}
Goto Spawn;
Death:
TMOD A 0
{
A_SetPitch(0);
if ( tracer )
{
SetOrigin(tracer.Vec2OffsetZ(0,0,pos.z),false);
vel.xy *= 0;
}
}
TMOD A 12;
TMOD B 8;
TMOD C -1 A_LightUp();
Stop;
}
}
Class TranslocatorAfterimage : Actor
{
Vector3 spreaddir;
Default
{
RenderStyle "AddStencil";
StencilColor "FF0000";
+NOCLIP;
+NOGRAVITY;
+DONTSPLASH;
+NOTELEPORT;
Radius 0.1;
Height 0;
Speed 1;
Alpha 0.1;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
if ( !target )
{
Destroy();
return;
}
scale = target.scale;
angle = target.angle;
pitch = target.pitch;
roll = target.roll;
sprite = target.sprite;
frame = target.frame;
vel = (FRandom[Transloc](-.5,.5),FRandom[Transloc](-.5,.5),FRandom[Transloc](-.5,.5));
}
action void A_Spread()
{
vel += invoker.spreaddir*speed;
A_FadeOut(0.003);
}
States
{
Spawn:
#### # 10 A_SetTics(Random[Transloc](20,50));
#### # 1 A_Spread();
Wait;
}
}
Class TranslocatorAmmo : Ammo
{
Default
{
Tag "Translocator Ammo";
Inventory.Amount 6;
Inventory.MaxAmount 6;
Ammo.BackpackAmount 0;
Ammo.BackpackMaxAmount 6;
}
}
Class Translocator : UTWeapon
{
Actor module;
double ammocharge;
override void Tick()
{
Super.Tick();
if ( !Owner ) return;
if ( flak_transloc2k4 )
{
AmmoType1 = "TranslocatorAmmo";
if ( !Ammo1 ) Ammo1 = NonIdioticAddAmmo(Owner,AmmoType1,6);
if ( Ammo1.Amount >= Ammo1.MaxAmount ) return;
if ( ammocharge >= 1. )
{
ammocharge = 0.;
Ammo1.Amount = min(Ammo1.Amount+1,Ammo1.MaxAmount);
}
else ammocharge = min(1.,ammocharge+0.4/TICRATE);
return;
}
if ( Ammo1 ) Ammo1.Destroy();
if ( AmmoType1 ) AmmoType1 = null;
}
action void A_ThrowModule()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
A_PlaySound("transloc/throw",CHAN_WEAPON);
invoker.FireEffect();
UTMainHandler.DoSwing(self,(FRandom[Translocator](-0.2,0.4),FRandom[Translocator](-0.2,0.7)),2,-0.3,3,SWING_Spring,2,3);
A_AlertMonsters();
Vector3 x, y, z;
[x, y, z] = dt_Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x-8.0*y-12.0*z;
let p = Spawn("TranslocatorModule",origin);
p.target = self;
p.angle = angle;
p.pitch = BulletSlope();
p.A_SetSize(radius);
Vector3 dir = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch));
dir.z += 0.35*(1-abs(dir.z));
p.vel = dir*p.speed;
invoker.module = p;
}
action void A_ReturnModule()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
A_PlaySound("transloc/return",CHAN_WEAPON);
invoker.FireEffect();
UTMainHandler.DoSwing(self,(FRandom[Translocator](-0.2,-0.4),FRandom[Translocator](-0.2,0.7)),3,-1,2,SWING_Spring,2,2);
A_AlertMonsters();
if ( invoker.module && invoker.module.bAMBUSH )
{
UTMainHandler.DoFlash(self,Color(255,255,255,255),50);
A_PlaySound("transloc/spark",CHAN_WEAPON);
DamageMobj(invoker,self,int.max,'Telefrag',DMG_THRUSTLESS);
}
if ( invoker.module ) invoker.module.Destroy();
}
action void A_Translocate()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( !invoker.module )
{
invoker.FireEffect();
A_AlertMonsters();
A_PlaySound("transloc/return",CHAN_WEAPON);
return;
}
// consume ammo if any
if ( weap.Ammo1 ) weap.Ammo1.Amount = max(0,weap.Ammo1.Amount-1);
// check if there's enough space
Vector3 oldpos = pos, newpos = invoker.module.pos;
double modulefloorz = invoker.module.floorz, moduleceilingz = invoker.module.ceilingz;
bool bBroken = invoker.module.bAMBUSH;
invoker.module.Destroy();
invoker.FireEffect();
A_AlertMonsters();
// squeeze down new z if ceiling is in the way
if ( (newpos.z+height > moduleceilingz) ) newpos.z = max(modulefloorz,moduleceilingz-height);
if ( Warp(self,newpos.x,newpos.y,newpos.z,flags:WARPF_ABSOLUTEPOSITION|WARPF_TESTONLY) && TeleportMove(newpos,true) )
{
SpawnTeleportFog(oldpos,true,false);
Vector3 diff = level.Vec3Diff(oldpos,newpos);
for ( int i=0; i<40; i++ )
{
let a = Spawn("TranslocatorAfterimage",oldpos);
a.target = self;
TranslocatorAfterimage(a).spreaddir = diff.unit();
a.speed = (diff.length()/400)**0.5;
}
SpawnTeleportFog(newpos,false,false);
player.fov = min(175,player.desiredfov+60);
}
else A_PlaySound("transloc/return",CHAN_WEAPON);
if ( bBroken )
{
UTMainHandler.DoFlash(self,Color(255,255,255,255),50);
A_PlaySound("transloc/spark",CHAN_WEAPON);
DamageMobj(invoker,self,int.max,'Telefrag',DMG_THRUSTLESS);
}
}
override void OnDestroy()
{
Super.OnDestroy();
if ( module ) module.Destroy();
}
Default
{
Tag "Translocator";
Inventory.PickupMessage "You got the Translocator Source Module.";
Weapon.SlotNumber 1;
Weapon.SelectionOrder 10;
+WEAPON.NO_AUTO_SWITCH;
+WEAPON.CHEATNOTWEAPON;
+WEAPON.AMMO_OPTIONAL;
+WEAPON.ALT_AMMO_OPTIONAL;
}
States
{
Spawn:
TLCP A -1;
Stop;
TLCP B -1;
Stop;
Select:
TLCS A 1 A_Raise(int.max);
Wait;
Ready:
TLCS A 0 A_JumpIf(invoker.module,"Ready2");
TLCS ABCDEFGHIJKL 1 A_WeaponReady(WRF_NOFIRE);
TLCS L 0 A_JumpIf(invoker.module,"Idle");
Goto Idle2;
Ready2:
TLD2 GFEDCBA 2 A_WeaponReady(WRF_NOFIRE);
Idle:
TLCI A 0 A_Overlay(-9999,"Dummy"); // little hackeroo to make this more responsive
TLCI AB 25 A_JumpIf(!invoker.module,"PickedUp");
Goto Idle+1;
Dummy:
TNT1 A 2
{
A_WeaponReady();
return A_JumpIf(!invoker.module,"Null");
}
Wait;
Idle2:
TLI2 ABCDEFGHIJKLMNOPQRS 2 A_WeaponReady(WRF_NOSECONDARY);
Loop;
PickedUp:
TLCI A 5;
TLI2 A 0;
Goto Idle2;
Fire:
TLCF A 0 A_JumpIf(invoker.module||(invoker.Ammo1&&invoker.Ammo1.Amount<=0),"Return");
TLCF A 0 A_ThrowModule();
TLCF ABCDEFGH 1;
TLCF IJKLMNOPQRS 1 A_WeaponReady(WRF_NOPRIMARY);
Goto Idle;
Return:
TLCF A 0 A_ReturnModule();
TLCF ABCDEFGH 1;
Goto Idle2;
AltFire:
TLCT A 0 A_Translocate();
TLCT ABCDEFGHIJKLM 1;
Goto Idle2;
Deselect:
TLCD A 0 A_JumpIf(invoker.module,"Deselect2");
TLCD ABCDEFG 1;
TLCD G 1 A_Lower(int.max);
Wait;
Deselect2:
TLD2 ABCDEFG 1;
TLD2 G 1 A_Lower(int.max);
Wait;
}
}