Master merge (#7093)
This commit is contained in:
commit
192bc1ec20
@ -118,7 +118,8 @@
|
||||
"profile": "https://linktr.ee/pkmnsnfrn",
|
||||
"contributions": [
|
||||
"maintenance",
|
||||
"code"
|
||||
"code",
|
||||
"projectManagement"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -223,7 +224,7 @@
|
||||
"name": "Ruby",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/178652077?v=4",
|
||||
"profile": "https://github.com/RubyRaven6",
|
||||
"contributions": [
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
@ -255,10 +256,45 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "bassforte123",
|
||||
"name": "bassforte123",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/130828119?v=4",
|
||||
"profile": "https://github.com/bassforte123",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "iriv24",
|
||||
"name": "iriv24",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/40581123?v=4",
|
||||
"profile": "https://github.com/iriv24",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Bivurnum",
|
||||
"name": "Bivurnum",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/147376167?v=4",
|
||||
"profile": "https://github.com/Bivurnum",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ravepossum",
|
||||
"name": "RavePossum",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/145081120?v=4",
|
||||
"profile": "https://github.com/ravepossum",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
"linkToUsage": true,
|
||||
"commitType": "docs",
|
||||
"skipCi": true
|
||||
"commitType": "docs"
|
||||
}
|
||||
|
||||
9
.github/workflows/build.yml
vendored
9
.github/workflows/build.yml
vendored
@ -9,6 +9,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: github.actor != 'allcontributors[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GAME_VERSION: EMERALD
|
||||
@ -36,3 +37,11 @@ jobs:
|
||||
TEST: 1
|
||||
run: |
|
||||
make -j${nproc} check
|
||||
allcontributors:
|
||||
if: github.actor == 'allcontributors[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
needs: []
|
||||
steps:
|
||||
- name: Automatically pass for allcontributors
|
||||
run: echo "CI automatically passes for allcontributors" && exit 0
|
||||
|
||||
|
||||
9
.github/workflows/labels.yml
vendored
9
.github/workflows/labels.yml
vendored
@ -6,6 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
label:
|
||||
if: github.actor != 'allcontributors[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: check labels
|
||||
@ -27,3 +28,11 @@ jobs:
|
||||
category: pokemon
|
||||
category: sprite-issue
|
||||
type: documentation
|
||||
allcontributors:
|
||||
if: github.actor == 'allcontributors[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
needs: []
|
||||
steps:
|
||||
- name: Automatically pass for allcontributors
|
||||
run: echo "CI automatically passes for allcontributors" && exit 0
|
||||
|
||||
|
||||
16
CREDITS.md
16
CREDITS.md
@ -30,24 +30,28 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Pawkkie"><img src="https://avatars.githubusercontent.com/u/61265402?v=4?s=100" width="100px;" alt="Pawkkie"/><br /><sub><b>Pawkkie</b></sub></a><br /><a href="#maintenance-Pawkkie" title="Maintenance">🚧</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=Pawkkie" title="Code">💻</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=Pawkkie" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SBird1337"><img src="https://avatars.githubusercontent.com/u/3799173?v=4?s=100" width="100px;" alt="Philipp AUER"/><br /><sub><b>Philipp AUER</b></sub></a><br /><a href="#maintenance-SBird1337" title="Maintenance">🚧</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=SBird1337" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tertu-m"><img src="https://avatars.githubusercontent.com/u/836640?v=4?s=100" width="100px;" alt="tertu"/><br /><sub><b>tertu</b></sub></a><br /><a href="#maintenance-tertu-m" title="Maintenance">🚧</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=tertu-m" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://linktr.ee/pkmnsnfrn"><img src="https://avatars.githubusercontent.com/u/77138753?v=4?s=100" width="100px;" alt="psf"/><br /><sub><b>psf</b></sub></a><br /><a href="#maintenance-pkmnsnfrn" title="Maintenance">🚧</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=pkmnsnfrn" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://linktr.ee/pkmnsnfrn"><img src="https://avatars.githubusercontent.com/u/77138753?v=4?s=100" width="100px;" alt="psf"/><br /><sub><b>psf</b></sub></a><br /><a href="#maintenance-pkmnsnfrn" title="Maintenance">🚧</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=pkmnsnfrn" title="Code">💻</a> <a href="#projectManagement-pkmnsnfrn" title="Project Management">📆</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wiz1989"><img src="https://avatars.githubusercontent.com/u/80073265?v=4?s=100" width="100px;" alt="wiz1989"/><br /><sub><b>wiz1989</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=wiz1989" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PCG06"><img src="https://avatars.githubusercontent.com/u/75729017?v=4?s=100" width="100px;" alt="PCG"/><br /><sub><b>PCG</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=PCG06" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kittenchilly"><img src="https://avatars.githubusercontent.com/u/23617175?v=4?s=100" width="100px;" alt="kittenchilly"/><br /><sub><b>kittenchilly</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=kittenchilly" title="Code">💻</a> <a href="#research-kittenchilly" title="Research">🔬</a> <a href="#data-kittenchilly" title="Data">🔣</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ExpoSeed"><img src="https://avatars.githubusercontent.com/u/43502820?v=4?s=100" width="100px;" alt="ExpoSeed"/><br /><sub><b>ExpoSeed</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=ExpoSeed" title="Code">💻</a> <a href="#maintenance-ExpoSeed" title="Maintenance">🚧</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/pulls?q=is%3Apr+reviewed-by%3AExpoSeed" title="Reviewed Pull Requests">👀</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ExpoSeed"><img src="https://avatars.githubusercontent.com/u/43502820?v=4?s=100" width="100px;" alt="ExpoSeed"/><br /><sub><b>ExpoSeed</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=ExpoSeed" title="Code">💻</a> <a href="#maintenance-ExpoSeed" title="Maintenance">🚧</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/pulls?q=is%3Apr+reviewed-by%3AExpoSeed" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LinathanZel"><img src="https://avatars.githubusercontent.com/u/35115312?v=4?s=100" width="100px;" alt="Linathan"/><br /><sub><b>Linathan</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=LinathanZel" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AsparagusEduardo"><img src="https://avatars.githubusercontent.com/u/2904965?v=4?s=100" width="100px;" alt="Eduardo Quezada"/><br /><sub><b>Eduardo Quezada</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=AsparagusEduardo" title="Code">💻</a> <a href="#data-AsparagusEduardo" title="Data">🔣</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=AsparagusEduardo" title="Documentation">📖</a> <a href="#infra-AsparagusEduardo" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-AsparagusEduardo" title="Maintenance">🚧</a> <a href="#projectManagement-AsparagusEduardo" title="Project Management">📆</a> <a href="#promotion-AsparagusEduardo" title="Promotion">📣</a> <a href="#research-AsparagusEduardo" title="Research">🔬</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/pulls?q=is%3Apr+reviewed-by%3AAsparagusEduardo" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=AsparagusEduardo" title="Tests">⚠️</a> <a href="#tutorial-AsparagusEduardo" title="Tutorials">✅</a> <a href="#userTesting-AsparagusEduardo" title="User Testing">📓</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/khbsd"><img src="https://avatars.githubusercontent.com/u/26092020?v=4?s=100" width="100px;" alt="khbsd"/><br /><sub><b>khbsd</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=khbsd" title="Documentation">📖</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=khbsd" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Cafeei"><img src="https://avatars.githubusercontent.com/u/46283144?v=4?s=100" width="100px;" alt="Cafe"/><br /><sub><b>Cafe</b></sub></a><br /><a href="#design-Cafeei" title="Design">🎨</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/agsmgmaster64"><img src="https://avatars.githubusercontent.com/u/67435611?v=4?s=100" width="100px;" alt="agsmgmaster64"/><br /><sub><b>agsmgmaster64</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=agsmgmaster64" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mudskipper13"><img src="https://avatars.githubusercontent.com/u/105766191?v=4?s=100" width="100px;" alt="mudskipper13"/><br /><sub><b>mudskipper13</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=mudskipper13" title="Code">💻</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=mudskipper13" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RubyRaven6"><img src="https://avatars.githubusercontent.com/u/178652077?v=4?s=100" width="100px;" alt="Ruby"/><br /><sub><b>Ruby</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=RubyRaven6" title="Code">💻</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=RubyRaven6" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RubyRaven6"><img src="https://avatars.githubusercontent.com/u/178652077?v=4?s=100" width="100px;" alt="Ruby"/><br /><sub><b>Ruby</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=RubyRaven6" title="Code">💻</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=RubyRaven6" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/surskitty"><img src="https://avatars.githubusercontent.com/u/1383512?v=4?s=100" width="100px;" alt="surskitty"/><br /><sub><b>surskitty</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=surskitty" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wiz1989"><img src="https://avatars.githubusercontent.com/u/80073265?v=4?s=100" width="100px;" alt="wiz1989"/><br /><sub><b>wiz1989</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=wiz1989" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mudskipper13"><img src="https://avatars.githubusercontent.com/u/105766191?v=4?s=100" width="100px;" alt="mudskipper13"/><br /><sub><b>mudskipper13</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=mudskipper13" title="Code">💻</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=mudskipper13" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/surskitty"><img src="https://avatars.githubusercontent.com/u/1383512?v=4?s=100" width="100px;" alt="surskitty"/><br /><sub><b>surskitty</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=surskitty" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/grintoul1"><img src="https://avatars.githubusercontent.com/u/166724814?v=4?s=100" width="100px;" alt="grintoul"/><br /><sub><b>grintoul</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=grintoul1" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bassforte123"><img src="https://avatars.githubusercontent.com/u/130828119?v=4?s=100" width="100px;" alt="bassforte123"/><br /><sub><b>bassforte123</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=bassforte123" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/iriv24"><img src="https://avatars.githubusercontent.com/u/40581123?v=4?s=100" width="100px;" alt="iriv24"/><br /><sub><b>iriv24</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=iriv24" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Bivurnum"><img src="https://avatars.githubusercontent.com/u/147376167?v=4?s=100" width="100px;" alt="Bivurnum"/><br /><sub><b>Bivurnum</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=Bivurnum" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ravepossum"><img src="https://avatars.githubusercontent.com/u/145081120?v=4?s=100" width="100px;" alt="RavePossum"/><br /><sub><b>RavePossum</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=ravepossum" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
|
||||
@ -8285,7 +8285,9 @@ BattleScript_WanderingSpiritActivates::
|
||||
printstring STRINGID_SWAPPEDABILITIES
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
switchinabilities BS_ATTACKER
|
||||
jumpiffainted BS_TARGET, TRUE, BattleScript_WanderingSpiritActivatesRet
|
||||
switchinabilities BS_TARGET
|
||||
BattleScript_WanderingSpiritActivatesRet:
|
||||
return
|
||||
|
||||
BattleScript_TargetsStatWasMaxedOut::
|
||||
|
||||
@ -265,6 +265,15 @@ void SetCurrentDifficultyLevel(enum DifficultyLevel desiredDifficulty)
|
||||
.power = B_UPDATED_MOVE_DATA >= GEN_6 ? 45 : 35,
|
||||
},
|
||||
```
|
||||
### Variable Declarations
|
||||
Loop iterators should be declared as part of the loop unless there's a very good reason not to.
|
||||
```C
|
||||
for (u32 i = 0; i < LOOP_ITERATIONS; i++)
|
||||
{
|
||||
dst1[i] = i;
|
||||
dst2[i] = i;
|
||||
}
|
||||
```
|
||||
## Data Type Sizes
|
||||
When a variable number is used, the data type should generally `u32` (unsigned) or `s32` (signed). There are a few exceptions to this rule, such as:
|
||||
* Values stored in the saveblock should use the smallest data type possible.
|
||||
@ -350,7 +359,7 @@ enum DifficultyLevel GetCurrentDifficultyLevel(void)
|
||||
}
|
||||
```
|
||||
|
||||
### Data file format
|
||||
## Data file format
|
||||
|
||||
External data files should use JSON.
|
||||
|
||||
|
||||
@ -31,13 +31,13 @@ Export the palette and place into the same folder.
|
||||
Sadly, just putting the image files into the graphics folder is not enough. To use the sprites we have to register them by linking the graphic files.
|
||||
[src/data/graphics/trainers](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/graphics/trainers.h):
|
||||
```diff
|
||||
const u32 gTrainerPalette_RubySapphireBrendan[] = INCBIN_U32("graphics/trainers/palettes/ruby_sapphire_brendan.gbapal.lz");
|
||||
const u16 gTrainerPalette_RubySapphireBrendan[] = INCBIN_U16("graphics/trainers/palettes/ruby_sapphire_brendan.gbapal");
|
||||
|
||||
const u32 gTrainerFrontPic_RubySapphireMay[] = INCBIN_U32("graphics/trainers/front_pics/ruby_sapphire.4bpp.lz");
|
||||
const u32 gTrainerPalette_RubySapphireMay[] = INCBIN_U32("graphics/trainers/palettes/ruby_sapphire_may.gbapal.lz");
|
||||
const u16 gTrainerPalette_RubySapphireMay[] = INCBIN_U16("graphics/trainers/palettes/ruby_sapphire_may.gbapal");
|
||||
|
||||
+ const u32 gTrainerFrontPic_myTrainerClass[] = INCBIN_U32("graphics/trainers/front_pics/myTrainerClass.4bpp.lz");
|
||||
+ const u32 gTrainerPalette_myTrainerClass[] = INCBIN_U32("graphics/trainers/palettes/myTrainerClass.gbapal.lz");
|
||||
+ const u16 gTrainerPalette_myTrainerClass[] = INCBIN_U16("graphics/trainers/palettes/myTrainerClass.gbapal");
|
||||
|
||||
const u8 gTrainerBackPic_Brendan[] = INCBIN_U8("graphics/trainers/back_pics/brendan.4bpp");
|
||||
```
|
||||
|
||||
@ -72,41 +72,63 @@ enum {
|
||||
// (e.g. MarkBattlerForControllerExec) instead of using these macros
|
||||
// directly.
|
||||
|
||||
#define MARK_BATTLE_CONTROLLER_ACTIVE_ON_LOCAL(battler) \
|
||||
gBattleControllerExecFlags |= (1u << battler)
|
||||
static inline void MarkBattleControllerActiveOnLocal(u32 battler)
|
||||
{
|
||||
gBattleControllerExecFlags |= (1u << battler);
|
||||
}
|
||||
|
||||
#define MARK_BATTLE_CONTROLLER_IDLE_ON_LOCAL(battler) \
|
||||
gBattleControllerExecFlags &= ~(1u << battler)
|
||||
static inline void MarkBattleControllerIdleOnLocal(u32 battler)
|
||||
{
|
||||
gBattleControllerExecFlags &= ~(1u << battler);
|
||||
}
|
||||
|
||||
#define IS_BATTLE_CONTROLLER_ACTIVE_ON_LOCAL(battler) \
|
||||
(gBattleControllerExecFlags & (1u << battler))
|
||||
static inline bool32 IsBattleControllerActiveOnLocal(u32 battler)
|
||||
{
|
||||
return gBattleControllerExecFlags & (1u << battler);
|
||||
}
|
||||
|
||||
#define MARK_BATTLE_CONTROLLER_MESSAGE_OUTBOUND_OVER_LINK(battler) \
|
||||
gBattleControllerExecFlags |= ((1u << battler) << (32 - MAX_BATTLERS_COUNT))
|
||||
static inline void MarkBattleControllerMessageOutboundOverLink(u32 battler)
|
||||
{
|
||||
gBattleControllerExecFlags |= ((1u << battler) << (32 - MAX_BATTLERS_COUNT));
|
||||
}
|
||||
|
||||
#define MARK_BATTLE_CONTROLLER_MESSAGE_SYNCHRONIZED_OVER_LINK(battler) \
|
||||
gBattleControllerExecFlags &= ~((1 << 28) << (battler))
|
||||
static inline void MarkBattleControllerMessageSynchronizedOverLink(u32 battler)
|
||||
{
|
||||
gBattleControllerExecFlags &= ~((1 << 28) << (battler));
|
||||
}
|
||||
|
||||
#define MARK_BATTLE_CONTROLLER_ACTIVE_FOR_PLAYER(battler, playerId) \
|
||||
gBattleControllerExecFlags |= ((1u << battler) << ((playerId) << 2))
|
||||
static inline bool32 IsBattleControllerMessageSynchronizedOverLink(u32 battler)
|
||||
{
|
||||
return gBattleControllerExecFlags & (1u << (battler + 28));
|
||||
}
|
||||
|
||||
#define MARK_BATTLE_CONTROLLER_IDLE_FOR_PLAYER(battler, playerId) \
|
||||
gBattleControllerExecFlags &= ~((1u << battler) << ((playerId) * 4))
|
||||
static inline void MarkBattleControllerActiveForPlayer(u32 battler, u32 playerId)
|
||||
{
|
||||
gBattleControllerExecFlags |= ((1u << battler) << ((playerId) << 2));
|
||||
}
|
||||
|
||||
#define IS_BATTLE_CONTROLLER_ACTIVE_FOR_PLAYER(battler, playerId) \
|
||||
(gBattleControllerExecFlags & ((1u << battler) << ((playerId) * 4)))
|
||||
static inline void MarkBattleControllerIdleForPlayer(u32 battler, u32 playerId)
|
||||
{
|
||||
gBattleControllerExecFlags &= ~((1u << battler) << ((playerId) * 4));
|
||||
}
|
||||
|
||||
static inline bool32 IsBattleControllerActiveForPlayer(u32 battler, u32 playerId)
|
||||
{
|
||||
return gBattleControllerExecFlags & ((1u << battler) << ((playerId) * 4));
|
||||
}
|
||||
|
||||
// This actually checks if a specific controller is active on any player or if
|
||||
// *any* controller is pending sync over link communications, but the macro name
|
||||
// can only be so specific before it just gets ridiculous.
|
||||
#define IS_BATTLE_CONTROLLER_ACTIVE_OR_PENDING_SYNC_ANYWHERE(battler) \
|
||||
(gBattleControllerExecFlags & ( \
|
||||
(1u << battler) \
|
||||
| (0xF << 28) \
|
||||
| (1u << battler << 4) \
|
||||
| (1u << battler << 8) \
|
||||
| (1u << battler << 12) \
|
||||
))
|
||||
static inline bool32 IsBattleControllerActiveOrPendingSyncAnywhere(u32 battler)
|
||||
{
|
||||
return gBattleControllerExecFlags & (
|
||||
(1u << battler)
|
||||
| (0xF << 28)
|
||||
| (1u << battler << 4)
|
||||
| (1u << battler << 8)
|
||||
| (1u << battler << 12));
|
||||
}
|
||||
|
||||
// Special arguments for Battle Controller functions.
|
||||
|
||||
|
||||
@ -310,6 +310,7 @@ enum BattleMoveEffects
|
||||
EFFECT_COURT_CHANGE,
|
||||
EFFECT_MAX_HP_50_RECOIL,
|
||||
EFFECT_MIND_BLOWN, // Same as EFFECT_MAX_HP_50_RECOIL but is cancelled by Damp
|
||||
EFFECT_CHLOROBLAST, // Same effect as EFFECT_MAX_HP_50_RECOIL but follows the same rules as EFFECT_RECOIL
|
||||
EFFECT_EXTREME_EVOBOOST,
|
||||
EFFECT_HIT_SET_REMOVE_TERRAIN,
|
||||
EFFECT_DARK_VOID,
|
||||
|
||||
@ -5497,6 +5497,7 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
break;
|
||||
case EFFECT_MAX_HP_50_RECOIL:
|
||||
case EFFECT_MIND_BLOWN:
|
||||
case EFFECT_CHLOROBLAST:
|
||||
case EFFECT_SWAGGER:
|
||||
case EFFECT_FLATTER:
|
||||
case EFFECT_ATTRACT:
|
||||
|
||||
@ -1022,6 +1022,7 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s
|
||||
{
|
||||
case EFFECT_MAX_HP_50_RECOIL:
|
||||
case EFFECT_MIND_BLOWN:
|
||||
case EFFECT_CHLOROBLAST:
|
||||
case EFFECT_EXPLOSION:
|
||||
case EFFECT_MISTY_EXPLOSION:
|
||||
case EFFECT_FINAL_GAMBIT:
|
||||
|
||||
@ -3395,7 +3395,7 @@ void AnimTask_ScaryFace(u8 taskId)
|
||||
bool32 onPlayer;
|
||||
|
||||
if (gAnimMoveIndex == MOVE_BITTER_MALICE)
|
||||
onPlayer = IsOnPlayerSide(gBattleAnimAttacker);
|
||||
onPlayer = !IsOnPlayerSide(gBattleAnimAttacker);
|
||||
else
|
||||
onPlayer = !IsOnPlayerSide(gBattleAnimTarget);
|
||||
|
||||
|
||||
@ -114,7 +114,7 @@ void SetControllerToLinkOpponent(u32 battler)
|
||||
|
||||
static void LinkOpponentBufferRunCommand(u32 battler)
|
||||
{
|
||||
if (gBattleControllerExecFlags & (1u << battler))
|
||||
if (IsBattleControllerActiveOnLocal(battler))
|
||||
{
|
||||
if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sLinkOpponentBufferCommands))
|
||||
sLinkOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler);
|
||||
@ -320,7 +320,7 @@ static void LinkOpponentBufferExecCompleted(u32 battler)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleControllerExecFlags &= ~(1u << battler);
|
||||
MarkBattleControllerIdleOnLocal(battler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -113,7 +113,7 @@ void SetControllerToLinkPartner(u32 battler)
|
||||
|
||||
static void LinkPartnerBufferRunCommand(u32 battler)
|
||||
{
|
||||
if (gBattleControllerExecFlags & (1u << battler))
|
||||
if (IsBattleControllerActiveOnLocal(battler))
|
||||
{
|
||||
if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sLinkPartnerBufferCommands))
|
||||
sLinkPartnerBufferCommands[gBattleResources->bufferA[battler][0]](battler);
|
||||
@ -164,7 +164,7 @@ static void LinkPartnerBufferExecCompleted(u32 battler)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleControllerExecFlags &= ~(1u << battler);
|
||||
MarkBattleControllerIdleOnLocal(battler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -127,7 +127,7 @@ void SetControllerToOpponent(u32 battler)
|
||||
|
||||
static void OpponentBufferRunCommand(u32 battler)
|
||||
{
|
||||
if (gBattleControllerExecFlags & (1u << battler))
|
||||
if (IsBattleControllerActiveOnLocal(battler))
|
||||
{
|
||||
if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sOpponentBufferCommands))
|
||||
sOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler);
|
||||
@ -364,7 +364,7 @@ static void OpponentBufferExecCompleted(u32 battler)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleControllerExecFlags &= ~(1u << battler);
|
||||
MarkBattleControllerIdleOnLocal(battler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -182,13 +182,13 @@ static void PlayerBufferExecCompleted(u32 battler)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleControllerExecFlags &= ~(1u << battler);
|
||||
MarkBattleControllerIdleOnLocal(battler);
|
||||
}
|
||||
}
|
||||
|
||||
static void PlayerBufferRunCommand(u32 battler)
|
||||
{
|
||||
if (gBattleControllerExecFlags & (1u << battler))
|
||||
if (IsBattleControllerActiveOnLocal(battler))
|
||||
{
|
||||
if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sPlayerBufferCommands))
|
||||
sPlayerBufferCommands[gBattleResources->bufferA[battler][0]](battler);
|
||||
|
||||
@ -117,7 +117,7 @@ void SetControllerToPlayerPartner(u32 battler)
|
||||
|
||||
static void PlayerPartnerBufferRunCommand(u32 battler)
|
||||
{
|
||||
if (gBattleControllerExecFlags & (1u << battler))
|
||||
if (IsBattleControllerActiveOnLocal(battler))
|
||||
{
|
||||
if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sPlayerPartnerBufferCommands))
|
||||
sPlayerPartnerBufferCommands[gBattleResources->bufferA[battler][0]](battler);
|
||||
@ -236,7 +236,7 @@ static void PlayerPartnerBufferExecCompleted(u32 battler)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleControllerExecFlags &= ~(1u << battler);
|
||||
MarkBattleControllerIdleOnLocal(battler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -120,7 +120,7 @@ void SetControllerToRecordedOpponent(u32 battler)
|
||||
|
||||
static void RecordedOpponentBufferRunCommand(u32 battler)
|
||||
{
|
||||
if (gBattleControllerExecFlags & (1u << battler))
|
||||
if (IsBattleControllerActiveOnLocal(battler))
|
||||
{
|
||||
if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sRecordedOpponentBufferCommands))
|
||||
sRecordedOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler);
|
||||
@ -141,7 +141,7 @@ static void RecordedOpponentBufferExecCompleted(u32 battler)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleControllerExecFlags &= ~(1u << battler);
|
||||
MarkBattleControllerIdleOnLocal(battler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -117,7 +117,7 @@ void SetControllerToRecordedPlayer(u32 battler)
|
||||
|
||||
static void RecordedPlayerBufferRunCommand(u32 battler)
|
||||
{
|
||||
if (gBattleControllerExecFlags & (1u << battler))
|
||||
if (IsBattleControllerActiveOnLocal(battler))
|
||||
{
|
||||
if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sRecordedPlayerBufferCommands))
|
||||
sRecordedPlayerBufferCommands[gBattleResources->bufferA[battler][0]](battler);
|
||||
@ -313,7 +313,7 @@ static void RecordedPlayerBufferExecCompleted(u32 battler)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleControllerExecFlags &= ~(1u << battler);
|
||||
MarkBattleControllerIdleOnLocal(battler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -109,7 +109,7 @@ void SetControllerToSafari(u32 battler)
|
||||
|
||||
static void SafariBufferRunCommand(u32 battler)
|
||||
{
|
||||
if (gBattleControllerExecFlags & (1u << battler))
|
||||
if (IsBattleControllerActiveOnLocal(battler))
|
||||
{
|
||||
if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sSafariBufferCommands))
|
||||
sSafariBufferCommands[gBattleResources->bufferA[battler][0]](battler);
|
||||
@ -237,7 +237,7 @@ static void SafariBufferExecCompleted(u32 battler)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleControllerExecFlags &= ~(1u << battler);
|
||||
MarkBattleControllerIdleOnLocal(battler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -125,7 +125,7 @@ void SetControllerToWally(u32 battler)
|
||||
|
||||
static void WallyBufferRunCommand(u32 battler)
|
||||
{
|
||||
if (gBattleControllerExecFlags & (1u << battler))
|
||||
if (IsBattleControllerActiveOnLocal(battler))
|
||||
{
|
||||
if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sWallyBufferCommands))
|
||||
sWallyBufferCommands[gBattleResources->bufferA[battler][0]](battler);
|
||||
@ -284,7 +284,7 @@ static void WallyBufferExecCompleted(u32 battler)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleControllerExecFlags &= ~(1u << battler);
|
||||
MarkBattleControllerIdleOnLocal(battler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -956,7 +956,7 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId)
|
||||
switch (BYTE_TO_RECEIVE(0))
|
||||
{
|
||||
case B_COMM_TO_CONTROLLER:
|
||||
if (IS_BATTLE_CONTROLLER_ACTIVE_ON_LOCAL(battler))
|
||||
if (IsBattleControllerActiveOnLocal(battler))
|
||||
return;
|
||||
|
||||
memcpy(gBattleResources->bufferA[battler], &BYTE_TO_RECEIVE(LINK_BUFF_DATA), blockSize);
|
||||
@ -975,7 +975,7 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId)
|
||||
break;
|
||||
case B_COMM_CONTROLLER_IS_DONE:
|
||||
playerId = BYTE_TO_RECEIVE(LINK_BUFF_DATA);
|
||||
MARK_BATTLE_CONTROLLER_IDLE_FOR_PLAYER(battler, playerId);
|
||||
MarkBattleControllerIdleForPlayer(battler, playerId);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -490,7 +490,7 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler)
|
||||
gBattleStruct->eventBlockCounter++;
|
||||
break;
|
||||
case FIRST_EVENT_BLOCK_GRASSY_TERRAIN_HEAL:
|
||||
if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerAlive(battler) && !IsBattlerAtMaxHp(battler))
|
||||
if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerAlive(battler) && !IsBattlerAtMaxHp(battler) && IsBattlerGrounded(battler))
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
gBattleStruct->moveDamage[battler] = -(GetNonDynamaxMaxHP(battler) / 16);
|
||||
|
||||
@ -4210,7 +4210,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT_ACTION_CHOSEN: // Try to perform an action.
|
||||
if (!(gBattleControllerExecFlags & (((1u << battler)) | (0xF << 28) | ((1u << battler) << 4) | ((1u << battler) << 8) | ((1u << battler) << 12))))
|
||||
if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler))
|
||||
{
|
||||
RecordedBattle_SetBattlerAction(battler, gBattleResources->bufferB[battler][1]);
|
||||
gChosenActionByBattler[battler] = gBattleResources->bufferB[battler][1];
|
||||
@ -4414,7 +4414,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT_ACTION_CASE_CHOSEN:
|
||||
if (!(gBattleControllerExecFlags & (((1u << battler)) | (0xF << 28) | ((1u << battler) << 4) | ((1u << battler) << 8) | ((1u << battler) << 12))))
|
||||
if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler))
|
||||
{
|
||||
switch (gChosenActionByBattler[battler])
|
||||
{
|
||||
@ -4544,11 +4544,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT_ACTION_CONFIRMED_STANDBY:
|
||||
if (!(gBattleControllerExecFlags & ((1u << battler)
|
||||
| (0xF << 28)
|
||||
| (1u << (battler + 4))
|
||||
| (1u << (battler + 8))
|
||||
| (1u << (battler + 12)))))
|
||||
if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler))
|
||||
{
|
||||
if (AllAtActionConfirmed())
|
||||
i = TRUE;
|
||||
@ -4570,7 +4566,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT_ACTION_CONFIRMED:
|
||||
if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12)))))
|
||||
if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler))
|
||||
{
|
||||
gBattleCommunication[ACTIONS_CONFIRMED_COUNT]++;
|
||||
}
|
||||
@ -4584,7 +4580,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
gBattlescriptCurrInstr = gSelectionBattleScripts[battler];
|
||||
if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12)))))
|
||||
if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler))
|
||||
{
|
||||
gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
|
||||
}
|
||||
@ -4592,7 +4588,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT_SET_BEFORE_ACTION:
|
||||
if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12)))))
|
||||
if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler))
|
||||
{
|
||||
gBattleCommunication[battler] = STATE_BEFORE_ACTION_CHOSEN;
|
||||
}
|
||||
@ -4616,7 +4612,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
gBattlescriptCurrInstr = gSelectionBattleScripts[battler];
|
||||
if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12)))))
|
||||
if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler))
|
||||
{
|
||||
gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
|
||||
}
|
||||
@ -4651,7 +4647,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (gChosenActionByBattler[i] == B_ACTION_SWITCH)
|
||||
SwitchPartyOrderInGameMulti(i, gBattleStruct->monToSwitchIntoId[battler]);
|
||||
SwitchPartyOrderInGameMulti(i, gBattleStruct->monToSwitchIntoId[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4703,6 +4699,10 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h
|
||||
{
|
||||
u32 speed = gBattleMons[battler].speed;
|
||||
|
||||
// stat stages
|
||||
speed *= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPEED]][0];
|
||||
speed /= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPEED]][1];
|
||||
|
||||
// weather abilities
|
||||
if (HasWeatherEffect())
|
||||
{
|
||||
@ -4730,10 +4730,6 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h
|
||||
else if (ability == ABILITY_UNBURDEN && gDisableStructs[battler].unburdenActive)
|
||||
speed *= 2;
|
||||
|
||||
// stat stages
|
||||
speed *= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPEED]][0];
|
||||
speed /= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPEED]][1];
|
||||
|
||||
// player's badge boost
|
||||
if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_FRONTIER))
|
||||
&& ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_SPEED, battler)
|
||||
@ -6002,7 +5998,9 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState
|
||||
{
|
||||
return TYPE_WATER;
|
||||
}
|
||||
else if (moveEffect == EFFECT_AURA_WHEEL && species == SPECIES_MORPEKO_HANGRY)
|
||||
else if (moveEffect == EFFECT_AURA_WHEEL
|
||||
&& species == SPECIES_MORPEKO_HANGRY
|
||||
&& ability != ABILITY_NORMALIZE)
|
||||
{
|
||||
return TYPE_DARK;
|
||||
}
|
||||
@ -6016,7 +6014,9 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState
|
||||
gBattleStruct->ateBoost[battler] = TRUE;
|
||||
return ateType;
|
||||
}
|
||||
else if (moveType != TYPE_NORMAL
|
||||
else if (moveEffect != EFFECT_CHANGE_TYPE_ON_ITEM
|
||||
&& moveEffect != EFFECT_TERRAIN_PULSE
|
||||
&& moveEffect != EFFECT_NATURAL_GIFT
|
||||
&& moveEffect != EFFECT_HIDDEN_POWER
|
||||
&& moveEffect != EFFECT_WEATHER_BALL
|
||||
&& ability == ABILITY_NORMALIZE
|
||||
|
||||
@ -3164,7 +3164,7 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize)
|
||||
dst[dstID] = *src;
|
||||
dstID++;
|
||||
|
||||
BreakStringAutomatic(dst, BATTLE_MSG_MAX_WIDTH, BATTLE_MSG_MAX_LINES, fontId, TRUE);
|
||||
BreakStringAutomatic(dst, BATTLE_MSG_MAX_WIDTH, BATTLE_MSG_MAX_LINES, fontId, SHOW_SCROLL_PROMPT);
|
||||
|
||||
return dstID;
|
||||
}
|
||||
|
||||
@ -6991,6 +6991,15 @@ static void Cmd_moveend(void)
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_CHLOROBLAST:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker))
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
case EFFECT_RAPID_SPIN:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget))
|
||||
{
|
||||
@ -7393,6 +7402,12 @@ static void Cmd_moveend(void)
|
||||
SetActiveGimmick(gBattlerAttacker, GIMMICK_NONE);
|
||||
if (B_CHARGE >= GEN_9 && moveType == TYPE_ELECTRIC && (IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT))
|
||||
gStatuses3[gBattlerAttacker] &= ~(STATUS3_CHARGED_UP);
|
||||
// check if Stellar type boost should be used up
|
||||
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA
|
||||
&& GetBattlerTeraType(gBattlerAttacker) == TYPE_STELLAR
|
||||
&& GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS
|
||||
&& IsTypeStellarBoosted(gBattlerAttacker, moveType))
|
||||
ExpendTypeStellarBoost(gBattlerAttacker, moveType);
|
||||
memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts));
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
@ -7882,7 +7897,16 @@ static void Cmd_openpartyscreen(void)
|
||||
{
|
||||
if (((1u << i) & hitmarkerFaintBits))
|
||||
{
|
||||
if (i > 1 && ((1u << BATTLE_PARTNER(i)) & hitmarkerFaintBits))
|
||||
u32 skipPartnerCheck = FALSE;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS
|
||||
&& GetBattlerSide(i) == B_SIDE_OPPONENT
|
||||
&& TRAINER_BATTLE_PARAM.opponentB != TRAINER_NONE)
|
||||
skipPartnerCheck = TRUE;
|
||||
|
||||
// In a 1v2 Double Battle if trainer A didn't have any more mons left
|
||||
// the battler for trainer B wasn't being registered to be send out.
|
||||
// Likely reason is because hitmarkerFaintBits was not set for battler 1 due to it being missing for a turn or cleared somewhere
|
||||
if (!skipPartnerCheck && i > 1 && ((1u << BATTLE_PARTNER(i)) & hitmarkerFaintBits))
|
||||
continue;
|
||||
|
||||
battler = i;
|
||||
|
||||
@ -545,6 +545,16 @@ void HandleAction_UseMove(void)
|
||||
void HandleAction_Switch(void)
|
||||
{
|
||||
gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
|
||||
|
||||
// if switching to a mon that is already on field, cancel switch
|
||||
if (!(gAbsentBattlerFlags & (1u << BATTLE_PARTNER(gBattlerAttacker)))
|
||||
&& IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker))
|
||||
&& gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)] == gBattleStruct->monToSwitchIntoId[gBattlerAttacker])
|
||||
{
|
||||
gCurrentActionFuncId = B_ACTION_FINISHED;
|
||||
return;
|
||||
}
|
||||
|
||||
gBattle_BG0_X = 0;
|
||||
gBattle_BG0_Y = 0;
|
||||
gActionSelectionCursor[gBattlerAttacker] = 0;
|
||||
@ -851,7 +861,7 @@ void HandleAction_NothingIsFainted(void)
|
||||
|
||||
void HandleAction_ActionFinished(void)
|
||||
{
|
||||
u32 i, j, moveType;
|
||||
u32 i, j;
|
||||
bool32 afterYouActive = gSpecialStatuses[gBattlerByTurnOrder[gCurrentTurnActionNumber + 1]].afterYou;
|
||||
gBattleStruct->monToSwitchIntoId[gBattlerByTurnOrder[gCurrentTurnActionNumber]] = gSelectedMonPartyId = PARTY_SIZE;
|
||||
gCurrentTurnActionNumber++;
|
||||
@ -862,16 +872,6 @@ void HandleAction_ActionFinished(void)
|
||||
| HITMARKER_OBEYS | HITMARKER_SYNCHRONIZE_EFFECT
|
||||
| HITMARKER_CHARGING | HITMARKER_IGNORE_DISGUISE);
|
||||
|
||||
// check if Stellar type boost should be used up
|
||||
moveType = GetBattleMoveType(gCurrentMove);
|
||||
|
||||
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA
|
||||
&& GetBattlerTeraType(gBattlerAttacker) == TYPE_STELLAR
|
||||
&& GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS
|
||||
&& IsTypeStellarBoosted(gBattlerAttacker, moveType))
|
||||
{
|
||||
ExpendTypeStellarBoost(gBattlerAttacker, moveType);
|
||||
}
|
||||
ClearDamageCalcResults();
|
||||
gCurrentMove = 0;
|
||||
gBattleScripting.animTurn = 0;
|
||||
@ -988,29 +988,29 @@ static void UNUSED MarkAllBattlersForControllerExec(void)
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
|
||||
{
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gBattleControllerExecFlags |= 1u << (i + 32 - MAX_BATTLERS_COUNT);
|
||||
MarkBattleControllerMessageOutboundOverLink(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gBattleControllerExecFlags |= 1u << i;
|
||||
MarkBattleControllerActiveOnLocal(i);
|
||||
}
|
||||
}
|
||||
|
||||
bool32 IsBattlerMarkedForControllerExec(u32 battler)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
|
||||
return (gBattleControllerExecFlags & (1u << (battler + 28))) != 0;
|
||||
return IsBattleControllerMessageSynchronizedOverLink(battler);
|
||||
else
|
||||
return (gBattleControllerExecFlags & (1u << battler)) != 0;
|
||||
return IsBattleControllerActiveOnLocal(battler);
|
||||
}
|
||||
|
||||
void MarkBattlerForControllerExec(u32 battler)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
|
||||
gBattleControllerExecFlags |= 1u << (battler + 32 - MAX_BATTLERS_COUNT);
|
||||
MarkBattleControllerMessageOutboundOverLink(battler);
|
||||
else
|
||||
gBattleControllerExecFlags |= 1u << battler;
|
||||
MarkBattleControllerActiveOnLocal(battler);
|
||||
}
|
||||
|
||||
void MarkBattlerReceivedLinkData(u32 battler)
|
||||
@ -1018,9 +1018,9 @@ void MarkBattlerReceivedLinkData(u32 battler)
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < GetLinkPlayerCount(); i++)
|
||||
gBattleControllerExecFlags |= 1u << (battler + (i << 2));
|
||||
MarkBattleControllerActiveForPlayer(battler, i);
|
||||
|
||||
gBattleControllerExecFlags &= ~(1u << (28 + battler));
|
||||
MarkBattleControllerMessageSynchronizedOverLink(battler);
|
||||
}
|
||||
|
||||
const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState)
|
||||
@ -4309,7 +4309,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
}
|
||||
break;
|
||||
case ABILITY_HUNGER_SWITCH:
|
||||
if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END))
|
||||
if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
|
||||
&& GetActiveGimmick(battler) != GIMMICK_TERA
|
||||
&& TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END))
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup);
|
||||
|
||||
@ -363,7 +363,7 @@ static void VBlankCB_ContestPainting(void)
|
||||
static void InitContestMonPixels(u16 species, bool8 backPic)
|
||||
{
|
||||
const void *pal = GetMonSpritePalFromSpeciesAndPersonality(species, gContestPaintingWinner->isShiny, gContestPaintingWinner->personality);
|
||||
DecompressDataWithHeaderVram(pal, gContestPaintingMonPalette);
|
||||
memcpy(gContestPaintingMonPalette, pal, PLTT_SIZE_4BPP);
|
||||
if (!backPic)
|
||||
{
|
||||
HandleLoadSpecialPokePic(TRUE,
|
||||
|
||||
@ -1978,6 +1978,12 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_CHLOROBLAST] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_EXTREME_EVOBOOST] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectExtremeEvoboost,
|
||||
|
||||
@ -19320,7 +19320,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.description = COMPOUND_STRING(
|
||||
"A user-hurting blast of\n"
|
||||
"amassed chlorophyll."),
|
||||
.effect = EFFECT_MAX_HP_50_RECOIL,
|
||||
.effect = EFFECT_CHLOROBLAST,
|
||||
.power = B_UPDATED_MOVE_DATA >= GEN_9 ? 150 : 120,
|
||||
.type = TYPE_GRASS,
|
||||
.accuracy = 95,
|
||||
|
||||
@ -528,6 +528,7 @@ void DoDiveWarp(void)
|
||||
TryFadeOutOldMapMusic();
|
||||
WarpFadeOutScreen();
|
||||
PlayRainStoppingSoundEffect();
|
||||
SetFollowerNPCData(FNPC_DATA_COME_OUT_DOOR, FNPC_DOOR_NONE);
|
||||
gFieldCallback = FieldCB_DefaultWarpExit;
|
||||
CreateTask(Task_WarpAndLoadMap, 10);
|
||||
}
|
||||
|
||||
@ -6431,7 +6431,7 @@ u32 GetSpeciesNameWidthInChars(const u8 *speciesName)
|
||||
|
||||
bool32 IsSpeciesAlcremie(u32 targetSpecies)
|
||||
{
|
||||
return targetSpecies >= SPECIES_ALCREMIE_STRAWBERRY_VANILLA_CREAM && targetSpecies <= SPECIES_ALCREMIE_RIBBON_RAINBOW_SWIRL;
|
||||
return GET_BASE_SPECIES_ID(targetSpecies) == SPECIES_ALCREMIE;
|
||||
}
|
||||
|
||||
bool32 IsItemSweet(u32 item)
|
||||
@ -6628,10 +6628,10 @@ static void PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 dept
|
||||
case IF_PID_UPPER_MODULO_10_EQ:
|
||||
case IF_PID_UPPER_MODULO_10_LT:
|
||||
arg = evolutions[i].params[j].arg1;
|
||||
if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_UPPER_MODULO_10_GT
|
||||
if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_UPPER_MODULO_10_GT
|
||||
&& arg < 10 && arg >= 0)
|
||||
arg = 9 - arg;
|
||||
else if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_UPPER_MODULO_10_EQ
|
||||
else if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_UPPER_MODULO_10_EQ
|
||||
&& arg < 10 && arg >= 0)
|
||||
arg = 1;
|
||||
ConvertIntToDecimalStringN(gStringVar2, arg * 10, STR_CONV_MODE_LEFT_ALIGN, 3);
|
||||
@ -6741,10 +6741,10 @@ static void PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 dept
|
||||
case IF_PID_MODULO_100_EQ:
|
||||
case IF_PID_MODULO_100_LT:
|
||||
arg = evolutions[i].params[j].arg1;
|
||||
if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_MODULO_100_GT
|
||||
if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_MODULO_100_GT
|
||||
&& arg < 100 && arg >= 0)
|
||||
arg = 99 - arg;
|
||||
else if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_MODULO_100_EQ
|
||||
else if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_MODULO_100_EQ
|
||||
&& arg < 100 && arg >= 0)
|
||||
arg = 1;
|
||||
ConvertIntToDecimalStringN(gStringVar2, arg, STR_CONV_MODE_LEFT_ALIGN, 3);
|
||||
@ -6776,7 +6776,7 @@ static void PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 dept
|
||||
}
|
||||
|
||||
if (isAlcremie)
|
||||
fontId = FONT_NARROWER;
|
||||
fontId = FONT_SMALL_NARROWER;
|
||||
else
|
||||
fontId = GetFontIdToFit(gStringVar4, FONT_SMALL, 0, maxScreenWidth);
|
||||
|
||||
|
||||
@ -22,3 +22,52 @@ SINGLE_BATTLE_TEST("Hunger Switch switches Morpeko's forms at the end of the tur
|
||||
EXPECT_EQ(player->species, SPECIES_MORPEKO_FULL_BELLY);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Hunger Switch does not switch a mon transformed into Morpeko's form")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_TRANSFORM) == EFFECT_TRANSFORM);
|
||||
PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_TRANSFORM); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Hunger Switch does not switch Morpeko's form when Terastallized")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); TeraType(TYPE_NORMAL); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { }
|
||||
TURN { MOVE(player, MOVE_SCRATCH, gimmick: GIMMICK_TERA); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Hunger Switch does not switch Morpeko's form after switching out while Terastallized")
|
||||
{
|
||||
KNOWN_FAILING; // #7062
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_ROAR) == EFFECT_ROAR);
|
||||
PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); TeraType(TYPE_NORMAL); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { }
|
||||
TURN { MOVE(player, MOVE_SCRATCH, gimmick: GIMMICK_TERA); MOVE(opponent, MOVE_ROAR); }
|
||||
TURN { SWITCH(player, 0); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
|
||||
} THEN {
|
||||
EXPECT_EQ(player->species, SPECIES_MORPEKO_HANGRY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,40 +80,52 @@ SINGLE_BATTLE_TEST("Normalize still makes Freeze-Dry do super effective damage t
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Normalize boosts power of unaffected moves by 20% (Gen7+)", s16 damage)
|
||||
SINGLE_BATTLE_TEST("Normalize doesn't boost power of unaffected moves by 20% (< Gen7)", s16 damage)
|
||||
{
|
||||
u32 ability, genConfig;
|
||||
PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_7; }
|
||||
PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_6; }
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_7; }
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_6; }
|
||||
u32 ability;
|
||||
PARAMETRIZE { ability = ABILITY_CUTE_CHARM; }
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig);
|
||||
PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_TACKLE); }
|
||||
WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_6);
|
||||
PLAYER(SPECIES_DELCATTY) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TACKLE); }
|
||||
TURN { MOVE(player, MOVE_POUND); }
|
||||
} SCENE {
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
if (genConfig >= GEN_7)
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.2), results[2].damage); // Ate
|
||||
else
|
||||
EXPECT_EQ(results[1].damage, results[3].damage); // No boost
|
||||
EXPECT_EQ(results[0].damage, results[1].damage); // No boost
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Normalize boosts power of affected moves by 20% (Gen7+)", s16 damage)
|
||||
SINGLE_BATTLE_TEST("Normalize boosts power of unaffected moves by 20% (Gen7+)", s16 damage)
|
||||
{
|
||||
u32 ability, genConfig;
|
||||
PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_7; }
|
||||
PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_6; }
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_7; }
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_6; }
|
||||
u32 ability;
|
||||
PARAMETRIZE { ability = ABILITY_CUTE_CHARM; }
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig);
|
||||
WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_7);
|
||||
PLAYER(SPECIES_DELCATTY) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_POUND); }
|
||||
} SCENE {
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, UQ_4_12(1.2), results[1].damage); // Ate
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Normalize doesn't boost power of affected moves by 20% (< Gen7)", s16 damage)
|
||||
{
|
||||
u32 ability;
|
||||
PARAMETRIZE { ability = ABILITY_CUTE_CHARM; }
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_6);
|
||||
PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -121,10 +133,26 @@ SINGLE_BATTLE_TEST("Normalize boosts power of affected moves by 20% (Gen7+)", s1
|
||||
} SCENE {
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
if (genConfig >= GEN_7)
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.8), results[2].damage); // STAB + ate
|
||||
else
|
||||
EXPECT_MUL_EQ(results[1].damage, Q_4_12(1.5), results[3].damage); // STAB + no ate
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); // STAB + no ate
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Normalize boosts power of affected moves by 20% (Gen7+)", s16 damage)
|
||||
{
|
||||
u32 ability;
|
||||
PARAMETRIZE { ability = ABILITY_CUTE_CHARM; }
|
||||
PARAMETRIZE { ability = ABILITY_NORMALIZE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_7);
|
||||
PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_WATER_GUN); }
|
||||
} SCENE {
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.8), results[1].damage); // STAB + ate
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,3 +2,18 @@
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Wandering Spirit (Ability) test titles")
|
||||
|
||||
SINGLE_BATTLE_TEST("Wandering Spirit copied ability should not trigger on fainted mon")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
PLAYER(SPECIES_WOBBUFFET)
|
||||
OPPONENT(SPECIES_YAMASK_GALAR) { HP(1); Ability(ABILITY_WANDERING_SPIRIT); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_POISON_FANG); SEND_OUT(opponent, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_FANG, player);
|
||||
NOT ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,4 +50,41 @@ SINGLE_BATTLE_TEST("Aura Wheel changes type depending on Morpeko's form")
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Aura Wheel can be used by Pokémon transformed into Morpeko");
|
||||
SINGLE_BATTLE_TEST("Aura Wheel can be used by Pokémon transformed into Morpeko")
|
||||
{
|
||||
KNOWN_FAILING; // Aura Wheel for some reason isn't used by the opponent?
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); }
|
||||
OPPONENT(SPECIES_DITTO) { Ability(ABILITY_IMPOSTER); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_AURA_WHEEL); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_AURA_WHEEL, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Aura Wheel can be turned into a Normal-type move after Morpeko gains Normalize")
|
||||
{
|
||||
bool32 hangryMode;
|
||||
PARAMETRIZE { hangryMode = FALSE; }
|
||||
PARAMETRIZE { hangryMode = TRUE; }
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_ENTRAINMENT) == EFFECT_ENTRAINMENT);
|
||||
ASSUME(gSpeciesInfo[SPECIES_DUSKULL].types[0] == TYPE_GHOST || gSpeciesInfo[SPECIES_DUSKULL].types[1] == TYPE_GHOST);
|
||||
PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); }
|
||||
OPPONENT(SPECIES_DELCATTY) { Ability(ABILITY_NORMALIZE); }
|
||||
OPPONENT(SPECIES_DUSKULL);
|
||||
} WHEN {
|
||||
if (hangryMode)
|
||||
TURN { }
|
||||
TURN { MOVE(opponent, MOVE_ENTRAINMENT); }
|
||||
TURN { MOVE(player, MOVE_AURA_WHEEL); SWITCH(opponent, 1); }
|
||||
} SCENE {
|
||||
if (hangryMode)
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_AURA_WHEEL, player);
|
||||
HP_BAR(opponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
153
test/battle/move_effect/chloroblast.c
Normal file
153
test/battle/move_effect/chloroblast.c
Normal file
@ -0,0 +1,153 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_CHLOROBLAST) == EFFECT_CHLOROBLAST);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Chloroblast makes the user lose 1/2 of its Max HP")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CHLOROBLAST); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player);
|
||||
HP_BAR(player, damage: 200);
|
||||
NOT MESSAGE("Wobbuffet fainted!"); // Wobb had more than 1/2 of its HP, so it can't faint.
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Chloroblast causes the user to faint when below 1/2 of its Max HP")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(200); MaxHP(400); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CHLOROBLAST); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player);
|
||||
HP_BAR(player, hp: 0);
|
||||
MESSAGE("Wobbuffet fainted!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Chloroblast causes the user & the target to faint when below 1/2 of its Max HP")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(200) ; MaxHP(400); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CHLOROBLAST); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player);
|
||||
HP_BAR(opponent, hp: 0);
|
||||
MESSAGE("The opposing Wobbuffet fainted!");
|
||||
HP_BAR(player, hp: 0);
|
||||
MESSAGE("Wobbuffet fainted!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Chloroblast hp loss is prevented by Magic Guard")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_CLEFAIRY) { Ability(ABILITY_MAGIC_GUARD); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CHLOROBLAST); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player);
|
||||
HP_BAR(opponent);
|
||||
NOT HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Chloroblast does not cause recoil damage if the user has Rock Head")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_AERODACTYL) { Ability(ABILITY_ROCK_HEAD); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CHLOROBLAST); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player);
|
||||
HP_BAR(opponent);
|
||||
NOT HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Chloroblast does not cause the user to lose HP even if the opposing mon protected")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_CHLOROBLAST); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player);
|
||||
HP_BAR(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Chloroblast does not cause the user to lose HP even if it is absorbed by Sap Sipper")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_CHLOROBLAST) == TYPE_GRASS);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GOGOAT) { Ability(ABILITY_SAP_SIPPER); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CHLOROBLAST); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponent, ABILITY_SAP_SIPPER);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player);
|
||||
HP_BAR(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Chloroblast does not cause the user to lose HP if there is no target")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_MEMENTO); MOVE(player, MOVE_CHLOROBLAST); SEND_OUT(opponent, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_MEMENTO, opponent);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player);
|
||||
HP_BAR(player);
|
||||
}
|
||||
MESSAGE("Wobbuffet used Chloroblast!");
|
||||
MESSAGE("But it failed!");
|
||||
MESSAGE("2 sent out Wobbuffet!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Chloroblast is not affected by Reckless", s16 damage)
|
||||
{
|
||||
u32 move;
|
||||
|
||||
PARAMETRIZE { move = MOVE_CHLOROBLAST; }
|
||||
PARAMETRIZE { move = MOVE_FRENZY_PLANT; }
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, move); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(results[0].damage, results[1].damage);
|
||||
}
|
||||
}
|
||||
@ -673,4 +673,24 @@ SINGLE_BATTLE_TEST("Pursuit user faints to Life Orb and target still switches ou
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Pursuit user switches out due to Red Card and partner's switch is cancelled if switching to same Pokémon")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetItemHoldEffect(ITEM_RED_CARD) == HOLD_EFFECT_RED_CARD);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_ARCEUS);
|
||||
OPPONENT(SPECIES_WYNAUT) { Item(ITEM_RED_CARD); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_ARCEUS);
|
||||
} WHEN {
|
||||
TURN { SWITCH(opponentLeft, 2); SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_PURSUIT, target: opponentLeft); }
|
||||
} THEN {
|
||||
// playerLeft switches to Arceus
|
||||
EXPECT_EQ(playerLeft->species, SPECIES_ARCEUS);
|
||||
// playerRight has their switch cancelled
|
||||
EXPECT_EQ(playerRight->species, SPECIES_WYNAUT);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Baton Pass doesn't cause Pursuit to increase its power or priority");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user