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:
@ -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));
|
||||
|
Reference in New Issue
Block a user