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:
parent
7e61211365
commit
5fae1c087e
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue