# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ # ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ # ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ # ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ # ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ # 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