From 23dc3342a85569c04e3deb3611f4340b99277e27 Mon Sep 17 00:00:00 2001 From: biosp4rk <37962487+biosp4rk@users.noreply.github.com> Date: Wed, 10 Sep 2025 12:50:23 -0700 Subject: [PATCH 1/3] Refactor random palettes and enemies --- src/mars_patcher/common_types.py | 4 + src/mars_patcher/constants/enemies.py | 64 ++++++++ src/mars_patcher/constants/palettes.py | 140 ++++++++++++++++++ src/mars_patcher/mf/constants/enemies.py | 58 -------- src/mars_patcher/mf/constants/palettes.py | 71 --------- src/mars_patcher/mf/constants/sprites.py | 71 +++++++++ src/mars_patcher/random_enemies.py | 4 +- src/mars_patcher/random_palettes.py | 104 +++++++------ src/mars_patcher/zm/constants/game_data.py | 4 + .../zm/constants/reserved_space.py | 2 + src/mars_patcher/zm/constants/sprites.py | 84 +++++++++++ 11 files changed, 430 insertions(+), 176 deletions(-) create mode 100644 src/mars_patcher/constants/enemies.py create mode 100644 src/mars_patcher/constants/palettes.py delete mode 100644 src/mars_patcher/mf/constants/enemies.py create mode 100644 src/mars_patcher/mf/constants/sprites.py create mode 100644 src/mars_patcher/zm/constants/sprites.py diff --git a/src/mars_patcher/common_types.py b/src/mars_patcher/common_types.py index 0a09c67..10122e4 100644 --- a/src/mars_patcher/common_types.py +++ b/src/mars_patcher/common_types.py @@ -2,6 +2,8 @@ import mars_patcher.mf.auto_generated_types as types_mf import mars_patcher.zm.auto_generated_types as types_zm +from mars_patcher.mf.constants.sprites import SpriteIdMF +from mars_patcher.zm.constants.sprites import SpriteIdZM TypeU8: TypeAlias = types_mf.Typeu8 | types_zm.TypeU8 @@ -11,3 +13,5 @@ AreaRoomPair = tuple[AreaId, RoomId] MinimapId: TypeAlias = Annotated[int, "0 <= value < 10"] + +SpriteId: TypeAlias = SpriteIdMF | SpriteIdZM diff --git a/src/mars_patcher/constants/enemies.py b/src/mars_patcher/constants/enemies.py new file mode 100644 index 0000000..cf0678a --- /dev/null +++ b/src/mars_patcher/constants/enemies.py @@ -0,0 +1,64 @@ +from enum import Enum + +from mars_patcher.mf.constants.sprites import SpriteIdMF +from mars_patcher.rom import Game + + +class EnemyType(Enum): + CRAWLING = 1 + GROUND = 2 + CEILING = 3 + GROUND_CEILING = 4 + WALL = 5 + FLYING = 6 + + +ENEMY_TYPES = { + Game.MF: { + SpriteIdMF.HORNOAD: EnemyType.GROUND, + SpriteIdMF.HALZYN: EnemyType.FLYING, + SpriteIdMF.ZEBESIAN_WALL: EnemyType.WALL, + SpriteIdMF.HORNOAD_SPAWNER: EnemyType.GROUND, + SpriteIdMF.MOTO: EnemyType.GROUND, + SpriteIdMF.YAMEBA: EnemyType.FLYING, + SpriteIdMF.ZEELA: EnemyType.CRAWLING, + SpriteIdMF.SKREE_UNUSED: EnemyType.CEILING, + SpriteIdMF.ZOMBIE: EnemyType.GROUND, + SpriteIdMF.GEEMER: EnemyType.CRAWLING, + SpriteIdMF.WAVER: EnemyType.FLYING, + SpriteIdMF.SCISER: EnemyType.CRAWLING, + SpriteIdMF.SIDEHOPPER: EnemyType.GROUND_CEILING, + SpriteIdMF.DESSGEEGA: EnemyType.GROUND_CEILING, + SpriteIdMF.ZORO: EnemyType.CRAWLING, + SpriteIdMF.KIHUNTER_FLYING: EnemyType.FLYING, + SpriteIdMF.KIHUNTER_GROUND: EnemyType.GROUND, + SpriteIdMF.REO: EnemyType.FLYING, + SpriteIdMF.NAMIHE: EnemyType.WALL, + SpriteIdMF.FUNE: EnemyType.WALL, + SpriteIdMF.BLUE_ZORO: EnemyType.CRAWLING, + SpriteIdMF.GERUDA: EnemyType.FLYING, + SpriteIdMF.SKULTERA_LARGE: EnemyType.FLYING, + SpriteIdMF.SKULTERA_SMALL_ONLY: EnemyType.FLYING, + SpriteIdMF.SOVA: EnemyType.CRAWLING, + SpriteIdMF.YARD: EnemyType.CRAWLING, + SpriteIdMF.EVIR: EnemyType.FLYING, + SpriteIdMF.BULL: EnemyType.FLYING, + SpriteIdMF.MEMU: EnemyType.FLYING, + SpriteIdMF.GERUBOSS: EnemyType.CEILING, + SpriteIdMF.CHOOT: EnemyType.GROUND, + SpriteIdMF.ZEBESIAN_GROUND: EnemyType.GROUND, + SpriteIdMF.RIPPER: EnemyType.FLYING, + SpriteIdMF.RED_ZEELA: EnemyType.CRAWLING, + SpriteIdMF.OWTCH: EnemyType.CRAWLING, + SpriteIdMF.GENESIS: EnemyType.GROUND, + SpriteIdMF.PUYO: EnemyType.GROUND, + SpriteIdMF.FAKE_ENERGY_TANK: EnemyType.GROUND, + SpriteIdMF.FAKE_MISSILE_TANK: EnemyType.GROUND, + SpriteIdMF.ZEBESIAN_AQUA: EnemyType.FLYING, + SpriteIdMF.ZEBESIAN_PRE_AQUA: EnemyType.GROUND, + SpriteIdMF.SKULTERA_SMALL: EnemyType.FLYING, + SpriteIdMF.POWAMP: EnemyType.FLYING, + SpriteIdMF.ZOZORO: EnemyType.CRAWLING, + }, + # TODO: Game.ZM +} diff --git a/src/mars_patcher/constants/palettes.py b/src/mars_patcher/constants/palettes.py new file mode 100644 index 0000000..6058adb --- /dev/null +++ b/src/mars_patcher/constants/palettes.py @@ -0,0 +1,140 @@ +from mars_patcher.common_types import SpriteId +from mars_patcher.mf.constants.sprites import SpriteIdMF +from mars_patcher.rom import Game +from mars_patcher.zm.constants.sprites import SpriteIdZM + +EXCLUDED_ENEMIES: dict[Game, set[SpriteId]] = { + Game.MF: { + SpriteIdMF.SAX_ELEVATOR, + SpriteIdMF.AREA_BANNER, + SpriteIdMF.MESSAGE_BANNER, + SpriteIdMF.SAX_TRO_1, + SpriteIdMF.SAX_NOC, + SpriteIdMF.SAX_ARC, + SpriteIdMF.SAX_LAB, + SpriteIdMF.SAX_BOSS, + SpriteIdMF.SAX_MONSTER, + SpriteIdMF.SAX_OMEGA, + SpriteIdMF.SAX_TRO_2, + }, + Game.ZM: { + SpriteIdZM.UNUSED_10, + SpriteIdZM.MESSAGE_BANNER, + }, +} + + +ENEMY_GROUPS: dict[Game, dict[str, list[SpriteId]]] = { + Game.MF: { + "Zebesian": [ + SpriteIdMF.ZEBESIAN_WALL, + SpriteIdMF.ZEBESIAN_GROUND, + SpriteIdMF.GOLD_ZEBESIAN, + SpriteIdMF.ZEBESIAN_AQUA, + SpriteIdMF.ZEBESIAN_PRE_AQUA, + ], + "Zeela": [SpriteIdMF.ZEELA, SpriteIdMF.RED_ZEELA], + "Sciser": [SpriteIdMF.SCISER, SpriteIdMF.GOLD_SCISER], + "BeamCoreX": [ + SpriteIdMF.CHARGE_BEAM_CORE_X, + SpriteIdMF.WIDE_BEAM_CORE_X, + SpriteIdMF.PLASMA_BEAM_CORE_X, + SpriteIdMF.WAVE_BEAM_CORE_X, + ], + "Zoro": [ + SpriteIdMF.ZORO, + SpriteIdMF.BLUE_ZORO, + SpriteIdMF.ZORO_COCOON, + SpriteIdMF.ZORO_HUSK, + ], + "FakeTank": [SpriteIdMF.FAKE_ENERGY_TANK, SpriteIdMF.FAKE_MISSILE_TANK], + }, + Game.ZM: { + "Ripper": [SpriteIdZM.RIPPER_BROWN, SpriteIdZM.RIPPER_PURPLE, SpriteIdZM.RIPPER_II], + "Zeb": [SpriteIdZM.ZEB, SpriteIdZM.ZEB_BLUE], + "Skree": [SpriteIdZM.SKREE_GREEN, SpriteIdZM.SKREE_BLUE], + "ChozoStatue": [ + SpriteIdZM.CHOZO_STATUE_LONG_BEAM_HINT, + SpriteIdZM.LONG_BEAM_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_ICE_BEAM_HINT, + SpriteIdZM.ICE_BEAM_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_WAVE_BEAM_HINT, + SpriteIdZM.WAVE_BEAM_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_BOMB_HINT, + SpriteIdZM.BOMB_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_SPEED_BOOSTER_HINT, + SpriteIdZM.SPEED_BOOSTER_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_HI_JUMP_HINT, + SpriteIdZM.HI_JUMP_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_SCREW_ATTACK_HINT, + SpriteIdZM.SCREW_ATTACK_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_VARIA_SUIT_HINT, + SpriteIdZM.VARIA_SUIT_CHOZO_STATUE, + SpriteIdZM.GRAVITY_SUIT_CHOZO_STATUE, + SpriteIdZM.SPACE_JUMP_CHOZO_STATUE, + SpriteIdZM.PLASMA_BEAM_CHOZO_STATUE, + ], + "Viola": [SpriteIdZM.MULTIVIOLA, SpriteIdZM.VIOLA_BLUE, SpriteIdZM.VIOLA_ORANGE], + "GerutaTangleVine": [ + SpriteIdZM.GERUTA_RED, + SpriteIdZM.GERUTA_GREEN, + SpriteIdZM.TANGLE_VINE_RED_GERUTA, + SpriteIdZM.TANGLE_VINE_GERUTA, + SpriteIdZM.TANGLE_VINE_LARVA_RIGHT, + SpriteIdZM.TANGLE_VINE_LARVA_LEFT, + ], + "Reo": [SpriteIdZM.REO_GREEN_WINGS, SpriteIdZM.REO_PURPLE_WINGS], + "Imago": [ + SpriteIdZM.IMAGO_LARVA_RIGHT, + SpriteIdZM.IMAGO_COCOON, + SpriteIdZM.IMAGO_COCOON_AFTER_FIGHT, + SpriteIdZM.IMAGO_LARVA_RIGHT_SIDE, + SpriteIdZM.IMAGO, + SpriteIdZM.IMAGO_LARVA_LEFT, + ], + "SpacePirate": [ + SpriteIdZM.SPACE_PIRATE, + SpriteIdZM.SPACE_PIRATE_WAITING_1, + SpriteIdZM.SPACE_PIRATE_WAITING_2, + SpriteIdZM.SPACE_PIRATE_WAITING_3, + SpriteIdZM.SPACE_PIRATE_2, + SpriteIdZM.SPACE_PIRATE_CARRYING_POWER_BOMB, + SpriteIdZM.BLACK_SPACE_PIRATE, + SpriteIdZM.ESCAPE_SHIP_SPACE_PIRATE, + ], + "Gamet": [ + SpriteIdZM.GAMET_BLUE_SINGLE, + SpriteIdZM.GAMET_RED_SINGLE, + SpriteIdZM.GAMET_BLUE_LEADER, + SpriteIdZM.GAMET_BLUE_FOLLOWER, + ], + "Zebbo": [ + SpriteIdZM.ZEBBO_GREEN, + SpriteIdZM.ZEBBO_YELLOW, + SpriteIdZM.ZEBBO_GREEN_LEADER, + SpriteIdZM.ZEBBO_GREEN_FOLLOWER, + ], + "Rinka": [ + SpriteIdZM.RINKA_ORANGE, + SpriteIdZM.RINKA_MOTHER_BRAIN, + SpriteIdZM.RINKA_GREEN, + SpriteIdZM.RINKA_MOTHER_BRAIN_C9, + SpriteIdZM.RINKA_MOTHER_BRAIN_CA, + SpriteIdZM.RINKA_MOTHER_BRAIN_CB, + SpriteIdZM.RINKA_MOTHER_BRAIN_CC, + SpriteIdZM.RINKA_MOTHER_BRAIN_CD, + ], + "Geega": [ + SpriteIdZM.GEEGA, + SpriteIdZM.GEEGA_WHITE, + SpriteIdZM.GEEGA_LEADER, + SpriteIdZM.GEEGA_FOLLOWER, + ], + "ElevatorStatue": [SpriteIdZM.KRAID_ELEVATOR_STATUE, SpriteIdZM.RIDLEY_ELEVATOR_STATUE], + "UnknownItemBlocks": [ + SpriteIdZM.PLASMA_BEAM_BLOCK, + SpriteIdZM.GRAVITY_SUIT_BLOCK, + SpriteIdZM.SPACE_JUMP_BLOCK, + ], + }, +} diff --git a/src/mars_patcher/mf/constants/enemies.py b/src/mars_patcher/mf/constants/enemies.py deleted file mode 100644 index a087f85..0000000 --- a/src/mars_patcher/mf/constants/enemies.py +++ /dev/null @@ -1,58 +0,0 @@ -from enum import Enum - - -class EnemyType(Enum): - CRAWLING = 1 - GROUND = 2 - CEILING = 3 - GROUND_CEILING = 4 - WALL = 5 - FLYING = 6 - - -ENEMY_TYPES = { - 0x12: ("Hornoad", EnemyType.GROUND), - 0x13: ("Halzyn", EnemyType.FLYING), - 0x14: ("Zebesian (wall)", EnemyType.WALL), - 0x15: ("Hornoad spawner", EnemyType.GROUND), - 0x18: ("Moto", EnemyType.GROUND), - 0x1B: ("Yameba", EnemyType.FLYING), - 0x31: ("Zeela", EnemyType.CRAWLING), - 0x33: ("Skree (unused)", EnemyType.CEILING), - 0x37: ("Zombie", EnemyType.GROUND), - 0x39: ("Geemer", EnemyType.CRAWLING), - 0x3B: ("Waver", EnemyType.FLYING), - 0x3C: ("Sciser", EnemyType.CRAWLING), - 0x3D: ("Sidehopper", EnemyType.GROUND_CEILING), - 0x3E: ("Dessgeega", EnemyType.GROUND_CEILING), - 0x5A: ("Zoro", EnemyType.CRAWLING), - 0x5B: ("Kihunter (flying)", EnemyType.FLYING), - 0x5C: ("Kihunter (ground)", EnemyType.GROUND), - 0x5E: ("Reo", EnemyType.FLYING), - 0x60: ("Namihe", EnemyType.WALL), - 0x61: ("Fune", EnemyType.WALL), - 0x63: ("Blue zoro", EnemyType.CRAWLING), - 0x64: ("Geruda", EnemyType.FLYING), - 0x6A: ("Skultera (large)", EnemyType.FLYING), - 0x6B: ("Skultera (small, cannot become large)", EnemyType.FLYING), - 0x6C: ("Sova", EnemyType.CRAWLING), - 0x6D: ("Yard", EnemyType.CRAWLING), - 0x6E: ("Evir", EnemyType.FLYING), - 0x6F: ("Bull", EnemyType.FLYING), - 0x70: ("Memu", EnemyType.FLYING), - 0x71: ("Geruboss", EnemyType.CEILING), - 0x72: ("Choot", EnemyType.GROUND), - 0x73: ("Zebesian (ground)", EnemyType.GROUND), - 0x88: ("Ripper", EnemyType.FLYING), - 0xA3: ("Red Zeela", EnemyType.CRAWLING), - 0xA4: ("Owtch", EnemyType.CRAWLING), - 0xA8: ("Genesis", EnemyType.GROUND), - 0xA9: ("Puyo", EnemyType.GROUND), - 0xAD: ("Fake energy tank", EnemyType.GROUND), - 0xAE: ("Fake missile tank", EnemyType.GROUND), - 0xB3: ("Zebesian (aqua)", EnemyType.FLYING), - 0xB4: ("Zebesian (pre-aqua)", EnemyType.GROUND), - 0xB5: ("Skultera (small)", EnemyType.FLYING), - 0xBD: ("Powamp", EnemyType.FLYING), - 0xBE: ("Zozoro", EnemyType.CRAWLING), -} diff --git a/src/mars_patcher/mf/constants/palettes.py b/src/mars_patcher/mf/constants/palettes.py index 0dd5591..83eb3ba 100644 --- a/src/mars_patcher/mf/constants/palettes.py +++ b/src/mars_patcher/mf/constants/palettes.py @@ -1,5 +1,3 @@ -from mars_patcher.rom import Game - MF_TILESET_ALT_PAL_ROWS = { 0x46F134: 0xD, # 08 0x4CCCC0: 0xD, # 09, 40 @@ -71,75 +69,6 @@ } -EXCLUDED_ENEMIES = { - Game.MF: { - 0x11, # SA-X (elevator) - 0x1D, # Area banner - 0x21, # Message box - 0x8C, # SA-X (TRO 1) - 0x8D, # SA-X (NOC) - 0xA0, # SA-X (ARC) - 0xBC, # SA-X (lab) - 0xC0, # SA-X (boss) - 0xC1, # SA-X monster - 0xC9, # SA-X (Omega cutscene) - 0xCD, # SA-X (TRO 2) - }, - Game.ZM: { - 0x10, # Unused - 0x11, # Item banner - 0x8A, # Crocomire - }, -} - -ENEMY_GROUPS = { - Game.MF: { - "Zebesian": [0x14, 0x73, 0xA2, 0xB3, 0xB4], - "Zeela": [0x31, 0xA3], - "Sciser": [0x3C, 0x8B], - "BeamCoreX": [0x56, 0x57, 0x58, 0x59], - "Zoro": [0x5A, 0x63, 0x89, 0x8A], - "FakeTank": [0xAD, 0xAE], - }, - Game.ZM: { - "Ripper": [0x16, 0x17, 0x71], - "Zeb": [0x18, 0x19], - "Skree": [0x1F, 0x20], - "ChozoStatue": [ - 0x22, - 0x23, - 0x24, - 0x25, - 0x26, - 0x27, - 0x28, - 0x29, - 0x2A, - 0x2B, - 0x2C, - 0x2D, - 0x2E, - 0x2F, - 0x30, - 0x31, - 0x58, - 0x59, - 0x94, - ], - "Viola": [0x34, 0x68, 0x69], - "GerutaTangleVine": [0x36, 0x37, 0xB7, 0xB8, 0xB9, 0xBA], - "Reo": [0x3F, 0x40], - "Imago": [0x4D, 0x4F, 0x70, 0x7F, 0x86, 0x8B], - "SpacePirate": [0x51, 0x52, 0x53, 0x54, 0x55, 0xB6, 0xC6, 0xC7], - "Gamet": [0x56, 0x57, 0x9D, 0x9E], - "Zebbo": [0x5B, 0x5C, 0xA1, 0xA2], - "Rinka": [0x66, 0x7C, 0xA5, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD], - "Geega": [0x7A, 0x7B, 0x9F, 0xA0], - "ElevatorStatue": [0x95, 0x96], - "UnknownItemBlocks": [0xAA, 0xAB, 0xAC], - }, -} - NETTORI_EXTRA_PALS = [ (0x36A480, 1), # Medium health palette (0x36A4A0, 1), # Low health palette diff --git a/src/mars_patcher/mf/constants/sprites.py b/src/mars_patcher/mf/constants/sprites.py new file mode 100644 index 0000000..f8c6cdd --- /dev/null +++ b/src/mars_patcher/mf/constants/sprites.py @@ -0,0 +1,71 @@ +from enum import IntEnum + + +class SpriteIdMF(IntEnum): + SAX_ELEVATOR = 0x11 + HORNOAD = 0x12 + HALZYN = 0x13 + ZEBESIAN_WALL = 0x14 + HORNOAD_SPAWNER = 0x15 + MOTO = 0x18 + YAMEBA = 0x1B + AREA_BANNER = 0x1D + MESSAGE_BANNER = 0x21 + SAMUS_EATER_BUD = 0x26 + SAMUS_EATER = 0x27 + ZEELA = 0x31 + SKREE_UNUSED = 0x33 + ZOMBIE = 0x37 + GEEMER = 0x39 + WAVER = 0x3B + SCISER = 0x3C + SIDEHOPPER = 0x3D + DESSGEEGA = 0x3E + ICE_BEAM_ABILITY = 0x4D + NETTORI = 0x54 + CHARGE_BEAM_CORE_X = 0x56 + WIDE_BEAM_CORE_X = 0x57 + PLASMA_BEAM_CORE_X = 0x58 + WAVE_BEAM_CORE_X = 0x59 + ZORO = 0x5A + KIHUNTER_FLYING = 0x5B + KIHUNTER_GROUND = 0x5C + REO = 0x5E + NAMIHE = 0x60 + FUNE = 0x61 + BLUE_ZORO = 0x63 + GERUDA = 0x64 + SKULTERA_LARGE = 0x6A + SKULTERA_SMALL_ONLY = 0x6B + SOVA = 0x6C + YARD = 0x6D + EVIR = 0x6E + BULL = 0x6F + MEMU = 0x70 + GERUBOSS = 0x71 + CHOOT = 0x72 + ZEBESIAN_GROUND = 0x73 + RIPPER = 0x88 + ZORO_COCOON = 0x89 + ZORO_HUSK = 0x8A + GOLD_SCISER = 0x8B + SAX_TRO_1 = 0x8C + SAX_NOC = 0x8D + SAX_ARC = 0xA0 + GOLD_ZEBESIAN = 0xA2 + RED_ZEELA = 0xA3 + OWTCH = 0xA4 + GENESIS = 0xA8 + PUYO = 0xA9 + FAKE_ENERGY_TANK = 0xAD + FAKE_MISSILE_TANK = 0xAE + ZEBESIAN_AQUA = 0xB3 + ZEBESIAN_PRE_AQUA = 0xB4 + SKULTERA_SMALL = 0xB5 + SAX_LAB = 0xBC + POWAMP = 0xBD + ZOZORO = 0xBE + SAX_BOSS = 0xC0 + SAX_MONSTER = 0xC1 + SAX_OMEGA = 0xC9 + SAX_TRO_2 = 0xCD diff --git a/src/mars_patcher/random_enemies.py b/src/mars_patcher/random_enemies.py index d8842d1..2e24c57 100644 --- a/src/mars_patcher/random_enemies.py +++ b/src/mars_patcher/random_enemies.py @@ -1,14 +1,14 @@ import random +from mars_patcher.constants.enemies import ENEMY_TYPES, EnemyType from mars_patcher.constants.game_data import spriteset_count, spriteset_ptrs -from mars_patcher.mf.constants.enemies import ENEMY_TYPES, EnemyType from mars_patcher.mf.constants.game_data import sprite_vram_sizes from mars_patcher.rom import Rom def randomize_enemies(rom: Rom) -> None: # Setup enemy types dictionary - enemy_types = {k: v[1] for k, v in ENEMY_TYPES.items()} + enemy_types = {k.value: v for k, v in ENEMY_TYPES[rom.game].items()} # Get graphics info for each enemy size_addr = sprite_vram_sizes(rom) diff --git a/src/mars_patcher/random_palettes.py b/src/mars_patcher/random_palettes.py index df40020..d084ae6 100644 --- a/src/mars_patcher/random_palettes.py +++ b/src/mars_patcher/random_palettes.py @@ -1,7 +1,11 @@ import random from enum import Enum +from typing import TypeAlias + +from typing_extensions import Self import mars_patcher.constants.game_data as gd +from mars_patcher.constants.palettes import ENEMY_GROUPS, EXCLUDED_ENEMIES from mars_patcher.mf.auto_generated_types import ( MarsschemamfPalettes, MarsschemamfPalettesColorspace, @@ -9,14 +13,17 @@ ) from mars_patcher.mf.constants.game_data import sax_palettes, sprite_vram_sizes from mars_patcher.mf.constants.palettes import ( - ENEMY_GROUPS, - EXCLUDED_ENEMIES, MF_TILESET_ALT_PAL_ROWS, NETTORI_EXTRA_PALS, TILESET_ANIM_PALS, ) +from mars_patcher.mf.constants.sprites import SpriteIdMF from mars_patcher.palette import ColorChange, Palette, SineWave from mars_patcher.rom import Game, Rom +from mars_patcher.zm.constants.game_data import statues_cutscene_palette_addr +from mars_patcher.zm.constants.sprites import SpriteIdZM + +HueRange: TypeAlias = tuple[int, int] class PaletteType(Enum): @@ -37,7 +44,7 @@ class PaletteSettings: def __init__( self, seed: int, - pal_types: dict[PaletteType, tuple[int, int]], # TODO: change this tuple(int, int) + pal_types: dict[PaletteType, HueRange], color_space: MarsschemamfPalettesColorspace, symmetric: bool, extra_variation: bool, @@ -49,7 +56,7 @@ def __init__( self.extra_variation = extra_variation @classmethod - def from_json(cls, data: MarsschemamfPalettes) -> "PaletteSettings": + def from_json(cls, data: MarsschemamfPalettes) -> Self: seed = data.get("Seed", random.randint(0, 2**31 - 1)) random.seed(seed) pal_types = {} @@ -63,7 +70,7 @@ def from_json(cls, data: MarsschemamfPalettes) -> "PaletteSettings": return cls(seed, pal_types, color_space, symmetric, True) @classmethod - def get_hue_range(cls, data: MarsschemamfPalettesRandomize) -> tuple[int, int]: + def get_hue_range(cls, data: MarsschemamfPalettesRandomize) -> HueRange: hue_min = data.get("HueMin") hue_max = data.get("HueMax") if hue_min is None or hue_max is None: @@ -104,15 +111,16 @@ def change_palette_oklab( ) -> None: pal.change_colors_oklab(change, excluded_rows) - def generate_palette_change(self, hue_range: tuple[int, int]) -> ColorChange: + def generate_palette_change(self, hue_range: HueRange) -> ColorChange: """Generates a random color change. hue_range determines how far each color's hue will be initially rotated. Individual colors can be additionally rotated using the values of a random sine wave.""" - hue_shift = random.randint(hue_range[0], hue_range[1]) + hue_min, hue_max = hue_range + hue_shift = random.randint(hue_min, hue_max) if self.settings.symmetric and random.choice([True, False]): hue_shift = 360 - hue_shift if self.settings.extra_variation: - hue_var_range = min(1.0, (hue_range[1] - hue_range[0]) / 180) + hue_var_range = min(1.0, (hue_max - hue_min) / 180) hue_var = SineWave.generate(hue_var_range) else: hue_var = None @@ -143,17 +151,17 @@ def change_palettes(self, pals: list[tuple[int, int]], change: ColorChange) -> N pal.write(self.rom, addr) self.randomized_pals.add(addr) - def randomize_samus(self, hue_range: tuple[int, int]) -> None: + def randomize_samus(self, hue_range: HueRange) -> None: change = self.generate_palette_change(hue_range) self.change_palettes(gd.samus_palettes(self.rom), change) self.change_palettes(gd.helmet_cursor_palettes(self.rom), change) self.change_palettes(sax_palettes(self.rom), change) - def randomize_beams(self, hue_range: tuple[int, int]) -> None: + def randomize_beams(self, hue_range: HueRange) -> None: change = self.generate_palette_change(hue_range) self.change_palettes(gd.beam_palettes(self.rom), change) - def randomize_tilesets(self, hue_range: tuple[int, int]) -> None: + def randomize_tilesets(self, hue_range: HueRange) -> None: rom = self.rom ts_addr = gd.tileset_entries(rom) ts_count = gd.tileset_count(rom) @@ -202,9 +210,9 @@ def randomize_anim_palette(self, anim_pal_id: int, change: ColorChange) -> None: pal.write(rom, pal_addr) self.randomized_pals.add(pal_addr) - def randomize_enemies(self, hue_range: tuple[int, int]) -> None: + def randomize_enemies(self, hue_range: HueRange) -> None: rom = self.rom - excluded = EXCLUDED_ENEMIES[rom.game] + excluded = {en_id.value for en_id in EXCLUDED_ENEMIES[rom.game]} sp_count = gd.sprite_count(rom) to_randomize = set(range(0x10, sp_count)) to_randomize -= excluded @@ -219,9 +227,9 @@ def randomize_enemies(self, hue_range: tuple[int, int]) -> None: to_randomize.remove(sprite_id) # Go through remaining sprites - for sprite_id in to_randomize: + for sp_id in to_randomize: change = self.generate_palette_change(hue_range) - self.randomize_enemy(sprite_id, change) + self.randomize_enemy(sp_id, change) def randomize_enemy(self, sprite_id: int, change: ColorChange) -> None: # Get palette address and row count @@ -229,10 +237,12 @@ def randomize_enemy(self, sprite_id: int, change: ColorChange) -> None: sprite_gfx_id = sprite_id - 0x10 pal_ptr = gd.sprite_palette_ptrs(rom) pal_addr = rom.read_ptr(pal_ptr + sprite_gfx_id * 4) + + # Skip palettes that have already been randomized if pal_addr in self.randomized_pals: return if rom.is_mf(): - if sprite_id == 0x4D or sprite_id == 0xBE: + if sprite_id == SpriteIdMF.ICE_BEAM_ABILITY or sprite_id == SpriteIdMF.ZOZORO: # Ice beam ability and zozoros only have 1 row, not 2 rows = 1 else: @@ -245,12 +255,17 @@ def randomize_enemy(self, sprite_id: int, change: ColorChange) -> None: rows = (rom.read_32(gfx_addr) >> 8) // 0x800 else: raise ValueError("Unknown game!") + # Load palette, change colors, and write to ROM pal = Palette(rows, rom, pal_addr) self.change_func(pal, change) pal.write(rom, pal_addr) self.randomized_pals.add(pal_addr) - if rom.is_mf() and sprite_id == 0x26: + if rom.is_mf() and sprite_id in { + SpriteIdMF.SAMUS_EATER_BUD, + SpriteIdMF.SAMUS_EATER, + SpriteIdMF.NETTORI, + }: self.fix_nettori(change) def get_sprite_addr(self, sprite_id: int) -> int: @@ -268,31 +283,30 @@ def fix_nettori(self, change: ColorChange) -> None: self.change_func(pal, change) pal.write(self.rom, addr) - # TODO: Uncomment this once ZM data addresses are added - # def fix_zm_palettes(self) -> None: - # if ( - # PaletteType.ENEMIES in self.settings.pal_types - # or PaletteType.TILESETS in self.settings.pal_types - # ): - # # Fix kraid's body - # sp_addr = self.get_sprite_addr(0x6F) - # ts_addr = self.get_tileset_addr(9) - # self.rom.copy_bytes(sp_addr, ts_addr + 0x100, 0x20) - - # if PaletteType.TILESETS in self.settings.pal_types: - # # Fix kraid elevator statue - # sp_addr = self.get_sprite_addr(0x95) - # ts_addr = self.get_tileset_addr(0x35) - # self.rom.copy_bytes(ts_addr + 0x20, sp_addr, 0x20) - - # # Fix ridley elevator statue - # ts_addr = self.get_tileset_addr(7) - # self.rom.copy_bytes(ts_addr + 0x20, sp_addr + 0x20, 0x20) - - # # Fix tourian statues - # sp_addr = self.get_sprite_addr(0xA3) - # ts_addr = self.get_tileset_addr(0x41) - # self.rom.copy_bytes(ts_addr + 0x60, sp_addr, 0x20) - # # Fix cutscene - # sp_addr = gd.tourian_statues_cutscene_palette(self.rom) - # self.rom.copy_bytes(ts_addr, sp_addr, 0xC0) + def fix_zm_palettes(self) -> None: + if ( + PaletteType.ENEMIES in self.settings.pal_types + or PaletteType.TILESETS in self.settings.pal_types + ): + # Fix kraid's body + sp_addr = self.get_sprite_addr(SpriteIdZM.KRAID) + ts_addr = self.get_tileset_addr(9) + self.rom.copy_bytes(sp_addr, ts_addr + 0x100, 0x20) + + if PaletteType.TILESETS in self.settings.pal_types: + # Fix kraid elevator statue + sp_addr = self.get_sprite_addr(SpriteIdZM.KRAID_ELEVATOR_STATUE) + ts_addr = self.get_tileset_addr(0x35) + self.rom.copy_bytes(ts_addr + 0x20, sp_addr, 0x20) + + # Fix ridley elevator statue + ts_addr = self.get_tileset_addr(7) + self.rom.copy_bytes(ts_addr + 0x20, sp_addr + 0x20, 0x20) + + # Fix tourian statues + sp_addr = self.get_sprite_addr(SpriteIdZM.KRAID_STATUE) + ts_addr = self.get_tileset_addr(0x41) + self.rom.copy_bytes(ts_addr + 0x60, sp_addr, 0x20) + # Fix cutscene + sp_addr = statues_cutscene_palette_addr(self.rom) + self.rom.copy_bytes(ts_addr, sp_addr, 0xC0) diff --git a/src/mars_patcher/zm/constants/game_data.py b/src/mars_patcher/zm/constants/game_data.py index a94378f..4308480 100644 --- a/src/mars_patcher/zm/constants/game_data.py +++ b/src/mars_patcher/zm/constants/game_data.py @@ -80,3 +80,7 @@ def power_bomb_tank_increase_amount_addr(rom: Rom) -> int: def title_text_lines_addr(rom: Rom) -> int: return rom.read_ptr(ReservedPointersZM.TITLE_TEXT_LINES_PTR) + + +def statues_cutscene_palette_addr(rom: Rom) -> int: + return rom.read_ptr(ReservedPointersZM.STATUES_CUTSCENE_PALETTE_PTR) diff --git a/src/mars_patcher/zm/constants/reserved_space.py b/src/mars_patcher/zm/constants/reserved_space.py index d660d76..9c81f1e 100644 --- a/src/mars_patcher/zm/constants/reserved_space.py +++ b/src/mars_patcher/zm/constants/reserved_space.py @@ -55,6 +55,8 @@ class ReservedPointersZM(IntEnum): """Pointer to the palette used for the helmet cursor in menus.""" BEAM_PALETTES_PTR = auto() """Pointer to the start of the beam palettes.""" + STATUES_CUTSCENE_PALETTE_PTR = auto() + """Pointer to the palette of the boss statues near Tourian used during the cutscene.""" CHARACTER_WIDTHS_PTR = auto() """Pointer to the character widths table.""" SOUND_DATA_PTR = auto() diff --git a/src/mars_patcher/zm/constants/sprites.py b/src/mars_patcher/zm/constants/sprites.py new file mode 100644 index 0000000..52ee908 --- /dev/null +++ b/src/mars_patcher/zm/constants/sprites.py @@ -0,0 +1,84 @@ +from enum import IntEnum + + +class SpriteIdZM(IntEnum): + UNUSED_10 = 0x10 + MESSAGE_BANNER = 0x11 + RIPPER_BROWN = 0x16 + RIPPER_PURPLE = 0x17 + ZEB = 0x18 + ZEB_BLUE = 0x19 + SKREE_GREEN = 0x1F + SKREE_BLUE = 0x20 + CHOZO_STATUE_LONG_BEAM_HINT = 0x22 + LONG_BEAM_CHOZO_STATUE = 0x23 + CHOZO_STATUE_ICE_BEAM_HINT = 0x24 + ICE_BEAM_CHOZO_STATUE = 0x25 + CHOZO_STATUE_WAVE_BEAM_HINT = 0x26 + WAVE_BEAM_CHOZO_STATUE = 0x27 + CHOZO_STATUE_BOMB_HINT = 0x28 + BOMB_CHOZO_STATUE = 0x29 + CHOZO_STATUE_SPEED_BOOSTER_HINT = 0x2A + SPEED_BOOSTER_CHOZO_STATUE = 0x2B + CHOZO_STATUE_HI_JUMP_HINT = 0x2C + HI_JUMP_CHOZO_STATUE = 0x2D + CHOZO_STATUE_SCREW_ATTACK_HINT = 0x2E + SCREW_ATTACK_CHOZO_STATUE = 0x2F + CHOZO_STATUE_VARIA_SUIT_HINT = 0x30 + VARIA_SUIT_CHOZO_STATUE = 0x31 + MULTIVIOLA = 0x34 + GERUTA_RED = 0x36 + GERUTA_GREEN = 0x37 + REO_GREEN_WINGS = 0x3F + REO_PURPLE_WINGS = 0x40 + IMAGO_LARVA_RIGHT = 0x4D + IMAGO_COCOON = 0x4F + SPACE_PIRATE = 0x51 + SPACE_PIRATE_WAITING_1 = 0x52 + SPACE_PIRATE_WAITING_2 = 0x53 + SPACE_PIRATE_WAITING_3 = 0x54 + SPACE_PIRATE_2 = 0x55 + GAMET_BLUE_SINGLE = 0x56 + GAMET_RED_SINGLE = 0x57 + GRAVITY_SUIT_CHOZO_STATUE = 0x58 + SPACE_JUMP_CHOZO_STATUE = 0x59 + ZEBBO_GREEN = 0x5B + ZEBBO_YELLOW = 0x5C + RINKA_ORANGE = 0x66 + VIOLA_BLUE = 0x68 + VIOLA_ORANGE = 0x69 + KRAID = 0x6F + IMAGO_COCOON_AFTER_FIGHT = 0x70 + RIPPER_II = 0x71 + GEEGA = 0x7A + GEEGA_WHITE = 0x7B + RINKA_MOTHER_BRAIN = 0x7C + IMAGO_LARVA_RIGHT_SIDE = 0x7F + IMAGO = 0x86 + IMAGO_LARVA_LEFT = 0x8B + PLASMA_BEAM_CHOZO_STATUE = 0x94 + KRAID_ELEVATOR_STATUE = 0x95 + RIDLEY_ELEVATOR_STATUE = 0x96 + GAMET_BLUE_LEADER = 0x9D + GAMET_BLUE_FOLLOWER = 0x9E + GEEGA_LEADER = 0x9F + GEEGA_FOLLOWER = 0xA0 + ZEBBO_GREEN_LEADER = 0xA1 + ZEBBO_GREEN_FOLLOWER = 0xA2 + KRAID_STATUE = 0xA3 + RINKA_GREEN = 0xA5 + PLASMA_BEAM_BLOCK = 0xAA + GRAVITY_SUIT_BLOCK = 0xAB + SPACE_JUMP_BLOCK = 0xAC + SPACE_PIRATE_CARRYING_POWER_BOMB = 0xB6 + TANGLE_VINE_RED_GERUTA = 0xB7 + TANGLE_VINE_GERUTA = 0xB8 + TANGLE_VINE_LARVA_RIGHT = 0xB9 + TANGLE_VINE_LARVA_LEFT = 0xBA + BLACK_SPACE_PIRATE = 0xC6 + ESCAPE_SHIP_SPACE_PIRATE = 0xC7 + RINKA_MOTHER_BRAIN_C9 = 0xC9 + RINKA_MOTHER_BRAIN_CA = 0xCA + RINKA_MOTHER_BRAIN_CB = 0xCB + RINKA_MOTHER_BRAIN_CC = 0xCC + RINKA_MOTHER_BRAIN_CD = 0xCD From 9749be1a15e7ebd4d95f1bd806f7eaa4a3376ae8 Mon Sep 17 00:00:00 2001 From: biosp4rk <37962487+biosp4rk@users.noreply.github.com> Date: Thu, 11 Sep 2025 16:35:45 -0700 Subject: [PATCH 2/3] Separate palette/enemy constants --- src/mars_patcher/common_types.py | 4 - src/mars_patcher/constants/enemies.py | 54 --------- src/mars_patcher/constants/palettes.py | 140 ---------------------- src/mars_patcher/constants/sprites.py | 4 + src/mars_patcher/mf/constants/enemies.py | 50 ++++++++ src/mars_patcher/mf/constants/palettes.py | 44 +++++++ src/mars_patcher/mf/constants/sprites.py | 4 +- src/mars_patcher/random_enemies.py | 11 +- src/mars_patcher/random_palettes.py | 19 ++- src/mars_patcher/zm/constants/palettes.py | 97 +++++++++++++++ src/mars_patcher/zm/constants/sprites.py | 4 +- 11 files changed, 224 insertions(+), 207 deletions(-) delete mode 100644 src/mars_patcher/constants/palettes.py create mode 100644 src/mars_patcher/constants/sprites.py create mode 100644 src/mars_patcher/mf/constants/enemies.py create mode 100644 src/mars_patcher/zm/constants/palettes.py diff --git a/src/mars_patcher/common_types.py b/src/mars_patcher/common_types.py index 10122e4..0a09c67 100644 --- a/src/mars_patcher/common_types.py +++ b/src/mars_patcher/common_types.py @@ -2,8 +2,6 @@ import mars_patcher.mf.auto_generated_types as types_mf import mars_patcher.zm.auto_generated_types as types_zm -from mars_patcher.mf.constants.sprites import SpriteIdMF -from mars_patcher.zm.constants.sprites import SpriteIdZM TypeU8: TypeAlias = types_mf.Typeu8 | types_zm.TypeU8 @@ -13,5 +11,3 @@ AreaRoomPair = tuple[AreaId, RoomId] MinimapId: TypeAlias = Annotated[int, "0 <= value < 10"] - -SpriteId: TypeAlias = SpriteIdMF | SpriteIdZM diff --git a/src/mars_patcher/constants/enemies.py b/src/mars_patcher/constants/enemies.py index cf0678a..5f0540a 100644 --- a/src/mars_patcher/constants/enemies.py +++ b/src/mars_patcher/constants/enemies.py @@ -1,8 +1,5 @@ from enum import Enum -from mars_patcher.mf.constants.sprites import SpriteIdMF -from mars_patcher.rom import Game - class EnemyType(Enum): CRAWLING = 1 @@ -11,54 +8,3 @@ class EnemyType(Enum): GROUND_CEILING = 4 WALL = 5 FLYING = 6 - - -ENEMY_TYPES = { - Game.MF: { - SpriteIdMF.HORNOAD: EnemyType.GROUND, - SpriteIdMF.HALZYN: EnemyType.FLYING, - SpriteIdMF.ZEBESIAN_WALL: EnemyType.WALL, - SpriteIdMF.HORNOAD_SPAWNER: EnemyType.GROUND, - SpriteIdMF.MOTO: EnemyType.GROUND, - SpriteIdMF.YAMEBA: EnemyType.FLYING, - SpriteIdMF.ZEELA: EnemyType.CRAWLING, - SpriteIdMF.SKREE_UNUSED: EnemyType.CEILING, - SpriteIdMF.ZOMBIE: EnemyType.GROUND, - SpriteIdMF.GEEMER: EnemyType.CRAWLING, - SpriteIdMF.WAVER: EnemyType.FLYING, - SpriteIdMF.SCISER: EnemyType.CRAWLING, - SpriteIdMF.SIDEHOPPER: EnemyType.GROUND_CEILING, - SpriteIdMF.DESSGEEGA: EnemyType.GROUND_CEILING, - SpriteIdMF.ZORO: EnemyType.CRAWLING, - SpriteIdMF.KIHUNTER_FLYING: EnemyType.FLYING, - SpriteIdMF.KIHUNTER_GROUND: EnemyType.GROUND, - SpriteIdMF.REO: EnemyType.FLYING, - SpriteIdMF.NAMIHE: EnemyType.WALL, - SpriteIdMF.FUNE: EnemyType.WALL, - SpriteIdMF.BLUE_ZORO: EnemyType.CRAWLING, - SpriteIdMF.GERUDA: EnemyType.FLYING, - SpriteIdMF.SKULTERA_LARGE: EnemyType.FLYING, - SpriteIdMF.SKULTERA_SMALL_ONLY: EnemyType.FLYING, - SpriteIdMF.SOVA: EnemyType.CRAWLING, - SpriteIdMF.YARD: EnemyType.CRAWLING, - SpriteIdMF.EVIR: EnemyType.FLYING, - SpriteIdMF.BULL: EnemyType.FLYING, - SpriteIdMF.MEMU: EnemyType.FLYING, - SpriteIdMF.GERUBOSS: EnemyType.CEILING, - SpriteIdMF.CHOOT: EnemyType.GROUND, - SpriteIdMF.ZEBESIAN_GROUND: EnemyType.GROUND, - SpriteIdMF.RIPPER: EnemyType.FLYING, - SpriteIdMF.RED_ZEELA: EnemyType.CRAWLING, - SpriteIdMF.OWTCH: EnemyType.CRAWLING, - SpriteIdMF.GENESIS: EnemyType.GROUND, - SpriteIdMF.PUYO: EnemyType.GROUND, - SpriteIdMF.FAKE_ENERGY_TANK: EnemyType.GROUND, - SpriteIdMF.FAKE_MISSILE_TANK: EnemyType.GROUND, - SpriteIdMF.ZEBESIAN_AQUA: EnemyType.FLYING, - SpriteIdMF.ZEBESIAN_PRE_AQUA: EnemyType.GROUND, - SpriteIdMF.SKULTERA_SMALL: EnemyType.FLYING, - SpriteIdMF.POWAMP: EnemyType.FLYING, - SpriteIdMF.ZOZORO: EnemyType.CRAWLING, - }, - # TODO: Game.ZM -} diff --git a/src/mars_patcher/constants/palettes.py b/src/mars_patcher/constants/palettes.py deleted file mode 100644 index 6058adb..0000000 --- a/src/mars_patcher/constants/palettes.py +++ /dev/null @@ -1,140 +0,0 @@ -from mars_patcher.common_types import SpriteId -from mars_patcher.mf.constants.sprites import SpriteIdMF -from mars_patcher.rom import Game -from mars_patcher.zm.constants.sprites import SpriteIdZM - -EXCLUDED_ENEMIES: dict[Game, set[SpriteId]] = { - Game.MF: { - SpriteIdMF.SAX_ELEVATOR, - SpriteIdMF.AREA_BANNER, - SpriteIdMF.MESSAGE_BANNER, - SpriteIdMF.SAX_TRO_1, - SpriteIdMF.SAX_NOC, - SpriteIdMF.SAX_ARC, - SpriteIdMF.SAX_LAB, - SpriteIdMF.SAX_BOSS, - SpriteIdMF.SAX_MONSTER, - SpriteIdMF.SAX_OMEGA, - SpriteIdMF.SAX_TRO_2, - }, - Game.ZM: { - SpriteIdZM.UNUSED_10, - SpriteIdZM.MESSAGE_BANNER, - }, -} - - -ENEMY_GROUPS: dict[Game, dict[str, list[SpriteId]]] = { - Game.MF: { - "Zebesian": [ - SpriteIdMF.ZEBESIAN_WALL, - SpriteIdMF.ZEBESIAN_GROUND, - SpriteIdMF.GOLD_ZEBESIAN, - SpriteIdMF.ZEBESIAN_AQUA, - SpriteIdMF.ZEBESIAN_PRE_AQUA, - ], - "Zeela": [SpriteIdMF.ZEELA, SpriteIdMF.RED_ZEELA], - "Sciser": [SpriteIdMF.SCISER, SpriteIdMF.GOLD_SCISER], - "BeamCoreX": [ - SpriteIdMF.CHARGE_BEAM_CORE_X, - SpriteIdMF.WIDE_BEAM_CORE_X, - SpriteIdMF.PLASMA_BEAM_CORE_X, - SpriteIdMF.WAVE_BEAM_CORE_X, - ], - "Zoro": [ - SpriteIdMF.ZORO, - SpriteIdMF.BLUE_ZORO, - SpriteIdMF.ZORO_COCOON, - SpriteIdMF.ZORO_HUSK, - ], - "FakeTank": [SpriteIdMF.FAKE_ENERGY_TANK, SpriteIdMF.FAKE_MISSILE_TANK], - }, - Game.ZM: { - "Ripper": [SpriteIdZM.RIPPER_BROWN, SpriteIdZM.RIPPER_PURPLE, SpriteIdZM.RIPPER_II], - "Zeb": [SpriteIdZM.ZEB, SpriteIdZM.ZEB_BLUE], - "Skree": [SpriteIdZM.SKREE_GREEN, SpriteIdZM.SKREE_BLUE], - "ChozoStatue": [ - SpriteIdZM.CHOZO_STATUE_LONG_BEAM_HINT, - SpriteIdZM.LONG_BEAM_CHOZO_STATUE, - SpriteIdZM.CHOZO_STATUE_ICE_BEAM_HINT, - SpriteIdZM.ICE_BEAM_CHOZO_STATUE, - SpriteIdZM.CHOZO_STATUE_WAVE_BEAM_HINT, - SpriteIdZM.WAVE_BEAM_CHOZO_STATUE, - SpriteIdZM.CHOZO_STATUE_BOMB_HINT, - SpriteIdZM.BOMB_CHOZO_STATUE, - SpriteIdZM.CHOZO_STATUE_SPEED_BOOSTER_HINT, - SpriteIdZM.SPEED_BOOSTER_CHOZO_STATUE, - SpriteIdZM.CHOZO_STATUE_HI_JUMP_HINT, - SpriteIdZM.HI_JUMP_CHOZO_STATUE, - SpriteIdZM.CHOZO_STATUE_SCREW_ATTACK_HINT, - SpriteIdZM.SCREW_ATTACK_CHOZO_STATUE, - SpriteIdZM.CHOZO_STATUE_VARIA_SUIT_HINT, - SpriteIdZM.VARIA_SUIT_CHOZO_STATUE, - SpriteIdZM.GRAVITY_SUIT_CHOZO_STATUE, - SpriteIdZM.SPACE_JUMP_CHOZO_STATUE, - SpriteIdZM.PLASMA_BEAM_CHOZO_STATUE, - ], - "Viola": [SpriteIdZM.MULTIVIOLA, SpriteIdZM.VIOLA_BLUE, SpriteIdZM.VIOLA_ORANGE], - "GerutaTangleVine": [ - SpriteIdZM.GERUTA_RED, - SpriteIdZM.GERUTA_GREEN, - SpriteIdZM.TANGLE_VINE_RED_GERUTA, - SpriteIdZM.TANGLE_VINE_GERUTA, - SpriteIdZM.TANGLE_VINE_LARVA_RIGHT, - SpriteIdZM.TANGLE_VINE_LARVA_LEFT, - ], - "Reo": [SpriteIdZM.REO_GREEN_WINGS, SpriteIdZM.REO_PURPLE_WINGS], - "Imago": [ - SpriteIdZM.IMAGO_LARVA_RIGHT, - SpriteIdZM.IMAGO_COCOON, - SpriteIdZM.IMAGO_COCOON_AFTER_FIGHT, - SpriteIdZM.IMAGO_LARVA_RIGHT_SIDE, - SpriteIdZM.IMAGO, - SpriteIdZM.IMAGO_LARVA_LEFT, - ], - "SpacePirate": [ - SpriteIdZM.SPACE_PIRATE, - SpriteIdZM.SPACE_PIRATE_WAITING_1, - SpriteIdZM.SPACE_PIRATE_WAITING_2, - SpriteIdZM.SPACE_PIRATE_WAITING_3, - SpriteIdZM.SPACE_PIRATE_2, - SpriteIdZM.SPACE_PIRATE_CARRYING_POWER_BOMB, - SpriteIdZM.BLACK_SPACE_PIRATE, - SpriteIdZM.ESCAPE_SHIP_SPACE_PIRATE, - ], - "Gamet": [ - SpriteIdZM.GAMET_BLUE_SINGLE, - SpriteIdZM.GAMET_RED_SINGLE, - SpriteIdZM.GAMET_BLUE_LEADER, - SpriteIdZM.GAMET_BLUE_FOLLOWER, - ], - "Zebbo": [ - SpriteIdZM.ZEBBO_GREEN, - SpriteIdZM.ZEBBO_YELLOW, - SpriteIdZM.ZEBBO_GREEN_LEADER, - SpriteIdZM.ZEBBO_GREEN_FOLLOWER, - ], - "Rinka": [ - SpriteIdZM.RINKA_ORANGE, - SpriteIdZM.RINKA_MOTHER_BRAIN, - SpriteIdZM.RINKA_GREEN, - SpriteIdZM.RINKA_MOTHER_BRAIN_C9, - SpriteIdZM.RINKA_MOTHER_BRAIN_CA, - SpriteIdZM.RINKA_MOTHER_BRAIN_CB, - SpriteIdZM.RINKA_MOTHER_BRAIN_CC, - SpriteIdZM.RINKA_MOTHER_BRAIN_CD, - ], - "Geega": [ - SpriteIdZM.GEEGA, - SpriteIdZM.GEEGA_WHITE, - SpriteIdZM.GEEGA_LEADER, - SpriteIdZM.GEEGA_FOLLOWER, - ], - "ElevatorStatue": [SpriteIdZM.KRAID_ELEVATOR_STATUE, SpriteIdZM.RIDLEY_ELEVATOR_STATUE], - "UnknownItemBlocks": [ - SpriteIdZM.PLASMA_BEAM_BLOCK, - SpriteIdZM.GRAVITY_SUIT_BLOCK, - SpriteIdZM.SPACE_JUMP_BLOCK, - ], - }, -} diff --git a/src/mars_patcher/constants/sprites.py b/src/mars_patcher/constants/sprites.py new file mode 100644 index 0000000..5448fed --- /dev/null +++ b/src/mars_patcher/constants/sprites.py @@ -0,0 +1,4 @@ +from enum import IntEnum + + +class SpriteId(IntEnum): ... diff --git a/src/mars_patcher/mf/constants/enemies.py b/src/mars_patcher/mf/constants/enemies.py new file mode 100644 index 0000000..bcc979c --- /dev/null +++ b/src/mars_patcher/mf/constants/enemies.py @@ -0,0 +1,50 @@ +from mars_patcher.constants.enemies import EnemyType +from mars_patcher.constants.sprites import SpriteId +from mars_patcher.mf.constants.sprites import SpriteIdMF + +ENEMY_TYPES_MF: dict[SpriteId, EnemyType] = { + SpriteIdMF.HORNOAD: EnemyType.GROUND, + SpriteIdMF.HALZYN: EnemyType.FLYING, + SpriteIdMF.ZEBESIAN_WALL: EnemyType.WALL, + SpriteIdMF.HORNOAD_SPAWNER: EnemyType.GROUND, + SpriteIdMF.MOTO: EnemyType.GROUND, + SpriteIdMF.YAMEBA: EnemyType.FLYING, + SpriteIdMF.ZEELA: EnemyType.CRAWLING, + SpriteIdMF.SKREE_UNUSED: EnemyType.CEILING, + SpriteIdMF.ZOMBIE: EnemyType.GROUND, + SpriteIdMF.GEEMER: EnemyType.CRAWLING, + SpriteIdMF.WAVER: EnemyType.FLYING, + SpriteIdMF.SCISER: EnemyType.CRAWLING, + SpriteIdMF.SIDEHOPPER: EnemyType.GROUND_CEILING, + SpriteIdMF.DESSGEEGA: EnemyType.GROUND_CEILING, + SpriteIdMF.ZORO: EnemyType.CRAWLING, + SpriteIdMF.KIHUNTER_FLYING: EnemyType.FLYING, + SpriteIdMF.KIHUNTER_GROUND: EnemyType.GROUND, + SpriteIdMF.REO: EnemyType.FLYING, + SpriteIdMF.NAMIHE: EnemyType.WALL, + SpriteIdMF.FUNE: EnemyType.WALL, + SpriteIdMF.BLUE_ZORO: EnemyType.CRAWLING, + SpriteIdMF.GERUDA: EnemyType.FLYING, + SpriteIdMF.SKULTERA_LARGE: EnemyType.FLYING, + SpriteIdMF.SKULTERA_SMALL_ONLY: EnemyType.FLYING, + SpriteIdMF.SOVA: EnemyType.CRAWLING, + SpriteIdMF.YARD: EnemyType.CRAWLING, + SpriteIdMF.EVIR: EnemyType.FLYING, + SpriteIdMF.BULL: EnemyType.FLYING, + SpriteIdMF.MEMU: EnemyType.FLYING, + SpriteIdMF.GERUBOSS: EnemyType.CEILING, + SpriteIdMF.CHOOT: EnemyType.GROUND, + SpriteIdMF.ZEBESIAN_GROUND: EnemyType.GROUND, + SpriteIdMF.RIPPER: EnemyType.FLYING, + SpriteIdMF.RED_ZEELA: EnemyType.CRAWLING, + SpriteIdMF.OWTCH: EnemyType.CRAWLING, + SpriteIdMF.GENESIS: EnemyType.GROUND, + SpriteIdMF.PUYO: EnemyType.GROUND, + SpriteIdMF.FAKE_ENERGY_TANK: EnemyType.GROUND, + SpriteIdMF.FAKE_MISSILE_TANK: EnemyType.GROUND, + SpriteIdMF.ZEBESIAN_AQUA: EnemyType.FLYING, + SpriteIdMF.ZEBESIAN_PRE_AQUA: EnemyType.GROUND, + SpriteIdMF.SKULTERA_SMALL: EnemyType.FLYING, + SpriteIdMF.POWAMP: EnemyType.FLYING, + SpriteIdMF.ZOZORO: EnemyType.CRAWLING, +} diff --git a/src/mars_patcher/mf/constants/palettes.py b/src/mars_patcher/mf/constants/palettes.py index 83eb3ba..46429a3 100644 --- a/src/mars_patcher/mf/constants/palettes.py +++ b/src/mars_patcher/mf/constants/palettes.py @@ -1,3 +1,6 @@ +from mars_patcher.constants.sprites import SpriteId +from mars_patcher.mf.constants.sprites import SpriteIdMF + MF_TILESET_ALT_PAL_ROWS = { 0x46F134: 0xD, # 08 0x4CCCC0: 0xD, # 09, 40 @@ -69,6 +72,47 @@ } +EXCLUDED_ENEMIES_MF: set[SpriteId] = { + SpriteIdMF.SAX_ELEVATOR, + SpriteIdMF.AREA_BANNER, + SpriteIdMF.MESSAGE_BANNER, + SpriteIdMF.SAX_TRO_1, + SpriteIdMF.SAX_NOC, + SpriteIdMF.SAX_ARC, + SpriteIdMF.SAX_LAB, + SpriteIdMF.SAX_BOSS, + SpriteIdMF.SAX_MONSTER, + SpriteIdMF.SAX_OMEGA, + SpriteIdMF.SAX_TRO_2, +} + + +ENEMY_GROUPS_MF: dict[str, list[SpriteId]] = { + "Zebesian": [ + SpriteIdMF.ZEBESIAN_WALL, + SpriteIdMF.ZEBESIAN_GROUND, + SpriteIdMF.GOLD_ZEBESIAN, + SpriteIdMF.ZEBESIAN_AQUA, + SpriteIdMF.ZEBESIAN_PRE_AQUA, + ], + "Zeela": [SpriteIdMF.ZEELA, SpriteIdMF.RED_ZEELA], + "Sciser": [SpriteIdMF.SCISER, SpriteIdMF.GOLD_SCISER], + "BeamCoreX": [ + SpriteIdMF.CHARGE_BEAM_CORE_X, + SpriteIdMF.WIDE_BEAM_CORE_X, + SpriteIdMF.PLASMA_BEAM_CORE_X, + SpriteIdMF.WAVE_BEAM_CORE_X, + ], + "Zoro": [ + SpriteIdMF.ZORO, + SpriteIdMF.BLUE_ZORO, + SpriteIdMF.ZORO_COCOON, + SpriteIdMF.ZORO_HUSK, + ], + "FakeTank": [SpriteIdMF.FAKE_ENERGY_TANK, SpriteIdMF.FAKE_MISSILE_TANK], +} + + NETTORI_EXTRA_PALS = [ (0x36A480, 1), # Medium health palette (0x36A4A0, 1), # Low health palette diff --git a/src/mars_patcher/mf/constants/sprites.py b/src/mars_patcher/mf/constants/sprites.py index f8c6cdd..23209b3 100644 --- a/src/mars_patcher/mf/constants/sprites.py +++ b/src/mars_patcher/mf/constants/sprites.py @@ -1,7 +1,7 @@ -from enum import IntEnum +from mars_patcher.constants.sprites import SpriteId -class SpriteIdMF(IntEnum): +class SpriteIdMF(SpriteId): SAX_ELEVATOR = 0x11 HORNOAD = 0x12 HALZYN = 0x13 diff --git a/src/mars_patcher/random_enemies.py b/src/mars_patcher/random_enemies.py index 2e24c57..82293e8 100644 --- a/src/mars_patcher/random_enemies.py +++ b/src/mars_patcher/random_enemies.py @@ -1,14 +1,21 @@ import random -from mars_patcher.constants.enemies import ENEMY_TYPES, EnemyType +from mars_patcher.constants.enemies import EnemyType from mars_patcher.constants.game_data import spriteset_count, spriteset_ptrs +from mars_patcher.mf.constants.enemies import ENEMY_TYPES_MF from mars_patcher.mf.constants.game_data import sprite_vram_sizes from mars_patcher.rom import Rom def randomize_enemies(rom: Rom) -> None: # Setup enemy types dictionary - enemy_types = {k.value: v for k, v in ENEMY_TYPES[rom.game].items()} + if rom.is_mf(): + _enemy_types = ENEMY_TYPES_MF + elif rom.is_zm(): + raise NotImplementedError("Enemey types not yet implemented for ZM") + else: + raise ValueError(rom.game) + enemy_types = {k.value: v for k, v in _enemy_types.items()} # Get graphics info for each enemy size_addr = sprite_vram_sizes(rom) diff --git a/src/mars_patcher/random_palettes.py b/src/mars_patcher/random_palettes.py index d084ae6..45294d0 100644 --- a/src/mars_patcher/random_palettes.py +++ b/src/mars_patcher/random_palettes.py @@ -5,7 +5,6 @@ from typing_extensions import Self import mars_patcher.constants.game_data as gd -from mars_patcher.constants.palettes import ENEMY_GROUPS, EXCLUDED_ENEMIES from mars_patcher.mf.auto_generated_types import ( MarsschemamfPalettes, MarsschemamfPalettesColorspace, @@ -13,6 +12,8 @@ ) from mars_patcher.mf.constants.game_data import sax_palettes, sprite_vram_sizes from mars_patcher.mf.constants.palettes import ( + ENEMY_GROUPS_MF, + EXCLUDED_ENEMIES_MF, MF_TILESET_ALT_PAL_ROWS, NETTORI_EXTRA_PALS, TILESET_ANIM_PALS, @@ -21,6 +22,7 @@ from mars_patcher.palette import ColorChange, Palette, SineWave from mars_patcher.rom import Game, Rom from mars_patcher.zm.constants.game_data import statues_cutscene_palette_addr +from mars_patcher.zm.constants.palettes import ENEMY_GROUPS_ZM, EXCLUDED_ENEMIES_ZM from mars_patcher.zm.constants.sprites import SpriteIdZM HueRange: TypeAlias = tuple[int, int] @@ -212,13 +214,24 @@ def randomize_anim_palette(self, anim_pal_id: int, change: ColorChange) -> None: def randomize_enemies(self, hue_range: HueRange) -> None: rom = self.rom - excluded = {en_id.value for en_id in EXCLUDED_ENEMIES[rom.game]} + if rom.is_mf(): + _excluded = EXCLUDED_ENEMIES_MF + elif rom.is_zm(): + _excluded = EXCLUDED_ENEMIES_ZM + else: + raise ValueError(rom.game) + excluded = {en_id.value for en_id in _excluded} sp_count = gd.sprite_count(rom) to_randomize = set(range(0x10, sp_count)) to_randomize -= excluded # Go through sprites in groups - groups = ENEMY_GROUPS[rom.game] + if rom.is_mf(): + groups = ENEMY_GROUPS_MF + elif rom.is_zm(): + groups = ENEMY_GROUPS_ZM + else: + raise ValueError(rom.game) for _, sprite_ids in groups.items(): change = self.generate_palette_change(hue_range) for sprite_id in sprite_ids: diff --git a/src/mars_patcher/zm/constants/palettes.py b/src/mars_patcher/zm/constants/palettes.py new file mode 100644 index 0000000..736db45 --- /dev/null +++ b/src/mars_patcher/zm/constants/palettes.py @@ -0,0 +1,97 @@ +from mars_patcher.constants.sprites import SpriteId +from mars_patcher.zm.constants.sprites import SpriteIdZM + +EXCLUDED_ENEMIES_ZM: set[SpriteId] = { + SpriteIdZM.UNUSED_10, + SpriteIdZM.MESSAGE_BANNER, +} + + +ENEMY_GROUPS_ZM: dict[str, list[SpriteId]] = { + "Ripper": [SpriteIdZM.RIPPER_BROWN, SpriteIdZM.RIPPER_PURPLE, SpriteIdZM.RIPPER_II], + "Zeb": [SpriteIdZM.ZEB, SpriteIdZM.ZEB_BLUE], + "Skree": [SpriteIdZM.SKREE_GREEN, SpriteIdZM.SKREE_BLUE], + "ChozoStatue": [ + SpriteIdZM.CHOZO_STATUE_LONG_BEAM_HINT, + SpriteIdZM.LONG_BEAM_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_ICE_BEAM_HINT, + SpriteIdZM.ICE_BEAM_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_WAVE_BEAM_HINT, + SpriteIdZM.WAVE_BEAM_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_BOMB_HINT, + SpriteIdZM.BOMB_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_SPEED_BOOSTER_HINT, + SpriteIdZM.SPEED_BOOSTER_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_HI_JUMP_HINT, + SpriteIdZM.HI_JUMP_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_SCREW_ATTACK_HINT, + SpriteIdZM.SCREW_ATTACK_CHOZO_STATUE, + SpriteIdZM.CHOZO_STATUE_VARIA_SUIT_HINT, + SpriteIdZM.VARIA_SUIT_CHOZO_STATUE, + SpriteIdZM.GRAVITY_SUIT_CHOZO_STATUE, + SpriteIdZM.SPACE_JUMP_CHOZO_STATUE, + SpriteIdZM.PLASMA_BEAM_CHOZO_STATUE, + ], + "Viola": [SpriteIdZM.MULTIVIOLA, SpriteIdZM.VIOLA_BLUE, SpriteIdZM.VIOLA_ORANGE], + "GerutaTangleVine": [ + SpriteIdZM.GERUTA_RED, + SpriteIdZM.GERUTA_GREEN, + SpriteIdZM.TANGLE_VINE_RED_GERUTA, + SpriteIdZM.TANGLE_VINE_GERUTA, + SpriteIdZM.TANGLE_VINE_LARVA_RIGHT, + SpriteIdZM.TANGLE_VINE_LARVA_LEFT, + ], + "Reo": [SpriteIdZM.REO_GREEN_WINGS, SpriteIdZM.REO_PURPLE_WINGS], + "Imago": [ + SpriteIdZM.IMAGO_LARVA_RIGHT, + SpriteIdZM.IMAGO_COCOON, + SpriteIdZM.IMAGO_COCOON_AFTER_FIGHT, + SpriteIdZM.IMAGO_LARVA_RIGHT_SIDE, + SpriteIdZM.IMAGO, + SpriteIdZM.IMAGO_LARVA_LEFT, + ], + "SpacePirate": [ + SpriteIdZM.SPACE_PIRATE, + SpriteIdZM.SPACE_PIRATE_WAITING_1, + SpriteIdZM.SPACE_PIRATE_WAITING_2, + SpriteIdZM.SPACE_PIRATE_WAITING_3, + SpriteIdZM.SPACE_PIRATE_2, + SpriteIdZM.SPACE_PIRATE_CARRYING_POWER_BOMB, + SpriteIdZM.BLACK_SPACE_PIRATE, + SpriteIdZM.ESCAPE_SHIP_SPACE_PIRATE, + ], + "Gamet": [ + SpriteIdZM.GAMET_BLUE_SINGLE, + SpriteIdZM.GAMET_RED_SINGLE, + SpriteIdZM.GAMET_BLUE_LEADER, + SpriteIdZM.GAMET_BLUE_FOLLOWER, + ], + "Zebbo": [ + SpriteIdZM.ZEBBO_GREEN, + SpriteIdZM.ZEBBO_YELLOW, + SpriteIdZM.ZEBBO_GREEN_LEADER, + SpriteIdZM.ZEBBO_GREEN_FOLLOWER, + ], + "Rinka": [ + SpriteIdZM.RINKA_ORANGE, + SpriteIdZM.RINKA_MOTHER_BRAIN, + SpriteIdZM.RINKA_GREEN, + SpriteIdZM.RINKA_MOTHER_BRAIN_C9, + SpriteIdZM.RINKA_MOTHER_BRAIN_CA, + SpriteIdZM.RINKA_MOTHER_BRAIN_CB, + SpriteIdZM.RINKA_MOTHER_BRAIN_CC, + SpriteIdZM.RINKA_MOTHER_BRAIN_CD, + ], + "Geega": [ + SpriteIdZM.GEEGA, + SpriteIdZM.GEEGA_WHITE, + SpriteIdZM.GEEGA_LEADER, + SpriteIdZM.GEEGA_FOLLOWER, + ], + "ElevatorStatue": [SpriteIdZM.KRAID_ELEVATOR_STATUE, SpriteIdZM.RIDLEY_ELEVATOR_STATUE], + "UnknownItemBlocks": [ + SpriteIdZM.PLASMA_BEAM_BLOCK, + SpriteIdZM.GRAVITY_SUIT_BLOCK, + SpriteIdZM.SPACE_JUMP_BLOCK, + ], +} diff --git a/src/mars_patcher/zm/constants/sprites.py b/src/mars_patcher/zm/constants/sprites.py index 52ee908..ed9724b 100644 --- a/src/mars_patcher/zm/constants/sprites.py +++ b/src/mars_patcher/zm/constants/sprites.py @@ -1,7 +1,7 @@ -from enum import IntEnum +from mars_patcher.constants.sprites import SpriteId -class SpriteIdZM(IntEnum): +class SpriteIdZM(SpriteId): UNUSED_10 = 0x10 MESSAGE_BANNER = 0x11 RIPPER_BROWN = 0x16 From 0f07697f3272e9bc6eaef607828d6eef410a5ced Mon Sep 17 00:00:00 2001 From: biosp4rk <37962487+biosp4rk@users.noreply.github.com> Date: Thu, 11 Sep 2025 16:57:27 -0700 Subject: [PATCH 3/3] Don't subclass enums --- src/mars_patcher/constants/sprites.py | 4 ---- src/mars_patcher/mf/constants/enemies.py | 3 +-- src/mars_patcher/mf/constants/palettes.py | 5 ++--- src/mars_patcher/mf/constants/sprites.py | 4 ++-- src/mars_patcher/random_enemies.py | 6 ++++++ src/mars_patcher/random_palettes.py | 2 ++ src/mars_patcher/zm/constants/palettes.py | 5 ++--- src/mars_patcher/zm/constants/sprites.py | 4 ++-- 8 files changed, 17 insertions(+), 16 deletions(-) delete mode 100644 src/mars_patcher/constants/sprites.py diff --git a/src/mars_patcher/constants/sprites.py b/src/mars_patcher/constants/sprites.py deleted file mode 100644 index 5448fed..0000000 --- a/src/mars_patcher/constants/sprites.py +++ /dev/null @@ -1,4 +0,0 @@ -from enum import IntEnum - - -class SpriteId(IntEnum): ... diff --git a/src/mars_patcher/mf/constants/enemies.py b/src/mars_patcher/mf/constants/enemies.py index bcc979c..c55b1da 100644 --- a/src/mars_patcher/mf/constants/enemies.py +++ b/src/mars_patcher/mf/constants/enemies.py @@ -1,8 +1,7 @@ from mars_patcher.constants.enemies import EnemyType -from mars_patcher.constants.sprites import SpriteId from mars_patcher.mf.constants.sprites import SpriteIdMF -ENEMY_TYPES_MF: dict[SpriteId, EnemyType] = { +ENEMY_TYPES_MF = { SpriteIdMF.HORNOAD: EnemyType.GROUND, SpriteIdMF.HALZYN: EnemyType.FLYING, SpriteIdMF.ZEBESIAN_WALL: EnemyType.WALL, diff --git a/src/mars_patcher/mf/constants/palettes.py b/src/mars_patcher/mf/constants/palettes.py index 46429a3..1fdd7d2 100644 --- a/src/mars_patcher/mf/constants/palettes.py +++ b/src/mars_patcher/mf/constants/palettes.py @@ -1,4 +1,3 @@ -from mars_patcher.constants.sprites import SpriteId from mars_patcher.mf.constants.sprites import SpriteIdMF MF_TILESET_ALT_PAL_ROWS = { @@ -72,7 +71,7 @@ } -EXCLUDED_ENEMIES_MF: set[SpriteId] = { +EXCLUDED_ENEMIES_MF = { SpriteIdMF.SAX_ELEVATOR, SpriteIdMF.AREA_BANNER, SpriteIdMF.MESSAGE_BANNER, @@ -87,7 +86,7 @@ } -ENEMY_GROUPS_MF: dict[str, list[SpriteId]] = { +ENEMY_GROUPS_MF = { "Zebesian": [ SpriteIdMF.ZEBESIAN_WALL, SpriteIdMF.ZEBESIAN_GROUND, diff --git a/src/mars_patcher/mf/constants/sprites.py b/src/mars_patcher/mf/constants/sprites.py index 23209b3..f8c6cdd 100644 --- a/src/mars_patcher/mf/constants/sprites.py +++ b/src/mars_patcher/mf/constants/sprites.py @@ -1,7 +1,7 @@ -from mars_patcher.constants.sprites import SpriteId +from enum import IntEnum -class SpriteIdMF(SpriteId): +class SpriteIdMF(IntEnum): SAX_ELEVATOR = 0x11 HORNOAD = 0x12 HALZYN = 0x13 diff --git a/src/mars_patcher/random_enemies.py b/src/mars_patcher/random_enemies.py index 82293e8..30e8b87 100644 --- a/src/mars_patcher/random_enemies.py +++ b/src/mars_patcher/random_enemies.py @@ -1,4 +1,5 @@ import random +from typing import TYPE_CHECKING from mars_patcher.constants.enemies import EnemyType from mars_patcher.constants.game_data import spriteset_count, spriteset_ptrs @@ -6,9 +7,14 @@ from mars_patcher.mf.constants.game_data import sprite_vram_sizes from mars_patcher.rom import Rom +if TYPE_CHECKING: + from mars_patcher.mf.constants.sprites import SpriteIdMF + from mars_patcher.zm.constants.sprites import SpriteIdZM + def randomize_enemies(rom: Rom) -> None: # Setup enemy types dictionary + _enemy_types: dict[SpriteIdMF, EnemyType] | dict[SpriteIdZM, EnemyType] if rom.is_mf(): _enemy_types = ENEMY_TYPES_MF elif rom.is_zm(): diff --git a/src/mars_patcher/random_palettes.py b/src/mars_patcher/random_palettes.py index 45294d0..da4a4f0 100644 --- a/src/mars_patcher/random_palettes.py +++ b/src/mars_patcher/random_palettes.py @@ -214,6 +214,7 @@ def randomize_anim_palette(self, anim_pal_id: int, change: ColorChange) -> None: def randomize_enemies(self, hue_range: HueRange) -> None: rom = self.rom + _excluded: set[SpriteIdMF] | set[SpriteIdZM] if rom.is_mf(): _excluded = EXCLUDED_ENEMIES_MF elif rom.is_zm(): @@ -226,6 +227,7 @@ def randomize_enemies(self, hue_range: HueRange) -> None: to_randomize -= excluded # Go through sprites in groups + groups: dict[str, list[SpriteIdMF]] | dict[str, list[SpriteIdZM]] if rom.is_mf(): groups = ENEMY_GROUPS_MF elif rom.is_zm(): diff --git a/src/mars_patcher/zm/constants/palettes.py b/src/mars_patcher/zm/constants/palettes.py index 736db45..4054681 100644 --- a/src/mars_patcher/zm/constants/palettes.py +++ b/src/mars_patcher/zm/constants/palettes.py @@ -1,13 +1,12 @@ -from mars_patcher.constants.sprites import SpriteId from mars_patcher.zm.constants.sprites import SpriteIdZM -EXCLUDED_ENEMIES_ZM: set[SpriteId] = { +EXCLUDED_ENEMIES_ZM = { SpriteIdZM.UNUSED_10, SpriteIdZM.MESSAGE_BANNER, } -ENEMY_GROUPS_ZM: dict[str, list[SpriteId]] = { +ENEMY_GROUPS_ZM = { "Ripper": [SpriteIdZM.RIPPER_BROWN, SpriteIdZM.RIPPER_PURPLE, SpriteIdZM.RIPPER_II], "Zeb": [SpriteIdZM.ZEB, SpriteIdZM.ZEB_BLUE], "Skree": [SpriteIdZM.SKREE_GREEN, SpriteIdZM.SKREE_BLUE], diff --git a/src/mars_patcher/zm/constants/sprites.py b/src/mars_patcher/zm/constants/sprites.py index ed9724b..52ee908 100644 --- a/src/mars_patcher/zm/constants/sprites.py +++ b/src/mars_patcher/zm/constants/sprites.py @@ -1,7 +1,7 @@ -from mars_patcher.constants.sprites import SpriteId +from enum import IntEnum -class SpriteIdZM(SpriteId): +class SpriteIdZM(IntEnum): UNUSED_10 = 0x10 MESSAGE_BANNER = 0x11 RIPPER_BROWN = 0x16