Landstalker: Fix issues on generation (#4345)
This commit is contained in:
parent
78637c96a7
commit
5578ccd578
|
@ -0,0 +1,28 @@
|
|||
|
||||
BASE_ITEM_ID = 4000
|
||||
|
||||
BASE_LOCATION_ID = 4000
|
||||
BASE_GROUND_LOCATION_ID = BASE_LOCATION_ID + 256
|
||||
BASE_SHOP_LOCATION_ID = BASE_GROUND_LOCATION_ID + 30
|
||||
BASE_REWARD_LOCATION_ID = BASE_SHOP_LOCATION_ID + 50
|
||||
|
||||
ENDGAME_REGIONS = [
|
||||
"kazalt",
|
||||
"king_nole_labyrinth_pre_door",
|
||||
"king_nole_labyrinth_post_door",
|
||||
"king_nole_labyrinth_exterior",
|
||||
"king_nole_labyrinth_fall_from_exterior",
|
||||
"king_nole_labyrinth_path_to_palace",
|
||||
"king_nole_labyrinth_raft_entrance",
|
||||
"king_nole_labyrinth_raft",
|
||||
"king_nole_labyrinth_sacred_tree",
|
||||
"king_nole_palace"
|
||||
]
|
||||
|
||||
ENDGAME_PROGRESSION_ITEMS = [
|
||||
"Gola's Nail",
|
||||
"Gola's Fang",
|
||||
"Gola's Horn",
|
||||
"Logs",
|
||||
"Snow Spikes"
|
||||
]
|
|
@ -45,7 +45,7 @@ def generate_lithograph_hint(world: "LandstalkerWorld"):
|
|||
words.append(item.name.split(" ")[0].upper())
|
||||
if item.location.player != world.player:
|
||||
# Add player name if it's not in our own world
|
||||
player_name = world.multiworld.get_player_name(world.player)
|
||||
player_name = world.multiworld.get_player_name(item.location.player)
|
||||
words.append(player_name.upper())
|
||||
world.random.shuffle(words)
|
||||
hint_text += " ".join(words) + "\n"
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
from typing import Dict, List, NamedTuple
|
||||
|
||||
from BaseClasses import Item, ItemClassification
|
||||
|
||||
BASE_ITEM_ID = 4000
|
||||
from .Constants import BASE_ITEM_ID
|
||||
|
||||
|
||||
class LandstalkerItem(Item):
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
from typing import Dict, Optional
|
||||
|
||||
from BaseClasses import Location, ItemClassification, Item
|
||||
from .Constants import *
|
||||
from .Regions import LandstalkerRegion
|
||||
from .data.item_source import ITEM_SOURCES_JSON
|
||||
from .data.world_path import WORLD_PATHS_JSON
|
||||
|
||||
BASE_LOCATION_ID = 4000
|
||||
BASE_GROUND_LOCATION_ID = BASE_LOCATION_ID + 256
|
||||
BASE_SHOP_LOCATION_ID = BASE_GROUND_LOCATION_ID + 30
|
||||
BASE_REWARD_LOCATION_ID = BASE_SHOP_LOCATION_ID + 50
|
||||
|
||||
|
||||
class LandstalkerLocation(Location):
|
||||
game: str = "Landstalker - The Treasures of King Nole"
|
||||
|
@ -21,10 +17,14 @@ class LandstalkerLocation(Location):
|
|||
self.type_string = type_string
|
||||
|
||||
|
||||
def create_locations(player: int, regions_table: Dict[str, LandstalkerRegion], name_to_id_table: Dict[str, int]):
|
||||
def create_locations(player: int, regions_table: Dict[str, LandstalkerRegion],
|
||||
name_to_id_table: Dict[str, int], reach_kazalt_goal: bool):
|
||||
# Create real locations from the data inside the corresponding JSON file
|
||||
for data in ITEM_SOURCES_JSON:
|
||||
region_id = data["nodeId"]
|
||||
# If "Reach Kazalt" goal is enabled and location is beyond Kazalt, don't create it
|
||||
if reach_kazalt_goal and region_id in ENDGAME_REGIONS:
|
||||
continue
|
||||
region = regions_table[region_id]
|
||||
new_location = LandstalkerLocation(player, data["name"], name_to_id_table[data["name"]], region, data["type"])
|
||||
region.locations.append(new_location)
|
||||
|
@ -32,6 +32,10 @@ def create_locations(player: int, regions_table: Dict[str, LandstalkerRegion], n
|
|||
# Create fake event locations that will be used to determine if some key regions has been visited
|
||||
regions_with_entrance_checks = []
|
||||
for data in WORLD_PATHS_JSON:
|
||||
# If "Reach Kazalt" goal is enabled and region is beyond Kazalt, don't create any event for it since it would
|
||||
# be useless anyway
|
||||
if reach_kazalt_goal and data["fromId"] in ENDGAME_REGIONS:
|
||||
continue
|
||||
if "requiredNodes" in data:
|
||||
regions_with_entrance_checks.extend([region_id for region_id in data["requiredNodes"]])
|
||||
regions_with_entrance_checks = sorted(set(regions_with_entrance_checks))
|
||||
|
|
|
@ -2,6 +2,7 @@ from typing import ClassVar, Set
|
|||
|
||||
from BaseClasses import LocationProgressType, Tutorial
|
||||
from worlds.AutoWorld import WebWorld, World
|
||||
from .Constants import *
|
||||
from .Hints import *
|
||||
from .Items import *
|
||||
from .Locations import *
|
||||
|
@ -87,7 +88,8 @@ class LandstalkerWorld(World):
|
|||
|
||||
def create_regions(self):
|
||||
self.regions_table = Regions.create_regions(self)
|
||||
Locations.create_locations(self.player, self.regions_table, self.location_name_to_id)
|
||||
Locations.create_locations(self.player, self.regions_table, self.location_name_to_id,
|
||||
self.options.goal == "reach_kazalt")
|
||||
self.create_teleportation_trees()
|
||||
|
||||
def create_item(self, name: str, classification_override: Optional[ItemClassification] = None) -> LandstalkerItem:
|
||||
|
@ -109,7 +111,16 @@ class LandstalkerWorld(World):
|
|||
# If item is an armor and progressive armors are enabled, transform it into a progressive armor item
|
||||
if self.options.progressive_armors and "Breast" in name:
|
||||
name = "Progressive Armor"
|
||||
item_pool += [self.create_item(name) for _ in range(data.quantity)]
|
||||
|
||||
qty = data.quantity
|
||||
if self.options.goal == "reach_kazalt":
|
||||
# In "Reach Kazalt" goal, remove all endgame progression items that would be useless anyway
|
||||
if name in ENDGAME_PROGRESSION_ITEMS:
|
||||
continue
|
||||
# Also reduce quantities for most filler items to let space for more EkeEke (see end of function)
|
||||
if data.classification == ItemClassification.filler:
|
||||
qty = int(qty * 0.8)
|
||||
item_pool += [self.create_item(name) for _ in range(qty)]
|
||||
|
||||
# If the appropriate setting is on, place one EkeEke in one shop in every town in the game
|
||||
if self.options.ensure_ekeeke_in_shops:
|
||||
|
@ -120,9 +131,10 @@ class LandstalkerWorld(World):
|
|||
"Mercator: Shop item #1",
|
||||
"Verla: Shop item #1",
|
||||
"Destel: Inn item",
|
||||
"Route to Lake Shrine: Greedly's shop item #1",
|
||||
"Kazalt: Shop item #1"
|
||||
"Route to Lake Shrine: Greedly's shop item #1"
|
||||
]
|
||||
if self.options.goal != "reach_kazalt":
|
||||
shops_to_fill.append("Kazalt: Shop item #1")
|
||||
for location_name in shops_to_fill:
|
||||
self.multiworld.get_location(location_name, self.player).place_locked_item(self.create_item("EkeEke"))
|
||||
|
||||
|
|
|
@ -73,6 +73,22 @@ WORLD_NODES_JSON = {
|
|||
"between Gumi and Ryuma"
|
||||
]
|
||||
},
|
||||
"tibor_tree": {
|
||||
"name": "Route from Gumi to Ryuma (Tibor tree)",
|
||||
"hints": [
|
||||
"on a route",
|
||||
"in a region inhabited by bears",
|
||||
"between Gumi and Ryuma"
|
||||
]
|
||||
},
|
||||
"mercator_gate_tree": {
|
||||
"name": "Route from Gumi to Ryuma (Mercator gate tree)",
|
||||
"hints": [
|
||||
"on a route",
|
||||
"in a region inhabited by bears",
|
||||
"between Gumi and Ryuma"
|
||||
]
|
||||
},
|
||||
"tibor": {
|
||||
"name": "Tibor",
|
||||
"hints": [
|
||||
|
@ -223,6 +239,13 @@ WORLD_NODES_JSON = {
|
|||
"in the infamous Greenmaze"
|
||||
]
|
||||
},
|
||||
"greenmaze_post_whistle_tree": {
|
||||
"name": "Greenmaze (post-whistle tree)",
|
||||
"hints": [
|
||||
"among the trees",
|
||||
"in the infamous Greenmaze"
|
||||
]
|
||||
},
|
||||
"verla_shore": {
|
||||
"name": "Verla shore",
|
||||
"hints": [
|
||||
|
@ -230,6 +253,13 @@ WORLD_NODES_JSON = {
|
|||
"near the town of Verla"
|
||||
]
|
||||
},
|
||||
"verla_shore_tree": {
|
||||
"name": "Verla shore tree",
|
||||
"hints": [
|
||||
"on a route",
|
||||
"near the town of Verla"
|
||||
]
|
||||
},
|
||||
"verla_shore_cliff": {
|
||||
"name": "Verla shore cliff (accessible from Verla Mines)",
|
||||
"hints": [
|
||||
|
@ -326,6 +356,12 @@ WORLD_NODES_JSON = {
|
|||
"in a mountainous area"
|
||||
]
|
||||
},
|
||||
"mountainous_area_tree": {
|
||||
"name": "Mountainous Area tree",
|
||||
"hints": [
|
||||
"in a mountainous area"
|
||||
]
|
||||
},
|
||||
"king_nole_cave": {
|
||||
"name": "King Nole's Cave",
|
||||
"hints": [
|
||||
|
|
|
@ -54,6 +54,16 @@ WORLD_PATHS_JSON = [
|
|||
"toId": "ryuma",
|
||||
"twoWay": True
|
||||
},
|
||||
{
|
||||
"fromId": "route_gumi_ryuma",
|
||||
"toId": "tibor_tree",
|
||||
"twoWay": True
|
||||
},
|
||||
{
|
||||
"fromId": "route_gumi_ryuma",
|
||||
"toId": "mercator_gate_tree",
|
||||
"twoWay": True
|
||||
},
|
||||
{
|
||||
"fromId": "ryuma",
|
||||
"toId": "ryuma_after_thieves_hideout",
|
||||
|
@ -211,6 +221,11 @@ WORLD_PATHS_JSON = [
|
|||
],
|
||||
"twoWay": True
|
||||
},
|
||||
{
|
||||
"fromId": "greenmaze_post_whistle",
|
||||
"toId": "greenmaze_post_whistle_tree",
|
||||
"twoWay": True
|
||||
},
|
||||
{
|
||||
"fromId": "greenmaze_post_whistle",
|
||||
"toId": "route_massan_gumi"
|
||||
|
@ -253,6 +268,11 @@ WORLD_PATHS_JSON = [
|
|||
"fromId": "verla_shore_cliff",
|
||||
"toId": "verla_shore"
|
||||
},
|
||||
{
|
||||
"fromId": "verla_shore",
|
||||
"toId": "verla_shore_tree",
|
||||
"twoWay": True
|
||||
},
|
||||
{
|
||||
"fromId": "verla_shore",
|
||||
"toId": "mir_tower_sector",
|
||||
|
@ -316,6 +336,11 @@ WORLD_PATHS_JSON = [
|
|||
"Axe Magic"
|
||||
]
|
||||
},
|
||||
{
|
||||
"fromId": "mountainous_area",
|
||||
"toId": "mountainous_area_tree",
|
||||
"twoWay": True
|
||||
},
|
||||
{
|
||||
"fromId": "mountainous_area",
|
||||
"toId": "route_lake_shrine_cliff",
|
||||
|
|
|
@ -57,7 +57,9 @@ WORLD_REGIONS_JSON = [
|
|||
"name": "Route between Gumi and Ryuma",
|
||||
"canBeHintedAsRequired": False,
|
||||
"nodeIds": [
|
||||
"route_gumi_ryuma"
|
||||
"route_gumi_ryuma",
|
||||
"tibor_tree",
|
||||
"mercator_gate_tree"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -157,7 +159,8 @@ WORLD_REGIONS_JSON = [
|
|||
"hintName": "in Greenmaze",
|
||||
"nodeIds": [
|
||||
"greenmaze_pre_whistle",
|
||||
"greenmaze_post_whistle"
|
||||
"greenmaze_post_whistle",
|
||||
"greenmaze_post_whistle_tree"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -165,7 +168,8 @@ WORLD_REGIONS_JSON = [
|
|||
"canBeHintedAsRequired": False,
|
||||
"nodeIds": [
|
||||
"verla_shore",
|
||||
"verla_shore_cliff"
|
||||
"verla_shore_cliff",
|
||||
"verla_shore_tree"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -244,7 +248,8 @@ WORLD_REGIONS_JSON = [
|
|||
"name": "Mountainous Area",
|
||||
"hintName": "in the mountainous area",
|
||||
"nodeIds": [
|
||||
"mountainous_area"
|
||||
"mountainous_area",
|
||||
"mountainous_area_tree"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -8,19 +8,19 @@ WORLD_TELEPORT_TREES_JSON = [
|
|||
{
|
||||
"name": "Tibor tree",
|
||||
"treeMapId": 534,
|
||||
"nodeId": "route_gumi_ryuma"
|
||||
"nodeId": "tibor_tree"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "Mercator front gate tree",
|
||||
"treeMapId": 539,
|
||||
"nodeId": "route_gumi_ryuma"
|
||||
"nodeId": "mercator_gate_tree"
|
||||
},
|
||||
{
|
||||
"name": "Verla shore tree",
|
||||
"treeMapId": 537,
|
||||
"nodeId": "verla_shore"
|
||||
"nodeId": "verla_shore_tree"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -44,7 +44,7 @@ WORLD_TELEPORT_TREES_JSON = [
|
|||
{
|
||||
"name": "Mountainous area tree",
|
||||
"treeMapId": 535,
|
||||
"nodeId": "mountainous_area"
|
||||
"nodeId": "mountainous_area_tree"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -56,7 +56,7 @@ WORLD_TELEPORT_TREES_JSON = [
|
|||
{
|
||||
"name": "Greenmaze end tree",
|
||||
"treeMapId": 511,
|
||||
"nodeId": "greenmaze_post_whistle"
|
||||
"nodeId": "greenmaze_post_whistle_tree"
|
||||
}
|
||||
]
|
||||
]
|
Loading…
Reference in New Issue