Refactor Lapsing Modifiers, Lerp Hue of Count

This commit is contained in:
xsn34kzx 2024-09-04 22:00:28 -04:00
parent 4e3a24c247
commit 395521c020
3 changed files with 90 additions and 96 deletions

View File

@ -433,15 +433,17 @@ export class RememberMoveModifierType extends PokemonModifierType {
} }
export class DoubleBattleChanceBoosterModifierType extends ModifierType { export class DoubleBattleChanceBoosterModifierType extends ModifierType {
public battleCount: integer; private maxBattles: number;
public battleCount: number;
constructor(localeKey: string, iconImage: string, battleCount: integer) { constructor(localeKey: string, iconImage: string, maxBattles: number, battleCount?: number) {
super(localeKey, iconImage, (_type, _args) => new Modifiers.DoubleBattleChanceBoosterModifier(this, this.battleCount), "lure"); super(localeKey, iconImage, (_type, _args) => new Modifiers.DoubleBattleChanceBoosterModifier(this, maxBattles), "lure");
this.battleCount = battleCount; this.maxBattles = maxBattles;
this.battleCount = battleCount ?? this.maxBattles;
} }
getDescription(scene: BattleScene): string { getDescription(_scene: BattleScene): string {
return i18next.t("modifierType:ModifierType.DoubleBattleChanceBoosterModifierType.description", { battleCount: this.battleCount }); return i18next.t("modifierType:ModifierType.DoubleBattleChanceBoosterModifierType.description", { battleCount: this.battleCount });
} }
} }
@ -452,7 +454,7 @@ export class TempStatStageBoosterModifierType extends ModifierType implements Ge
constructor(stat: TempBattleStat) { constructor(stat: TempBattleStat) {
const key = TempStatStageBoosterModifierTypeGenerator.items[stat]; const key = TempStatStageBoosterModifierTypeGenerator.items[stat];
super("", key, (_type, _args) => new Modifiers.TempStatStageBoosterModifier(this, this.stat)); super("", key, (_type, _args) => new Modifiers.TempStatStageBoosterModifier(this, this.stat, 5));
this.stat = stat; this.stat = stat;
this.key = key; this.key = key;
@ -1360,7 +1362,7 @@ export const modifierTypes = {
getDescription(_scene: BattleScene): string { getDescription(_scene: BattleScene): string {
return i18next.t("modifierType:ModifierType.TempStatStageBoosterModifierType.description", { stat: i18next.t("modifierType:ModifierType.DIRE_HIT.extra.raises") }); return i18next.t("modifierType:ModifierType.TempStatStageBoosterModifierType.description", { stat: i18next.t("modifierType:ModifierType.DIRE_HIT.extra.raises") });
} }
}("modifierType:ModifierType.DIRE_HIT", "dire_hit", (type, _args) => new Modifiers.TempCritBoosterModifier(type)), }("modifierType:ModifierType.DIRE_HIT", "dire_hit", (type, _args) => new Modifiers.TempCritBoosterModifier(type, 5)),
BASE_STAT_BOOSTER: () => new BaseStatBoosterModifierTypeGenerator(), BASE_STAT_BOOSTER: () => new BaseStatBoosterModifierTypeGenerator(),

View File

@ -293,59 +293,100 @@ export class AddVoucherModifier extends ConsumableModifier {
} }
export abstract class LapsingPersistentModifier extends PersistentModifier { export abstract class LapsingPersistentModifier extends PersistentModifier {
protected battlesLeft: integer; private maxBattles: number;
private battleCount: number;
constructor(type: ModifierTypes.ModifierType, battlesLeft?: integer, stackCount?: integer) { constructor(type: ModifierTypes.ModifierType, maxBattles: number, battleCount?: number, stackCount?: integer) {
super(type, stackCount); super(type, stackCount);
this.battlesLeft = battlesLeft!; // TODO: is this bang correct? this.maxBattles = maxBattles;
this.battleCount = battleCount ?? this.maxBattles;
} }
lapse(args: any[]): boolean { /**
return !!--this.battlesLeft; * Goes through existing modifiers for any that match the selected modifier,
* which will then either add it to the existing modifiers if none were found
* or, if one was found, it will refresh {@linkcode battleCount}.
* @param modifiers {@linkcode PersistentModifier} array of the player's modifiers
* @param _virtual N/A
* @param _scene N/A
* @returns true if the modifier was successfully added or applied, false otherwise
*/
add(modifiers: PersistentModifier[], _virtual: boolean, scene: BattleScene): boolean {
for (const modifier of modifiers) {
if (this.match(modifier)) {
const modifierInstance = modifier as LapsingPersistentModifier;
if (modifierInstance.getBattleCount() < modifierInstance.getMaxBattles()) {
modifierInstance.resetBattleCount();
scene.playSound("se/restore");
return true;
}
// should never get here
return false;
}
}
modifiers.push(this);
return true;
}
lapse(_args: any[]): boolean {
this.battleCount--;
return this.battleCount > 0;
} }
getIcon(scene: BattleScene): Phaser.GameObjects.Container { getIcon(scene: BattleScene): Phaser.GameObjects.Container {
const container = super.getIcon(scene); const container = super.getIcon(scene);
const battleCountText = addTextObject(scene, 27, 0, this.battlesLeft.toString(), TextStyle.PARTY, { fontSize: "66px", color: "#f89890" }); // Linear interpolation on hue
const hue = Math.floor(120 * (this.battleCount / this.maxBattles) + 5);
const typeHex = Utils.hslToHex(hue, 0.50, 0.90);
const strokeHex = Utils.hslToHex(hue, 0.70, 0.30);
const battleCountText = addTextObject(scene, 27, 0, this.battleCount.toString(), TextStyle.PARTY, { fontSize: "66px", color: typeHex });
battleCountText.setShadow(0, 0); battleCountText.setShadow(0, 0);
battleCountText.setStroke("#984038", 16); battleCountText.setStroke(strokeHex, 16);
battleCountText.setOrigin(1, 0); battleCountText.setOrigin(1, 0);
container.add(battleCountText); container.add(battleCountText);
return container; return container;
} }
getBattlesLeft(): integer { getBattleCount(): number {
return this.battlesLeft; return this.battleCount;
} }
getMaxStackCount(scene: BattleScene, forThreshold?: boolean): number { resetBattleCount(): void {
return 99; this.battleCount = this.maxBattles;
}
getMaxBattles(): number {
return this.maxBattles;
}
getArgs(): any[] {
return [ this.maxBattles, this.battleCount ];
}
getMaxStackCount(_scene: BattleScene, _forThreshold?: boolean): number {
return 1;
} }
} }
export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier { export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier {
constructor(type: ModifierTypes.DoubleBattleChanceBoosterModifierType, battlesLeft: integer, stackCount?: integer) { constructor(type: ModifierType, maxBattles:number, battleCount?: number, stackCount?: integer) {
super(type, battlesLeft, stackCount); super(type, maxBattles, battleCount, stackCount);
} }
match(modifier: Modifier): boolean { match(modifier: Modifier): boolean {
if (modifier instanceof DoubleBattleChanceBoosterModifier) { return (modifier instanceof DoubleBattleChanceBoosterModifier) && (modifier.getMaxBattles() === this.getMaxBattles());
// Check type id to not match different tiers of lures
return modifier.type.id === this.type.id && modifier.battlesLeft === this.battlesLeft;
}
return false;
} }
clone(): DoubleBattleChanceBoosterModifier { clone(): DoubleBattleChanceBoosterModifier {
return new DoubleBattleChanceBoosterModifier(this.type as ModifierTypes.DoubleBattleChanceBoosterModifierType, this.battlesLeft, this.stackCount); return new DoubleBattleChanceBoosterModifier(this.type as ModifierTypes.DoubleBattleChanceBoosterModifierType, this.getMaxBattles(), this.getBattleCount(), this.stackCount);
} }
getArgs(): any[] {
return [ this.battlesLeft ];
}
/** /**
* Modifies the chance of a double battle occurring * Modifies the chance of a double battle occurring
* @param args A single element array containing the double battle chance as a NumberHolder * @param args A single element array containing the double battle chance as a NumberHolder
@ -372,8 +413,8 @@ export class TempStatStageBoosterModifier extends LapsingPersistentModifier {
private stat: TempBattleStat; private stat: TempBattleStat;
private multiplierBoost: number; private multiplierBoost: number;
constructor(type: ModifierType, stat: TempBattleStat, battlesLeft?: number, stackCount?: number) { constructor(type: ModifierType, stat: TempBattleStat, maxBattles: number, battleCount?: number, stackCount?: number) {
super(type, battlesLeft ?? 5, stackCount); super(type, maxBattles, battleCount, stackCount);
this.stat = stat; this.stat = stat;
// Note that, because we want X Accuracy to maintain its original behavior, // Note that, because we want X Accuracy to maintain its original behavior,
@ -381,6 +422,7 @@ export class TempStatStageBoosterModifier extends LapsingPersistentModifier {
this.multiplierBoost = stat !== Stat.ACC ? 0.3 : 1; this.multiplierBoost = stat !== Stat.ACC ? 0.3 : 1;
} }
match(modifier: Modifier): boolean { match(modifier: Modifier): boolean {
if (modifier instanceof TempStatStageBoosterModifier) { if (modifier instanceof TempStatStageBoosterModifier) {
const modifierInstance = modifier as TempStatStageBoosterModifier; const modifierInstance = modifier as TempStatStageBoosterModifier;
@ -390,11 +432,11 @@ export class TempStatStageBoosterModifier extends LapsingPersistentModifier {
} }
clone() { clone() {
return new TempStatStageBoosterModifier(this.type, this.stat, this.battlesLeft, this.stackCount); return new TempStatStageBoosterModifier(this.type, this.stat, this.getMaxBattles(), this.getBattleCount(), this.stackCount);
} }
getArgs(): any[] { getArgs(): any[] {
return [ this.stat, this.battlesLeft ]; return [ this.stat, ...super.getArgs() ];
} }
/** /**
@ -417,36 +459,6 @@ export class TempStatStageBoosterModifier extends LapsingPersistentModifier {
(args[1] as Utils.NumberHolder).value += this.multiplierBoost; (args[1] as Utils.NumberHolder).value += this.multiplierBoost;
return true; return true;
} }
/**
* Goes through existing modifiers for any that match the selected modifier,
* which will then either add it to the existing modifiers if none were found
* or, if one was found, it will refresh {@linkcode battlesLeft}.
* @param modifiers {@linkcode PersistentModifier} array of the player's modifiers
* @param _virtual N/A
* @param _scene N/A
* @returns true if the modifier was successfully added or applied, false otherwise
*/
add(modifiers: PersistentModifier[], _virtual: boolean, _scene: BattleScene): boolean {
for (const modifier of modifiers) {
if (this.match(modifier)) {
const modifierInstance = modifier as TempStatStageBoosterModifier;
if (modifierInstance.getBattlesLeft() < 5) {
modifierInstance.battlesLeft = 5;
return true;
}
// should never get here
return false;
}
}
modifiers.push(this);
return true;
}
getMaxStackCount(_scene: BattleScene, _forThreshold?: boolean): number {
return 1;
}
} }
/** /**
@ -456,12 +468,12 @@ export class TempStatStageBoosterModifier extends LapsingPersistentModifier {
* @see {@linkcode apply} * @see {@linkcode apply}
*/ */
export class TempCritBoosterModifier extends LapsingPersistentModifier { export class TempCritBoosterModifier extends LapsingPersistentModifier {
constructor(type: ModifierType, battlesLeft?: integer, stackCount?: number) { constructor(type: ModifierType, maxBattles: number, battleCount?: number, stackCount?: number) {
super(type, battlesLeft || 5, stackCount); super(type, maxBattles, battleCount, stackCount);
} }
clone() { clone() {
return new TempCritBoosterModifier(this.type, this.stackCount); return new TempCritBoosterModifier(this.type, this.getMaxBattles(), this.getBattleCount(), this.stackCount);
} }
match(modifier: Modifier): boolean { match(modifier: Modifier): boolean {
@ -486,36 +498,6 @@ export class TempCritBoosterModifier extends LapsingPersistentModifier {
(args[0] as Utils.NumberHolder).value++; (args[0] as Utils.NumberHolder).value++;
return true; return true;
} }
/**
* Goes through existing modifiers for any that match the selected modifier,
* which will then either add it to the existing modifiers if none were found
* or, if one was found, it will refresh {@linkcode battlesLeft}.
* @param modifiers {@linkcode PersistentModifier} array of the player's modifiers
* @param _virtual N/A
* @param _scene N/A
* @returns true if the modifier was successfully added or applied, false otherwise
*/
add(modifiers: PersistentModifier[], _virtual: boolean, _scene: BattleScene): boolean {
for (const modifier of modifiers) {
if (this.match(modifier)) {
const modifierInstance = modifier as TempCritBoosterModifier;
if (modifierInstance.getBattlesLeft() < 5) {
modifierInstance.battlesLeft = 5;
return true;
}
// should never get here
return false;
}
}
modifiers.push(this);
return true;
}
getMaxStackCount(_scene: BattleScene, _forThreshold?: boolean): number {
return 1;
}
} }
export class MapModifier extends PersistentModifier { export class MapModifier extends PersistentModifier {

View File

@ -449,6 +449,16 @@ export function rgbaToInt(rgba: integer[]): integer {
return (rgba[0] << 24) + (rgba[1] << 16) + (rgba[2] << 8) + rgba[3]; return (rgba[0] << 24) + (rgba[1] << 16) + (rgba[2] << 8) + rgba[3];
} }
export function hslToHex(h: number, s: number, l: number) {
const a = s * Math.min(l, 1 - l);
const f = (n: number) => {
const k = (n + h / 30) % 12;
const rgb = l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));
return Math.round(rgb * 255).toString(16).padStart(2, "0");
};
return `#${f(0)}${f(8)}${f(4)}`;
}
/*This function returns true if the current lang is available for some functions /*This function returns true if the current lang is available for some functions
If the lang is not in the function, it usually means that lang is going to use the default english version If the lang is not in the function, it usually means that lang is going to use the default english version
This function is used in: This function is used in: