diff --git a/cmake/compiler-flags-gl.txt b/cmake/compiler-flags-gl.txt index 848d70de..99b6f039 100644 --- a/cmake/compiler-flags-gl.txt +++ b/cmake/compiler-flags-gl.txt @@ -7,3 +7,5 @@ src/OpenSHC/IO/ResourceManager/swapMapDataWithNextMap.cpp src/OpenSHC/UI/Rendering/WindowAndDirectDraw/takeScreenshot.cpp src/OpenSHC/IO/ResourceManager/readFirstPartOfCurrentResourceIntoMemory.cpp src/OpenSHC/IO/ResourceManager/readNextPartOfCurrentResourceIntoMemory.cpp +src/OpenSHC/Map/Navigation/DirectionAlgorithmState/getMouseVectorLengthBasedOnDirection.cpp +src/OpenSHC/Input/MouseState/updateRightDragCameraControl.cpp diff --git a/src/OpenSHC/Input/Mouse/ClickTypeBitMaskEnumByte.hpp b/src/OpenSHC/Input/Mouse/ClickTypeBitMaskEnumByte.hpp index 2f243aff..9e337c8c 100644 --- a/src/OpenSHC/Input/Mouse/ClickTypeBitMaskEnumByte.hpp +++ b/src/OpenSHC/Input/Mouse/ClickTypeBitMaskEnumByte.hpp @@ -13,7 +13,7 @@ namespace OpenSHC { namespace Input { namespace Mouse { - typedef byte ClickTypeBitMaskEnumByte; + typedef char ClickTypeBitMaskEnumByte; static_assert_cpp98_obj(sizeof(ClickTypeBitMaskEnumByte) == 1, ClickTypeBitMaskEnumByte); } // namespace Mouse diff --git a/src/OpenSHC/Input/MouseState.hpp b/src/OpenSHC/Input/MouseState.hpp index 860ce5c8..31b8e34e 100644 --- a/src/OpenSHC/Input/MouseState.hpp +++ b/src/OpenSHC/Input/MouseState.hpp @@ -32,10 +32,10 @@ namespace Input { undefined4 time0; // 0x00000004 length: 4 BOOLEnum anyActivity; // 0x00000008 length: 4 undefined4 flag; // 0x0000000C length: 4 - undefined4 screenSpaceX; // 0x00000010 length: 4 - undefined4 screenSpaceY; // 0x00000014 length: 4 - undefined4 cursorPosX; // 0x00000018 length: 4 - undefined4 cursorPosY; // 0x0000001C length: 4 + int screenSpaceX; // 0x00000010 length: 4 + int screenSpaceY; // 0x00000014 length: 4 + int cursorPosX; // 0x00000018 length: 4 + int cursorPosY; // 0x0000001C length: 4 undefined4 previousScreenSpaceX; // 0x00000020 length: 4 undefined4 previousScreenSpaceY; // 0x00000024 length: 4 BOOLEnum draggingStopped; // 0x00000028 length: 4 @@ -64,7 +64,7 @@ namespace Input { int previewEnabled; // 0x0000009C length: 4 MouseXYUUStruct mouseXY[10]; // 0x000000A0 length: 160 int mouseXY8[10]; // 0x00000140 length: 40 - undefined4 index; // 0x00000168 length: 4 + int index; // 0x00000168 length: 4 undefined4 storedScreenSpaceX; // 0x0000016C length: 4 undefined4 storedScreenSpaceY; // 0x00000170 length: 4 undefined4 field42_0x174; // 0x00000174 length: 4 @@ -81,8 +81,8 @@ namespace Input { undefined4 currentTime1; // 0x000001A0 length: 4 undefined4 currentTime2; // 0x000001A4 length: 4 undefined4 currentTime3; // 0x000001A8 length: 4 - undefined4 field56_0x1ac; // 0x000001AC length: 4 - undefined4 field57_0x1b0; // 0x000001B0 length: 4 + int field56_0x1ac; // 0x000001AC length: 4 + int field57_0x1b0; // 0x000001B0 length: 4 undefined4 field58_0x1b4; // 0x000001B4 length: 4 undefined4 field59_0x1b8; // 0x000001B8 length: 4 undefined4 field60_0x1bc; // 0x000001BC length: 4 @@ -98,9 +98,9 @@ namespace Input { int field70_0x1e4; // 0x000001E4 length: 4 undefined1 padding_0x1e8[8]; // 0x000001E8 length: 8 undefined4 cursorType; // 0x000001F0 length: 4 - undefined2 mouseWindowX; // 0x000001F4 length: 2 - undefined2 mouseWindowY; // 0x000001F6 length: 2 - undefined2 mouseWheelDelta; // 0x000001F8 length: 2 + short mouseWindowX; // 0x000001F4 length: 2 + short mouseWindowY; // 0x000001F6 length: 2 + short mouseWheelDelta; // 0x000001F8 length: 2 ClickTypeBitMaskEnumByte mouseClickTypes; // 0x000001FA length: 1 undefined1 padding1; // 0x000001FB length: 1 HCURSOR currentDefaultCursor; // 0x000001FC length: 4 diff --git a/src/OpenSHC/Input/MouseState/Constructor_MouseState.cpp b/src/OpenSHC/Input/MouseState/Constructor_MouseState.cpp new file mode 100644 index 00000000..9863654f --- /dev/null +++ b/src/OpenSHC/Input/MouseState/Constructor_MouseState.cpp @@ -0,0 +1,22 @@ +#include "../MouseState.func.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x004709B0 + MouseState* MouseState::Constructor_MouseState() + { + this->time0 = timeGetTime(); + MACRO_CALL_MEMBER(MouseState_Func::storeXYAndResetMouseState, this)(); + this->previewEnabled = 0; + this->flag = 0; + this->resetPending = 0; + this->waitCursorToggle = 0; + this->cursorType = 0; + this->field70_0x1e4 = 0; + this->field68_0x1dc = -1; + return this; + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/beginPointSelectionBox.cpp b/src/OpenSHC/Input/MouseState/beginPointSelectionBox.cpp new file mode 100644 index 00000000..09f57c5f --- /dev/null +++ b/src/OpenSHC/Input/MouseState/beginPointSelectionBox.cpp @@ -0,0 +1,42 @@ +#include "../MouseState.func.hpp" + +#include "OpenSHC/Globals/DAT_MouseState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x00468420 + void MouseState::beginPointSelectionBox() + { + this->previousSelectionBox.left + = this->screenSpaceX + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX - 1; + this->previousSelectionBox.top + = this->screenSpaceY + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY - 1; + this->previousSelectionBox.right + = this->screenSpaceX + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX + 1; + this->previousSelectionBox.bottom + = this->screenSpaceY + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY + 1; + + if (DAT_ViewportRenderState::instance.viewportState.isZoomedOutUnk) { + this->selectionBox.left + = (this->screenSpaceX + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX) * 2 - 2; + this->selectionBox.top + = (this->screenSpaceY + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY) * 2 - 2; + this->selectionBox.right + = (this->screenSpaceX + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX) * 2 + 2; + this->selectionBox.bottom + = (this->screenSpaceY + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY) * 2 + 2; + } else { + this->selectionBox.left = this->previousSelectionBox.left; + this->selectionBox.top = this->previousSelectionBox.top; + this->selectionBox.right = this->previousSelectionBox.right; + this->selectionBox.bottom = this->previousSelectionBox.bottom; + } + + DAT_MouseState::instance.field31_0x94 = 0; + DAT_MouseState::instance.selectionBoxMode = 1; + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/drawMouseBasedBox.cpp b/src/OpenSHC/Input/MouseState/drawMouseBasedBox.cpp new file mode 100644 index 00000000..19458d23 --- /dev/null +++ b/src/OpenSHC/Input/MouseState/drawMouseBasedBox.cpp @@ -0,0 +1,39 @@ +#include "../MouseState.func.hpp" + +#include "OpenSHC/UI/Rendering/PencilRenderCore.func.hpp" + +#include "OpenSHC/Globals/COL_BLACK.hpp" +#include "OpenSHC/Globals/COL_WHITE.hpp" +#include "OpenSHC/Globals/DAT_MouseState.hpp" +#include "OpenSHC/Globals/DAT_PencilRenderCore.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x00472A90 + void MouseState::drawMouseBasedBox() + { + if (!DAT_MouseState::instance.field31_0x94) { + return; + } + if (!DAT_MouseState::instance.leftClickState && !DAT_MouseState::instance.draggingStopped) { + MACRO_CALL_MEMBER(MouseState_Func::resetMouseCursorState, this)(); + return; + } + int left = this->previousSelectionBox.left; + int right = this->previousSelectionBox.right; + int top = this->previousSelectionBox.top; + int bottom = this->previousSelectionBox.bottom; + + DAT_PencilRenderCore::instance.surfaceTarget = Rendering::Enums::RT_MAP_GAME; + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawBorderBox, DAT_PencilRenderCore::ptr)( + left, top, right, bottom, COL_BLACK::instance.shortValue); + + MACRO_CALL_MEMBER(UI::Rendering::PencilRenderCore_Func::drawBorderBox, DAT_PencilRenderCore::ptr)( + left + 1, top + 1, right + -1, bottom + -1, COL_WHITE::instance.shortValue); + + DAT_PencilRenderCore::instance.surfaceTarget = Rendering::Enums::RT_SCREEN_MENU; + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/extendSelectionBoxToMouse.cpp b/src/OpenSHC/Input/MouseState/extendSelectionBoxToMouse.cpp new file mode 100644 index 00000000..34aa98ce --- /dev/null +++ b/src/OpenSHC/Input/MouseState/extendSelectionBoxToMouse.cpp @@ -0,0 +1,42 @@ +#include "../MouseState.func.hpp" + +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_MouseState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x00470B30 + void MouseState::extendSelectionBoxToMouse() + { + this->previousSelectionBox.right + = this->screenSpaceX + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX; + this->previousSelectionBox.bottom + = this->screenSpaceY + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY; + + if (DAT_ViewportRenderState::instance.viewportState.isZoomedOutUnk) { + this->selectionBox.right + = (DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX + this->screenSpaceX) * 2 + 2; + this->selectionBox.bottom + = (DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY + this->screenSpaceY) * 2 + 2; + } else { + this->selectionBox.right = this->previousSelectionBox.right; + this->selectionBox.bottom = this->previousSelectionBox.bottom; + } + + DAT_MouseState::instance.selectionBoxMode = 2; + + MACRO_CALL_MEMBER(Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)( + this->selectionBox.left, this->selectionBox.top, this->selectionBox.right, this->selectionBox.bottom); + + if (16 < DAT_DirectionAlgorithmState::instance.distanceHigh) { + DAT_MouseState::instance.field31_0x94 = 1; + } + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/isMouseInsideBox.cpp b/src/OpenSHC/Input/MouseState/isMouseInsideBox.cpp new file mode 100644 index 00000000..84f9ac2b --- /dev/null +++ b/src/OpenSHC/Input/MouseState/isMouseInsideBox.cpp @@ -0,0 +1,25 @@ +#include "../MouseState.func.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x004680C0 + BOOLEnum MouseState::isMouseInsideBox(int xPos, int yPos, int width, int heigth) + { + if (xPos > this->screenSpaceX) { + return FALSE; + } + if ((xPos + width) <= this->screenSpaceX) { + return FALSE; + } + if (yPos > this->screenSpaceY) { + return FALSE; + } + if ((yPos + heigth) <= this->screenSpaceY) { + return FALSE; + } + return TRUE; + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/loadAndSetCursor.cpp b/src/OpenSHC/Input/MouseState/loadAndSetCursor.cpp new file mode 100644 index 00000000..5542dbc4 --- /dev/null +++ b/src/OpenSHC/Input/MouseState/loadAndSetCursor.cpp @@ -0,0 +1,60 @@ +#include "../MouseState.func.hpp" + +#include "OpenSHC/string-literals.hpp" + +#include "OpenSHC/Globals/DAT_WindowAndDirectDraw.hpp" + +namespace OpenSHC { +namespace Input { + + // TODO: We later also need to add the proper resources. + + // FUNCTION: STRONGHOLDCRUSADER 0x00470A00 + void MouseState::loadAndSetCursor(int notAniDefaultCursorRef, int notAniDeleteCursorRef, + int notAniDeleteNotCursorRef, int unused1, int unused2, int unused3, int unused4, int notAniUnknownCursorRef) + { + this->notAniDefaultCursor_0x24c + = LoadCursorA(DAT_WindowAndDirectDraw::instance.hInstanceUnk_0xa8, MAKEINTRESOURCE(notAniDefaultCursorRef)); + + this->notAniDeleteCursor_0x250 + = LoadCursorA(DAT_WindowAndDirectDraw::instance.hInstanceUnk_0xa8, MAKEINTRESOURCE(notAniDeleteCursorRef)); + + this->notAniWaitCursor_0x258 = LoadCursorA(NULL, IDC_WAIT); + + this->notAniHandCursor_0x25c + = LoadCursorA(DAT_WindowAndDirectDraw::instance.hInstanceUnk_0xa8, MAKEINTRESOURCE(notAniDefaultCursorRef)); + + this->notAniDeleteNotCursor_0x260 = LoadCursorA( + DAT_WindowAndDirectDraw::instance.hInstanceUnk_0xa8, MAKEINTRESOURCE(notAniDeleteNotCursorRef)); + + this->notAniDefaultArabCursor_0x264 + = LoadCursorA(DAT_WindowAndDirectDraw::instance.hInstanceUnk_0xa8, MAKEINTRESOURCE(notAniDefaultCursorRef)); + + this->swordCursor_0x224 = LoadCursorFromFileA(s_sword_ani_005a625c); + this->deleteCursor_0x228 = LoadCursorFromFileA(s_delete_ani_005a6250); + this->jesterCursor_0x230 = LoadCursorFromFileA(s_jester_ani_005a6244); + this->handCursor_0x234 = LoadCursorFromFileA(s_hand_ani_005a6238); + this->deleteNotCursor_0x238 = LoadCursorFromFileA(s_delete_not_ani_005a6228); + this->scimitarCursor_0x23c = LoadCursorFromFileA(s_scimitar_ani_005a6218); + + if (!this->cursorType) { + if (DAT_WindowAndDirectDraw::instance.not_DDCAPS2_CANBOBHARDWARE_0xe0) { + this->cursorType = 2; + } else { + this->cursorType = 1; + } + } + MACRO_CALL_MEMBER(MouseState_Func::makeSelectedCursorTypeCurrent, this)(); + + if (notAniDeleteNotCursorRef) { + this->unknownNotAniDeleteNotCursor_0x204 = LoadCursorA( + DAT_WindowAndDirectDraw::instance.hInstanceUnk_0xa8, MAKEINTRESOURCE(notAniDeleteNotCursorRef)); + } + if (notAniUnknownCursorRef) { + this->unknownNotAniCursor_0x218 = LoadCursorA( + DAT_WindowAndDirectDraw::instance.hInstanceUnk_0xa8, MAKEINTRESOURCE(notAniUnknownCursorRef)); + } + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/makeSelectedCursorTypeCurrent.cpp b/src/OpenSHC/Input/MouseState/makeSelectedCursorTypeCurrent.cpp new file mode 100644 index 00000000..565a1826 --- /dev/null +++ b/src/OpenSHC/Input/MouseState/makeSelectedCursorTypeCurrent.cpp @@ -0,0 +1,30 @@ +#include "../MouseState.func.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x00467F80 + void MouseState::makeSelectedCursorTypeCurrent() + { + if (this->cursorType == 1) { + this->currentDefaultCursor = this->swordCursor_0x224; + this->currentDeleteCursor_0x200 = this->deleteCursor_0x228; + this->currentWaitCursor_0x208 = this->jesterCursor_0x230; + this->currentHandCursor_0x20c = this->handCursor_0x234; + this->currentDeleteNotCursor_0x210 = this->deleteNotCursor_0x238; + this->currentDefaultArabCursor_0x214 = this->scimitarCursor_0x23c; + return; + } + + if (this->cursorType == 2) { + this->currentDefaultCursor = this->notAniDefaultCursor_0x24c; + this->currentDeleteCursor_0x200 = this->notAniDeleteCursor_0x250; + this->currentWaitCursor_0x208 = this->notAniWaitCursor_0x258; + this->currentHandCursor_0x20c = this->notAniHandCursor_0x25c; + this->currentDeleteNotCursor_0x210 = this->notAniDeleteNotCursor_0x260; + this->currentDefaultArabCursor_0x214 = this->notAniDefaultArabCursor_0x264; + } + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/renderPreviewAtMouseLocation.cpp b/src/OpenSHC/Input/MouseState/renderPreviewAtMouseLocation.cpp new file mode 100644 index 00000000..07945ec2 --- /dev/null +++ b/src/OpenSHC/Input/MouseState/renderPreviewAtMouseLocation.cpp @@ -0,0 +1,90 @@ +#include "../MouseState.func.hpp" + +#include "OpenSHC/UI/Rendering/TextureRenderCore.func.hpp" + +#include "OpenSHC/Globals/DAT_GMImageHeaders.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_TextureRenderCoreObject.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/GMTotalPicturesProcessed.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x004685C0 + void MouseState::renderPreviewAtMouseLocation() + { + int iVar1 = 0; + if (!this->previewEnabled || !this->rightClickState + || !DAT_ViewportRenderState::instance.viewportState.field0_0x0 + || (DAT_GameCore::instance.currentMenuViewType != UI::Enums::MVT_BUILD_MENU + && DAT_GameCore::instance.currentMenuViewType != UI::Enums::MVT_MAP_EDITOR_LANDSCAPING)) { + return; + } + + if (DAT_TileMapState::instance.mapOrientation == 0) { + iVar1 = 0; + } else if (DAT_TileMapState::instance.mapOrientation == 2) { + iVar1 = 3; + } else if (DAT_TileMapState::instance.mapOrientation == 4) { + iVar1 = 2; + } else if (DAT_TileMapState::instance.mapOrientation == 6) { + iVar1 = 1; + } + + if (!this->field60_0x1bc) { + int imageIndex = GMTotalPicturesProcessed::instance[16] + 37 + iVar1; + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::renderGM, DAT_TextureRenderCoreObject::ptr)( + DE::SHCDE::GM_FLOATS, 38 + iVar1, + (this->storedScreenSpaceX - DAT_GMImageHeaders::instance.imh[imageIndex].width / 2) + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX, + (this->storedScreenSpaceY - DAT_GMImageHeaders::instance.imh[imageIndex].height / 2) + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY - 50); + } + + if (!this->field61_0x1c0) { + int uVar2 = this->mouseBasedEvent == 1; + + int imageIndex = GMTotalPicturesProcessed::instance[16] + 35 + uVar2; + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::renderGM, DAT_TextureRenderCoreObject::ptr)( + DE::SHCDE::GM_FLOATS, 36 + uVar2, + (this->storedScreenSpaceX - DAT_GMImageHeaders::instance.imh[imageIndex].width / 2) + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX, + (this->storedScreenSpaceY - DAT_GMImageHeaders::instance.imh[imageIndex].height / 2) + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY + 50); + } + + if (!this->field63_0x1c8) { + int uVar2 = !DAT_ViewportRenderState::instance.viewportState.isZoomedOutUnk; + if (this->field59_0x1b8 == 3) { + uVar2 += 2; + } + + int imageIndex = GMTotalPicturesProcessed::instance[16] + 45 + uVar2; + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::renderGM, DAT_TextureRenderCoreObject::ptr)( + DE::SHCDE::GM_FLOATS, 46 + uVar2, + (this->storedScreenSpaceX - DAT_GMImageHeaders::instance.imh[imageIndex].width / 2) + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX + 80, + (this->storedScreenSpaceY - DAT_GMImageHeaders::instance.imh[imageIndex].height / 2) + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY); + } + + if (!this->field62_0x1c4) { + int uVar2 = !!DAT_TileMapState::instance.flatViewToggleValue1; + if (this->field59_0x1b8 == 4) { + uVar2 += 2; + } + + int imageIndex = GMTotalPicturesProcessed::instance[16] + 124 + uVar2; + MACRO_CALL_MEMBER(UI::Rendering::TextureRenderCore_Func::renderGM, DAT_TextureRenderCoreObject::ptr)( + DE::SHCDE::GM_FLOATS, 125 + uVar2, + (this->storedScreenSpaceX - DAT_GMImageHeaders::instance.imh[imageIndex].width / 2) + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX - 80, + (this->storedScreenSpaceY - DAT_GMImageHeaders::instance.imh[imageIndex].height / 2) + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY); + } + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/resetMouseCursorState.cpp b/src/OpenSHC/Input/MouseState/resetMouseCursorState.cpp new file mode 100644 index 00000000..68a445fc --- /dev/null +++ b/src/OpenSHC/Input/MouseState/resetMouseCursorState.cpp @@ -0,0 +1,26 @@ +#include "../MouseState.func.hpp" + +#include "OpenSHC/Globals/DAT_MouseState.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x00468590 + void MouseState::resetMouseCursorState() + { + this->selectionBox.left = 0; + this->selectionBox.top = 0; + this->selectionBox.right = 0; + this->selectionBox.bottom = 0; + + this->previousSelectionBox.left = 0; + this->previousSelectionBox.top = 0; + this->previousSelectionBox.right = 0; + this->previousSelectionBox.bottom = 0; + + DAT_MouseState::instance.selectionBoxMode = 0; + DAT_MouseState::instance.field31_0x94 = 0; + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/resetMouseState2.cpp b/src/OpenSHC/Input/MouseState/resetMouseState2.cpp new file mode 100644 index 00000000..4f7b3f40 --- /dev/null +++ b/src/OpenSHC/Input/MouseState/resetMouseState2.cpp @@ -0,0 +1,33 @@ +#include "../MouseState.func.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x004689D0 + void MouseState::resetMouseState2() + { + if (!this->resetPending) { + this->draggingStopped = FALSE; + + this->midClickStop = FALSE; + this->rightClickStop = FALSE; + + this->leftClickStart = FALSE; + this->midClickStart = FALSE; + this->rightClickStart = FALSE; + + this->leftClickState = FALSE; + this->midClickState = FALSE; + this->rightClickState = FALSE; + + this->previousLeftClickState = FALSE; + this->previousMidClickStateUnk = FALSE; + this->previousRightClickState = FALSE; + + this->mouseClickTypes = 0; + } + this->resetPending = 0; + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/setCursor.cpp b/src/OpenSHC/Input/MouseState/setCursor.cpp new file mode 100644 index 00000000..3dc2dbcb --- /dev/null +++ b/src/OpenSHC/Input/MouseState/setCursor.cpp @@ -0,0 +1,39 @@ +#include "../MouseState.func.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x00468370 + HCURSOR MouseState::setCursor(DWORD cursorType) + { + if (cursorType == 0) { + if (this->lastSetCursorType) { + return SetCursor(this->currentDefaultCursor); + } + return SetCursor(this->currentDefaultCursor); + } + + if (cursorType == 1) { + return SetCursor(this->unknownNotAniDeleteNotCursor_0x204); + } + + if (cursorType == 3) { + return SetCursor(this->currentWaitCursor_0x208); + } + + if (cursorType == 4) { + return SetCursor(this->currentHandCursor_0x20c); + } + + if (cursorType == 5) { + return SetCursor(this->currentDeleteNotCursor_0x210); + } + + if (cursorType == 6) { + return SetCursor(this->currentDefaultArabCursor_0x214); + } + return SetCursor(this->currentDeleteCursor_0x200); + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/setupHitBox.cpp b/src/OpenSHC/Input/MouseState/setupHitBox.cpp new file mode 100644 index 00000000..e98130de --- /dev/null +++ b/src/OpenSHC/Input/MouseState/setupHitBox.cpp @@ -0,0 +1,38 @@ +#include "../MouseState.func.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x004684D0 + void MouseState::setupHitBox(int width, int height) + { + if (DAT_ViewportRenderState::instance.viewportState.isZoomedOutUnk) { + this->hitboxXStart = (this->screenSpaceX + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX - width / 2) + * 2; + this->hitboxYStart + = (this->screenSpaceY + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY + - height / 2) + * 2; + this->hitboxXEnd = (this->screenSpaceX + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX + width / 2) + * 2; + this->hitboxYEnd = (this->screenSpaceY + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY + height / 2) + * 2; + } else { + this->hitboxXStart + = this->screenSpaceX + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX - width / 2; + this->hitboxYStart = this->screenSpaceY + + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY - height / 2; + this->hitboxXEnd + = this->screenSpaceX + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetX + width / 2; + this->hitboxYEnd = this->screenSpaceY + DAT_ViewportRenderState::instance.viewportState.currentCameraOffsetY + + height / 2; + } + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/storeXYAndResetMouseState.cpp b/src/OpenSHC/Input/MouseState/storeXYAndResetMouseState.cpp new file mode 100644 index 00000000..67bca782 --- /dev/null +++ b/src/OpenSHC/Input/MouseState/storeXYAndResetMouseState.cpp @@ -0,0 +1,52 @@ +#include "../MouseState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x004687F0 + void MouseState::storeXYAndResetMouseState() + { + for (int i = 0; i < 10; ++i) { + this->mouseXY[i].x = 0; + this->mouseXY[i].y = 0; + this->mouseXY[i].unknownZero01 = 0; + this->mouseXY[i].unknownOne02 = 0; + } + + this->index = 0; + + this->storedScreenSpaceX = this->screenSpaceX; + this->storedScreenSpaceY = this->screenSpaceY; + + for (int i = 0; i < 10; ++i) { + this->mouseXY8[i] = 8; + } + + this->field46_0x184 = 0; + this->field42_0x174 = 0; + this->field47_0x188 = 8; + this->field51_0x198 = 0; + this->field52_0x19c = 0; + + this->mapOrientationCopy1 = DAT_TileMapState::instance.mapOrientation; + this->mapOrientationCopy2 = DAT_TileMapState::instance.mapOrientation; + this->mapOrientationCopy3 = DAT_TileMapState::instance.mapOrientation; + + this->field58_0x1b4 = 0; + + this->currentTime1 = timeGetTime(); + this->currentTime2 = timeGetTime(); + this->currentTime3 = timeGetTime(); + + this->field56_0x1ac = 0; + this->field59_0x1b8 = 0; + this->field60_0x1bc = 0; + this->field61_0x1c0 = 0; + this->field62_0x1c4 = 0; + this->field63_0x1c8 = 0; + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/updateMousePositionAndClicks.cpp b/src/OpenSHC/Input/MouseState/updateMousePositionAndClicks.cpp new file mode 100644 index 00000000..2b3f7eeb --- /dev/null +++ b/src/OpenSHC/Input/MouseState/updateMousePositionAndClicks.cpp @@ -0,0 +1,44 @@ +#include "../MouseState.func.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x00468030 + void MouseState::updateMousePositionAndClicks(short xMousePos, short yMousePos, MouseClickInteraction clickType) + { + this->mouseWindowX = xMousePos; + this->mouseWindowY = yMousePos; + + if (clickType == Mouse::MCI_LEFTDOWN) { + this->mouseClickTypes |= Mouse::CTBME_LEFT_DOWN; + return; + } + + if (clickType == Mouse::MCI_LEFTUP) { + this->mouseClickTypes &= Mouse::CTBME_LEFT_UP; + return; + } + + if (clickType == Mouse::MCI_MIDDOWN) { + this->mouseClickTypes |= Mouse::CTBME_MID_DOWN; + return; + } + + if (clickType == Mouse::MCI_MIDUP) { + this->mouseClickTypes &= Mouse::CTBME_MIDUP; + return; + } + + if (clickType == Mouse::MCI_RIGHTDOWN) { + this->mouseClickTypes |= Mouse::CTBME_RIGHT_DOWN; + return; + } + + if (clickType == Mouse::MCI_RIGHTUP) { + this->mouseClickTypes &= Mouse::CTBME_RIGHT_UP; + return; + } + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/updateMouseStateBasedOnCursorAndTime.cpp b/src/OpenSHC/Input/MouseState/updateMouseStateBasedOnCursorAndTime.cpp new file mode 100644 index 00000000..6af1e3f8 --- /dev/null +++ b/src/OpenSHC/Input/MouseState/updateMouseStateBasedOnCursorAndTime.cpp @@ -0,0 +1,148 @@ +#include "../MouseState.func.hpp" + +#include "OpenSHC/Globals/DAT_ScrollingHandler.hpp" +#include "OpenSHC/Globals/DAT_WindowAndDirectDraw.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x00468100 + void MouseState::updateMouseStateBasedOnCursorAndTime() + { + DWORD _now = timeGetTime(); + + this->anyActivity = FALSE; + + this->previousScreenSpaceX = this->screenSpaceX; + this->previousScreenSpaceY = this->screenSpaceY; + + this->previousLeftClickState = this->leftClickState; + this->previousRightClickState = this->rightClickState; + + this->screenSpaceX = this->mouseWindowX; + this->screenSpaceY = this->mouseWindowY; + + if (this->previousScreenSpaceX != this->mouseWindowX) { + this->anyActivity = TRUE; + } + if (this->previousScreenSpaceY != this->mouseWindowY) { + this->anyActivity = TRUE; + } + if (this->anyActivity) { + this->flag = 1; + + this->mouseXY[this->index].x = this->screenSpaceX; + this->mouseXY[this->index].y = this->screenSpaceY; + this->mouseXY[this->index].unknownZero01 = 0; + this->mouseXY[this->index].unknownOne02 = 1; + + ++this->index; + if (this->index >= 10) { + this->index = 0; + } + } + + POINT _cursorPos; + GetCursorPos(&_cursorPos); + this->cursorPosX = _cursorPos.x; + this->cursorPosY = _cursorPos.y; + if (this->cursorPosX <= 0) { + DAT_ScrollingHandler::instance.scrollLeft = TRUE; + } + if (this->cursorPosX >= DAT_WindowAndDirectDraw::instance.screenHorizontalResolutionInPixels + -1) { + DAT_ScrollingHandler::instance.scrollRight = TRUE; + } + if (this->cursorPosY <= 0) { + DAT_ScrollingHandler::instance.scrollUp = TRUE; + } + if (this->cursorPosY >= DAT_WindowAndDirectDraw::instance.screenVerticalResolutionInPixels + -1) { + DAT_ScrollingHandler::instance.scrollDown = TRUE; + } + + if (this->mouseClickTypes & Mouse::CTBME_RIGHT_DOWN) { + this->rightClickState = TRUE; + } else { + this->rightClickState = FALSE; + } + this->rightClickStart = 0; + this->rightClickStop = 0; + if (this->rightClickState != this->previousRightClickState) { + this->anyActivity = TRUE; + + if (this->rightClickState) { + this->rightClickStart = TRUE; + } else { + this->rightClickStop = TRUE; + } + } + + if (this->mouseClickTypes & Mouse::CTBME_MID_DOWN) { + this->midClickState = TRUE; + } else { + this->midClickState = FALSE; + } + this->midClickStart = 0; + this->midClickStop = 0; + if (this->midClickState != this->previousMidClickStateUnk) { + this->anyActivity = TRUE; + + if (this->midClickState) { + this->midClickStart = TRUE; + } else { + this->midClickStop = TRUE; + } + } + + if (this->mouseClickTypes & Mouse::CTBME_LEFT_DOWN) { + if (!this->leftClickState) { + this->leftClickStartMoment = _now; + this->dragReleaseX = this->mouseWindowX; + this->dragReleaseY = this->mouseWindowY; + this->leftClickState = TRUE; + } else { + if (this->dragReleaseX != this->mouseWindowX || this->dragReleaseY != this->mouseWindowY) { + this->leftClickStartMoment = -1; + } + this->leftClickState = TRUE; + } + } else { + this->leftClickState = FALSE; + if (this->dragReleaseX == this->mouseWindowX && this->dragReleaseY == this->mouseWindowY + && this->leftClickStartMoment != -1) { + this->leftClickStartMoment = -2; + } else { + this->leftClickStartMoment = -3; + } + } + + this->leftClickStart = FALSE; + this->draggingStopped = FALSE; + if (this->leftClickState != this->previousLeftClickState) { + this->anyActivity = TRUE; + + if (this->leftClickState) { + this->leftClickStart = TRUE; + } else { + this->draggingStopped = TRUE; + } + } + + if (!this->anyActivity) { + this->inactiveTime = _now - this->time0; + } else { + this->time0 = _now; + this->inactiveTime = 0; + } + + if (this->mouseWheelDelta < 0) { + this->scrollEventData = 7; + } else if (this->mouseWheelDelta > 0) { + this->scrollEventData = 8; + } else { + this->scrollEventData = 9; + } + this->mouseWheelDelta = 0; + } + +} +} diff --git a/src/OpenSHC/Input/MouseState/updateMouseWheelStatus.cpp b/src/OpenSHC/Input/MouseState/updateMouseWheelStatus.cpp new file mode 100644 index 00000000..57a1022d --- /dev/null +++ b/src/OpenSHC/Input/MouseState/updateMouseWheelStatus.cpp @@ -0,0 +1,10 @@ +#include "../MouseState.func.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x004680B0 + void MouseState::updateMouseWheelStatus(int delta) { this->mouseWheelDelta = delta; } + +} +} diff --git a/src/OpenSHC/Input/MouseState/updateRightDragCameraControl.cpp b/src/OpenSHC/Input/MouseState/updateRightDragCameraControl.cpp new file mode 100644 index 00000000..f0834bfa --- /dev/null +++ b/src/OpenSHC/Input/MouseState/updateRightDragCameraControl.cpp @@ -0,0 +1,137 @@ +#include "../MouseState.func.hpp" + +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" + +namespace OpenSHC { +namespace Input { + + // FUNCTION: STRONGHOLDCRUSADER 0x00470BC0 + void MouseState::updateRightDragCameraControl() + { + int iVar6 = this->mapOrientationCopy3; + + this->mouseBasedEvent = 0; + this->field44_0x17c = 0; + this->field43_0x178 = 0; + this->field59_0x1b8 = 0; + + DWORD DVar4 = timeGetTime(); + + this->currentTime3 = DVar4; + this->field56_0x1ac = DVar4 - this->currentTime2; + + ++this->field42_0x174; + if (this->field56_0x1ac > this->field57_0x1b0) { + this->currentTime2 = DVar4; + this->field58_0x1b4 = 0; + this->field51_0x198 = 0; + this->field52_0x19c = 0; + } + + int iVar5 + = MACRO_CALL_MEMBER(Map::Navigation::DirectionAlgorithmState_Func::getMouseVectorLengthBasedOnDirection, + DAT_DirectionAlgorithmState::ptr)( + this->storedScreenSpaceX, this->storedScreenSpaceY, this->screenSpaceX, this->screenSpaceY, 4); + + if (iVar5 < 12 || this->field61_0x1c0) { + this->field43_0x178 = 0; + } else if (iVar5 < 28) { + this->field43_0x178 = iVar5 / 2; + this->mouseBasedEvent = 2; + } else { + this->field59_0x1b8 = 1; + this->field60_0x1bc = 1; + this->field62_0x1c4 = 1; + this->field63_0x1c8 = 1; + this->field43_0x178 = 40; + this->mouseBasedEvent = 1; + } + + iVar5 = MACRO_CALL_MEMBER(Map::Navigation::DirectionAlgorithmState_Func::getMouseVectorLengthBasedOnDirection, + DAT_DirectionAlgorithmState::ptr)( + this->storedScreenSpaceX, this->storedScreenSpaceY, this->screenSpaceX, this->screenSpaceY, 0); + if (iVar5 < 22 || this->field60_0x1bc) { + this->field42_0x174 = 0; + this->field58_0x1b4 = 0; + + if (this->field59_0x1b8 == 2 || iVar5 < 22) { + this->currentTime2 = DVar4; + } + } else { + this->field61_0x1c0 = 1; + this->field62_0x1c4 = 1; + this->field63_0x1c8 = 1; + this->field59_0x1b8 = 2; + this->field57_0x1b0 = 1500; + + if (!this->field58_0x1b4) { + this->field58_0x1b4 = 1; + + iVar6 = this->mapOrientationCopy3 + 6; + if (iVar6 >= 8) { + iVar6 -= 8; + } + + this->field47_0x188 = 0; + } else { + this->field47_0x188 = 8; + } + } + + if (iVar6 != this->mapOrientationCopy2) { + this->mapOrientationCopy2 = iVar6; + this->mapOrientationCopy3 = iVar6; + this->mouseBasedEvent = 3; + } + + if (MACRO_CALL_MEMBER(Map::Navigation::DirectionAlgorithmState_Func::getMouseVectorLengthBasedOnDirection, + DAT_DirectionAlgorithmState::ptr)( + this->storedScreenSpaceX, this->storedScreenSpaceY, this->screenSpaceX, this->screenSpaceY, 2) + < 55 + || this->field63_0x1c8) { + + this->field42_0x174 = 0; + if (this->field59_0x1b8 == 3) { + this->currentTime2 = DVar4; + } + } else { + this->field61_0x1c0 = 1; + this->field62_0x1c4 = 1; + this->field60_0x1bc = 1; + this->field57_0x1b0 = 2000; + this->field59_0x1b8 = 3; + + if (this->field51_0x198 != 2) { + this->mouseBasedEvent = 4; + this->field51_0x198 = 1; + } + } + + if (MACRO_CALL_MEMBER(Map::Navigation::DirectionAlgorithmState_Func::getMouseVectorLengthBasedOnDirection, + DAT_DirectionAlgorithmState::ptr)( + this->storedScreenSpaceX, this->storedScreenSpaceY, this->screenSpaceX, this->screenSpaceY, 6) + < 55 + || this->field62_0x1c4) { + + this->field42_0x174 = 0; + if (this->field59_0x1b8 == 4) { + this->currentTime2 = DVar4; + } + } else { + this->field61_0x1c0 = 1; + this->field63_0x1c8 = 1; + this->field60_0x1bc = 1; + this->field57_0x1b0 = 2000; + this->field59_0x1b8 = 4; + + if (this->field52_0x19c != 2) { + this->mouseBasedEvent = 5; + this->field52_0x19c = 1; + } + } + } + +} +} diff --git a/src/OpenSHC/Map/Navigation/DirectionAlgorithmState.hpp b/src/OpenSHC/Map/Navigation/DirectionAlgorithmState.hpp index dd22884c..a647ed66 100644 --- a/src/OpenSHC/Map/Navigation/DirectionAlgorithmState.hpp +++ b/src/OpenSHC/Map/Navigation/DirectionAlgorithmState.hpp @@ -46,7 +46,7 @@ namespace Map { int destinationXPosition, int destinationYPosition, int fromXPosition, int fromYPosition); int getMouseVectorLengthBasedOnDirection( - int param_1, int param_2, int param_3, int param_4, int orientation); + int storedScreenSpaceX, int storedScreenSpaceY, int screenSpaceX, int screenSpaceY, int orientation); uint computeHash(int byteCount, int* address); diff --git a/src/OpenSHC/Map/Navigation/DirectionAlgorithmState/getMouseVectorLengthBasedOnDirection.cpp b/src/OpenSHC/Map/Navigation/DirectionAlgorithmState/getMouseVectorLengthBasedOnDirection.cpp new file mode 100644 index 00000000..c8e1d829 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/DirectionAlgorithmState/getMouseVectorLengthBasedOnDirection.cpp @@ -0,0 +1,33 @@ +#include "../DirectionAlgorithmState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + // FUNCTION: STRONGHOLDCRUSADER 0x0046CCD0 + int DirectionAlgorithmState::getMouseVectorLengthBasedOnDirection( + int storedScreenSpaceX, int storedScreenSpaceY, int screenSpaceX, int screenSpaceY, int orientation) + { + if (orientation == 0) { + if (storedScreenSpaceY > screenSpaceY) { + return storedScreenSpaceY - screenSpaceY; + } + } else if (orientation == 4) { + if (screenSpaceY > storedScreenSpaceY) { + return screenSpaceY - storedScreenSpaceY; + } + } else if (orientation == 6) { + if (storedScreenSpaceX > screenSpaceX) { + return storedScreenSpaceX - screenSpaceX; + } + } else if (orientation == 2) { + if (screenSpaceX > storedScreenSpaceX) { + return screenSpaceX - storedScreenSpaceX; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 6b3a4b48..72bf5602 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -20061,29 +20061,29 @@ SHC_3BB0A8C1_0x00467F50 | 0.0% | Pending SHC_3BB0A8C1_0x00467F60 | 0.0% | Pending -SHC_3BB0A8C1_0x00467F80 | 0.0% | Pending +SHC_3BB0A8C1_0x00467F80 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00468030 | 0.0% | Pending +SHC_3BB0A8C1_0x00468030 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004680B0 | 0.0% | Pending +SHC_3BB0A8C1_0x004680B0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004680C0 | 0.0% | Pending +SHC_3BB0A8C1_0x004680C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00468100 | 0.0% | Pending +SHC_3BB0A8C1_0x00468100 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00468370 | 0.0% | Pending +SHC_3BB0A8C1_0x00468370 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00468420 | 0.0% | Pending +SHC_3BB0A8C1_0x00468420 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004684D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004684D0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00468590 | 0.0% | Pending +SHC_3BB0A8C1_0x00468590 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004685C0 | 0.0% | Pending +SHC_3BB0A8C1_0x004685C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004687F0 | 0.0% | Pending +SHC_3BB0A8C1_0x004687F0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004689D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004689D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00468A10 | 0.0% | Pending @@ -20945,7 +20945,7 @@ SHC_3BB0A8C1_0x0046CAA0 | 0.0% | Pending SHC_3BB0A8C1_0x0046CC80 | 0.0% | Pending -SHC_3BB0A8C1_0x0046CCD0 | 0.0% | Pending +SHC_3BB0A8C1_0x0046CCD0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046CD30 | 0.0% | Pending @@ -21257,13 +21257,13 @@ SHC_3BB0A8C1_0x004707F0 | 0.0% | Pending SHC_3BB0A8C1_0x004708F0 | 0.0% | Pending -SHC_3BB0A8C1_0x004709B0 | 0.0% | Pending +SHC_3BB0A8C1_0x004709B0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00470A00 | 0.0% | Pending +SHC_3BB0A8C1_0x00470A00 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00470B30 | 0.0% | Pending +SHC_3BB0A8C1_0x00470B30 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00470BC0 | 0.0% | Pending +SHC_3BB0A8C1_0x00470BC0 | 100.0% | Reimplemented, requires SHC_3BB0A8C1_0x0046CCD0 to be active SHC_3BB0A8C1_0x00470E90 | 0.0% | Pending @@ -21415,7 +21415,7 @@ SHC_3BB0A8C1_0x00472950 | 0.0% | Pending SHC_3BB0A8C1_0x004729B0 | 0.0% | Pending -SHC_3BB0A8C1_0x00472A90 | 0.0% | Pending +SHC_3BB0A8C1_0x00472A90 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00472B20 | 0.0% | Pending