Everything in here is highly unstable and may not work. Current commit contains various new features for the HUD, some cleanup, and additional changes for compatibility with Doomreal as it is developed. The diff is kinda fucky on the font restructure due to flaky rename detection.
705 lines
16 KiB
Text
705 lines
16 KiB
Text
Class FlakAmmo : Ammo
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_FLAKAMMO";
|
|
Inventory.PickupMessage "";
|
|
Inventory.Amount 10;
|
|
Inventory.MaxAmount 50;
|
|
Ammo.BackpackAmount 20;
|
|
Ammo.BackpackMaxAmount 100;
|
|
Ammo.DropAmount 5;
|
|
}
|
|
override String PickupMessage()
|
|
{
|
|
return String.Format("%s%d%s",StringTable.Localize("$I_FLAKAMMOL"),Amount,StringTable.Localize("$I_FLAKAMMOR"));
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
FAMO A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class FlakAmmo2 : FlakAmmo
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_FLAKAMMO2";
|
|
Inventory.PickupMessage "$I_FLAKAMMO2";
|
|
Inventory.Amount 1;
|
|
Ammo.DropAmount 1;
|
|
+INVENTORY.IGNORESKILL;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
FSLG A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class ChunkLight : DynamicLight
|
|
{
|
|
Default
|
|
{
|
|
DynamicLight.Type "Point";
|
|
Args 255,224,128,8;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
SetOrigin(target.pos,true);
|
|
if ( isFrozen() ) return;
|
|
args[LIGHT_RED] = int(255*(10-target.frame)*0.1);
|
|
args[LIGHT_GREEN] = int(224*(10-target.frame)*0.1);
|
|
args[LIGHT_BLUE] = int(128*(10-target.frame)*0.1);
|
|
}
|
|
}
|
|
|
|
Class ChunkTrail : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Radius 0.1;
|
|
Height 0;
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+DONTSPLASH;
|
|
+FORCEXYBILLBOARD;
|
|
+NOTELEPORT;
|
|
Scale 0.2;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
let l = Spawn("ChunkLight",pos);
|
|
l.target = self;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( isFrozen() ) return;
|
|
if ( InStateSequence(CurState,FindState("Death")) ) return;
|
|
if ( !target )
|
|
{
|
|
int dist = FindState("Spawn").DistanceTo(CurState);
|
|
SetState(FindState("Death")+dist);
|
|
return;
|
|
}
|
|
SetOrigin(target.pos+(0,0,speed),true);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
FGLO ABCDEFGHIJK 3 Bright;
|
|
Stop;
|
|
Death:
|
|
FGLO ABCDEFGHIJK 1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class FlakAccumulator : Thinker
|
|
{
|
|
Actor victim;
|
|
int amount;
|
|
int cnt;
|
|
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
cnt++;
|
|
if ( cnt < 5 ) return;
|
|
Destroy();
|
|
}
|
|
|
|
static void Accumulate( Actor victim, int amount )
|
|
{
|
|
let ti = ThinkerIterator.Create("FlakAccumulator",STAT_USER);
|
|
FlakAccumulator a, match = null;
|
|
while ( a = FlakAccumulator(ti.Next()) )
|
|
{
|
|
if ( a.victim != victim ) continue;
|
|
match = a;
|
|
break;
|
|
}
|
|
if ( !match )
|
|
{
|
|
match = new("FlakAccumulator");
|
|
match.ChangeStatNum(STAT_USER);
|
|
match.victim = victim;
|
|
}
|
|
match.cnt = 0;
|
|
match.amount += amount;
|
|
}
|
|
|
|
static int GetAmount( Actor victim )
|
|
{
|
|
let ti = ThinkerIterator.Create("FlakAccumulator",STAT_USER);
|
|
FlakAccumulator a;
|
|
while ( a = FlakAccumulator(ti.Next()) )
|
|
{
|
|
if ( a.victim != victim ) continue;
|
|
return a.amount;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Class FlakChunk : Actor
|
|
{
|
|
ChunkTrail trail;
|
|
double rollvel, pitchvel, yawvel;
|
|
double lifetime, lifespeed;
|
|
int lifetics;
|
|
Vector3 oldvel;
|
|
Default
|
|
{
|
|
Obituary "$O_FLAKCANNON";
|
|
Radius 2;
|
|
Height 2;
|
|
Speed 32;
|
|
DamageFunction 16;
|
|
DamageType 'Shredded';
|
|
BounceType "Hexen";
|
|
BounceFactor 1.0;
|
|
WallBounceFactor 1.0;
|
|
PROJECTILE;
|
|
+USEBOUNCESTATE;
|
|
+CANBOUNCEWATER;
|
|
+SKYEXPLODE;
|
|
+INTERPOLATEANGLES;
|
|
+HITTRACER;
|
|
+DONTBOUNCEONSHOOTABLES;
|
|
Scale 0.3;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
lifetime = 0;
|
|
lifespeed = FRandom[Flak](0.004,0.008);
|
|
trail = ChunkTrail(Spawn("ChunkTrail",pos));
|
|
trail.target = self;
|
|
trail.speed = 1.2;
|
|
rollvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1);
|
|
pitchvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1);
|
|
yawvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1);
|
|
scale *= Frandom[Flak](0.8,1.2);
|
|
SetState(ResolveState("Spawn")+Random[Flak](0,3));
|
|
}
|
|
override void Tick()
|
|
{
|
|
oldvel = vel;
|
|
Super.Tick();
|
|
if ( isFrozen() ) return;
|
|
if ( waterlevel > 0 )
|
|
{
|
|
vel.xy *= 0.98;
|
|
rollvel *= 0.98;
|
|
pitchvel *= 0.98;
|
|
yawvel *= 0.98;
|
|
if ( trail ) trail.Destroy();
|
|
}
|
|
lifetics++;
|
|
if ( lifetics > 3 )
|
|
{
|
|
lifetics = 0;
|
|
if ( frame < 11 ) frame++;
|
|
}
|
|
lifetime += lifespeed;
|
|
if ( (waterlevel <= 0) && (frame < 10) && !(lifetics%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/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 ( trail ) trail.alpha = max(0,11-frame)/11.;
|
|
if ( InStateSequence(CurState,FindState("Death")) ) return;
|
|
roll += rollvel;
|
|
pitch += pitchvel;
|
|
angle += pitchvel;
|
|
}
|
|
void A_HandleBounce()
|
|
{
|
|
// chunks in vanilla have a special variation on the standard reflect formula that causes them to bounce differently when hitting a surface head-on
|
|
// (0.5 to 0.8 reduction perpendicular to the surface normal, to be specific)
|
|
Vector3 HitNormal = -vel.unit();
|
|
if ( BlockingFloor ) HitNormal = BlockingFloor.floorplane.Normal;
|
|
else if ( BlockingCeiling ) HitNormal = BlockingCeiling.ceilingplane.Normal;
|
|
else if ( BlockingLine )
|
|
{
|
|
HitNormal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit();
|
|
if ( !BlockingLine.sidedef[1] || (CurSector == BlockingLine.frontsector) )
|
|
HitNormal *= -1;
|
|
}
|
|
else if ( BlockingMobj )
|
|
{
|
|
Vector3 diff = level.Vec3Diff(pos,BlockingMobj.pos);
|
|
if ( (pos.x+radius) <= (BlockingMobj.pos.x-BlockingMobj.radius) )
|
|
HitNormal = (-1,0,0);
|
|
else if ( (pos.x-radius) >= (BlockingMobj.pos.x+BlockingMobj.radius) )
|
|
HitNormal = (1,0,0);
|
|
else if ( (pos.y+radius) <= (BlockingMobj.pos.y-BlockingMobj.radius) )
|
|
HitNormal = (0,-1,0);
|
|
else if ( (pos.y-radius) >= (BlockingMobj.pos.y+BlockingMobj.radius) )
|
|
HitNormal = (0,1,0);
|
|
else if ( pos.z >= (BlockingMobj.pos.z+BlockingMobj.height) )
|
|
HitNormal = (0,0,1);
|
|
else if ( (pos.z+height) <= BlockingMobj.pos.z )
|
|
HitNormal = (0,0,-1);
|
|
}
|
|
// undo the bounce, we need to hook in our own
|
|
vel = oldvel;
|
|
// re-do the bounce with our formula
|
|
vel = 0.8*((vel dot HitNormal)*HitNormal*(-1.8+FRandom[Flak](0.0,0.8))+vel);
|
|
bHITOWNER = true;
|
|
int numpt = Random[Flak](2,3);
|
|
if ( (frame < 10) && Random[Flak](0,1) )
|
|
{
|
|
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,4);
|
|
let s = Spawn("UTSpark",pos);
|
|
s.vel = pvel;
|
|
}
|
|
}
|
|
else A_SprayDecal("WallCrack",-8);
|
|
A_Gravity();
|
|
gravity = 0.35;
|
|
rollvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed);
|
|
pitchvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed);
|
|
yawvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed);
|
|
A_PlaySound("flak/bounce",volume:0.3);
|
|
A_AlertMonsters();
|
|
if ( vel.length() < 5.0 ) ExplodeMissile();
|
|
}
|
|
override int DoSpecialDamage( Actor target, int damage, Name damagetype )
|
|
{
|
|
if ( vel.length() <= 5.0 ) return -1;
|
|
FlakAccumulator.Accumulate(target,damage);
|
|
int gibhealth = (target.GibHealth==int.min)?-target.SpawnHealth():target.GibHealth;
|
|
int calcdmg = FlakAccumulator.GetAmount(target);
|
|
if ( target.Health-calcdmg <= (gibhealth/2) ) bEXTREMEDEATH = true;
|
|
if ( !target.bNOBLOOD )
|
|
{
|
|
target.SpawnBlood(pos,AngleTo(target),damage);
|
|
A_PlaySound("flak/meat",volume:0.3);
|
|
A_AlertMonsters();
|
|
}
|
|
return damage;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
FCH1 A 0;
|
|
Goto Idle;
|
|
FCH2 A 0;
|
|
Goto Idle;
|
|
FCH3 A 0;
|
|
Goto Idle;
|
|
FCH4 A 0;
|
|
Goto Idle;
|
|
Idle:
|
|
#### # -1;
|
|
Stop;
|
|
Bounce:
|
|
#### # 0 A_HandleBounce();
|
|
Goto Idle;
|
|
Death:
|
|
#### # 0
|
|
{
|
|
bMOVEWITHSECTOR = true;
|
|
A_SetTics(Random[Flak](30,50));
|
|
}
|
|
#### # 1
|
|
{
|
|
A_SetScale(scale.x-0.002);
|
|
if ( scale.x <= 0.0 ) Destroy();
|
|
}
|
|
Wait;
|
|
Crash:
|
|
TNT1 A 0
|
|
{
|
|
let l = Spawn("BulletImpact",pos);
|
|
Vector3 dir;
|
|
if ( tracer ) dir = level.Vec3Diff(pos,tracer.Vec3Offset(0,0,tracer.height/2)).unit();
|
|
else dir = vel.unit();
|
|
l.angle = atan2(dir.y,dir.x);
|
|
l.pitch = asin(-dir.z);
|
|
A_PlaySound("flak/hit",volume:0.3);
|
|
A_AlertMonsters();
|
|
}
|
|
XDeath:
|
|
TNT1 A 1;
|
|
Stop;
|
|
Dummy:
|
|
FCH1 ABCDEFGHIJKL -1;
|
|
FCH2 ABCDEFGHIJKL -1;
|
|
FCH3 ABCDEFGHIJKL -1;
|
|
FCH4 ABCDEFGHIJKL -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class SlugSmoke : Actor
|
|
{
|
|
double lifetime, lifespeed;
|
|
Default
|
|
{
|
|
Radius 0.1;
|
|
Height 0;
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+DONTSPLASH;
|
|
+NOTELEPORT;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
lifetime = 0;
|
|
lifespeed = FRandom[Flak](0.004,0.008);
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( isFrozen() ) return;
|
|
lifetime += lifespeed;
|
|
let s = Spawn("UTSmoke",pos);
|
|
s.vel = (FRandom[Flak](-0.5,0.5),FRandom[Flak](-0.5,0.5),FRandom[Flak](-0.5,0.5));
|
|
s.vel.z += 2.;
|
|
s.alpha = scale.x;
|
|
s.SetShade("AAAAAA");
|
|
scale.x = max(0,1-lifetime);
|
|
if ( scale.x <= 0 ) Destroy();
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class SlugLight : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
Args 0,0,0,80;
|
|
ReactionTime 20;
|
|
}
|
|
}
|
|
|
|
Class FlakSlug : Actor
|
|
{
|
|
Default
|
|
{
|
|
Obituary "$O_FLAKCANNON";
|
|
DamageType 'FlakDeath';
|
|
Radius 2;
|
|
Height 2;
|
|
Gravity 0.35;
|
|
Speed 20;
|
|
PROJECTILE;
|
|
-NOGRAVITY;
|
|
+SKYEXPLODE;
|
|
+EXPLODEONWATER;
|
|
+HITTRACER;
|
|
+FORCERADIUSDMG;
|
|
+NODAMAGETHRUST;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
vel.z += 3;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( waterlevel > 0 ) vel.xy *= 0.98;
|
|
}
|
|
action void A_FlakExplode()
|
|
{
|
|
bForceXYBillboard = true;
|
|
A_SetRenderStyle(1.0,STYLE_Add);
|
|
A_SprayDecal("RocketBlast",50);
|
|
A_NoGravity();
|
|
A_SetScale(1.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("FlakChunk",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
|
|
{
|
|
Spawn:
|
|
FSLG A 1
|
|
{
|
|
for ( int i=0; i<6; i++ )
|
|
{
|
|
let s = Spawn("UTSmoke",pos);
|
|
s.vel = (FRandom[Flak](-0.5,0.5),FRandom[Flak](-0.5,0.5),FRandom[Flak](-0.5,0.5));
|
|
s.alpha = 0.5;
|
|
s.SetShade("AAAAAA");
|
|
}
|
|
}
|
|
Wait;
|
|
Death:
|
|
EXP2 A 0 A_FlakExplode();
|
|
EXP2 ABCDEFGHIJKLMNOPQR 1 BRIGHT;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class FlakLight : DynamicLight
|
|
{
|
|
int cnt;
|
|
Default
|
|
{
|
|
DynamicLight.Type "Point";
|
|
args 255,224,128,150;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
if ( target.player ) SetOrigin(target.Vec3Offset(0,0,target.player.viewz-target.pos.z),true);
|
|
else SetOrigin(target.pos,true);
|
|
if ( cnt++ > 2 ) Destroy();
|
|
}
|
|
}
|
|
|
|
Class FlakCannon : UTWeapon
|
|
{
|
|
action void A_Loading( bool first = false )
|
|
{
|
|
if ( first ) A_PlaySound("flak/load",CHAN_WEAPON);
|
|
else A_PlaySound("flak/reload",CHAN_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);
|
|
invoker.FireEffect();
|
|
UTMainHandler.DoFlash(self,Color(160,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);
|
|
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+4.0*y-3.0*z;
|
|
A_Overlay(-2,"MuzzleFlash");
|
|
A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
|
|
A_OverlayRenderstyle(-2,STYLE_Add);
|
|
[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("FlakChunk",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,2,-3);
|
|
UTViewSpark(s).vvel = (FRandom[Flak](3,12),FRandom[Flak](-4,4),FRandom[Flak](-4,4));
|
|
s.target = self;
|
|
}
|
|
for ( int i=0; i<12; i++ )
|
|
{
|
|
let s = Spawn("UTViewSmoke",origin);
|
|
UTViewSmoke(s).ofs = (10,2,-3);
|
|
UTViewSmoke(s).vvel = (FRandom[Flak](0,1.2),FRandom[Flak](-.4,.4),FRandom[Flak](-.4,.4));
|
|
s.target = self;
|
|
s.scale *= 2.4;
|
|
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);
|
|
invoker.FireEffect();
|
|
UTMainHandler.DoFlash(self,Color(128,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);
|
|
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+2.0*y-3.0*z;
|
|
A_Overlay(-2,"MuzzleFlash");
|
|
A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
|
|
A_OverlayRenderstyle(-2,STYLE_Add);
|
|
Actor p = Spawn("FlakSlug",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,2,-3);
|
|
UTViewSpark(s).vvel = (FRandom[Flak](3,12),FRandom[Flak](-4,4),FRandom[Flak](-4,4));
|
|
s.target = self;
|
|
}
|
|
for ( int i=0; i<16; i++ )
|
|
{
|
|
let s = Spawn("UTViewSmoke",origin);
|
|
UTViewSmoke(s).ofs = (10,2,-3);
|
|
UTViewSmoke(s).vvel = (FRandom[Flak](0,1.2),FRandom[Flak](-.8,.8),FRandom[Flak](-.8,.8));
|
|
s.target = self;
|
|
s.scale *= 2.4;
|
|
s.alpha *= 0.5;
|
|
}
|
|
}
|
|
|
|
Default
|
|
{
|
|
Tag "$T_FLAKCANNON";
|
|
Inventory.PickupMessage "$I_FLAKCANNON";
|
|
Weapon.UpSound "flak/select";
|
|
Weapon.SlotNumber 8;
|
|
Weapon.SelectionOrder 2;
|
|
Weapon.AmmoType "FlakAmmo";
|
|
Weapon.AmmoUse 1;
|
|
Weapon.AmmoType2 "FlakAmmo";
|
|
Weapon.AmmoUse2 1;
|
|
Weapon.AmmoGive 10;
|
|
UTWeapon.DropAmmo 5;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
FPCK A -1;
|
|
Stop;
|
|
FPCK B -1;
|
|
Stop;
|
|
Ready:
|
|
FLKS ABDEGHJKMNPQSTVWYZ 1 A_WeaponReady(WRF_NOFIRE);
|
|
FKS2 BC 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;
|
|
Idle:
|
|
FLKI A 1 A_WeaponReady();
|
|
Wait;
|
|
Fire:
|
|
FLKF A 1 A_FireChunks();
|
|
FLKF BCDEFGHI 1;
|
|
FLKF J 4;
|
|
Goto Loading;
|
|
AltFire:
|
|
FLKA A 1 A_FireSlug();
|
|
FLKA BCDEFGHIJK 2;
|
|
FLKA K 4;
|
|
Goto Loading;
|
|
Select:
|
|
FLKS A 1 A_Raise(int.max);
|
|
Wait;
|
|
Deselect:
|
|
FLKD ABCDEFGHIJ 1;
|
|
FLKD J 1 A_Lower(int.max);
|
|
Wait;
|
|
MuzzleFlash:
|
|
FMUZ A 3 Bright
|
|
{
|
|
let l = Spawn("FlakLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
}
|
|
}
|