Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added patches/ips/remove_bluesuit.ips
Binary file not shown.
Binary file added patches/ips/remove_spikesuit.ips
Binary file not shown.
1 change: 1 addition & 0 deletions patches/rom_map/Bank 90.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ $F980 - $FA00: respin.asm
$FA00 - $FC00: map_progress_maintain.asm (list of cross-area tiles to reveal)
$FC00 - $FC10: Fake Lava.asm
$FC10 - $FC20: vanilla_bugfixes.asm
$FC20 - $FC40: remove_spikesuit.asm
15 changes: 15 additions & 0 deletions patches/src/remove_bluesuit.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
; Removes bluesuit ability

arch snes.cpu
lorom

; Patch "cancel speedboosting" routine to unconditionally zero out Samus' dash counter
; (compared to vanilla game, which only does this if Samus was running).
org $91DE59 ; replace branch check of samus running momentum flag
STZ $0B3E ; zero out Samus' dash counter first
LDA $0B3C ; then check Samus running flag
BEQ merge
STZ $0B3C

org $91DE8D
merge:
30 changes: 30 additions & 0 deletions patches/src/remove_spikesuit.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
; Removes a spikesuit state from samus

arch snes.cpu
lorom

!bank_90_free_space_start = $90FC20
!bank_90_free_space_end = $90FC40

org $90D4B9 ; hook end of shinespark crash
jsl check_ss
nop
nop

org !bank_90_free_space_start
check_ss:
LDA $0ACC ; Samus palette type normal? [regular shinecharge]
BNE .skip
LDA $0A68 ; special timer non zero? [can spark]
BEQ .skip
STZ $0A68 ; goodbye spikesuit
LDA #$0019
JSL $8090CB ; play a sound effect
.skip:

; Run hi-jacked instructions:
LDA #$0002
STA $0A32
RTL

assert pc() <= !bank_90_free_space_end
2 changes: 2 additions & 0 deletions rust/data/presets/full-settings/Community Race Season 4.json
Original file line number Diff line number Diff line change
Expand Up @@ -4564,6 +4564,8 @@
"map_station_reveal": "Full",
"energy_free_shinesparks": false,
"ultra_low_qol": false,
"disable_spikesuit": false,
"disable_bluesuit": false,
"race_mode": true,
"random_seed": null
},
Expand Down
2 changes: 2 additions & 0 deletions rust/data/presets/full-settings/Default.json
Original file line number Diff line number Diff line change
Expand Up @@ -4564,6 +4564,8 @@
"door_locks_size": "Large",
"map_station_reveal": "Full",
"energy_free_shinesparks": false,
"disable_spikesuit": false,
"disable_bluesuit": false,
"ultra_low_qol": false,
"race_mode": false,
"random_seed": null
Expand Down
3 changes: 3 additions & 0 deletions rust/maprando-game/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,13 @@ pub const TECH_ID_CAN_EXTENDED_MOONDANCE: TechId = 27;
pub const TECH_ID_CAN_ENEMY_STUCK_MOONFALL: TechId = 28;
pub const TECH_ID_CAN_SIDE_PLATFORM_CROSS_ROOM_JUMP: TechId = 197;
pub const TECH_ID_CAN_SPIKE_SUIT: TechId = 141;
pub const TECH_ID_CAN_SLOPE_SPARK: TechId = 210;
pub const TECH_ID_CAN_R_MODE_KNOCKBACK_SPARK: TechId = 213;
pub const TECH_ID_CAN_ELEVATOR_CRYSTAL_FLASH: TechId = 178;
pub const TECH_ID_CAN_CARRY_FLASH_SUIT: TechId = 207;
pub const TECH_ID_CAN_TRICKY_CARRY_FLASH_SUIT: TechId = 142;
pub const TECH_ID_CAN_HYPER_GATE_SHOT: TechId = 10001;
pub const TECH_ID_CAN_CARRY_BLUE_SUIT: TechId = 215;

