mbEditorPro2.0 release

This commit is contained in:
2022-12-25 08:47:00 -05:00
parent 30375c8413
commit 942b33a252
110 changed files with 3543 additions and 1089 deletions
@@ -0,0 +1,29 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from arcane.util import ResStream
from .ArcStructureObject import ArcStructureObject
class ArcAssetStructureObject(ArcStructureObject):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
self.asset_structure_template_id = stream.read_qword()
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.write_qword(self.asset_structure_template_id)
def load_json(self, data):
super().load_json(data)
self.asset_structure_template_id = data['asset_structure_template_id']
def save_json(self):
data = super().save_json()
data['asset_structure_template_id'] = self.asset_structure_template_id
return data
@@ -0,0 +1,386 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.util import ResStream
class RankInfo:
def load_binary(self, stream: ResStream):
self.rank_hirelings = stream.read_dword()
self.rank_shrines = stream.read_dword()
self.rank_spires = stream.read_dword()
self.rank_barracks = stream.read_dword()
self.rank_rank = stream.read_dword()
self.rank_health = stream.read_dword()
self.rank_automatic = stream.read_bool()
self.rank_energy_k1 = stream.read_float()
self.rank_energy_k2 = stream.read_float()
self.rank_level_val = stream.read_float()
num_builiding_ids = stream.read_dword()
self.rank_building_id = [
[
stream.read_dword(),
stream.read_qword(),
] for _ in range(num_builiding_ids)
]
self.rank_formula = stream.read_dword()
num_placement_limits = stream.read_dword()
self.rank_placement_limit = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_placement_limits)
]
def save_binary(self, stream: ResStream):
stream.write_dword(self.rank_hirelings)
stream.write_dword(self.rank_shrines)
stream.write_dword(self.rank_spires)
stream.write_dword(self.rank_barracks)
stream.write_dword(self.rank_rank)
stream.write_dword(self.rank_health)
stream.write_bool(self.rank_automatic)
stream.write_float(self.rank_energy_k1)
stream.write_float(self.rank_energy_k2)
stream.write_float(self.rank_level_val)
stream.write_dword(len(self.rank_building_id))
for building in self.rank_building_id:
stream.write_dword(building[0])
stream.write_qword(building[1])
stream.write_dword(self.rank_formula)
stream.write_dword(len(self.rank_placement_limit))
for placement in self.rank_placement_limit:
stream.write_dword(placement[0])
stream.write_dword(placement[1])
def load_json(self, data):
self.rank_hirelings = data['rank_hirelings']
self.rank_shrines = data['rank_shrines']
self.rank_spires = data['rank_spires']
self.rank_barracks = data['rank_barracks']
self.rank_rank = data['rank_rank']
self.rank_health = data['rank_health']
self.rank_automatic = data['rank_automatic']
self.rank_energy_k1 = data['rank_energy_k1']
self.rank_energy_k2 = data['rank_energy_k2']
self.rank_level_val = data['rank_level_val']
self.rank_building_id = data['rank_building_id']
self.rank_formula = data['rank_formula']
self.rank_placement_limit = data['rank_placement_limit']
def save_json(self):
data = OrderedDict()
data['rank_hirelings'] = self.rank_hirelings
data['rank_shrines'] = self.rank_shrines
data['rank_spires'] = self.rank_spires
data['rank_barracks'] = self.rank_barracks
data['rank_rank'] = self.rank_rank
data['rank_health'] = self.rank_health
data['rank_automatic'] = self.rank_automatic
data['rank_energy_k1'] = self.rank_energy_k1
data['rank_energy_k2'] = self.rank_energy_k2
data['rank_level_val'] = self.rank_level_val
data['rank_building_id'] = self.rank_building_id
data['rank_formula'] = self.rank_formula
data['rank_placement_limit'] = self.rank_placement_limit
return data
class ArcCityAssetTemplate():
def load_binary(self, stream: ResStream):
self.template_max_ranks = stream.read_dword()
self.template_start_rank = stream.read_dword()
self.template_asset_type = stream.read_dword()
self.template_trade_icon = stream.read_dword()
self.template_landmark = stream.read_dword()
self.template_is_maintenance = stream.read_bool()
self.template_has_keys = stream.read_bool()
self.template_use_hardpoints = stream.read_bool()
self.template_is_fort_asset = stream.read_bool()
self.template_is_building_of_war = stream.read_bool()
self.template_bow_can_place_on_grid = stream.read_bool()
self.template_requires_nation_tree_slot = stream.read_bool()
self.template_requires_guild_tree_slot = stream.read_bool()
self.template_use_fort_grid = stream.read_bool()
self.template_is_fort_start = stream.read_bool()
self.template_is_cap_asset = stream.read_bool()
self.template_zone_no_build = [
stream.read_float(),
stream.read_float(),
]
self.template_zone_influence = [
stream.read_float(),
stream.read_float(),
]
self.template_eject_loc = stream.read_tuple()
self.template_npc_load = stream.read_tuple()
self.template_fort_grid_offset = stream.read_tuple()
self.template_power_action_id = stream.read_dword()
self.template_zone_flag = stream.read_dword()
self.template_spire_event_rule = stream.read_dword()
self.template_maintenance_set = stream.read_dword()
self.template_damage_set = stream.read_dword()
self.template_energy_set = stream.read_dword()
self.template_use_trigger = stream.read_string()
self.template_unknown_check1 = stream.read_bool()
if self.template_unknown_check1:
pass
self.template_loot_trigger = stream.read_string()
self.template_unknown_check2 = stream.read_bool()
if self.template_unknown_check2:
pass
self.has_embedded_template = stream.read_bool()
if self.has_embedded_template:
self.template_embed_template = ArcCityAssetTemplate()
self.template_embed_template.load_binary(stream)
num_creators = stream.read_dword()
self.template_creator = [
stream.read_dword() for _ in range(num_creators)
]
num_terrains = stream.read_dword()
self.template_terrain = [
stream.read_dword() for _ in range(num_terrains)
]
num_valid_npc_types = stream.read_dword()
self.template_valid_npc_type = [
stream.read_dword() for _ in range(num_valid_npc_types)
]
num_valid_npc_cat = stream.read_dword()
self.template_valid_npc_cat = [
stream.read_dword() for _ in range(num_valid_npc_cat)
]
num_rank_info = stream.read_dword()
self.template_rank_info = [RankInfo() for _ in range(num_rank_info)]
for rank_info in self.template_rank_info:
rank_info.load_binary(stream)
num_cap_info = stream.read_dword()
self.template_cap_info = [
[
stream.read_dword(),
stream.read_dword(),
stream.read_qword(),
] for _ in range(num_cap_info)
]
num_event_rules = stream.read_dword()
self.template_event_rules = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_event_rules)
]
num_archs = stream.read_dword()
self.template_architecture = [
stream.read_string() for _ in range(num_archs)
]
self.template_offering_type = stream.read_string()
self.template_placement_type = stream.read_dword()
num_offering_adjusts = stream.read_dword()
self.template_offering_adjustment = [
[
stream.read_dword(),
stream.read_float(),
] for _ in range(num_offering_adjusts)
]
num_resource_limit = stream.read_dword()
self.template_resource_limit = [
[
stream.read_dword(),
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_resource_limit)
]
self.template_unknown = stream.read_dword()
def save_binary(self, stream: ResStream):
stream.write_dword(self.template_max_ranks)
stream.write_dword(self.template_start_rank)
stream.write_dword(self.template_asset_type)
stream.write_dword(self.template_trade_icon)
stream.write_dword(self.template_landmark)
stream.write_bool(self.template_is_maintenance)
stream.write_bool(self.template_has_keys)
stream.write_bool(self.template_use_hardpoints)
stream.write_bool(self.template_is_fort_asset)
stream.write_bool(self.template_is_building_of_war)
stream.write_bool(self.template_bow_can_place_on_grid)
stream.write_bool(self.template_requires_nation_tree_slot)
stream.write_bool(self.template_requires_guild_tree_slot)
stream.write_bool(self.template_use_fort_grid)
stream.write_bool(self.template_is_fort_start)
stream.write_bool(self.template_is_cap_asset)
stream.write_float(self.template_zone_no_build[0])
stream.write_float(self.template_zone_no_build[1])
stream.write_float(self.template_zone_influence[0])
stream.write_float(self.template_zone_influence[1])
stream.write_tuple(self.template_eject_loc)
stream.write_tuple(self.template_npc_load)
stream.write_tuple(self.template_fort_grid_offset)
stream.write_dword(self.template_power_action_id)
stream.write_dword(self.template_zone_flag)
stream.write_dword(self.template_spire_event_rule)
stream.write_dword(self.template_maintenance_set)
stream.write_dword(self.template_damage_set)
stream.write_dword(self.template_energy_set)
stream.write_string(self.template_use_trigger)
stream.write_bool(self.template_unknown_check1)
stream.write_string(self.template_loot_trigger)
stream.write_bool(self.template_unknown_check2)
stream.write_bool(self.has_embedded_template)
if self.has_embedded_template:
self.template_embed_template.save_binary(stream)
stream.write_dword(len(self.template_creator))
for creator in self.template_creator:
stream.write_dword(creator)
stream.write_dword(len(self.template_terrain))
for terrain in self.template_terrain:
stream.write_dword(terrain)
stream.write_dword(len(self.template_valid_npc_type))
for npc_type in self.template_valid_npc_type:
stream.write_dword(npc_type)
stream.write_dword(len(self.template_valid_npc_cat))
for npc_cat in self.template_valid_npc_cat:
stream.write_dword(npc_cat)
stream.write_dword(len(self.template_rank_info))
for rank_info in self.template_rank_info:
rank_info.save_binary(stream)
stream.write_dword(len(self.template_cap_info))
for cap in self.template_cap_info:
stream.write_dword(cap[0])
stream.write_dword(cap[1])
stream.write_qword(cap[2])
stream.write_dword(len(self.template_event_rules))
for event in self.template_event_rules:
stream.write_dword(event[0])
stream.write_dword(event[1])
stream.write_dword(len(self.template_architecture))
for arch in self.template_architecture:
stream.write_string(arch)
stream.write_string(self.template_offering_type)
stream.write_dword(self.template_placement_type)
stream.write_dword(len(self.template_offering_adjustment))
for adjust in self.template_offering_adjustment:
stream.write_dword(adjust[0])
stream.write_float(adjust[1])
stream.write_dword(len(self.template_resource_limit))
for resource in self.template_resource_limit:
stream.write_dword(resource[0])
stream.write_dword(resource[1])
stream.write_dword(resource[2])
stream.write_dword(self.template_unknown)
def load_json(self, data):
self.template_max_ranks = data['template_max_ranks']
self.template_start_rank = data['template_start_rank']
self.template_asset_type = data['template_asset_type']
self.template_trade_icon = data['template_trade_icon']
self.template_landmark = data['template_landmark']
self.template_is_maintenance = data['template_is_maintenance']
self.template_has_keys = data['template_has_keys']
self.template_use_hardpoints = data['template_use_hardpoints']
self.template_is_fort_asset = data['template_is_fort_asset']
self.template_is_building_of_war = data['template_is_building_of_war']
self.template_bow_can_place_on_grid = data['template_bow_can_place_on_grid']
self.template_requires_nation_tree_slot = data['template_requires_nation_tree_slot']
self.template_requires_guild_tree_slot = data['template_requires_guild_tree_slot']
self.template_use_fort_grid = data['template_use_fort_grid']
self.template_is_fort_start = data['template_is_fort_start']
self.template_is_cap_asset = data['template_is_cap_asset']
self.template_zone_no_build = data['template_zone_no_build']
self.template_zone_influence = data['template_zone_influence']
self.template_eject_loc = data['template_eject_loc']
self.template_npc_load = data['template_npc_load']
self.template_fort_grid_offset = data['template_fort_grid_offset']
self.template_power_action_id = data['template_power_action_id']
self.template_zone_flag = data['template_zone_flag']
self.template_spire_event_rule = data['template_spire_event_rule']
self.template_maintenance_set = data['template_maintenance_set']
self.template_damage_set = data['template_damage_set']
self.template_energy_set = data['template_energy_set']
self.template_use_trigger = data['template_use_trigger']
self.template_unknown_check1 = data['template_unknown_check1']
self.template_loot_trigger = data['template_loot_trigger']
self.template_unknown_check2 = data['template_unknown_check2']
self.has_embedded_template = data['has_embedded_template']
if self.has_embedded_template:
self.template_embed_template = ArcCityAssetTemplate()
self.template_embed_template.load_json(data['template_embed_template'])
self.template_creator = data['template_creator']
self.template_terrain = data['template_terrain']
self.template_valid_npc_type = data['template_valid_npc_type']
self.template_valid_npc_cat = data['template_valid_npc_cat']
self.template_rank_info = []
for rank_info_data in data['template_rank_info']:
rank_info = RankInfo()
rank_info.load_json(rank_info_data)
self.template_rank_info.append(rank_info)
self.template_cap_info = data['template_cap_info']
self.template_event_rules = data['template_event_rules']
self.template_architecture = data['template_architecture']
self.template_offering_type = data['template_offering_type']
self.template_placement_type = data['template_placement_type']
self.template_offering_adjustment = data['template_offering_adjustment']
self.template_resource_limit = data['template_resource_limit']
self.template_unknown = data['template_unknown']
def save_json(self):
data = OrderedDict()
data['template_max_ranks'] = self.template_max_ranks
data['template_start_rank'] = self.template_start_rank
data['template_asset_type'] = self.template_asset_type
data['template_trade_icon'] = self.template_trade_icon
data['template_landmark'] = self.template_landmark
data['template_is_maintenance'] = self.template_is_maintenance
data['template_has_keys'] = self.template_has_keys
data['template_use_hardpoints'] = self.template_use_hardpoints
data['template_is_fort_asset'] = self.template_is_fort_asset
data['template_is_building_of_war'] = self.template_is_building_of_war
data['template_bow_can_place_on_grid'] = self.template_bow_can_place_on_grid
data['template_requires_nation_tree_slot'] = self.template_requires_nation_tree_slot
data['template_requires_guild_tree_slot'] = self.template_requires_guild_tree_slot
data['template_use_fort_grid'] = self.template_use_fort_grid
data['template_is_fort_start'] = self.template_is_fort_start
data['template_is_cap_asset'] = self.template_is_cap_asset
data['template_zone_no_build'] = self.template_zone_no_build
data['template_zone_influence'] = self.template_zone_influence
data['template_eject_loc'] = self.template_eject_loc
data['template_npc_load'] = self.template_npc_load
data['template_fort_grid_offset'] = self.template_fort_grid_offset
data['template_power_action_id'] = self.template_power_action_id
data['template_zone_flag'] = self.template_zone_flag
data['template_spire_event_rule'] = self.template_spire_event_rule
data['template_maintenance_set'] = self.template_maintenance_set
data['template_damage_set'] = self.template_damage_set
data['template_energy_set'] = self.template_energy_set
data['template_use_trigger'] = self.template_use_trigger
data['template_unknown_check1'] = self.template_unknown_check1
data['template_loot_trigger'] = self.template_loot_trigger
data['template_unknown_check2'] = self.template_unknown_check2
data['has_embedded_template'] = self.has_embedded_template
if self.has_embedded_template:
data['template_embed_template'] = self.template_embed_template.save_json()
data['template_creator'] = self.template_creator
data['template_terrain'] = self.template_terrain
data['template_valid_npc_type'] = self.template_valid_npc_type
data['template_valid_npc_cat'] = self.template_valid_npc_cat
data['template_rank_info'] = []
for rank_info in self.template_rank_info:
data['template_rank_info'].append(rank_info.save_json())
data['template_cap_info'] = self.template_cap_info
data['template_event_rules'] = self.template_event_rules
data['template_architecture'] = self.template_architecture
data['template_offering_type'] = self.template_offering_type
data['template_placement_type'] = self.template_placement_type
data['template_offering_adjustment'] = self.template_offering_adjustment
data['template_resource_limit'] = self.template_resource_limit
data['template_unknown'] = self.template_unknown
return data
@@ -0,0 +1,68 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.arc_combat import *
from arcane.util import ResStream
from .ArcObj import ArcObj
class ArcCombatObj(ArcObj):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
self.combat_health_current = stream.read_float()
self.combat_health_full = stream.read_float()
self.combat_attack_resist = [
stream.read_float() for _ in range(0x10)
]
num_powers = stream.read_dword()
self.combat_powers = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_powers)
]
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.write_float(self.combat_health_current)
stream.write_float(self.combat_health_full)
for i in range(0x10):
stream.write_float(self.combat_attack_resist[i])
stream.write_dword(len(self.combat_powers))
for power in self.combat_powers:
stream.write_dword(power[0])
stream.write_dword(power[1])
def load_json(self, data):
super().load_json(data)
self.combat_health_current = data['combat_health_current']
self.combat_health_full = data['combat_health_full']
self.combat_attack_resist = []
for i in range(0x10):
self.combat_attack_resist.append(data['combat_attack_resist'][
ATTACK_RESIST_TO_STRING[i]
])
self.combat_powers = data['combat_powers']
def save_json(self):
data = super().save_json()
data['combat_health_current'] = self.combat_health_current
data['combat_health_full'] = self.combat_health_full
data['combat_attack_resist'] = OrderedDict()
for i in range(0x10):
data['combat_attack_resist'][
ATTACK_RESIST_TO_STRING[i]
] = self.combat_attack_resist[i]
data['combat_powers'] = self.combat_powers
return data
class ArcCharacter(ArcCombatObj):
pass
@@ -0,0 +1,69 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from arcane.util import ResStream
from .ArcItem import ArcItem
from .common.Inventory import Inventory
class ArcContainerObject(ArcItem):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
self.container_open = stream.read_dword()
self.container_locked = stream.read_dword()
self.container_locked_rank = stream.read_dword()
self.container_barred = stream.read_dword()
self.container_barred_rank = stream.read_dword()
self.container_trapped = stream.read_dword()
self.container_trappe_rank = stream.read_dword()
num_contents = stream.read_dword()
self.container_inventory_contents = [Inventory() for _ in range(num_contents)]
for content in self.container_inventory_contents:
content.load_binary(stream)
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.read_dword(self.container_open)
stream.read_dword(self.container_locked)
stream.read_dword(self.container_locked_rank)
stream.read_dword(self.container_barred)
stream.read_dword(self.container_barred_rank)
stream.read_dword(self.container_trapped)
stream.read_dword(self.container_trappe_rank)
stream.read_dword(len(self.container_inventory_contents))
for content in self.container_inventory_contents:
content.save_binary(stream)
def load_json(self, data):
super().load_json()
self.container_open = data['container_open']
self.container_locked = data['container_locked']
self.container_locked_rank = data['container_locked_rank']
self.container_barred = data['container_barred']
self.container_barred_rank = data['container_barred_rank']
self.container_trapped = data['container_trapped']
self.container_trappe_rank = data['container_trappe_rank']
self.container_inventory_contents = []
for content_data in data['container_inventory_contents']:
content = Inventory()
content.load_json(content_data)
self.container_inventory_contents.append(content)
def save_json(self):
data = super().save_json()
data['container_open'] = self.container_open
data['container_locked'] = self.container_locked
data['container_locked_rank'] = self.container_locked_rank
data['container_barred'] = self.container_barred
data['container_barred_rank'] = self.container_barred_rank
data['container_trapped'] = self.container_trapped
data['container_trappe_rank'] = self.container_trappe_rank
data['container_inventory_contents'] = []
for content in self.container_inventory_contents:
data['container_inventory_contents'].append(content.save_json())
return data
+83
View File
@@ -0,0 +1,83 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from arcane.util import ResStream
from .ArcItem import ArcItem
class ArcDeed(ArcItem):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
self.deed_type = stream.read_dword()
self.deed_furniture_id = stream.read_qword()
self.deed_target_id = stream.read_qword()
self.deed_employment = stream.read_dword()
self.deed_start_rank = stream.read_dword()
self.deed_name_lookup = stream.read_dword()
self.deed_indoors = stream.read_bool()
self.deed_is_fortress = stream.read_bool()
self.deed_namelookup_val = stream.read_float()
self.deed_custom_city = stream.read_bool()
if self.deed_custom_city:
set_length = stream.read_dword()
self.deed_custom_city_set = [
stream.read_dword() for _ in range(set_length)
]
self.deed_structure_id = stream.read_qword()
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.write_dword(self.deed_type)
stream.write_qword(self.deed_furniture_id)
stream.write_qword(self.deed_target_id)
stream.write_dword(self.deed_employment)
stream.write_dword(self.deed_start_rank)
stream.write_dword(self.deed_name_lookup)
stream.write_bool(self.deed_indoors)
stream.write_bool(self.deed_is_fortress)
stream.write_float(self.deed_namelookup_val)
stream.write_bool(self.deed_custom_city)
if self.deed_custom_city:
stream.write_dword(len(self.deed_custom_city_set))
for city in self.deed_custom_city_set:
stream.write_dword(city)
stream.write_qword(self.deed_structure_id)
def load_json(self, data):
super().load_json(data)
self.deed_type = data['deed_type']
self.deed_furniture_id = data['deed_furniture_id']
self.deed_target_id = data['deed_target_id']
self.deed_employment = data['deed_employment']
self.deed_start_rank = data['deed_start_rank']
self.deed_name_lookup = data['deed_name_lookup']
self.deed_indoors = data['deed_indoors']
self.deed_is_fortress = data['deed_is_fortress']
self.deed_namelookup_val = data['deed_namelookup_val']
self.deed_custom_city = data['deed_custom_city']
if self.deed_custom_city:
self.deed_custom_city_set = data['deed_custom_city_set']
self.deed_structure_id = data['deed_structure_id']
def save_json(self):
data = super().save_json()
data['deed_type'] = self.deed_type
data['deed_furniture_id'] = self.deed_furniture_id
data['deed_target_id'] = self.deed_target_id
data['deed_employment'] = self.deed_employment
data['deed_start_rank'] = self.deed_start_rank
data['deed_name_lookup'] = self.deed_name_lookup
data['deed_indoors'] = self.deed_indoors
data['deed_is_fortress'] = self.deed_is_fortress
data['deed_namelookup_val'] = self.deed_namelookup_val
data['deed_custom_city'] = self.deed_custom_city
if self.deed_custom_city:
data['deed_custom_city_set'] = self.deed_custom_city_set
data['deed_structure_id'] = self.deed_structure_id
return data
@@ -0,0 +1,88 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.arc_door import *
from arcane.util import ResStream
class ArcDoorObject():
def load_binary(self, stream: ResStream):
self.door_id = stream.read_qword()
self.door_type = stream.read_dword()
self.door_movement_axis = stream.read_dword()
self.door_swing_direction = stream.read_dword()
self.door_min_time_to_stay_open = stream.read_float()
self.door_max_time_to_stay_open = stream.read_float()
self.door_swing_time = stream.read_float()
self.door_swing = stream.read_float()
self.door_slide_distance = stream.read_float()
self.door_slide_direction = stream.read_tuple()
self.door_slide_start = stream.read_tuple()
self.door_slide_end = stream.read_tuple()
self.door_locked = stream.read_dword()
self.door_linked_to = stream.read_qword()
self.door_key = stream.read_qword()
self.door_sound_event = stream.read_qword()
def save_binary(self, stream: ResStream):
stream.write_qword(self.door_id)
stream.write_dword(self.door_type)
stream.write_dword(self.door_movement_axis)
stream.write_dword(self.door_swing_direction)
stream.write_float(self.door_min_time_to_stay_open)
stream.write_float(self.door_max_time_to_stay_open)
stream.write_float(self.door_swing_time)
stream.write_float(self.door_swing)
stream.write_float(self.door_slide_distance)
stream.write_tuple(self.door_slide_direction)
stream.write_tuple(self.door_slide_start)
stream.write_tuple(self.door_slide_end)
stream.write_dword(self.door_locked)
stream.write_qword(self.door_linked_to)
stream.write_qword(self.door_key)
stream.write_qword(self.door_sound_event)
def load_json(self, data):
self.door_id = data['door_id']
self.door_type = STRING_TO_DOOR_TYPE[data['door_type']]
self.door_movement_axis = STRING_TO_DOOR_MOVEMENT_AXIS[data['door_movement_axis']]
self.door_swing_direction = STRING_TO_DOOR_SWING_DIRECTION[data['door_swing_direction']]
self.door_min_time_to_stay_open = data['door_min_time_to_stay_open']
self.door_max_time_to_stay_open = data['door_max_time_to_stay_open']
self.door_swing_time = data['door_swing_time']
self.door_swing = data['door_swing']
self.door_slide_distance = data['door_slide_distance']
self.door_slide_direction = data['door_slide_direction']
self.door_slide_start = data['door_slide_start']
self.door_slide_end = data['door_slide_end']
self.door_locked = data['door_locked']
self.door_linked_to = data['door_linked_to']
self.door_key = data['door_key']
self.door_sound_event = data['door_sound_event']
def save_json(self):
data = OrderedDict()
data['door_id'] = self.door_id
data['door_type'] = DOOR_TYPE_TO_STRING[self.door_type]
data['door_movement_axis'] = DOOR_MOVEMENT_AXIS_TO_STRING[self.door_movement_axis]
data['door_swing_direction'] = DOOR_SWING_DIRECTION_TO_STRING[self.door_swing_direction]
data['door_min_time_to_stay_open'] = self.door_min_time_to_stay_open
data['door_max_time_to_stay_open'] = self.door_max_time_to_stay_open
data['door_swing_time'] = self.door_swing_time
data['door_swing'] = self.door_swing
data['door_slide_distance'] = self.door_slide_distance
data['door_slide_direction'] = self.door_slide_direction
data['door_slide_start'] = self.door_slide_start
data['door_slide_end'] = self.door_slide_end
data['door_locked'] = self.door_locked
data['door_linked_to'] = self.door_linked_to
data['door_key'] = self.door_key
data['door_sound_event'] = self.door_sound_event
return data
@@ -0,0 +1,43 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from arcane.util.ResStream import ResStream
from .ArcStructureObject import ArcStructureObject
class ArcDungeonUnitObject(ArcStructureObject):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
num_connectables = stream.read_dword()
self.dungeon_connectable_edges = [
stream.read_dword() for _ in range(num_connectables)
]
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.write_dword(len(self.dungeon_connectable_edges))
for edge in self.dungeon_connectable_edges:
stream.write_dword(edge)
def load_json(self, data):
super().load_json(data)
self.dungeon_connectable_edges = data['dungeon_connectable_edges']
return data
def save_json(self):
data = super().save_json()
data['dungeon_connectable_edges'] = self.dungeon_connectable_edges
return data
class ArcDungeonExitObject(ArcDungeonUnitObject):
pass
class ArcDungeonStairObject(ArcDungeonUnitObject):
pass
+517
View File
@@ -0,0 +1,517 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# 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
+41
View File
@@ -0,0 +1,41 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from arcane.util import ResStream
from .ArcItem import ArcItem
class ArcKey(ArcItem):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
self.key_keyval = stream.read_qword()
self.key_keyval2 = stream.read_qword()
self.key_keyval3 = stream.read_qword()
self.key_setting = stream.read_dword()
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.write_qword(self.key_keyval)
stream.write_qword(self.key_keyval2)
stream.write_qword(self.key_keyval3)
stream.write_dword(self.key_setting)
def load_json(self, data):
super().load_json(data)
self.key_keyval = data['key_keyval']
self.key_keyval2 = data['key_keyval2']
self.key_keyval3 = data['key_keyval3']
self.key_setting = data['key_setting']
def save_json(self):
data = super().save_json()
data['key_keyval'] = self.key_keyval
data['key_keyval2'] = self.key_keyval2
data['key_keyval3'] = self.key_keyval3
data['key_setting'] = self.key_setting
return data
+148
View File
@@ -0,0 +1,148 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.arc_object import *
from arcane.enums.hashes import hash_to_string, string_to_hash
from arcane.util import ResStream
from .common.SparseData import SparseData
class SoundEvent:
def load_binary(self, stream: ResStream):
self.sound_type = stream.read_dword()
self.sound_event = stream.read_qword()
def save_binary(self, stream: ResStream):
stream.write_dword(self.sound_type)
stream.write_qword(self.sound_event)
def load_json(self, data):
self.sound_type = STRING_TO_SOUND_TYPE[data['sound_type']]
self.sound_event = data['sound_event']
def save_json(self):
data = OrderedDict()
data['sound_type'] = SOUND_TYPE_TO_STRING[self.sound_type]
data['sound_event'] = self.sound_event
return data
class ArcObj:
def load_binary(self, stream: ResStream):
self.obj_name = stream.read_string()
self.obj_pickable = stream.read_bool()
self.obj_gravity = stream.read_float()
self.obj_cull_distance = stream.read_float()
self.obj_scale = stream.read_tuple()
self.obj_render_object = stream.read_qword()
self.obj_double_fusion = stream.read_bool()
self.obj_forward_vector = stream.read_tuple()
self.obj_tracking_name = stream.read_string()
self.obj_max_tracking_distance = stream.read_float()
self.obj_icon = stream.read_qword()
self.obj_gravity_f = stream.read_float()
num_sound_events = stream.read_dword()
self.obj_sound_events = [SoundEvent() for _ in range(num_sound_events)]
for sound_event in self.obj_sound_events:
sound_event.load_binary(stream)
num_hard_points = stream.read_dword()
self.obj_arc_hardpoint_list = [
[
stream.read_dword(),
stream.read_dword(),
[stream.read_float() for _ in range(10)]
] for _ in range(num_hard_points)
]
self.obj_sparse_data = SparseData()
self.obj_sparse_data.load_binary(stream)
self.obj_render_object_low_detail = stream.read_qword()
self.obj_default_alignment = stream.read_tuple()
self.obj_sound_table = stream.read_dword()
def save_binary(self, stream: ResStream):
stream.write_string(self.obj_name)
stream.write_bool(self.obj_pickable)
stream.write_float(self.obj_gravity)
stream.write_float(self.obj_cull_distance)
stream.write_tuple(self.obj_scale)
stream.write_qword(self.obj_render_object)
stream.write_bool(self.obj_double_fusion)
stream.write_tuple(self.obj_forward_vector)
stream.write_string(self.obj_tracking_name)
stream.write_float(self.obj_max_tracking_distance)
stream.write_qword(self.obj_icon)
stream.write_float(self.obj_gravity_f)
stream.write_dword(len(self.obj_sound_events))
for sound_event in self.obj_sound_events:
sound_event.save_binary(stream)
stream.write_dword(len(self.obj_arc_hardpoint_list))
for n, m, points in self.obj_arc_hardpoint_list:
stream.write_dword(n)
stream.write_dword(m)
for i in range(10):
stream.write_float(points[i])
self.obj_sparse_data.save_binary(stream)
stream.write_qword(self.obj_render_object_low_detail)
stream.write_tuple(self.obj_default_alignment)
stream.write_dword(self.obj_sound_table)
def load_json(self, data):
self.obj_name = data['obj_name']
self.obj_pickable = data['obj_pickable']
self.obj_gravity = data['obj_gravity']
self.obj_cull_distance = data['obj_cull_distance']
self.obj_scale = data['obj_scale']
self.obj_render_object = data['obj_render_object']
self.obj_double_fusion = data['obj_double_fusion']
self.obj_forward_vector = data['obj_forward_vector']
self.obj_tracking_name = data['obj_tracking_name']
self.obj_max_tracking_distance = data['obj_max_tracking_distance']
self.obj_icon = data['obj_icon']
self.obj_gravity_f = data['obj_gravity_f']
self.obj_sound_events = []
for sound_data in data['obj_sound_events']:
sound_event = SoundEvent()
sound_event.load_json(sound_data)
self.obj_sound_events.append(sound_event)
self.obj_arc_hardpoint_list = []
for point_list in data['obj_arc_hardpoint_list']:
self.obj_arc_hardpoint_list.append(point_list)
self.obj_sparse_data = SparseData()
self.obj_sparse_data.load_json(data['obj_sparse_data'])
self.obj_render_object_low_detail = data['obj_render_object_low_detail']
self.obj_default_alignment = data['obj_default_alignment']
self.obj_sound_table = string_to_hash(data['obj_sound_table'])
return data
def save_json(self):
data = OrderedDict()
data['obj_name'] = self.obj_name
data['obj_pickable'] = self.obj_pickable
data['obj_gravity'] = self.obj_gravity
data['obj_cull_distance'] = self.obj_cull_distance
data['obj_scale'] = self.obj_scale
data['obj_render_object'] = self.obj_render_object
data['obj_double_fusion'] = self.obj_double_fusion
data['obj_forward_vector'] = self.obj_forward_vector
data['obj_tracking_name'] = self.obj_tracking_name
data['obj_max_tracking_distance'] = self.obj_max_tracking_distance
data['obj_icon'] = self.obj_icon
data['obj_gravity_f'] = self.obj_gravity_f
data['obj_sound_events'] = []
for sound_event in self.obj_sound_events:
data['obj_sound_events'].append(sound_event.save_json())
data['obj_arc_hardpoint_list'] = []
for point_list in self.obj_arc_hardpoint_list:
data['obj_arc_hardpoint_list'].append(point_list)
data['obj_sparse_data'] = self.obj_sparse_data.save_json()
data['obj_render_object_low_detail'] = self.obj_render_object_low_detail
data['obj_default_alignment'] = self.obj_default_alignment
data['obj_sound_table'] = hash_to_string(self.obj_sound_table)
return data
+469
View File
@@ -0,0 +1,469 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.arc_rune import *
from arcane.enums.hashes import hash_to_string, string_to_hash
from arcane.util import ResStream
from .ArcItem import ArcItem
from .common.Arcane import AttributeValue, SkillGrant
from .common.Inventory import Inventory
from .common.SparseData import SparseData
class Group:
def load_binary(self, stream: ResStream):
self.group_type = stream.read_dword()
self.group_is_faction = stream.read_bool()
self.group_is_guild = stream.read_bool()
def save_binary(self, stream: ResStream):
stream.write_dword(self.group_type)
stream.write_bool(self.group_is_faction)
stream.write_bool(self.group_is_guild)
def load_json(self, data):
self.group_type = data['group_type']
self.group_is_faction = data['group_is_faction']
self.group_is_guild = data['group_is_guild']
def save_json(self):
data = OrderedDict()
data['group_type'] = self.group_type
data['group_is_faction'] = self.group_is_faction
data['group_is_guild'] = self.group_is_guild
return data
class SkillAdjust:
def load_binary(self, stream: ResStream):
self.skill_type = stream.read_dword()
num_adjusts = stream.read_dword()
self.skill_adjusts = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_adjusts)
]
def save_binary(self, stream: ResStream):
stream.write_dword(self.skill_type)
stream.write_dword(len(self.skill_adjusts))
for skill in self.skill_adjusts:
stream.write_dword(skill[0])
stream.write_dword(skill[1])
def load_json(self, data):
self.skill_type = string_to_hash(data['skill_type'])
self.skill_adjusts = []
for skill in data['skill_adjusts']:
self.skill_adjusts.append(skill)
def save_json(self):
data = OrderedDict()
data['skill_type'] = hash_to_string(self.skill_type)
data['skill_adjusts'] = []
for skill in self.skill_adjusts:
data['skill_adjusts'].append(skill)
return data
class BodyPart:
def load_binary(self, stream: ResStream):
self.body_part_render = stream.read_qword()
self.body_part_position = stream.read_tuple()
def save_binary(self, stream: ResStream):
stream.write_qword(self.body_part_render)
stream.write_tuple(self.body_part_position)
def load_json(self, data):
self.body_part_render = data['body_part_render']
self.body_part_position = data['body_part_position']
def save_json(self):
data = OrderedDict()
data['body_part_render'] = self.body_part_render
data['body_part_position'] = self.body_part_position
return data
class ArcRune(ArcItem):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
self.rune_type = stream.read_dword()
self.rune_sub_type = stream.read_dword()
self.rune_is_standard_character_creation = stream.read_bool()
self.rune_creation_cost = stream.read_dword()
self.rune_rank = stream.read_dword()
self.rune_pracs_per_level = stream.read_dword()
self.rune_exp_req_to_level = stream.read_float()
self.rune_sex = stream.read_dword()
self.rune_class_icon = stream.read_qword()
self.rune_health = stream.read_dword()
self.rune_mana = stream.read_dword()
self.rune_stamina = stream.read_dword()
self.rune_min_damage = stream.read_float()
self.rune_max_damage = stream.read_float()
self.rune_attack = stream.read_dword()
self.rune_defense = stream.read_dword()
self.rune_level = stream.read_dword()
self.rune_speed = [
stream.read_float() for _ in range(7)
]
self.rune_group = Group()
self.rune_group.load_binary(stream)
self.rune_dsc = stream.read_string()
self.rune_fx_txt = stream.read_string()
self.rune_group_tactics = stream.read_dword()
self.rune_group_role_set = stream.read_dword()
num_enemies = stream.read_dword()
self.rune_enemy_monster_types = [
stream.read_dword() for _ in range(num_enemies)
]
num_groupees = stream.read_dword()
self.rune_groupee_monster_types = [
stream.read_dword() for _ in range(num_groupees)
]
num_helpers = stream.read_dword()
self.rune_helper_monster_types = [
stream.read_dword() for _ in range(num_helpers)
]
num_not_enemies = stream.read_dword()
self.rune_not_enemy_monster_types = [
stream.read_dword() for _ in range(num_not_enemies)
]
num_genders = stream.read_dword()
self.rune_enemy_gender = [
stream.read_dword() for _ in range(num_genders)
]
num_skill_grants = stream.read_dword()
self.rune_skill_grant = [SkillGrant() for _ in range(num_skill_grants)]
for grant in self.rune_skill_grant:
grant.load_binary(stream)
num_skill_adjusts = stream.read_dword()
self.rune_skill_adj = [SkillAdjust() for _ in range(num_skill_adjusts)]
for adjust in self.rune_skill_adj:
adjust.load_binary(stream)
num_attr_adjusts = stream.read_dword()
self.rune_attr_adj = [AttributeValue() for _ in range(num_attr_adjusts)]
for attr in self.rune_attr_adj:
attr.load_binary(stream)
num_max_attr_adjusts = stream.read_dword()
self.rune_max_attr_adj = [AttributeValue() for _ in range(num_max_attr_adjusts)]
for attr in self.rune_max_attr_adj:
attr.load_binary(stream)
num_natural_attacks = stream.read_dword()
self.rune_naturalattacks = [
[
stream.read_float(),
stream.read_float(),
stream.read_dword(),
stream.read_dword(),
stream.read_qword(),
stream.read_float(),
stream.read_dword(),
stream.read_dword(),
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_natural_attacks)
]
num_enchants = stream.read_dword()
self.rune_enchantment_type = [
stream.read_dword() for _ in range(num_enchants)
]
num_contents = stream.read_dword()
self.rune_inventory_contents = [Inventory() for _ in range(num_contents)]
for content in self.rune_inventory_contents:
content.load_binary(stream)
self.rune_renderable = stream.read_bool()
if self.rune_renderable:
self.rune_scale_factor = stream.read_tuple()
self.rune_skeleton = stream.read_qword()
self.rune_slope_hugger = stream.read_bool()
self.rune_can_fly = stream.read_bool()
self.rune_death_effect = stream.read_qword()
self.rune_tombstone_id = stream.read_qword()
num_body_parts = stream.read_dword()
self.rune_body_parts = [BodyPart() for _ in range(num_body_parts)]
for part in self.rune_body_parts:
part.load_binary(stream)
num_hair = stream.read_dword()
self.rune_hair = [
stream.read_qword() for _ in range(num_hair)
]
num_beard = stream.read_dword()
self.rune_beard = [
stream.read_qword() for _ in range(num_beard)
]
self.rune_natural_power_attack = stream.read_dword()
self.rune_sparse_data = SparseData()
self.rune_sparse_data.load_binary(stream)
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.write_dword(self.rune_type)
stream.write_dword(self.rune_sub_type)
stream.write_bool(self.rune_is_standard_character_creation)
stream.write_dword(self.rune_creation_cost)
stream.write_dword(self.rune_rank)
stream.write_dword(self.rune_pracs_per_level)
stream.write_float(self.rune_exp_req_to_level)
stream.write_dword(self.rune_sex)
stream.write_qword(self.rune_class_icon)
stream.write_dword(self.rune_health)
stream.write_dword(self.rune_mana)
stream.write_dword(self.rune_stamina)
stream.write_float(self.rune_min_damage)
stream.write_float(self.rune_max_damage)
stream.write_dword(self.rune_attack)
stream.write_dword(self.rune_defense)
stream.write_dword(self.rune_level)
for i in range(7):
stream.write_float(self.rune_speed[i])
self.rune_group.save_binary(stream)
stream.write_string(self.rune_dsc)
stream.write_string(self.rune_fx_txt)
stream.write_dword(self.rune_group_tactics)
stream.write_dword(self.rune_group_role_set)
stream.write_dword(len(self.rune_enemy_monster_types))
for monster in self.rune_enemy_monster_types:
stream.write_dword(monster)
stream.write_dword(len(self.rune_groupee_monster_types))
for monster in self.rune_groupee_monster_types:
stream.write_dword(monster)
stream.write_dword(len(self.rune_helper_monster_types))
for monster in self.rune_helper_monster_types:
stream.write_dword(monster)
stream.write_dword(len(self.rune_not_enemy_monster_types))
for monster in self.rune_not_enemy_monster_types:
stream.write_dword(monster)
stream.write_dword(len(self.rune_enemy_gender))
for gender in self.rune_enemy_gender:
stream.write_dword(gender)
stream.write_dword(len(self.rune_skill_grant))
for grant in self.rune_skill_grant:
grant.save_binary(stream)
stream.write_dword(len(self.rune_skill_adj))
for adjust in self.rune_skill_adj:
adjust.save_binary(stream)
stream.write_dword(len(self.rune_attr_adj))
for attr in self.rune_attr_adj:
attr.save_binary(stream)
stream.write_dword(len(self.rune_max_attr_adj))
for attr in self.rune_max_attr_adj:
attr.save_binary(stream)
stream.write_dword(len(self.rune_naturalattacks))
for attack in self.rune_naturalattacks:
stream.write_float(attack[0])
stream.write_float(attack[1])
stream.write_dword(attack[2])
stream.write_dword(attack[3])
stream.write_qword(attack[4])
stream.write_float(attack[5])
stream.write_dword(attack[6])
stream.write_dword(attack[7])
stream.write_dword(attack[8])
stream.write_dword(attack[9])
stream.write_dword(len(self.rune_enchantment_type))
for enchantment in self.rune_enchantment_type:
stream.write_dword(enchantment)
stream.write_dword(len(self.rune_inventory_contents))
for content in self.rune_inventory_contents:
content.save_binary(stream)
stream.write_bool(self.rune_renderable)
if self.rune_renderable:
stream.write_tuple(self.rune_scale_factor)
stream.write_qword(self.rune_skeleton)
stream.write_bool(self.rune_slope_hugger)
stream.write_bool(self.rune_can_fly)
stream.write_qword(self.rune_death_effect)
stream.write_qword(self.rune_tombstone_id)
stream.write_dword(len(self.rune_body_parts))
for part in self.rune_body_parts:
part.save_binary(stream)
stream.write_dword(len(self.rune_hair))
for hair in self.rune_hair:
stream.write_qword(hair)
stream.write_dword(len(self.rune_beard))
for beard in self.rune_beard:
stream.write_qword(beard)
stream.write_dword(self.rune_natural_power_attack)
self.rune_sparse_data.save_binary(stream)
def load_json(self, data):
super().load_json(data)
self.rune_type = STRING_TO_RUNE_TYPE[data['rune_type']]
self.rune_sub_type = string_to_hash(data['rune_sub_type'])
self.rune_is_standard_character_creation = data['rune_is_standard_character_creation']
self.rune_creation_cost = data['rune_creation_cost']
self.rune_rank = data['rune_rank']
self.rune_pracs_per_level = data['rune_pracs_per_level']
self.rune_exp_req_to_level = data['rune_exp_req_to_level']
self.rune_sex = STRING_TO_RUNE_SEX[data['rune_sex']]
self.rune_class_icon = data['rune_class_icon']
self.rune_health = data['rune_health']
self.rune_mana = data['rune_mana']
self.rune_stamina = data['rune_stamina']
self.rune_min_damage = data['rune_min_damage']
self.rune_max_damage = data['rune_max_damage']
self.rune_attack = data['rune_attack']
self.rune_defense = data['rune_defense']
self.rune_level = data['rune_level']
self.rune_speed = []
for i in range(7):
self.rune_speed.append(data['rune_speed'][SPEED_TYPE_TO_STRING[i]])
self.rune_group = Group()
self.rune_group.load_json(data['rune_group'])
self.rune_dsc = data['rune_dsc']
self.rune_fx_txt = data['rune_fx_txt']
self.rune_group_tactics = data['rune_group_tactics']
self.rune_group_role_set = data['rune_group_role_set']
self.rune_enemy_monster_types = []
for monster in data['rune_enemy_monster_types']:
self.rune_enemy_monster_types.append(string_to_hash(monster))
self.rune_groupee_monster_types = []
for monster in data['rune_groupee_monster_types']:
self.rune_groupee_monster_types.append(string_to_hash(monster))
self.rune_helper_monster_types = []
for monster in data['rune_helper_monster_types']:
self.rune_helper_monster_types.append(string_to_hash(monster))
self.rune_not_enemy_monster_types = []
for monster in data['rune_not_enemy_monster_types']:
self.rune_not_enemy_monster_types.append(string_to_hash(monster))
self.rune_enemy_gender = []
for gender in data['rune_enemy_gender']:
self.rune_enemy_gender.append(gender)
self.rune_skill_grant = []
for grant_data in data['rune_skill_grant']:
grant = SkillGrant()
grant.load_json(grant_data)
self.rune_skill_grant.append(grant)
self.rune_skill_adj = []
for adjust_data in data['rune_skill_adj']:
adjust = SkillAdjust()
adjust.load_json(adjust_data)
self.rune_skill_adj.append(adjust)
self.rune_attr_adj = []
for attr_data in data['rune_attr_adj']:
attr = AttributeValue()
attr.load_json(attr_data)
self.rune_attr_adj.append(attr)
self.rune_max_attr_adj = []
for attr_data in data['rune_max_attr_adj']:
attr = AttributeValue()
attr.load_json(attr_data)
self.rune_max_attr_adj.append(attr)
self.rune_naturalattacks = data['rune_naturalattacks']
self.rune_enchantment_type = []
for enchantment in data['rune_enchantment_type']:
self.rune_enchantment_type.append(enchantment)
self.rune_inventory_contents = []
for content_data in data['rune_inventory_contents']:
content = Inventory()
content.load_json(content_data)
self.rune_inventory_contents.append(content)
self.rune_renderable = data['rune_renderable']
if self.rune_renderable:
self.rune_scale_factor = data['rune_scale_factor']
self.rune_skeleton = data['rune_skeleton']
self.rune_slope_hugger = data['rune_slope_hugger']
self.rune_can_fly = data['rune_can_fly']
self.rune_death_effect = data['rune_death_effect']
self.rune_tombstone_id = data['rune_tombstone_id']
self.rune_body_parts = []
for part_data in data['rune_body_parts']:
part = BodyPart()
part.load_json(part_data)
self.rune_body_parts.append(part)
self.rune_hair = data['rune_hair']
self.rune_beard = data['rune_beard']
self.rune_natural_power_attack = data['rune_natural_power_attack']
self.rune_sparse_data = SparseData()
self.rune_sparse_data.load_json(data['rune_sparse_data'])
def save_json(self):
data = super().save_json()
data['rune_type'] = RUNE_TYPE_TO_STRING[self.rune_type]
data['rune_sub_type'] = hash_to_string(self.rune_sub_type)
data['rune_is_standard_character_creation'] = self.rune_is_standard_character_creation
data['rune_creation_cost'] = self.rune_creation_cost
data['rune_rank'] = self.rune_rank
data['rune_pracs_per_level'] = self.rune_pracs_per_level
data['rune_exp_req_to_level'] = self.rune_exp_req_to_level
data['rune_sex'] = RUNE_SEX_TO_STRING[self.rune_sex]
data['rune_class_icon'] = self.rune_class_icon
data['rune_health'] = self.rune_health
data['rune_mana'] = self.rune_mana
data['rune_stamina'] = self.rune_stamina
data['rune_min_damage'] = self.rune_min_damage
data['rune_max_damage'] = self.rune_max_damage
data['rune_attack'] = self.rune_attack
data['rune_defense'] = self.rune_defense
data['rune_level'] = self.rune_level
data['rune_speed'] = OrderedDict()
for i in range(7):
data['rune_speed'][SPEED_TYPE_TO_STRING[i]] = self.rune_speed[i]
data['rune_group'] = self.rune_group.save_json()
data['rune_dsc'] = self.rune_dsc
data['rune_fx_txt'] = self.rune_fx_txt
data['rune_group_tactics'] = self.rune_group_tactics
data['rune_group_role_set'] = self.rune_group_role_set
data['rune_enemy_monster_types'] = []
for monster in self.rune_enemy_monster_types:
data['rune_enemy_monster_types'].append(hash_to_string(monster))
data['rune_groupee_monster_types'] = []
for monster in self.rune_groupee_monster_types:
data['rune_groupee_monster_types'].append(hash_to_string(monster))
data['rune_helper_monster_types'] = []
for monster in self.rune_helper_monster_types:
data['rune_helper_monster_types'].append(hash_to_string(monster))
data['rune_not_enemy_monster_types'] = []
for monster in self.rune_not_enemy_monster_types:
data['rune_not_enemy_monster_types'].append(hash_to_string(monster))
data['rune_enemy_gender'] = []
for gender in self.rune_enemy_gender:
data['rune_enemy_gender'].append(gender)
data['rune_skill_grant'] = []
for grant in self.rune_skill_grant:
data['rune_skill_grant'].append(grant.save_json())
data['rune_skill_adj'] = []
for adjust in self.rune_skill_adj:
data['rune_skill_adj'].append(adjust.save_json())
data['rune_attr_adj'] = []
for attr in self.rune_attr_adj:
data['rune_attr_adj'].append(attr.save_json())
data['rune_max_attr_adj'] = []
for attr in self.rune_max_attr_adj:
data['rune_max_attr_adj'].append(attr.save_json())
data['rune_naturalattacks'] = self.rune_naturalattacks
data['rune_enchantment_type'] = []
for enchantment in self.rune_enchantment_type:
data['rune_enchantment_type'].append(enchantment)
data['rune_inventory_contents'] = []
for content in self.rune_inventory_contents:
data['rune_inventory_contents'].append(content.save_json())
data['rune_renderable'] = self.rune_renderable
if self.rune_renderable:
data['rune_scale_factor'] = self.rune_scale_factor
data['rune_skeleton'] = self.rune_skeleton
data['rune_slope_hugger'] = self.rune_slope_hugger
data['rune_can_fly'] = self.rune_can_fly
data['rune_death_effect'] = self.rune_death_effect
data['rune_tombstone_id'] = self.rune_tombstone_id
data['rune_body_parts'] = []
for part in self.rune_body_parts:
data['rune_body_parts'].append(part.save_json())
data['rune_hair'] = self.rune_hair
data['rune_beard'] = self.rune_beard
data['rune_natural_power_attack'] = self.rune_natural_power_attack
data['rune_sparse_data'] = self.rune_sparse_data.save_json()
return data
@@ -0,0 +1,101 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.util import ResStream
from .ArcCombatObj import ArcCombatObj
class Sound:
def load_binary(self, stream: ResStream):
self.sound_0 = stream.read_qword()
self.sound_1 = stream.read_qword()
self.sound_min_dist = stream.read_float()
self.sound_max_dist = stream.read_float()
self.sound_dist = stream.read_bool()
self.sound_loop = stream.read_bool()
self.sound_chance = stream.read_dword()
self.sound_interval = stream.read_float()
self.sound_reserved = stream.read_dword()
def save_binary(self, stream: ResStream):
stream.write_qword(self.sound_0)
stream.write_qword(self.sound_1)
stream.write_float(self.sound_min_dist)
stream.write_float(self.sound_max_dist)
stream.write_bool(self.sound_dist)
stream.write_bool(self.sound_loop)
stream.write_dword(self.sound_chance)
stream.write_float(self.sound_interval)
stream.write_dword(self.sound_reserved)
def load_json(self, data):
self.sound_0 = data['sound_0']
self.sound_1 = data['sound_1']
self.sound_min_dist = data['sound_min_dist']
self.sound_max_dist = data['sound_max_dist']
self.sound_dist = data['sound_dist']
self.sound_loop = data['sound_loop']
self.sound_chance = data['sound_chance']
self.sound_interval = data['sound_interval']
self.sound_reserved = data['sound_reserved']
def save_json(self):
data = OrderedDict()
data['sound_0'] = self.sound_0
data['sound_1'] = self.sound_1
data['sound_min_dist'] = self.sound_min_dist
data['sound_max_dist'] = self.sound_max_dist
data['sound_dist'] = self.sound_dist
data['sound_loop'] = self.sound_loop
data['sound_chance'] = self.sound_chance
data['sound_interval'] = self.sound_interval
data['sound_reserved'] = self.sound_reserved
return data
class ArcStaticObject(ArcCombatObj):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
self.static_platform_height = stream.read_float()
self.static_has_platform = stream.read_bool()
self.static_collision_detect = stream.read_bool()
self.static_has_sound = stream.read_bool()
if self.static_has_sound:
self.static_sound = Sound()
self.static_sound.load_binary(stream)
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.write_float(self.static_platform_height)
stream.write_bool(self.static_has_platform)
stream.write_bool(self.static_collision_detect)
stream.write_bool(self.static_has_sound)
if self.static_has_sound:
self.static_sound.save_binary(stream)
def load_json(self, data):
super().load_json(data)
self.static_platform_height = data['static_platform_height']
self.static_has_platform = data['static_has_platform']
self.static_collision_detect = data['static_collision_detect']
self.static_has_sound = data['static_has_sound']
if self.static_has_sound:
self.static_sound = Sound()
self.static_sound.load_json(data['static_sound'])
def save_json(self):
data = super().save_json()
data['static_platform_height'] = self.static_platform_height
data['static_has_platform'] = self.static_has_platform
data['static_collision_detect'] = self.static_collision_detect
data['static_has_sound'] = self.static_has_sound
if self.static_has_sound:
data['static_sound'] = self.static_sound.save_json()
return data
@@ -0,0 +1,330 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.arc_structure import *
from arcane.util import ResStream
from .ArcDoorObject import ArcDoorObject
from .ArcStaticObject import ArcStaticObject
class Region:
def load_binary(self, stream: ResStream):
num_points = stream.read_dword()
self.region_points = [
stream.read_tuple() for _ in range(num_points)
]
self.region_render_scale = stream.read_tuple()
self.region_content_behavior = stream.read_dword()
self.region_state = stream.read_dword()
self.region_render_flipped = stream.read_bool()
self.region_has_stairs = stream.read_bool()
if self.region_has_stairs:
self.region_stairs = [
stream.read_byte(),
stream.read_byte()
]
self.region_unknown2 = stream.read_byte()
self.region_unknown3 = stream.read_byte()
self.region_unknown4 = stream.read_tuple()
def save_binary(self, stream: ResStream):
stream.write_dword(len(self.region_points))
for point in self.region_points:
stream.write_tuple(point)
stream.write_tuple(self.region_render_scale)
stream.write_dword(self.region_content_behavior)
stream.write_dword(self.region_state)
stream.write_bool(self.region_render_flipped)
stream.write_bool(self.region_has_stairs)
if self.region_has_stairs:
stream.write_byte(self.region_stairs[0])
stream.write_byte(self.region_stairs[1])
stream.write_byte(self.region_unknown2)
stream.write_byte(self.region_unknown3)
stream.write_tuple(self.region_unknown4)
def load_json(self, data):
self.region_points = data['region_points']
self.region_render_scale = data['region_render_scale']
self.region_content_behavior = STRING_TO_REGION_CONTENTBEHAVIOR[
data['region_content_behavior']
]
self.region_state = STRING_TO_REGION_STATE[data['region_state']]
self.region_render_flipped = data['region_render_flipped']
self.region_has_stairs = data['region_has_stairs']
if self.region_has_stairs:
self.region_stairs = data['region_stairs']
self.region_unknown2 = data['region_unknown2']
self.region_unknown3 = data['region_unknown3']
self.region_unknown4 = data['region_unknown4']
def save_json(self):
data = OrderedDict()
data['region_points'] = self.region_points
data['region_render_scale'] = self.region_render_scale
data['region_content_behavior'] = REGION_CONTENTBEHAVIOR_TO_STRING[
self.region_content_behavior
]
data['region_state'] = REGION_STATE_TO_STRING[self.region_state]
data['region_render_flipped'] = self.region_render_flipped
data['region_has_stairs'] = self.region_has_stairs
if self.region_has_stairs:
data['region_stairs'] = self.region_stairs
data['region_unknown2'] = self.region_unknown2
data['region_unknown3'] = self.region_unknown3
data['region_unknown4'] = self.region_unknown4
return data
class Room:
def load_binary(self, stream: ResStream):
num_regions = stream.read_dword()
self.room_regions = [Region() for _ in range(num_regions)]
for region in self.room_regions:
region.load_binary(stream)
def save_binary(self, stream: ResStream):
stream.write_dword(len(self.room_regions))
for region in self.room_regions:
region.save_binary(stream)
def load_json(self, data):
self.room_regions = []
for region_data in data:
region = Region()
region.load_json(region_data)
self.room_regions.append(region)
def save_json(self):
data = []
for region in self.room_regions:
data.append(region.save_json())
return data
class Floor:
def load_binary(self, stream: ResStream):
self.floor_level_number = stream.read_dword()
num_exits = stream.read_dword()
self.floor_exits = [Region() for _ in range(num_exits)]
for exit in self.floor_exits:
exit.load_binary(stream)
num_regions = stream.read_dword()
self.floor_rooms = [Room() for _ in range(num_regions)]
for room in self.floor_rooms:
room.load_binary(stream)
def save_binary(self, stream: ResStream):
stream.write_dword(self.floor_level_number)
stream.write_dword(len(self.floor_exits))
for exit in self.floor_exits:
exit.save_binary(stream)
stream.write_dword(len(self.floor_rooms))
for room in self.floor_rooms:
room.save_binary(stream)
def load_json(self, data):
self.floor_level_number = data['floor_level_number']
self.floor_exits = []
for exit_data in data['floor_exits']:
exit = Region()
exit.load_json(exit_data)
self.floor_exits.append(exit)
self.floor_rooms = []
for room_data in data['floor_rooms']:
room = Room()
room.load_json(room_data)
self.floor_rooms.append(room)
def save_json(self):
data = OrderedDict()
data['floor_level_number'] = self.floor_level_number
data['floor_exits'] = []
for exit in self.floor_exits:
data['floor_exits'].append(exit.save_json())
data['floor_rooms'] = []
for room in self.floor_rooms:
data['floor_rooms'].append(room.save_json())
return data
class Hole:
def load_binary(self, stream: ResStream):
num_edges = stream.read_dword()
self.hole_edges = [
[
stream.read_tuple(),
stream.read_tuple()
] for _ in range(num_edges)
]
def save_binary(self, stream: ResStream):
stream.write_dword(len(self.hole_edges))
for edge in self.hole_edges:
stream.write_tuple(edge[0])
stream.write_tuple(edge[1])
def load_json(self, data):
self.hole_edges = []
for edge in data:
self.hole_edges.append(edge)
def save_json(self):
data = []
for edge in self.hole_edges:
data.append(edge)
return data
class Level:
def load_binary(self, stream: ResStream):
self.level_number = stream.read_dword()
self.level_type = stream.read_bool()
self.level_value = stream.read_qword()
def save_binary(self, stream: ResStream):
stream.write_dword(self.level_number)
stream.write_bool(self.level_type)
stream.write_qword(self.level_value)
def load_json(self, data):
self.level_number = data['level_number']
self.level_type = STRING_TO_LEVEL_TYPE[data['level_type']]
self.level_value = data['level_value']
def save_json(self):
data = OrderedDict()
data['level_number'] = self.level_number
data['level_type'] = LEVEL_TYPE_TO_STRING[self.level_type]
data['level_value'] = self.level_value
return data
class RegionTrigger:
def load_binary(self, stream: ResStream):
self.trigger_class_name = stream.read_string()
self.trigger_parameters = stream.read_string()
self.trigger_level_number = stream.read_dword()
self.trigger_room_number = stream.read_dword()
self.trigger_region_number = stream.read_dword()
def save_binary(self, stream: ResStream):
stream.write_string(self.trigger_class_name)
stream.write_string(self.trigger_parameters)
stream.write_dword(self.trigger_level_number)
stream.write_dword(self.trigger_room_number)
stream.write_dword(self.trigger_region_number)
def load_json(self, data):
self.trigger_class_name = data['trigger_class_name']
self.trigger_parameters = data['trigger_parameters']
self.trigger_level_number = data['trigger_level_number']
self.trigger_room_number = data['trigger_room_number']
self.trigger_region_number = data['trigger_region_number']
def save_json(self):
data = OrderedDict()
data['trigger_class_name'] = self.trigger_class_name
data['trigger_parameters'] = self.trigger_parameters
data['trigger_level_number'] = self.trigger_level_number
data['trigger_room_number'] = self.trigger_room_number
data['trigger_region_number'] = self.trigger_region_number
return data
class ArcStructureObject(ArcStaticObject):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
length = stream.read_dword()
self.structure_floors = [Floor() for _ in range(length)]
for floor in self.structure_floors:
floor.load_binary(stream)
num_holes = stream.read_dword()
self.structure_holes = [Hole() for _ in range(num_holes)]
for hole in self.structure_holes:
hole.load_binary(stream)
num_levels = stream.read_dword()
self.structure_levels = [Level() for _ in range(num_levels)]
for level in self.structure_levels:
level.load_binary(stream)
num_doors = stream.read_dword()
self.structure_doors = [ArcDoorObject() for _ in range(num_doors)]
for door in self.structure_doors:
door.load_binary(stream)
num_region_triggers = stream.read_dword()
self.structure_region_triggers = [RegionTrigger() for _ in range(num_region_triggers)]
for trigger in self.structure_region_triggers:
trigger.load_binary(stream)
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.write_dword(len(self.structure_floors))
for floor in self.structure_floors:
floor.save_binary(stream)
stream.write_dword(len(self.structure_holes))
for hole in self.structure_holes:
hole.save_binary(stream)
stream.write_dword(len(self.structure_levels))
for level in self.structure_levels:
level.save_binary(stream)
stream.write_dword(len(self.structure_doors))
for door in self.structure_doors:
door.save_binary(stream)
stream.write_dword(len(self.structure_region_triggers))
for trigger in self.structure_region_triggers:
trigger.save_binary(stream)
def load_json(self, data):
super().load_json(data)
self.structure_floors = []
for floor_data in data['structure_floors']:
floor = Floor()
floor.load_json(floor_data)
self.structure_floors.append(floor)
self.structure_holes = []
for hole_data in data['structure_holes']:
hole = Hole()
hole.load_json(hole_data)
self.structure_holes.append(hole)
self.structure_levels = []
for level_data in data['structure_levels']:
level = Level()
level.load_json(level_data)
self.structure_levels.append(level)
self.structure_doors = []
for door_data in data['structure_doors']:
door = ArcDoorObject()
door.load_json(door_data)
self.structure_doors.append(door)
self.structure_region_triggers = []
for trigger_data in data['structure_region_triggers']:
trigger = RegionTrigger()
trigger.load_json(trigger_data)
self.structure_region_triggers.append(trigger)
return data
def save_json(self):
data = super().save_json()
data['structure_floors'] = []
for floor in self.structure_floors:
data['structure_floors'].append(floor.save_json())
data['structure_holes'] = []
for hole in self.structure_holes:
data['structure_holes'].append(hole.save_json())
data['structure_levels'] = []
for level in self.structure_levels:
data['structure_levels'].append(level.save_json())
data['structure_doors'] = []
for door in self.structure_doors:
data['structure_doors'].append(door.save_json())
data['structure_region_triggers'] = []
for trigger in self.structure_region_triggers:
data['structure_region_triggers'].append(trigger.save_json())
return data
+21
View File
@@ -0,0 +1,21 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from .ArcAssetStructureObject import ArcAssetStructureObject
from .ArcCityAssetTemplate import ArcCityAssetTemplate
from .ArcCombatObj import ArcCombatObj, ArcCharacter
from .ArcContainerObject import ArcContainerObject
from .ArcDeed import ArcDeed
from .ArcDoorObject import ArcDoorObject
from .ArcDungeonUnitObject import ArcDungeonUnitObject, ArcDungeonExitObject, ArcDungeonStairObject
from .ArcItem import ArcItem
from .ArcKey import ArcKey
from .ArcObj import ArcObj
from .ArcRune import ArcRune
from .ArcStaticObject import ArcStaticObject
from .ArcStructureObject import ArcStructureObject
@@ -0,0 +1,260 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.hashes import hash_to_string, string_to_hash
from arcane.util import ResStream
class AttributeValue:
def load_binary(self, stream: ResStream):
self.attr_type = stream.read_dword()
self.attr_value = stream.read_dword()
def save_binary(self, stream: ResStream):
stream.write_dword(self.attr_type)
stream.write_dword(self.attr_value)
def load_json(self, data):
self.attr_type = string_to_hash(data['attr_type'])
self.attr_value = data['attr_value']
def save_json(self):
data = OrderedDict()
data['attr_type'] = hash_to_string(self.attr_type)
data['attr_value'] = self.attr_value
return data
class PowerArgument:
def load_binary(self, stream: ResStream):
self.power_arguments = [
stream.read_dword(),
stream.read_dword(),
]
def save_binary(self, stream: ResStream):
stream.write_dword(self.power_arguments[0])
stream.write_dword(self.power_arguments[1])
def load_json(self, data):
self.power_arguments = data['power_arguments']
def save_json(self):
data = OrderedDict()
data['power_arguments'] = self.power_arguments
return data
class SkillLevel:
def load_binary(self, stream: ResStream):
self.skill_type = stream.read_dword()
self.skill_level = stream.read_dword()
def save_binary(self, stream: ResStream):
stream.write_dword(self.skill_type)
stream.write_dword(self.skill_level)
def load_json(self, data):
self.skill_type = string_to_hash(data['skill_type'])
self.skill_level = data['skill_level']
def save_json(self):
data = OrderedDict()
data['skill_type'] = hash_to_string(self.skill_type)
data['skill_level'] = self.skill_level
return data
class ResourceInfo:
def load_binary(self, stream: ResStream):
self.resource_type = stream.read_dword()
self.resource_value = stream.read_dword()
def save_binary(self, stream: ResStream):
stream.write_dword(self.resource_type)
stream.write_dword(self.resource_value)
def load_json(self, data):
self.resource_type = string_to_hash(data['resource_type'])
self.resource_value = data['resource_value']
def save_json(self):
data = OrderedDict()
data['resource_type'] = hash_to_string(self.resource_type)
data['resource_value'] = self.resource_value
return data
class PowerAction:
def load_binary(self, stream: ResStream):
self.power_type = stream.read_dword()
num_grants = stream.read_dword()
self.power_actions = [PowerArgument() for _ in range(num_grants)]
for power in self.power_actions:
power.load_binary(stream)
def save_binary(self, stream: ResStream):
stream.write_dword(self.power_type)
stream.write_dword(len(self.power_actions))
for power in self.power_actions:
power.save_binary(stream)
def load_json(self, data):
self.power_type = string_to_hash(data['power_type'])
self.power_actions = []
for power_data in data['power_actions']:
power = PowerArgument()
power.load_json(power_data)
self.power_actions.append(power)
def save_json(self):
data = OrderedDict()
data['power_type'] = hash_to_string(self.power_type)
data['power_actions'] = []
for power in self.power_actions:
data['power_actions'].append(power.save_json())
return data
class PowerGrant:
def load_binary(self, stream: ResStream):
self.power_type = stream.read_dword()
self.power_value = stream.read_dword()
num_attrs = stream.read_dword()
self.power_granted_attrs = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_attrs)
]
num_skills = stream.read_dword()
self.power_granted_skills = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_skills)
]
num_powers = stream.read_dword()
self.power_granted_powers = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_powers)
]
num_monster_types = stream.read_dword()
self.power_monster_types = [
stream.read_dword() for _ in range(num_monster_types)
]
def save_binary(self, stream: ResStream):
stream.write_dword(self.power_type)
stream.write_dword(self.power_value)
stream.write_dword(len(self.power_granted_attrs))
for attr in self.power_granted_attrs:
stream.write_dword(attr[0])
stream.write_dword(attr[1])
stream.write_dword(len(self.power_granted_skills))
for skill in self.power_granted_skills:
stream.write_dword(skill[0])
stream.write_dword(skill[1])
stream.write_dword(len(self.power_granted_powers))
for power in self.power_granted_powers:
stream.write_dword(power[0])
stream.write_dword(power[1])
stream.write_dword(len(self.power_monster_types))
for value in self.power_monster_types:
stream.write_dword(value)
def load_json(self, data):
self.power_type = string_to_hash(data['power_type'])
self.power_value = data['power_value']
self.power_granted_attrs = data['power_granted_attrs']
self.power_granted_skills = data['power_granted_skills']
self.power_granted_powers = data['power_granted_powers']
self.power_monster_types = data['power_monster_types']
def save_json(self):
data = OrderedDict()
data['power_type'] = hash_to_string(self.power_type)
data['power_value'] = self.power_value
data['power_granted_attrs'] = self.power_granted_attrs
data['power_granted_skills'] = self.power_granted_skills
data['power_granted_powers'] = self.power_granted_powers
data['power_monster_types'] = self.power_monster_types
return data
class SkillGrant:
def load_binary(self, stream: ResStream):
self.skill_type = stream.read_dword()
self.skill_value = stream.read_dword()
num_attrs = stream.read_dword()
self.skill_granted_attrs = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_attrs)
]
num_skills = stream.read_dword()
self.skill_granted_skills = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_skills)
]
num_powers = stream.read_dword()
self.skill_granted_powers = [
[
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_powers)
]
num_monster_types = stream.read_dword()
self.skill_monster_types = [
stream.read_dword() for _ in range(num_monster_types)
]
def save_binary(self, stream: ResStream):
stream.write_dword(self.skill_type)
stream.write_dword(self.skill_value)
stream.write_dword(len(self.skill_granted_attrs))
for attr in self.skill_granted_attrs:
stream.write_dword(attr[0])
stream.write_dword(attr[1])
stream.write_dword(len(self.skill_granted_skills))
for skill in self.skill_granted_skills:
stream.write_dword(skill[0])
stream.write_dword(skill[1])
stream.write_dword(len(self.skill_granted_powers))
for power in self.skill_granted_powers:
stream.write_dword(power[0])
stream.write_dword(power[1])
stream.write_dword(len(self.skill_monster_types))
for value in self.skill_monster_types:
stream.write_dword(value)
def load_json(self, data):
self.skill_type = string_to_hash(data['skill_type'])
self.skill_value = data['skill_value']
self.skill_granted_attrs = data['skill_granted_attrs']
self.skill_granted_skills = data['skill_granted_skills']
self.skill_granted_powers = data['skill_granted_powers']
self.skill_monster_types = data['skill_monster_types']
def save_json(self):
data = OrderedDict()
data['skill_type'] = hash_to_string(self.skill_type)
data['skill_value'] = self.skill_value
data['skill_granted_attrs'] = self.skill_granted_attrs
data['skill_granted_skills'] = self.skill_granted_skills
data['skill_granted_powers'] = self.skill_granted_powers
data['skill_monster_types'] = self.skill_monster_types
return data
@@ -0,0 +1,42 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.hashes import hash_to_string, string_to_hash
from arcane.util import ResStream
class ClassRequired:
def load_binary(self, stream: ResStream):
classs = stream.read_dword()
self.class_restrict = stream.read_bool()
self.class_values = [
stream.read_dword() for _ in range(classs)
]
def save_binary(self, stream: ResStream):
stream.write_dword(len(self.class_values))
stream.write_bool(self.class_restrict)
for cls in self.class_values:
stream.write_dword(cls)
def load_json(self, data):
self.class_restrict = data['restrict']
self.class_values = []
for cls in data['classes']:
self.class_values.append(string_to_hash(cls))
return data
def save_json(self):
data = OrderedDict()
data['restrict'] = self.class_restrict
data['classes'] = []
for cls in self.class_values:
data['classes'].append(hash_to_string(cls))
return data
@@ -0,0 +1,41 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.hashes import hash_to_string, string_to_hash
from arcane.util import ResStream
class DiscRequired:
def load_binary(self, stream: ResStream):
discs = stream.read_dword()
self.disc_restrict = stream.read_bool()
self.disc_values = [
stream.read_dword() for _ in range(discs)
]
def save_binary(self, stream: ResStream):
stream.write_dword(len(self.disc_values))
stream.write_bool(self.disc_restrict)
for disc in self.disc_values:
stream.write_dword(disc)
def load_json(self, data):
self.disc_restrict = data['restrict']
self.disc_values = []
for disc in data['discs']:
self.disc_values.append(string_to_hash(disc))
def save_json(self):
data = OrderedDict()
data['restrict'] = self.disc_restrict
data['discs'] = []
for disc in self.disc_values:
data['discs'].append(hash_to_string(disc))
return data
@@ -0,0 +1,67 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.common.arc_inventory import *
from arcane.util import ResStream
class Inventory:
def load_binary(self, stream: ResStream):
self.inventory_type = stream.read_dword()
if self.inventory_type == INVENTORY_TYPE_GOLD:
self.inventory_gold = [
stream.read_float(),
stream.read_float(),
stream.read_float(),
]
elif self.inventory_type == INVENTORY_TYPE_ITEM:
self.inventory_items = [
stream.read_float(),
stream.read_qword(),
]
elif self.inventory_type == INVENTORY_TYPE_BOOTYTABLE:
self.inventory_table = [
stream.read_float(),
stream.read_dword(),
]
def save_binary(self, stream: ResStream):
stream.write_dword(self.inventory_type)
if self.inventory_type == INVENTORY_TYPE_GOLD:
stream.write_float(self.inventory_gold[0])
stream.write_float(self.inventory_gold[1])
stream.write_float(self.inventory_gold[2])
elif self.inventory_type == INVENTORY_TYPE_ITEM:
stream.write_float(self.inventory_items[0])
stream.write_qword(self.inventory_items[1])
elif self.inventory_type == INVENTORY_TYPE_BOOTYTABLE:
stream.write_float(self.inventory_table[0])
stream.write_dword(self.inventory_table[1])
def load_json(self, data):
self.inventory_type = STRING_TO_INVENTORY_TYPE[data['type']]
if self.inventory_type == INVENTORY_TYPE_GOLD:
self.inventory_gold = data['gold']
elif self.inventory_type == INVENTORY_TYPE_ITEM:
self.inventory_items = data['items']
elif self.inventory_type == INVENTORY_TYPE_BOOTYTABLE:
self.inventory_table = data['table']
def save_json(self):
data = OrderedDict()
data['type'] = INVENTORY_TYPE_TO_STRING[self.inventory_type]
if self.inventory_type == INVENTORY_TYPE_GOLD:
data['gold'] = self.inventory_gold
elif self.inventory_type == INVENTORY_TYPE_ITEM:
data['items'] = self.inventory_items
elif self.inventory_type == INVENTORY_TYPE_BOOTYTABLE:
data['table'] = self.inventory_table
return data
@@ -0,0 +1,41 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.hashes import hash_to_string, string_to_hash
from arcane.util import ResStream
class RaceRequired:
def load_binary(self, stream: ResStream):
races = stream.read_dword()
self.race_restrict = stream.read_bool()
self.race_values = [
stream.read_dword() for _ in range(races)
]
def save_binary(self, stream: ResStream):
stream.write_dword(len(self.race_values))
stream.write_bool(self.race_restrict)
for race in self.race_values:
stream.write_dword(race)
def load_json(self, data):
self.race_restrict = data['restrict']
self.race_values = []
for race in data['races']:
self.race_values.append(string_to_hash(race))
def save_json(self):
data = OrderedDict()
data['restrict'] = self.race_restrict
data['races'] = []
for race in self.race_values:
data['races'].append(hash_to_string(race))
return data
@@ -0,0 +1,108 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.arc_sparse import *
from arcane.util import ResStream
class SparseData:
def __init__(self) -> None:
self.sp_data = OrderedDict()
def load_binary(self, stream: ResStream):
sparse_tag = stream.read_dword()
while sparse_tag:
sparse_type = SPARSE_TAG_TO_SPARSE_TYPE[sparse_tag]
value = None
if sparse_type == SPARSE_VAL_LONG:
value = stream.read_dword()
elif sparse_type == SPARSE_VAL_FLOAT:
value = stream.read_float()
elif sparse_type == SPARSE_VAL_BOOL:
value = stream.read_bool()
elif sparse_type == SPARSE_UID:
value = stream.read_dword()
elif sparse_type == SPARSE_REF_VECTOR3:
value = stream.read_tuple()
elif sparse_type == SPARSE_REF_ARC_STRING:
value = stream.read_string()
elif sparse_type == SPARSE_REF_MERCHANT_DATA:
value = [
stream.read_qword(),
stream.read_qword(),
stream.read_dword(),
]
elif sparse_type == SPARSE_REF_ARC_CACHE_ID:
value = stream.read_qword()
elif sparse_type == SPARSE_PTR_ACTION_RESPONSE:
value = stream.read_dword()
elif sparse_type == SPARSE_ENUM_ITEM_TYPE:
value = stream.read_dword()
self.sp_data[sparse_tag] = value
sparse_tag = stream.read_dword()
def save_binary(self, stream: ResStream):
for tag, value in self.sp_data.items():
stream.write_dword(tag)
sparse_type = SPARSE_TAG_TO_SPARSE_TYPE[tag]
if sparse_type == SPARSE_VAL_LONG:
stream.write_dword(value)
elif sparse_type == SPARSE_VAL_FLOAT:
stream.write_float(value)
elif sparse_type == SPARSE_VAL_BOOL:
stream.write_bool(value)
elif sparse_type == SPARSE_UID:
stream.write_dword(value)
elif sparse_type == SPARSE_REF_VECTOR3:
stream.write_tuple(value)
elif sparse_type == SPARSE_REF_ARC_STRING:
stream.write_string(value)
elif sparse_type == SPARSE_REF_MERCHANT_DATA:
stream.write_qword(value[0])
stream.write_qword(value[1])
stream.write_qword(value[2])
elif sparse_type == SPARSE_REF_ARC_CACHE_ID:
stream.write_qword(value)
elif sparse_type == SPARSE_PTR_ACTION_RESPONSE:
stream.write_dword(value)
elif sparse_type == SPARSE_ENUM_ITEM_TYPE:
stream.write_dword(value)
stream.write_dword(0)
def load_json(self, data):
for key, value in data.items():
self.sp_data[STRING_TO_SPARSE_TAG[key]] = value
def save_json(self):
data = OrderedDict()
for tag, value in self.sp_data.items():
data[SPARSE_TAG_TO_STRING[tag]] = value
return data
@@ -0,0 +1,7 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com