- scriptified all simple and explosive RR projectiles.

This commit is contained in:
Christoph Oelckers 2022-11-29 20:55:02 +01:00
parent 82515e1d76
commit 403141807f
12 changed files with 220 additions and 289 deletions

View file

@ -608,53 +608,6 @@ void detonate(DDukeActor *actor, int explosion)
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void rpgexplode(DDukeActor *actor, int hit, const DVector3 &pos, int EXPLOSION2, int EXPLOSION2BOT, int newextra, int playsound)
{
auto explosion = spawn(actor, EXPLOSION2);
if (!explosion) return;
explosion->spr.pos = pos;
if (actor->spr.scale.X < 0.15625)
{
explosion->spr.scale = DVector2(0.09375, 0.09375);
}
else if (hit == kHitSector)
{
if (actor->vel.Z > 0 && EXPLOSION2BOT >= 0)
spawn(actor, EXPLOSION2BOT);
else
{
explosion->spr.cstat |= CSTAT_SPRITE_YFLIP;
explosion->spr.pos.Z += 48;
}
}
if (newextra > 0) actor->spr.extra = newextra;
S_PlayActorSound(playsound, actor);
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 reactor(DDukeActor* const actor, int REACTOR, int REACTOR2, int REACTORBURNT, int REACTOR2BURNT, int REACTORSPARK, int REACTOR2SPARK)
{
auto sectp = actor->sector();

View file

@ -609,46 +609,6 @@ void movestandables_r(void)
//
//---------------------------------------------------------------------------
static void chickenarrow(DDukeActor* actor)
{
actor->spr.hitag++;
if (actor->attackertype != BOSS2 && actor->spr.scale.X >= 0.15625 && actor->sector()->lotag != 2)
{
auto spawned = spawn(actor, SMALLSMOKE);
if (spawned) spawned->spr.pos.Z += 1;
if ((krand() & 15) == 2)
{
spawn(actor, FEATHER);
}
}
DDukeActor* ts = actor->seek_actor;
if (!ts) return;
if (ts->spr.extra <= 0)
actor->seek_actor = nullptr;
if (actor->seek_actor && actor->spr.hitag > 5)
{
DAngle ang, ang2;
ang = (ts->spr.pos - actor->spr.pos).Angle();
ang2 = deltaangle(ang, actor->spr.Angles.Yaw);
// this was quite broken in the original code. Fixed so that it seeks properly
if (abs(ang2) < DAngle1 * 17.5)
{
actor->spr.Angles.Yaw = ang;
}
else if (ang2 > nullAngle)
{
actor->spr.Angles.Yaw -= DAngle1 * 9;
}
else
actor->spr.Angles.Yaw += DAngle1 * 9;
if (actor->spr.hitag > 180)
if (actor->vel.Z <= 0)
actor->vel.Z += 200 / 256;
}
}
static void rabbitguts(DDukeActor* proj)
{
@ -665,33 +625,6 @@ static void rabbitguts(DDukeActor* proj)
static bool weaponhitsprite(DDukeActor *proj, DDukeActor *targ, const DVector3 &oldpos)
{
if (isRRRA())
{
if (targ->spr.picnum == MINION
&& (proj->spr.picnum == RPG || proj->spr.picnum == RPG2)
&& targ->spr.pal == 19)
{
S_PlayActorSound(RPG_EXPLODE, proj);
auto spawned = spawn(proj, EXPLOSION2);
if (spawned)
spawned->spr.pos = oldpos;
return true;
}
}
else if (proj->spr.picnum == FREEZEBLAST && targ->spr.pal == 1)
if (badguy(targ) || targ->isPlayer())
{
auto star = spawn(proj, TRANSPORTERSTAR);
if (star)
{
star->spr.pal = 1;
star->spr.scale = DVector2(0.5, 0.5);
}
proj->Destroy();
return true;
}
fi.checkhitsprite(targ, proj);
if (targ->isPlayer())
@ -754,25 +687,9 @@ static bool weaponhitwall(DDukeActor *proj, walltype* wal, const DVector3& oldpo
SetActor(proj, oldpos);
fi.checkhitwall(proj, wal, proj->spr.pos, proj->spr.picnum);
if (!isRRRA() && proj->spr.picnum == FREEZEBLAST)
{
if (wal->overpicnum != MIRROR && wal->picnum != MIRROR)
{
proj->spr.extra >>= 1;
if (proj->spr.scale.X > 0.125 )
proj->spr.scale.X += (-0.03125);
if (proj->spr.scale.Y > 0.125 )
proj->spr.scale.Y += (-0.03125);
proj->spr.yint--;
}
DAngle walang = wal->delta().Angle();
proj->spr.Angles.Yaw = walang * 2 - proj->spr.Angles.Yaw;
return true;
}
if (proj->spr.picnum == SAWBLADE)
{
if (wal->picnum >= RRTILE3643 && wal->picnum < RRTILE3643 + 3)
if (wal->picnum >= PICKUPSIDE && wal->picnum < PICKUPSIDE + 3)
{
proj->Destroy();
}
@ -852,52 +769,12 @@ static void weaponcommon_r(DDukeActor *proj)
int p = -1;
if (proj->spr.picnum == RPG && proj->sector()->lotag == 2)
{
vel *= 0.5;
velz *= 0.5;
}
else if (isRRRA() && proj->spr.picnum == RPG2 && proj->sector()->lotag == 2)
{
vel *= 0.5;
velz *= 0.5;
}
auto oldpos = proj->spr.pos;
getglobalz(proj);
switch (proj->spr.picnum)
{
case RPG:
if (proj->attackertype != BOSS2 && proj->spr.scale.X >= 0.15625 && proj->sector()->lotag != 2)
{
auto spawned = spawn(proj, SMALLSMOKE);
if (spawned) spawned->spr.pos.Z += 1;
}
break;
case RPG2:
if (!isRRRA()) break;
chickenarrow(proj);
break;
case BOATGRENADE:
if (!isRRRA()) break;
if (proj->spr.extra)
{
proj->vel.Z = -(proj->spr.extra * 250/256.); // 250 looks like a typo...
proj->spr.extra--;
}
else
makeitfall(proj);
if (proj->spr.scale.X >= 0.15625 && proj->sector()->lotag != 2)
{
auto spawned = spawn(proj, SMALLSMOKE);
if (spawned) spawned->spr.pos.Z += 1;
}
break;
}
Collision coll;
movesprite_ex(proj, DVector3(proj->spr.Angles.Yaw.ToVector() * vel, velz), CLIPMASK1, coll);
@ -948,10 +825,7 @@ static void weaponcommon_r(DDukeActor *proj)
if (proj->spr.picnum != SHITBALL)
{
if (proj->spr.picnum == RPG) rpgexplode(proj, coll.type, oldpos, EXPLOSION2, -1, -1, RPG_EXPLODE);
else if (isRRRA() && proj->spr.picnum == RPG2) rpgexplode(proj, coll.type, oldpos, EXPLOSION2, -1, 150, 247);
else if (isRRRA() && proj->spr.picnum == BOATGRENADE) rpgexplode(proj, coll.type, oldpos, EXPLOSION2, -1, 160, RPG_EXPLODE);
else if (proj->spr.picnum != FREEZEBLAST && proj->spr.picnum != SAWBLADE)
if (proj->spr.picnum != FREEZEBLAST && proj->spr.picnum != SAWBLADE)
{
auto spawned = spawn(proj, 1441);
if (spawned)
@ -972,9 +846,6 @@ static void weaponcommon_r(DDukeActor *proj)
proj->Destroy();
return;
}
if ((proj->spr.picnum == RPG || (isRRRA() && proj->spr.picnum == RPG2)) && proj->sector()->lotag == 2 && proj->spr.scale.X >= 0.15625 && rnd(184))
spawn(proj, WATERBUBBLE);
}
//---------------------------------------------------------------------------
@ -1002,16 +873,8 @@ void moveweapons_r(void)
switch (proj->spr.picnum)
{
case RPG2:
case BOATGRENADE:
if (!isRRRA()) continue;
[[fallthrough]];
case SAWBLADE:
case RPG:
case SHITBALL:
case COOLEXPLOSION1:
case OWHIP:
case UWHIP:
weaponcommon_r(proj);
continue;
@ -2158,17 +2021,6 @@ void moveexplosions_r(void) // STATNUM 5
case FRAMEEFFECT1:
frameeffect1(act);
continue;
case COOLEXPLOSION1:
case OWHIP:
case UWHIP:
if (act->spr.extra != 999)
act->spr.extra = 999;
else
{
act->Destroy();
continue;
}
break;
case FEATHER + 1: // feather
act->spr.pos.Z = act->floorz = getflorzofslopeptr(act->sector(), act->spr.pos.X, act->spr.pos.Y);
if (act->sector()->lotag == 800)

View file

@ -273,30 +273,6 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
else t->cstat &= ~CSTAT_SPRITE_XFLIP;
t->picnum = EMPTYBOAT + k;
break;
case RPG:
kang = (h->spr.pos - viewVec).Angle();
k = angletorotation2(h->spr.Angles.Yaw, kang);
if (k > 6)
{
k = 12 - k;
t->cstat |= CSTAT_SPRITE_XFLIP;
}
else t->cstat &= ~CSTAT_SPRITE_XFLIP;
t->picnum = RPG + k;
break;
case RPG2:
if (!isRRRA()) goto default_case;
kang = (h->spr.pos - viewVec).Angle();
k = angletorotation2(h->spr.Angles.Yaw, kang);
if (k > 6)
{
k = 12 - k;
t->cstat |= CSTAT_SPRITE_XFLIP;
}
else t->cstat &= ~CSTAT_SPRITE_XFLIP;
t->picnum = RPG2 + k;
break;
case APLAYER:
p = h->PlayerIndex();
@ -638,19 +614,13 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
switch (h->spr.picnum)
{
case RPG2:
case BOATGRENADE:
if (!isRRRA()) break;
[[fallthrough]];
case EXPLOSION2:
case ATOMICHEALTH:
case SAWBLADE:
case CHAINGUN:
case RPG:
case EXPLOSION3:
case COOLEXPLOSION1:
case OWHIP:
case UWHIP:
if (t->picnum == EXPLOSION2)
{
ps[screenpeek].visibility = -127;

View file

@ -157,7 +157,7 @@ void initactorflags_r()
setflag(SFLAG_NOINTERPOLATE, { CRANEPOLE });
setflag(SFLAG_FALLINGFLAMMABLE, { BOX });
setflag(SFLAG_INFLAME, { RADIUSEXPLOSION, RPG, FIRELASER, HYDRENT, DYNAMITE, POWDERKEG, COOLEXPLOSION1, OWHIP, UWHIP });
setflag(SFLAG_INFLAME, { RADIUSEXPLOSION, RPG, FIRELASER, HYDRENT, DYNAMITE, POWDERKEG, VIXENSHOT, OWHIP, UWHIP });
if (isRRRA()) setflag(SFLAG_INFLAME, { RPG2 });
setflag(SFLAG_NOFLOORFIRE, { TREE1, TREE2 });
setflag(SFLAG_HITRADIUS_FLAG1, { BOX, TREE1, TREE2, TIRE });

View file

@ -37,7 +37,6 @@ void movefta();
void clearcameras(player_struct* p);
void RANDOMSCRAP(DDukeActor* i);
void detonate(DDukeActor* i, int explosion);
void rpgexplode(DDukeActor* i, int j, const DVector3& pos, int EXPLOSION2, int EXPLOSIONBOT2, int newextra, int playsound);
void lotsofstuff(DDukeActor* s, int n, int spawntype);
void reactor(DDukeActor* i, int REACTOR, int REACTOR2, int REACTORBURNT, int REACTOR2BURNT, int REACTORSPARK, int REACTOR2SPARK);
void watersplash2(DDukeActor* i);

View file

@ -667,7 +667,7 @@ y(RRTILE2072, 2072)
y(RRTILE2074, 2074)
y(RRTILE2075, 2075)
y(RRTILE2083, 2083)
x(COOLEXPLOSION1, 2095)
x(VIXENSHOT, 2095)
y(RRTILE2097, 2097)
y(RRTILE2121, 2121)
y(RRTILE2122, 2122)
@ -1032,10 +1032,10 @@ y(RRTILE3600, 3600)
y(RRTILE3631, 3631)
y(RRTILE3635, 3635)
y(RRTILE3637, 3637)
y(RRTILE3643, 3643)
y(RRTILE3644, 3644)
y(RRTILE3645, 3645)
y(RRTILE3646, 3646)
x(PICKUPSIDE, 3643)
x(PICKUPFRONT, 3644)
x(PICKUPBACK1, 3645)
x(PICKUPBACK2, 3646)
y(RRTILE3647, 3647)
y(RRTILE3652, 3652)
y(RRTILE3653, 3653)

View file

@ -246,17 +246,9 @@ static void shootweapon(DDukeActor* actor, int p, DVector3 pos, DAngle ang, int
pos.Z -= 4;
double dist = (ps[j].GetActor()->spr.pos.XY() - actor->spr.pos.XY()).Length();
zvel = ((ps[j].GetActor()->getOffsetZ() - pos.Z) * 16) / dist;
if (actor->spr.picnum != BOSS1)
{
zvel += 0.5 - krandf(1);
ang += DAngle22_5 / 4 - randomAngle(22.5 / 2);
}
else
{
zvel += 0.5 - krandf(1);
ang = (ps[j].GetActor()->spr.pos.XY() - pos.XY()).Angle() + DAngle22_5 / 2 - randomAngle(22.5);
}
}
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
hitscan(pos, sectp, DVector3(ang.ToVector() * vel, zvel * 64), hit, CLIPMASK1);
@ -530,7 +522,7 @@ static void shootstuff(DDukeActor* actor, int p, DVector3 pos, DAngle ang, int a
}
double oldzvel = zvel;
double scale = p >= 0? 0.109375 : atwith == COOLEXPLOSION1? 0.125 : 0.28125;
double scale = p >= 0? 0.109375 : atwith == VIXENSHOT? 0.125 : 0.28125;
if (atwith == SHITBALL)
{
@ -598,29 +590,12 @@ static void shootrpg(DDukeActor* actor, int p, DVector3 pos, DAngle ang, int atw
else
setFreeAimVelocity(vel, zvel, ps[p].Angles.getPitchWithView(), 40.5);
if (atwith == RPG)
S_PlayActorSound(RPG_SHOOT, actor);
else if (isRRRA())
{
if (atwith == RPG2)
S_PlayActorSound(244, actor);
else if (atwith == BOATGRENADE)
S_PlayActorSound(94, actor);
}
}
else
{
double x;
int j = findplayer(actor, &x);
ang = (ps[j].GetActor()->opos.XY() - pos.XY()).Angle();
if (actor->spr.picnum == BOSS3)
pos.Z -= 32;
else if (actor->spr.picnum == BOSS2)
{
vel += 8;
pos.Z += 24;
}
double dist = (ps[j].GetActor()->spr.pos.XY() - actor->spr.pos.XY()).Length();
zvel = ((ps[j].GetActor()->getPrevOffsetZ() - pos.Z) * vel) / dist;
@ -631,30 +606,18 @@ static void shootrpg(DDukeActor* actor, int p, DVector3 pos, DAngle ang, int atw
if (p < 0) aimed = nullptr;
if (isRRRA() && atwith == BOATGRENADE)
{
zvel = -10;
vel *= 2;
}
auto offset = (ang + DAngle1 * 61).ToVector() * (1024 / 448.);
auto spawned = CreateActor(sect, pos.plusZ(-1) + offset, atwith, 0, DVector2(0.21875, 0.21875), ang, vel, zvel, actor, 4);
if (!spawned) return;
if (isRRRA())
if (p >= 0)
{
if (atwith == BOATGRENADE)
{
spawned->spr.extra = 10;
spawned->vel.Z = -10;
int snd = spawned->IntVar(NAME_spawnsound);
if (snd > 0) S_PlayActorSound(FSoundID::fromInt(snd), actor);
}
else if (atwith == RPG2)
{
spawned->seek_actor = act90;
spawned->spr.hitag = 0;
fi.lotsofmoney(spawned, (krand() & 3) + 1);
}
}
spawned->spr.extra += (krand() & 7);
if (!(actorflag(spawned, SFLAG2_REFLECTIVE)))
@ -893,7 +856,7 @@ void shoot_r(DDukeActor* actor, int atwith, PClass* cls)
case FIRELASER:
case SHITBALL:
case COOLEXPLOSION1:
case VIXENSHOT:
shootstuff(actor, p, spos, sang, atwith);
return;

View file

@ -874,10 +874,10 @@ void checkhitwall_r(DDukeActor* spr, walltype* wal, const DVector3& pos, int atw
case IRONWHEELSWITCH:
if (isRRRA()) break;
break;
case RRTILE3643:
case RRTILE3643 + 1:
case RRTILE3643 + 2:
case RRTILE3643 + 3:
case PICKUPSIDE:
case PICKUPFRONT:
case PICKUPBACK1:
case PICKUPBACK2:
{
auto sect = wal->nextWall()->nextSector();
DukeSectIterator it(sect);

View file

@ -41,6 +41,8 @@ spawnclasses
5282 = RedneckUfo4
5286 = RedneckUfo5
8192 = RedneckUfoSpawnerToggle
1781 = RedneckChickenArrow
1790 = RedneckBoatGrenade
7636 = DukeGenericDestructible, "OLDPHOTO0", "OLDPHOTO0BROKE", "VENT_BUST"
7638 = DukeGenericDestructible, "OLDPHOTO1", "OLDPHOTO1BROKE", "VENT_BUST"

View file

@ -57,6 +57,10 @@ spawnclasses
1527 = DukeBloodSplat3
1528 = DukeBloodSplat4
3420 = DukeFireLaser
3471 = RedneckOWhip
3475 = RedneckUWhip
2095 = RedneckVixenShot
1774 = RedneckDynamiteArrow
285 = RedneckChickenSpawner1
286 = RedneckChickenSpawner2
@ -205,6 +209,8 @@ tileflag TFLAG_DOORWALL {
}
tileflag TFLAG_BLOCKDOOR {
PICKUPBACK1
PICKUPBACK1
RRTILE1792
RRTILE1801
RRTILE1805
@ -263,8 +269,6 @@ tileflag TFLAG_BLOCKDOOR {
RRTILE3631
RRTILE3635
RRTILE3637
RRTILE3645
RRTILE3646
RRTILE3647
RRTILE3652
RRTILE3653

View file

@ -249,7 +249,7 @@ $conreserve BIKEX_3 240
$conreserve TVSNOW 241
$conreserve WINDLITE 242
$conreserve EXITMENU 243
$conreserve CHKBOWFR 244
$conreserve CHICKENBOW_FIRE 244
$conreserve DSCREM04 245
$conreserve SHRNK_HIT 246
$conreserve CHKBOWEX 247

View file

@ -692,3 +692,191 @@ class DukeFireball : DukeProjectile // WorldTour only
}
//---------------------------------------------------------------------------
//
// These 3 just use the base projectile code...
//
//---------------------------------------------------------------------------
class RedneckUWhip : DukeProjectile
{
default
{
pic "UWHIP";
}
override bool animate(tspritetype tspr)
{
tspr.shade = -127;
return true;
}
}
class RedneckOWhip : RedneckUWhip
{
default
{
pic "OWHIP";
}
}
class RedneckVixenShot : RedneckUWhip // COOLEXPLOSION1
{
default
{
pic "VIXENSHOT";
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class RedneckDynamiteArrow : DukeRPG
{
default
{
pic "RPG";
}
override bool weaponhitsprite_pre(DukeActor targ)
{
if (targ.actorflag2(SFLAG2_TRANFERPALTOJIBS) && targ.pal == 19)
{
self.PlayActorSound("RPG_EXPLODE");
let spawned = self.spawn("DukeExplosion2");
if (spawned)
spawned.pos = oldpos;
return true;
}
return Super.weaponhitsprite_pre(targ);
}
override void posthiteffect(CollisionData coll)
{
self.rpgexplode(coll.type, oldpos, false, -1, "RPG_EXPLODE");
self.Destroy();
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class RedneckChickenArrow : RedneckDynamiteArrow
{
default
{
pic "RPG2";
hitag 0;
}
override void Initialize()
{
SpawnSound = "CHICKENBOW_FIRE";
self.lotsofstuff("RedneckFeather", random(1, 4));
}
override bool premoveeffect()
{
// seeker handling
self.hitag++;
if (self.scale.X >= 0.15625 && self.sector.lotag != ST_2_UNDERWATER)
{
let spawned = self.spawn("DukeSmallSmoke");
if (spawned) spawned.pos.Z += 1;
if (random(0, 15) == 2)
{
self.spawn("RedneckFeather");
}
}
DukeActor ts = self.seek_actor;
if (!ts) return false;
if (ts.extra <= 0)
self.seek_actor = null;
if (self.seek_actor && self.hitag > 5)
{
let ang = (ts.pos - self.pos).Angle();
let ang2 = deltaangle(ang, self.angle);
// this was quite broken in the original code. Fixed so that it seeks properly
if (abs(ang2) < 17.5)
{
self.angle = ang;
}
else if (ang2 > 0)
{
self.angle -= 9;
}
else
self.angle += 9;
if (self.hitag > 180)
if (self.vel.Z <= 0)
self.vel.Z += 200 / 256;
}
return false;
}
override void posthiteffect(CollisionData coll)
{
self.rpgexplode(coll.type, oldpos, false, 150, "CHKBOWEX");
self.Destroy();
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class RedneckBoatGrenade : RedneckDynamiteArrow // RRRA only
{
default
{
pic "BOATGRENADE";
extra 10;
}
override void Initialize()
{
SpawnSound = "MORTAR";
self.vel.Z = -10;
self.vel.X *= 2;
super.Initialize();
}
override bool premoveeffect()
{
if (self.extra)
{
self.vel.Z = -(self.extra * 250/256.); // 250 looks like a typo...
self.extra--;
}
else
self.makeitfall();
return Super.premoveeffect();
}
override void posthiteffect(CollisionData coll)
{
self.rpgexplode(coll.type, oldpos, false, 160, "RPG_EXPLODE");
self.Destroy();
}
}