diff options
| -rw-r--r-- | apworld/__init__.py | 1 | ||||
| -rw-r--r-- | apworld/client/manager.gd | 2 | ||||
| -rw-r--r-- | apworld/client/maps/control_center.gd | 33 | ||||
| -rw-r--r-- | apworld/options.py | 12 | ||||
| -rw-r--r-- | apworld/player_logic.py | 8 | ||||
| -rw-r--r-- | apworld/regions.py | 4 |
6 files changed, 59 insertions, 1 deletions
| diff --git a/apworld/__init__.py b/apworld/__init__.py index a80156c..6b5338e 100644 --- a/apworld/__init__.py +++ b/apworld/__init__.py | |||
| @@ -167,6 +167,7 @@ class Lingo2World(World): | |||
| 167 | 167 | ||
| 168 | slot_data: dict[str, object] = { | 168 | slot_data: dict[str, object] = { |
| 169 | **self.options.as_dict(*slot_options), | 169 | **self.options.as_dict(*slot_options), |
| 170 | "custom_mint_ending": self.player_logic.custom_mint_ending or "", | ||
| 170 | "rte": [self.static_logic.objects.maps[map_id].name for map_id in self.player_logic.rte_mapping], | 171 | "rte": [self.static_logic.objects.maps[map_id].name for map_id in self.player_logic.rte_mapping], |
| 171 | "seed": self.random.randint(0, 1000000), | 172 | "seed": self.random.randint(0, 1000000), |
| 172 | "version": self.static_logic.get_data_version(), | 173 | "version": self.static_logic.get_data_version(), |
| diff --git a/apworld/client/manager.gd b/apworld/client/manager.gd index e259708..f10a0b7 100644 --- a/apworld/client/manager.gd +++ b/apworld/client/manager.gd | |||
| @@ -67,6 +67,7 @@ const kEndingNameByVictoryValue = { | |||
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | var apworld_version = [0, 0, 0] | 69 | var apworld_version = [0, 0, 0] |
| 70 | var custom_mint_ending = "" | ||
| 70 | var cyan_door_behavior = kCYAN_DOOR_BEHAVIOR_H2 | 71 | var cyan_door_behavior = kCYAN_DOOR_BEHAVIOR_H2 |
| 71 | var daedalus_only = false | 72 | var daedalus_only = false |
| 72 | var daedalus_roof_access = false | 73 | var daedalus_roof_access = false |
| @@ -478,6 +479,7 @@ func _client_connected(slot_data): | |||
| 478 | _last_new_item = localdata[0] | 479 | _last_new_item = localdata[0] |
| 479 | 480 | ||
| 480 | # Read slot data. | 481 | # Read slot data. |
| 482 | custom_mint_ending = slot_data.get("custom_mint_ending", "") | ||
| 481 | cyan_door_behavior = int(slot_data.get("cyan_door_behavior", 0)) | 483 | cyan_door_behavior = int(slot_data.get("cyan_door_behavior", 0)) |
| 482 | daedalus_only = bool(slot_data.get("daedalus_only", false)) | 484 | daedalus_only = bool(slot_data.get("daedalus_only", false)) |
| 483 | daedalus_roof_access = bool(slot_data.get("daedalus_roof_access", false)) | 485 | daedalus_roof_access = bool(slot_data.get("daedalus_roof_access", false)) |
| diff --git a/apworld/client/maps/control_center.gd b/apworld/client/maps/control_center.gd index 1fecc7b..8e919ab 100644 --- a/apworld/client/maps/control_center.gd +++ b/apworld/client/maps/control_center.gd | |||
| @@ -96,6 +96,39 @@ func on_map_load(root): | |||
| 96 | sign2.text = "Masteries: %d/%d" % [mastery_count, ap.masteries_requirement] | 96 | sign2.text = "Masteries: %d/%d" % [mastery_count, ap.masteries_requirement] |
| 97 | root.get_node("/root/scene").add_child.call_deferred(sign2) | 97 | root.get_node("/root/scene").add_child.call_deferred(sign2) |
| 98 | 98 | ||
| 99 | # Handle custom Mint Ending. | ||
| 100 | if ap.custom_mint_ending != "": | ||
| 101 | var panel_prefab = preload("res://objects/nodes/panel.tscn") | ||
| 102 | var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn") | ||
| 103 | |||
| 104 | var mint_ending = root.get_node("/root/scene/Components/Endings/mint_ending") | ||
| 105 | |||
| 106 | var mint_panel = panel_prefab.instantiate() | ||
| 107 | mint_panel.name = "mint_panel" | ||
| 108 | mint_panel.clue = ap.custom_mint_ending | ||
| 109 | mint_panel.symbol = "" | ||
| 110 | mint_panel.answer = ap.custom_mint_ending | ||
| 111 | mint_panel.position = Vector3(-63, 3, -29) | ||
| 112 | mint_panel.rotation_degrees = Vector3(-45, 90, 0) | ||
| 113 | root.get_node("/root/scene").add_child.call_deferred(mint_panel) | ||
| 114 | |||
| 115 | var mint_tpl = tpl_prefab.instantiate() | ||
| 116 | mint_tpl.name = "mint_tpl" | ||
| 117 | mint_tpl.teleport_point = mint_ending.position | ||
| 118 | mint_tpl.teleport_rotate = mint_ending.rotation_degrees | ||
| 119 | mint_tpl.target_path = mint_ending | ||
| 120 | mint_tpl.senders.append(NodePath("/root/scene/mint_panel")) | ||
| 121 | root.get_node("/root/scene").add_child.call_deferred(mint_tpl) | ||
| 122 | |||
| 123 | var mint_tpl2 = tpl_prefab.instantiate() | ||
| 124 | mint_tpl2.name = "mint_tpl2" | ||
| 125 | mint_tpl2.teleport_point = Vector3(0, -1000, 0) | ||
| 126 | mint_tpl2.target_path = mint_panel | ||
| 127 | mint_tpl2.senders.append(NodePath("/root/scene/mint_panel")) | ||
| 128 | root.get_node("/root/scene").add_child.call_deferred(mint_tpl2) | ||
| 129 | |||
| 130 | mint_ending.position.y = -1000 | ||
| 131 | |||
| 99 | 132 | ||
| 100 | func _set_up_mastery_listener(root, name): | 133 | func _set_up_mastery_listener(root, name): |
| 101 | var prefab = preload("res://objects/nodes/listeners/unlockReaderListener.tscn") | 134 | var prefab = preload("res://objects/nodes/listeners/unlockReaderListener.tscn") |
| diff --git a/apworld/options.py b/apworld/options.py index fb159e1..c1eab33 100644 --- a/apworld/options.py +++ b/apworld/options.py | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | from dataclasses import dataclass | 1 | from dataclasses import dataclass |
| 2 | 2 | ||
| 3 | from Options import PerGameCommonOptions, Toggle, Choice, DefaultOnToggle, Range, OptionSet | 3 | from Options import PerGameCommonOptions, Toggle, Choice, DefaultOnToggle, Range, OptionSet, FreeText |
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | class ShuffleDoors(DefaultOnToggle): | 6 | class ShuffleDoors(DefaultOnToggle): |
| @@ -178,6 +178,15 @@ class DaedalusRoofAccess(Toggle): | |||
| 178 | display_name = "Allow Daedalus Roof Access" | 178 | display_name = "Allow Daedalus Roof Access" |
| 179 | 179 | ||
| 180 | 180 | ||
| 181 | class CustomMintEnding(FreeText): | ||
| 182 | """ | ||
| 183 | If not blank, this will add a new panel that must be solved before collecting Mint Ending (EXIT in the Control | ||
| 184 | Center). The panel will only require typing the text provided for this option, which means the choice of letters | ||
| 185 | here has an impact on logic. | ||
| 186 | """ | ||
| 187 | display_name = "Custom Mint Ending" | ||
| 188 | |||
| 189 | |||
| 181 | class StrictPurpleEnding(DefaultOnToggle): | 190 | class StrictPurpleEnding(DefaultOnToggle): |
| 182 | """ | 191 | """ |
| 183 | If enabled, the player will be required to have all purple (level 1) letters in order to get Purple Ending. | 192 | If enabled, the player will be required to have all purple (level 1) letters in order to get Purple Ending. |
| @@ -280,6 +289,7 @@ class Lingo2Options(PerGameCommonOptions): | |||
| 280 | enable_gift_maps: EnableGiftMaps | 289 | enable_gift_maps: EnableGiftMaps |
| 281 | daedalus_only: DaedalusOnly | 290 | daedalus_only: DaedalusOnly |
| 282 | daedalus_roof_access: DaedalusRoofAccess | 291 | daedalus_roof_access: DaedalusRoofAccess |
| 292 | custom_mint_ending: CustomMintEnding | ||
| 283 | strict_purple_ending: StrictPurpleEnding | 293 | strict_purple_ending: StrictPurpleEnding |
| 284 | strict_cyan_ending: StrictCyanEnding | 294 | strict_cyan_ending: StrictCyanEnding |
| 285 | victory_condition: VictoryCondition | 295 | victory_condition: VictoryCondition |
| diff --git a/apworld/player_logic.py b/apworld/player_logic.py index 7bfd49f..ea74266 100644 --- a/apworld/player_logic.py +++ b/apworld/player_logic.py | |||
| @@ -223,6 +223,7 @@ class Lingo2PlayerLogic: | |||
| 223 | double_letter_amount: dict[str, int] | 223 | double_letter_amount: dict[str, int] |
| 224 | goal_room_id: int | 224 | goal_room_id: int |
| 225 | rte_mapping: list[int] | 225 | rte_mapping: list[int] |
| 226 | custom_mint_ending: str | None | ||
| 226 | 227 | ||
| 227 | def __init__(self, world: "Lingo2World"): | 228 | def __init__(self, world: "Lingo2World"): |
| 228 | self.world = world | 229 | self.world = world |
| @@ -237,6 +238,7 @@ class Lingo2PlayerLogic: | |||
| 237 | self.real_items = list() | 238 | self.real_items = list() |
| 238 | self.starting_items = list() | 239 | self.starting_items = list() |
| 239 | self.double_letter_amount = dict() | 240 | self.double_letter_amount = dict() |
| 241 | self.custom_mint_ending = None | ||
| 240 | 242 | ||
| 241 | def should_shuffle_map(game_map) -> bool | set[int]: | 243 | def should_shuffle_map(game_map) -> bool | set[int]: |
| 242 | if world.options.daedalus_only: | 244 | if world.options.daedalus_only: |
| @@ -302,6 +304,12 @@ class Lingo2PlayerLogic: | |||
| 302 | raise OptionError(f"When Restrict Letter Placements is enabled and Shuffle Letters is set to Progressive, " | 304 | raise OptionError(f"When Restrict Letter Placements is enabled and Shuffle Letters is set to Progressive, " |
| 303 | f"both Shuffle Doors and Shuffle Symbols must be disabled (Player {world.player}).") | 305 | f"both Shuffle Doors and Shuffle Symbols must be disabled (Player {world.player}).") |
| 304 | 306 | ||
| 307 | if world.options.custom_mint_ending.value != "": | ||
| 308 | self.custom_mint_ending = ''.join(filter(str.isalpha, world.options.custom_mint_ending.value)).lower() | ||
| 309 | |||
| 310 | if len(self.custom_mint_ending) > 52: | ||
| 311 | raise OptionError(f"Custom Mint Ending should not be greater than 52 letters (Player {world.player}).") | ||
| 312 | |||
| 305 | maximum_masteries = 13 + len(world.options.enable_gift_maps.value) | 313 | maximum_masteries = 13 + len(world.options.enable_gift_maps.value) |
| 306 | if world.options.enable_icarus: | 314 | if world.options.enable_icarus: |
| 307 | maximum_masteries += 1 | 315 | maximum_masteries += 1 |
| diff --git a/apworld/regions.py b/apworld/regions.py index 076c143..3996153 100644 --- a/apworld/regions.py +++ b/apworld/regions.py | |||
| @@ -141,6 +141,10 @@ def create_regions(world: "Lingo2World"): | |||
| 141 | if connection.HasField("cyan_ending") and connection.cyan_ending and world.options.strict_cyan_ending: | 141 | if connection.HasField("cyan_ending") and connection.cyan_ending and world.options.strict_cyan_ending: |
| 142 | world.player_logic.add_solution_reqs(reqs, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz") | 142 | world.player_logic.add_solution_reqs(reqs, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz") |
| 143 | 143 | ||
| 144 | if (connection.HasField("mint_ending") and connection.mint_ending | ||
| 145 | and world.player_logic.custom_mint_ending is not None): | ||
| 146 | world.player_logic.add_solution_reqs(reqs, world.player_logic.custom_mint_ending) | ||
| 147 | |||
| 144 | reqs.simplify() | 148 | reqs.simplify() |
| 145 | reqs.remove_room(from_region) | 149 | reqs.remove_room(from_region) |
| 146 | 150 | ||
