Log item transfers

This commit is contained in:
RedstonewolfX 2024-07-12 10:44:03 -04:00
parent 8c12cb5483
commit 06b782cd06
6 changed files with 263 additions and 54 deletions

View File

@ -120,6 +120,7 @@ export default class BattleScene extends SceneBase {
public enableTutorials: boolean = import.meta.env.VITE_BYPASS_TUTORIAL === "1"; public enableTutorials: boolean = import.meta.env.VITE_BYPASS_TUTORIAL === "1";
public enableMoveInfo: boolean = true; public enableMoveInfo: boolean = true;
public enableRetries: boolean = false; public enableRetries: boolean = false;
public damageDisplay: string = "Off";
/** /**
* Determines the condition for a notification should be shown for Candy Upgrades * Determines the condition for a notification should be shown for Candy Upgrades
* - 0 = 'Off' * - 0 = 'Off'

View File

@ -16,6 +16,8 @@ import { Item } from "pokenode-ts";
import Trainer from "./field/trainer"; import Trainer from "./field/trainer";
import { Species } from "./enums/species"; import { Species } from "./enums/species";
import { junit } from "node:test/reporters"; import { junit } from "node:test/reporters";
import { i } from "vitest/dist/reporters-xEmem8D4.js";
import { GameModes } from "./game-mode";
/** /**
* All logs. * All logs.
@ -38,6 +40,33 @@ export const logKeys: string[] = [
"d", // Debug "d", // Debug
]; ];
export function getLogID(scene: BattleScene) {
return "drpd_log:" + scene.seed
}
export function getLogs() {
while(logs.length > 0)
logs.pop()
for (var i = 0; i < localStorage.length; i++) {
if (localStorage.key(i).substring(0, 9) == "drpd_log:") {
logs.push(["drpd.json", localStorage.key(i), localStorage.key(i).substring(9), "", "", ""])
}
}
}
export function getMode(scene: BattleScene) {
switch (scene.gameMode.modeId) {
case GameModes.CLASSIC:
return "Classic"
case GameModes.ENDLESS:
return "Endless"
case GameModes.SPLICED_ENDLESS:
return "Spliced Endless"
case GameModes.DAILY:
return "Daily"
case GameModes.CHALLENGE:
return "Challenge"
}
}
export const rarities = [] export const rarities = []
export const rarityslot = [0] export const rarityslot = [0]
@ -226,16 +255,23 @@ export function getSize(str: string) {
return d.toString() + filesizes[unit] return d.toString() + filesizes[unit]
} }
export function generateOption(i: integer): OptionSelectItem { export function generateOption(i: integer, saves: any): OptionSelectItem {
var filename: string = (JSON.parse(localStorage.getItem(logs[i][1])) as DRPD).title var filename: string = (JSON.parse(localStorage.getItem(logs[i][1])) as DRPD).title
var op: OptionSelectItem = { var op: OptionSelectItem = {
label: ` Export ${filename} (${getSize(printDRPD("", "", JSON.parse(localStorage.getItem(logs[i][1])) as DRPD))})`, label: `Export ${filename} (${getSize(printDRPD("", "", JSON.parse(localStorage.getItem(logs[i][1])) as DRPD))})`,
handler: () => { handler: () => {
downloadLogByID(i) downloadLogByID(i)
return false; return false;
} }
} }
for (var j = 0; j < saves.length; j++) {
console.log(saves[j].seed, logs[i][2], saves[j].seed == logs[i][2])
if (saves[j].seed == logs[i][2]) {
op.label = "[Slot " + (j + 1) + "]" + op.label.substring(6)
}
}
if (logs[i][4] != "") { if (logs[i][4] != "") {
op.label = " " + op.label
op.item = logs[i][4] op.item = logs[i][4]
} }
return op; return op;
@ -306,6 +342,7 @@ export function downloadLogByID(i: integer) {
export function logTeam(scene: BattleScene, floor: integer = undefined) { export function logTeam(scene: BattleScene, floor: integer = undefined) {
if (floor == undefined) floor = scene.currentBattle.waveIndex if (floor == undefined) floor = scene.currentBattle.waveIndex
var team = scene.getEnemyParty() var team = scene.getEnemyParty()
console.log("Log Enemy Team")
if (team[0].hasTrainer()) { if (team[0].hasTrainer()) {
//var sprite = scene.currentBattle.trainer.config.getSpriteKey() //var sprite = scene.currentBattle.trainer.config.getSpriteKey()
//var trainerCat = Utils.getEnumKeys(TrainerType)[Utils.getEnumValues(TrainerType).indexOf(scene.currentBattle.trainer.config.trainerType)] //var trainerCat = Utils.getEnumKeys(TrainerType)[Utils.getEnumValues(TrainerType).indexOf(scene.currentBattle.trainer.config.trainerType)]
@ -320,20 +357,47 @@ export function logTeam(scene: BattleScene, floor: integer = undefined) {
} }
} }
export function logActions(scene: BattleScene, floor: integer, action: string) { export function logActions(scene: BattleScene, floor: integer, action: string) {
if (localStorage.getItem("drpd") == null) localStorage.setItem("drpd", JSON.stringify(newDocument())) if (localStorage.getItem(getLogID(scene)) == null) localStorage.setItem(getLogID(scene), JSON.stringify(newDocument(getMode(scene) + " Run")))
var drpd: DRPD = JSON.parse(localStorage.getItem("drpd")) as DRPD; var drpd: DRPD = JSON.parse(localStorage.getItem(getLogID(scene))) as DRPD;
var wv: Wave = getWave(drpd, floor, scene) console.log("Log Action", drpd)
wv.actions.push(action) var wv: Wave = getWave(drpd, floor, scene)
console.log(drpd) wv.actions.push(action)
localStorage.setItem("drpd", JSON.stringify(drpd)) console.log(drpd)
localStorage.setItem(getLogID(scene), JSON.stringify(drpd))
}
export function logShop(scene: BattleScene, floor: integer, action: string) {
if (localStorage.getItem(getLogID(scene)) == null) localStorage.setItem(getLogID(scene), JSON.stringify(newDocument(getMode(scene) + " Run")))
var drpd: DRPD = JSON.parse(localStorage.getItem(getLogID(scene))) as DRPD;
console.log("Log Shop Item", drpd)
var wv: Wave = getWave(drpd, floor, scene)
wv.shop = action
console.log(drpd)
localStorage.setItem(getLogID(scene), JSON.stringify(drpd))
} }
export function getWave(drpd: DRPD, floor: integer, scene: BattleScene) { export function getWave(drpd: DRPD, floor: integer, scene: BattleScene) {
var wv: Wave; var wv: Wave;
var insertPos: integer; var insertPos: integer;
console.log(drpd.waves)
if (drpd.waves[floor - 1] != undefined) {
return drpd.waves[floor - 1]
}
drpd.waves[floor - 1] = {
id: floor,
reload: false,
//type: floor % 10 == 0 ? "boss" : (floor % 10 == 5 ? "trainer" : "wild"),
type: floor % 10 == 0 ? "boss" : "wild",
double: scene.currentBattle.double,
actions: [],
shop: "",
biome: getBiomeName(scene.arena.biomeType),
pokemon: []
}
return drpd.waves[floor - 1]
for (var i = 0; i < drpd.waves.length; i++) { for (var i = 0; i < drpd.waves.length; i++) {
if (drpd.waves[i] != undefined) { if (drpd.waves[i] != undefined && drpd.waves[i] != null) {
if (drpd.waves[i].id == floor) { if (drpd.waves[i].id == floor) {
wv = drpd.waves[i] wv = drpd.waves[i]
console.log("Found wave for floor " + floor + " at index " + i)
if (wv.pokemon == undefined) wv.pokemon = [] if (wv.pokemon == undefined) wv.pokemon = []
} }
} else if (insertPos == undefined) { } else if (insertPos == undefined) {
@ -341,6 +405,7 @@ export function getWave(drpd: DRPD, floor: integer, scene: BattleScene) {
} }
} }
if (wv == undefined && insertPos != undefined) { if (wv == undefined && insertPos != undefined) {
console.log("Created new wave for floor " + floor + " at index " + insertPos)
drpd.waves[insertPos] = { drpd.waves[insertPos] = {
id: floor, id: floor,
reload: false, reload: false,
@ -392,9 +457,10 @@ export function getWave(drpd: DRPD, floor: integer, scene: BattleScene) {
console.error("Go yell at @redstonewolf8557 to fix this") console.error("Go yell at @redstonewolf8557 to fix this")
} else { } else {
for (var i = 0; i < drpd.waves.length; i++) { for (var i = 0; i < drpd.waves.length; i++) {
if (drpd.waves[i] != undefined) { if (drpd.waves[i] != undefined && drpd.waves[i] != null) {
if (drpd.waves[i].id == floor) { if (drpd.waves[i].id == floor) {
wv = drpd.waves[i] wv = drpd.waves[i]
console.log("Found wave for floor " + floor + " at index " + i)
if (wv.pokemon == undefined) wv.pokemon = [] if (wv.pokemon == undefined) wv.pokemon = []
} }
} else if (insertPos == undefined) { } else if (insertPos == undefined) {
@ -402,6 +468,7 @@ export function getWave(drpd: DRPD, floor: integer, scene: BattleScene) {
} }
} }
if (wv == undefined && insertPos != undefined) { if (wv == undefined && insertPos != undefined) {
console.log("Created new wave for floor " + floor + " at index " + insertPos)
drpd.waves[insertPos] = { drpd.waves[insertPos] = {
id: floor, id: floor,
reload: false, reload: false,
@ -479,8 +546,9 @@ export function logPokemon(scene: BattleScene, floor: integer = undefined, slot:
setRow("e", newLine, floor, slot) setRow("e", newLine, floor, slot)
//console.log(localStorage.getItem(logs[logKeys.indexOf("e")][1]).split("\n")) //console.log(localStorage.getItem(logs[logKeys.indexOf("e")][1]).split("\n"))
*/ */
if (localStorage.getItem("drpd") == null) localStorage.setItem("drpd", JSON.stringify(newDocument())) if (localStorage.getItem(getLogID(scene)) == null) localStorage.setItem(getLogID(scene), JSON.stringify(newDocument(getMode(scene) + " Run")))
var drpd: DRPD = JSON.parse(localStorage.getItem("drpd")) as DRPD; var drpd: DRPD = JSON.parse(localStorage.getItem(getLogID(scene))) as DRPD;
console.log("Log Enemy Pokemon", drpd)
var wv: Wave = getWave(drpd, floor, scene) var wv: Wave = getWave(drpd, floor, scene)
var pk: PokeData = exportPokemon(pokemon, encounterRarity) var pk: PokeData = exportPokemon(pokemon, encounterRarity)
if (wv.pokemon[slot] != undefined) { if (wv.pokemon[slot] != undefined) {
@ -537,36 +605,33 @@ export function logPokemon(scene: BattleScene, floor: integer = undefined, slot:
} }
if (pk.rarity == undefined) pk.rarity = "[Unknown]" if (pk.rarity == undefined) pk.rarity = "[Unknown]"
wv.pokemon[slot] = pk; wv.pokemon[slot] = pk;
while (wv.actions.length > 0)
wv.actions.pop()
console.log(drpd) console.log(drpd)
localStorage.setItem("drpd", JSON.stringify(drpd)) localStorage.setItem(getLogID(scene), JSON.stringify(drpd))
}
export function resetWave(scene: BattleScene, floor: integer = undefined) {
if (localStorage.getItem("drpd") == null) localStorage.setItem("drpd", JSON.stringify(newDocument()))
var drpd: DRPD = JSON.parse(localStorage.getItem("drpd")) as DRPD;
drpd.waves[floor] = exportWave(scene)
console.log(drpd)
localStorage.setItem("drpd", JSON.stringify(drpd))
} }
export function logTrainer(scene: BattleScene, floor: integer = undefined) { export function logTrainer(scene: BattleScene, floor: integer = undefined) {
if (localStorage.getItem("drpd") == null) localStorage.setItem("drpd", JSON.stringify(newDocument())) if (localStorage.getItem(getLogID(scene)) == null) localStorage.setItem(getLogID(scene), JSON.stringify(newDocument(getMode(scene) + " Run")))
var drpd: DRPD = JSON.parse(localStorage.getItem("drpd")) as DRPD; var drpd: DRPD = JSON.parse(localStorage.getItem(getLogID(scene))) as DRPD;
console.log("Log Trainer", drpd)
var wv: Wave = getWave(drpd, floor, scene) var wv: Wave = getWave(drpd, floor, scene)
var t: TrainerData = exportTrainer(scene.currentBattle.trainer) var t: TrainerData = exportTrainer(scene.currentBattle.trainer)
wv.trainer = t wv.trainer = t
wv.type = "trainer" wv.type = "trainer"
console.log(drpd) console.log(drpd)
localStorage.setItem("drpd", JSON.stringify(drpd)) localStorage.setItem(getLogID(scene), JSON.stringify(drpd))
} }
export function logPlayerTeam(scene: BattleScene) { export function logPlayerTeam(scene: BattleScene) {
if (localStorage.getItem("drpd") == null) localStorage.setItem("drpd", JSON.stringify(newDocument())) if (localStorage.getItem(getLogID(scene)) == null) localStorage.setItem(getLogID(scene), JSON.stringify(newDocument(getMode(scene) + " Run")))
var drpd: DRPD = JSON.parse(localStorage.getItem("drpd")) as DRPD; var drpd: DRPD = JSON.parse(localStorage.getItem(getLogID(scene))) as DRPD;
//var wv: Wave = getWave(drpd, 1, scene) //var wv: Wave = getWave(drpd, 1, scene)
console.log("Log Player Starters", drpd)
var P = scene.getParty() var P = scene.getParty()
for (var i = 0; i < P.length; i++) { for (var i = 0; i < P.length; i++) {
drpd.starters[i] = exportPokemon(P[i]) drpd.starters[i] = exportPokemon(P[i])
} }
console.log(drpd) console.log(drpd)
localStorage.setItem("drpd", JSON.stringify(drpd)) localStorage.setItem(getLogID(scene), JSON.stringify(drpd))
} }
export function dataSorter(a: string, b: string) { export function dataSorter(a: string, b: string) {

View File

@ -409,9 +409,10 @@ export class TitlePhase extends Phase {
logMenu(): boolean { logMenu(): boolean {
const options: OptionSelectItem[] = []; const options: OptionSelectItem[] = [];
LoggerTools.getLogs()
for (var i = 0; i < LoggerTools.logs.length; i++) { for (var i = 0; i < LoggerTools.logs.length; i++) {
if (localStorage.getItem(LoggerTools.logs[i][1]) != null) { if (localStorage.getItem(LoggerTools.logs[i][1]) != null) {
options.push(LoggerTools.generateOption(i) as OptionSelectItem) options.push(LoggerTools.generateOption(i, this.getSaves()) as OptionSelectItem)
} else { } else {
//options.push(LoggerTools.generateAddOption(i, this.scene, this)) //options.push(LoggerTools.generateAddOption(i, this.scene, this))
} }
@ -1324,7 +1325,7 @@ export class EncounterPhase extends BattlePhase {
doEncounterCommon(showEncounterMessage: boolean = true) { doEncounterCommon(showEncounterMessage: boolean = true) {
const enemyField = this.scene.getEnemyField(); const enemyField = this.scene.getEnemyField();
LoggerTools.resetWave(this.scene, this.scene.currentBattle.waveIndex) //LoggerTools.resetWave(this.scene, this.scene.currentBattle.waveIndex)
LoggerTools.logTeam(this.scene, this.scene.currentBattle.waveIndex) LoggerTools.logTeam(this.scene, this.scene.currentBattle.waveIndex)
if (this.scene.getEnemyParty()[0].hasTrainer()) { if (this.scene.getEnemyParty()[0].hasTrainer()) {
LoggerTools.logTrainer(this.scene, this.scene.currentBattle.waveIndex) LoggerTools.logTrainer(this.scene, this.scene.currentBattle.waveIndex)
@ -2743,20 +2744,6 @@ export class TurnStartPhase extends FieldPhase {
if (!queuedMove) { if (!queuedMove) {
continue; continue;
} }
const move = pokemon.getMoveset().find(m => m.moveId === queuedMove.move) || new PokemonMove(queuedMove.move);
if (!this.scene.currentBattle.double) {
playerActions.push(move.getName())
} else {
var T = this.getBattlers(pokemon)
for (var i = 0; i < T.length; i++) {
if (T[i] == undefined) {
T.splice(i, 1)
i--
}
}
console.log(queuedMove.targets, T, queuedMove.targets.map(p => T[p+1].name))
playerActions.push(move.getName() + " → " + queuedMove.targets.map(p => T[p+1].name).join(", "))
}
break; break;
case Command.BALL: case Command.BALL:
var ballNames = [ var ballNames = [
@ -4502,11 +4489,13 @@ export class VictoryPhase extends PokemonPhase {
if (this.scene.currentBattle.waveIndex % 10) { if (this.scene.currentBattle.waveIndex % 10) {
this.scene.pushPhase(new SelectModifierPhase(this.scene)); this.scene.pushPhase(new SelectModifierPhase(this.scene));
} else if (this.scene.gameMode.isDaily) { } else if (this.scene.gameMode.isDaily) {
LoggerTools.logShop(this.scene, this.scene.currentBattle.waveIndex, "")
this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.EXP_CHARM)); this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.EXP_CHARM));
if (this.scene.currentBattle.waveIndex > 10 && !this.scene.gameMode.isWaveFinal(this.scene.currentBattle.waveIndex)) { if (this.scene.currentBattle.waveIndex > 10 && !this.scene.gameMode.isWaveFinal(this.scene.currentBattle.waveIndex)) {
this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.GOLDEN_POKEBALL)); this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.GOLDEN_POKEBALL));
} }
} else { } else {
LoggerTools.logShop(this.scene, this.scene.currentBattle.waveIndex, "")
const superExpWave = !this.scene.gameMode.isEndless ? (this.scene.offsetGym ? 0 : 20) : 10; const superExpWave = !this.scene.gameMode.isEndless ? (this.scene.offsetGym ? 0 : 20) : 10;
if (this.scene.gameMode.isEndless && this.scene.currentBattle.waveIndex === 10) { if (this.scene.gameMode.isEndless && this.scene.currentBattle.waveIndex === 10) {
this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.EXP_SHARE)); this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.EXP_SHARE));
@ -4524,6 +4513,7 @@ export class VictoryPhase extends PokemonPhase {
} }
this.scene.pushPhase(new NewBattlePhase(this.scene)); this.scene.pushPhase(new NewBattlePhase(this.scene));
} else { } else {
LoggerTools.logShop(this.scene, this.scene.currentBattle.waveIndex, "")
this.scene.currentBattle.battleType = BattleType.CLEAR; this.scene.currentBattle.battleType = BattleType.CLEAR;
this.scene.score += this.scene.gameMode.getClearScoreBonus(); this.scene.score += this.scene.gameMode.getClearScoreBonus();
this.scene.updateScoreText(); this.scene.updateScoreText();
@ -5612,6 +5602,7 @@ export class AttemptRunPhase extends PokemonPhase {
if (playerPokemon.randSeedInt(256) < escapeChance.value) { if (playerPokemon.randSeedInt(256) < escapeChance.value) {
this.scene.playSound("flee"); this.scene.playSound("flee");
LoggerTools.logShop(this.scene, this.scene.currentBattle.waveIndex, "")
this.scene.queueMessage(i18next.t("battle:runAwaySuccess"), null, true, 500); this.scene.queueMessage(i18next.t("battle:runAwaySuccess"), null, true, 500);
this.scene.tweens.add({ this.scene.tweens.add({
@ -5672,6 +5663,7 @@ export class SelectModifierPhase extends BattlePhase {
if (rowCursor < 0 || cursor < 0) { if (rowCursor < 0 || cursor < 0) {
this.scene.ui.showText(i18next.t("battle:skipItemQuestion"), null, () => { this.scene.ui.showText(i18next.t("battle:skipItemQuestion"), null, () => {
this.scene.ui.setOverlayMode(Mode.CONFIRM, () => { this.scene.ui.setOverlayMode(Mode.CONFIRM, () => {
LoggerTools.logShop(this.scene, this.scene.currentBattle.waveIndex, "")
this.scene.ui.revertMode(); this.scene.ui.revertMode();
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
super.end(); super.end();
@ -5691,6 +5683,7 @@ export class SelectModifierPhase extends BattlePhase {
return false; return false;
} else { } else {
this.scene.reroll = true; this.scene.reroll = true;
LoggerTools.logActions(this.scene, this.scene.currentBattle.waveIndex, "Reroll" + (this.scene.lockModifierTiers ? " (Locked)" : ""))
this.scene.unshiftPhase(new SelectModifierPhase(this.scene, this.rerollCount + 1, typeOptions.map(o => o.type.tier))); this.scene.unshiftPhase(new SelectModifierPhase(this.scene, this.rerollCount + 1, typeOptions.map(o => o.type.tier)));
this.scene.ui.clearText(); this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end()); this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
@ -5701,11 +5694,17 @@ export class SelectModifierPhase extends BattlePhase {
} }
break; break;
case 1: case 1:
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer) => { this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer, isAll: boolean, isFirst: boolean) => {
if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) { if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) {
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[]; && (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[];
const itemModifier = itemModifiers[itemIndex]; const itemModifier = itemModifiers[itemIndex];
if (isAll) {
if (isFirst)
LoggerTools.logActions(this.scene, this.scene.currentBattle.waveIndex, "Transfer [" + (fromSlotIndex + 1) + "] " + this.scene.getParty()[fromSlotIndex].name + " (All) → [" + (toSlotIndex + 1) + "] " + this.scene.getParty()[toSlotIndex].name)
} else {
LoggerTools.logActions(this.scene, this.scene.currentBattle.waveIndex, "Transfer [" + (fromSlotIndex + 1) + "] " + this.scene.getParty()[fromSlotIndex].name + " (" + itemModifier.type.name + (itemQuantity == itemModifier.getStackCount() ? "" : " x" + itemQuantity) + ") → [" + (toSlotIndex + 1) + "] " + this.scene.getParty()[toSlotIndex].name)
}
this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity); this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity);
} else { } else {
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers)); this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers));

View File

@ -43,7 +43,8 @@ const AUTO_DISABLED: SettingOption[] = [
export enum SettingType { export enum SettingType {
GENERAL, GENERAL,
DISPLAY, DISPLAY,
AUDIO AUDIO,
MOD
} }
type SettingOption = { type SettingOption = {
@ -98,6 +99,7 @@ export const SettingKeys = {
SE_Volume: "SE_VOLUME", SE_Volume: "SE_VOLUME",
Music_Preference: "MUSIC_PREFERENCE", Music_Preference: "MUSIC_PREFERENCE",
Show_BGM_Bar: "SHOW_BGM_BAR", Show_BGM_Bar: "SHOW_BGM_BAR",
Damage_Display: "DAMAGE_DISPLAY"
}; };
/** /**
@ -242,6 +244,22 @@ export const Setting: Array<Setting> = [
default: 0, default: 0,
type: SettingType.GENERAL type: SettingType.GENERAL
}, },
{
key: SettingKeys.Damage_Display,
label: "Damage Display",
options: [{
label: "Off",
value: "Off"
}, {
label: "Value",
value: "Value"
}, {
label: "Percent",
value: "Percent"
}],
default: 0,
type: SettingType.GENERAL
},
{ {
key: SettingKeys.Tutorials, key: SettingKeys.Tutorials,
label: i18next.t("settings:tutorials"), label: i18next.t("settings:tutorials"),
@ -604,6 +622,8 @@ export function setSetting(scene: BattleScene, setting: string, value: integer):
case SettingKeys.Enable_Retries: case SettingKeys.Enable_Retries:
scene.enableRetries = Setting[index].options[value].value === "On"; scene.enableRetries = Setting[index].options[value].value === "On";
break; break;
case SettingKeys.Damage_Display:
scene.damageDisplay = Setting[index].options[value].value
case SettingKeys.Skip_Seen_Dialogues: case SettingKeys.Skip_Seen_Dialogues:
scene.skipSeenDialogues = Setting[index].options[value].value === "On"; scene.skipSeenDialogues = Setting[index].options[value].value === "On";
break; break;

View File

@ -15,15 +15,16 @@ import { Stat } from "#app/data/pokemon-stat.js";
import { Abilities } from "#app/enums/abilities.js"; import { Abilities } from "#app/enums/abilities.js";
import { WeatherType } from "#app/data/weather.js"; import { WeatherType } from "#app/data/weather.js";
import { Moves } from "#app/enums/moves.js"; import { Moves } from "#app/enums/moves.js";
import { AddSecondStrikeAbAttr, AllyMoveCategoryPowerBoostAbAttr, applyAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, ConditionalCritAbAttr, DamageBoostAbAttr, FieldMoveTypePowerBoostAbAttr, FieldPriorityMoveImmunityAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, MultCritAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, StabBoostAbAttr, TypeImmunityAbAttr, UserFieldMoveTypePowerBoostAbAttr, VariableMovePowerAbAttr } from "#app/data/ability.js"; import { AddSecondStrikeAbAttr, AllyMoveCategoryPowerBoostAbAttr, AlwaysHitAbAttr, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, ConditionalCritAbAttr, DamageBoostAbAttr, FieldMoveTypePowerBoostAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentEvasionAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, MultCritAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, StabBoostAbAttr, TypeImmunityAbAttr, UserFieldMoveTypePowerBoostAbAttr, VariableMovePowerAbAttr, WonderSkinAbAttr } from "#app/data/ability.js";
import { ArenaTagType } from "#app/enums/arena-tag-type.js"; import { ArenaTagType } from "#app/enums/arena-tag-type.js";
import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from "#app/data/arena-tag.js"; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from "#app/data/arena-tag.js";
import { BattlerTagLapseType, HelpingHandTag, TypeBoostTag } from "#app/data/battler-tags.js"; import { BattlerTagLapseType, HelpingHandTag, SemiInvulnerableTag, TypeBoostTag } from "#app/data/battler-tags.js";
import { TerrainType } from "#app/data/terrain.js"; import { TerrainType } from "#app/data/terrain.js";
import { AttackTypeBoosterModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, PokemonMultiHitModifier, TempBattleStatBoosterModifier } from "#app/modifier/modifier.js"; import { AttackTypeBoosterModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, PokemonMoveAccuracyBoosterModifier, PokemonMultiHitModifier, TempBattleStatBoosterModifier } from "#app/modifier/modifier.js";
import { BattlerTagType } from "#app/enums/battler-tag-type.js"; import { BattlerTagType } from "#app/enums/battler-tag-type.js";
import { TempBattleStat } from "#app/data/temp-battle-stat.js"; import { TempBattleStat } from "#app/data/temp-battle-stat.js";
import { StatusEffect } from "#app/data/status-effect.js"; import { StatusEffect } from "#app/data/status-effect.js";
import { BattleStat } from "#app/data/battle-stat.js";
export default class FightUiHandler extends UiHandler { export default class FightUiHandler extends UiHandler {
private movesContainer: Phaser.GameObjects.Container; private movesContainer: Phaser.GameObjects.Container;
@ -439,6 +440,117 @@ export default class FightUiHandler extends UiHandler {
return [damage1.value, damage2.value] return [damage1.value, damage2.value]
} }
calculateAccuracy(user: Pokemon, target: Pokemon, move: PokemonMove) {
if (this.scene.currentBattle.double && false) {
switch (move.getMove().moveTarget) {
case MoveData.MoveTarget.USER: // Targets yourself
return -1; // Moves targeting yourself always hit
case MoveData.MoveTarget.OTHER: // Targets one Pokemon
return move.getMove().accuracy
case MoveData.MoveTarget.ALL_OTHERS: // Targets all Pokemon
return move.getMove().accuracy;
case MoveData.MoveTarget.NEAR_OTHER: // Targets a Pokemon adjacent to the user
return move.getMove().accuracy;
case MoveData.MoveTarget.ALL_NEAR_OTHERS: // Targets all Pokemon adjacent to the user
return move.getMove().accuracy;
case MoveData.MoveTarget.NEAR_ENEMY: // Targets an opponent adjacent to the user
return move.getMove().accuracy;
case MoveData.MoveTarget.ALL_NEAR_ENEMIES: // Targets all opponents adjacent to the user
return move.getMove().accuracy;
case MoveData.MoveTarget.RANDOM_NEAR_ENEMY: // Targets a random opponent adjacent to the user
return move.getMove().accuracy;
case MoveData.MoveTarget.ALL_ENEMIES: // Targets all opponents
return move.getMove().accuracy;
case MoveData.MoveTarget.ATTACKER: // Counter move
return move.getMove().accuracy;
case MoveData.MoveTarget.NEAR_ALLY: // Targets an adjacent ally
return move.getMove().accuracy;
case MoveData.MoveTarget.ALLY: // Targets an ally
return move.getMove().accuracy;
case MoveData.MoveTarget.USER_OR_NEAR_ALLY: // Targets an ally or yourself
return move.getMove().accuracy;
case MoveData.MoveTarget.USER_AND_ALLIES: // Targets all on your side
return move.getMove().accuracy;
case MoveData.MoveTarget.ALL: // Targets everyone
return move.getMove().accuracy;
case MoveData.MoveTarget.USER_SIDE: // Targets your field
return move.getMove().accuracy;
case MoveData.MoveTarget.ENEMY_SIDE: // Targets enemy field
return -1; // Moves placing entry hazards always hit
case MoveData.MoveTarget.BOTH_SIDES: // Targets the entire field
return move.getMove().accuracy;
case MoveData.MoveTarget.PARTY: // Targets all of the Player's Pokemon, including ones that aren't active
return move.getMove().accuracy;
case MoveData.MoveTarget.CURSE:
return move.getMove().accuracy;
}
}
// Moves targeting the user and entry hazards can't miss
if ([MoveData.MoveTarget.USER, MoveData.MoveTarget.ENEMY_SIDE].includes(move.getMove().moveTarget)) {
return -1;
}
if (target == undefined) return move.getMove().accuracy;
// If either Pokemon has No Guard,
if (user.hasAbilityWithAttr(AlwaysHitAbAttr) || target.hasAbilityWithAttr(AlwaysHitAbAttr)) {
return -1;
}
// If the user should ignore accuracy on a target, check who the user targeted last turn and see if they match
if (user.getTag(BattlerTagType.IGNORE_ACCURACY) && (user.getLastXMoves().slice(1).find(() => true)?.targets || []).indexOf(target.getBattlerIndex()) !== -1) {
return -1;
}
const hiddenTag = target.getTag(SemiInvulnerableTag);
if (hiddenTag && !move.getMove().getAttrs(MoveData.HitsTagAttr).some(hta => hta.tagType === hiddenTag.tagType)) {
return 0;
}
const moveAccuracy = new Utils.NumberHolder(move.getMove().accuracy);
MoveData.applyMoveAttrs(MoveData.VariableAccuracyAttr, user, target, move.getMove(), moveAccuracy);
applyPreDefendAbAttrs(WonderSkinAbAttr, target, user, move.getMove(), { value: false }, moveAccuracy);
if (moveAccuracy.value === -1) {
return -1;
}
const isOhko = move.getMove().hasAttr(MoveData.OneHitKOAccuracyAttr);
if (!isOhko) {
user.scene.applyModifiers(PokemonMoveAccuracyBoosterModifier, user.isPlayer(), user, moveAccuracy);
}
if (this.scene.arena.weather?.weatherType === WeatherType.FOG) {
moveAccuracy.value = Math.floor(moveAccuracy.value * 0.9);
}
if (!isOhko && this.scene.arena.getTag(ArenaTagType.GRAVITY)) {
moveAccuracy.value = Math.floor(moveAccuracy.value * 1.67);
}
const userAccuracyLevel = new Utils.IntegerHolder(user.summonData.battleStats[BattleStat.ACC]);
const targetEvasionLevel = new Utils.IntegerHolder(target.summonData.battleStats[BattleStat.EVA]);
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, target, null, userAccuracyLevel);
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, user, null, targetEvasionLevel);
applyAbAttrs(IgnoreOpponentEvasionAbAttr, user, null, targetEvasionLevel);
MoveData.applyMoveAttrs(MoveData.IgnoreOpponentStatChangesAttr, user, target, move.getMove(), targetEvasionLevel);
this.scene.applyModifiers(TempBattleStatBoosterModifier, user.isPlayer(), TempBattleStat.ACC, userAccuracyLevel);
const accuracyMultiplier = new Utils.NumberHolder(1);
if (userAccuracyLevel.value !== targetEvasionLevel.value) {
accuracyMultiplier.value = userAccuracyLevel.value > targetEvasionLevel.value
? (3 + Math.min(userAccuracyLevel.value - targetEvasionLevel.value, 6)) / 3
: 3 / (3 + Math.min(targetEvasionLevel.value - userAccuracyLevel.value, 6));
}
applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, user, BattleStat.ACC, accuracyMultiplier, move.getMove());
const evasionMultiplier = new Utils.NumberHolder(1);
applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, target, BattleStat.EVA, evasionMultiplier);
accuracyMultiplier.value /= evasionMultiplier.value;
return moveAccuracy.value * accuracyMultiplier.value
}
calcDamage(scene: BattleScene, user: PlayerPokemon, target: Pokemon, move: PokemonMove) { calcDamage(scene: BattleScene, user: PlayerPokemon, target: Pokemon, move: PokemonMove) {
/* /*
var power = move.getMove().power var power = move.getMove().power
@ -535,11 +647,17 @@ export default class FightUiHandler extends UiHandler {
var percentChance = (target.hp - dmgLow + 1) / (dmgHigh - dmgLow + 1) var percentChance = (target.hp - dmgLow + 1) / (dmgHigh - dmgLow + 1)
koText = " (" + Math.round(percentChance * 100) + "% KO)" koText = " (" + Math.round(percentChance * 100) + "% KO)"
} }
return (Math.round(dmgLow) == Math.round(dmgHigh) ? Math.round(dmgLow).toString() : Math.round(dmgLow) + "-" + Math.round(dmgHigh)) + koText if (target.getMoveEffectiveness(user, move) == undefined) {
return "---"
}
if (scene.damageDisplay == "Value")
return target.getMoveEffectiveness(user, move) + "x - " + (Math.round(dmgLow) == Math.round(dmgHigh) ? Math.round(dmgLow).toString() : Math.round(dmgLow) + "-" + Math.round(dmgHigh)) + koText
dmgLow = Math.round((dmgLow)/target.getBattleStat(Stat.HP)*100) dmgLow = Math.round((dmgLow)/target.getBattleStat(Stat.HP)*100)
dmgHigh = Math.round((dmgHigh)/target.getBattleStat(Stat.HP)*100) dmgHigh = Math.round((dmgHigh)/target.getBattleStat(Stat.HP)*100)
return (dmgLow == dmgHigh ? dmgLow + "%" : dmgLow + "%-" + dmgHigh + "%") + koText if (scene.damageDisplay == "Percent")
return "???" return target.getMoveEffectiveness(user, move) + "x - " + (dmgLow == dmgHigh ? dmgLow + "%" : dmgLow + "%-" + dmgHigh + "%") + koText
if (scene.damageDisplay == "Off")
return target.getMoveEffectiveness(user, move) + "x"
} }
setCursor(cursor: integer): boolean { setCursor(cursor: integer): boolean {
@ -574,9 +692,15 @@ export default class FightUiHandler extends UiHandler {
const maxPP = pokemonMove.getMovePp(); const maxPP = pokemonMove.getMovePp();
const pp = maxPP - pokemonMove.ppUsed; const pp = maxPP - pokemonMove.ppUsed;
const accuracy1 = this.calculateAccuracy(pokemon, this.scene.getEnemyField()[0], pokemonMove)
const accuracy2 = this.calculateAccuracy(pokemon, this.scene.getEnemyField()[1], pokemonMove)
this.ppText.setText(`${Utils.padInt(pp, 2, " ")}/${Utils.padInt(maxPP, 2, " ")}`); this.ppText.setText(`${Utils.padInt(pp, 2, " ")}/${Utils.padInt(maxPP, 2, " ")}`);
this.powerText.setText(`${power >= 0 ? power : "---"}`); this.powerText.setText(`${power >= 0 ? power : "---"}`);
this.accuracyText.setText(`${accuracy >= 0 ? accuracy : "---"}`); this.accuracyText.setText(`${accuracy >= 0 ? accuracy : "---"}`);
this.accuracyText.setText(`${accuracy1 >= 0 ? accuracy1 : "---"}`);
if (this.scene.getEnemyField()[1] != undefined)
this.accuracyText.setText(`${accuracy1 >= 0 ? accuracy1 : "---"}/${accuracy2 >= 0 ? accuracy2 : "---"}`);
const ppPercentLeft = pp / maxPP; const ppPercentLeft = pp / maxPP;
@ -939,8 +1063,8 @@ export function simulateAttack(scene: BattleScene, user: Pokemon, target: Pokemo
applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, user, target, move, cancelled, damage1); applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, user, target, move, cancelled, damage1);
applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, user, target, move, cancelled, damage2); applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, user, target, move, cancelled, damage2);
console.log("damage (min)", damage1.value, move.name, power.value, sourceAtk, targetDef); //console.log("damage (min)", damage1.value, move.name, power.value, sourceAtk, targetDef);
console.log("damage (max)", damage2.value, move.name, power.value, sourceAtkCrit, targetDefCrit); //console.log("damage (max)", damage2.value, move.name, power.value, sourceAtkCrit, targetDefCrit);
// In case of fatal damage, this tag would have gotten cleared before we could lapse it. // In case of fatal damage, this tag would have gotten cleared before we could lapse it.
const destinyTag = target.getTag(BattlerTagType.DESTINY_BOND); const destinyTag = target.getTag(BattlerTagType.DESTINY_BOND);

View File

@ -63,7 +63,7 @@ export enum PartyOption {
} }
export type PartySelectCallback = (cursor: integer, option: PartyOption) => void; export type PartySelectCallback = (cursor: integer, option: PartyOption) => void;
export type PartyModifierTransferSelectCallback = (fromCursor: integer, index: integer, itemQuantity?: integer, toCursor?: integer) => void; export type PartyModifierTransferSelectCallback = (fromCursor: integer, index: integer, itemQuantity?: integer, toCursor?: integer, isAll?: boolean, isFirst?: boolean) => void;
export type PartyModifierSpliceSelectCallback = (fromCursor: integer, toCursor?: integer) => void; export type PartyModifierSpliceSelectCallback = (fromCursor: integer, toCursor?: integer) => void;
export type PokemonSelectFilter = (pokemon: PlayerPokemon) => string; export type PokemonSelectFilter = (pokemon: PlayerPokemon) => string;
export type PokemonModifierTransferSelectFilter = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => string; export type PokemonModifierTransferSelectFilter = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => string;
@ -326,7 +326,7 @@ export default class PartyUiHandler extends MessageUiHandler {
if (option === PartyOption.TRANSFER) { if (option === PartyOption.TRANSFER) {
if (this.transferCursor !== this.cursor) { if (this.transferCursor !== this.cursor) {
if (this.transferAll) { if (this.transferAll) {
getTransferrableItemsFromPokemon(this.scene.getParty()[this.transferCursor]).forEach((_, i) => (this.selectCallback as PartyModifierTransferSelectCallback)(this.transferCursor, i, this.transferQuantitiesMax[i], this.cursor)); getTransferrableItemsFromPokemon(this.scene.getParty()[this.transferCursor]).forEach((_, i) => (this.selectCallback as PartyModifierTransferSelectCallback)(this.transferCursor, i, this.transferQuantitiesMax[i], this.cursor, true, i == 0));
} else { } else {
(this.selectCallback as PartyModifierTransferSelectCallback)(this.transferCursor, this.transferOptionCursor, this.transferQuantities[this.transferOptionCursor], this.cursor); (this.selectCallback as PartyModifierTransferSelectCallback)(this.transferCursor, this.transferOptionCursor, this.transferQuantities[this.transferOptionCursor], this.cursor);
} }