#pragma once
#include <algorithm>
#include <atomic>
#include <cctype>
#include <cstring>
#include <functional>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

#include "../il2cpp/unity.h"
#include "../il2cpp/il2utils.h"
#include "../il2cpp/Il2CppObjectInstance.h"
namespace eft_api
{
    inline bool is_bot_corpse_loot(Il2CppObject* loot_obj, Il2CppObject* item_obj);

    enum class npc_kind : char
    {
        pmc,
        scav,
        boss,
        guard,
        cultist,
        raider,
        defector,
        black_division,
        btr,
    };

    inline constexpr int wild_spawn_shooter_btr = 46;
    inline constexpr int wild_spawn_black_division = 68;
    inline constexpr int wild_spawn_boss_bully_black_div = 77;
    inline constexpr int wild_spawn_follower_bully_black_div = 78;
    inline constexpr int wild_spawn_pmc_bot_black_div = 79;

    inline Il2CppObject* try_get_field_object(Il2CppObject* obj, const char* field_name)
    {
        if (!obj || !obj->klass) return nullptr;
        const FieldInfo* field = il2utils::resolve_field(obj->klass, field_name);
        if (!field) return nullptr;
        return *reinterpret_cast<Il2CppObject**>(reinterpret_cast<UINT64>(obj) + field->offset);
    }

    inline int try_get_field_int(Il2CppObject* obj, const char* field_name)
    {
        if (!obj || !obj->klass) return -1;
        const FieldInfo* field = il2utils::resolve_field(obj->klass, field_name);
        if (!field) return -1;
        return *reinterpret_cast<int*>(reinterpret_cast<UINT64>(obj) + field->offset);
    }

    inline int get_profile_side(Il2CppObject* profile)
    {
        Il2CppObject* info = try_get_field_object(profile, "Info");
        if (!info) return -1;
        return try_get_field_int(info, "Side");
    }

    inline int get_wild_spawn_role(Il2CppObject* profile)
    {
        if (!profile) return -1;

        Il2CppObject* info = try_get_field_object(profile, "Info");
        if (!info) return -1;

        Il2CppObject* settings = try_get_field_object(info, "Settings");
        if (!settings) settings = try_get_field_object(info, "<Settings>k__BackingField");
        if (!settings) settings = try_get_field_object(info, "profileInfoSettingsClass");
        if (!settings) return -1;

        return try_get_field_int(settings, "Role");
    }

    struct health_value
    {
        float current = 0.f;
        float maximum = 0.f;
    };

    // EFT.HealthSystem.ValueStruct — dump-verified 20 bytes
    struct value_struct
    {
        float current = 0.f;
        float maximum = 0.f;
        float minimum = 0.f;
        float over_damage_received_multiplier = 0.f;
        float environment_damage_multiplier = 0.f;
    };

    struct player_label
    {
        std::wstring prefix_wide;
        std::string prefix_utf8;
        std::string name_utf8;
        std::wstring text_wide;
        std::string text_utf8;
        bool show_name_line = false;
        npc_kind kind = npc_kind::scav;
    };

