Add ring shooter tire grabbers + more player logic

This commit is contained in:
Sally Coolatta 2023-04-12 21:08:45 -04:00
parent d28601fd52
commit 4e7b6f0cc3
7 changed files with 366 additions and 60 deletions

View file

@ -2776,6 +2776,7 @@ void CL_ClearPlayer(INT32 playernum)
P_SetTarget(&players[playernum].hoverhyudoro, NULL); P_SetTarget(&players[playernum].hoverhyudoro, NULL);
P_SetTarget(&players[playernum].stumbleIndicator, NULL); P_SetTarget(&players[playernum].stumbleIndicator, NULL);
P_SetTarget(&players[playernum].sliptideZipIndicator, NULL); P_SetTarget(&players[playernum].sliptideZipIndicator, NULL);
P_SetTarget(&players[playernum].ringShooter, NULL);
} }
// Handle parties. // Handle parties.

View file

@ -505,7 +505,8 @@ struct player_t
UINT32 distancetofinish; UINT32 distancetofinish;
waypoint_t *currentwaypoint; waypoint_t *currentwaypoint;
waypoint_t *nextwaypoint; waypoint_t *nextwaypoint;
respawnvars_t respawn; // Respawn info respawnvars_t respawn; // Respawn info
mobj_t *ringShooter; // DEZ respawner object
tic_t airtime; // Used to track just air time, but has evolved over time into a general "karted" timer. Rename this variable? tic_t airtime; // Used to track just air time, but has evolved over time into a general "karted" timer. Rename this variable?
UINT8 startboost; // (0 to 125) - Boost you get from start of race or respawn drop dash UINT8 startboost; // (0 to 125) - Boost you get from start of race or respawn drop dash

View file

@ -2645,6 +2645,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
P_SetTarget(&players[player].follower, NULL); P_SetTarget(&players[player].follower, NULL);
P_SetTarget(&players[player].awayview.mobj, NULL); P_SetTarget(&players[player].awayview.mobj, NULL);
P_SetTarget(&players[player].stumbleIndicator, NULL); P_SetTarget(&players[player].stumbleIndicator, NULL);
P_SetTarget(&players[player].ringShooter, NULL);
P_SetTarget(&players[player].followmobj, NULL); P_SetTarget(&players[player].followmobj, NULL);
hoverhyudoro = players[player].hoverhyudoro; hoverhyudoro = players[player].hoverhyudoro;

View file

@ -107,8 +107,9 @@ void Obj_BeginDropTargetMorph(mobj_t *target, skincolornum_t color);
boolean Obj_DropTargetMorphThink(mobj_t *morph); boolean Obj_DropTargetMorphThink(mobj_t *morph);
/* Ring Shooter */ /* Ring Shooter */
void Obj_RingShooterThinker(mobj_t *mo); boolean Obj_RingShooterThinker(mobj_t *mo);
void Obj_RingShooterInput(player_t *player); void Obj_RingShooterInput(player_t *player);
void Obj_RingShooterDelete(mobj_t *mo);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"

View file

