Repository for mbEditorPro 2.0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

517 lines
24 KiB

# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.arc_item import *
from arcane.enums.hashes import hash_to_string, string_to_hash
from arcane.util import ResStream
from .ArcCombatObj import ArcCombatObj
from .common.Arcane import AttributeValue, SkillLevel, PowerGrant, PowerAction, ResourceInfo
from .common.Class import ClassRequired
from .common.Discipline import DiscRequired
from .common.Race import RaceRequired
class Damage:
def load_binary(self, stream: ResStream):
self.damage_type = stream.read_dword()
self.damage_min = stream.read_dword()
self.damage_max = stream.read_dword()
def save_binary(self, stream: ResStream):
stream.write_dword(self.damage_type)
stream.write_dword(self.damage_min)
stream.write_dword(self.damage_max)
def load_json(self, data):
self.damage_type = STRING_TO_DAMAGE[data['damage_type']]
self.damage_min = data['damage_min']
self.damage_max = data['damage_max']
def save_json(self):
data = OrderedDict()
data['damage_type'] = DAMAGE_TO_STRING[self.damage_type]
data['damage_min'] = self.damage_min
data['damage_max'] = self.damage_max
return data
class Offerings:
def load_binary(self, stream: ResStream):
self.offering_type = stream.read_string()
self.offering_value = stream.read_dword()
def save_binary(self, stream: ResStream):
stream.write_string(self.offering_type)
stream.write_dword(self.offering_value)
def load_json(self, data):
self.offering_type = data['offering_type']
self.offering_value = data['offering_value']
def save_json(self):
data = OrderedDict()
data['offering_type'] = self.offering_type
data['offering_value'] = self.offering_value
return data
class Weapon:
def load_binary(self, stream: ResStream):
self.weapon_wepspeed = stream.read_float()
self.weapon_max_range = stream.read_float()
self.weapon_projectile_id = stream.read_qword()
self.weapon_projectile_speed = stream.read_float()
self.weapon_combat_idle_anim = stream.read_dword()
num_damages = stream.read_dword()
self.weapon_damage = [Damage() for _ in range(num_damages)]
for damage in self.weapon_damage:
damage.load_binary(stream)
num_right_anims = stream.read_dword()
self.weapon_attack_anim_right = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_right_anims)
]
num_left_anims = stream.read_dword()
self.weapon_attack_anim_left = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_left_anims)
]
def save_binary(self, stream: ResStream):
stream.write_float(self.weapon_wepspeed)
stream.write_float(self.weapon_max_range)
stream.write_qword(self.weapon_projectile_id)
stream.write_float(self.weapon_projectile_speed)
stream.write_dword(self.weapon_combat_idle_anim)
stream.write_dword(len(self.weapon_damage))
for damage in self.weapon_damage:
damage.save_binary(stream)
stream.write_dword(len(self.weapon_attack_anim_right))
for anim in self.weapon_attack_anim_right:
stream.write_dword(anim[0])
stream.write_dword(anim[1])
stream.write_dword(len(self.weapon_attack_anim_left))
for anim in self.weapon_attack_anim_left:
stream.write_dword(anim[0])
stream.write_dword(anim[1])
def load_json(self, data):
self.weapon_wepspeed = data['weapon_wepspeed']
self.weapon_max_range = data['weapon_max_range']
self.weapon_projectile_id = data['weapon_projectile_id']
self.weapon_projectile_speed = data['weapon_projectile_speed']
self.weapon_combat_idle_anim = data['weapon_combat_idle_anim']
self.weapon_damage = []
for damage_data in data['weapon_damage']:
damage = Damage()
damage.load_json(damage_data)
self.weapon_damage.append(damage)
self.weapon_attack_anim_right = data['weapon_attack_anim_right']
self.weapon_attack_anim_left = data['weapon_attack_anim_left']
def save_json(self):
data = OrderedDict()
data['weapon_wepspeed'] = self.weapon_wepspeed
data['weapon_max_range'] = self.weapon_max_range
data['weapon_projectile_id'] = self.weapon_projectile_id
data['weapon_projectile_speed'] = self.weapon_projectile_speed
data['weapon_combat_idle_anim'] = self.weapon_combat_idle_anim
data['weapon_damage'] = []
for damage in self.weapon_damage:
data['weapon_damage'].append(damage.save_json())
data['weapon_attack_anim_right'] = self.weapon_attack_anim_right
data['weapon_attack_anim_left'] = self.weapon_attack_anim_left
return data
class ArcItem(ArcCombatObj):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
self.item_type = stream.read_dword()
self.item_eq_slots_value = stream.read_dword()
self.item_eq_slots_or = stream.read_dword()
self.item_eq_slots_and = stream.read_dword()
self.item_eq_slots_type = stream.read_bool()
self.item_takeable = stream.read_bool()
self.item_value = stream.read_dword()
self.item_wt = stream.read_dword()
self.item_passive_defense_mod = stream.read_float()
self.item_base_name = stream.read_string()
self.item_dsc = stream.read_string()
self.item_render_object_female = stream.read_qword()
self.item_health_full = stream.read_float()
self.item_skill_used = stream.read_dword()
self.item_skill_mastery_used = stream.read_dword()
self.item_parry_anim_id = stream.read_dword()
num_adjustments = stream.read_dword()
self.item_offering_info = [Offerings() for _ in range(num_adjustments)]
for offering in self.item_offering_info:
offering.load_binary(stream)
if self.item_type == ITEM_TYPE_WEAPON:
self.item_weapon = Weapon()
self.item_weapon.load_binary(stream)
self.item_primary_attr = stream.read_dword()
self.item_secondary_attr = stream.read_dword()
if self.item_type == ITEM_TYPE_ARMOR:
self.item_bulk_factor = stream.read_float()
self.item_defense_rating = stream.read_dword()
self.item_flags = stream.read_dword()
self.item_use_flags = stream.read_dword()
self.item_post_item_id = stream.read_qword()
self.item_initial_charges = stream.read_dword()
self.item_book_arcana = stream.read_dword()
num_skills = stream.read_dword()
self.item_skill_req = [SkillLevel() for _ in range(num_skills)]
for skill in self.item_skill_req:
skill.load_binary(stream)
self.item_race_req = RaceRequired()
self.item_race_req.load_binary(stream)
self.item_class_req = ClassRequired()
self.item_class_req.load_binary(stream)
self.item_disc_req = DiscRequired()
self.item_disc_req.load_binary(stream)
num_attrs = stream.read_dword()
self.item_attr_req = [AttributeValue() for _ in range(num_attrs)]
for attr in self.item_attr_req:
attr.load_binary(stream)
self.item_level_req = stream.read_dword()
self.item_rank_req = stream.read_dword()
self.item_sex_req = stream.read_dword()
num_user_actions = stream.read_dword()
self.item_user_power_action = [
[
stream.read_dword(),
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_user_actions)
]
num_power_grants = stream.read_dword()
self.item_power_grant = [PowerGrant() for _ in range(num_power_grants)]
for action in self.item_power_grant:
action.load_binary(stream)
num_power_actions = stream.read_dword()
self.item_power_action = [PowerAction() for _ in range(num_power_actions)]
for grant in self.item_power_action:
grant.load_binary(stream)
self.item_sheathable = stream.read_bool()
if self.item_sheathable:
self.item_sheath_slot = stream.read_dword()
self.item_sheath_offset = stream.read_tuple()
self.item_sheath_rotation = stream.read_tuple()
self.item_has_stub = stream.read_bool()
if self.item_has_stub:
self.item_stub_holder = [
stream.read_bool(),
stream.read_qword(),
]
num_adjustments = stream.read_dword()
self.item_offering_adjustments = [Offerings() for _ in range(num_adjustments)]
for offering in self.item_offering_adjustments:
offering.load_binary(stream)
num_costs = stream.read_dword()
self.item_resource_costs = [ResourceInfo() for _ in range(num_costs)]
for res in self.item_resource_costs:
res.load_binary(stream)
self.item_bane_rank = stream.read_dword()
self.item_ignore_saved_actions = stream.read_bool()
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.write_dword(self.item_type)
stream.write_dword(self.item_eq_slots_value)
stream.write_dword(self.item_eq_slots_or)
stream.write_dword(self.item_eq_slots_and)
stream.write_bool(self.item_eq_slots_type)
stream.write_bool(self.item_takeable)
stream.write_dword(self.item_value)
stream.write_dword(self.item_wt)
stream.write_float(self.item_passive_defense_mod)
stream.write_string(self.item_base_name)
stream.write_string(self.item_dsc)
stream.write_qword(self.item_render_object_female)
stream.write_float(self.item_health_full)
stream.write_dword(self.item_skill_used)
stream.write_dword(self.item_skill_mastery_used)
stream.write_dword(self.item_parry_anim_id)
stream.write_dword(len(self.item_offering_info))
for offering in self.item_offering_info:
offering.save_binary(stream)
if self.item_type == ITEM_TYPE_WEAPON:
self.item_weapon.save_binary(stream)
stream.write_dword(self.item_primary_attr)
stream.write_dword(self.item_secondary_attr)
if self.item_type == ITEM_TYPE_ARMOR:
stream.write_float(self.item_bulk_factor)
stream.write_dword(self.item_defense_rating)
stream.write_dword(self.item_flags)
stream.write_dword(self.item_use_flags)
stream.write_qword(self.item_post_item_id)
stream.write_dword(self.item_initial_charges)
stream.write_dword(self.item_book_arcana)
stream.write_dword(len(self.item_skill_req))
for skill in self.item_skill_req:
skill.save_binary(stream)
self.item_race_req.save_binary(stream)
self.item_class_req.save_binary(stream)
self.item_disc_req.save_binary(stream)
stream.write_dword(len(self.item_attr_req))
for attr in self.item_attr_req:
attr.save_binary(stream)
stream.write_dword(self.item_level_req)
stream.write_dword(self.item_rank_req)
stream.write_dword(self.item_sex_req)
stream.write_dword(len(self.item_user_power_action))
for power in self.item_user_power_action:
stream.write_dword(power[0])
stream.write_dword(power[1])
stream.write_dword(power[2])
stream.write_dword(len(self.item_power_grant))
for action in self.item_power_grant:
action.save_binary(stream)
stream.write_dword(len(self.item_power_action))
for grant in self.item_power_action:
grant.save_binary(stream)
stream.write_bool(self.item_sheathable)
if self.item_sheathable:
stream.write_dword(self.item_sheath_slot)
stream.write_tuple(self.item_sheath_offset)
stream.write_tuple(self.item_sheath_rotation)
stream.write_bool(self.item_has_stub)
if self.item_has_stub:
stream.write_bool(self.item_stub_holder[0])
stream.write_qword(self.item_stub_holder[1])
stream.write_dword(len(self.item_offering_adjustments))
for offering in self.item_offering_adjustments:
offering.save_binary(stream)
stream.write_dword(len(self.item_resource_costs))
for res in self.item_resource_costs:
res.save_binary(stream)
stream.write_dword(self.item_bane_rank)
stream.write_bool(self.item_ignore_saved_actions)
def load_json(self, data):
super().load_json(data)
self.item_type = STRING_TO_ITEM_TYPE[data['item_type']]
self.item_eq_slots_value = data['item_eq_slots_value']
self.item_eq_slots_type = data['item_eq_slots_type']
value = 0
for i in range(ITEM_EQUIP_SLOT_NUM):
eq_slot = 1 << i
if ITEM_EQIP_SLOT_TO_STRING[eq_slot] in data['item_eq_slots_or']:
value |= eq_slot
self.item_eq_slots_or = value
value = 0
for i in range(ITEM_EQUIP_SLOT_NUM):
eq_slot = 1 << i
if ITEM_EQIP_SLOT_TO_STRING[eq_slot] in data['item_eq_slots_and']:
value |= eq_slot
self.item_eq_slots_and = value
self.item_takeable = data['item_takeable']
self.item_value = data['item_value']
self.item_wt = data['item_wt']
self.item_passive_defense_mod = data['item_passive_defense_mod']
self.item_base_name = data['item_base_name']
self.item_dsc = data['item_dsc']
self.item_render_object_female = data['item_render_object_female']
self.item_health_full = data['item_health_full']
self.item_skill_used = string_to_hash(data['item_skill_used'])
self.item_skill_mastery_used = string_to_hash(data['item_skill_mastery_used'])
self.item_parry_anim_id = data['item_parry_anim_id']
self.item_offering_info = []
for offering_data in data['item_offering_info']:
offering = Offerings()
offering.load_json(offering_data)
self.item_offering_info.append(offering)
if self.item_type == ITEM_TYPE_WEAPON:
self.item_weapon = Weapon()
self.item_weapon.load_json(data['item_weapon'])
self.item_primary_attr = string_to_hash(data['item_primary_attr'])
self.item_secondary_attr = string_to_hash(data['item_secondary_attr'])
if self.item_type == ITEM_TYPE_ARMOR:
self.item_bulk_factor = data['item_bulk_factor']
self.item_defense_rating = data['item_defense_rating']
value = 0
for i in range(ITEM_FLAG_NUM):
item_flag = 1 << i
if ITEM_FLAG_TO_STRING[item_flag] in data['item_flags']:
value |= item_flag
self.item_flags = value
value = 0
for i in range(ITEM_USE_FLAGS_NUM):
item_use_flag = 1 << i
if ITEM_USE_FLAGS_TO_STRING[item_use_flag] in data['item_use_flags']:
value |= item_use_flag
self.item_use_flags = value
self.item_post_item_id = data['item_post_item_id']
self.item_initial_charges = data['item_initial_charges']
self.item_book_arcana = data['item_book_arcana']
self.item_skill_req = []
for skill_data in data['item_skill_req']:
skill = SkillLevel()
skill.load_json(skill_data)
self.item_skill_req.append(skill)
self.item_race_req = RaceRequired()
self.item_race_req.load_json(data['item_race_req'])
self.item_class_req = ClassRequired()
self.item_class_req.load_json(data['item_class_req'])
self.item_disc_req = DiscRequired()
self.item_disc_req.load_json(data['item_disc_req'])
self.item_attr_req = []
for attr_data in data['item_attr_req']:
attr = AttributeValue()
attr.load_json(attr_data)
self.item_attr_req.append(attr)
self.item_level_req = data['item_level_req']
self.item_rank_req = data['item_rank_req']
self.item_sex_req = STRING_TO_ITEM_SEX_REQ[data['item_sex_req']]
self.item_user_power_action = []
for action in data['item_user_power_action']:
self.item_user_power_action.append([
string_to_hash(action['power']),
action['arguments'][0],
action['arguments'][1],
])
self.item_power_grant = []
for grant_data in data['item_power_grant']:
grant = PowerGrant()
grant.load_json(grant_data)
self.item_power_grant.append(grant)
self.item_power_action = []
for action_data in data['item_power_action']:
action = PowerAction()
action.load_json(action_data)
self.item_power_action.append(action)
self.item_sheathable = data['item_sheathable']
if self.item_sheathable:
self.item_sheath_slot = STRING_TO_ITEM_SHEATHSLOT[data['item_sheath_slot']]
self.item_sheath_offset = data['item_sheath_offset']
self.item_sheath_rotation = data['item_sheath_rotation']
self.item_has_stub = data['item_has_stub']
if self.item_has_stub:
self.item_stub_holder = data['item_has_stub']
self.item_offering_adjustments = []
for offering_data in data['item_offering_adjustments']:
offering = Offerings()
offering.load_json(offering_data)
self.item_offering_adjustments.append(offering)
self.item_resource_costs = []
for res_data in data['item_resource_costs']:
res = ResourceInfo()
res.load_json(res_data)
self.item_resource_costs.append(res)
self.item_bane_rank = data['item_bane_rank']
self.item_ignore_saved_actions = data['item_ignore_saved_actions']
def save_json(self):
data = super().save_json()
data['item_type'] = ITEM_TYPE_TO_STRING[self.item_type]
data['item_eq_slots_value'] = self.item_eq_slots_value
data['item_eq_slots_type'] = self.item_eq_slots_type
if not self.item_eq_slots_or:
data['item_eq_slots_or'] = [ITEM_EQIP_SLOT_TO_STRING[ITEM_EQUIP_SLOT_NONE]]
else:
data['item_eq_slots_or'] = []
for i in range(ITEM_EQUIP_SLOT_NUM):
eq_slot = 1 << i
if self.item_eq_slots_or & eq_slot:
data['item_eq_slots_or'].append(ITEM_EQIP_SLOT_TO_STRING[eq_slot])
if not self.item_eq_slots_and:
data['item_eq_slots_and'] = [ITEM_EQIP_SLOT_TO_STRING[ITEM_EQUIP_SLOT_NONE]]
else:
data['item_eq_slots_and'] = []
for i in range(ITEM_EQUIP_SLOT_NUM):
eq_slot = 1 << i
if self.item_eq_slots_and & eq_slot:
data['item_eq_slots_and'].append(ITEM_EQIP_SLOT_TO_STRING[eq_slot])
data['item_takeable'] = self.item_takeable
data['item_value'] = self.item_value
data['item_wt'] = self.item_wt
data['item_passive_defense_mod'] = self.item_passive_defense_mod
data['item_base_name'] = self.item_base_name
data['item_dsc'] = self.item_dsc
data['item_render_object_female'] = self.item_render_object_female
data['item_health_full'] = self.item_health_full
data['item_skill_used'] = hash_to_string(self.item_skill_used)
data['item_skill_mastery_used'] = hash_to_string(self.item_skill_mastery_used)
data['item_parry_anim_id'] = self.item_parry_anim_id
data['item_offering_info'] = []
for offering in self.item_offering_info:
data['item_offering_info'].append(offering.save_json())
if self.item_type == ITEM_TYPE_WEAPON:
data['item_weapon'] = self.item_weapon.save_json()
data['item_primary_attr'] = hash_to_string(self.item_primary_attr)
data['item_secondary_attr'] = hash_to_string(self.item_secondary_attr)
if self.item_type == ITEM_TYPE_ARMOR:
data['item_bulk_factor'] = self.item_bulk_factor
data['item_defense_rating'] = self.item_defense_rating
data['item_flags'] = []
if self.item_flags:
for i in range(ITEM_FLAG_NUM):
item_flag = 1 << i
if self.item_flags & item_flag:
data['item_flags'].append(ITEM_FLAG_TO_STRING[item_flag])
data['item_use_flags'] = []
if self.item_use_flags:
for i in range(ITEM_USE_FLAGS_NUM):
item_use_flag = 1 << i
if self.item_use_flags & item_use_flag:
data['item_use_flags'].append(ITEM_USE_FLAGS_TO_STRING[item_use_flag])
data['item_post_item_id'] = self.item_post_item_id
data['item_initial_charges'] = self.item_initial_charges
data['item_book_arcana'] = self.item_book_arcana
data['item_skill_req'] = []
for skill in self.item_skill_req:
data['item_skill_req'].append(skill.save_json())
data['item_race_req'] = self.item_race_req.save_json()
data['item_class_req'] = self.item_class_req.save_json()
data['item_disc_req'] = self.item_disc_req.save_json()
data['item_attr_req'] = []
for attr in self.item_attr_req:
data['item_attr_req'].append(attr.save_json())
data['item_level_req'] = self.item_level_req
data['item_rank_req'] = self.item_rank_req
data['item_sex_req'] = ITEM_SEX_REQ_TO_STRING[self.item_sex_req]
data['item_user_power_action'] = []
for action in self.item_user_power_action:
data['item_user_power_action'].append({
'power': hash_to_string(action[0]),
'arguments': action[1:3],
})
data['item_power_grant'] = []
for grant in self.item_power_grant:
data['item_power_grant'].append(grant.save_json())
data['item_power_action'] = []
for action in self.item_power_action:
data['item_power_action'].append(action.save_json())
data['item_sheathable'] = self.item_sheathable
if self.item_sheathable:
data['item_sheath_slot'] = ITEM_SHEATHSLOT_TO_STRING[self.item_sheath_slot]
data['item_sheath_offset'] = self.item_sheath_offset
data['item_sheath_rotation'] = self.item_sheath_rotation
data['item_has_stub'] = self.item_has_stub
if self.item_has_stub:
data['item_has_stub'] = self.item_stub_holder
data['item_offering_adjustments'] = []
for offering in self.item_offering_adjustments:
data['item_offering_adjustments'].append(offering.save_json())
data['item_resource_costs'] = []
for res in self.item_resource_costs:
data['item_resource_costs'].append(res.save_json())
data['item_bane_rank'] = self.item_bane_rank
data['item_ignore_saved_actions'] = self.item_ignore_saved_actions
return data