flak_m/zscript/enforcer.zsc
Marisa Kirisame 4c451de008 Reverted radius/height changes to items, it causes issues on many maps.
Implemented proper HUD rendering, along with toggling and resizing. Works just like in UT now.
Added "extended" version of the Beta menu music, quickly put together in OpenMPT. I really like it.
Added M_DOOM graphic and changed the titlemap texture.
Made various screen graphics additive now that I know how to.
Separated pickup and first person brightmaps for Pulse Gun, this is needed for beta skin packs (there will be skins for the Pulse Gun, Redeemer and Impact Hammer).
2018-05-31 22:02:03 +02:00

536 lines
14 KiB
Text

Class EClip : MiniAmmo replaces Clip
{
Default
{
Tag "Clip"; // "Large Bullets" in UT, but I think that's an oversight, since it's the same as the Minigun ammo
Inventory.PickupMessage "You picked up a Clip.";
Inventory.Amount 20;
Ammo.DropAmount 5;
}
States
{
Spawn:
ECLP A -1;
Stop;
}
}
Class EnforcerLight : DynamicLight
{
int cnt;
Default
{
DynamicLight.Type "Point";
args 255,224,64,150;
}
override void Tick()
{
Super.Tick();
if ( !target )
{
Destroy();
return;
}
if ( target.player ) SetOrigin(target.Vec2OffsetZ(0,0,target.player.viewz),true);
else SetOrigin(target.pos,true);
if ( cnt++ > 2 ) Destroy();
}
}
Class BulletImpact : Actor
{
Default
{
RenderStyle "Add";
Radius 0.1;
Height 0;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
Scale 0.25;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_SprayDecal("Pock",-20);
int numpt = Random[Enforcer](5,10)*scale.x*4;
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Enforcer](-.8,.8),FRandom[Enforcer](-.8,.8),FRandom[Enforcer](-.8,.8))).unit()*FRandom[Enforcer](0.1,1.2);
let s = Spawn("UTSmoke",pos+x*2);
s.vel = pvel;
s.SetShade(Color(1,1,1)*Random[Enforcer](128,192));
}
numpt = Random[Enforcer](3,8)*scale.x*4;
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Enforcer](-1,1),FRandom[Enforcer](-1,1),FRandom[Enforcer](-1,1)).unit()*FRandom[Enforcer](2,8);
let s = Spawn("UTSpark",pos+x*2);
s.vel = pvel;
}
numpt = Random[Enforcer](2,5)*scale.x*4;
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Enforcer](-1,1),FRandom[Enforcer](-1,1),FRandom[Enforcer](-1,1)).unit()*FRandom[Enforcer](2,8);
let s = Spawn("UTChip",pos+x*2);
s.vel = pvel;
}
A_PlaySound("bullet/hit",CHAN_VOICE,attenuation:3.0);
}
States
{
Spawn:
BIMP ABCDE 1 Bright;
Stop;
}
}
Class UTCasing : Actor
{
int deadtimer;
double pitchvel, anglevel;
Default
{
Radius 2;
Height 2;
+NOBLOCKMAP;
+MISSILE;
+MOVEWITHSECTOR;
+THRUACTORS;
+USEBOUNCESTATE;
BounceType "Doom";
BounceFactor 0.65;
BounceSound "bullet/casing";
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
deadtimer = 0;
pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
}
override void Tick()
{
Super.Tick();
if ( InStateSequence(CurState,ResolveState("Death")) )
{
deadtimer++;
if ( deadtimer > 300 ) A_FadeOut(0.05);
return;
}
}
States
{
Spawn:
PCAS A 1
{
A_SetAngle(angle+anglevel,SPF_INTERPOLATE);
A_SetPitch(pitch+pitchvel,SPF_INTERPOLATE);
}
Loop;
Bounce:
PCAS A 0
{
pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
vel = (vel.unit()+(FRandom[Junk](-.2,.2),FRandom[Junk](-.2,.2),FRandom[Junk](-.2,.2))).unit()*vel.length();
}
Goto Spawn;
Death:
PCAS A -1
{
A_SetPitch(0);
A_SetRoll(FRandom[Junk](0,360));
}
Stop;
}
}
Class Enforcer : UTWeapon replaces Pistol
{
int ClipCount, SlaveClipCount;
bool SlaveActive, SlaveDown, SlaveReload, SlaveAltFire;
int SlaveRefire;
property ClipCount : ClipCount;
property SlaveClipCount : SlaveClipCount;
override void PostRender( double lbottom )
{
if ( !CVar.GetCVar('flak_enforcerreload').GetBool() ) return;
if ( Amount > 1 ) Screen.DrawText(confont,Font.CR_GREEN,Screen.GetWidth()*0.01,lbottom-Screen.GetHeight()*0.01-confont.GetHeight()*2,String.Format("L Clip: %2d / 20\nR Clip: %2d / 20",slaveclipcount,clipcount));
else Screen.DrawText(confont,Font.CR_GREEN,Screen.GetWidth()*0.01,lbottom-Screen.GetHeight()*0.01-confont.GetHeight(),String.Format("Clip: %2d / 20",clipcount));
}
override bool HandlePickup( Inventory item )
{
if ( item.GetClass() == GetClass() )
{
SetTag("Dual Enforcers");
return Super.HandlePickup(item);
}
return false;
}
override Inventory CreateTossable( int amt )
{
Inventory inv = Super.CreateTossable(amt);
if ( inv )
{
SetTag("Enforcer");
inv.SetTag("Enforcer");
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.Destroy();
slaveactive = false;
slavedown = false;
}
}
}
return inv;
}
action void A_EnforcerRefire( statelabel flash = null, bool slave = false )
{
Weapon weap = Weapon(invoker);
if ( !weap || !player ) return;
if ( slave )
{
if ( CVar.GetCVar('flak_enforcerreload').GetBool() && (invoker.slaveclipcount < 5) ) A_PlaySound("enforcer/click",CHAN_6);
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 ( CVar.GetCVar('flak_enforcerreload').GetBool() && (invoker.clipcount < 5) ) A_PlaySound("enforcer/click",CHAN_WEAPON);
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 )
{
invoker.slaverefire = 0;
invoker.slavealtfire = false;
player.setpsprite(2,ResolveState("LeftFire"));
}
else if ( player.cmd.buttons&BT_ALTATTACK && player.ReadyWeapon.bAltFire )
{
invoker.slaverefire = 0;
invoker.slavealtfire = true;
player.setpsprite(2,ResolveState("LeftAltFire"));
}
}
action void A_EnforcerFire( 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--;
if ( !CVar.GetCVar('flak_enforcerreload').GetBool() && (invoker.slaveclipcount <=0) ) invoker.slaveclipcount = Min(20,weap.Ammo1.Amount);
}
else
{
invoker.clipcount--;
if ( !CVar.GetCVar('flak_enforcerreload').GetBool() && (invoker.clipcount <=0) ) invoker.clipcount = Min(20,weap.Ammo1.Amount);
}
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(32,255,128,0),1);
A_PlaySound("enforcer/shoot",slave?CHAN_6:CHAN_WEAPON);
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);
}
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);
}
Vector3 x, y, z, x2, y2, z2;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x;
int ydir = slave?-1:1;
if ( alt ) origin = origin-z*9.0+ydir*y*1.0;
else origin = origin-z*2.0+ydir*y*6.0;
double a = FRandom[Enforcer](0,360), s = FRandom[Enforcer](0,alt?0.08:0.004);
[x2, y2, z2] = Matrix4.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 = Random[Enforcer](15,20);
dmg = d.HitActor.DamageMobj(invoker,self,dmg,'shot');
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);
}
origin += x*8.0+ydir*y*6.0-z*2.0;
let c = Spawn("UTCasing",origin);
c.vel = x*FRandom[Junk](-2,2)+y*ydir*FRandom[Junk](3,6)+z*FRandom[Junk](3,5);
}
override String GetObituary( Actor victim, Actor inflictor, Name mod, bool playerattack )
{
if ( Amount > 1 ) return "%k riddled %o full of holes with the Dual Enforcers.";
return "%k riddled %o full of holes with the Enforcer.";
}
Default
{
Tag "Enforcer";
Inventory.PickupMessage "You picked up another Enforcer!";
Inventory.MaxAmount 2;
Weapon.UpSound "enforcer/select";
Weapon.SlotNumber 2;
Weapon.SelectionOrder 8;
Weapon.AmmoType "MiniAmmo";
Weapon.AmmoUse 1;
Weapon.AmmoType2 "MiniAmmo";
Weapon.AmmoUse2 1;
Weapon.AmmoGive 30;
Enforcer.ClipCount 20;
Enforcer.SlaveClipCount 20;
}
States
{
Spawn:
ENFP A -1;
Stop;
ENFP B -1;
Stop;
Select:
ENFS A 1 A_Raise(int.max);
Ready:
ENFS A 0
{
invoker.slavedown = false;
if ( !invoker.slaveactive && (CountInv("Enforcer") > 1) )
A_Overlay(2,"LeftReady");
}
ENFS ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 A_WeaponReady(WRF_NOFIRE);
Idle:
ENFI A 0 A_Overlay(-9999,"Dummy");
ENFI AB 30;
ENFI A 0 A_Jump(50,"Twiddle");
Goto Idle+1;
LeftReady:
2NFS A 0
{
A_PlaySound("enforcer/select",CHAN_6);
invoker.slaveactive = true;
}
2NFS ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 A_JumpIf(invoker.slavedown,"LeftDeselect");
LeftIdle:
2NFI A 0 A_Overlay(-9998,"LeftDummy");
2NFI AB 30;
2NFI A 0 A_Jump(50,"LeftTwiddle");
Goto LeftIdle+1;
Twiddle:
ENFT ABCDEFGHIJKLMNOPQRSTUVWXY 2;
Goto Idle+1;
LeftTwiddle:
2NFT ABCDEFGHIJKLMNOPQRSTUVWXY 2;
Goto LeftIdle+1;
Dummy:
TNT1 A 1
{
if ( (invoker.clipcount <= 0) && (invoker.Ammo1.Amount > 0) ) A_Overlay(PSP_WEAPON,"Reload");
else if ( CVar.GetCVar('flak_enforcerreload').GetBool() && ((invoker.clipcount < min(20,invoker.Ammo1.Amount)) || (invoker.slaveclipcount < min(20,invoker.Ammo1.Amount))) ) A_WeaponReady(WRF_ALLOWRELOAD);
else A_WeaponReady();
if ( !invoker.slaveactive && (CountInv("Enforcer") > 1) ) A_Overlay(2,"LeftReady");
}
Wait;
LeftDummy:
TNT1 A 1
{
if ( health <= 0 )
{
invoker.slaveactive = false;
A_Overlay(2,"LeftDeselect");
}
else if ( CVar.GetCVar('flak_enforcerreload').GetBool() && (invoker.slavereload || (invoker.slaveclipcount < 0)) ) A_Overlay(2,"LeftReload");
else if ( invoker.slavedown ) A_Overlay(2,"LeftDeselect");
else A_LeftWeaponReady();
}
Wait;
Fire:
ENFF A 0 A_Overlay(-9999,"Null");
Hold:
ENFF A 0 A_EnforcerFire();
ENFF ABCDEFGHI 1;
ENFF J 3 A_EnforcerRefire();
Goto Idle;
LeftFire:
2NFI A 0 A_Overlay(-9998,"Null");
2NFI A 1 A_SetTics(Random[Enforcer](0,5));
LeftHold:
2NFF A 0 A_EnforcerFire(false,true);
2NFF ABCDEFGHI 1;
2NFF J 3 A_EnforcerRefire("LeftHold",true);
Goto LeftIdle;
AltFire:
ENFA A 0 A_Overlay(-9999,"Null");
ENFA ABCDEF 1;
AltHold:
ENFA G 0 A_EnforcerFire(true);
ENFA GHIJKLMN 1;
ENFA G 0 A_EnforcerRefire();
ENFA OPQRSTU 1;
Goto Idle;
LeftAltFire:
2NFI A 0 A_Overlay(-9998,"Null");
2NFI A 1 A_SetTics(Random[Enforcer](0,5));
2NFI A 0;
2NFA ABCDEF 1;
LeftAltHold:
2NFA G 0 A_EnforcerFire(true,true);
2NFA GHIJKLMN 1;
2NFA G 0 A_EnforcerRefire("LeftAltHold",true);
2NFA OPQRSTU 1;
Goto LeftIdle;
Reload:
ENFR A 0
{
invoker.slavereload = ((player.cmd.buttons&BT_RELOAD)&&(invoker.slaveclipcount < min(20,invoker.Ammo1.Amount)))||(invoker.slaveclipcount <= 0);
return A_JumpIf(invoker.clipcount>=min(20,invoker.Ammo1.Amount),"Idle");
}
ENFR A 0
{
invoker.clipcount = Min(20,invoker.Ammo1.Amount);
A_Overlay(-9999,"Null");
A_PlaySound("enforcer/click",CHAN_WEAPON);
}
ENFR ABCDEFGHIJKLMNOPQRSTUVWXYZ 1;
ENR2 AB 1;
ENR2 B 30 A_PlaySound("enforcer/reload",CHAN_WEAPON);
ENFS A 0 A_PlaySound("enforcer/select",CHAN_WEAPON);
Goto Ready;
LeftReload:
2NFR A 0
{
invoker.slaveclipcount = Min(20,invoker.Ammo1.Amount);
invoker.slavereload = false;
A_Overlay(-9998,"Null");
A_PlaySound("enforcer/click",CHAN_6);
}
2NFR ABCDEFGHIJKLMNOPQRSTUVWXYZ 1;
2NR2 AB 1;
2NR2 B 30 A_PlaySound("enforcer/reload",CHAN_6);
2NFS A 0 A_PlaySound("enforcer/select",CHAN_6);
Goto LeftReady;
Deselect:
ENFI A 1 { invoker.slavedown = true; }
ENFD A 0 A_Overlay(-9999,"Null");
ENFD A 0 A_JumpIf(invoker.slaveactive,"Deselect");
ENFD ABDEGHJK 1;
ENFD L 1 A_Lower(int.max);
Wait;
LeftDeselect:
2NFD A 0
{
A_Overlay(-9998,"Null");
invoker.slaveactive = false;
}
2NFD ABDEGHJK 1;
2NFD L 0;
Stop;
MuzzleFlash:
EMUZ A 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
AltMuzzleFlash:
EMUZ B 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
LeftMuzzleFlash:
EMUZ C 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
LeftAltMuzzleFlash:
EMUZ D 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
}
}