Skip to content

LTTP/SM/SMZ3: Show correct item icon for cross-game items #1112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7523fdb
LTTP/SM/SMZ3: Show correct item icon for cross-game items
Alchav Oct 17, 2022
a0d2d4b
remove comment
Alchav Oct 17, 2022
d3697ab
Revert accidental host.yaml changes
Alchav Oct 17, 2022
635e151
Merge branch 'main' into smz3_sprites_in_lttp
Alchav Oct 17, 2022
08efa27
Merge branch 'main' into smz3_sprites_in_lttp
Alchav Jan 17, 2023
b1d4b88
SMZ3/LTTP/SM cross game item fixes
Alchav Jan 18, 2023
0f2c707
Merge branch 'main' into smz3_sprites_in_lttp
Alchav Jan 28, 2023
d0a4d1e
Merge branch 'main' into smz3_sprites_in_lttp
Alchav Jan 31, 2023
c639163
Merge branch 'main' into smz3_sprites_in_lttp
Alchav Mar 22, 2023
2e3cc74
Update worlds/smz3/TotalSMZ3/Patch.py
Alchav Mar 26, 2023
3633d1c
Merge branch 'main' into smz3_sprites_in_lttp
Alchav Mar 26, 2023
e8db6fa
remove erroneous second copy of else branch
Alchav Mar 26, 2023
62be431
Use .get to provide default when getting SM items to future-proof for…
Alchav Mar 26, 2023
ff3b357
Merge branch 'main' into smz3_sprites_in_lttp
Alchav Apr 20, 2023
e142824
Merge branch 'main' into smz3_sprites_in_lttp
Alchav Apr 22, 2023
7b570fe
Use item_name_to_id
Alchav Jun 28, 2023
28bbb09
Merge remote-tracking branch 'origin/smz3_sprites_in_lttp' into smz3_…
Alchav Jun 28, 2023
13aa1fb
Merge branch 'main' into smz3_sprites_in_lttp
Alchav Jun 28, 2023
12df018
Merge branch 'main' into smz3_sprites_in_lttp
Alchav Jun 28, 2023
ad9d390
Update worlds/sm/__init__.py
Alchav Jun 29, 2023
5573797
Merge branch 'main' into smz3_sprites_in_lttp
Alchav Jun 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions worlds/alttp/Rom.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,9 @@ def write_to_rom(self, rom: LocalRom):
0x4D504, 0x4D507, 0x4D55E, 0x4D56A]


def get_nonnative_item_sprite(item: str) -> int:
def get_nonnative_item_sprite(code: int) -> int:
if 84173 >= code >= 84007: # LttP item in SMZ3
return code - 84000
return 0x6B # set all non-native sprites to Power Star as per 13 to 2 vote at
# https://discord.com/channels/731205301247803413/827141303330406408/852102450822905886

Expand All @@ -785,7 +787,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
if location.item.trap:
itemid = 0x5A # Nothing, which disguises
else:
itemid = get_nonnative_item_sprite(location.item.name)
itemid = get_nonnative_item_sprite(location.item.code)
# Keys in their native dungeon should use the orignal item code for keys
elif location.parent_region.dungeon:
if location.parent_region.dungeon.is_dungeon_item(location.item):
Expand Down Expand Up @@ -1739,7 +1741,7 @@ def write_custom_shops(rom, world, player):
replacement_price_data = get_price_data(item['replacement_price'], item['replacement_price_type'])
slot = 0 if shop.type == ShopType.TakeAny else index
if item['player'] and world.game[item['player']] != "A Link to the Past": # item not native to ALTTP
item_code = get_nonnative_item_sprite(item['item'])
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems janky but I don't know how else to get an item code from just the name. But also I think a lot of the shop code is janky and should be rewritten at some point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

world.item_name_to_id: dict[str, int]

item_code = get_nonnative_item_sprite(world.worlds[item['player']].item_name_to_id[item['item']])
else:
item_code = ItemFactory(item['item'], player).code
if item['item'] == 'Single Arrow' and item['player'] == 0 and world.retro_bow[player]:
Expand Down
50 changes: 29 additions & 21 deletions worlds/sm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,12 @@ def create_items(self):
isAdvancement = False

