Compare commits

..

5 Commits

Author SHA1 Message Date
Xavion3
3fd1ecf6a7
Update moveset logic to account for new sacrifice attr (#1192) 2024-05-21 02:40:53 -05:00
Sbug98
42e2be22bc
Implements bad dreams (#633)
* test commit

* de modified readme

* first implementation, needs testing with healer

* fixed beahviour if 2+ opponents are on field, also added message

* further fixed

* reset of overrides.ts before merge to main

* fixed grammar

Co-authored-by: Jonas Pinson <jonas.pinson@gmail.com>

* Implemented changes suggested by @bennybroseph and @TempsRay

* Added more docs to the class

* removed old comments

* fixed ability name in comments

* added translation and made message localized

* fixed ability name

* added missing bracket

---------

Co-authored-by: Jonas Pinson <jonas.pinson@gmail.com>
2024-05-21 02:26:01 -05:00
Jacob Knispel
6016ecfb46
Prevent Pokemon Info screen from being covered up (#1156)
* Move Pokemon info screen when confirming

Prevents the yes/no confirm menu from getting in the way when the Pokemon Info screen is open when catching a new Pokemon

* Greatly sped up makeRoomForConfirmUi()
2024-05-21 02:24:03 -05:00
0zuzu
67d5532d15
Check available Pkmn before asking to switch (#1194)
* Create Start Server.bat

idk anymore

* Update .gitignore

* Delete Start Server.bat

* Update .gitignore

* Update phases.ts

Check available party before asking to switch
2024-05-21 02:16:17 -05:00
Matthew Olker
70939bf89f Should fix black screen on load issue 2024-05-21 00:25:55 -04:00
12 changed files with 83 additions and 18 deletions

View File

@ -2282,6 +2282,34 @@ export class PostTurnFormChangeAbAttr extends PostTurnAbAttr {
} }
} }
/**
* Attribute used for abilities (Bad Dreams) that damages the opponents for being asleep
*/
export class PostTurnHurtIfSleepingAbAttr extends PostTurnAbAttr {
/**
* Deals damage to all sleeping opponents equal to 1/8 of their max hp (min 1)
* @param {Pokemon} pokemon Pokemon that has this ability
* @param {boolean} passive N/A
* @param {any[]} args N/A
* @returns {boolean} true if any opponents are sleeping
*/
applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> {
let hadEffect: boolean = false;
for(let opp of pokemon.getOpponents()) {
if(opp.status !== undefined && opp.status.effect === StatusEffect.SLEEP) {
opp.damageAndUpdate(Math.floor(Math.max(1, opp.getMaxHp() / 8)), HitResult.OTHER);
pokemon.scene.queueMessage(i18next.t('abilityTriggers:badDreams', {pokemonName: `${getPokemonPrefix(opp)}${opp.name}`}));
hadEffect = true;
}
}
return hadEffect;
}
}
/** /**
* Grabs the last failed Pokeball used * Grabs the last failed Pokeball used
* @extends PostTurnAbAttr * @extends PostTurnAbAttr
@ -3327,7 +3355,7 @@ export function initAbilities() {
.ignorable() .ignorable()
.partial(), .partial(),
new Ability(Abilities.BAD_DREAMS, 4) new Ability(Abilities.BAD_DREAMS, 4)
.unimplemented(), .attr(PostTurnHurtIfSleepingAbAttr),
new Ability(Abilities.PICKPOCKET, 5) new Ability(Abilities.PICKPOCKET, 5)
.attr(PostDefendStealHeldItemAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT)), .attr(PostDefendStealHeldItemAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT)),
new Ability(Abilities.SHEER_FORCE, 5) new Ability(Abilities.SHEER_FORCE, 5)

View File

@ -4,7 +4,7 @@ import { Variant, VariantSet, variantColorCache } from '#app/data/variant';
import { variantData } from '#app/data/variant'; import { variantData } from '#app/data/variant';
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info'; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info';
import { Moves } from "../data/enums/moves"; import { Moves } from "../data/enums/moves";
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr } from "../data/move"; import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit } from "../data/move";
import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from '../data/pokemon-species'; import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from '../data/pokemon-species';
import * as Utils from '../utils'; import * as Utils from '../utils';
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type';
@ -1282,11 +1282,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (this.isBoss()) // Bosses never get self ko moves if (this.isBoss()) // Bosses never get self ko moves
movePool = movePool.filter(m => !allMoves[m[0]].getAttrs(SacrificialAttr).length); movePool = movePool.filter(m => !allMoves[m[0]].getAttrs(SacrificialAttr).length);
movePool = movePool.filter(m => !allMoves[m[0]].getAttrs(SacrificialAttrOnHit).length);
if (this.hasTrainer()) { if (this.hasTrainer()) {
// Trainers never get OHKO moves // Trainers never get OHKO moves
movePool = movePool.filter(m => !allMoves[m[0]].getAttrs(OneHitKOAttr).length); movePool = movePool.filter(m => !allMoves[m[0]].getAttrs(OneHitKOAttr).length);
// Half the weight of self KO moves // Half the weight of self KO moves
movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].getAttrs(SacrificialAttr).length ? 0.5 : 1)]); movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].getAttrs(SacrificialAttr).length ? 0.5 : 1)]);
movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].getAttrs(SacrificialAttrOnHit).length ? 0.5 : 1)]);
// Trainers get a weight bump to stat buffing moves // Trainers get a weight bump to stat buffing moves
movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].getAttrs(StatChangeAttr).some(a => (a as StatChangeAttr).levels > 1 && (a as StatChangeAttr).selfTarget) ? 1.25 : 1)]); movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].getAttrs(StatChangeAttr).some(a => (a as StatChangeAttr).levels > 1 && (a as StatChangeAttr).selfTarget) ? 1.25 : 1)]);
// Trainers get a weight decrease to multiturn moves // Trainers get a weight decrease to multiturn moves

View File

@ -2,4 +2,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
'blockRecoilDamage' : `{{pokemonName}} wurde durch {{abilityName}}\nvor Rückstoß geschützt!`, 'blockRecoilDamage' : `{{pokemonName}} wurde durch {{abilityName}}\nvor Rückstoß geschützt!`,
'badDreams': `{{pokemonName}} wird gequält!`,
} as const; } as const;

View File

@ -2,4 +2,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`, 'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`,
'badDreams': `{{pokemonName}} is tormented!`,
} as const; } as const;

View File

@ -2,4 +2,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`, 'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`,
} as const; 'badDreams': `{{pokemonName}} Está atormentado!`
} as const;

View File

@ -2,4 +2,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
'blockRecoilDamage' : `{{abilityName}}\nde {{pokemonName}} le protège du contrecoup !`, 'blockRecoilDamage' : `{{abilityName}}\nde {{pokemonName}} le protège du contrecoup !`,
'badDreams': `{{pokemonName}} est tourmenté!`
} as const; } as const;

View File

@ -2,4 +2,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
'blockRecoilDamage' : `{{abilityName}} di {{pokemonName}}\nl'ha protetto dal contraccolpo!`, 'blockRecoilDamage' : `{{abilityName}} di {{pokemonName}}\nl'ha protetto dal contraccolpo!`,
'badDreams': `{{pokemonName}} è tormentato!`,
} as const; } as const;

View File

@ -2,4 +2,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
'blockRecoilDamage' : `{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力`, 'blockRecoilDamage' : `{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力`,
'badDreams': `{{pokemonName}} 被折磨着!`
} as const; } as const;

View File

@ -366,10 +366,14 @@ export class TitlePhase extends Phase {
this.scene.pushPhase(new SummonPhase(this.scene, 0, true, true)); this.scene.pushPhase(new SummonPhase(this.scene, 0, true, true));
if (this.scene.currentBattle.double && availablePartyMembers > 1) if (this.scene.currentBattle.double && availablePartyMembers > 1)
this.scene.pushPhase(new SummonPhase(this.scene, 1, true, true)); this.scene.pushPhase(new SummonPhase(this.scene, 1, true, true));
if (this.scene.currentBattle.waveIndex > 1 && this.scene.currentBattle.battleType !== BattleType.TRAINER) {
this.scene.pushPhase(new CheckSwitchPhase(this.scene, 0, this.scene.currentBattle.double)); if (this.scene.currentBattle.battleType !== BattleType.TRAINER && (this.scene.currentBattle.waveIndex > 1 || !this.scene.gameMode.isDaily)) {
if (this.scene.currentBattle.double && availablePartyMembers > 1) const minPartySize = this.scene.currentBattle.double ? 2 : 1;
this.scene.pushPhase(new CheckSwitchPhase(this.scene, 1, this.scene.currentBattle.double)); if (availablePartyMembers > minPartySize) {
this.scene.pushPhase(new CheckSwitchPhase(this.scene, 0, this.scene.currentBattle.double));
if (this.scene.currentBattle.double)
this.scene.pushPhase(new CheckSwitchPhase(this.scene, 1, this.scene.currentBattle.double));
}
} }
} }
@ -955,10 +959,13 @@ export class EncounterPhase extends BattlePhase {
this.scene.pushPhase(new ToggleDoublePositionPhase(this.scene, false)); this.scene.pushPhase(new ToggleDoublePositionPhase(this.scene, false));
} }
if (this.scene.currentBattle.waveIndex > startingWave && this.scene.currentBattle.battleType !== BattleType.TRAINER) { if (this.scene.currentBattle.battleType !== BattleType.TRAINER && (this.scene.currentBattle.waveIndex > 1 || !this.scene.gameMode.isDaily)) {
this.scene.pushPhase(new CheckSwitchPhase(this.scene, 0, this.scene.currentBattle.double)); const minPartySize = this.scene.currentBattle.double ? 2 : 1;
if (this.scene.currentBattle.double && availablePartyMembers.length > 1) if (availablePartyMembers.length > minPartySize) {
this.scene.pushPhase(new CheckSwitchPhase(this.scene, 1, this.scene.currentBattle.double)); this.scene.pushPhase(new CheckSwitchPhase(this.scene, 0, this.scene.currentBattle.double));
if (this.scene.currentBattle.double)
this.scene.pushPhase(new CheckSwitchPhase(this.scene, 1, this.scene.currentBattle.double));
}
} }
} }
@ -4416,6 +4423,7 @@ export class AttemptCapturePhase extends PokemonPhase {
if (this.scene.getParty().length === 6) { if (this.scene.getParty().length === 6) {
const promptRelease = () => { const promptRelease = () => {
this.scene.ui.showText(`Your party is full.\nRelease a Pokémon to make room for ${pokemon.name}?`, null, () => { this.scene.ui.showText(`Your party is full.\nRelease a Pokémon to make room for ${pokemon.name}?`, null, () => {
this.scene.pokemonInfoContainer.makeRoomForConfirmUi();
this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.CONFIRM, () => {
this.scene.ui.setMode(Mode.PARTY, PartyUiMode.RELEASE, this.fieldIndex, (slotIndex: integer, _option: PartyOption) => { this.scene.ui.setMode(Mode.PARTY, PartyUiMode.RELEASE, this.fieldIndex, (slotIndex: integer, _option: PartyOption) => {
this.scene.ui.setMode(Mode.MESSAGE).then(() => { this.scene.ui.setMode(Mode.MESSAGE).then(() => {

View File

@ -5,6 +5,9 @@ import i18next from "i18next";
import {Button} from "../enums/buttons"; import {Button} from "../enums/buttons";
export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
public static readonly windowWidth: integer = 48;
private switchCheck: boolean; private switchCheck: boolean;
private switchCheckCursor: integer; private switchCheckCursor: integer;
@ -13,7 +16,7 @@ export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
} }
getWindowWidth(): integer { getWindowWidth(): integer {
return 48; return ConfirmUiHandler.windowWidth;
} }
show(args: any[]): boolean { show(args: any[]): boolean {

View File

@ -9,8 +9,11 @@ import { getNatureName } from "../data/nature";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { Type } from "../data/type"; import { Type } from "../data/type";
import { getVariantTint } from "#app/data/variant"; import { getVariantTint } from "#app/data/variant";
import ConfirmUiHandler from "./confirm-ui-handler";
export default class PokemonInfoContainer extends Phaser.GameObjects.Container { export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
private readonly infoWindowWidth = 104;
private pokemonGenderLabelText: Phaser.GameObjects.Text; private pokemonGenderLabelText: Phaser.GameObjects.Text;
private pokemonGenderText: Phaser.GameObjects.Text; private pokemonGenderText: Phaser.GameObjects.Text;
private pokemonAbilityLabelText: Phaser.GameObjects.Text; private pokemonAbilityLabelText: Phaser.GameObjects.Text;
@ -37,7 +40,7 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
} }
setup(): void { setup(): void {
const infoBg = addWindow(this.scene, 0, 0, 104, 132); const infoBg = addWindow(this.scene, 0, 0, this.infoWindowWidth, 132);
infoBg.setOrigin(0.5, 0.5); infoBg.setOrigin(0.5, 0.5);
this.pokemonMovesContainer = this.scene.add.container(6, 14); this.pokemonMovesContainer = this.scene.add.container(6, 14);
@ -172,7 +175,7 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
targets: this, targets: this,
duration: Utils.fixedInt(Math.floor(750 / speedMultiplier)), duration: Utils.fixedInt(Math.floor(750 / speedMultiplier)),
ease: 'Cubic.easeInOut', ease: 'Cubic.easeInOut',
x: this.initialX - 104, x: this.initialX - this.infoWindowWidth,
onComplete: () => { onComplete: () => {
resolve(); resolve();
} }
@ -201,6 +204,20 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
}); });
} }
makeRoomForConfirmUi(speedMultiplier: number = 1): Promise<void> {
return new Promise<void>(resolve => {
this.scene.tweens.add({
targets: this,
duration: Utils.fixedInt(Math.floor(150 / speedMultiplier)),
ease: 'Cubic.easeInOut',
x: this.initialX - this.infoWindowWidth - ConfirmUiHandler.windowWidth,
onComplete: () => {
resolve();
}
});
});
}
hide(speedMultiplier: number = 1): Promise<void> { hide(speedMultiplier: number = 1): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
if (!this.shown) if (!this.shown)

View File

@ -70,12 +70,12 @@ const languageSettings: { [key: string]: LanguageSetting } = {
starterInfoTextSize: '54px', starterInfoTextSize: '54px',
instructionTextSize: '42px', instructionTextSize: '42px',
}, },
"zh_CN":{ "zh":{
starterInfoTextSize: '40px', starterInfoTextSize: '40px',
instructionTextSize: '42px', instructionTextSize: '42px',
starterInfoYOffset: 2 starterInfoYOffset: 2
}, },
"pt_BR":{ "pt":{
starterInfoTextSize: '47px', starterInfoTextSize: '47px',
instructionTextSize: '38px', instructionTextSize: '38px',
starterInfoXPos: 32, starterInfoXPos: 32,
@ -217,7 +217,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
setup() { setup() {
const ui = this.getUi(); const ui = this.getUi();
const currentLanguage = i18next.language; const currentLanguage = i18next.language;
const textSettings = languageSettings[currentLanguage]; const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang));
const textSettings = languageSettings[langSettingKey];
this.starterSelectContainer = this.scene.add.container(0, -this.scene.game.canvas.height / 6); this.starterSelectContainer = this.scene.add.container(0, -this.scene.game.canvas.height / 6);
this.starterSelectContainer.setVisible(false); this.starterSelectContainer.setVisible(false);
@ -280,7 +281,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
let starterInfoYOffset = textSettings?.starterInfoYOffset || 0; let starterInfoYOffset = textSettings?.starterInfoYOffset || 0;
// The font size should be set per language // The font size should be set per language
let starterInfoTextSize = textSettings.starterInfoTextSize; let starterInfoTextSize = textSettings?.starterInfoTextSize || 56;
this.pokemonAbilityLabelText = addTextObject(this.scene, 6, 127 + starterInfoYOffset, i18next.t("starterSelectUiHandler:ability"), TextStyle.SUMMARY_ALT, { fontSize: starterInfoTextSize }); this.pokemonAbilityLabelText = addTextObject(this.scene, 6, 127 + starterInfoYOffset, i18next.t("starterSelectUiHandler:ability"), TextStyle.SUMMARY_ALT, { fontSize: starterInfoTextSize });
this.pokemonAbilityLabelText.setOrigin(0, 0); this.pokemonAbilityLabelText.setOrigin(0, 0);