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; +	} +} + + +  | 
