diff --git a/src/game/activemenu.c b/src/game/activemenu.c index 7b024bb92..ca07b7aa8 100644 --- a/src/game/activemenu.c +++ b/src/game/activemenu.c @@ -94,7 +94,7 @@ s32 amPickTargetMenuList(s32 operation, struct menuitem *item, union handlerdata struct chrdata *playerchr = g_Vars.currentplayer->prop->chr; for (i = PLAYERCOUNT(); i < g_MpNumChrs; i++) { - if (g_MpAllChrPtrs[i]->team != playerchr->team) { + if (g_MpChrs[i].team != playerchr->team) { count++; } } @@ -116,18 +116,18 @@ s32 amPickTargetMenuList(s32 operation, struct menuitem *item, union handlerdata chrindex = -1; numremaining = data->list.value; - botchr = g_MpAllChrPtrs[g_Vars.currentplayer->aibuddynums[g_AmMenus[g_AmIndex].screenindex - 2]]; + botchr = g_MpChrs[g_Vars.currentplayer->aibuddynums[g_AmMenus[g_AmIndex].screenindex - 2]].chr; playerchr = g_Vars.currentplayer->prop->chr; do { chrindex++; if (g_AmMenus[g_AmIndex].prevallbots) { - if (playerchr == g_MpAllChrPtrs[chrindex] || playerchr->team != g_MpAllChrPtrs[chrindex]->team) { + if (playerchr == g_MpChrs[chrindex].chr || playerchr->team != g_MpChrs[chrindex].team) { numremaining--; } } else { - if (botchr != g_MpAllChrPtrs[chrindex]) { + if (botchr != g_MpChrs[chrindex].chr) { numremaining--; } } @@ -137,10 +137,10 @@ s32 amPickTargetMenuList(s32 operation, struct menuitem *item, union handlerdata g_AmMenus[g_AmIndex].prevallbots = false; for (i = 0; i < g_Vars.currentplayer->numaibuddies; i++) { - botApplyAttack(g_MpAllChrPtrs[g_Vars.currentplayer->aibuddynums[i]], g_MpAllChrPtrs[chrindex]->prop); + botApplyAttack(g_MpChrs[g_Vars.currentplayer->aibuddynums[i]].chr, g_MpChrs[chrindex].chr->prop); } } else { - botApplyAttack(botchr, g_MpAllChrPtrs[chrindex]->prop); + botApplyAttack(botchr, g_MpChrs[chrindex].chr->prop); } menuPopDialog(); @@ -158,24 +158,24 @@ s32 amPickTargetMenuList(s32 operation, struct menuitem *item, union handlerdata u32 colour; s32 numremaining = (s32)data->type19.unk04; s32 chrindex = -1; - struct chrdata *botchr = g_MpAllChrPtrs[g_Vars.currentplayer->aibuddynums[g_AmMenus[g_AmIndex].screenindex - 2]]; + struct chrdata *botchr = g_MpChrs[g_Vars.currentplayer->aibuddynums[g_AmMenus[g_AmIndex].screenindex - 2]].chr; struct chrdata *playerchr = g_Vars.currentplayer->prop->chr; do { chrindex++; if (g_AmMenus[g_AmIndex].prevallbots) { - if (playerchr == g_MpAllChrPtrs[chrindex] || playerchr->team != g_MpAllChrPtrs[chrindex]->team) { + if (playerchr == g_MpChrs[chrindex].chr || playerchr->team != g_MpChrs[chrindex].team) { numremaining--; } } else { - if (botchr != g_MpAllChrPtrs[chrindex]) { + if (botchr != g_MpChrs[chrindex].chr) { numremaining--; } } } while (numremaining >= 0); - colour = teamcolours[g_MpAllChrConfigPtrs[chrindex]->team] | (renderdata->colour & 0xff); + colour = teamcolours[g_MpChrs[chrindex].team] | (renderdata->colour & 0xff); if (renderdata->unk10) { u32 weight = menuGetSinOscFrac(40) * 255; @@ -186,7 +186,7 @@ s32 amPickTargetMenuList(s32 operation, struct menuitem *item, union handlerdata y = renderdata->y + 1; gdl = text0f153628(gdl); - gdl = textRenderProjected(gdl, &x, &y, g_MpAllChrConfigPtrs[chrindex]->name, g_CharsHandelGothicSm, g_FontHandelGothicSm, colour, viGetWidth(), viGetHeight(), 0, 0); + gdl = textRenderProjected(gdl, &x, &y, g_MpChrs[chrindex].config->name, g_CharsHandelGothicSm, g_FontHandelGothicSm, colour, viGetWidth(), viGetHeight(), 0, 0); gdl = text0f153780(gdl); return (s32)gdl; } @@ -335,10 +335,10 @@ void amApply(s32 slot) default: if (g_AmMenus[g_AmIndex].allbots) { for (i = 0; i < g_Vars.currentplayer->numaibuddies; i++) { - botcmdApply(g_MpAllChrPtrs[g_Vars.currentplayer->aibuddynums[i]], g_AmBotCommands[slot]); + botcmdApply(g_MpChrs[g_Vars.currentplayer->aibuddynums[i]].chr, g_AmBotCommands[slot]); } } else { - botcmdApply(g_MpAllChrPtrs[g_Vars.currentplayer->aibuddynums[g_AmMenus[g_AmIndex].screenindex - 2]], g_AmBotCommands[slot]); + botcmdApply(g_MpChrs[g_Vars.currentplayer->aibuddynums[g_AmMenus[g_AmIndex].screenindex - 2]].chr, g_AmBotCommands[slot]); } } } @@ -897,10 +897,10 @@ Gfx *amRenderAibotInfo(Gfx *gdl, s32 buddynum) if (!g_AmMenus[g_AmIndex].allbots) { buddynum = g_Vars.currentplayer->aibuddynums[buddynum]; - aibotname = g_MpAllChrConfigPtrs[buddynum]->name; + aibotname = g_MpChrs[buddynum].config->name; - if (g_MpAllChrPtrs[buddynum]->aibot) { - weaponnum = g_MpAllChrPtrs[buddynum]->aibot->weaponnum; + if (g_MpChrs[buddynum].chr->aibot) { + weaponnum = g_MpChrs[buddynum].chr->aibot->weaponnum; } else { weaponnum = 0; } @@ -957,7 +957,7 @@ Gfx *amRenderAibotInfo(Gfx *gdl, s32 buddynum) 0x000000ff, 320, 240, 0, 0); #endif - g_Vars.currentplayer->commandingaibot = g_MpAllChrPtrs[buddynum]; + g_Vars.currentplayer->commandingaibot = g_MpChrs[buddynum].chr; } else { char *title = langGet(L_MISC_215); // "All Simulants" @@ -1295,7 +1295,7 @@ Gfx *amRender(Gfx *gdl) if (mode == AMSLOTMODE_DEFAULT && g_AmMenus[g_AmIndex].screenindex >= 2) { s32 slotcmd = g_AmBotCommands[var800719a0[row][column]]; - s32 botcmd = g_MpAllChrPtrs[mpchrnum]->aibot->command; + s32 botcmd = g_MpChrs[mpchrnum].chr->aibot->command; if (slotcmd == botcmd) { mode = AMSLOTMODE_CURRENT; diff --git a/src/game/bondgun.c b/src/game/bondgun.c index 4c14ac833..cf5bfe97e 100644 --- a/src/game/bondgun.c +++ b/src/game/bondgun.c @@ -4266,7 +4266,7 @@ struct defaultobj *bgunCreateThrownProjectile2(struct chrdata *chr, struct gset obj->hidden &= 0x0fffffff; if (g_Vars.normmplayerisrunning) { - playernum = mpPlayerGetIndex(chr); + playernum = chr->chrnum; } else { playernum = playermgrGetPlayerNumByProp(chr->prop); } diff --git a/src/game/bondwalk.c b/src/game/bondwalk.c index 587700d93..42d258cae 100644 --- a/src/game/bondwalk.c +++ b/src/game/bondwalk.c @@ -634,7 +634,7 @@ void bwalk0f0c4d98(void) void bwalkUpdateSpeedSideways(f32 targetspeed, f32 accelspeed, s32 mult) { if (g_Vars.normmplayerisrunning) { - targetspeed = (g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].base.unk1c + 25.0f) / 100 * targetspeed; + targetspeed = (g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].unk1c + 25.0f) / 100 * targetspeed; } if (g_Vars.currentplayer->speedstrafe > targetspeed) { @@ -657,7 +657,7 @@ void bwalkUpdateSpeedSideways(f32 targetspeed, f32 accelspeed, s32 mult) void bwalkUpdateSpeedForwards(f32 targetspeed, f32 accelspeed) { if (g_Vars.normmplayerisrunning) { - targetspeed = (g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].base.unk1c + 25.0f) / 100 * targetspeed; + targetspeed = (g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].unk1c + 25.0f) / 100 * targetspeed; } if (g_Vars.currentplayer->speedgo < targetspeed) { diff --git a/src/game/bot.c b/src/game/bot.c index f6616be9f..869dbfdad 100644 --- a/src/game/bot.c +++ b/src/game/bot.c @@ -37,10 +37,6 @@ #define PICKUPCRITERIA_CRITICAL 1 #define PICKUPCRITERIA_ANY 2 -struct chrdata *g_MpBotChrPtrs[MAX_BOTS]; - -u8 g_BotCount = 0; - struct botdifficulty g_BotDifficulties[] = { // shootdelay // | unk04 @@ -261,8 +257,8 @@ void botSpawnAll(void) { s32 i; - for (i = 0; i < g_BotCount; i++) { - botSpawn(g_MpBotChrPtrs[i], false); + for (i = PLAYERCOUNT(); i < g_MpNumChrs; i++) { + botSpawn(g_MpChrs[i].chr, false); } } @@ -750,7 +746,7 @@ bool botIsAboutToAttack(struct chrdata *chr, bool arg1) if (chr->target != -1) { target = chrGetTargetProp(chr); - mpindex = mpPlayerGetIndex(target->chr); + mpindex = target->chr->chrnum; result = false; if (chr->aibot->chrsinsight[mpindex]) { @@ -873,7 +869,7 @@ s32 botTick(struct prop *prop) && aibot->chrdistances[aibot->followingplayernum] < 300 && aibot->unk1e4 >= g_Vars.lvframe60 - TICKS(60) && aibot->config->difficulty != BOTDIFF_MEAT) { - targetangle = chrGetInverseTheta(g_MpAllChrPtrs[aibot->followingplayernum]); + targetangle = chrGetInverseTheta(g_MpChrs[aibot->followingplayernum].chr); } else if (chr->myaction == MA_AIBOTDEFEND && aibot->unk1e4 >= g_Vars.lvframe60 - TICKS(60) && aibot->config->difficulty != BOTDIFF_MEAT) { @@ -1255,7 +1251,7 @@ void botSetTarget(struct chrdata *botchr, s32 propnum) if (propnum >= 0) { otherchr = (g_Vars.props + propnum)->chr; - index = mpPlayerGetIndex(otherchr); + index = otherchr->chrnum; botchr->aibot->targetinsight = botchr->aibot->chrsinsight[index]; botchr->aibot->targetlastseen60 = botchr->aibot->chrslastseen60[index]; @@ -1489,7 +1485,7 @@ void botChooseGeneralTarget(struct chrdata *botchr) // and update stats about that chr aibot->queryplayernum = (aibot->queryplayernum + 1) % g_MpNumChrs; - trychr = mpGetChrFromPlayerIndex(aibot->queryplayernum); + trychr = g_MpChrs[aibot->queryplayernum].chr; if (trychr != botchr) { // This condition passes on average once every 4 minutes per player. @@ -1558,8 +1554,8 @@ void botChooseGeneralTarget(struct chrdata *botchr) if (botchr->myaction == MA_AIBOTATTACK && aibot->attackingplayernum >= 0 && aibot->chrsinsight[aibot->attackingplayernum] - && !chrIsDead(g_MpAllChrPtrs[aibot->attackingplayernum])) { - botSetTarget(botchr, g_MpAllChrPtrs[aibot->attackingplayernum]->prop - g_Vars.props); + && !chrIsDead(g_MpChrs[aibot->attackingplayernum].chr)) { + botSetTarget(botchr, g_MpChrs[aibot->attackingplayernum].chr->prop - g_Vars.props); return; } @@ -1596,7 +1592,7 @@ void botChooseGeneralTarget(struct chrdata *botchr) for (tmp = 0; tmp < ARRAYCOUNT(aibot->chrnumsbydistanceasc); tmp++) { s32 i = aibot->chrnumsbydistanceasc[tmp]; - trychr = mpGetChrFromPlayerIndex(i); + trychr = g_MpChrs[i].chr; if (trychr != botchr && !chrIsDead(trychr) @@ -1627,7 +1623,7 @@ void botChooseGeneralTarget(struct chrdata *botchr) // Use closest out of sight chr if (closestavailablechrnum >= 0) { - trychr = mpGetChrFromPlayerIndex(closestavailablechrnum); + trychr = g_MpChrs[closestavailablechrnum].chr; botSetTarget(botchr, trychr->prop - g_Vars.props); return; } @@ -1639,7 +1635,7 @@ void botChooseGeneralTarget(struct chrdata *botchr) // Bot has an existing target // If they're still in sight, keep the target - playernum = mpPlayerGetIndex((g_Vars.props + botchr->target)->chr); + playernum = (g_Vars.props + botchr->target)->chr->chrnum; if (aibot->chrsinsight[playernum]) { botSetTarget(botchr, botchr->target); @@ -1650,7 +1646,7 @@ void botChooseGeneralTarget(struct chrdata *botchr) // Check for other chrs who are in sight, by distance for (i = 0; i < ARRAYCOUNT(aibot->chrnumsbydistanceasc); i++) { if (aibot->chrsinsight[aibot->chrnumsbydistanceasc[i]]) { - trychr = mpGetChrFromPlayerIndex(aibot->chrnumsbydistanceasc[i]); + trychr = g_MpChrs[aibot->chrnumsbydistanceasc[i]].chr; if (trychr != botchr && !chrIsDead(trychr) @@ -1683,7 +1679,7 @@ bool botCanFollow(struct chrdata *botchr, struct chrdata *leader) break; } - leader = g_MpAllChrPtrs[aibot->followingplayernum]; + leader = g_MpChrs[aibot->followingplayernum].chr; if (leader == botchr) { // Can't follow - it would create a follow loop @@ -1707,10 +1703,12 @@ s32 botFindTeammateToFollow(struct chrdata *chr, f32 range) s32 i; for (i = 0; i < g_MpNumChrs; i++) { - if (chr != g_MpAllChrPtrs[i] - && !chrIsDead(g_MpAllChrPtrs[i]) - && chr->team == g_MpAllChrPtrs[i]->team - && botCanFollow(chr, g_MpAllChrPtrs[i])) { + struct chrdata *loopchr = g_MpChrs[i].chr; + + if (chr != loopchr + && !chrIsDead(loopchr) + && chr->team == loopchr->team + && botCanFollow(chr, loopchr)) { f32 distance = chr->aibot->chrdistances[i]; if (closestplayernum < 0 || distance < closestdistance) { @@ -2221,7 +2219,7 @@ s32 botGetTeamSize(struct chrdata *chr) s32 i; for (i = 0; i < g_MpNumChrs; i++) { - if (chr->team == g_MpAllChrPtrs[i]->team) { + if (chr->team == g_MpChrs[i].team) { count++; } } @@ -2235,9 +2233,9 @@ s32 botGetCountInTeamDoingCommand(struct chrdata *self, u32 command, bool includ s32 i; for (i = PLAYERCOUNT(); i < g_MpNumChrs; i++) { - if (self->team == g_MpAllChrPtrs[i]->team) { - if (includeself || self != g_MpAllChrPtrs[i]) { - if (command == g_MpAllChrPtrs[i]->aibot->command) { + if (self->team == g_MpChrs[i].team) { + if (includeself || self != g_MpChrs[i].chr) { + if (command == g_MpChrs[i].chr->aibot->command) { count++; } } @@ -2249,7 +2247,7 @@ s32 botGetCountInTeamDoingCommand(struct chrdata *self, u32 command, bool includ s32 botIsChrsCtcTokenHeld(struct chrdata *chr) { - struct mpchrconfig *mpchr = g_MpAllChrConfigPtrs[mpPlayerGetIndex(chr)]; + struct mpchr *mpchr = &g_MpChrs[chr->chrnum]; struct prop *prop = g_ScenarioData.ctc.tokens[mpchr->team]; return prop && (prop->type == PROPTYPE_CHR || prop->type == PROPTYPE_PLAYER); @@ -2278,10 +2276,10 @@ s32 botGetNumTeammatesDefendingHill(struct chrdata *bot) s32 i; for (i = 0; i < g_MpNumChrs; i++) { - if (bot->team == g_MpAllChrPtrs[i]->team - && g_MpAllChrPtrs[i]->prop->rooms[0] == g_ScenarioData.koh.hillrooms[0]) { - if (g_MpAllChrPtrs[i]->aibot->command == AIBOTCMD_DEFHILL - || g_MpAllChrPtrs[i]->aibot->command == AIBOTCMD_HOLDHILL) { + struct chrdata *chr = g_MpChrs[i].chr; + + if (bot->team == chr->team && chr->prop->rooms[0] == g_ScenarioData.koh.hillrooms[0]) { + if (chr->aibot->command == AIBOTCMD_DEFHILL || chr->aibot->command == AIBOTCMD_HOLDHILL) { count++; } } @@ -2298,17 +2296,15 @@ s32 botGetNumTeammatesDefendingHill(struct chrdata *bot) */ s32 botGetNumOpponentsInHill(struct chrdata *chr) { - struct mpchrconfig *mpchr = g_MpAllChrConfigPtrs[mpPlayerGetIndex(chr)]; - struct mpchrconfig *loopmpchr; + struct mpchr *mpchr = &g_MpChrs[chr->chrnum]; + struct mpchr *loopmpchr; s32 countsperteam[8] = {0}; s32 max = 0; s32 i; for (i = 0; i < g_MpNumChrs; i++) { - if (g_MpAllChrPtrs[i]->prop->rooms[0] == g_ScenarioData.koh.hillrooms[0]) { - s32 mpindex = func0f18d074(i); - - loopmpchr = MPCHR(mpindex); + if (g_MpChrs[i].chr->prop->rooms[0] == g_ScenarioData.koh.hillrooms[0]) { + loopmpchr = &g_MpChrs[i]; if (loopmpchr->team != mpchr->team) { countsperteam[loopmpchr->team]++; @@ -2588,7 +2584,7 @@ void botTickUnpaused(struct chrdata *chr) // KazeSim will attack people on sight regardless of command if (aibot->config->type == BOTTYPE_KAZE && chr->target != -1 && aibot->targetinsight) { newaction = MA_AIBOTATTACK; - aibot->attackingplayernum = mpPlayerGetIndex(chrGetTargetProp(chr)->chr); + aibot->attackingplayernum = chrGetTargetProp(chr)->chr->chrnum; aibot->abortattacktimer60 = -1; } @@ -2612,7 +2608,7 @@ void botTickUnpaused(struct chrdata *chr) && !botIsTargetInvisible(chr, targetchr) && botPassesCowardCheck(chr, targetchr)) { newaction = MA_AIBOTATTACK; - aibot->attackingplayernum = mpPlayerGetIndex(targetchr); + aibot->attackingplayernum = targetchr->chrnum; aibot->abortattacktimer60 = -1; } } else if (aibot->command == AIBOTCMD_FOLLOW) { @@ -2620,13 +2616,13 @@ void botTickUnpaused(struct chrdata *chr) // This is a human command only newaction = MA_AIBOTFOLLOW; aibot->canbreakfollow = true; - aibot->followingplayernum = mpPlayerGetIndex((g_Vars.props + aibot->followprotectpropnum)->chr); + aibot->followingplayernum = (g_Vars.props + aibot->followprotectpropnum)->chr->chrnum; } else if (aibot->command == AIBOTCMD_PROTECT) { // Protect the prop (player) given in followprotectpropnum // This is a human command only newaction = MA_AIBOTFOLLOW; aibot->canbreakfollow = false; - aibot->followingplayernum = mpPlayerGetIndex((g_Vars.props + aibot->followprotectpropnum)->chr); + aibot->followingplayernum = (g_Vars.props + aibot->followprotectpropnum)->chr->chrnum; } else if (aibot->command == AIBOTCMD_DEFEND) { // Defend the position given in defendholdpos // This is a human command only @@ -2642,7 +2638,7 @@ void botTickUnpaused(struct chrdata *chr) if (g_MpSetup.scenario == MPSCENARIO_CAPTURETHECASE && !aibot->hascase) { // Make an array of pointers to other teams' tokens // but ignore enemy tokens held by other teams - s32 botteamindex = radarGetTeamIndex(chr->team); + s32 botteamindex = chr->team; s32 i; struct prop *tokens[4]; s32 numtokens = 0; @@ -2700,7 +2696,7 @@ void botTickUnpaused(struct chrdata *chr) } else if (botCanFollow(chr, tokens[index]->chr)) { newaction = MA_AIBOTFOLLOW; aibot->canbreakfollow = random() % 4 == 0; - aibot->followingplayernum = mpPlayerGetIndex(tokens[index]->chr); + aibot->followingplayernum = tokens[index]->chr->chrnum; } } } @@ -2708,7 +2704,7 @@ void botTickUnpaused(struct chrdata *chr) // Capture the case - recover/protect bot's own token if (g_MpSetup.scenario == MPSCENARIO_CAPTURETHECASE) { // Find out where the bot's token is - struct prop *token = g_ScenarioData.ctc.tokens[radarGetTeamIndex(chr->team)]; + struct prop *token = g_ScenarioData.ctc.tokens[chr->team]; if (token->type == PROPTYPE_CHR || token->type == PROPTYPE_PLAYER) { struct chrdata *tokenchr = token->chr; @@ -2718,7 +2714,7 @@ void botTickUnpaused(struct chrdata *chr) if (botCanFollow(chr, tokenchr)) { newaction = MA_AIBOTFOLLOW; aibot->canbreakfollow = random() % 4 == 0; - aibot->followingplayernum = mpPlayerGetIndex(tokenchr); + aibot->followingplayernum = tokenchr->chrnum; } } else { // Held by an opponent - attack them @@ -2726,7 +2722,7 @@ void botTickUnpaused(struct chrdata *chr) && !botIsTargetInvisible(chr, tokenchr) && botPassesCowardCheck(chr, tokenchr)) { newaction = MA_AIBOTATTACK; - aibot->attackingplayernum = mpPlayerGetIndex(tokenchr); + aibot->attackingplayernum = tokenchr->chrnum; aibot->abortattacktimer60 = -1; } } @@ -2749,7 +2745,7 @@ void botTickUnpaused(struct chrdata *chr) && botPassesCowardCheck(chr, chrGetTargetProp(chr)->chr)) { // Bot is in the hill and sees target - attack them newaction = MA_AIBOTATTACK; - aibot->attackingplayernum = mpPlayerGetIndex(chrGetTargetProp(chr)->chr); + aibot->attackingplayernum = chrGetTargetProp(chr)->chr->chrnum; aibot->abortattacktimer60 = TICKS(300); } else { // Go to the hill if not there already @@ -2808,13 +2804,13 @@ void botTickUnpaused(struct chrdata *chr) if (botCanFollow(chr, uplinkchr)) { newaction = MA_AIBOTFOLLOW; aibot->canbreakfollow = random() % 4 == 0; - aibot->followingplayernum = mpPlayerGetIndex(uplinkchr); + aibot->followingplayernum = uplinkchr->chrnum; } } else { // Uplink is held by opponent - attack them if (!botIsTargetInvisible(chr, uplinkchr) && botPassesCowardCheck(chr, uplinkchr)) { newaction = MA_AIBOTATTACK; - aibot->attackingplayernum = mpPlayerGetIndex(uplinkchr); + aibot->attackingplayernum = uplinkchr->chrnum; aibot->abortattacktimer60 = -1; } } @@ -2839,12 +2835,12 @@ void botTickUnpaused(struct chrdata *chr) if (botCanFollow(chr, tokenchr)) { newaction = MA_AIBOTFOLLOW; aibot->canbreakfollow = random() % 4 == 0; - aibot->followingplayernum = mpPlayerGetIndex(tokenchr); + aibot->followingplayernum = tokenchr->chrnum; } } else if (!botIsTargetInvisible(chr, tokenchr) && botPassesCowardCheck(chr, tokenchr)) { // Briefcase is held by opponent - attack them newaction = MA_AIBOTATTACK; - aibot->attackingplayernum = mpPlayerGetIndex(tokenchr); + aibot->attackingplayernum = tokenchr->chrnum; aibot->abortattacktimer60 = -1; } } else { @@ -2856,7 +2852,7 @@ void botTickUnpaused(struct chrdata *chr) } else if (aibot->command == AIBOTCMD_POPCAP) { // Pop a cap - attack the target if (g_MpSetup.scenario == MPSCENARIO_POPACAP && g_ScenarioData.pac.victimindex >= 0) { - struct prop *victimprop = g_MpAllChrPtrs[g_ScenarioData.pac.victims[g_ScenarioData.pac.victimindex]]->prop; + struct prop *victimprop = g_MpChrs[g_ScenarioData.pac.victims[g_ScenarioData.pac.victimindex]].chr->prop; if (victimprop != chr->prop) { // Victim is not the current bot @@ -2867,13 +2863,13 @@ void botTickUnpaused(struct chrdata *chr) if (botCanFollow(chr, victimchr)) { newaction = MA_AIBOTFOLLOW; aibot->canbreakfollow = random() % 4 == 0; - aibot->followingplayernum = mpPlayerGetIndex(victimchr); + aibot->followingplayernum = victimchr->chrnum; } } else { // Victim is an opponent - attack them if (!botIsTargetInvisible(chr, victimchr) && botPassesCowardCheck(chr, victimchr)) { newaction = MA_AIBOTATTACK; - aibot->attackingplayernum = mpPlayerGetIndex(victimchr); + aibot->attackingplayernum = victimchr->chrnum; aibot->abortattacktimer60 = -1; } } @@ -2903,7 +2899,7 @@ void botTickUnpaused(struct chrdata *chr) } } else if (g_MpSetup.scenario == MPSCENARIO_POPACAP) { if (g_ScenarioData.pac.victimindex >= 0) { - struct prop *victimprop = g_MpAllChrPtrs[g_ScenarioData.pac.victims[g_ScenarioData.pac.victimindex]]->prop; + struct prop *victimprop = g_MpChrs[g_ScenarioData.pac.victims[g_ScenarioData.pac.victimindex]].chr->prop; if (victimprop == chr->prop) { // Current bot is the victim - follow a teammate for protection @@ -2924,7 +2920,7 @@ void botTickUnpaused(struct chrdata *chr) // If the bot is holding an opponent's token, take it home if (botShouldReturnCtcToken(chr)) { struct pad pad; - s32 teamindex = g_ScenarioData.ctc.teamindexes[radarGetTeamIndex(chr->team)]; + s32 teamindex = g_ScenarioData.ctc.teamindexes[chr->team]; newaction = MA_AIBOTGOTOPOS; padUnpack(g_ScenarioData.ctc.spawnpadsperteam[teamindex].homepad, PADFIELD_POS | PADFIELD_ROOM, &pad); aibot->gotopos.x = pad.pos.x; @@ -2937,7 +2933,7 @@ void botTickUnpaused(struct chrdata *chr) } else if (g_MpSetup.scenario == MPSCENARIO_HACKERCENTRAL) { // If the bot has the uplink, go to the terminal if (g_ScenarioData.htm.uplink == chr->prop) { - if (g_ScenarioData.htm.playernuminrange != mpPlayerGetIndex(chr)) { + if (g_ScenarioData.htm.playernuminrange != chr->chrnum) { newaction = MA_AIBOTGOTOPROP; aibot->gotoprop = g_ScenarioData.htm.terminals[0].prop; } else { @@ -2952,7 +2948,7 @@ void botTickUnpaused(struct chrdata *chr) if (aibot->config->type == BOTTYPE_VENGE) { // Attack the last player who killed the bot if (aibot->lastkilledbyplayernum >= 0 - && !botIsTargetInvisible(chr, g_MpAllChrPtrs[aibot->lastkilledbyplayernum])) { + && !botIsTargetInvisible(chr, g_MpChrs[aibot->lastkilledbyplayernum].chr)) { newaction = MA_AIBOTATTACK; aibot->attackingplayernum = aibot->lastkilledbyplayernum; aibot->abortattacktimer60 = -1; @@ -2961,11 +2957,11 @@ void botTickUnpaused(struct chrdata *chr) // Attack a single player the whole match if (aibot->feudplayernum < 0 && aibot->lastkilledbyplayernum >= 0 - && !chrCompareTeams(chr, g_MpAllChrPtrs[aibot->lastkilledbyplayernum], COMPARE_FRIENDS)) { + && !chrCompareTeams(chr, g_MpChrs[aibot->lastkilledbyplayernum].chr, COMPARE_FRIENDS)) { aibot->feudplayernum = aibot->lastkilledbyplayernum; } - if (aibot->feudplayernum >= 0 && !botIsTargetInvisible(chr, g_MpAllChrPtrs[aibot->feudplayernum])) { + if (aibot->feudplayernum >= 0 && !botIsTargetInvisible(chr, g_MpChrs[aibot->feudplayernum].chr)) { newaction = MA_AIBOTATTACK; aibot->abortattacktimer60 = -1; aibot->attackingplayernum = aibot->feudplayernum; @@ -2977,8 +2973,8 @@ void botTickUnpaused(struct chrdata *chr) s32 i; for (i = 0; i < count; i++) { - s32 playernum = func0f18d0e8(rankings[i].chrnum); - struct chrdata *otherchr = mpGetChrFromPlayerIndex(playernum); + s32 playernum = rankings[i].chrnum; + struct chrdata *otherchr = g_MpChrs[playernum].chr; if (otherchr != chr && !chrIsDead(otherchr)) { #if PAL @@ -3000,7 +2996,7 @@ void botTickUnpaused(struct chrdata *chr) s32 i; for (i = 0; i < g_MpNumChrs; i++) { - struct chrdata *otherchr = mpGetChrFromPlayerIndex(i); + struct chrdata *otherchr = g_MpChrs[i].chr; if (otherchr != chr && !chrIsDead(otherchr) @@ -3131,7 +3127,7 @@ void botTickUnpaused(struct chrdata *chr) } } else if (chr->myaction == MA_AIBOTATTACK) { if (aibot->attackingplayernum >= 0 - && (chrIsDead(g_MpAllChrPtrs[aibot->attackingplayernum]) || !botPassesCowardCheck(chr, g_MpAllChrPtrs[aibot->attackingplayernum]))) { + && (chrIsDead(g_MpChrs[aibot->attackingplayernum].chr) || !botPassesCowardCheck(chr, g_MpChrs[aibot->attackingplayernum].chr))) { chr->myaction = MA_AIBOTMAINLOOP; } else if (aibot->attackingplayernum < 0 && (chr->target == -1 @@ -3149,7 +3145,7 @@ void botTickUnpaused(struct chrdata *chr) } } else if (chr->myaction == MA_AIBOTFOLLOW) { if (aibot->followingplayernum < 0 - || chrIsDead(g_MpAllChrPtrs[aibot->followingplayernum])) { + || chrIsDead(g_MpChrs[aibot->followingplayernum].chr)) { chr->myaction = MA_AIBOTMAINLOOP; } else { botcmdTickDistMode(chr); @@ -3158,8 +3154,8 @@ void botTickUnpaused(struct chrdata *chr) && chr->target != -1 && aibot->targetinsight && botPassesCowardCheck(chr, chrGetTargetProp(chr)->chr)) { - f32 xdist = chr->prop->pos.x - g_MpAllChrPtrs[aibot->followingplayernum]->prop->pos.x; - f32 zdist = chr->prop->pos.z - g_MpAllChrPtrs[aibot->followingplayernum]->prop->pos.z; + f32 xdist = chr->prop->pos.x - g_MpChrs[aibot->followingplayernum].chr->prop->pos.x; + f32 zdist = chr->prop->pos.z - g_MpChrs[aibot->followingplayernum].chr->prop->pos.z; if (xdist < 0) { xdist = -xdist; @@ -3172,7 +3168,7 @@ void botTickUnpaused(struct chrdata *chr) // No y check? if (xdist < 500 && zdist < 500) { chr->myaction = MA_AIBOTATTACK; - aibot->attackingplayernum = mpPlayerGetIndex(chrGetTargetProp(chr)->chr); + aibot->attackingplayernum = chrGetTargetProp(chr)->chr->chrnum; aibot->abortattacktimer60 = TICKS(300); aibot->distmode = -1; } @@ -3213,7 +3209,7 @@ void botTickUnpaused(struct chrdata *chr) && aibot->targetinsight && botPassesCowardCheck(chr, chrGetTargetProp(chr)->chr)) { chr->myaction = MA_AIBOTATTACK; - aibot->attackingplayernum = mpPlayerGetIndex(chrGetTargetProp(chr)->chr); + aibot->attackingplayernum = chrGetTargetProp(chr)->chr->chrnum; aibot->abortattacktimer60 = TICKS(300); aibot->distmode = -1; } @@ -3254,13 +3250,13 @@ void botTickUnpaused(struct chrdata *chr) // empty } else if (g_MpSetup.scenario == MPSCENARIO_HACKERCENTRAL && g_ScenarioData.htm.uplink == chr->prop - && g_ScenarioData.htm.playernuminrange == mpPlayerGetIndex(chr)) { + && g_ScenarioData.htm.playernuminrange == chr->chrnum) { chr->myaction = MA_AIBOTMAINLOOP; } } else if (chr->myaction == MA_AIBOTDOWNLOAD) { if (botCanDoCriticalPickup(chr)) { chr->myaction = MA_AIBOTMAINLOOP; - } else if (g_ScenarioData.htm.playernuminrange != mpPlayerGetIndex(chr)) { + } else if (g_ScenarioData.htm.playernuminrange != chr->chrnum) { chr->myaction = MA_AIBOTMAINLOOP; } } @@ -3269,7 +3265,7 @@ void botTickUnpaused(struct chrdata *chr) // route to them, even if it won't be followed botChooseGeneralTarget(chr); - if (mpPlayerGetIndex(chr) == (g_Vars.lvframenum % g_MpNumChrs) && chr->target != -1) { + if (chr->chrnum == (g_Vars.lvframenum % g_MpNumChrs) && chr->target != -1) { struct prop *targetprop = chrGetTargetProp(chr); struct waypoint *first = waypointFindClosestToPos(&chr->prop->pos, chr->prop->rooms); struct waypoint *last = waypointFindClosestToPos(&targetprop->pos, targetprop->rooms); diff --git a/src/game/botact.c b/src/game/botact.c index e823b5343..b010cfe10 100644 --- a/src/game/botact.c +++ b/src/game/botact.c @@ -223,8 +223,8 @@ bool botactShootFarsight(struct chrdata *chr, s32 arg1, struct coord *vector, st s32 value = fallback; for (i = 0; i < g_MpNumChrs; i++) { - oppchr = g_MpAllChrPtrs[i]; - oppprop = g_MpAllChrPtrs[i]->prop; + oppchr = g_MpChrs[i].chr; + oppprop = oppchr->prop; if (oppprop->type == PROPTYPE_PLAYER) { struct player *player = g_Vars.players[playermgrGetPlayerNumByProp(oppprop)]; diff --git a/src/game/botcmd.c b/src/game/botcmd.c index e9fcbfcb1..f8f671416 100644 --- a/src/game/botcmd.c +++ b/src/game/botcmd.c @@ -59,7 +59,7 @@ void botcmdTickDistMode(struct chrdata *chr) if (chr->myaction == MA_AIBOTFOLLOW && aibot->followingplayernum >= 0) { limits = g_BotDistConfigs[BOTDISTCFG_FOLLOW]; - targetprop = g_MpAllChrPtrs[aibot->followingplayernum]->prop; + targetprop = g_MpChrs[aibot->followingplayernum].chr->prop; insight = aibot->chrsinsight[aibot->followingplayernum]; if (chr->target != -1 && (confignum == BOTDISTCFG_CLOSE || confignum == BOTDISTCFG_KAZE)) { @@ -78,7 +78,7 @@ void botcmdTickDistMode(struct chrdata *chr) limits = g_BotDistConfigs[confignum]; if (chr->myaction == MA_AIBOTATTACK && aibot->attackingplayernum >= 0) { - targetprop = g_MpAllChrPtrs[aibot->attackingplayernum]->prop; + targetprop = g_MpChrs[aibot->attackingplayernum].chr->prop; insight = aibot->chrsinsight[aibot->attackingplayernum]; } else if (chr->target != -1) { targetprop = chrGetTargetProp(chr); diff --git a/src/game/botinv.c b/src/game/botinv.c index 56396e643..157695623 100644 --- a/src/game/botinv.c +++ b/src/game/botinv.c @@ -633,7 +633,7 @@ void botinvScoreWeapon(struct chrdata *chr, s32 weaponnum, s32 funcnum, s32 arg3 if (chr->aibot->config->difficulty > BOTDIFF_MEAT) { if (comparewithtarget) { if (chr->target != -1 - && chr->aibot->chrsinsight[mpPlayerGetIndex(chrGetTargetProp(chr)->chr)] == 0 + && chr->aibot->chrsinsight[chrGetTargetProp(chr)->chr->chrnum] == 0 && (chr->aibot->random1 % 2) == 0) { score1 += 10; } else { @@ -650,7 +650,7 @@ void botinvScoreWeapon(struct chrdata *chr, s32 weaponnum, s32 funcnum, s32 arg3 if (chr->aibot->config->difficulty >= BOTDIFF_NORMAL) { if (comparewithtarget) { if (chr->target != -1 - && chr->aibot->chrsinsight[mpPlayerGetIndex(chrGetTargetProp(chr)->chr)] == 0 + && chr->aibot->chrsinsight[chrGetTargetProp(chr)->chr->chrnum] == 0 && (chr->aibot->random1 % 2) == 0) { score1 = 178; score2 = 188; @@ -983,8 +983,8 @@ void botinvTick(struct chrdata *chr) if (newweaponnum == WEAPON_COMBATKNIFE && botactGetAmmoQuantityByWeapon(aibot, WEAPON_COMBATKNIFE, FUNC_SECONDARY, true) >= 2 && chr->target != -1 - && chr->aibot->chrdistances[mpPlayerGetIndex(chrGetTargetProp(chr)->chr)] > 200 - && chr->aibot->chrdistances[mpPlayerGetIndex(chrGetTargetProp(chr)->chr)] < 1500) { + && chr->aibot->chrdistances[chrGetTargetProp(chr)->chr->chrnum] > 200 + && chr->aibot->chrdistances[chrGetTargetProp(chr)->chr->chrnum] < 1500) { newfuncnum = FUNC_SECONDARY; } diff --git a/src/game/botmgr.c b/src/game/botmgr.c index 8d2b16c28..8220c29aa 100644 --- a/src/game/botmgr.c +++ b/src/game/botmgr.c @@ -14,18 +14,7 @@ #include "data.h" #include "types.h" -void botmgrRemoveAll(void) -{ - s32 i; - - for (i = 0; i < MAX_BOTS; i++) { - g_MpBotChrPtrs[i] = NULL; - } - - g_BotCount = 0; -} - -void botmgrAllocateBot(s32 chrnum, s32 aibotnum) +void botmgrAllocateBot(s32 chrnum, s32 botcfgnum, s32 botnum) { s16 rooms[1]; struct prop *prop; @@ -38,8 +27,8 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum) rooms[0] = -1; - headnum = mpGetHeadId(g_BotConfigsArray[aibotnum].base.mpheadnum); - bodynum = mpGetBodyId(g_BotConfigsArray[aibotnum].base.mpbodynum); + headnum = mpGetHeadId(g_BotConfigsArray[botcfgnum].base.mpheadnum); + bodynum = mpGetBodyId(g_BotConfigsArray[botcfgnum].base.mpbodynum); model = bodyAllocateModel(bodynum, headnum, 0); @@ -55,6 +44,8 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum) chr = prop->chr; + g_MpChrs[chrnum].chr = chr; + chrSetChrnum(chr, chrnum); chr->chrnum = chrnum; @@ -67,215 +58,204 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum) chr->race = bodyGetRace(chr->bodynum); chr->flags = CHRFLAG0_CAN_EXAMINE_BODY; // reused flag? chr->flags2 = 0; - chr->team = 1 << g_BotConfigsArray[aibotnum].base.team; + chr->team = g_BotConfigsArray[botcfgnum].base.team; chr->squadron = 0; - if (g_BotCount < MAX_BOTS) { - g_MpBotChrPtrs[g_BotCount] = chr; - g_BotCount++; + aibot = mempAlloc(sizeof(struct aibot), MEMPOOL_STAGE); + chr->aibot = aibot; - aibot = mempAlloc(sizeof(struct aibot), MEMPOOL_STAGE); - chr->aibot = aibot; - - if (aibot == NULL) { - g_MpBotChrPtrs[--g_BotCount] = NULL; - return; - } - - aibot->chrdistances = mempAlloc(MAX_MPCHRS * sizeof(f32), MEMPOOL_STAGE); - aibot->chrsinsight = mempAlloc(MAX_MPCHRS * sizeof(u8), MEMPOOL_STAGE); - aibot->chrslastseen60 = mempAlloc(MAX_MPCHRS * sizeof(s32), MEMPOOL_STAGE); - aibot->chrrooms = mempAlloc(MAX_MPCHRS * sizeof(s8), MEMPOOL_STAGE); - - if (!aibot->chrdistances || !aibot->chrsinsight || !aibot->chrslastseen60 || !aibot->chrrooms) { - g_MpBotChrPtrs[--g_BotCount] = NULL; - return; - } - - chr->tude = 0; - chr->voicebox = random() % 3; - - if (g_HeadsAndBodies[chr->bodynum].ismale == false) { - chr->voicebox = VOICEBOX_FEMALE; - } - - chr->target = -1; - chr->naturalanim = 0; - chr->myspecial = -1; - chr->yvisang = 0; - chr->teamscandist = 0; - chr->convtalk = 0; - chr->myaction = MA_AIBOTMAINLOOP; - - g_MpAllChrPtrs[g_MpNumChrs] = chr; - g_MpAllChrConfigPtrs[g_MpNumChrs] = &g_BotConfigsArray[aibotnum].base; - g_MpNumChrs++; - - aibot->ammoheld = mempAlloc(36 * sizeof(s32), MEMPOOL_STAGE); - - for (i = 0; i < 33; i++) { - aibot->ammoheld[i] = 0; - } - - aibot->config = &g_BotConfigsArray[aibotnum]; - - switch (g_BotConfigsArray[aibotnum].difficulty) { - case BOTDIFF_MEAT: - aibot->followchance = 0; - break; - case BOTDIFF_EASY: - aibot->followchance = 10; - break; - default: - case BOTDIFF_NORMAL: - aibot->followchance = 20; - break; - case BOTDIFF_HARD: - aibot->followchance = 40; - break; - case BOTDIFF_PERFECT: - aibot->followchance = 60; - break; - case BOTDIFF_DARK: - aibot->followchance = 0; - break; - } - - aibot->aibotnum = aibotnum; - aibot->unk064 = 0; - aibot->gotoprop = NULL; - aibot->timeuntilreload60[0] = 0; - aibot->timeuntilreload60[1] = 0; - aibot->throwtimer60 = 0; - aibot->unk040 = 0.0f; - aibot->loadedammo[0] = 0; - aibot->loadedammo[1] = 0; - aibot->unk058 = 0; - aibot->unk059 = 0; - aibot->nextbullettimer60[0] = 0; - aibot->nextbullettimer60[1] = 0; - aibot->unk030 = 301; - aibot->unk038 = 0; - aibot->punchtimer60[HAND_LEFT] = -1; - aibot->punchtimer60[HAND_RIGHT] = 0; - aibot->attackingplayernum = -1; - aibot->followingplayernum = -1; - aibot->dangerouspropnum = -1; - aibot->unk068 = 0; - aibot->unk06c = 0.0f; - aibot->unk070 = 0.0f; - aibot->distmode = -1; - aibot->lastkilledbyplayernum = -1; - aibot->feudplayernum = -1; - aibot->command = AIBOTCMD_NORMAL; - aibot->unk098 = 0.0f; - - aibot->defendholdpos.x = pos.x; - aibot->defendholdpos.y = pos.y; - aibot->defendholdpos.z = pos.z; - - aibot->weaponnum = WEAPON_UNARMED; - - aibot->burstsdone[0] = 0; - aibot->burstsdone[1] = 0; - aibot->skrocket = NULL; - aibot->unk0a0 = 0; - - aibot->gunfunc = FUNC_PRIMARY; - aibot->iscloserangeweapon = true; - aibot->teamisonlyai = false; - aibot->hasbriefcase = false; - aibot->hascase = false; - aibot->cloakdeviceenabled = false; - aibot->rcp120cloakenabled = false; - aibot->unk04c_04 = false; - aibot->unk04c_03 = false; - aibot->hasuplink = false; - aibot->unk04c_00 = false; - - aibot->hillpadnum = -1; - aibot->hillcovernum = -1; - - aibot->lastknownhill = -1; - aibot->cyclonedischarging[HAND_LEFT] = false; - aibot->cyclonedischarging[HAND_RIGHT] = false; - aibot->changeguntimer60 = 0; - aibot->distmodettl60 = 0; - aibot->forcemainloop = false; - aibot->returntodefendtimer60 = 0; - aibot->reaperspeed[HAND_LEFT] = 0; - aibot->reaperspeed[HAND_RIGHT] = 0; - aibot->maulercharge[HAND_LEFT] = 0.0f; - aibot->maulercharge[HAND_RIGHT] = 0.0f; - aibot->unk0a4 = model0001ae44(chr->model); - aibot->angleoffset = 0.0f; - aibot->speedtheta = 0.0f; - aibot->unk0b0 = model0001ae44(chr->model); - - aibot->unk0b4 = 0.0f; - aibot->unk0b8 = 0.0f; - aibot->shotspeed.x = 0.0f; - aibot->shotspeed.y = 0.0f; - aibot->shotspeed.z = 0.0f; - aibot->commandtimer60 = 0; - aibot->shootdelaytimer60 = 0; - aibot->targetlastseen60 = -1; - aibot->lastseenanytarget60 = -1; - aibot->targetinsight = false; - aibot->queryplayernum = 0; - - for (i = 0; i < ARRAYCOUNT(aibot->chrnumsbydistanceasc); i++) { - aibot->chrnumsbydistanceasc[i] = -1; - } - - for (i = 0; i < MAX_MPCHRS; i++) { - aibot->chrdistances[i] = U32_MAX; - aibot->chrsinsight[i] = 0; - aibot->chrslastseen60[i] = -1; - aibot->chrrooms[i] = -1; - } - - aibot->unk1c0 = 0.0f; - aibot->unk1c4 = 0.0f; - aibot->unk1c8 = 0.0f; - aibot->unk1cc = -1; - aibot->unk1d0 = 0; - aibot->unk1d4 = 0.0f; - aibot->unk1e4 = -1; - aibot->waypoints[0] = NULL; - aibot->unk208 = 0; - aibot->random1 = random(); - aibot->random1ttl60 = 0; - - for (i = 0; i < 6; i++) { - aibot->killsbygunfunc[i][0] = 0.0f; - aibot->killsbygunfunc[i][1] = 0.0f; - - aibot->suicidesbygunfunc[i][0] = 0.0f; - aibot->suicidesbygunfunc[i][1] = 0.0f; - - aibot->equipdurations60[i][0] = 0; - aibot->equipdurations60[i][1] = 0; - - aibot->unk2a8[i] = 0; - } - - aibot->unk2a4 = 0; - aibot->dampensuicidesttl60 = 0; - aibot->unk2c4 = 0.0f; - aibot->targetcloaktimer60 = 0; - aibot->canseecloaked = false; - - aibot->random2ttl60 = 0; - aibot->random2 = random(); - aibot->randomfrac = RANDOMFRAC(); - aibot->cheap = false; - aibot->unk078 = 0; - aibot->unk050 = 0; - aibot->unk09d = 0; - - botinvInit(chr, 10); + if (aibot == NULL) { + return; } + + aibot->chrdistances = mempAlloc(g_MpNumChrs * sizeof(f32), MEMPOOL_STAGE); + aibot->chrsinsight = mempAlloc(g_MpNumChrs * sizeof(u8), MEMPOOL_STAGE); + aibot->chrslastseen60 = mempAlloc(g_MpNumChrs * sizeof(s32), MEMPOOL_STAGE); + aibot->chrrooms = mempAlloc(g_MpNumChrs * sizeof(s8), MEMPOOL_STAGE); + + if (!aibot->chrdistances || !aibot->chrsinsight || !aibot->chrslastseen60 || !aibot->chrrooms) { + return; + } + + chr->tude = 0; + chr->voicebox = random() % 3; + + if (g_HeadsAndBodies[chr->bodynum].ismale == false) { + chr->voicebox = VOICEBOX_FEMALE; + } + + chr->target = -1; + chr->naturalanim = 0; + chr->myspecial = -1; + chr->yvisang = 0; + chr->teamscandist = 0; + chr->convtalk = 0; + chr->myaction = MA_AIBOTMAINLOOP; + + aibot->ammoheld = mempAlloc(36 * sizeof(s32), MEMPOOL_STAGE); + + for (i = 0; i < 33; i++) { + aibot->ammoheld[i] = 0; + } + + aibot->config = &g_BotConfigsArray[botcfgnum]; + + switch (g_BotConfigsArray[botcfgnum].difficulty) { + case BOTDIFF_MEAT: + aibot->followchance = 0; + break; + case BOTDIFF_EASY: + aibot->followchance = 10; + break; + default: + case BOTDIFF_NORMAL: + aibot->followchance = 20; + break; + case BOTDIFF_HARD: + aibot->followchance = 40; + break; + case BOTDIFF_PERFECT: + aibot->followchance = 60; + break; + case BOTDIFF_DARK: + aibot->followchance = 0; + break; + } + + aibot->aibotnum = botnum; + aibot->unk064 = 0; + aibot->gotoprop = NULL; + aibot->timeuntilreload60[0] = 0; + aibot->timeuntilreload60[1] = 0; + aibot->throwtimer60 = 0; + aibot->unk040 = 0.0f; + aibot->loadedammo[0] = 0; + aibot->loadedammo[1] = 0; + aibot->unk058 = 0; + aibot->unk059 = 0; + aibot->nextbullettimer60[0] = 0; + aibot->nextbullettimer60[1] = 0; + aibot->unk030 = 301; + aibot->unk038 = 0; + aibot->punchtimer60[HAND_LEFT] = -1; + aibot->punchtimer60[HAND_RIGHT] = 0; + aibot->attackingplayernum = -1; + aibot->followingplayernum = -1; + aibot->dangerouspropnum = -1; + aibot->unk068 = 0; + aibot->unk06c = 0.0f; + aibot->unk070 = 0.0f; + aibot->distmode = -1; + aibot->lastkilledbyplayernum = -1; + aibot->feudplayernum = -1; + aibot->command = AIBOTCMD_NORMAL; + aibot->unk098 = 0.0f; + + aibot->defendholdpos.x = pos.x; + aibot->defendholdpos.y = pos.y; + aibot->defendholdpos.z = pos.z; + + aibot->weaponnum = WEAPON_UNARMED; + + aibot->burstsdone[0] = 0; + aibot->burstsdone[1] = 0; + aibot->skrocket = NULL; + aibot->unk0a0 = 0; + + aibot->gunfunc = FUNC_PRIMARY; + aibot->iscloserangeweapon = true; + aibot->teamisonlyai = false; + aibot->hasbriefcase = false; + aibot->hascase = false; + aibot->cloakdeviceenabled = false; + aibot->rcp120cloakenabled = false; + aibot->unk04c_04 = false; + aibot->unk04c_03 = false; + aibot->hasuplink = false; + aibot->unk04c_00 = false; + + aibot->hillpadnum = -1; + aibot->hillcovernum = -1; + + aibot->lastknownhill = -1; + aibot->cyclonedischarging[HAND_LEFT] = false; + aibot->cyclonedischarging[HAND_RIGHT] = false; + aibot->changeguntimer60 = 0; + aibot->distmodettl60 = 0; + aibot->forcemainloop = false; + aibot->returntodefendtimer60 = 0; + aibot->reaperspeed[HAND_LEFT] = 0; + aibot->reaperspeed[HAND_RIGHT] = 0; + aibot->maulercharge[HAND_LEFT] = 0.0f; + aibot->maulercharge[HAND_RIGHT] = 0.0f; + aibot->unk0a4 = model0001ae44(chr->model); + aibot->angleoffset = 0.0f; + aibot->speedtheta = 0.0f; + aibot->unk0b0 = model0001ae44(chr->model); + + aibot->unk0b4 = 0.0f; + aibot->unk0b8 = 0.0f; + aibot->shotspeed.x = 0.0f; + aibot->shotspeed.y = 0.0f; + aibot->shotspeed.z = 0.0f; + aibot->commandtimer60 = 0; + aibot->shootdelaytimer60 = 0; + aibot->targetlastseen60 = -1; + aibot->lastseenanytarget60 = -1; + aibot->targetinsight = false; + aibot->queryplayernum = 0; + + for (i = 0; i < ARRAYCOUNT(aibot->chrnumsbydistanceasc); i++) { + aibot->chrnumsbydistanceasc[i] = -1; + } + + for (i = 0; i < g_MpNumChrs; i++) { + aibot->chrdistances[i] = U32_MAX; + aibot->chrsinsight[i] = 0; + aibot->chrslastseen60[i] = -1; + aibot->chrrooms[i] = -1; + } + + aibot->unk1c0 = 0.0f; + aibot->unk1c4 = 0.0f; + aibot->unk1c8 = 0.0f; + aibot->unk1cc = -1; + aibot->unk1d0 = 0; + aibot->unk1d4 = 0.0f; + aibot->unk1e4 = -1; + aibot->waypoints[0] = NULL; + aibot->unk208 = 0; + aibot->random1 = random(); + aibot->random1ttl60 = 0; + + for (i = 0; i < 6; i++) { + aibot->killsbygunfunc[i][0] = 0.0f; + aibot->killsbygunfunc[i][1] = 0.0f; + + aibot->suicidesbygunfunc[i][0] = 0.0f; + aibot->suicidesbygunfunc[i][1] = 0.0f; + + aibot->equipdurations60[i][0] = 0; + aibot->equipdurations60[i][1] = 0; + + aibot->unk2a8[i] = 0; + } + + aibot->unk2a4 = 0; + aibot->dampensuicidesttl60 = 0; + aibot->unk2c4 = 0.0f; + aibot->targetcloaktimer60 = 0; + aibot->canseecloaked = false; + + aibot->random2ttl60 = 0; + aibot->random2 = random(); + aibot->randomfrac = RANDOMFRAC(); + aibot->cheap = false; + aibot->unk078 = 0; + aibot->unk050 = 0; + aibot->unk09d = 0; + + botinvInit(chr, 10); } } } diff --git a/src/game/chr.c b/src/game/chr.c index 780e4e18c..7099acd41 100644 --- a/src/game/chr.c +++ b/src/game/chr.c @@ -835,7 +835,7 @@ bool chr0f01f378(struct model *model, struct coord *arg1, struct coord *arg2, f3 if (chr->lastshooter >= 0 && chr->timeshooter > 0) { shooter = chr->lastshooter; } else { - shooter = mpPlayerGetIndex(chr); + shooter = chr->chrnum; } chrDie(chr, shooter); diff --git a/src/game/chraction.c b/src/game/chraction.c index 86cc773c3..32e0f3500 100644 --- a/src/game/chraction.c +++ b/src/game/chraction.c @@ -2077,7 +2077,7 @@ void chrDamage(struct chrdata *chr, f32 damage, struct coord *vector, struct gse // (includes MP aibots, not applicable for solo chrs) if (g_Vars.mplayerisrunning) { if (aprop && (aprop->type == PROPTYPE_PLAYER || aprop->type == PROPTYPE_CHR)) { - aplayernum = mpPlayerGetIndex(aprop->chr); + aplayernum = aprop->chr->chrnum; } } else { if (aprop && aprop->type == PROPTYPE_PLAYER) { @@ -2510,7 +2510,7 @@ void chrDie(struct chrdata *chr, s32 aplayernum) chr->act_die.thudframe2 = -1; chr->act_die.timeextra = 0; - mpstatsRecordDeath(aplayernum, mpPlayerGetIndex(chr)); + mpstatsRecordDeath(aplayernum, chr->chrnum); botinvDropAll(chr, chr->aibot->weaponnum); #if VERSION >= VERSION_NTSC_1_0 @@ -5491,7 +5491,7 @@ void chrTickShoot(struct chrdata *chr, s32 handnum) s32 playernum = -1; if (g_Vars.mplayerisrunning) { - playernum = mpPlayerGetIndex(chr); + playernum = chr->chrnum; } bgunPlayPropHitSound(&gset, hitprop, -1); @@ -5521,7 +5521,7 @@ void chrTickShoot(struct chrdata *chr, s32 handnum) // Create explosion if using Phoenix if (gset.weaponnum == WEAPON_PHOENIX && gset.weaponfunc == FUNC_SECONDARY) { - s32 playernum = chr->aibot ? mpPlayerGetIndex(chr) : g_Vars.currentplayernum; + s32 playernum = chr->aibot ? chr->chrnum : g_Vars.currentplayernum; if (!queriedhitrooms) { func0f065e74(&gunpos, gunrooms, &hitpos, hitrooms); diff --git a/src/game/explosions.c b/src/game/explosions.c index c8b09f192..8f6969f22 100644 --- a/src/game/explosions.c +++ b/src/game/explosions.c @@ -962,7 +962,7 @@ void explosionInflictDamage(struct prop *expprop) } { - struct chrdata *ownerchr = mpGetChrFromPlayerIndex(exp->owner); + struct chrdata *ownerchr = g_MpChrs[exp->owner].chr; if (ownerchr) { ownerprop = ownerchr->prop; @@ -1178,7 +1178,7 @@ u32 explosionTick(struct prop *prop) scorchsize *= 0.8f + 0.2f * RANDOMFRAC(); - chr = mpGetChrFromPlayerIndex(exp->owner); + chr = g_MpChrs[exp->owner].chr; if (g_Rooms[exp->room].gfxdata) { if (g_Rooms[exp->room].gfxdata->xlublocks && bgTestHitInRoom(&prop->pos, &exp->unk3d0, exp->room, &hitthing)) { diff --git a/src/game/lv.c b/src/game/lv.c index 4cb45c4b9..211c9702d 100644 --- a/src/game/lv.c +++ b/src/game/lv.c @@ -350,6 +350,7 @@ void lvReset(s32 stagenum) propsndReset(); setupLoadFiles(stagenum); scenarioReset(); + varsResetRoomProps(); bodiesReset(stagenum); setupCreateProps(stagenum); explosionsReset(); @@ -1688,7 +1689,7 @@ void lvTick(void) } for (i = 0; i < g_MpNumChrs; i++) { - if (g_MpAllChrPtrs[i]->actiontype == ACT_DIE) { + if (g_MpChrs[i].chr->actiontype == ACT_DIE) { numdying++; } } diff --git a/src/game/menuitem.c b/src/game/menuitem.c index 1a7087c9b..935630da1 100644 --- a/src/game/menuitem.c +++ b/src/game/menuitem.c @@ -3480,7 +3480,7 @@ Gfx *menuitemRankingRender(Gfx *gdl, struct menurendercontext *context) gdl = textRenderProjected(gdl, &x, &y, g_BossFile.teamnames[ranking->teamnum], g_CharsHandelGothicSm, g_FontHandelGothicSm, textcolour, context->width, context->height, 0, 0); } else { - gdl = textRenderProjected(gdl, &x, &y, ranking->mpchr->name, + gdl = textRenderProjected(gdl, &x, &y, ranking->mpchr->config->name, g_CharsHandelGothicSm, g_FontHandelGothicSm, textcolour, context->width, context->height, 0, 0); } @@ -3563,7 +3563,7 @@ Gfx *menuitemPlayerStatsRender(Gfx *gdl, struct menurendercontext *context) s32 y; u32 maincolour; s32 playernum = g_MpSelectedPlayersForStats[g_MpPlayerNum]; - struct mpchrconfig *mpchr; + struct mpchr *mpchr; u32 selectioncolour; s32 textheight; s32 textwidth; @@ -3594,7 +3594,7 @@ Gfx *menuitemPlayerStatsRender(Gfx *gdl, struct menurendercontext *context) x = context->x + 2; y = context->y + 1; - gdl = textRenderProjected(gdl, &x, &y, mpchr->name, g_CharsHandelGothicSm, g_FontHandelGothicSm, + gdl = textRenderProjected(gdl, &x, &y, mpchr->config->name, g_CharsHandelGothicSm, g_FontHandelGothicSm, selectioncolour, context->width, context->height, 0, 0); // "Suicides" heading @@ -3765,45 +3765,43 @@ Gfx *menuitemPlayerStatsRender(Gfx *gdl, struct menurendercontext *context) ypos -= data->scrolloffset; - for (i = 0; i < MAX_MPCHRS; i++) { - if (g_MpSetup.chrslots & (1 << i)) { - struct mpchrconfig *loopmpchr = MPCHR(i); + for (i = 0; i < g_MpNumChrs; i++) { + struct mpchr *loopmpchr = MPCHR(i); - if (i != playernum) { - // Name - x = context->x + 29; - y = context->y + ypos; - gdl = textRenderProjected(gdl, &x, &y, loopmpchr->name, g_CharsHandelGothicSm, g_FontHandelGothicSm, - 0x00ffffff, context->width, context->height, 0, 0); + if (i != playernum) { + // Name + x = context->x + 29; + y = context->y + ypos; + gdl = textRenderProjected(gdl, &x, &y, loopmpchr->config->name, g_CharsHandelGothicSm, g_FontHandelGothicSm, + 0x00ffffff, context->width, context->height, 0, 0); - // Num deaths - sprintf(buffer, "%d\n", loopmpchr->killcounts[playernum]); - textMeasure(&textheight, &textwidth, buffer, g_CharsHandelGothicSm, g_FontHandelGothicSm, 0); - x = context->x - textwidth + 120; - y = context->y + ypos; - gdl = textRenderProjected(gdl, &x, &y, buffer, g_CharsHandelGothicSm, g_FontHandelGothicSm, - 0xff4040ff, context->width, context->height, 0, 0); + // Num deaths + sprintf(buffer, "%d\n", loopmpchr->killcounts[playernum]); + textMeasure(&textheight, &textwidth, buffer, g_CharsHandelGothicSm, g_FontHandelGothicSm, 0); + x = context->x - textwidth + 120; + y = context->y + ypos; + gdl = textRenderProjected(gdl, &x, &y, buffer, g_CharsHandelGothicSm, g_FontHandelGothicSm, + 0xff4040ff, context->width, context->height, 0, 0); - // Num kills - sprintf(buffer, "%d\n", mpchr->killcounts[i]); - textMeasure(&textheight, &textwidth, buffer, g_CharsHandelGothicSm, g_FontHandelGothicSm, 0); + // Num kills + sprintf(buffer, "%d\n", mpchr->killcounts[i]); + textMeasure(&textheight, &textwidth, buffer, g_CharsHandelGothicSm, g_FontHandelGothicSm, 0); #if VERSION == VERSION_JPN_FINAL - x = context->x + 4; + x = context->x + 4; #else - x = context->x - textwidth + 25; + x = context->x - textwidth + 25; #endif - y = context->y + ypos; - gdl = textRenderProjected(gdl, &x, &y, buffer, g_CharsHandelGothicSm, g_FontHandelGothicSm, - 0x00ff00ff, context->width, context->height, 0, 0); + y = context->y + ypos; + gdl = textRenderProjected(gdl, &x, &y, buffer, g_CharsHandelGothicSm, g_FontHandelGothicSm, + 0x00ff00ff, context->width, context->height, 0, 0); #if VERSION == VERSION_JPN_FINAL - ypos += 13; + ypos += 13; #else - ypos += 10; + ypos += 10; #endif - } } } } diff --git a/src/game/modelmgrreset.c b/src/game/modelmgrreset.c index 732c612f5..731ff19a4 100644 --- a/src/game/modelmgrreset.c +++ b/src/game/modelmgrreset.c @@ -73,7 +73,7 @@ void modelmgrAllocateSlots(s32 numobjs, s32 numchrs, bool haslaptops) g_ModelNumObjs = numobjs; g_ModelNumChrs = numchrs; - if (g_Vars.stagenum == STAGE_TITLE) { + if (g_Vars.stagenum >= STAGE_TITLE) { g_MaxRwdataType1 = 35; g_MaxRwdataType2 = 25; g_MaxRwdataType3 = 20; diff --git a/src/game/mplayer/ingame.c b/src/game/mplayer/ingame.c index 11f38ff4b..e930080f9 100644 --- a/src/game/mplayer/ingame.c +++ b/src/game/mplayer/ingame.c @@ -30,68 +30,17 @@ struct menudialogdef g_MpEndscreenSavePlayerMenuDialog; s32 mpStatsForPlayerDropdownHandler(s32 operation, struct menuitem *item, union handlerdata *data) { - struct mpchrconfig *mpchr; - s32 v0; - s32 v1; - s32 a1; - switch (operation) { case MENUOP_GETOPTIONCOUNT: - data->list.value = 0; - - for (v0 = 0; v0 < MAX_MPCHRS; v0++) { - if (g_MpSetup.chrslots & (1 << v0)) { - data->list.value++; - } - } + data->list.value = g_MpNumChrs; break; case MENUOP_GETOPTIONTEXT: - v0 = 0; - - for (a1 = 0; a1 < MAX_MPCHRS; a1++) { - if (g_MpSetup.chrslots & (1 << a1)) { - mpchr = MPCHR(a1); - - if (v0 == data->list.value) { - return (s32) mpchr->name; - } - - v0++; - } - } - - return (s32) ""; + return (s32) g_MpChrs[data->list.value].config->name; case MENUOP_SET: - v0 = 0; - - for (a1 = 0; a1 < MAX_MPCHRS; a1++) { - if (g_MpSetup.chrslots & (1 << a1)) { - if (v0); - - if (data->list.value == v0) { - g_MpSelectedPlayersForStats[g_MpPlayerNum] = a1; - } - - v0++; - } - } - + g_MpSelectedPlayersForStats[g_MpPlayerNum] = data->list.value; break; case MENUOP_GETSELECTEDINDEX: - v0 = 0; - - for (v1 = 0; v1 < MAX_MPCHRS; v1++) { - if (g_MpSetup.chrslots & (1 << v1)) { - if (v0); - - if (g_MpSelectedPlayersForStats[g_MpPlayerNum] == v1) { - data->list.value = v0; - } - - v0++; - } - } - + data->list.value = g_MpSelectedPlayersForStats[g_MpPlayerNum]; break; } @@ -425,10 +374,10 @@ char *mpMenuTextWeaponDescription(struct menuitem *item) char *mpMenuTitleStatsFor(struct menudialogdef *dialogdef) { - struct mpchrconfig *mpchr = MPCHR(g_MpSelectedPlayersForStats[g_MpPlayerNum]); + struct mpchr *mpchr = MPCHR(g_MpSelectedPlayersForStats[g_MpPlayerNum]); // "Stats for %s" - sprintf(g_StringPointer, langGet(L_MPMENU_280), mpchr->name); + sprintf(g_StringPointer, langGet(L_MPMENU_280), mpchr->config->name); return g_StringPointer; } @@ -583,13 +532,13 @@ char *mpMenuTextPlacementWithSuffix(struct menuitem *item) L_MPMENU_275, // "12th" }; - return langGet(suffixes[g_PlayerConfigsArray[g_MpPlayerNum].base.placement]); + return langGet(suffixes[g_MpChrs[g_MpPlayerNum].placement]); } s32 mpPlacementMenuHandler(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_GETCOLOUR) { - if (g_PlayerConfigsArray[g_MpPlayerNum].base.placement == 0) { // winner + if (g_MpChrs[g_MpPlayerNum].placement == 0) { // winner data->label.colour2 = colourBlend(data->label.colour2, 0xffff00ff, menuGetSinOscFrac(40) * 255); } } diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index 421e52d27..40cd319af 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -29,10 +29,9 @@ #include "types.h" // bss -struct chrdata *g_MpAllChrPtrs[MAX_MPCHRS]; -struct mpchrconfig *g_MpAllChrConfigPtrs[MAX_MPCHRS]; -s32 g_MpNumChrs; u32 var800ac534; +s32 g_MpNumChrs; +struct mpchr *g_MpChrs; struct mpbotconfig g_BotConfigsArray[MAX_BOTS]; u8 g_MpSimulantDifficultiesPerNumPlayers[8][4]; struct mpplayerconfig g_PlayerConfigsArray[6]; @@ -122,19 +121,6 @@ f32 mpHandicapToDamageScale(u8 value) return tmp * tmp * 3 - 2; } -void func0f187838(struct mpchrconfig *mpchr) -{ - s32 i = 0; - - while (i < ARRAYCOUNT(mpchr->killcounts)) { - mpchr->killcounts[i++] = 0; - } - - mpchr->numdeaths = 0; - mpchr->numpoints = 0; - mpchr->unk40 = 0; -} - void mpStartMatch(void) { s32 i; @@ -195,22 +181,12 @@ void mpReset(void) mpCalculatePlayerTitle(&g_PlayerConfigsArray[i]); - g_PlayerConfigsArray[i].newtitle = g_PlayerConfigsArray[i].title; - g_MpNumChrs++; mpindex++; } } - for (i = 0; i != MAX_MPCHRS; i++) { - struct mpchrconfig *mpchr = MPCHR(i); - - func0f187838(mpchr); - -#if VERSION >= VERSION_NTSC_1_0 - g_MpAllChrPtrs[i] = NULL; -#endif - } + g_MpChrs = NULL; g_MpSetup.paused = false; @@ -286,19 +262,15 @@ void mpCalculateTeamIsOnlyAi(void) s32 i; s32 j; - // Iterate simulants, which go after players in the g_MpAllChrPtrs array + // Iterate simulants for (i = playercount; i < g_MpNumChrs; i++) { - if (!g_MpAllChrPtrs[i]) { - continue; - } - - g_MpAllChrPtrs[i]->aibot->teamisonlyai = true; + g_MpChrs[i].chr->aibot->teamisonlyai = true; if (g_MpSetup.options & MPOPTION_TEAMSENABLED) { // Iterate human players for (j = 0; j < playercount; j++) { - if (g_MpAllChrPtrs[i]->team == g_MpAllChrPtrs[j]->team) { - g_MpAllChrPtrs[i]->aibot->teamisonlyai = false; + if (g_MpChrs[i].team == g_MpChrs[j].team) { + g_MpChrs[i].chr->aibot->teamisonlyai = false; break; } } @@ -308,9 +280,7 @@ void mpCalculateTeamIsOnlyAi(void) void func0f187fbc(s32 playernum) { - g_PlayerConfigsArray[playernum].base.unk18 = 80; - g_PlayerConfigsArray[playernum].base.unk1a = 80; - g_PlayerConfigsArray[playernum].base.unk1c = 75; + g_PlayerConfigsArray[playernum].unk1c = 75; } void func0f187fec(void) @@ -358,7 +328,7 @@ void mpPlayerSetDefaults(s32 playernum, bool autonames) } g_PlayerConfigsArray[playernum].base.mpheadnum = mpGetMpheadnumByMpbodynum(g_PlayerConfigsArray[playernum].base.mpbodynum); - g_PlayerConfigsArray[playernum].base.displayoptions = MPDISPLAYOPTION_RADAR | MPDISPLAYOPTION_HIGHLIGHTTEAMS; + g_PlayerConfigsArray[playernum].displayoptions = MPDISPLAYOPTION_RADAR | MPDISPLAYOPTION_HIGHLIGHTTEAMS; g_PlayerConfigsArray[playernum].fileguid.fileid = 0; g_PlayerConfigsArray[playernum].fileguid.deviceserial = 0; @@ -596,7 +566,7 @@ s32 mpGetPlayerRankings(struct ranking *rankings) s32 i; s32 scores[MAX_MPCHRS]; u32 rankablescores[MAX_MPCHRS]; - struct mpchrconfig *mpchrs[MAX_MPCHRS]; + struct mpchr *mpchrs[MAX_MPCHRS]; s32 chrnums[MAX_MPCHRS]; s32 count = 0; s32 numteams; @@ -605,7 +575,7 @@ s32 mpGetPlayerRankings(struct ranking *rankings) s32 loser; s32 score; s32 deaths; - struct mpchrconfig *mpchr; + struct mpchr *mpchr; s32 dstindex; bool found; u32 rankablescore; @@ -616,44 +586,42 @@ s32 mpGetPlayerRankings(struct ranking *rankings) } // Populate 4 arrays with player info, sorted by highest score descending - for (i = 0; i < MAX_MPCHRS; i++) { - if (g_MpSetup.chrslots & (1 << i)) { - mpchr = MPCHR(i); + for (i = 0; i < g_MpNumChrs; i++) { + mpchr = MPCHR(i); - scenarioCalculatePlayerScore(mpchr, i, &score, &deaths); + scenarioCalculatePlayerScore(mpchr, i, &score, &deaths); - rankablescore = (score + 0x8000) << 16 | (0xffff - deaths); - dstindex = 0; - found = false; + rankablescore = (score + 0x8000) << 16 | (0xffff - deaths); + dstindex = 0; + found = false; - // Find where this player should be placed in the sorted arrays - for (j = 0; j < count && !found; j++) { - if (rankablescore > rankablescores[j]) { - dstindex = j; - found = true; - } + // Find where this player should be placed in the sorted arrays + for (j = 0; j < count && !found; j++) { + if (rankablescore > rankablescores[j]) { + dstindex = j; + found = true; } - - if (!found) { - dstindex = count; - } - - // Shuffle everything forward after dstindex to create a gap - for (j = count; j > dstindex; j--) { - rankablescores[j] = rankablescores[j - 1]; - scores[j] = scores[j - 1]; - mpchrs[j] = mpchrs[j - 1]; - chrnums[j] = chrnums[j - 1]; - } - - count++; - - // Write the new figures - rankablescores[dstindex] = (score + 0x8000) << 16 | (0xffff - deaths); - scores[dstindex] = score; - mpchrs[dstindex] = mpchr; - chrnums[dstindex] = i; } + + if (!found) { + dstindex = count; + } + + // Shuffle everything forward after dstindex to create a gap + for (j = count; j > dstindex; j--) { + rankablescores[j] = rankablescores[j - 1]; + scores[j] = scores[j - 1]; + mpchrs[j] = mpchrs[j - 1]; + chrnums[j] = chrnums[j - 1]; + } + + count++; + + // Write the new figures + rankablescores[dstindex] = (score + 0x8000) << 16 | (0xffff - deaths); + scores[dstindex] = score; + mpchrs[dstindex] = mpchr; + chrnums[dstindex] = i; } // Populate the rankings array, copy some values into the mpchr structs @@ -726,7 +694,7 @@ s32 mpGetPlayerRankings(struct ranking *rankings) */ s32 mpCalculateTeamScore(s32 teamnum, s32 *result) { - struct mpchrconfig *mpchr; + struct mpchr *mpchr; s32 teamscore = 0; s32 teamdeaths = 0; bool teamexists = false; @@ -735,16 +703,14 @@ s32 mpCalculateTeamScore(s32 teamnum, s32 *result) s32 score; s32 deaths; - for (i = 0; i < MAX_MPCHRS; i++) { - if (g_MpSetup.chrslots & (1 << i)) { - mpchr = MPCHR(i); + for (i = 0; i < g_MpNumChrs; i++) { + mpchr = MPCHR(i); - if (mpchr->team == teamnum) { - scenarioCalculatePlayerScore(mpchr, i, &score, &deaths); - teamexists = true; - teamscore += score; - teamdeaths += deaths; - } + if (mpchr->team == teamnum) { + scenarioCalculatePlayerScore(mpchr, i, &score, &deaths); + teamexists = true; + teamscore += score; + teamdeaths += deaths; } } @@ -2177,8 +2143,8 @@ void mpCalculateAwards(void) // At the same time, populate the metrics array // which is a temporary array for award calculation. for (i = 0; i < playercount; i++) { - struct mpchrconfig *mpchr = mpGetChrConfigBySlotNum(i); - struct mpplayerconfig *mpplayer = (struct mpplayerconfig *)mpchr; + struct mpchr *mpchr = MPCHR(i); + struct mpplayerconfig *mpplayer = mpchr->playerconfig; s32 chrnum = mpGetChrIndexBySlotNum(i); s32 sum; @@ -2193,7 +2159,7 @@ void mpCalculateAwards(void) metrics[i].numdeaths = 0; metrics[i].numsuicides = 0; - for (j = 0; j < MAX_MPCHRS; j++) { + for (j = 0; j < g_MpNumChrs; j++) { if (chrnum == j) { metrics[i].numsuicides += mpchr->killcounts[j]; } else { @@ -2201,8 +2167,8 @@ void mpCalculateAwards(void) } } - for (j = 0; j < MAX_MPCHRS; j++) { - struct mpchrconfig *othermpchr = MPCHR(j); + for (j = 0; j < g_MpNumChrs; j++) { + struct mpchr *othermpchr = MPCHR(j); metrics[i].numdeaths += othermpchr->killcounts[chrnum]; } @@ -2258,16 +2224,14 @@ void mpCalculateAwards(void) if ((numchrs >= 2 && (g_MpSetup.options & MPOPTION_TEAMSENABLED) == 0) || numteams >= 2) { bool lost = false; - if (mpplayer->base.placement == 0) { - for (j = 0; j < MAX_MPCHRS; j++) { - if (g_MpSetup.chrslots & (1 << j)) { - struct mpchrconfig *othermpchr = MPCHR(j); + if (mpchr->placement == 0) { + for (j = 0; j < g_MpNumChrs; j++) { + struct mpchr *othermpchr = MPCHR(j); - if (othermpchr->rankablescore == mpplayer->base.rankablescore - && othermpchr != &mpplayer->base - && !((g_MpSetup.options & MPOPTION_TEAMSENABLED) && othermpchr->team == mpplayer->base.team)) { - lost = true; - } + if (othermpchr->rankablescore == mpchr->rankablescore + && othermpchr != mpchr + && !((g_MpSetup.options & MPOPTION_TEAMSENABLED) && othermpchr->team == mpchr->team)) { + lost = true; } } @@ -2276,19 +2240,17 @@ void mpCalculateAwards(void) } } - if (((g_MpSetup.options & MPOPTION_TEAMSENABLED) == 0 && numchrs == mpplayer->base.placement + 1) - || ((g_MpSetup.options & MPOPTION_TEAMSENABLED) && numteams == mpplayer->base.placement + 1)) { + if (((g_MpSetup.options & MPOPTION_TEAMSENABLED) == 0 && numchrs == mpchr->placement + 1) + || ((g_MpSetup.options & MPOPTION_TEAMSENABLED) && numteams == mpchr->placement + 1)) { bool won = false; - for (j = 0; j < MAX_MPCHRS; j++) { - if (g_MpSetup.chrslots & (1 << j)) { - struct mpchrconfig *othermpchr = MPCHR(j); + for (j = 0; j < g_MpNumChrs; j++) { + struct mpchr *othermpchr = MPCHR(j); - if (othermpchr->rankablescore == mpplayer->base.rankablescore - && &mpplayer->base != othermpchr - && !((g_MpSetup.options & MPOPTION_TEAMSENABLED) && othermpchr->team == mpplayer->base.team)) { - won = true; - } + if (othermpchr->rankablescore == mpchr->rankablescore + && mpchr != othermpchr + && !((g_MpSetup.options & MPOPTION_TEAMSENABLED) && othermpchr->team == mpchr->team)) { + won = true; } } @@ -2462,43 +2424,41 @@ void mpCalculateAwards(void) s32 leastdeathsplayer = -1; s32 k; - for (k = 0; k < MAX_MPCHRS; k++) { - if (g_MpSetup.chrslots & (1 << k)) { - s32 totalkills = 0; - struct mpchrconfig *mpchr = MPCHR(k); + for (k = 0; k < g_MpNumChrs; k++) { + s32 totalkills = 0; + struct mpchr *mpchr = MPCHR(k); - for (j = 0; j < MAX_MPCHRS; j++) { - // @bug: i should be k. The value of i was incremented after - // the last iteration of its loop above so it'll be between - // 1 and 4 inclusively depending on the number of players. - // The bot nums start from 4 regardless of how many players - // there are. So in a game with 4 humans, the kills on the - // first bot will not be considered for the killmaster medal - // which means the medal could go to a player who got fewer - // total kills. Additionally, suicides are counted as kills - // while the intention here was to omit them. - if (i != j) { - totalkills += mpchr->killcounts[j]; - } + for (j = 0; j < g_MpNumChrs; j++) { + // @bug: i should be k. The value of i was incremented after + // the last iteration of its loop above so it'll be between + // 1 and 4 inclusively depending on the number of players. + // The bot nums start from 4 regardless of how many players + // there are. So in a game with 4 humans, the kills on the + // first bot will not be considered for the killmaster medal + // which means the medal could go to a player who got fewer + // total kills. Additionally, suicides are counted as kills + // while the intention here was to omit them. + if (i != j) { + totalkills += mpchr->killcounts[j]; } + } - if (totalkills == mostkillsvalue) { - mostkillsplayer = -1; - } + if (totalkills == mostkillsvalue) { + mostkillsplayer = -1; + } - if (totalkills > mostkillsvalue) { - mostkillsplayer = k; - mostkillsvalue = totalkills; - } + if (totalkills > mostkillsvalue) { + mostkillsplayer = k; + mostkillsvalue = totalkills; + } - if (mpchr->numdeaths == leastdeathsvalue) { - leastdeathsplayer = -1; - } + if (mpchr->numdeaths == leastdeathsvalue) { + leastdeathsplayer = -1; + } - if (mpchr->numdeaths < leastdeathsvalue) { - leastdeathsplayer = k; - leastdeathsvalue = mpchr->numdeaths; - } + if (mpchr->numdeaths < leastdeathsvalue) { + leastdeathsplayer = k; + leastdeathsvalue = mpchr->numdeaths; } } @@ -2555,8 +2515,8 @@ void mpCalculateAwards(void) // Recalculate title for all players for (i = 0; i < playercount; i++) { - struct mpplayerconfig *mpchr = (struct mpplayerconfig *)mpGetChrConfigBySlotNum(i); - mpCalculatePlayerTitle(mpchr); + struct mpplayerconfig *mpcfg = (struct mpplayerconfig *)mpGetChrConfigBySlotNum(i); + mpCalculatePlayerTitle(mpcfg); } } #else @@ -4409,7 +4369,7 @@ struct mpchrconfig *mpGetChrConfigBySlotNum(s32 slot) for (i = 0; i < MAX_MPCHRS; i++) { if (g_MpSetup.chrslots & (1 << i)) { if (count == slot) { - result = MPCHR(i); + result = MPCHRCONFIG(i); break; } @@ -4442,7 +4402,7 @@ s32 mpGetChrIndexBySlotNum(s32 slot) } #endif -s32 mpGetNumChrs(void) +s32 mpGetNumConfigs(void) { s32 count = 0; s32 i; @@ -4456,6 +4416,11 @@ s32 mpGetNumChrs(void) return count; } +s32 mpGetNumChrs(void) +{ + return g_MpNumChrs; +} + u8 mpFindUnusedTeamNum(void) { u8 teamnum = 0; @@ -4467,7 +4432,7 @@ u8 mpFindUnusedTeamNum(void) for (i = 0; i < MAX_MPCHRS; i++) { if (g_MpSetup.chrslots & (1 << i)) { - struct mpchrconfig *mpchr = MPCHR(i); + struct mpchrconfig *mpchr = MPCHRCONFIG(i); if (mpchr->team == teamnum) { available = false; @@ -4514,9 +4479,9 @@ void mpCreateBotFromProfile(s32 botnum, u8 profilenum) for (i = 0; i < MAX_MPCHRS; i++) { if (g_MpSetup.chrslots & (1 << i)) { - struct mpchrconfig *mpchr = MPCHR(i); + struct mpchrconfig *mpcfg = MPCHRCONFIG(i); - if (mpchr->mpheadnum == headnum) { + if (mpcfg->mpheadnum == headnum) { available = false; } } @@ -4699,68 +4664,6 @@ const char var7f1b8c04[] = "PakId for player %d: %d\n"; const char var7f1b8c20[] = "Load Player - Result: %d\n"; #endif -s32 mpPlayerGetIndex(struct chrdata *chr) -{ - s32 i; - - for (i = 0; i < g_MpNumChrs; i++) { - if (g_MpAllChrPtrs[i] == chr) { - return i; - } - } - - return -1; -} - -struct chrdata *mpGetChrFromPlayerIndex(s32 index) -{ - if (index >= 0 && index < g_MpNumChrs) { - return g_MpAllChrPtrs[index]; - } - - return NULL; -} - -s32 func0f18d074(s32 index) -{ - s32 i; - - for (i = 0; i < 4; i++) { - if (&g_PlayerConfigsArray[i].base == g_MpAllChrConfigPtrs[index]) { - return i; - } - } - - for (i = 0; i < MAX_BOTS; i++) { - if (&g_BotConfigsArray[i].base == g_MpAllChrConfigPtrs[index]) { - return i + 4; - } - } - - return -1; -} - -s32 func0f18d0e8(s32 arg0) -{ - s32 i; - - if (arg0 < 4) { - for (i = 0; i < g_MpNumChrs; i++) { - if (g_MpAllChrConfigPtrs[i] == &g_PlayerConfigsArray[arg0].base) { - return i; - } - } - } else { - for (i = 0; i < g_MpNumChrs; i++) { - if (g_MpAllChrConfigPtrs[i] == &g_BotConfigsArray[arg0 - 4].base) { - return i; - } - } - } - - return -1; -} - void mpplayerfileLoadGunFuncs(struct savebuffer *buffer, s32 playernum) { s32 bitsremaining = 35; @@ -4834,7 +4737,7 @@ void mpplayerfileLoadWad(s32 playernum, struct savebuffer *buffer, s32 arg2) savebufferReadGuid(buffer, &guid); } - g_PlayerConfigsArray[playernum].base.displayoptions = savebufferReadBits(buffer, 8); + g_PlayerConfigsArray[playernum].displayoptions = savebufferReadBits(buffer, 8); g_PlayerConfigsArray[playernum].kills = savebufferReadBits(buffer, 20); g_PlayerConfigsArray[playernum].deaths = savebufferReadBits(buffer, 20); g_PlayerConfigsArray[playernum].gamesplayed = savebufferReadBits(buffer, 19); @@ -4887,7 +4790,7 @@ void mpplayerfileSaveWad(s32 playernum, struct savebuffer *buffer) savebufferWriteGuid(buffer, &guid); } - savebufferOr(buffer, g_PlayerConfigsArray[playernum].base.displayoptions, 8); + savebufferOr(buffer, g_PlayerConfigsArray[playernum].displayoptions, 8); if (g_PlayerConfigsArray[playernum].kills > 0xfffff) { // 1,048,575 g_PlayerConfigsArray[playernum].kills = 0xfffff; diff --git a/src/game/mplayer/scenarios.c b/src/game/mplayer/scenarios.c index 5b0a11be1..1b1ac77a2 100644 --- a/src/game/mplayer/scenarios.c +++ b/src/game/mplayer/scenarios.c @@ -61,7 +61,7 @@ struct mpscenario { void (*tickfunc)(void); void (*tickchrfunc)(struct chrdata *chr); Gfx *(*hudfunc)(Gfx *gdl); - void (*calcscorefunc)(struct mpchrconfig *mpchr, s32 chrnum, s32 *score, s32 *deaths); + void (*calcscorefunc)(struct mpchr *mpchr, s32 chrnum, s32 *score, s32 *deaths); Gfx *(*radarextrafunc)(Gfx *gdl); bool (*radarchrfunc)(Gfx **gdl, struct prop *prop); bool (*highlightpropfunc)(struct prop *prop, s32 *colour); @@ -501,7 +501,7 @@ void scenarioCreateMatchStartHudmsgs(void) sprintf(scenarioname, "%s\n", langGet(g_MpScenarioOverviews[g_MpSetup.scenario].name)); for (i = 0; i < g_MpNumChrs; i++) { - if (g_MpAllChrPtrs[i]->aibot == NULL) { + if (!g_MpChrs[i].isbot) { setCurrentPlayerNum(i); if (g_BossFile.locktype == MPLOCKTYPE_CHALLENGE) { @@ -620,7 +620,7 @@ Gfx *scenarioRenderHud(Gfx *gdl) gDPSetRenderMode(gdl++, G_RM_OPA_SURF, G_RM_OPA_SURF2); gDPPipelineMode(gdl++, G_PM_1PRIMITIVE); - colour = var80087ce4[radarGetTeamIndex(chr->team)]; + colour = var80087ce4[chr->team]; gDPSetFillColor(gdl++, colour); viewleft = viGetViewLeft(); @@ -666,9 +666,9 @@ Gfx *scenarioRenderHud(Gfx *gdl) * * If no callback is registered, the default calculation below will apply. */ -void scenarioCalculatePlayerScore(struct mpchrconfig *mpchr, s32 chrnum, s32 *score, s32 *deaths) +void scenarioCalculatePlayerScore(struct mpchr *mpchr, s32 chrnum, s32 *score, s32 *deaths) { - struct mpchrconfig *othermpchr; + struct mpchr *othermpchr; s32 i; if (g_MpScenarios[g_MpSetup.scenario].calcscorefunc) { @@ -676,7 +676,7 @@ void scenarioCalculatePlayerScore(struct mpchrconfig *mpchr, s32 chrnum, s32 *sc } else { *score = 0; - for (i = 0; i < MAX_MPCHRS; i++) { + for (i = 0; i < g_MpNumChrs; i++) { if (i == chrnum) { *score -= mpchr->killcounts[i]; } else if (g_MpSetup.options & MPOPTION_TEAMSENABLED) { @@ -739,7 +739,7 @@ bool scenarioHighlightProp(struct prop *prop, s32 *colour) struct defaultobj *obj = prop->obj; if ((g_MpSetup.scenario != MPSCENARIO_COMBAT || (g_MpSetup.options & MPOPTION_NOPICKUPHIGHLIGHT) == 0) - && (g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].base.displayoptions & MPDISPLAYOPTION_HIGHLIGHTPICKUPS)) { + && (g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].displayoptions & MPDISPLAYOPTION_HIGHLIGHTPICKUPS)) { switch (obj->type) { case OBJTYPE_AMMOCRATE: case OBJTYPE_WEAPON: @@ -774,15 +774,15 @@ bool scenarioHighlightProp(struct prop *prop, s32 *colour) if (!pulse && !isunselectedbot && (g_MpSetup.scenario != MPSCENARIO_COMBAT || (g_MpSetup.options & MPOPTION_NOPLAYERHIGHLIGHT) == 0)) { if ((g_MpSetup.options & MPOPTION_TEAMSENABLED) - && (g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].base.displayoptions & MPDISPLAYOPTION_HIGHLIGHTTEAMS)) { + && (g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].displayoptions & MPDISPLAYOPTION_HIGHLIGHTTEAMS)) { useteamcolour = true; - } else if (g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].base.displayoptions & MPDISPLAYOPTION_HIGHLIGHTPLAYERS) { + } else if (g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].displayoptions & MPDISPLAYOPTION_HIGHLIGHTPLAYERS) { useblue = true; } } if (useteamcolour) { - u32 tmp = g_TeamColours[radarGetTeamIndex(prop->chr->team)]; + u32 tmp = g_TeamColours[prop->chr->team]; colour[0] = tmp >> 24 & 0xff; colour[1] = tmp >> 16 & 0xff; @@ -1062,12 +1062,12 @@ void scenarioCreateHudmsg(s32 playernum, char *message) */ bool scenarioChrsAreSameTeam(s32 playernum1, s32 playernum2) { - struct mpchrconfig *achr; - struct mpchrconfig *bchr; + struct mpchr *achr; + struct mpchr *bchr; if ((g_MpSetup.options & MPOPTION_TEAMSENABLED) && playernum1 >= 0 && playernum2 >= 0) { - s32 a = func0f18d074(playernum1); - s32 b = func0f18d074(playernum2); + s32 a = playernum1; + s32 b = playernum2; if (a >= 0 && b >= 0) { achr = MPCHR(a); @@ -1096,14 +1096,14 @@ s32 scenarioPickUpBriefcase(struct chrdata *chr, struct prop *prop) char text1[64]; char text2[64]; char text3[64]; - struct mpchrconfig *mpchr; + struct mpchr *mpchr; if (g_MpSetup.scenario == MPSCENARIO_HOLDTHEBRIEFCASE) { // Player or bot has picked up the briefcase g_ScenarioData.htb.token = chr->prop; if (chr->aibot) { - mpchr = g_MpAllChrConfigPtrs[mpPlayerGetIndex(chr)]; + mpchr = &g_MpChrs[chr->chrnum]; propPlayPickupSound(prop, weapon->weaponnum); chr->aibot->hasbriefcase = true; botinvGiveSingleWeapon(chr, WEAPON_BRIEFCASE2); @@ -1115,16 +1115,8 @@ s32 scenarioPickUpBriefcase(struct chrdata *chr, struct prop *prop) weaponPlayPickupSound(WEAPON_BRIEFCASE2); } -#if VERSION >= VERSION_JPN_FINAL - // "%shas the Briefcase" - sprintf(text1, langGet(L_MPWEAPONS_000_2), scenarioRemoveLineBreaks(mpchr->name, 0), bgunGetShortName(WEAPON_BRIEFCASE2)); -#elif VERSION >= VERSION_PAL_BETA - // "%shas the Briefcase" - sprintf(text1, langGet(L_MPWEAPONS_000_2), mpchr->name, bgunGetShortName(WEAPON_BRIEFCASE2)); -#else // "%shas the\n%s" - sprintf(text1, langGet(L_MPWEAPONS_000), mpchr->name, bgunGetShortName(WEAPON_BRIEFCASE2)); -#endif + sprintf(text1, langGet(L_MPWEAPONS_000), mpchr->config->name, bgunGetShortName(WEAPON_BRIEFCASE2)); prevplayernum = g_Vars.currentplayernum; @@ -1154,7 +1146,7 @@ s32 scenarioPickUpBriefcase(struct chrdata *chr, struct prop *prop) #endif } else if (g_MpSetup.scenario == MPSCENARIO_CAPTURETHECASE) { if (chr->aibot) { - mpchr = g_MpAllChrConfigPtrs[mpPlayerGetIndex(chr)]; + mpchr = &g_MpChrs[chr->chrnum]; } else { mpchr = MPCHR(g_Vars.playerstats[g_Vars.currentplayernum].mpindex); } @@ -1180,34 +1172,14 @@ s32 scenarioPickUpBriefcase(struct chrdata *chr, struct prop *prop) invRemoveItemByNum(WEAPON_BRIEFCASE2); } -#if VERSION >= VERSION_JPN_FINAL - // "You captured the %s Briefcase" - sprintf(text1, langGet(L_MPWEAPONS_004), scenarioRemoveLineBreaks(g_BossFile.teamnames[i], 0)); - - // "%scaptured our Briefcase" - sprintf(text2, langGet(L_MPWEAPONS_005), scenarioRemoveLineBreaks(mpchr->name, 0)); - - // "%scaptured the %s Briefcase" - sprintf(text3, langGet(L_MPWEAPONS_006), scenarioRemoveLineBreaks(mpchr->name, 0), scenarioRemoveLineBreaks(g_BossFile.teamnames[i], 1)); -#elif VERSION >= VERSION_PAL_BETA - // "You captured the %s Briefcase" - sprintf(text1, langGet(L_MPWEAPONS_004), g_BossFile.teamnames[i]); - - // "%scaptured our Briefcase" - sprintf(text2, langGet(L_MPWEAPONS_005), mpchr->name); - - // "%scaptured the %s Briefcase" - sprintf(text3, langGet(L_MPWEAPONS_006), mpchr->name, g_BossFile.teamnames[i]); -#else // "You captured the %s%s" sprintf(text1, langGet(L_MPWEAPONS_004), g_BossFile.teamnames[i], bgunGetShortName(WEAPON_BRIEFCASE2)); // "%scaptured our %s" - sprintf(text2, langGet(L_MPWEAPONS_005), mpchr->name, bgunGetShortName(WEAPON_BRIEFCASE2)); + sprintf(text2, langGet(L_MPWEAPONS_005), mpchr->config->name, bgunGetShortName(WEAPON_BRIEFCASE2)); // "%scaptured the %s%s" - sprintf(text3, langGet(L_MPWEAPONS_006), mpchr->name, g_BossFile.teamnames[i], bgunGetShortName(WEAPON_BRIEFCASE2)); -#endif + sprintf(text3, langGet(L_MPWEAPONS_006), mpchr->config->name, g_BossFile.teamnames[i], bgunGetShortName(WEAPON_BRIEFCASE2)); prevplayernum = g_Vars.currentplayernum; @@ -1218,23 +1190,13 @@ s32 scenarioPickUpBriefcase(struct chrdata *chr, struct prop *prop) for (i = 0; i < PLAYERCOUNT(); i++) { setCurrentPlayerNum(i); -#if VERSION >= VERSION_JPN_FINAL - if (!chr->aibot && i == prevplayernum) { - hudmsgCreateWithFlags(text1, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE | HUDMSGFLAG_NOWRAP); - } else if (caseteam == g_MpAllChrConfigPtrs[i]->team) { - hudmsgCreateWithFlags(text2, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE | HUDMSGFLAG_NOWRAP); - } else { - hudmsgCreateWithFlags(text3, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE | HUDMSGFLAG_NOWRAP); - } -#else if (!chr->aibot && i == prevplayernum) { hudmsgCreateWithFlags(text1, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE); - } else if (caseteam == g_MpAllChrConfigPtrs[i]->team) { + } else if (caseteam == g_MpChrs[i].team) { hudmsgCreateWithFlags(text2, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE); } else { hudmsgCreateWithFlags(text3, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE); } -#endif } setCurrentPlayerNum(prevplayernum); @@ -1256,57 +1218,27 @@ s32 scenarioPickUpBriefcase(struct chrdata *chr, struct prop *prop) g_ScenarioData.ctc.tokens[weapon->team] = chr->prop; -#if VERSION >= VERSION_JPN_FINAL - // "%shas the %s Briefcase" - sprintf(text1, langGet(L_MPWEAPONS_000_3), scenarioRemoveLineBreaks(mpchr->name, 0), scenarioRemoveLineBreaks(g_BossFile.teamnames[weapon->team], 1)); - - // "%shas our\nBriefcase" - sprintf(text2, langGet(L_MPWEAPONS_002), scenarioRemoveLineBreaks(mpchr->name, 0)); - - // "Got the %s Briefcase" - sprintf(text3, langGet(L_MPWEAPONS_003), scenarioRemoveLineBreaks(g_BossFile.teamnames[weapon->team], 0)); -#elif VERSION >= VERSION_PAL_BETA - // "%shas the %s Briefcase" - sprintf(text1, langGet(L_MPWEAPONS_000_3), mpchr->name, g_BossFile.teamnames[weapon->team]); - - // "%shas our\nBriefcase" - sprintf(text2, langGet(L_MPWEAPONS_002), mpchr->name); - - // "Got the %s Briefcase" - sprintf(text3, langGet(L_MPWEAPONS_003), g_BossFile.teamnames[weapon->team]); -#else // "%shas the %s%s" - sprintf(text1, langGet(L_MPWEAPONS_001), mpchr->name, g_BossFile.teamnames[weapon->team], bgunGetShortName(WEAPON_BRIEFCASE2)); + sprintf(text1, langGet(L_MPWEAPONS_001), mpchr->config->name, g_BossFile.teamnames[weapon->team], bgunGetShortName(WEAPON_BRIEFCASE2)); // "%shas our %s" - sprintf(text2, langGet(L_MPWEAPONS_002), mpchr->name, bgunGetShortName(WEAPON_BRIEFCASE2)); + sprintf(text2, langGet(L_MPWEAPONS_002), mpchr->config->name, bgunGetShortName(WEAPON_BRIEFCASE2)); // "Got the %s%s" sprintf(text3, langGet(L_MPWEAPONS_003), g_BossFile.teamnames[weapon->team], bgunGetShortName(WEAPON_BRIEFCASE2)); -#endif prevplayernum = g_Vars.currentplayernum; for (i = 0; i < PLAYERCOUNT(); i++) { setCurrentPlayerNum(i); -#if VERSION >= VERSION_JPN_FINAL - if (!chr->aibot && i == prevplayernum) { - hudmsgCreateWithFlags(text3, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE | HUDMSGFLAG_NOWRAP); - } else if (weapon->team == g_MpAllChrConfigPtrs[i]->team) { - hudmsgCreateWithFlags(text2, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE | HUDMSGFLAG_NOWRAP); - } else { - hudmsgCreateWithFlags(text1, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE | HUDMSGFLAG_NOWRAP); - } -#else if (!chr->aibot && i == prevplayernum) { hudmsgCreateWithFlags(text3, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE); - } else if (weapon->team == g_MpAllChrConfigPtrs[i]->team) { + } else if (weapon->team == g_MpChrs[i].team) { hudmsgCreateWithFlags(text2, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE); } else { hudmsgCreateWithFlags(text1, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE); } -#endif } setCurrentPlayerNum(prevplayernum); @@ -1394,7 +1326,7 @@ s32 scenarioPickUpUplink(struct chrdata *chr, struct prop *prop) { s32 i; char message[64]; - struct mpchrconfig *mpchr; + struct mpchr *mpchr; u32 playernum; if (g_MpSetup.scenario == MPSCENARIO_HACKERCENTRAL) { @@ -1405,21 +1337,14 @@ s32 scenarioPickUpUplink(struct chrdata *chr, struct prop *prop) g_ScenarioData.htm.uplink = chr->prop; if (chr->aibot) { - mpchr = g_MpAllChrConfigPtrs[mpPlayerGetIndex(chr)]; + mpchr = &g_MpChrs[chr->chrnum]; } else { mpchr = MPCHR(g_Vars.playerstats[g_Vars.currentplayernum].mpindex); } -#if VERSION >= VERSION_JPN_FINAL - // "%shas the\nData Uplink%s" - sprintf(message, langGet(L_MPWEAPONS_000), scenarioRemoveLineBreaks(mpchr->name, 0)); -#elif VERSION >= VERSION_PAL_BETA - // "%shas the\nData Uplink%s" - sprintf(message, langGet(L_MPWEAPONS_000), mpchr->name); -#else // "%shas the\n%s" - sprintf(message, langGet(L_MPWEAPONS_000), mpchr->name, bgunGetShortName(WEAPON_DATAUPLINK)); -#endif + sprintf(message, langGet(L_MPWEAPONS_000), mpchr->config->name, bgunGetShortName(WEAPON_DATAUPLINK)); + playernum = g_Vars.currentplayernum; for (i = 0; i < PLAYERCOUNT(); i++) { @@ -1477,7 +1402,7 @@ void scenarioHandleActivatedProp(struct chrdata *chr, struct prop *prop) struct defaultobj *obj = prop->obj; if (obj->flags3 & OBJFLAG3_HTMTERMINAL) { - u32 mpindex = mpPlayerGetIndex(chr); + u32 mpindex = chr->chrnum; if ((obj->hidden & OBJHFLAG_ACTIVATED_BY_BOND) == 0) { obj->hidden &= 0x0fffffff; diff --git a/src/game/mplayer/scenarios/capturethecase.inc b/src/game/mplayer/scenarios/capturethecase.inc index 6f210fef2..20512fdf1 100644 --- a/src/game/mplayer/scenarios/capturethecase.inc +++ b/src/game/mplayer/scenarios/capturethecase.inc @@ -139,7 +139,7 @@ void ctcInit(void) for (k = 0; k < MAX_MPCHRS; k++) { if (g_MpSetup.chrslots & (1 << k)) { - struct mpchrconfig *mpchr = MPCHR(k); + struct mpchr *mpchr = MPCHR(k); while (mpchr->team >= scenarioGetMaxTeams()) { mpchr->team -= scenarioGetMaxTeams(); @@ -228,31 +228,21 @@ void ctcInitProps(void) for (k = 0; k < MAX_MPCHRS; k++) { if (g_MpSetup.chrslots & (1 << k)) { - mpchr = MPCHR(k); + mpchr = MPCHRCONFIG(k); while (mpchr->team >= scenarioGetMaxTeams()) { mpchr->team -= scenarioGetMaxTeams(); } -#if VERSION >= VERSION_NTSC_1_0 - mpindex = func0f18d0e8(k); + mpindex = k; if (mpindex >= 0) { - struct chrdata *chr = mpGetChrFromPlayerIndex(mpindex); + struct chrdata *chr = g_MpChrs[mpindex].chr; if (chr) { - chr->team = 1 << mpchr->team; + chr->team = mpchr->team; } } -#else - if (func0f18d0e8(k) >= 0) { - struct chrdata *chr = mpGetChrFromPlayerIndex(func0f18d0e8(k)); - - if (chr) { - chr->team = 1 << mpchr->team; - } - } -#endif g_ScenarioData.ctc.playercountsperteam[mpchr->team]++; } @@ -343,9 +333,9 @@ void ctcInitProps(void) } } -void ctcCalculatePlayerScore(struct mpchrconfig *mpchr, s32 mpchrnum, s32 *score, s32 *deaths) +void ctcCalculatePlayerScore(struct mpchr *mpchr, s32 mpchrnum, s32 *score, s32 *deaths) { - struct mpchrconfig *loopmpchr; + struct mpchr *loopmpchr; s32 i; *score = 0; @@ -400,7 +390,7 @@ bool ctcRadarChr(Gfx **gdl, struct prop *prop) if (prop == g_ScenarioData.ctc.tokens[i] && (g_ScenarioData.ctc.tokens[i]->type == PROPTYPE_CHR || g_ScenarioData.ctc.tokens[i]->type == PROPTYPE_PLAYER)) { struct coord dist; - s32 colour = g_TeamColours[radarGetTeamIndex(prop->chr->team)]; + s32 colour = g_TeamColours[prop->chr->team]; dist.x = g_ScenarioData.ctc.tokens[i]->pos.x - g_Vars.currentplayer->prop->pos.x; dist.y = g_ScenarioData.ctc.tokens[i]->pos.y - g_Vars.currentplayer->prop->pos.y; dist.z = g_ScenarioData.ctc.tokens[i]->pos.z - g_Vars.currentplayer->prop->pos.z; @@ -460,7 +450,7 @@ void ctcAddPad(s32 *cmd) bool ctcChooseSpawnLocation(f32 arg0, struct coord *pos, s16 *rooms, struct prop *prop, f32 *arg4) { struct chrdata *chr = prop->chr; - s32 index = radarGetTeamIndex(chr->team); + s32 index = chr->team; if (g_ScenarioData.ctc.spawnpadsperteam[g_ScenarioData.ctc.teamindexes[index]].numspawnpads > 0) { *arg4 = playerChooseSpawnLocation(arg0, pos, rooms, prop, diff --git a/src/game/mplayer/scenarios/hackthatmac.inc b/src/game/mplayer/scenarios/hackthatmac.inc index 85b3c6787..df32fde48 100644 --- a/src/game/mplayer/scenarios/hackthatmac.inc +++ b/src/game/mplayer/scenarios/hackthatmac.inc @@ -381,8 +381,8 @@ void htmTick(void) // Check if a simulant is holding it if (g_ScenarioData.htm.uplink == NULL) { for (i = PLAYERCOUNT(); i < g_MpNumChrs; i++) { - if (g_MpAllChrPtrs[i]->aibot->hasuplink) { - g_ScenarioData.htm.uplink = g_MpAllChrPtrs[i]->prop; + if (g_MpChrs[i].chr->aibot->hasuplink) { + g_ScenarioData.htm.uplink = g_MpChrs[i].chr->prop; break; } } @@ -403,7 +403,7 @@ void htmTickChr(struct chrdata *chr) if (chr) { hasuplink = chr->aibot->hasuplink; - playernum = mpPlayerGetIndex(chr); + playernum = chr->chrnum; } else { hasuplink = invHasDataUplink() && bgunGetWeaponNum(HAND_RIGHT) == WEAPON_DATAUPLINK; playernum = g_Vars.currentplayernum; @@ -616,14 +616,14 @@ Gfx *htmRenderHud(Gfx *gdl) return gdl; } -void htmCalculatePlayerScore(struct mpchrconfig *mpchr, s32 mpchrnum, s32 *score, s32 *deaths) +void htmCalculatePlayerScore(struct mpchr *mpchr, s32 mpchrnum, s32 *score, s32 *deaths) { - struct mpchrconfig *loopmpchr; + struct mpchr *loopmpchr; s32 i; s32 index; *score = 0; - index = func0f18d0e8(mpchrnum); + index = mpchrnum; if (index >= 0) { *score += g_ScenarioData.htm.numpoints[index] * 2; @@ -691,7 +691,7 @@ Gfx *htmRadarExtra(Gfx *gdl) bf = 0; af = 0; } else if (g_MpSetup.options & MPOPTION_TEAMSENABLED) { - u32 colour = g_TeamColours[radarGetTeamIndex(data->terminals[i].team)]; + u32 colour = g_TeamColours[data->terminals[i].team]; rf = (colour >> 24) & 0xff; gf = ((colour >> 16) & 0xff); bf = ((colour >> 8) & 0xff); @@ -745,7 +745,7 @@ bool htmRadarChr(Gfx **gdl, struct prop *prop) dist.z = prop->pos.z - g_Vars.currentplayer->prop->pos.z; if (g_MpSetup.options & MPOPTION_TEAMSENABLED) { - u32 colour = g_TeamColours[radarGetTeamIndex(prop->chr->team)]; + u32 colour = g_TeamColours[prop->chr->team]; *gdl = radarDrawDot(*gdl, g_ScenarioData.htm.uplink, &dist, colour, 0, 1); } else { *gdl = radarDrawDot(*gdl, g_ScenarioData.htm.uplink, &dist, 0x00ff0000, 0, 1); diff --git a/src/game/mplayer/scenarios/holdthebriefcase.inc b/src/game/mplayer/scenarios/holdthebriefcase.inc index 931999dcd..bd447037f 100644 --- a/src/game/mplayer/scenarios/holdthebriefcase.inc +++ b/src/game/mplayer/scenarios/holdthebriefcase.inc @@ -320,13 +320,8 @@ void htbTick(void) // Check if a simulant is holding it if (g_ScenarioData.htb.token == NULL) { for (i = PLAYERCOUNT(); i < g_MpNumChrs; i++) { -#if VERSION >= VERSION_NTSC_1_0 - if (g_MpAllChrPtrs[i]->prop && g_MpAllChrPtrs[i]->aibot->hasbriefcase) -#else - if (g_MpAllChrPtrs[i]->aibot->hasbriefcase) -#endif - { - g_ScenarioData.htb.token = g_MpAllChrPtrs[i]->prop; + if (g_MpChrs[i].chr->prop && g_MpChrs[i].chr->aibot->hasbriefcase) { + g_ScenarioData.htb.token = g_MpChrs[i].chr->prop; break; } } @@ -356,7 +351,7 @@ void htbTickChr(struct chrdata *chr) if (chr->aibot->unk0a0 >= TICKS(7200)) { sndStart(var80095200, SFX_MP_SCOREPOINT, NULL, -1, -1, -1, -1, -1); - g_MpAllChrConfigPtrs[mpPlayerGetIndex(chr)]->numpoints++; + g_MpChrs[chr->chrnum].numpoints++; chr->aibot->unk0a0 = 0; } } else { @@ -368,7 +363,7 @@ void htbTickChr(struct chrdata *chr) if (g_Vars.currentplayerstats->tokenheldtime >= TICKS(7200)) { sndStart(var80095200, SFX_MP_SCOREPOINT, NULL, -1, -1, -1, -1, -1); - g_MpAllChrConfigPtrs[g_Vars.currentplayernum]->numpoints++; + g_MpChrs[g_Vars.currentplayernum].numpoints++; #if VERSION >= VERSION_JPN_FINAL hudmsgCreateWithFlags(langGet(L_MPWEAPONS_024), HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE | HUDMSGFLAG_NOWRAP); // "1 Point!" #else @@ -437,9 +432,9 @@ Gfx *htbRenderHud(Gfx *gdl) return gdl; } -void htbCalculatePlayerScore(struct mpchrconfig *mpchr, s32 mpchrnum, s32 *score, s32 *deaths) +void htbCalculatePlayerScore(struct mpchr *mpchr, s32 mpchrnum, s32 *score, s32 *deaths) { - struct mpchrconfig *loopmpchr; + struct mpchr *loopmpchr; s32 i; *score = 0; @@ -494,7 +489,7 @@ bool htbRadarChr(Gfx **gdl, struct prop *prop) dist.z = prop->pos.z - g_Vars.currentplayer->prop->pos.z; if (g_MpSetup.options & MPOPTION_TEAMSENABLED) { - u32 colour = g_TeamColours[radarGetTeamIndex(prop->chr->team)]; + u32 colour = g_TeamColours[prop->chr->team]; *gdl = radarDrawDot(*gdl, g_ScenarioData.htb.token, &dist, colour, 0, 1); } else { *gdl = radarDrawDot(*gdl, g_ScenarioData.htb.token, &dist, 0x00ff0000, 0, 1); diff --git a/src/game/mplayer/scenarios/kingofthehill.inc b/src/game/mplayer/scenarios/kingofthehill.inc index 31b72100e..2057e01c9 100644 --- a/src/game/mplayer/scenarios/kingofthehill.inc +++ b/src/game/mplayer/scenarios/kingofthehill.inc @@ -337,7 +337,7 @@ void kohTick(void) for (s0 = 0, numteamsinhill = 0; s0 < numchrsinhill; s0++) { chr = chrsinhill[s0]->chr; - teamindex = radarGetTeamIndex(chr->team); + teamindex = chr->team; if (teamsinhill[teamindex] == 0) { numteamsinhill++; @@ -428,14 +428,14 @@ void kohTick(void) chr = g_Vars.currentplayer->prop->chr; #if VERSION >= VERSION_JPN_FINAL - if (radarGetTeamIndex(chr->team) == g_ScenarioData.koh.occupiedteam) { + if (chr->team == g_ScenarioData.koh.occupiedteam) { // "We have the Hill!" hudmsgCreateWithFlags(langGet(L_MPWEAPONS_021), HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE | HUDMSGFLAG_NOWRAP); } else { hudmsgCreateWithFlags(text, HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE | HUDMSGFLAG_NOWRAP); } #else - if (radarGetTeamIndex(chr->team) == g_ScenarioData.koh.occupiedteam) { + if (chr->team == g_ScenarioData.koh.occupiedteam) { // "We have the Hill!" hudmsgCreateWithFlags(langGet(L_MPWEAPONS_021), HUDMSGTYPE_MPSCENARIO, HUDMSGFLAG_ONLYIFALIVE); } else { @@ -460,11 +460,11 @@ void kohTick(void) // "press start" screen while their team mate scores the // hill, the dead player will always be awarded a point. for (playernum2 = 0; playernum2 < g_MpNumChrs; playernum2++) { - if (radarGetTeamIndex(g_MpAllChrPtrs[playernum2]->team) == g_ScenarioData.koh.occupiedteam) { - prop = g_MpAllChrPtrs[playernum2]->prop; + if (g_MpChrs[playernum2].team == g_ScenarioData.koh.occupiedteam) { + prop = g_MpChrs[playernum2].chr->prop; if (prop->rooms[0] == g_ScenarioData.koh.hillrooms[0]) { - g_MpAllChrConfigPtrs[playernum2]->numpoints++; + g_MpChrs[playernum2].numpoints++; } } } @@ -472,8 +472,8 @@ void kohTick(void) prevplayernum1 = g_Vars.currentplayernum; for (playernum2 = 0; playernum2 < g_MpNumChrs; playernum2++) { - if (g_MpAllChrPtrs[playernum2]->aibot == NULL - && radarGetTeamIndex(g_MpAllChrPtrs[playernum2]->team) == g_ScenarioData.koh.occupiedteam) { + if (g_MpChrs[playernum2].chr->aibot == NULL + && g_MpChrs[playernum2].team == g_ScenarioData.koh.occupiedteam) { setCurrentPlayerNum(playernum2); // "King of the Hill!" @@ -559,7 +559,7 @@ Gfx *kohRenderHud(Gfx *gdl) struct chrdata *chr = g_Vars.currentplayer->prop->chr; char text[64]; - if (radarGetTeamIndex(chr->team) == g_ScenarioData.koh.occupiedteam && !g_ScenarioData.koh.movehill) { + if (chr->team == g_ScenarioData.koh.occupiedteam && !g_ScenarioData.koh.movehill) { x = viGetViewLeft() + viGetViewWidth() / 2; y = viGetViewTop() + 10; @@ -600,9 +600,9 @@ Gfx *kohRenderHud(Gfx *gdl) return gdl; } -void kohCalculatePlayerScore(struct mpchrconfig *mpchr, s32 mpchrnum, s32 *score, s32 *deaths) +void kohCalculatePlayerScore(struct mpchr *mpchr, s32 mpchrnum, s32 *score, s32 *deaths) { - struct mpchrconfig *loopmpchr; + struct mpchr *loopmpchr; s32 i; *score = 0; diff --git a/src/game/mplayer/scenarios/popacap.inc b/src/game/mplayer/scenarios/popacap.inc index 7ffccfb10..07f2b9d8c 100644 --- a/src/game/mplayer/scenarios/popacap.inc +++ b/src/game/mplayer/scenarios/popacap.inc @@ -177,7 +177,7 @@ bool pacHighlightProp(struct prop *prop, s32 *colour) if (g_MpSetup.options & MPOPTION_PAC_HIGHLIGHTTARGET && (prop->type == PROPTYPE_PLAYER || prop->type == PROPTYPE_CHR) && data->victimindex != -1 - && prop->chr == g_MpAllChrPtrs[data->victims[data->victimindex]]) { + && prop->chr == g_MpChrs[data->victims[data->victimindex]].chr) { colour[0] = 0; colour[1] = 0xff; colour[2] = 0; @@ -209,17 +209,9 @@ void pacApplyNextVictim(void) if (vplayernum == i) { sprintf(text, langGet(L_MPWEAPONS_013)); // "You are the victim!" } else if (scenarioChrsAreSameTeam(vplayernum, i)) { -#if VERSION >= VERSION_JPN_FINAL - sprintf(text, langGet(L_MPWEAPONS_014), scenarioRemoveLineBreaks(g_MpAllChrConfigPtrs[vplayernum]->name, 0)); // "Protect %s!" -#else - sprintf(text, langGet(L_MPWEAPONS_014), g_MpAllChrConfigPtrs[vplayernum]->name); // "Protect %s!" -#endif + sprintf(text, langGet(L_MPWEAPONS_014), g_MpChrs[vplayernum].config->name); // "Protect %s!" } else { -#if VERSION >= VERSION_JPN_FINAL - sprintf(text, langGet(L_MPWEAPONS_015), scenarioRemoveLineBreaks(g_MpAllChrConfigPtrs[vplayernum]->name, 0)); // "Get %s!" -#else - sprintf(text, langGet(L_MPWEAPONS_015), g_MpAllChrConfigPtrs[vplayernum]->name); // "Get %s!" -#endif + sprintf(text, langGet(L_MPWEAPONS_015), g_MpChrs[vplayernum].config->name); // "Get %s!" } scenarioCreateHudmsg(i, text); @@ -331,14 +323,14 @@ Gfx *pacRenderHud(Gfx *gdl) return gdl; } -void pacCalculatePlayerScore(struct mpchrconfig *mpchr, s32 mpchrnum, s32 *score, s32 *arg3) +void pacCalculatePlayerScore(struct mpchr *mpchr, s32 mpchrnum, s32 *score, s32 *arg3) { - struct mpchrconfig *loopmpchr; + struct mpchr *loopmpchr; s32 i; s32 index; *score = 0; - index = func0f18d0e8(mpchrnum); + index = mpchrnum; if (index >= 0) { *score += g_ScenarioData.pac.killcounts[index] * 2; @@ -377,7 +369,7 @@ bool pacRadarChr(Gfx **gdl, struct prop *prop) struct coord dist; if ((g_MpSetup.options & MPOPTION_PAC_SHOWONRADAR) && data->victimindex >= 0) { - struct prop *vprop = g_MpAllChrPtrs[data->victims[data->victimindex]]->prop; + struct prop *vprop = g_MpChrs[data->victims[data->victimindex]].chr->prop; if (vprop == prop) { dist.x = prop->pos.x - g_Vars.currentplayer->prop->pos.x; @@ -385,7 +377,7 @@ bool pacRadarChr(Gfx **gdl, struct prop *prop) dist.z = prop->pos.z - g_Vars.currentplayer->prop->pos.z; if (g_MpSetup.options & MPOPTION_TEAMSENABLED) { - u32 colour = g_TeamColours[radarGetTeamIndex(prop->chr->team)]; + u32 colour = g_TeamColours[prop->chr->team]; *gdl = radarDrawDot(*gdl, vprop, &dist, colour, 0, 1); } else { *gdl = radarDrawDot(*gdl, vprop, &dist, 0x00ff0000, 0, 1); diff --git a/src/game/mplayer/setup.c b/src/game/mplayer/setup.c index ee989c040..b76cc7ba1 100644 --- a/src/game/mplayer/setup.c +++ b/src/game/mplayer/setup.c @@ -416,15 +416,15 @@ s32 menuhandlerMpDisplayOptionCheckbox(s32 operation, struct menuitem *item, uni { switch (operation) { case MENUOP_GET: - if ((g_PlayerConfigsArray[g_MpPlayerNum].base.displayoptions & item->param3) == 0) { + if ((g_PlayerConfigsArray[g_MpPlayerNum].displayoptions & item->param3) == 0) { return false; } return true; case MENUOP_SET: - g_PlayerConfigsArray[g_MpPlayerNum].base.displayoptions &= ~(u8)item->param3; + g_PlayerConfigsArray[g_MpPlayerNum].displayoptions &= ~(u8)item->param3; if (data->checkbox.value) { - g_PlayerConfigsArray[g_MpPlayerNum].base.displayoptions |= (u8)item->param3; + g_PlayerConfigsArray[g_MpPlayerNum].displayoptions |= (u8)item->param3; } break; } @@ -3196,43 +3196,35 @@ struct menudialogdef g_MpSimulantsMenuDialog = { s32 menuhandlerMpNTeams(s32 operation, struct menuitem *item, union handlerdata *data, s32 numteams) { if (operation == MENUOP_SET) { - s32 numchrs = mpGetNumChrs(); + s32 numconfigs = mpGetNumConfigs(); s32 array[] = {0, 0, 0, 0}; - s32 somevalue = (numchrs + numteams - 1) / numteams; + s32 somevalue = (numconfigs + numteams - 1) / numteams; s32 teamsremaining = numteams; - s32 chrsremaining = numchrs; - s32 start = random() % numchrs; + s32 configsremaining = numconfigs; + s32 start = random() % numconfigs; s32 i; s32 teamnum; -#if VERSION >= VERSION_NTSC_1_0 - if (!numchrs) { + if (!numconfigs) { return 0; } -#endif - i = (start + 1) % numchrs; + i = (start + 1) % numconfigs; do { - struct mpchrconfig *mpchr = mpGetChrConfigBySlotNum(i); + struct mpchrconfig *mpcfg = mpGetChrConfigBySlotNum(i); -#if VERSION >= VERSION_NTSC_1_0 - if (teamsremaining); -#else - if (start); -#endif - - if (teamsremaining >= chrsremaining) { + if (teamsremaining >= configsremaining) { teamnum = random() % numteams; while (true) { if (array[teamnum] == 0) { - mpchr->team = teamnum; + mpcfg->team = teamnum; array[teamnum]++; teamsremaining--; - chrsremaining--; + configsremaining--; break; } else { teamnum = (teamnum + 1) % numteams; @@ -3243,14 +3235,14 @@ s32 menuhandlerMpNTeams(s32 operation, struct menuitem *item, union handlerdata while (true) { if (array[teamnum] < somevalue) { - mpchr->team = teamnum; + mpcfg->team = teamnum; if (array[teamnum] == 0) { teamsremaining--; } array[teamnum]++; - chrsremaining--; + configsremaining--; break; } else { teamnum = (teamnum + 1) % numteams; @@ -3262,7 +3254,7 @@ s32 menuhandlerMpNTeams(s32 operation, struct menuitem *item, union handlerdata break; } - i = (i + 1) % numchrs; + i = (i + 1) % numconfigs; } while (true); menuPopDialog(); @@ -3294,9 +3286,9 @@ s32 menuhandlerMpMaximumTeams(s32 operation, struct menuitem *item, union handle for (i = 0; i != MAX_MPCHRS; i++) { if (g_MpSetup.chrslots & (1 << i)) { - struct mpchrconfig *mpchr = MPCHR(i); + struct mpchrconfig *mpcfg = MPCHRCONFIG(i); - mpchr->team = team++; + mpcfg->team = team++; if (team >= scenarioGetMaxTeams()) { team = 0; @@ -3317,9 +3309,9 @@ s32 menuhandlerMpHumansVsSimulants(s32 operation, struct menuitem *item, union h for (i = 0; i != MAX_MPCHRS; i++) { if (g_MpSetup.chrslots & (1 << i)) { - struct mpchrconfig *mpchr = MPCHR(i); + struct mpchrconfig *mpcfg = MPCHRCONFIG(i); - mpchr->team = i < 4 ? 0 : 1; + mpcfg->team = i < 4 ? 0 : 1; } } @@ -3339,12 +3331,12 @@ s32 menuhandlerMpHumanSimulantPairs(s32 operation, struct menuitem *item, union for (i = 0; i != MAX_MPCHRS; i++) { if (g_MpSetup.chrslots & (1 << i)) { - struct mpchrconfig *mpchr = MPCHR(i); + struct mpchrconfig *mpcfg = MPCHRCONFIG(i); if (i < 4) { - mpchr->team = team_ids[playerindex++]; + mpcfg->team = team_ids[playerindex++]; } else { - mpchr->team = team_ids[simindex++]; + mpcfg->team = team_ids[simindex++]; if (simindex >= playerindex) { simindex = 0; @@ -3361,16 +3353,10 @@ s32 menuhandlerMpHumanSimulantPairs(s32 operation, struct menuitem *item, union char *mpMenuTextChrNameForTeamSetup(struct menuitem *item) { - struct mpchrconfig *mpchr = mpGetChrConfigBySlotNum(item->param); + struct mpchrconfig *mpcfg = mpGetChrConfigBySlotNum(item->param); - if (mpchr) { - if (mpchr >= &g_BotConfigsArray[0].base && mpchr < &g_BotConfigsArray[MAX_BOTS].base) { - struct mpbotconfig *botconfig = (struct mpbotconfig *) mpchr; - sprintf(g_StringPointer, "%dx %s\n", botconfig->quantity, mpchr->name); - return g_StringPointer; - } - - return mpchr->name; + if (mpcfg) { + return mpcfg->name; } return ""; @@ -3395,27 +3381,27 @@ s32 func0f17dac4(s32 operation, struct menuitem *item, union handlerdata *data) s32 menuhandlerMpTeamSlot(s32 operation, struct menuitem *item, union handlerdata *data) { - struct mpchrconfig *mpchr; + struct mpchrconfig *mpcfg; switch (operation) { case MENUOP_SET: - mpchr = mpGetChrConfigBySlotNum(item->param); - mpchr->team = data->dropdown.value; + mpcfg = mpGetChrConfigBySlotNum(item->param); + mpcfg->team = data->dropdown.value; break; case MENUOP_GETSELECTEDINDEX: - mpchr = mpGetChrConfigBySlotNum(item->param); + mpcfg = mpGetChrConfigBySlotNum(item->param); - if (!mpchr) { + if (!mpcfg) { data->dropdown.value = 0xff; } else { - data->dropdown.value = mpchr->team; + data->dropdown.value = mpcfg->team; } break; case MENUOP_CHECKDISABLED: - mpchr = mpGetChrConfigBySlotNum(item->param); + mpcfg = mpGetChrConfigBySlotNum(item->param); - if (!mpchr) { + if (!mpcfg) { return 1; } @@ -4814,7 +4800,7 @@ void mpConfigureQuickTeamPlayers(void) void mpConfigureQuickTeamSimulants(void) { - struct mpchrconfig *mpchr; + struct mpchrconfig *mpcfg; s32 numchrs; s32 botnum; s32 i; @@ -4851,14 +4837,14 @@ void mpConfigureQuickTeamSimulants(void) break; case MPQUICKTEAM_PLAYERSIMTEAMS: for (i = mpGetNumChrs() - 1; i >= 0; i--) { - mpchr = mpGetChrConfigBySlotNum(i); + mpcfg = mpGetChrConfigBySlotNum(i); for (j = 0; j < g_Vars.unk0004a0; j++) { botnum = mpGetSlotForNewBot(); if (botnum >= 0) { mpCreateBotFromProfile(botnum, g_Vars.mpsimdifficulty); - g_BotConfigsArray[botnum].base.team = mpchr->team; + g_BotConfigsArray[botnum].base.team = mpcfg->team; } } } diff --git a/src/game/mpstats.c b/src/game/mpstats.c index 4ba3908e2..e96f99ee5 100644 --- a/src/game/mpstats.c +++ b/src/game/mpstats.c @@ -137,7 +137,7 @@ void mpstatsRecordPlayerSuicide(void) s32 duration; s32 time; s32 mpindex; - struct mpchrconfig *mpchr; + struct mpchr *mpchr; if (g_Vars.normmplayerisrunning) { time = playerGetMissionTime(); @@ -192,9 +192,9 @@ void mpstatsRecordPlayerSuicide(void) void mpstatsRecordDeath(s32 aplayernum, s32 vplayernum) { s32 vmpindex = -1; - struct mpchrconfig *vmpchr = NULL; + struct mpchr *vmpchr = NULL; s32 ampindex; - struct mpchrconfig *ampchr = NULL; + struct mpchr *ampchr = NULL; s32 prevplayernum; char text[256]; @@ -204,7 +204,7 @@ void mpstatsRecordDeath(s32 aplayernum, s32 vplayernum) // Find attacker and victim mpchrs if (aplayernum >= 0) { - ampindex = func0f18d074(aplayernum); + ampindex = aplayernum; if (ampindex >= 0) { ampchr = MPCHR(ampindex); @@ -212,7 +212,7 @@ void mpstatsRecordDeath(s32 aplayernum, s32 vplayernum) } if (vplayernum >= 0) { - vmpindex = func0f18d074(vplayernum); + vmpindex = vplayernum; if (vmpindex >= 0) { vmpchr = MPCHR(vmpindex); @@ -246,7 +246,7 @@ void mpstatsRecordDeath(s32 aplayernum, s32 vplayernum) if (g_Vars.normmplayerisrunning && aplayernum >= 0) { // "Killed by %s" - sprintf(text, "%s %s", langGet(L_MISC_183), g_MpAllChrConfigPtrs[aplayernum]->name); + sprintf(text, "%s %s", langGet(L_MISC_183), g_MpChrs[aplayernum].config->name); hudmsgCreate(text, HUDMSGTYPE_DEFAULT); } @@ -266,7 +266,7 @@ void mpstatsRecordDeath(s32 aplayernum, s32 vplayernum) if (g_Vars.normmplayerisrunning && vplayernum >= 0) { // "Killed %s" - sprintf(text, "%s %s", langGet(L_MISC_184), g_MpAllChrConfigPtrs[vplayernum]->name); + sprintf(text, "%s %s", langGet(L_MISC_184), g_MpChrs[vplayernum].config->name); hudmsgCreate(text, HUDMSGTYPE_DEFAULT); } @@ -279,18 +279,18 @@ void mpstatsRecordDeath(s32 aplayernum, s32 vplayernum) && aplayernum >= 0 && vplayernum >= PLAYERCOUNT() && aplayernum != vplayernum) { - g_MpAllChrPtrs[vplayernum]->aibot->lastkilledbyplayernum = aplayernum; + g_MpChrs[vplayernum].chr->aibot->lastkilledbyplayernum = aplayernum; } } - if (g_Vars.normmplayerisrunning && aplayernum >= 0 && g_MpAllChrPtrs[aplayernum]->aibot) { - s32 index = mpGetWeaponSlotByWeaponNum(g_MpAllChrPtrs[aplayernum]->aibot->weaponnum); + if (g_Vars.normmplayerisrunning && aplayernum >= 0 && g_MpChrs[aplayernum].chr->aibot) { + s32 index = mpGetWeaponSlotByWeaponNum(g_MpChrs[aplayernum].chr->aibot->weaponnum); if (index >= 0) { if (aplayernum == vplayernum) { - g_MpAllChrPtrs[aplayernum]->aibot->suicidesbygunfunc[index][g_MpAllChrPtrs[aplayernum]->aibot->gunfunc]++; + g_MpChrs[aplayernum].chr->aibot->suicidesbygunfunc[index][g_MpChrs[aplayernum].chr->aibot->gunfunc]++; } else { - g_MpAllChrPtrs[aplayernum]->aibot->killsbygunfunc[index][g_MpAllChrPtrs[aplayernum]->aibot->gunfunc]++; + g_MpChrs[aplayernum].chr->aibot->killsbygunfunc[index][g_MpChrs[aplayernum].chr->aibot->gunfunc]++; } } } diff --git a/src/game/player.c b/src/game/player.c index 7d5b4439b..bdb23b47c 100644 --- a/src/game/player.c +++ b/src/game/player.c @@ -257,13 +257,15 @@ f32 playerChooseSpawnLocation(f32 chrradius, struct coord *dstpos, s16 *dstrooms roomGetNeighbours(pad.room, neighbours, 20); - for (i = 0; i < g_BotCount; i++) { - if (g_MpBotChrPtrs[i]->prop - && g_MpBotChrPtrs[i]->prop != prop - && (!prop || chrCompareTeams(prop->chr, g_MpBotChrPtrs[i], COMPARE_ENEMIES))) { - xdiff = g_MpBotChrPtrs[i]->prop->pos.x - pad.pos.x; - ydiff = g_MpBotChrPtrs[i]->prop->pos.y - pad.pos.y; - zdiff = g_MpBotChrPtrs[i]->prop->pos.z - pad.pos.z; + for (i = playercount; i < g_MpNumChrs; i++) { + struct chrdata *chr = g_MpChrs[i].chr; + + if (chr->prop + && chr->prop != prop + && (!prop || chrCompareTeams(prop->chr, chr, COMPARE_ENEMIES))) { + xdiff = chr->prop->pos.x - pad.pos.x; + ydiff = chr->prop->pos.y - pad.pos.y; + zdiff = chr->prop->pos.z - pad.pos.z; sqdist = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff; @@ -271,11 +273,11 @@ f32 playerChooseSpawnLocation(f32 chrradius, struct coord *dstpos, s16 *dstrooms bestsqdist = sqdist; } - if (arrayIntersects(tmppadrooms, g_MpBotChrPtrs[i]->prop->rooms)) { + if (arrayIntersects(tmppadrooms, chr->prop->rooms)) { verybadpads[p] = true; } - if (verybadpads[p] || arrayIntersects(neighbours, g_MpBotChrPtrs[i]->prop->rooms)) { + if (verybadpads[p] || arrayIntersects(neighbours, chr->prop->rooms)) { badpads[p] = true; } } @@ -924,11 +926,6 @@ void playerTickChrBody(void) g_Vars.currentplayer->prop->type = PROPTYPE_PLAYER; chr = g_Vars.currentplayer->prop->chr; - if (g_Vars.mplayerisrunning) { - g_MpAllChrPtrs[g_Vars.currentplayernum] = chr; - g_MpAllChrConfigPtrs[g_Vars.currentplayernum] = &g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].base; - } - chr->chrflags |= CHRCFLAG_00000001; modelSetRootPosition(g_Vars.currentplayer->model00d4, &g_Vars.currentplayer->prop->pos); diff --git a/src/game/playermgr.c b/src/game/playermgr.c index 7a33c9cdc..ef6b567e8 100644 --- a/src/game/playermgr.c +++ b/src/game/playermgr.c @@ -605,10 +605,7 @@ void playermgrAllocatePlayer(s32 index) g_Vars.players[index]->lookaheadframe = 0; g_Vars.players[index]->numaibuddies = 0; - - for (i = 0; i < MAX_BOTS; i++) { - g_Vars.players[index]->aibuddynums[i] = 0; - } + g_Vars.players[index]->aibuddynums = NULL; g_Vars.players[index]->teleportstate = TELEPORTSTATE_INACTIVE; g_Vars.players[index]->teleporttime = 0; @@ -635,13 +632,23 @@ void playermgrAllocatePlayer(s32 index) void playermgrCalculateAiBuddyNums(void) { - s32 i; + s32 chrnum; s32 playernum = g_Vars.currentplayernum; s32 playercount = PLAYERCOUNT(); + s32 numbuddies = 0; - for (i = playercount; i < g_MpNumChrs; i++) { - if (g_MpAllChrConfigPtrs[i]->team == g_MpAllChrConfigPtrs[playernum]->team) { - g_Vars.players[playernum]->aibuddynums[g_Vars.players[playernum]->numaibuddies] = i; + for (chrnum = playercount; chrnum < g_MpNumChrs; chrnum++) { + if (g_MpChrs[chrnum].team == g_MpChrs[playernum].team) { + numbuddies++; + } + } + + g_Vars.players[playernum]->aibuddynums = mempAlloc(numbuddies * sizeof(s16), MEMPOOL_STAGE); + g_Vars.players[playernum]->numaibuddies = 0; + + for (chrnum = playercount; chrnum < g_MpNumChrs; chrnum++) { + if (g_MpChrs[chrnum].team == g_MpChrs[playernum].team) { + g_Vars.players[playernum]->aibuddynums[g_Vars.players[playernum]->numaibuddies] = chrnum; g_Vars.players[playernum]->numaibuddies++; } } diff --git a/src/game/playerreset.c b/src/game/playerreset.c index 7ec2eeb59..6f666c52d 100644 --- a/src/game/playerreset.c +++ b/src/game/playerreset.c @@ -172,7 +172,12 @@ void playerReset(void) propEnable(g_Vars.currentplayer->prop); chrInit(g_Vars.currentplayer->prop); - g_Vars.currentplayer->prop->chr->team = 1 << g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].base.team; + g_MpChrs[g_Vars.currentplayernum].chr = g_Vars.currentplayer->prop->chr; + + chrSetChrnum(g_Vars.currentplayer->prop->chr, g_Vars.currentplayernum); + g_Vars.currentplayer->prop->chr->chrnum = g_Vars.currentplayernum; + + g_Vars.currentplayer->prop->chr->team = g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].base.team; if (g_NumSpawnPoints > 0) { turnanglerad = M_BADTAU - scenarioChooseSpawnLocation(30, &pos, rooms, g_Vars.currentplayer->prop); diff --git a/src/game/propobj.c b/src/game/propobj.c index 80b0bc431..b76d5b126 100644 --- a/src/game/propobj.c +++ b/src/game/propobj.c @@ -1991,8 +1991,8 @@ void objFree(struct defaultobj *obj, bool freeprop, bool canregen) s32 i; for (i = 0; i < g_MpNumChrs; i++) { - if (g_MpAllChrPtrs[i]->aibot && g_MpAllChrPtrs[i]->aibot->skrocket == obj->prop) { - g_MpAllChrPtrs[i]->aibot->skrocket = NULL; + if (g_MpChrs[i].chr->aibot && g_MpChrs[i].chr->aibot->skrocket == obj->prop) { + g_MpChrs[i].chr->aibot->skrocket = NULL; } } } @@ -2062,8 +2062,8 @@ void objFree(struct defaultobj *obj, bool freeprop, bool canregen) s32 i; for (i = 0; i < g_MpNumChrs; i++) { - if (g_MpAllChrPtrs[i]->aibot && g_MpAllChrPtrs[i]->aibot->gotoprop == obj->prop) { - g_MpAllChrPtrs[i]->aibot->gotoprop = NULL; + if (g_MpChrs[i].chr->aibot && g_MpChrs[i].chr->aibot->gotoprop == obj->prop) { + g_MpChrs[i].chr->aibot->gotoprop = NULL; } } } @@ -3905,7 +3905,7 @@ void weaponTick(struct prop *prop) s32 i; if (g_Vars.normmplayerisrunning) { - struct chrdata *chr = mpGetChrFromPlayerIndex(ownerplayernum); + struct chrdata *chr = g_MpChrs[ownerplayernum].chr; if (chr) { ownerprop = chr->prop; @@ -3965,7 +3965,7 @@ void weaponTick(struct prop *prop) // If a player manages to throw a mine on themselves, it will not detonate. // You can't throw a mine on yourself anyway, so this check always passes - if (prop->parent == NULL || parentchr == NULL || mpPlayerGetIndex(parentchr) != ownerplayernum) { + if (prop->parent == NULL || parentchr == NULL || parentchr->chrnum != ownerplayernum) { if (g_PlayersDetonatingMines & 1 << ownerplayernum) { weapon->timer240 = 0; } @@ -4025,7 +4025,7 @@ void weaponTick(struct prop *prop) s32 ownerplayernum = (obj->hidden & 0xf0000000) >> 28; if (g_Vars.normmplayerisrunning) { - struct chrdata *chr = mpGetChrFromPlayerIndex(ownerplayernum); + struct chrdata *chr = g_MpChrs[ownerplayernum].chr; if (chr) { ownerprop = chr->prop; @@ -4401,7 +4401,7 @@ glabel var7f1aa2c4 /* f06ea90: 13200008 */ beqz $t9,.NB0f06eab4 /* f06ea94: 000f2702 */ srl $a0,$t7,0x1c /* f06ea98: afa00158 */ sw $zero,0x158($sp) -/* f06ea9c: 0fc61c91 */ jal mpGetChrFromPlayerIndex +/* f06ea9c: 0fc61c91 */ jal mpGetChrFromPlayernum /* f06eaa0: afa70170 */ sw $a3,0x170($sp) /* f06eaa4: 8fa50158 */ lw $a1,0x158($sp) /* f06eaa8: 10400002 */ beqz $v0,.NB0f06eab4 @@ -4526,7 +4526,7 @@ glabel var7f1aa2c4 /* f06ec60: 10800009 */ beqz $a0,.NB0f06ec88 /* f06ec64: 00000000 */ sll $zero,$zero,0x0 /* f06ec68: afa3014c */ sw $v1,0x14c($sp) -/* f06ec6c: 0fc61c7f */ jal mpPlayerGetIndex +/* f06ec6c: 0fc61c7f */ jal mpGetPlayernumFromChr /* f06ec70: afa70170 */ sw $a3,0x170($sp) /* f06ec74: 8fa3014c */ lw $v1,0x14c($sp) /* f06ec78: 3c058007 */ lui $a1,0x8007 @@ -4733,7 +4733,7 @@ glabel var7f1aa2c4 /* f06ef58: 11200008 */ beqz $t1,.NB0f06ef7c /* f06ef5c: 000d2702 */ srl $a0,$t5,0x1c /* f06ef60: afa00128 */ sw $zero,0x128($sp) -/* f06ef64: 0fc61c91 */ jal mpGetChrFromPlayerIndex +/* f06ef64: 0fc61c91 */ jal mpGetChrFromPlayernum /* f06ef68: afa70170 */ sw $a3,0x170($sp) /* f06ef6c: 8fa50128 */ lw $a1,0x128($sp) /* f06ef70: 10400002 */ beqz $v0,.NB0f06ef7c @@ -6191,7 +6191,7 @@ bool rocketTickFbw(struct weaponobj *rocket) // Check if close to an enemy if (ownerchr && rocket->timer240) { for (i = 0; i < g_MpNumChrs; i++) { - struct chrdata *chr = mpGetChrFromPlayerIndex(i); + struct chrdata *chr = g_MpChrs[i].chr; if (chr != ownerchr && !chrIsDead(chr) @@ -6209,7 +6209,7 @@ bool rocketTickFbw(struct weaponobj *rocket) // Check if rocket can fly directly to target if (chrGetTargetProp(ownerchr) == chr->prop - && mpPlayerGetIndex(ownerchr) == g_Vars.lvframenum % g_MpNumChrs + && ownerchr->chrnum == g_Vars.lvframenum % g_MpNumChrs && cdTestLos05(&rocketprop->pos, rocketprop->rooms, &chr->prop->pos, chr->prop->rooms, CDTYPE_OBJS | CDTYPE_DOORS | CDTYPE_PATHBLOCKER | CDTYPE_BG | CDTYPE_AIOPAQUE, GEOFLAG_BLOCK_SIGHT)) { @@ -7099,7 +7099,7 @@ s32 projectileTick(struct defaultobj *obj, bool *embedded) struct prop *ownerprop2 = NULL; if (g_Vars.normmplayerisrunning) { - struct chrdata *ownerchr = mpGetChrFromPlayerIndex(ownerplayernum); + struct chrdata *ownerchr = g_MpChrs[ownerplayernum].chr; if (ownerchr != NULL) { ownerprop2 = ownerchr->prop; @@ -8359,7 +8359,7 @@ void autogunTick(struct prop *prop) continue; } - chr = g_MpAllChrPtrs[autogun->nextchrtest]; + chr = g_MpChrs[autogun->nextchrtest].chr; if (!chr->prop) { continue; @@ -8770,7 +8770,7 @@ void autogunTickShoot(struct prop *autogunprop) if (g_Vars.normmplayerisrunning) { // Multiplayer - it must be a laptop gun - ownerchr = mpGetChrFromPlayerIndex(ownerplayernum); + ownerchr = g_MpChrs[ownerplayernum].chr; if (ownerchr) { ownerprop = ownerchr->prop; @@ -11896,7 +11896,7 @@ bool propobjInteract(struct prop *prop) s32 playernum; if (g_Vars.normmplayerisrunning) { - playernum = mpPlayerGetIndex(g_Vars.currentplayer->prop->chr); + playernum = g_Vars.currentplayer->prop->chr->chrnum; } else { playernum = g_Vars.currentplayernum; } @@ -13628,7 +13628,7 @@ bool chrEquipWeapon(struct weaponobj *weapon, struct chrdata *chr) if (weapon->base.prop && weapon->base.model) { if (g_Vars.mplayerisrunning) { - s32 playernum = mpPlayerGetIndex(chr); + s32 playernum = chr->chrnum; weapon->base.hidden &= 0x0fffffff; weapon->base.hidden |= (playernum << 28) & 0xf0000000; @@ -13743,7 +13743,7 @@ struct autogunobj *laptopDeploy(s32 modelnum, struct gset *gset, struct chrdata s32 index; if (g_Vars.normmplayerisrunning) { - index = mpPlayerGetIndex(chr); + index = chr->chrnum; } else { index = playermgrGetPlayerNumByProp(chr->prop); } @@ -13958,7 +13958,7 @@ struct weaponobj *weaponCreateProjectileFromGset(s32 modelnum, struct gset *gset prop = func0f08adc8(weapon, modeldef, prop, model); if (g_Vars.mplayerisrunning) { - s32 index = mpPlayerGetIndex(chr); + s32 index = chr->chrnum; weapon->base.hidden &= 0x0fffffff; weapon->base.hidden |= ((index << 28) & 0xf0000000); diff --git a/src/game/radar.c b/src/game/radar.c index 1c44f90cc..9f7d9de96 100644 --- a/src/game/radar.c +++ b/src/game/radar.c @@ -86,31 +86,6 @@ Gfx *radarRenderBackground(Gfx *gdl, struct textureconfig *tconfig, s32 arg2, s3 return gdl; } -s32 radarGetTeamIndex(s32 team) -{ - s32 index = 0; - - if (team & 1) { - index = 0; - } else if (team & 0x02) { - index = 1; - } else if (team & 0x04) { - index = 2; - } else if (team & 0x08) { - index = 3; - } else if (team & 0x10) { - index = 4; - } else if (team & 0x20) { - index = 5; - } else if (team & 0x40) { - index = 6; - } else if (team & 0x80) { - index = 7; - } - - return index; -} - Gfx *radarDrawDot(Gfx *gdl, struct prop *prop, struct coord *dist, u32 colour1, u32 colour2, bool swapcolours) { s32 x; @@ -250,7 +225,7 @@ Gfx *radarRender(Gfx *gdl) return gdl; } - if ((g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].base.displayoptions & 0x00000004) == 0) { + if ((g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].displayoptions & 0x00000004) == 0) { return gdl; } @@ -317,7 +292,7 @@ Gfx *radarRender(Gfx *gdl) pos.y = g_Vars.players[i]->prop->pos.y - g_Vars.currentplayer->prop->pos.y; pos.z = g_Vars.players[i]->prop->pos.z - g_Vars.currentplayer->prop->pos.z; - if (g_Vars.normmplayerisrunning && (g_MpSetup.options & MPOPTION_TEAMSENABLED)) { + if (g_MpSetup.options & MPOPTION_TEAMSENABLED) { s32 index = g_PlayerConfigsArray[g_Vars.playerstats[i].mpindex].base.team; colour = g_TeamColours[index]; } else { @@ -330,21 +305,23 @@ Gfx *radarRender(Gfx *gdl) } // Draw dots for MP simulants - for (i = 0; i < g_BotCount; i++) { - if (!chrIsDead(g_MpBotChrPtrs[i]) - && (g_MpBotChrPtrs[i]->hidden & CHRHFLAG_CLOAKED) == 0 - && scenarioRadarChr(&gdl, g_MpBotChrPtrs[i]->prop) == false) { - pos.x = g_MpBotChrPtrs[i]->prop->pos.x - g_Vars.currentplayer->prop->pos.x; - pos.y = g_MpBotChrPtrs[i]->prop->pos.y - g_Vars.currentplayer->prop->pos.y; - pos.z = g_MpBotChrPtrs[i]->prop->pos.z - g_Vars.currentplayer->prop->pos.z; + for (i = playercount; i < g_MpNumChrs; i++) { + struct chrdata *chr = g_MpChrs[i].chr; - if (g_Vars.normmplayerisrunning && (g_MpSetup.options & MPOPTION_TEAMSENABLED)) { - colour = g_TeamColours[radarGetTeamIndex(g_MpBotChrPtrs[i]->team)]; + if (!chrIsDead(chr) + && (chr->hidden & CHRHFLAG_CLOAKED) == 0 + && scenarioRadarChr(&gdl, chr->prop) == false) { + pos.x = chr->prop->pos.x - g_Vars.currentplayer->prop->pos.x; + pos.y = chr->prop->pos.y - g_Vars.currentplayer->prop->pos.y; + pos.z = chr->prop->pos.z - g_Vars.currentplayer->prop->pos.z; + + if (g_MpSetup.options & MPOPTION_TEAMSENABLED) { + colour = g_TeamColours[chr->team]; } else { colour = 0x00ff0000; } - gdl = radarDrawDot(gdl, g_MpBotChrPtrs[i]->prop, &pos, colour, 0, 0); + gdl = radarDrawDot(gdl, chr->prop, &pos, colour, 0, 0); } } diff --git a/src/game/setup.c b/src/game/setup.c index b3ed7a09f..b22acfdd1 100644 --- a/src/game/setup.c +++ b/src/game/setup.c @@ -819,15 +819,22 @@ s32 setupGetNumRequestedBots(void) s32 setupCalculateMaxBots(s32 numrequested, bool haslaptops) { - return numrequested; + return numrequested > 8 ? 8 : numrequested; } +bool g_DebugEnable = false; + void setupAllocateEverything(void) { + s32 numhumans; s32 numbotsrequested; bool haslaptops = false; + s32 botcfgnum; s32 i; - s32 j; + s16 *killcounts; + s32 chrnum = 0; + + numhumans = PLAYERCOUNT(); // Count how many bots were requested numbotsrequested = setupGetNumRequestedBots(); @@ -856,24 +863,58 @@ void setupAllocateEverything(void) chrmgrReset(); chrmgrConfigure(g_NumBots); - botmgrRemoveAll(); + g_MpNumChrs = numhumans + g_NumBots; - if (g_Vars.normmplayerisrunning && mpHasSimulants()) { - s32 chrnum = 0; + g_MpChrs = mempAlloc(g_MpNumChrs * sizeof(struct mpchr), MEMPOOL_STAGE); - for (i = 0; i < MAX_BOTS; i++) { - if ((g_MpSetup.chrslots & (1 << (i + 4))) && mpIsSimSlotEnabled(i)) { - for (j = 0; j < g_BotConfigsArray[i].quantity; j++) { - botmgrAllocateBot(chrnum, i); + killcounts = mempAlloc(g_MpNumChrs * g_MpNumChrs * sizeof(s16), MEMPOOL_STAGE); + + for (i = 0; i < g_MpNumChrs * g_MpNumChrs; i++) { + killcounts[i] = 0; + } + + for (i = 0; i < 4; i++) { + if (g_MpSetup.chrslots & (1 << i)) { + // player->prop is null here, so chr gets copied later on in playerReset + g_MpChrs[chrnum].isbot = false; + g_MpChrs[chrnum].team = g_PlayerConfigsArray[i].base.team; + g_MpChrs[chrnum].playerconfig = &g_PlayerConfigsArray[i]; + g_MpChrs[chrnum].placement = 0; + g_MpChrs[chrnum].rankablescore = 0; + g_MpChrs[chrnum].killcounts = &killcounts[chrnum * g_MpNumChrs]; + g_MpChrs[chrnum].numdeaths = 0; + g_MpChrs[chrnum].numpoints = 0; + + chrnum++; + } + } + + if (mpHasSimulants()) { + s32 botnum = 0; + s32 botconfignum; + + for (botcfgnum = 0; botcfgnum < MAX_BOTS; botcfgnum++) { + if ((g_MpSetup.chrslots & (1 << (botcfgnum + 4))) && mpIsSimSlotEnabled(botcfgnum)) { + for (i = 0; i < g_BotConfigsArray[botcfgnum].quantity; i++) { + g_MpChrs[chrnum].isbot = true; + g_MpChrs[chrnum].team = g_BotConfigsArray[botcfgnum].base.team; + g_MpChrs[chrnum].botconfig = &g_BotConfigsArray[botcfgnum]; + g_MpChrs[chrnum].chr = NULL; + g_MpChrs[chrnum].placement = 0; + g_MpChrs[chrnum].rankablescore = 0; + g_MpChrs[chrnum].killcounts = &killcounts[chrnum * g_MpNumChrs]; + g_MpChrs[chrnum].numdeaths = 0; + g_MpChrs[chrnum].numpoints = 0; + + botmgrAllocateBot(chrnum, botcfgnum, botnum); + botnum++; chrnum++; } } } } - if (g_Vars.normmplayerisrunning) { - scenarioInitProps(); - } + scenarioInitProps(); } void setupCreateProps(s32 stagenum) @@ -1133,6 +1174,6 @@ void setupCreateProps(s32 stagenum) } } } else { - setupAllocateEverything(); + modelmgrAllocateSlots(0, 0, 0); } } diff --git a/src/game/varsreset.c b/src/game/varsreset.c index 4ae2412cd..64f417e3b 100644 --- a/src/game/varsreset.c +++ b/src/game/varsreset.c @@ -34,7 +34,7 @@ void varsReset(void) g_Vars.props[i].next = &g_Vars.props[i + 1]; } - varsResetRoomProps(); + g_Vars.props[i].next = NULL; if (g_Vars.normmplayerisrunning) { g_Vars.numpropstates = 4; diff --git a/src/include/bss.h b/src/include/bss.h index 61f47cbe0..ac890304a 100644 --- a/src/include/bss.h +++ b/src/include/bss.h @@ -273,15 +273,13 @@ extern struct textureconfig *g_TexGeneralConfigs; extern struct textureconfig *g_TexRadarConfigs; extern struct scenariodata g_ScenarioData; extern u32 var800ac4cc; -extern struct chrdata *g_MpAllChrPtrs[MAX_MPCHRS]; -extern struct mpchrconfig *g_MpAllChrConfigPtrs[MAX_MPCHRS]; extern s32 g_MpNumChrs; +extern struct mpchr *g_MpChrs; extern struct mpbotconfig g_BotConfigsArray[MAX_BOTS]; extern u8 g_MpSimulantDifficultiesPerNumPlayers[8][4]; extern struct mpplayerconfig g_PlayerConfigsArray[6]; extern u8 g_AmBotCommands[16]; extern struct mpsetup g_MpSetup; extern struct bossfile g_BossFile; -extern struct chrdata *g_MpBotChrPtrs[MAX_BOTS]; #endif diff --git a/src/include/constants.h b/src/include/constants.h index 30683b604..47710ff3f 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -34,7 +34,8 @@ #define IS8MB() (g_Is4Mb != true) #define LINEHEIGHT (VERSION == VERSION_JPN_FINAL ? 14 : 11) #define MIXCOLOUR(dialog, property) dialog->transitionfrac < 0.0f ? g_MenuColourPalettes[dialog->type].property : colourBlend(g_MenuColourPalettes[dialog->type2].property, g_MenuColourPalettes[dialog->type].property, dialog->colourweight) -#define MPCHR(index) ((index) < 4 ? &g_PlayerConfigsArray[index].base : &g_BotConfigsArray[(index) - 4].base) +#define MPCHR(index) &g_MpChrs[index] +#define MPCHRCONFIG(index) ((index) < 4 ? &g_PlayerConfigsArray[index].base : &g_BotConfigsArray[index - 4].base) #define PLAYERCOUNT() ((g_Vars.players[0] ? 1 : 0) + (g_Vars.players[1] ? 1 : 0) + (g_Vars.players[2] ? 1 : 0) + (g_Vars.players[3] ? 1 : 0)) #define RANDOMFRAC() (random() * (1.0f / U32_MAX)) #define SECSTOTIME240(secs) (secs * 240) diff --git a/src/include/data.h b/src/include/data.h index aa7f04c93..99e144736 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -497,6 +497,7 @@ extern struct mpbody g_MpBodies[NUM_MPBODIES]; extern struct mppreset g_MpPresets[NUM_MPPRESETS]; extern u32 g_TeamColours[]; extern u32 var80087ce4[]; +extern s32 g_NumBots; extern u8 g_BotCount; extern struct aibotweaponpreference g_AibotWeaponPreferences[]; extern u32 var80087eb4; diff --git a/src/include/game/botmgr.h b/src/include/game/botmgr.h index e5530bf7e..cba0314e0 100644 --- a/src/include/game/botmgr.h +++ b/src/include/game/botmgr.h @@ -5,6 +5,6 @@ #include "types.h" void botmgrRemoveAll(void); -void botmgrAllocateBot(s32 chrnum, s32 aibotnum); +void botmgrAllocateBot(s32 chrnum, s32 botcfgnum, s32 botnum); #endif diff --git a/src/include/game/mplayer/mplayer.h b/src/include/game/mplayer/mplayer.h index 1326c0e0c..2dafcb6f1 100644 --- a/src/include/game/mplayer/mplayer.h +++ b/src/include/game/mplayer/mplayer.h @@ -5,7 +5,7 @@ #include "types.h" f32 mpHandicapToDamageScale(u8 value); -void func0f187838(struct mpchrconfig *mpchr); +void func0f187838(struct mpchr *mpchr); void mpStartMatch(void); void mpReset(void); void mpCalculateTeamIsOnlyAi(void); @@ -82,6 +82,7 @@ s32 mpGetCurrentTrackSlotNum(void); s32 mpChooseTrack(void); struct mpchrconfig *mpGetChrConfigBySlotNum(s32 slot); s32 mpGetChrIndexBySlotNum(s32 slot); +s32 mpGetNumConfigs(void); s32 mpGetNumChrs(void); u8 mpFindUnusedTeamNum(void); void mpCreateBotFromProfile(s32 botnum, u8 difficulty); @@ -93,10 +94,7 @@ bool mpHasUnusedBotSlots(void); bool mpIsSimSlotEnabled(s32 slot); s32 mpFindBotProfile(s32 type, s32 difficulty); void mpGenerateBotNames(void); -s32 mpPlayerGetIndex(struct chrdata *chr); -struct chrdata *mpGetChrFromPlayerIndex(s32 index); s32 func0f18d074(s32 index); -s32 func0f18d0e8(s32 arg0); void mpplayerfileLoadGunFuncs(struct savebuffer *buffer, s32 playernum); void mpplayerfileSaveGunFuncs(struct savebuffer *buffer, s32 playernum); void mpplayerfileLoadWad(s32 playernum, struct savebuffer *buffer, s32 arg2); diff --git a/src/include/game/mplayer/setup.h b/src/include/game/mplayer/setup.h index 4c9ca1950..c12db86f4 100644 --- a/src/include/game/mplayer/setup.h +++ b/src/include/game/mplayer/setup.h @@ -106,7 +106,7 @@ char *mpMenuTextScenarioName(struct menuitem *item); s32 scenarioScenarioMenuHandler(s32 operation, struct menuitem *item, union handlerdata *data); void scenarioCreateMatchStartHudmsgs(void); Gfx *scenarioRenderHud(Gfx *gdl); -void scenarioCalculatePlayerScore(struct mpchrconfig *mpchr, s32 chrnum, s32 *arg2, s32 *arg3); +void scenarioCalculatePlayerScore(struct mpchr *mpchr, s32 chrnum, s32 *arg2, s32 *arg3); bool scenarioHighlightProp(struct prop *prop, s32 *colour); void scenarioReset(void); struct prop *scenarioCreateObj(s32 modelnum, s16 padnum, f32 arg2, u32 flags, u32 flags2, u32 flags3); diff --git a/src/include/game/radar.h b/src/include/game/radar.h index 7082c3809..e90420338 100644 --- a/src/include/game/radar.h +++ b/src/include/game/radar.h @@ -5,7 +5,6 @@ #include "types.h" Gfx *radarRenderBackground(Gfx *gdl, struct textureconfig *tconfig, s32 arg2, s32 arg3, s32 arg4); -s32 radarGetTeamIndex(s32 team); Gfx *radarDrawDot(Gfx *gdl, struct prop *prop, struct coord *dist, u32 colour1, u32 colour2, bool swapcolours); Gfx *radarRender(Gfx *gdl); Gfx *radarRenderRTrackedProps(Gfx *gdl); diff --git a/src/include/lib/vars.h b/src/include/lib/vars.h index 66218e3f5..23dfcb36d 100644 --- a/src/include/lib/vars.h +++ b/src/include/lib/vars.h @@ -7,5 +7,6 @@ void varsInit(void); void varsReset(void); +void varsResetRoomProps(void); #endif diff --git a/src/include/types.h b/src/include/types.h index aea2aa241..7fc694937 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -2705,7 +2705,7 @@ struct player { /*0x1be0*/ f32 cachedlookahead; /*0x1be4*/ u16 lookaheadframe; /*0x1be6*/ u8 numaibuddies; - /*0x1be7*/ u8 aibuddynums[MAX_BOTS]; + /*0x1be7*/ u16 *aibuddynums; /*0x1bf0*/ bool bondexploding; /*0x1bf4*/ s32 bondnextexplode; // lvframe60 of next explosion /*0x1bf8*/ s32 bondcurexplode; // Increases by 1 on each tick even when not exploding @@ -4146,62 +4146,69 @@ struct gamefile { /*0xb5*/ u8 weaponsfound[6]; }; +// Allocated during setup - contains configuration common to both players and bots struct mpchrconfig { - /*0x00*/ char name[12]; // up to 10 visible chars plus line break plus null byte - /*0x0c*/ u8 unk0c; - /*0x0d*/ u8 unk0d; - /*0x0e*/ u8 unk0e; - /*0x0f*/ u8 mpheadnum; - /*0x10*/ u8 mpbodynum; - /*0x11*/ u8 team; - /*0x14*/ u32 displayoptions; - /*0x18*/ u16 unk18; - /*0x1a*/ u16 unk1a; - /*0x1c*/ u16 unk1c; - /*0x1e*/ s8 placement; // 0 = winner, 1 = second place etc - /*0x20*/ s32 rankablescore; - /*0x24*/ s16 killcounts[MAX_MPCHRS]; // per player - each index is a chrslot - /*0x3c*/ s16 numdeaths; - /*0x3e*/ s16 numpoints; - /*0x40*/ s16 unk40; + char name[15]; // up to 10 visible chars plus line break plus null byte + u8 mpheadnum; + u8 mpbodynum; + u8 team; }; +// Allocated during setup - extension of mpchrconfig struct mpplayerconfig { - /*0x00*/ struct mpchrconfig base; - /*0x44*/ u8 controlmode; - /*0x45*/ s8 contpad1; - /*0x46*/ s8 contpad2; - /*0x48*/ u16 options; - /*0x4c*/ struct fileguid fileguid; - /*0x54*/ u32 kills; - /*0x58*/ u32 deaths; - /*0x5c*/ u32 gamesplayed; - /*0x60*/ u32 gameswon; - /*0x64*/ u32 gameslost; - /*0x68*/ u32 time; - /*0x6c*/ u32 distance; // 1 unit = 100 metres - /*0x70*/ u32 accuracy; - /*0x74*/ u32 damagedealt; - /*0x78*/ u32 painreceived; - /*0x7c*/ u32 headshots; - /*0x80*/ u32 ammoused; - /*0x84*/ u32 accuracymedals; - /*0x88*/ u32 headshotmedals; - /*0x8c*/ u32 killmastermedals; - /*0x90*/ u32 survivormedals; - /*0x94*/ u8 medals; - /*0x95*/ u8 title; - /*0x96*/ u8 newtitle; - /*0x97*/ u8 gunfuncs[6]; - /*0x9d*/ u8 handicap; + struct mpchrconfig base; + u32 displayoptions; + u16 unk1c; + u8 controlmode; + s8 contpad1; + s8 contpad2; + u16 options; + struct fileguid fileguid; + u32 kills; + u32 deaths; + u32 gamesplayed; + u32 gameswon; + u32 gameslost; + u32 time; + u32 distance; // 1 unit = 100 metres + u32 accuracy; + u32 damagedealt; + u32 painreceived; + u32 headshots; + u32 ammoused; + u32 accuracymedals; + u32 headshotmedals; + u32 killmastermedals; + u32 survivormedals; + u8 medals; + u8 title; + u8 newtitle; + u8 gunfuncs[6]; + u8 handicap; }; struct mpbotconfig { - /*0x00*/ struct mpchrconfig base; - /*0x44*/ u8 unk44[3]; - /*0x47*/ u8 type; - /*0x48*/ u8 difficulty; - /*0x4a*/ u16 quantity; + struct mpchrconfig base; + u8 type; + u8 difficulty; + u16 quantity; +}; + +// Allocated at match start - one per chr +struct mpchr { + u8 isbot; + u8 team; + u16 placement; // 0 = winner, 1 = second place etc + union { + struct mpchrconfig *config; + struct mpplayerconfig *playerconfig; + struct mpbotconfig *botconfig; + }; + struct chrdata *chr; + s32 rankablescore; + s16 *killcounts; + s16 numdeaths; + s16 numpoints; }; struct missionconfig { @@ -4788,7 +4795,7 @@ struct chrbio { }; struct ranking { - struct mpchrconfig *mpchr; + struct mpchr *mpchr; union { u32 teamnum; u32 chrnum; diff --git a/src/lib/main.c b/src/lib/main.c index 4f7d6f7cb..ad55c1ac3 100644 --- a/src/lib/main.c +++ b/src/lib/main.c @@ -87,7 +87,7 @@ struct stageallocation g_StageAllocations8Mb[] = { { STAGE_MP_RUINS, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" }, { STAGE_MP_FORTRESS, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" }, { STAGE_MP_VILLA, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" }, - { STAGE_4MBMENU, "-mgfx100 -mvtx50 -ma50" }, + { STAGE_4MBMENU, "-ml0 -me0 -mgfx120 -mvtx98 -ma400" }, { STAGE_TITLE, "-ml0 -me0 -mgfx80 -mvtx20 -ma001" }, { 0, "-ml0 -me0 -mgfx120 -mvtx98 -ma300" }, }; diff --git a/src/lib/memp.c b/src/lib/memp.c index 12c4b5744..78e0da0fc 100644 --- a/src/lib/memp.c +++ b/src/lib/memp.c @@ -165,7 +165,11 @@ void *mempAllocFromBank(struct memorypool *pool, u32 size, u8 poolnum) void *mempAlloc(u32 len, u8 pool) { - void *allocation = mempAllocFromBank(g_MempOnboardPools, len, pool); + void *allocation; + + len = ALIGN8(len); + + allocation = mempAllocFromBank(g_MempOnboardPools, len, pool); if (allocation) { return allocation;