diff --git a/src/backend/looped/self/ptfx.cpp b/src/backend/looped/self/ptfx.cpp index 35b39508..3fb3a8c8 100644 --- a/src/backend/looped/self/ptfx.cpp +++ b/src/backend/looped/self/ptfx.cpp @@ -10,7 +10,7 @@ namespace big { using looped_command::looped_command; - PedBones ptfx_bones[5] = { + PedBones ptfx_ped_bones[5] = { PedBones::SKEL_Head, PedBones::SKEL_L_Hand, PedBones::SKEL_R_Hand, @@ -18,20 +18,40 @@ namespace big PedBones::SKEL_R_Foot }; - void show_ptfx_effect(const char* fx_name, const char* name) + const char* ptfx_vehicle_pos[4] = { + "wheel_lf", + "wheel_lr", + "wheel_rf", + "wheel_rr" + }; + + void show_player_ptfx_effect(const char* fx_name, const char* name) { - for (const auto& ptfx_bone : ptfx_bones) + STREAMING::REQUEST_NAMED_PTFX_ASSET(fx_name); + for (const auto& ptfx_bone : ptfx_ped_bones) { - STREAMING::REQUEST_NAMED_PTFX_ASSET(fx_name); GRAPHICS::USE_PARTICLE_FX_ASSET(fx_name); - GRAPHICS::START_NETWORKED_PARTICLE_FX_NON_LOOPED_ON_PED_BONE(name, self::ped, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.0f, (int)ptfx_bone, g.self.ptfx_effects.size, 1, 1, 1); + GRAPHICS::START_NETWORKED_PARTICLE_FX_NON_LOOPED_ON_PED_BONE(name, self::ped, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, (int)ptfx_bone, g.self.ptfx_effects.size, 1, 1, 1); STREAMING::REMOVE_PTFX_ASSET(); } } + void show_vehicle_ptfx_effect(const char* fx_name, const char* name) + { + for (const auto& ptfx_bone : ptfx_vehicle_pos) + { + GRAPHICS::USE_PARTICLE_FX_ASSET(fx_name); + Vector3 bone_pos = ENTITY::GET_WORLD_POSITION_OF_ENTITY_BONE(self::veh, ENTITY::GET_ENTITY_BONE_INDEX_BY_NAME(self::veh, ptfx_bone)); + GRAPHICS::START_NETWORKED_PARTICLE_FX_NON_LOOPED_AT_COORD(name, bone_pos.x, bone_pos.y, bone_pos.z, 0.f, 0.f, 0.f, g.self.ptfx_effects.size, 0.f, 0.f, 0.f, 0); + } + } + virtual void on_tick() override { - show_ptfx_effect(g.self.ptfx_effects.asset, g.self.ptfx_effects.effect); + if(self::veh == 0) + show_player_ptfx_effect(g.self.ptfx_effects.asset, g.self.ptfx_effects.effect); + else + show_vehicle_ptfx_effect(g.self.ptfx_effects.asset, g.self.ptfx_effects.effect); } }; diff --git a/src/backend/looped/world/blackhole.cpp b/src/backend/looped/world/blackhole.cpp new file mode 100644 index 00000000..a4ca566c --- /dev/null +++ b/src/backend/looped/world/blackhole.cpp @@ -0,0 +1,94 @@ +#include "natives.hpp" +#include "backend/looped_command.hpp" +#include "pointers.hpp" +#include "util/vehicle.hpp" +#include "util/mobile.hpp" +#include "gta_util.hpp" + +namespace big +{ + + class blackhole : looped_command + { + using looped_command::looped_command; + + std::vector target_entities; + + void get_entities() + { + const auto replay_interface = *g_pointers->m_replay_interface; + if(!replay_interface) + return; + + if (g.world.blackhole.include_vehicles) + { + const auto vehicle_interface = replay_interface->m_vehicle_interface; + for (int i = 0; i < vehicle_interface->m_max_vehicles; i++) + { + const auto vehicle_ptr = vehicle_interface->get_vehicle(i); + if (!vehicle_ptr) + continue; + + const auto veh = g_pointers->m_ptr_to_handle(vehicle_ptr); + if (!veh) + break; + + target_entities.push_back(veh); + } + } + + if (g.world.blackhole.include_peds) + { + const auto ped_interface = replay_interface->m_ped_interface; + for (int i = 0; i < ped_interface->m_max_peds; i++) + { + const auto ped_ptr = ped_interface->get_ped(i); + if (!ped_ptr) + continue; + + //make sure to don't include ourselves + if (ped_ptr == gta_util::get_local_ped()) + continue; + + const auto ped = g_pointers->m_ptr_to_handle(ped_ptr); + if (!ped) + break; + + target_entities.push_back(ped); + } + } + } + + virtual void on_tick() override + { + get_entities(); + + for (auto entity : target_entities) + { + auto entity_coord = ENTITY::GET_ENTITY_COORDS(entity, false); + ENTITY::APPLY_FORCE_TO_ENTITY(entity, 1, ((g.world.blackhole.pos.x - entity_coord.x) * 9.f), ((g.world.blackhole.pos.y - entity_coord.y) * 9.f), ((g.world.blackhole.pos.z - entity_coord.z) * 9.f), 0.f, 0.f, 0.f, 0, false, true, true, 0, 0); + } + + //draw blackhole + GRAPHICS::DRAW_MARKER(28, + g.world.blackhole.pos.x, g.world.blackhole.pos.y, g.world.blackhole.pos.z, + 0.f, 0.f, 0.f, 0, 0, 0, 15.f, 15.f, 15.f, + g.world.blackhole.color[0] * 255, + g.world.blackhole.color[1] * 255, + g.world.blackhole.color[2] * 255, + g.world.blackhole.alpha, + 0, 0, 0, 0, 0, 0, 0); + + //cleanup + target_entities.clear(); + } + + //make sure that we always cleanup our memory + virtual void on_disable() override + { + target_entities.clear(); + } + }; + + blackhole g_blackhole("blackhole", "Blackhole", "Spawns a black hole that picks up all the peds and vehicles in your area.", g.world.blackhole.enable); +} \ No newline at end of file diff --git a/src/core/globals.hpp b/src/core/globals.hpp index bc85bdf6..e24122fd 100644 --- a/src/core/globals.hpp +++ b/src/core/globals.hpp @@ -455,7 +455,21 @@ namespace big NLOHMANN_DEFINE_TYPE_INTRUSIVE(custom_time, local_weather, hour, minute, second) } custom_time; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(world, water, spawn_ped, custom_time) + + + struct blackhole + { + bool enable = false; + bool include_peds = false; + bool include_vehicles = false; + float color[3] = { 1, 1, 1 }; + int alpha = 150; + rage::fvector3 pos; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(blackhole, enable, include_peds, include_vehicles, color, alpha) + } blackhole{}; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(world, water, spawn_ped, custom_time, blackhole) } world{}; struct spoofing @@ -502,7 +516,7 @@ namespace big bool enabled = false; bool no_collision = false; bool stop_on_exit = false; - float speed = 1; + float speed = 100; NLOHMANN_DEFINE_TYPE_INTRUSIVE(fly, dont_stop, enabled, no_collision, stop_on_exit, speed) } fly{}; diff --git a/src/services/gui/gui_service.hpp b/src/services/gui/gui_service.hpp index ae632bb1..cc7837d7 100644 --- a/src/services/gui/gui_service.hpp +++ b/src/services/gui/gui_service.hpp @@ -29,6 +29,7 @@ namespace big CREATOR, TRAIN, WATER, + BLACKHOLE, NETWORK, SESSION, @@ -86,6 +87,7 @@ namespace big { tabs::CREATOR, { "Creator", view::creator }}, { tabs::TRAIN, { "Train", view::train }}, { tabs::WATER, { "Water", view::water }}, + { tabs::BLACKHOLE, { "Blackhole", view::blackhole }}, }}}, {tabs::NETWORK, { "Network", nullptr, { { tabs::SPOOFING, { "Spoofing", view::spoofing }}, diff --git a/src/views/view.hpp b/src/views/view.hpp index 22e62d53..281888fc 100644 --- a/src/views/view.hpp +++ b/src/views/view.hpp @@ -54,6 +54,7 @@ namespace big static void creator(); static void train(); static void water(); + static void blackhole(); static void player_info(); static void player_troll(); diff --git a/src/views/world/view_blackhole.cpp b/src/views/world/view_blackhole.cpp new file mode 100644 index 00000000..be86fe68 --- /dev/null +++ b/src/views/world/view_blackhole.cpp @@ -0,0 +1,33 @@ +#include "views/view.hpp" +#include "util/local_player.hpp" + +namespace big +{ + void view::blackhole() + { + components::command_checkbox<"blackhole">(); + + components::sub_title("Entities"); + ImGui::Checkbox("Vehicles", &g.world.blackhole.include_vehicles); + ImGui::SameLine(); + ImGui::Checkbox("Peds", &g.world.blackhole.include_peds); + + components::sub_title("Position"); + ImGui::InputFloat("X", &g.world.blackhole.pos.x, 5.f, 200.f); + ImGui::InputFloat("Y", &g.world.blackhole.pos.y, 5.f, 200.f); + ImGui::InputFloat("Z", &g.world.blackhole.pos.z, 5.f, 200.f); + + components::button("Set to current coords", [] { + const auto player_pos = g_local_player->get_position(); + + g.world.blackhole.pos.x = player_pos->x; + g.world.blackhole.pos.y = player_pos->y; + g.world.blackhole.pos.z = player_pos->z; + }); + + components::sub_title("Customize Hole"); + ImGui::SetNextItemWidth(214); + ImGui::ColorPicker3("Color", g.world.blackhole.color, ImGuiColorEditFlags_NoDragDrop | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHex); + ImGui::SliderInt("Alpha", &g.world.blackhole.alpha, 0, 255); + } +} \ No newline at end of file