@ -25,33 +25,76 @@
#include "../k_waypoint.h" #include "../k_waypoint.h"
#include "../r_skins.h" #include "../r_skins.h"
#include "../k_respawn.h" #include "../k_respawn.h"
#include "../lua_hook.h"
#define RS_FUSE_TIME (4*TICRATE) #define RS_FUSE_TIME (4*TICRATE)
static void ActivateRingShooter(mobj_t *mo) #define RS_GRABBER_START (16 << FRACBITS)
{ #define RS_GRABBER_SLIDE (RS_GRABBER_START >> 4)
mobj_t *part = mo->tracer; #define RS_GRABBER_EXTRA (18 << FRACBITS)
while (!P_MobjWasRemoved(part->tracer)) #define RS_KARTED_INC (3)
{
part = part->tracer;
part->renderflags &= ~RF_DONTDRAW;
part->frame += 4;
}
}
#define rs_base_scalespeed(o) ((o)->scalespeed) #define rs_base_scalespeed(o) ((o)->scalespeed)
#define rs_base_scalestate(o) ((o)->threshold) #define rs_base_scalestate(o) ((o)->threshold)
#define rs_base_xscale(o) ((o)->extravalue1) #define rs_base_xscale(o) ((o)->extravalue1)
#define rs_base_yscale(o) ((o)->extravalue2) #define rs_base_yscale(o) ((o)->extravalue2)
#define rs_base_playerid(o) ((o)->lastlook)
#define rs_base_karted(o) ((o)->movecount)
#define rs_base_grabberdist(o) ((o)->movefactor)
#define rs_base_canceled(o) ((o)->cvmem)
#define rs_part_xoffset(o) ((o)->extravalue1) #define rs_part_xoffset(o) ((o)->extravalue1)
#define rs_part_yoffset(o) ((o)->extravalue2) #define rs_part_yoffset(o) ((o)->extravalue2)
static void RemoveRingShooterPointer(mobj_t *base)
{
player_t *player = NULL;
if (rs_base_playerid(base) < 0 || rs_base_playerid(base) >= MAXPLAYERS)
{
// No pointer set
return;
}
// NULL the player's pointer.
player = &players[ rs_base_playerid(base) ];
P_SetTarget(&player->ringShooter, NULL);
// Remove our player ID
rs_base_playerid(base) = -1;
}
static void ChangeRingShooterPointer(mobj_t *base, player_t *player)
{
// Remove existing pointer first.
RemoveRingShooterPointer(base);
if (player == NULL)
{
// Just remove it.
return;
}
// Set new player pointer.
P_SetTarget(&player->ringShooter, base);
// Set new player ID.
rs_base_playerid(base) = (player - players);
}
static void ScalePart(mobj_t *part, mobj_t *base) static void ScalePart(mobj_t *part, mobj_t *base)
{ {
part->spritexscale = rs_base_xscale(base); part->spritexscale = rs_base_xscale(base);
part->spriteyscale = rs_base_yscale(base); part->spriteyscale = rs_base_yscale(base);
if (part->type == MT_TIREGRABBER)
{
part->spritexscale /= 2;
part->spriteyscale /= 2;
}
} }
static void MovePart(mobj_t *part, mobj_t *base, mobj_t *refNipple) static void MovePart(mobj_t *part, mobj_t *base, mobj_t *refNipple)
@ -64,12 +107,43 @@ static void MovePart(mobj_t *part, mobj_t *base, mobj_t *refNipple)
); );
} }
static void ShowHidePart(mobj_t *part, mobj_t *base)
{
part->renderflags = (part->renderflags & ~RF_DONTDRAW) | (base->renderflags & RF_DONTDRAW);
}
static fixed_t GetTireDist(mobj_t *base)
{
return -(RS_GRABBER_EXTRA + rs_base_grabberdist(base));
}
static void MoveTire(mobj_t *part, mobj_t *base)
{
const fixed_t dis = FixedMul(GetTireDist(base), base->scale);
const fixed_t c = FINECOSINE(part->angle >> ANGLETOFINESHIFT);
const fixed_t s = FINESINE(part->angle >> ANGLETOFINESHIFT);
P_MoveOrigin(
part,
base->x + FixedMul(dis, c),
base->y + FixedMul(dis, s),
part->z
);
}
// I've tried to reduce redundancy as much as I can, // I've tried to reduce redundancy as much as I can,
// but check K_SpawnRingShooter if you edit this // but check K_SpawnRingShooter if you edit this
static void UpdateRingShooterParts(mobj_t *mo) static void UpdateRingShooterParts(mobj_t *mo)
{ {
mobj_t *part, *refNipple; mobj_t *part, *refNipple;
part = mo;
while (!P_MobjWasRemoved(part->target))
{
part = part->target;
ScalePart(part, mo);
MoveTire(part, mo);
}
part = mo; part = mo;
while (!P_MobjWasRemoved(part->hprev)) while (!P_MobjWasRemoved(part->hprev))
{ {
@ -92,6 +166,47 @@ static void UpdateRingShooterParts(mobj_t *mo)
ScalePart(part, mo); ScalePart(part, mo);
} }
static void UpdateRingShooterPartsVisibility(mobj_t *mo)
{
mobj_t *part;
part = mo;
while (!P_MobjWasRemoved(part->target))
{
part = part->target;
ShowHidePart(part, mo);
}
part = mo;
while (!P_MobjWasRemoved(part->hprev))
{
part = part->hprev;
ShowHidePart(part, mo);
}
part = mo;
while (!P_MobjWasRemoved(part->hnext))
{
part = part->hnext;
ShowHidePart(part, mo);
}
part = mo->tracer;
ShowHidePart(part, mo);
}
static void ActivateRingShooter(mobj_t *mo)
{
mobj_t *part = mo->tracer;
while (!P_MobjWasRemoved(part->tracer))
{
part = part->tracer;
part->renderflags &= ~RF_DONTDRAW;
part->frame += 4;
}
}
static boolean RingShooterInit(mobj_t *mo) static boolean RingShooterInit(mobj_t *mo)
{ {
if (rs_base_scalestate(mo) == -1) if (rs_base_scalestate(mo) == -1)
@ -129,10 +244,26 @@ static boolean RingShooterInit(mobj_t *mo)
rs_base_xscale(mo) -= rs_base_scalespeed(mo); rs_base_xscale(mo) -= rs_base_scalespeed(mo);
if (rs_base_yscale(mo) >= FRACUNIT) if (rs_base_yscale(mo) >= FRACUNIT)
{ {
rs_base_scalestate(mo) = -1; rs_base_scalestate(mo)++;
rs_base_xscale(mo) = rs_base_yscale(mo) = FRACUNIT; rs_base_xscale(mo) = rs_base_yscale(mo) = FRACUNIT;
}
break;
}
case 3:
{
rs_base_grabberdist(mo) -= RS_GRABBER_SLIDE;
if (rs_base_grabberdist(mo) <= 0)
{
rs_base_scalestate(mo) = -1;
rs_base_grabberdist(mo) = 0;
ActivateRingShooter(mo); ActivateRingShooter(mo);
} }
break;
}
default:
{
rs_base_scalestate(mo) = 0; // fix invalid states
break;
} }
} }
@ -206,13 +337,87 @@ static void RingShooterFlicker(mobj_t *mo)
part->target->frame = (part->target->frame & ~FF_TRANSMASK) | trans; part->target->frame = (part->target->frame & ~FF_TRANSMASK) | trans;
} }
void Obj_RingShooterThinker(mobj_t *mo) boolean Obj_RingShooterThinker(mobj_t *mo)
{ {
if (P_MobjWasRemoved(mo->tracer) || RingShooterInit(mo)) if (RingShooterInit(mo) == true)
return; {
return true;
}
RingShooterCountdown(mo); if (mo->fuse > 0)
RingShooterFlicker(mo); {
mo->fuse--;
if (mo->fuse == 0)
{
P_RemoveMobj(mo);
return false;
}
}
if (rs_base_canceled(mo) != 0)
{
rs_base_karted(mo) += RS_KARTED_INC;
if (P_MobjWasRemoved(mo->tracer) == false)
{
RingShooterCountdown(mo);
RingShooterFlicker(mo);
}
}
if (mo->fuse < TICRATE)
{
if (leveltime & 1)
{
mo->renderflags |= RF_DONTDRAW;
}
else
{
mo->renderflags &= ~RF_DONTDRAW;
}
UpdateRingShooterPartsVisibility(mo);
}
return true;
}
void Obj_RingShooterDelete(mobj_t *mo)
{
mobj_t *part;
RemoveRingShooterPointer(mo);
part = mo->target;
while (P_MobjWasRemoved(part) == false)
{
mobj_t *delete = part;
part = part->target;
P_RemoveMobj(delete);
}
part = mo->hprev;
while (P_MobjWasRemoved(part) == false)
{
mobj_t *delete = part;
part = part->hprev;
P_RemoveMobj(delete);
}
part = mo->hnext;
while (P_MobjWasRemoved(part) == false)
{
mobj_t *delete = part;
part = part->hnext;
P_RemoveMobj(delete);
}
part = mo->tracer;
if (P_MobjWasRemoved(part) == false)
{
P_RemoveMobj(part);
}
} }
static boolean AllowRingShooter(player_t *player) static boolean AllowRingShooter(player_t *player)
@ -254,8 +459,11 @@ static void SpawnRingShooter(player_t *player)
vector2_t offset; vector2_t offset;
SINT8 i; SINT8 i;
rs_base_playerid(base) = -1;
rs_base_karted(base) = -(RS_KARTED_INC * TICRATE); // wait for "3"
rs_base_grabberdist(base) = RS_GRABBER_START;
K_FlipFromObject(base, mo); K_FlipFromObject(base, mo);
P_SetTarget(&base->target, mo);
P_SetScale(base, base->destscale = FixedMul(base->destscale, scale)); P_SetScale(base, base->destscale = FixedMul(base->destscale, scale));
base->angle = mo->angle; base->angle = mo->angle;
base->scalespeed = FRACUNIT/2; base->scalespeed = FRACUNIT/2;
@ -264,10 +472,11 @@ static void SpawnRingShooter(player_t *player)
base->fuse = RS_FUSE_TIME; base->fuse = RS_FUSE_TIME;
// the ring shooter object itself is invisible and acts as the thinker // the ring shooter object itself is invisible and acts as the thinker
// each ring shooter uses three linked lists to keep track of its parts // each ring shooter uses four linked lists to keep track of its parts
// the hprev chain stores the two NIPPLE BARS // the hprev chain stores the two NIPPLE BARS
// the hnext chain stores the four sides of the box // the hnext chain stores the four sides of the box
// the tracer chain stores the screen and the screen layers // the tracer chain stores the screen and the screen layers
// the target chain stores the tire grabbers
// spawn the RING NIPPLES // spawn the RING NIPPLES
part = base; part = base;
@ -343,14 +552,66 @@ static void SpawnRingShooter(player_t *player)
P_SetMobjState(part, S_RINGSHOOTER_NUMBERBACK + i); P_SetMobjState(part, S_RINGSHOOTER_NUMBERBACK + i);
part->renderflags |= RF_DONTDRAW; part->renderflags |= RF_DONTDRAW;
} }
// spawn the grabbers
part = base;
angle = base->angle + ANGLE_45;
for (i = 0; i < 4; i++)
{
const fixed_t dis = GetTireDist(base);
P_SetTarget(
&part->target,
P_SpawnMobjFromMobj(
base,
P_ReturnThrustX(NULL, angle, dis),
P_ReturnThrustY(NULL, angle, dis),
0,
MT_TIREGRABBER
)
);
part = part->target;
P_SetTarget(&part->tracer, base);
angle -= ANGLE_90;
part->angle = angle;
part->extravalue1 = part->extravalue2 = 0;
part->old_spriteyscale = part->spriteyscale = 0;
}
ChangeRingShooterPointer(base, player);
} }
void Obj_RingShooterInput(player_t *player) void Obj_RingShooterInput(player_t *player)
{ {
mobj_t *const base = player->ringShooter;
if (AllowRingShooter(player) == true if (AllowRingShooter(player) == true
&& (player->cmd.buttons & BT_RESPAWN) == BT_RESPAWN && (player->cmd.buttons & BT_RESPAWN) == BT_RESPAWN)
&& (player->oldcmd.buttons & BT_RESPAWN) == 0)
{ {
SpawnRingShooter(player); if (P_MobjWasRemoved(base) == true)
{
SpawnRingShooter(player);
return;
}
if (rs_base_canceled(base) != 0)
{
if (base->fuse < TICRATE)
{
base->renderflags &= ~RF_DONTDRAW;
UpdateRingShooterPartsVisibility(base);
}
base->fuse = RS_FUSE_TIME;
}
}
else if (P_MobjWasRemoved(base) == false)
{
if (rs_base_scalestate(base) != -1)
{
// We released during the intro animation.
// Cancel it entirely.
rs_base_canceled(base) = 1;
}
} }
} }

