Switched Impaler fire sound to something more appropriate (proto Skaarj fire). Add slot priorities to all weapons, final weapons come first. Adjust hud behavior to properly draw ammo bars by the order of their weapons.
712 lines
16 KiB
Text
712 lines
16 KiB
Text
Class StingerAmmo : Ammo
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_STINGERAMMO";
|
|
Inventory.Icon "I_Stingr";
|
|
Inventory.PickupMessage "";
|
|
Inventory.Amount 5;
|
|
Inventory.MaxAmount 200;
|
|
Ammo.BackpackAmount 20;
|
|
Ammo.BackpackMaxAmount 400;
|
|
Ammo.DropAmount 2;
|
|
}
|
|
override String PickupMessage()
|
|
{
|
|
return String.Format("%s%d%s",StringTable.Localize("$I_STINGERAMMOL"),Amount,StringTable.Localize("$I_STINGERAMMOR"));
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
SAMO A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class StingerAmmo2 : StingerAmmo
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_STINGERAMMO2";
|
|
Inventory.Amount 40;
|
|
Ammo.DropAmount 15;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
SAMO B -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class StingerBurstLight : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
Tag "Blue4";
|
|
Args 0,0,0,30;
|
|
ReactionTime 12;
|
|
}
|
|
}
|
|
|
|
Class StingerChunk : Actor
|
|
{
|
|
int deadtimer;
|
|
double rollvel, anglevel, pitchvel;
|
|
|
|
Default
|
|
{
|
|
Radius 2;
|
|
Height 2;
|
|
+NOBLOCKMAP;
|
|
+MISSILE;
|
|
+MOVEWITHSECTOR;
|
|
+THRUACTORS;
|
|
+NOTELEPORT;
|
|
+DONTSPLASH;
|
|
+INTERPOLATEANGLES;
|
|
BounceType "Doom";
|
|
BounceFactor 0.4;
|
|
Gravity 0.35;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
deadtimer = 0;
|
|
anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
frame = Random[Junk](0,8);
|
|
scale *= Frandom[Junk](0.4,0.8);
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( isFrozen() ) return;
|
|
if ( InStateSequence(CurState,ResolveState("Death")) )
|
|
{
|
|
deadtimer++;
|
|
if ( deadtimer > 60 ) A_FadeOut(0.05);
|
|
return;
|
|
}
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
CHIP # 1
|
|
{
|
|
angle += anglevel;
|
|
pitch += pitchvel;
|
|
roll += rollvel;
|
|
}
|
|
Loop;
|
|
Bounce:
|
|
CHIP # 0
|
|
{
|
|
anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
|
|
}
|
|
Goto Spawn;
|
|
Death:
|
|
CHIP # -1;
|
|
Stop;
|
|
Dummy:
|
|
CHIP ABCDEFGHI -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class ViewStingerChunk : StingerChunk
|
|
{
|
|
Vector3 ofs, vvel;
|
|
Default
|
|
{
|
|
+NOCLIP;
|
|
+NOGRAVITY;
|
|
-MISSILE;
|
|
BounceType "None";
|
|
}
|
|
override void Tick()
|
|
{
|
|
Actor.Tick();
|
|
if ( !target || !target.player )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Vector3 x, y, z;
|
|
[x, y, z] = dt_CoordUtil.GetAxes(target.pitch,target.angle,target.roll);
|
|
Vector3 origin = x*ofs.x+y*ofs.y+z*ofs.z+(0,0,target.player.viewz);
|
|
SetOrigin(target.Vec2OffsetZ(origin.x,origin.y,origin.z),true);
|
|
bInvisible = (players[consoleplayer].camera != target);
|
|
if ( isFrozen() ) return;
|
|
ofs += vvel;
|
|
scale *= 0.75;
|
|
if ( scale.x <= 0.01 ) Destroy();
|
|
}
|
|
}
|
|
|
|
Class TarydiumExLight : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
Tag "Blue2";
|
|
Args 0,0,0,60;
|
|
ReactionTime 30;
|
|
}
|
|
}
|
|
|
|
Class TarydiumExplosion : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
+NOGRAVITY;
|
|
+NOBLOCKMAP;
|
|
+FORCEXYBILLBOARD;
|
|
+FORCERADIUSDMG;
|
|
+NODAMAGETHRUST;
|
|
DamageType 'TarydiumCharge';
|
|
Obituary "$O_STINGERX";
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
A_Explode(special1,int(90*scale.x));
|
|
UTMainHandler.DoBlast(self,90*scale.x,90000);
|
|
A_PlaySound("flare/explode");
|
|
let l = Spawn("TarydiumExLight",pos);
|
|
l.args[3] = int(60*scale.x);
|
|
scale.x *= RandomPick[Stinger](-1,1);
|
|
scale.y *= RandomPick[Stinger](-1,1);
|
|
double ang, pt;
|
|
int numpt = Random[Stinger](10,15)*min(3,special1/60);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Stinger](0,360);
|
|
pt = FRandom[Stinger](-90,90);
|
|
let c = Spawn("UTSmoke",pos);
|
|
c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](2,7);
|
|
c.SetShade(Color(1,3,4)*Random[Stinger](24,63));
|
|
c.scale *= 3.;
|
|
}
|
|
numpt = Random[Stinger](4,8)*min(8,special1/25);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Stinger](0,360);
|
|
pt = FRandom[Stinger](-90,90);
|
|
let c = Spawn("StingerChunk",pos);
|
|
c.angle = ang;
|
|
c.pitch = pt;
|
|
c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](6,12);
|
|
}
|
|
numpt = Random[Stinger](10,20)*min(4,special1/40);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Stinger](0,360);
|
|
pt = FRandom[Stinger](-90,90);
|
|
let c = Spawn("UTChip",pos);
|
|
c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](6,12);
|
|
c.scale *= FRandom[Stinger](0.9,1.5);
|
|
}
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A 0 NoDelay A_Jump(128,"Explo2");
|
|
Explo1:
|
|
TEX1 ABCDEFGHI 3 Bright;
|
|
Stop;
|
|
Explo2:
|
|
TEX2 ABCDEFGHIJK 3 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class TarydiumDebuff : Thinker
|
|
{
|
|
Actor victim, instigator;
|
|
int amount; // accumulated damage for the explosion
|
|
Vector3 oldvel;
|
|
bool wasonair, reentrant;
|
|
|
|
void UpdateEffect()
|
|
{
|
|
if ( !victim )
|
|
{
|
|
BlowUp();
|
|
return;
|
|
}
|
|
victim.A_AttachLight('TDEBUFFLIGHT',DynamicLight.PointLight,Color(1,3,4)*min(amount,63),int(max(victim.radius,victim.height))+60+min(amount/4,40),0,DynamicLight.LF_ATTENUATE,(0,0,victim.height/2));
|
|
if ( Random[Stinger](0,amount) > 100 )
|
|
{
|
|
amount += 30;
|
|
BlowUp();
|
|
}
|
|
}
|
|
|
|
void BlowUp()
|
|
{
|
|
reentrant = true;
|
|
let b = victim.Spawn("TarydiumExplosion",victim.Vec3Offset(0,0,victim.height/2));
|
|
b.target = instigator;
|
|
b.special1 = amount;
|
|
b.scale *= 1.+min(1.5,amount*0.02);
|
|
Destroy();
|
|
}
|
|
|
|
override void OnDestroy()
|
|
{
|
|
Super.OnDestroy();
|
|
if ( victim ) victim.A_RemoveLight('TDEBUFFLIGHT');
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
if ( !sting_stinger )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
if ( !victim || (victim.Health <= 0) )
|
|
{
|
|
BlowUp();
|
|
return;
|
|
}
|
|
if ( victim.pos.z > victim.floorz ) wasonair = true;
|
|
else
|
|
{
|
|
if ( wasonair && (oldvel.z < -20) )
|
|
{
|
|
Amount += min(int(-oldvel.z),100);
|
|
BlowUp();
|
|
return;
|
|
}
|
|
wasonair = false;
|
|
}
|
|
oldvel = victim.vel;
|
|
if ( !(level.maptime%20) )
|
|
{
|
|
amount--;
|
|
UpdateEffect();
|
|
if ( amount <= 0 )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
}
|
|
if ( level.maptime%3 ) return;
|
|
int numpt = clamp(int(Random[Stinger](1,3)*amount*0.02),1,8);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pos = victim.Vec3Offset(FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](0,victim.height));
|
|
let l = victim.Spawn("StingerBurstLight",pos);
|
|
l.Args[3] /= 2;
|
|
double ang, pt;
|
|
int numpt2 = Random[Stinger](2,5);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Stinger](0,360);
|
|
pt = FRandom[Stinger](-90,90);
|
|
let c = victim.Spawn("UTSmoke",pos);
|
|
c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](0.3,0.8);
|
|
c.SetShade(Color(1,3,4)*Random[Stinger](24,63));
|
|
c.scale *= 3.;
|
|
c.alpha *= 0.35;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void Apply( Actor victim, Actor instigator, int amount )
|
|
{
|
|
if ( !victim || (victim.Health <= 0) || !victim.bISMONSTER ) return;
|
|
if ( !sting_stinger ) return;
|
|
let ti = ThinkerIterator.Create("TarydiumDebuff",STAT_USER);
|
|
TarydiumDebuff t;
|
|
while ( t = TarydiumDebuff(ti.Next()) )
|
|
{
|
|
if ( t.victim != victim ) continue;
|
|
if ( instigator ) t.instigator = instigator;
|
|
t.amount += amount;
|
|
t.UpdateEffect();
|
|
return;
|
|
}
|
|
t = new("TarydiumDebuff");
|
|
t.ChangeStatNum(STAT_USER);
|
|
t.victim = victim;
|
|
t.instigator = instigator;
|
|
t.amount = amount;
|
|
t.oldvel = victim.vel;
|
|
t.wasonair = (victim.pos.z>victim.floorz);
|
|
t.UpdateEffect();
|
|
}
|
|
}
|
|
|
|
Class StingerProjectile : Actor
|
|
{
|
|
Vector3 oldvel;
|
|
Default
|
|
{
|
|
Obituary "$O_STINGER";
|
|
DamageType 'Stinger';
|
|
DamageFunction Random[Stinger](15,25);
|
|
Speed 40;
|
|
Radius 2;
|
|
Height 2;
|
|
PROJECTILE;
|
|
+SKYEXPLODE;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
if ( sting_stingerb )
|
|
{
|
|
// set bounce stuff
|
|
bBOUNCEONWALLS = true;
|
|
bBOUNCEONFLOORS = true;
|
|
bBOUNCEONCEILINGS = true;
|
|
bALLOWBOUNCEONACTORS = true;
|
|
bCANBOUNCEWATER = true;
|
|
bUSEBOUNCESTATE = true;
|
|
BounceCount = 4;
|
|
BounceFactor = 1.;
|
|
WallBounceFactor = 1.;
|
|
}
|
|
}
|
|
override void Tick()
|
|
{
|
|
oldvel = vel;
|
|
Super.Tick();
|
|
}
|
|
void A_HandleBounce()
|
|
{
|
|
// cancel bounce based on "incidence"
|
|
if ( vel dot oldvel < 0.87 )
|
|
{
|
|
ClearBounce();
|
|
ExplodeMissile();
|
|
return;
|
|
}
|
|
if ( !Random[Stinger](0,2) ) A_PlaySound("stinger/hit2",CHAN_BODY,0.5,pitch:FRandom[Stinger](0.5,1.5));
|
|
else A_PlaySound("stinger/hit",CHAN_BODY,0.6);
|
|
A_SprayDecal("WallCrack",-20);
|
|
A_AlertMonsters();
|
|
let l = Spawn("StingerBurstLight",pos);
|
|
l.Args[3] /= 2;
|
|
double ang, pt;
|
|
int numpt = Random[Stinger](1,3);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Stinger](0,360);
|
|
pt = FRandom[Stinger](-90,90);
|
|
let c = Spawn("StingerChunk",pos);
|
|
c.scale *= 0.5;
|
|
c.angle = ang;
|
|
c.pitch = pt;
|
|
c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](3,9);
|
|
}
|
|
numpt = Random[Stinger](2,5);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Stinger](0,360);
|
|
pt = FRandom[Stinger](-90,90);
|
|
let c = Spawn("UTSmoke",pos);
|
|
c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](0.3,0.8);
|
|
c.SetShade(Color(1,3,4)*Random[Stinger](48,63));
|
|
c.alpha *= 0.35;
|
|
}
|
|
}
|
|
override int DoSpecialDamage( Actor target, int damage, Name damagetype )
|
|
{
|
|
if ( !target.bNOBLOOD )
|
|
{
|
|
target.SpawnBlood(pos,AngleTo(target),damage);
|
|
A_PlaySound("stinger/flesh");
|
|
A_AlertMonsters();
|
|
if ( sting_stinger ) TarydiumDebuff.Apply(target,self.target,damage/4);
|
|
}
|
|
return damage;
|
|
}
|
|
action void A_StingerHit()
|
|
{
|
|
if ( !Random[Stinger](0,2) ) A_PlaySound("stinger/hit2",CHAN_BODY,0.5,pitch:FRandom[Stinger](0.5,1.5));
|
|
else A_PlaySound("stinger/hit",CHAN_BODY,0.6);
|
|
A_SprayDecal("WallCrack",20);
|
|
A_AlertMonsters();
|
|
Spawn("StingerBurstLight",pos);
|
|
double ang, pt;
|
|
int numpt = Random[Stinger](4,8);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Stinger](0,360);
|
|
pt = FRandom[Stinger](-90,90);
|
|
let c = Spawn("StingerChunk",pos);
|
|
c.angle = ang;
|
|
c.pitch = pt;
|
|
c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](3,9);
|
|
}
|
|
numpt = Random[Stinger](6,12);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Stinger](0,360);
|
|
pt = FRandom[Stinger](-90,90);
|
|
let c = Spawn("UTSmoke",pos);
|
|
c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](0.3,0.8);
|
|
c.SetShade(Color(1,3,4)*Random[Stinger](48,63));
|
|
c.alpha *= 0.5;
|
|
}
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TPRJ A -1 Bright;
|
|
Stop;
|
|
Bounce:
|
|
TPRJ A 0 Bright A_HandleBounce();
|
|
Goto Spawn;
|
|
Death:
|
|
Crash:
|
|
TNT1 A 1 A_StingerHit();
|
|
Stop;
|
|
XDeath:
|
|
TNT1 A 1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class StingerLight : EnforcerLight
|
|
{
|
|
Default
|
|
{
|
|
args 64,128,255,80;
|
|
}
|
|
}
|
|
|
|
Class Stinger : UnrealWeapon
|
|
{
|
|
int flashnum;
|
|
|
|
Default
|
|
{
|
|
Tag "$T_STINGER";
|
|
Inventory.PickupMessage "$I_STINGER";
|
|
Weapon.UpSound "stinger/select";
|
|
Weapon.SlotNumber 3;
|
|
Weapon.SelectionOrder 7;
|
|
Weapon.SlotPriority 1;
|
|
Weapon.AmmoType "StingerAmmo";
|
|
Weapon.AmmoUse 1;
|
|
Weapon.AmmoType2 "StingerAmmo";
|
|
Weapon.AmmoUse2 1;
|
|
Weapon.AmmoGive 40;
|
|
UTWeapon.DropAmmo 20;
|
|
}
|
|
action void A_StingerFire( bool hold = false )
|
|
{
|
|
Weapon weap = Weapon(invoker);
|
|
if ( !weap ) return;
|
|
if ( weap.Ammo1.Amount <= 0 ) return;
|
|
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
|
|
if ( hold )
|
|
{
|
|
A_SoundVolume(CHAN_WEAPON,Dampener.Active(self)?.1:1.);
|
|
A_Overlay(PSP_FLASH,"MFlashHold");
|
|
}
|
|
else
|
|
{
|
|
A_PlaySound("stinger/fire",CHAN_WEAPON,Dampener.Active(self)?.1:1.);
|
|
A_Overlay(PSP_FLASH,"MFlash");
|
|
}
|
|
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
|
|
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
|
|
invoker.FireEffect();
|
|
UTMainHandler.DoFlash(self,Color(16,0,64,255),1);
|
|
UTMainHandler.DoSwing(self,(FRandom[Stinger](-0.1,-0.2),FRandom[Stinger](-0.1,0.1)),4,-1.5,2,SWING_Spring,2,2);
|
|
if ( !Dampener.Active(self) ) A_AlertMonsters();
|
|
A_QuakeEx(1,1,1,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
|
|
Vector3 x, y, z;
|
|
[x, y, z] = dt_Matrix4.GetAxes(pitch,angle,roll);
|
|
Vector3 origin = Vec2OffsetZ(0,0,player.viewz)+5.0*x+8.0*y-8.0*z;
|
|
Actor p = Spawn("StingerProjectile",origin);
|
|
p.angle = angle;
|
|
p.pitch = BulletSlope();
|
|
p.roll = FRandom[Stinger](0,360);
|
|
p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed;
|
|
p.target = self;
|
|
int numpt = Random[Stinger](5,9);
|
|
double ang;
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
let s = Spawn("ViewStingerChunk",origin);
|
|
ViewStingerChunk(s).ofs = (8,2,-2);
|
|
ang = FRandom[Stinger](0,360);
|
|
ViewStingerChunk(s).vvel = (FRandom[Stinger](0.2,1.2),0,0)+(0,cos(ang),sin(ang))*FRandom[Stinger](0.3,0.9);
|
|
s.target = self;
|
|
}
|
|
for ( int i=0; i<12; i++ )
|
|
{
|
|
let s = Spawn("UTViewSmoke",origin);
|
|
UTViewSmoke(s).ofs = (16,4,-4);
|
|
ang = FRandom[Stinger](0,360);
|
|
UTViewSmoke(s).vvel = (FRandom[Stinger](0,0.4),0,0)+(0,cos(ang),sin(ang))*FRandom[Stinger](0.2,0.5);
|
|
s.target = self;
|
|
s.scale *= 1.5;
|
|
s.alpha *= 0.3;
|
|
s.SetShade(Color(1,3,4)*Random[Stinger](31,63));
|
|
}
|
|
}
|
|
action void A_StingerAltFire()
|
|
{
|
|
Weapon weap = Weapon(invoker);
|
|
if ( !weap ) return;
|
|
if ( weap.Ammo1.Amount <= 0 ) return;
|
|
A_PlaySound("stinger/altfire",CHAN_WEAPON,Dampener.Active(self)?.1:1.);
|
|
A_Overlay(PSP_FLASH,"MFlash");
|
|
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
|
|
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
|
|
invoker.FireEffect();
|
|
UTMainHandler.DoFlash(self,Color(16,0,64,255),1);
|
|
UTMainHandler.DoSwing(self,(FRandom[Stinger](-0.3,-0.8),FRandom[Stinger](-0.4,0.4)),4,-1,3,SWING_Spring,3,5);
|
|
if ( !Dampener.Active(self) ) A_AlertMonsters();
|
|
A_QuakeEx(1,1,1,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
|
|
Vector3 x, y, z;
|
|
[x, y, z] = dt_Matrix4.GetAxes(pitch,angle,roll);
|
|
Vector3 origin = (pos.x,pos.y,player.viewz)+5.0*x+8.0*y-8.0*z;
|
|
[x, y, z] = dt_Matrix4.GetAxes(BulletSlope(),angle,roll);
|
|
Actor p;
|
|
double a, s;
|
|
Vector3 dir;
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
if ( weap.Ammo1.Amount <= 0 ) return;
|
|
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
|
|
a = FRandom[Stinger](0,360);
|
|
s = FRandom[Stinger](0,0.08);
|
|
dir = (x+y*cos(a)*s+z*sin(a)*s).unit();
|
|
p = Spawn("StingerProjectile",origin);
|
|
p.angle = atan2(dir.y,dir.x);
|
|
p.pitch = asin(-dir.z);
|
|
p.roll = FRandom[Stinger](0,360);
|
|
p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed;
|
|
p.target = self;
|
|
int numpt = Random[Stinger](5,9);
|
|
double ang;
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
let s = Spawn("ViewStingerChunk",origin);
|
|
ViewStingerChunk(s).ofs = (8,2,-2);
|
|
ang = FRandom[Stinger](0,360);
|
|
ViewStingerChunk(s).vvel = (FRandom[Stinger](0.2,1.2),0,0)+(0,cos(ang),sin(ang))*FRandom[Stinger](0.3,0.9);
|
|
s.target = self;
|
|
}
|
|
for ( int i=0; i<12; i++ )
|
|
{
|
|
let s = Spawn("UTViewSmoke",origin);
|
|
UTViewSmoke(s).ofs = (16,4,-4);
|
|
ang = FRandom[Stinger](0,360);
|
|
UTViewSmoke(s).vvel = (FRandom[Stinger](0,0.4),0,0)+(0,cos(ang),sin(ang))*FRandom[Stinger](0.2,0.5);
|
|
s.target = self;
|
|
s.scale *= 1.5;
|
|
s.alpha *= 0.3;
|
|
s.SetShade(Color(1,3,4)*Random[Stinger](48,63));
|
|
}
|
|
}
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
STNP A -1;
|
|
Stop;
|
|
STNP B -1;
|
|
Stop;
|
|
Select:
|
|
STNS A 1 A_Raise(int.max);
|
|
Wait;
|
|
Ready:
|
|
STNS ABCDEFGHIJKLMNOPQRSTU 1 A_WeaponReady(WRF_NOFIRE);
|
|
Idle:
|
|
STNI A 1
|
|
{
|
|
A_CheckReload();
|
|
A_WeaponReady();
|
|
}
|
|
Wait;
|
|
Fire:
|
|
STNF A 2 A_StingerFire();
|
|
STNF BC 2;
|
|
STNI A 3;
|
|
STNI A 0 A_Refire(1);
|
|
Goto Idle;
|
|
STNI A 0
|
|
{
|
|
A_PlaySound("stinger/hold",CHAN_WEAPON,Dampener.Active(self)?.1:1.,true);
|
|
invoker.flashnum = Random[Stinger](0,3);
|
|
}
|
|
Hold:
|
|
STNH A 1
|
|
{
|
|
// need to make sure player does the repeat fire anim
|
|
if ( self is 'UPlayer' )
|
|
UPlayer(self).PlayAttacking();
|
|
A_StingerFire(true);
|
|
invoker.flashnum = (invoker.flashnum+1)%4;
|
|
}
|
|
STNH BCDEFG 1;
|
|
STNH A 0 A_Refire();
|
|
STNH A 2 A_PlaySound("stinger/release",CHAN_WEAPON,Dampener.Active(self)?.1:1.);
|
|
Goto Idle;
|
|
AltFire:
|
|
STNF A 2 A_StingerAltFire();
|
|
STNF BC 2;
|
|
STNI A 35; // yes, 1 second cooldown
|
|
Goto Idle;
|
|
Deselect:
|
|
STND ACEGIK 1;
|
|
STND K 1 A_Lower(int.max);
|
|
Wait;
|
|
MFlash:
|
|
STFF A 2 Bright
|
|
{
|
|
let l = Spawn("StingerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
MFlashHold:
|
|
TNT1 A 0 A_JumpIf(invoker.flashnum==0,7);
|
|
TNT1 A 0 A_JumpIf(invoker.flashnum==1,4);
|
|
TNT1 A 0 A_JumpIf(invoker.flashnum==2,4);
|
|
TNT1 A 0 A_JumpIf(invoker.flashnum==3,1);
|
|
Stop;
|
|
STFF A 2 Bright
|
|
{
|
|
let l = Spawn("StingerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
STFF B 2 Bright
|
|
{
|
|
let l = Spawn("StingerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
STFF C 2 Bright
|
|
{
|
|
let l = Spawn("StingerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
STFF D 2 Bright
|
|
{
|
|
let l = Spawn("StingerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
/*MFlash:
|
|
STFF ABC 2 Bright;
|
|
Stop;
|
|
MFlashHold:
|
|
STFH ABCDEFG 1 Bright;
|
|
Stop;*/
|
|
}
|
|
}
|