summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSlawter666 <38655737+Slawter666@users.noreply.github.com>2018-09-16 21:39:59 +0100
committerSlawter666 <38655737+Slawter666@users.noreply.github.com>2018-09-16 21:39:59 +0100
commit3837e23676deb711a9b658b2ebee9bbc40102a75 (patch)
tree7543a16804eeac1b78227882cd7ea96a779a4c22
parent90a03031382a300105d98eebb8b00a2e92a171cd (diff)
Created Dynamic overworld palette system (markdown)
-rw-r--r--Dynamic-overworld-palette-system.md356
1 files changed, 356 insertions, 0 deletions
diff --git a/Dynamic-overworld-palette-system.md b/Dynamic-overworld-palette-system.md
new file mode 100644
index 0000000..f96d770
--- /dev/null
+++ b/Dynamic-overworld-palette-system.md
@@ -0,0 +1,356 @@
+For this tutorial we will be editting one function within **src/overworld.c** and three functions within **src/event_object_movement.c** along with adding one new function 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.
+
+## overworld.c
+### sub_8086988()
+```diff
+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();
+}
+```
+becomes:
+```c
+static void sub_8086988(u32 a1)
+{
+ ResetTasks();
+ ResetSpriteData();
+ ResetPaletteFade();
+ ScanlineEffect_Clear();
+ ResetAllPicSprites();
+ ResetCameraUpdateInfo();
+ InstallCameraPanAheadCallback();
+ FreeAllSpritePalettes();
+ FieldEffectActiveListClear();
+ sub_80AAFA4();
+ sub_80AEE84();
+ if (!a1)
+ SetUpFieldTasks();
+ mapheader_run_script_with_tag_x5();
+ sub_81BE6B8();
+}
+```
+## event_object_movement.c
+### TrySetupEventObjectSprite()
+```diff
+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;
+}
+```
+becomes:
+```c
+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 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);
+ }
+ if (eventObject->movementType == 0x4c)
+ {
+ eventObject->invisible = TRUE;
+ }
+ 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->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;
+}
+```
+### RemoveEventObjectInternal()
+First we need to add a new function, courtesy of ShantyTown.
+```c
+void FreeSpritePaletteIfUnused(u8 paletteNum)
+{
+ u8 i;
+ u16 tag = GetSpritePaletteTagByPaletteNum(paletteNum);
+
+ if (tag != 0xFFFF)
+ {
+ for (i = 0; i < MAX_SPRITES; i++)
+ if (gSprites[i].inUse && gSprites[i].oam.paletteNum == paletteNum)
+ return;
+ FreeSpritePaletteByTag(tag);
+ }
+}
+```
+```diff
+static void RemoveEventObjectInternal(struct EventObject *eventObject)
+{
++ u8 paletteNum;
+
+ struct SpriteFrameImage image;
+ image.size = GetEventObjectGraphicsInfo(eventObject->graphicsId)->size;
+ gSprites[eventObject->spriteId].images = &image;
++ paletteNum = gSprites[eventObject->spriteId].oam.paletteNum;
+ DestroySprite(&gSprites[eventObject->spriteId]);
++ FreeSpritePaletteIfUnused(paletteNum);
+}
+```
+becomes:
+```c
+static void RemoveEventObjectInternal(struct EventObject *eventObject)
+{
+ u8 paletteNum;
+
+ struct SpriteFrameImage image;
+ image.size = GetEventObjectGraphicsInfo(eventObject->graphicsId)->size;
+ gSprites[eventObject->spriteId].images = &image;
+ paletteNum = gSprites[eventObject->spriteId].oam.paletteNum;
+ DestroySprite(&gSprites[eventObject->spriteId]);
+ FreeSpritePaletteIfUnused(paletteNum);
+}
+```
+### sub_808E1B8()
+```diff
+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);
+ }
+}
+```
+becomes:
+```c
+static void sub_808E1B8(u8 eventObjectId, s16 x, s16 y)
+{
+ u8 spriteId;
+ 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);
+ }
+ 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->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);
+ }
+}
+``` \ No newline at end of file