Implemented Tailwind

Fixed a bug that prevented sided auras (Light Screen, Reflect, Aura Veil, Tailwind, etc.) to be active on both simultaneously, and implemented the move Tailwind
This commit is contained in:
ggiroussens 2024-05-01 13:49:16 +02:00
parent da9d2c8899
commit 84d49d24bb
7 changed files with 41 additions and 15 deletions

View File

@ -77,6 +77,24 @@ export class MistTag extends ArenaTag {
} }
} }
export class TailwindTag extends ArenaTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side);
}
onAdd(arena: Arena): void {
const sideDescriptor = this.side === ArenaTagSide.PLAYER ? '\non your side' : (this.side === ArenaTagSide.ENEMY ? '\non the foe\'s side' : '');
arena.scene.queueMessage(`The tail wind blew from behind ${sideDescriptor}.`);
}
onRemove(arena: Arena): void {
const sideDescriptor = this.side === ArenaTagSide.PLAYER ? '\non your side' : (this.side === ArenaTagSide.ENEMY ? '\non the foe\'s side' : '');
arena.scene.queueMessage(`The tail wind behind ${sideDescriptor} faded.`);
}
}
export class WeakenMoveScreenTag extends ArenaTag { export class WeakenMoveScreenTag extends ArenaTag {
constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide) { constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide) {
super(tagType, turnCount, sourceMove, sourceId, side); super(tagType, turnCount, sourceMove, sourceId, side);
@ -513,5 +531,7 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov
return new LightScreenTag(turnCount, sourceId, side); return new LightScreenTag(turnCount, sourceId, side);
case ArenaTagType.AURORA_VEIL: case ArenaTagType.AURORA_VEIL:
return new AuroraVeilTag(turnCount, sourceId, side); return new AuroraVeilTag(turnCount, sourceId, side);
case ArenaTagType.TAILWIND:
return new TailwindTag(turnCount, sourceId, side);
} }
} }

View File

@ -15,5 +15,6 @@ export enum ArenaTagType {
GRAVITY = "GRAVITY", GRAVITY = "GRAVITY",
REFLECT = "REFLECT", REFLECT = "REFLECT",
LIGHT_SCREEN = "LIGHT_SCREEN", LIGHT_SCREEN = "LIGHT_SCREEN",
AURORA_VEIL = "AURORA_VEIL" AURORA_VEIL = "AURORA_VEIL",
TAILWIND = "TAILWIND"
} }

View File

