You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
409 lines
20 KiB
409 lines
20 KiB
2 years ago
|
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||
|
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||
|
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||
|
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||
|
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||
|
# Magicbane Emulator Project © 2013 - 2022
|
||
|
# www.magicbane.com
|
||
2 years ago
|
|
||
|
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()
|
||
2 years ago
|
self.zone_unknown1 = stream.read_float()
|
||
2 years ago
|
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)
|
||
2 years ago
|
stream.write_float(self.zone_unknown1)
|
||
2 years ago
|
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
|
||
2 years ago
|
data['zone_unknown1'] = self.zone_unknown1
|
||
2 years ago
|
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']
|
||
2 years ago
|
self.zone_unknown1 = data['zone_unknown1']
|
||
2 years ago
|
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']
|