Skip to content

Commit

Permalink
Merge pull request ArchipelagoMW#10 from jcbantuelle/fix-surface-shop
Browse files Browse the repository at this point in the history
Lamulana: Fix Surface Shop Guardian Trigger
  • Loading branch information
jcbantuelle authored Nov 11, 2024
2 parents 5ccea28 + 3a5bd69 commit 9722d71
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 16 deletions.
6 changes: 6 additions & 0 deletions worlds/lamulana/DatMod.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ def apply_mods(self):
self.__rewrite_xelpud_pillar_conversation()
self.__update_slushfund_flags()

def find_shop_flag(self, card_name, slot):
shop_card = self.__find_card(card_name)
entries = shop_card.contents.entries
data_indices = [i for i,v in enumerate(entries) if v.header == HEADERS["data"]]
return entries[data_indices[3]].contents.values[slot]

# DAT Mod Methods

def __place_conversation_item(self, entries, item_id, location, item, original_obtain_flag, new_obtain_flag, obtain_value):
Expand Down
4 changes: 4 additions & 0 deletions worlds/lamulana/LmFlags.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,18 @@
"grail_tablet_shrine_back": 0x75,
"ankh_jewel_mausoleum": 0x8f,
"yagostr_found": 0xe5,
"guardians_killed": 0x102,
"diary_found": 0x104,
"mulana_talisman": 0x105,
"endless_fairyqueen": 0x1f5,
"diary_chest_puzzle": 0x212,
"shrine_dragon_bone": 0x218,
"shrine_diary_chest": 0x219,
"shrine_shawn": 0x21b,
"xelpud_msx2": 0x21d,
"slushfund_conversation": 0x228,
"cant_leave_conversation": 0x2e4,
"msx2_found": 0x2e6,
"xelpud_talisman": 0x327,
"grail_tablet_surface": 0x54e,
"starting_items": 0x84f,
Expand Down Expand Up @@ -63,6 +66,7 @@
"xelpud_pillar": 370,
"xelpud_mulana_talisman": 371,
"xelpud_conversation_tree": 480,
"nebur_guardian": 490,
"xelpud_howling_wind": 1049
}

Expand Down
41 changes: 28 additions & 13 deletions worlds/lamulana/RcdMod.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .FileMod import FileMod
from .Items import item_table
from .Rcd import Rcd
from .LmFlags import GLOBAL_FLAGS, RCD_OBJECTS, TEST_OPERATIONS, WRITE_OPERATIONS, grail_flag_by_zone
from .LmFlags import GLOBAL_FLAGS, RCD_OBJECTS, TEST_OPERATIONS, WRITE_OPERATIONS, CARDS, grail_flag_by_zone
from .Locations import get_locations_by_region

class RcdMod(FileMod):
Expand Down Expand Up @@ -73,11 +73,12 @@ def place_item_in_location(self, item, item_id, location) -> None:
params["location_id"] = location_id
self.__place_item(**params)

def apply_mods(self):
def apply_mods(self, dat_mod):
self.__give_starting_items(self.start_inventory)
self.__rewrite_diary_chest()
self.__add_diary_chest_timer()
self.__rewrite_slushfund_conversation_conditions()
self.__rewrite_four_guardian_shop_conditions(dat_mod)
self.__clean_up_test_operations()

