[SM] Add support for Remote Items (#317)
This commit is contained in:
parent
9ba70951d5
commit
7df12930ef
11
SNIClient.py
11
SNIClient.py
|
@ -201,7 +201,8 @@ async def deathlink_kill_player(ctx: Context):
|
|||
snes_buffered_write(ctx, WRAM_START + 0x0373,
|
||||
bytes([8])) # deal 1 full heart of damage at next opportunity
|
||||
elif ctx.game == GAME_SM:
|
||||
snes_buffered_write(ctx, WRAM_START + 0x09C2, bytes([0, 0])) # set current health to 0
|
||||
snes_buffered_write(ctx, WRAM_START + 0x09C2, bytes([1, 0])) # set current health to 1 (to prevent saving with 0 energy)
|
||||
snes_buffered_write(ctx, WRAM_START + 0x0A50, bytes([255])) # deal 255 of damage at next opportunity
|
||||
if not ctx.death_link_allow_survive:
|
||||
snes_buffered_write(ctx, WRAM_START + 0x09D6, bytes([0, 0])) # set current reserve to 0
|
||||
await snes_flush_writes(ctx)
|
||||
|
@ -266,6 +267,7 @@ SM_RECV_ITEM_ADDR = SAVEDATA_START + 0x4D2 # 1 byte
|
|||
SM_RECV_ITEM_PLAYER_ADDR = SAVEDATA_START + 0x4D3 # 1 byte
|
||||
|
||||
SM_DEATH_LINK_ACTIVE_ADDR = ROM_START + 0x277f04 # 1 byte
|
||||
SM_REMOTE_ITEM_FLAG_ADDR = ROM_START + 0x277f06 # 1 byte
|
||||
|
||||
# SMZ3
|
||||
SMZ3_ROMNAME_START = 0x00FFC0
|
||||
|
@ -983,7 +985,8 @@ async def game_watcher(ctx: Context):
|
|||
continue
|
||||
elif game_name[:2] == b"SM":
|
||||
ctx.game = GAME_SM
|
||||
ctx.items_handling = 0b001 # full local
|
||||
item_handling = await snes_read(ctx, SM_REMOTE_ITEM_FLAG_ADDR, 1)
|
||||
ctx.items_handling = 0b001 if item_handling is None else item_handling[0]
|
||||
else:
|
||||
game_name = await snes_read(ctx, SMZ3_ROMNAME_START, 3)
|
||||
if game_name == b"ZSM":
|
||||
|
@ -1133,13 +1136,15 @@ async def game_watcher(ctx: Context):
|
|||
itemOutPtr = data[2] | (data[3] << 8)
|
||||
|
||||
from worlds.sm.Items import items_start_id
|
||||
from worlds.sm.Locations import locations_start_id
|
||||
if itemOutPtr < len(ctx.items_received):
|
||||
item = ctx.items_received[itemOutPtr]
|
||||
itemId = item.item - items_start_id
|
||||
locationId = (item.location - locations_start_id) if item.location >= 0 else 0x00
|
||||
|
||||
playerID = item.player if item.player <= SM_ROM_PLAYER_LIMIT else 0
|
||||
snes_buffered_write(ctx, SM_RECV_PROGRESS_ADDR + itemOutPtr * 4, bytes(
|
||||
[playerID & 0xFF, (playerID >> 8) & 0xFF, itemId & 0xFF, (itemId >> 8) & 0xFF]))
|
||||
[playerID & 0xFF, (playerID >> 8) & 0xFF, itemId & 0xFF, locationId & 0xFF]))
|
||||
itemOutPtr += 1
|
||||
snes_buffered_write(ctx, SM_RECV_PROGRESS_ADDR + 0x602,
|
||||
bytes([itemOutPtr & 0xFF, (itemOutPtr >> 8) & 0xFF]))
|
||||
|
|
|
@ -52,6 +52,10 @@ class DeathLink(Choice):
|
|||
alias_true = 1
|
||||
default = 0
|
||||
|
||||
class RemoteItems(Toggle):
|
||||
"""Indicates you get items sent from your own world. This allows coop play of a world."""
|
||||
display_name = "Remote Items"
|
||||
|
||||
class MaxDifficulty(Choice):
|
||||
"""Depending on the perceived difficulties of the techniques, bosses, hell runs etc. from the preset, it will prevent the Randomizer from placing an item in a location too difficult to reach with the current items."""
|
||||
display_name = "Maximum Difficulty"
|
||||
|
@ -225,6 +229,7 @@ sm_options: typing.Dict[str, type(Option)] = {
|
|||
"start_inventory_removes_from_pool": StartItemsRemovesFromPool,
|
||||
"preset": Preset,
|
||||
"start_location": StartLocation,
|
||||
"remote_items": RemoteItems,
|
||||
"death_link": DeathLink,
|
||||
#"majors_split": "Full",
|
||||
#"scav_num_locs": "10",
|
||||
|
|
|
@ -91,6 +91,8 @@ class SMWorld(World):
|
|||
if (self.variaRando.args.morphPlacement == "early"):
|
||||
self.world.local_items[self.player].value.add('Morph')
|
||||
|
||||
self.remote_items = self.world.remote_items[self.player]
|
||||
|
||||
if (len(self.variaRando.randoExec.setup.restrictedLocs) > 0):
|
||||
self.world.accessibility[self.player] = self.world.accessibility[self.player].from_text("items")
|
||||
logger.warning(f"accessibility forced to 'items' for player {self.world.get_player_name(self.player)} because of 'fun' settings")
|
||||
|
@ -285,6 +287,7 @@ class SMWorld(World):
|
|||
openTourianGreyDoors = {0x07C823 + 5: [0x0C], 0x07C831 + 5: [0x0C]}
|
||||
|
||||
deathLink = {0x277f04: [self.world.death_link[self.player].value]}
|
||||
remoteItem = {0x277f06: self.getWordArray(0b001 + (0b010 if self.remote_items else 0b000))}
|
||||
|
||||
playerNames = {}
|
||||
playerNameIDMap = {}
|
||||
|
@ -299,6 +302,7 @@ class SMWorld(World):
|
|||
'offworldSprites': offworldSprites,
|
||||
'openTourianGreyDoors': openTourianGreyDoors,
|
||||
'deathLink': deathLink,
|
||||
'remoteItem': remoteItem,
|
||||
'PlayerName': playerNames,
|
||||
'PlayerNameIDMap': playerNameIDMap}
|
||||
romPatcher.applyIPSPatchDict(patchDict)
|
||||
|
@ -310,6 +314,7 @@ class SMWorld(World):
|
|||
self.romName.extend([0] * (21 - len(self.romName)))
|
||||
romPatcher.applyIPSPatch('ROMName', { 'ROMName': {0x1C4F00 : self.romName, 0x007FC0 : self.romName} })
|
||||
|
||||
|
||||
startItemROMAddressBase = 0x2FD8B9
|
||||
|
||||
# current, base value or bitmask, max, base value or bitmask
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue