diff --git a/soh/soh/Enhancements/ExtraTraps.cpp b/soh/soh/Enhancements/ExtraTraps.cpp index e88a8f1fe..155b1af71 100644 --- a/soh/soh/Enhancements/ExtraTraps.cpp +++ b/soh/soh/Enhancements/ExtraTraps.cpp @@ -82,7 +82,7 @@ static void RollRandomTrap(uint32_t seed) { case ADD_SPEED_TRAP: Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); - GameInteractor::State::RunSpeedModifier = -2; + GameInteractor::State::MovementSpeedMultiplier = 0.5f; statusTimer = 200; Notification::Emit({ .message = "Speed Decreased!" }); break; @@ -112,7 +112,7 @@ static void RollRandomTrap(uint32_t seed) { static void OnPlayerUpdate() { Player* player = GET_PLAYER(gPlayState); if (statusTimer == 0) { - GameInteractor::State::RunSpeedModifier = 0; + GameInteractor::State::MovementSpeedMultiplier = 1.0f; } if (eventTimer == 0) { switch (roll) { diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 91c0d4c1c..7713b48b8 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -1130,7 +1130,7 @@ static bool SpeedModifierHandler(std::shared_ptr Console, const s ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; } - GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyRunSpeedModifier(); + GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); try { dynamic_cast(effect)->parameters[0] = std::stoi(args[1], nullptr, 10); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp index 95455926b..03667dd86 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp @@ -11,6 +11,7 @@ have functions to both enable and disable said effect. #include "GameInteractionEffect.h" #include "GameInteractor.h" #include +#include "soh/Enhancements/cosmetics/CosmeticsEditor.h" extern "C" { #include @@ -371,19 +372,23 @@ void ForceEquipBoots::_Remove() { GameInteractor::RawAction::ForceEquipBoots(EQUIP_VALUE_BOOTS_KOKIRI); } -// MARK: - ModifyRunSpeedModifier -GameInteractionEffectQueryResult ModifyRunSpeedModifier::CanBeApplied() { +// MARK: - ModifyMovementSpeedMultiplier +GameInteractionEffectQueryResult ModifyMovementSpeedMultiplier::CanBeApplied() { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; } } -void ModifyRunSpeedModifier::_Apply() { - GameInteractor::State::RunSpeedModifier = parameters[0]; +void ModifyMovementSpeedMultiplier::_Apply() { + if (parameters[0] == -2) { + GameInteractor::State::MovementSpeedMultiplier = 0.5f; + } else if (parameters[0] == 2) { + GameInteractor::State::MovementSpeedMultiplier = 2.0f; + } } -void ModifyRunSpeedModifier::_Remove() { - GameInteractor::State::RunSpeedModifier = 0; +void ModifyMovementSpeedMultiplier::_Remove() { + GameInteractor::State::MovementSpeedMultiplier = 1.0f; } // MARK: - OneHitKO @@ -485,18 +490,6 @@ void SetCollisionViewer::_Remove() { GameInteractor::RawAction::SetCollisionViewer(false); } -// MARK: - SetCosmeticsColor -GameInteractionEffectQueryResult SetCosmeticsColor::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { - return GameInteractionEffectQueryResult::TemporarilyNotPossible; - } else { - return GameInteractionEffectQueryResult::Possible; - } -} -void SetCosmeticsColor::_Apply() { - GameInteractor::RawAction::SetCosmeticsColor(parameters[0], parameters[1]); -} - // MARK: - RandomizeCosmetics GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() { if (!GameInteractor::IsSaveLoaded()) { @@ -506,7 +499,7 @@ GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() { } } void RandomizeCosmetics::_Apply() { - GameInteractor::RawAction::RandomizeCosmeticsColors(true); + CosmeticsEditor_RandomizeAll(); } // MARK: - PressButton diff --git a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h index 72eb101b0..9243621d1 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h @@ -156,7 +156,7 @@ class ForceEquipBoots : public RemovableGameInteractionEffect, public Parameteri void _Remove() override; }; -class ModifyRunSpeedModifier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { +class ModifyMovementSpeedMultiplier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { GameInteractionEffectQueryResult CanBeApplied() override; void _Apply() override; void _Remove() override; @@ -200,11 +200,6 @@ class SetCollisionViewer : public RemovableGameInteractionEffect { void _Remove() override; }; -class SetCosmeticsColor : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { - GameInteractionEffectQueryResult CanBeApplied() override; - void _Apply() override; -}; - class RandomizeCosmetics : public GameInteractionEffectBase { GameInteractionEffectQueryResult CanBeApplied() override; void _Apply() override; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index db68ad86a..8ac2d9dda 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -76,7 +76,7 @@ uint8_t GameInteractor_PacifistModeActive(); uint8_t GameInteractor_DisableZTargetingActive(); uint8_t GameInteractor_ReverseControlsActive(); int32_t GameInteractor_DefenseModifier(); -int32_t GameInteractor_RunSpeedModifier(); +float GameInteractor_MovementSpeedMultiplier(); GIGravityLevel GameInteractor_GravityLevel(); uint32_t GameInteractor_GetEmulatedButtons(); void GameInteractor_SetEmulatedButtons(uint32_t buttons); @@ -204,7 +204,7 @@ class GameInteractor { static bool DisableZTargetingActive; static bool ReverseControlsActive; static int32_t DefenseModifier; - static int32_t RunSpeedModifier; + static float MovementSpeedMultiplier; static GIGravityLevel GravityLevel; static uint32_t EmulatedButtons; static uint8_t RandomBombFuseTimerActive; @@ -566,8 +566,6 @@ class GameInteractor { static void ClearAssignedButtons(uint8_t buttonSet); static void SetTimeOfDay(uint32_t time); static void SetCollisionViewer(bool active); - static void SetCosmeticsColor(uint8_t cosmeticCategory, uint8_t colorValue); - static void RandomizeCosmeticsColors(bool excludeBiddingWarColors); static void EmulateButtonPress(int32_t button); static void AddOrTakeAmmo(int16_t amount, int16_t item); static void EmulateRandomButtonPress(uint32_t chancePercentage = 100); @@ -575,8 +573,10 @@ class GameInteractor { static void SetPlayerInvincibility(bool active); static void ClearCutscenePointer(); - static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams); - static GameInteractionEffectQueryResult SpawnActor(uint32_t actorId, int32_t actorParams); + static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams, + std::string nameTag = ""); + static GameInteractionEffectQueryResult SpawnActor(uint32_t actorId, int32_t actorParams, + std::string nameTag = ""); }; }; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp index 779b37981..793466c19 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp @@ -1,9 +1,9 @@ #include "GameInteractor.h" #include -#include "soh/Enhancements/cosmetics/CosmeticsEditor.h" #include "soh/Enhancements/randomizer/3drando/random.hpp" #include #include "soh/Enhancements/debugger/colViewer.h" +#include "soh/Enhancements/nametag.h" extern "C" { #include "variables.h" @@ -405,125 +405,6 @@ void GameInteractor::RawAction::SetCollisionViewer(bool active) { } } -void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint8_t colorValue) { - Color_RGBA8 newColor; - newColor.r = 255; - newColor.g = 255; - newColor.b = 255; - newColor.a = 255; - - switch (colorValue) { - case GI_COLOR_RED: - newColor.r = 200; - newColor.g = 30; - newColor.b = 30; - break; - case GI_COLOR_GREEN: - newColor.r = 50; - newColor.g = 200; - newColor.b = 50; - break; - case GI_COLOR_BLUE: - newColor.r = 50; - newColor.g = 50; - newColor.b = 200; - break; - case GI_COLOR_ORANGE: - newColor.r = 200; - newColor.g = 120; - newColor.b = 0; - break; - case GI_COLOR_YELLOW: - newColor.r = 234; - newColor.g = 240; - newColor.b = 33; - break; - case GI_COLOR_PURPLE: - newColor.r = 144; - newColor.g = 13; - newColor.b = 178; - break; - case GI_COLOR_PINK: - newColor.r = 215; - newColor.g = 93; - newColor.b = 246; - break; - case GI_COLOR_BROWN: - newColor.r = 108; - newColor.g = 72; - newColor.b = 15; - break; - case GI_COLOR_BLACK: - newColor.r = 0; - newColor.g = 0; - newColor.b = 0; - break; - default: - break; - } - - switch (cosmeticCategory) { - case GI_COSMETICS_TUNICS: - CVarSetColor(CVAR_COSMETIC("Link.KokiriTunic.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Link.KokiriTunic.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Link.GoronTunic.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Link.GoronTunic.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Link.ZoraTunic.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Link.ZoraTunic.Changed"), 1); - break; - case GI_COSMETICS_NAVI: - CVarSetColor(CVAR_COSMETIC("Navi.EnemyPrimary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.EnemyPrimary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.EnemySecondary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.EnemySecondary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.IdlePrimary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.IdlePrimary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.IdleSecondary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.IdleSecondary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.NPCPrimary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.NPCPrimary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.NPCSecondary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.NPCSecondary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.PropsPrimary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.PropsPrimary.Changed"), 1); - CVarSetColor(CVAR_COSMETIC("Navi.PropsSecondary.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Navi.PropsSecondary.Changed"), 1); - break; - case GI_COSMETICS_HAIR: - CVarSetColor(CVAR_COSMETIC("Link.Hair.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Link.Hair.Changed"), 1); - break; - } - - Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); - ApplyOrResetCustomGfxPatches(); -} - -void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) { - const char* cvarsToLock[12] = { - CVAR_COSMETIC("Link.KokiriTunic.Locked"), CVAR_COSMETIC("Link.GoronTunic.Locked"), - CVAR_COSMETIC("Link.ZoraTunic.Locked"), CVAR_COSMETIC("Navi.EnemyPrimary.Locked"), - CVAR_COSMETIC("Navi.EnemySecondary.Locked"), CVAR_COSMETIC("Navi.IdlePrimary.Locked"), - CVAR_COSMETIC("Navi.IdleSecondary.Locked"), CVAR_COSMETIC("Navi.NPCPrimary.Locked"), - CVAR_COSMETIC("Navi.NPCSecondary.Locked"), CVAR_COSMETIC("Navi.PropsPrimary.Locked"), - CVAR_COSMETIC("Navi.PropsSecondary.Locked"), CVAR_COSMETIC("Link.Hair.Locked") - }; - - if (excludeBiddingWarColors) { - for (uint8_t i = 0; i < 12; i++) { - CVarSetInteger(cvarsToLock[i], 1); - } - } - - CosmeticsEditor_RandomizeAll(); - - if (excludeBiddingWarColors) { - for (uint8_t i = 0; i < 12; i++) { - CVarSetInteger(cvarsToLock[i], 0); - } - } -} - void GameInteractor::RawAction::EmulateButtonPress(int32_t button) { GameInteractor::State::EmulatedButtons |= button; } @@ -580,8 +461,8 @@ void GameInteractor::RawAction::ClearCutscenePointer() { gPlayState->csCtx.segment = &null_cs; } -GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, - int32_t enemyParams) { +GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams, + std::string nameTag) { if (!GameInteractor::CanSpawnActor()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; @@ -651,15 +532,29 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset pos.x += 10; pos.y += 10; pos.z += 10; - if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) == - NULL) { + Actor* actor = + Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0); + if (actor == NULL) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor(actor, nameTag.c_str()); + } + if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC); + } } return GameInteractionEffectQueryResult::Possible; } else { - if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) != - NULL) { + Actor* actor = + Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0); + if (actor != NULL) { + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor(actor, nameTag.c_str()); + } + if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC); + } return GameInteractionEffectQueryResult::Possible; } } @@ -667,7 +562,8 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset return GameInteractionEffectQueryResult::TemporarilyNotPossible; } -GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t actorId, int32_t actorParams) { +GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t actorId, int32_t actorParams, + std::string nameTag) { if (!GameInteractor::CanSpawnActor()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; @@ -684,6 +580,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t return GameInteractionEffectQueryResult::TemporarilyNotPossible; } + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor((Actor*)cucco, nameTag.c_str()); + } cucco->actionFunc = func_80AB70A0_nocutscene; return GameInteractionEffectQueryResult::Possible; } else if (actorId == ACTOR_EN_BOM) { @@ -703,8 +602,15 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t return GameInteractionEffectQueryResult::Possible; } else { // Generic spawn an actor at Link's position - if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x, - player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actorParams, 0) != NULL) { + Actor* actor = Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x, + player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actorParams, 0); + if (actor != NULL) { + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor((Actor*)actor, nameTag.c_str()); + } + if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC); + } return GameInteractionEffectQueryResult::Possible; } } diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp index 21642dded..bdcb4f37a 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp @@ -10,7 +10,7 @@ bool GameInteractor::State::PacifistModeActive = 0; bool GameInteractor::State::DisableZTargetingActive = 0; bool GameInteractor::State::ReverseControlsActive = 0; int32_t GameInteractor::State::DefenseModifier = 0; -int32_t GameInteractor::State::RunSpeedModifier = 0; +float GameInteractor::State::MovementSpeedMultiplier = 1.0f; GIGravityLevel GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL; uint32_t GameInteractor::State::EmulatedButtons = 0; uint8_t GameInteractor::State::RandomBombFuseTimerActive = 0; @@ -81,8 +81,8 @@ int32_t GameInteractor_DefenseModifier() { } // MARK: - GameInteractor::State::DisableCameraRotationActive -int32_t GameInteractor_RunSpeedModifier() { - return GameInteractor::State::RunSpeedModifier; +float GameInteractor_MovementSpeedMultiplier() { + return GameInteractor::State::MovementSpeedMultiplier; } // MARK: - GameInteractor::State::DisableCameraRotationActive diff --git a/soh/soh/Network/CrowdControl/CrowdControl.cpp b/soh/soh/Network/CrowdControl/CrowdControl.cpp index f706bed89..fd293d8ba 100644 --- a/soh/soh/Network/CrowdControl/CrowdControl.cpp +++ b/soh/soh/Network/CrowdControl/CrowdControl.cpp @@ -136,9 +136,11 @@ void CrowdControl::EmitMessage(uint32_t eventId, long timeRemaining, EffectResul CrowdControl::EffectResult CrowdControl::ExecuteEffect(Effect* effect) { GameInteractionEffectQueryResult giResult; if (effect->category == kEffectCatSpawnEnemy) { - giResult = GameInteractor::RawAction::SpawnEnemyWithOffset(effect->spawnParams[0], effect->spawnParams[1]); + giResult = GameInteractor::RawAction::SpawnEnemyWithOffset(effect->spawnParams[0], effect->spawnParams[1], + effect->viewerName); } else if (effect->category == kEffectCatSpawnActor) { - giResult = GameInteractor::RawAction::SpawnActor(effect->spawnParams[0], effect->spawnParams[1]); + giResult = + GameInteractor::RawAction::SpawnActor(effect->spawnParams[0], effect->spawnParams[1], effect->viewerName); } else { giResult = GameInteractor::ApplyEffect(effect->giEffect); } @@ -185,6 +187,7 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { Effect* effect = new Effect(); effect->lastExecutionResult = EffectResult::Initiate; effect->id = dataReceived["id"]; + effect->viewerName = dataReceived["viewer"]; auto parameters = dataReceived["parameters"]; uint32_t receivedParameter = 0; auto effectName = dataReceived["code"].get(); @@ -301,13 +304,13 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { case kEffectIncreaseSpeed: effect->category = kEffectCatSpeed; effect->timeRemaining = 30000; - effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier(); + effect->giEffect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); dynamic_cast(effect->giEffect)->parameters[0] = 2; break; case kEffectDecreaseSpeed: effect->category = kEffectCatSpeed; effect->timeRemaining = 30000; - effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier(); + effect->giEffect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); dynamic_cast(effect->giEffect)->parameters[0] = -2; break; case kEffectLowGravity: @@ -620,147 +623,6 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { dynamic_cast(effect->giEffect)->parameters[0] = GI_TP_DEST_PRELUDE; break; - // Tunic Color (Bidding War) - case kEffectTunicRed: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_RED; - break; - case kEffectTunicGreen: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_GREEN; - break; - case kEffectTunicBlue: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLUE; - break; - case kEffectTunicOrange: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE; - break; - case kEffectTunicYellow: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW; - break; - case kEffectTunicPurple: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE; - break; - case kEffectTunicPink: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PINK; - break; - case kEffectTunicBrown: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BROWN; - break; - case kEffectTunicBlack: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLACK; - break; - - // Navi Color (Bidding War) - case kEffectNaviRed: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_RED; - break; - case kEffectNaviGreen: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_GREEN; - break; - case kEffectNaviBlue: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLUE; - break; - case kEffectNaviOrange: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE; - break; - case kEffectNaviYellow: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW; - break; - case kEffectNaviPurple: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE; - break; - case kEffectNaviPink: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PINK; - break; - case kEffectNaviBrown: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BROWN; - break; - case kEffectNaviBlack: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLACK; - break; - - // Link's Hair Color (Bidding War) - case kEffectHairRed: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_RED; - break; - case kEffectHairGreen: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_GREEN; - break; - case kEffectHairBlue: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLUE; - break; - case kEffectHairOrange: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE; - break; - case kEffectHairYellow: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW; - break; - case kEffectHairPurple: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE; - break; - case kEffectHairPink: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PINK; - break; - case kEffectHairBrown: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BROWN; - break; - case kEffectHairBlack: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLACK; - break; - default: break; } diff --git a/soh/soh/Network/CrowdControl/CrowdControl.h b/soh/soh/Network/CrowdControl/CrowdControl.h index 8951e6cf1..f906961c3 100644 --- a/soh/soh/Network/CrowdControl/CrowdControl.h +++ b/soh/soh/Network/CrowdControl/CrowdControl.h @@ -56,6 +56,7 @@ class CrowdControl : public Network { uint32_t category = 0; long timeRemaining; GameInteractionEffectBase* giEffect; + std::string viewerName; // Metadata used while executing (only for timed effects) bool isPaused; diff --git a/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs b/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs index b1617435c..554e0d56b 100644 --- a/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs +++ b/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs @@ -124,50 +124,5 @@ public class ShipOfHarkinian : SimpleTCPPack new("Requiem Destination", "tp_requiem") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to Desert Colossus." }, new("Nocturne Destination", "tp_nocturne") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Raveyard." }, new("Prelude Destination", "tp_prelude") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Temple of Time." }, - - // Tunic Color (Bidding War) - new("Tunic Color", "tunic", ItemKind.BidWar) - { - Parameters = new ParameterDef("Color", "color_tunic_param", - new Parameter("Red", "red"), - new Parameter("Green", "green"), - new Parameter("Blue", "blue"), - new Parameter("Orange", "orange"), - new Parameter("Yellow", "yellow"), - new Parameter("Purple", "purple"), - new Parameter("Pink", "pink"), - new Parameter("Brown", "brown"), - new Parameter("Black", "black")) - }, - - // Navi Color (Bidding War) - new("Navi Color", "navi", ItemKind.BidWar) - { - Parameters = new ParameterDef("Color", "color_navi_param", - new Parameter("Red", "red"), - new Parameter("Green", "green"), - new Parameter("Blue", "blue"), - new Parameter("Orange", "orange"), - new Parameter("Yellow", "yellow"), - new Parameter("Purple", "purple"), - new Parameter("Pink", "pink"), - new Parameter("Brown", "brown"), - new Parameter("Black", "black")) - }, - - // Link's Hair Color (Bidding War) - new("Link's Hair Color", "hair", ItemKind.BidWar) - { - Parameters = new ParameterDef("Color", "color_hair_param", - new Parameter("Red", "red"), - new Parameter("Green", "green"), - new Parameter("Blue", "blue"), - new Parameter("Orange", "orange"), - new Parameter("Yellow", "yellow"), - new Parameter("Purple", "purple"), - new Parameter("Pink", "pink"), - new Parameter("Brown", "brown"), - new Parameter("Black", "black")) - } }; } diff --git a/soh/soh/Network/Sail/Sail.cpp b/soh/soh/Network/Sail/Sail.cpp index a5396777e..08f23fca5 100644 --- a/soh/soh/Network/Sail/Sail.cpp +++ b/soh/soh/Network/Sail/Sail.cpp @@ -242,8 +242,8 @@ GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) { effect->parameters[0] = payload["parameters"][0].get(); } return effect; - } else if (name == "ModifyRunSpeedModifier") { - auto effect = new GameInteractionEffect::ModifyRunSpeedModifier(); + } else if (name == "ModifyMovementSpeedMultiplier") { + auto effect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); if (payload.contains("parameters")) { effect->parameters[0] = payload["parameters"][0].get(); } @@ -282,13 +282,6 @@ GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) { return effect; } else if (name == "SetCollisionViewer") { return new GameInteractionEffect::SetCollisionViewer(); - } else if (name == "SetCosmeticsColor") { - auto effect = new GameInteractionEffect::SetCosmeticsColor(); - if (payload.contains("parameters")) { - effect->parameters[0] = payload["parameters"][0].get(); - effect->parameters[1] = payload["parameters"][1].get(); - } - return effect; } else if (name == "RandomizeCosmetics") { return new GameInteractionEffect::RandomizeCosmetics(); } else if (name == "PressButton") { diff --git a/soh/soh/SohGui/SohMenuNetwork.cpp b/soh/soh/SohGui/SohMenuNetwork.cpp index bb6004288..f2fba3ff1 100644 --- a/soh/soh/SohGui/SohMenuNetwork.cpp +++ b/soh/soh/SohGui/SohMenuNetwork.cpp @@ -96,21 +96,15 @@ void SohMenu::AddMenuNetwork() { AddSidebarEntry("Network", path.sidebarName, 3); path.column = SECTION_COLUMN_1; + AddWidget(path, "About Crowd Control", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Crowd Control is a platform that allows viewers to interact " "with a streamer's game in real time.\n" "\n" - "Click the question mark to copy the link to the Crowd Control " - "website to your clipboard.", + "Please head over to www.crowdcontrol.live for more information!", WIDGET_TEXT); - AddWidget(path, ICON_FA_CLIPBOARD "##CrowdControl", WIDGET_BUTTON) - .Callback([](WidgetInfo& info) { - ImGui::SetClipboardText("https://crowdcontrol.live"); - Notification::Emit({ - .message = "Copied to clipboard", - }); - }) - .Options(ButtonOptions().Tooltip("https://crowdcontrol.live")); + + AddWidget(path, "Connect to Crowd Control", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Host & Port", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { ImGui::BeginDisabled(CrowdControl::Instance->isEnabled || CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); ImGui::Text("%s", info.name.c_str()); @@ -155,14 +149,25 @@ void SohMenu::AddMenuNetwork() { CrowdControl::Instance->Enable(); } }); - AddWidget(path, "Connecting...##CrowdControl", WIDGET_TEXT).PreFunc([](WidgetInfo& info) { + AddWidget(path, "Connecting...", WIDGET_TEXT).PreFunc([](WidgetInfo& info) { info.isHidden = !CrowdControl::Instance->isEnabled; if (CrowdControl::Instance->isConnected) { - info.name = "Connected##CrowdControl"; + info.name = "Connected"; } else { - info.name = "Connecting...##CrowdControl"; + info.name = "Connecting..."; } }); + AddWidget(path, "Additional Settings", WIDGET_SEPARATOR_TEXT); + AddWidget(path, "Enemy Name Tags", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags")) + .RaceDisable(true) + .Options(CheckboxOptions().Tooltip( + "When viewers spawn enemies, the enemy will have a name tag above them with the viewer's name.")); + AddWidget(path, "Spawned Enemies Ignored Ingame", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame")) + .RaceDisable(true) + .Options(CheckboxOptions().Tooltip("Enemies spawned by CrowdControl won't be considered for \"clear enemy " + "rooms\", so they don't need to be killed to complete these rooms.")); } } // namespace SohGui diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 3933f263d..620cb4959 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1284,8 +1284,16 @@ void Actor_UpdatePos(Actor* actor) { } void Actor_UpdateVelocityXZGravity(Actor* actor) { - actor->velocity.x = Math_SinS(actor->world.rot.y) * actor->speedXZ; - actor->velocity.z = Math_CosS(actor->world.rot.y) * actor->speedXZ; + Player* player = GET_PLAYER(gPlayState); + uint8_t inCutscene = player->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER || + player->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE || + player->stateFlags2 & PLAYER_STATE2_CRAWLING; + f32 speedModifier = 1.0f; + if (actor->id == ACTOR_PLAYER && !inCutscene) { + speedModifier = GameInteractor_MovementSpeedMultiplier(); + } + actor->velocity.x = Math_SinS(actor->world.rot.y) * actor->speedXZ * speedModifier; + actor->velocity.z = Math_CosS(actor->world.rot.y) * actor->speedXZ * speedModifier; actor->velocity.y += actor->gravity; if (actor->velocity.y < actor->minVelocityY) { diff --git a/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c b/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c index aa455739e..70bd36a6b 100644 --- a/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c +++ b/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c @@ -58,6 +58,11 @@ void EnAttackNiw_Init(Actor* thisx, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED; this->actor.shape.rot.y = this->actor.world.rot.y = (Rand_ZeroOne() - 0.5f) * 60000.0f; this->actionFunc = func_809B5670; + + if (CVarGetInteger("gCrowdControl", 0) && + CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, this, ACTORCAT_NPC); + } } void EnAttackNiw_Destroy(Actor* thisx, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 4ae6fb744..205079576 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -7124,15 +7124,6 @@ void func_8083DFE0(Player* this, f32* arg1, s16* arg2) { if (this->meleeWeaponState == 0) { float maxSpeed = R_RUN_SPEED_LIMIT / 100.0f; - int32_t giSpeedModifier = GameInteractor_RunSpeedModifier(); - if (giSpeedModifier != 0) { - if (giSpeedModifier > 0) { - maxSpeed *= giSpeedModifier; - } else { - maxSpeed /= abs(giSpeedModifier); - } - } - if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) == BUNNY_HOOD_FAST_AND_JUMP && this->currentMask == PLAYER_MASK_BUNNY) { maxSpeed *= 1.5f; @@ -8873,14 +8864,6 @@ void Player_Action_80842180(Player* this, PlayState* play) { Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_CURVED, play); if (!func_8083C484(this, &sp2C, &sp2A)) { - int32_t giSpeedModifier = GameInteractor_RunSpeedModifier(); - if (giSpeedModifier != 0) { - if (giSpeedModifier > 0) { - sp2C *= giSpeedModifier; - } else { - sp2C /= abs(giSpeedModifier); - } - } if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) {