Double capacity with backpack for all ammo (except Redeemer, it just gets one extra). Made Enhanced Shock Rifle ammo drain over time (1 unit per second). Uncapped health and armor numbers in the HUD. Fixed Jump Boots not persisting between levels. Increased duration of invisibility. Made translocator toggleable (currently requires manually selecting "apply changes" under the menu option).
434 lines
8.9 KiB
Text
434 lines
8.9 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;
|
|
|
|
Default
|
|
{
|
|
Radius 2;
|
|
Height 2;
|
|
Speed 25;
|
|
PROJECTILE;
|
|
-NOGRAVITY;
|
|
+USEBOUNCESTATE;
|
|
+SKYEXPLODE;
|
|
+HITTRACER;
|
|
+MOVEWITHSECTOR;
|
|
+CANBOUNCEWATER;
|
|
-BOUNCEAUTOOFF;
|
|
+BOUNCEAUTOOFFFLOORONLY;
|
|
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();
|
|
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();
|
|
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;
|
|
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;
|
|
}
|
|
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,"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 1;
|
|
TLCD G 1 A_Lower(int.max);
|
|
Wait;
|
|
Deselect2:
|
|
TLD2 ABCDEFG 1;
|
|
TLD2 G 1 A_Lower(int.max);
|
|
Wait;
|
|
}
|
|
}
|