mirror of
				https://github.com/MarioSpore/Grinch-AP.git
				synced 2025-10-21 20:21:32 -06:00 
			
		
		
		
	Celeste 64: v1.2 Content Update (#3210)
* Cleanup and new option support * Handle new locations * Support higher Strawberry counts * Don't add start inventory items to the pool * Support Move Shuffle functionality and items * Hard and Move Shuffle Logic * Fix Options * Update CHANGELOG.md * Add standard moves logic for signs 3 and 4 * Fix Option Tooltip * Add tracker link to setup guide * Fix unit test * Fix option tooltips * Missing Space * Move option checking out of rule function * Delete just_gen500.bat
This commit is contained in:
		| @@ -1,6 +1,38 @@ | ||||
| # Celeste 64 - Changelog | ||||
|  | ||||
|  | ||||
| ## v1.2 | ||||
|  | ||||
| ### Features: | ||||
|  | ||||
| - New optional Location Checks | ||||
| 	- Friendsanity | ||||
| 	- Signsanity | ||||
| 	- Carsanity | ||||
| - Move Shuffle | ||||
| 	- Basic movement abilities can be shuffled into the item pool | ||||
| 		- Ground Dash | ||||
| 		- Air Dash | ||||
| 		- Skid Jump | ||||
| 		- Climb | ||||
| - Logic Difficulty | ||||
| 	- Completely overhauled logic system | ||||
| 	- Standard or Hard logic difficulty can be chosen | ||||
| - Badeline Chasers | ||||
| 	- Opt-in options which cause Badelines to start following you as you play, which will kill on contact | ||||
| 	- These can be set to spawn based on either: | ||||
| 		- The number of locations you've checked | ||||
| 		- The number of Strawberry items you've received | ||||
| 	- How fast they follow behind you can be specified | ||||
|  | ||||
| ### Quality of Life: | ||||
|  | ||||
| - The maximum number of Strawberries in the item pool can be directly set | ||||
| 	- The required amount of Strawberries is now set via percentage | ||||
| 	- All items beyond the amount placed in the item pool will be `Raspberry` items, which have no effect | ||||
| - Any unique items placed into the `start_inventory` will not be placed into the item pool | ||||
|  | ||||
|  | ||||
| ## v1.1 - First Stable Release | ||||
|  | ||||
| ### Features: | ||||
|   | ||||
| @@ -16,43 +16,29 @@ class Celeste64ItemData(NamedTuple): | ||||
|     type: ItemClassification = ItemClassification.filler | ||||
|  | ||||
|  | ||||
| item_data_table: Dict[str, Celeste64ItemData] = { | ||||
|     ItemName.strawberry: Celeste64ItemData( | ||||
|         code = celeste_64_base_id + 0, | ||||
|         type=ItemClassification.progression_skip_balancing, | ||||
|     ), | ||||
|     ItemName.dash_refill: Celeste64ItemData( | ||||
|         code = celeste_64_base_id + 1, | ||||
|         type=ItemClassification.progression, | ||||
|     ), | ||||
|     ItemName.double_dash_refill: Celeste64ItemData( | ||||
|         code = celeste_64_base_id + 2, | ||||
|         type=ItemClassification.progression, | ||||
|     ), | ||||
|     ItemName.feather: Celeste64ItemData( | ||||
|         code = celeste_64_base_id + 3, | ||||
|         type=ItemClassification.progression, | ||||
|     ), | ||||
|     ItemName.coin: Celeste64ItemData( | ||||
|         code = celeste_64_base_id + 4, | ||||
|         type=ItemClassification.progression, | ||||
|     ), | ||||
|     ItemName.cassette: Celeste64ItemData( | ||||
|         code = celeste_64_base_id + 5, | ||||
|         type=ItemClassification.progression, | ||||
|     ), | ||||
|     ItemName.traffic_block: Celeste64ItemData( | ||||
|         code = celeste_64_base_id + 6, | ||||
|         type=ItemClassification.progression, | ||||
|     ), | ||||
|     ItemName.spring: Celeste64ItemData( | ||||
|         code = celeste_64_base_id + 7, | ||||
|         type=ItemClassification.progression, | ||||
|     ), | ||||
|     ItemName.breakables: Celeste64ItemData( | ||||
|         code = celeste_64_base_id + 8, | ||||
|         type=ItemClassification.progression, | ||||
|     ) | ||||
| collectable_item_data_table: Dict[str, Celeste64ItemData] = { | ||||
|     ItemName.strawberry: Celeste64ItemData(celeste_64_base_id + 0x0, ItemClassification.progression_skip_balancing), | ||||
|     ItemName.raspberry:  Celeste64ItemData(celeste_64_base_id + 0x9, ItemClassification.filler), | ||||
| } | ||||
|  | ||||
| unlockable_item_data_table: Dict[str, Celeste64ItemData] = { | ||||
|     ItemName.dash_refill:        Celeste64ItemData(celeste_64_base_id + 0x1, ItemClassification.progression), | ||||
|     ItemName.double_dash_refill: Celeste64ItemData(celeste_64_base_id + 0x2, ItemClassification.progression), | ||||
|     ItemName.feather:            Celeste64ItemData(celeste_64_base_id + 0x3, ItemClassification.progression), | ||||
|     ItemName.coin:               Celeste64ItemData(celeste_64_base_id + 0x4, ItemClassification.progression), | ||||
|     ItemName.cassette:           Celeste64ItemData(celeste_64_base_id + 0x5, ItemClassification.progression), | ||||
|     ItemName.traffic_block:      Celeste64ItemData(celeste_64_base_id + 0x6, ItemClassification.progression), | ||||
|     ItemName.spring:             Celeste64ItemData(celeste_64_base_id + 0x7, ItemClassification.progression), | ||||
|     ItemName.breakables:         Celeste64ItemData(celeste_64_base_id + 0x8, ItemClassification.progression), | ||||
| } | ||||
|  | ||||
| move_item_data_table: Dict[str, Celeste64ItemData] = { | ||||
|     ItemName.ground_dash: Celeste64ItemData(celeste_64_base_id + 0xA, ItemClassification.progression), | ||||
|     ItemName.air_dash:    Celeste64ItemData(celeste_64_base_id + 0xB, ItemClassification.progression), | ||||
|     ItemName.skid_jump:   Celeste64ItemData(celeste_64_base_id + 0xC, ItemClassification.progression), | ||||
|     ItemName.climb:       Celeste64ItemData(celeste_64_base_id + 0xD, ItemClassification.progression), | ||||
| } | ||||
|  | ||||
| item_data_table: Dict[str, Celeste64ItemData] = {**collectable_item_data_table, **unlockable_item_data_table, **move_item_data_table} | ||||
|  | ||||
| item_table = {name: data.code for name, data in item_data_table.items() if data.code is not None} | ||||
|   | ||||
| @@ -16,127 +16,67 @@ class Celeste64LocationData(NamedTuple): | ||||
|     address: Optional[int] = None | ||||
|  | ||||
|  | ||||
| location_data_table: Dict[str, Celeste64LocationData] = { | ||||
|     LocationName.strawberry_1 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 0, | ||||
|     ), | ||||
|     LocationName.strawberry_2 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 1, | ||||
|     ), | ||||
|     LocationName.strawberry_3 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 2, | ||||
|     ), | ||||
|     LocationName.strawberry_4 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 3, | ||||
|     ), | ||||
|     LocationName.strawberry_5 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 4, | ||||
|     ), | ||||
|     LocationName.strawberry_6 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 5, | ||||
|     ), | ||||
|     LocationName.strawberry_7 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 6, | ||||
|     ), | ||||
|     LocationName.strawberry_8 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 7, | ||||
|     ), | ||||
|     LocationName.strawberry_9 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 8, | ||||
|     ), | ||||
|     LocationName.strawberry_10 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 9, | ||||
|     ), | ||||
|     LocationName.strawberry_11 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 10, | ||||
|     ), | ||||
|     LocationName.strawberry_12 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 11, | ||||
|     ), | ||||
|     LocationName.strawberry_13 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 12, | ||||
|     ), | ||||
|     LocationName.strawberry_14 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 13, | ||||
|     ), | ||||
|     LocationName.strawberry_15 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 14, | ||||
|     ), | ||||
|     LocationName.strawberry_16 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 15, | ||||
|     ), | ||||
|     LocationName.strawberry_17 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 16, | ||||
|     ), | ||||
|     LocationName.strawberry_18 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 17, | ||||
|     ), | ||||
|     LocationName.strawberry_19 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 18, | ||||
|     ), | ||||
|     LocationName.strawberry_20 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 19, | ||||
|     ), | ||||
|     LocationName.strawberry_21 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 20, | ||||
|     ), | ||||
|     LocationName.strawberry_22 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 21, | ||||
|     ), | ||||
|     LocationName.strawberry_23 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 22, | ||||
|     ), | ||||
|     LocationName.strawberry_24 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 23, | ||||
|     ), | ||||
|     LocationName.strawberry_25 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 24, | ||||
|     ), | ||||
|     LocationName.strawberry_26 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 25, | ||||
|     ), | ||||
|     LocationName.strawberry_27 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 26, | ||||
|     ), | ||||
|     LocationName.strawberry_28 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 27, | ||||
|     ), | ||||
|     LocationName.strawberry_29 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 28, | ||||
|     ), | ||||
|     LocationName.strawberry_30 : Celeste64LocationData( | ||||
|         region = "Forsaken City", | ||||
|         address = celeste_64_base_id + 29, | ||||
|     ) | ||||
| strawberry_location_data_table: Dict[str, Celeste64LocationData] = { | ||||
|     LocationName.strawberry_1:  Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x00), | ||||
|     LocationName.strawberry_2:  Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x01), | ||||
|     LocationName.strawberry_3:  Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x02), | ||||
|     LocationName.strawberry_4:  Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x03), | ||||
|     LocationName.strawberry_5:  Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x04), | ||||
|     LocationName.strawberry_6:  Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x05), | ||||
|     LocationName.strawberry_7:  Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x06), | ||||
|     LocationName.strawberry_8:  Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x07), | ||||
|     LocationName.strawberry_9:  Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x08), | ||||
|     LocationName.strawberry_10: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x09), | ||||
|     LocationName.strawberry_11: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0A), | ||||
|     LocationName.strawberry_12: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0B), | ||||
|     LocationName.strawberry_13: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0C), | ||||
|     LocationName.strawberry_14: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0D), | ||||
|     LocationName.strawberry_15: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0E), | ||||
|     LocationName.strawberry_16: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0F), | ||||
|     LocationName.strawberry_17: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x10), | ||||
|     LocationName.strawberry_18: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x11), | ||||
|     LocationName.strawberry_19: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x12), | ||||
|     LocationName.strawberry_20: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x13), | ||||
|     LocationName.strawberry_21: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x14), | ||||
|     LocationName.strawberry_22: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x15), | ||||
|     LocationName.strawberry_23: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x16), | ||||
|     LocationName.strawberry_24: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x17), | ||||
|     LocationName.strawberry_25: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x18), | ||||
|     LocationName.strawberry_26: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x19), | ||||
|     LocationName.strawberry_27: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x1A), | ||||
|     LocationName.strawberry_28: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x1B), | ||||
|     LocationName.strawberry_29: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x1C), | ||||
|     LocationName.strawberry_30: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x1D), | ||||
| } | ||||
|  | ||||
| friend_location_data_table: Dict[str, Celeste64LocationData] = { | ||||
|     LocationName.granny_1:   Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x00), | ||||
|     LocationName.granny_2:   Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x01), | ||||
|     LocationName.granny_3:   Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x02), | ||||
|     LocationName.theo_1:     Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x03), | ||||
|     LocationName.theo_2:     Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x04), | ||||
|     LocationName.theo_3:     Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x05), | ||||
|     LocationName.badeline_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x06), | ||||
|     LocationName.badeline_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x07), | ||||
|     LocationName.badeline_3: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x08), | ||||
| } | ||||
|  | ||||
| sign_location_data_table: Dict[str, Celeste64LocationData] = { | ||||
|     LocationName.sign_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x200 + 0x00), | ||||
|     LocationName.sign_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x200 + 0x01), | ||||
|     LocationName.sign_3: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x200 + 0x02), | ||||
|     LocationName.sign_4: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x200 + 0x03), | ||||
|     LocationName.sign_5: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x200 + 0x04), | ||||
| } | ||||
|  | ||||
| car_location_data_table: Dict[str, Celeste64LocationData] = { | ||||
|     LocationName.car_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x300 + 0x00), | ||||
|     LocationName.car_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x300 + 0x01), | ||||
| } | ||||
|  | ||||
| location_data_table: Dict[str, Celeste64LocationData] = {**strawberry_location_data_table, | ||||
|                                                          **friend_location_data_table, | ||||
|                                                          **sign_location_data_table, | ||||
|                                                          **car_location_data_table} | ||||
|  | ||||
| location_table = {name: data.address for name, data in location_data_table.items() if data.address is not None} | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| strawberry = "Strawberry" | ||||
| raspberry = "Raspberry" | ||||
|  | ||||
| dash_refill        = "Dash Refills" | ||||
| double_dash_refill = "Double Dash Refills" | ||||
| @@ -9,3 +10,8 @@ cassette           = "Cassettes" | ||||
| traffic_block = "Traffic Blocks" | ||||
| spring        = "Springs" | ||||
| breakables    = "Breakable Blocks" | ||||
|  | ||||
| ground_dash = "Ground Dash" | ||||
| air_dash    = "Air Dash" | ||||
| skid_jump   = "Skid Jump" | ||||
| climb       = "Climb" | ||||
|   | ||||
| @@ -29,3 +29,25 @@ strawberry_27 = "Distant Feather Cassette Strawberry" | ||||
| strawberry_28 = "Feather Arches Cassette Strawberry" | ||||
| strawberry_29 = "North-East Tower Cassette Strawberry" | ||||
| strawberry_30 = "Badeline Cassette Strawberry" | ||||
|  | ||||
| # Friend Locations | ||||
| granny_1   = "Granny Conversation 1" | ||||
| granny_2   = "Granny Conversation 2" | ||||
| granny_3   = "Granny Conversation 3" | ||||
| theo_1     = "Theo Conversation 1" | ||||
| theo_2     = "Theo Conversation 2" | ||||
| theo_3     = "Theo Conversation 3" | ||||
| badeline_1 = "Badeline Conversation 1" | ||||
| badeline_2 = "Badeline Conversation 2" | ||||
| badeline_3 = "Badeline Conversation 3" | ||||
|  | ||||
| # Sign Locations | ||||
| sign_1 = "Camera Sign" | ||||
| sign_2 = "Skid Jump Sign" | ||||
| sign_3 = "Dash Jump Sign" | ||||
| sign_4 = "Lonely Sign" | ||||
| sign_5 = "Credits Sign" | ||||
|  | ||||
| # Car Locations | ||||
| car_1 = "Intro Car" | ||||
| car_2 = "Secret Car" | ||||
|   | ||||
| @@ -1,25 +1,124 @@ | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| from Options import Range, DeathLink, PerGameCommonOptions | ||||
| from Options import Choice, Range, Toggle, DeathLink, PerGameCommonOptions | ||||
|  | ||||
|  | ||||
| class StrawberriesRequired(Range): | ||||
|     """How many Strawberries you must receive to finish""" | ||||
|     display_name = "Strawberries Required" | ||||
|     range_start = 0 | ||||
|     range_end = 20 | ||||
|     default = 15 | ||||
|  | ||||
| class DeathLinkAmnesty(Range): | ||||
|     """How many deaths it takes to send a DeathLink""" | ||||
|     """ | ||||
|     How many deaths it takes to send a DeathLink | ||||
|     """ | ||||
|     display_name = "Death Link Amnesty" | ||||
|     range_start = 1 | ||||
|     range_end = 30 | ||||
|     default = 10 | ||||
|  | ||||
| class TotalStrawberries(Range): | ||||
|     """ | ||||
|     How many Strawberries exist | ||||
|     """ | ||||
|     display_name = "Total Strawberries" | ||||
|     range_start = 0 | ||||
|     range_end = 46 | ||||
|     default = 20 | ||||
|  | ||||
| class StrawberriesRequiredPercentage(Range): | ||||
|     """ | ||||
|     Percentage of existing Strawberries you must receive to finish | ||||
|     """ | ||||
|     display_name = "Strawberries Required Percentage" | ||||
|     range_start = 0 | ||||
|     range_end = 100 | ||||
|     default = 80 | ||||
|  | ||||
|  | ||||
| class LogicDifficulty(Choice): | ||||
|     """ | ||||
|     Whether the logic expects you to play the intended way, or to be able to use advanced tricks and skips | ||||
|     """ | ||||
|     display_name = "Logic Difficulty" | ||||
|     option_standard = 0 | ||||
|     option_hard = 1 | ||||
|     default = 0 | ||||
|  | ||||
| class MoveShuffle(Toggle): | ||||
|     """ | ||||
|     Whether the following base movement abilities are shuffled into the item pool: | ||||
|     - Ground Dash | ||||
|     - Air Dash | ||||
|     - Skid Jump | ||||
|     - Climb | ||||
|     NOTE: Having Move Shuffle and Standard Logic Difficulty will guarantee that one of the four Move items will be immediately accessible | ||||
|     WARNING: Combining Move Shuffle and Hard Logic Difficulty can require very difficult tricks | ||||
|     """ | ||||
|     display_name = "Move Shuffle" | ||||
|  | ||||
|  | ||||
| class Friendsanity(Toggle): | ||||
|     """ | ||||
|     Whether chatting with your friends grants location checks | ||||
|     """ | ||||
|     display_name = "Friendsanity" | ||||
|  | ||||
| class Signsanity(Toggle): | ||||
|     """ | ||||
|     Whether reading signs grants location checks | ||||
|     """ | ||||
|     display_name = "Signsanity" | ||||
|  | ||||
| class Carsanity(Toggle): | ||||
|     """ | ||||
|     Whether riding on cars grants location checks | ||||
|     """ | ||||
|     display_name = "Carsanity" | ||||
|  | ||||
|  | ||||
| class BadelineChaserSource(Choice): | ||||
|     """ | ||||
|     What type of action causes more Badeline Chasers to start spawning | ||||
|     Locations: The number of locations you've checked contributes to Badeline Chasers | ||||
|     Strawberries: The number of Strawberry items you've received contributes to Badeline Chasers | ||||
|     """ | ||||
|     display_name = "Badeline Chaser Source" | ||||
|     option_locations = 0 | ||||
|     option_strawberries = 1 | ||||
|     default = 0 | ||||
|  | ||||
| class BadelineChaserFrequency(Range): | ||||
|     """ | ||||
|     How many of the `Badeline Chaser Source` actions must occur to make each Badeline Chaser start spawning | ||||
|     NOTE: Choosing `0` disables Badeline Chasers entirely | ||||
|     WARNING: Turning on Badeline Chasers alongside Move Shuffle could result in extremely difficult situations | ||||
|     """ | ||||
|     display_name = "Badeline Chaser Frequency" | ||||
|     range_start = 0 | ||||
|     range_end = 10 | ||||
|     default = 0 | ||||
|  | ||||
| class BadelineChaserSpeed(Range): | ||||
|     """ | ||||
|     How many seconds behind you each Badeline Chaser will be | ||||
|     """ | ||||
|     display_name = "Badeline Chaser Speed" | ||||
|     range_start = 2 | ||||
|     range_end = 10 | ||||
|     default = 3 | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Celeste64Options(PerGameCommonOptions): | ||||
|     death_link: DeathLink | ||||
|     death_link_amnesty: DeathLinkAmnesty | ||||
|     strawberries_required: StrawberriesRequired | ||||
|  | ||||
|     total_strawberries: TotalStrawberries | ||||
|     strawberries_required_percentage: StrawberriesRequiredPercentage | ||||
|  | ||||
|     logic_difficulty: LogicDifficulty | ||||
|     move_shuffle: MoveShuffle | ||||
|  | ||||
|     friendsanity: Friendsanity | ||||
|     signsanity: Signsanity | ||||
|     carsanity: Carsanity | ||||
|  | ||||
|     badeline_chaser_source: BadelineChaserSource | ||||
|     badeline_chaser_frequency: BadelineChaserFrequency | ||||
|     badeline_chaser_speed: BadelineChaserSpeed | ||||
|   | ||||
| @@ -1,3 +1,6 @@ | ||||
| from typing import Dict, List | ||||
|  | ||||
| from BaseClasses import CollectionState | ||||
| from worlds.generic.Rules import set_rule | ||||
|  | ||||
| from . import Celeste64World | ||||
| @@ -5,100 +8,336 @@ from .Names import ItemName, LocationName | ||||
|  | ||||
|  | ||||
| def set_rules(world: Celeste64World): | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_4, world.player), | ||||
|              lambda state: state.has_all({ItemName.traffic_block, | ||||
|                                           ItemName.breakables}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_5, world.player), | ||||
|              lambda state: state.has(ItemName.breakables, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_6, world.player), | ||||
|              lambda state: state.has(ItemName.dash_refill, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_8, world.player), | ||||
|              lambda state: state.has(ItemName.traffic_block, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_9, world.player), | ||||
|              lambda state: state.has(ItemName.dash_refill, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_11, world.player), | ||||
|              lambda state: state.has(ItemName.dash_refill, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_12, world.player), | ||||
|              lambda state: state.has_all({ItemName.dash_refill, | ||||
|                                           ItemName.double_dash_refill}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_13, world.player), | ||||
|              lambda state: state.has_all({ItemName.dash_refill, | ||||
|                                           ItemName.breakables}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_14, world.player), | ||||
|              lambda state: state.has_all({ItemName.dash_refill, | ||||
|                                           ItemName.feather}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_15, world.player), | ||||
|              lambda state: state.has_all({ItemName.dash_refill, | ||||
|                                           ItemName.feather}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_16, world.player), | ||||
|              lambda state: state.has_all({ItemName.dash_refill, | ||||
|                                           ItemName.feather}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_17, world.player), | ||||
|              lambda state: state.has_all({ItemName.dash_refill, | ||||
|                                           ItemName.double_dash_refill, | ||||
|                                           ItemName.feather, | ||||
|                                           ItemName.traffic_block}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_18, world.player), | ||||
|              lambda state: state.has(ItemName.double_dash_refill, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_19, world.player), | ||||
|              lambda state: state.has_all({ItemName.double_dash_refill, | ||||
|                                           ItemName.spring}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_20, world.player), | ||||
|              lambda state: state.has_all({ItemName.dash_refill, | ||||
|                                           ItemName.feather, | ||||
|                                           ItemName.breakables}, world.player)) | ||||
|     if world.options.logic_difficulty == "standard": | ||||
|         if world.options.move_shuffle: | ||||
|             world.active_logic_mapping = location_standard_moves_logic | ||||
|         else: | ||||
|             world.active_logic_mapping = location_standard_logic | ||||
|     else: | ||||
|         if world.options.move_shuffle: | ||||
|             world.active_logic_mapping = location_hard_moves_logic | ||||
|         else: | ||||
|             world.active_logic_mapping = location_hard_logic | ||||
|  | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_21, world.player), | ||||
|              lambda state: state.has_all({ItemName.cassette, | ||||
|                                           ItemName.traffic_block, | ||||
|                                           ItemName.breakables}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_22, world.player), | ||||
|              lambda state: state.has_all({ItemName.cassette, | ||||
|                                           ItemName.dash_refill, | ||||
|                                           ItemName.breakables}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_23, world.player), | ||||
|              lambda state: state.has_all({ItemName.cassette, | ||||
|                                           ItemName.dash_refill, | ||||
|                                           ItemName.coin}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_24, world.player), | ||||
|              lambda state: state.has_all({ItemName.cassette, | ||||
|                                           ItemName.traffic_block, | ||||
|                                           ItemName.dash_refill}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_25, world.player), | ||||
|              lambda state: state.has_all({ItemName.cassette, | ||||
|                                           ItemName.dash_refill, | ||||
|                                           ItemName.double_dash_refill}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_26, world.player), | ||||
|              lambda state: state.has_all({ItemName.cassette, | ||||
|                                           ItemName.dash_refill}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_27, world.player), | ||||
|              lambda state: state.has_all({ItemName.cassette, | ||||
|                                           ItemName.feather, | ||||
|                                           ItemName.coin, | ||||
|                                           ItemName.dash_refill}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_28, world.player), | ||||
|              lambda state: state.has_all({ItemName.cassette, | ||||
|                                           ItemName.feather, | ||||
|                                           ItemName.coin, | ||||
|                                           ItemName.dash_refill}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_29, world.player), | ||||
|              lambda state: state.has_all({ItemName.cassette, | ||||
|                                           ItemName.feather, | ||||
|                                           ItemName.coin, | ||||
|                                           ItemName.dash_refill}, world.player)) | ||||
|     set_rule(world.multiworld.get_location(LocationName.strawberry_30, world.player), | ||||
|              lambda state: state.has_all({ItemName.cassette, | ||||
|                                           ItemName.feather, | ||||
|                                           ItemName.traffic_block, | ||||
|                                           ItemName.spring, | ||||
|                                           ItemName.breakables, | ||||
|                                           ItemName.dash_refill, | ||||
|                                           ItemName.double_dash_refill}, world.player)) | ||||
|     for location in world.multiworld.get_locations(world.player): | ||||
|         set_rule(location, lambda state, location=location: location_rule(state, world, location.name)) | ||||
|  | ||||
|     if world.options.logic_difficulty == "standard": | ||||
|         if world.options.move_shuffle: | ||||
|             world.goal_logic_mapping = goal_standard_moves_logic | ||||
|         else: | ||||
|             world.goal_logic_mapping = goal_standard_logic | ||||
|     else: | ||||
|         if world.options.move_shuffle: | ||||
|             world.goal_logic_mapping = goal_hard_moves_logic | ||||
|         else: | ||||
|             world.goal_logic_mapping = goal_hard_logic | ||||
|  | ||||
|     # Completion condition. | ||||
|     world.multiworld.completion_condition[world.player] = lambda state: (state.has(ItemName.strawberry,world.player,world.options.strawberries_required.value) and | ||||
|                                                                          state.has_all({ItemName.feather, | ||||
|                                                                                         ItemName.traffic_block, | ||||
|                                                                                         ItemName.breakables, | ||||
|                                                                                         ItemName.dash_refill, | ||||
|                                                                                         ItemName.double_dash_refill}, world.player)) | ||||
|     world.multiworld.completion_condition[world.player] = lambda state: goal_rule(state, world) | ||||
|  | ||||
|  | ||||
| goal_standard_logic: List[List[str]] = [[ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.double_dash_refill]] | ||||
| goal_hard_logic: List[List[str]] = [[]] | ||||
| goal_standard_moves_logic: List[List[str]] = [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb]] | ||||
| goal_hard_moves_logic: List[List[str]] = [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb], | ||||
|                                           [ItemName.traffic_block, ItemName.air_dash, ItemName.skid_jump], | ||||
|                                           [ItemName.ground_dash, ItemName.air_dash, ItemName.skid_jump], | ||||
|                                           [ItemName.feather, ItemName.traffic_block, ItemName.air_dash], | ||||
|                                           [ItemName.traffic_block, ItemName.ground_dash, ItemName.air_dash]] | ||||
|  | ||||
|  | ||||
| location_standard_logic: Dict[str, List[List[str]]] = { | ||||
|     LocationName.strawberry_4:  [[ItemName.traffic_block, ItemName.breakables]], | ||||
|     LocationName.strawberry_6:  [[ItemName.dash_refill], | ||||
|                                  [ItemName.traffic_block]], | ||||
|     LocationName.strawberry_7:  [[ItemName.dash_refill], | ||||
|                                  [ItemName.traffic_block]], | ||||
|     LocationName.strawberry_8:  [[ItemName.traffic_block]], | ||||
|     LocationName.strawberry_9:  [[ItemName.dash_refill]], | ||||
|     LocationName.strawberry_11: [[ItemName.dash_refill], | ||||
|                                  [ItemName.traffic_block]], | ||||
|     LocationName.strawberry_12: [[ItemName.dash_refill, ItemName.double_dash_refill], | ||||
|                                  [ItemName.traffic_block, ItemName.double_dash_refill]], | ||||
|     LocationName.strawberry_13: [[ItemName.dash_refill, ItemName.breakables], | ||||
|                                  [ItemName.traffic_block, ItemName.breakables]], | ||||
|     LocationName.strawberry_14: [[ItemName.dash_refill, ItemName.feather], | ||||
|                                  [ItemName.traffic_block, ItemName.feather]], | ||||
|     LocationName.strawberry_15: [[ItemName.dash_refill, ItemName.feather], | ||||
|                                  [ItemName.traffic_block, ItemName.feather]], | ||||
|     LocationName.strawberry_16: [[ItemName.dash_refill, ItemName.feather], | ||||
|                                  [ItemName.traffic_block, ItemName.feather]], | ||||
|     LocationName.strawberry_17: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block]], | ||||
|     LocationName.strawberry_18: [[ItemName.dash_refill, ItemName.double_dash_refill], | ||||
|                                  [ItemName.traffic_block, ItemName.feather, ItemName.double_dash_refill]], | ||||
|     LocationName.strawberry_19: [[ItemName.dash_refill, ItemName.double_dash_refill, ItemName.spring], | ||||
|                                  [ItemName.traffic_block, ItemName.double_dash_refill, ItemName.feather, ItemName.spring]], | ||||
|     LocationName.strawberry_20: [[ItemName.dash_refill, ItemName.feather, ItemName.breakables], | ||||
|                                  [ItemName.traffic_block, ItemName.feather, ItemName.breakables]], | ||||
|  | ||||
|     LocationName.strawberry_21: [[ItemName.cassette, ItemName.traffic_block, ItemName.breakables]], | ||||
|     LocationName.strawberry_22: [[ItemName.cassette, ItemName.dash_refill, ItemName.breakables]], | ||||
|     LocationName.strawberry_23: [[ItemName.cassette, ItemName.dash_refill, ItemName.coin], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block, ItemName.coin]], | ||||
|     LocationName.strawberry_24: [[ItemName.cassette, ItemName.dash_refill, ItemName.traffic_block]], | ||||
|     LocationName.strawberry_25: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.double_dash_refill]], | ||||
|     LocationName.strawberry_26: [[ItemName.cassette, ItemName.dash_refill], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block]], | ||||
|     LocationName.strawberry_27: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.coin]], | ||||
|     LocationName.strawberry_28: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.coin]], | ||||
|     LocationName.strawberry_29: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin]], | ||||
|     LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.spring, ItemName.breakables]], | ||||
|  | ||||
|     LocationName.theo_1:     [[ItemName.traffic_block, ItemName.breakables]], | ||||
|     LocationName.theo_2:     [[ItemName.traffic_block, ItemName.breakables]], | ||||
|     LocationName.theo_3:     [[ItemName.traffic_block, ItemName.breakables]], | ||||
|     LocationName.badeline_1: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], | ||||
|     LocationName.badeline_2: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], | ||||
|     LocationName.badeline_3: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], | ||||
|  | ||||
|     LocationName.sign_2: [[ItemName.breakables]], | ||||
|     LocationName.sign_3: [[ItemName.dash_refill], | ||||
|                           [ItemName.traffic_block]], | ||||
|     LocationName.sign_4: [[ItemName.dash_refill, ItemName.double_dash_refill], | ||||
|                           [ItemName.dash_refill, ItemName.feather], | ||||
|                           [ItemName.traffic_block, ItemName.feather]], | ||||
|     LocationName.sign_5: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], | ||||
|  | ||||
|     LocationName.car_2: [[ItemName.breakables]], | ||||
| } | ||||
|  | ||||
| location_hard_logic: Dict[str, List[List[str]]] = { | ||||
|     LocationName.strawberry_13: [[ItemName.breakables]], | ||||
|     LocationName.strawberry_17: [[ItemName.double_dash_refill, ItemName.traffic_block]], | ||||
|     LocationName.strawberry_20: [[ItemName.breakables]], | ||||
|  | ||||
|     LocationName.strawberry_21: [[ItemName.cassette, ItemName.traffic_block, ItemName.breakables]], | ||||
|     LocationName.strawberry_22: [[ItemName.cassette]], | ||||
|     LocationName.strawberry_23: [[ItemName.cassette, ItemName.coin]], | ||||
|     LocationName.strawberry_24: [[ItemName.cassette]], | ||||
|     LocationName.strawberry_25: [[ItemName.cassette, ItemName.double_dash_refill]], | ||||
|     LocationName.strawberry_26: [[ItemName.cassette]], | ||||
|     LocationName.strawberry_27: [[ItemName.cassette]], | ||||
|     LocationName.strawberry_28: [[ItemName.cassette, ItemName.feather]], | ||||
|     LocationName.strawberry_29: [[ItemName.cassette]], | ||||
|     LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables]], | ||||
|  | ||||
|     LocationName.sign_2: [[ItemName.breakables]], | ||||
|  | ||||
|     LocationName.car_2: [[ItemName.breakables]], | ||||
| } | ||||
|  | ||||
| location_standard_moves_logic: Dict[str, List[List[str]]] = { | ||||
|     LocationName.strawberry_1:  [[ItemName.ground_dash], | ||||
|                                  [ItemName.air_dash], | ||||
|                                  [ItemName.skid_jump], | ||||
|                                  [ItemName.climb]], | ||||
|     LocationName.strawberry_2:  [[ItemName.ground_dash], | ||||
|                                  [ItemName.air_dash], | ||||
|                                  [ItemName.skid_jump], | ||||
|                                  [ItemName.climb]], | ||||
|     LocationName.strawberry_3:  [[ItemName.air_dash], | ||||
|                                  [ItemName.skid_jump]], | ||||
|     LocationName.strawberry_4:  [[ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], | ||||
|     LocationName.strawberry_5:  [[ItemName.air_dash]], | ||||
|     LocationName.strawberry_6:  [[ItemName.dash_refill, ItemName.air_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.ground_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.air_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.skid_jump], | ||||
|                                  [ItemName.traffic_block, ItemName.climb]], | ||||
|     LocationName.strawberry_7:  [[ItemName.dash_refill, ItemName.air_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.ground_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.air_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.skid_jump], | ||||
|                                  [ItemName.traffic_block, ItemName.climb]], | ||||
|     LocationName.strawberry_8:  [[ItemName.traffic_block, ItemName.ground_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.air_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.skid_jump], | ||||
|                                  [ItemName.traffic_block, ItemName.climb]], | ||||
|     LocationName.strawberry_9:  [[ItemName.dash_refill, ItemName.air_dash]], | ||||
|     LocationName.strawberry_10: [[ItemName.climb]], | ||||
|     LocationName.strawberry_11: [[ItemName.dash_refill, ItemName.air_dash, ItemName.climb], | ||||
|                                  [ItemName.traffic_block, ItemName.climb]], | ||||
|     LocationName.strawberry_12: [[ItemName.dash_refill, ItemName.double_dash_refill, ItemName.air_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.double_dash_refill, ItemName.air_dash]], | ||||
|     LocationName.strawberry_13: [[ItemName.dash_refill, ItemName.breakables, ItemName.air_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.breakables, ItemName.ground_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], | ||||
|     LocationName.strawberry_14: [[ItemName.dash_refill, ItemName.feather, ItemName.air_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.feather, ItemName.air_dash]], | ||||
|     LocationName.strawberry_15: [[ItemName.dash_refill, ItemName.feather, ItemName.air_dash, ItemName.climb], | ||||
|                                  [ItemName.traffic_block, ItemName.feather, ItemName.climb]], | ||||
|     LocationName.strawberry_16: [[ItemName.dash_refill, ItemName.feather, ItemName.air_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.feather]], | ||||
|     LocationName.strawberry_17: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.ground_dash], | ||||
|                                  [ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.air_dash], | ||||
|                                  [ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.skid_jump], | ||||
|                                  [ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.climb]], | ||||
|     LocationName.strawberry_18: [[ItemName.dash_refill, ItemName.double_dash_refill, ItemName.air_dash, ItemName.climb], | ||||
|                                  [ItemName.traffic_block, ItemName.feather, ItemName.double_dash_refill, ItemName.air_dash, ItemName.climb]], | ||||
|     LocationName.strawberry_19: [[ItemName.dash_refill, ItemName.double_dash_refill, ItemName.spring, ItemName.air_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.double_dash_refill, ItemName.feather, ItemName.spring, ItemName.air_dash]], | ||||
|     LocationName.strawberry_20: [[ItemName.dash_refill, ItemName.feather, ItemName.breakables, ItemName.air_dash], | ||||
|                                  [ItemName.traffic_block, ItemName.feather, ItemName.breakables, ItemName.air_dash]], | ||||
|  | ||||
|     LocationName.strawberry_21: [[ItemName.cassette, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], | ||||
|     LocationName.strawberry_22: [[ItemName.cassette, ItemName.dash_refill, ItemName.breakables, ItemName.air_dash]], | ||||
|     LocationName.strawberry_23: [[ItemName.cassette, ItemName.dash_refill, ItemName.coin, ItemName.air_dash, ItemName.climb], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block, ItemName.coin, ItemName.air_dash, ItemName.climb]], | ||||
|     LocationName.strawberry_24: [[ItemName.cassette, ItemName.dash_refill, ItemName.traffic_block, ItemName.air_dash]], | ||||
|     LocationName.strawberry_25: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.air_dash, ItemName.climb], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.double_dash_refill, ItemName.air_dash, ItemName.climb]], | ||||
|     LocationName.strawberry_26: [[ItemName.cassette, ItemName.dash_refill, ItemName.air_dash, ItemName.climb], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block, ItemName.air_dash, ItemName.climb]], | ||||
|     LocationName.strawberry_27: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin, ItemName.air_dash], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.coin, ItemName.air_dash]], | ||||
|     LocationName.strawberry_28: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin, ItemName.air_dash, ItemName.climb], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.coin, ItemName.air_dash, ItemName.climb]], | ||||
|     LocationName.strawberry_29: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin, ItemName.air_dash, ItemName.skid_jump]], | ||||
|     LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.spring, ItemName.breakables, ItemName.air_dash, ItemName.climb]], | ||||
|  | ||||
|     LocationName.granny_1:   [[ItemName.ground_dash], | ||||
|                               [ItemName.air_dash], | ||||
|                               [ItemName.skid_jump], | ||||
|                               [ItemName.climb]], | ||||
|     LocationName.granny_2:   [[ItemName.ground_dash], | ||||
|                               [ItemName.air_dash], | ||||
|                               [ItemName.skid_jump], | ||||
|                               [ItemName.climb]], | ||||
|     LocationName.granny_3:   [[ItemName.ground_dash], | ||||
|                               [ItemName.air_dash], | ||||
|                               [ItemName.skid_jump], | ||||
|                               [ItemName.climb]], | ||||
|     LocationName.theo_1:     [[ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], | ||||
|     LocationName.theo_2:     [[ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], | ||||
|     LocationName.theo_3:     [[ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], | ||||
|     LocationName.badeline_1: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb]], | ||||
|     LocationName.badeline_2: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb]], | ||||
|     LocationName.badeline_3: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb]], | ||||
|  | ||||
|     LocationName.sign_1: [[ItemName.ground_dash], | ||||
|                           [ItemName.air_dash], | ||||
|                           [ItemName.skid_jump], | ||||
|                           [ItemName.climb]], | ||||
|     LocationName.sign_2: [[ItemName.breakables, ItemName.ground_dash], | ||||
|                           [ItemName.breakables, ItemName.air_dash]], | ||||
|     LocationName.sign_3:  [[ItemName.dash_refill, ItemName.air_dash], | ||||
|                            [ItemName.traffic_block, ItemName.ground_dash], | ||||
|                            [ItemName.traffic_block, ItemName.air_dash], | ||||
|                            [ItemName.traffic_block, ItemName.skid_jump], | ||||
|                            [ItemName.traffic_block, ItemName.climb]], | ||||
|     LocationName.sign_4: [[ItemName.dash_refill, ItemName.double_dash_refill, ItemName.air_dash], | ||||
|                           [ItemName.dash_refill, ItemName.feather, ItemName.air_dash], | ||||
|                           [ItemName.traffic_block, ItemName.feather, ItemName.ground_dash], | ||||
|                           [ItemName.traffic_block, ItemName.feather, ItemName.air_dash], | ||||
|                           [ItemName.traffic_block, ItemName.feather, ItemName.skid_jump], | ||||
|                           [ItemName.traffic_block, ItemName.feather, ItemName.climb]], | ||||
|     LocationName.sign_5: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb]], | ||||
|  | ||||
|     LocationName.car_2: [[ItemName.breakables, ItemName.ground_dash], | ||||
|                          [ItemName.breakables, ItemName.air_dash]], | ||||
| } | ||||
|  | ||||
| location_hard_moves_logic: Dict[str, List[List[str]]] = { | ||||
|     LocationName.strawberry_3:  [[ItemName.air_dash], | ||||
|                                  [ItemName.skid_jump]], | ||||
|     LocationName.strawberry_5:  [[ItemName.ground_dash], | ||||
|                                  [ItemName.air_dash]], | ||||
|     LocationName.strawberry_8:  [[ItemName.traffic_block], | ||||
|                                  [ItemName.ground_dash, ItemName.air_dash]], | ||||
|     LocationName.strawberry_10: [[ItemName.air_dash], | ||||
|                                  [ItemName.climb]], | ||||
|     LocationName.strawberry_11: [[ItemName.ground_dash], | ||||
|                                  [ItemName.air_dash], | ||||
|                                  [ItemName.skid_jump]], | ||||
|     LocationName.strawberry_12: [[ItemName.feather], | ||||
|                                  [ItemName.ground_dash], | ||||
|                                  [ItemName.air_dash]], | ||||
|     LocationName.strawberry_13: [[ItemName.breakables, ItemName.ground_dash], | ||||
|                                  [ItemName.breakables, ItemName.air_dash]], | ||||
|     LocationName.strawberry_14: [[ItemName.feather, ItemName.air_dash], | ||||
|                                  [ItemName.air_dash, ItemName.climb]], | ||||
|     LocationName.strawberry_15: [[ItemName.feather], | ||||
|                                  [ItemName.ground_dash, ItemName.air_dash]], | ||||
|     LocationName.strawberry_17: [[ItemName.double_dash_refill, ItemName.traffic_block]], | ||||
|     LocationName.strawberry_18: [[ItemName.air_dash, ItemName.climb], | ||||
|                                  [ItemName.double_dash_refill, ItemName.air_dash]], | ||||
|     LocationName.strawberry_19: [[ItemName.air_dash, ItemName.skid_jump], | ||||
|                                  [ItemName.double_dash_refill, ItemName.spring, ItemName.air_dash], | ||||
|                                  [ItemName.spring, ItemName.ground_dash, ItemName.air_dash]], | ||||
|     LocationName.strawberry_20: [[ItemName.breakables, ItemName.air_dash]], | ||||
|  | ||||
|     LocationName.strawberry_21: [[ItemName.cassette, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], | ||||
|     LocationName.strawberry_22: [[ItemName.cassette, ItemName.ground_dash, ItemName.air_dash], | ||||
|                                  [ItemName.cassette, ItemName.dash_refill, ItemName.air_dash]], | ||||
|     LocationName.strawberry_23: [[ItemName.cassette, ItemName.coin, ItemName.air_dash]], | ||||
|     LocationName.strawberry_24: [[ItemName.cassette, ItemName.ground_dash, ItemName.air_dash], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block, ItemName.air_dash]], | ||||
|     LocationName.strawberry_25: [[ItemName.cassette, ItemName.double_dash_refill, ItemName.air_dash, ItemName.climb]], | ||||
|     LocationName.strawberry_26: [[ItemName.cassette, ItemName.ground_dash], | ||||
|                                  [ItemName.cassette, ItemName.air_dash]], | ||||
|     LocationName.strawberry_27: [[ItemName.cassette, ItemName.air_dash, ItemName.skid_jump], | ||||
|                                  [ItemName.cassette, ItemName.traffic_block, ItemName.coin, ItemName.air_dash], | ||||
|                                  [ItemName.cassette, ItemName.coin, ItemName.ground_dash], | ||||
|                                  [ItemName.cassette, ItemName.feather, ItemName.coin, ItemName.air_dash]], | ||||
|     LocationName.strawberry_28: [[ItemName.cassette, ItemName.feather, ItemName.air_dash], | ||||
|                                  [ItemName.cassette, ItemName.feather, ItemName.climb]], | ||||
|     LocationName.strawberry_29: [[ItemName.cassette, ItemName.dash_refill, ItemName.air_dash, ItemName.skid_jump], | ||||
|                                  [ItemName.cassette, ItemName.ground_dash, ItemName.air_dash]], | ||||
|     LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.ground_dash, ItemName.air_dash, ItemName.climb, ItemName.skid_jump], | ||||
|                                  [ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.feather, ItemName.air_dash, ItemName.climb, ItemName.skid_jump], | ||||
|                                  [ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.spring, ItemName.ground_dash, ItemName.air_dash, ItemName.climb], | ||||
|                                  [ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.spring, ItemName.feather, ItemName.air_dash, ItemName.climb]], | ||||
|  | ||||
|     LocationName.badeline_1: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb], | ||||
|                               [ItemName.traffic_block, ItemName.air_dash, ItemName.skid_jump], | ||||
|                               [ItemName.ground_dash, ItemName.air_dash, ItemName.skid_jump], | ||||
|                               [ItemName.feather, ItemName.traffic_block, ItemName.air_dash], | ||||
|                               [ItemName.traffic_block, ItemName.ground_dash, ItemName.air_dash]], | ||||
|     LocationName.badeline_2: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb], | ||||
|                               [ItemName.traffic_block, ItemName.air_dash, ItemName.skid_jump], | ||||
|                               [ItemName.ground_dash, ItemName.air_dash, ItemName.skid_jump], | ||||
|                               [ItemName.feather, ItemName.traffic_block, ItemName.air_dash], | ||||
|                               [ItemName.traffic_block, ItemName.ground_dash, ItemName.air_dash]], | ||||
|     LocationName.badeline_3: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb], | ||||
|                               [ItemName.traffic_block, ItemName.air_dash, ItemName.skid_jump], | ||||
|                               [ItemName.ground_dash, ItemName.air_dash, ItemName.skid_jump], | ||||
|                               [ItemName.feather, ItemName.traffic_block, ItemName.air_dash], | ||||
|                               [ItemName.traffic_block, ItemName.ground_dash, ItemName.air_dash]], | ||||
|  | ||||
|     LocationName.sign_2: [[ItemName.breakables, ItemName.ground_dash], | ||||
|                           [ItemName.breakables, ItemName.air_dash]], | ||||
|     LocationName.sign_5: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb], | ||||
|                           [ItemName.traffic_block, ItemName.air_dash, ItemName.skid_jump], | ||||
|                           [ItemName.ground_dash, ItemName.air_dash, ItemName.skid_jump], | ||||
|                           [ItemName.feather, ItemName.traffic_block, ItemName.air_dash], | ||||
|                           [ItemName.traffic_block, ItemName.ground_dash, ItemName.air_dash]], | ||||
|  | ||||
|     LocationName.car_2: [[ItemName.breakables, ItemName.ground_dash], | ||||
|                          [ItemName.breakables, ItemName.air_dash]], | ||||
| } | ||||
|  | ||||
|  | ||||
| def location_rule(state: CollectionState, world: Celeste64World, loc: str) -> bool: | ||||
|  | ||||
|     if loc not in world.active_logic_mapping: | ||||
|         return True | ||||
|  | ||||
|     for possible_access in world.active_logic_mapping[loc]: | ||||
|         if state.has_all(possible_access, world.player): | ||||
|             return True | ||||
|  | ||||
|     return False | ||||
|  | ||||
| def goal_rule(state: CollectionState, world: Celeste64World) -> bool: | ||||
|     if not state.has(ItemName.strawberry, world.player, world.strawberries_required): | ||||
|         return False | ||||
|  | ||||
|     for possible_access in world.goal_logic_mapping: | ||||
|         if state.has_all(possible_access, world.player): | ||||
|             return True | ||||
|  | ||||
|     return False | ||||
|   | ||||
| @@ -1,10 +1,12 @@ | ||||
| from typing import List | ||||
| from copy import deepcopy | ||||
| from typing import Dict, List | ||||
|  | ||||
| from BaseClasses import ItemClassification, Region, Tutorial | ||||
| from BaseClasses import ItemClassification, Location, Region, Tutorial | ||||
| from worlds.AutoWorld import WebWorld, World | ||||
| from .Items import Celeste64Item, item_data_table, item_table | ||||
| from .Locations import Celeste64Location, location_data_table, location_table | ||||
| from .Names import ItemName | ||||
| from .Items import Celeste64Item, unlockable_item_data_table, move_item_data_table, item_data_table, item_table | ||||
| from .Locations import Celeste64Location, strawberry_location_data_table, friend_location_data_table,\ | ||||
|                                           sign_location_data_table, car_location_data_table, location_table | ||||
| from .Names import ItemName, LocationName | ||||
| from .Options import Celeste64Options | ||||
|  | ||||
|  | ||||
| @@ -27,6 +29,7 @@ class Celeste64World(World): | ||||
|     """Relive the magic of Celeste Mountain alongside Madeline in this small, heartfelt 3D platformer. | ||||
|     Created in a week(ish) by the Celeste team to celebrate the game’s sixth anniversary 🍓✨""" | ||||
|  | ||||
|     # Class Data | ||||
|     game = "Celeste 64" | ||||
|     web = Celeste64WebWorld() | ||||
|     options_dataclass = Celeste64Options | ||||
| @@ -34,13 +37,18 @@ class Celeste64World(World): | ||||
|     location_name_to_id = location_table | ||||
|     item_name_to_id = item_table | ||||
|  | ||||
|     # Instance Data | ||||
|     strawberries_required: int | ||||
|     active_logic_mapping: Dict[str, List[List[str]]] | ||||
|     goal_logic_mapping: Dict[str, List[List[str]]] | ||||
|  | ||||
|  | ||||
|     def create_item(self, name: str) -> Celeste64Item: | ||||
|         # Only make required amount of strawberries be Progression | ||||
|         if getattr(self, "options", None) and name == ItemName.strawberry: | ||||
|         if getattr(self, "strawberries_required", None) and name == ItemName.strawberry: | ||||
|             classification: ItemClassification = ItemClassification.filler | ||||
|             self.prog_strawberries = getattr(self, "prog_strawberries", 0) | ||||
|             if self.prog_strawberries < self.options.strawberries_required.value: | ||||
|             if self.prog_strawberries < self.strawberries_required: | ||||
|                 classification = ItemClassification.progression_skip_balancing | ||||
|                 self.prog_strawberries += 1 | ||||
|  | ||||
| @@ -51,9 +59,48 @@ class Celeste64World(World): | ||||
|     def create_items(self) -> None: | ||||
|         item_pool: List[Celeste64Item] = [] | ||||
|  | ||||
|         item_pool += [self.create_item(name) for name in item_data_table.keys()] | ||||
|         location_count: int = 30 | ||||
|  | ||||
|         item_pool += [self.create_item(ItemName.strawberry) for _ in range(21)] | ||||
|         if self.options.friendsanity: | ||||
|             location_count += 9 | ||||
|  | ||||
|         if self.options.signsanity: | ||||
|             location_count += 5 | ||||
|  | ||||
|         if self.options.carsanity: | ||||
|             location_count += 2 | ||||
|  | ||||
|         item_pool += [self.create_item(name) | ||||
|                       for name in unlockable_item_data_table.keys() | ||||
|                       if name not in self.options.start_inventory] | ||||
|  | ||||
|         if self.options.move_shuffle: | ||||
|             move_items_for_itempool: List[str] = deepcopy(list(move_item_data_table.keys())) | ||||
|  | ||||
|             if self.options.logic_difficulty == "standard": | ||||
|                 # If the start_inventory already includes a move, don't worry about giving it one | ||||
|                 if not [move for move in move_items_for_itempool if move in self.options.start_inventory]: | ||||
|                     chosen_start_move = self.random.choice(move_items_for_itempool) | ||||
|                     move_items_for_itempool.remove(chosen_start_move) | ||||
|  | ||||
|                     if self.options.carsanity: | ||||
|                         intro_car_loc: Location = self.multiworld.get_location(LocationName.car_1, self.player) | ||||
|                         intro_car_loc.place_locked_item(self.create_item(chosen_start_move)) | ||||
|                         location_count -= 1 | ||||
|                     else: | ||||
|                         self.multiworld.push_precollected(self.create_item(chosen_start_move)) | ||||
|  | ||||
|             item_pool += [self.create_item(name) | ||||
|                           for name in move_items_for_itempool | ||||
|                           if name not in self.options.start_inventory] | ||||
|  | ||||
|         real_total_strawberries: int = min(self.options.total_strawberries.value, location_count - len(item_pool)) | ||||
|         self.strawberries_required = int(real_total_strawberries * (self.options.strawberries_required_percentage / 100)) | ||||
|  | ||||
|         item_pool += [self.create_item(ItemName.strawberry) for _ in range(real_total_strawberries)] | ||||
|  | ||||
|         filler_item_count: int = location_count - len(item_pool) | ||||
|         item_pool += [self.create_item(ItemName.raspberry) for _ in range(filler_item_count)] | ||||
|  | ||||
|         self.multiworld.itempool += item_pool | ||||
|  | ||||
| @@ -69,14 +116,33 @@ class Celeste64World(World): | ||||
|         for region_name, region_data in region_data_table.items(): | ||||
|             region = self.multiworld.get_region(region_name, self.player) | ||||
|             region.add_locations({ | ||||
|                 location_name: location_data.address for location_name, location_data in location_data_table.items() | ||||
|                 location_name: location_data.address for location_name, location_data in strawberry_location_data_table.items() | ||||
|                 if location_data.region == region_name | ||||
|             }, Celeste64Location) | ||||
|  | ||||
|             if self.options.friendsanity: | ||||
|                 region.add_locations({ | ||||
|                     location_name: location_data.address for location_name, location_data in friend_location_data_table.items() | ||||
|                     if location_data.region == region_name | ||||
|                 }, Celeste64Location) | ||||
|  | ||||
|             if self.options.signsanity: | ||||
|                 region.add_locations({ | ||||
|                     location_name: location_data.address for location_name, location_data in sign_location_data_table.items() | ||||
|                     if location_data.region == region_name | ||||
|                 }, Celeste64Location) | ||||
|  | ||||
|             if self.options.carsanity: | ||||
|                 region.add_locations({ | ||||
|                     location_name: location_data.address for location_name, location_data in car_location_data_table.items() | ||||
|                     if location_data.region == region_name | ||||
|                 }, Celeste64Location) | ||||
|  | ||||
|             region.add_exits(region_data_table[region_name].connecting_regions) | ||||
|  | ||||
|  | ||||
|     def get_filler_item_name(self) -> str: | ||||
|         return ItemName.strawberry | ||||
|         return ItemName.raspberry | ||||
|  | ||||
|  | ||||
|     def set_rules(self) -> None: | ||||
| @@ -88,5 +154,12 @@ class Celeste64World(World): | ||||
|         return { | ||||
|             "death_link": self.options.death_link.value, | ||||
|             "death_link_amnesty": self.options.death_link_amnesty.value, | ||||
|             "strawberries_required": self.options.strawberries_required.value | ||||
|             "strawberries_required": self.strawberries_required, | ||||
|             "move_shuffle": self.options.move_shuffle.value, | ||||
|             "friendsanity": self.options.friendsanity.value, | ||||
|             "signsanity": self.options.signsanity.value, | ||||
|             "carsanity": self.options.carsanity.value, | ||||
|             "badeline_chaser_source": self.options.badeline_chaser_source.value, | ||||
|             "badeline_chaser_frequency": self.options.badeline_chaser_frequency.value, | ||||
|             "badeline_chaser_speed": self.options.badeline_chaser_speed.value, | ||||
|         } | ||||
|   | ||||
| @@ -3,6 +3,11 @@ | ||||
| ## Required Software | ||||
| - Archipelago Build of Celeste 64 from: [Celeste 64 Archipelago Releases Page](https://github.com/PoryGoneDev/Celeste64/releases/) | ||||
|  | ||||
| ## Optional Software | ||||
| - Celeste 64 Tracker | ||||
| 	- PopTracker from: [PopTracker Releases Page](https://github.com/black-sliver/PopTracker/releases/) | ||||
| 	- Celeste 64 Archipelago PopTracker pack from: [Celeste 64 AP Tracker Releases Page](https://github.com/PoryGone/Celeste-64-AP-Tracker/releases/) | ||||
|  | ||||
| ## Installation Procedures (Windows) | ||||
|  | ||||
| 1. Download the above release and extract it. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 PoryGone
					PoryGone