View file

@ -6642,7 +6642,10 @@ static void P_MobjSceneryThink(mobj_t *mobj)
} }
break; break;
case MT_RINGSHOOTER: case MT_RINGSHOOTER:
Obj_RingShooterThinker(mobj); if (Obj_RingShooterThinker(mobj) == false)
{
return;
}
break; break;
case MT_SPINDASHWIND: case MT_SPINDASHWIND:
case MT_DRIFTELECTRICSPARK: case MT_DRIFTELECTRICSPARK:
@ -11143,26 +11146,10 @@ void P_RemoveMobj(mobj_t *mobj)
iquetail = (iquetail+1)&(ITEMQUESIZE-1); iquetail = (iquetail+1)&(ITEMQUESIZE-1);
} }
if (mobj->type == MT_KARMAHITBOX) // Remove linked list objects for certain types
{
mobj_t *cur = mobj->hnext;
while (cur && !P_MobjWasRemoved(cur))
{
mobj_t *prev = cur; // Kind of a dumb var, but we need to set cur before we remove the mobj
cur = cur->hnext;
P_RemoveMobj(prev);
}
}
if (mobj->type == MT_OVERLAY)
P_RemoveOverlay(mobj);
if (mobj->type == MT_SPB)
spbplace = -1;
if (P_IsTrackerType(mobj->type)) if (P_IsTrackerType(mobj->type))
{
P_RemoveTracker(mobj); P_RemoveTracker(mobj);
}
if (mobj->player && mobj->player->followmobj) if (mobj->player && mobj->player->followmobj)
{ {
@ -11170,19 +11157,56 @@ void P_RemoveMobj(mobj_t *mobj)
P_SetTarget(&mobj->player->followmobj, NULL); P_SetTarget(&mobj->player->followmobj, NULL);
} }
if (mobj->type == MT_SHRINK_POHBEE) // Remove linked list objects for certain types
switch (mobj->type)
{ {
Obj_PohbeeRemoved(mobj); case MT_KARMAHITBOX:
} {
mobj_t *cur = mobj->hnext;
if (mobj->type == MT_SHRINK_GUN) while (cur && !P_MobjWasRemoved(cur))
{ {
Obj_ShrinkGunRemoved(mobj); mobj_t *prev = cur; // Kind of a dumb var, but we need to set cur before we remove the mobj
} cur = cur->hnext;
P_RemoveMobj(prev);
}
if (mobj->type == MT_SPECIAL_UFO_PIECE) break;
{ }
Obj_UFOPieceRemoved(mobj); case MT_OVERLAY:
{
P_RemoveOverlay(mobj);
break;
}
case MT_SPB:
{
spbplace = -1;
break;
}
case MT_SHRINK_POHBEE:
{
Obj_PohbeeRemoved(mobj);
break;
}
case MT_SHRINK_GUN:
{
Obj_ShrinkGunRemoved(mobj);
break;
}
case MT_SPECIAL_UFO_PIECE:
{
Obj_UFOPieceRemoved(mobj);
break;
}
case MT_RINGSHOOTER:
{
Obj_RingShooterDelete(mobj);
break;
}
default:
{
break;
}
} }
mobj->health = 0; // Just because mobj->health = 0; // Just because

