mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-08 09:22:17 +02:00
Added changes to markdown files, reworked test boilerplate code + comment fixes
This commit is contained in:
parent
a6e87c8438
commit
4a96e9f7d0
2
.gitignore
vendored
2
.gitignore
vendored
@ -13,7 +13,7 @@ dist-ssr
|
|||||||
*.local
|
*.local
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.vscode/*
|
.vscode
|
||||||
.idea
|
.idea
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.suo
|
*.suo
|
||||||
|
@ -72,14 +72,16 @@ async function runInteractive() {
|
|||||||
|
|
||||||
const type = typeAnswer.selectedOption.toLowerCase();
|
const type = typeAnswer.selectedOption.toLowerCase();
|
||||||
// Convert fileName from kebab-case or camelCase to snake_case
|
// Convert fileName from kebab-case or camelCase to snake_case
|
||||||
|
// Ex: "Cud Chew/Cud-Chew" --> "cud_chew"
|
||||||
const fileName = fileNameAnswer.userInput
|
const fileName = fileNameAnswer.userInput
|
||||||
.replace(/-+/g, "_") // Convert kebab-case (dashes) to underscores
|
.replace(/-+/g, "_") // Convert kebab-case (dashes) to underscores
|
||||||
.replace(/([a-z])([A-Z])/g, "$1_$2") // Convert camelCase to snake_case
|
.replace(/([a-z])([A-Z])/g, "$1_$2") // Convert camelCase to snake_case
|
||||||
.replace(/\s+/g, "_") // Replace spaces with underscores
|
.replace(/\s+/g, "_") // Replace spaces with underscores
|
||||||
.toLowerCase(); // Ensure all lowercase
|
.toLowerCase(); // Ensure all lowercase
|
||||||
// Format the description for the test case
|
|
||||||
|
|
||||||
|
// Get proper english name for test names and data name for abilities/moves
|
||||||
const formattedName = fileName.replace(/_/g, " ").replace(/\b\w/g, char => char.toUpperCase());
|
const formattedName = fileName.replace(/_/g, " ").replace(/\b\w/g, char => char.toUpperCase());
|
||||||
|
const attrName = fileName.toUpperCase(); // Used for move/ability tests to override with ability/move being tested
|
||||||
// Determine the directory based on the type
|
// Determine the directory based on the type
|
||||||
let dir;
|
let dir;
|
||||||
let description;
|
let description;
|
||||||
@ -130,8 +132,8 @@ describe("${description}", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override
|
game.override
|
||||||
.moveset([ Moves.SPLASH ])
|
.moveset(Moves.${type === "move" ? attrName : "SPLASH"})
|
||||||
.ability(Abilities.BALL_FETCH)
|
.ability(Abilities.${type === "ability" ? attrName : "BALL_FETCH"})
|
||||||
.battleType("single")
|
.battleType("single")
|
||||||
.disableCrits()
|
.disableCrits()
|
||||||
.enemySpecies(Species.MAGIKARP)
|
.enemySpecies(Species.MAGIKARP)
|
||||||
|
@ -9,14 +9,14 @@
|
|||||||
- The best example of this is JSDoc-style comments as seen below:
|
- The best example of this is JSDoc-style comments as seen below:
|
||||||
- When formatted this way, the comment gets shown by intellisense in VS Code or similar IDEs just by hovering over the text!
|
- When formatted this way, the comment gets shown by intellisense in VS Code or similar IDEs just by hovering over the text!
|
||||||
- Functions also show each the comment for parameter as you type them, making keeping track of what each one does in lengthy functions much more clear
|
- Functions also show each the comment for parameter as you type them, making keeping track of what each one does in lengthy functions much more clear
|
||||||
```js
|
```ts
|
||||||
/**
|
/**
|
||||||
* Changes the type-based weather modifier if this move's power would be reduced by it
|
* Changes the type-based weather modifier if this move's power would be reduced by it
|
||||||
* @param user {@linkcode Pokemon} using this move
|
* @param user The {@linkcode Pokemon} using this move
|
||||||
* @param target {@linkcode Pokemon} target of this move
|
* @param target The {@linkcode Pokemon} being targeted by this move
|
||||||
* @param move {@linkcode Move} being used
|
* @param move The {@linkcode Move} being used
|
||||||
* @param args [0] {@linkcode Utils.NumberHolder} for arenaAttackTypeMultiplier
|
* @param args `[0]` {@linkcode Utils.NumberHolder} for arenaAttackTypeMultiplier
|
||||||
* @returns true if the function succeeds
|
* @returns `true` if the function succeeds
|
||||||
*/
|
*/
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ If you're interested in going more in depth, you can find a reference guide for
|
|||||||
While other classes should be fully documented, Abilities and Moves heavily incoperate inheritance (i.e. the `extends` keyword). Because of this, much of the functionality in these classes is duplicated or only slightly changed between classes.
|
While other classes should be fully documented, Abilities and Moves heavily incoperate inheritance (i.e. the `extends` keyword). Because of this, much of the functionality in these classes is duplicated or only slightly changed between classes.
|
||||||
### With this in mind, there's a few more things to keep in mind for these:
|
### With this in mind, there's a few more things to keep in mind for these:
|
||||||
- Do not document any parameters if the function mirrors the one they extend.
|
- Do not document any parameters if the function mirrors the one they extend.
|
||||||
- Keep this in mind for functions that are not the `apply` function as they are usually sparce and mostly reused
|
- Keep this in mind for functions that are not the `apply` function as they are usually sparse and mostly reused
|
||||||
- The class itself must be documented
|
- The class itself must be documented
|
||||||
- This must include the `@extends BaseClass` and `@see {@linkcode apply}` tags
|
- This must include the `@extends BaseClass` and `@see {@linkcode apply}` tags
|
||||||
- Class member variables must be documented
|
- Class member variables must be documented
|
||||||
|
@ -75,7 +75,13 @@ In `getNextMove()`, the enemy Pokémon chooses a move to use in the following st
|
|||||||
|
|
||||||
As part of the move selection process, the enemy Pokémon must compute a **target score (TS)** for each legal target for each move in its move pool. The base target score for all moves is a combination of the move's **user benefit score (UBS)** and **target benefit score (TBS)**.
|
As part of the move selection process, the enemy Pokémon must compute a **target score (TS)** for each legal target for each move in its move pool. The base target score for all moves is a combination of the move's **user benefit score (UBS)** and **target benefit score (TBS)**.
|
||||||
|
|
||||||

