flak_m/zscript/translocator.zsc
Marisa Kirisame a6ccec0997 Began working on Rocket Launcher.
Corrected some stuff and tweaked models and offsets again.
Added gib impact sounds (Droplets compat).
Made Translocator module throwing work like in UT (same math, even).
Corrected sludge wall sticking, uses projection now rather than a cheap trace.
2018-05-30 01:36:38 +02:00

420 lines
8.5 KiB
Text

Class ModuleHitbox : Actor
{
Default
{
Radius 10;
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-(0,0,height*0.5),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;
Default
{
Radius 2;
Height 2;
Speed 25;
PROJECTILE;
-NOGRAVITY;
+USEBOUNCESTATE;
+SKYEXPLODE;
+HITTRACER;
+MOVEWITHSECTOR;
BounceType "Doom";
BounceFactor 0.5;
WallBounceFactor 0.5;
}
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
{
A_SetPitch(0);
A_PlaySound("transloc/bounce");
}
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 Translocator : UTWeapon
{
Actor module;
action void A_ThrowModule()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
A_PlaySound("transloc/throw",CHAN_WEAPON);
invoker.FireEffect();
A_AlertMonsters();
Vector3 x, y, z;
[x, y, z] = 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();
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();
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;
}
// check if there's enough space
Vector3 oldpos = pos, newpos = invoker.module.pos;
bool bBroken = invoker.module.bAMBUSH;
invoker.module.Destroy();
invoker.FireEffect();
A_AlertMonsters();
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);
}
}
Default
{
Tag "Translocator";
Inventory.PickupMessage "You got the Translocator Source Module.";
Weapon.SlotNumber 1;
Weapon.SelectionOrder 10;
+WEAPON.NO_AUTO_SWITCH;
}
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;
TLCS L 0 A_JumpIf(invoker.module,"Idle");
Goto Idle2;
Ready2:
TLD2 GFEDCBA 2;
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,"Return");
TLCF A 0 A_ThrowModule();
TLCF ABCDEFGH 1;
TLCF IJKLMNOPQRS 1 A_WeaponReady();
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 2;
TLCD G 1 A_Lower(int.max);
Wait;
Deselect2:
TLD2 ABCDEFG 2;
TLD2 G 1 A_Lower(int.max);
Wait;
}
}