- scriptified the World Tour's flamethrower#s fireball.

Also using a better method to mark the trailing balls than checking the owner.
This commit is contained in:
Christoph Oelckers 2022-11-29 20:28:16 +01:00
parent 26d9511087
commit 82515e1d76
3 changed files with 115 additions and 253 deletions

View file

@ -746,253 +746,6 @@ void movestandables_d(void)
//
//---------------------------------------------------------------------------
static bool movefireball(DDukeActor* actor)
{
auto Owner = actor->GetOwner();
if (actor->sector()->lotag == 2)
{
actor->Destroy();
return true;
}
if (!Owner || Owner->spr.picnum != FIREBALL)
{
if (actor->temp_data[0] >= 1 && actor->temp_data[0] < 6)
{
float siz = 1.0f - (actor->temp_data[0] * 0.2f);
DDukeActor* trail = actor->temp_actor;
auto ball = spawn(actor, FIREBALL);
if (ball)
{
actor->temp_actor = ball;
ball->vel.X = actor->vel.X;
ball->vel.Z = actor->vel.Z;
if (actor->temp_data[0] > 1)
{
if (trail)
{
ball->spr.pos = trail->temp_pos;
ball->vel = trail->temp_pos2;
}
}
double scale = actor->spr.scale.X * siz;
ball->spr.scale = DVector2(scale, scale);
ball->spr.cstat = actor->spr.cstat;
ball->spr.extra = 0;
ball->temp_pos = ball->spr.pos;
ball->temp_pos2 = ball->vel;
ChangeActorStat(ball, STAT_PROJECTILE);
}
}
actor->temp_data[0]++;
}
if (actor->vel.Z < 15000. / 256.)
actor->vel.Z += 200 / 256.;
return false;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool weaponhitsprite(DDukeActor* proj, DDukeActor *targ, bool fireball)
{
if (!isWorldTour() || proj->spr.picnum != FIREBALL || fireball)
fi.checkhitsprite(targ, proj);
if (targ->isPlayer())
{
int p = targ->spr.yint;
auto Owner = proj->GetOwner();
if (ud.multimode >= 2 && fireball && Owner && Owner->isPlayer())
{
ps[p].numloogs = -1 - proj->spr.yint;
}
S_PlayActorSound(PISTOL_BODYHIT, targ);
}
return false;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool weaponhitwall(DDukeActor *proj, walltype* wal, const DVector3 &oldpos)
{
if (proj->spr.picnum != RPG && proj->spr.picnum != FREEZEBLAST && proj->spr.picnum != SPIT &&
(!isWorldTour() || proj->spr.picnum != FIREBALL) &&
(wal->overpicnum == MIRROR || wal->picnum == MIRROR))
{
DAngle k = wal->delta().Angle();
proj->spr.Angles.Yaw = k * 2 - proj->spr.Angles.Yaw;
proj->SetOwner(proj);
spawn(proj, TRANSPORTERSTAR);
return true;
}
else
{
SetActor(proj, oldpos);
fi.checkhitwall(proj, wal, proj->spr.pos, proj->spr.picnum);
}
return false;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool weaponhitsector(DDukeActor* proj, const DVector3& oldpos, bool fireball)
{
SetActor(proj, oldpos);
if (proj->vel.Z < 0)
{
if (proj->sector()->ceilingstat & CSTAT_SECTOR_SKY)
if (proj->sector()->ceilingpal == 0)
{
proj->Destroy();
return true;
}
fi.checkhitceiling(proj->sector());
}
else if (fireball)
{
auto spawned = spawn(proj, LAVAPOOL);
if (spawned)
{
spawned->SetOwner(proj);
spawned->SetHitOwner(proj);
spawned->spr.yint = proj->spr.yint;
}
proj->Destroy();
return true;
}
return false;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void weaponcommon_d(DDukeActor* proj)
{
double vel = proj->vel.X;
double velz = proj->vel.Z;
int p = -1;
auto oldpos = proj->spr.pos;
getglobalz(proj);
switch (proj->spr.picnum)
{
case FIREBALL:
if (movefireball(proj)) return;
break;
}
Collision coll;
movesprite_ex(proj, DVector3(proj->spr.Angles.Yaw.ToVector() * vel, velz), CLIPMASK1, coll);
if (!proj->insector())
{
proj->Destroy();
return;
}
if (coll.type != kHitSprite && proj->spr.picnum != FREEZEBLAST)
{
if (proj->spr.pos.Z < proj->ceilingz)
{
coll.setSector(proj->sector());
proj->vel.Z -= 1/256.;
}
else
if ((proj->spr.pos.Z > proj->floorz && proj->sector()->lotag != 1) ||
(proj->spr.pos.Z > proj->floorz + 16 && proj->sector()->lotag == 1))
{
coll.setSector(proj->sector());
if (proj->sector()->lotag != 1)
proj->vel.Z += 1/256.;
}
}
if (coll.type != 0)
{
bool fireball = (isWorldTour() && proj->spr.picnum == FIREBALL && (!proj->GetOwner() || proj->GetOwner()->spr.picnum != FIREBALL));
if (coll.type == kHitSprite)
{
if (weaponhitsprite(proj, coll.actor(), fireball)) return;
}
else if (coll.type == kHitWall)
{
if (weaponhitwall(proj, coll.hitWall, oldpos)) return;
}
else if (coll.type == kHitSector)
{
if (weaponhitsector(proj, oldpos, fireball)) return;
}
if (proj->spr.picnum != SPIT)
{
if (proj->spr.picnum != COOLEXPLOSION1 && proj->spr.picnum != FREEZEBLAST && (!isWorldTour() || proj->spr.picnum != FIREBALL))
{
auto spawned = spawn(proj, EXPLOSION2);
if (spawned)
{
auto scale = proj->spr.scale.X * 0.5;
spawned->spr.scale = DVector2(scale,scale);
if (coll.type == kHitSector)
{
if (proj->vel.Z < 0)
{
spawned->spr.cstat |= CSTAT_SPRITE_YFLIP;
spawned->spr.pos.Z += 72;
}
}
}
}
if (fireball)
{
auto spawned = spawn(proj, EXPLOSION2);
if (spawned)
{
auto scale = proj->spr.scale.X * 0.5;
spawned->spr.scale = DVector2(scale,scale);
}
}
}
if (proj->spr.picnum != COOLEXPLOSION1)
{
proj->Destroy();
return;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void moveweapons_d(void)
{
DukeStatIterator it(STAT_PROJECTILE);
@ -1012,12 +765,6 @@ void moveweapons_d(void)
switch(act->spr.picnum)
{
case FIREBALL:
// Twentieth Anniversary World Tour
if (act->spr.picnum == FIREBALL && !isWorldTour()) break;
weaponcommon_d(act);
break;
case SHOTSPARK1:
{
double x;

View file

@ -0,0 +1,6 @@
spawnclasses
{
5163 = DukeFireball
}

View file

@ -583,3 +583,112 @@ class DukeCoolExplosion1 : DukeProjectile // octabrain shot.
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeFireball : DukeProjectile // WorldTour only
{
default
{
pic "FIREBALL";
}
override bool premoveeffect()
{
let Owner = self.ownerActor;
if (self.sector.lotag == 2)
{
self.Destroy();
return true;
}
if (self.detail != 1)
{
if (self.temp_data[0] >= 1 && self.temp_data[0] < 6)
{
double siz = 1.0 - (self.temp_data[0] * 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.temp_data[0] > 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.temp_data[0]++;
}
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 bool animate(tspritetype tspr)
{
tspr.shade = -127;
return true;
}
}