Files
Jonathan Tinney 7971961166
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
add schedule I, sonic 1/frontiers/heroes, spirit island
2026-04-02 23:46:36 -07:00

502 lines
16 KiB
Python

"""All code associated with model swaps."""
import random
import js
from randomizer.Enums.Models import Model, Sprite
from randomizer.Enums.Maps import Maps
from randomizer.Enums.Settings import KongModels, RandomModels
from randomizer.Settings import Settings
from randomizer.Patching.Patcher import ROM
from randomizer.Patching.Library.Generic import applyCharacterSpawnerChanges, SpawnerChange
turtle_models = [
Model.Diddy, # Diddy
Model.DK, # DK
Model.Lanky, # Lanky
Model.Tiny, # Tiny
Model.Chunky, # Regular Chunky
Model.ChunkyDisco, # Disco Chunky
Model.Cranky, # Cranky
Model.Funky, # Funky
Model.Candy, # Candy
Model.Seal, # Seal
Model.Enguarde, # Enguarde
Model.BeaverBlue_LowPoly, # Beaver
Model.Squawks_28, # Squawks
Model.KlaptrapGreen, # Klaptrap Green
Model.KlaptrapPurple, # Klaptrap Purple
Model.KlaptrapRed, # Klaptrap Red
Model.KlaptrapTeeth, # Klaptrap Teeth
Model.SirDomino, # Sir Domino
Model.MrDice_41, # Mr Dice
Model.Beetle, # Beetle
Model.NintendoLogo, # N64 Logo
Model.MechanicalFish, # Mech Fish
Model.ToyCar, # Toy Car
Model.BananaFairy, # Fairy
Model.Shuri, # Starfish
Model.Gimpfish, # Gimpfish
Model.Spider, # Spider
Model.Rabbit, # Rabbit
Model.KRoolCutscene, # K Rool
Model.SkeletonHead, # Skeleton Head
Model.Vulture_76, # Vulture
Model.Vulture_77, # Racing Vulture
Model.Tomato, # Tomato
Model.Fly, # Fly
Model.SpotlightFish, # Spotlight Fish
Model.Puftup, # Pufftup
Model.CuckooBird, # Cuckoo Bird
Model.IceTomato, # Ice Tomato
Model.Boombox, # Boombox
Model.KRoolFight, # K Rool (Boxing)
Model.Microphone, # Microbuffer
Model.DeskKRool, # K Rool's Desk
Model.Bell, # Bell
Model.BonusBarrel, # Bonus Barrel
Model.HunkyChunkyBarrel, # HC Barrel
Model.MiniMonkeyBarrel, # MM Barrel
Model.TNTBarrel, # TNT Barrel
Model.Rocketbarrel, # RB Barrel
Model.StrongKongBarrel, # SK Barrel
Model.OrangstandSprintBarrel, # OSS Barrel
Model.BBBSlot_143, # BBB Slot
Model.PlayerCar, # Tiny Car
Model.Boulder, # Boulder
Model.Boat_158, # Boat
Model.Potion, # Potion
Model.ArmyDilloMissle, # AD Missile
Model.TagBarrel, # Tag Barrel
Model.QuestionMark, # Question Mark
Model.Krusha, # Krusha
Model.BananaPeel, # Banana Peel
Model.Butterfly, # Butterfly
Model.FunkyGun, # Funky's Gun
]
panic_models = [
Model.Diddy, # Diddy
Model.DK, # DK
Model.Lanky, # Lanky
Model.Tiny, # Tiny
Model.Chunky, # Regular Chunky
Model.ChunkyDisco, # Disco Chunky
Model.Cranky, # Cranky
Model.Funky, # Funky
Model.Candy, # Candy
Model.Seal, # Seal
Model.Enguarde, # Enguarde
Model.BeaverBlue_LowPoly, # Beaver
Model.Squawks_28, # Squawks
Model.KlaptrapGreen, # Klaptrap Green
Model.KlaptrapPurple, # Klaptrap Purple
Model.KlaptrapRed, # Klaptrap Red
Model.MadJack, # Mad Jack
Model.Troff, # Troff
Model.SirDomino, # Sir Domino
Model.MrDice_41, # Mr Dice
Model.RoboKremling, # Robo Kremling
Model.Scoff, # Scoff
Model.Beetle, # Beetle
Model.NintendoLogo, # N64 Logo
Model.MechanicalFish, # Mech Fish
Model.ToyCar, # Toy Car
Model.Klump, # Klump
Model.Dogadon, # Dogadon
Model.BananaFairy, # Fairy
Model.Guard, # Guard
Model.Shuri, # Starfish
Model.Gimpfish, # Gimpfish
Model.KLumsy, # K Lumsy
Model.Spider, # Spider
Model.Rabbit, # Rabbit
# Model.Beanstalk, # Beanstalk
Model.KRoolCutscene, # K Rool
Model.SkeletonHead, # Skeleton Head
Model.Vulture_76, # Vulture
Model.Vulture_77, # Racing Vulture
Model.Ghost, # Ghost
Model.Fly, # Fly
Model.FlySwatter_83, # Fly Swatter
Model.Owl, # Owl
Model.Book, # Book
Model.SpotlightFish, # Spotlight Fish
Model.Puftup, # Pufftup
Model.Mermaid, # Mermaid
Model.Mushroom, # Mushroom Man
Model.Worm, # Worm
Model.EscapeShip, # Escape Ship
Model.KRoolFight, # K Rool (Boxing)
Model.Microphone, # Microbuffer
Model.BonusBarrel, # Bonus Barrel
Model.HunkyChunkyBarrel, # HC Barrel
Model.MiniMonkeyBarrel, # MM Barrel
Model.TNTBarrel, # TNT Barrel
Model.Rocketbarrel, # RB Barrel
Model.StrongKongBarrel, # SK Barrel
Model.OrangstandSprintBarrel, # OSS Barrel
Model.PlayerCar, # Tiny Car
Model.Boulder, # Boulder
Model.VaseCircle, # Vase
Model.VaseColon, # Vase
Model.VaseTriangle, # Vase
Model.VasePlus, # Vase
Model.ArmyDilloMissle, # AD Missile
Model.TagBarrel, # Tag Barrel
Model.QuestionMark, # Question Mark
Model.Krusha, # Krusha
Model.Light, # Light
Model.BananaPeel, # Banana Peel
Model.FunkyGun, # Funky's Gun
]
bother_models = [
Model.BeaverBlue_LowPoly, # Beaver
Model.Klobber, # Klobber
Model.Kaboom, # Kaboom
Model.KlaptrapGreen, # Green Klap
Model.KlaptrapPurple, # Purple Klap
Model.KlaptrapRed, # Red Klap
Model.KlaptrapTeeth, # Klap Teeth
Model.Krash, # Krash
Model.Troff, # Troff
Model.NintendoLogo, # N64 Logo
Model.MechanicalFish, # Mech Fish
Model.Krossbones, # Krossbones
Model.Rabbit, # Rabbit
Model.SkeletonHead, # Minecart Skeleton Head
Model.Tomato, # Tomato
Model.IceTomato, # Ice Tomato
Model.GoldenBanana_104, # Golden Banana
Model.Microphone, # Microbuffer
Model.Bell, # Bell
Model.Missile, # Missile (Car Race)
Model.Buoy, # Red Buoy
Model.BuoyGreen, # Green Buoy
Model.RarewareLogo, # Rareware Logo
]
piano_models = [
Model.Krash,
Model.RoboKremling,
Model.KoshKremling,
Model.KoshKremlingRed,
Model.Kasplat,
Model.Guard,
Model.Krossbones,
Model.Mermaid,
Model.Mushroom,
Model.GoldenBanana_104,
Model.FlySwatter_83,
Model.Ruler,
]
piano_extreme_model = [
Model.SkeletonHead,
Model.Owl,
Model.Kosha,
# Model.Beanstalk,
]
spotlight_fish_models = [
# Model.Turtle, # Lighting Bug
Model.Seal,
Model.BeaverBlue,
Model.BeaverGold,
Model.Zinger,
Model.Squawks_28,
Model.Klobber,
Model.Kaboom,
Model.KlaptrapGreen,
Model.KlaptrapPurple,
Model.KlaptrapRed,
Model.Krash,
# Model.SirDomino, # Lighting issue
# Model.MrDice_41, # Lighting issue
# Model.Ruler, # Lighting issue
# Model.RoboKremling, # Lighting issue
Model.NintendoLogo,
Model.MechanicalFish,
Model.ToyCar,
Model.Kasplat,
Model.BananaFairy,
Model.Guard,
Model.Gimpfish,
# Model.Shuri, # Lighting issue
Model.Spider,
Model.Rabbit,
Model.KRoolCutscene,
Model.KRoolFight,
# Model.SkeletonHead, # Lighting bug
# Model.Vulture_76, # Lighting bug
# Model.Vulture_77, # Lighting bug
# Model.Bat, # Lighting bug
# Model.Tomato, # Lighting bug
# Model.IceTomato, # Lighting bug
# Model.FlySwatter_83, # Lighting bug
Model.SpotlightFish,
Model.Microphone,
# Model.Rocketbarrel, # Model too big, obstructs view
# Model.StrongKongBarrel, # Model too big, obstructs view
# Model.OrangstandSprintBarrel, # Model too big, obstructs view
# Model.MiniMonkeyBarrel, # Model too big, obstructs view
# Model.HunkyChunkyBarrel, # Model too big, obstructs view
]
candy_cutscene_models = [
Model.Cranky,
# Model.Funky, # Disappears with collision
Model.Candy,
Model.Snide,
Model.Seal,
Model.BeaverBlue,
Model.BeaverGold,
Model.Klobber,
Model.Kaboom,
Model.Krash,
Model.Troff,
Model.Scoff,
Model.RoboKremling,
Model.Beetle,
Model.MrDice_41,
Model.MrDice_56,
Model.BananaFairy,
Model.Rabbit,
Model.KRoolCutscene,
Model.KRoolFight,
Model.Vulture_76,
Model.Vulture_77,
Model.Tomato,
Model.IceTomato,
Model.FlySwatter_83,
Model.Microphone,
Model.StrongKongBarrel,
Model.Rocketbarrel,
Model.OrangstandSprintBarrel,
Model.MiniMonkeyBarrel,
Model.HunkyChunkyBarrel,
Model.RambiCrate,
Model.EnguardeCrate,
Model.Boulder,
Model.SteelKeg,
Model.GoldenBanana_104,
]
funky_cutscene_models = [
Model.Cranky,
Model.Candy,
Model.Funky,
Model.Troff,
Model.Scoff,
Model.Ruler,
Model.RoboKremling,
Model.KRoolCutscene,
Model.KRoolFight,
Model.Microphone,
]
# Not holding gun
funky_cutscene_models_extreme = [
Model.BeaverBlue,
Model.BeaverGold,
Model.Klobber,
Model.Kaboom,
Model.SirDomino,
Model.MechanicalFish,
Model.BananaFairy,
Model.SkeletonHand,
Model.IceTomato,
Model.Tomato,
]
boot_cutscene_models = [
Model.Turtle,
Model.Enguarde,
Model.BeaverBlue,
Model.BeaverGold,
Model.Zinger,
Model.Squawks_28,
Model.KlaptrapGreen,
Model.KlaptrapPurple,
Model.KlaptrapRed,
Model.BananaFairy,
Model.Spider,
Model.Bat,
Model.KRoolGlove,
]
melon_random_sprites = [
Sprite.BouncingMelon,
Sprite.BouncingOrange,
Sprite.Coconut,
Sprite.Peanut,
Sprite.Grape,
Sprite.Feather,
Sprite.Pineapple,
Sprite.CrystalCoconut0,
Sprite.DKCoin,
Sprite.DiddyCoin,
Sprite.LankyCoin,
Sprite.TinyCoin,
Sprite.ChunkyCoin,
Sprite.Fairy,
Sprite.RaceCoin,
]
model_mapping = {
KongModels.default: 0,
KongModels.disco_chunky: 6,
KongModels.krusha: 7,
KongModels.krool_cutscene: 9,
KongModels.krool_fight: 8,
KongModels.cranky: 10,
KongModels.candy: 11,
KongModels.funky: 12,
}
model_texture_sections = {
KongModels.krusha: {
"skin": [0x4738, 0x2E96, 0x3A5E],
"kong": [0x3126, 0x354E, 0x37FE, 0x41E6],
},
KongModels.krool_fight: {
"skin": [
0x61D6,
0x63FE,
0x6786,
0x7DD6,
0x7E8E,
0x7F3E,
0x7FEE,
0x5626,
0x56E6,
0x5A86,
0x5BAE,
0x5D46,
0x5E2E,
0x5FAE,
0x69BE,
0x735E,
0x7C5E,
0x7E4E,
0x7EF6,
0x7FA6,
0x8056,
],
"kong": [0x607E, 0x7446, 0x7D46, 0x80FE],
},
# KongModels.krool_cutscene: {
# "skin": [0x4A6E, 0x4CBE, 0x52AE, 0x55BE, 0x567E, 0x57E6, 0x5946, 0x5AA6, 0x5E06, 0x5EC6, 0x6020, 0x618E, 0x62F6, 0x6946, 0x6A6E, 0x6C5E, 0x6D86, 0x6F76, 0x702E, 0x70DE, 0x718E, 0x72FE, 0x4FBE, 0x51FE, 0x5C26, 0x6476, 0x6826, 0x6B26, 0x6E3E, 0x6FE6, 0x7096, 0x7146, 0x71F6, 0x733E, 0x743E],
# "kong": [],
# }
}
KLAPTRAPS = [Model.KlaptrapGreen, Model.KlaptrapPurple, Model.KlaptrapRed]
def getRandomKlaptrapModel() -> Model:
"""Get random klaptrap model."""
return random.choice(KLAPTRAPS)
def applyCosmeticModelSwaps(settings: Settings, ROM_COPY: ROM):
"""Apply model swaps to the settings dict."""
sav = settings.rom_data
bother_model_index = Model.KlaptrapGreen
panic_fairy_model_index = Model.BananaFairy
panic_klap_model_index = Model.KlaptrapGreen
turtle_model_index = Model.Turtle
sseek_klap_model_index = Model.KlaptrapGreen
fungi_tomato_model_index = Model.Tomato
caves_tomato_model_index = Model.IceTomato
racer_beetle = Model.Beetle
racer_rabbit = Model.Rabbit
piano_burper = Model.KoshKremlingRed
spotlight_fish_model_index = Model.SpotlightFish
candy_model_index = Model.Candy
funky_model_index = Model.Funky
boot_model_index = Model.Boot
melon_sprite = Sprite.BouncingMelon
swap_bitfield = 0
model_inverse_mapping = {}
for model in model_mapping:
val = model_mapping[model]
model_inverse_mapping[val] = model
ROM_COPY.seek(settings.rom_data + 0x1B8)
settings.kong_model_dk = model_inverse_mapping[int.from_bytes(ROM_COPY.readBytes(1), "big")]
settings.kong_model_diddy = model_inverse_mapping[int.from_bytes(ROM_COPY.readBytes(1), "big")]
settings.kong_model_lanky = model_inverse_mapping[int.from_bytes(ROM_COPY.readBytes(1), "big")]
settings.kong_model_tiny = model_inverse_mapping[int.from_bytes(ROM_COPY.readBytes(1), "big")]
settings.kong_model_chunky = model_inverse_mapping[int.from_bytes(ROM_COPY.readBytes(1), "big")]
if settings.override_cosmetics:
model_setting = RandomModels[js.document.getElementById("random_models").value]
else:
model_setting = settings.random_models
if model_setting == RandomModels.random:
bother_model_index = getRandomKlaptrapModel()
elif model_setting == RandomModels.extreme:
bother_model_index = random.choice(bother_models)
racer_beetle = random.choice([Model.Beetle, Model.Rabbit])
racer_rabbit = random.choice([Model.Beetle, Model.Rabbit])
if racer_rabbit == Model.Beetle:
spawner_changes = []
# Fungi
rabbit_race_fungi_change = SpawnerChange(Maps.FungiForest, 2)
rabbit_race_fungi_change.new_scale = 50
rabbit_race_fungi_change.new_speed_0 = 95
rabbit_race_fungi_change.new_speed_1 = 184
spawner_changes.append(rabbit_race_fungi_change)
# Caves
rabbit_caves_change = SpawnerChange(Maps.CavesChunkyIgloo, 1)
rabbit_caves_change.new_scale = 40
spawner_changes.append(rabbit_caves_change)
applyCharacterSpawnerChanges(ROM_COPY, spawner_changes)
if model_setting != RandomModels.off:
panic_fairy_model_index = random.choice(panic_models)
turtle_model_index = random.choice(turtle_models)
panic_klap_model_index = getRandomKlaptrapModel()
sseek_klap_model_index = getRandomKlaptrapModel()
fungi_tomato_model_index = random.choice([Model.Tomato, Model.IceTomato])
caves_tomato_model_index = random.choice([Model.Tomato, Model.IceTomato])
referenced_piano_models = piano_models.copy()
referenced_funky_models = funky_cutscene_models.copy()
if model_setting == RandomModels.extreme:
referenced_piano_models.extend(piano_extreme_model)
spotlight_fish_model_index = random.choice(spotlight_fish_models)
referenced_funky_models.extend(funky_cutscene_models_extreme)
boot_model_index = random.choice(boot_cutscene_models)
piano_burper = random.choice(referenced_piano_models)
candy_model_index = random.choice(candy_cutscene_models)
funky_model_index = random.choice(funky_cutscene_models)
settings.bother_klaptrap_model = bother_model_index
settings.beetle_model = racer_beetle
settings.rabbit_model = racer_rabbit
settings.panic_fairy_model = panic_fairy_model_index
settings.turtle_model = turtle_model_index
settings.panic_klaptrap_model = panic_klap_model_index
settings.seek_klaptrap_model = sseek_klap_model_index
settings.fungi_tomato_model = fungi_tomato_model_index
settings.caves_tomato_model = caves_tomato_model_index
settings.piano_burp_model = piano_burper
settings.spotlight_fish_model = spotlight_fish_model_index
settings.candy_cutscene_model = candy_model_index
settings.funky_cutscene_model = funky_model_index
settings.boot_cutscene_model = boot_model_index
settings.wrinkly_rgb = [255, 255, 255]
# Compute swap bitfield
swap_bitfield |= 0x10 if settings.rabbit_model == Model.Beetle else 0
swap_bitfield |= 0x20 if settings.beetle_model == Model.Rabbit else 0
swap_bitfield |= 0x40 if settings.fungi_tomato_model == Model.IceTomato else 0
swap_bitfield |= 0x80 if settings.caves_tomato_model == Model.Tomato else 0
if settings.misc_cosmetics and settings.override_cosmetics:
melon_sprite = random.choice(melon_random_sprites)
settings.wrinkly_rgb = [random.randint(0, 255) for _ in range(3)]
settings.minigame_melon_sprite = melon_sprite
# Write Models
ROM_COPY.seek(sav + 0x1B5)
ROM_COPY.writeMultipleBytes(settings.panic_fairy_model + 1, 1) # Still needed for end seq fairy swap
ROM_COPY.seek(sav + 0x1E2)
ROM_COPY.write(swap_bitfield)