if self.options.AutoScanGrailTablets:
Expand Down Expand Up @@ -109,11 +110,11 @@ def __place_item(self, objects, object_type, param_index, param_len, location, l

# Shrine of the Mother Map Crusher customization
if original_obtain_flag == GLOBAL_FLAGS["shrine_map"]:
self.__update_operation("write_operations", objects, RCD_OBJECTS["crusher"], original_obtain_flag, new_obtain_flag, obtain_value)
self.__update_operation("write_operations", objects, RCD_OBJECTS["crusher"], original_obtain_flag, new_obtain_flag, new_op_value=obtain_value)

# Mausoleum Ankh Jewel Trap customization
if original_obtain_flag == GLOBAL_FLAGS["ankh_jewel_mausoleum"]:
self.__update_operation("write_operations", objects, RCD_OBJECTS["moving_texture"], original_obtain_flag, new_obtain_flag, obtain_value)
self.__update_operation("write_operations", objects, RCD_OBJECTS["moving_texture"], original_obtain_flag, new_obtain_flag, new_op_value=obtain_value)

# Yagostr Dais customization
if original_obtain_flag == GLOBAL_FLAGS["yagostr_found"]:
Expand Down Expand Up @@ -231,6 +232,13 @@ def __add_diary_chest_timer(self) -> None:
screen.objects_without_position_length += 1
self.file_size += 20

def __rewrite_four_guardian_shop_conditions(self, dat_mod):
msx2_replacement_flag = dat_mod.find_shop_flag("nebur_guardian", 0)
objects = self.file_contents.zones[1].rooms[2].screens[0].objects_with_position
self.__update_operation("test_operations", objects, RCD_OBJECTS["language_conversation"], GLOBAL_FLAGS["xelpud_msx2"], GLOBAL_FLAGS["guardians_killed"], old_op_value=0, new_op_value=3, new_operation=TEST_OPERATIONS["lteq"])
self.__update_operation("test_operations", objects, RCD_OBJECTS["language_conversation"], GLOBAL_FLAGS["xelpud_msx2"], GLOBAL_FLAGS["guardians_killed"], old_op_value=1, new_op_value=4)
self.__update_operation("test_operations", objects, RCD_OBJECTS["language_conversation"], GLOBAL_FLAGS["msx2_found"], msx2_replacement_flag)

def __rewrite_slushfund_conversation_conditions(self):
objects = self.file_contents.zones[10].rooms[8].screens[0].objects_with_position
self.__update_operation("test_operations", objects, RCD_OBJECTS["language_conversation"], GLOBAL_FLAGS["slushfund_conversation"], GLOBAL_FLAGS["replacement_slushfund_conversation"])
Expand Down Expand Up @@ -291,25 +299,32 @@ def __create_grail_autoscans(self) -> None:

# Search Methods

def __find_objects_by_operation(self, op_type, objects, object_id, flag):
return [o for _, o in enumerate(objects) if o.id == object_id and len([op for op in getattr(o, op_type) if op.flag == flag]) > 0]
def __find_objects_by_operation(self, op_type, objects, object_id, flag, operation=None, op_value=None):
return [o for _, o in enumerate(objects) if o.id == object_id and len([op for op in getattr(o, op_type) if self.__op_matches(op, flag, operation, op_value)]) > 0]

def __find_operation_index(self, ops, flag, operation=None, op_value=None):
return next(i for i,op in enumerate(ops) if self.__op_matches(op, flag, operation, op_value))

# Conditionals

def __find_operation_index(self, ops, flag):
return next(i for i,op in enumerate(ops) if op.flag == flag)
def __op_matches(self, op, flag, operation, op_value):
return op.flag == flag and (operation is None or op.operation == operation) and (op_value is None or op.op_value == op_value)

# Write Methods

def __update_operation(self, op_type, objects, object_id, old_flag, new_flag, value=None):
objs = self.__find_objects_by_operation(op_type, objects, object_id, old_flag)
def __update_operation(self, op_type, objects, object_id, old_flag, new_flag, old_operation=None, new_operation=None, old_op_value=None, new_op_value=None):
objs = self.__find_objects_by_operation(op_type, objects, object_id, old_flag, old_operation, old_op_value)

for obj in objs:
ops = getattr(obj, op_type)
op_index = self.__find_operation_index(ops, old_flag)
op_index = self.__find_operation_index(ops, old_flag, old_operation, old_op_value)

op = getattr(obj, op_type)[op_index]
op.flag = new_flag
if value is not None:
op.op_value = value
if new_operation is not None:
op.operation = new_operation
if new_op_value is not None:
op.op_value = new_op_value

def __remove_operation(self, op_type, objects, object_id, flag):
objs = self.__find_objects_by_operation(op_type, objects, object_id, flag)
Expand Down
6 changes: 3 additions & 3 deletions worlds/lamulana/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,14 +564,14 @@ def start_inventory_as_list(self) -> List[str]:
return out

def generate_output(self, output_directory: str) -> None:
locations = self.multiworld.get_locations(self.player)

local_config = LocalConfig(self.multiworld, self.player)
rcd_mod = RcdMod("script.rcd", local_config, self.options, self.start_inventory_as_list() + list(self.precollected_items[self.player]))
dat_mod = DatMod("script_code.dat", local_config, self.options)

dat_mod.apply_mods()

locations = self.multiworld.get_locations(self.player)

for location in locations:
item = item_table.get(location.item.name)
if (item is None and location.item.player == self.player) or location.address is None:
Expand All @@ -583,7 +583,7 @@ def generate_output(self, output_directory: str) -> None:
elif location.file_type == 'dat':
dat_mod.place_item_in_location(item, item_id, location)

rcd_mod.apply_mods()
rcd_mod.apply_mods(dat_mod)

output_path = os.path.join(output_directory, f"AP-{self.multiworld.seed_name}-P{self.player}-{self.multiworld.get_file_safe_player_name(self.player)}_{Utils.__version__}.zip")
with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED, True, 9) as output_zip:
Expand Down

0 comments on commit 9722d71

Please sign in to comment.