Merge dcecd4fab7 into a5bafe5c47
commit
5d03144842
|
|
@ -126,6 +126,7 @@ export default class BattleScene extends SceneBase {
|
||||||
public gameData: GameData;
|
public gameData: GameData;
|
||||||
public sessionSlotId: integer;
|
public sessionSlotId: integer;
|
||||||
|
|
||||||
|
// can debug phases using "phase.constructor.name"
|
||||||
private phaseQueue: Phase[];
|
private phaseQueue: Phase[];
|
||||||
private phaseQueuePrepend: Phase[];
|
private phaseQueuePrepend: Phase[];
|
||||||
private phaseQueuePrependSpliceIndex: integer;
|
private phaseQueuePrependSpliceIndex: integer;
|
||||||
|
|
@ -1503,22 +1504,41 @@ export default class BattleScene extends SceneBase {
|
||||||
getStandbyPhase(): Phase {
|
getStandbyPhase(): Phase {
|
||||||
return this.standbyPhase;
|
return this.standbyPhase;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* PhaseQueuePrepend: is a temp storage of what will be added to PhaseQueue
|
||||||
|
* PhaseQueue: dequeue/remove the first element to get the next phase
|
||||||
|
* queues are moved around during shiftPhase() below
|
||||||
|
*/
|
||||||
|
|
||||||
|
// adds a phase to "nextCommandPhaseQueue", as long as boolean passed in is false
|
||||||
pushPhase(phase: Phase, defer: boolean = false): void {
|
pushPhase(phase: Phase, defer: boolean = false): void {
|
||||||
(!defer ? this.phaseQueue : this.nextCommandPhaseQueue).push(phase);
|
(!defer ? this.phaseQueue : this.nextCommandPhaseQueue).push(phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adds phase to the end, or at some specified index
|
||||||
unshiftPhase(phase: Phase): void {
|
unshiftPhase(phase: Phase): void {
|
||||||
if (this.phaseQueuePrependSpliceIndex === -1)
|
if (this.phaseQueuePrependSpliceIndex === -1)
|
||||||
|
// .push() adds to end of array
|
||||||
this.phaseQueuePrepend.push(phase);
|
this.phaseQueuePrepend.push(phase);
|
||||||
else
|
else
|
||||||
|
// .splice(index, num elements to remove, what to add)
|
||||||
|
// modifies array by inserting at index, removing num of elements after index
|
||||||
this.phaseQueuePrepend.splice(this.phaseQueuePrependSpliceIndex, 0, phase);
|
this.phaseQueuePrepend.splice(this.phaseQueuePrependSpliceIndex, 0, phase);
|
||||||
|
/**
|
||||||
|
* debugging queues via printing, may be helpful in the future
|
||||||
|
console.log(`State of the phaseQueuePrepend (will be moved over to phaseQeueu)`)
|
||||||
|
this.phaseQueuePrepend.forEach(p => console.log(p.constructor.name));
|
||||||
|
|
||||||
|
console.log(`State of the phaseQueue, what is going to be called next `)
|
||||||
|
this.phaseQueue.forEach(p => console.log(p.constructor.name));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
clearPhaseQueue(): void {
|
clearPhaseQueue(): void {
|
||||||
this.phaseQueue.splice(0, this.phaseQueue.length);
|
this.phaseQueue.splice(0, this.phaseQueue.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// combo with unshiftPhase(), want to start inserting at current length instead of the "end", useful if phaseQueuePrepend gets longer with Phases
|
||||||
setPhaseQueueSplice(): void {
|
setPhaseQueueSplice(): void {
|
||||||
this.phaseQueuePrependSpliceIndex = this.phaseQueuePrepend.length;
|
this.phaseQueuePrependSpliceIndex = this.phaseQueuePrepend.length;
|
||||||
}
|
}
|
||||||
|
|
@ -1527,6 +1547,10 @@ export default class BattleScene extends SceneBase {
|
||||||
this.phaseQueuePrependSpliceIndex = -1;
|
this.phaseQueuePrependSpliceIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is called by each Phase implementations "end()" by default
|
||||||
|
* dumps everything from phaseQueuePrepend to the start of of phaseQueue, then starts the first one
|
||||||
|
*/
|
||||||
shiftPhase(): void {
|
shiftPhase(): void {
|
||||||
if (this.standbyPhase) {
|
if (this.standbyPhase) {
|
||||||
this.currentPhase = this.standbyPhase;
|
this.currentPhase = this.standbyPhase;
|
||||||
|
|
@ -1534,14 +1558,28 @@ export default class BattleScene extends SceneBase {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shifting phase (with no standby phase) will move everything from prepend to actual PhaseQueue?
|
||||||
|
// resets the index, if it was changed via setPhaseQueueSplice()
|
||||||
if (this.phaseQueuePrependSpliceIndex > -1)
|
if (this.phaseQueuePrependSpliceIndex > -1)
|
||||||
this.clearPhaseQueueSplice();
|
this.clearPhaseQueueSplice();
|
||||||
if (this.phaseQueuePrepend.length) {
|
if (this.phaseQueuePrepend.length) {
|
||||||
while (this.phaseQueuePrepend.length)
|
while (this.phaseQueuePrepend.length)
|
||||||
|
// appends phaseQueuePrepend to phaseQueue
|
||||||
|
// eg: phaseQueue = [4,5,6], phaseQUeuePrepend = [1,2,3]
|
||||||
|
// -> [1,2,3,4,5,6]
|
||||||
this.phaseQueue.unshift(this.phaseQueuePrepend.pop());
|
this.phaseQueue.unshift(this.phaseQueuePrepend.pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// then starts from PhaseQueue, .shift() removes first elm of array
|
||||||
|
// populatePhaseQueue() adds a turnInit Phase at the end of phaseQueue (if the queue is emtpy)
|
||||||
if (!this.phaseQueue.length)
|
if (!this.phaseQueue.length)
|
||||||
this.populatePhaseQueue();
|
this.populatePhaseQueue();
|
||||||
|
|
||||||
|
/** debugging
|
||||||
|
*
|
||||||
|
console.log(`SHIFT PHASE: State of the phaseQueue, what is going to be called next`)
|
||||||
|
this.phaseQueue.forEach(p => console.log(p.constructor.name));
|
||||||
|
*/
|
||||||
this.currentPhase = this.phaseQueue.shift();
|
this.currentPhase = this.phaseQueue.shift();
|
||||||
this.currentPhase.start();
|
this.currentPhase.start();
|
||||||
}
|
}
|
||||||
|
|
@ -1592,11 +1630,14 @@ export default class BattleScene extends SceneBase {
|
||||||
queueMessage(message: string, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer, defer?: boolean) {
|
queueMessage(message: string, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer, defer?: boolean) {
|
||||||
const phase = new MessagePhase(this, message, callbackDelay, prompt, promptDelay);
|
const phase = new MessagePhase(this, message, callbackDelay, prompt, promptDelay);
|
||||||
if (!defer)
|
if (!defer)
|
||||||
|
// adds to the end of PhaseQueuePrepend
|
||||||
this.unshiftPhase(phase);
|
this.unshiftPhase(phase);
|
||||||
else
|
else
|
||||||
|
//remember that pushPhase adds it to nextCommandPhaseQueue
|
||||||
this.pushPhase(phase);
|
this.pushPhase(phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// moves everyhting from nextCommandPhaseQueue
|
||||||
populatePhaseQueue(): void {
|
populatePhaseQueue(): void {
|
||||||
if (this.nextCommandPhaseQueue.length) {
|
if (this.nextCommandPhaseQueue.length) {
|
||||||
this.phaseQueue.push(...this.nextCommandPhaseQueue);
|
this.phaseQueue.push(...this.nextCommandPhaseQueue);
|
||||||
|
|
|
||||||
|
|
@ -1607,6 +1607,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
|
|
||||||
console.log('damage', damage.value, move.name, power.value, sourceAtk, targetDef);
|
console.log('damage', damage.value, move.name, power.value, sourceAtk, targetDef);
|
||||||
|
|
||||||
|
|
||||||
if (damage.value) {
|
if (damage.value) {
|
||||||
if (this.getHpRatio() === 1)
|
if (this.getHpRatio() === 1)
|
||||||
applyPreDefendAbAttrs(PreDefendFullHpEndureAbAttr, this, source, battlerMove, cancelled, damage);
|
applyPreDefendAbAttrs(PreDefendFullHpEndureAbAttr, this, source, battlerMove, cancelled, damage);
|
||||||
|
|
@ -1614,11 +1615,38 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
this.scene.applyModifiers(EnemyEndureChanceModifier, false, this);
|
this.scene.applyModifiers(EnemyEndureChanceModifier, false, this);
|
||||||
|
|
||||||
const oneHitKo = result === HitResult.ONE_HIT_KO;
|
const oneHitKo = result === HitResult.ONE_HIT_KO;
|
||||||
|
|
||||||
|
// damageAndUpdate: will queue potential messages for critical hit, effectiveness, fainted - in that order
|
||||||
damage.value = this.damageAndUpdate(damage.value, result as DamageResult, isCritical, oneHitKo, oneHitKo);
|
damage.value = this.damageAndUpdate(damage.value, result as DamageResult, isCritical, oneHitKo, oneHitKo);
|
||||||
this.turnData.damageTaken += damage.value;
|
this.turnData.damageTaken += damage.value;
|
||||||
|
|
||||||
|
// queue critical message before effectiveness
|
||||||
if (isCritical)
|
if (isCritical)
|
||||||
this.scene.queueMessage(i18next.t('battle:hitResultCriticalHit'));
|
this.scene.queueMessage(i18next.t('battle:hitResultCriticalHit'));
|
||||||
this.scene.setPhaseQueueSplice();
|
|
||||||
|
// hitsLeft: for multi-hit moves, only want to render effectiveness text at end.
|
||||||
|
// also want to render if a pokemon fainted
|
||||||
|
//console.log(`the number of hits left for this turn for ${this.name} is ${source.turnData.hitsLeft}`)
|
||||||
|
if (source.turnData.hitsLeft === 1 || this.isFainted()) {
|
||||||
|
switch (result as HitResult) {
|
||||||
|
case HitResult.SUPER_EFFECTIVE:
|
||||||
|
this.scene.queueMessage(i18next.t('battle:hitResultSuperEffective'));
|
||||||
|
break;
|
||||||
|
case HitResult.NOT_VERY_EFFECTIVE:
|
||||||
|
this.scene.queueMessage(i18next.t('battle:hitResultNotVeryEffective'));
|
||||||
|
break;
|
||||||
|
case HitResult.NO_EFFECT:
|
||||||
|
this.scene.queueMessage(i18next.t('battle:hitResultNoEffect', { pokemonName: this.name }));
|
||||||
|
break;
|
||||||
|
case HitResult.IMMUNE:
|
||||||
|
this.scene.queueMessage(`${this.name} is unaffected!`);
|
||||||
|
break;
|
||||||
|
case HitResult.ONE_HIT_KO:
|
||||||
|
this.scene.queueMessage(i18next.t('battle:hitResultOneHitKO'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (source.isPlayer()) {
|
if (source.isPlayer()) {
|
||||||
this.scene.validateAchvs(DamageAchv, damage);
|
this.scene.validateAchvs(DamageAchv, damage);
|
||||||
if (damage.value > this.scene.gameData.gameStats.highestDamage)
|
if (damage.value > this.scene.gameData.gameStats.highestDamage)
|
||||||
|
|
@ -1626,34 +1654,40 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
source.turnData.damageDealt += damage.value;
|
source.turnData.damageDealt += damage.value;
|
||||||
this.battleData.hitCount++;
|
this.battleData.hitCount++;
|
||||||
|
// create attack result and push to turnData
|
||||||
const attackResult = { move: move.id, result: result as DamageResult, damage: damage.value, critical: isCritical, sourceId: source.id };
|
const attackResult = { move: move.id, result: result as DamageResult, damage: damage.value, critical: isCritical, sourceId: source.id };
|
||||||
this.turnData.attacksReceived.unshift(attackResult);
|
this.turnData.attacksReceived.unshift(attackResult);
|
||||||
if (source.isPlayer() && !this.isPlayer())
|
if (source.isPlayer() && !this.isPlayer())
|
||||||
this.scene.applyModifiers(DamageMoneyRewardModifier, true, source, damage)
|
this.scene.applyModifiers(DamageMoneyRewardModifier, true, source, damage)
|
||||||
}
|
|
||||||
|
|
||||||
if (source.turnData.hitsLeft === 1) {
|
|
||||||
switch (result) {
|
// finally checks and adds Fainted scene
|
||||||
case HitResult.SUPER_EFFECTIVE:
|
if (this.isFainted()) {
|
||||||
this.scene.queueMessage(i18next.t('battle:hitResultSuperEffective'));
|
/**
|
||||||
break;
|
* when adding the FaintPhase, want to toggle future unshiftPhase() and queueMessage() calls
|
||||||
case HitResult.NOT_VERY_EFFECTIVE:
|
* to appear before the FaintPhase (as FaintPhase will potentially end the encounter and add Phases such as
|
||||||
this.scene.queueMessage(i18next.t('battle:hitResultNotVeryEffective'));
|
* GameOverPhase, VictoryPhase, etc.. that will interfere with anything else that happens during this MoveEffectPhase)
|
||||||
break;
|
*
|
||||||
case HitResult.NO_EFFECT:
|
* once the MoveEffectPhase is over (and calls it's .end() function, shiftPhase() will reset the PhaseQueueSplice via clearPhaseQueueSplice() )
|
||||||
this.scene.queueMessage(i18next.t('battle:hitResultNoEffect', { pokemonName: this.name }));
|
*/
|
||||||
break;
|
this.scene.setPhaseQueueSplice();
|
||||||
case HitResult.IMMUNE:
|
this.scene.unshiftPhase(new FaintPhase(this.scene, this.getBattlerIndex(), oneHitKo));
|
||||||
this.scene.queueMessage(`${this.name} is unaffected!`);
|
this.resetSummonData();
|
||||||
break;
|
|
||||||
case HitResult.ONE_HIT_KO:
|
|
||||||
this.scene.queueMessage(i18next.t('battle:hitResultOneHitKO'));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (damage)
|
/**
|
||||||
this.scene.clearPhaseQueueSplice();
|
* since damage is an object, I don't see how this would ever by false?
|
||||||
|
* i think the motivation was to have this here to counter setPhaseQueueSplice()
|
||||||
|
* not sure the original motivation
|
||||||
|
*
|
||||||
|
* It would be bad to run both the top if block and the one below commented out without changing the later's condition
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
if (damage){
|
||||||
|
this.scene.clearPhaseQueueSplice();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MoveCategory.STATUS:
|
case MoveCategory.STATUS:
|
||||||
|
|
@ -1689,19 +1723,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
|
|
||||||
damage = Math.min(damage, this.hp);
|
damage = Math.min(damage, this.hp);
|
||||||
|
|
||||||
this.hp = this.hp - damage;
|
this.hp = this.hp - damage;
|
||||||
if (this.isFainted()) {
|
|
||||||
this.scene.unshiftPhase(new FaintPhase(this.scene, this.getBattlerIndex(), preventEndure));
|
|
||||||
this.resetSummonData();
|
|
||||||
}
|
|
||||||
|
|
||||||
return damage;
|
return damage;
|
||||||
}
|
}
|
||||||
|
|
||||||
damageAndUpdate(damage: integer, result?: DamageResult, critical: boolean = false, ignoreSegments: boolean = false, preventEndure: boolean = false): integer {
|
damageAndUpdate(damage: integer, result?: DamageResult, critical: boolean = false, ignoreSegments: boolean = false, preventEndure: boolean = false ): integer {
|
||||||
const damagePhase = new DamagePhase(this.scene, this.getBattlerIndex(), damage, result as DamageResult, critical);
|
const damagePhase = new DamagePhase(this.scene, this.getBattlerIndex(), damage, result as DamageResult, critical);
|
||||||
this.scene.unshiftPhase(damagePhase);
|
this.scene.unshiftPhase(damagePhase);
|
||||||
|
|
||||||
damage = this.damage(damage, ignoreSegments, preventEndure);
|
damage = this.damage(damage, ignoreSegments, preventEndure);
|
||||||
// Damage amount may have changed, but needed to be queued before calling damage function
|
// Damage amount may have changed, but needed to be queued before calling damage function
|
||||||
damagePhase.updateAmount(damage);
|
damagePhase.updateAmount(damage);
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,13 @@ export const POKEBALL_OVERRIDE: { active: boolean, pokeballs: PokeballCounts } =
|
||||||
// forms can be found in pokemon-species.ts
|
// forms can be found in pokemon-species.ts
|
||||||
export const STARTER_FORM_OVERRIDE: integer = 0;
|
export const STARTER_FORM_OVERRIDE: integer = 0;
|
||||||
// default 5 or 20 for Daily
|
// default 5 or 20 for Daily
|
||||||
export const STARTING_LEVEL_OVERRIDE: integer = 0;
|
export const STARTING_LEVEL_OVERRIDE: integer = 10;
|
||||||
export const ABILITY_OVERRIDE: Abilities = Abilities.NONE;
|
export const ABILITY_OVERRIDE: Abilities = Abilities.NONE;
|
||||||
export const PASSIVE_ABILITY_OVERRIDE: Abilities = Abilities.NONE;
|
export const PASSIVE_ABILITY_OVERRIDE: Abilities = Abilities.NONE;
|
||||||
export const MOVESET_OVERRIDE: Array<Moves> = [];
|
|
||||||
export const SHINY_OVERRIDE: boolean = false;
|
export const SHINY_OVERRIDE: boolean = false;
|
||||||
export const VARIANT_OVERRIDE: Variant = 0;
|
export const VARIANT_OVERRIDE: Variant = 0;
|
||||||
|
// eg: Moves.TACKLE
|
||||||
|
export const MOVESET_OVERRIDE: Array<Moves> = []
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OPPONENT / ENEMY OVERRIDES
|
* OPPONENT / ENEMY OVERRIDES
|
||||||
|
|
@ -60,7 +61,7 @@ export const VARIANT_OVERRIDE: Variant = 0;
|
||||||
|
|
||||||
export const OPP_ABILITY_OVERRIDE: Abilities = Abilities.NONE;
|
export const OPP_ABILITY_OVERRIDE: Abilities = Abilities.NONE;
|
||||||
export const OPP_PASSIVE_ABILITY_OVERRIDE = Abilities.NONE;
|
export const OPP_PASSIVE_ABILITY_OVERRIDE = Abilities.NONE;
|
||||||
export const OPP_MOVESET_OVERRIDE: Array<Moves> = [];
|
export const OPP_MOVESET_OVERRIDE: Array<Moves> = []
|
||||||
export const OPP_SHINY_OVERRIDE: boolean = false;
|
export const OPP_SHINY_OVERRIDE: boolean = false;
|
||||||
export const OPP_VARIANT_OVERRIDE: Variant = 0;
|
export const OPP_VARIANT_OVERRIDE: Variant = 0;
|
||||||
|
|
||||||
|
|
@ -70,8 +71,8 @@ export const OPP_VARIANT_OVERRIDE: Variant = 0;
|
||||||
* default is 0 to not override
|
* default is 0 to not override
|
||||||
* @example SPECIES_OVERRIDE = Species.Bulbasaur;
|
* @example SPECIES_OVERRIDE = Species.Bulbasaur;
|
||||||
*/
|
*/
|
||||||
export const STARTER_SPECIES_OVERRIDE: Species | integer = 0;
|
export const STARTER_SPECIES_OVERRIDE: Species | integer = 0
|
||||||
export const OPP_SPECIES_OVERRIDE: Species | integer = 0;
|
export const OPP_SPECIES_OVERRIDE: Species | integer = 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MODIFIER / ITEM OVERRIDES
|
* MODIFIER / ITEM OVERRIDES
|
||||||
|
|
|
||||||
|
|
@ -2060,6 +2060,11 @@ export class TurnStartPhase extends FieldPhase {
|
||||||
|
|
||||||
this.scene.pushPhase(new TurnEndPhase(this.scene));
|
this.scene.pushPhase(new TurnEndPhase(this.scene));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this.end() will call shiftPhase(), which dumps everything from PrependQueue (aka everything that is unshifted()) to the front
|
||||||
|
* of the queue and dequeues to start the next phase
|
||||||
|
* this is important since stuff like SwitchSummon, AttemptRun, AttemptCapture Phases break the "flow" and should take precedence
|
||||||
|
*/
|
||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2279,6 +2284,7 @@ export class MovePhase extends BattlePhase {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Readability?: this function declaration honestly gets in the way of readability of what start() is doing , move either to beginning or end
|
||||||
const doMove = () => {
|
const doMove = () => {
|
||||||
this.pokemon.turnData.acted = true; // Record that the move was attempted, even if it fails
|
this.pokemon.turnData.acted = true; // Record that the move was attempted, even if it fails
|
||||||
|
|
||||||
|
|
@ -2565,11 +2571,15 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||||
const user = this.getUserPokemon();
|
const user = this.getUserPokemon();
|
||||||
if (user) {
|
if (user) {
|
||||||
if (--user.turnData.hitsLeft >= 1 && this.getTarget()?.isActive())
|
if (--user.turnData.hitsLeft >= 1 && this.getTarget()?.isActive())
|
||||||
this.scene.unshiftPhase(this.getNewHitPhase());
|
this.scene.unshiftPhase(this.getNewHitPhase()); // adds another MoveAffectPhase
|
||||||
else {
|
else {
|
||||||
|
// queue message for number of hits made by multi-move
|
||||||
|
// BUG: when fainting occurs, the resulting message isn't rendered - has to do with FaintPhase
|
||||||
|
// temp fix in pokemon.ts apply() that checks, but ideally want to fix it here at the source
|
||||||
const hitsTotal = user.turnData.hitCount - Math.max(user.turnData.hitsLeft, 0);
|
const hitsTotal = user.turnData.hitCount - Math.max(user.turnData.hitsLeft, 0);
|
||||||
if (hitsTotal > 1)
|
if (hitsTotal > 1 || user.turnData.hitsLeft > 0){
|
||||||
this.scene.queueMessage(i18next.t('battle:attackHitsCount', { count: hitsTotal }));
|
this.scene.queueMessage(i18next.t('battle:attackHitsCount', { count: hitsTotal }));
|
||||||
|
}
|
||||||
this.scene.applyModifiers(HitHealModifier, this.player, user);
|
this.scene.applyModifiers(HitHealModifier, this.player, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue