diff --git a/BaseClasses.py b/BaseClasses.py
index a0c243c0fd9d..092f330bcbb4 100644
--- a/BaseClasses.py
+++ b/BaseClasses.py
@@ -1,7 +1,6 @@
from __future__ import annotations
import collections
-import copy
import itertools
import functools
import logging
@@ -290,6 +289,8 @@ def set_item_links(self):
def link_items(self) -> None:
"""Called to link together items in the itempool related to the registered item link groups."""
+ from worlds import AutoWorld
+
for group_id, group in self.groups.items():
def find_common_pool(players: Set[int], shared_pool: Set[str]) -> Tuple[
Optional[Dict[int, Dict[str, int]]], Optional[Dict[str, int]]
@@ -300,15 +301,15 @@ def find_common_pool(players: Set[int], shared_pool: Set[str]) -> Tuple[
if item.player in counters and item.name in shared_pool:
counters[item.player][item.name] += 1
classifications[item.name] |= item.classification
-
+
for player in players.copy():
if all([counters[player][item] == 0 for item in shared_pool]):
players.remove(player)
del (counters[player])
-
+
if not players:
return None, None
-
+
for item in shared_pool:
count = min(counters[player][item] for player in players)
if count:
@@ -318,11 +319,11 @@ def find_common_pool(players: Set[int], shared_pool: Set[str]) -> Tuple[
for player in players:
del (counters[player][item])
return counters, classifications
-
+
common_item_count, classifications = find_common_pool(group["players"], group["item_pool"])
if not common_item_count:
continue
-
+
new_itempool: List[Item] = []
for item_name, item_count in next(iter(common_item_count.values())).items():
for _ in range(item_count):
@@ -330,7 +331,7 @@ def find_common_pool(players: Set[int], shared_pool: Set[str]) -> Tuple[
# mangle together all original classification bits
new_item.classification |= classifications[item_name]
new_itempool.append(new_item)
-
+
region = Region("Menu", group_id, self, "ItemLink")
self.regions.append(region)
locations = region.locations
@@ -341,16 +342,16 @@ def find_common_pool(players: Set[int], shared_pool: Set[str]) -> Tuple[
None, region)
loc.access_rule = lambda state, item_name = item.name, group_id_ = group_id, count_ = count: \
state.has(item_name, group_id_, count_)
-
+
locations.append(loc)
loc.place_locked_item(item)
common_item_count[item.player][item.name] -= 1
else:
new_itempool.append(item)
-
+
itemcount = len(self.itempool)
self.itempool = new_itempool
-
+
while itemcount > len(self.itempool):
items_to_add = []
for player in group["players"]:
@@ -717,14 +718,14 @@ def update_reachable_regions(self, player: int):
def copy(self) -> CollectionState:
ret = CollectionState(self.multiworld)
- ret.prog_items = copy.deepcopy(self.prog_items)
- ret.reachable_regions = {player: copy.copy(self.reachable_regions[player]) for player in
- self.reachable_regions}
- ret.blocked_connections = {player: copy.copy(self.blocked_connections[player]) for player in
- self.blocked_connections}
- ret.events = copy.copy(self.events)
- ret.path = copy.copy(self.path)
- ret.locations_checked = copy.copy(self.locations_checked)
+ ret.prog_items = {player: counter.copy() for player, counter in self.prog_items.items()}
+ ret.reachable_regions = {player: region_set.copy() for player, region_set in
+ self.reachable_regions.items()}
+ ret.blocked_connections = {player: entrance_set.copy() for player, entrance_set in
+ self.blocked_connections.items()}
+ ret.events = self.events.copy()
+ ret.path = self.path.copy()
+ ret.locations_checked = self.locations_checked.copy()
for function in self.additional_copy_functions:
ret = function(self, ret)
return ret
@@ -1126,9 +1127,9 @@ def can_fill(self, state: CollectionState, item: Item, check_access=True) -> boo
and (not check_access or self.can_reach(state))))
def can_reach(self, state: CollectionState) -> bool:
- # self.access_rule computes faster on average, so placing it first for faster abort
+ # Region.can_reach is just a cache lookup, so placing it first for faster abort on average
assert self.parent_region, "Can't reach location without region"
- return self.access_rule(state) and self.parent_region.can_reach(state)
+ return self.parent_region.can_reach(state) and self.access_rule(state)
def place_locked_item(self, item: Item):
if self.item:
diff --git a/Main.py b/Main.py
index ce054dcd393f..6dc03aaa55e0 100644
--- a/Main.py
+++ b/Main.py
@@ -151,6 +151,7 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No
# Because some worlds don't actually create items during create_items this has to be as late as possible.
if any(getattr(multiworld.worlds[player].options, "start_inventory_from_pool", None) for player in multiworld.player_ids):
new_items: List[Item] = []
+ old_items: List[Item] = []
depletion_pool: Dict[int, Dict[str, int]] = {
player: getattr(multiworld.worlds[player].options,
"start_inventory_from_pool",
@@ -169,20 +170,24 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No
depletion_pool[item.player][item.name] -= 1
# quick abort if we have found all items
if not target:
- new_items.extend(multiworld.itempool[i+1:])
+ old_items.extend(multiworld.itempool[i+1:])
break
else:
- new_items.append(item)
+ old_items.append(item)
# leftovers?
if target:
for player, remaining_items in depletion_pool.items():
remaining_items = {name: count for name, count in remaining_items.items() if count}
if remaining_items:
- raise Exception(f"{multiworld.get_player_name(player)}"
+ logger.warning(f"{multiworld.get_player_name(player)}"
f" is trying to remove items from their pool that don't exist: {remaining_items}")
- assert len(multiworld.itempool) == len(new_items), "Item Pool amounts should not change."
- multiworld.itempool[:] = new_items
+ # find all filler we generated for the current player and remove until it matches
+ removables = [item for item in new_items if item.player == player]
+ for _ in range(sum(remaining_items.values())):
+ new_items.remove(removables.pop())
+ assert len(multiworld.itempool) == len(new_items + old_items), "Item Pool amounts should not change."
+ multiworld.itempool[:] = new_items + old_items
multiworld.link_items()
diff --git a/Options.py b/Options.py
index d040828509d1..ecde6275f1ea 100644
--- a/Options.py
+++ b/Options.py
@@ -1236,6 +1236,7 @@ def as_dict(self, *option_names: str, casing: str = "snake") -> typing.Dict[str,
:param option_names: names of the options to return
:param casing: case of the keys to return. Supports `snake`, `camel`, `pascal`, `kebab`
"""
+ assert option_names, "options.as_dict() was used without any option names."
option_results = {}
for option_name in option_names:
if option_name in type(self).type_hints:
@@ -1517,31 +1518,3 @@ def yaml_dump_scalar(scalar) -> str:
with open(os.path.join(target_folder, game_name + ".yaml"), "w", encoding="utf-8-sig") as f:
f.write(res)
-
-
-if __name__ == "__main__":
-
- from worlds.alttp.Options import Logic
- import argparse
-
- map_shuffle = Toggle
- compass_shuffle = Toggle
- key_shuffle = Toggle
- big_key_shuffle = Toggle
- hints = Toggle
- test = argparse.Namespace()
- test.logic = Logic.from_text("no_logic")
- test.map_shuffle = map_shuffle.from_text("ON")
- test.hints = hints.from_text('OFF')
- try:
- test.logic = Logic.from_text("overworld_glitches_typo")
- except KeyError as e:
- print(e)
- try:
- test.logic_owg = Logic.from_text("owg")
- except KeyError as e:
- print(e)
- if test.map_shuffle:
- print("map_shuffle is on")
- print(f"Hints are {bool(test.hints)}")
- print(test)
diff --git a/README.md b/README.md
index 75dc568cdff5..a2e9d3e5e5a3 100644
--- a/README.md
+++ b/README.md
@@ -72,6 +72,7 @@ Currently, the following games are supported:
* Aquaria
* Yu-Gi-Oh! Ultimate Masters: World Championship Tournament 2006
* A Hat in Time
+* Old School Runescape
* Kingdom Hearts 1
For setup and instructions check out our [tutorials page](https://archipelago.gg/tutorial/).
diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS
index 80b269ee0c9e..bba79c649fc1 100644
--- a/docs/CODEOWNERS
+++ b/docs/CODEOWNERS
@@ -118,6 +118,9 @@
# Ocarina of Time
/worlds/oot/ @espeon65536
+# Old School Runescape
+/worlds/osrs @digiholic
+
# Overcooked! 2
/worlds/overcooked2/ @toasterparty
diff --git a/setup.py b/setup.py
index cb4d1a7511b6..0c9ee2c29302 100644
--- a/setup.py
+++ b/setup.py
@@ -66,7 +66,6 @@
"Adventure",
"ArchipIDLE",
"Archipelago",
- "ChecksFinder",
"Clique",
"Final Fantasy",
"Lufia II Ancient Cave",
diff --git a/worlds/__init__.py b/worlds/__init__.py
index bb2fe866d02d..c277ac9ca1de 100644
--- a/worlds/__init__.py
+++ b/worlds/__init__.py
@@ -73,7 +73,12 @@ def load(self) -> bool:
else: # TODO: remove with 3.8 support
mod = importer.load_module(os.path.basename(self.path).rsplit(".", 1)[0])
- mod.__package__ = f"worlds.{mod.__package__}"
+ if mod.__package__ is not None:
+ mod.__package__ = f"worlds.{mod.__package__}"
+ else:
+ # load_module does not populate package, we'll have to assume mod.__name__ is correct here
+ # probably safe to remove with 3.8 support
+ mod.__package__ = f"worlds.{mod.__name__}"
mod.__name__ = f"worlds.{mod.__name__}"
sys.modules[mod.__name__] = mod
with warnings.catch_warnings():
diff --git a/worlds/aquaria/Items.py b/worlds/aquaria/Items.py
index 34557d95d00d..f822d675e6e7 100644
--- a/worlds/aquaria/Items.py
+++ b/worlds/aquaria/Items.py
@@ -99,7 +99,7 @@ def __init__(self, id: int, count: int, type: ItemType, group: ItemGroup):
"Mutant Costume": ItemData(698020, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mutant_costume
"Baby Nautilus": ItemData(698021, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_nautilus
"Baby Piranha": ItemData(698022, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_piranha
- "Arnassi Armor": ItemData(698023, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_seahorse_costume
+ "Arnassi Armor": ItemData(698023, 1, ItemType.PROGRESSION, ItemGroup.UTILITY), # collectible_seahorse_costume
"Seed Bag": ItemData(698024, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_seed_bag
"King's Skull": ItemData(698025, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_skull
"Song Plant Spore": ItemData(698026, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_spore_seed
diff --git a/worlds/aquaria/Locations.py b/worlds/aquaria/Locations.py
index 2eb9d1e9a29d..f6e098103fdc 100644
--- a/worlds/aquaria/Locations.py
+++ b/worlds/aquaria/Locations.py
@@ -45,7 +45,7 @@ class AquariaLocations:
"Home Water, bulb below the grouper fish": 698058,
"Home Water, bulb in the path below Nautilus Prime": 698059,
"Home Water, bulb in the little room above the grouper fish": 698060,
- "Home Water, bulb in the end of the left path from the Verse Cave": 698061,
+ "Home Water, bulb in the end of the path close to the Verse Cave": 698061,
"Home Water, bulb in the top left path": 698062,
"Home Water, bulb in the bottom left room": 698063,
"Home Water, bulb close to Naija's Home": 698064,
@@ -67,7 +67,7 @@ class AquariaLocations:
locations_song_cave = {
"Song Cave, Erulian spirit": 698206,
- "Song Cave, bulb in the top left part": 698071,
+ "Song Cave, bulb in the top right part": 698071,
"Song Cave, bulb in the big anemone room": 698072,
"Song Cave, bulb in the path to the singing statues": 698073,
"Song Cave, bulb under the rock in the path to the singing statues": 698074,
@@ -152,6 +152,9 @@ class AquariaLocations:
locations_arnassi_path = {
"Arnassi Ruins, Arnassi Statue": 698164,
+ }
+
+ locations_arnassi_cave_transturtle = {
"Arnassi Ruins, Transturtle": 698217,
}
@@ -269,9 +272,12 @@ class AquariaLocations:
}
locations_forest_bl = {
+ "Kelp Forest bottom left area, Transturtle": 698212,
+ }
+
+ locations_forest_bl_sc = {
"Kelp Forest bottom left area, bulb close to the spirit crystals": 698054,
"Kelp Forest bottom left area, Walker Baby": 698186,
- "Kelp Forest bottom left area, Transturtle": 698212,
}
locations_forest_br = {
@@ -370,7 +376,7 @@ class AquariaLocations:
locations_sun_temple_r = {
"Sun Temple, first bulb of the temple": 698091,
- "Sun Temple, bulb on the left part": 698092,
+ "Sun Temple, bulb on the right part": 698092,
"Sun Temple, bulb in the hidden room of the right part": 698093,
"Sun Temple, Sun Key": 698182,
}
@@ -402,6 +408,9 @@ class AquariaLocations:
"Abyss right area, bulb in the middle path": 698110,
"Abyss right area, bulb behind the rock in the middle path": 698111,
"Abyss right area, bulb in the left green room": 698112,
+ }
+
+ locations_abyss_r_transturtle = {
"Abyss right area, Transturtle": 698214,
}
@@ -499,6 +508,7 @@ class AquariaLocations:
**AquariaLocations.locations_skeleton_path_sc,
**AquariaLocations.locations_arnassi,
**AquariaLocations.locations_arnassi_path,
+ **AquariaLocations.locations_arnassi_cave_transturtle,
**AquariaLocations.locations_arnassi_crab_boss,
**AquariaLocations.locations_sun_temple_l,
**AquariaLocations.locations_sun_temple_r,
@@ -509,6 +519,7 @@ class AquariaLocations:
**AquariaLocations.locations_abyss_l,
**AquariaLocations.locations_abyss_lb,
**AquariaLocations.locations_abyss_r,
+ **AquariaLocations.locations_abyss_r_transturtle,
**AquariaLocations.locations_energy_temple_1,
**AquariaLocations.locations_energy_temple_2,
**AquariaLocations.locations_energy_temple_3,
@@ -530,6 +541,7 @@ class AquariaLocations:
**AquariaLocations.locations_forest_tr,
**AquariaLocations.locations_forest_tr_fp,
**AquariaLocations.locations_forest_bl,
+ **AquariaLocations.locations_forest_bl_sc,
**AquariaLocations.locations_forest_br,
**AquariaLocations.locations_forest_boss,
**AquariaLocations.locations_forest_boss_entrance,
diff --git a/worlds/aquaria/Regions.py b/worlds/aquaria/Regions.py
index 93c02d4e6766..3ec1fb880e13 100755
--- a/worlds/aquaria/Regions.py
+++ b/worlds/aquaria/Regions.py
@@ -14,97 +14,112 @@
# Every condition to connect regions
-def _has_hot_soup(state:CollectionState, player: int) -> bool:
+def _has_hot_soup(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the hotsoup item"""
- return state.has("Hot soup", player)
+ return state.has_any({"Hot soup", "Hot soup x 2"}, player)
-def _has_tongue_cleared(state:CollectionState, player: int) -> bool:
+def _has_tongue_cleared(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the Body tongue cleared item"""
return state.has("Body tongue cleared", player)
-def _has_sun_crystal(state:CollectionState, player: int) -> bool:
+def _has_sun_crystal(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the Sun crystal item"""
return state.has("Has sun crystal", player) and _has_bind_song(state, player)
-def _has_li(state:CollectionState, player: int) -> bool:
+def _has_li(state: CollectionState, player: int) -> bool:
"""`player` in `state` has Li in its team"""
return state.has("Li and Li song", player)
-def _has_damaging_item(state:CollectionState, player: int) -> bool:
+def _has_damaging_item(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the shield song item"""
- return state.has_any({"Energy form", "Nature form", "Beast form", "Li and Li song", "Baby Nautilus",
- "Baby Piranha", "Baby Blaster"}, player)
+ return state.has_any({"Energy form", "Nature form", "Beast form", "Li and Li song", "Baby Nautilus",
+ "Baby Piranha", "Baby Blaster"}, player)
-def _has_shield_song(state:CollectionState, player: int) -> bool:
+def _has_energy_attack_item(state: CollectionState, player: int) -> bool:
+ """`player` in `state` has items that can do a lot of damage (enough to beat bosses)"""
+ return _has_energy_form(state, player) or _has_dual_form(state, player)
+
+
+def _has_shield_song(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the shield song item"""
return state.has("Shield song", player)
-def _has_bind_song(state:CollectionState, player: int) -> bool:
+def _has_bind_song(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the bind song item"""
return state.has("Bind song", player)
-def _has_energy_form(state:CollectionState, player: int) -> bool:
+def _has_energy_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the energy form item"""
return state.has("Energy form", player)
-def _has_beast_form(state:CollectionState, player: int) -> bool:
+def _has_beast_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the beast form item"""
return state.has("Beast form", player)
-def _has_nature_form(state:CollectionState, player: int) -> bool:
+def _has_beast_and_soup_form(state: CollectionState, player: int) -> bool:
+ """`player` in `state` has the beast form item"""
+ return _has_beast_form(state, player) and _has_hot_soup(state, player)
+
+
+def _has_beast_form_or_arnassi_armor(state: CollectionState, player: int) -> bool:
+ """`player` in `state` has the beast form item"""
+ return _has_beast_form(state, player) or state.has("Arnassi Armor", player)
+
+
+def _has_nature_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the nature form item"""
return state.has("Nature form", player)
-def _has_sun_form(state:CollectionState, player: int) -> bool:
+def _has_sun_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the sun form item"""
return state.has("Sun form", player)
-def _has_light(state:CollectionState, player: int) -> bool:
+def _has_light(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the light item"""
return state.has("Baby Dumbo", player) or _has_sun_form(state, player)
-def _has_dual_form(state:CollectionState, player: int) -> bool:
+def _has_dual_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the dual form item"""
return _has_li(state, player) and state.has("Dual form", player)
-def _has_fish_form(state:CollectionState, player: int) -> bool:
+def _has_fish_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the fish form item"""
return state.has("Fish form", player)
-def _has_spirit_form(state:CollectionState, player: int) -> bool:
+def _has_spirit_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the spirit form item"""
return state.has("Spirit form", player)
-def _has_big_bosses(state:CollectionState, player: int) -> bool:
+def _has_big_bosses(state: CollectionState, player: int) -> bool:
"""`player` in `state` has beated every big bosses"""
return state.has_all({"Fallen God beated", "Mithalan God beated", "Drunian God beated",
- "Sun God beated", "The Golem beated"}, player)
+ "Sun God beated", "The Golem beated"}, player)
-def _has_mini_bosses(state:CollectionState, player: int) -> bool:
+def _has_mini_bosses(state: CollectionState, player: int) -> bool:
"""`player` in `state` has beated every big bosses"""
return state.has_all({"Nautilus Prime beated", "Blaster Peg Prime beated", "Mergog beated",
- "Mithalan priests beated", "Octopus Prime beated", "Crabbius Maximus beated",
- "Mantis Shrimp Prime beated", "King Jellyfish God Prime beated"}, player)
+ "Mithalan priests beated", "Octopus Prime beated", "Crabbius Maximus beated",
+ "Mantis Shrimp Prime beated", "King Jellyfish God Prime beated"}, player)
-def _has_secrets(state:CollectionState, player: int) -> bool:
- return state.has_all({"First secret obtained", "Second secret obtained", "Third secret obtained"},player)
+def _has_secrets(state: CollectionState, player: int) -> bool:
+ return state.has_all({"First secret obtained", "Second secret obtained", "Third secret obtained"}, player)
class AquariaRegions:
@@ -134,6 +149,7 @@ class AquariaRegions:
skeleton_path: Region
skeleton_path_sc: Region
arnassi: Region
+ arnassi_cave_transturtle: Region
arnassi_path: Region
arnassi_crab_boss: Region
simon: Region
@@ -152,6 +168,7 @@ class AquariaRegions:
forest_tr: Region
forest_tr_fp: Region
forest_bl: Region
+ forest_bl_sc: Region
forest_br: Region
forest_boss: Region
forest_boss_entrance: Region
@@ -179,6 +196,7 @@ class AquariaRegions:
abyss_l: Region
abyss_lb: Region
abyss_r: Region
+ abyss_r_transturtle: Region
ice_cave: Region
bubble_cave: Region
bubble_cave_boss: Region
@@ -213,7 +231,7 @@ class AquariaRegions:
"""
def __add_region(self, hint: str,
- locations: Optional[Dict[str, Optional[int]]]) -> Region:
+ locations: Optional[Dict[str, int]]) -> Region:
"""
Create a new Region, add it to the `world` regions and return it.
Be aware that this function have a side effect on ``world`.`regions`
@@ -236,7 +254,7 @@ def __create_home_water_area(self) -> None:
self.home_water_nautilus = self.__add_region("Home Water, Nautilus nest",
AquariaLocations.locations_home_water_nautilus)
self.home_water_transturtle = self.__add_region("Home Water, turtle room",
- AquariaLocations.locations_home_water_transturtle)
+ AquariaLocations.locations_home_water_transturtle)
self.naija_home = self.__add_region("Naija's Home", AquariaLocations.locations_naija_home)
self.song_cave = self.__add_region("Song Cave", AquariaLocations.locations_song_cave)
@@ -280,6 +298,8 @@ def __create_openwater(self) -> None:
self.arnassi = self.__add_region("Arnassi Ruins", AquariaLocations.locations_arnassi)
self.arnassi_path = self.__add_region("Arnassi Ruins, back entrance path",
AquariaLocations.locations_arnassi_path)
+ self.arnassi_cave_transturtle = self.__add_region("Arnassi Ruins, transturtle area",
+ AquariaLocations.locations_arnassi_cave_transturtle)
self.arnassi_crab_boss = self.__add_region("Arnassi Ruins, Crabbius Maximus lair",
AquariaLocations.locations_arnassi_crab_boss)
@@ -302,9 +322,9 @@ def __create_mithalas(self) -> None:
AquariaLocations.locations_cathedral_r)
self.cathedral_underground = self.__add_region("Mithalas Cathedral underground",
AquariaLocations.locations_cathedral_underground)
- self.cathedral_boss_r = self.__add_region("Mithalas Cathedral, Mithalan God room",
+ self.cathedral_boss_r = self.__add_region("Mithalas Cathedral, Mithalan God room", None)
+ self.cathedral_boss_l = self.__add_region("Mithalas Cathedral, after Mithalan God room",
AquariaLocations.locations_cathedral_boss)
- self.cathedral_boss_l = self.__add_region("Mithalas Cathedral, after Mithalan God room", None)
def __create_forest(self) -> None:
"""
@@ -320,6 +340,8 @@ def __create_forest(self) -> None:
AquariaLocations.locations_forest_tr_fp)
self.forest_bl = self.__add_region("Kelp Forest bottom left area",
AquariaLocations.locations_forest_bl)
+ self.forest_bl_sc = self.__add_region("Kelp Forest bottom left area, spirit crystals",
+ AquariaLocations.locations_forest_bl_sc)
self.forest_br = self.__add_region("Kelp Forest bottom right area",
AquariaLocations.locations_forest_br)
self.forest_sprite_cave = self.__add_region("Kelp Forest spirit cave",
@@ -375,9 +397,9 @@ def __create_sun_temple(self) -> None:
self.sun_temple_r = self.__add_region("Sun Temple right area",
AquariaLocations.locations_sun_temple_r)
self.sun_temple_boss_path = self.__add_region("Sun Temple before boss area",
- AquariaLocations.locations_sun_temple_boss_path)
+ AquariaLocations.locations_sun_temple_boss_path)
self.sun_temple_boss = self.__add_region("Sun Temple boss area",
- AquariaLocations.locations_sun_temple_boss)
+ AquariaLocations.locations_sun_temple_boss)
def __create_abyss(self) -> None:
"""
@@ -388,6 +410,8 @@ def __create_abyss(self) -> None:
AquariaLocations.locations_abyss_l)
self.abyss_lb = self.__add_region("Abyss left bottom area", AquariaLocations.locations_abyss_lb)
self.abyss_r = self.__add_region("Abyss right area", AquariaLocations.locations_abyss_r)
+ self.abyss_r_transturtle = self.__add_region("Abyss right area, transturtle",
+ AquariaLocations.locations_abyss_r_transturtle)
self.ice_cave = self.__add_region("Ice Cave", AquariaLocations.locations_ice_cave)
self.bubble_cave = self.__add_region("Bubble Cave", AquariaLocations.locations_bubble_cave)
self.bubble_cave_boss = self.__add_region("Bubble Cave boss area", AquariaLocations.locations_bubble_cave_boss)
@@ -407,7 +431,7 @@ def __create_sunken_city(self) -> None:
self.sunken_city_r = self.__add_region("Sunken City right area",
AquariaLocations.locations_sunken_city_r)
self.sunken_city_boss = self.__add_region("Sunken City boss area",
- AquariaLocations.locations_sunken_city_boss)
+ AquariaLocations.locations_sunken_city_boss)
def __create_body(self) -> None:
"""
@@ -427,7 +451,7 @@ def __create_body(self) -> None:
self.final_boss_tube = self.__add_region("The Body, final boss area turtle room",
AquariaLocations.locations_final_boss_tube)
self.final_boss = self.__add_region("The Body, final boss",
- AquariaLocations.locations_final_boss)
+ AquariaLocations.locations_final_boss)
self.final_boss_end = self.__add_region("The Body, final boss area", None)
def __connect_one_way_regions(self, source_name: str, destination_name: str,
@@ -455,8 +479,8 @@ def __connect_home_water_regions(self) -> None:
"""
Connect entrances of the different regions around `home_water`
"""
- self.__connect_regions("Menu", "Verse Cave right area",
- self.menu, self.verse_cave_r)
+ self.__connect_one_way_regions("Menu", "Verse Cave right area",
+ self.menu, self.verse_cave_r)
self.__connect_regions("Verse Cave left area", "Verse Cave right area",
self.verse_cave_l, self.verse_cave_r)
self.__connect_regions("Verse Cave", "Home Water", self.verse_cave_l, self.home_water)
@@ -464,7 +488,8 @@ def __connect_home_water_regions(self) -> None:
self.__connect_regions("Home Water", "Song Cave", self.home_water, self.song_cave)
self.__connect_regions("Home Water", "Home Water, nautilus nest",
self.home_water, self.home_water_nautilus,
- lambda state: _has_energy_form(state, self.player) and _has_bind_song(state, self.player))
+ lambda state: _has_energy_attack_item(state, self.player) and
+ _has_bind_song(state, self.player))
self.__connect_regions("Home Water", "Home Water transturtle room",
self.home_water, self.home_water_transturtle)
self.__connect_regions("Home Water", "Energy Temple first area",
@@ -472,7 +497,7 @@ def __connect_home_water_regions(self) -> None:
lambda state: _has_bind_song(state, self.player))
self.__connect_regions("Home Water", "Energy Temple_altar",
self.home_water, self.energy_temple_altar,
- lambda state: _has_energy_form(state, self.player) and
+ lambda state: _has_energy_attack_item(state, self.player) and
_has_bind_song(state, self.player))
self.__connect_regions("Energy Temple first area", "Energy Temple second area",
self.energy_temple_1, self.energy_temple_2,
@@ -482,28 +507,28 @@ def __connect_home_water_regions(self) -> None:
lambda state: _has_fish_form(state, self.player))
self.__connect_regions("Energy Temple idol room", "Energy Temple boss area",
self.energy_temple_idol, self.energy_temple_boss,
- lambda state: _has_energy_form(state, self.player))
+ lambda state: _has_energy_attack_item(state, self.player) and
+ _has_fish_form(state, self.player))
self.__connect_one_way_regions("Energy Temple first area", "Energy Temple boss area",
self.energy_temple_1, self.energy_temple_boss,
lambda state: _has_beast_form(state, self.player) and
- _has_energy_form(state, self.player))
+ _has_energy_attack_item(state, self.player))
self.__connect_one_way_regions("Energy Temple boss area", "Energy Temple first area",
self.energy_temple_boss, self.energy_temple_1,
- lambda state: _has_energy_form(state, self.player))
+ lambda state: _has_energy_attack_item(state, self.player))
self.__connect_regions("Energy Temple second area", "Energy Temple third area",
self.energy_temple_2, self.energy_temple_3,
- lambda state: _has_bind_song(state, self.player) and
- _has_energy_form(state, self.player))
+ lambda state: _has_energy_form(state, self.player))
self.__connect_regions("Energy Temple boss area", "Energy Temple blaster room",
self.energy_temple_boss, self.energy_temple_blaster_room,
lambda state: _has_nature_form(state, self.player) and
_has_bind_song(state, self.player) and
- _has_energy_form(state, self.player))
+ _has_energy_attack_item(state, self.player))
self.__connect_regions("Energy Temple first area", "Energy Temple blaster room",
self.energy_temple_1, self.energy_temple_blaster_room,
lambda state: _has_nature_form(state, self.player) and
_has_bind_song(state, self.player) and
- _has_energy_form(state, self.player) and
+ _has_energy_attack_item(state, self.player) and
_has_beast_form(state, self.player))
self.__connect_regions("Home Water", "Open Water top left area",
self.home_water, self.openwater_tl)
@@ -520,7 +545,7 @@ def __connect_open_water_regions(self) -> None:
self.openwater_tl, self.forest_br)
self.__connect_regions("Open Water top right area", "Open Water top right area, turtle room",
self.openwater_tr, self.openwater_tr_turtle,
- lambda state: _has_beast_form(state, self.player))
+ lambda state: _has_beast_form_or_arnassi_armor(state, self.player))
self.__connect_regions("Open Water top right area", "Open Water bottom right area",
self.openwater_tr, self.openwater_br)
self.__connect_regions("Open Water top right area", "Mithalas City",
@@ -529,10 +554,9 @@ def __connect_open_water_regions(self) -> None:
self.openwater_tr, self.veil_bl)
self.__connect_one_way_regions("Open Water top right area", "Veil bottom right",
self.openwater_tr, self.veil_br,
- lambda state: _has_beast_form(state, self.player))
+ lambda state: _has_beast_form_or_arnassi_armor(state, self.player))
self.__connect_one_way_regions("Veil bottom right", "Open Water top right area",
- self.veil_br, self.openwater_tr,
- lambda state: _has_beast_form(state, self.player))
+ self.veil_br, self.openwater_tr)
self.__connect_regions("Open Water bottom left area", "Open Water bottom right area",
self.openwater_bl, self.openwater_br)
self.__connect_regions("Open Water bottom left area", "Skeleton path",
@@ -551,10 +575,14 @@ def __connect_open_water_regions(self) -> None:
self.arnassi, self.openwater_br)
self.__connect_regions("Arnassi", "Arnassi path",
self.arnassi, self.arnassi_path)
+ self.__connect_regions("Arnassi ruins, transturtle area", "Arnassi path",
+ self.arnassi_cave_transturtle, self.arnassi_path,
+ lambda state: _has_fish_form(state, self.player))
self.__connect_one_way_regions("Arnassi path", "Arnassi crab boss area",
self.arnassi_path, self.arnassi_crab_boss,
- lambda state: _has_beast_form(state, self.player) and
- _has_energy_form(state, self.player))
+ lambda state: _has_beast_form_or_arnassi_armor(state, self.player) and
+ (_has_energy_attack_item(state, self.player) or
+ _has_nature_form(state, self.player)))
self.__connect_one_way_regions("Arnassi crab boss area", "Arnassi path",
self.arnassi_crab_boss, self.arnassi_path)
@@ -564,61 +592,62 @@ def __connect_mithalas_regions(self) -> None:
"""
self.__connect_one_way_regions("Mithalas City", "Mithalas City top path",
self.mithalas_city, self.mithalas_city_top_path,
- lambda state: _has_beast_form(state, self.player))
+ lambda state: _has_beast_form_or_arnassi_armor(state, self.player))
self.__connect_one_way_regions("Mithalas City_top_path", "Mithalas City",
self.mithalas_city_top_path, self.mithalas_city)
self.__connect_regions("Mithalas City", "Mithalas City home with fishpass",
self.mithalas_city, self.mithalas_city_fishpass,
lambda state: _has_fish_form(state, self.player))
self.__connect_regions("Mithalas City", "Mithalas castle",
- self.mithalas_city, self.cathedral_l,
- lambda state: _has_fish_form(state, self.player))
+ self.mithalas_city, self.cathedral_l)
self.__connect_one_way_regions("Mithalas City top path", "Mithalas castle, flower tube",
self.mithalas_city_top_path,
self.cathedral_l_tube,
lambda state: _has_nature_form(state, self.player) and
- _has_energy_form(state, self.player))
+ _has_energy_attack_item(state, self.player))
self.__connect_one_way_regions("Mithalas castle, flower tube area", "Mithalas City top path",
self.cathedral_l_tube,
self.mithalas_city_top_path,
- lambda state: _has_beast_form(state, self.player) and
- _has_nature_form(state, self.player))
+ lambda state: _has_nature_form(state, self.player))
self.__connect_one_way_regions("Mithalas castle flower tube area", "Mithalas castle, spirit crystals",
- self.cathedral_l_tube, self.cathedral_l_sc,
- lambda state: _has_spirit_form(state, self.player))
+ self.cathedral_l_tube, self.cathedral_l_sc,
+ lambda state: _has_spirit_form(state, self.player))
self.__connect_one_way_regions("Mithalas castle_flower tube area", "Mithalas castle",
- self.cathedral_l_tube, self.cathedral_l,
- lambda state: _has_spirit_form(state, self.player))
+ self.cathedral_l_tube, self.cathedral_l,
+ lambda state: _has_spirit_form(state, self.player))
self.__connect_regions("Mithalas castle", "Mithalas castle, spirit crystals",
self.cathedral_l, self.cathedral_l_sc,
lambda state: _has_spirit_form(state, self.player))
- self.__connect_regions("Mithalas castle", "Cathedral boss left area",
- self.cathedral_l, self.cathedral_boss_l,
- lambda state: _has_beast_form(state, self.player) and
- _has_energy_form(state, self.player) and
- _has_bind_song(state, self.player))
+ self.__connect_one_way_regions("Mithalas castle", "Cathedral boss right area",
+ self.cathedral_l, self.cathedral_boss_r,
+ lambda state: _has_beast_form(state, self.player))
+ self.__connect_one_way_regions("Cathedral boss left area", "Mithalas castle",
+ self.cathedral_boss_l, self.cathedral_l,
+ lambda state: _has_beast_form(state, self.player))
self.__connect_regions("Mithalas castle", "Mithalas Cathedral underground",
self.cathedral_l, self.cathedral_underground,
- lambda state: _has_beast_form(state, self.player) and
- _has_bind_song(state, self.player))
- self.__connect_regions("Mithalas castle", "Mithalas Cathedral",
- self.cathedral_l, self.cathedral_r,
- lambda state: _has_bind_song(state, self.player) and
- _has_energy_form(state, self.player))
- self.__connect_regions("Mithalas Cathedral", "Mithalas Cathedral underground",
- self.cathedral_r, self.cathedral_underground,
- lambda state: _has_energy_form(state, self.player))
- self.__connect_one_way_regions("Mithalas Cathedral underground", "Cathedral boss left area",
- self.cathedral_underground, self.cathedral_boss_r,
- lambda state: _has_energy_form(state, self.player) and
- _has_bind_song(state, self.player))
- self.__connect_one_way_regions("Cathedral boss left area", "Mithalas Cathedral underground",
+ lambda state: _has_beast_form(state, self.player))
+ self.__connect_one_way_regions("Mithalas castle", "Mithalas Cathedral",
+ self.cathedral_l, self.cathedral_r,
+ lambda state: _has_bind_song(state, self.player) and
+ _has_energy_attack_item(state, self.player))
+ self.__connect_one_way_regions("Mithalas Cathedral", "Mithalas Cathedral underground",
+ self.cathedral_r, self.cathedral_underground)
+ self.__connect_one_way_regions("Mithalas Cathedral underground", "Mithalas Cathedral",
+ self.cathedral_underground, self.cathedral_r,
+ lambda state: _has_beast_form(state, self.player) and
+ _has_energy_attack_item(state, self.player))
+ self.__connect_one_way_regions("Mithalas Cathedral underground", "Cathedral boss right area",
+ self.cathedral_underground, self.cathedral_boss_r)
+ self.__connect_one_way_regions("Cathedral boss right area", "Mithalas Cathedral underground",
self.cathedral_boss_r, self.cathedral_underground,
lambda state: _has_beast_form(state, self.player))
- self.__connect_regions("Cathedral boss right area", "Cathedral boss left area",
+ self.__connect_one_way_regions("Cathedral boss right area", "Cathedral boss left area",
self.cathedral_boss_r, self.cathedral_boss_l,
lambda state: _has_bind_song(state, self.player) and
- _has_energy_form(state, self.player))
+ _has_energy_attack_item(state, self.player))
+ self.__connect_one_way_regions("Cathedral boss left area", "Cathedral boss right area",
+ self.cathedral_boss_l, self.cathedral_boss_r)
def __connect_forest_regions(self) -> None:
"""
@@ -628,6 +657,12 @@ def __connect_forest_regions(self) -> None:
self.forest_br, self.veil_bl)
self.__connect_regions("Forest bottom right", "Forest bottom left area",
self.forest_br, self.forest_bl)
+ self.__connect_one_way_regions("Forest bottom left area", "Forest bottom left area, spirit crystals",
+ self.forest_bl, self.forest_bl_sc,
+ lambda state: _has_energy_attack_item(state, self.player) or
+ _has_fish_form(state, self.player))
+ self.__connect_one_way_regions("Forest bottom left area, spirit crystals", "Forest bottom left area",
+ self.forest_bl_sc, self.forest_bl)
self.__connect_regions("Forest bottom right", "Forest top right area",
self.forest_br, self.forest_tr)
self.__connect_regions("Forest bottom left area", "Forest fish cave",
@@ -641,7 +676,7 @@ def __connect_forest_regions(self) -> None:
self.forest_tl, self.forest_tl_fp,
lambda state: _has_nature_form(state, self.player) and
_has_bind_song(state, self.player) and
- _has_energy_form(state, self.player) and
+ _has_energy_attack_item(state, self.player) and
_has_fish_form(state, self.player))
self.__connect_regions("Forest top left area", "Forest top right area",
self.forest_tl, self.forest_tr)
@@ -649,7 +684,7 @@ def __connect_forest_regions(self) -> None:
self.forest_tl, self.forest_boss_entrance)
self.__connect_regions("Forest boss area", "Forest boss entrance",
self.forest_boss, self.forest_boss_entrance,
- lambda state: _has_energy_form(state, self.player))
+ lambda state: _has_energy_attack_item(state, self.player))
self.__connect_regions("Forest top right area", "Forest top right area fish pass",
self.forest_tr, self.forest_tr_fp,
lambda state: _has_fish_form(state, self.player))
@@ -663,7 +698,7 @@ def __connect_forest_regions(self) -> None:
self.__connect_regions("Fermog cave", "Fermog boss",
self.mermog_cave, self.mermog_boss,
lambda state: _has_beast_form(state, self.player) and
- _has_energy_form(state, self.player))
+ _has_energy_attack_item(state, self.player))
def __connect_veil_regions(self) -> None:
"""
@@ -681,8 +716,7 @@ def __connect_veil_regions(self) -> None:
self.veil_b_sc, self.veil_br,
lambda state: _has_spirit_form(state, self.player))
self.__connect_regions("Veil bottom right", "Veil top left area",
- self.veil_br, self.veil_tl,
- lambda state: _has_beast_form(state, self.player))
+ self.veil_br, self.veil_tl)
self.__connect_regions("Veil top left area", "Veil_top left area, fish pass",
self.veil_tl, self.veil_tl_fp,
lambda state: _has_fish_form(state, self.player))
@@ -691,20 +725,25 @@ def __connect_veil_regions(self) -> None:
self.__connect_regions("Veil top left area", "Turtle cave",
self.veil_tl, self.turtle_cave)
self.__connect_regions("Turtle cave", "Turtle cave Bubble Cliff",
- self.turtle_cave, self.turtle_cave_bubble,
- lambda state: _has_beast_form(state, self.player))
+ self.turtle_cave, self.turtle_cave_bubble)
self.__connect_regions("Veil right of sun temple", "Sun Temple right area",
self.veil_tr_r, self.sun_temple_r)
- self.__connect_regions("Sun Temple right area", "Sun Temple left area",
- self.sun_temple_r, self.sun_temple_l,
- lambda state: _has_bind_song(state, self.player))
+ self.__connect_one_way_regions("Sun Temple right area", "Sun Temple left area",
+ self.sun_temple_r, self.sun_temple_l,
+ lambda state: _has_bind_song(state, self.player) or
+ _has_light(state, self.player))
+ self.__connect_one_way_regions("Sun Temple left area", "Sun Temple right area",
+ self.sun_temple_l, self.sun_temple_r,
+ lambda state: _has_light(state, self.player))
self.__connect_regions("Sun Temple left area", "Veil left of sun temple",
self.sun_temple_l, self.veil_tr_l)
self.__connect_regions("Sun Temple left area", "Sun Temple before boss area",
- self.sun_temple_l, self.sun_temple_boss_path)
+ self.sun_temple_l, self.sun_temple_boss_path,
+ lambda state: _has_light(state, self.player) or
+ _has_sun_crystal(state, self.player))
self.__connect_regions("Sun Temple before boss area", "Sun Temple boss area",
self.sun_temple_boss_path, self.sun_temple_boss,
- lambda state: _has_energy_form(state, self.player))
+ lambda state: _has_energy_attack_item(state, self.player))
self.__connect_one_way_regions("Sun Temple boss area", "Veil left of sun temple",
self.sun_temple_boss, self.veil_tr_l)
self.__connect_regions("Veil left of sun temple", "Octo cave top path",
@@ -712,7 +751,7 @@ def __connect_veil_regions(self) -> None:
lambda state: _has_fish_form(state, self.player) and
_has_sun_form(state, self.player) and
_has_beast_form(state, self.player) and
- _has_energy_form(state, self.player))
+ _has_energy_attack_item(state, self.player))
self.__connect_regions("Veil left of sun temple", "Octo cave bottom path",
self.veil_tr_l, self.octo_cave_b,
lambda state: _has_fish_form(state, self.player))
@@ -728,16 +767,22 @@ def __connect_abyss_regions(self) -> None:
self.abyss_lb, self.sunken_city_r,
lambda state: _has_li(state, self.player))
self.__connect_one_way_regions("Abyss left bottom area", "Body center area",
- self.abyss_lb, self.body_c,
- lambda state: _has_tongue_cleared(state, self.player))
+ self.abyss_lb, self.body_c,
+ lambda state: _has_tongue_cleared(state, self.player))
self.__connect_one_way_regions("Body center area", "Abyss left bottom area",
- self.body_c, self.abyss_lb)
+ self.body_c, self.abyss_lb)
self.__connect_regions("Abyss left area", "King jellyfish cave",
self.abyss_l, self.king_jellyfish_cave,
- lambda state: _has_energy_form(state, self.player) and
- _has_beast_form(state, self.player))
+ lambda state: (_has_energy_form(state, self.player) and
+ _has_beast_form(state, self.player)) or
+ _has_dual_form(state, self.player))
self.__connect_regions("Abyss left area", "Abyss right area",
self.abyss_l, self.abyss_r)
+ self.__connect_one_way_regions("Abyss right area", "Abyss right area, transturtle",
+ self.abyss_r, self.abyss_r_transturtle)
+ self.__connect_one_way_regions("Abyss right area, transturtle", "Abyss right area",
+ self.abyss_r_transturtle, self.abyss_r,
+ lambda state: _has_light(state, self.player))
self.__connect_regions("Abyss right area", "Inside the whale",
self.abyss_r, self.whale,
lambda state: _has_spirit_form(state, self.player) and
@@ -747,13 +792,14 @@ def __connect_abyss_regions(self) -> None:
lambda state: _has_spirit_form(state, self.player) and
_has_sun_form(state, self.player) and
_has_bind_song(state, self.player) and
- _has_energy_form(state, self.player))
+ _has_energy_attack_item(state, self.player))
self.__connect_regions("Abyss right area", "Ice Cave",
self.abyss_r, self.ice_cave,
lambda state: _has_spirit_form(state, self.player))
- self.__connect_regions("Abyss right area", "Bubble Cave",
+ self.__connect_regions("Ice cave", "Bubble Cave",
self.ice_cave, self.bubble_cave,
- lambda state: _has_beast_form(state, self.player))
+ lambda state: _has_beast_form(state, self.player) or
+ _has_hot_soup(state, self.player))
self.__connect_regions("Bubble Cave boss area", "Bubble Cave",
self.bubble_cave, self.bubble_cave_boss,
lambda state: _has_nature_form(state, self.player) and _has_bind_song(state, self.player)
@@ -772,7 +818,7 @@ def __connect_sunken_city_regions(self) -> None:
self.sunken_city_l, self.sunken_city_boss,
lambda state: _has_beast_form(state, self.player) and
_has_sun_form(state, self.player) and
- _has_energy_form(state, self.player) and
+ _has_energy_attack_item(state, self.player) and
_has_bind_song(state, self.player))
def __connect_body_regions(self) -> None:
@@ -780,11 +826,13 @@ def __connect_body_regions(self) -> None:
Connect entrances of the different regions around The Body
"""
self.__connect_regions("Body center area", "Body left area",
- self.body_c, self.body_l)
+ self.body_c, self.body_l,
+ lambda state: _has_energy_form(state, self.player))
self.__connect_regions("Body center area", "Body right area top path",
self.body_c, self.body_rt)
self.__connect_regions("Body center area", "Body right area bottom path",
- self.body_c, self.body_rb)
+ self.body_c, self.body_rb,
+ lambda state: _has_energy_form(state, self.player))
self.__connect_regions("Body center area", "Body bottom area",
self.body_c, self.body_b,
lambda state: _has_dual_form(state, self.player))
@@ -803,22 +851,12 @@ def __connect_body_regions(self) -> None:
self.__connect_one_way_regions("final boss third form area", "final boss end",
self.final_boss, self.final_boss_end)
- def __connect_transturtle(self, item_source: str, item_target: str, region_source: Region, region_target: Region,
- rule=None) -> None:
+ def __connect_transturtle(self, item_source: str, item_target: str, region_source: Region,
+ region_target: Region) -> None:
"""Connect a single transturtle to another one"""
if item_source != item_target:
- if rule is None:
- self.__connect_one_way_regions(item_source, item_target, region_source, region_target,
- lambda state: state.has(item_target, self.player))
- else:
- self.__connect_one_way_regions(item_source, item_target, region_source, region_target, rule)
-
- def __connect_arnassi_path_transturtle(self, item_source: str, item_target: str, region_source: Region,
- region_target: Region) -> None:
- """Connect the Arnassi Ruins transturtle to another one"""
- self.__connect_one_way_regions(item_source, item_target, region_source, region_target,
- lambda state: state.has(item_target, self.player) and
- _has_fish_form(state, self.player))
+ self.__connect_one_way_regions(item_source, item_target, region_source, region_target,
+ lambda state: state.has(item_target, self.player))
def _connect_transturtle_to_other(self, item: str, region: Region) -> None:
"""Connect a single transturtle to all others"""
@@ -827,24 +865,10 @@ def _connect_transturtle_to_other(self, item: str, region: Region) -> None:
self.__connect_transturtle(item, "Transturtle Open Water top right", region, self.openwater_tr_turtle)
self.__connect_transturtle(item, "Transturtle Forest bottom left", region, self.forest_bl)
self.__connect_transturtle(item, "Transturtle Home Water", region, self.home_water_transturtle)
- self.__connect_transturtle(item, "Transturtle Abyss right", region, self.abyss_r)
+ self.__connect_transturtle(item, "Transturtle Abyss right", region, self.abyss_r_transturtle)
self.__connect_transturtle(item, "Transturtle Final Boss", region, self.final_boss_tube)
self.__connect_transturtle(item, "Transturtle Simon Says", region, self.simon)
- self.__connect_transturtle(item, "Transturtle Arnassi Ruins", region, self.arnassi_path,
- lambda state: state.has("Transturtle Arnassi Ruins", self.player) and
- _has_fish_form(state, self.player))
-
- def _connect_arnassi_path_transturtle_to_other(self, item: str, region: Region) -> None:
- """Connect the Arnassi Ruins transturtle to all others"""
- self.__connect_arnassi_path_transturtle(item, "Transturtle Veil top left", region, self.veil_tl)
- self.__connect_arnassi_path_transturtle(item, "Transturtle Veil top right", region, self.veil_tr_l)
- self.__connect_arnassi_path_transturtle(item, "Transturtle Open Water top right", region,
- self.openwater_tr_turtle)
- self.__connect_arnassi_path_transturtle(item, "Transturtle Forest bottom left", region, self.forest_bl)
- self.__connect_arnassi_path_transturtle(item, "Transturtle Home Water", region, self.home_water_transturtle)
- self.__connect_arnassi_path_transturtle(item, "Transturtle Abyss right", region, self.abyss_r)
- self.__connect_arnassi_path_transturtle(item, "Transturtle Final Boss", region, self.final_boss_tube)
- self.__connect_arnassi_path_transturtle(item, "Transturtle Simon Says", region, self.simon)
+ self.__connect_transturtle(item, "Transturtle Arnassi Ruins", region, self.arnassi_cave_transturtle)
def __connect_transturtles(self) -> None:
"""Connect every transturtle with others"""
@@ -853,10 +877,10 @@ def __connect_transturtles(self) -> None:
self._connect_transturtle_to_other("Transturtle Open Water top right", self.openwater_tr_turtle)
self._connect_transturtle_to_other("Transturtle Forest bottom left", self.forest_bl)
self._connect_transturtle_to_other("Transturtle Home Water", self.home_water_transturtle)
- self._connect_transturtle_to_other("Transturtle Abyss right", self.abyss_r)
+ self._connect_transturtle_to_other("Transturtle Abyss right", self.abyss_r_transturtle)
self._connect_transturtle_to_other("Transturtle Final Boss", self.final_boss_tube)
self._connect_transturtle_to_other("Transturtle Simon Says", self.simon)
- self._connect_arnassi_path_transturtle_to_other("Transturtle Arnassi Ruins", self.arnassi_path)
+ self._connect_transturtle_to_other("Transturtle Arnassi Ruins", self.arnassi_cave_transturtle)
def connect_regions(self) -> None:
"""
@@ -893,7 +917,7 @@ def __add_event_big_bosses(self) -> None:
self.__add_event_location(self.energy_temple_boss,
"Beating Fallen God",
"Fallen God beated")
- self.__add_event_location(self.cathedral_boss_r,
+ self.__add_event_location(self.cathedral_boss_l,
"Beating Mithalan God",
"Mithalan God beated")
self.__add_event_location(self.forest_boss,
@@ -970,8 +994,9 @@ def __adjusting_urns_rules(self) -> None:
"""Since Urns need to be broken, add a damaging item to rules"""
add_rule(self.multiworld.get_location("Open Water top right area, first urn in the Mithalas exit", self.player),
lambda state: _has_damaging_item(state, self.player))
- add_rule(self.multiworld.get_location("Open Water top right area, second urn in the Mithalas exit", self.player),
- lambda state: _has_damaging_item(state, self.player))
+ add_rule(
+ self.multiworld.get_location("Open Water top right area, second urn in the Mithalas exit", self.player),
+ lambda state: _has_damaging_item(state, self.player))
add_rule(self.multiworld.get_location("Open Water top right area, third urn in the Mithalas exit", self.player),
lambda state: _has_damaging_item(state, self.player))
add_rule(self.multiworld.get_location("Mithalas City, first urn in one of the homes", self.player),
@@ -1019,66 +1044,46 @@ def __adjusting_soup_rules(self) -> None:
Modify rules for location that need soup
"""
add_rule(self.multiworld.get_location("Turtle cave, Urchin Costume", self.player),
- lambda state: _has_hot_soup(state, self.player) and _has_beast_form(state, self.player))
- add_rule(self.multiworld.get_location("Sun Worm path, first cliff bulb", self.player),
- lambda state: _has_hot_soup(state, self.player) and _has_beast_form(state, self.player))
- add_rule(self.multiworld.get_location("Sun Worm path, second cliff bulb", self.player),
- lambda state: _has_hot_soup(state, self.player) and _has_beast_form(state, self.player))
+ lambda state: _has_hot_soup(state, self.player))
add_rule(self.multiworld.get_location("The Veil top right area, bulb at the top of the waterfall", self.player),
- lambda state: _has_hot_soup(state, self.player) and _has_beast_form(state, self.player))
+ lambda state: _has_beast_and_soup_form(state, self.player))
def __adjusting_under_rock_location(self) -> None:
"""
Modify rules implying bind song needed for bulb under rocks
"""
add_rule(self.multiworld.get_location("Home Water, bulb under the rock in the left path from the Verse Cave",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Verse Cave left area, bulb under the rock at the end of the path",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Naija's Home, bulb under the rock at the right of the main path",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Song Cave, bulb under the rock in the path to the singing statues",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Song Cave, bulb under the rock close to the song door",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Energy Temple second area, bulb under the rock",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Open Water top left area, bulb under the rock in the right path",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Open Water top left area, bulb under the rock in the left path",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Kelp Forest top right area, bulb under the rock in the right path",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("The Veil top left area, bulb under the rock in the top right path",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Abyss right area, bulb behind the rock in the whale room",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Abyss right area, bulb in the middle path",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("The Veil top left area, bulb under the rock in the top right path",
- self.player), lambda state: _has_bind_song(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
def __adjusting_light_in_dark_place_rules(self) -> None:
add_rule(self.multiworld.get_location("Kelp Forest top right area, Black Pearl", self.player),
lambda state: _has_light(state, self.player))
add_rule(self.multiworld.get_location("Kelp Forest bottom right area, Odd Container", self.player),
lambda state: _has_light(state, self.player))
- add_rule(self.multiworld.get_entrance("Transturtle Veil top left to Transturtle Abyss right", self.player),
- lambda state: _has_light(state, self.player))
- add_rule(self.multiworld.get_entrance("Transturtle Open Water top right to Transturtle Abyss right", self.player),
- lambda state: _has_light(state, self.player))
- add_rule(self.multiworld.get_entrance("Transturtle Veil top right to Transturtle Abyss right", self.player),
- lambda state: _has_light(state, self.player))
- add_rule(self.multiworld.get_entrance("Transturtle Forest bottom left to Transturtle Abyss right", self.player),
- lambda state: _has_light(state, self.player))
- add_rule(self.multiworld.get_entrance("Transturtle Home Water to Transturtle Abyss right", self.player),
- lambda state: _has_light(state, self.player))
- add_rule(self.multiworld.get_entrance("Transturtle Final Boss to Transturtle Abyss right", self.player),
- lambda state: _has_light(state, self.player))
- add_rule(self.multiworld.get_entrance("Transturtle Simon Says to Transturtle Abyss right", self.player),
- lambda state: _has_light(state, self.player))
- add_rule(self.multiworld.get_entrance("Transturtle Arnassi Ruins to Transturtle Abyss right", self.player),
- lambda state: _has_light(state, self.player))
add_rule(self.multiworld.get_entrance("Body center area to Abyss left bottom area", self.player),
lambda state: _has_light(state, self.player))
add_rule(self.multiworld.get_entrance("Veil left of sun temple to Octo cave top path", self.player),
@@ -1097,12 +1102,14 @@ def __adjusting_light_in_dark_place_rules(self) -> None:
def __adjusting_manual_rules(self) -> None:
add_rule(self.multiworld.get_location("Mithalas Cathedral, Mithalan Dress", self.player),
lambda state: _has_beast_form(state, self.player))
- add_rule(self.multiworld.get_location("Open Water bottom left area, bulb inside the lowest fish pass", self.player),
- lambda state: _has_fish_form(state, self.player))
+ add_rule(
+ self.multiworld.get_location("Open Water bottom left area, bulb inside the lowest fish pass", self.player),
+ lambda state: _has_fish_form(state, self.player))
add_rule(self.multiworld.get_location("Kelp Forest bottom left area, Walker Baby", self.player),
lambda state: _has_spirit_form(state, self.player))
- add_rule(self.multiworld.get_location("The Veil top left area, bulb hidden behind the blocking rock", self.player),
- lambda state: _has_bind_song(state, self.player))
+ add_rule(
+ self.multiworld.get_location("The Veil top left area, bulb hidden behind the blocking rock", self.player),
+ lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Turtle cave, Turtle Egg", self.player),
lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Abyss left area, bulb in the bottom fish pass", self.player),
@@ -1114,103 +1121,119 @@ def __adjusting_manual_rules(self) -> None:
add_rule(self.multiworld.get_location("Verse Cave right area, Big Seed", self.player),
lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Arnassi Ruins, Song Plant Spore", self.player),
- lambda state: _has_beast_form(state, self.player))
+ lambda state: _has_beast_form_or_arnassi_armor(state, self.player))
add_rule(self.multiworld.get_location("Energy Temple first area, bulb in the bottom room blocked by a rock",
- self.player), lambda state: _has_energy_form(state, self.player))
+ self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Home Water, bulb in the bottom left room", self.player),
lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Home Water, bulb in the path below Nautilus Prime", self.player),
lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location("Naija's Home, bulb after the energy door", self.player),
- lambda state: _has_energy_form(state, self.player))
+ lambda state: _has_energy_attack_item(state, self.player))
add_rule(self.multiworld.get_location("Abyss right area, bulb behind the rock in the whale room", self.player),
lambda state: _has_spirit_form(state, self.player) and
_has_sun_form(state, self.player))
add_rule(self.multiworld.get_location("Arnassi Ruins, Arnassi Armor", self.player),
- lambda state: _has_fish_form(state, self.player) and
- _has_spirit_form(state, self.player))
+ lambda state: _has_fish_form(state, self.player) or
+ _has_beast_and_soup_form(state, self.player))
+ add_rule(self.multiworld.get_location("Mithalas City, urn inside a home fish pass", self.player),
+ lambda state: _has_damaging_item(state, self.player))
+ add_rule(self.multiworld.get_location("Mithalas City, urn in the Castle flower tube entrance", self.player),
+ lambda state: _has_damaging_item(state, self.player))
+ add_rule(self.multiworld.get_location(
+ "The Veil top right area, bulb in the middle of the wall jump cliff", self.player
+ ), lambda state: _has_beast_form_or_arnassi_armor(state, self.player))
+ add_rule(self.multiworld.get_location("Kelp Forest top left area, Jelly Egg", self.player),
+ lambda state: _has_beast_form(state, self.player))
+ add_rule(self.multiworld.get_location("Sun Worm path, first cliff bulb", self.player),
+ lambda state: state.has("Sun God beated", self.player))
+ add_rule(self.multiworld.get_location("Sun Worm path, second cliff bulb", self.player),
+ lambda state: state.has("Sun God beated", self.player))
+ add_rule(self.multiworld.get_location("The Body center area, breaking Li's cage", self.player),
+ lambda state: _has_tongue_cleared(state, self.player))
def __no_progression_hard_or_hidden_location(self) -> None:
self.multiworld.get_location("Energy Temple boss area, Fallen God Tooth",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Mithalas boss area, beating Mithalan God",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Kelp Forest boss area, beating Drunian God",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Sun Temple boss area, beating Sun God",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Sunken City, bulb on top of the boss area",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Home Water, Nautilus Egg",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Energy Temple blaster room, Blaster Egg",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Mithalas City Castle, beating the Priests",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Mermog cave, Piranha Egg",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Octopus Cave, Dumbo Egg",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("King Jellyfish Cave, bulb in the right path from King Jelly",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("King Jellyfish Cave, Jellyfish Costume",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Final Boss area, bulb in the boss third form room",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Sun Worm path, first cliff bulb",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Sun Worm path, second cliff bulb",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("The Veil top right area, bulb at the top of the waterfall",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Bubble Cave, bulb in the left cave wall",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Bubble Cave, bulb in the right cave wall (behind the ice crystal)",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Bubble Cave, Verse Egg",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Kelp Forest bottom left area, bulb close to the spirit crystals",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Kelp Forest bottom left area, Walker Baby",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Sun Temple, Sun Key",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("The Body bottom area, Mutant Costume",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Sun Temple, bulb in the hidden room of the right part",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
self.multiworld.get_location("Arnassi Ruins, Arnassi Armor",
- self.player).item_rule =\
+ self.player).item_rule = \
lambda item: item.classification != ItemClassification.progression
def adjusting_rules(self, options: AquariaOptions) -> None:
"""
Modify rules for single location or optional rules
"""
+ self.multiworld.get_entrance("Before Final Boss to Final Boss", self.player)
self.__adjusting_urns_rules()
self.__adjusting_crates_rules()
self.__adjusting_soup_rules()
@@ -1234,7 +1257,7 @@ def adjusting_rules(self, options: AquariaOptions) -> None:
lambda state: _has_bind_song(state, self.player))
if options.unconfine_home_water.value in [0, 2]:
add_rule(self.multiworld.get_entrance("Home Water to Open Water top left area", self.player),
- lambda state: _has_bind_song(state, self.player) and _has_energy_form(state, self.player))
+ lambda state: _has_bind_song(state, self.player) and _has_energy_attack_item(state, self.player))
if options.early_energy_form:
self.multiworld.early_items[self.player]["Energy form"] = 1
@@ -1274,6 +1297,7 @@ def __add_open_water_regions_to_world(self) -> None:
self.multiworld.regions.append(self.arnassi)
self.multiworld.regions.append(self.arnassi_path)
self.multiworld.regions.append(self.arnassi_crab_boss)
+ self.multiworld.regions.append(self.arnassi_cave_transturtle)
self.multiworld.regions.append(self.simon)
def __add_mithalas_regions_to_world(self) -> None:
@@ -1300,6 +1324,7 @@ def __add_forest_regions_to_world(self) -> None:
self.multiworld.regions.append(self.forest_tr)
self.multiworld.regions.append(self.forest_tr_fp)
self.multiworld.regions.append(self.forest_bl)
+ self.multiworld.regions.append(self.forest_bl_sc)
self.multiworld.regions.append(self.forest_br)
self.multiworld.regions.append(self.forest_boss)
self.multiworld.regions.append(self.forest_boss_entrance)
@@ -1337,6 +1362,7 @@ def __add_abyss_regions_to_world(self) -> None:
self.multiworld.regions.append(self.abyss_l)
self.multiworld.regions.append(self.abyss_lb)
self.multiworld.regions.append(self.abyss_r)
+ self.multiworld.regions.append(self.abyss_r_transturtle)
self.multiworld.regions.append(self.ice_cave)
self.multiworld.regions.append(self.bubble_cave)
self.multiworld.regions.append(self.bubble_cave_boss)
diff --git a/worlds/aquaria/test/__init__.py b/worlds/aquaria/test/__init__.py
index 029db691b66b..8c4f64c3452c 100644
--- a/worlds/aquaria/test/__init__.py
+++ b/worlds/aquaria/test/__init__.py
@@ -141,7 +141,7 @@
"Sun Temple, bulb at the top of the high dark room",
"Sun Temple, Golden Gear",
"Sun Temple, first bulb of the temple",
- "Sun Temple, bulb on the left part",
+ "Sun Temple, bulb on the right part",
"Sun Temple, bulb in the hidden room of the right part",
"Sun Temple, Sun Key",
"Sun Worm path, first path bulb",
diff --git a/worlds/aquaria/test/test_beast_form_access.py b/worlds/aquaria/test/test_beast_form_access.py
index 0efc3e7388fe..c09586269d38 100644
--- a/worlds/aquaria/test/test_beast_form_access.py
+++ b/worlds/aquaria/test/test_beast_form_access.py
@@ -13,36 +13,16 @@ class BeastFormAccessTest(AquariaTestBase):
def test_beast_form_location(self) -> None:
"""Test locations that require beast form"""
locations = [
- "Mithalas City Castle, beating the Priests",
- "Arnassi Ruins, Crab Armor",
- "Arnassi Ruins, Song Plant Spore",
- "Mithalas City, first bulb at the end of the top path",
- "Mithalas City, second bulb at the end of the top path",
- "Mithalas City, bulb in the top path",
- "Mithalas City, Mithalas Pot",
- "Mithalas City, urn in the Castle flower tube entrance",
"Mermog cave, Piranha Egg",
+ "Kelp Forest top left area, Jelly Egg",
"Mithalas Cathedral, Mithalan Dress",
- "Turtle cave, bulb in Bubble Cliff",
- "Turtle cave, Urchin Costume",
- "Sun Worm path, first cliff bulb",
- "Sun Worm path, second cliff bulb",
"The Veil top right area, bulb at the top of the waterfall",
- "Bubble Cave, bulb in the left cave wall",
- "Bubble Cave, bulb in the right cave wall (behind the ice crystal)",
- "Bubble Cave, Verse Egg",
"Sunken City, bulb on top of the boss area",
"Octopus Cave, Dumbo Egg",
"Beating the Golem",
"Beating Mergog",
- "Beating Crabbius Maximus",
"Beating Octopus Prime",
- "Beating Mantis Shrimp Prime",
- "King Jellyfish Cave, Jellyfish Costume",
- "King Jellyfish Cave, bulb in the right path from King Jelly",
- "Beating King Jellyfish God Prime",
- "Beating Mithalan priests",
- "Sunken City cleared"
+ "Sunken City cleared",
]
items = [["Beast form"]]
self.assertAccessDependency(locations, items)
diff --git a/worlds/aquaria/test/test_beast_form_or_arnassi_armor_access.py b/worlds/aquaria/test/test_beast_form_or_arnassi_armor_access.py
new file mode 100644
index 000000000000..fa4c6923400a
--- /dev/null
+++ b/worlds/aquaria/test/test_beast_form_or_arnassi_armor_access.py
@@ -0,0 +1,39 @@
+"""
+Author: Louis M
+Date: Thu, 18 Apr 2024 18:45:56 +0000
+Description: Unit test used to test accessibility of locations with and without the beast form or arnassi armor
+"""
+
+from . import AquariaTestBase
+
+
+class BeastForArnassiArmormAccessTest(AquariaTestBase):
+ """Unit test used to test accessibility of locations with and without the beast form or arnassi armor"""
+
+ def test_beast_form_arnassi_armor_location(self) -> None:
+ """Test locations that require beast form or arnassi armor"""
+ locations = [
+ "Mithalas City Castle, beating the Priests",
+ "Arnassi Ruins, Crab Armor",
+ "Arnassi Ruins, Song Plant Spore",
+ "Mithalas City, first bulb at the end of the top path",
+ "Mithalas City, second bulb at the end of the top path",
+ "Mithalas City, bulb in the top path",
+ "Mithalas City, Mithalas Pot",
+ "Mithalas City, urn in the Castle flower tube entrance",
+ "Mermog cave, Piranha Egg",
+ "Mithalas Cathedral, Mithalan Dress",
+ "Kelp Forest top left area, Jelly Egg",
+ "The Veil top right area, bulb in the middle of the wall jump cliff",
+ "The Veil top right area, bulb at the top of the waterfall",
+ "Sunken City, bulb on top of the boss area",
+ "Octopus Cave, Dumbo Egg",
+ "Beating the Golem",
+ "Beating Mergog",
+ "Beating Crabbius Maximus",
+ "Beating Octopus Prime",
+ "Beating Mithalan priests",
+ "Sunken City cleared"
+ ]
+ items = [["Beast form", "Arnassi Armor"]]
+ self.assertAccessDependency(locations, items)
diff --git a/worlds/aquaria/test/test_energy_form_access.py b/worlds/aquaria/test/test_energy_form_access.py
index 82d8e89a0066..b443166823bc 100644
--- a/worlds/aquaria/test/test_energy_form_access.py
+++ b/worlds/aquaria/test/test_energy_form_access.py
@@ -17,55 +17,16 @@ class EnergyFormAccessTest(AquariaTestBase):
def test_energy_form_location(self) -> None:
"""Test locations that require Energy form"""
locations = [
- "Home Water, Nautilus Egg",
- "Naija's Home, bulb after the energy door",
- "Energy Temple first area, bulb in the bottom room blocked by a rock",
"Energy Temple second area, bulb under the rock",
- "Energy Temple bottom entrance, Krotite Armor",
"Energy Temple third area, bulb in the bottom path",
- "Energy Temple boss area, Fallen God Tooth",
- "Energy Temple blaster room, Blaster Egg",
- "Mithalas City Castle, beating the Priests",
- "Mithalas Cathedral, first urn in the top right room",
- "Mithalas Cathedral, second urn in the top right room",
- "Mithalas Cathedral, third urn in the top right room",
- "Mithalas Cathedral, urn in the flesh room with fleas",
- "Mithalas Cathedral, first urn in the bottom right path",
- "Mithalas Cathedral, second urn in the bottom right path",
- "Mithalas Cathedral, urn behind the flesh vein",
- "Mithalas Cathedral, urn in the top left eyes boss room",
- "Mithalas Cathedral, first urn in the path behind the flesh vein",
- "Mithalas Cathedral, second urn in the path behind the flesh vein",
- "Mithalas Cathedral, third urn in the path behind the flesh vein",
- "Mithalas Cathedral, fourth urn in the top right room",
- "Mithalas Cathedral, Mithalan Dress",
- "Mithalas Cathedral, urn below the left entrance",
- "Mithalas boss area, beating Mithalan God",
- "Kelp Forest top left area, bulb close to the Verse Egg",
- "Kelp Forest top left area, Verse Egg",
- "Kelp Forest boss area, beating Drunian God",
- "Mermog cave, Piranha Egg",
- "Octopus Cave, Dumbo Egg",
- "Sun Temple boss area, beating Sun God",
- "Arnassi Ruins, Crab Armor",
- "King Jellyfish Cave, bulb in the right path from King Jelly",
- "King Jellyfish Cave, Jellyfish Costume",
- "Sunken City, bulb on top of the boss area",
+ "The Body left area, first bulb in the top face room",
+ "The Body left area, second bulb in the top face room",
+ "The Body left area, bulb below the water stream",
+ "The Body left area, bulb in the top path to the top face room",
+ "The Body left area, bulb in the bottom face room",
+ "The Body right area, bulb in the top path to the bottom face room",
+ "The Body right area, bulb in the bottom face room",
"Final Boss area, bulb in the boss third form room",
- "Beating Fallen God",
- "Beating Mithalan God",
- "Beating Drunian God",
- "Beating Sun God",
- "Beating the Golem",
- "Beating Nautilus Prime",
- "Beating Blaster Peg Prime",
- "Beating Mergog",
- "Beating Mithalan priests",
- "Beating Octopus Prime",
- "Beating Crabbius Maximus",
- "Beating King Jellyfish God Prime",
- "First secret",
- "Sunken City cleared",
"Objective complete",
]
items = [["Energy form"]]
diff --git a/worlds/aquaria/test/test_energy_form_or_dual_form_access.py b/worlds/aquaria/test/test_energy_form_or_dual_form_access.py
new file mode 100644
index 000000000000..8a765bc4e4e2
--- /dev/null
+++ b/worlds/aquaria/test/test_energy_form_or_dual_form_access.py
@@ -0,0 +1,92 @@
+"""
+Author: Louis M
+Date: Thu, 18 Apr 2024 18:45:56 +0000
+Description: Unit test used to test accessibility of locations with and without the energy form and dual form (and Li)
+"""
+
+from . import AquariaTestBase
+
+
+class EnergyFormDualFormAccessTest(AquariaTestBase):
+ """Unit test used to test accessibility of locations with and without the energy form and dual form (and Li)"""
+ options = {
+ "early_energy_form": False,
+ }
+
+ def test_energy_form_or_dual_form_location(self) -> None:
+ """Test locations that require Energy form or dual form"""
+ locations = [
+ "Naija's Home, bulb after the energy door",
+ "Home Water, Nautilus Egg",
+ "Energy Temple second area, bulb under the rock",
+ "Energy Temple bottom entrance, Krotite Armor",
+ "Energy Temple third area, bulb in the bottom path",
+ "Energy Temple blaster room, Blaster Egg",
+ "Energy Temple boss area, Fallen God Tooth",
+ "Mithalas City Castle, beating the Priests",
+ "Mithalas boss area, beating Mithalan God",
+ "Mithalas Cathedral, first urn in the top right room",
+ "Mithalas Cathedral, second urn in the top right room",
+ "Mithalas Cathedral, third urn in the top right room",
+ "Mithalas Cathedral, urn in the flesh room with fleas",
+ "Mithalas Cathedral, first urn in the bottom right path",
+ "Mithalas Cathedral, second urn in the bottom right path",
+ "Mithalas Cathedral, urn behind the flesh vein",
+ "Mithalas Cathedral, urn in the top left eyes boss room",
+ "Mithalas Cathedral, first urn in the path behind the flesh vein",
+ "Mithalas Cathedral, second urn in the path behind the flesh vein",
+ "Mithalas Cathedral, third urn in the path behind the flesh vein",
+ "Mithalas Cathedral, fourth urn in the top right room",
+ "Mithalas Cathedral, Mithalan Dress",
+ "Mithalas Cathedral, urn below the left entrance",
+ "Kelp Forest top left area, bulb close to the Verse Egg",
+ "Kelp Forest top left area, Verse Egg",
+ "Kelp Forest boss area, beating Drunian God",
+ "Mermog cave, Piranha Egg",
+ "Octopus Cave, Dumbo Egg",
+ "Sun Temple boss area, beating Sun God",
+ "King Jellyfish Cave, bulb in the right path from King Jelly",
+ "King Jellyfish Cave, Jellyfish Costume",
+ "Sunken City right area, crate close to the save crystal",
+ "Sunken City right area, crate in the left bottom room",
+ "Sunken City left area, crate in the little pipe room",
+ "Sunken City left area, crate close to the save crystal",
+ "Sunken City left area, crate before the bedroom",
+ "Sunken City left area, Girl Costume",
+ "Sunken City, bulb on top of the boss area",
+ "The Body center area, breaking Li's cage",
+ "The Body center area, bulb on the main path blocking tube",
+ "The Body left area, first bulb in the top face room",
+ "The Body left area, second bulb in the top face room",
+ "The Body left area, bulb below the water stream",
+ "The Body left area, bulb in the top path to the top face room",
+ "The Body left area, bulb in the bottom face room",
+ "The Body right area, bulb in the top face room",
+ "The Body right area, bulb in the top path to the bottom face room",
+ "The Body right area, bulb in the bottom face room",
+ "The Body bottom area, bulb in the Jelly Zap room",
+ "The Body bottom area, bulb in the nautilus room",
+ "The Body bottom area, Mutant Costume",
+ "Final Boss area, bulb in the boss third form room",
+ "Final Boss area, first bulb in the turtle room",
+ "Final Boss area, second bulb in the turtle room",
+ "Final Boss area, third bulb in the turtle room",
+ "Final Boss area, Transturtle",
+ "Beating Fallen God",
+ "Beating Blaster Peg Prime",
+ "Beating Mithalan God",
+ "Beating Drunian God",
+ "Beating Sun God",
+ "Beating the Golem",
+ "Beating Nautilus Prime",
+ "Beating Mergog",
+ "Beating Mithalan priests",
+ "Beating Octopus Prime",
+ "Beating King Jellyfish God Prime",
+ "Beating the Golem",
+ "Sunken City cleared",
+ "First secret",
+ "Objective complete"
+ ]
+ items = [["Energy form", "Dual form", "Li and Li song", "Body tongue cleared"]]
+ self.assertAccessDependency(locations, items)
diff --git a/worlds/aquaria/test/test_fish_form_access.py b/worlds/aquaria/test/test_fish_form_access.py
index c98a53e92438..40b15a87cd35 100644
--- a/worlds/aquaria/test/test_fish_form_access.py
+++ b/worlds/aquaria/test/test_fish_form_access.py
@@ -17,6 +17,7 @@ def test_fish_form_location(self) -> None:
"""Test locations that require fish form"""
locations = [
"The Veil top left area, bulb inside the fish pass",
+ "Energy Temple first area, Energy Idol",
"Mithalas City, Doll",
"Mithalas City, urn inside a home fish pass",
"Kelp Forest top right area, bulb in the top fish pass",
@@ -30,8 +31,7 @@ def test_fish_form_location(self) -> None:
"Octopus Cave, Dumbo Egg",
"Octopus Cave, bulb in the path below the Octopus Cave path",
"Beating Octopus Prime",
- "Abyss left area, bulb in the bottom fish pass",
- "Arnassi Ruins, Arnassi Armor"
+ "Abyss left area, bulb in the bottom fish pass"
]
items = [["Fish form"]]
self.assertAccessDependency(locations, items)
diff --git a/worlds/aquaria/test/test_light_access.py b/worlds/aquaria/test/test_light_access.py
index b5d7cf99fea2..29d37d790b20 100644
--- a/worlds/aquaria/test/test_light_access.py
+++ b/worlds/aquaria/test/test_light_access.py
@@ -39,7 +39,6 @@ def test_light_location(self) -> None:
"Abyss right area, bulb in the middle path",
"Abyss right area, bulb behind the rock in the middle path",
"Abyss right area, bulb in the left green room",
- "Abyss right area, Transturtle",
"Ice Cave, bulb in the room to the right",
"Ice Cave, first bulb in the top exit room",
"Ice Cave, second bulb in the top exit room",
diff --git a/worlds/aquaria/test/test_spirit_form_access.py b/worlds/aquaria/test/test_spirit_form_access.py
index 3bcbd7d72e02..7e31de9905e9 100644
--- a/worlds/aquaria/test/test_spirit_form_access.py
+++ b/worlds/aquaria/test/test_spirit_form_access.py
@@ -30,7 +30,6 @@ def test_spirit_form_location(self) -> None:
"Sunken City left area, Girl Costume",
"Beating Mantis Shrimp Prime",
"First secret",
- "Arnassi Ruins, Arnassi Armor",
]
items = [["Spirit form"]]
self.assertAccessDependency(locations, items)
diff --git a/worlds/checksfinder/Items.py b/worlds/checksfinder/Items.py
index 2e86267396f9..5f9be79598af 100644
--- a/worlds/checksfinder/Items.py
+++ b/worlds/checksfinder/Items.py
@@ -3,8 +3,8 @@
class ItemData(typing.NamedTuple):
- code: typing.Optional[int]
- progression: bool
+ code: int
+ progression: bool = True
class ChecksFinderItem(Item):
@@ -12,16 +12,9 @@ class ChecksFinderItem(Item):
item_table = {
- "Map Width": ItemData(80000, True),
- "Map Height": ItemData(80001, True),
- "Map Bombs": ItemData(80002, True),
+ "Map Width": ItemData(80000),
+ "Map Height": ItemData(80001),
+ "Map Bombs": ItemData(80002),
}
-required_items = {
-}
-
-item_frequencies = {
-
-}
-
-lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in item_table.items() if data.code}
+lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in item_table.items()}
diff --git a/worlds/checksfinder/Locations.py b/worlds/checksfinder/Locations.py
index 59a96c83ea8a..aefdc3838100 100644
--- a/worlds/checksfinder/Locations.py
+++ b/worlds/checksfinder/Locations.py
@@ -3,46 +3,14 @@
class AdvData(typing.NamedTuple):
- id: typing.Optional[int]
- region: str
+ id: int
+ region: str = "Board"
-class ChecksFinderAdvancement(Location):
+class ChecksFinderLocation(Location):
game: str = "ChecksFinder"
-advancement_table = {
- "Tile 1": AdvData(81000, 'Board'),
- "Tile 2": AdvData(81001, 'Board'),
- "Tile 3": AdvData(81002, 'Board'),
- "Tile 4": AdvData(81003, 'Board'),
- "Tile 5": AdvData(81004, 'Board'),
- "Tile 6": AdvData(81005, 'Board'),
- "Tile 7": AdvData(81006, 'Board'),
- "Tile 8": AdvData(81007, 'Board'),
- "Tile 9": AdvData(81008, 'Board'),
- "Tile 10": AdvData(81009, 'Board'),
- "Tile 11": AdvData(81010, 'Board'),
- "Tile 12": AdvData(81011, 'Board'),
- "Tile 13": AdvData(81012, 'Board'),
- "Tile 14": AdvData(81013, 'Board'),
- "Tile 15": AdvData(81014, 'Board'),
- "Tile 16": AdvData(81015, 'Board'),
- "Tile 17": AdvData(81016, 'Board'),
- "Tile 18": AdvData(81017, 'Board'),
- "Tile 19": AdvData(81018, 'Board'),
- "Tile 20": AdvData(81019, 'Board'),
- "Tile 21": AdvData(81020, 'Board'),
- "Tile 22": AdvData(81021, 'Board'),
- "Tile 23": AdvData(81022, 'Board'),
- "Tile 24": AdvData(81023, 'Board'),
- "Tile 25": AdvData(81024, 'Board'),
-}
-
-exclusion_table = {
-}
-
-events_table = {
-}
-
-lookup_id_to_name: typing.Dict[int, str] = {data.id: item_name for item_name, data in advancement_table.items() if data.id}
\ No newline at end of file
+base_id = 81000
+advancement_table = {f"Tile {i+1}": AdvData(base_id+i) for i in range(25)}
+lookup_id_to_name: typing.Dict[int, str] = {data.id: item_name for item_name, data in advancement_table.items()}
diff --git a/worlds/checksfinder/Options.py b/worlds/checksfinder/Options.py
deleted file mode 100644
index a670109362f7..000000000000
--- a/worlds/checksfinder/Options.py
+++ /dev/null
@@ -1,6 +0,0 @@
-import typing
-from Options import Option
-
-
-checksfinder_options: typing.Dict[str, type(Option)] = {
-}
diff --git a/worlds/checksfinder/Rules.py b/worlds/checksfinder/Rules.py
index 38d7d77ad393..8e8809be5c13 100644
--- a/worlds/checksfinder/Rules.py
+++ b/worlds/checksfinder/Rules.py
@@ -1,44 +1,24 @@
-from ..generic.Rules import set_rule
-from BaseClasses import MultiWorld, CollectionState
+from worlds.generic.Rules import set_rule
+from BaseClasses import MultiWorld
-def _has_total(state: CollectionState, player: int, total: int):
- return (state.count('Map Width', player) + state.count('Map Height', player) +
- state.count('Map Bombs', player)) >= total
+items = ["Map Width", "Map Height", "Map Bombs"]
# Sets rules on entrances and advancements that are always applied
-def set_rules(world: MultiWorld, player: int):
- set_rule(world.get_location("Tile 6", player), lambda state: _has_total(state, player, 1))
- set_rule(world.get_location("Tile 7", player), lambda state: _has_total(state, player, 2))
- set_rule(world.get_location("Tile 8", player), lambda state: _has_total(state, player, 3))
- set_rule(world.get_location("Tile 9", player), lambda state: _has_total(state, player, 4))
- set_rule(world.get_location("Tile 10", player), lambda state: _has_total(state, player, 5))
- set_rule(world.get_location("Tile 11", player), lambda state: _has_total(state, player, 6))
- set_rule(world.get_location("Tile 12", player), lambda state: _has_total(state, player, 7))
- set_rule(world.get_location("Tile 13", player), lambda state: _has_total(state, player, 8))
- set_rule(world.get_location("Tile 14", player), lambda state: _has_total(state, player, 9))
- set_rule(world.get_location("Tile 15", player), lambda state: _has_total(state, player, 10))
- set_rule(world.get_location("Tile 16", player), lambda state: _has_total(state, player, 11))
- set_rule(world.get_location("Tile 17", player), lambda state: _has_total(state, player, 12))
- set_rule(world.get_location("Tile 18", player), lambda state: _has_total(state, player, 13))
- set_rule(world.get_location("Tile 19", player), lambda state: _has_total(state, player, 14))
- set_rule(world.get_location("Tile 20", player), lambda state: _has_total(state, player, 15))
- set_rule(world.get_location("Tile 21", player), lambda state: _has_total(state, player, 16))
- set_rule(world.get_location("Tile 22", player), lambda state: _has_total(state, player, 17))
- set_rule(world.get_location("Tile 23", player), lambda state: _has_total(state, player, 18))
- set_rule(world.get_location("Tile 24", player), lambda state: _has_total(state, player, 19))
- set_rule(world.get_location("Tile 25", player), lambda state: _has_total(state, player, 20))
+def set_rules(multiworld: MultiWorld, player: int):
+ for i in range(20):
+ set_rule(multiworld.get_location(f"Tile {i+6}", player), lambda state, i=i: state.has_from_list(items, player, i+1))
# Sets rules on completion condition
-def set_completion_rules(world: MultiWorld, player: int):
-
- width_req = 10-5
- height_req = 10-5
- bomb_req = 20-5
- completion_requirements = lambda state: \
- state.has("Map Width", player, width_req) and \
- state.has("Map Height", player, height_req) and \
- state.has("Map Bombs", player, bomb_req)
- world.completion_condition[player] = lambda state: completion_requirements(state)
+def set_completion_rules(multiworld: MultiWorld, player: int):
+ width_req = 5 # 10 - 5
+ height_req = 5 # 10 - 5
+ bomb_req = 15 # 20 - 5
+ multiworld.completion_condition[player] = lambda state: state.has_all_counts(
+ {
+ "Map Width": width_req,
+ "Map Height": height_req,
+ "Map Bombs": bomb_req,
+ }, player)
diff --git a/worlds/checksfinder/__init__.py b/worlds/checksfinder/__init__.py
index c8b9587f8500..e064a1c41947 100644
--- a/worlds/checksfinder/__init__.py
+++ b/worlds/checksfinder/__init__.py
@@ -1,9 +1,9 @@
-from BaseClasses import Region, Entrance, Item, Tutorial, ItemClassification
-from .Items import ChecksFinderItem, item_table, required_items
-from .Locations import ChecksFinderAdvancement, advancement_table, exclusion_table
-from .Options import checksfinder_options
+from BaseClasses import Region, Entrance, Tutorial, ItemClassification
+from .Items import ChecksFinderItem, item_table
+from .Locations import ChecksFinderLocation, advancement_table
+from Options import PerGameCommonOptions
from .Rules import set_rules, set_completion_rules
-from ..AutoWorld import World, WebWorld
+from worlds.AutoWorld import World, WebWorld
client_version = 7
@@ -25,38 +25,34 @@ class ChecksFinderWorld(World):
ChecksFinder is a game where you avoid mines and find checks inside the board
with the mines! You win when you get all your items and beat the board!
"""
- game: str = "ChecksFinder"
- option_definitions = checksfinder_options
- topology_present = True
+ game = "ChecksFinder"
+ options_dataclass = PerGameCommonOptions
web = ChecksFinderWeb()
item_name_to_id = {name: data.code for name, data in item_table.items()}
location_name_to_id = {name: data.id for name, data in advancement_table.items()}
- def _get_checksfinder_data(self):
- return {
- 'world_seed': self.multiworld.per_slot_randoms[self.player].getrandbits(32),
- 'seed_name': self.multiworld.seed_name,
- 'player_name': self.multiworld.get_player_name(self.player),
- 'player_id': self.player,
- 'client_version': client_version,
- 'race': self.multiworld.is_race,
- }
+ def create_regions(self):
+ menu = Region("Menu", self.player, self.multiworld)
+ board = Region("Board", self.player, self.multiworld)
+ board.locations += [ChecksFinderLocation(self.player, loc_name, loc_data.id, board)
+ for loc_name, loc_data in advancement_table.items()]
- def create_items(self):
+ connection = Entrance(self.player, "New Board", menu)
+ menu.exits.append(connection)
+ connection.connect(board)
+ self.multiworld.regions += [menu, board]
+ def create_items(self):
# Generate item pool
itempool = []
- # Add all required progression items
- for (name, num) in required_items.items():
- itempool += [name] * num
# Add the map width and height stuff
- itempool += ["Map Width"] * (10-5)
- itempool += ["Map Height"] * (10-5)
+ itempool += ["Map Width"] * 5 # 10 - 5
+ itempool += ["Map Height"] * 5 # 10 - 5
# Add the map bombs
- itempool += ["Map Bombs"] * (20-5)
+ itempool += ["Map Bombs"] * 15 # 20 - 5
# Convert itempool into real items
- itempool = [item for item in map(lambda name: self.create_item(name), itempool)]
+ itempool = [self.create_item(item) for item in itempool]
self.multiworld.itempool += itempool
@@ -64,28 +60,16 @@ def set_rules(self):
set_rules(self.multiworld, self.player)
set_completion_rules(self.multiworld, self.player)
- def create_regions(self):
- menu = Region("Menu", self.player, self.multiworld)
- board = Region("Board", self.player, self.multiworld)
- board.locations += [ChecksFinderAdvancement(self.player, loc_name, loc_data.id, board)
- for loc_name, loc_data in advancement_table.items() if loc_data.region == board.name]
-
- connection = Entrance(self.player, "New Board", menu)
- menu.exits.append(connection)
- connection.connect(board)
- self.multiworld.regions += [menu, board]
-
def fill_slot_data(self):
- slot_data = self._get_checksfinder_data()
- for option_name in checksfinder_options:
- option = getattr(self.multiworld, option_name)[self.player]
- if slot_data.get(option_name, None) is None and type(option.value) in {str, int}:
- slot_data[option_name] = int(option.value)
- return slot_data
+ return {
+ "world_seed": self.random.getrandbits(32),
+ "seed_name": self.multiworld.seed_name,
+ "player_name": self.player_name,
+ "player_id": self.player,
+ "client_version": client_version,
+ "race": self.multiworld.is_race,
+ }
- def create_item(self, name: str) -> Item:
+ def create_item(self, name: str) -> ChecksFinderItem:
item_data = item_table[name]
- item = ChecksFinderItem(name,
- ItemClassification.progression if item_data.progression else ItemClassification.filler,
- item_data.code, self.player)
- return item
+ return ChecksFinderItem(name, ItemClassification.progression, item_data.code, self.player)
diff --git a/worlds/checksfinder/docs/en_ChecksFinder.md b/worlds/checksfinder/docs/en_ChecksFinder.md
index c9569376c5f6..cb33ab39591a 100644
--- a/worlds/checksfinder/docs/en_ChecksFinder.md
+++ b/worlds/checksfinder/docs/en_ChecksFinder.md
@@ -24,8 +24,3 @@ next to an icon, the number is how many you have gotten and the icon represents
Victory is achieved when the player wins a board they were given after they have received all of their Map Width, Map
Height, and Map Bomb items. The game will say at the bottom of the screen how many of each you have received.
-## Unique Local Commands
-
-The following command is only available when using the ChecksFinderClient to play with Archipelago.
-
-- `/resync` Manually trigger a resync.
diff --git a/worlds/checksfinder/docs/setup_en.md b/worlds/checksfinder/docs/setup_en.md
index 673b34900af7..e15763ab3110 100644
--- a/worlds/checksfinder/docs/setup_en.md
+++ b/worlds/checksfinder/docs/setup_en.md
@@ -4,7 +4,6 @@
- ChecksFinder from
the [Github releases Page for the game](https://github.com/jonloveslegos/ChecksFinder/releases) (latest version)
-- Archipelago from the [Archipelago Releases Page](https://github.com/ArchipelagoMW/Archipelago/releases)
## Configuring your YAML file
@@ -17,28 +16,15 @@ guide: [Basic Multiworld Setup Guide](/tutorial/Archipelago/setup/en)
You can customize your options by visiting the [ChecksFinder Player Options Page](/games/ChecksFinder/player-options)
-### Generating a ChecksFinder game
+## Joining a MultiWorld Game
-**ChecksFinder is meant to be played _alongside_ another game! You may not be playing it for long periods of time if
-you play it by itself with another person!**
-
-When you join a multiworld game, you will be asked to provide your YAML file to whoever is hosting. Once that is done,
-the host will provide you with either a link to download your data file, or with a zip file containing everyone's data
-files. You do not have a file inside that zip though!
-
-You need to start ChecksFinder client yourself, it is located within the Archipelago folder.
-
-### Connect to the MultiServer
-
-First start ChecksFinder.
-
-Once both ChecksFinder and the client are started. In the client at the top type in the spot labeled `Server` type the
-`Ip Address` and `Port` separated with a `:` symbol.
-
-The client will then ask for the username you chose, input that in the text box at the bottom of the client.
-
-### Play the game
-
-When the console tells you that you have joined the room, you're all set. Congratulations on successfully joining a
-multiworld game!
+1. Start ChecksFinder
+2. Enter the following information:
+ - Enter the server url (starting from `wss://` for https connection like archipelago.gg, and starting from `ws://` for http connection and local multiserver)
+ - Enter server port
+ - Enter the name of the slot you wish to connect to
+ - Enter the room password (optional)
+ - Press `Play Online` to connect
+3. Start playing!
+Game options and controls are described in the readme on the github repository for the game
diff --git a/worlds/clique/Items.py b/worlds/clique/Items.py
index 5474f58b82d5..81e2540bacc0 100644
--- a/worlds/clique/Items.py
+++ b/worlds/clique/Items.py
@@ -1,6 +1,9 @@
-from typing import Callable, Dict, NamedTuple, Optional
+from typing import Callable, Dict, NamedTuple, Optional, TYPE_CHECKING
-from BaseClasses import Item, ItemClassification, MultiWorld
+from BaseClasses import Item, ItemClassification
+
+if TYPE_CHECKING:
+ from . import CliqueWorld
class CliqueItem(Item):
@@ -10,7 +13,7 @@ class CliqueItem(Item):
class CliqueItemData(NamedTuple):
code: Optional[int] = None
type: ItemClassification = ItemClassification.filler
- can_create: Callable[[MultiWorld, int], bool] = lambda multiworld, player: True
+ can_create: Callable[["CliqueWorld"], bool] = lambda world: True
item_data_table: Dict[str, CliqueItemData] = {
@@ -21,11 +24,11 @@ class CliqueItemData(NamedTuple):
"Button Activation": CliqueItemData(
code=69696968,
type=ItemClassification.progression,
- can_create=lambda multiworld, player: bool(getattr(multiworld, "hard_mode")[player]),
+ can_create=lambda world: world.options.hard_mode,
),
"A Cool Filler Item (No Satisfaction Guaranteed)": CliqueItemData(
code=69696967,
- can_create=lambda multiworld, player: False # Only created from `get_filler_item_name`.
+ can_create=lambda world: False # Only created from `get_filler_item_name`.
),
"The Urge to Push": CliqueItemData(
type=ItemClassification.progression,
diff --git a/worlds/clique/Locations.py b/worlds/clique/Locations.py
index 144becae5368..900b497eb4eb 100644
--- a/worlds/clique/Locations.py
+++ b/worlds/clique/Locations.py
@@ -1,6 +1,9 @@
-from typing import Callable, Dict, NamedTuple, Optional
+from typing import Callable, Dict, NamedTuple, Optional, TYPE_CHECKING
-from BaseClasses import Location, MultiWorld
+from BaseClasses import Location
+
+if TYPE_CHECKING:
+ from . import CliqueWorld
class CliqueLocation(Location):
@@ -10,7 +13,7 @@ class CliqueLocation(Location):
class CliqueLocationData(NamedTuple):
region: str
address: Optional[int] = None
- can_create: Callable[[MultiWorld, int], bool] = lambda multiworld, player: True
+ can_create: Callable[["CliqueWorld"], bool] = lambda world: True
locked_item: Optional[str] = None
@@ -22,7 +25,7 @@ class CliqueLocationData(NamedTuple):
"The Item on the Desk": CliqueLocationData(
region="The Button Realm",
address=69696968,
- can_create=lambda multiworld, player: bool(getattr(multiworld, "hard_mode")[player]),
+ can_create=lambda world: world.options.hard_mode,
),
"In the Player's Mind": CliqueLocationData(
region="The Button Realm",
diff --git a/worlds/clique/Options.py b/worlds/clique/Options.py
index 7976dcb62130..d88a1289903c 100644
--- a/worlds/clique/Options.py
+++ b/worlds/clique/Options.py
@@ -1,6 +1,5 @@
-from typing import Dict
-
-from Options import Choice, Option, Toggle
+from dataclasses import dataclass
+from Options import Choice, Toggle, PerGameCommonOptions, StartInventoryPool
class HardMode(Toggle):
@@ -25,10 +24,11 @@ class ButtonColor(Choice):
option_black = 11
-clique_options: Dict[str, type(Option)] = {
- "color": ButtonColor,
- "hard_mode": HardMode,
+@dataclass
+class CliqueOptions(PerGameCommonOptions):
+ color: ButtonColor
+ hard_mode: HardMode
+ start_inventory_from_pool: StartInventoryPool
# DeathLink is always on. Always.
- # "death_link": DeathLink,
-}
+ # death_link: DeathLink
diff --git a/worlds/clique/Rules.py b/worlds/clique/Rules.py
index 5ae1d2c68e39..63ecd4e9e17c 100644
--- a/worlds/clique/Rules.py
+++ b/worlds/clique/Rules.py
@@ -1,10 +1,13 @@
-from typing import Callable
+from typing import Callable, TYPE_CHECKING
-from BaseClasses import CollectionState, MultiWorld
+from BaseClasses import CollectionState
+if TYPE_CHECKING:
+ from . import CliqueWorld
-def get_button_rule(multiworld: MultiWorld, player: int) -> Callable[[CollectionState], bool]:
- if getattr(multiworld, "hard_mode")[player]:
- return lambda state: state.has("Button Activation", player)
+
+def get_button_rule(world: "CliqueWorld") -> Callable[[CollectionState], bool]:
+ if world.options.hard_mode:
+ return lambda state: state.has("Button Activation", world.player)
return lambda state: True
diff --git a/worlds/clique/__init__.py b/worlds/clique/__init__.py
index b5cc74d94ac0..3d06e477eba7 100644
--- a/worlds/clique/__init__.py
+++ b/worlds/clique/__init__.py
@@ -1,10 +1,10 @@
-from typing import List
+from typing import List, Dict, Any
from BaseClasses import Region, Tutorial
from worlds.AutoWorld import WebWorld, World
from .Items import CliqueItem, item_data_table, item_table
from .Locations import CliqueLocation, location_data_table, location_table, locked_locations
-from .Options import clique_options
+from .Options import CliqueOptions
from .Regions import region_data_table
from .Rules import get_button_rule
@@ -38,7 +38,8 @@ class CliqueWorld(World):
game = "Clique"
web = CliqueWebWorld()
- option_definitions = clique_options
+ options: CliqueOptions
+ options_dataclass = CliqueOptions
location_name_to_id = location_table
item_name_to_id = item_table
@@ -48,7 +49,7 @@ def create_item(self, name: str) -> CliqueItem:
def create_items(self) -> None:
item_pool: List[CliqueItem] = []
for name, item in item_data_table.items():
- if item.code and item.can_create(self.multiworld, self.player):
+ if item.code and item.can_create(self):
item_pool.append(self.create_item(name))
self.multiworld.itempool += item_pool
@@ -61,41 +62,40 @@ def create_regions(self) -> None:
# Create locations.
for region_name, region_data in region_data_table.items():
- region = self.multiworld.get_region(region_name, self.player)
+ region = self.get_region(region_name)
region.add_locations({
location_name: location_data.address for location_name, location_data in location_data_table.items()
- if location_data.region == region_name and location_data.can_create(self.multiworld, self.player)
+ if location_data.region == region_name and location_data.can_create(self)
}, CliqueLocation)
region.add_exits(region_data_table[region_name].connecting_regions)
# Place locked locations.
for location_name, location_data in locked_locations.items():
# Ignore locations we never created.
- if not location_data.can_create(self.multiworld, self.player):
+ if not location_data.can_create(self):
continue
locked_item = self.create_item(location_data_table[location_name].locked_item)
- self.multiworld.get_location(location_name, self.player).place_locked_item(locked_item)
+ self.get_location(location_name).place_locked_item(locked_item)
# Set priority location for the Big Red Button!
- self.multiworld.priority_locations[self.player].value.add("The Big Red Button")
+ self.options.priority_locations.value.add("The Big Red Button")
def get_filler_item_name(self) -> str:
return "A Cool Filler Item (No Satisfaction Guaranteed)"
def set_rules(self) -> None:
- button_rule = get_button_rule(self.multiworld, self.player)
- self.multiworld.get_location("The Big Red Button", self.player).access_rule = button_rule
- self.multiworld.get_location("In the Player's Mind", self.player).access_rule = button_rule
+ button_rule = get_button_rule(self)
+ self.get_location("The Big Red Button").access_rule = button_rule
+ self.get_location("In the Player's Mind").access_rule = button_rule
# Do not allow button activations on buttons.
- self.multiworld.get_location("The Big Red Button", self.player).item_rule =\
- lambda item: item.name != "Button Activation"
+ self.get_location("The Big Red Button").item_rule = lambda item: item.name != "Button Activation"
# Completion condition.
self.multiworld.completion_condition[self.player] = lambda state: state.has("The Urge to Push", self.player)
- def fill_slot_data(self):
+ def fill_slot_data(self) -> Dict[str, Any]:
return {
- "color": getattr(self.multiworld, "color")[self.player].current_key
+ "color": self.options.color.current_key
}
diff --git a/worlds/dark_souls_3/Bosses.py b/worlds/dark_souls_3/Bosses.py
new file mode 100644
index 000000000000..008a29713202
--- /dev/null
+++ b/worlds/dark_souls_3/Bosses.py
@@ -0,0 +1,264 @@
+# In almost all cases, we leave boss and enemy randomization up to the static randomizer. But for
+# Yhorm specifically we need to know where he ends up in order to ensure that the Storm Ruler is
+# available before his fight.
+
+from dataclasses import dataclass, field
+from typing import Set
+
+
+@dataclass
+class DS3BossInfo:
+ """The set of locations a given boss location blocks access to."""
+
+ name: str
+ """The boss's name."""
+
+ id: int
+ """The game's ID for this particular boss."""
+
+ dlc: bool = False
+ """This boss appears in one of the game's DLCs."""
+
+ before_storm_ruler: bool = False
+ """Whether this location appears before it's possible to get Storm Ruler in vanilla.
+
+ This is used to determine whether it's safe to place Yhorm here if weapons
+ aren't randomized.
+ """
+
+ locations: Set[str] = field(default_factory=set)
+ """Additional individual locations that can't be accessed until the boss is dead."""
+
+
+# Note: the static randomizer splits up some bosses into separate fights for separate phases, each
+# of which can be individually replaced by Yhorm.
+all_bosses = [
+ DS3BossInfo("Iudex Gundyr", 4000800, before_storm_ruler = True, locations = {
+ "CA: Coiled Sword - boss drop"
+ }),
+ DS3BossInfo("Vordt of the Boreal Valley", 3000800, before_storm_ruler = True, locations = {
+ "HWL: Soul of Boreal Valley Vordt"
+ }),
+ DS3BossInfo("Curse-rotted Greatwood", 3100800, locations = {
+ "US: Soul of the Rotted Greatwood",
+ "US: Transposing Kiln - boss drop",
+ "US: Wargod Wooden Shield - Pit of Hollows",
+ "FS: Hawkwood's Shield - gravestone after Hawkwood leaves",
+ "FS: Sunset Shield - by grave after killing Hodrick w/Sirris",
+ "US: Sunset Helm - Pit of Hollows after killing Hodrick w/Sirris",
+ "US: Sunset Armor - pit of hollows after killing Hodrick w/Sirris",
+ "US: Sunset Gauntlets - pit of hollows after killing Hodrick w/Sirris",
+ "US: Sunset Leggings - pit of hollows after killing Hodrick w/Sirris",
+ "FS: Sunless Talisman - Sirris, kill GA boss",
+ "FS: Sunless Veil - shop, Sirris quest, kill GA boss",
+ "FS: Sunless Armor - shop, Sirris quest, kill GA boss",
+ "FS: Sunless Gauntlets - shop, Sirris quest, kill GA boss",
+ "FS: Sunless Leggings - shop, Sirris quest, kill GA boss",
+ }),
+ DS3BossInfo("Crystal Sage", 3300850, locations = {
+ "RS: Soul of a Crystal Sage",
+ "FS: Sage's Big Hat - shop after killing RS boss",
+ "FS: Hawkwood's Shield - gravestone after Hawkwood leaves",
+ }),
+ DS3BossInfo("Deacons of the Deep", 3500800, locations = {
+ "CD: Soul of the Deacons of the Deep",
+ "CD: Small Doll - boss drop",
+ "FS: Hawkwood's Shield - gravestone after Hawkwood leaves",
+ }),
+ DS3BossInfo("Abyss Watchers", 3300801, before_storm_ruler = True, locations = {
+ "FK: Soul of the Blood of the Wolf",
+ "FK: Cinders of a Lord - Abyss Watcher",
+ "FS: Undead Legion Helm - shop after killing FK boss",
+ "FS: Undead Legion Armor - shop after killing FK boss",
+ "FS: Undead Legion Gauntlet - shop after killing FK boss",
+ "FS: Undead Legion Leggings - shop after killing FK boss",
+ "FS: Farron Ring - Hawkwood",
+ "FS: Hawkwood's Shield - gravestone after Hawkwood leaves",
+ }),
+ DS3BossInfo("High Lord Wolnir", 3800800, before_storm_ruler = True, locations = {
+ "CC: Soul of High Lord Wolnir",
+ "FS: Wolnir's Crown - shop after killing CC boss",
+ "CC: Homeward Bone - Irithyll bridge",
+ "CC: Pontiff's Right Eye - Irithyll bridge, miniboss drop",
+ }),
+ DS3BossInfo("Pontiff Sulyvahn", 3700850, locations = {
+ "IBV: Soul of Pontiff Sulyvahn",
+ }),
+ DS3BossInfo("Old Demon King", 3800830, locations = {
+ "SL: Soul of the Old Demon King",
+ }),
+ DS3BossInfo("Aldrich, Devourer of Gods", 3700800, locations = {
+ "AL: Soul of Aldrich",
+ "AL: Cinders of a Lord - Aldrich",
+ "FS: Smough's Helm - shop after killing AL boss",
+ "FS: Smough's Armor - shop after killing AL boss",
+ "FS: Smough's Gauntlets - shop after killing AL boss",
+ "FS: Smough's Leggings - shop after killing AL boss",
+ "AL: Sun Princess Ring - dark cathedral, after boss",
+ "FS: Leonhard's Garb - shop after killing Leonhard",
+ "FS: Leonhard's Gauntlets - shop after killing Leonhard",
+ "FS: Leonhard's Trousers - shop after killing Leonhard",
+ }),
+ DS3BossInfo("Dancer of the Boreal Valley", 3000899, locations = {
+ "HWL: Soul of the Dancer",
+ "FS: Dancer's Crown - shop after killing LC entry boss",
+ "FS: Dancer's Armor - shop after killing LC entry boss",
+ "FS: Dancer's Gauntlets - shop after killing LC entry boss",
+ "FS: Dancer's Leggings - shop after killing LC entry boss",
+ }),
+ DS3BossInfo("Dragonslayer Armour", 3010800, locations = {
+ "LC: Soul of Dragonslayer Armour",
+ "FS: Morne's Helm - shop after killing Eygon or LC boss",
+ "FS: Morne's Armor - shop after killing Eygon or LC boss",
+ "FS: Morne's Gauntlets - shop after killing Eygon or LC boss",
+ "FS: Morne's Leggings - shop after killing Eygon or LC boss",
+ "LC: Titanite Chunk - down stairs after boss",
+ }),
+ DS3BossInfo("Consumed King Oceiros", 3000830, locations = {
+ "CKG: Soul of Consumed Oceiros",
+ "CKG: Titanite Scale - tomb, chest #1",
+ "CKG: Titanite Scale - tomb, chest #2",
+ "CKG: Drakeblood Helm - tomb, after killing AP mausoleum NPC",
+ "CKG: Drakeblood Armor - tomb, after killing AP mausoleum NPC",
+ "CKG: Drakeblood Gauntlets - tomb, after killing AP mausoleum NPC",
+ "CKG: Drakeblood Leggings - tomb, after killing AP mausoleum NPC",
+ }),
+ DS3BossInfo("Champion Gundyr", 4000830, locations = {
+ "UG: Soul of Champion Gundyr",
+ "FS: Gundyr's Helm - shop after killing UG boss",
+ "FS: Gundyr's Armor - shop after killing UG boss",
+ "FS: Gundyr's Gauntlets - shop after killing UG boss",
+ "FS: Gundyr's Leggings - shop after killing UG boss",
+ "UG: Hornet Ring - environs, right of main path after killing FK boss",
+ "UG: Chaos Blade - environs, left of shrine",
+ "UG: Blacksmith Hammer - shrine, Andre's room",
+ "UG: Eyes of a Fire Keeper - shrine, Irina's room",
+ "UG: Coiled Sword Fragment - shrine, dead bonfire",
+ "UG: Soul of a Crestfallen Knight - environs, above shrine entrance",
+ "UG: Life Ring+3 - shrine, behind big throne",
+ "UG: Ring of Steel Protection+1 - environs, behind bell tower",
+ "FS: Ring of Sacrifice - Yuria shop",
+ "UG: Ember - shop",
+ "UG: Priestess Ring - shop",
+ "UG: Wolf Knight Helm - shop after killing FK boss",
+ "UG: Wolf Knight Armor - shop after killing FK boss",
+ "UG: Wolf Knight Gauntlets - shop after killing FK boss",
+ "UG: Wolf Knight Leggings - shop after killing FK boss",
+ }),
+ DS3BossInfo("Ancient Wyvern", 3200800),
+ DS3BossInfo("King of the Storm", 3200850, locations = {
+ "AP: Soul of the Nameless King",
+ "FS: Golden Crown - shop after killing AP boss",
+ "FS: Dragonscale Armor - shop after killing AP boss",
+ "FS: Golden Bracelets - shop after killing AP boss",
+ "FS: Dragonscale Waistcloth - shop after killing AP boss",
+ "AP: Titanite Slab - plaza",
+ "AP: Covetous Gold Serpent Ring+2 - plaza",
+ "AP: Dragonslayer Helm - plaza",
+ "AP: Dragonslayer Armor - plaza",
+ "AP: Dragonslayer Gauntlets - plaza",
+ "AP: Dragonslayer Leggings - plaza",
+ }),
+ DS3BossInfo("Nameless King", 3200851, locations = {
+ "AP: Soul of the Nameless King",
+ "FS: Golden Crown - shop after killing AP boss",
+ "FS: Dragonscale Armor - shop after killing AP boss",
+ "FS: Golden Bracelets - shop after killing AP boss",
+ "FS: Dragonscale Waistcloth - shop after killing AP boss",
+ "AP: Titanite Slab - plaza",
+ "AP: Covetous Gold Serpent Ring+2 - plaza",
+ "AP: Dragonslayer Helm - plaza",
+ "AP: Dragonslayer Armor - plaza",
+ "AP: Dragonslayer Gauntlets - plaza",
+ "AP: Dragonslayer Leggings - plaza",
+ }),
+ DS3BossInfo("Lothric, Younger Prince", 3410830, locations = {
+ "GA: Soul of the Twin Princes",
+ "GA: Cinders of a Lord - Lothric Prince",
+ }),
+ DS3BossInfo("Lorian, Elder Prince", 3410832, locations = {
+ "GA: Soul of the Twin Princes",
+ "GA: Cinders of a Lord - Lothric Prince",
+ "FS: Lorian's Helm - shop after killing GA boss",
+ "FS: Lorian's Armor - shop after killing GA boss",
+ "FS: Lorian's Gauntlets - shop after killing GA boss",
+ "FS: Lorian's Leggings - shop after killing GA boss",
+ }),
+ DS3BossInfo("Champion's Gravetender and Gravetender Greatwolf", 4500860, dlc = True,
+ locations = {"PW1: Valorheart - boss drop"}),
+ DS3BossInfo("Sister Friede", 4500801, dlc = True, locations = {
+ "PW2: Soul of Sister Friede",
+ "PW2: Titanite Slab - boss drop",
+ "PW1: Titanite Slab - Corvian",
+ "FS: Ordained Hood - shop after killing PW2 boss",
+ "FS: Ordained Dress - shop after killing PW2 boss",
+ "FS: Ordained Trousers - shop after killing PW2 boss",
+ }),
+ DS3BossInfo("Blackflame Friede", 4500800, dlc = True, locations = {
+ "PW2: Soul of Sister Friede",
+ "PW1: Titanite Slab - Corvian",
+ "FS: Ordained Hood - shop after killing PW2 boss",
+ "FS: Ordained Dress - shop after killing PW2 boss",
+ "FS: Ordained Trousers - shop after killing PW2 boss",
+ }),
+ DS3BossInfo("Demon Prince", 5000801, dlc = True, locations = {
+ "DH: Soul of the Demon Prince",
+ "DH: Small Envoy Banner - boss drop",
+ }),
+ DS3BossInfo("Halflight, Spear of the Church", 5100800, dlc = True, locations = {
+ "RC: Titanite Slab - mid boss drop",
+ "RC: Titanite Slab - ashes, NPC drop",
+ "RC: Titanite Slab - ashes, mob drop",
+ "RC: Filianore's Spear Ornament - mid boss drop",
+ "RC: Crucifix of the Mad King - ashes, NPC drop",
+ "RC: Shira's Crown - Shira's room after killing ashes NPC",
+ "RC: Shira's Armor - Shira's room after killing ashes NPC",
+ "RC: Shira's Gloves - Shira's room after killing ashes NPC",
+ "RC: Shira's Trousers - Shira's room after killing ashes NPC",
+ }),
+ DS3BossInfo("Darkeater Midir", 5100850, dlc = True, locations = {
+ "RC: Soul of Darkeater Midir",
+ "RC: Spears of the Church - hidden boss drop",
+ }),
+ DS3BossInfo("Slave Knight Gael 1", 5110801, dlc = True, locations = {
+ "RC: Soul of Slave Knight Gael",
+ "RC: Blood of the Dark Soul - end boss drop",
+ # These are accessible before you trigger the boss, but once you do you
+ # have to beat it before getting them.
+ "RC: Titanite Slab - ashes, mob drop",
+ "RC: Titanite Slab - ashes, NPC drop",
+ "RC: Sacred Chime of Filianore - ashes, NPC drop",
+ "RC: Crucifix of the Mad King - ashes, NPC drop",
+ "RC: Shira's Crown - Shira's room after killing ashes NPC",
+ "RC: Shira's Armor - Shira's room after killing ashes NPC",
+ "RC: Shira's Gloves - Shira's room after killing ashes NPC",
+ "RC: Shira's Trousers - Shira's room after killing ashes NPC",
+ }),
+ DS3BossInfo("Slave Knight Gael 2", 5110800, dlc = True, locations = {
+ "RC: Soul of Slave Knight Gael",
+ "RC: Blood of the Dark Soul - end boss drop",
+ # These are accessible before you trigger the boss, but once you do you
+ # have to beat it before getting them.
+ "RC: Titanite Slab - ashes, mob drop",
+ "RC: Titanite Slab - ashes, NPC drop",
+ "RC: Sacred Chime of Filianore - ashes, NPC drop",
+ "RC: Crucifix of the Mad King - ashes, NPC drop",
+ "RC: Shira's Crown - Shira's room after killing ashes NPC",
+ "RC: Shira's Armor - Shira's room after killing ashes NPC",
+ "RC: Shira's Gloves - Shira's room after killing ashes NPC",
+ "RC: Shira's Trousers - Shira's room after killing ashes NPC",
+ }),
+ DS3BossInfo("Lords of Cinder", 4100800, locations = {
+ "KFF: Soul of the Lords",
+ "FS: Billed Mask - Yuria after killing KFF boss",
+ "FS: Black Dress - Yuria after killing KFF boss",
+ "FS: Black Gauntlets - Yuria after killing KFF boss",
+ "FS: Black Leggings - Yuria after killing KFF boss"
+ }),
+]
+
+default_yhorm_location = DS3BossInfo("Yhorm the Giant", 3900800, locations = {
+ "PC: Soul of Yhorm the Giant",
+ "PC: Cinders of a Lord - Yhorm the Giant",
+ "PC: Siegbräu - Siegward after killing boss",
+})
diff --git a/worlds/dark_souls_3/Items.py b/worlds/dark_souls_3/Items.py
index 3dd5cb2d3c3f..19cd79a99414 100644
--- a/worlds/dark_souls_3/Items.py
+++ b/worlds/dark_souls_3/Items.py
@@ -1,7 +1,9 @@
+from dataclasses import dataclass
+import dataclasses
from enum import IntEnum
-from typing import NamedTuple
+from typing import Any, cast, ClassVar, Dict, Generator, List, Optional, Set
-from BaseClasses import Item
+from BaseClasses import Item, ItemClassification
class DS3ItemCategory(IntEnum):
@@ -14,1267 +16,1677 @@ class DS3ItemCategory(IntEnum):
RING = 6
SPELL = 7
MISC = 8
- KEY = 9
+ UNIQUE = 9
BOSS = 10
- SKIP = 11
+ SOUL = 11
+ UPGRADE = 12
+ HEALING = 13
+ @property
+ def is_infusible(self) -> bool:
+ """Returns whether this category can be infused."""
+ return self in [
+ DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE,
+ DS3ItemCategory.SHIELD_INFUSIBLE
+ ]
+
+ @property
+ def upgrade_level(self) -> Optional[int]:
+ """The maximum upgrade level for this category, or None if it's not upgradable."""
+ if self == DS3ItemCategory.WEAPON_UPGRADE_5: return 5
+ if self in [
+ DS3ItemCategory.WEAPON_UPGRADE_10,
+ DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE
+ ]: return 10
+ return None
+
+
+@dataclass
+class Infusion(IntEnum):
+ """Infusions supported by Dark Souls III.
+
+ The value of each infusion is the number added to the base weapon's ID to get the infused ID.
+ """
+
+ HEAVY = 100
+ SHARP = 200
+ REFINED = 300
+ SIMPLE = 400
+ CRYSTAL = 500
+ FIRE = 600
+ CHAOS = 700
+ LIGHTNING = 800
+ DEEP = 900
+ DARK = 1000
+ POISON = 1100
+ BLOOD = 1200
+ RAW = 1300
+ BLESSED = 1400
+ HOLLOW = 1500
+
+ @property
+ def prefix(self):
+ """The prefix to add to a weapon name with this infusion."""
+ return self.name.title()
+
+
+class UsefulIf(IntEnum):
+ """An enum that indicates when an item should be upgraded to ItemClassification.useful.
+
+ This is used for rings with +x variants that may or may not be the best in class depending on
+ the player's settings.
+ """
+
+ DEFAULT = 0
+ """Follows DS3ItemData.classification as written."""
+
+ BASE = 1
+ """Useful only if the DLC and NG+ locations are disabled."""
+
+ NO_DLC = 2
+ """Useful if the DLC is disabled, whether or not NG+ locations are."""
+
+ NO_NGP = 3
+ """Useful if NG+ locations is disabled, whether or not the DLC is."""
+
+
+@dataclass
+class DS3ItemData:
+ __item_id: ClassVar[int] = 100000
+ """The next item ID to use when creating item data."""
-class DS3ItemData(NamedTuple):
name: str
- ds3_code: int
- is_dlc: bool
+ ds3_code: Optional[int]
category: DS3ItemCategory
+ base_ds3_code: Optional[int] = None
+ """If this is an upgradable weapon, the base ID of the weapon it upgrades from.
+
+ Otherwise, or if the weapon isn't upgraded, this is the same as ds3_code.
+ """
+
+ base_name: Optional[str] = None
+ """The name of the individual item, if this is a multi-item group."""
+
+ classification: ItemClassification = ItemClassification.filler
+ """How important this item is to the game progression."""
+
+ ap_code: Optional[int] = None
+ """The Archipelago ID for this item."""
+
+ is_dlc: bool = False
+ """Whether this item is only found in one of the two DLC packs."""
+
+ count: int = 1
+ """The number of copies of this item included in each drop."""
+
+ inject: bool = False
+ """If this is set, the randomizer will try to inject this item into the game.
+
+ This is used for items such as covenant rewards that aren't realistically reachable in a
+ randomizer run, but are still fun to have available to the player. If there are more locations
+ available than there are items in the item pool, these items will be used to help make up the
+ difference.
+ """
+
+ souls: Optional[int] = None
+ """If this is a consumable item that gives souls, the number of souls it gives."""
+
+ useful_if: UsefulIf = UsefulIf.DEFAULT
+ """Whether and when this item should be marked as "useful"."""
+
+ filler: bool = False
+ """Whether this is a candidate for a filler item to be added to fill out extra locations."""
+
+ skip: bool = False
+ """Whether to omit this item from randomization and replace it with filler or unique items."""
+
+ @property
+ def unique(self):
+ """Whether this item should be unique, appearing only once in the randomizer."""
+ return self.category not in {
+ DS3ItemCategory.MISC, DS3ItemCategory.SOUL, DS3ItemCategory.UPGRADE,
+ DS3ItemCategory.HEALING,
+ }
+
+ def __post_init__(self):
+ self.ap_code = self.ap_code or DS3ItemData.__item_id
+ if not self.base_name: self.base_name = self.name
+ if not self.base_ds3_code: self.base_ds3_code = self.ds3_code
+ DS3ItemData.__item_id += 1
+
+ def item_groups(self) -> List[str]:
+ """The names of item groups this item should appear in.
+
+ This is computed from the properties assigned to this item."""
+ names = []
+ if self.classification == ItemClassification.progression: names.append("Progression")
+ if self.name.startswith("Cinders of a Lord -"): names.append("Cinders")
+
+ names.append({
+ DS3ItemCategory.WEAPON_UPGRADE_5: "Weapons",
+ DS3ItemCategory.WEAPON_UPGRADE_10: "Weapons",
+ DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE: "Weapons",
+ DS3ItemCategory.SHIELD: "Shields",
+ DS3ItemCategory.SHIELD_INFUSIBLE: "Shields",
+ DS3ItemCategory.ARMOR: "Armor",
+ DS3ItemCategory.RING: "Rings",
+ DS3ItemCategory.SPELL: "Spells",
+ DS3ItemCategory.MISC: "Miscellaneous",
+ DS3ItemCategory.UNIQUE: "Unique",
+ DS3ItemCategory.BOSS: "Boss Souls",
+ DS3ItemCategory.SOUL: "Small Souls",
+ DS3ItemCategory.UPGRADE: "Upgrade",
+ DS3ItemCategory.HEALING: "Healing",
+ }[self.category])
+
+ return names
+
+ def counts(self, counts: List[int]) -> Generator["DS3ItemData", None, None]:
+ """Returns an iterable of copies of this item with the given counts."""
+ yield self
+ for count in counts:
+ yield dataclasses.replace(
+ self,
+ ap_code = None,
+ name = "{} x{}".format(self.base_name, count),
+ base_name = self.base_name,
+ count = count,
+ filler = False, # Don't count multiples as filler by default
+ )
+
+ @property
+ def is_infused(self) -> bool:
+ """Returns whether this item is an infused weapon."""
+ return cast(int, self.ds3_code) - cast(int, self.base_ds3_code) >= 100
+
+ def infuse(self, infusion: Infusion) -> "DS3ItemData":
+ """Returns this item with the given infusion applied."""
+ if not self.category.is_infusible: raise RuntimeError(f"{self.name} is not infusible.")
+ if self.is_infused:
+ raise RuntimeError(f"{self.name} is already infused.")
+
+ # We can't change the name or AP code when infusing/upgrading weapons, because they both
+ # need to match what's in item_name_to_id. We don't want to add every possible
+ # infusion/upgrade combination to that map because it's way too many items.
+ return dataclasses.replace(
+ self,
+ name = self.name,
+ ds3_code = cast(int, self.ds3_code) + infusion.value,
+ filler = False,
+ )
+
+ @property
+ def is_upgraded(self) -> bool:
+ """Returns whether this item is a weapon that's upgraded beyond level 0."""
+ return (cast(int, self.ds3_code) - cast(int, self.base_ds3_code)) % 100 != 0
+
+ def upgrade(self, level: int) -> "DS3ItemData":
+ """Upgrades this item to the given level."""
+ if not self.category.upgrade_level: raise RuntimeError(f"{self.name} is not upgradable.")
+ if level > self.category.upgrade_level:
+ raise RuntimeError(f"{self.name} can't be upgraded to +{level}.")
+ if self.is_upgraded:
+ raise RuntimeError(f"{self.name} is already upgraded.")
+
+ # We can't change the name or AP code when infusing/upgrading weapons, because they both
+ # need to match what's in item_name_to_id. We don't want to add every possible
+ # infusion/upgrade combination to that map because it's way too many items.
+ return dataclasses.replace(
+ self,
+ name = self.name,
+ ds3_code = cast(int, self.ds3_code) + level,
+ filler = False,
+ )
+
+ def __hash__(self) -> int:
+ return (self.name, self.ds3_code).__hash__()
+
+ def __eq__(self, other: Any) -> bool:
+ if isinstance(other, self.__class__):
+ return self.name == other.name and self.ds3_code == other.ds3_code
+ else:
+ return False
+
class DarkSouls3Item(Item):
game: str = "Dark Souls III"
+ data: DS3ItemData
+
+ @property
+ def level(self) -> Optional[int]:
+ """This item's upgrade level, if it's a weapon."""
+ return cast(int, self.data.ds3_code) % 100 if self.data.category.upgrade_level else None
+
+ def __init__(
+ self,
+ player: int,
+ data: DS3ItemData,
+ classification = None):
+ super().__init__(data.name, classification or data.classification, data.ap_code, player)
+ self.data = data
@staticmethod
- def get_name_to_id() -> dict:
- base_id = 100000
- return {item_data.name: id for id, item_data in enumerate(_all_items, base_id)}
-
-
-key_item_names = {
- "Small Lothric Banner",
- "Basin of Vows",
- "Small Doll",
- "Storm Ruler",
- "Grand Archives Key",
- "Cinders of a Lord - Abyss Watcher",
- "Cinders of a Lord - Yhorm the Giant",
- "Cinders of a Lord - Aldrich",
- "Cinders of a Lord - Lothric Prince",
- "Mortician's Ashes",
- "Cell Key",
- #"Tower Key", #Not a relevant key item atm
- "Jailbreaker's Key",
- "Prisoner Chief's Ashes",
- "Old Cell Key",
- "Jailer's Key Ring",
- "Contraption Key",
- "Small Envoy Banner"
-}
+ def event(name: str, player: int) -> "DarkSouls3Item":
+ data = DS3ItemData(name, None, DS3ItemCategory.MISC,
+ skip = True, classification = ItemClassification.progression)
+ data.ap_code = None
+ return DarkSouls3Item(player, data)
-_vanilla_items = [DS3ItemData(row[0], row[1], False, row[2]) for row in [
+_vanilla_items = [
# Ammunition
- ("Standard Arrow", 0x00061A80, DS3ItemCategory.SKIP),
- ("Fire Arrow", 0x00061AE4, DS3ItemCategory.SKIP),
- ("Poison Arrow", 0x00061B48, DS3ItemCategory.SKIP),
- ("Large Arrow", 0x00061BAC, DS3ItemCategory.SKIP),
- ("Feather Arrow", 0x00061C10, DS3ItemCategory.SKIP),
- ("Moonlight Arrow", 0x00061C74, DS3ItemCategory.SKIP),
- ("Wood Arrow", 0x00061CD8, DS3ItemCategory.SKIP),
- ("Dark Arrow", 0x00061D3C, DS3ItemCategory.SKIP),
- ("Dragonslayer Greatarrow", 0x00062250, DS3ItemCategory.SKIP),
- ("Dragonslayer Lightning Arrow", 0x00062318, DS3ItemCategory.SKIP),
- ("Onislayer Greatarrow", 0x0006237C, DS3ItemCategory.SKIP),
- ("Standard Bolt", 0x00062A20, DS3ItemCategory.SKIP),
- ("Heavy Bolt", 0x00062A84, DS3ItemCategory.SKIP),
- ("Sniper Bolt", 0x00062AE8, DS3ItemCategory.SKIP),
- ("Wood Bolt", 0x00062B4C, DS3ItemCategory.SKIP),
- ("Lightning Bolt", 0x00062BB0, DS3ItemCategory.SKIP),
- ("Splintering Bolt", 0x00062C14, DS3ItemCategory.SKIP),
- ("Exploding Bolt", 0x00062C78, DS3ItemCategory.SKIP),
+ *DS3ItemData("Standard Arrow", 0x00061A80, DS3ItemCategory.MISC).counts([12]),
+ DS3ItemData("Standard Arrow x8", 0x00061A80, DS3ItemCategory.MISC, count = 8, filler = True),
+ DS3ItemData("Fire Arrow", 0x00061AE4, DS3ItemCategory.MISC),
+ DS3ItemData("Fire Arrow x8", 0x00061AE4, DS3ItemCategory.MISC, count = 8, filler = True),
+ *DS3ItemData("Poison Arrow", 0x00061B48, DS3ItemCategory.MISC).counts([18]),
+ DS3ItemData("Poison Arrow x8", 0x00061B48, DS3ItemCategory.MISC, count = 8, filler = True),
+ DS3ItemData("Large Arrow", 0x00061BAC, DS3ItemCategory.MISC),
+ DS3ItemData("Feather Arrow", 0x00061C10, DS3ItemCategory.MISC),
+ *DS3ItemData("Moonlight Arrow", 0x00061C74, DS3ItemCategory.MISC).counts([6]),
+ DS3ItemData("Wood Arrow", 0x00061CD8, DS3ItemCategory.MISC),
+ DS3ItemData("Dark Arrow", 0x00061D3C, DS3ItemCategory.MISC),
+ *DS3ItemData("Dragonslayer Greatarrow", 0x00062250, DS3ItemCategory.MISC).counts([5]),
+ *DS3ItemData("Dragonslayer Lightning Arrow", 0x00062318, DS3ItemCategory.MISC).counts([10]),
+ *DS3ItemData("Onislayer Greatarrow", 0x0006237C, DS3ItemCategory.MISC).counts([8]),
+ DS3ItemData("Standard Bolt", 0x00062A20, DS3ItemCategory.MISC),
+ DS3ItemData("Heavy Bolt", 0x00062A84, DS3ItemCategory.MISC),
+ *DS3ItemData("Sniper Bolt", 0x00062AE8, DS3ItemCategory.MISC).counts([11]),
+ DS3ItemData("Wood Bolt", 0x00062B4C, DS3ItemCategory.MISC),
+ *DS3ItemData("Lightning Bolt", 0x00062BB0, DS3ItemCategory.MISC).counts([9]),
+ *DS3ItemData("Lightning Bolt", 0x00062BB0, DS3ItemCategory.MISC).counts([12]),
+ DS3ItemData("Splintering Bolt", 0x00062C14, DS3ItemCategory.MISC),
+ *DS3ItemData("Exploding Bolt", 0x00062C78, DS3ItemCategory.MISC).counts([6]),
# Weapons
- ("Dagger", 0x000F4240, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Bandit's Knife", 0x000F6950, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Parrying Dagger", 0x000F9060, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Rotten Ghru Dagger", 0x000FDE80, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Harpe", 0x00102CA0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Scholar's Candlestick", 0x001053B0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Tailbone Short Sword", 0x00107AC0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Corvian Greatknife", 0x0010A1D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Handmaid's Dagger", 0x00111700, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Shortsword", 0x001E8480, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Longsword", 0x001EAB90, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Broadsword", 0x001ED2A0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Broken Straight Sword", 0x001EF9B0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Lothric Knight Sword", 0x001F6EE0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Sunlight Straight Sword", 0x00203230, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Rotten Ghru Curved Sword", 0x00205940, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Irithyll Straight Sword", 0x0020A760, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Cleric's Candlestick", 0x0020F580, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Morion Blade", 0x002143A0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Astora's Straight Sword", 0x002191C0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Barbed Straight Sword", 0x0021B8D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Executioner's Greatsword", 0x0021DFE0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Anri's Straight Sword", 0x002206F0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Estoc", 0x002DC6C0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Mail Breaker", 0x002DEDD0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Rapier", 0x002E14E0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Ricard's Rapier", 0x002E3BF0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Crystal Sage's Rapier", 0x002E6300, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Irithyll Rapier", 0x002E8A10, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Shotel", 0x003D3010, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Scimitar", 0x003D7E30, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Falchion", 0x003DA540, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Carthus Curved Sword", 0x003DCC50, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Carthus Curved Greatsword", 0x003DF360, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Pontiff Knight Curved Sword", 0x003E1A70, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Storm Curved Sword", 0x003E4180, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Painting Guardian's Curved Sword", 0x003E6890, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Crescent Moon Sword", 0x003E8FA0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Carthus Shotel", 0x003EB6B0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Uchigatana", 0x004C4B40, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Washing Pole", 0x004C7250, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Chaos Blade", 0x004C9960, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Black Blade", 0x004CC070, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Bloodlust", 0x004CE780, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Darkdrift", 0x004D0E90, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Bastard Sword", 0x005B8D80, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Claymore", 0x005BDBA0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Zweihander", 0x005C29C0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Greatsword", 0x005C50D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Astora Greatsword", 0x005C9EF0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Murakumo", 0x005CC600, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Lothric Knight Greatsword", 0x005D1420, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Flamberge", 0x005DB060, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Exile Greatsword", 0x005DD770, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Greatsword of Judgment", 0x005E2590, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Profaned Greatsword", 0x005E4CA0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Cathedral Knight Greatsword", 0x005E73B0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Farron Greatsword", 0x005E9AC0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Yhorm's Great Machete", 0x005F0FF0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Dark Sword", 0x005F3700, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Black Knight Sword", 0x005F5E10, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Lorian's Greatsword", 0x005F8520, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Twin Princes' Greatsword", 0x005FAC30, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Lothric's Holy Sword", 0x005FD340, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Wolnir's Holy Sword", 0x005FFA50, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Wolf Knight's Greatsword", 0x00602160, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Greatsword of Artorias", 0x0060216A, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Hollowslayer Greatsword", 0x00604870, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Moonlight Greatsword", 0x00606F80, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Drakeblood Greatsword", 0x00609690, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Firelink Greatsword", 0x0060BDA0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Fume Ultra Greatsword", 0x0060E4B0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Old Wolf Curved Sword", 0x00610BC0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Storm Ruler", 0x006132D0, DS3ItemCategory.KEY),
- ("Hand Axe", 0x006ACFC0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Battle Axe", 0x006AF6D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Deep Battle Axe", 0x006AFA54, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Brigand Axe", 0x006B1DE0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Crescent Axe", 0x006B6C00, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Great Axe", 0x006B9310, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Butcher Knife", 0x006BE130, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Dragonslayer's Axe", 0x006C0840, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Thrall Axe", 0x006C5660, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Dragonslayer Greataxe", 0x006C7D70, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Demon's Greataxe", 0x006CA480, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Eleonora", 0x006CCB90, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Man Serpent Hatchet", 0x006D19B0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Club", 0x007A1200, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Mace", 0x007A3910, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Morning Star", 0x007A6020, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Reinforced Club", 0x007A8730, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Large Club", 0x007AFC60, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Great Club", 0x007B4A80, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Great Mace", 0x007BBFB0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Great Wooden Hammer", 0x007C8300, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Gargoyle Flame Hammer", 0x007CAA10, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Vordt's Great Hammer", 0x007CD120, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Old King's Great Hammer", 0x007CF830, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Heysel Pick", 0x007D6D60, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Warpick", 0x007DBB80, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Pickaxe", 0x007DE290, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Dragon Tooth", 0x007E09A0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Smough's Great Hammer", 0x007E30B0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Blacksmith Hammer", 0x007E57C0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Morne's Great Hammer", 0x007E7ED0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Spiked Mace", 0x007EA5E0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Spear", 0x00895440, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Winged Spear", 0x00897B50, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Partizan", 0x0089C970, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Greatlance", 0x008A8CC0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Lothric Knight Long Spear", 0x008AB3D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Gargoyle Flame Spear", 0x008B01F0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Rotten Ghru Spear", 0x008B2900, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Tailbone Spear", 0x008B5010, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Soldering Iron", 0x008B7720, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Arstor's Spear", 0x008BEC50, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Saint Bident", 0x008C1360, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Yorshka's Spear", 0x008C3A70, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Pike", 0x008C6180, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Heavy Four-pronged Plow", 0x008ADAE0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Dragonslayer Spear", 0x008CAFA0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Great Scythe", 0x00989680, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Lucerne", 0x0098BD90, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Glaive", 0x0098E4A0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Halberd", 0x00990BB0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Black Knight Greataxe", 0x009959D0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Pontiff Knight Great Scythe", 0x0099A7F0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Great Corvian Scythe", 0x0099CF00, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Winged Knight Halberd", 0x0099F610, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Gundyr's Halberd", 0x009A1D20, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Red Hilted Halberd", 0x009AB960, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Black Knight Glaive", 0x009AE070, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Immolation Tinder", 0x009B0780, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Claw", 0x00A7D8C0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Caestus", 0x00A7FFD0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Manikin Claws", 0x00A826E0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Demon's Fist", 0x00A84DF0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Dark Hand", 0x00A87500, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Whip", 0x00B71B00, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Witch's Locks", 0x00B7B740, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Notched Whip", 0x00B7DE50, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Spotted Whip", 0x00B80560, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Talisman", 0x00C72090, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Sorcerer's Staff", 0x00C747A0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Storyteller's Staff", 0x00C76EB0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Mendicant's Staff", 0x00C795C0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Man-grub's Staff", 0x00C7E3E0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Archdeacon's Great Staff", 0x00C80AF0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Golden Ritual Spear", 0x00C83200, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Yorshka's Chime", 0x00C88020, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Sage's Crystal Staff", 0x00C8CE40, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Heretic's Staff", 0x00C8F550, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Court Sorcerer's Staff", 0x00C91C60, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Witchtree Branch", 0x00C94370, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Izalith Staff", 0x00C96A80, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Cleric's Sacred Chime", 0x00C99190, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Priest's Chime", 0x00C9B8A0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Saint-tree Bellvine", 0x00C9DFB0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Caitha's Chime", 0x00CA06C0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Crystal Chime", 0x00CA2DD0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Sunlight Talisman", 0x00CA54E0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Canvas Talisman", 0x00CA7BF0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Sunless Talisman", 0x00CAA300, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Saint's Talisman", 0x00CACA10, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("White Hair Talisman", 0x00CAF120, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Pyromancy Flame", 0x00CC77C0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Dragonslayer Greatbow", 0x00CF8500, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Short Bow", 0x00D5C690, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Composite Bow", 0x00D5EDA0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Light Crossbow", 0x00D63BC0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Arbalest", 0x00D662D0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Longbow", 0x00D689E0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Dragonrider Bow", 0x00D6B0F0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Avelyn", 0x00D6FF10, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Knight's Crossbow", 0x00D72620, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Heavy Crossbow", 0x00D74D30, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Darkmoon Longbow", 0x00D79B50, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Onislayer Greatbow", 0x00D7C260, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Black Bow of Pharis", 0x00D7E970, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Sniper Crossbow", 0x00D83790, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Sellsword Twinblades", 0x00F42400, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Warden Twinblades", 0x00F47220, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Winged Knight Twinaxes", 0x00F49930, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Dancer's Enchanted Swords", 0x00F4C040, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Great Machete", 0x00F4E750, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Brigand Twindaggers", 0x00F50E60, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Gotthard Twinswords", 0x00F53570, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Onikiri and Ubadachi", 0x00F58390, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Drang Twinspears", 0x00F5AAA0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Drang Hammers", 0x00F61FD0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Dagger", 0x000F4240, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Bandit's Knife", 0x000F6950, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Parrying Dagger", 0x000F9060, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Rotten Ghru Dagger", 0x000FDE80, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Harpe", 0x00102CA0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Scholar's Candlestick", 0x001053B0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Tailbone Short Sword", 0x00107AC0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Corvian Greatknife", 0x0010A1D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Handmaid's Dagger", 0x00111700, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Shortsword", 0x001E8480, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Longsword", 0x001EAB90, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Broadsword", 0x001ED2A0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Broken Straight Sword", 0x001EF9B0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Lothric Knight Sword", 0x001F6EE0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Sunlight Straight Sword", 0x00203230, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Rotten Ghru Curved Sword", 0x00205940, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Irithyll Straight Sword", 0x0020A760, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Cleric's Candlestick", 0x0020F580, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Morion Blade", 0x002143A0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Astora Straight Sword", 0x002191C0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Barbed Straight Sword", 0x0021B8D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Executioner's Greatsword", 0x0021DFE0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Anri's Straight Sword", 0x002206F0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Estoc", 0x002DC6C0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Mail Breaker", 0x002DEDD0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Rapier", 0x002E14E0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Ricard's Rapier", 0x002E3BF0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Crystal Sage's Rapier", 0x002E6300, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Irithyll Rapier", 0x002E8A10, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Shotel", 0x003D3010, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Scimitar", 0x003D7E30, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Falchion", 0x003DA540, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Carthus Curved Sword", 0x003DCC50, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Carthus Curved Greatsword", 0x003DF360, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Pontiff Knight Curved Sword", 0x003E1A70, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Storm Curved Sword", 0x003E4180, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Painting Guardian's Curved Sword", 0x003E6890, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Crescent Moon Sword", 0x003E8FA0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Carthus Shotel", 0x003EB6B0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Uchigatana", 0x004C4B40, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Washing Pole", 0x004C7250, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Chaos Blade", 0x004C9960, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Black Blade", 0x004CC070, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Bloodlust", 0x004CE780, DS3ItemCategory.WEAPON_UPGRADE_5,
+ inject = True), # Covenant reward
+ DS3ItemData("Darkdrift", 0x004D0E90, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Bastard Sword", 0x005B8D80, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Claymore", 0x005BDBA0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Zweihander", 0x005C29C0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Greatsword", 0x005C50D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Astora Greatsword", 0x005C9EF0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Murakumo", 0x005CC600, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Lothric Knight Greatsword", 0x005D1420, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Flamberge", 0x005DB060, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Exile Greatsword", 0x005DD770, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Greatsword of Judgment", 0x005E2590, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Profaned Greatsword", 0x005E4CA0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Cathedral Knight Greatsword", 0x005E73B0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Farron Greatsword", 0x005E9AC0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Yhorm's Great Machete", 0x005F0FF0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Dark Sword", 0x005F3700, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Black Knight Sword", 0x005F5E10, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Lorian's Greatsword", 0x005F8520, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Twin Princes' Greatsword", 0x005FAC30, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Lothric's Holy Sword", 0x005FD340, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Wolnir's Holy Sword", 0x005FFA50, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Wolf Knight's Greatsword", 0x00602160, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Greatsword of Artorias", 0x0060216A, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Hollowslayer Greatsword", 0x00604870, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Moonlight Greatsword", 0x00606F80, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Drakeblood Greatsword", 0x00609690, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Firelink Greatsword", 0x0060BDA0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Fume Ultra Greatsword", 0x0060E4B0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Old Wolf Curved Sword", 0x00610BC0, DS3ItemCategory.WEAPON_UPGRADE_5,
+ inject = True), # Covenant reward
+ DS3ItemData("Storm Ruler", 0x006132D0, DS3ItemCategory.WEAPON_UPGRADE_5,
+ classification = ItemClassification.progression),
+ DS3ItemData("Hand Axe", 0x006ACFC0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Battle Axe", 0x006AF6D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Deep Battle Axe", 0x006AFA54, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Brigand Axe", 0x006B1DE0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Crescent Axe", 0x006B6C00, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Greataxe", 0x006B9310, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Butcher Knife", 0x006BE130, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Dragonslayer's Axe", 0x006C0840, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Thrall Axe", 0x006C5660, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Dragonslayer Greataxe", 0x006C7D70, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Demon's Greataxe", 0x006CA480, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Eleonora", 0x006CCB90, DS3ItemCategory.WEAPON_UPGRADE_5,
+ classification = ItemClassification.progression), # Crow trade
+ DS3ItemData("Man Serpent Hatchet", 0x006D19B0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Club", 0x007A1200, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Mace", 0x007A3910, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Morning Star", 0x007A6020, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Reinforced Club", 0x007A8730, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Large Club", 0x007AFC60, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Great Club", 0x007B4A80, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Great Mace", 0x007BBFB0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Great Wooden Hammer", 0x007C8300, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Gargoyle Flame Hammer", 0x007CAA10, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Vordt's Great Hammer", 0x007CD120, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Old King's Great Hammer", 0x007CF830, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Heysel Pick", 0x007D6D60, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Warpick", 0x007DBB80, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Pickaxe", 0x007DE290, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Dragon Tooth", 0x007E09A0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Smough's Great Hammer", 0x007E30B0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Blacksmith Hammer", 0x007E57C0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE,
+ classification = ItemClassification.progression), # Crow trade
+ DS3ItemData("Morne's Great Hammer", 0x007E7ED0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Spiked Mace", 0x007EA5E0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Spear", 0x00895440, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Winged Spear", 0x00897B50, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Partizan", 0x0089C970, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Greatlance", 0x008A8CC0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Lothric Knight Long Spear", 0x008AB3D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Gargoyle Flame Spear", 0x008B01F0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Rotten Ghru Spear", 0x008B2900, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Tailbone Spear", 0x008B5010, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Soldering Iron", 0x008B7720, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Dragonslayer Swordspear", 0x008BC540, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Arstor's Spear", 0x008BEC50, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Saint Bident", 0x008C1360, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Yorshka's Spear", 0x008C3A70, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Pike", 0x008C6180, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Heavy Four-pronged Plow", 0x008ADAE0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Dragonslayer Spear", 0x008CAFA0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Great Scythe", 0x00989680, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Lucerne", 0x0098BD90, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Glaive", 0x0098E4A0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Halberd", 0x00990BB0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Black Knight Greataxe", 0x009959D0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Pontiff Knight Great Scythe", 0x0099A7F0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Great Corvian Scythe", 0x0099CF00, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Winged Knight Halberd", 0x0099F610, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Gundyr's Halberd", 0x009A1D20, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Red Hilted Halberd", 0x009AB960, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Black Knight Glaive", 0x009AE070, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Immolation Tinder", 0x009B0780, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Claw", 0x00A7D8C0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Caestus", 0x00A7FFD0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Manikin Claws", 0x00A826E0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Demon's Fist", 0x00A84DF0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Dark Hand", 0x00A87500, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Whip", 0x00B71B00, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Witch's Locks", 0x00B7B740, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Notched Whip", 0x00B7DE50, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Spotted Whip", 0x00B80560, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Talisman", 0x00C72090, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Sorcerer's Staff", 0x00C747A0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Storyteller's Staff", 0x00C76EB0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Mendicant's Staff", 0x00C795C0, DS3ItemCategory.WEAPON_UPGRADE_10,
+ classification = ItemClassification.progression, # Crow trade
+ inject = True), # This is just a random drop normally, but we need it in-logic
+ DS3ItemData("Man-grub's Staff", 0x00C7E3E0, DS3ItemCategory.WEAPON_UPGRADE_5,
+ inject = True), # Covenant reward
+ DS3ItemData("Archdeacon's Great Staff", 0x00C80AF0, DS3ItemCategory.WEAPON_UPGRADE_5,
+ inject = True), # Covenant reward
+ DS3ItemData("Golden Ritual Spear", 0x00C83200, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Yorshka's Chime", 0x00C88020, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Sage's Crystal Staff", 0x00C8CE40, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Heretic's Staff", 0x00C8F550, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Court Sorcerer's Staff", 0x00C91C60, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Witchtree Branch", 0x00C94370, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Izalith Staff", 0x00C96A80, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Cleric's Sacred Chime", 0x00C99190, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Priest's Chime", 0x00C9B8A0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Saint-tree Bellvine", 0x00C9DFB0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Caitha's Chime", 0x00CA06C0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Crystal Chime", 0x00CA2DD0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Sunlight Talisman", 0x00CA54E0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Canvas Talisman", 0x00CA7BF0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Sunless Talisman", 0x00CAA300, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Saint's Talisman", 0x00CACA10, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("White Hair Talisman", 0x00CAF120, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Pyromancy Flame", 0x00CC77C0, DS3ItemCategory.WEAPON_UPGRADE_10,
+ classification = ItemClassification.progression),
+ DS3ItemData("Dragonslayer Greatbow", 0x00CF8500, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Short Bow", 0x00D5C690, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Composite Bow", 0x00D5EDA0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Light Crossbow", 0x00D63BC0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Arbalest", 0x00D662D0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Longbow", 0x00D689E0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Dragonrider Bow", 0x00D6B0F0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Avelyn", 0x00D6FF10, DS3ItemCategory.WEAPON_UPGRADE_10,
+ classification = ItemClassification.progression), # Crow trade
+ DS3ItemData("Knight's Crossbow", 0x00D72620, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Heavy Crossbow", 0x00D74D30, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Darkmoon Longbow", 0x00D79B50, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Onislayer Greatbow", 0x00D7C260, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Black Bow of Pharis", 0x00D7E970, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Sniper Crossbow", 0x00D83790, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Sellsword Twinblades", 0x00F42400, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Warden Twinblades", 0x00F47220, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Winged Knight Twinaxes", 0x00F49930, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Dancer's Enchanted Swords", 0x00F4C040, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Great Machete", 0x00F4E750, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Brigand Twindaggers", 0x00F50E60, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Gotthard Twinswords", 0x00F53570, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Onikiri and Ubadachi", 0x00F58390, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Drang Twinspears", 0x00F5AAA0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Drang Hammers", 0x00F61FD0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
# Shields
- ("Buckler", 0x01312D00, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Small Leather Shield", 0x01315410, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Round Shield", 0x0131A230, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Large Leather Shield", 0x0131C940, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Hawkwood's Shield", 0x01323E70, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Iron Round Shield", 0x01326580, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Wooden Shield", 0x0132DAB0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Kite Shield", 0x013301C0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Ghru Rotshield", 0x013328D0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Havel's Greatshield", 0x013376F0, DS3ItemCategory.SHIELD),
- ("Target Shield", 0x01339E00, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Elkhorn Round Shield", 0x0133C510, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Warrior's Round Shield", 0x0133EC20, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Caduceus Round Shield", 0x01341330, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Red and White Shield", 0x01343A40, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Blessed Red and White Shield+1", 0x01343FB9, DS3ItemCategory.SHIELD),
- ("Plank Shield", 0x01346150, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Leather Shield", 0x01348860, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Crimson Parma", 0x0134AF70, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Eastern Iron Shield", 0x0134D680, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Llewellyn Shield", 0x0134FD90, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Golden Falcon Shield", 0x01354BB0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Sacred Bloom Shield", 0x013572C0, DS3ItemCategory.SHIELD),
- ("Ancient Dragon Greatshield", 0x013599D0, DS3ItemCategory.SHIELD),
- ("Lothric Knight Shield", 0x01409650, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Knight Shield", 0x01410B80, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Pontiff Knight Shield", 0x014159A0, DS3ItemCategory.SHIELD),
- ("Carthus Shield", 0x014180B0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Black Knight Shield", 0x0141F5E0, DS3ItemCategory.SHIELD),
- ("Silver Knight Shield", 0x01424400, DS3ItemCategory.SHIELD),
- ("Spiked Shield", 0x01426B10, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Pierce Shield", 0x01429220, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("East-West Shield", 0x0142B930, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Sunlight Shield", 0x0142E040, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Crest Shield", 0x01430750, DS3ItemCategory.SHIELD),
- ("Dragon Crest Shield", 0x01432E60, DS3ItemCategory.SHIELD),
- ("Spider Shield", 0x01435570, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Grass Crest Shield", 0x01437C80, DS3ItemCategory.SHIELD),
- ("Sunset Shield", 0x0143A390, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Golden Wing Crest Shield", 0x0143CAA0, DS3ItemCategory.SHIELD),
- ("Blue Wooden Shield", 0x0143F1B0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Silver Eagle Kite Shield", 0x014418C0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Stone Parma", 0x01443FD0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Spirit Tree Crest Shield", 0x014466E0, DS3ItemCategory.SHIELD),
- ("Porcine Shield", 0x01448DF0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Shield of Want", 0x0144B500, DS3ItemCategory.SHIELD),
- ("Wargod Wooden Shield", 0x0144DC10, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Lothric Knight Greatshield", 0x014FD890, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Cathedral Knight Greatshield", 0x014FFFA0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Dragonslayer Greatshield", 0x01504DC0, DS3ItemCategory.SHIELD),
- ("Moaning Shield", 0x015074D0, DS3ItemCategory.SHIELD),
- ("Yhorm's Greatshield", 0x0150C2F0, DS3ItemCategory.SHIELD),
- ("Black Iron Greatshield", 0x0150EA00, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Wolf Knight's Greatshield", 0x01511110, DS3ItemCategory.SHIELD),
- ("Twin Dragon Greatshield", 0x01513820, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Greatshield of Glory", 0x01515F30, DS3ItemCategory.SHIELD),
- ("Curse Ward Greatshield", 0x01518640, DS3ItemCategory.SHIELD),
- ("Bonewheel Shield", 0x0151AD50, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Stone Greatshield", 0x0151D460, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Buckler", 0x01312D00, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Small Leather Shield", 0x01315410, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Round Shield", 0x0131A230, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Large Leather Shield", 0x0131C940, DS3ItemCategory.SHIELD_INFUSIBLE,
+ classification = ItemClassification.progression, # Crow trade
+ inject = True), # This is a shop/infinite drop item, but we need it in logic
+ DS3ItemData("Hawkwood's Shield", 0x01323E70, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Iron Round Shield", 0x01326580, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Wooden Shield", 0x0132DAB0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Kite Shield", 0x013301C0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Ghru Rotshield", 0x013328D0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Havel's Greatshield", 0x013376F0, DS3ItemCategory.SHIELD),
+ DS3ItemData("Target Shield", 0x01339E00, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Elkhorn Round Shield", 0x0133C510, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Warrior's Round Shield", 0x0133EC20, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Caduceus Round Shield", 0x01341330, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Red and White Shield", 0x01343A40, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Blessed Red and White Shield+1", 0x01343FB9, DS3ItemCategory.SHIELD),
+ DS3ItemData("Plank Shield", 0x01346150, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Leather Shield", 0x01348860, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Crimson Parma", 0x0134AF70, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Eastern Iron Shield", 0x0134D680, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Llewellyn Shield", 0x0134FD90, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Golden Falcon Shield", 0x01354BB0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Sacred Bloom Shield", 0x013572C0, DS3ItemCategory.SHIELD),
+ DS3ItemData("Ancient Dragon Greatshield", 0x013599D0, DS3ItemCategory.SHIELD),
+ DS3ItemData("Lothric Knight Shield", 0x01409650, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Knight Shield", 0x01410B80, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Pontiff Knight Shield", 0x014159A0, DS3ItemCategory.SHIELD),
+ DS3ItemData("Carthus Shield", 0x014180B0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Black Knight Shield", 0x0141F5E0, DS3ItemCategory.SHIELD),
+ DS3ItemData("Silver Knight Shield", 0x01424400, DS3ItemCategory.SHIELD),
+ DS3ItemData("Spiked Shield", 0x01426B10, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Pierce Shield", 0x01429220, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("East-West Shield", 0x0142B930, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Sunlight Shield", 0x0142E040, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Crest Shield", 0x01430750, DS3ItemCategory.SHIELD),
+ DS3ItemData("Dragon Crest Shield", 0x01432E60, DS3ItemCategory.SHIELD),
+ DS3ItemData("Spider Shield", 0x01435570, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Grass Crest Shield", 0x01437C80, DS3ItemCategory.SHIELD,
+ classification = ItemClassification.useful),
+ DS3ItemData("Sunset Shield", 0x0143A390, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Golden Wing Crest Shield", 0x0143CAA0, DS3ItemCategory.SHIELD),
+ DS3ItemData("Blue Wooden Shield", 0x0143F1B0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Silver Eagle Kite Shield", 0x014418C0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Stone Parma", 0x01443FD0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Spirit Tree Crest Shield", 0x014466E0, DS3ItemCategory.SHIELD),
+ DS3ItemData("Porcine Shield", 0x01448DF0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Shield of Want", 0x0144B500, DS3ItemCategory.SHIELD),
+ DS3ItemData("Wargod Wooden Shield", 0x0144DC10, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Lothric Knight Greatshield", 0x014FD890, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Cathedral Knight Greatshield", 0x014FFFA0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Dragonslayer Greatshield", 0x01504DC0, DS3ItemCategory.SHIELD),
+ DS3ItemData("Moaning Shield", 0x015074D0, DS3ItemCategory.SHIELD,
+ classification = ItemClassification.progression), # Crow trade
+ DS3ItemData("Yhorm's Greatshield", 0x0150C2F0, DS3ItemCategory.SHIELD),
+ DS3ItemData("Black Iron Greatshield", 0x0150EA00, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Wolf Knight's Greatshield", 0x01511110, DS3ItemCategory.SHIELD,
+ inject = True), # Covenant reward
+ DS3ItemData("Twin Dragon Greatshield", 0x01513820, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Greatshield of Glory", 0x01515F30, DS3ItemCategory.SHIELD),
+ DS3ItemData("Curse Ward Greatshield", 0x01518640, DS3ItemCategory.SHIELD),
+ DS3ItemData("Bonewheel Shield", 0x0151AD50, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Stone Greatshield", 0x0151D460, DS3ItemCategory.SHIELD_INFUSIBLE),
# Armor
- ("Fallen Knight Helm", 0x1121EAC0, DS3ItemCategory.ARMOR),
- ("Fallen Knight Armor", 0x1121EEA8, DS3ItemCategory.ARMOR),
- ("Fallen Knight Gauntlets", 0x1121F290, DS3ItemCategory.ARMOR),
- ("Fallen Knight Trousers", 0x1121F678, DS3ItemCategory.ARMOR),
- ("Knight Helm", 0x11298BE0, DS3ItemCategory.ARMOR),
- ("Knight Armor", 0x11298FC8, DS3ItemCategory.ARMOR),
- ("Knight Gauntlets", 0x112993B0, DS3ItemCategory.ARMOR),
- ("Knight Leggings", 0x11299798, DS3ItemCategory.ARMOR),
- ("Firelink Helm", 0x11406F40, DS3ItemCategory.ARMOR),
- ("Firelink Armor", 0x11407328, DS3ItemCategory.ARMOR),
- ("Firelink Gauntlets", 0x11407710, DS3ItemCategory.ARMOR),
- ("Firelink Leggings", 0x11407AF8, DS3ItemCategory.ARMOR),
- ("Sellsword Helm", 0x11481060, DS3ItemCategory.ARMOR),
- ("Sellsword Armor", 0x11481448, DS3ItemCategory.ARMOR),
- ("Sellsword Gauntlet", 0x11481830, DS3ItemCategory.ARMOR),
- ("Sellsword Trousers", 0x11481C18, DS3ItemCategory.ARMOR),
- ("Herald Helm", 0x114FB180, DS3ItemCategory.ARMOR),
- ("Herald Armor", 0x114FB568, DS3ItemCategory.ARMOR),
- ("Herald Gloves", 0x114FB950, DS3ItemCategory.ARMOR),
- ("Herald Trousers", 0x114FBD38, DS3ItemCategory.ARMOR),
- ("Sunless Veil", 0x115752A0, DS3ItemCategory.ARMOR),
- ("Sunless Armor", 0x11575688, DS3ItemCategory.ARMOR),
- ("Sunless Gauntlets", 0x11575A70, DS3ItemCategory.ARMOR),
- ("Sunless Leggings", 0x11575E58, DS3ItemCategory.ARMOR),
- ("Black Hand Hat", 0x115EF3C0, DS3ItemCategory.ARMOR),
- ("Black Hand Armor", 0x115EF7A8, DS3ItemCategory.ARMOR),
- ("Assassin Gloves", 0x115EFB90, DS3ItemCategory.ARMOR),
- ("Assassin Trousers", 0x115EFF78, DS3ItemCategory.ARMOR),
- ("Assassin Hood", 0x11607A60, DS3ItemCategory.ARMOR),
- ("Assassin Armor", 0x11607E48, DS3ItemCategory.ARMOR),
- ("Xanthous Crown", 0x116694E0, DS3ItemCategory.ARMOR),
- ("Xanthous Overcoat", 0x116698C8, DS3ItemCategory.ARMOR),
- ("Xanthous Gloves", 0x11669CB0, DS3ItemCategory.ARMOR),
- ("Xanthous Trousers", 0x1166A098, DS3ItemCategory.ARMOR),
- ("Northern Helm", 0x116E3600, DS3ItemCategory.ARMOR),
- ("Northern Armor", 0x116E39E8, DS3ItemCategory.ARMOR),
- ("Northern Gloves", 0x116E3DD0, DS3ItemCategory.ARMOR),
- ("Northern Trousers", 0x116E41B8, DS3ItemCategory.ARMOR),
- ("Morne's Helm", 0x1175D720, DS3ItemCategory.ARMOR),
- ("Morne's Armor", 0x1175DB08, DS3ItemCategory.ARMOR),
- ("Morne's Gauntlets", 0x1175DEF0, DS3ItemCategory.ARMOR),
- ("Morne's Leggings", 0x1175E2D8, DS3ItemCategory.ARMOR),
- ("Silver Mask", 0x117D7840, DS3ItemCategory.ARMOR),
- ("Leonhard's Garb", 0x117D7C28, DS3ItemCategory.ARMOR),
- ("Leonhard's Gauntlets", 0x117D8010, DS3ItemCategory.ARMOR),
- ("Leonhard's Trousers", 0x117D83F8, DS3ItemCategory.ARMOR),
- ("Sneering Mask", 0x11851960, DS3ItemCategory.ARMOR),
- ("Pale Shade Robe", 0x11851D48, DS3ItemCategory.ARMOR),
- ("Pale Shade Gloves", 0x11852130, DS3ItemCategory.ARMOR),
- ("Pale Shade Trousers", 0x11852518, DS3ItemCategory.ARMOR),
- ("Sunset Helm", 0x118CBA80, DS3ItemCategory.ARMOR),
- ("Sunset Armor", 0x118CBE68, DS3ItemCategory.ARMOR),
- ("Sunset Gauntlets", 0x118CC250, DS3ItemCategory.ARMOR),
- ("Sunset Leggings", 0x118CC638, DS3ItemCategory.ARMOR),
- ("Old Sage's Blindfold", 0x11945BA0, DS3ItemCategory.ARMOR),
- ("Cornyx's Garb", 0x11945F88, DS3ItemCategory.ARMOR),
- ("Cornyx's Wrap", 0x11946370, DS3ItemCategory.ARMOR),
- ("Cornyx's Skirt", 0x11946758, DS3ItemCategory.ARMOR),
- ("Executioner Helm", 0x119BFCC0, DS3ItemCategory.ARMOR),
- ("Executioner Armor", 0x119C00A8, DS3ItemCategory.ARMOR),
- ("Executioner Gauntlets", 0x119C0490, DS3ItemCategory.ARMOR),
- ("Executioner Leggings", 0x119C0878, DS3ItemCategory.ARMOR),
- ("Billed Mask", 0x11A39DE0, DS3ItemCategory.ARMOR),
- ("Black Dress", 0x11A3A1C8, DS3ItemCategory.ARMOR),
- ("Black Gauntlets", 0x11A3A5B0, DS3ItemCategory.ARMOR),
- ("Black Leggings", 0x11A3A998, DS3ItemCategory.ARMOR),
- ("Pyromancer Crown", 0x11AB3F00, DS3ItemCategory.ARMOR),
- ("Pyromancer Garb", 0x11AB42E8, DS3ItemCategory.ARMOR),
- ("Pyromancer Wrap", 0x11AB46D0, DS3ItemCategory.ARMOR),
- ("Pyromancer Trousers", 0x11AB4AB8, DS3ItemCategory.ARMOR),
- ("Court Sorcerer Hood", 0x11BA8140, DS3ItemCategory.ARMOR),
- ("Court Sorcerer Robe", 0x11BA8528, DS3ItemCategory.ARMOR),
- ("Court Sorcerer Gloves", 0x11BA8910, DS3ItemCategory.ARMOR),
- ("Court Sorcerer Trousers", 0x11BA8CF8, DS3ItemCategory.ARMOR),
- ("Sorcerer Hood", 0x11C9C380, DS3ItemCategory.ARMOR),
- ("Sorcerer Robe", 0x11C9C768, DS3ItemCategory.ARMOR),
- ("Sorcerer Gloves", 0x11C9CB50, DS3ItemCategory.ARMOR),
- ("Sorcerer Trousers", 0x11C9CF38, DS3ItemCategory.ARMOR),
- ("Clandestine Coat", 0x11CB4E08, DS3ItemCategory.ARMOR),
- ("Cleric Hat", 0x11D905C0, DS3ItemCategory.ARMOR),
- ("Cleric Blue Robe", 0x11D909A8, DS3ItemCategory.ARMOR),
- ("Cleric Gloves", 0x11D90D90, DS3ItemCategory.ARMOR),
- ("Cleric Trousers", 0x11D91178, DS3ItemCategory.ARMOR),
- ("Steel Soldier Helm", 0x12625A00, DS3ItemCategory.ARMOR),
- ("Deserter Armor", 0x12625DE8, DS3ItemCategory.ARMOR),
- ("Deserter Trousers", 0x126265B8, DS3ItemCategory.ARMOR),
- ("Thief Mask", 0x12656740, DS3ItemCategory.ARMOR),
- ("Sage's Big Hat", 0x129020C0, DS3ItemCategory.ARMOR),
- ("Aristocrat's Mask", 0x129F6300, DS3ItemCategory.ARMOR),
- ("Jailer Robe", 0x129F66E8, DS3ItemCategory.ARMOR),
- ("Jailer Gloves", 0x129F6AD0, DS3ItemCategory.ARMOR),
- ("Jailer Trousers", 0x129F6EB8, DS3ItemCategory.ARMOR),
- ("Grave Warden Hood", 0x12BDE780, DS3ItemCategory.ARMOR),
- ("Grave Warden Robe", 0x12BDEB68, DS3ItemCategory.ARMOR),
- ("Grave Warden Wrap", 0x12BDEF50, DS3ItemCategory.ARMOR),
- ("Grave Warden Skirt", 0x12BDF338, DS3ItemCategory.ARMOR),
- ("Worker Hat", 0x12CD29C0, DS3ItemCategory.ARMOR),
- ("Worker Garb", 0x12CD2DA8, DS3ItemCategory.ARMOR),
- ("Worker Gloves", 0x12CD3190, DS3ItemCategory.ARMOR),
- ("Worker Trousers", 0x12CD3578, DS3ItemCategory.ARMOR),
- ("Thrall Hood", 0x12D4CAE0, DS3ItemCategory.ARMOR),
- ("Evangelist Hat", 0x12DC6C00, DS3ItemCategory.ARMOR),
- ("Evangelist Robe", 0x12DC6FE8, DS3ItemCategory.ARMOR),
- ("Evangelist Gloves", 0x12DC73D0, DS3ItemCategory.ARMOR),
- ("Evangelist Trousers", 0x12DC77B8, DS3ItemCategory.ARMOR),
- ("Scholar's Robe", 0x12E41108, DS3ItemCategory.ARMOR),
- ("Winged Knight Helm", 0x12EBAE40, DS3ItemCategory.ARMOR),
- ("Winged Knight Armor", 0x12EBB228, DS3ItemCategory.ARMOR),
- ("Winged Knight Gauntlets", 0x12EBB610, DS3ItemCategory.ARMOR),
- ("Winged Knight Leggings", 0x12EBB9F8, DS3ItemCategory.ARMOR),
- ("Cathedral Knight Helm", 0x130291A0, DS3ItemCategory.ARMOR),
- ("Cathedral Knight Armor", 0x13029588, DS3ItemCategory.ARMOR),
- ("Cathedral Knight Gauntlets", 0x13029970, DS3ItemCategory.ARMOR),
- ("Cathedral Knight Leggings", 0x13029D58, DS3ItemCategory.ARMOR),
- ("Lothric Knight Helm", 0x13197500, DS3ItemCategory.ARMOR),
- ("Lothric Knight Armor", 0x131978E8, DS3ItemCategory.ARMOR),
- ("Lothric Knight Gauntlets", 0x13197CD0, DS3ItemCategory.ARMOR),
- ("Lothric Knight Leggings", 0x131980B8, DS3ItemCategory.ARMOR),
- ("Outrider Knight Helm", 0x1328B740, DS3ItemCategory.ARMOR),
- ("Outrider Knight Armor", 0x1328BB28, DS3ItemCategory.ARMOR),
- ("Outrider Knight Gauntlets", 0x1328BF10, DS3ItemCategory.ARMOR),
- ("Outrider Knight Leggings", 0x1328C2F8, DS3ItemCategory.ARMOR),
- ("Black Knight Helm", 0x1337F980, DS3ItemCategory.ARMOR),
- ("Black Knight Armor", 0x1337FD68, DS3ItemCategory.ARMOR),
- ("Black Knight Gauntlets", 0x13380150, DS3ItemCategory.ARMOR),
- ("Black Knight Leggings", 0x13380538, DS3ItemCategory.ARMOR),
- ("Dark Mask", 0x133F9AA0, DS3ItemCategory.ARMOR),
- ("Dark Armor", 0x133F9E88, DS3ItemCategory.ARMOR),
- ("Dark Gauntlets", 0x133FA270, DS3ItemCategory.ARMOR),
- ("Dark Leggings", 0x133FA658, DS3ItemCategory.ARMOR),
- ("Exile Mask", 0x13473BC0, DS3ItemCategory.ARMOR),
- ("Exile Armor", 0x13473FA8, DS3ItemCategory.ARMOR),
- ("Exile Gauntlets", 0x13474390, DS3ItemCategory.ARMOR),
- ("Exile Leggings", 0x13474778, DS3ItemCategory.ARMOR),
- ("Pontiff Knight Crown", 0x13567E00, DS3ItemCategory.ARMOR),
- ("Pontiff Knight Armor", 0x135681E8, DS3ItemCategory.ARMOR),
- ("Pontiff Knight Gauntlets", 0x135685D0, DS3ItemCategory.ARMOR),
- ("Pontiff Knight Leggings", 0x135689B8, DS3ItemCategory.ARMOR),
- ("Golden Crown", 0x1365C040, DS3ItemCategory.ARMOR),
- ("Dragonscale Armor", 0x1365C428, DS3ItemCategory.ARMOR),
- ("Golden Bracelets", 0x1365C810, DS3ItemCategory.ARMOR),
- ("Dragonscale Waistcloth", 0x1365CBF8, DS3ItemCategory.ARMOR),
- ("Wolnir's Crown", 0x136D6160, DS3ItemCategory.ARMOR),
- ("Undead Legion Helm", 0x13750280, DS3ItemCategory.ARMOR),
- ("Undead Legion Armor", 0x13750668, DS3ItemCategory.ARMOR),
- ("Undead Legion Gauntlets", 0x13750A50, DS3ItemCategory.ARMOR),
- ("Undead Legion Leggings", 0x13750E38, DS3ItemCategory.ARMOR),
- ("Fire Witch Helm", 0x13938700, DS3ItemCategory.ARMOR),
- ("Fire Witch Armor", 0x13938AE8, DS3ItemCategory.ARMOR),
- ("Fire Witch Gauntlets", 0x13938ED0, DS3ItemCategory.ARMOR),
- ("Fire Witch Leggings", 0x139392B8, DS3ItemCategory.ARMOR),
- ("Lorian's Helm", 0x13A2C940, DS3ItemCategory.ARMOR),
- ("Lorian's Armor", 0x13A2CD28, DS3ItemCategory.ARMOR),
- ("Lorian's Gauntlets", 0x13A2D110, DS3ItemCategory.ARMOR),
- ("Lorian's Leggings", 0x13A2D4F8, DS3ItemCategory.ARMOR),
- ("Hood of Prayer", 0x13AA6A60, DS3ItemCategory.ARMOR),
- ("Robe of Prayer", 0x13AA6E48, DS3ItemCategory.ARMOR),
- ("Skirt of Prayer", 0x13AA7618, DS3ItemCategory.ARMOR),
- ("Dancer's Crown", 0x13C14DC0, DS3ItemCategory.ARMOR),
- ("Dancer's Armor", 0x13C151A8, DS3ItemCategory.ARMOR),
- ("Dancer's Gauntlets", 0x13C15590, DS3ItemCategory.ARMOR),
- ("Dancer's Leggings", 0x13C15978, DS3ItemCategory.ARMOR),
- ("Gundyr's Helm", 0x13D09000, DS3ItemCategory.ARMOR),
- ("Gundyr's Armor", 0x13D093E8, DS3ItemCategory.ARMOR),
- ("Gundyr's Gauntlets", 0x13D097D0, DS3ItemCategory.ARMOR),
- ("Gundyr's Leggings", 0x13D09BB8, DS3ItemCategory.ARMOR),
- ("Archdeacon White Crown", 0x13EF1480, DS3ItemCategory.ARMOR),
- ("Archdeacon Holy Garb", 0x13EF1868, DS3ItemCategory.ARMOR),
- ("Archdeacon Skirt", 0x13EF2038, DS3ItemCategory.ARMOR),
- ("Deacon Robe", 0x13F6B988, DS3ItemCategory.ARMOR),
- ("Deacon Skirt", 0x13F6C158, DS3ItemCategory.ARMOR),
- ("Fire Keeper Robe", 0x140D9CE8, DS3ItemCategory.ARMOR),
- ("Fire Keeper Gloves", 0x140DA0D0, DS3ItemCategory.ARMOR),
- ("Fire Keeper Skirt", 0x140DA4B8, DS3ItemCategory.ARMOR),
- ("Chain Helm", 0x142C1D80, DS3ItemCategory.ARMOR),
- ("Chain Armor", 0x142C2168, DS3ItemCategory.ARMOR),
- ("Leather Gauntlets", 0x142C2550, DS3ItemCategory.ARMOR),
- ("Chain Leggings", 0x142C2938, DS3ItemCategory.ARMOR),
- ("Nameless Knight Helm", 0x143B5FC0, DS3ItemCategory.ARMOR),
- ("Nameless Knight Armor", 0x143B63A8, DS3ItemCategory.ARMOR),
- ("Nameless Knight Gauntlets", 0x143B6790, DS3ItemCategory.ARMOR),
- ("Nameless Knight Leggings", 0x143B6B78, DS3ItemCategory.ARMOR),
- ("Elite Knight Helm", 0x144AA200, DS3ItemCategory.ARMOR),
- ("Elite Knight Armor", 0x144AA5E8, DS3ItemCategory.ARMOR),
- ("Elite Knight Gauntlets", 0x144AA9D0, DS3ItemCategory.ARMOR),
- ("Elite Knight Leggings", 0x144AADB8, DS3ItemCategory.ARMOR),
- ("Faraam Helm", 0x1459E440, DS3ItemCategory.ARMOR),
- ("Faraam Armor", 0x1459E828, DS3ItemCategory.ARMOR),
- ("Faraam Gauntlets", 0x1459EC10, DS3ItemCategory.ARMOR),
- ("Faraam Boots", 0x1459EFF8, DS3ItemCategory.ARMOR),
- ("Catarina Helm", 0x14692680, DS3ItemCategory.ARMOR),
- ("Catarina Armor", 0x14692A68, DS3ItemCategory.ARMOR),
- ("Catarina Gauntlets", 0x14692E50, DS3ItemCategory.ARMOR),
- ("Catarina Leggings", 0x14693238, DS3ItemCategory.ARMOR),
- ("Standard Helm", 0x1470C7A0, DS3ItemCategory.ARMOR),
- ("Hard Leather Armor", 0x1470CB88, DS3ItemCategory.ARMOR),
- ("Hard Leather Gauntlets", 0x1470CF70, DS3ItemCategory.ARMOR),
- ("Hard Leather Boots", 0x1470D358, DS3ItemCategory.ARMOR),
- ("Havel's Helm", 0x147868C0, DS3ItemCategory.ARMOR),
- ("Havel's Armor", 0x14786CA8, DS3ItemCategory.ARMOR),
- ("Havel's Gauntlets", 0x14787090, DS3ItemCategory.ARMOR),
- ("Havel's Leggings", 0x14787478, DS3ItemCategory.ARMOR),
- ("Brigand Hood", 0x148009E0, DS3ItemCategory.ARMOR),
- ("Brigand Armor", 0x14800DC8, DS3ItemCategory.ARMOR),
- ("Brigand Gauntlets", 0x148011B0, DS3ItemCategory.ARMOR),
- ("Brigand Trousers", 0x14801598, DS3ItemCategory.ARMOR),
- ("Pharis's Hat", 0x1487AB00, DS3ItemCategory.ARMOR),
- ("Leather Armor", 0x1487AEE8, DS3ItemCategory.ARMOR),
- ("Leather Gloves", 0x1487B2D0, DS3ItemCategory.ARMOR),
- ("Leather Boots", 0x1487B6B8, DS3ItemCategory.ARMOR),
- ("Ragged Mask", 0x148F4C20, DS3ItemCategory.ARMOR),
- ("Master's Attire", 0x148F5008, DS3ItemCategory.ARMOR),
- ("Master's Gloves", 0x148F53F0, DS3ItemCategory.ARMOR),
- ("Loincloth", 0x148F57D8, DS3ItemCategory.ARMOR),
- ("Old Sorcerer Hat", 0x1496ED40, DS3ItemCategory.ARMOR),
- ("Old Sorcerer Coat", 0x1496F128, DS3ItemCategory.ARMOR),
- ("Old Sorcerer Gauntlets", 0x1496F510, DS3ItemCategory.ARMOR),
- ("Old Sorcerer Boots", 0x1496F8F8, DS3ItemCategory.ARMOR),
- ("Conjurator Hood", 0x149E8E60, DS3ItemCategory.ARMOR),
- ("Conjurator Robe", 0x149E9248, DS3ItemCategory.ARMOR),
- ("Conjurator Manchettes", 0x149E9630, DS3ItemCategory.ARMOR),
- ("Conjurator Boots", 0x149E9A18, DS3ItemCategory.ARMOR),
- ("Black Leather Armor", 0x14A63368, DS3ItemCategory.ARMOR),
- ("Black Leather Gloves", 0x14A63750, DS3ItemCategory.ARMOR),
- ("Black Leather Boots", 0x14A63B38, DS3ItemCategory.ARMOR),
- ("Symbol of Avarice", 0x14ADD0A0, DS3ItemCategory.ARMOR),
- ("Creighton's Steel Mask", 0x14B571C0, DS3ItemCategory.ARMOR),
- ("Mirrah Chain Mail", 0x14B575A8, DS3ItemCategory.ARMOR),
- ("Mirrah Chain Gloves", 0x14B57990, DS3ItemCategory.ARMOR),
- ("Mirrah Chain Leggings", 0x14B57D78, DS3ItemCategory.ARMOR),
- ("Maiden Hood", 0x14BD12E0, DS3ItemCategory.ARMOR),
- ("Maiden Robe", 0x14BD16C8, DS3ItemCategory.ARMOR),
- ("Maiden Gloves", 0x14BD1AB0, DS3ItemCategory.ARMOR),
- ("Maiden Skirt", 0x14BD1E98, DS3ItemCategory.ARMOR),
- ("Alva Helm", 0x14C4B400, DS3ItemCategory.ARMOR),
- ("Alva Armor", 0x14C4B7E8, DS3ItemCategory.ARMOR),
- ("Alva Gauntlets", 0x14C4BBD0, DS3ItemCategory.ARMOR),
- ("Alva Leggings", 0x14C4BFB8, DS3ItemCategory.ARMOR),
- ("Shadow Mask", 0x14D3F640, DS3ItemCategory.ARMOR),
- ("Shadow Garb", 0x14D3FA28, DS3ItemCategory.ARMOR),
- ("Shadow Gauntlets", 0x14D3FE10, DS3ItemCategory.ARMOR),
- ("Shadow Leggings", 0x14D401F8, DS3ItemCategory.ARMOR),
- ("Eastern Helm", 0x14E33880, DS3ItemCategory.ARMOR),
- ("Eastern Armor", 0x14E33C68, DS3ItemCategory.ARMOR),
- ("Eastern Gauntlets", 0x14E34050, DS3ItemCategory.ARMOR),
- ("Eastern Leggings", 0x14E34438, DS3ItemCategory.ARMOR),
- ("Helm of Favor", 0x14F27AC0, DS3ItemCategory.ARMOR),
- ("Embraced Armor of Favor", 0x14F27EA8, DS3ItemCategory.ARMOR),
- ("Gauntlets of Favor", 0x14F28290, DS3ItemCategory.ARMOR),
- ("Leggings of Favor", 0x14F28678, DS3ItemCategory.ARMOR),
- ("Brass Helm", 0x1501BD00, DS3ItemCategory.ARMOR),
- ("Brass Armor", 0x1501C0E8, DS3ItemCategory.ARMOR),
- ("Brass Gauntlets", 0x1501C4D0, DS3ItemCategory.ARMOR),
- ("Brass Leggings", 0x1501C8B8, DS3ItemCategory.ARMOR),
- ("Silver Knight Helm", 0x1510FF40, DS3ItemCategory.ARMOR),
- ("Silver Knight Armor", 0x15110328, DS3ItemCategory.ARMOR),
- ("Silver Knight Gauntlets", 0x15110710, DS3ItemCategory.ARMOR),
- ("Silver Knight Leggings", 0x15110AF8, DS3ItemCategory.ARMOR),
- ("Lucatiel's Mask", 0x15204180, DS3ItemCategory.ARMOR),
- ("Mirrah Vest", 0x15204568, DS3ItemCategory.ARMOR),
- ("Mirrah Gloves", 0x15204950, DS3ItemCategory.ARMOR),
- ("Mirrah Trousers", 0x15204D38, DS3ItemCategory.ARMOR),
- ("Iron Helm", 0x152F83C0, DS3ItemCategory.ARMOR),
- ("Armor of the Sun", 0x152F87A8, DS3ItemCategory.ARMOR),
- ("Iron Bracelets", 0x152F8B90, DS3ItemCategory.ARMOR),
- ("Iron Leggings", 0x152F8F78, DS3ItemCategory.ARMOR),
- ("Drakeblood Helm", 0x153EC600, DS3ItemCategory.ARMOR),
- ("Drakeblood Armor", 0x153EC9E8, DS3ItemCategory.ARMOR),
- ("Drakeblood Gauntlets", 0x153ECDD0, DS3ItemCategory.ARMOR),
- ("Drakeblood Leggings", 0x153ED1B8, DS3ItemCategory.ARMOR),
- ("Drang Armor", 0x154E0C28, DS3ItemCategory.ARMOR),
- ("Drang Gauntlets", 0x154E1010, DS3ItemCategory.ARMOR),
- ("Drang Shoes", 0x154E13F8, DS3ItemCategory.ARMOR),
- ("Black Iron Helm", 0x155D4A80, DS3ItemCategory.ARMOR),
- ("Black Iron Armor", 0x155D4E68, DS3ItemCategory.ARMOR),
- ("Black Iron Gauntlets", 0x155D5250, DS3ItemCategory.ARMOR),
- ("Black Iron Leggings", 0x155D5638, DS3ItemCategory.ARMOR),
- ("Painting Guardian Hood", 0x156C8CC0, DS3ItemCategory.ARMOR),
- ("Painting Guardian Gown", 0x156C90A8, DS3ItemCategory.ARMOR),
- ("Painting Guardian Gloves", 0x156C9490, DS3ItemCategory.ARMOR),
- ("Painting Guardian Waistcloth", 0x156C9878, DS3ItemCategory.ARMOR),
- ("Wolf Knight Helm", 0x157BCF00, DS3ItemCategory.ARMOR),
- ("Wolf Knight Armor", 0x157BD2E8, DS3ItemCategory.ARMOR),
- ("Wolf Knight Gauntlets", 0x157BD6D0, DS3ItemCategory.ARMOR),
- ("Wolf Knight Leggings", 0x157BDAB8, DS3ItemCategory.ARMOR),
- ("Dragonslayer Helm", 0x158B1140, DS3ItemCategory.ARMOR),
- ("Dragonslayer Armor", 0x158B1528, DS3ItemCategory.ARMOR),
- ("Dragonslayer Gauntlets", 0x158B1910, DS3ItemCategory.ARMOR),
- ("Dragonslayer Leggings", 0x158B1CF8, DS3ItemCategory.ARMOR),
- ("Smough's Helm", 0x159A5380, DS3ItemCategory.ARMOR),
- ("Smough's Armor", 0x159A5768, DS3ItemCategory.ARMOR),
- ("Smough's Gauntlets", 0x159A5B50, DS3ItemCategory.ARMOR),
- ("Smough's Leggings", 0x159A5F38, DS3ItemCategory.ARMOR),
- ("Helm of Thorns", 0x15B8D800, DS3ItemCategory.ARMOR),
- ("Armor of Thorns", 0x15B8DBE8, DS3ItemCategory.ARMOR),
- ("Gauntlets of Thorns", 0x15B8DFD0, DS3ItemCategory.ARMOR),
- ("Leggings of Thorns", 0x15B8E3B8, DS3ItemCategory.ARMOR),
- ("Crown of Dusk", 0x15D75C80, DS3ItemCategory.ARMOR),
- ("Antiquated Dress", 0x15D76068, DS3ItemCategory.ARMOR),
- ("Antiquated Gloves", 0x15D76450, DS3ItemCategory.ARMOR),
- ("Antiquated Skirt", 0x15D76838, DS3ItemCategory.ARMOR),
- ("Karla's Pointed Hat", 0x15E69EC0, DS3ItemCategory.ARMOR),
- ("Karla's Coat", 0x15E6A2A8, DS3ItemCategory.ARMOR),
- ("Karla's Gloves", 0x15E6A690, DS3ItemCategory.ARMOR),
- ("Karla's Trousers", 0x15E6AA78, DS3ItemCategory.ARMOR),
+ DS3ItemData("Fallen Knight Helm", 0x1121EAC0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Fallen Knight Armor", 0x1121EEA8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Fallen Knight Gauntlets", 0x1121F290, DS3ItemCategory.ARMOR),
+ DS3ItemData("Fallen Knight Trousers", 0x1121F678, DS3ItemCategory.ARMOR),
+ DS3ItemData("Knight Helm", 0x11298BE0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Knight Armor", 0x11298FC8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Knight Gauntlets", 0x112993B0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Knight Leggings", 0x11299798, DS3ItemCategory.ARMOR),
+ DS3ItemData("Firelink Helm", 0x11406F40, DS3ItemCategory.ARMOR),
+ DS3ItemData("Firelink Armor", 0x11407328, DS3ItemCategory.ARMOR),
+ DS3ItemData("Firelink Gauntlets", 0x11407710, DS3ItemCategory.ARMOR),
+ DS3ItemData("Firelink Leggings", 0x11407AF8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sellsword Helm", 0x11481060, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sellsword Armor", 0x11481448, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sellsword Gauntlet", 0x11481830, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sellsword Trousers", 0x11481C18, DS3ItemCategory.ARMOR),
+ DS3ItemData("Herald Helm", 0x114FB180, DS3ItemCategory.ARMOR),
+ DS3ItemData("Herald Armor", 0x114FB568, DS3ItemCategory.ARMOR),
+ DS3ItemData("Herald Gloves", 0x114FB950, DS3ItemCategory.ARMOR),
+ DS3ItemData("Herald Trousers", 0x114FBD38, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sunless Veil", 0x115752A0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sunless Armor", 0x11575688, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sunless Gauntlets", 0x11575A70, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sunless Leggings", 0x11575E58, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Hand Hat", 0x115EF3C0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Hand Armor", 0x115EF7A8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Assassin Gloves", 0x115EFB90, DS3ItemCategory.ARMOR),
+ DS3ItemData("Assassin Trousers", 0x115EFF78, DS3ItemCategory.ARMOR),
+ DS3ItemData("Assassin Hood", 0x11607A60, DS3ItemCategory.ARMOR),
+ DS3ItemData("Assassin Armor", 0x11607E48, DS3ItemCategory.ARMOR),
+ DS3ItemData("Xanthous Crown", 0x116694E0, DS3ItemCategory.ARMOR,
+ classification = ItemClassification.progression), # Crow trade
+ DS3ItemData("Xanthous Overcoat", 0x116698C8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Xanthous Gloves", 0x11669CB0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Xanthous Trousers", 0x1166A098, DS3ItemCategory.ARMOR),
+ DS3ItemData("Northern Helm", 0x116E3600, DS3ItemCategory.ARMOR),
+ DS3ItemData("Northern Armor", 0x116E39E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Northern Gloves", 0x116E3DD0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Northern Trousers", 0x116E41B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Morne's Helm", 0x1175D720, DS3ItemCategory.ARMOR),
+ DS3ItemData("Morne's Armor", 0x1175DB08, DS3ItemCategory.ARMOR),
+ DS3ItemData("Morne's Gauntlets", 0x1175DEF0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Morne's Leggings", 0x1175E2D8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Silver Mask", 0x117D7840, DS3ItemCategory.ARMOR),
+ DS3ItemData("Leonhard's Garb", 0x117D7C28, DS3ItemCategory.ARMOR),
+ DS3ItemData("Leonhard's Gauntlets", 0x117D8010, DS3ItemCategory.ARMOR),
+ DS3ItemData("Leonhard's Trousers", 0x117D83F8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sneering Mask", 0x11851960, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pale Shade Robe", 0x11851D48, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pale Shade Gloves", 0x11852130, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pale Shade Trousers", 0x11852518, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sunset Helm", 0x118CBA80, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sunset Armor", 0x118CBE68, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sunset Gauntlets", 0x118CC250, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sunset Leggings", 0x118CC638, DS3ItemCategory.ARMOR),
+ DS3ItemData("Old Sage's Blindfold", 0x11945BA0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Cornyx's Garb", 0x11945F88, DS3ItemCategory.ARMOR),
+ DS3ItemData("Cornyx's Wrap", 0x11946370, DS3ItemCategory.ARMOR),
+ DS3ItemData("Cornyx's Skirt", 0x11946758, DS3ItemCategory.ARMOR),
+ DS3ItemData("Executioner Helm", 0x119BFCC0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Executioner Armor", 0x119C00A8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Executioner Gauntlets", 0x119C0490, DS3ItemCategory.ARMOR),
+ DS3ItemData("Executioner Leggings", 0x119C0878, DS3ItemCategory.ARMOR),
+ DS3ItemData("Billed Mask", 0x11A39DE0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Dress", 0x11A3A1C8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Gauntlets", 0x11A3A5B0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Leggings", 0x11A3A998, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pyromancer Crown", 0x11AB3F00, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pyromancer Garb", 0x11AB42E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pyromancer Wrap", 0x11AB46D0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pyromancer Trousers", 0x11AB4AB8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Court Sorcerer Hood", 0x11BA8140, DS3ItemCategory.ARMOR),
+ DS3ItemData("Court Sorcerer Robe", 0x11BA8528, DS3ItemCategory.ARMOR),
+ DS3ItemData("Court Sorcerer Gloves", 0x11BA8910, DS3ItemCategory.ARMOR),
+ DS3ItemData("Court Sorcerer Trousers", 0x11BA8CF8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sorcerer Hood", 0x11C9C380, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sorcerer Robe", 0x11C9C768, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sorcerer Gloves", 0x11C9CB50, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sorcerer Trousers", 0x11C9CF38, DS3ItemCategory.ARMOR),
+ DS3ItemData("Clandestine Coat", 0x11CB4E08, DS3ItemCategory.ARMOR),
+ DS3ItemData("Cleric Hat", 0x11D905C0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Cleric Blue Robe", 0x11D909A8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Cleric Gloves", 0x11D90D90, DS3ItemCategory.ARMOR),
+ DS3ItemData("Cleric Trousers", 0x11D91178, DS3ItemCategory.ARMOR),
+ DS3ItemData("Steel Soldier Helm", 0x12625A00, DS3ItemCategory.ARMOR),
+ DS3ItemData("Deserter Armor", 0x12625DE8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Deserter Trousers", 0x126265B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Thief Mask", 0x12656740, DS3ItemCategory.ARMOR),
+ DS3ItemData("Sage's Big Hat", 0x129020C0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Aristocrat's Mask", 0x129F6300, DS3ItemCategory.ARMOR),
+ DS3ItemData("Jailer Robe", 0x129F66E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Jailer Gloves", 0x129F6AD0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Jailer Trousers", 0x129F6EB8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Grave Warden Hood", 0x12BDE780, DS3ItemCategory.ARMOR),
+ DS3ItemData("Grave Warden Robe", 0x12BDEB68, DS3ItemCategory.ARMOR),
+ DS3ItemData("Grave Warden Wrap", 0x12BDEF50, DS3ItemCategory.ARMOR),
+ DS3ItemData("Grave Warden Skirt", 0x12BDF338, DS3ItemCategory.ARMOR),
+ DS3ItemData("Worker Hat", 0x12CD29C0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Worker Garb", 0x12CD2DA8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Worker Gloves", 0x12CD3190, DS3ItemCategory.ARMOR),
+ DS3ItemData("Worker Trousers", 0x12CD3578, DS3ItemCategory.ARMOR),
+ DS3ItemData("Thrall Hood", 0x12D4CAE0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Evangelist Hat", 0x12DC6C00, DS3ItemCategory.ARMOR),
+ DS3ItemData("Evangelist Robe", 0x12DC6FE8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Evangelist Gloves", 0x12DC73D0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Evangelist Trousers", 0x12DC77B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Scholar's Robe", 0x12E41108, DS3ItemCategory.ARMOR),
+ DS3ItemData("Winged Knight Helm", 0x12EBAE40, DS3ItemCategory.ARMOR),
+ DS3ItemData("Winged Knight Armor", 0x12EBB228, DS3ItemCategory.ARMOR),
+ DS3ItemData("Winged Knight Gauntlets", 0x12EBB610, DS3ItemCategory.ARMOR),
+ DS3ItemData("Winged Knight Leggings", 0x12EBB9F8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Cathedral Knight Helm", 0x130291A0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Cathedral Knight Armor", 0x13029588, DS3ItemCategory.ARMOR),
+ DS3ItemData("Cathedral Knight Gauntlets", 0x13029970, DS3ItemCategory.ARMOR),
+ DS3ItemData("Cathedral Knight Leggings", 0x13029D58, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lothric Knight Helm", 0x13197500, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lothric Knight Armor", 0x131978E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lothric Knight Gauntlets", 0x13197CD0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lothric Knight Leggings", 0x131980B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Outrider Knight Helm", 0x1328B740, DS3ItemCategory.ARMOR),
+ DS3ItemData("Outrider Knight Armor", 0x1328BB28, DS3ItemCategory.ARMOR),
+ DS3ItemData("Outrider Knight Gauntlets", 0x1328BF10, DS3ItemCategory.ARMOR),
+ DS3ItemData("Outrider Knight Leggings", 0x1328C2F8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Knight Helm", 0x1337F980, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Knight Armor", 0x1337FD68, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Knight Gauntlets", 0x13380150, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Knight Leggings", 0x13380538, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dark Mask", 0x133F9AA0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dark Armor", 0x133F9E88, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dark Gauntlets", 0x133FA270, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dark Leggings", 0x133FA658, DS3ItemCategory.ARMOR),
+ DS3ItemData("Exile Mask", 0x13473BC0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Exile Armor", 0x13473FA8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Exile Gauntlets", 0x13474390, DS3ItemCategory.ARMOR),
+ DS3ItemData("Exile Leggings", 0x13474778, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pontiff Knight Crown", 0x13567E00, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pontiff Knight Armor", 0x135681E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pontiff Knight Gauntlets", 0x135685D0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pontiff Knight Leggings", 0x135689B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Golden Crown", 0x1365C040, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dragonscale Armor", 0x1365C428, DS3ItemCategory.ARMOR),
+ DS3ItemData("Golden Bracelets", 0x1365C810, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dragonscale Waistcloth", 0x1365CBF8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Wolnir's Crown", 0x136D6160, DS3ItemCategory.ARMOR),
+ DS3ItemData("Undead Legion Helm", 0x13750280, DS3ItemCategory.ARMOR),
+ DS3ItemData("Undead Legion Armor", 0x13750668, DS3ItemCategory.ARMOR),
+ DS3ItemData("Undead Legion Gauntlet", 0x13750A50, DS3ItemCategory.ARMOR),
+ DS3ItemData("Undead Legion Leggings", 0x13750E38, DS3ItemCategory.ARMOR),
+ DS3ItemData("Fire Witch Helm", 0x13938700, DS3ItemCategory.ARMOR),
+ DS3ItemData("Fire Witch Armor", 0x13938AE8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Fire Witch Gauntlets", 0x13938ED0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Fire Witch Leggings", 0x139392B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lorian's Helm", 0x13A2C940, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lorian's Armor", 0x13A2CD28, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lorian's Gauntlets", 0x13A2D110, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lorian's Leggings", 0x13A2D4F8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Hood of Prayer", 0x13AA6A60, DS3ItemCategory.ARMOR),
+ DS3ItemData("Robe of Prayer", 0x13AA6E48, DS3ItemCategory.ARMOR),
+ DS3ItemData("Skirt of Prayer", 0x13AA7618, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dancer's Crown", 0x13C14DC0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dancer's Armor", 0x13C151A8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dancer's Gauntlets", 0x13C15590, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dancer's Leggings", 0x13C15978, DS3ItemCategory.ARMOR),
+ DS3ItemData("Gundyr's Helm", 0x13D09000, DS3ItemCategory.ARMOR),
+ DS3ItemData("Gundyr's Armor", 0x13D093E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Gundyr's Gauntlets", 0x13D097D0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Gundyr's Leggings", 0x13D09BB8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Archdeacon White Crown", 0x13EF1480, DS3ItemCategory.ARMOR),
+ DS3ItemData("Archdeacon Holy Garb", 0x13EF1868, DS3ItemCategory.ARMOR),
+ DS3ItemData("Archdeacon Skirt", 0x13EF2038, DS3ItemCategory.ARMOR),
+ DS3ItemData("Deacon Robe", 0x13F6B988, DS3ItemCategory.ARMOR),
+ DS3ItemData("Deacon Skirt", 0x13F6C158, DS3ItemCategory.ARMOR),
+ DS3ItemData("Fire Keeper Robe", 0x140D9CE8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Fire Keeper Gloves", 0x140DA0D0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Fire Keeper Skirt", 0x140DA4B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Chain Helm", 0x142C1D80, DS3ItemCategory.ARMOR),
+ DS3ItemData("Chain Armor", 0x142C2168, DS3ItemCategory.ARMOR),
+ DS3ItemData("Leather Gauntlets", 0x142C2550, DS3ItemCategory.ARMOR),
+ DS3ItemData("Chain Leggings", 0x142C2938, DS3ItemCategory.ARMOR),
+ DS3ItemData("Nameless Knight Helm", 0x143B5FC0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Nameless Knight Armor", 0x143B63A8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Nameless Knight Gauntlets", 0x143B6790, DS3ItemCategory.ARMOR),
+ DS3ItemData("Nameless Knight Leggings", 0x143B6B78, DS3ItemCategory.ARMOR),
+ DS3ItemData("Elite Knight Helm", 0x144AA200, DS3ItemCategory.ARMOR),
+ DS3ItemData("Elite Knight Armor", 0x144AA5E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Elite Knight Gauntlets", 0x144AA9D0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Elite Knight Leggings", 0x144AADB8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Faraam Helm", 0x1459E440, DS3ItemCategory.ARMOR),
+ DS3ItemData("Faraam Armor", 0x1459E828, DS3ItemCategory.ARMOR),
+ DS3ItemData("Faraam Gauntlets", 0x1459EC10, DS3ItemCategory.ARMOR),
+ DS3ItemData("Faraam Boots", 0x1459EFF8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Catarina Helm", 0x14692680, DS3ItemCategory.ARMOR),
+ DS3ItemData("Catarina Armor", 0x14692A68, DS3ItemCategory.ARMOR),
+ DS3ItemData("Catarina Gauntlets", 0x14692E50, DS3ItemCategory.ARMOR),
+ DS3ItemData("Catarina Leggings", 0x14693238, DS3ItemCategory.ARMOR),
+ DS3ItemData("Standard Helm", 0x1470C7A0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Hard Leather Armor", 0x1470CB88, DS3ItemCategory.ARMOR),
+ DS3ItemData("Hard Leather Gauntlets", 0x1470CF70, DS3ItemCategory.ARMOR),
+ DS3ItemData("Hard Leather Boots", 0x1470D358, DS3ItemCategory.ARMOR),
+ DS3ItemData("Havel's Helm", 0x147868C0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Havel's Armor", 0x14786CA8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Havel's Gauntlets", 0x14787090, DS3ItemCategory.ARMOR),
+ DS3ItemData("Havel's Leggings", 0x14787478, DS3ItemCategory.ARMOR),
+ DS3ItemData("Brigand Hood", 0x148009E0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Brigand Armor", 0x14800DC8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Brigand Gauntlets", 0x148011B0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Brigand Trousers", 0x14801598, DS3ItemCategory.ARMOR),
+ DS3ItemData("Pharis's Hat", 0x1487AB00, DS3ItemCategory.ARMOR),
+ DS3ItemData("Leather Armor", 0x1487AEE8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Leather Gloves", 0x1487B2D0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Leather Boots", 0x1487B6B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ragged Mask", 0x148F4C20, DS3ItemCategory.ARMOR),
+ DS3ItemData("Master's Attire", 0x148F5008, DS3ItemCategory.ARMOR),
+ DS3ItemData("Master's Gloves", 0x148F53F0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Loincloth", 0x148F57D8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Old Sorcerer Hat", 0x1496ED40, DS3ItemCategory.ARMOR),
+ DS3ItemData("Old Sorcerer Coat", 0x1496F128, DS3ItemCategory.ARMOR),
+ DS3ItemData("Old Sorcerer Gauntlets", 0x1496F510, DS3ItemCategory.ARMOR),
+ DS3ItemData("Old Sorcerer Boots", 0x1496F8F8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Conjurator Hood", 0x149E8E60, DS3ItemCategory.ARMOR),
+ DS3ItemData("Conjurator Robe", 0x149E9248, DS3ItemCategory.ARMOR),
+ DS3ItemData("Conjurator Manchettes", 0x149E9630, DS3ItemCategory.ARMOR),
+ DS3ItemData("Conjurator Boots", 0x149E9A18, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Leather Armor", 0x14A63368, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Leather Gloves", 0x14A63750, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Leather Boots", 0x14A63B38, DS3ItemCategory.ARMOR),
+ DS3ItemData("Symbol of Avarice", 0x14ADD0A0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Creighton's Steel Mask", 0x14B571C0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Mirrah Chain Mail", 0x14B575A8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Mirrah Chain Gloves", 0x14B57990, DS3ItemCategory.ARMOR),
+ DS3ItemData("Mirrah Chain Leggings", 0x14B57D78, DS3ItemCategory.ARMOR),
+ DS3ItemData("Maiden Hood", 0x14BD12E0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Maiden Robe", 0x14BD16C8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Maiden Gloves", 0x14BD1AB0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Maiden Skirt", 0x14BD1E98, DS3ItemCategory.ARMOR),
+ DS3ItemData("Alva Helm", 0x14C4B400, DS3ItemCategory.ARMOR),
+ DS3ItemData("Alva Armor", 0x14C4B7E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Alva Gauntlets", 0x14C4BBD0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Alva Leggings", 0x14C4BFB8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Shadow Mask", 0x14D3F640, DS3ItemCategory.ARMOR),
+ DS3ItemData("Shadow Garb", 0x14D3FA28, DS3ItemCategory.ARMOR),
+ DS3ItemData("Shadow Gauntlets", 0x14D3FE10, DS3ItemCategory.ARMOR),
+ DS3ItemData("Shadow Leggings", 0x14D401F8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Eastern Helm", 0x14E33880, DS3ItemCategory.ARMOR),
+ DS3ItemData("Eastern Armor", 0x14E33C68, DS3ItemCategory.ARMOR),
+ DS3ItemData("Eastern Gauntlets", 0x14E34050, DS3ItemCategory.ARMOR),
+ DS3ItemData("Eastern Leggings", 0x14E34438, DS3ItemCategory.ARMOR),
+ DS3ItemData("Helm of Favor", 0x14F27AC0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Embraced Armor of Favor", 0x14F27EA8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Gauntlets of Favor", 0x14F28290, DS3ItemCategory.ARMOR),
+ DS3ItemData("Leggings of Favor", 0x14F28678, DS3ItemCategory.ARMOR),
+ DS3ItemData("Brass Helm", 0x1501BD00, DS3ItemCategory.ARMOR),
+ DS3ItemData("Brass Armor", 0x1501C0E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Brass Gauntlets", 0x1501C4D0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Brass Leggings", 0x1501C8B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Silver Knight Helm", 0x1510FF40, DS3ItemCategory.ARMOR),
+ DS3ItemData("Silver Knight Armor", 0x15110328, DS3ItemCategory.ARMOR),
+ DS3ItemData("Silver Knight Gauntlets", 0x15110710, DS3ItemCategory.ARMOR),
+ DS3ItemData("Silver Knight Leggings", 0x15110AF8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lucatiel's Mask", 0x15204180, DS3ItemCategory.ARMOR),
+ DS3ItemData("Mirrah Vest", 0x15204568, DS3ItemCategory.ARMOR),
+ DS3ItemData("Mirrah Gloves", 0x15204950, DS3ItemCategory.ARMOR),
+ DS3ItemData("Mirrah Trousers", 0x15204D38, DS3ItemCategory.ARMOR),
+ DS3ItemData("Iron Helm", 0x152F83C0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Armor of the Sun", 0x152F87A8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Iron Bracelets", 0x152F8B90, DS3ItemCategory.ARMOR),
+ DS3ItemData("Iron Leggings", 0x152F8F78, DS3ItemCategory.ARMOR),
+ DS3ItemData("Drakeblood Helm", 0x153EC600, DS3ItemCategory.ARMOR),
+ DS3ItemData("Drakeblood Armor", 0x153EC9E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Drakeblood Gauntlets", 0x153ECDD0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Drakeblood Leggings", 0x153ED1B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Drang Armor", 0x154E0C28, DS3ItemCategory.ARMOR),
+ DS3ItemData("Drang Gauntlets", 0x154E1010, DS3ItemCategory.ARMOR),
+ DS3ItemData("Drang Shoes", 0x154E13F8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Iron Helm", 0x155D4A80, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Iron Armor", 0x155D4E68, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Iron Gauntlets", 0x155D5250, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Iron Leggings", 0x155D5638, DS3ItemCategory.ARMOR),
+ DS3ItemData("Painting Guardian Hood", 0x156C8CC0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Painting Guardian Gown", 0x156C90A8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Painting Guardian Gloves", 0x156C9490, DS3ItemCategory.ARMOR),
+ DS3ItemData("Painting Guardian Waistcloth", 0x156C9878, DS3ItemCategory.ARMOR),
+ DS3ItemData("Wolf Knight Helm", 0x157BCF00, DS3ItemCategory.ARMOR),
+ DS3ItemData("Wolf Knight Armor", 0x157BD2E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Wolf Knight Gauntlets", 0x157BD6D0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Wolf Knight Leggings", 0x157BDAB8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dragonslayer Helm", 0x158B1140, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dragonslayer Armor", 0x158B1528, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dragonslayer Gauntlets", 0x158B1910, DS3ItemCategory.ARMOR),
+ DS3ItemData("Dragonslayer Leggings", 0x158B1CF8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Smough's Helm", 0x159A5380, DS3ItemCategory.ARMOR),
+ DS3ItemData("Smough's Armor", 0x159A5768, DS3ItemCategory.ARMOR),
+ DS3ItemData("Smough's Gauntlets", 0x159A5B50, DS3ItemCategory.ARMOR),
+ DS3ItemData("Smough's Leggings", 0x159A5F38, DS3ItemCategory.ARMOR),
+ DS3ItemData("Helm of Thorns", 0x15B8D800, DS3ItemCategory.ARMOR),
+ DS3ItemData("Armor of Thorns", 0x15B8DBE8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Gauntlets of Thorns", 0x15B8DFD0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Leggings of Thorns", 0x15B8E3B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Crown of Dusk", 0x15D75C80, DS3ItemCategory.ARMOR),
+ DS3ItemData("Antiquated Dress", 0x15D76068, DS3ItemCategory.ARMOR),
+ DS3ItemData("Antiquated Gloves", 0x15D76450, DS3ItemCategory.ARMOR),
+ DS3ItemData("Antiquated Skirt", 0x15D76838, DS3ItemCategory.ARMOR),
+ DS3ItemData("Karla's Pointed Hat", 0x15E69EC0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Karla's Coat", 0x15E6A2A8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Karla's Gloves", 0x15E6A690, DS3ItemCategory.ARMOR),
+ DS3ItemData("Karla's Trousers", 0x15E6AA78, DS3ItemCategory.ARMOR),
# Covenants
- ("Blade of the Darkmoon", 0x20002710, DS3ItemCategory.SKIP),
- ("Watchdogs of Farron", 0x20002724, DS3ItemCategory.SKIP),
- ("Aldrich Faithful", 0x2000272E, DS3ItemCategory.SKIP),
- ("Warrior of Sunlight", 0x20002738, DS3ItemCategory.SKIP),
- ("Mound-makers", 0x20002742, DS3ItemCategory.SKIP),
- ("Way of Blue", 0x2000274C, DS3ItemCategory.SKIP),
- ("Blue Sentinels", 0x20002756, DS3ItemCategory.SKIP),
- ("Rosaria's Fingers", 0x20002760, DS3ItemCategory.SKIP),
+ DS3ItemData("Blade of the Darkmoon", 0x20002710, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Watchdogs of Farron", 0x20002724, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Aldrich Faithful", 0x2000272E, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Warrior of Sunlight", 0x20002738, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Mound-makers", 0x20002742, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Way of Blue", 0x2000274C, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Blue Sentinels", 0x20002756, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Rosaria's Fingers", 0x20002760, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Spears of the Church", 0x2000276A, DS3ItemCategory.UNIQUE, skip = True),
# Rings
- ("Life Ring", 0x20004E20, DS3ItemCategory.RING),
- ("Life Ring+1", 0x20004E21, DS3ItemCategory.RING),
- ("Life Ring+2", 0x20004E22, DS3ItemCategory.RING),
- ("Life Ring+3", 0x20004E23, DS3ItemCategory.RING),
- ("Chloranthy Ring", 0x20004E2A, DS3ItemCategory.RING),
- ("Chloranthy Ring+1", 0x20004E2B, DS3ItemCategory.RING),
- ("Chloranthy Ring+2", 0x20004E2C, DS3ItemCategory.RING),
- ("Havel's Ring", 0x20004E34, DS3ItemCategory.RING),
- ("Havel's Ring+1", 0x20004E35, DS3ItemCategory.RING),
- ("Havel's Ring+2", 0x20004E36, DS3ItemCategory.RING),
- ("Ring of Favor", 0x20004E3E, DS3ItemCategory.RING),
- ("Ring of Favor+1", 0x20004E3F, DS3ItemCategory.RING),
- ("Ring of Favor+2", 0x20004E40, DS3ItemCategory.RING),
- ("Ring of Steel Protection", 0x20004E48, DS3ItemCategory.RING),
- ("Ring of Steel Protection+1", 0x20004E49, DS3ItemCategory.RING),
- ("Ring of Steel Protection+2", 0x20004E4A, DS3ItemCategory.RING),
- ("Flame Stoneplate Ring", 0x20004E52, DS3ItemCategory.RING),
- ("Flame Stoneplate Ring+1", 0x20004E53, DS3ItemCategory.RING),
- ("Flame Stoneplate Ring+2", 0x20004E54, DS3ItemCategory.RING),
- ("Thunder Stoneplate Ring", 0x20004E5C, DS3ItemCategory.RING),
- ("Thunder Stoneplate Ring+1", 0x20004E5D, DS3ItemCategory.RING),
- ("Thunder Stoneplate Ring+2", 0x20004E5E, DS3ItemCategory.RING),
- ("Magic Stoneplate Ring", 0x20004E66, DS3ItemCategory.RING),
- ("Magic Stoneplate Ring+1", 0x20004E67, DS3ItemCategory.RING),
- ("Magic Stoneplate Ring+2", 0x20004E68, DS3ItemCategory.RING),
- ("Dark Stoneplate Ring", 0x20004E70, DS3ItemCategory.RING),
- ("Dark Stoneplate Ring+1", 0x20004E71, DS3ItemCategory.RING),
- ("Dark Stoneplate Ring+2", 0x20004E72, DS3ItemCategory.RING),
- ("Speckled Stoneplate Ring", 0x20004E7A, DS3ItemCategory.RING),
- ("Speckled Stoneplate Ring+1", 0x20004E7B, DS3ItemCategory.RING),
- ("Bloodbite Ring", 0x20004E84, DS3ItemCategory.RING),
- ("Bloodbite Ring+1", 0x20004E85, DS3ItemCategory.RING),
- ("Poisonbite Ring", 0x20004E8E, DS3ItemCategory.RING),
- ("Poisonbite Ring+1", 0x20004E8F, DS3ItemCategory.RING),
- ("Cursebite Ring", 0x20004E98, DS3ItemCategory.RING),
- ("Fleshbite Ring", 0x20004EA2, DS3ItemCategory.RING),
- ("Fleshbite Ring+1", 0x20004EA3, DS3ItemCategory.RING),
- ("Wood Grain Ring", 0x20004EAC, DS3ItemCategory.RING),
- ("Wood Grain Ring+1", 0x20004EAD, DS3ItemCategory.RING),
- ("Wood Grain Ring+2", 0x20004EAE, DS3ItemCategory.RING),
- ("Scholar Ring", 0x20004EB6, DS3ItemCategory.RING),
- ("Priestess Ring", 0x20004EC0, DS3ItemCategory.RING),
- ("Red Tearstone Ring", 0x20004ECA, DS3ItemCategory.RING),
- ("Blue Tearstone Ring", 0x20004ED4, DS3ItemCategory.RING),
- ("Wolf Ring", 0x20004EDE, DS3ItemCategory.RING),
- ("Wolf Ring+1", 0x20004EDF, DS3ItemCategory.RING),
- ("Wolf Ring+2", 0x20004EE0, DS3ItemCategory.RING),
- ("Leo Ring", 0x20004EE8, DS3ItemCategory.RING),
- ("Ring of Sacrifice", 0x20004EF2, DS3ItemCategory.RING),
- ("Young Dragon Ring", 0x20004F06, DS3ItemCategory.RING),
- ("Bellowing Dragoncrest Ring", 0x20004F07, DS3ItemCategory.RING),
- ("Great Swamp Ring", 0x20004F10, DS3ItemCategory.RING),
- ("Witch's Ring", 0x20004F11, DS3ItemCategory.RING),
- ("Morne's Ring", 0x20004F1A, DS3ItemCategory.RING),
- ("Ring of the Sun's First Born", 0x20004F1B, DS3ItemCategory.RING),
- ("Lingering Dragoncrest Ring", 0x20004F2E, DS3ItemCategory.RING),
- ("Lingering Dragoncrest Ring+1", 0x20004F2F, DS3ItemCategory.RING),
- ("Lingering Dragoncrest Ring+2", 0x20004F30, DS3ItemCategory.RING),
- ("Sage Ring", 0x20004F38, DS3ItemCategory.RING),
- ("Sage Ring+1", 0x20004F39, DS3ItemCategory.RING),
- ("Sage Ring+2", 0x20004F3A, DS3ItemCategory.RING),
- ("Slumbering Dragoncrest Ring", 0x20004F42, DS3ItemCategory.RING),
- ("Dusk Crown Ring", 0x20004F4C, DS3ItemCategory.RING),
- ("Saint's Ring", 0x20004F56, DS3ItemCategory.RING),
- ("Deep Ring", 0x20004F60, DS3ItemCategory.RING),
- ("Darkmoon Ring", 0x20004F6A, DS3ItemCategory.RING),
- ("Hawk Ring", 0x20004F92, DS3ItemCategory.RING),
- ("Hornet Ring", 0x20004F9C, DS3ItemCategory.RING),
- ("Covetous Gold Serpent Ring", 0x20004FA6, DS3ItemCategory.RING),
- ("Covetous Gold Serpent Ring+1", 0x20004FA7, DS3ItemCategory.RING),
- ("Covetous Gold Serpent Ring+2", 0x20004FA8, DS3ItemCategory.RING),
- ("Covetous Silver Serpent Ring", 0x20004FB0, DS3ItemCategory.RING),
- ("Covetous Silver Serpent Ring+1", 0x20004FB1, DS3ItemCategory.RING),
- ("Covetous Silver Serpent Ring+2", 0x20004FB2, DS3ItemCategory.RING),
- ("Sun Princess Ring", 0x20004FBA, DS3ItemCategory.RING),
- ("Silvercat Ring", 0x20004FC4, DS3ItemCategory.RING),
- ("Skull Ring", 0x20004FCE, DS3ItemCategory.RING),
- ("Untrue White Ring", 0x20004FD8, DS3ItemCategory.RING),
- ("Carthus Milkring", 0x20004FE2, DS3ItemCategory.RING),
- ("Knight's Ring", 0x20004FEC, DS3ItemCategory.RING),
- ("Hunter's Ring", 0x20004FF6, DS3ItemCategory.RING),
- ("Knight Slayer's Ring", 0x20005000, DS3ItemCategory.RING),
- ("Magic Clutch Ring", 0x2000500A, DS3ItemCategory.RING),
- ("Lightning Clutch Ring", 0x20005014, DS3ItemCategory.RING),
- ("Fire Clutch Ring", 0x2000501E, DS3ItemCategory.RING),
- ("Dark Clutch Ring", 0x20005028, DS3ItemCategory.RING),
- ("Flynn's Ring", 0x2000503C, DS3ItemCategory.RING),
- ("Prisoner's Chain", 0x20005046, DS3ItemCategory.RING),
- ("Untrue Dark Ring", 0x20005050, DS3ItemCategory.RING),
- ("Obscuring Ring", 0x20005064, DS3ItemCategory.RING),
- ("Ring of the Evil Eye", 0x2000506E, DS3ItemCategory.RING),
- ("Ring of the Evil Eye+1", 0x2000506F, DS3ItemCategory.RING),
- ("Ring of the Evil Eye+2", 0x20005070, DS3ItemCategory.RING),
- ("Calamity Ring", 0x20005078, DS3ItemCategory.RING),
- ("Farron Ring", 0x20005082, DS3ItemCategory.RING),
- ("Aldrich's Ruby", 0x2000508C, DS3ItemCategory.RING),
- ("Aldrich's Sapphire", 0x20005096, DS3ItemCategory.RING),
- ("Lloyd's Sword Ring", 0x200050B4, DS3ItemCategory.RING),
- ("Lloyd's Shield Ring", 0x200050BE, DS3ItemCategory.RING),
- ("Estus Ring", 0x200050DC, DS3ItemCategory.RING),
- ("Ashen Estus Ring", 0x200050E6, DS3ItemCategory.RING),
- ("Carthus Bloodring", 0x200050FA, DS3ItemCategory.RING),
- ("Reversal Ring", 0x20005104, DS3ItemCategory.RING),
- ("Pontiff's Right Eye", 0x2000510E, DS3ItemCategory.RING),
- ("Pontiff's Left Eye", 0x20005136, DS3ItemCategory.RING),
- ("Dragonscale Ring", 0x2000515E, DS3ItemCategory.RING),
+ DS3ItemData("Life Ring", 0x20004E20, DS3ItemCategory.RING),
+ DS3ItemData("Life Ring+1", 0x20004E21, DS3ItemCategory.RING),
+ DS3ItemData("Life Ring+2", 0x20004E22, DS3ItemCategory.RING),
+ DS3ItemData("Life Ring+3", 0x20004E23, DS3ItemCategory.RING),
+ DS3ItemData("Chloranthy Ring", 0x20004E2A, DS3ItemCategory.RING,
+ useful_if = UsefulIf.BASE),
+ DS3ItemData("Chloranthy Ring+1", 0x20004E2B, DS3ItemCategory.RING),
+ DS3ItemData("Chloranthy Ring+2", 0x20004E2C, DS3ItemCategory.RING,
+ useful_if = UsefulIf.NO_DLC),
+ DS3ItemData("Havel's Ring", 0x20004E34, DS3ItemCategory.RING,
+ useful_if = UsefulIf.BASE),
+ DS3ItemData("Havel's Ring+1", 0x20004E35, DS3ItemCategory.RING),
+ DS3ItemData("Havel's Ring+2", 0x20004E36, DS3ItemCategory.RING,
+ useful_if = UsefulIf.NO_DLC),
+ DS3ItemData("Ring of Favor", 0x20004E3E, DS3ItemCategory.RING,
+ useful_if = UsefulIf.BASE),
+ DS3ItemData("Ring of Favor+1", 0x20004E3F, DS3ItemCategory.RING),
+ DS3ItemData("Ring of Favor+2", 0x20004E40, DS3ItemCategory.RING,
+ useful_if = UsefulIf.NO_DLC),
+ DS3ItemData("Ring of Steel Protection", 0x20004E48, DS3ItemCategory.RING,
+ useful_if = UsefulIf.BASE),
+ DS3ItemData("Ring of Steel Protection+1", 0x20004E49, DS3ItemCategory.RING),
+ DS3ItemData("Ring of Steel Protection+2", 0x20004E4A, DS3ItemCategory.RING,
+ useful_if = UsefulIf.NO_DLC),
+ DS3ItemData("Flame Stoneplate Ring", 0x20004E52, DS3ItemCategory.RING),
+ DS3ItemData("Flame Stoneplate Ring+1", 0x20004E53, DS3ItemCategory.RING),
+ DS3ItemData("Flame Stoneplate Ring+2", 0x20004E54, DS3ItemCategory.RING),
+ DS3ItemData("Thunder Stoneplate Ring", 0x20004E5C, DS3ItemCategory.RING),
+ DS3ItemData("Thunder Stoneplate Ring+1", 0x20004E5D, DS3ItemCategory.RING),
+ DS3ItemData("Thunder Stoneplate Ring+2", 0x20004E5E, DS3ItemCategory.RING),
+ DS3ItemData("Magic Stoneplate Ring", 0x20004E66, DS3ItemCategory.RING),
+ DS3ItemData("Magic Stoneplate Ring+1", 0x20004E67, DS3ItemCategory.RING),
+ DS3ItemData("Magic Stoneplate Ring+2", 0x20004E68, DS3ItemCategory.RING),
+ DS3ItemData("Dark Stoneplate Ring", 0x20004E70, DS3ItemCategory.RING),
+ DS3ItemData("Dark Stoneplate Ring+1", 0x20004E71, DS3ItemCategory.RING),
+ DS3ItemData("Dark Stoneplate Ring+2", 0x20004E72, DS3ItemCategory.RING),
+ DS3ItemData("Speckled Stoneplate Ring", 0x20004E7A, DS3ItemCategory.RING),
+ DS3ItemData("Speckled Stoneplate Ring+1", 0x20004E7B, DS3ItemCategory.RING),
+ DS3ItemData("Bloodbite Ring", 0x20004E84, DS3ItemCategory.RING),
+ DS3ItemData("Bloodbite Ring+1", 0x20004E85, DS3ItemCategory.RING),
+ DS3ItemData("Poisonbite Ring", 0x20004E8E, DS3ItemCategory.RING),
+ DS3ItemData("Poisonbite Ring+1", 0x20004E8F, DS3ItemCategory.RING),
+ DS3ItemData("Cursebite Ring", 0x20004E98, DS3ItemCategory.RING),
+ DS3ItemData("Fleshbite Ring", 0x20004EA2, DS3ItemCategory.RING),
+ DS3ItemData("Fleshbite Ring+1", 0x20004EA3, DS3ItemCategory.RING),
+ DS3ItemData("Wood Grain Ring", 0x20004EAC, DS3ItemCategory.RING),
+ DS3ItemData("Wood Grain Ring+1", 0x20004EAD, DS3ItemCategory.RING),
+ DS3ItemData("Wood Grain Ring+2", 0x20004EAE, DS3ItemCategory.RING),
+ DS3ItemData("Scholar Ring", 0x20004EB6, DS3ItemCategory.RING),
+ DS3ItemData("Priestess Ring", 0x20004EC0, DS3ItemCategory.RING),
+ DS3ItemData("Red Tearstone Ring", 0x20004ECA, DS3ItemCategory.RING),
+ DS3ItemData("Blue Tearstone Ring", 0x20004ED4, DS3ItemCategory.RING),
+ DS3ItemData("Wolf Ring", 0x20004EDE, DS3ItemCategory.RING,
+ inject = True), # Covenant reward
+ DS3ItemData("Wolf Ring+1", 0x20004EDF, DS3ItemCategory.RING),
+ DS3ItemData("Wolf Ring+2", 0x20004EE0, DS3ItemCategory.RING),
+ DS3ItemData("Leo Ring", 0x20004EE8, DS3ItemCategory.RING),
+ DS3ItemData("Ring of Sacrifice", 0x20004EF2, DS3ItemCategory.RING, filler = True),
+ DS3ItemData("Young Dragon Ring", 0x20004F06, DS3ItemCategory.RING),
+ DS3ItemData("Bellowing Dragoncrest Ring", 0x20004F07, DS3ItemCategory.RING),
+ DS3ItemData("Great Swamp Ring", 0x20004F10, DS3ItemCategory.RING),
+ DS3ItemData("Witch's Ring", 0x20004F11, DS3ItemCategory.RING),
+ DS3ItemData("Morne's Ring", 0x20004F1A, DS3ItemCategory.RING),
+ DS3ItemData("Ring of the Sun's First Born", 0x20004F1B, DS3ItemCategory.RING),
+ DS3ItemData("Lingering Dragoncrest Ring", 0x20004F2E, DS3ItemCategory.RING),
+ DS3ItemData("Lingering Dragoncrest Ring+1", 0x20004F2F, DS3ItemCategory.RING),
+ DS3ItemData("Lingering Dragoncrest Ring+2", 0x20004F30, DS3ItemCategory.RING),
+ DS3ItemData("Sage Ring", 0x20004F38, DS3ItemCategory.RING,
+ useful_if = UsefulIf.NO_NGP),
+ DS3ItemData("Sage Ring+1", 0x20004F39, DS3ItemCategory.RING),
+ DS3ItemData("Sage Ring+2", 0x20004F3A, DS3ItemCategory.RING,
+ classification = ItemClassification.useful),
+ DS3ItemData("Slumbering Dragoncrest Ring", 0x20004F42, DS3ItemCategory.RING),
+ DS3ItemData("Dusk Crown Ring", 0x20004F4C, DS3ItemCategory.RING),
+ DS3ItemData("Saint's Ring", 0x20004F56, DS3ItemCategory.RING),
+ DS3ItemData("Deep Ring", 0x20004F60, DS3ItemCategory.RING),
+ DS3ItemData("Darkmoon Ring", 0x20004F6A, DS3ItemCategory.RING,
+ inject = True), # Covenant reward
+ DS3ItemData("Hawk Ring", 0x20004F92, DS3ItemCategory.RING),
+ DS3ItemData("Hornet Ring", 0x20004F9C, DS3ItemCategory.RING),
+ DS3ItemData("Covetous Gold Serpent Ring", 0x20004FA6, DS3ItemCategory.RING),
+ DS3ItemData("Covetous Gold Serpent Ring+1", 0x20004FA7, DS3ItemCategory.RING),
+ DS3ItemData("Covetous Gold Serpent Ring+2", 0x20004FA8, DS3ItemCategory.RING),
+ DS3ItemData("Covetous Silver Serpent Ring", 0x20004FB0, DS3ItemCategory.RING,
+ useful_if = UsefulIf.BASE),
+ DS3ItemData("Covetous Silver Serpent Ring+1", 0x20004FB1, DS3ItemCategory.RING),
+ DS3ItemData("Covetous Silver Serpent Ring+2", 0x20004FB2, DS3ItemCategory.RING,
+ useful_if = UsefulIf.NO_DLC),
+ DS3ItemData("Sun Princess Ring", 0x20004FBA, DS3ItemCategory.RING),
+ DS3ItemData("Silvercat Ring", 0x20004FC4, DS3ItemCategory.RING),
+ DS3ItemData("Skull Ring", 0x20004FCE, DS3ItemCategory.RING),
+ DS3ItemData("Untrue White Ring", 0x20004FD8, DS3ItemCategory.RING, skip = True),
+ DS3ItemData("Carthus Milkring", 0x20004FE2, DS3ItemCategory.RING),
+ DS3ItemData("Knight's Ring", 0x20004FEC, DS3ItemCategory.RING),
+ DS3ItemData("Hunter's Ring", 0x20004FF6, DS3ItemCategory.RING),
+ DS3ItemData("Knight Slayer's Ring", 0x20005000, DS3ItemCategory.RING),
+ DS3ItemData("Magic Clutch Ring", 0x2000500A, DS3ItemCategory.RING),
+ DS3ItemData("Lightning Clutch Ring", 0x20005014, DS3ItemCategory.RING),
+ DS3ItemData("Fire Clutch Ring", 0x2000501E, DS3ItemCategory.RING),
+ DS3ItemData("Dark Clutch Ring", 0x20005028, DS3ItemCategory.RING),
+ DS3ItemData("Flynn's Ring", 0x2000503C, DS3ItemCategory.RING),
+ DS3ItemData("Prisoner's Chain", 0x20005046, DS3ItemCategory.RING,
+ classification = ItemClassification.useful),
+ DS3ItemData("Untrue Dark Ring", 0x20005050, DS3ItemCategory.RING),
+ DS3ItemData("Obscuring Ring", 0x20005064, DS3ItemCategory.RING),
+ DS3ItemData("Ring of the Evil Eye", 0x2000506E, DS3ItemCategory.RING),
+ DS3ItemData("Ring of the Evil Eye+1", 0x2000506F, DS3ItemCategory.RING),
+ DS3ItemData("Ring of the Evil Eye+2", 0x20005070, DS3ItemCategory.RING),
+ DS3ItemData("Calamity Ring", 0x20005078, DS3ItemCategory.RING),
+ DS3ItemData("Farron Ring", 0x20005082, DS3ItemCategory.RING),
+ DS3ItemData("Aldrich's Ruby", 0x2000508C, DS3ItemCategory.RING),
+ DS3ItemData("Aldrich's Sapphire", 0x20005096, DS3ItemCategory.RING),
+ DS3ItemData("Lloyd's Sword Ring", 0x200050B4, DS3ItemCategory.RING,
+ classification = ItemClassification.useful),
+ DS3ItemData("Lloyd's Shield Ring", 0x200050BE, DS3ItemCategory.RING),
+ DS3ItemData("Estus Ring", 0x200050DC, DS3ItemCategory.RING),
+ DS3ItemData("Ashen Estus Ring", 0x200050E6, DS3ItemCategory.RING),
+ DS3ItemData("Horsehoof Ring", 0x200050F0, DS3ItemCategory.RING),
+ DS3ItemData("Carthus Bloodring", 0x200050FA, DS3ItemCategory.RING,
+ classification = ItemClassification.useful),
+ DS3ItemData("Reversal Ring", 0x20005104, DS3ItemCategory.RING),
+ DS3ItemData("Pontiff's Right Eye", 0x2000510E, DS3ItemCategory.RING),
+ DS3ItemData("Pontiff's Left Eye", 0x20005136, DS3ItemCategory.RING),
+ DS3ItemData("Dragonscale Ring", 0x2000515E, DS3ItemCategory.RING),
# Items
- ("Roster of Knights", 0x4000006C, DS3ItemCategory.SKIP),
- ("Cracked Red Eye Orb", 0x4000006F, DS3ItemCategory.SKIP),
- ("Divine Blessing", 0x400000F0, DS3ItemCategory.MISC),
- ("Hidden Blessing", 0x400000F1, DS3ItemCategory.MISC),
- ("Silver Pendant", 0x400000F2, DS3ItemCategory.SKIP),
- ("Green Blossom", 0x40000104, DS3ItemCategory.MISC),
- ("Budding Green Blossom", 0x40000106, DS3ItemCategory.MISC),
- ("Bloodred Moss Clump", 0x4000010E, DS3ItemCategory.SKIP),
- ("Purple Moss Clump", 0x4000010F, DS3ItemCategory.MISC),
- ("Blooming Purple Moss Clump", 0x40000110, DS3ItemCategory.SKIP),
- ("Purging Stone", 0x40000112, DS3ItemCategory.SKIP),
- ("Rime-blue Moss Clump", 0x40000114, DS3ItemCategory.SKIP),
- ("Repair Powder", 0x40000118, DS3ItemCategory.MISC),
- ("Kukri", 0x40000122, DS3ItemCategory.SKIP),
- ("Firebomb", 0x40000124, DS3ItemCategory.MISC),
- ("Dung Pie", 0x40000125, DS3ItemCategory.SKIP),
- ("Alluring Skull", 0x40000126, DS3ItemCategory.MISC),
- ("Undead Hunter Charm", 0x40000128, DS3ItemCategory.MISC),
- ("Black Firebomb", 0x40000129, DS3ItemCategory.MISC),
- ("Rope Firebomb", 0x4000012B, DS3ItemCategory.MISC),
- ("Lightning Urn", 0x4000012C, DS3ItemCategory.MISC),
- ("Rope Black Firebomb", 0x4000012E, DS3ItemCategory.MISC),
- ("Stalk Dung Pie", 0x4000012F, DS3ItemCategory.SKIP),
- ("Duel Charm", 0x40000130, DS3ItemCategory.MISC),
- ("Throwing Knife", 0x40000136, DS3ItemCategory.MISC),
- ("Poison Throwing Knife", 0x40000137, DS3ItemCategory.MISC),
- ("Charcoal Pine Resin", 0x4000014A, DS3ItemCategory.MISC),
- ("Gold Pine Resin", 0x4000014B, DS3ItemCategory.MISC),
- ("Human Pine Resin", 0x4000014E, DS3ItemCategory.MISC),
- ("Carthus Rouge", 0x4000014F, DS3ItemCategory.MISC),
- ("Pale Pine Resin", 0x40000150, DS3ItemCategory.MISC),
- ("Charcoal Pine Bundle", 0x40000154, DS3ItemCategory.MISC),
- ("Gold Pine Bundle", 0x40000155, DS3ItemCategory.MISC),
- ("Rotten Pine Resin", 0x40000157, DS3ItemCategory.MISC),
- ("Homeward Bone", 0x4000015E, DS3ItemCategory.MISC),
- ("Coiled Sword Fragment", 0x4000015F, DS3ItemCategory.MISC),
- ("Wolf's Blood Swordgrass", 0x4000016E, DS3ItemCategory.MISC),
- ("Human Dregs", 0x4000016F, DS3ItemCategory.SKIP),
- ("Forked Pale Tongue", 0x40000170, DS3ItemCategory.MISC),
- ("Proof of a Concord Well Kept", 0x40000171, DS3ItemCategory.SKIP),
- ("Prism Stone", 0x40000172, DS3ItemCategory.SKIP),
- ("Binoculars", 0x40000173, DS3ItemCategory.MISC),
- ("Proof of a Concord Kept", 0x40000174, DS3ItemCategory.SKIP),
- ("Pale Tongue", 0x40000175, DS3ItemCategory.MISC),
- ("Vertebra Shackle", 0x40000176, DS3ItemCategory.SKIP),
- ("Sunlight Medal", 0x40000177, DS3ItemCategory.SKIP),
- ("Dragon Head Stone", 0x40000179, DS3ItemCategory.MISC),
- ("Dragon Torso Stone", 0x4000017A, DS3ItemCategory.MISC),
- ("Rubbish", 0x4000017C, DS3ItemCategory.SKIP),
- ("Dried Finger", 0x40000181, DS3ItemCategory.SKIP),
- ("Twinkling Dragon Head Stone", 0x40000183, DS3ItemCategory.MISC),
- ("Twinkling Dragon Torso Stone", 0x40000184, DS3ItemCategory.MISC),
- ("Fire Keeper Soul", 0x40000186, DS3ItemCategory.MISC),
- ("Fading Soul", 0x40000190, DS3ItemCategory.MISC),
- ("Soul of a Deserted Corpse", 0x40000191, DS3ItemCategory.MISC),
- ("Large Soul of a Deserted Corpse", 0x40000192, DS3ItemCategory.MISC),
- ("Soul of an Unknown Traveler", 0x40000193, DS3ItemCategory.MISC),
- ("Large Soul of an Unknown Traveler", 0x40000194, DS3ItemCategory.MISC),
- ("Soul of a Nameless Soldier", 0x40000195, DS3ItemCategory.MISC),
- ("Large Soul of a Nameless Soldier", 0x40000196, DS3ItemCategory.MISC),
- ("Soul of a Weary Warrior", 0x40000197, DS3ItemCategory.MISC),
- ("Large Soul of a Weary Warrior", 0x40000198, DS3ItemCategory.MISC),
- ("Soul of a Crestfallen Knight", 0x40000199, DS3ItemCategory.MISC),
- ("Large Soul of a Crestfallen Knight", 0x4000019A, DS3ItemCategory.MISC),
- ("Soul of a Proud Paladin", 0x4000019B, DS3ItemCategory.MISC),
- ("Large Soul of a Proud Paladin", 0x4000019C, DS3ItemCategory.MISC),
- ("Soul of an Intrepid Hero", 0x4000019D, DS3ItemCategory.MISC),
- ("Large Soul of an Intrepid Hero", 0x4000019E, DS3ItemCategory.MISC),
- ("Soul of a Seasoned Warrior", 0x4000019F, DS3ItemCategory.MISC),
- ("Large Soul of a Seasoned Warrior", 0x400001A0, DS3ItemCategory.MISC),
- ("Soul of an Old Hand", 0x400001A1, DS3ItemCategory.MISC),
- ("Soul of a Venerable Old Hand", 0x400001A2, DS3ItemCategory.MISC),
- ("Soul of a Champion", 0x400001A3, DS3ItemCategory.MISC),
- ("Soul of a Great Champion", 0x400001A4, DS3ItemCategory.MISC),
- ("Seed of a Giant Tree", 0x400001B8, DS3ItemCategory.SKIP),
- ("Young White Branch", 0x400001C6, DS3ItemCategory.SKIP),
- ("Rusted Coin", 0x400001C7, DS3ItemCategory.MISC),
- ("Siegbräu", 0x400001C8, DS3ItemCategory.SKIP),
- ("Rusted Gold Coin", 0x400001C9, DS3ItemCategory.MISC),
- ("Blue Bug Pellet", 0x400001CA, DS3ItemCategory.SKIP),
- ("Red Bug Pellet", 0x400001CB, DS3ItemCategory.SKIP),
- ("Yellow Bug Pellet", 0x400001CC, DS3ItemCategory.SKIP),
- ("Black Bug Pellet", 0x400001CD, DS3ItemCategory.SKIP),
- ("Young White Branch", 0x400001CF, DS3ItemCategory.SKIP),
- ("Dark Sigil", 0x400001EA, DS3ItemCategory.SKIP),
- ("Ember", 0x400001F4, DS3ItemCategory.MISC),
- ("Soul of Champion Gundyr", 0x400002C8, DS3ItemCategory.BOSS),
- ("Soul of the Dancer", 0x400002CA, DS3ItemCategory.BOSS),
- ("Soul of a Crystal Sage", 0x400002CB, DS3ItemCategory.BOSS),
- ("Soul of the Blood of the Wolf", 0x400002CD, DS3ItemCategory.BOSS),
- ("Soul of Consumed Oceiros", 0x400002CE, DS3ItemCategory.BOSS),
- ("Soul of Boreal Valley Vordt", 0x400002CF, DS3ItemCategory.BOSS),
- ("Soul of the Old Demon King", 0x400002D0, DS3ItemCategory.BOSS),
- ("Soul of Dragonslayer Armour", 0x400002D1, DS3ItemCategory.BOSS),
- ("Soul of the Nameless King", 0x400002D2, DS3ItemCategory.BOSS),
- ("Soul of Pontiff Sulyvahn", 0x400002D4, DS3ItemCategory.BOSS),
- ("Soul of Aldrich", 0x400002D5, DS3ItemCategory.BOSS),
- ("Soul of High Lord Wolnir", 0x400002D6, DS3ItemCategory.BOSS),
- ("Soul of the Rotted Greatwood", 0x400002D7, DS3ItemCategory.BOSS),
- ("Soul of Rosaria", 0x400002D8, DS3ItemCategory.MISC),
- ("Soul of the Deacons of the Deep", 0x400002D9, DS3ItemCategory.BOSS),
- ("Soul of the Twin Princes", 0x400002DB, DS3ItemCategory.BOSS),
- ("Soul of Yhorm the Giant", 0x400002DC, DS3ItemCategory.BOSS),
- ("Soul of the Lords", 0x400002DD, DS3ItemCategory.MISC),
- ("Soul of a Demon", 0x400002E3, DS3ItemCategory.BOSS),
- ("Soul of a Stray Demon", 0x400002E7, DS3ItemCategory.BOSS),
- ("Titanite Shard", 0x400003E8, DS3ItemCategory.MISC),
- ("Large Titanite Shard", 0x400003E9, DS3ItemCategory.MISC),
- ("Titanite Chunk", 0x400003EA, DS3ItemCategory.MISC),
- ("Titanite Slab", 0x400003EB, DS3ItemCategory.MISC),
- ("Titanite Scale", 0x400003FC, DS3ItemCategory.MISC),
- ("Twinkling Titanite", 0x40000406, DS3ItemCategory.MISC),
- ("Heavy Gem", 0x4000044C, DS3ItemCategory.MISC),
- ("Sharp Gem", 0x40000456, DS3ItemCategory.MISC),
- ("Refined Gem", 0x40000460, DS3ItemCategory.MISC),
- ("Crystal Gem", 0x4000046A, DS3ItemCategory.MISC),
- ("Simple Gem", 0x40000474, DS3ItemCategory.MISC),
- ("Fire Gem", 0x4000047E, DS3ItemCategory.MISC),
- ("Chaos Gem", 0x40000488, DS3ItemCategory.MISC),
- ("Lightning Gem", 0x40000492, DS3ItemCategory.MISC),
- ("Deep Gem", 0x4000049C, DS3ItemCategory.MISC),
- ("Dark Gem", 0x400004A6, DS3ItemCategory.MISC),
- ("Poison Gem", 0x400004B0, DS3ItemCategory.MISC),
- ("Blood Gem", 0x400004BA, DS3ItemCategory.MISC),
- ("Raw Gem", 0x400004C4, DS3ItemCategory.MISC),
- ("Blessed Gem", 0x400004CE, DS3ItemCategory.MISC),
- ("Hollow Gem", 0x400004D8, DS3ItemCategory.MISC),
- ("Shriving Stone", 0x400004E2, DS3ItemCategory.MISC),
- ("Lift Chamber Key", 0x400007D1, DS3ItemCategory.KEY),
- ("Small Doll", 0x400007D5, DS3ItemCategory.KEY),
- ("Jailbreaker's Key", 0x400007D7, DS3ItemCategory.KEY),
- ("Jailer's Key Ring", 0x400007D8, DS3ItemCategory.KEY),
- ("Grave Key", 0x400007D9, DS3ItemCategory.KEY),
- ("Cell Key", 0x400007DA, DS3ItemCategory.KEY),
- ("Dungeon Ground Floor Key", 0x400007DB, DS3ItemCategory.KEY),
- ("Old Cell Key", 0x400007DC, DS3ItemCategory.KEY),
- ("Grand Archives Key", 0x400007DE, DS3ItemCategory.KEY),
- ("Tower Key", 0x400007DF, DS3ItemCategory.KEY),
- ("Small Lothric Banner", 0x40000836, DS3ItemCategory.KEY),
- ("Farron Coal", 0x40000837, DS3ItemCategory.MISC),
- ("Sage's Coal", 0x40000838, DS3ItemCategory.MISC),
- ("Giant's Coal", 0x40000839, DS3ItemCategory.MISC),
- ("Profaned Coal", 0x4000083A, DS3ItemCategory.MISC),
- ("Mortician's Ashes", 0x4000083B, DS3ItemCategory.MISC),
- ("Dreamchaser's Ashes", 0x4000083C, DS3ItemCategory.MISC),
- ("Paladin's Ashes", 0x4000083D, DS3ItemCategory.MISC),
- ("Grave Warden's Ashes", 0x4000083E, DS3ItemCategory.MISC),
- ("Greirat's Ashes", 0x4000083F, DS3ItemCategory.MISC),
- ("Orbeck's Ashes", 0x40000840, DS3ItemCategory.MISC),
- ("Cornyx's Ashes", 0x40000841, DS3ItemCategory.MISC),
- ("Karla's Ashes", 0x40000842, DS3ItemCategory.MISC),
- ("Irina's Ashes", 0x40000843, DS3ItemCategory.MISC),
- ("Yuria's Ashes", 0x40000844, DS3ItemCategory.MISC),
- ("Basin of Vows", 0x40000845, DS3ItemCategory.KEY),
- ("Loretta's Bone", 0x40000846, DS3ItemCategory.KEY),
- ("Braille Divine Tome of Carim", 0x40000847, DS3ItemCategory.MISC),
- ("Braille Divine Tome of Lothric", 0x40000848, DS3ItemCategory.MISC),
- ("Cinders of a Lord - Abyss Watcher", 0x4000084B, DS3ItemCategory.KEY),
- ("Cinders of a Lord - Aldrich", 0x4000084C, DS3ItemCategory.KEY),
- ("Cinders of a Lord - Yhorm the Giant", 0x4000084D, DS3ItemCategory.KEY),
- ("Cinders of a Lord - Lothric Prince", 0x4000084E, DS3ItemCategory.KEY),
- ("Great Swamp Pyromancy Tome", 0x4000084F, DS3ItemCategory.MISC),
- ("Carthus Pyromancy Tome", 0x40000850, DS3ItemCategory.MISC),
- ("Izalith Pyromancy Tome", 0x40000851, DS3ItemCategory.MISC),
- ("Quelana Pyromancy Tome", 0x40000852, DS3ItemCategory.MISC),
- ("Grave Warden Pyromancy Tome", 0x40000853, DS3ItemCategory.MISC),
- ("Sage's Scroll", 0x40000854, DS3ItemCategory.MISC),
- ("Logan's Scroll", 0x40000855, DS3ItemCategory.MISC),
- ("Crystal Scroll", 0x40000856, DS3ItemCategory.MISC),
- ("Transposing Kiln", 0x40000857, DS3ItemCategory.MISC),
- ("Coiled Sword", 0x40000859, DS3ItemCategory.SKIP), # Useless
- ("Eyes of a Fire Keeper", 0x4000085A, DS3ItemCategory.KEY),
- ("Sword of Avowal", 0x4000085B, DS3ItemCategory.KEY),
- ("Golden Scroll", 0x4000085C, DS3ItemCategory.MISC),
- ("Estus Shard", 0x4000085D, DS3ItemCategory.MISC),
- ("Hawkwood's Swordgrass", 0x4000085E, DS3ItemCategory.SKIP),
- ("Undead Bone Shard", 0x4000085F, DS3ItemCategory.MISC),
- ("Deep Braille Divine Tome", 0x40000860, DS3ItemCategory.MISC),
- ("Londor Braille Divine Tome", 0x40000861, DS3ItemCategory.MISC),
- ("Excrement-covered Ashes", 0x40000862, DS3ItemCategory.MISC),
- ("Prisoner Chief's Ashes", 0x40000863, DS3ItemCategory.MISC),
- ("Xanthous Ashes", 0x40000864, DS3ItemCategory.MISC),
- ("Hollow's Ashes", 0x40000865, DS3ItemCategory.MISC),
- ("Patches' Ashes", 0x40000866, DS3ItemCategory.MISC),
- ("Dragon Chaser's Ashes", 0x40000867, DS3ItemCategory.MISC),
- ("Easterner's Ashes", 0x40000868, DS3ItemCategory.MISC),
+ DS3ItemData("White Sign Soapstone", 0x40000064, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Red Sign Soapstone", 0x40000066, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Red Eye Orb", 0x40000066, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Roster of Knights", 0x4000006C, DS3ItemCategory.UNIQUE, skip = True),
+ *DS3ItemData("Cracked Red Eye Orb", 0x4000006F, DS3ItemCategory.MISC, skip = True).counts([5]),
+ DS3ItemData("Black Eye Orb", 0x40000073, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Divine Blessing", 0x400000F0, DS3ItemCategory.MISC),
+ DS3ItemData("Hidden Blessing", 0x400000F1, DS3ItemCategory.MISC),
+ *DS3ItemData("Green Blossom", 0x40000104, DS3ItemCategory.MISC, filler = True).counts([2, 3, 4]),
+ *DS3ItemData("Budding Green Blossom", 0x40000106, DS3ItemCategory.MISC).counts([2, 3]),
+ *DS3ItemData("Bloodred Moss Clump", 0x4000010E, DS3ItemCategory.MISC, filler = True).counts([3]),
+ *DS3ItemData("Purple Moss Clump", 0x4000010F, DS3ItemCategory.MISC, filler = True).counts([2, 3, 4]),
+ *DS3ItemData("Blooming Purple Moss Clump", 0x40000110, DS3ItemCategory.MISC).counts([3]),
+ *DS3ItemData("Purging Stone", 0x40000112, DS3ItemCategory.MISC, skip = True).counts([2, 3]),
+ *DS3ItemData("Rime-blue Moss Clump", 0x40000114, DS3ItemCategory.MISC, filler = True).counts([2, 4]),
+ *DS3ItemData("Repair Powder", 0x40000118, DS3ItemCategory.MISC, filler = True).counts([2, 3, 4]),
+ *DS3ItemData("Kukri", 0x40000122, DS3ItemCategory.MISC).counts([8, 9]),
+ DS3ItemData("Kukri x5", 0x40000122, DS3ItemCategory.MISC, count = 5, filler = True),
+ *DS3ItemData("Firebomb", 0x40000124, DS3ItemCategory.MISC).counts([3, 5, 6]),
+ DS3ItemData("Firebomb x2", 0x40000124, DS3ItemCategory.MISC, count = 2, filler = True),
+ *DS3ItemData("Dung Pie", 0x40000125, DS3ItemCategory.MISC).counts([2, 4]),
+ DS3ItemData("Dung Pie x3", 0x40000125, DS3ItemCategory.MISC, count = 3, filler = True),
+ *DS3ItemData("Alluring Skull", 0x40000126, DS3ItemCategory.MISC, filler = True).counts([2, 3]),
+ *DS3ItemData("Undead Hunter Charm", 0x40000128, DS3ItemCategory.MISC).counts([2, 3]),
+ *DS3ItemData("Black Firebomb", 0x40000129, DS3ItemCategory.MISC, filler = True).counts([2, 3, 4]),
+ DS3ItemData("Rope Firebomb", 0x4000012B, DS3ItemCategory.MISC),
+ *DS3ItemData("Lightning Urn", 0x4000012C, DS3ItemCategory.MISC, filler = True).counts([3, 4, 6]),
+ DS3ItemData("Rope Black Firebomb", 0x4000012E, DS3ItemCategory.MISC),
+ *DS3ItemData("Stalk Dung Pie", 0x4000012F, DS3ItemCategory.MISC).counts([6]),
+ *DS3ItemData("Duel Charm", 0x40000130, DS3ItemCategory.MISC).counts([3]),
+ *DS3ItemData("Throwing Knife", 0x40000136, DS3ItemCategory.MISC).counts([6, 8]),
+ DS3ItemData("Throwing Knife x5", 0x40000136, DS3ItemCategory.MISC, count = 5, filler = True),
+ DS3ItemData("Poison Throwing Knife", 0x40000137, DS3ItemCategory.MISC),
+ *DS3ItemData("Charcoal Pine Resin", 0x4000014A, DS3ItemCategory.MISC, filler = True).counts([2]),
+ *DS3ItemData("Gold Pine Resin", 0x4000014B, DS3ItemCategory.MISC, filler = True).counts([2]),
+ *DS3ItemData("Human Pine Resin", 0x4000014E, DS3ItemCategory.MISC, filler = True).counts([2, 4]),
+ *DS3ItemData("Carthus Rouge", 0x4000014F, DS3ItemCategory.MISC, filler = True).counts([2, 3]),
+ *DS3ItemData("Pale Pine Resin", 0x40000150, DS3ItemCategory.MISC, filler = True).counts([2]),
+ *DS3ItemData("Charcoal Pine Bundle", 0x40000154, DS3ItemCategory.MISC).counts([2]),
+ *DS3ItemData("Gold Pine Bundle", 0x40000155, DS3ItemCategory.MISC).counts([6]),
+ *DS3ItemData("Rotten Pine Resin", 0x40000157, DS3ItemCategory.MISC).counts([2, 4]),
+ *DS3ItemData("Homeward Bone", 0x4000015E, DS3ItemCategory.MISC, filler = True).counts([2, 3, 6]),
+ DS3ItemData("Coiled Sword Fragment", 0x4000015F, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression), # Crow trade
+ DS3ItemData("Wolf's Blood Swordgrass", 0x4000016E, DS3ItemCategory.MISC, skip = True),
+ DS3ItemData("Human Dregs", 0x4000016F, DS3ItemCategory.MISC, skip = True),
+ DS3ItemData("Forked Pale Tongue", 0x40000170, DS3ItemCategory.MISC, skip = True),
+ DS3ItemData("Proof of a Concord Well Kept", 0x40000171, DS3ItemCategory.MISC, skip = True),
+ *DS3ItemData("Prism Stone", 0x40000172, DS3ItemCategory.MISC, skip = True).counts([4, 6, 10]),
+ DS3ItemData("Binoculars", 0x40000173, DS3ItemCategory.MISC),
+ DS3ItemData("Proof of a Concord Kept", 0x40000174, DS3ItemCategory.MISC, skip = True),
+ # One is needed for Leonhard's quest, others are useful for restatting.
+ DS3ItemData("Pale Tongue", 0x40000175, DS3ItemCategory.MISC,
+ classification = ItemClassification.progression),
+ DS3ItemData("Vertebra Shackle", 0x40000176, DS3ItemCategory.MISC,
+ classification = ItemClassification.progression), # Crow trade
+ DS3ItemData("Sunlight Medal", 0x40000177, DS3ItemCategory.MISC, skip = True),
+ DS3ItemData("Dragon Head Stone", 0x40000179, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Dragon Torso Stone", 0x4000017A, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Rubbish", 0x4000017C, DS3ItemCategory.MISC, skip = True),
+ DS3ItemData("Dried Finger", 0x40000181, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Twinkling Dragon Head Stone", 0x40000183, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Twinkling Dragon Torso Stone", 0x40000184, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Fire Keeper Soul", 0x40000186, DS3ItemCategory.UNIQUE),
+ # Allow souls up to 2k in value to be used as filler
+ DS3ItemData("Fading Soul", 0x40000190, DS3ItemCategory.SOUL, souls = 50),
+ DS3ItemData("Soul of a Deserted Corpse", 0x40000191, DS3ItemCategory.SOUL, souls = 200),
+ DS3ItemData("Large Soul of a Deserted Corpse", 0x40000192, DS3ItemCategory.SOUL, souls = 400),
+ DS3ItemData("Soul of an Unknown Traveler", 0x40000193, DS3ItemCategory.SOUL, souls = 800),
+ DS3ItemData("Large Soul of an Unknown Traveler", 0x40000194, DS3ItemCategory.SOUL, souls = 1000),
+ DS3ItemData("Soul of a Nameless Soldier", 0x40000195, DS3ItemCategory.SOUL, souls = 2000),
+ DS3ItemData("Large Soul of a Nameless Soldier", 0x40000196, DS3ItemCategory.SOUL, souls = 3000),
+ DS3ItemData("Soul of a Weary Warrior", 0x40000197, DS3ItemCategory.SOUL, souls = 5000),
+ DS3ItemData("Large Soul of a Weary Warrior", 0x40000198, DS3ItemCategory.SOUL, souls = 8000),
+ DS3ItemData("Soul of a Crestfallen Knight", 0x40000199, DS3ItemCategory.SOUL, souls = 10000),
+ DS3ItemData("Large Soul of a Crestfallen Knight", 0x4000019A, DS3ItemCategory.SOUL, souls = 20000),
+ DS3ItemData("Soul of a Proud Paladin", 0x4000019B, DS3ItemCategory.SOUL, souls = 500),
+ DS3ItemData("Large Soul of a Proud Paladin", 0x4000019C, DS3ItemCategory.SOUL, souls = 1000),
+ DS3ItemData("Soul of an Intrepid Hero", 0x4000019D, DS3ItemCategory.SOUL, souls = 2000),
+ DS3ItemData("Large Soul of an Intrepid Hero", 0x4000019E, DS3ItemCategory.SOUL, souls = 2500),
+ DS3ItemData("Soul of a Seasoned Warrior", 0x4000019F, DS3ItemCategory.SOUL, souls = 5000),
+ DS3ItemData("Large Soul of a Seasoned Warrior", 0x400001A0, DS3ItemCategory.SOUL, souls = 7500),
+ DS3ItemData("Soul of an Old Hand", 0x400001A1, DS3ItemCategory.SOUL, souls = 12500),
+ DS3ItemData("Soul of a Venerable Old Hand", 0x400001A2, DS3ItemCategory.SOUL, souls = 20000),
+ DS3ItemData("Soul of a Champion", 0x400001A3, DS3ItemCategory.SOUL, souls = 25000),
+ DS3ItemData("Soul of a Great Champion", 0x400001A4, DS3ItemCategory.SOUL, souls = 50000),
+ DS3ItemData("Seed of a Giant Tree", 0x400001B8, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression, inject = True), # Crow trade
+ *DS3ItemData("Mossfruit", 0x400001C4, DS3ItemCategory.MISC, filler = True).counts([2]),
+ DS3ItemData("Young White Branch", 0x400001C6, DS3ItemCategory.MISC),
+ *DS3ItemData("Rusted Coin", 0x400001C7, DS3ItemCategory.MISC, filler = True).counts([2]),
+ DS3ItemData("Siegbräu", 0x400001C8, DS3ItemCategory.MISC,
+ classification = ItemClassification.progression), # Crow trade
+ *DS3ItemData("Rusted Gold Coin", 0x400001C9, DS3ItemCategory.MISC, filler = True).counts([2, 3]),
+ *DS3ItemData("Blue Bug Pellet", 0x400001CA, DS3ItemCategory.MISC, filler = True).counts([2]),
+ *DS3ItemData("Red Bug Pellet", 0x400001CB, DS3ItemCategory.MISC, filler = True).counts([2, 3]),
+ *DS3ItemData("Yellow Bug Pellet", 0x400001CC, DS3ItemCategory.MISC, filler = True).counts([2, 3]),
+ *DS3ItemData("Black Bug Pellet", 0x400001CD, DS3ItemCategory.MISC, filler = True).counts([2, 3]),
+ DS3ItemData("Young White Branch", 0x400001CF, DS3ItemCategory.MISC, skip = True),
+ DS3ItemData("Dark Sigil", 0x400001EA, DS3ItemCategory.MISC, skip = True),
+ *DS3ItemData("Ember", 0x400001F4, DS3ItemCategory.MISC, filler = True).counts([2]),
+ DS3ItemData("Hello Carving", 0x40000208, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Thank you Carving", 0x40000209, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Very good! Carving", 0x4000020A, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("I'm sorry Carving", 0x4000020B, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Help me! Carving", 0x4000020C, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Soul of Champion Gundyr", 0x400002C8, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of the Dancer", 0x400002CA, DS3ItemCategory.BOSS, souls = 10000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of a Crystal Sage", 0x400002CB, DS3ItemCategory.BOSS, souls = 3000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of the Blood of the Wolf", 0x400002CD, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of Consumed Oceiros", 0x400002CE, DS3ItemCategory.BOSS, souls = 12000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of Boreal Valley Vordt", 0x400002CF, DS3ItemCategory.BOSS, souls = 2000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of the Old Demon King", 0x400002D0, DS3ItemCategory.BOSS, souls = 10000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of Dragonslayer Armour", 0x400002D1, DS3ItemCategory.BOSS, souls = 15000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of the Nameless King", 0x400002D2, DS3ItemCategory.BOSS, souls = 16000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of Pontiff Sulyvahn", 0x400002D4, DS3ItemCategory.BOSS, souls = 12000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of Aldrich", 0x400002D5, DS3ItemCategory.BOSS, souls = 15000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of High Lord Wolnir", 0x400002D6, DS3ItemCategory.BOSS, souls = 10000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of the Rotted Greatwood", 0x400002D7, DS3ItemCategory.BOSS, souls = 3000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of Rosaria", 0x400002D8, DS3ItemCategory.BOSS, souls = 5000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of the Deacons of the Deep", 0x400002D9, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of the Twin Princes", 0x400002DB, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of Yhorm the Giant", 0x400002DC, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of the Lords", 0x400002DD, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of a Demon", 0x400002E3, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of a Stray Demon", 0x400002E7, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ *DS3ItemData("Titanite Shard", 0x400003E8, DS3ItemCategory.UPGRADE).counts([2]),
+ *DS3ItemData("Large Titanite Shard", 0x400003E9, DS3ItemCategory.UPGRADE).counts([2, 3]),
+ *DS3ItemData("Titanite Chunk", 0x400003EA, DS3ItemCategory.UPGRADE).counts([2, 6]),
+ DS3ItemData("Titanite Slab", 0x400003EB, DS3ItemCategory.UPGRADE,
+ classification = ItemClassification.useful),
+ *DS3ItemData("Titanite Scale", 0x400003FC, DS3ItemCategory.UPGRADE).counts([2, 3]),
+ *DS3ItemData("Twinkling Titanite", 0x40000406, DS3ItemCategory.UPGRADE).counts([2, 3]),
+ DS3ItemData("Heavy Gem", 0x4000044C, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Sharp Gem", 0x40000456, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Refined Gem", 0x40000460, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Crystal Gem", 0x4000046A, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Simple Gem", 0x40000474, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Fire Gem", 0x4000047E, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Chaos Gem", 0x40000488, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Lightning Gem", 0x40000492, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Deep Gem", 0x4000049C, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Dark Gem", 0x400004A6, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Poison Gem", 0x400004B0, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Blood Gem", 0x400004BA, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Raw Gem", 0x400004C4, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Blessed Gem", 0x400004CE, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Hollow Gem", 0x400004D8, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Shriving Stone", 0x400004E2, DS3ItemCategory.UPGRADE),
+ DS3ItemData("Lift Chamber Key", 0x400007D1, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Small Doll", 0x400007D5, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Jailbreaker's Key", 0x400007D7, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Jailer's Key Ring", 0x400007D8, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Grave Key", 0x400007D9, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Cell Key", 0x400007DA, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Dungeon Ground Floor Key", 0x400007DB, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Old Cell Key", 0x400007DC, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Grand Archives Key", 0x400007DE, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Tower Key", 0x400007DF, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Small Lothric Banner", 0x40000836, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Farron Coal", 0x40000837, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.useful),
+ DS3ItemData("Sage's Coal", 0x40000838, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.useful),
+ DS3ItemData("Giant's Coal", 0x40000839, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.useful),
+ DS3ItemData("Profaned Coal", 0x4000083A, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.useful),
+ DS3ItemData("Mortician's Ashes", 0x4000083B, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Dreamchaser's Ashes", 0x4000083C, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Paladin's Ashes", 0x4000083D, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Grave Warden's Ashes", 0x4000083E, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Greirat's Ashes", 0x4000083F, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Orbeck's Ashes", 0x40000840, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Cornyx's Ashes", 0x40000841, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Karla's Ashes", 0x40000842, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Irina's Ashes", 0x40000843, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Yuria's Ashes", 0x40000844, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Basin of Vows", 0x40000845, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Loretta's Bone", 0x40000846, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Braille Divine Tome of Carim", 0x40000847, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Braille Divine Tome of Lothric", 0x40000848, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Cinders of a Lord - Abyss Watcher", 0x4000084B, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Cinders of a Lord - Aldrich", 0x4000084C, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Cinders of a Lord - Yhorm the Giant", 0x4000084D, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Cinders of a Lord - Lothric Prince", 0x4000084E, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Great Swamp Pyromancy Tome", 0x4000084F, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Carthus Pyromancy Tome", 0x40000850, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Izalith Pyromancy Tome", 0x40000851, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Quelana Pyromancy Tome", 0x40000852, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Grave Warden Pyromancy Tome", 0x40000853, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Sage's Scroll", 0x40000854, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Logan's Scroll", 0x40000855, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Crystal Scroll", 0x40000856, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Transposing Kiln", 0x40000857, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Coiled Sword", 0x40000859, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Eyes of a Fire Keeper", 0x4000085A, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.useful), # Allow players to do any ending
+ DS3ItemData("Sword of Avowal", 0x4000085B, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.useful),
+ DS3ItemData("Golden Scroll", 0x4000085C, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Estus Shard", 0x4000085D, DS3ItemCategory.HEALING,
+ classification = ItemClassification.useful),
+ DS3ItemData("Hawkwood's Swordgrass", 0x4000085E, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Undead Bone Shard", 0x4000085F, DS3ItemCategory.HEALING,
+ classification = ItemClassification.useful),
+ DS3ItemData("Deep Braille Divine Tome", 0x40000860, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Londor Braille Divine Tome", 0x40000861, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Excrement-covered Ashes", 0x40000862, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.useful),
+ DS3ItemData("Prisoner Chief's Ashes", 0x40000863, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Xanthous Ashes", 0x40000864, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Hollow's Ashes", 0x40000865, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Patches' Ashes", 0x40000866, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Dragon Chaser's Ashes", 0x40000867, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Easterner's Ashes", 0x40000868, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+
+ # Fake item for controlling access to Archdragon Peak. The real drop isn't actually an item as
+ # such, so we have to inject this because there's no slot for it to come from.
+ DS3ItemData("Path of the Dragon", 0x40002346, DS3ItemCategory.UNIQUE,
+ inject = True, classification = ItemClassification.progression),
# Spells
- ("Farron Dart", 0x40124F80, DS3ItemCategory.SPELL),
- ("Great Farron Dart", 0x40127690, DS3ItemCategory.SPELL),
- ("Soul Arrow", 0x4013D620, DS3ItemCategory.SPELL),
- ("Great Soul Arrow", 0x4013DA08, DS3ItemCategory.SPELL),
- ("Heavy Soul Arrow", 0x4013DDF0, DS3ItemCategory.SPELL),
- ("Great Heavy Soul Arrow", 0x4013E1D8, DS3ItemCategory.SPELL),
- ("Homing Soulmass", 0x4013E5C0, DS3ItemCategory.SPELL),
- ("Homing Crystal Soulmass", 0x4013E9A8, DS3ItemCategory.SPELL),
- ("Soul Spear", 0x4013ED90, DS3ItemCategory.SPELL),
- ("Crystal Soul Spear", 0x4013F178, DS3ItemCategory.SPELL),
- ("Deep Soul", 0x4013F560, DS3ItemCategory.SPELL),
- ("Great Deep Soul", 0x4013F948, DS3ItemCategory.SPELL),
- ("Magic Weapon", 0x4013FD30, DS3ItemCategory.SPELL),
- ("Great Magic Weapon", 0x40140118, DS3ItemCategory.SPELL),
- ("Crystal Magic Weapon", 0x40140500, DS3ItemCategory.SPELL),
- ("Magic Shield", 0x40144B50, DS3ItemCategory.SPELL),
- ("Great Magic Shield", 0x40144F38, DS3ItemCategory.SPELL),
- ("Hidden Weapon", 0x40147260, DS3ItemCategory.SPELL),
- ("Hidden Body", 0x40147648, DS3ItemCategory.SPELL),
- ("Cast Light", 0x40149970, DS3ItemCategory.SPELL),
- ("Repair", 0x4014A528, DS3ItemCategory.SPELL),
- ("Spook", 0x4014A910, DS3ItemCategory.SPELL),
- ("Chameleon", 0x4014ACF8, DS3ItemCategory.SPELL),
- ("Aural Decoy", 0x4014B0E0, DS3ItemCategory.SPELL),
- ("White Dragon Breath", 0x4014E790, DS3ItemCategory.SPELL),
- ("Farron Hail", 0x4014EF60, DS3ItemCategory.SPELL),
- ("Crystal Hail", 0x4014F348, DS3ItemCategory.SPELL),
- ("Soul Greatsword", 0x4014F730, DS3ItemCategory.SPELL),
- ("Farron Flashsword", 0x4014FB18, DS3ItemCategory.SPELL),
- ("Affinity", 0x401875B8, DS3ItemCategory.SPELL),
- ("Dark Edge", 0x40189CC8, DS3ItemCategory.SPELL),
- ("Soul Stream", 0x4018B820, DS3ItemCategory.SPELL),
- ("Twisted Wall of Light", 0x40193138, DS3ItemCategory.SPELL),
- ("Pestilent Mist", 0x401A8CE0, DS3ItemCategory.SPELL), # Originally called "Pestilent Mercury" pre 1.15
- ("Fireball", 0x40249F00, DS3ItemCategory.SPELL),
- ("Fire Orb", 0x4024A6D0, DS3ItemCategory.SPELL),
- ("Firestorm", 0x4024AAB8, DS3ItemCategory.SPELL),
- ("Fire Surge", 0x4024B288, DS3ItemCategory.SPELL),
- ("Black Serpent", 0x4024BA58, DS3ItemCategory.SPELL),
- ("Combustion", 0x4024C610, DS3ItemCategory.SPELL),
- ("Great Combustion", 0x4024C9F8, DS3ItemCategory.SPELL),
- ("Poison Mist", 0x4024ED20, DS3ItemCategory.SPELL),
- ("Toxic Mist", 0x4024F108, DS3ItemCategory.SPELL),
- ("Acid Surge", 0x4024F4F0, DS3ItemCategory.SPELL),
- ("Iron Flesh", 0x40251430, DS3ItemCategory.SPELL),
- ("Flash Sweat", 0x40251818, DS3ItemCategory.SPELL),
- ("Carthus Flame Arc", 0x402527B8, DS3ItemCategory.SPELL),
- ("Rapport", 0x40252BA0, DS3ItemCategory.SPELL),
- ("Power Within", 0x40253B40, DS3ItemCategory.SPELL),
- ("Great Chaos Fire Orb", 0x40256250, DS3ItemCategory.SPELL),
- ("Chaos Storm", 0x40256638, DS3ItemCategory.SPELL),
- ("Fire Whip", 0x40256A20, DS3ItemCategory.SPELL),
- ("Black Flame", 0x40256E08, DS3ItemCategory.SPELL),
- ("Profaned Flame", 0x402575D8, DS3ItemCategory.SPELL),
- ("Chaos Bed Vestiges", 0x402579C0, DS3ItemCategory.SPELL),
- ("Warmth", 0x4025B070, DS3ItemCategory.SPELL),
- ("Profuse Sweat", 0x402717D0, DS3ItemCategory.SPELL),
- ("Black Fire Orb", 0x4027D350, DS3ItemCategory.SPELL),
- ("Bursting Fireball", 0x4027FA60, DS3ItemCategory.SPELL),
- ("Boulder Heave", 0x40282170, DS3ItemCategory.SPELL),
- ("Sacred Flame", 0x40284880, DS3ItemCategory.SPELL),
- ("Carthus Beacon", 0x40286F90, DS3ItemCategory.SPELL),
- ("Heal Aid", 0x403540D0, DS3ItemCategory.SPELL),
- ("Heal", 0x403567E0, DS3ItemCategory.SPELL),
- ("Med Heal", 0x40356BC8, DS3ItemCategory.SPELL),
- ("Great Heal", 0x40356FB0, DS3ItemCategory.SPELL),
- ("Soothing Sunlight", 0x40357398, DS3ItemCategory.SPELL),
- ("Replenishment", 0x40357780, DS3ItemCategory.SPELL),
- ("Bountiful Sunlight", 0x40357B68, DS3ItemCategory.SPELL),
- ("Bountiful Light", 0x40358338, DS3ItemCategory.SPELL),
- ("Caressing Tears", 0x40358720, DS3ItemCategory.SPELL),
- ("Tears of Denial", 0x4035B600, DS3ItemCategory.SPELL),
- ("Homeward", 0x4035B9E8, DS3ItemCategory.SPELL),
- ("Force", 0x4035DD10, DS3ItemCategory.SPELL),
- ("Wrath of the Gods", 0x4035E0F8, DS3ItemCategory.SPELL),
- ("Emit Force", 0x4035E4E0, DS3ItemCategory.SPELL),
- ("Seek Guidance", 0x40360420, DS3ItemCategory.SPELL),
- ("Lightning Spear", 0x40362B30, DS3ItemCategory.SPELL),
- ("Great Lightning Spear", 0x40362F18, DS3ItemCategory.SPELL),
- ("Sunlight Spear", 0x40363300, DS3ItemCategory.SPELL),
- ("Lightning Storm", 0x403636E8, DS3ItemCategory.SPELL),
- ("Gnaw", 0x40363AD0, DS3ItemCategory.SPELL),
- ("Dorhys' Gnawing", 0x40363EB8, DS3ItemCategory.SPELL),
- ("Magic Barrier", 0x40365240, DS3ItemCategory.SPELL),
- ("Great Magic Barrier", 0x40365628, DS3ItemCategory.SPELL),
- ("Sacred Oath", 0x40365DF8, DS3ItemCategory.SPELL),
- ("Vow of Silence", 0x4036A448, DS3ItemCategory.SPELL),
- ("Lightning Blade", 0x4036C770, DS3ItemCategory.SPELL),
- ("Darkmoon Blade", 0x4036CB58, DS3ItemCategory.SPELL),
- ("Dark Blade", 0x40378AC0, DS3ItemCategory.SPELL),
- ("Dead Again", 0x40387520, DS3ItemCategory.SPELL),
- ("Lightning Stake", 0x40389C30, DS3ItemCategory.SPELL),
- ("Divine Pillars of Light", 0x4038C340, DS3ItemCategory.SPELL),
- ("Lifehunt Scythe", 0x4038EA50, DS3ItemCategory.SPELL),
- ("Blessed Weapon", 0x40395F80, DS3ItemCategory.SPELL),
- ("Deep Protection", 0x40398690, DS3ItemCategory.SPELL),
- ("Atonement", 0x4039ADA0, DS3ItemCategory.SPELL),
-]]
-
-_dlc_items = [DS3ItemData(row[0], row[1], True, row[2]) for row in [
+ DS3ItemData("Farron Dart", 0x40124F80, DS3ItemCategory.SPELL),
+ DS3ItemData("Great Farron Dart", 0x40127690, DS3ItemCategory.SPELL),
+ DS3ItemData("Soul Arrow", 0x4013D620, DS3ItemCategory.SPELL),
+ DS3ItemData("Great Soul Arrow", 0x4013DA08, DS3ItemCategory.SPELL),
+ DS3ItemData("Heavy Soul Arrow", 0x4013DDF0, DS3ItemCategory.SPELL),
+ DS3ItemData("Great Heavy Soul Arrow", 0x4013E1D8, DS3ItemCategory.SPELL),
+ DS3ItemData("Homing Soulmass", 0x4013E5C0, DS3ItemCategory.SPELL),
+ DS3ItemData("Homing Crystal Soulmass", 0x4013E9A8, DS3ItemCategory.SPELL),
+ DS3ItemData("Soul Spear", 0x4013ED90, DS3ItemCategory.SPELL),
+ DS3ItemData("Crystal Soul Spear", 0x4013F178, DS3ItemCategory.SPELL),
+ DS3ItemData("Deep Soul", 0x4013F560, DS3ItemCategory.SPELL),
+ DS3ItemData("Great Deep Soul", 0x4013F948, DS3ItemCategory.SPELL,
+ inject = True), # Covenant reward
+ DS3ItemData("Magic Weapon", 0x4013FD30, DS3ItemCategory.SPELL),
+ DS3ItemData("Great Magic Weapon", 0x40140118, DS3ItemCategory.SPELL),
+ DS3ItemData("Crystal Magic Weapon", 0x40140500, DS3ItemCategory.SPELL),
+ DS3ItemData("Magic Shield", 0x40144B50, DS3ItemCategory.SPELL),
+ DS3ItemData("Great Magic Shield", 0x40144F38, DS3ItemCategory.SPELL),
+ DS3ItemData("Hidden Weapon", 0x40147260, DS3ItemCategory.SPELL),
+ DS3ItemData("Hidden Body", 0x40147648, DS3ItemCategory.SPELL,
+ classification = ItemClassification.useful),
+ DS3ItemData("Cast Light", 0x40149970, DS3ItemCategory.SPELL),
+ DS3ItemData("Repair", 0x4014A528, DS3ItemCategory.SPELL),
+ DS3ItemData("Spook", 0x4014A910, DS3ItemCategory.SPELL,
+ classification = ItemClassification.useful),
+ DS3ItemData("Chameleon", 0x4014ACF8, DS3ItemCategory.SPELL,
+ classification = ItemClassification.progression),
+ DS3ItemData("Aural Decoy", 0x4014B0E0, DS3ItemCategory.SPELL),
+ DS3ItemData("White Dragon Breath", 0x4014E790, DS3ItemCategory.SPELL),
+ DS3ItemData("Farron Hail", 0x4014EF60, DS3ItemCategory.SPELL),
+ DS3ItemData("Crystal Hail", 0x4014F348, DS3ItemCategory.SPELL),
+ DS3ItemData("Soul Greatsword", 0x4014F730, DS3ItemCategory.SPELL),
+ DS3ItemData("Farron Flashsword", 0x4014FB18, DS3ItemCategory.SPELL),
+ DS3ItemData("Affinity", 0x401875B8, DS3ItemCategory.SPELL),
+ DS3ItemData("Dark Edge", 0x40189CC8, DS3ItemCategory.SPELL),
+ DS3ItemData("Soul Stream", 0x4018B820, DS3ItemCategory.SPELL),
+ DS3ItemData("Twisted Wall of Light", 0x40193138, DS3ItemCategory.SPELL),
+ DS3ItemData("Pestilent Mist", 0x401A8CE0, DS3ItemCategory.SPELL,
+ classification = ItemClassification.useful), # Originally called "Pestilent Mercury" pre 1.15
+ DS3ItemData("Fireball", 0x40249F00, DS3ItemCategory.SPELL),
+ DS3ItemData("Fire Orb", 0x4024A6D0, DS3ItemCategory.SPELL),
+ DS3ItemData("Firestorm", 0x4024AAB8, DS3ItemCategory.SPELL),
+ DS3ItemData("Fire Surge", 0x4024B288, DS3ItemCategory.SPELL),
+ DS3ItemData("Black Serpent", 0x4024BA58, DS3ItemCategory.SPELL),
+ DS3ItemData("Combustion", 0x4024C610, DS3ItemCategory.SPELL),
+ DS3ItemData("Great Combustion", 0x4024C9F8, DS3ItemCategory.SPELL),
+ DS3ItemData("Poison Mist", 0x4024ED20, DS3ItemCategory.SPELL),
+ DS3ItemData("Toxic Mist", 0x4024F108, DS3ItemCategory.SPELL),
+ DS3ItemData("Acid Surge", 0x4024F4F0, DS3ItemCategory.SPELL),
+ DS3ItemData("Iron Flesh", 0x40251430, DS3ItemCategory.SPELL),
+ DS3ItemData("Flash Sweat", 0x40251818, DS3ItemCategory.SPELL),
+ DS3ItemData("Carthus Flame Arc", 0x402527B8, DS3ItemCategory.SPELL),
+ DS3ItemData("Rapport", 0x40252BA0, DS3ItemCategory.SPELL,
+ classification = ItemClassification.useful),
+ DS3ItemData("Power Within", 0x40253B40, DS3ItemCategory.SPELL,
+ classification = ItemClassification.useful),
+ DS3ItemData("Great Chaos Fire Orb", 0x40256250, DS3ItemCategory.SPELL),
+ DS3ItemData("Chaos Storm", 0x40256638, DS3ItemCategory.SPELL),
+ DS3ItemData("Fire Whip", 0x40256A20, DS3ItemCategory.SPELL),
+ DS3ItemData("Black Flame", 0x40256E08, DS3ItemCategory.SPELL),
+ DS3ItemData("Profaned Flame", 0x402575D8, DS3ItemCategory.SPELL),
+ DS3ItemData("Chaos Bed Vestiges", 0x402579C0, DS3ItemCategory.SPELL),
+ DS3ItemData("Warmth", 0x4025B070, DS3ItemCategory.SPELL,
+ inject = True), # Covenant reward
+ DS3ItemData("Profuse Sweat", 0x402717D0, DS3ItemCategory.SPELL),
+ DS3ItemData("Black Fire Orb", 0x4027D350, DS3ItemCategory.SPELL),
+ DS3ItemData("Bursting Fireball", 0x4027FA60, DS3ItemCategory.SPELL),
+ DS3ItemData("Boulder Heave", 0x40282170, DS3ItemCategory.SPELL),
+ DS3ItemData("Sacred Flame", 0x40284880, DS3ItemCategory.SPELL),
+ DS3ItemData("Carthus Beacon", 0x40286F90, DS3ItemCategory.SPELL),
+ DS3ItemData("Heal Aid", 0x403540D0, DS3ItemCategory.SPELL),
+ DS3ItemData("Heal", 0x403567E0, DS3ItemCategory.SPELL),
+ DS3ItemData("Med Heal", 0x40356BC8, DS3ItemCategory.SPELL,
+ classification = ItemClassification.useful),
+ DS3ItemData("Great Heal", 0x40356FB0, DS3ItemCategory.SPELL),
+ DS3ItemData("Soothing Sunlight", 0x40357398, DS3ItemCategory.SPELL),
+ DS3ItemData("Replenishment", 0x40357780, DS3ItemCategory.SPELL),
+ DS3ItemData("Bountiful Sunlight", 0x40357B68, DS3ItemCategory.SPELL),
+ DS3ItemData("Bountiful Light", 0x40358338, DS3ItemCategory.SPELL),
+ DS3ItemData("Caressing Tears", 0x40358720, DS3ItemCategory.SPELL),
+ DS3ItemData("Tears of Denial", 0x4035B600, DS3ItemCategory.SPELL,
+ classification = ItemClassification.useful),
+ DS3ItemData("Homeward", 0x4035B9E8, DS3ItemCategory.SPELL,
+ classification = ItemClassification.useful),
+ DS3ItemData("Force", 0x4035DD10, DS3ItemCategory.SPELL),
+ DS3ItemData("Wrath of the Gods", 0x4035E0F8, DS3ItemCategory.SPELL),
+ DS3ItemData("Emit Force", 0x4035E4E0, DS3ItemCategory.SPELL),
+ DS3ItemData("Seek Guidance", 0x40360420, DS3ItemCategory.SPELL),
+ DS3ItemData("Lightning Spear", 0x40362B30, DS3ItemCategory.SPELL),
+ DS3ItemData("Great Lightning Spear", 0x40362F18, DS3ItemCategory.SPELL,
+ inject = True), # Covenant reward
+ DS3ItemData("Sunlight Spear", 0x40363300, DS3ItemCategory.SPELL),
+ DS3ItemData("Lightning Storm", 0x403636E8, DS3ItemCategory.SPELL),
+ DS3ItemData("Gnaw", 0x40363AD0, DS3ItemCategory.SPELL),
+ DS3ItemData("Dorhys' Gnawing", 0x40363EB8, DS3ItemCategory.SPELL),
+ DS3ItemData("Magic Barrier", 0x40365240, DS3ItemCategory.SPELL),
+ DS3ItemData("Great Magic Barrier", 0x40365628, DS3ItemCategory.SPELL),
+ DS3ItemData("Sacred Oath", 0x40365DF8, DS3ItemCategory.SPELL,
+ inject = True), # Covenant reward
+ DS3ItemData("Vow of Silence", 0x4036A448, DS3ItemCategory.SPELL),
+ DS3ItemData("Lightning Blade", 0x4036C770, DS3ItemCategory.SPELL),
+ DS3ItemData("Darkmoon Blade", 0x4036CB58, DS3ItemCategory.SPELL,
+ inject = True), # Covenant reward
+ DS3ItemData("Dark Blade", 0x40378AC0, DS3ItemCategory.SPELL),
+ DS3ItemData("Dead Again", 0x40387520, DS3ItemCategory.SPELL),
+ DS3ItemData("Lightning Stake", 0x40389C30, DS3ItemCategory.SPELL),
+ DS3ItemData("Divine Pillars of Light", 0x4038C340, DS3ItemCategory.SPELL),
+ DS3ItemData("Lifehunt Scythe", 0x4038EA50, DS3ItemCategory.SPELL),
+ DS3ItemData("Blessed Weapon", 0x40395F80, DS3ItemCategory.SPELL),
+ DS3ItemData("Deep Protection", 0x40398690, DS3ItemCategory.SPELL),
+ DS3ItemData("Atonement", 0x4039ADA0, DS3ItemCategory.SPELL),
+]
+
+_dlc_items = [
# Ammunition
- ("Millwood Greatarrow", 0x000623E0, DS3ItemCategory.SKIP),
+ *DS3ItemData("Millwood Greatarrow", 0x000623E0, DS3ItemCategory.MISC).counts([5]),
# Weapons
- ("Aquamarine Dagger", 0x00116520, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Murky Hand Scythe", 0x00118C30, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Onyx Blade", 0x00222E00, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Ringed Knight Straight Sword", 0x00225510, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Gael's Greatsword", 0x00227C20, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Follower Sabre", 0x003EDDC0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Demon's Scar", 0x003F04D0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Frayed Blade", 0x004D35A0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Herald Curved Greatsword", 0x006159E0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Millwood Battle Axe", 0x006D67D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Earth Seeker", 0x006D8EE0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Quakestone Hammer", 0x007ECCF0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Ledo's Great Hammer", 0x007EF400, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Follower Javelin", 0x008CD6B0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Ringed Knight Spear", 0x008CFDC0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Lothric War Banner", 0x008D24D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Crucifix of the Mad King", 0x008D4BE0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Splitleaf Greatsword", 0x009B2E90, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Friede's Great Scythe", 0x009B55A0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Crow Talons", 0x00A89C10, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Rose of Ariandel", 0x00B82C70, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Pyromancer's Parting Flame", 0x00CC9ED0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Murky Longstaff", 0x00CCC5E0, DS3ItemCategory.WEAPON_UPGRADE_10),
- ("Sacred Chime of Filianore", 0x00CCECF0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Preacher's Right Arm", 0x00CD1400, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("White Birch Bow", 0x00D77440, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Millwood Greatbow", 0x00D85EA0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Repeating Crossbow", 0x00D885B0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Giant Door Shield", 0x00F5F8C0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Valorheart", 0x00F646E0, DS3ItemCategory.WEAPON_UPGRADE_5),
- ("Crow Quills", 0x00F66DF0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
- ("Ringed Knight Paired Greatswords", 0x00F69500, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Aquamarine Dagger", 0x00116520, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Murky Hand Scythe", 0x00118C30, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Onyx Blade", 0x00222E00, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Ringed Knight Straight Sword", 0x00225510, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Gael's Greatsword", 0x00227C20, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Follower Sabre", 0x003EDDC0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Demon's Scar", 0x003F04D0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Frayed Blade", 0x004D35A0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Harald Curved Greatsword", 0x006159E0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Millwood Battle Axe", 0x006D67D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Earth Seeker", 0x006D8EE0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Quakestone Hammer", 0x007ECCF0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Ledo's Great Hammer", 0x007EF400, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Follower Javelin", 0x008CD6B0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Ringed Knight Spear", 0x008CFDC0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Lothric War Banner", 0x008D24D0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Crucifix of the Mad King", 0x008D4BE0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Splitleaf Greatsword", 0x009B2E90, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Friede's Great Scythe", 0x009B55A0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Crow Talons", 0x00A89C10, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Rose of Ariandel", 0x00B82C70, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Pyromancer's Parting Flame", 0x00CC9ED0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Murky Longstaff", 0x00CCC5E0, DS3ItemCategory.WEAPON_UPGRADE_10),
+ DS3ItemData("Sacred Chime of Filianore", 0x00CCECF0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Preacher's Right Arm", 0x00CD1400, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("White Birch Bow", 0x00D77440, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Millwood Greatbow", 0x00D85EA0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Repeating Crossbow", 0x00D885B0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Giant Door Shield", 0x00F5F8C0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Valorheart", 0x00F646E0, DS3ItemCategory.WEAPON_UPGRADE_5),
+ DS3ItemData("Crow Quills", 0x00F66DF0, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE),
+ DS3ItemData("Ringed Knight Paired Greatswords", 0x00F69500, DS3ItemCategory.WEAPON_UPGRADE_5),
# Shields
- ("Follower Shield", 0x0135C0E0, DS3ItemCategory.SHIELD_INFUSIBLE),
- ("Dragonhead Shield", 0x0135E7F0, DS3ItemCategory.SHIELD),
- ("Ethereal Oak Shield", 0x01450320, DS3ItemCategory.SHIELD),
- ("Dragonhead Greatshield", 0x01452A30, DS3ItemCategory.SHIELD),
- ("Follower Torch", 0x015F1AD0, DS3ItemCategory.SHIELD),
+ DS3ItemData("Follower Shield", 0x0135C0E0, DS3ItemCategory.SHIELD_INFUSIBLE),
+ DS3ItemData("Dragonhead Shield", 0x0135E7F0, DS3ItemCategory.SHIELD),
+ DS3ItemData("Ethereal Oak Shield", 0x01450320, DS3ItemCategory.SHIELD),
+ DS3ItemData("Dragonhead Greatshield", 0x01452A30, DS3ItemCategory.SHIELD),
+ DS3ItemData("Follower Torch", 0x015F1AD0, DS3ItemCategory.SHIELD),
# Armor
- ("Vilhelm's Helm", 0x11312D00, DS3ItemCategory.ARMOR),
- ("Vilhelm's Armor", 0x113130E8, DS3ItemCategory.ARMOR),
- ("Vilhelm's Gauntlets", 0x113134D0, DS3ItemCategory.ARMOR),
- ("Vilhelm's Leggings", 0x113138B8, DS3ItemCategory.ARMOR),
- ("Antiquated Plain Garb", 0x11B2E408, DS3ItemCategory.ARMOR),
- ("Violet Wrappings", 0x11B2E7F0, DS3ItemCategory.ARMOR),
- ("Loincloth 2", 0x11B2EBD8, DS3ItemCategory.ARMOR),
- ("Shira's Crown", 0x11C22260, DS3ItemCategory.ARMOR),
- ("Shira's Armor", 0x11C22648, DS3ItemCategory.ARMOR),
- ("Shira's Gloves", 0x11C22A30, DS3ItemCategory.ARMOR),
- ("Shira's Trousers", 0x11C22E18, DS3ItemCategory.ARMOR),
- ("Lapp's Helm", 0x11E84800, DS3ItemCategory.ARMOR),
- ("Lapp's Armor", 0x11E84BE8, DS3ItemCategory.ARMOR),
- ("Lapp's Gauntlets", 0x11E84FD0, DS3ItemCategory.ARMOR),
- ("Lapp's Leggings", 0x11E853B8, DS3ItemCategory.ARMOR),
- ("Slave Knight Hood", 0x134EDCE0, DS3ItemCategory.ARMOR),
- ("Slave Knight Armor", 0x134EE0C8, DS3ItemCategory.ARMOR),
- ("Slave Knight Gauntlets", 0x134EE4B0, DS3ItemCategory.ARMOR),
- ("Slave Knight Leggings", 0x134EE898, DS3ItemCategory.ARMOR),
- ("Ordained Hood", 0x135E1F20, DS3ItemCategory.ARMOR),
- ("Ordained Dress", 0x135E2308, DS3ItemCategory.ARMOR),
- ("Ordained Trousers", 0x135E2AD8, DS3ItemCategory.ARMOR),
- ("Follower Helm", 0x137CA3A0, DS3ItemCategory.ARMOR),
- ("Follower Armor", 0x137CA788, DS3ItemCategory.ARMOR),
- ("Follower Gloves", 0x137CAB70, DS3ItemCategory.ARMOR),
- ("Follower Boots", 0x137CAF58, DS3ItemCategory.ARMOR),
- ("Millwood Knight Helm", 0x139B2820, DS3ItemCategory.ARMOR),
- ("Millwood Knight Armor", 0x139B2C08, DS3ItemCategory.ARMOR),
- ("Millwood Knight Gauntlets", 0x139B2FF0, DS3ItemCategory.ARMOR),
- ("Millwood Knight Leggings", 0x139B33D8, DS3ItemCategory.ARMOR),
- ("Ringed Knight Hood", 0x13C8EEE0, DS3ItemCategory.ARMOR),
- ("Ringed Knight Armor", 0x13C8F2C8, DS3ItemCategory.ARMOR),
- ("Ringed Knight Gauntlets", 0x13C8F6B0, DS3ItemCategory.ARMOR),
- ("Ringed Knight Leggings", 0x13C8FA98, DS3ItemCategory.ARMOR),
- ("Harald Legion Armor", 0x13D83508, DS3ItemCategory.ARMOR),
- ("Harald Legion Gauntlets", 0x13D838F0, DS3ItemCategory.ARMOR),
- ("Harald Legion Leggings", 0x13D83CD8, DS3ItemCategory.ARMOR),
- ("Iron Dragonslayer Helm", 0x1405F7E0, DS3ItemCategory.ARMOR),
- ("Iron Dragonslayer Armor", 0x1405FBC8, DS3ItemCategory.ARMOR),
- ("Iron Dragonslayer Gauntlets", 0x1405FFB0, DS3ItemCategory.ARMOR),
- ("Iron Dragonslayer Leggings", 0x14060398, DS3ItemCategory.ARMOR),
- ("White Preacher Head", 0x14153A20, DS3ItemCategory.ARMOR),
- ("Ruin Sentinel Helm", 0x14CC5520, DS3ItemCategory.ARMOR),
- ("Ruin Sentinel Armor", 0x14CC5908, DS3ItemCategory.ARMOR),
- ("Ruin Sentinel Gauntlets", 0x14CC5CF0, DS3ItemCategory.ARMOR),
- ("Ruin Sentinel Leggings", 0x14CC60D8, DS3ItemCategory.ARMOR),
- ("Desert Pyromancer Hood", 0x14DB9760, DS3ItemCategory.ARMOR),
- ("Desert Pyromancer Garb", 0x14DB9B48, DS3ItemCategory.ARMOR),
- ("Desert Pyromancer Gloves", 0x14DB9F30, DS3ItemCategory.ARMOR),
- ("Desert Pyromancer Skirt", 0x14DBA318, DS3ItemCategory.ARMOR),
- ("Black Witch Hat", 0x14EAD9A0, DS3ItemCategory.ARMOR),
- ("Black Witch Garb", 0x14EADD88, DS3ItemCategory.ARMOR),
- ("Black Witch Wrappings", 0x14EAE170, DS3ItemCategory.ARMOR),
- ("Black Witch Trousers", 0x14EAE558, DS3ItemCategory.ARMOR),
- ("Black Witch Veil", 0x14FA1BE0, DS3ItemCategory.ARMOR),
- ("Blindfold Mask", 0x15095E20, DS3ItemCategory.ARMOR),
+ DS3ItemData("Vilhelm's Helm", 0x11312D00, DS3ItemCategory.ARMOR),
+ DS3ItemData("Vilhelm's Armor", 0x113130E8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Vilhelm's Gauntlets", 0x113134D0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Vilhelm's Leggings", 0x113138B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Antiquated Plain Garb", 0x11B2E408, DS3ItemCategory.ARMOR),
+ DS3ItemData("Violet Wrappings", 0x11B2E7F0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Loincloth 2", 0x11B2EBD8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Shira's Crown", 0x11C22260, DS3ItemCategory.ARMOR),
+ DS3ItemData("Shira's Armor", 0x11C22648, DS3ItemCategory.ARMOR),
+ DS3ItemData("Shira's Gloves", 0x11C22A30, DS3ItemCategory.ARMOR),
+ DS3ItemData("Shira's Trousers", 0x11C22E18, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lapp's Helm", 0x11E84800, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lapp's Armor", 0x11E84BE8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lapp's Gauntlets", 0x11E84FD0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Lapp's Leggings", 0x11E853B8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Slave Knight Hood", 0x134EDCE0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Slave Knight Armor", 0x134EE0C8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Slave Knight Gauntlets", 0x134EE4B0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Slave Knight Leggings", 0x134EE898, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ordained Hood", 0x135E1F20, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ordained Dress", 0x135E2308, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ordained Trousers", 0x135E2AD8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Follower Helm", 0x137CA3A0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Follower Armor", 0x137CA788, DS3ItemCategory.ARMOR),
+ DS3ItemData("Follower Gloves", 0x137CAB70, DS3ItemCategory.ARMOR),
+ DS3ItemData("Follower Boots", 0x137CAF58, DS3ItemCategory.ARMOR),
+ DS3ItemData("Millwood Knight Helm", 0x139B2820, DS3ItemCategory.ARMOR),
+ DS3ItemData("Millwood Knight Armor", 0x139B2C08, DS3ItemCategory.ARMOR),
+ DS3ItemData("Millwood Knight Gauntlets", 0x139B2FF0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Millwood Knight Leggings", 0x139B33D8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ringed Knight Hood", 0x13C8EEE0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ringed Knight Armor", 0x13C8F2C8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ringed Knight Gauntlets", 0x13C8F6B0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ringed Knight Leggings", 0x13C8FA98, DS3ItemCategory.ARMOR),
+ DS3ItemData("Harald Legion Armor", 0x13D83508, DS3ItemCategory.ARMOR),
+ DS3ItemData("Harald Legion Gauntlets", 0x13D838F0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Harald Legion Leggings", 0x13D83CD8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Iron Dragonslayer Helm", 0x1405F7E0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Iron Dragonslayer Armor", 0x1405FBC8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Iron Dragonslayer Gauntlets", 0x1405FFB0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Iron Dragonslayer Leggings", 0x14060398, DS3ItemCategory.ARMOR),
+ DS3ItemData("White Preacher Head", 0x14153A20, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ruin Helm", 0x14CC5520, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ruin Armor", 0x14CC5908, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ruin Gauntlets", 0x14CC5CF0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Ruin Leggings", 0x14CC60D8, DS3ItemCategory.ARMOR),
+ DS3ItemData("Desert Pyromancer Hood", 0x14DB9760, DS3ItemCategory.ARMOR),
+ DS3ItemData("Desert Pyromancer Garb", 0x14DB9B48, DS3ItemCategory.ARMOR),
+ DS3ItemData("Desert Pyromancer Gloves", 0x14DB9F30, DS3ItemCategory.ARMOR),
+ DS3ItemData("Desert Pyromancer Skirt", 0x14DBA318, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Witch Hat", 0x14EAD9A0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Witch Garb", 0x14EADD88, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Witch Wrappings", 0x14EAE170, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Witch Trousers", 0x14EAE558, DS3ItemCategory.ARMOR),
+ DS3ItemData("Black Witch Veil", 0x14FA1BE0, DS3ItemCategory.ARMOR),
+ DS3ItemData("Blindfold Mask", 0x15095E20, DS3ItemCategory.ARMOR),
# Covenants
- ("Spear of the Church", 0x2000276A, DS3ItemCategory.SKIP),
+ DS3ItemData("Spear of the Church", 0x2000276A, DS3ItemCategory.UNIQUE, skip = True),
# Rings
- ("Chloranthy Ring+3", 0x20004E2D, DS3ItemCategory.RING),
- ("Havel's Ring+3", 0x20004E37, DS3ItemCategory.RING),
- ("Ring of Favor+3", 0x20004E41, DS3ItemCategory.RING),
- ("Ring of Steel Protection+3", 0x20004E4B, DS3ItemCategory.RING),
- ("Wolf Ring+3", 0x20004EE1, DS3ItemCategory.RING),
- ("Covetous Gold Serpent Ring+3", 0x20004FA9, DS3ItemCategory.RING),
- ("Covetous Silver Serpent Ring+3", 0x20004FB3, DS3ItemCategory.RING),
- ("Ring of the Evil Eye+3", 0x20005071, DS3ItemCategory.RING),
- ("Chillbite Ring", 0x20005208, DS3ItemCategory.RING),
+ DS3ItemData("Chloranthy Ring+3", 0x20004E2D, DS3ItemCategory.RING,
+ classification = ItemClassification.useful),
+ DS3ItemData("Havel's Ring+3", 0x20004E37, DS3ItemCategory.RING,
+ classification = ItemClassification.useful),
+ DS3ItemData("Ring of Favor+3", 0x20004E41, DS3ItemCategory.RING,
+ classification = ItemClassification.useful),
+ DS3ItemData("Ring of Steel Protection+3", 0x20004E4B, DS3ItemCategory.RING,
+ classification = ItemClassification.useful),
+ DS3ItemData("Wolf Ring+3", 0x20004EE1, DS3ItemCategory.RING),
+ DS3ItemData("Covetous Gold Serpent Ring+3", 0x20004FA9, DS3ItemCategory.RING),
+ DS3ItemData("Covetous Silver Serpent Ring+3", 0x20004FB3, DS3ItemCategory.RING,
+ classification = ItemClassification.useful),
+ DS3ItemData("Ring of the Evil Eye+3", 0x20005071, DS3ItemCategory.RING),
+ DS3ItemData("Chillbite Ring", 0x20005208, DS3ItemCategory.RING),
# Items
- ("Church Guardian Shiv", 0x4000013B, DS3ItemCategory.MISC),
- ("Filianore's Spear Ornament", 0x4000017B, DS3ItemCategory.SKIP),
- ("Ritual Spear Fragment", 0x4000028A, DS3ItemCategory.MISC),
- ("Divine Spear Fragment", 0x4000028B, DS3ItemCategory.SKIP),
- ("Soul of Sister Friede", 0x400002E8, DS3ItemCategory.BOSS),
- ("Soul of Slave Knight Gael", 0x400002E9, DS3ItemCategory.BOSS),
- ("Soul of the Demon Prince", 0x400002EA, DS3ItemCategory.BOSS),
- ("Soul of Darkeater Midir", 0x400002EB, DS3ItemCategory.BOSS),
- ("Champion's Bones", 0x40000869, DS3ItemCategory.SKIP),
- ("Captain's Ashes", 0x4000086A, DS3ItemCategory.MISC),
- ("Contraption Key", 0x4000086B, DS3ItemCategory.KEY),
- ("Small Envoy Banner", 0x4000086C, DS3ItemCategory.KEY),
- ("Old Woman's Ashes", 0x4000086D, DS3ItemCategory.SKIP),
- ("Blood of the Dark Soul", 0x4000086E, DS3ItemCategory.SKIP),
+ DS3ItemData("Church Guardian Shiv", 0x4000013B, DS3ItemCategory.MISC),
+ DS3ItemData("Filianore's Spear Ornament", 0x4000017B, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Ritual Spear Fragment", 0x4000028A, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Divine Spear Fragment", 0x4000028B, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Soul of Sister Friede", 0x400002E8, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of Slave Knight Gael", 0x400002E9, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of the Demon Prince", 0x400002EA, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Soul of Darkeater Midir", 0x400002EB, DS3ItemCategory.BOSS, souls = 20000,
+ classification = ItemClassification.progression),
+ DS3ItemData("Champion's Bones", 0x40000869, DS3ItemCategory.UNIQUE, skip = True),
+ DS3ItemData("Captain's Ashes", 0x4000086A, DS3ItemCategory.MISC,
+ classification = ItemClassification.progression),
+ DS3ItemData("Contraption Key", 0x4000086B, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Small Envoy Banner", 0x4000086C, DS3ItemCategory.UNIQUE,
+ classification = ItemClassification.progression),
+ DS3ItemData("Old Woman's Ashes", 0x4000086D, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Blood of the Dark Soul", 0x4000086E, DS3ItemCategory.UNIQUE, skip = True),
# Spells
- ("Frozen Weapon", 0x401408E8, DS3ItemCategory.SPELL),
- ("Old Moonlight", 0x4014FF00, DS3ItemCategory.SPELL),
- ("Great Soul Dregs", 0x401879A0, DS3ItemCategory.SPELL),
- ("Snap Freeze", 0x401A90C8, DS3ItemCategory.SPELL),
- ("Floating Chaos", 0x40257DA8, DS3ItemCategory.SPELL),
- ("Flame Fan", 0x40258190, DS3ItemCategory.SPELL),
- ("Seething Chaos", 0x402896A0, DS3ItemCategory.SPELL),
- ("Lightning Arrow", 0x40358B08, DS3ItemCategory.SPELL),
- ("Way of White Corona", 0x403642A0, DS3ItemCategory.SPELL),
- ("Projected Heal", 0x40364688, DS3ItemCategory.SPELL),
-]]
+ DS3ItemData("Frozen Weapon", 0x401408E8, DS3ItemCategory.SPELL),
+ DS3ItemData("Old Moonlight", 0x4014FF00, DS3ItemCategory.SPELL),
+ DS3ItemData("Great Soul Dregs", 0x401879A0, DS3ItemCategory.SPELL),
+ DS3ItemData("Snap Freeze", 0x401A90C8, DS3ItemCategory.SPELL),
+ DS3ItemData("Floating Chaos", 0x40257DA8, DS3ItemCategory.SPELL),
+ DS3ItemData("Flame Fan", 0x40258190, DS3ItemCategory.SPELL),
+ DS3ItemData("Seething Chaos", 0x402896A0, DS3ItemCategory.SPELL),
+ DS3ItemData("Lightning Arrow", 0x40358B08, DS3ItemCategory.SPELL),
+ DS3ItemData("Way of White Corona", 0x403642A0, DS3ItemCategory.SPELL),
+ DS3ItemData("Projected Heal", 0x40364688, DS3ItemCategory.SPELL),
+]
+for item in _dlc_items:
+ item.is_dlc = True
# Unused list for future reference
# These items exist to some degree in the code, but aren't accessible
# in-game and can't be picked up without modifications
-_cut_content_items = [DS3ItemData(row[0], row[1], False, row[2]) for row in [
+_cut_content_items = [
# Weapons
- ("Blood-stained Short Sword", 0x00100590, DS3ItemCategory.SKIP),
- ("Missionary's Axe", 0x006C2F50, DS3ItemCategory.SKIP),
- ("Dragon King Greataxe", 0x006D40C0, DS3ItemCategory.SKIP),
- ("Four Knights Hammer", 0x007D4650, DS3ItemCategory.SKIP),
- ("Hammer of the Great Tree", 0x007D9470, DS3ItemCategory.SKIP),
- ("Lothric's Scythe", 0x009A4430, DS3ItemCategory.SKIP),
- ("Ancient Dragon Halberd", 0x009A6B40, DS3ItemCategory.SKIP),
- ("Scythe of Want", 0x009A9250, DS3ItemCategory.SKIP),
- ("Sacred Beast Catalyst", 0x00C8A730, DS3ItemCategory.SKIP),
- ("Deep Pyromancy Flame", 0x00CC9ED0, DS3ItemCategory.SKIP), # Duplicate?
- ("Flickering Pyromancy Flame", 0x00CD3B10, DS3ItemCategory.SKIP),
- ("Strong Pyromancy Flame", 0x00CD6220, DS3ItemCategory.SKIP),
- ("Deep Pyromancy Flame", 0x00CDFE60, DS3ItemCategory.SKIP), # Duplicate?
- ("Pitch-Dark Pyromancy Flame", 0x00CE2570, DS3ItemCategory.SKIP),
- ("Dancer's Short Bow", 0x00D77440, DS3ItemCategory.SKIP),
- ("Shield Crossbow", 0x00D81080, DS3ItemCategory.SKIP),
- ("Golden Dual Swords", 0x00F55C80, DS3ItemCategory.SKIP),
- ("Channeler's Trident", 0x008C8890, DS3ItemCategory.SKIP),
+ DS3ItemData("Blood-stained Short Sword", 0x00100590, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Missionary's Axe", 0x006C2F50, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Dragon King Greataxe", 0x006D40C0, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Four Knights Hammer", 0x007D4650, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Hammer of the Great Tree", 0x007D9470, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Lothric's Scythe", 0x009A4430, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Ancient Dragon Halberd", 0x009A6B40, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Scythe of Want", 0x009A9250, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Sacred Beast Catalyst", 0x00C8A730, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Deep Pyromancy Flame", 0x00CC9ED0, DS3ItemCategory.UNIQUE), # Duplicate?
+ DS3ItemData("Flickering Pyromancy Flame", 0x00CD3B10, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Strong Pyromancy Flame", 0x00CD6220, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Deep Pyromancy Flame", 0x00CDFE60, DS3ItemCategory.UNIQUE), # Duplicate?
+ DS3ItemData("Pitch-Dark Pyromancy Flame", 0x00CE2570, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Dancer's Short Bow", 0x00D77440, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Shield Crossbow", 0x00D81080, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Golden Dual Swords", 0x00F55C80, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Channeler's Trident", 0x008C8890, DS3ItemCategory.UNIQUE),
# Shields
- ("Cleric's Parma", 0x013524A0, DS3ItemCategory.SKIP),
- ("Prince's Shield", 0x01421CF0, DS3ItemCategory.SKIP),
+ DS3ItemData("Cleric's Parma", 0x013524A0, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Prince's Shield", 0x01421CF0, DS3ItemCategory.UNIQUE),
# Armor
- ("Dingy Maiden's Overcoat", 0x11DA9048, DS3ItemCategory.SKIP),
- ("Grotto Hat", 0x11F78A40, DS3ItemCategory.SKIP),
- ("Grotto Robe", 0x11F78E28, DS3ItemCategory.SKIP),
- ("Grotto Wrap", 0x11F79210, DS3ItemCategory.SKIP),
- ("Grotto Trousers", 0x11F795F8, DS3ItemCategory.SKIP),
- ("Soldier's Gauntlets", 0x126261D0, DS3ItemCategory.SKIP),
- ("Soldier's Hood", 0x1263E0A0, DS3ItemCategory.SKIP),
- ("Elder's Robe", 0x129024A8, DS3ItemCategory.SKIP),
- ("Saint's Veil", 0x12A70420, DS3ItemCategory.SKIP),
- ("Saint's Dress", 0x12A70808, DS3ItemCategory.SKIP),
- ("Footman's Hood", 0x12AEA540, DS3ItemCategory.SKIP),
- ("Footman's Overcoat", 0x12AEA928, DS3ItemCategory.SKIP),
- ("Footman's Bracelets", 0x12AEAD10, DS3ItemCategory.SKIP),
- ("Footman's Trousers", 0x12AEB0F8, DS3ItemCategory.SKIP),
- ("Scholar's Shed Skin", 0x12E40D20, DS3ItemCategory.SKIP),
- ("Man Serpent's Mask", 0x138BE5E0, DS3ItemCategory.SKIP),
- ("Man Serpent's Robe", 0x138BE9C8, DS3ItemCategory.SKIP),
- ("Old Monarch's Crown", 0x13DFD240, DS3ItemCategory.SKIP),
- ("Old Monarch's Robe", 0x13DFD628, DS3ItemCategory.SKIP),
- ("Frigid Valley Mask", 0x13FE56C0, DS3ItemCategory.SKIP),
- ("Dingy Hood", 0x140D9900, DS3ItemCategory.SKIP),
- ("Hexer's Hood", 0x15A995C0, DS3ItemCategory.SKIP),
- ("Hexer's Robes", 0x15A999A8, DS3ItemCategory.SKIP),
- ("Hexer's Gloves", 0x15A99D90, DS3ItemCategory.SKIP),
- ("Hexer's Boots", 0x15A9A178, DS3ItemCategory.SKIP),
- ("Varangian Helm", 0x15C81A40, DS3ItemCategory.SKIP),
- ("Varangian Armor", 0x15C81E28, DS3ItemCategory.SKIP),
- ("Varangian Cuffs", 0x15C82210, DS3ItemCategory.SKIP),
- ("Varangian Leggings", 0x15C825F8, DS3ItemCategory.SKIP),
+ DS3ItemData("Dingy Maiden's Overcoat", 0x11DA9048, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Grotto Hat", 0x11F78A40, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Grotto Robe", 0x11F78E28, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Grotto Wrap", 0x11F79210, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Grotto Trousers", 0x11F795F8, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Soldier's Gauntlets", 0x126261D0, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Soldier's Hood", 0x1263E0A0, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Elder's Robe", 0x129024A8, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Saint's Veil", 0x12A70420, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Saint's Dress", 0x12A70808, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Footman's Hood", 0x12AEA540, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Footman's Overcoat", 0x12AEA928, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Footman's Bracelets", 0x12AEAD10, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Footman's Trousers", 0x12AEB0F8, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Scholar's Shed Skin", 0x12E40D20, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Man Serpent's Mask", 0x138BE5E0, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Man Serpent's Robe", 0x138BE9C8, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Old Monarch's Crown", 0x13DFD240, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Old Monarch's Robe", 0x13DFD628, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Frigid Valley Mask", 0x13FE56C0, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Dingy Hood", 0x140D9900, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Hexer's Hood", 0x15A995C0, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Hexer's Robes", 0x15A999A8, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Hexer's Gloves", 0x15A99D90, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Hexer's Boots", 0x15A9A178, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Varangian Helm", 0x15C81A40, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Varangian Armor", 0x15C81E28, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Varangian Cuffs", 0x15C82210, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Varangian Leggings", 0x15C825F8, DS3ItemCategory.UNIQUE),
# Rings
- ("Rare Ring of Sacrifice", 0x20004EFC, DS3ItemCategory.SKIP),
- ("Baneful Bird Ring", 0x20005032, DS3ItemCategory.SKIP),
- ("Darkmoon Blade Covenant Ring", 0x20004F7E, DS3ItemCategory.SKIP),
- ("Yorgh's Ring", 0x2000505A, DS3ItemCategory.SKIP),
- ("Ring of Hiding", 0x200050D2, DS3ItemCategory.SKIP),
- ("Ring of Sustained Toughness", 0x20005118, DS3ItemCategory.SKIP),
- ("Ring of Sustained Energy", 0x20005122, DS3ItemCategory.SKIP),
- ("Ring of Sustained Magic", 0x2000512C, DS3ItemCategory.SKIP),
- ("Ring of Sustained Essence", 0x20005140, DS3ItemCategory.SKIP),
- ("Ring of Sustained Might", 0x2000514A, DS3ItemCategory.SKIP),
- ("Ring of Sustained Fortune", 0x20005154, DS3ItemCategory.SKIP),
+ DS3ItemData("Rare Ring of Sacrifice", 0x20004EFC, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Baneful Bird Ring", 0x20005032, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Darkmoon Blade Covenant Ring", 0x20004F7E, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Yorgh's Ring", 0x2000505A, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Ring of Hiding", 0x200050D2, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Ring of Sustained Toughness", 0x20005118, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Ring of Sustained Energy", 0x20005122, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Ring of Sustained Magic", 0x2000512C, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Ring of Sustained Essence", 0x20005140, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Ring of Sustained Might", 0x2000514A, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Ring of Sustained Fortune", 0x20005154, DS3ItemCategory.UNIQUE),
# Items
- ("Soul of a Wicked Spirit", 0x400002C9, DS3ItemCategory.SKIP),
+ DS3ItemData("Soul of a Wicked Spirit", 0x400002C9, DS3ItemCategory.UNIQUE),
# Spells
- ("Dark Orb", 0x4027AC40, DS3ItemCategory.SKIP),
- ("Morbid Temptation", 0x40359AA8, DS3ItemCategory.SKIP),
- ("Dorris Swarm", 0x40393870, DS3ItemCategory.SKIP),
-]]
+ DS3ItemData("Dark Orb", 0x4027AC40, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Morbid Temptation", 0x40359AA8, DS3ItemCategory.UNIQUE),
+ DS3ItemData("Dorris Swarm", 0x40393870, DS3ItemCategory.UNIQUE),
+]
+
+
+item_name_groups: Dict[str, Set] = {
+ "Progression": set(),
+ "Cinders": set(),
+ "Weapons": set(),
+ "Shields": set(),
+ "Armor": set(),
+ "Rings": set(),
+ "Spells": set(),
+ "Miscellaneous": set(),
+ "Unique": set(),
+ "Boss Souls": set(),
+ "Small Souls": set(),
+ "Upgrade": set(),
+ "Healing": set(),
+}
+
item_descriptions = {
+ "Progression": "Items which unlock locations.",
"Cinders": "All four Cinders of a Lord.\n\nOnce you have these four, you can fight Soul of Cinder and win the game.",
+ "Miscellaneous": "Generic stackable items, such as arrows, firebombs, buffs, and so on.",
+ "Unique": "Items that are unique per NG cycle, such as scrolls, keys, ashes, and so on. Doesn't include equipment, spells, or souls.",
+ "Boss Souls": "Souls that can be traded with Ludleth, including Soul of Rosaria.",
+ "Small Souls": "Soul items, not including boss souls.",
+ "Upgrade": "Upgrade items, including titanite, gems, and Shriving Stones.",
+ "Healing": "Undead Bone Shards and Estus Shards.",
}
+
_all_items = _vanilla_items + _dlc_items
+for item_data in _all_items:
+ for group_name in item_data.item_groups():
+ item_name_groups[group_name].add(item_data.name)
+
+filler_item_names = [item_data.name for item_data in _all_items if item_data.filler]
item_dictionary = {item_data.name: item_data for item_data in _all_items}
diff --git a/worlds/dark_souls_3/Locations.py b/worlds/dark_souls_3/Locations.py
index df241a5fd1fb..08f4b7cd1a80 100644
--- a/worlds/dark_souls_3/Locations.py
+++ b/worlds/dark_souls_3/Locations.py
@@ -1,693 +1,3119 @@
-from enum import IntEnum
-from typing import Optional, NamedTuple, Dict
+from typing import cast, ClassVar, Optional, Dict, List, Set
+from dataclasses import dataclass
-from BaseClasses import Location, Region
+from BaseClasses import ItemClassification, Location, Region
+from .Items import DS3ItemCategory, item_dictionary
+# Regions in approximate order of reward, mostly measured by how high-quality the upgrade items are
+# in each region.
+region_order = [
+ "Cemetery of Ash",
+ "Firelink Shrine",
+ "High Wall of Lothric",
+ "Greirat's Shop",
+ "Undead Settlement",
+ "Road of Sacrifices",
+ "Farron Keep",
+ "Cathedral of the Deep",
+ "Catacombs of Carthus",
+ "Smouldering Lake",
+ "Irithyll of the Boreal Valley",
+ "Irithyll Dungeon",
+ "Karla's Shop",
+ # The first half of Painted World has one Titanite Slab but mostly Large Titanite Shards,
+ # much like Irithyll Dungeon.
+ "Painted World of Ariandel (Before Contraption)",
+ "Anor Londo",
+ "Profaned Capital",
+ # The second half of Painted World has two Titanite Chunks and two Titanite Slabs, which
+ # puts it on the low end of the post-Lothric Castle areas in terms of rewards.
+ "Painted World of Ariandel (After Contraption)",
+ "Lothric Castle",
+ "Consumed King's Garden",
+ "Untended Graves",
+ # List this late because it contains a Titanite Slab in the base game
+ "Firelink Shrine Bell Tower",
+ "Grand Archives",
+ "Archdragon Peak",
+ "Kiln of the First Flame",
+ # Both areas of DLC2 have premium rewards.
+ "Dreg Heap",
+ "Ringed City",
+]
-class DS3LocationCategory(IntEnum):
- WEAPON = 0
- SHIELD = 1
- ARMOR = 2
- RING = 3
- SPELL = 4
- NPC = 5
- KEY = 6
- BOSS = 7
- MISC = 8
- HEALTH = 9
- PROGRESSIVE_ITEM = 10
- EVENT = 11
+@dataclass
+class DS3LocationData:
+ __location_id: ClassVar[int] = 100000
+ """The next location ID to use when creating location data."""
-class DS3LocationData(NamedTuple):
name: str
- default_item: str
- category: DS3LocationCategory
+ """The name of this location according to Archipelago.
+
+ This needs to be unique within this world."""
+
+ default_item_name: Optional[str]
+ """The name of the item that appears by default in this location.
+
+ If this is None, that indicates that this location is an "event" that's
+ automatically considered accessed as soon as it's available. Events are used
+ to indicate major game transitions that aren't otherwise gated by items so
+ that progression balancing and item smoothing is more accurate for DS3.
+ """
+
+ ap_code: Optional[int] = None
+ """Archipelago's internal ID for this location (also known as its "address")."""
+
+ region_value: int = 0
+ """The relative value of items in this location's region.
+
+ This is used to sort locations when placing items like the base game.
+ """
+
+ static: Optional[str] = None
+ """The key in the static randomizer's Slots table that corresponds to this location.
+
+ By default, the static randomizer chooses its location based on the region and the item name.
+ If the item name is unique across the whole game, it can also look it up based on that alone. If
+ there are multiple instances of the same item type in the same region, it will assume its order
+ (in annotations.txt) matches Archipelago's order.
+
+ In cases where this heuristic doesn't work, such as when Archipelago's region categorization or
+ item name disagrees with the static randomizer's, this field is used to provide an explicit
+ association instead.
+ """
+
+ missable: bool = False
+ """Whether this item is possible to permanently lose access to.
+
+ This is also used for items that are *technically* possible to get at any time, but are
+ prohibitively difficult without blocking off other checks (items dropped by NPCs on death
+ generally fall into this category).
+
+ Missable locations are always marked as excluded, so they will never contain
+ progression or useful items.
+ """
+
+ dlc: bool = False
+ """Whether this location is only accessible if the DLC is enabled."""
+
+ ngp: bool = False
+ """Whether this location only contains an item in NG+ and later.
+
+ By default, these items aren't randomized or included in the randomization pool, but an option
+ can be set to enable them even for NG runs."""
+
+ npc: bool = False
+ """Whether this item is contingent on killing an NPC or following their quest."""
+
+ prominent: bool = False
+ """Whether this is one of few particularly prominent places for items to appear.
+
+ This is a small number of locations (boss drops and progression locations)
+ intended to be set as priority locations for players who don't want a lot of
+ mandatory checks.
+
+ For bosses with multiple drops, only one should be marked prominent.
+ """
+
+ progression: bool = False
+ """Whether this location normally contains an item that blocks forward progress."""
+
+ boss: bool = False
+ """Whether this location is a reward for defeating a full boss."""
+
+ miniboss: bool = False
+ """Whether this location is a reward for defeating a miniboss.
+
+ The classification of "miniboss" is a bit fuzzy, but we consider them to be enemies that are
+ visually distinctive in their locations, usually bigger than normal enemies, with a guaranteed
+ item drop. NPCs are never considered minibosses, and some normal-looking enemies with guaranteed
+ drops aren't either (these are instead classified as hidden locations)."""
+
+ drop: bool = False
+ """Whether this is an item dropped by a (non-boss) enemy.
+
+ This is automatically set to True if miniboss, mimic, lizard, or hostile_npc is True.
+ """
+
+ mimic: bool = False
+ """Whether this location is dropped by a mimic."""
+
+ hostile_npc: bool = False
+ """Whether this location is dropped by a hostile NPC.
+
+ An "NPC" is specifically a human (or rather, ash) is built like a player character rather than a
+ monster. This includes both scripted invaders and NPCs who are always on the overworld. It does
+ not include initially-friendly NPCs who become hostile as part of a quest or because you attack
+ them.
+ """
+
+ lizard: bool = False
+ """Whether this location is dropped by a (small) Crystal Lizard."""
+
+ shop: bool = False
+ """Whether this location can appear in an NPC's shop.
+
+ Items like Lapp's Set which can appear both in the overworld and in a shop
+ should still be tagged as shop.
+ """
+
+ conditional: bool = False
+ """Whether this location is conditional on a progression item.
+
+ This is used to track locations that won't become available until an unknown amount of time into
+ the run, and as such shouldn't have "similar to the base game" items placed in them.
+ """
+
+ hidden: bool = False
+ """Whether this location is particularly tricky to find.
+
+ This is for players without an encyclopedic knowledge of DS3 who don't want to get stuck looking
+ for an illusory wall or one random mob with a guaranteed drop.
+ """
+
+ @property
+ def is_event(self) -> bool:
+ """Whether this location represents an event rather than a specific item pickup."""
+ return self.default_item_name is None
+
+ def __post_init__(self):
+ if not self.is_event:
+ self.ap_code = self.ap_code or DS3LocationData.__location_id
+ DS3LocationData.__location_id += 1
+ if self.miniboss or self.mimic or self.lizard or self.hostile_npc: self.drop = True
+
+ def location_groups(self) -> List[str]:
+ """The names of location groups this location should appear in.
+
+ This is computed from the properties assigned to this location."""
+ names = []
+ if self.prominent: names.append("Prominent")
+ if self.progression: names.append("Progression")
+ if self.boss: names.append("Boss Rewards")
+ if self.miniboss: names.append("Miniboss Rewards")
+ if self.mimic: names.append("Mimic Rewards")
+ if self.hostile_npc: names.append("Hostile NPC Rewards")
+ if self.npc: names.append("Friendly NPC Rewards")
+ if self.lizard: names.append("Small Crystal Lizards")
+ if self.hidden: names.append("Hidden")
+
+ default_item = item_dictionary[cast(str, self.default_item_name)]
+ names.append({
+ DS3ItemCategory.WEAPON_UPGRADE_5: "Weapons",
+ DS3ItemCategory.WEAPON_UPGRADE_10: "Weapons",
+ DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE: "Weapons",
+ DS3ItemCategory.SHIELD: "Shields",
+ DS3ItemCategory.SHIELD_INFUSIBLE: "Shields",
+ DS3ItemCategory.ARMOR: "Armor",
+ DS3ItemCategory.RING: "Rings",
+ DS3ItemCategory.SPELL: "Spells",
+ DS3ItemCategory.MISC: "Miscellaneous",
+ DS3ItemCategory.UNIQUE: "Unique",
+ DS3ItemCategory.BOSS: "Boss Souls",
+ DS3ItemCategory.SOUL: "Small Souls",
+ DS3ItemCategory.UPGRADE: "Upgrade",
+ DS3ItemCategory.HEALING: "Healing",
+ }[default_item.category])
+ if default_item.classification == ItemClassification.progression:
+ names.append("Progression")
+
+ return names
class DarkSouls3Location(Location):
game: str = "Dark Souls III"
- category: DS3LocationCategory
- default_item_name: str
+ data: DS3LocationData
def __init__(
self,
player: int,
- name: str,
- category: DS3LocationCategory,
- default_item_name: str,
- address: Optional[int] = None,
- parent: Optional[Region] = None):
- super().__init__(player, name, address, parent)
- self.default_item_name = default_item_name
- self.category = category
-
- @staticmethod
- def get_name_to_id() -> dict:
- base_id = 100000
- table_offset = 100
-
- table_order = [
- "Firelink Shrine",
- "Firelink Shrine Bell Tower",
- "High Wall of Lothric",
- "Undead Settlement",
- "Road of Sacrifices",
- "Cathedral of the Deep",
- "Farron Keep",
- "Catacombs of Carthus",
- "Smouldering Lake",
- "Irithyll of the Boreal Valley",
- "Irithyll Dungeon",
- "Profaned Capital",
- "Anor Londo",
- "Lothric Castle",
- "Consumed King's Garden",
- "Grand Archives",
- "Untended Graves",
- "Archdragon Peak",
-
- "Painted World of Ariandel 1",
- "Painted World of Ariandel 2",
- "Dreg Heap",
- "Ringed City",
-
- "Progressive Items 1",
- "Progressive Items 2",
- "Progressive Items 3",
- "Progressive Items 4",
- "Progressive Items DLC",
- "Progressive Items Health",
- ]
-
- output = {}
- for i, region_name in enumerate(table_order):
- if len(location_tables[region_name]) > table_offset:
- raise Exception("A location table has {} entries, that is more than {} entries (table #{})".format(len(location_tables[region_name]), table_offset, i))
-
- output.update({location_data.name: id for id, location_data in enumerate(location_tables[region_name], base_id + (table_offset * i))})
-
- return output
-
-
-location_tables = {
+ data: DS3LocationData,
+ parent: Optional[Region] = None,
+ event: bool = False):
+ super().__init__(player, data.name, None if event else data.ap_code, parent)
+ self.data = data
+
+
+# Naming conventions:
+#
+# * The regions in item names should match the physical region where the item is
+# acquired, even if its logical region is different. For example, Irina's
+# inventory appears in the "Undead Settlement" region because she's not
+# accessible until there, but it begins with "FS:" because that's where her
+# items are purchased.
+#
+# * Avoid using vanilla enemy placements as landmarks, because these are
+# randomized by the enemizer by default. Instead, use generic terms like
+# "mob", "boss", and "miniboss".
+#
+# * Location descriptions don't need to direct the player to the precise spot.
+# You can assume the player is broadly familiar with Dark Souls III or willing
+# to look at a vanilla guide. Just give a general area to look in or an idea
+# of what quest a check is connected to. Terseness is valuable: try to keep
+# each location description short enough that the whole line doesn't exceed
+# 100 characters.
+#
+# * Use "[name] drop" for items that require killing an NPC who becomes hostile
+# as part of their normal quest, "kill [name]" for items that require killing
+# them even when they aren't hostile, and just "[name]" for items that are
+# naturally available as part of their quest.
+location_tables: Dict[str, List[DS3LocationData]] = {
+ "Cemetery of Ash": [
+ DS3LocationData("CA: Soul of a Deserted Corpse - right of spawn",
+ "Soul of a Deserted Corpse"),
+ DS3LocationData("CA: Firebomb - down the cliff edge", "Firebomb x5"),
+ DS3LocationData("CA: Titanite Shard - jump to coffin", "Titanite Shard"),
+ DS3LocationData("CA: Soul of an Unknown Traveler - by miniboss",
+ "Soul of an Unknown Traveler"),
+ DS3LocationData("CA: Speckled Stoneplate Ring+1 - by miniboss",
+ "Speckled Stoneplate Ring+1", ngp=True),
+ DS3LocationData("CA: Titanite Scale - miniboss drop", "Titanite Scale", miniboss=True),
+ DS3LocationData("CA: Coiled Sword - boss drop", "Coiled Sword", prominent=True,
+ progression=True, boss=True),
+ ],
"Firelink Shrine": [
- DS3LocationData("FS: Broken Straight Sword", "Broken Straight Sword", DS3LocationCategory.WEAPON),
- DS3LocationData("FS: East-West Shield", "East-West Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("FS: Uchigatana", "Uchigatana", DS3LocationCategory.WEAPON),
- DS3LocationData("FS: Master's Attire", "Master's Attire", DS3LocationCategory.ARMOR),
- DS3LocationData("FS: Master's Gloves", "Master's Gloves", DS3LocationCategory.ARMOR),
+ # Ludleth drop, does not permanently die
+ DS3LocationData("FS: Skull Ring - kill Ludleth", "Skull Ring", hidden=True, drop=True,
+ npc=True),
+
+ # Sword Master drops
+ DS3LocationData("FS: Uchigatana - NPC drop", "Uchigatana", hostile_npc=True),
+ DS3LocationData("FS: Master's Attire - NPC drop", "Master's Attire", hostile_npc=True),
+ DS3LocationData("FS: Master's Gloves - NPC drop", "Master's Gloves", hostile_npc=True),
+
+ DS3LocationData("FS: Broken Straight Sword - gravestone after boss",
+ "Broken Straight Sword"),
+ DS3LocationData("FS: Homeward Bone - cliff edge after boss", "Homeward Bone"),
+ DS3LocationData("FS: Ember - path right of Firelink entrance", "Ember"),
+ DS3LocationData("FS: Soul of a Deserted Corpse - bell tower door",
+ "Soul of a Deserted Corpse"),
+ DS3LocationData("FS: East-West Shield - tree by shrine entrance", "East-West Shield"),
+ DS3LocationData("FS: Homeward Bone - path above shrine entrance", "Homeward Bone"),
+ DS3LocationData("FS: Ember - above shrine entrance", "Ember"),
+ DS3LocationData("FS: Wolf Ring+2 - left of boss room exit", "Wolf Ring+2", ngp=True),
+ # Leonhard (quest)
+ DS3LocationData("FS: Cracked Red Eye Orb - Leonhard", "Cracked Red Eye Orb x5",
+ missable=True, npc=True),
+ # Leonhard (kill or quest), missable because he can disappear sometimes
+ DS3LocationData("FS: Lift Chamber Key - Leonhard", "Lift Chamber Key", missable=True,
+ npc=True, drop=True),
+
+ # Shrine Handmaid shop
+ DS3LocationData("FS: White Sign Soapstone - shop", "White Sign Soapstone", shop=True),
+ DS3LocationData("FS: Dried Finger - shop", "Dried Finger", shop=True),
+ DS3LocationData("FS: Tower Key - shop", "Tower Key", progression=True, shop=True),
+ DS3LocationData("FS: Ember - shop", "Ember", static='99,0:-1:110000:', shop=True),
+ DS3LocationData("FS: Farron Dart - shop", "Farron Dart", static='99,0:-1:110000:',
+ shop=True),
+ DS3LocationData("FS: Soul Arrow - shop", "Soul Arrow", static='99,0:-1:110000:',
+ shop=True),
+ DS3LocationData("FS: Heal Aid - shop", "Heal Aid", shop=True),
+ DS3LocationData("FS: Alluring Skull - Mortician's Ashes", "Alluring Skull", shop=True,
+ conditional=True),
+ DS3LocationData("FS: Ember - Mortician's Ashes", "Ember",
+ static='99,0:-1:110000,70000100:', shop=True, conditional=True),
+ DS3LocationData("FS: Grave Key - Mortician's Ashes", "Grave Key", shop=True,
+ conditional=True),
+ DS3LocationData("FS: Life Ring - Dreamchaser's Ashes", "Life Ring", shop=True,
+ conditional=True),
+ # Only if you say where the ashes were found
+ DS3LocationData("FS: Hidden Blessing - Dreamchaser's Ashes", "Hidden Blessing",
+ missable=True, shop=True),
+ DS3LocationData("FS: Lloyd's Shield Ring - Paladin's Ashes", "Lloyd's Shield Ring",
+ shop=True, conditional=True),
+ DS3LocationData("FS: Ember - Grave Warden's Ashes", "Ember",
+ static='99,0:-1:110000,70000103:', shop=True, conditional=True),
+ # Prisoner Chief's Ashes
+ DS3LocationData("FS: Karla's Pointed Hat - Prisoner Chief's Ashes", "Karla's Pointed Hat",
+ static='99,0:-1:110000,70000105:', shop=True, conditional=True),
+ DS3LocationData("FS: Karla's Coat - Prisoner Chief's Ashes", "Karla's Coat",
+ static='99,0:-1:110000,70000105:', shop=True, conditional=True),
+ DS3LocationData("FS: Karla's Gloves - Prisoner Chief's Ashes", "Karla's Gloves",
+ static='99,0:-1:110000,70000105:', shop=True, conditional=True),
+ DS3LocationData("FS: Karla's Trousers - Prisoner Chief's Ashes", "Karla's Trousers",
+ static='99,0:-1:110000,70000105:', shop=True, conditional=True),
+ DS3LocationData("FS: Xanthous Overcoat - Xanthous Ashes", "Xanthous Overcoat", shop=True,
+ conditional=True),
+ DS3LocationData("FS: Xanthous Gloves - Xanthous Ashes", "Xanthous Gloves", shop=True,
+ conditional=True),
+ DS3LocationData("FS: Xanthous Trousers - Xanthous Ashes", "Xanthous Trousers", shop=True,
+ conditional=True),
+ DS3LocationData("FS: Ember - Dragon Chaser's Ashes", "Ember",
+ static='99,0:-1:110000,70000108:', shop=True, conditional=True),
+ DS3LocationData("FS: Washing Pole - Easterner's Ashes", "Washing Pole", shop=True,
+ conditional=True),
+ DS3LocationData("FS: Eastern Helm - Easterner's Ashes", "Eastern Helm", shop=True,
+ conditional=True),
+ DS3LocationData("FS: Eastern Armor - Easterner's Ashes", "Eastern Armor", shop=True,
+ conditional=True),
+ DS3LocationData("FS: Eastern Gauntlets - Easterner's Ashes", "Eastern Gauntlets",
+ shop=True, conditional=True),
+ DS3LocationData("FS: Eastern Leggings - Easterner's Ashes", "Eastern Leggings", shop=True,
+ conditional=True),
+ DS3LocationData("FS: Wood Grain Ring - Easterner's Ashes", "Wood Grain Ring", shop=True,
+ conditional=True),
+ DS3LocationData("FS: Millwood Knight Helm - Captain's Ashes", "Millwood Knight Helm",
+ dlc=True, shop=True, conditional=True),
+ DS3LocationData("FS: Millwood Knight Armor - Captain's Ashes", "Millwood Knight Armor",
+ dlc=True, shop=True, conditional=True),
+ DS3LocationData("FS: Millwood Knight Gauntlets - Captain's Ashes",
+ "Millwood Knight Gauntlets", dlc=True, shop=True, conditional=True),
+ DS3LocationData("FS: Millwood Knight Leggings - Captain's Ashes",
+ "Millwood Knight Leggings", dlc=True, shop=True, conditional=True),
+ DS3LocationData("FS: Refined Gem - Captain's Ashes", "Refined Gem", dlc=True, shop=True,
+ conditional=True),
+
+ # Ludleth Shop
+ DS3LocationData("FS: Vordt's Great Hammer - Ludleth for Vordt", "Vordt's Great Hammer",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Pontiff's Left Eye - Ludleth for Vordt", "Pontiff's Left Eye",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Bountiful Sunlight - Ludleth for Rosaria", "Bountiful Sunlight",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Darkmoon Longbow - Ludleth for Aldrich", "Darkmoon Longbow",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Lifehunt Scythe - Ludleth for Aldrich", "Lifehunt Scythe",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Hollowslayer Greatsword - Ludleth for Greatwood",
+ "Hollowslayer Greatsword", missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Arstor's Spear - Ludleth for Greatwood", "Arstor's Spear",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Crystal Sage's Rapier - Ludleth for Sage", "Crystal Sage's Rapier",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Crystal Hail - Ludleth for Sage", "Crystal Hail", missable=True,
+ boss=True, shop=True),
+ DS3LocationData("FS: Cleric's Candlestick - Ludleth for Deacons", "Cleric's Candlestick",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Deep Soul - Ludleth for Deacons", "Deep Soul", missable=True,
+ boss=True, shop=True),
+ DS3LocationData("FS: Havel's Ring - Ludleth for Stray Demon", "Havel's Ring",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Boulder Heave - Ludleth for Stray Demon", "Boulder Heave",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Farron Greatsword - Ludleth for Abyss Watchers", "Farron Greatsword",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Wolf Knight's Greatsword - Ludleth for Abyss Watchers",
+ "Wolf Knight's Greatsword", missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Wolnir's Holy Sword - Ludleth for Wolnir", "Wolnir's Holy Sword",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Black Serpent - Ludleth for Wolnir", "Black Serpent", missable=True,
+ boss=True, shop=True),
+ DS3LocationData("FS: Demon's Greataxe - Ludleth for Fire Demon", "Demon's Greataxe",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Demon's Fist - Ludleth for Fire Demon", "Demon's Fist",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Old King's Great Hammer - Ludleth for Old Demon King",
+ "Old King's Great Hammer", missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Chaos Bed Vestiges - Ludleth for Old Demon King", "Chaos Bed Vestiges",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Greatsword of Judgment - Ludleth for Pontiff",
+ "Greatsword of Judgment", missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Profaned Greatsword - Ludleth for Pontiff", "Profaned Greatsword",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Yhorm's Great Machete - Ludleth for Yhorm", "Yhorm's Great Machete",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Yhorm's Greatshield - Ludleth for Yhorm", "Yhorm's Greatshield",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Dancer's Enchanted Swords - Ludleth for Dancer",
+ "Dancer's Enchanted Swords", missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Soothing Sunlight - Ludleth for Dancer", "Soothing Sunlight",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Dragonslayer Greataxe - Ludleth for Dragonslayer",
+ "Dragonslayer Greataxe", missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Dragonslayer Greatshield - Ludleth for Dragonslayer",
+ "Dragonslayer Greatshield", missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Moonlight Greatsword - Ludleth for Oceiros", "Moonlight Greatsword",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: White Dragon Breath - Ludleth for Oceiros", "White Dragon Breath",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Lorian's Greatsword - Ludleth for Princes", "Lorian's Greatsword",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Lothric's Holy Sword - Ludleth for Princes", "Lothric's Holy Sword",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Gundyr's Halberd - Ludleth for Champion", "Gundyr's Halberd",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Prisoner's Chain - Ludleth for Champion", "Prisoner's Chain",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Storm Curved Sword - Ludleth for Nameless", "Storm Curved Sword",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Dragonslayer Swordspear - Ludleth for Nameless",
+ "Dragonslayer Swordspear", missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Lightning Storm - Ludleth for Nameless", "Lightning Storm",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Firelink Greatsword - Ludleth for Cinder", "Firelink Greatsword",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Sunlight Spear - Ludleth for Cinder", "Sunlight Spear",
+ missable=True, boss=True, shop=True),
+ DS3LocationData("FS: Friede's Great Scythe - Ludleth for Friede", "Friede's Great Scythe",
+ missable=True, dlc=True, boss=True, shop=True),
+ DS3LocationData("FS: Rose of Ariandel - Ludleth for Friede", "Rose of Ariandel",
+ missable=True, dlc=True, boss=True, shop=True),
+ DS3LocationData("FS: Demon's Scar - Ludleth for Demon Prince", "Demon's Scar",
+ missable=True, dlc=True, boss=True, shop=True),
+ DS3LocationData("FS: Seething Chaos - Ludleth for Demon Prince", "Seething Chaos",
+ missable=True, dlc=True, boss=True, shop=True),
+ DS3LocationData("FS: Frayed Blade - Ludleth for Midir", "Frayed Blade", missable=True,
+ dlc=True, boss=True, shop=True),
+ DS3LocationData("FS: Old Moonlight - Ludleth for Midir", "Old Moonlight", missable=True,
+ dlc=True, boss=True, shop=True),
+ DS3LocationData("FS: Gael's Greatsword - Ludleth for Gael", "Gael's Greatsword",
+ missable=True, dlc=True, boss=True, shop=True),
+ DS3LocationData("FS: Repeating Crossbow - Ludleth for Gael", "Repeating Crossbow",
+ missable=True, dlc=True, boss=True, shop=True),
],
"Firelink Shrine Bell Tower": [
- DS3LocationData("FSBT: Covetous Silver Serpent Ring", "Covetous Silver Serpent Ring", DS3LocationCategory.RING),
- DS3LocationData("FSBT: Fire Keeper Robe", "Fire Keeper Robe", DS3LocationCategory.ARMOR),
- DS3LocationData("FSBT: Fire Keeper Gloves", "Fire Keeper Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("FSBT: Fire Keeper Skirt", "Fire Keeper Skirt", DS3LocationCategory.ARMOR),
- DS3LocationData("FSBT: Estus Ring", "Estus Ring", DS3LocationCategory.RING),
- DS3LocationData("FSBT: Fire Keeper Soul", "Fire Keeper Soul", DS3LocationCategory.MISC),
+ # Guarded by Tower Key
+ DS3LocationData("FSBT: Homeward Bone - roof", "Homeward Bone x3"),
+ DS3LocationData("FSBT: Estus Ring - tower base", "Estus Ring"),
+ DS3LocationData("FSBT: Estus Shard - rafters", "Estus Shard"),
+ DS3LocationData("FSBT: Fire Keeper Soul - tower top", "Fire Keeper Soul"),
+ DS3LocationData("FSBT: Fire Keeper Robe - partway down tower", "Fire Keeper Robe"),
+ DS3LocationData("FSBT: Fire Keeper Gloves - partway down tower", "Fire Keeper Gloves"),
+ DS3LocationData("FSBT: Fire Keeper Skirt - partway down tower", "Fire Keeper Skirt"),
+ DS3LocationData("FSBT: Covetous Silver Serpent Ring - illusory wall past rafters",
+ "Covetous Silver Serpent Ring", hidden=True),
+ DS3LocationData("FSBT: Twinkling Titanite - lizard behind Firelink",
+ "Twinkling Titanite", lizard=True),
+
+ # Mark all crow trades as missable since no one wants to have to try trading everything just
+ # in case it gives a progression item.
+ DS3LocationData("FSBT: Iron Bracelets - crow for Homeward Bone", "Iron Bracelets",
+ missable=True),
+ DS3LocationData("FSBT: Ring of Sacrifice - crow for Loretta's Bone", "Ring of Sacrifice",
+ missable=True),
+ DS3LocationData("FSBT: Porcine Shield - crow for Undead Bone Shard", "Porcine Shield",
+ missable=True),
+ DS3LocationData("FSBT: Lucatiel's Mask - crow for Vertebra Shackle", "Lucatiel's Mask",
+ missable=True),
+ DS3LocationData("FSBT: Very good! Carving - crow for Divine Blessing",
+ "Very good! Carving", missable=True),
+ DS3LocationData("FSBT: Thank you Carving - crow for Hidden Blessing", "Thank you Carving",
+ missable=True),
+ DS3LocationData("FSBT: I'm sorry Carving - crow for Shriving Stone", "I'm sorry Carving",
+ missable=True),
+ DS3LocationData("FSBT: Sunlight Shield - crow for Mendicant's Staff", "Sunlight Shield",
+ missable=True),
+ DS3LocationData("FSBT: Hollow Gem - crow for Eleonora", "Hollow Gem",
+ missable=True),
+ DS3LocationData("FSBT: Titanite Scale - crow for Blacksmith Hammer", "Titanite Scale x3",
+ static='99,0:50004330::', missable=True),
+ DS3LocationData("FSBT: Help me! Carving - crow for any sacred chime", "Help me! Carving",
+ missable=True),
+ DS3LocationData("FSBT: Titanite Slab - crow for Coiled Sword Fragment", "Titanite Slab",
+ missable=True),
+ DS3LocationData("FSBT: Hello Carving - crow for Alluring Skull", "Hello Carving",
+ missable=True),
+ DS3LocationData("FSBT: Armor of the Sun - crow for Siegbräu", "Armor of the Sun",
+ missable=True),
+ DS3LocationData("FSBT: Large Titanite Shard - crow for Firebomb", "Large Titanite Shard",
+ missable=True),
+ DS3LocationData("FSBT: Titanite Chunk - crow for Black Firebomb", "Titanite Chunk",
+ missable=True),
+ DS3LocationData("FSBT: Iron Helm - crow for Lightning Urn", "Iron Helm", missable=True),
+ DS3LocationData("FSBT: Twinkling Titanite - crow for Prism Stone", "Twinkling Titanite",
+ missable=True),
+ DS3LocationData("FSBT: Iron Leggings - crow for Seed of a Giant Tree", "Iron Leggings",
+ missable=True),
+ DS3LocationData("FSBT: Lightning Gem - crow for Xanthous Crown", "Lightning Gem",
+ missable=True),
+ DS3LocationData("FSBT: Twinkling Titanite - crow for Large Leather Shield",
+ "Twinkling Titanite", missable=True),
+ DS3LocationData("FSBT: Blessed Gem - crow for Moaning Shield", "Blessed Gem",
+ missable=True),
],
"High Wall of Lothric": [
- DS3LocationData("HWL: Deep Battle Axe", "Deep Battle Axe", DS3LocationCategory.WEAPON),
- DS3LocationData("HWL: Club", "Club", DS3LocationCategory.WEAPON),
- DS3LocationData("HWL: Claymore", "Claymore", DS3LocationCategory.WEAPON),
- DS3LocationData("HWL: Binoculars", "Binoculars", DS3LocationCategory.MISC),
- DS3LocationData("HWL: Longbow", "Longbow", DS3LocationCategory.WEAPON),
- DS3LocationData("HWL: Mail Breaker", "Mail Breaker", DS3LocationCategory.WEAPON),
- DS3LocationData("HWL: Broadsword", "Broadsword", DS3LocationCategory.WEAPON),
- DS3LocationData("HWL: Silver Eagle Kite Shield", "Silver Eagle Kite Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("HWL: Astora's Straight Sword", "Astora's Straight Sword", DS3LocationCategory.WEAPON),
- DS3LocationData("HWL: Cell Key", "Cell Key", DS3LocationCategory.KEY),
- DS3LocationData("HWL: Rapier", "Rapier", DS3LocationCategory.WEAPON),
- DS3LocationData("HWL: Lucerne", "Lucerne", DS3LocationCategory.WEAPON),
- DS3LocationData("HWL: Small Lothric Banner", "Small Lothric Banner", DS3LocationCategory.KEY),
- DS3LocationData("HWL: Basin of Vows", "Basin of Vows", DS3LocationCategory.KEY),
- DS3LocationData("HWL: Soul of Boreal Valley Vordt", "Soul of Boreal Valley Vordt", DS3LocationCategory.BOSS),
- DS3LocationData("HWL: Soul of the Dancer", "Soul of the Dancer", DS3LocationCategory.BOSS),
- DS3LocationData("HWL: Way of Blue", "Way of Blue", DS3LocationCategory.MISC),
- DS3LocationData("HWL: Greirat's Ashes", "Greirat's Ashes", DS3LocationCategory.NPC),
- DS3LocationData("HWL: Blue Tearstone Ring", "Blue Tearstone Ring", DS3LocationCategory.NPC),
+ DS3LocationData("HWL: Soul of Boreal Valley Vordt", "Soul of Boreal Valley Vordt",
+ prominent=True, boss=True),
+ DS3LocationData("HWL: Soul of the Dancer", "Soul of the Dancer", prominent=True,
+ boss=True),
+ DS3LocationData("HWL: Basin of Vows - Emma", "Basin of Vows", prominent=True,
+ progression=True, conditional=True),
+ DS3LocationData("HWL: Small Lothric Banner - Emma", "Small Lothric Banner",
+ prominent=True, progression=True),
+ DS3LocationData("HWL: Green Blossom - fort walkway, hall behind wheel", "Green Blossom x2",
+ hidden=True),
+ DS3LocationData("HWL: Gold Pine Resin - corpse tower, drop", "Gold Pine Resin x2",
+ hidden=True),
+ DS3LocationData("HWL: Large Soul of a Deserted Corpse - flame plaza",
+ "Large Soul of a Deserted Corpse"),
+ DS3LocationData("HWL: Soul of a Deserted Corpse - by wall tower door",
+ "Soul of a Deserted Corpse"),
+ DS3LocationData("HWL: Standard Arrow - back tower", "Standard Arrow x12"),
+ DS3LocationData("HWL: Longbow - back tower", "Longbow"),
+ DS3LocationData("HWL: Firebomb - wall tower, beam", "Firebomb x3"),
+ DS3LocationData("HWL: Throwing Knife - wall tower, path to Greirat", "Throwing Knife x8"),
+ DS3LocationData("HWL: Soul of a Deserted Corpse - corpse tower, bottom floor",
+ "Soul of a Deserted Corpse"),
+ DS3LocationData("HWL: Club - flame plaza", "Club"),
+ DS3LocationData("HWL: Claymore - flame plaza", "Claymore"),
+ DS3LocationData("HWL: Ember - flame plaza", "Ember"),
+ DS3LocationData("HWL: Firebomb - corpse tower, under table", "Firebomb x2"),
+ DS3LocationData("HWL: Titanite Shard - wall tower, corner by bonfire", "Titanite Shard",
+ hidden=True),
+ DS3LocationData("HWL: Undead Hunter Charm - fort, room off entry, in pot",
+ "Undead Hunter Charm x2", hidden=True),
+ DS3LocationData("HWL: Firebomb - top of ladder to fountain", "Firebomb x3"),
+ DS3LocationData("HWL: Cell Key - fort ground, down stairs", "Cell Key"),
+ DS3LocationData("HWL: Ember - fountain #1", "Ember"),
+ DS3LocationData("HWL: Soul of a Deserted Corpse - fort entry, corner",
+ "Soul of a Deserted Corpse"),
+ DS3LocationData("HWL: Lucerne - promenade, side path", "Lucerne"),
+ DS3LocationData("HWL: Mail Breaker - wall tower, path to Greirat", "Mail Breaker"),
+ DS3LocationData("HWL: Titanite Shard - fort ground behind crates", "Titanite Shard",
+ hidden=True),
+ DS3LocationData("HWL: Rapier - fountain, corner", "Rapier"),
+ DS3LocationData("HWL: Titanite Shard - fort, room off entry", "Titanite Shard"),
+ DS3LocationData("HWL: Large Soul of a Deserted Corpse - fort roof",
+ "Large Soul of a Deserted Corpse"),
+ DS3LocationData("HWL: Black Firebomb - small roof over fountain", "Black Firebomb x3"),
+ DS3LocationData("HWL: Soul of a Deserted Corpse - path to corpse tower",
+ "Soul of a Deserted Corpse"),
+ DS3LocationData("HWL: Ember - fountain #2", "Ember"),
+ DS3LocationData("HWL: Large Soul of a Deserted Corpse - platform by fountain",
+ "Large Soul of a Deserted Corpse", hidden=True), # Easily missed turnoff
+ DS3LocationData("HWL: Binoculars - corpse tower, upper platform", "Binoculars"),
+ DS3LocationData("HWL: Ring of Sacrifice - awning by fountain",
+ "Ring of Sacrifice", hidden=True), # Easily missed turnoff
+ DS3LocationData("HWL: Throwing Knife - shortcut, lift top", "Throwing Knife x6"),
+ DS3LocationData("HWL: Soul of a Deserted Corpse - path to back tower, by lift door",
+ "Soul of a Deserted Corpse"),
+ DS3LocationData("HWL: Green Blossom - shortcut, lower courtyard", "Green Blossom x3"),
+ DS3LocationData("HWL: Broadsword - fort, room off walkway", "Broadsword"),
+ DS3LocationData("HWL: Soul of a Deserted Corpse - fountain, path to promenade",
+ "Soul of a Deserted Corpse"),
+ DS3LocationData("HWL: Firebomb - fort roof", "Firebomb x3"),
+ DS3LocationData("HWL: Soul of a Deserted Corpse - wall tower, right of exit",
+ "Soul of a Deserted Corpse"),
+ DS3LocationData("HWL: Estus Shard - fort ground, on anvil", "Estus Shard"),
+ DS3LocationData("HWL: Fleshbite Ring+1 - fort roof, jump to other roof",
+ "Fleshbite Ring+1", ngp=True, hidden=True), # Hidden jump
+ DS3LocationData("HWL: Ring of the Evil Eye+2 - fort ground, far wall",
+ "Ring of the Evil Eye+2", ngp=True, hidden=True), # In barrels
+ DS3LocationData("HWL: Silver Eagle Kite Shield - fort mezzanine",
+ "Silver Eagle Kite Shield"),
+ DS3LocationData("HWL: Astora Straight Sword - fort walkway, drop down",
+ "Astora Straight Sword", hidden=True), # Hidden fall
+ DS3LocationData("HWL: Battle Axe - flame tower, mimic", "Battle Axe",
+ static='01,0:53000960::', mimic=True),
+
+ # Only dropped after transformation
+ DS3LocationData("HWL: Ember - fort roof, transforming hollow", "Ember", hidden=True),
+ DS3LocationData("HWL: Titanite Shard - fort roof, transforming hollow", "Titanite Shard",
+ hidden=True),
+ DS3LocationData("HWL: Ember - back tower, transforming hollow", "Ember", hidden=True),
+ DS3LocationData("HWL: Titanite Shard - back tower, transforming hollow", "Titanite Shard",
+ hidden=True),
+
+ DS3LocationData("HWL: Refined Gem - promenade miniboss", "Refined Gem", miniboss=True),
+ DS3LocationData("HWL: Way of Blue - Emma", "Way of Blue"),
+ # Categorize this as an NPC item so that it doesn't get randomized if the Lift Chamber Key
+ # isn't randomized, since in that case it's missable.
+ DS3LocationData("HWL: Red Eye Orb - wall tower, miniboss", "Red Eye Orb",
+ conditional=True, miniboss=True, npc=True),
+ DS3LocationData("HWL: Raw Gem - fort roof, lizard", "Raw Gem", lizard=True),
],
"Undead Settlement": [
- DS3LocationData("US: Small Leather Shield", "Small Leather Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("US: Whip", "Whip", DS3LocationCategory.WEAPON),
- DS3LocationData("US: Reinforced Club", "Reinforced Club", DS3LocationCategory.WEAPON),
- DS3LocationData("US: Blue Wooden Shield", "Blue Wooden Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("US: Cleric Hat", "Cleric Hat", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Cleric Blue Robe", "Cleric Blue Robe", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Cleric Gloves", "Cleric Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Cleric Trousers", "Cleric Trousers", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Mortician's Ashes", "Mortician's Ashes", DS3LocationCategory.KEY),
- DS3LocationData("US: Caestus", "Caestus", DS3LocationCategory.WEAPON),
- DS3LocationData("US: Plank Shield", "Plank Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("US: Flame Stoneplate Ring", "Flame Stoneplate Ring", DS3LocationCategory.RING),
- DS3LocationData("US: Caduceus Round Shield", "Caduceus Round Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("US: Fire Clutch Ring", "Fire Clutch Ring", DS3LocationCategory.RING),
- DS3LocationData("US: Partizan", "Partizan", DS3LocationCategory.WEAPON),
- DS3LocationData("US: Bloodbite Ring", "Bloodbite Ring", DS3LocationCategory.RING),
- DS3LocationData("US: Red Hilted Halberd", "Red Hilted Halberd", DS3LocationCategory.WEAPON),
- DS3LocationData("US: Saint's Talisman", "Saint's Talisman", DS3LocationCategory.WEAPON),
- DS3LocationData("US: Irithyll Straight Sword", "Irithyll Straight Sword", DS3LocationCategory.WEAPON),
- DS3LocationData("US: Large Club", "Large Club", DS3LocationCategory.WEAPON),
- DS3LocationData("US: Northern Helm", "Northern Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Northern Armor", "Northern Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Northern Gloves", "Northern Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Northern Trousers", "Northern Trousers", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Flynn's Ring", "Flynn's Ring", DS3LocationCategory.RING),
- DS3LocationData("US: Mirrah Vest", "Mirrah Vest", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Mirrah Gloves", "Mirrah Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Mirrah Trousers", "Mirrah Trousers", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Chloranthy Ring", "Chloranthy Ring", DS3LocationCategory.RING),
- DS3LocationData("US: Loincloth", "Loincloth", DS3LocationCategory.ARMOR),
- DS3LocationData("US: Wargod Wooden Shield", "Wargod Wooden Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("US: Loretta's Bone", "Loretta's Bone", DS3LocationCategory.KEY),
- DS3LocationData("US: Hand Axe", "Hand Axe", DS3LocationCategory.WEAPON),
- DS3LocationData("US: Great Scythe", "Great Scythe", DS3LocationCategory.WEAPON),
- DS3LocationData("US: Soul of the Rotted Greatwood", "Soul of the Rotted Greatwood", DS3LocationCategory.BOSS),
- DS3LocationData("US: Hawk Ring", "Hawk Ring", DS3LocationCategory.RING),
- DS3LocationData("US: Warrior of Sunlight", "Warrior of Sunlight", DS3LocationCategory.MISC),
- DS3LocationData("US: Blessed Red and White Shield+1", "Blessed Red and White Shield+1", DS3LocationCategory.SHIELD),
- DS3LocationData("US: Irina's Ashes", "Irina's Ashes", DS3LocationCategory.NPC),
- DS3LocationData("US: Cornyx's Ashes", "Cornyx's Ashes", DS3LocationCategory.NPC),
- DS3LocationData("US: Cornyx's Wrap", "Cornyx's Wrap", DS3LocationCategory.NPC),
- DS3LocationData("US: Cornyx's Garb", "Cornyx's Garb", DS3LocationCategory.NPC),
- DS3LocationData("US: Cornyx's Skirt", "Cornyx's Skirt", DS3LocationCategory.NPC),
- DS3LocationData("US: Pyromancy Flame", "Pyromancy Flame", DS3LocationCategory.NPC),
- DS3LocationData("US: Transposing Kiln", "Transposing Kiln", DS3LocationCategory.MISC),
- DS3LocationData("US: Tower Key", "Tower Key", DS3LocationCategory.NPC),
+ DS3LocationData("US: Soul of the Rotted Greatwood", "Soul of the Rotted Greatwood",
+ prominent=True, boss=True),
+ DS3LocationData("US: Transposing Kiln - boss drop", "Transposing Kiln", boss=True),
+ # Missable because it's unavailable if you start as a Pyromancer
+ DS3LocationData("US: Pyromancy Flame - Cornyx", "Pyromancy Flame", missable=True,
+ npc=True),
+ DS3LocationData("US: Old Sage's Blindfold - kill Cornyx", "Old Sage's Blindfold",
+ npc=True),
+ DS3LocationData("US: Cornyx's Garb - kill Cornyx", "Cornyx's Garb",
+ static='02,0:50006141::', npc=True),
+ DS3LocationData("US: Cornyx's Wrap - kill Cornyx", "Cornyx's Wrap",
+ static='02,0:50006141::', npc=True),
+ DS3LocationData("US: Cornyx's Skirt - kill Cornyx", "Cornyx's Skirt",
+ static='02,0:50006141::', npc=True),
+ DS3LocationData("US: Tower Key - kill Irina", "Tower Key", missable=True, npc=True),
+ DS3LocationData("US: Flynn's Ring - tower village, rooftop", "Flynn's Ring"),
+ DS3LocationData("US: Undead Bone Shard - by white tree", "Undead Bone Shard"),
+ DS3LocationData("US: Alluring Skull - foot, behind carriage", "Alluring Skull x2"),
+ DS3LocationData("US: Mortician's Ashes - graveyard by white tree", "Mortician's Ashes",
+ progression=True),
+ DS3LocationData("US: Homeward Bone - tower village, jump from roof", "Homeward Bone x2",
+ static='02,0:53100040::', hidden=True), # Hidden fall
+ DS3LocationData("US: Caduceus Round Shield - right after stable exit",
+ "Caduceus Round Shield"),
+ DS3LocationData("US: Ember - tower basement, miniboss", "Ember"),
+ DS3LocationData("US: Soul of an Unknown Traveler - chasm crypt",
+ "Soul of an Unknown Traveler"),
+ DS3LocationData("US: Repair Powder - first building, balcony", "Repair Powder x2"),
+ DS3LocationData("US: Homeward Bone - stable roof", "Homeward Bone x2",
+ static='02,0:53100090::'),
+ DS3LocationData("US: Titanite Shard - back alley, side path", "Titanite Shard"),
+ DS3LocationData("US: Wargod Wooden Shield - Pit of Hollows", "Wargod Wooden Shield"),
+ DS3LocationData("US: Large Soul of a Deserted Corpse - on the way to tower, by well",
+ "Large Soul of a Deserted Corpse"),
+ DS3LocationData("US: Ember - bridge on the way to tower", "Ember"),
+ DS3LocationData("US: Large Soul of a Deserted Corpse - stable",
+ "Large Soul of a Deserted Corpse"),
+ DS3LocationData("US: Titanite Shard - porch after burning tree", "Titanite Shard"),
+ DS3LocationData("US: Alluring Skull - tower village building, upstairs",
+ "Alluring Skull x2"),
+ DS3LocationData("US: Charcoal Pine Bundle - first building, middle floor",
+ "Charcoal Pine Bundle x2"),
+ DS3LocationData("US: Blue Wooden Shield - graveyard by white tree", "Blue Wooden Shield"),
+ DS3LocationData("US: Cleric Hat - graveyard by white tree", "Cleric Hat"),
+ DS3LocationData("US: Cleric Blue Robe - graveyard by white tree", "Cleric Blue Robe"),
+ DS3LocationData("US: Cleric Gloves - graveyard by white tree", "Cleric Gloves"),
+ DS3LocationData("US: Cleric Trousers - graveyard by white tree", "Cleric Trousers"),
+ DS3LocationData("US: Soul of an Unknown Traveler - portcullis by burning tree",
+ "Soul of an Unknown Traveler"),
+ DS3LocationData("US: Charcoal Pine Resin - hanging corpse room", "Charcoal Pine Resin x2"),
+ DS3LocationData("US: Loincloth - by Velka statue", "Loincloth"),
+ DS3LocationData("US: Bloodbite Ring - miniboss in sewer", "Bloodbite Ring",
+ miniboss=True), # Giant Rat drop
+ DS3LocationData("US: Charcoal Pine Bundle - first building, bottom floor",
+ "Charcoal Pine Bundle x2"),
+ DS3LocationData("US: Soul of an Unknown Traveler - back alley, past crates",
+ "Soul of an Unknown Traveler", hidden=True),
+ DS3LocationData("US: Titanite Shard - back alley, up ladder", "Titanite Shard"),
+ DS3LocationData("US: Red Hilted Halberd - chasm crypt", "Red Hilted Halberd"),
+ DS3LocationData("US: Rusted Coin - awning above Dilapidated Bridge", "Rusted Coin x2"),
+ DS3LocationData("US: Caestus - sewer", "Caestus"),
+ DS3LocationData("US: Saint's Talisman - chasm, by ladder", "Saint's Talisman"),
+ DS3LocationData("US: Alluring Skull - on the way to tower, behind building",
+ "Alluring Skull x3"),
+ DS3LocationData("US: Large Club - tower village, by miniboss", "Large Club"),
+ DS3LocationData("US: Titanite Shard - chasm #1", "Titanite Shard"),
+ DS3LocationData("US: Titanite Shard - chasm #2", "Titanite Shard"),
+ DS3LocationData("US: Fading Soul - outside stable", "Fading Soul"),
+ DS3LocationData("US: Titanite Shard - lower path to Cliff Underside", "Titanite Shard",
+ hidden=True), # hidden fall
+ DS3LocationData("US: Hand Axe - by Cornyx", "Hand Axe"),
+ DS3LocationData("US: Soul of an Unknown Traveler - pillory past stable",
+ "Soul of an Unknown Traveler"),
+ DS3LocationData("US: Ember - by stairs to boss", "Ember"),
+ DS3LocationData("US: Mirrah Vest - tower village, jump from roof", "Mirrah Vest",
+ hidden=True), # Hidden fall
+ DS3LocationData("US: Mirrah Gloves - tower village, jump from roof", "Mirrah Gloves",
+ hidden=True), # Hidden fall
+ DS3LocationData("US: Mirrah Trousers - tower village, jump from roof", "Mirrah Trousers",
+ hidden=True), # Hidden fall
+ DS3LocationData("US: Plank Shield - outside stable, by NPC", "Plank Shield"),
+ DS3LocationData("US: Red Bug Pellet - tower village building, basement",
+ "Red Bug Pellet x2"),
+ DS3LocationData("US: Chloranthy Ring - tower village, jump from roof", "Chloranthy Ring",
+ hidden=True), # Hidden fall
+ DS3LocationData("US: Fire Clutch Ring - wooden walkway past stable", "Fire Clutch Ring"),
+ DS3LocationData("US: Estus Shard - under burning tree", "Estus Shard"),
+ DS3LocationData("US: Firebomb - stable roof", "Firebomb x6"),
+ # In enemy rando, the enemy may not burst through the wall and make this room obvious
+ DS3LocationData("US: Whip - back alley, behind wooden wall", "Whip", hidden=True),
+ DS3LocationData("US: Great Scythe - building by white tree, balcony", "Great Scythe"),
+ DS3LocationData("US: Homeward Bone - foot, drop overlook", "Homeward Bone",
+ static='02,0:53100540::'),
+ DS3LocationData("US: Large Soul of a Deserted Corpse - around corner by Cliff Underside",
+ "Large Soul of a Deserted Corpse", hidden=True), # Hidden corner
+ DS3LocationData("US: Ember - behind burning tree", "Ember"),
+ DS3LocationData("US: Large Soul of a Deserted Corpse - across from Foot of the High Wall",
+ "Large Soul of a Deserted Corpse"),
+ DS3LocationData("US: Fading Soul - by white tree", "Fading Soul"),
+ DS3LocationData("US: Young White Branch - by white tree #1", "Young White Branch"),
+ DS3LocationData("US: Ember - by white tree", "Ember"),
+ DS3LocationData("US: Large Soul of a Deserted Corpse - by white tree",
+ "Large Soul of a Deserted Corpse"),
+ DS3LocationData("US: Young White Branch - by white tree #2", "Young White Branch"),
+ DS3LocationData("US: Reinforced Club - by white tree", "Reinforced Club"),
+ DS3LocationData("US: Soul of a Nameless Soldier - top of tower",
+ "Soul of a Nameless Soldier"),
+ DS3LocationData("US: Loretta's Bone - first building, hanging corpse on balcony",
+ "Loretta's Bone"),
+ DS3LocationData("US: Northern Helm - tower village, hanging corpse", "Northern Helm"),
+ DS3LocationData("US: Northern Armor - tower village, hanging corpse", "Northern Armor"),
+ DS3LocationData("US: Northern Gloves - tower village, hanging corpse", "Northern Gloves"),
+ DS3LocationData("US: Northern Trousers - tower village, hanging corpse",
+ "Northern Trousers"),
+ DS3LocationData("US: Partizan - hanging corpse above Cliff Underside", "Partizan",
+ missable=True), # requires projectile
+ DS3LocationData("US: Flame Stoneplate Ring - hanging corpse by Mound-Maker transport",
+ "Flame Stoneplate Ring"),
+ DS3LocationData("US: Red and White Shield - chasm, hanging corpse", "Red and White Shield",
+ static="02,0:53100740::", missable=True), # requires projectile
+ DS3LocationData("US: Small Leather Shield - first building, hanging corpse by entrance",
+ "Small Leather Shield"),
+ DS3LocationData("US: Pale Tongue - tower village, hanging corpse", "Pale Tongue"),
+ DS3LocationData("US: Large Soul of a Deserted Corpse - hanging corpse room, over stairs",
+ "Large Soul of a Deserted Corpse"),
+ DS3LocationData("US: Kukri - hanging corpse above burning tree", "Kukri x9",
+ missable=True), # requires projectile
+ DS3LocationData("US: Life Ring+1 - tower on the way to village", "Life Ring+1", ngp=True),
+ DS3LocationData("US: Poisonbite Ring+1 - graveyard by white tree, near well",
+ "Poisonbite Ring+1", ngp=True),
+ DS3LocationData("US: Covetous Silver Serpent Ring+2 - tower village, drop down from roof",
+ "Covetous Silver Serpent Ring+2", ngp=True, hidden=True), # Hidden fall
+ DS3LocationData("US: Human Pine Resin - tower village building, chest upstairs",
+ "Human Pine Resin x4"),
+ DS3LocationData("US: Homeward Bone - tower village, right at start", "Homeward Bone",
+ static='02,0:53100540::'),
+ DS3LocationData("US: Irithyll Straight Sword - miniboss drop, by Road of Sacrifices",
+ "Irithyll Straight Sword", miniboss=True),
+ DS3LocationData("US: Fire Gem - tower village, miniboss drop", "Fire Gem", miniboss=True),
+ DS3LocationData("US: Warrior of Sunlight - hanging corpse room, drop through hole",
+ "Warrior of Sunlight", hidden=True), # hidden fall
+ DS3LocationData("US: Mound-makers - Hodrick", "Mound-makers", missable=True),
+ DS3LocationData("US: Sharp Gem - lizard by Dilapidated Bridge", "Sharp Gem", lizard=True),
+ DS3LocationData("US: Heavy Gem - chasm, lizard", "Heavy Gem", lizard=True),
+ DS3LocationData("US: Siegbräu - Siegward", "Siegbräu", missable=True, npc=True),
+ DS3LocationData("US: Heavy Gem - Hawkwood", "Heavy Gem", static='00,0:50006070::',
+ missable=True, npc=True), # Hawkwood (quest, after Greatwood or Sage)
+ DS3LocationData("US -> RS", None),
+
+ # Yoel/Yuria of Londor
+ DS3LocationData("FS: Soul Arrow - Yoel/Yuria", "Soul Arrow",
+ static='99,0:-1:50000,110000,70000116:', missable=True, npc=True,
+ shop=True),
+ DS3LocationData("FS: Heavy Soul Arrow - Yoel/Yuria", "Heavy Soul Arrow",
+ static='99,0:-1:50000,110000,70000116:',
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Magic Weapon - Yoel/Yuria", "Magic Weapon",
+ static='99,0:-1:50000,110000,70000116:', missable=True, npc=True,
+ shop=True),
+ DS3LocationData("FS: Magic Shield - Yoel/Yuria", "Magic Shield",
+ static='99,0:-1:50000,110000,70000116:', missable=True, npc=True,
+ shop=True),
+ DS3LocationData("FS: Soul Greatsword - Yoel/Yuria", "Soul Greatsword",
+ static='99,0:-1:50000,110000,70000450,70000475:', missable=True,
+ npc=True, shop=True),
+ DS3LocationData("FS: Dark Hand - Yoel/Yuria", "Dark Hand", missable=True, npc=True),
+ DS3LocationData("FS: Untrue White Ring - Yoel/Yuria", "Untrue White Ring", missable=True,
+ npc=True),
+ DS3LocationData("FS: Untrue Dark Ring - Yoel/Yuria", "Untrue Dark Ring", missable=True,
+ npc=True),
+ DS3LocationData("FS: Londor Braille Divine Tome - Yoel/Yuria", "Londor Braille Divine Tome",
+ static='99,0:-1:40000,110000,70000116:', missable=True, npc=True),
+ DS3LocationData("FS: Darkdrift - Yoel/Yuria", "Darkdrift", missable=True, drop=True,
+ npc=True), # kill her or kill Soul of Cinder
+
+ # Cornyx of the Great Swamp
+ # These aren't missable because the Shrine Handmaid will carry them if you kill Cornyx.
+ DS3LocationData("FS: Fireball - Cornyx", "Fireball", npc=True, shop=True),
+ DS3LocationData("FS: Fire Surge - Cornyx", "Fire Surge", npc=True, shop=True),
+ DS3LocationData("FS: Great Combustion - Cornyx", "Great Combustion", npc=True,
+ shop=True),
+ DS3LocationData("FS: Flash Sweat - Cornyx", "Flash Sweat", npc=True, shop=True),
+ # These are missable if you kill Cornyx before giving him the right tomes.
+ DS3LocationData("FS: Poison Mist - Cornyx for Great Swamp Tome", "Poison Mist",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Fire Orb - Cornyx for Great Swamp Tome", "Fire Orb", missable=True,
+ npc=True, shop=True),
+ DS3LocationData("FS: Profuse Sweat - Cornyx for Great Swamp Tome", "Profuse Sweat",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Bursting Fireball - Cornyx for Great Swamp Tome", "Bursting Fireball",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Acid Surge - Cornyx for Carthus Tome", "Acid Surge", missable=True,
+ npc=True, shop=True),
+ DS3LocationData("FS: Carthus Flame Arc - Cornyx for Carthus Tome", "Carthus Flame Arc",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Carthus Beacon - Cornyx for Carthus Tome", "Carthus Beacon",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Great Chaos Fire Orb - Cornyx for Izalith Tome",
+ "Great Chaos Fire Orb", missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Chaos Storm - Cornyx for Izalith Tome", "Chaos Storm", missable=True,
+ npc=True, shop=True),
+
+ # Irina of Carim
+ # These aren't in their own location because you don't actually need the Grave Key to access
+ # Irena—you can just fall down the cliff near Eygon.
+ DS3LocationData("FS: Saint's Ring - Irina", "Saint's Ring", npc=True, shop=True),
+ DS3LocationData("FS: Heal - Irina", "Heal", npc=True, shop=True),
+ DS3LocationData("FS: Replenishment - Irina", "Replenishment", npc=True, shop=True),
+ DS3LocationData("FS: Caressing Tears - Irina", "Caressing Tears", npc=True, shop=True),
+ DS3LocationData("FS: Homeward - Irina", "Homeward", npc=True, shop=True),
+ DS3LocationData("FS: Med Heal - Irina for Tome of Carim", "Med Heal", missable=True,
+ npc=True, shop=True),
+ DS3LocationData("FS: Tears of Denial - Irina for Tome of Carim", "Tears of Denial",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Force - Irina for Tome of Carim", "Force", missable=True, npc=True,
+ shop=True),
+ DS3LocationData("FS: Bountiful Light - Irina for Tome of Lothric", "Bountiful Light",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Magic Barrier - Irina for Tome of Lothric", "Magic Barrier",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Blessed Weapon - Irina for Tome of Lothric", "Blessed Weapon",
+ missable=True, npc=True, shop=True),
],
"Road of Sacrifices": [
- DS3LocationData("RS: Brigand Twindaggers", "Brigand Twindaggers", DS3LocationCategory.WEAPON),
- DS3LocationData("RS: Brigand Hood", "Brigand Hood", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Brigand Armor", "Brigand Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Brigand Gauntlets", "Brigand Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Brigand Trousers", "Brigand Trousers", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Butcher Knife", "Butcher Knife", DS3LocationCategory.WEAPON),
- DS3LocationData("RS: Brigand Axe", "Brigand Axe", DS3LocationCategory.WEAPON),
- DS3LocationData("RS: Braille Divine Tome of Carim", "Braille Divine Tome of Carim", DS3LocationCategory.MISC),
- DS3LocationData("RS: Morne's Ring", "Morne's Ring", DS3LocationCategory.RING),
- DS3LocationData("RS: Twin Dragon Greatshield", "Twin Dragon Greatshield", DS3LocationCategory.SHIELD),
- DS3LocationData("RS: Heretic's Staff", "Heretic's Staff", DS3LocationCategory.WEAPON),
- DS3LocationData("RS: Sorcerer Hood", "Sorcerer Hood", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Sorcerer Robe", "Sorcerer Robe", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Sorcerer Gloves", "Sorcerer Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Sorcerer Trousers", "Sorcerer Trousers", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Sage Ring", "Sage Ring", DS3LocationCategory.RING),
- DS3LocationData("RS: Fallen Knight Helm", "Fallen Knight Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Fallen Knight Armor", "Fallen Knight Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Fallen Knight Gauntlets", "Fallen Knight Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Fallen Knight Trousers", "Fallen Knight Trousers", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Conjurator Hood", "Conjurator Hood", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Conjurator Robe", "Conjurator Robe", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Conjurator Manchettes", "Conjurator Manchettes", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Conjurator Boots", "Conjurator Boots", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Great Swamp Pyromancy Tome", "Great Swamp Pyromancy Tome", DS3LocationCategory.MISC),
- DS3LocationData("RS: Great Club", "Great Club", DS3LocationCategory.WEAPON),
- DS3LocationData("RS: Exile Greatsword", "Exile Greatsword", DS3LocationCategory.WEAPON),
- DS3LocationData("RS: Farron Coal", "Farron Coal", DS3LocationCategory.MISC),
- DS3LocationData("RS: Sellsword Twinblades", "Sellsword Twinblades", DS3LocationCategory.WEAPON),
- DS3LocationData("RS: Sellsword Helm", "Sellsword Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Sellsword Armor", "Sellsword Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Sellsword Gauntlet", "Sellsword Gauntlet", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Sellsword Trousers", "Sellsword Trousers", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Golden Falcon Shield", "Golden Falcon Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("RS: Herald Helm", "Herald Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Herald Armor", "Herald Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Herald Gloves", "Herald Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Herald Trousers", "Herald Trousers", DS3LocationCategory.ARMOR),
- DS3LocationData("RS: Grass Crest Shield", "Grass Crest Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("RS: Soul of a Crystal Sage", "Soul of a Crystal Sage", DS3LocationCategory.BOSS),
- DS3LocationData("RS: Great Swamp Ring", "Great Swamp Ring", DS3LocationCategory.RING),
- DS3LocationData("RS: Orbeck's Ashes", "Orbeck's Ashes", DS3LocationCategory.NPC),
+ DS3LocationData("RS: Soul of a Crystal Sage", "Soul of a Crystal Sage", prominent=True,
+ boss=True),
+ DS3LocationData("RS: Exile Greatsword - NPC drop by Farron Keep", "Exile Greatsword",
+ hostile_npc=True), # Exile Knight #2 drop
+ DS3LocationData("RS: Great Club - NPC drop by Farron Keep", "Great Club",
+ hostile_npc=True), # Exile Knight #1 drop
+ DS3LocationData("RS: Heysel Pick - Heysel drop", "Heysel Pick", missable=True,
+ hostile_npc=True),
+ DS3LocationData("RS: Xanthous Crown - Heysel drop", "Xanthous Crown", missable=True,
+ hostile_npc=True),
+ DS3LocationData("RS: Butcher Knife - NPC drop beneath road", "Butcher Knife",
+ hostile_npc=True), # Madwoman
+ DS3LocationData("RS: Titanite Shard - water by Halfway Fortress", "Titanite Shard"),
+ DS3LocationData("RS: Titanite Shard - woods, left of path from Halfway Fortress",
+ "Titanite Shard"),
+ DS3LocationData("RS: Green Blossom - by deep water", "Green Blossom x4"),
+ DS3LocationData("RS: Estus Shard - left of fire behind stronghold left room",
+ "Estus Shard"),
+ DS3LocationData("RS: Ring of Sacrifice - stronghold, drop from right room balcony",
+ "Ring of Sacrifice", hidden=True), # hidden fall
+ DS3LocationData("RS: Soul of an Unknown Traveler - drop along wall from Halfway Fortress",
+ "Soul of an Unknown Traveler"),
+ DS3LocationData("RS: Fallen Knight Helm - water's edge by Farron Keep",
+ "Fallen Knight Helm"),
+ DS3LocationData("RS: Fallen Knight Armor - water's edge by Farron Keep",
+ "Fallen Knight Armor"),
+ DS3LocationData("RS: Fallen Knight Gauntlets - water's edge by Farron Keep",
+ "Fallen Knight Gauntlets"),
+ DS3LocationData("RS: Fallen Knight Trousers - water's edge by Farron Keep",
+ "Fallen Knight Trousers"),
+ DS3LocationData("RS: Heretic's Staff - stronghold left room", "Heretic's Staff"),
+ DS3LocationData("RS: Large Soul of an Unknown Traveler - left of stairs to Farron Keep",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("RS: Conjurator Hood - deep water", "Conjurator Hood"),
+ DS3LocationData("RS: Conjurator Robe - deep water", "Conjurator Robe"),
+ DS3LocationData("RS: Conjurator Manchettes - deep water", "Conjurator Manchettes"),
+ DS3LocationData("RS: Conjurator Boots - deep water", "Conjurator Boots"),
+ DS3LocationData("RS: Soul of an Unknown Traveler - right of door to stronghold left",
+ "Soul of an Unknown Traveler"),
+ DS3LocationData("RS: Green Blossom - water beneath stronghold", "Green Blossom x2"),
+ DS3LocationData("RS: Great Swamp Pyromancy Tome - deep water",
+ "Great Swamp Pyromancy Tome"),
+ DS3LocationData("RS: Homeward Bone - balcony by Farron Keep", "Homeward Bone x2"),
+ DS3LocationData("RS: Titanite Shard - woods, surrounded by enemies", "Titanite Shard"),
+ DS3LocationData("RS: Twin Dragon Greatshield - woods by Crucifixion Woods bonfire",
+ "Twin Dragon Greatshield"),
+ DS3LocationData("RS: Sorcerer Hood - water beneath stronghold", "Sorcerer Hood",
+ hidden=True), # Hidden fall
+ DS3LocationData("RS: Sorcerer Robe - water beneath stronghold", "Sorcerer Robe",
+ hidden=True), # Hidden fall
+ DS3LocationData("RS: Sorcerer Gloves - water beneath stronghold", "Sorcerer Gloves",
+ hidden=True), # Hidden fall
+ DS3LocationData("RS: Sorcerer Trousers - water beneath stronghold", "Sorcerer Trousers",
+ hidden=True), # Hidden fall
+ DS3LocationData("RS: Sage Ring - water beneath stronghold", "Sage Ring",
+ hidden=True), # Hidden fall
+ DS3LocationData("RS: Grass Crest Shield - water by Crucifixion Woods bonfire",
+ "Grass Crest Shield"),
+ DS3LocationData("RS: Ember - right of fire behind stronghold left room", "Ember"),
+ DS3LocationData("RS: Blue Bug Pellet - broken stairs by Orbeck", "Blue Bug Pellet x2"),
+ DS3LocationData("RS: Soul of an Unknown Traveler - road, by wagon",
+ "Soul of an Unknown Traveler"),
+ DS3LocationData("RS: Shriving Stone - road, by start", "Shriving Stone"),
+ DS3LocationData("RS: Titanite Shard - road, on bridge after you go under",
+ "Titanite Shard"),
+ DS3LocationData("RS: Brigand Twindaggers - beneath road", "Brigand Twindaggers"),
+ DS3LocationData("RS: Braille Divine Tome of Carim - drop from bridge to Halfway Fortress",
+ "Braille Divine Tome of Carim", hidden=True), # Hidden fall
+ DS3LocationData("RS: Ember - right of Halfway Fortress entrance", "Ember"),
+ DS3LocationData("RS: Sellsword Twinblades - keep perimeter", "Sellsword Twinblades"),
+ DS3LocationData("RS: Golden Falcon Shield - path from stronghold right room to Farron Keep",
+ "Golden Falcon Shield"),
+ DS3LocationData("RS: Brigand Axe - beneath road", "Brigand Axe"),
+ DS3LocationData("RS: Brigand Hood - beneath road", "Brigand Hood"),
+ DS3LocationData("RS: Brigand Armor - beneath road", "Brigand Armor"),
+ DS3LocationData("RS: Brigand Gauntlets - beneath road", "Brigand Gauntlets"),
+ DS3LocationData("RS: Brigand Trousers - beneath road", "Brigand Trousers"),
+ DS3LocationData("RS: Morne's Ring - drop from bridge to Halfway Fortress", "Morne's Ring",
+ hidden=True), # Hidden fall
+ DS3LocationData("RS: Sellsword Helm - keep perimeter balcony", "Sellsword Helm"),
+ DS3LocationData("RS: Sellsword Armor - keep perimeter balcony", "Sellsword Armor"),
+ DS3LocationData("RS: Sellsword Gauntlet - keep perimeter balcony", "Sellsword Gauntlet"),
+ DS3LocationData("RS: Sellsword Trousers - keep perimeter balcony", "Sellsword Trousers"),
+ DS3LocationData("RS: Farron Coal - keep perimeter", "Farron Coal"),
+ DS3LocationData("RS: Chloranthy Ring+2 - road, drop across from carriage",
+ "Chloranthy Ring+2", hidden=True, ngp=True), # Hidden fall
+ DS3LocationData("RS: Lingering Dragoncrest Ring+1 - water", "Lingering Dragoncrest Ring+1",
+ ngp=True),
+ DS3LocationData("RS: Great Swamp Ring - miniboss drop, by Farron Keep",
+ "Great Swamp Ring", miniboss=True), # Giant Crab drop
+ DS3LocationData("RS: Blue Sentinels - Horace", "Blue Sentinels",
+ missable=True, npc=True), # Horace quest
+ DS3LocationData("RS: Crystal Gem - stronghold, lizard", "Crystal Gem"),
+ DS3LocationData("RS: Fading Soul - woods by Crucifixion Woods bonfire", "Fading Soul",
+ static='03,0:53300210::'),
+
+ # Orbeck shop, all missable because he'll disappear if you don't talk to him for too long or
+ # if you don't give him a scroll.
+ DS3LocationData("FS: Farron Dart - Orbeck", "Farron Dart",
+ static='99,0:-1:110000,130100,70000111:', missable=True, npc=True,
+ shop=True),
+ DS3LocationData("FS: Soul Arrow - Orbeck", "Soul Arrow",
+ static='99,0:-1:110000,130100,70000111:', missable=True, npc=True,
+ shop=True),
+ DS3LocationData("FS: Great Soul Arrow - Orbeck", "Great Soul Arrow", missable=True,
+ npc=True, shop=True),
+ DS3LocationData("FS: Heavy Soul Arrow - Orbeck", "Heavy Soul Arrow",
+ static='99,0:-1:110000,130100,70000111:', missable=True, npc=True,
+ shop=True),
+ DS3LocationData("FS: Great Heavy Soul Arrow - Orbeck", "Great Heavy Soul Arrow",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Magic Weapon - Orbeck", "Magic Weapon",
+ static='99,0:-1:110000,130100,70000111:', missable=True, npc=True,
+ shop=True),
+ DS3LocationData("FS: Magic Shield - Orbeck", "Magic Shield",
+ static='99,0:-1:110000,130100,70000111:', missable=True, npc=True,
+ shop=True),
+ DS3LocationData("FS: Spook - Orbeck", "Spook", missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Aural Decoy - Orbeck", "Aural Decoy", missable=True, npc=True,
+ shop=True),
+ DS3LocationData("FS: Soul Greatsword - Orbeck", "Soul Greatsword",
+ static='99,0:-1:110000,130100,70000111:', missable=True, npc=True),
+ DS3LocationData("FS: Farron Flashsword - Orbeck", "Farron Flashsword", missable=True,
+ npc=True, shop=True),
+ DS3LocationData("FS: Pestilent Mist - Orbeck for any scroll", "Pestilent Mist",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Great Farron Dart - Orbeck for Sage's Scroll", "Great Farron Dart",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Farron Hail - Orbeck for Sage's Scroll", "Farron Hail",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Homing Soulmass - Orbeck for Logan's Scroll", "Homing Soulmass",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Soul Spear - Orbeck for Logan's Scroll", "Soul Spear",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Homing Crystal Soulmass - Orbeck for Crystal Scroll",
+ "Homing Crystal Soulmass", missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Crystal Soul Spear - Orbeck for Crystal Scroll", "Crystal Soul Spear",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Crystal Magic Weapon - Orbeck for Crystal Scroll",
+ "Crystal Magic Weapon", missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Cast Light - Orbeck for Golden Scroll", "Cast Light", missable=True,
+ npc=True, shop=True),
+ DS3LocationData("FS: Twisted Wall of Light - Orbeck for Golden Scroll",
+ "Twisted Wall of Light", missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Hidden Weapon - Orbeck for Golden Scroll", "Hidden Weapon",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Hidden Body - Orbeck for Golden Scroll", "Hidden Body",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Repair - Orbeck for Golden Scroll", "Repair", missable=True,
+ npc=True, shop=True),
+ DS3LocationData("FS: Clandestine Coat - shop with Orbeck's Ashes", "Clandestine Coat",
+ missable=True, npc=True,
+ shop=True), # Shrine Handmaid with Orbeck's Ashes + reload
+ DS3LocationData("FS: Young Dragon Ring - Orbeck for one scroll and buying three spells",
+ "Young Dragon Ring", missable=True, npc=True),
+ DS3LocationData("FS: Slumbering Dragoncrest Ring - Orbeck for buying four specific spells",
+ "Slumbering Dragoncrest Ring", missable=True, npc=True),
+ DS3LocationData("RS -> FK", None),
+
+ # Shrine Handmaid after killing exiles
+ DS3LocationData("FS: Exile Mask - shop after killing NPCs in RS", "Exile Mask",
+ hostile_npc=True, shop=True, hidden=True),
+ DS3LocationData("FS: Exile Armor - shop after killing NPCs in RS", "Exile Armor",
+ hostile_npc=True, shop=True, hidden=True),
+ DS3LocationData("FS: Exile Gauntlets - shop after killing NPCs in RS", "Exile Gauntlets",
+ hostile_npc=True, shop=True, hidden=True),
+ DS3LocationData("FS: Exile Leggings - shop after killing NPCs in RS", "Exile Leggings",
+ hostile_npc=True, shop=True, hidden=True),
+
+ # Shrine Handmaid after killing Crystal Sage
+ DS3LocationData("FS: Sage's Big Hat - shop after killing RS boss", "Sage's Big Hat",
+ boss=True, shop=True),
+
+ # Yuria of Londor for Orbeck's Ashes
+ DS3LocationData("FS: Morion Blade - Yuria for Orbeck's Ashes", "Morion Blade",
+ missable=True, npc=True),
],
"Cathedral of the Deep": [
- DS3LocationData("CD: Paladin's Ashes", "Paladin's Ashes", DS3LocationCategory.MISC),
- DS3LocationData("CD: Spider Shield", "Spider Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("CD: Crest Shield", "Crest Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("CD: Notched Whip", "Notched Whip", DS3LocationCategory.WEAPON),
- DS3LocationData("CD: Astora Greatsword", "Astora Greatsword", DS3LocationCategory.WEAPON),
- DS3LocationData("CD: Executioner's Greatsword", "Executioner's Greatsword", DS3LocationCategory.WEAPON),
- DS3LocationData("CD: Curse Ward Greatshield", "Curse Ward Greatshield", DS3LocationCategory.SHIELD),
- DS3LocationData("CD: Saint-tree Bellvine", "Saint-tree Bellvine", DS3LocationCategory.WEAPON),
- DS3LocationData("CD: Poisonbite Ring", "Poisonbite Ring", DS3LocationCategory.RING),
- DS3LocationData("CD: Lloyd's Sword Ring", "Lloyd's Sword Ring", DS3LocationCategory.RING),
- DS3LocationData("CD: Seek Guidance", "Seek Guidance", DS3LocationCategory.SPELL),
- DS3LocationData("CD: Aldrich's Sapphire", "Aldrich's Sapphire", DS3LocationCategory.RING),
- DS3LocationData("CD: Deep Braille Divine Tome", "Deep Braille Divine Tome", DS3LocationCategory.MISC),
- DS3LocationData("CD: Saint Bident", "Saint Bident", DS3LocationCategory.WEAPON),
- DS3LocationData("CD: Maiden Hood", "Maiden Hood", DS3LocationCategory.ARMOR),
- DS3LocationData("CD: Maiden Robe", "Maiden Robe", DS3LocationCategory.ARMOR),
- DS3LocationData("CD: Maiden Gloves", "Maiden Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("CD: Maiden Skirt", "Maiden Skirt", DS3LocationCategory.ARMOR),
- DS3LocationData("CD: Drang Armor", "Drang Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("CD: Drang Gauntlets", "Drang Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("CD: Drang Shoes", "Drang Shoes", DS3LocationCategory.ARMOR),
- DS3LocationData("CD: Drang Hammers", "Drang Hammers", DS3LocationCategory.WEAPON),
- DS3LocationData("CD: Deep Ring", "Deep Ring", DS3LocationCategory.RING),
- DS3LocationData("CD: Archdeacon White Crown", "Archdeacon White Crown", DS3LocationCategory.ARMOR),
- DS3LocationData("CD: Archdeacon Holy Garb", "Archdeacon Holy Garb", DS3LocationCategory.ARMOR),
- DS3LocationData("CD: Archdeacon Skirt", "Archdeacon Skirt", DS3LocationCategory.ARMOR),
- DS3LocationData("CD: Arbalest", "Arbalest", DS3LocationCategory.WEAPON),
- DS3LocationData("CD: Small Doll", "Small Doll", DS3LocationCategory.KEY),
- DS3LocationData("CD: Soul of the Deacons of the Deep", "Soul of the Deacons of the Deep", DS3LocationCategory.BOSS),
- DS3LocationData("CD: Rosaria's Fingers", "Rosaria's Fingers", DS3LocationCategory.MISC)
+ DS3LocationData("CD: Herald Helm - path, by fire", "Herald Helm"),
+ DS3LocationData("CD: Herald Armor - path, by fire", "Herald Armor"),
+ DS3LocationData("CD: Herald Gloves - path, by fire", "Herald Gloves"),
+ DS3LocationData("CD: Herald Trousers - path, by fire", "Herald Trousers"),
+ DS3LocationData("CD: Twinkling Titanite - path, lizard #1", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("CD: Twinkling Titanite - path, lizard #2", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("CD: Small Doll - boss drop", "Small Doll", prominent=True,
+ progression=True, boss=True),
+ DS3LocationData("CD: Soul of the Deacons of the Deep", "Soul of the Deacons of the Deep",
+ boss=True),
+ DS3LocationData("CD: Black Eye Orb - Rosaria from Leonhard's quest", "Black Eye Orb",
+ missable=True, npc=True),
+ DS3LocationData("CD: Winged Spear - kill Patches", "Winged Spear", drop=True,
+ missable=True), # Patches (kill)
+ DS3LocationData("CD: Spider Shield - NPC drop on path", "Spider Shield",
+ hostile_npc=True), # Brigand
+ DS3LocationData("CD: Notched Whip - Cleansing Chapel", "Notched Whip"),
+ DS3LocationData("CD: Titanite Shard - Cleansing Chapel windowsill, by miniboss",
+ "Titanite Shard"),
+ DS3LocationData("CD: Astora Greatsword - graveyard, left of entrance", "Astora Greatsword"),
+ DS3LocationData("CD: Executioner's Greatsword - graveyard, far end",
+ "Executioner's Greatsword"),
+ DS3LocationData("CD: Undead Bone Shard - gravestone by white tree", "Undead Bone Shard"),
+ DS3LocationData("CD: Curse Ward Greatshield - by ladder from white tree to moat",
+ "Curse Ward Greatshield"),
+ DS3LocationData("CD: Titanite Shard - moat, far end", "Titanite Shard"),
+ DS3LocationData("CD: Large Soul of an Unknown Traveler - lower roofs, semicircle balcony",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("CD: Paladin's Ashes - path, guarded by lower NPC", "Paladin's Ashes",
+ progression=True),
+ DS3LocationData("CD: Arbalest - upper roofs, end of furthest buttress", "Arbalest"),
+ DS3LocationData("CD: Ember - by back door", "Ember"),
+ DS3LocationData("CD: Ember - side chapel upstairs, up ladder", "Ember"),
+ DS3LocationData("CD: Poisonbite Ring - moat, hall past miniboss", "Poisonbite Ring"),
+ DS3LocationData("CD: Drang Armor - main hall, east", "Drang Armor"),
+ DS3LocationData("CD: Ember - edge of platform before boss", "Ember"),
+ DS3LocationData("CD: Duel Charm - next to Patches in onion armor", "Duel Charm x3"),
+ DS3LocationData("CD: Seek Guidance - side chapel upstairs", "Seek Guidance"),
+ DS3LocationData("CD: Estus Shard - monument outside Cleansing Chapel", "Estus Shard"),
+ DS3LocationData("CD: Maiden Hood - main hall south", "Maiden Hood"),
+ DS3LocationData("CD: Maiden Robe - main hall south", "Maiden Robe"),
+ DS3LocationData("CD: Maiden Gloves - main hall south", "Maiden Gloves"),
+ DS3LocationData("CD: Maiden Skirt - main hall south", "Maiden Skirt"),
+ DS3LocationData("CD: Pale Tongue - upper roofs, outdoors far end", "Pale Tongue"),
+ DS3LocationData("CD: Fading Soul - graveyard, far end", "Fading Soul"),
+ DS3LocationData("CD: Blessed Gem - upper roofs, rafters", "Blessed Gem"),
+ DS3LocationData("CD: Red Bug Pellet - right of cathedral front doors", "Red Bug Pellet"),
+ DS3LocationData("CD: Soul of a Nameless Soldier - main hall south",
+ "Soul of a Nameless Soldier"),
+ DS3LocationData("CD: Duel Charm - by first elevator", "Duel Charm"),
+ DS3LocationData("CD: Large Soul of an Unknown Traveler - main hall south, side path",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("CD: Ember - side chapel, miniboss room", "Ember"),
+ DS3LocationData("CD: Repair Powder - by white tree", "Repair Powder x3"),
+ DS3LocationData("CD: Large Soul of an Unknown Traveler - by white tree #1",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("CD: Large Soul of an Unknown Traveler - by white tree #2",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("CD: Undead Hunter Charm - lower roofs, up stairs between buttresses",
+ "Undead Hunter Charm x3"),
+ DS3LocationData("CD: Red Bug Pellet - lower roofs, up stairs between buttresses",
+ "Red Bug Pellet x3"),
+ DS3LocationData("CD: Titanite Shard - outside building by white tree", "Titanite Shard",
+ hidden=True), # Easily missable side path
+ DS3LocationData("CD: Titanite Shard - moat, up a slope", "Titanite Shard"),
+ DS3LocationData("CD: Rusted Coin - left of cathedral front doors, behind crates",
+ "Rusted Coin x2", hidden=True),
+ DS3LocationData("CD: Drang Hammers - main hall east", "Drang Hammers"),
+ DS3LocationData("CD: Drang Shoes - main hall east", "Drang Shoes"),
+ DS3LocationData("CD: Large Soul of an Unknown Traveler - main hall east",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("CD: Pale Tongue - main hall east", "Pale Tongue"),
+ DS3LocationData("CD: Drang Gauntlets - main hall east", "Drang Gauntlets"),
+ DS3LocationData("CD: Soul of a Nameless Soldier - lower roofs, side room",
+ "Soul of a Nameless Soldier"),
+ DS3LocationData("CD: Exploding Bolt - ledge above main hall south", "Exploding Bolt x6"),
+ DS3LocationData("CD: Lloyd's Sword Ring - ledge above main hall south",
+ "Lloyd's Sword Ring"),
+ DS3LocationData("CD: Soul of a Nameless Soldier - ledge above main hall south",
+ "Soul of a Nameless Soldier"),
+ DS3LocationData("CD: Homeward Bone - outside main hall south door", "Homeward Bone x2"),
+ DS3LocationData("CD: Deep Gem - down stairs by first elevator", "Deep Gem"),
+ DS3LocationData("CD: Titanite Shard - path, side path by Cathedral of the Deep bonfire",
+ "Titanite Shard"),
+ DS3LocationData("CD: Large Soul of an Unknown Traveler - path, against outer wall",
+ "Large Soul of an Unknown Traveler"),
+ # Before the stairs leading down into the Deacons fight
+ DS3LocationData("CD: Ring of the Evil Eye+1 - by stairs to boss", "Ring of the Evil Eye+1",
+ ngp=True),
+ DS3LocationData("CD: Ring of Favor+2 - upper roofs, on buttress", "Ring of Favor+2",
+ hidden=True, ngp=True), # Hidden fall
+ DS3LocationData("CD: Crest Shield - path, drop down by Cathedral of the Deep bonfire",
+ "Crest Shield", hidden=True), # Hidden fall
+ DS3LocationData("CD: Young White Branch - by white tree #1", "Young White Branch"),
+ DS3LocationData("CD: Young White Branch - by white tree #2", "Young White Branch"),
+ DS3LocationData("CD: Saint-tree Bellvine - moat, by water", "Saint-tree Bellvine"),
+ DS3LocationData("CD: Saint Bident - outside main hall south door", "Saint Bident"),
+ # Archdeacon set is hidden because you have to return to a cleared area
+ DS3LocationData("CD: Archdeacon White Crown - boss room after killing boss",
+ "Archdeacon White Crown", boss=True, hidden=True),
+ DS3LocationData("CD: Archdeacon Holy Garb - boss room after killing boss",
+ "Archdeacon Holy Garb", boss=True, hidden=True),
+ DS3LocationData("CD: Archdeacon Skirt - boss room after killing boss", "Archdeacon Skirt",
+ boss=True, hidden=True),
+ # Heysel items may not be missable, but it's not clear what causes them to trigger
+ DS3LocationData("CD: Heysel Pick - Heysel Corpse-Grub in Rosaria's Bed Chamber",
+ "Heysel Pick", missable=True),
+ DS3LocationData("CD: Xanthous Crown - Heysel Corpse-Grub in Rosaria's Bed Chamber",
+ "Xanthous Crown", missable=True),
+ DS3LocationData("CD: Deep Ring - upper roofs, passive mob drop in first tower", "Deep Ring",
+ drop=True, hidden=True),
+ DS3LocationData("CD: Deep Braille Divine Tome - mimic by side chapel",
+ "Deep Braille Divine Tome", mimic=True),
+ DS3LocationData("CD: Red Sign Soapstone - passive mob drop by Rosaria's Bed Chamber",
+ "Red Sign Soapstone", drop=True, hidden=True),
+ DS3LocationData("CD: Aldrich's Sapphire - side chapel, miniboss drop", "Aldrich's Sapphire",
+ miniboss=True), # Deep Accursed Drop
+ DS3LocationData("CD: Titanite Scale - moat, miniboss drop", "Titanite Scale",
+ miniboss=True), # Ravenous Crystal Lizard drop
+ DS3LocationData("CD: Twinkling Titanite - moat, lizard #1", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("CD: Twinkling Titanite - moat, lizard #2", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("CD: Rosaria's Fingers - Rosaria", "Rosaria's Fingers",
+ hidden=True), # Hidden fall
+ DS3LocationData("CD -> PW1", None),
+
+ # Longfinger Kirk drops
+ DS3LocationData("CD: Barbed Straight Sword - Kirk drop", "Barbed Straight Sword",
+ missable=True, hostile_npc=True),
+ DS3LocationData("CD: Spiked Shield - Kirk drop", "Spiked Shield", missable=True,
+ hostile_npc=True),
+ # In Rosaria's Bed Chamber
+ DS3LocationData("CD: Helm of Thorns - Rosaria's Bed Chamber after killing Kirk",
+ "Helm of Thorns", missable=True, hostile_npc=True),
+ DS3LocationData("CD: Armor of Thorns - Rosaria's Bed Chamber after killing Kirk",
+ "Armor of Thorns", missable=True, hostile_npc=True),
+ DS3LocationData("CD: Gauntlets of Thorns - Rosaria's Bed Chamber after killing Kirk",
+ "Gauntlets of Thorns", missable=True, hostile_npc=True),
+ DS3LocationData("CD: Leggings of Thorns - Rosaria's Bed Chamber after killing Kirk",
+ "Leggings of Thorns", missable=True, hostile_npc=True),
+
+ # Unbreakable Patches
+ DS3LocationData("CD: Rusted Coin - don't forgive Patches", "Rusted Coin",
+ missable=True, npc=True),
+ DS3LocationData("FS: Rusted Gold Coin - don't forgive Patches", "Rusted Gold Coin",
+ static='99,0:50006201::', missable=True,
+ npc=True), # Don't forgive Patches
+ DS3LocationData("CD: Shotel - Patches", "Shotel", missable=True, npc=True, shop=True),
+ DS3LocationData("CD: Ember - Patches", "Ember", missable=True, npc=True, shop=True),
+ DS3LocationData("CD: Horsehoof Ring - Patches", "Horsehoof Ring", missable=True,
+ npc=True, drop=True, shop=True), # (kill or buy)
],
"Farron Keep": [
- DS3LocationData("FK: Ragged Mask", "Ragged Mask", DS3LocationCategory.ARMOR),
- DS3LocationData("FK: Iron Flesh", "Iron Flesh", DS3LocationCategory.SPELL),
- DS3LocationData("FK: Golden Scroll", "Golden Scroll", DS3LocationCategory.MISC),
- DS3LocationData("FK: Antiquated Dress", "Antiquated Dress", DS3LocationCategory.ARMOR),
- DS3LocationData("FK: Antiquated Gloves", "Antiquated Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("FK: Antiquated Skirt", "Antiquated Skirt", DS3LocationCategory.ARMOR),
- DS3LocationData("FK: Nameless Knight Helm", "Nameless Knight Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("FK: Nameless Knight Armor", "Nameless Knight Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("FK: Nameless Knight Gauntlets", "Nameless Knight Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("FK: Nameless Knight Leggings", "Nameless Knight Leggings", DS3LocationCategory.ARMOR),
- DS3LocationData("FK: Sunlight Talisman", "Sunlight Talisman", DS3LocationCategory.WEAPON),
- DS3LocationData("FK: Wolf's Blood Swordgrass", "Wolf's Blood Swordgrass", DS3LocationCategory.MISC),
- DS3LocationData("FK: Greatsword", "Greatsword", DS3LocationCategory.WEAPON),
- DS3LocationData("FK: Sage's Coal", "Sage's Coal", DS3LocationCategory.MISC),
- DS3LocationData("FK: Stone Parma", "Stone Parma", DS3LocationCategory.SHIELD),
- DS3LocationData("FK: Sage's Scroll", "Sage's Scroll", DS3LocationCategory.MISC),
- DS3LocationData("FK: Crown of Dusk", "Crown of Dusk", DS3LocationCategory.ARMOR),
- DS3LocationData("FK: Lingering Dragoncrest Ring", "Lingering Dragoncrest Ring", DS3LocationCategory.RING),
- DS3LocationData("FK: Pharis's Hat", "Pharis's Hat", DS3LocationCategory.ARMOR),
- DS3LocationData("FK: Black Bow of Pharis", "Black Bow of Pharis", DS3LocationCategory.WEAPON),
- DS3LocationData("FK: Dreamchaser's Ashes", "Dreamchaser's Ashes", DS3LocationCategory.MISC),
- DS3LocationData("FK: Great Axe", "Great Axe", DS3LocationCategory.WEAPON),
- DS3LocationData("FK: Dragon Crest Shield", "Dragon Crest Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("FK: Lightning Spear", "Lightning Spear", DS3LocationCategory.SPELL),
- DS3LocationData("FK: Atonement", "Atonement", DS3LocationCategory.SPELL),
- DS3LocationData("FK: Great Magic Weapon", "Great Magic Weapon", DS3LocationCategory.SPELL),
- DS3LocationData("FK: Cinders of a Lord - Abyss Watcher", "Cinders of a Lord - Abyss Watcher", DS3LocationCategory.KEY),
- DS3LocationData("FK: Soul of the Blood of the Wolf", "Soul of the Blood of the Wolf", DS3LocationCategory.BOSS),
- DS3LocationData("FK: Soul of a Stray Demon", "Soul of a Stray Demon", DS3LocationCategory.BOSS),
- DS3LocationData("FK: Watchdogs of Farron", "Watchdogs of Farron", DS3LocationCategory.MISC),
+ DS3LocationData("FK: Lightning Spear - upper keep, far side of the wall",
+ "Lightning Spear"),
+ DS3LocationData("FK: Dragon Crest Shield - upper keep, far side of the wall",
+ "Dragon Crest Shield"),
+ DS3LocationData("FK: Soul of the Blood of the Wolf", "Soul of the Blood of the Wolf",
+ boss=True),
+ DS3LocationData("FK: Cinders of a Lord - Abyss Watcher",
+ "Cinders of a Lord - Abyss Watcher",
+ static="03,0:50002100::", prominent=True, progression=True,
+ boss=True),
+ DS3LocationData("FK: Manikin Claws - Londor Pale Shade drop", "Manikin Claws",
+ missable=True, hostile_npc=True,
+ npc=True), # Londor Pale Shade (if Yoel/Yuria hostile)
+ DS3LocationData("FK: Purple Moss Clump - keep ruins, ritual island",
+ "Purple Moss Clump x2"),
+ DS3LocationData("FK: Purple Moss Clump - ramp directly in front of Farron Keep bonfire",
+ "Purple Moss Clump x4"),
+ DS3LocationData("FK: Greatsword - ramp by keep ruins ritual island", "Greatsword"),
+ DS3LocationData("FK: Hollow Gem - perimeter, drop down into swamp", "Hollow Gem",
+ hidden=True),
+ DS3LocationData("FK: Purple Moss Clump - Farron Keep bonfire, around right corner",
+ "Purple Moss Clump x3"),
+ DS3LocationData("FK: Undead Bone Shard - pavilion by keep ruins bonfire island",
+ "Undead Bone Shard"),
+ DS3LocationData("FK: Atonement - perimeter, drop down into swamp", "Atonement",
+ hidden=True),
+ DS3LocationData("FK: Titanite Shard - by ladder to keep proper", "Titanite Shard"),
+ DS3LocationData("FK: Iron Flesh - Farron Keep bonfire, right after exit", "Iron Flesh"),
+ DS3LocationData("FK: Stone Parma - near wall by left island", "Stone Parma"),
+ DS3LocationData("FK: Rotten Pine Resin - left island, behind fire", "Rotten Pine Resin x2"),
+ DS3LocationData("FK: Titanite Shard - between left island and keep ruins", "Titanite Shard"),
+ DS3LocationData("FK: Rusted Gold Coin - right island, behind wall", "Rusted Gold Coin",
+ hidden=True),
+ DS3LocationData("FK: Nameless Knight Helm - corner of keep and right island",
+ "Nameless Knight Helm"),
+ DS3LocationData("FK: Nameless Knight Armor - corner of keep and right island",
+ "Nameless Knight Armor"),
+ DS3LocationData("FK: Nameless Knight Gauntlets - corner of keep and right island",
+ "Nameless Knight Gauntlets"),
+ DS3LocationData("FK: Nameless Knight Leggings - corner of keep and right island",
+ "Nameless Knight Leggings"),
+ DS3LocationData("FK: Shriving Stone - perimeter, just past stone doors", "Shriving Stone"),
+ DS3LocationData("FK: Repair Powder - outside hidden cave", "Repair Powder x4",
+ hidden=True),
+ DS3LocationData("FK: Golden Scroll - hidden cave", "Golden Scroll", hidden=True),
+ DS3LocationData("FK: Sage's Scroll - near wall by keep ruins bonfire island",
+ "Sage's Scroll"),
+ DS3LocationData("FK: Dreamchaser's Ashes - keep proper, illusory wall",
+ "Dreamchaser's Ashes", progression=True, hidden=True),
+ DS3LocationData("FK: Titanite Shard - keep ruins bonfire island, under ramp",
+ "Titanite Shard"),
+ DS3LocationData("FK: Wolf's Blood Swordgrass - by ladder to keep proper",
+ "Wolf's Blood Swordgrass"),
+ DS3LocationData("FK: Great Magic Weapon - perimeter, by door to Road of Sacrifices",
+ "Great Magic Weapon"),
+ DS3LocationData("FK: Ember - perimeter, path to boss", "Ember"),
+ DS3LocationData("FK: Titanite Shard - swamp by right island", "Titanite Shard x2"),
+ DS3LocationData("FK: Titanite Shard - by left island stairs", "Titanite Shard"),
+ DS3LocationData("FK: Titanite Shard - by keep ruins ritual island stairs", "Titanite Shard"),
+ DS3LocationData("FK: Black Bug Pellet - perimeter, hill by boss door",
+ "Black Bug Pellet x3"),
+ DS3LocationData("FK: Rotten Pine Resin - outside pavilion by left island",
+ "Rotten Pine Resin x4"),
+ DS3LocationData("FK: Poison Gem - near wall by keep ruins bridge", "Poison Gem"),
+ DS3LocationData("FK: Ragged Mask - Farron Keep bonfire, around left corner", "Ragged Mask"),
+ DS3LocationData("FK: Estus Shard - between Farron Keep bonfire and left island",
+ "Estus Shard"),
+ DS3LocationData("FK: Homeward Bone - right island, behind fire", "Homeward Bone x2"),
+ DS3LocationData("FK: Titanite Shard - Farron Keep bonfire, left after exit",
+ "Titanite Shard"),
+ DS3LocationData("FK: Large Soul of a Nameless Soldier - corner of keep and right island",
+ "Large Soul of a Nameless Soldier", hidden=True), # Tricky corner to spot
+ DS3LocationData("FK: Prism Stone - by left island stairs", "Prism Stone x10"),
+ DS3LocationData("FK: Large Soul of a Nameless Soldier - near wall by right island",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("FK: Sage's Coal - pavilion by left island", "Sage's Coal"),
+ DS3LocationData("FK: Gold Pine Bundle - by white tree", "Gold Pine Bundle x6"),
+ DS3LocationData("FK: Ember - by white tree", "Ember"),
+ DS3LocationData("FK: Soul of a Nameless Soldier - by white tree", "Soul of a Nameless Soldier"),
+ DS3LocationData("FK: Large Soul of an Unknown Traveler - by white tree",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("FK: Greataxe - upper keep, by miniboss", "Greataxe"),
+ DS3LocationData("FK: Ember - upper keep, by miniboss #1", "Ember"),
+ DS3LocationData("FK: Ember - upper keep, by miniboss #2", "Ember"),
+ DS3LocationData("FK: Dark Stoneplate Ring+2 - keep ruins ritual island, behind wall",
+ "Dark Stoneplate Ring+2", ngp=True, hidden=True),
+ DS3LocationData("FK: Magic Stoneplate Ring+1 - between right island and wall",
+ "Magic Stoneplate Ring+1", ngp=True),
+ DS3LocationData("FK: Wolf Ring+1 - keep ruins bonfire island, outside building",
+ "Wolf Ring+1", ngp=True),
+ DS3LocationData("FK: Antiquated Dress - hidden cave", "Antiquated Dress", hidden=True),
+ DS3LocationData("FK: Antiquated Gloves - hidden cave", "Antiquated Gloves", hidden=True),
+ DS3LocationData("FK: Antiquated Skirt - hidden cave", "Antiquated Skirt", hidden=True),
+ DS3LocationData("FK: Sunlight Talisman - estus soup island, by ladder to keep proper",
+ "Sunlight Talisman"),
+ DS3LocationData("FK: Young White Branch - by white tree #1", "Young White Branch"),
+ DS3LocationData("FK: Young White Branch - by white tree #2", "Young White Branch"),
+ DS3LocationData("FK: Crown of Dusk - by white tree", "Crown of Dusk"),
+ DS3LocationData("FK: Lingering Dragoncrest Ring - by white tree, miniboss drop",
+ "Lingering Dragoncrest Ring", miniboss=True), # Great Crab drop
+ DS3LocationData("FK: Pharis's Hat - miniboss drop, by keep ruins near wall",
+ "Pharis's Hat", miniboss=True), # Elder Ghru drop
+ DS3LocationData("FK: Black Bow of Pharis - miniboss drop, by keep ruins near wall",
+ "Black Bow of Pharis", miniboss=True), # Elder Ghru drop
+ DS3LocationData("FK: Titanite Scale - perimeter, miniboss drop", "Titanite Scale x2",
+ miniboss=True), # Ravenous Crystal Lizard drop
+ DS3LocationData("FK: Large Titanite Shard - upper keep, lizard in open",
+ "Large Titanite Shard", lizard=True),
+ DS3LocationData("FK: Large Titanite Shard - upper keep, lizard by wyvern",
+ "Large Titanite Shard", lizard=True),
+ DS3LocationData("FK: Heavy Gem - upper keep, lizard on stairs", "Heavy Gem", lizard=True),
+ DS3LocationData("FK: Twinkling Titanite - keep proper, lizard", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("FK: Soul of a Stray Demon - upper keep, miniboss drop",
+ "Soul of a Stray Demon", miniboss=True),
+ DS3LocationData("FK: Watchdogs of Farron - Old Wolf", "Watchdogs of Farron"),
+ DS3LocationData("FS: Hawkwood's Shield - gravestone after Hawkwood leaves",
+ "Hawkwood's Shield", missable=True,
+ npc=True), # Hawkwood (quest, after Greatwood, Sage, Watchers, and Deacons)
+ DS3LocationData("US: Hawk Ring - Giant Archer", "Hawk Ring", drop=True,
+ npc=True), # Giant archer (kill or quest), here because you need to
+ # collect all seven White Branch locations to get it peacefully
+
+ # Hawkwood after killing Abyss Watchers
+ DS3LocationData("FS: Farron Ring - Hawkwood", "Farron Ring",
+ missable=True, npc=True),
+
+ # Shrine Handmaid after killing Abyss Watchers
+ DS3LocationData("FS: Undead Legion Helm - shop after killing FK boss", "Undead Legion Helm",
+ boss=True, shop=True),
+ DS3LocationData("FS: Undead Legion Armor - shop after killing FK boss",
+ "Undead Legion Armor", boss=True, shop=True),
+ DS3LocationData("FS: Undead Legion Gauntlet - shop after killing FK boss",
+ "Undead Legion Gauntlet", boss=True, shop=True),
+ DS3LocationData("FS: Undead Legion Leggings - shop after killing FK boss",
+ "Undead Legion Leggings", boss=True, shop=True),
+
+ # Appears after killing Havel Knight in Archdragon Peak
+ DS3LocationData("FK: Havel's Helm - upper keep, after killing AP belfry roof NPC",
+ "Havel's Helm", hidden=True, hostile_npc=True),
+ DS3LocationData("FK: Havel's Armor - upper keep, after killing AP belfry roof NPC",
+ "Havel's Armor", hidden=True, hostile_npc=True),
+ DS3LocationData("FK: Havel's Gauntlets - upper keep, after killing AP belfry roof NPC",
+ "Havel's Gauntlets", hidden=True, hostile_npc=True),
+ DS3LocationData("FK: Havel's Leggings - upper keep, after killing AP belfry roof NPC",
+ "Havel's Leggings", hidden=True, hostile_npc=True),
],
"Catacombs of Carthus": [
- DS3LocationData("CC: Carthus Pyromancy Tome", "Carthus Pyromancy Tome", DS3LocationCategory.MISC),
- DS3LocationData("CC: Carthus Milkring", "Carthus Milkring", DS3LocationCategory.RING),
- DS3LocationData("CC: Grave Warden's Ashes", "Grave Warden's Ashes", DS3LocationCategory.MISC),
- DS3LocationData("CC: Carthus Bloodring", "Carthus Bloodring", DS3LocationCategory.RING),
- DS3LocationData("CC: Grave Warden Pyromancy Tome", "Grave Warden Pyromancy Tome", DS3LocationCategory.MISC),
- DS3LocationData("CC: Old Sage's Blindfold", "Old Sage's Blindfold", DS3LocationCategory.ARMOR),
- DS3LocationData("CC: Witch's Ring", "Witch's Ring", DS3LocationCategory.RING),
- DS3LocationData("CC: Black Blade", "Black Blade", DS3LocationCategory.WEAPON),
- DS3LocationData("CC: Soul of High Lord Wolnir", "Soul of High Lord Wolnir", DS3LocationCategory.BOSS),
- DS3LocationData("CC: Soul of a Demon", "Soul of a Demon", DS3LocationCategory.BOSS),
+ DS3LocationData("CC: Soul of High Lord Wolnir", "Soul of High Lord Wolnir",
+ prominent=True, boss=True),
+ DS3LocationData("CC: Carthus Rouge - atrium upper, left after entrance",
+ "Carthus Rouge x2"),
+ DS3LocationData("CC: Sharp Gem - atrium lower, right before exit", "Sharp Gem"),
+ DS3LocationData("CC: Soul of a Nameless Soldier - atrium lower, down hall",
+ "Soul of a Nameless Soldier"),
+ DS3LocationData("CC: Titanite Shard - atrium lower, corner by stairs", "Titanite Shard x2"),
+ DS3LocationData("CC: Bloodred Moss Clump - atrium lower, down more stairs",
+ "Bloodred Moss Clump x3"),
+ DS3LocationData("CC: Carthus Milkring - crypt upper, among pots", "Carthus Milkring"),
+ DS3LocationData("CC: Ember - atrium, on long stairway", "Ember"),
+ DS3LocationData("CC: Carthus Rouge - crypt across, corner", "Carthus Rouge x3"),
+ DS3LocationData("CC: Ember - crypt upper, end of hall past hole", "Ember"),
+ DS3LocationData("CC: Carthus Bloodring - crypt lower, end of side hall", "Carthus Bloodring"),
+ DS3LocationData("CC: Titanite Shard - crypt lower, left of entrance", "Titanite Shard x2"),
+ DS3LocationData("CC: Titanite Shard - crypt lower, start of side hall", "Titanite Shard x2"),
+ DS3LocationData("CC: Ember - crypt lower, shortcut to cavern", "Ember"),
+ DS3LocationData("CC: Carthus Pyromancy Tome - atrium lower, jump from bridge",
+ "Carthus Pyromancy Tome",
+ hidden=True), # Behind illusory wall or hidden drop
+ DS3LocationData("CC: Large Titanite Shard - crypt upper, skeleton ball hall",
+ "Large Titanite Shard"),
+ DS3LocationData("CC: Large Titanite Shard - crypt across, middle hall",
+ "Large Titanite Shard"),
+ DS3LocationData("CC: Yellow Bug Pellet - cavern, on overlook", "Yellow Bug Pellet x3"),
+ DS3LocationData("CC: Large Soul of a Nameless Soldier - cavern, before bridge",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("CC: Black Bug Pellet - cavern, before bridge", "Black Bug Pellet x2"),
+ DS3LocationData("CC: Grave Warden's Ashes - crypt across, corner", "Grave Warden's Ashes",
+ progression=True),
+ DS3LocationData("CC: Large Titanite Shard - tomb lower", "Large Titanite Shard"),
+ DS3LocationData("CC: Large Soul of a Nameless Soldier - tomb lower",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("CC: Old Sage's Blindfold - tomb, hall before bonfire",
+ "Old Sage's Blindfold"),
+ DS3LocationData("CC: Witch's Ring - tomb, hall before bonfire", "Witch's Ring"),
+ DS3LocationData("CC: Soul of a Nameless Soldier - atrium upper, up more stairs",
+ "Soul of a Nameless Soldier"),
+ DS3LocationData("CC: Grave Warden Pyromancy Tome - boss arena",
+ "Grave Warden Pyromancy Tome"),
+ DS3LocationData("CC: Large Soul of an Unknown Traveler - crypt upper, hall middle",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("CC: Ring of Steel Protection+2 - atrium upper, drop onto pillar",
+ "Ring of Steel Protection+2", ngp=True),
+ DS3LocationData("CC: Thunder Stoneplate Ring+1 - crypt upper, among pots",
+ "Thunder Stoneplate Ring+1", ngp=True),
+ DS3LocationData("CC: Undead Bone Shard - crypt upper, skeleton ball drop",
+ "Undead Bone Shard", hidden=True), # Skeleton Ball puzzle
+ DS3LocationData("CC: Dark Gem - crypt lower, skeleton ball drop", "Dark Gem",
+ hidden=True), # Skeleton Ball puzzle
+ DS3LocationData("CC: Black Blade - tomb, mimic", "Black Blade", mimic=True),
+ DS3LocationData("CC: Soul of a Demon - tomb, miniboss drop", "Soul of a Demon",
+ miniboss=True),
+ DS3LocationData("CC: Twinkling Titanite - atrium lower, lizard down more stairs",
+ "Twinkling Titanite", lizard=True),
+ DS3LocationData("CC: Fire Gem - cavern, lizard", "Fire Gem", lizard=True),
+ DS3LocationData("CC: Homeward Bone - Irithyll bridge", "Homeward Bone"),
+ DS3LocationData("CC: Pontiff's Right Eye - Irithyll bridge, miniboss drop",
+ "Pontiff's Right Eye", miniboss=True), # Sulyvahn's Beast drop
+
+ # Shrine Handmaid after killing High Lord Wolnir
+ DS3LocationData("FS: Wolnir's Crown - shop after killing CC boss", "Wolnir's Crown",
+ boss=True, shop=True),
],
"Smouldering Lake": [
- DS3LocationData("SL: Shield of Want", "Shield of Want", DS3LocationCategory.SHIELD),
- DS3LocationData("SL: Speckled Stoneplate Ring", "Speckled Stoneplate Ring", DS3LocationCategory.RING),
- DS3LocationData("SL: Dragonrider Bow", "Dragonrider Bow", DS3LocationCategory.WEAPON),
- DS3LocationData("SL: Lightning Stake", "Lightning Stake", DS3LocationCategory.SPELL),
- DS3LocationData("SL: Izalith Pyromancy Tome", "Izalith Pyromancy Tome", DS3LocationCategory.MISC),
- DS3LocationData("SL: Black Knight Sword", "Black Knight Sword", DS3LocationCategory.WEAPON),
- DS3LocationData("SL: Quelana Pyromancy Tome", "Quelana Pyromancy Tome", DS3LocationCategory.MISC),
- DS3LocationData("SL: Toxic Mist", "Toxic Mist", DS3LocationCategory.SPELL),
- DS3LocationData("SL: White Hair Talisman", "White Hair Talisman", DS3LocationCategory.WEAPON),
- DS3LocationData("SL: Izalith Staff", "Izalith Staff", DS3LocationCategory.WEAPON),
- DS3LocationData("SL: Sacred Flame", "Sacred Flame", DS3LocationCategory.SPELL),
- DS3LocationData("SL: Fume Ultra Greatsword", "Fume Ultra Greatsword", DS3LocationCategory.WEAPON),
- DS3LocationData("SL: Black Iron Greatshield", "Black Iron Greatshield", DS3LocationCategory.SHIELD),
- DS3LocationData("SL: Soul of the Old Demon King", "Soul of the Old Demon King", DS3LocationCategory.BOSS),
- DS3LocationData("SL: Knight Slayer's Ring", "Knight Slayer's Ring", DS3LocationCategory.RING),
+ DS3LocationData("SL: Soul of the Old Demon King", "Soul of the Old Demon King",
+ prominent=True, boss=True),
+ DS3LocationData("SL: Fume Ultra Greatsword - ruins basement, NPC drop",
+ "Fume Ultra Greatsword", hostile_npc=True), # Knight Slayer Tsorig drop
+ DS3LocationData("SL: Black Iron Greatshield - ruins basement, NPC drop",
+ "Black Iron Greatshield", hostile_npc=True), # Knight Slayer Tsorig drop
+ DS3LocationData("SL: Large Titanite Shard - ledge by Demon Ruins bonfire",
+ "Large Titanite Shard"),
+ DS3LocationData("SL: Large Titanite Shard - lake, by entrance", "Large Titanite Shard"),
+ DS3LocationData("SL: Large Titanite Shard - lake, straight from entrance",
+ "Large Titanite Shard"),
+ DS3LocationData("SL: Large Titanite Shard - lake, by tree #1", "Large Titanite Shard"),
+ DS3LocationData("SL: Large Titanite Shard - lake, by miniboss", "Large Titanite Shard"),
+ DS3LocationData("SL: Yellow Bug Pellet - side lake", "Yellow Bug Pellet x2"),
+ DS3LocationData("SL: Large Titanite Shard - side lake #1", "Large Titanite Shard"),
+ DS3LocationData("SL: Large Titanite Shard - side lake #2", "Large Titanite Shard"),
+ DS3LocationData("SL: Large Titanite Shard - lake, by tree #2", "Large Titanite Shard"),
+ DS3LocationData("SL: Speckled Stoneplate Ring - lake, ballista breaks bricks",
+ "Speckled Stoneplate Ring", hidden=True), # Requires careful ballista shot
+ DS3LocationData("SL: Homeward Bone - path to ballista", "Homeward Bone x2"),
+ DS3LocationData("SL: Ember - ruins main upper, hall end by hole", "Ember"),
+ DS3LocationData("SL: Chaos Gem - lake, far end by mob", "Chaos Gem"),
+ DS3LocationData("SL: Ember - ruins main lower, path to antechamber", "Ember"),
+ DS3LocationData("SL: Izalith Pyromancy Tome - antechamber, room near bonfire",
+ "Izalith Pyromancy Tome"),
+ DS3LocationData("SL: Black Knight Sword - ruins main lower, illusory wall in far hall",
+ "Black Knight Sword", hidden=True),
+ DS3LocationData("SL: Ember - ruins main upper, just after entrance", "Ember"),
+ DS3LocationData("SL: Quelana Pyromancy Tome - ruins main lower, illusory wall in grey room",
+ "Quelana Pyromancy Tome", hidden=True),
+ DS3LocationData("SL: Izalith Staff - ruins basement, second illusory wall behind chest",
+ "Izalith Staff", hidden=True),
+ DS3LocationData("SL: White Hair Talisman - ruins main lower, in lava",
+ "White Hair Talisman",
+ missable=True), # This may not even be possible to get without enough fire
+ # protection gear which the player may not have
+ DS3LocationData("SL: Toxic Mist - ruins main lower, in lava", "Toxic Mist",
+ missable=True), # This is _probably_ reachable with normal gear, but it
+ # still sucks and will probably force a death.
+ DS3LocationData("SL: Undead Bone Shard - ruins main lower, left after stairs",
+ "Undead Bone Shard"),
+ DS3LocationData("SL: Titanite Scale - ruins basement, path to lava", "Titanite Scale"),
+ DS3LocationData("SL: Shield of Want - lake, by miniboss", "Shield of Want"),
+ DS3LocationData("SL: Soul of a Crestfallen Knight - ruins basement, above lava",
+ "Soul of a Crestfallen Knight"),
+
+ # Lava items are missable because they require a complex set of armor, rings, spells, and
+ # undead bone shards to reliably access without dying.
+ DS3LocationData("SL: Ember - ruins basement, in lava", "Ember", missable=True), # In lava
+ DS3LocationData("SL: Sacred Flame - ruins basement, in lava", "Sacred Flame",
+ missable=True), # In lava
+
+ DS3LocationData("SL: Dragonrider Bow - by ladder from ruins basement to ballista",
+ "Dragonrider Bow", hidden=True), # Hidden fall
+ DS3LocationData("SL: Estus Shard - antechamber, illusory wall", "Estus Shard",
+ hidden=True),
+ DS3LocationData("SL: Bloodbite Ring+1 - behind ballista", "Bloodbite Ring+1", ngp=True),
+ DS3LocationData("SL: Flame Stoneplate Ring+2 - ruins main lower, illusory wall in far hall",
+ "Flame Stoneplate Ring+2", ngp=True, hidden=True),
+ DS3LocationData("SL: Large Titanite Shard - ruins basement, illusory wall in upper hall",
+ "Large Titanite Shard x3", hidden=True),
+ DS3LocationData("SL: Undead Bone Shard - lake, miniboss drop", "Undead Bone Shard",
+ miniboss=True), # Sand Worm drop
+ DS3LocationData("SL: Lightning Stake - lake, miniboss drop", "Lightning Stake",
+ miniboss=True), # Sand Worm drop
+ DS3LocationData("SL: Twinkling Titanite - path to side lake, lizard", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("SL: Titanite Chunk - path to side lake, lizard", "Titanite Chunk",
+ lizard=True),
+ DS3LocationData("SL: Chaos Gem - antechamber, lizard at end of long hall", "Chaos Gem",
+ lizard=True),
+ DS3LocationData("SL: Knight Slayer's Ring - ruins basement, NPC drop",
+ "Knight Slayer's Ring", hostile_npc=True), # Knight Slayer Tsorig drop
+
+ # Horace the Hushed
+ # These are listed here even though you can kill Horace in the Road of Sacrifices because
+ # the player may want to complete his and Anri's quest first.
+ DS3LocationData("SL: Llewellyn Shield - Horace drop", "Llewellyn Shield", npc=True,
+ hostile_npc=True),
+ DS3LocationData("FS: Executioner Helm - shop after killing Horace", "Executioner Helm",
+ npc=True, hostile_npc=True, shop=True, hidden=True),
+ DS3LocationData("FS: Executioner Armor - shop after killing Horace", "Executioner Armor",
+ npc=True, hostile_npc=True, shop=True, hidden=True),
+ DS3LocationData("FS: Executioner Gauntlets - shop after killing Horace",
+ "Executioner Gauntlets", hostile_npc=True, npc=True, shop=True,
+ hidden=True),
+ DS3LocationData("FS: Executioner Leggings - shop after killing Horace",
+ "Executioner Leggings", hostile_npc=True, npc=True, shop=True,
+ hidden=True),
+
+ # Shrine Handmaid after killing Knight Slayer Tsorig
+ DS3LocationData("FS: Black Iron Helm - shop after killing Tsorig", "Black Iron Helm",
+ hostile_npc=True, shop=True, hidden=True),
+ DS3LocationData("FS: Black Iron Armor - shop after killing Tsorig", "Black Iron Armor",
+ hostile_npc=True, shop=True, hidden=True),
+ DS3LocationData("FS: Black Iron Gauntlets - shop after killing Tsorig",
+ "Black Iron Gauntlets", hostile_npc=True, shop=True, hidden=True),
+ DS3LocationData("FS: Black Iron Leggings - shop after killing Tsorig",
+ "Black Iron Leggings", hostile_npc=True, shop=True, hidden=True),
+
+ # Near Cornyx's cage after killing Old Demon King with Cuculus
+ DS3LocationData("US: Spotted Whip - by Cornyx's cage after Cuculus quest", "Spotted Whip",
+ missable=True, boss=True, npc=True),
+ DS3LocationData("US: Cornyx's Garb - by Cornyx's cage after Cuculus quest",
+ "Cornyx's Garb", static='02,0:53100100::', missable=True, boss=True,
+ npc=True),
+ DS3LocationData("US: Cornyx's Wrap - by Cornyx's cage after Cuculus quest", "Cornyx's Wrap",
+ static='02,0:53100100::', missable=True, boss=True, npc=True),
+ DS3LocationData("US: Cornyx's Skirt - by Cornyx's cage after Cuculus quest",
+ "Cornyx's Skirt", static='02,0:53100100::', missable=True, boss=True,
+ npc=True),
],
"Irithyll of the Boreal Valley": [
- DS3LocationData("IBV: Dorhys' Gnawing", "Dorhys' Gnawing", DS3LocationCategory.SPELL),
- DS3LocationData("IBV: Witchtree Branch", "Witchtree Branch", DS3LocationCategory.WEAPON),
- DS3LocationData("IBV: Magic Clutch Ring", "Magic Clutch Ring", DS3LocationCategory.RING),
- DS3LocationData("IBV: Ring of the Sun's First Born", "Ring of the Sun's First Born", DS3LocationCategory.RING),
- DS3LocationData("IBV: Roster of Knights", "Roster of Knights", DS3LocationCategory.MISC),
- DS3LocationData("IBV: Pontiff's Right Eye", "Pontiff's Right Eye", DS3LocationCategory.RING),
- DS3LocationData("IBV: Yorshka's Spear", "Yorshka's Spear", DS3LocationCategory.WEAPON),
- DS3LocationData("IBV: Great Heal", "Great Heal", DS3LocationCategory.SPELL),
- DS3LocationData("IBV: Smough's Great Hammer", "Smough's Great Hammer", DS3LocationCategory.WEAPON),
- DS3LocationData("IBV: Leo Ring", "Leo Ring", DS3LocationCategory.RING),
- DS3LocationData("IBV: Excrement-covered Ashes", "Excrement-covered Ashes", DS3LocationCategory.MISC),
- DS3LocationData("IBV: Dark Stoneplate Ring", "Dark Stoneplate Ring", DS3LocationCategory.RING),
- DS3LocationData("IBV: Easterner's Ashes", "Easterner's Ashes", DS3LocationCategory.MISC),
- DS3LocationData("IBV: Painting Guardian's Curved Sword", "Painting Guardian's Curved Sword", DS3LocationCategory.WEAPON),
- DS3LocationData("IBV: Painting Guardian Hood", "Painting Guardian Hood", DS3LocationCategory.ARMOR),
- DS3LocationData("IBV: Painting Guardian Gown", "Painting Guardian Gown", DS3LocationCategory.ARMOR),
- DS3LocationData("IBV: Painting Guardian Gloves", "Painting Guardian Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("IBV: Painting Guardian Waistcloth", "Painting Guardian Waistcloth", DS3LocationCategory.ARMOR),
- DS3LocationData("IBV: Dragonslayer Greatbow", "Dragonslayer Greatbow", DS3LocationCategory.WEAPON),
- DS3LocationData("IBV: Reversal Ring", "Reversal Ring", DS3LocationCategory.RING),
- DS3LocationData("IBV: Brass Helm", "Brass Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("IBV: Brass Armor", "Brass Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("IBV: Brass Gauntlets", "Brass Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("IBV: Brass Leggings", "Brass Leggings", DS3LocationCategory.ARMOR),
- DS3LocationData("IBV: Ring of Favor", "Ring of Favor", DS3LocationCategory.RING),
- DS3LocationData("IBV: Golden Ritual Spear", "Golden Ritual Spear", DS3LocationCategory.WEAPON),
- DS3LocationData("IBV: Soul of Pontiff Sulyvahn", "Soul of Pontiff Sulyvahn", DS3LocationCategory.BOSS),
- DS3LocationData("IBV: Aldrich Faithful", "Aldrich Faithful", DS3LocationCategory.MISC),
- DS3LocationData("IBV: Drang Twinspears", "Drang Twinspears", DS3LocationCategory.WEAPON),
+ DS3LocationData("IBV: Soul of Pontiff Sulyvahn", "Soul of Pontiff Sulyvahn",
+ prominent=True, boss=True),
+ DS3LocationData("IBV: Large Soul of a Nameless Soldier - central, by bonfire",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("IBV: Large Titanite Shard - ascent, down ladder in last building",
+ "Large Titanite Shard"),
+ DS3LocationData("IBV: Soul of a Weary Warrior - central, by first fountain",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("IBV: Soul of a Weary Warrior - central, railing by first fountain",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("IBV: Rime-blue Moss Clump - central, by bonfire", "Rime-blue Moss Clump"),
+ DS3LocationData("IBV: Witchtree Branch - by Dorhys", "Witchtree Branch",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("IBV: Large Titanite Shard - central, side path after first fountain",
+ "Large Titanite Shard"),
+ DS3LocationData("IBV: Budding Green Blossom - central, by second fountain",
+ "Budding Green Blossom"),
+ DS3LocationData("IBV: Rime-blue Moss Clump - central, past second fountain",
+ "Rime-blue Moss Clump x2"),
+ DS3LocationData("IBV: Large Titanite Shard - central, balcony just before plaza",
+ "Large Titanite Shard"),
+ DS3LocationData("IBV: Large Titanite Shard - path to Dorhys", "Large Titanite Shard",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("IBV: Ring of the Sun's First Born - fall from in front of cathedral",
+ "Ring of the Sun's First Born",
+ hidden=True), # Hidden fall
+ DS3LocationData("IBV: Large Soul of a Nameless Soldier - path to plaza",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("IBV: Large Titanite Shard - plaza, balcony overlooking ascent",
+ "Large Titanite Shard"),
+ DS3LocationData("IBV: Large Titanite Shard - plaza, by stairs to church",
+ "Large Titanite Shard"),
+ DS3LocationData("IBV: Soul of a Weary Warrior - plaza, side room lower",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("IBV: Magic Clutch Ring - plaza, illusory wall", "Magic Clutch Ring",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("IBV: Fading Soul - descent, cliff edge #1", "Fading Soul"),
+ DS3LocationData("IBV: Fading Soul - descent, cliff edge #2", "Fading Soul"),
+ DS3LocationData("IBV: Homeward Bone - descent, before gravestone", "Homeward Bone x3"),
+ DS3LocationData("IBV: Undead Bone Shard - descent, behind gravestone", "Undead Bone Shard",
+ hidden=True), # Hidden behind gravestone
+ DS3LocationData("IBV: Kukri - descent, side path", "Kukri x8"),
+ DS3LocationData("IBV: Rusted Gold Coin - descent, side path", "Rusted Gold Coin"),
+ DS3LocationData("IBV: Blue Bug Pellet - descent, dark room", "Blue Bug Pellet x2"),
+ DS3LocationData("IBV: Shriving Stone - descent, dark room rafters", "Shriving Stone"),
+ DS3LocationData("IBV: Blood Gem - descent, platform before lake", "Blood Gem"),
+ DS3LocationData("IBV: Green Blossom - lake, by stairs from descent", "Green Blossom x3"),
+ DS3LocationData("IBV: Ring of Sacrifice - lake, right of stairs from descent",
+ "Ring of Sacrifice"),
+ DS3LocationData("IBV: Great Heal - lake, dead Corpse-Grub", "Great Heal"),
+ DS3LocationData("IBV: Large Soul of a Nameless Soldier - lake island",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("IBV: Green Blossom - lake wall", "Green Blossom x3"),
+ DS3LocationData("IBV: Dung Pie - sewer #1", "Dung Pie x3"),
+ DS3LocationData("IBV: Dung Pie - sewer #2", "Dung Pie x3"),
+ # These don't actually guard any single item sales. Maybe we can inject one manually?
+ DS3LocationData("IBV: Excrement-covered Ashes - sewer, by stairs",
+ "Excrement-covered Ashes"),
+ DS3LocationData("IBV: Large Soul of a Nameless Soldier - ascent, after great hall",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("IBV: Soul of a Weary Warrior - ascent, by final staircase",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("IBV: Large Titanite Shard - ascent, by elevator door",
+ "Large Titanite Shard"),
+ DS3LocationData("IBV: Blue Bug Pellet - ascent, in last building", "Blue Bug Pellet x2"),
+ DS3LocationData("IBV: Ember - shortcut from church to cathedral", "Ember"),
+ DS3LocationData("IBV: Green Blossom - lake, by Distant Manor", "Green Blossom"),
+ DS3LocationData("IBV: Lightning Gem - plaza center", "Lightning Gem"),
+ DS3LocationData("IBV: Large Soul of a Nameless Soldier - central, by second fountain",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("IBV: Soul of a Weary Warrior - plaza, side room upper",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("IBV: Proof of a Concord Kept - Church of Yorshka altar",
+ "Proof of a Concord Kept"),
+ DS3LocationData("IBV: Rusted Gold Coin - Distant Manor, drop after stairs",
+ "Rusted Gold Coin"),
+ DS3LocationData("IBV: Chloranthy Ring+1 - plaza, behind altar", "Chloranthy Ring+1",
+ ngp=True),
+ DS3LocationData("IBV: Covetous Gold Serpent Ring+1 - descent, drop after dark room",
+ "Covetous Gold Serpent Ring+1", ngp=True, hidden=True), # Hidden fall
+ DS3LocationData("IBV: Wood Grain Ring+2 - ascent, right after great hall", "Wood Grain Ring+2",
+ ngp=True),
+ DS3LocationData("IBV: Divine Blessing - great hall, chest", "Divine Blessing"),
+ DS3LocationData("IBV: Smough's Great Hammer - great hall, chest",
+ "Smough's Great Hammer"),
+ DS3LocationData("IBV: Yorshka's Spear - descent, dark room rafters chest", "Yorshka's Spear"),
+ DS3LocationData("IBV: Leo Ring - great hall, chest", "Leo Ring"),
+ DS3LocationData("IBV: Dorhys' Gnawing - Dorhys drop", "Dorhys' Gnawing",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("IBV: Divine Blessing - great hall, mob drop",
+ "Divine Blessing", drop=True,
+ hidden=True), # Guaranteed drop from normal-looking Silver Knight
+ DS3LocationData("IBV: Large Titanite Shard - great hall, main floor mob drop",
+ "Large Titanite Shard", drop=True,
+ hidden=True), # Guaranteed drop from normal-looking Silver Knight
+ DS3LocationData("IBV: Large Titanite Shard - great hall, upstairs mob drop #1",
+ "Large Titanite Shard x2", drop=True,
+ hidden=True), # Guaranteed drop from normal-looking Silver Knight
+ DS3LocationData("IBV: Large Titanite Shard - great hall, upstairs mob drop #2",
+ "Large Titanite Shard x2", drop=True,
+ hidden=True), # Guaranteed drop from normal-looking Silver Knight
+ DS3LocationData("IBV: Roster of Knights - descent, first landing", "Roster of Knights"),
+ DS3LocationData("IBV: Twinkling Titanite - descent, lizard behind illusory wall",
+ "Twinkling Titanite", lizard=True, hidden=True), # Behind illusory wall
+ DS3LocationData("IBV: Twinkling Titanite - central, lizard before plaza",
+ "Twinkling Titanite", lizard=True),
+ DS3LocationData("IBV: Large Titanite Shard - Distant Manor, under overhang",
+ "Large Titanite Shard"),
+ DS3LocationData("IBV: Siegbräu - Siegward", "Siegbräu", missable=True, npc=True),
+ DS3LocationData("IBV: Emit Force - Siegward", "Emit Force", missable=True, npc=True),
+ DS3LocationData("IBV -> ID", None),
+
+ # After winning both Londor Pale Shade invasions
+ DS3LocationData("FS: Sneering Mask - Yoel's room, kill Londor Pale Shade twice",
+ "Sneering Mask", missable=True, hostile_npc=True),
+ DS3LocationData("FS: Pale Shade Robe - Yoel's room, kill Londor Pale Shade twice",
+ "Pale Shade Robe", missable=True, hostile_npc=True),
+ DS3LocationData("FS: Pale Shade Gloves - Yoel's room, kill Londor Pale Shade twice",
+ "Pale Shade Gloves", missable=True, hostile_npc=True),
+ DS3LocationData("FS: Pale Shade Trousers - Yoel's room, kill Londor Pale Shade twice",
+ "Pale Shade Trousers", missable=True, hostile_npc=True),
+
+ # Anri of Astora
+ DS3LocationData("IBV: Ring of the Evil Eye - Anri", "Ring of the Evil Eye", missable=True,
+ npc=True),
+
+ # Sirris quest after killing Creighton
+ DS3LocationData("FS: Mail Breaker - Sirris for killing Creighton", "Mail Breaker",
+ static='99,0:50006080::', missable=True, hostile_npc=True,
+ npc=True),
+ DS3LocationData("FS: Silvercat Ring - Sirris for killing Creighton", "Silvercat Ring",
+ missable=True, hostile_npc=True, npc=True),
+ DS3LocationData("IBV: Dragonslayer's Axe - Creighton drop", "Dragonslayer's Axe",
+ missable=True, hostile_npc=True, npc=True),
+ DS3LocationData("IBV: Creighton's Steel Mask - bridge after killing Creighton",
+ "Creighton's Steel Mask", missable=True, hostile_npc=True, npc=True),
+ DS3LocationData("IBV: Mirrah Chain Mail - bridge after killing Creighton",
+ "Mirrah Chain Mail", missable=True, hostile_npc=True, npc=True),
+ DS3LocationData("IBV: Mirrah Chain Gloves - bridge after killing Creighton",
+ "Mirrah Chain Gloves", missable=True, hostile_npc=True, npc=True),
+ DS3LocationData("IBV: Mirrah Chain Leggings - bridge after killing Creighton",
+ "Mirrah Chain Leggings", missable=True, hostile_npc=True, npc=True),
],
"Irithyll Dungeon": [
- DS3LocationData("ID: Bellowing Dragoncrest Ring", "Bellowing Dragoncrest Ring", DS3LocationCategory.RING),
- DS3LocationData("ID: Jailbreaker's Key", "Jailbreaker's Key", DS3LocationCategory.KEY),
- DS3LocationData("ID: Prisoner Chief's Ashes", "Prisoner Chief's Ashes", DS3LocationCategory.KEY),
- DS3LocationData("ID: Old Sorcerer Hat", "Old Sorcerer Hat", DS3LocationCategory.ARMOR),
- DS3LocationData("ID: Old Sorcerer Coat", "Old Sorcerer Coat", DS3LocationCategory.ARMOR),
- DS3LocationData("ID: Old Sorcerer Gauntlets", "Old Sorcerer Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("ID: Old Sorcerer Boots", "Old Sorcerer Boots", DS3LocationCategory.ARMOR),
- DS3LocationData("ID: Great Magic Shield", "Great Magic Shield", DS3LocationCategory.SPELL),
- DS3LocationData("ID: Dragon Torso Stone", "Dragon Torso Stone", DS3LocationCategory.MISC),
- DS3LocationData("ID: Lightning Blade", "Lightning Blade", DS3LocationCategory.SPELL),
- DS3LocationData("ID: Profaned Coal", "Profaned Coal", DS3LocationCategory.MISC),
- DS3LocationData("ID: Xanthous Ashes", "Xanthous Ashes", DS3LocationCategory.MISC),
- DS3LocationData("ID: Old Cell Key", "Old Cell Key", DS3LocationCategory.KEY),
- DS3LocationData("ID: Pickaxe", "Pickaxe", DS3LocationCategory.WEAPON),
- DS3LocationData("ID: Profaned Flame", "Profaned Flame", DS3LocationCategory.SPELL),
- DS3LocationData("ID: Covetous Gold Serpent Ring", "Covetous Gold Serpent Ring", DS3LocationCategory.RING),
- DS3LocationData("ID: Jailer's Key Ring", "Jailer's Key Ring", DS3LocationCategory.KEY),
- DS3LocationData("ID: Dusk Crown Ring", "Dusk Crown Ring", DS3LocationCategory.RING),
- DS3LocationData("ID: Dark Clutch Ring", "Dark Clutch Ring", DS3LocationCategory.RING),
- DS3LocationData("ID: Karla's Ashes", "Karla's Ashes", DS3LocationCategory.NPC),
- DS3LocationData("ID: Karla's Pointed Hat", "Karla's Pointed Hat", DS3LocationCategory.NPC),
- DS3LocationData("ID: Karla's Coat", "Karla's Coat", DS3LocationCategory.NPC),
- DS3LocationData("ID: Karla's Gloves", "Karla's Gloves", DS3LocationCategory.NPC),
- DS3LocationData("ID: Karla's Trousers", "Karla's Trousers", DS3LocationCategory.NPC),
+ DS3LocationData("ID: Titanite Slab - Siegward", "Titanite Slab", missable=True,
+ npc=True),
+ DS3LocationData("ID: Murakumo - Alva drop", "Murakumo", missable=True,
+ hostile_npc=True),
+ DS3LocationData("ID: Large Titanite Shard - after bonfire, second cell on left",
+ "Large Titanite Shard"),
+ DS3LocationData("ID: Fading Soul - B1 near, main hall", "Fading Soul"),
+ DS3LocationData("ID: Large Soul of a Nameless Soldier - B2, hall by stairs",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("ID: Jailbreaker's Key - B1 far, cell after gate", "Jailbreaker's Key"),
+ DS3LocationData("ID: Pale Pine Resin - B1 far, cell with broken wall",
+ "Pale Pine Resin x2"),
+ DS3LocationData("ID: Simple Gem - B2 far, cell by stairs", "Simple Gem"),
+ DS3LocationData("ID: Large Soul of a Nameless Soldier - B2 far, by lift",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("ID: Large Titanite Shard - B1 far, rightmost cell",
+ "Large Titanite Shard"),
+ DS3LocationData("ID: Homeward Bone - path from B2 to pit", "Homeward Bone x2"),
+ DS3LocationData("ID: Bellowing Dragoncrest Ring - drop from B1 towards pit",
+ "Bellowing Dragoncrest Ring", conditional=True),
+ DS3LocationData("ID: Soul of a Weary Warrior - by drop to pit", "Soul of a Weary Warrior"),
+ DS3LocationData("ID: Soul of a Crestfallen Knight - balcony above pit",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("ID: Lightning Bolt - awning over pit", "Lightning Bolt x9"),
+ DS3LocationData("ID: Large Titanite Shard - pit #1", "Large Titanite Shard"),
+ DS3LocationData("ID: Profaned Flame - pit", "Profaned Flame"),
+ DS3LocationData("ID: Large Titanite Shard - pit #2", "Large Titanite Shard"),
+ DS3LocationData("ID: Soul of a Weary Warrior - stairs between pit and B3",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("ID: Dung Pie - B3, by path from pit", "Dung Pie x4"),
+ DS3LocationData("ID: Ember - B3 center", "Ember"),
+ DS3LocationData("ID: Ember - B3 far right", "Ember"),
+ DS3LocationData("ID: Profaned Coal - B3 far, left cell", "Profaned Coal"),
+ DS3LocationData("ID: Large Titanite Shard - B3 near, right corner", "Large Titanite Shard"),
+ DS3LocationData("ID: Old Sorcerer Hat - B2 near, middle cell", "Old Sorcerer Hat"),
+ DS3LocationData("ID: Old Sorcerer Coat - B2 near, middle cell", "Old Sorcerer Coat"),
+ DS3LocationData("ID: Old Sorcerer Gauntlets - B2 near, middle cell",
+ "Old Sorcerer Gauntlets"),
+ DS3LocationData("ID: Old Sorcerer Boots - B2 near, middle cell", "Old Sorcerer Boots"),
+ DS3LocationData("ID: Large Soul of a Weary Warrior - just before Profaned Capital",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("ID: Covetous Gold Serpent Ring - Siegward's cell",
+ "Covetous Gold Serpent Ring", conditional=True),
+ DS3LocationData("ID: Lightning Blade - B3 lift, middle platform", "Lightning Blade"),
+ DS3LocationData("ID: Rusted Coin - after bonfire, first cell on left", "Rusted Coin"),
+ DS3LocationData("ID: Dusk Crown Ring - B3 far, right cell", "Dusk Crown Ring"),
+ DS3LocationData("ID: Pickaxe - path from pit to B3", "Pickaxe"),
+ DS3LocationData("ID: Xanthous Ashes - B3 far, right cell", "Xanthous Ashes",
+ progression=True),
+ DS3LocationData("ID: Large Titanite Shard - B1 near, by door", "Large Titanite Shard"),
+ DS3LocationData("ID: Rusted Gold Coin - after bonfire, last cell on right",
+ "Rusted Gold Coin"),
+ DS3LocationData("ID: Old Cell Key - stairs between pit and B3", "Old Cell Key"),
+ DS3LocationData("ID: Covetous Silver Serpent Ring+1 - pit lift, middle platform",
+ "Covetous Silver Serpent Ring+1", ngp=True),
+ DS3LocationData("ID: Dragon Torso Stone - B3, outside lift", "Dragon Torso Stone"),
+ DS3LocationData("ID: Prisoner Chief's Ashes - B2 near, locked cell by stairs",
+ "Prisoner Chief's Ashes", progression=True),
+ DS3LocationData("ID: Great Magic Shield - B2 near, mob drop in far left cell",
+ "Great Magic Shield", drop=True,
+ hidden=True), # Guaranteed drop from a normal-looking Corpse-Grub
+ DS3LocationData("ID: Dragonslayer Lightning Arrow - pit, mimic in hall",
+ "Dragonslayer Lightning Arrow x10", mimic=True),
+ DS3LocationData("ID: Titanite Scale - B3 far, mimic in hall", "Titanite Scale x2",
+ mimic=True),
+ DS3LocationData("ID: Dark Clutch Ring - stairs between pit and B3, mimic",
+ "Dark Clutch Ring", mimic=True),
+ DS3LocationData("ID: Estus Shard - mimic on path from B2 to pit", "Estus Shard",
+ mimic=True),
+ DS3LocationData("ID: Titanite Chunk - balcony above pit, lizard", "Titanite Chunk",
+ lizard=True),
+ DS3LocationData("ID: Titanite Scale - B2 far, lizard", "Titanite Scale", lizard=True),
+
+ # These are missable because of a bug that causes them to be dropped wherever the giant is
+ # randomized to, instead of where the miniboss is in vanilla.
+ DS3LocationData("ID: Dung Pie - pit, miniboss drop", "Dung Pie x4",
+ miniboss=True, missable=True), # Giant slave drop
+ DS3LocationData("ID: Titanite Chunk - pit, miniboss drop", "Titanite Chunk",
+ miniboss=True, missable=True), # Giant Slave Drop
+
+ # Alva (requires ember)
+ DS3LocationData("ID: Alva Helm - B3 near, by Karla's cell, after killing Alva", "Alva Helm",
+ missable=True, npc=True),
+ DS3LocationData("ID: Alva Armor - B3 near, by Karla's cell, after killing Alva",
+ "Alva Armor", missable=True, npc=True),
+ DS3LocationData("ID: Alva Gauntlets - B3 near, by Karla's cell, after killing Alva",
+ "Alva Gauntlets", missable=True, npc=True),
+ DS3LocationData("ID: Alva Leggings - B3 near, by Karla's cell, after killing Alva",
+ "Alva Leggings", missable=True, npc=True),
],
"Profaned Capital": [
- DS3LocationData("PC: Cursebite Ring", "Cursebite Ring", DS3LocationCategory.RING),
- DS3LocationData("PC: Court Sorcerer Hood", "Court Sorcerer Hood", DS3LocationCategory.ARMOR),
- DS3LocationData("PC: Court Sorcerer Robe", "Court Sorcerer Robe", DS3LocationCategory.ARMOR),
- DS3LocationData("PC: Court Sorcerer Gloves", "Court Sorcerer Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("PC: Court Sorcerer Trousers", "Court Sorcerer Trousers", DS3LocationCategory.ARMOR),
- DS3LocationData("PC: Wrath of the Gods", "Wrath of the Gods", DS3LocationCategory.SPELL),
- DS3LocationData("PC: Logan's Scroll", "Logan's Scroll", DS3LocationCategory.MISC),
- DS3LocationData("PC: Eleonora", "Eleonora", DS3LocationCategory.WEAPON),
- DS3LocationData("PC: Court Sorcerer's Staff", "Court Sorcerer's Staff", DS3LocationCategory.WEAPON),
- DS3LocationData("PC: Greatshield of Glory", "Greatshield of Glory", DS3LocationCategory.SHIELD),
- DS3LocationData("PC: Storm Ruler", "Storm Ruler", DS3LocationCategory.KEY),
- DS3LocationData("PC: Cinders of a Lord - Yhorm the Giant", "Cinders of a Lord - Yhorm the Giant", DS3LocationCategory.KEY),
- DS3LocationData("PC: Soul of Yhorm the Giant", "Soul of Yhorm the Giant", DS3LocationCategory.BOSS),
+ DS3LocationData("PC: Soul of Yhorm the Giant", "Soul of Yhorm the Giant", boss=True),
+ DS3LocationData("PC: Cinders of a Lord - Yhorm the Giant",
+ "Cinders of a Lord - Yhorm the Giant", static="07,0:50002170::",
+ prominent=True, progression=True, boss=True),
+ DS3LocationData("PC: Logan's Scroll - chapel roof, NPC drop", "Logan's Scroll",
+ hostile_npc=True), # Sorcerer
+ DS3LocationData("PC: Purging Stone - chapel ground floor", "Purging Stone x3"),
+ DS3LocationData("PC: Rusted Coin - tower exterior", "Rusted Coin x2"),
+ DS3LocationData("PC: Rusted Gold Coin - halls above swamp", "Rusted Gold Coin"),
+ DS3LocationData("PC: Purging Stone - swamp, by chapel ladder", "Purging Stone"),
+ DS3LocationData("PC: Cursebite Ring - swamp, below halls", "Cursebite Ring"),
+ DS3LocationData("PC: Poison Gem - swamp, below halls", "Poison Gem"),
+ DS3LocationData("PC: Shriving Stone - swamp, by chapel door", "Shriving Stone"),
+ DS3LocationData("PC: Poison Arrow - chapel roof", "Poison Arrow x18"),
+ DS3LocationData("PC: Rubbish - chapel, down stairs from second floor", "Rubbish"),
+ DS3LocationData("PC: Onislayer Greatarrow - bridge", "Onislayer Greatarrow x8"),
+ DS3LocationData("PC: Large Soul of a Weary Warrior - bridge, far end",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("PC: Rusted Coin - below bridge #1", "Rusted Coin"),
+ DS3LocationData("PC: Rusted Coin - below bridge #2", "Rusted Coin"),
+ DS3LocationData("PC: Blooming Purple Moss Clump - walkway above swamp",
+ "Blooming Purple Moss Clump x3"),
+ DS3LocationData("PC: Wrath of the Gods - chapel, drop from roof", "Wrath of the Gods"),
+ DS3LocationData("PC: Onislayer Greatbow - drop from bridge", "Onislayer Greatbow",
+ hidden=True), # Hidden fall
+ DS3LocationData("PC: Jailer's Key Ring - hall past chapel", "Jailer's Key Ring",
+ progression=True),
+ DS3LocationData("PC: Ember - palace, far room", "Ember"),
+ DS3LocationData("PC: Flame Stoneplate Ring+1 - chapel, drop from roof towards entrance",
+ "Flame Stoneplate Ring+1", ngp=True, hidden=True), # Hidden fall
+ DS3LocationData("PC: Magic Stoneplate Ring+2 - tower base", "Magic Stoneplate Ring+2",
+ ngp=True),
+ DS3LocationData("PC: Court Sorcerer Hood - chapel, second floor", "Court Sorcerer Hood"),
+ DS3LocationData("PC: Court Sorcerer Robe - chapel, second floor", "Court Sorcerer Robe"),
+ DS3LocationData("PC: Court Sorcerer Gloves - chapel, second floor", "Court Sorcerer Gloves"),
+ DS3LocationData("PC: Court Sorcerer Trousers - chapel, second floor",
+ "Court Sorcerer Trousers"),
+ DS3LocationData("PC: Storm Ruler - boss room", "Storm Ruler"),
+ DS3LocationData("PC: Undead Bone Shard - by bonfire", "Undead Bone Shard"),
+ DS3LocationData("PC: Eleonora - chapel ground floor, kill mob", "Eleonora",
+ drop=True,
+ hidden=True), # Guaranteed drop from a normal-looking Monstrosity of Sin
+ DS3LocationData("PC: Rusted Gold Coin - palace, mimic in far room", "Rusted Gold Coin x2",
+ mimic=True),
+ DS3LocationData("PC: Court Sorcerer's Staff - chapel, mimic on second floor",
+ "Court Sorcerer's Staff", mimic=True),
+ DS3LocationData("PC: Greatshield of Glory - palace, mimic in far room",
+ "Greatshield of Glory", mimic=True),
+ DS3LocationData("PC: Twinkling Titanite - halls above swamp, lizard #1",
+ "Twinkling Titanite", lizard=True),
+ DS3LocationData("PC: Twinkling Titanite - halls above swamp, lizard #2",
+ "Twinkling Titanite", lizard=True),
+ DS3LocationData("PC: Siegbräu - Siegward after killing boss", "Siegbräu",
+ missable=True, npc=True),
+
+ # Siegward drops (kill or quest)
+ DS3LocationData("PC: Storm Ruler - Siegward", "Storm Ruler", static='02,0:50006218::',
+ missable=True, drop=True, npc=True),
+ DS3LocationData("PC: Pierce Shield - Siegward", "Pierce Shield", missable=True,
+ drop=True, npc=True),
],
+ # We consider "Anor Londo" to be everything accessible only after killing Pontiff. This doesn't
+ # match up one-to-one with where the game pops up the region name, but it balances items better
+ # and covers the region that's full of DS1 Anor Londo references.
"Anor Londo": [
- DS3LocationData("AL: Giant's Coal", "Giant's Coal", DS3LocationCategory.MISC),
- DS3LocationData("AL: Sun Princess Ring", "Sun Princess Ring", DS3LocationCategory.RING),
- DS3LocationData("AL: Aldrich's Ruby", "Aldrich's Ruby", DS3LocationCategory.RING),
- DS3LocationData("AL: Cinders of a Lord - Aldrich", "Cinders of a Lord - Aldrich", DS3LocationCategory.KEY),
- DS3LocationData("AL: Soul of Aldrich", "Soul of Aldrich", DS3LocationCategory.BOSS),
+ DS3LocationData("AL: Soul of Aldrich", "Soul of Aldrich", boss=True),
+ DS3LocationData("AL: Cinders of a Lord - Aldrich", "Cinders of a Lord - Aldrich",
+ static='06,0:50002130::', prominent=True, progression=True,
+ boss=True),
+ DS3LocationData("AL: Yorshka's Chime - kill Yorshka", "Yorshka's Chime", missable=True,
+ drop=True,
+ npc=True), # Hidden walkway, missable because it will break Sirris's quest
+ DS3LocationData("AL: Drang Twinspears - plaza, NPC drop", "Drang Twinspears", drop=True,
+ hidden=True),
+ DS3LocationData("AL: Estus Shard - dark cathedral, by left stairs", "Estus Shard"),
+ DS3LocationData("AL: Painting Guardian's Curved Sword - prison tower rafters",
+ "Painting Guardian's Curved Sword", hidden=True), # Invisible walkway
+ DS3LocationData("AL: Brass Helm - tomb", "Brass Helm",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("AL: Brass Armor - tomb", "Brass Armor",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("AL: Brass Gauntlets - tomb", "Brass Gauntlets",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("AL: Brass Leggings - tomb", "Brass Leggings",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("AL: Human Dregs - water reserves", "Human Dregs",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("AL: Ember - spiral staircase, bottom", "Ember"),
+ DS3LocationData("AL: Large Titanite Shard - bottom of the furthest buttress",
+ "Large Titanite Shard"),
+ DS3LocationData("AL: Large Titanite Shard - right after light cathedral",
+ "Large Titanite Shard"),
+ DS3LocationData("AL: Large Titanite Shard - walkway, side path by cathedral",
+ "Large Titanite Shard"),
+ DS3LocationData("AL: Soul of a Weary Warrior - plaza, nearer", "Soul of a Weary Warrior"),
+ DS3LocationData("AL: Ember - plaza, right side", "Ember"),
+ DS3LocationData("AL: Ember - plaza, further", "Ember"),
+ DS3LocationData("AL: Large Titanite Shard - balcony by dead giants",
+ "Large Titanite Shard"),
+ DS3LocationData("AL: Dark Stoneplate Ring - by dark stairs up from plaza",
+ "Dark Stoneplate Ring"),
+ DS3LocationData("AL: Large Titanite Shard - bottom of the nearest buttress",
+ "Large Titanite Shard"),
+ DS3LocationData("AL: Deep Gem - water reserves", "Deep Gem"),
+ DS3LocationData("AL: Titanite Scale - top of ladder up to buttresses", "Titanite Scale"),
+ DS3LocationData("AL: Dragonslayer Greatarrow - drop from nearest buttress",
+ "Dragonslayer Greatarrow x5", static='06,0:53700620::',
+ hidden=True), # Hidden fall
+ DS3LocationData("AL: Dragonslayer Greatbow - drop from nearest buttress",
+ "Dragonslayer Greatbow", static='06,0:53700620::',
+ hidden=True), # Hidden fall
+ DS3LocationData("AL: Easterner's Ashes - below top of furthest buttress",
+ "Easterner's Ashes", progression=True),
+ DS3LocationData("AL: Painting Guardian Hood - prison tower, rafters",
+ "Painting Guardian Hood", hidden=True), # Invisible walkway
+ DS3LocationData("AL: Painting Guardian Gown - prison tower, rafters",
+ "Painting Guardian Gown", hidden=True), # Invisible walkway
+ DS3LocationData("AL: Painting Guardian Gloves - prison tower, rafters",
+ "Painting Guardian Gloves", hidden=True), # Invisible walkway
+ DS3LocationData("AL: Painting Guardian Waistcloth - prison tower, rafters",
+ "Painting Guardian Waistcloth", hidden=True), # Invisible walkway
+ DS3LocationData("AL: Soul of a Crestfallen Knight - right of dark cathedral entrance",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("AL: Moonlight Arrow - dark cathedral, up right stairs",
+ "Moonlight Arrow x6"),
+ DS3LocationData("AL: Proof of a Concord Kept - dark cathedral, up left stairs",
+ "Proof of a Concord Kept"),
+ DS3LocationData("AL: Large Soul of a Weary Warrior - left of dark cathedral entrance",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("AL: Giant's Coal - by giant near dark cathedral", "Giant's Coal"),
+ DS3LocationData("AL: Havel's Ring+2 - prison tower, rafters", "Havel's Ring+2", ngp=True,
+ hidden=True), # Invisible walkway
+ DS3LocationData("AL: Ring of Favor+1 - light cathedral, upstairs", "Ring of Favor+1",
+ ngp=True),
+ DS3LocationData("AL: Sun Princess Ring - dark cathedral, after boss", "Sun Princess Ring"),
+ DS3LocationData("AL: Reversal Ring - tomb, chest in corner", "Reversal Ring",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("AL: Golden Ritual Spear - light cathedral, mimic upstairs",
+ "Golden Ritual Spear", mimic=True),
+ DS3LocationData("AL: Ring of Favor - water reserves, both minibosses", "Ring of Favor",
+ miniboss=True,
+ hidden=True), # Sulyvahn's Beast Duo drop, behind illusory wall
+ DS3LocationData("AL: Blade of the Darkmoon - Yorshka with Darkmoon Loyalty",
+ "Blade of the Darkmoon", missable=True, drop=True,
+ npc=True), # Hidden walkway, missable because it will break Sirris's quest
+ DS3LocationData("AL: Simple Gem - light cathedral, lizard upstairs", "Simple Gem",
+ lizard=True),
+ DS3LocationData("AL: Twinkling Titanite - lizard after light cathedral #1",
+ "Twinkling Titanite", lizard=True),
+ DS3LocationData("AL: Twinkling Titanite - lizard after light cathedral #2",
+ "Twinkling Titanite", lizard=True),
+ DS3LocationData("AL: Aldrich's Ruby - dark cathedral, miniboss", "Aldrich's Ruby",
+ miniboss=True), # Deep Accursed drop
+ DS3LocationData("AL: Aldrich Faithful - water reserves, talk to McDonnel", "Aldrich Faithful",
+ hidden=True), # Behind illusory wall
+
+ DS3LocationData("FS: Budding Green Blossom - shop after killing Creighton and AL boss",
+ "Budding Green Blossom", static='99,0:-1:110000,70000118:',
+ missable=True, npc=True,
+ shop=True), # sold by Shrine Maiden after killing Aldrich and helping
+ # Sirris defeat Creighton
+
+ # Sirris (quest completion)
+ DS3LocationData("FS: Sunset Shield - by grave after killing Hodrick w/Sirris",
+ "Sunset Shield", missable=True, hostile_npc=True, npc=True),
+ # In Pit of Hollows after killing Hodrick
+ DS3LocationData("US: Sunset Helm - Pit of Hollows after killing Hodrick w/Sirris",
+ "Sunset Helm", missable=True, hostile_npc=True, npc=True),
+ DS3LocationData("US: Sunset Armor - pit of hollows after killing Hodrick w/Sirris",
+ "Sunset Armor", missable=True, hostile_npc=True, npc=True),
+ DS3LocationData("US: Sunset Gauntlets - pit of hollows after killing Hodrick w/Sirris",
+ "Sunset Gauntlets", missable=True, hostile_npc=True, npc=True),
+ DS3LocationData("US: Sunset Leggings - pit of hollows after killing Hodrick w/Sirris",
+ "Sunset Leggings", missable=True, hostile_npc=True, npc=True),
+
+ # Shrine Handmaid after killing Sulyvahn's Beast Duo
+ DS3LocationData("FS: Helm of Favor - shop after killing water reserve minibosses",
+ "Helm of Favor", hidden=True, miniboss=True, shop=True),
+ DS3LocationData("FS: Embraced Armor of Favor - shop after killing water reserve minibosses",
+ "Embraced Armor of Favor", hidden=True, miniboss=True, shop=True),
+ DS3LocationData("FS: Gauntlets of Favor - shop after killing water reserve minibosses",
+ "Gauntlets of Favor", hidden=True, miniboss=True, shop=True),
+ DS3LocationData("FS: Leggings of Favor - shop after killing water reserve minibosses",
+ "Leggings of Favor", hidden=True, miniboss=True, shop=True),
+
+ # Anri of Astora
+ DS3LocationData("AL: Chameleon - tomb after marrying Anri", "Chameleon", missable=True,
+ npc=True),
+ DS3LocationData("AL: Anri's Straight Sword - Anri quest", "Anri's Straight Sword",
+ missable=True, npc=True),
+
+ # Shrine Handmaid after killing Ringfinger Leonhard
+ # This is listed here even though you can kill Leonhard immediately because we want the
+ # logic to assume people will do his full quest. Missable because he can disappear forever
+ # if you use up all your Pale Tongues.
+ DS3LocationData("FS: Leonhard's Garb - shop after killing Leonhard",
+ "Leonhard's Garb", hidden=True, npc=True, shop=True, missable=True),
+ DS3LocationData("FS: Leonhard's Gauntlets - shop after killing Leonhard",
+ "Leonhard's Gauntlets", hidden=True, npc=True, shop=True,
+ missable=True),
+ DS3LocationData("FS: Leonhard's Trousers - shop after killing Leonhard",
+ "Leonhard's Trousers", hidden=True, npc=True, shop=True,
+ missable=True),
+
+ # Shrine Handmaid after killing Alrich, Devourer of Gods
+ DS3LocationData("FS: Smough's Helm - shop after killing AL boss", "Smough's Helm",
+ boss=True, shop=True),
+ DS3LocationData("FS: Smough's Armor - shop after killing AL boss", "Smough's Armor",
+ boss=True, shop=True),
+ DS3LocationData("FS: Smough's Gauntlets - shop after killing AL boss", "Smough's Gauntlets",
+ boss=True, shop=True),
+ DS3LocationData("FS: Smough's Leggings - shop after killing AL boss", "Smough's Leggings",
+ boss=True, shop=True),
+
+ # Ringfinger Leonhard (quest or kill)
+ DS3LocationData("AL: Crescent Moon Sword - Leonhard drop", "Crescent Moon Sword",
+ missable=True, npc=True),
+ DS3LocationData("AL: Silver Mask - Leonhard drop", "Silver Mask", missable=True,
+ npc=True),
+ DS3LocationData("AL: Soul of Rosaria - Leonhard drop", "Soul of Rosaria", missable=True,
+ npc=True),
+
+ # Shrine Handmaid after killing Anri or completing their quest
+ DS3LocationData("FS: Elite Knight Helm - shop after Anri quest", "Elite Knight Helm",
+ npc=True, shop=True),
+ DS3LocationData("FS: Elite Knight Armor - shop after Anri quest", "Elite Knight Armor",
+ npc=True, shop=True),
+ DS3LocationData("FS: Elite Knight Gauntlets - shop after Anri quest",
+ "Elite Knight Gauntlets", npc=True, shop=True),
+ DS3LocationData("FS: Elite Knight Leggings - shop after Anri quest",
+ "Elite Knight Leggings", npc=True, shop=True),
],
"Lothric Castle": [
- DS3LocationData("LC: Hood of Prayer", "Hood of Prayer", DS3LocationCategory.ARMOR),
- DS3LocationData("LC: Robe of Prayer", "Robe of Prayer", DS3LocationCategory.ARMOR),
- DS3LocationData("LC: Skirt of Prayer", "Skirt of Prayer", DS3LocationCategory.ARMOR),
- DS3LocationData("LC: Sacred Bloom Shield", "Sacred Bloom Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("LC: Winged Knight Helm", "Winged Knight Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("LC: Winged Knight Armor", "Winged Knight Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("LC: Winged Knight Gauntlets", "Winged Knight Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("LC: Winged Knight Leggings", "Winged Knight Leggings", DS3LocationCategory.ARMOR),
- DS3LocationData("LC: Greatlance", "Greatlance", DS3LocationCategory.WEAPON),
- DS3LocationData("LC: Sniper Crossbow", "Sniper Crossbow", DS3LocationCategory.WEAPON),
- DS3LocationData("LC: Spirit Tree Crest Shield", "Spirit Tree Crest Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("LC: Red Tearstone Ring", "Red Tearstone Ring", DS3LocationCategory.RING),
- DS3LocationData("LC: Caitha's Chime", "Caitha's Chime", DS3LocationCategory.WEAPON),
- DS3LocationData("LC: Braille Divine Tome of Lothric", "Braille Divine Tome of Lothric", DS3LocationCategory.MISC),
- DS3LocationData("LC: Knight's Ring", "Knight's Ring", DS3LocationCategory.RING),
- DS3LocationData("LC: Irithyll Rapier", "Irithyll Rapier", DS3LocationCategory.WEAPON),
- DS3LocationData("LC: Sunlight Straight Sword", "Sunlight Straight Sword", DS3LocationCategory.WEAPON),
- DS3LocationData("LC: Soul of Dragonslayer Armour", "Soul of Dragonslayer Armour", DS3LocationCategory.BOSS),
- DS3LocationData("LC: Grand Archives Key", "Grand Archives Key", DS3LocationCategory.KEY),
- DS3LocationData("LC: Gotthard Twinswords", "Gotthard Twinswords", DS3LocationCategory.WEAPON),
+ DS3LocationData("LC: Soul of Dragonslayer Armour", "Soul of Dragonslayer Armour",
+ prominent=True, boss=True),
+ DS3LocationData("LC: Sniper Bolt - moat, right path end", "Sniper Bolt x11"),
+ DS3LocationData("LC: Sniper Crossbow - moat, right path end", "Sniper Crossbow"),
+ DS3LocationData("LC: Titanite Scale - dark room, upper balcony", "Titanite Scale"),
+ DS3LocationData("LC: Titanite Chunk - dark room mid, out door opposite wyvern",
+ "Titanite Chunk"),
+ DS3LocationData("LC: Greatlance - overlooking Dragon Barracks bonfire", "Greatlance"),
+ DS3LocationData("LC: Titanite Chunk - ascent, first balcony", "Titanite Chunk"),
+ DS3LocationData("LC: Titanite Chunk - ascent, turret before barricades", "Titanite Chunk"),
+ DS3LocationData("LC: Sacred Bloom Shield - ascent, behind illusory wall",
+ "Sacred Bloom Shield", hidden=True), # Behind illusory wall
+ DS3LocationData("LC: Titanite Chunk - ascent, final turret", "Titanite Chunk x2"),
+ DS3LocationData("LC: Refined Gem - plaza", "Refined Gem"),
+ DS3LocationData("LC: Soul of a Crestfallen Knight - by lift bottom",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("LC: Undead Bone Shard - moat, far ledge", "Undead Bone Shard"),
+ DS3LocationData("LC: Lightning Urn - moat, right path, first room", "Lightning Urn x3"),
+ DS3LocationData("LC: Titanite Chunk - moat #1", "Titanite Chunk"),
+ DS3LocationData("LC: Titanite Chunk - moat #2", "Titanite Chunk"),
+ DS3LocationData("LC: Titanite Chunk - moat, near ledge", "Titanite Chunk"),
+ DS3LocationData("LC: Caitha's Chime - chapel, drop onto roof", "Caitha's Chime"),
+ DS3LocationData("LC: Lightning Urn - plaza", "Lightning Urn x6"),
+ DS3LocationData("LC: Ember - plaza, by gate", "Ember"),
+ DS3LocationData("LC: Raw Gem - plaza left", "Raw Gem"),
+ DS3LocationData("LC: Black Firebomb - dark room lower", "Black Firebomb x3"),
+ DS3LocationData("LC: Pale Pine Resin - dark room upper, by mimic", "Pale Pine Resin"),
+ DS3LocationData("LC: Large Soul of a Weary Warrior - main hall, by lever",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("LC: Sunlight Medal - by lift top", "Sunlight Medal"),
+ DS3LocationData("LC: Soul of a Crestfallen Knight - wyvern room, balcony",
+ "Soul of a Crestfallen Knight", hidden=True), # Hidden fall
+ DS3LocationData("LC: Titanite Chunk - altar roof", "Titanite Chunk"),
+ DS3LocationData("LC: Titanite Scale - dark room mid, out door opposite wyvern",
+ "Titanite Scale"),
+ DS3LocationData("LC: Large Soul of a Nameless Soldier - moat, right path",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("LC: Knight's Ring - altar", "Knight's Ring"),
+ DS3LocationData("LC: Ember - main hall, left of stairs", "Ember"),
+ DS3LocationData("LC: Large Soul of a Weary Warrior - ascent, last turret",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("LC: Ember - by Dragon Barracks bonfire", "Ember"),
+ DS3LocationData("LC: Twinkling Titanite - ascent, side room", "Twinkling Titanite"),
+ DS3LocationData("LC: Large Soul of a Nameless Soldier - dark room mid",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("LC: Ember - plaza center", "Ember"),
+ DS3LocationData("LC: Winged Knight Helm - ascent, behind illusory wall",
+ "Winged Knight Helm", hidden=True),
+ DS3LocationData("LC: Winged Knight Armor - ascent, behind illusory wall",
+ "Winged Knight Armor", hidden=True),
+ DS3LocationData("LC: Winged Knight Gauntlets - ascent, behind illusory wall",
+ "Winged Knight Gauntlets", hidden=True),
+ DS3LocationData("LC: Winged Knight Leggings - ascent, behind illusory wall",
+ "Winged Knight Leggings", hidden=True),
+ DS3LocationData("LC: Rusted Coin - chapel", "Rusted Coin x2"),
+ DS3LocationData("LC: Braille Divine Tome of Lothric - wyvern room",
+ "Braille Divine Tome of Lothric", hidden=True), # Hidden fall
+ DS3LocationData("LC: Red Tearstone Ring - chapel, drop onto roof", "Red Tearstone Ring"),
+ DS3LocationData("LC: Twinkling Titanite - moat, left side", "Twinkling Titanite x2"),
+ DS3LocationData("LC: Large Soul of a Nameless Soldier - plaza left, by pillar",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("LC: Titanite Scale - altar", "Titanite Scale x3"),
+ DS3LocationData("LC: Titanite Scale - chapel, chest", "Titanite Scale"),
+ DS3LocationData("LC: Hood of Prayer", "Hood of Prayer"),
+ DS3LocationData("LC: Robe of Prayer - ascent, chest at beginning", "Robe of Prayer"),
+ DS3LocationData("LC: Skirt of Prayer - ascent, chest at beginning", "Skirt of Prayer"),
+ DS3LocationData("LC: Spirit Tree Crest Shield - basement, chest",
+ "Spirit Tree Crest Shield"),
+ DS3LocationData("LC: Titanite Scale - basement, chest", "Titanite Scale"),
+ DS3LocationData("LC: Twinkling Titanite - basement, chest #1", "Twinkling Titanite"),
+ DS3LocationData("LC: Twinkling Titanite - basement, chest #2", "Twinkling Titanite x2"),
+ DS3LocationData("LC: Life Ring+2 - dark room mid, out door opposite wyvern, drop down",
+ "Life Ring+2", ngp=True, hidden=True), # Hidden fall
+ DS3LocationData("LC: Dark Stoneplate Ring+1 - wyvern room, balcony",
+ "Dark Stoneplate Ring+1", ngp=True, hidden=True), # Hidden fall
+ DS3LocationData("LC: Thunder Stoneplate Ring+2 - chapel, drop onto roof",
+ "Thunder Stoneplate Ring+2", ngp=True),
+ DS3LocationData("LC: Sunlight Straight Sword - wyvern room, mimic",
+ "Sunlight Straight Sword", mimic=True, hidden=True), # Hidden fall
+ DS3LocationData("LC: Titanite Scale - dark room, upper, mimic", "Titanite Scale x3",
+ mimic=True),
+ DS3LocationData("LC: Ember - wyvern room, wyvern foot mob drop", "Ember x2",
+ drop=True, hidden=True), # Hidden fall, Pus of Man Wyvern drop
+ DS3LocationData("LC: Titanite Chunk - wyvern room, wyvern foot mob drop", "Titanite Chunk x2",
+ drop=True, hidden=True), # Hidden fall, Pus of Man Wyvern drop
+ DS3LocationData("LC: Ember - dark room mid, pus of man mob drop", "Ember x2",
+ drop=True), # Pus of Man Wyvern drop
+ DS3LocationData("LC: Titanite Chunk - dark room mid, pus of man mob drop",
+ "Titanite Chunk x2"),
+ DS3LocationData("LC: Irithyll Rapier - basement, miniboss drop", "Irithyll Rapier",
+ miniboss=True), # Boreal Outrider drop
+ DS3LocationData("LC: Twinkling Titanite - dark room mid, out door opposite wyvern, lizard",
+ "Twinkling Titanite x2", lizard=True, missable=True),
+ DS3LocationData("LC: Twinkling Titanite - moat, right path, lizard",
+ "Twinkling Titanite x2", lizard=True, missable=True),
+ DS3LocationData("LC: Gotthard Twinswords - by Grand Archives door, after PC and AL bosses",
+ "Gotthard Twinswords", conditional=True),
+ DS3LocationData("LC: Grand Archives Key - by Grand Archives door, after PC and AL bosses",
+ "Grand Archives Key", prominent=True, progression=True,
+ conditional=True),
+ DS3LocationData("LC: Titanite Chunk - down stairs after boss", "Titanite Chunk"),
+
+ # Eygon of Carim (kill or quest)
+ DS3LocationData("FS: Morne's Great Hammer - Eygon", "Morne's Great Hammer", npc=True),
+ DS3LocationData("FS: Moaning Shield - Eygon", "Moaning Shield", npc=True),
+
+ # Shrine Handmaid after killing Dragonslayer Armour (or Eygon of Carim)
+ DS3LocationData("FS: Dancer's Crown - shop after killing LC entry boss", "Dancer's Crown",
+ boss=True, shop=True),
+ DS3LocationData("FS: Dancer's Armor - shop after killing LC entry boss", "Dancer's Armor",
+ boss=True, shop=True),
+ DS3LocationData("FS: Dancer's Gauntlets - shop after killing LC entry boss",
+ "Dancer's Gauntlets", boss=True, shop=True),
+ DS3LocationData("FS: Dancer's Leggings - shop after killing LC entry boss",
+ "Dancer's Leggings", boss=True, shop=True),
+
+ # Shrine Handmaid after killing Dragonslayer Armour (or Eygon of Carim)
+ DS3LocationData("FS: Morne's Helm - shop after killing Eygon or LC boss", "Morne's Helm",
+ boss=True, shop=True),
+ DS3LocationData("FS: Morne's Armor - shop after killing Eygon or LC boss", "Morne's Armor",
+ boss=True, shop=True),
+ DS3LocationData("FS: Morne's Gauntlets - shop after killing Eygon or LC boss",
+ "Morne's Gauntlets", boss=True, shop=True),
+ DS3LocationData("FS: Morne's Leggings - shop after killing Eygon or LC boss",
+ "Morne's Leggings", boss=True, shop=True),
],
"Consumed King's Garden": [
- DS3LocationData("CKG: Dragonscale Ring", "Dragonscale Ring", DS3LocationCategory.RING),
- DS3LocationData("CKG: Shadow Mask", "Shadow Mask", DS3LocationCategory.ARMOR),
- DS3LocationData("CKG: Shadow Garb", "Shadow Garb", DS3LocationCategory.ARMOR),
- DS3LocationData("CKG: Shadow Gauntlets", "Shadow Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("CKG: Shadow Leggings", "Shadow Leggings", DS3LocationCategory.ARMOR),
- DS3LocationData("CKG: Claw", "Claw", DS3LocationCategory.WEAPON),
- DS3LocationData("CKG: Soul of Consumed Oceiros", "Soul of Consumed Oceiros", DS3LocationCategory.BOSS),
- DS3LocationData("CKG: Magic Stoneplate Ring", "Magic Stoneplate Ring", DS3LocationCategory.RING),
+ DS3LocationData("CKG: Soul of Consumed Oceiros", "Soul of Consumed Oceiros",
+ prominent=True, boss=True),
+ # Could classify this as "hidden" because it's midway down an elevator, but the elevator is
+ # so slow and the midway point is so obvious that it's not actually hard to find.
+ DS3LocationData("CKG: Estus Shard - balcony", "Estus Shard"),
+ DS3LocationData("CKG: Shadow Mask - under center platform", "Shadow Mask"),
+ DS3LocationData("CKG: Shadow Garb - under rotunda", "Shadow Garb"),
+ DS3LocationData("CKG: Shadow Gauntlets - under rotunda", "Shadow Gauntlets"),
+ DS3LocationData("CKG: Shadow Leggings - under rotunda", "Shadow Leggings"),
+ DS3LocationData("CKG: Black Firebomb - under rotunda", "Black Firebomb x2"),
+ DS3LocationData("CKG: Claw - under rotunda", "Claw"),
+ DS3LocationData("CKG: Titanite Chunk - up lone stairway", "Titanite Chunk"),
+ DS3LocationData("CKG: Dragonscale Ring - shortcut, leave halfway down lift",
+ "Dragonscale Ring"),
+ DS3LocationData("CKG: Human Pine Resin - toxic pool, past rotunda", "Human Pine Resin"),
+ DS3LocationData("CKG: Titanite Chunk - shortcut", "Titanite Chunk"),
+ DS3LocationData("CKG: Titanite Chunk - balcony, drop onto rubble", "Titanite Chunk"),
+ DS3LocationData("CKG: Soul of a Weary Warrior - before first lift",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("CKG: Dark Gem - under lone stairway", "Dark Gem"),
+ DS3LocationData("CKG: Titanite Scale - shortcut", "Titanite Scale"),
+ DS3LocationData("CKG: Human Pine Resin - pool by lift", "Human Pine Resin x2"),
+ DS3LocationData("CKG: Titanite Chunk - right of shortcut lift bottom", "Titanite Chunk"),
+ DS3LocationData("CKG: Ring of Sacrifice - under balcony", "Ring of Sacrifice"),
+ DS3LocationData("CKG: Wood Grain Ring+1 - by first elevator bottom", "Wood Grain Ring+1",
+ ngp=True),
+ DS3LocationData("CKG: Sage Ring+2 - balcony, drop onto rubble, jump back", "Sage Ring+2",
+ ngp=True, hidden=True),
+ DS3LocationData("CKG: Titanite Scale - tomb, chest #1", "Titanite Scale"),
+ DS3LocationData("CKG: Titanite Scale - tomb, chest #2", "Titanite Scale"),
+ DS3LocationData("CKG: Magic Stoneplate Ring - mob drop before boss",
+ "Magic Stoneplate Ring", drop=True,
+ hidden=True), # Guaranteed drop from a normal-looking Cathedral Knight
+
+ # After Oceiros's boss room, only once the Drakeblood summon in AP has been killed
+ DS3LocationData("CKG: Drakeblood Helm - tomb, after killing AP mausoleum NPC",
+ "Drakeblood Helm", hostile_npc=True, hidden=True),
+ DS3LocationData("CKG: Drakeblood Armor - tomb, after killing AP mausoleum NPC",
+ "Drakeblood Armor", hostile_npc=True, hidden=True),
+ DS3LocationData("CKG: Drakeblood Gauntlets - tomb, after killing AP mausoleum NPC",
+ "Drakeblood Gauntlets", hostile_npc=True, hidden=True),
+ DS3LocationData("CKG: Drakeblood Leggings - tomb, after killing AP mausoleum NPC",
+ "Drakeblood Leggings", hostile_npc=True, hidden=True),
],
"Grand Archives": [
- DS3LocationData("GA: Avelyn", "Avelyn", DS3LocationCategory.WEAPON),
- DS3LocationData("GA: Witch's Locks", "Witch's Locks", DS3LocationCategory.WEAPON),
- DS3LocationData("GA: Power Within", "Power Within", DS3LocationCategory.SPELL),
- DS3LocationData("GA: Scholar Ring", "Scholar Ring", DS3LocationCategory.RING),
- DS3LocationData("GA: Soul Stream", "Soul Stream", DS3LocationCategory.SPELL),
- DS3LocationData("GA: Fleshbite Ring", "Fleshbite Ring", DS3LocationCategory.RING),
- DS3LocationData("GA: Crystal Chime", "Crystal Chime", DS3LocationCategory.WEAPON),
- DS3LocationData("GA: Golden Wing Crest Shield", "Golden Wing Crest Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("GA: Onikiri and Ubadachi", "Onikiri and Ubadachi", DS3LocationCategory.WEAPON),
- DS3LocationData("GA: Hunter's Ring", "Hunter's Ring", DS3LocationCategory.RING),
- DS3LocationData("GA: Divine Pillars of Light", "Divine Pillars of Light", DS3LocationCategory.SPELL),
- DS3LocationData("GA: Cinders of a Lord - Lothric Prince", "Cinders of a Lord - Lothric Prince", DS3LocationCategory.KEY),
- DS3LocationData("GA: Soul of the Twin Princes", "Soul of the Twin Princes", DS3LocationCategory.BOSS),
- DS3LocationData("GA: Sage's Crystal Staff", "Sage's Crystal Staff", DS3LocationCategory.WEAPON),
- DS3LocationData("GA: Outrider Knight Helm", "Outrider Knight Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("GA: Outrider Knight Armor", "Outrider Knight Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("GA: Outrider Knight Gauntlets", "Outrider Knight Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("GA: Outrider Knight Leggings", "Outrider Knight Leggings", DS3LocationCategory.ARMOR),
- DS3LocationData("GA: Crystal Scroll", "Crystal Scroll", DS3LocationCategory.MISC),
+ DS3LocationData("GA: Titanite Slab - final elevator secret", "Titanite Slab",
+ hidden=True),
+ DS3LocationData("GA: Soul of the Twin Princes", "Soul of the Twin Princes", boss=True),
+ DS3LocationData("GA: Cinders of a Lord - Lothric Prince",
+ "Cinders of a Lord - Lothric Prince",
+ static="09,0:50002040::", prominent=True, progression=True,
+ boss=True),
+ DS3LocationData("GA: Onikiri and Ubadachi - outside 5F, NPC drop", "Onikiri and Ubadachi",
+ hostile_npc=True, # Black Hand Kamui drop
+ missable=True), # This is placed at the location the NPC gets randomized
+ # to, which makes it hard to include in logic.
+ DS3LocationData("GA: Golden Wing Crest Shield - outside 5F, NPC drop",
+ "Golden Wing Crest Shield",
+ hostile_npc=True), # Lion Knight Albert drop
+ DS3LocationData("GA: Sage's Crystal Staff - outside 5F, NPC drop",
+ "Sage's Crystal Staff",
+ hostile_npc=True), # Daughter of Crystal Kriemhild drop
+ DS3LocationData("GA: Titanite Chunk - 1F, up right stairs", "Titanite Chunk"),
+ DS3LocationData("GA: Titanite Chunk - 1F, path from wax pool", "Titanite Chunk"),
+ DS3LocationData("GA: Soul of a Crestfallen Knight - 1F, loop left after drop",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("GA: Titanite Chunk - 1F, balcony", "Titanite Chunk"),
+ DS3LocationData("GA: Fleshbite Ring - up stairs from 4F", "Fleshbite Ring"),
+ DS3LocationData("GA: Soul of a Crestfallen Knight - path to dome",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("GA: Soul of a Nameless Soldier - dark room", "Soul of a Nameless Soldier"),
+ DS3LocationData("GA: Crystal Chime - 1F, path from wax pool", "Crystal Chime"),
+ DS3LocationData("GA: Titanite Scale - dark room, upstairs", "Titanite Scale"),
+ DS3LocationData("GA: Estus Shard - dome, far balcony", "Estus Shard"),
+ DS3LocationData("GA: Homeward Bone - 2F early balcony", "Homeward Bone x3"),
+ DS3LocationData("GA: Titanite Scale - 2F, titanite scale atop bookshelf", "Titanite Scale",
+ hidden=True), # Hidden fall
+ DS3LocationData("GA: Titanite Chunk - 2F, by wax pool", "Titanite Chunk"),
+ DS3LocationData("GA: Hollow Gem - rooftops lower, in hall", "Hollow Gem",
+ hidden=True), # Hidden fall
+ DS3LocationData("GA: Titanite Scale - 3F, corner up stairs", "Titanite Scale"),
+ DS3LocationData("GA: Titanite Scale - 1F, up stairs on bookshelf", "Titanite Scale"),
+ DS3LocationData("GA: Titanite Scale - 3F, by ladder to 2F late", "Titanite Scale",
+ hidden=True), # Hidden by a table
+ DS3LocationData("GA: Shriving Stone - 2F late, by ladder from 3F", "Shriving Stone"),
+ DS3LocationData("GA: Large Soul of a Crestfallen Knight - 4F, back",
+ "Large Soul of a Crestfallen Knight"),
+ DS3LocationData("GA: Titanite Chunk - rooftops, balcony", "Titanite Chunk"),
+ DS3LocationData("GA: Titanite Scale - rooftops lower, path to 2F", "Titanite Scale x3",
+ hidden=True), # Hidden fall
+ DS3LocationData("GA: Titanite Chunk - rooftops lower, ledge by buttress", "Titanite Chunk",
+ hidden=True), # Hidden fall
+ DS3LocationData("GA: Soul of a Weary Warrior - rooftops, by lizards",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("GA: Titanite Chunk - rooftops, just before 5F", "Titanite Chunk"),
+ DS3LocationData("GA: Ember - 5F, by entrance", "Ember"),
+ DS3LocationData("GA: Blessed Gem - rafters", "Blessed Gem"),
+ DS3LocationData("GA: Titanite Chunk - 5F, far balcony", "Titanite Chunk x2"),
+ DS3LocationData("GA: Large Soul of a Crestfallen Knight - outside 5F",
+ "Large Soul of a Crestfallen Knight"),
+ DS3LocationData("GA: Avelyn - 1F, drop from 3F onto bookshelves", "Avelyn",
+ hidden=True), # Hidden fall
+ DS3LocationData("GA: Titanite Chunk - 2F, right after dark room", "Titanite Chunk"),
+ DS3LocationData("GA: Hunter's Ring - dome, very top", "Hunter's Ring"),
+ DS3LocationData("GA: Divine Pillars of Light - cage above rafters",
+ "Divine Pillars of Light"),
+ DS3LocationData("GA: Power Within - dark room, behind retractable bookshelf",
+ "Power Within", hidden=True), # Switch in darkened room
+ DS3LocationData("GA: Sage Ring+1 - rafters, second level down", "Sage Ring+1", ngp=True),
+ DS3LocationData("GA: Lingering Dragoncrest Ring+2 - dome, room behind spire",
+ "Lingering Dragoncrest Ring+2", ngp=True),
+ DS3LocationData("GA: Divine Blessing - rafters, down lower level ladder",
+ "Divine Blessing"),
+ DS3LocationData("GA: Twinkling Titanite - rafters, down lower level ladder",
+ "Twinkling Titanite x3"),
+ DS3LocationData("GA: Witch's Locks - dark room, behind retractable bookshelf",
+ "Witch's Locks", hidden=True), # Switch in darkened room
+ DS3LocationData("GA: Titanite Slab - 1F, after pulling 2F switch", "Titanite Slab",
+ hidden=True),
+ DS3LocationData("GA: Titanite Scale - 4F, chest by exit", "Titanite Scale x3"),
+ DS3LocationData("GA: Soul Stream - 3F, behind illusory wall", "Soul Stream",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("GA: Scholar Ring - 2F, between late and early", "Scholar Ring"),
+ DS3LocationData("GA: Undead Bone Shard - 5F, by entrance", "Undead Bone Shard"),
+ DS3LocationData("GA: Titanite Slab - dome, kill all mobs", "Titanite Slab",
+ drop=True,
+ hidden=True), # Guaranteed drop from killing all Winged Knights
+ DS3LocationData("GA: Outrider Knight Helm - 3F, behind illusory wall, miniboss drop",
+ "Outrider Knight Helm", miniboss=True,
+ hidden=True), # Behind illusory wall, Outrider Knight drop
+ DS3LocationData("GA: Outrider Knight Armor - 3F, behind illusory wall, miniboss drop",
+ "Outrider Knight Armor", miniboss=True,
+ hidden=True), # Behind illusory wall, Outrider Knight drop
+ DS3LocationData("GA: Outrider Knight Gauntlets - 3F, behind illusory wall, miniboss drop",
+ "Outrider Knight Gauntlets", miniboss=True,
+ hidden=True), # Behind illusory wall, Outrider Knight drop
+ DS3LocationData("GA: Outrider Knight Leggings - 3F, behind illusory wall, miniboss drop",
+ "Outrider Knight Leggings", miniboss=True,
+ hidden=True), # Behind illusory wall, Outrider Knight drop
+ DS3LocationData("GA: Crystal Scroll - 2F late, miniboss drop", "Crystal Scroll",
+ miniboss=True), # Crystal Sage drop
+ DS3LocationData("GA: Twinkling Titanite - dark room, lizard #1", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("GA: Chaos Gem - dark room, lizard", "Chaos Gem", lizard=True),
+ DS3LocationData("GA: Twinkling Titanite - 1F, lizard by drop", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("GA: Crystal Gem - 1F, lizard by drop", "Crystal Gem", lizard=True),
+ DS3LocationData("GA: Twinkling Titanite - 2F, lizard by entrance", "Twinkling Titanite x2",
+ lizard=True),
+ DS3LocationData("GA: Titanite Scale - 1F, drop from 2F late onto bookshelves, lizard",
+ "Titanite Scale x2", lizard=True, hidden=True), # Hidden fall
+ DS3LocationData("GA: Twinkling Titanite - rooftops, lizard #1", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("GA: Heavy Gem - rooftops, lizard", "Heavy Gem", lizard=True),
+ DS3LocationData("GA: Twinkling Titanite - rooftops, lizard #2", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("GA: Sharp Gem - rooftops, lizard", "Sharp Gem", lizard=True),
+ DS3LocationData("GA: Twinkling Titanite - up stairs from 4F, lizard", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("GA: Refined Gem - up stairs from 4F, lizard", "Refined Gem",
+ lizard=True),
+ DS3LocationData("GA: Twinkling Titanite - dark room, lizard #2", "Twinkling Titanite x2",
+ lizard=True),
+
+ # Shrine Handmaid after killing NPCs
+ DS3LocationData("FS: Faraam Helm - shop after killing GA NPC", "Faraam Helm",
+ hidden=True, hostile_npc=True, shop=True),
+ DS3LocationData("FS: Faraam Armor - shop after killing GA NPC", "Faraam Armor",
+ hidden=True, hostile_npc=True, shop=True),
+ DS3LocationData("FS: Faraam Gauntlets - shop after killing GA NPC", "Faraam Gauntlets",
+ hidden=True, hostile_npc=True, shop=True),
+ DS3LocationData("FS: Faraam Boots - shop after killing GA NPC", "Faraam Boots",
+ hidden=True, hostile_npc=True, shop=True),
+ DS3LocationData("FS: Black Hand Hat - shop after killing GA NPC", "Black Hand Hat",
+ hidden=True, hostile_npc=True, shop=True),
+ DS3LocationData("FS: Black Hand Armor - shop after killing GA NPC", "Black Hand Armor",
+ hidden=True, hostile_npc=True, shop=True),
+
+ # Shrine Handmaid after killing Lothric, Younger Prince
+ DS3LocationData("FS: Lorian's Helm - shop after killing GA boss", "Lorian's Helm",
+ boss=True, shop=True),
+ DS3LocationData("FS: Lorian's Armor - shop after killing GA boss", "Lorian's Armor",
+ boss=True, shop=True),
+ DS3LocationData("FS: Lorian's Gauntlets - shop after killing GA boss", "Lorian's Gauntlets",
+ boss=True, shop=True),
+ DS3LocationData("FS: Lorian's Leggings - shop after killing GA boss", "Lorian's Leggings",
+ boss=True, shop=True),
+
+ # Sirris quest completion + beat Twin Princes
+ DS3LocationData("FS: Sunless Talisman - Sirris, kill GA boss", "Sunless Talisman",
+ missable=True, npc=True),
+ DS3LocationData("FS: Sunless Veil - shop, Sirris quest, kill GA boss", "Sunless Veil",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Sunless Armor - shop, Sirris quest, kill GA boss", "Sunless Armor",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Sunless Gauntlets - shop, Sirris quest, kill GA boss",
+ "Sunless Gauntlets", missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Sunless Leggings - shop, Sirris quest, kill GA boss",
+ "Sunless Leggings", missable=True, npc=True, shop=True),
+
+ # Unbreakable Patches
+ DS3LocationData("FS: Hidden Blessing - Patches after searching GA", "Hidden Blessing",
+ missable=True, npc=True, shop=True),
],
"Untended Graves": [
- DS3LocationData("UG: Ashen Estus Ring", "Ashen Estus Ring", DS3LocationCategory.RING),
- DS3LocationData("UG: Black Knight Glaive", "Black Knight Glaive", DS3LocationCategory.WEAPON),
- DS3LocationData("UG: Hornet Ring", "Hornet Ring", DS3LocationCategory.RING),
- DS3LocationData("UG: Chaos Blade", "Chaos Blade", DS3LocationCategory.WEAPON),
- DS3LocationData("UG: Blacksmith Hammer", "Blacksmith Hammer", DS3LocationCategory.WEAPON),
- DS3LocationData("UG: Eyes of a Fire Keeper", "Eyes of a Fire Keeper", DS3LocationCategory.KEY),
- DS3LocationData("UG: Coiled Sword Fragment", "Coiled Sword Fragment", DS3LocationCategory.MISC),
- DS3LocationData("UG: Soul of Champion Gundyr", "Soul of Champion Gundyr", DS3LocationCategory.BOSS),
+ DS3LocationData("UG: Soul of Champion Gundyr", "Soul of Champion Gundyr", prominent=True,
+ boss=True),
+ DS3LocationData("UG: Priestess Ring - shop", "Priestess Ring", shop=True),
+ DS3LocationData("UG: Shriving Stone - swamp, by bonfire", "Shriving Stone"),
+ DS3LocationData("UG: Titanite Chunk - swamp, left path by fountain", "Titanite Chunk"),
+ DS3LocationData("UG: Soul of a Crestfallen Knight - swamp, center",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("UG: Titanite Chunk - swamp, right path by fountain", "Titanite Chunk"),
+ DS3LocationData("UG: Ashen Estus Ring - swamp, path opposite bonfire", "Ashen Estus Ring"),
+ DS3LocationData("UG: Black Knight Glaive - boss arena", "Black Knight Glaive"),
+ DS3LocationData("UG: Hidden Blessing - cemetery, behind coffin", "Hidden Blessing"),
+ DS3LocationData("UG: Eyes of a Fire Keeper - shrine, Irina's room", "Eyes of a Fire Keeper",
+ hidden=True), # Illusory wall
+ DS3LocationData("UG: Soul of a Crestfallen Knight - environs, above shrine entrance",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("UG: Blacksmith Hammer - shrine, Andre's room", "Blacksmith Hammer"),
+ DS3LocationData("UG: Chaos Blade - environs, left of shrine", "Chaos Blade"),
+ DS3LocationData("UG: Hornet Ring - environs, right of main path after killing FK boss",
+ "Hornet Ring", conditional=True),
+ DS3LocationData("UG: Coiled Sword Fragment - shrine, dead bonfire", "Coiled Sword Fragment",
+ boss=True),
+ DS3LocationData("UG: Life Ring+3 - shrine, behind big throne", "Life Ring+3", ngp=True),
+ DS3LocationData("UG: Ring of Steel Protection+1 - environs, behind bell tower",
+ "Ring of Steel Protection+1", ngp=True),
+
+ # Yuria shop, or Shrine Handmaiden with Hollow's Ashes
+ # This is here because this is where the ashes end up if you kill Yoel or Yuria
+ DS3LocationData("FS: Ring of Sacrifice - Yuria shop", "Ring of Sacrifice",
+ static='99,0:-1:40000,110000,70000107,70000116:', npc=True,
+ shop=True),
+
+ # Untended Graves Handmaid
+ # All shop items are missable because she can be killed, except Priestess ring because she
+ # drops it on death anyway.
+ DS3LocationData("UG: Ember - shop", "Ember", shop=True, missable=True),
+ # Untended Graves Handmaid after killing Abyss Watchers
+ DS3LocationData("UG: Wolf Knight Helm - shop after killing FK boss", "Wolf Knight Helm",
+ boss=True, shop=True, conditional=True,
+ missable=True),
+ DS3LocationData("UG: Wolf Knight Armor - shop after killing FK boss",
+ "Wolf Knight Armor", boss=True, shop=True, missable=True),
+ DS3LocationData("UG: Wolf Knight Gauntlets - shop after killing FK boss",
+ "Wolf Knight Gauntlets", boss=True, shop=True, missable=True),
+ DS3LocationData("UG: Wolf Knight Leggings - shop after killing FK boss",
+ "Wolf Knight Leggings", boss=True, shop=True, missable=True),
+
+ # Shrine Handmaid after killing Champion Gundyr
+ DS3LocationData("FS: Gundyr's Helm - shop after killing UG boss", "Gundyr's Helm",
+ boss=True, shop=True),
+ DS3LocationData("FS: Gundyr's Armor - shop after killing UG boss", "Gundyr's Armor",
+ boss=True, shop=True),
+ DS3LocationData("FS: Gundyr's Gauntlets - shop after killing UG boss", "Gundyr's Gauntlets",
+ boss=True, shop=True),
+ DS3LocationData("FS: Gundyr's Leggings - shop after killing UG boss", "Gundyr's Leggings",
+ boss=True, shop=True),
],
"Archdragon Peak": [
- DS3LocationData("AP: Lightning Clutch Ring", "Lightning Clutch Ring", DS3LocationCategory.RING),
- DS3LocationData("AP: Ancient Dragon Greatshield", "Ancient Dragon Greatshield", DS3LocationCategory.SHIELD),
- DS3LocationData("AP: Ring of Steel Protection", "Ring of Steel Protection", DS3LocationCategory.RING),
- DS3LocationData("AP: Calamity Ring", "Calamity Ring", DS3LocationCategory.RING),
- DS3LocationData("AP: Drakeblood Greatsword", "Drakeblood Greatsword", DS3LocationCategory.WEAPON),
- DS3LocationData("AP: Dragonslayer Spear", "Dragonslayer Spear", DS3LocationCategory.WEAPON),
- DS3LocationData("AP: Thunder Stoneplate Ring", "Thunder Stoneplate Ring", DS3LocationCategory.RING),
- DS3LocationData("AP: Great Magic Barrier", "Great Magic Barrier", DS3LocationCategory.SPELL),
- DS3LocationData("AP: Dragon Chaser's Ashes", "Dragon Chaser's Ashes", DS3LocationCategory.MISC),
- DS3LocationData("AP: Twinkling Dragon Torso Stone", "Twinkling Dragon Torso Stone", DS3LocationCategory.MISC),
- DS3LocationData("AP: Dragonslayer Helm", "Dragonslayer Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("AP: Dragonslayer Armor", "Dragonslayer Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("AP: Dragonslayer Gauntlets", "Dragonslayer Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("AP: Dragonslayer Leggings", "Dragonslayer Leggings", DS3LocationCategory.ARMOR),
- DS3LocationData("AP: Ricard's Rapier", "Ricard's Rapier", DS3LocationCategory.WEAPON),
- DS3LocationData("AP: Soul of the Nameless King", "Soul of the Nameless King", DS3LocationCategory.BOSS),
- DS3LocationData("AP: Dragon Tooth", "Dragon Tooth", DS3LocationCategory.WEAPON),
- DS3LocationData("AP: Havel's Greatshield", "Havel's Greatshield", DS3LocationCategory.SHIELD),
+ DS3LocationData("AP: Dragon Head Stone - fort, boss drop", "Dragon Head Stone",
+ prominent=True, boss=True),
+ DS3LocationData("AP: Soul of the Nameless King", "Soul of the Nameless King",
+ prominent=True, boss=True),
+ DS3LocationData("AP: Dragon Tooth - belfry roof, NPC drop", "Dragon Tooth",
+ hostile_npc=True), # Havel Knight drop
+ DS3LocationData("AP: Havel's Greatshield - belfry roof, NPC drop", "Havel's Greatshield",
+ hostile_npc=True), # Havel Knight drop
+ DS3LocationData("AP: Drakeblood Greatsword - mausoleum, NPC drop", "Drakeblood Greatsword",
+ hostile_npc=True),
+ DS3LocationData("AP: Ricard's Rapier - belfry, NPC drop", "Ricard's Rapier",
+ hostile_npc=True),
+ DS3LocationData("AP: Lightning Clutch Ring - intro, left of boss door",
+ "Lightning Clutch Ring"),
+ DS3LocationData("AP: Stalk Dung Pie - fort overlook", "Stalk Dung Pie x6"),
+ DS3LocationData("AP: Titanite Chunk - fort, second room balcony", "Titanite Chunk"),
+ DS3LocationData("AP: Titanite Scale - mausoleum, downstairs balcony #1",
+ "Titanite Scale"),
+ DS3LocationData("AP: Soul of a Weary Warrior - intro, first cliff edge",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("AP: Titanite Chunk - intro, left before archway", "Titanite Chunk"),
+ DS3LocationData("AP: Lightning Gem - intro, side rise", "Lightning Gem"),
+ DS3LocationData("AP: Homeward Bone - intro, path to bonfire", "Homeward Bone x2"),
+ DS3LocationData("AP: Soul of a Nameless Soldier - intro, right before archway",
+ "Soul of a Nameless Soldier"),
+ DS3LocationData("AP: Titanite Chunk - intro, archway corner", "Titanite Chunk"),
+ DS3LocationData("AP: Ember - fort overlook #1", "Ember"),
+ DS3LocationData("AP: Large Soul of a Weary Warrior - fort, center",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("AP: Large Soul of a Nameless Soldier - fort, by stairs to first room",
+ "Large Soul of a Nameless Soldier"),
+ DS3LocationData("AP: Lightning Urn - fort, left of first room entrance",
+ "Lightning Urn x4"),
+ DS3LocationData("AP: Lightning Bolt - rotunda", "Lightning Bolt x12"),
+ DS3LocationData("AP: Titanite Chunk - rotunda", "Titanite Chunk x2"),
+ # Not 100% sure about this location name, can't find this on any maps
+ DS3LocationData("AP: Dung Pie - fort, landing after second room", "Dung Pie x3"),
+ DS3LocationData("AP: Titanite Scale - mausoleum, downstairs balcony #2", "Titanite Scale"),
+ DS3LocationData("AP: Soul of a Weary Warrior - walkway, building window",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("AP: Soul of a Crestfallen Knight - mausoleum, upstairs",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("AP: Titanite Chunk - intro, behind rock", "Titanite Chunk"),
+ DS3LocationData("AP: Ember - fort overlook #2", "Ember"),
+ DS3LocationData("AP: Thunder Stoneplate Ring - walkway, up ladder",
+ "Thunder Stoneplate Ring"),
+ DS3LocationData("AP: Titanite Scale - mausoleum, upstairs balcony", "Titanite Scale"),
+ DS3LocationData("AP: Ember - belfry, below bell", "Ember"),
+ DS3LocationData("AP: Ancient Dragon Greatshield - intro, on archway",
+ "Ancient Dragon Greatshield"),
+ DS3LocationData("AP: Large Soul of a Crestfallen Knight - summit, by fountain",
+ "Large Soul of a Crestfallen Knight"),
+ DS3LocationData("AP: Dragon Chaser's Ashes - summit, side path", "Dragon Chaser's Ashes",
+ progression=True),
+ DS3LocationData("AP: Ember - intro, by bonfire", "Ember"),
+ DS3LocationData("AP: Dragonslayer Spear - gate after mausoleum", "Dragonslayer Spear"),
+ DS3LocationData("AP: Dragonslayer Helm - plaza", "Dragonslayer Helm"),
+ DS3LocationData("AP: Dragonslayer Armor - plaza", "Dragonslayer Armor"),
+ DS3LocationData("AP: Dragonslayer Gauntlets - plaza", "Dragonslayer Gauntlets"),
+ DS3LocationData("AP: Dragonslayer Leggings - plaza", "Dragonslayer Leggings"),
+ DS3LocationData("AP: Twinkling Titanite - fort, end of rafters", "Twinkling Titanite x2"),
+ DS3LocationData("AP: Twinkling Titanite - fort, down second room balcony ladder",
+ "Twinkling Titanite x2"),
+ DS3LocationData("AP: Titanite Slab - belfry roof", "Titanite Slab"),
+ DS3LocationData("AP: Great Magic Barrier - drop off belfry roof", "Great Magic Barrier",
+ hidden=True), # Hidden fall
+ DS3LocationData("AP: Titanite Slab - plaza", "Titanite Slab"),
+ DS3LocationData("AP: Ring of Steel Protection - fort overlook, beside stairs",
+ "Ring of Steel Protection"),
+ DS3LocationData("AP: Havel's Ring+1 - summit, after building", "Havel's Ring+1",
+ ngp=True),
+ DS3LocationData("AP: Covetous Gold Serpent Ring+2 - plaza", "Covetous Gold Serpent Ring+2",
+ ngp=True),
+ DS3LocationData("AP: Titanite Scale - walkway building", "Titanite Scale x3"),
+ DS3LocationData("AP: Twinkling Titanite - belfry, by ladder to roof",
+ "Twinkling Titanite x3"),
+ DS3LocationData("AP: Twinkling Dragon Torso Stone - summit, gesture at altar",
+ "Twinkling Dragon Torso Stone", hidden=True), # Requires gesture
+ DS3LocationData("AP: Calamity Ring - mausoleum, gesture at altar", "Calamity Ring",
+ hidden=True), # Requires gesture
+ DS3LocationData("AP: Twinkling Titanite - walkway building, lizard",
+ "Twinkling Titanite x3", lizard=True),
+ DS3LocationData("AP: Titanite Chunk - walkway, miniboss drop", "Titanite Chunk x6",
+ miniboss=True), # Wyvern miniboss drop
+ DS3LocationData("AP: Titanite Scale - walkway, miniboss drop", "Titanite Scale x3",
+ miniboss=True), # Wyvern miniboss drop
+ DS3LocationData("AP: Twinkling Titanite - walkway, miniboss drop", "Twinkling Titanite x3",
+ miniboss=True), # Wyvern miniboss drop
+ DS3LocationData("FS: Hawkwood's Swordgrass - Andre after gesture in AP summit",
+ "Hawkwood's Swordgrass", conditional=True, hidden=True),
+
+ # Shrine Handmaid after killing Nameless King
+ DS3LocationData("FS: Golden Crown - shop after killing AP boss", "Golden Crown",
+ boss=True, shop=True),
+ DS3LocationData("FS: Dragonscale Armor - shop after killing AP boss", "Dragonscale Armor",
+ boss=True, shop=True),
+ DS3LocationData("FS: Golden Bracelets - shop after killing AP boss", "Golden Bracelets",
+ boss=True, shop=True),
+ DS3LocationData("FS: Dragonscale Waistcloth - shop after killing AP boss",
+ "Dragonscale Waistcloth", boss=True, shop=True),
+ DS3LocationData("FK: Twinkling Dragon Head Stone - Hawkwood drop",
+ "Twinkling Dragon Head Stone", missable=True,
+ npc=True), # Hawkwood (quest)
+ ],
+ "Kiln of the First Flame": [
+ DS3LocationData("KFF: Soul of the Lords", "Soul of the Lords", boss=True),
+
+ # Shrine Handmaid after placing all Cinders of a Lord
+ DS3LocationData("FS: Titanite Slab - shop after placing all Cinders", "Titanite Slab",
+ static='99,0:-1:9210,110000:', hidden=True),
+ DS3LocationData("FS: Firelink Helm - shop after placing all Cinders", "Firelink Helm",
+ boss=True, shop=True),
+ DS3LocationData("FS: Firelink Armor - shop after placing all Cinders", "Firelink Armor",
+ boss=True, shop=True),
+ DS3LocationData("FS: Firelink Gauntlets - shop after placing all Cinders",
+ "Firelink Gauntlets", boss=True, shop=True),
+ DS3LocationData("FS: Firelink Leggings - shop after placing all Cinders",
+ "Firelink Leggings", boss=True, shop=True),
+
+ # Yuria (quest, after Soul of Cinder)
+ DS3LocationData("FS: Billed Mask - Yuria after killing KFF boss", "Billed Mask",
+ missable=True, npc=True),
+ DS3LocationData("FS: Black Dress - Yuria after killing KFF boss", "Black Dress",
+ missable=True, npc=True),
+ DS3LocationData("FS: Black Gauntlets - Yuria after killing KFF boss", "Black Gauntlets",
+ missable=True, npc=True),
+ DS3LocationData("FS: Black Leggings - Yuria after killing KFF boss", "Black Leggings",
+ missable=True, npc=True),
],
- "Kiln of the First Flame": [],
# DLC
- "Painted World of Ariandel 1": [
- DS3LocationData("PW: Follower Javelin", "Follower Javelin", DS3LocationCategory.WEAPON),
- DS3LocationData("PW: Frozen Weapon", "Frozen Weapon", DS3LocationCategory.SPELL),
- DS3LocationData("PW: Millwood Greatbow", "Millwood Greatbow", DS3LocationCategory.WEAPON),
- DS3LocationData("PW: Captain's Ashes", "Captain's Ashes", DS3LocationCategory.MISC),
- DS3LocationData("PW: Millwood Battle Axe", "Millwood Battle Axe", DS3LocationCategory.WEAPON),
- DS3LocationData("PW: Ethereal Oak Shield", "Ethereal Oak Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("PW: Crow Quills", "Crow Quills", DS3LocationCategory.WEAPON),
- DS3LocationData("PW: Slave Knight Hood", "Slave Knight Hood", DS3LocationCategory.ARMOR),
- DS3LocationData("PW: Slave Knight Armor", "Slave Knight Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("PW: Slave Knight Gauntlets", "Slave Knight Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("PW: Slave Knight Leggings", "Slave Knight Leggings", DS3LocationCategory.ARMOR),
- DS3LocationData("PW: Way of White Corona", "Way of White Corona", DS3LocationCategory.SPELL),
- DS3LocationData("PW: Crow Talons", "Crow Talons", DS3LocationCategory.WEAPON),
- DS3LocationData("PW: Onyx Blade", "Onyx Blade", DS3LocationCategory.WEAPON),
- DS3LocationData("PW: Contraption Key", "Contraption Key", DS3LocationCategory.KEY),
+ "Painted World of Ariandel (Before Contraption)": [
+ DS3LocationData("PW1: Valorheart - boss drop", "Valorheart", prominent=True, boss=True),
+ DS3LocationData("PW1: Contraption Key - library, NPC drop", "Contraption Key",
+ prominent=True, progression=True,
+ hostile_npc=True), # Sir Vilhelm drop
+ DS3LocationData("PW1: Onyx Blade - library, NPC drop", "Onyx Blade",
+ hostile_npc=True), # Sir Vilhelm drop
+ DS3LocationData("PW1: Chillbite Ring - Friede", "Chillbite Ring",
+ npc=True), # Friede conversation
+ DS3LocationData("PW1: Rime-blue Moss Clump - snowfield upper, starting cave",
+ "Rime-blue Moss Clump x2"),
+ DS3LocationData("PW1: Poison Gem - snowfield upper, forward from bonfire", "Poison Gem"),
+ DS3LocationData("PW1: Large Soul of an Unknown Traveler - snowfield lower, path back up",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("PW1: Follower Javelin - snowfield lower, path back up", "Follower Javelin"),
+ DS3LocationData("PW1: Large Soul of an Unknown Traveler - snowfield lower, path to village",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("PW1: Homeward Bone - snowfield village, outcropping", "Homeward Bone x6"),
+ DS3LocationData("PW1: Blessed Gem - snowfield, behind tower", "Blessed Gem",
+ hidden=True), # Hidden behind a tower
+ DS3LocationData("PW1: Captain's Ashes - snowfield tower, 6F", "Captain's Ashes",
+ progression=True),
+ DS3LocationData("PW1: Black Firebomb - snowfield lower, path to bonfire",
+ "Black Firebomb x2"),
+ DS3LocationData("PW1: Shriving Stone - below bridge near", "Shriving Stone"),
+ DS3LocationData("PW1: Millwood Greatarrow - snowfield village, loop back to lower",
+ "Millwood Greatarrow x5"),
+ DS3LocationData("PW1: Millwood Greatbow - snowfield village, loop back to lower",
+ "Millwood Greatbow"),
+ DS3LocationData("PW1: Large Soul of an Unknown Traveler - snowfield upper",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("PW1: Rusted Coin - snowfield lower, straight from fall", "Rusted Coin"),
+ DS3LocationData("PW1: Large Titanite Shard - snowfield lower, left from fall",
+ "Large Titanite Shard"),
+ DS3LocationData("PW1: Large Soul of an Unknown Traveler - settlement courtyard, cliff",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("PW1: Crow Quills - settlement loop, jump into courtyard", "Crow Quills",
+ hidden=True), # Hidden fall
+ DS3LocationData("PW1: Simple Gem - settlement, lowest level, behind gate", "Simple Gem"),
+ DS3LocationData("PW1: Large Soul of an Unknown Traveler - settlement, by ladder to bonfire",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("PW1: Slave Knight Hood - settlement roofs, drop by ladder",
+ "Slave Knight Hood"),
+ DS3LocationData("PW1: Slave Knight Armor - settlement roofs, drop by ladder",
+ "Slave Knight Armor"),
+ DS3LocationData("PW1: Slave Knight Gauntlets - settlement roofs, drop by ladder",
+ "Slave Knight Gauntlets"),
+ DS3LocationData("PW1: Slave Knight Leggings - settlement roofs, drop by ladder",
+ "Slave Knight Leggings"),
+ DS3LocationData("PW1: Ember - settlement main, left building after bridge", "Ember"),
+ DS3LocationData("PW1: Dark Gem - settlement back, egg building", "Dark Gem"),
+ DS3LocationData("PW1: Large Soul of an Unknown Traveler - settlement roofs, balcony",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("PW1: Large Soul of an Unknown Traveler - settlement loop, by bonfire",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("PW1: Rusted Gold Coin - settlement roofs, roof near second ladder",
+ "Rusted Gold Coin x3"),
+ DS3LocationData("PW1: Soul of a Crestfallen Knight - settlement hall, rafters",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("PW1: Way of White Corona - settlement hall, by altar",
+ "Way of White Corona"),
+ DS3LocationData("PW1: Rusted Coin - right of library", "Rusted Coin x2"),
+ DS3LocationData("PW1: Young White Branch - right of library", "Young White Branch"),
+ DS3LocationData("PW1: Budding Green Blossom - settlement courtyard, ledge",
+ "Budding Green Blossom x3"),
+ DS3LocationData("PW1: Crow Talons - settlement roofs, near bonfire", "Crow Talons"),
+ DS3LocationData("PW1: Hollow Gem - beside chapel", "Hollow Gem"),
+ DS3LocationData("PW1: Rime-blue Moss Clump - below bridge far", "Rime-blue Moss Clump x4"),
+ DS3LocationData("PW1: Follower Sabre - roots above depths", "Follower Sabre"),
+ DS3LocationData("PW1: Ember - roots above depths", "Ember"),
+ DS3LocationData("PW1: Snap Freeze - depths, far end, mob drop", "Snap Freeze", drop=True,
+ hidden=True), # Guaranteed drop from normal-looking Tree Woman
+ DS3LocationData("PW1: Rime-blue Moss Clump - snowfield upper, overhang",
+ "Rime-blue Moss Clump"),
+ DS3LocationData("PW1: Large Soul of an Unknown Traveler - snowfield lower, by cliff",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("PW1: Ember - settlement, building near bonfire", "Ember"),
+ DS3LocationData("PW1: Frozen Weapon - snowfield lower, egg zone", "Frozen Weapon"),
+ DS3LocationData("PW1: Titanite Slab - depths, up secret ladder", "Titanite Slab",
+ static='11,0:54500640::',
+ hidden=True), # Must kill normal-looking Tree Woman
+ DS3LocationData("PW1: Homeward Bone - depths, up hill", "Homeward Bone x2"),
+ DS3LocationData("PW1: Large Soul of an Unknown Traveler - below snowfield village overhang",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("PW1: Large Soul of a Weary Warrior - settlement hall roof",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("PW1: Large Soul of an Unknown Traveler - settlement back",
+ "Large Soul of an Unknown Traveler"),
+ DS3LocationData("PW1: Heavy Gem - snowfield village", "Heavy Gem"),
+ DS3LocationData("PW1: Large Soul of a Weary Warrior - snowfield tower, 6F",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("PW1: Millwood Battle Axe - snowfield tower, 5F", "Millwood Battle Axe"),
+ DS3LocationData("PW1: Ethereal Oak Shield - snowfield tower, 3F", "Ethereal Oak Shield"),
+ DS3LocationData("PW1: Soul of a Weary Warrior - snowfield tower, 1F",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("PW1: Twinkling Titanite - snowfield tower, 3F lizard",
+ "Twinkling Titanite", lizard=True),
+ DS3LocationData("PW1: Large Titanite Shard - lizard under bridge near",
+ "Large Titanite Shard", lizard=True),
+ DS3LocationData("PW1: Twinkling Titanite - roots, lizard", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("PW1: Twinkling Titanite - settlement roofs, lizard before hall",
+ "Twinkling Titanite", lizard=True),
+ DS3LocationData("PW1: Large Titanite Shard - settlement loop, lizard",
+ "Large Titanite Shard x2", lizard=True),
],
- "Painted World of Ariandel 2": [
- DS3LocationData("PW: Quakestone Hammer", "Quakestone Hammer", DS3LocationCategory.WEAPON),
- DS3LocationData("PW: Earth Seeker", "Earth Seeker", DS3LocationCategory.WEAPON),
- DS3LocationData("PW: Follower Torch", "Follower Torch", DS3LocationCategory.SHIELD),
- DS3LocationData("PW: Follower Shield", "Follower Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("PW: Follower Sabre", "Follower Sabre", DS3LocationCategory.WEAPON),
- DS3LocationData("PW: Snap Freeze", "Snap Freeze", DS3LocationCategory.SPELL),
- DS3LocationData("PW: Floating Chaos", "Floating Chaos", DS3LocationCategory.SPELL),
- DS3LocationData("PW: Pyromancer's Parting Flame", "Pyromancer's Parting Flame", DS3LocationCategory.WEAPON),
- DS3LocationData("PW: Vilhelm's Helm", "Vilhelm's Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("PW: Vilhelm's Armor", "Vilhelm's Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("PW: Vilhelm's Gauntlets", "Vilhelm's Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("PW: Vilhelm's Leggings", "Vilhelm's Leggings", DS3LocationCategory.ARMOR),
- DS3LocationData("PW: Valorheart", "Valorheart", DS3LocationCategory.WEAPON),
- DS3LocationData("PW: Champion's Bones", "Champion's Bones", DS3LocationCategory.MISC),
- DS3LocationData("PW: Soul of Sister Friede", "Soul of Sister Friede", DS3LocationCategory.BOSS),
- DS3LocationData("PW: Chillbite Ring", "Chillbite Ring", DS3LocationCategory.RING),
+ "Painted World of Ariandel (After Contraption)": [
+ DS3LocationData("PW2: Soul of Sister Friede", "Soul of Sister Friede", prominent=True,
+ boss=True),
+ DS3LocationData("PW2: Titanite Slab - boss drop", "Titanite Slab",
+ static='11,0:50004700::',
+ boss=True), # One-time drop after Friede Phase 2
+ DS3LocationData("PW2: Floating Chaos - NPC drop", "Floating Chaos", hostile_npc=True,
+ hidden=True), # Livid Pyromancer Dunnel drop (requires ember)
+ DS3LocationData("PW2: Prism Stone - pass, tree by beginning", "Prism Stone x10"),
+ DS3LocationData("PW2: Titanite Chunk - pass, cliff overlooking bonfire", "Titanite Chunk"),
+ DS3LocationData("PW2: Titanite Chunk - pass, by kickable tree", "Titanite Chunk"),
+ DS3LocationData("PW2: Follower Shield - pass, far cliffside", "Follower Shield"),
+ DS3LocationData("PW2: Large Titanite Shard - pass, just before B1",
+ "Large Titanite Shard x2"),
+ DS3LocationData("PW2: Quakestone Hammer - pass, side path near B1", "Quakestone Hammer"),
+ DS3LocationData("PW2: Ember - pass, central alcove", "Ember"),
+ DS3LocationData("PW2: Large Titanite Shard - pass, far side path",
+ "Large Titanite Shard x2"),
+ DS3LocationData("PW2: Soul of a Crestfallen Knight - pit edge #1",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("PW2: Soul of a Crestfallen Knight - pit edge #2",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("PW2: Large Soul of a Crestfallen Knight - pit, by tree",
+ "Large Soul of a Crestfallen Knight"),
+ DS3LocationData("PW2: Earth Seeker - pit cave", "Earth Seeker"),
+ DS3LocationData("PW2: Follower Torch - pass, far side path", "Follower Torch"),
+ DS3LocationData("PW2: Dung Pie - B1", "Dung Pie x2"),
+ DS3LocationData("PW2: Vilhelm's Helm", "Vilhelm's Helm"),
+ DS3LocationData("PW2: Vilhelm's Armor - B2, along wall", "Vilhelm's Armor"),
+ DS3LocationData("PW2: Vilhelm's Gauntlets - B2, along wall", "Vilhelm's Gauntlets"),
+ DS3LocationData("PW2: Vilhelm's Leggings - B2, along wall", "Vilhelm's Leggings"),
+ DS3LocationData("PW2: Blood Gem - B2, center", "Blood Gem"),
+ DS3LocationData("PW2: Pyromancer's Parting Flame - rotunda",
+ "Pyromancer's Parting Flame", hidden=True), # Behind illusory wall
+ DS3LocationData("PW2: Homeward Bone - rotunda", "Homeward Bone x2",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("PW2: Twinkling Titanite - B3, lizard #1", "Twinkling Titanite",
+ lizard=True),
+ DS3LocationData("PW2: Twinkling Titanite - B3, lizard #2", "Twinkling Titanite",
+ lizard=True),
+
+ # Corvian Settler after killing Friede
+ DS3LocationData("PW1: Titanite Slab - Corvian", "Titanite Slab", npc=True),
+
+ # Shrine Handmaid after killing Sister Friede
+ DS3LocationData("FS: Ordained Hood - shop after killing PW2 boss", "Ordained Hood",
+ boss=True, shop=True),
+ DS3LocationData("FS: Ordained Dress - shop after killing PW2 boss", "Ordained Dress",
+ boss=True, shop=True),
+ DS3LocationData("FS: Ordained Trousers - shop after killing PW2 boss", "Ordained Trousers",
+ boss=True, shop=True),
],
"Dreg Heap": [
- DS3LocationData("DH: Loincloth", "Loincloth", DS3LocationCategory.ARMOR),
- DS3LocationData("DH: Aquamarine Dagger", "Aquamarine Dagger", DS3LocationCategory.WEAPON),
- DS3LocationData("DH: Murky Hand Scythe", "Murky Hand Scythe", DS3LocationCategory.WEAPON),
- DS3LocationData("DH: Murky Longstaff", "Murky Longstaff", DS3LocationCategory.WEAPON),
- DS3LocationData("DH: Great Soul Dregs", "Great Soul Dregs", DS3LocationCategory.SPELL),
- DS3LocationData("DH: Lothric War Banner", "Lothric War Banner", DS3LocationCategory.WEAPON),
- DS3LocationData("DH: Projected Heal", "Projected Heal", DS3LocationCategory.SPELL),
- DS3LocationData("DH: Desert Pyromancer Hood", "Desert Pyromancer Hood", DS3LocationCategory.ARMOR),
- DS3LocationData("DH: Desert Pyromancer Garb", "Desert Pyromancer Garb", DS3LocationCategory.ARMOR),
- DS3LocationData("DH: Desert Pyromancer Gloves", "Desert Pyromancer Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("DH: Desert Pyromancer Skirt", "Desert Pyromancer Skirt", DS3LocationCategory.ARMOR),
- DS3LocationData("DH: Giant Door Shield", "Giant Door Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("DH: Herald Curved Greatsword", "Herald Curved Greatsword", DS3LocationCategory.WEAPON),
- DS3LocationData("DH: Flame Fan", "Flame Fan", DS3LocationCategory.SPELL),
- DS3LocationData("DH: Soul of the Demon Prince", "Soul of the Demon Prince", DS3LocationCategory.BOSS),
- DS3LocationData("DH: Small Envoy Banner", "Small Envoy Banner", DS3LocationCategory.KEY),
- DS3LocationData("DH: Ring of Favor+3", "Ring of Favor+3", DS3LocationCategory.RING),
- DS3LocationData("DH: Covetous Silver Serpent Ring+3", "Covetous Silver Serpent Ring+3", DS3LocationCategory.RING),
- DS3LocationData("DH: Ring of Steel Protection+3", "Ring of Steel Protection+3", DS3LocationCategory.RING),
+ DS3LocationData("DH: Soul of the Demon Prince", "Soul of the Demon Prince",
+ prominent=True, boss=True),
+ DS3LocationData("DH: Siegbräu - Lapp", "Siegbräu", missable=True, drop=True,
+ npc=True), # Lapp (quest or kill)
+ DS3LocationData("DH: Flame Fan - swamp upper, NPC drop", "Flame Fan",
+ hostile_npc=True), # Desert Pyromancer Zoey drop
+ DS3LocationData("DH: Ember - castle, behind spire", "Ember"),
+ DS3LocationData("DH: Soul of a Weary Warrior - castle overhang", "Soul of a Weary Warrior"),
+ DS3LocationData("DH: Titanite Chunk - castle, up stairs", "Titanite Chunk"),
+ DS3LocationData("DH: Aquamarine Dagger - castle, up stairs", "Aquamarine Dagger"),
+ DS3LocationData("DH: Twinkling Titanite - library, chandelier", "Twinkling Titanite"),
+ DS3LocationData("DH: Murky Hand Scythe - library, behind bookshelves", "Murky Hand Scythe"),
+ DS3LocationData("DH: Divine Blessing - library, after drop", "Divine Blessing"),
+ DS3LocationData("DH: Ring of Steel Protection+3 - ledge before church",
+ "Ring of Steel Protection+3"),
+ DS3LocationData("DH: Soul of a Crestfallen Knight - church, altar",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("DH: Rusted Coin - behind fountain after church", "Rusted Coin x2"),
+ DS3LocationData("DH: Titanite Chunk - pantry, first room", "Titanite Chunk"),
+ DS3LocationData("DH: Murky Longstaff - pantry, last room", "Murky Longstaff"),
+ DS3LocationData("DH: Ember - pantry, behind crates just before upstairs", "Ember",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("DH: Great Soul Dregs - pantry upstairs", "Great Soul Dregs",
+ hidden=True), # Behind illusory wall
+ DS3LocationData("DH: Covetous Silver Serpent Ring+3 - pantry upstairs, drop down",
+ "Covetous Silver Serpent Ring+3", hidden=True), # Behind illusory wall
+ DS3LocationData("DH: Titanite Chunk - path from church, by pillar", "Titanite Chunk"),
+ DS3LocationData("DH: Homeward Bone - end of path from church", "Homeward Bone x3"),
+ DS3LocationData("DH: Lightning Urn - wall outside church", "Lightning Urn x4"),
+ DS3LocationData("DH: Projected Heal - parapets balcony", "Projected Heal"),
+ DS3LocationData("DH: Large Soul of a Weary Warrior - parapets, hall",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("DH: Lothric War Banner - parapets, end of hall", "Lothric War Banner"),
+ DS3LocationData("DH: Titanite Scale - library, back of room", "Titanite Scale"),
+ DS3LocationData("DH: Black Firebomb - ruins, up windmill from bonfire", "Black Firebomb x4"),
+ DS3LocationData("DH: Titanite Chunk - ruins, path from bonfire", "Titanite Chunk"),
+ DS3LocationData("DH: Twinkling Titanite - ruins, root near bonfire", "Twinkling Titanite"),
+ DS3LocationData("DH: Desert Pyromancer Garb - ruins, by shack near cliff",
+ "Desert Pyromancer Garb"),
+ DS3LocationData("DH: Titanite Chunk - ruins, by far shack", "Titanite Chunk x2"),
+ DS3LocationData("DH: Giant Door Shield - ruins, path below far shack", "Giant Door Shield"),
+ DS3LocationData("DH: Ember - ruins, alcove before swamp", "Ember"),
+ DS3LocationData("DH: Desert Pyromancer Gloves - swamp, far right",
+ "Desert Pyromancer Gloves"),
+ DS3LocationData("DH: Desert Pyromancer Skirt - swamp right, by roots",
+ "Desert Pyromancer Skirt"),
+ DS3LocationData("DH: Titanite Scale - swamp upper, drop and jump into tower",
+ "Titanite Scale"),
+ DS3LocationData("DH: Purple Moss Clump - swamp shack", "Purple Moss Clump x4"),
+ DS3LocationData("DH: Ring of Favor+3 - swamp right, up root", "Ring of Favor+3"),
+ DS3LocationData("DH: Titanite Chunk - swamp right, drop partway up root", "Titanite Chunk"),
+ DS3LocationData("DH: Large Soul of a Weary Warrior - swamp, under overhang",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("DH: Titanite Slab - swamp, path under overhang", "Titanite Slab"),
+ DS3LocationData("DH: Titanite Chunk - swamp, along buildings", "Titanite Chunk"),
+ DS3LocationData("DH: Loincloth - swamp, left edge", "Loincloth"),
+ DS3LocationData("DH: Titanite Chunk - swamp, path to upper", "Titanite Chunk"),
+ DS3LocationData("DH: Large Soul of a Weary Warrior - swamp center",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("DH: Harald Curved Greatsword - swamp left, under root",
+ "Harald Curved Greatsword"),
+ DS3LocationData("DH: Homeward Bone - swamp left, on root", "Homeward Bone"),
+ DS3LocationData("DH: Prism Stone - swamp upper, tunnel start", "Prism Stone x6"),
+ DS3LocationData("DH: Desert Pyromancer Hood - swamp upper, tunnel end",
+ "Desert Pyromancer Hood"),
+ DS3LocationData("DH: Twinkling Titanite - swamp upper, drop onto root",
+ "Twinkling Titanite", hidden=True), # Hidden fall
+ DS3LocationData("DH: Divine Blessing - swamp upper, building roof", "Divine Blessing"),
+ DS3LocationData("DH: Ember - ruins, alcove on cliff", "Ember", hidden=True), # Hidden fall
+ DS3LocationData("DH: Small Envoy Banner - boss drop", "Small Envoy Banner",
+ progression=True, boss=True),
+ DS3LocationData("DH: Twinkling Titanite - ruins, alcove on cliff, mob drop",
+ "Twinkling Titanite x2", drop=True,
+ hidden=True), # Hidden fall, also guaranteed drop from killing normal-looking pilgrim
+ DS3LocationData("DH: Twinkling Titanite - swamp upper, mob drop on roof",
+ "Twinkling Titanite x2", drop=True,
+ hidden=True), # Hidden fall, also guaranteed drop from killing normal-looking pilgrim
+ DS3LocationData("DH: Twinkling Titanite - path after church, mob drop",
+ "Twinkling Titanite x2", drop=True,
+ hidden=True), # Guaranteed drop from killing normal-looking pilgrim
+
+ # Stone-humped Hag's shop
+ DS3LocationData("DH: Splitleaf Greatsword - shop", "Splitleaf Greatsword", shop=True),
+ DS3LocationData("DH: Divine Blessing - shop", "Divine Blessing", shop=True),
+ DS3LocationData("DH: Hidden Blessing - shop", "Hidden Blessing", shop=True),
+ DS3LocationData("DH: Rusted Gold Coin - shop", "Rusted Gold Coin", shop=True),
+ DS3LocationData("DH: Ember - shop", "Ember", shop=True),
],
"Ringed City": [
- DS3LocationData("RC: Ruin Sentinel Helm", "Ruin Sentinel Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Ruin Sentinel Armor", "Ruin Sentinel Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Ruin Sentinel Gauntlets", "Ruin Sentinel Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Ruin Sentinel Leggings", "Ruin Sentinel Leggings", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Black Witch Veil", "Black Witch Veil", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Black Witch Hat", "Black Witch Hat", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Black Witch Garb", "Black Witch Garb", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Black Witch Wrappings", "Black Witch Wrappings", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Black Witch Trousers", "Black Witch Trousers", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: White Preacher Head", "White Preacher Head", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Havel's Ring+3", "Havel's Ring+3", DS3LocationCategory.RING),
- DS3LocationData("RC: Ringed Knight Spear", "Ringed Knight Spear", DS3LocationCategory.WEAPON),
- DS3LocationData("RC: Dragonhead Shield", "Dragonhead Shield", DS3LocationCategory.SHIELD),
- DS3LocationData("RC: Ringed Knight Straight Sword", "Ringed Knight Straight Sword", DS3LocationCategory.WEAPON),
- DS3LocationData("RC: Preacher's Right Arm", "Preacher's Right Arm", DS3LocationCategory.WEAPON),
- DS3LocationData("RC: White Birch Bow", "White Birch Bow", DS3LocationCategory.WEAPON),
- DS3LocationData("RC: Church Guardian Shiv", "Church Guardian Shiv", DS3LocationCategory.MISC),
- DS3LocationData("RC: Dragonhead Greatshield", "Dragonhead Greatshield", DS3LocationCategory.SHIELD),
- DS3LocationData("RC: Ringed Knight Paired Greatswords", "Ringed Knight Paired Greatswords", DS3LocationCategory.WEAPON),
- DS3LocationData("RC: Shira's Crown", "Shira's Crown", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Shira's Armor", "Shira's Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Shira's Gloves", "Shira's Gloves", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Shira's Trousers", "Shira's Trousers", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Crucifix of the Mad King", "Crucifix of the Mad King", DS3LocationCategory.WEAPON),
- DS3LocationData("RC: Sacred Chime of Filianore", "Sacred Chime of Filianore", DS3LocationCategory.WEAPON),
- DS3LocationData("RC: Iron Dragonslayer Helm", "Iron Dragonslayer Helm", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Iron Dragonslayer Armor", "Iron Dragonslayer Armor", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Iron Dragonslayer Gauntlets", "Iron Dragonslayer Gauntlets", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Iron Dragonslayer Leggings", "Iron Dragonslayer Leggings", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Lightning Arrow", "Lightning Arrow", DS3LocationCategory.SPELL),
- DS3LocationData("RC: Ritual Spear Fragment", "Ritual Spear Fragment", DS3LocationCategory.MISC),
- DS3LocationData("RC: Antiquated Plain Garb", "Antiquated Plain Garb", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Violet Wrappings", "Violet Wrappings", DS3LocationCategory.ARMOR),
- DS3LocationData("RC: Soul of Darkeater Midir", "Soul of Darkeater Midir", DS3LocationCategory.BOSS),
- DS3LocationData("RC: Soul of Slave Knight Gael", "Soul of Slave Knight Gael", DS3LocationCategory.BOSS),
- DS3LocationData("RC: Blood of the Dark Soul", "Blood of the Dark Soul", DS3LocationCategory.KEY),
- DS3LocationData("RC: Chloranthy Ring+3", "Chloranthy Ring+3", DS3LocationCategory.RING),
- DS3LocationData("RC: Covetous Gold Serpent Ring+3", "Covetous Gold Serpent Ring+3", DS3LocationCategory.RING),
- DS3LocationData("RC: Ring of the Evil Eye+3", "Ring of the Evil Eye+3", DS3LocationCategory.RING),
- DS3LocationData("RC: Wolf Ring+3", "Wolf Ring+3", DS3LocationCategory.RING),
+ DS3LocationData("RC: Titanite Slab - mid boss drop", "Titanite Slab",
+ prominent=True, boss=True), # Halflight drop, only once
+ DS3LocationData("RC: Filianore's Spear Ornament - mid boss drop",
+ "Filianore's Spear Ornament"),
+ DS3LocationData("RC: Soul of Darkeater Midir", "Soul of Darkeater Midir", prominent=True,
+ boss=True),
+ DS3LocationData("RC: Sacred Chime of Filianore - ashes, NPC drop",
+ "Sacred Chime of Filianore",
+ hostile_npc=True), # Shira (kill or quest)
+ DS3LocationData("RC: Titanite Slab - ashes, NPC drop", "Titanite Slab",
+ hostile_npc=True), # Shira (kill or quest)
+ DS3LocationData("RC: Crucifix of the Mad King - ashes, NPC drop",
+ "Crucifix of the Mad King", hostile_npc=True), # Shira drop
+ DS3LocationData("RC: Ledo's Great Hammer - streets high, opposite building, NPC drop",
+ "Ledo's Great Hammer", hostile_npc=True,
+ missable=True), # Silver Knight Ledo drop, doesn't invade once Halflight
+ # is defeated
+ DS3LocationData("RC: Wolf Ring+3 - street gardens, NPC drop", "Wolf Ring+3",
+ hostile_npc=True,
+ missable=True), # Alva drop, doesn't invade once Halflight is defeated
+ DS3LocationData("RC: Blindfold Mask - grave, NPC drop", "Blindfold Mask",
+ hostile_npc=True), # Moaning Knight drop
+ DS3LocationData("RC: Titanite Scale - wall top, behind spawn", "Titanite Scale"), # wrong
+ DS3LocationData("RC: Ruin Helm - wall top, under stairs to bonfire", "Ruin Helm"),
+ DS3LocationData("RC: Ruin Armor - wall top, under stairs to bonfire", "Ruin Armor"),
+ DS3LocationData("RC: Ruin Gauntlets - wall top, under stairs to bonfire", "Ruin Gauntlets"),
+ DS3LocationData("RC: Ruin Leggings - wall top, under stairs to bonfire", "Ruin Leggings"),
+ DS3LocationData("RC: Budding Green Blossom - wall top, in flower cluster",
+ "Budding Green Blossom x2"),
+ DS3LocationData("RC: Titanite Chunk - wall top, among graves", "Titanite Chunk x2"),
+ DS3LocationData("RC: Ember - wall top, by statue", "Ember"),
+ DS3LocationData("RC: Budding Green Blossom - wall top, flowers by stairs",
+ "Budding Green Blossom x2"),
+ DS3LocationData("RC: Hidden Blessing - wall top, tomb under platform", "Hidden Blessing",
+ hidden=True), # hidden fall
+ DS3LocationData("RC: Soul of a Crestfallen Knight - wall top, under drop",
+ "Soul of a Crestfallen Knight", hidden=True), # hidden fall
+ DS3LocationData("RC: Large Soul of a Weary Warrior - wall top, right of small tomb",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("RC: Ember - wall upper, balcony", "Ember"),
+ DS3LocationData("RC: Purging Stone - wall top, by door to upper", "Purging Stone x2"),
+ DS3LocationData("RC: Hollow Gem - wall upper, path to tower", "Hollow Gem"),
+ DS3LocationData("RC: Titanite Chunk - wall upper, courtyard alcove", "Titanite Chunk"),
+ DS3LocationData("RC: Twinkling Titanite - wall tower, jump from chandelier",
+ "Twinkling Titanite", hidden=True), # Hidden fall
+ DS3LocationData("RC: Shriving Stone - wall tower, bottom floor center", "Shriving Stone"),
+ DS3LocationData("RC: Shira's Crown - Shira's room after killing ashes NPC", "Shira's Crown",
+ hidden=True), # Have to return to a cleared area
+ DS3LocationData("RC: Shira's Armor - Shira's room after killing ashes NPC", "Shira's Armor",
+ hidden=True), # Have to return to a cleared area
+ DS3LocationData("RC: Shira's Gloves - Shira's room after killing ashes NPC",
+ "Shira's Gloves", hidden=True), # Have to return to a cleared area
+ DS3LocationData("RC: Shira's Trousers - Shira's room after killing ashes NPC",
+ "Shira's Trousers", hidden=True), # Have to return to a cleared area
+ DS3LocationData("RC: Mossfruit - streets near left, path to garden", "Mossfruit x2"),
+ DS3LocationData("RC: Large Soul of a Crestfallen Knight - streets, far stairs",
+ "Large Soul of a Crestfallen Knight"),
+ DS3LocationData("RC: Ringed Knight Spear - streets, down far right hall",
+ "Ringed Knight Spear"),
+ DS3LocationData("RC: Black Witch Hat - streets garden", "Black Witch Hat",
+ hostile_npc=True), # Alva
+ DS3LocationData("RC: Black Witch Garb - streets garden", "Black Witch Garb",
+ hostile_npc=True), # Alva
+ DS3LocationData("RC: Black Witch Wrappings - streets garden", "Black Witch Wrappings",
+ hostile_npc=True), # Alva
+ DS3LocationData("RC: Black Witch Trousers - streets garden", "Black Witch Trousers",
+ hostile_npc=True), # Alva
+ DS3LocationData("RC: Dragonhead Shield - streets monument, across bridge",
+ "Dragonhead Shield", hidden=True), # "Show Your Humanity" puzzle
+ DS3LocationData("RC: Titanite Chunk - streets, near left drop", "Titanite Chunk",
+ hidden=True), # Hidden fall
+ DS3LocationData("RC: Mossfruit - streets, far left alcove", "Mossfruit x2"),
+ DS3LocationData("RC: Large Soul of a Crestfallen Knight - streets monument, across bridge",
+ "Large Soul of a Crestfallen Knight",
+ hidden=True), # "Show Your Humanity" puzzle
+ DS3LocationData("RC: Covetous Gold Serpent Ring+3 - streets, by Lapp",
+ "Covetous Gold Serpent Ring+3"),
+ DS3LocationData("RC: Titanite Chunk - streets high, building opposite", "Titanite Chunk x2"),
+ DS3LocationData("RC: Dark Gem - swamp near, by stairs", "Dark Gem"),
+ DS3LocationData("RC: Prism Stone - swamp near, railing by bonfire", "Prism Stone x4"),
+ DS3LocationData("RC: Ringed Knight Straight Sword - swamp near, tower on peninsula",
+ "Ringed Knight Straight Sword"),
+ DS3LocationData("RC: Havel's Ring+3 - streets high, drop from building opposite",
+ "Havel's Ring+3", hidden=True), # Hidden fall
+ DS3LocationData("RC: Titanite Chunk - swamp near left, by spire top", "Titanite Chunk"),
+ DS3LocationData("RC: Twinkling Titanite - swamp near left", "Twinkling Titanite"),
+ DS3LocationData("RC: Soul of a Weary Warrior - swamp center", "Soul of a Weary Warrior"),
+ DS3LocationData("RC: Preacher's Right Arm - swamp near right, by tower",
+ "Preacher's Right Arm"),
+ DS3LocationData("RC: Rubbish - swamp far, by crystal", "Rubbish"),
+ DS3LocationData("RC: Titanite Chunk - swamp near right, behind rock",
+ "Titanite Chunk"),
+ DS3LocationData("RC: Black Witch Veil - swamp near right, by sunken church",
+ "Black Witch Veil"),
+ DS3LocationData("RC: Twinkling Titanite - swamp near right, on sunken church",
+ "Twinkling Titanite"),
+ DS3LocationData("RC: Soul of a Crestfallen Knight - swamp near left, nook",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("RC: White Preacher Head - swamp near, nook right of stairs",
+ "White Preacher Head"),
+ DS3LocationData("RC: Titanite Scale - swamp far, by miniboss", "Titanite Scale"),
+ DS3LocationData("RC: Dragonhead Greatshield - lower cliff, under bridge",
+ "Dragonhead Greatshield"),
+ DS3LocationData("RC: Titanite Scale - lower cliff, path under bridge", "Titanite Scale x2"),
+ DS3LocationData("RC: Rubbish - lower cliff, middle", "Rubbish"),
+ DS3LocationData("RC: Large Soul of a Weary Warrior - lower cliff, end",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("RC: Titanite Scale - lower cliff, first alcove", "Titanite Scale x2"),
+ DS3LocationData("RC: Titanite Scale - lower cliff, lower path", "Titanite Scale"),
+ DS3LocationData("RC: Lightning Gem - grave, room after first drop", "Lightning Gem"),
+ DS3LocationData("RC: Blessed Gem - grave, down lowest stairs", "Blessed Gem"),
+ DS3LocationData("RC: Simple Gem - grave, up stairs after first drop", "Simple Gem"),
+ DS3LocationData("RC: Large Soul of a Weary Warrior - wall lower, past two illusory walls",
+ "Large Soul of a Weary Warrior", hidden=True),
+ DS3LocationData("RC: Lightning Arrow - wall lower, past three illusory walls",
+ "Lightning Arrow"),
+ DS3LocationData("RC: Chloranthy Ring+3 - wall hidden, drop onto statue",
+ "Chloranthy Ring+3", hidden=True), # Hidden fall
+ DS3LocationData("RC: Ember - wall hidden, statue room", "Ember"),
+ DS3LocationData("RC: Filianore's Spear Ornament - wall hidden, by ladder",
+ "Filianore's Spear Ornament"),
+ DS3LocationData("RC: Antiquated Plain Garb - wall hidden, before boss",
+ "Antiquated Plain Garb"),
+ DS3LocationData("RC: Violet Wrappings - wall hidden, before boss", "Violet Wrappings"),
+ DS3LocationData("RC: Soul of a Weary Warrior - lower cliff, by first alcove",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("RC: Twinkling Titanite - church path, left of boss door",
+ "Twinkling Titanite x2"),
+ DS3LocationData("RC: Budding Green Blossom - church path", "Budding Green Blossom x3"),
+ DS3LocationData("RC: Titanite Chunk - swamp center, peninsula edge", "Titanite Chunk"),
+ DS3LocationData("RC: Large Soul of a Weary Warrior - swamp center, by peninsula",
+ "Large Soul of a Weary Warrior"),
+ DS3LocationData("RC: Soul of a Weary Warrior - swamp right, by sunken church",
+ "Soul of a Weary Warrior"),
+ DS3LocationData("RC: Titanite Scale - upper cliff, bridge", "Titanite Scale"),
+ DS3LocationData("RC: Soul of a Crestfallen Knight - swamp far, behind crystal",
+ "Soul of a Crestfallen Knight"),
+ DS3LocationData("RC: White Birch Bow - swamp far left, up hill", "White Birch Bow"),
+ DS3LocationData("RC: Titanite Chunk - swamp far left, up hill", "Titanite Chunk"),
+ DS3LocationData("RC: Young White Branch - swamp far left, by white tree #1",
+ "Young White Branch"),
+ DS3LocationData("RC: Young White Branch - swamp far left, by white tree #2",
+ "Young White Branch"),
+ DS3LocationData("RC: Young White Branch - swamp far left, by white tree #3",
+ "Young White Branch"),
+ DS3LocationData("RC: Ringed Knight Paired Greatswords - church path, mob drop",
+ "Ringed Knight Paired Greatswords", drop=True,
+ hidden=True), # Guaranteed drop from a normal-looking Ringed Knight
+ DS3LocationData("RC: Hidden Blessing - swamp center, mob drop", "Hidden Blessing",
+ drop=True, hidden=True), # Guaranteed drop from Judicator
+ DS3LocationData("RC: Divine Blessing - wall top, mob drop", "Divine Blessing",
+ drop=True, hidden=True), # Guaranteed drop from Judicator
+ DS3LocationData("RC: Divine Blessing - streets monument, mob drop", "Divine Blessing",
+ drop=True,
+ hidden=True), # Guaranteed drop from Judicator, "Show Your Humanity" puzzle
+ DS3LocationData("RC: Ring of the Evil Eye+3 - grave, mimic", "Ring of the Evil Eye+3",
+ mimic=True),
+ DS3LocationData("RC: Iron Dragonslayer Helm - swamp far, miniboss drop",
+ "Iron Dragonslayer Helm", miniboss=True),
+ DS3LocationData("RC: Iron Dragonslayer Armor - swamp far, miniboss drop",
+ "Iron Dragonslayer Armor", miniboss=True),
+ DS3LocationData("RC: Iron Dragonslayer Gauntlets - swamp far, miniboss drop",
+ "Iron Dragonslayer Gauntlets", miniboss=True),
+ DS3LocationData("RC: Iron Dragonslayer Leggings - swamp far, miniboss drop",
+ "Iron Dragonslayer Leggings", miniboss=True),
+ DS3LocationData("RC: Church Guardian Shiv - swamp far left, in building",
+ "Church Guardian Shiv"),
+ DS3LocationData("RC: Spears of the Church - hidden boss drop", "Spears of the Church",
+ boss=True), # Midir drop
+ DS3LocationData("RC: Ritual Spear Fragment - church path", "Ritual Spear Fragment"),
+ DS3LocationData("RC: Titanite Scale - swamp far, lagoon entrance", "Titanite Scale"),
+ DS3LocationData("RC: Twinkling Titanite - grave, lizard past first drop",
+ "Twinkling Titanite", lizard=True),
+ DS3LocationData("RC: Titanite Scale - grave, lizard past first drop", "Titanite Scale",
+ lizard=True),
+ DS3LocationData("RC: Twinkling Titanite - streets high, lizard", "Twinkling Titanite x2",
+ lizard=True),
+ DS3LocationData("RC: Titanite Scale - wall lower, lizard", "Titanite Scale", lizard=True),
+ DS3LocationData("RC: Twinkling Titanite - wall top, lizard on side path",
+ "Twinkling Titanite", lizard=True),
+ DS3LocationData("RC: Soul of Slave Knight Gael", "Soul of Slave Knight Gael",
+ prominent=True, boss=True),
+ DS3LocationData("RC: Blood of the Dark Soul - end boss drop", "Blood of the Dark Soul"),
+ DS3LocationData("RC: Titanite Slab - ashes, mob drop", "Titanite Slab",
+ drop=True,
+ hidden=True), # Guaranteed drop from normal-looking Ringed Knight
+
+ # Lapp
+ DS3LocationData("RC: Siegbräu - Lapp", "Siegbräu", missable=True,
+ npc=True), # Lapp (quest)
+ # Quest or Shrine Handmaiden after death
+ DS3LocationData("RC: Lapp's Helm - Lapp", "Lapp's Helm", npc=True, shop=True),
+ DS3LocationData("RC: Lapp's Armor - Lapp", "Lapp's Armor", npc=True, shop=True),
+ DS3LocationData("RC: Lapp's Gauntlets - Lapp", "Lapp's Gauntlets", npc=True, shop=True),
+ DS3LocationData("RC: Lapp's Leggings - Lapp", "Lapp's Leggings", npc=True, shop=True),
+ ],
+
+ # Unlockable shops. We only bother creating a "region" for these for shops that are locked
+ # behind keys and always have items available either through the shop or through the NPC's
+ # ashes.
+ "Greirat's Shop": [
+ DS3LocationData("FS: Blue Tearstone Ring - Greirat", "Blue Tearstone Ring",
+ static='01,0:50006120::', npc=True),
+ DS3LocationData("FS: Ember - Greirat", "Ember", static="99,0:-1:110000,120000,70000110:",
+ shop=True, npc=True),
+
+ # Undead Settlement rewards
+ DS3LocationData("FS: Divine Blessing - Greirat from US", "Divine Blessing",
+ static='99,0:-1:110000,120000,70000150,70000175:', missable=True,
+ shop=True, npc=True),
+ DS3LocationData("FS: Ember - Greirat from US", "Ember",
+ static='99,0:-1:110000,120000,70000150,70000175:', missable=True,
+ shop=True, npc=True),
+
+ # Irityhll rewards
+ DS3LocationData("FS: Divine Blessing - Greirat from IBV", "Divine Blessing",
+ static='99,0:-1:110000,120000,70000151,70000176:', missable=True,
+ shop=True, npc=True),
+ DS3LocationData("FS: Hidden Blessing - Greirat from IBV", "Hidden Blessing",
+ static='99,0:-1:110000,120000,70000151,70000176:', missable=True,
+ shop=True, npc=True),
+ DS3LocationData("FS: Titanite Scale - Greirat from IBV", "Titanite Scale",
+ static='99,0:-1:110000,120000,70000151,70000176:', missable=True,
+ shop=True, npc=True),
+ DS3LocationData("FS: Twinkling Titanite - Greirat from IBV", "Twinkling Titanite",
+ static='99,0:-1:110000,120000,70000151,70000176:', missable=True,
+ shop=True, npc=True),
+
+ # Lothric rewards (from Shrine Handmaid)
+ DS3LocationData("FS: Ember - shop for Greirat's Ashes", "Twinkling Titanite",
+ static='99,0:-1:110000,120000,70000152,70000177:', missable=True,
+ shop=True, npc=True),
+ ],
+ "Karla's Shop": [
+ DS3LocationData("FS: Affinity - Karla", "Affinity", shop=True, npc=True),
+ DS3LocationData("FS: Dark Edge - Karla", "Dark Edge", shop=True, npc=True),
+
+ # Quelana Pyromancy Tome
+ DS3LocationData("FS: Firestorm - Karla for Quelana Tome", "Firestorm", missable=True,
+ shop=True, npc=True),
+ DS3LocationData("FS: Rapport - Karla for Quelana Tome", "Rapport", missable=True,
+ shop=True, npc=True),
+ DS3LocationData("FS: Fire Whip - Karla for Quelana Tome", "Fire Whip", missable=True,
+ shop=True, npc=True),
+
+ # Grave Warden Pyromancy Tome
+ DS3LocationData("FS: Black Flame - Karla for Grave Warden Tome", "Black Flame",
+ missable=True, shop=True, npc=True),
+ DS3LocationData("FS: Black Fire Orb - Karla for Grave Warden Tome", "Black Fire Orb",
+ missable=True, shop=True, npc=True),
+
+ # Deep Braille Divine Tome. This can also be given to Irina, but it'll fail her quest
+ DS3LocationData("FS: Gnaw - Karla for Deep Braille Tome", "Gnaw", missable=True,
+ npc=True, shop=True),
+ DS3LocationData("FS: Deep Protection - Karla for Deep Braille Tome", "Deep Protection",
+ missable=True, npc=True, shop=True),
+
+ # Londor Braille Divine Tome. This can also be given to Irina, but it'll fail her quest
+ DS3LocationData("FS: Vow of Silence - Karla for Londor Tome", "Vow of Silence",
+ missable=True, npc=True, shop=True),
+ DS3LocationData("FS: Dark Blade - Karla for Londor Tome", "Dark Blade", missable=True,
+ npc=True, shop=True),
+ DS3LocationData("FS: Dead Again - Karla for Londor Tome", "Dead Again", missable=True,
+ npc=True, shop=True),
+
+ # Drops on death. Missable because the player would have to decide between killing her or
+ # seeing everything she sells.
+ DS3LocationData("FS: Karla's Pointed Hat - kill Karla", "Karla's Pointed Hat",
+ static='07,0:50006150::', missable=True, drop=True, npc=True),
+ DS3LocationData("FS: Karla's Coat - kill Karla", "Karla's Coat",
+ static='07,0:50006150::', missable=True, drop=True, npc=True),
+ DS3LocationData("FS: Karla's Gloves - kill Karla", "Karla's Gloves",
+ static='07,0:50006150::', missable=True, drop=True, npc=True),
+ DS3LocationData("FS: Karla's Trousers - kill Karla", "Karla's Trousers",
+ static='07,0:50006150::', missable=True, drop=True, npc=True),
],
+}
+
+for i, region in enumerate(region_order):
+ for location in location_tables[region]: location.region_value = i
+
+for region in [
+ "Painted World of Ariandel (Before Contraption)",
+ "Painted World of Ariandel (After Contraption)",
+ "Dreg Heap",
+ "Ringed City",
+]:
+ for location in location_tables[region]:
+ location.dlc = True
- # Progressive
- "Progressive Items 1": [] +
- # Upgrade materials
- [DS3LocationData(f"Titanite Shard #{i + 1}", "Titanite Shard", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(26)] +
- [DS3LocationData(f"Large Titanite Shard #{i + 1}", "Large Titanite Shard", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(28)] +
- [DS3LocationData(f"Titanite Slab #{i + 1}", "Titanite Slab", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Twinkling Titanite #{i + 1}", "Twinkling Titanite", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(15)],
-
- "Progressive Items 2": [] +
- # Items
- [DS3LocationData(f"Green Blossom #{i + 1}", "Green Blossom", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(6)] +
- [DS3LocationData(f"Firebomb #{i + 1}", "Firebomb", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(4)] +
- [DS3LocationData(f"Alluring Skull #{i + 1}", "Alluring Skull", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Undead Hunter Charm #{i + 1}", "Undead Hunter Charm", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Duel Charm #{i + 1}", "Duel Charm", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Throwing Knife #{i + 1}", "Throwing Knife", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Gold Pine Resin #{i + 1}", "Gold Pine Resin", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(1)] +
- [DS3LocationData(f"Charcoal Pine Resin #{i + 1}", "Charcoal Pine Resin", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(1)] +
- [DS3LocationData(f"Human Pine Resin #{i + 1}", "Human Pine Resin", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Carthus Rouge #{i + 1}", "Carthus Rouge", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(1)] +
- [DS3LocationData(f"Pale Pine Resin #{i + 1}", "Pale Pine Resin", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(1)] +
- [DS3LocationData(f"Charcoal Pine Bundle #{i + 1}", "Charcoal Pine Bundle", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Rotten Pine Resin #{i + 1}", "Rotten Pine Resin", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Homeward Bone #{i + 1}", "Homeward Bone", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(16)] +
- [DS3LocationData(f"Pale Tongue #{i + 1}", "Pale Tongue", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Rusted Coin #{i + 1}", "Rusted Coin", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Rusted Gold Coin #{i + 1}", "Rusted Gold Coin", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Ember #{i + 1}", "Ember", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(45)],
-
- "Progressive Items 3": [] +
- # Souls & Bulk Upgrade Materials
- [DS3LocationData(f"Fading Soul #{i + 1}", "Fading Soul", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(5)] +
- [DS3LocationData(f"Soul of a Deserted Corpse #{i + 1}", "Soul of a Deserted Corpse", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(5)] +
- [DS3LocationData(f"Large Soul of a Deserted Corpse #{i + 1}", "Large Soul of a Deserted Corpse", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(5)] +
- [DS3LocationData(f"Soul of an Unknown Traveler #{i + 1}", "Soul of an Unknown Traveler", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(5)] +
- [DS3LocationData(f"Large Soul of an Unknown Traveler #{i + 1}", "Large Soul of an Unknown Traveler", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(5)] +
- [DS3LocationData(f"Soul of a Nameless Soldier #{i + 1}", "Soul of a Nameless Soldier", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(4)] +
- [DS3LocationData(f"Large Soul of a Nameless Soldier #{i + 1}", "Large Soul of a Nameless Soldier", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(4)] +
- [DS3LocationData(f"Soul of a Weary Warrior #{i + 1}", "Soul of a Weary Warrior", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(6)] +
- [DS3LocationData(f"Soul of a Crestfallen Knight #{i + 1}", "Soul of a Crestfallen Knight", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Titanite Chunk #{i + 1}", "Titanite Chunk", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(22)] +
- [DS3LocationData(f"Titanite Scale #{i + 1}", "Titanite Scale", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(29)],
-
- "Progressive Items 4": [] +
- # Gems & Random Consumables
- [DS3LocationData(f"Ring of Sacrifice #{i + 1}", "Ring of Sacrifice", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(4)] +
- [DS3LocationData(f"Divine Blessing #{i + 1}", "Divine Blessing", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Hidden Blessing #{i + 1}", "Hidden Blessing", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(1)] +
- [DS3LocationData(f"Budding Green Blossom #{i + 1}", "Budding Green Blossom", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(5)] +
- [DS3LocationData(f"Bloodred Moss Clump #{i + 1}", "Bloodred Moss Clump", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(1)] +
- [DS3LocationData(f"Purple Moss Clump #{i + 1}", "Purple Moss Clump", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Blooming Purple Moss Clump #{i + 1}", "Blooming Purple Moss Clump", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(1)] +
- [DS3LocationData(f"Purging Stone #{i + 1}", "Purging Stone", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Rime-blue Moss Clump #{i + 1}", "Rime-blue Moss Clump", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Repair Powder #{i + 1}", "Repair Powder", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Kukri #{i + 1}", "Kukri", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Lightning Urn #{i + 1}", "Lightning Urn", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Rubbish #{i + 1}", "Rubbish", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(1)] +
- [DS3LocationData(f"Blue Bug Pellet #{i + 1}", "Blue Bug Pellet", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Red Bug Pellet #{i + 1}", "Red Bug Pellet", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Yellow Bug Pellet #{i + 1}", "Yellow Bug Pellet", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Black Bug Pellet #{i + 1}", "Black Bug Pellet", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Heavy Gem #{i + 1}", "Heavy Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Sharp Gem #{i + 1}", "Sharp Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Refined Gem #{i + 1}", "Refined Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Crystal Gem #{i + 1}", "Crystal Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Simple Gem #{i + 1}", "Simple Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Fire Gem #{i + 1}", "Fire Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Chaos Gem #{i + 1}", "Chaos Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Lightning Gem #{i + 1}", "Lightning Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Deep Gem #{i + 1}", "Deep Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Dark Gem #{i + 1}", "Dark Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Poison Gem #{i + 1}", "Poison Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Blood Gem #{i + 1}", "Blood Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(1)] +
- [DS3LocationData(f"Raw Gem #{i + 1}", "Raw Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Blessed Gem #{i + 1}", "Blessed Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Hollow Gem #{i + 1}", "Hollow Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Shriving Stone #{i + 1}", "Shriving Stone", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)],
-
- "Progressive Items DLC": [] +
- # Upgrade materials
- [DS3LocationData(f"Large Titanite Shard ${i + 1}", "Large Titanite Shard", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Titanite Chunk ${i + 1}", "Titanite Chunk", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(15)] +
- [DS3LocationData(f"Titanite Slab ${i + 1}", "Titanite Slab", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Twinkling Titanite ${i + 1}", "Twinkling Titanite", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(5)] +
- [DS3LocationData(f"Titanite Scale ${i + 1}", "Titanite Scale", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(11)] +
-
-
- # Items
- [DS3LocationData(f"Homeward Bone ${i + 1}", "Homeward Bone", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(6)] +
- [DS3LocationData(f"Rusted Coin ${i + 1}", "Rusted Coin", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
- [DS3LocationData(f"Ember ${i + 1}", "Ember", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(10)] +
-
- # Souls
- [DS3LocationData(f"Large Soul of an Unknown Traveler ${i + 1}", "Large Soul of an Unknown Traveler", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(9)] +
- [DS3LocationData(f"Soul of a Weary Warrior ${i + 1}", "Soul of a Weary Warrior", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(5)] +
- [DS3LocationData(f"Large Soul of a Weary Warrior ${i + 1}", "Large Soul of a Weary Warrior", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(6)] +
- [DS3LocationData(f"Soul of a Crestfallen Knight ${i + 1}", "Soul of a Crestfallen Knight", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(6)] +
- [DS3LocationData(f"Large Soul of a Crestfallen Knight ${i + 1}", "Large Soul of a Crestfallen Knight", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(3)] +
-
- # Gems
- [DS3LocationData(f"Dark Gem ${i + 1}", "Dark Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Blood Gem ${i + 1}", "Blood Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(1)] +
- [DS3LocationData(f"Blessed Gem ${i + 1}", "Blessed Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)] +
- [DS3LocationData(f"Hollow Gem ${i + 1}", "Hollow Gem", DS3LocationCategory.PROGRESSIVE_ITEM) for i in range(2)],
-
- "Progressive Items Health": [] +
- # Healing
- [DS3LocationData(f"Estus Shard #{i + 1}", "Estus Shard", DS3LocationCategory.HEALTH) for i in range(11)] +
- [DS3LocationData(f"Undead Bone Shard #{i + 1}", "Undead Bone Shard", DS3LocationCategory.HEALTH) for i in range(10)],
+for region in [
+ "Firelink Shrine Bell Tower",
+ "Greirat's Shop",
+ "Karla's Shop"
+]:
+ for location in location_tables[region]:
+ location.conditional = True
+
+location_name_groups: Dict[str, Set[str]] = {
+ # We could insert these locations automatically with setdefault(), but we set them up explicitly
+ # instead so we can choose the ordering.
+ "Prominent": set(),
+ "Progression": set(),
+ "Boss Rewards": set(),
+ "Miniboss Rewards": set(),
+ "Mimic Rewards": set(),
+ "Hostile NPC Rewards": set(),
+ "Friendly NPC Rewards": set(),
+ "Small Crystal Lizards": set(),
+ "Upgrade": set(),
+ "Small Souls": set(),
+ "Boss Souls": set(),
+ "Unique": set(),
+ "Healing": set(),
+ "Miscellaneous": set(),
+ "Hidden": set(),
+ "Weapons": set(),
+ "Shields": set(),
+ "Armor": set(),
+ "Rings": set(),
+ "Spells": set(),
+}
+
+location_descriptions = {
+ "Prominent": "A small number of locations that are in very obvious locations. Mostly boss " + \
+ "drops. Ideal for setting as priority locations.",
+ "Progression": "Locations that contain items in vanilla which unlock other locations.",
+ "Boss Rewards": "Boss drops. Does not include soul transfusions or shop items.",
+ "Miniboss Rewards": "Miniboss drops. Only includes enemies considered minibosses by the " + \
+ "enemy randomizer.",
+ "Mimic Rewards": "Drops from enemies that are mimics in vanilla.",
+ "Hostile NPC Rewards": "Drops from NPCs that are hostile to you. This includes scripted " + \
+ "invaders and initially-friendly NPCs that must be fought as part of their quest.",
+ "Friendly NPC Rewards": "Items given by friendly NPCs as part of their quests or from " + \
+ "non-violent interaction.",
+ "Upgrade": "Locations that contain upgrade items in vanilla, including titanite, gems, and " + \
+ "Shriving Stones.",
+ "Small Souls": "Locations that contain soul items in vanilla, not including boss souls.",
+ "Boss Souls": "Locations that contain boss souls in vanilla, as well as Soul of Rosaria.",
+ "Unique": "Locations that contain items in vanilla that are unique per NG cycle, such as " + \
+ "scrolls, keys, ashes, and so on. Doesn't cover equipment, spells, or souls.",
+ "Healing": "Locations that contain Undead Bone Shards and Estus Shards in vanilla.",
+ "Miscellaneous": "Locations that contain generic stackable items in vanilla, such as arrows, " +
+ "firebombs, buffs, and so on.",
+ "Hidden": "Locations that are particularly difficult to find, such as behind illusory " + \
+ "walls, down hidden drops, and so on. Does not include large locations like Untended " + \
+ "Graves or Archdragon Peak.",
+ "Weapons": "Locations that contain weapons in vanilla.",
+ "Shields": "Locations that contain shields in vanilla.",
+ "Armor": "Locations that contain armor in vanilla.",
+ "Rings": "Locations that contain rings in vanilla.",
+ "Spells": "Locations that contain spells in vanilla.",
}
location_dictionary: Dict[str, DS3LocationData] = {}
-for location_table in location_tables.values():
+for location_name, location_table in location_tables.items():
location_dictionary.update({location_data.name: location_data for location_data in location_table})
+
+ for location_data in location_table:
+ if not location_data.is_event:
+ for group_name in location_data.location_groups():
+ location_name_groups[group_name].add(location_data.name)
+
+ # Allow entire locations to be added to location sets.
+ if not location_name.endswith(" Shop"):
+ location_name_groups[location_name] = set([
+ location_data.name for location_data in location_table
+ if not location_data.is_event
+ ])
+
+location_name_groups["Painted World of Ariandel"] = (
+ location_name_groups["Painted World of Ariandel (Before Contraption)"]
+ .union(location_name_groups["Painted World of Ariandel (After Contraption)"])
+)
+del location_name_groups["Painted World of Ariandel (Before Contraption)"]
+del location_name_groups["Painted World of Ariandel (After Contraption)"]
+
+location_name_groups["DLC"] = (
+ location_name_groups["Painted World of Ariandel"]
+ .union(location_name_groups["Dreg Heap"])
+ .union(location_name_groups["Ringed City"])
+)
diff --git a/worlds/dark_souls_3/Options.py b/worlds/dark_souls_3/Options.py
index df0bb953b8d9..ad81dd9f7b85 100644
--- a/worlds/dark_souls_3/Options.py
+++ b/worlds/dark_souls_3/Options.py
@@ -1,80 +1,78 @@
-import typing
+from dataclasses import dataclass
+import json
+from typing import Any, Dict
-from Options import Toggle, DefaultOnToggle, Option, Range, Choice, ItemDict, DeathLink
+from Options import Choice, DeathLink, DefaultOnToggle, ExcludeLocations, NamedRange, OptionDict, \
+ OptionGroup, PerGameCommonOptions, Range, Removed, Toggle
+## Game Options
-class RandomizeWeaponLocations(DefaultOnToggle):
- """Randomizes weapons (+76 locations)"""
- display_name = "Randomize Weapon Locations"
-
-class RandomizeShieldLocations(DefaultOnToggle):
- """Randomizes shields (+24 locations)"""
- display_name = "Randomize Shield Locations"
-
-
-class RandomizeArmorLocations(DefaultOnToggle):
- """Randomizes armor pieces (+97 locations)"""
- display_name = "Randomize Armor Locations"
-
-
-class RandomizeRingLocations(DefaultOnToggle):
- """Randomizes rings (+49 locations)"""
- display_name = "Randomize Ring Locations"
-
-
-class RandomizeSpellLocations(DefaultOnToggle):
- """Randomizes spells (+18 locations)"""
- display_name = "Randomize Spell Locations"
-
-
-class RandomizeKeyLocations(DefaultOnToggle):
- """Randomizes items which unlock doors or bypass barriers"""
- display_name = "Randomize Key Locations"
+class EarlySmallLothricBanner(Choice):
+ """Force Small Lothric Banner into an early sphere in your world or across all worlds."""
+ display_name = "Early Small Lothric Banner"
+ option_off = 0
+ option_early_global = 1
+ option_early_local = 2
+ default = option_off
-class RandomizeBossSoulLocations(DefaultOnToggle):
- """Randomizes Boss Souls (+18 Locations)"""
- display_name = "Randomize Boss Soul Locations"
+class LateBasinOfVowsOption(Choice):
+ """Guarantee that you don't need to enter Lothric Castle until later in the run.
+ - **Off:** You may have to enter Lothric Castle and the areas beyond it immediately after High
+ Wall of Lothric.
+ - **After Small Lothric Banner:** You may have to enter Lothric Castle after Catacombs of
+ Carthus.
+ - **After Small Doll:** You won't have to enter Lothric Castle until after Irithyll of the
+ Boreal Valley.
+ """
+ display_name = "Late Basin of Vows"
+ option_off = 0
+ alias_false = 0
+ option_after_small_lothric_banner = 1
+ alias_true = 1
+ option_after_small_doll = 2
-class RandomizeNPCLocations(Toggle):
- """Randomizes friendly NPC drops (meaning you will probably have to kill them) (+14 locations)"""
- display_name = "Randomize NPC Locations"
+class LateDLCOption(Choice):
+ """Guarantee that you don't need to enter the DLC until later in the run.
-class RandomizeMiscLocations(Toggle):
- """Randomizes miscellaneous items (ashes, tomes, scrolls, etc.) to the pool. (+36 locations)"""
- display_name = "Randomize Miscellaneous Locations"
+ - **Off:** You may have to enter the DLC after Catacombs of Carthus.
+ - **After Small Doll:** You may have to enter the DLC after Irithyll of the Boreal Valley.
+ - **After Basin:** You won't have to enter the DLC until after Lothric Castle.
+ """
+ display_name = "Late DLC"
+ option_off = 0
+ alias_false = 0
+ option_after_small_doll = 1
+ alias_true = 1
+ option_after_basin = 2
-class RandomizeHealthLocations(Toggle):
- """Randomizes health upgrade items. (+21 locations)"""
- display_name = "Randomize Health Upgrade Locations"
+class EnableDLCOption(Toggle):
+ """Include DLC locations, items, and enemies in the randomized pools.
+ To use this option, you must own both the "Ashes of Ariandel" and the "Ringed City" DLCs.
+ """
+ display_name = "Enable DLC"
-class RandomizeProgressiveLocationsOption(Toggle):
- """Randomizes upgrade materials and consumables such as the titanite shards, firebombs, resin, etc...
- Instead of specific locations, these are progressive, so Titanite Shard #1 is the first titanite shard
- you pick up, regardless of whether it's from an enemy drop late in the game or an item on the ground in the
- first 5 minutes."""
- display_name = "Randomize Progressive Locations"
+class EnableNGPOption(Toggle):
+ """Include items and locations exclusive to NG+ cycles."""
+ display_name = "Enable NG+"
-class PoolTypeOption(Choice):
- """Changes which non-progression items you add to the pool
+## Equipment
- Shuffle: Items are picked from the locations being randomized
- Various: Items are picked from a list of all items in the game, but are the same type of item they replace"""
- display_name = "Pool Type"
- option_shuffle = 0
- option_various = 1
+class RandomizeStartingLoadout(DefaultOnToggle):
+ """Randomizes the equipment characters begin with."""
+ display_name = "Randomize Starting Loadout"
-class GuaranteedItemsOption(ItemDict):
- """Guarantees that the specified items will be in the item pool"""
- display_name = "Guaranteed Items"
+class RequireOneHandedStartingWeapons(DefaultOnToggle):
+ """Require starting equipment to be usable one-handed."""
+ display_name = "Require One-Handed Starting Weapons"
class AutoEquipOption(Toggle):
@@ -83,47 +81,56 @@ class AutoEquipOption(Toggle):
class LockEquipOption(Toggle):
- """Lock the equipment slots so you cannot change your armor or your left/right weapons. Works great with the
- Auto-equip option."""
+ """Lock the equipment slots so you cannot change your armor or your left/right weapons.
+
+ Works great with the Auto-equip option.
+ """
display_name = "Lock Equipment Slots"
+class NoEquipLoadOption(Toggle):
+ """Disable the equip load constraint from the game."""
+ display_name = "No Equip Load"
+
+
class NoWeaponRequirementsOption(Toggle):
- """Disable the weapon requirements by removing any movement or damage penalties.
- Permitting you to use any weapon early"""
+ """Disable the weapon requirements by removing any movement or damage penalties, permitting you
+ to use any weapon early.
+ """
display_name = "No Weapon Requirements"
class NoSpellRequirementsOption(Toggle):
- """Disable the spell requirements permitting you to use any spell"""
+ """Disable the spell requirements permitting you to use any spell."""
display_name = "No Spell Requirements"
-class NoEquipLoadOption(Toggle):
- """Disable the equip load constraint from the game"""
- display_name = "No Equip Load"
-
+## Weapons
class RandomizeInfusionOption(Toggle):
"""Enable this option to infuse a percentage of the pool of weapons and shields."""
display_name = "Randomize Infusion"
-class RandomizeInfusionPercentageOption(Range):
- """The percentage of weapons/shields in the pool to be infused if Randomize Infusion is toggled"""
+class RandomizeInfusionPercentageOption(NamedRange):
+ """The percentage of weapons/shields in the pool to be infused if Randomize Infusion is toggled.
+ """
display_name = "Percentage of Infused Weapons"
range_start = 0
range_end = 100
default = 33
+ # 3/155 weapons are infused in the base game, or about 2%
+ special_range_names = {"similar to base game": 2}
class RandomizeWeaponLevelOption(Choice):
- """Enable this option to upgrade a percentage of the pool of weapons to a random value between the minimum and
- maximum levels defined.
+ """Enable this option to upgrade a percentage of the pool of weapons to a random value between
+ the minimum and maximum levels defined.
- All: All weapons are eligible, both basic and epic
- Basic: Only weapons that can be upgraded to +10
- Epic: Only weapons that can be upgraded to +5"""
+ - **All:** All weapons are eligible, both basic and epic
+ - **Basic:** Only weapons that can be upgraded to +10
+ - **Epic:** Only weapons that can be upgraded to +5
+ """
display_name = "Randomize Weapon Level"
option_none = 0
option_all = 1
@@ -132,7 +139,7 @@ class RandomizeWeaponLevelOption(Choice):
class RandomizeWeaponLevelPercentageOption(Range):
- """The percentage of weapons in the pool to be upgraded if randomize weapons level is toggled"""
+ """The percentage of weapons in the pool to be upgraded if randomize weapons level is toggled."""
display_name = "Percentage of Randomized Weapons"
range_start = 0
range_end = 100
@@ -140,7 +147,7 @@ class RandomizeWeaponLevelPercentageOption(Range):
class MinLevelsIn5WeaponPoolOption(Range):
- """The minimum upgraded value of a weapon in the pool of weapons that can only reach +5"""
+ """The minimum upgraded value of a weapon in the pool of weapons that can only reach +5."""
display_name = "Minimum Level of +5 Weapons"
range_start = 0
range_end = 5
@@ -148,7 +155,7 @@ class MinLevelsIn5WeaponPoolOption(Range):
class MaxLevelsIn5WeaponPoolOption(Range):
- """The maximum upgraded value of a weapon in the pool of weapons that can only reach +5"""
+ """The maximum upgraded value of a weapon in the pool of weapons that can only reach +5."""
display_name = "Maximum Level of +5 Weapons"
range_start = 0
range_end = 5
@@ -156,7 +163,7 @@ class MaxLevelsIn5WeaponPoolOption(Range):
class MinLevelsIn10WeaponPoolOption(Range):
- """The minimum upgraded value of a weapon in the pool of weapons that can reach +10"""
+ """The minimum upgraded value of a weapon in the pool of weapons that can reach +10."""
display_name = "Minimum Level of +10 Weapons"
range_start = 0
range_end = 10
@@ -164,72 +171,308 @@ class MinLevelsIn10WeaponPoolOption(Range):
class MaxLevelsIn10WeaponPoolOption(Range):
- """The maximum upgraded value of a weapon in the pool of weapons that can reach +10"""
+ """The maximum upgraded value of a weapon in the pool of weapons that can reach +10."""
display_name = "Maximum Level of +10 Weapons"
range_start = 0
range_end = 10
default = 10
-class EarlySmallLothricBanner(Choice):
- """This option makes it so the user can choose to force the Small Lothric Banner into an early sphere in their world or
- into an early sphere across all worlds."""
- display_name = "Early Small Lothric Banner"
- option_off = 0
- option_early_global = 1
- option_early_local = 2
- default = option_off
+## Item Smoothing
+class SmoothSoulItemsOption(DefaultOnToggle):
+ """Distribute soul items in a similar order as the base game.
-class LateBasinOfVowsOption(Toggle):
- """This option makes it so the Basin of Vows is still randomized, but guarantees you that you wont have to venture into
- Lothric Castle to find your Small Lothric Banner to get out of High Wall of Lothric. So you may find Basin of Vows early,
- but you wont have to fight Dancer to find your Small Lothric Banner."""
- display_name = "Late Basin of Vows"
+ By default, soul items will be distributed totally randomly. If this is set, less valuable soul
+ items will generally appear in earlier spheres and more valuable ones will generally appear
+ later.
+ """
+ display_name = "Smooth Soul Items"
-class LateDLCOption(Toggle):
- """This option makes it so you are guaranteed to find your Small Doll without having to venture off into the DLC,
- effectively putting anything in the DLC in logic after finding both Contraption Key and Small Doll,
- and being able to get into Irithyll of the Boreal Valley."""
- display_name = "Late DLC"
+class SmoothUpgradeItemsOption(DefaultOnToggle):
+ """Distribute upgrade items in a similar order as the base game.
+ By default, upgrade items will be distributed totally randomly. If this is set, lower-level
+ upgrade items will generally appear in earlier spheres and higher-level ones will generally
+ appear later.
+ """
+ display_name = "Smooth Upgrade Items"
-class EnableDLCOption(Toggle):
- """To use this option, you must own both the ASHES OF ARIANDEL and the RINGED CITY DLC"""
- display_name = "Enable DLC"
+class SmoothUpgradedWeaponsOption(DefaultOnToggle):
+ """Distribute upgraded weapons in a similar order as the base game.
+
+ By default, upgraded weapons will be distributed totally randomly. If this is set, lower-level
+ weapons will generally appear in earlier spheres and higher-level ones will generally appear
+ later.
+ """
+ display_name = "Smooth Upgraded Weapons"
+
+
+### Enemies
+
+class RandomizeEnemiesOption(DefaultOnToggle):
+ """Randomize enemy and boss placements."""
+ display_name = "Randomize Enemies"
+
+
+class SimpleEarlyBossesOption(DefaultOnToggle):
+ """Avoid replacing Iudex Gundyr and Vordt with late bosses.
+
+ This excludes all bosses after Dancer of the Boreal Valley from these two boss fights. Disable
+ it for a chance at a much harder early game.
+
+ This is ignored unless enemies are randomized.
+ """
+ display_name = "Simple Early Bosses"
+
+
+class ScaleEnemiesOption(DefaultOnToggle):
+ """Scale randomized enemy stats to match the areas in which they appear.
+
+ Disabling this will tend to make the early game much more difficult and the late game much
+ easier.
+
+ This is ignored unless enemies are randomized.
+ """
+ display_name = "Scale Enemies"
+
+
+class RandomizeMimicsWithEnemiesOption(Toggle):
+ """Mix Mimics into the main enemy pool.
+
+ If this is enabled, Mimics will be replaced by normal enemies who drop the Mimic rewards on
+ death, and Mimics will be placed randomly in place of normal enemies. It's recommended to enable
+ Impatient Mimics as well if you enable this.
+
+ This is ignored unless enemies are randomized.
+ """
+ display_name = "Randomize Mimics With Enemies"
+
+
+class RandomizeSmallCrystalLizardsWithEnemiesOption(Toggle):
+ """Mix small Crystal Lizards into the main enemy pool.
+
+ If this is enabled, Crystal Lizards will be replaced by normal enemies who drop the Crystal
+ Lizard rewards on death, and Crystal Lizards will be placed randomly in place of normal enemies.
+
+ This is ignored unless enemies are randomized.
+ """
+ display_name = "Randomize Small Crystal Lizards With Enemies"
+
+
+class ReduceHarmlessEnemiesOption(Toggle):
+ """Reduce the frequency that "harmless" enemies appear.
+
+ Enable this to add a bit of extra challenge. This severely limits the number of enemies that are
+ slow to aggro, slow to attack, and do very little damage that appear in the enemy pool.
+
+ This is ignored unless enemies are randomized.
+ """
+ display_name = "Reduce Harmless Enemies"
+
+
+class AllChestsAreMimicsOption(Toggle):
+ """Replace all chests with mimics that drop the same items.
+
+ If "Randomize Mimics With Enemies" is set, these chests will instead be replaced with random
+ enemies that drop the same items.
+
+ This is ignored unless enemies are randomized.
+ """
+ display_name = "All Chests Are Mimics"
+
+
+class ImpatientMimicsOption(Toggle):
+ """Mimics attack as soon as you get close instead of waiting for you to open them.
+
+ This is ignored unless enemies are randomized.
+ """
+ display_name = "Impatient Mimics"
+
+
+class RandomEnemyPresetOption(OptionDict):
+ """The YAML preset for the static enemy randomizer.
+
+ See the static randomizer documentation in `randomizer\\presets\\README.txt` for details.
+ Include this as nested YAML. For example:
+
+ .. code-block:: YAML
+
+ random_enemy_preset:
+ RemoveSource: Ancient Wyvern; Darkeater Midir
+ DontRandomize: Iudex Gundyr
+ """
+ display_name = "Random Enemy Preset"
+ supports_weighting = False
+ default = {}
+
+ valid_keys = ["Description", "RecommendFullRandomization", "RecommendNoEnemyProgression",
+ "OopsAll", "Boss", "Miniboss", "Basic", "BuffBasicEnemiesAsBosses",
+ "DontRandomize", "RemoveSource", "Enemies"]
+
+ @classmethod
+ def get_option_name(cls, value: Dict[str, Any]) -> str:
+ return json.dumps(value)
+
+
+## Item & Location
+
+class DS3ExcludeLocations(ExcludeLocations):
+ """Prevent these locations from having an important item."""
+ default = frozenset({"Hidden", "Small Crystal Lizards", "Upgrade", "Small Souls", "Miscellaneous"})
-dark_souls_options: typing.Dict[str, Option] = {
- "enable_weapon_locations": RandomizeWeaponLocations,
- "enable_shield_locations": RandomizeShieldLocations,
- "enable_armor_locations": RandomizeArmorLocations,
- "enable_ring_locations": RandomizeRingLocations,
- "enable_spell_locations": RandomizeSpellLocations,
- "enable_key_locations": RandomizeKeyLocations,
- "enable_boss_locations": RandomizeBossSoulLocations,
- "enable_npc_locations": RandomizeNPCLocations,
- "enable_misc_locations": RandomizeMiscLocations,
- "enable_health_upgrade_locations": RandomizeHealthLocations,
- "enable_progressive_locations": RandomizeProgressiveLocationsOption,
- "pool_type": PoolTypeOption,
- "guaranteed_items": GuaranteedItemsOption,
- "auto_equip": AutoEquipOption,
- "lock_equip": LockEquipOption,
- "no_weapon_requirements": NoWeaponRequirementsOption,
- "randomize_infusion": RandomizeInfusionOption,
- "randomize_infusion_percentage": RandomizeInfusionPercentageOption,
- "randomize_weapon_level": RandomizeWeaponLevelOption,
- "randomize_weapon_level_percentage": RandomizeWeaponLevelPercentageOption,
- "min_levels_in_5": MinLevelsIn5WeaponPoolOption,
- "max_levels_in_5": MaxLevelsIn5WeaponPoolOption,
- "min_levels_in_10": MinLevelsIn10WeaponPoolOption,
- "max_levels_in_10": MaxLevelsIn10WeaponPoolOption,
- "early_banner": EarlySmallLothricBanner,
- "late_basin_of_vows": LateBasinOfVowsOption,
- "late_dlc": LateDLCOption,
- "no_spell_requirements": NoSpellRequirementsOption,
- "no_equip_load": NoEquipLoadOption,
- "death_link": DeathLink,
- "enable_dlc": EnableDLCOption,
-}
+
+class ExcludedLocationBehaviorOption(Choice):
+ """How to choose items for excluded locations in DS3.
+
+ - **Allow Useful:** Excluded locations can't have progression items, but they can have useful
+ items.
+ - **Forbid Useful:** Neither progression items nor useful items can be placed in excluded
+ locations.
+ - **Do Not Randomize:** Excluded locations always contain the same item as in vanilla Dark Souls
+ III.
+
+ A "progression item" is anything that's required to unlock another location in some game. A
+ "useful item" is something each game defines individually, usually items that are quite
+ desirable but not strictly necessary.
+ """
+ display_name = "Excluded Locations Behavior"
+ option_allow_useful = 1
+ option_forbid_useful = 2
+ option_do_not_randomize = 3
+ default = 2
+
+
+class MissableLocationBehaviorOption(Choice):
+ """Which items can be placed in locations that can be permanently missed.
+
+ - **Allow Useful:** Missable locations can't have progression items, but they can have useful
+ items.
+ - **Forbid Useful:** Neither progression items nor useful items can be placed in missable
+ locations.
+ - **Do Not Randomize:** Missable locations always contain the same item as in vanilla Dark Souls
+ III.
+
+ A "progression item" is anything that's required to unlock another location in some game. A
+ "useful item" is something each game defines individually, usually items that are quite
+ desirable but not strictly necessary.
+ """
+ display_name = "Missable Locations Behavior"
+ option_allow_useful = 1
+ option_forbid_useful = 2
+ option_do_not_randomize = 3
+ default = 2
+
+
+@dataclass
+class DarkSouls3Options(PerGameCommonOptions):
+ # Game Options
+ early_banner: EarlySmallLothricBanner
+ late_basin_of_vows: LateBasinOfVowsOption
+ late_dlc: LateDLCOption
+ death_link: DeathLink
+ enable_dlc: EnableDLCOption
+ enable_ngp: EnableNGPOption
+
+ # Equipment
+ random_starting_loadout: RandomizeStartingLoadout
+ require_one_handed_starting_weapons: RequireOneHandedStartingWeapons
+ auto_equip: AutoEquipOption
+ lock_equip: LockEquipOption
+ no_equip_load: NoEquipLoadOption
+ no_weapon_requirements: NoWeaponRequirementsOption
+ no_spell_requirements: NoSpellRequirementsOption
+
+ # Weapons
+ randomize_infusion: RandomizeInfusionOption
+ randomize_infusion_percentage: RandomizeInfusionPercentageOption
+ randomize_weapon_level: RandomizeWeaponLevelOption
+ randomize_weapon_level_percentage: RandomizeWeaponLevelPercentageOption
+ min_levels_in_5: MinLevelsIn5WeaponPoolOption
+ max_levels_in_5: MaxLevelsIn5WeaponPoolOption
+ min_levels_in_10: MinLevelsIn10WeaponPoolOption
+ max_levels_in_10: MaxLevelsIn10WeaponPoolOption
+
+ # Item Smoothing
+ smooth_soul_items: SmoothSoulItemsOption
+ smooth_upgrade_items: SmoothUpgradeItemsOption
+ smooth_upgraded_weapons: SmoothUpgradedWeaponsOption
+
+ # Enemies
+ randomize_enemies: RandomizeEnemiesOption
+ simple_early_bosses: SimpleEarlyBossesOption
+ scale_enemies: ScaleEnemiesOption
+ randomize_mimics_with_enemies: RandomizeMimicsWithEnemiesOption
+ randomize_small_crystal_lizards_with_enemies: RandomizeSmallCrystalLizardsWithEnemiesOption
+ reduce_harmless_enemies: ReduceHarmlessEnemiesOption
+ all_chests_are_mimics: AllChestsAreMimicsOption
+ impatient_mimics: ImpatientMimicsOption
+ random_enemy_preset: RandomEnemyPresetOption
+
+ # Item & Location
+ exclude_locations: DS3ExcludeLocations
+ excluded_location_behavior: ExcludedLocationBehaviorOption
+ missable_location_behavior: MissableLocationBehaviorOption
+
+ # Removed
+ pool_type: Removed
+ enable_weapon_locations: Removed
+ enable_shield_locations: Removed
+ enable_armor_locations: Removed
+ enable_ring_locations: Removed
+ enable_spell_locations: Removed
+ enable_key_locations: Removed
+ enable_boss_locations: Removed
+ enable_npc_locations: Removed
+ enable_misc_locations: Removed
+ enable_health_upgrade_locations: Removed
+ enable_progressive_locations: Removed
+ guaranteed_items: Removed
+ excluded_locations: Removed
+ missable_locations: Removed
+
+
+option_groups = [
+ OptionGroup("Equipment", [
+ RandomizeStartingLoadout,
+ RequireOneHandedStartingWeapons,
+ AutoEquipOption,
+ LockEquipOption,
+ NoEquipLoadOption,
+ NoWeaponRequirementsOption,
+ NoSpellRequirementsOption,
+ ]),
+ OptionGroup("Weapons", [
+ RandomizeInfusionOption,
+ RandomizeInfusionPercentageOption,
+ RandomizeWeaponLevelOption,
+ RandomizeWeaponLevelPercentageOption,
+ MinLevelsIn5WeaponPoolOption,
+ MaxLevelsIn5WeaponPoolOption,
+ MinLevelsIn10WeaponPoolOption,
+ MaxLevelsIn10WeaponPoolOption,
+ ]),
+ OptionGroup("Item Smoothing", [
+ SmoothSoulItemsOption,
+ SmoothUpgradeItemsOption,
+ SmoothUpgradedWeaponsOption,
+ ]),
+ OptionGroup("Enemies", [
+ RandomizeEnemiesOption,
+ SimpleEarlyBossesOption,
+ ScaleEnemiesOption,
+ RandomizeMimicsWithEnemiesOption,
+ RandomizeSmallCrystalLizardsWithEnemiesOption,
+ ReduceHarmlessEnemiesOption,
+ AllChestsAreMimicsOption,
+ ImpatientMimicsOption,
+ RandomEnemyPresetOption,
+ ]),
+ OptionGroup("Item & Location Options", [
+ DS3ExcludeLocations,
+ ExcludedLocationBehaviorOption,
+ MissableLocationBehaviorOption,
+ ])
+]
diff --git a/worlds/dark_souls_3/__init__.py b/worlds/dark_souls_3/__init__.py
index 020010981160..159a870c7658 100644
--- a/worlds/dark_souls_3/__init__.py
+++ b/worlds/dark_souls_3/__init__.py
@@ -1,15 +1,19 @@
# world/dark_souls_3/__init__.py
-from typing import Dict, Set, List
+from collections.abc import Sequence
+from collections import defaultdict
+import json
+from logging import warning
+from typing import cast, Any, Callable, Dict, Set, List, Optional, TextIO, Union
-from BaseClasses import MultiWorld, Region, Item, Entrance, Tutorial, ItemClassification
-from Options import Toggle
+from BaseClasses import CollectionState, MultiWorld, Region, Location, LocationProgressType, Entrance, Tutorial, ItemClassification
from worlds.AutoWorld import World, WebWorld
-from worlds.generic.Rules import set_rule, add_rule, add_item_rule
+from worlds.generic.Rules import CollectionRule, ItemRule, add_rule, add_item_rule
-from .Items import DarkSouls3Item, DS3ItemCategory, item_dictionary, key_item_names, item_descriptions
-from .Locations import DarkSouls3Location, DS3LocationCategory, location_tables, location_dictionary
-from .Options import RandomizeWeaponLevelOption, PoolTypeOption, EarlySmallLothricBanner, dark_souls_options
+from .Bosses import DS3BossInfo, all_bosses, default_yhorm_location
+from .Items import DarkSouls3Item, DS3ItemData, Infusion, UsefulIf, filler_item_names, item_descriptions, item_dictionary, item_name_groups
+from .Locations import DarkSouls3Location, DS3LocationData, location_tables, location_descriptions, location_dictionary, location_name_groups, region_order
+from .Options import DarkSouls3Options, option_groups
class DarkSouls3Web(WebWorld):
@@ -34,91 +38,117 @@ class DarkSouls3Web(WebWorld):
)
tutorials = [setup_en, setup_fr]
-
+ option_groups = option_groups
item_descriptions = item_descriptions
+ rich_text_options_doc = True
class DarkSouls3World(World):
"""
Dark souls III is an Action role-playing game and is part of the Souls series developed by FromSoftware.
- Played in a third-person perspective, players have access to various weapons, armour, magic, and consumables that
+ Played from a third-person perspective, players have access to various weapons, armour, magic, and consumables that
they can use to fight their enemies.
"""
- game: str = "Dark Souls III"
- option_definitions = dark_souls_options
- topology_present: bool = True
+ game = "Dark Souls III"
+ options: DarkSouls3Options
+ options_dataclass = DarkSouls3Options
web = DarkSouls3Web()
base_id = 100000
- enabled_location_categories: Set[DS3LocationCategory]
required_client_version = (0, 4, 2)
- item_name_to_id = DarkSouls3Item.get_name_to_id()
- location_name_to_id = DarkSouls3Location.get_name_to_id()
- item_name_groups = {
- "Cinders": {
- "Cinders of a Lord - Abyss Watcher",
- "Cinders of a Lord - Aldrich",
- "Cinders of a Lord - Yhorm the Giant",
- "Cinders of a Lord - Lothric Prince"
- }
+ item_name_to_id = {data.name: data.ap_code for data in item_dictionary.values() if data.ap_code is not None}
+ location_name_to_id = {
+ location.name: location.ap_code
+ for locations in location_tables.values()
+ for location in locations
+ if location.ap_code is not None
}
+ location_name_groups = location_name_groups
+ item_name_groups = item_name_groups
+ location_descriptions = location_descriptions
+ item_descriptions = item_descriptions
+
+ yhorm_location: DS3BossInfo = default_yhorm_location
+ """If enemy randomization is enabled, this is the boss who Yhorm the Giant should replace.
+
+ This is used to determine where the Storm Ruler can be placed.
+ """
+
+ all_excluded_locations: Set[str] = set()
+ """This is the same value as `self.options.exclude_locations.value` initially, but if
+ `options.exclude_locations` gets cleared due to `excluded_locations: allow_useful` this still
+ holds the old locations so we can ensure they don't get necessary items.
+ """
+
+ local_itempool: List[DarkSouls3Item] = []
+ """The pool of all items within this particular world. This is a subset of
+ `self.multiworld.itempool`."""
def __init__(self, multiworld: MultiWorld, player: int):
super().__init__(multiworld, player)
- self.locked_items = []
- self.locked_locations = []
- self.main_path_locations = []
- self.enabled_location_categories = set()
-
-
- def generate_early(self):
- if self.multiworld.enable_weapon_locations[self.player] == Toggle.option_true:
- self.enabled_location_categories.add(DS3LocationCategory.WEAPON)
- if self.multiworld.enable_shield_locations[self.player] == Toggle.option_true:
- self.enabled_location_categories.add(DS3LocationCategory.SHIELD)
- if self.multiworld.enable_armor_locations[self.player] == Toggle.option_true:
- self.enabled_location_categories.add(DS3LocationCategory.ARMOR)
- if self.multiworld.enable_ring_locations[self.player] == Toggle.option_true:
- self.enabled_location_categories.add(DS3LocationCategory.RING)
- if self.multiworld.enable_spell_locations[self.player] == Toggle.option_true:
- self.enabled_location_categories.add(DS3LocationCategory.SPELL)
- if self.multiworld.enable_npc_locations[self.player] == Toggle.option_true:
- self.enabled_location_categories.add(DS3LocationCategory.NPC)
- if self.multiworld.enable_key_locations[self.player] == Toggle.option_true:
- self.enabled_location_categories.add(DS3LocationCategory.KEY)
- if self.multiworld.early_banner[self.player] == EarlySmallLothricBanner.option_early_global:
- self.multiworld.early_items[self.player]['Small Lothric Banner'] = 1
- elif self.multiworld.early_banner[self.player] == EarlySmallLothricBanner.option_early_local:
- self.multiworld.local_early_items[self.player]['Small Lothric Banner'] = 1
- if self.multiworld.enable_boss_locations[self.player] == Toggle.option_true:
- self.enabled_location_categories.add(DS3LocationCategory.BOSS)
- if self.multiworld.enable_misc_locations[self.player] == Toggle.option_true:
- self.enabled_location_categories.add(DS3LocationCategory.MISC)
- if self.multiworld.enable_health_upgrade_locations[self.player] == Toggle.option_true:
- self.enabled_location_categories.add(DS3LocationCategory.HEALTH)
- if self.multiworld.enable_progressive_locations[self.player] == Toggle.option_true:
- self.enabled_location_categories.add(DS3LocationCategory.PROGRESSIVE_ITEM)
-
-
- def create_regions(self):
- progressive_location_table = []
- if self.multiworld.enable_progressive_locations[self.player]:
- progressive_location_table = [] + \
- location_tables["Progressive Items 1"] + \
- location_tables["Progressive Items 2"] + \
- location_tables["Progressive Items 3"] + \
- location_tables["Progressive Items 4"]
-
- if self.multiworld.enable_dlc[self.player].value:
- progressive_location_table += location_tables["Progressive Items DLC"]
-
- if self.multiworld.enable_health_upgrade_locations[self.player]:
- progressive_location_table += location_tables["Progressive Items Health"]
-
+ self.all_excluded_locations = set()
+
+ def generate_early(self) -> None:
+ self.all_excluded_locations.update(self.options.exclude_locations.value)
+
+ # Inform Universal Tracker where Yhorm is being randomized to.
+ if hasattr(self.multiworld, "re_gen_passthrough"):
+ if "Dark Souls III" in self.multiworld.re_gen_passthrough:
+ if self.multiworld.re_gen_passthrough["Dark Souls III"]["options"]["randomize_enemies"]:
+ yhorm_data = self.multiworld.re_gen_passthrough["Dark Souls III"]["yhorm"]
+ for boss in all_bosses:
+ if yhorm_data.startswith(boss.name):
+ self.yhorm_location = boss
+
+ # Randomize Yhorm manually so that we know where to place the Storm Ruler.
+ elif self.options.randomize_enemies:
+ self.yhorm_location = self.random.choice(
+ [boss for boss in all_bosses if self._allow_boss_for_yhorm(boss)])
+
+ # If Yhorm is early, make sure the Storm Ruler is easily available to avoid BK
+ # Iudex Gundyr is handled separately in _fill_local_items
+ if (
+ self.yhorm_location.name == "Vordt of the Boreal Valley" or (
+ self.yhorm_location.name == "Dancer of the Boreal Valley" and
+ not self.options.late_basin_of_vows
+ )
+ ):
+ self.multiworld.local_early_items[self.player]["Storm Ruler"] = 1
+
+ def _allow_boss_for_yhorm(self, boss: DS3BossInfo) -> bool:
+ """Returns whether boss is a valid location for Yhorm in this seed."""
+
+ if not self.options.enable_dlc and boss.dlc: return False
+
+ if not self._is_location_available("PC: Storm Ruler - boss room"):
+ # If the Storm Ruler isn't randomized, make sure the player can get to the normal Storm
+ # Ruler location before they need to get through Yhorm.
+ if boss.before_storm_ruler: return False
+
+ # If the Small Doll also wasn't randomized, make sure Yhorm isn't blocking access to it
+ # or it won't be possible to get into Profaned Capital before beating him.
+ if (
+ not self._is_location_available("CD: Small Doll - boss drop")
+ and boss.name in {"Crystal Sage", "Deacons of the Deep"}
+ ):
+ return False
+
+ if boss.name != "Iudex Gundyr": return True
+
+ # Cemetery of Ash has very few locations and all of them are excluded by default, so only
+ # allow Yhorm as Iudex Gundyr if there's at least one available location.
+ return any(
+ self._is_location_available(location)
+ and location.name not in self.all_excluded_locations
+ and location.name != "CA: Coiled Sword - boss drop"
+ for location in location_tables["Cemetery of Ash"]
+ )
+
+ def create_regions(self) -> None:
# Create Vanilla Regions
- regions: Dict[str, Region] = {}
- regions["Menu"] = self.create_region("Menu", progressive_location_table)
+ regions: Dict[str, Region] = {"Menu": self.create_region("Menu", {})}
regions.update({region_name: self.create_region(region_name, location_tables[region_name]) for region_name in [
+ "Cemetery of Ash",
"Firelink Shrine",
"Firelink Shrine Bell Tower",
"High Wall of Lothric",
@@ -138,18 +168,15 @@ def create_regions(self):
"Untended Graves",
"Archdragon Peak",
"Kiln of the First Flame",
+ "Greirat's Shop",
+ "Karla's Shop",
]})
- # Adds Path of the Dragon as an event item for Archdragon Peak access
- potd_location = DarkSouls3Location(self.player, "CKG: Path of the Dragon", DS3LocationCategory.EVENT, "Path of the Dragon", None, regions["Consumed King's Garden"])
- potd_location.place_locked_item(Item("Path of the Dragon", ItemClassification.progression, None, self.player))
- regions["Consumed King's Garden"].locations.append(potd_location)
-
# Create DLC Regions
- if self.multiworld.enable_dlc[self.player]:
+ if self.options.enable_dlc:
regions.update({region_name: self.create_region(region_name, location_tables[region_name]) for region_name in [
- "Painted World of Ariandel 1",
- "Painted World of Ariandel 2",
+ "Painted World of Ariandel (Before Contraption)",
+ "Painted World of Ariandel (After Contraption)",
"Dreg Heap",
"Ringed City",
]})
@@ -161,7 +188,9 @@ def create_connection(from_region: str, to_region: str):
connection.connect(regions[to_region])
regions["Menu"].exits.append(Entrance(self.player, "New Game", regions["Menu"]))
- self.multiworld.get_entrance("New Game", self.player).connect(regions["Firelink Shrine"])
+ self.multiworld.get_entrance("New Game", self.player).connect(regions["Cemetery of Ash"])
+
+ create_connection("Cemetery of Ash", "Firelink Shrine")
create_connection("Firelink Shrine", "High Wall of Lothric")
create_connection("Firelink Shrine", "Firelink Shrine Bell Tower")
@@ -169,6 +198,7 @@ def create_connection(from_region: str, to_region: str):
create_connection("High Wall of Lothric", "Undead Settlement")
create_connection("High Wall of Lothric", "Lothric Castle")
+ create_connection("High Wall of Lothric", "Greirat's Shop")
create_connection("Undead Settlement", "Road of Sacrifices")
@@ -185,6 +215,7 @@ def create_connection(from_region: str, to_region: str):
create_connection("Irithyll Dungeon", "Archdragon Peak")
create_connection("Irithyll Dungeon", "Profaned Capital")
+ create_connection("Irithyll Dungeon", "Karla's Shop")
create_connection("Lothric Castle", "Consumed King's Garden")
create_connection("Lothric Castle", "Grand Archives")
@@ -192,357 +223,1349 @@ def create_connection(from_region: str, to_region: str):
create_connection("Consumed King's Garden", "Untended Graves")
# Connect DLC Regions
- if self.multiworld.enable_dlc[self.player]:
- create_connection("Cathedral of the Deep", "Painted World of Ariandel 1")
- create_connection("Painted World of Ariandel 1", "Painted World of Ariandel 2")
- create_connection("Painted World of Ariandel 2", "Dreg Heap")
+ if self.options.enable_dlc:
+ create_connection("Cathedral of the Deep", "Painted World of Ariandel (Before Contraption)")
+ create_connection("Painted World of Ariandel (Before Contraption)",
+ "Painted World of Ariandel (After Contraption)")
+ create_connection("Painted World of Ariandel (After Contraption)", "Dreg Heap")
create_connection("Dreg Heap", "Ringed City")
-
# For each region, add the associated locations retrieved from the corresponding location_table
def create_region(self, region_name, location_table) -> Region:
new_region = Region(region_name, self.player, self.multiworld)
+ # Use this to un-exclude event locations so the fill doesn't complain about items behind
+ # them being unreachable.
+ excluded = self.options.exclude_locations.value
+
for location in location_table:
- if location.category in self.enabled_location_categories:
- new_location = DarkSouls3Location(
- self.player,
- location.name,
- location.category,
- location.default_item,
- self.location_name_to_id[location.name],
- new_region
- )
+ if self._is_location_available(location):
+ new_location = DarkSouls3Location(self.player, location, new_region)
+ if (
+ # Exclude missable locations that don't allow useful items
+ location.missable and self.options.missable_location_behavior == "forbid_useful"
+ and not (
+ # Unless they are excluded to a higher degree already
+ location.name in self.all_excluded_locations
+ and self.options.missable_location_behavior < self.options.excluded_location_behavior
+ )
+ ) or (
+ # Lift Chamber Key is missable. Exclude Lift-Chamber-Key-Locked locations if it isn't randomized
+ not self._is_location_available("FS: Lift Chamber Key - Leonhard")
+ and location.name == "HWL: Red Eye Orb - wall tower, miniboss"
+ ) or (
+ # Chameleon is missable. Exclude Chameleon-locked locations if it isn't randomized
+ not self._is_location_available("AL: Chameleon - tomb after marrying Anri")
+ and location.name in {"RC: Dragonhead Shield - streets monument, across bridge",
+ "RC: Large Soul of a Crestfallen Knight - streets monument, across bridge",
+ "RC: Divine Blessing - streets monument, mob drop", "RC: Lapp's Helm - Lapp",
+ "RC: Lapp's Armor - Lapp",
+ "RC: Lapp's Gauntlets - Lapp",
+ "RC: Lapp's Leggings - Lapp"}
+ ):
+ new_location.progress_type = LocationProgressType.EXCLUDED
else:
- # Replace non-randomized progression items with events
- event_item = self.create_item(location.default_item)
- if event_item.classification != ItemClassification.progression:
+ # Don't allow missable duplicates of progression items to be expected progression.
+ if location.name in {"PC: Storm Ruler - Siegward",
+ "US: Pyromancy Flame - Cornyx",
+ "US: Tower Key - kill Irina"}:
continue
+ # Replace non-randomized items with events that give the default item
+ event_item = (
+ self.create_item(location.default_item_name) if location.default_item_name
+ else DarkSouls3Item.event(location.name, self.player)
+ )
+
new_location = DarkSouls3Location(
self.player,
- location.name,
- location.category,
- location.default_item,
- None,
- new_region
+ location,
+ parent = new_region,
+ event = True,
)
event_item.code = None
new_location.place_locked_item(event_item)
-
- if region_name == "Menu":
- add_item_rule(new_location, lambda item: not item.advancement)
+ if location.name in excluded:
+ excluded.remove(location.name)
+ # Only remove from all_excluded if excluded does not have priority over missable
+ if not (self.options.missable_location_behavior < self.options.excluded_location_behavior):
+ self.all_excluded_locations.remove(location.name)
new_region.locations.append(new_location)
self.multiworld.regions.append(new_region)
return new_region
-
- def create_items(self):
- dlc_enabled = self.multiworld.enable_dlc[self.player] == Toggle.option_true
-
- itempool_by_category = {category: [] for category in self.enabled_location_categories}
+ def create_items(self) -> None:
+ # Just used to efficiently deduplicate items
+ item_set: Set[str] = set()
# Gather all default items on randomized locations
+ self.local_itempool = []
num_required_extra_items = 0
- for location in self.multiworld.get_locations(self.player):
- if location.category in itempool_by_category:
- if item_dictionary[location.default_item_name].category == DS3ItemCategory.SKIP:
+ for location in cast(List[DarkSouls3Location], self.multiworld.get_unfilled_locations(self.player)):
+ if not self._is_location_available(location.name):
+ raise Exception("DS3 generation bug: Added an unavailable location.")
+
+ default_item_name = cast(str, location.data.default_item_name)
+ item = item_dictionary[default_item_name]
+ if item.skip:
+ num_required_extra_items += 1
+ elif not item.unique:
+ self.local_itempool.append(self.create_item(default_item_name))
+ else:
+ # For unique items, make sure there aren't duplicates in the item set even if there
+ # are multiple in-game locations that provide them.
+ if default_item_name in item_set:
num_required_extra_items += 1
else:
- itempool_by_category[location.category].append(location.default_item_name)
-
- # Replace each item category with a random sample of items of those types
- if self.multiworld.pool_type[self.player] == PoolTypeOption.option_various:
- def create_random_replacement_list(item_categories: Set[DS3ItemCategory], num_items: int):
- candidates = [
- item.name for item
- in item_dictionary.values()
- if (item.category in item_categories and (not item.is_dlc or dlc_enabled))
- ]
- return self.multiworld.random.sample(candidates, num_items)
-
- if DS3LocationCategory.WEAPON in self.enabled_location_categories:
- itempool_by_category[DS3LocationCategory.WEAPON] = create_random_replacement_list(
- {
- DS3ItemCategory.WEAPON_UPGRADE_5,
- DS3ItemCategory.WEAPON_UPGRADE_10,
- DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE
- },
- len(itempool_by_category[DS3LocationCategory.WEAPON])
- )
- if DS3LocationCategory.SHIELD in self.enabled_location_categories:
- itempool_by_category[DS3LocationCategory.SHIELD] = create_random_replacement_list(
- {DS3ItemCategory.SHIELD, DS3ItemCategory.SHIELD_INFUSIBLE},
- len(itempool_by_category[DS3LocationCategory.SHIELD])
- )
- if DS3LocationCategory.ARMOR in self.enabled_location_categories:
- itempool_by_category[DS3LocationCategory.ARMOR] = create_random_replacement_list(
- {DS3ItemCategory.ARMOR},
- len(itempool_by_category[DS3LocationCategory.ARMOR])
- )
- if DS3LocationCategory.RING in self.enabled_location_categories:
- itempool_by_category[DS3LocationCategory.RING] = create_random_replacement_list(
- {DS3ItemCategory.RING},
- len(itempool_by_category[DS3LocationCategory.RING])
- )
- if DS3LocationCategory.SPELL in self.enabled_location_categories:
- itempool_by_category[DS3LocationCategory.SPELL] = create_random_replacement_list(
- {DS3ItemCategory.SPELL},
- len(itempool_by_category[DS3LocationCategory.SPELL])
- )
-
- itempool: List[DarkSouls3Item] = []
- for category in self.enabled_location_categories:
- itempool += [self.create_item(name) for name in itempool_by_category[category]]
-
- # A list of items we can replace
- removable_items = [item for item in itempool if item.classification != ItemClassification.progression]
-
- guaranteed_items = self.multiworld.guaranteed_items[self.player].value
- for item_name in guaranteed_items:
- # Break early just in case nothing is removable (if user is trying to guarantee more
- # items than the pool can hold, for example)
- if len(removable_items) == 0:
- break
-
- num_existing_copies = len([item for item in itempool if item.name == item_name])
- for _ in range(guaranteed_items[item_name]):
- if num_existing_copies > 0:
- num_existing_copies -= 1
- continue
-
- if num_required_extra_items > 0:
- # We can just add them instead of using "Soul of an Intrepid Hero" later
- num_required_extra_items -= 1
- else:
- if len(removable_items) == 0:
- break
+ item_set.add(default_item_name)
+ self.local_itempool.append(self.create_item(default_item_name))
- # Try to construct a list of items with the same category that can be removed
- # If none exist, just remove something at random
- removable_shortlist = [
- item for item
- in removable_items
- if item_dictionary[item.name].category == item_dictionary[item_name].category
- ]
- if len(removable_shortlist) == 0:
- removable_shortlist = removable_items
+ injectables = self._create_injectable_items(num_required_extra_items)
+ num_required_extra_items -= len(injectables)
+ self.local_itempool.extend(injectables)
- removed_item = self.multiworld.random.choice(removable_shortlist)
- removable_items.remove(removed_item) # To avoid trying to replace the same item twice
- itempool.remove(removed_item)
+ # Extra filler items for locations containing skip items
+ self.local_itempool.extend(self.create_item(self.get_filler_item_name()) for _ in range(num_required_extra_items))
- itempool.append(self.create_item(item_name))
-
- # Extra filler items for locations containing SKIP items
- itempool += [self.create_filler() for _ in range(num_required_extra_items)]
+ # Potentially fill some items locally and remove them from the itempool
+ self._fill_local_items()
# Add items to itempool
- self.multiworld.itempool += itempool
-
-
- def create_item(self, name: str) -> Item:
- useful_categories = {
- DS3ItemCategory.WEAPON_UPGRADE_5,
- DS3ItemCategory.WEAPON_UPGRADE_10,
- DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE,
- DS3ItemCategory.SPELL,
- }
- data = self.item_name_to_id[name]
-
- if name in key_item_names:
- item_classification = ItemClassification.progression
- elif item_dictionary[name].category in useful_categories or name in {"Estus Shard", "Undead Bone Shard"}:
- item_classification = ItemClassification.useful
- else:
- item_classification = ItemClassification.filler
-
- return DarkSouls3Item(name, item_classification, data, self.player)
+ self.multiworld.itempool += self.local_itempool
+
+ def _create_injectable_items(self, num_required_extra_items: int) -> List[DarkSouls3Item]:
+ """Returns a list of items to inject into the multiworld instead of skipped items.
+
+ If there isn't enough room to inject all the necessary progression items
+ that are in missable locations by default, this adds them to the
+ player's starting inventory.
+ """
+
+ all_injectable_items = [
+ item for item
+ in item_dictionary.values()
+ if item.inject and (not item.is_dlc or self.options.enable_dlc)
+ ]
+ injectable_mandatory = [
+ item for item in all_injectable_items
+ if item.classification == ItemClassification.progression
+ ]
+ injectable_optional = [
+ item for item in all_injectable_items
+ if item.classification != ItemClassification.progression
+ ]
+
+ number_to_inject = min(num_required_extra_items, len(all_injectable_items))
+ items = (
+ self.random.sample(
+ injectable_mandatory,
+ k=min(len(injectable_mandatory), number_to_inject)
+ )
+ + self.random.sample(
+ injectable_optional,
+ k=max(0, number_to_inject - len(injectable_mandatory))
+ )
+ )
+
+ if number_to_inject < len(injectable_mandatory):
+ # It's worth considering the possibility of _removing_ unimportant
+ # items from the pool to inject these instead rather than just
+ # making them part of the starting health back
+ for item in injectable_mandatory:
+ if item in items: continue
+ self.multiworld.push_precollected(self.create_item(item))
+ warning(
+ f"Couldn't add \"{item.name}\" to the item pool for " +
+ f"{self.player_name}. Adding it to the starting " +
+ f"inventory instead."
+ )
+ return [self.create_item(item) for item in items]
+
+ def create_item(self, item: Union[str, DS3ItemData]) -> DarkSouls3Item:
+ data = item if isinstance(item, DS3ItemData) else item_dictionary[item]
+ classification = None
+ if self.multiworld and data.useful_if != UsefulIf.DEFAULT and (
+ (
+ data.useful_if == UsefulIf.BASE and
+ not self.options.enable_dlc and
+ not self.options.enable_ngp
+ )
+ or (data.useful_if == UsefulIf.NO_DLC and not self.options.enable_dlc)
+ or (data.useful_if == UsefulIf.NO_NGP and not self.options.enable_ngp)
+ ):
+ classification = ItemClassification.useful
+
+ if (
+ self.options.randomize_weapon_level != "none"
+ and data.category.upgrade_level
+ # Because we require the Pyromancy Flame to be available early, don't upgrade it so it
+ # doesn't get shuffled around by weapon smoothing.
+ and data.name != "Pyromancy Flame"
+ ):
+ # if the user made an error and set a min higher than the max we default to the max
+ max_5 = self.options.max_levels_in_5.value
+ min_5 = min(self.options.min_levels_in_5.value, max_5)
+ max_10 = self.options.max_levels_in_10.value
+ min_10 = min(self.options.min_levels_in_10.value, max_10)
+ weapon_level_percentage = self.options.randomize_weapon_level_percentage
+
+ if self.random.randint(0, 99) < weapon_level_percentage:
+ if data.category.upgrade_level == 5:
+ data = data.upgrade(self.random.randint(min_5, max_5))
+ elif data.category.upgrade_level == 10:
+ data = data.upgrade(self.random.randint(min_10, max_10))
+
+ if self.options.randomize_infusion and data.category.is_infusible:
+ infusion_percentage = self.options.randomize_infusion_percentage
+ if self.random.randint(0, 99) < infusion_percentage:
+ data = data.infuse(self.random.choice(list(Infusion)))
+
+ return DarkSouls3Item(self.player, data, classification=classification)
+
+ def _fill_local_items(self) -> None:
+ """Removes certain items from the item pool and manually places them in the local world.
+
+ We can't do this in pre_fill because the itempool may not be modified after create_items.
+ """
+ # If Yhorm is at Iudex Gundyr, Storm Ruler must be randomized, so it can always be moved.
+ # Fill this manually so that, if very few slots are available in Cemetery of Ash, this
+ # doesn't get locked out by bad rolls on the next two fills.
+ if self.yhorm_location.name == "Iudex Gundyr":
+ self._fill_local_item("Storm Ruler", ["Cemetery of Ash"],
+ lambda location: location.name != "CA: Coiled Sword - boss drop")
+
+ # If the Coiled Sword is vanilla, it is early enough and doesn't need to be placed.
+ # Don't place this in the multiworld because it's necessary almost immediately, and don't
+ # mark it as a blocker for HWL because having a miniscule Sphere 1 screws with progression balancing.
+ if self._is_location_available("CA: Coiled Sword - boss drop"):
+ self._fill_local_item("Coiled Sword", ["Cemetery of Ash", "Firelink Shrine"])
+
+ # If the HWL Raw Gem is vanilla, it is early enough and doesn't need to be removed. If
+ # upgrade smoothing is enabled, make sure one raw gem is available early for SL1 players
+ if (
+ self._is_location_available("HWL: Raw Gem - fort roof, lizard")
+ and self.options.smooth_upgrade_items
+ ):
+ self._fill_local_item("Raw Gem", [
+ "Cemetery of Ash",
+ "Firelink Shrine",
+ "High Wall of Lothric"
+ ])
+
+ def _fill_local_item(
+ self, name: str,
+ regions: List[str],
+ additional_condition: Optional[Callable[[DS3LocationData], bool]] = None,
+ ) -> None:
+ """Chooses a valid location for the item with the given name and places it there.
+
+ This always chooses a local location among the given regions. If additional_condition is
+ passed, only locations meeting that condition will be considered.
+
+ If the item could not be placed, it will be added to starting inventory.
+ """
+ item = next((item for item in self.local_itempool if item.name == name), None)
+ if not item: return
+
+ candidate_locations = [
+ location for location in (
+ self.multiworld.get_location(location.name, self.player)
+ for region in regions
+ for location in location_tables[region]
+ if self._is_location_available(location)
+ and not location.missable
+ and not location.conditional
+ and (not additional_condition or additional_condition(location))
+ )
+ # We can't use location.progress_type here because it's not set
+ # until after `set_rules()` runs.
+ if not location.item and location.name not in self.all_excluded_locations
+ and location.item_rule(item)
+ ]
+
+ self.local_itempool.remove(item)
+
+ if not candidate_locations:
+ warning(f"Couldn't place \"{name}\" in a valid location for {self.player_name}. Adding it to starting inventory instead.")
+ location = next(
+ (location for location in self._get_our_locations() if location.data.default_item_name == item.name),
+ None
+ )
+ if location: self._replace_with_filler(location)
+ self.multiworld.push_precollected(self.create_item(name))
+ return
+
+ location = self.random.choice(candidate_locations)
+ location.place_locked_item(item)
+
+ def _replace_with_filler(self, location: DarkSouls3Location) -> None:
+ """If possible, choose a filler item to replace location's current contents with."""
+ if location.locked: return
+
+ # Try 10 filler items. If none of them work, give up and leave it as-is.
+ for _ in range(0, 10):
+ candidate = self.create_filler()
+ if location.item_rule(candidate):
+ location.item = candidate
+ return
def get_filler_item_name(self) -> str:
- return "Soul of an Intrepid Hero"
-
+ return self.random.choice(filler_item_names)
def set_rules(self) -> None:
- # Define the access rules to the entrances
- set_rule(self.multiworld.get_entrance("Go To Undead Settlement", self.player),
- lambda state: state.has("Small Lothric Banner", self.player))
- set_rule(self.multiworld.get_entrance("Go To Lothric Castle", self.player),
- lambda state: state.has("Basin of Vows", self.player))
- set_rule(self.multiworld.get_entrance("Go To Irithyll of the Boreal Valley", self.player),
- lambda state: state.has("Small Doll", self.player))
- set_rule(self.multiworld.get_entrance("Go To Archdragon Peak", self.player),
- lambda state: state.has("Path of the Dragon", self.player))
- set_rule(self.multiworld.get_entrance("Go To Grand Archives", self.player),
- lambda state: state.has("Grand Archives Key", self.player))
- set_rule(self.multiworld.get_entrance("Go To Kiln of the First Flame", self.player),
- lambda state: state.has("Cinders of a Lord - Abyss Watcher", self.player) and
- state.has("Cinders of a Lord - Yhorm the Giant", self.player) and
- state.has("Cinders of a Lord - Aldrich", self.player) and
- state.has("Cinders of a Lord - Lothric Prince", self.player))
-
- if self.multiworld.late_basin_of_vows[self.player] == Toggle.option_true:
- add_rule(self.multiworld.get_entrance("Go To Lothric Castle", self.player),
- lambda state: state.has("Small Lothric Banner", self.player))
+ randomized_items = {item.name for item in self.local_itempool}
+
+ self._add_shop_rules()
+ self._add_npc_rules()
+ self._add_transposition_rules()
+ self._add_crow_rules()
+ self._add_allow_useful_location_rules()
+ self._add_early_item_rules(randomized_items)
+
+ self._add_entrance_rule("Firelink Shrine Bell Tower", "Tower Key")
+ self._add_entrance_rule("Undead Settlement", lambda state: (
+ state.has("Small Lothric Banner", self.player)
+ and self._can_get(state, "HWL: Soul of Boreal Valley Vordt")
+ ))
+ self._add_entrance_rule("Road of Sacrifices", "US -> RS")
+ self._add_entrance_rule(
+ "Cathedral of the Deep",
+ lambda state: self._can_get(state, "RS: Soul of a Crystal Sage")
+ )
+ self._add_entrance_rule("Farron Keep", "RS -> FK")
+ self._add_entrance_rule(
+ "Catacombs of Carthus",
+ lambda state: self._can_get(state, "FK: Soul of the Blood of the Wolf")
+ )
+ self._add_entrance_rule("Irithyll Dungeon", "IBV -> ID")
+ self._add_entrance_rule(
+ "Lothric Castle",
+ lambda state: self._can_get(state, "HWL: Soul of the Dancer")
+ )
+ self._add_entrance_rule(
+ "Untended Graves",
+ lambda state: self._can_get(state, "CKG: Soul of Consumed Oceiros")
+ )
+ self._add_entrance_rule("Irithyll of the Boreal Valley", lambda state: (
+ state.has("Small Doll", self.player)
+ and self._can_get(state, "CC: Soul of High Lord Wolnir")
+ ))
+ self._add_entrance_rule(
+ "Anor Londo",
+ lambda state: self._can_get(state, "IBV: Soul of Pontiff Sulyvahn")
+ )
+ self._add_entrance_rule("Archdragon Peak", "Path of the Dragon")
+ self._add_entrance_rule("Grand Archives", lambda state: (
+ state.has("Grand Archives Key", self.player)
+ and self._can_get(state, "LC: Soul of Dragonslayer Armour")
+ ))
+ self._add_entrance_rule("Kiln of the First Flame", lambda state: (
+ state.has("Cinders of a Lord - Abyss Watcher", self.player)
+ and state.has("Cinders of a Lord - Yhorm the Giant", self.player)
+ and state.has("Cinders of a Lord - Aldrich", self.player)
+ and state.has("Cinders of a Lord - Lothric Prince", self.player)
+ and state.has("Transposing Kiln", self.player)
+ ))
+
+ if self.options.late_basin_of_vows:
+ self._add_entrance_rule("Lothric Castle", lambda state: (
+ state.has("Small Lothric Banner", self.player)
+ # Make sure these are actually available early.
+ and (
+ "Transposing Kiln" not in randomized_items
+ or state.has("Transposing Kiln", self.player)
+ ) and (
+ "Pyromancy Flame" not in randomized_items
+ or state.has("Pyromancy Flame", self.player)
+ )
+ # This isn't really necessary, but it ensures that the game logic knows players will
+ # want to do Lothric Castle after at least being _able_ to access Catacombs. This is
+ # useful for smooth item placement.
+ and self._has_any_scroll(state)
+ ))
+
+ if self.options.late_basin_of_vows > 1: # After Small Doll
+ self._add_entrance_rule("Lothric Castle", "Small Doll")
# DLC Access Rules Below
- if self.multiworld.enable_dlc[self.player]:
- set_rule(self.multiworld.get_entrance("Go To Ringed City", self.player),
- lambda state: state.has("Small Envoy Banner", self.player))
+ if self.options.enable_dlc:
+ self._add_entrance_rule("Painted World of Ariandel (Before Contraption)", "CD -> PW1")
+ self._add_entrance_rule("Painted World of Ariandel (After Contraption)", "Contraption Key")
+ self._add_entrance_rule(
+ "Dreg Heap",
+ lambda state: self._can_get(state, "PW2: Soul of Sister Friede")
+ )
+ self._add_entrance_rule("Ringed City", lambda state: (
+ state.has("Small Envoy Banner", self.player)
+ and self._can_get(state, "DH: Soul of the Demon Prince")
+ ))
- # If key items are randomized, must have contraption key to enter second half of Ashes DLC
- # If key items are not randomized, Contraption Key is guaranteed to be accessible before it is needed
- if self.multiworld.enable_key_locations[self.player] == Toggle.option_true:
- add_rule(self.multiworld.get_entrance("Go To Painted World of Ariandel 2", self.player),
- lambda state: state.has("Contraption Key", self.player))
+ if self.options.late_dlc:
+ self._add_entrance_rule(
+ "Painted World of Ariandel (Before Contraption)",
+ lambda state: state.has("Small Doll", self.player) and self._has_any_scroll(state))
- if self.multiworld.late_dlc[self.player] == Toggle.option_true:
- add_rule(self.multiworld.get_entrance("Go To Painted World of Ariandel 1", self.player),
- lambda state: state.has("Small Doll", self.player))
+ if self.options.late_dlc > 1: # After Basin
+ self._add_entrance_rule("Painted World of Ariandel (Before Contraption)", "Basin of Vows")
# Define the access rules to some specific locations
- set_rule(self.multiworld.get_location("PC: Cinders of a Lord - Yhorm the Giant", self.player),
- lambda state: state.has("Storm Ruler", self.player))
-
- if self.multiworld.enable_ring_locations[self.player] == Toggle.option_true:
- set_rule(self.multiworld.get_location("ID: Bellowing Dragoncrest Ring", self.player),
- lambda state: state.has("Jailbreaker's Key", self.player))
- set_rule(self.multiworld.get_location("ID: Covetous Gold Serpent Ring", self.player),
- lambda state: state.has("Old Cell Key", self.player))
- set_rule(self.multiworld.get_location("UG: Hornet Ring", self.player),
- lambda state: state.has("Small Lothric Banner", self.player))
-
- if self.multiworld.enable_npc_locations[self.player] == Toggle.option_true:
- set_rule(self.multiworld.get_location("HWL: Greirat's Ashes", self.player),
- lambda state: state.has("Cell Key", self.player))
- set_rule(self.multiworld.get_location("HWL: Blue Tearstone Ring", self.player),
- lambda state: state.has("Cell Key", self.player))
- set_rule(self.multiworld.get_location("ID: Karla's Ashes", self.player),
- lambda state: state.has("Jailer's Key Ring", self.player))
- set_rule(self.multiworld.get_location("ID: Karla's Pointed Hat", self.player),
- lambda state: state.has("Jailer's Key Ring", self.player))
- set_rule(self.multiworld.get_location("ID: Karla's Coat", self.player),
- lambda state: state.has("Jailer's Key Ring", self.player))
- set_rule(self.multiworld.get_location("ID: Karla's Gloves", self.player),
- lambda state: state.has("Jailer's Key Ring", self.player))
- set_rule(self.multiworld.get_location("ID: Karla's Trousers", self.player),
- lambda state: state.has("Jailer's Key Ring", self.player))
-
- if self.multiworld.enable_misc_locations[self.player] == Toggle.option_true:
- set_rule(self.multiworld.get_location("ID: Prisoner Chief's Ashes", self.player),
- lambda state: state.has("Jailer's Key Ring", self.player))
-
- if self.multiworld.enable_boss_locations[self.player] == Toggle.option_true:
- set_rule(self.multiworld.get_location("PC: Soul of Yhorm the Giant", self.player),
- lambda state: state.has("Storm Ruler", self.player))
- set_rule(self.multiworld.get_location("HWL: Soul of the Dancer", self.player),
- lambda state: state.has("Basin of Vows", self.player))
-
- # Lump Soul of the Dancer in with LC for locations that should not be reachable
- # before having access to US. (Prevents requiring getting Basin to fight Dancer to get SLB to go to US)
- if self.multiworld.late_basin_of_vows[self.player] == Toggle.option_true:
- add_rule(self.multiworld.get_location("HWL: Soul of the Dancer", self.player),
- lambda state: state.has("Small Lothric Banner", self.player))
-
- gotthard_corpse_rule = lambda state: \
- (state.can_reach("AL: Cinders of a Lord - Aldrich", "Location", self.player) and
- state.can_reach("PC: Cinders of a Lord - Yhorm the Giant", "Location", self.player))
-
- set_rule(self.multiworld.get_location("LC: Grand Archives Key", self.player), gotthard_corpse_rule)
-
- if self.multiworld.enable_weapon_locations[self.player] == Toggle.option_true:
- set_rule(self.multiworld.get_location("LC: Gotthard Twinswords", self.player), gotthard_corpse_rule)
-
- self.multiworld.completion_condition[self.player] = lambda state: \
- state.has("Cinders of a Lord - Abyss Watcher", self.player) and \
- state.has("Cinders of a Lord - Yhorm the Giant", self.player) and \
- state.has("Cinders of a Lord - Aldrich", self.player) and \
- state.has("Cinders of a Lord - Lothric Prince", self.player)
+ if self._is_location_available("FS: Lift Chamber Key - Leonhard"):
+ self._add_location_rule("HWL: Red Eye Orb - wall tower, miniboss",
+ "Lift Chamber Key")
+ self._add_location_rule("ID: Bellowing Dragoncrest Ring - drop from B1 towards pit",
+ "Jailbreaker's Key")
+ self._add_location_rule("ID: Covetous Gold Serpent Ring - Siegward's cell", "Old Cell Key")
+ self._add_location_rule([
+ "UG: Hornet Ring - environs, right of main path after killing FK boss",
+ "UG: Wolf Knight Helm - shop after killing FK boss",
+ "UG: Wolf Knight Armor - shop after killing FK boss",
+ "UG: Wolf Knight Gauntlets - shop after killing FK boss",
+ "UG: Wolf Knight Leggings - shop after killing FK boss"
+ ], lambda state: self._can_get(state, "FK: Cinders of a Lord - Abyss Watcher"))
+ self._add_location_rule(
+ "ID: Prisoner Chief's Ashes - B2 near, locked cell by stairs",
+ "Jailer's Key Ring"
+ )
+ self._add_entrance_rule("Karla's Shop", "Jailer's Key Ring")
+
+ # The static randomizer edits events to guarantee that Greirat won't go to Lothric until
+ # Grand Archives is available, so his shop will always be available one way or another.
+ self._add_entrance_rule("Greirat's Shop", "Cell Key")
+
+ self._add_location_rule("HWL: Soul of the Dancer", "Basin of Vows")
+
+ # Lump Soul of the Dancer in with LC for locations that should not be reachable
+ # before having access to US. (Prevents requiring getting Basin to fight Dancer to get SLB to go to US)
+ if self.options.late_basin_of_vows:
+ self._add_location_rule("HWL: Soul of the Dancer", lambda state: (
+ state.has("Small Lothric Banner", self.player)
+ # Make sure these are actually available early.
+ and (
+ "Transposing Kiln" not in randomized_items
+ or state.has("Transposing Kiln", self.player)
+ ) and (
+ "Pyromancy Flame" not in randomized_items
+ or state.has("Pyromancy Flame", self.player)
+ )
+ # This isn't really necessary, but it ensures that the game logic knows players will
+ # want to do Lothric Castle after at least being _able_ to access Catacombs. This is
+ # useful for smooth item placement.
+ and self._has_any_scroll(state)
+ ))
+
+ if self.options.late_basin_of_vows > 1: # After Small Doll
+ self._add_location_rule("HWL: Soul of the Dancer", "Small Doll")
+
+ self._add_location_rule([
+ "LC: Grand Archives Key - by Grand Archives door, after PC and AL bosses",
+ "LC: Gotthard Twinswords - by Grand Archives door, after PC and AL bosses"
+ ], lambda state: (
+ self._can_get(state, "AL: Cinders of a Lord - Aldrich") and
+ self._can_get(state, "PC: Cinders of a Lord - Yhorm the Giant")
+ ))
+
+ self._add_location_rule([
+ "FS: Morne's Great Hammer - Eygon",
+ "FS: Moaning Shield - Eygon"
+ ], lambda state: (
+ self._can_get(state, "LC: Soul of Dragonslayer Armour") and
+ self._can_get(state, "FK: Soul of the Blood of the Wolf")
+ ))
+
+ self._add_location_rule([
+ "CKG: Drakeblood Helm - tomb, after killing AP mausoleum NPC",
+ "CKG: Drakeblood Armor - tomb, after killing AP mausoleum NPC",
+ "CKG: Drakeblood Gauntlets - tomb, after killing AP mausoleum NPC",
+ "CKG: Drakeblood Leggings - tomb, after killing AP mausoleum NPC",
+ ], lambda state: self._can_go_to(state, "Archdragon Peak"))
+
+ self._add_location_rule([
+ "FK: Havel's Helm - upper keep, after killing AP belfry roof NPC",
+ "FK: Havel's Armor - upper keep, after killing AP belfry roof NPC",
+ "FK: Havel's Gauntlets - upper keep, after killing AP belfry roof NPC",
+ "FK: Havel's Leggings - upper keep, after killing AP belfry roof NPC",
+ ], lambda state: self._can_go_to(state, "Archdragon Peak"))
+
+ self._add_location_rule([
+ "RC: Dragonhead Shield - streets monument, across bridge",
+ "RC: Large Soul of a Crestfallen Knight - streets monument, across bridge",
+ "RC: Divine Blessing - streets monument, mob drop",
+ "RC: Lapp's Helm - Lapp",
+ "RC: Lapp's Armor - Lapp",
+ "RC: Lapp's Gauntlets - Lapp",
+ "RC: Lapp's Leggings - Lapp",
+ ], "Chameleon")
+
+ # Forbid shops from carrying items with multiple counts (the static randomizer has its own
+ # logic for choosing how many shop items to sell), and from carrying soul items.
+ for location in location_dictionary.values():
+ if location.shop:
+ self._add_item_rule(
+ location.name,
+ lambda item: (
+ item.player != self.player or
+ (item.data.count == 1 and not item.data.souls)
+ )
+ )
+
+ # This particular location is bugged, and will drop two copies of whatever item is placed
+ # there.
+ if self._is_location_available("US: Young White Branch - by white tree #2"):
+ self._add_item_rule(
+ "US: Young White Branch - by white tree #2",
+ lambda item: item.player == self.player and not item.data.unique
+ )
+
+ # Make sure the Storm Ruler is available BEFORE Yhorm the Giant
+ if self.yhorm_location.name == "Ancient Wyvern":
+ # This is a white lie, you can get to a bunch of items in AP before you beat the Wyvern,
+ # but this saves us from having to split the entire region in two just to mark which
+ # specific items are before and after.
+ self._add_entrance_rule("Archdragon Peak", "Storm Ruler")
+ for location in self.yhorm_location.locations:
+ self._add_location_rule(location, "Storm Ruler")
+
+ self.multiworld.completion_condition[self.player] = lambda state: self._can_get(state, "KFF: Soul of the Lords")
+
+ def _add_shop_rules(self) -> None:
+ """Adds rules for items unlocked in shops."""
+
+ # Ashes
+ ashes = {
+ "Mortician's Ashes": ["Alluring Skull", "Ember", "Grave Key"],
+ "Dreamchaser's Ashes": ["Life Ring", "Hidden Blessing"],
+ "Paladin's Ashes": ["Lloyd's Shield Ring"],
+ "Grave Warden's Ashes": ["Ember"],
+ "Prisoner Chief's Ashes": [
+ "Karla's Pointed Hat", "Karla's Coat", "Karla's Gloves", "Karla's Trousers"
+ ],
+ "Xanthous Ashes": ["Xanthous Overcoat", "Xanthous Gloves", "Xanthous Trousers"],
+ "Dragon Chaser's Ashes": ["Ember"],
+ "Easterner's Ashes": [
+ "Washing Pole", "Eastern Helm", "Eastern Armor", "Eastern Gauntlets",
+ "Eastern Leggings", "Wood Grain Ring",
+ ],
+ "Captain's Ashes": [
+ "Millwood Knight Helm", "Millwood Knight Armor", "Millwood Knight Gauntlets",
+ "Millwood Knight Leggings", "Refined Gem",
+ ]
+ }
+ for (ash, items) in ashes.items():
+ self._add_location_rule([f"FS: {item} - {ash}" for item in items], ash)
+
+ # Shop unlocks
+ shop_unlocks = {
+ "Cornyx": [
+ (
+ "Great Swamp Pyromancy Tome", "Great Swamp Tome",
+ ["Poison Mist", "Fire Orb", "Profuse Sweat", "Bursting Fireball"]
+ ),
+ (
+ "Carthus Pyromancy Tome", "Carthus Tome",
+ ["Acid Surge", "Carthus Flame Arc", "Carthus Beacon"]
+ ),
+ ("Izalith Pyromancy Tome", "Izalith Tome", ["Great Chaos Fire Orb", "Chaos Storm"]),
+ ],
+ "Irina": [
+ (
+ "Braille Divine Tome of Carim", "Tome of Carim",
+ ["Med Heal", "Tears of Denial", "Force"]
+ ),
+ (
+ "Braille Divine Tome of Lothric", "Tome of Lothric",
+ ["Bountiful Light", "Magic Barrier", "Blessed Weapon"]
+ ),
+ ],
+ "Orbeck": [
+ ("Sage's Scroll", "Sage's Scroll", ["Great Farron Dart", "Farron Hail"]),
+ (
+ "Golden Scroll", "Golden Scroll",
+ [
+ "Cast Light", "Repair", "Hidden Weapon", "Hidden Body",
+ "Twisted Wall of Light"
+ ],
+ ),
+ ("Logan's Scroll", "Logan's Scroll", ["Homing Soulmass", "Soul Spear"]),
+ (
+ "Crystal Scroll", "Crystal Scroll",
+ ["Homing Crystal Soulmass", "Crystal Soul Spear", "Crystal Magic Weapon"]
+ ),
+ ],
+ "Karla": [
+ ("Quelana Pyromancy Tome", "Quelana Tome", ["Firestorm", "Rapport", "Fire Whip"]),
+ (
+ "Grave Warden Pyromancy Tome", "Grave Warden Tome",
+ ["Black Flame", "Black Fire Orb"]
+ ),
+ ("Deep Braille Divine Tome", "Deep Braille Tome", ["Gnaw", "Deep Protection"]),
+ (
+ "Londor Braille Divine Tome", "Londor Tome",
+ ["Vow of Silence", "Dark Blade", "Dead Again"]
+ ),
+ ],
+ }
+ for (shop, unlocks) in shop_unlocks.items():
+ for (key, key_name, items) in unlocks:
+ self._add_location_rule(
+ [f"FS: {item} - {shop} for {key_name}" for item in items], key)
+
+ def _add_npc_rules(self) -> None:
+ """Adds rules for items accessible via NPC quests.
+
+ We list missable locations here even though they never contain progression items so that the
+ game knows what sphere they're in. This is especially useful for item smoothing. (We could
+ add rules for boss transposition items as well, but then we couldn't freely reorder boss
+ soul locations for smoothing.)
+
+ Generally, for locations that can be accessed early by killing NPCs, we set up requirements
+ assuming the player _doesn't_ so they aren't forced to start killing allies to advance the
+ quest.
+ """
+
+ ## Greirat
+
+ self._add_location_rule([
+ "FS: Divine Blessing - Greirat from US",
+ "FS: Ember - Greirat from US",
+ ], lambda state: (
+ self._can_go_to(state, "Undead Settlement")
+ and state.has("Loretta's Bone", self.player)
+ ))
+ self._add_location_rule([
+ "FS: Divine Blessing - Greirat from IBV",
+ "FS: Hidden Blessing - Greirat from IBV",
+ "FS: Titanite Scale - Greirat from IBV",
+ "FS: Twinkling Titanite - Greirat from IBV",
+ "FS: Ember - shop for Greirat's Ashes"
+ ], lambda state: (
+ self._can_go_to(state, "Irithyll of the Boreal Valley")
+ and self._can_get(state, "FS: Divine Blessing - Greirat from US")
+ # Either Patches or Siegward can save Greirat, but we assume the player will want to use
+ # Patches because it's harder to screw up
+ and self._can_get(state, "CD: Shotel - Patches")
+ ))
+ self._add_location_rule([
+ "FS: Ember - shop for Greirat's Ashes",
+ ], lambda state: (
+ self._can_go_to(state, "Grand Archives")
+ and self._can_get(state, "FS: Divine Blessing - Greirat from IBV")
+ ))
+
+ ## Patches
+
+ # Patches will only set up shop in Firelink once he's tricked you in the bell tower. He'll
+ # only do _that_ once you've spoken to Siegward after killing the Fire Demon and lit the
+ # Rosaria's Bed Chamber bonfire. He _won't_ set up shop in the Cathedral if you light the
+ # Rosaria's Bed Chamber bonfire before getting tricked by him, so we assume these locations
+ # require the bell tower.
+ self._add_location_rule([
+ "CD: Shotel - Patches",
+ "CD: Ember - Patches",
+ "FS: Rusted Gold Coin - don't forgive Patches"
+ ], lambda state: (
+ self._can_go_to(state, "Firelink Shrine Bell Tower")
+ and self._can_go_to(state, "Cathedral of the Deep")
+ ))
+
+ # Patches sells this after you tell him to search for Greirat in Grand Archives
+ self._add_location_rule([
+ "FS: Hidden Blessing - Patches after searching GA"
+ ], lambda state: (
+ self._can_get(state, "CD: Shotel - Patches")
+ and self._can_get(state, "FS: Ember - shop for Greirat's Ashes")
+ ))
+
+ # Only make the player kill Patches once all his other items are available
+ self._add_location_rule([
+ "CD: Winged Spear - kill Patches",
+ # You don't _have_ to kill him for this, but he has to be in Firelink at the same time
+ # as Greirat to get it in the shop and that may not be feasible if the player progresses
+ # Greirat's quest much faster.
+ "CD: Horsehoof Ring - Patches",
+ ], lambda state: (
+ self._can_get(state, "FS: Hidden Blessing - Patches after searching GA")
+ and self._can_get(state, "FS: Rusted Gold Coin - don't forgive Patches")
+ ))
+
+ ## Leonhard
+
+ self._add_location_rule([
+ # Talk to Leonhard in Firelink with a Pale Tongue after lighting Cliff Underside or
+ # killing Greatwood. This doesn't consume the Pale Tongue, it just has to be in
+ # inventory
+ "FS: Lift Chamber Key - Leonhard",
+ # Progress Leonhard's quest and then return to Rosaria after lighting Profaned Capital
+ "CD: Black Eye Orb - Rosaria from Leonhard's quest",
+ ], "Pale Tongue")
+
+ self._add_location_rule([
+ "CD: Black Eye Orb - Rosaria from Leonhard's quest",
+ ], lambda state: (
+ # The Black Eye Orb location won't spawn until you kill the HWL miniboss and resting at
+ # the Profaned Capital bonfire.
+ self._can_get(state, "HWL: Red Eye Orb - wall tower, miniboss")
+ and self._can_go_to(state, "Profaned Capital")
+ ))
+
+ # Perhaps counterintuitively, you CAN fight Leonhard before you access the location that
+ # would normally give you the Black Eye Orb.
+ self._add_location_rule([
+ "AL: Crescent Moon Sword - Leonhard drop",
+ "AL: Silver Mask - Leonhard drop",
+ "AL: Soul of Rosaria - Leonhard drop",
+ ] + [
+ f"FS: {item} - shop after killing Leonhard"
+ for item in ["Leonhard's Garb", "Leonhard's Gauntlets", "Leonhard's Trousers"]
+ ], "Black Eye Orb")
+
+ ## Hawkwood
+
+ # After Hawkwood leaves and once you have the Torso Stone, you can fight him for dragon
+ # stones. Andre will give Swordgrass as a hint as well
+ self._add_location_rule([
+ "FK: Twinkling Dragon Head Stone - Hawkwood drop",
+ "FS: Hawkwood's Swordgrass - Andre after gesture in AP summit"
+ ], lambda state: (
+ self._can_get(state, "FS: Hawkwood's Shield - gravestone after Hawkwood leaves")
+ and state.has("Twinkling Dragon Torso Stone", self.player)
+ ))
+
+ ## Siegward
+
+ # Unlock Siegward's cell after progressing his quest
+ self._add_location_rule([
+ "ID: Titanite Slab - Siegward",
+ ], lambda state: (
+ state.has("Old Cell Key", self.player)
+ # Progressing Siegward's quest requires buying his armor from Patches.
+ and self._can_get(state, "CD: Shotel - Patches")
+ ))
+
+ # These drop after completing Siegward's quest and talking to him in Yhorm's arena
+ self._add_location_rule([
+ "PC: Siegbräu - Siegward after killing boss",
+ "PC: Storm Ruler - Siegward",
+ "PC: Pierce Shield - Siegward",
+ ], lambda state: (
+ self._can_get(state, "ID: Titanite Slab - Siegward")
+ and self._can_get(state, "PC: Soul of Yhorm the Giant")
+ ))
+
+ ## Sirris
+
+ # Kill Greatwood and turn in Dreamchaser's Ashes to trigger this opportunity for invasion
+ self._add_location_rule([
+ "FS: Mail Breaker - Sirris for killing Creighton",
+ "FS: Silvercat Ring - Sirris for killing Creighton",
+ "IBV: Creighton's Steel Mask - bridge after killing Creighton",
+ "IBV: Mirrah Chain Gloves - bridge after killing Creighton",
+ "IBV: Mirrah Chain Leggings - bridge after killing Creighton",
+ "IBV: Mirrah Chain Mail - bridge after killing Creighton",
+ "IBV: Dragonslayer's Axe - Creighton drop",
+ # Killing Pontiff without progressing Sirris's quest will break it.
+ "IBV: Soul of Pontiff Sulyvahn"
+ ], lambda state: (
+ self._can_get(state, "US: Soul of the Rotted Greatwood")
+ and state.has("Dreamchaser's Ashes", self.player)
+ ))
+ # Add indirect condition since reaching AL requires defeating Pontiff which requires defeating Greatwood in US
+ self.multiworld.register_indirect_condition(
+ self.get_region("Undead Settlement"),
+ self.get_entrance("Go To Anor Londo")
+ )
+
+ # Kill Creighton and Aldrich to trigger this opportunity for invasion
+ self._add_location_rule([
+ "FS: Budding Green Blossom - shop after killing Creighton and AL boss",
+ "FS: Sunset Shield - by grave after killing Hodrick w/Sirris",
+ "US: Sunset Helm - Pit of Hollows after killing Hodrick w/Sirris",
+ "US: Sunset Armor - pit of hollows after killing Hodrick w/Sirris",
+ "US: Sunset Gauntlets - pit of hollows after killing Hodrick w/Sirris",
+ "US: Sunset Leggings - pit of hollows after killing Hodrick w/Sirris",
+ ], lambda state: (
+ self._can_get(state, "FS: Mail Breaker - Sirris for killing Creighton")
+ and self._can_get(state, "AL: Soul of Aldrich")
+ ))
+
+ # Kill Hodrick and Twin Princes to trigger the end of the quest
+ self._add_location_rule([
+ "FS: Sunless Talisman - Sirris, kill GA boss",
+ "FS: Sunless Veil - shop, Sirris quest, kill GA boss",
+ "FS: Sunless Armor - shop, Sirris quest, kill GA boss",
+ "FS: Sunless Gauntlets - shop, Sirris quest, kill GA boss",
+ "FS: Sunless Leggings - shop, Sirris quest, kill GA boss",
+ # Killing Yorshka will anger Sirris and stop her quest, so don't expect it until the
+ # quest is done
+ "AL: Yorshka's Chime - kill Yorshka",
+ ], lambda state: (
+ self._can_get(state, "US: Soul of the Rotted Greatwood")
+ and state.has("Dreamchaser's Ashes", self.player)
+ ))
+
+ ## Cornyx
+
+ self._add_location_rule([
+ "US: Old Sage's Blindfold - kill Cornyx",
+ "US: Cornyx's Garb - kill Cornyx",
+ "US: Cornyx's Wrap - kill Cornyx",
+ "US: Cornyx's Skirt - kill Cornyx",
+ ], lambda state: (
+ state.has("Great Swamp Pyromancy Tome", self.player)
+ and state.has("Carthus Pyromancy Tome", self.player)
+ and state.has("Izalith Pyromancy Tome", self.player)
+ ))
+
+ self._add_location_rule([
+ "US: Old Sage's Blindfold - kill Cornyx", "US: Cornyx's Garb - kill Cornyx",
+ "US: Cornyx's Wrap - kill Cornyx", "US: Cornyx's Skirt - kill Cornyx"
+ ], lambda state: (
+ state.has("Great Swamp Pyromancy Tome", self.player)
+ and state.has("Carthus Pyromancy Tome", self.player)
+ and state.has("Izalith Pyromancy Tome", self.player)
+ ))
+
+ ## Irina
+
+ self._add_location_rule([
+ "US: Tower Key - kill Irina",
+ ], lambda state: (
+ state.has("Braille Divine Tome of Carim", self.player)
+ and state.has("Braille Divine Tome of Lothric", self.player)
+ ))
+
+ ## Karla
+
+ self._add_location_rule([
+ "FS: Karla's Pointed Hat - kill Karla",
+ "FS: Karla's Coat - kill Karla",
+ "FS: Karla's Gloves - kill Karla",
+ "FS: Karla's Trousers - kill Karla",
+ ], lambda state: (
+ state.has("Quelana Pyromancy Tome", self.player)
+ and state.has("Grave Warden Pyromancy Tome", self.player)
+ and state.has("Deep Braille Divine Tome", self.player)
+ and state.has("Londor Braille Divine Tome", self.player)
+ ))
+
+ ## Emma
+
+ self._add_location_rule("HWL: Basin of Vows - Emma", "Small Doll")
+
+ ## Orbeck
+
+ self._add_location_rule([
+ "FS: Morion Blade - Yuria for Orbeck's Ashes",
+ "FS: Clandestine Coat - shop with Orbeck's Ashes"
+ ], lambda state: (
+ state.has("Golden Scroll", self.player)
+ and state.has("Logan's Scroll", self.player)
+ and state.has("Crystal Scroll", self.player)
+ and state.has("Sage's Scroll", self.player)
+ ))
+
+ self._add_location_rule([
+ "FS: Pestilent Mist - Orbeck for any scroll",
+ "FS: Young Dragon Ring - Orbeck for one scroll and buying three spells",
+ # Make sure that the player can keep Orbeck around by giving him at least one scroll
+ # before killing Abyss Watchers.
+ "FK: Soul of the Blood of the Wolf",
+ "FK: Cinders of a Lord - Abyss Watcher",
+ "FS: Undead Legion Helm - shop after killing FK boss",
+ "FS: Undead Legion Armor - shop after killing FK boss",
+ "FS: Undead Legion Gauntlet - shop after killing FK boss",
+ "FS: Undead Legion Leggings - shop after killing FK boss",
+ "FS: Farron Ring - Hawkwood",
+ "FS: Hawkwood's Shield - gravestone after Hawkwood leaves",
+ "UG: Hornet Ring - environs, right of main path after killing FK boss",
+ "UG: Wolf Knight Helm - shop after killing FK boss",
+ "UG: Wolf Knight Armor - shop after killing FK boss",
+ "UG: Wolf Knight Gauntlets - shop after killing FK boss",
+ "UG: Wolf Knight Leggings - shop after killing FK boss",
+ ], self._has_any_scroll)
+
+ # Not really necessary but ensures players can decide which way to go
+ if self.options.enable_dlc:
+ self._add_entrance_rule(
+ "Painted World of Ariandel (After Contraption)",
+ self._has_any_scroll
+ )
+
+ ## Anri
+
+ # Anri only leaves Road of Sacrifices once Deacons is defeated
+ self._add_location_rule([
+ "IBV: Ring of the Evil Eye - Anri",
+ "AL: Chameleon - tomb after marrying Anri",
+ ], lambda state: self._can_get(state, "CD: Soul of the Deacons of the Deep"))
+
+ # If the player does Anri's non-marriage quest, they'll need to defeat the AL boss as well
+ # before it's complete.
+ self._add_location_rule([
+ "AL: Anri's Straight Sword - Anri quest",
+ "FS: Elite Knight Helm - shop after Anri quest",
+ "FS: Elite Knight Armor - shop after Anri quest",
+ "FS: Elite Knight Gauntlets - shop after Anri quest",
+ "FS: Elite Knight Leggings - shop after Anri quest",
+ ], lambda state: (
+ self._can_get(state, "IBV: Ring of the Evil Eye - Anri") and
+ self._can_get(state, "AL: Soul of Aldrich")
+ ))
+
+ def _add_transposition_rules(self) -> None:
+ """Adds rules for items obtainable from Ludleth by soul transposition."""
+
+ transpositions = [
+ (
+ "Soul of Boreal Valley Vordt", "Vordt",
+ ["Vordt's Great Hammer", "Pontiff's Left Eye"]
+ ),
+ ("Soul of Rosaria", "Rosaria", ["Bountiful Sunlight"]),
+ ("Soul of Aldrich", "Aldrich", ["Darkmoon Longbow", "Lifehunt Scythe"]),
+ (
+ "Soul of the Rotted Greatwood", "Greatwood",
+ ["Hollowslayer Greatsword", "Arstor's Spear"]
+ ),
+ ("Soul of a Crystal Sage", "Sage", ["Crystal Sage's Rapier", "Crystal Hail"]),
+ ("Soul of the Deacons of the Deep", "Deacons", ["Cleric's Candlestick", "Deep Soul"]),
+ ("Soul of a Stray Demon", "Stray Demon", ["Havel's Ring", "Boulder Heave"]),
+ (
+ "Soul of the Blood of the Wolf", "Abyss Watchers",
+ ["Farron Greatsword", "Wolf Knight's Greatsword"]
+ ),
+ ("Soul of High Lord Wolnir", "Wolnir", ["Wolnir's Holy Sword", "Black Serpent"]),
+ ("Soul of a Demon", "Fire Demon", ["Demon's Greataxe", "Demon's Fist"]),
+ (
+ "Soul of the Old Demon King", "Old Demon King",
+ ["Old King's Great Hammer", "Chaos Bed Vestiges"]
+ ),
+ (
+ "Soul of Pontiff Sulyvahn", "Pontiff",
+ ["Greatsword of Judgment", "Profaned Greatsword"]
+ ),
+ ("Soul of Yhorm the Giant", "Yhorm", ["Yhorm's Great Machete", "Yhorm's Greatshield"]),
+ ("Soul of the Dancer", "Dancer", ["Dancer's Enchanted Swords", "Soothing Sunlight"]),
+ (
+ "Soul of Dragonslayer Armour", "Dragonslayer",
+ ["Dragonslayer Greataxe", "Dragonslayer Greatshield"]
+ ),
+ (
+ "Soul of Consumed Oceiros", "Oceiros",
+ ["Moonlight Greatsword", "White Dragon Breath"]
+ ),
+ (
+ "Soul of the Twin Princes", "Princes",
+ ["Lorian's Greatsword", "Lothric's Holy Sword"]
+ ),
+ ("Soul of Champion Gundyr", "Champion", ["Gundyr's Halberd", "Prisoner's Chain"]),
+ (
+ "Soul of the Nameless King", "Nameless",
+ ["Storm Curved Sword", "Dragonslayer Swordspear", "Lightning Storm"]
+ ),
+ ("Soul of the Lords", "Cinder", ["Firelink Greatsword", "Sunlight Spear"]),
+ ("Soul of Sister Friede", "Friede", ["Friede's Great Scythe", "Rose of Ariandel"]),
+ ("Soul of the Demon Prince", "Demon Prince", ["Demon's Scar", "Seething Chaos"]),
+ ("Soul of Darkeater Midir", "Midir", ["Frayed Blade", "Old Moonlight"]),
+ ("Soul of Slave Knight Gael", "Gael", ["Gael's Greatsword", "Repeating Crossbow"]),
+ ]
+ for (soul, soul_name, items) in transpositions:
+ self._add_location_rule([
+ f"FS: {item} - Ludleth for {soul_name}" for item in items
+ ], lambda state, s=soul: (
+ state.has(s, self.player) and state.has("Transposing Kiln", self.player)
+ ))
+
+ def _add_crow_rules(self) -> None:
+ """Adds rules for items obtainable by trading items to the crow on Firelink roof."""
+
+ crow = {
+ "Loretta's Bone": "Ring of Sacrifice",
+ # "Avelyn": "Titanite Scale", # Missing from static randomizer
+ "Coiled Sword Fragment": "Titanite Slab",
+ "Seed of a Giant Tree": "Iron Leggings",
+ "Siegbräu": "Armor of the Sun",
+ # Static randomizer can't randomize Hodrick's drop yet
+ # "Vertebra Shackle": "Lucatiel's Mask",
+ "Xanthous Crown": "Lightning Gem",
+ "Mendicant's Staff": "Sunlight Shield",
+ "Blacksmith Hammer": "Titanite Scale",
+ "Large Leather Shield": "Twinkling Titanite",
+ "Moaning Shield": "Blessed Gem",
+ "Eleonora": "Hollow Gem",
+ }
+ for (given, received) in crow.items():
+ name = f"FSBT: {received} - crow for {given}"
+ self._add_location_rule(name, given)
+
+ # Don't let crow items have foreign items because they're picked up in a way that's
+ # missed by the hook we use to send location items
+ self._add_item_rule(name, lambda item: (
+ item.player == self.player
+ # Because of the weird way they're delivered, crow items don't seem to support
+ # infused or upgraded weapons.
+ and not item.data.is_infused
+ and not item.data.is_upgraded
+ ))
+
+ def _add_allow_useful_location_rules(self) -> None:
+ """Adds rules for locations that can contain useful but not necessary items.
+
+ If we allow useful items in the excluded locations, we don't want Archipelago's fill
+ algorithm to consider them excluded because it never allows useful items there. Instead, we
+ manually add item rules to exclude important items.
+ """
+
+ all_locations = self._get_our_locations()
+
+ allow_useful_locations = (
+ (
+ {
+ location.name
+ for location in all_locations
+ if location.name in self.all_excluded_locations
+ and not location.data.missable
+ }
+ if self.options.excluded_location_behavior < self.options.missable_location_behavior
+ else self.all_excluded_locations
+ )
+ if self.options.excluded_location_behavior == "allow_useful"
+ else set()
+ ).union(
+ {
+ location.name
+ for location in all_locations
+ if location.data.missable
+ and not (
+ location.name in self.all_excluded_locations
+ and self.options.missable_location_behavior <
+ self.options.excluded_location_behavior
+ )
+ }
+ if self.options.missable_location_behavior == "allow_useful"
+ else set()
+ )
+ for location in allow_useful_locations:
+ self._add_item_rule(
+ location,
+ lambda item: not item.advancement
+ )
+
+ if self.options.excluded_location_behavior == "allow_useful":
+ self.options.exclude_locations.value.clear()
+
+ def _add_early_item_rules(self, randomized_items: Set[str]) -> None:
+ """Adds rules to make sure specific items are available early."""
+
+ if "Pyromancy Flame" in randomized_items:
+ # Make this available early because so many items are useless without it.
+ self._add_entrance_rule("Road of Sacrifices", "Pyromancy Flame")
+ self._add_entrance_rule("Consumed King's Garden", "Pyromancy Flame")
+ self._add_entrance_rule("Grand Archives", "Pyromancy Flame")
+ if "Transposing Kiln" in randomized_items:
+ # Make this available early so players can make use of their boss souls.
+ self._add_entrance_rule("Road of Sacrifices", "Transposing Kiln")
+ self._add_entrance_rule("Consumed King's Garden", "Transposing Kiln")
+ self._add_entrance_rule("Grand Archives", "Transposing Kiln")
+ # Make this available pretty early
+ if "Small Lothric Banner" in randomized_items:
+ if self.options.early_banner == "early_global":
+ self.multiworld.early_items[self.player]["Small Lothric Banner"] = 1
+ elif self.options.early_banner == "early_local":
+ self.multiworld.local_early_items[self.player]["Small Lothric Banner"] = 1
+
+ def _has_any_scroll(self, state: CollectionState) -> bool:
+ """Returns whether the given state has any scroll item."""
+ return (
+ state.has("Sage's Scroll", self.player)
+ or state.has("Golden Scroll", self.player)
+ or state.has("Logan's Scroll", self.player)
+ or state.has("Crystal Scroll", self.player)
+ )
+
+ def _add_location_rule(self, location: Union[str, List[str]], rule: Union[CollectionRule, str]) -> None:
+ """Sets a rule for the given location if it that location is randomized.
+
+ The rule can just be a single item/event name as well as an explicit rule lambda.
+ """
+ locations = location if isinstance(location, list) else [location]
+ for location in locations:
+ data = location_dictionary[location]
+ if data.dlc and not self.options.enable_dlc: return
+ if data.ngp and not self.options.enable_ngp: return
+
+ if not self._is_location_available(location): return
+ if isinstance(rule, str):
+ assert item_dictionary[rule].classification == ItemClassification.progression
+ rule = lambda state, item=rule: state.has(item, self.player)
+ add_rule(self.multiworld.get_location(location, self.player), rule)
+
+ def _add_entrance_rule(self, region: str, rule: Union[CollectionRule, str]) -> None:
+ """Sets a rule for the entrance to the given region."""
+ assert region in location_tables
+ if not any(region == reg for reg in self.multiworld.regions.region_cache[self.player]): return
+ if isinstance(rule, str):
+ if " -> " not in rule:
+ assert item_dictionary[rule].classification == ItemClassification.progression
+ rule = lambda state, item=rule: state.has(item, self.player)
+ add_rule(self.multiworld.get_entrance("Go To " + region, self.player), rule)
+
+ def _add_item_rule(self, location: str, rule: ItemRule) -> None:
+ """Sets a rule for what items are allowed in a given location."""
+ if not self._is_location_available(location): return
+ add_item_rule(self.multiworld.get_location(location, self.player), rule)
+
+ def _can_go_to(self, state, region) -> bool:
+ """Returns whether state can access the given region name."""
+ return state.can_reach_entrance(f"Go To {region}", self.player)
+
+ def _can_get(self, state, location) -> bool:
+ """Returns whether state can access the given location name."""
+ return state.can_reach_location(location, self.player)
+
+ def _is_location_available(
+ self,
+ location: Union[str, DS3LocationData, DarkSouls3Location]
+ ) -> bool:
+ """Returns whether the given location is being randomized."""
+ if isinstance(location, DS3LocationData):
+ data = location
+ elif isinstance(location, DarkSouls3Location):
+ data = location.data
+ else:
+ data = location_dictionary[location]
+
+ return (
+ not data.is_event
+ and (not data.dlc or bool(self.options.enable_dlc))
+ and (not data.ngp or bool(self.options.enable_ngp))
+ and not (
+ self.options.excluded_location_behavior == "do_not_randomize"
+ and data.name in self.all_excluded_locations
+ )
+ and not (
+ self.options.missable_location_behavior == "do_not_randomize"
+ and data.missable
+ )
+ )
+
+ def write_spoiler(self, spoiler_handle: TextIO) -> None:
+ text = ""
+
+ if self.yhorm_location != default_yhorm_location:
+ text += f"\nYhorm takes the place of {self.yhorm_location.name} in {self.player_name}'s world\n"
+
+ if self.options.excluded_location_behavior == "allow_useful":
+ text += f"\n{self.player_name}'s world excluded: {sorted(self.all_excluded_locations)}\n"
+
+ if text:
+ text = "\n" + text + "\n"
+ spoiler_handle.write(text)
+
+ def post_fill(self):
+ """If item smoothing is enabled, rearrange items so they scale up smoothly through the run.
+
+ This determines the approximate order a given silo of items (say, soul items) show up in the
+ main game, then rearranges their shuffled placements to match that order. It determines what
+ should come "earlier" or "later" based on sphere order: earlier spheres get lower-level
+ items, later spheres get higher-level ones. Within a sphere, items in DS3 are distributed in
+ region order, and then the best items in a sphere go into the multiworld.
+ """
+
+ locations_by_sphere = [
+ sorted(loc for loc in sphere if loc.item.player == self.player and not loc.locked)
+ for sphere in self.multiworld.get_spheres()
+ ]
+
+ # All items in the base game in approximately the order they appear
+ all_item_order: List[DS3ItemData] = [
+ item_dictionary[location.default_item_name]
+ for region in region_order
+ # Shuffle locations within each region.
+ for location in self._shuffle(location_tables[region])
+ if self._is_location_available(location)
+ ]
+
+ # All DarkSouls3Items for this world that have been assigned anywhere, grouped by name
+ full_items_by_name: Dict[str, List[DarkSouls3Item]] = defaultdict(list)
+ for location in self.multiworld.get_filled_locations():
+ if location.item.player == self.player and (
+ location.player != self.player or self._is_location_available(location)
+ ):
+ full_items_by_name[location.item.name].append(location.item)
+
+ def smooth_items(item_order: List[Union[DS3ItemData, DarkSouls3Item]]) -> None:
+ """Rearrange all items in item_order to match that order.
+
+ Note: this requires that item_order exactly matches the number of placed items from this
+ world matching the given names.
+ """
+
+ # Convert items to full DarkSouls3Items.
+ converted_item_order: List[DarkSouls3Item] = [
+ item for item in (
+ (
+ # full_items_by_name won't contain DLC items if the DLC is disabled.
+ (full_items_by_name[item.name] or [None]).pop(0)
+ if isinstance(item, DS3ItemData) else item
+ )
+ for item in item_order
+ )
+ # Never re-order event items, because they weren't randomized in the first place.
+ if item and item.code is not None
+ ]
+
+ names = {item.name for item in converted_item_order}
+
+ all_matching_locations = [
+ loc
+ for sphere in locations_by_sphere
+ for loc in sphere
+ if loc.item.name in names
+ ]
+
+ # It's expected that there may be more total items than there are matching locations if
+ # the player has chosen a more limited accessibility option, since the matching
+ # locations *only* include items in the spheres of accessibility.
+ if len(converted_item_order) < len(all_matching_locations):
+ raise Exception(
+ f"DS3 bug: there are {len(all_matching_locations)} locations that can " +
+ f"contain smoothed items, but only {len(converted_item_order)} items to smooth."
+ )
+ for sphere in locations_by_sphere:
+ locations = [loc for loc in sphere if loc.item.name in names]
+
+ # Check the game, not the player, because we know how to sort within regions for DS3
+ offworld = self._shuffle([loc for loc in locations if loc.game != "Dark Souls III"])
+ onworld = sorted((loc for loc in locations if loc.game == "Dark Souls III"),
+ key=lambda loc: loc.data.region_value)
+
+ # Give offworld regions the last (best) items within a given sphere
+ for location in onworld + offworld:
+ new_item = self._pop_item(location, converted_item_order)
+ location.item = new_item
+ new_item.location = location
+
+ if self.options.smooth_upgrade_items:
+ base_names = {
+ "Titanite Shard", "Large Titanite Shard", "Titanite Chunk", "Titanite Slab",
+ "Titanite Scale", "Twinkling Titanite", "Farron Coal", "Sage's Coal", "Giant's Coal",
+ "Profaned Coal"
+ }
+ smooth_items([item for item in all_item_order if item.base_name in base_names])
+
+ if self.options.smooth_soul_items:
+ smooth_items([
+ item for item in all_item_order
+ if item.souls and item.classification != ItemClassification.progression
+ ])
+
+ if self.options.smooth_upgraded_weapons:
+ upgraded_weapons = [
+ location.item
+ for location in self.multiworld.get_filled_locations()
+ if location.item.player == self.player
+ and location.item.level and location.item.level > 0
+ and location.item.classification != ItemClassification.progression
+ ]
+ upgraded_weapons.sort(key=lambda item: item.level)
+ smooth_items(upgraded_weapons)
+
+ def _shuffle(self, seq: Sequence) -> List:
+ """Returns a shuffled copy of a sequence."""
+ copy = list(seq)
+ self.random.shuffle(copy)
+ return copy
+
+ def _pop_item(
+ self,
+ location: Location,
+ items: List[DarkSouls3Item]
+ ) -> DarkSouls3Item:
+ """Returns the next item in items that can be assigned to location."""
+ for i, item in enumerate(items):
+ if location.can_fill(self.multiworld.state, item, False):
+ return items.pop(i)
+
+ # If we can't find a suitable item, give up and assign an unsuitable one.
+ return items.pop(0)
+
+ def _get_our_locations(self) -> List[DarkSouls3Location]:
+ return cast(List[DarkSouls3Location], self.multiworld.get_locations(self.player))
def fill_slot_data(self) -> Dict[str, object]:
slot_data: Dict[str, object] = {}
- # Depending on the specified option, modify items hexadecimal value to add an upgrade level or infusion
- name_to_ds3_code = {item.name: item.ds3_code for item in item_dictionary.values()}
-
- # Randomize some weapon upgrades
- if self.multiworld.randomize_weapon_level[self.player] != RandomizeWeaponLevelOption.option_none:
- # if the user made an error and set a min higher than the max we default to the max
- max_5 = self.multiworld.max_levels_in_5[self.player]
- min_5 = min(self.multiworld.min_levels_in_5[self.player], max_5)
- max_10 = self.multiworld.max_levels_in_10[self.player]
- min_10 = min(self.multiworld.min_levels_in_10[self.player], max_10)
- weapon_level_percentage = self.multiworld.randomize_weapon_level_percentage[self.player]
-
- for item in item_dictionary.values():
- if self.multiworld.per_slot_randoms[self.player].randint(0, 99) < weapon_level_percentage:
- if item.category == DS3ItemCategory.WEAPON_UPGRADE_5:
- name_to_ds3_code[item.name] += self.multiworld.per_slot_randoms[self.player].randint(min_5, max_5)
- elif item.category in {DS3ItemCategory.WEAPON_UPGRADE_10, DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE}:
- name_to_ds3_code[item.name] += self.multiworld.per_slot_randoms[self.player].randint(min_10, max_10)
-
- # Randomize some weapon infusions
- if self.multiworld.randomize_infusion[self.player] == Toggle.option_true:
- infusion_percentage = self.multiworld.randomize_infusion_percentage[self.player]
- for item in item_dictionary.values():
- if item.category in {DS3ItemCategory.WEAPON_UPGRADE_10_INFUSIBLE, DS3ItemCategory.SHIELD_INFUSIBLE}:
- if self.multiworld.per_slot_randoms[self.player].randint(0, 99) < infusion_percentage:
- name_to_ds3_code[item.name] += 100 * self.multiworld.per_slot_randoms[self.player].randint(0, 15)
-
- # Create the mandatory lists to generate the player's output file
- items_id = []
- items_address = []
- locations_id = []
- locations_address = []
- locations_target = []
- for location in self.multiworld.get_filled_locations():
- # Skip events
- if location.item.code is None:
- continue
-
- if location.item.player == self.player:
- items_id.append(location.item.code)
- items_address.append(name_to_ds3_code[location.item.name])
-
- if location.player == self.player:
- locations_address.append(item_dictionary[location_dictionary[location.name].default_item].ds3_code)
- locations_id.append(location.address)
- if location.item.player == self.player:
- locations_target.append(name_to_ds3_code[location.item.name])
- else:
- locations_target.append(0)
+ # Once all clients support overlapping item IDs, adjust the DS3 AP item IDs to encode the
+ # in-game ID as well as the count so that we don't need to send this information at all.
+ #
+ # We include all the items the game knows about so that users can manually request items
+ # that aren't randomized, and then we _also_ include all the items that are placed in
+ # practice `item_dictionary.values()` doesn't include upgraded or infused weapons.
+ all_items = {
+ cast(DarkSouls3Item, location.item).data
+ for location in self.multiworld.get_filled_locations()
+ # item.code None is used for events, which we want to skip
+ if location.item.code is not None and location.item.player == self.player
+ }.union(item_dictionary.values())
+
+ ap_ids_to_ds3_ids: Dict[str, int] = {}
+ item_counts: Dict[str, int] = {}
+ for item in all_items:
+ if item.ap_code is None: continue
+ if item.ds3_code: ap_ids_to_ds3_ids[str(item.ap_code)] = item.ds3_code
+ if item.count != 1: item_counts[str(item.ap_code)] = item.count
+
+ # A map from Archipelago's location IDs to the keys the static randomizer uses to identify
+ # locations.
+ location_ids_to_keys: Dict[int, str] = {}
+ for location in cast(List[DarkSouls3Location], self.multiworld.get_filled_locations(self.player)):
+ # Skip events and only look at this world's locations
+ if (location.address is not None and location.item.code is not None
+ and location.data.static):
+ location_ids_to_keys[location.address] = location.data.static
slot_data = {
"options": {
- "enable_weapon_locations": self.multiworld.enable_weapon_locations[self.player].value,
- "enable_shield_locations": self.multiworld.enable_shield_locations[self.player].value,
- "enable_armor_locations": self.multiworld.enable_armor_locations[self.player].value,
- "enable_ring_locations": self.multiworld.enable_ring_locations[self.player].value,
- "enable_spell_locations": self.multiworld.enable_spell_locations[self.player].value,
- "enable_key_locations": self.multiworld.enable_key_locations[self.player].value,
- "enable_boss_locations": self.multiworld.enable_boss_locations[self.player].value,
- "enable_npc_locations": self.multiworld.enable_npc_locations[self.player].value,
- "enable_misc_locations": self.multiworld.enable_misc_locations[self.player].value,
- "auto_equip": self.multiworld.auto_equip[self.player].value,
- "lock_equip": self.multiworld.lock_equip[self.player].value,
- "no_weapon_requirements": self.multiworld.no_weapon_requirements[self.player].value,
- "death_link": self.multiworld.death_link[self.player].value,
- "no_spell_requirements": self.multiworld.no_spell_requirements[self.player].value,
- "no_equip_load": self.multiworld.no_equip_load[self.player].value,
- "enable_dlc": self.multiworld.enable_dlc[self.player].value
+ "random_starting_loadout": self.options.random_starting_loadout.value,
+ "require_one_handed_starting_weapons": self.options.require_one_handed_starting_weapons.value,
+ "auto_equip": self.options.auto_equip.value,
+ "lock_equip": self.options.lock_equip.value,
+ "no_weapon_requirements": self.options.no_weapon_requirements.value,
+ "death_link": self.options.death_link.value,
+ "no_spell_requirements": self.options.no_spell_requirements.value,
+ "no_equip_load": self.options.no_equip_load.value,
+ "enable_dlc": self.options.enable_dlc.value,
+ "enable_ngp": self.options.enable_ngp.value,
+ "smooth_soul_locations": self.options.smooth_soul_items.value,
+ "smooth_upgrade_locations": self.options.smooth_upgrade_items.value,
+ "randomize_enemies": self.options.randomize_enemies.value,
+ "randomize_mimics_with_enemies": self.options.randomize_mimics_with_enemies.value,
+ "randomize_small_crystal_lizards_with_enemies": self.options.randomize_small_crystal_lizards_with_enemies.value,
+ "reduce_harmless_enemies": self.options.reduce_harmless_enemies.value,
+ "simple_early_bosses": self.options.simple_early_bosses.value,
+ "scale_enemies": self.options.scale_enemies.value,
+ "all_chests_are_mimics": self.options.all_chests_are_mimics.value,
+ "impatient_mimics": self.options.impatient_mimics.value,
},
"seed": self.multiworld.seed_name, # to verify the server's multiworld
"slot": self.multiworld.player_name[self.player], # to connect to server
- "base_id": self.base_id, # to merge location and items lists
- "locationsId": locations_id,
- "locationsAddress": locations_address,
- "locationsTarget": locations_target,
- "itemsId": items_id,
- "itemsAddress": items_address
+ # Reserializing here is silly, but it's easier for the static randomizer.
+ "random_enemy_preset": json.dumps(self.options.random_enemy_preset.value),
+ "yhorm": (
+ f"{self.yhorm_location.name} {self.yhorm_location.id}"
+ if self.yhorm_location != default_yhorm_location
+ else None
+ ),
+ "apIdsToItemIds": ap_ids_to_ds3_ids,
+ "itemCounts": item_counts,
+ "locationIdsToKeys": location_ids_to_keys,
}
return slot_data
+
+ @staticmethod
+ def interpret_slot_data(slot_data: Dict[str, Any]) -> Dict[str, Any]:
+ return slot_data
diff --git a/worlds/dark_souls_3/detailed_location_descriptions.py b/worlds/dark_souls_3/detailed_location_descriptions.py
new file mode 100644
index 000000000000..e20c700ab1bc
--- /dev/null
+++ b/worlds/dark_souls_3/detailed_location_descriptions.py
@@ -0,0 +1,97 @@
+# python -m worlds.dark_souls_3.detailed_location_descriptions \
+# worlds/dark_souls_3/detailed_location_descriptions.py
+#
+# This script downloads the static randomizer's descriptions for each location and adds them to
+# the location documentation.
+
+from collections import defaultdict
+import html
+import os
+import re
+import requests
+import yaml
+
+from .Locations import location_dictionary
+
+
+location_re = re.compile(r'^([A-Z0-9]+): (.*?)(?:$| - )')
+
+if __name__ == '__main__':
+ # TODO: update this to the main branch of the main randomizer once Archipelago support is merged
+ url = 'https://raw.githubusercontent.com/nex3/SoulsRandomizers/archipelago-server/dist/Base/annotations.txt'
+ response = requests.get(url)
+ if response.status_code != 200:
+ raise Exception(f"Got {response.status_code} when downloading static randomizer locations")
+ annotations = yaml.load(response.text, Loader=yaml.Loader)
+
+ static_to_archi_regions = {
+ area['Name']: area['Archipelago']
+ for area in annotations['Areas']
+ }
+
+ descriptions_by_key = {slot['Key']: slot['Text'] for slot in annotations['Slots']}
+
+ # A map from (region, item name) pairs to all the descriptions that match those pairs.
+ descriptions_by_location = defaultdict(list)
+
+ # A map from item names to all the descriptions for those item names.
+ descriptions_by_item = defaultdict(list)
+
+ for slot in annotations['Slots']:
+ region = static_to_archi_regions[slot['Area']]
+ for item in slot['DebugText']:
+ name = item.split(" - ")[0]
+ descriptions_by_location[(region, name)].append(slot['Text'])
+ descriptions_by_item[name].append(slot['Text'])
+ counts_by_location = {
+ location: len(descriptions) for (location, descriptions) in descriptions_by_location.items()
+ }
+
+ location_names_to_descriptions = {}
+ for location in location_dictionary.values():
+ if location.ap_code is None: continue
+ if location.static:
+ location_names_to_descriptions[location.name] = descriptions_by_key[location.static]
+ continue
+
+ match = location_re.match(location.name)
+ if not match:
+ raise Exception(f"Location name \"{location.name}\" doesn't match expected format.")
+
+ item_candidates = descriptions_by_item[match[2]]
+ if len(item_candidates) == 1:
+ location_names_to_descriptions[location.name] = item_candidates[0]
+ continue
+
+ key = (match[1], match[2])
+ if key not in descriptions_by_location:
+ raise Exception(f'No static randomizer location found matching "{match[1]}: {match[2]}".')
+
+ candidates = descriptions_by_location[key]
+ if len(candidates) == 0:
+ raise Exception(
+ f'There are only {counts_by_location[key]} locations in the static randomizer ' +
+ f'matching "{match[1]}: {match[2]}", but there are more in Archipelago.'
+ )
+
+ location_names_to_descriptions[location.name] = candidates.pop(0)
+
+ table = "
Location name | Detailed description | \n"
+ for (name, description) in sorted(
+ location_names_to_descriptions.items(),
+ key = lambda pair: pair[0]
+ ):
+ table += f"
---|
{html.escape(name)} | {html.escape(description)} |
\n"
+ table += "
\n"
+
+ with open(os.path.join(os.path.dirname(__file__), 'docs/locations_en.md'), 'r+') as f:
+ original = f.read()
+ start_flag = "\n"
+ start = original.index(start_flag) + len(start_flag)
+ end = original.index("")
+
+ f.seek(0)
+ f.write(original[:start] + table + original[end:])
+ f.truncate()
+
+ print("Updated docs/locations_en.md!")
diff --git a/worlds/dark_souls_3/docs/en_Dark Souls III.md b/worlds/dark_souls_3/docs/en_Dark Souls III.md
index f31358bb9c2f..06227226aafe 100644
--- a/worlds/dark_souls_3/docs/en_Dark Souls III.md
+++ b/worlds/dark_souls_3/docs/en_Dark Souls III.md
@@ -1,28 +1,201 @@
# Dark Souls III
+Game Page | [Items] | [Locations]
+
+[Items]: /tutorial/Dark%20Souls%20III/items/en
+[Locations]: /tutorial/Dark%20Souls%20III/locations/en
+
+## What do I need to do to randomize DS3?
+
+See full instructions on [the setup page].
+
+[the setup page]: /tutorial/Dark%20Souls%20III/setup/en
+
## Where is the options page?
-The [player options page for this game](../player-options) contains all the options you need to configure and export a
-config file.
+The [player options page for this game][options] contains all the options you
+need to configure and export a config file.
+
+[options]: ../player-options
## What does randomization do to this game?
-Items that can be picked up from static corpses, taken from chests, or earned from defeating enemies or NPCs can be
-randomized. Common pickups like titanite shards or firebombs can be randomized as "progressive" items. That is, the
-location "Titanite Shard #5" is the fifth titanite shard you pick up, no matter where it was from. This is also what
-happens when you randomize Estus Shards and Undead Bone Shards.
+1. All item locations are randomized, including those in the overworld, in
+ shops, and dropped by enemies. Most locations can contain games from other
+ worlds, and any items from your world can appear in other players' worlds.
+
+2. By default, all enemies and bosses are randomized. This can be disabled by
+ setting "Randomize Enemies" to false.
+
+3. By default, the starting equipment for each class is randomized. This can be
+ disabled by setting "Randomize Starting Loadout" to false.
+
+4. By setting the "Randomize Weapon Level" or "Randomize Infusion" options, you
+ can randomize whether the weapons you find will be upgraded or infused.
+
+There are also options that can make playing the game more convenient or
+bring a new experience, like removing equip loads or auto-equipping weapons as
+you pick them up. Check out [the options page][options] for more!
+
+## What's the goal?
+
+Your goal is to find the four "Cinders of a Lord" items randomized into the
+multiworld and defeat the boss in the Kiln of the First Flame.
+
+## Do I have to check every item in every area?
+
+Dark Souls III has about 1500 item locations, which is a lot of checks for a
+single run! But you don't necessarily need to check all of them. Locations that
+you can potentially miss, such as rewards for failable quests or soul
+transposition items, will _never_ have items required for any game to progress.
+The following types of locations are also guaranteed not to contain progression
+items by default:
+
+* **Hidden:** Locations that are particularly difficult to find, such as behind
+ illusory walls, down hidden drops, and so on. Does not include large locations
+ like Untended Graves or Archdragon Peak.
+
+* **Small Crystal Lizards:** Drops from small crystal lizards.
+
+* **Upgrade:** Locations that contain upgrade items in vanilla, including
+ titanite, gems, and Shriving Stones.
+
+* **Small Souls:** Locations that contain soul items in vanilla, not including
+ boss souls.
+
+* **Miscellaneous:** Locations that contain generic stackable items in vanilla,
+ such as arrows, firebombs, buffs, and so on.
+
+You can customize which locations are guaranteed not to contain progression
+items by setting the `exclude_locations` field in your YAML to the [location
+groups] you want to omit. For example, this is the default setting but without
+"Hidden" so that hidden locations can contain progression items:
+
+[location groups]: /tutorial/Dark%20Souls%20III/locations/en#location-groups
+
+```yaml
+Dark Souls III:
+ exclude_locations:
+ - Small Crystal Lizards
+ - Upgrade
+ - Small Souls
+ - Miscellaneous
+```
+
+This allows _all_ non-missable locations to have progression items, if you're in
+for the long haul:
+
+```yaml
+Dark Souls III:
+ exclude_locations: []
+```
+
+## What if I don't want to do the whole game?
+
+If you want a shorter DS3 randomizer experience, you can exclude entire regions
+from containing progression items. The items and enemies from those regions will
+still be included in the randomization pool, but none of them will be mandatory.
+For example, the following configuration just requires you to play the game
+through Irithyll of the Boreal Valley:
+
+```yaml
+Dark Souls III:
+ # Enable the DLC so it's included in the randomization pool
+ enable_dlc: true
+
+ exclude_locations:
+ # Exclude late-game and DLC regions
+ - Anor Londo
+ - Lothric Castle
+ - Consumed King's Garden
+ - Untended Graves
+ - Grand Archives
+ - Archdragon Peak
+ - Painted World of Ariandel
+ - Dreg Heap
+ - Ringed City
+
+ # Default exclusions
+ - Hidden
+ - Small Crystal Lizards
+ - Upgrade
+ - Small Souls
+ - Miscellaneous
+```
+
+## Where can I learn more about Dark Souls III locations?
+
+Location names have to pack a lot of information into very little space. To
+better understand them, check out the [location guide], which explains all the
+names used in locations and provides more detailed descriptions for each
+individual location.
+
+[location guide]: /tutorial/Dark%20Souls%20III/locations/en
+
+## Where can I learn more about Dark Souls III items?
+
+Check out the [item guide], which explains the named groups available for items.
+
+[item guide]: /tutorial/Dark%20Souls%20III/items/en
+
+## What's new from 2.x.x?
+
+Version 3.0.0 of the Dark Souls III Archipelago client has a number of
+substantial differences with the older 2.x.x versions. Improvements include:
+
+* Support for randomizing all item locations, not just unique items.
+
+* Support for randomizing items in shops, starting loadouts, Path of the Dragon,
+ and more.
+
+* Built-in integration with the enemy randomizer, including consistent seeding
+ for races.
+
+* Support for the latest patch for Dark Souls III, 1.15.2. Older patches are
+ *not* supported.
+
+* Optional smooth distribution for upgrade items, upgraded weapons, and soul
+ items so you're more likely to see weaker items earlier and more powerful
+ items later.
+
+* More detailed location names that indicate where a location is, not just what
+ it replaces.
+
+* Other players' item names are visible in DS3.
+
+* If you pick up items while static, they'll still send once you reconnect.
+
+However, 2.x.x YAMLs are not compatible with 3.0.0. You'll need to [generate a
+new YAML configuration] for use with 3.x.x.
+
+[generating a new YAML configuration]: /games/Dark%20Souls%20III/player-options
+
+The following options have been removed:
+
+* `enable_boss_locations` is now controlled by the `soul_locations` option.
+
+* `enable_progressive_locations` was removed because all locations are now
+ individually randomized rather than replaced with a progressive list.
+
+* `pool_type` has been removed. Since there are no longer any non-randomized
+ items in randomized categories, there's not a meaningful distinction between
+ "shuffle" and "various" mode.
-It's also possible to randomize the upgrade level of weapons and shields as well as their infusions (if they can have
-one). Additionally, there are options that can make the randomized experience more convenient or more interesting, such as
-removing weapon requirements or auto-equipping whatever equipment you most recently received.
+* `enable_*_locations` options have all been removed. Instead, you can now add
+ [location group names] to the `exclude_locations` option to prevent them from
+ containing important items.
-The goal is to find the four "Cinders of a Lord" items randomized into the multiworld and defeat the Soul of Cinder.
+ [location group names]: /tutorial/Dark%20Souls%20III/locations/en#location-groups
-## What Dark Souls III items can appear in other players' worlds?
+ By default, the Hidden, Small Crystal Lizards, Upgrade, Small Souls, and
+ Miscellaneous groups are in `exclude_locations`. Once you've chosen your
+ excluded locations, you can set `excluded_locations: unrandomized` to preserve
+ the default vanilla item placements for all excluded locations.
-Practically anything can be found in other worlds including pieces of armor, upgraded weapons, key items, consumables,
-spells, upgrade materials, etc...
+* `guaranteed_items`: In almost all cases, all items from the base game are now
+ included somewhere in the multiworld.
-## What does another world's item look like in Dark Souls III?
+In addition, the following options have changed:
-In Dark Souls III, items which are sent to other worlds appear as Prism Stones.
+* The location names used in options like `exclude_locations` have changed. See
+ the [location guide] for a full description.
diff --git a/worlds/dark_souls_3/docs/items_en.md b/worlds/dark_souls_3/docs/items_en.md
new file mode 100644
index 000000000000..b9de5e500a96
--- /dev/null
+++ b/worlds/dark_souls_3/docs/items_en.md
@@ -0,0 +1,24 @@
+# Dark Souls III Items
+
+[Game Page] | Items | [Locations]
+
+[Game Page]: /games/Dark%20Souls%20III/info/en
+[Locations]: /tutorial/Dark%20Souls%20III/locations/en
+
+## Item Groups
+
+The Dark Souls III randomizer supports a number of item group names, which can
+be used in YAML options like `local_items` to refer to many items at once:
+
+* **Progression:** Items which unlock locations.
+* **Cinders:** All four Cinders of a Lord. Once you have these four, you can
+ fight Soul of Cinder and win the game.
+* **Miscellaneous:** Generic stackable items, such as arrows, firebombs, buffs,
+ and so on.
+* **Unique:** Items that are unique per NG cycle, such as scrolls, keys, ashes,
+ and so on. Doesn't include equipment, spells, or souls.
+* **Boss Souls:** Souls that can be traded with Ludleth, including Soul of
+ Rosaria.
+* **Small Souls:** Soul items, not including boss souls.
+* **Upgrade:** Upgrade items, including titanite, gems, and Shriving Stones.
+* **Healing:** Undead Bone Shards and Estus Shards.
diff --git a/worlds/dark_souls_3/docs/locations_en.md b/worlds/dark_souls_3/docs/locations_en.md
new file mode 100644
index 000000000000..ef07b84b2b34
--- /dev/null
+++ b/worlds/dark_souls_3/docs/locations_en.md
@@ -0,0 +1,2276 @@
+# Dark Souls III Locations
+
+[Game Page] | [Items] | Locations
+
+[Game Page]: /games/Dark%20Souls%20III/info/en
+[Items]: /tutorial/Dark%20Souls%20III/items/en
+
+## Table of Contents
+
+* [Location Groups](#location-groups)
+* [Understanding Location Names](#understanding-location-names)
+ * [HWL: High Wall of Lothric](#high-wall-of-lothric)
+ * [US: Undead Settlement](#undead-settlement)
+ * [RS: Road of Sacrifices](#road-of-sacrifices)
+ * [CD: Cathedral of the Deep](#cathedral-of-the-deep)
+ * [FK: Farron Keep](#farron-keep)
+ * [CC: Catacombs of Carthus](#catacombs-of-carthus)
+ * [SL: Smouldering Lake](#smouldering-lake)
+ * [IBV: Irithyll of the Boreal Valley](#irithyll-of-the-boreal-valley)
+ * [ID: Irithyll Dungeon](#irithyll-dungeon)
+ * [PC: Profaned Capital](#profaned-capital)
+ * [AL: Anor Londo](#anor-londo)
+ * [LC: Lothric Castle](#lothric-castle)
+ * [CKG: Consumed King's Garden](#consumed-kings-garden)
+ * [GA: Grand Archives](#grand-archives)
+ * [UG: Untended Graves](#untended-graves)
+ * [AP: Archdragon Peak](#archdragon-peak)
+ * [PW1: Painted World of Ariandel (Before Contraption)](#painted-world-of-ariandel-before-contraption)
+ * [PW2: Painted World of Ariandel (After Contraption)](#painted-world-of-ariandel-after-contraption)
+ * [DH: Dreg Heap](#dreg-heap)
+ * [RC: Ringed City](#ringed-city)
+* [Detailed Location Descriptions](#detailed-location-descriptions)
+
+## Location Groups
+
+The Dark Souls III randomizer supports a number of location group names, which
+can be used in YAML options like `exclude_locations` to refer to many locations
+at once:
+
+* **Prominent:** A small number of locations that are in very obvious locations.
+ Mostly boss drops. Ideal for setting as priority locations.
+
+* **Progression:** Locations that contain items in vanilla which unlock other
+ locations.
+
+* **Boss Rewards:** Boss drops. Does not include soul transfusions or shop
+ items.
+
+* **Miniboss Rewards:** Miniboss drops. Minibosses are large enemies that don't
+ respawn after being killed and usually drop some sort of treasure, such as
+ Boreal Outrider Knights and Ravenous Crystal Lizards. Only includes enemies
+ considered minibosses by the enemy randomizer.
+
+* **Mimic Rewards:** Drops from enemies that are mimics in vanilla.
+
+* **Hostile NPC Rewards:** Drops from NPCs that are hostile to you. This
+ includes scripted invaders and initially-friendly NPCs that must be fought as
+ part of their quest.
+
+* **Friendly NPC Rewards:** Items given by friendly NPCs as part of their quests
+ or from non-violent interaction.
+
+* **Small Crystal Lizards:** Drops from small crystal lizards.
+
+* **Upgrade:** Locations that contain upgrade items in vanilla, including
+ titanite, gems, and Shriving Stones.
+
+* **Small Souls:** Locations that contain soul items in vanilla, not including
+ boss souls.
+
+* **Boss Souls:** Locations that contain boss souls in vanilla, as well as Soul
+ of Rosaria.
+
+* **Unique:** Locations that contain items in vanilla that are unique per NG
+ cycle, such as scrolls, keys, ashes, and so on. Doesn't cover equipment,
+ spells, or souls.
+
+* **Healing:** Locations that contain Undead Bone Shards and Estus Shards in
+ vanilla.
+
+* **Miscellaneous:** Locations that contain generic stackable items in vanilla,
+ such as arrows, firebombs, buffs, and so on.
+
+* **Hidden:** Locations that are particularly difficult to find, such as behind
+ illusory walls, down hidden drops, and so on. Does not include large locations
+ like Untended Graves or Archdragon Peak.
+
+* **Weapons:** Locations that contain weapons in vanilla.
+
+* **Shields:** Locations that contain shields in vanilla.
+
+* **Armor:** Locations that contain armor in vanilla.
+
+* **Rings:** Locations that contain rings in vanilla.
+
+* **Spells:** Locations that contain spells in vanilla.
+
+## Understanding Location Names
+
+All locations begin with an abbreviation indicating their general region. Most
+locations have a set of landmarks that are used in location names to keep them
+short.
+
+* **FS:** Firelink Shrine
+* **FSBT:** Firelink Shrine belltower
+* **HWL:** [High Wall of Lothric](#high-wall-of-lothric)
+* **US:** [Undead Settlement](#undead-settlement)
+* **RS:** [Road of Sacrifices](#road-of-sacrifices)
+* **CD:** [Cathedral of the Deep](#cathedral-of-the-deep)
+* **FK:** [Farron Keep](#farron-keep)
+* **CC:** [Catacombs of Carthus](#catacombs-of-carthus)
+* **SL:** [Smouldering Lake](#smouldering-lake)
+* **IBV:** [Irithyll of the Boreal Valley](#irithyll-of-the-boreal-valley)
+* **ID:** [Irithyll Dungeon](#irithyll-dungeon)
+* **PC:** [Profaned Capital](#profaned-capital)
+* **AL:** [Anor Londo](#anor-londo)
+* **LC:** [Lothric Castle](#lothric-castle)
+* **CKG:** [Consumed King's Garden](#consumed-kings-garden)
+* **GA:** [Grand Archives](#grand-archives)
+* **UG:** [Untended Graves](#untended-graves)
+* **AP:** [Archdragon Peak](#archdragon-peak)
+* **PW1:** [Painted World of Ariandel (Before Contraption)](#painted-world-of-ariandel-before-contraption)
+* **PW2:** [Painted World of Ariandel (After Contraption)](#painted-world-of-ariandel-after-contraption)
+* **DH:** [Dreg Heap](#dreg-heap)
+* **RC:** [Ringed City](#ringed-city)
+
+General notes:
+
+* "Lizard" always refers to a small crystal lizard.
+
+* "Miniboss" are large enemies that don't respawn after being killed and usually
+ drop some sort of treasure, such as Boreal Outrider Knights and Ravenous
+ Crystal Lizards.
+
+* NPC quest items are always in the first location you can get them _without_
+ killing the NPC or ending the quest early.
+
+### High Wall of Lothric
+
+* **Back tower:** The tower _behind_ the High Wall of Lothric bonfire, past the
+ path to the shortcut elevator.
+
+* **Corpse tower:** The first tower after the High Wall of Lothric bonfire, with
+ a dead Wyvern on top of it.
+
+* **Fire tower:** The second tower after the High Wall of Lothric bonfire, where
+ a living Wyvern lands and breathes fire at you.
+
+* **Flame plaza:** The open area with many items where the Wyvern breathes fire.
+
+* **Wall tower:** The third tower after the High Wall of Lothric bonfire, with
+ the Tower on the Wall bonfire.
+
+* **Fort:** The large building after the Tower on the Wall bonfire, with the
+ transforming hollow on top.
+
+ * "Entry": The first room you enter after descending the ladder from the roof.
+
+ * "Walkway": The top floor of the tall room, with a path around the edge
+ hidden by a large wheel.
+
+ * "Mezzanine": The middle floor of the tall room, with a chest.
+
+ * "Ground": The bottom floor of the tall room, with an anvil and many mobs.
+
+* **Fountain:** The large fountain with many dead knights around it, where the
+ Winged Knight patrols in vanilla.
+
+* **Shortcut:** The unlockable path between the promenade and the High Wall of
+ Lothric bonfire, including both the elevator and the area at its base.
+
+* **Promenade:** The long, wide path between the two boss arenas.
+
+### Undead Settlement
+
+* **Foot:** The area where you first appear, around the Foot of the High Wall
+ bonfire.
+
+* **Burning tree:** The tree near the beginning of the region, with the
+ Cathedral Evangelist in front of it in vanilla.
+
+* **Hanging corpse room:** The dark room to the left of the burning tree with
+ many hanging corpses inside, on the way to the Dilapidated Bridge bonfire.
+
+* **Back alley:** The path between buildings leading to the Dilapidated Bridge
+ bonfire.
+
+* **Stable:** The building complex across the bridge to the right of the burning
+ tree.
+
+* **White tree:** The birch tree by the Dilapidated Bridge bonfire, where the
+ giant shoots arrows.
+
+* **Sewer:** The underground passage between the chasm and the Dilapidated
+ Bridge bonfire.
+
+* **Chasm:** The chasm underneath the bridge on the way to the tower. It's
+ possible to get into the chasm without a key by dropping down next to Eygon of
+ Carim with a full health bar.
+
+* **Tower:** The tower at the end of the region with the giant archer at the
+ top.
+
+* **Tower village:** The village reachable from the tower, where the Fire Demon
+ patrols in vanilla.
+
+### Road of Sacrifices
+
+The area after the Crystal Sage is considered part of the Cathedral of the Deep
+region.
+
+* **Road:** The path from the Road of Sacrifices bonfire to the Halfway Fortress
+ bonfire.
+
+* **Woods:** The wooded area on land, after the Halfway Fortress bonfire and
+ surrounding the Crucifixion Woods bonfire.
+
+* **Water:** The watery area, covered in crabs in vanilla.
+
+* **Deep water:** The area in the water near the ladder to Farron Keep, where
+ your walking is slowed.
+
+* **Stronghold:** The stone building complex on the way to Crystal Sage.
+
+ * "Left room" is the room whose entrance is near the Crucifixion Woods
+ bonfire.
+
+ * "Right room" is the room up the stairs closer to Farron Keep.
+
+* **Keep perimeter:** The building with the Black Knight and the locked door to
+ the Farron Keep Perimeter bonfire.
+
+### Cathedral of the Deep
+
+* **Path:** The path from Road of Sacrifices to the cathedral proper.
+
+* **Moat:** The circular path around the base of the front of the
+ cathedral, with the Ravenous Crystal Lizard and Corpse-Grubs in vanilla.
+
+* **Graveyard:** The area with respawning enemies up the hill from the Cleansing
+ Chapel bonfire.
+
+* **White tree:** The birch tree below the front doors of the chapel and across
+ the moat from the graveyard, where the giant shoots arrows if he's still
+ alive.
+
+* **Lower roofs:** The roofs, flying buttresses, and associated areas to the
+ right of the front door, which must be traversed before entering the
+ cathedral.
+
+* **Upper roofs:** The roofs, flying buttresses, and rafters leading to the
+ Rosaria's Bedchamber bonfire.
+
+* **Main hall:** The central and largest room in the cathedral, with the muck
+ that slows your movement. Divided into the south (with the sleeping giant in
+ vanilla) and east (with many items) wings, with north pointing towards the
+ door to the boss.
+
+* **Side chapel:** The room with rows of pews and the patrolling Cathedral
+ Knight in vanilla, to the side of the main hall.
+
+### Farron Keep
+
+* **Left island:** The large island with the ritual flame, to the left as you
+ leave the Farron Keep bonfire.
+
+* **Right island:** The large island with the ritual flame, to the right as you
+ leave the Farron Keep bonfire.
+
+* **Hidden cave:** A small cave in the far corner of the map, closest to the
+ right island. Near a bunch of basilisks in vanilla.
+
+* **Keep ruins:** The following two islands:
+
+ * "Bonfire island": The island with the Keep Ruins bonfire.
+ * "Ritual island": The island with one of the three ritual fires.
+
+* **White tree**: The birch tree by the ramp down from the keep ruins bonfire
+ island, where the giant shoots arrows if he's still alive.
+
+* **Keep proper:** The building with the Old Wolf of Farron bonfire.
+
+* **Upper keep:** The area on top of the keep proper, reachable from the
+ elevator from the Old Wolf of Farron bonfire.
+
+* **Perimeter:** The area from near the Farron Keep Perimeter bonfire, including
+ the stone building and the path to the boss.
+
+### Catacombs of Carthus
+
+All the area up to the Small Doll wall into Irithyll is considered part of the
+Catacombs of Carthus region.
+
+* **Atrium:** The large open area you first enter and the rooms attached to it.
+
+ * "Upper" is the floor you begin on.
+ * "Lower" is the floor down the short stairs but at the top of the long
+ stairway that the skeleton ball rolls down.
+
+* **Crypt:** The enclosed area at the bottom of the long stairway that the
+ skeleton ball rolls down.
+
+ * "Upper" is the floor the long stairway leads to that also contains the
+ Catacombs of Carthus bonfire.
+ * "Lower" is the floor with rats and bonewheels in vanilla.
+ * "Across" is the area reached by going up the set of stairs across from
+ the entrance downstairs.
+
+* **Cavern:** The even larger open area past the crypt with the rope bridge to
+ the boss arena.
+
+* **Tomb:** The area on the way to Smouldering Lake, reachable by cutting down
+ the rope bridge and climbing down it.
+
+* **Irithyll Bridge:** The outdoor bridge leading to Irithyll of the Boreal
+ Valley.
+
+### Smouldering Lake
+
+* **Lake:** The watery area you enter initially, where you get shot at by the
+ ballista.
+
+* **Side lake:** The small lake accessible via a passage from the larger one, in
+ which you face Horace the Hushed as part of his quest.
+
+* **Ruins main:** The area you first enter after the Demon Ruins bonfire.
+
+ * "Upper" is the floor you begin on.
+ * "Lower" is the floor down the stairs.
+
+* **Antechamber:** The area up the flight of stairs near the
+Old King's Antechamber bonfire.
+
+* **Ruins basement:** The area further down from ruins main lower, with many
+ basilisks and Knight Slayer Tsorig in vanilla.
+
+### Irithyll of the Boreal Valley
+
+This region starts _after_ the Small Doll wall and ends with Pontiff Sulyvahn.
+Everything after that, including the contents of Sulyvahn's cathedral is
+considered part of Anor Londo.
+
+* **Central:** The beginning of the region, from the Central Irithyll bonfire up
+ to the plaza.
+
+* **Dorhys:** The sobbing mob (a Cathedral Evangelist in vanilla) behind the
+ locked door opening onto central. Accessed through an illusory railing by the
+ crystal lizard just before the plaza.
+
+* **Plaza:** The area in front of and below the cathedral, with a locked door up
+ to the cathedral and a locked elevator to the Ascent.
+
+* **Descent:** The path from the Church of Yorshka bonfire down to the lake.
+
+* **Lake:** The open watery area outside the room with the Distant Manor
+ bonfire.
+
+* **Sewer:** The room between the lake and the beginning of the ascent, filled
+ with Sewer Centipedes in vanilla.
+
+* **Ascent:** The path up from the lake to the cathedral, through several
+ buildings and some open stairs.
+
+* **Great hall:** The building along the ascent with a large picture of
+ Gwynevere and several Silver Knights in vanilla.
+
+### Irithyll Dungeon
+
+In Irithyll Dungeon locations, "left" and "right" are always oriented as though
+"near" is where you stand and "far" is where you're facing. (For example, you
+enter the dungeon from the bonfire on the near left.)
+
+* **B1:** The floor on which the player enters the dungeon, with the Irithyll
+ Dungeon bonfire.
+
+ * "Near" is the side of the dungeon with the bonfire.
+ * "Far" is the opposite side.
+
+* **B2:** The floor directly below B1, which can be reached by going down the
+ stairs or dropping.
+
+ * "Near" is the same side of the dungeon as the bonfire.
+ * "Far" is the opposite side.
+
+* **Pit:** The large room with the Giant Slave and many Rats in vanilla.
+
+* **Pit lift:** The elevator from the pit up to B1 near, right to the Irithyll
+ Dungeon bonfire.
+
+* **B3:** The lowest floor, with Karla's cell, a lift back to B2, and the exit
+ onwards to the Profaned Capital.
+
+ * "Near" is the side with Karla's cell and the path from the pit.
+ * "Far" is the opposite side with the mimic.
+
+* **B3 lift:** The elevator from B3 (near where you can use Path of the Dragon
+ to go to Archdragon Peak) up to B2.
+
+### Profaned Capital
+
+* **Tower:** The tower that contains the Profaned Capital bonfire.
+
+* **Swamp:** The pool of toxic liquid accessible by falling down out of the
+ lower floor of the tower, going into the corridor to the left, and falling
+ down a hole.
+
+* **Chapel:** The building in the swamp containing Monstrosities of Sin in
+ vanilla.
+
+* **Bridge:** The long bridge from the tower into the palace.
+
+* **Palace:** The large building carved into the wall of the cavern, full of
+ chalices and broken pillars.
+
+### Anor Londo
+
+This region includes everything after Sulyvahn's cathedral, including its upper
+story.
+
+* **Light cathedral:** The cathedral in which you fight Pontiff Sulyvahn in
+ vanilla.
+
+* **Plaza:** The wide open area filled with Giant Slaves in vanilla.
+
+* **Walkway:** The path above the plaza leading to the second floor of the light
+ cathedral, with Deacons in vanilla.
+
+* **Buttresses:** The flying buttresses that you have to climb to get to the
+ spiral staircase. "Near" and "far" are relative to the light cathedral, so the
+ nearest buttress is the one that leads back to the walkway.
+
+* **Tomb:** The area past the illusory wall just before the spiral staircase, in
+ which you marry Anri during Yoel and Yuria's quest.
+
+* **Dark cathedral:** The darkened cathedral just before the Aldrich fight in
+ vanilla.
+
+### Lothric Castle
+
+This region covers everything up the ladder from the Dancer of the Boreal Valley
+bonfire up to the door into Grand Archives, except the area to the left of the
+ladder which is part of Consumed King's Garden.
+
+* **Lift:** The elevator from the room straight after the Dancer of the Boreal
+ Valley bonfire up to just before the boss fight.
+
+* **Ascent:** The set of stairways and turrets leading from the Lothric Castle
+ bonfire to the Dragon Barracks bonfire.
+
+* **Barracks:** The large building with two fire-breathing wyverns across from
+ the Dragon Barracks bonfire.
+
+* **Moat:** The ditch beneath the bridge leading to the barracks.
+
+ * The "right path" leads to the right as you face the barracks, around and
+ above the stairs up to the Dragon Barracks bonfire.
+
+* **Plaza:** The open area in the center of the barracks, where the two wyverns
+ breathe fire.
+
+ * "Left" is the enclosed area on the left as you're coming from the Dragon
+ Barracks bonfire, with the stairs down to the basement.
+
+* **Basement:** The room beneath plaza left, with the Boreal Outrider in
+ vanilla.
+
+* **Dark room:** The large darkened room on the right of the barracks as you're
+ coming from the Dragon Barracks bonfire, with firebomb-throwing Hollows in
+ vanilla.
+
+ * "Lower" is the bottom floor that you enter onto from the plaza.
+ * "Upper" is the top floor with the door to the main hall.
+ * "Mid" is the middle floor accessible by climbing a ladder from lower or
+ going down stairs from upper.
+
+* **Main hall:** The central room of the barracks, behind the gate.
+
+* **Chapel:** The building to the right just before the stairs to the boss, with
+ a locked elevator to Grand Archives.
+
+* **Wyvern room:** The room where you can fight the Pus of Man infecting the
+ left wyvern, accessible by dropping down to the left of the stairs to the
+ boss.
+
+* **Altar:** The building containing the Altar of Sunlight, accessible by
+ climbing up a ladder onto a roof around the corner from the stairs to the
+ boss.
+
+### Consumed King's Garden
+
+This region covers everything to the left of the ladder up from the Dancer of
+the Boreal Valley bonfire up to the illusory wall into Untended Graves.
+
+* **Balcony:** The walkway accessible by getting off the first elevator halfway
+ down.
+
+* **Rotunda:** The building in the center of the toxic pool, with a Cathedral
+ Knight on it in vanilla.
+
+* **Lone stairway:** A set of stairs leading nowhere in the far left of the main
+ area as you enter from the first elevator.
+
+* **Shortcut:** The path from the locked door into Lothric Castle, through the
+ room filled with thralls in vanilla, and down a lift.
+
+* **Tomb:** The area after the boss room.
+
+### Grand Archives
+
+* **1F:** The first floor of the Grand Archives, including the first wax pool.
+
+* **Dark room:** The unlit room on 1F to the right of the wax pool.
+
+* **2F:** The second floor of the grand archives. It's split into two sections
+ that are separated by retractable bookshelves.
+
+ * "Early" is the first part you reach and has an outdoor balcony with a ladder
+ to 3F and a wax pool up a short set of stairs.
+ * "Late" is the part you can only reach by climbing down from F3, where you
+ encounter the teleporting miniboss for the final time.
+
+* **3F:** The third floor of the grand archives, where you encounter the
+ teleporting miniboss for the second time. Includes the area with a hidden room
+ with another miniboss.
+
+* **4F:** The topmost and most well-lit section of bookshelves, overlooking the
+ rest of the archives.
+
+* **Rooftops:** The outer rooftop area between 4F and 5F, with Gargoyles in
+ vanilla.
+
+ * "Lower" is the balcony you can reach by dropping off the rooftops, as well
+ as the further rooftops leading down to the 2F early balcony.
+
+* **5F:** The topmost floor of the archives interior, accessible from the
+ rooftops, with a ladder down to 4F.
+
+* **Dome:** The domed roof of the Grand Archives, with Ascended Winged Knights
+ in vanilla.
+
+* **Rafters:** The narrow walkways above the Grand Archives, accessible by
+ dropping down from the dome.
+
+### Untended Graves
+
+* **Swamp:** The watery area immediately after the Untended graves bonfire, up
+ to the cemetery.
+
+* **Cemetery:** The area past where the Cemetery of Ash bonfire would be, up to
+ the boss arena.
+
+* **Environs:** The area after the boss and outside the abandoned Firelink
+ Shrine.
+
+* **Shrine:** The area inside the abandoned Firelink Shrine.
+
+### Archdragon Peak
+
+"Gesture" always means the Path of the Dragon gesture.
+
+* **Intro:** The first section, from where you warp in from Irithyll Dungeon up
+ to the first boss fight.
+
+ * "Archway": The large stone archway in front of the boss door.
+
+* **Fort:** The arena where you fight Ancient Wyvern in vanilla.
+
+ * "Overlook": The area down the stairs from where the Ancient Wyvern first
+ lands in vanilla, overlooking the fog.
+
+ * "Rotunda": The top of the spiral staircase building, to the left before the
+ bridge with the chain-axe Man-Serpent in vanilla.
+
+* **Mausoleum:** The building with the Dragon-Kin Mausoleum bonfire, where
+ you're warped after the first boss fight.
+
+* **Walkway:** The path from the mausoleum to the belfry, looking out over
+ clouds.
+
+ * "Building": The building along the walkway, just before the wyvern in
+ vanilla.
+
+* **Belfry:** The building with the Great Belfry bonfire, including the room
+ with the summoner.
+
+* **Plaza:** The arena that appears after you defeat Nameless King in vanilla.
+
+* **Summit:** The path up from the belfry to the final altar at the top of the
+ mountain.
+
+### Painted World of Ariandel (Before Contraption)
+
+This region covers the Ashes of Ariandel DLC up to the point where you must use
+the Contraption Key to ascend to the second level of the building and first meet
+the painter.
+
+* **Snowfield:** The area around the Snowfield bonfire,
+
+ * "Upper": The area immediately after the Snowfield bonfire, before the
+ collapsing overhang, with the Followers in vanilla.
+
+ * "Lower": The snowy tree-filled area after the collapsing overhang, with the
+ Wolves in vanilla.
+
+ * "Village": The area with broken-down buildings and Millwood Knights in
+ vanilla.
+
+ * "Tower": The tower by the village, with Millwood Knights in Vanilla.
+
+* **Bridge:** The rope bridge to the chapel.
+
+ * "Near": The side of the bridge by the Rope Bridge Cave bonfire.
+
+ * "Far": The side of the bridge by the Ariandel Chapel bonfire.
+
+* **Chapel:** The building with the Ariandel Chapel bonfire and Lady Friede.
+
+* **Depths:** The area reachable by cutting down the bridge and descending on
+ the far side, with the Depths of the Painting bonfire.
+
+* **Settlement:** The area reachable by cutting down the bridge and descending
+ on the near side, with the Corvian Settlement bonfire. Everything after the
+ slide down the hill is considered part of the settlement.
+
+ * "Courtyard": The area in front of the settlement, immediately after the
+ slide.
+
+ * "Main": The main road of the settlement leading up to the locked gate to the
+ library. Also includes the buildings that are immediately accessible from
+ this road.
+
+ * "Loop": A side path that loops left from the main road and goes up and
+ behind the building with the bonfire.
+
+ * "Back": The back alley of the settlement, accessible by dropping down to the
+ right of the locked gate to the library. Also includes the buildings that
+ are immediately accessible from this alley.
+
+ * "Roofs": The village rooftops, first accessible by climbing a ladder from
+ the back alley. Also includes the buildings and items that are first
+ accessible from the roofs.
+
+ * "Hall": The largest building in the settlement, with two Corvian Knights in
+ vanilla.
+
+* **Library:** The building where you use the contraption key, where Vilhelm
+ appears in vanilla.
+
+### Painted World of Ariandel (After Contraption)
+
+This region covers the Ashes of Ariandel DLC past the point where you must use
+the Contraption Key to ascend to the second level of the building and first meet
+the painter, including the basement beneath the chapel.
+
+* **Pass:** The mountainous area past the Snowy Mountain Pass bonfire.
+
+* **Pit:** The area with a large tree and numerous Millwood Knights in vanilla,
+ reached by a collapsing overhang in the pass.
+
+* **B1:** The floor immediately below the chapel, first accessible from the
+ pass. Filled with Giant Flies in vanilla.
+
+* **B2:** The floor below B1, with lots of fly eggs. Filled with even more Giant
+ Flies than B1 in vanilla.
+
+* **B3:** The floor below B2, accessible through an illusory wall.
+
+* **Rotunda:** The round arena out in the open, accessible by platforming down
+ tree roots from B3.
+
+### Dreg Heap
+
+* **Shop:** Items sold by the Stone-Humped Hag by The Dreg Heap bonfire.
+
+* **Castle:** The building with The Dreg Heap bonfire, up to the large fall into
+ the library.
+
+* **Library:** The building with the stained-glass window that you fall into
+ from the castle.
+
+* **Church:** The building below and to the right of the library, which the
+ pillar falls into to make a bridge.
+
+* **Pantry:** The set of rooms entered through a door near the fountain just
+ past the church, with boxes and barrels.
+
+ * "Upstairs": The room with an open side, accessible through an illusory wall
+ in the furthest pantry room.
+
+* **Parapets:** The area with balconies and Overgrown Lothric Knights in
+ vanilla, accessible by taking the pillar bridge from the church, following
+ that path to the end, and dropping down to the right.
+
+* **Ruins:** The area around the Earthen Peak Ruins bonfire, up to the swamp.
+
+* **Swamp:** The area in and above the poisonous water, up to the point the
+ branches deposit you back on the ruins.
+
+ * "Left": Left as you enter from the ruins, towards the cliff edge.
+
+ * "Right": Right as you enter from the ruins, towards higher ground.
+
+ * "Upper": The path up and over the swamp towards the Within Earthen Peak
+ Ruins bonfire.
+
+### Ringed City
+
+The "mid boss", "end boss", and "hidden boss" are the bosses who take the place
+of Halflight, Gael, and Midir, respectively.
+
+* **Wall:** The large wall in which you spawn when you first enter the area,
+ with the Mausoleum Lookout bonfire.
+
+ * "Top": The open-air top of the wall, where you first spawn in.
+
+ * "Upper": The upper area of the wall, with the Ringed Inner Wall bonfire.
+
+ * "Tower": The tiered tower leading down from the upper area to the stairs.
+
+ * "Lower": The lower rooms of the wall, accessible from the lower cliff, with
+ an elevator back to upper.
+
+ * "Hidden": The hidden floor accessible from the elevator from lower to upper,
+ from which you can reach Midir in vanilla.
+
+* **Streets:** The streets and skyways of the city proper. "Left" and "right"
+ are relative to the main staircase as you head down towards the swamp, "near"
+ and "far" are relative to Shira's chamber at the top of the stairs.
+
+ * "Garden": The flower-filled back alley accessible from the left side of the
+ nearest bridge over the stairs.
+
+ * "High": The higher areas in the far left where you can find the Locust
+ Preacher, accessible from a long ladder in the swamp.
+
+ * "Monument": The area around the purging monument, which can only be accessed
+ by solving the "Show Your Humanity" puzzle.
+
+* **Swamp:** The wet area past the city streets. "Left" and "right" are relative
+ to heading out from the Ringed City Streets bonfire, and "near" and "far" are
+ relative to that bonfire as well.
+
+* **Lower cliff:** The cliffside path leading from the swamp into the shared
+ grave, where Midir breathes fire.
+
+* **Grave:** The cylindrical chamber with spiral stairs around the edges,
+ connecting the two cliffs, containing the Shared Grave bonfire.
+
+* **Upper cliff:** The cliffside path leading out of the grave to the lower
+ wall.
+
+* **Church path:** The sunlit path from the lower cliff up to the Church of
+ Filianore where you fight Halflight in vanilla.
+
+* **Ashes:** The final area, where you fight Gael in vanilla.
+
+## Detailed Location Descriptions
+
+These location descriptions were originally written by [Matt Gruen] for [the
+static _Dark Souls III_ randomizer].
+
+[Matt Gruen]: https://thefifthmatt.com/
+[the static _Dark Souls III_ randomizer]: https://www.nexusmods.com/darksouls3/mods/361
+
+
+
+
+Location name | Detailed description |
+
---|
AL: Aldrich Faithful - water reserves, talk to McDonnel | Given by Archdeacon McDonnel in Water Reserves. |
+AL: Aldrich's Ruby - dark cathedral, miniboss | Dropped by the Deep Accursed who drops down when you open the Anor Londo Cathedral shortcut |
+AL: Anri's Straight Sword - Anri quest | Dropped by Anri of Astora upon death or completing quest. In the Darkmoon Tomb with Lord of Hollows route, or given by Ludleth if summoned to defeat Aldrich. |
+AL: Blade of the Darkmoon - Yorshka with Darkmoon Loyalty | Given by Yorshka after learning the Darkmoon Loyalty gesture from Sirris, or by killing her |
+AL: Brass Armor - tomb | Behind the illusory statue in the hallway leading to the Darkmoon Tomb |
+AL: Brass Gauntlets - tomb | Behind the illusory statue in the hallway leading to the Darkmoon Tomb |
+AL: Brass Helm - tomb | Behind the illusory statue in the hallway leading to the Darkmoon Tomb |
+AL: Brass Leggings - tomb | Behind the illusory statue in the hallway leading to the Darkmoon Tomb |
+AL: Chameleon - tomb after marrying Anri | Dropped by the Stone-humped Hag assassin after Anri reaches the Church of Yorshka, either in the church or after marrying Anri |
+AL: Cinders of a Lord - Aldrich | Dropped by Aldrich |
+AL: Crescent Moon Sword - Leonhard drop | Drop by Ringfinger Leonhard upon death. Includes Soul of Rosaria if invaded in Anor Londo. |
+AL: Dark Stoneplate Ring - by dark stairs up from plaza | After the Pontiff fight, in the dark hallways to the left of the area with the Giant Slaves |
+AL: Deep Gem - water reserves | In the open in the Water Reserves |
+AL: Dragonslayer Greatarrow - drop from nearest buttress | Dropping down from about halfway down the flying buttress closest to the entrance to the Darkmoon Tomb |
+AL: Dragonslayer Greatbow - drop from nearest buttress | Dropping down from about halfway down the flying buttress closest to the entrance to the Darkmoon Tomb |
+AL: Drang Twinspears - plaza, NPC drop | Dropped by Drang Twinspears-wielding knight on the stairs leading up to the Anor Londo Silver Knights |
+AL: Easterner's Ashes - below top of furthest buttress | Dropping down from the rightmost flying buttress, or the rightmost set of stairs |
+AL: Ember - plaza, further | After the Pontiff fight, in the middle of the area with the Giant Slaves |
+AL: Ember - plaza, right side | After the Pontiff fight, next to one of the Giant Slaves on the right side |
+AL: Ember - spiral staircase, bottom | Next to the lever that summons the rotating Anor Londo stairs at the bottom |
+AL: Estus Shard - dark cathedral, by left stairs | In a chest on the floor of the Anor Londo cathedral |
+AL: Giant's Coal - by giant near dark cathedral | On the Giant Blacksmith's corpse in Anor Londo |
+AL: Golden Ritual Spear - light cathedral, mimic upstairs | Drop from a mimic in the higher levels of Pontiff's cathedral, accessible from the Deacons after the Pontiff fight |
+AL: Havel's Ring+2 - prison tower, rafters | On the rafters dropping down from Yorshka's Prison Tower to the Church of Yorshka |
+AL: Human Dregs - water reserves | In the open in the Water Reserves |
+AL: Large Soul of a Weary Warrior - left of dark cathedral entrance | In front of the Anor Londo cathedral, slightly to the left |
+AL: Large Titanite Shard - balcony by dead giants | After the Pontiff fight, on the balcony to the right of the area with the Giant Slaves |
+AL: Large Titanite Shard - bottom of the furthest buttress | At the base of the rightmost flying buttress leading up to Anor Londo |
+AL: Large Titanite Shard - bottom of the nearest buttress | On the tower leading back from Anor Londo to the shortcut to Irithyll, down the flying buttress closest to the Darkmoon Tomb entrance. |
+AL: Large Titanite Shard - right after light cathedral | After Pontiff's cathedral, hugging the wall to the right |
+AL: Large Titanite Shard - walkway, side path by cathedral | After the Pontiff fight, going back from the Deacons area to the original cathedral, before a dropdown |
+AL: Moonlight Arrow - dark cathedral, up right stairs | In the Anor Londo cathedral, up the stairs on the right side |
+AL: Painting Guardian Gloves - prison tower, rafters | On the rafters dropping down from Yorshka's Prison Tower to the Church of Yorshka |
+AL: Painting Guardian Gown - prison tower, rafters | On the rafters dropping down from Yorshka's Prison Tower to the Church of Yorshka |
+AL: Painting Guardian Hood - prison tower, rafters | On the rafters dropping down from Yorshka's Prison Tower to the Church of Yorshka |
+AL: Painting Guardian Waistcloth - prison tower, rafters | On the rafters dropping down from Yorshka's Prison Tower to the Church of Yorshka |
+AL: Painting Guardian's Curved Sword - prison tower rafters | On the rafters dropping down from Yorshka's Prison Tower to the Church of Yorshka |
+AL: Proof of a Concord Kept - dark cathedral, up left stairs | In the Anor Londo cathedral, halfway down the stairs on the left side next to some Deacons |
+AL: Reversal Ring - tomb, chest in corner | In a chest in Darkmoon Tomb |
+AL: Ring of Favor - water reserves, both minibosses | Dropped after killing both of Sulyvahn's Beasts in the Water Reserves |
+AL: Ring of Favor+1 - light cathedral, upstairs | In the higher levels of Pontiff's cathedral, accessible from the Deacons after the Pontiff fight |
+AL: Silver Mask - Leonhard drop | Drop by Ringfinger Leonhard upon death. Includes Soul of Rosaria if invaded in Anor Londo. |
+AL: Simple Gem - light cathedral, lizard upstairs | Dropped by a Crystal Lizard in the higher levels of Pontiff's cathedral, accessible from the Deacons after the Pontiff fight |
+AL: Soul of Aldrich | Dropped by Aldrich |
+AL: Soul of Rosaria - Leonhard drop | Drop by Ringfinger Leonhard upon death. Includes Soul of Rosaria if invaded in Anor Londo. |
+AL: Soul of a Crestfallen Knight - right of dark cathedral entrance | To the right of the Anor Londo cathedral entrance, past the red-eyed Silver Knight |
+AL: Soul of a Weary Warrior - plaza, nearer | After the Pontiff fight, in the middle of the area with the Giant Slaves |
+AL: Sun Princess Ring - dark cathedral, after boss | In the Anor Londo cathedral after defeating Aldrich, up the elevators in Gwynevere's Chamber |
+AL: Titanite Scale - top of ladder up to buttresses | On the platform after the stairs leading up to Anor Londo from the Water Reserves building |
+AL: Twinkling Titanite - lizard after light cathedral #1 | Dropped a Crystal Lizard straight after the Pontiff fight |
+AL: Twinkling Titanite - lizard after light cathedral #2 | Dropped a Crystal Lizard straight after the Pontiff fight |
+AL: Yorshka's Chime - kill Yorshka | Dropped by Yorshka upon death. |
+AP: Ancient Dragon Greatshield - intro, on archway | After the Archdragon Peak bonfire, on top of the arch in front of the Ancient Wyvern fight |
+AP: Calamity Ring - mausoleum, gesture at altar | Received using Path of the Dragon at the Altar by the Mausoleum bonfire |
+AP: Covetous Gold Serpent Ring+2 - plaza | In the Nameless King boss arena after he is defeated |
+AP: Dragon Chaser's Ashes - summit, side path | In the run-up to the Dragon Altar after the Belfry bonfire, in a side path to the left side |
+AP: Dragon Head Stone - fort, boss drop | Dropped by Ancient Wyvern |
+AP: Dragon Tooth - belfry roof, NPC drop | Dropped from any of the Havel Knights |
+AP: Dragonslayer Armor - plaza | In the Nameless King boss arena after he is defeated |
+AP: Dragonslayer Gauntlets - plaza | In the Nameless King boss arena after he is defeated |
+AP: Dragonslayer Helm - plaza | In the Nameless King boss arena after he is defeated |
+AP: Dragonslayer Leggings - plaza | In the Nameless King boss arena after he is defeated |
+AP: Dragonslayer Spear - gate after mausoleum | In the gate connecting the Dragon-Kin Mausoleum area to the bridge where the Nameless King fight takes place |
+AP: Drakeblood Greatsword - mausoleum, NPC drop | Dropped by the Drakeblood Knight summoned by the Serpent-Man Summoner |
+AP: Dung Pie - fort, landing after second room | On a landing going up the stairs from the Ancient Wyvern to the chainaxe Man-Serpent area |
+AP: Ember - belfry, below bell | In the area below the bell lever, either dropping down near the lever or going down the stairs from the open fountain area after the Belfry bonfire |
+AP: Ember - fort overlook #1 | From the right of where Ancient Wyvern first lands |
+AP: Ember - fort overlook #2 | From the right of where Ancient Wyvern first lands |
+AP: Ember - intro, by bonfire | Next to the Archdragon Peak bonfire |
+AP: Great Magic Barrier - drop off belfry roof | Dropping down to the left from the area with the Havel Knight and the dead Wyvern |
+AP: Havel's Greatshield - belfry roof, NPC drop | Dropped from any of the Havel Knights |
+AP: Havel's Ring+1 - summit, after building | Just past the building with all of the Man-Serpents on the way to the Dragon Altar, on the left side |
+AP: Homeward Bone - intro, path to bonfire | From the start of the area, along the left path leading to the first bonfire |
+AP: Large Soul of a Crestfallen Knight - summit, by fountain | In the middle of the open fountain area after the Belfry bonfire |
+AP: Large Soul of a Nameless Soldier - fort, by stairs to first room | to the left of where the Ancient Wyvern lands |
+AP: Large Soul of a Weary Warrior - fort, center | Where the Ancient Wyvern lands |
+AP: Lightning Bolt - rotunda | On top of the ruined dome found going up spiral stairs to the left before the bridge with the chainaxe Man-Serpent |
+AP: Lightning Clutch Ring - intro, left of boss door | To the left of gate leading to Ancient Wyvern, past the Rock Lizard |
+AP: Lightning Gem - intro, side rise | From the start of the area, up a ledge in between two forked paths toward the first bonfire |
+AP: Lightning Urn - fort, left of first room entrance | On the path to the left of where the Ancient Wyvern lands, left of the building entrance |
+AP: Ricard's Rapier - belfry, NPC drop | Dropped by the Richard Champion summoned by the Serpent-Man Summoner |
+AP: Ring of Steel Protection - fort overlook, beside stairs | To the right of the area where the Ancient Wyvern lands, dropping down onto the ledge |
+AP: Soul of a Crestfallen Knight - mausoleum, upstairs | From the Mausoleum bonfire, up the second set of stairs to the right |
+AP: Soul of a Nameless Soldier - intro, right before archway | From the Archdragon Peak bonfire, going right before the arch before Ancient Wyvern |
+AP: Soul of a Weary Warrior - intro, first cliff edge | At the very start of the area on the left cliff edge |
+AP: Soul of a Weary Warrior - walkway, building window | On the way to the Belfry bonfire after the sagging wooden bridge, on a ledge visible in a room with a Crystal Lizard, accessible by a tricky jump or just going around the other side |
+AP: Soul of the Nameless King | Dropped by Nameless King |
+AP: Stalk Dung Pie - fort overlook | From the right of where Ancient Wyvern first lands |
+AP: Thunder Stoneplate Ring - walkway, up ladder | After the long hallway after the Mausoleum bonfire, before the rope bridge, up the long ladder |
+AP: Titanite Chunk - fort, second room balcony | After going left of where Ancient Wyvern lands and left again, rather than going up the stairs to the right, go to the open area to the left |
+AP: Titanite Chunk - intro, archway corner | From the Archdragon Peak bonfire, under the arch, immediately to the right |
+AP: Titanite Chunk - intro, behind rock | Almost at the Archdragon Peak bonfire, behind a rock in the area with many Man-Serpents |
+AP: Titanite Chunk - intro, left before archway | After the Archdragon Peak bonfire, going left before the arch before Ancient Wyvern |
+AP: Titanite Chunk - rotunda | On top of the ruined dome found going up spiral stairs to the left before the bridge with the chainaxe Man-Serpent |
+AP: Titanite Chunk - walkway, miniboss drop | Dropped by the second Ancient Wyvern patrolling the path up to the Belfry |
+AP: Titanite Scale - mausoleum, downstairs balcony #1 | From the Mausoleum bonfire, up the stairs to the left, past the Rock Lizard |
+AP: Titanite Scale - mausoleum, downstairs balcony #2 | From the Mausoleum bonfire, up the stairs to the left, past the Rock Lizard |
+AP: Titanite Scale - mausoleum, upstairs balcony | From the Mausoleum bonfire, up the first stairs to the right, going around toward the Man-Serpent Summoner, on the balcony on the side |
+AP: Titanite Scale - walkway building | In a chest after the sagging wooden bridge on the way to the Belfry, in the building with the Crystal Lizard |
+AP: Titanite Scale - walkway, miniboss drop | Dropped by the second Ancient Wyvern patrolling the path up to the Belfry |
+AP: Titanite Slab - belfry roof | Next to the Havel Knight by the dead Wyvern |
+AP: Titanite Slab - plaza | In the Nameless King boss arena after he is defeated |
+AP: Twinkling Dragon Torso Stone - summit, gesture at altar | Received using Path of the Dragon at the Altar after the Belfry bonfire. Hawkwood also uses the gesture there when summoned. |
+AP: Twinkling Titanite - belfry, by ladder to roof | In the chest before the ladder climbing up to the Havel Knight |
+AP: Twinkling Titanite - fort, down second room balcony ladder | After going left of where Ancient Wyvern lands and left again, rather than going up the stairs to the right, go to the open area to the left and then down the ladder |
+AP: Twinkling Titanite - fort, end of rafters | Dropping down to the left of the Mausoleum bonfire, all the way down the wooden rafters |
+AP: Twinkling Titanite - walkway building, lizard | Dropped by Crystal Lizard in the building after the sagging wooden bridge toward the Belfry |
+AP: Twinkling Titanite - walkway, miniboss drop | Dropped by the second Ancient Wyvern patrolling the path up to the Belfry |
+CA: Coiled Sword - boss drop | Dropped by Iudex Gundyr |
+CA: Firebomb - down the cliff edge | Along the cliff edge before the Iudex Gundyr fight, to the right |
+CA: Soul of a Deserted Corpse - right of spawn | At the very start of the game |
+CA: Soul of an Unknown Traveler - by miniboss | In the area with the Ravenous Crystal Lizard |
+CA: Speckled Stoneplate Ring+1 - by miniboss | In the area with the Ravenous Crystal Lizard, along the right wall |
+CA: Titanite Scale - miniboss drop | Dropped by Ravenous Crystal Lizard |
+CA: Titanite Shard - jump to coffin | Making a jump to a coffin after the Cemetery of Ash bonfire |
+CC: Black Blade - tomb, mimic | Dropped by the mimic before Smouldering Lake |
+CC: Black Bug Pellet - cavern, before bridge | In the area where many many skeletons are before the bridge you can cut |
+CC: Bloodred Moss Clump - atrium lower, down more stairs | To the left before going down the main stairwell in the Catacombs, past the skeleton ambush and where Anri is standing, near the Crystal Lizard |
+CC: Carthus Bloodring - crypt lower, end of side hall | At the very end of the Bonewheel Skeleton area |
+CC: Carthus Milkring - crypt upper, among pots | After the first Skeleton Ball, in the hallway alcove with the many dark-exploding pots |
+CC: Carthus Pyromancy Tome - atrium lower, jump from bridge | Down the hallway to the right before going down the main stairwell in the Catacombs and through an illusory wall on the left, or making a difficult dropdown from the top-level platform |
+CC: Carthus Rouge - atrium upper, left after entrance | To the right after first entering the Catacombs |
+CC: Carthus Rouge - crypt across, corner | Making a difficult jump between the hallway after the first Skeleton Ball and the area at the same level on the opposite side, or going up the stairs from the main hall |
+CC: Dark Gem - crypt lower, skeleton ball drop | Dropped by second Skeleton Ball after killing its sorcerer skeleton |
+CC: Ember - atrium, on long stairway | On the main stairwell in Catacombs |
+CC: Ember - crypt lower, shortcut to cavern | In the short hallway with the level shortcut where Knight Slayer Tsorig invades |
+CC: Ember - crypt upper, end of hall past hole | Going right from the Catacombs bonfire, down the hall to the left, then to the right. After a hole that drops down into the Bonewheel Skeleton area. |
+CC: Fire Gem - cavern, lizard | Dropped by a Crystal Lizard found between the Catacombs main halls and the ledge overlooking the bridge you can cut down |
+CC: Grave Warden Pyromancy Tome - boss arena | In Wolnir's arena, or in the back left of the room containing his bonfire if not picked up in the arena |
+CC: Grave Warden's Ashes - crypt across, corner | From the Catacombs bonfire, down the stairs into the main hall and up the stairs to the other side, on the far left side. Stairwell past the illusory wall is most direct. |
+CC: Homeward Bone - Irithyll bridge | Found right before the wall blocking access to Irithyll |
+CC: Large Soul of a Nameless Soldier - cavern, before bridge | In the area where many many skeletons are before the bridge you can cut |
+CC: Large Soul of a Nameless Soldier - tomb lower | Down the ramp from the Fire Demon, where all the skeletons are |
+CC: Large Soul of an Unknown Traveler - crypt upper, hall middle | Going right from the Catacombs bonfire, then down the long hallway after the hallway to the left |
+CC: Large Titanite Shard - crypt across, middle hall | From the Catacombs bonfire, down the stairs into the main hall and up the stairs to the other side, in a middle hallway |
+CC: Large Titanite Shard - crypt upper, skeleton ball hall | Going right from the Catacombs bonfire, to the end of the hallway where second Skeleton Ball rolls |
+CC: Large Titanite Shard - tomb lower | Down the ramp from the Fire Demon, where all the skeletons are |
+CC: Old Sage's Blindfold - tomb, hall before bonfire | Down the ramp from the Fire Demon, straight down the hallway past the room with the Abandoned Tomb bonfire |
+CC: Pontiff's Right Eye - Irithyll bridge, miniboss drop | Dropped by killing Sulyvahn's Beast on the bridge to Irithyll or in the lake below |
+CC: Ring of Steel Protection+2 - atrium upper, drop onto pillar | From the first bridge in Catacombs where the first skeletons are encountered, parallel to the long stairwell, walk off onto a pillar on the left side. |
+CC: Sharp Gem - atrium lower, right before exit | Down the hallway to the right before going down the main stairwell in the Catacombs |
+CC: Soul of High Lord Wolnir | Dropped by High Lord Wolnir |
+CC: Soul of a Demon - tomb, miniboss drop | Dropped by the Fire Demon before Smouldering Lake |
+CC: Soul of a Nameless Soldier - atrium lower, down hall | All the way down the hallway to the right before going down the main stairwell in the Catacombs |
+CC: Soul of a Nameless Soldier - atrium upper, up more stairs | From the room before the Catacombs main stairwell, up the two ramps and to the end of the long hallway crossing the room |
+CC: Thunder Stoneplate Ring+1 - crypt upper, among pots | After the first Skeleton Ball, in the hallway alcove with the many dark-exploding pots, behind one of the pillars |
+CC: Titanite Shard - atrium lower, corner by stairs | To the left before going down the main stairwell in the Catacombs, behind the pensive Carthus Cursed Sword Skeleton |
+CC: Titanite Shard - crypt lower, left of entrance | In the main hall after the Catacombs bonfire, down the stairs and to the left |
+CC: Titanite Shard - crypt lower, start of side hall | In the Bonewheel Skeleton area, on the left side under a Writhing Flesh |
+CC: Twinkling Titanite - atrium lower, lizard down more stairs | Dropped by a Crystal Lizard found to the left before going down the main stairwell in the Catacombs, past the skeleton ambush and past where Anri is standing |
+CC: Undead Bone Shard - crypt upper, skeleton ball drop | Dropped by first Skeleton Ball after killing its sorcerer skeleton |
+CC: Witch's Ring - tomb, hall before bonfire | Down the ramp from the Fire Demon, straight down the hallway past the room with the Abandoned Tomb bonfire |
+CC: Yellow Bug Pellet - cavern, on overlook | To the right of the Carthus Curved Sword Skeleton overlooking the pit Horace falls into |
+CD: Aldrich's Sapphire - side chapel, miniboss drop | Dropped by the Deep Accursed |
+CD: Arbalest - upper roofs, end of furthest buttress | Before the rafters on the way to Rosaria, up a flying buttress, past a halberd-wielding Large Hollow Soldier to the right, and down another flying buttress to the right |
+CD: Archdeacon Holy Garb - boss room after killing boss | Near the Deacons of the Deep bonfire, found after resting at it |
+CD: Archdeacon Skirt - boss room after killing boss | Near the Deacons of the Deep bonfire, found after resting at it |
+CD: Archdeacon White Crown - boss room after killing boss | Near the Deacons of the Deep bonfire, found after resting at it |
+CD: Armor of Thorns - Rosaria's Bed Chamber after killing Kirk | Found in Rosaria's Bed Chamber after killing Longfinger Kirk |
+CD: Astora Greatsword - graveyard, left of entrance | Down one of the side paths to the left in the Reanimated Corpse area |
+CD: Barbed Straight Sword - Kirk drop | Dropped by Longfinger Kirk when he invades in the cathedral central room |
+CD: Black Eye Orb - Rosaria from Leonhard's quest | On Rosaria's corpse after joining Rosaria's Fingers, exhausting Leonhard's dialogue there and reaching the Profaned Capital bonfire. |
+CD: Blessed Gem - upper roofs, rafters | In the rafters leading to Rosaria, guarded by a Cathedral Knight to the right |
+CD: Crest Shield - path, drop down by Cathedral of the Deep bonfire | On a grave near the Cathedral of the Deep bonfire, accessed by dropping down to the right |
+CD: Curse Ward Greatshield - by ladder from white tree to moat | Taking a right after the Infested Corpse graveyard, before the shortcut ladder down to the Ravenous Crystal Lizard area |
+CD: Deep Braille Divine Tome - mimic by side chapel | Dropped by the Mimic before the room with the patrolling Cathedral Knight and Deep Accursed |
+CD: Deep Gem - down stairs by first elevator | Coming from the room where you first see deacons, go down instead of continuing to the main cathedral room. Guarded by a pensive Cathedral Evangelist. |
+CD: Deep Ring - upper roofs, passive mob drop in first tower | Dropped by the passive Deacon on the way to Rosaria |
+CD: Drang Armor - main hall, east | In the Giant Slave muck pit leading up to Deacons |
+CD: Drang Gauntlets - main hall east | In the Giant Slave muck pit leading up to Deacons |
+CD: Drang Hammers - main hall east | In the Giant Slave muck pit leading up to Deacons, underneath the stairwell |
+CD: Drang Shoes - main hall east | In the Giant Slave muck pit leading up to Deacons |
+CD: Duel Charm - by first elevator | After opening the cathedral's backdoor, where the Deacon enemies are first seen, under a fountain that spouts poison |
+CD: Duel Charm - next to Patches in onion armor | To the right of the bridge leading to Rosaria, from the Deacons side. Patches will lower the bridge if you try to cross from this side. |
+CD: Ember - Patches | Sold by Patches in Firelink Shrine |
+CD: Ember - by back door | Past the pair of Grave Wardens and the Cathedral backdoor against a wall, guarded by a greataxe-wielding Large Hollow Soldier |
+CD: Ember - edge of platform before boss | On the edge of the chapel before Deacons overlooking the Giant Slaves |
+CD: Ember - side chapel upstairs, up ladder | Up a ladder and past the Cathedral Evangelist from the top level of the room with the patrolling Cathedral Knight and Deep Accursed |
+CD: Ember - side chapel, miniboss room | In the room with the Deep Accursed |
+CD: Estus Shard - monument outside Cleansing Chapel | Right outside of the Cleansing Chapel. Requires killing praying hollows. |
+CD: Executioner's Greatsword - graveyard, far end | In an open area down one of the side paths to the left in the Reanimated Corpse area |
+CD: Exploding Bolt - ledge above main hall south | On the ledge where the Giant Slave slams his arms down |
+CD: Fading Soul - graveyard, far end | In an open area down one of the side paths to the left in the Reanimated Corpse area, next to the Executioner's Greatsword |
+CD: Gauntlets of Thorns - Rosaria's Bed Chamber after killing Kirk | Found in Rosaria's Bed Chamber after killing Longfinger Kirk |
+CD: Helm of Thorns - Rosaria's Bed Chamber after killing Kirk | Found in Rosaria's Bed Chamber after killing Longfinger Kirk |
+CD: Herald Armor - path, by fire | Guarded by the Cathedral Evangelist after the Crystal Sage fight |
+CD: Herald Gloves - path, by fire | Guarded by the Cathedral Evangelist after the Crystal Sage fight |
+CD: Herald Helm - path, by fire | Guarded by the Cathedral Evangelist after the Crystal Sage fight |
+CD: Herald Trousers - path, by fire | Guarded by the Cathedral Evangelist after the Crystal Sage fight |
+CD: Heysel Pick - Heysel Corpse-Grub in Rosaria's Bed Chamber | Dropped by the Heysel Corpse-grub in Rosaria's Bed Chamber |
+CD: Homeward Bone - outside main hall south door | Past the cathedral doors guarded by the Giant Slave opposite to the Deacons fight |
+CD: Horsehoof Ring - Patches | Sold or dropped by Patches after he mentions Greirat |
+CD: Large Soul of an Unknown Traveler - by white tree #1 | In the graveyard with the White Birch and Infested Corpses |
+CD: Large Soul of an Unknown Traveler - by white tree #2 | In the graveyard with the White Birch and Infested Corpses |
+CD: Large Soul of an Unknown Traveler - lower roofs, semicircle balcony | On the cathedral roof after climbing up the flying buttresses, on the edge of the semicircle platform balcony |
+CD: Large Soul of an Unknown Traveler - main hall east | In the Giant Slave muck pit leading up to Deacons |
+CD: Large Soul of an Unknown Traveler - main hall south, side path | Down a side path with poison-spouting fountains in the main cathedral room, accessible from the Cleansing Chapel shortcut, patrolled by a Cathedral Knight |
+CD: Large Soul of an Unknown Traveler - path, against outer wall | From the Cathedral of the Deep bonfire after the Brigand, against the wall in the area with the dogs and crossbowmen |
+CD: Leggings of Thorns - Rosaria's Bed Chamber after killing Kirk | Found in Rosaria's Bed Chamber after killing Longfinger Kirk |
+CD: Lloyd's Sword Ring - ledge above main hall south | On the ledge where the Giant Slave slams his arms down |
+CD: Maiden Gloves - main hall south | In the muck pit with the Giant Slave that can attack with his arms |
+CD: Maiden Hood - main hall south | In the muck pit with the Giant Slave that can attack with his arms |
+CD: Maiden Robe - main hall south | In the muck pit with the Giant Slave that can attack with his arms |
+CD: Maiden Skirt - main hall south | In the muck pit with the Giant Slave that can attack with his arms |
+CD: Notched Whip - Cleansing Chapel | In a corner of the Cleansing Chapel |
+CD: Paladin's Ashes - path, guarded by lower NPC | At the very start of the area, guarded by the Fallen Knight |
+CD: Pale Tongue - main hall east | In the Giant Slave muck pit leading up to Deacons |
+CD: Pale Tongue - upper roofs, outdoors far end | Before the rafters on the way to Rosaria, up a flying buttress and straight right, passing a halberd-wielding Large Hollow Soldier |
+CD: Poisonbite Ring - moat, hall past miniboss | In the pit with the Infested Corpse, accessible from the Ravenous Crystal Lizard area or from dropping down near the second Cleansing Chapel shortcut |
+CD: Red Bug Pellet - lower roofs, up stairs between buttresses | In the area after the cathedral roof against the wall of the cathedral, down the path from the Cathedral Evangelist. |
+CD: Red Bug Pellet - right of cathedral front doors | Up the stairs past the Infested Corpse graveyard and the left, toward the roof path to the right of the cathedral doors |
+CD: Red Sign Soapstone - passive mob drop by Rosaria's Bed Chamber | Dropped by passive Corpse-grub against the wall near the entrance to Rosaria's Bed Chamber |
+CD: Repair Powder - by white tree | In the graveyard with the White Birch and Infested Corpses |
+CD: Ring of Favor+2 - upper roofs, on buttress | Before the rafters on the way to Rosaria, up a flying buttress, behind a greataxe-wielding Large Hollow Soldier to the left |
+CD: Ring of the Evil Eye+1 - by stairs to boss | Before the stairs leading down into the Deacons fight |
+CD: Rosaria's Fingers - Rosaria | Given by Rosaria. |
+CD: Rusted Coin - don't forgive Patches | Given by Patches after not forgiving him after he lowers the bridge in Cathedral of the Deep. |
+CD: Rusted Coin - left of cathedral front doors, behind crates | Up the stairs past the Infested Corpse graveyard and to the left, hidden behind some crates to the left of the cathedral door |
+CD: Saint Bident - outside main hall south door | Past the cathedral doors guarded by the Giant Slave opposite to the Deacons fight |
+CD: Saint-tree Bellvine - moat, by water | In the Infested Corpse moat beneath the Cathedral |
+CD: Seek Guidance - side chapel upstairs | Above the room with the patrolling Cathedral Knight and Deep Accursed, below a writhing flesh on the ceiling. |
+CD: Shotel - Patches | Sold by Patches |
+CD: Small Doll - boss drop | Dropped by Deacons of the Deep |
+CD: Soul of a Nameless Soldier - ledge above main hall south | On the ledge where the Giant Slave slams his arms down |
+CD: Soul of a Nameless Soldier - lower roofs, side room | Coming from the cathedral roof, past the three crossbowmen to the path patrolled by the halberd-wielding Large Hollow Soldier, in a room to the left with many thralls. |
+CD: Soul of a Nameless Soldier - main hall south | In the muck pit with the Giant Slave that can attack with his arms |
+CD: Soul of the Deacons of the Deep | Dropped by Deacons of the Deep |
+CD: Spider Shield - NPC drop on path | Dropped by the brigand at the start of Cathedral of the Deep |
+CD: Spiked Shield - Kirk drop | Dropped by Longfinger Kirk when he invades in the cathedral central room |
+CD: Titanite Scale - moat, miniboss drop | Dropped by the Ravenous Crystal Lizard outside of the Cathedral |
+CD: Titanite Shard - Cleansing Chapel windowsill, by miniboss | On the ledge dropping back down into Cleansing Chapel from the area with the Ravenous Crystal Lizard |
+CD: Titanite Shard - moat, far end | Behind the cathedral near the Infested Corpse moat, going from the Ravenous Crystal Lizard |
+CD: Titanite Shard - moat, up a slope | Up one of the slopes in the Ravenous Crystal Lizard area |
+CD: Titanite Shard - outside building by white tree | Past the Infested Corpse graveyard to the left, hidden along the left wall of the building with the shortcut ladder and Curse Ward Greatshield |
+CD: Titanite Shard - path, side path by Cathedral of the Deep bonfire | Up a path to the left after the Cathedral of the Deep bonfire, after the Fallen Knight and before the Brigand |
+CD: Twinkling Titanite - moat, lizard #1 | Dropped by the Crystal Lizard behind the cathedral near the Infested Corpse moat, going from the Ravenous Crystal Lizard |
+CD: Twinkling Titanite - moat, lizard #2 | Dropped by the Crystal Lizard under the cathedral near the Infested Corpse moat, going from the Ravenous Crystal Lizard |
+CD: Twinkling Titanite - path, lizard #1 | Dropped by the first Crystal Lizard after the Crystal Sage fight |
+CD: Twinkling Titanite - path, lizard #2 | Dropped by the second Crystal Lizard after the Crystal Sage fight |
+CD: Undead Bone Shard - gravestone by white tree | In the graveyard with the Infested Corpses, on a coffin partly hanging off of the ledge |
+CD: Undead Hunter Charm - lower roofs, up stairs between buttresses | In the area after the cathedral roof guarded by a Cathedral Evangelist. Can be jumped to from a flying buttress or by going around and back |
+CD: Winged Spear - kill Patches | Dropped by Patches when killed in his own armor. |
+CD: Xanthous Crown - Heysel Corpse-Grub in Rosaria's Bed Chamber | Dropped by the Heysel Corpse-grub in Rosaria's Bed Chamber |
+CD: Young White Branch - by white tree #1 | By the White Birch tree in the Infested Corpse graveyard |
+CD: Young White Branch - by white tree #2 | By the White Birch tree in the Infested Corpse graveyard |
+CKG: Black Firebomb - under rotunda | Under the platform in the middle of the garden, in the toxic pool |
+CKG: Claw - under rotunda | Under the platform in the middle of the garden, in the toxic pool |
+CKG: Dark Gem - under lone stairway | Following the left wall, behind the standalone set of stairs |
+CKG: Dragonscale Ring - shortcut, leave halfway down lift | From the middle level of the second elevator, toward the Oceiros boss fight |
+CKG: Drakeblood Armor - tomb, after killing AP mausoleum NPC | On the Drakeblood Knight after Oceiros fight, after defeating the Drakeblood Knight from the Serpent-Man Summoner |
+CKG: Drakeblood Gauntlets - tomb, after killing AP mausoleum NPC | On the Drakeblood Knight after Oceiros fight, after defeating the Drakeblood Knight from the Serpent-Man Summoner |
+CKG: Drakeblood Helm - tomb, after killing AP mausoleum NPC | On the Drakeblood Knight after Oceiros fight, after defeating the Drakeblood Knight from the Serpent-Man Summoner |
+CKG: Drakeblood Leggings - tomb, after killing AP mausoleum NPC | On the Drakeblood Knight after Oceiros fight, after defeating the Drakeblood Knight from the Serpent-Man Summoner |
+CKG: Estus Shard - balcony | From the middle level of the first Consumed King's Gardens elevator, out the balcony and to the right |
+CKG: Human Pine Resin - by lone stairway bottom | On the right side of the garden, following the wall past the entrance to the shortcut elevator building, in a toxic pool |
+CKG: Human Pine Resin - toxic pool, past rotunda | In between two platforms near the middle of the garden, by a tree in a toxic pool |
+CKG: Magic Stoneplate Ring - mob drop before boss | Dropped by the Cathedral Knight closest to the Oceiros fog gate |
+CKG: Ring of Sacrifice - under balcony | Along the right wall of the garden, next to the first elevator building |
+CKG: Sage Ring+2 - balcony, drop onto rubble, jump back | From the middle platform of the first elevator in the target, going out and dropping off to the left, and then running off onto the ruined arch behind. |
+CKG: Shadow Garb - under rotunda | Under the platform in the middle of the garden, in the toxic pool |
+CKG: Shadow Gauntlets - under rotunda | Under the platform in the middle of the garden, in the toxic pool |
+CKG: Shadow Leggings - under rotunda | Under the platform in the middle of the garden, in the toxic pool |
+CKG: Shadow Mask - under center platform | Under the platform in the middle of the garden, in the toxic pool |
+CKG: Soul of Consumed Oceiros | Dropped by Consumed King Oceiros |
+CKG: Soul of a Weary Warrior - before first lift | On the path leading to the first elevator from Lothric Castle |
+CKG: Titanite Chunk - balcony, drop onto rubble | From the middle platform of the first elevator, dropping down to the left |
+CKG: Titanite Chunk - right of shortcut lift bottom | On the right side of the garden, following the wall past the entrance to the shortcut elevator building, all the way to the end |
+CKG: Titanite Chunk - shortcut | Right inside of the shortcut door leading to Oceiros from Lothric/Dancer bonfire |
+CKG: Titanite Chunk - up lone stairway | Following the left wall of the garden, in and up the standalone set of stairs |
+CKG: Titanite Scale - shortcut | In the room leading to the Oceiros shortcut elevator from Lothric/Dancer, in the first floor alcove. |
+CKG: Titanite Scale - tomb, chest #1 | Chest after Oceiros fight |
+CKG: Titanite Scale - tomb, chest #2 | Chest after Oceiros fight |
+CKG: Wood Grain Ring+1 - by first elevator bottom | Behind the first elevator going down into the garden, in the toxic pool |
+DH: Aquamarine Dagger - castle, up stairs | Up the second flight of stairs to the left of the starting area with the murkmen, before the long drop |
+DH: Black Firebomb - ruins, up windmill from bonfire | To the left of the Earthen Peak Ruins bonfire, past the ruined windmill, next to many Poisonhorn bugs. |
+DH: Covetous Silver Serpent Ring+3 - pantry upstairs, drop down | After exiting the building with the Lothric Knights where the front crumbles, to the last room of the building to the right, up stairs past an illusory wall to the left, then dropping down after exiting the building from the last room. |
+DH: Desert Pyromancer Garb - ruins, by shack near cliff | Behind a shack near the edge of the cliff of the area targeted by the second angel. |
+DH: Desert Pyromancer Gloves - swamp, far right | After dropping down in the poison swamp area, against the wall straight to the right. |
+DH: Desert Pyromancer Hood - swamp upper, tunnel end | At the end of the tunnel with Desert Pyromancy Zoey, to the right of the final branches. |
+DH: Desert Pyromancer Skirt - swamp right, by roots | In the poison swamp, against a tree guarded by a few Poisonhorn bugs in the front right. |
+DH: Divine Blessing - library, after drop | After the dropdown where an angel first targets you, behind you |
+DH: Divine Blessing - shop | Sold by Stone-humped Hag, or in her ashes |
+DH: Divine Blessing - swamp upper, building roof | On a rooftop of one of the buildings bordering the poison swamp. Can be reached by dropping down from the final tree branch and accessing the roof to the right. |
+DH: Ember - castle, behind spire | At the start of the area, behind a spire to the right of first drop down |
+DH: Ember - pantry, behind crates just before upstairs | After exiting the building with the Lothric Knights where the front crumbles, to the last room end of the building to the right, up stairs past an illusory wall to the left, in the second-to-last room of the sequence, behind some crates to the left. |
+DH: Ember - ruins, alcove before swamp | In an alcove providing cover from the second angel's projectiles, before dropping down in the poison swamp area. |
+DH: Ember - ruins, alcove on cliff | In the area with the pilgrim responsible for the second angel, below the Within Earthen Peak Ruins bonfire. Can be accessed by dropping down from a cliff edge, dropping down to the right of the bonfire. |
+DH: Ember - shop | Sold by Stone-humped Hag, or in her ashes |
+DH: Flame Fan - swamp upper, NPC drop | Dropped by Desert Pyromancer Zoey |
+DH: Giant Door Shield - ruins, path below far shack | Descending down a path from the edge of the cliff of the area targeted by the second angel, to the very end of the cliff. |
+DH: Great Soul Dregs - pantry upstairs | After exiting the building with the Lothric Knights where the front crumbles, to the last room of the building to the right, up stairs past an illusory wall to the left, then all the way to the end of the last room. |
+DH: Harald Curved Greatsword - swamp left, under root | In the back leftmost area of the poison swamp, underneath the tree branch leading up and out, guarded by a stationary Harald Legion Knight. |
+DH: Hidden Blessing - shop | Sold by Stone-humped Hag, or in her ashes |
+DH: Homeward Bone - end of path from church | Immediately before dropping into the area with the Earthen Peak Ruins bonfire, next to Gael's flag. |
+DH: Homeward Bone - swamp left, on root | All the way to the end of a short path in the back leftmost area of the poison swamp, where you can plunge attack the stationary Harald Legion Knight. |
+DH: Large Soul of a Weary Warrior - parapets, hall | After crossing the spire bridge that crashes into the building with the Lothric Knights, past Lapp's initial location, dropping down behind the murkman and dropping down again, in a corner to the left. |
+DH: Large Soul of a Weary Warrior - swamp center | In the middle of the poison swamp. |
+DH: Large Soul of a Weary Warrior - swamp, under overhang | In the cavern adjacent to the poison swamp, surrounded by a few Poisonhorn bugs. |
+DH: Lightning Urn - wall outside church | After the dropdown where an angel first targets you, against the wall on the left. |
+DH: Loincloth - swamp, left edge | In the leftmost edge of the poison swamp after dropping down, guarded by 6 Poisonhorn bugs. |
+DH: Lothric War Banner - parapets, end of hall | After crossing the spire bridge that crashes into the building with the Lothric Knights, past Lapp's initial location, dropping down behind the murkman and dropping down again, at the end of the hallway to the right. |
+DH: Murky Hand Scythe - library, behind bookshelves | After the first long drop into the building which looks like Grand Archives, to the left up the bookshelf stairs and behind the bookshelves |
+DH: Murky Longstaff - pantry, last room | After exiting the building with the Lothric Knights where the front crumbles, in the third-furthest room in the building to the right. |
+DH: Prism Stone - swamp upper, tunnel start | Near the start of the tunnel with Desert Pyromancer Zoey. |
+DH: Projected Heal - parapets balcony | After crossing the spire bridge that crashes into the building with the Lothric Knights, past Lapp's initial location, dropping down behind the murkman, against a wall in the area with the Lothric War Banner Knight and many murkmen. |
+DH: Purple Moss Clump - swamp shack | In the ruined shack with Poisonhorn bugs straight ahead of the dropdown into the poison swamp area. |
+DH: Ring of Favor+3 - swamp right, up root | Up the long branch close to the dropdown into the poison swamp area, in front of the cavern. |
+DH: Ring of Steel Protection+3 - ledge before church | After the dropdown where an angel first targets you, on an exposed edge to the left. Difficult to get without killing the angel. |
+DH: Rusted Coin - behind fountain after church | After exiting the building with the Lothric Knights where the front crumbles, behind the fountain on the right side. |
+DH: Rusted Gold Coin - shop | Sold by Stone-humped Hag, or in her ashes |
+DH: Siegbräu - Lapp | Given by Lapp after collecting the Titanite Slab in Earthen Peak Ruins, or left after Demon Princes fight, or dropped upon death if not given. |
+DH: Small Envoy Banner - boss drop | Found in the small room after beating Demon Prince. |
+DH: Soul of a Crestfallen Knight - church, altar | In the building where the front crumbles, guarded by the two Lothric Knights at the front of the chapel. |
+DH: Soul of a Weary Warrior - castle overhang | The bait item at the start of the area which falls down with you into the ruined building below. |
+DH: Soul of the Demon Prince | Dropped by Demon Prince |
+DH: Splitleaf Greatsword - shop | Sold by Stone-humped Hag, or in her ashes |
+DH: Titanite Chunk - castle, up stairs | Up first flight of stairs to the left of the starting area with the murkmen, before the long drop |
+DH: Titanite Chunk - pantry, first room | After exiting the building with the Lothric Knights where the front crumbles, on a ledge in the first room of the building to the right. |
+DH: Titanite Chunk - path from church, by pillar | Before dropping into the area with the Earthen Peak Ruins bonfire, behind a pillar in front of a murkman pool. |
+DH: Titanite Chunk - ruins, by far shack | In front of a shack at the far edge of the cliff of the area targeted by the second angel. There is a shortcut dropdown to the left of the building. |
+DH: Titanite Chunk - ruins, path from bonfire | At the Earthen Peak Ruins bonfire, straight a bit then all the way left, near the edge of the cliff in the area targeted by the second angel. |
+DH: Titanite Chunk - swamp right, drop partway up root | Partway up the long branch close to the dropdown into the poison swamp area, in front of the cavern, dropping down to a branch to the left. |
+DH: Titanite Chunk - swamp, along buildings | After dropping down into the poison swamp, along the buildings on the left side. |
+DH: Titanite Chunk - swamp, path to upper | Partway up the branch that leads out of the poison swamp, on a very exposed branch jutting out to the left. |
+DH: Titanite Scale - library, back of room | After the first long drop into the building which looks like Grand Archives, behind you at the back of the room |
+DH: Titanite Scale - swamp upper, drop and jump into tower | At the very end of the last tree branch before dropping down toward the Within Earthen Peak Ruins bonfire, drop down to the left instead. Make a jump into the interior of the overturned tower to the left. |
+DH: Titanite Slab - swamp, path under overhang | Deep within the cavern adjacent to the poison swamp, to the back and then left. Alternatively, given by Lapp after exhausting dialogue near the bonfire and dying, or left after he moves on, or dropped upon death if not given. |
+DH: Twinkling Titanite - library, chandelier | After the first long drop into the building which looks like Grand Archives, straight ahead hanging from a chandelier on the ground |
+DH: Twinkling Titanite - path after church, mob drop | Dropped the pilgrim responsible for the first angel encountered, below the spire bridge that forms by crashing into the building. |
+DH: Twinkling Titanite - ruins, alcove on cliff, mob drop | Dropped by the pilgrim responsible for the second angel, below the Within Earthen Peak Ruins bonfire. Can be accessed by dropping down from a cliff edge, or dropping down to the right of the bonfire. |
+DH: Twinkling Titanite - ruins, root near bonfire | Treasure visible straight ahead of the Earthen Peak Ruins bonfire on a branch. Can be accessed by following the right wall from the bonfire until a point of access onto the branch is found. |
+DH: Twinkling Titanite - swamp upper, drop onto root | On the final tree branches before dropping down toward the Within Earthen Peak Ruins bonfire, drop down on a smaller branch to the right. This loops back to the original branch. |
+DH: Twinkling Titanite - swamp upper, mob drop on roof | Dropped by the pilgrim responsible for the third angel in the swamp. Rather than heading left into the tunnel with Desert Pyromancy Zoey, go right onto a shack roof. Drop down onto a tree branch at the end, then drop down to another roof. |
+FK: Antiquated Dress - hidden cave | In a chest in the cave found along the keep wall in the basilisk area, with the Elizabeth corpse |
+FK: Antiquated Gloves - hidden cave | In a chest in the cave found along the keep wall in the basilisk area, with the Elizabeth corpse |
+FK: Antiquated Skirt - hidden cave | In a chest in the cave found along the keep wall in the basilisk area, with the Elizabeth corpse |
+FK: Atonement - perimeter, drop down into swamp | Dropping down from the Farron Keep Perimeter building, to the right past the bonfire, before the stairs going up |
+FK: Black Bow of Pharis - miniboss drop, by keep ruins near wall | Dropped the Elder Ghru on the left side of the group of three to the left of the Keep Ruins bonfire, as approached from the ritual fire. |
+FK: Black Bug Pellet - perimeter, hill by boss door | On the small hill to the right of the Abyss Watchers entrance, guarded by a spear-wielding Ghru Grunt |
+FK: Cinders of a Lord - Abyss Watcher | Dropped by Abyss Watchers |
+FK: Crown of Dusk - by white tree | Near the swamp birch tree patrolled by the greater crab, where the Giant shoots arrows |
+FK: Dark Stoneplate Ring+2 - keep ruins ritual island, behind wall | Hidden behind the right wall of the ritual fire before Keep Ruins |
+FK: Dragon Crest Shield - upper keep, far side of the wall | Up the elevator from Old Wolf of Farron bonfire, and dropping down to Crystal Lizard area, in the open. |
+FK: Dreamchaser's Ashes - keep proper, illusory wall | Near the Old Wolf of Farron bonfire, behind an illusory wall near the Crystal Lizard |
+FK: Ember - by white tree | Near the swamp birch tree patrolled by the greater crab, where the Giant shoots arrows |
+FK: Ember - perimeter, path to boss | Guarded by a spear-wielding Ghru Grunt to the right of the main path leading up to Abyss Watchers |
+FK: Ember - upper keep, by miniboss #1 | Guarded by Stray Demon, up from the Old Wolf of Farron bonfire |
+FK: Ember - upper keep, by miniboss #2 | Guarded by Stray Demon, up from the Old Wolf of Farron bonfire |
+FK: Estus Shard - between Farron Keep bonfire and left island | Straight ahead from the Farron Keep bonfire to the ritual fire stairs, guarded by a slug |
+FK: Gold Pine Bundle - by white tree | Near the swamp birch tree patrolled by the greater crab, where the Giant shoots arrows |
+FK: Golden Scroll - hidden cave | In a cave found along the keep wall in the basilisk area, with the Elizabeth corpse |
+FK: Great Magic Weapon - perimeter, by door to Road of Sacrifices | Next to the shortcut leading from Farron Keep Perimeter back into Crucifixion Woods, past the Ravenous Crystal Lizard |
+FK: Greataxe - upper keep, by miniboss | Guarded by Stray Demon, up from the Old Wolf of Farron bonfire |
+FK: Greatsword - ramp by keep ruins ritual island | In the middle of the swamp, on the pair of long ramps furthest from the Farron Keep bonfire, going out forward and slightly right from the bonfire. |
+FK: Havel's Armor - upper keep, after killing AP belfry roof NPC | Appears by Stray Demon, up from the Old Wolf of Farron bonfire, after the Havel Knight guarding the Titanite Slab in Archdragon Peak has been killed |
+FK: Havel's Gauntlets - upper keep, after killing AP belfry roof NPC | Appears by Stray Demon, up from the Old Wolf of Farron bonfire, after the Havel Knight guarding the Titanite Slab in Archdragon Peak has been killed |
+FK: Havel's Helm - upper keep, after killing AP belfry roof NPC | Appears by Stray Demon, up from the Old Wolf of Farron bonfire, after the Havel Knight guarding the Titanite Slab in Archdragon Peak has been killed |
+FK: Havel's Leggings - upper keep, after killing AP belfry roof NPC | Appears by Stray Demon, up from the Old Wolf of Farron bonfire, after the Havel Knight guarding the Titanite Slab in Archdragon Peak has been killed |
+FK: Heavy Gem - upper keep, lizard on stairs | Dropped by the Crystal Lizard that scurries up the stairs in the area dropping down from near Stray Demon, up from Old Wolf of Farron bonfire |
+FK: Hollow Gem - perimeter, drop down into swamp | Dropping down from the Farron Keep Perimeter building, to the right past the bonfire, before the stairs going up |
+FK: Homeward Bone - right island, behind fire | Behind the ritual fire with stairs guarded by Elder Ghrus/basilisks |
+FK: Iron Flesh - Farron Keep bonfire, right after exit | In the open in the swamp, heading straight right from Farron Keep bonfire |
+FK: Large Soul of a Nameless Soldier - corner of keep and right island | Hidden in a corner to the right of the stairs leading up to the ritual fire from the basilisk area |
+FK: Large Soul of a Nameless Soldier - near wall by right island | To the left of the stairs leading up to the ritual fire from the Basilisk area, by the keep wall |
+FK: Large Soul of an Unknown Traveler - by white tree | On a tree close to the swamp birch tree patrolled by the greater crab, where the Giant shoots arrows |
+FK: Large Titanite Shard - upper keep, lizard by wyvern | Dropped by the farther Crystal Lizard in the area dropping down from near Stray Demon, up from Old Wolf of Farron bonfire |
+FK: Large Titanite Shard - upper keep, lizard in open | Dropped by the closer Crystal Lizard in the area dropping down from near Stray Demon, up from Old Wolf of Farron bonfire |
+FK: Lightning Spear - upper keep, far side of the wall | Up the elevator from Old Wolf of Farron bonfire, and dropping down to Crystal Lizard area, in the open. |
+FK: Lingering Dragoncrest Ring - by white tree, miniboss drop | Dropped by the Greater Crab patrolling the birch tree where the Giant shoots arrows |
+FK: Magic Stoneplate Ring+1 - between right island and wall | Behind a tree in the basilisk area, heading directly right from Farron Keep bonfire |
+FK: Manikin Claws - Londor Pale Shade drop | Dropped by Londor Pale Shade when he invades near the basilisks, if Yoel or Yuria have been betrayed |
+FK: Nameless Knight Armor - corner of keep and right island | From the Keep Ruins bonfire to the ritual fire stairs patrolled by Elder Ghrus, along the edge of the ritual fire hill |
+FK: Nameless Knight Gauntlets - corner of keep and right island | From the Keep Ruins bonfire to the ritual fire stairs patrolled by Elder Ghrus, along the edge of the ritual fire hill |
+FK: Nameless Knight Helm - corner of keep and right island | From the Keep Ruins bonfire to the ritual fire stairs patrolled by Elder Ghrus, along the edge of the ritual fire hill |
+FK: Nameless Knight Leggings - corner of keep and right island | From the Keep Ruins bonfire to the ritual fire stairs patrolled by Elder Ghrus, along the edge of the ritual fire hill |
+FK: Pharis's Hat - miniboss drop, by keep ruins near wall | Dropped the Elder Ghru in the back of the group of three to the left of the Keep Ruins bonfire, as approached from the ritual fire. |
+FK: Poison Gem - near wall by keep ruins bridge | From the left of the bridge leading from the ritual fire to the Keep Ruins bonfire, guarded by the three Elder Ghru |
+FK: Prism Stone - by left island stairs | On an island to the left of the stairs leading up to the ritual fire straight ahead of the Farron Keep bonfire |
+FK: Purple Moss Clump - Farron Keep bonfire, around right corner | Along the inner wall of the keep, making an immediate right from Farron Keep bonfire |
+FK: Purple Moss Clump - keep ruins, ritual island | Close to the ritual fire before the Keep Ruins bonfire |
+FK: Purple Moss Clump - ramp directly in front of Farron Keep bonfire | In the middle of the swamp, on the pair of long ramps closest to the Farron Keep bonfire, going out forward and slightly right from the bonfire. |
+FK: Ragged Mask - Farron Keep bonfire, around left corner | Along the inner wall of the keep, making an immediate left from Farron Keep bonfire, guarded by slugs |
+FK: Repair Powder - outside hidden cave | Along the keep wall in the basilisk area, outside of the cave with the Elizabeth corpse and Golden Scroll |
+FK: Rotten Pine Resin - left island, behind fire | In the area behind the ritual fire which is straight ahead of the Farron Keep bonfire |
+FK: Rotten Pine Resin - outside pavilion by left island | From the Farron Keep bonfire straight ahead to the pavilion guarded by the Darkwraith, just to the left of the ritual fire stairs |
+FK: Rusted Gold Coin - right island, behind wall | Hidden behind the right wall of the ritual fire with stairs guarded by Elder Ghrus/basilisks |
+FK: Sage's Coal - pavilion by left island | In the pavilion guarded by a Darkwraith, straight ahead from the Farron Keep bonfire to the left of the ritual fire stairs |
+FK: Sage's Scroll - near wall by keep ruins bonfire island | Along the keep inner wall, heading left from the stone doors past the crab area, surrounded by many Ghru enemies |
+FK: Shriving Stone - perimeter, just past stone doors | Past the stone doors, on the path leading up to Abyss Watchers by the Corvians |
+FK: Soul of a Nameless Soldier - by white tree | Near the swamp birch tree patrolled by the greater crab, where the Giant shoots arrows |
+FK: Soul of a Stray Demon - upper keep, miniboss drop | Dropped by Stray Demon on the bridge above Farron Keep |
+FK: Soul of the Blood of the Wolf | Dropped by Abyss Watchers |
+FK: Stone Parma - near wall by left island | Along the inner wall of the keep, making a left from Farron Keep bonfire but before the area with the Darkwraith, guarded by a slug |
+FK: Sunlight Talisman - estus soup island, by ladder to keep proper | By the pot of estus soup to the left of the stairs leading up to Old Wolf of Farron |
+FK: Titanite Scale - perimeter, miniboss drop | Dropped by Ravenous Crystal Lizard near the shortcut from Farron Keep back to Road of Sacrifices |
+FK: Titanite Shard - Farron Keep bonfire, left after exit | Along the inner wall of the keep, making a left from Farron Keep bonfire, by the second group of four slugs |
+FK: Titanite Shard - between left island and keep ruins | In the swamp area with the Ghru Leaper between the Keep Ruins ritual fire and ritual fire straight ahead of Farron Keep bonfire, opposite from the keep wall |
+FK: Titanite Shard - by keep ruins ritual island stairs | By the stairs leading up to the Keep Ruins ritual fire from the middle of the swamp |
+FK: Titanite Shard - by ladder to keep proper | In the swamp area close to the foot of the ladder leading to Old Wolf of Farron bonfire |
+FK: Titanite Shard - by left island stairs | In front of the stairs leading up to the ritual fire straight ahead of the Farron Keep bonfire |
+FK: Titanite Shard - keep ruins bonfire island, under ramp | Under the ramp leading down from the Keep Ruins bonfire |
+FK: Titanite Shard - swamp by right island | Behind a tree patrolled by an Elder Ghru close to the ritual fire stairs |
+FK: Twinkling Dragon Head Stone - Hawkwood drop | Dropped by Hawkwood after killing him in the Abyss Watchers arena, after running up to the altar in Archdragon Peak. Twinkling Dragon Torso Stone needs to be acquired first. |
+FK: Twinkling Titanite - keep proper, lizard | Dropped by the Crystal Lizard on the balcony behind the Old Wolf of Farron bonfire |
+FK: Undead Bone Shard - pavilion by keep ruins bonfire island | In a standalone pavilion down the ramp from Keep Ruins bonfire and to the right |
+FK: Watchdogs of Farron - Old Wolf | Given by Old Wolf of Farron. |
+FK: Wolf Ring+1 - keep ruins bonfire island, outside building | To the right of the building with the Keep Ruins bonfire, when approached from the ritual fire |
+FK: Wolf's Blood Swordgrass - by ladder to keep proper | To the left of the ladder leading up to the Old Wolf of Farron bonfire |
+FK: Young White Branch - by white tree #1 | Near the swamp birch tree patrolled by the greater crab, where the Giant shoots arrows |
+FK: Young White Branch - by white tree #2 | Near the swamp birch tree patrolled by the greater crab, where the Giant shoots arrows |
+FS: Acid Surge - Cornyx for Carthus Tome | Sold by Cornyx after giving him the Carthus Pyromancy Tome |
+FS: Affinity - Karla | Sold by Karla after recruiting her, or in her ashes |
+FS: Alluring Skull - Mortician's Ashes | Sold by Handmaid after giving Mortician's Ashes |
+FS: Arstor's Spear - Ludleth for Greatwood | Boss weapon for Curse-Rotted Greatwood |
+FS: Aural Decoy - Orbeck | Sold by Orbeck |
+FS: Billed Mask - Yuria after killing KFF boss | Dropped by Yuria upon death or quest completion. |
+FS: Black Dress - Yuria after killing KFF boss | Dropped by Yuria upon death or quest completion. |
+FS: Black Fire Orb - Karla for Grave Warden Tome | Sold by Karla after giving her the Grave Warden Pyromancy Tome |
+FS: Black Flame - Karla for Grave Warden Tome | Sold by Karla after giving her the Grave Warden Pyromancy Tome |
+FS: Black Gauntlets - Yuria after killing KFF boss | Dropped by Yuria upon death or quest completion. |
+FS: Black Iron Armor - shop after killing Tsorig | Sold by Handmaid after killing Knight Slayer Tsorig in Smouldering Lake |
+FS: Black Iron Gauntlets - shop after killing Tsorig | Sold by Handmaid after killing Knight Slayer Tsorig in Smouldering Lake |
+FS: Black Iron Helm - shop after killing Tsorig | Sold by Handmaid after killing Knight Slayer Tsorig in Smouldering Lake |
+FS: Black Iron Leggings - shop after killing Tsorig | Sold by Handmaid after killing Knight Slayer Tsorig in Smouldering Lake |
+FS: Black Leggings - Yuria after killing KFF boss | Dropped by Yuria upon death or quest completion. |
+FS: Black Serpent - Ludleth for Wolnir | Boss weapon for High Lord Wolnir |
+FS: Blessed Weapon - Irina for Tome of Lothric | Sold by Irina after giving her the Braille Divine Tome of Lothric |
+FS: Blue Tearstone Ring - Greirat | Given by Greirat upon rescuing him from the High Wall cell |
+FS: Boulder Heave - Ludleth for Stray Demon | Boss weapon for Stray Demon |
+FS: Bountiful Light - Irina for Tome of Lothric | Sold by Irina after giving her the Braille Divine Tome of Lothric |
+FS: Bountiful Sunlight - Ludleth for Rosaria | Boss weapon for Rosaria, available after Leonhard is killed |
+FS: Broken Straight Sword - gravestone after boss | Near the grave after Iudex Gundyr fight |
+FS: Budding Green Blossom - shop after killing Creighton and AL boss | Sold by Handmaid after receiving Silvercat Ring item lot from Sirris and defeating Aldrich |
+FS: Bursting Fireball - Cornyx for Great Swamp Tome | Sold by Cornyx after giving him the Great Swamp Pyromancy Tome |
+FS: Caressing Tears - Irina | Sold by Irina after recruiting her, or in her ashes |
+FS: Carthus Beacon - Cornyx for Carthus Tome | Sold by Cornyx after giving him the Carthus Pyromancy Tome |
+FS: Carthus Flame Arc - Cornyx for Carthus Tome | Sold by Cornyx after giving him the Carthus Pyromancy Tome |
+FS: Cast Light - Orbeck for Golden Scroll | Sold by Orbeck after giving him the Golden Scroll |
+FS: Chaos Bed Vestiges - Ludleth for Old Demon King | Boss weapon for Old Demon King |
+FS: Chaos Storm - Cornyx for Izalith Tome | Sold by Cornyx after giving him Izalith Pyromancy Tome |
+FS: Clandestine Coat - shop with Orbeck's Ashes | Sold by Handmaid after giving Orbeck's Ashes and reloading |
+FS: Cleric's Candlestick - Ludleth for Deacons | Boss weapon for Deacons of the Deep |
+FS: Cracked Red Eye Orb - Leonhard | Given by Ringfinger Leonhard in Firelink Shrine after reaching Tower on the Wall bonfire |
+FS: Crystal Hail - Ludleth for Sage | Boss weapon for Crystal Sage |
+FS: Crystal Magic Weapon - Orbeck for Crystal Scroll | Sold by Orbeck after giving him the Crystal Scroll |
+FS: Crystal Sage's Rapier - Ludleth for Sage | Boss weapon for Crystal Sage |
+FS: Crystal Soul Spear - Orbeck for Crystal Scroll | Sold by Orbeck after giving him the Crystal Scroll |
+FS: Dancer's Armor - shop after killing LC entry boss | Sold by Handmaid after defeating Dancer of the Boreal Valley |
+FS: Dancer's Crown - shop after killing LC entry boss | Sold by Handmaid after defeating Dancer of the Boreal Valley |
+FS: Dancer's Enchanted Swords - Ludleth for Dancer | Boss weapon for Dancer of the Boreal Valley |
+FS: Dancer's Gauntlets - shop after killing LC entry boss | Sold by Handmaid after defeating Dancer of the Boreal Valley |
+FS: Dancer's Leggings - shop after killing LC entry boss | Sold by Handmaid after defeating Dancer of the Boreal Valley |
+FS: Dark Blade - Karla for Londor Tome | Sold by Irina or Karla after giving one the Londor Braille Divine Tome |
+FS: Dark Edge - Karla | Sold by Karla after recruiting her, or in her ashes |
+FS: Dark Hand - Yoel/Yuria | Sold by Yuria |
+FS: Darkdrift - Yoel/Yuria | Dropped by Yuria upon death or quest completion. |
+FS: Darkmoon Longbow - Ludleth for Aldrich | Boss weapon for Aldrich |
+FS: Dead Again - Karla for Londor Tome | Sold by Irina or Karla after giving one the Londor Braille Divine Tome |
+FS: Deep Protection - Karla for Deep Braille Tome | Sold by Irina or Karla after giving one the Deep Braille Divine Tome |
+FS: Deep Soul - Ludleth for Deacons | Boss weapon for Deacons of the Deep |
+FS: Demon's Fist - Ludleth for Fire Demon | Boss weapon for Fire Demon |
+FS: Demon's Greataxe - Ludleth for Fire Demon | Boss weapon for Fire Demon |
+FS: Demon's Scar - Ludleth for Demon Prince | Boss weapon for Demon Prince |
+FS: Divine Blessing - Greirat from IBV | Sold by Greirat after pillaging Irithyll |
+FS: Divine Blessing - Greirat from US | Sold by Greirat after pillaging Undead Settlement |
+FS: Dragonscale Armor - shop after killing AP boss | Sold by Handmaid after defeating Nameless King |
+FS: Dragonscale Waistcloth - shop after killing AP boss | Sold by Handmaid after defeating Nameless King |
+FS: Dragonslayer Greataxe - Ludleth for Dragonslayer | Boss weapon for Dragonslayer Armour |
+FS: Dragonslayer Greatshield - Ludleth for Dragonslayer | Boss weapon for Dragonslayer Armour |
+FS: Dragonslayer Swordspear - Ludleth for Nameless | Boss weapon for Nameless King |
+FS: Dried Finger - shop | Sold by both Shrine Handmaid and Untended Graves Handmaid |
+FS: East-West Shield - tree by shrine entrance | In a tree to the left of the Firelink Shrine entrance |
+FS: Eastern Armor - Easterner's Ashes | Sold by Handmaid after giving Easterner's Ashes |
+FS: Eastern Gauntlets - Easterner's Ashes | Sold by Handmaid after giving Easterner's Ashes |
+FS: Eastern Helm - Easterner's Ashes | Sold by Handmaid after giving Easterner's Ashes |
+FS: Eastern Leggings - Easterner's Ashes | Sold by Handmaid after giving Easterner's Ashes |
+FS: Elite Knight Armor - shop after Anri quest | Sold by Handmaid after completing Anri's questline or killing Anri |
+FS: Elite Knight Gauntlets - shop after Anri quest | Sold by Handmaid after completing Anri's questline or killing Anri |
+FS: Elite Knight Helm - shop after Anri quest | Sold by Handmaid after completing Anri's questline or killing Anri |
+FS: Elite Knight Leggings - shop after Anri quest | Sold by Handmaid after completing Anri's questline or killing Anri |
+FS: Ember - Dragon Chaser's Ashes | Sold by Handmaid after giving Dragon Chaser's Ashes |
+FS: Ember - Grave Warden's Ashes | Sold by Handmaid after giving Grave Warden's Ashes |
+FS: Ember - Greirat | Sold by Greirat after recruiting him, or in his ashes |
+FS: Ember - Greirat from US | Sold by Greirat after pillaging Undead Settlement |
+FS: Ember - Mortician's Ashes | Sold by Handmaid after giving Mortician's Ashes |
+FS: Ember - above shrine entrance | Above the Firelink Shrine entrance, up the stairs/slope from either left or right of the entrance |
+FS: Ember - path right of Firelink entrance | On a cliffside to the right of the main path leading up to Firelink Shrine, guarded by a dog |
+FS: Ember - shop | Sold by Handmaid |
+FS: Ember - shop for Greirat's Ashes | Sold by Handmaid after Greirat pillages Lothric Castle and handing in ashes |
+FS: Embraced Armor of Favor - shop after killing water reserve minibosses | Sold by Handmaid after killing Sulyvahn's Beasts in Water Reserve |
+FS: Executioner Armor - shop after killing Horace | Sold by Handmaid after killing Horace the Hushed |
+FS: Executioner Gauntlets - shop after killing Horace | Sold by Handmaid after killing Horace the Hushed |
+FS: Executioner Helm - shop after killing Horace | Sold by Handmaid after killing Horace the Hushed |
+FS: Executioner Leggings - shop after killing Horace | Sold by Handmaid after killing Horace the Hushed |
+FS: Exile Armor - shop after killing NPCs in RS | Sold by Handmaid after killing the exiles just before Farron Keep |
+FS: Exile Gauntlets - shop after killing NPCs in RS | Sold by Handmaid after killing the exiles just before Farron Keep |
+FS: Exile Leggings - shop after killing NPCs in RS | Sold by Handmaid after killing the exiles just before Farron Keep |
+FS: Exile Mask - shop after killing NPCs in RS | Sold by Handmaid after killing the exiles just before Farron Keep |
+FS: Faraam Helm - shop after killing GA NPC | Sold by Handmaid after killing Lion Knight Albert |
+FS: Farron Dart - Orbeck | Sold by Orbeck |
+FS: Farron Dart - shop | Sold by Handmaid |
+FS: Farron Flashsword - Orbeck | Sold by Orbeck |
+FS: Farron Greatsword - Ludleth for Abyss Watchers | Boss weapon for Abyss Watchers |
+FS: Farron Hail - Orbeck for Sage's Scroll | Sold by Orbeck after giving him the Sage's Scroll |
+FS: Farron Ring - Hawkwood | Given by Hawkwood, or dropped upon death, after defeating Abyss Watchers. |
+FS: Fire Orb - Cornyx for Great Swamp Tome | Sold by Cornyx after giving him the Great Swamp Pyromancy Tome |
+FS: Fire Surge - Cornyx | Sold by Cornyx after recruiting him, or in his ashes |
+FS: Fire Whip - Karla for Quelana Tome | Sold by Karla after giving her the Quelana Pyromancy Tome |
+FS: Fireball - Cornyx | Sold by Cornyx after recruiting him, or in his ashes |
+FS: Firelink Armor - shop after placing all Cinders | Sold by Handmaid after defeating Soul of Cinder |
+FS: Firelink Gauntlets - shop after placing all Cinders | Sold by Handmaid after defeating Soul of Cinder |
+FS: Firelink Greatsword - Ludleth for Cinder | Boss weapon for Soul of Cinder |
+FS: Firelink Helm - shop after placing all Cinders | Sold by Handmaid after defeating Soul of Cinder |
+FS: Firelink Leggings - shop after placing all Cinders | Sold by Handmaid after defeating Soul of Cinder |
+FS: Firestorm - Karla for Quelana Tome | Sold by Karla after giving her the Quelana Pyromancy Tome |
+FS: Flash Sweat - Cornyx | Sold by Cornyx after recruiting him, or in his ashes |
+FS: Force - Irina for Tome of Carim | Sold by Irina after giving her the Braille Divine Tome of Carim |
+FS: Frayed Blade - Ludleth for Midir | Boss weapon for Darkeater Midir |
+FS: Friede's Great Scythe - Ludleth for Friede | Boss weapon for Sister Friede |
+FS: Gael's Greatsword - Ludleth for Gael | Boss weapon for Slave Knight Gael |
+FS: Gauntlets of Favor - shop after killing water reserve minibosses | Sold by Handmaid after killing Sulyvahn's Beasts in Water Reserve |
+FS: Gnaw - Karla for Deep Braille Tome | Sold by Irina or Karla after giving one the Deep Braille Divine Tome |
+FS: Golden Bracelets - shop after killing AP boss | Sold by Handmaid after defeating Nameless King |
+FS: Golden Crown - shop after killing AP boss | Sold by Handmaid after defeating Nameless King |
+FS: Grave Key - Mortician's Ashes | Sold by Handmaid after giving Mortician's Ashes |
+FS: Great Chaos Fire Orb - Cornyx for Izalith Tome | Sold by Cornyx after giving him Izalith Pyromancy Tome |
+FS: Great Combustion - Cornyx | Sold by Cornyx after recruiting him, or in his ashes |
+FS: Great Farron Dart - Orbeck for Sage's Scroll | Sold by Orbeck after giving him the Sage's Scroll |
+FS: Great Heavy Soul Arrow - Orbeck | Sold by Orbeck |
+FS: Great Soul Arrow - Orbeck | Sold by Orbeck |
+FS: Greatsword of Judgment - Ludleth for Pontiff | Boss weapon for Pontiff Sulyvahn |
+FS: Gundyr's Armor - shop after killing UG boss | Sold by Handmaid after defeating Champion Gundyr |
+FS: Gundyr's Gauntlets - shop after killing UG boss | Sold by Handmaid after defeating Champion Gundyr |
+FS: Gundyr's Halberd - Ludleth for Champion | Boss weapon for Champion Gundyr |
+FS: Gundyr's Helm - shop after killing UG boss | Sold by Handmaid after defeating Champion Gundyr |
+FS: Gundyr's Leggings - shop after killing UG boss | Sold by Handmaid after defeating Champion Gundyr |
+FS: Havel's Ring - Ludleth for Stray Demon | Boss weapon for Stray Demon |
+FS: Hawkwood's Shield - gravestone after Hawkwood leaves | Left by Hawkwood after defeating Abyss Watchers, Curse-Rotted Greatwood, Deacons of the Deep, and Crystal Sage |
+FS: Hawkwood's Swordgrass - Andre after gesture in AP summit | Given by Andre after praying at the Dragon Altar in Archdragon Peak, after acquiring Twinkling Dragon Torso Stone. |
+FS: Heal - Irina | Sold by Irina after recruiting her, or in her ashes |
+FS: Heal Aid - shop | Sold by Handmaid |
+FS: Heavy Soul Arrow - Orbeck | Sold by Orbeck |
+FS: Heavy Soul Arrow - Yoel/Yuria | Sold by Yoel/Yuria |
+FS: Helm of Favor - shop after killing water reserve minibosses | Sold by Handmaid after killing Sulyvahn's Beasts in Water Reserve |
+FS: Hidden Blessing - Dreamchaser's Ashes | Sold by Greirat after pillaging Irithyll |
+FS: Hidden Blessing - Greirat from IBV | Sold by Greirat after pillaging Irithyll |
+FS: Hidden Blessing - Patches after searching GA | Sold by Handmaid after giving Dreamchaser's Ashes, saying where they were found |
+FS: Hidden Body - Orbeck for Golden Scroll | Sold by Orbeck after giving him the Golden Scroll |
+FS: Hidden Weapon - Orbeck for Golden Scroll | Sold by Orbeck after giving him the Golden Scroll |
+FS: Hollowslayer Greatsword - Ludleth for Greatwood | Boss weapon for Curse-Rotted Greatwood |
+FS: Homeward - Irina | Sold by Irina after recruiting her, or in her ashes |
+FS: Homeward Bone - cliff edge after boss | Along the cliff edge straight ahead of the Iudex Gundyr fight |
+FS: Homeward Bone - path above shrine entrance | To the right of the Firelink Shrine entrance, up a slope and before the ledge on top of a coffin |
+FS: Homing Crystal Soulmass - Orbeck for Crystal Scroll | Sold by Orbeck after giving him the Crystal Scroll |
+FS: Homing Soulmass - Orbeck for Logan's Scroll | Sold by Orbeck after giving him Logan's Scroll |
+FS: Karla's Coat - Prisoner Chief's Ashes | Sold by Handmaid after giving Prisoner Chief's Ashes |
+FS: Karla's Coat - kill Karla | Dropped from Karla upon death |
+FS: Karla's Gloves - Prisoner Chief's Ashes | Sold by Handmaid after giving Prisoner Chief's Ashes |
+FS: Karla's Gloves - kill Karla | Dropped from Karla upon death |
+FS: Karla's Pointed Hat - Prisoner Chief's Ashes | Sold by Handmaid after giving Prisoner Chief's Ashes |
+FS: Karla's Pointed Hat - kill Karla | Dropped from Karla upon death |
+FS: Karla's Trousers - Prisoner Chief's Ashes | Sold by Handmaid after giving Prisoner Chief's Ashes |
+FS: Karla's Trousers - kill Karla | Dropped from Karla upon death |
+FS: Leggings of Favor - shop after killing water reserve minibosses | Sold by Handmaid after killing Sulyvahn's Beasts in Water Reserve |
+FS: Leonhard's Garb - shop after killing Leonhard | Sold by Handmaid after killing Leonhard |
+FS: Leonhard's Gauntlets - shop after killing Leonhard | Sold by Handmaid after killing Leonhard |
+FS: Leonhard's Trousers - shop after killing Leonhard | Sold by Handmaid after killing Leonhard |
+FS: Life Ring - Dreamchaser's Ashes | Sold by Handmaid after giving Dreamchaser's Ashes |
+FS: Lifehunt Scythe - Ludleth for Aldrich | Boss weapon for Aldrich |
+FS: Lift Chamber Key - Leonhard | Given by Ringfinger Leonhard after acquiring a Pale Tongue. |
+FS: Lightning Storm - Ludleth for Nameless | Boss weapon for Nameless King |
+FS: Lloyd's Shield Ring - Paladin's Ashes | Sold by Handmaid after giving Paladin's Ashes |
+FS: Londor Braille Divine Tome - Yoel/Yuria | Sold by Yuria |
+FS: Lorian's Armor - shop after killing GA boss | Sold by Handmaid after defeating Lothric, Younger Prince |
+FS: Lorian's Gauntlets - shop after killing GA boss | Sold by Handmaid after defeating Lothric, Younger Prince |
+FS: Lorian's Greatsword - Ludleth for Princes | Boss weapon for Twin Princes |
+FS: Lorian's Helm - shop after killing GA boss | Sold by Handmaid after defeating Lothric, Younger Prince |
+FS: Lorian's Leggings - shop after killing GA boss | Sold by Handmaid after defeating Lothric, Younger Prince |
+FS: Lothric's Holy Sword - Ludleth for Princes | Boss weapon for Twin Princes |
+FS: Magic Barrier - Irina for Tome of Lothric | Sold by Irina after giving her the Braille Divine Tome of Lothric |
+FS: Magic Shield - Orbeck | Sold by Orbeck |
+FS: Magic Shield - Yoel/Yuria | Sold by Yoel/Yuria |
+FS: Magic Weapon - Orbeck | Sold by Orbeck |
+FS: Magic Weapon - Yoel/Yuria | Sold by Yoel/Yuria |
+FS: Mail Breaker - Sirris for killing Creighton | Given by Sirris talking to her in Firelink Shrine after invading and vanquishing Creighton. |
+FS: Master's Attire - NPC drop | Dropped by Sword Master |
+FS: Master's Gloves - NPC drop | Dropped by Sword Master |
+FS: Med Heal - Irina for Tome of Carim | Sold by Irina after giving her the Braille Divine Tome of Carim |
+FS: Millwood Knight Armor - Captain's Ashes | Sold by Handmaid after giving Captain's Ashes |
+FS: Millwood Knight Gauntlets - Captain's Ashes | Sold by Handmaid after giving Captain's Ashes |
+FS: Millwood Knight Helm - Captain's Ashes | Sold by Handmaid after giving Captain's Ashes |
+FS: Millwood Knight Leggings - Captain's Ashes | Sold by Handmaid after giving Captain's Ashes |
+FS: Moaning Shield - Eygon | Dropped by Eygon of Carim |
+FS: Moonlight Greatsword - Ludleth for Oceiros | Boss weapon for Oceiros, the Consumed King |
+FS: Morion Blade - Yuria for Orbeck's Ashes | Given by Yuria after giving Orbeck's Ashes after she asks you to assassinate him, after he moves to Firelink Shrine. Can be done without killing Orbeck, by completing his questline. |
+FS: Morne's Armor - shop after killing Eygon or LC boss | Sold by Handmaid after killing Eygon of Carim or defeating Dragonslayer Armour |
+FS: Morne's Gauntlets - shop after killing Eygon or LC boss | Sold by Handmaid after killing Eygon of Carim or defeating Dragonslayer Armour |
+FS: Morne's Great Hammer - Eygon | Dropped by Eygon of Carim |
+FS: Morne's Helm - shop after killing Eygon or LC boss | Sold by Handmaid after killing Eygon of Carim or defeating Dragonslayer Armour |
+FS: Morne's Leggings - shop after killing Eygon or LC boss | Sold by Handmaid after killing Eygon of Carim or defeating Dragonslayer Armour |
+FS: Old King's Great Hammer - Ludleth for Old Demon King | Boss weapon for Old Demon King |
+FS: Old Moonlight - Ludleth for Midir | Boss weapon for Darkeater Midir |
+FS: Ordained Dress - shop after killing PW2 boss | Sold by Handmaid after defeating Sister Friede |
+FS: Ordained Hood - shop after killing PW2 boss | Sold by Handmaid after defeating Sister Friede |
+FS: Ordained Trousers - shop after killing PW2 boss | Sold by Handmaid after defeating Sister Friede |
+FS: Pale Shade Gloves - Yoel's room, kill Londor Pale Shade twice | In Yoel/Yuria's area after defeating both Londor Pale Shade invasions |
+FS: Pale Shade Robe - Yoel's room, kill Londor Pale Shade twice | In Yoel/Yuria's area after defeating both Londor Pale Shade invasions |
+FS: Pale Shade Trousers - Yoel's room, kill Londor Pale Shade twice | In Yoel/Yuria's area after defeating both Londor Pale Shade invasions |
+FS: Pestilent Mist - Orbeck for any scroll | Sold by Orbeck after giving him any scroll |
+FS: Poison Mist - Cornyx for Great Swamp Tome | Sold by Cornyx after giving him the Great Swamp Pyromancy Tome |
+FS: Pontiff's Left Eye - Ludleth for Vordt | Boss weapon for Vordt of the Boreal Valley |
+FS: Prisoner's Chain - Ludleth for Champion | Boss weapon for Champion Gundyr |
+FS: Profaned Greatsword - Ludleth for Pontiff | Boss weapon for Pontiff Sulyvahn |
+FS: Profuse Sweat - Cornyx for Great Swamp Tome | Sold by Cornyx after giving him the Great Swamp Pyromancy Tome |
+FS: Rapport - Karla for Quelana Tome | Sold by Karla after giving her the Quelana Pyromancy Tome |
+FS: Refined Gem - Captain's Ashes | Sold by Handmaid after giving Captain's Ashes |
+FS: Repair - Orbeck for Golden Scroll | Sold by Orbeck after giving him the Golden Scroll |
+FS: Repeating Crossbow - Ludleth for Gael | Boss weapon for Slave Knight Gael |
+FS: Replenishment - Irina | Sold by Irina after recruiting her, or in her ashes |
+FS: Ring of Sacrifice - Yuria shop | Sold by Yuria, or by Handmaid after giving Hollow's Ashes |
+FS: Rose of Ariandel - Ludleth for Friede | Boss weapon for Sister Friede |
+FS: Rusted Gold Coin - don't forgive Patches | Given by Patches after not forgiving him after he locks you in the Bell Tower. |
+FS: Sage's Big Hat - shop after killing RS boss | Sold by Handmaid after defeating Crystal Sage |
+FS: Saint's Ring - Irina | Sold by Irina after recruiting her, or in her ashes |
+FS: Seething Chaos - Ludleth for Demon Prince | Boss weapon for Demon Prince |
+FS: Silvercat Ring - Sirris for killing Creighton | Given by Sirris talking to her in Firelink Shrine after invading and vanquishing Creighton. |
+FS: Skull Ring - kill Ludleth | Dropped by Ludleth upon death, including after placing all cinders. Note that if killed before giving Transposing Kiln, transposition is not possible. |
+FS: Slumbering Dragoncrest Ring - Orbeck for buying four specific spells | Given by Orbeck after purchasing the shop items corresponding to Aural Decoy, Farron Flashsword, Spook (starting items), and Pestilent Mist (after giving one scroll). |
+FS: Smough's Armor - shop after killing AL boss | Sold by Handmaid after defeating Alrich, Devourer of Gods |
+FS: Smough's Gauntlets - shop after killing AL boss | Sold by Handmaid after defeating Alrich, Devourer of Gods |
+FS: Smough's Helm - shop after killing AL boss | Sold by Handmaid after defeating Alrich, Devourer of Gods |
+FS: Smough's Leggings - shop after killing AL boss | Sold by Handmaid after defeating Alrich, Devourer of Gods |
+FS: Sneering Mask - Yoel's room, kill Londor Pale Shade twice | In Yoel/Yuria's area after defeating both Londor Pale Shade invasions |
+FS: Soothing Sunlight - Ludleth for Dancer | Boss weapon for Dancer of the Boreal Valley |
+FS: Soul Arrow - Orbeck | Sold by Orbeck |
+FS: Soul Arrow - Yoel/Yuria | Sold by Yoel/Yuria |
+FS: Soul Arrow - shop | Sold by Handmaid |
+FS: Soul Greatsword - Orbeck | Sold by Orbeck |
+FS: Soul Greatsword - Yoel/Yuria | Sold by Yoel/Yuria after using Draw Out True Strength |
+FS: Soul Spear - Orbeck for Logan's Scroll | Sold by Orbeck after giving him Logan's Scroll |
+FS: Soul of a Deserted Corpse - bell tower door | Next to the door requiring the Tower Key |
+FS: Spook - Orbeck | Sold by Orbeck |
+FS: Storm Curved Sword - Ludleth for Nameless | Boss weapon for Nameless King |
+FS: Sunless Armor - shop, Sirris quest, kill GA boss | Sold by Handmaid after completing Sirris' questline |
+FS: Sunless Gauntlets - shop, Sirris quest, kill GA boss | Sold by Handmaid after completing Sirris' questline |
+FS: Sunless Leggings - shop, Sirris quest, kill GA boss | Sold by Handmaid after completing Sirris' questline |
+FS: Sunless Talisman - Sirris, kill GA boss | Dropped by Sirris on death or quest completion. |
+FS: Sunless Veil - shop, Sirris quest, kill GA boss | Sold by Handmaid after completing Sirris' questline |
+FS: Sunlight Spear - Ludleth for Cinder | Boss weapon for Soul of Cinder |
+FS: Sunset Shield - by grave after killing Hodrick w/Sirris | Left by Sirris upon quest completion. |
+FS: Tears of Denial - Irina for Tome of Carim | Sold by Irina after giving her the Braille Divine Tome of Carim |
+FS: Titanite Scale - Greirat from IBV | Sold by Greirat after pillaging Irithyll |
+FS: Titanite Slab - shop after placing all Cinders | Sold by Handmaid after placing all Cinders of a Lord on their thrones |
+FS: Tower Key - shop | Sold by both Shrine Handmaid and Untended Graves Handmaid |
+FS: Twinkling Titanite - Greirat from IBV | Sold by Greirat after pillaging Irithyll |
+FS: Twisted Wall of Light - Orbeck for Golden Scroll | Sold by Orbeck after giving him the Golden Scroll |
+FS: Uchigatana - NPC drop | Dropped by Sword Master |
+FS: Undead Legion Armor - shop after killing FK boss | Sold by Handmaid after defeating Abyss Watchers |
+FS: Undead Legion Gauntlet - shop after killing FK boss | Sold by Handmaid after defeating Abyss Watchers |
+FS: Undead Legion Helm - shop after killing FK boss | Sold by Handmaid after defeating Abyss Watchers |
+FS: Undead Legion Leggings - shop after killing FK boss | Sold by Handmaid after defeating Abyss Watchers |
+FS: Untrue Dark Ring - Yoel/Yuria | Sold by Yuria |
+FS: Untrue White Ring - Yoel/Yuria | Sold by Yuria |
+FS: Vordt's Great Hammer - Ludleth for Vordt | Boss weapon for Vordt of the Boreal Valley |
+FS: Vow of Silence - Karla for Londor Tome | Sold by Irina or Karla after giving one the Londor Braille Divine Tome |
+FS: Washing Pole - Easterner's Ashes | Sold by Handmaid after giving Easterner's Ashes |
+FS: White Dragon Breath - Ludleth for Oceiros | Boss weapon for Oceiros, the Consumed King |
+FS: White Sign Soapstone - shop | Sold by both Shrine Handmaid and Untended Graves Handmaid |
+FS: Wolf Knight's Greatsword - Ludleth for Abyss Watchers | Boss weapon for Abyss Watchers |
+FS: Wolf Ring+2 - left of boss room exit | After Iudex Gundyr on the left |
+FS: Wolnir's Crown - shop after killing CC boss | Sold by Handmaid after defeating High Lord Wolnir |
+FS: Wolnir's Holy Sword - Ludleth for Wolnir | Boss weapon for High Lord Wolnir |
+FS: Wood Grain Ring - Easterner's Ashes | Sold by Handmaid after giving Easterner's Ashes |
+FS: Xanthous Gloves - Xanthous Ashes | Sold by Handmaid after giving Xanthous Ashes |
+FS: Xanthous Overcoat - Xanthous Ashes | Sold by Handmaid after giving Xanthous Ashes |
+FS: Xanthous Trousers - Xanthous Ashes | Sold by Handmaid after giving Xanthous Ashes |
+FS: Yhorm's Great Machete - Ludleth for Yhorm | Boss weapon for Yhorm the Giant |
+FS: Yhorm's Greatshield - Ludleth for Yhorm | Boss weapon for Yhorm the Giant |
+FS: Young Dragon Ring - Orbeck for one scroll and buying three spells | Given by Orbeck after purchasing four sorceries from him, and giving him one scroll, as a non-sorcerer. |
+FSBT: Armor of the Sun - crow for Siegbräu | Trade Siegbräu with crow |
+FSBT: Blessed Gem - crow for Moaning Shield | Trade Moaning Shield with crow |
+FSBT: Covetous Silver Serpent Ring - illusory wall past rafters | From the Firelink Shrine roof, past the rafters and an illusory wall |
+FSBT: Estus Ring - tower base | Dropping down from the Bell Tower to where Irina eventually resides |
+FSBT: Estus Shard - rafters | In the Firelink Shrine rafters, accessible from the roof |
+FSBT: Fire Keeper Gloves - partway down tower | Dropping down to the left after entering the Bell Tower. Align with the center of the closest floor tile row and run off the edge at full speed, aiming slightly left. |
+FSBT: Fire Keeper Robe - partway down tower | Dropping down to the left after entering the Bell Tower. Align with the center of the closest floor tile row and run off the edge at full speed, aiming slightly left. |
+FSBT: Fire Keeper Skirt - partway down tower | Dropping down to the left after entering the Bell Tower. Align with the center of the closest floor tile row and run off the edge at full speed, aiming slightly left. |
+FSBT: Fire Keeper Soul - tower top | At the top of the Bell Tower |
+FSBT: Hello Carving - crow for Alluring Skull | Trade Alluring Skull with crow |
+FSBT: Help me! Carving - crow for any sacred chime | Trade any Sacred Chime with crow |
+FSBT: Hollow Gem - crow for Eleonora | Trade Eleonora with crow |
+FSBT: Homeward Bone - roof | On Firelink Shrine roof |
+FSBT: I'm sorry Carving - crow for Shriving Stone | Trade Shriving Stone with crow |
+FSBT: Iron Bracelets - crow for Homeward Bone | Trade Homeward Bone with crow |
+FSBT: Iron Helm - crow for Lightning Urn | Trade Lightning Urn with crow |
+FSBT: Iron Leggings - crow for Seed of a Giant Tree | Trade Seed of a Giant Tree with crow |
+FSBT: Large Titanite Shard - crow for Firebomb | Trade Firebomb or Rope Firebomb with crow |
+FSBT: Lightning Gem - crow for Xanthous Crown | Trade Xanthous Crown with crow |
+FSBT: Lucatiel's Mask - crow for Vertebra Shackle | Trade Vertebra Shackle with crow |
+FSBT: Porcine Shield - crow for Undead Bone Shard | Trade Undead Bone Shard with crow |
+FSBT: Ring of Sacrifice - crow for Loretta's Bone | Trade Loretta's Bone with crow |
+FSBT: Sunlight Shield - crow for Mendicant's Staff | Trade Mendicant's Staff with crow |
+FSBT: Thank you Carving - crow for Hidden Blessing | Trade Hidden Blessing with crow |
+FSBT: Titanite Chunk - crow for Black Firebomb | Trade Black Firebomb or Rope Black Firebomb with crow |
+FSBT: Titanite Scale - crow for Blacksmith Hammer | Trade Blacksmith Hammer with crow |
+FSBT: Titanite Slab - crow for Coiled Sword Fragment | Trade Coiled Sword Fragment with crow |
+FSBT: Twinkling Titanite - crow for Large Leather Shield | Trade Large Leather Shield with crow |
+FSBT: Twinkling Titanite - crow for Prism Stone | Trade Prism Stone with crow |
+FSBT: Twinkling Titanite - lizard behind Firelink | Dropped by the Crystal Lizard behind Firelink Shrine. Can be accessed with tree jump by going all the way around the roof, left of the entrance to the rafters, or alternatively dropping down from the Bell Tower. |
+FSBT: Very good! Carving - crow for Divine Blessing | Trade Divine Blessing with crow |
+GA: Avelyn - 1F, drop from 3F onto bookshelves | On top of a bookshelf on the Archive first floor, accessible by going halfway up the stairs to the third floor, dropping down past the Grand Archives Scholar, and then dropping down again |
+GA: Black Hand Armor - shop after killing GA NPC | Sold by Handmaid after killing Black Hand Kumai |
+GA: Black Hand Hat - shop after killing GA NPC | Sold by Handmaid after killing Black Hand Kumai |
+GA: Blessed Gem - rafters | On the rafters high above the Archives, can be accessed by dropping down from the Winged Knight roof area |
+GA: Chaos Gem - dark room, lizard | Dropped by a Crystal Lizard on the Archives first floor in the dark room past the large wax pool |
+GA: Cinders of a Lord - Lothric Prince | Dropped by Twin Princes |
+GA: Crystal Chime - 1F, path from wax pool | On the Archives first floor, in the room with the Lothric Knight, to the right |
+GA: Crystal Gem - 1F, lizard by drop | Dropped by the Crystal Lizard on the Archives first floor along the left wall |
+GA: Crystal Scroll - 2F late, miniboss drop | Dropped by the Grand Archives Crystal Sage |
+GA: Divine Blessing - rafters, down lower level ladder | In a chest reachable after dropping down from the Archives rafters and down a ladder near the Corpse-grub |
+GA: Divine Pillars of Light - cage above rafters | In a cage above the rafters high above the Archives, can be accessed by dropping down from the Winged Knight roof area |
+GA: Ember - 5F, by entrance | On a balcony high in the Archives overlooking the area with the Grand Archives Scholars with a shortcut ladder, on the opposite side from the wax pool |
+GA: Estus Shard - dome, far balcony | On the Archives roof near the three Winged Knights, in a side area overlooking the ocean. |
+GA: Faraam Armor - shop after killing GA NPC | Sold by Handmaid after killing Lion Knight Albert |
+GA: Faraam Boots - shop after killing GA NPC | Sold by Handmaid after killing Lion Knight Albert |
+GA: Faraam Gauntlets - shop after killing GA NPC | Sold by Handmaid after killing Lion Knight Albert |
+GA: Fleshbite Ring - up stairs from 4F | From the first shortcut elevator with the movable bookshelf, past the Scholars right before going outside onto the roof, in an alcove to the right with many Clawed Curse bookshelves |
+GA: Golden Wing Crest Shield - outside 5F, NPC drop | Dropped by Lion Knight Albert before the stairs leading up to Twin Princes |
+GA: Heavy Gem - rooftops, lizard | Dropped by one of the pair of Crystal Lizards, on the right side, found going up a slope past the gargoyle on the Archives roof |
+GA: Hollow Gem - rooftops lower, in hall | Going onto the roof and down the first ladder, dropping down on either side from the ledge facing the ocean, in a tunnel underneath the ledge |
+GA: Homeward Bone - 2F early balcony | On the Archives second floor, on the balcony with the ladder going up to the Crystal Sage |
+GA: Hunter's Ring - dome, very top | At the top of the ladder in roof the area with the Winged Knights |
+GA: Large Soul of a Crestfallen Knight - 4F, back | In the back of a Clawed Curse-heavy corridor of bookshelves, in the area with the Grand Archives Scholars and dropdown ladder, after the first shortcut elevator with the movable bookshelf |
+GA: Large Soul of a Crestfallen Knight - outside 5F | In the middle of the area with the three human NPCs attacking you, before the Grand Archives bonfire shortcut elevator |
+GA: Lingering Dragoncrest Ring+2 - dome, room behind spire | Near the tower with the Winged Knights, up the stairs on the opposite side from the ladder leading up to the Hunter's Ring |
+GA: Onikiri and Ubadachi - outside 5F, NPC drop | Dropped by Black Hand Kamui before the stairs leading up to Twin Princes |
+GA: Outrider Knight Armor - 3F, behind illusory wall, miniboss drop | Dropped by an Outrider Knight past the Crystal Sage's third floor location and an illusory wall |
+GA: Outrider Knight Gauntlets - 3F, behind illusory wall, miniboss drop | Dropped by an Outrider Knight past the Crystal Sage's third floor location and an illusory wall |
+GA: Outrider Knight Helm - 3F, behind illusory wall, miniboss drop | Dropped by an Outrider Knight past the Crystal Sage's third floor location and an illusory wall |
+GA: Outrider Knight Leggings - 3F, behind illusory wall, miniboss drop | Dropped by an Outrider Knight past the Crystal Sage's third floor location and an illusory wall |
+GA: Power Within - dark room, behind retractable bookshelf | Behind a bookshelf in the dark room with the Crystal Lizards, moved by a lever in the same room |
+GA: Refined Gem - up stairs from 4F, lizard | Dropped by a Crystal Lizard found heading from the first elevator shortcut with the movable bookshelf, on the right side up the stairs before exiting to the roof |
+GA: Sage Ring+1 - rafters, second level down | On the rafters high above the Grand Archives, dropping down from the cage to the high rafters to the rafters below with the Corpse-grub |
+GA: Sage's Crystal Staff - outside 5F, NPC drop | Dropped by Daughter of Crystal Kriemhild before the stairs leading up to Twin Princes |
+GA: Scholar Ring - 2F, between late and early | On the corpse of a sitting Archives Scholar between two bookshelves, accessible by activating a lever before crossing the bridge that is the Crystal Sage's final location |
+GA: Sharp Gem - rooftops, lizard | Dropped by one of the pair of Crystal Lizards, on the left side, found going up a slope past the gargoyle on the Archives roof |
+GA: Shriving Stone - 2F late, by ladder from 3F | Going from the Crystal Sage's location on the third floor to its location on the bridge, after descending the ladder |
+GA: Soul Stream - 3F, behind illusory wall | Past the Crystal Sage's third floor location, an illusory wall, and an Outrider Knight, on the corpse of a sitting Archives Scholar |
+GA: Soul of a Crestfallen Knight - 1F, loop left after drop | On the Archives first floor, hugging the left wall, on a ledge that loops back around to the left wall |
+GA: Soul of a Crestfallen Knight - path to dome | On balcony of the building with the second shortcut elevator down to the bonfire, accessible by going up the spiral stairs to the left |
+GA: Soul of a Nameless Soldier - dark room | On the Archives first floor, after the wax pool, against a Clawed Curse bookshelf |
+GA: Soul of a Weary Warrior - rooftops, by lizards | On the Archives roof, going up the first rooftop slope where a Gargoyle always attacks you |
+GA: Soul of the Twin Princes | Dropped by Twin Princes |
+GA: Titanite Chunk - 1F, balcony | On the Archives first floor, on balcony overlooking the entrance opposite from the Grand Archives Scholars wax pool |
+GA: Titanite Chunk - 1F, path from wax pool | On the Archives first floor, toward the Lothric Knight, turning right to a ledge leading back to the entrance area |
+GA: Titanite Chunk - 1F, up right stairs | Going right after entering the Archives entrance and up the short flight of stairs |
+GA: Titanite Chunk - 2F, by wax pool | Up the stairs from the Archives second floor on the right side from the entrance, in a corner near the small wax pool |
+GA: Titanite Chunk - 2F, right after dark room | Exiting from the dark room with the Crystal Lizards on the first floor onto the second floor main room, then taking an immediate right |
+GA: Titanite Chunk - 5F, far balcony | On a balcony outside where Lothric Knight stands on the top floor of the Archives, accessing by going right from the final wax pool or by dropping down from the gargoyle area |
+GA: Titanite Chunk - rooftops, balcony | Going onto the roof and down the first ladder, all the way down the ledge facing the ocean to the right |
+GA: Titanite Chunk - rooftops lower, ledge by buttress | Going onto the roof and down the first ladder, dropping down on either side from the ledge facing the ocean, on a roof ledge to the right |
+GA: Titanite Chunk - rooftops, just before 5F | On the Archives roof, after a short dropdown, in the small area where the two Gargoyles attack you |
+GA: Titanite Scale - 1F, drop from 2F late onto bookshelves, lizard | Dropped by a Crystal Lizard on first floor bookshelves. Can be accessed by dropping down to the left at the end of the bridge which is the Crystal Sage's final location |
+GA: Titanite Scale - 1F, up stairs on bookshelf | On the Archives first floor, up a movable set of stairs near the large wax pool, on top of a bookshelf |
+GA: Titanite Scale - 2F, titanite scale atop bookshelf | On top of a bookshelf on the Archive second floor, accessible by going halfway up the stairs to the third floor and dropping down near a Grand Archives Scholar |
+GA: Titanite Scale - 3F, by ladder to 2F late | Going from the Crystal Sage's location on the third floor to its location on the bridge, on the left side of the ladder you descend, behind a table |
+GA: Titanite Scale - 3F, corner up stairs | From the Grand Archives third floor up past the thralls, in a corner with bookshelves to the left |
+GA: Titanite Scale - 5F, chest by exit | In a chest after the first elevator shortcut with the movable bookshelf, in the area with the Grand Archives Scholars, to the left of the stairwell leading up to the roof |
+GA: Titanite Scale - dark room, upstairs | Right after going up the stairs to the Archives second floor, on the left guarded by a Grand Archives Scholar and a sequence of Clawed Curse bookshelves |
+GA: Titanite Scale - rooftops lower, path to 2F | Going onto the roof and down the first ladder, dropping down on either side from the ledge facing the ocean, then going past the corvians all the way to the left and making a jump |
+GA: Titanite Slab - 1F, after pulling 2F switch | In a chest on the Archives first floor, behind a bookshelf moved by pulling a lever in the middle of the second floor between two cursed bookshelves |
+GA: Titanite Slab - dome, kill all mobs | Dropped by killing all three Winged Knights on top of the Archives |
+GA: Titanite Slab - final elevator secret | At the bottom of the shortcut elevator right outside the Twin Princes fight. Requires sending the elevator up to the top from the middle, and then riding the lower elevator down. |
+GA: Twinkling Titanite - 1F, lizard by drop | Dropped by the Crystal Lizard on the Archives first floor along the left wall |
+GA: Twinkling Titanite - 2F, lizard by entrance | Dropped by the Crystal Lizard on the Archives second floor, going toward the stairs/balcony |
+GA: Twinkling Titanite - dark room, lizard #1 | Dropped by a Crystal Lizard on the Archives first floor in the dark room past the large wax pool |
+GA: Twinkling Titanite - dark room, lizard #2 | Dropped by a Crystal Lizard on the Archives first floor in the dark room past the large wax pool |
+GA: Twinkling Titanite - rafters, down lower level ladder | In a chest reachable after dropping down from the Archives rafters and down a ladder near the Corpse-grub |
+GA: Twinkling Titanite - rooftops, lizard #1 | Dropped by one of the pair of Crystal Lizards, on the right side, found going up a slope past the gargoyle on the Archives roof |
+GA: Twinkling Titanite - rooftops, lizard #2 | Dropped by one of the pair of Crystal Lizards, on the left side, found going up a slope past the gargoyle on the Archives roof |
+GA: Twinkling Titanite - up stairs from 4F, lizard | Dropped by a Crystal Lizard found heading from the first elevator shortcut with the movable bookshelf, on the right side up the stairs before exiting to the roof |
+GA: Undead Bone Shard - 5F, by entrance | On the corpse of a sitting Archives Scholar on a balcony high in the Archives overlooking the area with the Grand Archives Scholars with a shortcut ladder, near the final wax pool |
+GA: Witch's Locks - dark room, behind retractable bookshelf | Behind a bookshelf in the dark room with the Crystal Lizards, moved by a lever in the same room |
+HWL: Astora Straight Sword - fort walkway, drop down | In the building with the Pus of Man on the roof, past the Lothric Knight down a hallway obscured by a wooden wheel, dropping down past the edge |
+HWL: Basin of Vows - Emma | Dropped by Emma upon killing her. This is possible to do at any time |
+HWL: Battle Axe - flame tower, mimic | Dropped by mimic in the building guarded by the fire-breathing wyvern |
+HWL: Binoculars - corpse tower, upper platform | In the area with the dead wyvern, at the top of a set of stairs past a Hollow Soldier |
+HWL: Black Firebomb - small roof over fountain | After roof with Pus of Man, on the edge of another rooftop to the left where you can drop down into Winged Knight area |
+HWL: Broadsword - fort, room off walkway | In the building with the Pus of Man on the roof, past the Lothric Knight in an alcove to the left |
+HWL: Cell Key - fort ground, down stairs | In the basement of the building with Pus of Man on the roof, down the stairs guarded by a dog |
+HWL: Claymore - flame plaza | In the area where the wyvern breathes fire, farthest away from the door |
+HWL: Club - flame plaza | In the area where the wyvern breathes fire, in the open |
+HWL: Ember - back tower, transforming hollow | Dropped by the Pus of Man on the tower to the right of the High Wall bonfire after transformation |
+HWL: Ember - flame plaza | In the area where the wyvern breathes fire, in the open |
+HWL: Ember - fort roof, transforming hollow | Dropped by the Pus of Man on the roof after the Tower on the Wall bonfire after transformation |
+HWL: Ember - fountain #1 | In the area with the Winged Knight |
+HWL: Ember - fountain #2 | In the area with the Winged Knight |
+HWL: Estus Shard - fort ground, on anvil | In the basement of the building with the Pus of Man on the roof, on the blacksmith anvil |
+HWL: Firebomb - corpse tower, under table | In the building near the dead wyvern, behind a table near the ladder you descend |
+HWL: Firebomb - fort roof | Next to the Pus of Man on the roof |
+HWL: Firebomb - top of ladder to fountain | By the long ladder leading down to the area with the Winged Knight |
+HWL: Firebomb - wall tower, beam | In the building with the Tower on the Wall bonfire, on a wooden beam overhanging the lower levels |
+HWL: Fleshbite Ring+1 - fort roof, jump to other roof | Jumping from the roof with the Pus of Man to a nearby building with a fenced roof |
+HWL: Gold Pine Resin - corpse tower, drop | Dropping past the dead wyvern, down the left path from the High Wall bonfire |
+HWL: Green Blossom - fort walkway, hall behind wheel | In the building with the Pus of Man on the roof, past the Lothric Knight down a hallway obscured by a wooden wheel |
+HWL: Green Blossom - shortcut, lower courtyard | In the courtyard at the bottom of the shortcut elevator |
+HWL: Large Soul of a Deserted Corpse - flame plaza | In the area where the wyvern breathes fire, behind one of the praying statues |
+HWL: Large Soul of a Deserted Corpse - fort roof | On the edge of the roof with the Pus of Man |
+HWL: Large Soul of a Deserted Corpse - platform by fountain | Coming from the elevator shortcut, on a side path to the left (toward Winged Knight area) |
+HWL: Longbow - back tower | Down the path from the right of the High Wall bonfire, where the Pus of Man and crossbowman are |
+HWL: Lucerne - promenade, side path | On one of the side paths from the main path connecting Dancer and Vordt fights, patrolled by a Lothric Knight |
+HWL: Mail Breaker - wall tower, path to Greirat | In the basement of the building with the Tower on the Wall bonfire on the roof, before Greirat's cell |
+HWL: Rapier - fountain, corner | In a corner in the area with the Winged Knight |
+HWL: Raw Gem - fort roof, lizard | Dropped by the Crystal Lizard on the rooftop after the Tower on the Wall bonfire |
+HWL: Red Eye Orb - wall tower, miniboss | Dropped by the Darkwraith past the Lift Chamber Key |
+HWL: Refined Gem - promenade miniboss | Dropped by the red-eyed Lothric Knight to the left of the Dancer's room entrance |
+HWL: Ring of Sacrifice - awning by fountain | Coming from the elevator shortcut, on a side path to the left (toward Winged Knight area), jumping onto a wooden support |
+HWL: Ring of the Evil Eye+2 - fort ground, far wall | In the basement of the building with the Pus of Man on the roof, on the far wall past the stairwell, behind some barrels |
+HWL: Silver Eagle Kite Shield - fort mezzanine | In the chest on the balcony overlooking the basement of the building with the Pus of Man on the roof |
+HWL: Small Lothric Banner - Emma | Given by Emma, or dropped upon death |
+HWL: Soul of Boreal Valley Vordt | Dropped by Vordt of the Boreal Valley |
+HWL: Soul of a Deserted Corpse - by wall tower door | Right before the entrance to the building with the Tower on the Wall bonfire |
+HWL: Soul of a Deserted Corpse - corpse tower, bottom floor | Down the ladder of the building near the dead wyvern, on the way to the living wyvern |
+HWL: Soul of a Deserted Corpse - fort entry, corner | In the corner of the room with a Lothric Knight, with the Pus of Man on the roof |
+HWL: Soul of a Deserted Corpse - fountain, path to promenade | In between the Winged Knight area and the Dancer/Vordt corridor |
+HWL: Soul of a Deserted Corpse - path to back tower, by lift door | Where the Greataxe Hollow Soldier patrols outside of the elevator shortcut entrance |
+HWL: Soul of a Deserted Corpse - path to corpse tower | At the very start, heading left from the High Wall bonfire |
+HWL: Soul of a Deserted Corpse - wall tower, right of exit | Exiting the building with the Tower on the Wall bonfire on the roof, immediately to the right |
+HWL: Soul of the Dancer | Dropped by Dancer of the Boreal Valley |
+HWL: Standard Arrow - back tower | Down the path from the right of the High Wall bonfire, where the Pus of Man and crossbowman are |
+HWL: Throwing Knife - shortcut, lift top | At the top of the elevator shortcut, opposite from the one-way door |
+HWL: Throwing Knife - wall tower, path to Greirat | In the basement of the building with the Tower on the Wall bonfire, in the room with the explosive barrels |
+HWL: Titanite Shard - back tower, transforming hollow | Dropped by the Pus of Man on the tower to the right of the High Wall bonfire after transformation |
+HWL: Titanite Shard - fort ground behind crates | Behind some wooden crates in the basement of the building with the Pus of Man on the roof |
+HWL: Titanite Shard - fort roof, transforming hollow | Dropped by the Pus of Man on the roof after the Tower on the Wall bonfire after transformation |
+HWL: Titanite Shard - fort, room off entry | In the building with the Pus of Man on the roof, in a room to the left and up the short stairs |
+HWL: Titanite Shard - wall tower, corner by bonfire | On the balcony with the Tower on the Wall bonfire |
+HWL: Undead Hunter Charm - fort, room off entry, in pot | In the building with the Pus of Man on the roof, in a room to the left, in a pot you have to break |
+HWL: Way of Blue - Emma | Given by Emma or dropped upon death. |
+IBV: Blood Gem - descent, platform before lake | In front of the tree in the courtyard before going down the stairs to the lake leading to the Distant Manor bonfire |
+IBV: Blue Bug Pellet - ascent, in last building | In the final building before Pontiff's cathedral, coming from the sewer, on the first floor |
+IBV: Blue Bug Pellet - descent, dark room | In the dark area with the Irithyllian slaves, to the left of the staircase |
+IBV: Budding Green Blossom - central, by second fountain | Next to the fountain up the stairs from the Central Irithyll bonfire |
+IBV: Chloranthy Ring+1 - plaza, behind altar | In the area before and below Pontiff's cathedral, behind the central structure |
+IBV: Covetous Gold Serpent Ring+1 - descent, drop after dark room | After the dark area with the Irithyllian slaves, drop down to the right |
+IBV: Creighton's Steel Mask - bridge after killing Creighton | Following Sirris' questline, found on the bridge to Irithyll after being invaded by Creighton the Wanderer in the graveyard after the Church of Yorshka. |
+IBV: Divine Blessing - great hall, chest | In a chest up the stairs in the room with the Silver Knight staring at the painting |
+IBV: Divine Blessing - great hall, mob drop | One-time drop from the Silver Knight staring at the painting in Irithyll |
+IBV: Dorhys' Gnawing - Dorhys drop | Dropped by Cathedral Evangelist Dorhys, past an illusory railing past the Central Irithyll Fire Witches and to the left |
+IBV: Dragonslayer's Axe - Creighton drop | Following Sirris' questline, dropped by Creighton the Wanderer when he invades in the graveyard after the Church of Yorshka. |
+IBV: Dung Pie - sewer #1 | In the area with the sewer centipedes |
+IBV: Dung Pie - sewer #2 | In the area with the sewer centipedes |
+IBV: Ember - shortcut from church to cathedral | After the gate shortcut from Church of Yorshka to Pontiff's cathedral |
+IBV: Emit Force - Siegward | Given by Siegward meeting him in the Irithyll kitchen after the Sewer Centipedes. |
+IBV: Excrement-covered Ashes - sewer, by stairs | In the area with the sewer centipedes, before going up the stairs to the kitchen |
+IBV: Fading Soul - descent, cliff edge #1 | In the graveyard down the stairs from the Church of Yorshka, at the cliff edge |
+IBV: Fading Soul - descent, cliff edge #2 | In the graveyard down the stairs from the Church of Yorshka, at the cliff edge |
+IBV: Great Heal - lake, dead Corpse-Grub | On the Corpse-grub at the edge of the lake leading to the Distant Manor bonfire |
+IBV: Green Blossom - lake wall | On the wall of the lake leading to the Distant Manor bonfire |
+IBV: Green Blossom - lake, by Distant Manor | In the lake close to the Distant Manor bonfire |
+IBV: Green Blossom - lake, by stairs from descent | Going down the stairs into the lake leading to the Distant Manor bonfire |
+IBV: Homeward Bone - descent, before gravestone | In the graveyard down the stairs from the Church of Yorshka, in front of the grave with the Corvian |
+IBV: Kukri - descent, side path | Down the stairs from the graveyard after Church of Yorshka, before the group of dogs in the left path |
+IBV: Large Soul of a Nameless Soldier - ascent, after great hall | By the tree near the stairs from the sewer leading up to Pontiff's cathedral, where the first dogs attack you |
+IBV: Large Soul of a Nameless Soldier - central, by bonfire | By the Central Irithyll bonfire |
+IBV: Large Soul of a Nameless Soldier - central, by second fountain | Next to the fountain up the stairs from the Central Irithyll bonfire |
+IBV: Large Soul of a Nameless Soldier - lake island | On an island in the lake leading to the Distant Manor bonfire |
+IBV: Large Soul of a Nameless Soldier - stairs to plaza | On the path from Central Irithyll bonfire, before making the left toward Church of Yorshka |
+IBV: Large Titanite Shard - Distant Manor, under overhang | Under overhang next to second set of stairs leading from Distant Manor bonfire |
+IBV: Large Titanite Shard - ascent, by elevator door | On the path from the sewer leading up to Pontiff's cathedral, to the right of the statue surrounded by dogs |
+IBV: Large Titanite Shard - ascent, down ladder in last building | Outside the final building before Pontiff's cathedral, coming from the sewer, dropping down to the left before the entrance |
+IBV: Large Titanite Shard - central, balcony just before plaza | From the Central Irithyll bonfire, on the balcony with the second Fire Witch. |
+IBV: Large Titanite Shard - central, side path after first fountain | Up the stairs from the Central Irithyll bonfire, on a railing to the right |
+IBV: Large Titanite Shard - great hall, main floor mob drop | One-time drop from the Silver Knight staring at the painting in Irithyll |
+IBV: Large Titanite Shard - great hall, upstairs mob drop #1 | One-time drop from the Silver Knight on the balcony of the room with the painting |
+IBV: Large Titanite Shard - great hall, upstairs mob drop #2 | One-time drop from the Silver Knight on the balcony of the room with the painting |
+IBV: Large Titanite Shard - path to Dorhys | Before the area with Cathedral Evangelist Dorhys, past an illusory railing past the Central Irithyll Fire Witches |
+IBV: Large Titanite Shard - plaza, balcony overlooking ascent | On the path from Central Irithyll bonfire, instead of going left toward the Church of Yorshka, going right, on the balcony |
+IBV: Large Titanite Shard - plaza, by stairs to church | To the left of the stairs leading up to the Church of Yorshka from Central Irithyll |
+IBV: Leo Ring - great hall, chest | In a chest up the stairs in the room with the Silver Knight staring at the painting |
+IBV: Lightning Gem - plaza center | In the area before and below Pontiff's cathedral, in the center guarded by the enemies |
+IBV: Magic Clutch Ring - plaza, illusory wall | In the area before and below Pontiff's cathedral, behind an illusory wall to the right |
+IBV: Mirrah Chain Gloves - bridge after killing Creighton | Following Sirris' questline, found on the bridge to Irithyll after being invaded by Creighton the Wanderer in the graveyard after the Church of Yorshka. |
+IBV: Mirrah Chain Leggings - bridge after killing Creighton | Following Sirris' questline, found on the bridge to Irithyll after being invaded by Creighton the Wanderer in the graveyard after the Church of Yorshka. |
+IBV: Mirrah Chain Mail - bridge after killing Creighton | Following Sirris' questline, found on the bridge to Irithyll after being invaded by Creighton the Wanderer in the graveyard after the Church of Yorshka. |
+IBV: Proof of a Concord Kept - Church of Yorshka altar | At the altar in the Church of Yorshka |
+IBV: Rime-blue Moss Clump - central, by bonfire | By the Central Irithyll bonfire |
+IBV: Rime-blue Moss Clump - central, past second fountain | From the Central Irithyll bonfire, to the left before the first Fire Witch. |
+IBV: Ring of Sacrifice - lake, right of stairs from descent | Near the sewer centipede at the start of the lake leading to the Distant Manor bonfire |
+IBV: Ring of the Evil Eye - Anri | Given by Anri of Astora in the Church of Yorshka, or if told of Horace's whereabouts in the Catacombs |
+IBV: Ring of the Sun's First Born - fall from in front of cathedral | Dropping down from in front of Pontiff Sulyvahn's church toward the Church of Yorshka |
+IBV: Roster of Knights - descent, first landing | On the landing going down the stairs from Church of Yorshka to the graveyard |
+IBV: Rusted Gold Coin - Distant Manor, drop after stairs | Dropping down after the first set of stairs leading from Distant Manor bonfire |
+IBV: Rusted Gold Coin - descent, side path | Down the stairs from the graveyard after Church of Yorshka, guarded by the group of dogs in the left path |
+IBV: Shriving Stone - descent, dark room rafters | On the rafters in the dark area with the Irithyllian slaves |
+IBV: Siegbräu - Siegward | Given by Siegward meeting him in the Irithyll kitchen after the Sewer Centipedes. |
+IBV: Smough's Great Hammer - great hall, chest | In a chest up the stairs in the room with the Silver Knight staring at the painting |
+IBV: Soul of Pontiff Sulyvahn | Dropped by Pontiff Sulyvahn |
+IBV: Soul of a Weary Warrior - ascent, by final staircase | Toward the end of the path from the sewer leading up to Pontiff's cathedral, to the left of the final staircase |
+IBV: Soul of a Weary Warrior - central, by first fountain | By the Central Irithyll bonfire |
+IBV: Soul of a Weary Warrior - central, railing by first fountain | On the railing overlooking the Central Irithyll bonfire, at the very start |
+IBV: Soul of a Weary Warrior - plaza, side room lower | Dropping down from the path from Church of Yorshka to Pontiff, guarded by the pensive Fire Witch |
+IBV: Soul of a Weary Warrior - plaza, side room upper | In the path from Church of Yorshka to Pontiff's cathedral, at the broken ledge you can drop down onto the Fire Witch |
+IBV: Twinkling Titanite - central, lizard before plaza | Dropped by a Crystal Lizard past the Central Irithyll Fire Witches and to the left |
+IBV: Twinkling Titanite - descent, lizard behind illusory wall | Dropped by a Crystal Lizard behind an illusory wall before going down the stairs to the lake leading to the Distant Manor bonfire |
+IBV: Undead Bone Shard - descent, behind gravestone | In the graveyard down the stairs from the Church of Yorshka, behind the grave with the Corvian |
+IBV: Witchtree Branch - by Dorhys | In the area with Cathedral Evangelist Dorhys, past an illusory railing past the Central Irithyll Fire Witches |
+IBV: Wood Grain Ring+2 - ascent, right after great hall | Leaving the building with the Silver Knight staring at the painting, instead of going left up the stairs, go right |
+IBV: Yorshka's Spear - descent, dark room rafters chest | In a chest in the rafters of the dark area with the Irithyllian slaves |
+ID: Alva Armor - B3 near, by Karla's cell, after killing Alva | In the main Jailer cell block on the floor close to Karla's cell, if the invading Alva is killed |
+ID: Alva Gauntlets - B3 near, by Karla's cell, after killing Alva | In the main Jailer cell block on the floor close to Karla's cell, if the invading Alva is killed |
+ID: Alva Helm - B3 near, by Karla's cell, after killing Alva | In the main Jailer cell block on the floor close to Karla's cell, if the invading Alva is killed |
+ID: Alva Leggings - B3 near, by Karla's cell, after killing Alva | In the main Jailer cell block on the floor close to Karla's cell, if the invading Alva is killed |
+ID: Bellowing Dragoncrest Ring - drop from B1 towards pit | Dropping down from the Jailbreaker's Key shortcut at the end of the top corridor on the bonfire side in Irithyll Dungeon |
+ID: Covetous Gold Serpent Ring - Siegward's cell | In the Old Cell where Siegward is rescued |
+ID: Covetous Silver Serpent Ring+1 - pit lift, middle platform | On one of the platforms in elevator shaft of the shortcut elevator from the Giant Slave area to the Irithyll Dungeon bonfire |
+ID: Dark Clutch Ring - stairs between pit and B3, mimic | Dropped by the mimic found going past the Giant Slave to the sewer with the rats and the basilisks, up the first flight of stairs, on the left side |
+ID: Dragon Torso Stone - B3, outside lift | On the balcony corpse in the Path of the Dragon pose |
+ID: Dragonslayer Lightning Arrow - pit, mimic in hall | Dropped by the mimic in the side corridor from where the Giant Slave is standing, before the long ladder |
+ID: Dung Pie - B3, by path from pit | In the room with the Giant Hound Rats |
+ID: Dung Pie - pit, miniboss drop | Drop from the Giant Slave |
+ID: Dusk Crown Ring - B3 far, right cell | In the cell in the main Jailer cell block to the left of the Profaned Capital exit |
+ID: Ember - B3 center | At the center pillar in the main Jailer cell block |
+ID: Ember - B3 far right | In the main Jailer cell block, on the left side coming from the Profaned Capital |
+ID: Estus Shard - mimic on path from B2 to pit | Dropped by the mimic in the room after the outside area of Irithyll Dungeon overlooking Profaned Capital |
+ID: Fading Soul - B1 near, main hall | On the top corridor on the bonfire side in Irithyll Dungeon, close to the first Jailer |
+ID: Great Magic Shield - B2 near, mob drop in far left cell | One-time drop from the Infested Corpse in the bottom corridor on the bonfire side of Irithyll Dungeon, in the closest cell |
+ID: Homeward Bone - path from B2 to pit | In the part of Irithyll Dungeon overlooking the Profaned Capital, after exiting the last jail cell corridor |
+ID: Jailbreaker's Key - B1 far, cell after gate | In the cell of the top corridor opposite to the bonfire in Irithyll Dungeon |
+ID: Large Soul of a Nameless Soldier - B2 far, by lift | Taking the elevator up from the area you can use Path of the Dragon, before the one-way door |
+ID: Large Soul of a Nameless Soldier - B2, hall by stairs | At the end of the bottom corridor on the bonfire side in Irithyll Dungeon |
+ID: Large Soul of a Weary Warrior - just before Profaned Capital | In the open area before the bridge leading into Profaned Capital from Irithyll Dungeon |
+ID: Large Titanite Shard - B1 far, rightmost cell | In a cell on the far end of the top corridor opposite to the bonfire in Irithyll Dungeon, nearby the Jailer |
+ID: Large Titanite Shard - B1 near, by door | At the end of the top corridor on the bonfire side in Irithyll Dungeon, before the Jailbreaker's Key door |
+ID: Large Titanite Shard - B3 near, right corner | In the main Jailer cell block, to the left of the hallway leading to the Path of the Dragon area |
+ID: Large Titanite Shard - after bonfire, second cell on right | In the second cell on the right after Irithyll Dungeon bonfire |
+ID: Large Titanite Shard - pit #1 | On the floor where the Giant Slave is standing |
+ID: Large Titanite Shard - pit #2 | On the floor where the Giant Slave is standing |
+ID: Lightning Blade - B3 lift, middle platform | On the middle platform riding the elevator up from the Path of the Dragon area |
+ID: Lightning Bolt - awning over pit | On the wooden overhangs above the Giant Slave. Can be reached by dropping down after climbing the long ladder around the area where the Giant stands. |
+ID: Murakumo - Alva drop | Dropped by Alva, Seeker of the Spurned when he invades in the cliffside path to Irithyll Dungeon |
+ID: Old Cell Key - stairs between pit and B3 | In a chest found going past the Giant Slave to the sewer with the rats and the basilisks, up the stairs to the end, on the right side |
+ID: Old Sorcerer Boots - B2 near, middle cell | In one of the cells on the bottom corridor on the bonfire side in Irithyll Dungeon, close to the bonfire, with many Infested Corpses |
+ID: Old Sorcerer Coat - B2 near, middle cell | In one of the cells on the bottom corridor on the bonfire side in Irithyll Dungeon, close to the bonfire, with many Infested Corpses |
+ID: Old Sorcerer Gauntlets - B2 near, middle cell | In one of the cells on the bottom corridor on the bonfire side in Irithyll Dungeon, close to the bonfire, with many Infested Corpses |
+ID: Old Sorcerer Hat - B2 near, middle cell | In one of the cells on the bottom corridor on the bonfire side in Irithyll Dungeon, close to the bonfire, with many Infested Corpses |
+ID: Pale Pine Resin - B1 far, cell with broken wall | In the jail cell with the broken wall in the top corridor opposite to the bonfire in Irithyll Dungeon, near the passive Wretch on the wall |
+ID: Pickaxe - path from pit to B3 | Passing by the Giant Slave, before the tunnel with the rats and basilisks |
+ID: Prisoner Chief's Ashes - B2 near, locked cell by stairs | In the cell at the far end of the bottom corridor on the bonfire side in Irithyll Dungeon |
+ID: Profaned Coal - B3 far, left cell | In the room with the Wretches next to the main Jailer cell block, guarded by a Wretch |
+ID: Profaned Flame - pit | On the floor where the Giant Slave is standing |
+ID: Rusted Coin - after bonfire, first cell on left | In the first cell on the left from the Irithyll dungeon bonfire |
+ID: Rusted Gold Coin - after bonfire, last cell on right | In the third cell on the right from the Irithyll Dungeon bonfire |
+ID: Simple Gem - B2 far, cell by stairs | In the cell near the bottom corridor opposite to the bonfire in Irithyll Dungeon, adjacent to the room with three Jailers and Cage Spiders |
+ID: Soul of a Crestfallen Knight - balcony above pit | Under whether the Giant Slave is resting his head |
+ID: Soul of a Weary Warrior - by drop to pit | At the end of the room with many peasant hollows after the Estus Shard mimic |
+ID: Soul of a Weary Warrior - stairs between pit and B3 | Going past the Giant Slave to the sewer with the rats and the basilisks, up the first flight of stairs |
+ID: Titanite Chunk - balcony above pit, lizard | Dropped by the Crystal Lizard where the Giant Slave is resting his head |
+ID: Titanite Chunk - pit, miniboss drop | Drop from the Giant Slave |
+ID: Titanite Scale - B2 far, lizard | Dropped by the Crystal Lizard on the bottom corridor opposite from the bonfire in Irithyll Dungeon where a Wretch attacks you |
+ID: Titanite Scale - B3 far, mimic in hall | Dropped by the mimic in the main Jailer cell block |
+ID: Titanite Slab - Siegward | Given by Siegward after unlocking Old Cell or on quest completion |
+ID: Xanthous Ashes - B3 far, right cell | In the cell in the main Jailer cell block to the left of the Profaned Capital exit |
+KFF: Soul of the Lords | Dropped by Soul of Cinder |
+LC: Black Firebomb - dark room lower | In the room with the firebomb-throwing hollows, against the wall on the lowest level |
+LC: Braille Divine Tome of Lothric - wyvern room | In the room next to the second Pus of Man wyvern |
+LC: Caitha's Chime - chapel, drop onto roof | Dropping down from the chapel balcony where the Red Tearstone Ring is found, and then dropping down again towards the Lothric knights |
+LC: Dark Stoneplate Ring+1 - wyvern room, balcony | Through the room next to the second Pus of Man wyvern, on the balcony outside |
+LC: Ember - by Dragon Barracks bonfire | Near the Dragon Barracks bonfire |
+LC: Ember - dark room mid, pus of man mob drop | Dropped by the first Pus of Man wyvern |
+LC: Ember - main hall, left of stairs | To the left of the stairs past the Dragon Barracks grate |
+LC: Ember - plaza center | In the area where the Pus of Man wyverns breathe fire |
+LC: Ember - plaza, by gate | On the railing near the area where the Pus of Man wyverns breathe fire, before the gate |
+LC: Ember - wyvern room, wyvern foot mob drop | Dropped by the second Pus of Man wyvern |
+LC: Gotthard Twinswords - by Grand Archives door, after PC and AL bosses | Before the door to the Grand Archives after Aldrich and Yhorm are killed |
+LC: Grand Archives Key - by Grand Archives door, after PC and AL bosses | Before the door to the Grand Archives after Aldrich and Yhorm are killed |
+LC: Greatlance - overlooking Dragon Barracks bonfire | Guarded by a pensive Lothric Knight after the Dragon Barracks bonfire and continuing up the stairs |
+LC: Hood of Prayer | In a chest right after the Lothric Castle bonfire |
+LC: Irithyll Rapier - basement, miniboss drop | Dropped by the Boreal Outrider Knight in the basement |
+LC: Knight's Ring - altar | Climbing the ladder to the rooftop outside the Dragonslayer Armour fight, past the Large Hollow Soldier, down into the room with the tables |
+LC: Large Soul of a Nameless Soldier - dark room mid | In the room with the firebomb-throwing hollows, up the ladder |
+LC: Large Soul of a Nameless Soldier - moat, right path | Found on the ledge after dropping into the area with the Pus of Man transforming hollows and making the entire loop |
+LC: Large Soul of a Nameless Soldier - plaza left, by pillar | In the building to the left of the area where the Pus of Man wyverns breathe fire, against a pillar |
+LC: Large Soul of a Weary Warrior - ascent, last turret | Rather than going up the stairs to the Dragon Barracks bonfire, continue straight down the stairs and forwards |
+LC: Large Soul of a Weary Warrior - main hall, by lever | On a ledge to the right of the lever opening the grate |
+LC: Life Ring+2 - dark room mid, out door opposite wyvern, drop down | Past the room with the firebomb-throwing hollows and Pus of Man wyvern, around to the front, dropping down past where the Titanite Chunk is |
+LC: Lightning Urn - moat, right path, first room | Starting the loop from where the Pus of Man hollows transform, behind some crates in the first room |
+LC: Lightning Urn - plaza | In the area where the Pus of Man wyverns breathe fire |
+LC: Pale Pine Resin - dark room upper, by mimic | In the room with the firebomb-throwing hollows, next to the mimic in the far back left |
+LC: Raw Gem - plaza left | On a balcony to the left of the area where the Pus of Man wyverns breathe fire, where the Hollow Soldier throws Undead Hunter Charms |
+LC: Red Tearstone Ring - chapel, drop onto roof | From the chapel to the right of the Dragonslayer Armour fight, on the balcony to the left |
+LC: Refined Gem - plaza | In the area where the Pus of Man wyverns breathe fire |
+LC: Robe of Prayer - ascent, chest at beginning | In a chest right after the Lothric Castle bonfire |
+LC: Rusted Coin - chapel | In the chapel to the right of the Dragonslayer Armour fight |
+LC: Sacred Bloom Shield - ascent, behind illusory wall | Up the ladder where the Winged Knight is waiting, past an illusory wall |
+LC: Skirt of Prayer - ascent, chest at beginning | In a chest right after the Lothric Castle bonfire |
+LC: Sniper Bolt - moat, right path end | Hanging from the arch passed under on the way to the Dragon Barracks bonfire. Can be accessed by dropping into the area with the Pus of Man transforming hollows and making the entire loop, but going left at the end |
+LC: Sniper Crossbow - moat, right path end | Hanging from the arch passed under on the way to the Dragon Barracks bonfire. Can be accessed by dropping into the area with the Pus of Man transforming hollows and making the entire loop, but going left at the end |
+LC: Soul of Dragonslayer Armour | Dropped by Dragonslayer Armour |
+LC: Soul of a Crestfallen Knight - by lift bottom | Guarded by a buffed Lothric Knight straight from the Dancer bonfire |
+LC: Soul of a Crestfallen Knight - wyvern room, balcony | On a ledge accessible after the second Pus of Man wyvern is defeated |
+LC: Spirit Tree Crest Shield - basement, chest | In a chest in the basement with the Outrider Knight |
+LC: Sunlight Medal - by lift top | Next to the shortcut elevator outside of the Dragonslayer Armour fight that goes down to the start of the area |
+LC: Sunlight Straight Sword - wyvern room, mimic | Dropped by the mimic in the room next to the second Pus of Man wyvern |
+LC: Thunder Stoneplate Ring+2 - chapel, drop onto roof | Dropping down from the chapel balcony where the Red Tearstone Ring is found, out on the edge |
+LC: Titanite Chunk - altar roof | Climbing the ladder to the rooftop outside the Dragonslayer Armour fight, overlooking the tree |
+LC: Titanite Chunk - ascent, final turret | Rather than going up the stairs to the Dragon Barracks bonfire, continue straight down the stairs, then right |
+LC: Titanite Chunk - ascent, first balcony | Right after the Lothric Castle bonfire, out on the balcony |
+LC: Titanite Chunk - ascent, turret before barricades | From the Lothric Castle bonfire, up the stairs, straight, and then down the stairs behind the barricade |
+LC: Titanite Chunk - dark room mid, out door opposite wyvern | From the room with the firebomb-throwing hollows, past the Pus of Man Wyvern and back around the front, before the Crystal Lizard |
+LC: Titanite Chunk - dark room mid, pus of man mob drop | Dropped by the first Pus of Man wyvern |
+LC: Titanite Chunk - down stairs after boss | Down the stairs to the right after Dragonslayer Armour |
+LC: Titanite Chunk - moat #1 | In the center of the area where the Pus of Man hollows transform |
+LC: Titanite Chunk - moat #2 | In the center of the area where the Pus of Man hollows transform |
+LC: Titanite Chunk - moat, near ledge | Dropping down from the bridge where the Pus of Man wyverns breathe fire on the near side to the bonfire |
+LC: Titanite Chunk - wyvern room, wyvern foot mob drop | Dropped by the second Pus of Man wyvern |
+LC: Titanite Scale - altar | In a chest climbing the ladder to the rooftop outside the Dragonslayer Armour fight, continuing the loop past the Red-Eyed Lothric Knight |
+LC: Titanite Scale - basement, chest | In a chest in the basement with the Outrider Knight |
+LC: Titanite Scale - chapel, chest | In a chest in the chapel to the right of the Dragonslayer Armour fight |
+LC: Titanite Scale - dark room mid, out door opposite wyvern | Passing through the room with the firebomb-throwing hollows and the Pus of Man wyvern around to the front, overlooking the area where the wyverns breathe fire |
+LC: Titanite Scale - dark room, upper balcony | In the room with the firebomb-throwing hollows, at the very top on a balcony to the right |
+LC: Titanite Scale - dark room, upper, mimic | Dropped by the crawling mimic at the top of the room with the firebomb-throwing hollows |
+LC: Twinkling Titanite - ascent, side room | In the room where the Winged Knight drops down |
+LC: Twinkling Titanite - basement, chest #1 | In a chest in the basement with the Outrider Knight |
+LC: Twinkling Titanite - basement, chest #2 | In a chest in the basement with the Outrider Knight |
+LC: Twinkling Titanite - dark room mid, out door opposite wyvern, lizard | Dropped by the Crystal Lizard after the room with the firebomb-throwing hollows around the front |
+LC: Twinkling Titanite - moat, left side | Behind one of the Pus of Man transforming hollows, to the left of the bridge to the wyvern fire-breathing area |
+LC: Twinkling Titanite - moat, right path, lizard | Dropped by the Crystal Lizard near the thieves after dropping down to the area with the Pus of Man transforming hollows |
+LC: Undead Bone Shard - moat, far ledge | Dropping down from the bridge where the Pus of Man wyverns breathe fire on the far side from the bonfire |
+LC: Winged Knight Armor - ascent, behind illusory wall | In the area where the Winged Knight drops down, up the ladder and past the illusory wall |
+LC: Winged Knight Gauntlets - ascent, behind illusory wall | In the area where the Winged Knight drops down, up the ladder and past the illusory wall |
+LC: Winged Knight Helm - ascent, behind illusory wall | In the area where the Winged Knight drops down, up the ladder and past the illusory wall |
+LC: Winged Knight Leggings - ascent, behind illusory wall | In the area where the Winged Knight drops down, up the ladder and past the illusory wall |
+PC: Blooming Purple Moss Clump - walkway above swamp | At the right end of the plank before dropping down into the Profaned Capital toxic pool |
+PC: Cinders of a Lord - Yhorm the Giant | Dropped by Yhorm the Giant |
+PC: Court Sorcerer Gloves - chapel, second floor | On the second floor of the Monstrosity of Sin building in front of the Monstrosity of Sin |
+PC: Court Sorcerer Hood - chapel, second floor | On the second floor of the Monstrosity of Sin building in front of the Monstrosity of Sin |
+PC: Court Sorcerer Robe - chapel, second floor | On the second floor of the Monstrosity of Sin building in front of the Monstrosity of Sin |
+PC: Court Sorcerer Trousers - chapel, second floor | On the second floor of the Monstrosity of Sin building in front of the Monstrosity of Sin |
+PC: Court Sorcerer's Staff - chapel, mimic on second floor | Dropped by the mimic on the second floor of the Monstrosity of Sin building |
+PC: Cursebite Ring - swamp, below halls | In the inner cave of the Profaned Capital toxic pool |
+PC: Eleonora - chapel ground floor, kill mob | Dropped by the Monstrosity of Sin on the first floor, furthest away from the door |
+PC: Ember - palace, far room | To the right of the Profaned Flame, in the room with the many Jailers looking at the mimics |
+PC: Flame Stoneplate Ring+1 - chapel, drop from roof towards entrance | Dropping down from the roof connected to the second floor of the Monstrosity of Sin building, above the main entrance to the building |
+PC: Greatshield of Glory - palace, mimic in far room | Dropped by the left mimic surrounded by the Jailers to the right of the Profaned Flame |
+PC: Jailer's Key Ring - hall past chapel | Past the Profaned Capital Court Sorcerer, in the corridor overlooking the Irithyll Dungeon Giant Slave area |
+PC: Large Soul of a Weary Warrior - bridge, far end | On the way from the Profaned Capital bonfire toward the Profaned Flame, crossing the bridge without dropping down |
+PC: Logan's Scroll - chapel roof, NPC drop | Dropped by the court sorcerer above the toxic pool |
+PC: Magic Stoneplate Ring+2 - tower base | At the base of the Profaned Capital structure, going all the way around the outside wall clockwise |
+PC: Onislayer Greatarrow - bridge | Item on the bridge descending from the Profaned Capital bonfire into the Profaned Flame building |
+PC: Onislayer Greatbow - drop from bridge | From the bridge leading from the Profaned Capital bonfire to Yhorm, onto the ruined pillars shortcut to the right, behind you after the first dropdown. |
+PC: Pierce Shield - Siegward | Dropped by Siegward upon death or quest completion, and sold by Patches while Siegward is in the well. |
+PC: Poison Arrow - chapel roof | At the far end of the roof with the Court Sorcerer |
+PC: Poison Gem - swamp, below halls | In the inner cave of the Profaned Capital toxic pool |
+PC: Purging Stone - chapel ground floor | At the back of the room with the three Monstrosities of Sin on the first floor |
+PC: Purging Stone - swamp, by chapel ladder | In the middle of the Profaned Capital toxic pool, near the ladder to the Court Sorcerer |
+PC: Rubbish - chapel, down stairs from second floor | Hanging corpse visible from Profaned Capital accessible from the second floor of the building with the Monstrosities of Sin, in the back right |
+PC: Rusted Coin - below bridge #1 | Among the rubble before the steps leading up to the Profaned Flame |
+PC: Rusted Coin - below bridge #2 | Among the rubble before the steps leading up to the Profaned Flame |
+PC: Rusted Coin - tower exterior | Treasure visible on a ledge in the Profaned Capital bonfire. Can be accessed by climbing a ladder outside the main structure. |
+PC: Rusted Gold Coin - halls above swamp | In the corridors leading to the Profaned Capital toxic pool |
+PC: Rusted Gold Coin - palace, mimic in far room | Dropped by the right mimic surrounded by the Jailers to the right of the Profaned Flame |
+PC: Shriving Stone - swamp, by chapel door | At the far end of the Profaned Capital toxic pool, to the left of the door leading to the Monstrosities of Sin |
+PC: Siegbräu - Siegward after killing boss | Given by Siegward after helping him defeat Yhorm the Giant. You must talk to him before Emma teleports you. |
+PC: Soul of Yhorm the Giant | Dropped by Yhorm the Giant |
+PC: Storm Ruler - Siegward | Dropped by Siegward upon death or quest completion. |
+PC: Storm Ruler - boss room | To the right of Yhorm's throne |
+PC: Twinkling Titanite - halls above swamp, lizard #1 | Dropped by the second Crystal Lizard in the corridors before the Profaned Capital toxic pool |
+PC: Twinkling Titanite - halls above swamp, lizard #2 | Dropped by the first Crystal Lizard in the corridors before the Profaned Capital toxic pool |
+PC: Undead Bone Shard - by bonfire | On the corpse of Laddersmith Gilligan next to the Profaned Capital bonfire |
+PC: Wrath of the Gods - chapel, drop from roof | Dropping down from the roof of the Monstrosity of Sin building where the Court Sorcerer is |
+PW1: Black Firebomb - snowfield lower, path to bonfire | Dropping down after the first snow overhang and following the wall on the left, past the rotting bed descending toward the second bonfire |
+PW1: Blessed Gem - snowfield, behind tower | Behind the Millwood Knight tower in the first area, approach from the right side |
+PW1: Budding Green Blossom - settlement courtyard, ledge | After sliding down the slope on the way to Corvian Settlement, dropping down hugging the left wall |
+PW1: Captain's Ashes - snowfield tower, 6F | At the very top of the Millwood Knight tower after climbing up the second ladder |
+PW1: Chillbite Ring - Friede | Given by Sister Friede while she is sitting in the Ariandel Chapel, or on the stool after she moves. |
+PW1: Contraption Key - library, NPC drop | Dropped by Sir Vilhelm |
+PW1: Crow Quills - settlement loop, jump into courtyard | Crossing the bridge after Corvian Settlement bonfire, follow the left edge past another bridge until a dropdown point looping back to the bonfire. Go right and jump past some barrels onto the central platform. |
+PW1: Crow Talons - settlement roofs, near bonfire | After climbing the ladder onto Corvian Settlement rooftops, dropping down on a bridge to the left, into the building, then looping around onto its roof. |
+PW1: Dark Gem - settlement back, egg building | Dropping down to the right of the gate guarded by a Corvian Knight in Corvian Settlement, inside of the last building on the right |
+PW1: Ember - roots above depths | In the tree branch area after climbing down the rope bridge, hugging a right wall past a Follower Javelin wielder |
+PW1: Ember - settlement main, left building after bridge | Crossing the bridge after Corvian Settlement bonfire, in the building to the left. |
+PW1: Ember - settlement, building near bonfire | In the first building in Corvian Settlement next to the bonfire building |
+PW1: Ethereal Oak Shield - snowfield tower, 3F | In the Millwood Knight tower on a Millwood Knight corpse, after climbing the first ladder, then going down the staircase |
+PW1: Follower Javelin - snowfield lower, path back up | Dropping down after the first snow overhang, follow the right wall around and up a slope, past the Followers |
+PW1: Follower Sabre - roots above depths | On a tree branch after climbing down the rope bridge. Rather than hugging a right wall toward a Follower Javelin wielder, drop off to the left. |
+PW1: Frozen Weapon - snowfield lower, egg zone | Dropping down after the first snow overhang, in the rotting bed along the left side |
+PW1: Heavy Gem - snowfield village | Before the Millwood Knight tower, on the far side of one of the ruined walls targeted by the archer |
+PW1: Hollow Gem - beside chapel | To the right of the entrance to the Ariandel |
+PW1: Homeward Bone - depths, up hill | In the Depths of the Painting, up a hill next to the giant crabs. |
+PW1: Homeward Bone - snowfield village, outcropping | Dropping down after the first snow overhang and following the cliff on the right, making a sharp right after a ruined wall segment before approaching the Millwood Knight tower |
+PW1: Large Soul of a Weary Warrior - settlement hall roof | On top of the chapel with the Corvian Knight to the left of Vilhelm's building |
+PW1: Large Soul of a Weary Warrior - snowfield tower, 6F | At the very top of the Millwood Knight tower after climbing up the second ladder, on a Millwood Knight corpse |
+PW1: Large Soul of an Unknown Traveler - below snowfield village overhang | Up the slope to the left of the Millwood Knight tower, dropping down after a snow overhang, then several more ledges. |
+PW1: Large Soul of an Unknown Traveler - settlement back | In Corvian Settlement, on the ground before the ladder climbing onto the rooftops |
+PW1: Large Soul of an Unknown Traveler - settlement courtyard, cliff | After sliding down the slope on the way to Corvian Settlement, on a cliff to the right and behind |
+PW1: Large Soul of an Unknown Traveler - settlement loop, by bonfire | Crossing the bridge after Corvian Settlement bonfire, follow the left edge past another bridge until a dropdown point looping back to the bonfire. On the corpse in a hole in the wall leading back to the bonfire. |
+PW1: Large Soul of an Unknown Traveler - settlement roofs, balcony | After climbing the ladder onto Corvian Settlement rooftops, dropping down on a bridge to the left, on the other side of the bridge. |
+PW1: Large Soul of an Unknown Traveler - settlement, by ladder to bonfire | To the right of the ladder leading up to Corvian Settlement bonfire. |
+PW1: Large Soul of an Unknown Traveler - snowfield lower, by cliff | Dropping down after the first snow overhang, between the forest and the cliff edge, before where the large wolf drops down |
+PW1: Large Soul of an Unknown Traveler - snowfield lower, path back up | Dropping down after the first snow overhang, follow the right wall around and up a slope, past the Followers |
+PW1: Large Soul of an Unknown Traveler - snowfield lower, path to village | Dropping down after the first snow overhang and following the cliff on the right, on a tree past where the large wolf jumps down |
+PW1: Large Soul of an Unknown Traveler - snowfield upper | Going straight after the first bonfire, to the left of the caving snow overhand |
+PW1: Large Titanite Shard - lizard under bridge near | Dropped by a Crystal Lizard after the Rope Bridge Cave on the way to Corvian Settlement |
+PW1: Large Titanite Shard - settlement loop, lizard | Crossing the bridge after Corvian Settlement bonfire, follow the left edge past another bridge until a dropdown point looping back to the bonfire. Hug the bonfire building's outer wall along the right side. |
+PW1: Large Titanite Shard - snowfield lower, left from fall | Dropping down after the first snow overhang, guarded by a Tree Woman overlooking the rotting bed along the left wall |
+PW1: Millwood Battle Axe - snowfield tower, 5F | In the Milkwood Knight tower, either dropping down from rafters after climbing the second ladder or making a risky jump |
+PW1: Millwood Greatarrow - snowfield village, loop back to lower | Dropping down after the first snow overhang and following the cliff on the right, making the full loop around, up the slope leading towards where the large wolf drops down |
+PW1: Millwood Greatbow - snowfield village, loop back to lower | Dropping down after the first snow overhang and following the cliff on the right, making the full loop around, up the slope leading towards where the large wolf drops down |
+PW1: Onyx Blade - library, NPC drop | Dropped by Sir Vilhelm |
+PW1: Poison Gem - snowfield upper, forward from bonfire | Following the left wall from the start, guarded by a Giant Fly |
+PW1: Rime-blue Moss Clump - below bridge far | In a small alcove to the right after climbing down the rope bridge |
+PW1: Rime-blue Moss Clump - snowfield upper, overhang | On the first snow overhang at the start. It drops down at the same time you do. |
+PW1: Rime-blue Moss Clump - snowfield upper, starting cave | In the starting cave |
+PW1: Rusted Coin - right of library | To the right of Vilhelm's building |
+PW1: Rusted Coin - snowfield lower, straight from fall | Dropping down after the first snow overhang, shortly straight ahead |
+PW1: Rusted Gold Coin - settlement roofs, roof near second ladder | After climbing the second ladder on the Corvian Settlement rooftops, immediately dropping off the bridge to the right, on a rooftop |
+PW1: Shriving Stone - below bridge near | After the Rope Bridge Cave bonfire, dropping down before the bridge, following the ledge all the way to the right |
+PW1: Simple Gem - settlement, lowest level, behind gate | Crossing the bridge after Corvian Settlement bonfire, follow the left edge until a bridge, then drop down on the right side. Guarded by a Sewer Centipede. |
+PW1: Slave Knight Armor - settlement roofs, drop by ladder | In Corvian Settlement, rather than climbing up a ladder leading to a bridge to the roof of the chapel with the Corvian Knight, dropping down a hole to the left of the ladder into the building below. |
+PW1: Slave Knight Gauntlets - settlement roofs, drop by ladder | In Corvian Settlement, rather than climbing up a ladder leading to a bridge to the roof of the chapel with the Corvian Knight, dropping down a hole to the left of the ladder into the building below. |
+PW1: Slave Knight Hood - settlement roofs, drop by ladder | In Corvian Settlement, rather than climbing up a ladder leading to a bridge to the roof of the chapel with the Corvian Knight, dropping down a hole to the left of the ladder into the building below. |
+PW1: Slave Knight Leggings - settlement roofs, drop by ladder | In Corvian Settlement, rather than climbing up a ladder leading to a bridge to the roof of the chapel with the Corvian Knight, dropping down a hole to the left of the ladder into the building below. |
+PW1: Snap Freeze - depths, far end, mob drop | In the Depths of the Painting, past the giant crabs, guarded by a special Tree Woman. Killing her drops down a very long nearby ladder. |
+PW1: Soul of a Crestfallen Knight - settlement hall, rafters | In the rafters of the chapel with the Corvian Knight to the left of Vilhelm's building. Can drop down from the windows exposed to the roof. |
+PW1: Soul of a Weary Warrior - snowfield tower, 1F | At the bottom of the Millwood Knight tower on a Millwood Knight corpse |
+PW1: Titanite Slab - Corvian | Given by the Corvian NPC in the building next to Corvian Settlement bonfire. |
+PW1: Titanite Slab - depths, up secret ladder | In the Depths of the Painting, past the giant crabs, killing a special Tree Woman drops down a very long nearby ladder. Climb the ladder and also the ladder after that one. |
+PW1: Twinkling Titanite - roots, lizard | Dropped by a Crystal Lizard in the tree branch area after climbing down the rope bridge, before the ledge with the Follower Javelin wielder |
+PW1: Twinkling Titanite - settlement roofs, lizard before hall | Dropped by a Crystal Lizard on a bridge in Corvian Settlement before the rooftop of the chapel with the Corvian Knight inside. |
+PW1: Twinkling Titanite - snowfield tower, 3F lizard | Dropped by a Crystal Lizard in the Millwood Knight tower, climbing up the first ladder and descending the stairs down |
+PW1: Valorheart - boss drop | Dropped by Champion's Gravetender |
+PW1: Way of White Corona - settlement hall, by altar | In the chapel with the Corvian Knight to the left of Vilhelm's building, in front of the altar. |
+PW1: Young White Branch - right of library | To the right of Vilhelm's building |
+PW2: Blood Gem - B2, center | On the lower level of the Ariandel Chapel basement, in the middle |
+PW2: Dung Pie - B1 | On the higher level of the Ariandel Chapel basement, on a wooden beam overlooking the lower level |
+PW2: Earth Seeker - pit cave | In the area after Snowy Mountain Pass with the giant tree and Earth Seeker Millwood Knight, in the cave |
+PW2: Ember - pass, central alcove | After the Snowy Mountain Pass bonfire, going left of the bell stuck in the ground, in a small alcove along the left wall |
+PW2: Floating Chaos - NPC drop | Dropped by Livid Pyromancer Dunnel when he invades while embered, whether boss is defeated or not. On the second level of Priscilla's building above the Gravetender fight, accessed from the lowest level of the Ariandel Chapel basement, past an illusory wall nearly straight left of the mechanism that moves the statue, then carefully dropping down tree branches. |
+PW2: Follower Shield - pass, far cliffside | After the Snowy Mountain Pass bonfire, going left of the bell stuck in the ground, on the cliff ledge past the open area, to the left |
+PW2: Follower Torch - pass, far side path | On the way to the Ariandel Chapel basement, where the first wolf enemies reappear, going all the way down the slope on the edge of the map. Guarded by a Follower |
+PW2: Homeward Bone - rotunda | On the second level of Priscilla's building above the Gravetender fight. Can be accessed from the lowest level of the Ariandel Chapel basement, past an illusory wall nearly straight left of the mechanism that moves the statue, then carefully dropping down tree branches. |
+PW2: Large Soul of a Crestfallen Knight - pit, by tree | In the area after Snowy Mountain Pass with the giant tree and Earth Seeker Millwood Knight, by the tree |
+PW2: Large Titanite Shard - pass, far side path | On the way to the Ariandel Chapel basement, where the first wolf enemies reappear, going partway down the slope on the edge of the map |
+PW2: Large Titanite Shard - pass, just before B1 | On the way to Ariandel Chapel basement, past the Millwood Knights and before the first rotten tree that can be knocked down |
+PW2: Prism Stone - pass, tree by beginning | Up the slope and to the left after the Snowy Mountain Pass, straight ahead by a tree |
+PW2: Pyromancer's Parting Flame - rotunda | On the second level of Priscilla's building above the Gravetender fight. Can be accessed from the lowest level of the Ariandel Chapel basement, past an illusory wall nearly straight left of the mechanism that moves the statue, then carefully dropping down tree branches. |
+PW2: Quakestone Hammer - pass, side path near B1 | On the way to Ariandel Chapel basement, rather than going right past the two Millwood Knights, go left, guarded by a very strong Millwood Knight |
+PW2: Soul of Sister Friede | Dropped by Sister Friede |
+PW2: Soul of a Crestfallen Knight - pit edge #1 | In the area after Snowy Mountain Pass with the giant tree and Earth Seeker Millwood Knight, along the edge |
+PW2: Soul of a Crestfallen Knight - pit edge #2 | In the area after Snowy Mountain Pass with the giant tree and Earth Seeker Millwood Knight, along the edge |
+PW2: Titanite Chunk - pass, by kickable tree | After the Snowy Mountain Pass bonfire, on a ledge to the right of the slope with the bell stuck in the ground, behind a tree |
+PW2: Titanite Chunk - pass, cliff overlooking bonfire | On a cliff overlooking the Snowy Mountain Pass bonfire. Requires following the left wall |
+PW2: Titanite Slab - boss drop | One-time drop after killing Father Ariandel and Friede (phase 2) for the first time. |
+PW2: Twinkling Titanite - B3, lizard #1 | Dropped by a Crystal Lizard past an illusory wall nearly straight left of the mechanism that moves the statue in the lowest level of the Ariandel Chapel basement |
+PW2: Twinkling Titanite - B3, lizard #2 | Dropped by a Crystal Lizard past an illusory wall nearly straight left of the mechanism that moves the statue in the lowest level of the Ariandel Chapel basement |
+PW2: Vilhelm's Armor - B2, along wall | On the lower level of the Ariandel Chapel basement, along a wall to the left of the contraption that turns the statue |
+PW2: Vilhelm's Gauntlets - B2, along wall | On the lower level of the Ariandel Chapel basement, along a wall to the left of the contraption that turns the statue |
+PW2: Vilhelm's Helm | On the lower level of the Ariandel Chapel basement, along a wall to the left of the contraption that turns the statue |
+PW2: Vilhelm's Leggings - B2, along wall | On the lower level of the Ariandel Chapel basement, along a wall to the left of the contraption that turns the statue |
+RC: Antiquated Plain Garb - wall hidden, before boss | In the chapel before the Midir fight in the Ringed Inner Wall building. |
+RC: Black Witch Garb - streets garden | Guarded by Alva (invades whether embered or not), partway down the stairs from Shira, across the bridge, and past the Ringed Knight. |
+RC: Black Witch Hat - streets garden | Guarded by Alva (invades whether embered or not), partway down the stairs from Shira, across the bridge, and past the Ringed Knight. |
+RC: Black Witch Trousers - streets garden | Guarded by Alva (invades whether embered or not), partway down the stairs from Shira, across the bridge, and past the Ringed Knight. |
+RC: Black Witch Veil - swamp near right, by sunken church | To the left of the submerged building with 4 Ringed Knights, near a spear-wielding knight. |
+RC: Black Witch Wrappings - streets garden | Guarded by Alva (invades whether embered or not), partway down the stairs from Shira, across the bridge, and past the Ringed Knight. |
+RC: Blessed Gem - grave, down lowest stairs | In Shared Grave, after dropping down near Gael's flag and dropping down again, behind you. Or from the bonfire, go back through the side tunnel with the skeletons and down the stairs after that. |
+RC: Blindfold Mask - grave, NPC drop | Dropped by Moaning Knight (invades whether embered or not, or boss defeated or not) in Shared Grave. |
+RC: Blood of the Dark Soul - end boss drop | Dropped by Slave Knight Gael |
+RC: Budding Green Blossom - church path | On the way to the Halflight building. |
+RC: Budding Green Blossom - wall top, flowers by stairs | In a patch of flowers to the right of the stairs leading up to the first Judicator along the left wall of the courtyard are Mausoleum Lookout. |
+RC: Budding Green Blossom - wall top, in flower cluster | Along the left wall of the courtyard after Mausoleum Lookout, in a patch of flowers. |
+RC: Chloranthy Ring+3 - wall hidden, drop onto statue | From the mid level of the Ringed Inner Wall elevator that leads to the Midir fight, dropping back down toward the way to Filianore, onto a platform with a Gwyn statue. Try to land on the platform rather than the statue. |
+RC: Church Guardian Shiv - swamp far left, in building | Inside of the building at the remote end of the muck pit surrounded by praying Hollow Clerics. |
+RC: Covetous Gold Serpent Ring+3 - streets, by Lapp | Going up the very long ladder from the muck pit, then up some stairs, to the left, and across the bridge, in a building past the Ringed Knights. Also where Lapp can be found to tell him of the Purging Monument. |
+RC: Crucifix of the Mad King - ashes, NPC drop | Dropped by Shira, who invades you (ember not required) in the far-future version of her room |
+RC: Dark Gem - swamp near, by stairs | In the middle of the muck pit, close to the long stairs. |
+RC: Divine Blessing - streets monument, mob drop | Dropped by the Judicator near the Purging Monument area. Requires solving "Show Your Humanity" puzzle. |
+RC: Divine Blessing - wall top, mob drop | Dropped by the Judicator after the Mausoleum Lookup bonfire. |
+RC: Dragonhead Greatshield - lower cliff, under bridge | Down a slope to the right of the bridge where Midir first assaults you, past a sword-wielding Ringed Knight, under the bridge. |
+RC: Dragonhead Shield - streets monument, across bridge | Found in Purging Monument area, across the bridge from the monument. Requires solving "Show Your Humanity" puzzle. |
+RC: Ember - wall hidden, statue room | From the mid level of the Ringed Inner Wall elevator that leads to the Midir fight, in the room with the illusory statue. |
+RC: Ember - wall top, by statue | Along the left wall of the courtyard after Mausoleum Lookout, in front of a tall monument. |
+RC: Ember - wall upper, balcony | On the balcony attached to the room with the Ringed Inner Wall bonfire. |
+RC: Filianore's Spear Ornament - mid boss drop | Dropped by Halflight, Spear of the Church |
+RC: Filianore's Spear Ornament - wall hidden, by ladder | Next the ladder leading down to the chapel before the Midir fight in the Ringed Inner Wall building. |
+RC: Havel's Ring+3 - streets high, drop from building opposite | Dropping down from the building where Silver Knight Ledo invades. The building is up the very long ladder from the muck pit, down the path all the way to the right. |
+RC: Hidden Blessing - swamp center, mob drop | Dropped by Judicator patrolling the muck pit. |
+RC: Hidden Blessing - wall top, tomb under platform | In a tomb underneath the platform with the first Judicator, accessed by approaching from Mausoleum Lookout bonfire. |
+RC: Hollow Gem - wall upper, path to tower | Heading down the cursed stairs after Ringed Inner Wall bonfire and another short flight of stairs, hanging on a balcony. |
+RC: Iron Dragonslayer Armor - swamp far, miniboss drop | Dropped by Dragonslayer Armour at the far end of the muck pit. |
+RC: Iron Dragonslayer Gauntlets - swamp far, miniboss drop | Dropped by Dragonslayer Armour at the far end of the muck pit. |
+RC: Iron Dragonslayer Helm - swamp far, miniboss drop | Dropped by Dragonslayer Armour at the far end of the muck pit. |
+RC: Iron Dragonslayer Leggings - swamp far, miniboss drop | Dropped by Dragonslayer Armour at the far end of the muck pit. |
+RC: Lapp's Armor - Lapp | Left at Lapp's final location in Shared Grave after his quest is complete, or sold by Shrine Handmaid upon killing Lapp. |
+RC: Lapp's Gauntlets - Lapp | Left at Lapp's final location in Shared Grave after his quest is complete, or sold by Shrine Handmaid upon killing Lapp. |
+RC: Lapp's Helm - Lapp | Left at Lapp's final location in Shared Grave after his quest is complete, or sold by Shrine Handmaid upon killing Lapp. |
+RC: Lapp's Leggings - Lapp | Left at Lapp's final location in Shared Grave after his quest is complete, or sold by Shrine Handmaid upon killing Lapp. |
+RC: Large Soul of a Crestfallen Knight - streets monument, across bridge | Found in Purging Monument area, on the other side of the bridge leading to the monument. Requires solving "Show Your Humanity" puzzle. |
+RC: Large Soul of a Crestfallen Knight - streets, far stairs | Toward the bottom of the stairs leading down to the muck pit. |
+RC: Large Soul of a Weary Warrior - lower cliff, end | Toward the end of the upper path attacked Midir's fire-breathing. |
+RC: Large Soul of a Weary Warrior - swamp center, by peninsula | In the muck pit approaching where the Judicator patrols from the stairs. |
+RC: Large Soul of a Weary Warrior - wall lower, past two illusory walls | In the Ringed Inner Wall building coming from Shared Grave, past two illusory walls on the right side of the ascending stairs. |
+RC: Large Soul of a Weary Warrior - wall top, right of small tomb | In the open toward the end of the courtyard after the Mausoleum Lookout bonfire, on the right side of the small tomb. |
+RC: Ledo's Great Hammer - streets high, opposite building, NPC drop | Dropped by Silver Knight Ledo (invades whether embered or not, or boss defeated or not) in the building down the path to the right after climbing the very long ladder from the muck area. |
+RC: Lightning Arrow - wall lower, past three illusory walls | In the Ringed Inner Wall building coming from Shared Grave, past three illusory walls on the right side of the ascending stairs. |
+RC: Lightning Gem - grave, room after first drop | In Shared Grave, in the first room encountered after falling down from the crumbling stairs and continuing upward. |
+RC: Mossfruit - streets near left, path to garden | Partway down the stairs from Shira, across the bridge. |
+RC: Mossfruit - streets, far left alcove | Near the bottom of the stairs before the muck pit, in an alcove to the left. |
+RC: Preacher's Right Arm - swamp near right, by tower | In the muck pit behind a crystal-covered structure, close to the Ringed City Streets shortcut entrance. |
+RC: Prism Stone - swamp near, railing by bonfire | On the balcony of the path leading up to Ringed City Streets bonfire from the muck pit. |
+RC: Purging Stone - wall top, by door to upper | At the end of the path from Mausoleum Lookup to Ringed Inner Wall, just outside the door. |
+RC: Ring of the Evil Eye+3 - grave, mimic | Dropped by mimic in Shared Grave. In one of the rooms after dropping down near Gael's flag and then dropping down again. |
+RC: Ringed Knight Paired Greatswords - church path, mob drop | Dropped by Ringed Knight with paired greatswords before Filianore building. |
+RC: Ringed Knight Spear - streets, down far right hall | In a courtyard guarded by a spear-wielding Ringed Knight. Can be accessed from a hallway filled with cursed clerics on the right side going down the long stairs, or by climbing up the long ladder from the muck pit and dropping down past the Locust Preacher. |
+RC: Ringed Knight Straight Sword - swamp near, tower on peninsula | On a monument next to the Ringed City Streets building. Can be easily accessed after unlocking the shortcut by following the left wall inside and then outside the building. |
+RC: Ritual Spear Fragment - church path | To the right of the Paired Greatswords Ringed Knight on the way to Halflight. |
+RC: Rubbish - lower cliff, middle | In the middle of the upper path attacked Midir's fire-breathing, after the first alcove. |
+RC: Rubbish - swamp far, by crystal | In the remote end of the muck pit, next to a massive crystal structure between a giant tree and the building with praying Hollow Clerics, guarded by several Locust Preachers. |
+RC: Ruin Armor - wall top, under stairs to bonfire | Underneath the stairs leading down from Mausoleum Lookout. |
+RC: Ruin Gauntlets - wall top, under stairs to bonfire | Underneath the stairs leading down from Mausoleum Lookout. |
+RC: Ruin Helm - wall top, under stairs to bonfire | Underneath the stairs leading down from Mausoleum Lookout. |
+RC: Ruin Leggings - wall top, under stairs to bonfire | Underneath the stairs leading down from Mausoleum Lookout. |
+RC: Sacred Chime of Filianore - ashes, NPC drop | Given by Shira after accepting her request to kill Midir, or dropped by her in post-Filianore Ringed City. |
+RC: Shira's Armor - Shira's room after killing ashes NPC | Found in Shira's room in Ringed City after killing her in post-Filianore Ringed City. |
+RC: Shira's Crown - Shira's room after killing ashes NPC | Found in Shira's room in Ringed City after killing her in post-Filianore Ringed City. |
+RC: Shira's Gloves - Shira's room after killing ashes NPC | Found in Shira's room in Ringed City after killing her in post-Filianore Ringed City. |
+RC: Shira's Trousers - Shira's room after killing ashes NPC | Found in Shira's room in Ringed City after killing her in post-Filianore Ringed City. |
+RC: Shriving Stone - wall tower, bottom floor center | In the cylindrical building before the long stairs with many Harald Legion Knights, in the center structure on the first floor. |
+RC: Siegbräu - Lapp | Given by Lapp within the Ringed Inner Wall. |
+RC: Simple Gem - grave, up stairs after first drop | In Shared Grave, following the path after falling down from the crumbling stairs and continuing upward. |
+RC: Soul of Darkeater Midir | Dropped by Darkeater Midir |
+RC: Soul of Slave Knight Gael | Dropped by Slave Knight Gael |
+RC: Soul of a Crestfallen Knight - swamp far, behind crystal | Behind a crystal structure at the far end of the muck pit, close to the building with the praying Hollow Clerics before Dragonslayer Armour. |
+RC: Soul of a Crestfallen Knight - swamp near left, nook | In the muck pit behind all of the Hollow Clerics near the very long ladder. |
+RC: Soul of a Crestfallen Knight - wall top, under drop | After dropping down onto the side path on the right side of the Mausoleum Lookout courtyard to where the Crystal Lizard is, behind you. |
+RC: Soul of a Weary Warrior - lower cliff, by first alcove | In front of the first alcove providing shelter from Midir's fire-breathing on the way to Shared Grave. |
+RC: Soul of a Weary Warrior - swamp center | In the middle of the muck pit where the Judicator is patrolling. |
+RC: Soul of a Weary Warrior - swamp right, by sunken church | In between where the Judicator patrols in the muck pit and the submerged building with the 4 Ringed Knights. Provides some shelter from his arrows. |
+RC: Spears of the Church - hidden boss drop | Dropped by Darkeater Midir |
+RC: Titanite Chunk - streets high, building opposite | Down a path past the room where Silver Knight Ledo invades. The building is up the very long ladder from the muck pit, down the path all the way to the right. |
+RC: Titanite Chunk - streets, near left drop | Near the top of the stairs by Shira, dropping down in an alcove to the left. |
+RC: Titanite Chunk - swamp center, peninsula edge | Along the edge of the muck pit close to where the Judicator patrols. |
+RC: Titanite Chunk - swamp far left, up hill | Up a hill at the edge of the muck pit with the Hollow Clerics. |
+RC: Titanite Chunk - swamp near left, by spire top | At the edge of the muck pit, on the opposite side of the wall from the very long ladder. |
+RC: Titanite Chunk - swamp near right, behind rock | At the very edge of the muck pit, to the left of the submerged building with 4 Ringed Knights. |
+RC: Titanite Chunk - wall top, among graves | Along the right edge of the courtyard after Mausoleum Lookout in a cluster of graves. |
+RC: Titanite Chunk - wall upper, courtyard alcove | In the courtyard where the first Ringed Knight is seen, along the right wall into an alcove. |
+RC: Titanite Scale - grave, lizard past first drop | Dropped by the Crystal Lizard right after the crumbling stairs in Shared Grave. |
+RC: Titanite Scale - lower cliff, first alcove | In the first alcove providing shelter from Midir's fire-breathing on the way to Shared Grave. |
+RC: Titanite Scale - lower cliff, lower path | After dropping down from the upper path attacked by Midir's fire-breathing to the lower path. |
+RC: Titanite Scale - lower cliff, path under bridge | Partway down a slope to the right of the bridge where Midir first assaults you. |
+RC: Titanite Scale - swamp far, by miniboss | In the area at the far end of the muck pit with the Dragonslayer Armour. |
+RC: Titanite Scale - swamp far, lagoon entrance | In the area at the far end of the muck pit with the Dragonslayer Armour. |
+RC: Titanite Scale - upper cliff, bridge | On the final bridge where Midir attacks before you knock him off. |
+RC: Titanite Scale - wall lower, lizard | Dropped by the Crystal Lizard on the stairs going up from Shared Grave to Ringed Inner Wall elevator. |
+RC: Titanite Scale - wall top, behind spawn | Behind you at the very start of the level. |
+RC: Titanite Slab - ashes, NPC drop | Given by Shira after defeating Midir, or dropped by her in post-Filianore Ringed City. |
+RC: Titanite Slab - ashes, mob drop | Dropped by the Ringed Knight wandering around near Gael's arena |
+RC: Titanite Slab - mid boss drop | Dropped by Halflight, Spear of the Church |
+RC: Twinkling Titanite - church path, left of boss door | Dropping down to the left of the door leading to Halflight. |
+RC: Twinkling Titanite - grave, lizard past first drop | Dropped by the Crystal Lizard right after the crumbling stairs in Shared Grave. |
+RC: Twinkling Titanite - streets high, lizard | Dropped by the Crystal Lizard which runs across the bridge after climbing the very long ladder up from the muck pit. |
+RC: Twinkling Titanite - swamp near left | At the left edge of the muck pit coming from the stairs, guarded by a Preacher Locust. |
+RC: Twinkling Titanite - swamp near right, on sunken church | Following the sloped roof of the submerged building with the 4 Ringed Knights, along the back wall |
+RC: Twinkling Titanite - wall top, lizard on side path | Dropped by the first Crystal Lizard on the side path on the right side of the Mausoleum Lookout courtyard |
+RC: Twinkling Titanite - wall tower, jump from chandelier | In the cylindrical building before the long stairs with many Harald Legion Knights. Carefully drop down to the chandelier in the center, then jump to the second floor. The item is on a ledge. |
+RC: Violet Wrappings - wall hidden, before boss | In the chapel before the Midir fight in the Ringed Inner Wall building. |
+RC: White Birch Bow - swamp far left, up hill | Up a hill at the edge of the muck pit with the Hollow Clerics. |
+RC: White Preacher Head - swamp near, nook right of stairs | Past the balcony to the right of the Ringed City Streets bonfire room entrance. Can be accessed by dropping down straight after from the bonfire, then around to the left. |
+RC: Wolf Ring+3 - street gardens, NPC drop | Dropped by Alva (invades whether embered or not, or boss defeated or not), partway down the stairs from Shira, across the bridge, and past the Ringed Knight. |
+RC: Young White Branch - swamp far left, by white tree #1 | Next to a small birch tree at the edge of the muck pit, between the hill with the aggressive Hollow Clerics and the building with the praying Hollow Clerics outside. |
+RC: Young White Branch - swamp far left, by white tree #2 | Next to a small birch tree at the edge of the muck pit, between the hill with the aggressive Hollow Clerics and the building with the praying Hollow Clerics outside. |
+RC: Young White Branch - swamp far left, by white tree #3 | Next to a small birch tree at the edge of the muck pit, between the hill with the aggressive Hollow Clerics and the building with the praying Hollow Clerics outside. |
+RS: Blue Bug Pellet - broken stairs by Orbeck | On the broken stairs leading down from Orbeck's area, on the opposite side from Orbeck |
+RS: Blue Sentinels - Horace | Given by Horace the Hushed by first "talking" to him, or upon death. |
+RS: Braille Divine Tome of Carim - drop from bridge to Halfway Fortress | Dropping down before the bridge leading up to Halfway Fortress from Road of Sacrifices, guarded by the maggot belly dog |
+RS: Brigand Armor - beneath road | In the middle of the path where the Madwoman waits in Road of Sacrifices |
+RS: Brigand Axe - beneath road | At the start of the path leading down to the Madwoman in Road of Sacrifices |
+RS: Brigand Gauntlets - beneath road | In the middle of the path where the Madwoman waits in Road of Sacrifices |
+RS: Brigand Hood - beneath road | In the middle of the path where the Madwoman waits in Road of Sacrifices |
+RS: Brigand Trousers - beneath road | In the middle of the path where the Madwoman waits in Road of Sacrifices |
+RS: Brigand Twindaggers - beneath road | At the end of the path guarded by the Madwoman in Road of Sacrifices |
+RS: Butcher Knife - NPC drop beneath road | Dropped by the Butcher Knife-wielding madwoman near the start of Road of Sacrifices |
+RS: Chloranthy Ring+2 - road, drop across from carriage | Found dropping down from the first Storyteller Corvian on the left side rather than the right side. You can then further drop down to where the madwoman is, after healing. |
+RS: Conjurator Boots - deep water | In the deep water part of the Crucifixion Woods crab area, between a large tree and the keep wall |
+RS: Conjurator Hood - deep water | In the deep water part of the Crucifixion Woods crab area, between a large tree and the keep wall |
+RS: Conjurator Manchettes - deep water | In the deep water part of the Crucifixion Woods crab area, between a large tree and the keep wall |
+RS: Conjurator Robe - deep water | In the deep water part of the Crucifixion Woods crab area, between a large tree and the keep wall |
+RS: Crystal Gem - stronghold, lizard | Dropped by the Crystal Lizard in the building before Crystal Sage |
+RS: Ember - right of Halfway Fortress entrance | On the ledge with the Corvian with the Storyteller Staff, to the right of the Halfway Fortress entrance |
+RS: Ember - right of fire behind stronghold left room | Behind the building before Crystal Sage, approached from Crucifixion Woods bonfire. Can drop down on left side or go under bridge on right side |
+RS: Estus Shard - left of fire behind stronghold left room | Behind the building leading to Crystal Sage, approached from Crucifixion Woods bonfire. Can drop down on left side of go under bridge on right side |
+RS: Exile Greatsword - NPC drop by Farron Keep | Dropped by the greatsword-wielding Exile Knight before the ladder down to Farron Keep |
+RS: Fading Soul - woods by Crucifixion Woods bonfire | Dropping down from the Crucifixion Woods bonfire toward the Halfway Fortress, guarded by dogs |
+RS: Fallen Knight Armor - water's edge by Farron Keep | On the edge of the water surrounding the building where you descend into Farron Keep |
+RS: Fallen Knight Gauntlets - water's edge by Farron Keep | On the edge of the water surrounding the building where you descend into Farron Keep |
+RS: Fallen Knight Helm - water's edge by Farron Keep | On the edge of the water surrounding the building where you descend into Farron Keep |
+RS: Fallen Knight Trousers - water's edge by Farron Keep | On the edge of the water surrounding the building where you descend into Farron Keep |
+RS: Farron Coal - keep perimeter | At the end of the Farron Keep Perimeter building on Crucifixion Woods side, behind the Black Knight |
+RS: Golden Falcon Shield - path from stronghold right room to Farron Keep | Halfway up the stairs to the sorcerer in the building before Crystal Sage, entering from the stairs leading up from the crab area, go straight and follow the path down |
+RS: Grass Crest Shield - water by Crucifixion Woods bonfire | Dropping down into the crab area from Crucifixion Woods, on the other side of a tree from the greater crab |
+RS: Great Club - NPC drop by Farron Keep | Dropped by the club-wielding Exile Knight before the ladder down to Farron Keep |
+RS: Great Swamp Pyromancy Tome - deep water | In the deep water part of the Crucifixion Woods crab area, between a large tree and the keep wall |
+RS: Great Swamp Ring - miniboss drop, by Farron Keep | Dropped by Greater Crab in Crucifixion Woods close to the Farron Keep outer wall |
+RS: Green Blossom - by deep water | In the Crucifixion Woods crab area out in the open, close to the edge of the deep water area |
+RS: Green Blossom - water beneath stronghold | In the Crucifixion Woods crab area close to the Crucifixion Woods bonfire, along the left wall of the water area, to the right of the entrance to the building before Crystal Sage |
+RS: Heretic's Staff - stronghold left room | In the building before Crystal Sage, entering from near Crucifixion Woods, in a corner under the first stairwell and balcony |
+RS: Heysel Pick - Heysel drop | Dropped by Heysel when she invades in Road of Sacrifices |
+RS: Homeward Bone - balcony by Farron Keep | At the far end of the building where you descend into Farron Keep, by the balcony |
+RS: Large Soul of an Unknown Traveler - left of stairs to Farron Keep | In the area before you descend into Farron Keep, before the stairs to the far left |
+RS: Lingering Dragoncrest Ring+1 - water | On a tree by the greater crab near the Crucifixion Woods bonfire, after the Grass Crest Shield tree |
+RS: Morne's Ring - drop from bridge to Halfway Fortress | Dropping down before the bridge leading up to Halfway Fortress from Road of Sacrifices, guarded by the maggot belly dog |
+RS: Ring of Sacrifice - stronghold, drop from right room balcony | Drop down from the platform behind the sorcerer in the building before Crystal Sage, entering from the stairs leading up from the crab area |
+RS: Sage Ring - water beneath stronghold | In an alcove under the building before Crystal Sage, guarded by a Lycanthrope, accessible from the swamp or from dropping down |
+RS: Sellsword Armor - keep perimeter balcony | In the Farron Keep Perimeter building on Crucifixion Woods side, on the balcony on the right side overlooking the Black Knight |
+RS: Sellsword Gauntlet - keep perimeter balcony | In the Farron Keep Perimeter building on Crucifixion Woods side, on the balcony on the right side overlooking the Black Knight |
+RS: Sellsword Helm - keep perimeter balcony | In the Farron Keep Perimeter building on Crucifixion Woods side, on the balcony on the right side overlooking the Black Knight |
+RS: Sellsword Trousers - keep perimeter balcony | In the Farron Keep Perimeter building on Crucifixion Woods side, on the balcony on the right side overlooking the Black Knight |
+RS: Sellsword Twinblades - keep perimeter | In the Farron Keep Perimeter building on Crucifixion Woods side, behind and to the right of the Black Knight |
+RS: Shriving Stone - road, by start | Dropping down to the left of the first Corvian enemy in Road of Sacrifices |
+RS: Sorcerer Gloves - water beneath stronghold | In an alcove under the building before Crystal Sage, guarded by a Lycanthrope, accessible from the swamp or from dropping down |
+RS: Sorcerer Hood - water beneath stronghold | In an alcove under the building before Crystal Sage, guarded by a Lycanthrope, accessible from the swamp or from dropping down |
+RS: Sorcerer Robe - water beneath stronghold | In an alcove under the building before Crystal Sage, guarded by a Lycanthrope, accessible from the swamp or from dropping down |
+RS: Sorcerer Trousers - water beneath stronghold | In an alcove under the building before Crystal Sage, guarded by a Lycanthrope, accessible from the swamp or from dropping down |
+RS: Soul of a Crystal Sage | Dropped by Crystal Sage |
+RS: Soul of an Unknown Traveler - drop along wall from Halfway Fortress | From Halfway Fortress, hug the right wall and drop down twice on the way to the crab area |
+RS: Soul of an Unknown Traveler - right of door to stronghold left | Out in the open to the right of the building before Crystal Sage, as entered from Crucifixion Woods bonfire |
+RS: Soul of an Unknown Traveler - road, by wagon | To the right of the overturned wagon descending from the Road of Sacrifices bonfire |
+RS: Titanite Shard - road, on bridge after you go under | Crossing the bridge you go under after the first Road of Sacrifices bonfire, after a sleeping Corvian and another Corvian guarding the pickup |
+RS: Titanite Shard - water by Halfway Fortress | Dropping down into the Crucifixion Woods crab area right after Halfway Fortress, on the left wall heading toward the Black Knight building, guarded by dog |
+RS: Titanite Shard - woods, left of path from Halfway Fortress | Hugging the left wall from Halfway Fortress to Crystal Sage, behind you after the first dropdown |
+RS: Titanite Shard - woods, surrounded by enemies | Hugging the left wall from Halfway Fortress to the Crystal Sage bonfire, after a dropdown surrounded by seven Poisonhorn bugs |
+RS: Twin Dragon Greatshield - woods by Crucifixion Woods bonfire | In the middle of the area with the Poisonhorn bugs and Lycanthrope Hunters, following the wall where the bugs guard a Titanite Shard |
+RS: Xanthous Crown - Heysel drop | Dropped by Heysel when she invades in Road of Sacrifices |
+SL: Black Iron Greatshield - ruins basement, NPC drop | Dropped by Knight Slayer Tsorig in Smouldering Lake |
+SL: Black Knight Sword - ruins main lower, illusory wall in far hall | On the far exit of the Demon Ruins main hall, past an illusory wall, guarded by a Black Knight |
+SL: Bloodbite Ring+1 - behind ballista | Behind the ballista, overlooking Smouldering Lake |
+SL: Chaos Gem - antechamber, lizard at end of long hall | Dropped by the Crystal Lizard found from the Antechamber bonfire, toward the Demon Cleric and to the right, then all the way down |
+SL: Chaos Gem - lake, far end by mob | In Smouldering Lake along the wall underneath the ballista, all the way to the left past two crabs |
+SL: Dragonrider Bow - by ladder from ruins basement to ballista | After climbing up the ladder after the Black Knight in Demon Ruins, falling back down to a ledge |
+SL: Ember - ruins basement, in lava | In the lava pit under the Black Knight, by Knight Slayer Tsorig |
+SL: Ember - ruins main lower, path to antechamber | Going down the stairs from the Antechamber bonfire, to the right, at the end of the short hallway to the next right |
+SL: Ember - ruins main upper, hall end by hole | In the Demon Ruins, hugging the right wall from the Demon Ruins bonfire, or making a jump from the illusory hall corridor from Antechamber bonfire |
+SL: Ember - ruins main upper, just after entrance | Behind the first Demon Cleric from the Demon Ruins bonfire |
+SL: Estus Shard - antechamber, illusory wall | Behind an illusory wall and Smouldering Writhing Flesh-filled corridor from Antechamber bonfire |
+SL: Flame Stoneplate Ring+2 - ruins main lower, illusory wall in far hall | On the far exit of the Demon Ruins main hall, past an illusory wall, past the Black Knight, hidden in a corner |
+SL: Fume Ultra Greatsword - ruins basement, NPC drop | Dropped by Knight Slayer Tsorig in Smouldering Lake |
+SL: Homeward Bone - path to ballista | In the area targeted by the ballista after the long ladder guarded by the Black Knight, before the Bonewheel Skeletons |
+SL: Izalith Pyromancy Tome - antechamber, room near bonfire | In the room straight down from the Antechamber bonfire, past a Demon Cleric, surrounded by many Ghrus. |
+SL: Izalith Staff - ruins basement, second illusory wall behind chest | Past an illusory wall to the left of the Large Hound Rat in Demon Ruins, and then past another illusory wall, before the basilisk area |
+SL: Knight Slayer's Ring - ruins basement, NPC drop | Dropped by Knight Slayer Tsorig after invading in the Catacombs |
+SL: Large Titanite Shard - lake, by entrance | In the middle of Smouldering Lake, close to the Abandoned Tomb |
+SL: Large Titanite Shard - lake, by miniboss | In the middle of Smouldering Lake, under the Carthus Sandworm |
+SL: Large Titanite Shard - lake, by tree #1 | In the middle of Smouldering Lake, by a tree before the hallway to the pit |
+SL: Large Titanite Shard - lake, by tree #2 | In the middle of Smouldering Lake, by a tree before the hallway to the pit |
+SL: Large Titanite Shard - lake, straight from entrance | In the middle of Smouldering Lake, in between Abandoned Tomb and Demon Ruins |
+SL: Large Titanite Shard - ledge by Demon Ruins bonfire | On a corpse hanging off the ledge outside the Demon Ruins bonfire |
+SL: Large Titanite Shard - ruins basement, illusory wall in upper hall | In a chest past an illusory wall to the left of the Large Hound Rat in Demon Ruins, before the basilisk area |
+SL: Large Titanite Shard - side lake #1 | In the Smouldering Lake pit where Horace can be found, following the right wall from Abandoned Tomb |
+SL: Large Titanite Shard - side lake #2 | In the Smouldering Lake pit where Horace can be found, following the right wall from Abandoned Tomb |
+SL: Lightning Stake - lake, miniboss drop | Dropped by the giant Carthus Sandworm |
+SL: Llewellyn Shield - Horace drop | Dropped by Horace the Hushed upon death or quest completion. |
+SL: Quelana Pyromancy Tome - ruins main lower, illusory wall in grey room | At the far end of the Demon Ruins main hall to the right, where the rats are, then another right and past the illusory wall |
+SL: Sacred Flame - ruins basement, in lava | In the lava pit under the Black Knight, by Knight Slayer Tsorig |
+SL: Shield of Want - lake, by miniboss | In the middle of Smouldering Lake, under the Carthus Sandworm |
+SL: Soul of a Crestfallen Knight - ruins basement, above lava | Next to the Black Knight in Demon Ruins |
+SL: Soul of the Old Demon King | Dropped by Old Demon King in Smouldering Lake |
+SL: Speckled Stoneplate Ring - lake, ballista breaks bricks | Behind a destructible wall in Smouldering Lake which the ballista has to destroy |
+SL: Titanite Chunk - path to side lake, lizard | Dropped by the second Crystal Lizard in the cave leading to the pit where Horace can be found in Smouldering Lake |
+SL: Titanite Scale - ruins basement, path to lava | In the area with Basilisks on the way to the ballista |
+SL: Toxic Mist - ruins main lower, in lava | At the far end of the Demon Ruins main hall to the right, where the rats are, then another right and past the illusory wall, in the middle of the lava pit. |
+SL: Twinkling Titanite - path to side lake, lizard | Dropped by the first Crystal Lizard in the cave leading to the pit where Horace can be found in Smouldering Lake |
+SL: Undead Bone Shard - lake, miniboss drop | Dropped by the giant Carthus Sandworm |
+SL: Undead Bone Shard - ruins main lower, left after stairs | In the close end of the Demon Ruins main hall, right below a Smouldering Writhing Flesh |
+SL: White Hair Talisman - ruins main lower, in lava | At the far end of the Demon Ruins main hall to the right, where the rats are, then another right and past the illusory wall, at the far end of the lava pit. |
+SL: Yellow Bug Pellet - side lake | In the Smouldering Lake pit where Horace can be found, following the right wall from Abandoned Tomb |
+UG: Ashen Estus Ring - swamp, path opposite bonfire | In the coffin similar to your initial spawn location, guarded by Corvians |
+UG: Black Knight Glaive - boss arena | In the Champion Gundyr boss area |
+UG: Blacksmith Hammer - shrine, Andre's room | Where Andre sits in Firelink Shrine |
+UG: Chaos Blade - environs, left of shrine | Where Sword Master is in Firelink Shrine |
+UG: Coiled Sword Fragment - shrine, dead bonfire | In the dead Firelink Shrine bonfire |
+UG: Ember - shop | Sold by Untended Graves Handmaid |
+UG: Eyes of a Fire Keeper - shrine, Irina's room | Behind an illusory wall, in the same location Irina sits in Firelink Shrine |
+UG: Hidden Blessing - cemetery, behind coffin | Behind the coffin that had a Titanite Shard in Cemetery of Ash |
+UG: Hornet Ring - environs, right of main path after killing FK boss | On a cliffside to the right of the main path leading up to dark Firelink Shrine, after Abyss Watchers is defeated. |
+UG: Life Ring+3 - shrine, behind big throne | Behind Prince Lothric's throne |
+UG: Priestess Ring - shop | Sold or dropped by Untended Graves Handmaid. Killing her is not recommended |
+UG: Ring of Steel Protection+1 - environs, behind bell tower | Behind Bell Tower to the right |
+UG: Shriving Stone - swamp, by bonfire | At the very start of the area |
+UG: Soul of Champion Gundyr | Dropped by Champion Gundyr |
+UG: Soul of a Crestfallen Knight - environs, above shrine entrance | Above the Firelink Shrine entrance, up the stairs/slope from either left or right of the entrance |
+UG: Soul of a Crestfallen Knight - swamp, center | Close to where Ashen Estus Flask was in Cemetery of Ash |
+UG: Titanite Chunk - swamp, left path by fountain | In a path to the left of where Ashen Estus Flask was in Cemetery of Ash |
+UG: Titanite Chunk - swamp, right path by fountain | In a path to the right of where Ashen Estus Flask was in Cemetery of Ash |
+UG: Wolf Knight Armor - shop after killing FK boss | Sold by Untended Graves Handmaid after defeating Abyss Watchers |
+UG: Wolf Knight Gauntlets - shop after killing FK boss | Sold by Untended Graves Handmaid after defeating Abyss Watchers |
+UG: Wolf Knight Helm - shop after killing FK boss | Sold by Untended Graves Handmaid after defeating Abyss Watchers |
+UG: Wolf Knight Leggings - shop after killing FK boss | Sold by Untended Graves Handmaid after defeating Abyss Watchers |
+US: Alluring Skull - foot, behind carriage | Guarded by two dogs after the Foot of the High Wall bonfire |
+US: Alluring Skull - on the way to tower, behind building | After the ravine bridge leading to Eygon and the Giant's tower, wrapping around the building to the right. |
+US: Alluring Skull - tower village building, upstairs | Up the stairs of the building with Cage Spiders after the Fire Demon, before the dogs |
+US: Bloodbite Ring - miniboss in sewer | Dropped by the large rat in the sewers with grave access |
+US: Blue Wooden Shield - graveyard by white tree | After Dilapidated Bridge bonfire, in the back of the Giant's arrow area. Guarded by a flamberge-wielding thrall. |
+US: Caduceus Round Shield - right after stable exit | After exiting the building across the bridge to the right of the first Undead Settlement building, to the left |
+US: Caestus - sewer | In the tunnel with the Giant Hound Rat and Grave Key door, from the ravine bridge toward Dilapidated Bridge bonfire |
+US: Charcoal Pine Bundle - first building, bottom floor | Down the stairs in the first building |
+US: Charcoal Pine Bundle - first building, middle floor | On the bottom floor of the first building |
+US: Charcoal Pine Resin - hanging corpse room | In the building after the burning tree and Cathedral Evangelist, in the room with the many hanging corpses |
+US: Chloranthy Ring - tower village, jump from roof | At the end of the Fire Demon loop, in the tower where you have to drop down after the roof |
+US: Cleric Blue Robe - graveyard by white tree | After Dilapidated Bridge bonfire, in the back of the Giant's arrow area. Guarded by a flamberge-wielding thrall. |
+US: Cleric Gloves - graveyard by white tree | After Dilapidated Bridge bonfire, in the back of the Giant's arrow area. Guarded by a flamberge-wielding thrall. |
+US: Cleric Hat - graveyard by white tree | After Dilapidated Bridge bonfire, in the back of the Giant's arrow area. Guarded by a flamberge-wielding thrall. |
+US: Cleric Trousers - graveyard by white tree | After Dilapidated Bridge bonfire, in the back of the Giant's arrow area. Guarded by a flamberge-wielding thrall. |
+US: Cornyx's Garb - by Cornyx's cage after Cuculus quest | Appears next to Cornyx's cage after defeating Old Demon King with Cuculus surviving |
+US: Cornyx's Garb - kill Cornyx | Dropped by Cornyx |
+US: Cornyx's Skirt - by Cornyx's cage after Cuculus quest | Appears next to Cornyx's cage after defeating Old Demon King with Cuculus surviving |
+US: Cornyx's Skirt - kill Cornyx | Dropped by Cornyx |
+US: Cornyx's Wrap - by Cornyx's cage after Cuculus quest | Appears next to Cornyx's cage after defeating Old Demon King with Cuculus surviving |
+US: Cornyx's Wrap - kill Cornyx | Dropped by Cornyx |
+US: Covetous Silver Serpent Ring+2 - tower village, drop down from roof | At the back of a roof near the end of the Fire Demon loop, dropping down past where Flynn's Ring is |
+US: Ember - behind burning tree | Behind the burning tree with the Cathedral Evangelist |
+US: Ember - bridge on the way to tower | On the ravine bridge leading toward Eygon and the Giant's tower |
+US: Ember - by stairs to boss | Next to the stairs leading up to Curse-Rotted Greatwood fight, near a tree guarded by a dog |
+US: Ember - by white tree | Near the Birch Tree where giant shoots arrows |
+US: Ember - tower basement, miniboss | In the room with the Outrider Knight |
+US: Estus Shard - under burning tree | In front of the burning tree guarded by the Cathedral Evangelist |
+US: Fading Soul - by white tree | Near the Birch Tree where giant shoots arrows |
+US: Fading Soul - outside stable | In the thrall area to the right of the bridge to the right of the burning tree with the Cathedral Evangelist |
+US: Fire Clutch Ring - wooden walkway past stable | From the area bombarded by firebombs above the Cliff Underside bonfire |
+US: Fire Gem - tower village, miniboss drop | Dropped by the Fire Demon you fight with Siegward |
+US: Firebomb - stable roof | In the thrall area across the bridge from the first Undead Settlement building, on a rooftop overlooking the Cliff Underside area. |
+US: Flame Stoneplate Ring - hanging corpse by Mound-Maker transport | On a hanging corpse in the area with the Pit of Hollows cage manservant, after the thrall area, overlooking the entrance to the Giant's tower. |
+US: Flynn's Ring - tower village, rooftop | On the roof toward the end of the Fire Demon loop, past the Cathedral Evangelists |
+US: Great Scythe - building by white tree, balcony | On the balcony of the building before Curse-Rotted Greatwood, coming from Dilapidated Bridge bonfire |
+US: Hand Axe - by Cornyx | Next to Cornyx's cell |
+US: Hawk Ring - Giant Archer | Dropped by Giant, either by killing him or collecting all of the birch tree items locations in the base game. |
+US: Heavy Gem - Hawkwood | Given or dropped by Hawkwood after defeating Curse-Rotted Greatwood or Crystal Sage |
+US: Heavy Gem - chasm, lizard | Drop by Crystal Lizard in ravine accessible by Grave Key or dropping down near Eygon. |
+US: Homeward Bone - foot, drop overlook | Under Foot of the High Wall bonfire, around where Yoel can be first met |
+US: Homeward Bone - stable roof | In the thrall area across the bridge from the first Undead Settlement building, on a roof overlooking the ravine bridge. |
+US: Homeward Bone - tower village, jump from roof | At the end of the loop from the Siegward Demon fight, after dropping down from the roof onto the tower with Chloranthy Ring, to the right of the tower entrance |
+US: Homeward Bone - tower village, right at start | Under Foot of the High Wall bonfire, around where Yoel can be first met |
+US: Human Pine Resin - tower village building, chest upstairs | In a chest after Fire Demon. Cage Spiders activate open opening it. |
+US: Irithyll Straight Sword - miniboss drop, by Road of Sacrifices | Dropped by the Boreal Outright Knight before Road of Sacrifices |
+US: Kukri - hanging corpse above burning tree | Hanging corpse high above the burning tree with the Cathedral Evangelist. Must be shot down with an arrow or projective. |
+US: Large Club - tower village, by miniboss | In the Fire Demon area |
+US: Large Soul of a Deserted Corpse - across from Foot of the High Wall | On the opposite tower from the Foot of the High Wall bonfire |
+US: Large Soul of a Deserted Corpse - around corner by Cliff Underside | After going up the stairs from Curse-Rotted Greatwood to Cliff Underside area, on a cliff edge to the right |
+US: Large Soul of a Deserted Corpse - by white tree | Near the Birch Tree where giant shoots arrows |
+US: Large Soul of a Deserted Corpse - hanging corpse room, over stairs | On a hanging corpse in the building after the burning tree. Can be knocked down by dropping onto the stairs through the broken railing. |
+US: Large Soul of a Deserted Corpse - on the way to tower, by well | After the ravine bridge leading toward Eygon and the Giant's tower, next to the well to the right |
+US: Large Soul of a Deserted Corpse - stable | In the building with stables across the bridge and to the right from the first Undead Settlement building |
+US: Life Ring+1 - tower on the way to village | On the wooden rafters near where Siegward is waiting for Fire Demon |
+US: Loincloth - by Velka statue | Next to the Velka statue. Requires Grave Key or dropping down near Eygon and backtracking through the skeleton area. |
+US: Loretta's Bone - first building, hanging corpse on balcony | On a hanging corpse after the first building, can be knocked down by rolling into it |
+US: Mirrah Gloves - tower village, jump from roof | At the end of the Fire Demon loop, in the tower where you have to drop down after the roof |
+US: Mirrah Trousers - tower village, jump from roof | At the end of the Fire Demon loop, in the tower where you have to drop down after the roof |
+US: Mirrah Vest - tower village, jump from roof | At the end of the Fire Demon loop, in the tower where you have to drop down after the roof |
+US: Mortician's Ashes - graveyard by white tree | In the area past the Dilapidated Bridge bonfire, where the Giant is shooting arrows, at the close end of the graveyard |
+US: Mound-makers - Hodrick | Given by Hodrick if accessing the Pit of Hollows before fighting Curse-Rotted Greatwood, or dropped after invading him with Sirris. |
+US: Northern Armor - tower village, hanging corpse | Hanging corpse in the Fire Demon fight area, can be knocked down by rolling into it |
+US: Northern Gloves - tower village, hanging corpse | Hanging corpse in the Fire Demon fight area, can be knocked down by rolling into it |
+US: Northern Helm - tower village, hanging corpse | Hanging corpse in the Fire Demon fight area, can be knocked down by rolling into it |
+US: Northern Trousers - tower village, hanging corpse | Hanging corpse in the Fire Demon fight area, can be knocked down by rolling into it |
+US: Old Sage's Blindfold - kill Cornyx | Dropped by Cornyx |
+US: Pale Tongue - tower village, hanging corpse | Hanging corpse in the Fire Demon fight area, can be knocked down by rolling into it |
+US: Partizan - hanging corpse above Cliff Underside | On a hanging corpse on the path from Cliff Underside to Cornyx's cage. Must be shot down with an arrow or projective. |
+US: Plank Shield - outside stable, by NPC | In the thrall area across the bridge from the first Undead Settlement building, on a cliff edge overlooking the ravine bridge. |
+US: Poisonbite Ring+1 - graveyard by white tree, near well | Behind the well in the back of area where the Giant shoots arrows, nearby where the flamberge-wielding thrall drops down. |
+US: Pyromancy Flame - Cornyx | Given by Cornyx in Firelink Shrine or dropped. |
+US: Red Bug Pellet - tower village building, basement | On the floor of the building after the Fire Demon encounter |
+US: Red Hilted Halberd - chasm crypt | In the skeleton area accessible from Grave Key or dropping down from near Eygon |
+US: Red and White Shield - chasm, hanging corpse | On a hanging corpse in the ravine accessible with the Grave Key or dropping down near Eygon, to the entrance of Irina's prison. Must be shot down with an arrow or projective. |
+US: Reinforced Club - by white tree | Near the Birch Tree where giant shoots arrows |
+US: Repair Powder - first building, balcony | On the balcony of the first Undead Settlement building |
+US: Rusted Coin - awning above Dilapidated Bridge | On a wooden ledge near the Dilapidated Bridge bonfire. Must be jumped to from near Cathedral Evangelist enemy |
+US: Saint's Talisman - chasm, by ladder | From the ravine accessible via Grave Key or dropping near Eygon, before ladder leading up to Irina of Carim |
+US: Sharp Gem - lizard by Dilapidated Bridge | Drop by Crystal Lizard near Dilapidated Bridge bonfire. |
+US: Siegbräu - Siegward | Given by Siegward after helping him defeat the Fire Demon. |
+US: Small Leather Shield - first building, hanging corpse by entrance | Hanging corpse in the first building, to the right of the entrance |
+US: Soul of a Nameless Soldier - top of tower | At the top of the tower where Giant shoots arrows |
+US: Soul of an Unknown Traveler - back alley, past crates | After exiting the building after the burning tree on the way to the Dilapidated Bridge bonfire. Hidden behind some crates between two buildings on the right. |
+US: Soul of an Unknown Traveler - chasm crypt | In the skeleton area accessible Grave Key or dropping down from near Eygon |
+US: Soul of an Unknown Traveler - pillory past stable | In the area bombarded by firebombs above the Cliff Underside bonfire |
+US: Soul of an Unknown Traveler - portcullis by burning tree | Behind a grate to the left of the burning tree and Cathedral Evangelist |
+US: Soul of the Rotted Greatwood | Dropped by Curse Rotted Greatwood |
+US: Spotted Whip - by Cornyx's cage after Cuculus quest | Appears next to Cornyx's cage after defeating Old Demon King with Cuculus surviving |
+US: Sunset Armor - pit of hollows after killing Hodrick w/Sirris | Found in Pit of Hollows after completing Sirris' questline. |
+US: Sunset Gauntlets - pit of hollows after killing Hodrick w/Sirris | Found in Pit of Hollows after completing Sirris' questline. |
+US: Sunset Helm - Pit of Hollows after killing Hodrick w/Sirris | Found in Pit of Hollows after completing Sirris' questline. |
+US: Sunset Leggings - pit of hollows after killing Hodrick w/Sirris | Found in Pit of Hollows after completing Sirris' questline. |
+US: Titanite Shard - back alley, side path | On a side path to the right of the Cathedral Evangelist before the Dilapidated Bridge bonfire |
+US: Titanite Shard - back alley, up ladder | Next to the Cathedral Evangelist close to the Dilapidated Bridge bonfire |
+US: Titanite Shard - chasm #1 | In the ravine accessible from Grave Key or dropping down from near Eygon |
+US: Titanite Shard - chasm #2 | In the ravine accessible from Grave Key or dropping down from near Eygon |
+US: Titanite Shard - lower path to Cliff Underside | At the end of the cliffside path next to Cliff Underside bonfire, guarded by a Hollow Peasant wielding a four-pronged plow. |
+US: Titanite Shard - porch after burning tree | In front of the building after the burning tree and Cathedral Evangelist |
+US: Tower Key - kill Irina | Dropped by Irina of Carim |
+US: Transposing Kiln - boss drop | Dropped by Curse Rotted Greatwood |
+US: Undead Bone Shard - by white tree | In the area past the Dilapidated Bridge bonfire, where the Giant is shooting arrows, jumping to the floating platform on the right |
+US: Wargod Wooden Shield - Pit of Hollows | In the Pit of Hollows |
+US: Warrior of Sunlight - hanging corpse room, drop through hole | Dropping through a hole in the floor in the first building after the burning tree. |
+US: Whip - back alley, behind wooden wall | In one of the houses between building after the burning tree and the Dilapidated Bridge bonfire |
+US: Young White Branch - by white tree #1 | Near the Birch Tree where giant shoots arrows |
+US: Young White Branch - by white tree #2 | Near the Birch Tree where giant shoots arrows |
+
+
diff --git a/worlds/dark_souls_3/docs/setup_en.md b/worlds/dark_souls_3/docs/setup_en.md
index 61215dbc6043..ed90289a8baf 100644
--- a/worlds/dark_souls_3/docs/setup_en.md
+++ b/worlds/dark_souls_3/docs/setup_en.md
@@ -7,48 +7,49 @@
## Optional Software
-- [Dark Souls III Maptracker Pack](https://github.com/Br00ty/DS3_AP_Maptracker/releases/latest), for use with [Poptracker](https://github.com/black-sliver/PopTracker/releases)
+- Map tracker not yet updated for 3.0.0
-## General Concept
+## Setting Up
-
-**This mod can ban you permanently from the FromSoftware servers if used online.**
-
-The Dark Souls III AP Client is a dinput8.dll triggered when launching Dark Souls III. This .dll file will launch a command
-prompt where you can read information about your run and write any command to interact with the Archipelago server.
+First, download the client from the link above. It doesn't need to go into any particular directory;
+it'll automatically locate _Dark Souls III_ in your Steam installation folder.
-This client has only been tested with the Official Steam version of the game at version 1.15. It does not matter which DLCs are installed. However, you will have to downpatch your Dark Souls III installation from current patch.
+Version 3.0.0 of the randomizer _only_ supports the latest version of _Dark Souls III_, 1.15.2. This
+is the latest version, so you don't need to do any downpatching! However, if you've already
+downpatched your game to use an older version of the randomizer, you'll need to reinstall the latest
+version before using this version.
-## Downpatching Dark Souls III
+### One-Time Setup
-To downpatch DS3 for use with Archipelago, use the following instructions from the speedsouls wiki database.
+Before you first connect to a multiworld, you need to generate the local data files for your world's
+randomized item and (optionally) enemy locations. You only need to do this once per multiworld.
-1. Launch Steam (in online mode).
-2. Press the Windows Key + R. This will open the Run window.
-3. Open the Steam console by typing the following string: `steam://open/console`. Steam should now open in Console Mode.
-4. Insert the string of the depot you wish to download. For the AP-supported v1.15, you will want to use: `download_depot 374320 374321 4471176929659548333`.
-5. Steam will now download the depot. Note: There is no progress bar for the download in Steam, but it is still downloading in the background.
-6. Back up your existing game executable (`DarkSoulsIII.exe`) found in `\Steam\steamapps\common\DARK SOULS III\Game`. Easiest way to do this is to move it to another directory. If you have file extensions enabled, you can instead rename the executable to `DarkSoulsIII.exe.bak`.
-7. Return to the Steam console. Once the download is complete, it should say so along with the temporary local directory in which the depot has been stored. This is usually something like `\Steam\steamapps\content\app_XXXXXX\depot_XXXXXX`.
-8. Take the `DarkSoulsIII.exe` from that folder and place it in `\Steam\steamapps\common\DARK SOULS III\Game`.
-9. Back up and delete your save file (`DS30000.sl2`) in AppData. AppData is hidden by default. To locate it, press Windows Key + R, type `%appdata%` and hit enter. Alternatively: open File Explorer > View > Hidden Items and follow `C:\Users\\AppData\Roaming\DarkSoulsIII\`.
-10. If you did all these steps correctly, you should be able to confirm your game version in the upper-left corner after launching Dark Souls III.
+1. Before you first connect to a multiworld, run `randomizer\DS3Randomizer.exe`.
+2. Put in your Archipelago room address (usually something like `archipelago.gg:12345`), your player
+ name (also known as your "slot name"), and your password if you have one.
-## Installing the Archipelago mod
+3. Click "Load" and wait a minute or two.
-Get the `dinput8.dll` from the [Dark Souls III AP Client](https://github.com/Marechal-L/Dark-Souls-III-Archipelago-client/releases) and
-add it at the root folder of your game (e.g. `SteamLibrary\steamapps\common\DARK SOULS III\Game`)
+### Running and Connecting the Game
-## Joining a MultiWorld Game
+To run _Dark Souls III_ in Archipelago mode:
-1. Run Steam in offline mode to avoid being banned.
-2. Launch Dark Souls III.
-3. Type in `/connect {SERVER_IP}:{SERVER_PORT} {SLOT_NAME} password:{PASSWORD}` in the "Windows Command Prompt" that opened. For example: `/connect archipelago.gg:38281 "Example Name" password:"Example Password"`. The password parameter is only necessary if your game requires one.
-4. Once connected, create a new game, choose a class and wait for the others before starting.
-5. You can quit and launch at anytime during a game.
+1. Start Steam. **Do not run in offline mode.** The mod will make sure you don't connect to the
+ DS3 servers, and running Steam in offline mode will make certain scripted invaders fail to spawn.
-## Where do I get a config file?
+2. Run `launchmod_darksouls3.bat`. This will start _Dark Souls III_ as well as a command prompt that
+ you can use to interact with the Archipelago server.
+
+3. Type `/connect {SERVER_IP}:{SERVER_PORT} {SLOT_NAME}` into the command prompt, with the
+ appropriate values filled in. For example: `/connect archipelago.gg:24242 PlayerName`.
+
+4. Start playing as normal. An "Archipelago connected" message will appear onscreen once you have
+ control of your character and the connection is established.
+
+## Frequently Asked Questions
+
+### Where do I get a config file?
The [Player Options](/games/Dark%20Souls%20III/player-options) page on the website allows you to
configure your personal options and export them into a config file.
diff --git a/worlds/dark_souls_3/test/TestDarkSouls3.py b/worlds/dark_souls_3/test/TestDarkSouls3.py
new file mode 100644
index 000000000000..e590cd732b41
--- /dev/null
+++ b/worlds/dark_souls_3/test/TestDarkSouls3.py
@@ -0,0 +1,27 @@
+from test.TestBase import WorldTestBase
+
+from worlds.dark_souls_3.Items import item_dictionary
+from worlds.dark_souls_3.Locations import location_tables
+from worlds.dark_souls_3.Bosses import all_bosses
+
+class DarkSouls3Test(WorldTestBase):
+ game = "Dark Souls III"
+
+ def testLocationDefaultItems(self):
+ for locations in location_tables.values():
+ for location in locations:
+ if location.default_item_name:
+ self.assertIn(location.default_item_name, item_dictionary)
+
+ def testLocationsUnique(self):
+ names = set()
+ for locations in location_tables.values():
+ for location in locations:
+ self.assertNotIn(location.name, names)
+ names.add(location.name)
+
+ def testBossLocations(self):
+ all_locations = {location.name for locations in location_tables.values() for location in locations}
+ for boss in all_bosses:
+ for location in boss.locations:
+ self.assertIn(location, all_locations)
diff --git a/worlds/dark_souls_3/test/__init__.py b/worlds/dark_souls_3/test/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/worlds/doom_1993/docs/setup_en.md b/worlds/doom_1993/docs/setup_en.md
index 8906efac9cea..5d96e6a8056e 100644
--- a/worlds/doom_1993/docs/setup_en.md
+++ b/worlds/doom_1993/docs/setup_en.md
@@ -2,7 +2,7 @@
## Required Software
-- [DOOM 1993 (e.g. Steam version)](https://store.steampowered.com/app/2280/DOOM_1993/)
+- [DOOM 1993 (e.g. Steam version)](https://store.steampowered.com/app/2280/DOOM__DOOM_II/)
- [Archipelago Crispy DOOM](https://github.com/Daivuk/apdoom/releases)
## Optional Software
diff --git a/worlds/doom_ii/docs/setup_en.md b/worlds/doom_ii/docs/setup_en.md
index 87054ab30783..ec6697c76da2 100644
--- a/worlds/doom_ii/docs/setup_en.md
+++ b/worlds/doom_ii/docs/setup_en.md
@@ -2,7 +2,7 @@
## Required Software
-- [DOOM II (e.g. Steam version)](https://store.steampowered.com/app/2300/DOOM_II/)
+- [DOOM II (e.g. Steam version)](https://store.steampowered.com/app/2280/DOOM__DOOM_II/)
- [Archipelago Crispy DOOM](https://github.com/Daivuk/apdoom/releases)
## Optional Software
diff --git a/worlds/generic/docs/advanced_settings_en.md b/worlds/generic/docs/advanced_settings_en.md
index 37467eeb468e..2197c0708e9c 100644
--- a/worlds/generic/docs/advanced_settings_en.md
+++ b/worlds/generic/docs/advanced_settings_en.md
@@ -102,10 +102,10 @@ See the plando guide for more info on plando options. Plando
guide: [Archipelago Plando Guide](/tutorial/Archipelago/plando/en)
* `accessibility` determines the level of access to the game the generation will expect you to have in order to reach
- your completion goal. This supports `items`, `locations`, and `minimal` and is set to `locations` by default.
- * `locations` will guarantee all locations are accessible in your world.
+ your completion goal. This supports `full`, `items`, and `minimal` and is set to `full` by default.
+ * `full` will guarantee all locations are accessible in your world.
* `items` will guarantee you can acquire all logically relevant items in your world. Some items, such as keys, may
- be self-locking.
+ be self-locking. This value only exists in and affects some worlds.
* `minimal` will only guarantee that the seed is beatable. You will be guaranteed able to finish the seed logically
but may not be able to access all locations or acquire all items. A good example of this is having a big key in
the big chest in a dungeon in ALTTP making it impossible to get and finish the dungeon.
diff --git a/worlds/hk/Options.py b/worlds/hk/Options.py
index e2602036a24e..c1206d41ee2c 100644
--- a/worlds/hk/Options.py
+++ b/worlds/hk/Options.py
@@ -405,9 +405,20 @@ class Goal(Choice):
option_radiance = 3
option_godhome = 4
option_godhome_flower = 5
+ option_grub_hunt = 6
default = 0
+class GrubHuntGoal(NamedRange):
+ """The amount of grubs required to finish Grub Hunt.
+ On 'All' any grubs from item links replacements etc. will be counted"""
+ display_name = "Grub Hunt Goal"
+ range_start = 1
+ range_end = 46
+ special_range_names = {"all": -1}
+ default = 46
+
+
class WhitePalace(Choice):
"""
Whether or not to include White Palace or not. Note: Even if excluded, the King Fragment check may still be
@@ -522,7 +533,7 @@ class CostSanityHybridChance(Range):
**{
option.__name__: option
for option in (
- StartLocation, Goal, WhitePalace, ExtraPlatforms, AddUnshuffledLocations, StartingGeo,
+ StartLocation, Goal, GrubHuntGoal, WhitePalace, ExtraPlatforms, AddUnshuffledLocations, StartingGeo,
DeathLink, DeathLinkShade, DeathLinkBreaksFragileCharms,
MinimumGeoPrice, MaximumGeoPrice,
MinimumGrubPrice, MaximumGrubPrice,
diff --git a/worlds/hk/__init__.py b/worlds/hk/__init__.py
index e5065876ddf3..cbb909606127 100644
--- a/worlds/hk/__init__.py
+++ b/worlds/hk/__init__.py
@@ -5,6 +5,7 @@
from copy import deepcopy
import itertools
import operator
+from collections import defaultdict, Counter
logger = logging.getLogger("Hollow Knight")
@@ -12,12 +13,12 @@
from .Regions import create_regions
from .Rules import set_rules, cost_terms, _hk_can_beat_thk, _hk_siblings_ending, _hk_can_beat_radiance
from .Options import hollow_knight_options, hollow_knight_randomize_options, Goal, WhitePalace, CostSanity, \
- shop_to_option, HKOptions
+ shop_to_option, HKOptions, GrubHuntGoal
from .ExtractedData import locations, starts, multi_locations, location_to_region_lookup, \
event_names, item_effects, connectors, one_ways, vanilla_shop_costs, vanilla_location_costs
from .Charms import names as charm_names
-from BaseClasses import Region, Location, MultiWorld, Item, LocationProgressType, Tutorial, ItemClassification
+from BaseClasses import Region, Location, MultiWorld, Item, LocationProgressType, Tutorial, ItemClassification, CollectionState
from worlds.AutoWorld import World, LogicMixin, WebWorld
path_of_pain_locations = {
@@ -155,6 +156,7 @@ class HKWorld(World):
ranges: typing.Dict[str, typing.Tuple[int, int]]
charm_costs: typing.List[int]
cached_filler_items = {}
+ grub_count: int
def __init__(self, multiworld, player):
super(HKWorld, self).__init__(multiworld, player)
@@ -164,6 +166,7 @@ def __init__(self, multiworld, player):
self.ranges = {}
self.created_shop_items = 0
self.vanilla_shop_costs = deepcopy(vanilla_shop_costs)
+ self.grub_count = 0
def generate_early(self):
options = self.options
@@ -201,7 +204,7 @@ def create_regions(self):
# check for any goal that godhome events are relevant to
all_event_names = event_names.copy()
- if self.options.Goal in [Goal.option_godhome, Goal.option_godhome_flower]:
+ if self.options.Goal in [Goal.option_godhome, Goal.option_godhome_flower, Goal.option_any]:
from .GodhomeData import godhome_event_names
all_event_names.update(set(godhome_event_names))
@@ -441,12 +444,67 @@ def set_rules(self):
multiworld.completion_condition[player] = lambda state: state.count("Defeated_Pantheon_5", player)
elif goal == Goal.option_godhome_flower:
multiworld.completion_condition[player] = lambda state: state.count("Godhome_Flower_Quest", player)
+ elif goal == Goal.option_grub_hunt:
+ pass # will set in stage_pre_fill()
else:
# Any goal
- multiworld.completion_condition[player] = lambda state: _hk_can_beat_thk(state, player) or _hk_can_beat_radiance(state, player)
+ multiworld.completion_condition[player] = lambda state: _hk_siblings_ending(state, player) and \
+ _hk_can_beat_radiance(state, player) and state.count("Godhome_Flower_Quest", player)
set_rules(self)
+ @classmethod
+ def stage_pre_fill(cls, multiworld: "MultiWorld"):
+ def set_goal(player, grub_rule: typing.Callable[[CollectionState], bool]):
+ world = multiworld.worlds[player]
+
+ if world.options.Goal == "grub_hunt":
+ multiworld.completion_condition[player] = grub_rule
+ else:
+ old_rule = multiworld.completion_condition[player]
+ multiworld.completion_condition[player] = lambda state: old_rule(state) and grub_rule(state)
+
+ worlds = [world for world in multiworld.get_game_worlds(cls.game) if world.options.Goal in ["any", "grub_hunt"]]
+ if worlds:
+ grubs = [item for item in multiworld.get_items() if item.name == "Grub"]
+ all_grub_players = [world.player for world in worlds if world.options.GrubHuntGoal == GrubHuntGoal.special_range_names["all"]]
+
+ if all_grub_players:
+ group_lookup = defaultdict(set)
+ for group_id, group in multiworld.groups.items():
+ for player in group["players"]:
+ group_lookup[group_id].add(player)
+
+ grub_count_per_player = Counter()
+ per_player_grubs_per_player = defaultdict(Counter)
+
+ for grub in grubs:
+ player = grub.player
+ if player in group_lookup:
+ for real_player in group_lookup[player]:
+ per_player_grubs_per_player[real_player][player] += 1
+ else:
+ per_player_grubs_per_player[player][player] += 1
+
+ if grub.location and grub.location.player in group_lookup.keys():
+ for real_player in group_lookup[grub.location.player]:
+ grub_count_per_player[real_player] += 1
+ else:
+ grub_count_per_player[player] += 1
+
+ for player, count in grub_count_per_player.items():
+ multiworld.worlds[player].grub_count = count
+
+ for player, grub_player_count in per_player_grubs_per_player.items():
+ if player in all_grub_players:
+ set_goal(player, lambda state, g=grub_player_count: all(state.has("Grub", owner, count) for owner, count in g.items()))
+
+ for world in worlds:
+ if world.player not in all_grub_players:
+ world.grub_count = world.options.GrubHuntGoal.value
+ player = world.player
+ set_goal(player, lambda state, p=player, c=world.grub_count: state.has("Grub", p, c))
+
def fill_slot_data(self):
slot_data = {}
@@ -484,6 +542,8 @@ def fill_slot_data(self):
slot_data["notch_costs"] = self.charm_costs
+ slot_data["grub_count"] = self.grub_count
+
return slot_data
def create_item(self, name: str) -> HKItem:
diff --git a/worlds/kh2/docs/setup_en.md b/worlds/kh2/docs/setup_en.md
index c6fdb020b8a4..ed4d90bb54fb 100644
--- a/worlds/kh2/docs/setup_en.md
+++ b/worlds/kh2/docs/setup_en.md
@@ -1,22 +1,25 @@
# Kingdom Hearts 2 Archipelago Setup Guide
+
Quick Links
- [Game Info Page](../../../../games/Kingdom%20Hearts%202/info/en)
- [Player Options Page](../../../../games/Kingdom%20Hearts%202/player-options)
Required Software:
- `Kingdom Hearts II Final Mix` from the [Epic Games Store](https://store.epicgames.com/en-US/discover/kingdom-hearts)
-- Follow this Guide to set up these requirements [KH2Rando.com](https://tommadness.github.io/KH2Randomizer/setup/Panacea-ModLoader/)
- 1. `3.2.0 OpenKH Mod Manager with Panacea`
- 2. `Lua Backend from the OpenKH Mod Manager`
- 3. `Install the mod KH2FM-Mods-Num/GoA-ROM-Edition using OpenKH Mod Manager`
+`Kingdom Hearts II Final Mix` from the [Epic Games Store](https://store.epicgames.com/en-US/discover/kingdom-hearts) or [Steam](https://store.steampowered.com/app/2552430/KINGDOM_HEARTS_HD_1525_ReMIX/)
+
+- Follow this Guide to set up these requirements [KH2Rando.com](https://tommadness.github.io/KH2Randomizer/setup/Panacea-ModLoader/)
+ 1. `Version 3.3.0 or greater OpenKH Mod Manager with Panacea`
+ 2. `Lua Backend from the OpenKH Mod Manager`
+ 3. `Install the mod KH2FM-Mods-Num/GoA-ROM-Edition using OpenKH Mod Manager`
- Needed for Archipelago
- 1. [`ArchipelagoKH2Client.exe`](https://github.com/ArchipelagoMW/Archipelago/releases)
- 2. `Install the Archipelago Companion mod from JaredWeakStrike/APCompanion using OpenKH Mod Manager`
- 3. `Install the Archipelago Quality Of Life mod from JaredWeakStrike/AP_QOL using OpenKH Mod Manager`
- 4. `Install the mod from KH2FM-Mods-equations19/auto-save using OpenKH Mod Manager`
+ 1. [`ArchipelagoKH2Client.exe`](https://github.com/ArchipelagoMW/Archipelago/releases)
+ 2. `Install the Archipelago Companion mod from JaredWeakStrike/APCompanion using OpenKH Mod Manager`
+ 3. `Install the Archipelago Quality Of Life mod from JaredWeakStrike/AP_QOL using OpenKH Mod Manager`
+ 4. `Install the mod from KH2FM-Mods-equations19/auto-save using OpenKH Mod Manager`
5. `AP Randomizer Seed`
+
Required: Archipelago Companion Mod
Load this mod just like the GoA ROM you did during the KH2 Rando setup. `JaredWeakStrike/APCompanion`
@@ -24,6 +27,7 @@ Have this mod second-highest priority below the .zip seed.
This mod is based upon Num's Garden of Assemblege Mod and requires it to work. Without Num this could not be possible.
Required: Auto Save Mod
+
Load this mod just like the GoA ROM you did during the KH2 Rando setup. `KH2FM-Mods-equations19/auto-save` Location doesn't matter, required in case of crashes. See [Best Practices](en#best-practices) on how to load the auto save
Installing A Seed
@@ -33,33 +37,33 @@ Make sure the seed is on the top of the list (Highest Priority)
After Installing the seed click `Mod Loader -> Build/Build and Run`. Every slot is a unique mod to install and will be needed be repatched for different slots/rooms.
What the Mod Manager Should Look Like.
+
![image](https://i.imgur.com/Si4oZ8w.png)
Using the KH2 Client
-Once you have started the game through OpenKH Mod Manager and are on the title screen run the [ArchipelagoKH2Client.exe](https://github.com/ArchipelagoMW/Archipelago/releases).
+Once you have started the game through OpenKH Mod Manager and are on the title screen run the [ArchipelagoKH2Client.exe](https://github.com/ArchipelagoMW/Archipelago/releases).
When you successfully connect to the server the client will automatically hook into the game to send/receive checks.
If the client ever loses connection to the game, it will also disconnect from the server and you will need to reconnect.
`Make sure the game is open whenever you try to connect the client to the server otherwise it will immediately disconnect you.`
Most checks will be sent to you anywhere outside a load or cutscene.
`If you obtain magic, you will need to pause your game to have it show up in your inventory, then enter a new room for it to become properly usable.`
-
+
KH2 Client should look like this:
+
![image](https://i.imgur.com/qP6CmV8.png)
-
-Enter `The room's port number` into the top box where the x's are and press "Connect". Follow the prompts there and you should be connected
+Enter `The room's port number` into the top box where the x's are and press "Connect". Follow the prompts there and you should be connected
Common Pitfalls
+
- Having an old GOA Lua Script in your `C:\Users\*YourName*\Documents\KINGDOM HEARTS HD 1.5+2.5 ReMIX\scripts\kh2` folder.
- - Pressing F2 while in game should look like this. ![image](https://i.imgur.com/ABSdtPC.png)
-
+ - Pressing F2 while in game should look like this. ![image](https://i.imgur.com/ABSdtPC.png)
- Not having Lua Backend Configured Correctly.
- - To fix this look over the guide at [KH2Rando.com](https://tommadness.github.io/KH2Randomizer/setup/Panacea-ModLoader/). Specifically the Lua Backend Configuration Step.
-
-- Loading into Simulated Twilight Town Instead of the GOA.
- - To fix this look over the guide at [KH2Rando.com](https://tommadness.github.io/KH2Randomizer/setup/Panacea-ModLoader/). Specifically the Panacea and Lua Backend Steps.
+ - To fix this look over the guide at [KH2Rando.com](https://tommadness.github.io/KH2Randomizer/setup/Panacea-ModLoader/). Specifically the Lua Backend Configuration Step.
+- Loading into Simulated Twilight Town Instead of the GOA.
+ - To fix this look over the guide at [KH2Rando.com](https://tommadness.github.io/KH2Randomizer/setup/Panacea-ModLoader/). Specifically the Panacea and Lua Backend Steps.
Best Practices
@@ -70,8 +74,11 @@ Enter `The room's port number` into the top box where the x's are and pr
- Make sure to save in a different save slot when playing in an async or disconnecting from the server to play a different seed
Logic Sheet
+
Have any questions on what's in logic? This spreadsheet made by Bulcon has the answer [Requirements/logic sheet](https://docs.google.com/spreadsheets/d/1nNi8ohEs1fv-sDQQRaP45o6NoRcMlLJsGckBonweDMY/edit?usp=sharing)
+
F.A.Q.
+
- Why is my Client giving me a "Cannot Open Process: " error?
- Due to how the client reads kingdom hearts 2 memory some people's computer flags it as a virus. Run the client as admin.
- Why is my HP/MP continuously increasing without stopping?
@@ -83,11 +90,13 @@ Have any questions on what's in logic? This spreadsheet made by Bulcon has the a
- Why did I not load into the correct visit?
- You need to trigger a cutscene or visit The World That Never Was for it to register that you have received the item.
- What versions of Kingdom Hearts 2 are supported?
- - Currently `only` the most up to date version on the Epic Game Store is supported: version `1.0.0.8_WW`.
+ - Currently the `only` supported versions are `Epic Games Version 1.0.0.9_WW` and `Steam Build Version 14716933`.
- Why am I getting wallpapered while going into a world for the first time?
- - Your `Lua Backend` was not configured correctly. Look over the step in the [KH2Rando.com](https://tommadness.github.io/KH2Randomizer/setup/Panacea-ModLoader/) guide.
+ - Your `Lua Backend` was not configured correctly. Look over the step in the [KH2Rando.com](https://tommadness.github.io/KH2Randomizer/setup/Panacea-ModLoader/) guide.
- Why am I not getting magic?
- If you obtain magic, you will need to pause your game to have it show up in your inventory, then enter a new room for it to become properly usable.
+- Why did I crash after picking my dream weapon?
+ - This is normally caused by having an outdated GOA mod or having an outdated panacea and/or luabackend. To fix this rerun the setup wizard and reinstall luabackend and panacea. Also make sure all your mods are up-to-date.
- Why did I crash?
- The port of Kingdom Hearts 2 can and will randomly crash, this is the fault of the game not the randomizer or the archipelago client.
- If you have a continuous/constant crash (in the same area/event every time) you will want to reverify your installed files. This can be done by doing the following: Open Epic Game Store --> Library --> Click Triple Dots --> Manage --> Verify
@@ -99,5 +108,3 @@ Have any questions on what's in logic? This spreadsheet made by Bulcon has the a
- Because Kingdom Hearts 2 is prone to crashes and will keep you from losing your progress.
- How do I load an auto save?
- To load an auto-save, hold down the Select or your equivalent on your prefered controller while choosing a file. Make sure to hold the button down the whole time.
-
-
diff --git a/worlds/osrs/Items.py b/worlds/osrs/Items.py
new file mode 100644
index 000000000000..0679c964e772
--- /dev/null
+++ b/worlds/osrs/Items.py
@@ -0,0 +1,85 @@
+import typing
+
+from BaseClasses import Item, ItemClassification
+from .Names import ItemNames
+
+
+class ItemRow(typing.NamedTuple):
+ name: str
+ amount: int
+ progression: ItemClassification
+
+
+class OSRSItem(Item):
+ game: str = "Old School Runescape"
+
+
+QP_Items: typing.List[str] = [
+ ItemNames.QP_Cooks_Assistant,
+ ItemNames.QP_Demon_Slayer,
+ ItemNames.QP_Restless_Ghost,
+ ItemNames.QP_Romeo_Juliet,
+ ItemNames.QP_Sheep_Shearer,
+ ItemNames.QP_Shield_of_Arrav,
+ ItemNames.QP_Ernest_the_Chicken,
+ ItemNames.QP_Vampyre_Slayer,
+ ItemNames.QP_Imp_Catcher,
+ ItemNames.QP_Prince_Ali_Rescue,
+ ItemNames.QP_Dorics_Quest,
+ ItemNames.QP_Black_Knights_Fortress,
+ ItemNames.QP_Witchs_Potion,
+ ItemNames.QP_Knights_Sword,
+ ItemNames.QP_Goblin_Diplomacy,
+ ItemNames.QP_Pirates_Treasure,
+ ItemNames.QP_Rune_Mysteries,
+ ItemNames.QP_Misthalin_Mystery,
+ ItemNames.QP_Corsair_Curse,
+ ItemNames.QP_X_Marks_the_Spot,
+ ItemNames.QP_Below_Ice_Mountain
+]
+
+starting_area_dict: typing.Dict[int, str] = {
+ 0: ItemNames.Lumbridge,
+ 1: ItemNames.Al_Kharid,
+ 2: ItemNames.Central_Varrock,
+ 3: ItemNames.West_Varrock,
+ 4: ItemNames.Edgeville,
+ 5: ItemNames.Falador,
+ 6: ItemNames.Draynor_Village,
+ 7: ItemNames.Wilderness,
+}
+
+chunksanity_starting_chunks: typing.List[str] = [
+ ItemNames.Lumbridge,
+ ItemNames.Lumbridge_Swamp,
+ ItemNames.Lumbridge_Farms,
+ ItemNames.HAM_Hideout,
+ ItemNames.Draynor_Village,
+ ItemNames.Draynor_Manor,
+ ItemNames.Wizards_Tower,
+ ItemNames.Al_Kharid,
+ ItemNames.Citharede_Abbey,
+ ItemNames.South_Of_Varrock,
+ ItemNames.Central_Varrock,
+ ItemNames.Varrock_Palace,
+ ItemNames.East_Of_Varrock,
+ ItemNames.West_Varrock,
+ ItemNames.Edgeville,
+ ItemNames.Barbarian_Village,
+ ItemNames.Monastery,
+ ItemNames.Ice_Mountain,
+ ItemNames.Dwarven_Mines,
+ ItemNames.Falador,
+ ItemNames.Falador_Farm,
+ ItemNames.Crafting_Guild,
+ ItemNames.Rimmington,
+ ItemNames.Port_Sarim,
+ ItemNames.Mudskipper_Point,
+ ItemNames.Wilderness
+]
+
+# Some starting areas contain multiple regions, so if that area is rolled for Chunksanity, we need to map it to one
+chunksanity_special_region_names: typing.Dict[str, str] = {
+ ItemNames.Lumbridge_Farms: 'Lumbridge Farms East',
+ ItemNames.Crafting_Guild: 'Crafting Guild Outskirts',
+}
diff --git a/worlds/osrs/Locations.py b/worlds/osrs/Locations.py
new file mode 100644
index 000000000000..b5827d60f2fe
--- /dev/null
+++ b/worlds/osrs/Locations.py
@@ -0,0 +1,21 @@
+import typing
+
+from BaseClasses import Location
+
+
+class SkillRequirement(typing.NamedTuple):
+ skill: str
+ level: int
+
+
+class LocationRow(typing.NamedTuple):
+ name: str
+ category: str
+ regions: typing.List[str]
+ skills: typing.List[SkillRequirement]
+ items: typing.List[str]
+ qp: int
+
+
+class OSRSLocation(Location):
+ game: str = "Old School Runescape"
diff --git a/worlds/osrs/LogicCSV/LogicCSVToPython.py b/worlds/osrs/LogicCSV/LogicCSVToPython.py
new file mode 100644
index 000000000000..ed8bd8172a01
--- /dev/null
+++ b/worlds/osrs/LogicCSV/LogicCSVToPython.py
@@ -0,0 +1,144 @@
+"""
+This is a utility file that converts logic in the form of CSV files into Python files that can be imported and used
+directly by the world implementation. Whenever the logic files are updated, this script should be run to re-generate
+the python files containing the data.
+"""
+import requests
+
+# The CSVs are updated at this repository to be shared between generator and client.
+data_repository_address = "https://raw.githubusercontent.com/digiholic/osrs-archipelago-logic/"
+# The Github tag of the CSVs this was generated with
+data_csv_tag = "v1.5"
+
+if __name__ == "__main__":
+ import sys
+ import os
+ import csv
+ import typing
+
+ # makes this module runnable from its world folder. Shamelessly stolen from Subnautica
+ sys.path.remove(os.path.dirname(__file__))
+ new_home = os.path.normpath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
+ os.chdir(new_home)
+ sys.path.append(new_home)
+
+
+ def load_location_csv():
+ this_dir = os.path.dirname(os.path.abspath(__file__))
+
+ with open(os.path.join(this_dir, "locations_generated.py"), 'w+') as locPyFile:
+ locPyFile.write('"""\nThis file was auto generated by LogicCSVToPython.py\n"""\n')
+ locPyFile.write("from ..Locations import LocationRow, SkillRequirement\n")
+ locPyFile.write("\n")
+ locPyFile.write("location_rows = [\n")
+
+ with requests.get(data_repository_address + "/" + data_csv_tag + "/locations.csv") as req:
+ locations_reader = csv.reader(req.text.splitlines())
+ for row in locations_reader:
+ row_line = "LocationRow("
+ row_line += str_format(row[0])
+ row_line += str_format(row[1].lower())
+
+ region_strings = row[2].split(", ") if row[2] else []
+ row_line += f"{str_list_to_py(region_strings)}, "
+
+ skill_strings = row[3].split(", ")
+ row_line += "["
+ if skill_strings:
+ split_skills = [skill.split(" ") for skill in skill_strings if skill != ""]
+ if split_skills:
+ for split in split_skills:
+ row_line += f"SkillRequirement('{split[0]}', {split[1]}), "
+ row_line += "], "
+
+ item_strings = row[4].split(", ") if row[4] else []
+ row_line += f"{str_list_to_py(item_strings)}, "
+ row_line += f"{row[5]})" if row[5] != "" else "0)"
+ locPyFile.write(f"\t{row_line},\n")
+ locPyFile.write("]\n")
+
+ def load_region_csv():
+ this_dir = os.path.dirname(os.path.abspath(__file__))
+
+ with open(os.path.join(this_dir, "regions_generated.py"), 'w+') as regPyFile:
+ regPyFile.write('"""\nThis file was auto generated by LogicCSVToPython.py\n"""\n')
+ regPyFile.write("from ..Regions import RegionRow\n")
+ regPyFile.write("\n")
+ regPyFile.write("region_rows = [\n")
+
+ with requests.get(data_repository_address + "/" + data_csv_tag + "/regions.csv") as req:
+ regions_reader = csv.reader(req.text.splitlines())
+ for row in regions_reader:
+ row_line = "RegionRow("
+ row_line += str_format(row[0])
+ row_line += str_format(row[1])
+ connections = row[2].replace("'", "\\'")
+ row_line += f"{str_list_to_py(connections.split(', '))}, "
+ resources = row[3].replace("'", "\\'")
+ row_line += f"{str_list_to_py(resources.split(', '))})"
+ regPyFile.write(f"\t{row_line},\n")
+ regPyFile.write("]\n")
+
+ def load_resource_csv():
+ this_dir = os.path.dirname(os.path.abspath(__file__))
+
+ with open(os.path.join(this_dir, "resources_generated.py"), 'w+') as resPyFile:
+ resPyFile.write('"""\nThis file was auto generated by LogicCSVToPython.py\n"""\n')
+ resPyFile.write("from ..Regions import ResourceRow\n")
+ resPyFile.write("\n")
+ resPyFile.write("resource_rows = [\n")
+
+ with requests.get(data_repository_address + "/" + data_csv_tag + "/resources.csv") as req:
+ resource_reader = csv.reader(req.text.splitlines())
+ for row in resource_reader:
+ name = row[0].replace("'", "\\'")
+ row_line = f"ResourceRow('{name}')"
+ resPyFile.write(f"\t{row_line},\n")
+ resPyFile.write("]\n")
+
+
+ def load_item_csv():
+ this_dir = os.path.dirname(os.path.abspath(__file__))
+
+ with open(os.path.join(this_dir, "items_generated.py"), 'w+') as itemPyfile:
+ itemPyfile.write('"""\nThis file was auto generated by LogicCSVToPython.py\n"""\n')
+ itemPyfile.write("from BaseClasses import ItemClassification\n")
+ itemPyfile.write("from ..Items import ItemRow\n")
+ itemPyfile.write("\n")
+ itemPyfile.write("item_rows = [\n")
+
+ with requests.get(data_repository_address + "/" + data_csv_tag + "/items.csv") as req:
+ item_reader = csv.reader(req.text.splitlines())
+ for row in item_reader:
+ row_line = "ItemRow("
+ row_line += str_format(row[0])
+ row_line += f"{row[1]}, "
+
+ row_line += f"ItemClassification.{row[2]})"
+
+ itemPyfile.write(f"\t{row_line},\n")
+ itemPyfile.write("]\n")
+
+
+ def str_format(s) -> str:
+ ret_str = s.replace("'", "\\'")
+ return f"'{ret_str}', "
+
+
+ def str_list_to_py(str_list) -> str:
+ ret_str = "["
+ for s in str_list:
+ ret_str += f"'{s}', "
+ ret_str += "]"
+ return ret_str
+
+
+
+ load_location_csv()
+ print("Generated locations py")
+ load_region_csv()
+ print("Generated regions py")
+ load_resource_csv()
+ print("Generated resource py")
+ load_item_csv()
+ print("Generated item py")
diff --git a/worlds/osrs/LogicCSV/items_generated.py b/worlds/osrs/LogicCSV/items_generated.py
new file mode 100644
index 000000000000..b5e610a6e3ab
--- /dev/null
+++ b/worlds/osrs/LogicCSV/items_generated.py
@@ -0,0 +1,43 @@
+"""
+This file was auto generated by LogicCSVToPython.py
+"""
+from BaseClasses import ItemClassification
+from ..Items import ItemRow
+
+item_rows = [
+ ItemRow('Area: Lumbridge', 1, ItemClassification.progression),
+ ItemRow('Area: Lumbridge Swamp', 1, ItemClassification.progression),
+ ItemRow('Area: HAM Hideout', 1, ItemClassification.progression),
+ ItemRow('Area: Lumbridge Farms', 1, ItemClassification.progression),
+ ItemRow('Area: South of Varrock', 1, ItemClassification.progression),
+ ItemRow('Area: East Varrock', 1, ItemClassification.progression),
+ ItemRow('Area: Central Varrock', 1, ItemClassification.progression),
+ ItemRow('Area: Varrock Palace', 1, ItemClassification.progression),
+ ItemRow('Area: West Varrock', 1, ItemClassification.progression),
+ ItemRow('Area: Edgeville', 1, ItemClassification.progression),
+ ItemRow('Area: Barbarian Village', 1, ItemClassification.progression),
+ ItemRow('Area: Draynor Manor', 1, ItemClassification.progression),
+ ItemRow('Area: Falador', 1, ItemClassification.progression),
+ ItemRow('Area: Dwarven Mines', 1, ItemClassification.progression),
+ ItemRow('Area: Ice Mountain', 1, ItemClassification.progression),
+ ItemRow('Area: Monastery', 1, ItemClassification.progression),
+ ItemRow('Area: Falador Farms', 1, ItemClassification.progression),
+ ItemRow('Area: Port Sarim', 1, ItemClassification.progression),
+ ItemRow('Area: Mudskipper Point', 1, ItemClassification.progression),
+ ItemRow('Area: Karamja', 1, ItemClassification.progression),
+ ItemRow('Area: Crandor', 1, ItemClassification.progression),
+ ItemRow('Area: Rimmington', 1, ItemClassification.progression),
+ ItemRow('Area: Crafting Guild', 1, ItemClassification.progression),
+ ItemRow('Area: Draynor Village', 1, ItemClassification.progression),
+ ItemRow('Area: Wizard Tower', 1, ItemClassification.progression),
+ ItemRow('Area: Corsair Cove', 1, ItemClassification.progression),
+ ItemRow('Area: Al Kharid', 1, ItemClassification.progression),
+ ItemRow('Area: Citharede Abbey', 1, ItemClassification.progression),
+ ItemRow('Area: Wilderness', 1, ItemClassification.progression),
+ ItemRow('Progressive Armor', 6, ItemClassification.progression),
+ ItemRow('Progressive Weapons', 6, ItemClassification.progression),
+ ItemRow('Progressive Tools', 6, ItemClassification.useful),
+ ItemRow('Progressive Ranged Weapons', 3, ItemClassification.useful),
+ ItemRow('Progressive Ranged Armor', 3, ItemClassification.useful),
+ ItemRow('Progressive Magic', 2, ItemClassification.useful),
+]
diff --git a/worlds/osrs/LogicCSV/locations_generated.py b/worlds/osrs/LogicCSV/locations_generated.py
new file mode 100644
index 000000000000..073e505ad8f4
--- /dev/null
+++ b/worlds/osrs/LogicCSV/locations_generated.py
@@ -0,0 +1,127 @@
+"""
+This file was auto generated by LogicCSVToPython.py
+"""
+from ..Locations import LocationRow, SkillRequirement
+
+location_rows = [
+ LocationRow('Quest: Cook\'s Assistant', 'quest', ['Lumbridge', 'Wheat', 'Windmill', 'Egg', 'Milk', ], [], [], 0),
+ LocationRow('Quest: Demon Slayer', 'quest', ['Central Varrock', 'Varrock Palace', 'Wizard Tower', 'South of Varrock', ], [], [], 0),
+ LocationRow('Quest: The Restless Ghost', 'quest', ['Lumbridge', 'Lumbridge Swamp', 'Wizard Tower', ], [], [], 0),
+ LocationRow('Quest: Romeo & Juliet', 'quest', ['Central Varrock', 'Varrock Palace', 'South of Varrock', 'West Varrock', ], [], [], 0),
+ LocationRow('Quest: Sheep Shearer', 'quest', ['Lumbridge Farms West', 'Spinning Wheel', ], [], [], 0),
+ LocationRow('Quest: Shield of Arrav', 'quest', ['Central Varrock', 'Varrock Palace', 'South of Varrock', 'West Varrock', ], [], [], 0),
+ LocationRow('Quest: Ernest the Chicken', 'quest', ['Draynor Manor', ], [], [], 0),
+ LocationRow('Quest: Vampyre Slayer', 'quest', ['Draynor Village', 'Central Varrock', 'Draynor Manor', ], [], [], 0),
+ LocationRow('Quest: Imp Catcher', 'quest', ['Wizard Tower', 'Imps', ], [], [], 0),
+ LocationRow('Quest: Prince Ali Rescue', 'quest', ['Al Kharid', 'Central Varrock', 'Bronze Ores', 'Clay Ore', 'Sheep', 'Spinning Wheel', 'Draynor Village', ], [], [], 0),
+ LocationRow('Quest: Doric\'s Quest', 'quest', ['Dwarven Mountain Pass', 'Clay Ore', 'Iron Ore', 'Bronze Ores', ], [SkillRequirement('Mining', 15), ], [], 0),
+ LocationRow('Quest: Black Knights\' Fortress', 'quest', ['Dwarven Mines', 'Falador', 'Monastery', 'Ice Mountain', 'Falador Farms', ], [], ['Progressive Armor', ], 12),
+ LocationRow('Quest: Witch\'s Potion', 'quest', ['Rimmington', 'Port Sarim', ], [], [], 0),
+ LocationRow('Quest: The Knight\'s Sword', 'quest', ['Falador', 'Varrock Palace', 'Mudskipper Point', 'South of Varrock', 'Windmill', 'Pie Dish', 'Port Sarim', ], [SkillRequirement('Cooking', 10), SkillRequirement('Mining', 10), ], [], 0),
+ LocationRow('Quest: Goblin Diplomacy', 'quest', ['Goblin Village', 'Draynor Village', 'Falador', 'South of Varrock', 'Onion', ], [], [], 0),
+ LocationRow('Quest: Pirate\'s Treasure', 'quest', ['Port Sarim', 'Karamja', 'Falador', ], [], [], 0),
+ LocationRow('Quest: Rune Mysteries', 'quest', ['Lumbridge', 'Wizard Tower', 'Central Varrock', ], [], [], 0),
+ LocationRow('Quest: Misthalin Mystery', 'quest', ['Lumbridge Swamp', ], [], [], 0),
+ LocationRow('Quest: The Corsair Curse', 'quest', ['Rimmington', 'Falador Farms', 'Corsair Cove', ], [], [], 0),
+ LocationRow('Quest: X Marks the Spot', 'quest', ['Lumbridge', 'Draynor Village', 'Port Sarim', ], [], [], 0),
+ LocationRow('Quest: Below Ice Mountain', 'quest', ['Dwarven Mines', 'Dwarven Mountain Pass', 'Ice Mountain', 'Barbarian Village', 'Falador', 'Central Varrock', 'Edgeville', ], [], [], 16),
+ LocationRow('Quest: Dragon Slayer', 'goal', ['Crandor', 'South of Varrock', 'Edgeville', 'Lumbridge', 'Rimmington', 'Monastery', 'Dwarven Mines', 'Port Sarim', 'Draynor Village', ], [], [], 32),
+ LocationRow('Activate the "Rock Skin" Prayer', 'prayer', [], [SkillRequirement('Prayer', 10), ], [], 0),
+ LocationRow('Activate the "Protect Item" Prayer', 'prayer', [], [SkillRequirement('Prayer', 25), ], [], 2),
+ LocationRow('Pray at the Edgeville Monastery', 'prayer', ['Monastery', ], [SkillRequirement('Prayer', 31), ], [], 6),
+ LocationRow('Cast Bones To Bananas', 'magic', ['Nature Runes', ], [SkillRequirement('Magic', 15), ], [], 0),
+ LocationRow('Teleport to Varrock', 'magic', ['Central Varrock', 'Law Runes', ], [SkillRequirement('Magic', 25), ], [], 0),
+ LocationRow('Teleport to Lumbridge', 'magic', ['Lumbridge', 'Law Runes', ], [SkillRequirement('Magic', 31), ], [], 2),
+ LocationRow('Teleport to Falador', 'magic', ['Falador', 'Law Runes', ], [SkillRequirement('Magic', 37), ], [], 6),
+ LocationRow('Craft an Air Rune', 'runecraft', ['Rune Essence', 'Falador Farms', ], [SkillRequirement('Runecraft', 1), ], [], 0),
+ LocationRow('Craft runes with a Mind Core', 'runecraft', ['Camdozaal', 'Goblin Village', ], [SkillRequirement('Runecraft', 2), ], [], 0),
+ LocationRow('Craft runes with a Body Core', 'runecraft', ['Camdozaal', 'Dwarven Mountain Pass', ], [SkillRequirement('Runecraft', 20), ], [], 0),
+ LocationRow('Make an Unblessed Symbol', 'crafting', ['Silver Ore', 'Furnace', 'Al Kharid', 'Sheep', 'Spinning Wheel', ], [SkillRequirement('Crafting', 16), ], [], 0),
+ LocationRow('Cut a Sapphire', 'crafting', ['Chisel', ], [SkillRequirement('Crafting', 20), ], [], 0),
+ LocationRow('Cut an Emerald', 'crafting', ['Chisel', ], [SkillRequirement('Crafting', 27), ], [], 0),
+ LocationRow('Cut a Ruby', 'crafting', ['Chisel', ], [SkillRequirement('Crafting', 34), ], [], 4),
+ LocationRow('Cut a Diamond', 'crafting', ['Chisel', ], [SkillRequirement('Crafting', 43), ], [], 8),
+ LocationRow('Mine a Blurite Ore', 'mining', ['Mudskipper Point', 'Port Sarim', ], [SkillRequirement('Mining', 10), ], [], 0),
+ LocationRow('Crush a Barronite Deposit', 'mining', ['Camdozaal', ], [SkillRequirement('Mining', 14), ], [], 0),
+ LocationRow('Mine Silver', 'mining', ['Silver Ore', ], [SkillRequirement('Mining', 20), ], [], 0),
+ LocationRow('Mine Coal', 'mining', ['Coal Ore', ], [SkillRequirement('Mining', 30), ], [], 2),
+ LocationRow('Mine Gold', 'mining', ['Gold Ore', ], [SkillRequirement('Mining', 40), ], [], 6),
+ LocationRow('Smelt an Iron Bar', 'smithing', ['Iron Ore', 'Furnace', ], [SkillRequirement('Smithing', 15), SkillRequirement('Mining', 15), ], [], 0),
+ LocationRow('Smelt a Silver Bar', 'smithing', ['Silver Ore', 'Furnace', ], [SkillRequirement('Smithing', 20), SkillRequirement('Mining', 20), ], [], 0),
+ LocationRow('Smelt a Steel Bar', 'smithing', ['Coal Ore', 'Iron Ore', 'Furnace', ], [SkillRequirement('Smithing', 30), SkillRequirement('Mining', 30), ], [], 2),
+ LocationRow('Smelt a Gold Bar', 'smithing', ['Gold Ore', 'Furnace', ], [SkillRequirement('Smithing', 40), SkillRequirement('Mining', 40), ], [], 6),
+ LocationRow('Catch some Anchovies', 'fishing', ['Shrimp Spot', ], [SkillRequirement('Fishing', 15), ], [], 0),
+ LocationRow('Catch a Trout', 'fishing', ['Fly Fishing Spot', ], [SkillRequirement('Fishing', 20), ], [], 0),
+ LocationRow('Prepare a Tetra', 'fishing', ['Camdozaal', ], [SkillRequirement('Fishing', 33), SkillRequirement('Cooking', 33), ], [], 2),
+ LocationRow('Catch a Lobster', 'fishing', ['Lobster Spot', ], [SkillRequirement('Fishing', 40), ], [], 6),
+ LocationRow('Catch a Swordfish', 'fishing', ['Lobster Spot', ], [SkillRequirement('Fishing', 50), ], [], 12),
+ LocationRow('Bake a Redberry Pie', 'cooking', ['Redberry Bush', 'Wheat', 'Windmill', 'Pie Dish', ], [SkillRequirement('Cooking', 10), ], [], 0),
+ LocationRow('Cook some Stew', 'cooking', ['Bowl', 'Meat', 'Potato', ], [SkillRequirement('Cooking', 25), ], [], 0),
+ LocationRow('Bake an Apple Pie', 'cooking', ['Cooking Apple', 'Wheat', 'Windmill', 'Pie Dish', ], [SkillRequirement('Cooking', 30), ], [], 2),
+ LocationRow('Bake a Cake', 'cooking', ['Wheat', 'Windmill', 'Egg', 'Milk', 'Cake Tin', ], [SkillRequirement('Cooking', 40), ], [], 6),
+ LocationRow('Bake a Meat Pizza', 'cooking', ['Wheat', 'Windmill', 'Cheese', 'Tomato', 'Meat', ], [SkillRequirement('Cooking', 45), ], [], 8),
+ LocationRow('Burn some Oak Logs', 'firemaking', ['Oak Tree', ], [SkillRequirement('Firemaking', 15), ], [], 0),
+ LocationRow('Burn some Willow Logs', 'firemaking', ['Willow Tree', ], [SkillRequirement('Firemaking', 30), ], [], 0),
+ LocationRow('Travel on a Canoe', 'woodcutting', ['Canoe Tree', ], [SkillRequirement('Woodcutting', 12), ], [], 0),
+ LocationRow('Cut an Oak Log', 'woodcutting', ['Oak Tree', ], [SkillRequirement('Woodcutting', 15), ], [], 0),
+ LocationRow('Cut a Willow Log', 'woodcutting', ['Willow Tree', ], [SkillRequirement('Woodcutting', 30), ], [], 0),
+ LocationRow('Kill Jeff', 'combat', ['Dwarven Mountain Pass', ], [SkillRequirement('Combat', 2), ], [], 0),
+ LocationRow('Kill a Goblin', 'combat', ['Goblin', ], [SkillRequirement('Combat', 2), ], [], 0),
+ LocationRow('Kill a Monkey', 'combat', ['Karamja', ], [SkillRequirement('Combat', 3), ], [], 0),
+ LocationRow('Kill a Barbarian', 'combat', ['Barbarian', ], [SkillRequirement('Combat', 10), ], [], 0),
+ LocationRow('Kill a Giant Frog', 'combat', ['Lumbridge Swamp', ], [SkillRequirement('Combat', 13), ], [], 0),
+ LocationRow('Kill a Zombie', 'combat', ['Zombie', ], [SkillRequirement('Combat', 13), ], [], 0),
+ LocationRow('Kill a Guard', 'combat', ['Guard', ], [SkillRequirement('Combat', 21), ], [], 0),
+ LocationRow('Kill a Hill Giant', 'combat', ['Hill Giant', ], [SkillRequirement('Combat', 28), ], [], 2),
+ LocationRow('Kill a Deadly Red Spider', 'combat', ['Deadly Red Spider', ], [SkillRequirement('Combat', 34), ], [], 2),
+ LocationRow('Kill a Moss Giant', 'combat', ['Moss Giant', ], [SkillRequirement('Combat', 42), ], [], 2),
+ LocationRow('Kill a Catablepon', 'combat', ['Barbarian Village', ], [SkillRequirement('Combat', 49), ], [], 4),
+ LocationRow('Kill an Ice Giant', 'combat', ['Ice Giant', ], [SkillRequirement('Combat', 53), ], [], 4),
+ LocationRow('Kill a Lesser Demon', 'combat', ['Lesser Demon', ], [SkillRequirement('Combat', 82), ], [], 8),
+ LocationRow('Kill an Ogress Shaman', 'combat', ['Corsair Cove', ], [SkillRequirement('Combat', 82), ], [], 8),
+ LocationRow('Kill Obor', 'combat', ['Edgeville', ], [SkillRequirement('Combat', 106), ], [], 28),
+ LocationRow('Kill Bryophyta', 'combat', ['Central Varrock', ], [SkillRequirement('Combat', 128), ], [], 28),
+ LocationRow('Total XP 5,000', 'general', [], [], [], 0),
+ LocationRow('Combat Level 5', 'general', [], [], [], 0),
+ LocationRow('Total XP 10,000', 'general', [], [], [], 0),
+ LocationRow('Total Level 50', 'general', [], [], [], 0),
+ LocationRow('Total XP 25,000', 'general', [], [], [], 0),
+ LocationRow('Total Level 100', 'general', [], [], [], 0),
+ LocationRow('Total XP 50,000', 'general', [], [], [], 0),
+ LocationRow('Combat Level 15', 'general', [], [], [], 0),
+ LocationRow('Total Level 150', 'general', [], [], [], 2),
+ LocationRow('Total XP 75,000', 'general', [], [], [], 2),
+ LocationRow('Combat Level 25', 'general', [], [], [], 2),
+ LocationRow('Total XP 100,000', 'general', [], [], [], 6),
+ LocationRow('Total Level 200', 'general', [], [], [], 6),
+ LocationRow('Total XP 125,000', 'general', [], [], [], 6),
+ LocationRow('Combat Level 30', 'general', [], [], [], 10),
+ LocationRow('Total Level 250', 'general', [], [], [], 10),
+ LocationRow('Total XP 150,000', 'general', [], [], [], 10),
+ LocationRow('Total Level 300', 'general', [], [], [], 16),
+ LocationRow('Combat Level 40', 'general', [], [], [], 16),
+ LocationRow('Open a Simple Lockbox', 'general', ['Camdozaal', ], [], [], 0),
+ LocationRow('Open an Elaborate Lockbox', 'general', ['Camdozaal', ], [], [], 0),
+ LocationRow('Open an Ornate Lockbox', 'general', ['Camdozaal', ], [], [], 0),
+ LocationRow('Points: Cook\'s Assistant', 'points', [], [], [], 0),
+ LocationRow('Points: Demon Slayer', 'points', [], [], [], 0),
+ LocationRow('Points: The Restless Ghost', 'points', [], [], [], 0),
+ LocationRow('Points: Romeo & Juliet', 'points', [], [], [], 0),
+ LocationRow('Points: Sheep Shearer', 'points', [], [], [], 0),
+ LocationRow('Points: Shield of Arrav', 'points', [], [], [], 0),
+ LocationRow('Points: Ernest the Chicken', 'points', [], [], [], 0),
+ LocationRow('Points: Vampyre Slayer', 'points', [], [], [], 0),
+ LocationRow('Points: Imp Catcher', 'points', [], [], [], 0),
+ LocationRow('Points: Prince Ali Rescue', 'points', [], [], [], 0),
+ LocationRow('Points: Doric\'s Quest', 'points', [], [], [], 0),
+ LocationRow('Points: Black Knights\' Fortress', 'points', [], [], [], 0),
+ LocationRow('Points: Witch\'s Potion', 'points', [], [], [], 0),
+ LocationRow('Points: The Knight\'s Sword', 'points', [], [], [], 0),
+ LocationRow('Points: Goblin Diplomacy', 'points', [], [], [], 0),
+ LocationRow('Points: Pirate\'s Treasure', 'points', [], [], [], 0),
+ LocationRow('Points: Rune Mysteries', 'points', [], [], [], 0),
+ LocationRow('Points: Misthalin Mystery', 'points', [], [], [], 0),
+ LocationRow('Points: The Corsair Curse', 'points', [], [], [], 0),
+ LocationRow('Points: X Marks the Spot', 'points', [], [], [], 0),
+ LocationRow('Points: Below Ice Mountain', 'points', [], [], [], 0),
+]
diff --git a/worlds/osrs/LogicCSV/regions_generated.py b/worlds/osrs/LogicCSV/regions_generated.py
new file mode 100644
index 000000000000..87b3747d938e
--- /dev/null
+++ b/worlds/osrs/LogicCSV/regions_generated.py
@@ -0,0 +1,47 @@
+"""
+This file was auto generated by LogicCSVToPython.py
+"""
+from ..Regions import RegionRow
+
+region_rows = [
+ RegionRow('Lumbridge', 'Area: Lumbridge', ['Lumbridge Farms East', 'Lumbridge Farms West', 'Al Kharid', 'Lumbridge Swamp', 'HAM Hideout', 'South of Varrock', 'Barbarian Village', 'Edgeville', 'Wilderness', ], ['Mind Runes', 'Spinning Wheel', 'Furnace', 'Chisel', 'Bronze Anvil', 'Fly Fishing Spot', 'Bowl', 'Cake Tin', 'Oak Tree', 'Willow Tree', 'Canoe Tree', 'Goblin', 'Imps', ]),
+ RegionRow('Lumbridge Swamp', 'Area: Lumbridge Swamp', ['Lumbridge', 'HAM Hideout', ], ['Bronze Ores', 'Coal Ore', 'Shrimp Spot', 'Meat', 'Goblin', 'Imps', ]),
+ RegionRow('HAM Hideout', 'Area: HAM Hideout', ['Lumbridge Farms West', 'Lumbridge', 'Lumbridge Swamp', 'Draynor Village', ], ['Goblin', ]),
+ RegionRow('Lumbridge Farms West', 'Area: Lumbridge Farms', ['Sourhog\'s Lair', 'HAM Hideout', 'Draynor Village', ], ['Sheep', 'Meat', 'Wheat', 'Windmill', 'Egg', 'Milk', 'Willow Tree', 'Imps', 'Potato', ]),
+ RegionRow('Lumbridge Farms East', 'Area: Lumbridge Farms', ['South of Varrock', 'Lumbridge', ], ['Meat', 'Egg', 'Milk', 'Willow Tree', 'Goblin', 'Imps', 'Potato', ]),
+ RegionRow('Sourhog\'s Lair', 'Area: South of Varrock', ['Lumbridge Farms West', 'Draynor Manor Outskirts', ], ['', ]),
+ RegionRow('South of Varrock', 'Area: South of Varrock', ['Al Kharid', 'West Varrock', 'Central Varrock', 'East Varrock', 'Lumbridge Farms East', 'Lumbridge', 'Barbarian Village', 'Edgeville', 'Wilderness', ], ['Sheep', 'Bronze Ores', 'Iron Ore', 'Silver Ore', 'Redberry Bush', 'Meat', 'Wheat', 'Oak Tree', 'Willow Tree', 'Canoe Tree', 'Guard', 'Imps', 'Clay Ore', ]),
+ RegionRow('East Varrock', 'Area: East Varrock', ['Wilderness', 'South of Varrock', 'Central Varrock', 'Varrock Palace', ], ['Guard', ]),
+ RegionRow('Central Varrock', 'Area: Central Varrock', ['Varrock Palace', 'East Varrock', 'South of Varrock', 'West Varrock', ], ['Mind Runes', 'Chisel', 'Anvil', 'Bowl', 'Cake Tin', 'Oak Tree', 'Barbarian', 'Guard', 'Rune Essence', 'Imps', ]),
+ RegionRow('Varrock Palace', 'Area: Varrock Palace', ['Wilderness', 'East Varrock', 'Central Varrock', 'West Varrock', ], ['Pie Dish', 'Oak Tree', 'Zombie', 'Guard', 'Deadly Red Spider', 'Moss Giant', 'Nature Runes', 'Law Runes', ]),
+ RegionRow('West Varrock', 'Area: West Varrock', ['Wilderness', 'Varrock Palace', 'South of Varrock', 'Barbarian Village', 'Edgeville', 'Cook\'s Guild', ], ['Anvil', 'Wheat', 'Oak Tree', 'Goblin', 'Guard', 'Onion', ]),
+ RegionRow('Cook\'s Guild', 'Area: West Varrock*', ['West Varrock', ], ['Bowl', 'Cooking Apple', 'Pie Dish', 'Cake Tin', 'Windmill', ]),
+ RegionRow('Edgeville', 'Area: Edgeville', ['Wilderness', 'West Varrock', 'Barbarian Village', 'South of Varrock', 'Lumbridge', ], ['Furnace', 'Chisel', 'Bronze Ores', 'Iron Ore', 'Coal Ore', 'Bowl', 'Meat', 'Cake Tin', 'Willow Tree', 'Canoe Tree', 'Zombie', 'Guard', 'Hill Giant', 'Nature Runes', 'Law Runes', 'Imps', ]),
+ RegionRow('Barbarian Village', 'Area: Barbarian Village', ['Edgeville', 'West Varrock', 'Draynor Manor Outskirts', 'Dwarven Mountain Pass', ], ['Spinning Wheel', 'Coal Ore', 'Anvil', 'Fly Fishing Spot', 'Meat', 'Canoe Tree', 'Barbarian', 'Zombie', 'Law Runes', ]),
+ RegionRow('Draynor Manor Outskirts', 'Area: Draynor Manor', ['Barbarian Village', 'Sourhog\'s Lair', 'Draynor Village', 'Falador East Outskirts', ], ['Goblin', ]),
+ RegionRow('Draynor Manor', 'Area: Draynor Manor', ['Draynor Village', ], ['', ]),
+ RegionRow('Falador East Outskirts', 'Area: Falador', ['Dwarven Mountain Pass', 'Draynor Manor Outskirts', 'Falador Farms', ], ['', ]),
+ RegionRow('Dwarven Mountain Pass', 'Area: Dwarven Mines', ['Goblin Village', 'Monastery', 'Barbarian Village', 'Falador East Outskirts', 'Falador', ], ['Anvil*', 'Wheat', ]),
+ RegionRow('Dwarven Mines', 'Area: Dwarven Mines', ['Monastery', 'Ice Mountain', 'Falador', ], ['Chisel', 'Bronze Ores', 'Iron Ore', 'Coal Ore', 'Gold Ore', 'Anvil', 'Pie Dish', 'Clay Ore', ]),
+ RegionRow('Goblin Village', 'Area: Ice Mountain', ['Wilderness', 'Dwarven Mountain Pass', ], ['Meat', ]),
+ RegionRow('Ice Mountain', 'Area: Ice Mountain', ['Wilderness', 'Monastery', 'Dwarven Mines', 'Camdozaal*', ], ['', ]),
+ RegionRow('Camdozaal', 'Area: Ice Mountain', ['Ice Mountain', ], ['Clay Ore', ]),
+ RegionRow('Monastery', 'Area: Monastery', ['Wilderness', 'Dwarven Mountain Pass', 'Dwarven Mines', 'Ice Mountain', ], ['Sheep', ]),
+ RegionRow('Falador', 'Area: Falador', ['Dwarven Mountain Pass', 'Falador Farms', 'Dwarven Mines', ], ['Furnace', 'Chisel', 'Bowl', 'Cake Tin', 'Oak Tree', 'Guard', 'Imps', ]),
+ RegionRow('Falador Farms', 'Area: Falador Farms', ['Falador', 'Falador East Outskirts', 'Draynor Village', 'Port Sarim', 'Rimmington', 'Crafting Guild Outskirts', ], ['Spinning Wheel', 'Meat', 'Egg', 'Milk', 'Oak Tree', 'Imps', ]),
+ RegionRow('Port Sarim', 'Area: Port Sarim', ['Falador Farms', 'Mudskipper Point', 'Rimmington', 'Karamja Docks', 'Crandor', ], ['Mind Runes', 'Shrimp Spot', 'Meat', 'Cheese', 'Tomato', 'Oak Tree', 'Willow Tree', 'Goblin', 'Potato', ]),
+ RegionRow('Karamja Docks', 'Area: Mudskipper Point', ['Port Sarim', 'Karamja', ], ['', ]),
+ RegionRow('Mudskipper Point', 'Area: Mudskipper Point', ['Rimmington', 'Port Sarim', ], ['Anvil', 'Ice Giant', 'Nature Runes', 'Law Runes', ]),
+ RegionRow('Karamja', 'Area: Karamja', ['Karamja Docks', 'Crandor', ], ['Gold Ore', 'Lobster Spot', 'Bowl', 'Cake Tin', 'Deadly Red Spider', 'Imps', ]),
+ RegionRow('Crandor', 'Area: Crandor', ['Karamja', 'Port Sarim', ], ['Coal Ore', 'Gold Ore', 'Moss Giant', 'Lesser Demon', 'Nature Runes', 'Law Runes', ]),
+ RegionRow('Rimmington', 'Area: Rimmington', ['Falador Farms', 'Port Sarim', 'Mudskipper Point', 'Crafting Guild Peninsula', 'Corsair Cove', ], ['Chisel', 'Bronze Ores', 'Iron Ore', 'Gold Ore', 'Bowl', 'Cake Tin', 'Wheat', 'Oak Tree', 'Willow Tree', 'Crafting Moulds', 'Imps', 'Clay Ore', 'Onion', ]),
+ RegionRow('Crafting Guild Peninsula', 'Area: Crafting Guild', ['Falador Farms', 'Rimmington', ], ['', ]),
+ RegionRow('Crafting Guild Outskirts', 'Area: Crafting Guild', ['Falador Farms', 'Crafting Guild', ], ['Sheep', 'Willow Tree', 'Oak Tree', ]),
+ RegionRow('Crafting Guild', 'Area: Crafting Guild*', ['Crafting Guild', ], ['Spinning Wheel', 'Chisel', 'Silver Ore', 'Gold Ore', 'Meat', 'Milk', 'Clay Ore', ]),
+ RegionRow('Draynor Village', 'Area: Draynor Village', ['Draynor Manor', 'Lumbridge Farms West', 'HAM Hideout', 'Wizard Tower', ], ['Anvil', 'Shrimp Spot', 'Wheat', 'Cheese', 'Tomato', 'Willow Tree', 'Goblin', 'Zombie', 'Nature Runes', 'Law Runes', 'Imps', ]),
+ RegionRow('Wizard Tower', 'Area: Wizard Tower', ['Draynor Village', ], ['Lesser Demon', 'Rune Essence', ]),
+ RegionRow('Corsair Cove', 'Area: Corsair Cove*', ['Rimmington', ], ['Anvil', 'Meat', ]),
+ RegionRow('Al Kharid', 'Area: Al Kharid', ['South of Varrock', 'Citharede Abbey', 'Lumbridge', 'Port Sarim', ], ['Furnace', 'Chisel', 'Bronze Ores', 'Iron Ore', 'Silver Ore', 'Coal Ore', 'Gold Ore', 'Shrimp Spot', 'Bowl', 'Cake Tin', 'Cheese', 'Crafting Moulds', 'Imps', ]),
+ RegionRow('Citharede Abbey', 'Area: Citharede Abbey', ['Al Kharid', ], ['Iron Ore', 'Coal Ore', 'Anvil', 'Hill Giant', 'Nature Runes', 'Law Runes', ]),
+ RegionRow('Wilderness', 'Area: Wilderness', ['East Varrock', 'Varrock Palace', 'West Varrock', 'Edgeville', 'Monastery', 'Ice Mountain', 'Goblin Village', 'South of Varrock', 'Lumbridge', ], ['Furnace', 'Chisel', 'Iron Ore', 'Coal Ore', 'Anvil', 'Meat', 'Cake Tin', 'Cheese', 'Tomato', 'Oak Tree', 'Canoe Tree', 'Zombie', 'Hill Giant', 'Deadly Red Spider', 'Moss Giant', 'Ice Giant', 'Lesser Demon', 'Nature Runes', 'Law Runes', ]),
+]
diff --git a/worlds/osrs/LogicCSV/resources_generated.py b/worlds/osrs/LogicCSV/resources_generated.py
new file mode 100644
index 000000000000..18c2ebe2f317
--- /dev/null
+++ b/worlds/osrs/LogicCSV/resources_generated.py
@@ -0,0 +1,54 @@
+"""
+This file was auto generated by LogicCSVToPython.py
+"""
+from ..Regions import ResourceRow
+
+resource_rows = [
+ ResourceRow('Mind Runes'),
+ ResourceRow('Spinning Wheel'),
+ ResourceRow('Sheep'),
+ ResourceRow('Furnace'),
+ ResourceRow('Chisel'),
+ ResourceRow('Bronze Ores'),
+ ResourceRow('Iron Ore'),
+ ResourceRow('Silver Ore'),
+ ResourceRow('Coal Ore'),
+ ResourceRow('Gold Ore'),
+ ResourceRow('Bronze Anvil'),
+ ResourceRow('Anvil'),
+ ResourceRow('Shrimp Spot'),
+ ResourceRow('Fly Fishing Spot'),
+ ResourceRow('Lobster Spot'),
+ ResourceRow('Redberry Bush'),
+ ResourceRow('Bowl'),
+ ResourceRow('Meat'),
+ ResourceRow('Cooking Apple'),
+ ResourceRow('Pie Dish'),
+ ResourceRow('Cake Tin'),
+ ResourceRow('Wheat'),
+ ResourceRow('Windmill'),
+ ResourceRow('Egg'),
+ ResourceRow('Milk'),
+ ResourceRow('Cheese'),
+ ResourceRow('Tomato'),
+ ResourceRow('Oak Tree'),
+ ResourceRow('Willow Tree'),
+ ResourceRow('Canoe Tree'),
+ ResourceRow('Goblin'),
+ ResourceRow('Barbarian'),
+ ResourceRow('Zombie'),
+ ResourceRow('Guard'),
+ ResourceRow('Hill Giant'),
+ ResourceRow('Deadly Red Spider'),
+ ResourceRow('Moss Giant'),
+ ResourceRow('Ice Giant'),
+ ResourceRow('Lesser Demon'),
+ ResourceRow('Rune Essence'),
+ ResourceRow('Crafting Moulds'),
+ ResourceRow('Nature Runes'),
+ ResourceRow('Law Runes'),
+ ResourceRow('Imps'),
+ ResourceRow('Clay Ore'),
+ ResourceRow('Onion'),
+ ResourceRow('Potato'),
+]
diff --git a/worlds/osrs/Names.py b/worlds/osrs/Names.py
new file mode 100644
index 000000000000..95aed742b6f1
--- /dev/null
+++ b/worlds/osrs/Names.py
@@ -0,0 +1,212 @@
+from enum import Enum
+
+
+class RegionNames(str, Enum):
+ Lumbridge = "Lumbridge"
+ Lumbridge_Swamp = "Lumbridge Swamp"
+ Lumbridge_Farms_East = "Lumbridge Farms East"
+ Lumbridge_Farms_West = "Lumbridge Farms West"
+ HAM_Hideout = "HAM Hideout"
+ Draynor_Village = "Draynor Village"
+ Draynor_Manor = "Draynor Manor"
+ Wizards_Tower = "Wizard Tower"
+ Al_Kharid = "Al Kharid"
+ Citharede_Abbey = "Citharede Abbey"
+ South_Of_Varrock = "South of Varrock"
+ Central_Varrock = "Central Varrock"
+ Varrock_Palace = "Varrock Palace"
+ East_Of_Varrock = "East Varrock"
+ West_Varrock = "West Varrock"
+ Edgeville = "Edgeville"
+ Barbarian_Village = "Barbarian Village"
+ Monastery = "Monastery"
+ Ice_Mountain = "Ice Mountain"
+ Dwarven_Mines = "Dwarven Mines"
+ Falador = "Falador"
+ Falador_Farm = "Falador Farms"
+ Crafting_Guild = "Crafting Guild"
+ Cooks_Guild = "Cook's Guild"
+ Rimmington = "Rimmington"
+ Port_Sarim = "Port Sarim"
+ Mudskipper_Point = "Mudskipper Point"
+ Karamja = "Karamja"
+ Corsair_Cove = "Corsair Cove"
+ Wilderness = "The Wilderness"
+ Crandor = "Crandor"
+ # Resource Regions
+ Egg = "Egg"
+ Sheep = "Sheep"
+ Milk = "Milk"
+ Wheat = "Wheat"
+ Windmill = "Windmill"
+ Spinning_Wheel = "Spinning Wheel"
+ Imp = "Imp"
+ Bronze_Ores = "Bronze Ores"
+ Clay_Rock = "Clay Ore"
+ Coal_Rock = "Coal Ore"
+ Iron_Rock = "Iron Ore"
+ Silver_Rock = "Silver Ore"
+ Gold_Rock = "Gold Ore"
+ Furnace = "Furnace"
+ Anvil = "Anvil"
+ Oak_Tree = "Oak Tree"
+ Willow_Tree = "Willow Tree"
+ Shrimp = "Shrimp Spot"
+ Fly_Fish = "Fly Fishing Spot"
+ Lobster = "Lobster Spot"
+ Mind_Runes = "Mind Runes"
+ Canoe_Tree = "Canoe Tree"
+
+ __str__ = str.__str__
+
+
+class ItemNames(str, Enum):
+ Lumbridge = "Area: Lumbridge"
+ Lumbridge_Swamp = "Area: Lumbridge Swamp"
+ Lumbridge_Farms = "Area: Lumbridge Farms"
+ HAM_Hideout = "Area: HAM Hideout"
+ Draynor_Village = "Area: Draynor Village"
+ Draynor_Manor = "Area: Draynor Manor"
+ Wizards_Tower = "Area: Wizard Tower"
+ Al_Kharid = "Area: Al Kharid"
+ Citharede_Abbey = "Area: Citharede Abbey"
+ South_Of_Varrock = "Area: South of Varrock"
+ Central_Varrock = "Area: Central Varrock"
+ Varrock_Palace = "Area: Varrock Palace"
+ East_Of_Varrock = "Area: East Varrock"
+ West_Varrock = "Area: West Varrock"
+ Edgeville = "Area: Edgeville"
+ Barbarian_Village = "Area: Barbarian Village"
+ Monastery = "Area: Monastery"
+ Ice_Mountain = "Area: Ice Mountain"
+ Dwarven_Mines = "Area: Dwarven Mines"
+ Falador = "Area: Falador"
+ Falador_Farm = "Area: Falador Farms"
+ Crafting_Guild = "Area: Crafting Guild"
+ Rimmington = "Area: Rimmington"
+ Port_Sarim = "Area: Port Sarim"
+ Mudskipper_Point = "Area: Mudskipper Point"
+ Karamja = "Area: Karamja"
+ Crandor = "Area: Crandor"
+ Corsair_Cove = "Area: Corsair Cove"
+ Wilderness = "Area: Wilderness"
+ Progressive_Armor = "Progressive Armor"
+ Progressive_Weapons = "Progressive Weapons"
+ Progressive_Tools = "Progressive Tools"
+ Progressive_Range_Armor = "Progressive Range Armor"
+ Progressive_Range_Weapon = "Progressive Range Weapon"
+ Progressive_Magic = "Progressive Magic Spell"
+ Lobsters = "10 Lobsters"
+ Swordfish = "5 Swordfish"
+ Energy_Potions = "10 Energy Potions"
+ Coins = "5,000 Coins"
+ Mind_Runes = "50 Mind Runes"
+ Chaos_Runes = "25 Chaos Runes"
+ Death_Runes = "10 Death Runes"
+ Law_Runes = "10 Law Runes"
+ QP_Cooks_Assistant = "1 QP (Cook's Assistant)"
+ QP_Demon_Slayer = "3 QP (Demon Slayer)"
+ QP_Restless_Ghost = "1 QP (The Restless Ghost)"
+ QP_Romeo_Juliet = "5 QP (Romeo & Juliet)"
+ QP_Sheep_Shearer = "1 QP (Sheep Shearer)"
+ QP_Shield_of_Arrav = "1 QP (Shield of Arrav)"
+ QP_Ernest_the_Chicken = "4 QP (Ernest the Chicken)"
+ QP_Vampyre_Slayer = "3 QP (Vampyre Slayer)"
+ QP_Imp_Catcher = "1 QP (Imp Catcher)"
+ QP_Prince_Ali_Rescue = "3 QP (Prince Ali Rescue)"
+ QP_Dorics_Quest = "1 QP (Doric's Quest)"
+ QP_Black_Knights_Fortress = "3 QP (Black Knights' Fortress)"
+ QP_Witchs_Potion = "1 QP (Witch's Potion)"
+ QP_Knights_Sword = "1 QP (The Knight's Sword)"
+ QP_Goblin_Diplomacy = "5 QP (Goblin Diplomacy)"
+ QP_Pirates_Treasure = "2 QP (Pirate's Treasure)"
+ QP_Rune_Mysteries = "1 QP (Rune Mysteries)"
+ QP_Misthalin_Mystery = "1 QP (Misthalin Mystery)"
+ QP_Corsair_Curse = "2 QP (The Corsair Curse)"
+ QP_X_Marks_the_Spot = "1 QP (X Marks The Spot)"
+ QP_Below_Ice_Mountain = "1 QP (Below Ice Mountain)"
+
+ __str__ = str.__str__
+
+
+class LocationNames(str, Enum):
+ Q_Cooks_Assistant = "Quest: Cook's Assistant"
+ Q_Demon_Slayer = "Quest: Demon Slayer"
+ Q_Restless_Ghost = "Quest: The Restless Ghost"
+ Q_Romeo_Juliet = "Quest: Romeo & Juliet"
+ Q_Sheep_Shearer = "Quest: Sheep Shearer"
+ Q_Shield_of_Arrav = "Quest: Shield of Arrav"
+ Q_Ernest_the_Chicken = "Quest: Ernest the Chicken"
+ Q_Vampyre_Slayer = "Quest: Vampyre Slayer"
+ Q_Imp_Catcher = "Quest: Imp Catcher"
+ Q_Prince_Ali_Rescue = "Quest: Prince Ali Rescue"
+ Q_Dorics_Quest = "Quest: Doric's Quest"
+ Q_Black_Knights_Fortress = "Quest: Black Knights' Fortress"
+ Q_Witchs_Potion = "Quest: Witch's Potion"
+ Q_Knights_Sword = "Quest: The Knight's Sword"
+ Q_Goblin_Diplomacy = "Quest: Goblin Diplomacy"
+ Q_Pirates_Treasure = "Quest: Pirate's Treasure"
+ Q_Rune_Mysteries = "Quest: Rune Mysteries"
+ Q_Misthalin_Mystery = "Quest: Misthalin Mystery"
+ Q_Corsair_Curse = "Quest: The Corsair Curse"
+ Q_X_Marks_the_Spot = "Quest: X Marks the Spot"
+ Q_Below_Ice_Mountain = "Quest: Below Ice Mountain"
+ QP_Cooks_Assistant = "Points: Cook's Assistant"
+ QP_Demon_Slayer = "Points: Demon Slayer"
+ QP_Restless_Ghost = "Points: The Restless Ghost"
+ QP_Romeo_Juliet = "Points: Romeo & Juliet"
+ QP_Sheep_Shearer = "Points: Sheep Shearer"
+ QP_Shield_of_Arrav = "Points: Shield of Arrav"
+ QP_Ernest_the_Chicken = "Points: Ernest the Chicken"
+ QP_Vampyre_Slayer = "Points: Vampyre Slayer"
+ QP_Imp_Catcher = "Points: Imp Catcher"
+ QP_Prince_Ali_Rescue = "Points: Prince Ali Rescue"
+ QP_Dorics_Quest = "Points: Doric's Quest"
+ QP_Black_Knights_Fortress = "Points: Black Knights' Fortress"
+ QP_Witchs_Potion = "Points: Witch's Potion"
+ QP_Knights_Sword = "Points: The Knight's Sword"
+ QP_Goblin_Diplomacy = "Points: Goblin Diplomacy"
+ QP_Pirates_Treasure = "Points: Pirate's Treasure"
+ QP_Rune_Mysteries = "Points: Rune Mysteries"
+ QP_Misthalin_Mystery = "Points: Misthalin Mystery"
+ QP_Corsair_Curse = "Points: The Corsair Curse"
+ QP_X_Marks_the_Spot = "Points: X Marks the Spot"
+ QP_Below_Ice_Mountain = "Points: Below Ice Mountain"
+ Guppy = "Prepare a Guppy"
+ Cavefish = "Prepare a Cavefish"
+ Tetra = "Prepare a Tetra"
+ Barronite_Deposit = "Crush a Barronite Deposit"
+ Oak_Log = "Cut an Oak Log"
+ Willow_Log = "Cut a Willow Log"
+ Catch_Lobster = "Catch a Lobster"
+ Mine_Silver = "Mine Silver"
+ Mine_Coal = "Mine Coal"
+ Mine_Gold = "Mine Gold"
+ Smelt_Silver = "Smelt a Silver Bar"
+ Smelt_Steel = "Smelt a Steel Bar"
+ Smelt_Gold = "Smelt a Gold Bar"
+ Cut_Sapphire = "Cut a Sapphire"
+ Cut_Emerald = "Cut an Emerald"
+ Cut_Ruby = "Cut a Ruby"
+ Cut_Diamond = "Cut a Diamond"
+ K_Lesser_Demon = "Kill a Lesser Demon"
+ K_Ogress_Shaman = "Kill an Ogress Shaman"
+ Bake_Apple_Pie = "Bake an Apple Pie"
+ Bake_Cake = "Bake a Cake"
+ Bake_Meat_Pizza = "Bake a Meat Pizza"
+ Total_XP_5000 = "5,000 Total XP"
+ Total_XP_10000 = "10,000 Total XP"
+ Total_XP_25000 = "25,000 Total XP"
+ Total_XP_50000 = "50,000 Total XP"
+ Total_XP_100000 = "100,000 Total XP"
+ Total_Level_50 = "Total Level 50"
+ Total_Level_100 = "Total Level 100"
+ Total_Level_150 = "Total Level 150"
+ Total_Level_200 = "Total Level 200"
+ Combat_Level_5 = "Combat Level 5"
+ Combat_Level_15 = "Combat Level 15"
+ Combat_Level_25 = "Combat Level 25"
+ Travel_on_a_Canoe = "Travel on a Canoe"
+ Q_Dragon_Slayer = "Quest: Dragon Slayer"
+
+ __str__ = str.__str__
diff --git a/worlds/osrs/Options.py b/worlds/osrs/Options.py
new file mode 100644
index 000000000000..520cd8e8b06b
--- /dev/null
+++ b/worlds/osrs/Options.py
@@ -0,0 +1,474 @@
+from dataclasses import dataclass
+
+from Options import Choice, Toggle, Range, PerGameCommonOptions
+
+MAX_COMBAT_TASKS = 16
+MAX_PRAYER_TASKS = 3
+MAX_MAGIC_TASKS = 4
+MAX_RUNECRAFT_TASKS = 3
+MAX_CRAFTING_TASKS = 5
+MAX_MINING_TASKS = 5
+MAX_SMITHING_TASKS = 4
+MAX_FISHING_TASKS = 5
+MAX_COOKING_TASKS = 5
+MAX_FIREMAKING_TASKS = 2
+MAX_WOODCUTTING_TASKS = 3
+
+NON_QUEST_LOCATION_COUNT = 22
+
+
+class StartingArea(Choice):
+ """
+ Which chunks are available at the start. The player may need to move through locked chunks to reach the starting
+ area, but any areas that require quests, skills, or coins are not available as a starting location.
+
+ "Any Bank" rolls a random region that contains a bank.
+ Chunksanity can start you in any chunk. Hope you like woodcutting!
+ """
+ display_name = "Starting Region"
+ option_lumbridge = 0
+ option_al_kharid = 1
+ option_varrock_east = 2
+ option_varrock_west = 3
+ option_edgeville = 4
+ option_falador = 5
+ option_draynor = 6
+ option_wilderness = 7
+ option_any_bank = 8
+ option_chunksanity = 9
+ default = 0
+
+
+class BrutalGrinds(Toggle):
+ """
+ Whether to allow skill tasks without having reasonable access to the usual skill training path.
+ For example, if enabled, you could be forced to train smithing without an anvil purely by smelting bars,
+ or training fishing to high levels entirely on shrimp.
+ """
+ display_name = "Allow Brutal Grinds"
+
+
+class ProgressiveTasks(Toggle):
+ """
+ Whether skill tasks should always be generated in order of easiest to hardest.
+ If enabled, you would not be assigned "Mine Gold" without also being assigned
+ "Mine Silver", "Mine Coal", and "Mine Iron". Enabling this will result in a generally shorter seed, but with
+ a lower variety of tasks.
+ """
+ display_name = "Progressive Tasks"
+
+
+class MaxCombatLevel(Range):
+ """
+ The highest combat level of monster to possibly be assigned as a task.
+ If set to 0, no combat tasks will be generated.
+ """
+ range_start = 0
+ range_end = 1520
+ default = 50
+
+
+class MaxCombatTasks(Range):
+ """
+ The maximum number of Combat Tasks to possibly be assigned.
+ If set to 0, no combat tasks will be generated.
+ This only determines the maximum possible, fewer than the maximum could be assigned.
+ """
+ range_start = 0
+ range_end = MAX_COMBAT_TASKS
+ default = MAX_COMBAT_TASKS
+
+
+class CombatTaskWeight(Range):
+ """
+ How much to favor generating combat tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxPrayerLevel(Range):
+ """
+ The highest Prayer requirement of any task generated.
+ If set to 0, no Prayer tasks will be generated.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxPrayerTasks(Range):
+ """
+ The maximum number of Prayer Tasks to possibly be assigned.
+ If set to 0, no Prayer tasks will be generated.
+ This only determines the maximum possible, fewer than the maximum could be assigned.
+ """
+ range_start = 0
+ range_end = MAX_PRAYER_TASKS
+ default = MAX_PRAYER_TASKS
+
+
+class PrayerTaskWeight(Range):
+ """
+ How much to favor generating Prayer tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxMagicLevel(Range):
+ """
+ The highest Magic requirement of any task generated.
+ If set to 0, no Magic tasks will be generated.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxMagicTasks(Range):
+ """
+ The maximum number of Magic Tasks to possibly be assigned.
+ If set to 0, no Magic tasks will be generated.
+ This only determines the maximum possible, fewer than the maximum could be assigned.
+ """
+ range_start = 0
+ range_end = MAX_MAGIC_TASKS
+ default = MAX_MAGIC_TASKS
+
+
+class MagicTaskWeight(Range):
+ """
+ How much to favor generating Magic tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxRunecraftLevel(Range):
+ """
+ The highest Runecraft requirement of any task generated.
+ If set to 0, no Runecraft tasks will be generated.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxRunecraftTasks(Range):
+ """
+ The maximum number of Runecraft Tasks to possibly be assigned.
+ If set to 0, no Runecraft tasks will be generated.
+ This only determines the maximum possible, fewer than the maximum could be assigned.
+ """
+ range_start = 0
+ range_end = MAX_RUNECRAFT_TASKS
+ default = MAX_RUNECRAFT_TASKS
+
+
+class RunecraftTaskWeight(Range):
+ """
+ How much to favor generating Runecraft tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxCraftingLevel(Range):
+ """
+ The highest Crafting requirement of any task generated.
+ If set to 0, no Crafting tasks will be generated.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxCraftingTasks(Range):
+ """
+ The maximum number of Crafting Tasks to possibly be assigned.
+ If set to 0, no Crafting tasks will be generated.
+ This only determines the maximum possible, fewer than the maximum could be assigned.
+ """
+ range_start = 0
+ range_end = MAX_CRAFTING_TASKS
+ default = MAX_CRAFTING_TASKS
+
+
+class CraftingTaskWeight(Range):
+ """
+ How much to favor generating Crafting tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxMiningLevel(Range):
+ """
+ The highest Mining requirement of any task generated.
+ If set to 0, no Mining tasks will be generated.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxMiningTasks(Range):
+ """
+ The maximum number of Mining Tasks to possibly be assigned.
+ If set to 0, no Mining tasks will be generated.
+ This only determines the maximum possible, fewer than the maximum could be assigned.
+ """
+ range_start = 0
+ range_end = MAX_MINING_TASKS
+ default = MAX_MINING_TASKS
+
+
+class MiningTaskWeight(Range):
+ """
+ How much to favor generating Mining tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxSmithingLevel(Range):
+ """
+ The highest Smithing requirement of any task generated.
+ If set to 0, no Smithing tasks will be generated.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxSmithingTasks(Range):
+ """
+ The maximum number of Smithing Tasks to possibly be assigned.
+ If set to 0, no Smithing tasks will be generated.
+ This only determines the maximum possible, fewer than the maximum could be assigned.
+ """
+ range_start = 0
+ range_end = MAX_SMITHING_TASKS
+ default = MAX_SMITHING_TASKS
+
+
+class SmithingTaskWeight(Range):
+ """
+ How much to favor generating Smithing tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxFishingLevel(Range):
+ """
+ The highest Fishing requirement of any task generated.
+ If set to 0, no Fishing tasks will be generated.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxFishingTasks(Range):
+ """
+ The maximum number of Fishing Tasks to possibly be assigned.
+ If set to 0, no Fishing tasks will be generated.
+ This only determines the maximum possible, fewer than the maximum could be assigned.
+ """
+ range_start = 0
+ range_end = MAX_FISHING_TASKS
+ default = MAX_FISHING_TASKS
+
+
+class FishingTaskWeight(Range):
+ """
+ How much to favor generating Fishing tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxCookingLevel(Range):
+ """
+ The highest Cooking requirement of any task generated.
+ If set to 0, no Cooking tasks will be generated.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxCookingTasks(Range):
+ """
+ The maximum number of Cooking Tasks to possibly be assigned.
+ If set to 0, no Cooking tasks will be generated.
+ This only determines the maximum possible, fewer than the maximum could be assigned.
+ """
+ range_start = 0
+ range_end = MAX_COOKING_TASKS
+ default = MAX_COOKING_TASKS
+
+
+class CookingTaskWeight(Range):
+ """
+ How much to favor generating Cooking tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxFiremakingLevel(Range):
+ """
+ The highest Firemaking requirement of any task generated.
+ If set to 0, no Firemaking tasks will be generated.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxFiremakingTasks(Range):
+ """
+ The maximum number of Firemaking Tasks to possibly be assigned.
+ If set to 0, no Firemaking tasks will be generated.
+ This only determines the maximum possible, fewer than the maximum could be assigned.
+ """
+ range_start = 0
+ range_end = MAX_FIREMAKING_TASKS
+ default = MAX_FIREMAKING_TASKS
+
+
+class FiremakingTaskWeight(Range):
+ """
+ How much to favor generating Firemaking tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxWoodcuttingLevel(Range):
+ """
+ The highest Woodcutting requirement of any task generated.
+ If set to 0, no Woodcutting tasks will be generated.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MaxWoodcuttingTasks(Range):
+ """
+ The maximum number of Woodcutting Tasks to possibly be assigned.
+ If set to 0, no Woodcutting tasks will be generated.
+ This only determines the maximum possible, fewer than the maximum could be assigned.
+ """
+ range_start = 0
+ range_end = MAX_WOODCUTTING_TASKS
+ default = MAX_WOODCUTTING_TASKS
+
+
+class WoodcuttingTaskWeight(Range):
+ """
+ How much to favor generating Woodcutting tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+class MinimumGeneralTasks(Range):
+ """
+ How many guaranteed general progression tasks to be assigned (total level, total XP, etc.).
+ General progression tasks will be used to fill out any holes caused by having fewer possible tasks than needed, so
+ there is no maximum.
+ """
+ range_start = 0
+ range_end = NON_QUEST_LOCATION_COUNT
+ default = 10
+
+
+class GeneralTaskWeight(Range):
+ """
+ How much to favor generating General tasks over other types of task.
+ Weights of all Task Types will be compared against each other, a task with 50 weight
+ is twice as likely to appear as one with 25.
+ """
+ range_start = 0
+ range_end = 99
+ default = 50
+
+
+@dataclass
+class OSRSOptions(PerGameCommonOptions):
+ starting_area: StartingArea
+ brutal_grinds: BrutalGrinds
+ progressive_tasks: ProgressiveTasks
+ max_combat_level: MaxCombatLevel
+ max_combat_tasks: MaxCombatTasks
+ combat_task_weight: CombatTaskWeight
+ max_prayer_level: MaxPrayerLevel
+ max_prayer_tasks: MaxPrayerTasks
+ prayer_task_weight: PrayerTaskWeight
+ max_magic_level: MaxMagicLevel
+ max_magic_tasks: MaxMagicTasks
+ magic_task_weight: MagicTaskWeight
+ max_runecraft_level: MaxRunecraftLevel
+ max_runecraft_tasks: MaxRunecraftTasks
+ runecraft_task_weight: RunecraftTaskWeight
+ max_crafting_level: MaxCraftingLevel
+ max_crafting_tasks: MaxCraftingTasks
+ crafting_task_weight: CraftingTaskWeight
+ max_mining_level: MaxMiningLevel
+ max_mining_tasks: MaxMiningTasks
+ mining_task_weight: MiningTaskWeight
+ max_smithing_level: MaxSmithingLevel
+ max_smithing_tasks: MaxSmithingTasks
+ smithing_task_weight: SmithingTaskWeight
+ max_fishing_level: MaxFishingLevel
+ max_fishing_tasks: MaxFishingTasks
+ fishing_task_weight: FishingTaskWeight
+ max_cooking_level: MaxCookingLevel
+ max_cooking_tasks: MaxCookingTasks
+ cooking_task_weight: CookingTaskWeight
+ max_firemaking_level: MaxFiremakingLevel
+ max_firemaking_tasks: MaxFiremakingTasks
+ firemaking_task_weight: FiremakingTaskWeight
+ max_woodcutting_level: MaxWoodcuttingLevel
+ max_woodcutting_tasks: MaxWoodcuttingTasks
+ woodcutting_task_weight: WoodcuttingTaskWeight
+ minimum_general_tasks: MinimumGeneralTasks
+ general_task_weight: GeneralTaskWeight
diff --git a/worlds/osrs/Regions.py b/worlds/osrs/Regions.py
new file mode 100644
index 000000000000..436cdf3c7c78
--- /dev/null
+++ b/worlds/osrs/Regions.py
@@ -0,0 +1,12 @@
+import typing
+
+
+class RegionRow(typing.NamedTuple):
+ name: str
+ itemReq: str
+ connections: typing.List[str]
+ resources: typing.List[str]
+
+
+class ResourceRow(typing.NamedTuple):
+ name: str
diff --git a/worlds/osrs/__init__.py b/worlds/osrs/__init__.py
new file mode 100644
index 000000000000..f726b4b81bf2
--- /dev/null
+++ b/worlds/osrs/__init__.py
@@ -0,0 +1,657 @@
+import typing
+
+from BaseClasses import Item, Tutorial, ItemClassification, Region, MultiWorld
+from worlds.AutoWorld import WebWorld, World
+from worlds.generic.Rules import add_rule, CollectionRule
+from .Items import OSRSItem, starting_area_dict, chunksanity_starting_chunks, QP_Items, ItemRow, \
+ chunksanity_special_region_names
+from .Locations import OSRSLocation, LocationRow
+
+from .Options import OSRSOptions, StartingArea
+from .Names import LocationNames, ItemNames, RegionNames
+
+from .LogicCSV.LogicCSVToPython import data_csv_tag
+from .LogicCSV.items_generated import item_rows
+from .LogicCSV.locations_generated import location_rows
+from .LogicCSV.regions_generated import region_rows
+from .LogicCSV.resources_generated import resource_rows
+from .Regions import RegionRow, ResourceRow
+
+
+class OSRSWeb(WebWorld):
+ theme = "stone"
+
+ setup_en = Tutorial(
+ "Multiworld Setup Guide",
+ "A guide to setting up the Old School Runescape Randomizer connected to an Archipelago Multiworld",
+ "English",
+ "docs/setup_en.md",
+ "setup/en",
+ ["digiholic"]
+ )
+ tutorials = [setup_en]
+
+
+class OSRSWorld(World):
+ game = "Old School Runescape"
+ options_dataclass = OSRSOptions
+ options: OSRSOptions
+ topology_present = True
+ web = OSRSWeb()
+ base_id = 0x070000
+ data_version = 1
+
+ item_name_to_id = {item_rows[i].name: 0x070000 + i for i in range(len(item_rows))}
+ location_name_to_id = {location_rows[i].name: 0x070000 + i for i in range(len(location_rows))}
+
+ region_name_to_data: typing.Dict[str, Region]
+ location_name_to_data: typing.Dict[str, OSRSLocation]
+
+ location_rows_by_name: typing.Dict[str, LocationRow]
+ region_rows_by_name: typing.Dict[str, RegionRow]
+ resource_rows_by_name: typing.Dict[str, ResourceRow]
+ item_rows_by_name: typing.Dict[str, ItemRow]
+
+ starting_area_item: str
+
+ locations_by_category: typing.Dict[str, typing.List[LocationRow]]
+
+ def __init__(self, world: MultiWorld, player: int):
+ super().__init__(world, player)
+ self.region_name_to_data = {}
+ self.location_name_to_data = {}
+
+ self.location_rows_by_name = {}
+ self.region_rows_by_name = {}
+ self.resource_rows_by_name = {}
+ self.item_rows_by_name = {}
+
+ self.starting_area_item = ""
+
+ self.locations_by_category = {}
+
+ def generate_early(self) -> None:
+ location_categories = [location_row.category for location_row in location_rows]
+ self.locations_by_category = {category:
+ [location_row for location_row in location_rows if
+ location_row.category == category]
+ for category in location_categories}
+
+ self.location_rows_by_name = {loc_row.name: loc_row for loc_row in location_rows}
+ self.region_rows_by_name = {reg_row.name: reg_row for reg_row in region_rows}
+ self.resource_rows_by_name = {rec_row.name: rec_row for rec_row in resource_rows}
+ self.item_rows_by_name = {it_row.name: it_row for it_row in item_rows}
+
+ rnd = self.random
+ starting_area = self.options.starting_area
+
+ if starting_area.value == StartingArea.option_any_bank:
+ self.starting_area_item = rnd.choice(starting_area_dict)
+ elif starting_area.value < StartingArea.option_chunksanity:
+ self.starting_area_item = starting_area_dict[starting_area.value]
+ else:
+ self.starting_area_item = rnd.choice(chunksanity_starting_chunks)
+
+ # Set Starting Chunk
+ self.multiworld.push_precollected(self.create_item(self.starting_area_item))
+
+ """
+ This function pulls from LogicCSVToPython so that it sends the correct tag of the repository to the client.
+ _Make sure to update that value whenever the CSVs change!_
+ """
+
+ def fill_slot_data(self):
+ data = self.options.as_dict("brutal_grinds")
+ data["data_csv_tag"] = data_csv_tag
+ return data
+
+ def create_regions(self) -> None:
+ """
+ called to place player's regions into the MultiWorld's regions list. If it's hard to separate, this can be done
+ during generate_early or basic as well.
+ """
+
+ # First, create the "Menu" region to start
+ menu_region = self.create_region("Menu")
+
+ for region_row in region_rows:
+ self.create_region(region_row.name)
+
+ for resource_row in resource_rows:
+ self.create_region(resource_row.name)
+
+ # Removes the word "Area: " from the item name to get the region it applies to.
+ # I figured tacking "Area: " at the beginning would make it _easier_ to tell apart. Turns out it made it worse
+ if self.starting_area_item in chunksanity_special_region_names:
+ starting_area_region = chunksanity_special_region_names[self.starting_area_item]
+ else:
+ starting_area_region = self.starting_area_item[6:] # len("Area: ")
+ starting_entrance = menu_region.create_exit(f"Start->{starting_area_region}")
+ starting_entrance.access_rule = lambda state: state.has(self.starting_area_item, self.player)
+ starting_entrance.connect(self.region_name_to_data[starting_area_region])
+
+ # Create entrances between regions
+ for region_row in region_rows:
+ region = self.region_name_to_data[region_row.name]
+
+ for outbound_region_name in region_row.connections:
+ parsed_outbound = outbound_region_name.replace('*', '')
+ entrance = region.create_exit(f"{region_row.name}->{parsed_outbound}")
+ entrance.connect(self.region_name_to_data[parsed_outbound])
+
+ item_name = self.region_rows_by_name[parsed_outbound].itemReq
+ if "*" not in outbound_region_name and "*" not in item_name:
+ entrance.access_rule = lambda state, item_name=item_name: state.has(item_name, self.player)
+ continue
+
+ self.generate_special_rules_for(entrance, region_row, outbound_region_name)
+
+ for resource_region in region_row.resources:
+ if not resource_region:
+ continue
+
+ entrance = region.create_exit(f"{region_row.name}->{resource_region.replace('*', '')}")
+ if "*" not in resource_region:
+ entrance.connect(self.region_name_to_data[resource_region])
+ else:
+ self.generate_special_rules_for(entrance, region_row, resource_region)
+ entrance.connect(self.region_name_to_data[resource_region.replace('*', '')])
+
+ self.roll_locations()
+
+ def generate_special_rules_for(self, entrance, region_row, outbound_region_name):
+ # print(f"Special rules required to access region {outbound_region_name} from {region_row.name}")
+ if outbound_region_name == RegionNames.Cooks_Guild:
+ item_name = self.region_rows_by_name[outbound_region_name].itemReq.replace('*', '')
+ cooking_level_rule = self.get_skill_rule("cooking", 32)
+ entrance.access_rule = lambda state: state.has(item_name, self.player) and \
+ cooking_level_rule(state)
+ return
+ if outbound_region_name == RegionNames.Crafting_Guild:
+ item_name = self.region_rows_by_name[outbound_region_name].itemReq.replace('*', '')
+ crafting_level_rule = self.get_skill_rule("crafting", 40)
+ entrance.access_rule = lambda state: state.has(item_name, self.player) and \
+ crafting_level_rule(state)
+ return
+ if outbound_region_name == RegionNames.Corsair_Cove:
+ item_name = self.region_rows_by_name[outbound_region_name].itemReq.replace('*', '')
+ # Need to be able to start Corsair Curse in addition to having the item
+ entrance.access_rule = lambda state: state.has(item_name, self.player) and \
+ state.can_reach(RegionNames.Falador_Farm, "Region", self.player)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Falador_Farm, self.player), entrance)
+
+ return
+ if outbound_region_name == "Camdozaal*":
+ item_name = self.region_rows_by_name[outbound_region_name.replace('*', '')].itemReq
+ entrance.access_rule = lambda state: state.has(item_name, self.player) and \
+ state.has(ItemNames.QP_Below_Ice_Mountain, self.player)
+ return
+ if region_row.name == "Dwarven Mountain Pass" and outbound_region_name == "Anvil*":
+ entrance.access_rule = lambda state: state.has(ItemNames.QP_Dorics_Quest, self.player)
+ return
+ # Special logic for canoes
+ canoe_regions = [RegionNames.Lumbridge, RegionNames.South_Of_Varrock, RegionNames.Barbarian_Village,
+ RegionNames.Edgeville, RegionNames.Wilderness]
+ if region_row.name in canoe_regions:
+ # Skill rules for greater distances
+ woodcutting_rule_d1 = self.get_skill_rule("woodcutting", 12)
+ woodcutting_rule_d2 = self.get_skill_rule("woodcutting", 27)
+ woodcutting_rule_d3 = self.get_skill_rule("woodcutting", 42)
+ woodcutting_rule_all = self.get_skill_rule("woodcutting", 57)
+
+ if region_row.name == RegionNames.Lumbridge:
+ # Canoe Tree access for the Location
+ if outbound_region_name == RegionNames.Canoe_Tree:
+ entrance.access_rule = \
+ lambda state: (state.can_reach_region(RegionNames.South_Of_Varrock, self.player)
+ and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12) or \
+ (state.can_reach_region(RegionNames.Barbarian_Village)
+ and woodcutting_rule_d2(state) and self.options.max_woodcutting_level >= 27) or \
+ (state.can_reach_region(RegionNames.Edgeville)
+ and woodcutting_rule_d3(state) and self.options.max_woodcutting_level >= 42) or \
+ (state.can_reach_region(RegionNames.Wilderness)
+ and woodcutting_rule_all(state) and self.options.max_woodcutting_level >= 57)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.South_Of_Varrock, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Barbarian_Village, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Edgeville, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Wilderness, self.player), entrance)
+ # Access to other chunks based on woodcutting settings
+ # South of Varrock does not need to be checked, because it's already adjacent
+ if outbound_region_name == RegionNames.Barbarian_Village:
+ entrance.access_rule = lambda state: woodcutting_rule_d2(state) \
+ and self.options.max_woodcutting_level >= 27
+ if outbound_region_name == RegionNames.Edgeville:
+ entrance.access_rule = lambda state: woodcutting_rule_d3(state) \
+ and self.options.max_woodcutting_level >= 42
+ if outbound_region_name == RegionNames.Wilderness:
+ entrance.access_rule = lambda state: woodcutting_rule_all(state) \
+ and self.options.max_woodcutting_level >= 57
+
+ if region_row.name == RegionNames.South_Of_Varrock:
+ if outbound_region_name == RegionNames.Canoe_Tree:
+ entrance.access_rule = \
+ lambda state: (state.can_reach_region(RegionNames.Lumbridge, self.player)
+ and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12) or \
+ (state.can_reach_region(RegionNames.Barbarian_Village)
+ and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12) or \
+ (state.can_reach_region(RegionNames.Edgeville)
+ and woodcutting_rule_d2(state) and self.options.max_woodcutting_level >= 27) or \
+ (state.can_reach_region(RegionNames.Wilderness)
+ and woodcutting_rule_d3(state) and self.options.max_woodcutting_level >= 42)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Lumbridge, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Barbarian_Village, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Edgeville, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Wilderness, self.player), entrance)
+ # Access to other chunks based on woodcutting settings
+ # Lumbridge does not need to be checked, because it's already adjacent
+ if outbound_region_name == RegionNames.Barbarian_Village:
+ entrance.access_rule = lambda state: woodcutting_rule_d1(state) \
+ and self.options.max_woodcutting_level >= 12
+ if outbound_region_name == RegionNames.Edgeville:
+ entrance.access_rule = lambda state: woodcutting_rule_d3(state) \
+ and self.options.max_woodcutting_level >= 27
+ if outbound_region_name == RegionNames.Wilderness:
+ entrance.access_rule = lambda state: woodcutting_rule_all(state) \
+ and self.options.max_woodcutting_level >= 42
+ if region_row.name == RegionNames.Barbarian_Village:
+ if outbound_region_name == RegionNames.Canoe_Tree:
+ entrance.access_rule = \
+ lambda state: (state.can_reach_region(RegionNames.Lumbridge, self.player)
+ and woodcutting_rule_d2(state) and self.options.max_woodcutting_level >= 27) or \
+ (state.can_reach_region(RegionNames.South_Of_Varrock)
+ and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12) or \
+ (state.can_reach_region(RegionNames.Edgeville)
+ and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12) or \
+ (state.can_reach_region(RegionNames.Wilderness)
+ and woodcutting_rule_d2(state) and self.options.max_woodcutting_level >= 27)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Lumbridge, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.South_Of_Varrock, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Edgeville, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Wilderness, self.player), entrance)
+ # Access to other chunks based on woodcutting settings
+ if outbound_region_name == RegionNames.Lumbridge:
+ entrance.access_rule = lambda state: woodcutting_rule_d2(state) \
+ and self.options.max_woodcutting_level >= 27
+ if outbound_region_name == RegionNames.South_Of_Varrock:
+ entrance.access_rule = lambda state: woodcutting_rule_d1(state) \
+ and self.options.max_woodcutting_level >= 12
+ # Edgeville does not need to be checked, because it's already adjacent
+ if outbound_region_name == RegionNames.Wilderness:
+ entrance.access_rule = lambda state: woodcutting_rule_d3(state) \
+ and self.options.max_woodcutting_level >= 42
+ if region_row.name == RegionNames.Edgeville:
+ if outbound_region_name == RegionNames.Canoe_Tree:
+ entrance.access_rule = \
+ lambda state: (state.can_reach_region(RegionNames.Lumbridge, self.player)
+ and woodcutting_rule_d3(state) and self.options.max_woodcutting_level >= 42) or \
+ (state.can_reach_region(RegionNames.South_Of_Varrock)
+ and woodcutting_rule_d2(state) and self.options.max_woodcutting_level >= 27) or \
+ (state.can_reach_region(RegionNames.Barbarian_Village)
+ and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12) or \
+ (state.can_reach_region(RegionNames.Wilderness)
+ and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Lumbridge, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.South_Of_Varrock, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Barbarian_Village, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Wilderness, self.player), entrance)
+ # Access to other chunks based on woodcutting settings
+ if outbound_region_name == RegionNames.Lumbridge:
+ entrance.access_rule = lambda state: woodcutting_rule_d3(state) \
+ and self.options.max_woodcutting_level >= 42
+ if outbound_region_name == RegionNames.South_Of_Varrock:
+ entrance.access_rule = lambda state: woodcutting_rule_d2(state) \
+ and self.options.max_woodcutting_level >= 27
+ # Barbarian Village does not need to be checked, because it's already adjacent
+ # Wilderness does not need to be checked, because it's already adjacent
+ if region_row.name == RegionNames.Wilderness:
+ if outbound_region_name == RegionNames.Canoe_Tree:
+ entrance.access_rule = \
+ lambda state: (state.can_reach_region(RegionNames.Lumbridge, self.player)
+ and woodcutting_rule_all(state) and self.options.max_woodcutting_level >= 57) or \
+ (state.can_reach_region(RegionNames.South_Of_Varrock)
+ and woodcutting_rule_d3(state) and self.options.max_woodcutting_level >= 42) or \
+ (state.can_reach_region(RegionNames.Barbarian_Village)
+ and woodcutting_rule_d2(state) and self.options.max_woodcutting_level >= 27) or \
+ (state.can_reach_region(RegionNames.Edgeville)
+ and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Lumbridge, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.South_Of_Varrock, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Barbarian_Village, self.player), entrance)
+ self.multiworld.register_indirect_condition(
+ self.multiworld.get_region(RegionNames.Edgeville, self.player), entrance)
+ # Access to other chunks based on woodcutting settings
+ if outbound_region_name == RegionNames.Lumbridge:
+ entrance.access_rule = lambda state: woodcutting_rule_all(state) \
+ and self.options.max_woodcutting_level >= 57
+ if outbound_region_name == RegionNames.South_Of_Varrock:
+ entrance.access_rule = lambda state: woodcutting_rule_d3(state) \
+ and self.options.max_woodcutting_level >= 42
+ if outbound_region_name == RegionNames.Barbarian_Village:
+ entrance.access_rule = lambda state: woodcutting_rule_d2(state) \
+ and self.options.max_woodcutting_level >= 27
+ # Edgeville does not need to be checked, because it's already adjacent
+
+ def roll_locations(self):
+ locations_required = 0
+ generation_is_fake = hasattr(self.multiworld, "generation_is_fake") # UT specific override
+ for item_row in item_rows:
+ locations_required += item_row.amount
+
+ locations_added = 1 # At this point we've already added the starting area, so we start at 1 instead of 0
+
+ # Quests are always added
+ for i, location_row in enumerate(location_rows):
+ if location_row.category in {"quest", "points", "goal"}:
+ self.create_and_add_location(i)
+ if location_row.category == "quest":
+ locations_added += 1
+
+ # Build up the weighted Task Pool
+ rnd = self.random
+
+ # Start with the minimum general tasks
+ general_tasks = [task for task in self.locations_by_category["general"]]
+ if not self.options.progressive_tasks:
+ rnd.shuffle(general_tasks)
+ else:
+ general_tasks.reverse()
+ for i in range(self.options.minimum_general_tasks):
+ task = general_tasks.pop()
+ self.add_location(task)
+ locations_added += 1
+
+ general_weight = self.options.general_task_weight if len(general_tasks) > 0 else 0
+
+ tasks_per_task_type: typing.Dict[str, typing.List[LocationRow]] = {}
+ weights_per_task_type: typing.Dict[str, int] = {}
+
+ task_types = ["prayer", "magic", "runecraft", "mining", "crafting",
+ "smithing", "fishing", "cooking", "firemaking", "woodcutting", "combat"]
+ for task_type in task_types:
+ max_level_for_task_type = getattr(self.options, f"max_{task_type}_level")
+ max_amount_for_task_type = getattr(self.options, f"max_{task_type}_tasks")
+ tasks_for_this_type = [task for task in self.locations_by_category[task_type]
+ if task.skills[0].level <= max_level_for_task_type]
+ if not self.options.progressive_tasks:
+ rnd.shuffle(tasks_for_this_type)
+ else:
+ tasks_for_this_type.reverse()
+
+ tasks_for_this_type = tasks_for_this_type[:max_amount_for_task_type]
+ weight_for_this_type = getattr(self.options,
+ f"{task_type}_task_weight")
+ if weight_for_this_type > 0 and tasks_for_this_type:
+ tasks_per_task_type[task_type] = tasks_for_this_type
+ weights_per_task_type[task_type] = weight_for_this_type
+
+ # Build a list of collections and weights in a matching order for rnd.choices later
+ all_tasks = []
+ all_weights = []
+ for task_type in task_types:
+ if task_type in tasks_per_task_type:
+ all_tasks.append(tasks_per_task_type[task_type])
+ all_weights.append(weights_per_task_type[task_type])
+
+ # Even after the initial forced generals, they can still be rolled randomly
+ if general_weight > 0:
+ all_tasks.append(general_tasks)
+ all_weights.append(general_weight)
+
+ while locations_added < locations_required or (generation_is_fake and len(all_tasks) > 0):
+ if all_tasks:
+ chosen_task = rnd.choices(all_tasks, all_weights)[0]
+ if chosen_task:
+ task = chosen_task.pop()
+ self.add_location(task)
+ locations_added += 1
+
+ # This isn't an else because chosen_task can become empty in the process of resolving the above block
+ # We still want to clear this list out while we're doing that
+ if not chosen_task:
+ index = all_tasks.index(chosen_task)
+ del all_tasks[index]
+ del all_weights[index]
+
+ else:
+ if len(general_tasks) == 0:
+ raise Exception(f"There are not enough available tasks to fill the remaining pool for OSRS " +
+ f"Please adjust {self.player_name}'s settings to be less restrictive of tasks.")
+ task = general_tasks.pop()
+ self.add_location(task)
+ locations_added += 1
+
+ def add_location(self, location):
+ index = [i for i in range(len(location_rows)) if location_rows[i].name == location.name][0]
+ self.create_and_add_location(index)
+
+ def create_items(self) -> None:
+ for item_row in item_rows:
+ if item_row.name != self.starting_area_item:
+ for c in range(item_row.amount):
+ item = self.create_item(item_row.name)
+ self.multiworld.itempool.append(item)
+
+ def get_filler_item_name(self) -> str:
+ return self.random.choice(
+ [ItemNames.Progressive_Armor, ItemNames.Progressive_Weapons, ItemNames.Progressive_Magic,
+ ItemNames.Progressive_Tools, ItemNames.Progressive_Range_Armor, ItemNames.Progressive_Range_Weapon])
+
+ def create_and_add_location(self, row_index) -> None:
+ location_row = location_rows[row_index]
+ # print(f"Adding task {location_row.name}")
+
+ # Create Location
+ location_id = self.base_id + row_index
+ if location_row.category == "points" or location_row.category == "goal":
+ location_id = None
+ location = OSRSLocation(self.player, location_row.name, location_id)
+ self.location_name_to_data[location_row.name] = location
+
+ # Add the location to its first region, or if it doesn't belong to one, to Menu
+ region = self.region_name_to_data["Menu"]
+ if location_row.regions:
+ region = self.region_name_to_data[location_row.regions[0]]
+ location.parent_region = region
+ region.locations.append(location)
+
+ def set_rules(self) -> None:
+ """
+ called to set access and item rules on locations and entrances.
+ """
+ quest_attr_names = ["Cooks_Assistant", "Demon_Slayer", "Restless_Ghost", "Romeo_Juliet",
+ "Sheep_Shearer", "Shield_of_Arrav", "Ernest_the_Chicken", "Vampyre_Slayer",
+ "Imp_Catcher", "Prince_Ali_Rescue", "Dorics_Quest", "Black_Knights_Fortress",
+ "Witchs_Potion", "Knights_Sword", "Goblin_Diplomacy", "Pirates_Treasure",
+ "Rune_Mysteries", "Misthalin_Mystery", "Corsair_Curse", "X_Marks_the_Spot",
+ "Below_Ice_Mountain"]
+ for qp_attr_name in quest_attr_names:
+ loc_name = getattr(LocationNames, f"QP_{qp_attr_name}")
+ item_name = getattr(ItemNames, f"QP_{qp_attr_name}")
+ self.multiworld.get_location(loc_name, self.player) \
+ .place_locked_item(self.create_event(item_name))
+
+ for quest_attr_name in quest_attr_names:
+ qp_loc_name = getattr(LocationNames, f"QP_{quest_attr_name}")
+ q_loc_name = getattr(LocationNames, f"Q_{quest_attr_name}")
+ add_rule(self.multiworld.get_location(qp_loc_name, self.player), lambda state, q_loc_name=q_loc_name: (
+ self.multiworld.get_location(q_loc_name, self.player).can_reach(state)
+ ))
+
+ # place "Victory" at "Dragon Slayer" and set collection as win condition
+ self.multiworld.get_location(LocationNames.Q_Dragon_Slayer, self.player) \
+ .place_locked_item(self.create_event("Victory"))
+ self.multiworld.completion_condition[self.player] = lambda state: (state.has("Victory", self.player))
+
+ for location_name, location in self.location_name_to_data.items():
+ location_row = self.location_rows_by_name[location_name]
+ # Set up requirements for region
+ for region_required_name in location_row.regions:
+ region_required = self.region_name_to_data[region_required_name]
+ add_rule(location,
+ lambda state, region_required=region_required: state.can_reach(region_required, "Region",
+ self.player))
+ for skill_req in location_row.skills:
+ add_rule(location, self.get_skill_rule(skill_req.skill, skill_req.level))
+ for item_req in location_row.items:
+ add_rule(location, lambda state, item_req=item_req: state.has(item_req, self.player))
+ if location_row.qp:
+ add_rule(location, lambda state, location_row=location_row: self.quest_points(state) > location_row.qp)
+
+ def create_region(self, name: str) -> "Region":
+ region = Region(name, self.player, self.multiworld)
+ self.region_name_to_data[name] = region
+ self.multiworld.regions.append(region)
+ return region
+
+ def create_item(self, item_name: str) -> "Item":
+ item = [item for item in item_rows if item.name == item_name][0]
+ index = item_rows.index(item)
+ return OSRSItem(item.name, item.progression, self.base_id + index, self.player)
+
+ def create_event(self, event: str):
+ # while we are at it, we can also add a helper to create events
+ return OSRSItem(event, ItemClassification.progression, None, self.player)
+
+ def quest_points(self, state):
+ qp = 0
+ for qp_event in QP_Items:
+ if state.has(qp_event, self.player):
+ qp += int(qp_event[0])
+ return qp
+
+ """
+ Ensures a target level can be reached with available resources
+ """
+
+ def get_skill_rule(self, skill, level) -> CollectionRule:
+ if skill.lower() == "fishing":
+ if self.options.brutal_grinds or level < 5:
+ return lambda state: state.can_reach(RegionNames.Shrimp, "Region", self.player)
+ if level < 20:
+ return lambda state: state.can_reach(RegionNames.Shrimp, "Region", self.player) and \
+ state.can_reach(RegionNames.Port_Sarim, "Region", self.player)
+ else:
+ return lambda state: state.can_reach(RegionNames.Shrimp, "Region", self.player) and \
+ state.can_reach(RegionNames.Port_Sarim, "Region", self.player) and \
+ state.can_reach(RegionNames.Fly_Fish, "Region", self.player)
+ if skill.lower() == "mining":
+ if self.options.brutal_grinds or level < 15:
+ return lambda state: state.can_reach(RegionNames.Bronze_Ores, "Region", self.player) or \
+ state.can_reach(RegionNames.Clay_Rock, "Region", self.player)
+ else:
+ # Iron is the best way to train all the way to 99, so having access to iron is all you need to check for
+ return lambda state: (state.can_reach(RegionNames.Bronze_Ores, "Region", self.player) or
+ state.can_reach(RegionNames.Clay_Rock, "Region", self.player)) and \
+ state.can_reach(RegionNames.Iron_Rock, "Region", self.player)
+ if skill.lower() == "woodcutting":
+ if self.options.brutal_grinds or level < 15:
+ # I've checked. There is not a single chunk in the f2p that does not have at least one normal tree.
+ # Even the desert.
+ return lambda state: True
+ if level < 30:
+ return lambda state: state.can_reach(RegionNames.Oak_Tree, "Region", self.player)
+ else:
+ return lambda state: state.can_reach(RegionNames.Oak_Tree, "Region", self.player) and \
+ state.can_reach(RegionNames.Willow_Tree, "Region", self.player)
+ if skill.lower() == "smithing":
+ if self.options.brutal_grinds:
+ return lambda state: state.can_reach(RegionNames.Bronze_Ores, "Region", self.player) and \
+ state.can_reach(RegionNames.Furnace, "Region", self.player)
+ if level < 15:
+ # Lumbridge has a special bronze-only anvil. This is the only anvil of its type so it's not included
+ # in the "Anvil" resource region. We still need to check for it though.
+ return lambda state: state.can_reach(RegionNames.Bronze_Ores, "Region", self.player) and \
+ state.can_reach(RegionNames.Furnace, "Region", self.player) and \
+ (state.can_reach(RegionNames.Anvil, "Region", self.player) or
+ state.can_reach(RegionNames.Lumbridge, "Region", self.player))
+ if level < 30:
+ # For levels between 15 and 30, the lumbridge anvil won't cut it. Only a real one will do
+ return lambda state: state.can_reach(RegionNames.Bronze_Ores, "Region", self.player) and \
+ state.can_reach(RegionNames.Iron_Rock, "Region", self.player) and \
+ state.can_reach(RegionNames.Furnace, "Region", self.player) and \
+ state.can_reach(RegionNames.Anvil, "Region", self.player)
+ else:
+ return lambda state: state.can_reach(RegionNames.Bronze_Ores, "Region", self.player) and \
+ state.can_reach(RegionNames.Iron_Rock, "Region", self.player) and \
+ state.can_reach(RegionNames.Coal_Rock, "Region", self.player) and \
+ state.can_reach(RegionNames.Furnace, "Region", self.player) and \
+ state.can_reach(RegionNames.Anvil, "Region", self.player)
+ if skill.lower() == "crafting":
+ # Crafting is really complex. Need a lot of sub-rules to make this even remotely readable
+ def can_spin(state):
+ return state.can_reach(RegionNames.Sheep, "Region", self.player) and \
+ state.can_reach(RegionNames.Spinning_Wheel, "Region", self.player)
+
+ def can_pot(state):
+ return state.can_reach(RegionNames.Clay_Rock, "Region", self.player) and \
+ state.can_reach(RegionNames.Barbarian_Village, "Region", self.player)
+
+ def can_tan(state):
+ return state.can_reach(RegionNames.Milk, "Region", self.player) and \
+ state.can_reach(RegionNames.Al_Kharid, "Region", self.player)
+
+ def mould_access(state):
+ return state.can_reach(RegionNames.Al_Kharid, "Region", self.player) or \
+ state.can_reach(RegionNames.Rimmington, "Region", self.player)
+
+ def can_silver(state):
+
+ return state.can_reach(RegionNames.Silver_Rock, "Region", self.player) and \
+ state.can_reach(RegionNames.Furnace, "Region", self.player) and mould_access(state)
+
+ def can_gold(state):
+ return state.can_reach(RegionNames.Gold_Rock, "Region", self.player) and \
+ state.can_reach(RegionNames.Furnace, "Region", self.player) and mould_access(state)
+
+ if self.options.brutal_grinds or level < 5:
+ return lambda state: can_spin(state) or can_pot(state) or can_tan(state)
+
+ can_smelt_gold = self.get_skill_rule("smithing", 40)
+ can_smelt_silver = self.get_skill_rule("smithing", 20)
+ if level < 16:
+ return lambda state: can_pot(state) or can_tan(state) or (can_gold(state) and can_smelt_gold(state))
+ else:
+ return lambda state: can_tan(state) or (can_silver(state) and can_smelt_silver(state)) or \
+ (can_gold(state) and can_smelt_gold(state))
+ if skill.lower() == "Cooking":
+ if self.options.brutal_grinds or level < 15:
+ return lambda state: state.can_reach(RegionNames.Milk, "Region", self.player) or \
+ state.can_reach(RegionNames.Egg, "Region", self.player) or \
+ state.can_reach(RegionNames.Shrimp, "Region", self.player) or \
+ (state.can_reach(RegionNames.Wheat, "Region", self.player) and
+ state.can_reach(RegionNames.Windmill, "Region", self.player))
+ else:
+ can_catch_fly_fish = self.get_skill_rule("fishing", 20)
+ return lambda state: state.can_reach(RegionNames.Fly_Fish, "Region", self.player) and \
+ can_catch_fly_fish(state) and \
+ (state.can_reach(RegionNames.Milk, "Region", self.player) or
+ state.can_reach(RegionNames.Egg, "Region", self.player) or
+ state.can_reach(RegionNames.Shrimp, "Region", self.player) or
+ (state.can_reach(RegionNames.Wheat, "Region", self.player) and
+ state.can_reach(RegionNames.Windmill, "Region", self.player)))
+ if skill.lower() == "runecraft":
+ return lambda state: state.has(ItemNames.QP_Rune_Mysteries, self.player)
+ if skill.lower() == "magic":
+ return lambda state: state.can_reach(RegionNames.Mind_Runes, "Region", self.player)
+
+ return lambda state: True
diff --git a/worlds/osrs/docs/en_Old School Runescape.md b/worlds/osrs/docs/en_Old School Runescape.md
new file mode 100644
index 000000000000..d367082b2274
--- /dev/null
+++ b/worlds/osrs/docs/en_Old School Runescape.md
@@ -0,0 +1,114 @@
+# Old School Runescape
+
+## What is the Goal of this Randomizer?
+The goal is to complete the quest "Dragon Slayer I" with limited access to gear and map chunks while following normal
+Ironman/Group Ironman restrictions on a fresh free-to-play account.
+
+## Where is the options page?
+
+The [player options page for this game](../player-options) contains all the options you need to configure and export a
+config file. OSRS contains many options for a highly customizable experience. The options available to you are:
+
+* **Starting Area** - The starting region of your run. This is the first region you will have available, and you can always
+freely return to it (see the section below for when it is allowed to cross locked regions to access it)
+ * You may select a starting city from the list of Lumbridge, Al Kharid, Varrock (East or West), Edgeville, Falador,
+Draynor Village, or The Wilderness (Ferox Enclave)
+ * The option "Any Bank" will choose one of the above regions at random
+ * The option "Chunksanity" can start you in _any_ chunk, regardless of whether it has access to a bank.
+* **Brutal Grinds** - If enabled, the logic will assume you are willing to go to great lengths to train skills.
+ * As an example, when enabled, it might be in logic to obtain tin and copper from mob drops and smelt bronze bars to
+reach Smithing Level 40 to smelt gold for a task.
+ * If left disabled, the logic will always ensure you have a reasonable method for training a skill to reach a specific
+task, such as having access to intermediate-level training options
+* **Progressive Tasks** - If enabled, tasks for a skill are generated in order from earliest to latest.
+ * For example, your first Smithing task would always be "Smelt an Iron Bar", then "Smelt a Silver Bar", and so on.
+You would never have the task "Smelt a Gold Bar" without having every previous Smithing task as well.
+This can lead to a more consistent length of run, and is generally shorter than disabling it, but with less variety.
+* **Skill Category Weighting Options**
+ * These are available in each task category (all trainable skills plus "Combat" and "General")
+ * **Max [Category] Level** - The highest level you intend to have to reach in order to complete all tasks for this
+category. For the Combat category, this is the max level of monster you are willing to fight.
+General tasks do not have a level and thus do not have this option.
+ * **Max [Category] Tasks** - The highest number of tasks in this category you are willing to be assigned.
+Note that you can end up with _less_ than this amount, but never more. The "General" category is used to fill remaining
+spots so a maximum is not specified, instead it has a _minimum_ count.
+ * **[Category] Task Weighting** - The relative weighting of this category to all of the others. Increase this to make
+tasks in this category more likely.
+
+## What does randomization do to this game?
+The OSRS Archipelago Randomizer takes the form of a "Chunkman" account, a form of challenge account
+where you are limited to specific regions of the map (known as "chunks") until you complete tasks to unlock
+more. The plugin will interface with the [Region Locker Plugin](https://github.com/slaytostay/region-locker) to
+visually display these chunk borders and highlight them as locked or unlocked. The optional included GPU plugin for the
+Region Locker can tint the locked areas gray, but is incompatible with other GPU plugins such as 117's HD OSRS.
+If you choose not to include it, the world map will show locked and unlocked regions instead.
+
+In order to access a region, you will need to access it entirely through unlocked regions. At no point are you
+ever allowed to cross through locked regions, with the following exceptions:
+* If your starting region is not Lumbridge, when you complete Tutorial Island, you will need to traverse locked regions
+to reach your intended starting location.
+* If your starting region is not Lumbridge, you are allowed to "Home Teleport" to your starting region by using the
+Lumbridge Home Teleport Spell and then walking to your start location. This is to prevent you from getting "stuck" after
+using one-way transportation such as the Port Sarim Jail Teleport from Shantay Pass and being locked out of progression.
+* All of your starting Tutorial Island items are assumed to be available at all times. If you have lost an important
+item such as a Tinderbox, and cannot re-obtain it in your unlocked region, you are allowed to enter locked regions to
+replace it in the least obtrusive way possible.
+* If you need to adjust Group Ironman settings, such as adding or removing a member, you may freely access The Node
+to do so.
+
+When passing through locked regions for such exceptions, do not interact with any NPCs, items, or enemies and attempt
+to spend as little time in them as possible.
+
+The plugin will prevent equipping items that you have not unlocked the ability to wield. For example, attempting
+to equip an Iron Platebody before the first Progressive Armor unlock will display a chat message and will not
+equip the item.
+
+The plugin will show a list of your current tasks in the sidebar. The plugin will be able to detect the completion
+of most tasks, but in the case that a task cannot be detected (for example, killing an enemy with no
+drop table such as Deadly Red Spiders), the task can be marked as complete manually by clicking
+on the button. This button can also be used to mark completed tasks you have done while playing OSRS mobile or
+on a different client without having the plugin available. Simply click the button the next time you are logged in to
+Runelite and connected to send the check.
+
+Due to the nature of randomizing a live MMO with no ability to freely edit the character or adjust game logic or
+balancing, this randomizer relies heavily on **the honor system**. The plugin cannot prevent you from walking through
+locked regions or equipping locked items with the plugin disabled before connecting. It is important
+to acknowledge before starting that the entire purpose of the randomizer is a self-imposed challenge, and there
+is little point in cheating by circumventing the plugin's restrictions or marking a task complete without actually
+completing it. If you wish to play OSRS with no restrictions, that is always available without the plugin.
+
+In order to access the AP Text Client commands (such as `!hint` or to chat with other players in the seed), enter your
+command in chat prefaced by the string `!ap`. Example commands:
+
+`!ap buying gf 100k` -> Sends the message "buying gf 100k" to the server
+`!ap !hint Area: Lumbridge` -> Attempts to hint for the "Area: Lumbridge" item. Results will appear in your chat box.
+
+Other server messages, such as chat, will appear in your chat box, prefaced by the Archipelago icon.
+
+## What items and locations get shuffled?
+Items:
+- Every map region (at least one chunk but sometimes more)
+- Weapon tiers from iron to Rune (bronze is available from the start)
+- Armor tiers from iron to Rune (bronze is available from the start)
+- Two Spell Tiers (bolt and blast spells)
+- Three tiers of Ranged Armor (leather, studded leather + vambraces, green dragonhide)
+- Three tiers of Ranged Weapons (oak, willow, maple bows and their respective highest tier of arrows)
+
+Locations:
+* Every Quest is a location that will always be included in every seed
+* A random assortment of tasks, separated into categories based on the skill required.
+These task categories can have different weights, minimums, and maximums based on your options.
+ * For a full list of Locations, items, and regions, see the
+[Logic Document](https://docs.google.com/spreadsheets/d/1R8Cm8L6YkRWeiN7uYrdru8Vc1DlJ0aFAinH_fwhV8aU/edit?usp=sharing)
+
+## Which items can be in another player's world?
+Any item or region unlock can be found in any player's world.
+
+## What does another world's item look like in Old School Runescape?
+Upon completing a task, the item and recipient will be listed in the player's chatbox.
+
+## When the player receives an item, what happens?
+In addition to the message appearing in the chatbox, a UI window will appear listing the item and who sent it.
+These boxes also appear when connecting to a seed already in progress to list the items you have acquired while offline.
+The sidebar will list all received items below the task list, starting with regions, then showing the highest tier of
+equipment in each category.
\ No newline at end of file
diff --git a/worlds/osrs/docs/setup_en.md b/worlds/osrs/docs/setup_en.md
new file mode 100644
index 000000000000..47c1c8f16fd7
--- /dev/null
+++ b/worlds/osrs/docs/setup_en.md
@@ -0,0 +1,58 @@
+# Setup Guide for Old School Runescape
+
+## Required Software
+
+- [RuneLite](https://runelite.net/)
+- If the account being used has been migrated to a Jagex Account, the [Jagex Launcher](https://www.jagex.com/en-GB/launcher)
+will also be necessary to run RuneLite
+
+## Configuring your YAML file
+
+### What is a YAML file and why do I need one?
+
+Your YAML file contains a set of configuration options which provide the generator with information about how it should
+generate your game. Each player of a multiworld will provide their own YAML file. This setup allows each player to enjoy
+an experience customized for their taste, and different players in the same multiworld can all have different options.
+
+### Where do I get a YAML file?
+
+You can customize your settings by visiting the
+[Old School Runescape Player Options Page](/games/Old%20School%20Runescape/player-options).
+
+## Joining a MultiWorld Game
+
+### Install the RuneLite Plugins
+Open RuneLite and click on the wrench icon on the right side. From there, click on the plug icon to access the
+Plugin Hub. You will need to install the [Archipelago Plugin](https://github.com/digiholic/osrs-archipelago)
+and [Region Locker Plugin](https://github.com/slaytostay/region-locker). The Region Locker plugin
+will include three plugins; only the `Region Locker` plugin itself is required. The `Region Locker GPU` plugin can be
+used to display locked chunks in gray, but is incompatible with other GPU plugins such as 117's HD OSRS and can be
+disabled.
+
+### Create a new OSRS Account
+The OSRS Randomizer assumes you are playing on a newly created f2p Ironman account. As such, you will need to [create a
+new Runescape account](https://secure.runescape.com/m=account-creation/create_account?theme=oldschool).
+
+If you already have a [Jagex Account](https://www.jagex.com/en-GB/accounts) you can add up to 20 characters on
+one account through the Jagex Launcher. Note that there is currently no way to _remove_ characters
+from a Jagex Account, as such, you might want to create a separate account to hold your Archipelago
+characters if you intend to use your main Jagex account for more characters in the future.
+
+**Protip**: In order to avoid having to remember random email addresses for many accounts, take advantage of an email
+alias, a feature supported by most email providers. Any text after a `+` in your email address will redirect to your
+normal address, but the email will be recognized by the Jagex login as a new email address. For example, if your email
+were `Archipelago@gmail.com`, entering `Archipelago+OSRSRandomizer@gmail.com` would cause the confirmation email to
+be sent to your primary address, but the alias can be used to create a new account. One recommendation would be to
+include the date of generation in the account, such as `Archipelago+APYYMMDD@gmail.com` for easy memorability.
+
+After creating an account, you may run through Tutorial Island without connecting; the randomizer has no
+effect on the Tutorial.
+
+### Connect to the Multiserver
+In the Archipelago Plugin, enter your server information. The `Auto Reconnect on Login For` field should remain blank;
+it will be populated by the character name you first connect with, and it will reconnect to the AP server whenever that
+character logs in. Open the Archipelago panel on the right-hand side to connect to the multiworld while logged in to
+a game world to associate this character to the randomizer.
+
+For further information about how to connect to the server in the RuneLite plugin,
+please see the [Archipelago Plugin](https://github.com/digiholic/osrs-archipelago) instructions.
\ No newline at end of file
diff --git a/worlds/pokemon_rb/options.py b/worlds/pokemon_rb/options.py
index 54d486a6cf9f..9f217e82e646 100644
--- a/worlds/pokemon_rb/options.py
+++ b/worlds/pokemon_rb/options.py
@@ -418,10 +418,10 @@ class ExpModifier(NamedRange):
"""Modifier for EXP gained. When specifying a number, exp is multiplied by this amount and divided by 16."""
display_name = "Exp Modifier"
default = 16
- range_start = default / 4
+ range_start = default // 4
range_end = 255
special_range_names = {
- "half": default / 2,
+ "half": default // 2,
"normal": default,
"double": default * 2,
"triple": default * 3,
@@ -960,4 +960,4 @@ class RandomizePokemonPalettes(Choice):
"ice_trap_weight": IceTrapWeight,
"randomize_pokemon_palettes": RandomizePokemonPalettes,
"death_link": DeathLink
-}
\ No newline at end of file
+}
diff --git a/worlds/ror2/rules.py b/worlds/ror2/rules.py
index 2e6b018f42fb..f0ab9f28313f 100644
--- a/worlds/ror2/rules.py
+++ b/worlds/ror2/rules.py
@@ -31,23 +31,17 @@ def has_all_items(multiworld: MultiWorld, items: Set[str], region: str, player:
# Checks to see if chest/shrine are accessible
def has_location_access_rule(multiworld: MultiWorld, environment: str, player: int, item_number: int, item_type: str)\
-> None:
- if item_number == 1:
- multiworld.get_location(f"{environment}: {item_type} {item_number}", player).access_rule = \
- lambda state: state.has(environment, player)
+ location_name = f"{environment}: {item_type} {item_number}"
+ if item_type == "Scavenger":
# scavengers need to be locked till after a full loop since that is when they are capable of spawning.
# (While technically the requirement is just beating 5 stages, this will ensure that the player will have
# a long enough run to have enough director credits for scavengers and
# help prevent being stuck in the same stages until that point).
- if item_type == "Scavenger":
- multiworld.get_location(f"{environment}: {item_type} {item_number}", player).access_rule = \
- lambda state: state.has(environment, player) and state.has("Stage 5", player)
+ multiworld.get_location(location_name, player).access_rule = \
+ lambda state: state.has(environment, player) and state.has("Stage 5", player)
else:
- multiworld.get_location(f"{environment}: {item_type} {item_number}", player).access_rule = \
- lambda state: check_location(state, environment, player, item_number, item_type)
-
-
-def check_location(state, environment: str, player: int, item_number: int, item_name: str) -> bool:
- return state.can_reach(f"{environment}: {item_name} {item_number - 1}", "Location", player)
+ multiworld.get_location(location_name, player).access_rule = \
+ lambda state: state.has(environment, player)
def set_rules(ror2_world: "RiskOfRainWorld") -> None:
diff --git a/worlds/soe/__init__.py b/worlds/soe/__init__.py
index 3baed165d821..161c749fd6bd 100644
--- a/worlds/soe/__init__.py
+++ b/worlds/soe/__init__.py
@@ -188,6 +188,7 @@ class SoEWorld(World):
connect_name: str
_halls_ne_chest_names: typing.List[str] = [loc.name for loc in _locations if 'Halls NE' in loc.name]
+ _fillers = sorted(item_name_groups["Ingredients"])
def __init__(self, multiworld: "MultiWorld", player: int):
self.connect_name_available_event = threading.Event()
@@ -469,7 +470,7 @@ def modify_multidata(self, multidata: typing.Dict[str, typing.Any]) -> None:
multidata["connect_names"][self.connect_name] = payload
def get_filler_item_name(self) -> str:
- return self.random.choice(list(self.item_name_groups["Ingredients"]))
+ return self.random.choice(self._fillers)
class SoEItem(Item):
diff --git a/worlds/timespinner/Locations.py b/worlds/timespinner/Locations.py
index 86839f0f2167..f99dd7615571 100644
--- a/worlds/timespinner/Locations.py
+++ b/worlds/timespinner/Locations.py
@@ -135,11 +135,11 @@ def get_location_datas(player: Optional[int], options: Optional[TimespinnerOptio
LocationData('Upper Lake Serene', 'Lake Serene: Pyramid keys room', 1337104),
LocationData('Upper Lake Serene', 'Lake Serene (Upper): Chicken ledge', 1337174),
LocationData('Lower Lake Serene', 'Lake Serene (Lower): Deep dive', 1337105),
- LocationData('Lower Lake Serene', 'Lake Serene (Lower): Under the eels', 1337106),
+ LocationData('Left Side forest Caves', 'Lake Serene (Lower): Under the eels', 1337106, lambda state: state.has('Water Mask', player)),
LocationData('Lower Lake Serene', 'Lake Serene (Lower): Water spikes room', 1337107),
LocationData('Lower Lake Serene', 'Lake Serene (Lower): Underwater secret', 1337108, logic.can_break_walls),
LocationData('Lower Lake Serene', 'Lake Serene (Lower): T chest', 1337109, lambda state: flooded.flood_lake_serene or logic.has_doublejump_of_npc(state)),
- LocationData('Lower Lake Serene', 'Lake Serene (Lower): Past the eels', 1337110),
+ LocationData('Left Side forest Caves', 'Lake Serene (Lower): Past the eels', 1337110, lambda state: state.has('Water Mask', player)),
LocationData('Lower Lake Serene', 'Lake Serene (Lower): Underwater pedestal', 1337111, lambda state: flooded.flood_lake_serene or logic.has_doublejump(state)),
LocationData('Caves of Banishment (upper)', 'Caves of Banishment (Maw): Shroom jump room', 1337112, lambda state: flooded.flood_maw or logic.has_doublejump(state)),
LocationData('Caves of Banishment (upper)', 'Caves of Banishment (Maw): Secret room', 1337113, lambda state: logic.can_break_walls(state) and (not flooded.flood_maw or state.has('Water Mask', player))),
diff --git a/worlds/tloz/__init__.py b/worlds/tloz/__init__.py
index 8ea5f3e18ca1..c8c76bd85a8a 100644
--- a/worlds/tloz/__init__.py
+++ b/worlds/tloz/__init__.py
@@ -110,8 +110,8 @@ class TLoZWorld(World):
if v is not None:
location_name_to_id[k] = v + base_id
- def __init__(self, world: MultiWorld, player: int):
- super().__init__(world, player)
+ def __init__(self, multiworld: MultiWorld, player: int):
+ super().__init__(multiworld, player)
self.generator_in_use = threading.Event()
self.rom_name_available_event = threading.Event()
self.levels = None
diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py
index 5253e9951437..6657b464ed2d 100644
--- a/worlds/tunic/__init__.py
+++ b/worlds/tunic/__init__.py
@@ -410,7 +410,9 @@ def fill_slot_data(self) -> Dict[str, Any]:
return slot_data
# for the universal tracker, doesn't get called in standard gen
+ # docs: https://github.com/FarisTheAncient/Archipelago/blob/tracker/worlds/tracker/docs/re-gen-passthrough.md
@staticmethod
def interpret_slot_data(slot_data: Dict[str, Any]) -> Dict[str, Any]:
# returning slot_data so it regens, giving it back in multiworld.re_gen_passthrough
+ # we are using re_gen_passthrough over modifying the world here due to complexities with ER
return slot_data
diff --git a/worlds/tunic/er_data.py b/worlds/tunic/er_data.py
index f49e7dff3e58..e999026dec78 100644
--- a/worlds/tunic/er_data.py
+++ b/worlds/tunic/er_data.py
@@ -169,100 +169,16 @@ def destination_scene(self) -> str: # the vanilla connection
destination="Overworld Redux", tag="_rafters"),
Portal(name="Temple Door Exit", region="Sealed Temple",
destination="Overworld Redux", tag="_main"),
-
- Portal(name="Well Ladder Exit", region="Beneath the Well Ladder Exit",
- destination="Overworld Redux", tag="_entrance"),
- Portal(name="Well to Well Boss", region="Beneath the Well Back",
- destination="Sewer_Boss", tag="_"),
- Portal(name="Well Exit towards Furnace", region="Beneath the Well Back",
- destination="Overworld Redux", tag="_west_aqueduct"),
-
- Portal(name="Well Boss to Well", region="Well Boss",
- destination="Sewer", tag="_"),
- Portal(name="Checkpoint to Dark Tomb", region="Dark Tomb Checkpoint",
- destination="Crypt Redux", tag="_"),
-
- Portal(name="Dark Tomb to Overworld", region="Dark Tomb Entry Point",
+
+ Portal(name="Forest Belltower to Fortress", region="Forest Belltower Main",
+ destination="Fortress Courtyard", tag="_"),
+ Portal(name="Forest Belltower to Forest", region="Forest Belltower Lower",
+ destination="East Forest Redux", tag="_"),
+ Portal(name="Forest Belltower to Overworld", region="Forest Belltower Main",
destination="Overworld Redux", tag="_"),
- Portal(name="Dark Tomb to Furnace", region="Dark Tomb Dark Exit",
- destination="Furnace", tag="_"),
- Portal(name="Dark Tomb to Checkpoint", region="Dark Tomb Entry Point",
- destination="Sewer_Boss", tag="_"),
-
- Portal(name="West Garden Exit near Hero's Grave", region="West Garden",
- destination="Overworld Redux", tag="_lower"),
- Portal(name="West Garden to Magic Dagger House", region="West Garden",
- destination="archipelagos_house", tag="_"),
- Portal(name="West Garden Exit after Boss", region="West Garden after Boss",
- destination="Overworld Redux", tag="_upper"),
- Portal(name="West Garden Shop", region="West Garden",
- destination="Shop", tag="_"),
- Portal(name="West Garden Laurels Exit", region="West Garden Laurels Exit Region",
- destination="Overworld Redux", tag="_lowest"),
- Portal(name="West Garden Hero's Grave", region="West Garden Hero's Grave Region",
- destination="RelicVoid", tag="_teleporter_relic plinth"),
- Portal(name="West Garden to Far Shore", region="West Garden Portal",
- destination="Transit", tag="_teleporter_archipelagos_teleporter"),
-
- Portal(name="Magic Dagger House Exit", region="Magic Dagger House",
- destination="Archipelagos Redux", tag="_"),
-
- Portal(name="Atoll Upper Exit", region="Ruined Atoll",
- destination="Overworld Redux", tag="_upper"),
- Portal(name="Atoll Lower Exit", region="Ruined Atoll Lower Entry Area",
- destination="Overworld Redux", tag="_lower"),
- Portal(name="Atoll Shop", region="Ruined Atoll",
- destination="Shop", tag="_"),
- Portal(name="Atoll to Far Shore", region="Ruined Atoll Portal",
- destination="Transit", tag="_teleporter_atoll"),
- Portal(name="Atoll Statue Teleporter", region="Ruined Atoll Statue",
- destination="Library Exterior", tag="_"),
- Portal(name="Frog Stairs Eye Entrance", region="Ruined Atoll Frog Eye",
- destination="Frog Stairs", tag="_eye"),
- Portal(name="Frog Stairs Mouth Entrance", region="Ruined Atoll Frog Mouth",
- destination="Frog Stairs", tag="_mouth"),
-
- Portal(name="Frog Stairs Eye Exit", region="Frog Stairs Eye Exit",
- destination="Atoll Redux", tag="_eye"),
- Portal(name="Frog Stairs Mouth Exit", region="Frog Stairs Upper",
- destination="Atoll Redux", tag="_mouth"),
- Portal(name="Frog Stairs to Frog's Domain's Entrance", region="Frog Stairs to Frog's Domain",
- destination="frog cave main", tag="_Entrance"),
- Portal(name="Frog Stairs to Frog's Domain's Exit", region="Frog Stairs Lower",
- destination="frog cave main", tag="_Exit"),
-
- Portal(name="Frog's Domain Ladder Exit", region="Frog's Domain Entry",
- destination="Frog Stairs", tag="_Entrance"),
- Portal(name="Frog's Domain Orb Exit", region="Frog's Domain Back",
- destination="Frog Stairs", tag="_Exit"),
-
- Portal(name="Library Exterior Tree", region="Library Exterior Tree Region",
- destination="Atoll Redux", tag="_"),
- Portal(name="Library Exterior Ladder", region="Library Exterior Ladder Region",
- destination="Library Hall", tag="_"),
-
- Portal(name="Library Hall Bookshelf Exit", region="Library Hall Bookshelf",
- destination="Library Exterior", tag="_"),
- Portal(name="Library Hero's Grave", region="Library Hero's Grave Region",
- destination="RelicVoid", tag="_teleporter_relic plinth"),
- Portal(name="Library Hall to Rotunda", region="Library Hall to Rotunda",
- destination="Library Rotunda", tag="_"),
-
- Portal(name="Library Rotunda Lower Exit", region="Library Rotunda to Hall",
- destination="Library Hall", tag="_"),
- Portal(name="Library Rotunda Upper Exit", region="Library Rotunda to Lab",
- destination="Library Lab", tag="_"),
-
- Portal(name="Library Lab to Rotunda", region="Library Lab Lower",
- destination="Library Rotunda", tag="_"),
- Portal(name="Library to Far Shore", region="Library Portal",
- destination="Transit", tag="_teleporter_library teleporter"),
- Portal(name="Library Lab to Librarian Arena", region="Library Lab to Librarian",
- destination="Library Arena", tag="_"),
-
- Portal(name="Librarian Arena Exit", region="Library Arena",
- destination="Library Lab", tag="_"),
-
+ Portal(name="Forest Belltower to Guard Captain Room", region="Forest Belltower Upper",
+ destination="Forest Boss Room", tag="_"),
+
Portal(name="Forest to Belltower", region="East Forest",
destination="Forest Belltower", tag="_"),
Portal(name="Forest Guard House 1 Lower Entrance", region="East Forest",
@@ -281,7 +197,14 @@ def destination_scene(self) -> str: # the vanilla connection
destination="Sword Access", tag="_lower"),
Portal(name="Forest Grave Path Upper Entrance", region="East Forest",
destination="Sword Access", tag="_upper"),
-
+
+ Portal(name="Forest Grave Path Upper Exit", region="Forest Grave Path Upper",
+ destination="East Forest Redux", tag="_upper"),
+ Portal(name="Forest Grave Path Lower Exit", region="Forest Grave Path Main",
+ destination="East Forest Redux", tag="_lower"),
+ Portal(name="East Forest Hero's Grave", region="Forest Hero's Grave",
+ destination="RelicVoid", tag="_teleporter_relic plinth"),
+
Portal(name="Guard House 1 Dance Fox Exit", region="Guard House 1 West",
destination="East Forest Redux", tag="_upper"),
Portal(name="Guard House 1 Lower Exit", region="Guard House 1 West",
@@ -290,33 +213,54 @@ def destination_scene(self) -> str: # the vanilla connection
destination="East Forest Redux", tag="_gate"),
Portal(name="Guard House 1 to Guard Captain Room", region="Guard House 1 East",
destination="Forest Boss Room", tag="_"),
-
- Portal(name="Forest Grave Path Upper Exit", region="Forest Grave Path Upper",
- destination="East Forest Redux", tag="_upper"),
- Portal(name="Forest Grave Path Lower Exit", region="Forest Grave Path Main",
- destination="East Forest Redux", tag="_lower"),
- Portal(name="East Forest Hero's Grave", region="Forest Hero's Grave",
- destination="RelicVoid", tag="_teleporter_relic plinth"),
-
+
Portal(name="Guard House 2 Lower Exit", region="Guard House 2 Lower",
destination="East Forest Redux", tag="_lower"),
Portal(name="Guard House 2 Upper Exit", region="Guard House 2 Upper",
destination="East Forest Redux", tag="_upper"),
-
+
Portal(name="Guard Captain Room Non-Gate Exit", region="Forest Boss Room",
destination="East Forest Redux Laddercave", tag="_"),
Portal(name="Guard Captain Room Gate Exit", region="Forest Boss Room",
destination="Forest Belltower", tag="_"),
+
+ Portal(name="Well Ladder Exit", region="Beneath the Well Ladder Exit",
+ destination="Overworld Redux", tag="_entrance"),
+ Portal(name="Well to Well Boss", region="Beneath the Well Back",
+ destination="Sewer_Boss", tag="_"),
+ Portal(name="Well Exit towards Furnace", region="Beneath the Well Back",
+ destination="Overworld Redux", tag="_west_aqueduct"),
- Portal(name="Forest Belltower to Fortress", region="Forest Belltower Main",
- destination="Fortress Courtyard", tag="_"),
- Portal(name="Forest Belltower to Forest", region="Forest Belltower Lower",
- destination="East Forest Redux", tag="_"),
- Portal(name="Forest Belltower to Overworld", region="Forest Belltower Main",
+ Portal(name="Well Boss to Well", region="Well Boss",
+ destination="Sewer", tag="_"),
+ Portal(name="Checkpoint to Dark Tomb", region="Dark Tomb Checkpoint",
+ destination="Crypt Redux", tag="_"),
+
+ Portal(name="Dark Tomb to Overworld", region="Dark Tomb Entry Point",
destination="Overworld Redux", tag="_"),
- Portal(name="Forest Belltower to Guard Captain Room", region="Forest Belltower Upper",
- destination="Forest Boss Room", tag="_"),
+ Portal(name="Dark Tomb to Furnace", region="Dark Tomb Dark Exit",
+ destination="Furnace", tag="_"),
+ Portal(name="Dark Tomb to Checkpoint", region="Dark Tomb Entry Point",
+ destination="Sewer_Boss", tag="_"),
+ Portal(name="West Garden Exit near Hero's Grave", region="West Garden",
+ destination="Overworld Redux", tag="_lower"),
+ Portal(name="West Garden to Magic Dagger House", region="West Garden",
+ destination="archipelagos_house", tag="_"),
+ Portal(name="West Garden Exit after Boss", region="West Garden after Boss",
+ destination="Overworld Redux", tag="_upper"),
+ Portal(name="West Garden Shop", region="West Garden",
+ destination="Shop", tag="_"),
+ Portal(name="West Garden Laurels Exit", region="West Garden Laurels Exit Region",
+ destination="Overworld Redux", tag="_lowest"),
+ Portal(name="West Garden Hero's Grave", region="West Garden Hero's Grave Region",
+ destination="RelicVoid", tag="_teleporter_relic plinth"),
+ Portal(name="West Garden to Far Shore", region="West Garden Portal",
+ destination="Transit", tag="_teleporter_archipelagos_teleporter"),
+
+ Portal(name="Magic Dagger House Exit", region="Magic Dagger House",
+ destination="Archipelagos Redux", tag="_"),
+
Portal(name="Fortress Courtyard to Fortress Grave Path Lower", region="Fortress Courtyard",
destination="Fortress Reliquary", tag="_Lower"),
Portal(name="Fortress Courtyard to Fortress Grave Path Upper", region="Fortress Courtyard Upper",
@@ -333,12 +277,12 @@ def destination_scene(self) -> str: # the vanilla connection
destination="Overworld Redux", tag="_"),
Portal(name="Fortress Courtyard Shop", region="Fortress Exterior near cave",
destination="Shop", tag="_"),
-
+
Portal(name="Beneath the Vault to Fortress Interior", region="Beneath the Vault Back",
destination="Fortress Main", tag="_"),
Portal(name="Beneath the Vault to Fortress Courtyard", region="Beneath the Vault Ladder Exit",
destination="Fortress Courtyard", tag="_"),
-
+
Portal(name="Fortress Interior Main Exit", region="Eastern Vault Fortress",
destination="Fortress Courtyard", tag="_Big Door"),
Portal(name="Fortress Interior to Beneath the Earth", region="Eastern Vault Fortress",
@@ -351,14 +295,14 @@ def destination_scene(self) -> str: # the vanilla connection
destination="Fortress East", tag="_upper"),
Portal(name="Fortress Interior to East Fortress Lower", region="Eastern Vault Fortress",
destination="Fortress East", tag="_lower"),
-
+
Portal(name="East Fortress to Interior Lower", region="Fortress East Shortcut Lower",
destination="Fortress Main", tag="_lower"),
Portal(name="East Fortress to Courtyard", region="Fortress East Shortcut Upper",
destination="Fortress Courtyard", tag="_"),
Portal(name="East Fortress to Interior Upper", region="Fortress East Shortcut Upper",
destination="Fortress Main", tag="_upper"),
-
+
Portal(name="Fortress Grave Path Lower Exit", region="Fortress Grave Path",
destination="Fortress Courtyard", tag="_Lower"),
Portal(name="Fortress Hero's Grave", region="Fortress Hero's Grave Region",
@@ -370,11 +314,67 @@ def destination_scene(self) -> str: # the vanilla connection
Portal(name="Dusty Exit", region="Fortress Leaf Piles",
destination="Fortress Reliquary", tag="_"),
-
+
Portal(name="Siege Engine Arena to Fortress", region="Fortress Arena",
destination="Fortress Main", tag="_"),
Portal(name="Fortress to Far Shore", region="Fortress Arena Portal",
destination="Transit", tag="_teleporter_spidertank"),
+
+ Portal(name="Atoll Upper Exit", region="Ruined Atoll",
+ destination="Overworld Redux", tag="_upper"),
+ Portal(name="Atoll Lower Exit", region="Ruined Atoll Lower Entry Area",
+ destination="Overworld Redux", tag="_lower"),
+ Portal(name="Atoll Shop", region="Ruined Atoll",
+ destination="Shop", tag="_"),
+ Portal(name="Atoll to Far Shore", region="Ruined Atoll Portal",
+ destination="Transit", tag="_teleporter_atoll"),
+ Portal(name="Atoll Statue Teleporter", region="Ruined Atoll Statue",
+ destination="Library Exterior", tag="_"),
+ Portal(name="Frog Stairs Eye Entrance", region="Ruined Atoll Frog Eye",
+ destination="Frog Stairs", tag="_eye"),
+ Portal(name="Frog Stairs Mouth Entrance", region="Ruined Atoll Frog Mouth",
+ destination="Frog Stairs", tag="_mouth"),
+
+ Portal(name="Frog Stairs Eye Exit", region="Frog Stairs Eye Exit",
+ destination="Atoll Redux", tag="_eye"),
+ Portal(name="Frog Stairs Mouth Exit", region="Frog Stairs Upper",
+ destination="Atoll Redux", tag="_mouth"),
+ Portal(name="Frog Stairs to Frog's Domain's Entrance", region="Frog Stairs to Frog's Domain",
+ destination="frog cave main", tag="_Entrance"),
+ Portal(name="Frog Stairs to Frog's Domain's Exit", region="Frog Stairs Lower",
+ destination="frog cave main", tag="_Exit"),
+
+ Portal(name="Frog's Domain Ladder Exit", region="Frog's Domain Entry",
+ destination="Frog Stairs", tag="_Entrance"),
+ Portal(name="Frog's Domain Orb Exit", region="Frog's Domain Back",
+ destination="Frog Stairs", tag="_Exit"),
+
+ Portal(name="Library Exterior Tree", region="Library Exterior Tree Region",
+ destination="Atoll Redux", tag="_"),
+ Portal(name="Library Exterior Ladder", region="Library Exterior Ladder Region",
+ destination="Library Hall", tag="_"),
+
+ Portal(name="Library Hall Bookshelf Exit", region="Library Hall Bookshelf",
+ destination="Library Exterior", tag="_"),
+ Portal(name="Library Hero's Grave", region="Library Hero's Grave Region",
+ destination="RelicVoid", tag="_teleporter_relic plinth"),
+ Portal(name="Library Hall to Rotunda", region="Library Hall to Rotunda",
+ destination="Library Rotunda", tag="_"),
+
+ Portal(name="Library Rotunda Lower Exit", region="Library Rotunda to Hall",
+ destination="Library Hall", tag="_"),
+ Portal(name="Library Rotunda Upper Exit", region="Library Rotunda to Lab",
+ destination="Library Lab", tag="_"),
+
+ Portal(name="Library Lab to Rotunda", region="Library Lab Lower",
+ destination="Library Rotunda", tag="_"),
+ Portal(name="Library to Far Shore", region="Library Portal",
+ destination="Transit", tag="_teleporter_library teleporter"),
+ Portal(name="Library Lab to Librarian Arena", region="Library Lab to Librarian",
+ destination="Library Arena", tag="_"),
+
+ Portal(name="Librarian Arena Exit", region="Library Arena",
+ destination="Library Lab", tag="_"),
Portal(name="Stairs to Top of the Mountain", region="Lower Mountain Stairs",
destination="Mountaintop", tag="_"),
@@ -1183,6 +1183,8 @@ class DeadEnd(IntEnum):
[],
"Library Hero's Grave Region":
[],
+ "Library Hall to Rotunda":
+ [],
},
"Library Hero's Grave Region": {
"Library Hall":
diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py
index 0bd8c5e80681..a4295cf9f2a4 100644
--- a/worlds/tunic/er_scripts.py
+++ b/worlds/tunic/er_scripts.py
@@ -24,10 +24,10 @@ def create_er_regions(world: "TunicWorld") -> Dict[Portal, Portal]:
regions: Dict[str, Region] = {}
if world.options.entrance_rando:
portal_pairs = pair_portals(world)
-
# output the entrances to the spoiler log here for convenience
- for portal1, portal2 in portal_pairs.items():
- world.multiworld.spoiler.set_entrance(portal1.name, portal2.name, "both", world.player)
+ sorted_portal_pairs = sort_portals(portal_pairs)
+ for portal1, portal2 in sorted_portal_pairs.items():
+ world.multiworld.spoiler.set_entrance(portal1, portal2, "both", world.player)
else:
portal_pairs = vanilla_portals()
@@ -504,3 +504,29 @@ def update_reachable_regions(connected_regions: Set[str], traversal_reqs: Dict[s
connected_regions = update_reachable_regions(connected_regions, traversal_reqs, has_laurels, logic)
return connected_regions
+
+
+# sort the portal dict by the name of the first portal, referring to the portal order in the master portal list
+def sort_portals(portal_pairs: Dict[Portal, Portal]) -> Dict[str, str]:
+ sorted_pairs: Dict[str, str] = {}
+ reference_list: List[str] = [portal.name for portal in portal_mapping]
+ reference_list.append("Shop Portal")
+
+ # note: this is not necessary yet since the shop portals aren't numbered yet -- they will be when decoupled happens
+ # due to plando, there can be a variable number of shops
+ # I could either do it like this, or just go up to like 200, this seemed better
+ # shop_count = 0
+ # for portal1, portal2 in portal_pairs.items():
+ # if portal1.name.startswith("Shop"):
+ # shop_count += 1
+ # if portal2.name.startswith("Shop"):
+ # shop_count += 1
+ # reference_list.extend([f"Shop Portal {i + 1}" for i in range(shop_count)])
+
+ for name in reference_list:
+ for portal1, portal2 in portal_pairs.items():
+ if name == portal1.name:
+ sorted_pairs[portal1.name] = portal2.name
+ break
+ return sorted_pairs
+
diff --git a/worlds/undertale/__init__.py b/worlds/undertale/__init__.py
index 9084c77b0065..9f09bb34526b 100644
--- a/worlds/undertale/__init__.py
+++ b/worlds/undertale/__init__.py
@@ -67,12 +67,15 @@ def _get_undertale_data(self):
"only_flakes": bool(self.options.only_flakes.value),
"no_equips": bool(self.options.no_equips.value),
"key_hunt": bool(self.options.key_hunt.value),
- "key_pieces": self.options.key_pieces.value,
- "rando_love": bool(self.options.rando_love.value),
- "rando_stats": bool(self.options.rando_stats.value),
+ "key_pieces": int(self.options.key_pieces.value),
+ "rando_love": bool(self.options.rando_love and (self.options.route_required == "genocide" or self.options.route_required == "all_routes")),
+ "rando_stats": bool(self.options.rando_stats and (self.options.route_required == "genocide" or self.options.route_required == "all_routes")),
"prog_armor": bool(self.options.prog_armor.value),
"prog_weapons": bool(self.options.prog_weapons.value),
- "rando_item_button": bool(self.options.rando_item_button.value)
+ "rando_item_button": bool(self.options.rando_item_button.value),
+ "route_required": int(self.options.route_required.value),
+ "temy_include": int(self.options.temy_include.value)
+
}
def get_filler_item_name(self):
@@ -220,16 +223,7 @@ def UndertaleRegion(region_name: str, exits=[]):
link_undertale_areas(self.multiworld, self.player)
def fill_slot_data(self):
- slot_data = self._get_undertale_data()
- for option_name in self.options.as_dict():
- option = getattr(self.multiworld, option_name)[self.player]
- if (option_name == "rando_love" or option_name == "rando_stats") and \
- self.options.route_required != "genocide" and \
- self.options.route_required != "all_routes":
- option.value = False
- if slot_data.get(option_name, None) is None and type(option.value) in {str, int}:
- slot_data[option_name] = int(option.value)
- return slot_data
+ return self._get_undertale_data()
def create_item(self, name: str) -> Item:
item_data = item_table[name]