Fixed Weapons JSON not properly using the most recent meta file. (#3550)

* Added ability to resolve WCT_INVALID attachments at runtime from the achievement_controller script, such as the game does.

* Improved component information extraction to also retrieve the descriptions from the scripts.
Redesigned Ammunation to now only display proper components.
Added a tooltip of the component description to Ammunation.

* Refactored script_function::call to fail gracefully if called out of lockstep when the scripts are running.
This commit is contained in:
gir489 2024-08-10 19:14:15 -04:00 committed by GitHub
parent b18ac64905
commit 5461455809
3 changed files with 74 additions and 16 deletions

View File

@ -30,10 +30,18 @@ namespace big
{ {
auto thread = gta_util::find_script_thread(m_script); auto thread = gta_util::find_script_thread(m_script);
auto program = gta_util::find_script_program(m_script); auto program = gta_util::find_script_program(m_script);
auto ip = get_ip(program);
if (!thread || !program || !ip) if (!thread || !program)
{
LOG(FATAL) << m_name << " failed to find its associated script running.";
return Ret(); return Ret();
}
auto ip = get_ip(program);
if (!ip)
{
return Ret();
}
auto tls_ctx = rage::tlsContext::get(); auto tls_ctx = rage::tlsContext::get();
auto stack = (uint64_t*)thread->m_stack; auto stack = (uint64_t*)thread->m_stack;
@ -70,5 +78,7 @@ namespace big
inline script_function reset_session_data("RSD", "main_persistent"_J, "2D 02 7D 00 00"); inline script_function reset_session_data("RSD", "main_persistent"_J, "2D 02 7D 00 00");
inline script_function add_clan_logo_to_vehicle("ACLTV", "main_persistent"_J, "2D 02 04 00 00 5D ? ? ? 61"); inline script_function add_clan_logo_to_vehicle("ACLTV", "main_persistent"_J, "2D 02 04 00 00 5D ? ? ? 61");
inline script_function vehicle_cannot_accept_clan_logo("CVACL", "main_persistent"_J, "2D 01 03 00 00 2C 01 00 A1 06 ? 04"); inline script_function vehicle_cannot_accept_clan_logo("CVACL", "main_persistent"_J, "2D 01 03 00 00 2C 01 00 A1 06 ? 04");
inline script_function get_component_name_string("GCNS", "mp_weapons"_J, "2D 02 43 00 00 38 01");
inline script_function get_component_desc_string("GCDS", "mp_weapons"_J, "2D 02 43 00 00 38 00");
} }
} }

View File

@ -256,9 +256,12 @@ namespace big
hash_array mapped_weapons; hash_array mapped_weapons;
hash_array mapped_components; hash_array mapped_components;
int mp_weapons_thread_id = 0;
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::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 {
@ -307,7 +310,7 @@ namespace big
} }
else if (const auto file_str = path.string(); file_str.find("weaponcomponents") != std::string::npos && path.extension() == ".meta") else if (const auto file_str = path.string(); file_str.find("weaponcomponents") != std::string::npos && path.extension() == ".meta")
{ {
rpf_wrapper.read_xml_file(path, [&exists, &weapon_components, &mapped_components](pugi::xml_document& doc) { rpf_wrapper.read_xml_file(path, [&exists, &weapon_components, &mapped_components, &mp_weapons_thread_id](pugi::xml_document& doc) {
const auto& items = doc.select_nodes("/CWeaponComponentInfoBlob/Infos/*[self::Item[@type='CWeaponComponentInfo'] or self::Item[@type='CWeaponComponentFlashLightInfo'] or self::Item[@type='CWeaponComponentScopeInfo'] or self::Item[@type='CWeaponComponentSuppressorInfo'] or self::Item[@type='CWeaponComponentVariantModelInfo'] or self::Item[@type='CWeaponComponentClipInfo']]"); const auto& items = doc.select_nodes("/CWeaponComponentInfoBlob/Infos/*[self::Item[@type='CWeaponComponentInfo'] or self::Item[@type='CWeaponComponentFlashLightInfo'] or self::Item[@type='CWeaponComponentScopeInfo'] or self::Item[@type='CWeaponComponentSuppressorInfo'] or self::Item[@type='CWeaponComponentVariantModelInfo'] or self::Item[@type='CWeaponComponentClipInfo']]");
for (const auto& item_node : items) for (const auto& item_node : items)
{ {
@ -315,7 +318,7 @@ namespace big
const std::string name = item.child("Name").text().as_string(); const std::string name = item.child("Name").text().as_string();
const auto hash = rage::joaat(name); const auto hash = rage::joaat(name);
if (!name.starts_with("COMPONENT")) if (!name.starts_with("COMPONENT") || name.ends_with("MK2_UPGRADE"))
{ {
continue; continue;
} }
@ -329,9 +332,49 @@ namespace big
std::string LocName = item.child("LocName").text().as_string(); std::string LocName = item.child("LocName").text().as_string();
std::string LocDesc = item.child("LocDesc").text().as_string(); std::string LocDesc = item.child("LocDesc").text().as_string();
if (LocName.ends_with("INVALID") || LocName.ends_with("RAIL")) if (LocName.ends_with("RAIL"))
{
continue; continue;
if (LocName.ends_with("INVALID"))
{
constexpr Hash script_hash = "MP_Weapons"_J;
if (!SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(script_hash))
{
while (!SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED(script_hash))
{
SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH(script_hash);
script::get_current()->yield(10ms);
}
mp_weapons_thread_id = SYSTEM::START_NEW_SCRIPT_WITH_NAME_HASH(script_hash, 1424);
auto thread = gta_util::find_script_thread_by_id(mp_weapons_thread_id);
if (thread)
thread->m_context.m_state = rage::eThreadState::unk_3;
else
LOG(FATAL) << "Failed to find MP_Weapons script!";
SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED(script_hash);
}
Hash weapon_hash = 0;
if (name.starts_with("COMPONENT_KNIFE"))
weapon_hash = "WEAPON_KNIFE"_J;
else if (name.starts_with("COMPONENT_KNUCKLE"))
weapon_hash = "WEAPON_KNUCKLE"_J;
else if (name.starts_with("COMPONENT_BAT"))
weapon_hash = "WEAPON_BAT"_J;
const auto display_string = scr_functions::get_component_name_string.call<const char*>(hash, weapon_hash);
if (display_string == nullptr)
continue;
LocName = display_string;
}
if (LocName.ends_with("INVALID"))
continue;
if (LocDesc.ends_with("INVALID"))
{
const auto display_string = scr_functions::get_component_desc_string.call<const char*>(hash, 0);
if (display_string != nullptr)
LocDesc = display_string;
} }
weapon_component component; weapon_component component;
@ -358,9 +401,8 @@ namespace big
if (hash == "WEAPON_BIRD_CRAP"_J) if (hash == "WEAPON_BIRD_CRAP"_J)
continue; continue;
if (exists(mapped_weapons, hash)) if (!exists(mapped_weapons, hash))
continue; mapped_weapons.emplace_back(hash);
mapped_weapons.emplace_back(hash);
const auto human_name_hash = item.child("HumanNameHash").text().as_string(); const auto human_name_hash = item.child("HumanNameHash").text().as_string();
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)
@ -435,7 +477,7 @@ namespace big
weapon.m_hash = hash; weapon.m_hash = hash;
weapons.emplace_back(std::move(weapon)); weapons[hash] = weapon;
skip: skip:
continue; continue;
} }
@ -475,6 +517,11 @@ namespace big
yim_fipackfile::for_each_fipackfile(); yim_fipackfile::for_each_fipackfile();
} }
if (mp_weapons_thread_id != 0)
{
SCRIPT::TERMINATE_THREAD(mp_weapons_thread_id);
}
static bool translate_label = false; static bool translate_label = false;
g_fiber_pool->queue_job([&] { g_fiber_pool->queue_job([&] {
@ -488,7 +535,7 @@ namespace big
} }
for (auto& item : weapons) for (auto& item : weapons)
{ {
item.m_display_name = HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(item.m_display_name.c_str()); item.second.m_display_name = HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(item.second.m_display_name.c_str());
} }
for (auto& item : weapon_components) for (auto& item : weapon_components)
{ {
@ -555,8 +602,8 @@ namespace big
m_weapons_cache.weapon_map.clear(); m_weapons_cache.weapon_map.clear();
for (auto weapon : weapons) for (auto weapon : weapons)
{ {
add_if_not_exists(m_weapon_types, weapon.m_weapon_type); add_if_not_exists(m_weapon_types, weapon.second.m_weapon_type);
m_weapons_cache.weapon_map.insert({weapon.m_name, weapon}); m_weapons_cache.weapon_map.insert({weapon.second.m_name, weapon.second});
} }
m_weapons_cache.weapon_components.clear(); m_weapons_cache.weapon_components.clear();

View File

@ -290,8 +290,7 @@ namespace big
Hash attachment_hash = attachment_component.m_hash; Hash attachment_hash = attachment_component.m_hash;
if (attachment_hash == NULL) if (attachment_hash == NULL)
{ {
attachment_name = attachment; continue;
attachment_hash = rage::joaat(attachment);
} }
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)); std::string display_name = attachment_name.append("##").append(std::to_string(attachment_hash));
@ -300,6 +299,8 @@ namespace big
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())
ImGui::SetTooltip(attachment_component.m_display_desc.c_str());
if (is_selected) if (is_selected)
{ {
ImGui::SetItemDefaultFocus(); ImGui::SetItemDefaultFocus();