summaryrefslogtreecommitdiff
path: root/src/rotating_tile_puzzle.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rotating_tile_puzzle.c')
-rw-r--r--src/rotating_tile_puzzle.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/src/rotating_tile_puzzle.c b/src/rotating_tile_puzzle.c
new file mode 100644
index 000000000..acc1c11cc
--- /dev/null
+++ b/src/rotating_tile_puzzle.c
@@ -0,0 +1,315 @@
+#include "global.h"
+#include "event_object_movement.h"
+#include "fieldmap.h"
+#include "malloc.h"
+#include "rotating_tile_puzzle.h"
+#include "script_movement.h"
+#include "constants/event_object_movement_constants.h"
+#include "constants/event_objects.h"
+#include "constants/metatile_labels.h"
+
+// Movement scripts.
+extern const u8 gUnknown_08612698[];
+extern const u8 gUnknown_0861269C[];
+extern const u8 gUnknown_086126A0[];
+extern const u8 gUnknown_086126A4[];
+extern const u8 MossdeepGym_Movement_FaceRight[];
+extern const u8 MossdeepGym_Movement_FaceDown[];
+extern const u8 MossdeepGym_Movement_FaceLeft[];
+extern const u8 MossdeepGym_Movement_FaceUp[];
+
+struct MossdeepSubStruct
+{
+ u8 unk0;
+ u8 eventTemplateId;
+};
+
+struct RotatingTilePuzzle
+{
+ struct MossdeepSubStruct objects[EVENT_OBJECTS_COUNT];
+ u8 count;
+ bool8 isTrickHouse;
+};
+
+// This file's functions.
+static void AddEventObject(u8 eventTemplateId, u8 arg1);
+static void sub_81A8D94(u8 eventTemplateId, u8 arg1);
+
+// EWRAM vars
+EWRAM_DATA static struct RotatingTilePuzzle *sRotatingTilePuzzle = NULL;
+
+// code
+void InitRotatingTilePuzzle(bool8 isTrickHouse)
+{
+ if (sRotatingTilePuzzle == NULL)
+ sRotatingTilePuzzle = AllocZeroed(sizeof(*sRotatingTilePuzzle));
+
+ sRotatingTilePuzzle->isTrickHouse = isTrickHouse;
+}
+
+void FinishMossdeepGymTiles(void)
+{
+ u8 id;
+
+ if (sRotatingTilePuzzle != NULL)
+ FREE_AND_SET_NULL(sRotatingTilePuzzle);
+
+ id = GetEventObjectIdByLocalIdAndMap(EVENT_OBJ_ID_PLAYER, 0, 0);
+ EventObjectClearHeldMovementIfFinished(&gEventObjects[id]);
+ ScriptMovement_UnfreezeEventObjects();
+}
+
+u16 MossdeepGym_MoveEvents(u8 puzzleNumber)
+{
+ u8 i;
+ struct EventObjectTemplate *eventObjects = gSaveBlock1Ptr->eventObjectTemplates;
+ u16 localId = 0;
+
+ for (i = 0; i < EVENT_OBJECT_TEMPLATES_COUNT; i++)
+ {
+ s32 puzzleTileStart;
+ u8 r5;
+ s16 x = eventObjects[i].x + 7;
+ s16 y = eventObjects[i].y + 7;
+ u16 metatile = MapGridGetMetatileIdAt(x, y);
+
+ if (!sRotatingTilePuzzle->isTrickHouse)
+ puzzleTileStart = METATILE_MossdeepGym_YellowRightArrow;
+ else
+ puzzleTileStart = METATILE_TrickHousePuzzle_Arrow_YellowOnWhite_Right;
+
+ if (metatile < METATILE_MossdeepGym_YellowRightArrow)
+ continue;
+
+ if ((u8)((metatile - puzzleTileStart) / 8) >= 5)
+ continue;
+ if ((u8)((metatile - puzzleTileStart) / 8) != puzzleNumber)
+ continue;
+
+ r5 = (u8)((metatile - puzzleTileStart) % 8);
+ if (r5 < 4)
+ {
+ s8 x = 0;
+ s8 y = 0;
+ const u8 *movementScript;
+
+ switch (r5)
+ {
+ case 0:
+ movementScript = gUnknown_08612698;
+ x = 1;
+ break;
+ case 1:
+ movementScript = gUnknown_0861269C;
+ y = 1;
+ break;
+ case 2:
+ movementScript = gUnknown_086126A0;
+ x = -1;
+ break;
+ case 3:
+ movementScript = gUnknown_086126A4;
+ y = -1;
+ break;
+ default:
+ continue;
+ }
+
+ eventObjects[i].x += x;
+ eventObjects[i].y += y;
+ if (GetEventObjectIdByLocalIdAndMap(eventObjects[i].localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup) != EVENT_OBJECTS_COUNT)
+ {
+ AddEventObject(i, r5);
+ localId = eventObjects[i].localId;
+ ScriptMovement_StartObjectMovementScript(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, movementScript);
+ }
+ else
+ {
+ sub_81A8D94(i, r5);
+ }
+ }
+ }
+
+ return localId;
+}
+
+void MossdeepGym_TurnEvents(void)
+{
+ u8 i;
+ s32 puzzleTileStart;
+ struct EventObjectTemplate *eventObjects;
+
+ if (sRotatingTilePuzzle == NULL)
+ return;
+
+ if (!sRotatingTilePuzzle->isTrickHouse)
+ puzzleTileStart = METATILE_MossdeepGym_YellowRightArrow;
+ else
+ puzzleTileStart = METATILE_TrickHousePuzzle_Arrow_YellowOnWhite_Right;
+
+ eventObjects = gSaveBlock1Ptr->eventObjectTemplates;
+ for (i = 0; i < sRotatingTilePuzzle->count; i++)
+ {
+ s32 r6;
+ s8 r0;
+ u8 eventObjectId;
+ s16 x = eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].x + 7;
+ s16 y = eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].y + 7;
+ u16 metatile = MapGridGetMetatileIdAt(x, y);
+
+ r0 = (u8)((metatile - puzzleTileStart) % 8);
+ r0 -= (sRotatingTilePuzzle->objects[i].unk0);
+ if (r0 < 0 || r0 == 3)
+ {
+ if (r0 == -3)
+ r6 = 1;
+ else
+ r6 = 0;
+ }
+ else
+ {
+ if (r0 > 0)
+ r6 = 1;
+ else
+ r6 = 2;
+ }
+
+ eventObjectId = GetEventObjectIdByLocalIdAndMap(eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
+ if (eventObjectId != EVENT_OBJECTS_COUNT)
+ {
+ const u8 *movementScript;
+ u8 direction = gEventObjects[eventObjectId].facingDirection;
+ if (r6 == 0)
+ {
+ switch (direction)
+ {
+ case DIR_EAST:
+ movementScript = MossdeepGym_Movement_FaceUp;
+ eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].movementType = MOVEMENT_TYPE_FACE_UP;
+ break;
+ case DIR_SOUTH:
+ movementScript = MossdeepGym_Movement_FaceRight;
+ eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].movementType = MOVEMENT_TYPE_FACE_RIGHT;
+ break;
+ case DIR_WEST:
+ movementScript = MossdeepGym_Movement_FaceDown;
+ eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].movementType = MOVEMENT_TYPE_FACE_DOWN;
+ break;
+ case DIR_NORTH:
+ movementScript = MossdeepGym_Movement_FaceLeft;
+ eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].movementType = MOVEMENT_TYPE_FACE_LEFT;
+ break;
+ default:
+ continue;
+ }
+ ScriptMovement_StartObjectMovementScript(eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].localId,
+ gSaveBlock1Ptr->location.mapNum,
+ gSaveBlock1Ptr->location.mapGroup,
+ movementScript);
+ }
+ else if (r6 == 1)
+ {
+ switch (direction)
+ {
+ case DIR_EAST:
+ movementScript = MossdeepGym_Movement_FaceDown;
+ eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].movementType = MOVEMENT_TYPE_FACE_DOWN;
+ break;
+ case DIR_SOUTH:
+ movementScript = MossdeepGym_Movement_FaceLeft;
+ eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].movementType = MOVEMENT_TYPE_FACE_LEFT;
+ break;
+ case DIR_WEST:
+ movementScript = MossdeepGym_Movement_FaceUp;
+ eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].movementType = MOVEMENT_TYPE_FACE_UP;
+ break;
+ case DIR_NORTH:
+ movementScript = MossdeepGym_Movement_FaceRight;
+ eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].movementType = MOVEMENT_TYPE_FACE_RIGHT;
+ break;
+ default:
+ continue;
+ }
+ ScriptMovement_StartObjectMovementScript(eventObjects[sRotatingTilePuzzle->objects[i].eventTemplateId].localId,
+ gSaveBlock1Ptr->location.mapNum,
+ gSaveBlock1Ptr->location.mapGroup,
+ movementScript);
+ }
+ }
+ }
+}
+
+static void AddEventObject(u8 eventTemplateId, u8 arg1)
+{
+ sRotatingTilePuzzle->objects[sRotatingTilePuzzle->count].eventTemplateId = eventTemplateId;
+ sRotatingTilePuzzle->objects[sRotatingTilePuzzle->count].unk0 = arg1;
+ sRotatingTilePuzzle->count++;
+}
+
+static void sub_81A8D94(u8 eventTemplateId, u8 arg1)
+{
+ s8 r0;
+ s32 r6;
+ s32 puzzleTileStart;
+ u16 movementType;
+ struct EventObjectTemplate *eventObjects = gSaveBlock1Ptr->eventObjectTemplates;
+ s16 x = eventObjects[eventTemplateId].x + 7;
+ s16 y = eventObjects[eventTemplateId].y + 7;
+ u16 metatile = MapGridGetMetatileIdAt(x, y);
+
+ if (!sRotatingTilePuzzle->isTrickHouse)
+ puzzleTileStart = METATILE_MossdeepGym_YellowRightArrow;
+ else
+ puzzleTileStart = METATILE_TrickHousePuzzle_Arrow_YellowOnWhite_Right;
+
+ r0 = (u8)((metatile - puzzleTileStart) % 8);
+ r0 -= arg1;
+ if (r0 < 0 || r0 == 3)
+ r6 = 0;
+ else if (r0 > 0 || r0 == -3)
+ r6 = 1;
+ else
+ r6 = 2;
+
+ movementType = eventObjects[eventTemplateId].movementType;
+ if (r6 == 0)
+ {
+ switch (movementType)
+ {
+ case MOVEMENT_TYPE_FACE_RIGHT:
+ eventObjects[eventTemplateId].movementType = MOVEMENT_TYPE_FACE_UP;
+ break;
+ case MOVEMENT_TYPE_FACE_DOWN:
+ eventObjects[eventTemplateId].movementType = MOVEMENT_TYPE_FACE_RIGHT;
+ break;
+ case MOVEMENT_TYPE_FACE_LEFT:
+ eventObjects[eventTemplateId].movementType = MOVEMENT_TYPE_FACE_DOWN;
+ break;
+ case MOVEMENT_TYPE_FACE_UP:
+ eventObjects[eventTemplateId].movementType = MOVEMENT_TYPE_FACE_LEFT;
+ break;
+ default:
+ break;
+ }
+ }
+ else if (r6 == 1)
+ {
+ switch (movementType)
+ {
+ case MOVEMENT_TYPE_FACE_RIGHT:
+ eventObjects[eventTemplateId].movementType = MOVEMENT_TYPE_FACE_DOWN;
+ break;
+ case MOVEMENT_TYPE_FACE_DOWN:
+ eventObjects[eventTemplateId].movementType = MOVEMENT_TYPE_FACE_LEFT;
+ break;
+ case MOVEMENT_TYPE_FACE_LEFT:
+ eventObjects[eventTemplateId].movementType = MOVEMENT_TYPE_FACE_UP;
+ break;
+ case MOVEMENT_TYPE_FACE_UP:
+ eventObjects[eventTemplateId].movementType = MOVEMENT_TYPE_FACE_RIGHT;
+ break;
+ default:
+ break;
+ }
+ }
+}