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.
408 lines
20 KiB
408 lines
20 KiB
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
|
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
|
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
|
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
|
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
|
# 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']
|
|
|