stinger_m/zscript/uflakcannon.zsc
Marisa the Magician a21aa43f35 1.2 update, w/ GZDoom 4.9 stuff:
- Customizable player skins here too.
 - Integrated re-skin add-ons ("Old Sounds" is still separate).
 - The usual fixes and optimizations.
 - All weapons are now left-handed, where possible.
2022-11-06 00:02:46 +01:00

384 lines
10 KiB
Text

Class UFlakBox : Ammo
{
Default
{
Tag "$T_FLAKAMMO";
Inventory.Icon "I_FlakAm";
Inventory.PickupMessage "";
Inventory.Amount 10;
Inventory.MaxAmount 50;
Ammo.BackpackAmount 5;
Ammo.BackpackMaxAmount 100;
Ammo.DropAmount 5;
}
override String PickupMessage()
{
if ( PickupMsg.Length() > 0 ) return Super.PickupMessage();
return String.Format("%s%d%s",StringTable.Localize("$I_FLAKAMMOL"),Amount,StringTable.Localize("$I_FLAKAMMOR"));
}
States
{
Spawn:
FAMO A -1;
Stop;
}
}
Class UFlakAmmo : UFlakBox
{
Default
{
Tag "$T_FLAKAMMO2";
Inventory.Icon "I_FlakAm";
Inventory.PickupMessage "$I_FLAKAMMO2";
Inventory.Amount 1;
Ammo.DropAmount 1;
+INVENTORY.IGNORESKILL;
}
States
{
Spawn:
FAMO B -1;
Stop;
}
}
// subclass to save time, much of the behavior is the same anyway
Class UFlakChunk : FlakChunk
{
override void PostBeginPlay()
{
Actor.PostBeginPlay();
// no trail, spin much slower
lifetime = 0;
rollvel = FRandom[Flak](5,10)*RandomPick[Flak](-1,1);
pitchvel = FRandom[Flak](5,10)*RandomPick[Flak](-1,1);
yawvel = FRandom[Flak](5,10)*RandomPick[Flak](-1,1);
scale *= Frandom[Flak](0.8,1.2);
SetState(ResolveState("Spawn")+Random[Flak](0,3));
}
override void Tick()
{
oldvel = vel;
Actor.Tick();
if ( isFrozen() ) return;
// no slowing down in water, only set to falling
if ( waterlevel > 0 )
{
bNOGRAVITY = false;
bAMBUSH = true;
}
lifetime += lifespeed;
// no frame changes, smoke based on speed + age
if ( (waterlevel <= 0) && !bAMBUSH && !(GetAge()%2) )
{
let s = Spawn("UTSmoke",pos);
s.vel = (FRandom[Flak](-0.1,0.1),FRandom[Flak](-0.1,0.1),FRandom[Flak](-0.1,0.1));
s.alpha = (scale.x*clamp((120-GetAge())/120.+(vel.length()/20.),0.5,2.0))/0.5;
s.SetShade("AAAAAA");
}
else if ( waterlevel > 0 )
{
let s = Spawn("UTBubble",pos);
s.vel = (FRandom[Flak](-0.1,0.1),FRandom[Flak](-0.1,0.1),FRandom[Flak](-0.1,0.1));
s.scale *= scale.x*0.5;
}
if ( InStateSequence(CurState,FindState("Death")) ) return;
roll += rollvel;
pitch += pitchvel;
angle += pitchvel;
}
Default
{
DamageFunction 17; // exactly 1 point higher than UT
Scale 0.5;
}
States
{
Bounce:
#### # 0
{
A_HandleBounce();
// override spin velocity changes from parent class
rollvel = FRandom[Flak](5,10)*RandomPick[Flak](-1,1);
pitchvel = FRandom[Flak](5,10)*RandomPick[Flak](-1,1);
yawvel = FRandom[Flak](5,10)*RandomPick[Flak](-1,1);
}
Goto Idle;
}
}
// Also subclassed to save time, only the explosion needs to change
Class UFlakSlug : FlakSlug
{
action void A_UFlakExplode()
{
bForceXYBillboard = true;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("RocketBlast",50);
A_NoGravity();
A_SetScale(2.2);
UTMainHandler.DoBlast(self,120,75000);
A_Explode(70,120);
A_QuakeEx(4,4,4,8,0,170,"",QF_RELATIVE|QF_SCALEDOWN,falloff:120,rollIntensity:0.2);
A_StartSound("uflak/explode",CHAN_VOICE);
A_AlertMonsters();
if ( !Tracer ) Spawn("SlugSmoke",pos);
Spawn("SlugLight",pos);
Vector3 x, y, z;
double a, s;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Actor p;
Vector3 spawnofs;
if ( BlockingMobj ) spawnofs = level.Vec3Diff(pos,BlockingMobj.Vec3Offset(0,0,BlockingMobj.height/2)).unit()*8;
else if ( BlockingFloor ) spawnofs = BlockingFloor.floorplane.Normal*8;
else if ( BlockingCeiling ) spawnofs = BlockingCeiling.ceilingplane.Normal*8;
else if ( BlockingLine )
{
spawnofs = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit()*8;
if ( !BlockingLine.sidedef[1] || (CurSector == BlockingLine.frontsector) )
spawnofs *= -1;
}
for ( int i=0; i<5; i++ )
{
p = Spawn("UFlakChunk",Vec3Offset(spawnofs.x,spawnofs.y,spawnofs.z));
p.bHITOWNER = true;
a = FRandom[Flak](0,360);
s = FRandom[Flak](0,0.1);
Vector3 dir = dt_Utility.ConeSpread(x,y,z,a,s);
p.angle = atan2(dir.y,dir.x);
p.pitch = -asin(dir.z);
p.vel = dt_Utility.Vec3FromAngle(p.angle,p.pitch)*(p.speed+FRandom[Flak](-3,3));
p.target = target;
}
int numpt = Random[Flak](8,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Flak](-1,1),FRandom[Flak](-1,1),FRandom[Flak](-1,1)).unit()*FRandom[Flak](2,8);
let s = Spawn("UTSpark",pos);
s.vel = pvel;
}
numpt = Random[Flak](15,30);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Flak](-1,1),FRandom[Flak](-1,1),FRandom[Flak](-1,1)).unit()*FRandom[Flak](6,16);
let s = Spawn("UTChip",pos);
s.vel = pvel;
s.scale *= FRandom[Flak](0.9,1.8);
}
}
States
{
Death:
FEXP A 0 A_UFlakExplode();
FEXP ABCDEFGHIJ 2 BRIGHT;
Stop;
}
}
Class UFlakMag : FlakMag
{
}
Class UFlakCannon : UnrealWeapon
{
action void A_Loading( bool first = false )
{
if ( first ) A_StartSound("uflak/load",CHAN_WEAPONMISC,CHANF_OVERLAP,Dampener.Active(self)?.1:1.);
else A_StartSound("uflak/reload",CHAN_WEAPONMISC,CHANF_OVERLAP,Dampener.Active(self)?.06:.6);
}
action void A_FireChunks()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_StartSound("uflak/fire",CHAN_WEAPON,CHANF_OVERLAP,Dampener.Active(self)?.2:1.);
A_Overlay(PSP_FLASH,"Flash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(48,255,96,0),1);
if ( !Dampener.Active(self) ) A_AlertMonsters();
A_QuakeEx(1,1,1,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.05);
Vector3 x, y, z;
double a, s;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x-5*y-4*z);
[x, y, z] = dt_CoordUtil.GetAxes(BulletSlope(),angle,roll);
Vector3 offsets[8]; // vanilla adds these to each chunk
offsets[0] = (0,0,0);
offsets[1] = -z;
offsets[2] = 2*y+z;
offsets[3] = -y;
offsets[4] = 2*y-z;
offsets[5] = (0,0,0);
offsets[6] = y-z;
offsets[7] = 2*y+z;
Actor p;
for ( int i=0; i<8; i++ )
{
p = Spawn("UFlakChunk",level.Vec3Offset(origin,offsets[i]));
a = FRandom[Flak](0,360);
s = FRandom[Flak](0,0.1);
Vector3 dir = dt_Utility.ConeSpread(x,y,z,a,s);
p.angle = atan2(dir.y,dir.x);
p.pitch = -asin(dir.z);
p.vel = dt_Utility.Vec3FromAngle(p.angle,p.pitch)*(p.speed+FRandom[Flak](-3,3));
p.target = self;
}
int numpt = Random[Flak](20,30);
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("UTViewSpark",origin);
UTViewSpark(s).ofs = (10,-5,-4);
UTViewSpark(s).vvel = (FRandom[Flak](3,12),FRandom[Flak](-4,4),FRandom[Flak](-4,4));
s.target = self;
}
for ( int i=0; i<10; i++ )
{
let s = Spawn("UTViewSmoke",origin);
UTViewSmoke(s).ofs = (10,-5,-4);
UTViewSmoke(s).vvel = (FRandom[Flak](0,1.2),FRandom[Flak](-.4,.4),FRandom[Flak](-.4,.4));
s.target = self;
s.scale *= 1.6;
s.alpha *= 0.5;
}
}
action void A_FireSlug()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_StartSound("uflak/altfire",CHAN_WEAPON,CHANF_OVERLAP,Dampener.Active(self)?.2:1.);
A_Overlay(PSP_FLASH,"Flash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(32,255,96,0),1);
if ( !Dampener.Active(self) ) A_AlertMonsters();
A_QuakeEx(2,2,2,6,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
double a, s;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x-5*y-4*z);
Actor p = Spawn("UFlakSlug",origin);
p.angle = angle;
p.pitch = BulletSlope();
p.vel = dt_Utility.Vec3FromAngle(p.angle,p.pitch)*p.speed;
p.target = self;
int numpt = Random[Flak](10,15);
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("UTViewSpark",origin);
UTViewSpark(s).ofs = (10,-5,-4);
UTViewSpark(s).vvel = (FRandom[Flak](3,12),FRandom[Flak](-4,4),FRandom[Flak](-4,4));
s.target = self;
}
for ( int i=0; i<8; i++ )
{
let s = Spawn("UTViewSmoke",origin);
UTViewSmoke(s).ofs = (10,-5,-4);
UTViewSmoke(s).vvel = (FRandom[Flak](0,1.2),FRandom[Flak](-.8,.8),FRandom[Flak](-.8,.8));
s.target = self;
s.scale *= 1.6;
s.alpha *= 0.5;
}
}
Default
{
Tag "$T_FLAKCANNON";
Inventory.PickupMessage "$I_FLAKCANNON";
Weapon.UpSound "uflak/select";
Weapon.SlotNumber 6;
Weapon.SelectionOrder 1100;
Weapon.SlotPriority 1;
Weapon.AmmoType "UFlakBox";
Weapon.AmmoUse 1;
Weapon.AmmoType2 "UFlakBox";
Weapon.AmmoUse2 1;
Weapon.AmmoGive 10;
UTWeapon.DropAmmo 5;
}
States
{
Spawn:
FPCK A -1;
Stop;
FPCK B -1;
Stop;
Select:
FLKS A 1 A_Raise(int.max);
Wait;
Ready:
FLKS ABCDFGHIKLMNPQRSUVWXZ 1 A_WeaponReady(WRF_NOFIRE);
FLS2 ABC 1 A_WeaponReady(WRF_NOFIRE);
FLKL A 1 A_Loading(true);
FLKL BCEFGIJKMNO 1;
Goto Idle;
Loading:
FLKL A 1
{
A_CheckReload();
if ( invoker.Ammo1.Amount > 0 ) A_Loading();
}
FLKL BCEFGIJKMNO 1;
Goto Idle;
AltLoading:
FLKL A 2
{
A_CheckReload();
if ( invoker.Ammo1.Amount > 0 ) A_Loading();
}
FLKL BCEFGIJKMNO 2;
Goto Idle;
Idle:
FLKI A 1 A_WeaponReady();
Wait;
Fire:
FLKF A 1 A_FireChunks();
FLKF BCDEFGHI 1;
FLKF J 5;
FLKE A 1 A_StartSound("uflak/click",CHAN_WEAPONMISC,CHANF_OVERLAP,Dampener.Active(self)?.05:.5);
FLKE BCDEFGHIJKLMN 1;
FLKE S 4
{
Vector3 x, y, z, origin;
[x,y,z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),x*4.-y*3.-z*8.);
let c = Spawn("UFlakMag",origin);
c.angle = angle;
c.pitch = pitch;
c.vel = vel*.5+x*FRandom[Junk](-.8,.1)+y*FRandom[Junk](-.2,.2)-z*FRandom[Junk](1,2);
}
Goto Loading;
AltFire:
FLKA A 1 A_FireSlug();
FLKA BCDEFGHIJK 1;
FLKA K 10;
Goto AltLoading;
Deselect:
FLKD A 0 A_JumpIfNoAmmo("Deselect2");
FLKD ABCDEF 1;
FLKD F 1 A_Lower(int.max);
Wait;
Deselect2:
FLD2 ABCDEF 1;
FLD2 F 1 A_Lower(int.max);
Wait;
Flash:
FMUZ A 3 Bright
{
let l = Spawn("FlakLight",pos);
l.target = self;
}
Stop;
/*Flash:
FLFF ABCDEFGHIJ 1 Bright;
Stop;
AltFlash:
FLFA ABCDEF 1 Bright;
Stop;*/
}
}