type hints

This commit is contained in:
Yentis 2024-05-18 00:28:56 +02:00
parent 5dd017fa30
commit aa91ae4c49
7 changed files with 167 additions and 16 deletions

View File

@ -119,6 +119,7 @@ export default class BattleScene extends SceneBase {
public fusionPaletteSwaps: boolean = true;
public enableTouchControls: boolean = false;
public enableVibration: boolean = false;
public typeHints: integer = 0;
public abSwapped: boolean = false;
public disableMenu: boolean = false;

View File

@ -943,6 +943,22 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return !this.isOfType(Type.FLYING, true) && !this.hasAbility(Abilities.LEVITATE);
}
isStabMove(move: Move): boolean {
if (move.category === MoveCategory.STATUS) return false;
const type = move.type;
const types = this.getTypes();
const teraType = this.getTeraType();
const matchesSourceType = types[0] === type || (types.length > 1 && types[1] === type);
return (teraType === Type.UNKNOWN && matchesSourceType) || (teraType !== Type.UNKNOWN && teraType === type);
}
getMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier | undefined {
if (move.getMove().category === MoveCategory.STATUS) return undefined;
return this.getAttackMoveEffectiveness(source, move);
}
getAttackMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier {
const typeless = !!move.getMove().getAttrs(TypelessAttr).length;
const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move.getMove().type, source));
@ -1096,11 +1112,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
let shinyThreshold = new Utils.IntegerHolder(32);
if (thresholdOverride === undefined) {
if (!this.hasTrainer()) {
if (new Date() < new Date('2024-05-21'))
shinyThreshold.value *= 3;
if (!this.hasTrainer())
this.scene.applyModifiers(ShinyRateBoosterModifier, true, shinyThreshold);
}
} else
shinyThreshold.value = thresholdOverride;
@ -1376,6 +1389,57 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return this.battleInfo.updateInfo(this, instant);
}
updateNameColor() {
const nameColor = this.getNameColor();
if (nameColor === undefined) return;
this.battleInfo.updateNameColor(nameColor);
}
getNameColor(): string | undefined {
const typeHints = this.scene.typeHints;
if (typeHints === 0) return undefined;
const opponents = this.getOpponents();
const opponentMoveEffectivenessList = opponents.map((opponent) => {
return opponent.getMoveset().map((move) => {
return this.getMoveEffectiveness(opponent, move);
});
}).flat().filter((effectiveness) => effectiveness !== undefined);
const moveEffectivenessList = opponents.map((opponent) => {
return this.getMoveset().map((move) => {
return opponent.getMoveEffectiveness(this, move);
});
}).flat().filter((effectiveness) => effectiveness !== undefined);
const fullHints = typeHints === 2;
if (fullHints && opponentMoveEffectivenessList.some((effectiveness) => effectiveness === 8)) {
return 'darkred';
} else if (fullHints && opponentMoveEffectivenessList.some((effectiveness) => effectiveness === 4)) {
return 'red';
} else if (fullHints && opponentMoveEffectivenessList.some((effectiveness) => effectiveness === 2)) {
return 'crimson';
} else if (moveEffectivenessList.some((effectiveness) => effectiveness === 8)) {
return 'darkgreen';
} else if (moveEffectivenessList.some((effectiveness) => effectiveness === 4)) {
return 'green';
} else if (moveEffectivenessList.some((effectiveness) => effectiveness === 2)) {
return 'lightgreen';
} else if (fullHints && opponentMoveEffectivenessList.every((effectiveness) => effectiveness === 0)) {
return 'yellow';
} else if (fullHints && opponentMoveEffectivenessList.every((effectiveness) => effectiveness === 0.125)) {
return 'darkblue';
} else if (fullHints && opponentMoveEffectivenessList.every((effectiveness) => effectiveness === 0.25)) {
return 'blue';
} else if (fullHints && opponentMoveEffectivenessList.every((effectiveness) => effectiveness === 0.5)) {
return 'lightblue';
}
return 'white';
}
toggleStats(visible: boolean): void {
this.battleInfo.toggleStats(visible);
}
@ -1526,11 +1590,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const isTypeImmune = (typeMultiplier.value * arenaAttackTypeMultiplier.value) === 0;
const sourceTypes = source.getTypes();
const matchesSourceType = sourceTypes[0] === type || (sourceTypes.length > 1 && sourceTypes[1] === type);
let stabMultiplier = new Utils.NumberHolder(1);
if (sourceTeraType === Type.UNKNOWN && matchesSourceType)
stabMultiplier.value += 0.5;
else if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === type)
if (source.isStabMove(move)) {
stabMultiplier.value += 0.5;
}
applyAbAttrs(StabBoostAbAttr, source, null, stabMultiplier);

