- scriptified the last two RR projectiles.

These are particularly messy - they have different looks depending on the shooter...
This commit is contained in:
Christoph Oelckers 2022-11-29 21:54:02 +01:00
parent 403141807f
commit 59659bc284
5 changed files with 140 additions and 293 deletions

View file

@ -609,251 +609,6 @@ void movestandables_r(void)
//
//---------------------------------------------------------------------------
static void rabbitguts(DDukeActor* proj)
{
spawnguts(proj, PClass::FindActor("RedneckRabbitGibA"), 2);
spawnguts(proj, PClass::FindActor("RedneckRabbitGibB"), 2);
spawnguts(proj, PClass::FindActor("RedneckRabbitGibC"), 2);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool weaponhitsprite(DDukeActor *proj, DDukeActor *targ, const DVector3 &oldpos)
{
fi.checkhitsprite(targ, proj);
if (targ->isPlayer())
{
int p = targ->PlayerIndex();
S_PlayActorSound(PISTOL_BODYHIT, targ);
if (proj->spr.picnum == SHITBALL)
{
if (isRRRA() && proj->GetOwner() && proj->GetOwner()->spr.picnum == MAMA)
{
rabbitguts(proj);
}
ps[p].Angles.addPitch(DAngle::fromDeg(-14.04));
ps[p].sync.actions |= SB_CENTERVIEW;
if (ps[p].loogcnt == 0)
{
if (!S_CheckActorSoundPlaying(ps[p].GetActor(), DUKE_LONGTERM_PAIN))
S_PlayActorSound(DUKE_LONGTERM_PAIN, ps[p].GetActor());
int j = 3 + (krand() & 3);
ps[p].numloogs = j;
ps[p].loogcnt = 24 * 4;
for (int x = 0; x < j; x++)
{
ps[p].loogie[x].X = krand() % 320;
ps[p].loogie[x].Y = krand() % 200;
}
}
}
}
return false;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool weaponhitwall(DDukeActor *proj, walltype* wal, const DVector3& oldpos)
{
if (isRRRA() && proj->GetOwner() && proj->GetOwner()->spr.picnum == MAMA)
{
rabbitguts(proj);
}
if (proj->spr.picnum != RPG && (!isRRRA() || proj->spr.picnum != RPG2) && proj->spr.picnum != FREEZEBLAST && proj->spr.picnum != SHITBALL && proj->spr.picnum != SHITBALL && (wal->overpicnum == MIRROR || wal->picnum == MIRROR))
{
DAngle walang = wal->delta().Angle();
proj->spr.Angles.Yaw = walang * 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);
if (proj->spr.picnum == SAWBLADE)
{
if (wal->picnum >= PICKUPSIDE && wal->picnum < PICKUPSIDE + 3)
{
proj->Destroy();
}
if (proj->spr.extra <= 0)
{
proj->spr.pos += proj->spr.Angles.Yaw.ToVector() * 8;
auto Owner = proj->GetOwner();
if (!isRRRA() || !Owner || (Owner->spr.picnum != CHEER && Owner->spr.picnum != CHEERSTAYPUT))
{
auto j = spawn(proj, CIRCLESTUCK);
if (j)
{
j->spr.scale = DVector2(0.125, 0.125);
j->spr.cstat = CSTAT_SPRITE_ALIGNMENT_WALL;
j->spr.Angles.Yaw += DAngle90;
j->clipdist = proj->spr.scale.X * tileWidth(proj->spr.picnum) * 0.125;
}
}
proj->Destroy();
return true;
}
if (wal->overpicnum != MIRROR && wal->picnum != MIRROR)
{
proj->spr.extra -= 20;
proj->spr.yint--;
}
DAngle k = wal->delta().Angle();
proj->spr.Angles.Yaw = k * 2 - proj->spr.Angles.Yaw;
return true;
}
}
return false;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
bool weaponhitsector(DDukeActor *proj, const DVector3& oldpos)
{
SetActor(proj, oldpos);
if (isRRRA() && proj->GetOwner() && proj->GetOwner()->spr.picnum == MAMA)
{
rabbitguts(proj);
}
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());
}
return false;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void weaponcommon_r(DDukeActor *proj)
{
double vel = proj->vel.X;
double velz = proj->vel.Z;
int p = -1;
auto oldpos = proj->spr.pos;
getglobalz(proj);
Collision coll;
movesprite_ex(proj, DVector3(proj->spr.Angles.Yaw.ToVector() * vel, velz), CLIPMASK1, coll);
if ((proj->spr.picnum == RPG || (isRRRA() && isIn(proj->spr.picnum, RPG2, BOATGRENADE))) && proj->temp_actor != nullptr)
if ((proj->spr.pos.XY() - proj->temp_actor->spr.pos.XY()).Length() < 16)
coll.setSprite(proj->temp_actor);
if (!proj->insector()) // || (isRR() && proj->sector()->filler == 800))
{
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)
{
coll.setSector(proj->sector());
if (proj->sector()->lotag != 1)
proj->vel.Z += 1/256.;
}
}
if (proj->spr.picnum == SHITBALL) if (proj->vel.Z < 24)
proj->vel.Z += gs.gravity - 112/256.;
if (coll.type != 0)
{
if (coll.type == kHitSprite)
{
if (weaponhitsprite(proj, coll.actor(), oldpos)) return;
}
else if (coll.type == kHitWall)
{
if (weaponhitwall(proj, coll.hitWall, oldpos)) return;
}
else if (coll.type == kHitSector)
{
if (weaponhitsector(proj, oldpos)) return;
}
if (proj->spr.picnum != SHITBALL)
{
if (proj->spr.picnum != FREEZEBLAST && proj->spr.picnum != SAWBLADE)
{
auto spawned = spawn(proj, 1441);
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;
}
}
}
}
}
proj->Destroy();
return;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void moveweapons_r(void)
{
DukeStatIterator it(STAT_PROJECTILE);
@ -873,12 +628,6 @@ void moveweapons_r(void)
switch (proj->spr.picnum)
{
case SAWBLADE:
case SHITBALL:
weaponcommon_r(proj);
continue;
case SHOTSPARK1:
{
double x;

View file

@ -205,15 +205,6 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
case CRYSTALAMMO:
t->shade = int(BobVal(PlayClock << 4) * 16);
break;
case SAWBLADE:
if (OwnerAc && (OwnerAc->spr.picnum == CHEER || OwnerAc->spr.picnum == CHEERSTAYPUT) && isRRRA())
{
t->picnum = CHEERBLADE + ((PlayClock >> 4) & 3);
t->shade = -127;
}
else
t->picnum = SAWBLADE + ((PlayClock >> 4) & 7);
break;
case CHEERBOMB:
if (isRRRA())
{
@ -221,34 +212,6 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
break;
}
else goto default_case;
case SHITBALL:
if (isRRRA() && OwnerAc)
{
if (OwnerAc->spr.picnum == MINION && OwnerAc->spr.pal == 8)
t->picnum = FROGBALL1 + ((PlayClock >> 4) % 6);
else if (OwnerAc->spr.picnum == MINION && OwnerAc->spr.pal == 19)
{
t->picnum = SHITBURN1 + ((PlayClock >> 4) & 3);
t->shade = -127;
}
else if (OwnerAc->spr.picnum == MAMA)
{
kang = (h->spr.pos - viewVec).Angle();
k = angletorotation1(h->spr.Angles.Yaw, kang);
if (k > 4)
{
k = 8 - k;
t->cstat |= CSTAT_SPRITE_XFLIP;
}
else t->cstat &= ~CSTAT_SPRITE_XFLIP;
t->picnum = RABBITBALL + k;
}
else
t->picnum = SHITBALL + ((PlayClock >> 4) & 3);
}
else
t->picnum = SHITBALL + ((PlayClock >> 4) & 3);
break;
case EMPTYBIKE:
if (!isRRRA()) goto default_case;
kang = (h->spr.pos - viewVec).Angle();
@ -618,7 +581,6 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
[[fallthrough]];
case EXPLOSION2:
case ATOMICHEALTH:
case SAWBLADE:
case CHAINGUN:
case EXPLOSION3:
if (t->picnum == EXPLOSION2)

View file

@ -1383,10 +1383,6 @@ y(RRTILE8681, 8681)
y(RRTILE8682, 8682)
y(RRTILE8683, 8683)
y(RRTILE8704, 8704)
x(BOSS1, 4477)
x(BOSS2, 4557)
x(BOSS3, 4607)
x(BOSS4, 4221)
x(BOULDER, 256)
x(BOULDER1, 264)

View file

@ -61,6 +61,8 @@ spawnclasses
3475 = RedneckUWhip
2095 = RedneckVixenShot
1774 = RedneckDynamiteArrow
3390 = RedneckShitBall
3400 = RedneckSawBlade
285 = RedneckChickenSpawner1
286 = RedneckChickenSpawner2

View file

@ -84,6 +84,7 @@ class DukeProjectile : DukeActor
protected bool weaponhitsprite(DukeActor targ)
{
if (self.weaponhitsprite_pre(targ)) return true;
if (!targ.isPlayer()) return false;
return self.weaponhitplayer(targ);
}
@ -880,3 +881,140 @@ class RedneckBoatGrenade : RedneckDynamiteArrow // RRRA only
}
//---------------------------------------------------------------------------
//
// this class is called shitball - but it's not just about throwing shit in the game,
// the entire logic with 4 different looks depending on the shooter is also shit...
//
//---------------------------------------------------------------------------
class RedneckShitBall : DukeSpit
{
default
{
spriteset "SHITBALL", "SHITBALL2", "SHITBALL3", "SHITBALL4",
"FROGBALL1", "FROGBALL2", "FROGBALL3", "FROGBALL4", "FROGBALL5", "FROGBALL6",
"SHITBURN", "SHITBURN2", "SHITBURN3", "SHITBURN4",
"RABBITBALL";
}
private void rabbitguts()
{
self.spawnguts('RedneckRabbitJibA', 2);
self.spawnguts('RedneckRabbitJibB', 2);
self.spawnguts('RedneckRabbitJibC', 2);
}
override bool weaponhitplayer(DukeActor targ)
{
if (ownerActor && ownerActor.actorflag2(SFLAG2_SPAWNRABBITGUTS))
rabbitguts();
return Super.weaponhitplayer(targ);
}
override bool weaponhitwall(walltype wal)
{
self.SetPosition(oldpos);
if (ownerActor && ownerActor.actorflag2(SFLAG2_SPAWNRABBITGUTS))
rabbitguts();
return super.weaponhitwall(wal);
}
override bool weaponhitsector()
{
self.setPosition(oldpos);
if (ownerActor && ownerActor.actorflag2(SFLAG2_SPAWNRABBITGUTS))
rabbitguts();
return super.weaponhitsector();
}
override bool animate(tspritetype tspr)
{
int sprite = ((PlayClock >> 4) & 3);
if (self.ownerActor)
{
let OwnerAc = self.ownerActor;
if (OwnerAc.actorflag2(SFLAG2_TRANFERPALTOJIBS))
{
if (OwnerAc.pal == 8)
{
sprite = 4 + ((PlayClock >> 4) % 6);
}
else if (OwnerAc.pal == 19)
{
sprite = 10 + ((PlayClock >> 4) & 3);
tspr.shade = -127;
}
}
else if (OwnerAc.actorflag2(SFLAG2_SPAWNRABBITGUTS))
{
tspr.clipdist |= TSPR_ROTATE8FRAMES;
sprite = 14;
}
}
return true;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class RedneckSawBlade : DukeProjectile
{
default
{
spriteset "SAWBLADE", "SAWBLADE2", "SAWBLADE3", "SAWBLADE4", "SAWBLADE5", "SAWBLADE6", "SAWBLADE7", "SAWBLADE8",
"CHEERBLADE", "CHEERBLADE2", "CHEERBLADE3", "CHEERBLADE4";
}
override bool weaponhitwall(walltype wal)
{
if (dlevel.wallflags(wal, 0) & Duke.TFLAG_NOCIRCLEREFLECT)
{
self.Destroy();
return true;
}
if (self.extra <= 0)
{
self.pos += self.angle.ToVector() * 8;
let Owner = self.ownerActor;
if (!Owner || !(Owner.actorflag2(SFLAG2_ALTPROJECTILESPRITE))) // depends on the shooter. Urgh...
{
let j = self.spawn("RedneckCircleStuck");
if (j)
{
j.scale = (0.125, 0.125);
j.cstat = CSTAT_SPRITE_ALIGNMENT_WALL;
j.angle += 90;
j.clipdist = self.scale.X * self.spriteWidth() * 0.125;
}
}
self.Destroy();
return true;
}
if (!dlevel.isMirror(wal))
{
self.extra -= 20;
self.yint--;
}
let k = wal.delta().Angle();
self.angle = k * 2 - self.angle;
return true;
}
override bool animate(tspritetype tspr)
{
int frame;
if (!OwnerActor || !(OwnerActor.actorflag2(SFLAG2_ALTPROJECTILESPRITE))) frame = ((PlayClock >> 4) & 7);
else frame = 8 + ((PlayClock >> 4) & 3);
tspr.SetSpritePic(self, frame);
return true;
}
}