diff --git a/ChaosMod/Components/EffectDispatchTimer.cpp b/ChaosMod/Components/EffectDispatchTimer.cpp index 2ad15a9a6..1ca8e5a67 100644 --- a/ChaosMod/Components/EffectDispatchTimer.cpp +++ b/ChaosMod/Components/EffectDispatchTimer.cpp @@ -26,9 +26,13 @@ void EffectDispatchTimer::UpdateTimer(int deltaTime) if (!m_EnableTimer || (ComponentExists() && GetComponent()->DisableChaos)) return; + int effectSpawnTime = ComponentExists() && GetComponent()->TimeToDispatchEffect > 0 + ? GetComponent()->TimeToDispatchEffect + : m_EffectSpawnTime; + m_TimerPercentage += deltaTime * (!ComponentExists() ? 1.f : GetComponent()->TimerSpeedModifier) - / m_EffectSpawnTime / 1000.f; + / effectSpawnTime / 1000.f; if (m_TimerPercentage >= 1.f && m_DispatchEffectsOnTimer && ComponentExists()) { @@ -66,14 +70,22 @@ void EffectDispatchTimer::UpdateTravelledDistance() return; } + int effectSpawnDistance = + ComponentExists() && GetComponent()->DistanceToDispatchEffect > 0 + ? GetComponent()->DistanceToDispatchEffect + : m_DistanceChaosState.DistanceToActivateEffect; + auto distance = GET_DISTANCE_BETWEEN_COORDS(position.x, position.y, position.z, m_DistanceChaosState.SavedPosition.x, m_DistanceChaosState.SavedPosition.y, m_DistanceChaosState.SavedPosition.z, true); if (m_DistanceChaosState.DistanceType == DistanceChaosState::TravelledDistanceType::Displacement) { - if (distance * (ComponentExists() ? GetComponent()->TimerSpeedModifier : 1.f) - >= m_DistanceChaosState.DistanceToActivateEffect) + m_TimerPercentage = + (distance * (ComponentExists() ? GetComponent()->TimerSpeedModifier : 1.f)) + / effectSpawnDistance; + + if (m_TimerPercentage >= 1.f) { if (m_DispatchEffectsOnTimer && ComponentExists()) { @@ -86,17 +98,13 @@ void EffectDispatchTimer::UpdateTravelledDistance() m_DistanceChaosState.SavedPosition = position; } - - m_TimerPercentage = - (distance * (ComponentExists() ? GetComponent()->TimerSpeedModifier : 1.f)) - / m_DistanceChaosState.DistanceToActivateEffect; } else if (m_DistanceChaosState.DistanceType == DistanceChaosState::TravelledDistanceType::Distance) { m_DistanceChaosState.SavedPosition = position; m_TimerPercentage += (distance * (ComponentExists() ? GetComponent()->TimerSpeedModifier : 1.f)) - / m_DistanceChaosState.DistanceToActivateEffect; + / effectSpawnDistance; if (m_TimerPercentage >= 1.f && m_DispatchEffectsOnTimer && ComponentExists()) { @@ -121,6 +129,21 @@ void EffectDispatchTimer::SetTimerEnabled(bool state) m_EnableTimer = state; } +int EffectDispatchTimer::GetDefaultEffectSpawnTime() const +{ + return m_EffectSpawnTime; +} + +int EffectDispatchTimer::GetDefaultEffectSpawnDistance() const +{ + return m_DistanceChaosState.DistanceToActivateEffect; +} + +void EffectDispatchTimer::ResetSavedPosition() +{ + m_DistanceChaosState.SavedPosition = GET_ENTITY_COORDS(PLAYER_PED_ID(), false); +} + std::uint64_t EffectDispatchTimer::GetTimer() const { return m_Timer; @@ -204,10 +227,24 @@ void EffectDispatchTimer::OnRun() if (!m_PauseTimer) { - if (m_DistanceChaosState.EnableDistanceBasedEffectDispatch) - UpdateTravelledDistance(); - else + const TimerMode modeOverride = + ComponentExists() ? GetComponent()->TimerModeOverride : TimerMode::None; + + switch (modeOverride) + { + case TimerMode::Time: UpdateTimer(deltaTime); + break; + case TimerMode::Distance: + UpdateTravelledDistance(); + break; + default: + if (m_DistanceChaosState.EnableDistanceBasedEffectDispatch) + UpdateTravelledDistance(); + else + UpdateTimer(deltaTime); + break; + } } m_Timer = curTime; diff --git a/ChaosMod/Components/EffectDispatchTimer.h b/ChaosMod/Components/EffectDispatchTimer.h index c45f7b9eb..9cf4c26b6 100644 --- a/ChaosMod/Components/EffectDispatchTimer.h +++ b/ChaosMod/Components/EffectDispatchTimer.h @@ -38,6 +38,11 @@ class EffectDispatchTimer : public Component bool IsTimerEnabled() const; void SetTimerEnabled(bool state); + int GetDefaultEffectSpawnTime() const; + int GetDefaultEffectSpawnDistance() const; + + void ResetSavedPosition(); + std::uint64_t GetTimer() const; void ResetTimer(); diff --git a/ChaosMod/Components/LuaScripts.cpp b/ChaosMod/Components/LuaScripts.cpp index c765a534f..52c1ecadd 100644 --- a/ChaosMod/Components/LuaScripts.cpp +++ b/ChaosMod/Components/LuaScripts.cpp @@ -555,6 +555,11 @@ void LuaScripts::SetupGlobalState() "Integer", LuaNativeReturnType::Int, "String", LuaNativeReturnType::String, "Float", LuaNativeReturnType::Float, "Vector3", LuaNativeReturnType::Vector3); + m_GlobalState.new_enum("TimerMode", "None", TimerMode::None, "Time", TimerMode::Time, "Distance", TimerMode::Distance); + + m_GlobalState.new_enum("VotingMode", "None", VotingMode::None, "Majority", VotingMode::Majority, "Percentage", + VotingMode::Percentage, "Antimajority", VotingMode::Antimajority); + if (ComponentExists()) { auto getMetaModFactory = [](T &modifier) @@ -580,7 +585,9 @@ void LuaScripts::SetupGlobalState() auto metaModifiersMetaTable = m_GlobalState.create_table_with( "EffectDurationModifier", P(EffectDurationModifier), "TimerSpeedModifier", P(TimerSpeedModifier), "AdditionalEffectsToDispatch", P(AdditionalEffectsToDispatch), "HideChaosUI", P(HideChaosUI), - "DisableChaos", P(DisableChaos), "FlipChaosUI", P(FlipChaosUI)); + "DisableChaos", P(DisableChaos), "FlipChaosUI", P(FlipChaosUI), "VotingModeOverride", P(VotingModeOverride), + "TimerModeOverride", P(TimerModeOverride), "TimeToDispatchEffect", P(TimeToDispatchEffect), + "DistanceToDispatchEffect", P(DistanceToDispatchEffect)); #undef P metaModifiersMetaTable[sol::meta_function::new_index] = [] {}; metaModifiersMetaTable[sol::meta_function::index] = metaModifiersMetaTable; diff --git a/ChaosMod/Components/MetaModifiers.h b/ChaosMod/Components/MetaModifiers.h index 5bbe4d08a..183110e19 100644 --- a/ChaosMod/Components/MetaModifiers.h +++ b/ChaosMod/Components/MetaModifiers.h @@ -2,6 +2,7 @@ #include "Components/Component.h" #include "Util/VotingMode.h" +#include "Util/TimerMode.h" #include @@ -15,4 +16,7 @@ class MetaModifiers : public Component bool DisableChaos = false; bool FlipChaosUI = false; VotingMode VotingModeOverride = VotingMode::None; + TimerMode TimerModeOverride = TimerMode::None; + int TimeToDispatchEffect = 0; + int DistanceToDispatchEffect = 0; }; \ No newline at end of file diff --git a/ChaosMod/Effects/Condition/ConditionUsingDistanceTimer.cpp b/ChaosMod/Effects/Condition/ConditionUsingDistanceTimer.cpp new file mode 100644 index 000000000..5d2e2c2d6 --- /dev/null +++ b/ChaosMod/Effects/Condition/ConditionUsingDistanceTimer.cpp @@ -0,0 +1,11 @@ +#include + +#include "Components/EffectDispatchTimer.h" +#include "Effects/Condition/EffectCondition.h" + +static bool OnCondition() +{ + return ComponentExists() && GetComponent()->IsUsingDistanceBasedDispatch(); +} + +REGISTER_EFFECT_CONDITION(EffectConditionType::UsingDistanceTimer, OnCondition); \ No newline at end of file diff --git a/ChaosMod/Effects/Condition/ConditionUsingTimeTimer.cpp b/ChaosMod/Effects/Condition/ConditionUsingTimeTimer.cpp new file mode 100644 index 000000000..938deb88e --- /dev/null +++ b/ChaosMod/Effects/Condition/ConditionUsingTimeTimer.cpp @@ -0,0 +1,11 @@ +#include + +#include "Components/EffectDispatchTimer.h" +#include "Effects/Condition/EffectCondition.h" + +static bool OnCondition() +{ + return ComponentExists() && !GetComponent()->IsUsingDistanceBasedDispatch(); +} + +REGISTER_EFFECT_CONDITION(EffectConditionType::UsingTimeTimer, OnCondition); \ No newline at end of file diff --git a/ChaosMod/Effects/Condition/EffectCondition.h b/ChaosMod/Effects/Condition/EffectCondition.h index a0e14ac79..41e95c6e7 100644 --- a/ChaosMod/Effects/Condition/EffectCondition.h +++ b/ChaosMod/Effects/Condition/EffectCondition.h @@ -7,7 +7,9 @@ enum class EffectConditionType { None, VotingEnabled, // Voting is enabled - ProportionalVotingEnabled + ProportionalVotingEnabled, + UsingDistanceTimer, + UsingTimeTimer, }; #define REGISTER_EFFECT_CONDITION(conditionType, condition) \ diff --git a/ChaosMod/Effects/db/Meta/MetaTimerMode.cpp b/ChaosMod/Effects/db/Meta/MetaTimerMode.cpp new file mode 100644 index 000000000..29100ecf4 --- /dev/null +++ b/ChaosMod/Effects/db/Meta/MetaTimerMode.cpp @@ -0,0 +1,77 @@ +/* + Effects by Regynate +*/ + +#include + +#include "Components/MetaModifiers.h" +#include "Effects/Register/RegisterEffect.h" +#include + +static void OnStop() +{ + if (!ComponentExists()) + return; + + GetComponent()->TimerModeOverride = TimerMode::None; + GetComponent()->DistanceToDispatchEffect = 0; + GetComponent()->TimeToDispatchEffect = 0; + if (ComponentExists()) + GetComponent()->ResetSavedPosition(); +} + +static void OnTick_Time() +{ + if (!ComponentExists()) + return; + + GetComponent()->TimerModeOverride = TimerMode::Time; + + int defaultDistance = ComponentExists() + ? GetComponent()->GetDefaultEffectSpawnDistance() + : 0; + GetComponent()->TimeToDispatchEffect = defaultDistance ? defaultDistance / 10 : 30; +} + +// clang-format off +REGISTER_EFFECT(nullptr, OnStop, OnTick_Time, + { + .Name = "Time Based Timer", + .Id = "meta_timer_timebased", + .IsTimed = true, + .IncompatibleWith = { "meta_timer_distancebased" }, + .ExecutionType = EffectExecutionType::Meta, + .ConditionType = EffectConditionType::UsingDistanceTimer + } +); +// clang-format on + +static void OnTick_Distance() +{ + if (!ComponentExists()) + return; + + GetComponent()->TimerModeOverride = TimerMode::Distance; + int defaultTime = + ComponentExists() ? GetComponent()->GetDefaultEffectSpawnTime() : 0; + GetComponent()->DistanceToDispatchEffect = defaultTime ? defaultTime * 10 : 300; +} + +static void OnStart_Distance() +{ + if (ComponentExists()) + GetComponent()->ResetSavedPosition(); +} + +// clang-format off +REGISTER_EFFECT(OnStart_Distance, OnStop, OnTick_Distance, + { + .Name = "Distance Based Timer", + .Id = "meta_timer_distancebased", + .IsTimed = true, + .IncompatibleWith = { "meta_timer_timebased" }, + .ExecutionType = EffectExecutionType::Meta, + .ConditionType = EffectConditionType::UsingTimeTimer + } +); +// clang-format on \ No newline at end of file diff --git a/ChaosMod/Util/TimerMode.h b/ChaosMod/Util/TimerMode.h new file mode 100644 index 000000000..d977740c8 --- /dev/null +++ b/ChaosMod/Util/TimerMode.h @@ -0,0 +1,6 @@ +enum class TimerMode +{ + None, + Time, + Distance +}; \ No newline at end of file diff --git a/ConfigApp/Effects.cs b/ConfigApp/Effects.cs index bcda27b30..f481c9a5d 100644 --- a/ConfigApp/Effects.cs +++ b/ConfigApp/Effects.cs @@ -416,6 +416,8 @@ public enum EffectTimedType { "player_tptowaypointopposite", new EffectInfo("Teleport To The Opposite Side Of Waypoint", EffectCategory.Player) }, { "meta_votingmode_majority", new EffectInfo("Majority Voting", EffectCategory.Meta, true) }, { "meta_votingmode_antimajority", new EffectInfo("Minority Voting", EffectCategory.Meta, true) }, + { "meta_timer_distancebased", new EffectInfo("Distance Based Timer", EffectCategory.Meta, true) }, + { "meta_timer_timebased", new EffectInfo("Time Based Timer", EffectCategory.Meta, true) }, }; } }