mbEditorPro2.0 release
This commit is contained in:
@@ -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']
|
||||
@@ -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'])
|
||||
@@ -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']
|
||||
@@ -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']
|
||||
@@ -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']
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user