Dynamic overworld palette system - pret/pokeemerald GitHub Wiki
TODO: Update this tutorial properly, explaining the changes that are made and the reasoning behind. NOTE This tutorial is a work in progress. Will add everything eventually, but currently I (smithk200) am adding this bit by bit. This is a long thing to write!
Goal: To replace the static overworld palettes with a dynamic system that loads the correct palette slot when you are playing the game, versus the palette slots being hardcoded when the game begins.
The most up to date code at time of writing can be found here. This also fixes some of the problems with the below system, like broken reflections and berry trees.
If you don't want to pull from a repository, you can look at this link here, and make the changes accordingly: https://github.com/pret/pokeemerald/compare/master...ExpoSeed:pokeemerald:dynamic-ow-pals
1. include/event_object_movement.h
First, remove this line:
- extern const u8 gReflectionEffectPaletteMap[];
Then, change these two lines
extern const u8 *const gBerryTreeObjectEventGraphicsIdTablePointers[];
extern const u8 *const gBerryTreePaletteSlotTablePointers[];
to this.
extern const u16 *const gBerryTreeObjectEventGraphicsIdTablePointers[];
extern const u16 *const gBerryTreePaletteSlotTablePointers[];
Finally, after these lines,
s16 GetFigure8XOffset(s16 idx);
s16 GetFigure8YOffset(s16 idx);
void CameraObjectReset2(void);
add this one.
void LoadObjectEventPalette(u16 paletteTag);
2. include/field_effect_helpers.h
After this line
void ShowWarpArrowSprite(u8 spriteId, u8 direction, s16 x, s16 y);
add this:
void LoadFieldEffectPalette(u8 fieldEffect);
3. include/field_weather.h
After this line
extern const u16 gFogPalette[];
add this:
enum
{
GAMMA_NONE,
GAMMA_NORMAL,
GAMMA_ALT,
};
void UpdatePaletteGammaType(u8 index, u8 gammaType);
Next, find this line:
void LoadCustomWeatherSpritePalette(const u16 *palette);
And change it to this:
void LoadCustomWeatherSpritePalette(const struct SpritePalette *palette);
4. src/event_object_movement.c
Add #include "field_weather.h"
after this line: #include "field_effect_helpers.h"
Add #include "data/object_events/object_event_graphics_info_pointers.h"
after #include "data/object_events/object_event_graphics_info.h"
Delete all the ReflectionPaletteTags from sReflectionPaletteTags_Brendan
to sObjectPaletteTagSets
.
Replace this function
static void RemoveObjectEventInternal(struct ObjectEvent *objectEvent)
{
struct SpriteFrameImage image;
image.size = GetObjectEventGraphicsInfo(objectEvent->graphicsId)->size;
gSprites[objectEvent->spriteId].images = ℑ
DestroySprite(&gSprites[objectEvent->spriteId]);
}
with this one.
static void RemoveObjectEventInternal(struct ObjectEvent *objectEvent)
{
u8 paletteNum;
struct SpriteFrameImage image;
image.size = GetObjectEventGraphicsInfo(objectEvent->graphicsId)->size;
gSprites[objectEvent->spriteId].images = ℑ
paletteNum = gSprites[objectEvent->spriteId].oam.paletteNum;
DestroySprite(&gSprites[objectEvent->spriteId]);
FieldEffectFreePaletteIfUnused(paletteNum);
}
Replace this
paletteSlot = graphicsInfo->paletteSlot;
if (paletteSlot == 0)
{
LoadPlayerObjectReflectionPalette(graphicsInfo->paletteTag, 0);
}
else if (paletteSlot == 10)
{
LoadSpecialObjectReflectionPalette(graphicsInfo->paletteTag, 10);
}
else if (paletteSlot >= 16)
{
paletteSlot -= 16;
_PatchObjectPalette(graphicsInfo->paletteTag, paletteSlot);
}
if (objectEvent->movementType == MOVEMENT_TYPE_INVISIBLE)
objectEvent->invisible = TRUE;
*(u16 *)&spriteTemplate->paletteTag = 0xFFFF;
with this.
if (spriteTemplate->paletteTag != 0xFFFF)
{
LoadObjectEventPalette(spriteTemplate->paletteTag);
UpdatePaletteGammaType(IndexOfSpritePaletteTag(spriteTemplate->paletteTag), GAMMA_ALT);
}
Next, find this line and remove it:
*(u16 *)&spriteTemplate->paletteTag = 0xFFFF;
Next, find this line:
if (graphicsInfo->paletteSlot == 10)
{
LoadSpecialObjectReflectionPalette(graphicsInfo->paletteTag, graphicsInfo->paletteSlot);
}
else if (graphicsInfo->paletteSlot >= 16)
and replace it with this:
if (graphicsInfo->paletteSlot >= 16)
Next, navigate to this line:
objectEvent->movementType, &spriteTemplate, &subspriteTables);
spriteTemplate.images = &spriteFrameImage;
Remove this:
*(u16 *)&spriteTemplate.paletteTag = 0xFFFF;
paletteSlot = graphicsInfo->paletteSlot;
if (paletteSlot == 0)
{
LoadPlayerObjectReflectionPalette(graphicsInfo->paletteTag, graphicsInfo->paletteSlot);
}
else if (paletteSlot == 10)
{
LoadSpecialObjectReflectionPalette(graphicsInfo->paletteTag, graphicsInfo->paletteSlot);
}
else if (paletteSlot >= 16)
{
paletteSlot -= 16;
_PatchObjectPalette(graphicsInfo->paletteTag, paletteSlot);
}
*(u16 *)&spriteTemplate.paletteTag = 0xFFFF;
Replace it with this:
if (spriteTemplate.paletteTag != 0xFFFF)
{
LoadObjectEventPalette(spriteTemplate.paletteTag);
UpdatePaletteGammaType(IndexOfSpritePaletteTag(spriteTemplate.paletteTag), GAMMA_ALT);
}
After this line
if (berryId > ITEM_TO_BERRY(LAST_BERRY_INDEX))
berryId = 0;
add this (this is for the berry trees)
LoadObjectEventPalette(gBerryTreePaletteTagTablePointers[berryId][berryStage]);
Replace this line:
sprite->oam.paletteNum = gBerryTreePaletteSlotTablePointers[berryId][berryStage];
with this:
sprite->oam.paletteNum = IndexOfSpritePaletteTag(gBerryTreePaletteTagTablePointers[berryId][berryStage]);
UpdatePaletteGammaType(sprite->oam.paletteNum, GAMMA_ALT);
Delete the entire functions LoadPlayerObjectReflectionPalette
, LoadSpecialObjectReflectionPalette
, InitObjectEventPalettes
, and GetObjectPaletteTag
, they're not needed.
Please see ExpoSeed's repository for the full tutorial! This tutorial is NOT complete! If I don't get to this, hopefully someone else will!