From 04b085d964f8f5f6d0e2d5066487df3d8d118c9a Mon Sep 17 00:00:00 2001 From: MrMiguel211 <60329473+MrMiguel211@users.noreply.github.com> Date: Mon, 27 May 2024 00:16:31 -0700 Subject: [PATCH] Add/Modify CameraWaypoints --- schema/randomprime.schema.json | 130 ++++++++++++++++------ src/add_modify_obj_patches.rs | 52 ++++++++- src/patch_config.rs | 17 ++- src/patches.rs | 11 ++ structs/src/scly_props/camera_waypoint.rs | 2 +- 5 files changed, 172 insertions(+), 40 deletions(-) diff --git a/schema/randomprime.schema.json b/schema/randomprime.schema.json index 6fb8958f..2e608bd4 100644 --- a/schema/randomprime.schema.json +++ b/schema/randomprime.schema.json @@ -4600,6 +4600,82 @@ "additionalProperties": false } }, + "playerActors": { + "description": "Add playerActors to this room. The animation used is the one of Samus riding an elevator. I was too lazy to add all the dependencies to the room, so the game may stutter substantially when loading a room with one of these.", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/addModifyId" + }, + "layer": { + "$ref": "#/$defs/addModifyLayer" + }, + "active": { + "description": "Default active state of the player actor.", + "type": "boolean", + "default": true + }, + "position": { + "description": "The position of the platform.", + "$ref": "#/$defs/vector3", + "default": [ + 0.0, + 0.0, + 0.0 + ] + }, + "rotation": { + "description": "The rotation of the platform.", + "$ref": "#/$defs/vector3", + "default": [ + 0.0, + 0.0, + 0.0 + ] + } + }, + "required": [ + "id" + ], + "additionalProperties": false + } + }, + "worldLightFaders": { + "description": "Add worldLightFaders to this room. These objects dim the room to the specified level when they receive the `ACTION` script message.", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/addModifyId" + }, + "layer": { + "$ref": "#/$defs/addModifyLayer" + }, + "active": { + "description": "Default active state of the worldLightFader.", + "type": "boolean", + "default": true + }, + "fadedLightLevel": { + "description": "Amount to scale light by where 1.0 is unchanged light level.", + "type": "number", + "exclusiveMinimum": 0.0 + }, + "fadeSpeed": { + "description": "Rate at which to execute the fade (higher is faster)", + "type": "number", + "exclusiveMinimum": 0.0 + } + }, + "required": [ + "id" + ], + "additionalProperties": false + } + }, "cameras": { "description": "Add cameras to this room. These are used for cutscenes.", "type": "array", @@ -4698,8 +4774,8 @@ "additionalProperties": false } }, - "playerActors": { - "description": "Add playerActors to this room. The animation used is the one of Samus riding an elevator. I was too lazy to add all the dependencies to the room, so the game may stutter substantially when loading a room with one of these.", + "cameraWaypoints": { + "description": "Add CameraWaypoints to this room, these are often used alongside camreas to indicate it's path and view via `CAMERA_PATH` and `CAMERA_TARGET` respectively.", "type": "array", "items": { "type": "object", @@ -4710,13 +4786,8 @@ "layer": { "$ref": "#/$defs/addModifyLayer" }, - "active": { - "description": "Default active state of the player actor.", - "type": "boolean", - "default": true - }, "position": { - "description": "The position of the platform.", + "description": "The position of the CameraWaypoint.", "$ref": "#/$defs/vector3", "default": [ 0.0, @@ -4725,47 +4796,32 @@ ] }, "rotation": { - "description": "The rotation of the platform.", + "description": "The rotation of the CameraWaypoint.", "$ref": "#/$defs/vector3", "default": [ 0.0, 0.0, 0.0 ] - } - }, - "required": [ - "id" - ], - "additionalProperties": false - } - }, - "worldLightFaders": { - "description": "Add worldLightFaders to this room. These objects dim the room to the specified level when they receive the `ACTION` script message.", - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "$ref": "#/$defs/addModifyId" - }, - "layer": { - "$ref": "#/$defs/addModifyLayer" }, "active": { - "description": "Default active state of the worldLightFader.", + "description": "Default active state of the CameraWaypoint.", "type": "boolean", - "default": true + "default": false }, - "fadedLightLevel": { - "description": "Amount to scale light by where 1.0 is unchanged light level.", + "fov": { + "description": "Used to specify the field of view of the camera if it's used as a `CAMERA_PATH`", "type": "number", - "exclusiveMinimum": 0.0 + "exclusiveMinimum": 0.0, + "exclusiveMaximum": 1000000.0, + "default:": 5.0 }, - "fadeSpeed": { - "description": "Rate at which to execute the fade (higher is faster)", - "type": "number", - "exclusiveMinimum": 0.0 + "unknown": { + "description": "Doesn't seem to do anything.", + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 2147483647 } }, "required": [ diff --git a/src/add_modify_obj_patches.rs b/src/add_modify_obj_patches.rs index 0f83543d..4d2cbd71 100644 --- a/src/add_modify_obj_patches.rs +++ b/src/add_modify_obj_patches.rs @@ -9,7 +9,7 @@ use crate::{ mlvl_wrapper, patch_config::{ ActorKeyFrameConfig, ActorRotateConfig, BlockConfig, BombSlotConfig, CameraConfig, - ControllerActionConfig, CounterConfig, DamageType, FogConfig, GenericTexture, + CameraWaypointConfig, ControllerActionConfig, CounterConfig, DamageType, FogConfig, GenericTexture, HudmemoConfig, LockOnPoint, PlatformConfig, PlatformType, PlayerActorConfig, PlayerHintConfig, RelayConfig, SpawnPointConfig, SpecialFunctionConfig, StreamedAudioConfig, SwitchConfig, TimerConfig, TriggerConfig, WaterConfig, WaypointConfig, @@ -1805,6 +1805,56 @@ pub fn patch_add_camera( ); } +pub fn patch_add_camera_waypoint( + _ps: &mut PatcherState, + area: &mut mlvl_wrapper::MlvlArea, + config: CameraWaypointConfig, +) -> Result<(), String> { + macro_rules! new { + () => { + structs::CameraWaypoint { + name: b"my camera waypoint\0".as_cstr(), + position: config.position.unwrap_or([0.0, 0.0, 0.0]).into(), + rotation: config.rotation.unwrap_or([0.0, 0.0, 0.0]).into(), + active: config.active.unwrap_or(true) as u8, + fov: config.fov.unwrap_or(70.0) as f32, + unknown: config.unknown.unwrap_or(0) as u32, + } + }; + } + + macro_rules! update { + ($obj:expr) => { + let property_data = $obj.property_data.as_camera_waypoint_mut().unwrap(); + + if let Some(position) = config.position { + property_data.position = position.into() + } + if let Some(rotation) = config.rotation { + property_data.rotation = rotation.into() + } + if let Some(active) = config.active { + property_data.active = active as u8 + } + if let Some(fov) = config.fov { + property_data.fov = fov as f32 + } + if let Some(unknown) = config.unknown { + property_data.unknown = unknown as u32 + } + }; + } + + add_edit_obj_helper!( + area, + Some(config.id), + config.layer, + CameraWaypoint, + new, + update + ); +} + pub fn patch_add_platform<'r>( _ps: &mut PatcherState, area: &mut mlvl_wrapper::MlvlArea<'r, '_, '_, '_>, diff --git a/src/patch_config.rs b/src/patch_config.rs index c9d2da7f..56513ff5 100644 --- a/src/patch_config.rs +++ b/src/patch_config.rs @@ -767,6 +767,18 @@ pub struct CameraConfig { pub disable_out_of_into: Option, } +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct CameraWaypointConfig { + pub id: u32, + pub layer: Option, + pub position: Option<[f32; 3]>, + pub rotation: Option<[f32; 3]>, + pub active: Option, + pub fov: Option, + pub unknown: Option, +} + #[allow(non_camel_case_types)] #[derive(Debug, Serialize, Deserialize, Copy, Clone, Eq, PartialEq)] #[repr(u32)] @@ -980,6 +992,7 @@ pub struct RoomConfig { pub player_actors: Option>, pub world_light_faders: Option>, pub cameras: Option>, + pub camera_waypoints: Option>, // Don't forget to update merge_json when adding here } @@ -1866,8 +1879,10 @@ impl PatchConfigPrivate { extend_option_vec!(distance_fogs, self_room_config, other_room_config); extend_option_vec!(bomb_slots, self_room_config, other_room_config); extend_option_vec!(controller_actions, self_room_config, other_room_config); - extend_option_vec!(cameras, self_room_config, other_room_config); extend_option_vec!(player_actors, self_room_config, other_room_config); + extend_option_vec!(world_light_faders, self_room_config, other_room_config); + extend_option_vec!(cameras, self_room_config, other_room_config); + extend_option_vec!(camera_waypoints, self_room_config, other_room_config); if let Some(other_layers) = &other_room_config.layers { if self_room_config.layers.is_none() { diff --git a/src/patches.rs b/src/patches.rs index 5b2aa48e..9289d872 100644 --- a/src/patches.rs +++ b/src/patches.rs @@ -16513,6 +16513,17 @@ fn build_and_run_patches<'r>( } } + if let Some(camera_waypoints) = room.camera_waypoints.as_ref() { + for config in camera_waypoints { + patcher.add_scly_patch( + (pak_name.as_bytes(), room_info.room_id.to_u32()), + move |ps, area| { + patch_add_camera_waypoint(ps, area, config.clone()) + }, + ); + } + } + if room.streamed_audios.is_some() { for config in room.streamed_audios.as_ref().unwrap() { patcher.add_scly_patch( diff --git a/structs/src/scly_props/camera_waypoint.rs b/structs/src/scly_props/camera_waypoint.rs index e260dce8..e41001a5 100644 --- a/structs/src/scly_props/camera_waypoint.rs +++ b/structs/src/scly_props/camera_waypoint.rs @@ -15,7 +15,7 @@ pub struct CameraWaypoint<'r> { pub rotation: GenericArray, pub active: u8, - pub h_fov: f32, + pub fov: f32, pub unknown: u32, }