From a8df16086d9744663bd727ef6a21d200d2ecca41 Mon Sep 17 00:00:00 2001 From: toasterparty Date: Mon, 26 Feb 2024 12:47:05 -0800 Subject: [PATCH] half-baked playerActors --- schema/randomprime.schema.json | 44 +++++++++++++- src/add_modify_obj_patches.rs | 101 +++++++++++++++++++++++++++++++++ src/custom_assets.rs | 2 + src/patch_config.rs | 14 ++++- src/patches.rs | 29 ++++++++-- 5 files changed, 184 insertions(+), 6 deletions(-) diff --git a/schema/randomprime.schema.json b/schema/randomprime.schema.json index a0e0cf3e..8a118cc8 100644 --- a/schema/randomprime.schema.json +++ b/schema/randomprime.schema.json @@ -4083,7 +4083,7 @@ "exclusiveMinimum": 0.0 }, "pause": { - "description": "Time in seconds which a following object will pause after it has `ARRIVED` at this waypoint before proceeding to the `NEXT`.", + "description": "Time in seconds which a following object will pause after it has `ARRIVED` at this waypoint before proceeding to the `NEXT`. Does not apply to platforms unfortunately.", "type": "number", "exclusiveMinimum": 0.0 }, @@ -4561,6 +4561,48 @@ ], "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 + } } }, "additionalProperties": false diff --git a/src/add_modify_obj_patches.rs b/src/add_modify_obj_patches.rs index 61e1210a..d14d242b 100644 --- a/src/add_modify_obj_patches.rs +++ b/src/add_modify_obj_patches.rs @@ -35,6 +35,7 @@ use crate::{ FogConfig, BombSlotConfig, ControllerActionConfig, + PlayerActorConfig, }, pickup_meta::PickupType, door_meta::DoorType, @@ -45,6 +46,7 @@ use resource_info_table::resource_info; use reader_writer::{ CStrConversionExtension, FourCC, + Reader, }; use structs::{res_id, ResId, SclyPropertyData}; @@ -1313,6 +1315,105 @@ pub fn patch_add_bomb_slot<'r>( Ok(()) } +fn player_actor_data<'r>() -> structs::PlayerActor<'r> +{ + let bytes: &'static [u8] = &[ + 0x00, 0x00, 0x00, 0x13, 0x50, 0x6C, 0x61, 0x79, + 0x65, 0x72, 0x41, 0x63, 0x74, 0x6F, 0x72, 0x20, + 0x2D, 0x20, 0x4C, 0x65, 0x61, 0x76, 0x69, 0x6E, + 0x67, 0x2D, 0x63, 0x6F, 0x6D, 0x70, 0x6F, 0x6E, + 0x65, 0x6E, 0x74, 0x00, 0x43, 0x33, 0xE1, 0x87, + 0xC4, 0x54, 0x93, 0xA5, 0x42, 0x83, 0x6B, 0x69, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x40, 0xA0, 0x00, 0x00, + 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x28, 0x9A, 0x4A, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, + 0x01, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0x80, 0x00, 0x00, 0x41, 0xA0, 0x00, + 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, + 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x01, 0x3F, 0x80, 0x00, 0x00, + 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x3F, 0x80, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + Reader::new(&bytes).read(()) +} + +pub fn patch_add_player_actor<'r>( + _ps: &mut PatcherState, + area: &mut mlvl_wrapper::MlvlArea<'r, '_, '_, '_>, + game_resources: &HashMap<(u32, FourCC), structs::Resource<'r>>, + config: PlayerActorConfig, +) + -> Result<(), String> +{ + let deps = vec![ + (0x836c33b3, b"ANCS"), + ]; + let deps_iter = deps.iter() + .map(|&(file_id, fourcc)| structs::Dependency { + asset_id: file_id, + asset_type: FourCC::from_bytes(fourcc), + } + ); + area.add_dependencies(game_resources, 0, deps_iter); + + let mut property_data = player_actor_data(); + property_data.active = config.active.unwrap_or(true) as u8; + property_data.position = config.position.unwrap_or([0.0, 0.0, 0.0]).into(); + property_data.rotation = config.rotation.unwrap_or([0.0, 0.0, 0.0]).into(); + + macro_rules! new { + () => { + property_data + }; + } + + macro_rules! update { + ($obj:expr) => { + let property_data = $obj.property_data.as_player_actor_mut().unwrap(); + if let Some(active ) = config.active {property_data.active = active as u8 } + if let Some(position ) = config.position {property_data.position = position.into() } + if let Some(rotation ) = config.rotation {property_data.rotation = rotation.into() } + }; + } + + add_edit_obj_helper!(area, config.id, config.layer, PlayerActor, new, update); +} + pub fn patch_add_controller_action<'r>( _ps: &mut PatcherState, area: &mut mlvl_wrapper::MlvlArea, diff --git a/src/custom_assets.rs b/src/custom_assets.rs index cdb0bc06..ad5454ba 100644 --- a/src/custom_assets.rs +++ b/src/custom_assets.rs @@ -1187,6 +1187,7 @@ pub fn collect_game_resources<'r>( (0x123A70A6, FourCC::from_bytes(b"TXTR")), (0xB3A153C0, FourCC::from_bytes(b"TXTR")), (0x57fe7e67, FourCC::from_bytes(b"AGSC")), // Misc.AGSC + (0x836c33b3, FourCC::from_bytes(b"ANCS")), ]; looking_for.extend(platform_deps); @@ -1272,6 +1273,7 @@ pub fn collect_game_resources<'r>( paks.push("AudioGrp.pak"); paks.push("NoARAM.pak"); paks.push("MiscData.pak"); + paks.push("TestAnim.Pak"); for pak_name in paks { let file_entry = gc_disc.find_file(pak_name).unwrap(); let pak = match *file_entry.file().unwrap() { diff --git a/src/patch_config.rs b/src/patch_config.rs index 769d2b36..87f8f675 100644 --- a/src/patch_config.rs +++ b/src/patch_config.rs @@ -501,7 +501,6 @@ pub struct SpecialFunctionConfig pub spinner3: Option, } - #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct ActorRotateConfig @@ -594,6 +593,17 @@ pub struct BombSlotConfig pub release_ball_delay_s: Option, } +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct PlayerActorConfig +{ + pub id: Option, + pub layer: Option, + pub active: Option, + pub position: Option<[f32; 3]>, + pub rotation: Option<[f32; 3]>, +} + #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct RepositionConfig @@ -984,6 +994,7 @@ pub struct RoomConfig pub distance_fogs: Option>, pub bomb_slots: Option>, pub controller_actions: Option>, + pub player_actors: Option>, // Don't forget to update merge_json when adding here } @@ -1822,6 +1833,7 @@ 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!(player_actors , 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 39ac8d58..b88e445f 100644 --- a/src/patches.rs +++ b/src/patches.rs @@ -2900,8 +2900,15 @@ fn is_water_related<'r>( } if obj.property_data.is_effect() { - let name = obj.property_data.as_effect().unwrap().name.to_str().ok().unwrap().to_string().to_lowercase(); - return name.contains("bubbles") || name.contains("waterfall"); + let effect = obj.property_data.as_effect().unwrap(); + let name = effect.name.to_str().ok().unwrap().to_string().to_lowercase(); + return name.contains("bubbles") || name.contains("waterfall") || vec![ + 0x5E2C7756, + 0xEEF504D4, + 0xC7CE1157, + 0x0640CE97, + 0x9FA2A896, + ].contains(&effect.part.to_u32()); } return false; @@ -15520,7 +15527,21 @@ fn build_and_run_patches<'r>(gc_disc: &mut structs::GcDisc<'r>, config: &PatchCo ); } } - + + if let Some(player_actors) = room.player_actors.as_ref() { + for config in player_actors { + patcher.add_scly_patch( + (pak_name.as_bytes(), room_info.room_id.to_u32()), + move |ps, area| patch_add_player_actor( + ps, + area, + game_resources, + config.clone(), + ), + ); + } + } + if let Some(controller_actions) = room.controller_actions.as_ref() { for config in controller_actions { patcher.add_scly_patch( @@ -15533,7 +15554,7 @@ fn build_and_run_patches<'r>(gc_disc: &mut structs::GcDisc<'r>, config: &PatchCo ); } } - + if room.streamed_audios.is_some() { for config in room.streamed_audios.as_ref().unwrap() { patcher.add_scly_patch(