View file

@ -63,14 +63,15 @@ savedata_t savedata;
// than an UINT16 // than an UINT16
typedef enum typedef enum
{ {
AWAYVIEW = 0x01, AWAYVIEW = 0x0001,
FOLLOWITEM = 0x02, FOLLOWITEM = 0x0002,
FOLLOWER = 0x04, FOLLOWER = 0x0004,
SKYBOXVIEW = 0x08, SKYBOXVIEW = 0x0008,
SKYBOXCENTER = 0x10, SKYBOXCENTER = 0x0010,
HOVERHYUDORO = 0x20, HOVERHYUDORO = 0x0020,
STUMBLE = 0x40, STUMBLE = 0x0040,
SLIPTIDEZIP = 0x80 SLIPTIDEZIP = 0x0080,
RINGSHOOTER = 0x0100
} player_saveflags; } player_saveflags;
static inline void P_ArchivePlayer(savebuffer_t *save) static inline void P_ArchivePlayer(savebuffer_t *save)
@ -217,6 +218,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
if (players[i].sliptideZipIndicator) if (players[i].sliptideZipIndicator)
flags |= SLIPTIDEZIP; flags |= SLIPTIDEZIP;
if (players[i].ringShooter)
flags |= RINGSHOOTER;
WRITEUINT16(save->p, flags); WRITEUINT16(save->p, flags);
if (flags & SKYBOXVIEW) if (flags & SKYBOXVIEW)
@ -240,6 +244,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
if (flags & SLIPTIDEZIP) if (flags & SLIPTIDEZIP)
WRITEUINT32(save->p, players[i].sliptideZipIndicator->mobjnum); WRITEUINT32(save->p, players[i].sliptideZipIndicator->mobjnum);
if (flags & RINGSHOOTER)
WRITEUINT32(save->p, players[i].ringShooter->mobjnum);
WRITEUINT32(save->p, (UINT32)players[i].followitem); WRITEUINT32(save->p, (UINT32)players[i].followitem);
WRITEUINT32(save->p, players[i].charflags); WRITEUINT32(save->p, players[i].charflags);
@ -613,6 +620,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
if (flags & SLIPTIDEZIP) if (flags & SLIPTIDEZIP)
players[i].sliptideZipIndicator = (mobj_t *)(size_t)READUINT32(save->p); players[i].sliptideZipIndicator = (mobj_t *)(size_t)READUINT32(save->p);
if (flags & RINGSHOOTER)
players[i].ringShooter = (mobj_t *)(size_t)READUINT32(save->p);
players[i].followitem = (mobjtype_t)READUINT32(save->p); players[i].followitem = (mobjtype_t)READUINT32(save->p);
//SetPlayerSkinByNum(i, players[i].skin); //SetPlayerSkinByNum(i, players[i].skin);
@ -4823,6 +4833,13 @@ static void P_RelinkPointers(void)
if (!P_SetTarget(&players[i].sliptideZipIndicator, P_FindNewPosition(temp))) if (!P_SetTarget(&players[i].sliptideZipIndicator, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "sliptideZipIndicator not found on player %d\n", i); CONS_Debug(DBG_GAMELOGIC, "sliptideZipIndicator not found on player %d\n", i);
} }
if (players[i].ringShooter)
{
temp = (UINT32)(size_t)players[i].ringShooter;
players[i].ringShooter = NULL;
if (!P_SetTarget(&players[i].ringShooter, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "ringShooter not found on player %d\n", i);
}
} }
} }