mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-07 07:03:44 -08:00
* 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>
237 lines
6.8 KiB
Python
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?
|