Skip to content

Commit 161fb2c

Browse files
authored
Merge pull request #2942 from UmedMuzl/ship-spawning-method
Win Condition Gates Krool Ship
2 parents f5cd35d + d05810e commit 161fb2c

33 files changed

+813
-540
lines changed

archipelago.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"minimum_ap_version": "0.6.4",
3-
"world_version": "1.4.15",
3+
"world_version": "1.4.16",
44
"authors": ["2dos", "AlmostSeagull", "Ballaam", "Green Bean", "Killklli", "Lrauq", "PoryGone", "Umed"],
55
"version": 7,
66
"compatible_version": 7,

archipelago/FillSettings.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def get_default_settings() -> dict:
189189
"kong_model_tiny": KongModels.default,
190190
"krool_access": False,
191191
"krool_in_boss_pool": False,
192-
"krool_key_count": 8,
192+
"krool_key_count": 0,
193193
"krool_phase_count": 3,
194194
"krool_phase_order_rando": True,
195195
"krool_random": False,
@@ -437,7 +437,8 @@ def apply_hard_mode_settings(settings_dict: dict, options) -> None:
437437
def apply_kong_settings(settings_dict: dict, options) -> None:
438438
"""Apply Kong settings."""
439439
# Key settings
440-
settings_dict["krool_key_count"] = options.krool_key_count.value
440+
settings_dict["krool_key_count"] = options.pregiven_keys.value
441+
settings_dict["win_condition_spawns_ship"] = 1 if options.require_beating_krool.value else 0
441442

