Refactor MP chr/config structs to allow a one config to many chrs relationship

This commit is contained in:
Ryan Dwyer
2022-11-08 08:00:33 +10:00
parent d5b5a8d72c
commit 73808c232b
42 changed files with 768 additions and 1017 deletions
+18 -18
View File
@@ -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;
+1 -1
View File
@@ -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);
}
+2 -2
View File
@@ -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) {
+67 -71
View File
@@ -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);
+2 -2
View File
@@ -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)];
+2 -2
View File
@@ -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);
+4 -4
View File
@@ -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;
}
+199 -219
View File
@@ -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);
}
}
}
+1 -1
View File
@@ -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);
+4 -4
View File
@@ -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);
+2 -2
View File
@@ -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)) {
+2 -1
View File
@@ -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++;
}
}
+28 -30
View File
@@ -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
}
}
}
}
+1 -1
View File
@@ -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;
+8 -59
View File
@@ -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);
}
}
+113 -210
View File
@@ -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;
+29 -104
View File
@@ -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;
+9 -19
View File
@@ -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,
+8 -8
View File
@@ -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);
@@ -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);
+11 -11
View File
@@ -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;
+8 -16
View File
@@ -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);
+37 -51
View File
@@ -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;
}
}
}
+12 -12
View File
@@ -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]++;
}
}
}
+11 -14
View File
@@ -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);
+15 -8
View File
@@ -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++;
}
}
+6 -1
View File
@@ -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);
+19 -19
View File
@@ -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);
+14 -37
View File
@@ -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);
}
}
+54 -13
View File
@@ -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);
}
}
+1 -1
View File
@@ -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;
+1 -3
View File
@@ -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
+2 -1
View File
@@ -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)
+1
View File
@@ -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;
+1 -1
View File
@@ -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
+2 -4
View File
@@ -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);
+1 -1
View File
@@ -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);
-1
View File
@@ -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);
+1
View File
@@ -7,5 +7,6 @@
void varsInit(void);
void varsReset(void);
void varsResetRoomProps(void);
#endif
+58 -51
View File
@@ -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;
+1 -1
View File
@@ -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" },
};
+5 -1
View File
@@ -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;