|
$$
|
||||||
|
\text{TS} = \text{UBS} + \text{TBS} \times
|
||||||
|
\begin{cases}
|
||||||
|
-1 & \text{if target is an opponent} \\
|
||||||
|
1 & \text{otherwise}
|
||||||
|
\end{cases}
|
||||||
|
$$
|
||||||
|
|
||||||
A move's UBS and TBS are computed with the respective functions in the `Move` class:
|
A move's UBS and TBS are computed with the respective functions in the `Move` class:
|
||||||
|
|
||||||
@ -98,14 +104,33 @@ In addition to the base score from `Move.getTargetBenefitScore()`, attack moves
|
|||||||
More specifically, the following steps are taken to compute the move's `attackScore`:
|
More specifically, the following steps are taken to compute the move's `attackScore`:
|
||||||
1. Compute a multiplier based on the move's type effectiveness:
|
1. Compute a multiplier based on the move's type effectiveness:
|
||||||
|
|
||||||
%7D%5C%5C-2&&%5Ctext%7Botherwise%7D%5C%5C%5Cend%7Bmatrix%7D%5Cright.)
|
$$
|
||||||
|
\text{typeMult} =
|
||||||
|
\begin{cases}
|
||||||
|
2 & \text{if move is super effective (or better)} \\
|
||||||
|
-2 & \text{otherwise}
|
||||||
|
\end{cases}
|
||||||
|
$$
|
||||||
2. Compute a multiplier based on the move's category and the user's offensive stats:
|
2. Compute a multiplier based on the move's category and the user's offensive stats:
|
||||||
1. Compute the user's offensive stat ratio:
|
1. Compute the user's offensive stat ratio:
|
||||||
|
|
||||||

