feat(Vehicle): Added option to override vehicle weapons. (#2081)

This commit is contained in:
張致強 2023-09-14 23:19:32 +08:00 committed by GitHub
parent 03b1668589
commit 0c6acb7581
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 375 additions and 2 deletions

View File

@ -0,0 +1,248 @@
#include "backend/looped_command.hpp"
namespace big
{
class custom_vehicle_weapon : looped_command
{
using looped_command::looped_command;
using vehicle_ammo_setting = struct menu_settings::vehicle::vehicle_ammo_special;
using CWeaponInfoFlags = std::bitset<192>;
// mg
CWeaponInfo* m_mg_weapon_info = nullptr;
eDamageType m_mg_damage_type = eDamageType::None;
CWeaponInfo::sExplosion m_mg_explosion{};
eAmmoSpecialType m_mg_ammo_type = eAmmoSpecialType::None;
float m_mg_speed = 0;
float m_mg_time_between_shots = 0;
float m_mg_alternate_wait_time = 0;
float m_mg_range = 0;
// rocket
CWeaponInfo* m_rocket_weapon_info = nullptr;
eDamageType m_rocket_damage_type = eDamageType::Explosive;
CWeaponInfoFlags m_rocket_weapon_flags = 0;
float m_rocket_time_between_shots = 0;
float m_rocket_alternate_wait_time = 0;
float m_rocket_lock_on_range = 0;
float m_rocket_range = 0;
float m_rocket_reload_time_mp = 0;
float m_rocket_reload_time_sp = 0;
// rocket ammo
CAmmoRocketInfo::sExplosion m_rocket_explosion{};
float m_rocket_lifetime = 0;
float m_rocket_launch_speed = 0;
float m_rocket_time_before_homing = 0;
CHomingRocketParams m_rocket_homing_params{};
virtual void on_tick() override
{
if (g_local_player == nullptr || g_local_player->m_weapon_manager == nullptr
|| g_local_player->m_weapon_manager->m_vehicle_weapon_info == nullptr
|| g_local_player->m_weapon_manager->m_vehicle_weapon_info->m_ammo_info == nullptr)
{
return;
}
CWeaponInfo* weapon_info = g_local_player->m_weapon_manager->m_vehicle_weapon_info;
if (is_weapon_mg(weapon_info))
{
// check if the player changed their weapon
if (m_mg_weapon_info != weapon_info)
{
// apply the original bullet and impact type to the old weapon
restore_mg();
// backup the bullet and impact type of the new weapon
backup_mg(weapon_info);
}
// apply ammo type changes to the current weapon
apply_mg(g.vehicle.vehicle_ammo_special);
}
else if (is_weapon_rocket(weapon_info))
{
if (m_rocket_weapon_info != weapon_info)
{
restore_rocket();
backup_rocket(weapon_info);
}
apply_rocket(g.vehicle.vehicle_ammo_special);
}
}
virtual void on_disable() override
{
restore_mg();
restore_rocket();
}
CWeaponInfoFlags& weapon_flags(CWeaponInfo* weapon_info)
{
return *((CWeaponInfoFlags*)((char*)weapon_info + 0x900));
}
bool is_weapon_mg(const CWeaponInfo* weapon_info)
{
return weapon_info->m_fire_type == eFireType::InstantHit || weapon_info->m_fire_type == eFireType::DelayedHit;
}
bool is_weapon_rocket(const CWeaponInfo* weapon_info)
{
if (weapon_info->m_fire_type != eFireType::ProjectTile)
return false;
// this is to differentiate missiles from turrets, mortars and barrage
CAmmoRocketInfo* rocket_info = (CAmmoRocketInfo*)weapon_info->m_ammo_info;
uint32_t trail_hash = rocket_info->m_m_trail_fx_hash;
return (trail_hash == RAGE_JOAAT("proj_rpg_trail") || trail_hash == RAGE_JOAAT("proj_xm_thruster_rpg_trail"));
}
void restore_mg()
{
// apply the original bullet and impact type to the old weapon
if (m_mg_weapon_info != nullptr)
{
m_mg_weapon_info->m_damage_type = m_mg_damage_type;
m_mg_weapon_info->m_explosion = m_mg_explosion;
m_mg_weapon_info->m_ammo_info->m_ammo_special_type = m_mg_ammo_type;
m_mg_weapon_info->m_speed = m_mg_speed;
m_mg_weapon_info->m_time_between_shots = m_mg_time_between_shots;
m_mg_weapon_info->m_alternate_wait_time = m_mg_alternate_wait_time;
m_mg_weapon_info->m_weapon_range = m_mg_range;
}
}
void backup_mg(CWeaponInfo* weapon_info)
{
// backup the bullet and impact type of the new weapon
m_mg_weapon_info = weapon_info;
m_mg_damage_type = weapon_info->m_damage_type;
m_mg_explosion = weapon_info->m_explosion;
m_mg_ammo_type = weapon_info->m_ammo_info->m_ammo_special_type;
m_mg_speed = weapon_info->m_speed;
m_mg_time_between_shots = weapon_info->m_time_between_shots;
m_mg_alternate_wait_time = weapon_info->m_alternate_wait_time;
m_mg_range = weapon_info->m_weapon_range;
}
void apply_mg(const vehicle_ammo_setting& g_vehicle_ammo_settings)
{
// apply ammo type changes to the current weapon
eDamageType damage_type = eDamageType::None;
eExplosionTag explosion_tag = g_vehicle_ammo_settings.explosion_tag;
eAmmoSpecialType ammo_type = eAmmoSpecialType::None;
if (explosion_tag == eExplosionTag::DONTCARE)
{
damage_type = m_mg_damage_type;
ammo_type = g_vehicle_ammo_settings.type;
}
else
{
damage_type = eDamageType::Explosive;
ammo_type = m_mg_ammo_type;
}
m_mg_weapon_info->m_damage_type = damage_type;
CWeaponInfo::sExplosion explosion;
explosion.m_default = explosion_tag;
explosion.m_hit_bike = explosion_tag;
explosion.m_hit_boat = explosion_tag;
explosion.m_hit_car = explosion_tag;
explosion.m_hit_plane = explosion_tag;
explosion.m_hit_truck = explosion_tag;
m_mg_weapon_info->m_explosion = explosion;
m_mg_weapon_info->m_ammo_info->m_ammo_special_type = ammo_type;
m_mg_weapon_info->m_speed = g_vehicle_ammo_settings.speed;
m_mg_weapon_info->m_time_between_shots = g_vehicle_ammo_settings.time_between_shots;
m_mg_weapon_info->m_alternate_wait_time = g_vehicle_ammo_settings.alternate_wait_time;
m_mg_weapon_info->m_weapon_range = g_vehicle_ammo_settings.weapon_range;
}
void restore_rocket()
{
if (m_rocket_weapon_info != nullptr)
{
m_rocket_weapon_info->m_damage_type = m_rocket_damage_type;
m_rocket_weapon_info->m_time_between_shots = m_rocket_time_between_shots;
m_rocket_weapon_info->m_alternate_wait_time = m_rocket_alternate_wait_time;
m_rocket_weapon_info->m_lock_on_range = m_rocket_lock_on_range;
m_rocket_weapon_info->m_weapon_range = m_rocket_range;
m_rocket_weapon_info->m_reload_time_mp = m_rocket_reload_time_mp;
m_rocket_weapon_info->m_reload_time_sp = m_rocket_reload_time_sp;
weapon_flags(m_rocket_weapon_info) = m_rocket_weapon_flags;
CAmmoRocketInfo* rocket_info = (CAmmoRocketInfo*)m_rocket_weapon_info->m_ammo_info;
rocket_info->m_explosion = m_rocket_explosion;
rocket_info->m_lifetime = m_rocket_lifetime;
rocket_info->m_launch_speed = m_rocket_launch_speed;
rocket_info->m_time_before_homing = m_rocket_time_before_homing;
rocket_info->m_homing_rocket_params = m_rocket_homing_params;
m_rocket_weapon_info = nullptr;
}
}
void backup_rocket(CWeaponInfo* weapon_info)
{
m_rocket_weapon_info = weapon_info;
m_rocket_time_between_shots = weapon_info->m_time_between_shots;
m_rocket_alternate_wait_time = weapon_info->m_alternate_wait_time;
m_rocket_lock_on_range = weapon_info->m_lock_on_range;
m_rocket_range = weapon_info->m_weapon_range;
m_rocket_reload_time_mp = weapon_info->m_reload_time_mp;
m_rocket_reload_time_sp = weapon_info->m_reload_time_sp;
m_rocket_weapon_flags = weapon_flags(weapon_info);
CAmmoRocketInfo* rocket_info = (CAmmoRocketInfo*)weapon_info->m_ammo_info;
m_rocket_explosion = rocket_info->m_explosion;
m_rocket_lifetime = rocket_info->m_lifetime;
m_rocket_launch_speed = rocket_info->m_launch_speed;
m_rocket_time_before_homing = rocket_info->m_time_before_homing;
m_rocket_homing_params = rocket_info->m_homing_rocket_params;
}
void apply_rocket(const vehicle_ammo_setting& g_vehicle_ammo_settings)
{
m_rocket_weapon_info->m_damage_type = eDamageType::Explosive;
m_rocket_weapon_info->m_time_between_shots = g_vehicle_ammo_settings.rocket_time_between_shots;
m_rocket_weapon_info->m_alternate_wait_time = g_vehicle_ammo_settings.rocket_alternate_wait_time;
m_rocket_weapon_info->m_weapon_range = g_vehicle_ammo_settings.rocket_range;
m_rocket_weapon_info->m_lock_on_range = g_vehicle_ammo_settings.rocket_lock_on_range;
m_rocket_weapon_info->m_reload_time_mp = g_vehicle_ammo_settings.rocket_reload_time;
m_rocket_weapon_info->m_reload_time_sp = g_vehicle_ammo_settings.rocket_reload_time;
CAmmoRocketInfo* rocket_info = (CAmmoRocketInfo*)m_rocket_weapon_info->m_ammo_info;
eExplosionTag explosion_tag = g_vehicle_ammo_settings.rocket_explosion_tag;
CAmmoRocketInfo::sExplosion explosion;
explosion.m_default = explosion_tag;
explosion.m_hit_bike = explosion_tag;
explosion.m_hit_boat = explosion_tag;
explosion.m_hit_car = explosion_tag;
explosion.m_hit_plane = explosion_tag;
explosion.m_hit_truck = explosion_tag;
rocket_info->m_explosion = explosion;
rocket_info->m_lifetime = g_vehicle_ammo_settings.rocket_lifetime;
rocket_info->m_launch_speed = g_vehicle_ammo_settings.rocket_launch_speed;
rocket_info->m_time_before_homing = g_vehicle_ammo_settings.rocket_time_before_homing;
if (g_vehicle_ammo_settings.rocket_improve_tracking)
{
rocket_info->m_homing_rocket_params.m_should_use_homing_params_from_info = true;
rocket_info->m_homing_rocket_params.m_turn_rate_modifier = 4.0;
rocket_info->m_homing_rocket_params.m_pitch_yaw_roll_clamp = 8.5;
rocket_info->m_homing_rocket_params.m_default_homing_rocket_break_lock_angle = 0.2;
rocket_info->m_homing_rocket_params.m_default_homing_rocket_break_lock_angle_close = 0.6;
rocket_info->m_homing_rocket_params.m_default_homing_rocket_break_lock_close_distance = 20.0;
rocket_info->m_homing_rocket_params.m_time_before_starting_homing = 0.15;
weapon_flags(m_rocket_weapon_info)[152] = 1;
}
else
{
rocket_info->m_homing_rocket_params = m_rocket_homing_params;
weapon_flags(m_rocket_weapon_info) = m_rocket_weapon_flags;
}
}
};
custom_vehicle_weapon g_custom_vehicle_weapon("customvehweaps", "CUSTOM_VEH_WEAPONS", "CUSTOM_VEH_WEAPONS_DESC", g.vehicle.vehicle_ammo_special.enabled);
}

View File

@ -10,6 +10,7 @@
#include <rage/rlSessionInfo.hpp>
#include <weapon/CAmmoInfo.hpp>
#include <weapon/CWeaponInfo.hpp>
#include <weapon/CAmmoRocketInfo.hpp>
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui.h>
@ -717,7 +718,30 @@ namespace big
bool siren_mute = false;
bool all_vehs_in_heists = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(vehicle, speedo_meter, fly, rainbow_paint, speed_unit, god_mode, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_water, proof_mask, auto_drive_destination, auto_drive_style, auto_drive_speed, auto_turn_signals, boost_behavior, drive_on_water, horn_boost, instant_brake, block_homing, seatbelt, turn_signals, vehicle_jump, keep_vehicle_repaired, no_water_collision, disable_engine_auto_start, change_engine_state_immediately, keep_engine_running, keep_vehicle_clean, vehinvisibility, localveh_visibility, keep_on_ground, no_collision, unlimited_weapons, siren_mute, all_vehs_in_heists)
struct vehicle_ammo_special
{
bool enabled = false;
eAmmoSpecialType type = eAmmoSpecialType::None;
eExplosionTag explosion_tag = eExplosionTag::EXP_TAG_ROGUE_CANNON;
float speed = 2000;
float time_between_shots = 0.04;
float alternate_wait_time = -1;
float weapon_range = 250;
float rocket_time_between_shots = 0.66;
float rocket_alternate_wait_time = 0.66;
float rocket_lock_on_range = 500;
float rocket_range = 1000;
float rocket_reload_time = -1;
eExplosionTag rocket_explosion_tag = eExplosionTag::TANKSHELL;
float rocket_lifetime = 15;
float rocket_launch_speed = 1200;
float rocket_time_before_homing = 0.75;
bool rocket_improve_tracking = true;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(vehicle_ammo_special, enabled, type, explosion_tag, speed, time_between_shots, alternate_wait_time, weapon_range, rocket_time_between_shots, rocket_alternate_wait_time, rocket_lock_on_range, rocket_range, rocket_reload_time, rocket_explosion_tag, rocket_lifetime, rocket_launch_speed, rocket_time_before_homing, rocket_improve_tracking)
} vehicle_ammo_special{};
NLOHMANN_DEFINE_TYPE_INTRUSIVE(vehicle, speedo_meter, fly, rainbow_paint, speed_unit, god_mode, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_water, proof_mask, auto_drive_destination, auto_drive_style, auto_drive_speed, auto_turn_signals, boost_behavior, drive_on_water, horn_boost, instant_brake, block_homing, seatbelt, turn_signals, vehicle_jump, keep_vehicle_repaired, no_water_collision, disable_engine_auto_start, change_engine_state_immediately, keep_engine_running, keep_vehicle_clean, vehinvisibility, localveh_visibility, keep_on_ground, no_collision, unlimited_weapons, siren_mute, all_vehs_in_heists, vehicle_ammo_special)
} vehicle{};
struct weapons

View File

@ -1,3 +1,5 @@
#include "core/data/bullet_impact_types.hpp"
#include "core/data/special_ammo_types.hpp"
#include "core/data/speed_units.hpp"
#include "core/enums.hpp"
#include "fiber_pool.hpp"
@ -144,7 +146,7 @@ namespace big
{
ImGui::Text("KEEP_VEHICLE_CLEAN"_T.data());
}
else if (g.vehicle.keep_vehicle_repaired)
else if (g.vehicle.keep_vehicle_repaired)
{
ImGui::Text("KEEP_VEHICLE_REPAIRED"_T.data());
}
@ -246,5 +248,104 @@ namespace big
g.vehicle.fly.speed = vehicle::speed_to_mps(fly_speed_user_unit, g.vehicle.speed_unit);
}
}
ImGui::SeparatorText("CUSTOM_VEH_WEAPONS"_T.data());
{
components::command_checkbox<"customvehweaps">(std::format("{}##customvehweaps", "ENABLED"_T));
components::options_modal("CUSTOM_VEH_WEAPONS"_T.data(), [] {
eAmmoSpecialType selected_ammo = g.vehicle.vehicle_ammo_special.type;
eExplosionTag selected_explosion = g.vehicle.vehicle_ammo_special.explosion_tag;
eExplosionTag selected_rocket_explosion = g.vehicle.vehicle_ammo_special.rocket_explosion_tag;
ImGui::BeginGroup();
components::sub_title("CUSTOM_VEH_WEAPONS_MG"_T.data());
if (ImGui::BeginCombo("SPECIAL_AMMO"_T.data(), SPECIAL_AMMOS[(int)selected_ammo].name))
{
for (const auto& special_ammo : SPECIAL_AMMOS)
{
if (ImGui::Selectable(special_ammo.name, special_ammo.type == selected_ammo))
{
g.vehicle.vehicle_ammo_special.type = special_ammo.type;
}
if (special_ammo.type == selected_ammo)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
if (ImGui::BeginCombo("BULLET_IMPACT"_T.data(), BULLET_IMPACTS[selected_explosion]))
{
for (const auto& [type, name] : BULLET_IMPACTS)
{
if (ImGui::Selectable(name, type == selected_explosion))
{
g.vehicle.vehicle_ammo_special.explosion_tag = type;
}
if (type == selected_explosion)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
ImGui::InputFloat("CUSTOM_VEH_WEAPONS_SPEED"_T.data(), &g.vehicle.vehicle_ammo_special.speed, 10, 100, "%.1f");
ImGui::InputFloat("CUSTOM_VEH_WEAPONS_RANGE"_T.data(), &g.vehicle.vehicle_ammo_special.weapon_range, 50, 100, "%.1f");
ImGui::InputFloat("CUSTOM_VEH_WEAPONS_TBS"_T.data(), &g.vehicle.vehicle_ammo_special.time_between_shots, 0.001, 0.1, "%.3f");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("CUSTOM_VEH_WEAPONS_TBS_DESC"_T.data());
ImGui::InputFloat("CUSTOM_VEH_WEAPONS_AWT"_T.data(), &g.vehicle.vehicle_ammo_special.alternate_wait_time, 0.001, 0.1, "%.3f");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("CUSTOM_VEH_WEAPONS_AWT_DESC"_T.data());
ImGui::EndGroup();
ImGui::SameLine();
ImGui::BeginGroup();
components::sub_title("CUSTOM_VEH_WEAPONS_MISSILE"_T.data());
if (ImGui::BeginCombo(std::format("{}##customvehweaps", "EXPLOSION"_T).data(), BULLET_IMPACTS[selected_rocket_explosion]))
{
for (const auto& [type, name] : BULLET_IMPACTS)
{
if (ImGui::Selectable(name, type == selected_rocket_explosion))
{
g.vehicle.vehicle_ammo_special.rocket_explosion_tag = type;
}
if (type == selected_rocket_explosion)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
ImGui::InputFloat("CUSTOM_VEH_WEAPONS_RELOAD_TIME"_T.data(), &g.vehicle.vehicle_ammo_special.rocket_reload_time, 0.1, 1, "%.1f");
ImGui::InputFloat(std::format("{}##rocket", "CUSTOM_VEH_WEAPONS_SPEED"_T).data(),
&g.vehicle.vehicle_ammo_special.rocket_launch_speed, 10, 100, "%.1f");
ImGui::InputFloat(std::format("{}##rocket", "CUSTOM_VEH_WEAPONS_RANGE"_T).data(),
&g.vehicle.vehicle_ammo_special.rocket_range, 50, 100, "%.1f");
ImGui::InputFloat("CUSTOM_VEH_WEAPONS_LOCKON_RANGE"_T.data(), &g.vehicle.vehicle_ammo_special.rocket_lock_on_range, 50, 100, "%.1f");
ImGui::InputFloat("CUSTOM_VEH_WEAPONS_LOCKON_TIME"_T.data(), &g.vehicle.vehicle_ammo_special.rocket_time_before_homing, 0.01, 0.1, "%.2f");
ImGui::InputFloat(std::format("{}##rocket", "CUSTOM_VEH_WEAPONS_TBS"_T).data(),
&g.vehicle.vehicle_ammo_special.rocket_time_between_shots, 0.001, 0.1, "%.3f");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("CUSTOM_VEH_WEAPONS_TBS_DESC"_T.data());
ImGui::InputFloat(std::format("{}##rocket", "CUSTOM_VEH_WEAPONS_AWT"_T).data(),
&g.vehicle.vehicle_ammo_special.rocket_alternate_wait_time, 0.001, 0.1, "%.3f");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("CUSTOM_VEH_WEAPONS_AWT_DESC"_T.data());
ImGui::InputFloat("CUSTOM_VEH_WEAPONS_LIFETIME"_T.data(), &g.vehicle.vehicle_ammo_special.rocket_lifetime, 0.1, 1, "%.1f");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("CUSTOM_VEH_WEAPONS_LIFETIME_DESC"_T.data());
ImGui::Checkbox("CUSTOM_VEH_WEAPONS_SMART_MISSILE"_T.data(), &g.vehicle.vehicle_ammo_special.rocket_improve_tracking);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("CUSTOM_VEH_WEAPONS_SMART_MISSILE_DESC"_T.data());
ImGui::EndGroup();
});
}
}
}