diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 659a2fd31..7e8e16f63 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -52,6 +52,8 @@ add_custom_target(_SRB2_reconf ALL ) add_dependencies(SRB2SDL2 _SRB2_reconf) + + add_subdirectory(blua) add_subdirectory(blan) add_subdirectory(sdl) diff --git a/src/Sourcefile b/src/Sourcefile index dbea241ca..fac294f12 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -115,12 +115,12 @@ k_collide.c k_color.c k_battle.c k_pwrlv.c -k_waypoint.c +k_waypoint.cpp k_pathfind.c k_bheap.c -k_bot.c -k_botitem.c -k_botsearch.c +k_bot.cpp +k_botitem.cpp +k_botsearch.cpp k_grandprix.c k_boss.c k_hud.c diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 44d8175ac..1b5029a90 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3543,19 +3543,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) node = (UINT8)READUINT8(*p); newplayernum = (UINT8)READUINT8(*p); - CONS_Debug(DBG_NETPLAY, "addplayer: %d %d\n", node, newplayernum); - - { - // Clear player before joining, lest some things get set incorrectly - CL_ClearPlayer(newplayernum); - - playeringame[newplayernum] = true; - G_AddPlayer(newplayernum); - - if (newplayernum+1 > doomcom->numslots) - doomcom->numslots = (INT16)(newplayernum+1); - } - newplayer = &players[newplayernum]; newplayer->jointime = 0; @@ -3565,6 +3552,8 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) console = (UINT8)READUINT8(*p); splitscreenplayer = (UINT8)READUINT8(*p); + G_AddPlayer(newplayernum, console); + // the server is creating my player if (node == mynode) { @@ -3685,34 +3674,7 @@ static void Got_AddBot(UINT8 **p, INT32 playernum) difficulty = READUINT8(*p); style = READUINT8(*p); - CONS_Debug(DBG_NETPLAY, "addbot: %d\n", newplayernum); - - // Clear player before joining, lest some things get set incorrectly - CL_ClearPlayer(newplayernum); - - playeringame[newplayernum] = true; - G_AddPlayer(newplayernum); - if (newplayernum+1 > doomcom->numslots) - doomcom->numslots = (INT16)(newplayernum+1); - - playernode[newplayernum] = servernode; - - players[newplayernum].splitscreenindex = 0; - players[newplayernum].bot = true; - players[newplayernum].botvars.difficulty = difficulty; - players[newplayernum].botvars.style = style; - players[newplayernum].lives = 9; - - players[newplayernum].skincolor = skins[skinnum].prefcolor; - sprintf(player_names[newplayernum], "%s", skins[skinnum].realname); - SetPlayerSkinByNum(newplayernum, skinnum); - - if (netgame) - { - HU_AddChatText(va("\x82*Bot %d has been added to the game", newplayernum+1), false); - } - - LUA_HookInt(newplayernum, HOOK(PlayerJoin)); + K_SetBot(newplayernum, skinnum, difficulty, style); } static boolean SV_AddWaitingPlayers(SINT8 node, const char *name, const char *name2, const char *name3, const char *name4) @@ -3811,6 +3773,85 @@ static boolean SV_AddWaitingPlayers(SINT8 node, const char *name, const char *na return newplayer; } +/*-------------------------------------------------- + boolean K_AddBotFromServer(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p) + + See header file for description. +--------------------------------------------------*/ +boolean K_AddBotFromServer(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p) +{ + UINT8 newplayernum = *p; + + // search for a free playernum + // we can't use playeringame since it is not updated here + for (; newplayernum < MAXPLAYERS; newplayernum++) + { + UINT8 n; + + for (n = 0; n < MAXNETNODES; n++) + { + if (nodetoplayer[n] == newplayernum + || nodetoplayer2[n] == newplayernum + || nodetoplayer3[n] == newplayernum + || nodetoplayer4[n] == newplayernum) + break; + } + + if (n == MAXNETNODES) + break; + } + + for (; newplayernum < MAXPLAYERS; newplayernum++) + { + if (playeringame[newplayernum] == false) + { + // free player slot + break; + } + } + + if (newplayernum >= MAXPLAYERS) + { + // nothing is free + *p = MAXPLAYERS; + return false; + } + + if (server) + { + UINT8 buf[4]; + UINT8 *buf_p = buf; + + WRITEUINT8(buf_p, newplayernum); + + if (skin > numskins) + { + skin = numskins; + } + + WRITEUINT8(buf_p, skin); + + if (difficulty < 1) + { + difficulty = 1; + } + else if (difficulty > MAXBOTDIFFICULTY) + { + difficulty = MAXBOTDIFFICULTY; + } + + WRITEUINT8(buf_p, difficulty); + WRITEUINT8(buf_p, style); + + SendNetXCmd(XD_ADDBOT, buf, buf_p - buf); + DEBFILE(va("Server added bot %d\n", newplayernum)); + } + + // use the next free slot (we can't put playeringame[newplayernum] = true here) + *p = newplayernum+1; + return true; +} + void CL_AddSplitscreenPlayer(void) { if (cl_mode == CL_CONNECTED) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index fa14bbf1e..c4c0890a2 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -262,6 +262,11 @@ static consvar_t cv_dummyconsvar = CVAR_INIT ("dummyconsvar", "Off", CV_CALL|CV_ consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_NETVAR, CV_YesNo, NULL); +#ifdef DEVELOP + // change the default value in doomdef.h (so it affects release builds too) + consvar_t cv_debugtraversemax = CVAR_INIT ("debugtraversemax", TOSTR2(TRAVERSE_MAX), CV_NETVAR|CV_CHEAT, CV_Unsigned, NULL); +#endif + static CV_PossibleValue_t ingamecap_cons_t[] = {{0, "MIN"}, {MAXPLAYERS-1, "MAX"}, {0, NULL}}; consvar_t cv_ingamecap = CVAR_INIT ("ingamecap", "0", CV_NETVAR, ingamecap_cons_t, NULL); @@ -3652,6 +3657,40 @@ static void Command_ServerTeamChange_f(void) SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); } +void P_SetPlayerSpectator(INT32 playernum) +{ + //Make sure you're in the right gametype. + if (!G_GametypeHasTeams() && !G_GametypeHasSpectators()) + return; + + // Don't duplicate efforts. + if (players[playernum].spectator) + return; + + players[playernum].spectator = true; + players[playernum].pflags &= ~PF_WANTSTOJOIN; + + players[playernum].playerstate = PST_REBORN; + + /*if (cv_spectatormusic.value && (players[displayplayers[0]].spectator == true) && !r_splitscreen) + { + if (P_UseContinuousLevelMusic()) + { + if (!stricmp(Music_Song("level_nosync"), cv_spectatormusiclump.string)) + { + // Do not reset music if it is the same + Music_BatchExempt("level_nosync"); + } + Music_Remap("level_nosync", cv_spectatormusiclump.string); + } + else + { + Music_Remap("level", cv_spectatormusiclump.string); + } + }*/ + +} + //todo: This and the other teamchange functions are getting too long and messy. Needs cleaning. static void Got_Teamchange(UINT8 **cp, INT32 playernum) { @@ -3739,7 +3778,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) { players[playernum].playerstate = PST_REBORN; } - + } else wasspectator = true; @@ -3832,7 +3871,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) if (players[playernum].spectator) { players[playernum].spectatorreentry = (cv_spectatorreentry.value * TICRATE); - + if (gametyperules & GTR_BUMPERS) // SRB2kart { players[playernum].roundscore = 0; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 78d2dd554..84fa3d4e0 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -65,6 +65,10 @@ extern consvar_t cv_pause; extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_ingamecap, cv_respawntime; extern consvar_t cv_spectatorreentry, cv_antigrief; +#ifdef DEVELOP + extern consvar_t cv_debugtraversemax; +#endif + // SRB2kart items extern consvar_t cv_superring, cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana; extern consvar_t cv_eggmanmonitor, cv_orbinaut, cv_jawz, cv_mine, cv_landmine, cv_droptarget; @@ -255,6 +259,8 @@ void RemoveAdminPlayer(INT32 playernum); void ItemFinder_OnChange(void); void D_SetPassword(const char *pw); +void P_SetPlayerSpectator(INT32 playernum); + struct scheduleTask_t { UINT16 basetime; diff --git a/src/doomdef.h b/src/doomdef.h index fa0db8e47..5088491d4 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -274,6 +274,9 @@ enum { LE_PARAMWIDTH = -100 // If an object that calls LinedefExecute has a nonzero parameter value, this times the parameter will be subtracted. (Mostly for the purpose of coexisting bosses...) }; +#define TOSTR(x) #x +#define TOSTR2(x) TOSTR(x) // expand x first + // Name of local directory for config files and savegames #if (((defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON)) && !defined (__CYGWIN__)) && !defined (__APPLE__) #define DEFAULTDIR ".srb2kart-v2" @@ -562,6 +565,9 @@ extern int compuncommitted; /// Camera always has noclip. #define NOCLIPCAM +// p_sight.c +#define TRAVERSE_MAX 8 + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/f_finale.c b/src/f_finale.c index 32255dcd4..b3ab3ccff 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1951,7 +1951,7 @@ void F_EndTextPrompt(boolean forceexec, boolean noexec) // \todo net safety, maybe loop all player thinkers? if ((promptwasactive || forceexec) && !noexec && promptpostexectag) { - if (tm.thing) // edge case where starting an invalid prompt immediately on level load will make P_MapStart fail + if (g_tm.thing) // edge case where starting an invalid prompt immediately on level load will make P_MapStart fail P_LinedefExecute(promptpostexectag, promptmo, NULL); else { diff --git a/src/g_demo.c b/src/g_demo.c index b4467afa8..62abc324f 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -336,7 +336,7 @@ void G_ReadDemoExtraData(void) { CL_ClearPlayer(p); playeringame[p] = true; - G_AddPlayer(p); + G_AddPlayer(p, p); players[p].spectator = true; //CONS_Printf("player %s is joining server on tic %d\n", player_names[p], leveltime); } diff --git a/src/g_game.c b/src/g_game.c index 08f5617f8..a57eae42f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2995,10 +2995,21 @@ void G_DoReborn(INT32 playernum) ACS_RunPlayerEnterScript(player); } -void G_AddPlayer(INT32 playernum) +void G_AddPlayer(INT32 playernum, INT32 console) { - player_t *p = &players[playernum]; - p->playerstate = PST_REBORN; + CL_ClearPlayer(playernum); + //G_DestroyParty(playernum); + + playeringame[playernum] = true; + + playerconsole[playernum] = console; + //G_BuildLocalSplitscreenParty(playernum); + + player_t *newplayer = &players[playernum]; + + newplayer->playerstate = PST_REBORN; + newplayer->jointime = 0; + demo_extradata[playernum] |= DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN|DXD_FOLLOWER; // Set everything } @@ -5260,6 +5271,21 @@ void G_SetGamestate(gamestate_t newstate) #endif } +boolean G_GamestateUsesLevel(void) +{ + switch (gamestate) + { + case GS_TITLESCREEN: + return titlemapinaction; + + case GS_LEVEL: + return true; + + default: + return false; + } +} + /* These functions handle the exitgame flag. Before, when the user chose to end a game, it happened immediately, which could cause crashes if the game was in the middle of something. Now, a flag diff --git a/src/g_game.h b/src/g_game.h index 5192de72d..82dc9683e 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -247,7 +247,7 @@ void G_AddPartyMember (INT32 party_member, INT32 new_party_member); void G_RemovePartyMember (INT32 party_member); void G_ResetSplitscreen (INT32 playernum); -void G_AddPlayer(INT32 playernum); +void G_AddPlayer(INT32 playernum, INT32 console); void G_SetExitGameFlag(void); void G_ClearExitGameFlag(void); @@ -268,6 +268,8 @@ void G_SetGameModified(boolean silent, boolean major); void G_SetGamestate(gamestate_t newstate); +boolean G_GamestateUsesLevel(void); + // Gamedata record shit void G_AllocMainRecordData(INT16 i); void G_ClearRecords(void); diff --git a/src/k_bot.c b/src/k_bot.cpp similarity index 55% rename from src/k_bot.c rename to src/k_bot.cpp index 1f55f33c7..236d5cfa3 100644 --- a/src/k_bot.c +++ b/src/k_bot.cpp @@ -1,19 +1,24 @@ -// SONIC ROBO BLAST 2 KART +// DR. ROBOTNIK'S RING RACERS //----------------------------------------------------------------------------- -// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour -// Copyright (C) 2018-2020 by Kart Krew +// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2024 by Kart Krew // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file k_bot.c +/// \file k_bot.cpp /// \brief Bot logic & ticcmd generation code +#include + +#include + +#include "cxxutil.hpp" + #include "doomdef.h" #include "d_player.h" #include "g_game.h" -#include "p_mobj.h" #include "r_main.h" #include "p_local.h" #include "k_bot.h" @@ -27,9 +32,116 @@ #include "d_ticcmd.h" #include "m_random.h" #include "r_things.h" // numskins -#include "k_boss.h" #include "m_perfstats.h" #include "m_easing.h" +#include "d_clisrv.h" +#include "k_grandprix.h" // K_CanChangeRules +#include "hu_stuff.h" // HU_AddChatText +#ifdef HAVE_DISCORDRPC +#include "discord.h" // DRPC_UpdatePresence +#endif +#include "i_net.h" // doomcom + +//extern "C" consvar_t cv_forcebots; + +/*-------------------------------------------------- + void K_SetNameForBot(UINT8 playerNum, UINT8 skinnum) + + See header file for description. +--------------------------------------------------*/ +void K_SetNameForBot(UINT8 newplayernum, const char *realname) +{ + UINT8 ix = MAXPLAYERS; + + // These names are generally sourced from skins. + I_Assert(MAXPLAYERNAME >= SKINNAMESIZE+2); + + if (netgame == true) + { + // Check if a player is currently using the name, case-insensitively. + // We only do this if online, because it doesn't matter if there are multiple Eggrobo *off*line. + // See also EnsurePlayerNameIsGood + for (ix = 0; ix < MAXPLAYERS; ix++) + { + if (ix == newplayernum) + continue; + if (playeringame[ix] == false) + continue; + if (strcasecmp(realname, player_names[ix]) != 0) + continue; + + break; + } + } + + if (ix == MAXPLAYERS) + { + // No conflict detected! + sprintf(player_names[newplayernum], "%s", realname); + return; + } + + // Ok, now we append on the end for duplicates... + char namebuffer[MAXPLAYERNAME+1]; + sprintf(namebuffer, "%s %c", realname, 'A'+newplayernum); + + // ...and use the actual function, to handle more devious duplication. + if (!EnsurePlayerNameIsGood(namebuffer, newplayernum)) + { + // we can't bail from adding the bot... + // this hopefully uncontroversial pick is all we CAN do + sprintf(namebuffer, "Bot %u", newplayernum+1); + } + + // And finally write. + sprintf(player_names[newplayernum], "%s", namebuffer); +} + +/*-------------------------------------------------- + void K_SetBot(UINT8 playerNum, UINT8 skinnum, UINT8 difficulty, botStyle_e style) + + See header file for description. +--------------------------------------------------*/ +void K_SetBot(UINT8 newplayernum, UINT8 skinnum, UINT8 difficulty, botStyle_e style) +{ + CONS_Debug(DBG_NETPLAY, "addbot: %d\n", newplayernum); + + G_AddPlayer(newplayernum, newplayernum); + + if (newplayernum+1 > doomcom->numslots) + doomcom->numslots = (INT16)(newplayernum+1); + + playernode[newplayernum] = servernode; + + players[newplayernum].splitscreenindex = 0; + players[newplayernum].bot = true; + players[newplayernum].botvars.difficulty = difficulty; + players[newplayernum].botvars.style = style; + players[newplayernum].lives = 9; + + // The bot may immediately become a spectator AT THE START of a GP. + // For each subsequent round of GP, K_UpdateGrandPrixBots will handle this. + players[newplayernum].spectator = grandprixinfo.gp && grandprixinfo.initalize; + + skincolornum_t color = static_cast(skins[skinnum].prefcolor); + const char *realname = skins[skinnum].realname; + players[newplayernum].skincolor = color; + K_SetNameForBot(newplayernum, realname); + + SetPlayerSkinByNum(newplayernum, skinnum); + + for (UINT8 i = 0; i < PWRLV_NUMTYPES; i++) + { + clientpowerlevels[newplayernum][i] = 0; + } + + if (netgame) + { + HU_AddChatText(va("\x82*Bot %d has been added to the game", newplayernum+1), false); + } + + LUA_HookInt(newplayernum, HOOK(PlayerJoin)); +} /*-------------------------------------------------- boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p) @@ -38,68 +150,30 @@ --------------------------------------------------*/ boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p) { - UINT8 buf[4]; - UINT8 *buf_p = buf; UINT8 newplayernum = *p; - // search for a free playernum - // we can't use playeringame since it is not updated here for (; newplayernum < MAXPLAYERS; newplayernum++) { - UINT8 n; - - for (n = 0; n < MAXNETNODES; n++) - if (nodetoplayer[n] == newplayernum - || nodetoplayer2[n] == newplayernum - || nodetoplayer3[n] == newplayernum - || nodetoplayer4[n] == newplayernum) - break; - - if (n == MAXNETNODES) + if (playeringame[newplayernum] == false) + { + // free player slot break; - } - - while (playeringame[newplayernum] - && players[newplayernum].bot - && newplayernum < MAXPLAYERS) - { - newplayernum++; + } } if (newplayernum >= MAXPLAYERS) { - *p = newplayernum; + // nothing is free + *p = MAXPLAYERS; return false; } - WRITEUINT8(buf_p, newplayernum); + K_SetBot(newplayernum, skin, difficulty, style); + DEBFILE(va("Everyone added bot %d\n", newplayernum)); - if (skin > numskins) - { - skin = numskins; - } + // use the next free slot + *p = newplayernum+1; - WRITEUINT8(buf_p, skin); - - if (difficulty < 1) - { - difficulty = 1; - } - else if (difficulty > MAXBOTDIFFICULTY) - { - difficulty = MAXBOTDIFFICULTY; - } - - WRITEUINT8(buf_p, difficulty); - WRITEUINT8(buf_p, style); - - SendNetXCmd(XD_ADDBOT, buf, buf_p - buf); - - DEBFILE(va("Server added bot %d\n", newplayernum)); - // use the next free slot (we can't put playeringame[newplayernum] = true here) - newplayernum++; - - *p = newplayernum; return true; } @@ -110,36 +184,47 @@ boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p) --------------------------------------------------*/ void K_UpdateMatchRaceBots(void) { - const UINT8 difficulty = cv_kartbot.value; - UINT8 pmax = min((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), cv_maxplayers.value); + const UINT8 defaultbotskin = K_BotDefaultSkin(); + UINT8 difficulty; + UINT8 pmax = (dedicated ? MAXPLAYERS-1 : MAXPLAYERS); UINT8 numplayers = 0; UINT8 numbots = 0; UINT8 numwaiting = 0; SINT8 wantedbots = 0; - boolean skinusable[MAXSKINS]; + UINT8 usableskins = 0, skincount = numskins; + UINT8 grabskins[MAXSKINS+1]; UINT8 i; - if (!server) + // Init usable bot skins list + for (i = 0; i < skincount; i++) { - return; + grabskins[usableskins++] = i; } + grabskins[usableskins] = MAXSKINS; - // init usable bot skins list - for (i = 0; i < MAXSKINS; i++) + if (gamestate == GS_TITLESCREEN) { - if (i < numskins) - { - skinusable[i] = true; - } - else - { - skinusable[i] = false; - } + difficulty = 0; } - - if (cv_ingamecap.value > 0) + else if ((gametyperules & GTR_BOTS) == 0 /*&& !cv_forcebots.value*/) { - pmax = min(pmax, cv_ingamecap.value); + difficulty = 0; + } + else if (K_CanChangeRules() == false) + { + difficulty = 0; + } + else + { + difficulty = cv_kartbot.value; + /*if (netgame) + { + pmax = std::min(pmax, static_cast(cv_maxconnections.value)); + }*/ + if (cv_maxplayers.value > 0) + { + pmax = std::min(pmax, static_cast(cv_maxplayers.value)); + } } for (i = 0; i < MAXPLAYERS; i++) @@ -148,7 +233,7 @@ void K_UpdateMatchRaceBots(void) { if (!players[i].spectator) { - skinusable[players[i].skin] = false; + grabskins[players[i].skin] = MAXSKINS; if (players[i].bot) { @@ -172,104 +257,104 @@ void K_UpdateMatchRaceBots(void) } } - if (difficulty == 0 || !(gametyperules & GTR_BOTS) || bossinfo.boss == true) + if (difficulty == 0) { + // Remove bots if there are any. wantedbots = 0; } else { + // Add bots to fill up MAXPLAYERS wantedbots = pmax - numplayers - numwaiting; if (wantedbots < 0) { wantedbots = 0; } - - if (numbosswaypoints > 0 && !waypointcap) - { - CONS_Alert(CONS_ERROR, "Bots do not work on maps using the legacy checkpoint system.\nPlease consider using waypoints instead if bot support is desired!\n"); - } } + auto clear_bots = [&numbots](UINT8 max) + { + UINT8 i = MAXPLAYERS; + while (numbots > max && i > 0) + { + i--; + + if (playeringame[i] && players[i].bot) + { + CL_RemovePlayer(i, KR_LEAVE); + numbots--; + } + } + }; + if (numbots < wantedbots) { // We require MORE bots! UINT8 newplayernum = 0; - boolean usedallskins = false; if (dedicated) { newplayernum = 1; } - while (numbots < wantedbots) + for (i = 0; i < usableskins; i++) { - UINT8 skin = M_RandomKey(numskins); - - if (usedallskins == false) + if (!(grabskins[i] == MAXSKINS || !R_SkinUsable(-1, grabskins[i]))) { - UINT8 loops = 0; - - while (!skinusable[skin]) - { - if (loops >= numskins) - { - // no more skins, stick to our first choice - usedallskins = true; - break; - } - - skin++; - - if (skin >= numskins) - { - skin = 0; - } - - loops++; - } + continue; } - if (!K_AddBot(skin, difficulty, BOT_STYLE_NORMAL, &newplayernum)) + while (usableskins > i && (grabskins[usableskins] == MAXSKINS || !R_SkinUsable(-1, grabskins[usableskins]))) + { + usableskins--; + } + + grabskins[i] = grabskins[usableskins]; + grabskins[usableskins] = MAXSKINS; + } + + while (numbots < wantedbots) + { + UINT8 skinnum = defaultbotskin; + + if (usableskins > 0) + { + UINT8 index = P_RandomKey(usableskins); + skinnum = grabskins[index]; + grabskins[index] = grabskins[--usableskins]; + } + + if (!K_AddBot(skinnum, difficulty, BOT_STYLE_NORMAL, &newplayernum)) { // Not enough player slots to add the bot, break the loop. break; } - skinusable[skin] = false; numbots++; } } else if (numbots > wantedbots) { - UINT8 buf[2]; - - i = MAXPLAYERS; - while (numbots > wantedbots && i > 0) - { - i--; - - if (playeringame[i] && players[i].bot) - { - buf[0] = i; - buf[1] = KR_LEAVE; - SendNetXCmd(XD_REMOVEPLAYER, &buf, 2); - - numbots--; - } - } + clear_bots(wantedbots); } // We should have enough bots now :) + +#ifdef HAVE_DISCORDRPC + // Player count change was possible, so update presence + DRPC_UpdatePresence(); +#endif } /*-------------------------------------------------- - boolean K_PlayerUsesBotMovement(player_t *player) + boolean K_PlayerUsesBotMovement(const player_t *player) See header file for description. --------------------------------------------------*/ -boolean K_PlayerUsesBotMovement(player_t *player) +boolean K_PlayerUsesBotMovement(const player_t *player) { + if (player->exiting) return false; @@ -287,7 +372,7 @@ boolean K_PlayerUsesBotMovement(player_t *player) boolean K_BotCanTakeCut(player_t *player) { if ( - ((K_TripwirePassConditions(player) != TRIPWIRE_NONE) || (K_ApplyOffroad(player) == false)) + (K_TripwirePassConditions(player) != TRIPWIRE_NONE || K_ApplyOffroad(player) == false) || player->itemtype == KITEM_SNEAKER || player->itemtype == KITEM_ROCKETSNEAKER || player->itemtype == KITEM_INVINCIBILITY @@ -300,7 +385,7 @@ boolean K_BotCanTakeCut(player_t *player) } /*-------------------------------------------------- - static fixed_t K_BotSpeedScaled(player_t *player, fixed_t speed) + static fixed_t K_BotSpeedScaled(const player_t *player, fixed_t speed) What the bot "thinks" their speed is, for predictions. Mainly to make bots brake earlier when on friction sectors. @@ -312,7 +397,7 @@ boolean K_BotCanTakeCut(player_t *player) Return:- The bot's speed value for calculations. --------------------------------------------------*/ -static fixed_t K_BotSpeedScaled(player_t *player, fixed_t speed) +static fixed_t K_BotSpeedScaled(const player_t *player, fixed_t speed) { fixed_t result = speed; @@ -342,7 +427,7 @@ static fixed_t K_BotSpeedScaled(player_t *player, fixed_t speed) result = FixedMul(result, moveFactor); } - if (player->mo->standingslope != NULL) + if (player->mo->standingslope != nullptr) { const pslope_t *slope = player->mo->standingslope; @@ -367,78 +452,73 @@ static fixed_t K_BotSpeedScaled(player_t *player, fixed_t speed) } /*-------------------------------------------------- - static line_t *K_FindBotController(mobj_t *mo) + const botcontroller_t *K_GetBotController(const mobj_t *mobj) - Finds if any bot controller linedefs are tagged to the bot's sector. - - Input Arguments:- - mo - The bot player's mobj. - - Return:- - Linedef of the bot controller. NULL if it doesn't exist. + See header file for description. --------------------------------------------------*/ -static line_t *K_FindBotController(mobj_t *mo) +const botcontroller_t *K_GetBotController(mobj_t *mobj) { - msecnode_t *node; - ffloor_t *rover; - INT16 lineNum = -1; - mtag_t tag; + botcontroller_t *ret = nullptr; - I_Assert(mo != NULL); - I_Assert(!P_MobjWasRemoved(mo)); - - for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + if (P_MobjWasRemoved(mobj) == true) { - if (!node->m_sector) + return nullptr; + } + + if (mobj->subsector == nullptr || mobj->subsector->sector == nullptr) + { + return nullptr; + } + + ret = &mobj->subsector->sector->botController; + + ffloor_t *rover = nullptr; + for (rover = mobj->subsector->sector->ffloors; rover; rover = rover->next) + { + if ((rover->fofflags & FOF_EXISTS) == 0) { continue; } - tag = Tag_FGet(&node->m_sector->tags); - lineNum = P_FindSpecialLineFromTag(2004, tag, -1); // todo: needs to not use P_FindSpecialLineFromTag + fixed_t topheight = P_GetFOFTopZ(mobj, mobj->subsector->sector, rover, mobj->x, mobj->y, nullptr); + fixed_t bottomheight = P_GetFOFBottomZ(mobj, mobj->subsector->sector, rover, mobj->x, mobj->y, nullptr); - if (lineNum != -1) + if (mobj->z > topheight || mobj->z + mobj->height < bottomheight) { - break; + continue; } - for (rover = node->m_sector->ffloors; rover; rover = rover->next) + botcontroller_t *roverController = &rover->master->frontsector->botController; + if (roverController->flags != 0) { - sector_t *rs = NULL; - - if (!(rover->fofflags & FOF_EXISTS)) - { - continue; - } - - if (mo->z > *rover->topheight || mo->z + mo->height < *rover->bottomheight) - { - continue; - } - - rs = §ors[rover->secnum]; - tag = Tag_FGet(&rs->tags); - lineNum = P_FindSpecialLineFromTag(2004, tag, -1); - - if (lineNum != -1) - { - break; - } + ret = roverController; } } - if (lineNum != -1) - { - return &lines[lineNum]; - } - else - { - return NULL; - } + return ret; } /*-------------------------------------------------- - static UINT32 K_BotRubberbandDistance(player_t *player) + fixed_t K_BotMapModifier(void) + + See header file for description. +--------------------------------------------------*/ +fixed_t K_BotMapModifier(void) +{ + constexpr INT32 complexity_scale = 10000; + constexpr fixed_t modifier_max = FRACUNIT * 2; + + const fixed_t complexity_value = std::clamp( + FixedDiv(K_GetTrackComplexity(), complexity_scale), + -FixedDiv(FRACUNIT, modifier_max), + modifier_max + ); + + return FRACUNIT + complexity_value; +} + +/*-------------------------------------------------- + static UINT32 K_BotRubberbandDistance(const player_t *player) Calculates the distance away from 1st place that the bot should rubberband to. @@ -498,49 +578,56 @@ static UINT32 K_BotRubberbandDistance(const player_t *player) } /*-------------------------------------------------- - fixed_t K_BotRubberband(player_t *player) + fixed_t K_BotRubberband(const player_t *player) See header file for description. --------------------------------------------------*/ -fixed_t K_BotRubberband(player_t *player) +fixed_t K_BotRubberband(const player_t *player) { - fixed_t rubberband = FRACUNIT >> 1; - fixed_t rubbermin = FRACUNIT; - fixed_t rubbermax = FRACUNIT; - player_t *firstplace = NULL; - UINT8 i; - if (player->exiting) { // You're done, we don't need to rubberband anymore. return FRACUNIT; } - if (player->botvars.controller != UINT16_MAX) + const botcontroller_t *botController = K_GetBotController(player->mo); + if (botController != nullptr && (botController->flags & TMBOT_NORUBBERBAND) == TMBOT_NORUBBERBAND) // Disable rubberbanding { - const line_t *botController = &lines[player->botvars.controller]; - - if (botController != NULL) - { - // Disable rubberbanding - if (botController->args[1] & TMBOT_NORUBBERBAND) - { - return FRACUNIT; - } - } + return FRACUNIT; } - // Lv. 1: x0.5 min - // Lv. 5: x0.75 min - // Lv. 9: x1.0 min - // Lv. MAX: x1.25 min - rubbermin = FRACUNIT - (((FRACUNIT/2) * (DIFFICULTBOT - player->botvars.difficulty)) / (DIFFICULTBOT - 1)); + fixed_t difficultyEase = ((player->botvars.difficulty - 1) * FRACUNIT) / (MAXBOTDIFFICULTY - 1); - // Lv. 1: x0.8 max - // Lv. 5: x1.2 max - // Lv. 9: x1.4 max - // Lv. MAX: x2.0 max - rubbermax = FRACUNIT + ((FRACUNIT * (player->botvars.difficulty - 3)) / 10); + // Lv. 1: x0.65 avg + // Lv. MAX: x1.05 avg + const fixed_t rubberBase = Easing_OutSine( + difficultyEase, + FRACUNIT * 65 / 100, + FRACUNIT * 105 / 100 + ); + + // +/- x0.35 + const fixed_t rubberStretchiness = FixedMul( + FixedDiv( + 35 * FRACUNIT / 100, + K_GetKartGameSpeedScalar(gamespeed) + ), + K_BotMapModifier() + ); + + // Lv. 1: x0.4 min + // Lv. MAX: x0.85 min + constexpr fixed_t rubberSlowMin = FRACUNIT / 2; + const fixed_t rubberSlow = std::max( rubberBase - rubberStretchiness, rubberSlowMin ); + + // Lv. 1: x0.9 max + // Lv. MAX: x1.35 max + constexpr fixed_t rubberFastMax = FRACUNIT * 3 / 2; + const fixed_t rubberFast = std::min( rubberBase + rubberStretchiness, rubberFastMax ); + + fixed_t rubberband = FRACUNIT >> 1; + player_t *firstplace = nullptr; + size_t i = SIZE_MAX; for (i = 0; i < MAXPLAYERS; i++) { @@ -549,6 +636,12 @@ fixed_t K_BotRubberband(player_t *player) continue; } + // Don't rubberband to ourselves... + if (player == &players[i]) + { + continue; + } + #if 0 // Only rubberband up to players. if (players[i].bot) @@ -557,31 +650,57 @@ fixed_t K_BotRubberband(player_t *player) } #endif - if (firstplace == NULL || players[i].distancetofinish < firstplace->distancetofinish) + if (firstplace == nullptr || players[i].distancetofinish < firstplace->distancetofinish) { firstplace = &players[i]; } } - if (firstplace != NULL) + if (firstplace != nullptr) { - const UINT32 spacing = FixedDiv(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT; + const UINT32 spacing = FixedDiv(10240 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT; const UINT32 wanteddist = firstplace->distancetofinish + K_BotRubberbandDistance(player); const INT32 distdiff = player->distancetofinish - wanteddist; - rubberband += (distdiff * (FRACUNIT >> 1)) / spacing; + rubberband = FixedDiv(distdiff + spacing, spacing * 2); + + if (player->boostpower < FRACUNIT) + { + // Do not let bots cheese offroad as much. + rubberband = FixedMul(rubberband, player->boostpower); + } + + if (P_MobjWasRemoved(player->mo) == false && player->mo->movefactor < FRACUNIT) + { + // Do not let bots speed up on ice too much. + rubberband = FixedMul(rubberband, player->mo->movefactor); + } + + if (rubberband > FRACUNIT) + { + rubberband = FRACUNIT; + } + else if (rubberband < 0) + { + rubberband = 0; + } } - if (rubberband > FRACUNIT) + UINT32 scaled_dist = player->distancetofinish; + if (mapobjectscale != FRACUNIT) { - rubberband = FRACUNIT; - } - else if (rubberband < 0) - { - rubberband = 0; + // Bring back to normal scale. + scaled_dist = FixedDiv(scaled_dist, mapobjectscale); } - return Easing_Linear(rubberband, rubbermin, rubbermax); + constexpr UINT32 END_DIST = 2048 * 14; + if (scaled_dist < END_DIST) + { + // At the end of tracks, start slowing down. + rubberband = FixedMul(rubberband, FixedDiv(scaled_dist, END_DIST)); + } + + return Easing_Linear(rubberband, rubberSlow, rubberFast); } /*-------------------------------------------------- @@ -595,7 +714,7 @@ fixed_t K_UpdateRubberband(player_t *player) fixed_t ret = player->botvars.rubberband; // Ease into the new value. - ret += (dest - player->botvars.rubberband) >> 3; + ret += (dest - player->botvars.rubberband) / 8; return ret; } @@ -637,7 +756,7 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t } /*-------------------------------------------------- - static fixed_t K_GetBotWaypointRadius(waypoint_t *waypoint) + static void K_GetBotWaypointRadius(waypoint_t *waypoint, fixed_t *smallestRadius, fixed_t *smallestScaled) Calculates a new waypoint radius size to use, making it thinner depending on how harsh the turn is. @@ -646,12 +765,12 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t waypoint - Waypoint to retrieve the radius of. Return:- - New radius value. + N/A --------------------------------------------------*/ -static fixed_t K_GetBotWaypointRadius(waypoint_t *const waypoint) +static void K_GetBotWaypointRadius(waypoint_t *const waypoint, fixed_t *smallestRadius, fixed_t *smallestScaled) { static const fixed_t maxReduce = FRACUNIT/32; - static const angle_t maxDelta = ANGLE_45; + static const angle_t maxDelta = ANGLE_22h; fixed_t radius = waypoint->mobj->radius; fixed_t reduce = FRACUNIT; @@ -675,7 +794,7 @@ static fixed_t K_GetBotWaypointRadius(waypoint_t *const waypoint) waypoint->mobj->x, waypoint->mobj->y ); - delta = max(delta, AngleDelta(nextAngle, prevAngle)); + delta = std::max(delta, AngleDelta(nextAngle, prevAngle)); } } @@ -687,12 +806,13 @@ static fixed_t K_GetBotWaypointRadius(waypoint_t *const waypoint) reduce = FixedDiv(delta, maxDelta); reduce = FRACUNIT + FixedMul(reduce, maxReduce - FRACUNIT); - return FixedMul(radius, reduce); + *smallestRadius = std::min(*smallestRadius, radius); + *smallestScaled = std::min(*smallestScaled, FixedMul(radius, reduce)); } static fixed_t K_ScaleWPDistWithSlope(fixed_t disttonext, angle_t angletonext, const pslope_t *slope, SINT8 flip) { - if (slope == NULL) + if (slope == nullptr) { return disttonext; } @@ -720,7 +840,7 @@ static fixed_t K_ScaleWPDistWithSlope(fixed_t disttonext, angle_t angletonext, c } /*-------------------------------------------------- - static botprediction_t *K_CreateBotPrediction(player_t *player) + static botprediction_t *K_CreateBotPrediction(const player_t *player) Calculates a point further along the track to attempt to drive towards. @@ -732,22 +852,26 @@ static fixed_t K_ScaleWPDistWithSlope(fixed_t disttonext, angle_t angletonext, c --------------------------------------------------*/ static botprediction_t *K_CreateBotPrediction(player_t *player) { + ZoneScoped; + const precise_t time = I_GetPreciseTime(); const INT16 handling = K_GetKartTurnValue(player, KART_FULLTURN); // Reduce prediction based on how fast you can turn - const tic_t futuresight = (TICRATE * KART_FULLTURN) / max(1, handling); // How far ahead into the future to try and predict + const tic_t futuresight = (TICRATE * KART_FULLTURN) / std::max(1, handling); // How far ahead into the future to try and predict const fixed_t speed = K_BotSpeedScaled(player, P_AproxDistance(player->mo->momx, player->mo->momy)); const INT32 startDist = 0; //(DEFAULT_WAYPOINT_RADIUS * mapobjectscale) / FRACUNIT; const INT32 maxDist = (DEFAULT_WAYPOINT_RADIUS * 3 * mapobjectscale) / FRACUNIT; // This function gets very laggy when it goes far distances, and going too far isn't very helpful anyway. - const INT32 distance = min(((speed / FRACUNIT) * (INT32)futuresight) + startDist, maxDist); + const INT32 distance = std::min(((speed / FRACUNIT) * static_cast(futuresight)) + startDist, maxDist); // Halves radius when encountering a wall on your way to your destination. - fixed_t radreduce = FRACUNIT; + fixed_t radReduce = FRACUNIT; + + fixed_t radius = INT32_MAX; + fixed_t radiusScaled = INT32_MAX; INT32 distanceleft = distance; - fixed_t smallestradius = INT32_MAX; angle_t angletonext = ANGLE_MAX; INT32 disttonext = INT32_MAX; INT32 distscaled = INT32_MAX; @@ -761,16 +885,16 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) boolean pathfindsuccess = false; path_t pathtofinish = {0}; - botprediction_t *predict = NULL; + botprediction_t *predict = nullptr; size_t i; - if (wp == NULL || P_MobjWasRemoved(wp->mobj) == true) + if (wp == nullptr || P_MobjWasRemoved(wp->mobj) == true) { // Can't do any of this if we don't have a waypoint. - return NULL; + return nullptr; } - predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); + predict = static_cast(Z_Calloc(sizeof(botprediction_t), PU_LEVEL, nullptr)); // Init defaults in case of pathfind failure angletonext = R_PointToAngle2(prevwpmobj->x, prevwpmobj->y, wp->mobj->x, wp->mobj->y); @@ -779,7 +903,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) distscaled = K_ScaleWPDistWithSlope(disttonext, angletonext, nextslope, P_MobjFlip(wp->mobj)) / FRACUNIT; pathfindsuccess = K_PathfindThruCircuit( - player->nextwaypoint, (unsigned)distanceleft, + wp, (unsigned)distanceleft, &pathtofinish, useshortcuts, huntbackwards ); @@ -789,8 +913,6 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) { for (i = 0; i < pathtofinish.numnodes; i++) { - fixed_t radius = 0; - wp = (waypoint_t *)pathtofinish.array[i].nodedata; if (i == 0) @@ -811,15 +933,10 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) { // If we can't get a direct path to this waypoint, reduce our prediction drastically. distscaled *= 4; - radreduce = FRACUNIT >> 1; - } - - radius = K_GetBotWaypointRadius(wp); - if (radius < smallestradius) - { - smallestradius = radius; + radReduce = FRACUNIT >> 1; } + K_GetBotWaypointRadius(wp, &radius, &radiusScaled); distanceleft -= distscaled; if (distanceleft <= 0) @@ -836,14 +953,16 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) // and use the smallest radius of all of the waypoints in the chain! predict->x = wp->mobj->x; predict->y = wp->mobj->y; - predict->radius = FixedMul(smallestradius, radreduce); + + predict->baseRadius = radius; + predict->radius = FixedMul(radiusScaled, radReduce); // Set the prediction coordinates between the 2 waypoints if there's still distance left. if (distanceleft > 0) { // Scaled with the leftover anglemul! - predict->x += P_ReturnThrustX(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT); - predict->y += P_ReturnThrustY(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT); + predict->x += P_ReturnThrustX(nullptr, angletonext, std::min(disttonext, distanceleft) * FRACUNIT); + predict->y += P_ReturnThrustY(nullptr, angletonext, std::min(disttonext, distanceleft) * FRACUNIT); } ps_bots[player - players].prediction += I_GetPreciseTime() - time; @@ -851,7 +970,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) } /*-------------------------------------------------- - static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player) + static void K_DrawPredictionDebug(botprediction_t *predict, const player_t *player) Draws objects to show where the viewpoint bot is trying to go. @@ -862,15 +981,15 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) Return:- None --------------------------------------------------*/ -static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player) +static void K_DrawPredictionDebug(botprediction_t *predict, const player_t *player) { - mobj_t *debugMobj = NULL; + mobj_t *debugMobj = nullptr; angle_t sideAngle = ANGLE_MAX; UINT8 i = UINT8_MAX; - I_Assert(predict != NULL); - I_Assert(player != NULL); - I_Assert(player->mo != NULL && P_MobjWasRemoved(player->mo) == false); + I_Assert(predict != nullptr); + I_Assert(player != nullptr); + I_Assert(player->mo != nullptr && P_MobjWasRemoved(player->mo) == false); sideAngle = player->mo->angle + ANGLE_90; @@ -887,7 +1006,7 @@ static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player) for (i = 0; i < 2; i++) { - mobj_t *radiusMobj = NULL; + mobj_t *radiusMobj = nullptr; fixed_t radiusX = predict->x, radiusY = predict->y; if (i & 1) @@ -915,7 +1034,7 @@ static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player) } /*-------------------------------------------------- - static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t *predict) + static INT32 K_HandleBotTrack(const player_t *player, ticcmd_t *cmd, botprediction_t *predict) Determines inputs for standard track driving. @@ -929,13 +1048,15 @@ static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player) --------------------------------------------------*/ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t *predict, angle_t destangle) { + ZoneScoped; + // Handle steering towards waypoints! INT32 turnamt = 0; SINT8 turnsign = 0; angle_t moveangle; INT32 anglediff; - I_Assert(predict != NULL); + I_Assert(predict != nullptr); moveangle = player->mo->angle; anglediff = AngleDeltaSigned(moveangle, destangle); @@ -944,7 +1065,7 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t * { turnsign = 1; } - else + else { turnsign = -1; } @@ -978,7 +1099,7 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t * // This makes predictions into turns a little nicer // Facing 90 degrees away from the predicted point gives you 0 radius rad = FixedMul(rad, - FixedDiv(max(0, ANGLE_90 - anglediff), ANGLE_90) + FixedDiv(std::max(0, ANGLE_90 - anglediff), ANGLE_90) ); // Become more precise the slower you're moving @@ -1013,17 +1134,164 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t * } /*-------------------------------------------------- - static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd) + static INT32 K_HandleBotReverse(const player_t *player, ticcmd_t *cmd, botprediction_t *predict) + + Determines inputs for reversing. + + Input Arguments:- + player - Player to generate the ticcmd for. + cmd - The player's ticcmd to modify. + predict - Pointer to the bot's prediction. + + Return:- + New value for turn amount. +--------------------------------------------------*/ +/*static INT32 K_HandleBotReverse(player_t *player, ticcmd_t *cmd, botprediction_t *predict, angle_t destangle) +{ + ZoneScoped; + + // Handle steering towards waypoints! + INT32 turnamt = 0; + SINT8 turnsign = 0; + angle_t moveangle, angle; + INT16 anglediff, momdiff; + + if (predict != nullptr) + { + // TODO: Should we reverse through bot controllers? + return K_HandleBotTrack(player, cmd, predict, destangle); + } + + if (player->nextwaypoint == nullptr + || player->nextwaypoint->mobj == nullptr + || P_MobjWasRemoved(player->nextwaypoint->mobj)) + { + // No data available... + return 0; + } + + if ((player->nextwaypoint->prevwaypoints != nullptr) + && (player->nextwaypoint->numprevwaypoints > 0U)) + { + size_t i; + for (i = 0U; i < player->nextwaypoint->numprevwaypoints; i++) + { + if (!K_GetWaypointIsEnabled(player->nextwaypoint->prevwaypoints[i])) + { + continue; + } + + destangle = R_PointToAngle2( + player->nextwaypoint->prevwaypoints[i]->mobj->x, player->nextwaypoint->prevwaypoints[i]->mobj->y, + player->nextwaypoint->mobj->x, player->nextwaypoint->mobj->y + ); + + break; + } + } + + // Calculate turn direction first. + moveangle = player->mo->angle; + angle = (moveangle - destangle); + + if (angle < ANGLE_180) + { + turnsign = -1; // Turn right + anglediff = AngleFixed(angle)>>FRACBITS; + } + else + { + turnsign = 1; // Turn left + anglediff = 360-(AngleFixed(angle)>>FRACBITS); + } + + anglediff = abs(anglediff); + turnamt = KART_FULLTURN * turnsign; + + // Now calculate momentum + momdiff = 180; + if (player->speed > player->mo->scale) + { + momdiff = 0; + moveangle = K_MomentumAngle(player->mo); + angle = (moveangle - destangle); + + if (angle < ANGLE_180) + { + momdiff = AngleFixed(angle)>>FRACBITS; + } + else + { + momdiff = 360-(AngleFixed(angle)>>FRACBITS); + } + + momdiff = abs(momdiff); + } + + if (anglediff > 90 || momdiff < 90) + { + // We're not facing the track, + // or we're going too fast. + // Let's E-Brake. + cmd->forwardmove = 0; + cmd->buttons |= BT_ACCELERATE|BT_BRAKE; + } + else + { + fixed_t slopeMul = FRACUNIT; + + if (player->mo->standingslope != nullptr) + { + const pslope_t *slope = player->mo->standingslope; + + if (!(slope->flags & SL_NOPHYSICS) && abs(slope->zdelta) >= FRACUNIT/21) + { + angle_t sangle = player->mo->angle - slope->xydirection; + + if (P_MobjFlip(player->mo) * slope->zdelta < 0) + sangle ^= ANGLE_180; + + slopeMul = FRACUNIT - FINECOSINE(sangle >> ANGLETOFINESHIFT); + } + } + +#define STEEP_SLOPE (FRACUNIT*11/10) + if (slopeMul > STEEP_SLOPE) + { + // Slope is too steep to reverse -- EBrake. + cmd->forwardmove = 0; + cmd->buttons |= BT_ACCELERATE|BT_BRAKE; + } + else + { + cmd->forwardmove = -MAXPLMOVE; + cmd->buttons |= BT_BRAKE; //|BT_LOOKBACK + } +#undef STEEP_SLOPE + + if (anglediff < 10) + { + turnamt = 0; + } + } + + return turnamt; +}*/ + +/*-------------------------------------------------- + static void K_BuildBotTiccmdNormal(const player_t *player, ticcmd_t *cmd) Build ticcmd for bots with a style of BOT_STYLE_NORMAL --------------------------------------------------*/ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd) { precise_t t = 0; - botprediction_t *predict = NULL; + + botprediction_t *predict = nullptr; + auto predict_finally = srb2::finally([&predict]() { Z_Free(predict); }); + angle_t destangle = 0; INT32 turnamt = 0; - const line_t *botController = player->botvars.controller != UINT16_MAX ? &lines[player->botvars.controller] : NULL; if (!(gametyperules & GTR_BOTS) // No bot behaviors || K_GetNumWaypoints() == 0 // No waypoints @@ -1041,17 +1309,16 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd) return; } - botController = K_FindBotController(player->mo); - if (botController == NULL) - { - player->botvars.controller = UINT16_MAX; - } - else - { - player->botvars.controller = botController - lines; - } + // Defanging bots for testing. + #ifdef DEVELOP + if (!cv_botcontrol.value) + return; + #endif - if (botController != NULL && (botController->args[1] & TMBOT_NOCONTROL)) + // Actual gameplay behaviors below this block! + const botcontroller_t *botController = K_GetBotController(player->mo); + + if (botController != nullptr && (botController->flags & TMBOT_NOCONTROL) == TMBOT_NOCONTROL) { // Disable bot controls entirely. return; @@ -1059,23 +1326,28 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd) destangle = player->mo->angle; - if (botController != NULL && (botController->args[1] & TMBOT_FORCEDIR)) + boolean forcedDir = false; + if (botController != nullptr && (botController->flags & TMBOT_FORCEDIR) == TMBOT_FORCEDIR) { const fixed_t dist = DEFAULT_WAYPOINT_RADIUS * player->mo->scale; - // X Offset: Movement direction - destangle = FixedAngle(botController->args[2] * FRACUNIT); - // Overwritten prediction - predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); + predict = static_cast(Z_Calloc(sizeof(botprediction_t), PU_STATIC, nullptr)); - predict->x = player->mo->x + FixedMul(dist, FINECOSINE(destangle >> ANGLETOFINESHIFT)); - predict->y = player->mo->y + FixedMul(dist, FINESINE(destangle >> ANGLETOFINESHIFT)); + predict->x = player->mo->x + FixedMul(dist, FINECOSINE(botController->forceAngle >> ANGLETOFINESHIFT)); + predict->y = player->mo->y + FixedMul(dist, FINESINE(botController->forceAngle >> ANGLETOFINESHIFT)); predict->radius = (DEFAULT_WAYPOINT_RADIUS / 4) * mapobjectscale; - } - if (leveltime <= starttime) - { + forcedDir = true; + } + + if (forcedDir == true) + { + destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); + turnamt = K_HandleBotTrack(player, cmd, predict, destangle); + } + else if (leveltime <= starttime ) + { if (leveltime >= starttime-TICRATE-TICRATE/7) { cmd->buttons |= BT_ACCELERATE; @@ -1085,13 +1357,13 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd) else { // Handle steering towards waypoints! - if (predict == NULL) + if (predict == nullptr) { // Create a prediction. predict = K_CreateBotPrediction(player); } - if (predict != NULL) + if (predict != nullptr) { K_NudgePredictionTowardsObjects(predict, player); destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); @@ -1099,7 +1371,9 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd) } } + if (player->exiting == 0) { + // TODO: Allowing projectile items like orbinaut while e-braking would be nice, maybe just pass in the spindash variable? t = I_GetPreciseTime(); K_BotItemUsage(player, cmd, turnamt); ps_bots[player - players].item = I_GetPreciseTime() - t; @@ -1153,14 +1427,12 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd) } // Free the prediction we made earlier - if (predict != NULL) + if (predict != nullptr) { - if (cv_kartdebugbotpredict.value != 0 && player - players == displayplayers[0]) + if (cv_kartdebugbotpredict.value != 0 && player - players == displayplayers[0] && !(paused || P_AutoPause())) { K_DrawPredictionDebug(predict, player); } - - Z_Free(predict); } } @@ -1169,19 +1441,27 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd) See header file for description. --------------------------------------------------*/ -void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) +void K_BuildBotTiccmd( + player_t *player, // annoyingly NOT const because of LUA_HookTiccmd... grumble grumble + ticcmd_t *cmd) { + ZoneScoped; + // Remove any existing controls memset(cmd, 0, sizeof(ticcmd_t)); - if (player->mo == NULL - || player->spectator == true) + if (player->mo == nullptr + || player->spectator == true + || G_GamestateUsesLevel() == false) { // Not in the level. return; } - // Complete override of all ticcmd functionality + // Complete override of all ticcmd functionality. + // May add more hooks to individual pieces of bot ticcmd, + // but this should always be here so anyone can roll + // their own :) if (LUA_HookTiccmd(player, cmd, HOOK(BotTiccmd)) == true) { cmd->flags |= TICCMD_BOT; @@ -1212,19 +1492,15 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ void K_UpdateBotGameplayVars(player_t *player) { - const line_t *botController; - if (gamestate != GS_LEVEL || !player->mo) { // Not in the level. return; } - botController = K_FindBotController(player->mo); - - player->botvars.controller = botController ? (botController - lines) : UINT16_MAX; player->botvars.rubberband = K_UpdateRubberband(player); player->botvars.turnconfirm += player->cmd.bot.turnconfirm; + K_UpdateBotGameplayVarsItemUsage(player); } diff --git a/src/k_bot.h b/src/k_bot.h index cf1225762..267b13450 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -1,7 +1,7 @@ -// SONIC ROBO BLAST 2 KART +// DR. ROBOTNIK'S RING RACERS //----------------------------------------------------------------------------- -// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour -// Copyright (C) 2018-2020 by Kart Krew +// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2024 by Kart Krew // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -13,6 +13,7 @@ #ifndef __K_BOT__ #define __K_BOT__ +#include "typedef.h" #include "k_waypoint.h" #include "d_player.h" #include "r_defs.h" @@ -21,28 +22,41 @@ extern "C" { #endif +#ifdef DEVELOP + extern consvar_t cv_botcontrol; +#endif + // Maximum value of botvars.difficulty -#define MAXBOTDIFFICULTY 13 +#define MAXBOTDIFFICULTY (13) // Level of a "difficult" bot. The max bot level was increased, but this keeps all of the same calculations. -#define DIFFICULTBOT 9 +#define DIFFICULTBOT (9) // How many tics in a row do you need to turn in this direction before we'll let you turn. // Made it as small as possible without making it look like the bots are twitching constantly. #define BOTTURNCONFIRM 4 -// Point for bots to aim for -struct botprediction_t { - fixed_t x, y; - fixed_t radius; -}; +// How many tics with only one spindash-viable condition before we'll let you spindash. +#define BOTSPINDASHCONFIRM (4*TICRATE) +// How many tics without being able to make progress before we'll let you respawn. +#define BOTRESPAWNCONFIRM (5*TICRATE) + +// How long it takes for a Lv.1 bot to decide to pick an item. +#define BOT_ITEM_DECISION_TIME (2*TICRATE) + +// Point for bots to aim for +struct botprediction_t +{ + fixed_t x, y; + fixed_t radius, baseRadius; +}; // AVAILABLE FOR LUA /*-------------------------------------------------- - boolean K_PlayerUsesBotMovement(player_t *player); + boolean K_PlayerUsesBotMovement(const player_t *player); Tells if this player is being controlled via bot movement code (is a bot, or is exiting). @@ -53,7 +67,7 @@ struct botprediction_t { true if using bot movement code, otherwise false. --------------------------------------------------*/ -boolean K_PlayerUsesBotMovement(player_t *player); +boolean K_PlayerUsesBotMovement(const player_t *player); /*-------------------------------------------------- @@ -73,7 +87,43 @@ boolean K_BotCanTakeCut(player_t *player); /*-------------------------------------------------- - fixed_t K_BotRubberband(player_t *player); + const botcontroller_t *K_GetBotController(mobj_t *mobj); + + Retrieves the current bot controller values from + the player's current sector. + + Input Arguments:- + mobj - The player's object to get the bot controller for. + + Return:- + Pointer to the sector's bot controller struct. +--------------------------------------------------*/ + +const botcontroller_t *K_GetBotController(mobj_t *mobj); + + +/*-------------------------------------------------- + fixed_t K_BotMapModifier(void); + + Gives a multiplier, based on the track complexity. + Track complexity is a measure of how easy it is for + the bots to continuously rubberband. This is used + to make the rubberbanding and other difficulty + adjustments feel roughly the same between wildly + different layouts. + + Input Arguments:- + N/A + + Return:- + A multiplier in fixed point scale, between 0.0 and 2.0. +--------------------------------------------------*/ + +fixed_t K_BotMapModifier(void); + + +/*-------------------------------------------------- + fixed_t K_BotRubberband(const player_t *player); Gives a multiplier for a bot's rubberbanding. Meant to be used for acceleration and handling. @@ -85,7 +135,7 @@ boolean K_BotCanTakeCut(player_t *player); A multiplier in fixed point scale. --------------------------------------------------*/ -fixed_t K_BotRubberband(player_t *player); +fixed_t K_BotRubberband(const player_t *player); /*-------------------------------------------------- @@ -125,13 +175,10 @@ fixed_t K_UpdateRubberband(player_t *player); fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy); -// NOT AVAILABLE FOR LUA - - /*-------------------------------------------------- - boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *newplayernum); + boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p); - Returns the waypoint actually being used as the finish line. + Adds a new bot, using code intended to run on all clients. Input Arguments:- skin - Skin number that the bot will use. @@ -141,12 +188,53 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t Is a pointer so that this function can be called multiple times to add more than one bot. Return:- - true if a bot packet can be sent, otherwise false. + true if a bot was added, otherwise false. --------------------------------------------------*/ boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p); +// NOT AVAILABLE FOR LUA + + +/*-------------------------------------------------- + void K_SetNameForBot(UINT8 newplayernum, const char *realname) + + Sets a bot's name. + by K_AddBot, and indirectly by K_AddBotFromServer by sending + a packet. + + Input Arguments:- + newplayernum - Player slot number to set name for. + realname - Proposed name for bot. + + Return:- + None +--------------------------------------------------*/ + +void K_SetNameForBot(UINT8 newplayernum, const char *realname); + + +/*-------------------------------------------------- + void K_SetBot(UINT8 newplayernum, UINT8 skinnum, UINT8 difficulty, botStyle_e style); + + Sets a player ID to be a new bot directly. Invoked directly + by K_AddBot, and indirectly by K_AddBotFromServer by sending + a packet. + + Input Arguments:- + newplayernum - Player slot number to set as a bot. + skin - Skin number that the bot will use. + difficulty - Difficulty level this bot will use. + style - Bot style to spawn this bot with, see botStyle_e. + + Return:- + None +--------------------------------------------------*/ + +void K_SetBot(UINT8 newplayernum, UINT8 skinnum, UINT8 difficulty, botStyle_e style); + + /*-------------------------------------------------- void K_UpdateMatchRaceBots(void); @@ -205,11 +293,11 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t None --------------------------------------------------*/ -void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player); +void K_NudgePredictionTowardsObjects(botprediction_t *predict, const player_t *player); /*-------------------------------------------------- - INT32 K_PositionBully(player_t *player) + INT32 K_PositionBully(const player_t *player) Calculates a turn value to reach a player that can be bullied. @@ -220,7 +308,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) INT32_MAX if couldn't find anything, otherwise a steering value. --------------------------------------------------*/ -INT32 K_PositionBully(player_t *player); +INT32 K_PositionBully(const player_t *player); /*-------------------------------------------------- @@ -240,6 +328,23 @@ INT32 K_PositionBully(player_t *player); void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd); +/*-------------------------------------------------- + void K_UpdateBotGameplayVarsItemUsage(player_t *player) + + Updates gamestate affecting botvars, relating to + item usage. This must be called for both client + and server. + + Input Arguments:- + player - Player to whom to update the botvars. + + Return:- + N/A +--------------------------------------------------*/ + +void K_UpdateBotGameplayVarsItemUsage(player_t *player); + + /*-------------------------------------------------- void K_UpdateBotGameplayVars(player_t *player); @@ -272,22 +377,6 @@ void K_UpdateBotGameplayVars(player_t *player); void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt); -/*-------------------------------------------------- - void K_UpdateBotGameplayVarsItemUsage(player_t *player) - - Updates gamestate affecting botvars, relating to - item usage. This must be called for both client - and server. - - Input Arguments:- - player - Player to whom to update the botvars. - - Return:- - N/A ---------------------------------------------------*/ - -void K_UpdateBotGameplayVarsItemUsage(player_t *player); - #ifdef __cplusplus } // extern "C" diff --git a/src/k_botitem.c b/src/k_botitem.cpp similarity index 77% rename from src/k_botitem.c rename to src/k_botitem.cpp index 9285b8539..158bb9e6c 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.cpp @@ -1,15 +1,19 @@ -// SONIC ROBO BLAST 2 KART +// DR. ROBOTNIK'S RING RACERS //----------------------------------------------------------------------------- -// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour -// Copyright (C) 2018-2020 by Kart Krew +// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2024 by Kart Krew // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file k_botitem.c +/// \file k_botitem.cpp /// \brief Bot item usage logic +#include + +#include + #include "doomdef.h" #include "d_player.h" #include "g_game.h" @@ -29,7 +33,7 @@ #include "m_easing.h" /*-------------------------------------------------- - static inline boolean K_ItemButtonWasDown(player_t *player) + static inline boolean K_ItemButtonWasDown(const player_t *player) Looks for players around the bot, and presses the item button if there is one in range. @@ -40,13 +44,13 @@ Return:- true if the item button was pressed last tic, otherwise false. --------------------------------------------------*/ -static inline boolean K_ItemButtonWasDown(player_t *player) +static inline boolean K_ItemButtonWasDown(const player_t *player) { return (player->oldcmd.buttons & BT_ATTACK); } /*-------------------------------------------------- - static boolean K_BotUseItemNearPlayer(player_t *player, ticcmd_t *cmd, fixed_t radius) + static boolean K_BotUseItemNearPlayer(const player_t *player, ticcmd_t *cmd, fixed_t radius) Looks for players around the bot, and presses the item button if there is one in range. @@ -59,8 +63,10 @@ static inline boolean K_ItemButtonWasDown(player_t *player) Return:- true if a player was found & we can press the item button, otherwise false. --------------------------------------------------*/ -static boolean K_BotUseItemNearPlayer(player_t *player, ticcmd_t *cmd, fixed_t radius) +static boolean K_BotUseItemNearPlayer(const player_t *player, ticcmd_t *cmd, fixed_t radius) { + ZoneScoped; + UINT8 i; if (K_ItemButtonWasDown(player) == true) @@ -104,7 +110,7 @@ static boolean K_BotUseItemNearPlayer(player_t *player, ticcmd_t *cmd, fixed_t r } /*-------------------------------------------------- - static player_t *K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius) + static player_t *K_PlayerNearSpot(const player_t *player, fixed_t x, fixed_t y, fixed_t radius) Looks for players around a specified x/y coordinate. @@ -117,8 +123,10 @@ static boolean K_BotUseItemNearPlayer(player_t *player, ticcmd_t *cmd, fixed_t r Return:- The player we found, NULL if nothing was found. --------------------------------------------------*/ -static player_t *K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_t radius) +static player_t *K_PlayerNearSpot(const player_t *player, fixed_t x, fixed_t y, fixed_t radius) { + ZoneScoped; + UINT8 i; for (i = 0; i < MAXPLAYERS; i++) @@ -155,7 +163,7 @@ static player_t *K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_ } /*-------------------------------------------------- - static player_t *K_PlayerPredictThrow(player_t *player, UINT8 extra) + static player_t *K_PlayerPredictThrow(const player_t *player, UINT8 extra) Looks for players around the predicted coordinates of their thrown item. @@ -166,36 +174,21 @@ static player_t *K_PlayerNearSpot(player_t *player, fixed_t x, fixed_t y, fixed_ Return:- The player we're trying to throw at, NULL if none was found. --------------------------------------------------*/ -static player_t *K_PlayerPredictThrow(player_t *player, UINT8 extra) +static player_t *K_PlayerPredictThrow(const player_t *player, UINT8 extra) { + ZoneScoped; + const fixed_t dist = (30 + (extra * 10)) * player->mo->scale; const UINT32 airtime = FixedDiv(dist + player->mo->momz, gravity); - fixed_t throwspeed; - fixed_t estx; - fixed_t esty; - - switch (gamespeed) - { - case 0: - throwspeed = 68*mapobjectscale; // Avg Speed is 34 - break; - case 2: - throwspeed = 96*mapobjectscale; // Avg Speed is 48 - break; - default: - throwspeed = 82*mapobjectscale; // Avg Speed is 41 - break; - } - - estx = player->mo->x + P_ReturnThrustX(NULL, player->mo->angle, (throwspeed + player->speed) * airtime); - - esty = player->mo->y + P_ReturnThrustY(NULL, player->mo->angle, (throwspeed + player->speed) * airtime); - + const fixed_t throwspeed = FixedMul(82 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); + const fixed_t estx = player->mo->x + P_ReturnThrustX(NULL, player->mo->angle, (throwspeed + player->speed) * airtime); + const fixed_t esty = player->mo->y + P_ReturnThrustY(NULL, player->mo->angle, (throwspeed + player->speed) * airtime); + return K_PlayerNearSpot(player, estx, esty, player->mo->radius * 2); } /*-------------------------------------------------- - static player_t *K_PlayerInCone(player_t *player, UINT16 cone, boolean flip) + static player_t *K_PlayerInCone(const player_t *player, UINT16 cone, boolean flip) Looks for players in the . @@ -208,8 +201,10 @@ static player_t *K_PlayerPredictThrow(player_t *player, UINT8 extra) Return:- true if a player was found in the cone, otherwise false. --------------------------------------------------*/ -static player_t *K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, boolean flip) +static player_t *K_PlayerInCone(const player_t *player, fixed_t radius, UINT16 cone, boolean flip) { + ZoneScoped; + UINT8 i; for (i = 0; i < MAXPLAYERS; i++) @@ -247,7 +242,7 @@ static player_t *K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, b { ad = AngleFixed(a)>>FRACBITS; } - else + else { ad = 360-(AngleFixed(a)>>FRACBITS); } @@ -275,7 +270,7 @@ static player_t *K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, b } /*-------------------------------------------------- - static boolean K_RivalBotAggression(player_t *bot, player_t *target) + static boolean K_RivalBotAggression(const player_t *bot, const player_t *target) Returns if a bot is a rival & wants to be aggressive to a player. @@ -286,7 +281,7 @@ static player_t *K_PlayerInCone(player_t *player, fixed_t radius, UINT16 cone, b Return:- false if not the rival. false if the target is another bot. Otherwise, true. --------------------------------------------------*/ -static boolean K_RivalBotAggression(player_t *bot, player_t *target) +static boolean K_RivalBotAggression(const player_t *bot, const player_t *target) { if (bot == NULL || target == NULL) { @@ -317,19 +312,20 @@ static boolean K_RivalBotAggression(player_t *bot, player_t *target) } /*-------------------------------------------------- - static void K_ItemConfirmForTarget(player_t *bot, player_t *target, UINT16 amount) + static void K_ItemConfirmForTarget(const player_t *bot, ticcmd_t *cmd, const player_t *target, UINT16 amount) Handles updating item confirm values for offense items. Input Arguments:- bot - Bot to check. + cmd - Bot's ticcmd to edit. target - Who the bot wants to attack. amount - Amount to increase item confirm time by. Return:- None --------------------------------------------------*/ -static void K_ItemConfirmForTarget(player_t *bot, ticcmd_t *cmd, player_t *target, UINT16 amount) +static void K_ItemConfirmForTarget(const player_t *bot, ticcmd_t *cmd, const player_t *target, UINT16 amount) { if (bot == NULL || target == NULL) { @@ -349,7 +345,7 @@ static void K_ItemConfirmForTarget(player_t *bot, ticcmd_t *cmd, player_t *targe } /*-------------------------------------------------- - static boolean K_BotGenericPressItem(player_t *player, ticcmd_t *cmd, SINT8 dir) + static boolean K_BotGenericPressItem(const player_t *player, ticcmd_t *cmd, SINT8 dir) Presses the item button & aim buttons for the bot. @@ -361,8 +357,10 @@ static void K_ItemConfirmForTarget(player_t *bot, ticcmd_t *cmd, player_t *targe Return:- true if we could press, false if not. --------------------------------------------------*/ -static boolean K_BotGenericPressItem(player_t *player, ticcmd_t *cmd, SINT8 dir) +static boolean K_BotGenericPressItem(const player_t *player, ticcmd_t *cmd, SINT8 dir) { + ZoneScoped; + if (K_ItemButtonWasDown(player) == true) { return false; @@ -375,7 +373,7 @@ static boolean K_BotGenericPressItem(player_t *player, ticcmd_t *cmd, SINT8 dir) } /*-------------------------------------------------- - static void K_BotItemGenericTap(player_t *player, ticcmd_t *cmd) + static void K_BotItemGenericTap(const player_t *player, ticcmd_t *cmd) Item usage for generic items that you need to tap. @@ -386,8 +384,10 @@ static boolean K_BotGenericPressItem(player_t *player, ticcmd_t *cmd, SINT8 dir) Return:- None --------------------------------------------------*/ -static void K_BotItemGenericTap(player_t *player, ticcmd_t *cmd) +static void K_BotItemGenericTap(const player_t *player, ticcmd_t *cmd) { + ZoneScoped; + if (K_ItemButtonWasDown(player) == false) { cmd->buttons |= BT_ATTACK; @@ -396,7 +396,7 @@ static void K_BotItemGenericTap(player_t *player, ticcmd_t *cmd) } /*-------------------------------------------------- - static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean mine) + static boolean K_BotRevealsGenericTrap(const player_t *player, INT16 turnamt, boolean mine) Decides if a bot is ready to reveal their trap item or not. @@ -408,8 +408,10 @@ static void K_BotItemGenericTap(player_t *player, ticcmd_t *cmd) Return:- true if we want the bot to reveal their banana, otherwise false. --------------------------------------------------*/ -static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean mine) +static boolean K_BotRevealsGenericTrap(const player_t *player, INT16 turnamt, boolean mine) { + ZoneScoped; + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); if (abs(turnamt) >= KART_FULLTURN/2) @@ -443,7 +445,7 @@ static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean } /*-------------------------------------------------- - static void K_BotItemGenericTrapShield(player_t *player, ticcmd_t *cmd, INT16 turnamt, boolean mine) + static void K_BotItemGenericTrapShield(const player_t *player, ticcmd_t *cmd, INT16 turnamt, boolean mine) Item usage for Eggman shields. @@ -456,8 +458,10 @@ static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean Return:- None --------------------------------------------------*/ -static void K_BotItemGenericTrapShield(player_t *player, ticcmd_t *cmd, INT16 turnamt, boolean mine) +static void K_BotItemGenericTrapShield(const player_t *player, ticcmd_t *cmd, INT16 turnamt, boolean mine) { + ZoneScoped; + if (player->itemflags & IF_ITEMOUT) { return; @@ -465,14 +469,14 @@ static void K_BotItemGenericTrapShield(player_t *player, ticcmd_t *cmd, INT16 tu cmd->bot.itemconfirm++; - if (K_BotRevealsGenericTrap(player, turnamt, mine) || (player->botvars.itemconfirm++ > 5*TICRATE)) + if (K_BotRevealsGenericTrap(player, turnamt, mine) || (player->botvars.itemconfirm > 5*TICRATE)) { K_BotGenericPressItem(player, cmd, 0); } } /*-------------------------------------------------- - static void K_BotItemGenericOrbitShield(player_t *player, ticcmd_t *cmd) + static void K_BotItemGenericOrbitShield(const player_t *player, ticcmd_t *cmd) Item usage for orbitting shields. @@ -483,8 +487,10 @@ static void K_BotItemGenericTrapShield(player_t *player, ticcmd_t *cmd, INT16 tu Return:- None --------------------------------------------------*/ -static void K_BotItemGenericOrbitShield(player_t *player, ticcmd_t *cmd) +static void K_BotItemGenericOrbitShield(const player_t *player, ticcmd_t *cmd) { + ZoneScoped; + if (player->itemflags & IF_ITEMOUT) { return; @@ -494,7 +500,7 @@ static void K_BotItemGenericOrbitShield(player_t *player, ticcmd_t *cmd) } /*-------------------------------------------------- - static void K_BotItemSneaker(player_t *player, ticcmd_t *cmd) + static void K_BotItemSneaker(const player_t *player, ticcmd_t *cmd) Item usage for sneakers. @@ -507,6 +513,8 @@ static void K_BotItemGenericOrbitShield(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ static void K_BotItemSneaker(player_t *player, ticcmd_t *cmd) { + ZoneScoped; + if (P_IsObjectOnGround(player->mo) == false) { // Don't use while mid-air. @@ -543,8 +551,10 @@ static void K_BotItemSneaker(player_t *player, ticcmd_t *cmd) Return:- None --------------------------------------------------*/ -static void K_BotItemRocketSneaker(player_t *player, ticcmd_t *cmd) +static void K_BotItemRocketSneaker(const player_t *player, ticcmd_t *cmd) { + ZoneScoped; + if (P_IsObjectOnGround(player->mo) == false) { // Don't use while mid-air. @@ -578,8 +588,10 @@ static void K_BotItemRocketSneaker(player_t *player, ticcmd_t *cmd) Return:- None --------------------------------------------------*/ -static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) +static void K_BotItemBanana(const player_t *player, ticcmd_t *cmd, INT16 turnamt) { + ZoneScoped; + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); SINT8 throwdir = -1; boolean tryLookback = false; @@ -635,8 +647,10 @@ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) Return:- None --------------------------------------------------*/ -static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) +static void K_BotItemMine(const player_t *player, ticcmd_t *cmd, INT16 turnamt) { + ZoneScoped; + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); SINT8 throwdir = 0; boolean tryLookback = false; @@ -698,8 +712,10 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) Return:- None --------------------------------------------------*/ -static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) +static void K_BotItemLandmine(const player_t *player, ticcmd_t *cmd, INT16 turnamt) { + ZoneScoped; + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); player_t *target = NULL; @@ -714,7 +730,6 @@ static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) if (target != NULL) { K_ItemConfirmForTarget(player, cmd, target, player->botvars.difficulty); - cmd->buttons |= BT_LOOKBACK; } @@ -736,8 +751,10 @@ static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) Return:- None --------------------------------------------------*/ -static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) +static void K_BotItemEggman(const player_t *player, ticcmd_t *cmd) { + ZoneScoped; + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y); SINT8 throwdir = -1; @@ -761,9 +778,9 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) tryLookback = true; } - if (stealth > 1 || player->itemroulette > 0) + if (stealth > 1 || player->itemroulette) { - player->botvars.itemconfirm += player->botvars.difficulty * 4; + cmd->bot.itemconfirm += player->botvars.difficulty * 4; throwdir = -1; } @@ -779,7 +796,7 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) } /*-------------------------------------------------- - static boolean K_BotRevealsEggbox(player_t *player) + static boolean K_BotRevealsEggbox(const player_t *player) Decides if a bot is ready to place their Eggman item or not. @@ -789,8 +806,10 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) Return:- true if we want the bot to reveal their eggbox, otherwise false. --------------------------------------------------*/ -static boolean K_BotRevealsEggbox(player_t *player) +static boolean K_BotRevealsEggbox(const player_t *player) { + ZoneScoped; + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y); player_t *target = NULL; @@ -819,7 +838,7 @@ static boolean K_BotRevealsEggbox(player_t *player) } /*-------------------------------------------------- - static void K_BotItemEggmanShield(player_t *player, ticcmd_t *cmd) + static void K_BotItemEggmanShield(const player_t *player, ticcmd_t *cmd) Item usage for Eggman shields. @@ -830,8 +849,10 @@ static boolean K_BotRevealsEggbox(player_t *player) Return:- None --------------------------------------------------*/ -static void K_BotItemEggmanShield(player_t *player, ticcmd_t *cmd) +static void K_BotItemEggmanShield(const player_t *player, ticcmd_t *cmd) { + ZoneScoped; + if (player->itemflags & IF_EGGMANOUT) { return; @@ -839,14 +860,14 @@ static void K_BotItemEggmanShield(player_t *player, ticcmd_t *cmd) cmd->bot.itemconfirm++; - if (K_BotRevealsEggbox(player) == true || (player->botvars.itemconfirm++ > 20*TICRATE)) + if (K_BotRevealsEggbox(player) == true || (player->botvars.itemconfirm > 20*TICRATE)) { K_BotGenericPressItem(player, cmd, 0); } } /*-------------------------------------------------- - static void K_BotItemEggmanExplosion(player_t *player, ticcmd_t *cmd) + static void K_BotItemEggmanExplosion(const player_t *player, ticcmd_t *cmd) Item usage for Eggman explosions. @@ -857,8 +878,10 @@ static void K_BotItemEggmanShield(player_t *player, ticcmd_t *cmd) Return:- None --------------------------------------------------*/ -static void K_BotItemEggmanExplosion(player_t *player, ticcmd_t *cmd) +static void K_BotItemEggmanExplosion(const player_t *player, ticcmd_t *cmd) { + ZoneScoped; + if (player->position == 1) { // Hey, we aren't gonna find anyone up here... @@ -870,7 +893,7 @@ static void K_BotItemEggmanExplosion(player_t *player, ticcmd_t *cmd) } /*-------------------------------------------------- - static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) + static void K_BotItemOrbinaut(const player_t *player, ticcmd_t *cmd) Item usage for Orbinaut throwing. @@ -883,6 +906,8 @@ static void K_BotItemEggmanExplosion(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) { + ZoneScoped; + const fixed_t topspeed = K_GetKartSpeed(player, false, true); fixed_t radius = FixedMul(2560 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); SINT8 throwdir = -1; @@ -928,9 +953,9 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) } /*-------------------------------------------------- - static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd) + static void K_BotItemBallhog(const player_t *player, ticcmd_t *cmd) - Item usage for Drop Target throwing. + Item usage for Ballhog throwing. Input Arguments:- player - Bot to do this for. @@ -939,8 +964,87 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) Return:- None --------------------------------------------------*/ -static void K_BotItemDropTarget(player_t *player, INT16 turnamt, ticcmd_t *cmd) +static void K_BotItemBallhog(player_t *player, ticcmd_t *cmd) { + ZoneScoped; + + const fixed_t topspeed = K_GetKartSpeed(player, false, true); + fixed_t radius = FixedMul(2560 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); + SINT8 throwdir = -1; + boolean tryLookback = false; + UINT8 snipeMul = 2; + player_t *target = NULL; + boolean hold = false; + + if (player->speed > topspeed) + { + radius = FixedMul(radius, FixedDiv(player->speed, topspeed)); + snipeMul = 3; // Confirm faster when you'll throw it with a bunch of extra speed!! + } + + target = K_PlayerInCone(player, radius, 15, false); + if (target != NULL) + { + K_ItemConfirmForTarget(player, cmd, target, player->botvars.difficulty * snipeMul); + throwdir = 1; + } + else + { + target = K_PlayerInCone(player, radius, 15, true); + + if (target != NULL) + { + K_ItemConfirmForTarget(player, cmd, target, player->botvars.difficulty); + throwdir = -1; + tryLookback = true; + } + } + + if (tryLookback == true && throwdir == -1) + { + cmd->buttons |= BT_LOOKBACK; + } + + if (target != NULL) + { + // Charge up! + hold = true; + } + else + { + // If we lose sight of the target, then we'll just + // let go and it'll do a partial-blast. + + // If we've been waiting for too long though, then + // we'll go for the full charge :) + cmd->bot.itemconfirm++; + hold = (player->botvars.itemconfirm > 10*TICRATE); + } + + if (hold == true) + { + cmd->throwdir = KART_FULLTURN * throwdir; + cmd->buttons |= BT_ATTACK; + } +} + +/*-------------------------------------------------- + static void K_BotItemDropTarget(const player_t *player, ticcmd_t *cmd, INT16 turnamt) + + Item usage for Drop Target throwing. + + Input Arguments:- + player - Bot to do this for. + cmd - Bot's ticcmd to edit. + turnamt - How hard they currently are turning. + + Return:- + None +--------------------------------------------------*/ +static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd, INT16 turnamt) +{ + ZoneScoped; + const fixed_t topspeed = K_GetKartSpeed(player, false, true); fixed_t radius = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); SINT8 throwdir = -1; @@ -992,7 +1096,7 @@ static void K_BotItemDropTarget(player_t *player, INT16 turnamt, ticcmd_t *cmd) } /*-------------------------------------------------- - static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) + static void K_BotItemJawz(const player_t *player, ticcmd_t *cmd) Item usage for Jawz throwing. @@ -1005,6 +1109,8 @@ static void K_BotItemDropTarget(player_t *player, INT16 turnamt, ticcmd_t *cmd) --------------------------------------------------*/ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) { + ZoneScoped; + const fixed_t topspeed = K_GetKartSpeed(player, false, true); fixed_t radius = FixedMul(2560 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); SINT8 throwdir = 1; @@ -1072,9 +1178,9 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) } /*-------------------------------------------------- - static void K_BotItemLightning(player_t *player, ticcmd_t *cmd) + static void K_BotItemLightning(const player_t *player, ticcmd_t *cmd) - Item usage for Thunder Shield. + Item usage for Lightning Shield. Input Arguments:- player - Bot to do this for. @@ -1083,8 +1189,10 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) Return:- None --------------------------------------------------*/ -static void K_BotItemLightning(player_t *player, ticcmd_t *cmd) +static void K_BotItemLightning(const player_t *player, ticcmd_t *cmd) { + ZoneScoped; + fixed_t radius = 192 * player->mo->scale; radius = Easing_Linear(FRACUNIT * player->botvars.difficulty / MAXBOTDIFFICULTY, 2*radius, radius); @@ -1102,7 +1210,7 @@ static void K_BotItemLightning(player_t *player, ticcmd_t *cmd) } /*-------------------------------------------------- - static void K_BotItemBubble(player_t *player, ticcmd_t *cmd) + static void K_BotItemBubble(const player_t *player, ticcmd_t *cmd) Item usage for Bubble Shield. @@ -1113,8 +1221,10 @@ static void K_BotItemLightning(player_t *player, ticcmd_t *cmd) Return:- None --------------------------------------------------*/ -static void K_BotItemBubble(player_t *player, ticcmd_t *cmd) +static void K_BotItemBubble(const player_t *player, ticcmd_t *cmd) { + ZoneScoped; + boolean hold = false; if (player->bubbleblowup <= 0) @@ -1180,7 +1290,7 @@ static void K_BotItemBubble(player_t *player, ticcmd_t *cmd) } /*-------------------------------------------------- - static void K_BotItemFlame(player_t *player, ticcmd_t *cmd) + static void K_BotItemFlame(const player_t *player, ticcmd_t *cmd) Item usage for Flame Shield. @@ -1191,15 +1301,17 @@ static void K_BotItemBubble(player_t *player, ticcmd_t *cmd) Return:- None --------------------------------------------------*/ -static void K_BotItemFlame(player_t *player, ticcmd_t *cmd) +static void K_BotItemFlame(const player_t *player, ticcmd_t *cmd) { + ZoneScoped; + if (player->botvars.itemconfirm > 0) { cmd->bot.itemconfirm--; } else if (player->itemflags & IF_HOLDREADY) { - INT32 flamemax = player->flamelength * flameseg; + INT32 flamemax = player->flamelength; if (player->flamemeter < flamemax || flamemax == 0) { @@ -1213,7 +1325,7 @@ static void K_BotItemFlame(player_t *player, ticcmd_t *cmd) } /*-------------------------------------------------- - static void K_BotItemRings(player_t *player, ticcmd_t *cmd) + static void K_BotItemRings(const player_t *player, ticcmd_t *cmd) Item usage for rings. @@ -1226,8 +1338,22 @@ static void K_BotItemFlame(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ static void K_BotItemRings(player_t *player, ticcmd_t *cmd) { + ZoneScoped; + INT32 saferingsval = 16 - K_GetKartRingPower(player, false); + if (leveltime < starttime) + { + // Don't use rings during POSITION!! + return; + } + + if ((cmd->buttons & BT_ACCELERATE) == 0) + { + // Don't use rings if you're not trying to accelerate. + return; + } + if (P_IsObjectOnGround(player->mo) == false) { // Don't use while mid-air. @@ -1247,7 +1373,7 @@ static void K_BotItemRings(player_t *player, ticcmd_t *cmd) } /*-------------------------------------------------- - static void K_BotItemRouletteMash(player_t *player, ticcmd_t *cmd) + static void K_BotItemRouletteMash(const player_t *player, ticcmd_t *cmd) Item usage for item roulette mashing. @@ -1284,18 +1410,19 @@ static void K_BotItemRouletteMash(player_t *player, ticcmd_t *cmd) } /*-------------------------------------------------- - void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) + void K_BotItemUsage(const player_t *player, ticcmd_t *cmd, INT16 turnamt) See header file for description. --------------------------------------------------*/ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) { + ZoneScoped; + if (player->itemflags & IF_USERINGS) { - // Use rings! - - if (leveltime > starttime) + if (player->rings > 0) { + // Use rings! K_BotItemRings(player, cmd); } } @@ -1343,7 +1470,6 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) case KITEM_SPB: case KITEM_GROW: case KITEM_SHRINK: - case KITEM_HYUDORO: case KITEM_SUPERRING: K_BotItemGenericTap(player, cmd); break; @@ -1375,8 +1501,6 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemGenericOrbitShield(player, cmd); } else if (player->position != 1) // Hold onto orbiting items when in 1st :) - /* FALLTHRU */ - case KITEM_BALLHOG: { K_BotItemOrbinaut(player, cmd); } @@ -1402,8 +1526,12 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) } break; case KITEM_LANDMINE: + case KITEM_HYUDORO: // Function re-use, as they have about the same usage. K_BotItemLandmine(player, cmd, turnamt); break; + case KITEM_BALLHOG: + K_BotItemBallhog(player, cmd); + break; case KITEM_DROPTARGET: if (!(player->itemflags & IF_ITEMOUT)) { @@ -1411,7 +1539,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) } else { - K_BotItemDropTarget(player, turnamt, cmd); + K_BotItemDropTarget(player, cmd, turnamt); } break; case KITEM_THUNDERSHIELD: @@ -1448,5 +1576,70 @@ void K_UpdateBotGameplayVarsItemUsage(player_t *player) return; } - player->botvars.itemconfirm += player->cmd.bot.itemconfirm; + if (player->cmd.bot.itemconfirm < 0 && abs(player->cmd.bot.itemconfirm) > player->botvars.itemconfirm) + { + player->botvars.itemconfirm = 0; + } + else + { + player->botvars.itemconfirm += player->cmd.bot.itemconfirm; + } + + if (player->itemflags & IF_USERINGS) + { + ; + } + else + { + if (player->itemroulette) + { + // Mashing behaviors + K_BotItemRouletteMash(player, &player->cmd); + return; + } + + if (player->stealingtimer == 0) + { + if (player->eggmanexplode) + { + ; + } + else if (player->itemflags & IF_EGGMANOUT) + { + ; + } + else if (player->rocketsneakertimer > 0) + { + ; + } + else + { + switch (player->itemtype) + { + default: + { + break; + } + case KITEM_FLAMESHIELD: + { + if (player->botvars.itemconfirm == 0 + && (player->itemflags & IF_HOLDREADY) == IF_HOLDREADY) + { + INT32 flamemax = player->flamelength; + + if (player->flamemeter < flamemax || flamemax == 0) + { + ; + } + else + { + player->botvars.itemconfirm = (3 * flamemax / 4) + (TICRATE / 2); + } + } + break; + } + } + } + } + } } diff --git a/src/k_botsearch.c b/src/k_botsearch.cpp similarity index 69% rename from src/k_botsearch.c rename to src/k_botsearch.cpp index 5e5b108c9..b25df5763 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.cpp @@ -1,15 +1,19 @@ -// SONIC ROBO BLAST 2 KART +// DR. ROBOTNIK'S RING RACERS //----------------------------------------------------------------------------- -// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour -// Copyright (C) 2018-2020 by Kart Krew +// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2024 by Kart Krew // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file k_botsearch.c +/// \file k_botsearch.cpp /// \brief Bot blockmap search functions +#include + +#include + #include "doomdef.h" #include "d_player.h" #include "g_game.h" @@ -28,28 +32,7 @@ #include "r_things.h" // numskins #include "p_slopes.h" // P_GetZAt #include "m_perfstats.h" - -struct globalsmuggle -{ - mobj_t *botmo; - botprediction_t *predict; - fixed_t distancetocheck; - - INT64 gotoAvgX[2], gotoAvgY[2]; - UINT32 gotoObjs[2]; - - INT64 avoidAvgX[2], avoidAvgY[2]; - UINT32 avoidObjs[2]; - - fixed_t annoyscore; - mobj_t *annoymo; - - fixed_t closestlinedist; - - fixed_t eggboxx, eggboxy; - UINT8 randomitems; - UINT8 eggboxes; -} globalsmuggle; +#include "k_objects.h" /*-------------------------------------------------- static BlockItReturn_t K_FindEggboxes(mobj_t *thing) @@ -63,6 +46,14 @@ struct globalsmuggle Return:- BlockItReturn_t enum, see its definition for more information. --------------------------------------------------*/ +static struct eggboxSearch_s +{ + fixed_t distancetocheck; + fixed_t eggboxx, eggboxy; + UINT8 randomitems; + UINT8 eggboxes; +} g_eggboxSearch; + static BlockItReturn_t K_FindEggboxes(mobj_t *thing) { fixed_t dist; @@ -77,20 +68,20 @@ static BlockItReturn_t K_FindEggboxes(mobj_t *thing) return BMIT_CONTINUE; } - dist = P_AproxDistance(thing->x - globalsmuggle.eggboxx, thing->y - globalsmuggle.eggboxy); + dist = P_AproxDistance(thing->x - g_eggboxSearch.eggboxx, thing->y - g_eggboxSearch.eggboxy); - if (dist > globalsmuggle.distancetocheck) + if (dist > g_eggboxSearch.distancetocheck) { return BMIT_CONTINUE; } if (thing->type == MT_RANDOMITEM) { - globalsmuggle.randomitems++; + g_eggboxSearch.randomitems++; } else { - globalsmuggle.eggboxes++; + g_eggboxSearch.eggboxes++; } return BMIT_CONTINUE; @@ -103,18 +94,20 @@ static BlockItReturn_t K_FindEggboxes(mobj_t *thing) --------------------------------------------------*/ UINT8 K_EggboxStealth(fixed_t x, fixed_t y) { + ZoneScoped; + INT32 xl, xh, yl, yh, bx, by; - globalsmuggle.eggboxx = x; - globalsmuggle.eggboxy = y; - globalsmuggle.distancetocheck = (mapobjectscale * 256); - globalsmuggle.randomitems = 0; - globalsmuggle.eggboxes = 0; + g_eggboxSearch.eggboxx = x; + g_eggboxSearch.eggboxy = y; + g_eggboxSearch.distancetocheck = (mapobjectscale * 256); + g_eggboxSearch.randomitems = 0; + g_eggboxSearch.eggboxes = 0; - xl = (unsigned)(globalsmuggle.eggboxx - globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(globalsmuggle.eggboxx + globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(globalsmuggle.eggboxy - globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(globalsmuggle.eggboxy + globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(g_eggboxSearch.eggboxx - g_eggboxSearch.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(g_eggboxSearch.eggboxx + g_eggboxSearch.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(g_eggboxSearch.eggboxy - g_eggboxSearch.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(g_eggboxSearch.eggboxy + g_eggboxSearch.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -126,11 +119,11 @@ UINT8 K_EggboxStealth(fixed_t x, fixed_t y) } } - return (globalsmuggle.randomitems * (globalsmuggle.eggboxes + 1)); + return (g_eggboxSearch.randomitems * (g_eggboxSearch.eggboxes + 1)); } /*-------------------------------------------------- - static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec) + static boolean K_BotHatesThisSectorsSpecial(const player_t *player, sector_t *sec) Tells us if a bot will play more careful around this sector's special type. @@ -175,7 +168,7 @@ static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec, con } /*-------------------------------------------------- - boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) + boolean K_BotHatesThisSector(const player_t *player, sector_t *sec, fixed_t x, fixed_t y) See header file for description. --------------------------------------------------*/ @@ -269,6 +262,19 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t Return:- None --------------------------------------------------*/ +static struct nudgeSearch_s +{ + mobj_t *botmo; + angle_t angle; + fixed_t distancetocheck; + + INT64 gotoAvgX[2], gotoAvgY[2]; + UINT32 gotoObjs[2]; + + INT64 avoidAvgX[2], avoidAvgY[2]; + UINT32 avoidObjs[2]; +} g_nudgeSearch; + static void K_AddAttackObject(mobj_t *thing, UINT8 side, UINT8 weight) { fixed_t x, y; @@ -284,7 +290,7 @@ static void K_AddAttackObject(mobj_t *thing, UINT8 side, UINT8 weight) x = thing->x; y = thing->y; - a = R_PointToAngle2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, x, y); + a = R_PointToAngle2(g_nudgeSearch.botmo->x, g_nudgeSearch.botmo->y, x, y); dir = a + (side ? -ANGLE_90 : ANGLE_90); x += FixedMul(thing->radius, FINECOSINE(dir >> ANGLETOFINESHIFT)); @@ -295,9 +301,9 @@ static void K_AddAttackObject(mobj_t *thing, UINT8 side, UINT8 weight) for (i = 0; i < weight; i++) { - globalsmuggle.gotoAvgX[side] += x; - globalsmuggle.gotoAvgY[side] += y; - globalsmuggle.gotoObjs[side]++; + g_nudgeSearch.gotoAvgX[side] += x; + g_nudgeSearch.gotoAvgY[side] += y; + g_nudgeSearch.gotoObjs[side]++; } } @@ -329,7 +335,7 @@ static void K_AddDodgeObject(mobj_t *thing, UINT8 side, UINT8 weight) x = thing->x; y = thing->y; - a = R_PointToAngle2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, x, y); + a = R_PointToAngle2(g_nudgeSearch.botmo->x, g_nudgeSearch.botmo->y, x, y); dir = a + (side ? -ANGLE_90 : ANGLE_90); x += FixedMul(thing->radius, FINECOSINE(dir >> ANGLETOFINESHIFT)); @@ -340,9 +346,9 @@ static void K_AddDodgeObject(mobj_t *thing, UINT8 side, UINT8 weight) for (i = 0; i < weight; i++) { - globalsmuggle.avoidAvgX[side] += x; - globalsmuggle.avoidAvgY[side] += y; - globalsmuggle.avoidObjs[side]++; + g_nudgeSearch.avoidAvgX[side] += x; + g_nudgeSearch.avoidAvgY[side] += y; + g_nudgeSearch.avoidObjs[side]++; } } @@ -392,12 +398,13 @@ static boolean K_PlayerAttackSteer(mobj_t *thing, UINT8 side, UINT8 weight, bool --------------------------------------------------*/ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) { + ZoneScoped; + INT16 angledelta, anglediff; - fixed_t fulldist; - angle_t destangle, angle, predictangle; + angle_t destangle, angle; UINT8 side = 0; - if (!globalsmuggle.botmo || P_MobjWasRemoved(globalsmuggle.botmo) || !globalsmuggle.botmo->player) + if (!g_nudgeSearch.botmo || P_MobjWasRemoved(g_nudgeSearch.botmo) || !g_nudgeSearch.botmo->player) { return BMIT_ABORT; } @@ -407,32 +414,36 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) return BMIT_CONTINUE; } - if (globalsmuggle.botmo == thing) + if (g_nudgeSearch.botmo == thing) { return BMIT_CONTINUE; } - fulldist = R_PointToDist2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, thing->x, thing->y) - thing->radius; + const fixed_t xDelta = abs(g_nudgeSearch.botmo->x - thing->x); + const fixed_t yDelta = abs(g_nudgeSearch.botmo->y - thing->y); + const fixed_t fullDist = (FixedMul(xDelta, xDelta) + FixedMul(yDelta, yDelta)) - FixedMul(thing->radius, thing->radius); - if (fulldist > globalsmuggle.distancetocheck) + if (fullDist > g_nudgeSearch.distancetocheck) { return BMIT_CONTINUE; } - if (P_CheckSight(globalsmuggle.botmo, thing) == false) +#if 0 + // this is very expensive to do, and probably not worth it. + if (P_CheckSight(g_nudgeSearch.botmo, thing) == false) { return BMIT_CONTINUE; } +#endif - predictangle = R_PointToAngle2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, globalsmuggle.predict->x, globalsmuggle.predict->y); - destangle = R_PointToAngle2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, thing->x, thing->y); - angle = (predictangle - destangle); + destangle = R_PointToAngle2(g_nudgeSearch.botmo->x, g_nudgeSearch.botmo->y, thing->x, thing->y); + angle = (g_nudgeSearch.angle - destangle); if (angle < ANGLE_180) { angledelta = AngleFixed(angle)>>FRACBITS; } - else + else { angledelta = 360-(AngleFixed(angle)>>FRACBITS); side = 1; @@ -448,7 +459,6 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) case MT_ORBINAUT: case MT_ORBINAUT_SHIELD: case MT_JAWZ: - case MT_JAWZ_DUD: case MT_JAWZ_SHIELD: case MT_SSMINE: case MT_SSMINE_SHIELD: @@ -466,9 +476,9 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) break; } - if (P_CanPickupItem(globalsmuggle.botmo->player, 1)) + if (P_CanPickupItem(g_nudgeSearch.botmo->player, 1)) { - K_AddAttackObject(thing, side, 10); + K_AddAttackObject(thing, side, 20); } break; case MT_EGGMANITEM: @@ -477,18 +487,18 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) break; } - if (P_CanPickupItem(globalsmuggle.botmo->player, 1)) // Can pick up an actual item + if (P_CanPickupItem(g_nudgeSearch.botmo->player, 1)) // Can pick up an actual item { const UINT8 stealth = K_EggboxStealth(thing->x, thing->y); - const UINT8 requiredstealth = (globalsmuggle.botmo->player->botvars.difficulty * globalsmuggle.botmo->player->botvars.difficulty); + const UINT8 requiredstealth = (g_nudgeSearch.botmo->player->botvars.difficulty * g_nudgeSearch.botmo->player->botvars.difficulty); if (stealth >= requiredstealth) { - K_AddAttackObject(thing, side, 10); + K_AddAttackObject(thing, side, 20); } else { - K_AddDodgeObject(thing, side, 10); + K_AddDodgeObject(thing, side, 20); } } break; @@ -498,7 +508,7 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) break; } - if (P_CanPickupItem(globalsmuggle.botmo->player, 3)) + if (P_CanPickupItem(g_nudgeSearch.botmo->player, 3)) { K_AddAttackObject(thing, side, 20); } @@ -510,40 +520,39 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) break; } - if ((RINGTOTAL(globalsmuggle.botmo->player) < 20 && !(globalsmuggle.botmo->player->pflags & PF_RINGLOCK) - && P_CanPickupItem(globalsmuggle.botmo->player, 0)) + if ((RINGTOTAL(g_nudgeSearch.botmo->player) < 20 && !(g_nudgeSearch.botmo->player->pflags & PF_RINGLOCK) + && P_CanPickupItem(g_nudgeSearch.botmo->player, 0)) && !thing->extravalue1 - && (globalsmuggle.botmo->player->itemtype != KITEM_THUNDERSHIELD)) + && (g_nudgeSearch.botmo->player->itemtype != KITEM_THUNDERSHIELD)) { - K_AddAttackObject(thing, side, (RINGTOTAL(globalsmuggle.botmo->player) < 3) ? 5 : 1); + K_AddAttackObject(thing, side, (RINGTOTAL(g_nudgeSearch.botmo->player) < 3) ? 5 : 1); } break; case MT_PLAYER: if (thing->player && !thing->player->spectator && !thing->player->hyudorotimer - && !globalsmuggle.botmo->player->hyudorotimer) + && !g_nudgeSearch.botmo->player->hyudorotimer) { // There REALLY ought to be a better way to handle this logic, right?! // Squishing if (K_PlayerAttackSteer(thing, side, 20, - globalsmuggle.botmo->scale > thing->scale + (mapobjectscale/8), - thing->scale > globalsmuggle.botmo->scale + (mapobjectscale/8) - )) + g_nudgeSearch.botmo->scale > thing->scale, + thing->scale > g_nudgeSearch.botmo->scale)) { break; } // Invincibility else if (K_PlayerAttackSteer(thing, side, 20, - globalsmuggle.botmo->player->invincibilitytimer, + g_nudgeSearch.botmo->player->invincibilitytimer, thing->player->invincibilitytimer )) { break; } - // thunder Shield + // Thunder Shield else if (K_PlayerAttackSteer(thing, side, 20, - globalsmuggle.botmo->player->itemtype == KITEM_THUNDERSHIELD, + g_nudgeSearch.botmo->player->itemtype == KITEM_THUNDERSHIELD, thing->player->itemtype == KITEM_THUNDERSHIELD )) { @@ -551,7 +560,7 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) } // Bubble Shield else if (K_PlayerAttackSteer(thing, side, 20, - globalsmuggle.botmo->player->itemtype == KITEM_BUBBLESHIELD, + g_nudgeSearch.botmo->player->itemtype == KITEM_BUBBLESHIELD, thing->player->itemtype == KITEM_BUBBLESHIELD )) { @@ -559,7 +568,7 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) } // Flame Shield else if (K_PlayerAttackSteer(thing, side, 20, - globalsmuggle.botmo->player->itemtype == KITEM_FLAMESHIELD, + g_nudgeSearch.botmo->player->itemtype == KITEM_FLAMESHIELD, thing->player->itemtype == KITEM_FLAMESHIELD )) { @@ -568,24 +577,24 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) // Has held item shield else if (K_PlayerAttackSteer(thing, side, 20, (thing->player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT)), - (globalsmuggle.botmo->player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT)) + (g_nudgeSearch.botmo->player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT)) )) { break; } // Ring Sting - /*else if (K_PlayerAttackSteer(thing, side, 20, + else if (K_PlayerAttackSteer(thing, side, 20, thing->player->rings <= 0, - globalsmuggle.botmo->player->rings <= 0 + g_nudgeSearch.botmo->player->rings <= 0 )) { break; - }*/ + } else { // After ALL of that, we can do standard bumping - fixed_t ourweight = K_GetMobjWeight(globalsmuggle.botmo, thing); - fixed_t theirweight = K_GetMobjWeight(thing, globalsmuggle.botmo); + fixed_t ourweight = K_GetMobjWeight(g_nudgeSearch.botmo, thing); + fixed_t theirweight = K_GetMobjWeight(thing, g_nudgeSearch.botmo); fixed_t weightdiff = 0; if (anglediff >= 90) @@ -644,17 +653,20 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) } /*-------------------------------------------------- - void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) + void K_NudgePredictionTowardsObjects(botprediction_t *predict, const player_t *player) See header file for description. --------------------------------------------------*/ -void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) +void K_NudgePredictionTowardsObjects(botprediction_t *predict, const player_t *player) { + ZoneScoped; + const precise_t time = I_GetPreciseTime(); INT32 xl, xh, yl, yh, bx, by; fixed_t distToPredict = 0; + fixed_t radToPredict = 0; angle_t angleToPredict = 0; fixed_t avgX = 0, avgY = 0; @@ -677,31 +689,32 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); angleToPredict = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); - globalsmuggle.distancetocheck = distToPredict >> 1; + radToPredict = distToPredict >> 1; + g_nudgeSearch.distancetocheck = FixedMul(radToPredict, radToPredict); - baseNudge = predict->radius * 2; - maxNudge = distToPredict; + baseNudge = predict->baseRadius >> 3; + maxNudge = predict->baseRadius - baseNudge; - globalsmuggle.botmo = player->mo; - globalsmuggle.predict = predict; + g_nudgeSearch.botmo = player->mo; + g_nudgeSearch.angle = angleToPredict; // silly variable reuse - avgX = globalsmuggle.botmo->x + FixedMul(globalsmuggle.distancetocheck, FINECOSINE(angleToPredict >> ANGLETOFINESHIFT)); - avgY = globalsmuggle.botmo->y + FixedMul(globalsmuggle.distancetocheck, FINESINE(angleToPredict >> ANGLETOFINESHIFT)); + avgX = g_nudgeSearch.botmo->x + FixedMul(radToPredict, FINECOSINE(angleToPredict >> ANGLETOFINESHIFT)); + avgY = g_nudgeSearch.botmo->y + FixedMul(radToPredict, FINESINE(angleToPredict >> ANGLETOFINESHIFT)); for (i = 0; i < 2; i++) { - globalsmuggle.gotoAvgX[i] = globalsmuggle.gotoAvgY[i] = 0; - globalsmuggle.gotoObjs[i] = 0; + g_nudgeSearch.gotoAvgX[i] = g_nudgeSearch.gotoAvgY[i] = 0; + g_nudgeSearch.gotoObjs[i] = 0; - globalsmuggle.avoidAvgX[i] = globalsmuggle.avoidAvgY[i] = 0; - globalsmuggle.avoidObjs[i] = 0; + g_nudgeSearch.avoidAvgX[i] = g_nudgeSearch.avoidAvgY[i] = 0; + g_nudgeSearch.avoidObjs[i] = 0; } - xl = (unsigned)(avgX - (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(avgX + (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(avgY - (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(avgY + (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(avgX - (radToPredict + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(avgX + (radToPredict + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(avgY - (radToPredict + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(avgY + (radToPredict + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -714,9 +727,9 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) } // Handle dodge characters - if (globalsmuggle.avoidObjs[1] > 0 || globalsmuggle.avoidObjs[0] > 0) + if (g_nudgeSearch.avoidObjs[1] > 0 || g_nudgeSearch.avoidObjs[0] > 0) { - if (globalsmuggle.avoidObjs[1] > globalsmuggle.avoidObjs[0]) + if (g_nudgeSearch.avoidObjs[1] > g_nudgeSearch.avoidObjs[0]) { gotoSide = 1; } @@ -725,8 +738,8 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) gotoSide = 0; } - avgX = (globalsmuggle.avoidAvgX[gotoSide] / globalsmuggle.avoidObjs[gotoSide]) * mapobjectscale; - avgY = (globalsmuggle.avoidAvgY[gotoSide] / globalsmuggle.avoidObjs[gotoSide]) * mapobjectscale; + avgX = (g_nudgeSearch.avoidAvgX[gotoSide] / g_nudgeSearch.avoidObjs[gotoSide]) * mapobjectscale; + avgY = (g_nudgeSearch.avoidAvgY[gotoSide] / g_nudgeSearch.avoidObjs[gotoSide]) * mapobjectscale; avgDist = R_PointToDist2( avgX, avgY, @@ -734,9 +747,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) ); // High handling characters dodge better - nudgeDist = ((9 - globalsmuggle.botmo->player->kartweight) + 1) * baseNudge; - - maxNudge = max(distToPredict - predict->radius, predict->radius); + nudgeDist = ((9 - g_nudgeSearch.botmo->player->kartweight) + 1) * baseNudge; if (nudgeDist > maxNudge) { nudgeDist = maxNudge; @@ -750,6 +761,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) predict->x += FixedMul(nudgeDist, FINECOSINE(nudgeDir >> ANGLETOFINESHIFT)); predict->y += FixedMul(nudgeDist, FINESINE(nudgeDir >> ANGLETOFINESHIFT)); + predict->radius = std::max(predict->radius - nudgeDist, baseNudge); distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); @@ -770,7 +782,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) // We don't want to pick contradictory sides, so keep the old side otherwise, // even if there's more to grab on the other side. - if (globalsmuggle.gotoObjs[1] > globalsmuggle.gotoObjs[0]) + if (g_nudgeSearch.gotoObjs[1] > g_nudgeSearch.gotoObjs[0]) { gotoSide = 1; } @@ -781,7 +793,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) } // Check if our side is invalid, if so, don't do the code below. - if (gotoSide != -1 && globalsmuggle.gotoObjs[gotoSide] == 0) + if (gotoSide != -1 && g_nudgeSearch.gotoObjs[gotoSide] == 0) { // Do not use a side gotoSide = -1; @@ -789,8 +801,8 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) if (gotoSide != -1) { - avgX = (globalsmuggle.gotoAvgX[gotoSide] / globalsmuggle.gotoObjs[gotoSide]) * mapobjectscale; - avgY = (globalsmuggle.gotoAvgY[gotoSide] / globalsmuggle.gotoObjs[gotoSide]) * mapobjectscale; + avgX = (g_nudgeSearch.gotoAvgX[gotoSide] / g_nudgeSearch.gotoObjs[gotoSide]) * mapobjectscale; + avgY = (g_nudgeSearch.gotoAvgY[gotoSide] / g_nudgeSearch.gotoObjs[gotoSide]) * mapobjectscale; avgDist = R_PointToDist2( predict->x, predict->y, @@ -798,9 +810,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) ); // Acceleration characters are more aggressive - nudgeDist = ((9 - globalsmuggle.botmo->player->kartspeed) + 1) * baseNudge; - - maxNudge = max(distToPredict - predict->radius, predict->radius); + nudgeDist = ((9 - g_nudgeSearch.botmo->player->kartspeed) + 1) * baseNudge; if (nudgeDist > maxNudge) { nudgeDist = maxNudge; @@ -810,6 +820,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) { predict->x = avgX; predict->y = avgY; + predict->radius = baseNudge; } else { @@ -821,6 +832,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) predict->x += FixedMul(nudgeDist, FINECOSINE(nudgeDir >> ANGLETOFINESHIFT)); predict->y += FixedMul(nudgeDist, FINESINE(nudgeDir >> ANGLETOFINESHIFT)); + predict->radius = std::max(predict->radius - nudgeDist, baseNudge); //distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); } @@ -841,6 +853,15 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) Return:- BlockItReturn_t enum, see its definition for more information. --------------------------------------------------*/ +static struct bullySearch_s +{ + mobj_t *botmo; + fixed_t distancetocheck; + + fixed_t annoyscore; + mobj_t *annoymo; +} g_bullySearch; + static BlockItReturn_t K_FindPlayersToBully(mobj_t *thing) { INT16 anglediff; @@ -848,7 +869,7 @@ static BlockItReturn_t K_FindPlayersToBully(mobj_t *thing) fixed_t ourweight, theirweight, weightdiff; angle_t ourangle, destangle, angle; - if (!globalsmuggle.botmo || P_MobjWasRemoved(globalsmuggle.botmo) || !globalsmuggle.botmo->player) + if (!g_bullySearch.botmo || P_MobjWasRemoved(g_bullySearch.botmo) || !g_bullySearch.botmo->player) { return BMIT_ABORT; } @@ -863,40 +884,40 @@ static BlockItReturn_t K_FindPlayersToBully(mobj_t *thing) return BMIT_CONTINUE; } - if (globalsmuggle.botmo == thing) + if (g_bullySearch.botmo == thing) { return BMIT_CONTINUE; } - fulldist = R_PointToDist2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, thing->x, thing->y) - thing->radius; + fulldist = R_PointToDist2(g_bullySearch.botmo->x, g_bullySearch.botmo->y, thing->x, thing->y) - thing->radius; - if (fulldist > globalsmuggle.distancetocheck) + if (fulldist > g_bullySearch.distancetocheck) { return BMIT_CONTINUE; } - if (P_CheckSight(globalsmuggle.botmo, thing) == false) + if (P_CheckSight(g_bullySearch.botmo, thing) == false) { return BMIT_CONTINUE; } - ourangle = globalsmuggle.botmo->angle; - destangle = R_PointToAngle2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, thing->x, thing->y); + ourangle = g_bullySearch.botmo->angle; + destangle = R_PointToAngle2(g_bullySearch.botmo->x, g_bullySearch.botmo->y, thing->x, thing->y); angle = (ourangle - destangle); if (angle < ANGLE_180) { anglediff = AngleFixed(angle)>>FRACBITS; } - else + else { anglediff = 360-(AngleFixed(angle)>>FRACBITS); } anglediff = abs(anglediff); - ourweight = K_GetMobjWeight(globalsmuggle.botmo, thing); - theirweight = K_GetMobjWeight(thing, globalsmuggle.botmo); + ourweight = K_GetMobjWeight(g_bullySearch.botmo, thing); + theirweight = K_GetMobjWeight(thing, g_bullySearch.botmo); weightdiff = 0; if (anglediff >= 90) @@ -908,37 +929,39 @@ static BlockItReturn_t K_FindPlayersToBully(mobj_t *thing) weightdiff = ourweight - theirweight; } - if (weightdiff > mapobjectscale && weightdiff > globalsmuggle.annoyscore) + if (weightdiff > mapobjectscale && weightdiff > g_bullySearch.annoyscore) { - globalsmuggle.annoyscore = weightdiff; - globalsmuggle.annoymo = thing; + g_bullySearch.annoyscore = weightdiff; + g_bullySearch.annoymo = thing; } return BMIT_CONTINUE; } /*-------------------------------------------------- - INT32 K_PositionBully(player_t *player) + INT32 K_PositionBully(const player_t *player) See header file for description. --------------------------------------------------*/ -INT32 K_PositionBully(player_t *player) +INT32 K_PositionBully(const player_t *player) { + ZoneScoped; + INT32 xl, xh, yl, yh, bx, by; angle_t ourangle, destangle, angle; INT16 anglediff; - globalsmuggle.botmo = player->mo; - globalsmuggle.distancetocheck = 1024*player->mo->scale; + g_bullySearch.botmo = player->mo; + g_bullySearch.distancetocheck = 1024*player->mo->scale; - globalsmuggle.annoymo = NULL; - globalsmuggle.annoyscore = 0; + g_bullySearch.annoymo = NULL; + g_bullySearch.annoyscore = 0; - xl = (unsigned)(globalsmuggle.botmo->x - globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(globalsmuggle.botmo->x + globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(globalsmuggle.botmo->y - globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(globalsmuggle.botmo->y + globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(g_bullySearch.botmo->x - g_bullySearch.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(g_bullySearch.botmo->x + g_bullySearch.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(g_bullySearch.botmo->y - g_bullySearch.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(g_bullySearch.botmo->y + g_bullySearch.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -950,25 +973,25 @@ INT32 K_PositionBully(player_t *player) } } - if (globalsmuggle.annoymo == NULL) + if (g_bullySearch.annoymo == NULL) { return INT32_MAX; } - ourangle = globalsmuggle.botmo->angle; - destangle = R_PointToAngle2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, globalsmuggle.annoymo->x, globalsmuggle.annoymo->y); + ourangle = g_bullySearch.botmo->angle; + destangle = R_PointToAngle2(g_bullySearch.botmo->x, g_bullySearch.botmo->y, g_bullySearch.annoymo->x, g_bullySearch.annoymo->y); angle = (ourangle - destangle); if (angle < ANGLE_180) { anglediff = AngleFixed(angle)>>FRACBITS; } - else + else { anglediff = 360-(AngleFixed(angle)>>FRACBITS); } - if (anglediff < 30) + if (abs(anglediff) < 30) return 0; if (anglediff < 0) diff --git a/src/k_collide.c b/src/k_collide.c index dff678846..33a591e02 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -721,12 +721,12 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) { // Counter desyncs /*mobj_t *oldthing = thing; - mobj_t *oldtm.thing = tm.thing; + mobj_t *oldg_tm.thing = g_tm.thing; - P_Thrust(tm.thing, R_PointToAngle2(thing->x, thing->y, tm.thing->x, tm.thing->y), 4*thing->scale); + P_Thrust(g_tm.thing, R_PointToAngle2(thing->x, thing->y, g_tm.thing->x, g_tm.thing->y), 4*thing->scale); thing = oldthing; - P_SetTarget(&tm.thing, oldtm.thing);*/ + P_SetTarget(&g_tm.thing, oldg_tm.thing);*/ if (P_PlayerInPain(t2->player) || t2->player->flashing || t2->player->hyudorotimer diff --git a/src/k_grandprix.c b/src/k_grandprix.c index d5c70a72d..361778e62 100644 --- a/src/k_grandprix.c +++ b/src/k_grandprix.c @@ -102,7 +102,7 @@ INT16 K_CalculateGPRankPoints(UINT8 position, UINT8 numplayers) --------------------------------------------------*/ UINT8 K_BotDefaultSkin(void) { - const char *defaultbotskinname = "eggrobo"; + const char *defaultbotskinname = "eggman"; INT32 defaultbotskin = R_SkinAvailable(defaultbotskinname); if (defaultbotskin == -1) @@ -114,6 +114,21 @@ UINT8 K_BotDefaultSkin(void) return (UINT8)defaultbotskin; } +/*-------------------------------------------------- + UINT8 K_GetGPPlayerCount(UINT8 humans) + + See header file for description. +--------------------------------------------------*/ +UINT8 K_GetGPPlayerCount(UINT8 humans) +{ + // 1P -> 8 total + // 2P -> 8 total + // 3P -> 12 total + // 4P -> 16 total + + return max(min(humans * 4, MAXPLAYERS), 8); +} + /*-------------------------------------------------- void K_InitGrandPrixBots(void) @@ -132,7 +147,7 @@ void K_InitGrandPrixBots(void) UINT8 numplayers = 0; UINT8 competitors[MAXSPLITSCREENPLAYERS]; - UINT8 usableskins; + UINT8 usableskins, skincount = numskins; UINT8 grabskins[MAXSKINS+1]; UINT8 botskinlist[MAXPLAYERS]; @@ -145,7 +160,7 @@ void K_InitGrandPrixBots(void) memset(botskinlist, defaultbotskin, sizeof (botskinlist)); // Init usable bot skins list - for (usableskins = 0; usableskins < numskins; usableskins++) + for (usableskins = 0; usableskins < skincount; usableskins++) { grabskins[usableskins] = usableskins; } @@ -185,6 +200,13 @@ void K_InitGrandPrixBots(void) { if (playeringame[i]) { + if (players[i].bot == true) + { + // Remove existing bots. + CL_RemovePlayer(i, KR_LEAVE); + continue; + } + if (numplayers < MAXSPLITSCREENPLAYERS && !players[i].spectator) { competitors[numplayers] = i; @@ -193,27 +215,13 @@ void K_InitGrandPrixBots(void) } else { - players[i].spectator = true; // force spectate for all other players, if they happen to exist? + P_SetPlayerSpectator(i); // force spectate for all other players, if they happen to exist? } } } - if (numplayers > 2) - { - // Add 3 bots per player beyond 2P - playercount += (numplayers-2) * 3; - } - - if (numbosswaypoints > 0 && !waypointcap) - { - CONS_Alert(CONS_ERROR, "Bots do not work on maps using the legacy checkpoint system.\nPlease consider using waypoints instead if bot support is desired!\n"); - wantedbots = 0; - } - else - { - - wantedbots = playercount - numplayers; - } + playercount = K_GetGPPlayerCount(numplayers); + wantedbots = playercount - numplayers; // Create rival list if (numplayers > 0) @@ -223,8 +231,10 @@ void K_InitGrandPrixBots(void) for (j = 0; j < numplayers; j++) { player_t *p = &players[competitors[j]]; - char *rivalname = skins[p->skin].rivals[i]; - INT32 rivalnum = R_SkinAvailable(rivalname); + + INT32 rivalnum; + const char *rivalname = skins[p->skin].rivals[i]; + rivalnum = R_SkinAvailable(rivalname); // Intentionally referenced before (currently dummied out) unlock check. Such a tease! if (rivalnum != -1 && grabskins[(UINT8)rivalnum] != MAXSKINS) @@ -239,12 +249,16 @@ void K_InitGrandPrixBots(void) // Rearrange usable bot skins list to prevent gaps for randomised selection for (i = 0; i < usableskins; i++) { - if (!(grabskins[i] == MAXSKINS /*|| K_SkinLocked(grabskins[i])*/)) + if (!(grabskins[i] == MAXSKINS || !R_SkinUsable(-1, grabskins[i]))) + { continue; - while (usableskins > i && (grabskins[usableskins] == MAXSKINS /*|| K_SkinLocked(grabskins[i])*/)) + } + + while (usableskins > i && (grabskins[usableskins] == MAXSKINS || !R_SkinUsable(-1, grabskins[usableskins]))) { usableskins--; } + grabskins[i] = grabskins[usableskins]; grabskins[usableskins] = MAXSKINS; } @@ -258,7 +272,7 @@ void K_InitGrandPrixBots(void) if (usableskins > 0) { - UINT8 index = M_RandomKey(usableskins); + UINT8 index = P_RandomKey(usableskins); skinnum = grabskins[index]; grabskins[index] = grabskins[--usableskins]; } diff --git a/src/k_grandprix.h b/src/k_grandprix.h index 60fbf4604..59481d3d0 100644 --- a/src/k_grandprix.h +++ b/src/k_grandprix.h @@ -80,6 +80,21 @@ INT16 K_CalculateGPRankPoints(UINT8 position, UINT8 numplayers); UINT8 K_BotDefaultSkin(void); +/*-------------------------------------------------- + UINT8 K_GetGPPlayerCount(UINT8 humans) + + Counts the number of total players, + including humans and bots, to put into + a GP session. + + Input Arguments:- + humans - Number of human players. + + Return:- + Number of both human players and CPU. +--------------------------------------------------*/ + +UINT8 K_GetGPPlayerCount(UINT8 humans); /*-------------------------------------------------- void K_InitGrandPrixBots(void); diff --git a/src/k_kart.c b/src/k_kart.c index ce13b1154..fab6b394d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3235,6 +3235,12 @@ static void K_GetKartBoostPower(player_t *player) ADDBOOST(FRACUNIT/5, 4*FRACUNIT); // + 20% top speed, + 400% acceleration } + // This should always remain the last boost stack before tethering + if (player->botvars.rubberband > FRACUNIT && K_PlayerUsesBotMovement(player) == true) + { + ADDBOOST(player->botvars.rubberband - FRACUNIT, 0); + } + player->boostpower = boostpower; // value smoothing @@ -3327,7 +3333,8 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower, boolean dorubberb if (K_PlayerUsesBotMovement(player)) { // Increase bot speed by 1-10% depending on difficulty - fixed_t add = (player->botvars.difficulty * (FRACUNIT/10)) / DIFFICULTBOT; + const fixed_t modifier = K_BotMapModifier(); + fixed_t add = ((player->botvars.difficulty-1) * FixedMul(FRACUNIT / 10, modifier)) / (DIFFICULTBOT-1); finalspeed = FixedMul(finalspeed, FRACUNIT + add); if (player->bot && player->botvars.rival) @@ -7475,7 +7482,7 @@ boolean K_SafeRespawnPosition(mobj_t * mo) po->validcount = validcount; - if (!P_BBoxInsidePolyobj(po, tm.bbox) + if (!P_BBoxInsidePolyobj(po, g_tm.bbox) || !(po->flags & POF_SOLID)) { plink = (polymaplink_t *)(plink->link.next); @@ -8904,7 +8911,7 @@ static void K_AdjustPlayerFriction(player_t *player) // Reduce friction after hitting a spring if (player->tiregrease) { - player->mo->friction += ((FRACUNIT - prevfriction) / greasetics) * player->tiregrease; + player->mo->friction += ((FRACUNIT - FRACUNIT) / greasetics) * player->tiregrease; } // Karma ice physics @@ -8942,6 +8949,14 @@ static void K_AdjustPlayerFriction(player_t *player) // Remove this line once they can drift. player->mo->friction -= extraFriction; + // Bots gain more traction as they rubberband. + const fixed_t traction_value = FixedMul(player->botvars.rubberband, max(FRACUNIT, K_BotMapModifier())); + if (traction_value > FRACUNIT) + { + const fixed_t traction_mul = traction_value - FRACUNIT; + player->mo->friction -= FixedMul(extraFriction, traction_mul); + } + if (player->mo->friction > FRACUNIT) player->mo->friction = FRACUNIT; if (player->mo->friction < 0) @@ -8949,7 +8964,6 @@ static void K_AdjustPlayerFriction(player_t *player) player->mo->movefactor = FixedDiv(ORIG_FRICTION, player->mo->friction); - if (player->mo->movefactor < FRACUNIT) player->mo->movefactor = 19*player->mo->movefactor - 18*FRACUNIT; else diff --git a/src/k_waypoint.c b/src/k_waypoint.cpp similarity index 84% rename from src/k_waypoint.c rename to src/k_waypoint.cpp index f2f18a627..ab110798f 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.cpp @@ -1,13 +1,13 @@ -// SONIC ROBO BLAST 2 KART +// DR. ROBOTNIK'S RING RACERS //----------------------------------------------------------------------------- -// Copyright (C) 2018-2020 by Sean "Sryder" Ryder -// Copyright (C) 2018-2020 by Kart Krew +// Copyright (C) 2024 by Sean "Sryder" Ryder +// Copyright (C) 2024 by Kart Krew // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file k_waypoint.c +/// \file k_waypoint.cpp /// \brief Waypoint handling from the relevant mobjs /// Setup and interfacing with waypoints for the main game @@ -21,6 +21,13 @@ #include "g_game.h" #include "p_slopes.h" +#include "cxxutil.hpp" + +#include +#include + +#include + // The number of sparkles per waypoint connection in the waypoint visualisation static const UINT32 SPARKLES_PER_CONNECTION = 16U; @@ -350,7 +357,6 @@ static void K_CompareOverlappingWaypoint const boolean huntbackwards = false; boolean pathfindsuccess = false; path_t pathtofinish = {0}; - Z_Free(pathtofinish.array); if (K_GetWaypointIsShortcut(*bestwaypoint) == false && K_GetWaypointIsShortcut(checkwaypoint) == true) @@ -369,6 +375,8 @@ static void K_CompareOverlappingWaypoint *bestwaypoint = checkwaypoint; *bestfindist = pathtofinish.totaldist; } + + Z_Free(pathtofinish.array); } } @@ -391,7 +399,7 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj, waypoint_t *const hint) fixed_t checkdist = INT32_MAX; fixed_t bestfindist = INT32_MAX; - void sort_waypoint (waypoint_t *const checkwaypoint) + auto sort_waypoint = [&](waypoint_t *const checkwaypoint) { if (!K_GetWaypointIsEnabled(checkwaypoint)) { @@ -1853,7 +1861,7 @@ static waypoint_t *K_SearchWaypointGraph( I_Assert(conditionalfunc != NULL); I_Assert(firstwaypoint != NULL); - visitedarray = Z_Calloc(numwaypoints * sizeof(boolean), PU_STATIC, NULL); + visitedarray = static_cast(Z_Calloc(numwaypoints * sizeof(boolean), PU_STATIC, NULL)); foundwaypoint = K_TraverseWaypoints(firstwaypoint, conditionalfunc, condition, visitedarray); Z_Free(visitedarray); @@ -1975,6 +1983,8 @@ static UINT32 K_SetupCircuitLength(void) if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) == LF_SECTIONRACE) { path_t bestsprintpath = {0}; + auto sprint_finally = srb2::finally([&bestsprintpath]() { Z_Free(bestsprintpath.array); }); + const boolean useshortcuts = false; const boolean huntbackwards = true; const UINT32 traveldist = UINT32_MAX - UINT16_MAX; // Go as far back as possible. Not exactly UINT32_MAX to avoid possible overflow. @@ -1991,8 +2001,6 @@ static UINT32 K_SetupCircuitLength(void) { startingwaypoint = (waypoint_t *)bestsprintpath.array[ bestsprintpath.numnodes - 1 ].nodedata; } - Z_Free(bestsprintpath.array); - } else { @@ -2000,6 +2008,8 @@ static UINT32 K_SetupCircuitLength(void) waypoint_t fakefinishline = *finishline; path_t bestcircuitpath = {0}; + auto circuit_finally = srb2::finally([&bestcircuitpath]() { Z_Free(bestcircuitpath.array); }); + const boolean useshortcuts = false; const boolean huntbackwards = false; @@ -2013,7 +2023,6 @@ static UINT32 K_SetupCircuitLength(void) // this instead would be the most ideal startingwaypoint = finishline->nextwaypoints[0]; } - Z_Free(bestcircuitpath.array); } return circuitlength; @@ -2039,16 +2048,18 @@ static void K_AddPrevToWaypoint(waypoint_t *const waypoint, waypoint_t *const pr I_Assert(prevwaypoint != NULL); waypoint->numprevwaypoints++; - waypoint->prevwaypoints = - Z_Realloc(waypoint->prevwaypoints, waypoint->numprevwaypoints * sizeof(waypoint_t *), PU_LEVEL, NULL); + waypoint->prevwaypoints = static_cast( + Z_Realloc(waypoint->prevwaypoints, waypoint->numprevwaypoints * sizeof(waypoint_t *), PU_LEVEL, NULL) + ); if (!waypoint->prevwaypoints) { I_Error("K_AddPrevToWaypoint: Failed to reallocate memory for previous waypoints."); } - waypoint->prevwaypointdistances = - Z_Realloc(waypoint->prevwaypointdistances, waypoint->numprevwaypoints * sizeof(fixed_t), PU_LEVEL, NULL); + waypoint->prevwaypointdistances = static_cast( + Z_Realloc(waypoint->prevwaypointdistances, waypoint->numprevwaypoints * sizeof(fixed_t), PU_LEVEL, NULL) + ); if (!waypoint->prevwaypointdistances) { @@ -2104,14 +2115,16 @@ static waypoint_t *K_MakeWaypoint(mobj_t *const mobj) if (madewaypoint->numnextwaypoints != 0) { // Allocate memory to hold enough pointers to all of the next waypoints - madewaypoint->nextwaypoints = - Z_Calloc(madewaypoint->numnextwaypoints * sizeof(waypoint_t *), PU_LEVEL, NULL); + madewaypoint->nextwaypoints = static_cast( + Z_Calloc(madewaypoint->numnextwaypoints * sizeof(waypoint_t *), PU_LEVEL, NULL) + ); if (madewaypoint->nextwaypoints == NULL) { I_Error("K_MakeWaypoint: Out of Memory allocating next waypoints."); } - madewaypoint->nextwaypointdistances = - Z_Calloc(madewaypoint->numnextwaypoints * sizeof(fixed_t), PU_LEVEL, NULL); + madewaypoint->nextwaypointdistances = static_cast( + Z_Calloc(madewaypoint->numnextwaypoints * sizeof(fixed_t), PU_LEVEL, NULL) + ); if (madewaypoint->nextwaypointdistances == NULL) { I_Error("K_MakeWaypoint: Out of Memory allocating next waypoint distances."); @@ -2262,7 +2275,7 @@ static boolean K_AllocateWaypointHeap(void) { // Allocate space in the heap for every mobj, it's possible some mobjs aren't linked up and not all of the // heap allocated will be used, but it's a fairly reasonable assumption that this isn't going to be awful - waypointheap = Z_Calloc(numwaypointmobjs * sizeof(waypoint_t), PU_LEVEL, NULL); + waypointheap = static_cast(Z_Calloc(numwaypointmobjs * sizeof(waypoint_t), PU_LEVEL, NULL)); if (waypointheap == NULL) { @@ -2299,6 +2312,460 @@ static void K_FreeWaypoints(void) K_ClearWaypoints(); } +namespace +{ + +/*-------------------------------------------------- + BlockItReturn_t K_TrackWaypointNearOffroad(line_t *line) + + Blockmap iteration function to check in an extra radius + around a waypoint to find any solid walls around it. +--------------------------------------------------*/ +static fixed_t g_track_wp_x = INT32_MAX; +static fixed_t g_track_wp_y = INT32_MAX; +static fixed_t g_track_wp_radius = INT32_MAX; + +static BlockItReturn_t K_TrackWaypointNearOffroad(line_t *line) +{ + fixed_t dist = INT32_MAX; + vertex_t v = {0}; + + P_ClosestPointOnLine( + g_track_wp_x, g_track_wp_y, + line, + &v + ); + + dist = R_PointToDist2( + g_track_wp_x, g_track_wp_y, + v.x, v.y + ); + + const fixed_t buffer = FixedMul(mobjinfo[MT_PLAYER].radius * 2, mapobjectscale) * 3; + dist -= buffer; + + if (dist <= 0) // line gets crossed + { + if (((line->flags & (ML_TWOSIDED|ML_IMPASSABLE|ML_MIDSOLID)) == ML_TWOSIDED) && !line->blockplayers) + { + // double-sided, and no blocking flags -- it's not a wall + const INT32 side = P_PointOnLineSide(g_track_wp_x, g_track_wp_y, line); + const sector_t *sec = side ? line->frontsector : line->backsector; + + if (sec != nullptr && (sec->damagetype == SD_DEATHPIT || sec->damagetype == SD_INSTAKILL)) + { + // force kill sectors to be more complex + return BMIT_STOP; + } + } + else + { + // actually is a wall + return BMIT_ABORT; + } + } + + // not crossed, or not a wall + return BMIT_CONTINUE; +} + +/*-------------------------------------------------- + boolean K_SneakerPanelOverlap(struct sneakerpanel &panelA, struct sneakerpanel &panelB) + + Returns whenever or not a sneaker panel sector / thing overlap +--------------------------------------------------*/ +struct complexity_sneaker_s +{ + fixed_t bbox[4]; + //std::vector sectors; + //std::vector things; + + complexity_sneaker_s(sector_t *sec) + { + M_ClearBox(bbox); + + for (size_t i = 0; i < sec->linecount; i++) + { + line_t *const ld = sec->lines[i]; + + M_AddToBox(bbox, ld->bbox[BOXRIGHT], ld->bbox[BOXTOP]); + M_AddToBox(bbox, ld->bbox[BOXLEFT], ld->bbox[BOXBOTTOM]); + } + } + + /*complexity_sneaker_s(mapthing_t *mt) + { + M_ClearBox(bbox); + + fixed_t x = mt->x << FRACBITS; + fixed_t y = mt->y << FRACBITS; + fixed_t radius = FixedMul(FixedMul(mobjinfo[MT_SNEAKERPANEL].radius, mt->scale), mapobjectscale); + + M_AddToBox(bbox, x - radius, y - radius); + M_AddToBox(bbox, x + radius, y + radius); + }*/ +}; + +static boolean K_SneakerPanelOverlap(complexity_sneaker_s &panelA, complexity_sneaker_s &panelB) +{ + const fixed_t overlap_extra = 528 * mapobjectscale; // merge ones this close together + + const fixed_t a_width_half = (panelA.bbox[BOXRIGHT] - panelA.bbox[BOXLEFT]) / 2; + const fixed_t a_height_half = (panelA.bbox[BOXTOP] - panelA.bbox[BOXBOTTOM]) / 2; + const fixed_t a_x = panelA.bbox[BOXLEFT] + a_width_half; + const fixed_t a_y = panelA.bbox[BOXBOTTOM] + a_height_half; + + const fixed_t b_width_half = (panelB.bbox[BOXRIGHT] - panelB.bbox[BOXLEFT]) / 2; + const fixed_t b_height_half = (panelB.bbox[BOXTOP] - panelB.bbox[BOXBOTTOM]) / 2; + const fixed_t b_x = panelB.bbox[BOXLEFT] + b_width_half; + const fixed_t b_y = panelB.bbox[BOXBOTTOM] + b_height_half; + + const fixed_t dx = b_x - a_x; + const fixed_t px = (b_width_half - a_width_half) - abs(dx); + if (px <= -overlap_extra) + { + return false; + } + + const fixed_t dy = b_y - a_y; + const fixed_t py = (b_height_half - a_height_half) - abs(dy); + if (py <= -overlap_extra) + { + return false; + } + + return true; +} + +/*-------------------------------------------------- + INT32 K_CalculateTrackComplexity(void) + + Sets the value of trackcomplexity. This value accumulates all of the + turn angle deltas to get an idea of how complicated the map is. +--------------------------------------------------*/ +static INT32 K_CalculateTrackComplexity(void) +{ + const boolean huntbackwards = false; + const boolean useshortcuts = false; + + boolean pathfindsuccess = false; + path_t path = {0}; + + trackcomplexity = BASE_TRACK_COMPLEXITY; + + if (startingwaypoint == NULL || finishline == NULL) + { + return trackcomplexity; + } + + pathfindsuccess = K_PathfindToWaypoint( + startingwaypoint, finishline, + &path, + useshortcuts, huntbackwards + ); + + if (pathfindsuccess == true) + { + auto path_finally = srb2::finally([&path]() { Z_Free(path.array); }); + + for (size_t i = 1; i < path.numnodes-1; i++) + { + waypoint_t *const start = (waypoint_t *)path.array[ i - 1 ].nodedata; + waypoint_t *const mid = (waypoint_t *)path.array[ i ].nodedata; + waypoint_t *const end = (waypoint_t *)path.array[ i + 1 ].nodedata; + + const INT32 turn_id = K_GetWaypointID(mid); + + // would it be better to just check mid? + if (K_GetWaypointIsSpawnpoint(start) == false + || K_GetWaypointIsSpawnpoint(mid) == false + || K_GetWaypointIsSpawnpoint(end) == false) + { + CONS_Debug(DBG_SETUP, "%s", fmt::format("TURN [{}]: skipped\n", turn_id).c_str()); + continue; + } + + const fixed_t start_mid_dist = R_PointToDist2( + start->mobj->x, start->mobj->y, + mid->mobj->x, mid->mobj->y + ); + const fixed_t mid_end_dist = R_PointToDist2( + mid->mobj->x, mid->mobj->y, + end->mobj->x, end->mobj->y + ); + + const angle_t start_mid_angle = R_PointToAngle2( + start->mobj->x, start->mobj->y, + mid->mobj->x, mid->mobj->y + ); + const angle_t mid_end_angle = R_PointToAngle2( + mid->mobj->x, mid->mobj->y, + end->mobj->x, end->mobj->y + ); + + const angle_t start_mid_pitch = R_PointToAngle2( + 0, start->mobj->z, + start_mid_dist, mid->mobj->z + ); + const angle_t mid_end_pitch = R_PointToAngle2( + 0, mid->mobj->z, + mid_end_dist, end->mobj->z + ); + + const fixed_t avg_radius = (start->mobj->radius + mid->mobj->radius + end->mobj->radius) / 3; + const fixed_t base_scale = DEFAULT_WAYPOINT_RADIUS * mapobjectscale; + + // Reduce complexity with wider turns. + fixed_t radius_factor = FixedDiv( + base_scale, + std::max( + 1, + avg_radius + ) + ); + radius_factor = FRACUNIT + ((radius_factor - FRACUNIT) / 2); // reduce how much it's worth + + // Reduce complexity with wider spaced waypoints. + fixed_t dist_factor = FixedDiv( + base_scale, + std::max( + 1, + start_mid_dist + mid_end_dist + ) + ); + + fixed_t wall_factor = FRACUNIT; + + constexpr fixed_t minimum_turn = 10 * FRACUNIT; // If the delta is lower than this, it's practically a straight-away. + fixed_t delta = AngleFixed( + AngleDelta( + start_mid_angle, + mid_end_angle + ) + ) - minimum_turn; + + if (delta < 0) + { + dist_factor = FixedDiv(FRACUNIT, std::max(1, dist_factor)); + radius_factor = FixedDiv(FRACUNIT, std::max(1, radius_factor)); + } + else + { + // Weight turns hard enough + delta = FixedMul(delta, delta); + + // Reduce turn complexity in walled maps. + wall_factor = FRACUNIT; + + g_track_wp_x = mid->mobj->x; + g_track_wp_y = mid->mobj->y; + g_track_wp_radius = mid->mobj->radius; + + const fixed_t searchRadius = /*g_track_wp_radius +*/ MAXRADIUS; + INT32 xl, xh, yl, yh; + INT32 bx, by; + + const fixed_t c = FixedMul(g_track_wp_radius, FINECOSINE((start_mid_angle + ANGLE_90) >> ANGLETOFINESHIFT)); + const fixed_t s = FixedMul(g_track_wp_radius, FINESINE((start_mid_angle + ANGLE_90) >> ANGLETOFINESHIFT)); + + validcount++; // used to make sure we only process a line once + + xl = (unsigned)((g_track_wp_x + c - searchRadius) - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)((g_track_wp_x + c + searchRadius) - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)((g_track_wp_y + s - searchRadius) - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)((g_track_wp_y + s + searchRadius) - bmaporgy)>>MAPBLOCKSHIFT; + + BMBOUNDFIX(xl, xh, yl, yh); + + for (bx = xl; bx <= xh; bx++) + { + for (by = yl; by <= yh; by++) + { + if (P_BlockLinesIterator(bx, by, K_TrackWaypointNearOffroad) == false) + { + wall_factor /= 4; + bx = xh + 1; + by = yh + 1; + } + } + } + + validcount++; // used to make sure we only process a line once + + xl = (unsigned)((g_track_wp_x - c - searchRadius) - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)((g_track_wp_x - c + searchRadius) - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)((g_track_wp_y - s - searchRadius) - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)((g_track_wp_y - s + searchRadius) - bmaporgy)>>MAPBLOCKSHIFT; + + BMBOUNDFIX(xl, xh, yl, yh); + + for (bx = xl; bx <= xh; bx++) + { + for (by = yl; by <= yh; by++) + { + if (P_BlockLinesIterator(bx, by, K_TrackWaypointNearOffroad) == false) + { + wall_factor /= 4; + bx = xh + 1; + by = yh + 1; + } + } + } + } + + fixed_t pitch_delta = AngleFixed( + AngleDelta( + start_mid_pitch, + mid_end_pitch + ) + ); + + constexpr fixed_t minimum_drop = 30 * FRACUNIT; // If the delta is lower than this, it's probably just a slope. + if (pitch_delta > minimum_drop) + { + // bonus complexity for drop-off / ramp + constexpr fixed_t drop_factor = 10 * FRACUNIT; + const fixed_t drop_off_mul = FRACUNIT + FixedDiv(pitch_delta - minimum_drop, drop_factor); + delta += FixedMul(pitch_delta, drop_off_mul); + } + + delta = FixedMul(delta, FixedMul(FixedMul(dist_factor, radius_factor), wall_factor)); + + std::string msg = fmt::format( + "TURN [{}]: r: {:.2f}, d: {:.2f}, w: {:.2f}, r*d*w: {:.2f}, DELTA: {}\n", + turn_id, + FixedToFloat(radius_factor), + FixedToFloat(dist_factor), + FixedToFloat(wall_factor), + FixedToFloat(FixedMul(FixedMul(dist_factor, radius_factor), wall_factor)), + (delta / FRACUNIT) + ); + CONS_Debug(DBG_SETUP, "%s", msg.c_str()); + trackcomplexity += (delta / FRACUNIT); + } + + std::vector sneaker_panels; + + for (size_t i = 0; i < numsectors; i++) + { + sector_t *const sec = §ors[i]; + if (sec->linecount == 0) + { + continue; + } + + terrain_t *terrain_f = K_GetTerrainForFlatNum(sec->floorpic); + terrain_t *terrain_c = K_GetTerrainForFlatNum(sec->ceilingpic); + + if ((terrain_f != nullptr && (terrain_f->flags & (TRF_SNEAKERPANEL|TRF_WATERRUNPANEL)) == (TRF_SNEAKERPANEL|TRF_WATERRUNPANEL)) + || (terrain_c != nullptr && (terrain_c->flags & (TRF_SNEAKERPANEL|TRF_WATERRUNPANEL)) == (TRF_SNEAKERPANEL|TRF_WATERRUNPANEL))) + { + complexity_sneaker_s new_panel(sec); + boolean create_new = true; + + for (size_t j = 0; j < sec->linecount; j++) + { + line_t *const ld = sec->lines[j]; + + M_AddToBox(new_panel.bbox, ld->bbox[BOXRIGHT], ld->bbox[BOXTOP]); + M_AddToBox(new_panel.bbox, ld->bbox[BOXLEFT], ld->bbox[BOXBOTTOM]); + } + + for (auto &panel : sneaker_panels) + { + if (K_SneakerPanelOverlap(new_panel, panel) == true) + { + // merge together + M_AddToBox(panel.bbox, new_panel.bbox[BOXRIGHT], new_panel.bbox[BOXTOP]); + M_AddToBox(panel.bbox, new_panel.bbox[BOXLEFT], new_panel.bbox[BOXBOTTOM]); + //panel.sectors.push_back(sec); + create_new = false; + break; + } + } + + if (create_new == true) + { + //new_panel.sectors.push_back(sec); + sneaker_panels.push_back(new_panel); + } + } + + if ((sec->specialflags & SSF_SNEAKERPANEL) || (sec->specialflags & SSF_WATERPANEL)) + { + complexity_sneaker_s new_panel(sec); + boolean create_new = true; + + for (size_t j = 0; j < sec->linecount; j++) + { + line_t *const ld = sec->lines[j]; + + M_AddToBox(new_panel.bbox, ld->bbox[BOXRIGHT], ld->bbox[BOXTOP]); + M_AddToBox(new_panel.bbox, ld->bbox[BOXLEFT], ld->bbox[BOXBOTTOM]); + } + + for (auto &panel : sneaker_panels) + { + if (K_SneakerPanelOverlap(new_panel, panel) == true) + { + // merge together + M_AddToBox(panel.bbox, new_panel.bbox[BOXRIGHT], new_panel.bbox[BOXTOP]); + M_AddToBox(panel.bbox, new_panel.bbox[BOXLEFT], new_panel.bbox[BOXBOTTOM]); + //panel.sectors.push_back(sec); + create_new = false; + break; + } + } + + if (create_new == true) + { + //new_panel.sectors.push_back(sec); + sneaker_panels.push_back(new_panel); + } + } + } + + + /*for (size_t i = 0; i < nummapthings; i++) + { + mapthing_t *const mt = &mapthings[i]; + if (mt->type != mobjinfo[MT_SNEAKERPANEL].doomednum) + { + continue; + } + + complexity_sneaker_s new_panel(mt); + boolean create_new = true; + + for (auto &panel : sneaker_panels) + { + if (K_SneakerPanelOverlap(new_panel, panel) == true) + { + // merge together + M_AddToBox(panel.bbox, new_panel.bbox[BOXRIGHT], new_panel.bbox[BOXTOP]); + M_AddToBox(panel.bbox, new_panel.bbox[BOXLEFT], new_panel.bbox[BOXBOTTOM]); + create_new = false; + break; + } + } + + if (create_new == true) + { + sneaker_panels.push_back(new_panel); + } + }*/ + + CONS_Debug(DBG_SETUP, "%s", fmt::format("Num sneaker panel sets: {}\n", sneaker_panels.size()).c_str()); + trackcomplexity -= sneaker_panels.size() * 1250; + + CONS_Debug(DBG_SETUP, " ** MAP COMPLEXITY: %d\n", trackcomplexity); + } + + return trackcomplexity; +} + +}; // namespace + /*-------------------------------------------------- boolean K_SetupWaypointList(void) @@ -2314,7 +2781,7 @@ boolean K_SetupWaypointList(void) { if (numbosswaypoints == 0) { - CONS_Alert(CONS_ERROR, "No waypoints or checkpoints in map.\n"); + CONS_Alert(CONS_ERROR, "No waypoints or legacy checkpoints in map.\n"); } } else @@ -2334,7 +2801,7 @@ boolean K_SetupWaypointList(void) { if (numbosswaypoints == 0) { - CONS_Alert(CONS_ERROR, "No waypoints or checkpoints in map.\n"); + CONS_Alert(CONS_ERROR, "No waypoints or legacy checkpoints in map.\n"); } } else @@ -2353,10 +2820,10 @@ boolean K_SetupWaypointList(void) CONS_Alert(CONS_ERROR, "Circuit track waypoints do not form a circuit.\n"); } - /*if (startingwaypoint != NULL) + if (startingwaypoint != NULL) { K_CalculateTrackComplexity(); - }*/ + } setupsuccessful = true; } diff --git a/src/k_waypoint.h b/src/k_waypoint.h index 39de98e2c..ca4aa351a 100644 --- a/src/k_waypoint.h +++ b/src/k_waypoint.h @@ -1,7 +1,7 @@ -// SONIC ROBO BLAST 2 KART +// DR. ROBOTNIK'S RING RACERS //----------------------------------------------------------------------------- -// Copyright (C) 2018-2020 by Sean "Sryder" Ryder -// Copyright (C) 2018-2020 by Kart Krew +// Copyright (C) 2024 by Sean "Sryder" Ryder +// Copyright (C) 2024 by Kart Krew // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -156,8 +156,10 @@ 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) @@ -172,6 +174,7 @@ INT32 K_GetWaypointID(waypoint_t *waypoint); waypoint_t *K_GetWaypointFromID(INT32 waypointID); + /*-------------------------------------------------- UINT32 K_GetCircuitLength(void) @@ -182,6 +185,7 @@ waypoint_t *K_GetWaypointFromID(INT32 waypointID); Return:- The circuit length. --------------------------------------------------*/ + UINT32 K_GetCircuitLength(void); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 840909eb8..73ee51527 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1041,7 +1041,8 @@ static int lib_pRemoveFloorSpriteSlope(lua_State *L) static int lib_pRailThinker(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - tm_t ptm = tm; + tm_t ptm = g_tm; + NOHUD INLEVEL if (!mobj) @@ -1054,7 +1055,8 @@ static int lib_pRailThinker(lua_State *L) static int lib_pXYMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - tm_t ptm = tm; + tm_t ptm = g_tm; + NOHUD INLEVEL if (!actor) @@ -1067,7 +1069,8 @@ static int lib_pXYMovement(lua_State *L) static int lib_pRingXYMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - tm_t ptm = tm; + tm_t ptm = g_tm; + NOHUD INLEVEL if (!actor) @@ -1080,7 +1083,8 @@ static int lib_pRingXYMovement(lua_State *L) static int lib_pSceneryXYMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - tm_t ptm = tm; + tm_t ptm = g_tm; + NOHUD INLEVEL if (!actor) @@ -1093,7 +1097,8 @@ static int lib_pSceneryXYMovement(lua_State *L) static int lib_pZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - tm_t ptm = tm; + tm_t ptm = g_tm; + NOHUD INLEVEL if (!actor) @@ -1107,7 +1112,8 @@ static int lib_pZMovement(lua_State *L) static int lib_pRingZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - tm_t ptm = tm; + tm_t ptm = g_tm; + NOHUD INLEVEL if (!actor) @@ -1121,7 +1127,8 @@ static int lib_pRingZMovement(lua_State *L) static int lib_pSceneryZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - tm_t ptm = tm; + tm_t ptm = g_tm; + NOHUD INLEVEL if (!actor) @@ -1135,7 +1142,8 @@ static int lib_pSceneryZMovement(lua_State *L) static int lib_pPlayerZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - tm_t ptm = tm; + tm_t ptm = g_tm; + NOHUD INLEVEL if (!actor) @@ -1354,7 +1362,8 @@ static int lib_pGivePlayerLives(lua_State *L) static int lib_pMovePlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - tm_t ptm = tm; + tm_t ptm = g_tm; + NOHUD INLEVEL if (!player) @@ -1432,7 +1441,8 @@ static int lib_pNukeEnemies(lua_State *L) static int lib_pCheckPosition(lua_State *L) { - tm_t ptm = tm; + tm_t ptm = g_tm; + mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); @@ -1441,14 +1451,15 @@ static int lib_pCheckPosition(lua_State *L) if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_CheckPosition(thing, x, y, NULL)); - LUA_PushUserdata(L, tm.thing, META_MOBJ); + LUA_PushUserdata(L, g_tm.thing, META_MOBJ); P_RestoreTMStruct(ptm); return 2; } static int lib_pTryMove(lua_State *L) { - tm_t ptm = tm; + tm_t ptm = g_tm; + mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); @@ -1458,14 +1469,15 @@ static int lib_pTryMove(lua_State *L) if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_TryMove(thing, x, y, allowdropoff, NULL)); - LUA_PushUserdata(L, tm.thing, META_MOBJ); + LUA_PushUserdata(L, g_tm.thing, META_MOBJ); P_RestoreTMStruct(ptm); return 2; } static int lib_pMove(lua_State *L) { - tm_t ptm = tm; + tm_t ptm = g_tm; + mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t speed = luaL_checkfixed(L, 2); NOHUD @@ -1473,14 +1485,15 @@ static int lib_pMove(lua_State *L) if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_Move(actor, speed)); - LUA_PushUserdata(L, tm.thing, META_MOBJ); + LUA_PushUserdata(L, g_tm.thing, META_MOBJ); P_RestoreTMStruct(ptm); return 2; } static int lib_pTeleportMove(lua_State *L) { - tm_t ptm = tm; + tm_t ptm = g_tm; + mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); @@ -1491,14 +1504,15 @@ static int lib_pTeleportMove(lua_State *L) return LUA_ErrInvalid(L, "mobj_t"); LUA_Deprecated(L, "P_TeleportMove", "P_SetOrigin\" or \"P_MoveOrigin"); lua_pushboolean(L, P_MoveOrigin(thing, x, y, z)); - LUA_PushUserdata(L, tm.thing, META_MOBJ); + LUA_PushUserdata(L, g_tm.thing, META_MOBJ); P_RestoreTMStruct(ptm); return 2; } static int lib_pSetOrigin(lua_State *L) { - tm_t ptm = tm; + tm_t ptm = g_tm; + mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); @@ -1508,14 +1522,15 @@ static int lib_pSetOrigin(lua_State *L) if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_SetOrigin(thing, x, y, z)); - LUA_PushUserdata(L, tm.thing, META_MOBJ); + LUA_PushUserdata(L, g_tm.thing, META_MOBJ); P_RestoreTMStruct(ptm); return 2; } static int lib_pMoveOrigin(lua_State *L) { - tm_t ptm = tm; + tm_t ptm = g_tm; + mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); @@ -1525,7 +1540,7 @@ static int lib_pMoveOrigin(lua_State *L) if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_MoveOrigin(thing, x, y, z)); - LUA_PushUserdata(L, tm.thing, META_MOBJ); + LUA_PushUserdata(L, g_tm.thing, META_MOBJ); P_RestoreTMStruct(ptm); return 2; } diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 77a3e6174..841141a26 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -812,7 +812,8 @@ static int sector_set(lua_State *L) return luaL_error(L, "sector_t has no field named " LUA_QS ".", lua_tostring(L, 2)); case sector_floorheight: { // floorheight boolean flag; - tm_t ptm = tm; + tm_t ptm = g_tm; + fixed_t lastpos = sector->floorheight; sector->floorheight = luaL_checkfixed(L, 3); flag = P_CheckSector(sector, true); @@ -826,7 +827,8 @@ static int sector_set(lua_State *L) } case sector_ceilingheight: { // ceilingheight boolean flag; - tm_t ptm = tm; + tm_t ptm = g_tm; + fixed_t lastpos = sector->ceilingheight; sector->ceilingheight = luaL_checkfixed(L, 3); flag = P_CheckSector(sector, true); @@ -2264,7 +2266,8 @@ static int ffloor_set(lua_State *L) case ffloor_topheight: { // topheight boolean flag; fixed_t lastpos = *ffloor->topheight; - tm_t ptm = tm; + tm_t ptm = g_tm; + sector_t *sector = §ors[ffloor->secnum]; sector->ceilingheight = luaL_checkfixed(L, 3); flag = P_CheckSector(sector, true); @@ -2285,7 +2288,8 @@ static int ffloor_set(lua_State *L) case ffloor_bottomheight: { // bottomheight boolean flag; fixed_t lastpos = *ffloor->bottomheight; - tm_t ptm = tm; + tm_t ptm = g_tm; + sector_t *sector = §ors[ffloor->secnum]; sector->floorheight = luaL_checkfixed(L, 3); flag = P_CheckSector(sector, true); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 78d511402..eab532d9e 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -654,13 +654,14 @@ static int mobj_set(lua_State *L) case mobj_z: { // z doesn't cross sector bounds so it's okay. - tm_t ptm = tm; + tm_t ptm = g_tm; + mo->z = luaL_checkfixed(L, 3); P_CheckPosition(mo, mo->x, mo->y, NULL); - mo->floorz = tm.floorz; - mo->ceilingz = tm.ceilingz; - mo->floorrover = tm.floorrover; - mo->ceilingrover = tm.ceilingrover; + mo->floorz = g_tm.floorz; + mo->ceilingz = g_tm.ceilingz; + mo->floorrover = g_tm.floorrover; + mo->ceilingrover = g_tm.ceilingrover; P_RestoreTMStruct(ptm); break; } @@ -734,29 +735,31 @@ static int mobj_set(lua_State *L) return NOSET; case mobj_radius: { - tm_t ptm = tm; + tm_t ptm = g_tm; + mo->radius = luaL_checkfixed(L, 3); if (mo->radius < 0) mo->radius = 0; P_CheckPosition(mo, mo->x, mo->y, NULL); - mo->floorz = tm.floorz; - mo->ceilingz = tm.ceilingz; - mo->floorrover = tm.floorrover; - mo->ceilingrover = tm.ceilingrover; + mo->floorz = g_tm.floorz; + mo->ceilingz = g_tm.ceilingz; + mo->floorrover = g_tm.floorrover; + mo->ceilingrover = g_tm.ceilingrover; P_RestoreTMStruct(ptm); break; } case mobj_height: { - tm_t ptm = tm; + tm_t ptm = g_tm; + mo->height = luaL_checkfixed(L, 3); if (mo->height < 0) mo->height = 0; P_CheckPosition(mo, mo->x, mo->y, NULL); - mo->floorz = tm.floorz; - mo->ceilingz = tm.ceilingz; - mo->floorrover = tm.floorrover; - mo->ceilingrover = tm.ceilingrover; + mo->floorz = g_tm.floorz; + mo->ceilingz = g_tm.ceilingz; + mo->floorrover = g_tm.floorrover; + mo->ceilingrover = g_tm.ceilingrover; P_RestoreTMStruct(ptm); break; } diff --git a/src/p_enemy.c b/src/p_enemy.c index 09a426c25..9f83f5e77 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -269,10 +269,10 @@ boolean P_Move(mobj_t *actor, fixed_t speed) if (!P_TryMove(actor, tryx, tryy, false, NULL)) { - if (actor->flags & MF_FLOAT && tm.floatok) + if (actor->flags & MF_FLOAT && g_tm.floatok) { // must adjust height - if (actor->z < tm.floorz) + if (actor->z < g_tm.floorz) actor->z += FixedMul(FLOATSPEED, actor->scale); else actor->z -= FixedMul(FLOATSPEED, actor->scale); @@ -10314,13 +10314,13 @@ void A_FlickyCenter(mobj_t *actor) { actor->extravalue2 = 1; P_SetOrigin(actor, actor->target->x, actor->target->y, actor->target->z); - P_SetTarget(&tm.thing, NULL); + P_SetTarget(&g_tm.thing, NULL); } else if(actor->extravalue2) { actor->extravalue2 = 0; P_SetOrigin(actor, originx, originy, originz); - P_SetTarget(&tm.thing, NULL); + P_SetTarget(&g_tm.thing, NULL); } } } @@ -12999,7 +12999,7 @@ void A_ItemPop(mobj_t *actor) remains->skin = NULL; remains->spawnpoint = actor->spawnpoint; - P_SetTarget(&tm.thing, remains); + P_SetTarget(&g_tm.thing, remains); //if (actor->info->deathsound) //S_StartSound(remains, actor->info->deathsound); diff --git a/src/p_local.h b/src/p_local.h index b70eb7eda..d16051dc9 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -404,12 +404,12 @@ struct tm_t fixed_t precipbbox[4]; // If "floatok" true, move would be ok - // if within "tm.floorz - tm.ceilingz". + // if within "g_tm.floorz - g_tm.ceilingz". boolean floatok; fixed_t floorz, ceilingz; fixed_t dropoffz, drpoffceilz; // drop-off floor/ceiling heights - mobj_t *floorthing; // the thing corresponding to tm.floorz or NULL if tm.floorz is from a sector + mobj_t *floorthing; // the thing corresponding to g_tm.floorz or NULL if g_tm.floorz is from a sector mobj_t *hitthing; // the solid thing you bumped into (for collisions) ffloor_t *floorrover, *ceilingrover; pslope_t *floorslope, *ceilingslope; @@ -428,11 +428,11 @@ struct tm_t // lines boolean sweep; - // sweep: max step up at tm.x, tm.y + // sweep: max step up at g_tm.x, g_tm.y fixed_t maxstep; }; -extern tm_t tm; +extern tm_t g_tm; void P_RestoreTMStruct(tm_t tmrestore); diff --git a/src/p_map.c b/src/p_map.c index 4ea3e6b12..58c42169e 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -42,33 +42,33 @@ #include "m_perfstats.h" // ps_checkposition_calls -tm_t tm = {0}; +tm_t g_tm = {0}; void P_RestoreTMStruct(tm_t tmrestore) { // Reference count management // These are effectively a no-op if mobj remains the same - P_SetTarget(&tm.thing, tmrestore.thing); - P_SetTarget(&tm.floorthing, tmrestore.floorthing); - P_SetTarget(&tm.hitthing, tmrestore.hitthing); + P_SetTarget(&g_tm.thing, tmrestore.thing); + P_SetTarget(&g_tm.floorthing, tmrestore.floorthing); + P_SetTarget(&g_tm.hitthing, tmrestore.hitthing); // Restore state - tm = tmrestore; + g_tm = tmrestore; // Validation - if (tm.thing && P_MobjWasRemoved(tm.thing) == true) + if (g_tm.thing && P_MobjWasRemoved(g_tm.thing) == true) { - P_SetTarget(&tm.thing, NULL); + P_SetTarget(&g_tm.thing, NULL); } - if (tm.floorthing && P_MobjWasRemoved(tm.floorthing) == true) + if (g_tm.floorthing && P_MobjWasRemoved(g_tm.floorthing) == true) { - P_SetTarget(&tm.floorthing, NULL); + P_SetTarget(&g_tm.floorthing, NULL); } - if (tm.hitthing && P_MobjWasRemoved(tm.hitthing) == true) + if (g_tm.hitthing && P_MobjWasRemoved(g_tm.hitthing) == true) { - P_SetTarget(&tm.hitthing, NULL); + P_SetTarget(&g_tm.hitthing, NULL); } } @@ -124,10 +124,10 @@ static boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z) if (P_MobjWasRemoved(thing)) return true; - thing->floorz = tm.floorz; - thing->ceilingz = tm.ceilingz; - thing->floorrover = tm.floorrover; - thing->ceilingrover = tm.ceilingrover; + thing->floorz = g_tm.floorz; + thing->ceilingz = g_tm.ceilingz; + thing->floorrover = g_tm.floorrover; + thing->ceilingrover = g_tm.ceilingrover; return true; } @@ -469,28 +469,28 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) { fixed_t blockdist; - if (tm.thing == NULL || P_MobjWasRemoved(tm.thing) == true) - return BMIT_STOP; // func just popped our tm.thing, cannot continue. + if (g_tm.thing == NULL || P_MobjWasRemoved(g_tm.thing) == true) + return BMIT_STOP; // func just popped our g_tm.thing, cannot continue. // Ignore... things. if (thing == NULL || P_MobjWasRemoved(thing) == true) return BMIT_CONTINUE; // don't clip against self - if (thing == tm.thing) + if (thing == g_tm.thing) return BMIT_CONTINUE; // Ignore spectators - if ((tm.thing->player && tm.thing->player->spectator) + if ((g_tm.thing->player && g_tm.thing->player->spectator) || (thing->player && thing->player->spectator)) return BMIT_CONTINUE; if ((thing->flags & MF_NOCLIPTHING) || !(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING))) return BMIT_CONTINUE; - blockdist = thing->radius + tm.thing->radius; + blockdist = thing->radius + g_tm.thing->radius; - if (abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist) + if (abs(thing->x - g_tm.x) >= blockdist || abs(thing->y - g_tm.y) >= blockdist) return BMIT_CONTINUE; // didn't hit it if (thing->flags & MF_PAPERCOLLISION) // CAUTION! Very easy to get stuck inside MF_SOLID objects. Giving the player MF_PAPERCOLLISION is a bad idea unless you know what you're doing. @@ -512,47 +512,47 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) junk.dx = 2*cosradius; // v2.x - v1.x; junk.dy = 2*sinradius; // v2.y - v1.y; - if (tm.thing->flags & MF_PAPERCOLLISION) // more strenuous checking to prevent clipping issues + if (g_tm.thing->flags & MF_PAPERCOLLISION) // more strenuous checking to prevent clipping issues { INT32 check1, check2, check3, check4; - fixed_t tmcosradius = FixedMul(tm.thing->radius, FINECOSINE(tm.thing->angle>>ANGLETOFINESHIFT)); - fixed_t tmsinradius = FixedMul(tm.thing->radius, FINESINE(tm.thing->angle>>ANGLETOFINESHIFT)); - if (abs(thing->x - tm.x) >= (abs(tmcosradius) + abs(cosradius)) || abs(thing->y - tm.y) >= (abs(tmsinradius) + abs(sinradius))) + fixed_t tmcosradius = FixedMul(g_tm.thing->radius, FINECOSINE(g_tm.thing->angle>>ANGLETOFINESHIFT)); + fixed_t tmsinradius = FixedMul(g_tm.thing->radius, FINESINE(g_tm.thing->angle>>ANGLETOFINESHIFT)); + if (abs(thing->x - g_tm.x) >= (abs(tmcosradius) + abs(cosradius)) || abs(thing->y - g_tm.y) >= (abs(tmsinradius) + abs(sinradius))) return BMIT_CONTINUE; // didn't hit it - check1 = P_PointOnLineSide(tm.x - tmcosradius, tm.y - tmsinradius, &junk); - check2 = P_PointOnLineSide(tm.x + tmcosradius, tm.y + tmsinradius, &junk); - check3 = P_PointOnLineSide(tm.x + tm.thing->momx - tmcosradius, tm.y + tm.thing->momy - tmsinradius, &junk); - check4 = P_PointOnLineSide(tm.x + tm.thing->momx + tmcosradius, tm.y + tm.thing->momy + tmsinradius, &junk); + check1 = P_PointOnLineSide(g_tm.x - tmcosradius, g_tm.y - tmsinradius, &junk); + check2 = P_PointOnLineSide(g_tm.x + tmcosradius, g_tm.y + tmsinradius, &junk); + check3 = P_PointOnLineSide(g_tm.x + g_tm.thing->momx - tmcosradius, g_tm.y + g_tm.thing->momy - tmsinradius, &junk); + check4 = P_PointOnLineSide(g_tm.x + g_tm.thing->momx + tmcosradius, g_tm.y + g_tm.thing->momy + tmsinradius, &junk); if ((check1 == check2) && (check2 == check3) && (check3 == check4)) return BMIT_CONTINUE; // the line doesn't cross between collider's start or end } else { - if (abs(thing->x - tm.x) >= (tm.thing->radius + abs(cosradius)) || abs(thing->y - tm.y) >= (tm.thing->radius + abs(sinradius))) + if (abs(thing->x - g_tm.x) >= (g_tm.thing->radius + abs(cosradius)) || abs(thing->y - g_tm.y) >= (g_tm.thing->radius + abs(sinradius))) return BMIT_CONTINUE; // didn't hit it - if ((P_PointOnLineSide(tm.x - tm.thing->radius, tm.y - tm.thing->radius, &junk) - == P_PointOnLineSide(tm.x + tm.thing->radius, tm.y + tm.thing->radius, &junk)) - && (P_PointOnLineSide(tm.x + tm.thing->radius, tm.y - tm.thing->radius, &junk) - == P_PointOnLineSide(tm.x - tm.thing->radius, tm.y + tm.thing->radius, &junk))) + if ((P_PointOnLineSide(g_tm.x - g_tm.thing->radius, g_tm.y - g_tm.thing->radius, &junk) + == P_PointOnLineSide(g_tm.x + g_tm.thing->radius, g_tm.y + g_tm.thing->radius, &junk)) + && (P_PointOnLineSide(g_tm.x + g_tm.thing->radius, g_tm.y - g_tm.thing->radius, &junk) + == P_PointOnLineSide(g_tm.x - g_tm.thing->radius, g_tm.y + g_tm.thing->radius, &junk))) return BMIT_CONTINUE; // the line doesn't cross between either pair of opposite corners } } - else if (tm.thing->flags & MF_PAPERCOLLISION) + else if (g_tm.thing->flags & MF_PAPERCOLLISION) { fixed_t tmcosradius, tmsinradius; vertex_t v1, v2; // fake vertexes line_t junk; // fake linedef - tmcosradius = FixedMul(tm.thing->radius, FINECOSINE(tm.thing->angle>>ANGLETOFINESHIFT)); - tmsinradius = FixedMul(tm.thing->radius, FINESINE(tm.thing->angle>>ANGLETOFINESHIFT)); + tmcosradius = FixedMul(g_tm.thing->radius, FINECOSINE(g_tm.thing->angle>>ANGLETOFINESHIFT)); + tmsinradius = FixedMul(g_tm.thing->radius, FINESINE(g_tm.thing->angle>>ANGLETOFINESHIFT)); - if (abs(thing->x - tm.x) >= (thing->radius + abs(tmcosradius)) || abs(thing->y - tm.y) >= (thing->radius + abs(tmsinradius))) + if (abs(thing->x - g_tm.x) >= (thing->radius + abs(tmcosradius)) || abs(thing->y - g_tm.y) >= (thing->radius + abs(tmsinradius))) return BMIT_CONTINUE; // didn't hit it - v1.x = tm.x - tmcosradius; - v1.y = tm.y - tmsinradius; - v2.x = tm.x + tmcosradius; - v2.y = tm.y + tmsinradius; + v1.x = g_tm.x - tmcosradius; + v1.y = g_tm.y - tmsinradius; + v2.x = g_tm.x + tmcosradius; + v2.y = g_tm.y + tmsinradius; junk.v1 = &v1; junk.v2 = &v2; @@ -568,16 +568,16 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } { - UINT8 shouldCollide = LUA_Hook2Mobj(thing, tm.thing, MOBJ_HOOK(MobjCollide)); // checks hook for thing's type - if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) + UINT8 shouldCollide = LUA_Hook2Mobj(thing, g_tm.thing, MOBJ_HOOK(MobjCollide)); // checks hook for thing's type + if (P_MobjWasRemoved(g_tm.thing) || P_MobjWasRemoved(thing)) return BMIT_CONTINUE; // one of them was removed??? if (shouldCollide == 1) return BMIT_ABORT; // force collide else if (shouldCollide == 2) return BMIT_CONTINUE; // force no collide - shouldCollide = LUA_Hook2Mobj(tm.thing, thing, MOBJ_HOOK(MobjMoveCollide)); // checks hook for tm.thing's type - if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) + shouldCollide = LUA_Hook2Mobj(g_tm.thing, thing, MOBJ_HOOK(MobjMoveCollide)); // checks hook for g_tm.thing's type + if (P_MobjWasRemoved(g_tm.thing) || P_MobjWasRemoved(thing)) return BMIT_CONTINUE; // one of them was removed??? if (shouldCollide == 1) return BMIT_ABORT; // force collide @@ -586,66 +586,66 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // When solid spikes move, assume they just popped up and teleport things on top of them to hurt. - if (tm.thing->type == MT_SPIKE && tm.thing->flags & MF_SOLID) + if (g_tm.thing->type == MT_SPIKE && g_tm.thing->flags & MF_SOLID) { - if (thing->z > tm.thing->z + tm.thing->height) + if (thing->z > g_tm.thing->z + g_tm.thing->height) return BMIT_CONTINUE; // overhead - if (thing->z + thing->height < tm.thing->z) + if (thing->z + thing->height < g_tm.thing->z) return BMIT_CONTINUE; // underneath - if (tm.thing->eflags & MFE_VERTICALFLIP) - P_SetOrigin(thing, thing->x, thing->y, tm.thing->z - thing->height - FixedMul(FRACUNIT, tm.thing->scale)); + if (g_tm.thing->eflags & MFE_VERTICALFLIP) + P_SetOrigin(thing, thing->x, thing->y, g_tm.thing->z - thing->height - FixedMul(FRACUNIT, g_tm.thing->scale)); else - P_SetOrigin(thing, thing->x, thing->y, tm.thing->z + tm.thing->height + FixedMul(FRACUNIT, tm.thing->scale)); + P_SetOrigin(thing, thing->x, thing->y, g_tm.thing->z + g_tm.thing->height + FixedMul(FRACUNIT, g_tm.thing->scale)); if (thing->flags & MF_SHOOTABLE) - P_DamageMobj(thing, tm.thing, tm.thing, 1, 0); + P_DamageMobj(thing, g_tm.thing, g_tm.thing, 1, 0); return BMIT_CONTINUE; } if (thing->flags & MF_PAIN) { // Player touches painful thing sitting on the floor // see if it went over / under - if (thing->z > tm.thing->z + tm.thing->height) + if (thing->z > g_tm.thing->z + g_tm.thing->height) return BMIT_CONTINUE; // overhead - if (thing->z + thing->height < tm.thing->z) + if (thing->z + thing->height < g_tm.thing->z) return BMIT_CONTINUE; // underneath - if (tm.thing->player && tm.thing->flags & MF_SHOOTABLE && thing->health > 0) + if (g_tm.thing->player && g_tm.thing->flags & MF_SHOOTABLE && thing->health > 0) { - UINT32 damagetype = (tm.thing->info->mass & DMG_TYPEMASK); + UINT32 damagetype = (g_tm.thing->info->mass & DMG_TYPEMASK); if (!damagetype && thing->flags & MF_FIRE) // BURN! damagetype = DMG_NORMAL; - P_DamageMobj(tm.thing, thing, thing, 1, damagetype); + P_DamageMobj(g_tm.thing, thing, thing, 1, damagetype); } return BMIT_CONTINUE; } - else if (tm.thing->flags & MF_PAIN) + else if (g_tm.thing->flags & MF_PAIN) { // Painful thing splats player in the face // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - if (thing->player && thing->flags & MF_SHOOTABLE && tm.thing->health > 0) + if (thing->player && thing->flags & MF_SHOOTABLE && g_tm.thing->health > 0) { - UINT32 damagetype = (tm.thing->info->mass & DMG_TYPEMASK); - if (!damagetype && tm.thing->flags & MF_FIRE) // BURN! + UINT32 damagetype = (g_tm.thing->info->mass & DMG_TYPEMASK); + if (!damagetype && g_tm.thing->flags & MF_FIRE) // BURN! damagetype = DMG_NORMAL; - P_DamageMobj(thing, tm.thing, tm.thing, 1, damagetype); + P_DamageMobj(thing, g_tm.thing, g_tm.thing, 1, damagetype); } return BMIT_CONTINUE; } // check for skulls slamming into things - if (tm.thing->flags2 & MF2_SKULLFLY) + if (g_tm.thing->flags2 & MF2_SKULLFLY) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - tm.thing->flags2 &= ~MF2_SKULLFLY; - tm.thing->momx = tm.thing->momy = tm.thing->momz = 0; + g_tm.thing->flags2 &= ~MF2_SKULLFLY; + g_tm.thing->momx = g_tm.thing->momy = g_tm.thing->momz = 0; return BMIT_ABORT; // stop moving } @@ -654,252 +654,252 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (thing->type == MT_SMK_ICEBLOCK) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_SMKIceBlockCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_SMKIceBlockCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tm.thing->type == MT_EGGMANITEM || tm.thing->type == MT_EGGMANITEM_SHIELD) + if (g_tm.thing->type == MT_EGGMANITEM || g_tm.thing->type == MT_EGGMANITEM_SHIELD) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_EggItemCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_EggItemCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_EGGMANITEM || thing->type == MT_EGGMANITEM_SHIELD) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_EggItemCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_EggItemCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tm.thing->type == MT_RANDOMITEM) + if (g_tm.thing->type == MT_RANDOMITEM) return BMIT_CONTINUE; // Bubble Shield reflect if (((thing->type == MT_BUBBLESHIELD && thing->target->player && thing->target->player->bubbleblowup) || (thing->player && thing->player->bubbleblowup)) - && (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ || tm.thing->type == MT_JAWZ_DUD - || tm.thing->type == MT_BANANA || tm.thing->type == MT_EGGMANITEM || tm.thing->type == MT_BALLHOG - || tm.thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || tm.thing->type == MT_SINK - || (tm.thing->type == MT_PLAYER && thing->target != tm.thing))) + && (g_tm.thing->type == MT_ORBINAUT || g_tm.thing->type == MT_JAWZ || g_tm.thing->type == MT_JAWZ_DUD + || g_tm.thing->type == MT_BANANA || g_tm.thing->type == MT_EGGMANITEM || g_tm.thing->type == MT_BALLHOG + || g_tm.thing->type == MT_SSMINE || g_tm.thing->type == MT_LANDMINE || g_tm.thing->type == MT_SINK + || (g_tm.thing->type == MT_PLAYER && thing->target != g_tm.thing))) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_BubbleShieldCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_BubbleShieldCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - else if (((tm.thing->type == MT_BUBBLESHIELD && tm.thing->target->player && tm.thing->target->player->bubbleblowup) - || (tm.thing->player && tm.thing->player->bubbleblowup)) + else if (((g_tm.thing->type == MT_BUBBLESHIELD && g_tm.thing->target->player && g_tm.thing->target->player->bubbleblowup) + || (g_tm.thing->player && g_tm.thing->player->bubbleblowup)) && (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG - || thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || thing->type == MT_SINK - || (thing->type == MT_PLAYER && tm.thing->target != thing))) + || thing->type == MT_SSMINE || g_tm.thing->type == MT_LANDMINE || thing->type == MT_SINK + || (thing->type == MT_PLAYER && g_tm.thing->target != thing))) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_BubbleShieldCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_BubbleShieldCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } // double make sure bubbles won't collide with anything else - if (thing->type == MT_BUBBLESHIELD || tm.thing->type == MT_BUBBLESHIELD) + if (thing->type == MT_BUBBLESHIELD || g_tm.thing->type == MT_BUBBLESHIELD) return BMIT_CONTINUE; // Droptarget reflect if ((thing->type == MT_DROPTARGET || thing->type == MT_DROPTARGET_SHIELD) - && (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ || tm.thing->type == MT_JAWZ_DUD - || tm.thing->type == MT_BANANA || tm.thing->type == MT_EGGMANITEM || tm.thing->type == MT_BALLHOG - || tm.thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || tm.thing->type == MT_SINK - || (tm.thing->type == MT_PLAYER))) + && (g_tm.thing->type == MT_ORBINAUT || g_tm.thing->type == MT_JAWZ || g_tm.thing->type == MT_JAWZ_DUD + || g_tm.thing->type == MT_BANANA || g_tm.thing->type == MT_EGGMANITEM || g_tm.thing->type == MT_BALLHOG + || g_tm.thing->type == MT_SSMINE || g_tm.thing->type == MT_LANDMINE || g_tm.thing->type == MT_SINK + || (g_tm.thing->type == MT_PLAYER))) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_DropTargetCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_DropTargetCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - else if ((tm.thing->type == MT_DROPTARGET || tm.thing->type == MT_DROPTARGET_SHIELD) + else if ((g_tm.thing->type == MT_DROPTARGET || g_tm.thing->type == MT_DROPTARGET_SHIELD) && (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG - || thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || thing->type == MT_SINK + || thing->type == MT_SSMINE || g_tm.thing->type == MT_LANDMINE || thing->type == MT_SINK || (thing->type == MT_PLAYER))) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_DropTargetCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_DropTargetCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } // double make sure drop targets won't collide with anything else - if (thing->type == MT_DROPTARGET || tm.thing->type == MT_DROPTARGET - || thing->type == MT_DROPTARGET_SHIELD || tm.thing->type == MT_DROPTARGET_SHIELD) + if (thing->type == MT_DROPTARGET || g_tm.thing->type == MT_DROPTARGET + || thing->type == MT_DROPTARGET_SHIELD || g_tm.thing->type == MT_DROPTARGET_SHIELD) return BMIT_CONTINUE; - if (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ || tm.thing->type == MT_JAWZ_DUD - || tm.thing->type == MT_ORBINAUT_SHIELD || tm.thing->type == MT_JAWZ_SHIELD) + if (g_tm.thing->type == MT_ORBINAUT || g_tm.thing->type == MT_JAWZ || g_tm.thing->type == MT_JAWZ_DUD + || g_tm.thing->type == MT_ORBINAUT_SHIELD || g_tm.thing->type == MT_JAWZ_SHIELD) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_OrbinautJawzCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_OrbinautJawzCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_OrbinautJawzCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_OrbinautJawzCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tm.thing->type == MT_BANANA || tm.thing->type == MT_BANANA_SHIELD || tm.thing->type == MT_BALLHOG) + if (g_tm.thing->type == MT_BANANA || g_tm.thing->type == MT_BANANA_SHIELD || g_tm.thing->type == MT_BALLHOG) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_BananaBallhogCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_BananaBallhogCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD || thing->type == MT_BALLHOG) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_BananaBallhogCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_BananaBallhogCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tm.thing->type == MT_SSMINE || tm.thing->type == MT_SSMINE_SHIELD) + if (g_tm.thing->type == MT_SSMINE || g_tm.thing->type == MT_SSMINE_SHIELD) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_MineCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_MineCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_SSMINE || thing->type == MT_SSMINE_SHIELD) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_MineCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_MineCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tm.thing->type == MT_LANDMINE) + if (g_tm.thing->type == MT_LANDMINE) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_LandMineCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_LandMineCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_LANDMINE) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_LandMineCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_LandMineCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tm.thing->type == MT_SINK) + if (g_tm.thing->type == MT_SINK) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_KitchenSinkCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_KitchenSinkCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_SINK) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_KitchenSinkCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_KitchenSinkCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tm.thing->type == MT_FALLINGROCK) + if (g_tm.thing->type == MT_FALLINGROCK) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_FallingRockCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_FallingRockCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_FALLINGROCK) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_FallingRockCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_FallingRockCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } //} if ((thing->type == MT_SPRINGSHELL || thing->type == MT_YELLOWSHELL) && thing->health > 0 - && (tm.thing->player || (tm.thing->flags & MF_PUSHABLE)) && tm.thing->health > 0) + && (g_tm.thing->player || (g_tm.thing->flags & MF_PUSHABLE)) && g_tm.thing->health > 0) { // Multiplying by -1 inherently flips "less than" and "greater than" - fixed_t tmz = ((thing->eflags & MFE_VERTICALFLIP) ? -(tm.thing->z + tm.thing->height) : tm.thing->z); - fixed_t tmznext = ((thing->eflags & MFE_VERTICALFLIP) ? -tm.thing->momz : tm.thing->momz) + tmz; + fixed_t tmz = ((thing->eflags & MFE_VERTICALFLIP) ? -(g_tm.thing->z + g_tm.thing->height) : g_tm.thing->z); + fixed_t tmznext = ((thing->eflags & MFE_VERTICALFLIP) ? -g_tm.thing->momz : g_tm.thing->momz) + tmz; fixed_t thzh = ((thing->eflags & MFE_VERTICALFLIP) ? -thing->z : thing->z + thing->height); //fixed_t sprarea = FixedMul(8*FRACUNIT, thing->scale) * P_MobjFlip(thing); //if ((tmznext <= thzh && tmz > thzh) || (tmznext > thzh - sprarea && tmznext < thzh)) if (tmznext <= thzh) { - P_DoSpring(thing, tm.thing); + P_DoSpring(thing, g_tm.thing); // return BMIT_CONTINUE; } //else if (tmz > thzh - sprarea && tmz < thzh) // Don't damage people springing up / down @@ -907,20 +907,20 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // missiles can hit other things - if (tm.thing->flags & MF_MISSILE) + if (g_tm.thing->flags & MF_MISSILE) { - UINT8 damagetype = tm.thing->info->mass; + UINT8 damagetype = g_tm.thing->info->mass; // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - if (tm.thing->target && tm.thing->target->type == thing->type) + if (g_tm.thing->target && g_tm.thing->target->type == thing->type) { // Don't hit same species as originator. - if (thing == tm.thing->target) + if (thing == g_tm.thing->target) return BMIT_CONTINUE; if (thing->type != MT_PLAYER) @@ -938,40 +938,40 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // damage / explode - P_DamageMobj(thing, tm.thing, tm.thing->target, 1, damagetype); + P_DamageMobj(thing, g_tm.thing, g_tm.thing->target, 1, damagetype); // don't traverse any more return BMIT_ABORT; } - if (thing->flags & MF_PUSHABLE && (tm.thing->player || tm.thing->flags & MF_PUSHABLE) - && tm.thing->z + tm.thing->height > thing->z && tm.thing->z < thing->z + thing->height - && !(netgame && tm.thing->player && tm.thing->player->spectator)) // Push thing! + if (thing->flags & MF_PUSHABLE && (g_tm.thing->player || g_tm.thing->flags & MF_PUSHABLE) + && g_tm.thing->z + g_tm.thing->height > thing->z && g_tm.thing->z < thing->z + thing->height + && !(netgame && g_tm.thing->player && g_tm.thing->player->spectator)) // Push thing! { if (thing->flags2 & MF2_SLIDEPUSH) // Make it slide { - if (tm.thing->momy > 0 && tm.thing->momy > FixedMul(4*FRACUNIT, thing->scale) && tm.thing->momy > thing->momy) + if (g_tm.thing->momy > 0 && g_tm.thing->momy > FixedMul(4*FRACUNIT, thing->scale) && g_tm.thing->momy > thing->momy) { thing->momy += FixedMul(PUSHACCEL, thing->scale); - tm.thing->momy -= FixedMul(PUSHACCEL, thing->scale); + g_tm.thing->momy -= FixedMul(PUSHACCEL, thing->scale); } - else if (tm.thing->momy < 0 && tm.thing->momy < FixedMul(-4*FRACUNIT, thing->scale) - && tm.thing->momy < thing->momy) + else if (g_tm.thing->momy < 0 && g_tm.thing->momy < FixedMul(-4*FRACUNIT, thing->scale) + && g_tm.thing->momy < thing->momy) { thing->momy -= FixedMul(PUSHACCEL, thing->scale); - tm.thing->momy += FixedMul(PUSHACCEL, thing->scale); + g_tm.thing->momy += FixedMul(PUSHACCEL, thing->scale); } - if (tm.thing->momx > 0 && tm.thing->momx > FixedMul(4*FRACUNIT, thing->scale) - && tm.thing->momx > thing->momx) + if (g_tm.thing->momx > 0 && g_tm.thing->momx > FixedMul(4*FRACUNIT, thing->scale) + && g_tm.thing->momx > thing->momx) { thing->momx += FixedMul(PUSHACCEL, thing->scale); - tm.thing->momx -= FixedMul(PUSHACCEL, thing->scale); + g_tm.thing->momx -= FixedMul(PUSHACCEL, thing->scale); } - else if (tm.thing->momx < 0 && tm.thing->momx < FixedMul(-4*FRACUNIT, thing->scale) - && tm.thing->momx < thing->momx) + else if (g_tm.thing->momx < 0 && g_tm.thing->momx < FixedMul(-4*FRACUNIT, thing->scale) + && g_tm.thing->momx < thing->momx) { thing->momx -= FixedMul(PUSHACCEL, thing->scale); - tm.thing->momx += FixedMul(PUSHACCEL, thing->scale); + g_tm.thing->momx += FixedMul(PUSHACCEL, thing->scale); } if (thing->momx > FixedMul(thing->info->speed, thing->scale)) @@ -985,88 +985,88 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } else { - if (tm.thing->momx > FixedMul(4*FRACUNIT, thing->scale)) - tm.thing->momx = FixedMul(4*FRACUNIT, thing->scale); - else if (tm.thing->momx < FixedMul(-4*FRACUNIT, thing->scale)) - tm.thing->momx = FixedMul(-4*FRACUNIT, thing->scale); - if (tm.thing->momy > FixedMul(4*FRACUNIT, thing->scale)) - tm.thing->momy = FixedMul(4*FRACUNIT, thing->scale); - else if (tm.thing->momy < FixedMul(-4*FRACUNIT, thing->scale)) - tm.thing->momy = FixedMul(-4*FRACUNIT, thing->scale); + if (g_tm.thing->momx > FixedMul(4*FRACUNIT, thing->scale)) + g_tm.thing->momx = FixedMul(4*FRACUNIT, thing->scale); + else if (g_tm.thing->momx < FixedMul(-4*FRACUNIT, thing->scale)) + g_tm.thing->momx = FixedMul(-4*FRACUNIT, thing->scale); + if (g_tm.thing->momy > FixedMul(4*FRACUNIT, thing->scale)) + g_tm.thing->momy = FixedMul(4*FRACUNIT, thing->scale); + else if (g_tm.thing->momy < FixedMul(-4*FRACUNIT, thing->scale)) + g_tm.thing->momy = FixedMul(-4*FRACUNIT, thing->scale); - thing->momx = tm.thing->momx; - thing->momy = tm.thing->momy; + thing->momx = g_tm.thing->momx; + thing->momy = g_tm.thing->momy; } if (thing->type != MT_GARGOYLE || P_IsObjectOnGround(thing)) S_StartSound(thing, thing->info->activesound); - P_SetTarget(&thing->target, tm.thing); + P_SetTarget(&thing->target, g_tm.thing); } // check for special pickup - if (thing->flags & MF_SPECIAL && tm.thing->player) + if (thing->flags & MF_SPECIAL && g_tm.thing->player) { - P_TouchSpecialThing(thing, tm.thing, true); // can remove thing + P_TouchSpecialThing(thing, g_tm.thing, true); // can remove thing return BMIT_CONTINUE; } // check again for special pickup - if (tm.thing->flags & MF_SPECIAL && thing->player) + if (g_tm.thing->flags & MF_SPECIAL && thing->player) { - P_TouchSpecialThing(tm.thing, thing, true); // can remove thing + P_TouchSpecialThing(g_tm.thing, thing, true); // can remove thing return BMIT_CONTINUE; } // Sprite Spikes! // Do not return because solidity code comes below. - if (tm.thing->type == MT_SPIKE && tm.thing->flags & MF_SOLID && thing->player) // moving spike rams into player?! + if (g_tm.thing->type == MT_SPIKE && g_tm.thing->flags & MF_SOLID && thing->player) // moving spike rams into player?! { - if (tm.thing->eflags & MFE_VERTICALFLIP) + if (g_tm.thing->eflags & MFE_VERTICALFLIP) { - if (thing->z + thing->height <= tm.thing->z + FixedMul(FRACUNIT, tm.thing->scale) - && thing->z + thing->height + thing->momz >= tm.thing->z + FixedMul(FRACUNIT, tm.thing->scale) + tm.thing->momz) - P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_NORMAL); + if (thing->z + thing->height <= g_tm.thing->z + FixedMul(FRACUNIT, g_tm.thing->scale) + && thing->z + thing->height + thing->momz >= g_tm.thing->z + FixedMul(FRACUNIT, g_tm.thing->scale) + g_tm.thing->momz) + P_DamageMobj(thing, g_tm.thing, g_tm.thing, 1, DMG_NORMAL); } - else if (thing->z >= tm.thing->z + tm.thing->height - FixedMul(FRACUNIT, tm.thing->scale) - && thing->z + thing->momz <= tm.thing->z + tm.thing->height - FixedMul(FRACUNIT, tm.thing->scale) + tm.thing->momz) - P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_NORMAL); + else if (thing->z >= g_tm.thing->z + g_tm.thing->height - FixedMul(FRACUNIT, g_tm.thing->scale) + && thing->z + thing->momz <= g_tm.thing->z + g_tm.thing->height - FixedMul(FRACUNIT, g_tm.thing->scale) + g_tm.thing->momz) + P_DamageMobj(thing, g_tm.thing, g_tm.thing, 1, DMG_NORMAL); } - else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tm.thing->player) // unfortunate player falls into spike?! + else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && g_tm.thing->player) // unfortunate player falls into spike?! { if (thing->eflags & MFE_VERTICALFLIP) { - if (tm.thing->z + tm.thing->height <= thing->z - FixedMul(FRACUNIT, thing->scale) - && tm.thing->z + tm.thing->height + tm.thing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)) - P_DamageMobj(tm.thing, thing, thing, 1, DMG_NORMAL); + if (g_tm.thing->z + g_tm.thing->height <= thing->z - FixedMul(FRACUNIT, thing->scale) + && g_tm.thing->z + g_tm.thing->height + g_tm.thing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)) + P_DamageMobj(g_tm.thing, thing, thing, 1, DMG_NORMAL); } - else if (tm.thing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) - && tm.thing->z + tm.thing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)) - P_DamageMobj(tm.thing, thing, thing, 1, DMG_NORMAL); + else if (g_tm.thing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) + && g_tm.thing->z + g_tm.thing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)) + P_DamageMobj(g_tm.thing, thing, thing, 1, DMG_NORMAL); } - if (tm.thing->type == MT_WALLSPIKE && tm.thing->flags & MF_SOLID && thing->player) // wall spike impales player + if (g_tm.thing->type == MT_WALLSPIKE && g_tm.thing->flags & MF_SOLID && thing->player) // wall spike impales player { fixed_t bottomz, topz; - bottomz = tm.thing->z; - topz = tm.thing->z + tm.thing->height; - if (tm.thing->eflags & MFE_VERTICALFLIP) - bottomz -= FixedMul(FRACUNIT, tm.thing->scale); + bottomz = g_tm.thing->z; + topz = g_tm.thing->z + g_tm.thing->height; + if (g_tm.thing->eflags & MFE_VERTICALFLIP) + bottomz -= FixedMul(FRACUNIT, g_tm.thing->scale); else - topz += FixedMul(FRACUNIT, tm.thing->scale); + topz += FixedMul(FRACUNIT, g_tm.thing->scale); if (thing->z + thing->height > bottomz // above bottom && thing->z < topz) // below top // don't check angle, the player was clearly in the way in this case - P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_NORMAL); + P_DamageMobj(thing, g_tm.thing, g_tm.thing, 1, DMG_NORMAL); } - else if (thing->type == MT_WALLSPIKE && thing->flags & MF_SOLID && tm.thing->player) + else if (thing->type == MT_WALLSPIKE && thing->flags & MF_SOLID && g_tm.thing->player) { fixed_t bottomz, topz; - angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tm.thing->x, tm.thing->y); + angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, g_tm.thing->x, g_tm.thing->y); - if (P_PlayerInPain(tm.thing->player) && (tm.thing->momx || tm.thing->momy)) + if (P_PlayerInPain(g_tm.thing->player) && (g_tm.thing->momx || g_tm.thing->momy)) { - angle_t playerangle = R_PointToAngle2(0, 0, tm.thing->momx, tm.thing->momy) - touchangle; + angle_t playerangle = R_PointToAngle2(0, 0, g_tm.thing->momx, g_tm.thing->momy) - touchangle; if (playerangle > ANGLE_180) playerangle = InvAngle(playerangle); if (playerangle < ANGLE_90) @@ -1081,111 +1081,111 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) else topz += FixedMul(FRACUNIT, thing->scale); - if (tm.thing->z + tm.thing->height > bottomz // above bottom - && tm.thing->z < topz // below top + if (g_tm.thing->z + g_tm.thing->height > bottomz // above bottom + && g_tm.thing->z < topz // below top && !P_MobjWasRemoved(thing->tracer)) // this probably wouldn't work if we didn't have a tracer { // use base as a reference point to determine what angle you touched the spike at touchangle = thing->angle - touchangle; if (touchangle > ANGLE_180) touchangle = InvAngle(touchangle); if (touchangle <= ANGLE_22h) // if you touched it at this close an angle, you get poked! - P_DamageMobj(tm.thing, thing, thing, 1, DMG_NORMAL); + P_DamageMobj(g_tm.thing, thing, thing, 1, DMG_NORMAL); } } if (thing->flags & MF_PUSHABLE) { - if (tm.thing->type == MT_FAN || tm.thing->type == MT_STEAM) - P_DoFanAndGasJet(tm.thing, thing); + if (g_tm.thing->type == MT_FAN || g_tm.thing->type == MT_STEAM) + P_DoFanAndGasJet(g_tm.thing, thing); } - if (tm.thing->flags & MF_PUSHABLE) + if (g_tm.thing->flags & MF_PUSHABLE) { if (thing->type == MT_FAN || thing->type == MT_STEAM) { - P_DoFanAndGasJet(thing, tm.thing); + P_DoFanAndGasJet(thing, g_tm.thing); return BMIT_CONTINUE; } else if (thing->flags & MF_SPRING) { - if ( thing->z <= tm.thing->z + tm.thing->height - && tm.thing->z <= thing->z + thing->height) - if (P_DoSpring(thing, tm.thing)) + if ( thing->z <= g_tm.thing->z + g_tm.thing->height + && g_tm.thing->z <= thing->z + thing->height) + if (P_DoSpring(thing, g_tm.thing)) return BMIT_ABORT; return BMIT_CONTINUE; } } // thanks to sal for solidenemies dot lua - if (thing->flags & (MF_ENEMY|MF_BOSS) && tm.thing->flags & (MF_ENEMY|MF_BOSS)) + if (thing->flags & (MF_ENEMY|MF_BOSS) && g_tm.thing->flags & (MF_ENEMY|MF_BOSS)) { - if ((thing->z + thing->height >= tm.thing->z) - && (tm.thing->z + tm.thing->height >= thing->z)) + if ((thing->z + thing->height >= g_tm.thing->z) + && (g_tm.thing->z + g_tm.thing->height >= thing->z)) return BMIT_ABORT; } if (thing->player) { - if (tm.thing->type == MT_FAN || tm.thing->type == MT_STEAM) - P_DoFanAndGasJet(tm.thing, thing); + if (g_tm.thing->type == MT_FAN || g_tm.thing->type == MT_STEAM) + P_DoFanAndGasJet(g_tm.thing, thing); } - if (tm.thing->player) // Is the moving/interacting object the player? + if (g_tm.thing->player) // Is the moving/interacting object the player? { - if (!tm.thing->health) + if (!g_tm.thing->health) return BMIT_CONTINUE; if (thing->type == MT_FAN || thing->type == MT_STEAM) - P_DoFanAndGasJet(thing, tm.thing); + P_DoFanAndGasJet(thing, g_tm.thing); else if (thing->flags & MF_SPRING) { - if ( thing->z <= tm.thing->z + tm.thing->height - && tm.thing->z <= thing->z + thing->height) - if (P_DoSpring(thing, tm.thing)) + if ( thing->z <= g_tm.thing->z + g_tm.thing->height + && g_tm.thing->z <= thing->z + thing->height) + if (P_DoSpring(thing, g_tm.thing)) return BMIT_ABORT; return BMIT_CONTINUE; } else if (thing->player) // bounce when players collide { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - if (thing->player->hyudorotimer || tm.thing->player->hyudorotimer) + if (thing->player->hyudorotimer || g_tm.thing->player->hyudorotimer) { return BMIT_CONTINUE; } if ((gametyperules & GTR_BUMPERS) - && ((thing->player->bumper && !tm.thing->player->bumper) - || (tm.thing->player->bumper && !thing->player->bumper))) + && ((thing->player->bumper && !g_tm.thing->player->bumper) + || (g_tm.thing->player->bumper && !thing->player->bumper))) { return BMIT_CONTINUE; } { // The bump has to happen last - mobj_t *mo1 = tm.thing; + mobj_t *mo1 = g_tm.thing; mobj_t *mo2 = thing; boolean zbounce = false; - if (P_IsObjectOnGround(thing) && tm.thing->momz < 0) + if (P_IsObjectOnGround(thing) && g_tm.thing->momz < 0) { zbounce = true; mo1 = thing; - mo2 = tm.thing; + mo2 = g_tm.thing; - if (tm.thing->player->pogospring) - P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_WIPEOUT|DMG_STEAL); + if (g_tm.thing->player->pogospring) + P_DamageMobj(thing, g_tm.thing, g_tm.thing, 1, DMG_WIPEOUT|DMG_STEAL); } - else if (P_IsObjectOnGround(tm.thing) && thing->momz < 0) + else if (P_IsObjectOnGround(g_tm.thing) && thing->momz < 0) { zbounce = true; if (thing->player->pogospring) - P_DamageMobj(tm.thing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL); + P_DamageMobj(g_tm.thing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL); } if (K_KartBouncing(mo1, mo2, zbounce, false)) @@ -1199,48 +1199,48 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) else if (thing->type == MT_BLUEROBRA_HEAD || thing->type == MT_BLUEROBRA_JOINT) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath if (!thing->health) return BMIT_CONTINUE; // dead - if (tm.thing->player->invincibilitytimer > 0 - || tm.thing->player->growshrinktimer > 0) + if (g_tm.thing->player->invincibilitytimer > 0 + || g_tm.thing->player->growshrinktimer > 0) { if (thing->type == MT_BLUEROBRA_JOINT) - P_KillMobj(thing->target, tm.thing, tm.thing, DMG_NORMAL); + P_KillMobj(thing->target, g_tm.thing, g_tm.thing, DMG_NORMAL); else - P_KillMobj(thing, tm.thing, tm.thing, DMG_NORMAL); + P_KillMobj(thing, g_tm.thing, g_tm.thing, DMG_NORMAL); return BMIT_CONTINUE; } else { - K_KartBouncing(tm.thing, thing, false, true); + K_KartBouncing(g_tm.thing, thing, false, true); return BMIT_CONTINUE; } } else if (thing->type == MT_SMK_PIPE) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath if (!thing->health) return BMIT_CONTINUE; // dead - if (tm.thing->player->invincibilitytimer > 0 - || tm.thing->player->growshrinktimer > 0) + if (g_tm.thing->player->invincibilitytimer > 0 + || g_tm.thing->player->growshrinktimer > 0) { - P_KillMobj(thing, tm.thing, tm.thing, DMG_NORMAL); + P_KillMobj(thing, g_tm.thing, g_tm.thing, DMG_NORMAL); return BMIT_CONTINUE; // kill } - K_KartBouncing(tm.thing, thing, false, true); + K_KartBouncing(g_tm.thing, thing, false, true); return BMIT_CONTINUE; } else if (thing->type == MT_SMK_THWOMP) @@ -1251,38 +1251,38 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (!thwompsactive) return BMIT_CONTINUE; // not active yet - if ((tm.thing->z < thing->z) && (thing->z >= thing->movefactor-(256<z < thing->z) && (thing->z >= thing->movefactor-(256<extravalue1 = 1; // purposely try to stomp on players early //S_StartSound(thing, sfx_s1bb); } // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath // kill - if (tm.thing->player->invincibilitytimer > 0 - || tm.thing->player->growshrinktimer > 0) + if (g_tm.thing->player->invincibilitytimer > 0 + || g_tm.thing->player->growshrinktimer > 0) { - P_KillMobj(thing, tm.thing, tm.thing, DMG_NORMAL); + P_KillMobj(thing, g_tm.thing, g_tm.thing, DMG_NORMAL); return BMIT_CONTINUE; } // no interaction - if (tm.thing->player->flashing > 0 || tm.thing->player->hyudorotimer > 0 || tm.thing->player->spinouttimer > 0) + if (g_tm.thing->player->flashing > 0 || g_tm.thing->player->hyudorotimer > 0 || g_tm.thing->player->spinouttimer > 0) return BMIT_CONTINUE; // collide - if (tm.thing->z < thing->z && thing->momz < 0) - P_DamageMobj(tm.thing, thing, thing, 1, DMG_SQUISH); + if (g_tm.thing->z < thing->z && thing->momz < 0) + P_DamageMobj(g_tm.thing, thing, thing, 1, DMG_SQUISH); else { if (thing->flags2 & MF2_AMBUSH) - P_DamageMobj(tm.thing, thing, thing, 1, DMG_WIPEOUT); - K_KartBouncing(tm.thing, thing, false, true); + P_DamageMobj(g_tm.thing, thing, thing, 1, DMG_WIPEOUT); + K_KartBouncing(g_tm.thing, thing, false, true); } return BMIT_CONTINUE; @@ -1290,57 +1290,57 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) else if (thing->type == MT_KART_LEFTOVER) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - if (P_IsObjectOnGround(thing) && tm.thing->momz < 0) - K_KartBouncing(tm.thing, thing, true, false); + if (P_IsObjectOnGround(thing) && g_tm.thing->momz < 0) + K_KartBouncing(g_tm.thing, thing, true, false); else - K_KartBouncing(tm.thing, thing, false, false); + K_KartBouncing(g_tm.thing, thing, false, false); return BMIT_CONTINUE; } else if (thing->flags & MF_SOLID) { // see if it went over / under - if (tm.thing->z > thing->z + thing->height) + if (g_tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tm.thing->z + tm.thing->height < thing->z) + if (g_tm.thing->z + g_tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - if (P_IsObjectOnGround(thing) && tm.thing->momz < 0) - K_KartBouncing(tm.thing, thing, true, true); + if (P_IsObjectOnGround(thing) && g_tm.thing->momz < 0) + K_KartBouncing(g_tm.thing, thing, true, true); else - K_KartBouncing(tm.thing, thing, false, true); + K_KartBouncing(g_tm.thing, thing, false, true); return BMIT_CONTINUE; } } #if 0 - if ((tm.thing->flags & MF_SPRING || tm.thing->type == MT_STEAM || tm.thing->type == MT_SPIKE || tm.thing->type == MT_WALLSPIKE) && (thing->player)) + if ((g_tm.thing->flags & MF_SPRING || g_tm.thing->type == MT_STEAM || g_tm.thing->type == MT_SPIKE || g_tm.thing->type == MT_WALLSPIKE) && (thing->player)) ; // springs, gas jets and springs should never be able to step up onto a player // z checking at last // Treat noclip things as non-solid! else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID - && (tm.thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID) + && (g_tm.thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID) { fixed_t topz, tmtopz; - if (tm.thing->eflags & MFE_VERTICALFLIP) + if (g_tm.thing->eflags & MFE_VERTICALFLIP) { // pass under - tmtopz = tm.thing->z; + tmtopz = g_tm.thing->z; if (tmtopz > thing->z + thing->height) { - if (thing->z + thing->height > tm.floorz) + if (thing->z + thing->height > g_tm.floorz) { - tm.floorz = thing->z + thing->height; - tm.floorrover = NULL; - tm.floorslope = NULL; - tm.floorpic = -1; + g_tm.floorz = thing->z + thing->height; + g_tm.floorrover = NULL; + g_tm.floorslope = NULL; + g_tm.floorpic = -1; } return BMIT_CONTINUE; } @@ -1351,40 +1351,40 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) // (dont climb max. 24units while already in air) // since return false doesn't handle momentum properly, // we lie to P_TryMove() so it's always too high - if (tm.thing->player && tm.thing->z + tm.thing->height > topz - && tm.thing->z + tm.thing->height < tm.thing->ceilingz) + if (g_tm.thing->player && g_tm.thing->z + g_tm.thing->height > topz + && g_tm.thing->z + g_tm.thing->height < g_tm.thing->ceilingz) { if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->info->flags & MF_MONITOR)) // Gold monitor hack... return BMIT_ABORT; - tm.floorz = tm.ceilingz = topz; // block while in air - tm.ceilingrover = NULL; - tm.ceilingslope = NULL; - tm.ceilingpic = -1; - P_SetTarget(&tm.floorthing, thing); // needed for side collision + g_tm.floorz = g_tm.ceilingz = topz; // block while in air + g_tm.ceilingrover = NULL; + g_tm.ceilingslope = NULL; + g_tm.ceilingpic = -1; + P_SetTarget(&g_tm.floorthing, thing); // needed for side collision } - else if (topz < tm.ceilingz && tm.thing->z <= thing->z+thing->height) + else if (topz < g_tm.ceilingz && g_tm.thing->z <= thing->z+thing->height) { - tm.ceilingz = topz; - tm.ceilingrover = NULL; - tm.ceilingslope = NULL; - tm.ceilingpic = -1; - P_SetTarget(&tm.floorthing, thing); // thing we may stand on + g_tm.ceilingz = topz; + g_tm.ceilingrover = NULL; + g_tm.ceilingslope = NULL; + g_tm.ceilingpic = -1; + P_SetTarget(&g_tm.floorthing, thing); // thing we may stand on } } else { // pass under - tmtopz = tm.thing->z + tm.thing->height; + tmtopz = g_tm.thing->z + g_tm.thing->height; if (tmtopz < thing->z) { - if (thing->z < tm.ceilingz) + if (thing->z < g_tm.ceilingz) { - tm.ceilingz = thing->z; - tm.ceilingrover = NULL; - tm.ceilingslope = NULL; - tm.ceilingpic = -1; + g_tm.ceilingz = thing->z; + g_tm.ceilingrover = NULL; + g_tm.ceilingslope = NULL; + g_tm.ceilingpic = -1; } return BMIT_CONTINUE; } @@ -1395,25 +1395,25 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) // (dont climb max. 24units while already in air) // since return false doesn't handle momentum properly, // we lie to P_TryMove() so it's always too high - if (tm.thing->player && tm.thing->z < topz - && tm.thing->z > tm.thing->floorz) + if (g_tm.thing->player && g_tm.thing->z < topz + && g_tm.thing->z > g_tm.thing->floorz) { if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->info->flags & MF_MONITOR)) // Gold monitor hack... return BMIT_ABORT; - tm.floorz = tm.ceilingz = topz; // block while in air - tm.floorrover = NULL; - tm.floorslope = NULL; - tm.floorpic = -1; - P_SetTarget(&tm.floorthing, thing); // needed for side collision + g_tm.floorz = g_tm.ceilingz = topz; // block while in air + g_tm.floorrover = NULL; + g_tm.floorslope = NULL; + g_tm.floorpic = -1; + P_SetTarget(&g_tm.floorthing, thing); // needed for side collision } - else if (topz > tm.floorz && tm.thing->z+tm.thing->height >= thing->z) + else if (topz > g_tm.floorz && g_tm.thing->z+g_tm.thing->height >= thing->z) { - tm.floorz = topz; - tm.floorrover = NULL; - tm.floorslope = NULL; - tm.floorpic = -1; - P_SetTarget(&tm.floorthing, thing); // thing we may stand on + g_tm.floorz = topz; + g_tm.floorrover = NULL; + g_tm.floorslope = NULL; + g_tm.floorpic = -1; + P_SetTarget(&g_tm.floorthing, thing); // thing we may stand on } } } @@ -1423,7 +1423,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // PIT_CheckCameraLine -// Adjusts tm.floorz and tm.ceilingz as lines are contacted - FOR CAMERA ONLY +// Adjusts g_tm.floorz and g_tm.ceilingz as lines are contacted - FOR CAMERA ONLY static BlockItReturn_t PIT_CheckCameraLine(line_t *ld) { opening_t open = {0}; @@ -1431,13 +1431,13 @@ static BlockItReturn_t PIT_CheckCameraLine(line_t *ld) if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID)) return BMIT_CONTINUE; - if (tm.bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || tm.bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tm.bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || tm.bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + if (g_tm.bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || g_tm.bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] + || g_tm.bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || g_tm.bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) { return BMIT_CONTINUE; } - if (P_BoxOnLineSide(tm.bbox, ld) != -1) + if (P_BoxOnLineSide(g_tm.bbox, ld) != -1) return BMIT_CONTINUE; // A line has been hit @@ -1463,22 +1463,22 @@ static BlockItReturn_t PIT_CheckCameraLine(line_t *ld) P_CameraLineOpening(ld, &open); // adjust floor / ceiling heights - if (open.ceiling < tm.ceilingz) + if (open.ceiling < g_tm.ceilingz) { - tm.ceilingz = open.ceiling; - tm.ceilingline = ld; + g_tm.ceilingz = open.ceiling; + g_tm.ceilingline = ld; } - if (open.floor > tm.floorz) + if (open.floor > g_tm.floorz) { - tm.floorz = open.floor; + g_tm.floorz = open.floor; } - if (open.highceiling > tm.drpoffceilz) - tm.drpoffceilz = open.highceiling; + if (open.highceiling > g_tm.drpoffceilz) + g_tm.drpoffceilz = open.highceiling; - if (open.lowfloor < tm.dropoffz) - tm.dropoffz = open.lowfloor; + if (open.lowfloor < g_tm.dropoffz) + g_tm.dropoffz = open.lowfloor; return BMIT_CONTINUE; } @@ -1540,45 +1540,45 @@ static boolean P_UsingStepUp(mobj_t *thing) // // PIT_CheckLine -// Adjusts tm.floorz and tm.ceilingz as lines are contacted +// Adjusts g_tm.floorz and g_tm.ceilingz as lines are contacted // static BlockItReturn_t PIT_CheckLine(line_t *ld) { - const fixed_t thingtop = tm.thing->z + tm.thing->height; + const fixed_t thingtop = g_tm.thing->z + g_tm.thing->height; opening_t open = {0}; if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID)) return BMIT_CONTINUE; - if (tm.bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || tm.bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tm.bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || tm.bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + if (g_tm.bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || g_tm.bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] + || g_tm.bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || g_tm.bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) return BMIT_CONTINUE; - if (P_BoxOnLineSide(tm.bbox, ld) != -1) + if (P_BoxOnLineSide(g_tm.bbox, ld) != -1) return BMIT_CONTINUE; - if (tm.thing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag. + if (g_tm.thing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag. { fixed_t cosradius, sinradius; - cosradius = FixedMul(tm.thing->radius, FINECOSINE(tm.thing->angle>>ANGLETOFINESHIFT)); - sinradius = FixedMul(tm.thing->radius, FINESINE(tm.thing->angle>>ANGLETOFINESHIFT)); - if (P_PointOnLineSide(tm.x - cosradius, tm.y - sinradius, ld) - == P_PointOnLineSide(tm.x + cosradius, tm.y + sinradius, ld)) + cosradius = FixedMul(g_tm.thing->radius, FINECOSINE(g_tm.thing->angle>>ANGLETOFINESHIFT)); + sinradius = FixedMul(g_tm.thing->radius, FINESINE(g_tm.thing->angle>>ANGLETOFINESHIFT)); + if (P_PointOnLineSide(g_tm.x - cosradius, g_tm.y - sinradius, ld) + == P_PointOnLineSide(g_tm.x + cosradius, g_tm.y + sinradius, ld)) return BMIT_CONTINUE; // the line doesn't cross between collider's start or end #ifdef PAPER_COLLISIONCORRECTION { fixed_t dist; vertex_t result; angle_t langle; - P_ClosestPointOnLine(tm.x, tm.y, ld, &result); + P_ClosestPointOnLine(g_tm.x, g_tm.y, ld, &result); langle = R_PointToAngle2(ld->v1->x, ld->v1->y, ld->v2->x, ld->v2->y); - langle += ANGLE_90*(P_PointOnLineSide(tm.x, tm.y, ld) ? -1 : 1); - dist = abs(FixedMul(tm.thing->radius, FINECOSINE((tm.thing->angle - langle)>>ANGLETOFINESHIFT))); + langle += ANGLE_90*(P_PointOnLineSide(g_tm.x, g_tm.y, ld) ? -1 : 1); + dist = abs(FixedMul(g_tm.thing->radius, FINECOSINE((g_tm.thing->angle - langle)>>ANGLETOFINESHIFT))); cosradius = FixedMul(dist, FINECOSINE(langle>>ANGLETOFINESHIFT)); sinradius = FixedMul(dist, FINESINE(langle>>ANGLETOFINESHIFT)); - tm.thing->flags |= MF_NOCLIP; - P_MoveOrigin(tm.thing, result.x + cosradius - tm.thing->momx, result.y + sinradius - tm.thing->momy, tm.thing->z); - tm.thing->flags &= ~MF_NOCLIP; + g_tm.thing->flags |= MF_NOCLIP; + P_MoveOrigin(g_tm.thing, result.x + cosradius - g_tm.thing->momx, result.y + sinradius - g_tm.thing->momy, g_tm.thing->z); + g_tm.thing->flags &= ~MF_NOCLIP; } #endif } @@ -1597,16 +1597,16 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) // this line is out of the if so upper and lower textures can be hit by a splat { - UINT8 shouldCollide = LUA_HookMobjLineCollide(tm.thing, ld); // checks hook for thing's type - if (P_MobjWasRemoved(tm.thing)) + UINT8 shouldCollide = LUA_HookMobjLineCollide(g_tm.thing, ld); // checks hook for thing's type + if (P_MobjWasRemoved(g_tm.thing)) return BMIT_CONTINUE; // one of them was removed??? if (shouldCollide == 1) { - if (tm.sweep) + if (g_tm.sweep) { P_TestLine(ld); } - tm.blocking = true; // force collide + g_tm.blocking = true; // force collide return BMIT_CONTINUE; } else if (shouldCollide == 2) @@ -1615,50 +1615,50 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) if (!ld->backsector) // one sided line { - if (P_PointOnLineSide(tm.thing->x, tm.thing->y, ld)) + if (P_PointOnLineSide(g_tm.thing->x, g_tm.thing->y, ld)) return BMIT_CONTINUE; // don't hit the back side - if (tm.sweep) + if (g_tm.sweep) { P_TestLine(ld); } - tm.blocking = true; + g_tm.blocking = true; return BMIT_CONTINUE; } - if (P_IsLineBlocking(ld, tm.thing)) + if (P_IsLineBlocking(ld, g_tm.thing)) { - if (tm.sweep) + if (g_tm.sweep) { P_TestLine(ld); } - tm.blocking = true; + g_tm.blocking = true; return BMIT_CONTINUE; } // set openrange, opentop, openbottom - P_LineOpening(ld, tm.thing, &open); + P_LineOpening(ld, g_tm.thing, &open); - if (tm.sweep && P_UsingStepUp(tm.thing)) + if (g_tm.sweep && P_UsingStepUp(g_tm.thing)) { // copied from P_TryMove // TODO: refactor this into one place - if (open.range < tm.thing->height) + if (open.range < g_tm.thing->height) { P_TestLine(ld); } - else if (tm.maxstep > 0) + else if (g_tm.maxstep > 0) { - if (tm.thing->z < open.floor) + if (g_tm.thing->z < open.floor) { - if (open.floorstep > tm.maxstep) + if (open.floorstep > g_tm.maxstep) { P_TestLine(ld); } } - else if (open.ceiling < tm.thing->z + tm.thing->height) + else if (open.ceiling < g_tm.thing->z + g_tm.thing->height) { - if (open.ceilingstep > tm.maxstep) + if (open.ceilingstep > g_tm.maxstep) { P_TestLine(ld); } @@ -1667,38 +1667,38 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) } // adjust floor / ceiling heights - if (open.ceiling < tm.ceilingz) + if (open.ceiling < g_tm.ceilingz) { - tm.ceilingz = open.ceiling; - tm.ceilingline = ld; - tm.ceilingrover = open.ceilingrover; - tm.ceilingslope = open.ceilingslope; - tm.ceilingpic = open.ceilingpic; - tm.ceilingstep = open.ceilingstep; - if (thingtop == tm.thing->ceilingz) + g_tm.ceilingz = open.ceiling; + g_tm.ceilingline = ld; + g_tm.ceilingrover = open.ceilingrover; + g_tm.ceilingslope = open.ceilingslope; + g_tm.ceilingpic = open.ceilingpic; + g_tm.ceilingstep = open.ceilingstep; + if (thingtop == g_tm.thing->ceilingz) { - tm.thing->ceilingdrop = open.ceilingdrop; + g_tm.thing->ceilingdrop = open.ceilingdrop; } } - if (open.floor > tm.floorz) + if (open.floor > g_tm.floorz) { - tm.floorz = open.floor; - tm.floorrover = open.floorrover; - tm.floorslope = open.floorslope; - tm.floorpic = open.floorpic; - tm.floorstep = open.floorstep; - if (tm.thing->z == tm.thing->floorz) + g_tm.floorz = open.floor; + g_tm.floorrover = open.floorrover; + g_tm.floorslope = open.floorslope; + g_tm.floorpic = open.floorpic; + g_tm.floorstep = open.floorstep; + if (g_tm.thing->z == g_tm.thing->floorz) { - tm.thing->floordrop = open.floordrop; + g_tm.thing->floordrop = open.floordrop; } } - if (open.highceiling > tm.drpoffceilz) - tm.drpoffceilz = open.highceiling; + if (open.highceiling > g_tm.drpoffceilz) + g_tm.drpoffceilz = open.highceiling; - if (open.lowfloor < tm.dropoffz) - tm.dropoffz = open.lowfloor; + if (open.lowfloor < g_tm.dropoffz) + g_tm.dropoffz = open.lowfloor; // we've crossed the line if (P_SpecialIsLinedefCrossType(ld)) @@ -1716,7 +1716,7 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) know the height values anymore. So don't even add this line to the list unless this thing clips the tripwire's midtexture. */ - if (tm.thing->z <= textop && thingtop >= texbottom) + if (g_tm.thing->z <= textop && thingtop >= texbottom) add_spechit(ld); } @@ -1743,20 +1743,20 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) // // out: // newsubsec -// tm.floorz -// tm.ceilingz -// tm.dropoffz -// tm.drpoffceilz +// g_tm.floorz +// g_tm.ceilingz +// g_tm.dropoffz +// g_tm.drpoffceilz // the lowest point contacted // (monsters won't move to a dropoff) // speciallines[] // numspeciallines // -// tm.floorz -// the nearest floor or thing's top under tm.thing -// tm.ceilingz -// the nearest ceiling or thing's bottom over tm.thing +// g_tm.floorz +// the nearest floor or thing's top under g_tm.thing +// g_tm.ceilingz +// the nearest ceiling or thing's bottom over g_tm.thing // static const fixed_t hoopblockdist = 16*FRACUNIT + 8*FRACUNIT; @@ -1777,36 +1777,36 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re I_Error("Previously-removed Thing of type %u crashes P_CheckPosition!", thing->type); #endif - P_SetTarget(&tm.thing, thing); - tm.flags = thing->flags; + P_SetTarget(&g_tm.thing, thing); + g_tm.flags = thing->flags; - tm.x = x; - tm.y = y; + g_tm.x = x; + g_tm.y = y; - tm.bbox[BOXTOP] = y + tm.thing->radius; - tm.bbox[BOXBOTTOM] = y - tm.thing->radius; - tm.bbox[BOXRIGHT] = x + tm.thing->radius; - tm.bbox[BOXLEFT] = x - tm.thing->radius; + g_tm.bbox[BOXTOP] = y + g_tm.thing->radius; + g_tm.bbox[BOXBOTTOM] = y - g_tm.thing->radius; + g_tm.bbox[BOXRIGHT] = x + g_tm.thing->radius; + g_tm.bbox[BOXLEFT] = x - g_tm.thing->radius; newsubsec = R_PointInSubsector(x, y); - tm.ceilingline = NULL; - tm.blocking = false; + g_tm.ceilingline = NULL; + g_tm.blocking = false; // The base floor / ceiling is from the subsector // that contains the point. // Any contacted lines the step closer together // will adjust them. - tm.floorz = tm.dropoffz = P_GetFloorZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->floorheight; - tm.ceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; - tm.floorrover = NULL; - tm.ceilingrover = NULL; - tm.floorslope = newsubsec->sector->f_slope; - tm.ceilingslope = newsubsec->sector->c_slope; - tm.floorpic = newsubsec->sector->floorpic; - tm.ceilingpic = newsubsec->sector->ceilingpic; + g_tm.floorz = g_tm.dropoffz = P_GetFloorZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->floorheight; + g_tm.ceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; + g_tm.floorrover = NULL; + g_tm.ceilingrover = NULL; + g_tm.floorslope = newsubsec->sector->f_slope; + g_tm.ceilingslope = newsubsec->sector->c_slope; + g_tm.floorpic = newsubsec->sector->floorpic; + g_tm.ceilingpic = newsubsec->sector->ceilingpic; - tm.floorstep = 0; - tm.ceilingstep = 0; + g_tm.floorstep = 0; + g_tm.ceilingstep = 0; if (thingtop < thing->ceilingz) { @@ -1818,7 +1818,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re thing->floordrop = 0; } - // Check list of fake floors and see if tm.floorz/tm.ceilingz need to be altered. + // Check list of fake floors and see if g_tm.floorz/g_tm.ceilingz need to be altered. if (newsubsec->sector->ffloors) { ffloor_t *rover; @@ -1853,22 +1853,22 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re // Land on the top or the bottom, depending on gravity flip. if (!(thing->eflags & MFE_VERTICALFLIP) && thing->z >= topheight - sinklevel && thing->momz <= 0) { - if (tm.floorz < topheight - sinklevel) + if (g_tm.floorz < topheight - sinklevel) { - tm.floorz = topheight - sinklevel; - tm.floorrover = rover; - tm.floorslope = *rover->t_slope; - tm.floorpic = *rover->toppic; + g_tm.floorz = topheight - sinklevel; + g_tm.floorrover = rover; + g_tm.floorslope = *rover->t_slope; + g_tm.floorpic = *rover->toppic; } } else if (thing->eflags & MFE_VERTICALFLIP && thingtop <= bottomheight + sinklevel && thing->momz >= 0) { - if (tm.ceilingz > bottomheight + sinklevel) + if (g_tm.ceilingz > bottomheight + sinklevel) { - tm.ceilingz = bottomheight + sinklevel; - tm.ceilingrover = rover; - tm.ceilingslope = *rover->b_slope; - tm.ceilingpic = *rover->bottompic; + g_tm.ceilingz = bottomheight + sinklevel; + g_tm.ceilingrover = rover; + g_tm.ceilingslope = *rover->b_slope; + g_tm.ceilingpic = *rover->bottompic; } } } @@ -1888,12 +1888,12 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re { if (thing->z < topheight && bottomheight < thingtop) { - if (tm.floorz < thing->z) + if (g_tm.floorz < thing->z) { - tm.floorz = thing->z; - tm.floorrover = rover; - tm.floorslope = NULL; - tm.floorpic = *rover->toppic; + g_tm.floorz = thing->z; + g_tm.floorrover = rover; + g_tm.floorslope = NULL; + g_tm.floorpic = *rover->toppic; } } // Quicksand blocks never change heights otherwise. @@ -1905,23 +1905,23 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); - if (topheight > tm.floorz && abs(delta1) < abs(delta2) + if (topheight > g_tm.floorz && abs(delta1) < abs(delta2) && !(rover->fofflags & FOF_REVERSEPLATFORM)) { - tm.floorz = tm.dropoffz = topheight; - tm.floorrover = rover; - tm.floorslope = *rover->t_slope; - tm.floorpic = *rover->toppic; + g_tm.floorz = g_tm.dropoffz = topheight; + g_tm.floorrover = rover; + g_tm.floorslope = *rover->t_slope; + g_tm.floorpic = *rover->toppic; } - if (bottomheight < tm.ceilingz && abs(delta1) >= abs(delta2) + if (bottomheight < g_tm.ceilingz && abs(delta1) >= abs(delta2) && !(rover->fofflags & FOF_PLATFORM) && !(thing->type == MT_SKIM && (rover->fofflags & FOF_SWIMMABLE))) { - tm.ceilingz = tm.drpoffceilz = bottomheight; - tm.ceilingrover = rover; - tm.ceilingslope = *rover->b_slope; - tm.ceilingpic = *rover->bottompic; + g_tm.ceilingz = g_tm.drpoffceilz = bottomheight; + g_tm.ceilingrover = rover; + g_tm.ceilingslope = *rover->b_slope; + g_tm.ceilingpic = *rover->bottompic; } } } @@ -1933,14 +1933,14 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re // based on their origin point, and can overlap // into adjacent blocks by up to MAXRADIUS units. - xl = (unsigned)(tm.bbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (unsigned)(tm.bbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (unsigned)(tm.bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (unsigned)(tm.bbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + xl = (unsigned)(g_tm.bbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (unsigned)(g_tm.bbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (unsigned)(g_tm.bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (unsigned)(g_tm.bbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); - // Check polyobjects and see if tm.floorz/tm.ceilingz need to be altered + // Check polyobjects and see if g_tm.floorz/g_tm.ceilingz need to be altered { validcount++; @@ -1971,7 +1971,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re po->validcount = validcount; - if (!P_BBoxInsidePolyobj(po, tm.bbox) + if (!P_BBoxInsidePolyobj(po, g_tm.bbox) || !(po->flags & POF_SOLID)) { plink = (polymaplink_t *)(plink->link.next); @@ -1995,20 +1995,20 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re delta1 = thing->z - (polybottom + ((polytop - polybottom)/2)); delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); - if (polytop > tm.floorz && abs(delta1) < abs(delta2)) + if (polytop > g_tm.floorz && abs(delta1) < abs(delta2)) { - tm.floorz = tm.dropoffz = polytop; - tm.floorslope = NULL; - tm.floorrover = NULL; - tm.floorpic = polysec->ceilingpic; + g_tm.floorz = g_tm.dropoffz = polytop; + g_tm.floorslope = NULL; + g_tm.floorrover = NULL; + g_tm.floorpic = polysec->ceilingpic; } - if (polybottom < tm.ceilingz && abs(delta1) >= abs(delta2)) + if (polybottom < g_tm.ceilingz && abs(delta1) >= abs(delta2)) { - tm.ceilingz = tm.drpoffceilz = polybottom; - tm.ceilingslope = NULL; - tm.ceilingrover = NULL; - tm.ceilingpic = polysec->floorpic; + g_tm.ceilingz = g_tm.drpoffceilz = polybottom; + g_tm.ceilingslope = NULL; + g_tm.ceilingrover = NULL; + g_tm.ceilingpic = polysec->floorpic; } } plink = (polymaplink_t *)(plink->link.next); @@ -2017,9 +2017,9 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re } } - // tm.floorthing is set when tm.floorz comes from a thing's top - P_SetTarget(&tm.floorthing, NULL); - P_SetTarget(&tm.hitthing, NULL); + // g_tm.floorthing is set when g_tm.floorz comes from a thing's top + P_SetTarget(&g_tm.floorthing, NULL); + P_SetTarget(&g_tm.hitthing, NULL); validcount++; @@ -2042,10 +2042,10 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re } else { - P_SetTarget(&tm.hitthing, tm.floorthing); + P_SetTarget(&g_tm.hitthing, g_tm.floorthing); } - if (P_MobjWasRemoved(tm.thing)) + if (P_MobjWasRemoved(g_tm.thing)) { return false; } @@ -2053,7 +2053,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re } } - if (tm.flags & MF_NOCLIP) + if (g_tm.flags & MF_NOCLIP) { // Sal 12/19/2022 -- PIT_CheckThing code will still run // with MF_NOCLIP enabled, but they won't be blocked @@ -2074,7 +2074,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re } } - if (tm.blocking) + if (g_tm.blocking) { blockval = false; } @@ -2082,14 +2082,14 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re if (result != NULL) { result->line = NULL; - result->mo = tm.hitthing; + result->mo = g_tm.hitthing; } else { P_ClearTestLines(); } - tm.sweep = false; + g_tm.sweep = false; return blockval; } @@ -2126,23 +2126,23 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) INT32 xl, xh, yl, yh, bx, by; subsector_t *newsubsec; - tm.x = x; - tm.y = y; + g_tm.x = x; + g_tm.y = y; - tm.bbox[BOXTOP] = y + thiscam->radius; - tm.bbox[BOXBOTTOM] = y - thiscam->radius; - tm.bbox[BOXRIGHT] = x + thiscam->radius; - tm.bbox[BOXLEFT] = x - thiscam->radius; + g_tm.bbox[BOXTOP] = y + thiscam->radius; + g_tm.bbox[BOXBOTTOM] = y - thiscam->radius; + g_tm.bbox[BOXRIGHT] = x + thiscam->radius; + g_tm.bbox[BOXLEFT] = x - thiscam->radius; newsubsec = R_PointInSubsector(x, y); - tm.ceilingline = NULL; + g_tm.ceilingline = NULL; mapcampointer = thiscam; if (newsubsec->sector->flags & MSF_NOCLIPCAMERA) { // Camera noclip on entire sector. - tm.floorz = tm.dropoffz = thiscam->z; - tm.ceilingz = tm.drpoffceilz = thiscam->z + thiscam->height; + g_tm.floorz = g_tm.dropoffz = thiscam->z; + g_tm.ceilingz = g_tm.drpoffceilz = thiscam->z + thiscam->height; return true; } @@ -2150,26 +2150,26 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) // that contains the point. // Any contacted lines the step closer together // will adjust them. - tm.floorz = tm.dropoffz = P_CameraGetFloorZ(thiscam, newsubsec->sector, x, y, NULL); + g_tm.floorz = g_tm.dropoffz = P_CameraGetFloorZ(thiscam, newsubsec->sector, x, y, NULL); - tm.ceilingz = P_CameraGetCeilingZ(thiscam, newsubsec->sector, x, y, NULL); + g_tm.ceilingz = P_CameraGetCeilingZ(thiscam, newsubsec->sector, x, y, NULL); // Cameras use the heightsec's heights rather then the actual sector heights. // If you can see through it, why not move the camera through it too? if (newsubsec->sector->heightsec >= 0) { - tm.floorz = tm.dropoffz = sectors[newsubsec->sector->heightsec].floorheight; - tm.ceilingz = tm.drpoffceilz = sectors[newsubsec->sector->heightsec].ceilingheight; + g_tm.floorz = g_tm.dropoffz = sectors[newsubsec->sector->heightsec].floorheight; + g_tm.ceilingz = g_tm.drpoffceilz = sectors[newsubsec->sector->heightsec].ceilingheight; } // Use preset camera clipping heights if set with Sector Special Parameters whose control sector has Camera Intangible special -Red if (newsubsec->sector->camsec >= 0) { - tm.floorz = tm.dropoffz = sectors[newsubsec->sector->camsec].floorheight; - tm.ceilingz = tm.drpoffceilz = sectors[newsubsec->sector->camsec].ceilingheight; + g_tm.floorz = g_tm.dropoffz = sectors[newsubsec->sector->camsec].floorheight; + g_tm.ceilingz = g_tm.drpoffceilz = sectors[newsubsec->sector->camsec].ceilingheight; } - // Check list of fake floors and see if tm.floorz/tm.ceilingz need to be altered. + // Check list of fake floors and see if g_tm.floorz/g_tm.ceilingz need to be altered. if (newsubsec->sector->ffloors) { ffloor_t *rover; @@ -2189,13 +2189,13 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) + ((topheight - bottomheight)/2)); delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); - if (topheight > tm.floorz && abs(delta1) < abs(delta2)) + if (topheight > g_tm.floorz && abs(delta1) < abs(delta2)) { - tm.floorz = tm.dropoffz = topheight; + g_tm.floorz = g_tm.dropoffz = topheight; } - if (bottomheight < tm.ceilingz && abs(delta1) >= abs(delta2)) + if (bottomheight < g_tm.ceilingz && abs(delta1) >= abs(delta2)) { - tm.ceilingz = tm.drpoffceilz = bottomheight; + g_tm.ceilingz = g_tm.drpoffceilz = bottomheight; } } } @@ -2205,14 +2205,14 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) // based on their origin point, and can overlap // into adjacent blocks by up to MAXRADIUS units. - xl = (unsigned)(tm.bbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(tm.bbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(tm.bbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(tm.bbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(g_tm.bbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(g_tm.bbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(g_tm.bbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(g_tm.bbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); - // Check polyobjects and see if tm.floorz/tm.ceilingz need to be altered + // Check polyobjects and see if g_tm.floorz/g_tm.ceilingz need to be altered { validcount++; @@ -2272,11 +2272,11 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) delta1 = thiscam->z - (polybottom + ((polytop - polybottom)/2)); delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); - if (polytop > tm.floorz && abs(delta1) < abs(delta2)) - tm.floorz = tm.dropoffz = polytop; + if (polytop > g_tm.floorz && abs(delta1) < abs(delta2)) + g_tm.floorz = g_tm.dropoffz = polytop; - if (polybottom < tm.ceilingz && abs(delta1) >= abs(delta2)) - tm.ceilingz = tm.drpoffceilz = polybottom; + if (polybottom < g_tm.ceilingz && abs(delta1) >= abs(delta2)) + g_tm.ceilingz = g_tm.drpoffceilz = polybottom; } plink = (polymaplink_t *)(plink->link.next); } @@ -2309,7 +2309,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) UINT8 i; - tm.floatok = false; + g_tm.floatok = false; for (i = 0; i <= r_splitscreen; i++) { @@ -2337,7 +2337,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) if (!(players[displayplayers[i]].pflags & PF_NOCONTEST)) // Time Over should not clip through walls #endif { - tm.floatok = true; + g_tm.floatok = true; thiscam->floorz = thiscam->z; thiscam->ceilingz = thiscam->z + thiscam->height; thiscam->x = x; @@ -2363,18 +2363,18 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) if (!P_CheckCameraPosition(tryx, tryy, thiscam)) return false; // solid wall or thing - if (tm.ceilingz - tm.floorz < thiscam->height) + if (g_tm.ceilingz - g_tm.floorz < thiscam->height) return false; // doesn't fit - tm.floatok = true; + g_tm.floatok = true; - if (tm.ceilingz - thiscam->z < thiscam->height) + if (g_tm.ceilingz - thiscam->z < thiscam->height) { - if (s == thiscam->subsector && tm.ceilingz >= thiscam->z) + if (s == thiscam->subsector && g_tm.ceilingz >= thiscam->z) { - tm.floatok = true; - thiscam->floorz = tm.floorz; - thiscam->ceilingz = tm.floorz + thiscam->height; + g_tm.floatok = true; + thiscam->floorz = g_tm.floorz; + thiscam->ceilingz = g_tm.floorz + thiscam->height; thiscam->x = x; thiscam->y = y; thiscam->subsector = s; @@ -2384,21 +2384,21 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) return false; // mobj must lower itself to fit } - if ((tm.floorz - thiscam->z > MAXCAMERASTEPMOVE)) + if ((g_tm.floorz - thiscam->z > MAXCAMERASTEPMOVE)) return false; // too big a step up } while(tryx != x || tryy != y); } else { - tm.floorz = P_CameraGetFloorZ(thiscam, thiscam->subsector->sector, x, y, NULL); - tm.ceilingz = P_CameraGetCeilingZ(thiscam, thiscam->subsector->sector, x, y, NULL); + g_tm.floorz = P_CameraGetFloorZ(thiscam, thiscam->subsector->sector, x, y, NULL); + g_tm.ceilingz = P_CameraGetCeilingZ(thiscam, thiscam->subsector->sector, x, y, NULL); } // the move is ok, // so link the thing into its new position - thiscam->floorz = tm.floorz; - thiscam->ceilingz = tm.ceilingz; + thiscam->floorz = g_tm.floorz; + thiscam->ceilingz = g_tm.ceilingz; thiscam->x = x; thiscam->y = y; thiscam->subsector = s; @@ -2450,7 +2450,7 @@ BlockItReturn_t PIT_PushableMoved(mobj_t *thing) // These are all non-static map variables that are changed for each and every single mobj // See, changing player's momx/y would possibly trigger stuff as if the player were running somehow, so this must be done to keep the player standing // All this so players can ride gargoyles! - tm_t oldtm = tm; + tm_t oldtm = g_tm; // Move the player P_TryMove(thing, thing->x + stand->momx, thing->y + stand->momy, true, NULL); @@ -2527,7 +2527,7 @@ increment_move fixed_t tryy = thing->y; fixed_t radius = thing->radius; fixed_t thingtop; - tm.floatok = false; + g_tm.floatok = false; // reset this to 0 at the start of each trymove call as it's only used here numspechitint = 0U; @@ -2569,12 +2569,12 @@ increment_move if (P_UsingStepUp(thing)) { - tm.maxstep = P_GetThingStepUp(thing, tryx, tryy); + g_tm.maxstep = P_GetThingStepUp(thing, tryx, tryy); } if (result) { - tm.sweep = true; + g_tm.sweep = true; } boolean move_ok = P_CheckPosition(thing, tryx, tryy, result); @@ -2605,26 +2605,26 @@ increment_move if (thing->type == MT_SKIM) maxstep = 0; - if (tm.ceilingz - tm.floorz < thing->height) + if (g_tm.ceilingz - g_tm.floorz < thing->height) { - if (tm.floorthing != NULL) + if (g_tm.floorthing != NULL) { - P_SetTarget(&tm.hitthing, tm.floorthing); + P_SetTarget(&g_tm.hitthing, g_tm.floorthing); } return false; // doesn't fit } - tm.floatok = true; + g_tm.floatok = true; thingtop = thing->z + thing->height; // Step up - if (thing->z < tm.floorz) + if (thing->z < g_tm.floorz) { - if (tm.floorz - thing->z <= maxstep) + if (g_tm.floorz - thing->z <= maxstep) { - thing->z = thing->floorz = tm.floorz; + thing->z = thing->floorz = g_tm.floorz; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } else @@ -2632,11 +2632,11 @@ increment_move return false; // mobj must raise itself to fit } } - else if (tm.ceilingz < thingtop) + else if (g_tm.ceilingz < thingtop) { - if (thingtop - tm.ceilingz <= maxstep) + if (thingtop - g_tm.ceilingz <= maxstep) { - thing->z = ( thing->ceilingz = tm.ceilingz ) - thing->height; + thing->z = ( thing->ceilingz = g_tm.ceilingz ) - thing->height; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } else @@ -2653,28 +2653,28 @@ increment_move // If the floor difference is MAXSTEPMOVE or less, and the sector isn't Section1:14, ALWAYS // step down! Formerly required a Section1:13 sector for the full MAXSTEPMOVE, but no more. - if (thingtop == thing->ceilingz && tm.ceilingz > thingtop && tm.ceilingz - thingtop <= maxstep) + if (thingtop == thing->ceilingz && g_tm.ceilingz > thingtop && g_tm.ceilingz - thingtop <= maxstep) { - thing->z = (thing->ceilingz = tm.ceilingz) - thing->height; + thing->z = (thing->ceilingz = g_tm.ceilingz) - thing->height; thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->ceilingdrop = 0; } - else if (thing->z == thing->floorz && tm.floorz < thing->z && thing->z - tm.floorz <= maxstep) + else if (thing->z == thing->floorz && g_tm.floorz < thing->z && thing->z - g_tm.floorz <= maxstep) { - thing->z = thing->floorz = tm.floorz; + thing->z = thing->floorz = g_tm.floorz; thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->floordrop = 0; } } - if (!allowdropoff && !(thing->flags & MF_FLOAT) && thing->type != MT_SKIM && !tm.floorthing) + if (!allowdropoff && !(thing->flags & MF_FLOAT) && thing->type != MT_SKIM && !g_tm.floorthing) { if (thing->eflags & MFE_VERTICALFLIP) { - if (tm.drpoffceilz - tm.ceilingz > maxstep) + if (g_tm.drpoffceilz - g_tm.ceilingz > maxstep) return false; } - else if (tm.floorz - tm.dropoffz > maxstep) + else if (g_tm.floorz - g_tm.dropoffz > maxstep) return false; // don't stand over a dropoff } } @@ -2746,26 +2746,26 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, Try // Link the thing into its new position P_UnsetThingPosition(thing); - thing->floorz = tm.floorz; - thing->ceilingz = tm.ceilingz; - thing->floorrover = tm.floorrover; - thing->ceilingrover = tm.ceilingrover; + thing->floorz = g_tm.floorz; + thing->ceilingz = g_tm.ceilingz; + thing->floorrover = g_tm.floorrover; + thing->ceilingrover = g_tm.ceilingrover; if (!(thing->flags & MF_NOCLIPHEIGHT)) { // Assign thing's standingslope if needed - if (thing->z <= tm.floorz && !(thing->eflags & MFE_VERTICALFLIP)) + if (thing->z <= g_tm.floorz && !(thing->eflags & MFE_VERTICALFLIP)) { - K_UpdateMobjTerrain(thing, tm.floorpic); + K_UpdateMobjTerrain(thing, g_tm.floorpic); - if (!startingonground && tm.floorslope) + if (!startingonground && g_tm.floorslope) { - P_HandleSlopeLanding(thing, tm.floorslope); + P_HandleSlopeLanding(thing, g_tm.floorslope); } if (thing->momz <= 0) { - thing->standingslope = tm.floorslope; + thing->standingslope = g_tm.floorslope; P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) @@ -2774,18 +2774,18 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, Try } } } - else if (thing->z+thing->height >= tm.ceilingz && (thing->eflags & MFE_VERTICALFLIP)) + else if (thing->z+thing->height >= g_tm.ceilingz && (thing->eflags & MFE_VERTICALFLIP)) { - K_UpdateMobjTerrain(thing, tm.ceilingpic); + K_UpdateMobjTerrain(thing, g_tm.ceilingpic); - if (!startingonground && tm.ceilingslope) + if (!startingonground && g_tm.ceilingslope) { - P_HandleSlopeLanding(thing, tm.ceilingslope); + P_HandleSlopeLanding(thing, g_tm.ceilingslope); } if (thing->momz >= 0) { - thing->standingslope = tm.ceilingslope; + thing->standingslope = g_tm.ceilingslope; P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) @@ -2805,7 +2805,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, Try thing->x = x; thing->y = y; - if (tm.floorthing) + if (g_tm.floorthing) thing->eflags &= ~MFE_ONGROUND; // not on real floor else thing->eflags |= MFE_ONGROUND; @@ -2867,13 +2867,13 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *r { const fixed_t maxstep = P_BaseStepUp(); - if (tm.ceilingz - tm.floorz < thing->height) + if (g_tm.ceilingz - g_tm.floorz < thing->height) return false; // doesn't fit - if (tm.ceilingz - thing->z < thing->height) + if (g_tm.ceilingz - thing->z < thing->height) return false; // mobj must lower itself to fit - if (tm.floorz - thing->z > maxstep) + if (g_tm.floorz - thing->z > maxstep) return false; // too big a step up } } while(tryx != x || tryy != y); @@ -2882,14 +2882,14 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *r // so link the thing into its new position P_UnsetThingPosition(thing); - thing->floorz = tm.floorz; - thing->ceilingz = tm.ceilingz; - thing->floorrover = tm.floorrover; - thing->ceilingrover = tm.ceilingrover; + thing->floorz = g_tm.floorz; + thing->ceilingz = g_tm.ceilingz; + thing->floorrover = g_tm.floorrover; + thing->ceilingrover = g_tm.ceilingrover; thing->x = x; thing->y = y; - if (tm.floorthing) + if (g_tm.floorthing) thing->eflags &= ~MFE_ONGROUND; // not on real floor else thing->eflags |= MFE_ONGROUND; @@ -3017,17 +3017,17 @@ static boolean P_ThingHeightClip(mobj_t *thing) if (P_MobjWasRemoved(thing)) return true; - floormoved = (thing->eflags & MFE_VERTICALFLIP && tm.ceilingz != thing->ceilingz) - || (!(thing->eflags & MFE_VERTICALFLIP) && tm.floorz != thing->floorz); + floormoved = (thing->eflags & MFE_VERTICALFLIP && g_tm.ceilingz != thing->ceilingz) + || (!(thing->eflags & MFE_VERTICALFLIP) && g_tm.floorz != thing->floorz); - thing->floorz = tm.floorz; - thing->ceilingz = tm.ceilingz; - thing->floorrover = tm.floorrover; - thing->ceilingrover = tm.ceilingrover; + thing->floorz = g_tm.floorz; + thing->ceilingz = g_tm.ceilingz; + thing->floorrover = g_tm.floorrover; + thing->ceilingrover = g_tm.ceilingrover; // Ugly hack?!?! As long as just ceilingz is the lowest, // you'll still get crushed, right? - if (tm.floorz > oldfloorz+thing->height) + if (g_tm.floorz > oldfloorz+thing->height) return true; if (onfloor && !(thing->flags & MF_NOGRAVITY) && floormoved) @@ -3051,15 +3051,15 @@ static boolean P_ThingHeightClip(mobj_t *thing) thing->z = thing->floorz; } } - else if (!tm.floorthing) + else if (!g_tm.floorthing) { // don't adjust a floating monster unless forced to if (thing->eflags & MFE_VERTICALFLIP) { - if (!onfloor && thing->z < tm.floorz) + if (!onfloor && thing->z < g_tm.floorz) thing->z = thing->floorz; } - else if (!onfloor && thing->z + thing->height > tm.ceilingz) + else if (!onfloor && thing->z + thing->height > g_tm.ceilingz) thing->z = thing->ceilingz - thing->height; } @@ -4516,13 +4516,13 @@ void P_DelPrecipSeclist(mprecipsecnode_t *node) static inline BlockItReturn_t PIT_GetSectors(line_t *ld) { - if (tm.bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || - tm.bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || - tm.bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || - tm.bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + if (g_tm.bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || + g_tm.bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || + g_tm.bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || + g_tm.bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) return BMIT_CONTINUE; - if (P_BoxOnLineSide(tm.bbox, ld) != -1) + if (P_BoxOnLineSide(g_tm.bbox, ld) != -1) return BMIT_CONTINUE; if (ld->polyobj) // line belongs to a polyobject, don't add it @@ -4535,7 +4535,7 @@ static inline BlockItReturn_t PIT_GetSectors(line_t *ld) // allowed to move to this position, then the sector_list // will be attached to the Thing's mobj_t at touching_sectorlist. - sector_list = P_AddSecnode(ld->frontsector,tm.thing,sector_list); + sector_list = P_AddSecnode(ld->frontsector,g_tm.thing,sector_list); // Don't assume all lines are 2-sided, since some Things // like MT_TFOG are allowed regardless of whether their radius takes @@ -4543,7 +4543,7 @@ static inline BlockItReturn_t PIT_GetSectors(line_t *ld) // Use sidedefs instead of 2s flag to determine two-sidedness. if (ld->backsector) - sector_list = P_AddSecnode(ld->backsector, tm.thing, sector_list); + sector_list = P_AddSecnode(ld->backsector, g_tm.thing, sector_list); return BMIT_CONTINUE; } @@ -4551,13 +4551,13 @@ static inline BlockItReturn_t PIT_GetSectors(line_t *ld) // Tails 08-25-2002 static inline BlockItReturn_t PIT_GetPrecipSectors(line_t *ld) { - if (tm.precipbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || - tm.precipbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || - tm.precipbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || - tm.precipbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + if (g_tm.precipbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || + g_tm.precipbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || + g_tm.precipbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || + g_tm.precipbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) return BMIT_CONTINUE; - if (P_BoxOnLineSide(tm.precipbbox, ld) != -1) + if (P_BoxOnLineSide(g_tm.precipbbox, ld) != -1) return BMIT_CONTINUE; if (ld->polyobj) // line belongs to a polyobject, don't add it @@ -4570,7 +4570,7 @@ static inline BlockItReturn_t PIT_GetPrecipSectors(line_t *ld) // allowed to move to this position, then the sector_list // will be attached to the Thing's mobj_t at touching_sectorlist. - precipsector_list = P_AddPrecipSecnode(ld->frontsector, tm.precipthing, precipsector_list); + precipsector_list = P_AddPrecipSecnode(ld->frontsector, g_tm.precipthing, precipsector_list); // Don't assume all lines are 2-sided, since some Things // like MT_TFOG are allowed regardless of whether their radius takes @@ -4578,7 +4578,7 @@ static inline BlockItReturn_t PIT_GetPrecipSectors(line_t *ld) // Use sidedefs instead of 2s flag to determine two-sidedness. if (ld->backsector) - precipsector_list = P_AddPrecipSecnode(ld->backsector, tm.precipthing, precipsector_list); + precipsector_list = P_AddPrecipSecnode(ld->backsector, g_tm.precipthing, precipsector_list); return BMIT_CONTINUE; } @@ -4590,7 +4590,8 @@ void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y) { INT32 xl, xh, yl, yh, bx, by; msecnode_t *node = sector_list; - tm_t ptm = tm; /* cph - see comment at func end */ + tm_t ptm = g_tm; + /* cph - see comment at func end */ // First, clear out the existing m_thing fields. As each node is // added or verified as needed, m_thing will be set properly. When @@ -4603,23 +4604,23 @@ void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y) node = node->m_sectorlist_next; } - P_SetTarget(&tm.thing, thing); - tm.flags = thing->flags; + P_SetTarget(&g_tm.thing, thing); + g_tm.flags = thing->flags; - tm.x = x; - tm.y = y; + g_tm.x = x; + g_tm.y = y; - tm.bbox[BOXTOP] = y + tm.thing->radius; - tm.bbox[BOXBOTTOM] = y - tm.thing->radius; - tm.bbox[BOXRIGHT] = x + tm.thing->radius; - tm.bbox[BOXLEFT] = x - tm.thing->radius; + g_tm.bbox[BOXTOP] = y + g_tm.thing->radius; + g_tm.bbox[BOXBOTTOM] = y - g_tm.thing->radius; + g_tm.bbox[BOXRIGHT] = x + g_tm.thing->radius; + g_tm.bbox[BOXLEFT] = x - g_tm.thing->radius; validcount++; // used to make sure we only process a line once - xl = (unsigned)(tm.bbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(tm.bbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(tm.bbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(tm.bbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(g_tm.bbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(g_tm.bbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(g_tm.bbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(g_tm.bbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -4646,10 +4647,10 @@ void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y) } /* cph - - * This is the strife we get into for using global variables. tm.thing + * This is the strife we get into for using global variables. g_tm.thing * is being used by several different functions calling * P_BlockThingIterator, including functions that can be called *from* - * P_BlockThingIterator. Using a global tm.thing is not reentrant. + * P_BlockThingIterator. Using a global g_tm.thing is not reentrant. * OTOH for Boom/MBF demos we have to preserve the buggy behavior. * Fun. We restore its previous value unless we're in a Boom/MBF demo. */ @@ -4661,7 +4662,8 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing,fixed_t x,fixed_t y) { INT32 xl, xh, yl, yh, bx, by; mprecipsecnode_t *node = precipsector_list; - tm_t ptm = tm; /* cph - see comment at func end */ + tm_t ptm = g_tm; + /* cph - see comment at func end */ // First, clear out the existing m_thing fields. As each node is // added or verified as needed, m_thing will be set properly. When @@ -4674,19 +4676,19 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing,fixed_t x,fixed_t y) node = node->m_sectorlist_next; } - tm.precipthing = thing; + g_tm.precipthing = thing; - tm.precipbbox[BOXTOP] = y + 2*FRACUNIT; - tm.precipbbox[BOXBOTTOM] = y - 2*FRACUNIT; - tm.precipbbox[BOXRIGHT] = x + 2*FRACUNIT; - tm.precipbbox[BOXLEFT] = x - 2*FRACUNIT; + g_tm.precipbbox[BOXTOP] = y + 2*FRACUNIT; + g_tm.precipbbox[BOXBOTTOM] = y - 2*FRACUNIT; + g_tm.precipbbox[BOXRIGHT] = x + 2*FRACUNIT; + g_tm.precipbbox[BOXLEFT] = x - 2*FRACUNIT; validcount++; // used to make sure we only process a line once - xl = (unsigned)(tm.precipbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(tm.precipbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(tm.precipbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(tm.precipbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(g_tm.precipbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(g_tm.precipbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(g_tm.precipbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(g_tm.precipbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -4713,10 +4715,10 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing,fixed_t x,fixed_t y) } /* cph - - * This is the strife we get into for using global variables. tm.thing + * This is the strife we get into for using global variables. g_tm.thing * is being used by several different functions calling * P_BlockThingIterator, including functions that can be called *from* - * P_BlockThingIterator. Using a global tm.thing is not reentrant. + * P_BlockThingIterator. Using a global g_tm.thing is not reentrant. * OTOH for Boom/MBF demos we have to preserve the buggy behavior. * Fun. We restore its previous value unless we're in a Boom/MBF demo. */ @@ -4724,16 +4726,16 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing,fixed_t x,fixed_t y) } /* cphipps 2004/08/30 - - * Must clear tm.thing at tic end, as it might contain a pointer to a removed thinker, or the level might have ended/been ended and we clear the objects it was pointing too. Hopefully we don't need to carry this between tics for sync. */ + * Must clear g_tm.thing at tic end, as it might contain a pointer to a removed thinker, or the level might have ended/been ended and we clear the objects it was pointing too. Hopefully we don't need to carry this between tics for sync. */ void P_MapStart(void) { - if (tm.thing) - I_Error("P_MapStart: tm.thing set!"); + if (g_tm.thing) + I_Error("P_MapStart: g_tm.thing set!"); } void P_MapEnd(void) { - P_SetTarget(&tm.thing, NULL); + P_SetTarget(&g_tm.thing, NULL); } // P_FloorzAtPos diff --git a/src/p_maputl.c b/src/p_maputl.c index f67ed5994..867e2b1a4 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -315,8 +315,8 @@ void P_CameraLineOpening(line_t *linedef, opening_t *open) } else { - frontfloor = P_CameraGetFloorZ (mapcampointer, front, tm.x, tm.y, linedef); - frontceiling = P_CameraGetCeilingZ(mapcampointer, front, tm.x, tm.y, linedef); + frontfloor = P_CameraGetFloorZ (mapcampointer, front, g_tm.x, g_tm.y, linedef); + frontceiling = P_CameraGetCeilingZ(mapcampointer, front, g_tm.x, g_tm.y, linedef); } if (back->camsec >= 0) @@ -333,8 +333,8 @@ void P_CameraLineOpening(line_t *linedef, opening_t *open) } else { - backfloor = P_CameraGetFloorZ(mapcampointer, back, tm.x, tm.y, linedef); - backceiling = P_CameraGetCeilingZ(mapcampointer, back, tm.x, tm.y, linedef); + backfloor = P_CameraGetFloorZ(mapcampointer, back, g_tm.x, g_tm.y, linedef); + backceiling = P_CameraGetCeilingZ(mapcampointer, back, g_tm.x, g_tm.y, linedef); } thingtop = mapcampointer->z + mapcampointer->height; @@ -375,8 +375,8 @@ void P_CameraLineOpening(line_t *linedef, opening_t *open) if (!(rover->fofflags & FOF_BLOCKOTHERS) || !(rover->fofflags & FOF_RENDERALL) || !(rover->fofflags & FOF_EXISTS) ) continue; - topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, tm.x, tm.y, linedef); - bottomheight = P_CameraGetFOFBottomZ(mapcampointer, front, rover, tm.x, tm.y, linedef); + topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, g_tm.x, g_tm.y, linedef); + bottomheight = P_CameraGetFOFBottomZ(mapcampointer, front, rover, g_tm.x, g_tm.y, linedef); delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); @@ -399,8 +399,8 @@ void P_CameraLineOpening(line_t *linedef, opening_t *open) if (!(rover->fofflags & FOF_BLOCKOTHERS) || !(rover->fofflags & FOF_RENDERALL) || !(rover->fofflags & FOF_EXISTS) ) continue; - topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tm.x, tm.y, linedef); - bottomheight = P_CameraGetFOFBottomZ(mapcampointer, back, rover, tm.x, tm.y, linedef); + topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, g_tm.x, g_tm.y, linedef); + bottomheight = P_CameraGetFOFBottomZ(mapcampointer, back, rover, g_tm.x, g_tm.y, linedef); delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); @@ -539,7 +539,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) return; } - P_ClosestPointOnLine(tm.x, tm.y, linedef, &cross); + P_ClosestPointOnLine(g_tm.x, g_tm.y, linedef, &cross); // Treat polyobjects kind of like 3D Floors if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) @@ -567,8 +567,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) fixed_t height[2]; const sector_t * sector[2] = { front, back }; - height[FRONT] = P_GetCeilingZ(mobj, front, tm.x, tm.y, linedef); - height[BACK] = P_GetCeilingZ(mobj, back, tm.x, tm.y, linedef); + height[FRONT] = P_GetCeilingZ(mobj, front, g_tm.x, g_tm.y, linedef); + height[BACK] = P_GetCeilingZ(mobj, back, g_tm.x, g_tm.y, linedef); hi = ( height[0] < height[1] ); lo = ! hi; @@ -587,8 +587,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) open->ceilingdrop = ( topedge[hi] - topedge[lo] ); } - height[FRONT] = P_GetFloorZ(mobj, front, tm.x, tm.y, linedef); - height[BACK] = P_GetFloorZ(mobj, back, tm.x, tm.y, linedef); + height[FRONT] = P_GetFloorZ(mobj, front, g_tm.x, g_tm.y, linedef); + height[BACK] = P_GetFloorZ(mobj, back, g_tm.x, g_tm.y, linedef); hi = ( height[0] < height[1] ); lo = ! hi; @@ -777,8 +777,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) } else { - topheight = P_GetFOFTopZ(mobj, front, rover, tm.x, tm.y, linedef); - bottomheight = P_GetFOFBottomZ(mobj, front, rover, tm.x, tm.y, linedef); + topheight = P_GetFOFTopZ(mobj, front, rover, g_tm.x, g_tm.y, linedef); + bottomheight = P_GetFOFBottomZ(mobj, front, rover, g_tm.x, g_tm.y, linedef); } switch (open->fofType) @@ -869,8 +869,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) } else { - topheight = P_GetFOFTopZ(mobj, back, rover, tm.x, tm.y, linedef); - bottomheight = P_GetFOFBottomZ(mobj, back, rover, tm.x, tm.y, linedef); + topheight = P_GetFOFTopZ(mobj, back, rover, g_tm.x, g_tm.y, linedef); + bottomheight = P_GetFOFBottomZ(mobj, back, rover, g_tm.x, g_tm.y, linedef); } switch (open->fofType) @@ -1834,16 +1834,16 @@ boolean P_RadiusLinesCheck(fixed_t radius, fixed_t x, fixed_t y, INT32 xl, xh, yl, yh; INT32 bx, by; - tm.bbox[BOXTOP] = y + radius; - tm.bbox[BOXBOTTOM] = y - radius; - tm.bbox[BOXRIGHT] = x + radius; - tm.bbox[BOXLEFT] = x - radius; + g_tm.bbox[BOXTOP] = y + radius; + g_tm.bbox[BOXBOTTOM] = y - radius; + g_tm.bbox[BOXRIGHT] = x + radius; + g_tm.bbox[BOXLEFT] = x - radius; // check lines - xl = (unsigned)(tm.bbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(tm.bbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(tm.bbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(tm.bbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(g_tm.bbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(g_tm.bbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(g_tm.bbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(g_tm.bbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; for (bx = xl; bx <= xh; bx++) for (by = yl; by <= yh; by++) diff --git a/src/p_mobj.c b/src/p_mobj.c index 94bd091c8..6130a77b0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1508,12 +1508,12 @@ bustupdone: // static boolean P_CheckSkyHit(mobj_t *mo) { - if (tm.ceilingline && tm.ceilingline->backsector - && tm.ceilingline->backsector->ceilingpic == skyflatnum - && tm.ceilingline->frontsector - && tm.ceilingline->frontsector->ceilingpic == skyflatnum - && (mo->z >= tm.ceilingline->frontsector->ceilingheight - || mo->z >= tm.ceilingline->backsector->ceilingheight)) + if (g_tm.ceilingline && g_tm.ceilingline->backsector + && g_tm.ceilingline->backsector->ceilingpic == skyflatnum + && g_tm.ceilingline->frontsector + && g_tm.ceilingline->frontsector->ceilingpic == skyflatnum + && (mo->z >= g_tm.ceilingline->frontsector->ceilingheight + || mo->z >= g_tm.ceilingline->backsector->ceilingheight)) return true; return false; } @@ -1610,7 +1610,7 @@ void P_XYMovement(mobj_t *mo) // blocked move moved = false; - if (LUA_HookMobjMoveBlocked(mo, tm.hitthing, result.line)) + if (LUA_HookMobjMoveBlocked(mo, g_tm.hitthing, result.line)) { if (P_MobjWasRemoved(mo)) return; @@ -1651,7 +1651,7 @@ void P_XYMovement(mobj_t *mo) // draw damage on wall //SPLAT TEST ---------------------------------------------------------- #ifdef WALLSPLATS - if (tm.blockingline && mo->type != MT_REDRING && mo->type != MT_FIREBALL + if (g_tm.blockingline && mo->type != MT_REDRING && mo->type != MT_FIREBALL && !(mo->flags2 & (MF2_AUTOMATIC|MF2_RAILRING|MF2_BOUNCERING|MF2_EXPLOSION|MF2_SCATTER))) // set by last P_TryMove() that failed { @@ -1659,13 +1659,13 @@ void P_XYMovement(mobj_t *mo) divline_t misl; fixed_t frac; - P_MakeDivline(tm.blockingline, &divl); + P_MakeDivline(g_tm.blockingline, &divl); misl.x = mo->x; misl.y = mo->y; misl.dx = mo->momx; misl.dy = mo->momy; frac = P_InterceptVector(&divl, &misl); - R_AddWallSplat(tm.blockingline, P_PointOnLineSide(mo->x,mo->y,tm.blockingline), + R_AddWallSplat(g_tm.blockingline, P_PointOnLineSide(mo->x,mo->y,g_tm.blockingline), "A_DMG3", mo->z, frac, SPLATDRAWMODE_SHADE); } #endif @@ -2388,11 +2388,11 @@ boolean P_ZMovement(mobj_t *mo) if (P_MobjWasRemoved(mo)) // mobjs can be removed by P_CheckPosition -- Monster Iestyn 31/07/21 return false; - K_UpdateMobjTerrain(mo, ((mo->eflags & MFE_VERTICALFLIP) ? tm.ceilingpic : tm.floorpic)); + K_UpdateMobjTerrain(mo, ((mo->eflags & MFE_VERTICALFLIP) ? g_tm.ceilingpic : g_tm.floorpic)); - if (((mo->eflags & MFE_VERTICALFLIP) ? tm.ceilingslope : tm.floorslope) && (mo->type != MT_STEAM)) + if (((mo->eflags & MFE_VERTICALFLIP) ? g_tm.ceilingslope : g_tm.floorslope) && (mo->type != MT_STEAM)) { - mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tm.ceilingslope : tm.floorslope; + mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? g_tm.ceilingslope : g_tm.floorslope; P_SetPitchRollFromSlope(mo, mo->standingslope); P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); } @@ -2525,11 +2525,11 @@ boolean P_ZMovement(mobj_t *mo) } } else - mom.z = (tm.floorthing ? tm.floorthing->momz : 0); + mom.z = (g_tm.floorthing ? g_tm.floorthing->momz : 0); } - else if (tm.floorthing) - mom.z = tm.floorthing->momz; + else if (g_tm.floorthing) + mom.z = g_tm.floorthing->momz; if (mo->standingslope) { // MT_STEAM will never have a standingslope, see above. P_QuantizeMomentumToSlope(&mom, mo->standingslope); @@ -2763,7 +2763,7 @@ void P_PlayerZMovement(mobj_t *mo) mo->z = mo->floorz; } - K_UpdateMobjTerrain(mo, (mo->eflags & MFE_VERTICALFLIP ? tm.ceilingpic : tm.floorpic)); + K_UpdateMobjTerrain(mo, (mo->eflags & MFE_VERTICALFLIP ? g_tm.ceilingpic : g_tm.floorpic)); // Get up if you fell. if (mo->player->panim == PA_HURT && mo->player->spinouttimer == 0 && mo->player->squishedtimer == 0) @@ -2771,10 +2771,10 @@ void P_PlayerZMovement(mobj_t *mo) P_SetPlayerMobjState(mo, S_KART_STILL); } - if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tm.ceilingslope : tm.floorslope)) + if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? g_tm.ceilingslope : g_tm.floorslope)) { // Handle landing on slope during Z movement - P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tm.ceilingslope : tm.floorslope)); + P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? g_tm.ceilingslope : g_tm.floorslope)); } if (P_MobjFlip(mo) * mo->momz < 0) // falling @@ -2789,12 +2789,12 @@ void P_PlayerZMovement(mobj_t *mo) if (clipmomz) { - mo->momz = (tm.floorthing ? tm.floorthing->momz : 0); + mo->momz = (g_tm.floorthing ? g_tm.floorthing->momz : 0); } } - else if (tm.floorthing) + else if (g_tm.floorthing) { - mo->momz = tm.floorthing->momz; + mo->momz = g_tm.floorthing->momz; } } else @@ -2963,9 +2963,9 @@ boolean P_SceneryZMovement(mobj_t *mo) { mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack - if (tm.floorthing) - mo->momz = tm.floorthing->momz; - else if (!tm.floorthing) + if (g_tm.floorthing) + mo->momz = g_tm.floorthing->momz; + else if (!g_tm.floorthing) mo->momz = 0; } } @@ -3633,8 +3633,8 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled } thiscam->subsector = R_PointInSubsectorFast(thiscam->x, thiscam->y); - thiscam->floorz = tm.floorz; - thiscam->ceilingz = tm.ceilingz; + thiscam->floorz = g_tm.floorz; + thiscam->ceilingz = g_tm.ceilingz; if (thiscam->momz || player->mo->pmomz) { @@ -3781,8 +3781,8 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->z += mobj->momz; P_SetThingPosition(mobj); P_CheckPosition(mobj, mobj->x, mobj->y, NULL); - mobj->floorz = tm.floorz; - mobj->ceilingz = tm.ceilingz; + mobj->floorz = g_tm.floorz; + mobj->ceilingz = g_tm.ceilingz; mobj->terrain = NULL; goto animonly; } @@ -8603,8 +8603,8 @@ void P_MobjThinker(mobj_t *mobj) mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG|MFE_JUSTBOUNCEDWALL|MFE_SLOPELAUNCHED); // sal: what the hell? is there any reason this isn't done, like, literally ANYWHERE else? - P_SetTarget(&tm.floorthing, NULL); - P_SetTarget(&tm.hitthing, NULL); + P_SetTarget(&g_tm.floorthing, NULL); + P_SetTarget(&g_tm.hitthing, NULL); if (udmf) { @@ -8988,10 +8988,10 @@ void P_SceneryThinker(mobj_t *mobj) P_CheckPosition(mobj, mobj->x, mobj->y, NULL); // Need this to pick up objects! if (P_MobjWasRemoved(mobj)) return; - mobj->floorz = tm.floorz; - mobj->ceilingz = tm.ceilingz; - mobj->floorrover = tm.floorrover; - mobj->ceilingrover = tm.ceilingrover; + mobj->floorz = g_tm.floorz; + mobj->ceilingz = g_tm.ceilingz; + mobj->floorrover = g_tm.floorrover; + mobj->ceilingrover = g_tm.ceilingrover; } else { diff --git a/src/p_polyobj.c b/src/p_polyobj.c index ae73fd31f..a1f1463b3 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -200,7 +200,7 @@ boolean P_BBoxInsidePolyobj(polyobj_t *po, fixed_t *bbox) { if (P_BoxOnLineSide(bbox, po->lines[i]) == 0) return false; - if (tm.sweep) + if (g_tm.sweep) { P_TestLine(po->lines[i]); } @@ -801,7 +801,7 @@ static void Polyobj_removeFromBlockmap(polyobj_t *po) // Movement functions // A version of Lee's routine from p_maputl.c that accepts an mobj pointer -// argument instead of using tm.thing. Returns true if the line isn't contacted +// argument instead of using g_tm.thing. Returns true if the line isn't contacted // and false otherwise. static inline boolean Polyobj_untouched(line_t *ld, mobj_t *mo) { @@ -845,10 +845,10 @@ static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo) if (po->damage && (mo->flags & MF_SHOOTABLE)) { P_CheckPosition(mo, mo->x + momx, mo->y + momy, NULL); - mo->floorz = tm.floorz; - mo->ceilingz = tm.ceilingz; - mo->floorrover = tm.floorrover; - mo->ceilingrover = tm.ceilingrover; + mo->floorz = g_tm.floorz; + mo->ceilingz = g_tm.ceilingz; + mo->floorrover = g_tm.floorrover; + mo->ceilingrover = g_tm.ceilingrover; } } diff --git a/src/p_saveg.c b/src/p_saveg.c index 0aa2cd3bb..91a36170c 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -995,6 +995,7 @@ static void P_NetUnArchiveColormaps(savebuffer_t *save) //diff5 flags #define SD_ACTIVATION 0x01 +#define SD_BOTCONTROLLER 0x02 static boolean P_SectorArgsEqual(const sector_t *sc, const sector_t *spawnsc) { @@ -1230,6 +1231,12 @@ static void ArchiveSectors(savebuffer_t *save) diff4 |= SD_STRINGARGS; if (ss->activation != spawnss->activation) diff5 |= SD_ACTIVATION; + if (/*ss->botController.trick != spawnss->botController.trick + ||*/ss->botController.flags != spawnss->botController.flags + || ss->botController.forceAngle != spawnss->botController.forceAngle) + { + diff5 |= SD_BOTCONTROLLER; + } if (ss->ffloors && CheckFFloorDiff(ss)) diff |= SD_FFLOORS; @@ -1343,6 +1350,13 @@ static void ArchiveSectors(savebuffer_t *save) if (diff5 & SD_ACTIVATION) WRITEUINT32(save->p, ss->activation); + if (diff5 & SD_BOTCONTROLLER) + { + //WRITEUINT8(save->p, ss->botController.trick); + WRITEUINT32(save->p, ss->botController.flags); + WRITEANGLE(save->p, ss->botController.forceAngle); + } + if (diff & SD_FFLOORS) ArchiveFFloors(save, ss); } @@ -1499,6 +1513,13 @@ static void UnArchiveSectors(savebuffer_t *save) if (diff5 & SD_ACTIVATION) sectors[i].activation = READUINT32(save->p); + if (diff5 & SD_BOTCONTROLLER) + { + //sectors[i].botController.trick = READUINT8(save->p); + sectors[i].botController.flags = READUINT32(save->p); + sectors[i].botController.forceAngle = READANGLE(save->p); + } + if (diff & SD_FFLOORS) UnArchiveFFloors(save, §ors[i]); } diff --git a/src/p_setup.c b/src/p_setup.c index 18532fecf..403107bef 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -942,6 +942,8 @@ static void P_InitializeSector(sector_t *ss) ss->spawn_lightlevel = ss->lightlevel; ss->spawn_extra_colormap = NULL; + + memset(&ss->botController, 0, sizeof(ss->botController)); } static void P_LoadSectors(UINT8 *data) @@ -8634,7 +8636,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) P_ResetTubeWaypoints(); - P_MapStart(); // tm.thing can be used starting from this point + P_MapStart(); // g_tm.thing can be used starting from this point // init anything that P_SpawnSlopes/P_LoadThings needs to know P_InitSpecials(); @@ -8749,7 +8751,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) G_AddMapToBuffer(gamemap-1); - P_MapEnd(); // tm.thing is no longer needed from this point onwards + P_MapEnd(); // g_tm.thing is no longer needed from this point onwards // Took me 3 hours to figure out why my progression kept on getting overwritten with the titlemap... if (!titlemapinaction) @@ -8834,7 +8836,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) void P_PostLoadLevel(void) { TracyCZone(__zone, true); - P_MapStart(); // tm.thing can be used starting from this point + P_MapStart(); // g_tm.thing can be used starting from this point if (G_GametypeHasSpectators()) { diff --git a/src/p_sight.c b/src/p_sight.c index 373cc1581..f934e1a6d 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -1,8 +1,10 @@ -// SONIC ROBO BLAST 2 +// DR. ROBOTNIK'S RING RACERS //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour. +// Copyright (C) 2024 by Kart Krew. +// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2000 by DooM Legacy Team. +// Copyright (C) 1996 by id Software, Inc. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -37,7 +39,6 @@ typedef struct mobj_t *t1, *t2; boolean alreadyHates; // For bot traversal, for if the bot is already in a sector it doesn't want to be UINT8 traversed; - mobj_t *compareThing; // Original thing } los_t; typedef boolean (*los_init_t)(mobj_t *, mobj_t *, register los_t *); @@ -53,7 +54,11 @@ typedef struct static INT32 sightcounts[2]; -#define TRAVERSE_MAX (8) +#ifdef DEVELOP +extern consvar_t cv_debugtraversemax; +#undef TRAVERSE_MAX +#define TRAVERSE_MAX (cv_debugtraversemax.value) +#endif // // P_DivlineSide @@ -335,13 +340,13 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los frac = P_InterceptVector(&los->strace, divl); // calculate position at intercept - tm.x = los->strace.x + FixedMul(los->strace.dx, frac); - tm.y = los->strace.y + FixedMul(los->strace.dy, frac); + g_tm.x = los->strace.x + FixedMul(los->strace.dx, frac); + g_tm.y = los->strace.y + FixedMul(los->strace.dy, frac); // set openrange, opentop, openbottom open.fofType = (flip ? LO_FOF_CEILINGS : LO_FOF_FLOORS); P_LineOpening(line, los->t1, &open); - maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y); + maxstep = P_GetThingStepUp(los->t1, g_tm.x, g_tm.y); if (open.range < los->t1->height) { @@ -363,7 +368,7 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los UINT8 side = P_DivlineSide(los->t2x, los->t2y, divl) & 1; sector_t *sector = (side == 1) ? seg->backsector : seg->frontsector; - if (K_BotHatesThisSector(los->t1->player, sector, tm.x, tm.y)) + if (K_BotHatesThisSector(los->t1->player, sector, g_tm.x, g_tm.y)) { // This line does not block us, but we don't want to cross it regardless. return false; @@ -403,13 +408,13 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t frac = P_InterceptVector(&los->strace, divl); // calculate position at intercept - tm.x = los->strace.x + FixedMul(los->strace.dx, frac); - tm.y = los->strace.y + FixedMul(los->strace.dy, frac); + g_tm.x = los->strace.x + FixedMul(los->strace.dx, frac); + g_tm.y = los->strace.y + FixedMul(los->strace.dy, frac); // set openrange, opentop, openbottom open.fofType = (flip ? LO_FOF_CEILINGS : LO_FOF_FLOORS); P_LineOpening(line, los->t1, &open); - maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y); + maxstep = P_GetThingStepUp(los->t1, g_tm.x, g_tm.y); #if 0 if (los->t2->type == MT_WAYPOINT) @@ -470,10 +475,11 @@ static boolean P_CrossSubsector(size_t num, register los_t *los, register los_fu seg_t *seg; INT32 count; -#ifdef RANGECHECK if (num >= numsubsectors) - I_Error("P_CrossSubsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors)); -#endif + { + CONS_Debug(DBG_RENDER, "P_CrossSubsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors)); + return true; + } // haleyjd 02/23/06: this assignment should be after the above check seg = segs + subsectors[num].firstline; @@ -556,11 +562,6 @@ static boolean P_CrossSubsector(size_t num, register los_t *los, register los_fu static boolean P_CrossBSPNode(INT32 bspnum, register los_t *los, register los_funcs_t *funcs) { - if (funcs->validate == NULL) - { - return false; - } - while (!(bspnum & NF_SUBSECTOR)) { register node_t *bsp = nodes + bspnum; diff --git a/src/p_spec.c b/src/p_spec.c index 6874f82db..3bc0f6072 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2431,6 +2431,20 @@ mobj_t* P_FindObjectTypeFromTag(mobjtype_t type, mtag_t tag) } } +static void K_UpdateBotControllers(INT32 *args) +{ + INT32 secnum; + + TAG_ITER_SECTORS(args[0], secnum) + { + sector_t *const sec = sectors + secnum; + + //sec->botController.trick = args[1]; + sec->botController.flags = args[2]; + sec->botController.forceAngle = FixedAngle(args[3] * FRACUNIT); + } +} + /** Processes the line special triggered by an object. * * \param line Line with the special command on it. @@ -4426,6 +4440,12 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha } break; + case 2004: // Bot Controller. + { + K_UpdateBotControllers(args); + break; + } + default: break; } @@ -7692,6 +7712,10 @@ void P_SpawnSpecials(boolean fromnetsave) } break; + case 2004: // Bot Controller. + K_UpdateBotControllers(lines[i].args); + break; + default: break; } diff --git a/src/r_defs.h b/src/r_defs.h index ce833906d..c86a1c192 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -360,6 +360,14 @@ typedef enum MSF_DIRECTIONLIGHTING = 1<<14, } sectorflags_t; +// Per-sector bot controller override +struct botcontroller_t +{ + //UINT8 trick; + UINT32 flags; + angle_t forceAngle; +}; + typedef enum { SSF_NOSTEPUP = 1, @@ -568,6 +576,9 @@ struct sector_t // colormap structure extracolormap_t *spawn_extra_colormap; + // Ring Racers bots + botcontroller_t botController; + // Action specials INT16 action; INT32 args[NUM_SCRIPT_ARGS]; diff --git a/src/typedef.h b/src/typedef.h index 04155d4ef..ca33b24e9 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -158,6 +158,7 @@ TYPEDEF (weakspot_t); // k_bot.h TYPEDEF (botprediction_t); +TYPEDEF (botcontroller_t); // k_brightmap.h TYPEDEF (brightmapStorage_t);