mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-06-05 11:37:04 -04:00
@@ -191,6 +191,9 @@ inline void from_json(const json& j, SaveContext& saveContext) {
|
||||
j.at("swordHealth").get_to(saveContext.swordHealth);
|
||||
std::vector<u32> sceneFlagsArray;
|
||||
j.at("sceneFlags").get_to(sceneFlagsArray);
|
||||
if (sceneFlagsArray.size() < 124 * 4) {
|
||||
sceneFlagsArray.resize(124 * 4, 0);
|
||||
}
|
||||
for (int i = 0; i < 124; i++) {
|
||||
saveContext.sceneFlags[i].chest = sceneFlagsArray[i * 4];
|
||||
saveContext.sceneFlags[i].swch = sceneFlagsArray[i * 4 + 1];
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <libultraship/libultraship.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/Enhancements/randomizer/randomizerEnums/RandomizerCheck.h"
|
||||
|
||||
static bool isResultOfHandling = false;
|
||||
|
||||
@@ -39,6 +40,10 @@ void Anchor::HandlePacket_SetCheckStatus(nlohmann::json payload) {
|
||||
auto randoContext = Rando::Context::GetInstance();
|
||||
|
||||
RandomizerCheck rc = payload["rc"].get<RandomizerCheck>();
|
||||
if (rc < 0 || rc >= RC_MAX) {
|
||||
SPDLOG_ERROR("[Anchor] SET_CHECK_STATUS: rc {} out of range", (int)rc);
|
||||
return;
|
||||
}
|
||||
RandomizerCheckStatus status = payload["status"].get<RandomizerCheckStatus>();
|
||||
bool skipped = payload["skipped"].get<bool>();
|
||||
|
||||
|
||||
@@ -41,6 +41,13 @@ void Anchor::HandlePacket_SetFlag(nlohmann::json payload) {
|
||||
s16 flagType = payload["flagType"].get<s16>();
|
||||
s16 flag = payload["flag"].get<s16>();
|
||||
|
||||
// sceneNum == SCENE_ID_MAX is a sentinel meaning "global flag" (handled below); only larger
|
||||
// values would index gSaveContext.sceneFlags out of bounds.
|
||||
if (sceneNum < 0 || sceneNum > SCENE_ID_MAX) {
|
||||
SPDLOG_ERROR("[Anchor] SET_FLAG: sceneNum {} out of range", sceneNum);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sceneNum == SCENE_ID_MAX) {
|
||||
auto effect = new GameInteractionEffect::SetFlag();
|
||||
effect->parameters[0] = flagType;
|
||||
|
||||
@@ -39,6 +39,12 @@ void Anchor::HandlePacket_TeleportTo(nlohmann::json payload) {
|
||||
|
||||
s32 entranceIndex = payload["entranceIndex"].get<s32>();
|
||||
s8 roomIndex = payload["roomIndex"].get<s8>();
|
||||
|
||||
if (entranceIndex < 0 || roomIndex < 0) {
|
||||
SPDLOG_ERROR("[Anchor] TELEPORT_TO: invalid entranceIndex {} or roomIndex {}", entranceIndex, (int)roomIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
PosRot posRot = payload["posRot"].get<PosRot>();
|
||||
|
||||
gPlayState->nextEntranceIndex = entranceIndex;
|
||||
|
||||
@@ -41,6 +41,13 @@ void Anchor::HandlePacket_UnsetFlag(nlohmann::json payload) {
|
||||
s16 flagType = payload["flagType"].get<s16>();
|
||||
s16 flag = payload["flag"].get<s16>();
|
||||
|
||||
// sceneNum == SCENE_ID_MAX is a sentinel meaning "global flag" (handled below); only larger
|
||||
// values would index gSaveContext.sceneFlags out of bounds.
|
||||
if (sceneNum < 0 || sceneNum > SCENE_ID_MAX) {
|
||||
SPDLOG_ERROR("[Anchor] UNSET_FLAG: sceneNum {} out of range", sceneNum);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sceneNum == SCENE_ID_MAX) {
|
||||
auto effect = new GameInteractionEffect::UnsetFlag();
|
||||
effect->parameters[0] = flagType;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "soh/Network/Anchor/Anchor.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <libultraship/libultraship.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
|
||||
@@ -33,6 +34,12 @@ void Anchor::HandlePacket_UpdateDungeonItems(nlohmann::json payload) {
|
||||
}
|
||||
|
||||
u16 mapIndex = payload["mapIndex"].get<u16>();
|
||||
// dungeonKeys is shorter than dungeonItems (19 vs 20), so bound by the smaller of the two.
|
||||
if (mapIndex >= ARRAY_COUNT(gSaveContext.inventory.dungeonItems) ||
|
||||
mapIndex >= ARRAY_COUNT(gSaveContext.inventory.dungeonKeys)) {
|
||||
SPDLOG_ERROR("[Anchor] UPDATE_DUNGEON_ITEMS: mapIndex {} out of range", mapIndex);
|
||||
return;
|
||||
}
|
||||
gSaveContext.inventory.dungeonItems[mapIndex] = payload["dungeonItems"].get<u8>();
|
||||
gSaveContext.inventory.dungeonKeys[mapIndex] = payload["dungeonKeys"].get<s8>();
|
||||
}
|
||||
|
||||
@@ -29,19 +29,19 @@ void CrowdControl::OnDisconnected() {
|
||||
}
|
||||
|
||||
void CrowdControl::OnIncomingJson(nlohmann::json payload) {
|
||||
Effect* incomingEffect = ParseMessage(payload);
|
||||
std::unique_ptr<Effect> incomingEffect = ParseMessage(payload);
|
||||
if (!incomingEffect) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If effect is not a timed effect, execute and return result.
|
||||
if (!incomingEffect->timeRemaining) {
|
||||
EffectResult result = CrowdControl::ExecuteEffect(incomingEffect);
|
||||
EffectResult result = CrowdControl::ExecuteEffect(incomingEffect.get());
|
||||
EmitMessage(incomingEffect->id, incomingEffect->timeRemaining, result);
|
||||
} else {
|
||||
// If another timed effect is already active that conflicts with the incoming effect.
|
||||
bool isConflictingEffectActive = false;
|
||||
for (Effect* effect : activeEffects) {
|
||||
for (const auto& effect : activeEffects) {
|
||||
if (effect != incomingEffect && effect->category == incomingEffect->category &&
|
||||
effect->id < incomingEffect->id) {
|
||||
isConflictingEffectActive = true;
|
||||
@@ -52,14 +52,14 @@ void CrowdControl::OnIncomingJson(nlohmann::json payload) {
|
||||
|
||||
if (!isConflictingEffectActive) {
|
||||
// Check if effect can be applied, if it can't, let CC know.
|
||||
EffectResult result = CrowdControl::CanApplyEffect(incomingEffect);
|
||||
EffectResult result = CrowdControl::CanApplyEffect(incomingEffect.get());
|
||||
if (result == EffectResult::Retry || result == EffectResult::Failure) {
|
||||
EmitMessage(incomingEffect->id, incomingEffect->timeRemaining, result);
|
||||
return;
|
||||
}
|
||||
|
||||
activeEffectsMutex.lock();
|
||||
activeEffects.push_back(incomingEffect);
|
||||
activeEffects.push_back(std::move(incomingEffect));
|
||||
activeEffectsMutex.unlock();
|
||||
}
|
||||
}
|
||||
@@ -74,17 +74,15 @@ void CrowdControl::ProcessActiveEffects() {
|
||||
auto it = activeEffects.begin();
|
||||
|
||||
while (it != activeEffects.end()) {
|
||||
Effect* effect = *it;
|
||||
Effect* effect = it->get();
|
||||
EffectResult result = CrowdControl::ExecuteEffect(effect);
|
||||
|
||||
if (result == EffectResult::Success) {
|
||||
// If time remaining has reached 0, we have finished the effect.
|
||||
if (effect->timeRemaining <= 0) {
|
||||
it = activeEffects.erase(std::remove(activeEffects.begin(), activeEffects.end(), effect),
|
||||
activeEffects.end());
|
||||
GameInteractor::RemoveEffect(
|
||||
*dynamic_cast<RemovableGameInteractionEffect*>(effect->giEffect.get()));
|
||||
delete effect;
|
||||
it = activeEffects.erase(it);
|
||||
} else {
|
||||
// If we have a success after previously being paused, tell CC to resume timer.
|
||||
if (effect->isPaused) {
|
||||
@@ -168,7 +166,7 @@ CrowdControl::EffectResult CrowdControl::TranslateGiEnum(GameInteractionEffectQu
|
||||
return result;
|
||||
}
|
||||
|
||||
CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) {
|
||||
std::unique_ptr<CrowdControl::Effect> CrowdControl::ParseMessage(nlohmann::json dataReceived) {
|
||||
if (!dataReceived.contains("id") || !dataReceived.contains("type")) {
|
||||
SPDLOG_ERROR("[CrowdControl] Invalid payload received:\n{}", dataReceived.dump());
|
||||
return nullptr;
|
||||
@@ -176,13 +174,16 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) {
|
||||
|
||||
SPDLOG_INFO("[CrowdControl] Received payload:\n{}", dataReceived.dump());
|
||||
|
||||
if (!dataReceived.contains("code")) {
|
||||
// "parameters" is intentionally not required: most effects (spawn enemies, teleports, status
|
||||
// effects, etc.) carry no parameters. Its absence is handled safely below, and any type error
|
||||
// is caught by the guard in Network::HandleRemoteJson.
|
||||
if (!dataReceived.contains("code") || !dataReceived.contains("viewer")) {
|
||||
// This seems to happen when the CC session ends
|
||||
SPDLOG_ERROR("[CrowdControl] Payload does not contain code, ignoring.");
|
||||
SPDLOG_ERROR("[CrowdControl] Payload does not contain code or viewer, ignoring.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Effect* effect = new Effect();
|
||||
auto effect = std::make_unique<Effect>();
|
||||
effect->lastExecutionResult = EffectResult::Initiate;
|
||||
effect->id = dataReceived["id"];
|
||||
effect->viewerName = dataReceived["viewer"];
|
||||
@@ -194,9 +195,15 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) {
|
||||
receivedParameter = dataReceived["parameters"][0];
|
||||
}
|
||||
|
||||
auto it = effectStringToEnum.find(effectName);
|
||||
if (it == effectStringToEnum.end()) {
|
||||
SPDLOG_ERROR("[CrowdControl] Unknown effect code: {}", effectName);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Assign GameInteractionEffect + values to CC effect.
|
||||
// Categories are mostly used for checking for conflicting timed effects.
|
||||
switch (effectStringToEnum[effectName]) {
|
||||
switch (it->second) {
|
||||
|
||||
// Spawn Enemies and Objects
|
||||
case kEffectSpawnCuccoStorm:
|
||||
|
||||
@@ -64,14 +64,14 @@ class CrowdControl : public Network {
|
||||
|
||||
std::thread ccThreadProcess;
|
||||
|
||||
std::vector<Effect*> activeEffects;
|
||||
std::vector<std::unique_ptr<Effect>> activeEffects;
|
||||
std::mutex activeEffectsMutex;
|
||||
|
||||
void HandleRemoteData(nlohmann::json payload);
|
||||
void ProcessActiveEffects();
|
||||
|
||||
void EmitMessage(uint32_t eventId, long timeRemaining, EffectResult status);
|
||||
Effect* ParseMessage(nlohmann::json payload);
|
||||
std::unique_ptr<Effect> ParseMessage(nlohmann::json payload);
|
||||
EffectResult ExecuteEffect(Effect* effect);
|
||||
EffectResult CanApplyEffect(Effect* effect);
|
||||
EffectResult TranslateGiEnum(GameInteractionEffectQueryResult giResult);
|
||||
|
||||
@@ -157,5 +157,9 @@ void Network::HandleRemoteJson(std::string payload) {
|
||||
return;
|
||||
}
|
||||
|
||||
OnIncomingJson(jsonPayload);
|
||||
try {
|
||||
OnIncomingJson(jsonPayload);
|
||||
} catch (const std::exception& e) {
|
||||
SPDLOG_ERROR("[Network] Exception handling incoming JSON: {}", e.what());
|
||||
} catch (...) { SPDLOG_ERROR("[Network] Unknown exception handling incoming JSON"); }
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#include <libultraship/bridge.h>
|
||||
#include <libultraship/libultraship.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/util.h"
|
||||
|
||||
template <class DstType, class SrcType> bool IsType(const SrcType* src) {
|
||||
return dynamic_cast<const DstType*>(src) != nullptr;
|
||||
@@ -98,12 +96,12 @@ void Sail::OnIncomingJson(nlohmann::json payload) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* giEffect = EffectFromJson(payload["effect"]);
|
||||
auto giEffect = EffectFromJson(payload["effect"]);
|
||||
if (giEffect) {
|
||||
GameInteractionEffectQueryResult result;
|
||||
if (effectType == "remove") {
|
||||
if (IsType<RemovableGameInteractionEffect>(giEffect)) {
|
||||
result = dynamic_cast<RemovableGameInteractionEffect*>(giEffect)->Remove();
|
||||
if (IsType<RemovableGameInteractionEffect>(giEffect.get())) {
|
||||
result = dynamic_cast<RemovableGameInteractionEffect*>(giEffect.get())->Remove();
|
||||
} else {
|
||||
result = GameInteractionEffectQueryResult::NotPossible;
|
||||
}
|
||||
@@ -133,7 +131,7 @@ void Sail::OnIncomingJson(nlohmann::json payload) {
|
||||
} catch (...) { SPDLOG_ERROR("[Sail] Unknown exception handling remote JSON"); }
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) {
|
||||
std::unique_ptr<GameInteractionEffectBase> Sail::EffectFromJson(nlohmann::json payload) {
|
||||
if (!payload.contains("name")) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -141,7 +139,7 @@ GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) {
|
||||
std::string name = payload["name"].get<std::string>();
|
||||
|
||||
if (name == "SetSceneFlag") {
|
||||
auto effect = new GameInteractionEffect::SetSceneFlag();
|
||||
auto effect = std::make_unique<GameInteractionEffect::SetSceneFlag>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
effect->parameters[1] = payload["parameters"][1].get<int32_t>();
|
||||
@@ -149,7 +147,7 @@ GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) {
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "UnsetSceneFlag") {
|
||||
auto effect = new GameInteractionEffect::UnsetSceneFlag();
|
||||
auto effect = std::make_unique<GameInteractionEffect::UnsetSceneFlag>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
effect->parameters[1] = payload["parameters"][1].get<int32_t>();
|
||||
@@ -157,171 +155,171 @@ GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) {
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "SetFlag") {
|
||||
auto effect = new GameInteractionEffect::SetFlag();
|
||||
auto effect = std::make_unique<GameInteractionEffect::SetFlag>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
effect->parameters[1] = payload["parameters"][1].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "UnsetFlag") {
|
||||
auto effect = new GameInteractionEffect::UnsetFlag();
|
||||
auto effect = std::make_unique<GameInteractionEffect::UnsetFlag>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
effect->parameters[1] = payload["parameters"][1].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "ModifyHeartContainers") {
|
||||
auto effect = new GameInteractionEffect::ModifyHeartContainers();
|
||||
auto effect = std::make_unique<GameInteractionEffect::ModifyHeartContainers>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "FillMagic") {
|
||||
return new GameInteractionEffect::FillMagic();
|
||||
return std::make_unique<GameInteractionEffect::FillMagic>();
|
||||
} else if (name == "EmptyMagic") {
|
||||
return new GameInteractionEffect::EmptyMagic();
|
||||
return std::make_unique<GameInteractionEffect::EmptyMagic>();
|
||||
} else if (name == "ModifyRupees") {
|
||||
auto effect = new GameInteractionEffect::ModifyRupees();
|
||||
auto effect = std::make_unique<GameInteractionEffect::ModifyRupees>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "NoUI") {
|
||||
return new GameInteractionEffect::NoUI();
|
||||
return std::make_unique<GameInteractionEffect::NoUI>();
|
||||
} else if (name == "ModifyGravity") {
|
||||
auto effect = new GameInteractionEffect::ModifyGravity();
|
||||
auto effect = std::make_unique<GameInteractionEffect::ModifyGravity>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "ModifyHealth") {
|
||||
auto effect = new GameInteractionEffect::ModifyHealth();
|
||||
auto effect = std::make_unique<GameInteractionEffect::ModifyHealth>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "SetPlayerHealth") {
|
||||
auto effect = new GameInteractionEffect::SetPlayerHealth();
|
||||
auto effect = std::make_unique<GameInteractionEffect::SetPlayerHealth>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "FreezePlayer") {
|
||||
return new GameInteractionEffect::FreezePlayer();
|
||||
return std::make_unique<GameInteractionEffect::FreezePlayer>();
|
||||
} else if (name == "BurnPlayer") {
|
||||
return new GameInteractionEffect::BurnPlayer();
|
||||
return std::make_unique<GameInteractionEffect::BurnPlayer>();
|
||||
} else if (name == "ElectrocutePlayer") {
|
||||
return new GameInteractionEffect::ElectrocutePlayer();
|
||||
return std::make_unique<GameInteractionEffect::ElectrocutePlayer>();
|
||||
} else if (name == "KnockbackPlayer") {
|
||||
auto effect = new GameInteractionEffect::KnockbackPlayer();
|
||||
auto effect = std::make_unique<GameInteractionEffect::KnockbackPlayer>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "ModifyLinkSize") {
|
||||
auto effect = new GameInteractionEffect::ModifyLinkSize();
|
||||
auto effect = std::make_unique<GameInteractionEffect::ModifyLinkSize>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "InvisibleLink") {
|
||||
return new GameInteractionEffect::InvisibleLink();
|
||||
return std::make_unique<GameInteractionEffect::InvisibleLink>();
|
||||
} else if (name == "PacifistMode") {
|
||||
return new GameInteractionEffect::PacifistMode();
|
||||
return std::make_unique<GameInteractionEffect::PacifistMode>();
|
||||
} else if (name == "DisableZTargeting") {
|
||||
return new GameInteractionEffect::DisableZTargeting();
|
||||
return std::make_unique<GameInteractionEffect::DisableZTargeting>();
|
||||
} else if (name == "WeatherRainstorm") {
|
||||
return new GameInteractionEffect::WeatherRainstorm();
|
||||
return std::make_unique<GameInteractionEffect::WeatherRainstorm>();
|
||||
} else if (name == "ReverseControls") {
|
||||
return new GameInteractionEffect::ReverseControls();
|
||||
return std::make_unique<GameInteractionEffect::ReverseControls>();
|
||||
} else if (name == "ForceEquipBoots") {
|
||||
auto effect = new GameInteractionEffect::ForceEquipBoots();
|
||||
auto effect = std::make_unique<GameInteractionEffect::ForceEquipBoots>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "ModifyMovementSpeedMultiplier") {
|
||||
auto effect = new GameInteractionEffect::ModifyMovementSpeedMultiplier();
|
||||
auto effect = std::make_unique<GameInteractionEffect::ModifyMovementSpeedMultiplier>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "OneHitKO") {
|
||||
return new GameInteractionEffect::OneHitKO();
|
||||
return std::make_unique<GameInteractionEffect::OneHitKO>();
|
||||
} else if (name == "ModifyDefenseModifier") {
|
||||
auto effect = new GameInteractionEffect::ModifyDefenseModifier();
|
||||
auto effect = std::make_unique<GameInteractionEffect::ModifyDefenseModifier>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "GiveOrTakeShield") {
|
||||
auto effect = new GameInteractionEffect::GiveOrTakeShield();
|
||||
auto effect = std::make_unique<GameInteractionEffect::GiveOrTakeShield>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "TeleportPlayer") {
|
||||
auto effect = new GameInteractionEffect::TeleportPlayer();
|
||||
auto effect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "ClearAssignedButtons") {
|
||||
auto effect = new GameInteractionEffect::ClearAssignedButtons();
|
||||
auto effect = std::make_unique<GameInteractionEffect::ClearAssignedButtons>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "SetTimeOfDay") {
|
||||
auto effect = new GameInteractionEffect::SetTimeOfDay();
|
||||
auto effect = std::make_unique<GameInteractionEffect::SetTimeOfDay>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "SetCollisionViewer") {
|
||||
return new GameInteractionEffect::SetCollisionViewer();
|
||||
return std::make_unique<GameInteractionEffect::SetCollisionViewer>();
|
||||
} else if (name == "RandomizeCosmetics") {
|
||||
return new GameInteractionEffect::RandomizeCosmetics();
|
||||
return std::make_unique<GameInteractionEffect::RandomizeCosmetics>();
|
||||
} else if (name == "PressButton") {
|
||||
auto effect = new GameInteractionEffect::PressButton();
|
||||
auto effect = std::make_unique<GameInteractionEffect::PressButton>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "PressRandomButton") {
|
||||
auto effect = new GameInteractionEffect::PressRandomButton();
|
||||
auto effect = std::make_unique<GameInteractionEffect::PressRandomButton>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "AddOrTakeAmmo") {
|
||||
auto effect = new GameInteractionEffect::AddOrTakeAmmo();
|
||||
auto effect = std::make_unique<GameInteractionEffect::AddOrTakeAmmo>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
effect->parameters[1] = payload["parameters"][1].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "RandomBombFuseTimer") {
|
||||
return new GameInteractionEffect::RandomBombFuseTimer();
|
||||
return std::make_unique<GameInteractionEffect::RandomBombFuseTimer>();
|
||||
} else if (name == "DisableLedgeGrabs") {
|
||||
return new GameInteractionEffect::DisableLedgeGrabs();
|
||||
return std::make_unique<GameInteractionEffect::DisableLedgeGrabs>();
|
||||
} else if (name == "RandomWind") {
|
||||
return new GameInteractionEffect::RandomWind();
|
||||
return std::make_unique<GameInteractionEffect::RandomWind>();
|
||||
} else if (name == "RandomBonks") {
|
||||
return new GameInteractionEffect::RandomBonks();
|
||||
return std::make_unique<GameInteractionEffect::RandomBonks>();
|
||||
} else if (name == "PlayerInvincibility") {
|
||||
return new GameInteractionEffect::PlayerInvincibility();
|
||||
return std::make_unique<GameInteractionEffect::PlayerInvincibility>();
|
||||
} else if (name == "SlipperyFloor") {
|
||||
return new GameInteractionEffect::SlipperyFloor();
|
||||
return std::make_unique<GameInteractionEffect::SlipperyFloor>();
|
||||
} else if (name == "SpawnEnemyWithOffset") {
|
||||
auto effect = new GameInteractionEffect::SpawnEnemyWithOffset();
|
||||
auto effect = std::make_unique<GameInteractionEffect::SpawnEnemyWithOffset>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
effect->parameters[1] = payload["parameters"][1].get<int32_t>();
|
||||
}
|
||||
return effect;
|
||||
} else if (name == "SpawnActor") {
|
||||
auto effect = new GameInteractionEffect::SpawnActor();
|
||||
auto effect = std::make_unique<GameInteractionEffect::SpawnActor>();
|
||||
if (payload.contains("parameters")) {
|
||||
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
|
||||
effect->parameters[1] = payload["parameters"][1].get<int32_t>();
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
#define NETWORK_SAIL_H
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "soh/Network/Network.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
|
||||
class Sail : public Network {
|
||||
private:
|
||||
GameInteractionEffectBase* EffectFromJson(nlohmann::json payload);
|
||||
std::unique_ptr<GameInteractionEffectBase> EffectFromJson(nlohmann::json payload);
|
||||
void RegisterHooks();
|
||||
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user