diff --git a/ChaosMod/Components/EffectDispatchTimer.cpp b/ChaosMod/Components/EffectDispatchTimer.cpp index fe29425e6..7988544c2 100644 --- a/ChaosMod/Components/EffectDispatchTimer.cpp +++ b/ChaosMod/Components/EffectDispatchTimer.cpp @@ -159,6 +159,21 @@ void EffectDispatchTimer::ResetFakeTimerPercentage() m_FakeTimerPercentage = 0.f; } +bool EffectDispatchTimer::IsTimerPaused() const +{ + return m_PauseTimer; +} + +void EffectDispatchTimer::SetTimerPaused(bool pause) +{ + m_PauseTimer = pause; +} + +bool EffectDispatchTimer::IsUsingDistanceBasedDispatch() const +{ + return m_DistanceChaosState.EnableDistanceBasedEffectDispatch; +} + void EffectDispatchTimer::OnRun() { auto curTime = GetTickCount64(); diff --git a/ChaosMod/Components/EffectDispatchTimer.h b/ChaosMod/Components/EffectDispatchTimer.h index 5ab659f11..c45f7b9eb 100644 --- a/ChaosMod/Components/EffectDispatchTimer.h +++ b/ChaosMod/Components/EffectDispatchTimer.h @@ -49,5 +49,10 @@ class EffectDispatchTimer : public Component void SetFakeTimerPercentage(float percentage); void ResetFakeTimerPercentage(); + bool IsTimerPaused() const; + void SetTimerPaused(bool pause); + + bool IsUsingDistanceBasedDispatch() const; + virtual void OnRun() override; }; \ No newline at end of file diff --git a/ChaosMod/Components/EffectDispatcher.cpp b/ChaosMod/Components/EffectDispatcher.cpp index 1ddc6e953..8e1c60efd 100644 --- a/ChaosMod/Components/EffectDispatcher.cpp +++ b/ChaosMod/Components/EffectDispatcher.cpp @@ -345,7 +345,7 @@ void EffectDispatcher::UpdateEffects(int deltaTime) if (!effectSharedData->OverrideEffectName.empty()) { activeEffect.FakeName = effectSharedData->OverrideEffectName; - effectSharedData->OverrideEffectId.clear(); + effectSharedData->OverrideEffectName.clear(); } if (!effectSharedData->OverrideEffectId.empty()) @@ -353,7 +353,7 @@ void EffectDispatcher::UpdateEffects(int deltaTime) if (g_EnabledEffects.contains(effectSharedData->OverrideEffectId)) { auto &fakeEffect = g_EnabledEffects.at(effectSharedData->OverrideEffectId); - activeEffect.FakeName = !fakeEffect.HasCustomName() ? "" : fakeEffect.CustomName; + activeEffect.FakeName = !fakeEffect.HasCustomName() ? fakeEffect.Name : fakeEffect.CustomName; } else { diff --git a/ChaosMod/Effects/db/Player/PlayerBlimpStrats.cpp b/ChaosMod/Effects/db/Player/PlayerBlimpStrats.cpp index a9ec19dc4..b191897d3 100644 --- a/ChaosMod/Effects/db/Player/PlayerBlimpStrats.cpp +++ b/ChaosMod/Effects/db/Player/PlayerBlimpStrats.cpp @@ -6,9 +6,13 @@ #include "Memory/Hooks/ScriptThreadRunHook.h" -static void OnStart() +#include "PlayerBlimpStrats.h" + +void OnStartBlimpStrats(bool bHandleThreadBlock) { - Hooks::EnableScriptThreadBlock(); + if (bHandleThreadBlock) + Hooks::EnableScriptThreadBlock(); + bool cutscenePlaying = IS_CUTSCENE_PLAYING(); Hash blimpHash = "blimp"_hash; @@ -61,10 +65,17 @@ static void OnStart() SET_PED_AS_NO_LONGER_NEEDED(&pedDave); } - Hooks::DisableScriptThreadBlock(); + if (bHandleThreadBlock) + Hooks::DisableScriptThreadBlock(); + SET_VEHICLE_AS_NO_LONGER_NEEDED(&veh); } +static void OnStart() +{ + OnStartBlimpStrats(true); +} + // clang-format off REGISTER_EFFECT(OnStart, nullptr, nullptr, EffectInfo { @@ -72,4 +83,4 @@ REGISTER_EFFECT(OnStart, nullptr, nullptr, EffectInfo .Id = "player_blimp_strats", .EffectGroupType = EffectGroupType::Teleport } -); +); \ No newline at end of file diff --git a/ChaosMod/Effects/db/Player/PlayerBlimpStrats.h b/ChaosMod/Effects/db/Player/PlayerBlimpStrats.h new file mode 100644 index 000000000..d22a3e2f6 --- /dev/null +++ b/ChaosMod/Effects/db/Player/PlayerBlimpStrats.h @@ -0,0 +1,3 @@ +#pragma once + +void OnStartBlimpStrats(bool bHandleThreadBlock); \ No newline at end of file diff --git a/ChaosMod/Effects/db/Player/PlayerRandomStuntJump.cpp b/ChaosMod/Effects/db/Player/PlayerRandomStuntJump.cpp index 5617d413c..60708841e 100644 --- a/ChaosMod/Effects/db/Player/PlayerRandomStuntJump.cpp +++ b/ChaosMod/Effects/db/Player/PlayerRandomStuntJump.cpp @@ -7,6 +7,8 @@ #include "Util/Player.h" #include "Util/Vehicle.h" +#include "PlayerRandomStuntJump.h" + struct Location { Vector3 coordinates; @@ -47,7 +49,7 @@ CHAOS_VAR std::vector allPossibleJumps = { { { -958.207, -2766.583, 13.693 }, 151.829, 45.f } // 30 }; -static void OnStart() +void OnStartMakeRandomStuntJump() { Ped playerPed = PLAYER_PED_ID(); Vehicle veh; @@ -76,7 +78,7 @@ static void OnStart() } // clang-format off -REGISTER_EFFECT(OnStart, nullptr, nullptr, EffectInfo +REGISTER_EFFECT(OnStartMakeRandomStuntJump, nullptr, nullptr, EffectInfo { .Name = "Make Random Stunt Jump", .Id = "player_tp_stunt", diff --git a/ChaosMod/Effects/db/Player/PlayerRandomStuntJump.h b/ChaosMod/Effects/db/Player/PlayerRandomStuntJump.h new file mode 100644 index 000000000..a3e0ca3d1 --- /dev/null +++ b/ChaosMod/Effects/db/Player/PlayerRandomStuntJump.h @@ -0,0 +1,3 @@ +#pragma once + +void OnStartMakeRandomStuntJump(); \ No newline at end of file diff --git a/ChaosMod/Effects/db/Player/PlayerTpController.cpp b/ChaosMod/Effects/db/Player/PlayerTpController.cpp index 08aa8ae25..07942207b 100644 --- a/ChaosMod/Effects/db/Player/PlayerTpController.cpp +++ b/ChaosMod/Effects/db/Player/PlayerTpController.cpp @@ -1,9 +1,15 @@ #include +#include "Components/EffectDispatcher.h" + #include "Memory/Hooks/ScriptThreadRunHook.h" #include "Util/Player.h" +#include "Effects/db/Player/PlayerBlimpStrats.h" +#include "Effects/db/Player/PlayerRandomStuntJump.h" +#include "Effects/db/Player/PlayerTpToRandomStore.h" + static void OnStartLSIA() { TeleportPlayer(-1388.6f, -3111.61f, 13.94f); @@ -85,6 +91,21 @@ REGISTER_EFFECT(OnStartSkyFall, nullptr, nullptr, EffectInfo ); // clang-format on +static bool HasValidWaypointForTp() +{ + if (IS_WAYPOINT_ACTIVE()) + return true; + + for (int i = 0; i < 3; i++) + { + Blip blip = GET_FIRST_BLIP_INFO_ID(i); + if (DOES_BLIP_EXIST(blip)) + return true; + } + + return false; +} + static void OnStartWaypoint() { Vector3 coords; @@ -116,47 +137,63 @@ static void OnStartWaypoint() { float z; if (!playerBlip) - { - z = coords.z; - } + TeleportPlayer(coords.x, coords.y, coords.z); else - { - float groundZ; - bool useGroundZ; - for (int i = 0; i < 100; i++) - { - float testZ = (i * 10.f) - 100.f; - - TeleportPlayer(coords.x, coords.y, testZ); - if (i % 5 == 0) - WAIT(0); + TeleportPlayerFindZ(coords.x, coords.y); + } +} - useGroundZ = GET_GROUND_Z_FOR_3D_COORD(coords.x, coords.y, testZ, &groundZ, false, false); - if (useGroundZ) - break; - } +// clang-format off +REGISTER_EFFECT(OnStartWaypoint, nullptr, nullptr, EffectInfo + { + .Name = "Teleport To Waypoint", + .Id = "player_tptowaypoint" + } +); +// clang-format on - if (useGroundZ) - { - z = groundZ; - } - else +static void OnStartWaypointOpposite() +{ + Vector3 coords; + bool found = false, playerBlip = false; + if (IS_WAYPOINT_ACTIVE()) + { + coords = GET_BLIP_COORDS(GET_FIRST_BLIP_INFO_ID(8)); + found = true; + playerBlip = true; + } + else + { + for (int i = 0; i < 3; i++) + { + Blip blip = GET_FIRST_BLIP_INFO_ID(i); + if (DOES_BLIP_EXIST(blip)) { - Vector3 playerPos = GET_ENTITY_COORDS(playerPed, false); + coords = GET_BLIP_COORDS(blip); + found = true; - z = playerPos.z; + break; } } + } - TeleportPlayer(coords.x, coords.y, z); + Ped playerPed = PLAYER_PED_ID(); + + if (found) + { + Vector3 playerPos = GET_ENTITY_COORDS(playerPed, false); + + coords = coords + coords - playerPos; + + TeleportPlayerFindZ(coords.x, coords.y); } } // clang-format off -REGISTER_EFFECT(OnStartWaypoint, nullptr, nullptr, EffectInfo +REGISTER_EFFECT(OnStartWaypointOpposite, nullptr, nullptr, EffectInfo { - .Name = "Teleport To Waypoint", - .Id = "player_tptowaypoint" + .Name = "Teleport To The Opposite Side Of Waypoint", + .Id = "player_tptowaypointopposite" } ); // clang-format on @@ -193,22 +230,7 @@ static void OnStartRandom() } while (TEST_VERTICAL_PROBE_AGAINST_ALL_WATER(x, y, z, 0, &_)); - float groundZ; - bool useGroundZ; - for (int i = 0; i < 100; i++) - { - float testZ = (i * 10.f) - 100.f; - - TeleportPlayer(x, y, testZ); - if (i % 5 == 0) - WAIT(0); - - useGroundZ = GET_GROUND_Z_FOR_3D_COORD(x, y, testZ, &groundZ, false, false); - if (useGroundZ) - break; - } - - TeleportPlayer(x, y, useGroundZ ? groundZ : z); + TeleportPlayerFindZ(x, y); } // clang-format off @@ -221,7 +243,7 @@ REGISTER_EFFECT(OnStartRandom, nullptr, nullptr, EffectInfo ); // clang-format on -static void OnStartMission() +static std::vector GetAllMissionBlips() { std::vector excludedColors; switch (GET_ENTITY_MODEL(PLAYER_PED_ID())) @@ -256,6 +278,12 @@ static void OnStartMission() nextBlip = GET_NEXT_BLIP_INFO_ID(i); } } + + return validBlips; +} +static void OnStartMission() +{ + std::vector validBlips = GetAllMissionBlips(); if (validBlips.size() >= 1) { Blip randomBlip = validBlips[g_Random.GetRandomInt(0, validBlips.size() - 1)]; @@ -273,37 +301,42 @@ REGISTER_EFFECT(OnStartMission, nullptr, nullptr, EffectInfo ); // clang-format on -struct FakeTeleportInfo -{ - std::string_view type; - Vector3 playerPos; - Vector3 vehiclePos; +static const std::vector fakeTpTypes = { + "tp_lsairport", "tp_mazebanktower", "tp_fortzancudo", "tp_mountchilliad", + "tp_skyfall", "tp_mission", "tp_random", "player_tp_store", + "player_tptowaypoint", "player_blimp_strats", "player_tp_stunt", "player_tptowaypointopposite" }; -CHAOS_VAR const std::vector tpLocations = { - { "tp_lsairport", { -1388.6f, -3111.61f, 13.94f } }, // LSIA - { "tp_mazebanktower", { -75.7f, -818.62f, 326.16f } }, // Maze Tower - { "tp_fortzancudo", { -2360.3f, 3244.83f, 92.9f }, { -2267.89f, 3121.04f, 32.5f } }, // Fort Zancudo - { "tp_mountchilliad", { 501.77f, 5604.85f, 797.91f }, { 503.33f, 5531.91f, 777.45f } }, // Mount Chilliad - { "tp_skyfall", { 935.f, 3800.f, 2300.f } } // Heaven -}; - -static int GetFakeWantedLevel(std::string_view effect) +static bool IsValidFakeTpType(std::string_view type) { - if (effect == "tp_lsairport") - return 3; - else if (effect == "tp_fortzancudo") - return 4; + auto effectIdentifier = EffectIdentifier(std::string(type)); + if (!g_EnabledEffects.contains(effectIdentifier)) + return false; + + if (type == "tp_mission") + return GetAllMissionBlips().size() > 0; + else if (type == "player_tptowaypoint") + return HasValidWaypointForTp(); - return 0; + return true; } -static void OnStartFakeTp() +static Vector3 PerformFakeTeleport(std::string effectId) { - auto selectedLocationInfo = tpLocations.at(g_Random.GetRandomInt(0, tpLocations.size() - 1)); - auto overrideId = selectedLocationInfo.type; + std::string fakeTpType; + + std::vector validTpTypes; + + for (auto &type : fakeTpTypes) + if (IsValidFakeTpType(type)) + validTpTypes.emplace_back(type); + + if (validTpTypes.empty()) + return GET_ENTITY_COORDS(PLAYER_PED_ID(), false); - CurrentEffect::OverrideEffectNameFromId(std::string(overrideId)); + fakeTpType = validTpTypes.at(g_Random.GetRandomInt(0, validTpTypes.size() - 1)); + + CurrentEffect::OverrideEffectNameFromId(fakeTpType); Player player = PLAYER_ID(); Ped playerPed = PLAYER_PED_ID(); @@ -314,27 +347,66 @@ static void OnStartFakeTp() Hooks::EnableScriptThreadBlock(); SET_ENTITY_INVINCIBLE(playerPed, true); - Vector3 destinationPos = selectedLocationInfo.playerPos; if (playerVeh) - { - if (!selectedLocationInfo.vehiclePos.IsDefault()) - destinationPos = selectedLocationInfo.vehiclePos; SET_ENTITY_INVINCIBLE(playerVeh, true); - } - int currentWanted = GET_PLAYER_WANTED_LEVEL(player); - int wanted = GetFakeWantedLevel(selectedLocationInfo.type); - if (wanted == 0 || wanted < currentWanted) - wanted = currentWanted; + int oldWantedLevel = GET_PLAYER_WANTED_LEVEL(player); - SET_PLAYER_WANTED_LEVEL(player, 0, false); - SET_PLAYER_WANTED_LEVEL_NOW(player, false); - SET_MAX_WANTED_LEVEL(0); - SET_FAKE_WANTED_LEVEL(wanted); - TeleportPlayer(destinationPos); + switch (GET_HASH_KEY(fakeTpType.data())) + { + case "tp_lsairport"_hash: + SET_PLAYER_WANTED_LEVEL(player, 3, false); + SET_PLAYER_WANTED_LEVEL_NOW(player, false); + OnStartLSIA(); + break; + case "tp_mazebanktower"_hash: + OnStartMazeTower(); + break; + case "tp_fortzancudo"_hash: + SET_PLAYER_WANTED_LEVEL(player, 4, false); + SET_PLAYER_WANTED_LEVEL_NOW(player, false); + OnStartFortZancudo(); + break; + case "tp_mountchilliad"_hash: + OnStartMountChilliad(); + break; + case "tp_skyfall"_hash: + OnStartSkyFall(); + break; + case "tp_mission"_hash: + OnStartMission(); + break; + case "tp_random"_hash: + OnStartRandom(); + break; + case "player_tp_store"_hash: + OnStartTpRandomStore(); + break; + case "player_tptowaypoint"_hash: + OnStartWaypoint(); + break; + case "player_blimp_strats"_hash: + OnStartBlimpStrats(false); + break; + case "player_tp_stunt"_hash: + OnStartMakeRandomStuntJump(); + + // Wait for stunt jump to start + WAIT(1000); + + while (IS_STUNT_JUMP_IN_PROGRESS()) + WAIT(0); + + break; + case 11: // player_tptowaypointopposite + OnStartWaypointOpposite(); + break; + } WAIT(g_Random.GetRandomInt(3500, 6000)); + Vector3 destinationCoords = GET_ENTITY_COORDS(playerPed, false); + TeleportPlayer(playerPos); WAIT(0); @@ -343,10 +415,17 @@ static void OnStartFakeTp() if (playerVeh) SET_ENTITY_INVINCIBLE(playerVeh, false); - SET_FAKE_WANTED_LEVEL(0); - SET_MAX_WANTED_LEVEL(5); - SET_PLAYER_WANTED_LEVEL(player, currentWanted, false); - SET_PLAYER_WANTED_LEVEL_NOW(player, false); + SET_PLAYER_WANTED_LEVEL(player, oldWantedLevel, false); + SET_PLAYER_WANTED_LEVEL_NOW(player, 0); + + return destinationCoords; +} + +static void OnStartFakeTp() +{ + Hooks::EnableScriptThreadBlock(); + + PerformFakeTeleport("tp_fake"); Hooks::DisableScriptThreadBlock(); } @@ -363,53 +442,9 @@ REGISTER_EFFECT(OnStartFakeTp, nullptr, nullptr, EffectInfo static void OnStartFakeFakeTp() { - auto selectedLocationInfo = tpLocations.at(g_Random.GetRandomInt(0, tpLocations.size() - 1)); - auto overrideId = selectedLocationInfo.type; - - CurrentEffect::OverrideEffectNameFromId(std::string(overrideId)); - - Player player = PLAYER_ID(); - Ped playerPed = PLAYER_PED_ID(); - Vehicle playerVeh = IS_PED_IN_ANY_VEHICLE(playerPed, false) ? GET_VEHICLE_PED_IS_IN(playerPed, false) : 0; - - Vector3 playerPos = GET_ENTITY_COORDS(playerPed, false); - Hooks::EnableScriptThreadBlock(); - SET_ENTITY_INVINCIBLE(playerPed, true); - Vector3 destinationPos = selectedLocationInfo.playerPos; - if (playerVeh) - { - if (!selectedLocationInfo.vehiclePos.IsDefault()) - destinationPos = selectedLocationInfo.vehiclePos; - SET_ENTITY_INVINCIBLE(playerVeh, true); - } - - int currentWanted = GET_PLAYER_WANTED_LEVEL(player); - int wanted = GetFakeWantedLevel(selectedLocationInfo.type); - if (wanted == 0 || wanted < currentWanted) - wanted = currentWanted; - - SET_PLAYER_WANTED_LEVEL(player, 0, false); - SET_PLAYER_WANTED_LEVEL_NOW(player, false); - SET_MAX_WANTED_LEVEL(0); - SET_FAKE_WANTED_LEVEL(wanted); - TeleportPlayer(destinationPos); - - WAIT(g_Random.GetRandomInt(3500, 6000)); - - TeleportPlayer(playerPos); - - WAIT(0); - - SET_ENTITY_INVINCIBLE(playerPed, false); - if (playerVeh) - SET_ENTITY_INVINCIBLE(playerVeh, false); - - SET_FAKE_WANTED_LEVEL(0); - SET_MAX_WANTED_LEVEL(5); - SET_PLAYER_WANTED_LEVEL(player, currentWanted, false); - SET_PLAYER_WANTED_LEVEL_NOW(player, false); + Vector3 destinationPos = PerformFakeTeleport("tp_fakex2"); CurrentEffect::OverrideEffectNameFromId("tp_fake"); @@ -427,4 +462,4 @@ REGISTER_EFFECT(OnStartFakeFakeTp, nullptr, nullptr, EffectInfo .Id = "tp_fakex2", .HideRealNameOnStart = true } -); +); \ No newline at end of file diff --git a/ChaosMod/Effects/db/Player/PlayerTpToRandomStore.cpp b/ChaosMod/Effects/db/Player/PlayerTpToRandomStore.cpp index 55e887efa..fa7391127 100644 --- a/ChaosMod/Effects/db/Player/PlayerTpToRandomStore.cpp +++ b/ChaosMod/Effects/db/Player/PlayerTpToRandomStore.cpp @@ -6,6 +6,8 @@ #include "Util/Player.h" +#include "PlayerTpToRandomStore.h" + CHAOS_VAR std::vector allPossibleStores = { // Convenience Stores { 372.29217529297f, 326.39370727539f, 103.56636047363f }, // 247 Clinton @@ -58,16 +60,16 @@ CHAOS_VAR std::vector allPossibleStores = { }; -static void OnStart() +void OnStartTpRandomStore() { TeleportPlayer(allPossibleStores.at(g_Random.GetRandomInt(0, allPossibleStores.size() - 1))); } // clang-format off -REGISTER_EFFECT(OnStart, nullptr, nullptr, EffectInfo +REGISTER_EFFECT(OnStartTpRandomStore, nullptr, nullptr, EffectInfo { .Name = "Teleport to Random Store", .Id = "player_tp_store", .EffectGroupType = EffectGroupType::Teleport } -); +); \ No newline at end of file diff --git a/ChaosMod/Effects/db/Player/PlayerTpToRandomStore.h b/ChaosMod/Effects/db/Player/PlayerTpToRandomStore.h new file mode 100644 index 000000000..7249c11f7 --- /dev/null +++ b/ChaosMod/Effects/db/Player/PlayerTpToRandomStore.h @@ -0,0 +1,3 @@ +#pragma once + +void OnStartTpRandomStore(); \ No newline at end of file diff --git a/ChaosMod/Util/Player.h b/ChaosMod/Util/Player.h index bcc538b3f..3d2ac8e95 100644 --- a/ChaosMod/Util/Player.h +++ b/ChaosMod/Util/Player.h @@ -1,6 +1,7 @@ #pragma once #include "Natives.h" +#include "Components/EffectDispatchTimer.h" inline void TeleportPlayer(float x, float y, float z, bool noOffset = false) { @@ -37,3 +38,34 @@ inline void TeleportPlayer(const Vector3 &coords, bool noOffset = false) { TeleportPlayer(coords.x, coords.y, coords.z, noOffset); } + +inline void TeleportPlayerFindZ(float x, float y) +{ + bool shouldPause = ComponentExists() + && GetComponent()->IsUsingDistanceBasedDispatch() + && !GetComponent()->IsTimerPaused(); + + if (shouldPause) + GetComponent()->SetTimerPaused(true); + + float groundZ; + bool useGroundZ; + for (int i = 0; i < 100; i++) + { + float testZ = (i * 10.f) - 100.f; + + TeleportPlayer(x, y, testZ); + if (i % 5 == 0) + WAIT(0); + + useGroundZ = GET_GROUND_Z_FOR_3D_COORD(x, y, testZ, &groundZ, false, false); + if (useGroundZ) + break; + } + + if (shouldPause) + GetComponent()->SetTimerPaused(false); + + if (useGroundZ) + TeleportPlayer(x, y, groundZ); +} \ No newline at end of file