diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Anchor.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Anchor.cpp index 3e4fdea2aff..45fa668da73 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Anchor.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Anchor.cpp @@ -462,6 +462,42 @@ void GameInteractorAnchor::HandleRemoteJson(nlohmann::json payload) { if (payload["type"] == "UPDATE_KEY_COUNT" && GameInteractor::IsSaveLoaded()) { gSaveContext.inventory.dungeonKeys[payload["sceneNum"].get()] = payload["amount"].get(); } + if (payload["type"] == "DAMAGE_PLAYER") { + if (payload["damageEffect"] > 0 && GET_PLAYER(gPlayState)->invincibilityTimer <= 0 && + !Player_InBlockingCsMode(gPlayState, GET_PLAYER(gPlayState))) { + if (payload["damageEffect"] == PUPPET_DMGEFF_NORMAL) { + u8 damage = payload["damageValue"]; + Player_InflictDamage(gPlayState, damage * -4); + func_80837C0C(gPlayState, GET_PLAYER(gPlayState), 0, 0, 0, 0, 0); + GET_PLAYER(gPlayState)->invincibilityTimer = 18; + GET_PLAYER(gPlayState)->actor.freezeTimer = 0; + } else if (payload["damageEffect"] == PUPPET_DMGEFF_ICE) { + GET_PLAYER(gPlayState)->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD); + func_80837C0C(gPlayState, GET_PLAYER(gPlayState), 3, 0.0f, 0.0f, 0, 20); + GET_PLAYER(gPlayState)->invincibilityTimer = 18; + GET_PLAYER(gPlayState)->actor.freezeTimer = 0; + } else if (payload["damageEffect"] == PUPPET_DMGEFF_FIRE) { + for (int i = 0; i < 18; i++) { + GET_PLAYER(gPlayState)->flameTimers[i] = Rand_S16Offset(0, 200); + } + GET_PLAYER(gPlayState)->isBurning = true; + func_80837C0C(gPlayState, GET_PLAYER(gPlayState), 0, 0, 0, 0, 0); + GET_PLAYER(gPlayState)->invincibilityTimer = 18; + GET_PLAYER(gPlayState)->actor.freezeTimer = 0; + } else if (payload["damageEffect"] == PUPPET_DMGEFF_THUNDER) { + func_80837C0C(gPlayState, GET_PLAYER(gPlayState), 4, 0.0f, 0.0f, 0, 20); + GET_PLAYER(gPlayState)->invincibilityTimer = 18; + GET_PLAYER(gPlayState)->actor.freezeTimer = 0; + } else if (payload["damageEffect"] == PUPPET_DMGEFF_KNOCKBACK) { + func_8002F71C(gPlayState, &GET_PLAYER(gPlayState)->actor, 100.0f * 0.04f + 4.0f, GET_PLAYER(gPlayState)->actor.world.rot.y, 8.0f); + GET_PLAYER(gPlayState)->invincibilityTimer = 28; + GET_PLAYER(gPlayState)->actor.freezeTimer = 0; + } else if (payload["damageEffect"] == PUPPET_DMGEFF_STUN) { + GET_PLAYER(gPlayState)->actor.freezeTimer = 20; + Actor_SetColorFilter(&GET_PLAYER(gPlayState)->actor, 0, 0xFF, 0, 10); + } + } + } if (payload["type"] == "GAME_COMPLETE") { AnchorClient anchorClient = GameInteractorAnchor::AnchorClients[payload["clientId"].get()]; Anchor_DisplayMessage({ @@ -845,6 +881,20 @@ void Anchor_UpdateKeyCount(int16_t sceneNum, int8_t amount) { GameInteractorAnchor::Instance->TransmitJsonToRemote(payload); } +void Anchor_DamagePlayer(uint32_t puppetIndex, u8 damageEffect, u8 damageValue) { + if (!GameInteractor::Instance->isRemoteInteractorConnected || !GameInteractor::Instance->IsSaveLoaded()) return; + + uint32_t clientId = GameInteractorAnchor::FairyIndexToClientId[puppetIndex]; + nlohmann::json payload; + + payload["type"] = "DAMAGE_PLAYER"; + payload["damageEffect"] = damageEffect; + payload["damageValue"] = damageValue; + payload["targetClientId"] = clientId; + + GameInteractorAnchor::Instance->TransmitJsonToRemote(payload); +} + void Anchor_GameComplete() { if (!GameInteractor::Instance->isRemoteInteractorConnected || !GameInteractor::Instance->IsSaveLoaded()) return; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Anchor.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Anchor.h index 0b8f8985214..7a442566e4d 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Anchor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Anchor.h @@ -6,6 +6,7 @@ #include "z64item.h" #include "z64actor.h" #include "z64save.h" +#include "src/overlays/actors/ovl_Link_Puppet/z_link_puppet.h" #include "./GameInteractor.h" typedef struct { @@ -93,6 +94,7 @@ void Anchor_UpdateBeansBought(uint8_t amount); void Anchor_UpdateBeansCount(uint8_t amount); void Anchor_ConsumeAdultTradeItem(uint8_t itemId); void Anchor_UpdateKeyCount(int16_t sceneNum, int8_t amount); +void Anchor_DamagePlayer(uint32_t puppetIndex, u8 damageEffect, u8 damageValue); void Anchor_GameComplete(); #ifdef __cplusplus diff --git a/soh/src/overlays/actors/ovl_Link_Puppet/z_link_puppet.c b/soh/src/overlays/actors/ovl_Link_Puppet/z_link_puppet.c index d0c18e9cbb6..42d17be4c8d 100644 --- a/soh/src/overlays/actors/ovl_Link_Puppet/z_link_puppet.c +++ b/soh/src/overlays/actors/ovl_Link_Puppet/z_link_puppet.c @@ -37,16 +37,6 @@ static Vec3s D_80854730 = { -57, 3377, 0 }; extern func_80833338(Player* this); -typedef enum { - PUPPET_DMGEFF_NONE, - PUPPET_DMGEFF_NORMAL, - PUPPET_DMGEFF_ICE, - PUPPET_DMGEFF_FIRE, - PUPPET_DMGEFF_THUNDER, - PUPPET_DMGEFF_KNOCKBACK, - PUPPET_DMGEFF_STUN, -} PuppetDamageEffect; - static DamageTable sDamageTable[] = { /* Deku nut */ DMG_ENTRY(0, PUPPET_DMGEFF_STUN), /* Deku stick */ DMG_ENTRY(2, PUPPET_DMGEFF_NORMAL), @@ -128,44 +118,11 @@ void LinkPuppet_Update(Actor* thisx, PlayState* play) { this->damageTimer--; } - if (playerData.damageEffect > 0 && GET_PLAYER(play)->invincibilityTimer <= 0 && - !Player_InBlockingCsMode(play, GET_PLAYER(play))) { - if (playerData.damageEffect == PUPPET_DMGEFF_NORMAL) { - Player_InflictDamage(play, playerData.damageValue * -4); - func_80837C0C(play, GET_PLAYER(play), 0, 0, 0, 0, 0); - GET_PLAYER(play)->invincibilityTimer = 18; - GET_PLAYER(play)->actor.freezeTimer = 0; - } else if (playerData.damageEffect == PUPPET_DMGEFF_ICE) { - GET_PLAYER(play)->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD); - func_80837C0C(play, GET_PLAYER(play), 3, 0.0f, 0.0f, 0, 20); - GET_PLAYER(play)->invincibilityTimer = 18; - GET_PLAYER(play)->actor.freezeTimer = 0; - } else if (playerData.damageEffect == PUPPET_DMGEFF_FIRE) { - for (int i = 0; i < 18; i++) { - GET_PLAYER(play)->flameTimers[i] = Rand_S16Offset(0, 200); - } - GET_PLAYER(play)->isBurning = true; - func_80837C0C(play, GET_PLAYER(play), 0, 0, 0, 0, 0); - GET_PLAYER(play)->invincibilityTimer = 18; - GET_PLAYER(play)->actor.freezeTimer = 0; - } else if (playerData.damageEffect == PUPPET_DMGEFF_THUNDER) { - func_80837C0C(play, GET_PLAYER(play), 4, 0.0f, 0.0f, 0, 20); - GET_PLAYER(play)->invincibilityTimer = 18; - GET_PLAYER(play)->actor.freezeTimer = 0; - } else if (playerData.damageEffect == PUPPET_DMGEFF_KNOCKBACK) { - func_8002F71C(play, &this->actor, 100.0f * 0.04f + 4.0f, this->actor.world.rot.y, 8.0f); - GET_PLAYER(play)->invincibilityTimer = 28; - GET_PLAYER(play)->actor.freezeTimer = 0; - } else if (playerData.damageEffect == PUPPET_DMGEFF_STUN) { - GET_PLAYER(play)->actor.freezeTimer = 20; - Actor_SetColorFilter(&GET_PLAYER(play)->actor, 0, 0xFF, 0, 10); - } - } - if (this->collider.base.acFlags & AC_HIT && this->damageTimer <= 0) { this->collider.base.acFlags &= ~AC_HIT; gSaveContext.playerData.damageEffect = this->actor.colChkInfo.damageEffect; gSaveContext.playerData.damageValue = this->actor.colChkInfo.damage; + Anchor_DamagePlayer(this->actor.params - 3, this->actor.colChkInfo.damageEffect, this->actor.colChkInfo.damage); if (gSaveContext.playerData.damageEffect == PUPPET_DMGEFF_STUN) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOMA_JR_FREEZE); diff --git a/soh/src/overlays/actors/ovl_Link_Puppet/z_link_puppet.h b/soh/src/overlays/actors/ovl_Link_Puppet/z_link_puppet.h index 1ce33382db3..51957e85a65 100644 --- a/soh/src/overlays/actors/ovl_Link_Puppet/z_link_puppet.h +++ b/soh/src/overlays/actors/ovl_Link_Puppet/z_link_puppet.h @@ -17,6 +17,16 @@ typedef struct LinkPuppet { uint8_t puppetAge; } LinkPuppet; +typedef enum { + PUPPET_DMGEFF_NONE, + PUPPET_DMGEFF_NORMAL, + PUPPET_DMGEFF_ICE, + PUPPET_DMGEFF_FIRE, + PUPPET_DMGEFF_THUNDER, + PUPPET_DMGEFF_KNOCKBACK, + PUPPET_DMGEFF_STUN, +} PuppetDamageEffect; + #ifdef __cplusplus extern "C" { #endif