From e15eef6a025af42d1d090d7c958513586b494a28 Mon Sep 17 00:00:00 2001 From: Hisuian Zoroark <96159984+HisuianZoroark@users.noreply.github.com> Date: Sun, 18 Feb 2024 01:33:26 -0500 Subject: [PATCH] this fucking sucks lmao --- data/mods/gen9ssb/conditions.ts | 8 ++- data/mods/gen9ssb/scripts.ts | 96 +++++++++++++++++++++++++++++++++ sim/global-types.ts | 3 ++ 3 files changed, 105 insertions(+), 2 deletions(-) diff --git a/data/mods/gen9ssb/conditions.ts b/data/mods/gen9ssb/conditions.ts index c9989eea9..9e4152ff4 100644 --- a/data/mods/gen9ssb/conditions.ts +++ b/data/mods/gen9ssb/conditions.ts @@ -25,11 +25,15 @@ export const Conditions: {[k: string]: ModdedConditionData & {innateName?: strin onStart() { this.add(`c:|${getName('aegii')}|**It is now aegii's turn to beat you down.**`); }, - onSwitchOut(pokemon) { + // @ts-ignore Support peeking at new pokemon + onSwitchOut(source, pokemon) { + // @ts-ignore if (this.randomChance(2, 100)) { + // @ts-ignore this.add(`c:|${getName('aegii')}|...right, I was saying in SSB4 to "stan loona", but this has to be changed now that we've found out that the company managing loona is shady af. I would like to amend that to "stan the individual members of loona" (or if you want, you can choose to stan any other group of your choice!)`); } else { - this.add(`c:|${getName('aegii')}|~yes ${pokemon.side.active[0]}`); + // @ts-ignore + this.add(`c:|${getName('aegii')}|~yes ${pokemon.name}`); } }, onFaint() { diff --git a/data/mods/gen9ssb/scripts.ts b/data/mods/gen9ssb/scripts.ts index 7358c73c1..240dffa5b 100644 --- a/data/mods/gen9ssb/scripts.ts +++ b/data/mods/gen9ssb/scripts.ts @@ -971,6 +971,102 @@ export const Scripts: ModdedBattleScriptsData = { } return hitResults; }, + switchIn(pokemon, pos, sourceEffect, isDrag) { + if (!pokemon || pokemon.isActive) { + this.battle.hint("A switch failed because the Pokémon trying to switch in is already in."); + return false; + } + + const side = pokemon.side; + if (pos >= side.active.length) { + throw new Error(`Invalid switch position ${pos} / ${side.active.length}`); + } + const oldActive = side.active[pos]; + const unfaintedActive = oldActive?.hp ? oldActive : null; + if (unfaintedActive) { + oldActive.beingCalledBack = true; + let switchCopyFlag: 'copyvolatile' | 'shedtail' | boolean = false; + if (sourceEffect && typeof (sourceEffect as Move).selfSwitch === 'string') { + switchCopyFlag = (sourceEffect as Move).selfSwitch!; + } + if (!oldActive.skipBeforeSwitchOutEventFlag && !isDrag) { + this.battle.runEvent('BeforeSwitchOut', oldActive); + if (this.battle.gen >= 5) { + this.battle.eachEvent('Update'); + } + } + oldActive.skipBeforeSwitchOutEventFlag = false; + if (!this.battle.runEvent('SwitchOut', oldActive, pokemon)) { + // Warning: DO NOT interrupt a switch-out if you just want to trap a pokemon. + // To trap a pokemon and prevent it from switching out, (e.g. Mean Look, Magnet Pull) + // use the 'trapped' flag instead. + + // Note: Nothing in the real games can interrupt a switch-out (except Pursuit KOing, + // which is handled elsewhere); this is just for custom formats. + return false; + } + if (!oldActive.hp) { + // a pokemon fainted from Pursuit before it could switch + return 'pursuitfaint'; + } + + // will definitely switch out at this point + + oldActive.illusion = null; + this.battle.singleEvent('End', oldActive.getAbility(), oldActive.abilityState, oldActive); + + // if a pokemon is forced out by Whirlwind/etc or Eject Button/Pack, it can't use its chosen move + this.battle.queue.cancelAction(oldActive); + + let newMove = null; + if (this.battle.gen === 4 && sourceEffect) { + newMove = oldActive.lastMove; + } + if (switchCopyFlag) { + pokemon.copyVolatileFrom(oldActive, switchCopyFlag); + } + if (newMove) pokemon.lastMove = newMove; + oldActive.clearVolatile(); + } + if (oldActive) { + oldActive.isActive = false; + oldActive.isStarted = false; + oldActive.usedItemThisTurn = false; + oldActive.statsRaisedThisTurn = false; + oldActive.statsLoweredThisTurn = false; + oldActive.position = pokemon.position; + pokemon.position = pos; + side.pokemon[pokemon.position] = pokemon; + side.pokemon[oldActive.position] = oldActive; + } + pokemon.isActive = true; + side.active[pos] = pokemon; + pokemon.activeTurns = 0; + pokemon.activeMoveActions = 0; + for (const moveSlot of pokemon.moveSlots) { + moveSlot.used = false; + } + this.battle.runEvent('BeforeSwitchIn', pokemon); + if (sourceEffect) { + this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getDetails, '[from] ' + sourceEffect); + } else { + this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getDetails); + } + pokemon.abilityOrder = this.battle.abilityOrder++; + if (isDrag && this.battle.gen === 2) pokemon.draggedIn = this.battle.turn; + pokemon.previouslySwitchedIn++; + + if (isDrag && this.battle.gen >= 5) { + // runSwitch happens immediately so that Mold Breaker can make hazards bypass Clear Body and Levitate + this.battle.singleEvent('PreStart', pokemon.getAbility(), pokemon.abilityState, pokemon); + this.runSwitch(pokemon); + } else { + this.battle.queue.insertChoice({choice: 'runUnnerve', pokemon}); + this.battle.queue.insertChoice({choice: 'runSwitch', pokemon}); + } + + return true; + }, }, pokemon: { isGrounded(negateImmunity) { diff --git a/sim/global-types.ts b/sim/global-types.ts index ae944bd46..41d8b5b6f 100644 --- a/sim/global-types.ts +++ b/sim/global-types.ts @@ -273,6 +273,9 @@ interface ModdedBattleActions { this: BattleActions, targets: SpreadMoveTargets, pokemon: Pokemon, move: ActiveMove, moveData?: ActiveMove, isSecondary?: boolean, isSelf?: boolean ) => [SpreadMoveDamage, SpreadMoveTargets]; + switchIn?: ( + this: BattleActions, pokemon: Pokemon, pos: number, sourceEffect: Effect | null, isDrag?: boolean + ) => string | boolean; targetTypeChoices?: (this: BattleActions, targetType: string) => boolean; terastallize?: (this: BattleActions, pokemon: Pokemon) => void; tryMoveHit?: (