forked from mirror/Archipelago
First integration of Dark Souls 3
This commit is contained in:
16
worlds/dark_souls_3/Items.py
Normal file
16
worlds/dark_souls_3/Items.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import typing
|
||||
from BaseClasses import Item
|
||||
from worlds.dark_souls_3.data.items_data import dictionary_table
|
||||
|
||||
|
||||
class ItemData(typing.NamedTuple):
|
||||
code: int
|
||||
progression: bool
|
||||
|
||||
|
||||
class DarkSouls3Item(Item):
|
||||
game: str = "Dark Souls III"
|
||||
|
||||
@staticmethod
|
||||
def get_item_name_to_id() -> typing.Dict[str, int]:
|
||||
return dictionary_table
|
||||
20
worlds/dark_souls_3/Locations.py
Normal file
20
worlds/dark_souls_3/Locations.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import typing
|
||||
from BaseClasses import Location, Region, RegionType
|
||||
from worlds.dark_souls_3.data.items_data import dictionary_table
|
||||
|
||||
|
||||
class LocationData(int):
|
||||
code: int
|
||||
|
||||
|
||||
class DarkSouls3Location(Location):
|
||||
game: str = "Dark Souls III"
|
||||
|
||||
# override constructor to automatically mark event locations as such
|
||||
def __init__(self, player: int, name='', code=None, parent=None):
|
||||
super(DarkSouls3Location, self).__init__(player, name, code, parent)
|
||||
self.event = code is None
|
||||
|
||||
@staticmethod
|
||||
def get_item_name_to_id() -> typing.Dict[str, int]:
|
||||
return dictionary_table
|
||||
18
worlds/dark_souls_3/Options.py
Normal file
18
worlds/dark_souls_3/Options.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import typing
|
||||
from Options import Choice, Option
|
||||
|
||||
|
||||
class SampleOption(Choice):
|
||||
"""
|
||||
This is a sample option.
|
||||
"""
|
||||
display_name = "Sample Option"
|
||||
option_1 = 1
|
||||
option_2 = 2
|
||||
default = 0
|
||||
|
||||
|
||||
dark_souls_options: typing.Dict[str, type(Option)] = {
|
||||
"sample_option": SampleOption,
|
||||
}
|
||||
|
||||
16
worlds/dark_souls_3/README.md
Normal file
16
worlds/dark_souls_3/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Dark Souls in [Archipelago](https://archipelago.gg)
|
||||
|
||||
## Abstract
|
||||
|
||||
- Extract the list of items (Weapons, Armors, KeyItems and Goods)
|
||||
- Hardcode this list along rules on the Archipelago server
|
||||
- The Archipelago server will shuffle and create a specific file for the Dark Souls client
|
||||
- This file or seed will place the items to their locations
|
||||
|
||||
## Prerequisities
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- onItemPicked event
|
||||
87
worlds/dark_souls_3/__init__.py
Normal file
87
worlds/dark_souls_3/__init__.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# world/dark_souls_3/__init__.py
|
||||
import json
|
||||
import os
|
||||
|
||||
from .Options import dark_souls_options # the options we defined earlier
|
||||
from .Items import DarkSouls3Item # data used below to add items to the World
|
||||
from .Locations import DarkSouls3Location # same as above
|
||||
from .data.items_data import dictionary_table
|
||||
from ..AutoWorld import World
|
||||
from BaseClasses import MultiWorld, Location, Region, Item, RegionType
|
||||
|
||||
|
||||
class DarkSouls3World(World):
|
||||
"""Insert description of the world/game here."""
|
||||
|
||||
def __init__(self, world: MultiWorld, player: int):
|
||||
super().__init__(world, player)
|
||||
self.locked_items = []
|
||||
self.locked_locations = []
|
||||
|
||||
def create_item(self, name: str) -> Item:
|
||||
data = self.item_name_to_id[name]
|
||||
return DarkSouls3Item(name, False, data, self.player)
|
||||
|
||||
def create_regions(self):
|
||||
menu_region = Region("Menu", RegionType.Generic, "Menu", self.player)
|
||||
for name, address in self.location_name_to_id.items():
|
||||
location = Location(self.player, name, address, menu_region)
|
||||
menu_region.locations.append(location)
|
||||
self.world.regions += [menu_region]
|
||||
|
||||
def create_items(self):
|
||||
for name, address in self.item_name_to_id.items():
|
||||
self.world.itempool += [self.create_item(name)]
|
||||
|
||||
def generate_early(self):
|
||||
pass
|
||||
|
||||
def set_rules(self):
|
||||
pass
|
||||
|
||||
def generate_basic(self):
|
||||
pass
|
||||
|
||||
def generate_output(self, output_directory: str):
|
||||
|
||||
location_list = list();
|
||||
for location in self.world.get_filled_locations(self.player):
|
||||
if location.item.player == self.player:
|
||||
location_list.append(location.item.code)
|
||||
else:
|
||||
location_list.append(0)
|
||||
|
||||
data = {
|
||||
"seed": self.world.seed_name, # to verify the server's multiworld
|
||||
"slot": self.world.player_name[self.player], # to connect to server
|
||||
"base_id": self.base_id, # to merge location and items lists
|
||||
"locations": location_list,
|
||||
"itemsAddress": list(dictionary_table.values())
|
||||
}
|
||||
|
||||
# generate the file
|
||||
filename = f"AP_{self.world.seed_name}_P{self.player}_{self.world.get_file_safe_player_name(self.player)}.json"
|
||||
with open(os.path.join(output_directory, filename), 'w') as outfile:
|
||||
json.dump(data, outfile)
|
||||
|
||||
game: str = "Dark Souls III" # name of the game/world
|
||||
options = dark_souls_options # options the player can set
|
||||
topology_present: bool = True # show path to required location checks in spoiler
|
||||
remote_items: bool = False # True if all items come from the server
|
||||
remote_start_inventory: bool = False # True if start inventory comes from the server
|
||||
|
||||
# data_version is used to signal that items, locations or their names
|
||||
# changed. Set this to 0 during development so other games' clients do not
|
||||
# cache any texts, then increase by 1 for each release that makes changes.
|
||||
data_version = 0
|
||||
|
||||
# ID of first item and location, could be hard-coded but code may be easier
|
||||
# to read with this as a propery.
|
||||
base_id = 1234
|
||||
# Instead of dynamic numbering, IDs could be part of data.
|
||||
|
||||
# The following two dicts are required for the generation to know which
|
||||
# items exist. They could be generated from json or something else. They can
|
||||
# include events, but don't have to since events will be placed manually.
|
||||
item_name_to_id = {name: id for id, name in enumerate(DarkSouls3Item.get_item_name_to_id(), base_id)}
|
||||
location_name_to_id = {name: id for id, name in enumerate(DarkSouls3Location.get_item_name_to_id(), base_id)}
|
||||
27
worlds/dark_souls_3/data/items_data.py
Normal file
27
worlds/dark_souls_3/data/items_data.py
Normal file
@@ -0,0 +1,27 @@
|
||||
class ItemData:
|
||||
pass
|
||||
|
||||
|
||||
rings_table = {
|
||||
"Covetous Silver Serpent Ring": 0x20004FB0,
|
||||
"Estus Ring": 0x200050DC,
|
||||
"Flame Stoneplate Ring": 0x20004E52,
|
||||
"Fire Clutch Ring": 0x2000501E,
|
||||
}
|
||||
|
||||
weapons_table = {
|
||||
"Rapier": 0x002E14E0,
|
||||
"East-West Shield": 0x0142B930,
|
||||
"Longbow": 0x00D689E0,
|
||||
"Mail Breaker": 0x002DEDD0,
|
||||
"Astora Straight Sword": 0x002191C0,
|
||||
"Broken Straight Sword": 0x001EF9B0,
|
||||
}
|
||||
|
||||
flask_items_table = {
|
||||
"Estus Flask Shard": 0x4000085D,
|
||||
"Ash Estus Flask": 0x400000BF,
|
||||
"Undead Bone Shard": 0x4000085F,
|
||||
}
|
||||
|
||||
dictionary_table = {**rings_table, **weapons_table, **flask_items_table }
|
||||
Reference in New Issue
Block a user