forked from mirror/Archipelago
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
105 lines
5.0 KiB
Python
105 lines
5.0 KiB
Python
"""Apply Coin Rando changes."""
|
|
|
|
from randomizer.Patching.Library.DataTypes import float_to_hex
|
|
from randomizer.Patching.Library.Assets import getPointerLocation, TableNames
|
|
from randomizer.Patching.Patcher import LocalROM
|
|
|
|
|
|
def randomize_coins(spoiler, ROM_COPY: LocalROM):
|
|
"""Place Coins into ROM."""
|
|
if spoiler.settings.coin_rando:
|
|
for cont_map_id in range(216):
|
|
# Wipe setup and paths of Coin information
|
|
# SETUP
|
|
coin_items = [0x1D, 0x24, 0x23, 0x1C, 0x27] # Has to remain in this order
|
|
setup_table = getPointerLocation(TableNames.Setups, cont_map_id)
|
|
ROM_COPY.seek(setup_table)
|
|
model2_count = int.from_bytes(ROM_COPY.readBytes(4), "big")
|
|
# Model Two Coins
|
|
persisted_m2_data = []
|
|
used_m2_ids = []
|
|
for item in range(model2_count):
|
|
item_start = setup_table + 4 + (item * 0x30)
|
|
ROM_COPY.seek(item_start + 0x28)
|
|
item_type = int.from_bytes(ROM_COPY.readBytes(2), "big")
|
|
if item_type not in coin_items: # Not Coin
|
|
ROM_COPY.seek(item_start + 0x2A)
|
|
used_m2_ids.append(int.from_bytes(ROM_COPY.readBytes(2), "big"))
|
|
ROM_COPY.seek(item_start)
|
|
item_data = []
|
|
for x in range(int(0x30 / 4)):
|
|
item_data.append(int.from_bytes(ROM_COPY.readBytes(4), "big"))
|
|
persisted_m2_data.append(item_data)
|
|
ROM_COPY.seek(setup_table + 4 + (0x30 * model2_count))
|
|
mystery_count = int.from_bytes(ROM_COPY.readBytes(4), "big")
|
|
# Mystery
|
|
persisted_mys_data = []
|
|
for item in range(mystery_count):
|
|
ROM_COPY.seek(setup_table + 4 + (model2_count * 0x30) + 4 + (item * 0x24))
|
|
item_data = []
|
|
for x in range(int(0x24 / 4)):
|
|
item_data.append(int.from_bytes(ROM_COPY.readBytes(4), "big"))
|
|
persisted_mys_data.append(item_data)
|
|
actor_block = setup_table + 4 + (0x30 * model2_count) + 4 + (0x24 * mystery_count)
|
|
ROM_COPY.seek(actor_block)
|
|
actor_count = int.from_bytes(ROM_COPY.readBytes(4), "big")
|
|
# Actors
|
|
persisted_act_data = []
|
|
used_actor_ids = []
|
|
for item in range(actor_count):
|
|
actor_start = actor_block + 4 + (item * 0x38)
|
|
ROM_COPY.seek(actor_start + 0x34)
|
|
used_actor_ids.append(int.from_bytes(ROM_COPY.readBytes(2), "big"))
|
|
ROM_COPY.seek(actor_start)
|
|
item_data = []
|
|
for x in range(int(0x38 / 4)):
|
|
item_data.append(int.from_bytes(ROM_COPY.readBytes(4), "big"))
|
|
persisted_act_data.append(item_data)
|
|
# Place all new coins
|
|
new_id = 0
|
|
for new_coin in spoiler.coin_placements:
|
|
if new_coin["map"] == cont_map_id:
|
|
# Model Two Coins
|
|
for loc in new_coin["locations"]:
|
|
item_data = []
|
|
item_data.extend(
|
|
[
|
|
int(float_to_hex(loc[1]), 16),
|
|
int(float_to_hex(loc[2]), 16),
|
|
int(float_to_hex(loc[3]), 16),
|
|
int(float_to_hex(loc[0]), 16),
|
|
]
|
|
)
|
|
item_data.append(2)
|
|
item_data.append(0x01C7FFFF)
|
|
for x in range(int((0x24 - 0x18) / 4)):
|
|
item_data.append(0)
|
|
item_data.append(0x40400000)
|
|
coin_item_type = coin_items[new_coin["kong"]]
|
|
found_vacant = False
|
|
found_id = 0
|
|
while not found_vacant:
|
|
if new_id not in used_m2_ids:
|
|
used_m2_ids.append(new_id)
|
|
found_id = new_id
|
|
found_vacant = True
|
|
new_id += 1
|
|
item_data.append((coin_item_type << 16) + found_id)
|
|
item_data.append((2 << 16) + 1)
|
|
persisted_m2_data.append(item_data)
|
|
# Recompile Tables
|
|
# SETUP
|
|
ROM_COPY.seek(setup_table)
|
|
ROM_COPY.writeMultipleBytes(len(persisted_m2_data), 4)
|
|
for x in persisted_m2_data:
|
|
for y in x:
|
|
ROM_COPY.writeMultipleBytes(y, 4)
|
|
ROM_COPY.writeMultipleBytes(len(persisted_mys_data), 4)
|
|
for x in persisted_mys_data:
|
|
for y in x:
|
|
ROM_COPY.writeMultipleBytes(y, 4)
|
|
ROM_COPY.writeMultipleBytes(len(persisted_act_data), 4)
|
|
for x in persisted_act_data:
|
|
for y in x:
|
|
ROM_COPY.writeMultipleBytes(y, 4)
|