Merge branch 'bortsport' into blankart-dev
This commit is contained in:
commit
064be1b201
35 changed files with 2744 additions and 1443 deletions
|
|
@ -52,6 +52,8 @@ add_custom_target(_SRB2_reconf ALL
|
|||
)
|
||||
add_dependencies(SRB2SDL2 _SRB2_reconf)
|
||||
|
||||
|
||||
|
||||
add_subdirectory(blua)
|
||||
add_subdirectory(blan)
|
||||
add_subdirectory(sdl)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
123
src/d_clisrv.c
123
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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
32
src/g_game.c
32
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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
167
src/k_bot.h
167
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"
|
||||
|
|
|
|||
|
|
@ -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 <algorithm>
|
||||
|
||||
#include <tracy/tracy/Tracy.hpp>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 <algorithm>
|
||||
|
||||
#include <tracy/tracy/Tracy.hpp>
|
||||
|
||||
#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)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
22
src/k_kart.c
22
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
|
||||
|
|
|
|||
|
|
@ -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 <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
// 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<boolean*>(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<waypoint_t**>(
|
||||
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<UINT32*>(
|
||||
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<waypoint_t**>(
|
||||
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<UINT32*>(
|
||||
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<waypoint_t*>(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<sector_t *> sectors;
|
||||
//std::vector<mapthing_t *> 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<fixed_t>(
|
||||
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<fixed_t>(
|
||||
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<fixed_t>(1, dist_factor));
|
||||
radius_factor = FixedDiv(FRACUNIT, std::max<fixed_t>(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<complexity_sneaker_s> 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
1236
src/p_map.c
1236
src/p_map.c
File diff suppressed because it is too large
Load diff
|
|
@ -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++)
|
||||
|
|
|
|||
70
src/p_mobj.c
70
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
24
src/p_spec.c
24
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;
|
||||
}
|
||||
|
|
|
|||
11
src/r_defs.h
11
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];
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ TYPEDEF (weakspot_t);
|
|||
|
||||
// k_bot.h
|
||||
TYPEDEF (botprediction_t);
|
||||
TYPEDEF (botcontroller_t);
|
||||
|
||||
// k_brightmap.h
|
||||
TYPEDEF (brightmapStorage_t);
|
||||
|
|
|
|||
Loading…
Reference in a new issue