Refactor Weapons JSON parser to associate path with recentness (#3565)
* Added a RPF parse hierarchy to ensure the latest weapon file is loaded into the Weapons JSON. * Fixed erroneous attachment descriptions being displayed and persisted to the Weapons JSON. * Fix for components that had empty descriptions.
This commit is contained in:
parent
a1fb2ae6d8
commit
ee69b3b0b9
@ -218,6 +218,27 @@ namespace big
|
|||||||
std::sort(m_weapon_types.begin(), m_weapon_types.end());
|
std::sort(m_weapon_types.begin(), m_weapon_types.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RPFDatafileSource determine_file_type(std::string file_path, std::string_view rpf_filename)
|
||||||
|
{
|
||||||
|
if (file_path.contains("/dlc_patch/"))
|
||||||
|
{
|
||||||
|
return RPFDatafileSource::DLCUPDATE;
|
||||||
|
}
|
||||||
|
else if (rpf_filename == "dlc.rpf")
|
||||||
|
{
|
||||||
|
return RPFDatafileSource::DLC;
|
||||||
|
}
|
||||||
|
else if (rpf_filename == "update.rpf")
|
||||||
|
{
|
||||||
|
return RPFDatafileSource::UPDATE;
|
||||||
|
}
|
||||||
|
else if (rpf_filename == "common.rpf")
|
||||||
|
{
|
||||||
|
return RPFDatafileSource::BASE;
|
||||||
|
}
|
||||||
|
return RPFDatafileSource::UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
inline void parse_ped(std::vector<ped_item>& peds, std::vector<uint32_t>& mapped_peds, pugi::xml_document& doc)
|
inline void parse_ped(std::vector<ped_item>& peds, std::vector<uint32_t>& mapped_peds, pugi::xml_document& doc)
|
||||||
{
|
{
|
||||||
const auto& items = doc.select_nodes("/CPedModelInfo__InitDataList/InitDatas/Item");
|
const auto& items = doc.select_nodes("/CPedModelInfo__InitDataList/InitDatas/Item");
|
||||||
@ -261,7 +282,7 @@ namespace big
|
|||||||
std::vector<ped_item> peds;
|
std::vector<ped_item> peds;
|
||||||
std::vector<vehicle_item> vehicles;
|
std::vector<vehicle_item> vehicles;
|
||||||
//std::vector<weapon_item> weapons;
|
//std::vector<weapon_item> weapons;
|
||||||
std::unordered_map<Hash, weapon_item> weapons;
|
std::unordered_map<Hash, weapon_item_parsed> weapons;
|
||||||
std::vector<weapon_component> weapon_components;
|
std::vector<weapon_component> weapon_components;
|
||||||
|
|
||||||
constexpr auto exists = [](const hash_array& arr, uint32_t val) -> bool {
|
constexpr auto exists = [](const hash_array& arr, uint32_t val) -> bool {
|
||||||
@ -377,6 +398,9 @@ namespace big
|
|||||||
LocDesc = display_string;
|
LocDesc = display_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LocDesc.ends_with("INVALID"))
|
||||||
|
LocDesc.clear();
|
||||||
|
|
||||||
weapon_component component;
|
weapon_component component;
|
||||||
|
|
||||||
component.m_name = name;
|
component.m_name = name;
|
||||||
@ -388,9 +412,9 @@ namespace big
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (const auto file_str = path.string(); file_str.find("weapon") != std::string::npos && path.extension() == ".meta")
|
else if (const auto file_str = path.string(); file_str.contains("weapon") && !file_str.contains("vehicle") && path.extension() == ".meta")
|
||||||
{
|
{
|
||||||
rpf_wrapper.read_xml_file(path, [&exists, &weapons, &mapped_weapons](pugi::xml_document& doc) {
|
rpf_wrapper.read_xml_file(path, [&exists, &weapons, &mapped_weapons, file_str, &rpf_wrapper](pugi::xml_document& doc) {
|
||||||
const auto& items = doc.select_nodes("/CWeaponInfoBlob/Infos/Item/Infos/Item[@type='CWeaponInfo']");
|
const auto& items = doc.select_nodes("/CWeaponInfoBlob/Infos/Item/Infos/Item[@type='CWeaponInfo']");
|
||||||
for (const auto& item_node : items)
|
for (const auto& item_node : items)
|
||||||
{
|
{
|
||||||
@ -408,11 +432,11 @@ namespace big
|
|||||||
if (std::strcmp(human_name_hash, "WT_INVALID") == 0 || std::strcmp(human_name_hash, "WT_VEHMINE") == 0)
|
if (std::strcmp(human_name_hash, "WT_INVALID") == 0 || std::strcmp(human_name_hash, "WT_VEHMINE") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto weapon = weapon_item{};
|
auto weapon = weapon_item_parsed{};
|
||||||
|
|
||||||
weapon.m_name = name;
|
weapon.m_name = name;
|
||||||
|
|
||||||
weapon.m_display_name = human_name_hash;
|
weapon.m_display_name = human_name_hash;
|
||||||
|
weapon.rpf_file_type = determine_file_type(file_str, rpf_wrapper.get_name());
|
||||||
|
|
||||||
auto weapon_flags = std::string(item.child("WeaponFlags").text().as_string());
|
auto weapon_flags = std::string(item.child("WeaponFlags").text().as_string());
|
||||||
|
|
||||||
@ -477,6 +501,14 @@ namespace big
|
|||||||
|
|
||||||
weapon.m_hash = hash;
|
weapon.m_hash = hash;
|
||||||
|
|
||||||
|
if (weapons.contains(hash))
|
||||||
|
{
|
||||||
|
if (weapons[hash].rpf_file_type > weapon.rpf_file_type)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
weapons[hash] = weapon;
|
weapons[hash] = weapon;
|
||||||
skip:
|
skip:
|
||||||
continue;
|
continue;
|
||||||
@ -540,7 +572,12 @@ namespace big
|
|||||||
for (auto& item : weapon_components)
|
for (auto& item : weapon_components)
|
||||||
{
|
{
|
||||||
item.m_display_name = HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(item.m_display_name.c_str());
|
item.m_display_name = HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(item.m_display_name.c_str());
|
||||||
item.m_display_desc = HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(item.m_display_desc.c_str());
|
if (!item.m_display_desc.empty())
|
||||||
|
{
|
||||||
|
item.m_display_desc = HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(item.m_display_desc.c_str());
|
||||||
|
if (item.m_display_desc == "NULL")
|
||||||
|
item.m_display_desc.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (auto it = peds.begin(); it != peds.end();)
|
for (auto it = peds.begin(); it != peds.end();)
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,16 @@
|
|||||||
|
|
||||||
namespace big
|
namespace big
|
||||||
{
|
{
|
||||||
class weapon_item final
|
enum RPFDatafileSource : std::uint8_t
|
||||||
|
{
|
||||||
|
UNKNOWN,
|
||||||
|
BASE,
|
||||||
|
UPDATE,
|
||||||
|
DLC,
|
||||||
|
DLCUPDATE
|
||||||
|
};
|
||||||
|
|
||||||
|
class weapon_item
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
@ -16,4 +25,10 @@ namespace big
|
|||||||
|
|
||||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(weapon_item, m_name, m_display_name, m_weapon_type, m_hash, m_reward_hash, m_reward_ammo_hash, m_attachments, m_throwable)
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(weapon_item, m_name, m_display_name, m_weapon_type, m_hash, m_reward_hash, m_reward_ammo_hash, m_attachments, m_throwable)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class weapon_item_parsed : public weapon_item
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RPFDatafileSource rpf_file_type = RPFDatafileSource::UNKNOWN;
|
||||||
|
};
|
||||||
}
|
}
|
@ -292,19 +292,20 @@ namespace big
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
ImGui::PushID(attachment_hash);
|
||||||
bool is_selected = attachment_hash == selected_weapon_attachment_hash;
|
bool is_selected = attachment_hash == selected_weapon_attachment_hash;
|
||||||
std::string display_name = attachment_name.append("##").append(std::to_string(attachment_hash));
|
if (ImGui::Selectable(attachment_name.c_str(), is_selected, ImGuiSelectableFlags_None))
|
||||||
if (ImGui::Selectable(display_name.c_str(), is_selected, ImGuiSelectableFlags_None))
|
|
||||||
{
|
{
|
||||||
selected_weapon_attachment = attachment_name;
|
selected_weapon_attachment = attachment_name;
|
||||||
selected_weapon_attachment_hash = attachment_hash;
|
selected_weapon_attachment_hash = attachment_hash;
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered() && !attachment_component.m_display_desc.empty())
|
||||||
ImGui::SetTooltip(attachment_component.m_display_desc.c_str());
|
ImGui::SetTooltip(attachment_component.m_display_desc.c_str());
|
||||||
if (is_selected)
|
if (is_selected)
|
||||||
{
|
{
|
||||||
ImGui::SetItemDefaultFocus();
|
ImGui::SetItemDefaultFocus();
|
||||||
}
|
}
|
||||||
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user