You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
340 lines
18 KiB
340 lines
18 KiB
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
|
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
|
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
|
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
|
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
|
# 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.objects.ArcRune import Group |
|
from arcane.objects.common.Inventory import Inventory |
|
from arcane.util import ResStream |
|
from .ArcBasicZoneObjectInfo import ArcBasicZoneObjectInfo |
|
|
|
|
|
class Unknown: |
|
def load_binary(self, stream: ResStream): |
|
self.unknown_u = stream.read_dword() |
|
self.unknown_u = stream.read_dword() |
|
self.unknown_u = stream.read_dword() |
|
self.unknown_check = stream.read_bool() |
|
if self.unknown_check: |
|
self.unknown_u = stream.read_qword() |
|
else: |
|
self.unknown_u = stream.read_dword() |
|
self.unknown_u = stream.read_string() |
|
self.unknown_u = stream.read_float() |
|
|
|
|
|
class InventoryContents: |
|
def load_binary(self, stream: ResStream): |
|
self.mobile_inventory_u = stream.read_qword() |
|
self.mobile_inventory_u = stream.read_qword() |
|
self.mobile_inventory_u = stream.read_tuple() |
|
self.mobile_inventory_u = stream.read_tuple() |
|
self.mobile_inventory_u = [stream.read_float() for _ in range(4)] |
|
self.mobile_inventory_u = stream.read_qword() |
|
self.mobile_inventory_u = stream.read_dword() |
|
self.mobile_inventory_u = stream.read_dword() |
|
self.mobile_inventory_u = stream.read_dword() |
|
self.mobile_inventory_u = stream.read_bool() |
|
self.mobile_inventory_u = stream.read_string() |
|
self.mobile_inventory_check = stream.read_bool() |
|
if self.mobile_inventory_check: |
|
self.mobile_inventory_u = stream.read_float() |
|
self.mobile_inventory_u = stream.read_float() |
|
self.mobile_inventory_check = stream.read_bool() |
|
if self.mobile_inventory_check: |
|
self.mobile_inventory_u = stream.read_qword() |
|
self.mobile_inventory_u = stream.read_dword() |
|
self.mobile_inventory_u = stream.read_dword() |
|
self.mobile_inventory_u = stream.read_float() |
|
self.mobile_inventory_u = stream.read_dword() |
|
self.mobile_inventory_u = stream.read_dword() |
|
num = stream.read_dword() |
|
self.mobile_inventory_u = [Unknown() for _ in range(num)] |
|
self.mobile_inventory_u = stream.read_dword() |
|
self.mobile_inventory_check = stream.read_bool() |
|
if self.mobile_inventory_check: |
|
self.mobile_inventory_u = stream.read_qword() |
|
self.mobile_inventory_u = stream.read_qword() |
|
self.mobile_inventory_u = stream.read_qword() |
|
self.mobile_inventory_u = stream.read_dword() |
|
self.mobile_inventory_check = stream.read_bool() |
|
if self.mobile_inventory_check: |
|
self.mobile_inventory_u = stream.read_qword() |
|
self.mobile_inventory_u = stream.read_dword() |
|
self.mobile_inventory_check = stream.read_bool() |
|
if self.mobile_inventory_check: |
|
self.mobile_inventory_u = stream.read_bool() |
|
self.mobile_inventory_u = stream.read_float() |
|
self.mobile_inventory_u = stream.read_dword() |
|
self.mobile_inventory_u = stream.read_dword() |
|
self.mobile_inventory_check = stream.read_bool() |
|
if self.mobile_inventory_check: |
|
self.mobile_inventory_u = [stream.read_dword() for _ in range(5)] |
|
self.mobile_inventory_check = stream.read_bool() |
|
if self.mobile_inventory_check: |
|
self.mobile_inventory_u = [stream.read_dword() for _ in range(5)] |
|
self.mobile_inventory_u = stream.read_bool() |
|
|
|
|
|
class MobileInfo: |
|
|
|
def load_binary(self, stream: ResStream): |
|
self.mobile_base_zone = ArcBasicZoneObjectInfo() |
|
self.mobile_base_zone.load_binary(stream) |
|
self.mobile_number_in_group = stream.read_dword() |
|
self.mobile_change_to_find = stream.read_float() |
|
self.mobile_level = stream.read_dword() |
|
self.mobile_behavior_file = stream.read_string() |
|
self.mobile_dialog_override = stream.read_dword() |
|
self.mobile_base_exp_reward = stream.read_dword() |
|
self.mobile_tenacity = stream.read_float() |
|
self.mobile_courage = stream.read_float() |
|
self.mobile_has_group_tactics = stream.read_bool() |
|
if self.mobile_has_group_tactics: |
|
self.mobile_group_tactics = stream.read_dword() |
|
self.mobile_has_role_set = stream.read_bool() |
|
if self.mobile_has_role_set: |
|
self.mobile_role_set = stream.read_dword() |
|
self.mobile_has_home_goal = stream.read_bool() |
|
if self.mobile_has_home_goal: |
|
self.mobile_home_goal = stream.read_dword() |
|
self.mobile_spawn_home_goal = stream.read_bool() |
|
self.mobile_has_target_goal = stream.read_bool() |
|
if self.mobile_has_target_goal: |
|
self.mobile_target_goal = stream.read_dword() |
|
self.mobile_spawn_target_goal = stream.read_bool() |
|
num_rune_stone_ids = stream.read_dword() |
|
self.mobile_rune_stone_ids = [stream.read_qword() for _ in range(num_rune_stone_ids)] |
|
self.mobile_has_content = stream.read_bool() |
|
if self.mobile_has_content: |
|
num_contents = stream.read_dword() |
|
self.mobile_inventory_contents = [InventoryContents() for _ in range(num_contents)] |
|
for content in self.mobile_inventory_contents: |
|
content.load_binary(stream) |
|
num_equipments = stream.read_dword() |
|
self.mobile_equipment = [[ |
|
stream.read_qword(), |
|
stream.read_float(), |
|
] for _ in range(num_equipments)] |
|
num_lores = stream.read_dword() |
|
self.mobile_lores = [stream.read_dword() for _ in range(num_lores)] |
|
self.mobile_use_prefered_hp = stream.read_bool() |
|
num_spawn_hps = stream.read_dword() |
|
self.mobile_spawn_hps = [stream.read_dword() for _ in range(num_spawn_hps)] |
|
num = stream.read_dword() |
|
self.mobile_booties = [Inventory() for _ in range(num)] |
|
for booty in self.mobile_booties: |
|
booty.load_binary(stream) |
|
self.mobile_root_fs_mid = stream.read_string() |
|
self.mobile_group = Group() |
|
self.mobile_group.load_binary(stream) |
|
num_enemy_monster_types = stream.read_dword() |
|
self.mobile_enemy_monster_types = [stream.read_dword() for _ in range(num_enemy_monster_types)] |
|
num_not_enemy_monster_types = stream.read_dword() |
|
self.mobile_not_enemy_monster_types = [stream.read_dword() for _ in range(num_not_enemy_monster_types)] |
|
num_groupee_monster_types = stream.read_dword() |
|
self.mobile_groupee_monster_types = [stream.read_dword() for _ in range(num_groupee_monster_types)] |
|
num_helper_monster_types = stream.read_dword() |
|
self.mobile_helper_monster_types = [stream.read_dword() for _ in range(num_helper_monster_types)] |
|
num_enemy_genders = stream.read_dword() |
|
self.mobile_enemy_genders = [stream.read_dword() for _ in range(num_enemy_genders)] |
|
num_friendly_charters = stream.read_dword() |
|
self.mobile_friendly_charters = [stream.read_dword() for _ in range(num_friendly_charters)] |
|
self.mobile_parley_name = stream.read_string() |
|
|
|
def save_binary(self, stream: ResStream): |
|
self.mobile_base_zone.save_binary(stream) |
|
stream.write_dword(self.mobile_number_in_group) |
|
stream.write_float(self.mobile_change_to_find) |
|
stream.write_dword(self.mobile_level) |
|
stream.write_string(self.mobile_behavior_file) |
|
stream.write_dword(self.mobile_dialog_override) |
|
stream.write_dword(self.mobile_base_exp_reward) |
|
stream.write_float(self.mobile_tenacity) |
|
stream.write_float(self.mobile_courage) |
|
stream.write_bool(self.mobile_has_group_tactics) |
|
if self.mobile_has_group_tactics: |
|
stream.write_dword(self.mobile_group_tactics) |
|
stream.write_bool(self.mobile_has_role_set) |
|
if self.mobile_has_role_set: |
|
stream.write_dword(self.mobile_role_set) |
|
stream.write_bool(self.mobile_has_home_goal) |
|
if self.mobile_has_home_goal: |
|
stream.write_dword(self.mobile_home_goal) |
|
stream.write_bool(self.mobile_spawn_home_goal) |
|
stream.write_bool(self.mobile_has_target_goal) |
|
if self.mobile_has_target_goal: |
|
stream.write_dword(self.mobile_target_goal) |
|
stream.write_bool(self.mobile_spawn_target_goal) |
|
stream.write_dword(len(self.mobile_rune_stone_ids)) |
|
for rune_stone_id in self.mobile_rune_stone_ids: |
|
stream.write_qword(rune_stone_id) |
|
stream.write_bool(self.mobile_has_content) |
|
if self.mobile_has_content: |
|
stream.write_dword(len(self.mobile_inventory_contents)) |
|
for content in self.mobile_inventory_contents: |
|
content.save_binary(stream) |
|
stream.write_dword(len(self.mobile_equipment)) |
|
for equipment in self.mobile_equipment: |
|
stream.write_qword(equipment[0]) |
|
stream.write_float(equipment[1]) |
|
stream.write_dword(len(self.mobile_lores)) |
|
for lore in self.mobile_lores: |
|
stream.write_dword(lore) |
|
stream.write_bool(self.mobile_use_prefered_hp) |
|
stream.write_dword(len(self.mobile_spawn_hps)) |
|
for spawn_hp in self.mobile_spawn_hps: |
|
stream.write_dword(spawn_hp) |
|
stream.write_dword(len(self.mobile_booties)) |
|
for booty in self.mobile_booties: |
|
booty.save_binary(stream) |
|
stream.write_string(self.mobile_root_fs_mid) |
|
self.mobile_group.save_binary(stream) |
|
stream.write_dword(len(self.mobile_enemy_monster_types)) |
|
for enemy_monster_type in self.mobile_enemy_monster_types: |
|
stream.write_dword(enemy_monster_type) |
|
stream.write_dword(len(self.mobile_not_enemy_monster_types)) |
|
for not_enemy_monster_type in self.mobile_not_enemy_monster_types: |
|
stream.write_dword(not_enemy_monster_type) |
|
stream.write_dword(len(self.mobile_groupee_monster_types)) |
|
for groupee_monster_type in self.mobile_groupee_monster_types: |
|
stream.write_dword(groupee_monster_type) |
|
stream.write_dword(len(self.mobile_helper_monster_types)) |
|
for helper_monster_type in self.mobile_helper_monster_types: |
|
stream.write_dword(helper_monster_type) |
|
stream.write_dword(len(self.mobile_enemy_genders)) |
|
for enemy_gender in self.mobile_enemy_genders: |
|
stream.write_dword(enemy_gender) |
|
stream.write_dword(len(self.mobile_friendly_charters)) |
|
for friendly_charter in self.mobile_friendly_charters: |
|
stream.write_dword(friendly_charter) |
|
stream.write_string(self.mobile_parley_name) |
|
|
|
def save_json(self): |
|
data = OrderedDict() |
|
data['mobile_base_zone'] = self.mobile_base_zone.save_json() |
|
data['mobile_number_in_group'] = self.mobile_number_in_group |
|
data['mobile_change_to_find'] = self.mobile_change_to_find |
|
data['mobile_level'] = self.mobile_level |
|
data['mobile_behavior_file'] = self.mobile_behavior_file |
|
data['mobile_dialog_override'] = self.mobile_dialog_override |
|
data['mobile_base_exp_reward'] = self.mobile_base_exp_reward |
|
data['mobile_tenacity'] = self.mobile_tenacity |
|
data['mobile_courage'] = self.mobile_courage |
|
data['mobile_has_group_tactics'] = self.mobile_has_group_tactics |
|
if self.mobile_has_group_tactics: |
|
data['mobile_group_tactics'] = self.mobile_group_tactics |
|
data['mobile_has_role_set'] = self.mobile_has_role_set |
|
if self.mobile_has_role_set: |
|
data['mobile_role_set'] = self.mobile_role_set |
|
data['mobile_has_home_goal'] = self.mobile_has_home_goal |
|
if self.mobile_has_home_goal: |
|
data['mobile_home_goal'] = self.mobile_home_goal |
|
data['mobile_spawn_home_goal'] = self.mobile_spawn_home_goal |
|
data['mobile_has_target_goal'] = self.mobile_has_target_goal |
|
if self.mobile_has_target_goal: |
|
data['mobile_target_goal'] = self.mobile_target_goal |
|
data['mobile_spawn_target_goal'] = self.mobile_spawn_target_goal |
|
data['mobile_rune_stone_ids'] = self.mobile_rune_stone_ids |
|
data['mobile_has_content'] = self.mobile_has_content |
|
if self.mobile_has_content: |
|
data['mobile_inventory_contents'] = [] |
|
for content in self.mobile_inventory_contents: |
|
data['mobile_inventory_contents'].append(content.save_json()) |
|
data['mobile_equipment'] = self.mobile_equipment |
|
data['mobile_lores'] = self.mobile_lores |
|
data['mobile_use_prefered_hp'] = self.mobile_use_prefered_hp |
|
data['mobile_spawn_hps'] = self.mobile_spawn_hps |
|
data['mobile_booties'] = [] |
|
for booty in self.mobile_booties: |
|
data['mobile_booties'].append(booty.save_json()) |
|
data['mobile_root_fs_mid'] = self.mobile_root_fs_mid |
|
data['mobile_group'] = self.mobile_group.save_json() |
|
data['mobile_enemy_monster_types'] = [] |
|
for enemy_monster_type in self.mobile_enemy_monster_types: |
|
data['mobile_enemy_monster_types'].append(hash_to_string(enemy_monster_type)) |
|
data['mobile_not_enemy_monster_types'] = [] |
|
for not_enemy_monster_type in self.mobile_not_enemy_monster_types: |
|
data['mobile_not_enemy_monster_types'].append(hash_to_string(not_enemy_monster_type)) |
|
data['mobile_groupee_monster_types'] = [] |
|
for groupee_monster_type in self.mobile_groupee_monster_types: |
|
data['mobile_groupee_monster_types'].append(hash_to_string(groupee_monster_type)) |
|
data['mobile_helper_monster_types'] = [] |
|
for helper_monster_type in self.mobile_helper_monster_types: |
|
data['mobile_helper_monster_types'].append(hash_to_string(helper_monster_type)) |
|
data['mobile_enemy_genders'] = [] |
|
for enemy_gender in self.mobile_enemy_genders: |
|
data['mobile_enemy_genders'].append(RUNE_SEX_TO_STRING[enemy_gender]) |
|
data['mobile_friendly_charters'] = self.mobile_friendly_charters |
|
data['mobile_parley_name'] = self.mobile_parley_name |
|
return data |
|
|
|
def load_json(self, data): |
|
self.mobile_base_zone = ArcBasicZoneObjectInfo() |
|
self.mobile_base_zone.load_json(data['mobile_base_zone']) |
|
self.mobile_number_in_group = data['mobile_number_in_group'] |
|
self.mobile_change_to_find = data['mobile_change_to_find'] |
|
self.mobile_level = data['mobile_level'] |
|
self.mobile_behavior_file = data['mobile_behavior_file'] |
|
self.mobile_dialog_override = data['mobile_dialog_override'] |
|
self.mobile_base_exp_reward = data['mobile_base_exp_reward'] |
|
self.mobile_tenacity = data['mobile_tenacity'] |
|
self.mobile_courage = data['mobile_courage'] |
|
self.mobile_has_group_tactics = data['mobile_has_group_tactics'] |
|
if self.mobile_has_group_tactics: |
|
self.mobile_group_tactics = data['mobile_group_tactics'] |
|
self.mobile_has_role_set = data['mobile_has_role_set'] |
|
if self.mobile_has_role_set: |
|
self.mobile_role_set = data['mobile_role_set'] |
|
self.mobile_has_home_goal = data['mobile_has_home_goal'] |
|
if self.mobile_has_home_goal: |
|
self.mobile_home_goal = data['mobile_home_goal'] |
|
self.mobile_spawn_home_goal = data['mobile_spawn_home_goal'] |
|
self.mobile_has_target_goal = data['mobile_has_target_goal'] |
|
if self.mobile_has_target_goal: |
|
self.mobile_target_goal = data['mobile_target_goal'] |
|
self.mobile_spawn_target_goal = data['mobile_spawn_target_goal'] |
|
self.mobile_rune_stone_ids = data['mobile_rune_stone_ids'] |
|
self.mobile_has_content = data['mobile_has_content'] |
|
if self.mobile_has_content: |
|
self.mobile_inventory_contents = [] |
|
for content_data in data['mobile_inventory_contents']: |
|
content = InventoryContents() |
|
content.load_json(content_data) |
|
self.mobile_inventory_contents.append(content) |
|
self.mobile_equipment = data['mobile_equipment'] |
|
self.mobile_lores = data['mobile_lores'] |
|
self.mobile_use_prefered_hp = data['mobile_use_prefered_hp'] |
|
self.mobile_spawn_hps = data['mobile_spawn_hps'] |
|
self.mobile_booties = [] |
|
for booty_data in data['mobile_booties']: |
|
booty = Inventory() |
|
booty.load_json(booty_data) |
|
self.mobile_booties.append(booty) |
|
self.mobile_root_fs_mid = data['mobile_root_fs_mid'] |
|
self.mobile_group = Group() |
|
self.mobile_group.load_json(data['mobile_group']) |
|
self.mobile_enemy_monster_types = [] |
|
for enemy_monster_type in data['mobile_enemy_monster_types']: |
|
self.mobile_enemy_monster_types.append(string_to_hash(enemy_monster_type)) |
|
self.mobile_not_enemy_monster_types = [] |
|
for not_enemy_monster_type in data['mobile_not_enemy_monster_types']: |
|
self.mobile_not_enemy_monster_types.append(string_to_hash(not_enemy_monster_type)) |
|
self.mobile_groupee_monster_types = [] |
|
for groupee_monster_type in data['mobile_groupee_monster_types']: |
|
self.mobile_groupee_monster_types.append(string_to_hash(groupee_monster_type)) |
|
self.mobile_helper_monster_types = [] |
|
for helper_monster_type in data['mobile_helper_monster_types']: |
|
self.mobile_helper_monster_types.append(string_to_hash(helper_monster_type)) |
|
self.mobile_enemy_genders = [] |
|
for enemy_gender in data['mobile_enemy_genders']: |
|
self.mobile_enemy_genders.append(STRING_TO_RUNE_SEX[enemy_gender]) |
|
self.mobile_friendly_charters = data['mobile_friendly_charters'] |
|
self.mobile_parley_name = data['mobile_parley_name']
|
|
|