itemClass = ItemManager.Items[item.Type].Class
smitem = SMItem(item.Name,
ItemClassification.progression if isAdvancement else ItemClassification.filler,
smitem = SMItem(item.Name,
ItemClassification.progression if isAdvancement else ItemClassification.filler,
item.Type,
None if itemClass == 'Boss' else self.item_name_to_id[item.Name],
None if itemClass == 'Boss' else self.item_name_to_id[item.Name],
player=self.player)

if itemClass == 'Boss':
self.locked_items[item.Name] = smitem
elif item.Category == 'Nothing':
Expand All @@ -192,10 +192,10 @@ def create_items(self):
for (location, item) in self.locked_items.items():
self.multiworld.get_location(location, self.player).place_locked_item(item)
self.multiworld.get_location(location, self.player).address = None

def evalSMBool(self, smbool, maxDiff):
return smbool.bool == True and smbool.difficulty <= maxDiff

def add_entrance_rule(self, entrance, player, func):
add_rule(entrance, lambda state: self.evalSMBool(func(state.smbm[player]), state.smbm[player].maxDiff))

Expand All @@ -221,12 +221,12 @@ def set_entrance_rule(entrance, player, func):
add_accessFrom_rule(location, self.player, value.AccessFrom)
if value.PostAvailable is not None:
add_postAvailable_rule(location, self.player, value.PostAvailable)

for accessPoint in Logic.accessPoints:
if not accessPoint.Escape:
for key, value1 in accessPoint.intraTransitions.items():
set_entrance_rule(self.multiworld.get_entrance(accessPoint.Name + "->" + key, self.player), self.player, value1)

def create_region(self, world: MultiWorld, player: int, name: str, locations=None, exits=None):
ret = Region(name, player, world)
if locations:
Expand All @@ -238,7 +238,7 @@ def create_region(self, world: MultiWorld, player: int, name: str, locations=Non
for exit in exits:
ret.exits.append(Entrance(player, exit, ret))
return ret

def create_regions(self):
# create locations
for name in locationsDict:
Expand All @@ -248,9 +248,9 @@ def create_regions(self):
regions = []
for accessPoint in Logic.accessPoints:
if not accessPoint.Escape:
regions.append(self.create_region( self.multiworld,
self.player,
accessPoint.Name,
regions.append(self.create_region( self.multiworld,
self.player,
accessPoint.Name,
None,
[accessPoint.Name + "->" + key for key in accessPoint.intraTransitions.keys()]))

Expand All @@ -261,9 +261,9 @@ def create_regions(self):
# this is required in AP because a location cant have multiple parent regions
locationRegions = []
for locationName, value in locationsDict.items():
locationRegions.append(self.create_region( self.multiworld,
self.player,
locationName,
locationRegions.append(self.create_region( self.multiworld,
self.player,
locationName,
[locationName]))
for key in value.AccessFrom.keys():
currentRegion = self.multiworld.get_region(key, self.player)
Expand Down Expand Up @@ -320,7 +320,7 @@ def get_filler_item_name(self) -> str:
return "Super Missile"
else:
return "Nothing"

def pre_fill(self):
if len(self.NothingPool) > 0:
nonChozoLoc = []
Expand Down Expand Up @@ -371,8 +371,8 @@ def post_fill(self):
itemLoc.item.type if isinstance(itemLoc.item, SMItem) and itemLoc.item.type in ItemManager.Items else
'ArchipelagoItem']),
copy.copy(locationsDict[itemLoc.name] if itemLoc.game == self.game else
locationsDict[first_local_collected_loc.name]),
itemLoc.item.player,
locationsDict[first_local_collected_loc.name]),
itemLoc.item.player,
True)
for itemLoc in SMWorld.spheres if itemLoc.item.player == self.player
]
Expand All @@ -387,7 +387,7 @@ def post_fill(self):
escapeOk = self.variaRando.randoExec.graphBuilder.escapeGraph(self.variaRando.container, self.variaRando.randoExec.areaGraph, self.variaRando.randoExec.randoSettings.maxDiff, escapeTrigger)
if (not escapeOk):
logger.warning(f"Escape Rando forced to 'Off' for player {self.multiworld.get_player_name(self.player)} because could not find a solution for escape")

# if we couldn't find an area layout then the escape graph is not created either
# and getDoorConnections will crash if random escape is activated.
self.variaRando.doors = GraphUtils.getDoorConnections(self.variaRando.randoExec.areaGraph,
Expand All @@ -406,7 +406,7 @@ def stage_post_fill(cls, world):

for item in progitempool:
new_state.collect(item, True)

bossesLoc = ['Draygon', 'Kraid', 'Ridley', 'Phantoon', 'Mother Brain']
for player in world.get_game_players("Super Metroid"):
for bossLoc in bossesLoc:
Expand Down Expand Up @@ -548,9 +548,17 @@ def APPostPatchRom(self, romPatcher):
vanillaItemTypesCount = 21
for itemLoc in self.multiworld.get_locations():
if itemLoc.player == self.player and "Boss" not in locationsDict[itemLoc.name].Class:
# item to place in this SM world: write full item data to tables
SMZ3NameToSMType = {
"ETank": "ETank", "Missile": "Missile", "Super": "Super", "PowerBomb": "PowerBomb", "Bombs": "Bomb",
"Charge": "Charge", "Ice": "Ice", "HiJump": "HiJump", "SpeedBooster": "SpeedBooster",
"Wave": "Wave", "Spazer": "Spazer", "SpringBall": "SpringBall", "Varia": "Varia", "Plasma": "Plasma",
"Grapple": "Grapple", "Morph": "Morph", "ReserveTank": "Reserve", "Gravity": "Gravity",
"XRay": "XRayScope", "SpaceJump": "SpaceJump", "ScrewAttack": "ScrewAttack"
}
if isinstance(itemLoc.item, SMItem) and itemLoc.item.type in ItemManager.Items:
itemId = ItemManager.Items[itemLoc.item.type].Id
elif itemLoc.item.game == "SMZ3" and itemLoc.item.name in SMZ3NameToSMType.keys():
itemId = ItemManager.Items[SMZ3NameToSMType[itemLoc.item.name]].Id
else:
itemId = ItemManager.Items["ArchipelagoItem"].Id + idx
multiWorldItems.append({"sym": symbols["message_item_names"],
Expand Down
25 changes: 24 additions & 1 deletion worlds/smz3/TotalSMZ3/Patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import random
import typing
from BaseClasses import Location
from .Item import Item, ItemType
from .Item import Item, ItemType, lookup_id_to_name
from .Location import LocationType
from .Region import IReward, RewardType, SMRegion, Z3Region
from .Regions.Zelda.EasternPalace import EasternPalace
Expand Down Expand Up @@ -351,6 +351,29 @@ def GetZ3ItemId(self, location: Location):
not (item.IsDungeonItem() and location.Region.IsRegionItem(item) and item.World == self.myWorld) else itemDungeon

return value.value
elif (location.APLocation.item.game == "A Link to the Past"):
if location.APLocation.item.code + 84000 in lookup_id_to_name:
ALTTPBottleContentCodeToSMZ3ItemCode = {
ItemType.RedContent.value: ItemType.BottleWithRedPotion.value,
ItemType.GreenContent.value: ItemType.BottleWithGreenPotion.value,
ItemType.BlueContent.value: ItemType.BottleWithBluePotion.value,
ItemType.BeeContent.value: ItemType.BottleWithBee.value,
}
return ALTTPBottleContentCodeToSMZ3ItemCode.get(location.APLocation.item.code, location.APLocation.item.code)
else:
return ItemType.Something.value
elif (location.APLocation.item.game == "Super Metroid"):
SMNameToSMZ3Code = {
"Energy Tank": ItemType.ETank, "Missile": ItemType.Missile, "Super Missile": ItemType.Super,
"Power Bomb": ItemType.PowerBomb, "Bomb": ItemType.Bombs, "Charge Beam": ItemType.Charge,
"Ice Beam": ItemType.Ice, "Hi-Jump Boots": ItemType.HiJump, "Speed Booster": ItemType.SpeedBooster,
"Wave Beam": ItemType.Wave, "Spazer": ItemType.Spazer, "Spring Ball": ItemType.SpringBall,
"Varia Suit": ItemType.Varia, "Plasma Beam": ItemType.Plasma, "Grappling Beam": ItemType.Grapple,
"Morph Ball": ItemType.Morph, "Reserve Tank": ItemType.ReserveTank, "Gravity Suit": ItemType.Gravity,
"X-Ray Scope": ItemType.XRay, "Space Jump": ItemType.SpaceJump, "Screw Attack": ItemType.ScrewAttack,
"Nothing": ItemType.Something, "No Energy": ItemType.Something, "Generic": ItemType.Something
}
return SMNameToSMZ3Code.get(location.APLocation.item.name, ItemType.Something).value
else:
return ItemType.Something.value

Expand Down