- scriptified World Tour's flamethrowerflame.

The first of 3 mixed native/CON items which are the last things remaining in the main thinker loops.
This commit is contained in:
Christoph Oelckers 2022-12-12 00:58:04 +01:00
parent dce0afe499
commit 9783b8c402
12 changed files with 244 additions and 224 deletions

View file

@ -822,6 +822,7 @@ DEFINE_FIELD_NAMED(DCoreActor, spr.Angles.Yaw, angle)
DEFINE_FIELD_NAMED(DCoreActor, spr.Angles.Pitch, pitch)
DEFINE_FIELD(DCoreActor, vel)
DEFINE_FIELD(DCoreActor, viewzoffset)
DEFINE_FIELD(DCoreActor, oviewzoffset)
DEFINE_FIELD(DCoreActor, opos)
void coreactor_setpos(DCoreActor* self, double x, double y, double z, int relink)

View file

@ -577,9 +577,11 @@ void tickstat(int stat, bool deleteinvalid)
if (actorflag(act, SFLAG2_DIENOW) || act->sector() == nullptr || (deleteinvalid && act->spr.scale.X == 0))
{
act->Destroy();
continue;
}
CallTick(act);
else if (stat != STAT_ACTOR || !badguy(act) || !monsterCheatCheck(act))
{
CallTick(act);
}
}
}

View file