@ -2821,7 +2821,9 @@ export class AddArenaTagAttr extends MoveEffectAttr {
return false; return false;
if (move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) { if (move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) {
user.scene.arena.addTag(this.tagType, this.turnCount, move.id, user.id, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY); const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
user.scene.arena.addTag(this.tagType, this.turnCount, move.id, user.id, side);
console.log(`Adding tag ${this.tagType} to the side ${side} for ${this.turnCount} turns`);
return true; return true;
} }
@ -2829,8 +2831,8 @@ export class AddArenaTagAttr extends MoveEffectAttr {
} }
getCondition(): MoveConditionFunc { getCondition(): MoveConditionFunc {
return this.failOnOverlap return this.failOnOverlap ?
? (user, target, move) => !user.scene.arena.getTagOnSide(this.tagType, target.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY) (user, target, move) => !user.scene.arena.getTagOnSide(this.tagType, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)
: null; : null;
} }
} }
@ -4780,8 +4782,9 @@ export function initMoves() {
.partial(), .partial(),
new StatusMove(Moves.TAILWIND, Type.FLYING, -1, 15, -1, 0, 4) new StatusMove(Moves.TAILWIND, Type.FLYING, -1, 15, -1, 0, 4)
.windMove() .windMove()
.target(MoveTarget.USER_SIDE) .attr(AddArenaTagAttr, ArenaTagType.TAILWIND, 4, true)
.unimplemented(), .target(MoveTarget.USER_SIDE),
// .unimplemented(),
new StatusMove(Moves.ACUPRESSURE, Type.NORMAL, -1, 30, -1, 0, 4) new StatusMove(Moves.ACUPRESSURE, Type.NORMAL, -1, 30, -1, 0, 4)
.attr(StatChangeAttr, BattleStat.RAND, 2) .attr(StatChangeAttr, BattleStat.RAND, 2)
.target(MoveTarget.USER_OR_NEAR_ALLY), .target(MoveTarget.USER_OR_NEAR_ALLY),

View File

@ -492,7 +492,7 @@ export class Arena {
} }
addTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide = ArenaTagSide.BOTH, targetIndex?: BattlerIndex): boolean { addTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide = ArenaTagSide.BOTH, targetIndex?: BattlerIndex): boolean {
const existingTag = this.getTag(tagType); const existingTag = side === ArenaTagSide.BOTH ? this.getTag(tagType) : this.getTagOnSide(tagType, side);
if (existingTag) { if (existingTag) {
existingTag.onOverlap(this); existingTag.onOverlap(this);
return false; return false;

View File

@ -581,6 +581,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
ret *= 1.5; ret *= 1.5;
break; break;
case Stat.SPD: case Stat.SPD:
if((this.isPlayer() && this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.PLAYER))
|| (!this.isPlayer() && this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.ENEMY))) {
ret *= 2;
}
if (this.getTag(BattlerTagType.SLOW_START)) if (this.getTag(BattlerTagType.SLOW_START))
ret >>= 1; ret >>= 1;
if (this.status && this.status.effect === StatusEffect.PARALYSIS) if (this.status && this.status.effect === StatusEffect.PARALYSIS)

View File

@ -14,10 +14,10 @@ export const STARTING_MONEY_OVERRIDE = 0;
export const WEATHER_OVERRIDE = WeatherType.NONE; export const WEATHER_OVERRIDE = WeatherType.NONE;
export const ABILITY_OVERRIDE = Abilities.NONE; export const ABILITY_OVERRIDE = Abilities.NONE;
export const MOVE_OVERRIDE = Moves.NONE; export const MOVE_OVERRIDE = Moves.TAILWIND;
export const OPP_SPECIES_OVERRIDE = 0; export const OPP_SPECIES_OVERRIDE = 0;
export const OPP_ABILITY_OVERRIDE = Abilities.NONE; export const OPP_ABILITY_OVERRIDE = Abilities.NONE;
export const OPP_MOVE_OVERRIDE = Moves.NONE; export const OPP_MOVE_OVERRIDE = Moves.TAILWIND;
export const OPP_SHINY_OVERRIDE = false; export const OPP_SHINY_OVERRIDE = false;
export const OPP_VARIANT_OVERRIDE = 0; export const OPP_VARIANT_OVERRIDE = 0;

View File

@ -1941,7 +1941,8 @@ export class TurnStartPhase extends FieldPhase {
// Set the priority of the different move command // Set the priority of the different move command
for (let _battlerIndex of moveOrder) { for (let _battlerIndex of moveOrder) {
let command = this.scene.currentBattle.turnCommands[_battlerIndex]; let command = this.scene.currentBattle.turnCommands[_battlerIndex];
command.priority = 6; // Default Command priority for non battling actions
if(command.command === Command.FIGHT) { if(command.command === Command.FIGHT) {
// The command Priority is the Command of the Move // The command Priority is the Command of the Move
let source = this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === _battlerIndex); let source = this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === _battlerIndex);
@ -1953,13 +1954,9 @@ export class TurnStartPhase extends FieldPhase {
applyAbAttrs(IncrementMovePriorityAbAttr, source, null, move, movePriority); applyAbAttrs(IncrementMovePriorityAbAttr, source, null, move, movePriority);
command.priority = movePriority.value; command.priority = movePriority.value;
} }
else {
// The command Priority is +6
command.priority = 6;
}
} }
moveOrder.sort((a, b) => { moveOrder.sort((a, b) => {
// Comparison of the priority Brackets // Comparison of the priority Brackets
const priorityComp = this.scene.currentBattle.turnCommands[b].priority - this.scene.currentBattle.turnCommands[a].priority; const priorityComp = this.scene.currentBattle.turnCommands[b].priority - this.scene.currentBattle.turnCommands[a].priority;