diff --git a/port/src/pdmain.c b/port/src/pdmain.c index b08870abd..f361310c8 100644 --- a/port/src/pdmain.c +++ b/port/src/pdmain.c @@ -465,7 +465,13 @@ void mainLoop(void) } if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { +#ifdef PLATFORM_N64 g_MpSetup.chrslots = 0x03; +#else + if (getNumPlayers() <= 2) { + g_MpSetup.chrslots = 0x03; + } +#endif mpReset(); } else if (g_Vars.perfectbuddynum) { mpReset(); diff --git a/src/game/bondwalk.c b/src/game/bondwalk.c index 8bd907e2e..cdfa78e7e 100644 --- a/src/game/bondwalk.c +++ b/src/game/bondwalk.c @@ -475,7 +475,11 @@ bool bwalkCalculateNewPositionWithPush(struct coord *delta, f32 rotateamount, bo } } else if (chr->chrflags & CHRCFLAG_PUSHABLE) { if (g_Vars.antiplayernum < 0 +#ifdef PLATFORM_N64 || g_Vars.currentplayer != g_Vars.anti +#else + || g_Vars.currentplayer == g_Vars.bond +#endif || (chr->hidden & CHRHFLAG_ANTINONINTERACTABLE) == 0) { canpush = true; } @@ -809,7 +813,11 @@ void bwalkUpdateVertical(void) // Maybe reset counter-op's radius - not sure why // Maybe it gets set to 0 when they die? if (g_Vars.antiplayernum >= 0 +#ifdef PLATFORM_N64 && g_Vars.currentplayer == g_Vars.anti +#else + && g_Vars.currentplayer != g_Vars.bond +#endif && g_Vars.currentplayer->bond2.radius != 30 && cdTestVolume(&g_Vars.currentplayer->prop->pos, 30, g_Vars.currentplayer->prop->rooms, CDTYPE_ALL, CHECKVERTICAL_YES, ymax - g_Vars.currentplayer->prop->pos.y, ymin - g_Vars.currentplayer->prop->pos.y)) { g_Vars.currentplayer->prop->chr->radius = 30; diff --git a/src/game/chraction.c b/src/game/chraction.c index 4bf5ccb64..bf35338b5 100644 --- a/src/game/chraction.c +++ b/src/game/chraction.c @@ -4351,7 +4351,14 @@ void chrDamage(struct chrdata *chr, f32 damage, struct coord *vector, struct gse // Don't damage if attacker was anti and chr is non-interactable by anti if (g_Vars.antiplayernum >= 0 && aprop + +#ifdef PLATFORM_N64 && aprop == g_Vars.anti->prop +#else + && aprop->type == PROPTYPE_PLAYER + && aprop != g_Vars.bond->prop +#endif + && (chr->hidden & CHRHFLAG_ANTINONINTERACTABLE)) { return; } @@ -4490,7 +4497,15 @@ void chrDamage(struct chrdata *chr, f32 damage, struct coord *vector, struct gse } // Anti shooting other enemies is lethal - if (aprop && aprop == g_Vars.anti->prop && vprop != g_Vars.bond->prop) { + if (aprop +#ifdef PLATFORM_N64 + && aprop == g_Vars.anti->prop +#else + && aprop->type == PROPTYPE_PLAYER + && aprop != g_Vars.bond->prop +#endif + + && vprop != g_Vars.bond->prop) { damage *= 100; } } else { @@ -8321,7 +8336,14 @@ void chrAlertOthersOfInjury(struct chrdata *chr, bool dying) s32 numinrange = 0; s32 numchrs = chrsGetNumSlots(); - if (g_Vars.antiplayernum >= 0 && chr->prop == g_Vars.anti->prop) { + if (g_Vars.antiplayernum >= 0 +#ifdef PLATFORM_N64 + && chr->prop == g_Vars.anti->prop +#else + && chr->prop->type == PROPTYPE_PLAYER + && chr->prop != g_Vars.bond->prop +#endif + ) { return; } @@ -13556,7 +13578,11 @@ void chraTickBg(void) if (targetprop && (targetprop->type == PROPTYPE_CHR || targetprop->type == PROPTYPE_PLAYER)) { if ((targetprop->type == PROPTYPE_PLAYER +#ifdef PLATFORM_N64 && !(g_Vars.antiplayernum >= 0 && g_Vars.anti && g_Vars.anti->prop == targetprop) +#else + && !(g_Vars.antiplayernum >= 0 && g_Vars.bond && g_Vars.bond->prop != targetprop) +#endif && chrCompareTeams(chr, targetprop->chr, COMPARE_ENEMIES)) || CHRRACE(targetprop->chr) == RACE_EYESPY) { s32 time60; diff --git a/src/game/mainmenu.c b/src/game/mainmenu.c index 1e84f2daf..0b65599b5 100644 --- a/src/game/mainmenu.c +++ b/src/game/mainmenu.c @@ -757,7 +757,20 @@ MenuItemHandlerResult menuhandlerAcceptMission(s32 operation, struct menuitem *i } g_Vars.coopplayernum = -1; +#ifdef PLATFORM_N64 setNumPlayers(2); +#else + if ((joyGetConnectedControllers() & 0xF) == 0xF) { + setNumPlayers(4); + g_MpSetup.chrslots = 0xF; + } else if ((joyGetConnectedControllers() & 0x7) == 0x7) { + setNumPlayers(3); + g_MpSetup.chrslots = 0x7; + } else { + setNumPlayers(2); + g_MpSetup.chrslots = 0x3; + } +#endif } else { // Solo g_Vars.bondplayernum = 0; diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index 7f27e0165..6b27e3ad3 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -256,7 +256,12 @@ void mpReset(void) g_Vars.lvmpbotlevel = true; } - if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { +#ifdef PLATFORM_N64 + if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) +#else + if ((g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) && getNumPlayers() <= 2) +#endif + { struct mpplayerconfig tmp; tmp = g_PlayerConfigsArray[MAX_PLAYERS]; @@ -1333,7 +1338,11 @@ Gfx *mpRenderModalText(Gfx *gdl) && g_Vars.currentplayer->redbloodfinished && g_Vars.currentplayer->deathanimfinished && !(g_Vars.coopplayernum >= 0 && ((g_Vars.bond->isdead && g_Vars.coop->isdead) || !g_Vars.currentplayer->coopcanrestart || g_InCutscene)) +#ifdef PLATFORM_N64 && !(g_Vars.antiplayernum >= 0 && ((g_Vars.currentplayer != g_Vars.anti || g_InCutscene))) +#else + && !(g_Vars.antiplayernum >= 0 && ((g_Vars.currentplayer == g_Vars.bond || g_InCutscene))) +#endif && g_NumReasonsToEndMpMatch == 0) { // Render "Press START" text gdl = text0f153628(gdl); diff --git a/src/game/player.c b/src/game/player.c index 6c54d5bde..3366d0f69 100644 --- a/src/game/player.c +++ b/src/game/player.c @@ -606,7 +606,13 @@ void playerStartNewLife(void) if (cmd); if (cmd); - if (g_Vars.antiplayernum < 0 || g_Vars.currentplayer != g_Vars.anti) { + if (g_Vars.antiplayernum < 0 +#ifdef PLATFORM_N64 + || g_Vars.currentplayer != g_Vars.anti +#else + || g_Vars.currentplayer == g_Vars.bond +#endif + ) { while (cmd[0] != INTROCMD_END) { switch (cmd[0]) { case INTROCMD_SPAWN: @@ -980,7 +986,13 @@ void playerSpawn(void) } if (g_Vars.mplayerisrunning) { - if (g_Vars.antiplayernum >= 0 && g_Vars.currentplayer == g_Vars.anti) { + if (g_Vars.antiplayernum >= 0 +#ifdef PLATFORM_N64 + && g_Vars.currentplayer == g_Vars.anti +#else + && g_Vars.currentplayer != g_Vars.bond +#endif + ) { numsqdists = 0; force = false; @@ -1182,7 +1194,11 @@ void playerChooseBodyAndHead(s32 *bodynum, s32 *headnum, s32 *arg2) bool solo; if (g_Vars.antiplayernum >= 0 +#ifdef PLATFORM_N64 && g_Vars.currentplayer == g_Vars.anti +#else + && g_Vars.currentplayer != g_Vars.bond +#endif && g_Vars.antiheadnum >= 0 && g_Vars.antibodynum >= 0) { *headnum = g_Vars.antiheadnum; @@ -1514,7 +1530,11 @@ void playerTickChrBody(void) #if VERSION >= VERSION_NTSC_1_0 if (g_Vars.antiplayernum >= 0 +#ifdef PLATFORM_N64 && g_Vars.currentplayer == g_Vars.anti +#else + && g_Vars.currentplayer != g_Vars.bond +#endif && g_Vars.currentplayer->vv_eyeheight > 159) { g_Vars.currentplayer->vv_eyeheight = 159; } @@ -4713,7 +4733,13 @@ Gfx *playerRenderHud(Gfx *gdl) chr->chrflags |= CHRCFLAG_HIDDEN; } - if (g_Vars.antiplayernum >= 0 && g_Vars.currentplayer == g_Vars.anti) { + if (g_Vars.antiplayernum >= 0 +#ifdef PLATFORM_N64 + && g_Vars.currentplayer == g_Vars.anti +#else + && g_Vars.currentplayer != g_Vars.bond +#endif + ) { // Anti #ifndef PLATFORM_N64 if (g_NetMode == NETMODE_SERVER && g_Vars.currentplayer->isremote) { diff --git a/src/game/playerreset.c b/src/game/playerreset.c index 6e941dd9c..1091ea2a6 100644 --- a/src/game/playerreset.c +++ b/src/game/playerreset.c @@ -186,7 +186,14 @@ void playerReset(void) cmd = (struct cmd32 *)((uintptr_t)cmd + 8); break; case INTROCMD_WEAPON: - if (cmd->param3 == 0 && g_Vars.currentplayer != g_Vars.anti) { + if (cmd->param3 == 0 +#ifdef PLATFORM_N64 + && g_Vars.currentplayer != g_Vars.anti +#else + && (g_Vars.antiplayernum < 0 || g_Vars.currentplayer == g_Vars.bond) +#endif + ) { + modelmgrLoadProjectileModeldefs(cmd->param1); if (cmd->param2 >= 0) { @@ -213,7 +220,13 @@ void playerReset(void) cmd = (struct cmd32 *)((uintptr_t)cmd + 16); break; case INTROCMD_AMMO: - if (cmd->param3 == 0 && g_Vars.currentplayer != g_Vars.anti) { + if (cmd->param3 == 0 +#ifdef PLATFORM_N64 + && g_Vars.currentplayer != g_Vars.anti +#else + && (g_Vars.antiplayernum < 0 || g_Vars.currentplayer == g_Vars.bond) +#endif + ) { bgunSetAmmoQuantity(cmd->param1, cmd->param2); } cmd = (struct cmd32 *)((uintptr_t)cmd + 16); diff --git a/src/game/prop.c b/src/game/prop.c index e9d544e06..7db390774 100644 --- a/src/game/prop.c +++ b/src/game/prop.c @@ -2358,7 +2358,12 @@ void propsTestForPickup(void) if (g_Vars.currentplayer->bondmovemode != MOVEMODE_CUTSCENE && !g_PlayerInvincible - && g_Vars.currentplayer != g_Vars.anti) { +#ifdef PLATFORM_N64 + && g_Vars.currentplayer != g_Vars.anti +#else + && (g_Vars.antiplayernum < 0 || g_Vars.currentplayer == g_Vars.bond) +#endif + ) { roomsCopy(g_Vars.currentplayer->prop->rooms, allrooms); for (i = 0; g_Vars.currentplayer->prop->rooms[i] != -1; i++) { diff --git a/src/game/propobj.c b/src/game/propobj.c index 598eae641..aa3ed5893 100644 --- a/src/game/propobj.c +++ b/src/game/propobj.c @@ -15942,7 +15942,14 @@ void objHit(struct shotdata *shotdata, struct hit *hit) } } - if (g_Vars.antiplayernum < 0 || g_Vars.currentplayer != g_Vars.anti || (obj->flags2 & OBJFLAG2_IMMUNETOANTI) == 0) { + if (g_Vars.antiplayernum < 0 +#ifdef PLATFORM_N64 + || g_Vars.currentplayer != g_Vars.anti +#else + || g_Vars.currentplayer == g_Vars.bond +#endif + || (obj->flags2 & OBJFLAG2_IMMUNETOANTI) == 0) { + if (hit->hitthing.texturenum != 10000) { f32 damage = gsetGetDamage(&shotdata->gset); diff --git a/src/include/constants.h b/src/include/constants.h index 163812868..571f09be8 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -20,8 +20,9 @@ #define MAX_CHRWAYPOINTS 6 #define MAX_EXPLOSIONS 6 #define MAX_EYESPYDARTS 8 +#define MAX_COOPCHRS MAX_PLAYERS #define MAX_MPCHRS (MAX_PLAYERS + MAX_BOTS) -#define MAX_MPPLAYERCONFIGS (MAX_PLAYERS + 2) +#define MAX_MPPLAYERCONFIGS (MAX_PLAYERS + MAX_COOPCHRS) #define MAX_OBJECTIVES 10 #define MAX_LOCAL_PLAYERS 4 #define MAX_PLAYERS 8