From 6cb21da74d8826ab7575e4afe568cd829937186a Mon Sep 17 00:00:00 2001 From: Henrique Gemignani Passos Lima Date: Mon, 24 May 2021 20:55:11 +0300 Subject: [PATCH] Add item_max_capacity to config, allowing setting capacity of any item to any value --- src/patch_config.rs | 34 ++++++++++++-------------------- src/patches.rs | 33 ++++++++++++------------------- src/pickup_meta.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 41 deletions(-) diff --git a/src/patch_config.rs b/src/patch_config.rs index a0ab8821..28c64e0e 100644 --- a/src/patch_config.rs +++ b/src/patch_config.rs @@ -142,8 +142,7 @@ pub struct PatchConfig pub nonvaria_heat_damage: bool, pub heat_damage_per_sec: f32, pub staggered_suit_damage: bool, - pub missile_capacity: u32, - pub power_bomb_capacity: u32, + pub item_max_capacity: HashMap, pub map_default_state: MapState, pub auto_enabled_elevators: bool, pub quiet: bool, @@ -234,8 +233,7 @@ struct GameConfig item_loss_items: Option, etank_capacity: Option, - missile_capacity: Option, - power_bomb_capacity: Option, + item_max_capacity: Option>, game_banner: Option, comment: Option, @@ -316,14 +314,6 @@ impl PatchConfig .long("staggered-suit-damage") .help(concat!("The suit damage reduction is determinted by the number of suits ", "collected rather than the most powerful one collected."))) - .arg(Arg::with_name("missile capacity") - .long("missile-capacity") - .help("Set the max amount of Missiles you can carry") - .takes_value(true)) - .arg(Arg::with_name("power bomb capacity") - .long("power-bomb-capacity") - .help("Set the max amount of Power Bombs you can carry") - .takes_value(true)) .arg(Arg::with_name("map default state") .long("map-default-state") .help("Change the default state of map for each world (Either default, visible or visited)") @@ -440,13 +430,7 @@ impl PatchConfig if let Some(etank_capacity) = matches.value_of("etank capacity") { patch_config.game_config.etank_capacity = Some(etank_capacity.parse::().unwrap()); } - if let Some(s) = matches.value_of("missile capacity") { - patch_config.game_config.missile_capacity= Some(s.parse::().unwrap()); - } - if let Some(s) = matches.value_of("power bomb capacity") { - patch_config.game_config.power_bomb_capacity = Some(s.parse::().unwrap()); - } - + // custom if let Some(pickup_layout_str) = matches.value_of("pickup layout") { patch_config.layout = Some(LayoutWrapper::String(pickup_layout_str.to_string())); @@ -544,6 +528,15 @@ impl PatchConfigPrivate .map(|path| extract_flaahgra_music_files(path)) .transpose()?; + let item_max_capacity = match &self.game_config.item_max_capacity { + Some(max_capacity) => { + max_capacity.iter() + .map(|(name, capacity) | (PickupType::from_str(name), *capacity)) + .collect() + }, + None => HashMap::new(), + }; + Ok(PatchConfig { input_iso, iso_format, @@ -576,8 +569,7 @@ impl PatchConfigPrivate .unwrap_or_else(|| StartingItems::from_u64(1)), etank_capacity: self.game_config.etank_capacity.unwrap_or(100), - missile_capacity: self.game_config.missile_capacity.unwrap_or(999), - power_bomb_capacity: self.game_config.power_bomb_capacity.unwrap_or(8), + item_max_capacity: item_max_capacity, game_banner: self.game_config.game_banner.clone().unwrap_or_default(), comment: self.game_config.comment.clone().unwrap_or(String::new()), diff --git a/src/patches.rs b/src/patches.rs index 2932c238..6b72ee90 100644 --- a/src/patches.rs +++ b/src/patches.rs @@ -2437,26 +2437,18 @@ fn patch_dol<'r>( dol_patcher.ppcasm_patch(&staggered_suit_damage_patch)?; } - if config.missile_capacity > 999 { - Err("The max amount of missiles you can carry has exceeded the limit (>999)!".to_string())?; - } - - if config.power_bomb_capacity > 9 { - Err("The max amount of power bombs you can carry has exceeded the limit (>9)!".to_string())?; + for (pickup_type, value) in &config.item_max_capacity { + match pickup_type.item_type() { + Some(index) => { + let capacity_patch = ppcasm!(symbol_addr!("CPlayerState_PowerUpMaxValues", version) + index * 4, { + .long *value; + }); + dol_patcher.ppcasm_patch(&capacity_patch)?; + } + None => {} + } } - // CPlayerState_PowerUpMaxValues[4] - let missile_capacity_patch = ppcasm!(symbol_addr!("CPlayerState_PowerUpMaxValues", version) + 0x10, { - .long config.missile_capacity; - }); - dol_patcher.ppcasm_patch(&missile_capacity_patch)?; - - // CPlayerState_PowerUpMaxValues[7] - let power_bomb_capacity_patch = ppcasm!(symbol_addr!("CPlayerState_PowerUpMaxValues", version) + 0x1c, { - .long config.power_bomb_capacity; - }); - dol_patcher.ppcasm_patch(&power_bomb_capacity_patch)?; - // set etank capacity and base health let etank_capacity = config.etank_capacity as f32; let base_health = etank_capacity - 1.0; @@ -2643,8 +2635,9 @@ pub fn patch_iso(config: PatchConfig, mut pn: T) -> Result<(), String> writeln!(ct, "staggered suit damage: {}", config.staggered_suit_damage).unwrap(); writeln!(ct, "etank capacity: {}", config.etank_capacity).unwrap(); writeln!(ct, "map default state: {}", config.map_default_state.to_string().to_lowercase()).unwrap(); - writeln!(ct, "missile capacity: {}", config.missile_capacity).unwrap(); - writeln!(ct, "power bomb capacity: {}", config.power_bomb_capacity).unwrap(); + for (pickup_type, value) in &config.item_max_capacity { + writeln!(ct, "{} capacity: {}", pickup_type.name(), value).unwrap(); + } writeln!(ct, "{}", config.comment).unwrap(); let mut reader = Reader::new(&config.input_iso[..]); diff --git a/src/pickup_meta.rs b/src/pickup_meta.rs index a319747c..2699d829 100644 --- a/src/pickup_meta.rs +++ b/src/pickup_meta.rs @@ -217,6 +217,54 @@ impl PickupType &PickupTable::get()[*self] } + pub fn item_type(&self) -> Option + { + match self { + PickupType::PowerBeam => Some(0), + PickupType::IceBeam => Some(1), + PickupType::WaveBeam => Some(2), + PickupType::PlasmaBeam => Some(3), + PickupType::Missile => Some(4), + PickupType::ScanVisor => Some(5), + PickupType::MorphBallBomb => Some(6), + PickupType::PowerBomb => Some(7), + PickupType::Flamethrower => Some(8), + PickupType::ThermalVisor => Some(9), + PickupType::ChargeBeam => Some(10), + PickupType::SuperMissile => Some(11), + PickupType::GrappleBeam => Some(12), + PickupType::XRayVisor => Some(13), + PickupType::IceSpreader => Some(14), + PickupType::SpaceJumpBoots => Some(15), + PickupType::MorphBall => Some(16), + // PickupType::CombatVisor => Some(17), + PickupType::BoostBall => Some(18), + PickupType::SpiderBall => Some(19), + // PickupType::PowerSuit => Some(20), + PickupType::GravitySuit => Some(21), + PickupType::VariaSuit => Some(22), + PickupType::PhazonSuit => Some(23), + PickupType::EnergyTank => Some(24), + PickupType::UnknownItem1 => Some(25), + PickupType::HealthRefill => Some(26), + PickupType::UnknownItem2 => Some(27), + PickupType::Wavebuster => Some(28), + PickupType::ArtifactOfTruth => Some(29), + PickupType::ArtifactOfStrength => Some(30), + PickupType::ArtifactOfElder => Some(31), + PickupType::ArtifactOfWild => Some(32), + PickupType::ArtifactOfLifegiver => Some(33), + PickupType::ArtifactOfWarrior => Some(34), + PickupType::ArtifactOfChozo => Some(35), + PickupType::ArtifactOfNature => Some(36), + PickupType::ArtifactOfSun => Some(37), + PickupType::ArtifactOfWorld => Some(38), + PickupType::ArtifactOfSpirit => Some(39), + PickupType::ArtifactOfNewborn => Some(40), + _ => None, + } + } + pub fn iter() -> impl Iterator { [