- moved all WorldTour actors to a subfolder and consolidated the flamethrower actors in a single file.

This commit is contained in:
Christoph Oelckers 2022-12-31 12:28:23 +01:00
parent e27dc51133
commit 01c6db7b5b
11 changed files with 661 additions and 575 deletions

View file

@ -60,23 +60,14 @@ version "4.10"
#include "zscript/games/duke/actors/genericdestructible.zs"
#include "zscript/games/duke/actors/_placeholders.zs"
#include "zscript/games/duke/actors/projectiles.zs"
#include "zscript/games/duke/actors/recon.zs"
#include "zscript/games/duke/actors/greenslime.zs"
#include "zscript/games/duke/actors/burning.zs"
#include "zscript/games/duke/actors/dukedecos.zs"
#include "zscript/games/duke/actors/player.zs"
#include "zscript/games/duke/actors/dukeitems.zs"
#include "zscript/games/duke/actors/batteryammo.zs"
#include "zscript/games/duke/actors/sixpak.zs"
#include "zscript/games/duke/actors/atomichealth.zs"
#include "zscript/games/duke/actors/boss5.zs"
#include "zscript/games/duke/actors/flamethrowerflame.zs"
#include "zscript/games/duke/actors/firefly.zs"
#include "zscript/games/duke/actors/lavapool.zs"
#include "zscript/games/duke/actors/powderkeg.zs"
#include "zscript/games/duke/actors/redneckmisc.zs"
@ -165,6 +156,10 @@ version "4.10"
#include "zscript/games/duke/actors/dukeweapons/shrinker.zs"
#include "zscript/games/duke/actors/dukeweapons/tripbomb.zs"
#include "zscript/games/duke/actors/worldtour/boss5.zs"
#include "zscript/games/duke/actors/worldtour/firefly.zs"
#include "zscript/games/duke/actors/worldtour/flamethrower.zs"
#include "zscript/games/duke/actors/redneckcstuff/airplane.zs"
#include "zscript/games/duke/actors/redneckcstuff/balloons.zs"
#include "zscript/games/duke/actors/redneckcstuff/bowling.zs"

View file

@ -1,28 +0,0 @@
class DukeBoss5 : DukeBoss1
{
default
{
pic "BOSS5";
-ALTHITSCANDIRECTION;
-DONTENTERWATER;
}
}
class DukeBoss5Stayput : DukeBoss5
{
default
{
pic "BOSS5STAYPUT";
}
override void initialize()
{
super.initialize();
self.actorstayput = self.sector; // make this a flag once everything has been exported.
}
}

View file

@ -1,39 +0,0 @@
class DukeOnFire : DukeActor
{
default
{
pic "FLOORFLAME";
+FORCERUNCON;
}
override void Initialize()
{
if (!self.mapspawned)
{
self.Angle = self.ownerActor.Angle;
self.shade = -64;
self.cstat = randomXFlip();
double c, f;
[c, f] = self.sector.getSlopes(self.pos.XY);
if (self.pos.Z > f - 12)
self.pos.Z = f - 12;
}
self.pos.X += frandom(-16, 16);
self.pos.Y += frandom(-16, 16);
self.pos.Z -= frandom(0, 40);
self.cstat |= CSTAT_SPRITE_YCENTER;
self.scale = (0.375, 0.375);
self.ChangeStat(STAT_MISC);
}
}
class DukeOnFireSmoke : DukeActor
{
default
{
pic "ONFIRESMOKE";
+FORCERUNCON;
}
}

View file

@ -1,43 +0,0 @@
class DukeLavaBubble : DukeActor // (4340)
{
default
{
pic "LAVABUBBLE";
}
}
class DukeBurnedCorpse : DukeActor
{
default
{
pic "BURNEDCORPSE";
+FORCERUNCON;
}
}
class DukeWhispySmoke : DukeActor
{
default
{
pic "WHISPYSMOKE";
+FORCERUNCON;
}
override void Initialize()
{
self.pos.X += frandom(-8, 8);
self.pos.Y += frandom(-8, 8);
self.scale = (0.3125, 0.3125);
self.ChangeStat(STAT_MISC);
}
}
class DukeLavaSplash : DukeActor
{
default
{
pic "LAVASPLASH";
}
}

View file

