Merge branch 'master' into master-merge

Conflicts:
	src/contest_painting.c
This commit is contained in:
Hedara 2025-06-09 23:27:18 +02:00
commit bdd7c5bfa8
38 changed files with 562 additions and 133 deletions

View File

@ -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"
}

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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::

View File

@ -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.

View File

@ -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");
```

View File

@ -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.

View File

@ -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,

View File

@ -5559,6 +5559,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:

View File

@ -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:

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View 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);
}
}

View File

@ -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");