Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for changing the final boss #454

Merged
merged 16 commits into from
Aug 10, 2024
6 changes: 5 additions & 1 deletion src/open_samus_returns_rando/files/custom/arachnus.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Game.ImportLibrary("actors/characters/arachnus/scripts/arachnus_original.lc")
function Arachnus.main()
Game.AddSF(0.0, "Arachnus.RotatePickup", "")
if Init.sFinalBoss == "Arachnus" then
Game.DeleteEntity("LE_PowerUp_Springball")
else
Game.AddSF(0.0, "Arachnus.RotatePickup", "")
end
end
function Arachnus.RotatePickup()
local springball = Game.GetEntity("LE_PowerUp_Springball")
Expand Down
28 changes: 28 additions & 0 deletions src/open_samus_returns_rando/files/custom/scenario.lua
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,34 @@ function Scenario.RandoOnElevatorUse(from_actor, _ARG_1_, _ARG_2_)
Elevator.Use("c10_samus", destination.scenario, destination.actor, _ARG_2_)
end

function Scenario.ShowFinalBossMessage()
if Init.sFinalBoss == "Ridley" then return end
local boss = Init.sFinalBoss
local startpoint = boss
if boss == "Diggernaut" then
startpoint = "ManicMiner"
elseif boss == "Queen" then
boss = "the Queen"
end
GUI.LaunchMessage("Not enough Metroid DNA!\nCollect more DNA to fight " .. boss .. "!", "RandomizerPowerup.Dummy", "")
if Init.sFinalBoss ~= "Queen" then
Game.AddSF(0, "Scenario.FinalBossReload", "s", startpoint)
end
end

function Scenario.FinalBossReload(startpoint)
Scenario.LoadNewScenario(Scenario.CurrentScenarioID, "ST_SG_" .. startpoint)
end

function Scenario.LaunchCredits()
Game.ShowEndGameCredits(true)
end

function Scenario.OnPostCreditsEnd()
Game.SaveGameComplete()
Game.GoToMainMenu()
end

Scenario.QueuedPopups = Scenario.QueuedPopups or Queue()