@ -1,18 +0,0 @@
class DukeFlamethrowerSprite : DukeItemBase
{
default
{
pic "FLAMETHROWERSPRITE";
}
}
class DukeFlamethrowerAmmo : DukeItemBase
{
default
{
pic "FLAMETHROWERAMMO";
}
}

View file

@ -1,197 +0,0 @@
class DukeFlamethrowerFlame : DukeActor
{
default
{
pic "FLAMETHROWERFLAME";
+HITRADIUS_DONTHURTSPECIES;
}
override void Tick()
{
let sectp = self.sector;
double xx;
Super.Tick(); // Run CON or its replacement.
if (self.bDestroyed) return; // killed by script.
self.counter++;
if (sectp.lotag == ST_2_UNDERWATER)
{
let spawned = self.spawn("DukeExplosion2");
if (spawned) spawned.shade = 127;
self.Destroy();
return;
}
let dapos = self.pos;
self.getglobalz();
int ds = self.counter / 6;
if (self.scale.X < 0.1250)
{
self.scale.X += (ds * REPEAT_SCALE);
self.scale.Y = (self.scale.X);
}
self.clipdist += ds * 0.25;
if (self.counter <= 2)
self.temp_data[3] = random(0, 9);
if (self.counter > 30)
{
let spawned = self.spawn("DukeExplosion2");
if (spawned) spawned.shade = 127;
self.Destroy();
return;
}
CollisionData coll;
self.movesprite_ex((self.angle.ToVector() * self.vel.X, self.vel.Z), CLIPMASK1, coll);
if (self.sector == null)
{
self.Destroy();
return;
}
if (coll.type != kHitSprite)
{
if (self.pos.Z < self.ceilingz)
{
coll.setSector(self.sector);
self.vel.Z -= 1/256.;
}
else if ((self.pos.Z > self.floorz && self.sector.lotag != ST_1_ABOVE_WATER)
|| (self.pos.Z > self.floorz + 16 && self.sector.lotag == ST_1_ABOVE_WATER))
{
coll.setSector(self.sector);
if (self.sector.lotag != 1)
self.vel.Z += 1/256.;
}
}
if (coll.type != 0)
{
self.vel.XY = (0, 0);
self.vel.Z = 0;
if (coll.type == kHitSprite)
{
let hitact = DukeActor(coll.hitActor());
hitact.OnHit(self);
if (hitact.isPlayer())
hitact.PlayActorSound("PISTOL_BODYHIT");
}
else if (coll.type == kHitWall)
{
self.SetPosition(dapos);
dlevel.checkhitwall(coll.hitWall(), self, self.pos);
}
else if (coll.type == kHitSector)
{
self.SetPosition(dapos);
if (self.vel.Z < 0)
dlevel.checkhitceiling(self.sector, self);
}
if (self.scale.X >= 0.15625)
{
int x = self.extra;
self.hitradius(gs.rpgblastradius, x >> 2, x >> 1, x - (x >> 2), x);
}
else
{
int x = self.extra + (Duke.global_random() & 3);
self.hitradius((gs.rpgblastradius >> 1), x >> 2, x >> 1, x - (x >> 2), x);
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
override bool shootthis(DukeActor actor, DukePlayer p, Vector3 spos, double sang) const
{
double vel, zvel = 0;
if (actor.extra >= 0)
actor.shade = -96;
vel = 25;
DukeActor spawned = nullptr;
if (p == null)
{
double x;
DukePlayer j;
[j, x] = actor.findplayer();
sang = (j.Actor.opos.XY - spos.XY).Angle();
if (actor is 'DukeBoss5')
{
vel = 33;
spos.Z += 24;
}
else if (actor is 'DukeBoss3')
spos.Z -= 32;
double dist = (j.actor.pos.XY - actor.pos.XY).Length();
if (dist != 0)
zvel = (((j.actor.opos.Z + j.actor.oviewzoffset - spos.Z) * vel) / dist);
if (actor.badguy() && (actor.hitag & face_player_smart) != 0)
sang = actor.Angle + Raze.BAngToDegree * random(-16, 15);
}
else
{
[vel, zvel] = Raze.setFreeAimVelocity(vel, zvel, p.getPitchWithView(), 40.5);
// WTF???
double myang = 90. - (180. - abs(abs((spos.XY - p.actor.pos.XY).Angle() - sang) - 180.));
if (p.actor.vel.X != 0)
vel = ((myang / 90.) * p.actor.vel.X) + 25;
}
if (actor.sector.lotag == ST_2_UNDERWATER && (random(0, 4)) == 0)
spawned = actor.spawn("DukeWaterBubble");
if (spawned == nullptr)
{
spawned = actor.spawn("DukeFlamethrowerFlame");
if (!spawned) return true;
spawned.vel.X = vel;
spawned.vel.Z = zvel;
}
Vector3 offset;
offset.X = cos(sang + Raze.BAngToDegree * 118) * (1024 / 448.); // Yes, these angles are really different!
offset.Y = sin(sang + Raze.BAngToDegree * 112) * (1024 / 448.);
offset.Z = -1;
spawned.pos = spos + offset;
spawned.pos.Z--;
spawned.sector = actor.sector;
spawned.cstat = CSTAT_SPRITE_YCENTER;
spawned.Angle = sang;
spawned.scale = (0.03125, 0.03125);
spawned.clipdist = 10;
spawned.yint = Duke.GetPlayerIndex(p);
spawned.ownerActor = actor;
if (p == null)
{
if (actor is 'DukeBoss5')
{
spawned.pos += sang.ToVector() * (128. / 7);
spawned.scale = (0.15625, 0.15625);
}
}
return true;
}
override class<DukeActor> GetRadiusDamageType(int targhealth)
{
return 'DukeFlamethrowerFlame';
}
}

View file

@ -1,63 +0,0 @@
class DukeLavaPool : DukeActor
{
default
{
pic "LAVAPOOL";
+FORCERUNCON;
+HITRADIUS_NODAMAGE;
}
override void Initialize()
{
bool away = self.isAwayFromWall(6.75);
if (!away)
{
self.ChangeStat(STAT_MISC);
self.scale = (0, 0);
return;
}
if (self.sector.lotag == 1)
{
return;
}
self.cstat |= CSTAT_SPRITE_ALIGNMENT_FLOOR;
double c, f;
[c, f] = self.sector.getslopes(self.pos.XY);
self.pos.Z = f - 0.78125;
if (self != self.ownerActor)
self.scale = (REPEAT_SCALE, REPEAT_SCALE);
self.ChangeStat(STAT_MISC);
}
override class<DukeActor> GetRadiusDamageType(int targhealth)
{
return 'DukeFlamethrowerFlame';
}
}
class DukeLavaPoolBubble : DukeActor
{
default
{
pic "LAVAPOOLBUBBLE";
+FORCERUNCON;
}
override void Initialize()
{
let owner = self.ownerActor;
self.ChangeStat(STAT_MISC);
if (owner.scale.X < 0.46875)
{
self.scale = (0, 0);
return;
}
self.pos.X += frandom(-16, 16);
self.pos.Y += frandom(-16, 16);
self.scale = (0.25, 0.25);
}
}

View file

@ -1,173 +0,0 @@
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeFireball : DukeProjectile // WorldTour only
{
default
{
pic "FIREBALL";
+FULLBRIGHT;
}
override bool ShootThis(DukeActor actor, DukePlayer p, Vector3 pos, double ang) const
{
// World Tour's values for angles and velocities are quite arbitrary...
double vel, zvel;
if (actor.extra >= 0)
actor.shade = -96;
pos.Z -= 2;
if (!(actor is 'DukeBoss5'))
vel = 840/16.;
else {
vel = 968/16.;
pos.Z += 24;
}
if (p == null)
{
ang += 22.5 / 8 - frandom(0, 22.5 / 4);
let j = actor.findplayer();
double dist = (j.actor.pos.XY - actor.pos.XY).Length();
zvel = ((j.actor.opos.z + j.actor.oviewzoffset - pos.Z + 3) * vel) / dist;
}
else
{
[vel, zvel] = Raze.setFreeAimVelocity(vel, zvel, p.getPitchWithView(), 49.);
pos += (ang + 61.171875).ToVector() * (1024. / 448.);
pos.Z += 3;
}
double scale = 0.28125;
let spawned = dlevel.SpawnActor(actor.sector, pos, GetClass(), -127, (0.28125, 0.28125), ang, vel, zvel, actor, STAT_PROJECTILE);
if (spawned)
{
spawned.extra += random(0, 7);
if ((actor is 'DukeBoss5') || p)
{
spawned.scale = (0.625, 0.625);
}
//spawned.yint = p;
spawned.cstat = CSTAT_SPRITE_YCENTER;
spawned.clipdist = 1;
}
return true;
}
override bool premoveeffect()
{
let Owner = self.ownerActor;
if (self.sector.lotag == 2)
{
self.Destroy();
return true;
}
if (self.detail != 1)
{
if (self.counter >= 1 && self.counter < 6)
{
double siz = 1.0 - (self.counter * 0.2);
DukeActor trail = self.temp_actor;
let ball = self.spawn('DukeFireball');
if (ball)
{
self.temp_actor = ball;
ball.vel.X = self.vel.X;
ball.vel.Z = self.vel.Z;
ball.angle = self.angle;
if (self.counter > 1)
{
if (trail)
{
ball.pos = trail.temp_pos;
ball.vel = trail.temp_pos2;
}
}
double scale = self.scale.X * siz;
ball.scale = (scale, scale);
ball.cstat = self.cstat;
ball.extra = 0;
ball.temp_pos = ball.pos;
ball.temp_pos2 = ball.vel;
ball.detail = 1;
ball.ChangeStat(STAT_PROJECTILE);
}
}
self.counter++;
}
if (self.vel.Z < 15000. / 256.)
self.vel.Z += 200 / 256.;
return false;
}
override bool weaponhitsprite_pre(DukeActor targ)
{
if (self.detail != 1)
return super.weaponhitsprite_pre(targ);
return false;
}
override bool weaponhitplayer(DukeActor targ)
{
let p = targ.GetPlayer();
let Owner = self.ownerActor;
if (p && ud.multimode >= 2 && Owner && Owner.isPlayer())
{
p.numloogs = -1 - self.yint;
}
return Super.weaponhitplayer(targ);
}
override bool weaponhitsector()
{
if (super.weaponhitsector()) return true;
if (self.detail != 1)
{
let spawned = self.spawn('DukeLavapool');
if (spawned)
{
spawned.ownerActor = self;
spawned.hitOwnerActor = self;
spawned.yint = self.yint;
}
self.Destroy();
return true;
}
return false;
}
override void posthiteffect(CollisionData coll)
{
if (self.detail != 1)
{
let spawned = self.spawn('DukeExplosion2');
if (spawned)
{
let scale = self.scale.X * 0.5;
spawned.scale = (scale,scale);
}
}
Super.postHitEffect(coll);
}
override class<DukeActor> GetRadiusDamageType(int targhealth)
{
if (self.detail == 0) return 'DukeFlamethrowerFlame';
return 'DukeRadiusExplosion';
}
}

View file

@ -0,0 +1,24 @@
class DukeBoss5 : DukeBossBase
{
const BOSS5STRENGTH = 6000;
const BOSS5PALSTRENGTH = 1000;
default
{
pic "BOSS5";
-ALTHITSCANDIRECTION;
Strength BOSS5STRENGTH;
}
}
class DukeBoss5Stayput : DukeBoss5
{
default
{
pic "BOSS5STAYPUT";
+BADGUYSTAYPUT;
}
}

View file

@ -4,18 +4,19 @@ class DukeFireflyShrinkEffect : DukeActor
default
{
pic "FIREFLYSHRINKEFFECT";
Strength 0;
}
}
class DukeFireflyGrowEffect : DukeActor
{
default
{
pic "FIREFLYGROWEFFECT";
Strength 0;
}
}
class DukeFireflyFlyingEffect : DukeActor
@ -24,6 +25,7 @@ class DukeFireflyFlyingEffect : DukeActor
{
pic "FIREFLYFLYINGEFFECT";
+FORCERUNCON;
Strength 0;
}
override void Initialize()
@ -32,6 +34,12 @@ class DukeFireflyFlyingEffect : DukeActor
self.ChangeStat(STAT_MISC);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
override void Tick()
{
Super.Tick();
@ -64,13 +72,22 @@ class DukeFireflyFlyingEffect : DukeActor
}
}
class DukeFirefly : DukeActor
class DukeFirefly : DukeLizTrooper // recycles part of the Liztrooper code and data
{
const FF_STRENGTH = 50;
const FF_SIZEX = 48;
const FF_SIZEY = 40;
const FF_SHRUNKSIZEX = 12;
const FF_SHRUNKSIZEY = 10;
default
{
pic "FIREFLY";
+INTERNAL_BADGUY;
+KILLCOUNT;
-DONTENTERWATERONGROUND;
Strength FF_STRENGTH;
}
override bool ShootThis(DukeActor shooter, DukePlayer p, Vector3 spos, double sang) const
@ -86,6 +103,10 @@ class DukeFirefly : DukeActor
}
return true;
}
}
override void Initialize()
{
}
}

