mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Servant Hand
- Points in the direction of the best waypoint to take - Vwoops in and out like a drop target squash-n-stretch - Shows WRONG WAY only on debugwaypoints - Flexible enough to be used for custom purposes and other gametypes, the only caveat being if those gametypes use GTR_CIRCUIT conflicting with the other purpose of PF_WRONGWAY
This commit is contained in:
parent
7d82d8cd0c
commit
1fee9f65fb
10 changed files with 198 additions and 7 deletions
|
|
@ -744,10 +744,14 @@ struct player_t
|
|||
mobj_t *stumbleIndicator;
|
||||
mobj_t *sliptideZipIndicator;
|
||||
mobj_t *whip;
|
||||
mobj_t *hand;
|
||||
|
||||
UINT8 instaShieldCooldown;
|
||||
UINT8 guardCooldown;
|
||||
|
||||
UINT8 handtimer;
|
||||
angle_t besthanddirection;
|
||||
|
||||
INT16 incontrol; // -1 to -175 when spinning out or tumbling, 1 to 175 when not. Use to check for combo hits or emergency inputs.
|
||||
|
||||
boolean markedfordeath;
|
||||
|
|
|
|||
|
|
@ -3291,6 +3291,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_BLOCKRING",
|
||||
"S_BLOCKBODY",
|
||||
|
||||
"S_SERVANTHAND",
|
||||
|
||||
// Signpost sparkles
|
||||
"S_SIGNSPARK1",
|
||||
"S_SIGNSPARK2",
|
||||
|
|
@ -5337,6 +5339,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_BLOCKRING",
|
||||
"MT_BLOCKBODY",
|
||||
|
||||
"MT_SERVANTHAND",
|
||||
|
||||
"MT_SIGNSPARKLE",
|
||||
|
||||
"MT_FASTLINE",
|
||||
|
|
|
|||
|
|
@ -2689,6 +2689,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
P_SetTarget(&players[player].awayview.mobj, NULL);
|
||||
P_SetTarget(&players[player].stumbleIndicator, NULL);
|
||||
P_SetTarget(&players[player].whip, NULL);
|
||||
P_SetTarget(&players[player].hand, NULL);
|
||||
P_SetTarget(&players[player].ringShooter, NULL);
|
||||
P_SetTarget(&players[player].followmobj, NULL);
|
||||
|
||||
|
|
|
|||
31
src/info.c
31
src/info.c
|
|
@ -559,6 +559,8 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"GRNG", // Guard ring
|
||||
"GBDY", // Guard body
|
||||
|
||||
"DHND", // Servant Hand
|
||||
|
||||
"WIPD", // Wipeout dust trail
|
||||
"DRIF", // Drift Sparks
|
||||
"BDRF", // Brake drift sparks
|
||||
|
|
@ -3956,6 +3958,8 @@ state_t states[NUMSTATES] =
|
|||
{SPR_GRNG, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_BLOCKRING
|
||||
{SPR_GBDY, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY
|
||||
|
||||
{SPR_DHND, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SERVANTHAND
|
||||
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_SIGNSPARK4}, // S_SIGNSPARK3
|
||||
|
|
@ -22760,6 +22764,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SERVANTHAND
|
||||
-1, // doomednum
|
||||
S_SERVANTHAND, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
40*FRACUNIT, // radius
|
||||
40*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SIGNSPARKLE
|
||||
-1, // doomednum
|
||||
|
|
|
|||
|
|
@ -1112,6 +1112,8 @@ typedef enum sprite
|
|||
SPR_GRNG, // Guard ring
|
||||
SPR_GBDY, // Guard body
|
||||
|
||||
SPR_DHND, // Servant Hand
|
||||
|
||||
SPR_WIPD, // Wipeout dust trail
|
||||
SPR_DRIF, // Drift Sparks
|
||||
SPR_BDRF, // Brake drift sparks
|
||||
|
|
@ -4367,6 +4369,8 @@ typedef enum state
|
|||
S_BLOCKRING,
|
||||
S_BLOCKBODY,
|
||||
|
||||
S_SERVANTHAND,
|
||||
|
||||
// Signpost sparkles
|
||||
S_SIGNSPARK1,
|
||||
S_SIGNSPARK2,
|
||||
|
|
@ -6448,6 +6452,8 @@ typedef enum mobj_type
|
|||
MT_BLOCKRING,
|
||||
MT_BLOCKBODY,
|
||||
|
||||
MT_SERVANTHAND,
|
||||
|
||||
MT_SIGNSPARKLE,
|
||||
|
||||
MT_FASTLINE,
|
||||
|
|
|
|||
|
|
@ -5005,7 +5005,7 @@ static void K_DrawWaypointDebugger(void)
|
|||
}
|
||||
|
||||
V_DrawString(8, 156, 0, va("Current Waypoint ID: %d", K_GetWaypointID(stplyr->currentwaypoint)));
|
||||
V_DrawString(8, 166, 0, va("Next Waypoint ID: %d", K_GetWaypointID(stplyr->nextwaypoint)));
|
||||
V_DrawString(8, 166, 0, va("Next Waypoint ID: %d%s", K_GetWaypointID(stplyr->nextwaypoint), ((stplyr->pflags & PF_WRONGWAY) ? " (WRONG WAY)" : "")));
|
||||
V_DrawString(8, 176, 0, va("Finishline Distance: %d", stplyr->distancetofinish));
|
||||
|
||||
if (numstarposts > 0)
|
||||
|
|
@ -5365,11 +5365,6 @@ void K_drawKartHUD(void)
|
|||
// Draw FREE PLAY.
|
||||
K_drawKartFreePlay();
|
||||
|
||||
if (r_splitscreen == 0 && (stplyr->pflags & PF_WRONGWAY) && ((leveltime / 8) & 1))
|
||||
{
|
||||
V_DrawCenteredString(BASEVIDWIDTH>>1, 176, V_REDMAP|V_SNAPTOBOTTOM, "WRONG WAY");
|
||||
}
|
||||
|
||||
if ((netgame || cv_mindelay.value) && r_splitscreen && Playing())
|
||||
{
|
||||
K_drawMiniPing();
|
||||
|
|
|
|||
110
src/k_kart.c
110
src/k_kart.c
|
|
@ -8275,9 +8275,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
player->tripwireState = TRIPSTATE_NONE;
|
||||
}
|
||||
|
||||
if (player->hand && P_MobjWasRemoved(player->hand))
|
||||
P_SetTarget(&player->hand, NULL);
|
||||
|
||||
if (player->spectator == false)
|
||||
{
|
||||
K_KartEbrakeVisuals(player);
|
||||
|
||||
K_KartServantHandVisuals(player);
|
||||
}
|
||||
|
||||
if (K_GetKartButtons(player) & BT_BRAKE &&
|
||||
|
|
@ -8596,6 +8601,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
|||
{
|
||||
angle_t nextbestdelta = ANGLE_90;
|
||||
angle_t nextbestmomdelta = ANGLE_90;
|
||||
angle_t nextbestanydelta = ANGLE_MAX;
|
||||
size_t i = 0U;
|
||||
|
||||
if ((waypoint->nextwaypoints != NULL) && (waypoint->numnextwaypoints > 0U))
|
||||
|
|
@ -8637,8 +8643,14 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
|||
momdelta = InvAngle(momdelta);
|
||||
}
|
||||
|
||||
if (angledelta < nextbestdelta || momdelta < nextbestmomdelta)
|
||||
if (angledelta < nextbestanydelta || momdelta < nextbestanydelta)
|
||||
{
|
||||
nextbestanydelta = min(angledelta, momdelta);
|
||||
player->besthanddirection = angletowaypoint;
|
||||
|
||||
if (nextbestanydelta >= ANGLE_90)
|
||||
continue;
|
||||
|
||||
// Wanted to use a next waypoint, so remove WRONG WAY flag.
|
||||
// Done here instead of when set, because of finish line
|
||||
// hacks meaning we might not actually use this one, but
|
||||
|
|
@ -10158,6 +10170,102 @@ void K_KartEbrakeVisuals(player_t *p)
|
|||
}
|
||||
}
|
||||
|
||||
void K_KartServantHandVisuals(player_t *player)
|
||||
{
|
||||
if (player->pflags & PF_WRONGWAY)
|
||||
{
|
||||
if (player->handtimer < TICRATE)
|
||||
{
|
||||
player->handtimer++;
|
||||
if (player->hand == NULL && player->handtimer == TICRATE)
|
||||
{
|
||||
mobj_t *hand = P_SpawnMobj(
|
||||
player->mo->x,
|
||||
player->mo->y,
|
||||
player->mo->z + player->mo->height + 30*mapobjectscale,
|
||||
MT_SERVANTHAND
|
||||
);
|
||||
|
||||
if (hand)
|
||||
{
|
||||
K_FlipFromObject(hand, player->mo);
|
||||
hand->old_z = hand->z;
|
||||
|
||||
P_SetTarget(&hand->target, player->mo);
|
||||
P_SetTarget(&player->hand, hand);
|
||||
|
||||
hand->fuse = 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (player->hand)
|
||||
{
|
||||
player->hand->destscale = mapobjectscale;
|
||||
}
|
||||
}
|
||||
else if (player->handtimer != 0)
|
||||
{
|
||||
player->handtimer--;
|
||||
}
|
||||
|
||||
if (player->hand)
|
||||
{
|
||||
const fixed_t handpokespeed = 4;
|
||||
const fixed_t looping = handpokespeed - abs((player->hand->threshold % (handpokespeed*2)) - handpokespeed);
|
||||
fixed_t xoffs = 0, yoffs = 0;
|
||||
|
||||
player->hand->color = player->skincolor;
|
||||
player->hand->angle = player->besthanddirection;
|
||||
|
||||
if (player->hand->fuse != 0)
|
||||
{
|
||||
;
|
||||
}
|
||||
else if (looping != 0)
|
||||
{
|
||||
xoffs = FixedMul(2 * looping * mapobjectscale, FINECOSINE(player->hand->angle >> ANGLETOFINESHIFT)),
|
||||
yoffs = FixedMul(2 * looping * mapobjectscale, FINESINE(player->hand->angle >> ANGLETOFINESHIFT)),
|
||||
|
||||
player->hand->threshold++;
|
||||
}
|
||||
else if (player->handtimer == 0)
|
||||
{
|
||||
player->hand->fuse = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->hand->threshold++;
|
||||
}
|
||||
|
||||
if (player->hand->fuse != 0)
|
||||
{
|
||||
if ((player->hand->fuse > 4) ^ (player->handtimer < TICRATE/2))
|
||||
{
|
||||
player->hand->spritexscale = FRACUNIT/3;
|
||||
player->hand->spriteyscale = 3*FRACUNIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->hand->spritexscale = 2*FRACUNIT;
|
||||
player->hand->spriteyscale = FRACUNIT/2;
|
||||
}
|
||||
}
|
||||
|
||||
P_MoveOrigin(player->hand,
|
||||
player->mo->x + xoffs,
|
||||
player->mo->y + yoffs,
|
||||
player->mo->z + player->mo->height + 30*mapobjectscale
|
||||
);
|
||||
K_FlipFromObject(player->hand, player->mo);
|
||||
|
||||
player->hand->sprzoff = player->mo->sprzoff;
|
||||
|
||||
player->hand->renderflags &= ~RF_DONTDRAW;
|
||||
player->hand->renderflags |= (RF_DONTDRAW & ~K_GetPlayerDontDrawFlag(player));
|
||||
}
|
||||
}
|
||||
|
||||
static void K_KartSpindashDust(mobj_t *parent)
|
||||
{
|
||||
fixed_t rad = FixedDiv(FixedHypot(parent->radius, parent->radius), parent->scale);
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ UINT8 K_GetInvincibilityItemFrame(void);
|
|||
UINT8 K_GetOrbinautItemFrame(UINT8 count);
|
||||
boolean K_IsSPBInGame(void);
|
||||
void K_KartEbrakeVisuals(player_t *p);
|
||||
void K_KartServantHandVisuals(player_t *player);
|
||||
void K_HandleDirectionalInfluence(player_t *player);
|
||||
fixed_t K_DefaultPlayerRadius(player_t *player);
|
||||
|
||||
|
|
|
|||
16
src/p_mobj.c
16
src/p_mobj.c
|
|
@ -9776,6 +9776,22 @@ static boolean P_FuseThink(mobj_t *mobj)
|
|||
Obj_SPBExplode(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_SERVANTHAND:
|
||||
{
|
||||
if (!mobj->target
|
||||
|| P_MobjWasRemoved(mobj->target)
|
||||
|| !mobj->target->player
|
||||
|| mobj->target->player->handtimer == 0)
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return false;
|
||||
}
|
||||
|
||||
mobj->spritexscale = FRACUNIT;
|
||||
mobj->spriteyscale = FRACUNIT;
|
||||
|
||||
break;
|
||||
}
|
||||
case MT_PLAYER:
|
||||
break; // don't remove
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ typedef enum
|
|||
SLIPTIDEZIP = 0x0080,
|
||||
RINGSHOOTER = 0x0100,
|
||||
WHIP = 0x0200,
|
||||
HAND = 0x0400,
|
||||
} player_saveflags;
|
||||
|
||||
static inline void P_ArchivePlayer(savebuffer_t *save)
|
||||
|
|
@ -229,6 +230,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
if (players[i].whip)
|
||||
flags |= WHIP;
|
||||
|
||||
if (players[i].hand)
|
||||
flags |= HAND;
|
||||
|
||||
if (players[i].ringShooter)
|
||||
flags |= RINGSHOOTER;
|
||||
|
||||
|
|
@ -258,6 +262,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
if (flags & WHIP)
|
||||
WRITEUINT32(save->p, players[i].whip->mobjnum);
|
||||
|
||||
if (flags & HAND)
|
||||
WRITEUINT32(save->p, players[i].hand->mobjnum);
|
||||
|
||||
if (flags & RINGSHOOTER)
|
||||
WRITEUINT32(save->p, players[i].ringShooter->mobjnum);
|
||||
|
||||
|
|
@ -429,6 +436,10 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
|
||||
WRITEUINT8(save->p, players[i].instaShieldCooldown);
|
||||
WRITEUINT8(save->p, players[i].guardCooldown);
|
||||
|
||||
WRITEUINT8(save->p, players[i].handtimer);
|
||||
WRITEANGLE(save->p, players[i].besthanddirection);
|
||||
|
||||
WRITEINT16(save->p, players[i].incontrol);
|
||||
|
||||
WRITEUINT8(save->p, players[i].markedfordeath);
|
||||
|
|
@ -652,6 +663,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
if (flags & WHIP)
|
||||
players[i].whip = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
|
||||
if (flags & HAND)
|
||||
players[i].hand = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
|
||||
if (flags & RINGSHOOTER)
|
||||
players[i].ringShooter = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
|
||||
|
|
@ -824,6 +838,10 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
|
||||
players[i].instaShieldCooldown = READUINT8(save->p);
|
||||
players[i].guardCooldown = READUINT8(save->p);
|
||||
|
||||
players[i].handtimer = READUINT8(save->p);
|
||||
players[i].besthanddirection = READANGLE(save->p);
|
||||
|
||||
players[i].incontrol = READINT16(save->p);
|
||||
|
||||
players[i].markedfordeath = READUINT8(save->p);
|
||||
|
|
@ -5136,6 +5154,13 @@ static void P_RelinkPointers(void)
|
|||
if (!P_SetTarget(&players[i].whip, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "whip not found on player %d\n", i);
|
||||
}
|
||||
if (players[i].hand)
|
||||
{
|
||||
temp = (UINT32)(size_t)players[i].hand;
|
||||
players[i].hand = NULL;
|
||||
if (!P_SetTarget(&players[i].hand, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "hand not found on player %d\n", i);
|
||||
}
|
||||
if (players[i].ringShooter)
|
||||
{
|
||||
temp = (UINT32)(size_t)players[i].ringShooter;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue