Squad spawner improvements (#1329)
* New Fun UI for self with Super hero fly & bulletshield * Added missing hotkey global * New debug window for animations * Some more context menu additions * Changed private variable to public for Orbital drone * Added max vehicle & favour roads & spawn ahead & orbital drone coords on custom spawn mode & persisten vehicle integration * Removed Log entry * Removed some more log entries * Some small tweaks * Added persistent vehicle to the logic
This commit is contained in:
parent
49235195b5
commit
34c37b2042
@ -9,9 +9,8 @@ namespace big
|
||||
bool m_lock;
|
||||
Entity m_lock_ent;
|
||||
|
||||
Vector3 m_ground_pos;
|
||||
Vector3 m_start_pos;
|
||||
|
||||
|
||||
int m_scaleform;
|
||||
|
||||
bool m_should_tp;
|
||||
@ -23,15 +22,17 @@ namespace big
|
||||
void tick();
|
||||
|
||||
bool initialized()
|
||||
{ return m_initialized; };
|
||||
{
|
||||
return m_initialized;
|
||||
};
|
||||
|
||||
Vector3 m_ground_pos;
|
||||
|
||||
private:
|
||||
void cam_nav();
|
||||
void detect_player(Entity ent);
|
||||
void orbital_cannon_explosion();
|
||||
|
||||
};
|
||||
|
||||
inline orbital_drone g_orbital_drone_service;
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
#include "squad_spawner.hpp"
|
||||
|
||||
#include "gta/joaat.hpp"
|
||||
#include "services/vehicle/persist_car_service.hpp"
|
||||
#include "util/math.hpp"
|
||||
#include "util/pathfind.hpp"
|
||||
#include "util/ped.hpp"
|
||||
@ -75,19 +76,69 @@ namespace big
|
||||
|
||||
std::pair<Vehicle, CVehicle*> squad_spawner::spawn_squad_vehicle(squad s)
|
||||
{
|
||||
auto handle = vehicle::spawn(rage::joaat(s.m_vehicle_model), s.m_spawn_pos, s.m_spawn_heading);
|
||||
std::pair<Vehicle, CVehicle*> veh;
|
||||
if (!s.does_squad_have_persistent_vehicle())
|
||||
{
|
||||
veh.first = vehicle::spawn(rage::joaat(s.m_vehicle_model), s.m_spawn_pos, s.m_spawn_heading);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto persistent_vehicles = persist_car_service::list_files();
|
||||
|
||||
VEHICLE::SET_VEHICLE_ON_GROUND_PROPERLY(handle, 5);
|
||||
ENTITY::SET_ENTITY_INVINCIBLE(handle, s.m_veh_invincibility);
|
||||
VEHICLE::SET_VEHICLE_ENGINE_ON(handle, true, true, false);
|
||||
for (auto c : persistent_vehicles)
|
||||
{
|
||||
if (c == s.m_persistent_vehicle)
|
||||
{
|
||||
veh.first = persist_car_service::load_vehicle(c);
|
||||
ENTITY::SET_ENTITY_COORDS(veh.first, s.m_spawn_pos.x, s.m_spawn_pos.y, s.m_spawn_pos.z, 0, 0, 0, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::pair<Vehicle, CVehicle*>(handle, reinterpret_cast<CVehicle*>(g_pointers->m_gta.m_handle_to_ptr(handle)));
|
||||
veh.second = (CVehicle*)g_pointers->m_gta.m_handle_to_ptr(veh.first);
|
||||
|
||||
VEHICLE::SET_VEHICLE_ON_GROUND_PROPERLY(veh.first, 5);
|
||||
ENTITY::SET_ENTITY_INVINCIBLE(veh.first, s.m_veh_invincibility);
|
||||
VEHICLE::SET_VEHICLE_ENGINE_ON(veh.first, true, true, false);
|
||||
ENTITY::SET_ENTITY_HEADING(veh.first, s.m_spawn_heading);
|
||||
|
||||
if (s.m_max_vehicle)
|
||||
vehicle::max_vehicle(veh.first);
|
||||
|
||||
return veh;
|
||||
}
|
||||
|
||||
bool find_road(squad& s)
|
||||
{
|
||||
const Vector3 original_pos = s.m_spawn_pos;
|
||||
const Vector3 target_ped_pos = ENTITY::GET_ENTITY_COORDS(s.current_target_ped, false);
|
||||
Vector3 south, north, chosen_pos;
|
||||
|
||||
//Initial search for an actual road
|
||||
pathfind::find_closest_road(s.m_spawn_pos, &south, &north);
|
||||
|
||||
//Check which is closer
|
||||
if (math::distance_between_vectors(south, s.m_spawn_pos) <= math::distance_between_vectors(north, s.m_spawn_pos))
|
||||
chosen_pos = south;
|
||||
else
|
||||
chosen_pos = north;
|
||||
|
||||
//Get a node to specify heading
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
if (pathfind::find_closest_vehicle_node_favour_direction(chosen_pos, target_ped_pos, s.m_spawn_pos, s.m_spawn_heading, 0, i) && math::distance_between_vectors(target_ped_pos, s.m_spawn_pos) >= s.m_spawn_distance)
|
||||
return true;
|
||||
}
|
||||
|
||||
s.m_spawn_pos = original_pos;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool squad_spawner::find_suitable_spawn_pos(squad& s)
|
||||
{
|
||||
Hash veh_model_hash = rage::joaat(s.m_vehicle_model);
|
||||
const Vector3 original_pos = s.m_spawn_pos;
|
||||
Hash veh_model_hash = rage::joaat(s.m_vehicle_model);
|
||||
int node_search_flag = (VEHICLE::IS_THIS_MODEL_A_BOAT(veh_model_hash) || VEHICLE::IS_THIS_MODEL_A_JETSKI(veh_model_hash)) ? 2 : 0;
|
||||
Vector3 new_pos = s.m_spawn_pos;
|
||||
|
||||
@ -102,21 +153,48 @@ namespace big
|
||||
}
|
||||
}
|
||||
|
||||
const float original_spawn_distance = s.m_spawn_distance;
|
||||
|
||||
static auto reset_spawn_pos_to_offset = [&]() -> void {
|
||||
Ped player_ped_handle = g_pointers->m_gta.m_ptr_to_handle(s.target->get_ped());
|
||||
s.m_spawn_pos = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(player_ped_handle, 0, -7, 0);
|
||||
//LOG(INFO) << "Squad spawner: No suitable spot found, spawning at an offset";
|
||||
g_notification_service->push_warning("Squad Spawner", "No suitable spot found, spawning at an offset");
|
||||
};
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
static auto is_pos_valid = [&]() -> bool {
|
||||
return math::distance_between_vectors(new_pos, s.m_spawn_pos) < (s.m_spawn_distance + 50.f) && new_pos != s.m_spawn_pos;
|
||||
};
|
||||
|
||||
static auto find_location = [&]() -> void {
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
if (pathfind::find_random_location_in_vicinity_precise(s.m_spawn_pos, new_pos, s.m_spawn_heading, node_search_flag, s.m_spawn_distance, 200, true))
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
//Use spawn distance to find a position ahead of target and limit the vicinity
|
||||
if (s.m_spawn_ahead)
|
||||
{
|
||||
if (pathfind::find_random_location_in_vicinity_precise(s.m_spawn_pos, new_pos, s.m_spawn_heading, node_search_flag, s.m_spawn_distance, 200))
|
||||
break;
|
||||
s.m_spawn_pos = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(s.current_target_ped, 0.0, s.m_spawn_distance, 0.0);
|
||||
s.m_spawn_distance = 5.f;
|
||||
}
|
||||
|
||||
//Actual algorithm to find a nice spot
|
||||
find_location();
|
||||
|
||||
//Try and find a road
|
||||
if (s.m_favour_roads)
|
||||
{
|
||||
if (find_road(s) && is_pos_valid())
|
||||
return true;
|
||||
|
||||
//If the road search failed, revert to original method
|
||||
find_location();
|
||||
}
|
||||
|
||||
//Reset if all searches failed with an allowance of up to 50.0f
|
||||
if (math::distance_between_vectors(new_pos, s.m_spawn_pos) > (s.m_spawn_distance + 50.f) || new_pos == s.m_spawn_pos)
|
||||
if (!is_pos_valid())
|
||||
{
|
||||
reset_spawn_pos_to_offset();
|
||||
return false;
|
||||
@ -137,8 +215,9 @@ namespace big
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::string(s.m_name).empty()){
|
||||
s.m_name = std::string(std::to_string(s.m_squad_size) + std::string("_").append(s.m_ped_model).append("_").append(std::to_string(s.m_internal_id)));
|
||||
if (std::string(s.m_name).empty())
|
||||
{
|
||||
s.m_name = std::string(std::to_string(s.m_squad_size) + std::string("_").append(s.m_ped_model).append("_").append(std::to_string(s.m_internal_id)));
|
||||
}
|
||||
|
||||
Hash veh_model_hash = rage::joaat(s.m_vehicle_model);
|
||||
@ -231,6 +310,7 @@ namespace big
|
||||
if (s.has_squad_spawned())
|
||||
{
|
||||
m_active_squads.push_back(s);
|
||||
script::get_current()->yield(100ms);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -57,19 +57,23 @@ namespace big
|
||||
std::string m_ped_model;
|
||||
std::string m_weapon_model;
|
||||
std::string m_vehicle_model;
|
||||
std::string m_persistent_vehicle = "None"; //The connection to persistent vehicle is done by the file name
|
||||
bool m_ped_invincibility;
|
||||
bool m_veh_invincibility;
|
||||
bool m_ped_proofs[5]; // 0 headshot, 1 bullet, 2 flame, 3 melee, 4 explosion
|
||||
float m_ped_health; //Leave at 0 to default
|
||||
float m_ped_armor; //Leave at 0 to default
|
||||
float m_ped_accuracy;
|
||||
float m_ped_accuracy = 50.f;
|
||||
float m_spawn_distance;
|
||||
int m_squad_size;
|
||||
eSquadSpawnDistance m_spawn_distance_mode;
|
||||
eCombatAbilityLevel m_combat_ability_level;
|
||||
int m_squad_size = 1;
|
||||
eSquadSpawnDistance m_spawn_distance_mode = eSquadSpawnDistance::CLOSEBY;
|
||||
eCombatAbilityLevel m_combat_ability_level = eCombatAbilityLevel::AVERAGE;
|
||||
bool m_stay_in_veh;
|
||||
bool m_spawn_behind_same_velocity; //Spawns behind a moving target with the same velocity as the targets vehicle
|
||||
bool m_disperse; //Spawns attackers that are on foot on seperate positions
|
||||
bool m_spawn_ahead;
|
||||
bool m_favour_roads;
|
||||
bool m_max_vehicle;
|
||||
|
||||
/*
|
||||
Leave vehicle_model empty to spawn a squad on foot
|
||||
@ -78,16 +82,17 @@ namespace big
|
||||
Leave spawn_distance at 0 to let the spawn_distance_mode to handle it
|
||||
*/
|
||||
squad(){};
|
||||
squad(std::string name, std::string ped_model, std::string weapon_model, std::string vehicle_model, int squad_size, bool ped_invincibility = false, bool veh_invincibility = false, bool ped_proofs[5] = {}, float ped_health = 0, float ped_armor = 0, float spawn_distance = 0, float ped_accuracy = 50.f, eSquadSpawnDistance spawn_distance_mode = eSquadSpawnDistance::CLOSEBY, eCombatAbilityLevel combat_ability_level = eCombatAbilityLevel::AVERAGE, bool stay_in_veh = false, bool spawn_behind_same_velocity = false, std::string description = "", bool disperse = false)
|
||||
squad(std::string name, std::string ped_model, std::string weapon_model, std::string vehicle_model, int squad_size, bool ped_invincibility = false, bool veh_invincibility = false, bool ped_proofs[5] = {}, float ped_health = 0, float ped_armor = 0, float spawn_distance = 0, float ped_accuracy = 50.f, eSquadSpawnDistance spawn_distance_mode = eSquadSpawnDistance::CLOSEBY, eCombatAbilityLevel combat_ability_level = eCombatAbilityLevel::AVERAGE, bool stay_in_veh = false, bool spawn_behind_same_velocity = false, std::string description = "", bool disperse = false, bool spawn_ahead = false, bool favour_roads = false, bool max_vehicle = false, std::string persistent_vehicle = "None")
|
||||
{
|
||||
m_internal_id = ++m_instance_count;
|
||||
|
||||
m_name = name;
|
||||
m_description = description;
|
||||
m_ped_model = ped_model;
|
||||
m_weapon_model = weapon_model;
|
||||
m_vehicle_model = vehicle_model;
|
||||
m_squad_size = squad_size;
|
||||
m_name = name;
|
||||
m_description = description;
|
||||
m_ped_model = ped_model;
|
||||
m_weapon_model = weapon_model;
|
||||
m_vehicle_model = vehicle_model;
|
||||
m_persistent_vehicle = persistent_vehicle;
|
||||
m_squad_size = squad_size;
|
||||
|
||||
m_ped_invincibility = ped_invincibility;
|
||||
m_veh_invincibility = veh_invincibility;
|
||||
@ -104,6 +109,9 @@ namespace big
|
||||
m_stay_in_veh = stay_in_veh;
|
||||
m_spawn_behind_same_velocity = spawn_behind_same_velocity;
|
||||
m_disperse = disperse;
|
||||
m_spawn_ahead = spawn_ahead;
|
||||
m_favour_roads = favour_roads;
|
||||
m_max_vehicle = max_vehicle;
|
||||
}
|
||||
|
||||
int get_id() const
|
||||
@ -113,12 +121,17 @@ namespace big
|
||||
|
||||
bool does_squad_have_description()
|
||||
{
|
||||
return !std::string(m_description).empty();
|
||||
return !m_description.empty();
|
||||
}
|
||||
|
||||
bool does_squad_have_vehicle()
|
||||
{
|
||||
return !std::string(m_vehicle_model).empty();
|
||||
return !m_vehicle_model.empty() || does_squad_have_persistent_vehicle();
|
||||
}
|
||||
|
||||
bool does_squad_have_persistent_vehicle()
|
||||
{
|
||||
return m_persistent_vehicle != "None";
|
||||
}
|
||||
|
||||
bool should_override_health()
|
||||
@ -190,7 +203,7 @@ namespace big
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(eSquadSpawnDistance, {{eSquadSpawnDistance::CUSTOM, "custom"}, {eSquadSpawnDistance::ON_TARGET, "on target"}, {eSquadSpawnDistance::CLOSEBY, "closeby"}, {eSquadSpawnDistance::MODERATELY_DISTANCED, "moderately distanced"}, {eSquadSpawnDistance::FAR_AWAY, "far away"}})
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(squad, m_name, m_description, m_ped_model, m_weapon_model, m_vehicle_model, m_ped_invincibility, m_veh_invincibility, m_ped_proofs, m_ped_health, m_ped_armor, m_ped_accuracy, m_spawn_distance, m_squad_size, m_spawn_distance_mode, m_combat_ability_level, m_stay_in_veh, m_spawn_behind_same_velocity, m_disperse);
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(squad, m_name, m_description, m_ped_model, m_weapon_model, m_vehicle_model, m_ped_invincibility, m_veh_invincibility, m_ped_proofs, m_ped_health, m_ped_armor, m_ped_accuracy, m_spawn_distance, m_squad_size, m_spawn_distance_mode, m_combat_ability_level, m_stay_in_veh, m_spawn_behind_same_velocity, m_disperse, m_spawn_ahead, m_favour_roads, m_max_vehicle, m_persistent_vehicle);
|
||||
|
||||
class squad_spawner
|
||||
{
|
||||
|
@ -27,11 +27,8 @@ namespace big
|
||||
read.close();
|
||||
}
|
||||
squad new_squad{};
|
||||
LOG(INFO) << "TEST1";
|
||||
from_json(j, new_squad);
|
||||
LOG(INFO) << "TEST2";
|
||||
g_squad_spawner_service.m_templates.push_back(new_squad);
|
||||
LOG(INFO) << "TEST3";
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
@ -99,7 +96,7 @@ namespace big
|
||||
m_templates.push_back(squad("Shotgunners", "g_m_y_lost_03", "WEAPON_AUTOSHOTGUN", "daemon", 2, false, false, ped_proofs, 0, 0, 0, 65, eSquadSpawnDistance::MODERATELY_DISTANCED, eCombatAbilityLevel::AVERAGE, false, false, "A duo biker gang that utilize sawn off shotguns on their Harley's"));
|
||||
m_templates.push_back(squad("Machete jesus", "u_m_m_jesus_01", "WEAPON_MACHETE", "", 1, false, false, ped_proofs_annoying, 0, 0, 0, 10, eSquadSpawnDistance::CLOSEBY, eCombatAbilityLevel::AVERAGE, false, false, "Christ has had enough of the sins"));
|
||||
m_templates.push_back(squad("Annoying security guard", "mp_m_securoguard_01", "WEAPON_STUNGUN_MP", "", 1, false, false, ped_proofs_annoying, 0, 0, 0, 100, eSquadSpawnDistance::CLOSEBY, eCombatAbilityLevel::PROFESSIONAL, false, false, "The mall security guard with superiority issues"));
|
||||
m_templates.push_back(squad("Heavy attack choppers", "s_m_y_swat_01", "WEAPON_MG", "valkyrie", 4, false, false, ped_proofs, 0, 0, 0, 100, eSquadSpawnDistance::MODERATELY_DISTANCED, eCombatAbilityLevel::PROFESSIONAL, false, false, "Very deadly attack chopper eqquiped with a cannon"));
|
||||
m_templates.push_back(squad("Heavy attack chopper", "s_m_y_swat_01", "WEAPON_MG", "valkyrie", 4, false, false, ped_proofs, 0, 0, 0, 100, eSquadSpawnDistance::MODERATELY_DISTANCED, eCombatAbilityLevel::PROFESSIONAL, false, false, "Very deadly attack chopper eqquiped with a cannon"));
|
||||
m_templates.push_back(squad("Fighter jet", "s_m_m_pilot_02", "WEAPON_UNARMED", "lazer", 1, false, false, ped_proofs, 0, 0, 0, 100, eSquadSpawnDistance::FAR_AWAY, eCombatAbilityLevel::PROFESSIONAL, false, false, "Tedious yet precise form of attack with a Fighter jet"));
|
||||
m_templates.push_back(squad("Mobile squad", "s_m_m_highsec_01", "WEAPON_MICROSMG", "komoda", 4, false, false, ped_proofs, 0, 0, 0, 100, eSquadSpawnDistance::FAR_AWAY, eCombatAbilityLevel::PROFESSIONAL, true, true, "This squad makes use of 'Vehicle catchup'"));
|
||||
m_templates.push_back(squad("Altruists", "a_m_m_acult_01", "WEAPON_SNSPISTOL", "", 8, false, false, ped_proofs, 0, 0, 0, 100, eSquadSpawnDistance::CLOSEBY, eCombatAbilityLevel::PROFESSIONAL, false, false, "Cannibals from the alrtuist cult will surround the victim using 'Disperse'", true));
|
||||
|
@ -75,6 +75,28 @@ namespace big::pathfind
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Same as find_closest_vehicle_node but will favour nodes that are facing the facecoords with their heading
|
||||
*/
|
||||
inline bool find_closest_vehicle_node_favour_direction(Vector3 coords, Vector3 facecoords, Vector3& outcoords, float& outheading, int flag, int nth = 1, float zMeasureMult = 3.f, float zTolerance = 0.f)
|
||||
{
|
||||
if (load_path_nodes(coords))
|
||||
return PATHFIND::GET_NTH_CLOSEST_VEHICLE_NODE_FAVOUR_DIRECTION(coords.x,
|
||||
coords.y,
|
||||
coords.z,
|
||||
facecoords.x,
|
||||
facecoords.y,
|
||||
facecoords.z,
|
||||
nth,
|
||||
&outcoords,
|
||||
&outheading,
|
||||
flag,
|
||||
zMeasureMult,
|
||||
zTolerance);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool find_random_vehicle_node(Vector3 center, Vector3& outcoords, float radius, bool avoid_dead_ends, bool avoid_highways, int min_lanes = 0)
|
||||
{
|
||||
int node_id;
|
||||
@ -100,7 +122,7 @@ namespace big::pathfind
|
||||
}
|
||||
}
|
||||
|
||||
inline bool find_random_location_in_vicinity(Vector3 coords, Vector3& outcoords, float& outheading, int flag, int vicinity)
|
||||
inline bool find_random_location_in_vicinity(Vector3 coords, Vector3& outcoords, float& outheading, int flag, int vicinity, bool favour_heading_to_original_coords = false)
|
||||
{
|
||||
outcoords = coords;
|
||||
|
||||
@ -108,7 +130,7 @@ namespace big::pathfind
|
||||
|
||||
Vector3 changed_coords = outcoords;
|
||||
|
||||
if (!find_closest_vehicle_node(outcoords, outcoords, outheading, flag) || math::distance_between_vectors(outcoords, coords) > vicinity || math::distance_between_vectors(outcoords, coords) < (vicinity / 2))
|
||||
if ((favour_heading_to_original_coords ? !find_closest_vehicle_node_favour_direction(outcoords, outcoords, outcoords, outheading, flag) : !find_closest_vehicle_node(outcoords, outcoords, outheading, flag)) || math::distance_between_vectors(outcoords, coords) > vicinity || math::distance_between_vectors(outcoords, coords) < (vicinity / 2))
|
||||
{
|
||||
outcoords = coords;
|
||||
|
||||
@ -126,7 +148,7 @@ namespace big::pathfind
|
||||
Param precision goes up to a value of 200 meaning how many positions it will try and filter from
|
||||
Might prove resource demanding based on hardware
|
||||
*/
|
||||
inline bool find_random_location_in_vicinity_precise(Vector3 coords, Vector3& outcoords, float& outheading, int flag, float vicinity, int precision = 50)
|
||||
inline bool find_random_location_in_vicinity_precise(Vector3 coords, Vector3& outcoords, float& outheading, int flag, float vicinity, int precision = 50, bool favour_heading_to_original_coords = false)
|
||||
{
|
||||
if (precision > 200)
|
||||
precision = 200;
|
||||
@ -137,7 +159,7 @@ namespace big::pathfind
|
||||
for (int i = 0; i < precision; i++)
|
||||
{
|
||||
Vector3 new_pos{};
|
||||
find_random_location_in_vicinity(coords, new_pos, outheading, flag, vicinity);
|
||||
find_random_location_in_vicinity(coords, new_pos, outheading, flag, vicinity, favour_heading_to_original_coords);
|
||||
found_locations.push_back(new_pos);
|
||||
}
|
||||
|
||||
@ -158,4 +180,12 @@ namespace big::pathfind
|
||||
|
||||
return outcoords != coords;
|
||||
}
|
||||
|
||||
/*
|
||||
Will give you two vectors representing the road extremes of the road closest to the given coords.
|
||||
*/
|
||||
inline bool find_closest_road(Vector3 coords, Vector3* south_end, Vector3* north_end, int* south_bound_lanes = nullptr, int* north_bound_lanes = nullptr, float* width_between_directional_lanes = nullptr, bool ignore_disabled_nodes = true, float min_lenght = 10.f, float min_lanes = 1)
|
||||
{
|
||||
return PATHFIND::GET_CLOSEST_ROAD(coords.x, coords.y, coords.z, min_lenght, min_lanes, south_end, north_end, south_bound_lanes, north_bound_lanes, width_between_directional_lanes, ignore_disabled_nodes);
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
#include "services/gta_data/gta_data_service.hpp"
|
||||
#include "services/squad_spawner/squad_spawner.hpp"
|
||||
#include "misc/cpp/imgui_stdlib.h"
|
||||
#include "services/gta_data/gta_data_service.hpp"
|
||||
#include "services/orbital_drone/orbital_drone.hpp"
|
||||
#include "services/squad_spawner/squad_spawner.hpp"
|
||||
#include "services/vehicle/persist_car_service.hpp"
|
||||
#include "views/view.hpp"
|
||||
|
||||
namespace big
|
||||
@ -109,7 +111,7 @@ namespace big
|
||||
ImGui::Spacing();
|
||||
|
||||
ImGui::PushItemWidth(250);
|
||||
|
||||
|
||||
components::input_text_with_hint("##name", "Name", &new_template.m_name);
|
||||
components::input_text_with_hint("##pedmodel", "Ped model", &new_template.m_ped_model);
|
||||
|
||||
@ -117,7 +119,7 @@ namespace big
|
||||
return pair.second.m_name == new_template.m_ped_model;
|
||||
});
|
||||
|
||||
if (!std::string(new_template.m_ped_model).empty() && ped_found == g_gta_data_service->peds().end())
|
||||
if (!new_template.m_ped_model.empty() && ped_found == g_gta_data_service->peds().end())
|
||||
{
|
||||
if (ImGui::ListBoxHeader("##pedlist", ImVec2(250, 200)))
|
||||
{
|
||||
@ -137,9 +139,7 @@ namespace big
|
||||
}
|
||||
}
|
||||
|
||||
components::input_text_with_hint("##vehmodel",
|
||||
"Vehicle model",
|
||||
&new_template.m_vehicle_model);
|
||||
components::input_text_with_hint("##vehmodel", "Vehicle model", &new_template.m_vehicle_model);
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Leave empty to spawn on foot");
|
||||
|
||||
@ -167,9 +167,7 @@ namespace big
|
||||
}
|
||||
}
|
||||
|
||||
components::input_text_with_hint("##weapmodel",
|
||||
"Weapon model",
|
||||
&new_template.m_weapon_model);
|
||||
components::input_text_with_hint("##weapmodel", "Weapon model", &new_template.m_weapon_model);
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Leave empty to spawn unarmed, beware that a player can only attain 3 melee attackers at a time");
|
||||
|
||||
@ -177,7 +175,7 @@ namespace big
|
||||
return pair.second.m_name == new_template.m_weapon_model;
|
||||
});
|
||||
|
||||
if (!std::string(new_template.m_weapon_model).empty() && weap_found == g_gta_data_service->weapons().end())
|
||||
if (!new_template.m_weapon_model.empty() && weap_found == g_gta_data_service->weapons().end())
|
||||
{
|
||||
if (ImGui::ListBoxHeader("##weaplist", ImVec2(250, 200)))
|
||||
{
|
||||
@ -223,25 +221,29 @@ namespace big
|
||||
});
|
||||
|
||||
components::button("Reset Fields", [] {
|
||||
new_template.m_spawn_distance_mode = (eSquadSpawnDistance)1;
|
||||
new_template.m_combat_ability_level = (eCombatAbilityLevel)2;
|
||||
new_template.m_name[0] = '\0';
|
||||
new_template.m_description[0] = '\0';
|
||||
new_template.m_ped_model[0] = '\0';
|
||||
new_template.m_vehicle_model[0] = '\0';
|
||||
new_template.m_weapon_model[0] = '\0';
|
||||
new_template.m_squad_size = 0;
|
||||
new_template.m_ped_invincibility = 0;
|
||||
new_template.m_veh_invincibility = 0;
|
||||
new_template.m_ped_health = 0;
|
||||
new_template.m_ped_armor = 0;
|
||||
new_template.m_ped_accuracy = 0;
|
||||
new_template.m_spawn_distance = 0;
|
||||
new_template.m_spawn_distance_mode = eSquadSpawnDistance::CLOSEBY;
|
||||
new_template.m_combat_ability_level = eCombatAbilityLevel::AVERAGE;
|
||||
new_template.m_name.clear();
|
||||
new_template.m_description.clear();
|
||||
new_template.m_ped_model.clear();
|
||||
new_template.m_vehicle_model.clear();
|
||||
new_template.m_weapon_model.clear();
|
||||
new_template.m_persistent_vehicle = "None";
|
||||
new_template.m_squad_size = 1;
|
||||
new_template.m_ped_invincibility = 0;
|
||||
new_template.m_veh_invincibility = 0;
|
||||
new_template.m_ped_health = 0;
|
||||
new_template.m_ped_armor = 0;
|
||||
new_template.m_ped_accuracy = 50;
|
||||
new_template.m_spawn_distance = 0;
|
||||
for (int i = 0; i < sizeof(new_template.m_ped_proofs) / sizeof(new_template.m_ped_proofs[0]); i++)
|
||||
new_template.m_ped_proofs[i] = false;
|
||||
new_template.m_stay_in_veh = 0;
|
||||
new_template.m_spawn_behind_same_velocity = 0;
|
||||
new_template.m_disperse = 0;
|
||||
new_template.m_spawn_ahead = 0;
|
||||
new_template.m_favour_roads = 0;
|
||||
new_template.m_max_vehicle = 0;
|
||||
});
|
||||
|
||||
ImGui::EndGroup();
|
||||
@ -250,6 +252,12 @@ namespace big
|
||||
{
|
||||
ImGui::BeginGroup(); //Toggleables
|
||||
|
||||
ImGui::Checkbox("Spawn ahead", &new_template.m_spawn_ahead);
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Will use the distance specified and apply it in a forward direction to find a position ahead of the target");
|
||||
ImGui::Checkbox("Favour roads", &new_template.m_favour_roads);
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Will try and find a road first");
|
||||
ImGui::Checkbox("Disperse", &new_template.m_disperse);
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("If the squad is on foot, will scatter units within the spawn distance");
|
||||
@ -257,6 +265,12 @@ namespace big
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Will spawn the mobile squad behind the target with identical velocity if applicable.\nOnly for squads with a vehicle.");
|
||||
ImGui::Checkbox("Stay In Vehicle", &new_template.m_stay_in_veh);
|
||||
ImGui::Checkbox("Vehicle mods maxed", &new_template.m_max_vehicle);
|
||||
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::Checkbox("Ped God Mode", &new_template.m_ped_invincibility);
|
||||
ImGui::Checkbox("Vehicle God Mode", &new_template.m_veh_invincibility);
|
||||
ImGui::Checkbox("Headshot Proof", &new_template.m_ped_proofs[0]);
|
||||
@ -268,6 +282,7 @@ namespace big
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginGroup(); //Slideables
|
||||
|
||||
ImGui::PushItemWidth(200);
|
||||
ImGui::Text("Ped Health");
|
||||
ImGui::SliderFloat("##pedhealth", &new_template.m_ped_health, 100, 2000);
|
||||
@ -293,6 +308,19 @@ namespace big
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
ImGui::Text("Persistent vehicle");
|
||||
if (ImGui::BeginCombo("##persistent_vehicle", new_template.m_persistent_vehicle.data()))
|
||||
{
|
||||
if (ImGui::Selectable("None", new_template.m_persistent_vehicle == "None"))
|
||||
new_template.m_persistent_vehicle = "None";
|
||||
for (auto& p : persist_car_service::list_files())
|
||||
{
|
||||
if (ImGui::Selectable(p.data(), p == new_template.m_persistent_vehicle))
|
||||
new_template.m_persistent_vehicle = p;
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::EndGroup();
|
||||
|
||||
@ -334,12 +362,43 @@ namespace big
|
||||
};
|
||||
|
||||
components::button("Spawn Squad", [] {
|
||||
try{
|
||||
|
||||
if (check_validity(false))
|
||||
g_squad_spawner_service.spawn_squad({new_template.m_name, new_template.m_ped_model, new_template.m_weapon_model, new_template.m_vehicle_model, new_template.m_squad_size, new_template.m_ped_invincibility, new_template.m_veh_invincibility, new_template.m_ped_proofs, new_template.m_ped_health, new_template.m_ped_armor, new_template.m_spawn_distance, new_template.m_ped_accuracy, new_template.m_spawn_distance_mode, new_template.m_combat_ability_level, new_template.m_stay_in_veh, new_template.m_spawn_behind_same_velocity, new_template.m_description, new_template.m_disperse},
|
||||
g_squad_spawner_service.spawn_squad({
|
||||
new_template.m_name,
|
||||
new_template.m_ped_model,
|
||||
new_template.m_weapon_model,
|
||||
new_template.m_vehicle_model,
|
||||
new_template.m_squad_size,
|
||||
new_template.m_ped_invincibility,
|
||||
new_template.m_veh_invincibility,
|
||||
new_template.m_ped_proofs,
|
||||
new_template.m_ped_health,
|
||||
new_template.m_ped_armor,
|
||||
new_template.m_spawn_distance,
|
||||
new_template.m_ped_accuracy,
|
||||
new_template.m_spawn_distance_mode,
|
||||
new_template.m_combat_ability_level,
|
||||
new_template.m_stay_in_veh,
|
||||
new_template.m_spawn_behind_same_velocity,
|
||||
new_template.m_description,
|
||||
new_template.m_disperse,
|
||||
new_template.m_spawn_ahead,
|
||||
new_template.m_favour_roads,
|
||||
new_template.m_max_vehicle,
|
||||
new_template.m_persistent_vehicle},
|
||||
victim,
|
||||
false,
|
||||
{});
|
||||
new_template.m_spawn_distance_mode == eSquadSpawnDistance::CUSTOM,
|
||||
g_orbital_drone_service.m_ground_pos);
|
||||
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
LOG(WARNING) << "Exception while spawning squad " << e.what();
|
||||
}
|
||||
});
|
||||
|
||||
ImGui::SameLine();
|
||||
components::button("Save", [] {
|
||||
if (check_validity(true) && !check_if_exists(new_template.m_name))
|
||||
|
Reference in New Issue
Block a user