diff options
-rw-r--r-- | src/tilegod.cpp | 222 | ||||
-rw-r--r-- | tilegod.yaml | 14 |
2 files changed, 232 insertions, 4 deletions
diff --git a/src/tilegod.cpp b/src/tilegod.cpp new file mode 100644 index 0000000..5162148 --- /dev/null +++ b/src/tilegod.cpp @@ -0,0 +1,222 @@ +#include <game.h> +#include <sfx.h> + +//#define REIMPLEMENT + +extern "C" bool SpawnEffect(const char*, int, Vec*, S16Vec*, Vec*); + +class daChengeBlock_c : public dStageActor_c { + static daChengeBlock_c *build(); + + u32 _394; + u64 initialFlags; + + enum Action { Destroy, Create }; + enum Pattern { Fill, CheckerA, CheckerB }; + + int width, height; + Action action; + int blockType; + int isPermanent; + Pattern pattern; + u16 hasTriggered; + + u32 _3BC; + + + int onCreate(); + int onExecute(); + + void doStuff(Action action, bool wasCalledOnCreation); + void tryToTrigger(); +}; + +#ifdef REIMPLEMENT +daChengeBlock_c *daChengeBlock_c::build() { + return new(AllocFromGameHeap1(sizeof(daChengeBlock_c))) daChengeBlock_c; +} + + + +int daChengeBlock_c::onCreate() { + hasTriggered = 0; + + height = settings & 0xF; + width = (settings & 0xF0) >> 4; + blockType = (settings & 0xF000) >> 12; + pattern = (Pattern)((settings & 0xF0000) >> 16); + isPermanent = (settings & 0xF0000000) >> 28; + + if (width == 0) + width++; + if (height == 0) + height++; + + action = (Action)((settings & 0xF00) >> 8); + + initialFlags = dFlagMgr_c::instance->flags & dStageActor_c::creatingFlagMask; + + if (initialFlags) { + if (action == Destroy) { + doStuff(Destroy, true); + } else { + doStuff(Create, true); + hasTriggered = true; + } + + if (isPermanent) + return 2; + } + + return 1; +} + + +int daChengeBlock_c::onExecute() { + tryToTrigger(); + + if (!hasTriggered) + checkZoneBoundaries(0); + + return 1; +} + + +#endif // REIMPLEMENT + +// Red, Brick, Blank/Unused, Stone, Wood, Blank +static const u16 Tiles[] = {124, 2, 12, 123, 15, 0}; + +void daChengeBlock_c::doStuff(Action action, bool wasCalledOnCreation) { + u16 perTilePatternFlag = 1, perRowPatternFlag = 1; + + u16 worldX = ((u16)pos.x) & 0xFFF0; + u16 baseWorldX = worldX; + u16 worldY = ((u16)(-pos.y)) & 0xFFF0; + + if (pattern == CheckerB) { + perTilePatternFlag = 0; + perRowPatternFlag = 0; + } + + u16 tile; + if (action != Destroy) { + if (blockType & 8) { + // Specify a tile number + tile = 0x8000 | ((blockType & 3) << 8) | ((settings & 0xFF00000) >> 20); + } else { + // fall through + tile = Tiles[blockType]; + } + } else { + tile = 0; + } + + for (u16 y = 0; y < height; y++) { + for (u16 x = 0; x < width; x++) { + if (perTilePatternFlag) { + u16 *pExistingTile = dBgGm_c::instance->getPointerToTile(worldX, worldY, 0); + u16 existingTile = pExistingTile ? *pExistingTile : 0; + + dBgGm_c::instance->placeTile(worldX, worldY, 0, tile); + + if (!wasCalledOnCreation) { + Vec effectPos; + + if (action == Destroy) { + if (blockType != 2) { + effectPos.x = ((float)(worldX)) + 8.0f; + effectPos.y = ((float)(-worldY)) - 8.0f; + effectPos.z = pos.z; + + u16 shardType; + switch (existingTile) { + case 0x30: shardType = 0; break; + case 0x31: shardType = 3; break; + case 0x32: shardType = 4; break; + case 0x33: shardType = 2; break; + case 0x34: shardType = 1; break; + case 0x37: shardType = 5; break; + default: shardType = 0xFFFF; + } + + if (shardType == 0xFFFF) { + SpawnEffect("Wm_en_burst_ss", 0, &effectPos, 0, 0); + } else { + u32 sets = (shardType << 8) | 3; + effectPos.y -= 8; + dEffectBreakMgr_c::instance->spawnTile(&effectPos, sets, 0); + } + + Vec2 soundPos; + ConvertStagePositionToScreenPosition(&soundPos, &effectPos); + SoundPlayingClass::instance2->PlaySoundAtPosition(SE_OBJ_BLOCK_BREAK, &soundPos, 0); + } + } else { + effectPos.x = ((float)(worldX)) + 8.0f; + effectPos.y = ((float)(-worldY)) - 8.0f; + effectPos.z = pos.z; + + if (blockType != 2) { + SpawnEffect("Wm_en_burst_ss", 0, &effectPos, 0, 0); + } + } + } + } + + if (pattern != Fill) { + perTilePatternFlag ^= 1; + } + + worldX += 16; + } + + if (pattern != Fill) { + perRowPatternFlag ^= 1; + perTilePatternFlag = perRowPatternFlag; + } + + worldX = baseWorldX; + worldY += 16; + } +} + + +#ifdef REIMPLEMENT +void daChengeBlock_c::tryToTrigger() { + u64 result = spriteFlagMask & dFlagMgr_c::instance->flags; + + if (action == Destroy) { + if (result & initialFlags) { + if (result) { + doStuff(Destroy, false); + hasTriggered = true; + } else { + doStuff(Create, false); + hasTriggered = false; + } + + initialFlags = result; + + if (isPermanent) + fBase_c::Delete(); + } + } else { + if (result & initialFlags) { + if (result) { + doStuff(Create, false); + hasTriggered = true; + } else { + doStuff(Destroy, false); + hasTriggered = false; + } + + initialFlags = result; + + if (isPermanent) + fBase_c::Delete(); + } + } +} +#endif + diff --git a/tilegod.yaml b/tilegod.yaml index 235adf0..6da2163 100644 --- a/tilegod.yaml +++ b/tilegod.yaml @@ -1,12 +1,18 @@ ---
-source_files: [../src/tilegod.S]
+source_files: [../src/tilegod.S, ../src/tilegod.cpp]
hooks:
+# - name: TileGodHack
+# type: branch_insn
+# branch_type: b
+# src_addr_pal: 0x807E1668
+# target_func: 'TileGodHack'
+
- name: TileGodHack
type: branch_insn
branch_type: b
- src_addr_pal: 0x807E1668
- target_func: 'TileGodHack'
-
+ src_addr_pal: 0x807E15D0
+ target_func: 'daChengeBlock_c::doStuff(daChengeBlock_c::Action, bool)'
+
- name: GetTileFromTileTableHack
type: branch_insn
branch_type: b
|