Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions LunaDll/GlobalFuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,8 @@ void ResetLunaModule()
gLastRunPress = 0;
gRunTapped = 0;

gHurtBlockHitspot = 0;

gLevelEnum = Invalid;

g_EventHandler.reset();
Expand Down
3 changes: 3 additions & 0 deletions LunaDll/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions LunaDll/Globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions LunaDll/LuaMain/LuaProxyFFI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions LunaDll/LuaMain/LunaLuaMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ bool CLunaLua::shutdown()
gRenderBackgroundFlag = true;
gDisablePlayerFilterBounceFix = false;
gDisableNPCRespawnBugFix = false;
gDisableInvisibleHurtBlockBugFix = false;
gLavaIsWeak = false;
gCamerasInitialised = false;
gDisablePlayerDownwardClipFix.Apply();
Expand Down
2 changes: 1 addition & 1 deletion LunaDll/Misc/NpcIdExtender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions LunaDll/Misc/RuntimeHook.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,14 @@ void __stdcall runtimeHookChangeResolution(void* arg1, void* arg2, void* arg3, v
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);
int __stdcall runtimeHookSwordBounceable(int id);

void __stdcall runtimeHookNPCVulnerabilityRaw(void);
void __stdcall runtimeHookNPCSpinjumpSafeRaw(void);
void __stdcall runtimeHookNPCNoWaterPhysicsRaw(void);
Expand Down
17 changes: 17 additions & 0 deletions LunaDll/Misc/RuntimeHookComponents/RuntimeHookGeneral.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1741,6 +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 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();

Expand Down
233 changes: 233 additions & 0 deletions LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include "../../SMBXInternal/Blocks.h"
#include "../../SMBXInternal/Level.h"
#include "../../SMBXInternal/Sound.h"
#include "../../SMBXInternal/Functions.h"
#include "../../SMBXInternal/Variables.h"

#include "../PerfTracker.h"

Expand Down Expand Up @@ -1746,6 +1748,237 @@ __declspec(naked) void __stdcall runtimeHookBlockBumpableRaw(void)
}
}

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 & 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 );
break;
case 1: // top
tempBool = ((flags & 0x02) != 0);
break;
case 2: // right
tempBool = ((flags & 0x04) != 0);
break;
case 3: // bottom
tempBool = ((flags & 0x08) != 0);
break;
case 4: // left
tempBool = ((flags & 0x10) != 0);
break;
case 5: // inside/zipping
tempBool = ((flags & 0x20) != 0);
break;
}

// floor slope should harm
if ((floorSlope != 0 && ((flags & 0x02) != 0) && player->SlopeRelated == blockIdx)) tempBool = true;

// ceiling slope should harm
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 && !gDisableInvisibleHurtBlockBugFix) tempBool = false;

if (tempBool)
{
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;
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 eax // push these to make sure they're safe after the function call
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
call runtimeHookHurtfulBlocksInternal

pop edx // we can pop these again
pop ecx
pop eax

movsx esi, word ptr ds : [edx + ecx * 0x8 + 0x1E] // recreates the instruction we are replacing
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<SMBX13::Types::Location_t*>(&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:[<blockdef_isResizeableBlock>]
push eax // push these to make sure they're safe after the function call

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 eax
push 0x9BBA39
ret
alternate_exit :
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
}
}

int __stdcall runtimeHookSwordBounceable(int id)
{
return Blocks::GetBlockSwordBounce(id) ? -1 : 0;
}

static int __stdcall runtimeHookNPCVulnerability(NPCMOB* npc, CollidersType *harmType, short* otherIdx)
{
if ((npc == nullptr) || (harmType == nullptr) || (otherIdx == nullptr))
Expand Down
Loading