#include #include 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; } }