diff --git a/source/blood/src/actor.cpp b/source/blood/src/actor.cpp index ff286f642..2b53e94bb 100644 --- a/source/blood/src/actor.cpp +++ b/source/blood/src/actor.cpp @@ -3601,6 +3601,17 @@ int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE a3, int a4) PLAYER *pSourcePlayer = NULL; if (IsPlayerSprite(&sprite[nSource])) pSourcePlayer = &gPlayer[sprite[nSource].type-kDudePlayer1]; + if (!gGameOptions.bFriendlyFire && pSourcePlayer != NULL && (gGameOptions.nGameType == 1 || gGameOptions.nGameType == 3) && IsPlayerSprite(pSprite)) + { + PLAYER *pTargetPlayer = &gPlayer[pSprite->type-kDudePlayer1]; + if (pSourcePlayer != pTargetPlayer) + { + if (gGameOptions.nGameType == 1) + return 0; + if (gGameOptions.nGameType == 3 && (pSourcePlayer->at2ea&3) == (pTargetPlayer->at2ea&3)) + return 0; + } + } switch (pSprite->statnum) { case 6: diff --git a/source/blood/src/blood.cpp b/source/blood/src/blood.cpp index 8ba90b99d..8f2d33a67 100644 --- a/source/blood/src/blood.cpp +++ b/source/blood/src/blood.cpp @@ -533,6 +533,8 @@ void StartLevel(GAMEOPTIONS *gameOptions) gGameOptions.nWeaponSettings = gPacketStartGame.weaponSettings; gGameOptions.nItemSettings = gPacketStartGame.itemSettings; gGameOptions.nRespawnSettings = gPacketStartGame.respawnSettings; + gGameOptions.bFriendlyFire = gPacketStartGame.bFriendlyFire; + gGameOptions.bKeepKeysOnRespawn = gPacketStartGame.bKeepKeysOnRespawn; if (gPacketStartGame.userMap) levelAddUserMap(gPacketStartGame.userMapName); else @@ -684,6 +686,8 @@ void StartNetworkLevel(void) gGameOptions.nWeaponSettings = gPacketStartGame.weaponSettings; gGameOptions.nItemSettings = gPacketStartGame.itemSettings; gGameOptions.nRespawnSettings = gPacketStartGame.respawnSettings; + gGameOptions.bFriendlyFire = gPacketStartGame.bFriendlyFire; + gGameOptions.bKeepKeysOnRespawn = gPacketStartGame.bKeepKeysOnRespawn; /////// gGameOptions.weaponsV10x = gPacketStartGame.weaponsV10x; diff --git a/source/blood/src/levels.h b/source/blood/src/levels.h index 306ffff9a..4d5529677 100644 --- a/source/blood/src/levels.h +++ b/source/blood/src/levels.h @@ -54,6 +54,8 @@ struct GAMEOPTIONS { int nWeaponRespawnTime; int nItemRespawnTime; int nSpecialRespawnTime; + bool bFriendlyFire; + bool bKeepKeysOnRespawn; }; #pragma pack(pop) diff --git a/source/blood/src/menu.cpp b/source/blood/src/menu.cpp index 71176c316..ee64f40e8 100644 --- a/source/blood/src/menu.cpp +++ b/source/blood/src/menu.cpp @@ -277,15 +277,17 @@ CGameMenuItemZEditBitmap itemLoadGame10(NULL, 3, 20, 150, 320, strRestoreGameStr CGameMenuItemBitmapLS itemLoadGamePic(NULL, 3, 0, 0, 2518); CGameMenuItemTitle itemNetStartTitle("MULTIPLAYER", 1, 160, 20, 2038); -CGameMenuItemZCycle itemNetStart1("GAME", 1, 20, 35, 280, 0, 0, zNetGameTypes, 3, 0); -CGameMenuItemZCycle itemNetStart2("EPISODE", 1, 20, 50, 280, 0, SetupNetLevels, NULL, 0, 0); -CGameMenuItemZCycle itemNetStart3("LEVEL", 1, 20, 65, 280, 0, NULL, NULL, 0, 0); -CGameMenuItemZCycle itemNetStart4("DIFFICULTY", 1, 20, 80, 280, 0, 0, zDiffStrings, 5, 0); -CGameMenuItemZCycle itemNetStart5("MONSTERS", 1, 20, 95, 280, 0, 0, zMonsterStrings, 3, 0); -CGameMenuItemZCycle itemNetStart6("WEAPONS", 1, 20, 110, 280, 0, 0, zWeaponStrings, 4, 0); -CGameMenuItemZCycle itemNetStart7("ITEMS", 1, 20, 125, 280, 0, 0, zItemStrings, 3, 0); -CGameMenuItemZEdit itemNetStart9("USER MAP:", 1, 20, 155, 280, zUserMapName, 13, 0, NULL, 0); -CGameMenuItemChain itemNetStart10("START GAME", 1, 20, 170, 280, 0, 0, -1, StartNetGame, 0); +CGameMenuItemZCycle itemNetStart1("GAME:", 3, 66, 60, 180, 0, 0, zNetGameTypes, 3, 0); +CGameMenuItemZCycle itemNetStart2("EPISODE:", 3, 66, 70, 180, 0, SetupNetLevels, NULL, 0, 0); +CGameMenuItemZCycle itemNetStart3("LEVEL:", 3, 66, 80, 180, 0, NULL, NULL, 0, 0); +CGameMenuItemZCycle itemNetStart4("DIFFICULTY:", 3, 66, 90, 180, 0, 0, zDiffStrings, 5, 0); +CGameMenuItemZCycle itemNetStart5("MONSTERS:", 3, 66, 100, 180, 0, 0, zMonsterStrings, 3, 0); +CGameMenuItemZCycle itemNetStart6("WEAPONS:", 3, 66, 110, 180, 0, 0, zWeaponStrings, 4, 0); +CGameMenuItemZCycle itemNetStart7("ITEMS:", 3, 66, 120, 180, 0, 0, zItemStrings, 3, 0); +CGameMenuItemZBool itemNetStart8("FRIENDLY FIRE:", 3, 66, 130, 180, true, 0, NULL, NULL); +CGameMenuItemZBool itemNetStart9("KEEP KEYS ON RESPAWN:", 3, 66, 140, 180, false, 0, NULL, NULL); +CGameMenuItemZEdit itemNetStart10("USER MAP:", 3, 66, 150, 180, zUserMapName, 13, 0, NULL, 0); +CGameMenuItemChain itemNetStart11("START GAME", 1, 66, 165, 280, 0, 0, -1, StartNetGame, 0); CGameMenuItemText itemLoadingText("LOADING...", 1, 160, 100, 1); @@ -883,8 +885,10 @@ void SetupNetStartMenu(void) menuNetStart.Add(&itemNetStart5, false); menuNetStart.Add(&itemNetStart6, false); menuNetStart.Add(&itemNetStart7, false); + menuNetStart.Add(&itemNetStart8, false); menuNetStart.Add(&itemNetStart9, false); menuNetStart.Add(&itemNetStart10, false); + menuNetStart.Add(&itemNetStart11, false); itemNetStart1.SetTextIndex(1); itemNetStart4.SetTextIndex(2); itemNetStart5.SetTextIndex(0); @@ -2156,9 +2160,11 @@ void StartNetGame(CGameMenuItemChain *pItem) gPacketStartGame.weaponSettings = itemNetStart6.m_nFocus; gPacketStartGame.itemSettings = itemNetStart7.m_nFocus; gPacketStartGame.respawnSettings = 0; + gPacketStartGame.bFriendlyFire = itemNetStart8.at20; + gPacketStartGame.bKeepKeysOnRespawn = itemNetStart9.at20; gPacketStartGame.unk = 0; gPacketStartGame.userMapName[0] = 0; - strncpy(gPacketStartGame.userMapName, itemNetStart9.at20, 13); + strncpy(gPacketStartGame.userMapName, itemNetStart10.at20, 13); gPacketStartGame.userMapName[12] = 0; gPacketStartGame.userMap = gPacketStartGame.userMapName[0] != 0; netBroadcastNewGame(); diff --git a/source/blood/src/network.h b/source/blood/src/network.h index c62597582..136efc3ff 100644 --- a/source/blood/src/network.h +++ b/source/blood/src/network.h @@ -76,6 +76,8 @@ struct PKT_STARTGAME { char episodeId, levelId; int unk; char userMap, userMapName[13]; + bool bFriendlyFire; + bool bKeepKeysOnRespawn; }; extern PKT_STARTGAME gPacketStartGame; diff --git a/source/blood/src/player.cpp b/source/blood/src/player.cpp index 36cd8d363..e282bf86e 100644 --- a/source/blood/src/player.cpp +++ b/source/blood/src/player.cpp @@ -349,10 +349,10 @@ ARMORDATA armorData[5] = { }; void PlayerSurvive(int, int); -void PlayerKeelsOver(int, int); +void PlayerKneelsOver(int, int); int nPlayerSurviveClient = seqRegisterClient(PlayerSurvive); -int nPlayerKeelClient = seqRegisterClient(PlayerKeelsOver); +int nPlayerKneelClient = seqRegisterClient(PlayerKneelsOver); struct VICTORY { const char *at0; @@ -934,8 +934,9 @@ void playerStart(int nPlayer) pPlayer->at1ca.dz = 0; pPlayer->at1d6 = -1; pPlayer->at6b = pPlayer->at73; - for (int i = 0; i < 8; i++) - pPlayer->at88[i] = gGameOptions.nGameType >= 2; + if (!(gGameOptions.nGameType == 1 && gGameOptions.bKeepKeysOnRespawn)) + for (int i = 0; i < 8; i++) + pPlayer->at88[i] = gGameOptions.nGameType >= 2; pPlayer->at90 = 0; for (int i = 0; i < 8; i++) pPlayer->at91[i] = -1; @@ -2157,7 +2158,7 @@ int playerDamageSprite(int nSource, PLAYER *pPlayer, DAMAGE_TYPE nDamageType, in int nXSector = sector[pSprite->sectnum].extra; DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type-kDudeBase]; int nDeathSeqID = -1; - int v18 = -1; + int nKneelingPlayer = -1; int nSprite = pSprite->index; char va = playerSeqPlaying(pPlayer, 16); if (!pXSprite->health) @@ -2252,7 +2253,7 @@ int playerDamageSprite(int nSource, PLAYER *pPlayer, DAMAGE_TYPE nDamageType, in DAMAGEINFO *pDamageInfo = &damageInfo[nDamageType]; sfxPlay3DSound(pSprite, pDamageInfo->at10[0], 0, 2); nDeathSeqID = 16; - v18 = nPlayerKeelClient; + nKneelingPlayer = nPlayerKneelClient; powerupActivate(pPlayer, 28); pXSprite->target = nSource; evPost(pSprite->index, 3, 15, CALLBACK_ID_13); @@ -2282,7 +2283,7 @@ int playerDamageSprite(int nSource, PLAYER *pPlayer, DAMAGE_TYPE nDamageType, in trTriggerSprite(nSprite, pXSprite, 0); } dassert(gSysRes.Lookup(pDudeInfo->seqStartID + nDeathSeqID, "SEQ") != NULL); - seqSpawn(pDudeInfo->seqStartID+nDeathSeqID, 3, nXSprite, v18); + seqSpawn(pDudeInfo->seqStartID+nDeathSeqID, 3, nXSprite, nKneelingPlayer); return nDamage; } @@ -2369,7 +2370,7 @@ void PlayerSurvive(int, int nXSprite) } } -void PlayerKeelsOver(int, int nXSprite) +void PlayerKneelsOver(int, int nXSprite) { XSPRITE *pXSprite = &xsprite[nXSprite]; for (int p = connecthead; p >= 0; p = connectpoint2[p]) diff --git a/source/blood/src/player.h b/source/blood/src/player.h index 725b75310..18238130d 100644 --- a/source/blood/src/player.h +++ b/source/blood/src/player.h @@ -114,7 +114,7 @@ struct PLAYER { int at202[kMaxPowerUps]; // [13]: cloak of invisibility, [14]: death mask (invulnerability), [15]: jump boots, [17]: guns akimbo, [18]: diving suit, [21]: crystal ball, [24]: reflective shots, [25]: beast vision, [26]: cloak of shadow int at2c6; // frags int at2ca[8]; - int at2ea; + int at2ea; // color (team) int at2ee; // killer int at2f2; int at2f6; @@ -249,7 +249,7 @@ int UseAmmo(PLAYER *pPlayer, int nAmmoType, int nDec); void sub_41250(PLAYER *pPlayer); void playerLandingSound(PLAYER *pPlayer); void PlayerSurvive(int, int nXSprite); -void PlayerKeelsOver(int, int nXSprite); +void PlayerKneelsOver(int, int nXSprite); bool isGrown(spritetype* pSprite); bool isShrinked(spritetype* pSprite); bool shrinkPlayerSize(PLAYER* pPlayer, int divider);