@ -991,138 +991,6 @@ void movetransports_d(void)
//
//---------------------------------------------------------------------------
static void flamethrowerflame(DDukeActor *actor)
{
auto sectp = actor->sector();
double xx;
int p = findplayer(actor, &xx);
execute(actor, p, xx);
if (actor->ObjectFlags & OF_EuthanizeMe) return; // killed by script.
actor->temp_data[0]++;
if (sectp->lotag == 2)
{
spawn(actor, DTILE_EXPLOSION2)->spr.shade = 127;
actor->Destroy();
return;
}
auto dapos = actor->spr.pos;
getglobalz(actor);
int ds = actor->temp_data[0] / 6;
if (actor->spr.scale.X < 0.1250)
{
actor->spr.scale.X += (ds * REPEAT_SCALE);
actor->spr.scale.Y = (actor->spr.scale.X);
}
actor->clipdist += ds * 0.25;
if (actor->temp_data[0] <= 2)
actor->temp_data[3] = krand() % 10;
if (actor->temp_data[0] > 30)
{
spawn(actor, DTILE_EXPLOSION2)->spr.shade = 127;
actor->Destroy();
return;
}
Collision coll;
movesprite_ex(actor, DVector3(actor->spr.Angles.Yaw.ToVector() * actor->vel.X, actor->vel.Z), CLIPMASK1, coll);
if (!actor->insector())
{
actor->Destroy();
return;
}
if (coll.type != kHitSprite)
{
if (actor->spr.pos.Z < actor->ceilingz)
{
coll.setSector(actor->sector());
actor->vel.Z -= 1/256.;
}
else if ((actor->spr.pos.Z > actor->floorz && actor->sector()->lotag != 1)
|| (actor->spr.pos.Z > actor->floorz + 16 && actor->sector()->lotag == 1))
{
coll.setSector(actor->sector());
if (actor->sector()->lotag != 1)
actor->vel.Z += 1/256.;
}
}
if (coll.type != 0) {
actor->vel.XY().Zero();
actor->vel.Z = 0;
if (coll.type == kHitSprite)
{
fi.checkhitsprite(coll.actor(), actor);
if (coll.actor()->isPlayer())
S_PlayActorSound(PISTOL_BODYHIT, coll.actor());
}
else if (coll.type == kHitWall)
{
SetActor(actor, dapos);
checkhitwall(actor, coll.hitWall, actor->spr.pos);
}
else if (coll.type == kHitSector)
{
SetActor(actor, dapos);
if (actor->vel.Z < 0)
checkhitceiling(actor->sector());
}
if (actor->spr.scale.X >= 0.15625)
{
int x = actor->spr.extra;
fi.hitradius(actor, gs.rpgblastradius, x >> 2, x >> 1, x - (x >> 2), x);
}
else
{
int x = actor->spr.extra + (global_random & 3);
fi.hitradius(actor, (gs.rpgblastradius >> 1), x >> 2, x >> 1, x - (x >> 2), x);
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void moveactors_d(void)
{
DukeStatIterator it(STAT_ACTOR);
while (auto act = it.Next())
{
if (act->spr.scale.X == 0 || act->spr.sectp == nullptr || actorflag(act, SFLAG2_DIENOW))
{
act->Destroy();
}
else if (monsterCheatCheck(act) && badguy(act))
{
continue;
}
else if (isWorldTour() && act->spr.picnum == DTILE_FLAMETHROWERFLAME)
{
flamethrowerflame(act);
}
else
{
CallTick(act);
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void fireflyflyingeffect(DDukeActor *actor)
{
double xx;
@ -1745,7 +1613,7 @@ void think_d(void)
actortime.Reset();
actortime.Clock();
moveactors_d(); //ST 1
tickstat(STAT_ACTOR); //ST 1
actortime.Unclock();
moveeffectors_d(); //ST 3

View file

@ -140,91 +140,6 @@ static void shootfireball(DDukeActor *actor, int p, DVector3 pos, DAngle ang)
//
//---------------------------------------------------------------------------
static void shootflamethrowerflame(DDukeActor* actor, int p, DVector3 spos, DAngle sang)
{
double vel, zvel = 0;
if (actor->spr.extra >= 0)
actor->spr.shade = -96;
vel = 25;
DDukeActor* spawned = nullptr;
if (p < 0)
{
double x;
int j = findplayer(actor, &x);
sang = (ps[j].GetActor()->opos.XY() - spos.XY()).Angle();
if (actor->spr.picnum == DTILE_BOSS5)
{
vel = 33;
spos.Z += 24;
}
else if (actor->spr.picnum == DTILE_BOSS3)
spos.Z -= 32;
double dist = (ps[j].GetActor()->spr.pos.XY() - actor->spr.pos.XY()).Length();
if (dist != 0)
zvel = (((ps[j].GetActor()->getPrevOffsetZ() - spos.Z) * vel) / dist);
if (badguy(actor) && (actor->spr.hitag & face_player_smart) != 0)
sang = actor->spr.Angles.Yaw + mapangle((krand() & 31) - 16);
if (actor->sector()->lotag == 2 && (krand() % 5) == 0)
spawned = spawn(actor, DTILE_WATERBUBBLE);
}
else
{
setFreeAimVelocity(vel, zvel, ps[p].Angles.getPitchWithView(), 40.5);
// WTF???
DAngle myang = DAngle90 - (DAngle180 - abs(abs((spos.XY() - ps[p].GetActor()->spr.pos.XY()).Angle() - sang) - DAngle180));
if (ps[p].GetActor()->vel.X != 0)
vel = ((myang / DAngle90) * ps[p].GetActor()->vel.X) + 25;
if (actor->sector()->lotag == 2 && (krand() % 5) == 0)
spawned = spawn(actor, DTILE_WATERBUBBLE);
}
if (spawned == nullptr)
{
spawned = spawn(actor, DTILE_FLAMETHROWERFLAME);
if (!spawned) return;
spawned->vel.X = vel;
spawned->vel.Z = zvel;
}
DVector3 offset;
offset.X = (sang + DAngle::fromBuild(118)).Cos() * (1024 / 448.); // Yes, these angles are really different!
offset.Y = (sang + DAngle::fromBuild(112)).Sin() * (1024 / 448.);
offset.Z = -1;
spawned->spr.pos = spos + offset;
spawned->spr.pos.Z--;
spawned->setsector(actor->sector());
spawned->spr.cstat = CSTAT_SPRITE_YCENTER;
spawned->spr.Angles.Yaw = sang;
spawned->spr.scale = DVector2(0.03125, 0.03125);
spawned->clipdist = 10;
spawned->spr.yint = p;
spawned->SetOwner(actor);
if (p == -1)
{
if (actor->spr.picnum == DTILE_BOSS5)
{
spawned->spr.pos += sang.ToVector() * (128. / 7);
spawned->spr.scale = DVector2(0.15625, 0.15625);
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void shootknee(DDukeActor* actor, int p, DVector3 pos, DAngle ang)
{
auto sectp = actor->sector();
@ -1074,10 +989,6 @@ void shoot_d(DDukeActor* actor, int atwith, PClass *cls)
shootfireball(actor, p, spos, sang);
return;
case DTILE_FLAMETHROWERFLAME:
shootflamethrowerflame(actor, p, spos, sang);
return;
case DTILE_FIREFLY: // DTILE_BOSS5 shot
{
auto k = spawn(actor, atwith);

View file

@ -212,6 +212,20 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Duke, StopCommentary, StopCommentary)
return 0;
}
int getPlayerIndex(player_struct* p)
{
if (!p) return -1;
return int(p - ps);
}
DEFINE_ACTION_FUNCTION_NATIVE(_Duke, getPlayerIndex, getPlayerIndex)
{
PARAM_PROLOGUE;
PARAM_POINTER(p, player_struct);
ACTION_RETURN_INT(getPlayerIndex(p));
return 0;
}
DEFINE_GLOBAL_UNSIZED(dlevel)
DEFINE_GLOBAL(camsprite)

View file

@ -5,4 +5,5 @@ spawnclasses
5736 = DukeGenericDestructible, "WTGLASS1", "", "GLASS_BREAKING", spawnglass
5737 = DukeGenericDestructible, "WTGLASS2", "", "GLASS_BREAKING", spawnglass
5294 = DeveloperCommentary
1891 = DukeFlamethrowerFlame
}

View file

@ -102,6 +102,7 @@ version "4.10"
#include "zscript/games/duke/actors/bloodpool.zs"
#include "zscript/games/duke/actors/toilet.zs"
#include "zscript/games/duke/actors/flamethrowerflame.zs"
#include "zscript/games/duke/actors/redneckmisc.zs"
#include "zscript/games/duke/actors/emptybike.zs"

View file

@ -57,6 +57,7 @@ class CoreActor native
native double pitch;
native Vector3 vel;
native double viewzoffset;
native double oviewzoffset;
native readonly int16 spritesetindex;
native readonly int spawnindex;

View file

@ -0,0 +1,192 @@
class DukeFlamethrowerFlame : DukeActor
{
default
{
pic "FLAMETHROWERFLAME";
}
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.temp_data[0]++;
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.temp_data[0] / 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.temp_data[0] <= 2)
self.temp_data[3] = random(0, 9);
if (self.temp_data[0] > 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.checkhitsprite(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
{
Console.Printf("launching");
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.checktype("BOSS5"))
{
vel = 33;
spos.Z += 24;
}
else if (actor.checktype("BOSS3"))
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.checktype("BOSS5"))
{
spawned.pos += sang.ToVector() * (128. / 7);
spawned.scale = (0.15625, 0.15625);
}
}
return true;
}
}

View file

@ -115,6 +115,28 @@ class DukeActor : CoreActor native
STAT_REMOVED = MAXSTATUS-2,
};
enum amoveflags_t
{
face_player = 1,
geth = 2,
getv = 4,
random_angle = 8,
face_player_slow = 16,
spin = 32,
face_player_smart = 64,
fleeenemy = 128,
jumptoplayer_only = 256,
justjump1 = 256,
jumptoplayer = 257,
seekplayer = 512,
furthestdir = 1024,
dodgebullet = 4096,
justjump2 = 8192,
windang = 16384,
antifaceplayerslow = 32768
};
native void SetSpritesetImage(int index);
native int GetSpritesetSize();

View file

@ -170,6 +170,7 @@ struct Duke native
native static void updatepindisplay(int tag, int pinmask);
native static bool StartCommentary(int tag, DukeActor act);
native static void StopCommentary();
static native int getPlayerIndex(DukePlayer p);
static int rnd(int val)
{
return (random(0, 255) >= (255 - (val)));
@ -216,6 +217,7 @@ struct Duke native
if (align != -1) x -= myfont.StringWidth(t) * (align == 0 ? 0.5 : 1);
Screen.DrawText(myfont, Font.CR_NATIVEPAL, x, y + 2, t, DTA_FullscreenScale, fsmode, DTA_TranslationIndex, Translation.MakeID(Translation_Remap, trans), DTA_Color, Raze.shadeToLight(shade));
}
}
struct DukePlayer native

View file

@ -264,6 +264,11 @@ struct Raze
// Right now, with no MP support there is no need, though.
}
static double, double setFreeAimVelocity(double vel, double zvel, double pitch, double zvspeed)
{
return vel * cos(pitch), sin(pitch) * zvspeed;
}
}
/*