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
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
|
|
|