// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . // ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· // ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ // ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ // ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ // Magicbane Emulator Project © 2013 - 2026 // https://www.magicbane.com package engine.parsers.objects; import engine.math.Vector3fImmutable; import engine.mbEnums; import org.json.JSONArray; import java.util.ArrayList; import java.util.EnumMap; import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedHashMap; // Item template as defined by the client's cache data // (MBDATA/data/COBJECTS/ITEM). Field names match the JSON keys. // Field layout follows ArcItemTemplate_Load (sb.exe 0x4AABD0). // // Values are kept as the client defines them: no req/res splitting, // no defaults substituted. Strings with a matching enum in mbEnums // are stored as that enum; everything else stays a String. // Read only once loaded. public class ItemTemplate implements CObjectTemplate { public static HashMap _items = new HashMap<>(); // Legacy templates zero-filled the weapon block on non-weapons; held shields and the like rely on it. private static final Weapon NO_WEAPON = new Weapon(); public int template_id; // obj_ public String obj_name; public boolean obj_pickable; public float obj_gravity; public float obj_cull_distance; public Vector3fImmutable obj_scale; public int obj_render_object; public boolean obj_double_fusion; public Vector3fImmutable obj_forward_vector; public String obj_tracking_name; public float obj_max_tracking_distance; public int obj_icon; public float obj_gravity_f; public final LinkedHashMap obj_sound_events = new LinkedHashMap<>(); public JSONArray obj_arc_hardpoint_list; public final HashMap obj_sparse_data = new HashMap<>(); public int obj_render_object_low_detail; public Vector3fImmutable obj_default_alignment; public String obj_sound_table; // combat_ public float combat_health_current; public float combat_health_full; public final EnumMap combat_attack_resist = new EnumMap<>(mbEnums.DamageType.class); public JSONArray combat_powers; // item_ public mbEnums.ItemType item_type; // Index into the client's equip slot names; the leading slot of EQSLOTAND. public int item_eq_slots_value; // true: any one of item_eq_slots_or; false: all of item_eq_slots_and (sb.exe 0x4AC430). public boolean item_eq_slots_type; public final EnumSet item_eq_slots_or = EnumSet.noneOf(mbEnums.EquipSlotType.class); public final EnumSet item_eq_slots_and = EnumSet.noneOf(mbEnums.EquipSlotType.class); public boolean item_takeable; public int item_value; public int item_wt; public float item_passive_defense_mod; public String item_base_name; public String item_dsc; public int item_render_object_female; public float item_health_full; public String item_skill_used; public String item_skill_mastery_used; public int item_parry_anim_id; public final EnumMap item_offering_info = new EnumMap<>(mbEnums.ShrineType.class); // WEAPON only; null otherwise. public Weapon item_weapon; public mbEnums.AttributeType item_primary_attr; public mbEnums.AttributeType item_secondary_attr; // ARMOR only. public float item_bulk_factor; public int item_defense_rating; public final EnumSet item_flags = EnumSet.noneOf(mbEnums.ItemFlags.class); public final EnumSet item_use_flags = EnumSet.noneOf(mbEnums.ItemUseFlags.class); public int item_post_item_id; public int item_initial_charges; // Read as an unsigned value, possibly a hash; 0 in every ITEM file. public int item_book_arcana; public final LinkedHashMap item_skill_req = new LinkedHashMap<>(); // For race, class and disc: restrict true means the list is excluded // (RACERESTRICT), false means it is required (RACEREQ). public boolean item_race_req_restrict; public final EnumSet item_race_req = EnumSet.noneOf(mbEnums.MonsterType.class); public boolean item_class_req_restrict; public final EnumSet item_class_req = EnumSet.noneOf(mbEnums.ClassType.class); public boolean item_disc_req_restrict; public final EnumSet item_disc_req = EnumSet.noneOf(mbEnums.DisciplineType.class); public final EnumMap item_attr_req = new EnumMap<>(mbEnums.AttributeType.class); public int item_level_req; public int item_rank_req; public mbEnums.SexType item_sex_req; public final ArrayList item_user_power_action = new ArrayList<>(); public final ArrayList item_power_grant = new ArrayList<>(); public final LinkedHashMap> item_power_action = new LinkedHashMap<>(); // Sheath fields are only present when item_sheathable is true. public boolean item_sheathable; public mbEnums.SheathSlot item_sheath_slot; public Vector3fImmutable item_sheath_offset; public Vector3fImmutable item_sheath_rotation; // The JSON holds false, or [flag, id] when the stub is present (ArcItemStubHolder2, sb.exe 0x4A8D40). // Meaning of the flag is not known. public boolean item_has_stub; public boolean item_stub_flag; public int item_stub_id; public final EnumMap item_offering_adjustments = new EnumMap<>(mbEnums.ShrineType.class); public final EnumMap item_resource_costs = new EnumMap<>(mbEnums.ResourceType.class); public int item_bane_rank; public boolean item_ignore_saved_actions; @Override public int getTemplateId() { return template_id; } @Override public String getObjName() { return obj_name; } @Override public boolean getObjPickable() { return obj_pickable; } @Override public float getObjGravity() { return obj_gravity; } @Override public float getObjCullDistance() { return obj_cull_distance; } @Override public Vector3fImmutable getObjScale() { return obj_scale; } @Override public int getObjRenderObject() { return obj_render_object; } @Override public boolean getObjDoubleFusion() { return obj_double_fusion; } @Override public Vector3fImmutable getObjForwardVector() { return obj_forward_vector; } @Override public String getObjTrackingName() { return obj_tracking_name; } @Override public float getObjMaxTrackingDistance() { return obj_max_tracking_distance; } @Override public int getObjIcon() { return obj_icon; } @Override public float getObjGravityF() { return obj_gravity_f; } @Override public LinkedHashMap getObjSoundEvents() { return obj_sound_events; } @Override public JSONArray getObjArcHardpointList() { return obj_arc_hardpoint_list; } @Override public HashMap getObjSparseData() { return obj_sparse_data; } @Override public int getObjRenderObjectLowDetail() { return obj_render_object_low_detail; } @Override public Vector3fImmutable getObjDefaultAlignment() { return obj_default_alignment; } @Override public String getObjSoundTable() { return obj_sound_table; } @Override public float getCombatHealthCurrent() { return combat_health_current; } @Override public float getCombatHealthFull() { return combat_health_full; } @Override public EnumMap getCombatAttackResist() { return combat_attack_resist; } @Override public JSONArray getCombatPowers() { return combat_powers; } @Override public mbEnums.ItemType getItemType() { return item_type; } @Override public int getItemEqSlotsValue() { return item_eq_slots_value; } @Override public boolean getItemEqSlotsType() { return item_eq_slots_type; } @Override public EnumSet getItemEqSlotsOr() { return item_eq_slots_or; } @Override public EnumSet getItemEqSlotsAnd() { return item_eq_slots_and; } @Override public boolean getItemTakeable() { return item_takeable; } @Override public int getItemValue() { return item_value; } @Override public int getItemWt() { return item_wt; } @Override public float getItemPassiveDefenseMod() { return item_passive_defense_mod; } @Override public String getItemBaseName() { return item_base_name; } @Override public String getItemDsc() { return item_dsc; } @Override public int getItemRenderObjectFemale() { return item_render_object_female; } @Override public float getItemHealthFull() { return item_health_full; } @Override public String getItemSkillUsed() { return item_skill_used; } @Override public String getItemSkillMasteryUsed() { return item_skill_mastery_used; } @Override public int getItemParryAnimId() { return item_parry_anim_id; } @Override public EnumMap getItemOfferingInfo() { return item_offering_info; } @Override public EnumSet getItemFlags() { return item_flags; } @Override public EnumSet getItemUseFlags() { return item_use_flags; } @Override public int getItemPostItemId() { return item_post_item_id; } @Override public int getItemInitialCharges() { return item_initial_charges; } @Override public int getItemBookArcana() { return item_book_arcana; } @Override public LinkedHashMap getItemSkillReq() { return item_skill_req; } @Override public boolean getItemRaceReqRestrict() { return item_race_req_restrict; } @Override public EnumSet getItemRaceReq() { return item_race_req; } @Override public boolean getItemClassReqRestrict() { return item_class_req_restrict; } @Override public EnumSet getItemClassReq() { return item_class_req; } @Override public boolean getItemDiscReqRestrict() { return item_disc_req_restrict; } @Override public EnumSet getItemDiscReq() { return item_disc_req; } @Override public EnumMap getItemAttrReq() { return item_attr_req; } @Override public int getItemLevelReq() { return item_level_req; } @Override public int getItemRankReq() { return item_rank_req; } @Override public mbEnums.SexType getItemSexReq() { return item_sex_req; } @Override public ArrayList getItemUserPowerAction() { return item_user_power_action; } @Override public ArrayList getItemPowerGrant() { return item_power_grant; } @Override public LinkedHashMap> getItemPowerAction() { return item_power_action; } @Override public boolean getItemSheathable() { return item_sheathable; } @Override public boolean getItemHasStub() { return item_has_stub; } @Override public EnumMap getItemOfferingAdjustments() { return item_offering_adjustments; } @Override public EnumMap getItemResourceCosts() { return item_resource_costs; } @Override public int getItemBaneRank() { return item_bane_rank; } @Override public boolean getItemIgnoreSavedActions() { return item_ignore_saved_actions; } public static Weapon getWeapon(int templateID) { ItemTemplate template = _items.get(templateID); if (template == null || template.item_weapon == null) return NO_WEAPON; return template.item_weapon; } // item_weapon (ArcAttackInfo_LoadWeapon, sb.exe 0x61FA60). public static class Weapon { public float weapon_wepspeed; public float weapon_max_range; public int weapon_projectile_id; public float weapon_projectile_speed; public int weapon_combat_idle_anim; public final ArrayList weapon_damage = new ArrayList<>(); // [animation, duration] pairs in file order; names from the old static_item_templates export, not the client. public final ArrayList weapon_attack_anim_right = new ArrayList<>(); public final ArrayList weapon_attack_anim_left = new ArrayList<>(); } // One entry of weapon_damage. public static class Damage { public mbEnums.DamageType damage_type; public int damage_min; public int damage_max; } }