    inline std::string wstring_to_utf8(const std::wstring& input)
    {
        if (input.empty()) return {};
        const int size = WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()),
                                             nullptr, 0, nullptr, nullptr);
        if (size <= 0) return {};
        std::string out(static_cast<size_t>(size), '\0');
        WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()),
                            out.data(), size, nullptr, nullptr);
        return out;
    }

    static std::unordered_map<wchar_t, std::string> converted_letters =
    {
        {L'\u0430', "a"}, {L'\u0431', "b"}, {L'\u0432', "v"}, {L'\u0433', "g"}, {L'\u0434', "d"},
        {L'\u0435', "e"}, {L'\u0451', "yo"}, {L'\u0436', "zh"}, {L'\u0437', "z"}, {L'\u0438', "i"},
        {L'\u0439', "j"}, {L'\u043a', "k"}, {L'\u043b', "l"}, {L'\u043c', "m"}, {L'\u043d', "n"},
        {L'\u043e', "o"}, {L'\u043f', "p"}, {L'\u0440', "r"}, {L'\u0441', "s"}, {L'\u0442', "t"},
        {L'\u0443', "u"}, {L'\u0444', "f"}, {L'\u0445', "h"}, {L'\u0446', "c"}, {L'\u0447', "ch"},
        {L'\u0448', "sh"}, {L'\u0449', "sch"}, {L'\u044a', "j"}, {L'\u044b', "i"}, {L'\u044c', "j"},
        {L'\u044d', "e"}, {L'\u044e', "yu"}, {L'\u044f', "ya"},
        {L'\u0410', "A"}, {L'\u0411', "B"}, {L'\u0412', "V"}, {L'\u0413', "G"}, {L'\u0414', "D"},
        {L'\u0415', "E"}, {L'\u0401', "Yo"}, {L'\u0416', "Zh"}, {L'\u0417', "Z"}, {L'\u0418', "I"},
        {L'\u0419', "J"}, {L'\u041a', "K"}, {L'\u041b', "L"}, {L'\u041c', "M"}, {L'\u041d', "N"},
        {L'\u041e', "O"}, {L'\u041f', "P"}, {L'\u0420', "R"}, {L'\u0421', "S"}, {L'\u0422', "T"},
        {L'\u0423', "U"}, {L'\u0424', "F"}, {L'\u0425', "H"}, {L'\u0426', "C"}, {L'\u0427', "Ch"},
        {L'\u0428', "Sh"}, {L'\u0429', "Sch"}, {L'\u042a', "J"}, {L'\u042b', "I"}, {L'\u042c', "J"},
        {L'\u042d', "E"}, {L'\u042e', "Yu"}, {L'\u042f', "Ya"},
        {L'\u03b1', "a"}, {L'\u03b2', "b"}, {L'\u03b3', "g"}, {L'\u03b4', "d"}, {L'\u03b5', "e"},
        {L'\u03b6', "z"}, {L'\u03b7', "i"}, {L'\u03b8', "th"}, {L'\u03b9', "i"}, {L'\u03ba', "k"},
        {L'\u03bb', "l"}, {L'\u03bc', "m"}, {L'\u03bd', "n"}, {L'\u03be', "x"}, {L'\u03bf', "o"},
        {L'\u03c0', "p"}, {L'\u03c1', "r"}, {L'\u03c2', "s"}, {L'\u03c3', "s"}, {L'\u03c4', "t"},
        {L'\u03c5', "y"}, {L'\u03c6', "f"}, {L'\u03c7', "ch"}, {L'\u03c8', "ps"}, {L'\u03c9', "o"},
        {L'\u0391', "A"}, {L'\u0392', "B"}, {L'\u0393', "G"}, {L'\u0394', "D"}, {L'\u0395', "E"},
        {L'\u0396', "Z"}, {L'\u0397', "I"}, {L'\u0398', "Th"}, {L'\u0399', "I"}, {L'\u039a', "K"},
        {L'\u039b', "L"}, {L'\u039c', "M"}, {L'\u039d', "N"}, {L'\u039e', "X"}, {L'\u039f', "O"},
        {L'\u03a0', "P"}, {L'\u03a1', "R"}, {L'\u03a3', "S"}, {L'\u03a4', "T"}, {L'\u03a5', "Y"},
        {L'\u03a6', "F"}, {L'\u03a7', "Ch"}, {L'\u03a8', "Ps"}, {L'\u03a9', "O"}
    };

    inline std::string to_display_utf8(const std::wstring& input)
    {
        return wstring_to_utf8(input);
    }

    inline std::string to_display_utf8(const Il2CppString* str)
    {
        if (!str) return {};
        return wstring_to_utf8(il2utils::conv_wstring(str));
    }

    inline std::string to_english(const std::wstring& input)
    {
        std::stringstream out;
        for (const wchar_t c : input)
        {
            if (converted_letters.contains(c))
            {
                out << converted_letters.at(c);
                continue;
            }

            if (c <= 0x7F)
            {
                out << static_cast<char>(c);
                continue;
            }

            wchar_t single[] = { c, L'\0' };
            out << wstring_to_utf8(single);
        }
        return out.str();
    }

    inline bool wstring_contains(const std::wstring& haystack, const wchar_t* needle)
    {
        return haystack.find(needle) != std::wstring::npos;
    }

    struct wild_spawn_api
    {
        bool ready = false;
        bool(*is_boss)(int) = nullptr;
        bool(*is_follower)(int) = nullptr;
        bool(*is_ex_usec)(int) = nullptr;
        bool(*is_vsrf)(int) = nullptr;
        bool(*is_pmc_bot)(int) = nullptr;
        bool(*is_sectant)(int) = nullptr;
        Il2CppString*(*get_scav_role_key)(int) = nullptr;
        Il2CppString*(*localized)(Il2CppString*, int) = nullptr;
    };

    inline wild_spawn_api& wild_spawn_methods()
    {
        static wild_spawn_api api{};
        if (api.ready) return api;

        static auto* assembly = il2utils::resolve_image("Assembly-CSharp.dll");
        if (!assembly) return api;

        if (const Il2CppClass* ext = il2utils::resolve_class(assembly, "", "WildSpawnTypeExtension"))
        {
            api.is_boss = il2utils::get_method<bool(*)(int)>(ext, "IsBoss", 1);
            api.is_follower = il2utils::get_method<bool(*)(int)>(ext, "IsFollower", 1);
            api.is_ex_usec = il2utils::get_method<bool(*)(int)>(ext, "IsExUsec", 1);
            api.is_vsrf = il2utils::get_method<bool(*)(int)>(ext, "IsVSRF", 1);
            api.is_pmc_bot = il2utils::get_method<bool(*)(int)>(ext, "IsPmcBot", 1);
            api.is_sectant = il2utils::get_method<bool(*)(int)>(ext, "IsSectant", 1);
            api.get_scav_role_key = il2utils::get_method<Il2CppString*(*)(int)>(ext, "GetScavRoleKey", 1);
        }

        if (const Il2CppClass* loc = il2utils::resolve_class(assembly, "EFT", "LocalizationExtensions"))
            api.localized = il2utils::get_method<Il2CppString*(*)(Il2CppString*, int)>(loc, "Localized", 2);

        api.ready = api.get_scav_role_key != nullptr && api.localized != nullptr;
        return api;
    }

    inline bool is_black_division_role(const int role)
    {
        return role == wild_spawn_black_division
            || role == wild_spawn_boss_bully_black_div
            || role == wild_spawn_follower_bully_black_div
            || role == wild_spawn_pmc_bot_black_div;
    }

    inline bool is_boss_role(const int role)
    {
        if (role < 0) return false;
        const wild_spawn_api& api = wild_spawn_methods();
        if (api.is_boss) return api.is_boss(role);
        return false;
    }

    inline bool is_follower_role(const int role)
    {
        if (role < 0) return false;
        const wild_spawn_api& api = wild_spawn_methods();
        if (api.is_follower) return api.is_follower(role);
        return false;
    }

    inline npc_kind classify_wild_spawn_role(const int role)
    {
        if (role < 0) return npc_kind::scav;
        if (role == wild_spawn_shooter_btr) return npc_kind::btr;
        if (is_black_division_role(role)) return npc_kind::black_division;

        const wild_spawn_api& api = wild_spawn_methods();
        if (api.is_vsrf && api.is_vsrf(role)) return npc_kind::defector;
        if (api.is_ex_usec && api.is_ex_usec(role)) return npc_kind::raider;
        if (api.is_pmc_bot && api.is_pmc_bot(role)) return npc_kind::raider;
        if (api.is_sectant && api.is_sectant(role)) return npc_kind::cultist;
        if (api.is_follower && api.is_follower(role)) return npc_kind::guard;
        if (api.is_boss && api.is_boss(role)) return npc_kind::boss;

        return npc_kind::scav;
    }

    inline std::wstring kind_label_fallback_wide(const npc_kind kind)
    {
        switch (kind)
        {
        case npc_kind::boss: return L"Boss";
        case npc_kind::guard: return L"Guard";
        case npc_kind::cultist: return L"Cultist";
        case npc_kind::raider: return L"Raider";
        case npc_kind::defector: return L"Defector";
        case npc_kind::black_division: return L"Black Division";
        case npc_kind::btr: return L"BTR";
        case npc_kind::scav:
        default: return L"Scav";
        }
    }

    namespace detail
    {
        inline std::unordered_map<int, std::wstring>& role_label_cache()
        {
            static std::unordered_map<int, std::wstring> cache;
            return cache;
        }
    }

    inline std::wstring get_localized_role_label_wide(const int role)
    {
        if (role < 0) return kind_label_fallback_wide(npc_kind::scav);

        auto& cache = detail::role_label_cache();
        if (const auto it = cache.find(role); it != cache.end())
            return it->second;

        std::wstring label = kind_label_fallback_wide(classify_wild_spawn_role(role));
        const wild_spawn_api& api = wild_spawn_methods();
        if (api.get_scav_role_key && api.localized)
        {
            Il2CppString* key = api.get_scav_role_key(role);
            if (key)
            {
                Il2CppString* localized = api.localized(key, 0);
                if (localized)
                {
                    const std::wstring resolved = il2utils::conv_wstring(localized);
                    if (!resolved.empty()) label = resolved;
                }
            }
        }

        cache.emplace(role, label);
        return label;
    }

    inline std::wstring role_tag_wide(const int role)
    {
        return L"[" + get_localized_role_label_wide(role) + L"]";
    }

    inline std::wstring pmc_tag_wide(const int side)
    {
        if (side == 1) return L"[USEC]";
        if (side == 2) return L"[BEAR]";
        return L"[PMC]";
    }

    inline std::wstring format_distance_suffix(const int distance_m)
    {
        wchar_t dist_buf[32];
        swprintf_s(dist_buf, L"[%dm]", distance_m);
        return dist_buf;
    }

    inline void finalize_player_label(player_label& result)
    {
        result.prefix_utf8 = wstring_to_utf8(result.prefix_wide);
        result.text_wide = result.prefix_wide;
        result.text_utf8 = result.prefix_utf8;
    }

    inline bool try_is_btr_by_weapon(Il2CppObject* player_obj);

    inline player_label build_player_label(const bool is_pmc, const std::wstring& nickname_wide,
                                           const int distance_m, const bool show_bot_names,
                                           Il2CppObject* profile_ptr, Il2CppObject* player_obj,
                                           const int side = -1)
    {
        player_label result{};
        const std::wstring dist_suffix = format_distance_suffix(distance_m);
        const int role = profile_ptr ? get_wild_spawn_role(profile_ptr) : -1;

        if (is_pmc)
            result.kind = npc_kind::pmc;
        else if (role == wild_spawn_shooter_btr || try_is_btr_by_weapon(player_obj))
            result.kind = npc_kind::btr;
        else
            result.kind = classify_wild_spawn_role(role);

        if (show_bot_names)
        {
            result.prefix_wide = (is_pmc ? pmc_tag_wide(side) : role_tag_wide(role)) + L" " + dist_suffix;
            result.show_name_line = true;
            result.name_utf8 = to_display_utf8(nickname_wide);
            finalize_player_label(result);
            return result;
        }

        if (is_pmc)
        {
            result.text_utf8 = wstring_to_utf8(pmc_tag_wide(side)) + " "
                + to_display_utf8(nickname_wide) + " " + wstring_to_utf8(dist_suffix);
            result.text_wide = std::wstring(result.text_utf8.begin(), result.text_utf8.end());
            return result;
        }

        result.text_utf8 = wstring_to_utf8(get_localized_role_label_wide(role))
            + " " + wstring_to_utf8(dist_suffix);
        result.text_wide = std::wstring(result.text_utf8.begin(), result.text_utf8.end());
        return result;
    }

    inline bool try_get_head_position(Il2CppObject* player_obj, unity::vector3& out)
    {
        Il2CppObject* body = try_get_field_object(player_obj, "_playerBody");
        if (!body) return false;

        Il2CppObject* bones = try_get_field_object(body, "PlayerBones");
        if (!bones) return false;

        Il2CppObject* head = try_get_field_object(bones, "Head");
        if (!head || !head->klass) return false;

        const MethodInfo* method = il2utils::resolve_method(head->klass, "get_position", 0);
        if (!method || !method->methodPointer) return false;

        out = reinterpret_cast<unity::vector3(*)(Il2CppObject*)>(method->methodPointer)(head);
        return true;
    }

    inline bool try_detect_is_pmc(Il2CppObject* player_obj)
    {
        if (!player_obj || !player_obj->klass) return false;

        Il2CppObject* inventory_controller = try_get_field_object(player_obj, "_inventoryController");
        if (!inventory_controller || !inventory_controller->klass) return false;

        Il2CppObjectInstance ic(inventory_controller);
        const auto get_inventory = ic.get_method<Il2CppObject*(*)(Il2CppObject*)>("get_Inventory", 0);
        if (!get_inventory) return false;

        Il2CppObject* inventory = get_inventory(inventory_controller);
        if (!inventory || !inventory->klass) return false;

        Il2CppObject* equipment = try_get_field_object(inventory, "Equipment");
        if (!equipment || !equipment->klass) return false;

        Il2CppObjectInstance eq(equipment);
        const auto get_slot = eq.get_method<Il2CppObject*(*)(Il2CppObject*, int)>("GetSlot", 1);
        if (!get_slot) return false;

        Il2CppObject* slot = get_slot(equipment, 13);
        if (!slot || !slot->klass) return false;

        Il2CppObjectInstance slot_inst(slot);
        const auto get_item = slot_inst.get_method<Il2CppObject*(*)(Il2CppObject*)>("get_ContainedItem", 0);
        if (!get_item) return false;

        return get_item(slot) != nullptr;
    }

    inline Il2CppObject* try_get_health_controller(Il2CppObject* player_obj)
    {
        if (!player_obj || !player_obj->klass) return nullptr;

        Il2CppObjectInstance player(player_obj);
        const auto get_active = player.get_method<Il2CppObject*(*)(Il2CppObject*)>("get_ActiveHealthController", 0);
        if (get_active)
        {
            Il2CppObject* active = get_active(player_obj);
            if (active) return active;
        }

        const auto get_health = player.get_method<Il2CppObject*(*)(Il2CppObject*)>("get_HealthController", 0);
        if (!get_health) return nullptr;
        return get_health(player_obj);
    }

    inline bool is_valid_health_pair(const float current, const float maximum)
    {
        return maximum > 0.01f
            && maximum < 10000.f
            && current >= 0.f
            && current <= maximum * 1.05f;
    }

    inline bool is_valid_health_value(const value_struct& value)
    {
        return is_valid_health_pair(value.current, value.maximum);
    }

    inline bool try_read_health_from_health_value(Il2CppObject* health_value_obj, health_value& out)
    {
        if (!health_value_obj || !health_value_obj->klass) return false;

        Il2CppObjectInstance health_value_instance(health_value_obj);
        const auto get_current = health_value_instance.get_method<float(*)(Il2CppObject*)>("get_Current", 0);
        const auto get_maximum = health_value_instance.get_method<float(*)(Il2CppObject*)>("get_Maximum", 0);
        if (get_current && get_maximum)
        {
            const float current = get_current(health_value_obj);
            const float maximum = get_maximum(health_value_obj);
            if (is_valid_health_pair(current, maximum))
            {
                out.current = current;
                out.maximum = maximum;
                return true;
            }
        }

        const FieldInfo* value_field = il2utils::resolve_field(health_value_obj->klass, "Value");
        if (!value_field) return false;

        const auto* value = reinterpret_cast<const value_struct*>(
            reinterpret_cast<UINT64>(health_value_obj) + value_field->offset);
        if (!is_valid_health_value(*value)) return false;

        out.current = value->current;
        out.maximum = value->maximum;
        return true;
    }

    inline bool try_read_health_from_part_state(Il2CppObject* part_state, health_value& out)
    {
        if (!part_state || !part_state->klass) return false;
        return try_read_health_from_health_value(try_get_field_object(part_state, "Health"), out);
    }

    // Dictionary<EBodyPart, BodyPartState> entry — int key + object value needs 4-byte pad on x64
    struct body_state_dict_entry
    {
        int hash_code;
        int next;
        int key;
        int padding;
        Il2CppObject* part_state;
    };

    inline bool try_is_part_destroyed(Il2CppObject* part_state)
    {
        if (!part_state || !part_state->klass) return false;
        const FieldInfo* field = il2utils::resolve_field(part_state->klass, "IsDestroyed");
        if (!field) return false;
        return *reinterpret_cast<bool*>(reinterpret_cast<UINT64>(part_state) + field->offset);
    }

    inline bool try_read_part_state_health(Il2CppObject* part_state, health_value& out, bool& destroyed)
    {
        destroyed = try_is_part_destroyed(part_state);
        if (!try_read_health_from_part_state(part_state, out))
        {
            if (destroyed)
            {
                out = {};
                return true;
            }
            return false;
        }

        if (out.current <= 0.01f) destroyed = true;
        return true;
    }

    inline bool try_collect_limbs_from_entries(const body_state_dict_entry* entries, const int entry_count,
                                               health_value* parts, bool* destroyed, const int part_count)
    {
        if (!entries || !parts || !destroyed || part_count <= 0) return false;

        bool any = false;
        for (int i = 0; i < entry_count; ++i)
        {
            const auto& entry = entries[i];
            if (entry.hash_code < 0) continue;

            const int part = entry.key;
            if (part < 0 || part >= part_count) continue;

            if (try_read_part_state_health(entry.part_state, parts[part], destroyed[part]))
                any = true;
        }
        return any;
    }

    inline bool try_collect_limbs_from_compact(unity::dict<int, Il2CppObject*>* body_state,
                                             health_value* parts, bool* destroyed, const int part_count)
    {
        if (!body_state || !body_state->m_p_entries || body_state->m_p_entries->max_length == 0)
            return false;

        const int entry_count = static_cast<int>(body_state->m_p_entries->max_length);
        if (entry_count <= 0 || entry_count > 64) return false;

        const auto* entries = body_state->get_entry();
        if (!entries) return false;

        bool any = false;
        for (int i = 0; i < entry_count; ++i)
        {
            const auto& entry = entries[i];
            if (entry.m_i_hash_code < 0) continue;

            const int part = entry.m_t_key;
            if (part < 0 || part >= part_count) continue;

            if (try_read_part_state_health(entry.m_t_value, parts[part], destroyed[part]))
                any = true;
        }
        return any;
    }

    inline bool try_get_limb_health(Il2CppObject* player_obj, health_value* parts, bool* destroyed,
                                    const int part_count = 7)
    {
        if (!player_obj || !parts || !destroyed || part_count <= 0) return false;

        for (int i = 0; i < part_count; ++i)
        {
            parts[i] = {};
            destroyed[i] = false;
        }

        Il2CppObject* health_controller = try_get_health_controller(player_obj);
        if (!health_controller) return false;

        Il2CppObject* body_state_obj = nullptr;
        for (const char* field_name : {"_bodyState", "BodyState", "<BodyState>k__BackingField"})
        {
            body_state_obj = try_get_field_object(health_controller, field_name);
            if (body_state_obj) break;
        }

        if (!body_state_obj || !body_state_obj->klass) return false;

        auto* body_state = reinterpret_cast<unity::dict<int, Il2CppObject*>*>(body_state_obj);
        if (!body_state->m_p_entries || body_state->m_p_entries->max_length == 0) return false;

        const int entry_count = static_cast<int>(body_state->m_p_entries->max_length);
        if (entry_count <= 0 || entry_count > 64) return false;

        const auto* entries = reinterpret_cast<const body_state_dict_entry*>(&body_state->m_p_entries->data);
        if (entries && try_collect_limbs_from_entries(entries, entry_count, parts, destroyed, part_count))
            return true;

        return try_collect_limbs_from_compact(body_state, parts, destroyed, part_count);
    }

    inline bool try_sum_body_state_entries(unity::dict<int, Il2CppObject*>* body_state, health_value& out)
    {
        if (!body_state || !body_state->m_p_entries || body_state->m_p_entries->max_length == 0)
            return false;

        const int entry_count = static_cast<int>(body_state->m_p_entries->max_length);
        if (entry_count <= 0 || entry_count > 64) return false;
        if (body_state->m_i_count < 0 || body_state->m_i_count > entry_count) return false;

        const auto* entries = reinterpret_cast<const body_state_dict_entry*>(&body_state->m_p_entries->data);
        if (!entries) return false;

        float total_current = 0.f;
        float total_maximum = 0.f;

        for (int i = 0; i < entry_count; ++i)
        {
            const auto& entry = entries[i];
            if (entry.hash_code < 0) continue;

            const int part = entry.key;
            Il2CppObject* part_state = entry.part_state;
            if (!part_state) continue;

            health_value part_health{};
            if (!try_read_health_from_part_state(part_state, part_health)) continue;

            if (part == 7)
            {
                out = part_health;
                return true;
            }

            if (part >= 0 && part <= 6)
            {
                total_current += part_health.current;
                total_maximum += part_health.maximum;
            }
        }

        if (!is_valid_health_pair(total_current, total_maximum)) return false;
        out.current = total_current;
        out.maximum = total_maximum;
        return true;
    }

    inline bool try_sum_body_state_entries_compact(unity::dict<int, Il2CppObject*>* body_state, health_value& out)
    {
        if (!body_state || !body_state->m_p_entries || body_state->m_p_entries->max_length == 0)
            return false;

        const int entry_count = static_cast<int>(body_state->m_p_entries->max_length);
        if (entry_count <= 0 || entry_count > 64) return false;

        const auto* entries = body_state->get_entry();
        if (!entries) return false;

        float total_current = 0.f;
        float total_maximum = 0.f;

        for (int i = 0; i < entry_count; ++i)
        {
            const auto& entry = entries[i];
            if (entry.m_i_hash_code < 0) continue;

            health_value part_health{};
            if (!try_read_health_from_part_state(entry.m_t_value, part_health)) continue;

            if (entry.m_t_key == 7)
            {
                out = part_health;
                return true;
            }

            if (entry.m_t_key >= 0 && entry.m_t_key <= 6)
            {
                total_current += part_health.current;
                total_maximum += part_health.maximum;
            }
        }

        if (!is_valid_health_pair(total_current, total_maximum)) return false;
        out.current = total_current;
        out.maximum = total_maximum;
        return true;
    }

    inline bool try_invoke_get_body_part_health(Il2CppObject* health_controller, const int body_part, health_value& out)
    {
        if (!health_controller || !health_controller->klass) return false;

        const MethodInfo* method = il2utils::resolve_method(health_controller->klass, "GetBodyPartHealth", 1);
        if (!method || !method->methodPointer) return false;

        value_struct buffer{};
        using sig = void(*)(Il2CppObject*, value_struct*, int);
        reinterpret_cast<sig>(method->methodPointer)(health_controller, &buffer, body_part);

        if (!is_valid_health_value(buffer)) return false;
        out.current = buffer.current;
        out.maximum = buffer.maximum;
        return true;
    }

    inline bool try_read_health_from_body_state(Il2CppObject* health_controller, health_value& out)
    {
        if (!health_controller || !health_controller->klass) return false;

        Il2CppObject* body_state_obj = nullptr;
        for (const char* field_name : {"_bodyState", "BodyState", "<BodyState>k__BackingField"})
        {
            body_state_obj = try_get_field_object(health_controller, field_name);
            if (body_state_obj) break;
        }

        if (body_state_obj && body_state_obj->klass)
        {
            auto* body_state = reinterpret_cast<unity::dict<int, Il2CppObject*>*>(body_state_obj);
            if (try_sum_body_state_entries(body_state, out)) return true;
            if (try_sum_body_state_entries_compact(body_state, out)) return true;
        }

        constexpr int body_part_common = 7;
        return try_invoke_get_body_part_health(health_controller, body_part_common, out);
    }

    inline bool try_get_player_health(Il2CppObject* player_obj, health_value& out, bool& is_alive)
    {
        if (!player_obj || !player_obj->klass) return false;

        Il2CppObject* health_controller = try_get_health_controller(player_obj);
        if (!health_controller || !health_controller->klass) return false;

        Il2CppObjectInstance hc(health_controller);
        const auto get_is_alive = hc.get_method<bool(*)(Il2CppObject*)>("get_IsAlive", 0);
        if (get_is_alive)
            is_alive = get_is_alive(health_controller);

        if (!is_alive) return false;
        return try_read_health_from_body_state(health_controller, out);
    }
    inline unity::vector3 world_to_screen(Il2CppObject* camera, unity::vector3 world_point, float zoom)
    {
        unity::vector3 screen_point = unity::world_to_screen_point(camera, world_point);
        const float scale = menu::get_height() / static_cast<float>(unity::camera_pixel_height(camera));
        screen_point.y = menu::get_height() - screen_point.y * scale;
        screen_point.x *= scale;

        if (zoom > 1)
        {
            screen_point.x -= menu::get_width() / 2;
            screen_point.y -= menu::get_height() / 2;
            screen_point.x *= zoom;
            screen_point.y *= zoom;
            screen_point.x += menu::get_width() / 2;
            screen_point.y += menu::get_height() / 2;
        }

        return screen_point;
    }

    inline float get_scope_zoom(Il2CppObjectInstance& player)
    {
        Il2CppObject* hands_controller_object = player.get_method<Il2CppObject*(
            *)(Il2CppObject*)>("get_HandsController", 0)(player.get_instance());

        if (hands_controller_object && std::string(hands_controller_object->klass->name) == "FirearmController")
        {
            Il2CppObjectInstance firearm_controller(hands_controller_object);

            if (!firearm_controller.get_method<bool(*)(Il2CppObject*)>("get_IsAiming", 0)(hands_controller_object))
                return 1;

            Il2CppObjectInstance procedural_weapon_animation(
                player.get_method<Il2CppObject*(*)(Il2CppObject*)>("get_ProceduralWeaponAnimation", 0)(
                    player.get_instance()));

            const auto mod_ptr = procedural_weapon_animation.get_method<Il2CppObject*(*)(Il2CppObject*)>(
                "get_CurrentAimingMod", 0)(
                procedural_weapon_animation.get_instance());

            if (!mod_ptr) return 1;

            Il2CppObjectInstance sight_component(mod_ptr);
            const float zoom = sight_component.get_field<float>("ScopeZoomValue");
            auto adjustable_data = Il2CppObjectInstance(
                sight_component.get_method<Il2CppObject*(*)(Il2CppObject*)>("get_AdjustableOpticData", 0)(
                    sight_component.get_instance()));

            // not a magnifying scope
            if (zoom == 0.0f) return 1;

            const auto minmax = adjustable_data.get_field<unity::vector3>("MinMaxFov");

            // calculate the actual zoom by dividing by max fov;
            return minmax.x / zoom;
        }

        return 1;
    }

    inline bool is_visible(const unity::vector3& screen_point)
    {
        return screen_point.z > 0.01f && screen_point.x > -100.0f && screen_point.y > -100.0f && screen_point.x <
            menu::get_width() + 100.0f && screen_point.y < menu::get_height() + 100.0f;
    }

    inline bool is_loot_container_display_name(const std::string& name)
    {
        static const char* names[] = {
            "Toolbox", "Duffle bag", "Wooden ammo box", "Grenade box", "Weapon box",
            "Wooden crate", "Plastic suitcase", "Dead Scav", "Ground cache",
            "Buried barrel cache", "PC block", "Jacket", "Drawer", "Cash register",
            "Medbag SMU06", "Medcase", "Safe", "Technical supply crate",
            "Ration supply crate", "Medical supply crate", "Civilian body",
            "PMC body", "Scav body", "Lab technician body", "Bank safe",
            "Bank cash register", "Shturman's Stash"
        };
        for (const char* entry : names)
        {
            if (name == entry) return true;
        }
        return false;
    }

    inline bool is_readable_address(const void* ptr, const size_t size = 8)
    {
        if (!ptr) return false;

        MEMORY_BASIC_INFORMATION mbi{};
        if (!VirtualQuery(ptr, &mbi, sizeof(mbi))) return false;
        if (mbi.State != MEM_COMMIT) return false;
        if (mbi.Protect & (PAGE_NOACCESS | PAGE_GUARD)) return false;

        const auto base = reinterpret_cast<uintptr_t>(ptr);
        const auto region_end = reinterpret_cast<uintptr_t>(mbi.BaseAddress) + mbi.RegionSize;
        return base + size <= region_end;
    }

    inline bool is_il2cpp_object_likely_valid(Il2CppObject* obj)
    {
        return obj && obj->klass && obj->klass->name;
    }

    inline bool is_il2cpp_object_strict(Il2CppObject* obj)
    {
        if (!is_readable_address(obj, sizeof(Il2CppObject))) return false;
        if (!obj->klass || !is_readable_address(obj->klass, sizeof(Il2CppClass))) return false;
        if (!obj->klass->name || !is_readable_address(obj->klass->name, 1)) return false;
        return true;
    }

    inline std::string try_read_il2cpp_string(Il2CppString* str)
    {
        if (!str || !is_readable_address(str, sizeof(Il2CppString))) return {};
        if (str->length <= 0 || str->length > 512) return {};
        if (!is_readable_address(str->chars, static_cast<size_t>(str->length) * sizeof(wchar_t)))
            return {};
        return to_display_utf8(il2utils::conv_wstring(str));
    }

    inline std::string try_read_string_field(Il2CppObject* obj, const char* field_name)
    {
        if (!is_il2cpp_object_likely_valid(obj)) return {};

        const FieldInfo* field = il2utils::resolve_field(obj->klass, field_name);
        if (!field) return {};

        const UINT64 field_addr = reinterpret_cast<UINT64>(obj) + field->offset;
        if (!is_readable_address(reinterpret_cast<void*>(field_addr), sizeof(Il2CppString*)))
            return {};

        Il2CppString* str = *reinterpret_cast<Il2CppString**>(field_addr);
        return try_read_il2cpp_string(str);
    }

    inline std::wstring get_info_nickname_wide(Il2CppObject* profile)
    {
        Il2CppObject* info = try_get_field_object(profile, "Info");
        if (!info) return {};

        const std::string nickname = try_read_string_field(info, "Nickname");
        if (nickname.empty()) return {};

        return std::wstring(nickname.begin(), nickname.end());
    }

    inline bool weapon_short_name_is_btr(const std::string& short_name)
    {
        if (short_name.empty()) return false;
        return short_name.find("PKTM") != std::string::npos
            || short_name.find("PKP") != std::string::npos
            || short_name.find("KORD") != std::string::npos
            || short_name.find("kord") != std::string::npos;
    }

    inline bool try_is_btr_by_weapon(Il2CppObject* player_obj)
    {
        if (!player_obj || !player_obj->klass) return false;

        Il2CppObjectInstance player(player_obj);
        Il2CppObject* hands_controller = player.get_method<Il2CppObject*(*)(Il2CppObject*)>(
            "get_HandsController", 0)(player_obj);
        if (!hands_controller || !hands_controller->klass) return false;

        const std::string controller_name = hands_controller->klass->name;
        if (controller_name.find("Stationary") != std::string::npos
            || controller_name.find("BTR") != std::string::npos)
            return true;

        Il2CppObject* weapon_item = nullptr;
        if (const MethodInfo* get_item = il2utils::resolve_method(hands_controller->klass, "get_Item", 0))
        {
            using get_item_fn = Il2CppObject*(*)(Il2CppObject*);
            weapon_item = reinterpret_cast<get_item_fn>(get_item->methodPointer)(hands_controller);
        }
        if (!weapon_item)
            weapon_item = try_get_field_object(hands_controller, "Item");
        if (!weapon_item)
            return false;

        Il2CppObjectInstance weapon(weapon_item);
        Il2CppObject* template_obj = weapon.get_method<Il2CppObject*(*)(Il2CppObject*)>(
            "get_Template", 0)(weapon_item);
        if (!template_obj) return false;

        return weapon_short_name_is_btr(try_read_string_field(template_obj, "ShortName"));
    }

    inline bool is_btr_bot(const std::wstring& nickname_wide, const std::wstring& info_nickname_wide,
                           Il2CppObject* player_obj, Il2CppObject* profile_ptr = nullptr)
    {
        if (profile_ptr)
        {
            const int role = get_wild_spawn_role(profile_ptr);
        if (role == wild_spawn_shooter_btr) return true;
        }
        (void)nickname_wide;
        (void)info_nickname_wide;
        return try_is_btr_by_weapon(player_obj);
    }

    inline bool is_lootable_container_class_fast(Il2CppObject* obj)
    {
        if (!is_il2cpp_object_likely_valid(obj)) return false;
        return strstr(obj->klass->name, "LootableContainer") != nullptr;
    }

    inline bool is_lootable_container_object(Il2CppObject* obj)
    {
        return is_lootable_container_class_fast(obj);
    }

    inline bool is_container_object_alive(Il2CppObject* obj)
    {
        if (!is_lootable_container_class_fast(obj)) return false;

        Il2CppObject* game_object = unity::component_get_game_object(obj);
        if (!game_object) return false;

        return unity::gameobject_get_transform(game_object) != nullptr;
    }

    inline bool is_nested_compound_item(Il2CppObject* item_obj)
    {
        if (!is_il2cpp_object_likely_valid(item_obj)) return false;
        const char* class_name = item_obj->klass->name;
        return strstr(class_name, "CompoundItem") != nullptr
            || strstr(class_name, "Inventory") != nullptr;
    }

    inline Il2CppObject* try_get_backing_field_object(Il2CppObject* obj, const char* backing_field,
                                                      const char* plain_field = nullptr)
    {
        Il2CppObject* value = try_get_field_object(obj, backing_field);
        if (!value && plain_field) value = try_get_field_object(obj, plain_field);
        return value;
    }

    inline Il2CppArray* try_get_array_field(Il2CppObject* obj, const char* field_name)
    {
        if (!is_il2cpp_object_likely_valid(obj)) return nullptr;

        const FieldInfo* field = il2utils::resolve_field(obj->klass, field_name);
        if (!field) return nullptr;

        const UINT64 field_addr = reinterpret_cast<UINT64>(obj) + field->offset;
        if (!is_readable_address(reinterpret_cast<void*>(field_addr), sizeof(Il2CppArray*)))
            return nullptr;

        Il2CppArray* arr = *reinterpret_cast<Il2CppArray**>(field_addr);
        if (!arr || !is_readable_address(arr, sizeof(Il2CppArray))) return nullptr;
        if (arr->max_length > 256) return nullptr;
        return arr;
    }

    inline int try_get_list_count(Il2CppObject* list_obj)
    {
        if (!list_obj || !list_obj->klass) return 0;

        const FieldInfo* size_field = il2utils::resolve_field(list_obj->klass, "_size");
        if (size_field)
        {
            const int size = *reinterpret_cast<int*>(reinterpret_cast<UINT64>(list_obj) + size_field->offset);
            if (size >= 0) return size;
        }

        Il2CppObjectInstance list_inst(list_obj);
        const auto get_count = list_inst.get_method<int(*)(Il2CppObject*)>("get_Count", 0);
        if (!get_count) return 0;
        return get_count(list_obj);
    }

    inline void append_list_items(Il2CppObject* list_obj, std::vector<Il2CppObject*>& out,
                                  const int max_items = 128)
    {
        if (!list_obj) return;

        auto* list = reinterpret_cast<unity::list*>(list_obj);
        if (!list || !list->m_p_list_array) return;

        const int count = (std::min)(try_get_list_count(list_obj), max_items);
        const int limit = static_cast<int>(list->m_p_list_array->max_length);
        if (limit <= 0 || limit > 512) return;

        const size_t bytes_needed = static_cast<size_t>(limit) * sizeof(Il2CppObject*);
        if (!is_readable_address(&list->m_p_list_array->data, bytes_needed)) return;

        for (int i = 0; i < count && i < limit; ++i)
        {
            Il2CppObject* item_obj = reinterpret_cast<Il2CppObject**>(&list->m_p_list_array->data)[i];
            if (is_il2cpp_object_likely_valid(item_obj)) out.push_back(item_obj);
        }
    }

    inline void collect_compound_items_recursive(Il2CppObject* compound_item, std::vector<Il2CppObject*>& out,
                                                 const int depth = 0)
    {
        if (!is_il2cpp_object_likely_valid(compound_item) || depth > 3
            || static_cast<int>(out.size()) >= 256) return;

        if (Il2CppArray* grids = try_get_array_field(compound_item, "Grids"))
        {
            const size_t grid_count = (std::min)(grids->max_length, static_cast<size_t>(16));
            for (size_t i = 0; i < grid_count; ++i)
            {
                Il2CppObject* grid = reinterpret_cast<Il2CppObject**>(&grids->data)[i];
                if (!is_il2cpp_object_likely_valid(grid)) continue;

                Il2CppObject* collection = try_get_backing_field_object(
                    grid, "<ItemCollection>k__BackingField", "ItemCollection");
                if (!collection) continue;

                append_list_items(
                    try_get_field_object(collection, "ItemsList"), out, 128);
            }
        }

        if (Il2CppArray* slots = try_get_array_field(compound_item, "Slots"))
        {
            const size_t slot_count = (std::min)(slots->max_length, static_cast<size_t>(32));
            for (size_t i = 0; i < slot_count; ++i)
            {
                Il2CppObject* slot = reinterpret_cast<Il2CppObject**>(&slots->data)[i];
                if (!is_il2cpp_object_likely_valid(slot)) continue;

                Il2CppObject* contained = try_get_backing_field_object(
                    slot, "<ContainedItem>k__BackingField", "ContainedItem");
                if (!is_il2cpp_object_likely_valid(contained)) continue;

                out.push_back(contained);
                if (is_nested_compound_item(contained))
                    collect_compound_items_recursive(contained, out, depth + 1);
            }
        }
    }

    inline Il2CppObject* try_get_container_item_owner(Il2CppObject* container_obj)
    {
        return try_get_field_object(container_obj, "ItemOwner");
    }

    inline Il2CppObject* try_get_controller_root_item(Il2CppObject* item_owner)
    {
        if (!item_owner) return nullptr;

        Il2CppObject* root_item = try_get_field_object(item_owner, "<RootItem>k__BackingField");
        if (root_item) return root_item;

        Il2CppObjectInstance owner_inst(item_owner);
        const auto get_root = owner_inst.get_method<Il2CppObject*(*)(Il2CppObject*)>("get_Root", 0);
        if (get_root) return get_root(item_owner);
        return nullptr;
    }

    inline bool is_lootable_container_valid(Il2CppObject* obj)
    {
        if (!obj || !obj->klass || !obj->klass->name) return false;

        Il2CppObject* item_owner = try_get_container_item_owner(obj);
        if (!item_owner) return false;
        return try_get_controller_root_item(item_owner) != nullptr;
    }

    inline Il2CppObject* try_get_item_template(Il2CppObject* item_obj)
    {
        if (!is_il2cpp_object_likely_valid(item_obj)) return nullptr;
        return try_get_backing_field_object(item_obj, "<Template>k__BackingField", "Template");
    }

    inline bool is_inventory_item_valid(Il2CppObject* item_obj)
    {
        return try_get_item_template(item_obj) != nullptr;
    }

    inline int try_get_item_stack_count(Il2CppObject* item_obj)
    {
        if (!is_il2cpp_object_likely_valid(item_obj)) return 1;

        const FieldInfo* field = il2utils::resolve_field(item_obj->klass, "StackObjectsCount");
        if (!field) return 1;

        const UINT64 field_addr = reinterpret_cast<UINT64>(item_obj) + field->offset;
        if (!is_readable_address(reinterpret_cast<void*>(field_addr), sizeof(int))) return 1;

        return *reinterpret_cast<int*>(field_addr);
    }

    inline int try_get_item_stack_max(Il2CppObject* item_obj)
    {
        if (!is_il2cpp_object_likely_valid(item_obj)) return 1;

        Il2CppObject* template_obj = try_get_item_template(item_obj);
        if (!template_obj) return 1;

        const FieldInfo* field = il2utils::resolve_field(template_obj->klass, "StackMaxSize");
        if (!field) return 1;

        const UINT64 field_addr = reinterpret_cast<UINT64>(template_obj) + field->offset;
        if (!is_readable_address(reinterpret_cast<void*>(field_addr), sizeof(int))) return 1;

        const int max_size = *reinterpret_cast<int*>(field_addr);
        return max_size > 0 ? max_size : 1;
    }

    inline bool try_get_item_is_quest(Il2CppObject* item_obj)
    {
        if (!is_il2cpp_object_likely_valid(item_obj)) return false;

        Il2CppObject* template_obj = try_get_item_template(item_obj);
        if (!template_obj) return false;

        const FieldInfo* field = il2utils::resolve_field(template_obj->klass, "QuestItem");
        if (!field) return false;

        const UINT64 field_addr = reinterpret_cast<UINT64>(template_obj) + field->offset;
        if (!is_readable_address(reinterpret_cast<void*>(field_addr), sizeof(bool))) return false;

        return *reinterpret_cast<bool*>(field_addr);
    }

    inline bool try_get_item_is_provision(Il2CppObject* item_obj)
    {
        if (!item_obj || !item_obj->klass || !item_obj->klass->name) return false;
        const char* cls_name = item_obj->klass->name;
        return strstr(cls_name, "Food") != nullptr || strstr(cls_name, "Drink") != nullptr;
    }

    inline std::string try_get_template_string_id(Il2CppObject* template_obj)
    {
        if (!is_il2cpp_object_likely_valid(template_obj)) return {};

        static const MethodInfo* get_string_id = nullptr;
        if (!get_string_id && template_obj->klass)
            get_string_id = il2utils::resolve_method(template_obj->klass, "get_StringId", 0);

        if (get_string_id && get_string_id->methodPointer)
        {
            Il2CppString* str = reinterpret_cast<Il2CppString*(*)(Il2CppObject*, const MethodInfo*)>(
                get_string_id->methodPointer)(template_obj, get_string_id);
            const std::string id = try_read_il2cpp_string(str);
            if (!id.empty()) return id;
        }

        const FieldInfo* id_field = il2utils::resolve_field(template_obj->klass, "<_id>k__BackingField");
        if (!id_field) return {};

        const UINT64 mongo_base = reinterpret_cast<UINT64>(template_obj) + id_field->offset;
        if (!is_readable_address(reinterpret_cast<void*>(mongo_base), 0x18)) return {};

        // MongoID._stringID is at +0x10 inside the struct (dump 1.0.6.0.46010).
        Il2CppString* str = *reinterpret_cast<Il2CppString**>(mongo_base + 0x10);
        return try_read_il2cpp_string(str);
    }

    inline std::string try_get_item_template_id(Il2CppObject* item_obj)
    {
        return try_get_template_string_id(try_get_item_template(item_obj));
    }

    inline bool class_name_contains(Il2CppObject* obj, const char* needle)
    {
        if (!needle || !needle[0]) return false;
        if (!is_il2cpp_object_likely_valid(obj) || !obj->klass || !obj->klass->name) return false;
        return strstr(obj->klass->name, needle) != nullptr;
    }

    inline bool is_inventory_equipment_item(Il2CppObject* item_obj)
    {
        if (!is_il2cpp_object_likely_valid(item_obj) || !item_obj->klass || !item_obj->klass->name)
            return false;

        const char* item_class = item_obj->klass->name;
        return strcmp(item_class, "InventoryEquipment") == 0
            || strcmp(item_class, "Equipment") == 0;
    }

    inline bool is_player_inventory_item(Il2CppObject* item_obj)
    {
        if (!is_il2cpp_object_likely_valid(item_obj) || !item_obj->klass || !item_obj->klass->name)
            return false;

        if (is_inventory_equipment_item(item_obj))
            return true;

        const char* item_class = item_obj->klass->name;
        if (strcmp(item_class, "Inventory") == 0)
            return true;

        if (!strstr(item_class, "CompoundItem") && !strstr(item_class, "Inventory"))
            return false;

        Il2CppArray* slots = try_get_array_field(item_obj, "Slots");
        Il2CppArray* grids = try_get_array_field(item_obj, "Grids");
        if (!slots || !grids || slots->max_length < 4 || grids->max_length < 2)
            return false;

        return try_get_item_template_id(item_obj).empty();
    }

    inline Il2CppObject* try_find_player_by_profile_id(Il2CppObject* game_world, const std::string& profile_id)
    {
        if (!is_il2cpp_object_strict(game_world) || profile_id.empty()) return nullptr;

        Il2CppObject* dict_obj = try_get_field_object(game_world, "_allPlayersEverExistedByProfileId");
        if (!dict_obj) return nullptr;

        auto* players_dict = reinterpret_cast<unity::dict<Il2CppString*, Il2CppObject*>*>(dict_obj);
        if (!players_dict || players_dict->m_i_count <= 0) return nullptr;

        for (int i = 0; i < players_dict->m_i_count; ++i)
        {
            Il2CppString* key = players_dict->get_key_by_index(i);
            if (!key) continue;
            if (try_read_il2cpp_string(key) != profile_id) continue;

            Il2CppObject* player = players_dict->get_value_by_index(i);
            if (is_il2cpp_object_strict(player)) return player;
        }

        return nullptr;
    }

    inline bool try_player_is_ai(Il2CppObject* player_obj)
    {
        if (!is_il2cpp_object_strict(player_obj)) return false;

        Il2CppObjectInstance player(player_obj);
        const auto get_is_ai = player.get_method<bool(*)(Il2CppObject*)>("get_IsAI", 0);
        if (!get_is_ai) return false;

        return get_is_ai(player_obj);
    }

    inline bool try_is_bot_corpse(Il2CppObject* corpse_obj, Il2CppObject* game_world)
    {
        if (!corpse_obj || !class_name_contains(corpse_obj, "Corpse")) return false;

        const std::string profile_id = try_read_string_field(corpse_obj, "PlayerProfileID");
        if (profile_id.empty() || !game_world) return false;

        Il2CppObject* player = try_find_player_by_profile_id(game_world, profile_id);
        return player && try_player_is_ai(player);
    }

    inline bool is_bot_corpse_loot(Il2CppObject* loot_obj, Il2CppObject* item_obj)
    {
        if (class_name_contains(loot_obj, "Corpse"))
            return true;

        return is_player_inventory_item(item_obj);
    }

    inline std::string try_get_item_display_name(Il2CppObject* item_obj)
    {
        Il2CppObject* template_obj = try_get_item_template(item_obj);
        if (template_obj)
        {
            std::string name = try_read_string_field(template_obj, "ShortName");
            if (!name.empty()) return name;

            name = try_read_string_field(template_obj, "Name");
            if (!name.empty()) return name;
        }

        if (is_il2cpp_object_likely_valid(item_obj))
            return item_obj->klass->name;

        return "Item";
    }

    inline std::string try_get_item_localized_short_name(
        Il2CppObject* item_obj,
        Il2CppString*(*localized_short_name)(Il2CppObject*))
    {
        if (!item_obj || !localized_short_name) return {};

        Il2CppString* name_str = localized_short_name(item_obj);
        if (!name_str) return {};

        std::string name = to_display_utf8(il2utils::conv_wstring(name_str));
        return name.empty() ? "Item" : name;
    }

    inline std::string try_get_item_localized_name(
        Il2CppObject* item_obj,
        Il2CppString*(*localized_short_name)(Il2CppObject*),
        Il2CppString*(*localized_name)(Il2CppObject*))
    {
        std::string name = try_get_item_localized_short_name(item_obj, localized_short_name);
        if (!name.empty() && name != "Item") return name;

        if (!item_obj || !localized_name) return name.empty() ? "Item" : name;

        Il2CppString* name_str = localized_name(item_obj);
        if (!name_str) return name.empty() ? "Item" : name;

        name = to_display_utf8(il2utils::conv_wstring(name_str));
        return name.empty() ? "Item" : name;
    }

    inline void collect_compound_grid_items_recursive(Il2CppObject* compound_item, std::vector<Il2CppObject*>& out,
                                                      const int depth = 0)
    {
        if (!is_il2cpp_object_likely_valid(compound_item) || depth > 3
            || static_cast<int>(out.size()) >= 256) return;

        if (Il2CppArray* grids = try_get_array_field(compound_item, "Grids"))
        {
            const size_t grid_count = (std::min)(grids->max_length, static_cast<size_t>(16));
            for (size_t i = 0; i < grid_count; ++i)
            {
                Il2CppObject* grid = reinterpret_cast<Il2CppObject**>(&grids->data)[i];
                if (!is_il2cpp_object_likely_valid(grid)) continue;

                Il2CppObject* collection = try_get_backing_field_object(
                    grid, "<ItemCollection>k__BackingField", "ItemCollection");
                if (!collection) continue;

                const size_t before = out.size();
                append_list_items(
                    try_get_field_object(collection, "ItemsList"), out, 128);

                for (size_t j = before; j < out.size(); ++j)
                {
                    if (static_cast<int>(out.size()) >= 256) return;
                    if (is_nested_compound_item(out[j]))
                        collect_compound_grid_items_recursive(out[j], out, depth + 1);
                }
            }
        }
    }

    inline Il2CppObject* try_get_inventory_equipment(Il2CppObject* inventory_obj)
    {
        if (!is_il2cpp_object_likely_valid(inventory_obj) || !inventory_obj->klass || !inventory_obj->klass->name)
            return nullptr;
        if (strcmp(inventory_obj->klass->name, "Inventory") != 0)
            return nullptr;
        return try_get_field_object(inventory_obj, "Equipment");
    }

    inline Il2CppObject* try_get_slot_contained_item(Il2CppObject* slot_obj)
    {
        if (Il2CppObject* value = try_get_backing_field_object(
                slot_obj, "<ContainedItem>k__BackingField", "ContainedItem"))
            return value;

        if (!is_il2cpp_object_likely_valid(slot_obj) || !slot_obj->klass)
            return nullptr;

        Il2CppObjectInstance slot(slot_obj);
        const auto get_contained = slot.get_method<Il2CppObject*(*)(Il2CppObject*)>("get_ContainedItem", 0);
        if (!get_contained) return nullptr;
        return get_contained(slot_obj);
    }

    inline void append_contained_loot_items(Il2CppObject* contained, std::vector<Il2CppObject*>& out,
                                            const bool grid_contents_only)
    {
        if (!is_il2cpp_object_likely_valid(contained)) return;

        if (grid_contents_only)
        {
            const size_t before = out.size();
            collect_compound_grid_items_recursive(contained, out);
            if (out.size() == before && is_inventory_item_valid(contained))
                out.push_back(contained);
        }
        else if (is_inventory_item_valid(contained))
        {
            out.push_back(contained);
        }
    }

    inline Il2CppObject* try_get_equipment_slot_by_enum(Il2CppObject* equipment_like, const int slot_index)
    {
        if (!is_il2cpp_object_likely_valid(equipment_like) || !equipment_like->klass)
            return nullptr;

        Il2CppObjectInstance eq(equipment_like);
        const auto get_slot = eq.get_method<Il2CppObject*(*)(Il2CppObject*, int)>("GetSlot", 1);
        if (!get_slot) return nullptr;
        return get_slot(equipment_like, slot_index);
    }

    inline Il2CppObject* try_get_equipment_slot_object(Il2CppObject* loot_item, const int slot_index)
    {
        if (is_inventory_equipment_item(loot_item))
            return try_get_equipment_slot_by_enum(loot_item, slot_index);

        if (Il2CppObject* equipment = try_get_inventory_equipment(loot_item))
            return try_get_equipment_slot_by_enum(equipment, slot_index);

        return nullptr;
    }

    inline void collect_corpse_slot_items(Il2CppObject* loot_item, const int slot_index,
                                          std::vector<Il2CppObject*>& out, const bool grid_contents_only)
    {
        Il2CppObject* slot = try_get_equipment_slot_object(loot_item, slot_index);
        if (!is_il2cpp_object_likely_valid(slot)) return;
        append_contained_loot_items(try_get_slot_contained_item(slot), out, grid_contents_only);
    }

    inline bool is_corpse_lootable_inventory(Il2CppObject* item_obj)
    {
        if (!is_il2cpp_object_likely_valid(item_obj)) return false;
        if (is_inventory_equipment_item(item_obj)) return true;
        if (try_get_inventory_equipment(item_obj)) return true;
        return is_player_inventory_item(item_obj);
    }

    inline Il2CppObject* try_resolve_corpse_inventory_root(Il2CppObject* loot_obj, Il2CppObject* item_obj)
    {
        if (is_corpse_lootable_inventory(item_obj))
            return item_obj;

        if (!is_il2cpp_object_likely_valid(loot_obj))
            return nullptr;

        Il2CppObject* item_owner = try_get_container_item_owner(loot_obj);
        Il2CppObject* root_item = try_get_controller_root_item(item_owner);
        if (is_corpse_lootable_inventory(root_item))
            return root_item;

        return nullptr;
    }

    inline bool foreach_corpse_lootable_item(
        Il2CppObject* inventory_root,
        const std::function<bool(Il2CppObject*)>& visitor)
    {
        if (!visitor || !is_corpse_lootable_inventory(inventory_root)) return false;

        std::vector<Il2CppObject*> items;
        items.reserve(32);

        // EquipmentSlot from dump: FirstPrimary=0, SecondPrimary=1, Holster=2, Scabbard=3,
        // Backpack=4, TacticalVest=6, Pockets=8
        collect_corpse_slot_items(inventory_root, 0, items, true);
        collect_corpse_slot_items(inventory_root, 1, items, true);
        collect_corpse_slot_items(inventory_root, 2, items, true);
        collect_corpse_slot_items(inventory_root, 3, items, true);
        collect_corpse_slot_items(inventory_root, 4, items, true);
        collect_corpse_slot_items(inventory_root, 6, items, true);
        collect_corpse_slot_items(inventory_root, 8, items, true);

        for (Il2CppObject* item_obj : items)
        {
            if (!is_il2cpp_object_likely_valid(item_obj)) continue;
            if (!visitor(item_obj)) return true;
        }
        return !items.empty();
    }

    inline bool foreach_container_item(
        Il2CppObject* root_item,
        const std::function<bool(Il2CppObject*)>& visitor)
    {
        if (!visitor || !is_il2cpp_object_likely_valid(root_item)) return false;

        std::vector<Il2CppObject*> items;
        items.reserve(32);
        collect_compound_items_recursive(root_item, items);

        for (Il2CppObject* item_obj : items)
        {
            if (item_obj == root_item) continue;
            if (!is_il2cpp_object_likely_valid(item_obj)) continue;
            if (!visitor(item_obj)) return true;
        }
        return !items.empty();
    }

    inline std::atomic<bool>& external_loot_inventory_open_cached()
    {
        static std::atomic<bool> value{false};
        return value;
    }

    inline bool query_external_loot_inventory_open()
    {
        static const Il2CppImage* assembly = il2utils::resolve_image("Assembly-CSharp.dll");
        if (!assembly) return false;

        static const Il2CppClass* screen_manager_class =
            il2utils::resolve_class(assembly, "EFT.UI.Screens", "EftScreenManager");
        if (!screen_manager_class) return false;

        static auto get_screen_manager = il2utils::get_method<Il2CppObject*(*)()>(
            screen_manager_class, "get_Instance", 0);
        if (!get_screen_manager) return false;

        Il2CppObject* screen_manager = get_screen_manager();
        if (!is_il2cpp_object_likely_valid(screen_manager)) return false;

        static auto get_current_controller = il2utils::get_method<Il2CppObject*(*)(Il2CppObject*)>(
            screen_manager_class, "get_CurrentScreenController", 0);
        if (!get_current_controller) return false;

        Il2CppObject* controller = get_current_controller(screen_manager);
        if (!is_il2cpp_object_likely_valid(controller)) return false;

        Il2CppObjectInstance controller_inst(controller);
        const auto get_closed = controller_inst.get_method<bool(*)(Il2CppObject*)>("get_Closed", 0);
        if (get_closed && get_closed(controller)) return false;

        const auto get_screen_type = controller_inst.get_method<int(*)(Il2CppObject*)>("get_ScreenType", 0);
        if (!get_screen_type) return false;

        const int screen_type = get_screen_type(controller);
        constexpr int inventory_screen = 15; // EEftScreenType.Inventory
        constexpr int transfer_items_in_raid = 42; // EEftScreenType.TransferItemsInRaid

        if (screen_type == transfer_items_in_raid)
            return true;

        if (screen_type != inventory_screen)
            return false;

        // Tab inventory: LootItem is null and ShowAsGridContent is false.
        // Corpse/container/bag loot: LootItem is set or grid loot view is active.
        Il2CppObject* loot_item = try_get_field_object(controller, "LootItem");
        if (is_il2cpp_object_likely_valid(loot_item))
            return true;

        const auto get_show_as_grid = controller_inst.get_method<bool(*)(Il2CppObject*)>(
            "get_ShowAsGridContent", 0);
        return get_show_as_grid && get_show_as_grid(controller);
    }

    inline void update_external_loot_inventory_open_cached()
    {
        external_loot_inventory_open_cached().store(
            query_external_loot_inventory_open(), std::memory_order_relaxed);
    }

    inline bool is_external_loot_inventory_open_cached()
    {
        return external_loot_inventory_open_cached().load(std::memory_order_relaxed);
    }

    inline bool is_bot_corpse_inventory_open()
    {
        return is_external_loot_inventory_open_cached();
    }

    namespace detail
    {
        using localization_instance_fn_t = Il2CppObject*(*)();
        using localization_value_fn_t = Il2CppString*(*)(Il2CppObject*, Il2CppString*);
        using parse_localization_fn_t = Il2CppString*(*)(Il2CppString*);

        inline parse_localization_fn_t parse_localization_fn()
        {
            static parse_localization_fn_t fn = nullptr;
            static bool resolved = false;
            if (!resolved)
            {
                resolved = true;
                const Il2CppImage* assembly = il2utils::resolve_image("Assembly-CSharp.dll");
                if (!assembly) return fn;
                const Il2CppClass* cls = il2utils::resolve_class(assembly, "EFT", "LocalizationExtensions");
                if (!cls) return fn;
                fn = il2utils::get_method<parse_localization_fn_t>(cls, "ParseLocalization", 1);
            }
            return fn;
        }

        inline localization_instance_fn_t localization_manager_instance_fn()
        {
            static localization_instance_fn_t fn = nullptr;
            static bool resolved = false;
            if (!resolved)
            {
                resolved = true;
                const Il2CppImage* assembly = il2utils::resolve_image("Assembly-CSharp.dll");
                if (!assembly) return fn;
                const Il2CppClass* cls = il2utils::resolve_class(assembly, "EFT", "LocalizationManager");
                if (!cls) return fn;
                fn = il2utils::get_method<localization_instance_fn_t>(cls, "get_Instance", 0);
            }
            return fn;
        }

        inline localization_value_fn_t localization_value_fn()
        {
            static localization_value_fn_t fn = nullptr;
            static bool resolved = false;
            if (!resolved)
            {
                resolved = true;
                const Il2CppImage* assembly = il2utils::resolve_image("Assembly-CSharp.dll");
                if (!assembly) return fn;
                const Il2CppClass* cls = il2utils::resolve_class(assembly, "EFT", "LocalizationManager");
                if (!cls) return fn;
                fn = il2utils::get_method<localization_value_fn_t>(cls, "LocalizedValue", 1);
            }
            return fn;
        }

        inline std::unordered_map<std::string, std::string>& localization_lookup_cache()
        {
            static std::unordered_map<std::string, std::string> cache;
            return cache;
        }

        inline std::unordered_map<std::string, std::string>& game_key_cache()
        {
            static std::unordered_map<std::string, std::string> cache;
            return cache;
        }

        inline std::unordered_map<uintptr_t, std::string>& exfil_display_cache()
        {
            static std::unordered_map<uintptr_t, std::string> cache;
            return cache;
        }

        inline std::unordered_map<uintptr_t, std::string>& transit_display_cache()
        {
            static std::unordered_map<uintptr_t, std::string> cache;
            return cache;
        }

        inline std::unordered_map<uintptr_t, std::string>& container_display_cache()
        {
            static std::unordered_map<uintptr_t, std::string> cache;
            return cache;
        }

        inline std::unordered_map<std::string, std::string>& template_display_cache()
        {
            static std::unordered_map<std::string, std::string> cache;
            return cache;
        }

        inline std::unordered_map<std::string, std::string>& location_display_cache()
        {
            static std::unordered_map<std::string, std::string> cache;
            return cache;
        }

        using localized_item_fn_t = Il2CppString*(*)(Il2CppObject*);

        inline localized_item_fn_t localized_short_name_fn()
        {
            static localized_item_fn_t fn = nullptr;
            static bool resolved = false;
            if (!resolved)
            {
                resolved = true;
                const Il2CppImage* assembly = il2utils::resolve_image("Assembly-CSharp.dll");
                if (!assembly) return fn;
                const Il2CppClass* cls = il2utils::resolve_class(assembly, "EFT", "LocalizationExtensions");
                if (!cls) return fn;
                fn = il2utils::get_method<localized_item_fn_t>(cls, "LocalizedShortName", 1);
            }
            return fn;
        }

        inline localized_item_fn_t localized_name_fn()
        {
            static localized_item_fn_t fn = nullptr;
            static bool resolved = false;
            if (!resolved)
            {
                resolved = true;
                const Il2CppImage* assembly = il2utils::resolve_image("Assembly-CSharp.dll");
                if (!assembly) return fn;
                const Il2CppClass* cls = il2utils::resolve_class(assembly, "EFT", "LocalizationExtensions");
                if (!cls) return fn;
                fn = il2utils::get_method<localized_item_fn_t>(cls, "LocalizedName", 1);
            }
            return fn;
        }
    }

    inline void clear_localization_cache()
    {
        detail::localization_lookup_cache().clear();
        detail::role_label_cache().clear();
        detail::game_key_cache().clear();
        detail::exfil_display_cache().clear();
        detail::transit_display_cache().clear();
        detail::container_display_cache().clear();
        detail::template_display_cache().clear();
        detail::location_display_cache().clear();
    }

    inline bool is_plausible_localized_result(const std::string& key, const std::string& result)
    {
        if (result.empty() || result == key) return false;
        if (!result.empty() && result.front() == '/') return false;
        if (result.find("/Name/") != std::string::npos) return false;
        if (result.find("/Description/") != std::string::npos) return false;
        return true;
    }

    inline Il2CppObject* try_get_localization_manager()
    {
        static Il2CppObject* cached_manager = nullptr;

        if (cached_manager && is_il2cpp_object_strict(cached_manager))
            return cached_manager;

        detail::localization_instance_fn_t get_instance = detail::localization_manager_instance_fn();
        if (!get_instance) return nullptr;

        Il2CppObject* manager = get_instance();
        if (!is_il2cpp_object_strict(manager)) return nullptr;

        cached_manager = manager;
        return cached_manager;
    }

    inline std::string try_localize_key(const std::string& key)
    {
        if (key.empty()) return {};

        auto& cache = detail::localization_lookup_cache();
        if (const auto cached = cache.find(key); cached != cache.end())
            return cached->second;

        detail::localization_value_fn_t localized_value = detail::localization_value_fn();
        Il2CppObject* manager = try_get_localization_manager();
        if (!manager || !localized_value)
        {
            cache[key] = {};
            return {};
        }

        Il2CppString* key_str = il2cpp::il2cpp_string_new(key.c_str());
        if (!key_str)
        {
            cache[key] = {};
            return {};
        }

        const std::string localized = try_read_il2cpp_string(localized_value(manager, key_str));
        const std::string result = is_plausible_localized_result(key, localized) ? localized : std::string{};
        cache[key] = result;
        return result;
    }

    inline std::string try_localize_with_suffix(const std::string& id, const char* suffix)
    {
        if (id.empty() || !suffix || !suffix[0]) return {};
        return try_localize_key(id + "/" + suffix);
    }

    inline std::string try_parse_localization(const std::string& key)
    {
        if (key.empty()) return {};

        const std::string cache_key = "\x01parse:" + key;
        auto& cache = detail::localization_lookup_cache();
        if (const auto cached = cache.find(cache_key); cached != cache.end())
            return cached->second;

        if (!try_get_localization_manager())
        {
            cache[cache_key] = {};
            return {};
        }

        detail::parse_localization_fn_t parse_fn = detail::parse_localization_fn();
        if (!parse_fn)
        {
            cache[cache_key] = {};
            return {};
        }

        Il2CppString* key_str = il2cpp::il2cpp_string_new(key.c_str());
        if (!key_str)
        {
            cache[cache_key] = {};
            return {};
        }

        const std::string localized = try_read_il2cpp_string(parse_fn(key_str));
        const std::string result = is_plausible_localized_result(key, localized) ? localized : std::string{};
        cache[cache_key] = result;
        return result;
    }

    inline std::string try_localize_game_key(const std::string& key)
    {
        if (key.empty()) return {};

        auto& cache = detail::game_key_cache();
        if (const auto cached = cache.find(key); cached != cache.end())
            return cached->second;

        if (!try_get_localization_manager())
        {
            cache[key] = {};
            return {};
        }

        const bool looks_like_desc_key = key.find("_DESC") != std::string::npos
            || key.find("_desc") != std::string::npos;

        auto store_and_return = [&](const std::string& value) -> std::string
        {
            cache[key] = value;
            return value;
        };

        if (!looks_like_desc_key)
        {
            if (const std::string by_name = try_localize_with_suffix(key, "Name");
                is_plausible_localized_result(key, by_name))
                return store_and_return(by_name);
        }

        if (const std::string direct = try_localize_key(key);
            is_plausible_localized_result(key, direct))
            return store_and_return(direct);

        if (looks_like_desc_key || key.find('_') != std::string::npos)
        {
            if (const std::string parsed = try_parse_localization(key);
                is_plausible_localized_result(key, parsed))
                return store_and_return(parsed);
        }

        if (!looks_like_desc_key)
        {
            if (const std::string by_description = try_localize_with_suffix(key, "Description");
                is_plausible_localized_result(key, by_description))
                return store_and_return(by_description);
        }

        cache[key] = {};
        return {};
    }

    inline std::string normalize_location_id_for_display(const std::string& location_id)
    {
        if (location_id == "factory4_day" || location_id == "factory4_night")
            return "factory4";
        if (location_id == "Sandbox_high" || location_id == "Sandbox_start")
            return "Sandbox";
        return location_id;
    }

    inline Il2CppObject* try_get_raid_location_settings()
    {
        using location_get_fn_t = Il2CppObject*(*)(Il2CppObject*);

        static bool resolved = false;
        static const Il2CppImage* assembly = nullptr;
        static location_get_fn_t get_location_from_owner = nullptr;
        static location_get_fn_t get_location_from_local_game = nullptr;

        if (!resolved)
        {
            resolved = true;
            assembly = il2utils::resolve_image("Assembly-CSharp.dll");
            if (!assembly) return nullptr;

            if (const Il2CppClass* owner_class = il2utils::resolve_class(assembly, "EFT", "GamePlayerOwner"))
            {
                if (const MethodInfo* method = il2utils::resolve_method(owner_class, "get_Location", 0);
                    method && method->methodPointer)
                    get_location_from_owner = reinterpret_cast<location_get_fn_t>(method->methodPointer);
            }

            if (const Il2CppClass* local_game_class = il2utils::resolve_class(assembly, "EFT", "LocalGame"))
            {
                if (const MethodInfo* method = il2utils::resolve_method(local_game_class, "get_Location", 0);
                    method && method->methodPointer)
                    get_location_from_local_game = reinterpret_cast<location_get_fn_t>(method->methodPointer);
            }
        }

        const auto try_source = [&](location_get_fn_t getter, const char* class_name) -> Il2CppObject*
        {
            if (!assembly || !getter) return nullptr;

            Il2CppObject* type = il2utils::get_system_type(assembly, "EFT", class_name);
            if (!type) return nullptr;

            Il2CppObject* source = unity::find_object_of_type(type);
            if (!is_il2cpp_object_likely_valid(source)) return nullptr;

            Il2CppObject* location = getter(source);
            return is_il2cpp_object_likely_valid(location) ? location : nullptr;
        };

        if (Il2CppObject* location = try_source(get_location_from_owner, "GamePlayerOwner"))
            return location;

        return try_source(get_location_from_local_game, "LocalGame");
    }

    inline std::string try_read_location_localized_name(Il2CppObject* location)
    {
        if (!is_il2cpp_object_likely_valid(location)) return {};

        using location_localized_name_fn_t = Il2CppString*(*)(Il2CppObject*);

        static location_localized_name_fn_t get_localized_name = nullptr;
        static bool resolved = false;
        if (!resolved)
        {
            resolved = true;
            const Il2CppClass* location_class = location->klass;
            if (!location_class)
            {
                if (const Il2CppImage* assembly = il2utils::resolve_image("Assembly-CSharp.dll"))
                {
                    if (const Il2CppClass* location_settings_class = il2utils::resolve_class(assembly, "", "LocationSettings"))
                        location_class = il2utils::resolve_class_nested(location_settings_class, "Location");
                }
            }

            if (location_class)
            {
                if (const MethodInfo* method = il2utils::resolve_method(location_class, "get_LocalizedName", 0);
                    method && method->methodPointer)
                    get_localized_name = reinterpret_cast<location_localized_name_fn_t>(method->methodPointer);
            }
        }

        if (!get_localized_name) return {};
        return try_read_il2cpp_string(get_localized_name(location));
    }

    inline std::string try_get_location_display_name(const std::string& location_id)
    {
        if (location_id.empty()) return {};

        auto& cache = detail::location_display_cache();
        if (const auto cached = cache.find(location_id); cached != cache.end())
            return cached->second;

        const std::string normalized = normalize_location_id_for_display(location_id);
        std::string display_name;

        if (Il2CppObject* location = try_get_raid_location_settings())
        {
            if (const std::string runtime_name = try_read_location_localized_name(location);
                is_plausible_localized_result(location_id, runtime_name))
                display_name = runtime_name;

            if (display_name.empty())
            {
                const std::string name_key = try_read_string_field(location, "Name");
                if (!name_key.empty())
                {
                    if (const std::string localized = try_localize_game_key(name_key); !localized.empty())
                        display_name = localized;
                }
            }
        }

        const auto try_candidates = [&](const std::vector<std::string>& ids)
        {
            for (const std::string& id : ids)
            {
                if (id.empty()) continue;

                if (const std::string by_name = try_localize_with_suffix(id, "Name");
                    is_plausible_localized_result(id, by_name))
                {
                    display_name = by_name;
                    return true;
                }

                if (const std::string localized = try_localize_game_key(id); !localized.empty())
                {
                    display_name = localized;
                    return true;
                }
            }
            return false;
        };

        if (display_name.empty() && !try_candidates({normalized, location_id}))
            display_name = normalized.empty() ? location_id : normalized;

        cache[location_id] = display_name;
        return display_name;
    }

    inline std::string try_get_exfil_display_name(Il2CppObject* exfil_point)
    {
        if (!is_il2cpp_object_likely_valid(exfil_point)) return {};

        const uintptr_t point_key = reinterpret_cast<uintptr_t>(exfil_point);
        auto& cache = detail::exfil_display_cache();
        if (const auto cached = cache.find(point_key); cached != cache.end())
            return cached->second;

        Il2CppObject* settings = try_get_field_object(exfil_point, "Settings");
        const std::string code_name = settings ? try_read_string_field(settings, "Name") : std::string{};
        if (code_name.empty()) return {};

        std::string display_name = code_name;
        if (const std::string localized = try_localize_game_key(code_name); !localized.empty())
            display_name = localized;

        cache[point_key] = display_name;
        return display_name;
    }

    inline std::string try_get_transit_display_name(Il2CppObject* transit_point)
    {
        if (!is_il2cpp_object_likely_valid(transit_point)) return {};

        const uintptr_t point_key = reinterpret_cast<uintptr_t>(transit_point);
        auto& cache = detail::transit_display_cache();
        if (const auto cached = cache.find(point_key); cached != cache.end())
            return cached->second;

        Il2CppObject* parameters = try_get_field_object(transit_point, "parameters");
        if (!parameters) return {};

        const std::string description_key = try_read_string_field(parameters, "description");
        const std::string location_id = try_read_string_field(parameters, "location");
        const std::string name_key = try_read_string_field(parameters, "name");

        std::string display_name;
        for (const std::string& candidate : {description_key, location_id})
        {
            if (candidate.empty()) continue;

            if (const std::string localized = try_localize_game_key(candidate);
                is_plausible_localized_result(candidate, localized))
            {
                display_name = localized;
                break;
            }
        }

        if (display_name.empty())
        {
            if (!description_key.empty()) display_name = description_key;
            else if (!location_id.empty()) display_name = location_id;
            else display_name = name_key;
        }

        cache[point_key] = display_name;
        return display_name;
    }

    inline std::string try_read_localized_item_fn(Il2CppObject* item_obj, detail::localized_item_fn_t localized_fn)
    {
        if (!item_obj || !localized_fn) return {};

        Il2CppString* name_str = localized_fn(item_obj);
        if (!name_str) return {};

        const std::string name = to_display_utf8(il2utils::conv_wstring(name_str));
        if (name.empty() || name == "Item") return {};
        return name;
    }

    inline std::string try_get_item_localized_full_name(Il2CppObject* item_obj)
    {
        if (!is_il2cpp_object_strict(item_obj)) return {};

        std::string display_name = try_read_localized_item_fn(item_obj, detail::localized_name_fn());
        if (display_name.empty())
            display_name = try_read_localized_item_fn(item_obj, detail::localized_short_name_fn());
        if (display_name.empty())
            display_name = try_get_item_display_name(item_obj);

        return display_name;
    }

    inline std::string try_resolve_caliber_display_name(const std::string& caliber_key)
    {
        if (caliber_key.empty()) return {};

        using get_caliber_name_fn_t = Il2CppString*(*)(Il2CppString*);
        static get_caliber_name_fn_t fn = nullptr;
        static bool resolved = false;
        if (!resolved)
        {
            resolved = true;
            const Il2CppImage* assembly = il2utils::resolve_image("Assembly-CSharp.dll");
            if (assembly)
            {
                const Il2CppClass* cls = il2utils::resolve_class(assembly, "EFT.Builds", "MagBuildsStorage");
                if (cls)
                    fn = il2utils::get_method<get_caliber_name_fn_t>(cls, "GetCaliberName", 1);
            }
        }

        if (fn)
        {
            Il2CppString* result = fn(il2cpp::il2cpp_string_new(caliber_key.c_str()));
            if (result)
            {
                const std::string localized = to_display_utf8(il2utils::conv_wstring(result));
                if (!localized.empty())
                    return localized;
            }
        }

        if (const std::string localized = try_localize_game_key(caliber_key); !localized.empty())
            return localized;

        return caliber_key;
    }

    inline bool is_generic_bullet_ammo_type(const std::string& ammo_type_key)
    {
        if (ammo_type_key.empty()) return false;

        std::string lower = ammo_type_key;
        std::transform(lower.begin(), lower.end(), lower.begin(),
            [](const unsigned char c) { return static_cast<char>(std::tolower(c)); });
        return lower == "bullet";
    }

    inline std::string try_get_ammo_type_suffix(Il2CppObject* template_obj)
    {
        if (!template_obj) return {};

        const std::string ammo_type_key = try_read_string_field(template_obj, "ammoType");
        if (ammo_type_key.empty() || is_generic_bullet_ammo_type(ammo_type_key)) return {};

        if (const std::string localized = try_localize_game_key(ammo_type_key); !localized.empty())
            return localized;

        return ammo_type_key;
    }

    inline std::string try_get_ammo_display_name(Il2CppObject* ammo_or_template)
    {
        if (!is_il2cpp_object_strict(ammo_or_template)) return {};

        Il2CppObject* template_obj = nullptr;
        Il2CppObject* item_obj = ammo_or_template;
        if (ammo_or_template->klass && ammo_or_template->klass->name
            && strstr(ammo_or_template->klass->name, "Template") != nullptr)
        {
            template_obj = ammo_or_template;
            item_obj = nullptr;
        }
        else
        {
            template_obj = try_get_item_template(ammo_or_template);
        }

        std::string caliber_key;
        if (template_obj)
            caliber_key = try_read_string_field(template_obj, "Caliber");

        if (caliber_key.empty() && item_obj && item_obj->klass && item_obj->klass->name
            && strcmp(item_obj->klass->name, "Ammo") == 0)
        {
            Il2CppObjectInstance ammo_inst(item_obj);
            if (const auto get_caliber = ammo_inst.get_method<Il2CppString*(*)(Il2CppObject*)>("get_Caliber", 0))
            {
                if (Il2CppString* cal_str = get_caliber(item_obj))
                    caliber_key = to_display_utf8(il2utils::conv_wstring(cal_str));
            }
        }

        const std::string caliber_display = try_resolve_caliber_display_name(caliber_key);

        std::string short_display;
        if (item_obj)
            short_display = try_read_localized_item_fn(item_obj, detail::localized_short_name_fn());
        else if (template_obj)
            short_display = try_read_localized_item_fn(template_obj, detail::localized_short_name_fn());

        const std::string type_suffix = try_get_ammo_type_suffix(template_obj);
        if (!type_suffix.empty() && short_display.find(type_suffix) == std::string::npos)
        {
            if (!short_display.empty())
                short_display += ' ';
            short_display += type_suffix;
        }

        if (!caliber_display.empty() && !short_display.empty())
            return caliber_display + " " + short_display;
        if (!caliber_display.empty())
            return caliber_display;
        if (!short_display.empty())
            return short_display;

        if (item_obj)
            return try_get_item_localized_full_name(item_obj);

        return {};
    }

    inline std::string try_get_item_localized_display_name(Il2CppObject* item_obj)
    {
        if (!is_il2cpp_object_strict(item_obj)) return {};

        const std::string template_id = try_get_item_template_id(item_obj);
        if (!template_id.empty())
        {
            const auto cached = detail::template_display_cache().find(template_id);
            if (cached != detail::template_display_cache().end())
                return cached->second;
        }

        detail::localized_item_fn_t short_name_fn = detail::localized_short_name_fn();
        detail::localized_item_fn_t name_fn = detail::localized_name_fn();

        std::string display_name = try_get_item_localized_name(item_obj, short_name_fn, name_fn);
        if (display_name.empty() || display_name == "Item")
            display_name = try_get_item_display_name(item_obj);

        if (!template_id.empty() && !display_name.empty())
            detail::template_display_cache()[template_id] = display_name;

        return display_name;
    }

    inline std::string try_get_lootable_container_display_name(Il2CppObject* container_obj)
    {
        if (!is_il2cpp_object_likely_valid(container_obj)) return {};

        const uintptr_t cache_key = reinterpret_cast<uintptr_t>(container_obj);
        auto& cache = detail::container_display_cache();
        if (const auto cached = cache.find(cache_key); cached != cache.end())
            return cached->second;

        std::string display_name;

        if (Il2CppObject* item_owner = try_get_container_item_owner(container_obj))
        {
            if (Il2CppObject* root_item = try_get_controller_root_item(item_owner))
            {
                display_name = try_get_item_localized_display_name(root_item);
                if (!display_name.empty() && display_name != "Item")
                {
                    cache[cache_key] = display_name;
                    return display_name;
                }
                display_name.clear();
            }
        }

        const std::string template_key = try_read_string_field(container_obj, "Template");
        if (!template_key.empty())
        {
            if (const std::string localized = try_localize_game_key(template_key); !localized.empty())
                display_name = localized;
            else
                display_name = template_key;
        }

        if (display_name.empty())
        {
            Il2CppObjectInstance container_inst(container_obj);
            if (const auto get_type_key = container_inst.get_method<Il2CppString*(*)(Il2CppObject*)>(
                "get_TypeKey", 0))
            {
                const std::string type_key = try_read_il2cpp_string(get_type_key(container_obj));
                if (!type_key.empty())
                {
                    if (const std::string localized = try_localize_game_key(type_key); !localized.empty())
                        display_name = localized;
                    else
                        display_name = type_key;
                }
            }
        }

        if (display_name.empty())
        {
            display_name = container_obj->klass && container_obj->klass->name
                ? container_obj->klass->name
                : "Container";
        }

        cache[cache_key] = display_name;
        return display_name;
    }

    struct weapon_ammo_state
    {
        bool active = false;
        int mag_count = 0;
        int mag_max = 0;
        int chamber_count = 0;
        std::string chamber_name;
    };

    inline bool try_read_weapon_ammo(Il2CppObject* player_obj, weapon_ammo_state& out, bool* hands_not_firearm = nullptr)
    {
        if (hands_not_firearm)
            *hands_not_firearm = false;
        if (!player_obj) return false;

        Il2CppObjectInstance player(player_obj);
        Il2CppObject* hands_controller = player.get_method<Il2CppObject*(*)(Il2CppObject*)>(
            "get_HandsController", 0)(player_obj);
        if (!hands_controller || !hands_controller->klass) return false;
        if (strcmp(hands_controller->klass->name, "FirearmController") != 0)
        {
            if (hands_not_firearm)
                *hands_not_firearm = true;
            return false;
        }

        out = {};

        Il2CppObjectInstance firearm_controller(hands_controller);
        Il2CppObject* weapon_obj = firearm_controller.get_method<Il2CppObject*(*)(Il2CppObject*)>(
            "get_Item", 0)(hands_controller);
        if (!weapon_obj) return false;

        Il2CppObjectInstance weapon(weapon_obj);

        if (const auto get_mag_count = weapon.get_method<int(*)(Il2CppObject*)>("GetCurrentMagazineCount", 0))
            out.mag_count = get_mag_count(weapon_obj);
        if (const auto get_mag_max = weapon.get_method<int(*)(Il2CppObject*)>("GetMaxMagazineCount", 0))
            out.mag_max = get_mag_max(weapon_obj);
        if (const auto get_chamber_count = weapon.get_method<int(*)(Il2CppObject*)>("get_ChamberAmmoCount", 0))
            out.chamber_count = get_chamber_count(weapon_obj);

        if (const auto get_first_chamber = weapon.get_method<Il2CppObject*(*)(Il2CppObject*)>(
                "get_FirstLoadedChamberSlot", 0))
        {
            if (Il2CppObject* slot_obj = get_first_chamber(weapon_obj))
            {
                if (Il2CppObject* ammo_item = try_get_slot_contained_item(slot_obj))
                    out.chamber_name = try_get_ammo_display_name(ammo_item);
            }
        }

        if (out.chamber_name.empty() && out.chamber_count > 0)
        {
            if (const auto get_template = weapon.get_method<Il2CppObject*(*)(Il2CppObject*)>(
                    "get_CurrentAmmoTemplate", 0))
            {
                if (Il2CppObject* tmpl = get_template(weapon_obj))
                    out.chamber_name = try_get_ammo_display_name(tmpl);
            }
        }

        out.active = true;
        return true;
    }

}
