mbEditorPro2.0 release
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from arcane.objects.common.SparseData import SparseData
|
||||
from arcane.util import ResStream
|
||||
|
||||
|
||||
class ArcBasicZoneObjectInfo:
|
||||
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.basic_zone_spawn_location = stream.read_tuple()
|
||||
self.basic_zone_name_override = stream.read_string()
|
||||
self.basic_zone_time_to_respawn = stream.read_float()
|
||||
self.basic_zone_spawn_radius = stream.read_float()
|
||||
self.basic_zone_y_rot = stream.read_float()
|
||||
self.basic_zone_template_id = stream.read_qword()
|
||||
self.basic_zone_unknown1 = stream.read_qword()
|
||||
self.basic_zone_level_number = stream.read_dword()
|
||||
self.basic_zone_room_number = stream.read_dword()
|
||||
self.basic_zone_unknown2 = stream.read_qword()
|
||||
self.basic_zone_dungeon_level = stream.read_dword()
|
||||
self.basic_zone_dungeon_row = stream.read_dword()
|
||||
self.basic_zone_dungeon_column = stream.read_dword()
|
||||
self.basic_zone_sparse_data = SparseData()
|
||||
self.basic_zone_sparse_data.load_binary(stream)
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
stream.write_tuple(self.basic_zone_spawn_location)
|
||||
stream.write_string(self.basic_zone_name_override)
|
||||
stream.write_float(self.basic_zone_time_to_respawn)
|
||||
stream.write_float(self.basic_zone_spawn_radius)
|
||||
stream.write_float(self.basic_zone_y_rot)
|
||||
stream.write_qword(self.basic_zone_template_id)
|
||||
stream.write_qword(self.basic_zone_unknown1)
|
||||
stream.write_dword(self.basic_zone_level_number)
|
||||
stream.write_dword(self.basic_zone_room_number)
|
||||
stream.write_qword(self.basic_zone_unknown2)
|
||||
stream.write_dword(self.basic_zone_dungeon_level)
|
||||
stream.write_dword(self.basic_zone_dungeon_row)
|
||||
stream.write_dword(self.basic_zone_dungeon_column)
|
||||
self.basic_zone_sparse_data.save_binary(stream)
|
||||
|
||||
def save_json(self):
|
||||
data = OrderedDict()
|
||||
data['basic_zone_spawn_location'] = self.basic_zone_spawn_location
|
||||
data['basic_zone_name_override'] = self.basic_zone_name_override
|
||||
data['basic_zone_time_to_respawn'] = self.basic_zone_time_to_respawn
|
||||
data['basic_zone_spawn_radius'] = self.basic_zone_spawn_radius
|
||||
data['basic_zone_y_rot'] = self.basic_zone_y_rot
|
||||
data['basic_zone_template_id'] = self.basic_zone_template_id
|
||||
data['basic_zone_unknown1'] = self.basic_zone_unknown1
|
||||
data['basic_zone_level_number'] = self.basic_zone_level_number
|
||||
data['basic_zone_room_number'] = self.basic_zone_room_number
|
||||
data['basic_zone_unknown2'] = self.basic_zone_unknown2
|
||||
data['basic_zone_dungeon_level'] = self.basic_zone_dungeon_level
|
||||
data['basic_zone_dungeon_row'] = self.basic_zone_dungeon_row
|
||||
data['basic_zone_dungeon_column'] = self.basic_zone_dungeon_column
|
||||
data['basic_zone_sparse_data'] = self.basic_zone_sparse_data.save_json()
|
||||
return data
|
||||
|
||||
def load_json(self, data):
|
||||
self.basic_zone_spawn_location = data['basic_zone_spawn_location']
|
||||
self.basic_zone_name_override = data['basic_zone_name_override']
|
||||
self.basic_zone_time_to_respawn = data['basic_zone_time_to_respawn']
|
||||
self.basic_zone_spawn_radius = data['basic_zone_spawn_radius']
|
||||
self.basic_zone_y_rot = data['basic_zone_y_rot']
|
||||
self.basic_zone_template_id = data['basic_zone_template_id']
|
||||
self.basic_zone_unknown1 = data['basic_zone_unknown1']
|
||||
self.basic_zone_level_number = data['basic_zone_level_number']
|
||||
self.basic_zone_room_number = data['basic_zone_room_number']
|
||||
self.basic_zone_unknown2 = data['basic_zone_unknown2']
|
||||
self.basic_zone_dungeon_level = data['basic_zone_dungeon_level']
|
||||
self.basic_zone_dungeon_row = data['basic_zone_dungeon_row']
|
||||
self.basic_zone_dungeon_column = data['basic_zone_dungeon_column']
|
||||
self.basic_zone_sparse_data = SparseData()
|
||||
self.basic_zone_sparse_data.load_json(data['basic_zone_sparse_data'])
|
||||
@@ -0,0 +1,129 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
|
||||
from arcane.util import ResStream
|
||||
from .MerchantInfo import MerchantInfo
|
||||
|
||||
|
||||
class Product:
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.product_cost = stream.read_dword()
|
||||
self.product_base_time = stream.read_dword()
|
||||
self.product_min_rank = stream.read_dword()
|
||||
self.product_is_complete = stream.read_bool()
|
||||
self.product_is_pending = stream.read_bool()
|
||||
self.product_order_num = stream.read_dword()
|
||||
self.product_time_mod = stream.read_dword()
|
||||
self.product_enchantment = stream.read_dword()
|
||||
self.product_action_prefix_id = stream.read_dword()
|
||||
self.product_action_suffix_id = stream.read_dword()
|
||||
self.product_u = stream.read_dword()
|
||||
self.product_u = stream.read_bool()
|
||||
self.product_id = stream.read_qword()
|
||||
self.product_pending_id = stream.read_qword()
|
||||
self.product_item_type_id = stream.read_qword()
|
||||
self.product_next_complete = [stream.read_dword() for _ in range(6)]
|
||||
|
||||
|
||||
class MinionElement:
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.minion_element_id = stream.read_qword()
|
||||
self.minion_element_type = stream.read_qword()
|
||||
self.minion_element_lookup = stream.read_qword()
|
||||
self.minion_element_base_time = stream.read_dword()
|
||||
self.minion_element_mod_time = stream.read_dword()
|
||||
self.minion_element_u = stream.read_dword()
|
||||
self.minion_element_is_complete = stream.read_bool()
|
||||
self.minion_element_next_complete = [stream.read_dword() for _ in range(6)]
|
||||
self.minion_element_name = stream.read_string()
|
||||
self.minion_element_u = stream.read_string()
|
||||
self.minion_element_rank = stream.read_dword()
|
||||
self.minion_element_category = stream.read_dword()
|
||||
self.minion_element_u = stream.read_string()
|
||||
self.minion_element_u = stream.read_string()
|
||||
|
||||
|
||||
class ServiceElement:
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.service_element_id = stream.read_qword()
|
||||
self.service_element_keyword = stream.read_dword()
|
||||
self.service_element_key_value = stream.read_dword()
|
||||
self.service_element_description = stream.read_string()
|
||||
self.service_element_unit_description = stream.read_string()
|
||||
self.service_element_cost = stream.read_dword()
|
||||
self.service_element_unit_value = stream.read_dword()
|
||||
self.service_element_min_rank = stream.read_dword()
|
||||
|
||||
|
||||
class HirelingMod:
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.hireling_mod_type = stream.read_dword()
|
||||
self.hireling_mod_rank = stream.read_dword()
|
||||
self.hireling_mod_quantity = stream.read_dword()
|
||||
self.hireling_mod_percent = stream.read_float()
|
||||
|
||||
|
||||
class JunkerBasics:
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.junker_auto_junk = stream.read_bool()
|
||||
self.junker_auto_junk_magic = stream.read_bool()
|
||||
self.junker_auto_junk_int = stream.read_dword()
|
||||
self.junker_auto_junk_magic_int = stream.read_dword()
|
||||
|
||||
|
||||
class HirelingInfo(MerchantInfo):
|
||||
def load_binary(self, stream: ResStream):
|
||||
super().load_binary(stream)
|
||||
self.hireling_all_items = stream.read_bool()
|
||||
self.hireling_rank = stream.read_dword()
|
||||
self.hireling_title = stream.read_string()
|
||||
self.hireling_salary = stream.read_dword()
|
||||
self.hireling_upgrade_cost = stream.read_dword()
|
||||
self.hireling_upgrade_time = stream.read_dword()
|
||||
self.hireling_can_upgrade = stream.read_bool()
|
||||
self.hireling_use_specified_location = stream.read_bool()
|
||||
self.hireling_category = stream.read_dword()
|
||||
num_npc_features = stream.read_dword()
|
||||
self.hireling_npc_features = [stream.read_dword() for _ in range(num_npc_features)]
|
||||
num_item_types = stream.read_dword()
|
||||
self.hireling_item_types = [stream.read_dword() for _ in range(num_item_types)]
|
||||
num_products = stream.read_dword()
|
||||
self.hireling_products = [Product() for _ in range(num_products)]
|
||||
num_stocks = stream.read_dword()
|
||||
self.hireling_stocks = [Product() for _ in range(num_stocks)]
|
||||
num_minions = stream.read_dword()
|
||||
self.hireling_minions = [MinionElement() for _ in range(num_minions)]
|
||||
num_servies = stream.read_dword()
|
||||
self.hireling_servies = [ServiceElement() for _ in range(num_servies)]
|
||||
num_orders = stream.read_dword()
|
||||
self.hireling_orders = [[
|
||||
stream.read_dword() for _ in range(4)
|
||||
] for _ in range(num_orders)]
|
||||
num_starting_formulas = stream.read_dword()
|
||||
self.hireling_starting_formulas = [stream.read_qword() for _ in range(num_starting_formulas)]
|
||||
num_valid_formula_types = stream.read_dword()
|
||||
self.hireling_valid_formula_types = [stream.read_dword() for _ in range(num_valid_formula_types)]
|
||||
num_valid_formula_categories = stream.read_dword()
|
||||
self.hireling_valid_formula_category = [stream.read_dword() for _ in range(num_valid_formula_categories)]
|
||||
num_enchantment_types = stream.read_dword()
|
||||
self.hireling_enchantment_types = [stream.read_dword() for _ in range(num_enchantment_types)]
|
||||
num_valid_weapons = stream.read_dword()
|
||||
self.hireling_valid_weapons = [stream.read_dword() for _ in range(num_valid_weapons)]
|
||||
num_valid_armors = stream.read_dword()
|
||||
self.hireling_valid_armors = [stream.read_dword() for _ in range(num_valid_armors)]
|
||||
num_valid_slaves = stream.read_dword()
|
||||
self.hireling_valid_slaves = [stream.read_dword() for _ in range(num_valid_slaves)]
|
||||
num_mods = stream.read_dword()
|
||||
self.hireling_mods = [HirelingMod() for _ in range(num_mods)]
|
||||
for mod in self.hireling_mods:
|
||||
mod.load_binary(stream)
|
||||
self.hireling_max_items_stocked = stream.read_dword()
|
||||
self.hireling_has_junker = stream.read_bool()
|
||||
if self.hireling_has_junker:
|
||||
self.hireling_junker = JunkerBasics()
|
||||
self.hireling_junker.load_binary(stream)
|
||||
@@ -0,0 +1,50 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
|
||||
from arcane.util import ResStream
|
||||
from .MobileInfo import MobileInfo
|
||||
|
||||
|
||||
class MerchantInfo(MobileInfo):
|
||||
def load_binary(self, stream: ResStream):
|
||||
super().load_binary(stream)
|
||||
self.merchant_trade_type = stream.read_dword()
|
||||
self.merchant_std_buy_margin = stream.read_float()
|
||||
self.merchant_std_sell_margin = stream.read_float()
|
||||
self.merchant_guild_buy_margin = stream.read_float()
|
||||
self.merchant_guild_sell_margin = stream.read_float()
|
||||
self.merchant_nation_buy_margin = stream.read_float()
|
||||
self.merchant_nation_sell_margin = stream.read_float()
|
||||
num_buy_list = stream.read_dword()
|
||||
self.merchant_buy_list = [[
|
||||
stream.read_qword(),
|
||||
stream.read_dword(),
|
||||
] for _ in range(num_buy_list)]
|
||||
num_sell_list = stream.read_dword()
|
||||
self.merchant_sell_list = [[
|
||||
stream.read_qword(),
|
||||
stream.read_dword(),
|
||||
] for _ in range(num_sell_list)]
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
super().save_binary(stream)
|
||||
stream.write_dword(self.merchant_trade_type)
|
||||
stream.write_float(self.merchant_std_buy_margin)
|
||||
stream.write_float(self.merchant_std_sell_margin)
|
||||
stream.write_float(self.merchant_guild_buy_margin)
|
||||
stream.write_float(self.merchant_guild_sell_margin)
|
||||
stream.write_float(self.merchant_nation_buy_margin)
|
||||
stream.write_float(self.merchant_nation_sell_margin)
|
||||
stream.write_dword(len(self.merchant_buy_list))
|
||||
for l in self.merchant_buy_list:
|
||||
stream.write_qword(l[0])
|
||||
stream.write_dword(l[1])
|
||||
stream.write_dword(len(self.merchant_sell_list))
|
||||
for l in self.merchant_sell_list:
|
||||
stream.write_qword(l[0])
|
||||
stream.write_dword(l[1])
|
||||
@@ -0,0 +1,16 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
|
||||
from arcane.util import ResStream
|
||||
from .HirelingInfo import HirelingInfo
|
||||
|
||||
|
||||
class MinionInfo(HirelingInfo):
|
||||
def load_binary(self, stream: ResStream):
|
||||
super().load_binary(stream)
|
||||
self.minion_info_u = stream.read_string()
|
||||
@@ -0,0 +1,340 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# 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_firendly_charters = stream.read_dword()
|
||||
self.mobile_firendly_charters = [stream.read_dword() for _ in range(num_firendly_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_firendly_charters))
|
||||
for firendly_charter in self.mobile_firendly_charters:
|
||||
stream.write_dword(firendly_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_firendly_charters'] = self.mobile_firendly_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_firendly_charters = data['mobile_firendly_charters']
|
||||
self.mobile_parley_name = data['mobile_parley_name']
|
||||
@@ -0,0 +1,48 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
|
||||
from arcane.util import ResStream
|
||||
from .MobileInfo import MobileInfo
|
||||
|
||||
|
||||
class ShopKeeperInfo(MobileInfo):
|
||||
def load_binary(self, stream: ResStream):
|
||||
super().load_binary(stream)
|
||||
self.shopkeeper_shop_type = stream.read_dword()
|
||||
self.shopkeeper_start_gold = stream.read_dword()
|
||||
self.shopkeeper_std_buy_percent = stream.read_float()
|
||||
self.shopkeeper_std_sell_percent = stream.read_float()
|
||||
self.shopkeeper_nation_buy_percent = stream.read_float()
|
||||
self.shopkeeper_nation_sell_percent = stream.read_float()
|
||||
num_buy_list = stream.read_dword()
|
||||
self.shopkeeper_buy_list = [[
|
||||
stream.read_qword(),
|
||||
stream.read_dword(),
|
||||
] for _ in range(num_buy_list)]
|
||||
num_sell_list = stream.read_dword()
|
||||
self.shopkeeper_sell_list = [[
|
||||
stream.read_qword(),
|
||||
stream.read_dword(),
|
||||
] for _ in range(num_sell_list)]
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
super().save_binary(stream)
|
||||
stream.write_dword(self.shopkeeper_shop_type)
|
||||
stream.write_dword(self.shopkeeper_start_gold)
|
||||
stream.write_float(self.shopkeeper_std_buy_percent)
|
||||
stream.write_float(self.shopkeeper_std_sell_percent)
|
||||
stream.write_float(self.shopkeeper_nation_buy_percent)
|
||||
stream.write_float(self.shopkeeper_nation_sell_percent)
|
||||
stream.write_dword(len(self.shopkeeper_buy_list))
|
||||
for l in self.shopkeeper_buy_list:
|
||||
stream.write_qword(l[0])
|
||||
stream.write_dword(l[1])
|
||||
stream.write_dword(len(self.shopkeeper_sell_list))
|
||||
for l in self.shopkeeper_sell_list:
|
||||
stream.write_qword(l[0])
|
||||
stream.write_dword(l[1])
|
||||
@@ -0,0 +1,33 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
|
||||
from arcane.util import ResStream
|
||||
from .MobileInfo import MobileInfo
|
||||
|
||||
|
||||
class TrainerInfo(MobileInfo):
|
||||
def load_binary(self, stream: ResStream):
|
||||
super().load_binary(stream)
|
||||
self.trainer_std_profit_margin = stream.read_float()
|
||||
self.trainer_profit_margin = stream.read_float()
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
super().save_binary(stream)
|
||||
stream.write_float(self.trainer_std_profit_margin)
|
||||
stream.write_float(self.trainer_profit_margin)
|
||||
|
||||
def save_json(self):
|
||||
data = super().save_json()
|
||||
data['trainer_std_profit_margin'] = self.trainer_std_profit_margin
|
||||
data['trainer_profit_margin'] = self.trainer_profit_margin
|
||||
return data
|
||||
|
||||
def load_json(self, data):
|
||||
super().load_json(data)
|
||||
self.trainer_std_profit_margin = data['trainer_std_profit_margin']
|
||||
self.trainer_profit_margin = data['trainer_profit_margin']
|
||||
@@ -0,0 +1,7 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
Reference in New Issue
Block a user