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.
402 lines
10 KiB
Text
402 lines
10 KiB
Text
Class UShells : Ammo
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_SHELLS";
|
|
Inventory.Icon "I_ShotSh";
|
|
Inventory.PickupMessage "";
|
|
Inventory.Amount 12;
|
|
Inventory.MaxAmount 48;
|
|
Ammo.BackpackAmount 12;
|
|
Ammo.BackpackMaxAmount 96;
|
|
Ammo.DropAmount 6;
|
|
}
|
|
override String PickupMessage()
|
|
{
|
|
if ( PickupMsg.Length() > 0 ) return Super.PickupMessage();
|
|
return String.Format("%s%d%s",StringTable.Localize("$I_SHELLSL"),Amount,StringTable.Localize("$I_SHELLSR"));
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
QAMO A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class UShells2 : UShells
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_SHELLS2";
|
|
Inventory.Amount 4;
|
|
Ammo.DropAmount 4;
|
|
+INVENTORY.IGNORESKILL;
|
|
}
|
|
}
|
|
|
|
Class QCasing : UCasing
|
|
{
|
|
Default
|
|
{
|
|
BounceSound "quadshot/shell";
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
heat = 0.; // no smoke
|
|
}
|
|
}
|
|
|
|
Class QuadshotTracer : LineTracer
|
|
{
|
|
Actor ignoreme;
|
|
|
|
override ETraceStatus TraceCallback()
|
|
{
|
|
if ( Results.HitType == TRACE_HitActor )
|
|
{
|
|
if ( Results.HitActor == ignoreme ) return TRACE_Skip;
|
|
if ( Results.HitActor.bSHOOTABLE )
|
|
{
|
|
int amt = FlakAccumulator.GetAmount(Results.HitActor);
|
|
// getgibhealth isn't clearscope, fuck
|
|
int gibhealth = -int(Results.HitActor.GetSpawnHealth()*gameinfo.gibfactor);
|
|
if ( Results.HitActor.GibHealth != int.min ) gibhealth = -abs(Results.HitActor.GibHealth);
|
|
// go through actors that are already gibbed
|
|
if ( Results.HitActor.health-amt <= gibhealth ) return TRACE_Skip;
|
|
return TRACE_Stop;
|
|
}
|
|
return TRACE_Skip;
|
|
}
|
|
else if ( (Results.HitType == TRACE_HitWall) && (Results.Tier == TIER_Middle) )
|
|
{
|
|
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
|
|
return TRACE_Stop;
|
|
return TRACE_Skip;
|
|
}
|
|
return TRACE_Stop;
|
|
}
|
|
}
|
|
|
|
Class QuadShot : UnrealWeapon
|
|
{
|
|
int clipcount;
|
|
QuadshotTracer t;
|
|
|
|
action void ProcessTraceHit( Linetracer t )
|
|
{
|
|
if ( t.Results.HitType == TRACE_HitActor )
|
|
{
|
|
int dmg = Random[Quadshot](4,8);
|
|
FlakAccumulator.Accumulate(t.Results.HitActor,dmg,invoker,self,'shot');
|
|
double mm = 2400;
|
|
UTMainHandler.DoKnockback(t.Results.HitActor,t.Results.HitVector+(0,0,0.025),mm*FRandom[Quadshot](0.4,1.2));
|
|
if ( t.Results.HitActor.bNOBLOOD )
|
|
{
|
|
let p = Spawn("BulletImpact",t.Results.HitPos);
|
|
p.scale *= FRandom[Quadshot](0.2,0.4);
|
|
p.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x)+180;
|
|
p.pitch = asin(t.Results.HitVector.z);
|
|
}
|
|
else
|
|
{
|
|
t.Results.HitActor.TraceBleed(dmg,self);
|
|
t.Results.HitActor.SpawnBlood(t.Results.HitPos,atan2(t.Results.HitVector.y,t.Results.HitVector.x)+180,dmg);
|
|
}
|
|
}
|
|
else if ( t.Results.HitType != TRACE_HitNone )
|
|
{
|
|
Vector3 hitnormal = -t.Results.HitVector;
|
|
if ( t.Results.HitType == TRACE_HitFloor )
|
|
{
|
|
if ( t.Results.FFloor ) hitnormal = -t.Results.FFloor.top.Normal;
|
|
else hitnormal = t.Results.HitSector.floorplane.Normal;
|
|
}
|
|
else if ( t.Results.HitType == TRACE_HitCeiling )
|
|
{
|
|
if ( t.Results.FFloor ) hitnormal = -t.Results.FFloor.bottom.Normal;
|
|
else hitnormal = t.Results.HitSector.ceilingplane.Normal;
|
|
}
|
|
else if ( t.Results.HitType == TRACE_HitWall )
|
|
{
|
|
hitnormal = (-t.Results.HitLine.delta.y,t.Results.HitLine.delta.x,0).unit();
|
|
if ( !t.Results.Side ) hitnormal *= -1;
|
|
}
|
|
let p = Spawn("BulletImpact",t.Results.HitPos+hitnormal*0.01);
|
|
p.scale *= FRandom[Quadshot](0.2,0.4);
|
|
p.angle = atan2(hitnormal.y,hitnormal.x);
|
|
p.pitch = asin(-hitnormal.z);
|
|
if ( t.Results.HitLine ) t.Results.HitLine.RemoteActivate(self,t.Results.Side,SPAC_Impact,t.Results.HitPos);
|
|
}
|
|
}
|
|
|
|
action void A_QuadshotFire( bool bAlt = false )
|
|
{
|
|
Weapon weap = Weapon(invoker);
|
|
if ( !weap ) return;
|
|
if ( weap.Ammo1.Amount <= 0 ) return;
|
|
if ( bAlt && (invoker.clipcount > 2) )
|
|
{
|
|
// fall back to normal fire strength
|
|
player.SetPSprite(PSP_WEAPON,invoker.FindState("Fire"));
|
|
return;
|
|
}
|
|
Vector3 x, y, z, x2, y2, z2;
|
|
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
|
|
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+y*2-z*2);
|
|
[x2, y2, z2] = dt_CoordUtil.GetAxes(BulletSlope(),angle,roll);
|
|
double a, s;
|
|
Vector3 dir;
|
|
FLineTraceData d;
|
|
if ( bAlt )
|
|
{
|
|
A_QuakeEx(1,1,1,6,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.12);
|
|
A_PlaySound("quadshot/alt",CHAN_WEAPON,!Dampener.Active(self)?1.:.2);
|
|
A_PlaySound("quadshot/alt",CHAN_7,!Dampener.Active(self)?1.:.2);
|
|
double spread = (4-invoker.clipcount);
|
|
for ( int i=invoker.clipcount; i<4; i++ )
|
|
{
|
|
for ( int i=0; i<3; i++ )
|
|
UTMainHandler.DoSwing(self,(FRandom[Quadshot](-0.04,-0.2),FRandom[Quadshot](-0.2,0.2)),FRandom[Quadshot](2,4),FRandom[Quadshot](-0.2,0.5),Random[Quadshot](3,4),SWING_Spring,Random[Quadshot](1,6),FRandom[Quadshot](0.8,1.4));
|
|
weap.DepleteAmmo(weap.bAltFire,true,1);
|
|
for ( int i=0; i<10; i++ )
|
|
{
|
|
a = FRandom[Quadshot](0,360);
|
|
s = FRandom[Quadshot](0,0.09+0.05*spread);
|
|
dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
|
|
if ( !invoker.t ) invoker.t = new("QuadshotTracer");
|
|
invoker.t.ignoreme = self;
|
|
invoker.t.Trace(origin,CurSector,dir,10000,0);
|
|
ProcessTraceHit(invoker.t);
|
|
}
|
|
}
|
|
vel += (0,0,(0.3+0.3*spread))-x*(1.5+1.1*spread);
|
|
invoker.clipcount = 4;
|
|
}
|
|
else
|
|
{
|
|
A_QuakeEx(1,1,1,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.12);
|
|
A_PlaySound("quadshot/fire",CHAN_WEAPON,!Dampener.Active(self)?1.:.2);
|
|
A_PlaySound("quadshot/fire",CHAN_7,!Dampener.Active(self)?1.:.2);
|
|
for ( int i=0; i<3; i++ )
|
|
UTMainHandler.DoSwing(self,(FRandom[Quadshot](-0.04,-0.2),FRandom[Quadshot](-0.2,0.2)),FRandom[Quadshot](2,3),FRandom[Quadshot](-0.2,0.5),Random[Quadshot](2,3),SWING_Spring,Random[Quadshot](0,3),FRandom[Quadshot](0.8,1.4));
|
|
weap.DepleteAmmo(weap.bAltFire,true,1);
|
|
for ( int i=0; i<10; i++ )
|
|
{
|
|
a = FRandom[Quadshot](0,360);
|
|
s = FRandom[Quadshot](0,0.08);
|
|
dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
|
|
if ( !invoker.t ) invoker.t = new("QuadshotTracer");
|
|
invoker.t.ignoreme = self;
|
|
invoker.t.Trace(origin,CurSector,dir,10000,0);
|
|
ProcessTraceHit(invoker.t);
|
|
}
|
|
vel += (0,0,0.3)-x*1.5;
|
|
invoker.clipcount++;
|
|
}
|
|
if ( bAlt ) A_Overlay(-2,"MuzzleFlashAlt");
|
|
else A_Overlay(-2,"MuzzleFlash");
|
|
A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
|
|
A_OverlayRenderstyle(-2,STYLE_Add);
|
|
if ( !Dampener.Active(self) ) A_AlertMonsters();
|
|
invoker.FireEffect();
|
|
UTMainHandler.DoFlash(self,Color(32,255,128,0),1);
|
|
int numpt = bAlt?40:15;
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
let s = Spawn("UTStaticViewSmoke",origin);
|
|
UTViewSmoke(s).ofs = (10,2,-2);
|
|
UTViewSmoke(s).vvel += (FRandom[Quadshot](-0.05,0.25),FRandom[Quadshot](-0.3,0.3),FRandom[Sniper](-0.3,0.3));
|
|
s.target = self;
|
|
s.scale *= 1.2;
|
|
s.alpha *= 0.4;
|
|
}
|
|
}
|
|
action void A_DropShells()
|
|
{
|
|
Vector3 x, y, z;
|
|
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
|
|
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),-x*4-y*8-z*8);
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
let c = Spawn("QCasing",origin);
|
|
c.vel = x*FRandom[Junk](-1.5,0.25)-y*FRandom[Junk](1,4)-z*FRandom[Junk](1,4);
|
|
}
|
|
}
|
|
action bool A_QuadshotCheckForReload( bool bDryFire = false )
|
|
{
|
|
let weap = Weapon(invoker);
|
|
if ( invoker.clipcount > 3 )
|
|
{
|
|
if ( weap.Ammo1.Amount > 0 )
|
|
{
|
|
player.SetPSprite(PSP_WEAPON,invoker.FindState("Reload"));
|
|
return true;
|
|
}
|
|
else if ( bDryFire )
|
|
{
|
|
player.SetPSprite(PSP_WEAPON,invoker.FindState("DryFire"));
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
Default
|
|
{
|
|
Tag "$T_QUADSHOT";
|
|
Inventory.PickupMessage "$I_QUADSHOT";
|
|
Weapon.UpSound "quadshot/select";
|
|
Weapon.SlotNumber 3;
|
|
Weapon.SelectionOrder 2;
|
|
Weapon.SlotPriority 0.9;
|
|
Weapon.AmmoType "UShells";
|
|
Weapon.AmmoUse 1;
|
|
Weapon.AmmoType2 "UShells";
|
|
Weapon.AmmoUse2 1;
|
|
Weapon.AmmoGive 20;
|
|
Weapon.Kickback 320;
|
|
UTWeapon.DropAmmo 10;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
QSPK A -1;
|
|
Stop;
|
|
QSPK B -1;
|
|
Stop;
|
|
Select:
|
|
QUAS A 1 A_Raise(int.max);
|
|
Wait;
|
|
Ready:
|
|
QUAS ABCDEFGHIJK 2 A_WeaponReady(WRF_NOFIRE);
|
|
Goto Idle;
|
|
Dummy:
|
|
TNT1 A 1
|
|
{
|
|
A_CheckReload();
|
|
if ( !A_QuadshotCheckForReload() )
|
|
{
|
|
let weap = Weapon(invoker);
|
|
if ( (invoker.clipcount > 0) && (weap.Ammo1.Amount > 4-invoker.clipcount) )
|
|
A_WeaponReady(WRF_ALLOWRELOAD);
|
|
else A_WeaponReady();
|
|
}
|
|
}
|
|
Wait;
|
|
Idle:
|
|
QUAI A 0 A_Overlay(-9999,"Dummy");
|
|
QUAI A 50;
|
|
QUAI A 0 A_Jump(40,"Twiddle");
|
|
Goto Idle+1;
|
|
Twiddle:
|
|
#### # 2;
|
|
QUAT ABCDEFGHIJKLMNOPQRSTU 2;
|
|
Goto Idle+1;
|
|
Fire:
|
|
#### # 1
|
|
{
|
|
if ( !A_QuadshotCheckForReload(true) )
|
|
{
|
|
A_Overlay(-9999,"Null");
|
|
A_QuadshotFire();
|
|
}
|
|
}
|
|
QUAF ABCDEFGHIJK 1;
|
|
Goto Pump;
|
|
DryFire:
|
|
#### # 1
|
|
{
|
|
A_Overlay(-9999,"Null");
|
|
A_PlaySound("automag/click",CHAN_WEAPON,Dampener.Active(self)?.05:.5);
|
|
}
|
|
QUAF AJK 2;
|
|
Goto Idle;
|
|
AltFire:
|
|
#### # 1
|
|
{
|
|
if ( !A_QuadshotCheckForReload(true) )
|
|
{
|
|
A_Overlay(-9999,"Null");
|
|
A_QuadshotFire(true);
|
|
}
|
|
}
|
|
QUAA ABCDEFGHIJKLMNOPQRS 1;
|
|
Goto Idle;
|
|
Pump:
|
|
QUAP A 0
|
|
{
|
|
if ( self is 'UTPlayer' )
|
|
UTPlayer(self).PlayReloading();
|
|
}
|
|
QUAP ABCD 1;
|
|
QUAP E 0 A_PlaySound("quadshot/pump1",CHAN_6,Dampener.Active(self)?.1:1.);
|
|
QUAP EFGHIJKLM 1;
|
|
QUAP N 0 A_PlaySound("quadshot/pump2",CHAN_6,Dampener.Active(self)?.1:1.);
|
|
QUAP NOPQRSTUVWXYZ[\ 1;
|
|
QUAP \ 0;
|
|
QUAI A 0; // force no tween
|
|
Goto Idle;
|
|
Reload:
|
|
QUAR A 0 A_Overlay(-9999,"Null");
|
|
QUAR ABCDEFGHIJK 1;
|
|
QUAR L 0
|
|
{
|
|
A_PlaySound("quadshot/open",CHAN_6,Dampener.Active(self)?.1:1.);
|
|
if ( self is 'UTPlayer' )
|
|
UTPlayer(self).PlayAttacking3();
|
|
}
|
|
QUAR LMNOPQRSTU 1;
|
|
QUAR V 0 A_DropShells();
|
|
QUAR VWXYZ[\] 1;
|
|
QUR2 ABCDEFGHIJKLMNOPQR 1;
|
|
QUR2 S 0
|
|
{
|
|
A_PlaySound("quadshot/load",CHAN_6,Dampener.Active(self)?.1:1.);
|
|
if ( self is 'UTPlayer' )
|
|
UTPlayer(self).PlayReloading();
|
|
}
|
|
QUR2 STUVWXYZ[\] 1;
|
|
QUR3 ABCDEFGHIJKLMNO 1;
|
|
QUR3 P 0
|
|
{
|
|
A_PlaySound("quadshot/load",CHAN_6,Dampener.Active(self)?.1:1.);
|
|
if ( self is 'UTPlayer' )
|
|
UTPlayer(self).PlayReloading();
|
|
}
|
|
QUR3 PQRSTUVWXYZ[\] 1;
|
|
QUR4 ABCDE 1;
|
|
QUR4 F 0
|
|
{
|
|
A_PlaySound("quadshot/close",CHAN_6,Dampener.Active(self)?.1:1.);
|
|
if ( self is 'UTPlayer' ) UTPlayer(self).PlayAttacking3();
|
|
}
|
|
QUR4 FGHIJKLMNOPQ 1;
|
|
QUAI A 0
|
|
{
|
|
let weap = Weapon(invoker);
|
|
invoker.clipcount = max(0,4-weap.Ammo1.Amount);
|
|
}
|
|
Goto Idle;
|
|
Deselect:
|
|
#### # 1 A_Overlay(-9999,"Null");
|
|
QUAD ABCDEFG 1;
|
|
QUAD G 1 A_Lower(int.max);
|
|
Wait;
|
|
MuzzleFlash:
|
|
QFLA A 3 Bright
|
|
{
|
|
let l = Spawn("EnforcerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
MuzzleFlashAlt:
|
|
QFLA B 3 Bright
|
|
{
|
|
let l = Spawn("EnforcerLight",pos);
|
|
l.target = self;
|
|
l.args[3] += 20;
|
|
}
|
|
Stop;
|
|
}
|
|
}
|