New Flying feature (#2206)
* Remove ultra trash feature * Added extra raycast * refactor(OptionsModal): Support translations * feat(Components): added input float * feat(SuperHeroFly): converted code to commands and move strings to translations --------- Co-authored-by: Yimura <24669514+Yimura@users.noreply.github.com>
This commit is contained in:
parent
590fb4af9f
commit
ab5c484948
411
src/backend/looped/self/super_hero_fly.cpp
Normal file
411
src/backend/looped/self/super_hero_fly.cpp
Normal file
@ -0,0 +1,411 @@
|
||||
#include "backend/looped_command.hpp"
|
||||
#include "backend/bool_command.hpp"
|
||||
#include "backend/float_command.hpp"
|
||||
#include "gta/enums.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "util/entity.hpp"
|
||||
#include "util/math.hpp"
|
||||
#include "util/notify.hpp"
|
||||
#include "util/ped.hpp"
|
||||
#include "util/vehicle.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
class super_hero_fly : looped_command
|
||||
{
|
||||
using looped_command::looped_command;
|
||||
|
||||
bool m_flying = false;
|
||||
bool m_landing = false;
|
||||
bool m_launching = false;
|
||||
bool m_anims_are_playing = false;
|
||||
|
||||
bool m_timer = false;
|
||||
std::chrono::system_clock::time_point m_time_stamp;
|
||||
std::chrono::milliseconds m_duration;
|
||||
|
||||
bool m_charging = false;
|
||||
double m_charge_intensity = 1;
|
||||
int m_charge_ptfx = 0;
|
||||
float m_explosion_intensity = 0;
|
||||
|
||||
Vehicle m_veh_handle{};
|
||||
Vector3 m_land_coords{};
|
||||
Vector3 m_fly_motion{};
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_flying = false;
|
||||
m_landing = false;
|
||||
m_launching = false;
|
||||
m_timer = false;
|
||||
m_charging = false;
|
||||
m_charge_intensity = 0;
|
||||
m_charge_ptfx = 0;
|
||||
m_explosion_intensity = 0;
|
||||
TASK::CLEAR_PED_TASKS(self::ped);
|
||||
m_time_stamp = std::chrono::system_clock::now();
|
||||
PED::SET_PED_CAN_RAGDOLL(self::ped, true);
|
||||
detach_delete_vehicle();
|
||||
if (STREAMING::HAS_NAMED_PTFX_ASSET_LOADED("scr_rcbarry1"))
|
||||
STREAMING::REMOVE_NAMED_PTFX_ASSET("scr_rcbarry1");
|
||||
}
|
||||
|
||||
void apply_fly_animations(bool apply_lower_body, bool apply_uppder_body)
|
||||
{
|
||||
//A mix of two animations with their flags specifically tailored to mimic a sort of superman stance
|
||||
|
||||
if (apply_lower_body)
|
||||
ped::ped_play_animation(self::ped, "skydive@parachute@first_person", "chute_idle_alt_lookright", 4, 1, -1, 1 | 1048576);
|
||||
|
||||
if (apply_uppder_body)
|
||||
ped::ped_play_animation(self::ped, "missfam5_yoga", "c8_to_start", 4, 1, -1, 2 | 16 | 32 | 131072 | 1048576);
|
||||
}
|
||||
|
||||
void apply_explosion()
|
||||
{
|
||||
if (g.self.super_hero_fly.explosions)
|
||||
FIRE::ADD_EXPLOSION(self::pos.x, self::pos.y, self::pos.z, eExplosionTag::TANKSHELL, 0, true, true, 1, true);
|
||||
}
|
||||
|
||||
void detach_delete_vehicle()
|
||||
{
|
||||
ENTITY::DETACH_ENTITY(m_veh_handle, false, false);
|
||||
ENTITY::DETACH_ENTITY(self::ped, true, true);
|
||||
ENTITY::SET_ENTITY_COLLISION(m_veh_handle, false, false);
|
||||
script::get_current()->yield(50ms);
|
||||
|
||||
if (ENTITY::DOES_ENTITY_EXIST(m_veh_handle))
|
||||
{
|
||||
if (entity::take_control_of(m_veh_handle))
|
||||
{
|
||||
ENTITY::DETACH_ENTITY(m_veh_handle, false, false);
|
||||
|
||||
entity::delete_entity(m_veh_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create_psuedo_vehicle()
|
||||
{
|
||||
detach_delete_vehicle();
|
||||
m_veh_handle = vehicle::spawn(0xEEF345EC, ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.0, 0.0, 5.f), ENTITY::GET_ENTITY_HEADING(self::ped), true, false);
|
||||
VEHICLE::SET_VEHICLE_GRAVITY(m_veh_handle, false);
|
||||
ENTITY::SET_ENTITY_INVINCIBLE(m_veh_handle, true);
|
||||
ENTITY::SET_ENTITY_VISIBLE(m_veh_handle, false, 0);
|
||||
}
|
||||
|
||||
void attach_to_psuedo_vehicle()
|
||||
{
|
||||
if (ENTITY::DOES_ENTITY_EXIST(m_veh_handle))
|
||||
{
|
||||
ENTITY::ATTACH_ENTITY_TO_ENTITY(self::ped, m_veh_handle, 0, 0, 0, 0, 0, 0, 0, true, false, false, false, 0, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
void gravitate(Entity ent, Vector3 coord, float speed)
|
||||
{
|
||||
ENTITY::SET_ENTITY_VELOCITY(ent,
|
||||
(coord.x - self::pos.x) * speed,
|
||||
(coord.y - self::pos.y) * speed,
|
||||
(coord.z - self::pos.z) * speed);
|
||||
}
|
||||
|
||||
/*
|
||||
This method is called in conjunction with a pressed key, so it can be considered a loop.
|
||||
Consider all its content to have a lifetime similar to a while loop.
|
||||
*/
|
||||
void charge_launch()
|
||||
{
|
||||
if (ENTITY::IS_ENTITY_IN_AIR(self::ped) || ENTITY::GET_ENTITY_HEIGHT_ABOVE_GROUND(self::ped) > 5 || m_duration.count() < 0.2)
|
||||
return;
|
||||
|
||||
if (!ENTITY::IS_ENTITY_PLAYING_ANIM(self::ped, "anim@amb@inspect@crouch@male_a@base", "base", 3))
|
||||
ped::ped_play_animation(self::ped, "anim@amb@inspect@crouch@male_a@base", "base", 4, 1, -1, 1 | 131072 | 262144 | 1048576 | 33554432);
|
||||
|
||||
m_charge_intensity = m_duration.count();
|
||||
|
||||
if (m_charge_intensity > 5)
|
||||
m_charge_intensity = 5;
|
||||
if (m_explosion_intensity > 10)
|
||||
m_explosion_intensity = 10;
|
||||
|
||||
if (g.self.super_hero_fly.ptfx && m_charge_intensity > 0.4)
|
||||
{
|
||||
STREAMING::REQUEST_NAMED_PTFX_ASSET("scr_rcbarry1");
|
||||
GRAPHICS::USE_PARTICLE_FX_ASSET("scr_rcbarry1");
|
||||
m_charge_ptfx = GRAPHICS::START_NETWORKED_PARTICLE_FX_NON_LOOPED_AT_COORD("scr_alien_disintegrate",
|
||||
self::pos.x,
|
||||
self::pos.y,
|
||||
self::pos.z - 1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
m_charge_intensity / 10,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
|
||||
if ((((int)(std::round(m_charge_intensity * 10)) % 5)) == 1)
|
||||
{
|
||||
for (int i = 0; i < m_explosion_intensity; i++)
|
||||
{
|
||||
FIRE::ADD_EXPLOSION(self::pos.x, self::pos.y, self::pos.z + i, eExplosionTag::EXP_TAG_TORPEDO_UNDERWATER, 0, true, true, m_charge_intensity / 10, true);
|
||||
}
|
||||
m_explosion_intensity += 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
m_charging = true;
|
||||
}
|
||||
|
||||
/*
|
||||
Unlike the method name, this method is responsible for both initiating the flight and landing once in air.
|
||||
*/
|
||||
void launch()
|
||||
{
|
||||
if (!m_flying)
|
||||
{
|
||||
m_launching = true;
|
||||
m_landing = false;
|
||||
m_fly_motion = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.0, 0.0, 5.f);
|
||||
TASK::CLEAR_PED_TASKS_IMMEDIATELY(self::ped);
|
||||
|
||||
apply_fly_animations(true, true);
|
||||
|
||||
//Avoid gravity related game mechanics to interupt any of our operations
|
||||
ENTITY::SET_ENTITY_VELOCITY(self::ped, 0, 0, 1);
|
||||
//Since flight is tightly connected to the animations, flying is only true if and when the animations are playing.
|
||||
m_flying = true;
|
||||
|
||||
create_psuedo_vehicle();
|
||||
attach_to_psuedo_vehicle();
|
||||
|
||||
//Special effect if player is on ground
|
||||
if (!ENTITY::IS_ENTITY_IN_AIR(m_veh_handle) && ENTITY::GET_ENTITY_HEIGHT_ABOVE_GROUND(m_veh_handle) < 10)
|
||||
{
|
||||
m_fly_motion = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped,
|
||||
0.0,
|
||||
0.0,
|
||||
g.self.super_hero_fly.charge ? m_charge_intensity * 50 : g.self.super_hero_fly.initial_launch);
|
||||
|
||||
apply_explosion();
|
||||
}
|
||||
|
||||
m_charge_intensity = 0;
|
||||
m_timer = false;
|
||||
GRAPHICS::STOP_PARTICLE_FX_LOOPED(m_charge_ptfx, false);
|
||||
STREAMING::REMOVE_NAMED_PTFX_ASSET("scr_rcbarry1");
|
||||
m_charge_ptfx = 0;
|
||||
m_explosion_intensity = 0;
|
||||
m_launching = false;
|
||||
|
||||
//Relying on a script yield, we return since flying wasn't true. Anything beyond this point would initiate landing.
|
||||
return;
|
||||
}
|
||||
|
||||
land();
|
||||
}
|
||||
|
||||
void land()
|
||||
{
|
||||
if (!m_landing && m_flying)
|
||||
{
|
||||
//Negative Z velocity results in gravity assuming we are falling, hence the removal of the parachute.
|
||||
constexpr auto parachute_hash = RAGE_JOAAT("GADGET_PARACHUTE");
|
||||
WEAPON::REMOVE_WEAPON_FROM_PED(self::ped, parachute_hash);
|
||||
detach_delete_vehicle();
|
||||
TASK::CLEAR_PED_TASKS_IMMEDIATELY(self::ped);
|
||||
m_flying = false;
|
||||
m_landing = true;
|
||||
|
||||
//Using raycast probe to determine where the player camera is looking at.
|
||||
m_land_coords = math::raycast_coords(CAM::GET_GAMEPLAY_CAM_COORD(), CAM::GET_GAMEPLAY_CAM_ROT(2), self::ped);
|
||||
|
||||
//If the determined land_coords are further than 500, we change our landing coord to the ground beneath.
|
||||
if (math::distance_between_vectors(self::pos, m_land_coords) > 500)
|
||||
{
|
||||
m_land_coords = self::pos;
|
||||
MISC::GET_GROUND_Z_FOR_3D_COORD(self::pos.x, self::pos.y, self::pos.z, &m_land_coords.z, true, 0);
|
||||
}
|
||||
|
||||
PED::SET_PED_CAN_RAGDOLL(self::ped, false);
|
||||
|
||||
//Use gravitate singularly to swing the player ped to the determined land_coords. Roughly innacurate since velocity is physics based.
|
||||
gravitate(self::ped, m_land_coords, 40);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void on_tick() override
|
||||
{
|
||||
//Both anims are required in order to consider the player ped flying.
|
||||
m_anims_are_playing = ENTITY::IS_ENTITY_PLAYING_ANIM(self::ped, "missfam5_yoga", "c8_to_start", 3) && ENTITY::IS_ENTITY_PLAYING_ANIM(self::ped, "skydive@parachute@first_person", "chute_idle_alt_lookright", 3);
|
||||
|
||||
//Check whether animations are compromised which would mean our flight is interrupted. Reset to avoid unwanted behaviour.
|
||||
if (!m_anims_are_playing && !m_launching && m_flying)
|
||||
reset();
|
||||
|
||||
PAD::DISABLE_CONTROL_ACTION(0, (int)ControllerInputs::INPUT_COVER, false);
|
||||
|
||||
if (m_timer)
|
||||
m_duration = std::chrono::duration_cast<std::chrono::milliseconds> (std::chrono::system_clock::now() - m_time_stamp);
|
||||
|
||||
//Timer is used for both the reset and the charged launch
|
||||
if (PAD::IS_DISABLED_CONTROL_JUST_RELEASED(0, (int)ControllerInputs::INPUT_COVER))
|
||||
{
|
||||
m_timer = false;
|
||||
m_charging = false;
|
||||
|
||||
//Check whether the button was released quickly to reset instead of initiate landing
|
||||
if (m_flying && m_duration.count() <= 0.2)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
launch();
|
||||
|
||||
script::get_current()->yield(10ms);
|
||||
}
|
||||
|
||||
m_duration = std::chrono::milliseconds::zero();
|
||||
}
|
||||
|
||||
//Timer is started once the button is pressed and a marker is drawn if player is flying to visualize landing coords.
|
||||
if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_COVER))
|
||||
{
|
||||
if (!m_timer)
|
||||
{
|
||||
m_time_stamp = std::chrono::system_clock::now();
|
||||
m_timer = true;
|
||||
}
|
||||
|
||||
if (m_flying)
|
||||
{
|
||||
auto probable_land_coords = math::raycast_coords(CAM::GET_GAMEPLAY_CAM_COORD(), CAM::GET_GAMEPLAY_CAM_ROT(2), self::ped);
|
||||
GRAPHICS::DRAW_MARKER(25, probable_land_coords.x, probable_land_coords.y, probable_land_coords.z + 0.1f, 0.f, 0.f, 0.f, 0, 0, 0, 5.f, 5.f, 5.f, 255, 255, 255, 100, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_COVER) && !m_flying
|
||||
&& g.self.super_hero_fly.charge)
|
||||
{
|
||||
charge_launch();
|
||||
}
|
||||
|
||||
if (m_flying)
|
||||
{
|
||||
if (g.self.super_hero_fly.fly_speed > 20)
|
||||
g.self.super_hero_fly.fly_speed = 20;
|
||||
if (g.self.super_hero_fly.fly_speed < 1)
|
||||
g.self.super_hero_fly.fly_speed = 1;
|
||||
|
||||
Vector3 rot = CAM::GET_GAMEPLAY_CAM_ROT(2);
|
||||
|
||||
if (!NETWORK::NETWORK_HAS_CONTROL_OF_ENTITY(m_veh_handle))
|
||||
entity::take_control_of(m_veh_handle);
|
||||
|
||||
ENTITY::SET_ENTITY_ROTATION(m_veh_handle, rot.x, rot.y, rot.z, 2, 0);
|
||||
|
||||
//Gravitate is called as long as flying is true to move our player ped to the desired coords with velocity.
|
||||
gravitate(m_veh_handle, m_fly_motion, g.self.super_hero_fly.fly_speed);
|
||||
|
||||
if (ENTITY::GET_ENTITY_HEIGHT_ABOVE_GROUND(m_veh_handle) < 1 && g.self.super_hero_fly.auto_land)
|
||||
launch();
|
||||
|
||||
//Fly motion nav
|
||||
Vector3 fly_nav{};
|
||||
bool moved = false;
|
||||
if (PAD::IS_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_MOVE_UP_ONLY))
|
||||
{
|
||||
fly_nav =
|
||||
ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(m_veh_handle, 0.0, (1.0 * g.self.super_hero_fly.fly_speed), 0.f);
|
||||
moved = true;
|
||||
}
|
||||
if (PAD::IS_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_MOVE_LEFT_ONLY))
|
||||
{
|
||||
fly_nav = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(m_veh_handle, (-1.0 * g.self.super_hero_fly.fly_speed), 0.0, 0.f);
|
||||
moved = true;
|
||||
}
|
||||
if (PAD::IS_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_MOVE_RIGHT_ONLY))
|
||||
{
|
||||
fly_nav = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(m_veh_handle, (1.0 * g.self.super_hero_fly.fly_speed), 0.0, 0.f);
|
||||
moved = true;
|
||||
}
|
||||
if (PAD::IS_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_MOVE_DOWN_ONLY))
|
||||
{
|
||||
fly_nav =
|
||||
ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(m_veh_handle, 0.0, (-1.0 * g.self.super_hero_fly.fly_speed), 0.f);
|
||||
moved = true;
|
||||
}
|
||||
if (PAD::IS_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_SPRINT))
|
||||
{
|
||||
Vector3 above = {self::pos.x, self::pos.y, self::pos.z + (float)(1.0 * g.self.super_hero_fly.fly_speed)};
|
||||
fly_nav = above;
|
||||
moved = true;
|
||||
}
|
||||
if (PAD::IS_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_DUCK))
|
||||
{
|
||||
Vector3 below = {self::pos.x, self::pos.y, self::pos.z - (float)(1.0 * g.self.super_hero_fly.fly_speed)};
|
||||
fly_nav = below;
|
||||
moved = true;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
{
|
||||
//Gradual smoothes the flight by incrementing speed as long as we are moving
|
||||
if (g.self.super_hero_fly.gradual)
|
||||
{
|
||||
g.self.super_hero_fly.fly_speed += 0.1f;
|
||||
}
|
||||
m_fly_motion = fly_nav;
|
||||
moved = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Reset the speed for gradual movement
|
||||
if (g.self.super_hero_fly.gradual)
|
||||
{
|
||||
g.self.super_hero_fly.fly_speed = 1.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_landing)
|
||||
{
|
||||
if (ENTITY::GET_ENTITY_HEIGHT_ABOVE_GROUND(self::ped) < 2 || !ENTITY::IS_ENTITY_IN_AIR(self::ped))
|
||||
{
|
||||
detach_delete_vehicle();
|
||||
|
||||
ENTITY::SET_ENTITY_VELOCITY(self::ped, 0, 0, 0);
|
||||
TASK::CLEAR_PED_TASKS(self::ped);
|
||||
m_landing = false;
|
||||
ENTITY::SET_ENTITY_VELOCITY(m_veh_handle, 0, 0, 0);
|
||||
ped::ped_play_animation(self::ped, "move_fall@beastjump", "high_land_stand", 4, -4, 2000, 0 | 4);
|
||||
apply_explosion();
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void on_enable() override
|
||||
{
|
||||
g_notification_service->push("SUPER_HERO_FLY"_T.data(), "SUPER_HERO_FLY_ENABLE_NOTIFICATION"_T.data());
|
||||
}
|
||||
|
||||
virtual void on_disable() override
|
||||
{
|
||||
reset();
|
||||
}
|
||||
};
|
||||
|
||||
super_hero_fly g_super_hero_fly("superherofly", "SUPER_HERO_FLY", "SUPER_HERO_FLY_DESC", g.self.super_hero_fly.enabled);
|
||||
bool_command gradual_speed("superheroflygradualspeed", "SUPER_HERO_FLY_GRADUAL_SPEED", "SUPER_HERO_FLY_GRADUAL_SPEED_DESC", g.self.super_hero_fly.gradual);
|
||||
bool_command explosions("superheroflyexplosions", "SUPER_HERO_FLY_EXPLOSIONS", "SUPER_HERO_FLY_EXPLOSIONS_DESC", g.self.super_hero_fly.explosions);
|
||||
bool_command auto_land("superheroflyautoland", "SUPER_HERO_FLY_AUTO_LAND", "SUPER_HERO_FLY_AUTO_LAND_DESC", g.self.super_hero_fly.auto_land);
|
||||
bool_command charge_launch("superheroflychargelaunch", "SUPER_HERO_FLY_CHARGE_LAUNCH", "SUPER_HERO_FLY_CHARGE_LAUNCH_DESC", g.self.super_hero_fly.charge);
|
||||
bool_command charge_ptfx("superheroflychargeptfx", "SUPER_HERO_FLY_CHARGE_PTFX", "SUPER_HERO_FLY_CHARGE_PTFX_DESC", g.self.super_hero_fly.ptfx);
|
||||
float_command speed("superheroflyspeed", "SUPER_HERO_FLY_SPEED", "SUPER_HERO_FLY_SPEED_DESC", g.self.super_hero_fly.fly_speed, 1.f, 50.f);
|
||||
float_command initial_launch("superheroflyinitiallaunch", "SUPER_HERO_FLY_INITIAL_LAUNCH", "SUPER_HERO_FLY_INITIAL_LAUNCH_DESC", g.self.super_hero_fly.initial_launch, 1.f, 50.f);
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
#include "backend/looped_command.hpp"
|
||||
#include "gta/enums.hpp"
|
||||
#include "natives.hpp"
|
||||
namespace big
|
||||
{
|
||||
class superman : looped_command
|
||||
{
|
||||
using looped_command::looped_command;
|
||||
|
||||
void apply_force(float x, float y, float z)
|
||||
{
|
||||
ENTITY::APPLY_FORCE_TO_ENTITY(self::ped, 1, x, y, z, 0, 0, 0, 0, true, true, true, false, true);
|
||||
}
|
||||
|
||||
virtual void on_tick() override
|
||||
{
|
||||
if (PAD::IS_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_JUMP))
|
||||
apply_force(0, 0, 10);
|
||||
|
||||
WEAPON::GIVE_DELAYED_WEAPON_TO_PED(self::ped, rage::joaat("GADGET_PARACHUTE"), 1, 1);
|
||||
if (!ENTITY::IS_ENTITY_IN_AIR(self::ped) || PED::IS_PED_RAGDOLL(self::ped))
|
||||
return;
|
||||
|
||||
if (PAD::IS_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_MOVE_UP_ONLY))
|
||||
apply_force(3, 0, 0);
|
||||
|
||||
if (PAD::IS_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_MOVE_DOWN_ONLY))
|
||||
apply_force(3, 6, 0);
|
||||
|
||||
if (PAD::IS_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_SPRINT))
|
||||
apply_force(6, 0, 0);
|
||||
}
|
||||
|
||||
virtual void on_enable() override
|
||||
{
|
||||
g_notification_service->push("Superman Controls", "Use the following keys to control the Superman mode:\n'W' / 'S' / 'SPACE' / 'SHIFT'.");
|
||||
}
|
||||
};
|
||||
|
||||
superman g_superman("superman", "SUPERMAN", "SUPERMAN_DESC", g.self.superman);
|
||||
}
|
@ -367,7 +367,21 @@ namespace big
|
||||
// do not save below entries
|
||||
bool dance_mode = false;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(self, ipls, ptfx_effects, clean_player, force_wanted_level, passive, free_cam, invisibility, local_visibility, never_wanted, no_ragdoll, noclip, noclip_aim_speed_multiplier, noclip_speed_multiplier, off_radar, super_run, no_collision, unlimited_oxygen, no_water_collision, wanted_level, god_mode, part_water, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_drown, proof_water, proof_mask, mobile_radio, fast_respawn, auto_tp, super_jump, beast_jump, healthregen, healthregenrate, hud, superman, custom_weapon_stop, prompt_ambient_animations, persist_outfit, persist_outfits_mis)
|
||||
struct super_hero_fly
|
||||
{
|
||||
bool enabled = false;
|
||||
bool gradual = true;
|
||||
bool explosions = true;
|
||||
bool auto_land = false;
|
||||
bool charge = true;
|
||||
bool ptfx = true;
|
||||
float fly_speed = 15.f;
|
||||
float initial_launch = 15.f;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(super_hero_fly, gradual, explosions, auto_land, charge, ptfx, fly_speed, initial_launch)
|
||||
} super_hero_fly{};
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(self, ipls, ptfx_effects, clean_player, force_wanted_level, passive, free_cam, invisibility, local_visibility, never_wanted, no_ragdoll, noclip, noclip_aim_speed_multiplier, noclip_speed_multiplier, off_radar, super_run, no_collision, unlimited_oxygen, no_water_collision, wanted_level, god_mode, part_water, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_drown, proof_water, proof_mask, mobile_radio, fast_respawn, auto_tp, super_jump, beast_jump, healthregen, healthregenrate, hud, superman, custom_weapon_stop, prompt_ambient_animations, persist_outfit, persist_outfits_mis, super_hero_fly)
|
||||
} self{};
|
||||
|
||||
struct session
|
||||
|
@ -35,7 +35,7 @@ namespace big
|
||||
|
||||
static bool script_patch_checkbox(const std::string_view text, bool* option, const std::string_view tooltip = "");
|
||||
|
||||
static void options_modal(std::string element_name, std::function<void()> render_elements, bool sameline = true, std::string custom_button_name = "Options");
|
||||
static void options_modal(const std::string_view element_name, std::function<void()> render_elements, bool sameline = true, std::string custom_button_name = "Options");
|
||||
|
||||
template<template_str cmd_str, ImVec2 size = ImVec2(0, 0), ImVec4 color = ImVec4(0.24f, 0.23f, 0.29f, 1.00f)>
|
||||
static void command_button(const std::vector<uint64_t> args = {}, std::optional<const std::string_view> label_override = std::nullopt)
|
||||
@ -117,6 +117,22 @@ namespace big
|
||||
ImGui::SetTooltip(command->get_description().c_str());
|
||||
}
|
||||
|
||||
template<template_str cmd_str>
|
||||
static void command_float_input(std::optional<const std::string_view> label_override = std::nullopt)
|
||||
{
|
||||
static float_command* command = (float_command*)command::get(rage::consteval_joaat(cmd_str.value));
|
||||
if (command == nullptr)
|
||||
return ImGui::Text("INVALID COMMAND");
|
||||
|
||||
ImGui::InputFloat(label_override.value_or(command->get_label()).data(),
|
||||
&command->get_value(),
|
||||
command->get_lower_bound(),
|
||||
command->get_upper_bound());
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip(command->get_description().c_str());
|
||||
}
|
||||
|
||||
template<ImVec2 size = ImVec2(0, 0), ImVec4 color = ImVec4(0.24f, 0.23f, 0.29f, 1.00f)>
|
||||
static bool button(const std::string_view text)
|
||||
{
|
||||
|
@ -5,12 +5,13 @@ namespace big
|
||||
/*
|
||||
Will provide an options button next to the previous element that opens up a popup to run the content of 'render_elements'
|
||||
*/
|
||||
void components::options_modal(std::string element_name, std::function<void()> render_elements, bool sameline, std::string custom_button_name)
|
||||
void components::options_modal(const std::string_view element_name, std::function<void()> render_elements, bool sameline, std::string custom_button_name)
|
||||
{
|
||||
if (sameline)
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button(std::string(custom_button_name + "##" + element_name).data()))
|
||||
ImGui::PushID(element_name.data());
|
||||
if (ImGui::Button(custom_button_name.c_str()))
|
||||
ImGui::OpenPopup(element_name.data());
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x * 0.5f, ImGui::GetIO().DisplaySize.y * 0.5f), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
@ -18,10 +19,11 @@ namespace big
|
||||
{
|
||||
render_elements();
|
||||
ImGui::Spacing();
|
||||
if (ImGui::Button(std::format("{}##{}", "CLOSE"_T, element_name).c_str()) || ((!ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered()) && ImGui::IsMouseClicked(ImGuiMouseButton_Left)))
|
||||
if (components::button("CLOSE"_T) || ((!ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered()) && ImGui::IsMouseClicked(ImGuiMouseButton_Left)))
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "pointers.hpp"
|
||||
#include "natives.hpp"
|
||||
|
||||
namespace big::math
|
||||
{
|
||||
@ -36,4 +37,30 @@ namespace big::math
|
||||
|
||||
return (float)distance_between_vectors(plyr_coords, cam_coords);
|
||||
}
|
||||
|
||||
inline Vector3 raycast_coords(Vector3 coord, Vector3 rot, Entity ignore)
|
||||
{
|
||||
BOOL hit;
|
||||
Vector3 end_coords;
|
||||
Vector3 surface_normal;
|
||||
Entity hit_entity;
|
||||
Vector3 dir = math::rotation_to_direction(rot);
|
||||
Vector3 far_coords;
|
||||
|
||||
far_coords.x = coord.x + dir.x * 1000;
|
||||
far_coords.y = coord.y + dir.y * 1000;
|
||||
far_coords.z = coord.z + dir.z * 1000;
|
||||
|
||||
int ray = SHAPETEST::START_EXPENSIVE_SYNCHRONOUS_SHAPE_TEST_LOS_PROBE(coord.x,
|
||||
coord.y,
|
||||
coord.z,
|
||||
far_coords.x,
|
||||
far_coords.y,
|
||||
far_coords.z,
|
||||
-1,
|
||||
ignore,
|
||||
7);
|
||||
SHAPETEST::GET_SHAPE_TEST_RESULT(ray, &hit, &end_coords, &surface_normal, &hit_entity);
|
||||
return end_coords;
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ namespace big
|
||||
ImGui::BeginGroup();
|
||||
|
||||
components::command_checkbox<"noclip">();
|
||||
components::options_modal("Noclip", [] {
|
||||
components::options_modal("NO_CLIP"_T, [] {
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
@ -82,7 +82,25 @@ namespace big
|
||||
|
||||
components::command_checkbox<"cleanloop">();
|
||||
components::command_checkbox<"mobileradio">();
|
||||
components::command_checkbox<"superman">();
|
||||
components::command_checkbox<"superherofly">();
|
||||
components::options_modal("SUPER_HERO_FLY_OPTION_MODAL"_T, [] {
|
||||
ImGui::Text("SUPER_HERO_FLY_OPTION_MODAL_DETAILED_DESC"_T.data());
|
||||
ImGui::Separator();
|
||||
|
||||
components::command_checkbox<"superheroflygradualspeed">();
|
||||
components::disable_unless([] { return !g.self.super_hero_fly.gradual; }, []{
|
||||
ImGui::SetNextItemWidth(150);
|
||||
components::command_float_input<"superheroflyspeed">();
|
||||
});
|
||||
components::command_checkbox<"superheroflyexplosions">();
|
||||
components::command_checkbox<"superheroflyautoland">();
|
||||
components::command_checkbox<"superheroflychargelaunch">();
|
||||
components::disable_unless([] { return g.self.super_hero_fly.charge; }, []{
|
||||
components::command_checkbox<"superheroflychargeptfx">();
|
||||
});
|
||||
ImGui::SetNextItemWidth(150);
|
||||
components::command_float_input<"superheroflyinitiallaunch">();
|
||||
});
|
||||
|
||||
ImGui::Checkbox("DANCE_MODE"_T.data(), &g.self.dance_mode);
|
||||
|
||||
|
Reference in New Issue
Block a user