|
$$
|
||||||
|
\text{statRatio} =
|
||||||
|
\begin{cases}
|
||||||
|
\frac{\text{userSpAtk}}{\text{userAtk}} & \text{if move is physical} \\
|
||||||
|
\frac{\text{userAtk}}{\text{userSpAtk}} & \text{otherwise}
|
||||||
|
\end{cases}
|
||||||
|
$$
|
||||||
2. Compute the stat-based multiplier:
|
2. Compute the stat-based multiplier:
|
||||||
|
|
||||||

|
$$
|
||||||
|
\text{statMult} =
|
||||||
|
\begin{cases}
|
||||||
|
2 & \text{if statRatio} \leq 0.75 \\
|
||||||
|
1.5 & \text{if } 0.75 \leq \text{statRatio} \leq 0.875 \\
|
||||||
|
1 & \text{otherwise}
|
||||||
|
\end{cases}
|
||||||
|
$$
|
||||||
3. Calculate the move's `attackScore`:
|
3. Calculate the move's `attackScore`:
|
||||||
|
|
||||||
$\text{attackScore} = (\text{typeMult}\times \text{statMult})+\lfloor \frac{\text{power}}{5} \rfloor$
|
$\text{attackScore} = (\text{typeMult}\times \text{statMult})+\lfloor \frac{\text{power}}{5} \rfloor$
|
||||||
@ -125,13 +150,26 @@ The final step to calculate an attack move's target score (TS) is to multiply th
|
|||||||
|
|
||||||
The enemy's target selection for single-target moves works in a very similar way to its move selection. Each potential target is given a **target selection score (TSS)** which is based on the move's [target benefit score](#calculating-move-and-target-scores) for that target:
|
The enemy's target selection for single-target moves works in a very similar way to its move selection. Each potential target is given a **target selection score (TSS)** which is based on the move's [target benefit score](#calculating-move-and-target-scores) for that target:
|
||||||
|
|
||||||

|
$$
|
||||||
|
\text{TSS} = \text{TBS} \times
|
||||||
|
\begin{cases}
|
||||||
|
-1 & \text{if target is an opponent} \\
|
||||||
|
1 & \text{otherwise}
|
||||||
|
\end{cases}
|
||||||
|
$$
|
||||||
|
|
||||||
Once the TSS is calculated for each target, the target is selected as follows:
|
Once the TSS is calculated for each target, the target is selected as follows:
|
||||||
1. Sort the targets (indexes) in decreasing order of their target selection scores (or weights). Let $t_i$ be the index of the *i*-th target in the sorted list, and let $w_i$ be that target's corresponding TSS.
|
1. Sort the targets (indexes) in decreasing order of their target selection scores (or weights). Let $t_i$ be the index of the *i*-th target in the sorted list, and let $w_i$ be that target's corresponding TSS.
|
||||||
2. Normalize the weights. Let $w_n$ be the lowest-weighted target in the sorted list, then:
|
2. Normalize the weights. Let $w_n$ be the lowest-weighted target in the sorted list, then:
|
||||||
|
|
||||||

|
$$
|
||||||
|
W_i =
|
||||||
|
\begin{cases}
|
||||||
|
w_i + |w_n| & \text{if } w_n \text{ is negative} \\
|
||||||
|
w_i & \text{otherwise}
|
||||||
|
\end{cases}
|
||||||
|
$$
|
||||||
|
|
||||||
3. Remove all weights from the list such that $W_i < \frac{W_0}{2}$
|
3. Remove all weights from the list such that $W_i < \frac{W_0}{2}$
|
||||||
4. Generate a random integer $R=\text{rand}(0, W_{\text{total}})$ where $W_{\text{total}}$ is the sum of all the remaining weights after Step 3.
|
4. Generate a random integer $R=\text{rand}(0, W_{\text{total}})$ where $W_{\text{total}}$ is the sum of all the remaining weights after Step 3.
|
||||||
5. For each target $(t_i, W_i)$,
|
5. For each target $(t_i, W_i)$,
|
||||||
|
@ -594,7 +594,7 @@ export function getLocalizedSpriteKey(baseKey: string) {
|
|||||||
* @returns `true` if number is **inclusive** between min and max
|
* @returns `true` if number is **inclusive** between min and max
|
||||||
*/
|
*/
|
||||||
export function isBetween(num: number, min: number, max: number): boolean {
|
export function isBetween(num: number, min: number, max: number): boolean {
|
||||||
return num >= min && num <= max;
|
return min <= num && num <= max;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -347,7 +347,10 @@ export default class GameManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Emulate selecting a modifier (item) */
|
/**
|
||||||
|
* Emulate selecting a modifier (item) the next time the {@linkcode SelectModifierPhase} occurs.
|
||||||
|
* Does not actually take anything (in fact, it just skips grabbing an item).
|
||||||
|
*/
|
||||||
doSelectModifier() {
|
doSelectModifier() {
|
||||||
this.onNextPrompt(
|
this.onNextPrompt(
|
||||||
"SelectModifierPhase",
|
"SelectModifierPhase",
|
||||||
@ -421,7 +424,9 @@ export default class GameManager {
|
|||||||
await this.phaseInterceptor.to(CommandPhase);
|
await this.phaseInterceptor.to(CommandPhase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Emulate selecting a modifier (item) and transition to the next upcoming {@linkcode CommandPhase} */
|
/**
|
||||||
|
* Emulate selecting a modifier (item) and transition to the next upcoming {@linkcode CommandPhase}.
|
||||||
|
*/
|
||||||
async toNextWave() {
|
async toNextWave() {
|
||||||
this.doSelectModifier();
|
this.doSelectModifier();
|
||||||
|
|
||||||
@ -512,8 +517,9 @@ export default class GameManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command an in-battle switch to another Pokemon via the main battle menu.
|
* Command an in-battle switch to another {@linkcode Pokemon} via the main battle menu.
|
||||||
* @param pokemonIndex the index of the pokemon in your party to switch to
|
* @param pokemonIndex the 0-indexed position of the party pokemon to switch to.
|
||||||
|
* Should generally never be called with 0 as that will just select your current active pokemon.
|
||||||
*/
|
*/
|
||||||
doSwitchPokemon(pokemonIndex: number) {
|
doSwitchPokemon(pokemonIndex: number) {
|
||||||
this.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
this.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
||||||
@ -540,7 +546,7 @@ export default class GameManager {
|
|||||||
* of the party UI, where you just need to navigate to a party slot and press
|
* of the party UI, where you just need to navigate to a party slot and press
|
||||||
* Action twice - navigating any menus that come up after you select a party member
|
* Action twice - navigating any menus that come up after you select a party member
|
||||||
* is not supported.
|
* is not supported.
|
||||||
* @param slot the index of the pokemon in your party to switch to
|
* @param slot the 0-indexed position of the pokemon in your party to switch to
|
||||||
* @param inPhase Which phase to expect the selection to occur in. Typically
|
* @param inPhase Which phase to expect the selection to occur in. Typically
|
||||||
* non-command switch actions happen in SwitchPhase.
|
* non-command switch actions happen in SwitchPhase.
|
||||||
*/
|
*/
|
||||||
@ -575,7 +581,8 @@ export default class GameManager {
|
|||||||
/**
|
/**
|
||||||
* Intercepts `TurnStartPhase` and mocks {@linkcode TurnStartPhase.getSpeedOrder}'s return value.
|
* Intercepts `TurnStartPhase` and mocks {@linkcode TurnStartPhase.getSpeedOrder}'s return value.
|
||||||
* Used to manually modify Pokemon turn order.
|
* Used to manually modify Pokemon turn order.
|
||||||
* Note: This *DOES NOT* account for priority, only speed.
|
|
||||||
|
* Note: This *DOES NOT* account for priority.
|
||||||
* @param {BattlerIndex[]} order The turn order to set
|
* @param {BattlerIndex[]} order The turn order to set
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
|
Loading…
Reference in New Issue
Block a user