775 lines
19 KiB
Text
775 lines
19 KiB
Text
// wasn't placeable in UT99
|
|
Class WarheadAmmo : Ammo
|
|
{
|
|
int OldSkin;
|
|
|
|
void A_CheckSkin()
|
|
{
|
|
switch ( flak_oldredeemer )
|
|
{
|
|
case 1:
|
|
if ( OldSkin != 1 ) A_ChangeModel("WarheadAmmo220");
|
|
OldSkin = 1;
|
|
break;
|
|
case 2:
|
|
if ( OldSkin != 2 ) A_ChangeModel("WarheadAmmo222");
|
|
OldSkin = 2;
|
|
break;
|
|
default:
|
|
if ( OldSkin != 0 ) A_ChangeModel("WarheadAmmo");
|
|
OldSkin = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Default
|
|
{
|
|
Tag "$T_WARHEADAMMO";
|
|
Inventory.PickupMessage "$I_WARHEADAMMO";
|
|
Inventory.Amount 1;
|
|
Inventory.MaxAmount 2;
|
|
Ammo.BackpackAmount 0;
|
|
Ammo.BackpackMaxAmount 3;
|
|
Ammo.DropAmount 1;
|
|
Inventory.RespawnTics 2100;
|
|
+INVENTORY.IGNORESKILL;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
WMIS A 1 A_CheckSkin();
|
|
Wait;
|
|
}
|
|
}
|
|
|
|
// dummies so we can copy MODELDEF
|
|
Class WarheadAmmo220 : Actor abstract {}
|
|
Class WarheadAmmo222 : Actor abstract {}
|
|
|
|
Class ShockWave : Actor
|
|
{
|
|
double shocksize, olddmgradius;
|
|
double lifespan;
|
|
int icount;
|
|
transient ThinkerIterator t;
|
|
Default
|
|
{
|
|
Obituary "$O_REDEEMER";
|
|
RenderStyle "Add";
|
|
Radius 0.1;
|
|
Height 0;
|
|
Scale 1.0;
|
|
ReactionTime 60;
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+DONTSPLASH;
|
|
+NOTELEPORT;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
switch ( flak_oldredeemer )
|
|
{
|
|
case 1:
|
|
A_ChangeModel("",0,"","",0,"models/220","Shockt1.png");
|
|
break;
|
|
case 2:
|
|
A_ChangeModel("",0,"","",0,"models/222","Shockt1.png");
|
|
break;
|
|
default:
|
|
// change nothing
|
|
break;
|
|
}
|
|
lifespan = ReactionTime;
|
|
A_StartSound("warhead/explode",CHAN_VOICE,attenuation:ATTN_NONE);
|
|
A_QuakeEx(9,9,9,100,0,12000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:1200,rollIntensity:0.5);
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( isFrozen() ) return;
|
|
if ( alpha <= 0 ) return;
|
|
if ( !t ) t = ThinkerIterator.Create("Actor");
|
|
icount++;
|
|
if ( icount == 4 ) Spawn("WarheadSubExplosion",pos);
|
|
lifespan--;
|
|
alpha -= 1./ReactionTime;
|
|
shocksize = 13*(ReactionTime-lifespan)+3.5/(lifespan/ReactionTime+0.05);
|
|
A_SetScale(shocksize*0.25);
|
|
double dmgradius = shocksize*1.5;
|
|
Actor a;
|
|
t.Reinit();
|
|
while ( a = Actor(t.Next()) )
|
|
{
|
|
if ( !a.bShootable || !CheckSight(a,0xf) || (Distance3D(a) > dmgradius) ) continue;
|
|
Vector3 dir = Vec3To(a);
|
|
double dist = max(1,dir.length());
|
|
dir = dir/dist+(0,0,0.3);
|
|
double moscale = max(0,1100-0.22*dist);
|
|
if ( (dist > olddmgradius-a.radius) || (dir dot a.vel <= 0) )
|
|
{
|
|
if ( !a.bDONTTHRUST ) a.vel += dir*((moscale+20)/a.mass);
|
|
a.DamageMobj(self,target,int(moscale),'RedeemerDeath',DMG_THRUSTLESS);
|
|
}
|
|
if ( a.player ) UTMainHandler.DoFlash(a,Color(32,255,255,255),80);
|
|
}
|
|
olddmgradius = dmgradius;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
RWAV A 100 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class WarheadSubExplosion : Actor
|
|
{
|
|
Default
|
|
{
|
|
Renderstyle "Add";
|
|
Scale 2.8;
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
+FORCEXYBILLBOARD;
|
|
+NOTELEPORT;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
Spawn("WarheadExplodLight",pos);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
WE__ ABCDEFGHIJKLMNOPR 3 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class WarheadHitbox : Actor
|
|
{
|
|
Default
|
|
{
|
|
Radius 2;
|
|
Height 4;
|
|
+SHOOTABLE;
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
+NOBLOOD;
|
|
+NOTELEPORT;
|
|
}
|
|
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
|
|
{
|
|
if ( (damage > 5) && target )
|
|
{
|
|
target.bAMBUSH = true;
|
|
target.ExplodeMissile(null,inflictor);
|
|
}
|
|
return 0;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
SetOrigin(target.Vec3Offset(0,0,-height*0.5),true);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A 10 A_AlertMonsters(0,AMF_TARGETEMITTER);
|
|
Wait;
|
|
}
|
|
}
|
|
|
|
Class WarheadExplodLight : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
ReactionTime 50;
|
|
Args 0,0,0,300;
|
|
}
|
|
}
|
|
|
|
Class WarheadLight : DynamicLight
|
|
{
|
|
Default
|
|
{
|
|
DynamicLight.Type "Point";
|
|
Args 255,224,192,70;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Vector3 taildir = -dt_Utility.Vec3FromAngle(target.angle,target.pitch);
|
|
SetOrigin(level.Vec3Offset(pos,taildir*20),true);
|
|
args[LIGHT_INTENSITY] = Random[Warhead](6,8)*10;
|
|
}
|
|
}
|
|
|
|
Class WarheadTrail : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Radius 0.1;
|
|
Height 0;
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
+FORCEXYBILLBOARD;
|
|
+ROLLSPRITE;
|
|
+ROLLCENTER;
|
|
+NOTELEPORT;
|
|
Scale 0.2;
|
|
}
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
double ang, pt;
|
|
scale *= FRandom[Puff](0.5,1.5);
|
|
alpha *= FRandom[Puff](0.5,1.5);
|
|
ang = FRandom[Puff](0,360);
|
|
pt = FRandom[Puff](-90,90);
|
|
vel += dt_Utility.Vec3FromAngle(ang,pt)*FRandom[Puff](0.2,0.8);
|
|
roll = FRandom[Puff](0,360);
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( isFrozen() ) return;
|
|
vel *= 0.99;
|
|
A_FadeOut(0.1);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
RTRL A -1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class WarShell : Actor
|
|
{
|
|
double destangle, destpitch;
|
|
Actor l, b;
|
|
int OldSkin;
|
|
|
|
Default
|
|
{
|
|
Obituary "$O_REDEEMER";
|
|
Radius 2;
|
|
Height 2;
|
|
Speed 6;
|
|
DamageType 'RedeemerDeath';
|
|
DamageFactor 1000;
|
|
PROJECTILE;
|
|
+FORCEXYBILLBOARD;
|
|
+SKYEXPLODE;
|
|
+FORCERADIUSDMG;
|
|
+EXPLODEONWATER;
|
|
+INTERPOLATEANGLES;
|
|
+NOFRICTION;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
l = Spawn("Warheadlight",pos);
|
|
l.target = self;
|
|
b = Spawn("WarheadHitbox",pos);
|
|
b.target = self;
|
|
A_StartSound("warhead/fly",CHAN_VOICE,CHANF_LOOPING);
|
|
destangle = angle;
|
|
destpitch = pitch;
|
|
}
|
|
override int SpecialMissileHit( Actor victim )
|
|
{
|
|
if ( victim == b ) return 1;
|
|
return -1;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( isFrozen() ) return;
|
|
if ( !bMISSILE ) return;
|
|
if ( vel.length() > 0 )
|
|
{
|
|
if ( waterlevel > 0 )
|
|
{
|
|
vel *= 0.98;
|
|
if ( vel.length() < 6 ) vel += vel.unit()*0.35;
|
|
}
|
|
else if ( vel.length() < 20 ) vel += vel.unit()*0.35;
|
|
}
|
|
}
|
|
void A_CheckSkin()
|
|
{
|
|
switch ( flak_oldredeemer )
|
|
{
|
|
case 1:
|
|
if ( OldSkin != 1 ) A_ChangeModel("Warshell220");
|
|
OldSkin = 1;
|
|
break;
|
|
case 2:
|
|
if ( OldSkin != 2 ) A_ChangeModel("Warshell222");
|
|
OldSkin = 2;
|
|
break;
|
|
default:
|
|
if ( OldSkin != 0 ) A_ChangeModel("Warshell");
|
|
OldSkin = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
action void A_Trail()
|
|
{
|
|
invoker.A_CheckSkin();
|
|
Vector3 taildir = -dt_Utility.Vec3FromAngle(angle,pitch);
|
|
if ( waterlevel > 0 )
|
|
{
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
let s = Spawn("UTBubble",pos+taildir*32+(FRandom[Warhead](-.5,.5),FRandom[Warhead](-.5,.5),FRandom[Warhead](-.5,.5)));
|
|
s.vel = taildir*2;
|
|
}
|
|
return;
|
|
}
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
let s = Spawn("UTSmoke",pos+taildir*32+(FRandom[Warhead](-.5,.5),FRandom[Warhead](-.5,.5),FRandom[Warhead](-.5,.5)));
|
|
s.vel = taildir*2;
|
|
s.SetShade("404040");
|
|
}
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
let s = Spawn("WarheadTrail",pos+taildir*35+(FRandom[Warhead](-1,1),FRandom[Warhead](-1,1),FRandom[Warhead](-1,1)));
|
|
s.vel = taildir*4;
|
|
}
|
|
}
|
|
action void A_Vaporize()
|
|
{
|
|
if ( invoker.l ) invoker.l.Destroy();
|
|
if ( invoker.b ) invoker.b.Destroy();
|
|
A_SetScale(2.0);
|
|
A_Explode(1000,180);
|
|
A_SprayDecal("BigBlast");
|
|
A_QuakeEx(8,8,8,20,0,300,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.35);
|
|
A_StartSound("shock/hit",CHAN_VOICE,attenuation:0.5);
|
|
A_AlertMonsters();
|
|
A_SetRenderStyle(1.0,STYLE_Add);
|
|
Spawn("WarheadExplodLight",pos);
|
|
let s = Spawn("ShockWave",pos);
|
|
s.target = target;
|
|
}
|
|
action void A_Intercepted()
|
|
{
|
|
if ( invoker.l ) invoker.l.Destroy();
|
|
if ( invoker.b ) invoker.b.Destroy();
|
|
A_Explode(1000,220);
|
|
A_SprayDecal("BigBlast");
|
|
A_QuakeEx(8,8,8,20,0,300,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.35);
|
|
A_StartSound("shock/hit",CHAN_VOICE,attenuation:0.5);
|
|
A_AlertMonsters();
|
|
A_SetRenderStyle(1.0,STYLE_Add);
|
|
Spawn("WarheadExplodLight",pos);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
WMIS A 1 A_Trail();
|
|
Wait;
|
|
Death:
|
|
TNT1 A 0 A_JumpIf(bAMBUSH,"Death.Intercept");
|
|
TNT1 A 0 A_Vaporize();
|
|
NE__ ABCDEFGHIJKLMNOPR 3 Bright;
|
|
Stop;
|
|
Death.Intercept:
|
|
TNT1 A 0 A_Intercepted();
|
|
WE__ ABCDEFGHIJKLMNOPR 3 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class GuidedWarShell : WarShell
|
|
{
|
|
double lagangle, lagpitch, lagroll, lagangle2, lagpitch2, lagroll2,
|
|
guideangle, guidepitch, guideroll;
|
|
bool justleft;
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
if ( target && target.player ) target.player.camera = self;
|
|
A_StartSound("warhead/altfire",CHAN_WEAPON,CHANF_LOCAL);
|
|
justleft = true;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Actor.Tick();
|
|
if ( justleft && (Distance3D(target) > (2*max(target.radius,target.height))) )
|
|
{
|
|
justleft = false;
|
|
bHITOWNER = true;
|
|
}
|
|
if ( isFrozen() ) return;
|
|
if ( !bMISSILE ) return;
|
|
if ( !target || !target.player || (target.Health <= 0) )
|
|
{
|
|
bAMBUSH = true;
|
|
ExplodeMissile();
|
|
return;
|
|
}
|
|
if ( target.player.cmd.buttons&BT_ATTACK )
|
|
{
|
|
ExplodeMissile();
|
|
return;
|
|
}
|
|
if ( vel.length() > 0 )
|
|
{
|
|
lagangle = target.player.cmd.yaw/128.;
|
|
lagpitch = -target.player.cmd.pitch/128.;
|
|
if ( target.player.cmd.buttons&BT_RELOAD ) lagroll = 5;
|
|
else if ( target.player.cmd.buttons&BT_ZOOM ) lagroll = -5;
|
|
else lagroll = 0;
|
|
guideangle = lagangle2*0.95+lagangle*0.05;
|
|
guidepitch = lagpitch2*0.95+lagpitch*0.05;
|
|
guideroll = lagroll2*0.95+lagroll*0.05;
|
|
Quat orient = Quat.FromAngles(angle,pitch,roll);
|
|
Quat angles = Quat.FromAngles(guideangle,guidepitch,guideroll);
|
|
orient *= angles;
|
|
double nangle, npitch, nroll;
|
|
[nangle, npitch, nroll] = dt_Utility.ToAngles(orient);
|
|
angle = nangle;
|
|
pitch = npitch;
|
|
roll = nroll;
|
|
vel = (vel+dt_Utility.Vec3FromAngle(angle,pitch)*0.8).unit()*11;
|
|
}
|
|
lagangle2 = lagangle2*0.95+lagangle*0.05;
|
|
lagpitch2 = lagpitch2*0.95+lagpitch*0.05;
|
|
lagroll2 = lagroll2*0.95+lagroll*0.05;
|
|
}
|
|
States
|
|
{
|
|
Death:
|
|
TNT1 A 0
|
|
{
|
|
if ( WarheadLauncher(master) )
|
|
WarheadLauncher(master).Guided = null;
|
|
if ( target && target.player && target.player.camera == self ) target.player.camera = target;
|
|
}
|
|
Goto Super::Death;
|
|
}
|
|
}
|
|
|
|
// dummies so we can copy MODELDEF
|
|
Class Warshell220 : Actor abstract {}
|
|
Class Warshell222 : Actor abstract {}
|
|
|
|
Class MidTracer : LineTracer
|
|
{
|
|
override ETraceStatus TraceCallback()
|
|
{
|
|
if ( Results.HitType == TRACE_HitActor ) return TRACE_Skip;
|
|
else if ( (Results.HitType == TRACE_HitWall) && (Results.Tier == TIER_Middle) )
|
|
{
|
|
if ( !Results.HitLine.sidedef[1] ) return TRACE_Stop;
|
|
return TRACE_Skip;
|
|
}
|
|
return TRACE_Stop;
|
|
}
|
|
}
|
|
|
|
Class RedeemerHUD : HUDMessageBase
|
|
{
|
|
Actor Camera;
|
|
Vector3 ViewPos;
|
|
double ViewAngle, ViewPitch, ViewRoll, LagRoll, LagRoll2, OldLagRoll2;
|
|
TextureID reticle1, reticle2, arrow, mark, readout;
|
|
Font whfont;
|
|
transient ThinkerIterator t;
|
|
transient MidTracer tr;
|
|
bool dodim;
|
|
dt_ProjectionData projdata;
|
|
|
|
RedeemerHUD Init()
|
|
{
|
|
reticle1 = TexMan.CheckForTexture("GuidedX1",TexMan.Type_Any);
|
|
reticle2 = TexMan.CheckForTexture("GuidedX2",TexMan.Type_Any);
|
|
arrow = TexMan.CheckForTexture("AroDup",TexMan.Type_Any);
|
|
mark = TexMan.CheckForTexture("Crosshr6",TexMan.Type_Any);
|
|
readout = TexMan.CheckForTexture("Readout",TexMan.Type_Any);
|
|
whfont = Font.GetFont('WHFONT');
|
|
return self;
|
|
}
|
|
override bool Tick()
|
|
{
|
|
|
|
LagRoll = Actor.Normalize180(ViewRoll-LagRoll2);
|
|
OldLagRoll2 = LagRoll2;
|
|
LagRoll2 += Actor.Normalize180(LagRoll-LagRoll2)*0.1;
|
|
return !Camera;
|
|
}
|
|
override void Draw( int bottom, int visibility )
|
|
{
|
|
if ( visibility != StatusBar.HUDMSGLayer_UnderHUD ) return;
|
|
if ( dodim ) Screen.Dim("C8 00 00",0.2,0,0,Screen.GetWidth(),Screen.GetHeight());
|
|
// shootable targetting
|
|
if ( flak_redeemerreadout )
|
|
{
|
|
dt_Utility.PrepareProjData(projdata,ViewPos,ViewAngle,ViewPitch,ViewRoll,players[consoleplayer].fov);
|
|
if ( !t ) t = ThinkerIterator.Create("Actor");
|
|
else t.Reinit();
|
|
if ( !tr ) tr = new("MidTracer");
|
|
Actor a;
|
|
Vector3 vdir = dt_Utility.Vec3FromAngle(ViewAngle,ViewPitch);
|
|
while ( a = Actor(t.Next()) )
|
|
{
|
|
Vector3 tdir = Level.Vec3Diff(ViewPos,a.Pos+(0,0,a.Height*0.5));
|
|
if ( !a.bSHOOTABLE || (a.Health <= 0) || ((Camera is 'GuidedWarShell') && (a == GuidedWarShell(Camera).b)) || (tdir.length() > 2000) || (acos(tdir.unit() dot vdir) > players[consoleplayer].FOV) || tr.Trace(ViewPos,Camera.CurSector,tdir.unit(),tdir.length(),0) ) continue;
|
|
Vector3 ndc = dt_Utility.ProjectPoint(projdata,ViewPos+tdir);
|
|
if ( ndc.z >= 1. ) continue;
|
|
Vector2 vpos = dt_Utility.NDCToViewport(projdata,ndc);
|
|
String diststr = String.Format("%f",tdir.length());
|
|
diststr.Replace(".","");
|
|
Screen.DrawTexture(mark,false,vpos.x,vpos.y,DTA_LegacyRenderStyle,STYLE_Add);
|
|
Screen.DrawText(whfont,Font.CR_UNTRANSLATED,(vpos.x-whfont.StringWidth(diststr)/2)-12,vpos.y+8,diststr,DTA_LegacyRenderStyle,STYLE_Add);
|
|
}
|
|
}
|
|
// reticle
|
|
double fractic = System.GetTimeFrac();
|
|
double rrot = -(LagRoll2*fractic+OldLagRoll2*(1.-fractic))*2;
|
|
double scl = Screen.GetWidth()/640.;
|
|
Screen.DrawTexture(reticle1,false,Screen.GetWidth()/2,Screen.GetHeight()/2,DTA_ScaleX,scl,DTA_ScaleY,scl,DTA_LegacyRenderStyle,STYLE_Add,DTA_Rotate,rrot);
|
|
Vector2 apos = Actor.AngleToVector(rrot+90,140*scl);
|
|
Screen.DrawTexture(arrow,false,Screen.GetWidth()/2+apos.x,Screen.GetHeight()/2+apos.y,DTA_ScaleX,scl,DTA_ScaleY,scl,DTA_LegacyRenderStyle,STYLE_Add,DTA_Rotate,-rrot);
|
|
Screen.DrawTexture(reticle2,false,Screen.GetWidth()/2,Screen.GetHeight()/2,DTA_ScaleX,scl,DTA_ScaleY,scl,DTA_LegacyRenderStyle,STYLE_Add);
|
|
// faux assembly readout
|
|
double scroll = ((gametic+fractic)*5.)%128;
|
|
double y = -scroll*scl;
|
|
while ( y < Screen.GetHeight() )
|
|
{
|
|
Screen.DrawTexture(readout,false,0,y,DTA_ScaleX,scl,DTA_ScaleY,scl,DTA_LegacyRenderStyle,STYLE_Add);
|
|
y += 128*scl;
|
|
}
|
|
}
|
|
}
|
|
|
|
Class RedeemerHUDStatic : HUDMessageBase
|
|
{
|
|
int tickcnt;
|
|
TextureID tx;
|
|
|
|
RedeemerHUDStatic Init()
|
|
{
|
|
tx = TexMan.CheckForTexture("static1",TexMan.Type_Any);
|
|
tickcnt = 0;
|
|
return self;
|
|
}
|
|
override bool Tick()
|
|
{
|
|
return (++tickcnt>15);
|
|
}
|
|
override void Draw( int bottom, int visibility )
|
|
{
|
|
if ( visibility != StatusBar.HUDMSGLayer_UnderHUD ) return;
|
|
double scl = max(Screen.GetWidth()/256.,Screen.GetHeight()/256.);
|
|
Screen.DrawTexture(tx,true,0,0,DTA_ScaleX,scl,DTA_ScaleY,scl);
|
|
}
|
|
}
|
|
|
|
Class WarheadLauncher : UTWeapon
|
|
{
|
|
transient CVar noswitchdeemer;
|
|
Actor guided;
|
|
int OldSkin;
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
switch ( flak_oldredeemer )
|
|
{
|
|
case 1:
|
|
if ( OldSkin != 1 )
|
|
{
|
|
A_ChangeModel("",1,"","",1,"models/220","Jwhpick1.png");
|
|
A_ChangeModel("",0,"","",0,"models/220","Jwarhead1.png",CMDL_USESURFACESKIN);
|
|
A_ChangeModel("",0,"","",1,"models/220","Jwarhead2.png",CMDL_USESURFACESKIN);
|
|
A_ChangeModel("",0,"","",2,"models/220","Jwarhead3.png",CMDL_USESURFACESKIN);
|
|
A_ChangeModel("",0,"","",3,"models/220","Jwarhead4.png",CMDL_USESURFACESKIN);
|
|
}
|
|
OldSkin = 1;
|
|
break;
|
|
case 2:
|
|
if ( OldSkin != 2 )
|
|
{
|
|
A_ChangeModel("",1,"","",1,"models/222","Jwhpick1.png");
|
|
A_ChangeModel("",0,"","",0,"models/222","Jwarhead1.png",CMDL_USESURFACESKIN);
|
|
A_ChangeModel("",0,"","",1,"models/222","Jwarhead2.png",CMDL_USESURFACESKIN);
|
|
A_ChangeModel("",0,"","",2,"models/222","Jwarhead3.png",CMDL_USESURFACESKIN);
|
|
A_ChangeModel("",0,"","",3,"models/222","Jwarhead4.png",CMDL_USESURFACESKIN);
|
|
}
|
|
OldSkin = 2;
|
|
break;
|
|
default:
|
|
if ( OldSkin != 0 )
|
|
{
|
|
A_ChangeModel("",1,"","",1,"models","Jwhpick1.png");
|
|
A_ChangeModel("",0,"","",0,"models","Jwarhead1.png",CMDL_USESURFACESKIN);
|
|
A_ChangeModel("",0,"","",1,"models","Jwarhead2.png",CMDL_USESURFACESKIN);
|
|
A_ChangeModel("",0,"","",2,"models","Jwarhead3.png",CMDL_USESURFACESKIN);
|
|
A_ChangeModel("",0,"","",3,"models","Jwarhead4.png",CMDL_USESURFACESKIN);
|
|
}
|
|
OldSkin = 0;
|
|
break;
|
|
}
|
|
if ( !Owner || !Owner.player ) return;
|
|
if ( guided ) crosshair = 99;
|
|
else crosshair = 0;
|
|
if ( !noswitchdeemer ) noswitchdeemer = CVar.GetCVar('flak_noswitchdeemer',Owner.player);
|
|
if ( noswitchdeemer.GetBool() ) SelectionOrder = int.max;
|
|
else SelectionOrder = 0;
|
|
}
|
|
action void A_WarheadFire()
|
|
{
|
|
Weapon weap = Weapon(invoker);
|
|
if ( !weap ) return;
|
|
if ( weap.Ammo1.Amount <= 0 ) return;
|
|
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
|
|
A_StartSound("warhead/fire",CHAN_WEAPON,CHANF_OVERLAP);
|
|
invoker.FireEffect();
|
|
UTMainHandler.DoFlash(self,Color(128,255,128,128),1);
|
|
A_AlertMonsters();
|
|
A_QuakeEx(6,6,6,20,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.2);
|
|
vel -= dt_Utility.GetPlayerViewDir(self)*10;
|
|
Vector3 origin = dt_Utility.GetFireOffset(self,10,2,-2);
|
|
Actor p = Spawn("WarShell",origin);
|
|
p.angle = angle;
|
|
p.pitch = BulletSlope();
|
|
p.vel = dt_Utility.Vec3FromAngle(p.angle,p.pitch)*p.speed;
|
|
p.target = self;
|
|
}
|
|
action void A_WarheadSmoke()
|
|
{
|
|
Weapon weap = Weapon(invoker);
|
|
if ( !weap ) return;
|
|
Vector3 x, y, z;
|
|
[x, y, z] = dt_Utility.GetPlayerAxes(self);
|
|
vel -= x*0.2;
|
|
Vector3 origin = dt_Utility.GetFireOffset(self,10,2,-2);
|
|
int numpt = Random[Warhead](10,20);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (x+(FRandom[Warhead](-.8,.8),FRandom[Warhead](-.8,.8),FRandom[Warhead](-.8,.8))).unit()*FRandom[Warhead](1,2);
|
|
let s = Spawn("UTSmoke",origin);
|
|
s.vel = pvel;
|
|
s.SetShade(Color(1,1,1)*Random[Warhead](32,128));
|
|
}
|
|
}
|
|
action void A_WarheadAlt()
|
|
{
|
|
Weapon weap = Weapon(invoker);
|
|
if ( !weap ) return;
|
|
if ( weap.Ammo1.Amount <= 0 ) return;
|
|
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
|
|
A_StartSound("warhead/altfire",CHAN_WEAPON,CHANF_OVERLAP);
|
|
invoker.FireEffect();
|
|
UTMainHandler.DoFlash(self,Color(128,255,128,128),1);
|
|
A_AlertMonsters();
|
|
A_QuakeEx(6,6,6,20,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.2);
|
|
vel -= dt_Utility.GetPlayerViewDir(self)*10;
|
|
Vector3 origin = dt_Utility.GetFireOffset(self,10,2,-2);
|
|
Actor p = Spawn("GuidedWarShell",origin);
|
|
p.angle = angle;
|
|
p.pitch = BulletSlope();
|
|
p.vel = dt_Utility.Vec3FromAngle(p.angle,p.pitch)*p.speed;
|
|
p.target = self;
|
|
p.master = invoker;
|
|
invoker.guided = p;
|
|
}
|
|
|
|
// disallow dropping while guiding
|
|
override Inventory CreateTossable( int amt )
|
|
{
|
|
if ( guided ) return null;
|
|
return Super.CreateTossable();
|
|
}
|
|
|
|
override void OwnerDied()
|
|
{
|
|
Super.OwnerDied();
|
|
if ( guided ) guided.ExplodeMissile();
|
|
}
|
|
|
|
override void OnDestroy()
|
|
{
|
|
Super.OnDestroy();
|
|
if ( guided ) guided.ExplodeMissile();
|
|
}
|
|
|
|
Default
|
|
{
|
|
Tag "$T_REDEEMER";
|
|
Inventory.PickupMessage "$I_REDEEMER";
|
|
Weapon.UpSound "warhead/select";
|
|
Weapon.SlotNumber 0;
|
|
Weapon.SelectionOrder 0;
|
|
Weapon.AmmoType "WarheadAmmo";
|
|
Weapon.AmmoUse 1;
|
|
Weapon.AmmoType2 "WarheadAmmo";
|
|
Weapon.AmmoUse2 1;
|
|
Weapon.AmmoGive 1;
|
|
Inventory.RespawnTics 2100;
|
|
+INVENTORY.ALWAYSPICKUP;
|
|
+INVENTORY.IGNORESKILL;
|
|
+WEAPON.NOAUTOFIRE;
|
|
UTWeapon.DropAmmo 1;
|
|
UTWeapon.NameColor "FF 80 80";
|
|
UTWeapon.BobDamping .45;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
RDMP A -1;
|
|
Stop;
|
|
RDMP B -1;
|
|
Stop;
|
|
Ready:
|
|
WARS ABCDEFGHIJKLMNO 1 A_WeaponReady(WRF_NOFIRE);
|
|
Idle:
|
|
WARI A 1
|
|
{
|
|
A_CheckReload();
|
|
A_WeaponReady();
|
|
}
|
|
Wait;
|
|
Fire:
|
|
WARF A 4 A_WarheadFire();
|
|
WARF BCDEFG 4 A_WarheadSmoke();
|
|
WARI A 5;
|
|
Goto Idle;
|
|
AltFire:
|
|
WARF A 4 A_WarheadAlt();
|
|
WARF BCDEFG 4 A_WarheadSmoke();
|
|
WARI A 1 A_JumpIf(!invoker.Guided,1);
|
|
Wait;
|
|
WARI A 30;
|
|
Goto Idle;
|
|
Select:
|
|
WARS A 1 A_Raise(int.max);
|
|
Wait;
|
|
Deselect:
|
|
WARD ABCDEFG 1;
|
|
WARD G 1 A_Lower(int.max);
|
|
Wait;
|
|
}
|
|
}
|