From 110384ddaee55890653a59172442f9d5ff5db243 Mon Sep 17 00:00:00 2001 From: aquanight Date: Thu, 11 Jun 2026 20:13:55 -0600 Subject: [PATCH 1/5] Customizable Tank Sizes --- .../Community Race Season 5.json | 5 + rust/data/presets/full-settings/Default.json | 5 + .../full-settings/Mentor Tournament.json | 5 + .../Summer Series Expert Challenge.json | 5 + .../presets/item-progression/Challenge.json | 5 + .../presets/item-progression/Desolate.json | 5 + .../data/presets/item-progression/Normal.json | 5 + .../presets/item-progression/Technical.json | 5 + .../data/presets/item-progression/Tricky.json | 5 + rust/maprando-logic/src/lib.rs | 15 ++- .../templates/generate/item_progression.html | 5 + .../templates/generate/scripts.html | 71 +++++++++++--- rust/maprando/src/patch.rs | 95 ++++++++++++++++++- rust/maprando/src/randomize.rs | 84 +++++++++++----- rust/maprando/src/settings.rs | 21 +++- 15 files changed, 291 insertions(+), 45 deletions(-) diff --git a/rust/data/presets/full-settings/Community Race Season 5.json b/rust/data/presets/full-settings/Community Race Season 5.json index f38d1e186b..685246a338 100644 --- a/rust/data/presets/full-settings/Community Race Season 5.json +++ b/rust/data/presets/full-settings/Community Race Season 5.json @@ -4267,6 +4267,11 @@ "item_pool_preset": null, "stop_item_placement_early": false, "ammo_collect_fraction": 0.7, + "etank_size": 100, + "reserve_size": 100, + "missile_size": 5, + "super_size": 5, + "powerbomb_size": 5, "item_pool": [ { "item": "Missile", diff --git a/rust/data/presets/full-settings/Default.json b/rust/data/presets/full-settings/Default.json index 61233b9894..fd9d877451 100644 --- a/rust/data/presets/full-settings/Default.json +++ b/rust/data/presets/full-settings/Default.json @@ -4267,6 +4267,11 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 0.7, + "etank_size": 100, + "reserve_size": 100, + "missile_size": 5, + "super_size": 5, + "powerbomb_size": 5, "item_pool": [ { "item": "Missile", diff --git a/rust/data/presets/full-settings/Mentor Tournament.json b/rust/data/presets/full-settings/Mentor Tournament.json index ec23230088..1bb2a327d4 100644 --- a/rust/data/presets/full-settings/Mentor Tournament.json +++ b/rust/data/presets/full-settings/Mentor Tournament.json @@ -4267,6 +4267,11 @@ "item_pool_preset": null, "stop_item_placement_early": false, "ammo_collect_fraction": 0.7, + "etank_size": 100, + "reserve_size": 100, + "missile_size": 5, + "super_size": 5, + "powerbomb_size": 5, "item_pool": [ { "item": "Missile", diff --git a/rust/data/presets/full-settings/Summer Series Expert Challenge.json b/rust/data/presets/full-settings/Summer Series Expert Challenge.json index 83aec261e7..2b6c571a54 100644 --- a/rust/data/presets/full-settings/Summer Series Expert Challenge.json +++ b/rust/data/presets/full-settings/Summer Series Expert Challenge.json @@ -4267,6 +4267,11 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 1.0, + "etank_size": 100, + "reserve_size": 100, + "missile_size": 5, + "super_size": 5, + "powerbomb_size": 5, "item_pool": [ { "item": "Missile", diff --git a/rust/data/presets/item-progression/Challenge.json b/rust/data/presets/item-progression/Challenge.json index 9e2557aa51..a6aab3cecf 100644 --- a/rust/data/presets/item-progression/Challenge.json +++ b/rust/data/presets/item-progression/Challenge.json @@ -8,6 +8,11 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 1.0, + "etank_size": 100, + "reserve_size": 100, + "missile_size": 5, + "super_size": 5, + "powerbomb_size": 5, "item_pool": [ { "item": "Missile", diff --git a/rust/data/presets/item-progression/Desolate.json b/rust/data/presets/item-progression/Desolate.json index 9a9a72cc05..8d58f11181 100644 --- a/rust/data/presets/item-progression/Desolate.json +++ b/rust/data/presets/item-progression/Desolate.json @@ -8,6 +8,11 @@ "item_pool_preset": "Reduced", "stop_item_placement_early": true, "ammo_collect_fraction": 1.0, + "etank_size": 100, + "reserve_size": 100, + "missile_size": 5, + "super_size": 5, + "powerbomb_size": 5, "item_pool": [ { "item": "Missile", diff --git a/rust/data/presets/item-progression/Normal.json b/rust/data/presets/item-progression/Normal.json index dfbd74d43c..8cf8b97aad 100644 --- a/rust/data/presets/item-progression/Normal.json +++ b/rust/data/presets/item-progression/Normal.json @@ -8,6 +8,11 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 0.7, + "etank_size": 100, + "reserve_size": 100, + "missile_size": 5, + "super_size": 5, + "powerbomb_size": 5, "item_pool": [ { "item": "Missile", diff --git a/rust/data/presets/item-progression/Technical.json b/rust/data/presets/item-progression/Technical.json index a0b370c02a..1c7c98a5cd 100644 --- a/rust/data/presets/item-progression/Technical.json +++ b/rust/data/presets/item-progression/Technical.json @@ -8,6 +8,11 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 1.0, + "etank_size": 100, + "reserve_size": 100, + "missile_size": 5, + "super_size": 5, + "powerbomb_size": 5, "item_pool": [ { "item": "Missile", diff --git a/rust/data/presets/item-progression/Tricky.json b/rust/data/presets/item-progression/Tricky.json index bbc149cda9..d48096ea8b 100644 --- a/rust/data/presets/item-progression/Tricky.json +++ b/rust/data/presets/item-progression/Tricky.json @@ -8,6 +8,11 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 0.7, + "etank_size": 100, + "reserve_size": 100, + "missile_size": 5, + "super_size": 5, + "powerbomb_size": 5, "item_pool": [ { "item": "Missile", diff --git a/rust/maprando-logic/src/lib.rs b/rust/maprando-logic/src/lib.rs index 85a27ea35c..6f9a4001af 100644 --- a/rust/maprando-logic/src/lib.rs +++ b/rust/maprando-logic/src/lib.rs @@ -45,6 +45,11 @@ impl GlobalState { item: Item, game_data: &GameData, ammo_collect_fraction: f32, + missile_size: u16, + super_size: u16, + powerbomb_size: u16, + etank_size: u16, + reserve_size: u16, tech: &[bool], ) { self.inventory.items[item as usize] = true; @@ -54,7 +59,7 @@ impl GlobalState { let new_max_missiles = (ammo_collect_fraction * self.inventory.collectible_missile_packs as f32) .round() as Capacity - * 5; + * (missile_size as Capacity); self.inventory.max_missiles = new_max_missiles; } Item::Super => { @@ -62,7 +67,7 @@ impl GlobalState { let new_max_supers = (ammo_collect_fraction * self.inventory.collectible_super_packs as f32) .round() as Capacity - * 5; + * (super_size as Capacity); self.inventory.max_supers = new_max_supers; } Item::PowerBomb => { @@ -70,11 +75,11 @@ impl GlobalState { let new_max_power_bombs = (ammo_collect_fraction * self.inventory.collectible_power_bomb_packs as f32) .round() as Capacity - * 5; + * (powerbomb_size as Capacity); self.inventory.max_power_bombs = new_max_power_bombs; } Item::ETank => { - self.inventory.max_energy += 100; + self.inventory.max_energy += etank_size as Capacity; if !tech[game_data.manage_reserves_tech_idx] { self.inventory.max_reserves = Capacity::min(self.inventory.max_reserves, self.inventory.max_energy); @@ -82,7 +87,7 @@ impl GlobalState { } Item::ReserveTank => { self.inventory.collectible_reserve_tanks += 1; - self.inventory.max_reserves = self.inventory.collectible_reserve_tanks * 100; + self.inventory.max_reserves = self.inventory.collectible_reserve_tanks * reserve_size as Capacity; if !tech[game_data.manage_reserves_tech_idx] { self.inventory.max_reserves = Capacity::min(self.inventory.max_reserves, self.inventory.max_energy); diff --git a/rust/maprando-web/templates/generate/item_progression.html b/rust/maprando-web/templates/generate/item_progression.html index e0efc0c82d..76e2f954f3 100644 --- a/rust/maprando-web/templates/generate/item_progression.html +++ b/rust/maprando-web/templates/generate/item_progression.html @@ -197,6 +197,11 @@

+ +
+ +
{% endfor %} {% for item in item_names_single %} diff --git a/rust/maprando-web/templates/generate/scripts.html b/rust/maprando-web/templates/generate/scripts.html index d639626bd0..40c7deff57 100644 --- a/rust/maprando-web/templates/generate/scripts.html +++ b/rust/maprando-web/templates/generate/scripts.html @@ -272,6 +272,11 @@ "starting_items": buildStartingItems(), "key_item_priority": buildItemPriorities(), "filler_items": buildFillerItems(), + "etank_size": tryParseInt(formData.get("tank_size_ETank")), + "reserve_size": tryParseInt(formData.get("tank_size_ReserveTank")), + "missile_size": tryParseInt(formData.get("tank_size_Missile")), + "super_size": tryParseInt(formData.get("tank_size_Super")), + "powerbomb_size": tryParseInt(formData.get("tank_size_PowerBomb")), }, "quality_of_life_settings": { "preset": formData.get("quality_of_life_preset"), @@ -1134,13 +1139,20 @@ for (x of preset.item_pool) { let item = x.item; let cnt = x.count; - let el = document.getElementById(`itemPool${item}`); - if (el.classList.contains("item-pool-input-multiple")) { - el.value = cnt; - } else { - applyRadioValue(`itemPool${item}`, cnt > 0 ? "Yes" : "No"); - } + let el = document.getElementById(`itemPool${item}`); + if (el.classList.contains("item-pool-input-multiple")) { + el.value = cnt; + } else { + applyRadioValue(`itemPool${item}`, cnt > 0 ? "Yes" : "No"); + } } + + document.getElementById("tankSizeETank").value = preset.etank_size; + document.getElementById("tankSizeReserveTank").value = preset.reserve_size; + document.getElementById("tankSizeMissile").value = preset.missile_size; + document.getElementById("tankSizeSuper").value = preset.super_size; + document.getElementById("tankSizePowerBomb").value = preset.powerbomb_size; + processItemPoolPreset(); applyRadioValue("startingItemsPreset", preset.starting_items_preset); for (x of preset.starting_items) { @@ -1273,8 +1285,8 @@ } } function validateItemPool() { - if (parseInt(document.getElementById("itemPoolMissile").value) > 199) { - document.getElementById("itemPoolMissile").value = "199"; + if (parseInt(document.getElementById("itemPoolMissile").value) > 999) { + document.getElementById("itemPoolMissile").value = "999"; } if (parseInt(document.getElementById("itemPoolETank").value) > 14) { document.getElementById("itemPoolETank").value = "14"; @@ -1282,11 +1294,11 @@ if (parseInt(document.getElementById("itemPoolReserveTank").value) > 4) { document.getElementById("itemPoolReserveTank").value = "4"; } - if (parseInt(document.getElementById("itemPoolSuper").value) > 19) { - document.getElementById("itemPoolSuper").value = "19"; + if (parseInt(document.getElementById("itemPoolSuper").value) > 99) { + document.getElementById("itemPoolSuper").value = "99"; } - if (parseInt(document.getElementById("itemPoolPowerBomb").value) > 19) { - document.getElementById("itemPoolPowerBomb").value = "19"; + if (parseInt(document.getElementById("itemPoolPowerBomb").value) > 99) { + document.getElementById("itemPoolPowerBomb").value = "99"; } if (parseInt(document.getElementById("itemPoolMissile").value) < 0) { @@ -1304,6 +1316,41 @@ if (parseInt(document.getElementById("itemPoolPowerBomb").value) < 0) { document.getElementById("itemPoolPowerBomb").value = "0"; } + + let esz = tryParseInt(document.getElementById("tankSizeETank").value); + if (esz === null || isNaN(esz) || esz < 2) { + document.getElementById("tankSizeETank").value = "100"; + } + if (esz > 100 && (esz % 100) != 0) { + document.getElementById("tankSizeETank").value = Math.floor((esz / 100)) * 100; + } + if (esz > 1400) { + document.getElementById("tankSizeETank").value = "1400"; + } + if (parseInt(document.getElementById("tankSizeReserveTank").value) < 1) { + document.getElementById("tankSizeReserveTank").value = "100"; + } + if (parseInt(document.getElementById("tankSizeReserveTank").value) > 200) { + document.getElementById("tankSizeReserveTank").value = "200"; + } + if (parseInt(document.getElementById("tankSizeMissile").value) < 1) { + document.getElementById("tankSizeMissile").value = "5"; + } + if (parseInt(document.getElementById("tankSizeMissile").value) * parseInt(document.getElementById("itemPoolMissile").value) > 32000) { + document.getElementById("tankSizeMissile").value = "5"; + } + if (parseInt(document.getElementById("tankSizeMissile").value) > 99) { + document.getElementById("tankSizeMissile").value = "99"; + } + if (parseInt(document.getElementById("tankSizeSuper").value) < 1) { + document.getElementById("tankSizeSuper").value = "5"; + } + if (parseInt(document.getElementById("tankSizeSuper").value) > 99) { + document.getElementById("tankSizeSuper").value = "99"; + } + if (parseInt(document.getElementById("tankSizePowerBomb").value) < 1) { + document.getElementById("tankSizePowerBomb").value = "5"; + } } function itemPoolPresetChanged() { processItemPoolPreset(); diff --git a/rust/maprando/src/patch.rs b/rust/maprando/src/patch.rs index 7313defed3..affd87eb9b 100644 --- a/rust/maprando/src/patch.rs +++ b/rust/maprando/src/patch.rs @@ -766,6 +766,86 @@ impl Patcher<'_> { if let Some(escape_items) = escape_itembits { self.rom.write_u16(snes2pc(0xA9FB7B), escape_items)?; } + + if self.settings.item_progression_settings.etank_size != 100 { + let e_sz = self.settings.item_progression_settings.etank_size as isize; + + for addr in [ + 0x84E0B8, // PLM EED7 (E-Tank) + 0x84E474, // PLM EF2B (E-Tank, Chozo) + 0x84E93F, // PLM EF7F (E-Tank, Shot Block) + 0x88E717, // Credits, E-Tank Item % Divisor + ] { + self.rom.write_u16(snes2pc(addr), e_sz)?; + } + + if e_sz < 100 { + self.rom.write_u8(snes2pc(0x809B9F), e_sz)?; // HUD divisor for current energy -> full tanks + self.rom.write_u8(snes2pc(0x809BBC), e_sz)?; // HUD divisor for max energy -> tank count + + if self.settings.quality_of_life_settings.disableable_etanks != DisableETankSetting::Off { + for addr in [ + 0x83BBA8, // Disable E-Tank Patch: Disable tank check + 0x83BBB4, // Disable E-Tank Patch: Disable tank + 0x83BBE6 // Disable E-Tank Patch: Enable tank + ] { + self.rom.write_u16(snes2pc(addr), e_sz)?; + } + + for addr in [ + 0x83BB16, // Disable E-Tank Patch: divisor for e-tank calculations + 0x83BB2E // Disable E-Tank Patch: divisor for e-tank calculations + ] { + self.rom.write_u8(snes2pc(addr), e_sz)?; + } + } + } + } + + if self.settings.item_progression_settings.reserve_size != 100 { + let r_sz = self.settings.item_progression_settings.reserve_size; + + self.rom.write_u16(snes2pc(0x84E444), r_sz as isize)?; // PLM EF27 (Reserve Tank) + self.rom.write_u16(snes2pc(0x84E909), r_sz as isize)?; // PLM EF7B (Reserve Tank, Chozo) + self.rom.write_u16(snes2pc(0x84EE43), r_sz as isize)?; // PLM EFCF (Reserve Tank, Shot Block) + self.rom.write_u16(snes2pc(0x88E719), r_sz as isize)?; // Credits, Reserve Tank Item % Divisor + self.rom.write_u8(snes2pc(0x82B2C1), r_sz as isize)?; // Pause Menu: Reserve Tank Bars + self.rom.write_u8(snes2pc(0x82B2DC), r_sz as isize)?; // Pause Menu: Divisor for full reserve tanks + if r_sz > 7 { + self.rom.write_u8(snes2pc(0x82B320), (r_sz / 7) as isize)?; // Pause Menu: 1/7 reserve tank per pixel + } + else { + self.rom.write_u8(snes2pc(0x82B320), 1)?; // Pause Menu: 1 unit per pixel + } + } + + if self.settings.item_progression_settings.missile_size != 5 { + let m_sz = self.settings.item_progression_settings.missile_size as isize; + + self.rom.write_u16(snes2pc(0x84E0DD), m_sz)?; // PLM EEDB (Missile Tank) + self.rom.write_u16(snes2pc(0x84E4A6), m_sz)?; // PLM EF2F (Missile, Chozo) + self.rom.write_u16(snes2pc(0x84E977), m_sz)?; // PLM EF83 (Missile, Shot Block) + self.rom.write_u16(snes2pc(0x88E71B), m_sz)?; // Credits, Missile Item % Divisor + } + + if self.settings.item_progression_settings.super_size != 5 { + let s_sz = self.settings.item_progression_settings.super_size as isize; + + self.rom.write_u16(snes2pc(0x84E102), s_sz)?; // PLM EEDF (Super Tank) + self.rom.write_u16(snes2pc(0x84E4D8), s_sz)?; // PLM EF33 (Super, Chozo) + self.rom.write_u16(snes2pc(0x84E9AF), s_sz)?; // PLM EF87 (Super, Shot Block) + self.rom.write_u16(snes2pc(0x88E71D), s_sz)?; // Credits, Super Item % Divisor + + } + + if self.settings.item_progression_settings.powerbomb_size != 5 { + let p_sz = self.settings.item_progression_settings.powerbomb_size as isize; + + self.rom.write_u16(snes2pc(0x84E127), p_sz)?; // PLM EEE3 (PB Tank) + self.rom.write_u16(snes2pc(0x84E50A), p_sz)?; // PLM EF37 (PB, Chozo) + self.rom.write_u16(snes2pc(0x84E9E7), p_sz)?; // PLM EF8B (PB, Shot Block) + self.rom.write_u16(snes2pc(0x88E71F), p_sz)?; // Credits, Power Bomb Item % Divisor + } Ok(()) } @@ -2243,10 +2323,15 @@ impl Patcher<'_> { let mut item_mask = 0; let mut beam_mask = 0; let mut starting_missiles = 0; - let mut starting_energy = 99; + let mut starting_energy = if self.settings.item_progression_settings.etank_size <= 100 { (self.settings.item_progression_settings.etank_size as isize) - 1 } else { 99 }; let mut starting_reserves = 0; let mut starting_supers = 0; let mut starting_powerbombs = 0; + + if starting_energy < 1 { + bail!("E-Tank size is too low".to_string()); + } + let item_bitmask_map: HashMap = vec![ (Item::Varia, 0x0001), (Item::SpringBall, 0x0002), @@ -2284,15 +2369,15 @@ impl Patcher<'_> { } else if beam_bitmask_map.contains_key(&x.item) { beam_mask |= beam_bitmask_map[&x.item]; } else if x.item == Item::Missile { - starting_missiles += (x.count as isize) * 5; + starting_missiles += (x.count as isize) * (self.settings.item_progression_settings.missile_size as isize); } else if x.item == Item::ETank { - starting_energy += (x.count as isize) * 100; + starting_energy += (x.count as isize) * (self.settings.item_progression_settings.etank_size as isize); } else if x.item == Item::ReserveTank { starting_reserves += (x.count as isize) * 100; } else if x.item == Item::Super { - starting_supers += (x.count as isize) * 5; + starting_supers += (x.count as isize) * (self.settings.item_progression_settings.super_size as isize); } else if x.item == Item::PowerBomb { - starting_powerbombs += (x.count as isize) * 5; + starting_powerbombs += (x.count as isize) * (self.settings.item_progression_settings.powerbomb_size as isize); } } let beam_equipped_mask = if beam_mask & 0x000C == 0x000C { diff --git a/rust/maprando/src/randomize.rs b/rust/maprando/src/randomize.rs index 6382d44b37..0bcf3b2c4d 100644 --- a/rust/maprando/src/randomize.rs +++ b/rust/maprando/src/randomize.rs @@ -3405,15 +3405,15 @@ pub fn filter_links( out } -fn get_minimal_tank_count(difficulty: &DifficultyConfig) -> usize { +fn get_minimal_energy(difficulty: &DifficultyConfig) -> Capacity { if difficulty.ridley_proficiency < 0.3 { - 12 + 1200 } else if difficulty.ridley_proficiency < 0.8 { - 9 + 900 } else if difficulty.ridley_proficiency < 0.9 { - 7 + 700 } else { - 3 + 300 } } @@ -3699,20 +3699,48 @@ impl<'r> Randomizer<'r> { } } - let mut minimal_tank_count = get_minimal_tank_count(&difficulty_tiers[0]); + let mut minimal_energy = get_minimal_energy(&difficulty_tiers[0]); for x in &starting_items { initial_items_remaining[x.item as usize] -= usize::min(x.count, initial_items_remaining[x.item as usize]); - if x.item == Item::ETank || x.item == Item::ReserveTank { - minimal_tank_count = minimal_tank_count.saturating_sub(x.count); + if x.item == Item::ETank { + minimal_energy = minimal_energy.saturating_sub((x.count * settings.item_progression_settings.etank_size as usize) as Capacity); + } + else if x.item == Item::ReserveTank { + minimal_energy = minimal_energy.saturating_sub((x.count * settings.item_progression_settings.reserve_size as usize) as Capacity); } } - - while initial_items_remaining[Item::ETank as usize] - + initial_items_remaining[Item::ReserveTank as usize] - < minimal_tank_count + + while ((initial_items_remaining[Item::ETank as usize] as u16 * settings.item_progression_settings.etank_size) as Capacity + + (initial_items_remaining[Item::ReserveTank as usize] as u16 * settings.item_progression_settings.reserve_size) as Capacity) + < minimal_energy { - initial_items_remaining[Item::ETank as usize] += 1; + if (initial_items_remaining[Item::ETank as usize] < 14) && ((initial_items_remaining[Item::ETank as usize] + 1) * settings.item_progression_settings.etank_size as usize <= 1400) { + initial_items_remaining[Item::ETank as usize] += 1; + } + else if initial_items_remaining[Item::ReserveTank as usize] < 4 { + initial_items_remaining[Item::ReserveTank as usize] += 1; + } + else { + panic!("Can't ensure enough energy!"); + } + } + + // Enforce HUD-based total resource limits t(1400 energy, 999 reserve, 999 missile, 99 super, 99 PB) + while initial_items_remaining[Item::ETank as usize] * settings.item_progression_settings.etank_size as usize > 1400 { + initial_items_remaining[Item::ETank as usize] -= 1; + } + while initial_items_remaining[Item::ReserveTank as usize] * settings.item_progression_settings.reserve_size as usize > 999 { + initial_items_remaining[Item::ReserveTank as usize] -= 1; + } + while initial_items_remaining[Item::Missile as usize] * settings.item_progression_settings.missile_size as usize > 999 { + initial_items_remaining[Item::Missile as usize] -= 1; + } + while initial_items_remaining[Item::Super as usize] * settings.item_progression_settings.super_size as usize > 99 { + initial_items_remaining[Item::Super as usize] -= 1; + } + while initial_items_remaining[Item::PowerBomb as usize] * settings.item_progression_settings.powerbomb_size as usize > 99 { + initial_items_remaining[Item::PowerBomb as usize] -= 1; } let target_initial_items = initial_items_remaining.clone(); @@ -3728,10 +3756,10 @@ impl<'r> Randomizer<'r> { .sum::() .saturating_sub(available_items) { - let tank_count = initial_items_remaining[Item::ETank as usize] - + initial_items_remaining[Item::ReserveTank as usize]; + let energy_left_to_place = ((initial_items_remaining[Item::ETank as usize] as u16 * settings.item_progression_settings.etank_size) as Capacity) + + ((initial_items_remaining[Item::ReserveTank as usize] as u16 * settings.item_progression_settings.reserve_size) as Capacity); let mut removal_options = ammo_shortage_weight.clone(); - if tank_count > minimal_tank_count { + if energy_left_to_place > minimal_energy { removal_options.extend(tank_shortage_weight.clone()); } let mut best_removal_item: Option = None; @@ -4400,6 +4428,11 @@ impl<'r> Randomizer<'r> { self.settings .item_progression_settings .ammo_collect_fraction, + self.settings.item_progression_settings.missile_size, + self.settings.item_progression_settings.super_size, + self.settings.item_progression_settings.powerbomb_size, + self.settings.item_progression_settings.etank_size, + self.settings.item_progression_settings.reserve_size, &self.difficulty_tiers[0].tech, ); } @@ -5248,11 +5281,13 @@ impl<'r> Randomizer<'r> { .iter() .map(|&x| x > 0) .collect(), - max_energy: (99 + collectible_etanks * 100) as Capacity, - max_reserves: (collectible_reserve_tanks * 100) as Capacity, - max_missiles: (acf * collectible_missile_packs as f32).round() as Capacity * 5, - max_supers: (acf * collectible_super_packs as f32).round() as Capacity * 5, - max_power_bombs: (acf * collectible_pb_packs as f32).round() as Capacity * 5, + max_energy: if self.settings.item_progression_settings.etank_size <= 100 { + (((1 + collectible_etanks) * (self.settings.item_progression_settings.etank_size as usize)) - 1) as Capacity + } else { (99 + collectible_etanks * (self.settings.item_progression_settings.etank_size as usize)) as Capacity }, + max_reserves: (collectible_reserve_tanks * (self.settings.item_progression_settings.reserve_size as usize)) as Capacity, + max_missiles: (acf * collectible_missile_packs as f32).round() as Capacity * (self.settings.item_progression_settings.missile_size as i16), + max_supers: (acf * collectible_super_packs as f32).round() as Capacity * (self.settings.item_progression_settings.super_size as i16), + max_power_bombs: (acf * collectible_pb_packs as f32).round() as Capacity * (self.settings.item_progression_settings.powerbomb_size as i16), collectible_missile_packs: collectible_missile_packs as Capacity, collectible_super_packs: collectible_super_packs as Capacity, collectible_power_bomb_packs: collectible_pb_packs as Capacity, @@ -5268,7 +5303,7 @@ impl<'r> Randomizer<'r> { let mut global = GlobalState { inventory: Inventory { items, - max_energy: 99, + max_energy: if self.settings.item_progression_settings.etank_size <= 100 { (self.settings.item_progression_settings.etank_size - 1) as Capacity } else { 99 }, max_reserves: 0, max_missiles: 0, max_supers: 0, @@ -5291,6 +5326,11 @@ impl<'r> Randomizer<'r> { self.settings .item_progression_settings .ammo_collect_fraction, + self.settings.item_progression_settings.missile_size, + self.settings.item_progression_settings.super_size, + self.settings.item_progression_settings.powerbomb_size, + self.settings.item_progression_settings.etank_size, + self.settings.item_progression_settings.reserve_size, &self.difficulty_tiers[0].tech, ); } diff --git a/rust/maprando/src/settings.rs b/rust/maprando/src/settings.rs index 4ad5502483..df122e770e 100644 --- a/rust/maprando/src/settings.rs +++ b/rust/maprando/src/settings.rs @@ -101,6 +101,11 @@ pub struct ItemProgressionSettings { pub starting_items: Vec, pub key_item_priority: Vec, pub filler_items: Vec, + pub etank_size: u16, + pub reserve_size: u16, + pub missile_size: u16, + pub super_size: u16, + pub powerbomb_size: u16 } #[repr(u8)] @@ -1051,7 +1056,21 @@ fn upgrade_item_progression_settings(settings: &mut serde_json::Value) -> Result if !item_progression_settings.contains_key("ammo_collect_fraction") { item_progression_settings.insert("ammo_collect_fraction".to_string(), (0.7).into()); } - + if !item_progression_settings.contains_key("etank_size") { + item_progression_settings.insert("etank_size".to_string(), (100).into()); + } + if !item_progression_settings.contains_key("reserve_size") { + item_progression_settings.insert("reserve_size".to_string(), (5).into()); + } + if !item_progression_settings.contains_key("missile_size") { + item_progression_settings.insert("missile_size".to_string(), (5).into()); + } + if !item_progression_settings.contains_key("super_size") { + item_progression_settings.insert("super_size".to_string(), (5).into()); + } + if !item_progression_settings.contains_key("powerbomb_size") { + item_progression_settings.insert("powerbomb_size".to_string(), (5).into()); + } Ok(()) } From 390eca14120490cdb70769017ad43b36e3f21d5d Mon Sep 17 00:00:00 2001 From: aquanight Date: Tue, 16 Jun 2026 19:21:20 -0600 Subject: [PATCH 2/5] Remove e-tank customization (for now) --- .../Community Race Season 5.json | 2 - rust/data/presets/full-settings/Default.json | 2 - .../full-settings/Mentor Tournament.json | 2 - .../Summer Series Expert Challenge.json | 2 - .../presets/item-progression/Challenge.json | 2 - .../presets/item-progression/Desolate.json | 2 - .../data/presets/item-progression/Normal.json | 2 - .../presets/item-progression/Technical.json | 2 - .../data/presets/item-progression/Tricky.json | 2 - rust/maprando-logic/src/lib.rs | 6 +- .../templates/generate/item_progression.html | 48 ++++++++++++++-- .../templates/generate/scripts.html | 20 ------- rust/maprando/src/patch.rs | 56 +------------------ rust/maprando/src/randomize.rs | 36 ++++-------- rust/maprando/src/settings.rs | 2 - 15 files changed, 59 insertions(+), 127 deletions(-) diff --git a/rust/data/presets/full-settings/Community Race Season 5.json b/rust/data/presets/full-settings/Community Race Season 5.json index 685246a338..9ee17d7595 100644 --- a/rust/data/presets/full-settings/Community Race Season 5.json +++ b/rust/data/presets/full-settings/Community Race Season 5.json @@ -4267,8 +4267,6 @@ "item_pool_preset": null, "stop_item_placement_early": false, "ammo_collect_fraction": 0.7, - "etank_size": 100, - "reserve_size": 100, "missile_size": 5, "super_size": 5, "powerbomb_size": 5, diff --git a/rust/data/presets/full-settings/Default.json b/rust/data/presets/full-settings/Default.json index fd9d877451..6e5dc59501 100644 --- a/rust/data/presets/full-settings/Default.json +++ b/rust/data/presets/full-settings/Default.json @@ -4267,8 +4267,6 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 0.7, - "etank_size": 100, - "reserve_size": 100, "missile_size": 5, "super_size": 5, "powerbomb_size": 5, diff --git a/rust/data/presets/full-settings/Mentor Tournament.json b/rust/data/presets/full-settings/Mentor Tournament.json index 1bb2a327d4..b8c4f61a8f 100644 --- a/rust/data/presets/full-settings/Mentor Tournament.json +++ b/rust/data/presets/full-settings/Mentor Tournament.json @@ -4267,8 +4267,6 @@ "item_pool_preset": null, "stop_item_placement_early": false, "ammo_collect_fraction": 0.7, - "etank_size": 100, - "reserve_size": 100, "missile_size": 5, "super_size": 5, "powerbomb_size": 5, diff --git a/rust/data/presets/full-settings/Summer Series Expert Challenge.json b/rust/data/presets/full-settings/Summer Series Expert Challenge.json index 2b6c571a54..c4d912b3d0 100644 --- a/rust/data/presets/full-settings/Summer Series Expert Challenge.json +++ b/rust/data/presets/full-settings/Summer Series Expert Challenge.json @@ -4267,8 +4267,6 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 1.0, - "etank_size": 100, - "reserve_size": 100, "missile_size": 5, "super_size": 5, "powerbomb_size": 5, diff --git a/rust/data/presets/item-progression/Challenge.json b/rust/data/presets/item-progression/Challenge.json index a6aab3cecf..176ad8ff92 100644 --- a/rust/data/presets/item-progression/Challenge.json +++ b/rust/data/presets/item-progression/Challenge.json @@ -8,8 +8,6 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 1.0, - "etank_size": 100, - "reserve_size": 100, "missile_size": 5, "super_size": 5, "powerbomb_size": 5, diff --git a/rust/data/presets/item-progression/Desolate.json b/rust/data/presets/item-progression/Desolate.json index 8d58f11181..6a7fdb90d0 100644 --- a/rust/data/presets/item-progression/Desolate.json +++ b/rust/data/presets/item-progression/Desolate.json @@ -8,8 +8,6 @@ "item_pool_preset": "Reduced", "stop_item_placement_early": true, "ammo_collect_fraction": 1.0, - "etank_size": 100, - "reserve_size": 100, "missile_size": 5, "super_size": 5, "powerbomb_size": 5, diff --git a/rust/data/presets/item-progression/Normal.json b/rust/data/presets/item-progression/Normal.json index 8cf8b97aad..f9b60ff2e7 100644 --- a/rust/data/presets/item-progression/Normal.json +++ b/rust/data/presets/item-progression/Normal.json @@ -8,8 +8,6 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 0.7, - "etank_size": 100, - "reserve_size": 100, "missile_size": 5, "super_size": 5, "powerbomb_size": 5, diff --git a/rust/data/presets/item-progression/Technical.json b/rust/data/presets/item-progression/Technical.json index 1c7c98a5cd..41aaabe6d2 100644 --- a/rust/data/presets/item-progression/Technical.json +++ b/rust/data/presets/item-progression/Technical.json @@ -8,8 +8,6 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 1.0, - "etank_size": 100, - "reserve_size": 100, "missile_size": 5, "super_size": 5, "powerbomb_size": 5, diff --git a/rust/data/presets/item-progression/Tricky.json b/rust/data/presets/item-progression/Tricky.json index d48096ea8b..e4d9961c7b 100644 --- a/rust/data/presets/item-progression/Tricky.json +++ b/rust/data/presets/item-progression/Tricky.json @@ -8,8 +8,6 @@ "item_pool_preset": "Full", "stop_item_placement_early": false, "ammo_collect_fraction": 0.7, - "etank_size": 100, - "reserve_size": 100, "missile_size": 5, "super_size": 5, "powerbomb_size": 5, diff --git a/rust/maprando-logic/src/lib.rs b/rust/maprando-logic/src/lib.rs index 6f9a4001af..c38417106b 100644 --- a/rust/maprando-logic/src/lib.rs +++ b/rust/maprando-logic/src/lib.rs @@ -48,8 +48,6 @@ impl GlobalState { missile_size: u16, super_size: u16, powerbomb_size: u16, - etank_size: u16, - reserve_size: u16, tech: &[bool], ) { self.inventory.items[item as usize] = true; @@ -79,7 +77,7 @@ impl GlobalState { self.inventory.max_power_bombs = new_max_power_bombs; } Item::ETank => { - self.inventory.max_energy += etank_size as Capacity; + self.inventory.max_energy += 100; if !tech[game_data.manage_reserves_tech_idx] { self.inventory.max_reserves = Capacity::min(self.inventory.max_reserves, self.inventory.max_energy); @@ -87,7 +85,7 @@ impl GlobalState { } Item::ReserveTank => { self.inventory.collectible_reserve_tanks += 1; - self.inventory.max_reserves = self.inventory.collectible_reserve_tanks * reserve_size as Capacity; + self.inventory.max_reserves = self.inventory.collectible_reserve_tanks * 100 as Capacity; if !tech[game_data.manage_reserves_tech_idx] { self.inventory.max_reserves = Capacity::min(self.inventory.max_reserves, self.inventory.max_energy); diff --git a/rust/maprando-web/templates/generate/item_progression.html b/rust/maprando-web/templates/generate/item_progression.html index 76e2f954f3..766d669578 100644 --- a/rust/maprando-web/templates/generate/item_progression.html +++ b/rust/maprando-web/templates/generate/item_progression.html @@ -137,6 +137,49 @@

Item Progression

id="ammoCollectFraction" value="0.7" min="0.5" max="1.0" step="0.1" onchange="itemProgressionChanged()"> + +
+
+ +
+
+
+

+ +

+
+
+
+ + +
+ +
+
+ +
+ + +
+ +
+
+ +
+ + +
+ +
+
+
+
+
@@ -197,11 +240,6 @@

- -
- -
{% endfor %} {% for item in item_names_single %} diff --git a/rust/maprando-web/templates/generate/scripts.html b/rust/maprando-web/templates/generate/scripts.html index 40c7deff57..c1e863eb35 100644 --- a/rust/maprando-web/templates/generate/scripts.html +++ b/rust/maprando-web/templates/generate/scripts.html @@ -272,8 +272,6 @@ "starting_items": buildStartingItems(), "key_item_priority": buildItemPriorities(), "filler_items": buildFillerItems(), - "etank_size": tryParseInt(formData.get("tank_size_ETank")), - "reserve_size": tryParseInt(formData.get("tank_size_ReserveTank")), "missile_size": tryParseInt(formData.get("tank_size_Missile")), "super_size": tryParseInt(formData.get("tank_size_Super")), "powerbomb_size": tryParseInt(formData.get("tank_size_PowerBomb")), @@ -1147,8 +1145,6 @@ } } - document.getElementById("tankSizeETank").value = preset.etank_size; - document.getElementById("tankSizeReserveTank").value = preset.reserve_size; document.getElementById("tankSizeMissile").value = preset.missile_size; document.getElementById("tankSizeSuper").value = preset.super_size; document.getElementById("tankSizePowerBomb").value = preset.powerbomb_size; @@ -1317,22 +1313,6 @@ document.getElementById("itemPoolPowerBomb").value = "0"; } - let esz = tryParseInt(document.getElementById("tankSizeETank").value); - if (esz === null || isNaN(esz) || esz < 2) { - document.getElementById("tankSizeETank").value = "100"; - } - if (esz > 100 && (esz % 100) != 0) { - document.getElementById("tankSizeETank").value = Math.floor((esz / 100)) * 100; - } - if (esz > 1400) { - document.getElementById("tankSizeETank").value = "1400"; - } - if (parseInt(document.getElementById("tankSizeReserveTank").value) < 1) { - document.getElementById("tankSizeReserveTank").value = "100"; - } - if (parseInt(document.getElementById("tankSizeReserveTank").value) > 200) { - document.getElementById("tankSizeReserveTank").value = "200"; - } if (parseInt(document.getElementById("tankSizeMissile").value) < 1) { document.getElementById("tankSizeMissile").value = "5"; } diff --git a/rust/maprando/src/patch.rs b/rust/maprando/src/patch.rs index affd87eb9b..5e1f10e478 100644 --- a/rust/maprando/src/patch.rs +++ b/rust/maprando/src/patch.rs @@ -767,58 +767,6 @@ impl Patcher<'_> { self.rom.write_u16(snes2pc(0xA9FB7B), escape_items)?; } - if self.settings.item_progression_settings.etank_size != 100 { - let e_sz = self.settings.item_progression_settings.etank_size as isize; - - for addr in [ - 0x84E0B8, // PLM EED7 (E-Tank) - 0x84E474, // PLM EF2B (E-Tank, Chozo) - 0x84E93F, // PLM EF7F (E-Tank, Shot Block) - 0x88E717, // Credits, E-Tank Item % Divisor - ] { - self.rom.write_u16(snes2pc(addr), e_sz)?; - } - - if e_sz < 100 { - self.rom.write_u8(snes2pc(0x809B9F), e_sz)?; // HUD divisor for current energy -> full tanks - self.rom.write_u8(snes2pc(0x809BBC), e_sz)?; // HUD divisor for max energy -> tank count - - if self.settings.quality_of_life_settings.disableable_etanks != DisableETankSetting::Off { - for addr in [ - 0x83BBA8, // Disable E-Tank Patch: Disable tank check - 0x83BBB4, // Disable E-Tank Patch: Disable tank - 0x83BBE6 // Disable E-Tank Patch: Enable tank - ] { - self.rom.write_u16(snes2pc(addr), e_sz)?; - } - - for addr in [ - 0x83BB16, // Disable E-Tank Patch: divisor for e-tank calculations - 0x83BB2E // Disable E-Tank Patch: divisor for e-tank calculations - ] { - self.rom.write_u8(snes2pc(addr), e_sz)?; - } - } - } - } - - if self.settings.item_progression_settings.reserve_size != 100 { - let r_sz = self.settings.item_progression_settings.reserve_size; - - self.rom.write_u16(snes2pc(0x84E444), r_sz as isize)?; // PLM EF27 (Reserve Tank) - self.rom.write_u16(snes2pc(0x84E909), r_sz as isize)?; // PLM EF7B (Reserve Tank, Chozo) - self.rom.write_u16(snes2pc(0x84EE43), r_sz as isize)?; // PLM EFCF (Reserve Tank, Shot Block) - self.rom.write_u16(snes2pc(0x88E719), r_sz as isize)?; // Credits, Reserve Tank Item % Divisor - self.rom.write_u8(snes2pc(0x82B2C1), r_sz as isize)?; // Pause Menu: Reserve Tank Bars - self.rom.write_u8(snes2pc(0x82B2DC), r_sz as isize)?; // Pause Menu: Divisor for full reserve tanks - if r_sz > 7 { - self.rom.write_u8(snes2pc(0x82B320), (r_sz / 7) as isize)?; // Pause Menu: 1/7 reserve tank per pixel - } - else { - self.rom.write_u8(snes2pc(0x82B320), 1)?; // Pause Menu: 1 unit per pixel - } - } - if self.settings.item_progression_settings.missile_size != 5 { let m_sz = self.settings.item_progression_settings.missile_size as isize; @@ -2323,7 +2271,7 @@ impl Patcher<'_> { let mut item_mask = 0; let mut beam_mask = 0; let mut starting_missiles = 0; - let mut starting_energy = if self.settings.item_progression_settings.etank_size <= 100 { (self.settings.item_progression_settings.etank_size as isize) - 1 } else { 99 }; + let mut starting_energy = 99; let mut starting_reserves = 0; let mut starting_supers = 0; let mut starting_powerbombs = 0; @@ -2371,7 +2319,7 @@ impl Patcher<'_> { } else if x.item == Item::Missile { starting_missiles += (x.count as isize) * (self.settings.item_progression_settings.missile_size as isize); } else if x.item == Item::ETank { - starting_energy += (x.count as isize) * (self.settings.item_progression_settings.etank_size as isize); + starting_energy += (x.count as isize) * 100; } else if x.item == Item::ReserveTank { starting_reserves += (x.count as isize) * 100; } else if x.item == Item::Super { diff --git a/rust/maprando/src/randomize.rs b/rust/maprando/src/randomize.rs index 0bcf3b2c4d..14e521a2bf 100644 --- a/rust/maprando/src/randomize.rs +++ b/rust/maprando/src/randomize.rs @@ -3704,18 +3704,18 @@ impl<'r> Randomizer<'r> { initial_items_remaining[x.item as usize] -= usize::min(x.count, initial_items_remaining[x.item as usize]); if x.item == Item::ETank { - minimal_energy = minimal_energy.saturating_sub((x.count * settings.item_progression_settings.etank_size as usize) as Capacity); + minimal_energy = minimal_energy.saturating_sub(100); } else if x.item == Item::ReserveTank { - minimal_energy = minimal_energy.saturating_sub((x.count * settings.item_progression_settings.reserve_size as usize) as Capacity); + minimal_energy = minimal_energy.saturating_sub(100); } } - while ((initial_items_remaining[Item::ETank as usize] as u16 * settings.item_progression_settings.etank_size) as Capacity - + (initial_items_remaining[Item::ReserveTank as usize] as u16 * settings.item_progression_settings.reserve_size) as Capacity) + while ((initial_items_remaining[Item::ETank as usize] * 100) as Capacity + + (initial_items_remaining[Item::ReserveTank as usize] * 100) as Capacity) < minimal_energy { - if (initial_items_remaining[Item::ETank as usize] < 14) && ((initial_items_remaining[Item::ETank as usize] + 1) * settings.item_progression_settings.etank_size as usize <= 1400) { + if (initial_items_remaining[Item::ETank as usize] < 14) && ((initial_items_remaining[Item::ETank as usize] + 1) * 100 <= 1400) { initial_items_remaining[Item::ETank as usize] += 1; } else if initial_items_remaining[Item::ReserveTank as usize] < 4 { @@ -3727,12 +3727,6 @@ impl<'r> Randomizer<'r> { } // Enforce HUD-based total resource limits t(1400 energy, 999 reserve, 999 missile, 99 super, 99 PB) - while initial_items_remaining[Item::ETank as usize] * settings.item_progression_settings.etank_size as usize > 1400 { - initial_items_remaining[Item::ETank as usize] -= 1; - } - while initial_items_remaining[Item::ReserveTank as usize] * settings.item_progression_settings.reserve_size as usize > 999 { - initial_items_remaining[Item::ReserveTank as usize] -= 1; - } while initial_items_remaining[Item::Missile as usize] * settings.item_progression_settings.missile_size as usize > 999 { initial_items_remaining[Item::Missile as usize] -= 1; } @@ -3756,8 +3750,8 @@ impl<'r> Randomizer<'r> { .sum::() .saturating_sub(available_items) { - let energy_left_to_place = ((initial_items_remaining[Item::ETank as usize] as u16 * settings.item_progression_settings.etank_size) as Capacity) - + ((initial_items_remaining[Item::ReserveTank as usize] as u16 * settings.item_progression_settings.reserve_size) as Capacity); + let energy_left_to_place = ((initial_items_remaining[Item::ETank as usize] * 100) as Capacity) + + ((initial_items_remaining[Item::ReserveTank as usize] * 100) as Capacity); let mut removal_options = ammo_shortage_weight.clone(); if energy_left_to_place > minimal_energy { removal_options.extend(tank_shortage_weight.clone()); @@ -4431,8 +4425,6 @@ impl<'r> Randomizer<'r> { self.settings.item_progression_settings.missile_size, self.settings.item_progression_settings.super_size, self.settings.item_progression_settings.powerbomb_size, - self.settings.item_progression_settings.etank_size, - self.settings.item_progression_settings.reserve_size, &self.difficulty_tiers[0].tech, ); } @@ -5273,18 +5265,16 @@ impl<'r> Randomizer<'r> { let collectible_missile_packs = self.initial_items_remaining[Item::Missile as usize]; let collectible_super_packs = self.initial_items_remaining[Item::Super as usize]; let collectible_pb_packs = self.initial_items_remaining[Item::PowerBomb as usize]; - let collectible_etanks = self.initial_items_remaining[Item::ETank as usize]; - let collectible_reserve_tanks = self.initial_items_remaining[Item::ReserveTank as usize]; + let collectible_etanks = self.initial_items_remaining[Item::ETank as usize] as u16; + let collectible_reserve_tanks = self.initial_items_remaining[Item::ReserveTank as usize] as u16; Inventory { items: self .initial_items_remaining .iter() .map(|&x| x > 0) .collect(), - max_energy: if self.settings.item_progression_settings.etank_size <= 100 { - (((1 + collectible_etanks) * (self.settings.item_progression_settings.etank_size as usize)) - 1) as Capacity - } else { (99 + collectible_etanks * (self.settings.item_progression_settings.etank_size as usize)) as Capacity }, - max_reserves: (collectible_reserve_tanks * (self.settings.item_progression_settings.reserve_size as usize)) as Capacity, + max_energy: (99 + collectible_etanks * 100) as Capacity, + max_reserves: (collectible_reserve_tanks * 100) as Capacity, max_missiles: (acf * collectible_missile_packs as f32).round() as Capacity * (self.settings.item_progression_settings.missile_size as i16), max_supers: (acf * collectible_super_packs as f32).round() as Capacity * (self.settings.item_progression_settings.super_size as i16), max_power_bombs: (acf * collectible_pb_packs as f32).round() as Capacity * (self.settings.item_progression_settings.powerbomb_size as i16), @@ -5303,7 +5293,7 @@ impl<'r> Randomizer<'r> { let mut global = GlobalState { inventory: Inventory { items, - max_energy: if self.settings.item_progression_settings.etank_size <= 100 { (self.settings.item_progression_settings.etank_size - 1) as Capacity } else { 99 }, + max_energy: 99, max_reserves: 0, max_missiles: 0, max_supers: 0, @@ -5329,8 +5319,6 @@ impl<'r> Randomizer<'r> { self.settings.item_progression_settings.missile_size, self.settings.item_progression_settings.super_size, self.settings.item_progression_settings.powerbomb_size, - self.settings.item_progression_settings.etank_size, - self.settings.item_progression_settings.reserve_size, &self.difficulty_tiers[0].tech, ); } diff --git a/rust/maprando/src/settings.rs b/rust/maprando/src/settings.rs index df122e770e..3142ed581a 100644 --- a/rust/maprando/src/settings.rs +++ b/rust/maprando/src/settings.rs @@ -101,8 +101,6 @@ pub struct ItemProgressionSettings { pub starting_items: Vec, pub key_item_priority: Vec, pub filler_items: Vec, - pub etank_size: u16, - pub reserve_size: u16, pub missile_size: u16, pub super_size: u16, pub powerbomb_size: u16 From e2b99134b4ee029f873e6d508a6bcb4a16be4662 Mon Sep 17 00:00:00 2001 From: aquanight Date: Tue, 16 Jun 2026 19:31:08 -0600 Subject: [PATCH 3/5] Clean up more e-tank debris --- rust/maprando-logic/src/lib.rs | 2 +- rust/maprando/src/randomize.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/maprando-logic/src/lib.rs b/rust/maprando-logic/src/lib.rs index c38417106b..ce11ea6a9b 100644 --- a/rust/maprando-logic/src/lib.rs +++ b/rust/maprando-logic/src/lib.rs @@ -85,7 +85,7 @@ impl GlobalState { } Item::ReserveTank => { self.inventory.collectible_reserve_tanks += 1; - self.inventory.max_reserves = self.inventory.collectible_reserve_tanks * 100 as Capacity; + self.inventory.max_reserves = self.inventory.collectible_reserve_tanks * 100; if !tech[game_data.manage_reserves_tech_idx] { self.inventory.max_reserves = Capacity::min(self.inventory.max_reserves, self.inventory.max_energy); diff --git a/rust/maprando/src/randomize.rs b/rust/maprando/src/randomize.rs index 14e521a2bf..b39f893c0a 100644 --- a/rust/maprando/src/randomize.rs +++ b/rust/maprando/src/randomize.rs @@ -5265,8 +5265,8 @@ impl<'r> Randomizer<'r> { let collectible_missile_packs = self.initial_items_remaining[Item::Missile as usize]; let collectible_super_packs = self.initial_items_remaining[Item::Super as usize]; let collectible_pb_packs = self.initial_items_remaining[Item::PowerBomb as usize]; - let collectible_etanks = self.initial_items_remaining[Item::ETank as usize] as u16; - let collectible_reserve_tanks = self.initial_items_remaining[Item::ReserveTank as usize] as u16; + let collectible_etanks = self.initial_items_remaining[Item::ETank as usize]; + let collectible_reserve_tanks = self.initial_items_remaining[Item::ReserveTank as usize]; Inventory { items: self .initial_items_remaining From 8ed6124f3e5237cfb9bd49d59b5b6ea2edd93876 Mon Sep 17 00:00:00 2001 From: aquanight Date: Wed, 17 Jun 2026 18:59:33 -0600 Subject: [PATCH 4/5] Make tank sizes visible to spoiler visualizer and seed details --- rust/maprando-web/src/randomize_helpers.rs | 6 ++++++ .../templates/seed/item_progression_details.html | 6 ++++++ rust/maprando/src/randomize.rs | 3 +++ rust/maprando/src/spoiler_log.rs | 12 +++++++++--- visualizer/script.js | 6 +++--- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/rust/maprando-web/src/randomize_helpers.rs b/rust/maprando-web/src/randomize_helpers.rs index 56dba4f545..35dcfe0c26 100644 --- a/rust/maprando-web/src/randomize_helpers.rs +++ b/rust/maprando-web/src/randomize_helpers.rs @@ -40,6 +40,9 @@ pub struct SeedHeaderTemplate<'a> { semi_filler_items: Vec, early_filler_items: Vec, item_placement_style: String, + missile_size: i32, + super_size: i32, + powerbomb_size: i32, difficulty: &'a DifficultyConfig, quality_of_life_preset: String, supers_double: bool, @@ -423,6 +426,9 @@ pub fn render_seed( .progression_rate ), random_tank: seed_data.settings.item_progression_settings.random_tank, + missile_size: seed_data.settings.item_progression_settings.missile_size as i32, + super_size: seed_data.settings.item_progression_settings.super_size as i32, + powerbomb_size: seed_data.settings.item_progression_settings.powerbomb_size as i32, filler_items: seed_data .settings .item_progression_settings diff --git a/rust/maprando-web/templates/seed/item_progression_details.html b/rust/maprando-web/templates/seed/item_progression_details.html index 6f29d4a9f8..eb8e2cea1e 100644 --- a/rust/maprando-web/templates/seed/item_progression_details.html +++ b/rust/maprando-web/templates/seed/item_progression_details.html @@ -26,6 +26,12 @@ {% endif %} +
+
Tank Sizes:
+
+ Missile {{+ missile_size }}, Super {{+ super_size }}, PowerBomb {{+ powerbomb_size }} +
+
Stop item placement early:
{% if settings.item_progression_settings.stop_item_placement_early %}Yes{% else %}No{% endif %}
diff --git a/rust/maprando/src/randomize.rs b/rust/maprando/src/randomize.rs index b39f893c0a..c1538e1213 100644 --- a/rust/maprando/src/randomize.rs +++ b/rust/maprando/src/randomize.rs @@ -5389,6 +5389,9 @@ impl<'r> Randomizer<'r> { x: StartLocation::default().x, y: StartLocation::default().y, }, + missile_size: self.settings.item_progression_settings.missile_size as i32, + super_size: self.settings.item_progression_settings.super_size as i32, + powerbomb_size: self.settings.item_progression_settings.powerbomb_size as i32, hub_location_name: String::new(), hub_obtain_route: vec![], hub_return_route: vec![], diff --git a/rust/maprando/src/spoiler_log.rs b/rust/maprando/src/spoiler_log.rs index 004b58cd4d..7f33db88c9 100644 --- a/rust/maprando/src/spoiler_log.rs +++ b/rust/maprando/src/spoiler_log.rs @@ -196,6 +196,9 @@ pub struct SpoilerTraversal { #[derive(Serialize, Deserialize)] pub struct SpoilerLog { pub item_priority: Vec, + pub missile_size: i32, + pub super_size: i32, + pub powerbomb_size: i32, pub summary: Vec, pub objectives: Vec, pub escape: SpoilerEscape, @@ -514,9 +517,9 @@ fn get_spoiler_start_state( max_missiles: global_state.inventory.max_missiles, max_supers: global_state.inventory.max_supers, max_power_bombs: global_state.inventory.max_power_bombs, - collectible_missiles: global_state.inventory.collectible_missile_packs * 5, - collectible_supers: global_state.inventory.collectible_super_packs * 5, - collectible_power_bombs: global_state.inventory.collectible_power_bomb_packs * 5, + collectible_missiles: global_state.inventory.collectible_missile_packs * randomizer.settings.item_progression_settings.missile_size as i16, + collectible_supers: global_state.inventory.collectible_super_packs * randomizer.settings.item_progression_settings.super_size as i16, + collectible_power_bombs: global_state.inventory.collectible_power_bomb_packs * randomizer.settings.item_progression_settings.powerbomb_size as i16, items, flags, } @@ -1321,6 +1324,9 @@ pub fn get_spoiler_log( .iter() .map(|x| format!("{x:?}")) .collect(), + missile_size: randomizer.settings.item_progression_settings.missile_size as i32, + super_size: randomizer.settings.item_progression_settings.super_size as i32, + powerbomb_size: randomizer.settings.item_progression_settings.powerbomb_size as i32, summary: spoiler_summaries, objectives: spoiler_objectives, start_location: SpoilerStartLocation { diff --git a/visualizer/script.js b/visualizer/script.js index f385247f94..04029e1343 100644 --- a/visualizer/script.js +++ b/visualizer/script.js @@ -505,9 +505,9 @@ fetch(`../spoiler.json`).then(c => c.json()).then(c => { let non_unique_counts = { "ETank": 1, "ReserveTank": 1, - "Missile": 5, - "PowerBomb": 5, - "Super": 5 + "Missile": c.missile_size, + "PowerBomb": c.powerbomb_size, + "Super": c.super_size }; let last = null; let added_item = false; From b9a0b17b6e2200f8a9f244373031e45863d172e7 Mon Sep 17 00:00:00 2001 From: aquanight Date: Wed, 17 Jun 2026 19:06:20 -0600 Subject: [PATCH 5/5] Format/testing cleanup --- rust/maprando/src/patch.rs | 22 +++++++------ rust/maprando/src/randomize.rs | 44 ++++++++++++++++---------- rust/maprando/src/settings.rs | 2 +- rust/maprando/src/spoiler_log.rs | 9 ++++-- rust/maprando/tests/logic_scenarios.rs | 3 ++ 5 files changed, 49 insertions(+), 31 deletions(-) diff --git a/rust/maprando/src/patch.rs b/rust/maprando/src/patch.rs index 5e1f10e478..c9999aa4b3 100644 --- a/rust/maprando/src/patch.rs +++ b/rust/maprando/src/patch.rs @@ -766,24 +766,23 @@ impl Patcher<'_> { if let Some(escape_items) = escape_itembits { self.rom.write_u16(snes2pc(0xA9FB7B), escape_items)?; } - + if self.settings.item_progression_settings.missile_size != 5 { let m_sz = self.settings.item_progression_settings.missile_size as isize; - + self.rom.write_u16(snes2pc(0x84E0DD), m_sz)?; // PLM EEDB (Missile Tank) self.rom.write_u16(snes2pc(0x84E4A6), m_sz)?; // PLM EF2F (Missile, Chozo) self.rom.write_u16(snes2pc(0x84E977), m_sz)?; // PLM EF83 (Missile, Shot Block) self.rom.write_u16(snes2pc(0x88E71B), m_sz)?; // Credits, Missile Item % Divisor } - + if self.settings.item_progression_settings.super_size != 5 { let s_sz = self.settings.item_progression_settings.super_size as isize; - + self.rom.write_u16(snes2pc(0x84E102), s_sz)?; // PLM EEDF (Super Tank) self.rom.write_u16(snes2pc(0x84E4D8), s_sz)?; // PLM EF33 (Super, Chozo) self.rom.write_u16(snes2pc(0x84E9AF), s_sz)?; // PLM EF87 (Super, Shot Block) self.rom.write_u16(snes2pc(0x88E71D), s_sz)?; // Credits, Super Item % Divisor - } if self.settings.item_progression_settings.powerbomb_size != 5 { @@ -2275,11 +2274,11 @@ impl Patcher<'_> { let mut starting_reserves = 0; let mut starting_supers = 0; let mut starting_powerbombs = 0; - + if starting_energy < 1 { bail!("E-Tank size is too low".to_string()); } - + let item_bitmask_map: HashMap = vec![ (Item::Varia, 0x0001), (Item::SpringBall, 0x0002), @@ -2317,15 +2316,18 @@ impl Patcher<'_> { } else if beam_bitmask_map.contains_key(&x.item) { beam_mask |= beam_bitmask_map[&x.item]; } else if x.item == Item::Missile { - starting_missiles += (x.count as isize) * (self.settings.item_progression_settings.missile_size as isize); + starting_missiles += (x.count as isize) + * (self.settings.item_progression_settings.missile_size as isize); } else if x.item == Item::ETank { starting_energy += (x.count as isize) * 100; } else if x.item == Item::ReserveTank { starting_reserves += (x.count as isize) * 100; } else if x.item == Item::Super { - starting_supers += (x.count as isize) * (self.settings.item_progression_settings.super_size as isize); + starting_supers += (x.count as isize) + * (self.settings.item_progression_settings.super_size as isize); } else if x.item == Item::PowerBomb { - starting_powerbombs += (x.count as isize) * (self.settings.item_progression_settings.powerbomb_size as isize); + starting_powerbombs += (x.count as isize) + * (self.settings.item_progression_settings.powerbomb_size as isize); } } let beam_equipped_mask = if beam_mask & 0x000C == 0x000C { diff --git a/rust/maprando/src/randomize.rs b/rust/maprando/src/randomize.rs index c1538e1213..4604b732fe 100644 --- a/rust/maprando/src/randomize.rs +++ b/rust/maprando/src/randomize.rs @@ -3703,37 +3703,43 @@ impl<'r> Randomizer<'r> { for x in &starting_items { initial_items_remaining[x.item as usize] -= usize::min(x.count, initial_items_remaining[x.item as usize]); - if x.item == Item::ETank { - minimal_energy = minimal_energy.saturating_sub(100); - } - else if x.item == Item::ReserveTank { + if x.item == Item::ETank || x.item == Item::ReserveTank { minimal_energy = minimal_energy.saturating_sub(100); } } - + while ((initial_items_remaining[Item::ETank as usize] * 100) as Capacity + (initial_items_remaining[Item::ReserveTank as usize] * 100) as Capacity) < minimal_energy { - if (initial_items_remaining[Item::ETank as usize] < 14) && ((initial_items_remaining[Item::ETank as usize] + 1) * 100 <= 1400) { + if (initial_items_remaining[Item::ETank as usize] < 14) + && ((initial_items_remaining[Item::ETank as usize] + 1) * 100 <= 1400) + { initial_items_remaining[Item::ETank as usize] += 1; - } - else if initial_items_remaining[Item::ReserveTank as usize] < 4 { + } else if initial_items_remaining[Item::ReserveTank as usize] < 4 { initial_items_remaining[Item::ReserveTank as usize] += 1; - } - else { + } else { panic!("Can't ensure enough energy!"); } } // Enforce HUD-based total resource limits t(1400 energy, 999 reserve, 999 missile, 99 super, 99 PB) - while initial_items_remaining[Item::Missile as usize] * settings.item_progression_settings.missile_size as usize > 999 { + while initial_items_remaining[Item::Missile as usize] + * settings.item_progression_settings.missile_size as usize + > 999 + { initial_items_remaining[Item::Missile as usize] -= 1; } - while initial_items_remaining[Item::Super as usize] * settings.item_progression_settings.super_size as usize > 99 { + while initial_items_remaining[Item::Super as usize] + * settings.item_progression_settings.super_size as usize + > 99 + { initial_items_remaining[Item::Super as usize] -= 1; } - while initial_items_remaining[Item::PowerBomb as usize] * settings.item_progression_settings.powerbomb_size as usize > 99 { + while initial_items_remaining[Item::PowerBomb as usize] + * settings.item_progression_settings.powerbomb_size as usize + > 99 + { initial_items_remaining[Item::PowerBomb as usize] -= 1; } @@ -3750,7 +3756,8 @@ impl<'r> Randomizer<'r> { .sum::() .saturating_sub(available_items) { - let energy_left_to_place = ((initial_items_remaining[Item::ETank as usize] * 100) as Capacity) + let energy_left_to_place = ((initial_items_remaining[Item::ETank as usize] * 100) + as Capacity) + ((initial_items_remaining[Item::ReserveTank as usize] * 100) as Capacity); let mut removal_options = ammo_shortage_weight.clone(); if energy_left_to_place > minimal_energy { @@ -5275,9 +5282,12 @@ impl<'r> Randomizer<'r> { .collect(), max_energy: (99 + collectible_etanks * 100) as Capacity, max_reserves: (collectible_reserve_tanks * 100) as Capacity, - max_missiles: (acf * collectible_missile_packs as f32).round() as Capacity * (self.settings.item_progression_settings.missile_size as i16), - max_supers: (acf * collectible_super_packs as f32).round() as Capacity * (self.settings.item_progression_settings.super_size as i16), - max_power_bombs: (acf * collectible_pb_packs as f32).round() as Capacity * (self.settings.item_progression_settings.powerbomb_size as i16), + max_missiles: (acf * collectible_missile_packs as f32).round() as Capacity + * (self.settings.item_progression_settings.missile_size as i16), + max_supers: (acf * collectible_super_packs as f32).round() as Capacity + * (self.settings.item_progression_settings.super_size as i16), + max_power_bombs: (acf * collectible_pb_packs as f32).round() as Capacity + * (self.settings.item_progression_settings.powerbomb_size as i16), collectible_missile_packs: collectible_missile_packs as Capacity, collectible_super_packs: collectible_super_packs as Capacity, collectible_power_bomb_packs: collectible_pb_packs as Capacity, diff --git a/rust/maprando/src/settings.rs b/rust/maprando/src/settings.rs index 3142ed581a..eaf13b7fcf 100644 --- a/rust/maprando/src/settings.rs +++ b/rust/maprando/src/settings.rs @@ -103,7 +103,7 @@ pub struct ItemProgressionSettings { pub filler_items: Vec, pub missile_size: u16, pub super_size: u16, - pub powerbomb_size: u16 + pub powerbomb_size: u16, } #[repr(u8)] diff --git a/rust/maprando/src/spoiler_log.rs b/rust/maprando/src/spoiler_log.rs index 7f33db88c9..f5ed506ecb 100644 --- a/rust/maprando/src/spoiler_log.rs +++ b/rust/maprando/src/spoiler_log.rs @@ -517,9 +517,12 @@ fn get_spoiler_start_state( max_missiles: global_state.inventory.max_missiles, max_supers: global_state.inventory.max_supers, max_power_bombs: global_state.inventory.max_power_bombs, - collectible_missiles: global_state.inventory.collectible_missile_packs * randomizer.settings.item_progression_settings.missile_size as i16, - collectible_supers: global_state.inventory.collectible_super_packs * randomizer.settings.item_progression_settings.super_size as i16, - collectible_power_bombs: global_state.inventory.collectible_power_bomb_packs * randomizer.settings.item_progression_settings.powerbomb_size as i16, + collectible_missiles: global_state.inventory.collectible_missile_packs + * randomizer.settings.item_progression_settings.missile_size as i16, + collectible_supers: global_state.inventory.collectible_super_packs + * randomizer.settings.item_progression_settings.super_size as i16, + collectible_power_bombs: global_state.inventory.collectible_power_bomb_packs + * randomizer.settings.item_progression_settings.powerbomb_size as i16, items, flags, } diff --git a/rust/maprando/tests/logic_scenarios.rs b/rust/maprando/tests/logic_scenarios.rs index 9a5d5c9d9e..e999c42b12 100644 --- a/rust/maprando/tests/logic_scenarios.rs +++ b/rust/maprando/tests/logic_scenarios.rs @@ -200,6 +200,9 @@ fn get_settings(scenario: &Scenario) -> Result { progression_rate: maprando::settings::ProgressionRate::Fast, item_placement_style: maprando::settings::ItemPlacementStyle::Neutral, item_priority_strength: maprando::settings::ItemPriorityStrength::Moderate, + missile_size: 5, + super_size: 5, + powerbomb_size: 5, random_tank: true, spazer_before_plasma: true, item_pool_preset: None,