Added follower transform effect and Castform forms. Credit: larryturbo
Castform forms from https://www.deviantart.com/larryturbo/art/351-Castform-Froms-830190053
This commit is contained in:
parent
ec756d3d12
commit
01f73f54e1
13 changed files with 202 additions and 22 deletions
BIN
graphics/object_events/pics/pokemon/castform_rainy.png
Normal file
BIN
graphics/object_events/pics/pokemon/castform_rainy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.9 KiB |
BIN
graphics/object_events/pics/pokemon/castform_snowy.png
Normal file
BIN
graphics/object_events/pics/pokemon/castform_snowy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.4 KiB |
BIN
graphics/object_events/pics/pokemon/castform_sunny.png
Normal file
BIN
graphics/object_events/pics/pokemon/castform_sunny.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 656 B After Width: | Height: | Size: 11 KiB |
|
@ -6,7 +6,7 @@ JASC-PAL
|
||||||
205 90 74
|
205 90 74
|
||||||
238 123 74
|
238 123 74
|
||||||
255 156 65
|
255 156 65
|
||||||
0 0 0
|
255 197 136
|
||||||
255 246 106
|
255 246 106
|
||||||
230 213 106
|
230 213 106
|
||||||
255 156 98
|
255 156 98
|
||||||
|
|
|
@ -26,6 +26,13 @@ enum ReflectionTypes
|
||||||
NUM_REFLECTION_TYPES
|
NUM_REFLECTION_TYPES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum FollowerTransformTypes
|
||||||
|
{
|
||||||
|
TRANSFORM_TYPE_NONE,
|
||||||
|
TRANSFORM_TYPE_PERMANENT,
|
||||||
|
TRANSFORM_TYPE_RANDOM_WILD,
|
||||||
|
};
|
||||||
|
|
||||||
#define FIGURE_8_LENGTH 72
|
#define FIGURE_8_LENGTH 72
|
||||||
|
|
||||||
#define GROUND_EFFECT_FLAG_TALL_GRASS_ON_SPAWN (1 << 0)
|
#define GROUND_EFFECT_FLAG_TALL_GRASS_ON_SPAWN (1 << 0)
|
||||||
|
|
|
@ -1820,6 +1820,15 @@ $(OBJEVENTGFXDIR)/pokemon/milotic.4bpp: %.4bpp: %.png
|
||||||
$(OBJEVENTGFXDIR)/pokemon/castform.4bpp: %.4bpp: %.png
|
$(OBJEVENTGFXDIR)/pokemon/castform.4bpp: %.4bpp: %.png
|
||||||
$(GFX) $< $@ -mwidth 4 -mheight 4
|
$(GFX) $< $@ -mwidth 4 -mheight 4
|
||||||
|
|
||||||
|
$(OBJEVENTGFXDIR)/pokemon/castform_sunny.4bpp: %.4bpp: %.png
|
||||||
|
$(GFX) $< $@ -mwidth 4 -mheight 4
|
||||||
|
|
||||||
|
$(OBJEVENTGFXDIR)/pokemon/castform_rainy.4bpp: %.4bpp: %.png
|
||||||
|
$(GFX) $< $@ -mwidth 4 -mheight 4
|
||||||
|
|
||||||
|
$(OBJEVENTGFXDIR)/pokemon/castform_snowy.4bpp: %.4bpp: %.png
|
||||||
|
$(GFX) $< $@ -mwidth 4 -mheight 4
|
||||||
|
|
||||||
$(OBJEVENTGFXDIR)/pokemon/kecleon.4bpp: %.4bpp: %.png
|
$(OBJEVENTGFXDIR)/pokemon/kecleon.4bpp: %.4bpp: %.png
|
||||||
$(GFX) $< $@ -mwidth 4 -mheight 4
|
$(GFX) $< $@ -mwidth 4 -mheight 4
|
||||||
|
|
||||||
|
|
|
@ -721,6 +721,12 @@ const u32 gObjectEventPic_Armaldo[] = INCBIN_U32("graphics/object_events/pics/po
|
||||||
const u32 gObjectEventPic_Feebas[] = INCBIN_U32("graphics/object_events/pics/pokemon/feebas.4bpp");
|
const u32 gObjectEventPic_Feebas[] = INCBIN_U32("graphics/object_events/pics/pokemon/feebas.4bpp");
|
||||||
const u32 gObjectEventPic_Milotic[] = INCBIN_U32("graphics/object_events/pics/pokemon/milotic.4bpp");
|
const u32 gObjectEventPic_Milotic[] = INCBIN_U32("graphics/object_events/pics/pokemon/milotic.4bpp");
|
||||||
const u32 gObjectEventPic_Castform[] = INCBIN_U32("graphics/object_events/pics/pokemon/castform.4bpp");
|
const u32 gObjectEventPic_Castform[] = INCBIN_U32("graphics/object_events/pics/pokemon/castform.4bpp");
|
||||||
|
const u32 gObjectEventPic_CastformSunny[] = INCBIN_U32("graphics/object_events/pics/pokemon/castform_sunny.4bpp");
|
||||||
|
const u16 gObjectEventPal_CastformSunny[] = INCBIN_U16("graphics/pokemon/castform/normal_sunny_form.gbapal");
|
||||||
|
const u32 gObjectEventPic_CastformRainy[] = INCBIN_U32("graphics/object_events/pics/pokemon/castform_rainy.4bpp");
|
||||||
|
const u16 gObjectEventPal_CastformRainy[] = INCBIN_U16("graphics/pokemon/castform/normal_rainy_form.gbapal");
|
||||||
|
const u32 gObjectEventPic_CastformSnowy[] = INCBIN_U32("graphics/object_events/pics/pokemon/castform_snowy.4bpp");
|
||||||
|
const u16 gObjectEventPal_CastformSnowy[] = INCBIN_U16("graphics/pokemon/castform/normal_snowy_form.gbapal");
|
||||||
const u32 gObjectEventPic_Kecleon[] = INCBIN_U32("graphics/object_events/pics/pokemon/kecleon.4bpp");
|
const u32 gObjectEventPic_Kecleon[] = INCBIN_U32("graphics/object_events/pics/pokemon/kecleon.4bpp");
|
||||||
const u32 gObjectEventPic_Shuppet[] = INCBIN_U32("graphics/object_events/pics/pokemon/shuppet.4bpp");
|
const u32 gObjectEventPic_Shuppet[] = INCBIN_U32("graphics/object_events/pics/pokemon/shuppet.4bpp");
|
||||||
const u32 gObjectEventPic_Banette[] = INCBIN_U32("graphics/object_events/pics/pokemon/banette.4bpp");
|
const u32 gObjectEventPic_Banette[] = INCBIN_U32("graphics/object_events/pics/pokemon/banette.4bpp");
|
||||||
|
|
|
@ -414,3 +414,11 @@ const struct ObjectEventGraphicsInfo gPokemonObjectGraphics[] = {
|
||||||
[SPECIES_JIRACHI] = {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_Jirachi, gDummySpriteAffineAnimTable},
|
[SPECIES_JIRACHI] = {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_Jirachi, gDummySpriteAffineAnimTable},
|
||||||
[SPECIES_DEOXYS] = {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_Deoxys, gDummySpriteAffineAnimTable},
|
[SPECIES_DEOXYS] = {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_Deoxys, gDummySpriteAffineAnimTable},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Normal, sunny, rainy, snowy
|
||||||
|
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},
|
||||||
|
{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},
|
||||||
|
{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},
|
||||||
|
};
|
||||||
|
|
|
@ -5014,6 +5014,30 @@ static const struct SpriteFrameImage sPicTable_Castform[] = {
|
||||||
overworld_frame(gObjectEventPic_Castform, 4, 4, 4),
|
overworld_frame(gObjectEventPic_Castform, 4, 4, 4),
|
||||||
overworld_frame(gObjectEventPic_Castform, 4, 4, 5),
|
overworld_frame(gObjectEventPic_Castform, 4, 4, 5),
|
||||||
};
|
};
|
||||||
|
static const struct SpriteFrameImage sPicTable_CastformSunny[] = {
|
||||||
|
overworld_frame(gObjectEventPic_CastformSunny, 4, 4, 0),
|
||||||
|
overworld_frame(gObjectEventPic_CastformSunny, 4, 4, 1),
|
||||||
|
overworld_frame(gObjectEventPic_CastformSunny, 4, 4, 2),
|
||||||
|
overworld_frame(gObjectEventPic_CastformSunny, 4, 4, 3),
|
||||||
|
overworld_frame(gObjectEventPic_CastformSunny, 4, 4, 4),
|
||||||
|
overworld_frame(gObjectEventPic_CastformSunny, 4, 4, 5),
|
||||||
|
};
|
||||||
|
static const struct SpriteFrameImage sPicTable_CastformRainy[] = {
|
||||||
|
overworld_frame(gObjectEventPic_CastformRainy, 4, 4, 0),
|
||||||
|
overworld_frame(gObjectEventPic_CastformRainy, 4, 4, 1),
|
||||||
|
overworld_frame(gObjectEventPic_CastformRainy, 4, 4, 2),
|
||||||
|
overworld_frame(gObjectEventPic_CastformRainy, 4, 4, 3),
|
||||||
|
overworld_frame(gObjectEventPic_CastformRainy, 4, 4, 4),
|
||||||
|
overworld_frame(gObjectEventPic_CastformRainy, 4, 4, 5),
|
||||||
|
};
|
||||||
|
static const struct SpriteFrameImage sPicTable_CastformSnowy[] = {
|
||||||
|
overworld_frame(gObjectEventPic_CastformSnowy, 4, 4, 0),
|
||||||
|
overworld_frame(gObjectEventPic_CastformSnowy, 4, 4, 1),
|
||||||
|
overworld_frame(gObjectEventPic_CastformSnowy, 4, 4, 2),
|
||||||
|
overworld_frame(gObjectEventPic_CastformSnowy, 4, 4, 3),
|
||||||
|
overworld_frame(gObjectEventPic_CastformSnowy, 4, 4, 4),
|
||||||
|
overworld_frame(gObjectEventPic_CastformSnowy, 4, 4, 5),
|
||||||
|
};
|
||||||
static const struct SpriteFrameImage sPicTable_Kecleon[] = {
|
static const struct SpriteFrameImage sPicTable_Kecleon[] = {
|
||||||
overworld_frame(gObjectEventPic_Kecleon, 4, 4, 0),
|
overworld_frame(gObjectEventPic_Kecleon, 4, 4, 0),
|
||||||
overworld_frame(gObjectEventPic_Kecleon, 4, 4, 1),
|
overworld_frame(gObjectEventPic_Kecleon, 4, 4, 1),
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "field_weather.h"
|
#include "field_weather.h"
|
||||||
#include "fieldmap.h"
|
#include "fieldmap.h"
|
||||||
#include "follower_helper.h"
|
#include "follower_helper.h"
|
||||||
|
#include "gpu_regs.h"
|
||||||
#include "mauville_old_man.h"
|
#include "mauville_old_man.h"
|
||||||
#include "metatile_behavior.h"
|
#include "metatile_behavior.h"
|
||||||
#include "overworld.h"
|
#include "overworld.h"
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
#include "trainer_see.h"
|
#include "trainer_see.h"
|
||||||
#include "trainer_hill.h"
|
#include "trainer_hill.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "wild_encounter.h"
|
||||||
#include "constants/event_object_movement.h"
|
#include "constants/event_object_movement.h"
|
||||||
#include "constants/abilities.h"
|
#include "constants/abilities.h"
|
||||||
#include "constants/battle.h"
|
#include "constants/battle.h"
|
||||||
|
@ -157,6 +159,7 @@ static struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8, u8,
|
||||||
static void RemoveObjectEventIfOutsideView(struct ObjectEvent *);
|
static void RemoveObjectEventIfOutsideView(struct ObjectEvent *);
|
||||||
static void SpawnObjectEventOnReturnToField(u8, s16, s16);
|
static void SpawnObjectEventOnReturnToField(u8, s16, s16);
|
||||||
static void SetPlayerAvatarObjectEventIdAndObjectId(u8, u8);
|
static void SetPlayerAvatarObjectEventIdAndObjectId(u8, u8);
|
||||||
|
static u8 UpdateSpritePalette(const struct SpritePalette * spritePalette, struct Sprite * sprite);
|
||||||
static void ResetObjectEventFldEffData(struct ObjectEvent *);
|
static void ResetObjectEventFldEffData(struct ObjectEvent *);
|
||||||
static u8 LoadSpritePaletteIfTagExists(const struct SpritePalette *);
|
static u8 LoadSpritePaletteIfTagExists(const struct SpritePalette *);
|
||||||
static u8 FindObjectEventPaletteIndexByTag(u16);
|
static u8 FindObjectEventPaletteIndexByTag(u16);
|
||||||
|
@ -462,6 +465,9 @@ const u8 gInitialMovementTypeFacingDirections[] = {
|
||||||
#define OBJ_EVENT_PAL_TAG_RS_BRENDAN 0x1122
|
#define OBJ_EVENT_PAL_TAG_RS_BRENDAN 0x1122
|
||||||
#define OBJ_EVENT_PAL_TAG_RS_MAY 0x1123
|
#define OBJ_EVENT_PAL_TAG_RS_MAY 0x1123
|
||||||
#define OBJ_EVENT_PAL_TAG_DYNAMIC 0x1124
|
#define OBJ_EVENT_PAL_TAG_DYNAMIC 0x1124
|
||||||
|
#define OBJ_EVENT_PAL_TAG_CASTFORM_SUNNY 0x1125
|
||||||
|
#define OBJ_EVENT_PAL_TAG_CASTFORM_RAINY 0x1126
|
||||||
|
#define OBJ_EVENT_PAL_TAG_CASTFORM_SNOWY 0x1127
|
||||||
#define OBJ_EVENT_PAL_TAG_EMOTES 0x8002
|
#define OBJ_EVENT_PAL_TAG_EMOTES 0x8002
|
||||||
#define OBJ_EVENT_PAL_TAG_NONE 0x11FF
|
#define OBJ_EVENT_PAL_TAG_NONE 0x11FF
|
||||||
|
|
||||||
|
@ -510,7 +516,9 @@ static const struct SpritePalette sObjectEventSpritePalettes[] = {
|
||||||
{gObjectEventPal_Lugia, OBJ_EVENT_PAL_TAG_LUGIA},
|
{gObjectEventPal_Lugia, OBJ_EVENT_PAL_TAG_LUGIA},
|
||||||
{gObjectEventPal_RubySapphireBrendan, OBJ_EVENT_PAL_TAG_RS_BRENDAN},
|
{gObjectEventPal_RubySapphireBrendan, OBJ_EVENT_PAL_TAG_RS_BRENDAN},
|
||||||
{gObjectEventPal_RubySapphireMay, OBJ_EVENT_PAL_TAG_RS_MAY},
|
{gObjectEventPal_RubySapphireMay, OBJ_EVENT_PAL_TAG_RS_MAY},
|
||||||
{gObjectEventPal_Npc1, OBJ_EVENT_PAL_TAG_DYNAMIC},
|
{gObjectEventPal_CastformSunny, OBJ_EVENT_PAL_TAG_CASTFORM_SUNNY},
|
||||||
|
{gObjectEventPal_CastformRainy, OBJ_EVENT_PAL_TAG_CASTFORM_RAINY},
|
||||||
|
{gObjectEventPal_CastformSnowy, OBJ_EVENT_PAL_TAG_CASTFORM_SNOWY},
|
||||||
{gObjectEventPaletteEmotes, OBJ_EVENT_PAL_TAG_EMOTES},
|
{gObjectEventPaletteEmotes, OBJ_EVENT_PAL_TAG_EMOTES},
|
||||||
{NULL, OBJ_EVENT_PAL_TAG_NONE},
|
{NULL, OBJ_EVENT_PAL_TAG_NONE},
|
||||||
};
|
};
|
||||||
|
@ -1701,6 +1709,9 @@ static const struct ObjectEventGraphicsInfo * SpeciesToGraphicsInfo(u16 species,
|
||||||
form %= NUM_UNOWN_FORMS;
|
form %= NUM_UNOWN_FORMS;
|
||||||
graphicsInfo = &gPokemonObjectGraphics[form ? SPECIES_UNOWN_B + form - 1 : species];
|
graphicsInfo = &gPokemonObjectGraphics[form ? SPECIES_UNOWN_B + form - 1 : species];
|
||||||
break;
|
break;
|
||||||
|
case SPECIES_CASTFORM: // Sunny, rainy, snowy forms stored separately
|
||||||
|
graphicsInfo = &gCastformObjectGraphics[form % NUM_CASTFORM_FORMS];
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
graphicsInfo = &gPokemonObjectGraphics[species];
|
graphicsInfo = &gPokemonObjectGraphics[species];
|
||||||
break;
|
break;
|
||||||
|
@ -1739,7 +1750,56 @@ static void FollowerSetGraphics(struct ObjectEvent *objEvent, u16 species, u8 fo
|
||||||
FieldEffectFreePaletteIfUnused(sprite->oam.paletteNum);
|
FieldEffectFreePaletteIfUnused(sprite->oam.paletteNum);
|
||||||
sprite->inUse = TRUE;
|
sprite->inUse = TRUE;
|
||||||
sprite->oam.paletteNum = LoadDynamicFollowerPalette(species, form, shiny);
|
sprite->oam.paletteNum = LoadDynamicFollowerPalette(species, form, shiny);
|
||||||
|
} else if (gWeatherPtr->currWeather != WEATHER_FOG_HORIZONTAL) // don't want to weather blend in fog
|
||||||
|
UpdateSpritePaletteWithWeather(gSprites[objEvent->spriteId].oam.paletteNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Like FollowerSetGraphics, but does not reposition sprite; intended to be used for mid-movement form changes, etc.
|
||||||
|
// TODO: Reposition sprite if size changes
|
||||||
|
static void RefreshFollowerGraphics(struct ObjectEvent *objEvent) {
|
||||||
|
u16 species = objEvent->extra.mon.species;
|
||||||
|
u8 form = objEvent->extra.mon.form;
|
||||||
|
u8 shiny = objEvent->extra.mon.shiny;
|
||||||
|
const struct ObjectEventGraphicsInfo *graphicsInfo = SpeciesToGraphicsInfo(species, form);
|
||||||
|
struct Sprite *sprite = &gSprites[objEvent->spriteId];
|
||||||
|
u8 i = FindObjectEventPaletteIndexByTag(graphicsInfo->paletteTag);
|
||||||
|
|
||||||
|
sprite->oam.shape = graphicsInfo->oam->shape;
|
||||||
|
sprite->oam.size = graphicsInfo->oam->size;
|
||||||
|
sprite->images = graphicsInfo->images;
|
||||||
|
sprite->anims = graphicsInfo->anims;
|
||||||
|
sprite->subspriteTables = graphicsInfo->subspriteTables;
|
||||||
|
objEvent->inanimate = graphicsInfo->inanimate;
|
||||||
|
sprite->centerToCornerVecX = -(graphicsInfo->width >> 1);
|
||||||
|
sprite->centerToCornerVecY = -(graphicsInfo->height >> 1);
|
||||||
|
|
||||||
|
if (graphicsInfo->paletteTag == OBJ_EVENT_PAL_TAG_DYNAMIC) {
|
||||||
|
sprite->inUse = FALSE;
|
||||||
|
FieldEffectFreePaletteIfUnused(sprite->oam.paletteNum);
|
||||||
|
sprite->inUse = TRUE;
|
||||||
|
sprite->oam.paletteNum = LoadDynamicFollowerPalette(species, form, shiny);
|
||||||
|
} else if (i != 0xFF) {
|
||||||
|
UpdateSpritePalette(&sObjectEventSpritePalettes[i], sprite);
|
||||||
|
if (gWeatherPtr->currWeather != WEATHER_FOG_HORIZONTAL) // don't want to weather blend in fog
|
||||||
|
UpdateSpritePaletteWithWeather(sprite->oam.paletteNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Like CastformDataTypeChange, but for overworld weather
|
||||||
|
static u8 GetOverworldCastformForm(void) {
|
||||||
|
switch (GetCurrentWeather())
|
||||||
|
{
|
||||||
|
case WEATHER_SUNNY_CLOUDS:
|
||||||
|
case WEATHER_DROUGHT:
|
||||||
|
return CASTFORM_FIRE;
|
||||||
|
case WEATHER_RAIN:
|
||||||
|
case WEATHER_RAIN_THUNDERSTORM:
|
||||||
|
case WEATHER_DOWNPOUR:
|
||||||
|
return CASTFORM_WATER;
|
||||||
|
case WEATHER_SNOW:
|
||||||
|
return CASTFORM_ICE;
|
||||||
|
}
|
||||||
|
return CASTFORM_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve graphic information about the following pokemon, if any
|
// Retrieve graphic information about the following pokemon, if any
|
||||||
|
@ -1753,7 +1813,16 @@ static bool8 GetFollowerInfo(u16 *species, u8 *form, u8 *shiny) {
|
||||||
}
|
}
|
||||||
*species = GetMonData(mon, MON_DATA_SPECIES);
|
*species = GetMonData(mon, MON_DATA_SPECIES);
|
||||||
*shiny = IsMonShiny(mon);
|
*shiny = IsMonShiny(mon);
|
||||||
*form = *species == SPECIES_UNOWN ? GET_UNOWN_LETTER(mon->box.personality) : 0;
|
*form = 0; // default
|
||||||
|
switch (*species)
|
||||||
|
{
|
||||||
|
case SPECIES_UNOWN:
|
||||||
|
*form = GET_UNOWN_LETTER(mon->box.personality);
|
||||||
|
break;
|
||||||
|
case SPECIES_CASTFORM: // form is based on overworld weather
|
||||||
|
*form = GetOverworldCastformForm();
|
||||||
|
break;
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1764,7 +1833,7 @@ void UpdateFollowingPokemon(void) { // Update following pokemon if any
|
||||||
bool8 shiny;
|
bool8 shiny;
|
||||||
u8 form;
|
u8 form;
|
||||||
// Avoid spawning large (64x64) follower pokemon inside buildings
|
// Avoid spawning large (64x64) follower pokemon inside buildings
|
||||||
if (GetFollowerInfo(&species, &form, &shiny) && !(gMapHeader.mapType == MAP_TYPE_INDOOR && SpeciesToGraphicsInfo(species, 0)->width == 64)) {
|
if (GetFollowerInfo(&species, &form, &shiny) && !(gMapHeader.mapType == MAP_TYPE_INDOOR && SpeciesToGraphicsInfo(species, 0)->height == 64)) {
|
||||||
if (objEvent == NULL) { // Spawn follower
|
if (objEvent == NULL) { // Spawn follower
|
||||||
struct ObjectEventTemplate template = {
|
struct ObjectEventTemplate template = {
|
||||||
.localId = OBJ_EVENT_ID_FOLLOWER,
|
.localId = OBJ_EVENT_ID_FOLLOWER,
|
||||||
|
@ -2242,13 +2311,7 @@ static u8 UpdateSpritePalette(const struct SpritePalette * spritePalette, struct
|
||||||
sprite->inUse = FALSE;
|
sprite->inUse = FALSE;
|
||||||
FieldEffectFreePaletteIfUnused(sprite->oam.paletteNum);
|
FieldEffectFreePaletteIfUnused(sprite->oam.paletteNum);
|
||||||
sprite->inUse = TRUE;
|
sprite->inUse = TRUE;
|
||||||
if (IndexOfSpritePaletteTag(spritePalette->tag) == 0xFF) {
|
return sprite->oam.paletteNum = LoadSpritePalette(spritePalette);
|
||||||
sprite->oam.paletteNum = LoadSpritePalette(spritePalette);
|
|
||||||
} else {
|
|
||||||
sprite->oam.paletteNum = LoadSpritePalette(spritePalette);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sprite->oam.paletteNum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find and update based on template's paletteTag
|
// Find and update based on template's paletteTag
|
||||||
|
@ -4803,6 +4866,73 @@ bool8 CopyablePlayerMovement_Jump2(struct ObjectEvent *objectEvent, struct Sprit
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool8 EndFollowerTransformEffect(struct ObjectEvent *objectEvent, struct Sprite *sprite) {
|
||||||
|
if (!sprite)
|
||||||
|
return FALSE;
|
||||||
|
SetGpuReg(REG_OFFSET_MOSAIC, 0);
|
||||||
|
if (!sprite->data[7])
|
||||||
|
return FALSE;
|
||||||
|
sprite->oam.mosaic = FALSE;
|
||||||
|
sprite->data[7] = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool8 TryStartFollowerTransformEffect(struct ObjectEvent *objectEvent, struct Sprite *sprite) {
|
||||||
|
u32 multi;
|
||||||
|
if (objectEvent->extra.mon.species == SPECIES_CASTFORM && objectEvent->extra.mon.form != (multi = GetOverworldCastformForm())) {
|
||||||
|
sprite->data[7] = TRANSFORM_TYPE_PERMANENT << 8;
|
||||||
|
objectEvent->extra.mon.form = multi;
|
||||||
|
return TRUE;
|
||||||
|
} else if ((gRngValue >> 16) < 18 && GetLocalWildMon(FALSE)
|
||||||
|
&& (objectEvent->extra.mon.species == SPECIES_MEW || objectEvent->extra.mon.species == SPECIES_DITTO)) {
|
||||||
|
sprite->data[7] = TRANSFORM_TYPE_RANDOM_WILD << 8;
|
||||||
|
PlaySE(SE_M_MINIMIZE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool8 UpdateFollowerTransformEffect(struct ObjectEvent *objectEvent, struct Sprite *sprite) {
|
||||||
|
u8 type = sprite->data[7] >> 8;
|
||||||
|
u8 frames = sprite->data[7] & 0xFF;
|
||||||
|
u8 stretch;
|
||||||
|
u32 multi;
|
||||||
|
if (!type)
|
||||||
|
return TryStartFollowerTransformEffect(objectEvent, sprite);
|
||||||
|
sprite->oam.mosaic = TRUE;
|
||||||
|
if (frames < 8)
|
||||||
|
stretch = frames >> 1;
|
||||||
|
else if (frames < 16)
|
||||||
|
stretch = (16 - frames) >> 1;
|
||||||
|
else {
|
||||||
|
return EndFollowerTransformEffect(objectEvent, sprite);
|
||||||
|
}
|
||||||
|
if (frames == 8) {
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case TRANSFORM_TYPE_PERMANENT:
|
||||||
|
RefreshFollowerGraphics(objectEvent);
|
||||||
|
break;
|
||||||
|
case TRANSFORM_TYPE_RANDOM_WILD:
|
||||||
|
multi = objectEvent->extra.asU16;
|
||||||
|
objectEvent->extra.mon.species = GetLocalWildMon(FALSE);
|
||||||
|
if (!objectEvent->extra.mon.species) {
|
||||||
|
objectEvent->extra.asU16 = multi;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
objectEvent->extra.mon.form = 0;
|
||||||
|
RefreshFollowerGraphics(objectEvent);
|
||||||
|
objectEvent->extra.asU16 = multi;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetGpuReg(REG_OFFSET_MOSAIC, (stretch << 12) | (stretch << 8));
|
||||||
|
frames++;
|
||||||
|
sprite->data[7] = (sprite->data[7] & 0xFF00) | frames;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
movement_type_def(MovementType_FollowPlayer, gMovementTypeFuncs_FollowPlayer)
|
movement_type_def(MovementType_FollowPlayer, gMovementTypeFuncs_FollowPlayer)
|
||||||
|
|
||||||
bool8 MovementType_FollowPlayer_Shadow(struct ObjectEvent *objectEvent, struct Sprite *sprite)
|
bool8 MovementType_FollowPlayer_Shadow(struct ObjectEvent *objectEvent, struct Sprite *sprite)
|
||||||
|
@ -4859,6 +4989,8 @@ bool8 MovementType_FollowPlayer_Moving(struct ObjectEvent *objectEvent, struct S
|
||||||
if (sprite->data[1]) { // restore nonzero state
|
if (sprite->data[1]) { // restore nonzero state
|
||||||
sprite->data[1] = 1;
|
sprite->data[1] = 1;
|
||||||
}
|
}
|
||||||
|
} else if (objectEvent->movementActionId != MOVEMENT_ACTION_EXIT_POKEBALL) {
|
||||||
|
UpdateFollowerTransformEffect(objectEvent, sprite);
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -4874,6 +5006,7 @@ bool8 FollowablePlayerMovement_Idle(struct ObjectEvent *objectEvent, struct Spri
|
||||||
} else if (ObjectEventExecSingleMovementAction(objectEvent, sprite)) { // finish movement action
|
} else if (ObjectEventExecSingleMovementAction(objectEvent, sprite)) { // finish movement action
|
||||||
objectEvent->singleMovementActive = 0;
|
objectEvent->singleMovementActive = 0;
|
||||||
}
|
}
|
||||||
|
UpdateFollowerTransformEffect(objectEvent, sprite);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6542,6 +6675,7 @@ bool8 MovementAction_EnterPokeball_Step0(struct ObjectEvent *objectEvent, struct
|
||||||
u8 direction = objectEvent->facingDirection;
|
u8 direction = objectEvent->facingDirection;
|
||||||
InitMoveInPlace(objectEvent, sprite, direction, GetMoveDirectionFasterAnimNum(direction), 16);
|
InitMoveInPlace(objectEvent, sprite, direction, GetMoveDirectionFasterAnimNum(direction), 16);
|
||||||
sprite->data[6] = direction == DIR_EAST ? 3 : 2; // affine animation number
|
sprite->data[6] = direction == DIR_EAST ? 3 : 2; // affine animation number
|
||||||
|
EndFollowerTransformEffect(objectEvent, sprite);
|
||||||
return MovementAction_EnterPokeball_Step1(objectEvent, sprite);
|
return MovementAction_EnterPokeball_Step1(objectEvent, sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2998,12 +2998,8 @@ static void SurfFieldEffect_Init(struct Task *task)
|
||||||
FreezeObjectEvents();
|
FreezeObjectEvents();
|
||||||
// Put follower into pokeball before using Surf
|
// Put follower into pokeball before using Surf
|
||||||
if (followerObject && !followerObject->invisible) {
|
if (followerObject && !followerObject->invisible) {
|
||||||
// TODO: ClearObjectEventMovement (
|
ClearObjectEventMovement(followerObject, &gSprites[followerObject->spriteId]);
|
||||||
followerObject->singleMovementActive = 0;
|
|
||||||
ObjectEventClearHeldMovement(followerObject);
|
|
||||||
gSprites[followerObject->spriteId].data[1] = 0;
|
|
||||||
gSprites[followerObject->spriteId].animCmdIndex = 0; // Needed because of weird animCmdIndex stuff
|
gSprites[followerObject->spriteId].animCmdIndex = 0; // Needed because of weird animCmdIndex stuff
|
||||||
// )
|
|
||||||
ObjectEventSetHeldMovement(followerObject, MOVEMENT_ACTION_ENTER_POKEBALL);
|
ObjectEventSetHeldMovement(followerObject, MOVEMENT_ACTION_ENTER_POKEBALL);
|
||||||
}
|
}
|
||||||
gPlayerAvatar.preventStep = TRUE;
|
gPlayerAvatar.preventStep = TRUE;
|
||||||
|
|
|
@ -688,12 +688,8 @@ static void Task_DoDoorWarp(u8 taskId)
|
||||||
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
|
||||||
// TODO: ClearObjectEventMovement (
|
ClearObjectEventMovement(followerObject, &gSprites[followerObject->spriteId]);
|
||||||
followerObject->singleMovementActive = 0;
|
|
||||||
ObjectEventClearHeldMovement(followerObject);
|
|
||||||
gSprites[followerObject->spriteId].data[1] = 0;
|
|
||||||
gSprites[followerObject->spriteId].animCmdIndex = 0; // Needed because of weird animCmdIndex stuff
|
gSprites[followerObject->spriteId].animCmdIndex = 0; // Needed because of weird animCmdIndex stuff
|
||||||
// )
|
|
||||||
ObjectEventSetHeldMovement(followerObject, MOVEMENT_ACTION_ENTER_POKEBALL);
|
ObjectEventSetHeldMovement(followerObject, MOVEMENT_ACTION_ENTER_POKEBALL);
|
||||||
}
|
}
|
||||||
task->data[1] = FieldAnimateDoorOpen(*x, *y - 1);
|
task->data[1] = FieldAnimateDoorOpen(*x, *y - 1);
|
||||||
|
|
Loading…
Reference in a new issue