#[allow(clippy::type_complexity)]
#[derive(Deserialize, Serialize, Clone, Debug)]
Expand Down
16 changes: 5 additions & 11 deletions rust/maprando-web/src/web/randomize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ fn handle_randomize_request(
settings: RandomizerSettings,
app_data: web::Data<AppData>,
) -> Result<AttemptOutput, AttemptError> {
let skill_settings = &settings.skill_assumption_settings;
let race_mode = settings.other_settings.race_mode;
let random_seed = if settings.other_settings.random_seed.is_none() || race_mode {
get_random_seed()
Expand All @@ -111,14 +110,6 @@ fn handle_randomize_request(
rng_seed[..8].copy_from_slice(&random_seed.to_le_bytes());
let mut rng = rand::rngs::StdRng::from_seed(rng_seed);

let implicit_tech = &app_data.preset_data.tech_by_difficulty["Implicit"];
let implicit_notables = &app_data.preset_data.notables_by_difficulty["Implicit"];
let difficulty = DifficultyConfig::new(
skill_settings,
&app_data.game_data,
implicit_tech,
implicit_notables,
);
let difficulty_tiers = get_difficulty_tiers(
&settings,
&app_data.preset_data.difficulty_tiers,
Expand All @@ -127,8 +118,11 @@ fn handle_randomize_request(
&app_data.preset_data.notables_by_difficulty["Implicit"],
);

let filtered_base_links =
filter_links(&app_data.game_data.links, &app_data.game_data, &difficulty);
let filtered_base_links = filter_links(
&app_data.game_data.links,
&app_data.game_data,
&difficulty_tiers[0],
);
let filtered_base_links_data = LinksDataGroup::new(
filtered_base_links,
app_data.game_data.vertex_isv.keys.len(),
Expand Down
24 changes: 24 additions & 0 deletions rust/maprando-web/templates/generate/game_variations.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,30 @@
<label class="btn btn-outline-primary" for="energyFreeShinesparksYes">Yes</label>
</div>
</div>
<div class="form-group row">
<div class="col-lg-4 col-md-6 my-2">
{% include "help/variations/disable_spikesuit.html" %}
<label for="disable_spike_suit">Disable spikesuits</label>
</div>
<div id="disableSpikesuit" class="col-2 btn-group my-2" role="group">
<input type="radio" class="btn-check" name="disable_spike_suit" id="disableSpikesuitNo" value="false" checked>
<label class="btn btn-outline-primary" for="disableSpikesuitNo">No</label>
<input type="radio" class="btn-check" name="disable_spike_suit" id="disableSpikesuitYes" value="true">
<label class="btn btn-outline-primary" for="disableSpikesuitYes">Yes</label>
</div>
</div>
<div class="form-group row">
<div class="col-lg-4 col-md-6 my-2">
{% include "help/variations/disable_bluesuit.html" %}
<label for="disable_blue_suit">Disable blue suits</label>
</div>
<div id="disableBluesuit" class="col-2 btn-group my-2" role="group">
<input type="radio" class="btn-check" name="disable_blue_suit" id="disableBlueSuitNo" value="false" checked>
<label class="btn btn-outline-primary" for="disableBlueSuitNo">No</label>
<input type="radio" class="btn-check" name="disable_blue_suit" id="disableBlueSuitYes" value="true">
<label class="btn btn-outline-primary" for="disableBlueSuitYes">Yes</label>
</div>
</div>
<div class="form-group row">
<div class="col-lg-4 col-md-6 my-2">
{% include "help/variations/ultra_low_qol.html" %}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!-- Button trigger modal -->
<button type="button" class="btn mr-1 px-2 py-1" data-bs-toggle="modal" data-bs-target="#disableBlueSuitModal">
<i class="bi bi-question-circle"></i>
</button>
<!-- Modal -->
<div class="modal" id="disableBlueSuitModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5">Disable blue suits</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>When this option is enabled, the game is modified so that Samus is not able to obtain a blue suit,
a glitched state in which Samus would remain permanently blue (e.g. after interrupting a shinespark with
a Crystal Flash, an R-mode standup, Draygon kill, or Baby Metroid hug).
Any logic that would require the use of a blue suit will also be disabled.
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!-- Button trigger modal -->
<button type="button" class="btn mr-1 px-2 py-1" data-bs-toggle="modal" data-bs-target="#disableSpikeSuitModal">
<i class="bi bi-question-circle"></i>
</button>
<!-- Modal -->
<div class="modal" id="disableSpikeSuitModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5">Disable spikesuits</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>When this option is enabled, the game will be modified so that Samus is no longer able to obtain a
flash suit via a glitched shinespark (by a spikesuit, slopespark, or R-mode knockback spark). Any
logic that would require the use of these techniques will also be disabled.
</p>
<p>A flash suit is a glitched state in which Samus is in a permanent state of shinecharge. A flash suit
may still be obtained by other methods, by interrupting a Crystal Flash using an elevator or
R-mode stand-up.
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
4 changes: 4 additions & 0 deletions rust/maprando-web/templates/generate/scripts.html
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@
"ultra_low_qol": formData.get("ultra_low_qol") == "true",
"race_mode": formData.get("race_mode") == "true",
"random_seed": tryParseInt(formData.get("random_seed")),
"disable_spikesuit": formData.get("disable_spike_suit") == "true",
"disable_bluesuit": formData.get("disable_blue_suit") == "true",
}
};
return settings;
Expand Down Expand Up @@ -545,6 +547,8 @@
applyRadioValue("mapStationReveal", other.map_station_reveal);
applyRadioValue("energyFreeShinesparks", other.energy_free_shinesparks);
applyRadioValue("ultraLowQoL", other.ultra_low_qol);
applyRadioValue("disableSpikesuit", other.disable_spikesuit);
applyRadioValue("disableBluesuit", other.disable_bluesuit);
applyRadioValue("raceMode", other.race_mode);
document.getElementById("randomSeed").value = other.random_seed;
}
Expand Down
8 changes: 8 additions & 0 deletions rust/maprando/src/patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,14 @@ impl Patcher<'_> {
patches.push("energy_free_shinesparks");
}

if self.settings.other_settings.disable_spikesuit {
patches.push("remove_spikesuit")
}

if self.settings.other_settings.disable_bluesuit {
patches.push("remove_bluesuit")
}

if self.settings.quality_of_life_settings.respin {
patches.push("respin");
// patches.push("spinjumprestart");
Expand Down
29 changes: 21 additions & 8 deletions rust/maprando/src/randomize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@ use maprando_game::{
GameData, GrappleJumpPosition, GrappleSwingBlock, HubLocation, Item, ItemId, ItemLocationId,
Link, LinksDataGroup, MainEntranceCondition, Map, NodeId, NotableId, Physics, Requirement,
RoomGeometryRoomIdx, RoomId, SidePlatformEntrance, SidePlatformEnvironment, SparkPosition,
StartLocation, TECH_ID_CAN_ARTIFICIAL_MORPH, TECH_ID_CAN_CARRY_FLASH_SUIT,
TECH_ID_CAN_DISABLE_EQUIPMENT, TECH_ID_CAN_ENTER_G_MODE, TECH_ID_CAN_ENTER_G_MODE_IMMOBILE,
TECH_ID_CAN_ENTER_R_MODE, TECH_ID_CAN_GRAPPLE_JUMP, TECH_ID_CAN_GRAPPLE_TELEPORT,
TECH_ID_CAN_HEATED_G_MODE, TECH_ID_CAN_HORIZONTAL_SHINESPARK, TECH_ID_CAN_MIDAIR_SHINESPARK,
TECH_ID_CAN_MOCKBALL, TECH_ID_CAN_MOONFALL, TECH_ID_CAN_PRECISE_GRAPPLE,
StartLocation, TECH_ID_CAN_ARTIFICIAL_MORPH, TECH_ID_CAN_CARRY_BLUE_SUIT,
TECH_ID_CAN_CARRY_FLASH_SUIT, TECH_ID_CAN_DISABLE_EQUIPMENT, TECH_ID_CAN_ENTER_G_MODE,
TECH_ID_CAN_ENTER_G_MODE_IMMOBILE, TECH_ID_CAN_ENTER_R_MODE, TECH_ID_CAN_GRAPPLE_JUMP,
TECH_ID_CAN_GRAPPLE_TELEPORT, TECH_ID_CAN_HEATED_G_MODE, TECH_ID_CAN_HORIZONTAL_SHINESPARK,
TECH_ID_CAN_MIDAIR_SHINESPARK, TECH_ID_CAN_MOCKBALL, TECH_ID_CAN_MOONFALL,
TECH_ID_CAN_PRECISE_GRAPPLE, TECH_ID_CAN_R_MODE_KNOCKBACK_SPARK,
TECH_ID_CAN_RIGHT_SIDE_DOOR_STUCK, TECH_ID_CAN_RIGHT_SIDE_DOOR_STUCK_FROM_WATER,
TECH_ID_CAN_SAMUS_EATER_TELEPORT, TECH_ID_CAN_SHINECHARGE_MOVEMENT,
TECH_ID_CAN_SIDE_PLATFORM_CROSS_ROOM_JUMP, TECH_ID_CAN_SPEEDBALL,
TECH_ID_CAN_SPRING_BALL_BOUNCE, TECH_ID_CAN_STATIONARY_SPIN_JUMP,
TECH_ID_CAN_SIDE_PLATFORM_CROSS_ROOM_JUMP, TECH_ID_CAN_SLOPE_SPARK, TECH_ID_CAN_SPEEDBALL,
TECH_ID_CAN_SPIKE_SUIT, TECH_ID_CAN_SPRING_BALL_BOUNCE, TECH_ID_CAN_STATIONARY_SPIN_JUMP,
TECH_ID_CAN_STUTTER_WATER_SHINECHARGE, TECH_ID_CAN_SUPER_SINK, TECH_ID_CAN_TEMPORARY_BLUE,
TECH_ID_CAN_TRICKY_CARRY_FLASH_SUIT, TechId, TemporaryBlueDirection, TraversalId, VertexId,
VertexKey,
Expand Down Expand Up @@ -3191,12 +3192,24 @@ pub fn get_difficulty_tiers(
implicit_tech: &[TechId],
implicit_notables: &[(RoomId, NotableId)],
) -> Vec<DifficultyConfig> {
let main_tier = DifficultyConfig::new(
let mut main_tier = DifficultyConfig::new(
&settings.skill_assumption_settings,
game_data,
implicit_tech,
implicit_notables,
);

if settings.other_settings.disable_spikesuit {
main_tier.tech[game_data.tech_isv.index_by_key[&TECH_ID_CAN_SPIKE_SUIT]] = false;
main_tier.tech[game_data.tech_isv.index_by_key[&TECH_ID_CAN_SLOPE_SPARK]] = false;
main_tier.tech[game_data.tech_isv.index_by_key[&TECH_ID_CAN_R_MODE_KNOCKBACK_SPARK]] =
false;
}

if settings.other_settings.disable_bluesuit {
main_tier.tech[game_data.tech_isv.index_by_key[&TECH_ID_CAN_CARRY_BLUE_SUIT]] = false;
}

let mut difficulty_tiers = vec![];

difficulty_tiers.push(main_tier.clone());
Expand Down
10 changes: 10 additions & 0 deletions rust/maprando/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ pub struct OtherSettings {
pub map_station_reveal: MapStationReveal,
pub energy_free_shinesparks: bool,
pub ultra_low_qol: bool,
pub disable_spikesuit: bool,
pub disable_bluesuit: bool,
pub race_mode: bool,
pub random_seed: Option<usize>,
}
Expand Down Expand Up @@ -909,6 +911,14 @@ fn upgrade_other_settings(settings: &mut serde_json::Value) -> Result<()> {
*area_assignment = serde_json::to_value(AreaAssignment::from_preset(preset))?;
}

if other_settings.get("disable_spikesuit").is_none() {
other_settings.insert("disable_spikesuit".to_string(), false.into());
}

if other_settings.get("disable_bluesuit").is_none() {
other_settings.insert("disable_bluesuit".to_string(), false.into());
}

Ok(())
}

Expand Down
2 changes: 2 additions & 0 deletions rust/maprando/tests/logic_scenarios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ fn get_settings(scenario: &Scenario) -> Result<RandomizerSettings> {
door_locks_size: maprando::settings::DoorLocksSize::Large,
map_station_reveal: maprando::settings::MapStationReveal::Full,
energy_free_shinesparks: false,
disable_bluesuit: false,
disable_spikesuit: false,
ultra_low_qol: false,
race_mode: false,
random_seed: None,
Expand Down