774 lines
39 KiB
C++
774 lines
39 KiB
C++
#ifdef ENABLE_REMOTE_CONTROL
|
|
|
|
#include "CrowdControl.h"
|
|
#include "CrowdControlTypes.h"
|
|
#include <libultraship/bridge.h>
|
|
#include <libultraship/libultraship.h>
|
|
#include <nlohmann/json.hpp>
|
|
#include <spdlog/spdlog.h>
|
|
#include <spdlog/fmt/fmt.h>
|
|
#include <regex>
|
|
|
|
extern "C" {
|
|
#include <z64.h>
|
|
#include "variables.h"
|
|
#include "functions.h"
|
|
#include "macros.h"
|
|
extern PlayState* gPlayState;
|
|
}
|
|
|
|
void CrowdControl::Enable() {
|
|
if (isEnabled) {
|
|
return;
|
|
}
|
|
|
|
isEnabled = true;
|
|
GameInteractor::Instance->EnableRemoteInteractor();
|
|
GameInteractor::Instance->RegisterRemoteJsonHandler([&](nlohmann::json payload) {
|
|
HandleRemoteData(payload);
|
|
});
|
|
|
|
ccThreadProcess = std::thread(&CrowdControl::ProcessActiveEffects, this);
|
|
}
|
|
|
|
void CrowdControl::Disable() {
|
|
if (!isEnabled) {
|
|
return;
|
|
}
|
|
|
|
isEnabled = false;
|
|
ccThreadProcess.join();
|
|
GameInteractor::Instance->DisableRemoteInteractor();
|
|
}
|
|
|
|
void CrowdControl::HandleRemoteData(nlohmann::json payload) {
|
|
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);
|
|
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) {
|
|
if (effect != incomingEffect && effect->category == incomingEffect->category && effect->id < incomingEffect->id) {
|
|
isConflictingEffectActive = true;
|
|
EmitMessage(incomingEffect->id, incomingEffect->timeRemaining, EffectResult::Retry);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!isConflictingEffectActive) {
|
|
// Check if effect can be applied, if it can't, let CC know.
|
|
EffectResult result = CrowdControl::CanApplyEffect(incomingEffect);
|
|
if (result == EffectResult::Retry || result == EffectResult::Failure) {
|
|
EmitMessage(incomingEffect->id, incomingEffect->timeRemaining, result);
|
|
return;
|
|
}
|
|
|
|
activeEffectsMutex.lock();
|
|
activeEffects.push_back(incomingEffect);
|
|
activeEffectsMutex.unlock();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CrowdControl::ProcessActiveEffects() {
|
|
while (isEnabled) {
|
|
// We only want to send events when status changes, on start we send Success.
|
|
// If it fails at some point, we send Pause, and when it starts to succeed again we send Success.
|
|
// CC uses this to pause the timer on the overlay.
|
|
activeEffectsMutex.lock();
|
|
auto it = activeEffects.begin();
|
|
|
|
while (it != activeEffects.end()) {
|
|
Effect *effect = *it;
|
|
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));
|
|
delete effect;
|
|
} else {
|
|
// If we have a success after previously being paused, tell CC to resume timer.
|
|
if (effect->isPaused) {
|
|
effect->isPaused = false;
|
|
EmitMessage(effect->id, effect->timeRemaining, EffectResult::Resumed);
|
|
// If not paused before, subtract time from the timer and send a Success event if
|
|
// the result is different from the last time this was ran.
|
|
// Timed events are put on a thread that runs once per second.
|
|
} else {
|
|
effect->timeRemaining -= 1000;
|
|
if (result != effect->lastExecutionResult) {
|
|
effect->lastExecutionResult = result;
|
|
EmitMessage(effect->id, effect->timeRemaining, EffectResult::Success);
|
|
}
|
|
}
|
|
it++;
|
|
}
|
|
} else { // Timed effects only do Success or Retry
|
|
if (!effect->isPaused && effect->timeRemaining > 0) {
|
|
effect->isPaused = true;
|
|
EmitMessage(effect->id, effect->timeRemaining, EffectResult::Paused);
|
|
}
|
|
it++;
|
|
}
|
|
}
|
|
|
|
activeEffectsMutex.unlock();
|
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
}
|
|
|
|
SPDLOG_TRACE("[CrowdControl] Ending Process thread...");
|
|
}
|
|
|
|
void CrowdControl::EmitMessage(uint32_t eventId, long timeRemaining, EffectResult status) {
|
|
nlohmann::json payload;
|
|
|
|
payload["id"] = eventId;
|
|
payload["type"] = 0;
|
|
payload["timeRemaining"] = timeRemaining;
|
|
payload["status"] = status;
|
|
|
|
SPDLOG_INFO("[CrowdControl] Sending payload:\n{}", payload.dump());
|
|
|
|
GameInteractor::Instance->TransmitJsonToRemote(payload);
|
|
}
|
|
|
|
CrowdControl::EffectResult CrowdControl::ExecuteEffect(Effect* effect) {
|
|
GameInteractionEffectQueryResult giResult;
|
|
if (effect->category == kEffectCatSpawnEnemy) {
|
|
giResult = GameInteractor::RawAction::SpawnEnemyWithOffset(effect->spawnParams[0], effect->spawnParams[1]);
|
|
} else if (effect->category == kEffectCatSpawnActor) {
|
|
giResult = GameInteractor::RawAction::SpawnActor(effect->spawnParams[0], effect->spawnParams[1]);
|
|
} else {
|
|
giResult = GameInteractor::ApplyEffect(effect->giEffect);
|
|
}
|
|
|
|
return TranslateGiEnum(giResult);
|
|
}
|
|
|
|
/// Checks if effect can be applied -- should not be used to check for spawn enemy effects.
|
|
CrowdControl::EffectResult CrowdControl::CanApplyEffect(Effect* effect) {
|
|
assert(effect->category != kEffectCatSpawnEnemy || effect->category != kEffectCatSpawnActor);
|
|
GameInteractionEffectQueryResult giResult = GameInteractor::CanApplyEffect(effect->giEffect);
|
|
|
|
return TranslateGiEnum(giResult);
|
|
}
|
|
|
|
CrowdControl::EffectResult CrowdControl::TranslateGiEnum(GameInteractionEffectQueryResult giResult) {
|
|
// Translate GameInteractor result into CC's own enums.
|
|
EffectResult result;
|
|
if (giResult == GameInteractionEffectQueryResult::Possible) {
|
|
result = EffectResult::Success;
|
|
} else if (giResult == GameInteractionEffectQueryResult::TemporarilyNotPossible) {
|
|
result = EffectResult::Retry;
|
|
} else {
|
|
result = EffectResult::Failure;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) {
|
|
if (!dataReceived.contains("id") || !dataReceived.contains("type")) {
|
|
SPDLOG_ERROR("[CrowdControl] Invalid payload received:\n{}", dataReceived);
|
|
return nullptr;
|
|
}
|
|
|
|
SPDLOG_INFO("[CrowdControl] Received payload:\n{}", dataReceived.dump());
|
|
|
|
Effect* effect = new Effect();
|
|
effect->lastExecutionResult = EffectResult::Initiate;
|
|
effect->id = dataReceived["id"];
|
|
auto parameters = dataReceived["parameters"];
|
|
uint32_t receivedParameter = 0;
|
|
auto effectName = dataReceived["code"].get<std::string>();
|
|
|
|
if (parameters.size() > 0) {
|
|
receivedParameter = dataReceived["parameters"][0];
|
|
}
|
|
|
|
// Assign GameInteractionEffect + values to CC effect.
|
|
// Categories are mostly used for checking for conflicting timed effects.
|
|
switch (effectStringToEnum[effectName]) {
|
|
|
|
// Spawn Enemies and Objects
|
|
case kEffectSpawnCuccoStorm:
|
|
effect->spawnParams[0] = ACTOR_EN_NIW;
|
|
effect->category = kEffectCatSpawnActor;
|
|
break;
|
|
case kEffectSpawnLitBomb:
|
|
effect->spawnParams[0] = ACTOR_EN_BOM;
|
|
effect->category = kEffectCatSpawnActor;
|
|
break;
|
|
case kEffectSpawnExplosion:
|
|
effect->spawnParams[0] = ACTOR_EN_BOM;
|
|
effect->spawnParams[1] = 1;
|
|
effect->category = kEffectCatSpawnActor;
|
|
break;
|
|
case kEffectSpawnArwing:
|
|
effect->spawnParams[0] = ACTOR_EN_CLEAR_TAG;
|
|
// Parameter for no cutscene Arwing
|
|
effect->spawnParams[1] = 1;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
case kEffectSpawnDarklink:
|
|
effect->spawnParams[0] = ACTOR_EN_TORCH2;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
case kEffectSpawnIronKnuckle:
|
|
effect->spawnParams[0] = ACTOR_EN_IK;
|
|
// Parameter for black standing Iron Knuckle
|
|
effect->spawnParams[1] = 2;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
case kEffectSpawnStalfos:
|
|
effect->spawnParams[0] = ACTOR_EN_TEST;
|
|
// Parameter for gravity-obeying Stalfos
|
|
effect->spawnParams[1] = 2;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
case kEffectSpawnFreezard:
|
|
effect->spawnParams[0] = ACTOR_EN_FZ;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
case kEffectSpawnLikeLike:
|
|
effect->spawnParams[0] = ACTOR_EN_RR;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
case kEffectSpawnGibdo:
|
|
effect->spawnParams[0] = ACTOR_EN_RD;
|
|
// Parameter for Gibdo
|
|
effect->spawnParams[1] = 32766;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
case kEffectSpawnKeese:
|
|
effect->spawnParams[0] = ACTOR_EN_FIREFLY;
|
|
// Parameter for normal keese
|
|
effect->spawnParams[1] = 2;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
case kEffectSpawnIceKeese:
|
|
effect->spawnParams[0] = ACTOR_EN_FIREFLY;
|
|
// Parameter for ice keese
|
|
effect->spawnParams[1] = 4;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
case kEffectSpawnFireKeese:
|
|
effect->spawnParams[0] = ACTOR_EN_FIREFLY;
|
|
// Parameter for fire keese
|
|
effect->spawnParams[1] = 1;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
case kEffectSpawnWolfos:
|
|
effect->spawnParams[0] = ACTOR_EN_WF;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
case kEffectSpawnWallmaster:
|
|
effect->spawnParams[0] = ACTOR_EN_WALLMAS;
|
|
effect->category = kEffectCatSpawnEnemy;
|
|
break;
|
|
|
|
// Link Modifiers
|
|
case kEffectTakeHalfDamage:
|
|
effect->category = kEffectCatDamageTaken;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ModifyDefenseModifier();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = 2;
|
|
break;
|
|
case kEffectTakeDoubleDamage:
|
|
effect->category = kEffectCatDamageTaken;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ModifyDefenseModifier();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = -2;
|
|
break;
|
|
case kEffectOneHitKo:
|
|
effect->category = kEffectCatDamageTaken;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::OneHitKO();
|
|
break;
|
|
case kEffectInvincibility:
|
|
effect->category = kEffectCatDamageTaken;
|
|
effect->timeRemaining = 15000;
|
|
effect->giEffect = new GameInteractionEffect::PlayerInvincibility();
|
|
break;
|
|
break;
|
|
case kEffectIncreaseSpeed:
|
|
effect->category = kEffectCatSpeed;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = 2;
|
|
break;
|
|
case kEffectDecreaseSpeed:
|
|
effect->category = kEffectCatSpeed;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = -2;
|
|
break;
|
|
case kEffectLowGravity:
|
|
effect->category = kEffectCatGravity;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ModifyGravity();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_GRAVITY_LEVEL_LIGHT;
|
|
break;
|
|
case kEffectHighGravity:
|
|
effect->category = kEffectCatGravity;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ModifyGravity();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_GRAVITY_LEVEL_HEAVY;
|
|
break;
|
|
case kEffectForceIronBoots:
|
|
effect->category = kEffectCatBoots;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ForceEquipBoots();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = EQUIP_VALUE_BOOTS_IRON;
|
|
break;
|
|
case kEffectForceHoverBoots:
|
|
effect->category = kEffectCatBoots;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ForceEquipBoots();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = EQUIP_VALUE_BOOTS_HOVER;
|
|
break;
|
|
case kEffectSlipperyFloor:
|
|
effect->category = kEffectCatSlipperyFloor;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::SlipperyFloor();
|
|
break;
|
|
case kEffectNoLedgeGrabs:
|
|
effect->category = kEffectCatNoLedgeGrabs;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::DisableLedgeGrabs();
|
|
break;
|
|
case kEffectRandomWind:
|
|
effect->category = kEffectCatRandomWind;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::RandomWind();
|
|
break;
|
|
case kEffectRandomBonks:
|
|
effect->category = kEffectCatRandomBonks;
|
|
effect->timeRemaining = 60000;
|
|
effect->giEffect = new GameInteractionEffect::RandomBonks();
|
|
break;
|
|
|
|
// Hurt or Heal Link
|
|
case kEffectEmptyHeart:
|
|
effect->giEffect = new GameInteractionEffect::ModifyHealth();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter * -1;
|
|
break;
|
|
case kEffectFillHeart:
|
|
effect->giEffect = new GameInteractionEffect::ModifyHealth();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter;
|
|
break;
|
|
case kEffectKnockbackLinkWeak:
|
|
effect->giEffect = new GameInteractionEffect::KnockbackPlayer();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = 1;
|
|
break;
|
|
case kEffectKnockbackLinkStrong:
|
|
effect->giEffect = new GameInteractionEffect::KnockbackPlayer();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = 3;
|
|
break;
|
|
case kEffectKnockbackLinkMega:
|
|
effect->giEffect = new GameInteractionEffect::KnockbackPlayer();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = 6;
|
|
break;
|
|
case kEffectBurnLink:
|
|
effect->giEffect = new GameInteractionEffect::BurnPlayer();
|
|
break;
|
|
case kEffectFreezeLink:
|
|
effect->giEffect = new GameInteractionEffect::FreezePlayer();
|
|
break;
|
|
case kEffectElectrocuteLink:
|
|
effect->giEffect = new GameInteractionEffect::ElectrocutePlayer();
|
|
break;
|
|
case kEffectKillLink:
|
|
effect->giEffect = new GameInteractionEffect::SetPlayerHealth();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = 0;
|
|
break;
|
|
|
|
// Give Items and Consumables
|
|
case kEffectAddHeartContainer:
|
|
effect->giEffect = new GameInteractionEffect::ModifyHeartContainers();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = 1;
|
|
break;
|
|
case kEffectFillMagic:
|
|
effect->giEffect = new GameInteractionEffect::FillMagic();
|
|
break;
|
|
case kEffectAddRupees:
|
|
effect->giEffect = new GameInteractionEffect::ModifyRupees();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter;
|
|
break;
|
|
case kEffectGiveDekuShield:
|
|
effect->giEffect = new GameInteractionEffect::GiveOrTakeShield();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = ITEM_SHIELD_DEKU;
|
|
break;
|
|
case kEffectGiveHylianShield:
|
|
effect->giEffect = new GameInteractionEffect::GiveOrTakeShield();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = ITEM_SHIELD_HYLIAN;
|
|
break;
|
|
case kEffectRefillSticks:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_STICK;
|
|
break;
|
|
case kEffectRefillNuts:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_NUT;
|
|
break;
|
|
case kEffectRefillBombs:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_BOMB;
|
|
break;
|
|
case kEffectRefillSeeds:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_SLINGSHOT;
|
|
break;
|
|
case kEffectRefillArrows:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_BOW;
|
|
break;
|
|
case kEffectRefillBombchus:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_BOMBCHU;
|
|
break;
|
|
|
|
// Take Items and Consumables
|
|
case kEffectRemoveHeartContainer:
|
|
effect->giEffect = new GameInteractionEffect::ModifyHeartContainers();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = -1;
|
|
break;
|
|
case kEffectEmptyMagic:
|
|
effect->giEffect = new GameInteractionEffect::EmptyMagic();
|
|
break;
|
|
case kEffectRemoveRupees:
|
|
effect->giEffect = new GameInteractionEffect::ModifyRupees();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter * -1;
|
|
break;
|
|
case kEffectTakeDekuShield:
|
|
effect->giEffect = new GameInteractionEffect::GiveOrTakeShield();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = -ITEM_SHIELD_DEKU;
|
|
break;
|
|
case kEffectTakeHylianShield:
|
|
effect->giEffect = new GameInteractionEffect::GiveOrTakeShield();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = -ITEM_SHIELD_HYLIAN;
|
|
break;
|
|
case kEffectTakeSticks:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter * -1;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_STICK;
|
|
break;
|
|
case kEffectTakeNuts:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter * -1;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_NUT;
|
|
break;
|
|
case kEffectTakeBombs:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter * -1;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_BOMB;
|
|
break;
|
|
case kEffectTakeSeeds:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter * -1;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_SLINGSHOT;
|
|
break;
|
|
case kEffectTakeArrows:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter * -1;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_BOW;
|
|
break;
|
|
case kEffectTakeBombchus:
|
|
effect->giEffect = new GameInteractionEffect::AddOrTakeAmmo();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = receivedParameter * -1;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = ITEM_BOMBCHU;
|
|
break;
|
|
|
|
// Link Size Modifiers
|
|
case kEffectGiantLink:
|
|
effect->category = kEffectCatLinkSize;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ModifyLinkSize();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_LINK_SIZE_GIANT;
|
|
break;
|
|
case kEffectMinishLink:
|
|
effect->category = kEffectCatLinkSize;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ModifyLinkSize();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_LINK_SIZE_MINISH;
|
|
break;
|
|
case kEffectPaperLink:
|
|
effect->category = kEffectCatLinkSize;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ModifyLinkSize();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_LINK_SIZE_PAPER;
|
|
break;
|
|
case kEffectSquishedLink:
|
|
effect->category = kEffectCatLinkSize;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::ModifyLinkSize();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_LINK_SIZE_SQUISHED;
|
|
break;
|
|
case kEffectInvisibleLink:
|
|
effect->category = kEffectCatLinkSize;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::InvisibleLink();
|
|
break;
|
|
|
|
// Generic Effects
|
|
case kEffectRandomBombTimer:
|
|
effect->category = kEffectCatRandomBombFuseTimer;
|
|
effect->timeRemaining = 60000;
|
|
effect->giEffect = new GameInteractionEffect::RandomBombFuseTimer();
|
|
break;
|
|
case kEffectSetTimeToDawn:
|
|
effect->giEffect = new GameInteractionEffect::SetTimeOfDay();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_TIMEOFDAY_DAWN;
|
|
break;
|
|
case kEffectSetTimeToDusk:
|
|
effect->giEffect = new GameInteractionEffect::SetTimeOfDay();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_TIMEOFDAY_DUSK;
|
|
break;
|
|
|
|
// Visual Effects
|
|
case kEffectNoUi:
|
|
effect->category = kEffectCatUi;
|
|
effect->timeRemaining = 60000;
|
|
effect->giEffect = new GameInteractionEffect::NoUI();
|
|
break;
|
|
case kEffectRainstorm:
|
|
effect->category = kEffectCatWeather;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::WeatherRainstorm();
|
|
break;
|
|
case kEffectDebugMode:
|
|
effect->category = kEffectCatDebugMode;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::SetCollisionViewer();
|
|
break;
|
|
case kEffectRandomCosmetics:
|
|
effect->giEffect = new GameInteractionEffect::RandomizeCosmetics();
|
|
break;
|
|
|
|
// Controls
|
|
case kEffectNoZButton:
|
|
effect->category = kEffectCatNoZ;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::DisableZTargeting();
|
|
break;
|
|
case kEffectReverseControls:
|
|
effect->category = kEffectCatReverseControls;
|
|
effect->timeRemaining = 60000;
|
|
effect->giEffect = new GameInteractionEffect::ReverseControls();
|
|
break;
|
|
case kEffectPacifistMode:
|
|
effect->category = kEffectCatPacifist;
|
|
effect->timeRemaining = 15000;
|
|
effect->giEffect = new GameInteractionEffect::PacifistMode();
|
|
break;
|
|
case kEffectPressRandomButtons:
|
|
effect->category = kEffectCatRandomButtons;
|
|
effect->timeRemaining = 30000;
|
|
effect->giEffect = new GameInteractionEffect::PressRandomButton();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = 30;
|
|
break;
|
|
case kEffectClearCbuttons:
|
|
effect->giEffect = new GameInteractionEffect::ClearAssignedButtons();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_BUTTONS_CBUTTONS;
|
|
break;
|
|
case kEffectClearDpad:
|
|
effect->giEffect = new GameInteractionEffect::ClearAssignedButtons();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_BUTTONS_DPAD;
|
|
break;
|
|
|
|
// Teleport Player
|
|
case kEffectTpLinksHouse:
|
|
effect->giEffect = new GameInteractionEffect::TeleportPlayer();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_TP_DEST_LINKSHOUSE;
|
|
break;
|
|
case kEffectTpMinuet:
|
|
effect->giEffect = new GameInteractionEffect::TeleportPlayer();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_TP_DEST_MINUET;
|
|
break;
|
|
case kEffectTpBolero:
|
|
effect->giEffect = new GameInteractionEffect::TeleportPlayer();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_TP_DEST_BOLERO;
|
|
break;
|
|
case kEffectTpSerenade:
|
|
effect->giEffect = new GameInteractionEffect::TeleportPlayer();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_TP_DEST_SERENADE;
|
|
break;
|
|
case kEffectTpRequiem:
|
|
effect->giEffect = new GameInteractionEffect::TeleportPlayer();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_TP_DEST_REQUIEM;
|
|
break;
|
|
case kEffectTpNocturne:
|
|
effect->giEffect = new GameInteractionEffect::TeleportPlayer();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_TP_DEST_NOCTURNE;
|
|
break;
|
|
case kEffectTpPrelude:
|
|
effect->giEffect = new GameInteractionEffect::TeleportPlayer();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_TP_DEST_PRELUDE;
|
|
break;
|
|
|
|
// Tunic Color (Bidding War)
|
|
case kEffectTunicRed:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_RED;
|
|
break;
|
|
case kEffectTunicGreen:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_GREEN;
|
|
break;
|
|
case kEffectTunicBlue:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLUE;
|
|
break;
|
|
case kEffectTunicOrange:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE;
|
|
break;
|
|
case kEffectTunicYellow:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW;
|
|
break;
|
|
case kEffectTunicPurple:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE;
|
|
break;
|
|
case kEffectTunicPink:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PINK;
|
|
break;
|
|
case kEffectTunicBrown:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BROWN;
|
|
break;
|
|
case kEffectTunicBlack:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLACK;
|
|
break;
|
|
|
|
// Navi Color (Bidding War)
|
|
case kEffectNaviRed:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_RED;
|
|
break;
|
|
case kEffectNaviGreen:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_GREEN;
|
|
break;
|
|
case kEffectNaviBlue:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLUE;
|
|
break;
|
|
case kEffectNaviOrange:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE;
|
|
break;
|
|
case kEffectNaviYellow:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW;
|
|
break;
|
|
case kEffectNaviPurple:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE;
|
|
break;
|
|
case kEffectNaviPink:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PINK;
|
|
break;
|
|
case kEffectNaviBrown:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BROWN;
|
|
break;
|
|
case kEffectNaviBlack:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLACK;
|
|
break;
|
|
|
|
// Link's Hair Color (Bidding War)
|
|
case kEffectHairRed:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_RED;
|
|
break;
|
|
case kEffectHairGreen:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_GREEN;
|
|
break;
|
|
case kEffectHairBlue:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLUE;
|
|
break;
|
|
case kEffectHairOrange:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE;
|
|
break;
|
|
case kEffectHairYellow:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW;
|
|
break;
|
|
case kEffectHairPurple:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE;
|
|
break;
|
|
case kEffectHairPink:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PINK;
|
|
break;
|
|
case kEffectHairBrown:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BROWN;
|
|
break;
|
|
case kEffectHairBlack:
|
|
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
|
|
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLACK;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return effect;
|
|
}
|
|
|
|
#endif
|