Spaces:
Running
Running
This is a pseudocode overview of how Pokémon Showdown works - particularly relevant to anyone writing event code. | |
(A) = negated by Mold Breaker (and Turboblaze/Teravolt) on abilities only during a move | |
(S) = negated by Sheer Force only during a move with a secondary effect | |
(U) = negated by Substitute | |
(Air Lock and Klutz negates every event for the corresponding effect, so don't need to be marked) | |
=== MOVES === | |
A quick overview of how moves work: | |
STEP 1. MOVE PRE-USAGE | |
external execution interruption (flinch, full paralysis) | |
"POKEMON used MOVE!" | |
STEP 2: MOVE USAGE | |
internal execution interruption (charge turn for SolarBeam etc) | |
move start of sub-move (Metronome, Sleep Talk etc) | |
PP deduction | |
STEP 3. MOVE EXECUTION (sub-moves start from here) | |
there is no target | |
internal move failure ("But it failed!") | |
STEP 4. MOVE HIT (happens once per target) | |
move misses | |
external move failure (Protect, Substitute blocked etc) | |
immunity | |
move animation | |
damage | |
other effects | |
secondary effects | |
=== MAIN LOOP === | |
[BeforeTurn] | |
for every move: | |
[ModifyPriority] | |
move's [BeforeTurn] | |
runAction() - runs runSwitch, runAfterSwitch, and runMove in priority order, then residual at end { | |
runSwitch() { | |
[BeforeSwitch] | |
switch | |
} | |
runAfterSwitch() - after all pokemon are switched in { | |
[Switch] | |
ability's [Start] | |
item's [Start] | |
} | |
runMove() { | |
[BeforeMove] (A) | |
-> false => exit runMove | |
display "POKEMON used MOVE!" | |
useMove() { | |
[ModifyMove] (A) | |
if no targets: | |
display "But there was no target..." and exit useMove() | |
moveHit() - once for each hit of multi-hit move, and also once for secondary hits { | |
move's [TryHit], [TryHitSide] or [TryHitField] (A) | |
if hit: | |
[TryHit] (A) | |
-> 0 => skip to SelfHit (used for Substitute) | |
-> null => exit moveHit() | |
-> false => display "But it failed!" and exit moveHit() | |
[Immunity] (A) | |
-> null => exit moveHit() | |
-> false => display "It had no effect!" and exit moveHit() | |
move animation | |
getDamage() { | |
move's [BasePower] | |
[BasePower] (A) | |
move's [Damage] | |
if critical hit: | |
[CriticalHit] (A) | |
} | |
damage() { | |
[Damage] (A,U) | |
-> false => exit damage() | |
damage | |
} | |
heal() { | |
[Heal] (A) | |
-> false => exit heal() | |
heal | |
} | |
status() (U) { | |
[Status] (A) | |
-> false => exit status() | |
status change | |
status's [Start] (A) | |
-> false => restore previous status and exit status() | |
[AfterStatus] | |
} | |
effect() (U) { | |
if effect already exists: | |
effect's [Restart] (A) | |
otherwise: | |
effect change | |
effect's [Start] (A) | |
-> false => remove effect and exit effect() | |
} | |
recoil() { | |
call damage() | |
} | |
drain() { | |
call heal() | |
} | |
if hit: | |
[SelfHit] (A) | |
if secondary hit: | |
[SecondarySelfHit] (A) | |
if hit: | |
if secondary roll succeeds: | |
secondary() (S,U) { | |
call moveHit() | |
} | |
} | |
[AfterMoveSecondary] (S,U) | |
[AfterMoveSecondarySelf] (S) | |
[AfterMove] | |
} | |
pp deducted | |
} | |
runFaint() { | |
[Faint] | |
} | |
residual() { | |
for every effect: | |
if duration = 0: | |
effect's [End] | |
remove effect | |
otherwise: | |
effect's [Residual] | |
} | |
choose switch-ins for fainted pokemon | |
=> runSwitch() and runAfterSwitch() again | |
[Update] | |
} | |
=== ISOLATED === | |
These are not part of the main loop, and are only called from inside an event. | |
(For instance, eatItem() is usually called from within the Update event of a berry, and weather() is called | |
from the Residual event of a weather condition) | |
eatItem() { | |
[UseItem] (A) | |
-> false => exit EatItem() | |
[EatItem] (A) | |
-> false => exit EatItem() | |
item's [Eat] | |
remove item from pokemon | |
} | |
useItem() { | |
[UseItem] (A) | |
-> false => exit UseItem() | |
remove item from pokemon | |
} | |
takeItem() { | |
[TakeItem] (A) | |
-> false => exit TakeItem() | |
remove item from pokemon | |
} | |
setItem() { | |
set item | |
item's [Start] | |
} | |
setAbility() { | |
set ability | |
ability's [Start] | |
} | |
weather() { | |
[Weather] | |
} | |