Disguise Changes 2
Added comments as requested. Changed names and conditions. Using now the new once per battle restriction on abilities. New attribute "SpecialOncePerBattleAbilityAbAttr"pull/205/head
parent
90b8f2ac68
commit
ffadd87d22
|
@ -306,17 +306,24 @@ export class ReceivedTypeDamageMultiplierAbAttr extends ReceivedMoveDamageMultip
|
|||
}
|
||||
}
|
||||
|
||||
export class PreDefendReceivedMoveNullifierAbAttr extends PreDefendAbAttr {
|
||||
protected condition: PokemonDefendCondition;
|
||||
|
||||
constructor(condition: PokemonDefendCondition) {
|
||||
super();
|
||||
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
/*
|
||||
Attribute used for the Disguise ability
|
||||
Before getting hit and the ability has not been triggered for the battle nullifies damage from moves.
|
||||
*/
|
||||
export class PreDefendDisguiseNullifyDamageAbAttr extends PreDefendAbAttr {
|
||||
/**
|
||||
* Sets damage received to 1 and hit result as "Effective". Set ability as triggered.
|
||||
* @param {Pokemon} pokemon Pokemon has the ability
|
||||
* @param {Pokemon} passive N/A
|
||||
* @param {Pokemon} attacker N/A.
|
||||
* @param {PokemonMove} move N/A.
|
||||
* @param {any[]} args 0: Damage dealt to user. 1: Hit result type.
|
||||
* @returns {boolean} true if the function succeeds
|
||||
*/
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move.getMove()) && (args[1] as Utils.NumberHolder).value != HitResult.NO_EFFECT && (args[1] as Utils.NumberHolder).value != HitResult.FAIL) {
|
||||
if (pokemon.battleData && !pokemon.battleData.abilitiesApplied.includes(Abilities.DISGUISE) && (args[1] as Utils.NumberHolder).value != HitResult.NO_EFFECT && (args[1] as Utils.NumberHolder).value != HitResult.FAIL) {
|
||||
//Damage dealt is set to 1 as 0 can cause some issues. This 1 damage is subtracted later.
|
||||
console.log(pokemon.battleData);
|
||||
(args[0] as Utils.NumberHolder).value = 1;
|
||||
(args[1] as Utils.NumberHolder).value = HitResult.EFFECTIVE;
|
||||
return true;
|
||||
|
@ -330,6 +337,39 @@ export class PreDefendReceivedMoveNullifierAbAttr extends PreDefendAbAttr {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Attribute used for the Disguise ability
|
||||
When the user is hit by confusion, Disguise triggers.
|
||||
*/
|
||||
export class DisguiseConfusionInteractionAbAttr extends AbAttr {
|
||||
/**
|
||||
* Cancels confusion damage and triggers disguise.
|
||||
* @param {Pokemon} pokemon Pokemon has the ability
|
||||
* @param {Pokemon} passive N/A
|
||||
* @param {Utils.BooleanHolder} damageCancelled If true confusion damage is cancelled.
|
||||
* @param {any[]} args N/A
|
||||
* @returns {boolean} true if the function succeeds
|
||||
*/
|
||||
apply(pokemon: Pokemon, passive: boolean, damageCancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
//This checks if ability has been triggered during battle, and if the current form is correct.
|
||||
if((pokemon.battleData && pokemon.battleData.abilitiesApplied.includes(Abilities.DISGUISE)) || pokemon.formIndex === 1)
|
||||
return false;
|
||||
|
||||
damageCancelled.value = true;
|
||||
const hpLost = Math.round(pokemon.getMaxHp() / 8)
|
||||
pokemon.damageAndUpdate(hpLost, HitResult.OTHER);
|
||||
pokemon.turnData.damageTaken += hpLost;
|
||||
pokemon.battleData.abilitiesApplied.push(Abilities.DISGUISE);
|
||||
pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false);
|
||||
pokemon.scene.queueMessage(`Its disguise served it as a decoy!`);
|
||||
return true;
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
return `${pokemon.name}\'s disguise was busted!`;
|
||||
}
|
||||
}
|
||||
|
||||
export class TypeImmunityAbAttr extends PreDefendAbAttr {
|
||||
private immuneType: Type;
|
||||
private condition: AbAttrCondition;
|
||||
|
@ -455,25 +495,32 @@ export class PostDefendAbAttr extends AbAttr {
|
|||
}
|
||||
}
|
||||
|
||||
export class PostDefendDisguiseAbAttr extends PostDefendAbAttr {
|
||||
protected condition: PokemonDefendCondition;
|
||||
|
||||
constructor(condition: PokemonDefendCondition) {
|
||||
super(true);
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
/*
|
||||
Attribute used for the Disguise ability
|
||||
After getting hit and the ability has not been triggered for the battle inflicts recoil damage on the user.
|
||||
*/
|
||||
export class PostDefendDisguiseRecoilAbAttr extends PostDefendAbAttr {
|
||||
/**
|
||||
* Inflicts 1/8 user's of max HP as recoil when triggered, and sets ability as triggered for the battle.
|
||||
* @param {Pokemon} pokemon Pokemon has the ability
|
||||
* @param {Pokemon} passive N/A
|
||||
* @param {Pokemon} attacker Pokémon that targeted the ability's user.
|
||||
* @param {HitResult} hitResult The result type of the hit, should be "EFFECTIVE".
|
||||
* @param {any[]} args N/A
|
||||
* @returns {boolean} true if the function succeeds
|
||||
*/
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
|
||||
if (this.condition(pokemon, attacker, move.getMove()) && (hitResult == HitResult.EFFECTIVE)) {
|
||||
//If ability has not been triggered during the battle and the hit result is effective...
|
||||
if (pokemon.battleData && !pokemon.battleData.abilitiesApplied.includes(Abilities.DISGUISE) && (hitResult == HitResult.EFFECTIVE)) {
|
||||
//damageDealt is taken into account as it is and not just 1 to prevent issues.
|
||||
const damageDealt = attacker.turnData.damageDealt;
|
||||
let recoilDamage = Math.round(pokemon.getMaxHp() / 8 - damageDealt);
|
||||
if (!recoilDamage)
|
||||
let hpLost = Math.round(pokemon.getMaxHp() / 8 - damageDealt);
|
||||
if (!hpLost )
|
||||
return false;
|
||||
|
||||
pokemon.damageAndUpdate(recoilDamage, HitResult.OTHER);
|
||||
pokemon.battleData.abilityTriggered = true;
|
||||
pokemon.turnData.damageTaken += recoilDamage;
|
||||
pokemon.damageAndUpdate(hpLost , HitResult.OTHER);
|
||||
pokemon.turnData.damageTaken += hpLost;
|
||||
pokemon.battleData.abilitiesApplied.push(Abilities.DISGUISE);
|
||||
pokemon.scene.queueMessage(getPokemonMessage(pokemon, '\'s disguise was busted!'));
|
||||
return true;
|
||||
}
|
||||
|
@ -1724,25 +1771,6 @@ export class BlockNonDirectDamageAbAttr extends AbAttr {
|
|||
}
|
||||
}
|
||||
|
||||
export class DisguiseConfusionDamageInteractionAbAttr extends AbAttr {
|
||||
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
|
||||
if(pokemon.battleData.abilityTriggered == true)
|
||||
return false;
|
||||
|
||||
cancelled.value = true;
|
||||
pokemon.damageAndUpdate(Math.round(pokemon.getMaxHp() / 8), HitResult.OTHER);
|
||||
pokemon.battleData.abilityTriggered = true;
|
||||
pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false);
|
||||
pokemon.scene.queueMessage(`Its disguise served it as a decoy!`);
|
||||
return true;
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
return `${pokemon.name}\'s disguise was busted!`;
|
||||
}
|
||||
}
|
||||
|
||||
export class BlockOneHitKOAbAttr extends AbAttr {
|
||||
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
cancelled.value = true;
|
||||
|
@ -2521,6 +2549,16 @@ export class NoFusionAbilityAbAttr extends AbAttr {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute for to not be pushed to the Pokémon battleData.abilityApplied
|
||||
* This is for abilities that have secondary attributes (like Form Change) that could malfunction.
|
||||
* The ability has to be pushed to battleData.abilityApplied in another attribute.
|
||||
*/
|
||||
export class SpecialOncePerBattleAbilityAbAttr extends AbAttr {
|
||||
constructor() {
|
||||
super(false);
|
||||
}
|
||||
}
|
||||
export class IgnoreTypeImmunityAbAttr extends AbAttr {
|
||||
defenderType: Type;
|
||||
allowedMoveTypes: Type[];
|
||||
|
@ -2571,7 +2609,7 @@ function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: { new(...args: any
|
|||
return applyNextAbAttr();
|
||||
pokemon.scene.setPhaseQueueSplice();
|
||||
const onApplySuccess = () => {
|
||||
if (pokemon.battleData && !pokemon.battleData.abilitiesApplied.includes(ability.id)) {
|
||||
if (pokemon.battleData && !pokemon.battleData.abilitiesApplied.includes(ability.id) && !ability.hasAttr(SpecialOncePerBattleAbilityAbAttr)) {
|
||||
pokemon.battleData.abilitiesApplied.push(ability.id);
|
||||
}
|
||||
if (attr.showAbility && !quiet) {
|
||||
|
@ -3329,18 +3367,19 @@ export function initAbilities() {
|
|||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr),
|
||||
new Ability(Abilities.DISGUISE, 7)
|
||||
.attr(DisguiseConfusionDamageInteractionAbAttr)
|
||||
.attr(PreDefendReceivedMoveNullifierAbAttr, (target, user, move) => target.battleData.abilityTriggered == false)
|
||||
.attr(PostDefendDisguiseAbAttr, (target, user, move) => target.battleData.abilityTriggered == false)
|
||||
.attr(PreDefendFormChangeAbAttr, p => p.battleData.abilityTriggered == false ? 0 : 1)
|
||||
.attr(PostSummonFormChangeAbAttr, p => p.battleData.abilityTriggered == false ? 0 : 1)
|
||||
.attr(PostBattleInitFormChangeAbAttr, p => p.battleData.abilityTriggered == false ? 0 : 1)
|
||||
.attr(PostDefendFormChangeAbAttr, p => p.battleData.abilityTriggered == false ? 0 : 1)
|
||||
.attr(DisguiseConfusionInteractionAbAttr)
|
||||
.attr(PreDefendDisguiseNullifyDamageAbAttr)
|
||||
.attr(PostDefendDisguiseRecoilAbAttr)
|
||||
.attr(PreDefendFormChangeAbAttr, p => p.battleData && !p.battleData.abilitiesApplied.includes(Abilities.DISGUISE) ? 0 : 1)
|
||||
.attr(PostSummonFormChangeAbAttr, p => p.battleData && !p.battleData.abilitiesApplied.includes(Abilities.DISGUISE) ? 0 : 1)
|
||||
.attr(PostBattleInitFormChangeAbAttr, p => p.battleData && !p.battleData.abilitiesApplied.includes(Abilities.DISGUISE) ? 0 : 1)
|
||||
.attr(PostDefendFormChangeAbAttr, p => p.battleData && !p.battleData.abilitiesApplied.includes(Abilities.DISGUISE) ? 0 : 1)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.attr(SpecialOncePerBattleAbilityAbAttr)
|
||||
.ignorable()
|
||||
.partial(),
|
||||
new Ability(Abilities.BATTLE_BOND, 7)
|
||||
|
|
|
@ -8,7 +8,7 @@ import * as Utils from "../utils";
|
|||
import { Moves } from "./enums/moves";
|
||||
import { ChargeAttr, MoveFlags, allMoves } from "./move";
|
||||
import { Type } from "./type";
|
||||
import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, ReverseDrainAbAttr, applyAbAttrs, DisguiseConfusionDamageInteractionAbAttr } from "./ability";
|
||||
import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, ReverseDrainAbAttr, applyAbAttrs, DisguiseConfusionInteractionAbAttr } from "./ability";
|
||||
import { Abilities } from "./enums/abilities";
|
||||
import { BattlerTagType } from "./enums/battler-tag-type";
|
||||
import { TerrainType } from "./terrain";
|
||||
|
@ -227,10 +227,10 @@ export class ConfusedTag extends BattlerTag {
|
|||
const damage = Math.ceil(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * (pokemon.randSeedInt(15, 85) / 100));
|
||||
pokemon.scene.queueMessage('It hurt itself in its\nconfusion!');
|
||||
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
applyAbAttrs(DisguiseConfusionDamageInteractionAbAttr, pokemon, cancelled);
|
||||
|
||||
if (!cancelled.value) {
|
||||
const damageCancelled = new Utils.BooleanHolder(false);
|
||||
applyAbAttrs(DisguiseConfusionInteractionAbAttr, pokemon, damageCancelled);
|
||||
//Confusion damage will not be dealt if Pokémon has Disguise and has not triggered.
|
||||
if (!damageCancelled.value) {
|
||||
pokemon.damageAndUpdate(damage);
|
||||
pokemon.battleData.hitCount++;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import { TempBattleStat } from '../data/temp-battle-stat';
|
|||
import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag';
|
||||
import { ArenaTagType } from "../data/enums/arena-tag-type";
|
||||
import { Biome } from "../data/enums/biome";
|
||||
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, PreDefendReceivedMoveNullifierAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr } from '../data/ability';
|
||||
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, PreDefendDisguiseNullifyDamageAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr } from '../data/ability';
|
||||
import { Abilities } from "#app/data/enums/abilities";
|
||||
import PokemonData from '../system/pokemon-data';
|
||||
import Battle, { BattlerIndex } from '../battle';
|
||||
|
@ -1444,8 +1444,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
damage.value = 0;
|
||||
}
|
||||
|
||||
//All incoming damage from moves will be set to 1 if the target is a Disguise user.
|
||||
let preResult = new Utils.NumberHolder(result);
|
||||
applyPreDefendAbAttrs(PreDefendReceivedMoveNullifierAbAttr, this, source, battlerMove, cancelled, damage , preResult);
|
||||
applyPreDefendAbAttrs(PreDefendDisguiseNullifyDamageAbAttr, this, source, battlerMove, cancelled, damage , preResult);
|
||||
result = (preResult as Utils.NumberHolder).value;
|
||||
|
||||
console.log('damage', damage.value, move.name, power.value, sourceAtk, targetDef);
|
||||
|
|
|
@ -1616,7 +1616,7 @@ export class TurnInitPhase extends FieldPhase {
|
|||
this.scene.currentBattle.addParticipant(pokemon as PlayerPokemon);
|
||||
|
||||
pokemon.resetTurnData();
|
||||
|
||||
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon);
|
||||
this.scene.pushPhase(pokemon.isPlayer() ? new CommandPhase(this.scene, i) : new EnemyCommandPhase(this.scene, i - BattlerIndex.ENEMY));
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue