class_name RSWFormat ## Byte Length: 4 [br] ## GRAT var signature: String = "GRSW" ## Byte Type: u8 [br] ## Byte Length: 2 var version: Version ## Byte Type: u8, u32 [br] ## Byte Length: 1, 4 ## Versions: [2.2, 2.5] var build_number: int ## Byte Type: u8 [br] ## Byte Length: 1 ## Versions: [2.5] var unknown_render_flag: int ## Byte Type: u8 [br] ## Byte Length: 40 var ini_file: String ## Byte Type: u8 [br] ## Byte Length: 40 var gnd_file: String ## Byte Type: u8 [br] ## Byte Length: 40 var gat_file: String ## Byte Type: u8 [br] ## Byte Length: 40 ## Versions: [1.4] var source_file: String var water_configuration: WaterConfiguration var lighting_parameters: LightingParameters ## Byte Type: u32 [br] ## Byte Length: 4 var map_resource_count: int ## Length: [member map_resource_count] var map_resources: Array[MapResource] var quad_tree static func from_bytes(bytes: ByteStream) -> RSWFormat: var rsw_format = RSWFormat.new() bytes.advance(rsw_format.signature.length()) @warning_ignore("shadowed_variable") var version = Version.new() version.major = bytes.decode_u8() version.minor = bytes.decode_u8() rsw_format.version = version if version.major < 2: print(version) return rsw_format if version.major >= 2 and version.minor >= 5: rsw_format.build_number = bytes.decode_u32() rsw_format.unknown_render_flag = bytes.decode_u8() elif version.major >= 2 and version.minor >= 2: rsw_format.build_number = bytes.decode_u8() rsw_format.ini_file = bytes.get_string_from_utf8(40) rsw_format.gnd_file = bytes.get_string_from_utf8(40) rsw_format.gat_file = bytes.get_string_from_utf8(40) rsw_format.source_file = bytes.get_string_from_utf8(40) if version.major >= 2 and version.minor <= 5: rsw_format.water_configuration = WaterConfiguration.from_bytes(bytes) rsw_format.lighting_parameters = LightingParameters.from_bytes(bytes) bytes.advance(16) # map boundaries - bounding box # TODO rsw_format.map_resource_count = bytes.decode_u32() rsw_format.map_resources = [] as Array[MapResource] for _n in rsw_format.map_resource_count: var resource_type = bytes.decode_u32() var resource: MapResource if resource_type == MapResourceType.Animated3DModel: resource = Animated3DModel.from_bytes(bytes) elif resource_type == MapResourceType.DynamicLightSource: resource = DynamicLightSource.from_bytes(bytes) elif resource_type == MapResourceType.SpatialAudioSource: resource = SpatialAudioSource.from_bytes(bytes) elif resource_type == MapResourceType.ParticleEffectEmitter: resource = ParticleEffectEmitter.from_bytes(bytes) rsw_format.map_resources.append(resource) # TODO: quadtree #print(inst_to_dict(rsw_format)) return rsw_format class WaterConfiguration: ## Byte Type: f32 [br] ## Byte Length: 4 var water_level: int ## Byte Type: i32 [br] ## Byte Length: 4 var water_type: int ## Byte Type: f32 [br] ## Byte Length: 4 var wave_height: int ## Byte Type: f32 [br] ## Byte Length: 4 var wave_speed: int ## Byte Type: f32 [br] ## Byte Length: 4 var wave_pitch: int ## Byte Type: i32 [br] ## Byte Length: 4 var water_animation_speed: int static func from_bytes(bytes: ByteStream) -> WaterConfiguration: var config = WaterConfiguration.new() config.water_level = bytes.decode_float() config.water_type = bytes.decode_u32() config.wave_height = bytes.decode_float() config.wave_speed = bytes.decode_float() config.wave_pitch = bytes.decode_float() config.water_animation_speed = bytes.decode_u32() return config class LightingParameters: ## Byte Type: i32 [br] ## Byte Length: 4 var longitude: int ## Byte Type: i32 [br] ## Byte Length: 4 var latitude: int ## Byte Type: f32 [br] ## Byte Length: 4 var diffuse_color_r: int ## Byte Type: f32 [br] ## Byte Length: 4 var diffuse_color_g: int ## Byte Type: f32 [br] ## Byte Length: 4 var diffuse_color_b: int ## Byte Type: f32 [br] ## Byte Length: 4 var ambient_color_r: int ## Byte Type: f32 [br] ## Byte Length: 4 var ambient_color_g: int ## Byte Type: f32 [br] ## Byte Length: 4 var ambient_color_b: int ## Byte Type: f32 [br] ## Byte Length: 4 ## Shadow Map Alpha var intensity: int func get_diffuse_color() -> Color: return Color(diffuse_color_r, diffuse_color_g, diffuse_color_b) func get_ambient_color() -> Color: return Color(ambient_color_r, ambient_color_g, ambient_color_b) static func from_bytes(bytes: ByteStream) -> LightingParameters: var params = LightingParameters.new() params.longitude = bytes.decode_s32() params.latitude = bytes.decode_s32() params.diffuse_color_r = bytes.decode_float() params.diffuse_color_g = bytes.decode_float() params.diffuse_color_b = bytes.decode_float() params.ambient_color_r = bytes.decode_float() params.ambient_color_g = bytes.decode_float() params.ambient_color_b = bytes.decode_float() params.intensity = bytes.decode_float() return params class MapResource: pass enum MapResourceType { Animated3DModel = 1, DynamicLightSource = 2, SpatialAudioSource = 3, ParticleEffectEmitter = 4, } enum ModelAnimationType { None = 0, Looping = 2, } enum ParticlePresetEffect { None = -1, Hit_1 = 1, Hit_2 = 2, Hit_3 = 3, Torch = 47, TunaParty = 1097, } class Animated3DModel extends MapResource: ## Byte Type: u8 [br] ## Byte Length: 40 var name: String ## Byte Type: u32 [br] ## Byte Length: 4 var animation_type: ModelAnimationType ## Byte Type: f32 [br] ## Byte Length: 4 var animation_speed_percent: float ## Byte Type: u32 [br] ## Byte Length: 4 var collision_flags: int ## Byte Type: u8 [br] ## Byte Length: 80 var model_file: String ## Byte Type: u8 [br] ## Byte Length: 80 var root_node_name: String ## Byte Type: f32 [br] ## Byte Length: 4 var position_x: float ## Byte Type: f32 [br] ## Byte Length: 4 var position_y: float ## Byte Type: f32 [br] ## Byte Length: 4 var position_z: float ## Byte Type: f32 [br] ## Byte Length: 4 var rotation_x: float ## Byte Type: f32 [br] ## Byte Length: 4 var rotation_y: float ## Byte Type: f32 [br] ## Byte Length: 4 var rotation_z: float ## Byte Type: f32 [br] ## Byte Length: 4 var scale_x: float ## Byte Type: f32 [br] ## Byte Length: 4 var scale_y: float ## Byte Type: f32 [br] ## Byte Length: 4 var scale_z: float func get_position() -> Vector3: return Vector3(position_x, position_y, position_z) func get_rotation() -> Vector3: return Vector3(rotation_x, rotation_y, rotation_z) func get_scale() -> Vector3: return Vector3(scale_x, scale_y, scale_z) static func from_bytes(bytes: ByteStream) -> Animated3DModel: var resource = Animated3DModel.new() resource.name = bytes.get_string_from_ascii(40) resource.animation_type = bytes.decode_u32() resource.animation_speed_percent = bytes.decode_float() resource.collision_flags = bytes.decode_u32() resource.model_file = bytes.get_string_from_ascii(80) resource.root_node_name = bytes.get_string_from_utf8(80) resource.position_x = bytes.decode_float() resource.position_y = bytes.decode_float() resource.position_z = bytes.decode_float() resource.rotation_x = bytes.decode_float() resource.rotation_y = bytes.decode_float() resource.rotation_z = bytes.decode_float() resource.scale_x = bytes.decode_float() resource.scale_y = bytes.decode_float() resource.scale_z = bytes.decode_float() #print(inst_to_dict(resource)) return resource class DynamicLightSource extends MapResource: ## Byte Type: u8 [br] ## Byte Length: 80 var name: String ## Byte Type: f32 [br] ## Byte Length: 4 var position_x: float ## Byte Type: f32 [br] ## Byte Length: 4 var position_y: float ## Byte Type: f32 [br] ## Byte Length: 4 var position_z: float ## Byte Type: f32 [br] ## Byte Length: 4 var diffuse_color_r: float ## Byte Type: f32 [br] ## Byte Length: 4 var diffuse_color_g: float ## Byte Type: f32 [br] ## Byte Length: 4 var diffuse_color_b: float ## Byte Type: f32 [br] ## Byte Length: 4 var light_range: float func get_position() -> Vector3: return Vector3(position_x, position_y, position_z) func get_diffuse_color() -> Color: return Color(diffuse_color_r, diffuse_color_g, diffuse_color_b) static func from_bytes(bytes: ByteStream) -> DynamicLightSource: var resource = DynamicLightSource.new() resource.name = bytes.get_string_from_ascii(80) resource.position_x = bytes.decode_float() resource.position_y = bytes.decode_float() resource.position_z = bytes.decode_float() resource.diffuse_color_r = bytes.decode_float() resource.diffuse_color_g = bytes.decode_float() resource.diffuse_color_b = bytes.decode_float() resource.light_range = bytes.decode_float() #print(inst_to_dict(resource)) return resource class SpatialAudioSource extends MapResource: ## Byte Type: u8 [br] ## Byte Length: 80 var name: String ## Byte Type: u8 [br] ## Byte Length: 80 var audio_file: String ## Byte Type: f32 [br] ## Byte Length: 4 var position_x: float ## Byte Type: f32 [br] ## Byte Length: 4 var position_y: float ## Byte Type: f32 [br] ## Byte Length: 4 var position_z: float ## Byte Type: f32 [br] ## Byte Length: 4 var volume_gain: float ## Byte Type: u32 [br] ## Byte Length: 4 var width: int ## Byte Type: u32 [br] ## Byte Length: 4 var height: int ## Byte Type: f32 [br] ## Byte Length: 4 var audio_range: float ## Byte Type: f32 [br] ## Byte Length: 4 var duration: float func get_position() -> Vector3: return Vector3(position_x, position_y, position_z) func get_size() -> Vector2: return Vector2(width, height) static func from_bytes(bytes: ByteStream) -> SpatialAudioSource: var resource = SpatialAudioSource.new() resource.name = bytes.get_string_from_ascii(80) resource.audio_file = bytes.get_string_from_ascii(80) resource.position_x = bytes.decode_float() resource.position_y = bytes.decode_float() resource.position_z = bytes.decode_float() resource.volume_gain = bytes.decode_float() resource.width = bytes.decode_u32() resource.height = bytes.decode_u32() resource.audio_range = bytes.decode_float() resource.duration = bytes.decode_float() return resource class ParticleEffectEmitter extends MapResource: ## Byte Type: u8 [br] ## Byte Length: 80 var name: String ## Byte Type: f32 [br] ## Byte Length: 4 var position_x: float ## Byte Type: f32 [br] ## Byte Length: 4 var position_y: float ## Byte Type: f32 [br] ## Byte Length: 4 var position_z: float @warning_ignore("enum_variable_without_default") ## Byte Type: u32 [br] ## Byte Length: 4 var preset_effect: ParticlePresetEffect ## Byte Type: f32 [br] ## Byte Length: 4 [br] ## in frames; 60 means 1 second var emission_delay: float ## Byte Type: f32 [br] ## Byte Length: 4 var launch_parameter_a: float ## Byte Type: f32 [br] ## Byte Length: 4 var launch_parameter_b: float ## Byte Type: f32 [br] ## Byte Length: 4 var launch_parameter_c: float ## Byte Type: f32 [br] ## Byte Length: 4 var launch_parameter_d: float func get_position() -> Vector3: return Vector3(position_x, position_y, position_z) static func from_bytes(bytes: ByteStream) -> ParticleEffectEmitter: var resource = ParticleEffectEmitter.new() resource.name = bytes.get_string_from_ascii(80) resource.position_x = bytes.decode_float() resource.position_y = bytes.decode_float() resource.position_z = bytes.decode_float() resource.preset_effect = bytes.decode_u32() resource.emission_delay = bytes.decode_float() resource.launch_parameter_a = bytes.decode_float() resource.launch_parameter_b = bytes.decode_float() resource.launch_parameter_c = bytes.decode_float() resource.launch_parameter_d = bytes.decode_float() return resource