diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 91d150a4d..cae0ff9d7 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -833,7 +833,6 @@ set( NOT_COMPILED_SOURCE_FILES games/exhumed/src/object.cpp games/exhumed/src/osdcmds.cpp games/exhumed/src/player.cpp - games/exhumed/src/playerpickups.cpp games/exhumed/src/queen.cpp games/exhumed/src/ra.cpp games/exhumed/src/ramses.cpp diff --git a/source/games/exhumed/all.cpp b/source/games/exhumed/all.cpp index 9af882790..3aaf9ed8f 100644 --- a/source/games/exhumed/all.cpp +++ b/source/games/exhumed/all.cpp @@ -24,7 +24,6 @@ #include "src/object.cpp" #include "src/osdcmds.cpp" #include "src/player.cpp" -#include "src/playerpickups.cpp" #include "src/queen.cpp" #include "src/ra.cpp" #include "src/ramses.cpp" diff --git a/source/games/exhumed/src/player.cpp b/source/games/exhumed/src/player.cpp index 8bdabda8e..4aa18580e 100644 --- a/source/games/exhumed/src/player.cpp +++ b/source/games/exhumed/src/player.cpp @@ -701,6 +701,366 @@ void AIPlayer::Damage(RunListEvent* ev) // //--------------------------------------------------------------------------- +static DExhumedActor* feebtag(const DVector3& pos, sectortype* pSector, int nMagic, int nHealth, double deflen) +{ + DExhumedActor* pPickupActor = nullptr; + auto startwall = pSector->walls.Data(); + int nWalls = pSector->walls.Size(); + + while (1) + { + if (pSector != nullptr) + { + ExhumedSectIterator it(pSector); + while (const auto itActor = it.Next()) + { + const int nStat = itActor->spr.statnum; + const auto diff = itActor->spr.pos - pos; + + if (nStat < 900 || nStat > 960 || (itActor->spr.cstat & CSTAT_SPRITE_INVISIBLE) || diff.Z >= 20 || diff.Z <= -100) + continue; + + const auto len = diff.XY().Length(); + const bool needsMagic = (nStat != 950 && nStat != 949) || nMagic < 1000; + const bool needsHealth = (nStat != 912 && nStat != 913) || nHealth < 800; + + if (len < deflen && needsMagic && needsHealth) + { + deflen = len; + pPickupActor = itActor; + } + } + } + + if ((nWalls--) < 0) + return pPickupActor; + + pSector = startwall->nextSector(); + startwall++; + } + + return pPickupActor; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void doPickupNotification(Player* const pPlayer, const int nItem, const int nSound = -1, const int tintRed = 0, const int tintGreen = 16) +{ + if (pPlayer->nPlayer != nLocalPlayer) + return; + + if (nItemText[nItem] > -1 && nTotalPlayers == 1) + pickupMessage(nItem); + + if (nSound > -1) + PlayLocalSound(nSound, 0); + + TintPalette(tintRed * 4, tintGreen * 4, 0); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void doPickupDestroy(DExhumedActor* const pPickupActor, const int nItem) +{ + if (!(currentLevel->gameflags & LEVEL_EX_MULTI) || (nItem >= 25 && (nItem <= 25 || nItem == 50))) + { + // If this is an anim we need to properly destroy it so we need to do some proper detection and not wild guesses. + if (pPickupActor->nRun == pPickupActor->nDamage && pPickupActor->nRun != 0 && pPickupActor->nPhase == ITEM_MAGIC) + { + DestroyAnim(pPickupActor); + } + else + { + DeleteActor(pPickupActor); + } + } + else + { + StartRegenerate(pPickupActor); + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void doPickupWeapon(Player* pPlayer, DExhumedActor* pPickupActor, int nItem, int nWeapon, int nAmount, int nSound = kSound72) +{ + const int weapFlag = 1 << nWeapon; + + if (pPlayer->nPlayerWeapons & weapFlag) + { + if (currentLevel->gameflags & LEVEL_EX_MULTI) + AddAmmo(pPlayer->nPlayer, WeaponInfo[nWeapon].nAmmoType, nAmount); + } + else + { + SetNewWeaponIfBetter(pPlayer->nPlayer, nWeapon); + pPlayer->nPlayerWeapons |= weapFlag; + AddAmmo(pPlayer->nPlayer, WeaponInfo[nWeapon].nAmmoType, nAmount); + } + + if (nWeapon == 2) + CheckClip(pPlayer->nPlayer); + + if (nItem > 50) + { + pPickupActor->spr.cstat = CSTAT_SPRITE_INVISIBLE; + DestroyItemAnim(pPickupActor); + } + else + { + doPickupDestroy(pPickupActor, nItem); + } + + doPickupNotification(pPlayer, nItem, StaticSound[nSound]); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void doPickupHealth(Player* pPlayer, DExhumedActor* pPickupActor, int nItem, const int nAmount, int nSound) +{ + if (!pPickupActor->spr.hitag || nAmount > 0 && pPlayer->nHealth >= 800) + return; + + int tintRed = 0, tintGreen = 16; + + if (!pPlayer->invincibility || nAmount > 0) + { + pPlayer->nHealth += nAmount; + + if (pPlayer->nHealth > 800) + { + pPlayer->nHealth = 800; + } + else if (pPlayer->nHealth < 0) + { + nSound = -1; + StartDeathSeq(pPlayer->nPlayer, 0); + } + } + + if (nItem == 12) + { + pPickupActor->spr.hitag = 0; + pPickupActor->spr.picnum++; + ChangeActorStat(pPickupActor, 0); + } + else + { + if (nItem == 14) + { + tintRed = tintGreen; + tintGreen = 0; + } + + doPickupDestroy(pPickupActor, nItem); + } + + doPickupNotification(pPlayer, nItem, nSound, tintRed, tintGreen); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void doPlayerItemPickups(Player* const pPlayer) +{ + const auto pPlayerActor = pPlayer->pActor; + const auto pPlayerSect = pPlayerActor->sector(); + + if (const auto pPickupActor = feebtag(pPlayerActor->spr.pos, pPlayerSect, pPlayer->nMagic, pPlayer->nHealth, 48)) + { + static constexpr int itemArray[] = {kItemHeart, kItemInvincibility, kItemDoubleDamage, kItemInvisibility, kItemTorch, kItemMask}; + static constexpr int weapArray[] = {6, 24, 100, 20, 2}; + static constexpr int healArray[] = {40, 160, -200}; + static constexpr int ammoArray[] = {1, 3, 2}; + + switch (const int nItem = pPickupActor->spr.statnum - 900) + { + case 6: // Speed Loader + case 7: // Fuel Canister + case 8: // M - 60 Ammo Belt + if (AddAmmo(pPlayer->nPlayer, ammoArray[nItem - 6], pPickupActor->spr.hitag)) + { + if (nItem == 8) CheckClip(pPlayer->nPlayer); + doPickupDestroy(pPickupActor, nItem); + doPickupNotification(pPlayer, nItem, StaticSound[kSoundAmmoPickup]); + } + break; + + case 9: // Grenade + case 27: // May not be grenade, needs confirmation + case 55: + doPickupWeapon(pPlayer, pPickupActor, nItem, 4, 1, kSoundAmmoPickup); + break; + + case 10: // Pickable item + case 15: // Pickable item + case 16: // Reserved + case 24: + case 31: // Check whether is grenade or not as it matches sequence for weapons below + case 34: + case 35: + case 36: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 51: + case 58: + doPickupDestroy(pPickupActor, nItem); + doPickupNotification(pPlayer, nItem); + break; + + case 11: // Map + GrabMap(); + doPickupDestroy(pPickupActor, nItem); + doPickupNotification(pPlayer, nItem); + break; + + case 12: // Berry Twig + case 13: // Blood Bowl + case 14: // Cobra Venom Bowl + doPickupHealth(pPlayer, pPickupActor, nItem, healArray[nItem - 12], nItem + 8); + break; + + case 17: // Bubble Nest + pPlayer->nAir += 10; + + if (pPlayer->nAir > 100) + pPlayer->nAir = 100; // TODO - constant + + if (pPlayer->nBreathTimer < 89) + D3PlayFX(StaticSound[kSound13], pPlayerActor); + + pPlayer->nBreathTimer = 90; + break; + + case 18: // Still Beating Heart + case 19: // Scarab amulet(Invicibility) + case 20: // Severed Slave Hand(double damage) + case 21: // Unseen eye(Invisibility) + case 22: // Torch + case 23: // Sobek Mask + if (GrabItem(pPlayer->nPlayer, itemArray[nItem - 18])) + { + doPickupDestroy(pPickupActor, nItem); + doPickupNotification(pPlayer, nItem); + } + break; + + case 25: // Extra Life + if (pPlayer->nLives < kMaxPlayerLives) + { + pPlayer->nLives++; + doPickupDestroy(pPickupActor, nItem); + doPickupNotification(pPlayer, nItem, -1, 32, 32); + } + break; + + case 26: // sword pickup?? + doPickupWeapon(pPlayer, pPickupActor, nItem, 0, 0); + break; + + case 28: // .357 Magnum Revolver + case 52: + case 29: // M - 60 Machine Gun + case 53: + case 30: // Flame Thrower + case 54: + case 32: // Cobra Staff + case 56: + case 33: // Eye of Ra Gauntlet + case 57: + { + const int index = nItem - 28 - 24 * (nItem > 50); + doPickupWeapon(pPlayer, pPickupActor, nItem, index + 1, weapArray[index]); + break; + } + + case 37: // Cobra staff ammo + case 38: // Raw Energy + if (AddAmmo(pPlayer->nPlayer, nItem - 32, (nItem == 38) ? pPickupActor->spr.hitag : 1)) + { + doPickupDestroy(pPickupActor, nItem); + doPickupNotification(pPlayer, nItem, StaticSound[kSoundAmmoPickup]); + } + break; + + case 45: // Power key + case 46: // Time key + case 47: // War key + case 48: // Earth key + { + const int keybit = 4096 << (nItem - 45); + if (!(pPlayer->keys & keybit)) + { + pPlayer->keys |= keybit; + doPickupDestroy(pPickupActor, nItem); + doPickupNotification(pPlayer, nItem); + } + break; + } + + case 49: // Magical Essence + case 50: // ? + if (pPlayer->nMagic < 1000) + { + pPlayer->nMagic += 100; + + if (pPlayer->nMagic >= 1000) + pPlayer->nMagic = 1000; + + doPickupDestroy(pPickupActor, nItem); + doPickupNotification(pPlayer, nItem, StaticSound[kSoundMana1]); + } + break; + + case 59: // Scarab (Checkpoint) + if (nLocalPlayer == pPlayer->nPlayer) + { + pPickupActor->nIndex2++; + pPickupActor->nAction &= 0xEF; + pPickupActor->nIndex = 0; + ChangeActorStat(pPickupActor, 899); + } + SetSavePoint(pPlayer->nPlayer, pPlayerActor->spr.pos, pPlayerSect, pPlayerActor->spr.Angles.Yaw); + break; + + case 60: // Golden Sarcophagus (End Level) + if (!bInDemo) LevelFinished(); + DestroyItemAnim(pPickupActor); + DeleteActor(pPickupActor); + break; + } + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void updatePlayerTarget(Player* const pPlayer) { const auto pPlayerActor = pPlayer->pActor; diff --git a/source/games/exhumed/src/playerpickups.cpp b/source/games/exhumed/src/playerpickups.cpp deleted file mode 100644 index 3e2b0d3c6..000000000 --- a/source/games/exhumed/src/playerpickups.cpp +++ /dev/null @@ -1,397 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 2010-2019 EDuke32 developers and contributors -Copyright (C) 2019 sirlemonhead, Nuke.YKT -This file is part of PCExhumed. -PCExhumed is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 2 -as published by the Free Software Foundation. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -//------------------------------------------------------------------------- - -#include "ns.h" -#include "player.h" - -BEGIN_PS_NS - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -static DExhumedActor* feebtag(const DVector3& pos, sectortype* pSector, int nMagic, int nHealth, double deflen) -{ - DExhumedActor* pPickupActor = nullptr; - auto startwall = pSector->walls.Data(); - int nWalls = pSector->walls.Size(); - - while (1) - { - if (pSector != nullptr) - { - ExhumedSectIterator it(pSector); - while (auto itActor = it.Next()) - { - const int nStat = itActor->spr.statnum; - - if (nStat >= 900 && !(itActor->spr.cstat & CSTAT_SPRITE_INVISIBLE)) - { - const auto diff = itActor->spr.pos - pos; - - if (diff.Z < 20 && diff.Z > -100) - { - const auto len = diff.XY().Length(); - const bool needsMagic = (nStat != 950 && nStat != 949) || nMagic < 1000; - const bool needsHealth = (nStat != 912 && nStat != 913) || nHealth < 800; - - if (len < deflen && needsMagic && needsHealth) - { - deflen = len; - pPickupActor = itActor; - } - } - } - } - } - - nWalls--; - if (nWalls < 0) - return pPickupActor; - - pSector = startwall->nextSector(); - startwall++; - } - - return pPickupActor; -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -static void doPickupNotification(Player* const pPlayer, const int nItem, const int nSound = -1, const int tintRed = 0, const int tintGreen = 16) -{ - if (pPlayer->nPlayer == nLocalPlayer) - { - if (nItemText[nItem] > -1 && nTotalPlayers == 1) - pickupMessage(nItem); - - if (nSound > -1) - PlayLocalSound(nSound, 0); - - TintPalette(tintRed * 4, tintGreen * 4, 0); - } -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -static void doPickupDestroy(DExhumedActor* const pPickupActor, const int nItem) -{ - if (!(currentLevel->gameflags & LEVEL_EX_MULTI) || (nItem >= 25 && (nItem <= 25 || nItem == 50))) - { - // If this is an anim we need to properly destroy it so we need to do some proper detection and not wild guesses. - if (pPickupActor->nRun == pPickupActor->nDamage && pPickupActor->nRun != 0 && pPickupActor->nPhase == ITEM_MAGIC) - { - DestroyAnim(pPickupActor); - } - else - { - DeleteActor(pPickupActor); - } - } - else - { - StartRegenerate(pPickupActor); - } -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -static void doPickupWeapon(Player* pPlayer, DExhumedActor* pPickupActor, int nItem, int nWeapon, int nAmount, int nSound = kSound72) -{ - const int weapFlag = 1 << nWeapon; - - if (pPlayer->nPlayerWeapons & weapFlag) - { - if (currentLevel->gameflags & LEVEL_EX_MULTI) - { - AddAmmo(pPlayer->nPlayer, WeaponInfo[nWeapon].nAmmoType, nAmount); - } - } - else - { - SetNewWeaponIfBetter(pPlayer->nPlayer, nWeapon); - pPlayer->nPlayerWeapons |= weapFlag; - AddAmmo(pPlayer->nPlayer, WeaponInfo[nWeapon].nAmmoType, nAmount); - } - - if (nWeapon == 2) - CheckClip(pPlayer->nPlayer); - - if (nItem > 50) - { - pPickupActor->spr.cstat = CSTAT_SPRITE_INVISIBLE; - DestroyItemAnim(pPickupActor); - } - else - { - doPickupDestroy(pPickupActor, nItem); - } - - doPickupNotification(pPlayer, nItem, StaticSound[nSound]); -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -static void doPickupHealth(Player* pPlayer, DExhumedActor* pPickupActor, int nItem, const int nAmount, int nSound) -{ - if (nAmount <= 0 || pPlayer->nHealth < 800) - { - int tintRed = 0, tintGreen = 16; - - if (!pPlayer->invincibility || nAmount > 0) - { - pPlayer->nHealth += nAmount; - - if (pPlayer->nHealth > 800) - { - pPlayer->nHealth = 800; - } - else if (pPlayer->nHealth < 0) - { - nSound = -1; - StartDeathSeq(pPlayer->nPlayer, 0); - } - } - - if (nItem == 12) - { - pPickupActor->spr.hitag = 0; - pPickupActor->spr.picnum++; - ChangeActorStat(pPickupActor, 0); - } - else - { - if (nItem == 14) - { - tintRed = tintGreen; - tintGreen = 0; - } - - doPickupDestroy(pPickupActor, nItem); - } - - doPickupNotification(pPlayer, nItem, nSound, tintRed, tintGreen); - } -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void doPlayerItemPickups(Player* const pPlayer) -{ - const auto pPlayerActor = pPlayer->pActor; - const auto pPickupActor = feebtag(pPlayerActor->spr.pos, pPlayerActor->sector(), pPlayer->nMagic, pPlayer->nHealth, 48); - - if (pPickupActor != nullptr && pPickupActor->spr.statnum >= 900) - { - const int nItem = pPickupActor->spr.statnum - 900; - - if (nItem <= 60) - { - static constexpr int itemArray[] = {kItemHeart, kItemInvincibility, kItemDoubleDamage, kItemInvisibility, kItemTorch, kItemMask}; - static constexpr int weapArray[] = {6, 24, 100, 20, 2}; - static constexpr int healArray[] = {40, 160, -200}; - static constexpr int ammoArray[] = {1, 3, 2}; - - switch (nItem) - { - case 6: // Speed Loader - case 7: // Fuel Canister - case 8: // M - 60 Ammo Belt - if (AddAmmo(pPlayer->nPlayer, ammoArray[nItem - 6], pPickupActor->spr.hitag)) - { - if (nItem == 8) CheckClip(pPlayer->nPlayer); - doPickupDestroy(pPickupActor, nItem); - doPickupNotification(pPlayer, nItem, StaticSound[kSoundAmmoPickup]); - } - break; - - case 9: // Grenade - case 27: // May not be grenade, needs confirmation - case 55: - doPickupWeapon(pPlayer, pPickupActor, nItem, 4, 1, kSoundAmmoPickup); - break; - - case 10: // Pickable item - case 15: // Pickable item - case 16: // Reserved - case 24: - case 31: // Check whether is grenade or not as it matches sequence for weapons below - case 34: - case 35: - case 36: - case 39: - case 40: - case 41: - case 42: - case 43: - case 44: - case 51: - case 58: - doPickupDestroy(pPickupActor, nItem); - doPickupNotification(pPlayer, nItem); - break; - - case 11: // Map - GrabMap(); - doPickupDestroy(pPickupActor, nItem); - doPickupNotification(pPlayer, nItem); - break; - - case 12: // Berry Twig - case 13: // Blood Bowl - case 14: // Cobra Venom Bowl - if (pPickupActor->spr.hitag != 0) - doPickupHealth(pPlayer, pPickupActor, nItem, healArray[nItem - 12], nItem + 8); - break; - - case 17: // Bubble Nest - pPlayer->nAir += 10; - - if (pPlayer->nAir > 100) - pPlayer->nAir = 100; // TODO - constant - - if (pPlayer->nBreathTimer < 89) - D3PlayFX(StaticSound[kSound13], pPlayerActor); - - pPlayer->nBreathTimer = 90; - break; - - case 18: // Still Beating Heart - case 19: // Scarab amulet(Invicibility) - case 20: // Severed Slave Hand(double damage) - case 21: // Unseen eye(Invisibility) - case 22: // Torch - case 23: // Sobek Mask - if (GrabItem(pPlayer->nPlayer, itemArray[nItem - 18])) - { - doPickupDestroy(pPickupActor, nItem); - doPickupNotification(pPlayer, nItem); - } - break; - - case 25: // Extra Life - if (pPlayer->nLives < kMaxPlayerLives) - { - pPlayer->nLives++; - doPickupDestroy(pPickupActor, nItem); - doPickupNotification(pPlayer, nItem, -1, 32, 32); - } - break; - - case 26: // sword pickup?? - doPickupWeapon(pPlayer, pPickupActor, nItem, 0, 0); - break; - - case 28: // .357 Magnum Revolver - case 52: - case 29: // M - 60 Machine Gun - case 53: - case 30: // Flame Thrower - case 54: - case 32: // Cobra Staff - case 56: - case 33: // Eye of Ra Gauntlet - case 57: - { - const int index = nItem - 28 - 24 * (nItem > 50); - doPickupWeapon(pPlayer, pPickupActor, nItem, index + 1, weapArray[index]); - break; - } - - case 37: // Cobra staff ammo - case 38: // Raw Energy - if (AddAmmo(pPlayer->nPlayer, nItem - 32, (nItem == 38) ? pPickupActor->spr.hitag : 1)) - { - doPickupDestroy(pPickupActor, nItem); - doPickupNotification(pPlayer, nItem, StaticSound[kSoundAmmoPickup]); - } - break; - - case 45: // Power key - case 46: // Time key - case 47: // War key - case 48: // Earth key - { - const int keybit = 4096 << (nItem - 45); - if (!(pPlayer->keys & keybit)) - { - pPlayer->keys |= keybit; - doPickupDestroy(pPickupActor, nItem); - doPickupNotification(pPlayer, nItem); - } - break; - } - - case 49: // Magical Essence - case 50: // ? - if (pPlayer->nMagic < 1000) - { - pPlayer->nMagic += 100; - - if (pPlayer->nMagic >= 1000) - pPlayer->nMagic = 1000; - - doPickupDestroy(pPickupActor, nItem); - doPickupNotification(pPlayer, nItem, StaticSound[kSoundMana1]); - } - break; - - case 59: // Scarab (Checkpoint) - if (nLocalPlayer == pPlayer->nPlayer) - { - pPickupActor->nIndex2++; - pPickupActor->nAction &= 0xEF; - pPickupActor->nIndex = 0; - ChangeActorStat(pPickupActor, 899); - } - SetSavePoint(pPlayer->nPlayer, pPlayerActor->spr.pos, pPlayerActor->sector(), pPlayerActor->spr.Angles.Yaw); - break; - - case 60: // Golden Sarcophagus (End Level) - if (!bInDemo) LevelFinished(); - DestroyItemAnim(pPickupActor); - DeleteActor(pPickupActor); - break; - } - } - } -} - -END_PS_NS