stinger_m/zscript/uflakcannon.zsc
Marisa Kirisame fae4f6d50b Partially implemented Stunner and Impaler (very unfinished).
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.
2019-09-16 00:38:38 +02:00

365 lines
9.7 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_PlaySound("flak/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 = (x+y*cos(a)*s+z*sin(a)*s).unit();
p.angle = atan2(dir.y,dir.x);
p.pitch = -asin(dir.z);
p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(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 UFlakCannon : UnrealWeapon
{
action void A_Loading( bool first = false )
{
if ( first ) A_PlaySound("flak/load",CHAN_WEAPON,Dampener.Active(self)?.1:1.);
else A_PlaySound("flak/reload",CHAN_6,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_PlaySound("flak/fire",CHAN_WEAPON,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);
UTMainHandler.DoSwing(self,(FRandom[Flak](-0.3,-0.8),FRandom[Flak](-0.5,0.5)),4,-1.5,2,SWING_Spring,2,2);
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 = (pos.x,pos.y,player.viewz)+10.0*x+5.0*y-4.0*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 = (x+y*cos(a)*s+z*sin(a)*s).unit();
p.angle = atan2(dir.y,dir.x);
p.pitch = -asin(dir.z);
p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(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_PlaySound("flak/altfire",CHAN_WEAPON,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);
UTMainHandler.DoSwing(self,(FRandom[Flak](-0.4,-0.8),FRandom[Flak](0.4,0.8)),4,-1,3,SWING_Spring,3,5);
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 = (pos.x,pos.y,player.viewz)+10.0*x+5.0*y-4.0*z;
Actor p = Spawn("UFlakSlug",origin);
p.angle = angle;
p.pitch = BulletSlope();
p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(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 "flak/select";
Weapon.SlotNumber 6;
Weapon.SelectionOrder 4;
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;
Idle:
FLKI A 1 A_WeaponReady();
Wait;
Fire:
FLKF A 1 A_FireChunks();
FLKF BCDEFGHI 1;
FLKF J 5;
FLKE A 1 A_PlaySound("flak/click",CHAN_6,Dampener.Active(self)?.05:.5);
FLKE BCDEFGHIJKLMN 1;
FLKE S 4;
Goto Loading;
AltFire:
FLKA A 1 A_FireSlug();
FLKA BCDEFGHIJK 1;
FLKA K 10;
Goto Loading;
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;*/
}
}