/* GameInteractor is meant to be used for interacting with the game (yup...). It exposes functions that directly modify, add or remove game related elements. GameInteractionEffects.cpp is used when code that needs these functions also need a check wether a command can be run or not. If these checks need to happen wherever GameInteractor functions are needed, the GameInteractor functions can be called directly. */ #include "GameInteractor.h" #include extern "C" { #include "variables.h" #include "macros.h" #include "functions.h" extern PlayState* gPlayState; } #include "overlays/actors/ovl_En_Niw/z_en_niw.h" // MARK: - Effects GameInteractionEffectQueryResult GameInteractor::CanApplyEffect(GameInteractionEffectBase* effect) { return effect->CanBeApplied(); } GameInteractionEffectQueryResult GameInteractor::ApplyEffect(GameInteractionEffectBase* effect) { return effect->Apply(); } GameInteractionEffectQueryResult GameInteractor::RemoveEffect(RemovableGameInteractionEffect* effect) { return effect->Remove(); } // MARK: - Helpers bool GameInteractor::IsSaveLoaded(bool allowDbgSave) { Player* player; if (gPlayState != NULL) { player = GET_PLAYER(gPlayState); } // Checking for normal game mode prevents debug saves from reporting true on title screen if (gPlayState == NULL || player == NULL || gSaveContext.gameMode != GAMEMODE_NORMAL) { return false; } // Valid save file or debug save return (gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2) || (allowDbgSave && gSaveContext.fileNum == 0xFF); } bool GameInteractor::IsGameplayPaused() { Player* player = GET_PLAYER(gPlayState); return (Player_InBlockingCsMode(gPlayState, player) || gPlayState->pauseCtx.state != 0 || gPlayState->msgCtx.msgMode != 0) ? true : false; } bool GameInteractor::CanSpawnActor() { return GameInteractor::IsSaveLoaded() && !GameInteractor::IsGameplayPaused(); } bool GameInteractor::CanAddOrTakeAmmo(int16_t amount, int16_t item) { int16_t upgradeToCheck = 0; switch (item) { case ITEM_STICK: upgradeToCheck = UPG_STICKS; break; case ITEM_NUT: upgradeToCheck = UPG_NUTS; break; case ITEM_BOW: upgradeToCheck = UPG_QUIVER; break; case ITEM_SLINGSHOT: upgradeToCheck = UPG_BULLET_BAG; break; case ITEM_BOMB: upgradeToCheck = UPG_BOMB_BAG; break; default: break; } if (amount < 0 && AMMO(item) == 0) { return false; } if (item != ITEM_BOMBCHU && item != ITEM_BEAN) { if ((CUR_CAPACITY(upgradeToCheck) == 0) || (amount > 0 && AMMO(item) == CUR_CAPACITY(upgradeToCheck))) { return false; } return true; } else { // Separate checks for beans and bombchus because they don't have capacity upgrades if (INV_CONTENT(item) != item || (amount > 0 && ((item == ITEM_BOMBCHU && AMMO(item) == 50) || (item == ITEM_BEAN && AMMO(item) == 10)))) { return false; } return true; } }