Support new versions of Kinsie's test map. Switch to new GetAxes implementation across the board. Minor fixes here and there.
484 lines
10 KiB
Text
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 "$T_TRANSLOCATORAMMO";
|
|
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_CoordUtil.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 "$T_TRANSLOCATOR";
|
|
Inventory.PickupMessage "$I_TRANSLOCATOR";
|
|
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;
|
|
}
|
|
}
|