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,39 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.util import ResStream
class ArcDungeonInfo:
def load_binary(self, stream: ResStream):
self.dungeon_template_id = stream.read_qword()
self.dungeon_unknown = stream.read_qword()
self.dungeon_spawn_location = stream.read_tuple()
self.dungeon_y_offset = stream.read_float()
def save_binary(self, stream: ResStream):
stream.write_qword(self.dungeon_template_id)
stream.write_qword(self.dungeon_unknown)
stream.write_tuple(self.dungeon_spawn_location)
stream.write_float(self.dungeon_y_offset)
def save_json(self):
data = OrderedDict()
data['dungeon_template_id'] = self.dungeon_template_id
data['dungeon_unknown'] = self.dungeon_unknown
data['dungeon_spawn_location'] = self.dungeon_spawn_location
data['dungeon_y_offset'] = self.dungeon_y_offset
return data
def load_json(self, data):
self.dungeon_template_id = data['dungeon_template_id']
self.dungeon_unknown = data['dungeon_unknown']
self.dungeon_spawn_location = data['dungeon_spawn_location']
self.dungeon_y_offset = data['dungeon_y_offset']
+79
View File
@@ -0,0 +1,79 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.zone.arc_mobile import *
from arcane.util import ResStream
from .mobile.HirelingInfo import HirelingInfo
from .mobile.MerchantInfo import MerchantInfo
from .mobile.MinionInfo import MinionInfo
from .mobile.MobileInfo import MobileInfo
from .mobile.ShopKeeperInfo import ShopKeeperInfo
from .mobile.TrainerInfo import TrainerInfo
class ArcMobile:
def load_binary(self, stream: ResStream):
self.mobile_type = stream.read_dword()
if self.mobile_type == 1:
self.mobile_data = MobileInfo()
self.mobile_data.load_binary(stream)
elif self.mobile_type == 2:
self.mobile_data = MobileInfo()
self.mobile_data.load_binary(stream)
elif self.mobile_type == 3:
self.mobile_data = ShopKeeperInfo()
self.mobile_data.load_binary(stream)
elif self.mobile_type == 4:
self.mobile_data = TrainerInfo()
self.mobile_data.load_binary(stream)
elif self.mobile_type == 8:
self.mobile_data = MerchantInfo()
self.mobile_data.load_binary(stream)
elif self.mobile_type == 9:
self.mobile_data = HirelingInfo()
self.mobile_data.load_binary(stream)
elif self.mobile_type == 10:
self.mobile_data = HirelingInfo()
self.mobile_data.load_binary(stream)
elif self.mobile_type == 11:
self.mobile_data = MinionInfo()
self.mobile_data.load_binary(stream)
def save_binary(self, stream: ResStream):
stream.write_dword(self.mobile_type)
self.mobile_data.save_binary(stream)
def save_json(self):
data = OrderedDict()
data['mobile_type'] = MOBILE_TO_STRING[self.mobile_type]
data['mobile_data'] = self.mobile_data.save_json()
return data
def load_json(self, data):
self.mobile_type = STRING_TO_MOBILE[data['mobile_type']]
if self.mobile_type == 1:
self.mobile_data = MobileInfo()
elif self.mobile_type == 2:
self.mobile_data = MobileInfo()
elif self.mobile_type == 3:
self.mobile_data = ShopKeeperInfo()
elif self.mobile_type == 4:
self.mobile_data = TrainerInfo()
elif self.mobile_type == 8:
self.mobile_data = MerchantInfo()
elif self.mobile_type == 9:
self.mobile_data = HirelingInfo()
elif self.mobile_type == 10:
self.mobile_data = HirelingInfo()
elif self.mobile_type == 11:
self.mobile_data = MinionInfo()
self.mobile_data.load_json(data['mobile_data'])
+270
View File
@@ -0,0 +1,270 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# 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.enums.zone.arc_prop import *
from arcane.objects.common.Inventory import Inventory
from arcane.util import ResStream
from .ArcMobile import ArcMobile
from .mobile.ArcBasicZoneObjectInfo import ArcBasicZoneObjectInfo
class ArcPropInfo:
def load_binary(self, stream: ResStream):
self.prop_basic_zone = ArcBasicZoneObjectInfo()
self.prop_basic_zone.load_binary(stream)
self.prop_has_platform = stream.read_bool()
self.prop_platform_height = stream.read_float()
self.prop_is_light_data = stream.read_bool()
if self.prop_is_light_data:
self.prop_light_color = [stream.read_dword() for _ in range(4)]
self.prop_light_radius = stream.read_float()
self.prop_light_flicker = stream.read_dword()
self.prop_light_cube_map = stream.read_dword()
num_content_props = stream.read_dword()
self.prop_content_props = [ArcProp() for _ in range(num_content_props)]
for prop in self.prop_content_props:
prop.load_binary(stream)
num_content_mobiles = stream.read_dword()
self.prop_content_mobiles = [ArcMobile() for _ in range(num_content_mobiles)]
for mobile in self.prop_content_mobiles:
mobile.load_binary(stream)
num_descriptors = stream.read_dword()
self.prop_descriptors = [stream.read_string() for _ in range(num_descriptors)]
self.prop_registry = stream.read_dword()
if self.prop_registry:
self.prop_registry_name = stream.read_string()
self.prop_has_zone_event = stream.read_bool()
self.prop_has_teleporter = stream.read_bool()
if self.prop_has_zone_event:
self.prop_zone_event = stream.read_dword()
if self.prop_has_teleporter:
self.prop_teleporter = stream.read_dword()
def save_binary(self, stream: ResStream):
self.prop_basic_zone.save_binary(stream)
stream.write_bool(self.prop_has_platform)
stream.write_float(self.prop_platform_height)
stream.write_bool(self.prop_is_light_data)
if self.prop_is_light_data:
for i in range(4):
stream.write_dword(self.prop_light_color[i])
stream.write_float(self.prop_light_radius)
stream.write_dword(self.prop_light_flicker)
stream.write_dword(self.prop_light_cube_map)
stream.write_dword(len(self.prop_content_props))
for prop in self.prop_content_props:
prop.save_binary(stream)
stream.write_dword(len(self.prop_content_mobiles))
for mobile in self.prop_content_mobiles:
mobile.save_binary(stream)
stream.write_dword(len(self.prop_descriptors))
for descriptor in self.prop_descriptors:
stream.write_string(descriptor)
stream.write_dword(self.prop_registry)
if self.prop_registry:
stream.write_string(self.prop_registry_name)
stream.write_bool(self.prop_has_zone_event)
stream.write_bool(self.prop_has_teleporter)
if self.prop_has_zone_event:
stream.write_dword(self.prop_zone_event)
if self.prop_has_teleporter:
stream.write_dword(self.prop_teleporter)
def save_json(self):
data = OrderedDict()
data['prop_basic_zone'] = self.prop_basic_zone.save_json()
data['prop_has_platform'] = self.prop_has_platform
data['prop_platform_height'] = self.prop_platform_height
data['prop_is_light_data'] = self.prop_is_light_data
if self.prop_is_light_data:
data['prop_light_color'] = self.prop_light_color
data['prop_light_radius'] = self.prop_light_radius
data['prop_light_flicker'] = self.prop_light_flicker
data['prop_light_cube_map'] = self.prop_light_cube_map
data['prop_content_props'] = []
for prop in self.prop_content_props:
data['prop_content_props'].append(prop.save_json())
data['prop_content_mobiles'] = []
for mobile in self.prop_content_mobiles:
data['prop_content_mobiles'].append(mobile.save_json())
data['prop_descriptors'] = self.prop_descriptors
data['prop_registry'] = self.prop_registry
if self.prop_registry:
data['prop_registry_name'] = self.prop_registry_name
data['prop_has_zone_event'] = self.prop_has_zone_event
data['prop_has_teleporter'] = self.prop_has_teleporter
if self.prop_has_zone_event:
data['prop_zone_event'] = hash_to_string(self.prop_zone_event)
if self.prop_has_teleporter:
data['prop_teleporter'] = hash_to_string(self.prop_teleporter)
return data
def load_json(self, data):
self.prop_basic_zone = ArcBasicZoneObjectInfo()
self.prop_basic_zone.load_json(data['prop_basic_zone'])
self.prop_has_platform = data['prop_has_platform']
self.prop_platform_height = data['prop_platform_height']
self.prop_is_light_data = data['prop_is_light_data']
if self.prop_is_light_data:
self.prop_light_color = data['prop_light_color']
self.prop_light_radius = data['prop_light_radius']
self.prop_light_flicker = data['prop_light_flicker']
self.prop_light_cube_map = data['prop_light_cube_map']
self.prop_content_props = []
for prop_data in data['prop_content_props']:
prop = ArcProp()
prop.load_json(prop_data)
self.prop_content_props.append(prop)
self.prop_content_mobiles = []
for mobile_data in data['prop_content_mobiles']:
mobile = ArcMobile()
mobile.load_json(mobile_data)
self.prop_content_mobiles.append(mobile)
self.prop_descriptors = data['prop_descriptors']
self.prop_registry = data['prop_registry']
if self.prop_registry:
self.prop_registry_name = data['prop_registry_name']
self.prop_has_zone_event = data['prop_has_zone_event']
self.prop_has_teleporter = data['prop_has_teleporter']
if self.prop_has_zone_event:
self.prop_zone_event = string_to_hash(data['prop_zone_event'])
if self.prop_has_teleporter:
self.prop_teleporter = string_to_hash(data['prop_teleporter'])
class ArcCityPropInfo(ArcPropInfo):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
self.city_prop_gm_guild = stream.read_dword()
self.city_prop_gm_nation = stream.read_dword()
self.city_prop_asset_rank = stream.read_dword()
self.city_prop_asset_funds = stream.read_dword()
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.write_dword(self.city_prop_gm_guild)
stream.write_dword(self.city_prop_gm_nation)
stream.write_dword(self.city_prop_asset_rank)
stream.write_dword(self.city_prop_asset_funds)
def save_json(self):
data = super().save_json()
data['city_prop_gm_guild'] = self.city_prop_gm_guild
data['city_prop_gm_nation'] = self.city_prop_gm_nation
data['city_prop_asset_rank'] = self.city_prop_asset_rank
data['city_prop_asset_funds'] = self.city_prop_asset_funds
return data
def load_json(self, data):
super().load_json(data)
self.city_prop_gm_guild = data['city_prop_gm_guild']
self.city_prop_gm_nation = data['city_prop_gm_nation']
self.city_prop_asset_rank = data['city_prop_asset_rank']
self.city_prop_asset_funds = data['city_prop_asset_funds']
class ArcContainerInfo(ArcPropInfo):
def load_binary(self, stream: ResStream):
super().load_binary(stream)
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_trapped_rank = stream.read_dword()
num_booties = stream.read_dword()
self.container_booties = [Inventory() for _ in range(num_booties)]
for inventory in self.container_booties:
inventory.load_binary(stream)
def save_binary(self, stream: ResStream):
super().save_binary(stream)
stream.write_dword(self.container_locked)
stream.write_dword(self.container_locked_rank)
stream.write_dword(self.container_barred)
stream.write_dword(self.container_barred_rank)
stream.write_dword(self.container_trapped)
stream.write_dword(self.container_trapped_rank)
stream.write_dword(len(self.container_booties))
for inventory in self.container_booties:
inventory.save_binary(stream)
def save_json(self):
data = super().save_json()
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_trapped_rank'] = self.container_trapped_rank
data['container_booties'] = []
for inventory in self.container_booties:
data['container_booties'].append(inventory.save_json())
return data
def load_json(self, data):
super().load_json(data)
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_trapped_rank = data['container_trapped_rank']
self.container_booties = []
for inventory_data in data['container_booties']:
inventory = Inventory()
inventory.load_json(inventory_data)
self.container_booties.append(inventory)
class ArcProp:
def load_binary(self, stream: ResStream):
self.prop_type = stream.read_dword()
if self.prop_type == 5:
self.prop_data = ArcPropInfo()
self.prop_data.load_binary(stream)
elif self.prop_type == 6:
self.prop_data = ArcCityPropInfo()
self.prop_data.load_binary(stream)
elif self.prop_type == 7:
self.prop_data = ArcContainerInfo()
self.prop_data.load_binary(stream)
def save_binary(self, stream: ResStream):
stream.write_dword(self.prop_type)
self.prop_data.save_binary(stream)
def save_json(self):
data = OrderedDict()
data['prop_type'] = PROP_TO_STRING[self.prop_type]
data['prop_data'] = self.prop_data.save_json()
return data
def load_json(self, data):
self.prop_type = STRING_TO_PROP[data['prop_type']]
if self.prop_type == 5:
self.prop_data = ArcPropInfo()
elif self.prop_type == 6:
self.prop_data = ArcCityPropInfo()
elif self.prop_type == 7:
self.prop_data = ArcContainerInfo()
self.prop_data.load_json(data['prop_data'])
@@ -0,0 +1,44 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.util import ResStream
class ArcSoundInfo:
def load_binary(self, stream: ResStream):
self.sound_playlist = stream.read_string()
self.sound_id = stream.read_dword()
self.sound_template = stream.read_string()
self.sound_location = stream.read_tuple()
self.sound_radius = stream.read_float()
def save_binary(self, stream: ResStream):
stream.write_string(self.sound_playlist)
stream.write_dword(self.sound_id)
stream.write_string(self.sound_template)
stream.write_tuple(self.sound_location)
stream.write_float(self.sound_radius)
def save_json(self):
data = OrderedDict()
data['sound_playlist'] = self.sound_playlist
data['sound_id'] = self.sound_id
data['sound_template'] = self.sound_template
data['sound_location'] = self.sound_location
data['sound_radius'] = self.sound_radius
return data
def load_json(self, data):
self.sound_playlist = data['sound_playlist']
self.sound_id = data['sound_id']
self.sound_template = data['sound_template']
self.sound_location = data['sound_location']
self.sound_radius = data['sound_radius']
@@ -0,0 +1,141 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.zone.arc_terraingen import *
from arcane.util import ResStream
class ArcTerrainGen:
def load_binary(self, stream: ResStream):
self.terrain_type = stream.read_dword()
if self.terrain_type in [1, 2, 3, 5]:
self.terrain_max_x = stream.read_float()
self.terrain_max_z = stream.read_float()
self.terrain_h = stream.read_float()
self.terrain_lacunarity = stream.read_float()
self.terrain_octaves = stream.read_dword()
self.terrain_offset = stream.read_float()
self.terrain_gain = stream.read_float()
self.terrain_seeds = [
stream.read_dword(),
stream.read_dword(),
]
if self.terrain_type == 4:
self.terrain_max_x = stream.read_float()
self.terrain_max_z = stream.read_float()
self.terrain_height = stream.read_float()
if self.terrain_type == 6:
self.terrain_max_x = stream.read_float()
self.terrain_max_z = stream.read_float()
self.terrain_x_size = stream.read_float()
self.terrain_z_size = stream.read_float()
self.terrain_mesh = stream.read_qword()
if self.terrain_type == 7:
self.terrain_max_x = stream.read_float()
self.terrain_max_z = stream.read_float()
self.terrain_x_size = stream.read_float()
self.terrain_z_size = stream.read_float()
self.terrain_min_y = stream.read_float()
self.terrain_max_y = stream.read_float()
self.terrain_image = stream.read_qword()
def save_binary(self, stream: ResStream):
stream.write_dword(self.terrain_type)
if self.terrain_type in [1, 2, 3, 5]:
stream.write_float(self.terrain_max_x)
stream.write_float(self.terrain_max_z)
stream.write_float(self.terrain_h)
stream.write_float(self.terrain_lacunarity)
stream.write_dword(self.terrain_octaves)
stream.write_float(self.terrain_offset)
stream.write_float(self.terrain_gain)
stream.read_dword(self.terrain_seeds[0])
stream.read_dword(self.terrain_seeds[1])
if self.terrain_type == 4:
stream.write_float(self.terrain_max_x)
stream.write_float(self.terrain_max_z)
stream.write_float(self.terrain_height)
if self.terrain_type == 6:
stream.write_float(self.terrain_max_x)
stream.write_float(self.terrain_max_z)
stream.write_float(self.terrain_x_size)
stream.write_float(self.terrain_z_size)
stream.write_qword(self.terrain_mesh)
if self.terrain_type == 7:
stream.write_float(self.terrain_max_x)
stream.write_float(self.terrain_max_z)
stream.write_float(self.terrain_x_size)
stream.write_float(self.terrain_z_size)
stream.write_float(self.terrain_min_y)
stream.write_float(self.terrain_max_y)
stream.write_qword(self.terrain_image)
def save_json(self):
data = OrderedDict()
data['terrain_type'] = TERRAIN_TYPE_TO_STRING[self.terrain_type]
if self.terrain_type in [1, 2, 3, 5]:
data['terrain_max_x'] = self.terrain_max_x
data['terrain_max_z'] = self.terrain_max_z
data['terrain_h'] = self.terrain_h
data['terrain_lacunarity'] = self.terrain_lacunarity
data['terrain_octaves'] = self.terrain_octaves
data['terrain_offset'] = self.terrain_offset
data['terrain_gain'] = self.terrain_gain
data['terrain_seeds'] = self.terrain_seeds
if self.terrain_type == 4:
data['terrain_max_x'] = self.terrain_max_x
data['terrain_max_z'] = self.terrain_max_z
data['terrain_height'] = self.terrain_height
if self.terrain_type == 6:
data['terrain_max_x'] = self.terrain_max_x
data['terrain_max_z'] = self.terrain_max_z
data['terrain_x_size'] = self.terrain_x_size
data['terrain_z_size'] = self.terrain_z_size
data['terrain_mesh'] = self.terrain_mesh
if self.terrain_type == 7:
data['terrain_max_x'] = self.terrain_max_x
data['terrain_max_z'] = self.terrain_max_z
data['terrain_x_size'] = self.terrain_x_size
data['terrain_z_size'] = self.terrain_z_size
data['terrain_min_y'] = self.terrain_min_y
data['terrain_max_y'] = self.terrain_max_y
data['terrain_image'] = self.terrain_image
return data
def load_json(self, data):
self.terrain_type = STRING_TO_TERRAIN_TYPE[data['terrain_type']]
if self.terrain_type in [1, 2, 3, 5]:
self.terrain_max_x = data['terrain_max_x']
self.terrain_max_z = data['terrain_max_z']
self.terrain_h = data['terrain_h']
self.terrain_lacunarity = data['terrain_lacunarity']
self.terrain_octaves = data['terrain_octaves']
self.terrain_offset = data['terrain_offset']
self.terrain_gain = data['terrain_gain']
self.terrain_seeds = data['terrain_seeds']
if self.terrain_type == 4:
self.terrain_max_x = data['terrain_max_x']
self.terrain_max_z = data['terrain_max_z']
self.terrain_height = data['terrain_height']
if self.terrain_type == 6:
self.terrain_max_x = data['terrain_max_x']
self.terrain_max_z = data['terrain_max_z']
self.terrain_x_size = data['terrain_x_size']
self.terrain_z_size = data['terrain_z_size']
self.terrain_mesh = data['terrain_mesh']
if self.terrain_type == 7:
self.terrain_max_x = data['terrain_max_x']
self.terrain_max_z = data['terrain_max_z']
self.terrain_x_size = data['terrain_x_size']
self.terrain_z_size = data['terrain_z_size']
self.terrain_min_y = data['terrain_min_y']
self.terrain_max_y = data['terrain_max_y']
self.terrain_image = data['terrain_image']
+408
View File
@@ -0,0 +1,408 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.enums.zone.arc_zone import *
from arcane.util import ResStream
from .ArcDungeonInfo import ArcDungeonInfo
from .ArcMobile import ArcMobile
from .ArcProp import ArcProp
from .ArcSoundInfo import ArcSoundInfo
from .ArcTerrainGen import ArcTerrainGen
from .ArcZoneBiomState import ArcZoneBiomState
from .ArcZoneEvent import ArcZoneEvent
from .ArcZoneGoal import ArcZoneGoal
from .TerrainObjectInfo import TerrainObjectInfo
from .WaterInfo import WaterInfo
from .WeatherEventInfo import WeatherEventInfo
class ArcZone:
def load_binary(self, stream: ResStream):
self.zone_type = stream.read_dword()
self.zone_name = stream.read_string()
self.zone_custom_texture = stream.read_qword()
self.zone_width_threshold = stream.read_dword()
self.zone_material_threshold = stream.read_dword()
self.zone_max_width_index = stream.read_dword()
self.zone_max_material_index = stream.read_dword()
self.zone_custom_texture_wrap = stream.read_bool()
self.zone_peace_zone = stream.read_bool()
self.zone_guild_zone = stream.read_bool()
self.zone_minor_radius = stream.read_float()
self.zone_major_radius = stream.read_float()
self.zone_min_blend = stream.read_float()
self.zone_max_blend = stream.read_float()
self.zone_influence = stream.read_float()
self.zone_unknown1 = stream.read_float()
self.zone_y_offset = stream.read_float()
self.zone_global_height = stream.read_float()
self.zone_transition_height = stream.read_float()
self.zone_upper_transition_height = stream.read_float()
self.zone_tile_cord_type = stream.read_dword()
self.zone_tile_pattern_prob = stream.read_float()
self.zone_pattern_type = stream.read_dword()
self.zone_sea_level_index = stream.read_dword()
self.zone_sea_level = stream.read_float()
self.zone_sea_level_type = stream.read_dword()
self.zone_grad = stream.read_float()
self.zone_tile_set = stream.read_qword()
self.zone_song = stream.read_qword()
self.zone_is_biom = stream.read_bool()
if self.zone_is_biom:
self.zone_biom = ArcZoneBiomState()
self.zone_biom.load_binary(stream)
num_weather_events = stream.read_dword()
self.zone_weather_events = [WeatherEventInfo() for _ in range(num_weather_events)]
for event in self.zone_weather_events:
event.load_binary(stream)
self.zone_has_water = stream.read_bool()
if self.zone_has_water:
self.zone_water = WaterInfo()
self.zone_water.load_binary(stream)
self.zone_has_terrain_gen = stream.read_bool()
if self.zone_has_terrain_gen:
self.zone_terrain_gen = ArcTerrainGen()
self.zone_terrain_gen.load_binary(stream)
num_patterns = stream.read_dword()
self.zone_patterns = [
[
stream.read_dword(),
stream.read_float(),
] for _ in range(num_patterns)
]
num_alts = stream.read_dword()
self.zone_alts = [stream.read_float() for _ in range(num_alts)]
num_terrain_objects = stream.read_dword()
self.zone_terrain_objects = [TerrainObjectInfo() for _ in range(num_terrain_objects)]
for obj in self.zone_terrain_objects:
obj.load_binary(stream)
num_mobiles = stream.read_dword()
self.zone_mobile_info = [ArcMobile() for _ in range(num_mobiles)]
for mobile in self.zone_mobile_info:
mobile.load_binary(stream)
num_sounds = stream.read_dword()
self.zone_sound_info = [ArcSoundInfo() for _ in range(num_sounds)]
for sound in self.zone_sound_info:
sound.load_binary(stream)
num_dungeons = stream.read_dword()
self.zone_dungeon_info = [ArcDungeonInfo() for _ in range(num_dungeons)]
for dungeon in self.zone_dungeon_info:
dungeon.load_binary(stream)
num_props = stream.read_dword()
self.zone_prop_info = [ArcProp() for _ in range(num_props)]
for prop in self.zone_prop_info:
prop.load_binary(stream)
num_architectures = stream.read_dword()
self.zone_architecture = [stream.read_string() for _ in range(num_architectures)]
num_events = stream.read_dword()
self.zone_events = [ArcZoneEvent() for _ in range(num_events)]
for event in self.zone_events:
event.load_binary(stream)
num_point_sets = stream.read_dword()
self.zone_point_sets = [ArcZoneGoal() for _ in range(num_point_sets)]
for point_set in self.zone_point_sets:
point_set.load_binary(stream)
self.zone_has_layers = stream.read_bool()
if self.zone_has_layers:
self.zone_base_texture = stream.read_qword()
num_layer_texture_ids = stream.read_dword()
self.zone_layer_texture_ids = [stream.read_qword() for _ in range(num_layer_texture_ids)]
num_layer_mappings = stream.read_dword()
self.zone_layer_mappings = []
for _ in range(num_layer_mappings):
layer = stream.read_qword()
num = stream.read_dword()
textures = [stream.read_qword() for _ in range(num)]
self.zone_layer_mappings.append([layer, textures])
else:
num_textures = stream.read_dword()
self.zone_textures = [
[
stream.read_qword(),
stream.read_float(),
stream.read_float(),
stream.read_float(),
stream.read_float(),
stream.read_float(),
stream.read_dword(),
stream.read_dword(),
stream.read_dword(),
] for _ in range(num_textures)
]
def save_binary(self, stream: ResStream):
stream.write_dword(self.zone_type)
stream.write_string(self.zone_name)
stream.write_qword(self.zone_custom_texture)
stream.write_dword(self.zone_width_threshold)
stream.write_dword(self.zone_material_threshold)
stream.write_dword(self.zone_max_width_index)
stream.write_dword(self.zone_max_material_index)
stream.write_bool(self.zone_custom_texture_wrap)
stream.write_bool(self.zone_peace_zone)
stream.write_bool(self.zone_guild_zone)
stream.write_float(self.zone_minor_radius)
stream.write_float(self.zone_major_radius)
stream.write_float(self.zone_min_blend)
stream.write_float(self.zone_max_blend)
stream.write_float(self.zone_influence)
stream.write_float(self.zone_unknown1)
stream.write_float(self.zone_y_offset)
stream.write_float(self.zone_global_height)
stream.write_float(self.zone_transition_height)
stream.write_float(self.zone_upper_transition_height)
stream.write_dword(self.zone_tile_cord_type)
stream.write_float(self.zone_tile_pattern_prob)
stream.write_dword(self.zone_pattern_type)
stream.write_dword(self.zone_sea_level_index)
stream.write_float(self.zone_sea_level)
stream.write_dword(self.zone_sea_level_type)
stream.write_float(self.zone_grad)
stream.write_qword(self.zone_tile_set)
stream.write_qword(self.zone_song)
stream.write_bool(self.zone_is_biom)
if self.zone_is_biom:
self.zone_biom.save_binary(stream)
stream.write_dword(len(self.zone_weather_events))
for event in self.zone_weather_events:
event.save_binary(stream)
stream.write_bool(self.zone_has_water)
if self.zone_has_water:
self.zone_water.save_binary(stream)
stream.write_bool(self.zone_has_terrain_gen)
if self.zone_has_terrain_gen:
self.zone_terrain_gen.save_binary(stream)
stream.write_dword(len(self.zone_patterns))
for pattern in self.zone_patterns:
stream.write_dword(pattern[0])
stream.write_float(pattern[1])
stream.write_dword(len(self.zone_alts))
for alt in self.zone_alts:
stream.write_float(alt)
stream.write_dword(len(self.zone_terrain_objects))
for obj in self.zone_terrain_objects:
obj.save_binary(stream)
stream.write_dword(len(self.zone_mobile_info))
for mobile in self.zone_mobile_info:
mobile.save_binary(stream)
stream.write_dword(len(self.zone_sound_info))
for sound in self.zone_sound_info:
sound.save_binary(stream)
stream.write_dword(len(self.zone_dungeon_info))
for dungeon in self.zone_dungeon_info:
dungeon.save_binary(stream)
stream.write_dword(len(self.zone_prop_info))
for prop in self.zone_prop_info:
prop.save_binary(stream)
stream.write_dword(len(self.zone_architecture))
for arch in self.zone_architecture:
stream.write_string(arch)
stream.write_dword(len(self.zone_events))
for event in self.zone_events:
event.save_binary(stream)
stream.write_dword(len(self.zone_point_sets))
for point_set in self.zone_point_sets:
point_set.save_binary(stream)
stream.write_bool(self.zone_has_layers)
if self.zone_has_layers:
stream.write_qword(self.zone_base_texture)
stream.write_dword(len(self.zone_layer_texture_ids))
for texture_id in self.zone_layer_texture_ids:
stream.write_qword(texture_id)
stream.write_dword(len(self.zone_layer_mappings))
for layer, textures in self.zone_layer_mappings:
stream.write_qword(layer)
stream.write_dword(len(textures))
for texture in textures:
stream.write_qword(texture)
else:
stream.write_dword(len(self.zone_textures))
for texture in self.zone_textures:
stream.write_qword(texture[0])
stream.write_float(texture[1])
stream.write_float(texture[2])
stream.write_float(texture[3])
stream.write_float(texture[4])
stream.write_float(texture[5])
stream.write_dword(texture[6])
stream.write_dword(texture[7])
stream.write_dword(texture[8])
def save_json(self):
data = OrderedDict()
data['zone_type'] = ZONE_TO_STRING[self.zone_type]
data['zone_name'] = self.zone_name
data['zone_custom_texture'] = self.zone_custom_texture
data['zone_width_threshold'] = self.zone_width_threshold
data['zone_material_threshold'] = self.zone_material_threshold
data['zone_max_width_index'] = self.zone_max_width_index
data['zone_max_material_index'] = self.zone_max_material_index
data['zone_custom_texture_wrap'] = self.zone_custom_texture_wrap
data['zone_peace_zone'] = self.zone_peace_zone
data['zone_guild_zone'] = self.zone_guild_zone
data['zone_minor_radius'] = self.zone_minor_radius
data['zone_major_radius'] = self.zone_major_radius
data['zone_min_blend'] = self.zone_min_blend
data['zone_max_blend'] = self.zone_max_blend
data['zone_influence'] = self.zone_influence
data['zone_unknown1'] = self.zone_unknown1
data['zone_y_offset'] = self.zone_y_offset
data['zone_global_height'] = self.zone_global_height
data['zone_transition_height'] = self.zone_transition_height
data['zone_upper_transition_height'] = self.zone_upper_transition_height
data['zone_tile_cord_type'] = TILECOORD_TO_STRING[self.zone_tile_cord_type]
data['zone_tile_pattern_prob'] = self.zone_tile_pattern_prob
data['zone_pattern_type'] = PATTERN_TO_STRING[self.zone_pattern_type]
data['zone_sea_level_index'] = self.zone_sea_level_index
data['zone_sea_level'] = self.zone_sea_level
data['zone_sea_level_type'] = SEALEVEL_TO_STRING[self.zone_sea_level_type]
data['zone_grad'] = self.zone_grad
data['zone_tile_set'] = self.zone_tile_set
data['zone_song'] = self.zone_song
data['zone_is_biom'] = self.zone_is_biom
if self.zone_is_biom:
data['zone_biom'] = self.zone_biom.save_json()
data['zone_weather_events'] = []
for event in self.zone_weather_events:
data['zone_weather_events'].append(event.save_json())
data['zone_has_water'] = self.zone_has_water
if self.zone_has_water:
data['zone_water'] = self.zone_water.save_json()
data['zone_has_terrain_gen'] = self.zone_has_terrain_gen
if self.zone_has_terrain_gen:
data['zone_terrain_gen'] = self.zone_terrain_gen.save_json()
data['zone_patterns'] = self.zone_patterns
data['zone_alts'] = self.zone_alts
data['zone_terrain_objects'] = []
for obj in self.zone_terrain_objects:
data['zone_terrain_objects'].append(obj.save_json())
data['zone_mobile_info'] = []
for mobile in self.zone_mobile_info:
data['zone_mobile_info'].append(mobile.save_json())
data['zone_sound_info'] = []
for sound in self.zone_sound_info:
data['zone_sound_info'].append(sound.save_json())
data['zone_dungeon_info'] = []
for dungeon in self.zone_dungeon_info:
data['zone_dungeon_info'].append(dungeon.save_json())
data['zone_prop_info'] = []
for prop in self.zone_prop_info:
data['zone_prop_info'].append(prop.save_json())
data['zone_architecture'] = self.zone_architecture
data['zone_events'] = []
for event in self.zone_events:
data['zone_events'].append(event.save_json())
data['zone_point_sets'] = []
for point_set in self.zone_point_sets:
data['zone_point_sets'].append(point_set.save_json())
data['zone_has_layers'] = self.zone_has_layers
if self.zone_has_layers:
data['zone_base_texture'] = self.zone_base_texture
data['zone_layer_texture_ids'] = self.zone_layer_texture_ids
data['zone_layer_mappings'] = self.zone_layer_mappings
else:
data['zone_textures'] = self.zone_textures
return data
def load_json(self, data):
self.zone_type = STRING_TO_ZONE[data['zone_type']]
self.zone_name = data['zone_name']
self.zone_custom_texture = data['zone_custom_texture']
self.zone_width_threshold = data['zone_width_threshold']
self.zone_material_threshold = data['zone_material_threshold']
self.zone_max_width_index = data['zone_max_width_index']
self.zone_max_material_index = data['zone_max_material_index']
self.zone_custom_texture_wrap = data['zone_custom_texture_wrap']
self.zone_peace_zone = data['zone_peace_zone']
self.zone_guild_zone = data['zone_guild_zone']
self.zone_minor_radius = data['zone_minor_radius']
self.zone_major_radius = data['zone_major_radius']
self.zone_min_blend = data['zone_min_blend']
self.zone_max_blend = data['zone_max_blend']
self.zone_influence = data['zone_influence']
self.zone_unknown1 = data['zone_unknown1']
self.zone_y_offset = data['zone_y_offset']
self.zone_global_height = data['zone_global_height']
self.zone_transition_height = data['zone_transition_height']
self.zone_upper_transition_height = data['zone_upper_transition_height']
self.zone_tile_cord_type = STRING_TO_TILECOORD[data['zone_tile_cord_type']]
self.zone_tile_pattern_prob = data['zone_tile_pattern_prob']
self.zone_pattern_type = STRING_TO_PATTERN[data['zone_pattern_type']]
self.zone_sea_level_index = data['zone_sea_level_index']
self.zone_sea_level = data['zone_sea_level']
self.zone_sea_level_type = STRING_TO_SEALEVEL[data['zone_sea_level_type']]
self.zone_grad = data['zone_grad']
self.zone_tile_set = data['zone_tile_set']
self.zone_song = data['zone_song']
self.zone_is_biom = data['zone_is_biom']
if self.zone_is_biom:
self.zone_biom = ArcZoneBiomState()
self.zone_biom.load_json(data['zone_biom'])
self.zone_weather_events = []
for event_data in data['zone_weather_events']:
event = WeatherEventInfo()
event.load_json(event_data)
self.zone_weather_events.append(event)
self.zone_has_water = data['zone_has_water']
if self.zone_has_water:
self.zone_water = WaterInfo()
self.zone_water.load_json(data['zone_water'])
self.zone_has_terrain_gen = data['zone_has_terrain_gen']
if self.zone_has_terrain_gen:
self.zone_terrain_gen = ArcTerrainGen()
self.zone_terrain_gen.load_json(data['zone_terrain_gen'])
self.zone_patterns = data['zone_patterns']
self.zone_alts = data['zone_alts']
self.zone_terrain_objects = []
for obj_data in data['zone_terrain_objects']:
obj = TerrainObjectInfo()
obj.load_json(obj_data)
self.zone_terrain_objects.append(obj)
self.zone_mobile_info = []
for mobile_data in data['zone_mobile_info']:
mobile = ArcMobile()
mobile.load_json(mobile_data)
self.zone_mobile_info.append(mobile)
self.zone_sound_info = []
for sound_data in data['zone_sound_info']:
sound = ArcSoundInfo()
sound.load_json(sound_data)
self.zone_sound_info.append(sound)
self.zone_dungeon_info = []
for dungeon_data in data['zone_dungeon_info']:
dungeon = ArcDungeonInfo()
dungeon.load_json(dungeon_data)
self.zone_dungeon_info.append(dungeon)
self.zone_prop_info = []
for prop_data in data['zone_prop_info']:
prop = ArcProp()
prop.load_json(prop_data)
self.zone_prop_info.append(prop)
self.zone_architecture = data['zone_architecture']
self.zone_events = []
for event_data in data['zone_events']:
event = ArcZoneEvent()
event.load_json(event_data)
self.zone_events.append(event)
self.zone_point_sets = []
for point_set_data in data['zone_point_sets']:
point_set = ArcZoneGoal()
point_set.load_json(point_set_data)
self.zone_point_sets.append(point_set)
self.zone_has_layers = data['zone_has_layers']
if self.zone_has_layers:
self.zone_base_texture = data['zone_base_texture']
self.zone_layer_texture_ids = data['zone_layer_texture_ids']
self.zone_layer_mappings = data['zone_layer_mappings']
else:
self.zone_textures = data['zone_textures']
@@ -0,0 +1,37 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# 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 ArcZoneBiomState:
def load_binary(self, stream: ResStream):
self.biom_sky_state_id = stream.read_dword()
self.biom_environment_state_id = stream.read_dword()
self.biom_weather_state_id = stream.read_dword()
def save_binary(self, stream: ResStream):
stream.write_dword(self.biom_sky_state_id)
stream.write_dword(self.biom_environment_state_id)
stream.write_dword(self.biom_weather_state_id)
def save_json(self):
data = OrderedDict()
data['biom_sky_state_id'] = hash_to_string(self.biom_sky_state_id)
data['biom_environment_state_id'] = hash_to_string(self.biom_environment_state_id)
data['biom_weather_state_id'] = hash_to_string(self.biom_weather_state_id)
return data
def load_json(self, data):
self.biom_sky_state_id = string_to_hash(data['biom_sky_state_id'])
self.biom_environment_state_id = string_to_hash(data['biom_environment_state_id'])
self.biom_weather_state_id = string_to_hash(data['biom_weather_state_id'])
@@ -0,0 +1,62 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from arcane.util import ResStream
class ArcZTriggerAction:
def load_binary(self, stream: ResStream):
self.zone_trigger_action_type = stream.read_dword()
self.zone_trigger_action_unknown1 = stream.read_bool()
self.zone_trigger_action_is_timed = stream.read_bool()
self.zone_trigger_action_unknown2 = stream.read_bool()
if self.zone_trigger_action_is_timed:
self.zone_trigger_action_time_begin = stream.read_float()
self.zone_trigger_action_time_end = stream.read_float()
self.zone_trigger_action_has_state = stream.read_bool()
if self.zone_trigger_action_has_state:
self.zone_trigger_action_new_state = stream.read_dword()
num_specifics = stream.read_dword()
self.zone_trigger_action_specifics = [stream.read_dword() for _ in range(num_specifics)]
num_items = stream.read_dword()
self.zone_trigger_action_items = [stream.read_dword() for _ in range(num_items)]
num_parent_states = stream.read_dword()
self.zone_trigger_action_parent_states = [stream.read_dword() for _ in range(num_parent_states)]
class ArcZoneEventInfo:
def load_binary(self, stream: ResStream):
self.zone_event_recycle = stream.read_dword()
self.zone_event_spawn_radius = stream.read_float()
self.zone_event_fc_label = stream.read_string()
self.zone_event_event_name = stream.read_string()
self.zone_event_unknown1 = stream.read_dword()
self.zone_event_spawn_location = stream.read_tuple()
self.zone_event_parent_name = stream.read_string()
self.zone_event_unknown2 = stream.read_dword()
self.zone_event_unknown3 = stream.read_bool()
num_triggers = stream.read_dword()
self.zone_event_triggers = [ArcZTriggerAction() for _ in range(num_triggers)]
for action in self.zone_event_triggers:
action.load_binary(stream)
class ArcZoneEvent:
def load_binary(self, stream: ResStream):
self.zone_event_type = stream.read_dword()
if self.zone_event_type == 1:
self.zone_event_data = ArcZoneEventInfo()
self.zone_event_data.load_binary(stream)
elif self.zone_event_type == 2:
self.zone_event_data = ArcZoneEventInfo()
self.zone_event_data.load_binary(stream)
elif self.zone_event_type == 3:
self.zone_event_data = ArcZoneEventInfo()
self.zone_event_data.load_binary(stream)
@@ -0,0 +1,93 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# 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.enums.zone.arc_zone_goal import *
from arcane.util import ResStream
class ArcZoneGoalPoint:
def load_binary(self, stream: ResStream):
self.zone_goal_point_vectors = [stream.read_dword() for _ in range(6)]
self.zone_goal_point_location = stream.read_tuple()
def save_binary(self, stream: ResStream):
for i in range(6):
stream.write_dword(self.zone_goal_point_vectors[i])
stream.write_tuple(self.zone_goal_point_location)
def save_json(self):
data = OrderedDict()
data['zone_goal_point_vectors'] = self.zone_goal_point_vectors
data['zone_goal_point_location'] = self.zone_goal_point_location
return data
def load_json(self, data):
self.zone_goal_point_vectors = data['zone_goal_point_vectors']
self.zone_goal_point_location = data['zone_goal_point_location']
class ArcZoneGoal:
def load_binary(self, stream: ResStream):
self.zone_goal_type = stream.read_dword()
self.zone_goal_value = stream.read_dword()
self.zone_goal_name = stream.read_string()
self.zone_goal_delay = stream.read_dword()
self.zone_goal_has_teleport_registry = stream.read_bool()
if self.zone_goal_has_teleport_registry:
self.zone_goal_teleport_registry = stream.read_dword()
self.zone_goal_dungeon = stream.read_qword()
num_points = stream.read_dword()
self.zone_goal_points = [ArcZoneGoalPoint() for _ in range(num_points)]
for point in self.zone_goal_points:
point.load_binary(stream)
def save_binary(self, stream: ResStream):
stream.write_dword(self.zone_goal_type)
stream.write_dword(self.zone_goal_value)
stream.write_string(self.zone_goal_name)
stream.write_dword(self.zone_goal_delay)
stream.write_bool(self.zone_goal_has_teleport_registry)
if self.zone_goal_has_teleport_registry:
stream.write_dword(self.zone_goal_teleport_registry)
stream.write_qword(self.zone_goal_dungeon)
stream.write_dword(len(self.zone_goal_points))
for point in self.zone_goal_points:
point.save_binary(stream)
def save_json(self):
data = OrderedDict()
data['zone_goal_type'] = GOAL_TYPE_TO_STRING[self.zone_goal_type]
data['zone_goal_value'] = hash_to_string(self.zone_goal_value)
data['zone_goal_name'] = self.zone_goal_name
data['zone_goal_delay'] = self.zone_goal_delay
data['zone_goal_has_teleport_registry'] = self.zone_goal_has_teleport_registry
if self.zone_goal_has_teleport_registry:
data['zone_goal_teleport_registry'] = hash_to_string(self.zone_goal_teleport_registry)
data['zone_goal_dungeon'] = self.zone_goal_dungeon
data['zone_goal_points'] = []
for point in self.zone_goal_points:
data['zone_goal_points'].append(point.save_json())
return data
def load_json(self, data):
self.zone_goal_type = STRING_TO_GOAL_TYPE[data['zone_goal_type']]
self.zone_goal_value = string_to_hash(data['zone_goal_value'])
self.zone_goal_name = data['zone_goal_name']
self.zone_goal_delay = data['zone_goal_delay']
self.zone_goal_has_teleport_registry = data['zone_goal_has_teleport_registry']
if self.zone_goal_has_teleport_registry:
self.zone_goal_teleport_registry = string_to_hash(data['zone_goal_teleport_registry'])
self.zone_goal_dungeon = data['zone_goal_dungeon']
self.zone_goal_points = []
for point_data in data['zone_goal_points']:
point = ArcZoneGoalPoint()
point.load_json(point_data)
self.zone_goal_points.append(point)
@@ -0,0 +1,92 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.util import ResStream
class TerrainObjectInfo:
def load_binary(self, stream: ResStream):
self.terrain_object_id = stream.read_qword()
self.terrain_object_h = stream.read_float()
self.terrain_object_lacunarity = stream.read_float()
self.terrain_object_octaves = stream.read_dword()
self.terrain_object_offset = stream.read_float()
self.terrain_object_gain = stream.read_float()
self.terrain_object_min_alt = stream.read_float()
self.terrain_object_max_alt = stream.read_float()
self.terrain_object_min_slope = stream.read_float()
self.terrain_object_max_slope = stream.read_float()
self.terrain_object_max_pop = stream.read_dword()
self.terrain_object_is_fractal_pop = stream.read_bool()
self.terrain_object_unknown1 = stream.read_dword()
self.terrain_object_y_offset = stream.read_float()
self.terrain_object_pop_image_id = stream.read_qword()
self.terrain_object_image_min_y = stream.read_float()
self.terrain_object_image_max_y = stream.read_float()
def save_binary(self, stream: ResStream):
stream.write_qword(self.terrain_object_id)
stream.write_float(self.terrain_object_h)
stream.write_float(self.terrain_object_lacunarity)
stream.write_dword(self.terrain_object_octaves)
stream.write_float(self.terrain_object_offset)
stream.write_float(self.terrain_object_gain)
stream.write_float(self.terrain_object_min_alt)
stream.write_float(self.terrain_object_max_alt)
stream.write_float(self.terrain_object_min_slope)
stream.write_float(self.terrain_object_max_slope)
stream.write_dword(self.terrain_object_max_pop)
stream.write_bool(self.terrain_object_is_fractal_pop)
stream.write_dword(self.terrain_object_unknown1)
stream.write_float(self.terrain_object_y_offset)
stream.write_qword(self.terrain_object_pop_image_id)
stream.write_float(self.terrain_object_image_min_y)
stream.write_float(self.terrain_object_image_max_y)
def save_json(self):
data = OrderedDict()
data['terrain_object_id'] = self.terrain_object_id
data['terrain_object_h'] = self.terrain_object_h
data['terrain_object_lacunarity'] = self.terrain_object_lacunarity
data['terrain_object_octaves'] = self.terrain_object_octaves
data['terrain_object_offset'] = self.terrain_object_offset
data['terrain_object_gain'] = self.terrain_object_gain
data['terrain_object_min_alt'] = self.terrain_object_min_alt
data['terrain_object_max_alt'] = self.terrain_object_max_alt
data['terrain_object_min_slope'] = self.terrain_object_min_slope
data['terrain_object_max_slope'] = self.terrain_object_max_slope
data['terrain_object_max_pop'] = self.terrain_object_max_pop
data['terrain_object_is_fractal_pop'] = self.terrain_object_is_fractal_pop
data['terrain_object_unknown1'] = self.terrain_object_unknown1
data['terrain_object_y_offset'] = self.terrain_object_y_offset
data['terrain_object_pop_image_id'] = self.terrain_object_pop_image_id
data['terrain_object_image_min_y'] = self.terrain_object_image_min_y
data['terrain_object_image_max_y'] = self.terrain_object_image_max_y
return data
def load_json(self, data):
self.terrain_object_id = data['terrain_object_id']
self.terrain_object_h = data['terrain_object_h']
self.terrain_object_lacunarity = data['terrain_object_lacunarity']
self.terrain_object_octaves = data['terrain_object_octaves']
self.terrain_object_offset = data['terrain_object_offset']
self.terrain_object_gain = data['terrain_object_gain']
self.terrain_object_min_alt = data['terrain_object_min_alt']
self.terrain_object_max_alt = data['terrain_object_max_alt']
self.terrain_object_min_slope = data['terrain_object_min_slope']
self.terrain_object_max_slope = data['terrain_object_max_slope']
self.terrain_object_max_pop = data['terrain_object_max_pop']
self.terrain_object_is_fractal_pop = data['terrain_object_is_fractal_pop']
self.terrain_object_unknown1 = data['terrain_object_unknown1']
self.terrain_object_y_offset = data['terrain_object_y_offset']
self.terrain_object_pop_image_id = data['terrain_object_pop_image_id']
self.terrain_object_image_min_y = data['terrain_object_image_min_y']
self.terrain_object_image_max_y = data['terrain_object_image_max_y']
+92
View File
@@ -0,0 +1,92 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from collections import OrderedDict
from arcane.util import ResStream
class WaterInfo:
def load_binary(self, stream: ResStream):
self.water_texture = stream.read_qword()
self.water_unknown1 = [
stream.read_float(),
stream.read_float(),
stream.read_float(),
stream.read_float(),
]
self.water_x_wave_length = stream.read_float()
self.water_z_wave_length = stream.read_float()
self.water_x_speed = stream.read_float()
self.water_z_speed = stream.read_float()
self.water_unknown2 = stream.read_float()
self.water_amplitude = stream.read_float()
self.water_vertex_density = stream.read_float()
self.water_texture_density = stream.read_float()
self.water_color = [
stream.read_float(),
stream.read_float(),
stream.read_float(),
stream.read_float(),
]
self.water_reflectivity = stream.read_float()
self.water_eye_factor = stream.read_float()
def save_binary(self, stream: ResStream):
stream.write_qword(self.water_texture)
stream.write_float(self.water_unknown1[0])
stream.write_float(self.water_unknown1[1])
stream.write_float(self.water_unknown1[2])
stream.write_float(self.water_unknown1[3])
stream.write_float(self.water_x_wave_length)
stream.write_float(self.water_z_wave_length)
stream.write_float(self.water_x_speed)
stream.write_float(self.water_z_speed)
stream.write_float(self.water_unknown2)
stream.write_float(self.water_amplitude)
stream.write_float(self.water_vertex_density)
stream.write_float(self.water_texture_density)
stream.write_float(self.water_color[0])
stream.write_float(self.water_color[1])
stream.write_float(self.water_color[2])
stream.write_float(self.water_color[3])
stream.write_float(self.water_reflectivity)
stream.write_float(self.water_eye_factor)
def save_json(self):
data = OrderedDict()
data['water_texture'] = self.water_texture
data['water_unknown1'] = self.water_unknown1
data['water_x_wave_length'] = self.water_x_wave_length
data['water_z_wave_length'] = self.water_z_wave_length
data['water_x_speed'] = self.water_x_speed
data['water_z_speed'] = self.water_z_speed
data['water_unknown2'] = self.water_unknown2
data['water_amplitude'] = self.water_amplitude
data['water_vertex_density'] = self.water_vertex_density
data['water_texture_density'] = self.water_texture_density
data['water_color'] = self.water_color
data['water_reflectivity'] = self.water_reflectivity
data['water_eye_factor'] = self.water_eye_factor
return data
def load_json(self, data):
self.water_texture = data['water_texture']
self.water_unknown1 = data['water_unknown1']
self.water_x_wave_length = data['water_x_wave_length']
self.water_z_wave_length = data['water_z_wave_length']
self.water_x_speed = data['water_x_speed']
self.water_z_speed = data['water_z_speed']
self.water_unknown2 = data['water_unknown2']
self.water_amplitude = data['water_amplitude']
self.water_vertex_density = data['water_vertex_density']
self.water_texture_density = data['water_texture_density']
self.water_color = data['water_color']
self.water_reflectivity = data['water_reflectivity']
self.water_eye_factor = data['water_eye_factor']
@@ -0,0 +1,52 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# 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 WeatherEventInfo:
def load_binary(self, stream: ResStream):
self.weather_event_effect_id = stream.read_dword()
self.weather_event_spawn_location = stream.read_tuple()
self.weather_event_min_duration = stream.read_float()
self.weather_event_duration_variant = stream.read_float()
self.weather_event_time_to_respawn = stream.read_float()
self.weather_event_init_height_off_ground = stream.read_float()
self.weather_event_local_top = stream.read_bool()
def save_binary(self, stream: ResStream):
stream.write_dword(self.weather_event_effect_id)
stream.write_tuple(self.weather_event_spawn_location)
stream.write_float(self.weather_event_min_duration)
stream.write_float(self.weather_event_duration_variant)
stream.write_float(self.weather_event_time_to_respawn)
stream.write_float(self.weather_event_init_height_off_ground)
stream.write_bool(self.weather_event_local_top)
def save_json(self):
data = OrderedDict()
data['weather_event_effect_id'] = hash_to_string(self.weather_event_effect_id)
data['weather_event_spawn_location'] = self.weather_event_spawn_location
data['weather_event_min_duration'] = self.weather_event_min_duration
data['weather_event_duration_variant'] = self.weather_event_duration_variant
data['weather_event_time_to_respawn'] = self.weather_event_time_to_respawn
data['weather_event_init_height_off_ground'] = self.weather_event_init_height_off_ground
data['weather_event_local_top'] = self.weather_event_local_top
return data
def load_json(self, data):
self.weather_event_effect_id = string_to_hash(data['weather_event_effect_id'])
self.weather_event_spawn_location = data['weather_event_spawn_location']
self.weather_event_min_duration = data['weather_event_min_duration']
self.weather_event_duration_variant = data['weather_event_duration_variant']
self.weather_event_time_to_respawn = data['weather_event_time_to_respawn']
self.weather_event_init_height_off_ground = data['weather_event_init_height_off_ground']
self.weather_event_local_top = data['weather_event_local_top']
+9
View File
@@ -0,0 +1,9 @@
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from .ArcZone import ArcZone
@@ -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