Merge branch 'followers' into lighting

This commit is contained in:
Ariel A 2024-02-17 17:49:14 -05:00
commit 7cf2d1eca0
92 changed files with 2483 additions and 1784 deletions

4
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1,4 @@
725252905baf28dbb9298dd5fa0daaf0e804a455
afbb88d77ada8a636a318ec32b61b4ea849d85ab
f861504cfc50941768286c0703d24ab0aaceb88e
ebbcb7d025cff716eec5008b5dd2b7d55aa8c3f3

View File

@ -7,13 +7,21 @@ This fork tries to maintain vanilla compatibility whenever possible. It doesn't
There are several branches, each with one main feature (and sometimes some extra stuff): There are several branches, each with one main feature (and sometimes some extra stuff):
**followers** branch: **followers** branch:
* [HGSS-style pokémon followers](https://bulbapedia.bulbagarden.net/wiki/Walking_Pok%C3%A9mon#Pok.C3.A9mon_HeartGold_and_SoulSilver) for all 386 pokémon, including emotes, the 28 Unown forms and a majority of follower messages. * [HGSS-style pokémon followers](https://bulbapedia.bulbagarden.net/wiki/Walking_Pok%C3%A9mon#Pok.C3.A9mon_HeartGold_and_SoulSilver) for all 386 pokémon (including forms & shinies)
* Dynamic overworld palettes & reflections compatible with vanilla berry trees. * Includes follower emotes and a majority of the HGSS messages
* PID (but not legitimacy) preserving Pokémon nature-changing function * Custom pokeball sprites for Gen 1-7 pokéballs
* Function to detect modern emulators/GBA hardware. * Followers can use field moves in the overworld
* Overworld form changes for Ditto, Mew, Castform, etc.
* Asymmetrical & 64x64 OW support
* Dynamic Overworld Palette System (DOWP) & reflections compatible with berry trees, etc.
> Note: Unless you have a specific need for it, you should probably use `followers-expanded-id` over this. > Note: Unless you have a specific need for it, you should probably use `followers-expanded-id` over this.
![Pokeball](https://i.imgur.com/OMbS67Q.gif)
![Messages](https://i.imgur.com/sTbGVEY.gif)
![Forms](https://i.imgur.com/wDhFNf4.gif)
![HM](https://i.imgur.com/lnXJGHd.gif)
**icons** branch: **icons** branch:
* Everything from the **followers** branch. * Everything from the **followers** branch.
* All pokemon icons updated to Gen 6, based on [this repo](https://github.com/msikma/pokesprite/tree/master/icons/pokemon/regular) * All pokemon icons updated to Gen 6, based on [this repo](https://github.com/msikma/pokesprite/tree/master/icons/pokemon/regular)
@ -32,7 +40,7 @@ There are several branches, each with one main feature (and sometimes some extra
**just-lighting** branch: **just-lighting** branch:
* `lighting-expanded-id` but with following pokémon code & assets completely removed. (This allows for more than 255 OW graphics) * `lighting-expanded-id` but with following pokémon code & assets completely removed. (This allows for more than 255 OW graphics)
* Saves with following pokémon can safely be loaded. * Saves with following pokémon can still safely be loaded.
**followers-expanded-id** branch: **followers-expanded-id** branch:
* Like `followers`, but includes expands OW graphicsIds to 16-bits * Like `followers`, but includes expands OW graphicsIds to 16-bits
@ -45,6 +53,12 @@ Additional branches to mention:
To set up the repository, see [INSTALL.md](INSTALL.md). To set up the repository, see [INSTALL.md](INSTALL.md).
**guillotine** branch:
* ~~Decapitates~~ Decapitalizes **all** text at runtime, with some exceptions (see the [FAQ](#guillotine-q-how-can-i-keep-my-strings-from-being-decapped))
* Future-proof, does not require mass-replacing strings
To set up the repository, see [INSTALL.md](INSTALL.md).
## FAQ ## FAQ
### `(followers*)` Q: Where are the config settings? ### `(followers*)` Q: Where are the config settings?
A: Configuration for the follower system is mostly in [event_objects.h](include/constants/event_objects.h): A: Configuration for the follower system is mostly in [event_objects.h](include/constants/event_objects.h):
@ -57,6 +71,10 @@ A: Configuration for the follower system is mostly in [event_objects.h](include/
// to OW code so that large (48x48, 64x64) OWs // to OW code so that large (48x48, 64x64) OWs
// will display correctly under bridges, etc. // will display correctly under bridges, etc.
#define LARGE_OW_SUPPORT TRUE #define LARGE_OW_SUPPORT TRUE
// Followers will emerge from the pokeball they are stored in,
// instead of a normal pokeball
#define OW_MON_POKEBALLS TRUE
``` ```
### `(lighting)` Q: How do I mark certain colors in a palette as light-blended? ### `(lighting)` Q: How do I mark certain colors in a palette as light-blended?
@ -76,6 +94,35 @@ on separate lines to mark those colors as being light-blended, i.e:
You might have to `make mostlyclean` or change the `.pal` file to pick up the changes. You might have to `make mostlyclean` or change the `.pal` file to pick up the changes.
### `(guillotine)` Q: How can I keep my string(s) from being decapped?
A: There are a number of ways to make a string "fixed case" so that it will not be decapitalized when displayed:
C strings: Replace the `_` with `_C`:
```c
// _C = fixed (C)ase string!
const u8 gText_IDNumber[] = _C("IDNo.");
```
ASM strings: Replace `.string` with `.fixstr`:
```arm
gText_SavingDontTurnOff::
@ Lasts until the string terminator '$'
.fixstr "SAVING…\n"
.string "DON'T TURN OFF THE POWER.$"
```
You can fix-case/unfix parts of a string like so:
```arm
.string "{FIXED_CASE}WARNING!{UNFIX_CASE}\p"
```
For a placeholder (only the placeholder will be fixed-case):
```arm
.string "{STR_VAR_2_FIXED} was transferred to\n"
.string "BOX “{STR_VAR_1}.”$"
```
See also the configuration in [text.h](gflib/text.h).
There's also special handling for "separated bigrams"; basically, two letter words.
This includes: `"TM01", "PC", "EV"`, any two uppercase characters surrounded by digits, whitespace, or the start/end of a string. These will not be decapped.
## See also ## See also
For contacts and other pret projects, see [pret.github.io](https://pret.github.io/). For contacts and other pret projects, see [pret.github.io](https://pret.github.io/).

View File

@ -84,3 +84,4 @@ AncientTomb_EventScript_RanFromRegisteel::
setvar VAR_0x8004, SPECIES_REGISTEEL setvar VAR_0x8004, SPECIES_REGISTEEL
goto Common_EventScript_LegendaryFlewAway goto Common_EventScript_LegendaryFlewAway
end end

View File

@ -650,3 +650,4 @@ BattleFrontier_BattlePalaceLobby_Text_ExplainRulesWhenInDanger:
.string "nature when it is in trouble.\p" .string "nature when it is in trouble.\p"
.string "If a POKéMON begins behaving oddly\n" .string "If a POKéMON begins behaving oddly\n"
.string "in a pinch, watch it carefully.$" .string "in a pinch, watch it carefully.$"

View File

@ -434,3 +434,4 @@ BattleFrontier_BattlePikeLobby_Text_ExplainMonOrderRules:
.string "changed.\p" .string "changed.\p"
.string "The sequence must be set before\n" .string "The sequence must be set before\n"
.string "starting your challenge.$" .string "starting your challenge.$"

View File

@ -904,3 +904,4 @@ BattleFrontier_BattlePyramidLobby_Text_ExplainBagRules:
.string "of ten kinds of items.\p" .string "of ten kinds of items.\p"
.string "The contents of the BATTLE BAG are\n" .string "The contents of the BATTLE BAG are\n"
.string "lost if you fail in your quest.$" .string "lost if you fail in your quest.$"

View File

@ -84,3 +84,4 @@ DesertRuins_EventScript_RanFromRegirock::
setvar VAR_0x8004, SPECIES_REGIROCK setvar VAR_0x8004, SPECIES_REGIROCK
goto Common_EventScript_LegendaryFlewAway goto Common_EventScript_LegendaryFlewAway
end end

View File

@ -530,3 +530,4 @@ RusturfTunnel_Text_MikePostBattle:
.string "They halted development here to\n" .string "They halted development here to\n"
.string "protect POKéMON, right?\l" .string "protect POKéMON, right?\l"
.string "There's a feel-good story!$" .string "There's a feel-good story!$"

View File

@ -438,3 +438,4 @@ SlateportCity_OceanicMuseum_2F_Text_SSAnneReplica:
.string "“S.S. ANNE\p" .string "“S.S. ANNE\p"
.string "“A replica of the luxury liner that\n" .string "“A replica of the luxury liner that\n"
.string "circles the globe.”$" .string "circles the globe.”$"

View File

@ -30,17 +30,6 @@ EventScript_Follower::
bufferlivemonnickname 0 bufferlivemonnickname 0
playfirstmoncry playfirstmoncry
callfunc ScrFunc_getfolloweraction callfunc ScrFunc_getfolloweraction
checkpartymove MOVE_FLY
compare VAR_RESULT 6
goto_if_eq EventScript_FollowerEnd
bufferlivemonnickname 0
msgbox gText_WantsToFly, MSGBOX_YESNO
switch VAR_RESULT
case NO, EventScript_FollowerEnd
case YES, EventScript_FollowerFly
case MULTI_B_PRESSED, EventScript_FollowerEnd
EventScript_FollowerFly::
callfunc ScrFunc_followerfly
EventScript_FollowerEnd:: EventScript_FollowerEnd::
waitfieldeffect FLDEFF_EMOTE waitfieldeffect FLDEFF_EMOTE
release release

View File

@ -56,7 +56,6 @@ static void AddSpritesToOamBuffer(void);
static u8 CreateSpriteAt(u8 index, const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority); static u8 CreateSpriteAt(u8 index, const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority);
static void ResetOamMatrices(void); static void ResetOamMatrices(void);
static void ResetSprite(struct Sprite *sprite); static void ResetSprite(struct Sprite *sprite);
static s16 AllocSpriteTiles(u16 tileCount);
static void RequestSpriteFrameImageCopy(u16 index, u16 tileNum, const struct SpriteFrameImage *images); static void RequestSpriteFrameImageCopy(u16 index, u16 tileNum, const struct SpriteFrameImage *images);
static void ResetAllSprites(void); static void ResetAllSprites(void);
static void BeginAnim(struct Sprite *sprite); static void BeginAnim(struct Sprite *sprite);

View File

@ -298,6 +298,7 @@ void SetOamMatrixRotationScaling(u8 matrixNum, s16 xScale, s16 yScale, u16 rotat
u16 LoadSpriteSheet(const struct SpriteSheet *sheet); u16 LoadSpriteSheet(const struct SpriteSheet *sheet);
u16 LoadSpriteSheetByTemplate(const struct SpriteTemplate *template, u8 frame); u16 LoadSpriteSheetByTemplate(const struct SpriteTemplate *template, u8 frame);
void LoadSpriteSheets(const struct SpriteSheet *sheets); void LoadSpriteSheets(const struct SpriteSheet *sheets);
s16 AllocSpriteTiles(u16 tileCount);
u16 AllocTilesForSpriteSheet(struct SpriteSheet *sheet); u16 AllocTilesForSpriteSheet(struct SpriteSheet *sheet);
void AllocTilesForSpriteSheets(struct SpriteSheet *sheets); void AllocTilesForSpriteSheets(struct SpriteSheet *sheets);
void LoadTilesForSpriteSheet(const struct SpriteSheet *sheet); void LoadTilesForSpriteSheet(const struct SpriteSheet *sheet);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -276,6 +276,11 @@
#define ANIM_RUN_WEST (ANIM_STD_COUNT + 2) #define ANIM_RUN_WEST (ANIM_STD_COUNT + 2)
#define ANIM_RUN_EAST (ANIM_STD_COUNT + 3) #define ANIM_RUN_EAST (ANIM_STD_COUNT + 3)
#define ANIM_EXIT_POKEBALL_FAST_SOUTH (ANIM_STD_COUNT + 0)
#define ANIM_EXIT_POKEBALL_FAST_NORTH (ANIM_STD_COUNT + 1)
#define ANIM_EXIT_POKEBALL_FAST_WEST (ANIM_STD_COUNT + 2)
#define ANIM_EXIT_POKEBALL_FAST_EAST (ANIM_STD_COUNT + 3)
#define ANIM_BUNNY_HOP_BACK_WHEEL_SOUTH (ANIM_STD_COUNT + 0) #define ANIM_BUNNY_HOP_BACK_WHEEL_SOUTH (ANIM_STD_COUNT + 0)
#define ANIM_BUNNY_HOP_BACK_WHEEL_NORTH (ANIM_STD_COUNT + 1) #define ANIM_BUNNY_HOP_BACK_WHEEL_NORTH (ANIM_STD_COUNT + 1)
#define ANIM_BUNNY_HOP_BACK_WHEEL_WEST (ANIM_STD_COUNT + 2) #define ANIM_BUNNY_HOP_BACK_WHEEL_WEST (ANIM_STD_COUNT + 2)

View File

@ -286,6 +286,10 @@
// will display correctly under bridges, etc. // will display correctly under bridges, etc.
#define LARGE_OW_SUPPORT TRUE #define LARGE_OW_SUPPORT TRUE
// Followers will emerge from the pokeball they are stored in,
// instead of a normal pokeball
#define OW_MON_POKEBALLS TRUE
#define SHADOW_SIZE_S 0 #define SHADOW_SIZE_S 0
#define SHADOW_SIZE_M 1 #define SHADOW_SIZE_M 1
#define SHADOW_SIZE_L 2 #define SHADOW_SIZE_L 2

View File

@ -110,7 +110,6 @@
#define FLDEFFOBJ_BUBBLES 34 #define FLDEFFOBJ_BUBBLES 34
#define FLDEFFOBJ_SMALL_SPARKLE 35 #define FLDEFFOBJ_SMALL_SPARKLE 35
#define FLDEFFOBJ_RAYQUAZA 36 #define FLDEFFOBJ_RAYQUAZA 36
#define FLDEFFOBJ_TRACKS_SLITHER 37 #define FLDEFFOBJ_TRACKS_SLITHER 37
#define FLDEFFOBJ_TRACKS_SPOT 38 #define FLDEFFOBJ_TRACKS_SPOT 38
#define FLDEFFOBJ_TRACKS_BUG 39 #define FLDEFFOBJ_TRACKS_BUG 39

View File

@ -8,6 +8,8 @@ extern u8 ALIGNED(4) gDecompressionBuffer[0x4000];
void LZDecompressWram(const u32 *src, void *dest); void LZDecompressWram(const u32 *src, void *dest);
void LZDecompressVram(const u32 *src, void *dest); void LZDecompressVram(const u32 *src, void *dest);
bool32 IsLZ77Data(const void *ptr, u32 minSize, u32 maxSize);
u16 LoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src); u16 LoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src);
void LoadCompressedSpriteSheetOverrideBuffer(const struct CompressedSpriteSheet *src, void *buffer); void LoadCompressedSpriteSheetOverrideBuffer(const struct CompressedSpriteSheet *src, void *buffer);
bool8 LoadCompressedSpriteSheetUsingHeap(const struct CompressedSpriteSheet *src); bool8 LoadCompressedSpriteSheetUsingHeap(const struct CompressedSpriteSheet *src);

View File

@ -292,6 +292,7 @@ void MovementType_FollowPlayer(struct Sprite *);
u8 GetSlideMovementAction(u32); u8 GetSlideMovementAction(u32);
u8 GetJumpMovementAction(u32); u8 GetJumpMovementAction(u32);
u8 GetJump2MovementAction(u32); u8 GetJump2MovementAction(u32);
u8 CopySprite(struct Sprite *sprite, s16 x, s16 y, u8 subpriority);
u8 CreateCopySpriteAt(struct Sprite *sprite, s16 x, s16 y, u8 subpriority); u8 CreateCopySpriteAt(struct Sprite *sprite, s16 x, s16 y, u8 subpriority);
u8 MovementType_WanderAround_Step0(struct ObjectEvent *, struct Sprite *); u8 MovementType_WanderAround_Step0(struct ObjectEvent *, struct Sprite *);

View File

@ -16,81 +16,67 @@ enum {
FOLLOWER_EMOTION_LENGTH, FOLLOWER_EMOTION_LENGTH,
}; };
// This struct is optimized for size // Can be either 3 bytes, a u16 and a byte, or a 24-bit value
// Each "section" can be used to combine multiple conditions, union __attribute__((packed)) MsgConditionData {
// i.e, species and map u8 bytes[3];
// Just set the flags accordingly and use the right union member struct __attribute__((packed)) {
struct __attribute__((packed)) FollowerMsgInfoExtended { u16 hw;
u8 b;
} split;
u32 raw:24;
}; // size = 0x3
struct __attribute__((packed)) MsgCondition {
u32 type:8;
union MsgConditionData data;
}; // size = 0x4
struct FollowerMsgInfoExtended {
const u8 *text; const u8 *text;
const u8 *script; const u8 *script;
union __attribute__((packed)) { u32 emotion:4;
u16 species:10; u32 weight:3;
struct __attribute__((packed)) {
u16 type1:5;
u16 type2:5; // if >= NUMBER_OF_MON_TYPES, inverts checking for type1
} types;
u16 status:10;
} st;
u16 stFlags:2; // 0 = no matching, 1 = species matching, 2 = type matching, 3 = status
u16 emotion:4; // emotion for this message
union __attribute__((packed)) {
struct __attribute__((packed)) {
u16 mapSec:8;
} mapSec;
struct __attribute__((packed)) {
u16 mapNum:8;
u16 mapGroup:6;
} map;
struct __attribute__((packed)) {
u16 behavior1:8;
u16 behavior2:6; // not full; only goes up to 0x3F
} mb;
} mm;
u16 mmFlags:2; // 1 = map sec, 2 = map, 3 = metatile behavior
union __attribute__((packed)) {
struct __attribute__((packed)) {
u16 weather1:5;
u16 weather2:5;
} weather;
u16 song:10;
u16 timeOfDay:10;
} wt;
u16 wtFlags:2; // 1 = weather matching, 2 = song, 3 = time
u16 weight:3;
// if set, `text` is treated as an array of up to 4 texts instead // if set, `text` is treated as an array of up to 4 texts instead
u16 textSpread:1; // which one is displayed is chosen at random
u32 textSpread:1;
u32 orFlag:1; // if set, *any* condition can match, rather than all
union __attribute__((packed)) { struct MsgCondition conditions[5];
struct __attribute__((packed)) { }; // size = 8 + 4 + 5*4 = 32, 0x20
u16 behavior:8;
u16 distance:6;
} mb;
} near;
u16 nearFlags:2; // 1 = mb within '+'-shaped distance away
};
enum { // Follower message conditions
ST_FLAGS_SPECIES = 1, #define MSG_COND_NONE 0
ST_FLAGS_TYPE, #define MSG_COND_SPECIES 1
ST_FLAGS_STATUS, #define MSG_COND_TYPE 2
}; #define MSG_COND_STATUS 3
#define MSG_COND_MAPSEC 4
#define MSG_COND_MAP 5
#define MSG_COND_ON_MB 6
#define MSG_COND_WEATHER 7
#define MSG_COND_MUSIC 8
#define MSG_COND_TIME_OF_DAY 9
#define MSG_COND_NEAR_MB 10
enum { #define MATCH_U24(type, value) {type, {.raw = value}}
MM_FLAGS_MAPSEC = 1, #define MATCH_U16(type, value1, value2) {type, {.split = {.hw = value1, .b = value2}}}
MM_FLAGS_MAP, #define MATCH_U8(type, v1, v2, v3) {type, {.bytes = {v1, v2, v3}}}
MM_FLAGS_MB, // (m)etatile (b)ehavior
};
enum { #define MATCH_SPECIES(species) MATCH_U24(MSG_COND_SPECIES, species)
WT_FLAGS_WEATHER = 1, #define MATCH_TYPES(type1, type2) MATCH_U8(MSG_COND_TYPE, type1, type2, 0)
WT_FLAGS_MUSIC, // Checks that follower has *neither* of the two types
WT_FLAGS_TIME, #define MATCH_NOT_TYPES(type1, type2) MATCH_U8(MSG_COND_TYPE, type1, type2, TYPE_NONE)
}; #define MATCH_STATUS(status) MATCH_U24(MSG_COND_STATUS, status)
#define MATCH_MAPSEC(mapsec) MATCH_U24(MSG_COND_MAPSEC, mapsec)
#define NEAR_FLAGS_MB 1 #define MATCH_MAP_RAW(mapGroup, mapNum) MATCH_U8(MSG_COND_MAP, mapGroup, mapNum, 0)
#define MATCH_MAP(map) MATCH_U8(MSG_COND_MAP, MAP_GROUP(map), MAP_NUM(map), 0)
// Matches one of two metatile behaviors follower is standing on
#define MATCH_ON_MB(mb1, mb2) MATCH_U8(MSG_COND_ON_MB, mb1, mb2, 0)
#define MATCH_WEATHER(weather1, weather2) MATCH_U8(MSG_COND_WEATHER, weather1, weather2, 0)
#define MATCH_MUSIC(song) MATCH_U24(MSG_COND_MUSIC, song)
#define MATCH_TIME_OF_DAY(time) MATCH_U24(MSG_COND_TIME_OF_DAY, time)
// Matches metatile behavior within a '+' shape of size `distance`
#define MATCH_NEAR_MB(mb, distance) MATCH_U8(MSG_COND_NEAR_MB, mb, distance, 0)
enum { enum {
COND_MSG_CELEBI, COND_MSG_CELEBI,
@ -127,5 +113,6 @@ enum {
}; };
extern const struct FollowerMsgInfoExtended gFollowerConditionalMessages[COND_MSG_COUNT]; extern const struct FollowerMsgInfoExtended gFollowerConditionalMessages[COND_MSG_COUNT];
extern const struct FollowerMessagePool gFollowerBasicMessages[FOLLOWER_EMOTION_LENGTH];
#endif //GUARD_FOLLOWER_HELPER_H #endif //GUARD_FOLLOWER_HELPER_H

View File

@ -275,6 +275,11 @@ enum {
#define PLAYER_AVATAR_FLAG_FORCED_MOVE (1 << 6) #define PLAYER_AVATAR_FLAG_FORCED_MOVE (1 << 6)
#define PLAYER_AVATAR_FLAG_DASH (1 << 7) #define PLAYER_AVATAR_FLAG_DASH (1 << 7)
#define PLAYER_AVATAR_FLAG_BIKE (PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE)
// Player avatar flags for which follower pokemon are hidden
#define FOLLOWER_INVISIBLE_FLAGS (PLAYER_AVATAR_FLAG_SURFING | PLAYER_AVATAR_FLAG_UNDERWATER | \
PLAYER_AVATAR_FLAG_BIKE | PLAYER_AVATAR_FLAG_FORCED_MOVE)
enum enum
{ {
ACRO_BIKE_NORMAL, ACRO_BIKE_NORMAL,

View File

@ -538,7 +538,6 @@ struct SaveBlock2
extern struct SaveBlock2 *gSaveBlock2Ptr; extern struct SaveBlock2 *gSaveBlock2Ptr;
extern u8 UpdateSpritePaletteWithTime(u8); extern u8 UpdateSpritePaletteWithTime(u8);
extern bool8 IsAccurateGBA(void);
struct SecretBaseParty struct SecretBaseParty
{ {

View File

@ -11,7 +11,23 @@ remote_path=$(git remote get-url build | sed -nr -e "s/ssh:\/\/\w+@?\w*://p") #
make_cmd=$(git config --local remake.make) make_cmd=$(git config --local remake.make)
make_product=$(git config --local remake.src) make_product=$(git config --local remake.src)
make_dest=$(git config --local remake.dest) make_dest=$(git config --local remake.dest)
set -x old_head=$(git rev-parse --short @)
set +e
# Make a temp commit for unstaged changes
temp_commit_msg="temp build"
git commit -aem "$temp_commit_msg"
retVal=$?
set -e
# set -x
git push build --force-with-lease git push build --force-with-lease
ssh $remote_host "cd $remote_path && git reset --hard && git checkout $git_branch && $make_cmd" # { set +x; } 2>/dev/null
scp "$remote_host:$remote_path/$make_product" $make_dest # Reset temp commit
if [[ $retVal -eq 0 ]]; then
commit_msg=$(git log -1 --pretty=%B)
if [[ "$commit_msg" == "$temp_commit_msg" ]]; then
git reset "$old_head" &>/dev/null
fi
fi
set -x
ssh -o "VisualHostKey=no" $remote_host "cd $remote_path && git reset --hard && git checkout $git_branch && $make_cmd"
scp -o "VisualHostKey=no" "$remote_host:$remote_path/$make_product" $make_dest

View File

@ -687,6 +687,9 @@ $(FLDEFFGFXDIR)/secret_power_tree.4bpp: %.4bpp: %.png
$(FLDEFFGFXDIR)/record_mix_lights.4bpp: %.4bpp: %.png $(FLDEFFGFXDIR)/record_mix_lights.4bpp: %.4bpp: %.png
$(GFX) $< $@ -mwidth 4 -mheight 1 $(GFX) $< $@ -mwidth 4 -mheight 1
$(OBJEVENTGFXDIR)/pokemon/substitute.4bpp: %.4bpp: %.png
$(GFX) $< $@ -mwidth 4 -mheight 4
$(OBJEVENTGFXDIR)/pokemon/bulbasaur.4bpp: %.4bpp: %.png $(OBJEVENTGFXDIR)/pokemon/bulbasaur.4bpp: %.4bpp: %.png
$(GFX) $< $@ -mwidth 4 -mheight 4 $(GFX) $< $@ -mwidth 4 -mheight 4
@ -1938,5 +1941,8 @@ $(OBJEVENTGFXDIR)/pokemon/deoxys.4bpp: %.4bpp: %.png
$(MISCGFXDIR)/emotes.4bpp: %.4bpp: %.png $(MISCGFXDIR)/emotes.4bpp: %.4bpp: %.png
$(GFX) $< $@ -mwidth 2 -mheight 2 $(GFX) $< $@ -mwidth 2 -mheight 2
# All pokeballs are 16x32
$(OBJEVENTGFXDIR)/misc/ball_%.4bpp: $(OBJEVENTGFXDIR)/misc/ball_%.png ; $(GFX) $< $@ -mwidth 2 -mheight 4
graphics/door_anims/battle_tower_multi_corridor.4bpp: %.4bpp: %.png graphics/door_anims/battle_tower_multi_corridor.4bpp: %.4bpp: %.png
$(GFX) $< $@ -mwidth 2 -mheight 4 $(GFX) $< $@ -mwidth 2 -mheight 4

View File

@ -1053,7 +1053,7 @@ void Bike_HandleBumpySlopeJump(void)
bool32 IsRunningDisallowed(u8 metatile) bool32 IsRunningDisallowed(u8 metatile)
{ {
if (IsRunningDisallowedByMetatile(metatile) == TRUE) if (!gMapHeader.allowRunning || IsRunningDisallowedByMetatile(metatile) == TRUE)
return TRUE; return TRUE;
else else
return FALSE; return FALSE;

View File

@ -217,6 +217,12 @@ static const union AnimCmd sAnim_FaceEast2F[] =
ANIMCMD_JUMP(0), ANIMCMD_JUMP(0),
}; };
static const union AnimCmd sAnim_FaceEast2F_Asym[] =
{
ANIMCMD_FRAME(6, 16),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_GoSouth[] = static const union AnimCmd sAnim_GoSouth[] =
{ {
ANIMCMD_FRAME(3, 8), ANIMCMD_FRAME(3, 8),
@ -289,6 +295,15 @@ static const union AnimCmd sAnim_GoEast2F[] =
ANIMCMD_JUMP(0), ANIMCMD_JUMP(0),
}; };
static const union AnimCmd sAnim_GoEast2F_Asym[] =
{
ANIMCMD_FRAME(6, 6),
ANIMCMD_FRAME(7, 6),
ANIMCMD_FRAME(7, 6),
ANIMCMD_FRAME(6, 6),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_GoFastSouth[] = static const union AnimCmd sAnim_GoFastSouth[] =
{ {
ANIMCMD_FRAME(3, 4), ANIMCMD_FRAME(3, 4),
@ -361,6 +376,15 @@ static const union AnimCmd sAnim_GoFastEast2F[] =
ANIMCMD_JUMP(0), ANIMCMD_JUMP(0),
}; };
static const union AnimCmd sAnim_GoFastEast2F_Asym[] =
{
ANIMCMD_FRAME(6, 4),
ANIMCMD_FRAME(7, 4),
ANIMCMD_FRAME(7, 4),
ANIMCMD_FRAME(6, 4),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_GoFasterSouth[] = static const union AnimCmd sAnim_GoFasterSouth[] =
{ {
ANIMCMD_FRAME(3, 2), ANIMCMD_FRAME(3, 2),
@ -422,6 +446,19 @@ static const union AnimCmd sAnim_ExitPokeballEast[] =
ANIMCMD_JUMP(0), ANIMCMD_JUMP(0),
}; };
static const union AnimCmd sAnim_ExitPokeballEast_Asym[] =
{
ANIMCMD_FRAME(0, 1),
ANIMCMD_FRAME(0, 3),
ANIMCMD_FRAME(0, 1),
ANIMCMD_FRAME(1, 1),
ANIMCMD_FRAME(2, 1),
ANIMCMD_FRAME(3, 1),
ANIMCMD_FRAME(4, 1),
ANIMCMD_FRAME(6, 8),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_EnterSouth[] = static const union AnimCmd sAnim_EnterSouth[] =
{ {
ANIMCMD_FRAME(0, 8), ANIMCMD_FRAME(0, 8),
@ -497,6 +534,18 @@ static const union AnimCmd sAnim_EnterEast[] =
ANIMCMD_JUMP(0), ANIMCMD_JUMP(0),
}; };
static const union AnimCmd sAnim_EnterEast_Asym[] =
{
ANIMCMD_FRAME(6, 8),
ANIMCMD_FRAME(4, 1),
ANIMCMD_FRAME(3, 1),
ANIMCMD_FRAME(2, 1),
ANIMCMD_FRAME(1, 1),
ANIMCMD_FRAME(0, 1),
ANIMCMD_FRAME(0, 3),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_GoFastestSouth[] = static const union AnimCmd sAnim_GoFastestSouth[] =
{ {
ANIMCMD_FRAME(3, 1), ANIMCMD_FRAME(3, 1),
@ -554,6 +603,18 @@ static const union AnimCmd sAnim_ExitPokeballFastEast[] =
ANIMCMD_JUMP(0), ANIMCMD_JUMP(0),
}; };
static const union AnimCmd sAnim_ExitPokeballFastEast_Asym[] =
{
ANIMCMD_FRAME(0, 1),
ANIMCMD_FRAME(1, 1),
ANIMCMD_FRAME(2, 1),
ANIMCMD_FRAME(3, 1),
ANIMCMD_FRAME(4, 1),
ANIMCMD_FRAME(6, 2),
ANIMCMD_FRAME(6, 1),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_GoFastestNorth[] = static const union AnimCmd sAnim_GoFastestNorth[] =
{ {
ANIMCMD_FRAME(5, 1), ANIMCMD_FRAME(5, 1),
@ -1084,31 +1145,59 @@ static const union AnimCmd *const sAnimTable_Standard[] = {
}; };
static const union AnimCmd *const sAnimTable_Following[] = { static const union AnimCmd *const sAnimTable_Following[] = {
sAnim_FaceSouth, [ANIM_STD_FACE_SOUTH] = sAnim_FaceSouth,
sAnim_FaceNorth2F, [ANIM_STD_FACE_NORTH] = sAnim_FaceNorth2F,
sAnim_FaceWest2F, [ANIM_STD_FACE_WEST] = sAnim_FaceWest2F,
sAnim_FaceEast2F, [ANIM_STD_FACE_EAST] = sAnim_FaceEast2F,
sAnim_GoSouth2F, [ANIM_STD_GO_SOUTH] = sAnim_GoSouth2F,
sAnim_GoNorth2F, [ANIM_STD_GO_NORTH] = sAnim_GoNorth2F,
sAnim_GoWest2F, [ANIM_STD_GO_WEST] = sAnim_GoWest2F,
sAnim_GoEast2F, [ANIM_STD_GO_EAST] = sAnim_GoEast2F,
sAnim_GoFastSouth2F, [ANIM_STD_GO_FAST_SOUTH] = sAnim_GoFastSouth2F,
sAnim_GoFastNorth2F, [ANIM_STD_GO_FAST_NORTH] = sAnim_GoFastNorth2F,
sAnim_GoFastWest2F, [ANIM_STD_GO_FAST_WEST] = sAnim_GoFastWest2F,
sAnim_GoFastEast2F, [ANIM_STD_GO_FAST_EAST] = sAnim_GoFastEast2F,
sAnim_EnterSouth, // 'Faster' and above used for entering/exiting pokeball
sAnim_EnterNorth, [ANIM_STD_GO_FASTER_SOUTH] = sAnim_EnterSouth,
sAnim_EnterWest, [ANIM_STD_GO_FASTER_NORTH] = sAnim_EnterNorth,
sAnim_EnterEast, [ANIM_STD_GO_FASTER_WEST] = sAnim_EnterWest,
sAnim_ExitPokeballSouth, [ANIM_STD_GO_FASTER_EAST] = sAnim_EnterEast,
sAnim_ExitPokeballNorth, [ANIM_STD_GO_FASTEST_SOUTH] = sAnim_ExitPokeballSouth,
sAnim_ExitPokeballWest, [ANIM_STD_GO_FASTEST_NORTH] = sAnim_ExitPokeballNorth,
sAnim_ExitPokeballEast, [ANIM_STD_GO_FASTEST_WEST] = sAnim_ExitPokeballWest,
// ANIM_STD_COUNT = [ANIM_STD_GO_FASTEST_EAST] = sAnim_ExitPokeballEast,
sAnim_ExitPokeballFastSouth, [ANIM_EXIT_POKEBALL_FAST_SOUTH] = sAnim_ExitPokeballFastSouth,
sAnim_ExitPokeballFastNorth, [ANIM_EXIT_POKEBALL_FAST_NORTH] = sAnim_ExitPokeballFastNorth,
sAnim_ExitPokeballFastWest, [ANIM_EXIT_POKEBALL_FAST_WEST] = sAnim_ExitPokeballFastWest,
sAnim_ExitPokeballFastEast, [ANIM_EXIT_POKEBALL_FAST_EAST] = sAnim_ExitPokeballFastEast,
};
// Like the above, but has separate frames for facing right
static const union AnimCmd *const sAnimTable_Following_Asym[] = {
[ANIM_STD_FACE_SOUTH] = sAnim_FaceSouth,
[ANIM_STD_FACE_NORTH] = sAnim_FaceNorth2F,
[ANIM_STD_FACE_WEST] = sAnim_FaceWest2F,
[ANIM_STD_FACE_EAST] = sAnim_FaceEast2F_Asym,
[ANIM_STD_GO_SOUTH] = sAnim_GoSouth2F,
[ANIM_STD_GO_NORTH] = sAnim_GoNorth2F,
[ANIM_STD_GO_WEST] = sAnim_GoWest2F,
[ANIM_STD_GO_EAST] = sAnim_GoEast2F_Asym,
[ANIM_STD_GO_FAST_SOUTH] = sAnim_GoFastSouth2F,
[ANIM_STD_GO_FAST_NORTH] = sAnim_GoFastNorth2F,
[ANIM_STD_GO_FAST_WEST] = sAnim_GoFastWest2F,
[ANIM_STD_GO_FAST_EAST] = sAnim_GoFastEast2F_Asym,
[ANIM_STD_GO_FASTER_SOUTH] = sAnim_EnterSouth,
[ANIM_STD_GO_FASTER_NORTH] = sAnim_EnterNorth,
[ANIM_STD_GO_FASTER_WEST] = sAnim_EnterWest,
[ANIM_STD_GO_FASTER_EAST] = sAnim_EnterEast_Asym,
[ANIM_STD_GO_FASTEST_SOUTH] = sAnim_ExitPokeballSouth,
[ANIM_STD_GO_FASTEST_NORTH] = sAnim_ExitPokeballNorth,
[ANIM_STD_GO_FASTEST_WEST] = sAnim_ExitPokeballWest,
[ANIM_STD_GO_FASTEST_EAST] = sAnim_ExitPokeballEast_Asym,
[ANIM_EXIT_POKEBALL_FAST_SOUTH] = sAnim_ExitPokeballFastSouth,
[ANIM_EXIT_POKEBALL_FAST_NORTH] = sAnim_ExitPokeballFastNorth,
[ANIM_EXIT_POKEBALL_FAST_WEST] = sAnim_ExitPokeballFastWest,
[ANIM_EXIT_POKEBALL_FAST_EAST] = sAnim_ExitPokeballFastEast_Asym,
}; };
static const union AnimCmd *const sAnimTable_HoOh[] = { static const union AnimCmd *const sAnimTable_HoOh[] = {

View File

@ -346,6 +346,56 @@ const u32 gObjectEventPic_Noland[] = INCBIN_U32("graphics/object_events/pics/peo
const u32 gObjectEventPic_Lucy[] = INCBIN_U32("graphics/object_events/pics/people/frontier_brains/lucy.4bpp"); const u32 gObjectEventPic_Lucy[] = INCBIN_U32("graphics/object_events/pics/people/frontier_brains/lucy.4bpp");
const u32 gObjectEventPic_Brandon[] = INCBIN_U32("graphics/object_events/pics/people/frontier_brains/brandon.4bpp"); const u32 gObjectEventPic_Brandon[] = INCBIN_U32("graphics/object_events/pics/people/frontier_brains/brandon.4bpp");
const u32 gObjectEventPic_AnimatedBall[] = INCBIN_U32("graphics/object_events/pics/misc/animated_ball.4bpp"); const u32 gObjectEventPic_AnimatedBall[] = INCBIN_U32("graphics/object_events/pics/misc/animated_ball.4bpp");
#if OW_MON_POKEBALLS
// Vanilla
const u32 gObjectEventPic_MasterBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_master.4bpp");
const u32 gObjectEventPic_UltraBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_ultra.4bpp");
const u32 gObjectEventPic_GreatBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_great.4bpp");
const u32 gObjectEventPic_SafariBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_safari.4bpp");
const u32 gObjectEventPic_NetBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_net.4bpp");
const u32 gObjectEventPic_DiveBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_dive.4bpp");
const u32 gObjectEventPic_NestBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_nest.4bpp");
const u32 gObjectEventPic_RepeatBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_repeat.4bpp");
const u32 gObjectEventPic_TimerBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_timer.4bpp");
const u32 gObjectEventPic_LuxuryBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_luxury.4bpp");
const u32 gObjectEventPic_PremierBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_premier.4bpp");
// Gen IV/Sinnoh
#ifdef ITEM_DUSK_BALL
const u32 gObjectEventPic_DuskBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_dusk.4bpp");
const u32 gObjectEventPic_HealBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_heal.4bpp");
const u32 gObjectEventPic_QuickBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_quick.4bpp");
const u32 gObjectEventPic_CherishBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_cherish.4bpp");
#endif
#ifdef ITEM_PARK_BALL
const u32 gObjectEventPic_ParkBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_park.4bpp");
#endif
// Gen II/Johto Apricorns
#ifdef ITEM_FAST_BALL
const u32 gObjectEventPic_FastBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_fast.4bpp");
const u32 gObjectEventPic_LevelBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_level.4bpp");
const u32 gObjectEventPic_LureBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_lure.4bpp");
const u32 gObjectEventPic_HeavyBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_heavy.4bpp");
const u32 gObjectEventPic_LoveBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_love.4bpp");
const u32 gObjectEventPic_FriendBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_friend.4bpp");
const u32 gObjectEventPic_MoonBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_moon.4bpp");
const u32 gObjectEventPic_SportBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_sport.4bpp");
#endif
// Gen V
#ifdef ITEM_DREAM_BALL
const u32 gObjectEventPic_DreamBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_dream.4bpp");
#endif
// Gen VII
#ifdef ITEM_BEAST_BALL
const u32 gObjectEventPic_BeastBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_beast.4bpp");
#endif
// Gen VIII
#ifdef ITEM_STRANGE_BALL
const u32 gObjectEventPic_StrangeBall[] = INCBIN_U32("graphics/object_events/pics/misc/ball_strange.4bpp");
#endif
#endif
const u32 gObjectEventPic_Substitute[] = INCBIN_U32("graphics/object_events/pics/pokemon/substitute.4bpp");
const u32 gObjectEventPic_Bulbasaur[] = INCBIN_U32("graphics/object_events/pics/pokemon/bulbasaur.4bpp"); const u32 gObjectEventPic_Bulbasaur[] = INCBIN_U32("graphics/object_events/pics/pokemon/bulbasaur.4bpp");
const u32 gObjectEventPic_Ivysaur[] = INCBIN_U32("graphics/object_events/pics/pokemon/ivysaur.4bpp"); const u32 gObjectEventPic_Ivysaur[] = INCBIN_U32("graphics/object_events/pics/pokemon/ivysaur.4bpp");
const u32 gObjectEventPic_Venusaur[] = INCBIN_U32("graphics/object_events/pics/pokemon/venusaur.4bpp"); const u32 gObjectEventPic_Venusaur[] = INCBIN_U32("graphics/object_events/pics/pokemon/venusaur.4bpp");
@ -792,5 +842,44 @@ const u16 gObjectEventPal_Lugia[] = INCBIN_U16("graphics/object_events/palettes/
const u16 gObjectEventPaletteLight[] = INCBIN_U16("graphics/object_events/palettes/light.gbapal"); const u16 gObjectEventPaletteLight[] = INCBIN_U16("graphics/object_events/palettes/light.gbapal");
const u16 gObjectEventPaletteLight2[] = INCBIN_U16("graphics/object_events/palettes/light2.gbapal"); const u16 gObjectEventPaletteLight2[] = INCBIN_U16("graphics/object_events/palettes/light2.gbapal");
const u16 gObjectEventPal_Substitute[] = INCBIN_U16("graphics/object_events/pics/pokemon/substitute.gbapal");
const u16 gObjectEventPaletteEmotes[] = INCBIN_U16("graphics/misc/emotes.gbapal"); const u16 gObjectEventPaletteEmotes[] = INCBIN_U16("graphics/misc/emotes.gbapal");
const u16 gObjectEventPaletteNeonLight[] = INCBIN_U16("graphics/object_events/palettes/neon_light.gbapal"); const u16 gObjectEventPaletteNeonLight[] = INCBIN_U16("graphics/object_events/palettes/neon_light.gbapal");
#if OW_MON_POKEBALLS
// Palettes are small, so always include all of the palettes (no #ifdef)
// Vanilla
const u16 gObjectEventPal_MasterBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_master.gbapal");
const u16 gObjectEventPal_UltraBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_ultra.gbapal");
const u16 gObjectEventPal_GreatBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_great.gbapal");
const u16 gObjectEventPal_SafariBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_safari.gbapal");
const u16 gObjectEventPal_NetBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_net.gbapal");
const u16 gObjectEventPal_DiveBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_dive.gbapal");
const u16 gObjectEventPal_NestBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_nest.gbapal");
const u16 gObjectEventPal_RepeatBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_repeat.gbapal");
const u16 gObjectEventPal_TimerBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_timer.gbapal");
const u16 gObjectEventPal_LuxuryBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_luxury.gbapal");
const u16 gObjectEventPal_PremierBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_premier.gbapal");
// Gen IV/Sinnoh
const u16 gObjectEventPal_DuskBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_dusk.gbapal");
const u16 gObjectEventPal_HealBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_heal.gbapal");
const u16 gObjectEventPal_QuickBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_quick.gbapal");
const u16 gObjectEventPal_CherishBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_cherish.gbapal");
const u16 gObjectEventPal_ParkBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_park.gbapal");
// Gen II/Johto Apricorns
const u16 gObjectEventPal_FastBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_fast.gbapal");
const u16 gObjectEventPal_LevelBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_level.gbapal");
const u16 gObjectEventPal_LureBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_lure.gbapal");
const u16 gObjectEventPal_HeavyBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_heavy.gbapal");
const u16 gObjectEventPal_LoveBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_love.gbapal");
const u16 gObjectEventPal_FriendBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_friend.gbapal");
const u16 gObjectEventPal_MoonBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_moon.gbapal");
const u16 gObjectEventPal_SportBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_sport.gbapal");
// Gen V
const u16 gObjectEventPal_DreamBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_dream.gbapal");
// Gen VII
const u16 gObjectEventPal_BeastBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_beast.gbapal");
// Gen VIII
const u16 gObjectEventPal_StrangeBall[] = INCBIN_U16("graphics/object_events/pics/misc/ball_strange.gbapal");
#endif

View File

@ -1,5 +1,7 @@
// Species-indexed pokemon object event table // Species-indexed pokemon object event table
const struct ObjectEventGraphicsInfo gPokemonObjectGraphics[] = { const struct ObjectEventGraphicsInfo gPokemonObjectGraphics[] = {
// placeholder gfx, used when other gfx aren't found
[SPECIES_NONE] = {0xFFFF, OBJ_EVENT_PAL_TAG_SUBSTITUTE, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_NONE, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_Substitute, gDummySpriteAffineAnimTable},
[SPECIES_BULBASAUR] = {0xFFFF, OBJ_EVENT_PAL_TAG_DYNAMIC, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_FOOT, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_Bulbasaur, gDummySpriteAffineAnimTable}, [SPECIES_BULBASAUR] = {0xFFFF, OBJ_EVENT_PAL_TAG_DYNAMIC, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_FOOT, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_Bulbasaur, gDummySpriteAffineAnimTable},
[SPECIES_IVYSAUR] = {0xFFFF, OBJ_EVENT_PAL_TAG_DYNAMIC, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_FOOT, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_Ivysaur, gDummySpriteAffineAnimTable}, [SPECIES_IVYSAUR] = {0xFFFF, OBJ_EVENT_PAL_TAG_DYNAMIC, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_FOOT, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_Ivysaur, gDummySpriteAffineAnimTable},
[SPECIES_VENUSAUR] = {0xFFFF, OBJ_EVENT_PAL_TAG_DYNAMIC, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_FOOT, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_Venusaur, gDummySpriteAffineAnimTable}, [SPECIES_VENUSAUR] = {0xFFFF, OBJ_EVENT_PAL_TAG_DYNAMIC, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_FOOT, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_Venusaur, gDummySpriteAffineAnimTable},
@ -416,9 +418,89 @@ const struct ObjectEventGraphicsInfo gPokemonObjectGraphics[] = {
}; };
// Normal, sunny, rainy, snowy // Normal, sunny, rainy, snowy
const struct ObjectEventGraphicsInfo gCastformObjectGraphics[] = { const struct ObjectEventGraphicsInfo gCastformObjectGraphics[] =
{0xFFFF, OBJ_EVENT_PAL_TAG_DYNAMIC, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_NONE, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_Castform, gDummySpriteAffineAnimTable}, {
{0xFFFF, OBJ_EVENT_PAL_TAG_CASTFORM_SUNNY, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_NONE, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_CastformSunny, gDummySpriteAffineAnimTable}, {TAG_NONE, OBJ_EVENT_PAL_TAG_DYNAMIC, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_NONE, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_Castform, gDummySpriteAffineAnimTable},
{0xFFFF, OBJ_EVENT_PAL_TAG_CASTFORM_RAINY, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_NONE, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_CastformRainy, gDummySpriteAffineAnimTable}, {TAG_NONE, OBJ_EVENT_PAL_TAG_CASTFORM_SUNNY, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_NONE, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_CastformSunny, gDummySpriteAffineAnimTable},
{0xFFFF, OBJ_EVENT_PAL_TAG_CASTFORM_SNOWY, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_NONE, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_CastformSnowy, gDummySpriteAffineAnimTable}, {TAG_NONE, OBJ_EVENT_PAL_TAG_CASTFORM_RAINY, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_NONE, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_CastformRainy, gDummySpriteAffineAnimTable},
{TAG_NONE, OBJ_EVENT_PAL_TAG_CASTFORM_SNOWY, OBJ_EVENT_PAL_TAG_NONE, 512, 32, 32, 2, SHADOW_SIZE_M, FALSE, FALSE, TRACKS_NONE, &gObjectEventBaseOam_32x32, sOamTables_32x32, sAnimTable_Following, sPicTable_CastformSnowy, gDummySpriteAffineAnimTable},
}; };
// Standalone follower palettes
// If not NULL, entries here override the front-sprite-based pals
// used by OBJ_EVENT_PAL_TAG_DYNAMIC
// Palette data may be compressed, or not
const void* const gFollowerPalettes[][2] =
{
// Must have at least one entry, or ARRAY_COUNT comparison fails
// (SPECIES_NONE does not use OBJ_EVENT_PAL_TAG_DYNAMIC anyway)
[SPECIES_NONE] = {gMonPalette_CircledQuestionMark, gMonShinyPalette_CircledQuestionMark},
};
#if OW_MON_POKEBALLS
#define POKEBALL_GFX_INFO(NAME) \
[BALL_##NAME] = { \
.tileTag = TAG_NONE, \
.paletteTag = OBJ_EVENT_PAL_TAG_BALL_##NAME, \
.size = 256, \
.width = 16, \
.height = 32, \
.shadowSize = SHADOW_SIZE_M, \
.inanimate = TRUE, \
.oam = &gObjectEventBaseOam_16x32, \
.subspriteTables = sOamTables_16x32, \
.anims = sAnimTable_Following, \
.images = sPicTable_Ball_##NAME, \
.affineAnims = gDummySpriteAffineAnimTable, \
}
const struct ObjectEventGraphicsInfo gPokeballGraphics[POKEBALL_COUNT] = {
// Vanilla
POKEBALL_GFX_INFO(MASTER),
POKEBALL_GFX_INFO(ULTRA),
POKEBALL_GFX_INFO(GREAT),
POKEBALL_GFX_INFO(SAFARI),
POKEBALL_GFX_INFO(NET),
POKEBALL_GFX_INFO(DIVE),
POKEBALL_GFX_INFO(NEST),
POKEBALL_GFX_INFO(REPEAT),
POKEBALL_GFX_INFO(TIMER),
POKEBALL_GFX_INFO(LUXURY),
POKEBALL_GFX_INFO(PREMIER),
// Gen IV/Sinnoh pokeballs
#ifdef ITEM_DUSK_BALL
POKEBALL_GFX_INFO(DUSK),
POKEBALL_GFX_INFO(HEAL),
POKEBALL_GFX_INFO(QUICK),
POKEBALL_GFX_INFO(CHERISH),
#endif
#ifdef ITEM_PARK_BALL
POKEBALL_GFX_INFO(PARK),
#endif
// Gen II/Johto Apricorn pokeballs
#ifdef ITEM_FAST_BALL
POKEBALL_GFX_INFO(FAST),
POKEBALL_GFX_INFO(LEVEL),
POKEBALL_GFX_INFO(LURE),
POKEBALL_GFX_INFO(HEAVY),
POKEBALL_GFX_INFO(LOVE),
POKEBALL_GFX_INFO(FRIEND),
POKEBALL_GFX_INFO(MOON),
POKEBALL_GFX_INFO(SPORT),
#endif
// Gen V
#ifdef ITEM_DREAM_BALL
POKEBALL_GFX_INFO(DREAM),
#endif
// Gen VII
#ifdef ITEM_BEAST_BALL
POKEBALL_GFX_INFO(BEAST),
#endif
// Gen VIII
#ifdef ITEM_STRANGE_BALL
POKEBALL_GFX_INFO(STRANGE),
#endif
};
#endif

View File

@ -1987,11 +1987,146 @@ static const struct SpriteFrameImage sPicTable_AnimatedBall[] = {
overworld_frame(gObjectEventPic_AnimatedBall, 2, 4, 2), overworld_frame(gObjectEventPic_AnimatedBall, 2, 4, 2),
overworld_frame(gObjectEventPic_AnimatedBall, 2, 4, 3), overworld_frame(gObjectEventPic_AnimatedBall, 2, 4, 3),
overworld_frame(gObjectEventPic_AnimatedBall, 2, 4, 4), overworld_frame(gObjectEventPic_AnimatedBall, 2, 4, 4),
overworld_frame(gObjectEventPic_AnimatedBall, 2, 4, 5), overworld_frame(gObjectEventPic_AnimatedBall, 2, 4, 0),
}; };
extern const struct SpriteFrameImage gFieldEffectObjectPicTable_BallLight[]; extern const struct SpriteFrameImage gFieldEffectObjectPicTable_BallLight[];
#if OW_MON_POKEBALLS
#define POKEBALL_PIC_FRAMES(name) \
overworld_frame(gObjectEventPic_##name##Ball, 2, 4, 0), \
overworld_frame(gObjectEventPic_##name##Ball, 2, 4, 1), \
overworld_frame(gObjectEventPic_##name##Ball, 2, 4, 2), \
overworld_frame(gObjectEventPic_##name##Ball, 2, 4, 3), \
overworld_frame(gObjectEventPic_##name##Ball, 2, 4, 4), \
overworld_frame(gObjectEventPic_##name##Ball, 2, 4, 0)
static const struct SpriteFrameImage sPicTable_Ball_MASTER[] = {
POKEBALL_PIC_FRAMES(Master),
};
static const struct SpriteFrameImage sPicTable_Ball_ULTRA[] = {
POKEBALL_PIC_FRAMES(Ultra),
};
static const struct SpriteFrameImage sPicTable_Ball_GREAT[] = {
POKEBALL_PIC_FRAMES(Great),
};
static const struct SpriteFrameImage sPicTable_Ball_SAFARI[] = {
POKEBALL_PIC_FRAMES(Safari),
};
static const struct SpriteFrameImage sPicTable_Ball_NET[] = {
POKEBALL_PIC_FRAMES(Net),
};
static const struct SpriteFrameImage sPicTable_Ball_DIVE[] = {
POKEBALL_PIC_FRAMES(Dive),
};
static const struct SpriteFrameImage sPicTable_Ball_NEST[] = {
POKEBALL_PIC_FRAMES(Nest),
};
static const struct SpriteFrameImage sPicTable_Ball_REPEAT[] = {
POKEBALL_PIC_FRAMES(Repeat),
};
static const struct SpriteFrameImage sPicTable_Ball_TIMER[] = {
POKEBALL_PIC_FRAMES(Timer),
};
static const struct SpriteFrameImage sPicTable_Ball_LUXURY[] = {
POKEBALL_PIC_FRAMES(Luxury),
};
static const struct SpriteFrameImage sPicTable_Ball_PREMIER[] = {
POKEBALL_PIC_FRAMES(Premier),
};
// Gen IV/Sinnoh
#ifdef ITEM_DUSK_BALL
static const struct SpriteFrameImage sPicTable_Ball_DUSK[] = {
POKEBALL_PIC_FRAMES(Dusk),
};
static const struct SpriteFrameImage sPicTable_Ball_HEAL[] = {
POKEBALL_PIC_FRAMES(Heal),
};
static const struct SpriteFrameImage sPicTable_Ball_QUICK[] = {
POKEBALL_PIC_FRAMES(Quick),
};
static const struct SpriteFrameImage sPicTable_Ball_CHERISH[] = {
POKEBALL_PIC_FRAMES(Cherish),
};
#endif
#ifdef ITEM_PARK_BALL
static const struct SpriteFrameImage sPicTable_Ball_PARK[] = {
POKEBALL_PIC_FRAMES(Park),
};
#endif
// Gen II/Johto Apricorns
#ifdef ITEM_FAST_BALL
static const struct SpriteFrameImage sPicTable_Ball_FAST[] = {
POKEBALL_PIC_FRAMES(Fast),
};
static const struct SpriteFrameImage sPicTable_Ball_LEVEL[] = {
POKEBALL_PIC_FRAMES(Level),
};
static const struct SpriteFrameImage sPicTable_Ball_LURE[] = {
POKEBALL_PIC_FRAMES(Lure),
};
static const struct SpriteFrameImage sPicTable_Ball_HEAVY[] = {
POKEBALL_PIC_FRAMES(Heavy),
};
static const struct SpriteFrameImage sPicTable_Ball_LOVE[] = {
POKEBALL_PIC_FRAMES(Love),
};
static const struct SpriteFrameImage sPicTable_Ball_FRIEND[] = {
POKEBALL_PIC_FRAMES(Friend),
};
static const struct SpriteFrameImage sPicTable_Ball_MOON[] = {
POKEBALL_PIC_FRAMES(Moon),
};
static const struct SpriteFrameImage sPicTable_Ball_SPORT[] = {
POKEBALL_PIC_FRAMES(Sport),
};
#endif
// Gen V
#ifdef ITEM_DREAM_BALL
static const struct SpriteFrameImage sPicTable_Ball_DREAM[] = {
POKEBALL_PIC_FRAMES(Dream),
};
#endif
// Gen VII
#ifdef ITEM_BEAST_BALL
static const struct SpriteFrameImage sPicTable_Ball_BEAST[] = {
POKEBALL_PIC_FRAMES(Beast),
};
#endif
// Gen VIII
#ifdef ITEM_STRANGE_BALL
static const struct SpriteFrameImage sPicTable_Ball_STRANGE[] = {
POKEBALL_PIC_FRAMES(Strange),
};
#endif
#endif
static const struct SpriteFrameImage sPicTable_Substitute[] = {
overworld_frame(gObjectEventPic_Substitute, 4, 4, 0),
overworld_frame(gObjectEventPic_Substitute, 4, 4, 1),
overworld_frame(gObjectEventPic_Substitute, 4, 4, 2),
overworld_frame(gObjectEventPic_Substitute, 4, 4, 3),
overworld_frame(gObjectEventPic_Substitute, 4, 4, 4),
overworld_frame(gObjectEventPic_Substitute, 4, 4, 5),
};
static const struct SpriteFrameImage sPicTable_Bulbasaur[] = { static const struct SpriteFrameImage sPicTable_Bulbasaur[] = {
overworld_frame(gObjectEventPic_Bulbasaur, 4, 4, 0), overworld_frame(gObjectEventPic_Bulbasaur, 4, 4, 0),
overworld_frame(gObjectEventPic_Bulbasaur, 4, 4, 1), overworld_frame(gObjectEventPic_Bulbasaur, 4, 4, 1),

View File

@ -19,6 +19,24 @@ void LZDecompressVram(const u32 *src, void *dest)
LZ77UnCompVram(src, dest); LZ77UnCompVram(src, dest);
} }
// Checks if `ptr` is likely LZ77 data
// Checks word-alignment, min/max size, and header byte
bool32 IsLZ77Data(const void *ptr, u32 minSize, u32 maxSize) {
const u8 *data = ptr;
u32 size;
// Compressed data must be word aligned
if (((u32)ptr) & 3)
return FALSE;
// Check LZ77 header byte
// See https://problemkaputt.de/gbatek.htm#biosdecompressionfunctions
if (data[0] != 0x10)
return FALSE;
// Read 24-bit uncompressed size
size = data[1] | (data[2] << 8) | (data[3] << 16);
return (size >= minSize && size <= maxSize);
}
u16 LoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src) u16 LoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src)
{ {
struct SpriteSheet dest; struct SpriteSheet dest;

File diff suppressed because it is too large Load Diff

View File

@ -687,7 +687,8 @@ static void Task_DoDoorWarp(u8 taskId)
FreezeObjectEvents(); FreezeObjectEvents();
PlayerGetDestCoords(x, y); PlayerGetDestCoords(x, y);
PlaySE(GetDoorSoundEffect(*x, *y - 1)); PlaySE(GetDoorSoundEffect(*x, *y - 1));
if (followerObject) { // Put follower into pokeball if (followerObject) {
// Put follower into pokeball
ClearObjectEventMovement(followerObject, &gSprites[followerObject->spriteId]); ClearObjectEventMovement(followerObject, &gSprites[followerObject->spriteId]);
ObjectEventSetHeldMovement(followerObject, MOVEMENT_ACTION_ENTER_POKEBALL); ObjectEventSetHeldMovement(followerObject, MOVEMENT_ACTION_ENTER_POKEBALL);
} }

View File

@ -80,241 +80,236 @@ const struct FollowerMsgInfoExtended gFollowerConditionalMessages[COND_MSG_COUNT
.text = (u8*)sCelebiTexts, .text = (u8*)sCelebiTexts,
.textSpread = 1, .textSpread = 1,
.script = EventScript_FollowerDance, .script = EventScript_FollowerDance,
.st = {.species = SPECIES_CELEBI},
.stFlags = ST_FLAGS_SPECIES,
.emotion = FOLLOWER_EMOTION_NEUTRAL, .emotion = FOLLOWER_EMOTION_NEUTRAL,
.conditions = {MATCH_SPECIES(SPECIES_CELEBI)},
}, },
[COND_MSG_FIRE] = [COND_MSG_FIRE] =
{ {
.text = (u8*)sFireTexts, .text = (u8*)sFireTexts,
.st = {.types = {.type1 = TYPE_FIRE, .type2 = TYPE_FIRE}},
.stFlags = ST_FLAGS_TYPE,
.emotion = FOLLOWER_EMOTION_NEUTRAL,
.textSpread = 1, .textSpread = 1,
.emotion = FOLLOWER_EMOTION_NEUTRAL,
.conditions = {MATCH_TYPES(TYPE_FIRE, TYPE_FIRE)},
}, },
[COND_MSG_EVER_GRANDE] = [COND_MSG_EVER_GRANDE] =
{ {
.text = sCondMsg06, .text = sCondMsg06,
.script = EventScript_FollowerFaceUp, .script = EventScript_FollowerFaceUp,
.mm = {.map = {.mapNum = MAP_NUM(EVER_GRANDE_CITY), .mapGroup = MAP_GROUP(EVER_GRANDE_CITY)}},
.mmFlags = MM_FLAGS_MAP,
.emotion = FOLLOWER_EMOTION_HAPPY, .emotion = FOLLOWER_EMOTION_HAPPY,
.conditions = {MATCH_MAP(EVER_GRANDE_CITY)},
}, },
[COND_MSG_ROUTE_112] = [COND_MSG_ROUTE_112] =
{ {
.text = sCondMsg07, .text = sCondMsg07,
.mm = {.map = {.mapNum = MAP_NUM(ROUTE112), .mapGroup = MAP_GROUP(ROUTE112)}},
.mmFlags = MM_FLAGS_MAP,
.emotion = FOLLOWER_EMOTION_HAPPY, .emotion = FOLLOWER_EMOTION_HAPPY,
.conditions = {MATCH_MAP(ROUTE112)},
}, },
[COND_MSG_DAY_CARE] = [COND_MSG_DAY_CARE] =
{ {
.text = sCondMsg08, .text = sCondMsg08,
.script = EventScript_FollowerNostalgia, .script = EventScript_FollowerNostalgia,
.mm = {.map = {.mapNum = MAP_NUM(ROUTE117_POKEMON_DAY_CARE), .mapGroup = MAP_GROUP(ROUTE117_POKEMON_DAY_CARE)}},
.mmFlags = MM_FLAGS_MAP,
.emotion = FOLLOWER_EMOTION_NEUTRAL, .emotion = FOLLOWER_EMOTION_NEUTRAL,
.conditions = {MATCH_MAP(ROUTE117_POKEMON_DAY_CARE)},
}, },
[COND_MSG_MART] = [COND_MSG_MART] =
{ {
.text = (u8*)sShopTexts, .text = (u8*)sShopTexts,
.textSpread = 1, .textSpread = 1,
.script = EventScript_FollowerLookAround, .script = EventScript_FollowerLookAround,
.wt = {.song = MUS_POKE_MART},
.wtFlags = WT_FLAGS_MUSIC,
.emotion = FOLLOWER_EMOTION_NEUTRAL, .emotion = FOLLOWER_EMOTION_NEUTRAL,
.conditions = {MATCH_MUSIC(MUS_POKE_MART)},
}, },
[COND_MSG_VICTORY_ROAD] = [COND_MSG_VICTORY_ROAD] =
{ {
.text = sCondMsg11, .text = sCondMsg11,
.wt = {.song = MUS_VICTORY_ROAD},
.wtFlags = WT_FLAGS_MUSIC,
.emotion = FOLLOWER_EMOTION_PENSIVE, .emotion = FOLLOWER_EMOTION_PENSIVE,
.conditions = {MATCH_MUSIC(MUS_VICTORY_ROAD)},
}, },
[COND_MSG_BIKE_SHOP] = [COND_MSG_BIKE_SHOP] =
{ {
.text = sCondMsg12, .text = sCondMsg12,
.mm = {.map = {.mapNum = MAP_NUM(MAUVILLE_CITY_BIKE_SHOP), .mapGroup = MAP_GROUP(MAUVILLE_CITY_BIKE_SHOP)}},
.mmFlags = MM_FLAGS_MAP,
.emotion = FOLLOWER_EMOTION_PENSIVE, .emotion = FOLLOWER_EMOTION_PENSIVE,
.conditions = {MATCH_MAP(MAUVILLE_CITY_BIKE_SHOP)},
}, },
[COND_MSG_MACHINES] = [COND_MSG_MACHINES] =
{ {
.text = (u8*)sMachineTexts, .text = (u8*)sMachineTexts,
.mm = {.map = {.mapNum = MAP_NUM(NEW_MAUVILLE_INSIDE), .mapGroup = MAP_GROUP(NEW_MAUVILLE_INSIDE)}},
.mmFlags = MM_FLAGS_MAP,
.emotion = FOLLOWER_EMOTION_MUSIC,
.textSpread = 1, .textSpread = 1,
.emotion = FOLLOWER_EMOTION_MUSIC,
.orFlag = 1, // match any of these maps
.conditions = {
MATCH_MAP(NEW_MAUVILLE_INSIDE),
MATCH_MAP(SLATEPORT_CITY_STERNS_SHIPYARD_1F),
MATCH_MAP(SLATEPORT_CITY_STERNS_SHIPYARD_2F),
}
}, },
[COND_MSG_SAILING] = [COND_MSG_SAILING] =
{ {
.text = (u8*)sBoatTexts, .text = (u8*)sBoatTexts,
.script = EventScript_FollowerLookAround,
.wt = {.song = MUS_SAILING},
.wtFlags = WT_FLAGS_MUSIC,
.emotion = FOLLOWER_EMOTION_MUSIC,
.textSpread = 1, .textSpread = 1,
.emotion = FOLLOWER_EMOTION_MUSIC,
.script = EventScript_FollowerLookAround,
.conditions = {MATCH_MUSIC(MUS_SAILING)},
}, },
[COND_MSG_PUDDLE] = [COND_MSG_PUDDLE] =
{ {
.text = sCondMsg18, .text = sCondMsg18,
.script = EventScript_FollowerHopping, .script = EventScript_FollowerHopping,
.mm = {.mb = {.behavior1 = MB_SHALLOW_WATER, .behavior2 = MB_PUDDLE}},
.mmFlags = MM_FLAGS_MB,
.emotion = FOLLOWER_EMOTION_MUSIC, .emotion = FOLLOWER_EMOTION_MUSIC,
.conditions = {MATCH_ON_MB(MB_SHALLOW_WATER, MB_PUDDLE)},
}, },
[COND_MSG_SAND] = [COND_MSG_SAND] =
{ {
.text = sCondMsg19, .text = sCondMsg19,
.mm = {.mb = {.behavior1 = MB_SAND, .behavior2 = MB_DEEP_SAND}},
.mmFlags = MM_FLAGS_MB,
.emotion = FOLLOWER_EMOTION_MUSIC, .emotion = FOLLOWER_EMOTION_MUSIC,
.conditions = {MATCH_ON_MB(MB_SAND, MB_DEEP_SAND)},
}, },
[COND_MSG_GRASS] = [COND_MSG_GRASS] =
{ {
.text = sCondMsg20, .text = sCondMsg20,
.mm = {.mb = {.behavior1 = MB_TALL_GRASS, .behavior2 = MB_LONG_GRASS}},
.mmFlags = MM_FLAGS_MB,
.emotion = FOLLOWER_EMOTION_MUSIC, .emotion = FOLLOWER_EMOTION_MUSIC,
.conditions = {MATCH_ON_MB(MB_TALL_GRASS, MB_LONG_GRASS)},
}, },
[COND_MSG_FOOTPRINTS] = [COND_MSG_FOOTPRINTS] =
{ {
.text = sCondMsg21, .text = sCondMsg21,
.mm = {.mb = {.behavior1 = MB_SAND, .behavior2 = MB_FOOTPRINTS}},
.mmFlags = MM_FLAGS_MB,
.emotion = FOLLOWER_EMOTION_MUSIC, .emotion = FOLLOWER_EMOTION_MUSIC,
.conditions = {MATCH_ON_MB(MB_SAND, MB_FOOTPRINTS)},
}, },
[COND_MSG_ELEVATOR] = [COND_MSG_ELEVATOR] =
{ {
.text = (u8*)sElevatorTexts, .text = (u8*)sElevatorTexts,
.textSpread = 1, .textSpread = 1,
.mm = {.map = {.mapNum = MAP_NUM(LILYCOVE_CITY_DEPARTMENT_STORE_ELEVATOR), .mapGroup = MAP_GROUP(LILYCOVE_CITY_DEPARTMENT_STORE_ELEVATOR)}},
.mmFlags = MM_FLAGS_MAP,
.emotion = FOLLOWER_EMOTION_SURPRISE, .emotion = FOLLOWER_EMOTION_SURPRISE,
.conditions = {MATCH_MAP(LILYCOVE_CITY_DEPARTMENT_STORE_ELEVATOR)},
}, },
[COND_MSG_ICE_ROOM] = [COND_MSG_ICE_ROOM] =
{ {
.text = (u8*)sColdTexts, .text = (u8*)sColdTexts,
.textSpread = 1, .textSpread = 1,
.mm = {.map = {.mapNum = MAP_NUM(SHOAL_CAVE_LOW_TIDE_ICE_ROOM), .mapGroup = MAP_GROUP(SHOAL_CAVE_LOW_TIDE_ICE_ROOM)}},
.mmFlags = MM_FLAGS_MAP,
.emotion = FOLLOWER_EMOTION_SURPRISE, .emotion = FOLLOWER_EMOTION_SURPRISE,
.conditions = {MATCH_MAP(SHOAL_CAVE_LOW_TIDE_ICE_ROOM)},
}, },
[COND_MSG_ROUTE_117] = [COND_MSG_ROUTE_117] =
{ {
.text = sCondMsg27, .text = sCondMsg27,
.mm = {.map = {.mapNum = MAP_NUM(ROUTE117), .mapGroup = MAP_GROUP(ROUTE117)}},
.mmFlags = MM_FLAGS_MAP,
.emotion = FOLLOWER_EMOTION_SURPRISE, .emotion = FOLLOWER_EMOTION_SURPRISE,
.conditions = {MATCH_MAP(ROUTE117)},
}, },
[COND_MSG_DRAGON_GROWL] = [COND_MSG_DRAGON_GROWL] =
{ {
.text = sCondMsg28, .text = sCondMsg28,
.st = {.types = {.type1 = TYPE_DRAGON, .type2 = TYPE_DRAGON}},
.stFlags = ST_FLAGS_TYPE,
.mm = {.mapSec = {.mapSec = MAPSEC_SKY_PILLAR}},
.mmFlags = MM_FLAGS_MAPSEC,
.emotion = FOLLOWER_EMOTION_UPSET, .emotion = FOLLOWER_EMOTION_UPSET,
.conditions = {
MATCH_TYPES(TYPE_DRAGON, TYPE_DRAGON),
MATCH_MAPSEC(MAPSEC_SKY_PILLAR),
}
}, },
[COND_MSG_FEAR] = [COND_MSG_FEAR] =
{ {
.text = (u8*)sFearTexts, .text = (u8*)sFearTexts,
.textSpread = 1, .textSpread = 1,
.st = {.types = {.type1 = TYPE_GHOST, .type2 = TYPE_NOT_TYPE1}},
.stFlags = ST_FLAGS_TYPE,
.mm = {.mapSec = {.mapSec = MAPSEC_MT_PYRE}},
.mmFlags = MM_FLAGS_MAPSEC,
.wt = {.song = MUS_MT_PYRE},
.wtFlags = WT_FLAGS_MUSIC,
.emotion = FOLLOWER_EMOTION_UPSET, .emotion = FOLLOWER_EMOTION_UPSET,
.conditions = {
MATCH_NOT_TYPES(TYPE_GHOST, TYPE_GHOST),
MATCH_MAPSEC(MAPSEC_MT_PYRE),
MATCH_MUSIC(MUS_MT_PYRE),
}
}, },
[COND_MSG_FIRE_RAIN] = [COND_MSG_FIRE_RAIN] =
{ {
.text = sCondMsg31, .text = sCondMsg31,
.st = {.types = {.type1 = TYPE_FIRE, .type2 = TYPE_FIRE}},
.stFlags = ST_FLAGS_TYPE,
.wt = {.weather = {.weather1 = WEATHER_RAIN, .weather2 = WEATHER_RAIN_THUNDERSTORM}},
.wtFlags = WT_FLAGS_WEATHER,
.emotion = FOLLOWER_EMOTION_UPSET, .emotion = FOLLOWER_EMOTION_UPSET,
.conditions = {
MATCH_TYPES(TYPE_FIRE, TYPE_FIRE),
MATCH_WEATHER(WEATHER_RAIN, WEATHER_RAIN_THUNDERSTORM),
}
}, },
[COND_MSG_FROZEN] = [COND_MSG_FROZEN] =
{ {
.text = sCondMsg32, .text = sCondMsg32,
.st = {.status = STATUS1_FREEZE},
.stFlags = ST_FLAGS_STATUS,
.emotion = FOLLOWER_EMOTION_UPSET, .emotion = FOLLOWER_EMOTION_UPSET,
.conditions = {
MATCH_STATUS(STATUS1_FREEZE),
}
}, },
[COND_MSG_SEASIDE] = [COND_MSG_SEASIDE] =
{ {
.text = (u8*)sSeaTexts, .text = (u8*)sSeaTexts,
.textSpread = 1, .textSpread = 1,
.script = EventScript_FollowerFaceResult, .script = EventScript_FollowerFaceResult,
.near = {.mb = {.behavior = MB_OCEAN_WATER, .distance = 5}},
.nearFlags = NEAR_FLAGS_MB,
.emotion = FOLLOWER_EMOTION_MUSIC, .emotion = FOLLOWER_EMOTION_MUSIC,
.conditions = {MATCH_NEAR_MB(MB_OCEAN_WATER, 5)},
}, },
[COND_MSG_WATERFALL] = [COND_MSG_WATERFALL] =
{ {
.text = sCondMsg36, .text = sCondMsg36,
.script = EventScript_FollowerFaceResult, .script = EventScript_FollowerFaceResult,
.near = {.mb = {.behavior = MB_WATERFALL, .distance = 5}},
.nearFlags = NEAR_FLAGS_MB,
.emotion = FOLLOWER_EMOTION_MUSIC, .emotion = FOLLOWER_EMOTION_MUSIC,
.conditions = {MATCH_NEAR_MB(MB_WATERFALL, 5)},
}, },
[COND_MSG_RAIN] = [COND_MSG_RAIN] =
{ {
.text = sCondMsg37, .text = sCondMsg37,
.st = {.types = {.type1 = TYPE_FIRE, .type2 = TYPE_NOT_TYPE1}},
.stFlags = ST_FLAGS_TYPE,
.wt = {.weather = {.weather1 = WEATHER_RAIN, .weather2 = WEATHER_RAIN_THUNDERSTORM}},
.wtFlags = WT_FLAGS_WEATHER,
.emotion = FOLLOWER_EMOTION_MUSIC, .emotion = FOLLOWER_EMOTION_MUSIC,
.conditions = {
MATCH_NOT_TYPES(TYPE_FIRE, TYPE_FIRE),
MATCH_WEATHER(WEATHER_RAIN, WEATHER_RAIN_THUNDERSTORM)
}
}, },
[COND_MSG_REFLECTION] = [COND_MSG_REFLECTION] =
{ {
.text = sCondMsg38, .text = sCondMsg38,
.script = EventScript_FollowerFaceResult, .script = EventScript_FollowerFaceResult,
.near = {.mb = {.behavior = MB_POND_WATER, .distance = 1}},
.nearFlags = NEAR_FLAGS_MB,
.emotion = FOLLOWER_EMOTION_PENSIVE, .emotion = FOLLOWER_EMOTION_PENSIVE,
.conditions = {MATCH_NEAR_MB(MB_POND_WATER, 1)},
}, },
[COND_MSG_LEAVES] = [COND_MSG_LEAVES] =
{ {
.text = sCondMsg39, .text = sCondMsg39,
.mm = {.mapSec = {.mapSec = MAPSEC_PETALBURG_WOODS}},
.mmFlags = MM_FLAGS_MAPSEC,
.emotion = FOLLOWER_EMOTION_PENSIVE, .emotion = FOLLOWER_EMOTION_PENSIVE,
.conditions = {MATCH_MAPSEC(MAPSEC_PETALBURG_WOODS)},
}, },
[COND_MSG_ICE] = [COND_MSG_ICE] =
{ {
.text = (u8*)sIceTexts, .text = (u8*)sIceTexts,
.textSpread = 1, .textSpread = 1,
.script = EventScript_FollowerFaceResult, .script = EventScript_FollowerFaceResult,
.near = {.mb = {.behavior = MB_ICE, .distance = 1}},
.nearFlags = NEAR_FLAGS_MB,
.emotion = FOLLOWER_EMOTION_PENSIVE, .emotion = FOLLOWER_EMOTION_PENSIVE,
.conditions = {MATCH_NEAR_MB(MB_ICE, 1)},
}, },
[COND_MSG_BURN] = [COND_MSG_BURN] =
{ {
.text = sCondMsg42, .text = sCondMsg42,
.st = {.status = STATUS1_BURN},
.stFlags = ST_FLAGS_STATUS,
.emotion = FOLLOWER_EMOTION_SAD, .emotion = FOLLOWER_EMOTION_SAD,
.conditions = {MATCH_STATUS(STATUS1_BURN)},
}, },
[COND_MSG_DAY] = [COND_MSG_DAY] =
{ {
.text = (u8*)sDayTexts, .text = (u8*)sDayTexts,
.textSpread = 1, .textSpread = 1,
.wt = {.timeOfDay = TIME_OF_DAY_DAY},
.wtFlags = 3, // time
.emotion = FOLLOWER_EMOTION_MUSIC, .emotion = FOLLOWER_EMOTION_MUSIC,
.conditions = {MATCH_TIME_OF_DAY(TIME_OF_DAY_DAY)},
}, },
[COND_MSG_NIGHT] = [COND_MSG_NIGHT] =
{ {
.text = (u8*)sNightTexts, .text = (u8*)sNightTexts,
.textSpread = 1, .textSpread = 1,
.wt = {.timeOfDay = TIME_OF_DAY_NIGHT},
.wtFlags = 3, // time
.emotion = FOLLOWER_EMOTION_MUSIC, .emotion = FOLLOWER_EMOTION_MUSIC,
.conditions = {MATCH_TIME_OF_DAY(TIME_OF_DAY_NIGHT)},
}, },
}; };
// Pool of "unconditional" follower messages
const struct FollowerMessagePool gFollowerBasicMessages[FOLLOWER_EMOTION_LENGTH] = {
[FOLLOWER_EMOTION_HAPPY] = {gFollowerHappyMessages, EventScript_FollowerGeneric, N_FOLLOWER_HAPPY_MESSAGES},
[FOLLOWER_EMOTION_NEUTRAL] = {gFollowerNeutralMessages, EventScript_FollowerGeneric, N_FOLLOWER_NEUTRAL_MESSAGES},
[FOLLOWER_EMOTION_SAD] = {gFollowerSadMessages, EventScript_FollowerGeneric, N_FOLLOWER_SAD_MESSAGES},
[FOLLOWER_EMOTION_UPSET] = {gFollowerUpsetMessages, EventScript_FollowerGeneric, N_FOLLOWER_UPSET_MESSAGES},
[FOLLOWER_EMOTION_ANGRY] = {gFollowerAngryMessages, EventScript_FollowerGeneric, N_FOLLOWER_ANGRY_MESSAGES},
[FOLLOWER_EMOTION_PENSIVE] = {gFollowerPensiveMessages, EventScript_FollowerGeneric, N_FOLLOWER_PENSIVE_MESSAGES},
[FOLLOWER_EMOTION_LOVE] = {gFollowerLoveMessages, EventScript_FollowerGeneric, N_FOLLOWER_LOVE_MESSAGES},
[FOLLOWER_EMOTION_SURPRISE] = {gFollowerSurpriseMessages, EventScript_FollowerGeneric, N_FOLLOWER_SURPRISE_MESSAGES},
[FOLLOWER_EMOTION_CURIOUS] = {gFollowerCuriousMessages, EventScript_FollowerGeneric, N_FOLLOWER_CURIOUS_MESSAGES},
[FOLLOWER_EMOTION_MUSIC] = {gFollowerMusicMessages, EventScript_FollowerGeneric, N_FOLLOWER_MUSIC_MESSAGES},
[FOLLOWER_EMOTION_POISONED] = {gFollowerPoisonedMessages, EventScript_FollowerGeneric, N_FOLLOWER_POISONED_MESSAGES},
};

View File

@ -441,13 +441,3 @@ void ClearPokemonCrySongs(void)
{ {
CpuFill16(0, gPokemonCrySongs, MAX_POKEMON_CRIES * sizeof(struct PokemonCrySong)); CpuFill16(0, gPokemonCrySongs, MAX_POKEMON_CRIES * sizeof(struct PokemonCrySong));
} }
// TODO: Needs to be updated if compiling for a different processor than the GBA's
bool8 IsAccurateGBA(void) { // tests to see whether running on either an accurate emulator in >=2020, or real hardware
u32 code[5] = {0xFF1EE12F, 0xE1DF00B0, 0xE12FFF1E, 0xAAAABBBB, 0xCCCCDDDD}; // ARM: _;ldrh r0, [pc];bx lr
u32 func = (u32) &code[0];
if (func & 3) // not word aligned; safer to just return false here
return FALSE;
func = (func & ~3) | 0x2; // misalign PC to test PC-relative loading
return ((u32 (*)(void)) func)() == code[3] >> 16;
}

View File

@ -206,7 +206,6 @@ EWRAM_DATA static u16 sAmbientCrySpecies = 0;
EWRAM_DATA static bool8 sIsAmbientCryWaterMon = FALSE; EWRAM_DATA static bool8 sIsAmbientCryWaterMon = FALSE;
EWRAM_DATA struct LinkPlayerObjectEvent gLinkPlayerObjectEvents[4] = {0}; EWRAM_DATA struct LinkPlayerObjectEvent gLinkPlayerObjectEvents[4] = {0};
static const struct WarpData sDummyWarpData = static const struct WarpData sDummyWarpData =
{ {
.mapGroup = MAP_GROUP(UNDEFINED), .mapGroup = MAP_GROUP(UNDEFINED),
@ -2130,6 +2129,7 @@ static bool32 ReturnToFieldLocal(u8 *state)
case 3: case 3:
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }

View File

@ -512,13 +512,12 @@ static u8 UpdateTimeOfDayPaletteFade(void)
// First pply TOD blend to relevant subset of palettes // First pply TOD blend to relevant subset of palettes
if (gPaletteFade.objPaletteToggle) { // Sprite palettes, don't blend those with tags if (gPaletteFade.objPaletteToggle) { // Sprite palettes, don't blend those with tags
u8 i; u32 i;
u16 j = 1; u32 j = 1;
for (i = 0; i < 16; i++, j <<= 1) { // Mask out palettes that should not be light blended for (i = 0; i < 16; i++, j <<= 1) { // Mask out palettes that should not be light blended
if ((selectedPalettes & j) && !(GetSpritePaletteTagByPaletteNum(i) >> 15)) if ((selectedPalettes & j) && !(GetSpritePaletteTagByPaletteNum(i) >> 15))
timePalettes |= j; timePalettes |= j;
} }
} else { // tile palettes, don't blend [13, 15] } else { // tile palettes, don't blend [13, 15]
timePalettes = selectedPalettes & 0x1FFF; timePalettes = selectedPalettes & 0x1FFF;
} }

View File

@ -3360,36 +3360,23 @@ static void PrintRibbonCount(void)
PrintTextOnWindow(AddWindowFromTemplateList(sPageSkillsTemplate, PSS_DATA_WINDOW_SKILLS_RIBBON_COUNT), text, x, 1, 0, 0); PrintTextOnWindow(AddWindowFromTemplateList(sPageSkillsTemplate, PSS_DATA_WINDOW_SKILLS_RIBBON_COUNT), text, x, 1, 0, 0);
} }
// Based on https://www.pokecommunity.com/showpost.php?p=10024409&postcount=21
static void BufferStat(u8 *dst, s8 natureMod, u32 stat, u32 strId, u32 n) {
static const u8 textNatureMinus[] = _("{COLOR_HIGHLIGHT_SHADOW}{BLUE}{TRANSPARENT}{07}"); // Blue
static const u8 textNaturePlus[] = _("{COLOR_HIGHLIGHT_SHADOW}{05}{TRANSPARENT}{06}"); // Red
static const u8 textNatureNone[] = _("{COLOR_HIGHLIGHT_SHADOW}{01}{TRANSPARENT}{DARK_GRAY}"); // Black
u8 *txtPtr;
if (natureMod == 0)
txtPtr = StringCopy(dst, textNatureNone);
else if (natureMod > 0)
txtPtr = StringCopy(dst, textNaturePlus);
else
txtPtr = StringCopy(dst, textNatureMinus);
ConvertIntToDecimalStringN(txtPtr, stat, STR_CONV_MODE_RIGHT_ALIGN, n);
DynamicPlaceholderTextUtil_SetPlaceholderPtr(strId, dst);
}
static void BufferLeftColumnStats(void) static void BufferLeftColumnStats(void)
{ {
u8 *currentHPString = Alloc(20); u8 *currentHPString = Alloc(8);
u8 *maxHPString = Alloc(20); u8 *maxHPString = Alloc(8);
u8 *attackString = Alloc(20); u8 *attackString = Alloc(8);
u8 *defenseString = Alloc(20); u8 *defenseString = Alloc(8);
const s8 *natureMod = gNatureStatTable[sMonSummaryScreen->summary.nature];
ConvertIntToDecimalStringN(currentHPString, sMonSummaryScreen->summary.currentHP, STR_CONV_MODE_RIGHT_ALIGN, 3);
ConvertIntToDecimalStringN(maxHPString, sMonSummaryScreen->summary.maxHP, STR_CONV_MODE_RIGHT_ALIGN, 3);
ConvertIntToDecimalStringN(attackString, sMonSummaryScreen->summary.atk, STR_CONV_MODE_RIGHT_ALIGN, 7);
ConvertIntToDecimalStringN(defenseString, sMonSummaryScreen->summary.def, STR_CONV_MODE_RIGHT_ALIGN, 7);
DynamicPlaceholderTextUtil_Reset(); DynamicPlaceholderTextUtil_Reset();
BufferStat(currentHPString, 0, sMonSummaryScreen->summary.currentHP, 0, 3); DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, currentHPString);
BufferStat(maxHPString, 0, sMonSummaryScreen->summary.maxHP, 1, 3); DynamicPlaceholderTextUtil_SetPlaceholderPtr(1, maxHPString);
BufferStat(attackString, natureMod[STAT_ATK - 1], sMonSummaryScreen->summary.atk, 2, 7); DynamicPlaceholderTextUtil_SetPlaceholderPtr(2, attackString);
BufferStat(defenseString, natureMod[STAT_DEF - 1], sMonSummaryScreen->summary.def, 3, 7); DynamicPlaceholderTextUtil_SetPlaceholderPtr(3, defenseString);
DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, sStatsLeftColumnLayout); DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, sStatsLeftColumnLayout);
Free(currentHPString); Free(currentHPString);
@ -3405,12 +3392,14 @@ static void PrintLeftColumnStats(void)
static void BufferRightColumnStats(void) static void BufferRightColumnStats(void)
{ {
const s8 *natureMod = gNatureStatTable[sMonSummaryScreen->summary.nature]; ConvertIntToDecimalStringN(gStringVar1, sMonSummaryScreen->summary.spatk, STR_CONV_MODE_RIGHT_ALIGN, 3);
ConvertIntToDecimalStringN(gStringVar2, sMonSummaryScreen->summary.spdef, STR_CONV_MODE_RIGHT_ALIGN, 3);
ConvertIntToDecimalStringN(gStringVar3, sMonSummaryScreen->summary.speed, STR_CONV_MODE_RIGHT_ALIGN, 3);
DynamicPlaceholderTextUtil_Reset(); DynamicPlaceholderTextUtil_Reset();
BufferStat(gStringVar1, natureMod[STAT_SPATK - 1], sMonSummaryScreen->summary.spatk, 0, 3); DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gStringVar1);
BufferStat(gStringVar2, natureMod[STAT_SPDEF - 1], sMonSummaryScreen->summary.spdef, 1, 3); DynamicPlaceholderTextUtil_SetPlaceholderPtr(1, gStringVar2);
BufferStat(gStringVar3, natureMod[STAT_SPEED - 1], sMonSummaryScreen->summary.speed, 2, 3); DynamicPlaceholderTextUtil_SetPlaceholderPtr(2, gStringVar3);
DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, sStatsRightColumnLayout); DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, sStatsRightColumnLayout);
} }

View File

@ -1019,7 +1019,8 @@ bool8 ScrCmd_applymovement(struct ScriptContext *ctx)
} }
ScriptMovement_StartObjectMovementScript(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, movementScript); ScriptMovement_StartObjectMovementScript(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, movementScript);
sMovingNpcId = localId; sMovingNpcId = localId;
if (localId != OBJ_EVENT_ID_FOLLOWER && !FlagGet(FLAG_SAFE_FOLLOWER_MOVEMENT)) { // Force follower into pokeball // Force follower into pokeball
if (localId != OBJ_EVENT_ID_FOLLOWER && !FlagGet(FLAG_SAFE_FOLLOWER_MOVEMENT)) {
objEvent = GetFollowerObject(); objEvent = GetFollowerObject();
// return early if no follower or in shadowing state // return early if no follower or in shadowing state
if (objEvent == NULL || gSprites[objEvent->spriteId].data[1] == 0) if (objEvent == NULL || gSprites[objEvent->spriteId].data[1] == 0)

View File

@ -867,7 +867,10 @@ static void BuyMenuCollectObjectEventData(void)
u8 objEventId = GetObjectEventIdByXY(facingX - 4 + x, facingY - 2 + y); u8 objEventId = GetObjectEventIdByXY(facingX - 4 + x, facingY - 2 + y);
// skip if invalid or an overworld pokemon that is not following the player // skip if invalid or an overworld pokemon that is not following the player
if (objEventId != OBJECT_EVENTS_COUNT && !(gObjectEvents[objEventId].active && gObjectEvents[objEventId].graphicsId == OBJ_EVENT_GFX_OW_MON && gObjectEvents[objEventId].localId != OBJ_EVENT_ID_FOLLOWER)) if (objEventId != OBJECT_EVENTS_COUNT
&& !(gObjectEvents[objEventId].active
&& gObjectEvents[objEventId].graphicsId == OBJ_EVENT_GFX_OW_MON
&& gObjectEvents[objEventId].localId != OBJ_EVENT_ID_FOLLOWER))
{ {
sShopData->viewportObjects[numObjects][OBJ_EVENT_ID] = objEventId; sShopData->viewportObjects[numObjects][OBJ_EVENT_ID] = objEventId;
sShopData->viewportObjects[numObjects][X_COORD] = x; sShopData->viewportObjects[numObjects][X_COORD] = x;

View File

@ -152,101 +152,112 @@ static const struct SpriteFrameImage sSpriteImageTable_HeartIcon[] =
static const struct SpriteFrameImage sSpriteImageTable_Emotes[] = static const struct SpriteFrameImage sSpriteImageTable_Emotes[] =
{ {
{ .data = (u8 *)sEmotion_Gfx+0*0x80, .size = 0x80}, // FOLLOWER_EMOTION_HAPPY overworld_frame(sEmotion_Gfx, 2, 2, 0), // FOLLOWER_EMOTION_HAPPY
{ .data = (u8 *)sEmotion_Gfx+1*0x80, .size = 0x80}, // FOLLOWER_EMOTION_HAPPY overworld_frame(sEmotion_Gfx, 2, 2, 1), // FOLLOWER_EMOTION_HAPPY
{ .data = (u8 *)sEmotion_Gfx+2*0x80, .size = 0x80}, // FOLLOWER_EMOTION_NEUTRAL overworld_frame(sEmotion_Gfx, 2, 2, 2), // FOLLOWER_EMOTION_NEUTRAL
{ .data = (u8 *)sEmotion_Gfx+3*0x80, .size = 0x80}, // FOLLOWER_EMOTION_NEUTRAL overworld_frame(sEmotion_Gfx, 2, 2, 3), // FOLLOWER_EMOTION_NEUTRAL
{ .data = (u8 *)sEmotion_Gfx+4*0x80, .size = 0x80}, // FOLLOWER_EMOTION_SAD overworld_frame(sEmotion_Gfx, 2, 2, 4), // FOLLOWER_EMOTION_SAD
{ .data = (u8 *)sEmotion_Gfx+5*0x80, .size = 0x80}, // FOLLOWER_EMOTION_SAD overworld_frame(sEmotion_Gfx, 2, 2, 5), // FOLLOWER_EMOTION_SAD
{ .data = (u8 *)sEmotion_Gfx+6*0x80, .size = 0x80}, // FOLLOWER_EMOTION_UPSET overworld_frame(sEmotion_Gfx, 2, 2, 6), // FOLLOWER_EMOTION_UPSET
{ .data = (u8 *)sEmotion_Gfx+7*0x80, .size = 0x80}, // FOLLOWER_EMOTION_UPSET overworld_frame(sEmotion_Gfx, 2, 2, 7), // FOLLOWER_EMOTION_UPSET
{ .data = (u8 *)sEmotion_Gfx+8*0x80, .size = 0x80}, // FOLLOWER_EMOTION_ANGRY overworld_frame(sEmotion_Gfx, 2, 2, 8), // FOLLOWER_EMOTION_ANGRY
{ .data = (u8 *)sEmotion_Gfx+9*0x80, .size = 0x80}, // FOLLOWER_EMOTION_ANGRY overworld_frame(sEmotion_Gfx, 2, 2, 9), // FOLLOWER_EMOTION_ANGRY
{ .data = (u8 *)sEmotion_Gfx+10*0x80, .size = 0x80}, // FOLLOWER_EMOTION_PENSIVE overworld_frame(sEmotion_Gfx, 2, 2, 10), // FOLLOWER_EMOTION_PENSIVE
{ .data = (u8 *)sEmotion_Gfx+11*0x80, .size = 0x80}, // FOLLOWER_EMOTION_PENSIVE overworld_frame(sEmotion_Gfx, 2, 2, 11), // FOLLOWER_EMOTION_PENSIVE
{ .data = (u8 *)sEmotion_Gfx+12*0x80, .size = 0x80}, // FOLLOWER_EMOTION_LOVE overworld_frame(sEmotion_Gfx, 2, 2, 12), // FOLLOWER_EMOTION_LOVE
{ .data = (u8 *)sEmotion_Gfx+13*0x80, .size = 0x80}, // FOLLOWER_EMOTION_LOVE overworld_frame(sEmotion_Gfx, 2, 2, 13), // FOLLOWER_EMOTION_LOVE
{ .data = (u8 *)sEmotion_Gfx+14*0x80, .size = 0x80}, // FOLLOWER_EMOTION_SURPRISE overworld_frame(sEmotion_Gfx, 2, 2, 14), // FOLLOWER_EMOTION_SURPRISE
{ .data = (u8 *)sEmotion_Gfx+15*0x80, .size = 0x80}, // FOLLOWER_EMOTION_SURPRISE overworld_frame(sEmotion_Gfx, 2, 2, 15), // FOLLOWER_EMOTION_SURPRISE
{ .data = (u8 *)sEmotion_Gfx+16*0x80, .size = 0x80}, // FOLLOWER_EMOTION_CURIOUS overworld_frame(sEmotion_Gfx, 2, 2, 16), // FOLLOWER_EMOTION_CURIOUS
{ .data = (u8 *)sEmotion_Gfx+17*0x80, .size = 0x80}, // FOLLOWER_EMOTION_CURIOUS overworld_frame(sEmotion_Gfx, 2, 2, 17), // FOLLOWER_EMOTION_CURIOUS
{ .data = (u8 *)sEmotion_Gfx+18*0x80, .size = 0x80}, // FOLLOWER_EMOTION_MUSIC overworld_frame(sEmotion_Gfx, 2, 2, 18), // FOLLOWER_EMOTION_MUSIC
{ .data = (u8 *)sEmotion_Gfx+19*0x80, .size = 0x80}, // FOLLOWER_EMOTION_MUSIC overworld_frame(sEmotion_Gfx, 2, 2, 19), // FOLLOWER_EMOTION_MUSIC
{ .data = (u8 *)sEmotion_Gfx+20*0x80, .size = 0x80}, // FOLLOWER_EMOTION_POISONED overworld_frame(sEmotion_Gfx, 2, 2, 20), // FOLLOWER_EMOTION_POISONED
{ .data = (u8 *)sEmotion_Gfx+21*0x80, .size = 0x80}, // FOLLOWER_EMOTION_POISONED overworld_frame(sEmotion_Gfx, 2, 2, 21), // FOLLOWER_EMOTION_POISONED
}; };
static const union AnimCmd sSpriteAnim_Emotes0[] = { static const union AnimCmd sSpriteAnim_Emotes0[] =
{
ANIMCMD_FRAME(0*2, 30), ANIMCMD_FRAME(0*2, 30),
ANIMCMD_FRAME(0*2+1, 25), ANIMCMD_FRAME(0*2+1, 25),
ANIMCMD_FRAME(0*2, 30), ANIMCMD_FRAME(0*2, 30),
ANIMCMD_END ANIMCMD_END
}; };
static const union AnimCmd sSpriteAnim_Emotes1[] = { static const union AnimCmd sSpriteAnim_Emotes1[] =
{
ANIMCMD_FRAME(1*2, 30), ANIMCMD_FRAME(1*2, 30),
ANIMCMD_FRAME(1*2+1, 25), ANIMCMD_FRAME(1*2+1, 25),
ANIMCMD_FRAME(1*2, 30), ANIMCMD_FRAME(1*2, 30),
ANIMCMD_END ANIMCMD_END
}; };
static const union AnimCmd sSpriteAnim_Emotes2[] = { static const union AnimCmd sSpriteAnim_Emotes2[] =
{
ANIMCMD_FRAME(2*2, 30), ANIMCMD_FRAME(2*2, 30),
ANIMCMD_FRAME(2*2+1, 25), ANIMCMD_FRAME(2*2+1, 25),
ANIMCMD_FRAME(2*2, 30), ANIMCMD_FRAME(2*2, 30),
ANIMCMD_END ANIMCMD_END
}; };
static const union AnimCmd sSpriteAnim_Emotes3[] = { static const union AnimCmd sSpriteAnim_Emotes3[] =
{
ANIMCMD_FRAME(3*2, 30), ANIMCMD_FRAME(3*2, 30),
ANIMCMD_FRAME(3*2+1, 25), ANIMCMD_FRAME(3*2+1, 25),
ANIMCMD_FRAME(3*2, 30), ANIMCMD_FRAME(3*2, 30),
ANIMCMD_END ANIMCMD_END
}; };
static const union AnimCmd sSpriteAnim_Emotes4[] = { static const union AnimCmd sSpriteAnim_Emotes4[] =
{
ANIMCMD_FRAME(4*2, 30), ANIMCMD_FRAME(4*2, 30),
ANIMCMD_FRAME(4*2+1, 25), ANIMCMD_FRAME(4*2+1, 25),
ANIMCMD_FRAME(4*2, 30), ANIMCMD_FRAME(4*2, 30),
ANIMCMD_END ANIMCMD_END
}; };
static const union AnimCmd sSpriteAnim_Emotes5[] = { static const union AnimCmd sSpriteAnim_Emotes5[] =
{
ANIMCMD_FRAME(5*2, 30), ANIMCMD_FRAME(5*2, 30),
ANIMCMD_FRAME(5*2+1, 25), ANIMCMD_FRAME(5*2+1, 25),
ANIMCMD_FRAME(5*2, 30), ANIMCMD_FRAME(5*2, 30),
ANIMCMD_END ANIMCMD_END
}; };
static const union AnimCmd sSpriteAnim_Emotes6[] = { static const union AnimCmd sSpriteAnim_Emotes6[] =
{
ANIMCMD_FRAME(6*2, 30), ANIMCMD_FRAME(6*2, 30),
ANIMCMD_FRAME(6*2+1, 25), ANIMCMD_FRAME(6*2+1, 25),
ANIMCMD_FRAME(6*2, 30), ANIMCMD_FRAME(6*2, 30),
ANIMCMD_END ANIMCMD_END
}; };
static const union AnimCmd sSpriteAnim_Emotes7[] = { static const union AnimCmd sSpriteAnim_Emotes7[] =
{
ANIMCMD_FRAME(7*2, 30), ANIMCMD_FRAME(7*2, 30),
ANIMCMD_FRAME(7*2+1, 25), ANIMCMD_FRAME(7*2+1, 25),
ANIMCMD_FRAME(7*2, 30), ANIMCMD_FRAME(7*2, 30),
ANIMCMD_END ANIMCMD_END
}; };
static const union AnimCmd sSpriteAnim_Emotes8[] = { static const union AnimCmd sSpriteAnim_Emotes8[] =
{
ANIMCMD_FRAME(8*2, 30), ANIMCMD_FRAME(8*2, 30),
ANIMCMD_FRAME(8*2+1, 25), ANIMCMD_FRAME(8*2+1, 25),
ANIMCMD_FRAME(8*2, 30), ANIMCMD_FRAME(8*2, 30),
ANIMCMD_END ANIMCMD_END
}; };
static const union AnimCmd sSpriteAnim_Emotes9[] = { static const union AnimCmd sSpriteAnim_Emotes9[] =
{
ANIMCMD_FRAME(9*2, 30), ANIMCMD_FRAME(9*2, 30),
ANIMCMD_FRAME(9*2+1, 25), ANIMCMD_FRAME(9*2+1, 25),
ANIMCMD_FRAME(9*2, 30), ANIMCMD_FRAME(9*2, 30),
ANIMCMD_END ANIMCMD_END
}; };
static const union AnimCmd sSpriteAnim_Emotes10[] = { static const union AnimCmd sSpriteAnim_Emotes10[] =
{
ANIMCMD_FRAME(10*2, 30), ANIMCMD_FRAME(10*2, 30),
ANIMCMD_FRAME(10*2+1, 25), ANIMCMD_FRAME(10*2+1, 25),
ANIMCMD_FRAME(10*2, 30), ANIMCMD_FRAME(10*2, 30),
@ -271,7 +282,8 @@ static const union AnimCmd *const sSpriteAnimTable_Icons[] =
sSpriteAnim_Icons2 sSpriteAnim_Icons2
}; };
static const union AnimCmd *const sSpriteAnimTable_Emotes[] = { static const union AnimCmd *const sSpriteAnimTable_Emotes[] =
{
sSpriteAnim_Emotes0, sSpriteAnim_Emotes0,
sSpriteAnim_Emotes1, sSpriteAnim_Emotes1,
sSpriteAnim_Emotes2, sSpriteAnim_Emotes2,
@ -311,8 +323,9 @@ static const struct SpriteTemplate sSpriteTemplate_HeartIcon =
.callback = SpriteCB_TrainerIcons .callback = SpriteCB_TrainerIcons
}; };
static const struct SpriteTemplate sSpriteTemplate_Emote = { static const struct SpriteTemplate sSpriteTemplate_Emote =
.tileTag = 0xffff, {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_EMOTES, .paletteTag = OBJ_EVENT_PAL_TAG_EMOTES,
.oam = &sOamData_Icons, .oam = &sOamData_Icons,
.anims = sSpriteAnimTable_Emotes, .anims = sSpriteAnimTable_Emotes,
@ -842,7 +855,8 @@ u8 FldEff_ExclamationMarkIcon(void)
u8 FldEff_QuestionMarkIcon(void) u8 FldEff_QuestionMarkIcon(void)
{ {
u8 spriteId; u8 spriteId;
if (gFieldEffectArguments[7] >= 0) { // Use follower emotes if (gFieldEffectArguments[7] >= 0) {
// Use follower emotes
u8 emotion = gFieldEffectArguments[7]; u8 emotion = gFieldEffectArguments[7];
spriteId = CreateSpriteAtEnd(&sSpriteTemplate_Emote, 0, 0, 0x52); spriteId = CreateSpriteAtEnd(&sSpriteTemplate_Emote, 0, 0, 0x52);
if (spriteId == MAX_SPRITES) if (spriteId == MAX_SPRITES)