View File

@ -1572,6 +1572,10 @@ export class CheckSwitchPhase extends BattlePhase {
super.start();
const pokemon = this.scene.getPlayerField()[this.fieldIndex];
this.scene.getParty().forEach((pokemon) => {
pokemon.updateNameColor();
});
if (this.scene.field.getAll().indexOf(pokemon) === -1) {
this.scene.unshiftPhase(new SummonMissingPhase(this.scene, this.fieldIndex));
@ -1651,6 +1655,10 @@ export class TurnInitPhase extends FieldPhase {
}
});
this.scene.getParty().forEach((pokemon) => {
pokemon.updateNameColor();
});
this.scene.pushPhase(new TurnStartPhase(this.scene));
this.end();

View File

@ -28,7 +28,8 @@ export enum Setting {
Gamepad_Support = "GAMEPAD_SUPPORT",
Swap_A_and_B = "SWAP_A_B", // Swaps which gamepad button handles ACTION and CANCEL
Touch_Controls = "TOUCH_CONTROLS",
Vibration = "VIBRATION"
Vibration = "VIBRATION",
Type_Hints = "TYPE_HINTS"
}
export interface SettingOptions {
@ -61,7 +62,8 @@ export const settingOptions: SettingOptions = {
[Setting.Gamepad_Support]: ['Auto', 'Disabled'],
[Setting.Swap_A_and_B]: ['Enabled', 'Disabled'],
[Setting.Touch_Controls]: ['Auto', 'Disabled'],
[Setting.Vibration]: ['Auto', 'Disabled']
[Setting.Vibration]: ['Auto', 'Disabled'],
[Setting.Type_Hints]: ['Off', 'Partial', 'Full']
};
export const settingDefaults: SettingDefaults = {
@ -86,7 +88,8 @@ export const settingDefaults: SettingDefaults = {
[Setting.Gamepad_Support]: 0,
[Setting.Swap_A_and_B]: 1, // Set to 'Disabled' by default
[Setting.Touch_Controls]: 0,
[Setting.Vibration]: 0
[Setting.Vibration]: 0,
[Setting.Type_Hints]: 0,
};
export const reloadSettings: Setting[] = [Setting.UI_Theme, Setting.Language, Setting.Sprite_Set];
@ -171,6 +174,9 @@ export function setSetting(scene: BattleScene, setting: Setting, value: integer)
case Setting.Vibration:
scene.enableVibration = settingOptions[setting][value] !== 'Disabled' && hasTouchscreen();
break;
case Setting.Type_Hints:
scene.typeHints = value;
break;
case Setting.Language:
if (value) {
if (scene.ui) {

View File

@ -551,6 +551,10 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
this.lastName = pokemon.name;
}
updateNameColor(color: string) {
this.nameText.setColor(color);
}
updatePokemonExp(pokemon: Pokemon, instant?: boolean, levelDurationMultiplier: number = 1): Promise<void> {
return new Promise(resolve => {
const levelUp = this.lastLevel < pokemon.level;

View File

@ -1,6 +1,6 @@
import BattleScene from "../battle-scene";
import { addTextObject, TextStyle } from "./text";
import { Type } from "../data/type";
import { Type, TypeDamageMultiplier } from "../data/type";
import { Command } from "./command-ui-handler";
import { Mode } from "./ui";
import UiHandler from "./ui-handler";
@ -9,6 +9,7 @@ import { CommandPhase } from "../phases";
import { MoveCategory } from "#app/data/move.js";
import i18next from '../plugins/i18n';
import {Button} from "../enums/buttons";
import Pokemon, { PokemonMove } from "#app/field/pokemon.js";
export default class FightUiHandler extends UiHandler {
private movesContainer: Phaser.GameObjects.Container;
@ -189,15 +190,79 @@ export default class FightUiHandler extends UiHandler {
}
displayMoves() {
const moveset = (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getMoveset();
for (let m = 0; m < 4; m++) {
const moveText = addTextObject(this.scene, m % 2 === 0 ? 0 : 100, m < 2 ? 0 : 16, '-', TextStyle.WINDOW);
if (m < moveset.length)
moveText.setText(moveset[m].getName());
const pokemon = (this.scene.getCurrentPhase() as CommandPhase).getPokemon();
const moveset = pokemon.getMoveset();
for (let moveIndex = 0; moveIndex < 4; moveIndex++) {
const moveText = addTextObject(this.scene, moveIndex % 2 === 0 ? 0 : 100, moveIndex < 2 ? 0 : 16, '-', TextStyle.WINDOW);
if (moveIndex < moveset.length) {
const pokemonMove = moveset[moveIndex];
moveText.setText(pokemonMove.getName());
if (this.scene.typeHints > 0) {
this.setTypeHints(pokemon, pokemonMove, moveText);
}
}
this.movesContainer.add(moveText);
}
}
private setTypeHints(pokemon: Pokemon, pokemonMove: PokemonMove, moveText: Phaser.GameObjects.Text) {
const opponents = pokemon.getOpponents();
if (opponents.length < 1) return;
const move = pokemonMove.getMove();
const moveEffectivenessList = opponents.map((opponent) => opponent.getMoveEffectiveness(pokemon, pokemonMove));
let text = moveText.text;
const effectivenessTextList = moveEffectivenessList.map((effectiveness) => this.getMoveEffectivenessText(effectiveness));
if (effectivenessTextList.every((text) => text === effectivenessTextList[0])) {
if (moveEffectivenessList[0] !== 1) {
text += effectivenessTextList[0];
}
} else {
moveEffectivenessList.forEach((effectiveness) => {
text += this.getMoveEffectivenessText(effectiveness);
});
}
moveText.setText(text);
const stab = pokemon.isStabMove(move);
if (stab) moveText.setFontStyle('bold');
const moveColors = moveEffectivenessList.sort((a, b) => b - a).map((effectiveness) => this.getMoveColor(effectiveness));
moveText.setColor(moveColors[0]);
}
private getMoveEffectivenessText(moveEffectiveness?: TypeDamageMultiplier): string {
if (moveEffectiveness === undefined) return '';
return ` ${moveEffectiveness}x`;
}
private getMoveColor(moveEffectiveness?: TypeDamageMultiplier): string {
switch (moveEffectiveness) {
case 0:
return 'black';
case 0.125:
return 'darkred';
case 0.25:
return 'red';
case 0.5:
return 'crimson';
case 2:
return 'lightgreen';
case 4:
return 'green';
case 8:
return 'darkgreen';
}
return 'white';
}
clear() {
super.clear();
this.clearMoves();

View File

@ -870,6 +870,9 @@ class PartySlot extends Phaser.GameObjects.Container {
slotName.setPositionRelative(slotBg, this.slotIndex >= battlerCount ? 21 : 24, this.slotIndex >= battlerCount ? 2 : 10);
slotName.setOrigin(0, 0);
const color = this.pokemon.getNameColor();
if (color !== undefined) slotName.setColor(color);
const slotLevelLabel = this.scene.add.image(0, 0, 'party_slot_overlay_lv');
slotLevelLabel.setPositionRelative(slotName, 8, 12);
slotLevelLabel.setOrigin(0, 0);