summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NewerProject.yaml1
-rw-r--r--magicplatform.yaml15
-rw-r--r--src/magicplatform.cpp281
3 files changed, 297 insertions, 0 deletions
diff --git a/NewerProject.yaml b/NewerProject.yaml
index fc97361..2108e0b 100644
--- a/NewerProject.yaml
+++ b/NewerProject.yaml
@@ -2,6 +2,7 @@ output_dir: "NewerASM"
code_address: 0x808D9000
modules:
- processed/prolog.yaml
+ - processed/magicplatform.yaml
- processed/bugfixes.yaml
- processed/worldmap.yaml
- processed/levelnames.yaml
diff --git a/magicplatform.yaml b/magicplatform.yaml
new file mode 100644
index 0000000..69b349c
--- /dev/null
+++ b/magicplatform.yaml
@@ -0,0 +1,15 @@
+---
+source_files: [../src/magicplatform.cpp]
+hooks:
+ - name: BuildMagicPlatform
+ type: add_func_pointer
+ src_addr_pal: 0x80B08630
+ target_func: 'daEnMagicPlatform_c::build(void)'
+
+ - name: UpdateMagicPlatformSpriteInfo
+ type: patch
+ addr_pal: 0x8030BDA8
+ # -ID- ---- -X Offs- -Y Offs- -RectX1- -RectY1- -RectX2- -RectY2- -1C- -1E- -20- -22- Flag ----
+ # Orig 00C4 0000 00000008 FFFFFFF0 00000000 00000010 00000010 00000010 0000 0000 0000 0000 0000 0000
+ data: '00C4 0000 00000000 00000000 00000000 00000000 00000100 00000100 0000 0000 0000 0000 0000 0000'
+
diff --git a/src/magicplatform.cpp b/src/magicplatform.cpp
new file mode 100644
index 0000000..924d849
--- /dev/null
+++ b/src/magicplatform.cpp
@@ -0,0 +1,281 @@
+#include <game.h>
+#include <dCourse.h>
+
+class daEnMagicPlatform_c : public dEn_c {
+ public:
+ static daEnMagicPlatform_c *build();
+
+ int onCreate();
+ int onExecute();
+ int onDelete();
+
+ // Settings
+ u8 rectID, moveSpeed, moveDirection, moveLength;
+
+ float moveMin, moveMax, moveDelta, moveBaseDelta;
+ float *moveTarget;
+
+ bool isMoving;
+ void setupMovement();
+ void handleMovement();
+
+ Physics physics;
+
+ TileRenderer *renderers;
+ int rendererCount;
+
+ void findSourceArea();
+ void createTiles();
+ void deleteTiles();
+ void updateTilePositions();
+
+ int srcX, srcY;
+ int width, height;
+};
+
+/*****************************************************************************/
+// Glue Code
+daEnMagicPlatform_c *daEnMagicPlatform_c::build() {
+ void *buffer = AllocFromGameHeap1(sizeof(daEnMagicPlatform_c));
+ daEnMagicPlatform_c *c = new(buffer) daEnMagicPlatform_c;
+ return c;
+}
+
+int daEnMagicPlatform_c::onCreate() {
+ rectID = settings & 0xFF;
+ moveSpeed = (settings & 0xF00) >> 8;
+ moveDirection = (settings & 0x3000) >> 12;
+ moveLength = ((settings & 0xF0000) >> 16) + 1;
+
+ setupMovement();
+
+ findSourceArea();
+ createTiles();
+
+ float fWidth = width * 16.0f;
+ float fHeight = height * 16.0f;
+ physics.setup(this,
+ 0.0f, 0.0f, fWidth, -fHeight,
+ 0, 0, 0/*&PhysCB1, &PhysCB2, &PhysCB3*/, 1, 0, 0);
+
+ physics.addToList();
+
+ return 1;
+}
+
+int daEnMagicPlatform_c::onDelete() {
+ deleteTiles();
+
+ physics.removeFromList();
+
+ return 1;
+}
+
+int daEnMagicPlatform_c::onExecute() {
+ handleMovement();
+
+ updateTilePositions();
+ physics.update();
+
+ return 1;
+}
+
+/*****************************************************************************/
+// Movement
+void daEnMagicPlatform_c::setupMovement() {
+ float fMoveLength = 16.0f * moveLength;
+ float fMoveSpeed = 0.2f * moveSpeed;
+
+ switch (moveDirection) {
+ case 0: // RIGHT
+ moveTarget = &pos.x;
+ moveMin = pos.x;
+ moveMax = pos.x + fMoveLength;
+ moveBaseDelta = fMoveSpeed;
+ break;
+ case 1: // LEFT
+ moveTarget = &pos.x;
+ moveMin = pos.x - fMoveLength;
+ moveMax = pos.x;
+ moveBaseDelta = -fMoveSpeed;
+ break;
+ case 2: // UP
+ moveTarget = &pos.y;
+ moveMin = pos.y;
+ moveMax = pos.y + fMoveLength;
+ moveBaseDelta = fMoveSpeed;
+ break;
+ case 3: // DOWN
+ moveTarget = &pos.y;
+ moveMin = pos.y - fMoveLength;
+ moveMax = pos.y;
+ moveBaseDelta = -fMoveSpeed;
+ break;
+ }
+
+ if (spriteFlagNum == 0) {
+ isMoving = (moveSpeed > 0);
+ moveDelta = moveBaseDelta;
+ } else {
+ isMoving = false;
+ }
+}
+
+void daEnMagicPlatform_c::handleMovement() {
+ if (spriteFlagNum > 0) {
+ // Do event checks
+ bool flagOn = ((dFlagMgr_c::instance->flags & spriteFlagMask) != 0);
+
+ if (isMoving) {
+ if (!flagOn) {
+ // Flag was turned off while moving, so go back
+ moveDelta = -moveBaseDelta;
+ } else {
+ moveDelta = moveBaseDelta;
+ }
+ } else {
+ if (flagOn) {
+ // Flag was turned on, so start moving
+ moveDelta = moveBaseDelta;
+ isMoving = true;
+ }
+ }
+ }
+
+ if (!isMoving)
+ return;
+
+ // Do it
+ bool goesForward = (moveDelta > 0.0f);
+ bool reachedEnd = false;
+
+ *moveTarget += moveDelta;
+
+ if (goesForward) {
+ if (*moveTarget >= moveMax) {
+ *moveTarget = moveMax;
+ reachedEnd = true;
+ }
+ } else {
+ if (*moveTarget <= moveMin) {
+ *moveTarget = moveMin;
+ reachedEnd = true;
+ }
+ }
+
+ if (reachedEnd) {
+ if (spriteFlagNum > 0) {
+ // If event, just do nothing.. depending on what side we are on
+ if ((moveDelta > 0.0f && moveBaseDelta > 0.0f) || (moveDelta < 0.0f && moveBaseDelta < 0.0f)) {
+ // We reached the end, so keep isMoving on for when we need to reverse
+ } else {
+ // We're back at the start, so turn it off
+ isMoving = false;
+ }
+ } else {
+ // Otherwise, reverse
+ moveDelta = -moveDelta;
+ }
+ }
+}
+
+/*****************************************************************************/
+// Tile Renderers
+
+void daEnMagicPlatform_c::findSourceArea() {
+ mRect rect;
+ dCourseFull_c::instance->get(GetAreaNum())->getRectByID(rectID, &rect);
+
+ // Round the positions down/up to get the rectangle
+ int left = rect.x;
+ int right = left + rect.width;
+ int top = -rect.y;
+ int bottom = top + rect.height;
+
+ left &= 0xFFF0;
+ right = (right + 15) & 0xFFF0;
+
+ top &= 0xFFF0;
+ bottom = (bottom + 15) & 0xFFF0;
+
+ // Calculate the actual stuff
+ srcX = left >> 4;
+ srcY = top >> 4;
+ width = (right - left) >> 4;
+ height = (bottom - top) >> 4;
+
+ //OSReport("Area: %f, %f ; %f x %f\n", rect.x, rect.y, rect.width, rect.height);
+ //OSReport("Source: %d, %d ; Size: %d x %d\n", srcX, srcY, width, height);
+}
+
+
+void daEnMagicPlatform_c::createTiles() {
+ TileRenderer::List *list = dBgGm_c::instance->getTileRendererList(0);
+
+ rendererCount = width * height;
+ renderers = new TileRenderer[rendererCount];
+
+ // copy all the fuckers over
+ int baseWorldX = srcX << 4, worldY = srcY << 4, rendererID = 0;
+
+ for (int y = 0; y < height; y++) {
+ int worldX = baseWorldX;
+
+ for (int x = 0; x < width; x++) {
+ u16 *pExistingTile = dBgGm_c::instance->getPointerToTile(worldX, worldY, 0);
+
+ if (*pExistingTile > 0) {
+ TileRenderer *r = &renderers[rendererID];
+ r->tileNumber = *pExistingTile;
+ r->z = pos.z;
+ list->add(r);
+ }
+
+ worldX += 16;
+ rendererID++;
+ }
+
+ worldY += 16;
+ }
+
+}
+
+void daEnMagicPlatform_c::deleteTiles() {
+ if (renderers != 0) {
+ TileRenderer::List *list = dBgGm_c::instance->getTileRendererList(0);
+
+ for (int i = 0; i < rendererCount; i++) {
+ if (renderers[i].isInList())
+ list->remove(&renderers[i]);
+ }
+
+ delete[] renderers;
+ renderers = 0;
+ }
+}
+
+void daEnMagicPlatform_c::updateTilePositions() {
+ float baseX = pos.x;
+
+ float y = -pos.y;
+
+ int rendererID = 0;
+
+ for (int yIdx = 0; yIdx < height; yIdx++) {
+ float x = baseX;
+
+ for (int xIdx = 0; xIdx < width; xIdx++) {
+ TileRenderer *r = &renderers[rendererID];
+ r->x = x;
+ r->y = y;
+
+ x += 16.0f;
+ rendererID++;
+ }
+
+ y += 16.0f;
+ }
+}
+
+
+