386 lines
10 KiB
Text
386 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 = (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 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);
|
|
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 = 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 = (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_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);
|
|
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 = 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 = (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 "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;*/
|
|
}
|
|
}
|