stinger_m/zscript/automag.zsc
Marisa Kirisame 912cad96c5 Oh boy, it begins.
Assigned all pickup models.
Implemented all ammo types.
Finished Flak Cannon.
Additional cleanup.
Slot reassignments and other adjustments to match known Unreal prototype info.
2019-09-04 02:37:59 +02:00

568 lines
15 KiB
Text

Class UClip : UMiniAmmo
{
Default
{
Tag "$T_CLIP";
Inventory.PickupMessage "$I_CLIP";
Inventory.Amount 20;
Ammo.DropAmount 5;
}
States
{
Spawn:
UCLP A -1;
Stop;
}
}
Class UCasing : UTCasing
{
}
Class Automag : UnrealWeapon
{
int ClipCount, SlaveClipCount;
bool SlaveActive, SlaveDown, SlaveReload, SlaveAltFire, SlaveSpin;
int SlaveRefire;
double AltAccuracy;
property ClipCount : ClipCount;
property SlaveClipCount : SlaveClipCount;
override bool HandlePickup( Inventory item )
{
if ( sting_automags && (item.GetClass() == GetClass()) )
{
SetTag(StringTable.Localize("$T_AUTOMAG2"));
return Super.HandlePickup(item);
}
return Super.HandlePickup(item);
}
override String PickupMessage()
{
if ( Owner ) return Super.PickupMessage();
return StringTable.Localize("$I_AUTOMAG2");
}
override Inventory CreateTossable( int amt )
{
Inventory inv = Super.CreateTossable(amt);
if ( inv )
{
SetTag(StringTable.Localize("$T_AUTOMAG"));
inv.SetTag(StringTable.Localize("$T_AUTOMAG"));
if ( Owner && (Owner.player.ReadyWeapon == self) )
{
// delete the slave overlay
PSprite psp;
for ( psp = Owner.player.psprites; psp; psp = psp.next )
{
if ( (psp.Caller == self) && ((psp.id == 2) || (psp.id == -9998)) ) psp.Destroy();
slaveactive = false;
slavedown = false;
}
}
}
return inv;
}
action void A_AutomagRefire( statelabel flash = null, bool slave = false )
{
Weapon weap = Weapon(invoker);
if ( !weap || !player ) return;
if ( invoker.altaccuracy < 0.2 ) invoker.altaccuracy += 0.05;
if ( slave )
{
if ( invoker.slaveclipcount < 5 ) A_PlaySound("automag/click",CHAN_ITEM,!Dampener.Active(self)?1.:.35);
if ( (invoker.slaveclipcount <= 0) || (weap.Ammo1.Amount <= 0) )
{
invoker.slaverefire = 0;
return;
}
bool pending = (player.PendingWeapon != WP_NOCHANGE) && (player.WeaponState & WF_REFIRESWITCHOK);
if ( (player.cmd.buttons&BT_ATTACK) && !invoker.slavealtfire && !pending && (player.health > 0) )
{
invoker.slaverefire++;
if ( player.ReadyWeapon.CheckAmmo(Weapon.PrimaryFire,true) )
player.setpsprite(2,flash?ResolveState(flash):ResolveState("LeftHold"));
}
else if ( (player.cmd.buttons&BT_ALTATTACK) && invoker.slavealtfire && !pending && (player.health > 0) )
{
invoker.slaverefire++;
if ( player.ReadyWeapon.CheckAmmo(Weapon.AltFire,true) )
player.setpsprite(2,flash?ResolveState(flash):ResolveState("LeftAltHold"));
}
else
{
invoker.slaverefire = 0;
player.ReadyWeapon.CheckAmmo(invoker.slavealtfire?Weapon.AltFire:Weapon.PrimaryFire,true);
}
}
else
{
if ( invoker.clipcount < 5 ) A_PlaySound("automag/click",CHAN_ITEM,!Dampener.Active(self)?1.:.35);
if ( (invoker.clipcount <= 0) || (weap.Ammo1.Amount <= 0) )
{
A_ClearRefire();
return;
}
A_Refire(flash);
}
}
action void A_LeftWeaponReady()
{
Weapon weap = Weapon(invoker);
if ( !weap || !player ) return;
if ( player.cmd.buttons&BT_ATTACK && !player.ReadyWeapon.bAltFire )
{
if ( (invoker.slaveclipcount <= 0) && (weap.Ammo1.Amount > 0) )
{
player.setpsprite(2,ResolveState("LeftReload"));
return;
}
invoker.slaverefire = 0;
invoker.slavealtfire = false;
player.setpsprite(2,ResolveState("LeftFire"));
}
else if ( player.cmd.buttons&BT_ALTATTACK && player.ReadyWeapon.bAltFire )
{
if ( (invoker.slaveclipcount <= 0) && (weap.Ammo1.Amount > 0) )
{
player.setpsprite(2,ResolveState("LeftReload"));
return;
}
invoker.slaverefire = 0;
invoker.slavealtfire = true;
player.setpsprite(2,ResolveState("LeftAltFire"));
}
}
action void A_AutomagFire( bool alt = false, bool slave = false )
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
if ( slave ) invoker.slaveclipcount--;
else invoker.clipcount--;
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(32,255,128,0),1);
A_PlaySound("automag/fire",slave?CHAN_6:CHAN_WEAPON,!Dampener.Active(self)?1.:.2);
if ( !Dampener.Active(self) ) A_AlertMonsters();
A_QuakeEx(2,2,2,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.08);
if ( slave )
{
if ( alt ) A_Overlay(-3,"LeftAltMuzzleFlash");
else A_Overlay(-3,"LeftMuzzleFlash");
A_OverlayFlags(-3,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
A_OverlayRenderstyle(-3,STYLE_Add);
UTMainHandler.DoSwing(self,(FRandom[Automag](0.5,0.2),FRandom[Automag](-0.3,0.2)),2,0,1,SWING_Spring,0,2);
}
else
{
if ( alt ) A_Overlay(-2,"AltMuzzleFlash");
else A_Overlay(-2,"MuzzleFlash");
A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
A_OverlayRenderstyle(-2,STYLE_Add);
UTMainHandler.DoSwing(self,(FRandom[Automag](-0.2,-0.5),FRandom[Automag](-0.3,0.2)),2,0,1,SWING_Spring,0,2);
}
Vector3 x, y, z, x2, y2, z2;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = Vec2OffsetZ(0,0,player.viewz)+10.0*x;
int ydir = slave?-1:1;
if ( alt ) origin = origin-z*3.0+ydir*y*1.0;
else origin = origin-z*1.0+ydir*y*4.0;
double a = FRandom[Automag](0,360), s = FRandom[Automag](0,alt?invoker.altaccuracy:0.01);
[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 ) hitnormal = d.HitSector.floorplane.Normal;
else if ( d.HitType == TRACE_HitCeiling ) 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);
if ( alt ) UTViewSmoke(s).ofs = (10,ydir,-3);
else UTViewSmoke(s).ofs = (10,4*ydir,-1);
s.target = self;
s.alpha *= 0.5;
}
origin += x*8.0+ydir*y*6.0-z*2.0;
let c = Spawn("UCasing",origin);
c.vel = x*FRandom[Junk](-1.5,1.5)+y*ydir*FRandom[Junk](2,4)+z*FRandom[Junk](2,3);
}
override String GetObituary( Actor victim, Actor inflictor, Name mod, bool playerattack )
{
if ( Amount > 1 ) return StringTable.Localize("$O_AUTOMAG2");
return StringTable.Localize("$O_AUTOMAG");
}
override void Travelled()
{
Super.Travelled();
slaveactive = false;
}
override void OwnerDied()
{
Super.OwnerDied();
slaverefire = 0;
}
override void Tick()
{
Super.Tick();
if ( sting_automags && (MaxAmount <= 1) ) MaxAmount = 2;
else if ( !sting_automags && (MaxAmount > 1) ) MaxAmount = 1;
if ( !Owner || sting_automags || (Amount <= 1) ) return;
// no dual wielding
if ( Owner.player.ReadyWeapon == self )
{
// delete the slave overlay
PSprite psp;
for ( psp = Owner.player.psprites; psp; psp = psp.next )
{
if ( (psp.Caller == self) && ((psp.id == 2) || (psp.id == -9998)) ) psp.Destroy();
slaveactive = false;
slavedown = false;
}
}
Amount = 1;
}
Default
{
Tag "$T_AUTOMAG";
Inventory.Icon "I_ClipAm";
Inventory.PickupMessage "$I_AUTOMAG";
Inventory.MaxAmount 1;
Inventory.InterHubAmount 2;
Weapon.UpSound "automag/select";
Weapon.SlotNumber 2;
Weapon.SelectionOrder 2;
Weapon.AmmoType "UMiniAmmo";
Weapon.AmmoUse 1;
Weapon.AmmoType2 "UMiniAmmo";
Weapon.AmmoUse2 1;
Weapon.AmmoGive 30;
Weapon.Kickback 180;
UTWeapon.DropAmmo 10;
Automag.ClipCount 20;
Automag.SlaveClipCount 20;
}
States
{
Spawn:
AUTP A -1;
Stop;
AUTP B -1;
Stop;
Select:
AUTS A 1 A_Raise(int.max);
Ready:
AUTS A 0
{
invoker.slavedown = false;
if ( !invoker.slaveactive && (CountInv("Automag") > 1) )
A_Overlay(2,"LeftReady");
}
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;
LeftReady:
2UTS A 0
{
A_PlaySound("automag/select",CHAN_6,!Dampener.Active(self)?1.:.1);
invoker.slaveactive = true;
}
2UTS ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 A_JumpIf(invoker.slavedown,"LeftDeselect");
2US2 ABCD 1 A_JumpIf(invoker.slavedown,"LeftDeselect");
LeftIdle:
2UTI A 0 A_Overlay(-9998,"LeftDummy");
2UTI AB 30;
2UTI A 0 A_Jump(50,"LeftTwiddle");
Goto LeftIdle+1;
Twiddle:
AUTT ABCDEFGHIJKLMNOPQRSTUVWXY 2;
Goto Idle+1;
LeftTwiddle:
2UTT ABCDEFGHIJKLMNOPQRSTUVWXY 2;
Goto LeftIdle+1;
Dummy:
TNT1 A 1
{
if ( (invoker.clipcount <= 0) && (invoker.Ammo1.Amount > 0) ) A_Overlay(PSP_WEAPON,"Reload");
else if ( ((invoker.clipcount < min(20,invoker.Ammo1.Amount)) || (invoker.slaveclipcount < min(20,invoker.Ammo1.Amount))) ) A_WeaponReady(WRF_ALLOWRELOAD|WRF_ALLOWZOOM);
else A_WeaponReady(WRF_ALLOWZOOM);
if ( !invoker.slaveactive && (CountInv("Automag") > 1) ) A_Overlay(2,"LeftReady");
}
Wait;
LeftDummy:
TNT1 A 1
{
if ( health <= 0 )
{
invoker.slaveactive = false;
A_Overlay(2,"LeftDeselect");
}
else if ( invoker.slavereload ) A_Overlay(2,"LeftReload");
else if ( invoker.slavedown ) A_Overlay(2,"LeftDeselect");
else if ( invoker.slavespin ) A_Overlay(2,"LeftZoom");
else A_LeftWeaponReady();
}
Wait;
Fire:
AUTF A 1 A_Overlay(-9999,null);
AUTF BCD 1;
Hold:
AUTF E 2 A_AutomagFire();
AUTF FG 2;
AUTF N 0 A_AutomagRefire(1);
Goto Release;
AUTF NN 2;
AUTF H 2 A_AutomagFire();
AUTF IJ 2;
AUTF N 0 A_AutomagRefire(1);
Goto Release;
AUTF NN 2;
AUTF K 2 A_AutomagFire();
AUTF LM 2;
AUTF N 0 A_AutomagRefire(1);
Goto Release;
AUTF NN 2;
Goto Hold;
Release:
AUTF NN 2;
AUTF OPQRST 1;
AUTI A 0;
Goto Idle;
LeftFire:
2UTI A 5 A_Overlay(-9998,null);
2UTI A 0 A_AutomagRefire(1,true);
Goto LeftIdle;
LeftHold:
2UTF ABCD 1;
2UTF E 2 A_AutomagFire(false,true);
2UTF FG 2;
2UTF N 0 A_AutomagRefire(1,true);
Goto LeftRelease;
2UTF NN 2;
2UTF H 2 A_AutomagFire(false,true);
2UTF IJ 2;
2UTF N 0 A_AutomagRefire(1,true);
Goto LeftRelease;
2UTF NN 2;
2UTF K 2 A_AutomagFire(false,true);
2UTF LM 2;
2UTF N 0 A_AutomagRefire(1,true);
Goto LeftRelease;
2UTF NN 2;
Goto LeftHold+4;
LeftRelease:
2UTF NN 2;
2UTF OPQRST 1;
2UTI A 0;
Goto LeftIdle;
AltFire:
AUTA A 0
{
invoker.altaccuracy = 0.08;
A_Overlay(-9999,null);
}
AUTA ABCDEFGHIJ 1;
AltHold:
AUTA K 2 A_AutomagFire(true);
AUTA LM 2;
AUTA T 0 A_AutomagRefire(1);
Goto AltRelease;
AUTA T 1;
AUTA N 2 A_AutomagFire(true);
AUTA OP 2;
AUTA T 0 A_AutomagRefire(1);
Goto AltRelease;
AUTA T 1;
AUTA Q 2 A_AutomagFire(true);
AUTA RS 2;
AUTA T 0 A_AutomagRefire(1);
Goto AltRelease;
AUTA T 1;
Goto AltHold;
AltRelease:
AUTA TUVWXYZ 1;
AUA2 ABCD 1;
Goto Idle;
LeftAltFire:
2UTI A 5 A_Overlay(-9998,null);
2UTI A 0 A_AutomagRefire(1,true);
LeftAltHold:
2UTA ABCDEFGHIJ 1;
2UTA K 2 A_AutomagFire(true,true);
2UTA LM 2;
2UTA T 0 A_AutomagRefire(1,true);
Goto LeftAltRelease;
2UTA T 1;
2UTA N 2 A_AutomagFire(true,true);
2UTA OP 2;
2UTA T 0 A_AutomagRefire(1,true);
Goto LeftAltRelease;
2UTA T 1;
2UTA Q 2 A_AutomagFire(true,true);
2UTA RS 2;
2UTA T 0 A_AutomagRefire(1,true);
Goto LeftAltRelease;
2UTA T 1;
Goto LeftAltHold+10;
LeftAltRelease:
2UTA TUVWXYZ 1;
2UA2 ABCD 1;
Goto LeftIdle;
Reload:
AUTR A 0
{
invoker.slavereload = ((player.cmd.buttons&BT_RELOAD)&&invoker.slaveactive&&(invoker.slaveclipcount < min(20,invoker.Ammo1.Amount)))||(invoker.slaveclipcount <= 0);
return A_JumpIf(invoker.clipcount>=min(20,invoker.Ammo1.Amount),"Idle");
}
AUTR A 0
{
invoker.clipcount = Min(20,invoker.Ammo1.Amount);
A_Overlay(-9999,null);
A_WeaponOffset(0,32); // fix sudden psprite lowering
A_PlaySound("automag/click",CHAN_WEAPON,!Dampener.Active(self)?1.:.1);
}
AUTR ABCDEFGHIJKLMNOPQRSTUVWXY 1;
AUTD ABCD 1;
AUTD E 30
{
A_PlaySound("automag/reload",CHAN_WEAPON,!Dampener.Active(self)?1.:.1);
if ( self is 'UTPlayer' )
UTPlayer(self).PlayReloading();
}
AUTS A 0 A_PlaySound("automag/select",CHAN_WEAPON,!Dampener.Active(self)?1.:.1);
Goto Ready;
LeftReload:
2UTR A 0
{
invoker.slaveclipcount = Min(20,invoker.Ammo1.Amount);
invoker.slavereload = false;
A_Overlay(-9998,null);
A_PlaySound("automag/click",CHAN_6,!Dampener.Active(self)?1.:.1);
}
2UTR ABCDEFGHIJKLMNOPQRSTUVWXY 1;
2UTD ABCD 1;
2UTD E 30
{
A_PlaySound("automag/reload",CHAN_6,!Dampener.Active(self)?1.:.1);
if ( self is 'UTPlayer' )
UTPlayer(self).PlayReloading();
}
2UTS A 0 A_PlaySound("automag/select",CHAN_6,!Dampener.Active(self)?1.:.1);
Goto LeftReady;
Zoom:
AUT2 A 1
{
A_Overlay(-9999,null);
invoker.slavespin = true;
}
AUT2 BCDEFGHIJKLMNOPQRSTUVWXYZ 1;
AUT3 AB 1;
ZoomLoop:
AUT3 CDEFGH 1;
AUT3 I 0 A_JumpIf(player.cmd.buttons&BT_ZOOM,"ZoomLoop1");
AUT3 IJKLMNOPQRS 1;
Goto Idle;
ZoomLoop1:
AUT3 I 1;
AUT3 C 0;
Goto ZoomLoop;
LeftZoom:
2UT2 A 1
{
A_Overlay(-9998,null);
invoker.slavespin = false;
}
2UT2 BCDEFGHIJKLMNOPQRSTUVWXYZ 1;
2UT3 AB 1;
LeftZoomLoop:
2UT3 CDEFGH 1;
2UT3 I 0 A_JumpIf(player.cmd.buttons&BT_ZOOM,"LeftZoomLoop1");
2UT3 IJKLMNOPQRS 1;
Goto LeftIdle;
LeftZoomLoop1:
2UT3 I 1;
2UT3 C 0;
Goto LeftZoomLoop;
Deselect:
AUTI A 1 { invoker.slavedown = true; }
AUTD A 0 A_Overlay(-9999,null);
AUTD A 0 A_JumpIf(invoker.slaveactive,"Deselect");
AUTD ABCD 1;
AUTD E 1 A_Lower(int.max);
Wait;
LeftDeselect:
2UTD A 0
{
A_Overlay(-9998,null);
invoker.slaveactive = false;
}
2UTD ABCD 1;
2UTD E 0;
Stop;
MuzzleFlash:
AMUZ A 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
AltMuzzleFlash:
AMUZ B 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
LeftMuzzleFlash:
AMUZ C 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
LeftAltMuzzleFlash:
AMUZ D 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
}
}