TmpMenu/src/views/world/view_squad_spawner.cpp

349 lines
12 KiB
C++
Raw Normal View History

2023-04-23 17:23:00 +02:00
#include "services/gta_data/gta_data_service.hpp"
#include "services/squad_spawner/squad_spawner.hpp"
#include "misc/cpp/imgui_stdlib.h"
#include "views/view.hpp"
namespace big
{
void view::squad_spawner()
{
const char* const spawn_distance_modes[5]{"Custom", "On target", "Closeby", "Moderately distanced", "Far away"};
const char* const combat_ability_levels[3]{"Poor", "Average", "Professional"};
static squad new_template{};
static player_ptr victim = g_player_service->get_selected();
ImGui::Text("Victim");
ImGui::SetNextItemWidth(200);
if (ImGui::BeginCombo("##victim", victim->get_name()))
{
auto self = g_player_service->get_self();
if (ImGui::Selectable(self->get_name(), self->id() == victim->id()))
victim = self;
for (auto p : g_player_service->players() | std::ranges::views::values)
{
if (ImGui::Selectable(p->get_name(), p->id() == victim->id()))
{
victim = p;
if (g.player.spectating)
g_player_service->set_selected(victim);
}
}
ImGui::EndCombo();
}
ImGui::SameLine();
if (ImGui::Checkbox("SPECTATE"_T.data(), &g.player.spectating))
{
g_player_service->set_selected(victim);
};
if (victim->id() != g_player_service->get_selected()->id() && victim->is_valid())
{
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.5f, 0.3f, 1.0f));
ImGui::Text("Warning: Victim and selected player are not the same");
ImGui::PopStyleColor();
}
ImGui::Separator();
static squad deletion_squad;
if (!std::string(deletion_squad.m_name).empty())
ImGui::OpenPopup("##deletesquad");
if (ImGui::BeginPopupModal("##deletesquad"))
{
ImGui::Text("Are you sure you want to delete %s?", deletion_squad.m_name);
if (ImGui::Button("Yes"))
{
g_squad_spawner_service.delete_squad(deletion_squad);
deletion_squad.m_name = "";
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("No"))
{
deletion_squad.m_name = "";
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
ImGui::SetNextItemWidth(200);
if (ImGui::BeginCombo("Choose From Templates", "Templates"))
{
components::button("Fetch Custom Squads", [] {
g_squad_spawner_service.fetch_squads();
});
for (auto& temp : g_squad_spawner_service.m_templates)
{
if (ImGui::Selectable(temp.m_name.data()))
{
if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
{
deletion_squad = temp;
}
else
{
new_template = temp;
}
}
if (ImGui::IsItemHovered() && temp.does_squad_have_description())
ImGui::SetTooltip(temp.m_description.data());
}
ImGui::EndCombo();
}
ImGui::Separator();
ImGui::BeginGroup(); //Main variables
ImGui::Text("Squad Details");
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);
auto ped_found = std::find_if(g_gta_data_service->peds().begin(), g_gta_data_service->peds().end(), [=](const auto& pair) {
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 (ImGui::ListBoxHeader("##pedlist", ImVec2(250, 200)))
{
for (auto& p : g_gta_data_service->peds() | std::ranges::views::values)
{
std::string p_model = p.m_name;
std::string filter = new_template.m_ped_model;
std::transform(p_model.begin(), p_model.end(), p_model.begin(), ::tolower);
std::transform(filter.begin(), filter.end(), filter.begin(), ::tolower);
if (p_model.find(filter) != std::string::npos && ImGui::Selectable(p.m_name))
{
new_template.m_ped_model = p.m_name;
}
}
ImGui::ListBoxFooter();
}
}
components::input_text_with_hint("##vehmodel",
"Vehicle model",
&new_template.m_vehicle_model);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Leave empty to spawn on foot");
auto veh_found = std::find_if(g_gta_data_service->vehicles().begin(), g_gta_data_service->vehicles().end(), [=](const auto& pair) {
return pair.second.m_name == new_template.m_vehicle_model;
});
if (!new_template.m_vehicle_model.empty() && veh_found == g_gta_data_service->vehicles().end())
{
if (ImGui::ListBoxHeader("##vehlist", ImVec2(250, 200)))
{
for (auto& p : g_gta_data_service->vehicles() | std::ranges::views::values)
{
std::string p_model = p.m_name;
std::string filter = new_template.m_vehicle_model;
std::transform(p_model.begin(), p_model.end(), p_model.begin(), ::tolower);
std::transform(filter.begin(), filter.end(), filter.begin(), ::tolower);
if (p_model.find(filter) != std::string::npos && ImGui::Selectable(p.m_name))
{
new_template.m_vehicle_model = p.m_name;
}
}
ImGui::ListBoxFooter();
}
}
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");
auto weap_found = std::find_if(g_gta_data_service->weapons().begin(), g_gta_data_service->weapons().end(), [=](const auto& pair) {
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 (ImGui::ListBoxHeader("##weaplist", ImVec2(250, 200)))
{
for (auto& p : g_gta_data_service->weapons() | std::ranges::views::values)
{
std::string p_model = p.m_name;
std::string filter = new_template.m_weapon_model;
std::transform(p_model.begin(), p_model.end(), p_model.begin(), ::tolower);
std::transform(filter.begin(), filter.end(), filter.begin(), ::tolower);
if (p_model.find(filter) != std::string::npos && ImGui::Selectable(p.m_name))
{
new_template.m_weapon_model = p.m_name;
}
}
ImGui::ListBoxFooter();
}
}
ImGui::Spacing();
ImGui::Text("Spawn Distance");
if (ImGui::BeginCombo("##spawndistance", spawn_distance_modes[(int)new_template.m_spawn_distance_mode]))
{
for (int i = 0; i < 5; i++)
{
if (ImGui::Selectable(spawn_distance_modes[i], (int)new_template.m_spawn_distance_mode == i))
new_template.m_spawn_distance_mode = (eSquadSpawnDistance)i;
}
ImGui::EndCombo();
}
ImGui::Text("Squad Size");
ImGui::SliderInt("##squadsize", &new_template.m_squad_size, 1, 8);
ImGui::PopItemWidth();
ImGui::EndGroup();
ImGui::SameLine();
ImGui::BeginGroup(); //General actions
ImGui::Text("Actions");
ImGui::Spacing();
components::button(std::string("Terminate " + std::to_string(g_squad_spawner_service.m_active_squads.size()) + " squads"), [] {
g_squad_spawner_service.terminate_squads();
});
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;
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;
});
ImGui::EndGroup();
ImGui::Spacing();
if (ImGui::TreeNode("Advanced Options"))
{
ImGui::BeginGroup(); //Toggleables
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");
ImGui::Checkbox("Vehicle catch up", &new_template.m_spawn_behind_same_velocity);
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("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]);
ImGui::Checkbox("Bullet Proof", &new_template.m_ped_proofs[1]);
ImGui::Checkbox("Flame Proof", &new_template.m_ped_proofs[2]);
ImGui::Checkbox("Melee Proof", &new_template.m_ped_proofs[3]);
ImGui::Checkbox("Explosion Proof", &new_template.m_ped_proofs[4]);
ImGui::EndGroup();
ImGui::SameLine();
ImGui::BeginGroup(); //Slideables
ImGui::PushItemWidth(200);
ImGui::Text("Ped Health");
ImGui::SliderFloat("##pedhealth", &new_template.m_ped_health, 100, 2000);
ImGui::Text("Ped Armor");
ImGui::SliderFloat("##pedarmor", &new_template.m_ped_armor, 0, 2000);
ImGui::Text("Ped Accuracy");
ImGui::SliderFloat("##pedaccuracy", &new_template.m_ped_accuracy, 0, 100);
ImGui::Text("Custom Spawn Distance");
ImGui::SliderFloat("##customspawndistance", &new_template.m_spawn_distance, 10, 500);
ImGui::EndGroup();
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Leave these values at 0 to default, except for accuracy.");
ImGui::SameLine();
ImGui::BeginGroup(); //Chooseables
ImGui::Text("Combat Ability");
if (ImGui::BeginCombo("##combatability", combat_ability_levels[(int)new_template.m_combat_ability_level]))
{
for (int i = 0; i < 3; i++)
{
if (ImGui::Selectable(combat_ability_levels[i], (int)new_template.m_combat_ability_level == i))
new_template.m_combat_ability_level = (eCombatAbilityLevel)i;
}
ImGui::EndCombo();
}
ImGui::PopItemWidth();
ImGui::EndGroup();
components::input_text_with_hint("##new_template.m_description",
"Squad new_template.m_description",
&new_template.m_description);
ImGui::TreePop();
}
static auto check_validity = [=](bool save) -> bool {
if (!victim->is_valid() && !save)
{
g_notification_service->push_error("Squad spawner", "Choose a victim first");
return false;
}
if (std::string(new_template.m_ped_model).empty())
{
g_notification_service->push_error("Squad spawner", "A ped model is required");
return false;
}
return true;
};
static auto check_if_exists = [=](std::string squad_name) -> bool {
bool exists = false;
for (auto& s : g_squad_spawner_service.m_templates)
{
if (s.m_name.compare(squad_name) == 0)
{
exists = true;
break;
}
}
return exists;
};
components::button("Spawn Squad", [] {
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},
victim,
false,
{});
});
ImGui::SameLine();
components::button("Save", [] {
if (check_validity(true) && !check_if_exists(new_template.m_name))
g_squad_spawner_service.save_squad(new_template);
});
}
}