diff options
-rw-r--r-- | NewerProject.yaml | 1 | ||||
-rw-r--r-- | magicplatform.yaml | 15 | ||||
-rw-r--r-- | src/magicplatform.cpp | 281 |
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; + } +} + + + |