mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-01-11 01:02:16 +00:00
Podium cutscene basics
- Bots follow a slightly more strict path via waypoints - Bots decide their starting waypoint path depending on their position. (The 1st place winner will start by chasing waypoint ID 1, etc) - The map used for podium sequence can be decided via `PodiumMap = x` in MainCfg. TODO: - Camera work - Add Lose / Win animation states when stopping at final waypoint - Adjust physics so that the bots can follow the path more strictly in this mode - Actually go to it after GP
This commit is contained in:
parent
9f46c705f0
commit
4a8dd02320
9 changed files with 218 additions and 1 deletions
|
|
@ -2842,6 +2842,10 @@ void readmaincfg(MYFILE *f, boolean mainfile)
|
|||
{
|
||||
tutorialmap = Z_StrDup(word2);
|
||||
}
|
||||
else if (fastcmp(word, "PODIUMMAP"))
|
||||
{
|
||||
podiummap = Z_StrDup(word2);
|
||||
}
|
||||
else
|
||||
deh_warning("Maincfg: unknown word '%s'", word);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,6 +210,8 @@ extern char * bootmap; //bootmap for loading a map on startup
|
|||
extern char * tutorialmap; // map to load for tutorial
|
||||
extern boolean tutorialmode; // are we in a tutorial right now?
|
||||
|
||||
extern char * podiummap; // map to load for podium
|
||||
|
||||
extern boolean looptitle;
|
||||
|
||||
// CTF colors.
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ char * bootmap = NULL; //bootmap for loading a map on startup
|
|||
char * tutorialmap = NULL; // map to load for tutorial
|
||||
boolean tutorialmode = false; // are we in a tutorial right now?
|
||||
|
||||
char * podiummap = NULL; // map to load for podium
|
||||
|
||||
boolean looptitle = true;
|
||||
|
||||
UINT16 skincolor_redteam = SKINCOLOR_RED;
|
||||
|
|
|
|||
66
src/k_bot.c
66
src/k_bot.c
|
|
@ -261,6 +261,9 @@ void K_UpdateMatchRaceBots(void)
|
|||
--------------------------------------------------*/
|
||||
boolean K_PlayerUsesBotMovement(player_t *player)
|
||||
{
|
||||
if (K_PodiumSequence() == true)
|
||||
return true;
|
||||
|
||||
if (player->exiting)
|
||||
return true;
|
||||
|
||||
|
|
@ -1264,6 +1267,54 @@ static INT32 K_HandleBotReverse(player_t *player, ticcmd_t *cmd, botprediction_t
|
|||
return turnamt;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_BotPodiumTurning(player_t *player, ticcmd_t *cmd)
|
||||
|
||||
Calculates bot turning for the podium cutscene.
|
||||
--------------------------------------------------*/
|
||||
static void K_BotPodiumTurning(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
const angle_t destAngle = R_PointToAngle2(
|
||||
player->mo->x, player->mo->y,
|
||||
player->currentwaypoint->mobj->x, player->currentwaypoint->mobj->y
|
||||
);
|
||||
const INT32 delta = AngleDeltaSigned(destAngle, player->mo->angle);
|
||||
const INT16 handling = K_GetKartTurnValue(player, KART_FULLTURN);
|
||||
fixed_t mul = FixedDiv(delta, (angle_t)(handling << TICCMD_REDUCE));
|
||||
|
||||
if (mul > FRACUNIT)
|
||||
{
|
||||
mul = FRACUNIT;
|
||||
}
|
||||
|
||||
if (mul < -FRACUNIT)
|
||||
{
|
||||
mul = -FRACUNIT;
|
||||
}
|
||||
|
||||
cmd->turning = FixedMul(mul, KART_FULLTURN);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_BuildBotPodiumTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
|
||||
Calculates all bot movement for the podium cutscene.
|
||||
--------------------------------------------------*/
|
||||
static void K_BuildBotPodiumTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
if (player->currentwaypoint == NULL)
|
||||
{
|
||||
// We've reached the end of our path.
|
||||
// Simply stop moving.
|
||||
return;
|
||||
}
|
||||
|
||||
cmd->forwardmove = MAXPLMOVE;
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
|
||||
K_BotPodiumTurning(player, cmd);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
|
||||
|
|
@ -1294,6 +1345,12 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
return;
|
||||
}
|
||||
|
||||
if (K_PodiumSequence() == true)
|
||||
{
|
||||
K_BuildBotPodiumTiccmd(player, cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(gametyperules & GTR_BOTS) // No bot behaviors
|
||||
|| K_GetNumWaypoints() == 0 // No waypoints
|
||||
|| leveltime <= introtime // During intro camera
|
||||
|
|
@ -1556,12 +1613,21 @@ void K_UpdateBotGameplayVars(player_t *player)
|
|||
{
|
||||
const line_t *botController;
|
||||
|
||||
player->botvars.controller = UINT16_MAX;
|
||||
player->botvars.rubberband = FRACUNIT;
|
||||
|
||||
if (gamestate != GS_LEVEL || !player->mo)
|
||||
{
|
||||
// Not in the level.
|
||||
return;
|
||||
}
|
||||
|
||||
if (K_PodiumSequence() == true)
|
||||
{
|
||||
// We don't want these during podium.
|
||||
return;
|
||||
}
|
||||
|
||||
botController = K_FindBotController(player->mo);
|
||||
|
||||
player->botvars.controller = botController ? (botController - lines) : UINT16_MAX;
|
||||
|
|
|
|||
101
src/k_kart.c
101
src/k_kart.c
|
|
@ -51,6 +51,19 @@
|
|||
// comeback is Battle Mode's karma comeback, also bool
|
||||
// mapreset is set when enough players fill an empty server
|
||||
|
||||
boolean K_PodiumSequence(void)
|
||||
{
|
||||
// FIXME: Cache so we don't have to iterate all map headers every time
|
||||
INT32 podiumMapNum = nummapheaders;
|
||||
|
||||
if (podiummap && ((podiumMapNum = G_MapNumber(podiummap)) < nummapheaders))
|
||||
{
|
||||
return (gamemap == podiumMapNum+1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean K_IsDuelItem(mobjtype_t type)
|
||||
{
|
||||
switch (type)
|
||||
|
|
@ -354,6 +367,12 @@ boolean K_IsPlayerLosing(player_t *player)
|
|||
INT32 winningpos = 1;
|
||||
UINT8 i, pcount = 0;
|
||||
|
||||
if (K_PodiumSequence() == true)
|
||||
{
|
||||
// Need to be in top 3 to win.
|
||||
return (player->position > 3);
|
||||
}
|
||||
|
||||
if (player->pflags & PF_NOCONTEST)
|
||||
return true;
|
||||
|
||||
|
|
@ -8449,6 +8468,59 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
|||
return bestwaypoint;
|
||||
}
|
||||
|
||||
static void K_UpdatePodiumWaypoint(player_t *const player, waypoint_t *const waypoint)
|
||||
{
|
||||
// Set the new waypoint.
|
||||
player->currentwaypoint = waypoint;
|
||||
|
||||
if ((waypoint == NULL)
|
||||
|| (waypoint->nextwaypoints == NULL)
|
||||
|| (waypoint->numnextwaypoints == 0U))
|
||||
{
|
||||
// No waypoint, or no next waypoint.
|
||||
player->nextwaypoint = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Simply use the first available next waypoint.
|
||||
// No need for split paths in these cutscenes.
|
||||
player->nextwaypoint = waypoint->nextwaypoints[0];
|
||||
}
|
||||
|
||||
static void K_UpdatePodiumWaypoints(player_t *const player)
|
||||
{
|
||||
if ((player != NULL) && (player->mo != NULL))
|
||||
{
|
||||
if ((player->currentwaypoint == NULL)
|
||||
&& (player->position > 0 && player->position <= MAXPLAYERS)
|
||||
&& (leveltime <= 2))
|
||||
{
|
||||
// Initialize our first waypoint to the one that
|
||||
// matches our position.
|
||||
K_UpdatePodiumWaypoint(player, K_GetWaypointFromID(player->position));
|
||||
}
|
||||
|
||||
if (player->currentwaypoint != NULL)
|
||||
{
|
||||
const fixed_t xydist = P_AproxDistance(
|
||||
player->mo->x - player->currentwaypoint->mobj->x,
|
||||
player->mo->y - player->currentwaypoint->mobj->y
|
||||
);
|
||||
const fixed_t xyzdist = P_AproxDistance(
|
||||
xydist,
|
||||
player->mo->z - player->currentwaypoint->mobj->z
|
||||
);
|
||||
//const fixed_t speed = P_AproxDistance(player->mo->momx, player->mo->momy);
|
||||
|
||||
if (xyzdist <= player->mo->radius + player->currentwaypoint->mobj->radius)
|
||||
{
|
||||
// Reached waypoint, go to the next waypoint.
|
||||
K_UpdatePodiumWaypoint(player, player->nextwaypoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_UpdateDistanceFromFinishLine(player_t *const player)
|
||||
|
||||
|
|
@ -8462,6 +8534,12 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
|||
--------------------------------------------------*/
|
||||
void K_UpdateDistanceFromFinishLine(player_t *const player)
|
||||
{
|
||||
if (K_PodiumSequence() == true)
|
||||
{
|
||||
K_UpdatePodiumWaypoints(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((player != NULL) && (player->mo != NULL))
|
||||
{
|
||||
waypoint_t *finishline = K_GetFinishLineWaypoint();
|
||||
|
|
@ -9261,7 +9339,28 @@ void K_KartUpdatePosition(player_t *player)
|
|||
|
||||
realplayers++;
|
||||
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
if (K_PodiumSequence() == true)
|
||||
{
|
||||
if (players[i].score > player->score)
|
||||
{
|
||||
// Final score is the important part.
|
||||
position++;
|
||||
}
|
||||
else if (players[i].score == player->score)
|
||||
{
|
||||
if (players[i].bot == false && player->bot == true)
|
||||
{
|
||||
// Bots are never as important as players.
|
||||
position++;
|
||||
}
|
||||
else if (i < player - players)
|
||||
{
|
||||
// Port priority is the final tie breaker.
|
||||
position++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gametyperules & GTR_CIRCUIT)
|
||||
{
|
||||
if (player->exiting) // End of match standings
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ Make sure this matches the actual number of states
|
|||
#define STUMBLE_STEEP_VAL ANG60
|
||||
#define STUMBLE_STEEP_VAL_AIR (ANG30 + ANG10)
|
||||
|
||||
boolean K_PodiumSequence(void);
|
||||
|
||||
player_t *K_GetItemBoxPlayer(mobj_t *mobj);
|
||||
angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed);
|
||||
|
||||
|
|
|
|||
|
|
@ -235,6 +235,29 @@ INT32 K_GetWaypointID(waypoint_t *waypoint)
|
|||
return waypointid;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
waypoint_t *K_GetWaypointFromID(INT32 waypointID)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
waypoint_t *K_GetWaypointFromID(INT32 waypointID)
|
||||
{
|
||||
waypoint_t *waypoint = NULL;
|
||||
size_t i = SIZE_MAX;
|
||||
|
||||
for (i = 0; i < numwaypoints; i++)
|
||||
{
|
||||
waypoint = &waypointheap[i];
|
||||
|
||||
if (K_GetWaypointID(waypoint) == waypointID)
|
||||
{
|
||||
return waypoint;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT32 K_GetCircuitLength(void)
|
||||
|
||||
|
|
|
|||
|
|
@ -141,9 +141,25 @@ INT32 K_GetWaypointNextID(waypoint_t *waypoint);
|
|||
Return:-
|
||||
The waypoint ID, -1 if there is no waypoint or mobj.
|
||||
--------------------------------------------------*/
|
||||
|
||||
INT32 K_GetWaypointID(waypoint_t *waypoint);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
waypoint_t *K_GetWaypointFromID(INT32 waypointID)
|
||||
|
||||
Returns the first waypoint with the specified ID.
|
||||
|
||||
Input Arguments:-
|
||||
waypointID - The ID of the waypoint to get
|
||||
|
||||
Return:-
|
||||
The first waypoint with this ID, NULL if the ID doesn't exist at all in the map
|
||||
--------------------------------------------------*/
|
||||
|
||||
waypoint_t *K_GetWaypointFromID(INT32 waypointID);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT32 K_GetCircuitLength(void)
|
||||
|
||||
|
|
|
|||
|
|
@ -223,6 +223,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word,"tutorialmode")) {
|
||||
lua_pushboolean(L, tutorialmode);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"podiummap")) {
|
||||
lua_pushstring(L, podiummap);
|
||||
return 1;
|
||||
// end map vars
|
||||
// begin CTF colors
|
||||
} else if (fastcmp(word,"skincolor_redteam")) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue