Initial Commit
This commit is contained in:
commit
fa38469735
30 files changed
+6902
No files matched your search
@@ -0,0 +1,42 @@
|
||||
# called after the game.json file has been loaded
|
||||
def after_load_game_file(game_table: dict) -> dict:
|
||||
return game_table
|
||||
# called after the items.json file has been loaded, before any item loading or processing has occurred
|
||||
# if you need access to the items after processing to add ids, etc., you should use the hooks in World.py
|
||||
def after_load_item_file(item_table: list) -> list:
|
||||
return item_table
|
||||
|
||||
# NOTE: Progressive items are not currently supported in Manual. Once they are,
|
||||
# this hook will provide the ability to meaningfully change those.
|
||||
def after_load_progressive_item_file(progressive_item_table: list) -> list:
|
||||
return progressive_item_table
|
||||
|
||||
# called after the locations.json file has been loaded, before any location loading or processing has occurred
|
||||
# if you need access to the locations after processing to add ids, etc., you should use the hooks in World.py
|
||||
def after_load_location_file(location_table: list) -> list:
|
||||
return location_table
|
||||
|
||||
# called after the events.json file has been loaded, before any processing has occurred
|
||||
# If you need access to the events after processing, you should use the hooks in World.py
|
||||
def after_load_event_file(event_table: list) -> list:
|
||||
return event_table
|
||||
|
||||
# called after the regions.json file has been loaded, before any location loading or processing has occurred
|
||||
# if you need access to the locations after processing to add ids, etc., you should use the hooks in World.py
|
||||
def after_load_region_file(region_table: dict) -> dict:
|
||||
return region_table
|
||||
|
||||
# called after the categories.json file has been loaded
|
||||
def after_load_category_file(category_table: dict) -> dict:
|
||||
return category_table
|
||||
|
||||
# called after the categories.json file has been loaded
|
||||
def after_load_option_file(option_table: dict) -> dict:
|
||||
# option_table["core"] is the dictionary of modification of existing options
|
||||
# option_table["user"] is the dictionary of custom options
|
||||
return option_table
|
||||
|
||||
# called after the meta.json file has been loaded and just before the properties of the apworld are defined. You can use this hook to change what is displayed on the webhost
|
||||
# for more info check https://github.com/ArchipelagoMW/Archipelago/blob/main/docs/world%20api.md#webworld-class
|
||||
def after_load_meta_file(meta_table: dict) -> dict:
|
||||
return meta_table
|
||||
@@ -0,0 +1,23 @@
|
||||
from typing import Optional, Any
|
||||
from BaseClasses import MultiWorld
|
||||
|
||||
|
||||
# Use this if you want to override the default behavior of is_option_enabled
|
||||
# Return True to enable the category, False to disable it, or None to use the default behavior
|
||||
def before_is_category_enabled(multiworld: MultiWorld, player: int, category_name: str) -> Optional[bool]:
|
||||
return None
|
||||
|
||||
# Use this if you want to override the default behavior of is_option_enabled
|
||||
# Return True to enable the item, False to disable it, or None to use the default behavior
|
||||
def before_is_item_enabled(multiworld: MultiWorld, player: int, item: dict[str, Any]) -> Optional[bool]:
|
||||
return None
|
||||
|
||||
# Use this if you want to override the default behavior of is_option_enabled
|
||||
# Return True to enable the location, False to disable it, or None to use the default behavior
|
||||
def before_is_location_enabled(multiworld: MultiWorld, player: int, location: dict[str, Any]) -> Optional[bool]:
|
||||
return None
|
||||
|
||||
# Use this if you want to override the default behavior of is_option_enabled
|
||||
# Return True to enable the event, False to disable it, or None to use the default behavior
|
||||
def before_is_event_enabled(multiworld: MultiWorld, player: int, event: dict[str, Any]) -> Optional[bool]:
|
||||
return None
|
||||
@@ -0,0 +1,57 @@
|
||||
# Object classes from AP that represent different types of options that you can create
|
||||
from Options import Option, FreeText, NumericOption, Toggle, DefaultOnToggle, Choice, TextChoice, Range, NamedRange, OptionGroup, PerGameCommonOptions
|
||||
# These helper methods allow you to determine if an option has been set, or what its value is, for any player in the multiworld
|
||||
from ..Helpers import is_option_enabled, get_option_value
|
||||
from typing import Type, Any
|
||||
|
||||
|
||||
####################################################################
|
||||
# NOTE: At the time that options are created, Manual has no concept of the multiworld or its own world.
|
||||
# Options are defined before the world is even created.
|
||||
#
|
||||
# Example of creating your own option:
|
||||
#
|
||||
# class MakeThePlayerOP(Toggle):
|
||||
# """Should the player be overpowered? Probably not, but you can choose for this to do... something!"""
|
||||
# display_name = "Make me OP"
|
||||
#
|
||||
# options["make_op"] = MakeThePlayerOP
|
||||
#
|
||||
#
|
||||
# Then, to see if the option is set, you can call is_option_enabled or get_option_value.
|
||||
#####################################################################
|
||||
|
||||
|
||||
# To add an option, use the before_options_defined hook below and something like this:
|
||||
# options["total_characters_to_win_with"] = TotalCharactersToWinWith
|
||||
#
|
||||
class TotalCharactersToWinWith(Range):
|
||||
"""Instead of having to beat the game with all characters, you can limit locations to a subset of character victory locations."""
|
||||
display_name = "Number of characters to beat the game with before victory"
|
||||
range_start = 10
|
||||
range_end = 50
|
||||
default = 50
|
||||
|
||||
# This is called before any manual options are defined, in case you want to define your own with a clean slate or let Manual define over them
|
||||
def before_options_defined(options: dict[str, Type[Option[Any]]]) -> dict[str, Type[Option[Any]]]:
|
||||
return options
|
||||
|
||||
# This is called after any manual options are defined, in case you want to see what options are defined or want to modify the defined options
|
||||
def after_options_defined(options: Type[PerGameCommonOptions]):
|
||||
# To access a modifiable version of options check the dict in options.type_hints
|
||||
# For example if you want to change DLC_enabled's display name you would do:
|
||||
# options.type_hints["DLC_enabled"].display_name = "New Display Name"
|
||||
|
||||
# Here's an example on how to add your aliases to the generated goal
|
||||
# options.type_hints['goal'].aliases.update({"example": 0, "second_alias": 1})
|
||||
# options.type_hints['goal'].options.update({"example": 0, "second_alias": 1}) #for an alias to be valid it must also be in options
|
||||
|
||||
pass
|
||||
|
||||
# Use this Hook if you want to add your Option to an Option group (existing or not)
|
||||
def before_option_groups_created(groups: dict[str, list[Type[Option[Any]]]]) -> dict[str, list[Type[Option[Any]]]]:
|
||||
# Uses the format groups['GroupName'] = [TotalCharactersToWinWith]
|
||||
return groups
|
||||
|
||||
def after_option_groups_created(groups: list[OptionGroup]) -> list[OptionGroup]:
|
||||
return groups
|
||||
@@ -0,0 +1,29 @@
|
||||
from typing import Optional
|
||||
from worlds.AutoWorld import World
|
||||
from ..Helpers import clamp, get_items_with_value
|
||||
from BaseClasses import MultiWorld, CollectionState
|
||||
|
||||
import re
|
||||
|
||||
# Sometimes you have a requirement that is just too messy or repetitive to write out with boolean logic.
|
||||
# Define a function here, and you can use it in a requires string with {function_name()}.
|
||||
def overfishedAnywhere(world: World, state: CollectionState, player: int):
|
||||
"""Has the player collected all fish from any fishing log?"""
|
||||
for cat, items in world.item_name_groups:
|
||||
if cat.endswith("Fishing Log") and state.has_all(items, player):
|
||||
return True
|
||||
return False
|
||||
|
||||
# You can also pass an argument to your function, like {function_name(15)}
|
||||
# Note that all arguments are strings, so you'll need to convert them to ints if you want to do math.
|
||||
def anyClassLevel(state: CollectionState, player: int, level: str):
|
||||
"""Has the player reached the given level in any class?"""
|
||||
for item in ["Figher Level", "Black Belt Level", "Thief Level", "Red Mage Level", "White Mage Level", "Black Mage Level"]:
|
||||
if state.count(item, player) >= int(level):
|
||||
return True
|
||||
return False
|
||||
|
||||
# You can also return a string from your function, and it will be evaluated as a requires string.
|
||||
def requiresMelee():
|
||||
"""Returns a requires string that checks if the player has unlocked the tank."""
|
||||
return "|Figher Level:15| or |Black Belt Level:15| or |Thief Level:15|"
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
# Object classes from AP core, to represent an entire MultiWorld and this individual World that's part of it
|
||||
from typing import Any
|
||||
from worlds.AutoWorld import World
|
||||
from BaseClasses import MultiWorld, CollectionState, Item
|
||||
|
||||
# Object classes from Manual -- extending AP core -- representing items and locations that are used in generation
|
||||
from ..Items import ManualItem
|
||||
from ..Locations import ManualLocation
|
||||
|
||||
# Raw JSON data from the Manual apworld, respectively:
|
||||
# data/game.json, data/items.json, data/locations.json, data/regions.json
|
||||
#
|
||||
from ..Data import game_table, item_table, location_table, region_table
|
||||
|
||||
# These helper methods allow you to determine if an option has been set, or what its value is, for any player in the multiworld
|
||||
from ..Helpers import is_option_enabled, get_option_value, format_state_prog_items_key, ProgItemsCat, remove_specific_item
|
||||
|
||||
# calling logging.info("message") anywhere below in this file will output the message to both console and log file
|
||||
import logging
|
||||
|
||||
########################################################################################
|
||||
## Order of method calls when the world generates:
|
||||
## 1. create_regions - Creates regions and locations
|
||||
## 2. create_items - Creates the item pool
|
||||
## 3. set_rules - Creates rules for accessing regions and locations
|
||||
## 4. generate_basic - Runs any post item pool options, like place item/category
|
||||
## 5. pre_fill - Creates the victory location
|
||||
##
|
||||
## The create_item method is used by plando and start_inventory settings to create an item from an item name.
|
||||
## The fill_slot_data method will be used to send data to the Manual client for later use, like deathlink.
|
||||
########################################################################################
|
||||
|
||||
|
||||
|
||||
# Use this function to change the valid filler items to be created to replace item links or starting items.
|
||||
# Default value is the `filler_item_name` from game.json
|
||||
def hook_get_filler_item_name(world: World, multiworld: MultiWorld, player: int) -> list[str] | str | bool:
|
||||
return False
|
||||
|
||||
def before_generate_early(world: World, multiworld: MultiWorld, player: int) -> None:
|
||||
"""
|
||||
This is the earliest hook called during generation, before anything else is done.
|
||||
Use it to check or modify incompatible options, or to set up variables for later use.
|
||||
"""
|
||||
pass
|
||||
|
||||
def before_create_regions(world: World, multiworld: MultiWorld, player: int):
|
||||
"""
|
||||
Called before regions and locations are created. Not clear why you'd want this, but it's here.
|
||||
Victory location is included, but Victory event is not placed yet.
|
||||
"""
|
||||
pass
|
||||
|
||||
def after_create_regions(world: World, multiworld: MultiWorld, player: int):
|
||||
"""
|
||||
Called after regions and locations are created, in case you want to see or modify that information.
|
||||
Victory location is included.
|
||||
|
||||
Use this hook to modify locations from the world
|
||||
If you wish to remove them entirely, use Helpers.before_is_location_enabled instead.
|
||||
"""
|
||||
|
||||
# Add your code here to calculate which locations to exclude
|
||||
for region in multiworld.regions:
|
||||
if region.player == player:
|
||||
for location in region.locations:
|
||||
# If you have other things you want to modify, you can do it here as well.
|
||||
# The fields you might care about are: item_rule, always_allow, progress_type, and show_in_spoiler.
|
||||
pass
|
||||
|
||||
# This hook allows you to access the item names & counts before the items are created. Use this to increase/decrease the amount of a specific item in the pool
|
||||
# Valid item_config key/values:
|
||||
# {"Item Name": 5} <- This will create qty 5 items using all the default settings
|
||||
# {"Item Name": {"useful": 7}} <- This will create qty 7 items and force them to be classified as useful
|
||||
# {"Item Name": {"progression": 2, "useful": 1}} <- This will create 3 items, with 2 classified as progression and 1 as useful
|
||||
# {"Item Name": {0b0110: 5}} <- If you know the special flag for the item classes, you can also define non-standard options. This setup
|
||||
# will create 5 items that are the "useful trap" class
|
||||
# {"Item Name": {ItemClassification.useful: 5}} <- You can also use the classification directly
|
||||
def before_create_items_all(item_config: dict[str, int|dict], world: World, multiworld: MultiWorld, player: int) -> dict[str, int|dict]:
|
||||
return item_config
|
||||
|
||||
# The item pool before place_item(_category) are processed, in case you want to see the raw item pool at that stage
|
||||
def before_create_items_place_items(item_pool: list, world: World, multiworld: MultiWorld, player: int) -> list:
|
||||
return item_pool
|
||||
|
||||
# The item pool before starting items are processed, in case you want to see the raw item pool at that stage
|
||||
def before_create_items_starting(item_pool: list, world: World, multiworld: MultiWorld, player: int) -> list:
|
||||
return item_pool
|
||||
|
||||
# The item pool after starting items are processed but before filler is added, in case you want to see the raw item pool at that stage
|
||||
def before_create_items_filler(item_pool: list, world: World, multiworld: MultiWorld, player: int) -> list:
|
||||
# Use this hook to remove items from the item pool
|
||||
itemNamesToRemove: list[str] = [] # List of item names
|
||||
|
||||
# Add your code here to calculate which items to remove.
|
||||
#
|
||||
# Because multiple copies of an item can exist, you need to add an item name
|
||||
# to the list multiple times if you want to remove multiple copies of it.
|
||||
|
||||
for itemName in itemNamesToRemove:
|
||||
item = next(i for i in item_pool if i.name == itemName)
|
||||
remove_specific_item(item_pool, item)
|
||||
|
||||
return item_pool
|
||||
|
||||
# Some other useful hook options:
|
||||
|
||||
## Place an item at a specific location
|
||||
# location = next(l for l in multiworld.get_unfilled_locations(player=player) if l.name == "Location Name")
|
||||
# item_to_place = next(i for i in item_pool if i.name == "Item Name")
|
||||
# location.place_locked_item(item_to_place)
|
||||
# remove_specific_item(item_pool, item_to_place)
|
||||
|
||||
# The complete item pool prior to being set for generation is provided here, in case you want to make changes to it
|
||||
def after_create_items(item_pool: list, world: World, multiworld: MultiWorld, player: int) -> list:
|
||||
return item_pool
|
||||
|
||||
# Called before rules for accessing regions and locations are created. Not clear why you'd want this, but it's here.
|
||||
def before_set_rules(world: World, multiworld: MultiWorld, player: int):
|
||||
pass
|
||||
|
||||
# Called after rules for accessing regions and locations are created, in case you want to see or modify that information.
|
||||
def after_set_rules(world: World, multiworld: MultiWorld, player: int):
|
||||
# Use this hook to modify the access rules for a given location
|
||||
|
||||
def Example_Rule(state: CollectionState) -> bool:
|
||||
# Calculated rules take a CollectionState object and return a boolean
|
||||
# True if the player can access the location
|
||||
# CollectionState is defined in BaseClasses
|
||||
return True
|
||||
|
||||
## Common functions:
|
||||
# location = world.get_location(location_name, player)
|
||||
# location.access_rule = Example_Rule
|
||||
|
||||
## Combine rules:
|
||||
# old_rule = location.access_rule
|
||||
# location.access_rule = lambda state: old_rule(state) and Example_Rule(state)
|
||||
# OR
|
||||
# location.access_rule = lambda state: old_rule(state) or Example_Rule(state)
|
||||
|
||||
# The item name to create is provided before the item is created, in case you want to make changes to it
|
||||
def before_create_item(item_name: str, world: World, multiworld: MultiWorld, player: int) -> str:
|
||||
return item_name
|
||||
|
||||
# The item that was created is provided after creation, in case you want to modify the item
|
||||
def after_create_item(item: ManualItem, world: World, multiworld: MultiWorld, player: int) -> ManualItem:
|
||||
return item
|
||||
|
||||
# This method is run towards the end of pre-generation, before the place_item options have been handled and before AP generation occurs
|
||||
def before_generate_basic(world: World, multiworld: MultiWorld, player: int):
|
||||
pass
|
||||
|
||||
# This method is run every time an item is added to the state, can be used to modify the value of an item.
|
||||
# IMPORTANT! Any changes made in this hook must be cancelled/undone in after_remove_item
|
||||
def after_collect_item(world: World, state: CollectionState, Changed: bool, item: Item):
|
||||
# the following let you add to the Potato Item Value count
|
||||
# if item.name == "Cooked Potato":
|
||||
# state.prog_items[item.player][format_state_prog_items_key(ProgItemsCat.VALUE, "Potato")] += 1
|
||||
pass
|
||||
|
||||
# This method is run every time an item is removed from the state, can be used to modify the value of an item.
|
||||
# IMPORTANT! Any changes made in this hook must be first done in after_collect_item
|
||||
def after_remove_item(world: World, state: CollectionState, Changed: bool, item: Item):
|
||||
# the following let you undo the addition to the Potato Item Value count
|
||||
# if item.name == "Cooked Potato":
|
||||
# state.prog_items[item.player][format_state_prog_items_key(ProgItemsCat.VALUE, "Potato")] -= 1
|
||||
pass
|
||||
|
||||
|
||||
# This is called before slot data is set and provides an empty dict ({}), in case you want to modify it before Manual does
|
||||
def before_fill_slot_data(slot_data: dict, world: World, multiworld: MultiWorld, player: int) -> dict:
|
||||
return slot_data
|
||||
|
||||
# This is called after slot data is set and provides the slot data at the time, in case you want to check and modify it after Manual is done with it
|
||||
def after_fill_slot_data(slot_data: dict, world: World, multiworld: MultiWorld, player: int) -> dict:
|
||||
return slot_data
|
||||
|
||||
# This is called right at the end, in case you want to write stuff to the spoiler log
|
||||
def before_write_spoiler(world: World, multiworld: MultiWorld, spoiler_handle) -> None:
|
||||
pass
|
||||
|
||||
# This is called when you want to add information to the hint text
|
||||
def before_extend_hint_information(hint_data: dict[int, dict[int, str]], world: World, multiworld: MultiWorld, player: int) -> None:
|
||||
|
||||
### Example way to use this hook:
|
||||
# if player not in hint_data:
|
||||
# hint_data.update({player: {}})
|
||||
# for location in multiworld.get_locations(player):
|
||||
# if not location.address:
|
||||
# continue
|
||||
#
|
||||
# use this section to calculate the hint string
|
||||
#
|
||||
# hint_data[player][location.address] = hint_string
|
||||
|
||||
pass
|
||||
|
||||
def after_extend_hint_information(hint_data: dict[int, dict[int, str]], world: World, multiworld: MultiWorld, player: int) -> None:
|
||||
pass
|
||||
|
||||
def hook_interpret_slot_data(world: World, player: int, slot_data: dict[str, Any]) -> dict[str, Any]:
|
||||
"""
|
||||
Called when Universal Tracker wants to perform a fake generation
|
||||
Use this if you want to use or modify the slot_data for passed into re_gen_passthrough
|
||||
"""
|
||||
return slot_data
|
||||
@@ -0,0 +1 @@
|
||||
# intentionally empty
|
||||
Reference in new issue
Block a user