function Scenario.ShowIfNotActive()
Expand Down
7 changes: 7 additions & 0 deletions src/open_samus_returns_rando/files/levels/s000_surface.lua
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ function s000_surface.InitFromBlackboard()
Game.SetPlayerInputEnabled(false, false)
s000_surface.LaunchPlanetArrival()
end
if Game.GetEntity("LE_Item_Ridley") ~= nil then
if not Blackboard.GetProp("DEFEATED_ENEMIES", "Ridley") then
Game.DisableEntity("LE_Item_Ridley")
else
Game.EnableEntity("LE_Item_Ridley")
end
end
dyceron marked this conversation as resolved.
Show resolved Hide resolved
end
function s000_surface.OnReloaded()
end
Expand Down
10 changes: 10 additions & 0 deletions src/open_samus_returns_rando/files/levels/s020_area2.lua
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,17 @@ end
function s020_area2.OnExit()
end
function s020_area2.OnSubAreaChange(_ARG_0_, _ARG_1_, _ARG_2_, _ARG_3_, _ARG_4_)
if _ARG_2_ == "collision_camera_005" and Init.sFinalBoss == "Arachnus" and 0 < Scenario.ReadFromBlackboard("entity_SG_Arachnus_001_deaths", 0) then
if _ARG_0_ == "" then
Scenario.OnPostCreditsEnd()
else
Game.AddSF(0, "Scenario.LaunchCredits", "")
end
end
if _ARG_2_ == "collision_camera_006" then
if Init.sFinalBoss == "Arachnus" and not Blackboard.GetProp("GAME", "OBJECTIVE_COMPLETE") then
Game.AddSF(0.0, "Scenario.ShowFinalBossMessage", "")
end
Game.DelSF("s020_area2.CloseDoor004")
Game.AddSF(0.1, "s020_area2.CloseDoor004", "")
end
Expand Down
23 changes: 16 additions & 7 deletions src/open_samus_returns_rando/files/levels/s070_area7.lua
Original file line number Diff line number Diff line change
Expand Up @@ -800,20 +800,26 @@ function s070_area7.OnFansInit()
end
end
function s070_area7.OnSubAreaChange(_ARG_0_, _ARG_1_, _ARG_2_, _ARG_3_, _ARG_4_)
if _ARG_0_ == "" and _ARG_2_ == "collision_camera_043" and _ARG_3_ == "ManicMiner_Dead" and Game.GetEntity("SG_ManicMinerBot") ~= nil then
Game.GetEntity("SG_ManicMinerBot").SPAWNGROUP:EnableSpawnGroup()
if Game.GetEntityFromSpawnPoint("SP_ManicMinerBot") ~= nil then
Game.GetEntityFromSpawnPoint("SP_ManicMinerBot").ANIMATION.sDefaultSpawnAction = "deathloop"
Game.GetEntityFromSpawnPoint("SP_ManicMinerBot").ANIMATION:SetAction("deathloop", true)
Game.GetEntityFromSpawnPoint("SP_ManicMinerBot").AI:OnDeadCutsceneEnd()
if _ARG_0_ == "" and _ARG_2_ == "collision_camera_043" and _ARG_3_ == "ManicMiner_Dead" then
if Init.sFinalBoss == "Diggernaut" then
Scenario.OnPostCreditsEnd()
elseif Game.GetEntity("SG_ManicMinerBot") ~= nil then
Game.GetEntity("SG_ManicMinerBot").SPAWNGROUP:EnableSpawnGroup()
if Game.GetEntityFromSpawnPoint("SP_ManicMinerBot") ~= nil then
Game.GetEntityFromSpawnPoint("SP_ManicMinerBot").ANIMATION.sDefaultSpawnAction = "deathloop"
Game.GetEntityFromSpawnPoint("SP_ManicMinerBot").ANIMATION:SetAction("deathloop", true)
Game.GetEntityFromSpawnPoint("SP_ManicMinerBot").AI:OnDeadCutsceneEnd()
end
end
end
if _ARG_0_ == "collision_camera_041" and _ARG_2_ == "collision_camera_038" then
if not Scenario.ReadFromBlackboard("ManicMinerBotStealOrbPlayed", false) then
s070_area7.LaunchManicMinerBotStealOrb()
end
elseif _ARG_0_ == "collision_camera_034" and _ARG_2_ == "collision_camera_043" then
if not Scenario.ReadFromBlackboard("ManicMinerBotIntroCutscenePlayed", false) then
if Init.sFinalBoss == "Diggernaut" and not Blackboard.GetProp("GAME", "OBJECTIVE_COMPLETE") then
Game.AddSF(0, "Scenario.ShowFinalBossMessage", "")
elseif not Scenario.ReadFromBlackboard("ManicMinerBotIntroCutscenePlayed", false) then
Game.SetCameraEnemy("manicminerbot")
s070_area7.LaunchManicMinerBotIntroCutscene()
end
Expand Down Expand Up @@ -908,6 +914,9 @@ function s070_area7.OnStartManicMinerBotDeathCutscene()
end
end
function s070_area7.OnEndManicMinerBotDeathCutscene()
if Init.sFinalBoss == "Diggernaut" then
Scenario.LaunchCredits()
end
s070_area7.UpdateMinimapItemsphereIcon()
Game.RemoveEntityToUpdateInCutscene("LE_ManicMinerWall")
Game.RemoveEntityToUpdateInCutscene("LE_PowerUp_Powerbomb")
Expand Down
19 changes: 17 additions & 2 deletions src/open_samus_returns_rando/files/levels/s100_area10.lua
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ function s100_area10.InitFromBlackboard()
Scenario.WriteToBlackboard("firstTimeMetroidHatchlingIntroPlayed", "b", true)
Game.DisableEntity("LE_Baby_Hatchling")
Game.DisableTrigger("TG_MetroidRadar")
Game.GetEntity("LE_RandoDNA").USABLE:Activate(false)
if Init.sFinalBoss ~= "Queen" then
Game.GetEntity("LE_RandoDNA").USABLE:Activate(false)
end
s100_area10.SetLowModelsVisibility(false)
if Game.GetEntity("LE_ValveQueen") ~= nil then
if Blackboard.GetProp("DEFEATED_ENEMIES", "Metroid") ~= nil and s100_area10.iNumMetroids == Blackboard.GetProp("DEFEATED_ENEMIES", "Metroid") then
Expand Down Expand Up @@ -109,6 +111,11 @@ end
function s100_area10.OnEnter_ActivationTeleport_10_02()
Game.OnTeleportApproached("LE_Teleporter_10_02")
end
function s100_area10.OnEnter_Queen_Access()
if Init.sFinalBoss == "Queen" and not Blackboard.GetProp("GAME", "OBJECTIVE_COMPLETE") and Blackboard.GetProp("DEFEATED_ENEMIES", "Metroid") ~= nil and s100_area10.iNumMetroids == Blackboard.GetProp("DEFEATED_ENEMIES", "Metroid") then
Game.AddSF(0, "Scenario.ShowFinalBossMessage", "")
end
end
function s100_area10.OnLarva_001_Generated(_ARG_0_, _ARG_1_)
if _ARG_1_ ~= nil and _ARG_1_.AI ~= nil then
_ARG_1_.AI.bPlaceholder = false
Expand Down Expand Up @@ -291,10 +298,15 @@ function s100_area10.OnSubAreaChange(_ARG_0_, _ARG_1_, _ARG_2_, _ARG_3_, _ARG_4_
elseif _ARG_0_ == "collision_camera_020" then
Game.SetSafeFarPlaneFactor(s100_area10.fSafeFarPlaneFactor)
end
if _ARG_0_ == "" and _ARG_2_ == "collision_camera_020" and _ARG_3_ == "PostMetroids_001" then
Scenario.OnPostCreditsEnd()
end
if _ARG_0_ == "collision_camera_020" and _ARG_2_ == "collision_camera_022" then
s100_area10.OnBabyCreationCutsceneTrigger()
elseif _ARG_0_ == "collision_camera_019" and _ARG_2_ == "collision_camera_020" and Blackboard.GetProp("DEFEATED_ENEMIES", "Metroid") ~= nil and s100_area10.iNumMetroids == Blackboard.GetProp("DEFEATED_ENEMIES", "Metroid") then
s100_area10.LaunchQueenIntro()
if Init.sFinalBoss ~= "Queen" or Blackboard.GetProp("GAME", "OBJECTIVE_COMPLETE") then
s100_area10.LaunchQueenIntro()
end
end
Game.BossCheckPointManagerForceUnlockDoors()
Scenario.OnSubAreaChange(_ARG_0_, _ARG_1_, _ARG_2_, _ARG_3_, _ARG_4_)
Expand Down Expand Up @@ -386,6 +398,9 @@ function s100_area10.OnEndQueenDeathCutscene()
if Game.GetPlayer() ~= nil then
Game.GetPlayer().LIFE:SetInvulnerableWithReaction(false)
end
if Init.sFinalBoss == "Queen" then
Scenario.LaunchCredits()
end
Game.EnableTrigger("TG_BabyCreation")
Game.SetSceneGroupEnabledByName("sg_vignette_20", true)
Game.SetSceneGroupEnabledByName("sg_vignette_09", true)
Expand Down
22 changes: 19 additions & 3 deletions src/open_samus_returns_rando/files/levels/s110_surfaceb.lua
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ function s110_surfaceb.InitFromBlackboard()
s110_surfaceb.SetLowModelsVisibility(false)
if Game.GetItemAmount(Game.GetPlayerName(), "ITEM_ADN") < 39 and Game.GetItemAmount(Game.GetPlayerName(), "ITEM_BABY_HATCHLING") < 1 then
Game.PlayMusicStream(0, "streams/music/t_m2_surface_arr1.wav", -1, -1, -1, 2, 2, 1)
end
end
if Blackboard.GetProp("DEFEATED_ENEMIES", "Ridley") and Game.GetEntity("TG_Ridley_Access") ~= nil then
Game.DeleteEntity("TG_Ridley_Access")
end
end
function s110_surfaceb.OnReloaded()
end
Expand Down Expand Up @@ -99,6 +102,12 @@ end
function s110_surfaceb.OnEnter_ActivationTeleport_00b_01()
Game.OnTeleportApproached("LE_Teleporter_00b_01")
end
function s110_surfaceb.LoadSurface()
Scenario.LoadNewScenario("s000_surface", "ST_Surface_Connector")
end
function s110_surfaceb.OnEnter_Ridley_Access()
GUI.LaunchMessage("Proteus Ridley can be fought at any time.\nAre you prepared to fight?", "s110_surfaceb.OnReloaded", "s110_surfaceb.LoadSurface")
end
function s110_surfaceb.OnRidleyStartPoint()
Game.HUDIdleScreenLeave()
end
Expand Down Expand Up @@ -299,6 +308,11 @@ function s110_surfaceb.LaunchRidleyDeadCutscene()
GUI.ForceIdleCinematicControlledOn()
Game.LaunchCutscene("cutscenes/ridley4/takes/10/ridley410.bmscu")
s110_surfaceb.SetLowModelsVisibility(false)
if Init.sFinalBoss ~= "Ridley" then
Blackboard.SetProp("DEFEATED_ENEMIES", "Ridley", "b", true)
dyceron marked this conversation as resolved.
Show resolved Hide resolved
Game.GetEntity("Baby Hatchling"):SetVisible(true)
Scenario.LoadNewScenario("s000_surface", "StartPoint0")
end
end
function s110_surfaceb.OnStartRidleyDead()
Game.AddEntityToUpdateInCutscene("LE_RidleyStorm")
Expand Down Expand Up @@ -560,8 +574,10 @@ function s110_surfaceb.OnSubAreaChange(_ARG_0_, _ARG_1_, _ARG_2_, _ARG_3_, _ARG_
Game.SetScenarioItemEnabledByName("ray01", false)
Game.SetSceneGroupEnabledByName("sg_debris02", false)
Game.SetSceneGroupEnabledByName("sg_debris03", false)
if _ARG_2_ == "collision_camera_000" and not Blackboard.GetProp("GAME", "OBJECTIVE_COMPLETE") then
Scenario.LoadNewScenario("s000_surface", "ST_Surface_Connector")
if _ARG_2_ == "collision_camera_000" then
if (Init.sFinalBoss == "Ridley" and not Blackboard.GetProp("GAME", "OBJECTIVE_COMPLETE")) or Blackboard.GetProp("DEFEATED_ENEMIES", "Ridley") then
s110_surfaceb.LoadSurface()
end
end
if _ARG_2_ == "collision_camera_021" and _ARG_0_ == "collision_camera_021" and _ARG_3_ == "RidleyCombat" then
if Game.GetEntity("SG_Ridley") ~= nil then
Expand Down
33 changes: 28 additions & 5 deletions src/open_samus_returns_rando/files/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -255,16 +255,39 @@
},
"default": {}
},
"required_dna": {
"description": "The amount of Metroid DNA required to access Proteus Ridley.",
"type": "integer",
"minimum": 0
},
"reveal_map_on_start": {
"type": "boolean",
"default": false,
"description": "When true, the game will start with the whole map revealed"
},
"objective": {
"description": "Requirements for completing a seed.",
"type": "object",
"properties": {
"required_dna": {
"description": "The amount of Metroid DNA required to complete the objective.",
"type": "integer",
"minimum": 0
},
"final_boss": {
"description": "The required boss to defeat to complete the objective.",
"type": "string",
"enum": [
"Arachnus",
"Diggernaut",
"Queen",
"Ridley"
],
"default": "Ridley"
}
},
"required": [
"final_boss"
],
"default": {
"final_boss": "Ridley"
}
},
"game_patches": {
"type": "object",
"properties": {
Expand Down
18 changes: 11 additions & 7 deletions src/open_samus_returns_rando/files/templates/custom_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Init.bEnableRoomIds = TEMPLATE("enable_room_ids")
Init.sBabyMetroidHint = TEMPLATE("baby_metroid_hint")
Init.bTanksRefillAmmo = TEMPLATE("tanks_refill_ammo")
Init.iRequiredDNA = TEMPLATE("required_dna")
Init.sFinalBoss = TEMPLATE("final_boss")

local orig_log = Game.LogWarn
if TEMPLATE("enable_remote_lua") then
Expand All @@ -60,7 +61,16 @@ function Init.InitGameBlackboard()
end
end
end
Blackboard.SetProp("PLAYER_INVENTORY", "ITEM_ADN", "f", 39 - Init.iRequiredDNA)
Blackboard.SetProp("GAME", "OBJECTIVE_COMPLETE", "b", false)
if Init.iRequiredDNA == 0 then
-- If no DNA is required, then the path to Ridley should always be open
Blackboard.SetProp("GAME", "OBJECTIVE_COMPLETE", "b", true)
Blackboard.SetProp("PLAYER_INVENTORY", "ITEM_ADN", "f", 39)
elseif Init.iRequiredDNA <= 39 then
Blackboard.SetProp("PLAYER_INVENTORY", "ITEM_ADN", "f", 39 - Init.iRequiredDNA)
else
Blackboard.SetProp("PLAYER_INVENTORY", "ITEM_ADN", "f", 0)
end
Blackboard.SetProp("PLAYER_INVENTORY", "ITEM_METROID_COUNT", "f", 0)
Blackboard.SetProp("PLAYER_INVENTORY", "ITEM_CURRENT_LIFE", "f", Init.tNewGameInventory.ITEM_MAX_LIFE)
Blackboard.SetProp("PLAYER_INVENTORY", "ITEM_WEAPON_MISSILE_CURRENT", "f", Init.tNewGameInventory.ITEM_WEAPON_MISSILE_MAX)
Expand All @@ -73,12 +83,6 @@ function Init.InitGameBlackboard()
Blackboard.SetProp("GAME", "Version", "i", SaveGame.Version)
Blackboard.SetProp("GAME", "HUD", "b", true)
Blackboard.SetProp("GAME", "Player", "s", "samus")
-- If no DNA is required, then the path to Ridley should always be open
if Init.iRequiredDNA == 0 then
Blackboard.SetProp("GAME", "OBJECTIVE_COMPLETE", "b", true)
else
Blackboard.SetProp("GAME", "OBJECTIVE_COMPLETE", "b", false)
end
Blackboard.SetProp(Game.GetPlayerBlackboardSectionName(), "LevelID", "s", "c10_samus")
Blackboard.SetProp(Game.GetPlayerBlackboardSectionName(), "ScenarioID", "s", TEMPLATE("starting_scenario"))
Blackboard.SetProp(Game.GetPlayerBlackboardSectionName(), "StartPoint", "s", TEMPLATE("starting_actor"))
Expand Down
40 changes: 34 additions & 6 deletions src/open_samus_returns_rando/files/templates/randomizerpowerup.lua
Original file line number Diff line number Diff line change
Expand Up @@ -195,20 +195,48 @@ function RandomizerPowerup.IncreaseAmmo(resource)
end

function RandomizerPowerup.ObjectiveComplete()
if RandomizerPowerup.GetItemAmount("ITEM_ADN") == 39 then
local required_dna = 39
-- Default required_dna is 39, so change the requirement if set higher in the config
if Init.iRequiredDNA > 39 then
required_dna = Init.iRequiredDNA
end

if RandomizerPowerup.GetItemAmount("ITEM_ADN") == required_dna then
Blackboard.SetProp("GAME", "OBJECTIVE_COMPLETE", "b", true)
Game.HUDIdleScreenLeave()
local baby = RandomizerPowerup.GetItemAmount("ITEM_BABY_HATCHLING")
RandomizerPowerup.UpdateDNACounter()
Game.AddGUISF(3, "RandomizerPowerup.DisableBlink", "")

-- Assign boss names and areas to each boss
local boss = Init.sFinalBoss
local boss_name = boss
local boss_area = ""
if boss == "Arachnus" then
boss_area = "Area 2 Dam Exterior"
elseif boss == "Diggernaut" then
boss_area = "Area 6"
elseif boss == "Queen" then
boss_name = "the Queen"
boss_area = "Area 8"
elseif boss == "Ridley" then
boss_name = "Proteus Ridley"
boss_area = "Surface West"
end

-- Handle the message depending the boss/other factors
local baby = RandomizerPowerup.GetItemAmount("ITEM_BABY_HATCHLING")
local message = "Enough Metroid DNA has been collected!\nThe path to " .. boss_name .. " has been opened in " .. boss_area .. "!"
if baby > 0 then
GUI.LaunchMessage("Enough Metroid DNA has been collected!\nThe path to Proteus Ridley has been opened in Surface West!",
"RandomizerPowerup.Dummy", "")
if Scenario.CurrentScenarioID == "s110_surfaceb" then
GUI.LaunchMessage(message, "RandomizerPowerup.Dummy", "")
if Scenario.CurrentScenarioID == "s110_surfaceb" and boss == "Ridley" then
Game.PlayMusicStream(0, "streams/music/k_crateria99.wav", -1, -1, -1, 2, 2, 1)
end
elseif baby == 0 then
GUI.LaunchMessage("Enough Metroid DNA has been collected!\n" .. Init.sBabyMetroidHint, "RandomizerPowerup.Dummy", "")
if boss == "Ridley" then
GUI.LaunchMessage("Enough Metroid DNA has been collected!\n" .. Init.sBabyMetroidHint, "RandomizerPowerup.Dummy", "")
else
GUI.LaunchMessage(message .. "\n" .. Init.sBabyMetroidHint, "RandomizerPowerup.Dummy", "")
end
end
end
end
Expand Down
8 changes: 5 additions & 3 deletions src/open_samus_returns_rando/lua_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ def _create_custom_init(self, editor: PatcherEditor, configuration: dict) -> str
inventory: dict[str, int] = configuration["starting_items"]
starting_location: dict = configuration["starting_location"]
starting_text: list[str] = configuration.get("starting_text", [])
objective: dict = configuration["objective"]
game_patches: dict = configuration["game_patches"]
cosmetic_options: dict = configuration["cosmetic_patches"]
configuration_identifier: str = configuration["configuration_identifier"]
Expand Down Expand Up @@ -261,8 +262,8 @@ def chunks(array: list[str], n: int) -> Iterable[list[str]]:
if "baby_metroid_hint" in configuration:
baby_metroid_hint = lua_util.wrap_string(configuration["baby_metroid_hint"])

if "required_dna" in configuration:
required_dna = configuration["required_dna"]
if "required_dna" in objective:
required_dna = objective["required_dna"]
else:
starting_dna = [item for item in inventory if item.startswith("ITEM_RANDO_DNA")]
required_dna = 39 - len(starting_dna)
Expand All @@ -282,7 +283,8 @@ def chunks(array: list[str], n: int) -> Iterable[list[str]]:
"enable_remote_lua": enable_remote_lua,
"baby_metroid_hint": baby_metroid_hint,
"tanks_refill_ammo": game_patches["tanks_refill_ammo"],
"required_dna": required_dna
"required_dna": required_dna,
"final_boss": lua_util.wrap_string(objective["final_boss"])
}

return lua_util.replace_lua_template("custom_init.lua", replacement)
Expand Down
Loading