486 lines
10 KiB
Text
486 lines
10 KiB
Text
Class ModuleHitbox : Actor
|
|
{
|
|
Default
|
|
{
|
|
Radius 5;
|
|
Height 4;
|
|
+SHOOTABLE;
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
+NOBLOOD;
|
|
+NOTELEPORT;
|
|
}
|
|
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;
|
|
+NOTELEPORT;
|
|
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;
|
|
}
|
|
}
|