From 32138533299e9e7e3f4171184abe3471e3d536cf Mon Sep 17 00:00:00 2001 From: krazybluemonkey <39660982+krazybluemonkey@users.noreply.github.com> Date: Wed, 21 Feb 2024 01:35:32 -0700 Subject: [PATCH 1/3] hurtful blocks commit --- LunaDll/Misc/NpcIdExtender.cpp | 2 +- LunaDll/Misc/RuntimeHook.h | 7 + .../RuntimeHookGeneral.cpp | 7 + .../RuntimeHookHooks.cpp | 269 ++++++++++++++++++ LunaDll/SMBXInternal/Blocks.cpp | 60 ++++ LunaDll/SMBXInternal/Blocks.h | 4 + 6 files changed, 348 insertions(+), 1 deletion(-) diff --git a/LunaDll/Misc/NpcIdExtender.cpp b/LunaDll/Misc/NpcIdExtender.cpp index f8a5cd77..93e6fa37 100644 --- a/LunaDll/Misc/NpcIdExtender.cpp +++ b/LunaDll/Misc/NpcIdExtender.cpp @@ -459,7 +459,7 @@ static const uint32_t array_b2c09c_patches[] = { 0x9a1837, 0x9bbcf7, 0x9bbd46, 0 static ResizableGameArray array_b2c09c_obj((void**)0xb2c09c, 701, 2, array_b2c09c_patches); static const uint32_t array_b2c0b8_patches[] = { 0x9e39cc, 0x000000 }; static ResizableGameArray array_b2c0b8_obj((void**)0xb2c0b8, 701, 2, array_b2c0b8_patches); -static const uint32_t array_b2c0d4_patches[] = { 0x8f7067, 0x998322, 0x9a1748, 0x9bba16, 0x9c03b1, 0x9c0b28, 0x9eed7a, 0xa11309, 0xa1c3cf, 0xa1c884, 0xa1cc2a, 0xa3bfba, 0xa4f927, 0xa4fd12, 0xa501e1, 0xa50563, 0xa509ac, 0xa50d7f, 0xa511fa, 0xa515c5, 0xa5260b, 0xa5b23d, 0xa5d3ea, 0x000000 }; +static const uint32_t array_b2c0d4_patches[] = { 0x8f7067, 0x998322, 0x9a1748, 0x9c03b1, 0x9c0b28, 0x9eed7a, 0xa11309, 0xa1c3cf, 0xa1c884, 0xa1cc2a, 0xa3bfba, 0xa4f927, 0xa4fd12, 0xa501e1, 0xa50563, 0xa509ac, 0xa50d7f, 0xa511fa, 0xa515c5, 0xa5260b, 0xa5b23d, 0xa5d3ea, 0x000000 }; static ResizableGameArray array_b2c0d4_obj((void**)0xb2c0d4, 701, 2, array_b2c0d4_patches); static const uint32_t array_blockdef_isResizeableBlock_patches[] = { 0x8d58cf, 0x8d5c86, 0x8f70de, 0x91055a, 0x91d6c8, 0x943714, 0x943f2e, 0x99827c, 0x9a1788, 0x9a2a03, 0x9aee88, 0x9bb9ba, 0x9c0430, 0x9c09dd, 0x9dbb7c, 0x9dc333, 0x9e2d2e, 0x9e300b, 0x9ed6d9, 0x9ed6c5, 0x9ed80c, 0x9eed4d, 0x9ef511, 0x9f10b4, 0x9f1823, 0x9f59ca, 0x9f974a, 0x9fd68c, 0xa06a48, 0xa11fa7, 0xa11fec, 0xa1233a, 0xa131bc, 0xa14aca, 0xa1a669, 0xa1c462, 0xa1c927, 0xa1cccd, 0xa2261d, 0xa4f9a1, 0xa4fd8f, 0xa50260, 0xa505df, 0xa50a29, 0xa50df9, 0xa51274, 0xa51642, 0xa52689, 0xa5b278, 0xa87089, 0xa998be, 0xaf7159, 0x000000 }; static ResizableGameArray array_blockdef_isResizeableBlock_obj((void**)0xb2b930, 701, 2, array_blockdef_isResizeableBlock_patches); diff --git a/LunaDll/Misc/RuntimeHook.h b/LunaDll/Misc/RuntimeHook.h index fc43829f..1b26ed6e 100644 --- a/LunaDll/Misc/RuntimeHook.h +++ b/LunaDll/Misc/RuntimeHook.h @@ -335,6 +335,13 @@ void __stdcall runtimeHookChangeResolution(void* arg1, void* arg2, void* arg3, v void __stdcall runtimeHookSmbxCheckWindowedRaw(void); void __stdcall runtimeHookBlockBumpableRaw(void); + +void __stdcall runtimeHookHurtfulBlocksRaw(void); +void __stdcall runtimeHookTailSwipeRaw_9bb9c6(void); +void __stdcall runtimeHookTailSwipeRaw_9bba74(void); +void __stdcall runtimeHookTailSwipeRaw_9bbd03(void); +void __stdcall runtimeHookTailSwipeRaw_9bbd52(void); + void __stdcall runtimeHookNPCVulnerabilityRaw(void); void __stdcall runtimeHookNPCSpinjumpSafeRaw(void); void __stdcall runtimeHookNPCNoWaterPhysicsRaw(void); diff --git a/LunaDll/Misc/RuntimeHookComponents/RuntimeHookGeneral.cpp b/LunaDll/Misc/RuntimeHookComponents/RuntimeHookGeneral.cpp index 0b6d0465..47d77bce 100644 --- a/LunaDll/Misc/RuntimeHookComponents/RuntimeHookGeneral.cpp +++ b/LunaDll/Misc/RuntimeHookComponents/RuntimeHookGeneral.cpp @@ -1721,6 +1721,13 @@ void TrySkipPatch() PATCH(0x96ADD7).CALL(runtimeHookSmbxCheckWindowedRaw).NOP_PAD_TO_SIZE<8>().Apply(); PATCH(0x9DB1D8).JMP(runtimeHookBlockBumpableRaw).NOP_PAD_TO_SIZE<6>().Apply(); + // Hurtful Blocks Hook + PATCH(0x9A1843).JMP(0x9A1BDA).NOP_PAD_TO_SIZE<919>().Apply(); + PATCH(0x9A391A).JMP(runtimeHookHurtfulBlocksRaw).Apply(); + PATCH(0x9BB9C6).JMP(runtimeHookTailSwipeRaw_9bb9c6).NOP_PAD_TO_SIZE<115>().Apply(); + PATCH(0x9BBA74).JMP(runtimeHookTailSwipeRaw_9bba74).Apply(); + PATCH(0x9BBD03).JMP(runtimeHookTailSwipeRaw_9bbd03).NOP_PAD_TO_SIZE<13>().Apply(); + PATCH(0x9BBD52).JMP(runtimeHookTailSwipeRaw_9bbd52).NOP_PAD_TO_SIZE<13>().Apply(); PATCH(0xA28FE3).JMP(runtimeHookNPCVulnerabilityRaw).Apply(); diff --git a/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp b/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp index 813132ad..7709bb80 100644 --- a/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp +++ b/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp @@ -1,5 +1,6 @@ #include #include "../../Misc/CollisionMatrix.h" +#include "../../Misc/CollisionMatrix.h" #include "string.h" #include "../../Globals.h" #include "../RuntimeHook.h" @@ -28,6 +29,8 @@ #include "../../SMBXInternal/Blocks.h" #include "../../SMBXInternal/Level.h" #include "../../SMBXInternal/Sound.h" +#include "../../SMBXInternal/Functions.h" +#include "../../SMBXInternal/Variables.h" #include "../PerfTracker.h" @@ -1743,6 +1746,272 @@ __declspec(naked) void __stdcall runtimeHookBlockBumpableRaw(void) } } +static void __stdcall runtimeHookHurtfulBlocksInternal(int hitSpot, short playerIdx, int blockIdx, const double& slope) +{ + PlayerMOB* player = Player::Get(playerIdx); + Block* block = Block::GetRaw(blockIdx); + + // don't worry about lava + if (SMBX13::Vars::BlockHurts[block->BlockType] && !SMBX13::Vars::BlockKills[block->BlockType]) + { + short floorSlope = SMBX13::Vars::BlockSlope[block->BlockType]; + unsigned char flags = Blocks::GetBlockHurtSide(block->BlockType); + bool tempBool = false; + + // stop if we shouldn't be hurt + if (player->MountType == 2 || ((hitSpot == 1 || floorSlope != 0 && player->SlopeRelated == blockIdx) && player->MountType != 0) && (flags & 0x80) != 0) return; + + // check hitspot & collision config for blocks and hurt as needed + switch (hitSpot) { + case 0: // cancelled (slopes, sizables, semi solids) + tempBool = ((flags & 0x01) != 0 || (flags & 0x40) != 0); + break; + case 1: // top + tempBool = ((flags & 0x02) != 0 || (flags & 0x40) != 0); + break; + case 2: // right + tempBool = ((flags & 0x04) != 0 || (flags & 0x40) != 0); + break; + case 3: // bottom + tempBool = ((flags & 0x08) != 0 || (flags & 0x40) != 0); + break; + case 4: // left + tempBool = ((flags & 0x10) != 0 || (flags & 0x40) != 0); + break; + case 5: // inside/zipping + tempBool = ((flags & 0x20) != 0 || (flags & 0x40) != 0); + break; + } + + // floor slope should harm + if ((floorSlope != 0 && ((flags & 0x02) != 0 || (flags & 0x40) != 0) && player->SlopeRelated == blockIdx)) tempBool = true; + + // ceiling slope should harm + if ((SMBX13::Vars::BlockSlope2[block->BlockType] && ((flags & 0x08) != 0 || (flags & 0x40) != 0) && player->momentum.y <= block->momentum.y + block->momentum.height - (block->momentum.height * slope))) + { + tempBool = true; + } + + // if set as invisible, don't harm (potential compatibility break) + if (block->IsInvisible2) tempBool = false; + + if (tempBool) + { + if ((player->MountType > 0 && hitSpot == 1)) + { + double tempY = player->momentum.y + player->momentum.height; + player->momentum.y = block->momentum.y - player->momentum.height; + SMBX13::modPlayer::PlayerHurt(playerIdx); + player->momentum.y = tempY - player->momentum.height; + } + else SMBX13::modPlayer::PlayerHurt(playerIdx); + } + } +} + +__declspec(naked) void __stdcall runtimeHookHurtfulBlocksRaw(void) +{ + __asm { + //009A391A | 0FBF74CA 1E | movsx esi,word ptr ds:[edx+ecx*8+1E] + push esi // push these to make sure they're safe after the function call + push eax + push ecx + push edx + + lea ecx, qword ptr ss : [ebp - 0xE4] + push ecx // local Slope + movsx ecx, word ptr ss : [ebp - 0x120] + push ecx // Block Index + movsx ecx, word ptr ss : [ebp - 0x114] + push ecx // Player Index + movsx ecx, word ptr ss : [ebp - 0x54] + push ecx // hitSpot + call runtimeHookHurtfulBlocksInternal + + pop edx // we can pop these again + pop ecx + pop eax + pop esi + + movsx esi, word ptr ds : [edx + ecx * 0x8 + 0x1E] // recreates the instruction we are replacing + push 0x9A391F + ret + } +} + +static int __stdcall runtimeHookTailSwipe_9bb9c6(Block* block, short playerIdx, short stabBool, int stabDirection, Momentum* tail) +{ + // Get slope type + short slopeDirection = SMBX13::Vars::BlockSlope[block->BlockType]; + + // The following uses a slope calculation like 1.3 does + double refY = 0; + if (slopeDirection != 0) + { + // Get right or left x coordinate as relevant for the slope direction + double refX = tail->x - 1; + if (slopeDirection != 1) refX += tail->width + 2; + + // Get how far along the slope we are in the x direction + double slope = (refX - block->momentum.x) / block->momentum.width; + if (slopeDirection > 0) slope = 1.0 - slope; + if (slope < 0.0) slope = 0.0; + if (slope > 1.0) slope = 1.0; + + // Determine the y coordinate + refY = block->momentum.y + block->momentum.height - (block->momentum.height * slope) - 0.1; + } + + if (!block->IsHidden && (block->BlockType != 293 || stabBool == -1) && !block->IsInvisible2) + { + // use 1.3 check for anything but down thrust + if (stabDirection != 2 && !SMBX13::Vars::BlockIsSizable[block->BlockType] && !SMBX13::Vars::BlockNoClipping[block->BlockType]) return 0; + else if (stabDirection == 2) + { + // make floor slopes work better + if (slopeDirection != 0 && block->ContentsID == 0) return (tail->y + tail->height < refY) ? -1 : 0; + + // make sizables and semi solids work better with down thrust + if ((SMBX13::Vars::BlockIsSizable[block->BlockType] || SMBX13::Vars::BlockOnlyHitspot1[block->BlockType]) && !SMBX13::Vars::BlockNoClipping[block->BlockType]) + { + return (SMBX13::Functions::FindRunningCollision(SMBX13::Vars::Player[playerIdx].Location, *reinterpret_cast(&block->momentum)) != 1) ? -1 : 0; + } + + return 0; + } + } + + return -1; +} + +__declspec(naked) void __stdcall runtimeHookTailSwipeRaw_9bb9c6(void) +{ + __asm { + //009BB9C6 | A1 30B9B200 | mov eax,dword ptr ds:[] + push eax // push these to make sure they're safe after the function call + push ecx + push ebx + push edx + + lea ecx, dword ptr ss : [ebp - 0x20C] + push ecx // tail + mov edx, dword ptr ss : [ebp + 0x14] + movsx ecx, word ptr ds : [edx] + push ecx // stab direction + mov edx, dword ptr ss : [ebp + 0x10] + movsx ecx, word ptr ds : [edx] + push ecx // stab bool + mov edx, dword ptr ss : [ebp + 0x8] + movsx ecx, word ptr ds : [edx] + push ecx // player index + push ebx // block pointer + call runtimeHookTailSwipe_9bb9c6 + cmp eax, 0 + jne alternate_exit + + pop edx // put these back in place + pop ebx + pop ecx + pop eax + push 0x9BBA39 + ret + alternate_exit : + pop edx // put these back in place + pop ebx + pop ecx + pop eax + push 0x9BBFB5 + ret + } +} + + +static int __stdcall runtimeHookTailSwipe_9bba74(int id) +{ + return SMBX13::Vars::BlockIsSizable[id] ? -1 : 0; +} + +__declspec(naked) void __stdcall runtimeHookTailSwipeRaw_9bba74(void) +{ + __asm { + //009BBA74 | 66:837B 50 00 | cmp word ptr ds:[ebx+50],0 + push eax // push this to make sure it's safe after the function call + + movsx eax, word ptr ds : [ebx + 0x1E] + push eax // block id + call runtimeHookTailSwipe_9bba74 + cmp eax, 0 + jne alternate_exit + + pop eax //we can pop this again + cmp word ptr ds : [ebx + 50], 0 + push 0x9BBA79 + ret + alternate_exit : + pop eax + mov ax, word ptr ds : [ebx + 0x1E] // put registers in expected states before jumping + mov esi, dword ptr ss : [ebp + 0x14] + mov dword ptr ss : [ebp - 0x2A4], 0 + lea eax, dword ptr ss : [ebp - 0x2A4] + lea ecx, dword ptr ss : [ebp - 0x1A0] + lea edx, dword ptr ss : [ebp - 0x1A0] + push 0x9BBCDA + ret + } +} + +static int __stdcall runtimeHookTailSwipe_9bbd03(int id) +{ + return Blocks::GetBlockSwordBounce(id) ? -1 : 0; +} + +__declspec(naked) void __stdcall runtimeHookTailSwipeRaw_9bbd03(void) +{ + __asm { + //009BBD03 | 8B0D 9CC0B200 | mov ecx,dword ptr ds:[B2C09C] + push eax // push this to make sure it's safe after the function call + + push esi // block id + call runtimeHookTailSwipe_9bbd03 + cmp eax, 0 + jne alternate_exit + + pop eax //we can pop this again + push 0x9BBD10 + ret + alternate_exit : + pop eax //we can pop this again + push 0x9BBD40 + ret + } +} + +static int __stdcall runtimeHookTailSwipe_9bbd52(int id) +{ + return Blocks::GetBlockSwordBounce(id) ? -1 : 0; +} + +__declspec(naked) void __stdcall runtimeHookTailSwipeRaw_9bbd52(void) +{ + __asm { + //009BBD52 | 8B15 9CC0B200 | mov edx, dword ptr ds : [B2C09C] + push eax // push this to make sure it's safe after the function call + + push esi // block id + call runtimeHookTailSwipe_9bbd52 + cmp eax, 0 + je alternate_exit + + pop eax //we can pop this again + push 0x9BBD5F + ret + alternate_exit : + pop eax //we can pop this again + push 0x9BBD75 + ret + } +} + static int __stdcall runtimeHookNPCVulnerability(NPCMOB* npc, CollidersType *harmType, short* otherIdx) { if ((npc == nullptr) || (harmType == nullptr) || (otherIdx == nullptr)) diff --git a/LunaDll/SMBXInternal/Blocks.cpp b/LunaDll/SMBXInternal/Blocks.cpp index bea0e4a3..f221ab6b 100644 --- a/LunaDll/SMBXInternal/Blocks.cpp +++ b/LunaDll/SMBXInternal/Blocks.cpp @@ -134,6 +134,8 @@ static int16_t blockprop_bumpable[Block::MAX_ID + 1] = { 0 }; static int16_t blockprop_playerfilter[Block::MAX_ID + 1] = { 0 }; static int16_t blockprop_npcfilter[Block::MAX_ID + 1] = { 0 }; static int16_t blockprop_walkpaststair[Block::MAX_ID + 1] = { 0 }; // whether to walk past semisolid slopes (like ghost house stairs) +static int16_t blockprop_swordbounce[Block::MAX_ID + 1] = { 0 }; +static uint8_t blockprop_hurtside[Block::MAX_ID + 1] = { 0 }; void Blocks::InitProperties() { for (int id = 1; id <= Block::MAX_ID; id++) @@ -142,6 +144,8 @@ void Blocks::InitProperties() { SetBlockPlayerFilter(id, 0); SetBlockNPCFilter(id, 0); SetBlockWalkPastStair(id, false); + SetBlockHurtSide(id, 0x00); + SetBlockSwordBounce(id, false); } // Default game config @@ -172,6 +176,34 @@ void Blocks::InitProperties() { SetBlockPlayerFilter(628, 3); SetBlockPlayerFilter(629, 4); SetBlockPlayerFilter(632, 5); + + SetBlockHurtSide(109, (0x80 | 0x40)); + SetBlockHurtSide(110, (0x80 | 0x02)); + SetBlockHurtSide(267, (0x80 | 0x04)); + SetBlockHurtSide(268, (0x80 | 0x08)); + SetBlockHurtSide(269, (0x80 | 0x10)); + SetBlockHurtSide(407, (0x80 | 0x08)); + SetBlockHurtSide(408, (0x80 | 0x02)); + SetBlockHurtSide(428, (0x80 | 0x04)); + SetBlockHurtSide(429, (0x80 | 0x10)); + SetBlockHurtSide(430, (0x80 | 0x02)); + SetBlockHurtSide(431, (0x80 | 0x08)); + SetBlockHurtSide(511, (0x80 | 0x02)); + SetBlockHurtSide(598, 0x40); + + SetBlockSwordBounce(109, true); + SetBlockSwordBounce(110, true); + SetBlockSwordBounce(267, true); + SetBlockSwordBounce(268, true); + SetBlockSwordBounce(269, true); + SetBlockSwordBounce(407, true); + SetBlockSwordBounce(408, true); + SetBlockSwordBounce(428, true); + SetBlockSwordBounce(429, true); + SetBlockSwordBounce(430, true); + SetBlockSwordBounce(431, true); + SetBlockSwordBounce(511, true); + SetBlockSwordBounce(598, true); } bool Blocks::GetBlockBumpable(int id) { @@ -218,6 +250,26 @@ void Blocks::SetBlockWalkPastStair(int id, bool walkpaststair) { blockprop_walkpaststair[id] = walkpaststair ? -1 : 0; } +unsigned char Blocks::GetBlockHurtSide(int id) { + if ((id < 1) || (id > Block::MAX_ID)) return false; + return blockprop_hurtside[id]; +} + +void Blocks::SetBlockHurtSide(int id, unsigned char options) { + if ((id < 1) || (id > Block::MAX_ID)) return; + blockprop_hurtside[id] = options; +} + +bool Blocks::GetBlockSwordBounce(int id) { + if ((id < 1) || (id > Block::MAX_ID)) return false; + return (blockprop_swordbounce[id] != 0); +} + +void Blocks::SetBlockSwordBounce(int id, bool swordbounce) { + if ((id < 1) || (id > Block::MAX_ID)) return; + blockprop_swordbounce[id] = swordbounce ? -1 : 0; +} + // Getter for address of Block property arrays uintptr_t Blocks::GetPropertyTableAddress(const std::string& s) { @@ -237,6 +289,14 @@ uintptr_t Blocks::GetPropertyTableAddress(const std::string& s) { return reinterpret_cast(blockprop_walkpaststair); } + else if (s == "hurtside") + { + return reinterpret_cast(blockprop_hurtside); + } + else if (s == "swordbounce") + { + return reinterpret_cast(blockprop_swordbounce); + } else { return 0; diff --git a/LunaDll/SMBXInternal/Blocks.h b/LunaDll/SMBXInternal/Blocks.h index 1ffdb660..6cddaa5f 100644 --- a/LunaDll/SMBXInternal/Blocks.h +++ b/LunaDll/SMBXInternal/Blocks.h @@ -108,6 +108,10 @@ namespace Blocks { void SetBlockNPCFilter(int id, short npcId); bool GetBlockWalkPastStair(int id); void SetBlockWalkPastStair(int id, bool walkpaststair); + unsigned char GetBlockHurtSide(int id); + void SetBlockHurtSide(int id, unsigned char options); + bool GetBlockSwordBounce(int id); + void SetBlockSwordBounce(int id, bool mountsafe); uintptr_t GetPropertyTableAddress(const std::string& s); bool FilterSemisolidSlopeCollision(Momentum* entityMomentum, Momentum* speed, int blockIdx, int entityBottomCollisionTimer, bool standingOnSlope); From 63e00bde175808e67bd9c6d2eb1ae0508738266e Mon Sep 17 00:00:00 2001 From: krazybluemonkey <39660982+krazybluemonkey@users.noreply.github.com> Date: Wed, 21 Feb 2024 01:38:45 -0700 Subject: [PATCH 2/3] quick dupe erase --- LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp b/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp index 7709bb80..5ae52be1 100644 --- a/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp +++ b/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp @@ -1,6 +1,5 @@ #include #include "../../Misc/CollisionMatrix.h" -#include "../../Misc/CollisionMatrix.h" #include "string.h" #include "../../Globals.h" #include "../RuntimeHook.h" From 0ce7e71dd1de84e5d19ab5bc4865baaa8acd3ad0 Mon Sep 17 00:00:00 2001 From: krazybluemonkey Date: Sun, 4 May 2025 07:26:26 -0600 Subject: [PATCH 3/3] improvements & additions - code tidied up & commented as suggested by supermario1313 - removed flag 0x40's initial use as it was deemed superfluous - moved mount safe checks from 0x80 to 0x40 - added gDisableInvisibleHurtBlockBugFix --- LunaDll/GlobalFuncs.cpp | 2 + LunaDll/Globals.cpp | 3 + LunaDll/Globals.h | 3 + LunaDll/LuaMain/LuaProxyFFI.cpp | 5 + LunaDll/LuaMain/LunaLuaMain.cpp | 1 + LunaDll/Misc/RuntimeHook.h | 5 +- .../RuntimeHookGeneral.cpp | 24 ++-- .../RuntimeHookHooks.cpp | 115 ++++++------------ LunaDll/SMBXInternal/Blocks.cpp | 26 ++-- 9 files changed, 87 insertions(+), 97 deletions(-) diff --git a/LunaDll/GlobalFuncs.cpp b/LunaDll/GlobalFuncs.cpp index 25fac006..6e1d1442 100644 --- a/LunaDll/GlobalFuncs.cpp +++ b/LunaDll/GlobalFuncs.cpp @@ -316,6 +316,8 @@ void ResetLunaModule() gLastRunPress = 0; gRunTapped = 0; + gHurtBlockHitspot = 0; + gLevelEnum = Invalid; g_EventHandler.reset(); diff --git a/LunaDll/Globals.cpp b/LunaDll/Globals.cpp index 2bd3e777..7190f925 100644 --- a/LunaDll/Globals.cpp +++ b/LunaDll/Globals.cpp @@ -34,6 +34,7 @@ bool gRenderBackgroundFlag = true; // Settings for glitch fixes bool gDisablePlayerFilterBounceFix = false; bool gDisableNPCRespawnBugFix = false; +bool gDisableInvisibleHurtBlockBugFix = false; // Other gameplay settings bool gLavaIsWeak = false; @@ -66,6 +67,8 @@ HDC ghMemDC; // General use screen-compatible DC HBITMAP ghGeneralDIB; // General use screen-sized DIB DWORD* gpScreenBits; // Pointer to screen bits for general use DIB +int gHurtBlockHitspot; + // Mouse cursor HCURSOR gCustomCursor = nullptr; bool gCustomCursorHide = false; diff --git a/LunaDll/Globals.h b/LunaDll/Globals.h index 0af4b23c..49d0a06f 100644 --- a/LunaDll/Globals.h +++ b/LunaDll/Globals.h @@ -107,6 +107,7 @@ extern bool gRenderBackgroundFlag; // Settings for glitch fixes extern bool gDisablePlayerFilterBounceFix; extern bool gDisableNPCRespawnBugFix; +extern bool gDisableInvisibleHurtBlockBugFix; // Other gameplay settings extern bool gLavaIsWeak; @@ -137,6 +138,8 @@ extern int gRunTapped; extern BYTE gKeyState[256]; +extern int gHurtBlockHitspot; + extern HDC ghMemDC; // General-use screen-compatible DC extern HBITMAP ghGeneralDIB; // General-use screen-sized DIB extern DWORD* gpScreenBits; // Pointer to screen bits for general use DIB diff --git a/LunaDll/LuaMain/LuaProxyFFI.cpp b/LunaDll/LuaMain/LuaProxyFFI.cpp index add95bd3..5f826ff1 100644 --- a/LunaDll/LuaMain/LuaProxyFFI.cpp +++ b/LunaDll/LuaMain/LuaProxyFFI.cpp @@ -592,6 +592,11 @@ typedef struct ExtendedPlayerFields_\ gDisableNPCRespawnBugFix = !enable; } + FFI_EXPORT(void) LunaLuaSetInvisibleHurtBlockBugFix(bool enable) + { + gDisableInvisibleHurtBlockBugFix = !enable; + } + FFI_EXPORT(void) LunaLuaSetFenceBugFix(bool enable) { if (enable) { gFenceFixes.Apply(); diff --git a/LunaDll/LuaMain/LunaLuaMain.cpp b/LunaDll/LuaMain/LunaLuaMain.cpp index 819415e0..e119fc35 100644 --- a/LunaDll/LuaMain/LunaLuaMain.cpp +++ b/LunaDll/LuaMain/LunaLuaMain.cpp @@ -130,6 +130,7 @@ bool CLunaLua::shutdown() gRenderBackgroundFlag = true; gDisablePlayerFilterBounceFix = false; gDisableNPCRespawnBugFix = false; + gDisableInvisibleHurtBlockBugFix = false; gLavaIsWeak = false; gCamerasInitialised = false; gDisablePlayerDownwardClipFix.Apply(); diff --git a/LunaDll/Misc/RuntimeHook.h b/LunaDll/Misc/RuntimeHook.h index 2d727ddd..cf7558b5 100644 --- a/LunaDll/Misc/RuntimeHook.h +++ b/LunaDll/Misc/RuntimeHook.h @@ -339,10 +339,11 @@ void __stdcall runtimeHookSmbxCheckWindowedRaw(void); void __stdcall runtimeHookBlockBumpableRaw(void); void __stdcall runtimeHookHurtfulBlocksRaw(void); +void __stdcall runtimeHookHurtfulBlocks_9A1843(int hitspot); +void __stdcall runtimeHookHurtfulBlocksRaw_9A1843(void); void __stdcall runtimeHookTailSwipeRaw_9bb9c6(void); void __stdcall runtimeHookTailSwipeRaw_9bba74(void); -void __stdcall runtimeHookTailSwipeRaw_9bbd03(void); -void __stdcall runtimeHookTailSwipeRaw_9bbd52(void); +int __stdcall runtimeHookSwordBounceable(int id); void __stdcall runtimeHookNPCVulnerabilityRaw(void); void __stdcall runtimeHookNPCSpinjumpSafeRaw(void); diff --git a/LunaDll/Misc/RuntimeHookComponents/RuntimeHookGeneral.cpp b/LunaDll/Misc/RuntimeHookComponents/RuntimeHookGeneral.cpp index c55add6e..9c3a71d3 100644 --- a/LunaDll/Misc/RuntimeHookComponents/RuntimeHookGeneral.cpp +++ b/LunaDll/Misc/RuntimeHookComponents/RuntimeHookGeneral.cpp @@ -1741,13 +1741,23 @@ void TrySkipPatch() PATCH(0x96ADD7).CALL(runtimeHookSmbxCheckWindowedRaw).NOP_PAD_TO_SIZE<8>().Apply(); PATCH(0x9DB1D8).JMP(runtimeHookBlockBumpableRaw).NOP_PAD_TO_SIZE<6>().Apply(); - // Hurtful Blocks Hook - PATCH(0x9A1843).JMP(0x9A1BDA).NOP_PAD_TO_SIZE<919>().Apply(); - PATCH(0x9A391A).JMP(runtimeHookHurtfulBlocksRaw).Apply(); - PATCH(0x9BB9C6).JMP(runtimeHookTailSwipeRaw_9bb9c6).NOP_PAD_TO_SIZE<115>().Apply(); - PATCH(0x9BBA74).JMP(runtimeHookTailSwipeRaw_9bba74).Apply(); - PATCH(0x9BBD03).JMP(runtimeHookTailSwipeRaw_9bbd03).NOP_PAD_TO_SIZE<13>().Apply(); - PATCH(0x9BBD52).JMP(runtimeHookTailSwipeRaw_9bbd52).NOP_PAD_TO_SIZE<13>().Apply(); + // Hurtful Blocks Hooks + PATCH(0x9A1843).JMP(runtimeHookHurtfulBlocksRaw_9A1843).NOP_PAD_TO_SIZE<919>().Apply(); // grabs the hit spot from the check for hurtful blocks at line 2036 of modPlayer.bas and jumps to line 2058, nop'ing the lines + PATCH(0x9A391A).CALL(runtimeHookHurtfulBlocksRaw).Apply(); // function to replace the check at line 2036, put at line 2231 + PATCH(0x9BB9C6).JMP(runtimeHookTailSwipeRaw_9bb9c6).NOP_PAD_TO_SIZE<115>().Apply(); // replaces the condition in modPlayer.bas line 5103 + PATCH(0x9BBA74).JMP(runtimeHookTailSwipeRaw_9bba74).Apply(); // inserts a check between lines 5105 and 5106 of modPlayer.bas, if the stabbed/tailed block is sizeable, goto line 5117 + PATCH(0x9BBD03) // replaces the BlockHurts check at line 5126 by a Blocks::GetBlockSwordBounce check + .PUSH_ESI() + .CALL(runtimeHookSwordBounceable) + .bytes(0x85, 0xC0) // test eax, eax + .bytes(0x0F, 0x1F, 0x00) // nop + .Apply(); + PATCH(0x9BBD52) // replaces the BlockHurts check at line 5127 by a Blocks::GetBlockSwordBounce check + .PUSH_ESI() + .CALL(runtimeHookSwordBounceable) + .bytes(0x85, 0xC0) // test eax, eax + .bytes(0x0F, 0x1F, 0x00) // nop + .Apply(); PATCH(0xA28FE3).JMP(runtimeHookNPCVulnerabilityRaw).Apply(); diff --git a/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp b/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp index 2bcc94de..f97d909c 100644 --- a/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp +++ b/LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp @@ -1748,58 +1748,84 @@ __declspec(naked) void __stdcall runtimeHookBlockBumpableRaw(void) } } -static void __stdcall runtimeHookHurtfulBlocksInternal(int hitSpot, short playerIdx, int blockIdx, const double& slope) +static void __stdcall runtimeHookHurtfulBlocks_9A1843(int hitspot) +{ + gHurtBlockHitspot = hitspot; +} + + +__declspec(naked) void __stdcall runtimeHookHurtfulBlocksRaw_9A1843(void) +{ + __asm { + + push ecx + + movsx ecx, word ptr ss : [ebp - 0x54] + push ecx // hitSpot + call runtimeHookHurtfulBlocks_9A1843 + + pop ecx + push 0x9A1BDA + ret + } +} + +static void __stdcall runtimeHookHurtfulBlocksInternal(short playerIdx, int blockIdx, const double& slope) { PlayerMOB* player = Player::Get(playerIdx); Block* block = Block::GetRaw(blockIdx); + int hitSpot = gHurtBlockHitspot; // don't worry about lava if (SMBX13::Vars::BlockHurts[block->BlockType] && !SMBX13::Vars::BlockKills[block->BlockType]) { short floorSlope = SMBX13::Vars::BlockSlope[block->BlockType]; + short ceilingSlope = SMBX13::Vars::BlockSlope2[block->BlockType]; unsigned char flags = Blocks::GetBlockHurtSide(block->BlockType); bool tempBool = false; + // if we're on a slope, we haven't actually hit anything + if (floorSlope != 0 || ceilingSlope != 0) hitSpot = 0; // stop if we shouldn't be hurt - if (player->MountType == 2 || ((hitSpot == 1 || floorSlope != 0 && player->SlopeRelated == blockIdx) && player->MountType != 0) && (flags & 0x80) != 0) return; + if (player->MountType == 2 || ((hitSpot == 1 || floorSlope != 0 && player->SlopeRelated == blockIdx) && player->MountType != 0) && (flags & 0x40) != 0) return; // check hitspot & collision config for blocks and hurt as needed switch (hitSpot) { case 0: // cancelled (slopes, sizables, semi solids) - tempBool = ((flags & 0x01) != 0 || (flags & 0x40) != 0); + tempBool = ((flags & 0x01) != 0 ); break; case 1: // top - tempBool = ((flags & 0x02) != 0 || (flags & 0x40) != 0); + tempBool = ((flags & 0x02) != 0); break; case 2: // right - tempBool = ((flags & 0x04) != 0 || (flags & 0x40) != 0); + tempBool = ((flags & 0x04) != 0); break; case 3: // bottom - tempBool = ((flags & 0x08) != 0 || (flags & 0x40) != 0); + tempBool = ((flags & 0x08) != 0); break; case 4: // left - tempBool = ((flags & 0x10) != 0 || (flags & 0x40) != 0); + tempBool = ((flags & 0x10) != 0); break; case 5: // inside/zipping - tempBool = ((flags & 0x20) != 0 || (flags & 0x40) != 0); + tempBool = ((flags & 0x20) != 0); break; } // floor slope should harm - if ((floorSlope != 0 && ((flags & 0x02) != 0 || (flags & 0x40) != 0) && player->SlopeRelated == blockIdx)) tempBool = true; + if ((floorSlope != 0 && ((flags & 0x02) != 0) && player->SlopeRelated == blockIdx)) tempBool = true; // ceiling slope should harm - if ((SMBX13::Vars::BlockSlope2[block->BlockType] && ((flags & 0x08) != 0 || (flags & 0x40) != 0) && player->momentum.y <= block->momentum.y + block->momentum.height - (block->momentum.height * slope))) + if ((ceilingSlope != 0 && ((flags & 0x08) != 0) && player->momentum.y <= block->momentum.y + block->momentum.height - (block->momentum.height * slope))) { tempBool = true; } // if set as invisible, don't harm (potential compatibility break) - if (block->IsInvisible2) tempBool = false; + if (block->IsInvisible2 && !gDisableInvisibleHurtBlockBugFix) tempBool = false; if (tempBool) { - if ((player->MountType > 0 && hitSpot == 1)) + if ((player->MountType > 0 && hitSpot == 1)) // fixes yoshi clipping into the block if not mount safe and colliding from above { double tempY = player->momentum.y + player->momentum.height; player->momentum.y = block->momentum.y - player->momentum.height; @@ -1815,8 +1841,7 @@ __declspec(naked) void __stdcall runtimeHookHurtfulBlocksRaw(void) { __asm { //009A391A | 0FBF74CA 1E | movsx esi,word ptr ds:[edx+ecx*8+1E] - push esi // push these to make sure they're safe after the function call - push eax + push eax // push these to make sure they're safe after the function call push ecx push edx @@ -1826,17 +1851,13 @@ __declspec(naked) void __stdcall runtimeHookHurtfulBlocksRaw(void) push ecx // Block Index movsx ecx, word ptr ss : [ebp - 0x114] push ecx // Player Index - movsx ecx, word ptr ss : [ebp - 0x54] - push ecx // hitSpot call runtimeHookHurtfulBlocksInternal pop edx // we can pop these again pop ecx pop eax - pop esi movsx esi, word ptr ds : [edx + ecx * 0x8 + 0x1E] // recreates the instruction we are replacing - push 0x9A391F ret } } @@ -1891,9 +1912,6 @@ __declspec(naked) void __stdcall runtimeHookTailSwipeRaw_9bb9c6(void) __asm { //009BB9C6 | A1 30B9B200 | mov eax,dword ptr ds:[] push eax // push these to make sure they're safe after the function call - push ecx - push ebx - push edx lea ecx, dword ptr ss : [ebp - 0x20C] push ecx // tail @@ -1911,16 +1929,10 @@ __declspec(naked) void __stdcall runtimeHookTailSwipeRaw_9bb9c6(void) cmp eax, 0 jne alternate_exit - pop edx // put these back in place - pop ebx - pop ecx pop eax push 0x9BBA39 ret alternate_exit : - pop edx // put these back in place - pop ebx - pop ecx pop eax push 0x9BBFB5 ret @@ -1962,58 +1974,11 @@ __declspec(naked) void __stdcall runtimeHookTailSwipeRaw_9bba74(void) } } -static int __stdcall runtimeHookTailSwipe_9bbd03(int id) -{ - return Blocks::GetBlockSwordBounce(id) ? -1 : 0; -} - -__declspec(naked) void __stdcall runtimeHookTailSwipeRaw_9bbd03(void) -{ - __asm { - //009BBD03 | 8B0D 9CC0B200 | mov ecx,dword ptr ds:[B2C09C] - push eax // push this to make sure it's safe after the function call - - push esi // block id - call runtimeHookTailSwipe_9bbd03 - cmp eax, 0 - jne alternate_exit - - pop eax //we can pop this again - push 0x9BBD10 - ret - alternate_exit : - pop eax //we can pop this again - push 0x9BBD40 - ret - } -} - -static int __stdcall runtimeHookTailSwipe_9bbd52(int id) +int __stdcall runtimeHookSwordBounceable(int id) { return Blocks::GetBlockSwordBounce(id) ? -1 : 0; } -__declspec(naked) void __stdcall runtimeHookTailSwipeRaw_9bbd52(void) -{ - __asm { - //009BBD52 | 8B15 9CC0B200 | mov edx, dword ptr ds : [B2C09C] - push eax // push this to make sure it's safe after the function call - - push esi // block id - call runtimeHookTailSwipe_9bbd52 - cmp eax, 0 - je alternate_exit - - pop eax //we can pop this again - push 0x9BBD5F - ret - alternate_exit : - pop eax //we can pop this again - push 0x9BBD75 - ret - } -} - static int __stdcall runtimeHookNPCVulnerability(NPCMOB* npc, CollidersType *harmType, short* otherIdx) { if ((npc == nullptr) || (harmType == nullptr) || (otherIdx == nullptr)) diff --git a/LunaDll/SMBXInternal/Blocks.cpp b/LunaDll/SMBXInternal/Blocks.cpp index f221ab6b..ac19c83f 100644 --- a/LunaDll/SMBXInternal/Blocks.cpp +++ b/LunaDll/SMBXInternal/Blocks.cpp @@ -177,19 +177,19 @@ void Blocks::InitProperties() { SetBlockPlayerFilter(629, 4); SetBlockPlayerFilter(632, 5); - SetBlockHurtSide(109, (0x80 | 0x40)); - SetBlockHurtSide(110, (0x80 | 0x02)); - SetBlockHurtSide(267, (0x80 | 0x04)); - SetBlockHurtSide(268, (0x80 | 0x08)); - SetBlockHurtSide(269, (0x80 | 0x10)); - SetBlockHurtSide(407, (0x80 | 0x08)); - SetBlockHurtSide(408, (0x80 | 0x02)); - SetBlockHurtSide(428, (0x80 | 0x04)); - SetBlockHurtSide(429, (0x80 | 0x10)); - SetBlockHurtSide(430, (0x80 | 0x02)); - SetBlockHurtSide(431, (0x80 | 0x08)); - SetBlockHurtSide(511, (0x80 | 0x02)); - SetBlockHurtSide(598, 0x40); + SetBlockHurtSide(109, (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40)); + SetBlockHurtSide(110, (0x02 | 0x40)); + SetBlockHurtSide(267, (0x04 | 0x40)); + SetBlockHurtSide(268, (0x08 | 0x40)); + SetBlockHurtSide(269, (0x10 | 0x40)); + SetBlockHurtSide(407, (0x08 | 0x40)); + SetBlockHurtSide(408, (0x02 | 0x40)); + SetBlockHurtSide(428, (0x04 | 0x40)); + SetBlockHurtSide(429, (0x10 | 0x40)); + SetBlockHurtSide(430, (0x02 | 0x40)); + SetBlockHurtSide(431, (0x08 | 0x40)); + SetBlockHurtSide(511, (0x02 | 0x40)); + SetBlockHurtSide(598, (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20)); SetBlockSwordBounce(109, true); SetBlockSwordBounce(110, true);