View file

@ -0,0 +1,607 @@
class DukeFlamethrowerFlame : DukeActor
{
const FLAMETHROWER_WEAPON_STRENGTH = 6;
default
{
pic "FLAMETHROWERFLAME";
+HITRADIUS_DONTHURTSPECIES;
Strength FLAMETHROWER_WEAPON_STRENGTH;
}
override void Tick()
{
Console.Printf("ticky");
let sectp = self.sector;
double xx;
Super.Tick(); // Run CON or its replacement.
if (self.bDestroyed) return; // killed by script.
self.counter++;
if (sectp.lotag == ST_2_UNDERWATER)
{
let spawned = self.spawn("DukeExplosion2");
if (spawned) spawned.shade = 127;
self.Destroy();
return;
}
let dapos = self.pos;
self.getglobalz();
int ds = self.counter / 6;
if (self.scale.X < 0.1250)
{
self.scale.X += (ds * REPEAT_SCALE);
self.scale.Y = (self.scale.X);
}
self.clipdist += ds * 0.25;
if (self.counter <= 2)
self.temp_data[3] = random(0, 9);
if (self.counter > 30)
{
let spawned = self.spawn("DukeExplosion2");
if (spawned) spawned.shade = 127;
self.Destroy();
return;
}
CollisionData coll;
self.movesprite_ex((self.angle.ToVector() * self.vel.X, self.vel.Z), CLIPMASK1, coll);
if (self.sector == null)
{
self.Destroy();
return;
}
if (coll.type != kHitSprite)
{
if (self.pos.Z < self.ceilingz)
{
coll.setSector(self.sector);
self.vel.Z -= 1/256.;
}
else if ((self.pos.Z > self.floorz && self.sector.lotag != ST_1_ABOVE_WATER)
|| (self.pos.Z > self.floorz + 16 && self.sector.lotag == ST_1_ABOVE_WATER))
{
coll.setSector(self.sector);
if (self.sector.lotag != 1)
self.vel.Z += 1/256.;
}
}
if (coll.type != 0)
{
self.vel.XY = (0, 0);
self.vel.Z = 0;
if (coll.type == kHitSprite)
{
let hitact = DukeActor(coll.hitActor());
hitact.OnHit(self);
if (hitact.isPlayer())
hitact.PlayActorSound("PISTOL_BODYHIT");
}
else if (coll.type == kHitWall)
{
self.SetPosition(dapos);
dlevel.checkhitwall(coll.hitWall(), self, self.pos);
}
else if (coll.type == kHitSector)
{
self.SetPosition(dapos);
if (self.vel.Z < 0)
dlevel.checkhitceiling(self.sector, self);
}
if (self.scale.X >= 0.15625)
{
int x = self.extra;
self.hitradius(gs.rpgblastradius, x >> 2, x >> 1, x - (x >> 2), x);
}
else
{
int x = self.extra + (Duke.global_random() & 3);
self.hitradius((gs.rpgblastradius >> 1), x >> 2, x >> 1, x - (x >> 2), x);
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
override bool shootthis(DukeActor actor, DukePlayer p, Vector3 spos, double sang) const
{
double vel, zvel = 0;
if (actor.extra >= 0)
actor.shade = -96;
vel = 25;
DukeActor spawned = nullptr;
if (p == null)
{
double x;
DukePlayer j;
[j, x] = actor.findplayer();
sang = (j.Actor.opos.XY - spos.XY).Angle();
if (actor is 'DukeBoss5')
{
vel = 33;
spos.Z += 24;
}
else if (actor is 'DukeBoss3')
spos.Z -= 32;
double dist = (j.actor.pos.XY - actor.pos.XY).Length();
if (dist != 0)
zvel = (((j.actor.opos.Z + j.actor.oviewzoffset - spos.Z) * vel) / dist);
if (actor.badguy() && (actor.hitag & face_player_smart) != 0)
sang = actor.Angle + Raze.BAngToDegree * random(-16, 15);
}
else
{
[vel, zvel] = Raze.setFreeAimVelocity(vel, zvel, p.getPitchWithView(), 40.5);
// WTF???
double myang = 90. - (180. - abs(abs((spos.XY - p.actor.pos.XY).Angle() - sang) - 180.));
if (p.actor.vel.X != 0)
vel = ((myang / 90.) * p.actor.vel.X) + 25;
}
if (actor.sector.lotag == ST_2_UNDERWATER && (random(0, 4)) == 0)
spawned = actor.spawn("DukeWaterBubble");
if (spawned == nullptr)
{
spawned = actor.spawn("DukeFlamethrowerFlame");
if (!spawned) return true;
spawned.vel.X = vel;
spawned.vel.Z = zvel;
}
Vector3 offset;
offset.X = cos(sang + Raze.BAngToDegree * 118) * (1024 / 448.); // Yes, these angles are really different!
offset.Y = sin(sang + Raze.BAngToDegree * 112) * (1024 / 448.);
offset.Z = -1;
spawned.pos = spos + offset;
spawned.pos.Z--;
spawned.sector = actor.sector;
spawned.cstat = CSTAT_SPRITE_YCENTER;
spawned.Angle = sang;
spawned.scale = (0.03125, 0.03125);
spawned.clipdist = 10;
spawned.yint = Duke.GetPlayerIndex(p);
spawned.ownerActor = actor;
if (p == null)
{
if (actor is 'DukeBoss5')
{
spawned.pos += sang.ToVector() * (128. / 7);
spawned.scale = (0.15625, 0.15625);
}
}
return true;
}
override class<DukeActor> GetRadiusDamageType(int targhealth)
{
return 'DukeFlamethrowerFlame';
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeLavaBubble : DukeActor // (4340)
{
default
{
pic "LAVABUBBLE";
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeFlamethrowerSprite : DukeItemBase
{
const FLAMETHROWERAMMOAMOUNT = 25;
default
{
pic "FLAMETHROWERSPRITE";
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeFlamethrowerAmmo : DukeItemBase
{
default
{
pic "FLAMETHROWERAMMO";
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeOnFireSmoke : DukeActor
{
default
{
pic "ONFIRESMOKE";
+FORCERUNCON;
Strength 1;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeOnFire : DukeActor
{
default
{
pic "FLOORFLAME";
+FORCERUNCON;
Strength 0;
}
override void Initialize()
{
if (!self.mapspawned)
{
self.Angle = self.ownerActor.Angle;
self.shade = -64;
self.cstat = randomXFlip();
double c, f;
[c, f] = self.sector.getSlopes(self.pos.XY);
if (self.pos.Z > f - 12)
self.pos.Z = f - 12;
}
self.pos.X += frandom(-16, 16);
self.pos.Y += frandom(-16, 16);
self.pos.Z -= frandom(0, 40);
self.cstat |= CSTAT_SPRITE_YCENTER;
self.scale = (0.375, 0.375);
self.ChangeStat(STAT_MISC);
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeBurnedCorpse : DukeActor
{
default
{
pic "BURNEDCORPSE";
+FORCERUNCON;
Strength 0;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeWhispySmoke : DukeActor
{
default
{
pic "WHISPYSMOKE";
+FORCERUNCON;
Strength 0;
}
override void Initialize()
{
self.pos.X += frandom(-8, 8);
self.pos.Y += frandom(-8, 8);
self.scale = (0.3125, 0.3125);
self.ChangeStat(STAT_MISC);
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeLavaSplash : DukeActor
{
default
{
pic "LAVASPLASH";
Strength 0;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeLavaPoolBubble : DukeActor
{
default
{
pic "LAVAPOOLBUBBLE";
statnum STAT_MISC;
+FORCERUNCON;
Strength 0;
}
override void Initialize()
{
let owner = self.ownerActor;
if (owner.scale.X < 0.46875)
{
self.scale = (0, 0);
return;
}
self.pos.X += frandom(-16, 16);
self.pos.Y += frandom(-16, 16);
self.scale = (0.25, 0.25);
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeLavaPool : DukeActor
{
default
{
pic "LAVAPOOL";
statnum STAT_MISC;
+FORCERUNCON;
+HITRADIUS_NODAMAGE;
Strength 0;
}
override void Initialize()
{
bool away = self.isAwayFromWall(6.75);
if (!away)
{
self.scale = (0, 0);
return;
}
if (self.sector.lotag == 1)
{
return;
}
self.cstat |= CSTAT_SPRITE_ALIGNMENT_FLOOR;
double c, f;
[c, f] = self.sector.getslopes(self.pos.XY);
self.pos.Z = f - 0.78125;
if (self != self.ownerActor)
self.scale = (REPEAT_SCALE, REPEAT_SCALE);
}
override class<DukeActor> GetRadiusDamageType(int targhealth)
{
return 'DukeFlamethrowerFlame';
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeFireball : DukeProjectile // WorldTour only
{
default
{
pic "FIREBALL";
+FULLBRIGHT;
}
override bool ShootThis(DukeActor actor, DukePlayer p, Vector3 pos, double ang) const
{
// World Tour's values for angles and velocities are quite arbitrary...
double vel, zvel;
if (actor.extra >= 0)
actor.shade = -96;
pos.Z -= 2;
if (!(actor is 'DukeBoss5'))
vel = 840/16.;
else {
vel = 968/16.;
pos.Z += 24;
}
if (p == null)
{
ang += 22.5 / 8 - frandom(0, 22.5 / 4);
let j = actor.findplayer();
double dist = (j.actor.pos.XY - actor.pos.XY).Length();
zvel = ((j.actor.opos.z + j.actor.oviewzoffset - pos.Z + 3) * vel) / dist;
}
else
{
[vel, zvel] = Raze.setFreeAimVelocity(vel, zvel, p.getPitchWithView(), 49.);
pos += (ang + 61.171875).ToVector() * (1024. / 448.);
pos.Z += 3;
}
double scale = 0.28125;
let spawned = dlevel.SpawnActor(actor.sector, pos, GetClass(), -127, (0.28125, 0.28125), ang, vel, zvel, actor, STAT_PROJECTILE);
if (spawned)
{
spawned.extra += random(0, 7);
if ((actor is 'DukeBoss5') || p)
{
spawned.scale = (0.625, 0.625);
}
//spawned.yint = p;
spawned.cstat = CSTAT_SPRITE_YCENTER;
spawned.clipdist = 1;
}
return true;
}
override bool premoveeffect()
{
let Owner = self.ownerActor;
if (self.sector.lotag == ST_2_UNDERWATER)
{
self.Destroy();
return true;
}
if (self.detail != 1)
{
if (self.counter >= 1 && self.counter < 6)
{
double siz = 1.0 - (self.counter * 0.2);
DukeActor trail = self.temp_actor;
let ball = self.spawn('DukeFireball');
if (ball)
{
self.temp_actor = ball;
ball.vel.X = self.vel.X;
ball.vel.Z = self.vel.Z;
ball.angle = self.angle;
if (self.counter > 1)
{
if (trail)
{
ball.pos = trail.temp_pos;
ball.vel = trail.temp_pos2;
}
}
double scale = self.scale.X * siz;
ball.scale = (scale, scale);
ball.cstat = self.cstat;
ball.extra = 0;
ball.temp_pos = ball.pos;
ball.temp_pos2 = ball.vel;
ball.detail = 1;
ball.ChangeStat(STAT_PROJECTILE);
}
}
self.counter++;
}
if (self.vel.Z < 15000. / 256.)
self.vel.Z += 200 / 256.;
return false;
}
override bool weaponhitsprite_pre(DukeActor targ)
{
if (self.detail != 1)
return super.weaponhitsprite_pre(targ);
return false;
}
override bool weaponhitplayer(DukeActor targ)
{
let p = targ.GetPlayer();
let Owner = self.ownerActor;
if (p && ud.multimode >= 2 && Owner && Owner.isPlayer())
{
p.numloogs = -1 - self.yint;
}
return Super.weaponhitplayer(targ);
}
override bool weaponhitsector()
{
if (super.weaponhitsector()) return true;
if (self.detail != 1)
{
let spawned = self.spawn('DukeLavapool');
if (spawned)
{
spawned.ownerActor = self;
spawned.hitOwnerActor = self;
spawned.yint = self.yint;
}
self.Destroy();
return true;
}
return false;
}
override void posthiteffect(CollisionData coll)
{
if (self.detail != 1)
{
let spawned = self.spawn('DukeExplosion2');
if (spawned)
{
let scale = self.scale.X * 0.5;
spawned.scale = (scale,scale);
}
}
Super.postHitEffect(coll);
}
override class<DukeActor> GetRadiusDamageType(int targhealth)
{
if (self.detail == 0) return 'DukeFlamethrowerFlame';
return 'DukeRadiusExplosion';
}
}