- scriptified the mortar projectiles.

This was split off heavyhbomb for clarity and to avoid interference with the pickup code.
This commit is contained in:
Christoph Oelckers 2022-12-01 11:55:35 +01:00
parent 0bc9023e17
commit 44d4e7a20a
8 changed files with 222 additions and 323 deletions

View file

@ -1165,144 +1165,6 @@ static void flamethrowerflame(DDukeActor *actor)
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void heavyhbomb(DDukeActor *actor)
{
auto Owner = actor->GetOwner();
auto sectp = actor->sector();
int l;
double xx;
int p = findplayer(actor, &xx);
if (xx < 1220 / 16.) actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
else actor->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL;
if (actor->temp_data[3] == 0)
{
int j = fi.ifhitbyweapon(actor);
if (j >= 0)
{
actor->temp_data[3] = 1;
actor->temp_data[4] = 0;
l = 0;
actor->vel.X = 0;
goto DETONATEB;
}
}
if (actor->spr.picnum != BOUNCEMINE)
{
makeitfall(actor);
if (sectp->lotag != 1 && actor->spr.pos.Z >= actor->floorz - FOURSLEIGHT_F && actor->spr.yint < 3)
{
if (actor->spr.yint > 0 || (actor->spr.yint == 0 && actor->floorz == sectp->floorz))
S_PlayActorSound(PIPEBOMB_BOUNCE, actor);
actor->vel.Z = -(4 - actor->spr.yint);
if (actor->sector()->lotag == 2)
actor->vel.Z *= 0.25;
actor->spr.yint++;
}
if (actor->spr.pos.Z < actor->ceilingz) // && sectp->lotag != 2 )
{
actor->spr.pos.Z = actor->ceilingz + 3;
actor->vel.Z = 0;
}
}
Collision coll;
movesprite_ex(actor, DVector3(actor->spr.Angles.Yaw.ToVector() * actor->vel.X, actor->vel.Z), CLIPMASK0, coll);
if (actor->sector()->lotag == 1 && actor->vel.Z == 0)
{
actor->spr.pos.Z += 32;
if (actor->temp_data[5] == 0)
{
actor->temp_data[5] = 1;
spawn(actor, WATERSPLASH2);
}
}
else actor->temp_data[5] = 0;
if (actor->temp_data[3] == 0 && (actor->spr.picnum == BOUNCEMINE || actor->spr.picnum == MORTER) && (coll.type || xx < 844/16.))
{
actor->temp_data[3] = 1;
actor->temp_data[4] = 0;
l = 0;
actor->vel.X = 0;
goto DETONATEB;
}
if ( Owner && Owner->isPlayer())
l = Owner->PlayerIndex();
else l = -1;
if(actor->vel.X > 0)
{
actor->vel.X -= 5. / 16;
if (sectp->lotag == 2)
actor->vel.X -= 10. / 16;
if(actor->vel.X < 0)
actor->vel.X = 0;
if (int(actor->vel.X * 16) & 8) actor->spr.cstat ^= CSTAT_SPRITE_XFLIP;
}
if (coll.type== kHitWall)
{
auto wal = coll.hitWall;
fi.checkhitwall(actor, wal, actor->spr.pos, actor->spr.picnum);
DAngle k = wal->delta().Angle();
actor->spr.Angles.Yaw = k * 2 - actor->spr.Angles.Yaw;
actor->vel.X *= 0.5;
}
DETONATEB:
if (actor->temp_data[3] == 1)
{
actor->temp_data[4]++;
if (actor->temp_data[4] == 2)
{
int x = actor->spr.extra;
int m = 0;
switch (actor->spr.picnum)
{
case MORTER: m = gs.morterblastradius; break;
case BOUNCEMINE: m = gs.bouncemineblastradius; break;
}
fi.hitradius(actor, m, x >> 2, x >> 1, x - (x >> 2), x);
spawn(actor, EXPLOSION2);
if (actor->vel.Z == 0) spawn(actor, EXPLOSION2BOT);
S_PlayActorSound(PIPEBOMB_EXPLODE, actor);
for (x = 0; x < 8; x++)
RANDOMSCRAP(actor);
}
if (actor->spr.scale.Y)
{
actor->spr.scale.Y = (0);
return;
}
if (actor->temp_data[4] > 20)
{
actor->Destroy();
return;
}
}
if (actor->temp_data[0] < 8) actor->temp_data[0]++;
}
//---------------------------------------------------------------------------
//
@ -1334,18 +1196,13 @@ void moveactors_d(void)
if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
{
CallTick(act);
continue;
}
else switch (act->spr.picnum)
{
case FLAMETHROWERFLAME:
if (isWorldTour()) flamethrowerflame(act);
continue;
case BOUNCEMINE:
case MORTER:
spawn(act, FRAMEEFFECT1)->temp_data[0] = 3;
heavyhbomb(act);
continue;
}
if (monsterCheatCheck(act) && badguy(act))
{

View file

@ -1254,171 +1254,6 @@ void rr_specialstats()
//
//---------------------------------------------------------------------------
static void heavyhbomb(DDukeActor *actor)
{
auto sectp = actor->sector();
int l;
double xx;
auto Owner = actor->GetOwner();
if ((actor->spr.cstat & CSTAT_SPRITE_INVISIBLE))
{
actor->temp_data[2]--;
if (actor->temp_data[2] <= 0)
{
S_PlayActorSound(TELEPORTER, actor);
spawn(actor, TRANSPORTERSTAR);
actor->spr.cstat = CSTAT_SPRITE_BLOCK_ALL;
}
return;
}
int p = findplayer(actor, &xx);
makeitfall(actor);
if (sectp->lotag != 1 && (!isRRRA() || sectp->lotag != ST_160_FLOOR_TELEPORT) && actor->spr.pos.Z >= actor->floorz - FOURSLEIGHT_F && actor->spr.yint < 3)
{
if (actor->spr.yint > 0 || (actor->spr.yint == 0 && actor->floorz == sectp->floorz))
{
if (actor->spr.picnum != CHEERBOMB)
S_PlayActorSound(PIPEBOMB_BOUNCE, actor);
else
{
actor->temp_data[3] = 1;
actor->temp_data[4] = 1;
l = 0;
goto DETONATEB;
}
}
actor->vel.Z = -(4 - actor->spr.yint);
if (actor->sector()->lotag == 2)
actor->vel.Z *= 0.25;
actor->spr.yint++;
}
if (actor->spr.picnum != CHEERBOMB && actor->spr.pos.Z < actor->ceilingz + 16 && sectp->lotag != 2)
{
actor->spr.pos.Z = actor->ceilingz + 16;
actor->vel.Z = 0;
}
Collision coll;
movesprite_ex(actor, DVector3(actor->spr.Angles.Yaw.ToVector() * actor->vel.X, actor->vel.Z), CLIPMASK0, coll);
if (actor->sector()->lotag == 1 && actor->vel.Z == 0)
{
actor->spr.pos.Z += 32;
if (actor->temp_data[5] == 0)
{
actor->temp_data[5] = 1;
spawn(actor, WATERSPLASH2);
if (isRRRA() && actor->spr.picnum == MORTER)
actor->vel.X = 0;
}
}
else actor->temp_data[5] = 0;
if (actor->temp_data[3] == 0 && actor->spr.picnum == MORTER && (coll.type || xx < 844 / 16.))
{
actor->temp_data[3] = 1;
actor->temp_data[4] = 0;
l = 0;
actor->vel.X = 0;
goto DETONATEB;
}
if (actor->temp_data[3] == 0 && actor->spr.picnum == CHEERBOMB && (coll.type || xx < 844 / 16.))
{
actor->temp_data[3] = 1;
actor->temp_data[4] = 0;
l = 0;
actor->vel.X = 0;
goto DETONATEB;
}
if (Owner && Owner->isPlayer())
l = Owner->PlayerIndex();
else l = -1;
if(actor->vel.X > 0)
{
actor->vel.X -= 5. / 16;
if (sectp->lotag == 2)
actor->vel.X -= 10. / 16;
if(actor->vel.X < 0)
actor->vel.X = 0;
if (int(actor->vel.X * 16) & 8) actor->spr.cstat ^= CSTAT_SPRITE_XFLIP;
}
if (coll.type == kHitWall)
{
auto wal = coll.hitWall;
fi.checkhitwall(actor, wal, actor->spr.pos, actor->spr.picnum);
if (actor->spr.picnum == CHEERBOMB)
{
actor->temp_data[3] = 1;
actor->temp_data[4] = 0;
l = 0;
actor->vel.X = 0;
goto DETONATEB;
}
DAngle k = wal->delta().Angle();
actor->spr.Angles.Yaw = k * 2 - actor->spr.Angles.Yaw;
actor->vel.X *= 0.5;
}
DETONATEB:
if (actor->temp_data[3] == 1)
{
actor->temp_data[4]++;
if (actor->temp_data[4] == 2)
{
int x = actor->spr.extra;
int m = gs.morterblastradius;
if (actor->sector()->lotag != 800)
{
fi.hitradius(actor, m, x >> 2, x >> 1, x - (x >> 2), x);
spawn(actor, EXPLOSION2);
if (actor->spr.picnum == CHEERBOMB)
spawn(actor, BURNING);
S_PlayActorSound(PIPEBOMB_EXPLODE, actor);
for (x = 0; x < 8; x++)
RANDOMSCRAP(actor);
}
}
if (actor->spr.scale.Y)
{
actor->spr.scale.Y = (0);
return;
}
if (actor->temp_data[4] > 20)
{
actor->Destroy();
return;
}
if (actor->spr.picnum == CHEERBOMB)
{
spawn(actor, BURNING);
actor->Destroy();
return;
}
}
if (actor->temp_data[0] < 8) actor->temp_data[0]++;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static int henstand(DDukeActor *actor)
{
if (actor->spr.picnum == HENSTAND || actor->spr.picnum == HENSTAND + 1)
@ -1535,6 +1370,7 @@ void moveactors_r(void)
if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
{
CallTick(act);
continue;
}
else switch(act->spr.picnum)
{
@ -1590,13 +1426,6 @@ void moveactors_r(void)
act->vel.X -= 1. / 16.;
}
break;
case CHEERBOMB:
if (!isRRRA()) break;
[[fallthrough]];
case MORTER:
heavyhbomb(act);
continue;
}

View file

@ -205,13 +205,6 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
case CRYSTALAMMO:
t->shade = int(BobVal(PlayClock << 4) * 16);
break;
case CHEERBOMB:
if (isRRRA())
{
t->picnum = CHEERBOMB + ((PlayClock >> 4) & 3);
break;
}
else goto default_case;
case EMPTYBIKE:
if (!isRRRA()) goto default_case;
kang = (h->spr.pos - viewVec).Angle();

View file

@ -77,6 +77,8 @@ spawnclasses
1346 = DukeHelicopter
2491 = DukeCar
26 = DukePipeBomb
940 = DukeBounceMine
1650 = DukeMortar
1272 = DukeTrash
634 = DukeBolt1

View file

@ -2,6 +2,7 @@ include "engine/defines.def"
spawnclasses
{
3464 = RedneckCheerBomb
2430 = RedneckCactusLargeYellow
2431 = RedneckCactusLargeGreen
2432 = RedneckCactusLargeBrown

View file

@ -75,6 +75,7 @@ spawnclasses
1172 = DukeVase
26 = RedneckDynamite
1416 = RedneckMortar
285 = RedneckChickenSpawner1
286 = RedneckChickenSpawner2
287 = RedneckFeatherSpawner

View file

@ -89,6 +89,7 @@ version "4.10"
#include "zscript/games/duke/actors/helicopt.zs"
#include "zscript/games/duke/actors/greenslime.zs"
#include "zscript/games/duke/actors/heavyhbomb.zs"
#include "zscript/games/duke/actors/mortar.zs"
#include "zscript/games/duke/actors/redneckmisc.zs"
#include "zscript/games/duke/actors/rabbitspawner.zs"

View file

@ -0,0 +1,215 @@
class DukeMortar : DukeActor
{
default
{
pic "MORTAR";
detail 3;
}
override void Tick()
{
let spawned = self.spawn("DukeFrameEffect1");
if (spawned) spawned.temp_data[0] = 3;
Common(1);
}
void Common(int itemmode)
{
let Owner = self.ownerActor;
let sectp = self.sector;
DukePlayer p;
double xx;
[p,xx] = self.findplayer();
if (self.temp_data[3] == 0)
{
int j = self.ifhitbyweapon();
if (j >= 0)
{
self.temp_data[3] = 1;
self.temp_data[4] = 0;
self.vel.X = 0;
self.DetonateIt(itemmode);
return;
}
}
if (itemmode != 0)
{
self.makeitfall();
// Feature check later needs to be map controlled, not game controlled.
if (sectp.lotag != ST_1_ABOVE_WATER && (!Raze.isRRRA() || sectp.lotag != ST_160_FLOOR_TELEPORT) && self.pos.Z >= self.floorz - 1 && self.yint < 3)
{
if (self.yint > 0 || (self.yint == 0 && self.floorz == sectp.floorz))
{
if (itemmode != 2)
self.PlayActorSound("PIPEBOMB_BOUNCE");
else if (self.temp_data[3] == 0)
{
self.temp_data[3] = 1;
self.temp_data[4] = 0;
self.DetonateIt(itemmode);
return;
}
}
self.vel.Z = -(4 - self.yint);
if (sectp.lotag == 2)
self.vel.Z *= 0.25;
self.yint++;
}
if (itemmode != 2 && self.pos.Z < self.ceilingz + self.detail && (!Raze.isRR() || sectp.lotag != ST_2_UNDERWATER)) // underwater check only for RR
{
self.pos.Z = self.ceilingz + self.detail;
self.vel.Z = 0;
}
}
CollisionData coll;
self.movesprite_ex((self.angle.ToVector() * self.vel.X, self.vel.Z), CLIPMASK0, coll);
if (sectp.lotag == ST_1_ABOVE_WATER && self.vel.Z == 0)
{
self.pos.Z += 32;
if (self.temp_data[5] == 0)
{
self.temp_data[5] = 1;
self.spawn("DukeWaterSplash2");
}
}
else self.temp_data[5] = 0;
if (self.temp_data[3] == 0 && (coll.type || xx < 844 / 16.))
{
self.temp_data[3] = 1;
self.temp_data[4] = 0;
self.vel.X = 0;
}
else if(self.vel.X > 0)
{
self.vel.X -= 5. / 16;
if (sectp.lotag == ST_2_UNDERWATER)
self.vel.X -= 10. / 16;
if(self.vel.X < 0)
self.vel.X = 0;
//if (int(self.vel.X * 16) & 8) self.spr.cstat ^= CSTAT_SPRITE_XFLIP;
}
self.DetonateIt(itemmode);
}
void DetonateIt(int itemmode)
{
if (self.temp_data[3] == 1)
{
self.temp_data[4]++;
DukePlayer p;
double xx;
[p,xx] = self.findplayer();
if (self.temp_data[4] == 2)
{
int x = self.extra;
int m = itemmode == 0? gs.bouncemineblastradius : gs.morterblastradius;
if (self.sector.lotag != 800 || !Raze.isRR()) // this line is RR only
{
self.hitradius(m, x >> 2, x >> 1, x - (x >> 2), x);
self.spawn("DukeExplosion2");
if (self.vel.Z == 0 && !Raze.isRR()) self.spawn("DukeExplosion2Bot"); // this line is Duke only
if (itemmode == 2) self.spawn("DukeBurning");
self.PlayActorSound("PIPEBOMB_EXPLODE");
for (x = 0; x < 8; x++)
self.RANDOMSCRAP();
}
}
if (self.scale.Y)
{
self.scale.Y = 0;
return;
}
if (self.temp_data[4] > 20)
{
self.Destroy();
return;
}
if (itemmode == 2)
{
self.spawn("DukeBurning");
self.Destroy();
return;
}
}
if (self.temp_data[0] < 8) self.temp_data[0]++;
}
}
class DukeBounceMine : DukeMortar
{
default
{
pic "BOUNCEMINE";
}
override void Initialize()
{
// This is only for placed items, not for armed weapons!
// Although this can be shot, it doesn't really work for that.
if (self.ownerActor == self)
{
self.ownerActor = self;
self.extra = gs.impact_damage << 2;
self.cstat |= CSTAT_SPRITE_BLOCK_ALL; // Make it hitable
self.ChangeStat(STAT_ZOMBIEACTOR);
self.shade = -127;
self.Scale = (0.375, 0.375);
}
}
override void Tick()
{
Common(0);
}
}
class RedneckNortar : DukeMortar
{
default
{
pic "MORTAR";
detail 16;
}
override void Tick()
{
Common(1);
}
}
class RedneckCheerBomb : DukeMortar
{
default
{
spriteset "CHEERBOMB", "CHEERBOMB1", "CHEERBOMB2", "CHEERBOMB3";
detail 16;
}
override bool Animate(tspritetype t)
{
t.SetSpritePic(self, (PlayClock >> 4) & 3);
return true;
}
override void Tick()
{
Common(2);
}
}