735 lines
17 KiB
Text
735 lines
17 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 TDebuffLight : PointLightAttenuated
|
|
{
|
|
TarydiumDebuff dbf;
|
|
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !dbf || !dbf.victim )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Args[0] = min(dbf.Amount,64);
|
|
Args[1] = min(dbf.Amount*3,192);
|
|
Args[2] = min(dbf.Amount*4,255);
|
|
Args[3] = int(max(dbf.victim.radius,dbf.victim.height))+60+min(dbf.amount/4,40);
|
|
SetOrigin(dbf.Victim.Vec3Offset(0,0,dbf.Victim.Height/2),true);
|
|
}
|
|
}
|
|
|
|
Class TarydiumDebuff : Thinker
|
|
{
|
|
Actor victim, instigator, lite;
|
|
int amount; // accumulated damage for the explosion
|
|
Vector3 oldvel;
|
|
bool wasonair, reentrant;
|
|
|
|
void UpdateEffect()
|
|
{
|
|
if ( !victim )
|
|
{
|
|
BlowUp();
|
|
return;
|
|
}
|
|
if ( !lite )
|
|
{
|
|
lite = Actor.Spawn("TDebuffLight",victim.pos);
|
|
TDebuffLight(lite).dbf = self;
|
|
lite.Args[0] = min(Amount,64);
|
|
lite.Args[1] = min(Amount*3,192);
|
|
lite.Args[2] = min(Amount*4,255);
|
|
lite.Args[3] = int(max(victim.radius,victim.height))+60+min(amount/4,40);
|
|
}
|
|
if ( Random[Stinger](0,amount) > 100 )
|
|
{
|
|
amount += 30;
|
|
BlowUp();
|
|
}
|
|
}
|
|
|
|
void BlowUp()
|
|
{
|
|
reentrant = true;
|
|
let b = victim.Spawn("TarydiumExplosion",victim.Vec3Offset(0,0,victim.default.height/2));
|
|
b.target = instigator;
|
|
b.special1 = amount;
|
|
b.scale *= 1.+min(1.5,amount*0.02);
|
|
Destroy();
|
|
}
|
|
|
|
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_JumpIfNoAmmo(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;*/
|
|
}
|
|
}
|