Addition to HUD for showing clip counts (kinda cheap-looking, but still better than what Oldskool did). Charge for some weapons and loaded rockets for eightball also use the clipcount display, like in Doom Tournament. Small fixups for dual wielding logic.
411 lines
9.9 KiB
Text
411 lines
9.9 KiB
Text
/*
|
|
usaar33 is a wiener
|
|
|
|
now watch as I turn this trash fire into a better weapon
|
|
*/
|
|
Class OLSMPAmmo : Ammo
|
|
{
|
|
override bool TryPickup( in out Actor toucher )
|
|
{
|
|
if ( !sting_olsmp ) return false; // not allowed
|
|
return Super.TryPickup(toucher);
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( sting_olsmp ) return;
|
|
if ( !Owner )
|
|
{
|
|
let r = Spawn("CellPack",pos,ALLOW_REPLACE);
|
|
r.spawnangle = spawnangle;
|
|
r.spawnpoint = spawnpoint;
|
|
r.angle = angle;
|
|
r.pitch = pitch;
|
|
r.roll = roll;
|
|
r.special = special;
|
|
r.args[0] = args[0];
|
|
r.args[1] = args[1];
|
|
r.args[2] = args[2];
|
|
r.args[3] = args[3];
|
|
r.args[4] = args[4];
|
|
r.ChangeTid(tid);
|
|
r.SpawnFlags = SpawnFlags&~MTF_SECRET;
|
|
r.HandleSpawnFlags();
|
|
r.SpawnFlags = SpawnFlags;
|
|
r.bCountSecret = SpawnFlags&MTF_SECRET;
|
|
r.vel = vel;
|
|
r.master = master;
|
|
r.target = target;
|
|
r.tracer = tracer;
|
|
r.bDropped = bDropped;
|
|
}
|
|
else Owner.RemoveInventory(self);
|
|
Destroy();
|
|
}
|
|
Default
|
|
{
|
|
Tag "$T_OLSMPAMMO";
|
|
Inventory.Icon "I_OLSMP";
|
|
Inventory.PickupMessage "$I_OLSMPAMMO";
|
|
Inventory.Amount 100;
|
|
Inventory.MaxAmount 300;
|
|
Ammo.BackpackAmount 0;
|
|
Ammo.BackpackMaxAmount 900;
|
|
Ammo.DropAmount 100;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
UCLP A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class OLSMP : UnrealWeapon
|
|
{
|
|
int ClipCount;
|
|
double AltAccuracy;
|
|
|
|
property ClipCount : ClipCount;
|
|
|
|
override int, int, bool, bool GetClipAmount()
|
|
{
|
|
return ClipCount, -1, (ClipCount<35), false;
|
|
}
|
|
override void PlayUpSound( Actor origin )
|
|
{
|
|
origin.A_PlaySound(upsound,CHAN_WEAPON,Dampener.Active(origin)?.1:1.,pitch:0.8);
|
|
}
|
|
override bool TryPickup( in out Actor toucher )
|
|
{
|
|
if ( !sting_olsmp ) return false; // not allowed
|
|
return Super.TryPickup(toucher);
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( sting_olsmp ) return;
|
|
if ( !Owner )
|
|
{
|
|
let r = Spawn("BFG9000",pos,ALLOW_REPLACE);
|
|
r.spawnangle = spawnangle;
|
|
r.spawnpoint = spawnpoint;
|
|
r.angle = angle;
|
|
r.pitch = pitch;
|
|
r.roll = roll;
|
|
r.special = special;
|
|
r.args[0] = args[0];
|
|
r.args[1] = args[1];
|
|
r.args[2] = args[2];
|
|
r.args[3] = args[3];
|
|
r.args[4] = args[4];
|
|
r.ChangeTid(tid);
|
|
r.SpawnFlags = SpawnFlags&~MTF_SECRET;
|
|
r.HandleSpawnFlags();
|
|
r.SpawnFlags = SpawnFlags;
|
|
r.bCountSecret = SpawnFlags&MTF_SECRET;
|
|
r.vel = vel;
|
|
r.master = master;
|
|
r.target = target;
|
|
r.tracer = tracer;
|
|
r.bDropped = bDropped;
|
|
Destroy();
|
|
}
|
|
else
|
|
{
|
|
Owner.RemoveInventory(self);
|
|
Destroy();
|
|
}
|
|
}
|
|
action void A_OLSMPRefire( statelabel flash = null, bool slave = false )
|
|
{
|
|
Weapon weap = Weapon(invoker);
|
|
if ( !weap || !player ) return;
|
|
if ( invoker.altaccuracy < 0.2 ) invoker.altaccuracy += 0.01;
|
|
if ( invoker.clipcount < 35 ) A_PlaySound("automag/click",CHAN_ITEM,!Dampener.Active(self)?1.:.35,pitch:1.6);
|
|
if ( invoker.clipcount <= 0 )
|
|
{
|
|
A_ClearRefire();
|
|
return;
|
|
}
|
|
A_Refire(flash);
|
|
}
|
|
action void A_OLSMPFire( bool alt = false )
|
|
{
|
|
Weapon weap = Weapon(invoker);
|
|
if ( !weap ) return;
|
|
if ( invoker.clipcount <= 0 ) return;
|
|
invoker.clipcount--;
|
|
invoker.FireEffect();
|
|
UTMainHandler.DoFlash(self,Color(32,255,128,0),1);
|
|
A_PlaySound("automag/fire",CHAN_WEAPON,!Dampener.Active(self)?1.:.2,pitch:FRandom[Automag](1.2,1.8)*(alt?2.5:1.));
|
|
if ( !Dampener.Active(self) ) A_AlertMonsters();
|
|
A_QuakeEx(1,1,1,8,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.15);
|
|
A_Overlay(-2,"MuzzleFlash");
|
|
A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
|
|
A_OverlayRenderstyle(-2,STYLE_Add);
|
|
UTMainHandler.DoSwing(self,(FRandom[Automag](-2.,-5.)*invoker.altaccuracy,FRandom[Automag](-3.,2.)*invoker.altaccuracy),3,1,2,SWING_Spring,1,2);
|
|
Vector3 x, y, z, x2, y2, z2;
|
|
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
|
|
if ( alt )
|
|
{
|
|
vel -= x*(player.onground?2.:0.8);
|
|
vel.z += (player.onground?.3:.08);
|
|
}
|
|
else
|
|
{
|
|
vel -= x*(player.onground?2.2:1.);
|
|
vel.z += (player.onground?.5:.15);
|
|
}
|
|
Vector3 origin = Vec2OffsetZ(0,0,player.viewz)+10.0*x;
|
|
origin = origin-z*1.0+y*4.0;
|
|
double a = FRandom[Automag](0,360), s = FRandom[Automag](0,alt?(0.05+invoker.altaccuracy):0.05);
|
|
[x2, y2, z2] = dt_CoordUtil.GetAxes(BulletSlope(),angle,roll);
|
|
Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
|
|
FLineTraceData d;
|
|
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
|
|
if ( d.HitType == TRACE_HitActor )
|
|
{
|
|
int dmg = 17;
|
|
dmg = d.HitActor.DamageMobj(invoker,self,dmg,'shot',DMG_USEANGLE|DMG_THRUSTLESS,atan2(d.HitDir.y,d.HitDir.x));
|
|
double mm = 3000;
|
|
if ( FRandom[Automag](0,1) < 0.2 ) mm *= 5;
|
|
UTMainHandler.DoKnockback(d.HitActor,d.HitDir,mm);
|
|
if ( d.HitActor.bNOBLOOD )
|
|
{
|
|
let p = Spawn("BulletImpact",d.HitLocation);
|
|
p.angle = atan2(d.HitDir.y,d.HitDir.x)+180;
|
|
p.pitch = asin(d.HitDir.z);
|
|
}
|
|
else
|
|
{
|
|
d.HitActor.TraceBleed(dmg,self);
|
|
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
|
|
}
|
|
}
|
|
else if ( d.HitType != TRACE_HitNone )
|
|
{
|
|
Vector3 hitnormal = -d.HitDir;
|
|
if ( d.HitType == TRACE_HitFloor )
|
|
{
|
|
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
|
|
else hitnormal = d.HitSector.floorplane.Normal;
|
|
}
|
|
else if ( d.HitType == TRACE_HitCeiling )
|
|
{
|
|
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
|
|
else hitnormal = d.HitSector.ceilingplane.Normal;
|
|
}
|
|
else if ( d.HitType == TRACE_HitWall )
|
|
{
|
|
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
|
|
if ( !d.LineSide ) hitnormal *= -1;
|
|
}
|
|
let p = Spawn("BulletImpact",d.HitLocation+hitnormal*0.01);
|
|
p.angle = atan2(hitnormal.y,hitnormal.x);
|
|
p.pitch = asin(-hitnormal.z);
|
|
if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
|
|
}
|
|
for ( int i=0; i<3; i++ )
|
|
{
|
|
let s = Spawn("UTViewSmoke",origin);
|
|
UTViewSmoke(s).ofs = (10,4,-1);
|
|
s.target = self;
|
|
s.alpha *= 0.5;
|
|
}
|
|
origin += x*8.0+y*6.0-z*2.0;
|
|
let c = Spawn("UCasing",origin);
|
|
c.vel = x*FRandom[Junk](-1.5,1.5)+y*FRandom[Junk](2,4)+z*FRandom[Junk](2,3);
|
|
}
|
|
override bool CheckAmmo( int fireMode, bool autoSwitch, bool requireAmmo, int ammocount )
|
|
{
|
|
if ( ClipCount > 0 ) return true;
|
|
return Super.CheckAmmo(firemode,autoswitch,requireammo,ammocount);
|
|
}
|
|
Default
|
|
{
|
|
Tag "$T_OLSMP";
|
|
Inventory.PickupMessage "$I_OLSMP";
|
|
Weapon.UpSound "automag/select";
|
|
Weapon.SlotNumber 0;
|
|
Weapon.SelectionOrder 9;
|
|
Weapon.SlotPriority 0.95;
|
|
Weapon.AmmoType "OLSMPAmmo";
|
|
Weapon.AmmoUse 1;
|
|
Weapon.AmmoType2 "OLSMPAmmo";
|
|
Weapon.AmmoUse2 1;
|
|
Weapon.AmmoGive 100;
|
|
Weapon.Kickback 320;
|
|
UTWeapon.DropAmmo 50;
|
|
OLSMP.ClipCount 100;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
AUTP A -1;
|
|
Stop;
|
|
AUTP B -1;
|
|
Stop;
|
|
Select:
|
|
AUTS A 1 A_Raise(int.max);
|
|
Ready:
|
|
AUTS ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 A_WeaponReady(WRF_NOFIRE);
|
|
AUS2 ABCD 1 A_WeaponReady(WRF_NOFIRE);
|
|
Idle:
|
|
AUTI A 0 A_Overlay(-9999,"Dummy");
|
|
AUTI AB 30;
|
|
AUTI A 0 A_Jump(50,"Twiddle");
|
|
Goto Idle+1;
|
|
Twiddle:
|
|
AUTT ABCDEFGHIJKLMNOPQRSTUVWXY 2;
|
|
Goto Idle+1;
|
|
Dummy:
|
|
TNT1 A 1
|
|
{
|
|
A_CheckReload();
|
|
if ( (invoker.clipcount <= 0) && (invoker.Ammo1.Amount > 0) ) A_Overlay(PSP_WEAPON,"Reload");
|
|
else if ( invoker.clipcount < min(invoker.default.clipcount,invoker.Ammo1.Amount) ) A_WeaponReady(WRF_ALLOWRELOAD);
|
|
else A_WeaponReady();
|
|
}
|
|
Wait;
|
|
Fire:
|
|
AUTF A 1 A_Overlay(-9999,null);
|
|
AUTF BCD 1;
|
|
Hold:
|
|
AUTF E 1 A_OLSMPFire();
|
|
AUTF F 1;
|
|
AUTF G 0 A_OLSMPRefire(1);
|
|
Goto Release1;
|
|
AUTF G 1;
|
|
AUTF H 1 A_OLSMPFire();
|
|
AUTF I 1;
|
|
AUTF J 0 A_OLSMPRefire(1);
|
|
Goto Release2;
|
|
AUTF J 1;
|
|
AUTF K 1 A_OLSMPFire();
|
|
AUTF L 1;
|
|
AUTF M 0 A_OLSMPRefire(1);
|
|
Goto Release3;
|
|
AUTF M 1;
|
|
Goto Hold;
|
|
Release1:
|
|
AUTF G 1;
|
|
Goto Release;
|
|
Release2:
|
|
AUTF J 1;
|
|
Goto Release;
|
|
Release3:
|
|
AUTF M 1;
|
|
Goto Release;
|
|
Release:
|
|
AUTF NOPQRST 1;
|
|
AUTI A 0;
|
|
Goto Idle;
|
|
AltFire:
|
|
AUTF A 1 A_Overlay(-9999,null);
|
|
AUTF BCD 1;
|
|
AltHold:
|
|
AUTF E 1 A_OLSMPFire(true);
|
|
AUTF H 0 A_OLSMPRefire(1);
|
|
Goto AltRelease1;
|
|
AUTF H 1 A_OLSMPFire(true);
|
|
AUTF K 0 A_OLSMPRefire(1);
|
|
Goto AltRelease2;
|
|
AUTF K 1 A_OLSMPFire(true);
|
|
AUTF E 0 A_OLSMPRefire("AltHold");
|
|
Goto AltRelease3;
|
|
AltRelease1:
|
|
AUTF FG 1;
|
|
Goto Release;
|
|
AltRelease2:
|
|
AUTF IJ 1;
|
|
Goto Release;
|
|
AltRelease3:
|
|
AUTF LM 1;
|
|
Goto Release;
|
|
Reload:
|
|
AUTR A 0 A_JumpIf(invoker.clipcount>=min(invoker.default.clipcount,invoker.Ammo1.Amount),"Idle");
|
|
AUTR A 0
|
|
{
|
|
invoker.special1 = min(invoker.default.clipcount,invoker.Ammo1.Amount)-invoker.clipcount;
|
|
invoker.clipcount = -1;
|
|
A_Overlay(-9999,null);
|
|
A_WeaponOffset(0,32); // fix sudden psprite lowering
|
|
A_PlaySound("automag/click",CHAN_WEAPON,!Dampener.Active(self)?1.:.1,pitch:0.8);
|
|
}
|
|
AUTR ABCDEFGHIJKLMNOPQRSTUVWXY 1;
|
|
AUTD ABCD 1;
|
|
AUTD E 30
|
|
{
|
|
|
|
invoker.clipcount = Min(invoker.default.clipcount,invoker.Ammo1.Amount);
|
|
invoker.Ammo1.Amount -= invoker.special1;
|
|
A_PlaySound("automag/reload",CHAN_WEAPON,!Dampener.Active(self)?1.:.1,pitch:0.8);
|
|
if ( self is 'UTPlayer' )
|
|
UTPlayer(self).PlayReloading();
|
|
}
|
|
AUTS A 0 A_PlaySound("automag/select",CHAN_WEAPON,!Dampener.Active(self)?1.:.1,pitch:0.8);
|
|
Goto Ready;
|
|
Deselect:
|
|
AUTD A 1 A_Overlay(-9999,null);
|
|
AUTD BCD 1;
|
|
AUTD E 1 A_Lower(int.max);
|
|
Wait;
|
|
MuzzleFlash:
|
|
TNT1 A 0 A_Jump(256,1,2,3,4,5,6,7,8,9);
|
|
AMUZ A 2 Bright
|
|
{
|
|
let l = Spawn("EnforcerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
AMUZ B 2 Bright
|
|
{
|
|
let l = Spawn("EnforcerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
AMUZ C 2 Bright
|
|
{
|
|
let l = Spawn("EnforcerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
AMUZ D 2 Bright
|
|
{
|
|
let l = Spawn("EnforcerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
AMUZ E 2 Bright
|
|
{
|
|
let l = Spawn("EnforcerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
AMUZ F 2 Bright
|
|
{
|
|
let l = Spawn("EnforcerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
AMUZ G 2 Bright
|
|
{
|
|
let l = Spawn("EnforcerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
AMUZ H 2 Bright
|
|
{
|
|
let l = Spawn("EnforcerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
AMUZ I 2 Bright
|
|
{
|
|
let l = Spawn("EnforcerLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
}
|
|
}
|