442443
# Kong mapping
443444
kong_mapping = {
@@ -679,6 +680,13 @@ def apply_goal_settings(settings_dict: dict, options, random_obj) -> None:
679680
"""Apply goal and win condition settings."""
680681
settings_dict["win_condition_item"] = GOAL_MAPPING[options.goal]
681682

683+
# Krool's Challenge always requires beating K. Rool otherwise wheres the challenge
684+
if options.goal == Goal.option_krools_challenge:
685+
settings_dict["win_condition_spawns_ship"] = True
686+
# The rabbit is too powerful to allow this
687+
elif options.goal == Goal.option_kill_the_rabbit:
688+
settings_dict["win_condition_spawns_ship"] = False
689+
682690
if options.goal in QUANTITY_GOALS.keys():
683691
goal_name = QUANTITY_GOALS[options.goal]
684692
settings_dict["win_condition_count"] = calculate_quantity(goal_name, options.goal_quantity.value, random_obj)

archipelago/Goals.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
# Goal mapping for wincon determination
1111
GOAL_MAPPING = {
12-
Goal.option_beat_k_rool: WinConditionComplex.beat_krool,
12+
Goal.option_acquire_keys_3_and_8: WinConditionComplex.get_keys_3_and_8,
1313
Goal.option_acquire_key_8: WinConditionComplex.get_key8,
1414
Goal.option_kremling_kapture: WinConditionComplex.krem_kapture,
1515
Goal.option_dk_rap: WinConditionComplex.dk_rap_items,
@@ -70,6 +70,7 @@ def pp_wincon(win_condition_item, wc_count=0):
7070
win_con_name_table = {
7171
WinConditionComplex.beat_krool: "Beat K. Rool",
7272
WinConditionComplex.get_key8: "Acquire Key 8",
73+
WinConditionComplex.get_keys_3_and_8: "Acquire Keys 3 and 8",
7374
WinConditionComplex.krem_kapture: "Kremling Kapture",
7475
WinConditionComplex.dk_rap_items: "Complete the Rap",
7576
WinConditionComplex.req_bean: "Acquire the Bean",

archipelago/Logic.py

Lines changed: 100 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,75 @@ def AnyKongCanBuy(self, location, buy_empty=True):
14481448
return AnyKongCanBuy(self.spoiler, location, self, buy_empty)
14491449

14501450
def CanAccessKRool(self):
1451-
"""Make sure that each required key has been turned in."""
1451+
"""Make sure that each required key has been turned in, or if ship spawn method is win condition-based, check if win condition items are obtained."""
1452+
# If using win condition-based ship spawning, check if win condition item requirements are met
1453+
if self.settings.win_condition_spawns_ship:
1454+
condition = self.settings.win_condition_item
1455+
if condition == WinConditionComplex.krem_kapture:
1456+
for subject in self.spoiler.valid_photo_items:
1457+
if subject in (
1458+
Items.PhotoKasplatDK,
1459+
Items.PhotoKasplatDiddy,
1460+
Items.PhotoKasplatLanky,
1461+
Items.PhotoKasplatTiny,
1462+
Items.PhotoKasplatChunky,
1463+
):
1464+
continue
1465+
if self.Photos.get(subject, 0) == 0:
1466+
return False
1467+
return self.camera
1468+
elif condition == WinConditionComplex.get_key8:
1469+
return self.HelmKey
1470+
elif condition == WinConditionComplex.dk_rap_items:
1471+
dk_rap_items = [
1472+
self.donkey,
1473+
self.diddy,
1474+
self.lanky,
1475+
self.tiny,
1476+
self.chunky,
1477+
self.coconut,
1478+
self.peanut,
1479+
self.grape,
1480+
self.pineapple,
1481+
self.guitar,
1482+
self.trombone,
1483+
self.strongKong,
1484+
self.jetpack,
1485+
self.handstand,
1486+
self.balloon,
1487+
self.mini,
1488+
self.twirl,
1489+
self.barrels,
1490+
self.oranges,
1491+
self.climbing,
1492+
self.crankyAccess,
1493+
]
1494+
return all(dk_rap_items)
1495+
elif condition == WinConditionComplex.kill_the_rabbit:
1496+
return Events.KilledRabbit in self.Events
1497+
elif condition == WinConditionComplex.req_bonuses:
1498+
return self.bonuses_beaten >= self.settings.win_condition_count
1499+
elif condition == WinConditionComplex.req_bosses:
1500+
return self.bosses_beaten >= self.settings.win_condition_count
1501+
else:
1502+
# Item-based win conditions
1503+
win_con_table = {
1504+
WinConditionComplex.req_bean: BarrierItems.Bean,
1505+
WinConditionComplex.req_bp: BarrierItems.Blueprint,
1506+
WinConditionComplex.req_companycoins: BarrierItems.CompanyCoin,
1507+
WinConditionComplex.req_crown: BarrierItems.Crown,
1508+
WinConditionComplex.req_fairy: BarrierItems.Fairy,
1509+
WinConditionComplex.req_key: BarrierItems.Key,
1510+
WinConditionComplex.req_gb: BarrierItems.GoldenBanana,
1511+
WinConditionComplex.req_medal: BarrierItems.Medal,
1512+
WinConditionComplex.req_pearl: BarrierItems.Pearl,
1513+
WinConditionComplex.req_rainbowcoin: BarrierItems.RainbowCoin,
1514+
}
1515+
if condition in win_con_table:
1516+
return self.ItemCheck(win_con_table[condition], self.settings.win_condition_count)
1517+
return True
1518+
1519+
# Otherwise use key-based access
14521520
required_base_keys = [
14531521
Events.JapesKeyTurnedIn,
14541522
Events.AztecKeyTurnedIn,
@@ -1662,10 +1730,14 @@ def IsLevelEnterable(self, level):
16621730

16631731
def WinConditionMet(self):
16641732
"""Check if the current game state has met the win condition."""
1733+
condition = self.settings.win_condition_item
1734+
# When using win condition-based ship spawning, always require K. Rool defeat in addition to win condition items
1735+
krool_complete = not self.settings.win_condition_spawns_ship or Events.KRoolDefeated in self.Events
1736+
16651737
# Special Win Cons
1666-
if self.settings.win_condition_item == WinConditionComplex.beat_krool:
1738+
if condition == WinConditionComplex.beat_krool:
16671739
return Events.KRoolDefeated in self.Events
1668-
elif self.settings.win_condition_item == WinConditionComplex.krem_kapture:
1740+
elif condition == WinConditionComplex.krem_kapture:
16691741
for subject in self.spoiler.valid_photo_items:
16701742
if subject in (
16711743
Items.PhotoKasplatDK,
@@ -1676,11 +1748,17 @@ def WinConditionMet(self):
16761748
):
16771749
continue
16781750
if self.Photos.get(subject, 0) == 0:
1751+
# print(f"Could not reach {subject.name}")
16791752
return False
1680-
return self.camera
1681-
elif self.settings.win_condition_item == WinConditionComplex.get_key8:
1682-
return self.HelmKey
1683-
elif self.settings.win_condition_item == WinConditionComplex.dk_rap_items:
1753+
result = self.camera
1754+
return result and krool_complete
1755+
elif condition == WinConditionComplex.get_key8:
1756+
result = self.HelmKey
1757+
return result and krool_complete
1758+
elif condition == WinConditionComplex.get_keys_3_and_8:
1759+
result = self.FactoryKey and self.HelmKey
1760+
return result and krool_complete
1761+
elif condition == WinConditionComplex.dk_rap_items:
16841762
dk_rap_items = [
16851763
self.donkey,
16861764
self.diddy,
@@ -1711,16 +1789,20 @@ def WinConditionMet(self):
17111789
for k in dk_rap_items:
17121790
if not k:
17131791
return False
1714-
return True
1715-
elif self.settings.win_condition_item == WinConditionComplex.krools_challenge:
1792+
result = True
1793+
return result and krool_complete
1794+
elif condition == WinConditionComplex.krools_challenge:
17161795
# Krool's Challenge: Beat K. Rool + collect all Keys, Blueprints, Bosses, and Bonus Barrels
17171796
return Events.KRoolDefeated in self.Events and self.ItemCheck(BarrierItems.Key, 8) and self.ItemCheck(BarrierItems.Blueprint, 40) and self.bosses_beaten >= 7 and self.bonuses_beaten >= 43
1718-
elif self.settings.win_condition_item == WinConditionComplex.kill_the_rabbit:
1719-
return Events.KilledRabbit in self.Events
1720-
elif self.settings.win_condition_item == WinConditionComplex.req_bosses:
1721-
return self.bosses_beaten >= self.settings.win_condition_count
1722-
elif self.settings.win_condition_item == WinConditionComplex.req_bonuses:
1723-
return self.bonuses_beaten >= self.settings.win_condition_count
1797+
elif condition == WinConditionComplex.kill_the_rabbit:
1798+
result = Events.KilledRabbit in self.Events
1799+
return result and krool_complete
1800+
elif condition == WinConditionComplex.req_bonuses:
1801+
result = self.bonuses_beaten >= self.settings.win_condition_count
1802+
return result and krool_complete
1803+
elif condition == WinConditionComplex.req_bosses:
1804+
result = self.bosses_beaten >= self.settings.win_condition_count
1805+
return result and krool_complete
17241806
# Get X amount of Y item win cons
17251807
win_con_table = {
17261808
WinConditionComplex.req_bean: BarrierItems.Bean,
@@ -1734,9 +1816,10 @@ def WinConditionMet(self):
17341816
WinConditionComplex.req_pearl: BarrierItems.Pearl,
17351817
WinConditionComplex.req_rainbowcoin: BarrierItems.RainbowCoin,
17361818
}
1737-
if self.settings.win_condition_item not in win_con_table:
1819+
if condition not in win_con_table:
17381820
raise Exception(f"Invalid Win Condition {self.settings.win_condition_item.name}")
1739-
return self.ItemCheck(win_con_table[self.settings.win_condition_item], self.settings.win_condition_count)
1821+
result = self.ItemCheck(win_con_table[condition], self.settings.win_condition_count)
1822+
return result and krool_complete
17401823

17411824
def CanGetRarewareCoin(self):
17421825
"""Check if you meet the logical requirements to obtain the Rareware Coin."""

archipelago/Options.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class Goal(Choice):
4343
"""
4444

4545
display_name = "Goal"
46-
option_beat_k_rool = 0
46+
option_acquire_keys_3_and_8 = 0
4747
option_acquire_key_8 = 1
4848
option_kremling_kapture = 2
4949
option_dk_rap = 3
@@ -62,7 +62,7 @@ class Goal(Choice):
6262
option_treasure_hurry = 16
6363
option_krools_challenge = 17
6464
option_kill_the_rabbit = 18
65-
default = 0
65+
default = 7
6666

6767

6868
class GoalQuantity(OptionDict):
@@ -362,16 +362,26 @@ class MermaidRequirement(Range):
362362

363363

364364
class KeysRequiredToBeatKrool(Range):
365-
"""Determines how many keys are needed to spawn Krool's Ship.
365+
"""Determines how many keys are pregiven.
366366
367-
Choosing a value of 0 means you start with all 8 keys.
368-
Choosing a value of 8 means you start with no keys.
367+
Choosing a value of 0 means you start with 0 keys.
368+
Choosing a value of 8 means you start with all 8 keys.
369369
"""
370370

371-
display_name = "Keys Required to Beat Krool"
371+
display_name = "Amount of Pregiven Keys"
372372
range_start = 0
373373
range_end = 8
374-
default = 8
374+
default = 0
375+
376+
377+
class RequireBeatingKrool(DefaultOnToggle):
378+
"""Require defeating K. Rool in addition to the win condition requirements.
379+
380+
K. Rool's ship will not spawn until you meet your win condition requirements, and you must defeat K. Rool to win.
381+
Automatically enabled for Krool's Challenge. Automatically disabled for Kill the Rabbit.
382+
"""
383+
384+
display_name = "Require Beating K. Rool"
375385

376386

377387
class SwitchSanity(Choice):
@@ -1173,7 +1183,8 @@ class DK64Options(PerGameCommonOptions):
11731183
tag_link: TagLink
11741184
trap_link: TrapLink
11751185
goal: Goal
1176-
krool_key_count: KeysRequiredToBeatKrool
1186+
pregiven_keys: KeysRequiredToBeatKrool
1187+
require_beating_krool: RequireBeatingKrool
11771188
helm_key_lock: HelmKeyLock
11781189
shuffle_helm_level_order: ShuffleHelmLevel
11791190
krool_phase_count: KroolPhaseCount
@@ -1264,6 +1275,7 @@ class DK64Options(PerGameCommonOptions):
12641275
"Victory Conditions",
12651276
[
12661277
Goal,
1278+
RequireBeatingKrool,
12671279
GoalQuantity,
12681280
KeysRequiredToBeatKrool,
12691281
HelmPhaseCount,

base-hack/include/common_enums.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ typedef enum win_conditions {
314314
/* 0x004 */ GOAL_DKRAP,
315315
/* 0x005 */ GOAL_KROOLS_CHALLENGE,
316316
/* 0x006 */ GOAL_KILL_THE_RABBIT,
317+
/* 0x007 */ GOAL_KEYS_3_AND_8,
317318
} win_conditions;
318319

319320
typedef enum master_types_list {

base-hack/include/global.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ extern void checkVictory_flaghook(int flag);
237237
extern void winRabbitSeed(int song, float volume);
238238
extern void safeguardRabbitReward(void);
239239
extern int canAccessKroolsChallenge(void);
240+
extern int canAccessWinCondition(void);
240241
extern void FileProgressInitSub(int file, int shuffle);
241242
extern void handleFileSelectSprites(void* paad, void* sprite, int x, int y, float scale, int unk0, int control);
242243
extern void checkSkippableCutscene(void);

base-hack/include/variable_space_structs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ typedef struct varspace {
131131
/* 0x1B0 */ int password;
132132
/* 0x1B4 */ char song_speed_near_win;
133133
/* 0x1B5 */ unsigned char pppanic_fairy_model; // 0 = Vanilla
134-
/* 0x1B6 */ unsigned char krool_ship_spawn_method; // 0 = Key Bases, 1 = Collectible Based
134+
/* 0x1B6 */ unsigned char win_condition_spawns_ship; // 0 = Key Bases, 1 = Collectible Based
135135
/* 0x1B7 */ DisabledMusicStruct disabled_music;
136136
/* 0x1B8 */ unsigned char kong_models[5];
137137
/* 0x1BD */ char unk_1bd[0x1C6 - 0x1BD];

base-hack/src/instances/instances.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -495,9 +495,9 @@ int change_object_scripts(behaviour_data* behaviour_pointer, int id, int index,
495495
}
496496
} else if (param2 == K_ROOL_SHIP) {
497497
// Check access requirements based on ship spawn method
498-
if (Rando.krool_ship_spawn_method == 1) {
499-
// Collectible-based access
500-
if (!canAccessKroolsChallenge()) {
498+
if (Rando.win_condition_spawns_ship == 1) {
499+
// Win condition-based access
500+
if (!canAccessWinCondition()) {
501501
return 0;
502502
}
503503
} else {

0 commit comments

Comments
 (0)