diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4447614d3..ce1fd031b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -159,7 +159,9 @@ set(SRB2_CORE_GAME_SOURCES p_user.c k_battle.c k_bheap.c + k_bot.c k_collide.c + k_grandprix.c k_kart.c k_pathfind.c k_pwrlv.c @@ -177,7 +179,9 @@ set(SRB2_CORE_GAME_SOURCES p_tick.h k_battle.h k_bheap.h + k_bot.h k_collide.h + k_grandprix.h k_kart.h k_pathfind.h k_pwrlv.h diff --git a/src/Makefile b/src/Makefile index 2b1e7c7f8..27477d10f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -501,6 +501,8 @@ OBJS:=$(i_main_o) \ $(OBJDIR)/k_waypoint.o\ $(OBJDIR)/k_pathfind.o\ $(OBJDIR)/k_bheap.o \ + $(OBJDIR)/k_bot.o \ + $(OBJDIR)/k_grandprix.o\ $(OBJDIR)/m_aatree.o \ $(OBJDIR)/m_anigif.o \ $(OBJDIR)/m_argv.o \ @@ -550,7 +552,6 @@ OBJS:=$(i_main_o) \ $(OBJDIR)/i_tcp.o \ $(OBJDIR)/lzf.o \ $(OBJDIR)/vid_copy.o \ - $(OBJDIR)/k_bot.o \ $(i_cdmus_o) \ $(i_net_o) \ $(i_system_o) \ diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 406c07150..08b93bfbf 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -50,6 +50,7 @@ #include "k_battle.h" #include "k_pwrlv.h" #include "k_bot.h" +#include "k_grandprix.h" #ifdef CLIENT_LOADINGSCREEN // cl loading screen diff --git a/src/d_main.c b/src/d_main.c index 1ef581407..075a3f8b1 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -774,6 +774,7 @@ void D_StartTitle(void) // In case someone exits out at the same time they start a time attack run, // reset modeattacking modeattacking = ATTACKING_NONE; + grandprixmatch = 0; // empty maptol so mario/etc sounds don't play in sound test when they shouldn't maptol = 0; diff --git a/src/k_bot.c b/src/k_bot.c index 285207caa..bc35bc21d 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -197,147 +197,6 @@ void K_UpdateMatchRaceBots(void) // We should have enough bots now :) } -#if 0 -// This is mostly just pesudo code right now... -void K_InitGrandPrixBots(void) -{ - const UINT8 defaultbotskin = 9; // eggrobo - - // startingdifficulty: Easy = 3, Normal = 6, Hard = 9 - const UINT8 startingdifficulty = min(MAXBOTDIFFICULTY, (cv_kartspeed.value + 1) * 3); - UINT8 difficultylevels[MAXPLAYERS]; - - UINT8 playercount = 8; - UINT8 wantedbots = 0; - - UINT8 numplayers = 0; - UINT8 competitors[4]; - - boolean skinusable[MAXSKINS]; - UINT8 botskinlist[MAXPLAYERS]; - UINT8 botskinlistpos = 0; - - UINT8 i; - - memset(difficultylevels, MAXBOTDIFFICULTY, sizeof (difficultylevels)); - memset(competitors, MAXPLAYERS, sizeof (competitors)); - memset(botskinlist, defaultbotskin, sizeof (botskinlist)); - - // init usable bot skins list - for (i = 0; i < MAXSKINS; i++) - { - if (i < numskins) - { - skinusable[i] = true; - } - else - { - skinusable[i] = false; - } - } - - // init difficulty levels list - //if (!mastermodebots) { - difficultylevels[MAXPLAYERS] = { - max(1, startingdifficulty), - max(1, startingdifficulty-1), - max(1, startingdifficulty-2), - max(1, startingdifficulty-3), - max(1, startingdifficulty-3), - max(1, startingdifficulty-4), - max(1, startingdifficulty-4), - max(1, startingdifficulty-4), - max(1, startingdifficulty-5), - max(1, startingdifficulty-5), - max(1, startingdifficulty-6), - max(1, startingdifficulty-6), - max(1, startingdifficulty-7), - max(1, startingdifficulty-7), - max(1, startingdifficulty-8), - max(1, startingdifficulty-8), - }; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (numplayers < MAXSPLITSCREENPLAYERS) - { - if (playeringame[i] && !players[i].spectator) - { - competitors[numplayers] = i; - numplayers++; - } - } - else - { - if (playeringame[i]) - { - players[i].spectator = true; // 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; - } - - wantedbots = playercount - numplayers; - - // Create rival list - - // TODO: Use player skin's set rivals - // Starting with P1's rival1, P2's rival1, P3's rival1, P4's rival1, - // then P1's rival2, P2's rival2, etc etc etc etc....... - // then skip over any duplicates. - - // Pad the remaining list with random skins if we need to - if (botskinlistpos < wantedbots) - { - for (i = botskinlistpos; i < wantedbots; i++) - { - UINT8 val = M_RandomKey(numskins); - UINT8 loops = 0; - - while (!skinusable[val]) - { - if (loops >= numskins) - { - // no more skins - break; - } - - val++; - - if (val >= numskins) - { - val = 0; - } - - loops++; - } - - if (loops >= numskins) - { - // leave the rest of the table as the default skin - break; - } - - botskinlist[i] = val; - skinusable[val] = false; - } - } - - for (i = 0; i < wantedbots; i++) - { - if (!K_AddBot(botskinlist[i], difficultylevels[i], &newplayernum)) - { - break; - } - } -} -#endif - boolean K_PlayerUsesBotMovement(player_t *player) { if (player->bot || player->exiting) diff --git a/src/k_grandprix.c b/src/k_grandprix.c new file mode 100644 index 000000000..b8f04aa6e --- /dev/null +++ b/src/k_grandprix.c @@ -0,0 +1,168 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2007-2016 by John "JTE" Muniz. +// Copyright (C) 2011-2018 by Sonic Team Junior. +// +// 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_grandprix.c +/// \brief Grand Prix mode specific code + +#include "k_grandprix.h" +#include "doomdef.h" +#include "d_player.h" +#include "g_game.h" +#include "k_bot.h" +#include "k_kart.h" +#include "m_random.h" +#include "r_things.h" + +UINT8 grandprixmatch = 0; +boolean initgpbots = false; + +void K_InitGrandPrixBots(void) +{ + const UINT8 defaultbotskin = 9; // eggrobo + + // startingdifficulty: Easy = 3, Normal = 6, Hard = 9 + const UINT8 startingdifficulty = min(MAXBOTDIFFICULTY, (gamespeed + 1) * 3); + UINT8 difficultylevels[MAXPLAYERS]; + + UINT8 playercount = 8; + UINT8 wantedbots = 0; + + UINT8 numplayers = 0; + UINT8 competitors[4]; + + boolean skinusable[MAXSKINS]; + UINT8 botskinlist[MAXPLAYERS]; + UINT8 botskinlistpos = 0; + + UINT8 newplayernum = 0; + UINT8 i; + + if (initgpbots != true) + { + return; + } + + memset(difficultylevels, MAXBOTDIFFICULTY, sizeof (difficultylevels)); + memset(competitors, MAXPLAYERS, sizeof (competitors)); + memset(botskinlist, defaultbotskin, sizeof (botskinlist)); + + // init usable bot skins list + for (i = 0; i < MAXSKINS; i++) + { + if (i < numskins) + { + skinusable[i] = true; + } + else + { + skinusable[i] = false; + } + } + +#if MAXPLAYERS != 16 + I_Error("GP bot difficulty levels need rebalacned for the new player count!\n"); +#endif + + // init difficulty levels list + //if (!mastermodebots) { // leave as all level 9 + difficultylevels[0] = max(1, startingdifficulty); + difficultylevels[1] = max(1, startingdifficulty-1); + difficultylevels[2] = max(1, startingdifficulty-2); + difficultylevels[3] = max(1, startingdifficulty-3); + difficultylevels[4] = max(1, startingdifficulty-3); + difficultylevels[5] = max(1, startingdifficulty-4); + difficultylevels[6] = max(1, startingdifficulty-4); + difficultylevels[7] = max(1, startingdifficulty-4); + difficultylevels[8] = max(1, startingdifficulty-5); + difficultylevels[9] = max(1, startingdifficulty-5); + difficultylevels[10] = max(1, startingdifficulty-5); + difficultylevels[11] = max(1, startingdifficulty-6); + difficultylevels[12] = max(1, startingdifficulty-6); + difficultylevels[13] = max(1, startingdifficulty-6); + difficultylevels[14] = max(1, startingdifficulty-7); + difficultylevels[15] = max(1, startingdifficulty-7); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + if (numplayers < MAXSPLITSCREENPLAYERS && !players[i].spectator) + { + competitors[numplayers] = i; + numplayers++; + } + else + { + players[i].spectator = true; // 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; + } + + wantedbots = playercount - numplayers; + + // Create rival list + + // TODO: Use player skin's set rivals + // Starting with P1's rival1, P2's rival1, P3's rival1, P4's rival1, + // then P1's rival2, P2's rival2, etc etc etc etc....... + // then skip over any duplicates. + + // Pad the remaining list with random skins if we need to + if (botskinlistpos < wantedbots) + { + for (i = botskinlistpos; i < wantedbots; i++) + { + UINT8 val = M_RandomKey(numskins); + UINT8 loops = 0; + + while (!skinusable[val]) + { + if (loops >= numskins) + { + // no more skins + break; + } + + val++; + + if (val >= numskins) + { + val = 0; + } + + loops++; + } + + if (loops >= numskins) + { + // leave the rest of the table as the default skin + break; + } + + botskinlist[i] = val; + skinusable[val] = false; + } + } + + for (i = 0; i < wantedbots; i++) + { + if (!K_AddBot(botskinlist[i], difficultylevels[i], &newplayernum)) + { + break; + } + } + + initgpbots = false; +} diff --git a/src/k_grandprix.h b/src/k_grandprix.h new file mode 100644 index 000000000..4644c43ca --- /dev/null +++ b/src/k_grandprix.h @@ -0,0 +1,18 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2007-2016 by John "JTE" Muniz. +// Copyright (C) 2012-2018 by Sonic Team Junior. +// +// 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_grandprix.h +/// \brief Grand Prix mode specific code + +#include "doomdef.h" + +extern UINT8 grandprixmatch; +extern boolean initgpbots; + +void K_InitGrandPrixBots(void); diff --git a/src/m_menu.c b/src/m_menu.c index 3abf64476..f9a9112ac 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -59,6 +59,7 @@ #include "k_kart.h" // SRB2kart #include "k_pwrlv.h" #include "d_player.h" // KITEM_ constants +#include "k_grandprix.h" #include "i_joy.h" // for joystick menu controls @@ -225,7 +226,7 @@ menu_t SP_MainDef, MP_MainDef, OP_MainDef; menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef, MISC_ChangeSpectateDef; // Single Player -//static void M_LoadGame(INT32 choice); +static void M_StartGrandPrix(INT32 choice); static void M_TimeAttack(INT32 choice); static boolean M_QuitTimeAttackMenu(void); static void M_BreakTheCapsules(INT32 choice); @@ -803,14 +804,14 @@ static menuitem_t SR_EmblemHintMenu[] = // Single Player Main static menuitem_t SP_MainMenu[] = { - //{IT_CALL | IT_STRING, NULL, "Grand Prix", M_LoadGame, 92}, - {IT_SECRET, NULL, "Time Attack", M_TimeAttack, 100}, - {IT_SECRET, NULL, "Break the Capsules", M_BreakTheCapsules, 108}, + {IT_CALL | IT_STRING, NULL, "Grand Prix", M_StartGrandPrix, 92}, + {IT_SECRET, NULL, "Time Attack", M_TimeAttack, 100}, + {IT_SECRET, NULL, "Break the Capsules", M_BreakTheCapsules, 108}, }; enum { - //spgrandprix, + spgrandprix, sptimeattack, spbreakthecapsules }; @@ -6568,6 +6569,8 @@ static void M_Credits(INT32 choice) static void M_SinglePlayerMenu(INT32 choice) { (void)choice; + + SP_MainMenu[spgrandprix].status = IT_CALL|IT_STRING; SP_MainMenu[sptimeattack].status = (M_SecretUnlocked(SECRET_TIMEATTACK)) ? IT_CALL|IT_STRING : IT_SECRET; SP_MainMenu[spbreakthecapsules].status = @@ -7646,6 +7649,20 @@ void M_DrawTimeAttackMenu(void) } } +// Start Grand Prix! +static void M_StartGrandPrix(INT32 choice) +{ + (void)choice; + + M_ClearMenus(true); + + grandprixmatch = 1; + initgpbots = true; + + G_DeferedInitNew(false, "MAP01", (UINT8)(cv_chooseskin.value-1), 0, false); // G_BuildMapName(startmap) +} + + // Going to Time Attack menu... static void M_TimeAttack(INT32 choice) { diff --git a/src/p_setup.c b/src/p_setup.c index d5891e84a..b4a2def48 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -88,6 +88,7 @@ #include "k_pwrlv.h" #include "k_waypoint.h" #include "k_bot.h" +#include "k_grandprix.h" // // Map MD5, calculated on level load. @@ -2426,9 +2427,6 @@ static void P_LevelInitStuff(void) memset(&battleovertime, 0, sizeof(struct battleovertime)); speedscramble = encorescramble = -1; - - //if (!grandprix) - K_UpdateMatchRaceBots(); } // @@ -3368,6 +3366,19 @@ boolean P_SetupLevel(boolean skipprecip) // NOW you can try to spawn in the Battle capsules, if there's not enough players for a match K_SpawnBattleCapsules(); + if (grandprixmatch == 0) + { + K_UpdateMatchRaceBots(); + } + else + { + if (initgpbots == true) + { + K_InitGrandPrixBots(); + initgpbots = false; + } + } + return true; }