From fe298c39e2c2dfb14fcd3e4ebb166f1559489a25 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Sun, 30 Apr 2023 23:58:16 -0400 Subject: [PATCH] Add tall grass BG and fix a hanging bug with charge moves --- public/images/arenas/tall_grass_a.png | Bin 0 -> 1424 bytes public/images/arenas/tall_grass_b.png | Bin 0 -> 2774 bytes public/images/arenas/tall_grass_bg.png | Bin 0 -> 640 bytes src/arena.ts | 2 - src/battle-phases.ts | 55 ++++++++++++++----------- src/data/ability.ts | 5 ++- src/pokemon.ts | 16 +++---- src/ui/fight-ui-handler.ts | 2 +- 8 files changed, 44 insertions(+), 36 deletions(-) create mode 100644 public/images/arenas/tall_grass_a.png create mode 100644 public/images/arenas/tall_grass_b.png create mode 100644 public/images/arenas/tall_grass_bg.png diff --git a/public/images/arenas/tall_grass_a.png b/public/images/arenas/tall_grass_a.png new file mode 100644 index 0000000000000000000000000000000000000000..5fa1421903d723964c5a6c62e5b94d26d2f2edee GIT binary patch literal 1424 zcmd6n{Xf$Q0LQ;XT%LPC8Lsup(~MCvt=BxKVcg+vJ9$`ch4OGK^SGz7$>Xhi5lhA0 z%R?eh#nzCAv8EEmu8i23`~2|vygxsEe*5Hn7vQ6_@5nv?0CZ62 zyn+Bg#ZAd{&Am#WD*Mu*43%p^J{~~BAZT7$)S}(d?f}rt)Y`tF4gl)kqP*NgQX>|} zx)Mz;g1V<5-tmPN>a`)h`q0`MFFxSM_l3_I`{Q#K^TPm4&N+_NE4O~v{93?Cv<(v0Zm8<_Bv5MA_l#~;lFYCIC z(yKf0Mml>lB?FA$Uj1TcmEd!LWy~0OqvyeL;&V(IF|caZ5ju1;69wpHYpy)R%)Y#m zVd-sO=0}>?l_qodmUVc}9ET1cT;IXCuBJb;qio1N$x|Zi8V~VX%M)djY}9z=>Y|aD zNLk)E90k^KriL%JzE1ERa%FzLZLYAgBVQ9C`^%cYuHCxv&KdtFkR>RHV38N44S|>a=hyyqf2}3;h+smT>Xx$ib#cXtzXg5&=Wt zkUja1a(Z=+-HT)Un{xuMOI3}d+Oe(;B9Un7CL|o}dj)c3rnO!VzmVkJ1fg&jLPUmf zD)=LyY*UzPw%|Umw7Tt<048~N=wXtA;0gCtoA%5?4n<$0RHt6tNlo)>-%32$MY4_y zAE^Z#b;>qPn@;zv-bs}>q65<^OI2BZg!6D$%)sDl?UK9sCcI7+?b!Ws?TVa8cGfgk zet^Fnw$;LU+!p$%;e)xIGefx~1M!)$DN1+{9$ERMBfhMf_+BeFhKHjoo?4_?ckXqr@_p6oA|Q0Pn7de?_~b#Y?^w1j<NIe zY~)gyH9cCK{!m8C)y!HogfMY;XGZSw2efWx1X>Eq~ApOY>ea qFM8EI-2@7Lqr5QPi&)epG#ao`vgUu6HXK~|FQL2xyc#@kH~s-(BXGX} literal 0 HcmV?d00001 diff --git a/public/images/arenas/tall_grass_b.png b/public/images/arenas/tall_grass_b.png new file mode 100644 index 0000000000000000000000000000000000000000..39d23a2247f0a0f35dd14abf3bb2e036ed3e7681 GIT binary patch literal 2774 zcmcIm`#%$G8z1RSL{scpjIdXd=;7hnR?H!DKIPEl!FY7QXcjgr8+oL{tWqela(X;r zB4=ijLvkE3=hYmS!*VtauRfpmPk7(^hx__oKYXw6{kcEa^}X+h&W=_xQi@Ul06@mZ z+QJ0@5HsD!agzVq-@j(9)b9teFc&Lx0HYhi-%liNm^qjM0Hri(k>5c8KVXpgEa+{VOk$I` z8rvOYrXUmK5@0@1Eo+0nNPkXRphqKT$1ZFr-&xxF@wn*39mZ^TQUoh($(XYtv9JDr zT8*Jd7)#=9Hf5{-q|r;v%k7<#y+*WNESw$`C|$WAzf`c1drD==gOS-6jfA6^!LcXSS& zJFQ!EIdo#DgEh-Zwp!|hY||Qm)_-q8tb!Au?qraeV%`qA00mE z%B60nv9_-0ISZJ(p_E1EWUpj*typifL~egYQ8S=*ZaSu_NtusaWBx+EO8QAj@#g`j zB;iqLA|aoCgD7Z#F-3D3RxoO0be`|aQ?cG12p3rl-9N7QErQYqi!s?1((>nb7fUFd znuYYDffTV@_Phskb?54RWH4)?L}J;G?>YQ+7s<_yjZ=BP!pb7;*oq%1ZB84S0@jZ2 zZKl&!E>0BA6^MlNmtt-rpWTse&t%YH)j``3gY^Y&mLmhRw<3CXGvQTKs9<7kr9ES` z-|kX*klq`VbI{|_QL@4C$Z%#f!5Z@mH-AAHW(}v3B!M2n%hIdA?qn%vm^7zQe z3yd~RL z%}M58l4qQsK%cdMN98Tw615~#Lzwj~&?s6GW&spAu%X=Y)cE*A1NFdVHkjLM@5FJS5~87*yg zFYezSDo>-$NuGWb=aUu8{4V6rs=Ou{%LaSRl>aGFAuV_wRQ&FD>^MqpP~yR7pZ)?+ zV|C$}Lc6;K0MD=$D|h)E?p288INnO{gc>>BELR`WjLD9;R=h`7f z=AiHQdYT#W1N4@3OFHz-#UF$XNWDVDAq%*(;1>tLn#h%IC=S5$ zf=4}8pK~?NHIPb#T%hx^Wk%FiL+~8E+8^Ki0`d&rJgFX=S$&t@3NGhet}C9-<<6=$ zYnDV%;7M|yd50X^vy{Hw%rj|rct9l^kPPX_*z6e=ATS62$p8aRu z?3_*JxO-9gU6XgEdNrbZlhIYMp6|Cm5JlUqH*u6>6(LUK}KUST$9*tpvnG8V$eRYGEfg!Q6+K#qD>0yT^za)sG}M?1@MY z6A|b&TbeN!_msmOxq7>_doaZUh~jU#;2aEOds?M{B#uyO(ynt++V${h@Tdsbf`;u7LU=-bkA zBWES1_T$ehQv#@rNo=YWhX+&DVpbwGELSiuuAn4Y(Y&e@UfbEDLXmDGJJaV-rwF-9Kq@z!1)Pwhva>_E4y*15xjaGW^ zp|$VNy2S;}qqzh+X@4MsxoukB-1*TkK#nN?N%R3LUa2|jeW<#@TL8*AEwQ;rX{}Vo zILTKfdWC;=UTD|F^Wn~j& z)^0>9JB_kANn&c?hfl{Bhu0x#9cQyQ(rxGYljE#iEM@VLC27}LB)Wf8eQ&H4Y@!we z{{<1Xdd|rybD(vqB+#F58j^@y?q}p6w|C8Y6iYa?oIEUot6RIa`fxjWmq)%vJ}FR_ zH`(!uukUeh)cw`+{a&2ao(2QNs>W|9D-VjFAPUsmst9#~H7;LrBmSTRzLBCbD=Jpv9gaBhy-^QCs^sJZ}UUi4W3 z23@$5*w?pIOaawG<{2e&rb+Rz^V%U%6?^(={=+Yfks-d0{&RrAKhY@|mM4I7P^{Tg zE2J@-I#kEro;;Fgopoa?`?7@L?e(~Olc!`eGiQzhn>o1gpKl|!WxvO{Yqq@!S5>Z! zlo3eSAUU_(G}4$3axa2L2bvZ=L$>9&>VIN~waa-C0Ou5ati9k;uZSnnm2 La5jgR z3=A9lx&I`xGB7X+c)B=-RK&f#yO8&g14G+IIq!!nRvz8J(Z+f%VWY|$heIMd2lWze zJgPpw;ox-pz279hUw^)vf#vPL{S1~&94VX%6I2@^Vr1Ds54!W zAyN#k(66ykhg;x;kb}bMYy*dBtQ;wpER36U92C5PN*P%;v4G_Wa*qA{RU)r2A%zia z^-dxA6CkVF6~HEl$9 Sa4C2)i1Kvxb6Mw<&;$StZ@Q!a literal 0 HcmV?d00001 diff --git a/src/arena.ts b/src/arena.ts index bd7908d75ff..cfe224e00a3 100644 --- a/src/arena.ts +++ b/src/arena.ts @@ -99,8 +99,6 @@ export class Arena { getBiomeKey(): string { switch (this.biomeType) { - case Biome.TALL_GRASS: - return 'grass'; case Biome.CITY: return 'dojo'; case Biome.LAKE: diff --git a/src/battle-phases.ts b/src/battle-phases.ts index ea1e8145b7e..e85cd412302 100644 --- a/src/battle-phases.ts +++ b/src/battle-phases.ts @@ -25,7 +25,7 @@ import { Gender } from "./data/gender"; import { Weather, WeatherType, getRandomWeatherType, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather"; import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTrapTag, TrickRoomTag } from "./data/arena-tag"; -import { PostWeatherLapseAbAttr, PreWeatherDamageAbAttr, ProtectStatAttr, SuppressWeatherEffectAbAttr, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreWeatherEffectAbAttrs } from "./data/ability"; +import { ArenaTrapAbAttr, PostWeatherLapseAbAttr, PreWeatherDamageAbAttr, ProtectStatAttr, SuppressWeatherEffectAbAttr, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreWeatherEffectAbAttrs } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; export class CheckLoadPhase extends BattlePhase { @@ -596,11 +596,11 @@ export class CommandPhase extends FieldPhase { if (moveQueue.length) { const queuedMove = moveQueue[0]; if (!queuedMove.move) - this.handleCommand(Command.FIGHT, -1); + this.handleCommand(Command.FIGHT, -1, false); else { const moveIndex = playerPokemon.moveset.findIndex(m => m.moveId === queuedMove.move); - if (playerPokemon.moveset[moveIndex].isUsable(queuedMove.ignorePP)) - this.handleCommand(Command.FIGHT, moveIndex); + if (moveIndex > -1 && playerPokemon.moveset[moveIndex].isUsable(queuedMove.ignorePP)) + this.handleCommand(Command.FIGHT, moveIndex, queuedMove.ignorePP); } } else this.scene.ui.setMode(Mode.COMMAND); @@ -614,9 +614,9 @@ export class CommandPhase extends FieldPhase { let isDelayed = (command: Command, playerMove: PokemonMove, enemyMove: PokemonMove) => { switch (command) { case Command.FIGHT: - if (playerMove && enemyMove) { - const playerMovePriority = playerMove.getMove().priority; - const enemyMovePriority = enemyMove.getMove().priority; + if (playerMove || enemyMove) { + const playerMovePriority = playerMove?.getMove()?.priority || 0; + const enemyMovePriority = enemyMove?.getMove()?.priority || 0; if (playerMovePriority !== enemyMovePriority) return playerMovePriority < enemyMovePriority; } @@ -641,9 +641,9 @@ export class CommandPhase extends FieldPhase { break; } - if (playerPokemon.trySelectMove(cursor)) { + if (playerPokemon.trySelectMove(cursor, args[0] as boolean)) { playerMove = playerPokemon.moveset[cursor]; - const playerPhase = new PlayerMovePhase(this.scene, playerPokemon, playerMove); + const playerPhase = new PlayerMovePhase(this.scene, playerPokemon, playerMove, false, args[0] as boolean); this.scene.pushPhase(playerPhase); success = true; } else if (cursor < playerPokemon.moveset.length) { @@ -673,12 +673,13 @@ export class CommandPhase extends FieldPhase { break; case Command.POKEMON: const trapTag = playerPokemon.findTag(t => t instanceof TrappedTag) as TrappedTag; + const arenaTrapped = !!enemyPokemon.getAbility().getAttrs(ArenaTrapAbAttr).length; const batonPass = args[0] as boolean; - if (batonPass || !trapTag) { + if (batonPass || (!trapTag && !arenaTrapped)) { this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, cursor, true, args[0] as boolean)); success = true; } else - this.scene.ui.showText(`${this.scene.getPokemonById(trapTag.sourceId).name}'s ${trapTag.getMoveName()}\nprevents switching!`, null, () => { + this.scene.ui.showText(`${this.scene.getPokemonById(trapTag.sourceId).name}'s ${trapTag?.getMoveName() || enemyPokemon.getAbility().name}\nprevents switching!`, null, () => { this.scene.ui.showText(null, 0); }, null, true); break; @@ -692,19 +693,23 @@ export class CommandPhase extends FieldPhase { if (this.scene.arena.weather) this.scene.unshiftPhase(new WeatherEffectPhase(this.scene, this.scene.arena.weather)); - const enemyMove = enemyPokemon.getNextMove(); - const enemyPhase = new EnemyMovePhase(this.scene, enemyPokemon, enemyMove); - if (isDelayed(command, playerMove, enemyMove)) - this.scene.unshiftPhase(enemyPhase); - else - this.scene.pushPhase(enemyPhase); + const enemyNextMove = enemyPokemon.getNextMove(); + let enemyMove: PokemonMove; + if (enemyNextMove.move) { + enemyMove = enemyPokemon.moveset.find(m => m.moveId === enemyNextMove.move) || new PokemonMove(enemyNextMove.move, 0, 0); + const enemyPhase = new EnemyMovePhase(this.scene, enemyPokemon, enemyMove, false, enemyNextMove.ignorePP); + if (isDelayed(command, playerMove, enemyMove)) + this.scene.unshiftPhase(enemyPhase); + else + this.scene.pushPhase(enemyPhase); + } const statusEffectPhases: PostTurnStatusEffectPhase[] = []; if (playerPokemon.status && playerPokemon.status.isPostTurn()) statusEffectPhases.push(new PostTurnStatusEffectPhase(this.scene, true)); if (enemyPokemon.status && enemyPokemon.status.isPostTurn()) { const enemyStatusEffectPhase = new PostTurnStatusEffectPhase(this.scene, false); - if (isDelayed(command, playerMove, enemyMove)) + if (this.isPlayerDelayed()) statusEffectPhases.unshift(enemyStatusEffectPhase); else statusEffectPhases.push(enemyStatusEffectPhase); @@ -837,21 +842,23 @@ export abstract class MovePhase extends BattlePhase { protected pokemon: Pokemon; protected move: PokemonMove; protected followUp: boolean; + protected ignorePp: boolean; protected cancelled: boolean; - constructor(scene: BattleScene, pokemon: Pokemon, move: PokemonMove, followUp?: boolean) { + constructor(scene: BattleScene, pokemon: Pokemon, move: PokemonMove, followUp?: boolean, ignorePp?: boolean) { super(scene); this.pokemon = pokemon; this.move = move; this.followUp = !!followUp; + this.ignorePp = !!ignorePp; this.cancelled = false; } abstract getEffectPhase(): MoveEffectPhase; canMove(): boolean { - return !!this.pokemon.hp && this.move.isUsable(); + return !!this.pokemon.hp && this.move.isUsable(this.ignorePp); } cancel(): void { @@ -955,8 +962,8 @@ export abstract class MovePhase extends BattlePhase { } export class PlayerMovePhase extends MovePhase { - constructor(scene: BattleScene, pokemon: PlayerPokemon, move: PokemonMove, followUp?: boolean) { - super(scene, pokemon, move, followUp); + constructor(scene: BattleScene, pokemon: PlayerPokemon, move: PokemonMove, followUp?: boolean, ignorePp?: boolean) { + super(scene, pokemon, move, followUp, ignorePp); } getEffectPhase(): MoveEffectPhase { @@ -965,8 +972,8 @@ export class PlayerMovePhase extends MovePhase { } export class EnemyMovePhase extends MovePhase { - constructor(scene: BattleScene, pokemon: EnemyPokemon, move: PokemonMove, followUp?: boolean) { - super(scene, pokemon, move, followUp); + constructor(scene: BattleScene, pokemon: EnemyPokemon, move: PokemonMove, followUp?: boolean, ignorePp?: boolean) { + super(scene, pokemon, move, followUp, ignorePp); } getEffectPhase(): MoveEffectPhase { diff --git a/src/data/ability.ts b/src/data/ability.ts index bf79a643853..f91fb4d1380 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -247,6 +247,8 @@ export class ProtectStatAttr extends PreStatChangeAbAttr { } } +export class ArenaTrapAbAttr extends AbAttr { } + export class PreWeatherEffectAbAttr extends AbAttr { applyPreWeatherEffect(pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { return false; @@ -636,7 +638,8 @@ export function initAbilities() { abilities.push( new Ability(Abilities.AIR_LOCK, "Air Lock", "Eliminates the effects of all weather.", 3) .attr(SuppressWeatherEffectAbAttr, true), - new Ability(Abilities.ARENA_TRAP, "Arena Trap (N)", "Prevents the foe from fleeing.", 3), + new Ability(Abilities.ARENA_TRAP, "Arena Trap", "Prevents the foe from fleeing.", 3) + .attr(ArenaTrapAbAttr), new Ability(Abilities.BATTLE_ARMOR, "Battle Armor (N)", "The POKéMON is protected against critical hits.", 3), new Ability(Abilities.BLAZE, "Blaze", "Powers up FIRE-type moves in a pinch.", 3) .attr(LowHpMoveTypePowerBoostAbAttr, Type.FIRE), diff --git a/src/pokemon.ts b/src/pokemon.ts index 48f0c393982..dae33b8673a 100644 --- a/src/pokemon.ts +++ b/src/pokemon.ts @@ -431,11 +431,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - trySelectMove(moveIndex: integer): boolean { + trySelectMove(moveIndex: integer, ignorePp?: boolean): boolean { const move = this.moveset.length > moveIndex ? this.moveset[moveIndex] : null; - return move?.isUsable(); + return move?.isUsable(ignorePp); } showInfo() { @@ -991,13 +991,13 @@ export class EnemyPokemon extends Pokemon { } } - getNextMove(): PokemonMove { + getNextMove(): QueuedMove { const queuedMove = this.getMoveQueue().length ? this.moveset.find(m => m.moveId === this.getMoveQueue()[0].move) : null; if (queuedMove) { if (queuedMove.isUsable(this.getMoveQueue()[0].ignorePP)) - return queuedMove; + return { move: queuedMove.moveId, ignorePP: this.getMoveQueue()[0].ignorePP }; else { this.getMoveQueue().shift(); return this.getNextMove(); @@ -1007,10 +1007,10 @@ export class EnemyPokemon extends Pokemon { const movePool = this.moveset.filter(m => m.isUsable()); if (movePool.length) { if (movePool.length === 1) - return movePool[0]; + return { move: movePool[0].moveId }; switch (this.aiType) { case AiType.RANDOM: - return movePool[Utils.randInt(movePool.length)]; + return { move: movePool[Utils.randInt(movePool.length)].moveId }; case AiType.SMART_RANDOM: case AiType.SMART: const target = this.scene.getPlayerPokemon(); @@ -1072,11 +1072,11 @@ export class EnemyPokemon extends Pokemon { r++; } console.log(movePool.map(m => m.getName()), moveScores, r, sortedMovePool.map(m => m.getName())); - return sortedMovePool[r]; + return { move: sortedMovePool[r].moveId }; } } - return new PokemonMove(Moves.STRUGGLE, 0, 0); + return { move: Moves.STRUGGLE }; } isPlayer() { diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index 94d7e1c8257..2757d50feb8 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -49,7 +49,7 @@ export default class FightUiHandler extends UiHandler { if (button === Button.CANCEL || button === Button.ACTION) { if (button === Button.ACTION) { - if ((this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, this.cursor)) + if ((this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, this.cursor, false)) success = true; else ui.playError();