-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Dynamic overworld palette system
Alexander Nicholi edited this page Aug 1, 2019
·
13 revisions
For this tutorial we will be editing one function within src/overworld.c
and three functions within src/event_object_movement.c
to make it easier when adding new overworlds, with new palettes.
Note that the current implementation breaks the reflection palette system, though for ease of adding new overworlds that should be adapted so it is dynamic as well, rather than requiring explicit reflection palettes.
Note: Function sub_808E894()
has been decompiled so depending on your version it might be called LoadEventObjectPalette()
instead.
static void sub_8086988(u32 a1)
{
ResetTasks();
ResetSpriteData(); ResetPaletteFade();
ScanlineEffect_Clear();
ResetAllPicSprites();
ResetCameraUpdateInfo();
InstallCameraPanAheadCallback();
+ FreeAllSpritePalettes();
- if (!a1)
- InitEventObjectPalettes(0);
- else
- InitEventObjectPalettes(1);
FieldEffectActiveListClear();
sub_80AAFA4();
sub_80AEE84();
if (!a1)
SetUpFieldTasks();
mapheader_run_script_with_tag_x5();
sub_81BE6B8();
}
static u8 TrySetupEventObjectSprite(struct EventObjectTemplate *eventObjectTemplate, struct SpriteTemplate *spriteTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY)
{
struct EventObject *eventObject;
const struct EventObjectGraphicsInfo *graphicsInfo;
struct Sprite *sprite;
u8 eventObjectId;
- u8 paletteSlot;
u8 spriteId;
eventObjectId = InitEventObjectStateFromTemplate(eventObjectTemplate, mapNum, mapGroup);
if (eventObjectId == NUM_EVENT_OBJECTS)
return NUM_EVENT_OBJECTS;
eventObject = &gEventObjects[eventObjectId];
graphicsInfo = GetEventObjectGraphicsInfo(eventObject->graphicsId);
+ if (spriteTemplate->paletteTag != 0xffff)
+ {
+ sub_808E894(spriteTemplate->paletteTag);
+ }
- paletteSlot = graphicsInfo->paletteSlot;
- if (paletteSlot == 0)
- {
- LoadPlayerObjectReflectionPalette(graphicsInfo->paletteTag1, 0);
- }
- else if (paletteSlot == 10)
- {
- LoadSpecialObjectReflectionPalette(graphicsInfo->paletteTag1, 10);
- }
- else if (paletteSlot >= 16)
- {
- paletteSlot -= 16;
- sub_808EAB0(graphicsInfo->paletteTag1, paletteSlot);
- }
if (eventObject->movementType == 0x4c)
{
eventObject->invisible = TRUE;
}
- *(u16 *)&spriteTemplate->paletteTag = 0xFFFF;
spriteId = CreateSprite(spriteTemplate, 0, 0, 0);
if (spriteId == MAX_SPRITES)
{
gEventObjects[eventObjectId].active = FALSE;
return NUM_EVENT_OBJECTS;
}
sprite = &gSprites[spriteId];
sub_8092FF0(eventObject->currentCoords.x + cameraX, eventObject->currentCoords.y + cameraY, &sprite->pos1.x, &sprite->pos1.y);
sprite->centerToCornerVecX = -(graphicsInfo->width >> 1);
sprite->centerToCornerVecY = -(graphicsInfo->height >> 1);
sprite->pos1.x += 8;
sprite->pos1.y += 16 + sprite->centerToCornerVecY;
- sprite->oam.paletteNum = paletteSlot;
sprite->coordOffsetEnabled = TRUE;
sprite->data[0] = eventObjectId;
eventObject->spriteId = spriteId;
eventObject->inanimate = graphicsInfo->inanimate;
if (!eventObject->inanimate)
{
StartSpriteAnim(sprite, GetFaceDirectionAnimNum(eventObject->facingDirection));
}
SetObjectSubpriorityByZCoord(eventObject->previousElevation, sprite, 1);
UpdateEventObjectVisibility(eventObject, sprite);
return eventObjectId;
}
static void RemoveEventObjectInternal(struct EventObject *eventObject)
{
+ u8 paletteNum;
struct SpriteFrameImage image;
image.size = GetEventObjectGraphicsInfo(eventObject->graphicsId)->size;
gSprites[eventObject->spriteId].images = ℑ
+ paletteNum = gSprites[eventObject->spriteId].oam.paletteNum;
DestroySprite(&gSprites[eventObject->spriteId]);
+ FieldEffectFreePaletteIfUnused(paletteNum);
}
static void sub_808E1B8(u8 eventObjectId, s16 x, s16 y)
{
u8 spriteId;
- u8 paletteSlot;
struct EventObject *eventObject;
const struct SubspriteTable *subspriteTables;
const struct EventObjectGraphicsInfo *graphicsInfo;
struct SpriteFrameImage spriteFrameImage;
struct SpriteTemplate spriteTemplate;
struct Sprite *sprite;
#define i spriteId
for (i = 0; i < ARRAY_COUNT(gLinkPlayerEventObjects); i++)
{
if (gLinkPlayerEventObjects[i].active && eventObjectId == gLinkPlayerEventObjects[i].eventObjId)
{
return;
}
}
#undef i
eventObject = &gEventObjects[eventObjectId];
subspriteTables = NULL;
graphicsInfo = GetEventObjectGraphicsInfo(eventObject->graphicsId);
spriteFrameImage.size = graphicsInfo->size;
MakeObjectTemplateFromEventObjectGraphicsInfoWithCallbackIndex(eventObject->graphicsId, eventObject->movementType, &spriteTemplate, &subspriteTables);
spriteTemplate.images = &spriteFrameImage;
+ if (spriteTemplate.paletteTag != 0xffff)
+ {
+ sub_808E894(spriteTemplate.paletteTag);
+ }
- *(u16 *)&spriteTemplate.paletteTag = 0xffff;
- paletteSlot = graphicsInfo->paletteSlot;
- if (paletteSlot == 0)
- {
- LoadPlayerObjectReflectionPalette(graphicsInfo->paletteTag1, graphicsInfo->paletteSlot);
- }
- else if (paletteSlot == 10)
- {
- LoadSpecialObjectReflectionPalette(graphicsInfo->paletteTag1, graphicsInfo->paletteSlot);
- }
- else if (paletteSlot >= 16)
- {
- paletteSlot -= 16;
- sub_808EAB0(graphicsInfo->paletteTag1, paletteSlot);
- }
- *(u16 *)&spriteTemplate.paletteTag = 0xffff;
spriteId = CreateSprite(&spriteTemplate, 0, 0, 0);
if (spriteId != MAX_SPRITES)
{
sprite = &gSprites[spriteId];
sub_8092FF0(x + eventObject->currentCoords.x, y + eventObject->currentCoords.y, &sprite->pos1.x, &sprite->pos1.y);
sprite->centerToCornerVecX = -(graphicsInfo->width >> 1);
sprite->centerToCornerVecY = -(graphicsInfo->height >> 1);
sprite->pos1.x += 8;
sprite->pos1.y += 16 + sprite->centerToCornerVecY;
sprite->images = graphicsInfo->images;
if (eventObject->movementType == 0x0b)
{
SetPlayerAvatarEventObjectIdAndObjectId(eventObjectId, spriteId);
eventObject->warpArrowSpriteId = sub_8154228();
}
if (subspriteTables != NULL)
{
SetSubspriteTables(sprite, subspriteTables);
}
- sprite->oam.paletteNum = paletteSlot;
sprite->coordOffsetEnabled = TRUE;
sprite->data[0] = eventObjectId;
eventObject->spriteId = spriteId;
if (!eventObject->inanimate && eventObject->movementType != 0x0b)
{
StartSpriteAnim(sprite, GetFaceDirectionAnimNum(eventObject->facingDirection));
}
sub_808E38C(eventObject);
SetObjectSubpriorityByZCoord(eventObject->previousElevation, sprite, 1);
}
}