Files
Archipelago/worlds/earthbound/modules/enemizer/randomize_enemy_attacks.py
PinkSwitch 55c70a5ba8 EarthBound: Implement New Game (#5159)
* Add the world

* doc update

* docs

* Fix Blast/Missile not clearing Reflect

* Update worlds/earthbound/__init__.py

Co-authored-by: Duck <31627079+duckboycool@users.noreply.github.com>

* Update worlds/earthbound/__init__.py

remove unused import

Co-authored-by: Duck <31627079+duckboycool@users.noreply.github.com>

* Update worlds/earthbound/__init__.py

Co-authored-by: Duck <31627079+duckboycool@users.noreply.github.com>

* Update worlds/earthbound/modules/dungeon_er.py

make bool optional

Co-authored-by: Duck <31627079+duckboycool@users.noreply.github.com>

* Update worlds/earthbound/modules/boss_shuffle.py

typing update

Co-authored-by: Duck <31627079+duckboycool@users.noreply.github.com>

* Update worlds/earthbound/modules/boss_shuffle.py

Co-authored-by: Duck <31627079+duckboycool@users.noreply.github.com>

* Filter events out of item name to id

* we call it a glorp

* Update worlds/earthbound/Regions.py

Co-authored-by: Duck <31627079+duckboycool@users.noreply.github.com>

* Update worlds/earthbound/__init__.py

Co-authored-by: Duck <31627079+duckboycool@users.noreply.github.com>

* Update worlds/earthbound/Items.py

Co-authored-by: Duck <31627079+duckboycool@users.noreply.github.com>

* Update worlds/earthbound/Regions.py

Co-authored-by: Duck <31627079+duckboycool@users.noreply.github.com>

* Fix missing optional import

* hint stuff

* -Fix Apple Kid text being wrong
-Fix Slimy Pile text being wrong

* -Fix some sprite corruption if PSI was used when an enemy loaded another enemy
-Fixed a visible artifact tile during some cutscenes

* Update ver

* Update docs

* Fix some money scripting issues

* Add argument to PSI fakeout attack

* Updated monkey caves shop description

* Remove closing markdown from doc

* Add new flavors

* Make flavors actually work

* Update platforms

* Fix common gear getting duplicated

* Split region initialization

* Condense checks for start inventory + some other junk

* Fix some item groups - change receiver phone to warp pad

* wow that one was really bad :glorp:

* blah

* Fix cutoff option text

* switch start inventory concatenation to itertools

* Fix sky runner scripting bug - added some new comm suggestions

* Fix crash when generating with spoiler_only

* Fix happy-happy teleport not unlocking after beating carpainter

* Hint man hints can now use CreateHint packets to create hints in other games

* Adjust some filler rarity

* Update world to use CreateHints and deprecate old method

* Fix epilogue skip being offset

* Rearrange a couple regions

* Fix tendapants getting deleted in battle

* update doc

* i got scared and forgot i had multiple none checks and am worried about this triggering but tested and it works

* Fix mostly typing errors from silvris

* More type checks

* More typing

* Typema

* Type

* Fix enemy levels overwriting music

* Fix gihugic blunder

* Fix Lumine Hall enabling OSS

* del world

* Rel 4.2.7

* Remove some debug logs

* Fix vanilla bug with weird ambush detection

* Fix Starman Junior having an unscaled Freeze

* Change shop scaling

* Fix shops using the wrong thankful script

* Update some bosses in boss shuffle

* Loc group adjustment

* Update some boss shuffle stuff | Fix Enemizer attacks getting overwritten by Shuffle data | Fix flunkies not updating and still being used with enemizer

* Get rid of some debug stuff

* Get boss shuffle running, dont merge

* Fix json and get boss shuffle no plando back up

* Fix Magicant Boost not initializing to Ness if party count = 4

* Fix belch shop using wrong logic

* Don't re-send goal status

* EBitem

* remove :

* idk if this is whatvi wanted

* All client messagesnow only send when relevant instead of constantly

* Patch up the rest of boss plando

* Fix Giygas being not excluded from enemizer

* Fix epilogue again

* adjust the sphere scaling name

* add the things

* Fix Ness being placed onto monotoli when monotoli was in sea of eden

* Fix prefill properly

* Fix boss shuffle on vanilla slots.

* rename this, apparently

* Update archipelago.json

---------

Co-authored-by: Duck <31627079+duckboycool@users.noreply.github.com>
Co-authored-by: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com>
2025-12-19 14:52:27 +01:00

237 lines
6.8 KiB
Python

import struct
from .enemy_attributes import excluded_enemies
from ..enemy_data import spell_breaks
from ..enemy_shuffler import enemy_ids
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ... import EarthBoundWorld
from ...Rom import LocalRom
battle_actions = { # Actions in camel case are scaled
"Attack": 0x04,
"Shoot": 0x05,
"Spy": 0x06,
"Defend": 0x08,
"None": 0x09,
"Magnet Alpha": 0x36,
"Magnet Omega": 0x37,
"Call": 0x3E,
"Sow Seeds": 0x3F,
"Steal": 0x42,
"Freeze in Time": 0x43,
"diamond_eyes": 0x44,
"Strange Beam": 0x46,
"nauseous_breath": 0x47,
"poison_stinger": 0x48,
"kiss_of_death": 0x49,
"Arctic Breath": 0x4A,
"Mushroom Spores": 0x4B,
"Possess": 0x4C,
"Sprinkle Powder": 0x4D,
"Mold Spores": 0x4E,
"Binding Attack": 0x4F,
"Sticky Mucus": 0x50,
"Spew Fly Honey": 0x51,
"Shoot Silk": 0x52,
"Say Something Scary": 0x53,
"Do Something Mysterious": 0x54,
"Disrupt Sense": 0x55,
"Size Up Situation": 0x56,
"Exhale Stinky": 0x57,
"summon_storm": 0x58,
"scalding_espresso": 0x59,
"Haunting Melody": 0x5A,
"extinguishing_blast": 0x5B,
"crashing_boom_bang": 0x5C,
"spray_fire": 0x5D,
"breathe_fire": 0x5E,
"Spin Around": 0x5F,
"Lose Temper": 0x60,
"Say Nasty": 0x61,
"Vacuum Attack": 0x62,
# "Replenish Fuel",
"poisonous_fangs": 0x64,
# Dizzy Missile
"Continuous Attack": 0x66,
"Guard": 0x67,
"flaming_fireball": 0x68,
"Intertwine": 0x69,
"Crushing Chop": 0x6A,
"Submission Hold": 0x6B,
"Rev and Accelerate": 0x6C,
"Brandish a Knife": 0x6D,
"Tear Into": 0x6E,
"Bite": 0x6F,
"Claw with Nails": 0x70,
"Swing Tail": 0x71,
"Lunge": 0x72,
"Shopping Bag": 0x73,
"Swing Club": 0x74,
"Tornado": 0x75,
"Spray Water": 0x76,
"Flash a Menacing Smile": 0x77,
"Laugh Hysterically": 78,
"Edge Closer": 0x79,
"Whisper 3": 0x7A,
"Murmur 2": 0x7B,
"Mutter 1": 0x7C,
"Fall down": 0x7D,
"Be Absentminded": 0x7E,
"Burst of Steam": 0x7F,
"Wobble": 0x80,
"Reel": 0x81,
"Big Grin": 0x82,
"Take Breath": 0x83,
"Greeting": 0x84,
"Howl": 0x85,
"Tick Tock": 0x86,
# "Eat Food": 0x8A,
"PSI Food": 0x8E,
# Counter PSI: 0x9F World.gadget actions?
# Shield Killer
# HP Sucker
"Yogurt Dispenser": 0xAA,
"Toothbrush": 0xAE,
"Sudden Guts": 0xB6,
"Ruler": 0xBA,
"Protractor": 0xBB,
"Fly Honey": 0xBD,
"glorious_light": 0xC9,
"electrical_shock": 0xCA,
"paralyzing_pollen": 0xCB,
"Icy Hand": 0xCC,
"poison_flute": 0xCD,
"Exhaust Fumes": 0xCE,
"Laugh Maniacally": 0xCF,
"Breathe Flute": 0xD0,
"Leap and Spread Wings": 0xD1,
"Become Friendly": 0xD2,
"Rumble": 0xD3,
"Give Hug": 0xD4,
"hacking_cough": 0xD5,
"Misery Attack": 0xD6,
"Paint Attack": 0xD7,
"Come Out Swinging": 0xD8,
"Scratch with Claws": 0xD9,
"Peck at Eyes": 0xDA,
"Ram and Trample": 0xDB,
"Punch": 0xDC,
"Spit Seeds": 0xDD,
"Fire a Beam": 0xDE,
"Spear": 0xDF,
"Stomp with Foot": 0xE0,
"Hula Hoop": 0xE1,
"Charge Forward": 0xE2,
"Shred on Skateboard": 0xE3,
"diamond_bite": 0xE4,
"Grumble": 0xE5,
"Lecture": 0xE6,
"Scow": 0xE7,
"Vent Odor": 0xE8,
"Shout": 0xE9,
"Shriek": 0xEA,
"Knit Brow": 0xEB,
"scatter_spores": 0xED,
"Bite Attack": 0xEE,
"stuffiness_beam": 0xF1,
"Coil Around": 0xF2,
"Emit Light": 0xF8,
"Homesick": 0xFB,
"Fake PSI": 0x0100,
"Bark": 0x0108,
"Chant": 0x0109,
"Scratch Head": 0x010B,
"Discharge Gas": 0x0111,
"Monkey Love": 0x011B,
"Lost Bolts": 0x013A,
"Clean Area": 0x013C,
"Want Battery": 0x013D,
"throw_bomb": 0x01FC,
"shoot_rocket": 0x0203
}
needs_argument = {
"PSI Food": [0xCF, 0xF7, 0x6E, 0xF6, 0x63, 0x62],
"Ruler": [0x8C],
"Protractor": [0x8F],
"Toothbrush": [0x9A],
"Monkey Love": [0xD1],
"Sudden Guts": [0x9F],
"Shield Alpha": [0x1F],
"Shield Beta": [0x21],
"PSI Shield Alpha": [0x23],
"PSI Shield Beta": [0x25],
"Offense Up Alpha": [0x27],
"Offense Up Omega": [0x28],
"Defense Down Alpha": [0x29],
"Defense Down Omega": [0x2A],
"Hypnosis Alpha": [0x2B],
"Hypnosis Omega": [0x2C],
"Brainshock": [0x31],
"Magnet Alpha": [0x2D],
"Magnet Omega": [0x2E],
"Yogurt Dispenser": [0x8B],
"Fake PSI": [0x55, 0x04, 0x14, 0x16, 0x30, 0x32, 0x4D, 0x57]
}
psi_actions = {
"special": 0x0A,
"fire": 0x0E,
"freeze": 0x12,
"thunder": 0x16,
"flash": 0x1A,
"starstorm": 0x1E,
"lifeup": 0x20,
"healing": 0x24,
"Shield Alpha": 0x28,
"Shield Beta": 0x29,
"PSI Shield Alpha": 0x2C,
"PSI Shield Beta": 0x2D,
"Offense Up Alpha": 0x30,
"Offense Up Omega": 0x31,
"Defense Down Alpha": 0x32,
"Defense Down Omega": 0x33,
"Hypnosis Alpha": 0x34,
"Hypnosis Omega": 0x35,
"paralysis": 0x38,
"Brainshock": 0x3A,
"blast": 0x01A4,
"missile": 0x01A8
}
def randomize_enemy_attacks(world: "EarthBoundWorld", rom: "LocalRom") -> None:
"""Generates random attacks for enemies.
Certain attacks need to have an argument variable attached.
PSI moves have a 19% chance of being rolled only if the enemy has a non-zero max PP stat."""
for enemy in world.enemies:
if enemy not in excluded_enemies:
enemy_ai = world.random.randint(0, 3)
world.enemy_psi[enemy] = ["null", "null", "null", "null"]
max_calls = 0
for i in range(4):
if world.enemies[enemy].pp and world.random.randint(1, 100) < 20:
attack = world.random.choice(list(psi_actions.keys()))
attack_id = psi_actions[attack]
else:
attack = world.random.choice(list(battle_actions.keys()))
attack_id = battle_actions[attack]
if attack in spell_breaks:
world.enemy_psi[enemy][i] = attack
if attack in needs_argument:
argument = world.random.choice(needs_argument[attack])
elif attack in ["Sow Seeds", "Call"]:
argument = enemy_ids[enemy]
max_calls = world.random.randint(1, 4)
else:
argument = 0
rom.write_bytes(world.enemies[enemy].address + (0x46 + (i * 2)), struct.pack("H", attack_id))
rom.write_bytes(world.enemies[enemy].address + (0x50 + (i)), bytearray([argument]))
rom.write_bytes(world.enemies[enemy].address + 0x5C, bytearray([max_calls]))
rom.write_bytes(world.enemies[enemy].address + 0x45, bytearray([enemy_ai]))
# Todo; attack extenders?