Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 5 additions & 2 deletions Callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,13 @@ def handle_vendor(ctx: "Rac2Context"):
# Use Down/Up to toggle between ammo/weapon mode
holding_down: bool = interface.pcsx2_interface.read_int16(addresses.controller_input) == 0x4000
holding_up: bool = interface.pcsx2_interface.read_int16(addresses.controller_input) == 0x1000
if holding_down and interface.vendor.mode is Vendor.Mode.MEGACORP:
if holding_down and interface.vendor.mode in [Vendor.Mode.MEGACORP, Vendor.Mode.GADGETRON]:
interface.vendor.change_mode(ctx, Vendor.Mode.AMMO)
if holding_up and interface.vendor.mode is Vendor.Mode.AMMO:
interface.vendor.change_mode(ctx, Vendor.Mode.MEGACORP)
if interface.vendor.is_megacorp():
interface.vendor.change_mode(ctx, Vendor.Mode.MEGACORP)
else:
interface.vendor.change_mode(ctx, Vendor.Mode.GADGETRON)


def process_vendor_text(manager: TextManager, ctx: "Rac2Context") -> None:
Expand Down
40 changes: 20 additions & 20 deletions Container.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,26 +211,6 @@ def generate_patch(world: "Rac2World", patch: Rac2ProcedurePatch, instruction=No
# Put the base scaling from vanilla game for XP & Bolts even for revisits
patch.write_token(APTokenTypes.WRITE, address, bytes([100, 50, 40, 30, 25, 20, 15, 10] * 4))

""" Normally, when the game gives you equipment (Gadgets/Items/Weapons), it will set a Primary and Secondary byte.
The Primary byte is what the game uses to determine if you have the equipment. The Secondary byte doesn't seem to
be used for anything. For the randomizer, the Primary byte will continue to be used to indicate whether the
equipment is collected but the Secondary byte will be repurposed to keep track of whether the location has been
visited. Here, the give equipment function for each planet is modified to only set the Secondary byte to mark that
the locations has been visited and prevent giving normal equipment. """
for address in addresses.GIVE_EQUIPMENT_FUNCS:
patch.write_token(APTokenTypes.WRITE, address + 0x14, bytes([0x01, 0x00, 0x03, 0x24])) # addiu v1,zero,0x1
patch.write_token(APTokenTypes.WRITE, address + 0x18, bytes([0x21, 0x38, 0x82, 0x00])) # addu a3,a0,v0
patch.write_token(APTokenTypes.WRITE, address + 0x1C, bytes([0x38, 0x00, 0xE3, 0xA0])) # sb v1,0x38(a3)
patch.write_token(APTokenTypes.WRITE, address + 0x20, NOP * 43)

for address in addresses.VENDOR_CONFIRM_MENU_FUNCS:
# Prevent auto-equipping anything purchased at the vendor.
patch.write_token(APTokenTypes.WRITE, address + 0x740, NOP)

# Prevent vendor from overwriting slots after purchases.
patch.write_token(APTokenTypes.WRITE, address + 0x60C, NOP)
patch.write_token(APTokenTypes.WRITE, address + 0x790, NOP)

""" Prevent any inference of an upgraded weapon type, always take the base Lv1 weapon so that we know which
weapon to edit temporarily into a fake buyable item. """
for address in addresses.VENDOR_LOOP_FUNCS:
Expand Down Expand Up @@ -333,6 +313,26 @@ def generate_patch(world: "Rac2World", patch: Rac2ProcedurePatch, instruction=No
patch.write_token(APTokenTypes.WRITE, address + 0x4, NOP * 3)
patch.write_token(APTokenTypes.WRITE, address + 0x14, NOP * 21)

""" Normally, when the game gives you equipment (Gadgets/Items/Weapons), it will set a Primary and Secondary byte.
The Primary byte is what the game uses to determine if you have the equipment. The Secondary byte doesn't seem to
be used for anything. For the randomizer, the Primary byte will continue to be used to indicate whether the
equipment is collected but the Secondary byte will be repurposed to keep track of whether the location has been
visited. Here, the give equipment function for each planet is modified to only set the Secondary byte to mark that
the locations has been visited and prevent giving normal equipment. """
for address in addresses.GIVE_EQUIPMENT_FUNCS:
patch.write_token(APTokenTypes.WRITE, address + 0x14, bytes([0x01, 0x00, 0x03, 0x24])) # addiu v1,zero,0x1
patch.write_token(APTokenTypes.WRITE, address + 0x18, bytes([0x21, 0x38, 0x82, 0x00])) # addu a3,a0,v0
patch.write_token(APTokenTypes.WRITE, address + 0x1C, bytes([0x38, 0x00, 0xE3, 0xA0])) # sb v1,0x38(a3)
patch.write_token(APTokenTypes.WRITE, address + 0x20, NOP * 43)

for address in addresses.VENDOR_CONFIRM_MENU_FUNCS:
# Prevent auto-equipping anything purchased at the vendor.
patch.write_token(APTokenTypes.WRITE, address + 0x740, NOP)

# Prevent vendor from overwriting slots after purchases.
patch.write_token(APTokenTypes.WRITE, address + 0x60C, NOP)
patch.write_token(APTokenTypes.WRITE, address + 0x790, NOP)

"""---------
Oozla
---------"""
Expand Down
10 changes: 10 additions & 0 deletions ItemPool.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,20 @@ def create_equipment(world: "Rac2World") -> list["Item"]:
# Gadgetron Vendor
if world.options.randomize_gadgetron_vendor:
equipment_to_add += [i for i in Items.GADGETRON_VENDOR_WEAPONS if i not in world.starting_weapons]
else:
mapping: list[tuple[Locations.LocationData, Items.WeaponData]] = zip(Locations.GADGETRON_VENDOR_LOCATIONS, Items.GADGETRON_VENDOR_WEAPONS)
for loc, item in mapping:
location = world.multiworld.get_location(loc.name, world.player)
location.place_locked_item(world.create_item(item.name))

# Megacorp Vendor
if world.options.randomize_megacorp_vendor:
equipment_to_add += [i for i in Items.MEGACORP_VENDOR_WEAPONS if i not in world.starting_weapons]
else:
mapping: list[tuple[Locations.LocationData, Items.WeaponData]] = zip(Locations.MEGACORP_VENDOR_LOCATIONS, Items.MEGACORP_VENDOR_WEAPONS)
for loc, item in mapping:
location = world.multiworld.get_location(loc.name, world.player)
location.place_locked_item(world.create_item(item.name))

# Misc Weapons
equipment_to_add += [Items.SHEEPINATOR]
Expand Down
7 changes: 6 additions & 1 deletion Rac2Interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,9 @@ def change_mode(self, ctx: "Rac2Context", new_mode: Mode):
return

if new_mode is Vendor.Mode.AMMO:
if not ctx.slot_data["randomize_megacorp_vendor"]:
if self.mode is self.Mode.MEGACORP and not ctx.slot_data["randomize_megacorp_vendor"]:
return
if self.mode is self.Mode.GADGETRON and not ctx.slot_data["randomize_gadgetron_vendor"]:
return

current_inventory: dict[str, int] = ctx.game_interface.get_current_inventory()
Expand Down Expand Up @@ -337,6 +339,9 @@ def change_mode(self, ctx: "Rac2Context", new_mode: Mode):
slots.append(Vendor.VendorSlot(weapons[i].offset, False, 0x47))

self.interface.pcsx2_interface.write_int16(equipment_table + weapons[i].offset * 0xE0 + 0x3C, Items.get_icon_id(item))
if not slots:
self.change_mode(ctx, self.Mode.AMMO)
return
self.populate_slots(slots)
elif new_mode is Vendor.Mode.CLOSED:
# reset weapon data back to default when not in vendor
Expand Down
20 changes: 0 additions & 20 deletions data/Locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,123 +209,103 @@ class LocationData(NamedTuple):
OOZLA_VENDOR_WEAPON_1 = LocationData(
300, "Oozla: Megacorp Vendor - New Weapon 1",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.CHOPPER.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
OOZLA_VENDOR_WEAPON_2 = LocationData(
301, "Oozla: Megacorp Vendor - New Weapon 2",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.BLITZ_GUN.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
ENDAKO_VENDOR_WEAPON_1 = LocationData(
302, "Endako: Megacorp Vendor - New Weapon 1",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.PULSE_RIFLE.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
ENDAKO_VENDOR_WEAPON_2 = LocationData(
303, "Endako: Megacorp Vendor - New Weapon 2",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.MINITURRET_GLOVE.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
BARLOW_VENDOR_WEAPON = LocationData(
304, "Barlow: Megacorp Vendor - New Weapon",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.SEEKER_GUN.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
NOTAK_VENDOR_WEAPON = LocationData(
305, "Notak: Megacorp Vendor - New Weapon",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.SYNTHENOID.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
TABORA_VENDOR_WEAPON_1 = LocationData(
306, "Tabora: Megacorp Vendor - New Weapon 1",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.LAVA_GUN.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
TABORA_VENDOR_WEAPON_2 = LocationData(
307, "Tabora: Megacorp Vendor - New Weapon 2",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.BOUNCER.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
DOBBO_VENDOR_WEAPON = LocationData(
308, "Dobbo: Megacorp Vendor - New Weapon",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.MINIROCKET_TUBE.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
JOBA_VENDOR_WEAPON_1 = LocationData(
309, "Joba: Megacorp Vendor - New Weapon 1",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.SPIDERBOT_GLOVE.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
JOBA_VENDOR_WEAPON_2 = LocationData(
310, "Joba: Megacorp Vendor - New Weapon 2",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.PLASMA_COIL.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
TODANO_VENDOR_WEAPON = LocationData(
311, "Todano: Megacorp Vendor - New Weapon",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.HOVERBOMB_GUN.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
ARANOS_VENDOR_WEAPON_1 = LocationData(
312, "Aranos Prison: Megacorp Vendor - New Weapon 1",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.SHIELD_CHARGER.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)
ARANOS_VENDOR_WEAPON_2 = LocationData(
313, "Aranos Prison: Megacorp Vendor - New Weapon 2",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.ZODIAC.offset,
enable_if=lambda options_dict: options_dict["randomize_megacorp_vendor"],
is_vendor=True
)

""" Gadgetron Vendor """
BARLOW_GADGETRON_1 = LocationData(
314, "Barlow: Gadgetron Vendor - Weapon 1",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.BOMB_GLOVE.offset,
enable_if=lambda options_dict: options_dict["randomize_gadgetron_vendor"],
is_vendor=True
)
BARLOW_GADGETRON_2 = LocationData(
315, "Barlow: Gadgetron Vendor - Weapon 2",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.VISIBOMB_GUN.offset,
enable_if=lambda options_dict: options_dict["randomize_gadgetron_vendor"],
is_vendor=True
)
BARLOW_GADGETRON_3 = LocationData(
316, "Barlow: Gadgetron Vendor - Weapon 3",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.TESLA_CLAW.offset,
enable_if=lambda options_dict: options_dict["randomize_gadgetron_vendor"],
is_vendor=True
)
BARLOW_GADGETRON_4 = LocationData(
317, "Barlow: Gadgetron Vendor - Weapon 4",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.DECOY_GLOVE.offset,
enable_if=lambda options_dict: options_dict["randomize_gadgetron_vendor"],
is_vendor=True
)
BARLOW_GADGETRON_5 = LocationData(
318, "Barlow: Gadgetron Vendor - Weapon 5",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.RYNO_II.offset,
enable_if=lambda options_dict: options_dict["randomize_gadgetron_vendor"],
is_vendor=True
)
BARLOW_GADGETRON_6 = LocationData(
319, "Barlow: Gadgetron Vendor - Weapon 6",
checked_flag_address=lambda ram: ram.secondary_inventory + Items.WALLOPER.offset,
enable_if=lambda options_dict: options_dict["randomize_gadgetron_vendor"],
is_vendor=True
)

Expand Down