diff --git a/.gitignore b/.gitignore index 754c8b8..73586a1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ cmake-build* -build +build*/* .idea .vscode \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a25b19..877e4fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 4.0) project(ReHitmanRoot) +set(CMAKE_POLICY_VERSION_MINIMUM 3.5) #TODO Check that we will compile only under x86! add_subdirectory(ReHitman) \ No newline at end of file diff --git a/ReHitman/BloodMoney/CMakeLists.txt b/ReHitman/BloodMoney/CMakeLists.txt index 9a14639..c53033f 100644 --- a/ReHitman/BloodMoney/CMakeLists.txt +++ b/ReHitman/BloodMoney/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.16) +cmake_minimum_required(VERSION 4.0) project(BloodMoney) set(CMAKE_CXX_STANDARD 20) diff --git a/ReHitman/BloodMoney/include/BloodMoney/BMConfigurationService.h b/ReHitman/BloodMoney/include/BloodMoney/BMConfigurationService.h index cd7ac46..1d88f12 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/BMConfigurationService.h +++ b/ReHitman/BloodMoney/include/BloodMoney/BMConfigurationService.h @@ -19,6 +19,7 @@ namespace Hitman::BloodMoney static std::intptr_t BMAPI_FunctionAddress_CMetalDetector_DoAlarm; static std::intptr_t BMAPI_FunctionAddress_ZHM3Actor_PreparePath; static std::intptr_t BMAPI_FunctionAddress_ZHM3Actor_ActivateBloodSpurt; + static std::intptr_t BMAPI_FunctionAddress_ZHM3Actor_InitMapIcon; static std::intptr_t BMAPI_FunctionAddress_ZTie_HideTie; static std::intptr_t BMAPI_FunctionAddress_ZTie_HideTieInMirror; static std::intptr_t BMAPI_FunctionAddress_ZXMLGUISystem_GetTopWindow; diff --git a/ReHitman/BloodMoney/include/BloodMoney/Engine/ZBoidSystem.h b/ReHitman/BloodMoney/include/BloodMoney/Engine/ZBoidSystem.h index 99102db..b45ed68 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Engine/ZBoidSystem.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Engine/ZBoidSystem.h @@ -3,6 +3,7 @@ #include #include +#include namespace Hitman::BloodMoney { @@ -19,7 +20,7 @@ namespace Hitman::BloodMoney ZBoid** m_boidsPool; //0x0000 int32_t m_pFreeAvailableMemForPoolBegin; //0x0004 int32_t m_pFreeAvailableMemForPoolEnd; //0x0008 - Glacier::PF4::Interface* m_pPF4Interface; //0x000C (always nullptr, maybe unused) + Glacier::PF4::ZInterface* m_pPF4Interface; //0x000C (always nullptr, maybe unused) int32_t m_totalBoids; //0x0010 int32_t m_unknownField; //0x0014 diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Actions/EHM3Action.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Actions/EHM3Action.h new file mode 100644 index 0000000..df4fc4b --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Actions/EHM3Action.h @@ -0,0 +1,69 @@ +#pragma once + +namespace Hitman::BloodMoney +{ + enum EHM3Action { + eNone = 0, + eCancel = 1, + eOpenDoor = 2, + eCloseDoor = 3, + eLockDoor = 4, + eUnLockDoor = 5, + ePickLock = 6, + eStrangle = 7, + eHackSlash = 8, + ePushPerson = 9, + eReload = 10, + eCombine = 11, + eDrop = 12, + eThrow = 13, + eHolster = 14, + eLookKeyhole = 15, + ePickup = 16, + eChangeClothes = 17, + eTalk = 18, + eHumanShield = 19, + eHumanShieldRelease = 20, + eDragBody = 21, + ePutInSuitcase = 22, + eConcealWeapon = 23, + eHideWeapon = 24, + eHideInCloset = 25, + eDropBody = 26, + eOpenLid = 27, + eCloseLid = 28, + eUseKeyCard = 29, + eGrab = 30, + eRelease = 31, + eClimbHatch = 32, + eStrangleInElevator = 33, + ePutItemElevator = 34, + ePlaceItem = 35, + ePlaceBomb = 36, + eRetrieveItem = 37, + eJumpBalcony = 38, + eActionKill = 39, + eElevatorButton = 40, + ePlace = 41, + eRetrieve = 42, + eUseSwitch = 43, + eGeneric = 44, + eHideBodyOnTable = 45, + ePlaceItemToPos = 46, + eHitmanUseWeaponStorage = 47, + eBreakUtilBox = 48, + eUseLightSwitch = 49, + eUseFireAlarm = 50, + eExitKeyhole = 51, + eExitCloset = 52, + eSurrendWeapon = 53, + eStealTape = 54, + eADisposeBodyToDumpster = 55, + eADisposeBodyToCrate = 56, + eADisposeBodyGarbageTruck = 57, + eAThrowRail = 58, + eAThrowChute = 59, + eLast = 60, + }; + +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Actions/ZHitmanAction.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Actions/ZHitmanAction.h index 327bfb9..558e378 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Actions/ZHitmanAction.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Actions/ZHitmanAction.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace Hitman::BloodMoney { diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/CEVENTCONTROLLER.h b/ReHitman/BloodMoney/include/BloodMoney/Game/CEVENTCONTROLLER.h index ed79608..1e3cc4d 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/CEVENTCONTROLLER.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/CEVENTCONTROLLER.h @@ -1,18 +1,31 @@ #pragma once -#include #include +#include +#include + + +namespace Hitman::BloodMoney +{ + struct SActor + { + int32_t lType; + Glacier::ZGEOM* pActor; + Glacier::TIMETYPE vLastCheckTime; + struct SActor* m_pNext; + struct SActor* m_pPrev; + }; + RE_VERIFY_SIZE(SActor, 0x14); // Verified -namespace Hitman::BloodMoney { - class CEVENTCONTROLLER { - public: - //vftable: no vftable + struct CEVENTCONTROLLER + { //data (total size is 0x18) - Glacier::REFTAB* m_refTab0; - Glacier::LINKREFTAB* m_linkRefTab4; - int m_field8; - int m_fieldC; - int m_field10; - int m_field14; + Glacier::REFTAB* m_prtEventList; + Glacier::LINKREFTAB* m_prtActorList; + int32_t m_lUpdateCount; + SActor* m_pActors; + SActor* m_pNextOnScreen; + SActor* m_pNextOffScreen; }; + RE_VERIFY_SIZE(CEVENTCONTROLLER, 0x18); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/CExplosionController.h b/ReHitman/BloodMoney/include/BloodMoney/Game/CExplosionController.h new file mode 100644 index 0000000..ac2cd7d --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/CExplosionController.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include // ZBaseGeom +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class CExplosionController : public Glacier::CBaseEvent + { + public: + // vtbl + // data + float m_fMaxDamage; + float m_fMaxDamageRange; + float m_fMaxRange; + Glacier::ZREF m_rEffectGroup; + Glacier::ZREF m_rExplodedGeom; + Glacier::REFTAB m_rAfterEffectGeomsToActivate; + Glacier::REFTAB m_rAfterEffectGeomsToInactivate; + float m_fHitPoints; + Glacier::ZMSGID m_msgDirectActivationMessage; + bool m_bExploded; + bool m_bExploding; + uint32_t m_iNumberOfTargets; + Glacier::ZBaseGeom* m_pTargets[30]; + uint32_t m_iTargetCheck; + + }; + RE_VERIFY_SIZE(CExplosionController, 0x104); // verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/CIngameMap.h b/ReHitman/BloodMoney/include/BloodMoney/Game/CIngameMap.h index d476097..c5cf0ab 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/CIngameMap.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/CIngameMap.h @@ -1,52 +1,98 @@ #pragma once #include +#include #include #include #include #include #include +#include #include +#include #include #include #include #include +#ifdef small // thx msvc +# undef small +#endif + namespace Hitman::BloodMoney { - struct SMapText + enum EAnimMode + { + none = 0, + scale = 1, + jump = 2, + alpha = 4, + saturation = 8, + big = 16, + small = 32 + }; + + struct SIconDef + { + uint16_t u; + uint16_t v; + uint16_t w; + uint16_t h; + uint32_t iColor; + EAnimMode eAnimMode; + bool bRotate; + int8_t iMaxDifficulty; + RE_ADD_PADDING(2); + }; + RE_VERIFY_SIZE(SIconDef, 0x14); + + struct SMapText : public SIconBase { - int id; //0x0000 - bool field_04; //0x0004 - bool field_05; //0x0005 - bool field_06; //0x0006 - bool field_07; //0x0007 - char str[0x5C]; //0x0008 - int field_64; //0x0064 - int field_68; - int field_6C; - int field_70; - int field_74; - int field_78; - int field_7C; - int field_80; - int field_84; - int field_88; - int field_8C; - int field_90; - int field_94; + char szText[128]; + uint32_t iColor; + EAnimMode eAnimMode; + float fSize; + int8_t iAlignment; + bool bRotate; + RE_ADD_PADDING(2); }; //Size: 0x0098 (see CIngameMap::AddText at 00663E20 for details) + RE_VERIFY_SIZE(SMapText, 0x98); // Verified - struct SIconInstance + struct SIconInstance : public SIconBase { - int32_t ref; // SRef id (object id) - bool field_04; // must be true if you want to replace icon - char field_5; // ? - char field_6; // ? - char field_7; // ? - int32_t eIconType; // icon type (enum) + uint32_t iIconIndex; }; + RE_VERIFY_SIZE(SIconInstance, 0xC); + + struct CMapIconDraw : public Glacier::ZSTDOBJ + { + struct SMatPos + { + Glacier::ZVector3 vPos; + Glacier::ZMat3x3 mPos; + }; + RE_VERIFY_SIZE(SMatPos, 0x30); + + struct SIconInfo + { + uint32_t m_iIcon; + Glacier::ZREF m_rBaseGeom; + SMatPos m_sLastPos; + }; + RE_VERIFY_SIZE(SIconInfo, 0x38); + + // Size: 0x4bac (19372) bytes + Glacier::ZStackArray<256, CMapIconDraw::SIconInfo> m_Icons; + Glacier::ZStackArray<32, SMapText> m_Texts; + Glacier::ZStackArray<32, ZCHAROBJ*> m_TextObjects; + uint32_t* m_pPrims; + Glacier::SSpriteArray* m_pSpriteArrays; + Glacier::SSpriteArrayElementRaw* m_pSprites; + float m_fScale; + }; + RE_VERIFY_SIZE(CMapIconDraw, 0x4BAC); + class CIngameMap : public CWinEvent { @@ -63,95 +109,75 @@ namespace Hitman::BloodMoney virtual void NotifyUpdate(uint16_t); //data (total size is 0x2C4, CWinEvent : ZEventBase size is 0x30) - Glacier::ZHandle m_mapLegendAction; - Glacier::ZHandle m_mapSelectAction; - Glacier::ZHandle m_mapCameraLeftAction; - Glacier::ZHandle m_mapCameraRightAction; - Glacier::ZHandle m_mapCameraUpAction; - Glacier::ZHandle m_mapCameraDownAction; - Glacier::ZHandle m_mapMoveUpAction; - Glacier::ZHandle m_mapMoveDownAction; - Glacier::ZHandle m_mapPrevAction; - Glacier::ZHandle m_mapNextAction; - Glacier::ZHandle m_mapMenuAction; - Glacier::ZHandle m_mapAction; - int field_00C0; - int field_00C4; - int field_00C8; - int field_00CC; - int field_00D0; - int field_00D4; - int field_00D8; - int field_00DC; - int field_00E0; - int field_00E4; - int field_00E8; - int field_00EC; - int field_00F0; - int field_00F4; - Glacier::REFTAB32 m_reftab32_00F8; - int field_01A4; - SMapGroup* m_legendMapGroup; - int field_01AC; - Glacier::REFTAB m_mapGroups; //REFTAB of SMapGroup - int field_01CC; - int field_01D0; - Glacier::REFTAB m_iconsRefTab; - Glacier::REFTAB m_textsRefTab; - int field_020C; - int field_0210; - int field_0214; - int field_0218; - int field_021C; - int field_0220; - int field_0224; - int field_0228; - int field_022C; - int field_0230; - int field_0234; - int field_0238; - int field_023C; - int field_0240; - int field_0244; - int field_0248; - int field_024C; - int field_0250; - int field_0254; - int field_0258; - int field_025C; - int field_0260; - int field_0264; - int field_0268; - int field_026C; - int field_0270; - int field_0274; - int field_0278; - int field_027C; - int field_0280; - int field_0284; - int field_0288; - int field_028C; - int field_0290; - int field_0294; - char m_isMapListOpened; - char field_299; - char field_29A; - char field_29B; - char field_029C; - char field_29D; - char m_mapsComboShowing; - char field_29F; - char field_02A0; - char field_2A1; - char field_2A2; - char field_2A3; - int field_02A4; - int field_02A8; - SMapGroup* m_currentMapGroup; - int field_02B0; - int field_02B4; - int field_02B8; - int field_02BC; - int field_02C0; + Glacier::ZHandle m_ahLegend; + Glacier::ZHandle m_ahSelect; + Glacier::ZHandle m_ahCamLeft; + Glacier::ZHandle m_ahCamRight; + Glacier::ZHandle m_ahCamUp; + Glacier::ZHandle m_ahCamDown; + Glacier::ZHandle m_ahMoveUp; + Glacier::ZHandle m_ahMoveDown; + Glacier::ZHandle m_ahPrev; + Glacier::ZHandle m_ahNext; + Glacier::ZHandle m_ahMenu; + Glacier::ZHandle m_ahMap; + Glacier::ZREF m_rBackgroundCamera; + Glacier::ZREF m_rMapCamera; + Glacier::ZREF m_rOverlayCamera; + Glacier::ZREF m_rIconCamera; + Glacier::ZREF m_rIconGroup; + Glacier::ZREF m_rReferenceCamera; + Glacier::ZREF m_rZoomCursor; + Glacier::ZREF m_rPanCursor; + Glacier::ZREF m_rBackgroundGroup; + Glacier::ZREF m_rOverlayGroup; + Glacier::ZREF m_rZoomBox; + Glacier::ZREF m_rSelectionList; + Glacier::ZREF m_rCurrentMapTitle; + Glacier::ZREF m_rLegendButton; + Glacier::REFTAB32 m_rtButtons; + Glacier::ZREF m_rCompass; + SMapGroup* m_pLegendGroup; + Glacier::ZREF m_rReferenceMap; + Glacier::REFTAB m_rtGroups; + int32_t m_iCurrentMapIndexOffset; + CMapIconDraw* m_pDraw; + Glacier::REFTAB m_rtIcons; + Glacier::REFTAB m_rtTexts; + Glacier::ZVector2 m_v2MapPosition; + Glacier::ZVector2 m_v2MousePosition; + Glacier::ZVector3 m_vOldCamPos; + Glacier::ZVector3 m_vOldZoomBoxPos; + Glacier::ZVector3 m_vZoomPanMin; + Glacier::ZVector3 m_vZoomPanMax; + Glacier::ZMat3x3 m_mBoxMat; + float m_fZoomBoxStartScale; + float m_fZoomBoxEndScale; + float m_fCurrentScale; + float m_fScalePul; + Glacier::ZVector2 m_v2SubScale; + Glacier::ZVector2 m_v2MouseStartPosition; + float m_fMouseDownTime; + Glacier::ZGROUP* m_pCurSniperOverlay; + bool m_bMapListOpen; + bool m_bShowingLegend; + bool m_bScopecameraDeactivatedOnWindowOpen; + bool m_bMouseInside; + bool m_bMouseMoving; + bool m_bLMouseDown; + bool m_bCrossHack; + bool m_bWasEnable4_3CutOff; + bool m_bZoom_Pressed; + bool m_bPan_Pressed; + RE_ADD_PADDING(2); + Glacier::ZREF m_sound_Moving; + uint32_t m_lRemMaxFrameInterval; + SMapGroup* m_pCurrentMap; + SMapGroup* m_pLastMap; + Glacier::ZREF m_rTmpMapGroup; + Glacier::ZREF m_rTmpWorldGroup; + Glacier::ZREF m_rHintObject; + Glacier::TIMETYPE m_fHintTimeout; }; + RE_VERIFY_SIZE(CIngameMap, 0x2C4); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/CTelePortList.h b/ReHitman/BloodMoney/include/BloodMoney/Game/CTelePortList.h index 9c51981..8e50fcd 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/CTelePortList.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/CTelePortList.h @@ -1,17 +1,23 @@ #pragma once #include -#include +#include +#include -namespace Hitman::BloodMoney { - class CTelePortList : public Glacier::ZEventBase { +namespace Hitman::BloodMoney +{ + class CTelePortList : public Glacier::CBaseEvent + { public: // size is 0x3C - int m_field30; - int m_field34; - Glacier::ZREF m_targetREF; // REF to entity who will be teleported to position + int32_t m_iCurPos; + uint32_t m_iKey; + Glacier::ZREF m_rObject; // REF to entity who will be teleported to position // public API void TeleportToPointAtIndex(int index); }; + RE_VERIFY_SIZE(CTelePortList, 0x3C); // Verified + RE_VERIFY_OFFSET(CTelePortList, m_iCurPos, 0x30); + RE_VERIFY_OFFSET(CTelePortList, m_iKey, 0x34); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Elevator/CElevatorHouse.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Elevator/CElevatorHouse.h index 3b13a12..6e278b2 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Elevator/CElevatorHouse.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Elevator/CElevatorHouse.h @@ -1,12 +1,12 @@ #pragma once -#include +#include #include #include #include namespace Hitman::BloodMoney { - class CElevatorHouse : public Glacier::ZEventBase { + class CElevatorHouse : public Glacier::ZBaseConRout { public: // vftable (not changed) diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Globals.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Globals.h index 7342873..57cbac0 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Globals.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Globals.h @@ -2,6 +2,17 @@ #include + +namespace Glacier +{ + class ZSysInterfaceWintel; +} + +namespace Hitman::BloodMoney +{ + class ZHM3GameData; +} + namespace Hitman::BloodMoney::Globals { static constexpr std::uintptr_t kSysInterfaceAddr = 0x00820820; @@ -11,4 +22,8 @@ namespace Hitman::BloodMoney::Globals static constexpr std::uintptr_t kActionManagerAddr = 0x008ACAC4; static constexpr std::uintptr_t kD3DDllAddr = 0x008ACA30; static constexpr std::uintptr_t kSysInputAddr = 0x008ACAA0; -} \ No newline at end of file +} + +// NEW: I will try to migrate to global vars like in G1HBM +extern Glacier::ZSysInterfaceWintel*& g_pSysInterface; +extern Hitman::BloodMoney::ZHM3GameData*& g_pGameData; \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EAmmoType.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EAmmoType.h new file mode 100644 index 0000000..132b09e --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EAmmoType.h @@ -0,0 +1,14 @@ +#pragma once + + +namespace Hitman::BloodMoney +{ + enum EAmmoType { + eNormalAmmo = 0, + eLowVelAmmo = 1, + eHighVelAmmo = 2, + eAmmoPiercingAmmo = 3, + e45CalAmmo = 4, + eMagnumAmmo = 5, + }; +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EHM3ItemType.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EHM3ItemType.h index 963bbaa..a1ed6fd 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EHM3ItemType.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EHM3ItemType.h @@ -3,326 +3,327 @@ namespace Hitman::BloodMoney { enum class EHM3ItemType : int { - NoType = 1, - Item_LockPick, - Custom_Pistol, - Custom_Pistol_PICKUP, - Custom_SniperRifle, - Custom_SubMachineGun, - Custom_AssaultRifle, - Custom_ShotGun, - Equip_Bomb_01, - Equip_BombRemote_01, - Gun_Browning_01, - Gun_DesertEagle_01, - Gun_HKusp_01, - Gun_HKusp_Silenced_01, - Gun_Mauser_01, - Gun_PropMauser_01, - Gun_NailGun_01, - Gun_SixShooter_01, - Gun_SnubNosed_01, - Gun_Taurus_01, - Gun_Albino_01, - Rifle_Airrifle_01_unused, - Rifle_Airrifle_Tranquilizer_01, - Rifle_Enfield_01, - Rifle_FN2000_01, - Rifle_M14_01, - Rifle_Remington_01, - Rifle_SG552_01, - Sniper, - SniperRifle_Browning_01, - SniperRifle_Dragunov_01, - SniperRifle_SakoTRG_01, - SMG_FamaeSAF_01, - SMG_MP5_01, - SMG_MP7_01, - SMG_RugerMP9_01, - SMG_SteyrTMP_01, - CC_BaseballBat_01, - CC_FiberWire_01, - CC_FireExtinguisher_01, - CC_Knife_Bowie_01, - CC_Knife_Butterfly_01, - CC_Knife_Kitchen_01, - CC_Knife_Throwing_01, - CC_NailFile_01, - CC_Pens_01, - CC_PickAxe_01, - CC_StunGun_01, - CC_Sword_Cane_01, - CC_Sword_Cane_03, - CC_Sword_Marine_01, - CC_Syringe_Anastetic_01, - CC_Syringe_HeartAttack_01, - CC_Syringe_Laxative_01, - CC_Syringe_Poison_01, - CC_HedgeCutter_01, - CC_Pitchfork_01, - CloseCombatSword, - CloseCombatChloroform, - CloseCombatGolfclub, - CloseCombatKitchenKnife, - Suitcase, - KeyLocker, - FlowerBuket_01, - CrateGrocery, - PartyInvitation_01, - WineGlass_01, - Sausages_01, - Ammo_45ACP_01, - Ammo_Blank, - Ammo_Dart_Tranquilizer_01, - Ammo_Magnum_01, - Ammo_NailGun_01, - Ammo_Pistol_01, - Ammo_Prop_Mauser_01, - Ammo_Rifle_01, - Ammo_ShotGun_01, - Ammo_SMG_01, - Ammo_Sniper_01, - Ammo_Custom_AssaultRifle_01, - Ammo_Custom_Pistol_01, - Ammo_Custom_ShotGun_01, - Ammo_Custom_Sniper_01, - Ammo_Custom_SubMachineGun_01, - Scope_CameraTV_01, - Item_Poison_01, - Item_Cello_01, - Item_Cello_Bow_01, - Item_KeyCard_LightControl_01, - Container_ToolBoxCarpenter_01, - Item_WardrobeTicket_01, - Item_NoteExecutioner_01, - Container_SuitcaseNegotiator_01, - Container_ToolBoxMechanic_01, - Item_BrothelPass_01, - Food_GlassDrink_01, - Container_RifleFlightcase_01, - Item_MaskParty_01, - Item_KeyStorage_01, - Container_CrateKitchen_01, - Item_KeyCard_Elevator_01, - Al07_Food, - Item_KeyM11Office, - Container_BeerCase_01, - Container_BibleHollow_01, - Container_Briefcase_01, - Container_Briefcase_Afrikaner_01, - Container_Briefcase_Diamonds_01, - Container_Briefcase_Sheik_01, - Container_BucketChicken_01, - Container_CrateCatering_01, - Container_CrateDonuts_01, - Container_GarbageCan_01, - Container_GiftBox_01, - Container_Rifle_01, - Food_Aphrodiciac_01, - Food_BottleBaklava_01, - Food_BottleChampagne_01, - Food_BottleCleanser_01, - Food_BottleLiqour_01, - Food_BottleMartini_01, - Food_BottlePort_01, - Food_BottleVodka_01, - Food_BottleWhiskey_01, - Container_Cake_01, - Food_ChickenMorsel_01, - Food_CupCoffee_01, - Food_FlaskMetal_01, - Food_GlassLiquor_01, - Food_GlassMartini_01, - Food_GlassWine_01, - Food_SantaPort_01, - Item_AdmissionPaper_01, - Item_Balloon_01, - Item_BoxClosed_01, - Item_CartLaundry_01, - Item_CoffeeMachine_01 = 0x88, - Item_Diamonds_01, - Item_DNA_01, - Item_HatDevil_01, - Item_HatEngel_01, - Item_HatUnicorn_01, - Item_HeartVIP_01, - Item_HelmetPilot_01, - Item_KeyBoat_01, - Item_KeyCard_01, - Item_KeyCard_Cabin_01, - Item_KeyCard_Cabin_02, - Item_KeyCard_Cabin_03, - Item_KeyCard_Cabin_Master_01, - Item_KeyCard_Universal_01, - Item_KeyCard_WH_01, - Item_KeyCard_WH_Senior_01, - Item_KeyClinicCells_01, - Item_KeyClinicRoom_01, - Item_KeyCrew_01, - Item_KeyHelicopter_01, - Item_KeyMansion_01, - Item_KeyPoolHouse_01, - Item_KeySedanLuxury_01, - Item_Money_01, - Item_Necklace_01, - Item_NoteRifle_01, - Item_ParcelPictures_01, - Item_PartyInvitation_01, - Item_PassLounge_01, - Item_PassVIP_01 = 0xA6, - Item_PhoneNumberSheik_01, - Item_PhotoHitman_01, - Item_PhotosGovSon_01, - Item_Poison_01_DUP, //dup - Item_Radio_01, - Item_Sack_01, - Food_Sausage_01, - Item_VestKevlar_01, - Item_WalkieTalkie_01, - Scope_Camera_01, - Scope_CameraTV_01_DUP, //dup - Equip_Goggles_NV_01, - Food_Burger_01, - Food_Burger_02, - Food_BottleBeer_01, - Item_PyroFlaskExplodes_01, - Item_PyroFlask_01, - Item_GunMauser_01, - Item_KeyStorage_01_DUP, //dup - Gun_SnubNosed_01_DUP, //dup - CC_Scythe_01, - CC_Knife_Stiletto_01, - Item_Pen_01, - Item_Paper_01, - Item_Dishcloth_01, - Item_Dumbbell_01, - Item_ChipsMoney_01, - Food_BottleBeer_01_DUP, //dup - Container_SuitcaseSniper_01, - Item_PhotoTarget1_01, - Item_PhotoTarget2_01, - Item_PhotoTarget3_01, - CC_Syringe_HeartAttack_01_2, //dup - CC_Knife_MeatCleaver_01, - CC_Hammer_01, - CC_Shovel_01, - Food_GlassWhisky_01, - Item_MobilePhone_01, - Item_WaitressTray_01, - Item_FishingPole_01, - Item_FishingRod_01, - Item_KeyCard_Universal_02_01, - Item_SecurityDevice_01, - Item_BookSmallLeft_01, - Item_Scope_SLRCamera_01, - Item_Scope_SLRCameraFlash_01, - Item_VHSCassette_01, - Item_GasolineCan_01, - Item_Tray_01, - Container_TrayBurger_01, - Item_Plate_01, - Item_TeddyBear_01, - Item_PoolCleanerNet_01, - Item_BalloonDeflated_01, - Item_BalloonSmall_01, - Item_BalloonMedium_01, - Item_BalloonLarge_01, - Item_KeyCard_Hitman_01, - Item_medicineTray_01, - Item_VoiceRecorder_01, - Item_KeyCard_Afrikaaner_01, - Item_Microphone_01, - Item_Paintbrush_01, - Item_Book_01, - Item_GiftPackage_01, - Item_trash_01, - Item_Fork_01, - Item_Knife_01, - CC_Screwdriver_01, - Item_KeyCard_Rehab_01, - Food_BottleEmpty_01, - Food_BottleCoke_01, - Item_WhitehousePaper_01, - Item_CroupierRake_01, - Item_ChipsMoneyA_01, - Item_Shoes_01, - Item_Sponge_01, - Item_ThreeCards_01, - Item_CardFan_01, - Item_card_01, - Item_KeyCard_RatClub_01, - Item_Cigarette_01, - Item_KeyCard_Scientist_01, - Item_KeyCard_Samantha_01, - Item_KeyCard_Universal_03, - Item_KeyCard_Universal_02, - Item_KeyCard_Chemist_01, - Item_NoteRoomNumber707_01, - Item_BottleFireLighter_01, - Item_BottleEther_01, - Item_Scope_Video_Camera_01, - Item_QuarterBackPhoto_01, - Item_pillow_01, - Item_CigarUnLit_01, - Item_Cigar_01, - Item_Spoon_01, - Item_Thong_01, - Container_CrateBakingSoda_01, - Equip_PainKillers_01, - Equip_Binoculars_01, - Equip_Adrenaline_01, - Food_GlassEmpty_01, - Food_ChickenLeg_01, - Item_CigaretteLit_01, - Item_BookAnimated_01, - Item_BubblePack_01, - Pc09H_WeddingCake, - Equip_Suitcase_FoilPadded_01, - Equip_LockPick_03, - Equip_LockPick_02, - Equip_LockPick_01, - Equip_KevlarVest_01 = 0x116, - Equip_FlakVest_02, - Equip_FlakVest_01, - Equip_Binoculars_NV_01, - Equip_Binoculars_02, - Item_CelloBow_01, - Container_CakeHack_01, - CC_Sword_Cane_02, - Food_ChickenLeg_01_DUP, //dup - Food_GlassTim_01, - Item_BookAnimated_01_DUP, //dup - Item_BubblePack_01_DUP, //dup - Pc09H_WeddingCake_01, //dup - Item_WineBarrel_01, - Container_SuitcaseWoman_01, - Item_KeyCard_Universal_04, - Item_TVRemote_01, - Item_Donut_01, - Item_Rifle_Enfield_01, - Food_SteakCooked_01, - Item_SteakRaw_01, - Item_SteakJoint_01, - Item_Coin_01, - Item_Elephant, - Item_PhotoBoy_01, - Item_KeyCard_Room_704, - Item_KeyCard_Room_705, - Item_KeyCard_Room_706, - Item_KeyCard_Room_708, - Item_KeyCard_Room_801, - Item_KeyCard_Room_807, - Container_WaitressTray_01, - Item_Dart_Tranquilizer_01, - Item_NailFile_01, - CC_Syringe_Antidote_01, - CC_BaseballBat_Used_01, - CC_FireExtinguisher_Used_01, - CC_Shovel_Used_01, - CC_Hammer_Used_01, - CC_HedgeCutter_Used_01, - CC_PickAxe_Used_01, - CC_Screwdriver_Used_01, - Ammo_Magnum_02 = 0x140 + eHM3NoType = 0, + eHM3Lockpick = 1, + eHM3CustomHardballer = 2, + eHM3CustomHardballerPickup = 3, + eHM3CustomSniper = 4, + eHM3CustomSMG = 5, + eHM3CustomMG = 6, + eHM3CustomSG = 7, + eHM3RemoteBomb = 8, + eHM3RemoteControl = 9, + eHM3Gun_Browning_01 = 10, + eHM3Gun_DesertEagle_01 = 11, + eHM3Gun_HKusp_01 = 12, + eHM3Gun_HKusp_Silenced_01 = 13, + eHM3Gun_Mauser_01 = 14, + eHM3Gun_PropMauser_01 = 15, + eHM3Gun_NailGun_01 = 16, + eHM3Gun_SixShooter_01 = 17, + eHM3Gun_StubNosed_01 = 18, + eHM3Gun_Taurus_01 = 19, + eHM3Gun_Albino_01 = 20, + eHM3Rifle_Airrifle_01_unused = 21, + eHM3Rifle_Airrifle_Tranquilizer_01 = 22, + eHM3Rifle_Enfield_01 = 23, + eHM3Rifle_FN2000_01 = 24, + eHM3Rifle_M14_01 = 25, + eHM3Rifle_Remington_01 = 26, + eHM3Rifle_SG552_01 = 27, + eHM3Sniper = 28, + eHM3SniperRifle_Browning_01 = 29, + eHM3SniperRifle_Dragunov_01 = 30, + eHM3SniperRifle_SakoTRG_01 = 31, + eHM3SMG_FamaeSAF_01 = 32, + eHM3SMG_MP5_01 = 33, + eHM3SMG_MP7_01 = 34, + eHM3SMG_RugerMP9_01 = 35, + eHM3SMG_SteyrTMP_01 = 36, + eHM3CC_BaseballBat_01 = 37, + eHM3CC_FiberWire_01 = 38, + eHM3CC_FireExtinguisher_01 = 39, + eHM3CC_Knife_Bowie_01 = 40, + eHM3CC_Knife_Butterfly_01 = 41, + eHM3CC_Knife_Kitchen_01 = 42, + eHM3CC_Knife_Throwing_01 = 43, + eHM3CC_NailFile_01 = 44, + eHM3CC_Pens_01 = 45, + eHM3CC_PickAxe_01 = 46, + eHM3CC_StunGun_01 = 47, + eHM3CC_Sword_Cane_01 = 48, + eHM3CC_Sword_Cane_03 = 49, + eHM3CC_Sword_Marine_01 = 50, + eHM3CC_Syringe_Anastetic_01 = 51, + eHM3CC_Syringe_HeartAttack_01 = 52, + eHM3CC_Syringe_Laxative_01 = 53, + eHM3CC_Syringe_Poison_01 = 54, + eHM3CC_HedgeCutter_01 = 55, + eHM3CC_PitchFork_01 = 56, + eHM3CloseCombatSword = 57, + eHM3CloseCombatChloroform = 58, + eHM3CloseCombatGolfclub = 59, + eHM3CloseCombatKnife = 60, + eHM3Suitcase = 61, + eHM3Key = 62, + eHM3Flowers = 63, + eHM3GroceryCrate = 64, + eHM3PartyInvitation = 65, + eHM3WineGlass = 66, + eHM3Sausages = 67, + eHM3Ammo_45ACP_01 = 68, + eHM3AmmoBlank = 69, + eHM3Ammo_DartTranquilizer_01 = 70, + eHM3Ammo_Magnum_01 = 71, + eHM3AmmoNailGun = 72, + eHM3Ammo_Pistol_01 = 73, + eHM3Ammo_Prop_Mauser_01 = 74, + eHM3Ammo_Rifle_01 = 75, + eHM3Ammo_ShotGun_01 = 76, + eHM3Ammo_SMG_01 = 77, + eHM3Ammo_Sniper_01 = 78, + eHM3AmmoCustomAssaultRifle = 79, + eHM3AmmoCustomPistol = 80, + eHM3AmmoCustomShotGun = 81, + eHM3AmmoCustomSniper = 82, + eHM3AmmoCustomSubMachineGun = 83, + eHM3CameraTVCrew = 84, + eHM3Poison = 85, + eHM3M01Cello = 86, + eHM3M01CelloBow = 87, + eHM3M03KeycardLightControlRoom = 88, + eHM3M03ToolBoxCarpenter = 89, + eHM3M03WardropeTicket = 90, + eHM3M03NoteExecutioner = 91, + eHM3M07SuitcaseNegotiator = 92, + eHM3M07ToolboxMechanic = 93, + eHM3M07BrothelPass = 94, + eHM3M11FoodGlassdrink = 95, + eHM3M11FlightcaseRifle = 96, + eHM3M11PartyMask = 97, + eHM3M11KeyStorage = 98, + eHM3M11KitchenCrate = 99, + eHM3M11KeyCardElevator = 100, + eHM3M11Cake = 101, + eHM3M11KeyOffice = 102, + eHM3ContainerBeerCase = 103, + eHM3ContainerBibleHollow = 104, + eHM3ContainerBriefcase = 105, + eHM3ContainerBriefcaseAfrikaner = 106, + eHM3ContainerBriefcaseDiamonds = 107, + eHM3ContainerBriefcaseSheik = 108, + eHM3ContainerBucketChicken = 109, + eHM3ContainerCrateCatering = 110, + eHM3ContainerCrateDonuts = 111, + eHM3ContainerGarbageCan = 112, + eHM3ContainerGiftBox = 113, + eHM3ContainerRifle = 114, + eHM3FoodAphrodiciac = 115, + eHM3FoodBottleBaklava = 116, + eHM3FoodBottleChampagne = 117, + eHM3FoodBottleCleanser = 118, + eHM3FoodBottleLiqour = 119, + eHM3FoodBottleMartini = 120, + eHM3FoodBottlePort = 121, + eHM3FoodBottleVodka = 122, + eHM3FoodBottleWhiskey = 123, + eHM3ContainerCake = 124, + eHM3FoodChickenMorsel = 125, + eHM3FoodCupCoffee = 126, + eHM3FoodFlaskMetal = 127, + eHM3FoodGlassLiquor = 128, + eHM3FoodGlassMartini = 129, + eHM3FoodGlassWine = 130, + eHM3FoodSantaPort = 131, + eHM3ItemAdmissionPaper = 132, + eHM3ItemBalloon = 133, + eHM3ItemBoxClosed = 134, + eHM3ItemCartLaundry = 135, + eHM3ItemCoffeeMachine = 136, + eHM3ItemDiamonds = 137, + eHM3ItemDNA = 138, + eHM3ItemHatDevil = 139, + eHM3ItemHatEngel = 140, + eHM3ItemHatUnicorn = 141, + eHM3ItemHeartVIP = 142, + eHM3ItemHelmetPilot = 143, + eHM3ItemKeyBoat = 144, + eHM3ItemKeyCard = 145, + eHM3ItemKeyCard_Cabin_01 = 146, + eHM3ItemKeyCard_Cabin_02 = 147, + eHM3ItemKeyCard_Cabin_03 = 148, + eHM3ItemKeyCard_Cabin_Master_01 = 149, + eHM3ItemKeyCard_Universal = 150, + eHM3ItemKeyCard_WH = 151, + eHM3ItemKeyCard_WH_Senior = 152, + eHM3ItemKeyClinicCells = 153, + eHM3ItemKeyClinicRoom = 154, + eHM3ItemKeyCrew = 155, + eHM3ItemKeyHelicopter = 156, + eHM3ItemKeyMansion = 157, + eHM3ItemKeyPoolHouse = 158, + eHM3ItemKeySedanLuxury = 159, + eHM3ItemMoney = 160, + eHM3ItemNecklace = 161, + eHM3ItemNoteRifle = 162, + eHM3ItemParcelPictures = 163, + eHM3ItemPartyInvitation = 164, + eHM3ItemPassLounge = 165, + eHM3ItemPassVIP = 166, + eHM3ItemPhoneNumberSheik = 167, + eHM3ItemPhotoHitman = 168, + eHM3ItemPhotosGovSon = 169, + eHM3ItemPoison = 170, + eHM3ItemRadio = 171, + eHM3ItemSack = 172, + eHM3FoodSausage = 173, + eHM3ItemVestKevlar = 174, + eHM3ItemWalkieTalkie = 175, + eHM3ScopeCamera = 176, + eHM3ScopeCameraTV = 177, + eHM3EquipGogglesNV01 = 178, + eHM3FoodBurger01 = 179, + eHM3FoodBurger02 = 180, + eHM3FoodBottleBeer01 = 181, + eHM3ItemPyroFlaskExplodes01 = 182, + eHM3ItemPyroFlask01 = 183, + eHM3ItemGunMauser01 = 184, + eHM3ItemKeyStorage01 = 185, + eHM3GunSnubNosed01 = 186, + eHM3CCScythe01 = 187, + eHM3CCKnifeStiletto01 = 188, + eHM3ItemPen = 189, + eHM3ItemPaper = 190, + eHM3ItemDishCloth = 191, + eHM3ItemDumbbell = 192, + eHMItemChipsMoney = 193, + eHM3FoodBottleBeer = 194, + eHM3ContainerSuitcaseSniper01 = 195, + eHM3PhotoTarget1 = 196, + eHM3PhotoTarget2 = 197, + eHM3PhotoTarget3 = 198, + eHM3CCSyringeHeartAttack = 199, + eHM3CCKnifeMeatCleaver01 = 200, + eHM3CCHammer = 201, + eHM3CCShovel = 202, + eHM3FoodGlassWhisky = 203, + eHM3ItemMobilePhone = 204, + eHM3ItemWaitressTray = 205, + eHM3ItemFishingPole = 206, + eHM3ItemFishingRod = 207, + eHM3ItemKeyCardUniversal02 = 208, + eHM3ItemSecurityDevice = 209, + eHM3ItemBookSmallLeft = 210, + eHM3ItemScopeSLRCamera = 211, + eHM3ItemScopeSLRCameraFlash = 212, + eHM3ItemVHSCassette = 213, + eHM3ItemGasolineCan = 214, + eHM3ItemTray = 215, + eHM3ItemTrayBurger = 216, + eHM3ItemPlate = 217, + eHM3ItemTeddyBear = 218, + eHM3ItemPoolCleanerNet = 219, + eHM3ItemBalloonDeflated = 220, + eHM3ItemBalloonSmall = 221, + eHM3ItemBalloonMedium = 222, + eHM3ItemBalloonLarge = 223, + eHM3ItemKeyCardHitman = 224, + eHM3ItemmedicineTray = 225, + eHM3ItemVoiceRecorder = 226, + eHM3ItemKeyCardAfrikaaner = 227, + eHM3ItemMicrophone = 228, + eHM3ItemPaintbrush = 229, + eHM3ItemBook = 230, + eHM3ItemGiftPackage = 231, + eHM3Itemtrash = 232, + eHM3ItemFork = 233, + eHM3ItemKnife = 234, + eHM3CCScrewdriver01 = 235, + eHM3ItemKeyCard_Rehab = 236, + eHM3FoodBottleEmpty = 237, + eHM3FoodBottleCoke = 238, + eHM3ItemWhitehousePaper = 239, + eHM3ItemCroupierRake = 240, + eHM3ItemChipsMoneyA = 241, + eHM3ItemShoes = 242, + eHM3ItemSponge = 243, + eHM3ItemThreeCards = 244, + eHM3ItemCardFan = 245, + eHM3Itemcard = 246, + eHM3ItemKeyCard_RatClub = 247, + eHM3ItemCigarette = 248, + eHM3ItemKeyCardScientist = 249, + eHM3ItemKeyCardSamantha = 250, + eHM3ItemKeyCardUniversal_03 = 251, + eHM3ItemKeyCardUniversal_02 = 252, + eHM3ItemKeyCardChemist_01 = 253, + eHM3ItemNoteRoomNumber707 = 254, + eHM3ItemBottleFireLighter = 255, + eHM3ItemBottleEther = 256, + eHM3ItemScopeVideoCamera = 257, + eHM3ItemQuarterBackPhoto = 258, + eHM3Itempillow = 259, + eHM3ItemCigarUnLit = 260, + eHM3ItemCigar = 261, + eHM3ItemSpoon = 262, + eHM3ItemThong = 263, + eHM3ContainerCrateBakingSoda = 264, + eHM3PainKillers = 265, + eHM3Binoculars = 266, + eHM3Adrenaline = 267, + eHM3FoodGlassEmpty = 268, + eHM3FoodChickenLeg = 269, + eHM3ItemCigaretteLit = 270, + eHM3ItemBookAnimated = 271, + eHM3ItemBubblePack = 272, + eHM3Pc09H_WeddingCake = 273, + eHM3EquipSuitcaseFoilPadded = 274, + eHM3EquipLockPick03 = 275, + eHM3EquipLockPick02 = 276, + eHM3EquipLockPick01 = 277, + eHM3EquipKevlarVest01 = 278, + eHM3EquipFlakVest02 = 279, + eHM3EquipFlakVest01 = 280, + eHM3EquipBinocularsNV01 = 281, + eHM3EquipBinoculars02 = 282, + eHM3ItemCelloBow01 = 283, + eHM3ContainerCakeHack01 = 284, + eHM3CCSwordCane02 = 285, + eHM3FoodChickenLeg01 = 286, + eHM3FoodGlassTim01 = 287, + eHM3ItemBookAnimated01 = 288, + eHM3ItemBubblePack01 = 289, + eHM3Pc09HWeddingCake = 290, + eHM3ItemWineBarrel01 = 291, + eHM3ContainerSuitcaseWoman = 292, + eHM3ItemKeyCardUniversal_04 = 293, + eHM3ItemItemTVRemote = 294, + eHM3ItemItemDonut = 295, + eHM3ItemRifleEnfield = 296, + eHM3Food_SteakCooked = 297, + eHM3ItemSteakRaw = 298, + eHM3ItemSteakJoint = 299, + eHM3ItemCoin = 300, + eHM3ItemElephant = 301, + eHM3ItemPhotoBoy = 302, + eHM3ItemKeyCardRoom704 = 303, + eHM3ItemKeyCardRoom705 = 304, + eHM3ItemKeyCardRoom706 = 305, + eHM3ItemKeyCardRoom708 = 306, + eHM3ItemKeyCardRoom801 = 307, + eHM3ItemKeyCardRoom807 = 308, + eHM3ContainerWaitressTray = 309, + eHM3ItemAirgunDarts = 310, + eHM3ItemNailFile = 311, + eHM3CC_Syringe_Antidote_01 = 312, + eHM3CC_BaseballBat_Used_01 = 313, + eHM3CC_FireExtinguisher_Used_01 = 314, + eHM3CC_Shovel_Used_01 = 315, + eHM3CC_Hammer_Used_01 = 316, + eHM3CC_HedgeCutter_Used_01 = 317, + eHM3CC_PickAxe_Used_01 = 318, + eHM3CC_Screwdriver_Used_01 = 319, + eHM3Ammo_Magnum_02 = 320, + eHM3NumItems = 321, }; } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EHM3RecoilRandom.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EHM3RecoilRandom.h new file mode 100644 index 0000000..578b2a0 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EHM3RecoilRandom.h @@ -0,0 +1,12 @@ +#pragma once + + +namespace Hitman::BloodMoney +{ + enum EHM3RecoilRandom : int { + eNoRandom = 0, + eXRandom = 1, + eYRandom = 2, + eXYRandom = 3, + }; +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EHM3WeaponScope.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EHM3WeaponScope.h index 6522d06..adaaf06 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EHM3WeaponScope.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EHM3WeaponScope.h @@ -1,8 +1,9 @@ #pragma once namespace Hitman::BloodMoney { - enum class EHM3WeaponScope { - eHiTech, - eNoScope + enum class EHM3WeaponScope : int { + eNoScope = 0, + eNormal = 1, + eHiTech = 2, }; } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EScopeType.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EScopeType.h new file mode 100644 index 0000000..fdfc9d2 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/EScopeType.h @@ -0,0 +1,12 @@ +#pragma once + +namespace Hitman::BloodMoney +{ + enum EScopeType { + eNoScope = 0, + eStandardScope = 1, + eIncreasedZoomScope = 2, + eLargeScope = 3, + eNigtvisionScope = 4, + }; +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ESilencerType.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ESilencerType.h index 6fc6190..15ef0ad 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ESilencerType.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ESilencerType.h @@ -1,11 +1,11 @@ #pragma once namespace Hitman::BloodMoney { - enum class ESilencerType { - eSilentWithNoEvent, - eSilentOver20, - eSilentUpTo20, - eSilentLowVelocityAmmo, - eNotSilent + enum class ESilencerType : int { + eNotSilent = 0, + eSilentLowVelocityAmmo = 1, + eSilentUpTo20 = 2, + eSilentOver20 = 3, + eSilentWithNoEvent = 4, }; } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3Item.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3Item.h index 0250b0e..f71ff64 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3Item.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3Item.h @@ -15,11 +15,13 @@ namespace Hitman::BloodMoney virtual void UseItemActivateAnimation(); // data (total size is 0x9C, ZItem size is 0x84) - int m_field84; - int m_field88; - EHM3ItemType m_itemType; - int m_field90; - int m_field94; - int m_field98; + Glacier::ZLNKOBJ* m_pGround; + Glacier::Animation::Header* m_pAnimUse; + EHM3ItemType m_eOverriddenType; + uint32_t m_ItemProperties; + uint32_t m_iNumBitesRemoved; + bool m_bForceUnpickable; + RE_ADD_PADDING(3); }; + RE_VERIFY_SIZE(ZHM3Item, 0x9C); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemAmmo.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemAmmo.h index efde314..c041669 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemAmmo.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemAmmo.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -11,4 +12,5 @@ namespace Hitman::BloodMoney // vftable virtual EHM3ItemType GetHM3ItemType(); }; + RE_VERIFY_SIZE(ZHM3ItemAmmo, 0x88); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemBomb.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemBomb.h index da7bb61..ab23d88 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemBomb.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemBomb.h @@ -1,6 +1,8 @@ #pragma once +#include #include +#include #include namespace Hitman::BloodMoney @@ -12,47 +14,20 @@ namespace Hitman::BloodMoney void Explode(); // data (total size is 0x2A0, base size is 0x15C) - bool m_field15C; - bool field_15D; - bool field_15E; - bool field_15F; - int m_field160; - int m_field164; - int m_field168; - int m_field16C; - int m_field170; - int m_field174; - int m_field178; - int m_field17C; - int m_field180; - int m_field184; - int m_field188; - int m_field18C; - int m_field190; - int m_field194; - int m_field198; - int m_field19C; - int m_field1A0; - int m_field1A4; - int m_field1A8; - int m_field1AC; - int m_field1B0; - int m_field1B4; - int m_field1B8; - int m_field1BC; - int m_field1C0; - int m_field1C4; - int m_field1C8; - int m_field1CC; - int m_field1D0; - int m_field1D4; - int m_field1D8; - int m_field1DC; - int m_field1E0; - int m_field1E4; - Glacier::REFTAB32 m_reftab32; - int m_field294; - int m_field298; - int m_field29C; + bool m_bExploded; + bool m_bExploding; + bool m_bTimerActivated; + RE_ADD_PADDING(1); + uint32_t m_iNumberOfTargets; + Glacier::ZBaseGeom* m_pTargets[30]; + uint32_t m_iTargetCheck; + Glacier::TIMETYPE m_ttTimeToExplode; + uint32_t m_iNumberOfLines; + Glacier::REFTAB32 m_Lines; + Glacier::ZGEOM* m_pPlaceBombActionGeom; + uint32_t m_nTopEvCamId; + Glacier::TIMETYPE m_ttTopViewCamStartTime; + }; + RE_VERIFY_SIZE(ZHM3ItemBomb, 0x2A0); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemContainer.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemContainer.h index 3afa913..a906f23 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemContainer.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemContainer.h @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include @@ -13,7 +15,9 @@ namespace Hitman::BloodMoney virtual bool IsDetectable(); // data (total size is 0xD0, ZItemContainer size is 0xC8) - int m_fieldC8; - int m_fieldCC; + Glacier::ZLNKOBJ* m_pGround; + bool m_bForceUnpickable; + RE_ADD_PADDING(3); }; + RE_VERIFY_SIZE(ZHM3ItemContainer, 0xD0); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplate.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplate.h index f6e4124..ba795dc 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplate.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplate.h @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include @@ -12,13 +14,17 @@ namespace Hitman::BloodMoney virtual EHM3ItemType GetHM3ItemType(); // data (total size is 0x94, ZItemTemplate size is 0x74) - EHM3ItemType m_itemType; - int m_field78; - int m_field7C; - int m_field80; - int m_field84; - int m_field88; - int m_field8C; - int m_field90; + EHM3ItemType m_eHM3ItemType; + Glacier::ZRTString m_szHM3NormalHoldAnim; + Glacier::ZRTString m_szHM3RunHoldAnim; + Glacier::ZRTString m_szActorHoldAnim; + int m_nHM3NormalHoldAnimIdx; + int m_nHM3RunHoldAnimIdx; + int m_nActorHoldAnimIdx; + uint8_t m_iNumBites; + bool m_bDrinkable; + bool m_bEdible; + RE_ADD_PADDING(1); }; + RE_VERIFY_SIZE(ZHM3ItemTemplate, 0x94); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateAmmo.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateAmmo.h index 534d246..b80dc5c 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateAmmo.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateAmmo.h @@ -12,6 +12,8 @@ namespace Hitman::BloodMoney virtual EHM3ItemType GetHM3ItemType(); //data (total size is 0xA8, Glacier::ZItemTemplateAmmo size is 0xA4) - EHM3ItemType m_itemType; + EHM3ItemType m_eHM3ItemType; }; + RE_VERIFY_SIZE(ZHM3ItemTemplateAmmo, 0xA8); // Verified + RE_VERIFY_OFFSET(ZHM3ItemTemplateAmmo, m_eHM3ItemType, 0xA4); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateAmmoCustom.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateAmmoCustom.h index 7e92392..5802c2b 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateAmmoCustom.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateAmmoCustom.h @@ -1,19 +1,36 @@ #pragma once +#include +#include + #include -#include +#include +#include +#include + namespace Hitman::BloodMoney { class ZHM3ItemTemplateAmmoCustom : public ZHM3ItemTemplateAmmo { public: + struct SDefaultValues // Тип 3358 + { + int32_t m_lProjectilesPerMagazine; + int32_t m_lProjectilesPerShot; + float m_fNearDamage; + float m_fFarDamage; + bool m_bCanPenetrate; + RE_ADD_PADDING(3); + }; + RE_VERIFY_SIZE(SDefaultValues, 0x14); + // data (total size is 0xC0, ZHM3ItemTemplateAmmo size is 0xA8) - int m_fieldA8; - int m_fieldAC; - int m_fieldB0; - int m_fieldB4; - int m_fieldB8; - int m_fieldBC; + SDefaultValues m_DefaultValues; + bool m_bCanPenetrate; + RE_ADD_PADDING(3); }; + RE_VERIFY_SIZE(ZHM3ItemTemplateAmmoCustom, 0xC0); // Verified + RE_VERIFY_OFFSET(ZHM3ItemTemplateAmmoCustom, m_DefaultValues, 0xA8); + RE_VERIFY_OFFSET(ZHM3ItemTemplateAmmoCustom, m_bCanPenetrate, 0xBC); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateBomb.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateBomb.h index 2c22f28..8adbf0c 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateBomb.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateBomb.h @@ -1,5 +1,7 @@ #pragma once +#include +#include #include namespace Hitman::BloodMoney @@ -8,10 +10,11 @@ namespace Hitman::BloodMoney { public: // data (total size is 0x1B4, base size is 0x1A0) - int m_field1A0; - int m_field1A4; - int m_field1A8; - int m_field1AC; - int m_field1B0; + float m_fMaxDamage; + float m_fMaxDamageRange; + float m_fMaxRange; + float m_fExplodeTimer; + Glacier::ZGROUP* m_pEffectGroup; }; + RE_VERIFY_SIZE(ZHM3ItemTemplateBomb, 0x1B4); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateContainer.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateContainer.h index 335de3c..3dc67b1 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateContainer.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateContainer.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -12,14 +13,13 @@ namespace Hitman::BloodMoney virtual EHM3ItemType GetHM3ItemType(); //data (total size is 0xB4, ZItemTemplateContainer is 0x90) - int m_field90; - int m_field94; - EHM3ItemType m_itemType; - int m_field9C; - int m_fieldA0; - int m_fieldA4; - int m_fieldA8; - int m_fieldAC; - int m_fieldB0; + EHM3ItemType m_eHM3ItemType; + Glacier::ZRTString m_szHM3NormalHoldAnim; + Glacier::ZRTString m_szHM3RunHoldAnim; + Glacier::ZRTString m_szActorHoldAnim; + int m_nHM3NormalHoldAnimIdx; + int m_nHM3RunHoldAnimIdx; + int m_nActorHoldAnimIdx; }; + RE_VERIFY_SIZE(ZHM3ItemTemplateContainer, 0xB4); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateWeapon.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateWeapon.h index bbe395e..0b0ca9d 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateWeapon.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemTemplateWeapon.h @@ -1,9 +1,15 @@ #pragma once +#include +#include +#include #include + +#include #include #include #include +#include namespace Hitman::BloodMoney { @@ -28,22 +34,24 @@ namespace Hitman::BloodMoney virtual void* GetClipParticleControl(bool); //data (total size is 0x1A0, ZItemTemplateWeapon size is 0x15C) - int m_field15C; - EHM3ItemType m_eWeaponType; - int m_field164; - int m_field168; - int m_field16C; + Glacier::ZAnimVariationHandle m_1stPersonAimId; + Glacier::ZAnimVariationHandle m_1stPersonRecoilId; + EHM3ItemType m_eHM3ItemType; + ZHM3ClipParticleControl* m_pClipParticleControl; + ZHM3ClipParticleControl* m_pFireShellParticleControl; + EHM3RecoilRandom m_eHM3RecoilRandom; float m_fRecoilStrengthX; float m_fRecoilStrengthY; - EHM3WeaponScope m_eScopeType; - int m_field17C; - int m_field180; - int m_field184; - int m_field188; - int m_field18C; - int m_field190; - int m_field194; - int m_field198; + EHM3WeaponScope m_eScope; + Glacier::ZRTString m_pAnimNameActorReload; + Glacier::ZRTString m_pAnimNameActorChamber; + Glacier::ZRTString m_pAnimName1stPersonAim; + Glacier::ZRTString m_pAnimName1stPersonRecoil; + float RecognitionDistance; + float m_PelvisUpDown; + float m_PelvisFrontBack; + float m_PelvisLeftRight; ESilencerType m_eSilencerType; }; + RE_VERIFY_SIZE(ZHM3ItemTemplateWeapon, 0x1A0); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeapon.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeapon.h index 2fe1a2a..0a7542e 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeapon.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeapon.h @@ -2,10 +2,14 @@ #include #include +#include #include namespace Hitman::BloodMoney { + using ZStackArrayItemWeaponMetaKeyEvents = Glacier::ZStackArrayInsert<5, int, float>; + RE_VERIFY_SIZE(ZStackArrayItemWeaponMetaKeyEvents, 44); + class ZHM3ItemWeapon : public Glacier::ZItemWeapon { public: @@ -24,38 +28,25 @@ namespace Hitman::BloodMoney virtual bool IsDetectable(); //always true //data (total size is 0x15C, ZItemWeapon size is 0xDC) - int m_fieldDC; - int m_fieldE0; - int m_fieldE4; - int m_fieldE8; - int m_fieldEC; - int m_fieldF0; - int m_fieldF4; - int m_fieldF8; - int m_fieldFC; - int m_field100; - int m_field104; - int m_field108; - int m_clipBoneNr; - int m_field110; - int m_field114; - int m_field118; - int m_field11C; - int m_field120; - Glacier::ZGEOM* m_pRootGeom; - int m_field128; - int m_field12C; - int m_field130; - int m_field134; - int m_field138; - int m_field13C; - int m_field140; - int m_field144; - int m_field148; - int m_field14C; - int m_field150; - int m_field154; - int m_field158; + float m_fRecoilValues[5]; + float m_fRecoilDamping; + float m_fRecoilShotImpact; + float m_fRecoilMasterValue; + Glacier::Animation::Header* m_pAnimReload; + Glacier::Animation::Header* m_pAnimFire; + Glacier::Animation::Header* m_pAnimChamber; + Glacier::Animation::Header* m_pAnimUse; + int32_t m_iClipBoneNr; + int32_t m_nCurFrame; + Glacier::ZVector3 m_vClipPosOld; + bool m_bDualWeapon; + bool m_bBeingReloaded; + bool m_bSixShooter; + RE_ADD_PADDING(1); + Glacier::ZLNKOBJ* m_pGround; + Glacier::ZREF m_rCurrentSound; + Glacier::Animation::ActiveAnimation* m_pBoneAnim; + ZStackArrayItemWeaponMetaKeyEvents m_MetaKeyEvents; }; - + RE_VERIFY_SIZE(ZHM3ItemWeapon, 0x15C); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeaponCustom.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeaponCustom.h index 46c9459..81fd7ea 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeaponCustom.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeaponCustom.h @@ -2,9 +2,12 @@ #include #include +#include namespace Hitman::BloodMoney { + using ZStackArrayVisibleBones = Glacier::ZStackArray<20, uint32_t>; + class ZHM3ItemWeaponCustom : public ZHM3ItemWeapon { public: @@ -19,30 +22,11 @@ namespace Hitman::BloodMoney void SetSilencerType(ESilencerType type); // data (new size is 0x1C0) - int m_field15C; - int m_field160; - int m_field164; - int m_field168; - int m_field16C; - int m_field170; - int m_field174; - int m_field178; - int m_field17C; - int m_field180; - int m_field184; - int m_field188; - int m_field18C; - int m_field190; - int m_field194; - int m_field198; - int m_field19C; - int m_field1A0; - int m_field1A4; - int m_field1A8; - ESilencerType m_eSilencerType; - int m_anim_Reload_Bolt; - int m_anim_Reload_DoubleClip; - int m_anim_Reload_100shot; - int m_field1BC; + ZStackArrayVisibleBones m_VisibleBones; + Glacier::Animation::Header* m_pAnimReloadBoltAction; + Glacier::Animation::Header* m_pAnimReloadDoubleCapMag; + Glacier::Animation::Header* m_pAnimReloadBeltFeeding; + int32_t m_nNumOfReloads; }; + RE_VERIFY_SIZE(ZHM3ItemWeaponCustom, 0x1C0); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeaponCustomTemplate.h b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeaponCustomTemplate.h index f354bbe..e2915bd 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeaponCustomTemplate.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/Items/ZHM3ItemWeaponCustomTemplate.h @@ -1,39 +1,75 @@ #pragma once +#include +#include +#include +#include #include +#include +#include +#include + + +#include namespace Hitman::BloodMoney { class ZHM3ItemWeaponCustomTemplate : public ZHM3ItemTemplateWeapon { public: + // types + struct SCustomWeaponData { + ESilencerType m_eSilencerType; + EScopeType m_eScopeType; + Glacier::EWeaponOperation m_eWeaponOperation; + EAmmoType m_eAmmoType; + bool m_bNightVision : 1; + bool m_bLaserIndicator : 1; + bool m_bRedDot : 1; + bool m_bFlashLight : 1; + bool m_bDoubleCapacityAmmo : 1; + bool m_bHasMagazine : 1; + bool m_bBiPod : 1; + bool m_bLightWeightFrame : 1; + bool m_bBarrelExtension : 1; + bool m_bReloadBoost : 1; + bool m_bTrippleAmmo : 1; + }; + RE_VERIFY_SIZE(SCustomWeaponData, 0x14); + + struct SDefaultValues + { + uint32_t m_WeaponOperations; + float m_fMuzzleVelocity; + float m_fPrecisionDeg; + float m_fNearRange; + float m_fFarRange; + float m_fDamageMultiplier; + float m_fImpact; + float m_fTimeBetweenShot; + bool m_bCanFireProjectiles; + bool m_bCanHaveMagazines; + bool m_bSniperMode; + RE_ADD_PADDING(1); + int32_t m_eHM3RecoilRandom; + float m_fRecoilStrengthX; + float m_fRecoilStrengthY; + int32_t m_eScope; + int32_t m_eSilencerType; + }; + RE_VERIFY_SIZE(SDefaultValues, 0x38); + /// vftable virtual void* GetCustomData(); virtual void SetMuzzleVelocity(float); /// data (total size is 0x1FC, base size is 0x1A0) - int m_field1A0; - int m_field1A4; - int m_field1A8; - int m_customData; - int m_field1B0; - int m_field1B4; - int m_field1B8; - int m_field1BC; - int m_field1C0; - int m_field1C4; - int m_field1C8; - int m_field1CC; - int m_field1D0; - int m_field1D4; - int m_field1D8; - int m_field1DC; - int m_field1E0; - int m_field1E4; - int m_field1E8; - int m_field1EC; - int m_field1F0; - int m_field1F4; - int m_field1F8; + Glacier::REFTAB* m_pUpgrades; + ZHM3ClipParticleControl* m_pLargeClipParticleControl; + ZHM3ClipParticleControl* m_pShellParticleControl; + SCustomWeaponData m_CustomData; + SDefaultValues m_DefaultValues; + Glacier::ZAnimVariationHandle m_CustomHBAnimHandle; }; + RE_VERIFY_SIZE(ZHM3ItemWeaponCustomTemplate, 0x1FC); // Verfied } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ESecurityZone.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ESecurityZone.h index 719abe3..68b448f 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ESecurityZone.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ESecurityZone.h @@ -2,8 +2,15 @@ namespace Hitman::BloodMoney { - enum ESecurityZone - { - + enum ESecurityZone { + eZoneUNDEFINED = 0, + eZone1 = 1, + eZone2 = 2, + eZone2A = 4, + eZone2B = 8, + eZone3 = 16, + eZone3A = 32, + eZone3B = 64, + eZoneMegaForbidden = 128, }; } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControl.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControl.h index 92ed66f..56ddeed 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControl.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControl.h @@ -1,16 +1,20 @@ #pragma once #include -#include +#include #include #include +#include +#include #include +#include #include #include namespace Hitman::BloodMoney { + class ZHM3Actor; class ZHM3HmAs; class ZHM3Item; class ZHM3ItemBomb; @@ -19,7 +23,12 @@ namespace Hitman::BloodMoney class ZMusicController; - class ZHM3LevelControl : public Glacier::ZEventBase + class ZHitmanWeaponStorage; + class ZPostFilterCollectionEvent; + class ZPostFilterEvent; + class ZPostFilterSetEvent; + + class ZHM3LevelControl : public Glacier::CBaseEvent { public: // vftable @@ -109,157 +118,55 @@ namespace Hitman::BloodMoney * M13 - 0x668 * * So, total size of class is 0x5E0, ZEventBase size is 0x30 + * + * 21.06.26: Updated base size to 0x5D8 because base class data found in PS2 build. */ - int m_field30; - ZMusicController* m_musicController; - Glacier::ZSDOwner m_sdOwner; - int m_field48; - Glacier::REFTAB m_reftab4C; - int m_hashTab68; - int m_field6C; - int m_field70; - int m_field74; - int m_field78; - int m_field7C; - int m_field80; - int m_field84; - int m_hashTab88; - int m_field8C; - int m_field90; - int m_field94; - int m_field98; - int m_field9C; - int m_fieldA0; - int m_fieldA4; - int m_fieldA8; - int m_fieldAC; - int m_fieldB0; - int m_fieldB4; - int m_fieldB8; - int m_fieldBC; - int m_fieldC0; - int m_fieldC4; - int m_fieldC8; - int m_fieldCC; - int m_fieldD0; - int m_fieldD4; - int m_fieldD8; - int m_fieldDC; - int m_fieldE0; - int m_fieldE4; - int m_fieldE8; - int m_fieldEC; - int m_fieldF0; - int m_fieldF4; - int m_fieldF8; - int m_fieldFC; - int m_field100; - int m_field104; - int m_field108; - int m_field10C; - int m_field110; - int m_field114; - int m_field118; - int m_field11C; - int m_field120; - int m_field124; - int m_field128; - int m_field12C; - int m_field130; - int m_field134; - int m_field138; - int m_field13C; - int m_field140; - int m_field144; - int m_field148; - int m_field14C; - int m_field150; - int m_field154; - int m_field158; - int m_field15C; - int m_field160; - int m_field164; - int m_field168; - int m_field16C; - int m_field170; - int m_field174; - int m_field178; - int m_field17C; - int m_field180; - int m_field184; - int m_field188; - int m_field18C; - int m_field190; - int m_field194; - int m_field198; - int m_field19C; - int m_field1A0; - int m_field1A4; - int m_field1A8; - int m_field1AC; - char m_field1B0; - char field_1B1; - char field_1B2; - char field_1B3; - int m_field1B4; - int m_field1B8; - int m_field1BC; - int m_field1C0; - int m_field1C4; - int m_field1C8; - int m_field1CC; - int m_field1D0; - int m_field1D4; - int m_field1D8; - int m_field1DC; - int m_field1E0; - int m_field1E4; - int m_field1E8; - Glacier::REFTAB m_reftab1EC; - Glacier::REFTAB32 m_reftab32_208; - int m_field2B4; - int m_field2B8; - int m_field2BC; - char m_field2C0; - char field_2C1; - char field_2C2; - char field_2C3; - int m_field2C4; - int m_field2C8; - int m_field2CC; - int m_field2D0; - int m_field2D4; - int m_field2D8; - int m_field2DC; - int m_field2E0; - int m_field2E4; - int m_field2E8; - int m_field2EC; - int m_field2F0; - int m_field2F4; - int m_field2F8; - int m_field2FC; - int m_field300; - int m_field304; - int m_field308; - int m_field30C; - int m_field310; - int m_field314; - int m_field318; - Glacier::REFTAB32 m_reftab32_31C; - Glacier::REFTAB32 m_reftab32_3C8; - Glacier::REFTAB32 m_reftab32_474; - int m_field520; - Glacier::REFTAB32 m_reftab32_524; - int m_field5D0; - int m_field5D4; - bool m_field5D8; - bool m_field5D9; - bool m_field5DA; - bool m_field5DB; - bool m_field5DC; - bool m_field5DD; - bool m_field5DE; - bool m_field5DF; + float m_fHitmanDiedAt; //+0x30 + ZMusicController* m_pMusicController; + Glacier::ZSDOwner m_Music; + int m_iMusicDefinition; + Glacier::REFTAB m_rHitmanChangeClothesSubscribers; + Glacier::ZIntHash m_WeaponsUsedToKill; + Glacier::ZIntHash m_WeaponsFired; + int m_iNumWeaponsUsed; + Glacier::ZREF m_pDisguisesUsed[64]; + int m_iNumDisguisesUsed; + bool m_bTapeStolen; + RE_ADD_PADDING(3); + int m_iCustomWeaponsStart; + int m_iActorCount; + Glacier::ZREF m_arTargets[6]; + Glacier::ZREF m_arTargetsKilledWith[6]; + Glacier::REFTAB m_HarmedCharacters; + Glacier::REFTAB32 m_rtAudioPauseObjects; + float m_fTimeSinceLastOneliner; + int m_lObjectiveHiddenFlags; + int m_lObjectiveCompletedFlags; + bool m_bShowNotoriety; + RE_ADD_PADDING(3); + ZHitmanWeaponStorage* m_pNormalWeaponStorage; + ZHitmanWeaponStorage* m_pSmuggleWeaponStorage; + Glacier::ZVector3 m_vP1; + Glacier::ZVector3 m_vP2; + Glacier::ZVector3 m_vP3; + Glacier::ZVector3 m_vN; + int m_iSyringeUsed_HeartAttack; + int m_iSyringeUsed_Poison; + int m_iSyringeUsed_Anastetic; + ZPostFilterCollectionEvent* m_pPFCollection; + ZPostFilterEvent* m_pPF; + ZPostFilterSetEvent* m_pPFSet; + float m_fPFBlend; + int m_PFFadeDir; + Glacier::REFTAB32 m_BeginningItems; + Glacier::REFTAB32 m_rtClothlist; + Glacier::REFTAB32 m_rtWitnesses; + Glacier::ZREF m_rSecurityDevice; + Glacier::REFTAB32 m_rtSuitcaseBoxes; + Glacier::ZREF m_rBreathEmitter; + Glacier::ZREF m_rWaterSplashParticleSystem; }; + RE_VERIFY_SIZE(ZHM3LevelControl, 0x5D8); // Verified + RE_VERIFY_OFFSET(ZHM3LevelControl, m_fHitmanDiedAt, 0x30); + RE_VERIFY_OFFSET(ZHM3LevelControl, m_pMusicController, 0x34); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlHideout.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlHideout.h new file mode 100644 index 0000000..5c30b58 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlHideout.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZHM3LevelControlHideout : public ZHM3LevelControl + { + public: + // vtbl (no changes) + // data + EHM3ItemType m_eAvailableAmmoType[15]; // 0x5DC + int m_iNumberOfAmmoTypes; // +0x614 + }; + RE_VERIFY_SIZE(ZHM3LevelControlHideout, 0x618); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM00.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM00.h new file mode 100644 index 0000000..23d5326 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM00.h @@ -0,0 +1,91 @@ +#pragma once + +#include +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + struct M00Data + { + Glacier::ZMSGID m_msgShowTutorial; + Glacier::ZMSGID m_msgShowHint; + Glacier::ZMSGID m_msgKnockKnock; + Glacier::ZMSGID m_msgTesterOverRail; + Glacier::ZMSGID m_msgGateCutFinished; + Glacier::ZMSGID m_msgIntroCutFinished; + int m_bFirstFrame; + bool m_bTargetStillAliveHintShow; + float m_fRespawnCountdown; + Glacier::ZREF m_rCheckPoint; + int32_t m_iTestersKilled; + int32_t m_iTestersHidden; + int32_t m_iGuadsForSnipingKilled; + bool m_bBombPickedup; + bool m_bBombRemotePickedup; + bool m_bAtGate; + Glacier::TIMETYPE m_tBriefingFirstTime; + bool m_bPsychoBobHasGun; + bool m_bPsychoBobDead; + bool m_bShowHolsterGunHint; + bool s_Music_M00_ChemistDead; + bool m_bAddExtraAmmoToShotgun; + bool m_bAddExtraAmmoToTmp; + bool m_bAddExtraAmmoToSecretTmp; + }; + RE_VERIFY_SIZE(M00Data, 0x38); + + class ZHM3LevelControlM00 : public ZHM3LevelControl + { + public: + // vtbl (no changes) + // data + Glacier::ZPStrHash m_TutorialsHintsShown; + bool m_bSwingKingDead; + bool m_bScoopDead; + RE_ADD_PADDING(2); + Glacier::REFTAB m_lBurn; + Glacier::REFTAB m_lBurnFireEmitters; + Glacier::REFTAB m_lBurnSmokeEmitters; + Glacier::ZREF m_rGasolineEmitter; + Glacier::ZREF m_rGasolineCan; + Glacier::ZGEOM* m_pGasolineEmitter; + Glacier::ZItem* m_pGasolineCan; + Glacier::ZItemContainer* m_pCrateBakingSoda; + bool m_bBurnLawyer; + bool m_bWaitForForcedBriefingClose; + RE_ADD_PADDING(2); + float m_fTimeEmitBurnLawyer; + float m_fTimeBurnLawyer; + float m_fNewEmitTime; + float m_fTimeSmokeLawyer; + Glacier::ZREF m_rLawyer; + Glacier::ZREF m_rLawyerBurnedModel; + Glacier::ZREF m_rActionEscape; + bool m_bExitBoxShown; + RE_ADD_PADDING(3); + Glacier::ZREF m_rElephant; + Glacier::ZREF m_rElephantBurned; + M00Data* _p; + M00Data* _StoredData; + bool m_bMoveGasolineEmitter; + bool m_bSwapLawyerModel; + bool m_bChemistClothesOn; + bool m_bChemistKeycardPickedUp; + bool m_bShowDropCrateTip; + bool m_bCokeGuard1Down; + bool m_bCokeGuard2Down; + RE_ADD_PADDING(1); + Glacier::ZREF m_rChemist; + Glacier::ZREF m_rFactoryRoom; + Glacier::ZREF m_rCrateBakingSoda; + Glacier::ZREF m_rTestingRoomDoor1; + Glacier::ZREF m_rTestingRoomDoor2; + Glacier::ZREF m_rHMPositionAfterGateCut; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM00, 0x6B8); // Verified + RE_VERIFY_OFFSET(ZHM3LevelControlM00, m_bSwingKingDead, 0x5f8); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM01.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM01.h new file mode 100644 index 0000000..5322cce --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM01.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZHM3LevelControlM01 : public ZHM3LevelControl + { + public: + // vtbl + virtual void CompleteObjective(int iObjectiveIdx); + + // data + bool m_bDonKilled; + bool m_bAllTargetsDead; + Glacier::ZREF m_rGuardHouseGuard; + Glacier::ZMSGID m_M01_MissionComplete; + Glacier::ZGEOM* m_pCamera; + Glacier::ZGEOM* m_pCameraFlash; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM01, 0x5EC); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM02.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM02.h new file mode 100644 index 0000000..02023d5 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM02.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZHM3LevelControlM02 : public ZHM3LevelControl + { + public: + // vtbl (no changes) + // data + Glacier::ZREF m_rLaserBeamCheckInside; + Glacier::ZREF m_rGovernorSon; + Glacier::ZREF m_rSlapGirl; + Glacier::ZREF m_rGovSonDrink; + Glacier::ZREF m_rAphrodisiac; + Glacier::ZREF m_rlvlctrl2; + Glacier::ZREF m_rBottleChampagne; + Glacier::ZREF m_rVIPDrink; + Glacier::ZREF m_rVIPGuest; + Glacier::ZREF m_rStaffFuseboxGuard; + Glacier::ZREF m_rJacuzziGirl1; + Glacier::ZREF m_rJacuzziGirl2; + Glacier::ZREF m_rJacuzziGirl3; + Glacier::ZREF m_rWaiter; + Glacier::ZREF m_rExitBoxPier; + Glacier::ZREF m_rExitBoxHelipad; + Glacier::ZREF m_rPilot; + Glacier::ZREF m_rPianoBartender; + Glacier::ZREF m_rPornBoss; + Glacier::ZREF m_rPoisonGlassAction; + Glacier::ZREF m_rJacuzziWaterBox; + Glacier::ZREF m_rEscapeVideoPlayer; + Glacier::ZREF m_rJacuzziPathfinderCutout; + bool m_bPornBossDead; + bool m_bGovenorSonDead; + bool m_bVideoTapeRetrieved; + bool m_bHeliKeyRetrieved; + bool m_bAphroUsed; + bool m_JacuzziGoner; + Glacier::ZMSGID m_msgJumpBalcony; + Glacier::ZMSGID msg_CheckInsideEnter; + Glacier::ZMSGID msg_CheckInsideLeave; + Glacier::ZMSGID msg_M02_UseAphrodisiac; + Glacier::ZMSGID msg_M02_UseAphrodisiacAlternativ; + Glacier::ZMSGID msg_M02_PourChampagne; + Glacier::ZMSGID msg_M02_Jacuzzicrash; + Glacier::ZMSGID msg_M02_ExitBoxHelipad; + Glacier::ZMSGID msg_M02_ExitBoxPier; + Glacier::ZMSGID msg_M02_HeliKeyCheck; + Glacier::ZMSGID msg_M02_CompleteLevelHelipad; + Glacier::PF4::ZDynamicObstacle* m_pObstacle; + ZPostFilterCollectionEvent* m_pPFCollection; + ZPostFilterEvent* m_pPF; + Glacier::Animation::Header* m_pAniHMPoisonBottle; + bool m_bCompletedAfterMovie; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM02, 0x664); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM03.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM03.h new file mode 100644 index 0000000..fcaf0e3 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM03.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZHM3LevelControlM03 : public ZHM3LevelControl + { + public: + // vtbl + // data + Glacier::ZREF m_rChandelierDebris; + Glacier::ZREF m_rMauserClothes; + Glacier::ZREF m_rBoxHitmanBomb1; + Glacier::ZREF m_rBoxHitmanBomb2; + Glacier::REFTAB m_rtFightRats; + Glacier::REFTAB m_rtFightRatsGloves; + Glacier::REFTAB m_rtPokerRats; + Glacier::REFTAB m_rtPokerRatsCards; + Glacier::REFTAB m_rtPokerRatsHats; + Glacier::REFTAB m_rtPokerRatsCigars; + Glacier::REFTAB m_rtWaitressRats; + Glacier::REFTAB m_rtWaitressRatsTrays; + Glacier::ZREF m_rOperaSinger; + Glacier::ZREF m_rAmbassador; + Glacier::ZGEOM* m_pCamera; + Glacier::ZGEOM* m_pCameraFlash; + bool m_bIgnoreWeapons; + bool m_bHitmanInRatRoom; + int8_t m_iBombAddedToHitmanGeomNumbe; + Glacier::ZMSGID m_msg_evM03_EscapeCutEnd; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM03, 0x6E0); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM04.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM04.h new file mode 100644 index 0000000..551319f --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM04.h @@ -0,0 +1,109 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + + enum eAgentSmithState + { + eANormal = 0, + eAFakeDeath = 1, + eAInTheMorgue = 2, + eARevived = 3, + eADead = 4, + }; + + enum eGlobeLidState + { + eClosed = 0, + eOpened = 1, + eOpening = 2, + eClosing = 3, + }; + + struct SM04Vars + { + uint8_t m_bMainTargetDead : 1; + uint8_t m_bHMInDropWeightBox : 1; + uint8_t m_bExitBoxShown : 1; + uint8_t m_bHMInLocker : 1; + uint8_t m_bOptTarget1Dead : 1; + uint8_t m_bOptTarget2Dead : 1; + uint8_t m_HMTalkedToAgent : 1; + uint8_t m_bMoveBed : 1; + }; + + struct SM04HMasClothes + { + uint8_t m_bHMasHitman : 1; + uint8_t m_bHMasBodyguard : 1; + uint8_t m_bHMasPatient : 1; + uint8_t m_bHMasGuard : 1; + uint8_t m_bHMasWarden : 1; + uint8_t m_bHMasTherapist : 1; + uint8_t m_pad : 2; + }; + + class ZHM3LevelControlM04 : public ZHM3LevelControl + { + public: + // vtbl + // data + Glacier::REFTAB m_rTargets; + Glacier::ZREF m_rReceptionNurse; + Glacier::ZREF m_rMetalDoorGuard; + Glacier::ZREF m_rAgentSmith; + Glacier::REFTAB m_rTargetPhotos; + Glacier::ZREF m_rSpecWarden; + Glacier::ZREF m_rHospitalBed; + Glacier::ZREF m_rCellDoor; + Glacier::ZREF m_rElevDoor; + Glacier::ZREF m_rPathToMorgueSpline; + Glacier::ZREF m_rGlobe; + Glacier::ZAUDIOREF m_rGlobeOpenSound; + Glacier::ZAUDIOREF m_rGlobeCloseSound; + Glacier::ZREF m_rDumbBell; + Glacier::ZREF m_rActionEscape; + Glacier::ZREF m_rLockerBox; + Glacier::ZREF m_rGasTank; + Glacier::ZREF m_rBalconyGuy; + Glacier::ZREF m_rMobilePhone; + Glacier::ZREF m_rsGasTankSound; + Glacier::ZMSGID m_M04_MissionComplete; + Glacier::ZMSGID m_msgEnterBoxEnter; + Glacier::ZMSGID m_msgExitBoxEnter; + Glacier::ZMSGID m_msgStartSplineMoving; + Glacier::REFTAB m_bHMasBodyguardClothe; + Glacier::REFTAB m_bHMasPatientClothes; + Glacier::REFTAB m_bHMasGuardClothes; + Glacier::REFTAB m_bHMasWardenClothes; + Glacier::REFTAB m_bHMasTherapistClothe; + Glacier::ZREF m_rFinalTargetRef; + Glacier::ZREF m_rFinalTargetPhoto; + Glacier::ZREF m_rOptTarget1; + Glacier::ZREF m_rOptTarget2; + eAgentSmithState m_eAgentState; + Glacier::ZGEOM* m_pEvCamPos1; + Glacier::ZGEOM* m_pEvCamPos2; + Glacier::ZREF m_rAgentAction; + Glacier::ZGEOM* m_pGlobeLid; + eGlobeLidState m_eGlobeLidState; + float m_fAnimLength; + Glacier::ZREF m_rGlobeAction; + Glacier::ZREF m_rGasAction; + Glacier::ZREF m_rDumbBellAction; + int m_iHitmanInMedWing; + SM04Vars m_Vars; + Glacier::PF4::ZDynamicObstacle* m_pObstacle; + Glacier::SSplineMover m_sSplineMover; + SM04HMasClothes m_HMas; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM04, 0x77C); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM05.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM05.h new file mode 100644 index 0000000..8a8861e --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM05.h @@ -0,0 +1,102 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + enum eGarageState + { + eGClosed = 0, + eGOpened = 1, + eGOpening = 2, + eGClosing = 3, + }; + + class ZHM3LevelControlM05 : public ZHM3LevelControl + { + public: + // vtbl + // data + int32_t m_iTargetsToKill; + + Glacier::REFTAB m_lBurn; + Glacier::REFTAB m_lBurnFireEmitters; + Glacier::REFTAB m_lBurnSmokeEmitters; + + Glacier::ZREF m_rCameraGuard01; + Glacier::ZREF m_rCameraGuard02; + Glacier::ZREF m_rCaterer; + Glacier::ZREF m_rWitness; + Glacier::ZREF m_rWitnessWife; + Glacier::ZREF m_rWifeBurnedModel; + Glacier::ZREF m_rBBQ; + Glacier::ZREF m_rGarageDoor; + Glacier::ZREF m_rGarageDoorActionArea; + Glacier::ZREF m_rExitBox; + Glacier::ZREF m_rDonutCrate; + Glacier::ZREF m_rDonutHack; + Glacier::ZREF m_rAirgun; + Glacier::ZREF m_rDarts; + Glacier::ZREF m_rGarageDoorSound; + Glacier::ZREF m_rGaragePathfinderExitBox; + + Glacier::ZItem* m_pDonutCrate; + Glacier::ZItem* m_pDonutHack; + Glacier::ZGEOM* m_pGarageGeom; + Glacier::ZGEOM* m_pGarageDoorActionArea; + + Glacier::ZRunMatPosAnim m_GarageAnim; + eGarageState m_eState; + float m_fGarageAnimTime; + Glacier::ZREF m_rGarageDoorAction; + + Glacier::ZVector3 m_vGaragePathfinderLinksBoxMin; + Glacier::ZVector3 m_vGaragePathfinderLinksBoxMax; + Glacier::ZVector3 m_vGarageDoorOffset; + Glacier::ZMat3x3 m_mGarageDoorOffset; + + bool m_bBurnWife; + RE_ADD_PADDING(3); + float m_fTimeSmokeWife; + float m_fTimeBurnWife; + float m_fTimeEmitBurnWife; + float m_fNewEmitTime; + bool m_bNecklacePickedUp; + bool m_bSwapWifeModel; + bool m_bWifeBurned; + bool m_bGetMoreGuards; + + Glacier::ZMSGID m_msgAddSuspiciousGuard; + Glacier::ZMSGID m_msgSubSuspiciousGuard; + Glacier::ZMSGID m_msgAddThreateningGuard; + Glacier::ZMSGID m_msgSubThreateningGuard; + Glacier::ZMSGID m_msgAddDeadBodyFound; + Glacier::ZMSGID m_msgCallForBackup; + Glacier::ZMSGID m_msgImmediateBackup; + Glacier::ZMSGID m_LevelEnd; + + int32_t m_KilledFBIGuards; + int32_t m_GuardSendTimer; + int32_t m_iLevelStartTime; + int32_t m_iSuspiciousGuards; + int32_t m_iThreateningGuards; + int32_t m_iBodiesFound; + int32_t m_iAllowedSuspiciousGuards; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM05, 0x734); // Verified + RE_VERIFY_OFFSET(ZHM3LevelControlM05, m_rCameraGuard01, 0x630); + RE_VERIFY_OFFSET(ZHM3LevelControlM05, m_GarageAnim, 0x680); + RE_VERIFY_OFFSET(ZHM3LevelControlM05, m_lBurn, 0x5DC); + RE_VERIFY_OFFSET(ZHM3LevelControlM05, m_lBurnFireEmitters, 0x5F8); + RE_VERIFY_OFFSET(ZHM3LevelControlM05, m_lBurnSmokeEmitters, 0x614); + RE_VERIFY_OFFSET(ZHM3LevelControlM05, m_vGarageDoorOffset, 0x6C0); // Verified by ZHM3LevelControlM05::Animate + RE_VERIFY_OFFSET(ZHM3LevelControlM05, m_mGarageDoorOffset, 0x6CC); // Verified by ZHM3LevelControlM05::Animate + RE_VERIFY_OFFSET(ZHM3LevelControlM05, m_bGetMoreGuards, 0x707); // Verified by m_bGetMoreGuards + RE_VERIFY_OFFSET(ZHM3LevelControlM05, m_KilledFBIGuards, 0x718); // Verified by ZHM3LevelControlM05::CharacterKilled +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM06.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM06.h new file mode 100644 index 0000000..4914791 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM06.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Hitman::BloodMoney +{ + class ZHM3Actor; + + class ZHM3LevelControlM06 : public ZHM3LevelControl + { + public: + // vtbl + virtual void CompleteObjective(int iObjectiveIdx); + + // data + bool m_bSniperRifleInCurrentRoom; + bool m_bTargetInSight; + bool m_bAssassinInMeeting; + Glacier::ZREF m_rLeader; + Glacier::ZREF m_rRaymond; + Glacier::ZREF m_rAngelina; + Glacier::ZREF m_rBarfingGuy; + Glacier::REFTAB m_lPuke; + Glacier::ZAUDIOREF m_lWalkieStaticResource; + Glacier::ZREF m_rFloatPolitician; + Glacier::REFTAB32 m_rtFloatActors; + Glacier::REFTAB32 m_rtFloatActorsPos; + Glacier::ZREF m_rRaymondRifle; + Glacier::ZREF m_rBluesRoom; + Glacier::ZREF m_rRockRoom; + Glacier::ZREF m_rRockRoom2; + Glacier::ZREF m_rSalsaRoom; + ZHM3Actor* m_apFloatActors[5]; + Glacier::ZGEOM* m_apFloatActorsPos[5]; + Glacier::ZGEOM* m_pLeader; + Glacier::ZGEOM* m_pRaymond; + Glacier::ZGEOM* m_pAngelina; + Glacier::ZGEOM* m_pRaymondRifle; + ZMardiGrassFloat* m_pFloat; + Glacier::TIMETYPE m_ttLastMoveTime; + Glacier::Animation::Header* m_pAnimBlues; + Glacier::Animation::Header* m_pAnimRock; + Glacier::Animation::Header* m_pAnimSalsa; + bool m_bDancing; + bool m_bFloatsMoving; + Glacier::ZREF m_rClubMusic; + Glacier::ZREF m_rRaymondInWalkie; + Glacier::REFTAB32 m_rtRadioMusicSources; + int32_t m_lPosEnum; + int32_t m_lClubMusicId; + Glacier::ZROOM* m_pOldHitmanRoom; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM06, 0x88C); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM07.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM07.h new file mode 100644 index 0000000..43539e1 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM07.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + // Unfinished game mission + class ZHM3LevelControlM07 : public ZHM3LevelControl + { + public: + // vtbl (no changes) + // data + bool m_bNegotiatorKilled; + bool m_bCrabBossKilled; + bool m_bPilotKilled; + bool m_bMessengerKilled; + bool m_bGamblerKilled; + bool m_bMissionCompleted; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM07, 0x5E0); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM08.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM08.h new file mode 100644 index 0000000..dee02d1 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM08.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZHM3LevelControlM08 : public ZHM3LevelControl + { + public: + // vtbl + virtual void CompleteObjective(int iObjectiveIdx); + + // data + Glacier::ZLIST* m_pRiverBanksList; + Glacier::ZREF m_rPowerboxGuard; + Glacier::ZREF m_rRightSidePiston; + Glacier::ZREF m_rRightSidePlejelstang; + Glacier::ZREF m_rRightSideValveStick; + Glacier::REFTAB m_pRightSidePropellarObject; + Glacier::ZREF m_rDeathBox1; + Glacier::ZREF m_rDeathBox2; + Glacier::ZREF m_rLeftSidePiston; + Glacier::ZREF m_rLeftSidePlejelstang; + Glacier::ZREF m_rLeftSideValveStick; + Glacier::REFTAB m_pLeftSidePropellarObjects; + Glacier::ZREF m_rLeftPartitlesystem1; + Glacier::ZREF m_rCake; + Glacier::ZREF m_rCakeHack; + Glacier::ZREF m_rUtilBoxControlledThings; + Glacier::ZREF m_rFoodCycleController; + Glacier::ZREF m_rBuffetOne; + Glacier::ZREF m_rBuffetTwo; + Glacier::ZREF m_rCakeGoesHere; + Glacier::ZREF m_rBoss; + Glacier::ZItem* m_pCake; + Glacier::ZItem* m_pCakeHack; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM08, 0x664); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM09.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM09.h new file mode 100644 index 0000000..b0c035b --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM09.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZHM3LevelControlM09 : public ZHM3LevelControl + { + public: + // vtbl + virtual void CompleteObjective(int iObjectiveIdx); + + // data + Glacier::Animation::Header* m_pAnimSquareDance; + Glacier::ZREF m_rFuseBox01; + Glacier::ZREF m_rFuseBoxGuard01; + Glacier::REFTAB m_rtAlligators; + Glacier::ZREF m_rWaterBox; + bool m_bIsGroomOnBandstan; + float m_fWaterBoxSendTime; + Glacier::REFTAB m_rtNoobs; + bool m_bNoobsDone; + Glacier::ZAUDIOREF m_rSoundBoatArrive; + bool m_bBoatArriveDone; + Glacier::REFTAB m_rtFemaleDancers; + bool m_bCanHitmanDance; + bool m_bDancing; + float m_fDanceWaitTimer; + Glacier::ZREF m_rDancePartner; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM09, 0x65C); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM10.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM10.h new file mode 100644 index 0000000..4fc1fe5 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM10.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZHM3LevelControlM10 : public ZHM3LevelControl + { + public: + // vtbl (no changes) + // data + Glacier::ZREF m_r7thFloorBox; + Glacier::ZREF m_r8thFloorBox; + Glacier::ZREF m_r7thFloorEmergencySwitch; + Glacier::ZREF m_r8thFloorEmergencySwitch; + Glacier::ZREF m_r7thFloorFireAlarm; + Glacier::ZREF m_r8thFloorFireAlarm; + Glacier::ZREF m_rSuitcase_Diamonds; + Glacier::ZMSGID m_M10_MissionComplete; + Glacier::ZMSGID m_M10_HMPutDownSuitcase; + Glacier::ZGEOM* m_pCamera; + Glacier::ZGEOM* m_pCameraFlash; + Glacier::ZAction* m_pExitAction; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM10, 0x604); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM11.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM11.h new file mode 100644 index 0000000..2efc847 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM11.h @@ -0,0 +1,56 @@ +#pragma once + +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZHM3Actor; + + class ZHM3LevelControlM11 : public ZHM3LevelControl + { + public: + // vtbl (no changes) + // data + Glacier::REFTAB m_lNoDisarm; + Glacier::ZREF m_rBarfingGuy; + Glacier::ZREF m_rPartyGirlArranger; + Glacier::ZREF m_rArrangerSword1; + Glacier::ZREF m_rArrangerSword3; + Glacier::REFTAB m_lPuke; + Glacier::REFTAB m_lBurn; + Glacier::ZREF m_rSpitDrink; + Glacier::ZREF m_rProjectorFilmRollTop; + Glacier::ZREF m_rProjectorFilmRollBotto; + Glacier::ZREF m_rEatingShark; + Glacier::ZREF m_rWaterBox; + Glacier::ZREF m_rHeavenMusic; + Glacier::ZREF m_rHellMusic; + Glacier::ZREF m_rKaraokeMusic; + Glacier::ZREF m_rKaraokeVoice; + Glacier::ZREF m_rHackValidHitmanPos; + bool m_bKaraokeMusicPlaying; + bool m_bKaraokeVoicePlaying; + bool m_bColiCheckArranger; + bool m_bColiCheckAngel; + ZHM3Actor* m_pArranger; + ZHM3Actor* m_pAngel; + ZHM3Item* m_pColiCheckItem[3]; + ZHM3Actor* m_pColiCheckActor[3]; + float m_fColiCheckLength[3]; + float m_fTimeNoDamage; + float m_fWaterBoxSendTime; + bool m_bBurnArranger; + float m_fTimeBurnArranger; + Glacier::ZREF m_rSpittingPerson; + bool m_bProjectorRunning; + Glacier::SREF m_rKaraokeVocals; + Glacier::ZREF m_rKaraokeSinger; + float m_TimeKaraokeStarted; + Glacier::ZREF m_rCrowdController; + Glacier::ZMSGID m_msg_evM11_EscapeCutEnd; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM11, 0x6C0); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM12.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM12.h new file mode 100644 index 0000000..a581b81 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM12.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZHM3LevelControlM12 : public ZHM3LevelControl + { + public: + // vtbl (no changes) + // data + Glacier::ZREF m_rMrX; + Glacier::ZREF m_rAlbino; + Glacier::ZREF m_rAlbinoVictim; + Glacier::ZREF m_rMontre; + Glacier::ZREF m_rMontreAlarm; + Glacier::ZREF m_rCheckInsideMontre; + Glacier::ZREF m_rCheckInsideEntrance; + Glacier::ZREF m_rCheckInsideEntranceTo; + Glacier::ZREF m_rMoveObject; + Glacier::ZVector3 m_vMoveTo; + Glacier::ZVector3 m_vMoveFrom; + float m_fMoveTime; + float m_fMoveStartTime; + float m_fXrayYOffset; + bool m_bHighNoonActive; + bool m_bHighNoonSilenced; + Glacier::ZGEOM* m_pCamera; + Glacier::ZGEOM* m_pCameraFlash; + }; + RE_VERIFY_SIZE(ZHM3LevelControlM12, 0x62C); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM13.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM13.h index 1a8f5b1..df5b0a6 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM13.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LevelControls/ZHM3LevelControlM13.h @@ -1,529 +1,47 @@ #pragma once +#include #include +#include #include namespace Hitman::BloodMoney { - using Glacier::ISerializerStream; - using Glacier::IInputSerializerStream; - using Glacier::IOutputSerializerStream; - - // Type forwardings for class ZHM3LevelControlM13 - enum class ESecurityZone; - class ZItem; - class ZEventBase; - class ZItemWeapon; - class ZHM3ItemWeapon; - class ZHM3Item; - class ZHM3ClothBundle; - class ZBaseGeom; - class ZCheckPoBuffer; - class ZHM3HmAs; - class ZItemContainer; - class ZAction; - class ZHM3Actor; - class ZGEOM; - class ZROUTCLASSINFO; - class ZHM3ItemBomb; - enum class EHM3ItemType; - - class ZCheckPointBuffer{}; - // Class definition ZHM3LevelControlM13 - class ZHM3LevelControlM13 { - public: - virtual void Release_ZHM3LevelControlM13(bool); //#0000 at 00478374 org ZHM3LevelControlM13::~ZHM3LevelControlM13() - virtual void PreSave(ISerializerStream &); //#0001 at 0043E228 org ZSerializable::PreSave(ISerializerStream &) - virtual void PostSave(ISerializerStream &); //#0002 at 003FF584 org ZHM3LevelControlM13::PostSave(ISerializerStream &) - virtual void PreLoad(ISerializerStream &); //#0003 at 0043E238 org ZSerializable::PreLoad(ISerializerStream &) - virtual void PostLoad(ISerializerStream &); //#0004 at 003FF514 org ZHM3LevelControlM13::PostLoad(ISerializerStream &) - virtual void PostProcess(unsigned int,unsigned int); //#0005 at 0043E248 org ZSerializable::PostProcess(unsigned int,unsigned int) - virtual void LoadSave(ISerializerStream &,bool); //#0006 at 003DC7F0 org ZHM3LevelControl::LoadSave(ISerializerStream &,bool) - virtual void LoadObject(IInputSerializerStream &); //#0007 at 003DC848 org ZHM3LevelControl::LoadObject(IInputSerializerStream &) - virtual void SaveObject(IOutputSerializerStream &); //#0008 at 003DC9BC org ZHM3LevelControl::SaveObject(IOutputSerializerStream &) - virtual void ExchangeObject(ISerializerStream &); //#0009 at 0043CC1C org ZSerializable::ExchangeObject(ISerializerStream &) - virtual void SetToDefault(); //#0010 at 0043C568 org ZSerializable::SetToDefault(void) - virtual void GetTypeID(); //#0011 at 0043F270 org RTP::cBase::GetTypeID(void) - virtual void GetProperties(); //#0012 at 00478414 org ZHM3LevelControlM13::GetProperties(void)const - virtual void GetEventPriority(); //#0013 at 00475DF0 org ZHM3LevelControl::GetEventPriority(void)const - virtual void Init(); //#0014 at 003FE4AC org ZHM3LevelControlM13::Init(void) - virtual void Init2(); //#0015 at 003FE59C org ZHM3LevelControlM13::Init2(void) - virtual void PostInit(); //#0016 at 0043FA28 org ZEventBase::PostInit(void) - virtual void PostInit2(); //#0017 at 003FE700 org ZHM3LevelControlM13::PostInit2(void) - virtual void CopyData(ZEventBase *); //#0018 at 003DC258 org ZHM3LevelControl::CopyData(ZEventBase *) - virtual void EventName(); //#0019 at 0043FAB0 org ZBaseConRout::EventName(void) - virtual void ExpandBounds(float *,float *,float *,ZBaseGeom *); //#0020 at 0043FA48 org ZEventBase::ExpandBounds(float *,float *,float *,ZBaseGeom *) - virtual void PreSaveGame(); //#0021 at 00174824 org ZEventBase::PreSaveGame(void) - virtual void RegisterInstance(unsigned int); //#0022 at 0043FA50 org ZEventBase::RegisterInstance(unsigned int) - virtual void CheckPointSave(ZCheckPointBuffer &); //#0023 at 0043FA58 org ZEventBase::CheckPointSave(ZCheckPointBuffer &) - virtual void CheckPointLoad(ZCheckPointBuffer &); //#0024 at 0043FA60 org ZEventBase::CheckPointLoad(ZCheckPointBuffer &) - virtual void Reset(); //#0025 at 00174C0C org ZEventBase::Reset(void) - virtual void TimeUpdate(); //#0026 at 0043FA68 org ZEventBase::TimeUpdate(void) - virtual void FrameUpdate(); //#0027 at 003FEE80 org ZHM3LevelControlM13::FrameUpdate(void) - virtual void Command(unsigned short,void *); //#0028 at 003FEC28 org ZHM3LevelControlM13::Command(unsigned short,void *) - virtual void DoEvent(int,int,void *); //#0029 at 0043FAD0 org ZBaseConRout::DoEvent(int,int,void *) - virtual void End(); //#0030 at 003FEAEC org ZHM3LevelControlM13::End(void) - virtual void EditorCommand(unsigned short,void *); //#0031 at 0043FA90 org ZEventBase::EditorCommand(unsigned short,void *) - virtual void Remove(); //#0032 at 00174BF0 org ZEventBase::Remove(void) - virtual void SchedUpdate(); //#0033 at 0043FA98 org ZEventBase::SchedUpdate(void) - virtual void InitBaseConRout(ZROUTCLASSINFO *); //#0034 at 0043FAA0 org ZBaseConRout::InitBaseConRout(ZROUTCLASSINFO *) - virtual void UnknownCommand(unsigned short,void *); //#0035 at 0043FAC8 org ZBaseConRout::UnknownCommand(unsigned short,void *) - virtual void MusicInit(); //#0036 at 003FEA30 org ZHM3LevelControlM13::MusicInit(void) - virtual void CharacterKilled(unsigned int); //#0037 at 003FEB34 org ZHM3LevelControlM13::CharacterKilled(unsigned int) - virtual void CharacterHarmed(unsigned int); //#0038 at 003DCDDC org ZHM3LevelControl::CharacterHarmed(unsigned int) - virtual void HitmanHideWeapon(); //#0039 at 003DE708 org ZHM3LevelControl::HitmanHideWeapon(void) - virtual void HitmanDragBody(ZGEOM *); //#0040 at 00475DF8 org ZHM3LevelControl::HitmanDragBody(ZGEOM *) - virtual void HitmanDropDeadBody(unsigned int,int); //#0041 at 003FEC14 org ZHM3LevelControlM13::HitmanDropDeadBody(unsigned int,int) - virtual void HitmanPickupItem(ZItem *); //#0042 at 003FEC04 org ZHM3LevelControlM13::HitmanPickupItem(ZItem *) - virtual void HitmanDropItem(ZItem *); //#0043 at 003FEC0C org ZHM3LevelControlM13::HitmanDropItem(ZItem *) - virtual void HitmanUseItem(ZItem *); //#0044 at 003DD0EC org ZHM3LevelControl::HitmanUseItem(ZItem *) - virtual void HitmanThrowItem(ZItem *); //#0045 at 003DCFE0 org ZHM3LevelControl::HitmanThrowItem(ZItem *) - virtual void HitmanGetCurrentUBAnim(unsigned int *); //#0046 at 003DD0F4 org ZHM3LevelControl::HitmanGetCurrentUBAnim(unsigned int *) - virtual void HitmanDied(); //#0047 at 003DD104 org ZHM3LevelControl::HitmanDied(void) - virtual void HitmanNearDeath(); //#0048 at 003DD0FC org ZHM3LevelControl::HitmanNearDeath(void) - virtual void OnHitmanMayAttackCloseCombat(ZHM3ItemWeapon *,ZHM3Actor *); //#0049 at 00475E08 org ZHM3LevelControl::OnHitmanMayAttackCloseCombat(ZHM3ItemWeapon *,ZHM3Actor *) - virtual void OnHitmanMayStrangulateTarget(ZHM3Actor *); //#0050 at 00475E10 org ZHM3LevelControl::OnHitmanMayStrangulateTarget(ZHM3Actor *) - virtual void OnHitmanMayDisarmTarget(ZHM3Actor *); //#0051 at 00475E18 org ZHM3LevelControl::OnHitmanMayDisarmTarget(ZHM3Actor *) - virtual void OnHitmanTakeHumanShield(ZHM3Actor *); //#0052 at 00475E20 org ZHM3LevelControl::OnHitmanTakeHumanShield(ZHM3Actor *) - virtual void OnHitmanUnpackSniper(); //#0053 at 00475E28 org ZHM3LevelControl::OnHitmanUnpackSniper(void) - virtual void OnHitmanCloseInventory(); //#0054 at 00475E30 org ZHM3LevelControl::OnHitmanCloseInventory(void) - virtual void OnHitmanChangeClothes(ZHM3HmAs *,ZGEOM *); //#0055 at 003DD1A0 org ZHM3LevelControl::OnHitmanChangeClothes(ZHM3HmAs *,ZGEOM *) - virtual void OnDropHitmanClothBundle(ZHM3ClothBundle *); //#0056 at 00475E38 org ZHM3LevelControl::OnDropHitmanClothBundle(ZHM3ClothBundle *) - virtual void BombExploded(ZHM3ItemBomb *); //#0057 at 00475E40 org ZHM3LevelControl::BombExploded(ZHM3ItemBomb *) - virtual void OnBombPlaced(ZHM3ItemBomb *); //#0058 at 00475E48 org ZHM3LevelControl::OnBombPlaced(ZHM3ItemBomb *) - virtual void BombAddedToHitman(ZItem *); //#0059 at 00475E50 org ZHM3LevelControl::BombAddedToHitman(ZItem *) - virtual void MissionFailed(char const*); //#0060 at 003DCEE4 org ZHM3LevelControl::MissionFailed(char const*) - virtual void CalculateExtraStats(); //#0061 at 003DB434 org ZHM3LevelControl::CalculateExtraStats(void) - virtual void MissionCompleted(); //#0062 at 003DB340 org ZHM3LevelControl::MissionCompleted(void) - virtual void MissionCompleted2(); //#0063 at 003FEB00 org ZHM3LevelControlM13::MissionCompleted2(void) - virtual void TerminateScene(); //#0064 at 003DCFC8 org ZHM3LevelControl::TerminateScene(void) - virtual void CompleteObjective(int,bool); //#0065 at 003DCFE8 org ZHM3LevelControl::CompleteObjective(int,bool) - virtual void UnCompleteObjective(int); //#0066 at 003DD00C org ZHM3LevelControl::UnCompleteObjective(int) - virtual void HideObjective(int); //#0067 at 003DD02C org ZHM3LevelControl::HideObjective(int) - virtual void UnHideObjective(int); //#0068 at 003DD04C org ZHM3LevelControl::UnHideObjective(int) - virtual void IsHitmanAllowedHere(ESecurityZone,ZHM3HmAs *,ZGEOM *,ZItem *,ZItem *); //#0069 at 00475E58 org ZHM3LevelControl::IsHitmanAllowedHere(ESecurityZone,ZHM3HmAs *,ZGEOM *,ZItem *,ZItem *) - virtual void IsIgnoredWeapon(ZItemWeapon *); //#0070 at 00475E60 org ZHM3LevelControl::IsIgnoredWeapon(ZItemWeapon *) - virtual void IsWeaponFoundAtHitman(bool &); //#0071 at 00475E68 org ZHM3LevelControl::IsWeaponFoundAtHitman(bool &) - virtual void TransferHitmanWeaponsToActor(unsigned int,bool &); //#0072 at 00475E74 org ZHM3LevelControl::TransferHitmanWeaponsToActor(unsigned int,bool &) - virtual void CanHMSyringeTarget(ZHM3Actor *,ZHM3ItemWeapon *); //#0073 at 00475E7C org ZHM3LevelControl::CanHMSyringeTarget(ZHM3Actor *,ZHM3ItemWeapon *)const - virtual void CanHMSyringeItem(ZHM3Item *,ZHM3ItemWeapon *); //#0074 at 00475E84 org ZHM3LevelControl::CanHMSyringeItem(ZHM3Item *,ZHM3ItemWeapon *)const - virtual void CanHitmanFiberWireTarget(ZHM3Actor *); //#0075 at 00475E8C org ZHM3LevelControl::CanHitmanFiberWireTarget(ZHM3Actor *)const - virtual void CanHMPutItemIntoElevator(ZGEOM *); //#0076 at 00475E94 org ZHM3LevelControl::CanHMPutItemIntoElevator(ZGEOM *)const - virtual void OnObjectExplode(ZGEOM *); //#0077 at 00475E9C org ZHM3LevelControl::OnObjectExplode(ZGEOM *) - virtual void CanHMOperateElevatorButton(ZAction *,bool &); //#0078 at 00475EA4 org ZHM3LevelControl::CanHMOperateElevatorButton(ZAction *,bool &) - virtual void OnActorDropItemsInHand(ZHM3Actor *); //#0079 at 00475EB0 org ZHM3LevelControl::OnActorDropItemsInHand(ZHM3Actor *) - virtual void DisguiseUsed(unsigned int); //#0080 at 003DDBD4 org ZHM3LevelControl::DisguiseUsed(unsigned int) - virtual void CanHMPlaceItemToContainer(ZItemContainer *,bool &); //#0081 at 00475EB8 org ZHM3LevelControl::CanHMPlaceItemToContainer(ZItemContainer *,bool &) - virtual void CanHMRetrieveItemFromContainer(ZItemContainer *,bool &); //#0082 at 00475EC4 org ZHM3LevelControl::CanHMRetrieveItemFromContainer(ZItemContainer *,bool &) - virtual void PlaceItemToContainer(ZItemContainer *,ZItem *); //#0083 at 00475ED0 org ZHM3LevelControl::PlaceItemToContainer(ZItemContainer *,ZItem *) - virtual void RetrieveItemFromContainer(ZItemContainer *,ZItem *); //#0084 at 00475ED8 org ZHM3LevelControl::RetrieveItemFromContainer(ZItemContainer *,ZItem *) - virtual void OnHitmanPlaceItemToContainer(ZItemContainer *,ZItem *); //#0085 at 00475EE0 org ZHM3LevelControl::OnHitmanPlaceItemToContainer(ZItemContainer *,ZItem *) - virtual void OnHitmanRetrieveItemFromContainer(ZItemContainer *,ZItem *); //#0086 at 00475EE8 org ZHM3LevelControl::OnHitmanRetrieveItemFromContainer(ZItemContainer *,ZItem *) - virtual void CanHitmanOperateGenericAction(ZAction *,bool &); //#0087 at 003FEC1C org ZHM3LevelControlM13::CanHitmanOperateGenericAction(ZAction *,bool &) - virtual void OnHitmanBreakUtilBox(ZGEOM *); //#0088 at 00475EFC org ZHM3LevelControl::OnHitmanBreakUtilBox(ZGEOM *) - virtual void OnUtilBoxRepaired(ZGEOM *); //#0089 at 00475F04 org ZHM3LevelControl::OnUtilBoxRepaired(ZGEOM *) - virtual void OnPickLockOpenDoor(ZGEOM *); //#0090 at 00475F0C org ZHM3LevelControl::OnPickLockOpenDoor(ZGEOM *) - virtual void OnOpenedDoorWithKeycard(ZGEOM *); //#0091 at 00475F14 org ZHM3LevelControl::OnOpenedDoorWithKeycard(ZGEOM *) - virtual void OnHitmanReloadWeapon(ZItem *); //#0092 at 00475F1C org ZHM3LevelControl::OnHitmanReloadWeapon(ZItem *) - virtual void OnHitmanPickupWeapon(ZItem *); //#0093 at 00475F24 org ZHM3LevelControl::OnHitmanPickupWeapon(ZItem *) - virtual void OnHitmanPickupItem(ZItem *); //#0094 at 00475F2C org ZHM3LevelControl::OnHitmanPickupItem(ZItem *) - virtual void OnHitmanDisarmNPC(ZHM3Actor *); //#0095 at 00475F34 org ZHM3LevelControl::OnHitmanDisarmNPC(ZHM3Actor *) - virtual void OnHitmanPutWeaponRightHandItem(ZItem *); //#0096 at 00475F3C org ZHM3LevelControl::OnHitmanPutWeaponRightHandItem(ZItem *) - virtual void OnHitmanPlacedBomb(); //#0097 at 00475F44 org ZHM3LevelControl::OnHitmanPlacedBomb(void) - virtual void OnHitmanUseSyringeOnItem(ZHM3Item *); //#0098 at 00475F4C org ZHM3LevelControl::OnHitmanUseSyringeOnItem(ZHM3Item *) - virtual void OnHitmanUseSyringe(EHM3ItemType); //#0099 at 003DE0E8 org ZHM3LevelControl::OnHitmanUseSyringe(EHM3ItemType) - virtual void OnHitmanHideInCloset(ZGEOM *); //#0100 at 00475F54 org ZHM3LevelControl::OnHitmanHideInCloset(ZGEOM *) - - + class ZHM3LevelControlM13 : public ZHM3LevelControl + { public: - //Data - int field_30; - int field_34; - int field_38; - int field_3c; - int field_40; - int field_44; - int field_48; - int field_4c; - int field_50; - int field_54; - int field_58; - int field_5c; - int field_60; - int field_64; - int field_68; - int field_6c; - int field_70; - int field_74; - int field_78; - int field_7c; - int field_80; - int field_84; - int field_88; - int field_8c; - int field_90; - int field_94; - int field_98; - int field_9c; - int field_a0; - int field_a4; - int field_a8; - int field_ac; - int field_b0; - int field_b4; - int field_b8; - int field_bc; - int field_c0; - int field_c4; - int field_c8; - int field_cc; - int field_d0; - int field_d4; - int field_d8; - int field_dc; - int field_e0; - int field_e4; - int field_e8; - int field_ec; - int field_f0; - int field_f4; - int field_f8; - int field_fc; - int field_100; - int field_104; - int field_108; - int field_10c; - int field_110; - int field_114; - int field_118; - int field_11c; - int field_120; - int field_124; - int field_128; - int field_12c; - int field_130; - int field_134; - int field_138; - int field_13c; - int field_140; - int field_144; - int field_148; - int field_14c; - int field_150; - int field_154; - int field_158; - int field_15c; - int field_160; - int field_164; - int field_168; - int field_16c; - int field_170; - int field_174; - int field_178; - int field_17c; - int field_180; - int field_184; - int field_188; - int field_18c; - int field_190; - int field_194; - int field_198; - int field_19c; - int field_1a0; - int field_1a4; - int field_1a8; - int field_1ac; - int field_1b0; - int field_1b4; - int field_1b8; - int field_1bc; - int field_1c0; - int field_1c4; - int field_1c8; - int field_1cc; - int field_1d0; - int field_1d4; - int field_1d8; - int field_1dc; - int field_1e0; - int field_1e4; - int field_1e8; - int field_1ec; - int field_1f0; - int field_1f4; - int field_1f8; - int field_1fc; - int field_200; - int field_204; - int field_208; - int field_20c; - int field_210; - int field_214; - int field_218; - int field_21c; - int field_220; - int field_224; - int field_228; - int field_22c; - int field_230; - int field_234; - int field_238; - int field_23c; - int field_240; - int field_244; - int field_248; - int field_24c; - int field_250; - int field_254; - int field_258; - int field_25c; - int field_260; - int field_264; - int field_268; - int field_26c; - int field_270; - int field_274; - int field_278; - int field_27c; - int field_280; - int field_284; - int field_288; - int field_28c; - int field_290; - int field_294; - int field_298; - int field_29c; - int field_2a0; - int field_2a4; - int field_2a8; - int field_2ac; - int field_2b0; - int field_2b4; - int field_2b8; - int field_2bc; - int field_2c0; - int field_2c4; - int field_2c8; - int field_2cc; - int field_2d0; - int field_2d4; - int field_2d8; - int field_2dc; - int field_2e0; - int field_2e4; - int field_2e8; - int field_2ec; - int field_2f0; - int field_2f4; - int field_2f8; - int field_2fc; - int field_300; - int field_304; - int field_308; - int field_30c; - int field_310; - int field_314; - int field_318; - int field_31c; - int field_320; - int field_324; - int field_328; - int field_32c; - int field_330; - int field_334; - int field_338; - int field_33c; - int field_340; - int field_344; - int field_348; - int field_34c; - int field_350; - int field_354; - int field_358; - int field_35c; - int field_360; - int field_364; - int field_368; - int field_36c; - int field_370; - int field_374; - int field_378; - int field_37c; - int field_380; - int field_384; - int field_388; - int field_38c; - int field_390; - int field_394; - int field_398; - int field_39c; - int field_3a0; - int field_3a4; - int field_3a8; - int field_3ac; - int field_3b0; - int field_3b4; - int field_3b8; - int field_3bc; - int field_3c0; - int field_3c4; - int field_3c8; - int field_3cc; - int field_3d0; - int field_3d4; - int field_3d8; - int field_3dc; - int field_3e0; - int field_3e4; - int field_3e8; - int field_3ec; - int field_3f0; - int field_3f4; - int field_3f8; - int field_3fc; - int field_400; - int field_404; - int field_408; - int field_40c; - int field_410; - int field_414; - int field_418; - int field_41c; - int field_420; - int field_424; - int field_428; - int field_42c; - int field_430; - int field_434; - int field_438; - int field_43c; - int field_440; - int field_444; - int field_448; - int field_44c; - int field_450; - int field_454; - int field_458; - int field_45c; - int field_460; - int field_464; - int field_468; - int field_46c; - int field_470; - int field_474; - int field_478; - int field_47c; - int field_480; - int field_484; - int field_488; - int field_48c; - int field_490; - int field_494; - int field_498; - int field_49c; - int field_4a0; - int field_4a4; - int field_4a8; - int field_4ac; - int field_4b0; - int field_4b4; - int field_4b8; - int field_4bc; - int field_4c0; - int field_4c4; - int field_4c8; - int field_4cc; - int field_4d0; - int field_4d4; - int field_4d8; - int field_4dc; - int field_4e0; - int field_4e4; - int field_4e8; - int field_4ec; - int field_4f0; - int field_4f4; - int field_4f8; - int field_4fc; - int field_500; - int field_504; - int field_508; - int field_50c; - int field_510; - int field_514; - int field_518; - int field_51c; - int field_520; - int field_524; - int field_528; - int field_52c; - int field_530; - int field_534; - int field_538; - int field_53c; - int field_540; - int field_544; - int field_548; - int field_54c; - int field_550; - int field_554; - int field_558; - int field_55c; - int field_560; - int field_564; - int field_568; - int field_56c; - int field_570; - int field_574; - int field_578; - int field_57c; - int field_580; - int field_584; - int field_588; - int field_58c; - int field_590; - int field_594; - int field_598; - int field_59c; - int field_5a0; - int field_5a4; - int field_5a8; - int field_5ac; - int field_5b0; - int field_5b4; - int field_5b8; - int field_5bc; - int field_5c0; - int field_5c4; - int field_5c8; - int field_5cc; - int field_5d0; - int field_5d4; - int field_5d8; - int field_5dc; - int field_5e0; - int field_5e4; - int field_5e8; - int field_5ec; - int field_5f0; - int field_5f4; - int field_5f8; - int field_5fc; - int field_600; - int field_604; - int field_608; - int field_60c; - int field_610; - int field_614; - int field_618; - int field_61c; - int field_620; - int field_624; - int field_628; - int field_62c; - int field_630; - int field_634; + //Data (starts from +0x5D8) + bool m_bMissionComplete; + RE_ADD_PADDING(3); + Glacier::ZREF m_rTable; + Glacier::ZREF m_rTrapDoor; + bool m_bFirstFrame; + bool m_bHitmanRevived; + bool m_bHitmanLeftTable; + RE_ADD_PADDING(1); + float m_fLeftTableTime; + float m_fLastHeartBeat; + int m_sndHeartBeat; + float m_fHeartBeatBoost; + Glacier::ZVector3 m_vOldDir; + Glacier::ZREF m_rWheelChairGuy; + Glacier::ZREF m_rJournalist; + Glacier::ZREF m_rLimoDriver; + Glacier::ZREF m_rPriest; + Glacier::ZREF m_rEndCut; + Glacier::ZREF m_rOutroMovie; + bool m_bTriggerHumanShield; + RE_ADD_PADDING(3); + int m_iDeathToll; + float m_fLevelCompleteTime; + bool m_bTableMoving; + RE_ADD_PADDING(3); + ZPostFilterCollectionEvent* m_pPFCollection; + ZPostFilterEvent* m_pPF; + ZPostFilterSetEvent* m_pPFSet; ZPodiumController m_podiumControl; }; //End of ZHM3LevelControlM13 from 0057E6B8 + RE_VERIFY_SIZE(ZHM3LevelControlM13, 0x668); + RE_VERIFY_OFFSET(ZHM3LevelControlM13, m_bMissionComplete, 0x5D8); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Info.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Info.h new file mode 100644 index 0000000..a65f907 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Info.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +namespace Hitman::BloodMoney +{ + struct SKeyFrame_Info + { + float m_fTime; + }; + RE_VERIFY_SIZE(SKeyFrame_Info, 0x4); // verified + + struct SPicture_Info + { + const char* m_Picture_Name; + uint32_t m_iPicture_Nr; + float m_fPosX; + float m_fPosY; + float m_fOpacity; + float m_fMultiply; + uint32_t m_iPosition_Interpolation; + }; + RE_VERIFY_SIZE(SPicture_Info, 0x1C); // verified + + struct ZLoader_Sequence_Info + { + uint32_t m_iNr_Key_Frames; + uint32_t m_iPicture_Name_Count; + char* m_pPicture_Name_Buffer; + uint32_t* m_pPicture_Name_Offsets_Buffer; + SKeyFrame_Info* m_pKey_Frame_Info_Table; + SPicture_Info* m_pPicture_Info_Table; + uint32_t m_field18; + uint32_t m_field1C; + uint32_t m_field20; + uint32_t m_field24; + uint32_t m_field28; + float m_field2C; + }; + RE_VERIFY_SIZE(ZLoader_Sequence_Info, 0x30); // verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Player_Base.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Player_Base.h new file mode 100644 index 0000000..d56dccd --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Player_Base.h @@ -0,0 +1,18 @@ +#pragma once + +#include + + +namespace Hitman::BloodMoney +{ + class ZLoader_Sequence_Player_Base + { + public: + virtual ~ZLoader_Sequence_Player_Base(); + virtual void Start(); + virtual void Finish(); + virtual void Progress(float fValue); + virtual void Disable_Render(); + virtual void Enable_Render(); + }; +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Script.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Script.h new file mode 100644 index 0000000..601459a --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Script.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + + +namespace Hitman::BloodMoney +{ + struct ZLoader_Sequence_Script + { + ZLoader_Sequence_Info m_Loader_Sequence_Info; + float m_fLast_KeyFrame_Time; + float m_fScreen_Size_X; + float m_fScreen_Size_Y; + float m_fFull_Progress_Time; + float m_fProgress; + float m_fTime_Adjustment; + }; +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Script_Reader.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Script_Reader.h new file mode 100644 index 0000000..ef58e7e --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Script_Reader.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +namespace Hitman::BloodMoney +{ + enum eREAD_MODE { + eNOTHING = 0, + eGATHER_INFO = 1, + eFILL_STRUCTS = 2, + }; + + struct ZLoader_Sequence_Script_Reader : public Glacier::SimpleXML + { + float m_fLast_KeyFrame_Time; + float m_fScreen_Size_X; + float m_fScreen_Size_Y; + float m_fFull_Progress_Time; + eREAD_MODE m_eRead_Mode; + uint32_t m_iNr_Key_Frames; + uint32_t m_iPicture_Name_Count; + char* m_pPicture_Name_Buffer; + uint32_t m_iPicture_Name_Buffer_Size_Total; + uint32_t m_iPicture_Name_Buffer_Size_Used; + uint32_t* m_pPicture_Name_Offsets_Buffer; + uint32_t m_iPicture_Name_Offsets_Buffer_Size; + float m_fCurrent_Time; + uint32_t m_iCurrent_Key_Frame_Nr; + ZLoader_Sequence_Info* m_pLoader_Sequence_Info; + }; // 0x1F4 current state, target is 0x1F8 +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Setup.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Setup.h new file mode 100644 index 0000000..2df9ab5 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Setup.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZLoader_Sequence_Setup : public Glacier::ZSTDOBJ + { + public: + Glacier::ZRTString m_Loader_Script_File; + Glacier::REFTAB32 m_Pictures; + }; + RE_VERIFY_SIZE(ZLoader_Sequence_Setup, 0xC0); + RE_VERIFY_OFFSET(ZLoader_Sequence_Setup, m_Loader_Script_File, 0x10); + RE_VERIFY_OFFSET(ZLoader_Sequence_Setup, m_Pictures, 0x14); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Wintel_D3D.h b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Wintel_D3D.h new file mode 100644 index 0000000..cb49965 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/LoaderSequence/ZLoader_Sequence_Wintel_D3D.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + struct ZLoader_Sequence_Script_Reader; + + struct ZGeometrySubObject + { + uint16_t m_usSize[2]; + float m_fOffset[2]; + float m_fMoveSpeed[2]; + char m_szName[24]; + int *pTexture; + uint32_t *m_pAnimData; + Glacier::ZPFORMAT m_Format; + uint32_t m_dwDataSize; + float m_fScaleFactor; + uint16_t m_lTextureId; + uint16_t m_lDrawEntryId; + float m_fCustomParamX; + float m_fCustomParamY; + int *pVertexBuffer; + }; + RE_VERIFY_SIZE(ZGeometrySubObject, 0x50); + + struct ZGeometryObjectHeader + { + ZGeometrySubObject *pSubObjectsArray; + int iSubObjectCount; + }; + RE_VERIFY_SIZE(ZGeometryObjectHeader, 0x8); + + + class ZLoader_Sequence_Wintel_D3D : public ZLoader_Sequence_Player_Base + { + public: + // vtbl (no changes) + // members + uint32_t m_hEvent; // +0x4 + uint32_t m_hThread; // +0x8 + ZLoader_Sequence_Script_Reader *pReader; // +0xC + int m_pPoolEnd; // +0x10 + float m_fCurrentTime; // +0x14 + uint32_t m_field18; + uint32_t m_field1C; + ZGeometryObjectHeader* m_aObjects; // +0x20 + int m_iTotalObjects; + int m_pUnknownPool; + int m_iUnknownPoolFreeObjects; + }; + RE_VERIFY_SIZE(ZLoader_Sequence_Wintel_D3D, 0x30); + RE_VERIFY_OFFSET(ZLoader_Sequence_Wintel_D3D, m_fCurrentTime, 0x14); + RE_VERIFY_OFFSET(ZLoader_Sequence_Wintel_D3D, m_aObjects, 0x20); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/CBodyContainer.h b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/CBodyContainer.h new file mode 100644 index 0000000..271cfdc --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/CBodyContainer.h @@ -0,0 +1,62 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + enum eBCState + { + STATE_OPEN = 0, + STATE_CLOSE = 1, + STATE_OPENING = 2, + STATE_CLOSING = 3, + }; + + enum eBCType + { + BC_CRATE = 0, + BC_DUMPSTER = 1, + BC_GARBAGETRUCK = 2, + }; + + // used in "ContainerState" ZMSG (via SendCommand("ContainerState", &state)) + struct sBodyContainerState + { + int m_iNumBodies; + eBCState m_eState; + }; + + class CBodyContainer : public Glacier::CBaseEvent + { + public: + // vtbl + // data + Glacier::ZGEOM* m_pDoor; + Glacier::ZGEOM* m_pOperatePoint; + eBCState m_eState; + eBCType m_eType; + Glacier::ZAction* m_pAction; + Glacier::ZREF m_rContainedBody; + Glacier::ZAUDIOREF m_sndOpen; + Glacier::ZAUDIOREF m_sndOpened; + Glacier::ZAUDIOREF m_sndClose; + Glacier::ZAUDIOREF m_sndClosed; + Glacier::ZREF m_rDoor; + Glacier::ZREF m_rOperatePoint; + float m_fAnimTime; + eBCState m_eInitialState; + bool m_bRemoveBodies; + Glacier::ZRunMatPosAnim m_Animation; + Glacier::ZGEOM* m_pEndPosGeom; + Glacier::ZMat3x3 m_mActorEndMat; + Glacier::ZVector3 m_vActorEndPos; + float m_fOpenTime; + }; // Size 0xC0 + RE_VERIFY_SIZE(CBodyContainer, 0xC0); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/CKeycardReader.h b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/CKeycardReader.h index 97b3406..339ff27 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/CKeycardReader.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/CKeycardReader.h @@ -1,11 +1,13 @@ #pragma once -#include +#include +#include +#include #include #include - #include + namespace Hitman::BloodMoney { /** @@ -16,12 +18,18 @@ namespace Hitman::BloodMoney bool m_bLocatedNearToKeycardReader; //out }; - class CKeycardReader : public Glacier::ZEventBase + enum eControlledObjecttype + { + eDoor = 0, + eElevator = 1, + }; + + class CKeycardReader : public Glacier::CBaseEvent { public: //vftable (no changes) // custom API - Glacier::ZEntityLocator* GetNearestDoor(unsigned int iDoorsCount, Glacier::ZEntityLocator** ppDoorsList); + Glacier::ZBaseGeom* GetNearestDoor(unsigned int iDoorsCount, Glacier::ZBaseGeom** ppDoorsList); void ValidateKeyCard(Glacier::ZREF cardREF); void InvalidateKeyCard(Glacier::ZREF cardREF); void DetermineLnkObjLocation(sQueryLnkObjLocation* pQuery); @@ -30,20 +38,18 @@ namespace Hitman::BloodMoney bool IsKeyCardValid(BloodMoney::ZHM3Item* pItem); // data (total size is 0x8C, base size is 0x30) - Glacier::ZREF m_useKeycardActionREF; // REF to Event (use ZEventBuffer to locate instance) - int m_nearestDoor; - int m_field38; - int m_field3C; - unsigned short m_field40; - unsigned short m_field42; - int m_field44; - int m_field48; - Glacier::REFTAB m_reftab4C; - Glacier::REFTAB m_reftab68; - char m_field84; - char m_field85; - char m_field86; - char m_field87; - int m_bIsElevatorButton; + Glacier::ZAction* m_pAction; + Glacier::ZREF m_rControlledObject; + Glacier::ZRTString m_szKeyCardTemplates; + Glacier::ZRTString m_szKeyCard; + Glacier::ZMSGID m_msgObjectActivator; + Glacier::ZAUDIOREF m_sValidCardSound; + Glacier::ZAUDIOREF m_sInvalidCardSound; + Glacier::REFTAB m_rValidKeyCardTemplate; + Glacier::REFTAB m_rValidKeycardItems; + bool m_bElevRequested; + bool m_bUseLnkAction; + eControlledObjecttype m_eObjectType; }; + RE_VERIFY_SIZE(CKeycardReader, 0x8C); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/CMetalDetector.h b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/CMetalDetector.h index fbe6600..bc1190c 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/CMetalDetector.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/CMetalDetector.h @@ -1,26 +1,29 @@ #pragma once -#include +#include +#include #include +#include + namespace Hitman::BloodMoney { - class CMetalDetector : public Glacier::ZEventBase + class CMetalDetector : public Glacier::CBaseEvent { public: + // vtbl // api void DoDetectWeapon(); void DoAlarm(); // data (total size is 0xA8, ZEventBase size is 0x30) - Glacier::REFTAB m_pAttachedActorsRefTab; - int field_4C; - Glacier::REFTAB m_reftab1; - Glacier::REFTAB m_reftab2; - Glacier::REFTAB m_reftab3; - char m_bIsAlarming; - char field_A5; - char field_A6; - char field_A7; + Glacier::REFTAB m_rtTargets; + Glacier::ZAUDIOREF m_rSnd; + Glacier::REFTAB m_rIgnoredHMAs; + Glacier::REFTAB m_rIgnoredWeapons; + Glacier::REFTAB m_rtMetalItems; + bool m_bInside; + RE_ADD_PADDING(3); }; + RE_VERIFY_SIZE(CMetalDetector, 0xA8); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZFireAlarm.h b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZFireAlarm.h index 1e15836..4dc5013 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZFireAlarm.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZFireAlarm.h @@ -1,19 +1,21 @@ #pragma once -#include +#include +#include #include namespace Hitman::BloodMoney { - class ZFireAlarm : public Glacier::ZEventBase + class ZFireAlarm : public Glacier::CBaseEvent { /// vftable - no custom vftable /// data (total size : 0x48, ZEventBase size: 0x30) - int m_field30; - int m_field34; - int m_field38; - Glacier::REFTAB* m_listeners; - Glacier::REFTAB* m_reftab40; - int m_field44; + Glacier::ZREF m_rAlarmArea; + Glacier::ZREF m_rPanicArea; + int m_iTime; + Glacier::REFTAB* m_pSwitches; + Glacier::REFTAB* m_pBells; + float m_fTimeOutCounter; }; + RE_VERIFY_SIZE(ZFireAlarm, 0x48); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZFurniture.h b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZFurniture.h new file mode 100644 index 0000000..eb34185 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZFurniture.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + struct ZBits + { + bool bPulledIn; + bool bSofaLeftSideUser; + bool bSofaRightSideUser; + bool bSofaCenterSideUser; + }; + RE_VERIFY_SIZE(ZBits, 4); + + enum EFurnitureType + { + CHAIR = 0, + MOVEABLECHAIR = 1, + BARCHAIR = 2, + SOFA_2PERS = 3, + SOFA_3PERS = 4, + BED = 5, + }; + + class ZFurniture : public Glacier::CBaseEvent + { + public: + // vtbl + // methods + void SetPulledIn(bool bPulledIn) + { + ZASSERT(m_iType == EFurnitureType::MOVEABLECHAIR); + m_Bits.bPulledIn = bPulledIn; + } + + // data + EFurnitureType m_iType; + uint8_t m_iMaxNumUser; + Glacier::ZVector3 m_vResetPos; + uint8_t m_iNumUsers; + ZBits m_Bits; + }; + RE_VERIFY_SIZE(ZFurniture, 0x4C); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZInterestPoint.h b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZInterestPoint.h new file mode 100644 index 0000000..e69de29 diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZM13PosController.h b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZM13PosController.h new file mode 100644 index 0000000..3b68b64 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZM13PosController.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZM13PosController : public Glacier::CBaseEvent + { + public: + // vtbl + // data + Glacier::ZGEOM* m_aActors[10]; + int m_iNrOfActors; + }; // Size 0x5C + RE_VERIFY_SIZE(ZM13PosController, 0x5C); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZMardiGrassFloat.h b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZMardiGrassFloat.h new file mode 100644 index 0000000..0b12aaa --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZMardiGrassFloat.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Hitman::BloodMoney +{ + struct ZMardiGrassFloat : public Glacier::ZGROUP + { + float m_fWidth; + float m_fLength; + uint32_t m_lNumCorners; + Glacier::ZMatrix m_MovementCorners[9]; + Glacier::ZStackArray<16, ZGEOM*> m_Corners; + Glacier::ZREF m_rObstacleBase; + ZMardiGrassFloat* m_pFloatGroup; + Glacier::ZMat3x3 m_mTrackerPosition; + Glacier::ZVector3 m_vTrackerPosition; + uint32_t m_lNextCorner; + Glacier::ZMat3x3 m_mPosition; + Glacier::ZVector3 m_vPosition; + Glacier::ZMatrix m_PrevPosition; + Glacier::ZGEOM* m_pCenterGeom; + Glacier::PF4::ZDynamicObstacle* m_pObstacle; + }; + RE_VERIFY_SIZE(ZMardiGrassFloat, 0x2F0); // Not finished yet +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZUsePoint.h b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZUsePoint.h new file mode 100644 index 0000000..1427c9d --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZUsePoint.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZUsePoint : public Glacier::ZSTDOBJ + { + public: + // vtbl + // data + float m_fProbability; + bool m_bLocked; + RE_ADD_PADDING(3); + Glacier::ZREF m_rRelocBox; + Glacier::ZGEOM* m_pRelocBox; + }; + RE_VERIFY_SIZE(ZUsePoint, 0x20); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZVCR.h b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZVCR.h index f3600ac..0344be9 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZVCR.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZVCR.h @@ -1,10 +1,12 @@ #pragma once -#include +#include +#include +#include namespace Hitman::BloodMoney { - class ZVCR : public Glacier::ZEventBase + class ZVCR : public Glacier::CBaseEvent { public: // vtbl (no changes) @@ -13,6 +15,7 @@ namespace Hitman::BloodMoney static bool TapeWasStolen(); // data (size is 0x34) - Glacier::ZAction* m_stealTapeAction; + Glacier::ZAction* m_pAction; }; + RE_VERIFY_SIZE(ZVCR, 0x34); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZZoneControl.h b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZZoneControl.h new file mode 100644 index 0000000..8d4a952 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/OnLevel/ZZoneControl.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZZoneControl : public Glacier::CBaseEvent + { + public: + Glacier::ZBitfield m_eZone; + Glacier::REFTAB m_Rooms; + }; + RE_VERIFY_SIZE(ZZoneControl, 0x50); // Verified + +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/PF/ZPathFollower.h b/ReHitman/BloodMoney/include/BloodMoney/Game/PF/ZPathFollower.h index 31ecb8e..f26d133 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/PF/ZPathFollower.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/PF/ZPathFollower.h @@ -2,7 +2,7 @@ #include #include -#include +#include namespace Hitman::BloodMoney { @@ -10,7 +10,7 @@ namespace Hitman::BloodMoney enum EScriptPathType : int {}; //TODO: Reverse all possible values of enum - class ZPathFollower : public Glacier::ZEventBase + class ZPathFollower : public Glacier::ZBaseConRout { public: /// === consts === diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/PF4/PF4RunTime.h b/ReHitman/BloodMoney/include/BloodMoney/Game/PF4/PF4RunTime.h index 64aa37f..f716252 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/PF4/PF4RunTime.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/PF4/PF4RunTime.h @@ -1,5 +1,7 @@ #pragma once +#include + namespace Hitman::BloodMoney::PF4RunTime { class ZData { public: @@ -12,4 +14,33 @@ namespace Hitman::BloodMoney::PF4RunTime { int m_field4; //TODO: Complete reverse here }; + + + struct ZPath + { + int* m_PathIdx; + int m_iMaxSize; + Glacier::ZVector3 m_Vertices[4]; + int m_CustomVertices; + void* m_PathFinder; + int m_Size; + float m_Cost; + + void GetPosition(int index, Glacier::ZVector3& pos) + { + using GetPosition_t = void(__thiscall *)(ZPath*, int, Glacier::ZVector3&); + + GetPosition_t GetPositionImpl = reinterpret_cast(0x004D8E20); + GetPositionImpl(this, index, pos); + } + + void GetEndPosition(Glacier::ZVector3& pos) + { + // from original code + if (m_Size > 0) + { + GetPosition(m_Size - 1, pos); + } + } + }; } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/SIconBase.h b/ReHitman/BloodMoney/include/BloodMoney/Game/SIconBase.h index 89a00f7..65dc5e6 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/SIconBase.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/SIconBase.h @@ -1,12 +1,15 @@ #pragma once +#include #include namespace Hitman::BloodMoney { - struct SIconBase + struct SIconBase { - Glacier::ZREF m_iIconREF; - bool m_bIsVisible; + Glacier::ZREF rGeomObj; + bool bVisible; + RE_ADD_PADDING(3); }; + RE_VERIFY_SIZE(SIconBase, 0x8); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/SMapGroup.h b/ReHitman/BloodMoney/include/BloodMoney/Game/SMapGroup.h index 3a6df3e..3f152d0 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/SMapGroup.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/SMapGroup.h @@ -4,10 +4,11 @@ namespace Hitman::BloodMoney { - struct SMapGroup + struct SMapGroup { - int m_unk0; //0x0000 - Glacier::ZREF m_ROOM_REF; //0x0004 (ZGROUP or derived from ZGROUP) - char* m_name; //0x0008 - }; //Size is 0xC + Glacier::ZREF rWorldGroup; + Glacier::ZREF rMapGroup; + const char* szName; + uint32_t iIndex; + }; // Not confirmed, but should be valid } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/CMainMenu.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/CMainMenu.h new file mode 100644 index 0000000..e97aa0e --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/CMainMenu.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include + +namespace Glacier +{ + struct IView; +} + +namespace Hitman::BloodMoney +{ + class CMainMenu : public Glacier::CBaseEvent + { + public: + // vtbl + // data + Glacier::ZCAMERA* m_pAnimCamera; + Glacier::ZCAMERA* m_pOverlayCamera; + Glacier::ZCAMERA* m_pLogoCamera; + Glacier::IView* m_pView1; + Glacier::IView* m_pView2; + Glacier::IView* m_pView3; + Glacier::REFTAB m_rtCameras; + Glacier::ZREF m_rScopeCamera; + Glacier::ZREF m_rScopeGroup; + Glacier::REFTAB m_rtTargets; + Glacier::REFTAB m_rtOverlays; + Glacier::ZREF m_rLogoCamera; + Glacier::ZREF m_rLogoGroup; + }; + RE_VERIFY_SIZE(CMainMenu, 0xAC); // verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/CMenuWindow.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/CMenuWindow.h new file mode 100644 index 0000000..d0586d3 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/CMenuWindow.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include +#include + +namespace Hitman::BloodMoney +{ + class CMenuWindow : public CWinEvent + { + public: + // vtbl (no new entries) + // data + Glacier::ZREF m_rFadeDown; + float m_fOtherVis; + float m_fVisibility; + float m_fPushTime; + bool m_bDeactivateFrmupdWhenFaded; + }; + RE_VERIFY_SIZE(CMenuWindow, 0x44); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/CWinEvent.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/CWinEvent.h index 238475f..878a595 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/CWinEvent.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/CWinEvent.h @@ -3,65 +3,15 @@ #include #include #include -#include +#include #include #include namespace Hitman::BloodMoney { - /** - * @todo Think about class inheritance here. Probably, - * I'm not right here and partial specialization isn't a key to this solution. - * I guess the virtual functions table was built from template type 'T", - * not manually but I don't know where is the class' T data? - * @tparam T - type of class - */ - template class CWinEvent; - - template <> class CWinEvent : public Glacier::ZEventBase - { - public: - //vftable - virtual ZWINDOWS* GetSystem(); //#36 | +90 - virtual void WndMessage(Glacier::ZWMEVENT *); //#37 | +94 - virtual void OnCommand(Glacier::ZMSGID); //#38 | +98 - virtual void OnMouseMove(Glacier::ZVector2*); //#39 | +9C - virtual void OnKeyUp(unsigned int); //#40 | +104 - virtual void OnKeyDown(unsigned int); //#41 | +108 - virtual void OnKeyPress(unsigned int); //#42 | +10C - virtual void OnFocusReceived(unsigned int); //#43 | +110 - virtual void OnFocusLost(unsigned int); //#44 | +114 - virtual void OnClick(float x, float y); //#45 | +118 - virtual void OnWindowOpen(unsigned int, bool); //#46 | +11C - virtual void OnWindowClose(unsigned int, bool); //#47 | +120 - virtual void OnSliderChange(unsigned int, unsigned int); //#48 | +124 - virtual void OnFocusChanged(unsigned int, unsigned int); //#49 | +128 - - /** - * Base size : 0x30 - * Size : 0x30 - * - * Why: - * Classes: - * CIngameMap - 0x2C4 - * ZActionMenu - 0x810 - * ZActionMenuBase - N/A (not instantiated manually) - * ZActionMenuFade - 0xD0 - * ZCheatMenu - 0x78 - * ZContainerMenu - 0x658 - * ZDropDisplay - 0xD0 - * ZPickupMenu - 0x808 - * ZXMLGUISystem - 0x580 - * - * If we will look for CIngameMap we will see that the first member (ZHandle) was located at 0x30, its class-specific location. - * This means that CWinEvent doesn't contain any internal fields or smth like that. - */ - }; - - template <> class CWinEvent : public Glacier::ZEventBase + template class CWinEvent : public Glacier::CBaseEvent { - public: //vftable virtual ZWINDOWS* GetSystem(); //#36 | +90 virtual void WndMessage(Glacier::ZWMEVENT *); //#37 | +94 diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/IGUIElement.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/IGUIElement.h index 10a8144..fa1b655 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/IGUIElement.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/IGUIElement.h @@ -4,32 +4,32 @@ #include #include -namespace Hitman::BloodMoney { +namespace Hitman::BloodMoney +{ class ZWINDOW; class ZXMLGUISystem; class ZResourceManager; + class ZButtonGraphic; + + enum EFontType + { + FT_HEADER = 0, + FT_MENU = 1, + FT_TEXT = 2, + NUM_OF_FONTS = 3, + }; - class IGUIElement : public ZGUIBase { - public: - //pub - enum class EAlignment { - Left = 1, - Right = 0, - Center = 2 - }; - - enum class EFontType { - Header = 0, - Menu = 1, - Text = 2 - }; - - struct SVector44 { - int m_count; - IGUIElement* pEntry[44]; - }; + enum EAlignment + { + ERIGHT = 0, + ELEFT = 1, + ECENTER = 2, + }; - //vftable + class IGUIElement : public ZGUIBase + { + public: + //vtbl virtual void Update(bool); virtual void Click(eZWUserEvents, int, ZXMLGUISystem*); virtual void OpenSubwindow(); @@ -49,42 +49,14 @@ namespace Hitman::BloodMoney { void SetColor(uint32_t rgba, ZWINGROUP* pGroup, uint32_t mask = 0xFFFFFFFFu); void GetRightPosOfTextGroup(ZWINGROUP*, Glacier::Vector3* pPos, int iOffsetByX); - //data (total size is 0x70, base size is 0x4C) - ZColorSet* m_pColorSet; //0x4C - int m_field50; //0x50 - int m_field54; //0x54 - EFontType m_eFontType; //0x58 - EAlignment m_eAlignment; //0x5C - int m_pButtonGraphic; //0x60 - bool m_bShadow; //0x61 - bool m_field62; //0x62 - bool m_field63; //0x63 - bool m_field64; //0x64 - int m_field68; //0x68 - int m_iActivateButtonKeyCode; //0x6C - - /* - * @note: - * Why the size of this class is 0x6C? - * Because there are no direct allocations of IGUIElement instance without any inheritance - * we need to find a class with the lowest size and small inheritance tree and if it exists we can choose - * the size of that class as the base size (means that this class does not contain any additional information). - * There are presented the class list which selected to find base size: - * - * Class Size (HEX, in bytes) - * ----------------------------- - * ZBackgroundCameraClear 0x6C - * ZHM3HintDetail 0x6C - * ZAnimation 0x80 - * ZTextBlock 0x80 - * ZXMLFrame 0x80 - * ZGraphic 0x84 - * ZWeaponDetails 0x110 - * ZUpgradeInfo 0x110 - * ZGUIEdit 0x240 - * ZWeaponSelector 0x564 - * ZListBox 0xC14 - * ZGUIList 0x1A48 - */ + //data (total size is 0x68, base size is 0x4C) + ZColorSet* m_pColorSet; + int32_t m_iIndex; + int32_t m_iControlPrompt; + EFontType m_eFontType; + EAlignment m_eAlignment; + ZButtonGraphic* m_pButtonGraphic; + bool m_bShadow; }; + RE_VERIFY_SIZE(IGUIElement, 0x68); // Verified by PS2 and previous comment } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/IWindowInterface.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/IWindowInterface.h index 20ea5b6..ff70bcd 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/IWindowInterface.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/IWindowInterface.h @@ -1,35 +1,39 @@ #pragma once +#include +#include +#include #include #include -namespace Hitman::BloodMoney { +namespace Hitman::BloodMoney +{ class ZFRAME; + class ZResourceManager; - enum ENavigation { - ENAV_HORIZONTAL, - ENAV_VERTICAL + enum ENavigation + { + EVERTICAL = 0, + EHORIZONTAL = 1, }; - enum EGUIAlignType { - //Horizontal - AT_H_Left = 1, - AT_H_Right = 2, - AT_H_Center = 4, - //Vertical - AT_V_Top = 16, - AT_V_Bottom = 32, - AT_V_Center = 64 - }; - class IWindowInterface : public ZGUIBase { + class IWindowInterface : public ZGUIBase + { public: + // types + struct ZElementExtraInfo + { + IGUIElement* m_pGUIElement; + int32_t m_iAlignmentOverride; + }; + //vftable - virtual void OpenWindow(ZResourceManager* pResourceManager, bool, ZWINGROUP* pWinGroup, bool); //pure virtual - virtual void CloseWindow(ZResourceManager* pResourceManager, bool); //pure virtual + virtual void OpenWindow(ZResourceManager* pResourceManager, bool, ZWINGROUP* pWinGroup, bool); + virtual void CloseWindow(ZResourceManager* pResourceManager, bool); virtual void PushSubWindow(const char* psName, IGUIElement* pGuiElement, bool, bool); virtual void PopSubWindow(); - virtual void Update(int); //pure virtual + virtual void Update(int); virtual ZWINDOW* GetTopSubWindow(); virtual ZWINDOW* GetButtomSubWindow(); virtual IGUIElement* GetCurrentElements(); @@ -39,42 +43,24 @@ namespace Hitman::BloodMoney { virtual bool IsDialog(); virtual bool IsTRC(); virtual int GetTRCPriority(); - virtual void Click(IGUIElement* pGuiElement, int /*eZWUserEvents*/, unsigned int); + virtual void Click(IGUIElement* pGuiElement, eZWUserEvents, unsigned int); - /** - * Size reconstruction: - * Here we have 2 inherited things: - * 1) ZStandardWindow - size is 0x15C - * 2) ZComponentWindow - size is 0x39C - * - * And there are contains first field at 0x90. So, I guess that total size of base class is 0x90 - */ //data (total size is 0x90, base size is 0x4C) - int m_field4C; + ZResourceManager* m_pResourceManager; bool m_bPopOnBack; - bool field_51; - bool field_52; - bool field_53; - const char* m_psBackground; - int m_field58; - int m_field5C; - const char* m_psRollBackWindow; - int m_field64; - int m_field68; - ZWINGROUP* m_pGraphicGroup; - ZFRAME* m_pFrame; - int m_iWidth; - int m_iHeight; - bool m_bUseBackgroundImage; - bool m_bFrame; - bool field_7E; - bool field_7F; - int m_iAlignment; //it's mask, see EGUIAlignType for details - int m_iLineSpace; + Glacier::zstring m_sBackground; + Glacier::zstring m_sRollBackWindow; + ZWINGROUP* m_pWinGroupBackGround; + ZFRAME* m_pFrameBackground; + Glacier::ZVector2 m_v2WindowSize; + bool m_bUseBackgroundIngame; + bool m_bBackgroundIsFrame; + uint32_t m_iWindowAlignment; + int32_t m_iLineSpace; ENavigation m_eNavigation; - bool m_bIsOpened; + bool m_bOpen; bool m_bRollBackMark; bool m_bPauseEngine; - bool field_8F; }; + RE_VERIFY_SIZE(IWindowInterface, 0x90); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZCHAROBJ.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZCHAROBJ.h index fb16c7a..5e5ed38 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZCHAROBJ.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZCHAROBJ.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -24,11 +25,14 @@ namespace Hitman::BloodMoney // api // data (size is 0xA0, base size is 0x88) - int m_field88; - int m_field8C; - int m_field90; - int m_field94; - int m_field98; - int m_field9C; + int8_t m_iLineSpacing; + uint32_t m_iIconPrim; + Glacier::ZRTString m_szTextPtr; + Glacier::ZRTString m_szStringId; + ZFONT* m_pFont; + int8_t m_iTabSize; + int8_t m_iMonoSpaceSize; + int8_t m_iSpacingAdd; }; + RE_VERIFY_SIZE(ZCHAROBJ, 0xA0); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZCUSTOMFRAME.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZCUSTOMFRAME.h new file mode 100644 index 0000000..468502f --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZCUSTOMFRAME.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZCUSTOMFRAME : public ZFRAME + { + public: + // vtbl (no changes except overrides) + // data + int32_t m_aWidths[3]; + int32_t m_aHeights[3]; + }; + RE_VERIFY_SIZE(ZCUSTOMFRAME, 0xD0); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZColorSet.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZColorSet.h index 160a5b1..78a41e1 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZColorSet.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZColorSet.h @@ -5,10 +5,11 @@ namespace Hitman::BloodMoney { class ZColorSet : public ZGUIBase { public: - enum EColorIndex { - DisableColor, - FocusColor, - NormalColor + enum EColorIndex + { + DisableColor = 0, + FocusColor = 1, + NormalColor = 2 }; //vftable (no changes) @@ -16,9 +17,7 @@ namespace Hitman::BloodMoney { uint32_t GetColor(EColorIndex colorIndex); //data (total size is 0x58, base size is 0x4C) - int m_field4C; - uint32_t m_NormalColor; - uint32_t m_FocusColor; - uint32_t m_DisableColor; + uint32_t m_aiColors[3]; }; + RE_VERIFY_SIZE(ZColorSet, 0x58); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZExtCharObj.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZExtCharObj.h new file mode 100644 index 0000000..ce13dc3 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZExtCharObj.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZExtCharObj : public ZCHAROBJ + { + public: + // vtbl + // data (no new data) + }; + RE_VERIFY_SIZE(ZExtCharObj, 0xA0); +} diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZFONT.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZFONT.h index c7f290e..d6e4384 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZFONT.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZFONT.h @@ -1,15 +1,26 @@ #pragma once +#include +#include #include -namespace Hitman::BloodMoney { - struct SCharInfo { - uint32_t charCode; - uint32_t unk0; - uint32_t unk1; - uint32_t unk2; - uint32_t unk3; +namespace Hitman::BloodMoney +{ + using UTC4CHAR = uint32_t; + + struct SGlyph + { + UTC4CHAR uChar; + Glacier::ZREF rTexture; + int8_t vUV1[2]; + int8_t vUV2[2]; + uint8_t vSize[2]; + int8_t vStart[2]; + int8_t vAdvance; + int8_t bIcon; + int8_t _pad; }; + RE_VERIFY_SIZE(SGlyph, 0x14); // Verified by ZTTFONT::GetCharInfo (bsearch method contains size of entry) enum EFontFilterMode { FFM_Normal, @@ -18,15 +29,16 @@ namespace Hitman::BloodMoney { FFM_Invert }; - class ZFONT : public ZWINOBJ { + class ZFONT : public ZWINOBJ + { public: - // vftable - // at least 5 virtual methods - virtual int GetNumTextures(); // It's pure virtual for base class ZFONT - virtual SCharInfo* GetCharInfo(unsigned int); // It's pure virtual for base class ZFONT - virtual int GetMaxHeight(); // It's pure virtual for base class ZFONT - virtual bool ContainsChar(unsigned int); // It's pure virtual for base class ZFONT - virtual void* GetKerning(unsigned int, unsigned int); // It's pure virtual for base class ZFONT + // vftable - 5 pure virtual methods + virtual int GetNumTextures(); + virtual SGlyph* GetCharInfo(unsigned int); + virtual int GetMaxHeight(); + virtual bool ContainsChar(unsigned int); + virtual void* GetKerning(unsigned int, unsigned int); // data (size is 0x88, base size is 0x88) }; + RE_VERIFY_SIZE(ZFONT, 0x88); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZFRAME.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZFRAME.h new file mode 100644 index 0000000..116a84a --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZFRAME.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +namespace Hitman::BloodMoney +{ + class ZFRAME : public ZWINOBJ + { + public: + // vtbl + virtual void SetSize(int, int); + virtual void SetOuterSize(int, int); + virtual void CreateGeometry(); + + // data + uint32_t m_aPieces[9]; + uint32_t m_lTextSize; + int32_t m_lWidth; + int32_t m_lHeight; + }; + RE_VERIFY_SIZE(ZFRAME, 0xB8); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZGUIBase.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZGUIBase.h index 615316b..10f49e9 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZGUIBase.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZGUIBase.h @@ -1,24 +1,27 @@ #pragma once +#include #include namespace Hitman::BloodMoney { - class ZHM3MenuElements; + class ZMenuElements; class ZWINGROUP; class ZGUIBase { public: // vtable - virtual void readParams(const char**, ZHM3MenuElements*); + virtual void readParams(const char**, ZMenuElements*); virtual void addElement(const char*, ZGUIBase*); // api void GetSize(ZWINGROUP* pGroup, Glacier::Vector2* pSize); + void GetPos(Glacier::Vector2* pPos); // data (total size is 0x4C) - char m_name[0x40] { 0 }; //0x0004 - Glacier::ZVector2 m_position {}; //0x0044 + char m_szName[0x40] { 0 }; //0x0004 + Glacier::ZVector2 m_v2Pos {}; //0x0044 }; + RE_VERIFY_SIZE(ZGUIBase, 0x4C); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZKerningFont.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZKerningFont.h index aeeedce..232e9be 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZKerningFont.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZKerningFont.h @@ -1,13 +1,19 @@ +#pragma once + +#include #include -namespace Hitman::BloodMoney { - class ZKerningFont : public ZTTFONT { +namespace Hitman::BloodMoney +{ + class ZKerningFont : public ZTTFONT + { public: - // vftable - // custom api + // vtbl (no changes) + // methods static ZKerningFont* Create(); // data (size is 0x9C, base size is 0x98) - int m_field98; + int32_t m_iExtraKerning; }; + RE_VERIFY_SIZE(ZKerningFont, 0x9C); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZLINEOBJ.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZLINEOBJ.h index 3bf5aff..ce37938 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZLINEOBJ.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZLINEOBJ.h @@ -1,5 +1,6 @@ #pragma once +#include #include namespace Hitman::BloodMoney @@ -18,8 +19,9 @@ namespace Hitman::BloodMoney static ZLINEOBJ* Create(); // data (total size is 0xAC, base size is 0xA0) - int m_fieldA0; - int m_fieldA4; - int m_fieldA8; + char* m_szText; + int32_t m_iWidth; + int8_t m_iNumberOfLines; }; + RE_VERIFY_SIZE(ZLINEOBJ, 0xAC); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZOSD.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZOSD.h index 9ea0d19..c6f9294 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZOSD.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZOSD.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -9,6 +10,7 @@ namespace Hitman::BloodMoney { class ZLINEOBJ; class ZCheatMenu; + class ZContainerMenu; class ZOSD : public Glacier::ZSTDOBJ { @@ -41,24 +43,24 @@ namespace Hitman::BloodMoney void AddHint(const char* message, bool a2, bool shouldPlayNotificationSound, int osdElement, bool a6, const char* tutorialId); //data (total size is 0x8FC, base size is 0x10) - char m_field10; - char field_11; - char field_12; - char field_13; - char m_field14; - char field_15; - char field_16; - char field_17; - char m_field18; - char field_19; - char m_bShowWeaponDisplay; - char field_1B; - char m_field1C; - char field_1D; - char m_bDrawActionMenu; - char field_1F; - char m_field20; - char field_21; + char m_field10; //+0x10 + char field_11; //+0x11 + char field_12; //+0x12 + char field_13; //+0x13 + char m_field14; //+0x14 + char field_15; //+0x15 + char field_16; //+0x16 + char field_17; //+0x17 + char m_field18; //+0x18 + char field_19; //+0x19 + char m_bShowWeaponDisplay; //+0x1A + char field_1B; //+0x1B + char m_field1C; //+0x1C + char field_1D; //+0x1D + char m_bDrawActionMenu; //+0x1E + char m_bDrawContainerMenu; //+0x1F + char m_bForceHideCrosshair; //+0x20 + char field_21; //+0x21 char field_22; char field_23; int m_field24; @@ -103,12 +105,17 @@ namespace Hitman::BloodMoney char field_A2; char field_A3; int m_fieldA4; - Glacier::ZVector3 m_vInfoDisplayPosition; - int m_rInfoDisplay; - int m_pInfoDisplay; - float m_fHitpoints; - int m_fieldC0_REF; - int m_pHealthFrame; + +#pragma region "Info & Health bars" + // ******** Info & Health ******** + Glacier::ZVector3 m_pInfoPos; + uint32_t m_rInfoDisplay; + class ZInfoDisplay* m_pInfoDisplay; + float m_fCurrentHitpointsFactor; + uint32_t m_rHealthFrame; + class ZWINPIC* m_pHealthFrame; +#pragma endregion + int m_fieldC8_REF; int m_fieldCC; int m_fieldD0_REF; @@ -162,30 +169,43 @@ namespace Hitman::BloodMoney int m_field190; int m_field194; int m_field198; - int m_field19C; - int m_field1A0; - int m_field1A4; - int m_rCheatMenu; - ZCheatMenu* m_pCheatMenu; - int m_vPickupMenuPosition; - int m_field1B4; - int m_field1B8; - int m_rPickupMenu; - int m_pPickupMenu; - Glacier::ZVector3 m_vDropDisplayPosition; - int m_rDropDisplay; - int m_pDropDisplay; - int m_vActionDisplayPosition; - int m_field1DC; - int m_field1E0; - int m_rActionMenu; - int m_pActionDisplay; - int m_field1EC; - int m_field1F0; - int m_field1F4; - int m_rContainerMenu; - int m_pContainerMenu; - Glacier::ZSDOwner m_sdOwner; + +#pragma region "Cheats" + // ********* Cheats ********* + Glacier::ZVector3 m_pCheatsPos; + uint32_t m_rCheatsMenu; + ZCheatMenu* m_pCheatsMenu; +#pragma endregion + +#pragma region "Pickup menu" + // ********* Pickup Menu ********* + Glacier::ZVector3 m_pPickupMenuPos; + uint32_t m_rPickupMenu; + class ZPickupMenu* m_pPickupMenu; +#pragma endregion + +#pragma region "Drop menu" + // ********* Drop Menu ********* + Glacier::ZVector3 m_pDropDisplayPos; + uint32_t m_rDropDisplay; + class ZDropDisplay* m_pDropDisplay; +#pragma endregion + +#pragma region "Action menu" + // ********* Action Menu ********* + Glacier::ZVector3 m_pActionMenuPos; + uint32_t m_rActionMenu; + class ZActionMenu* m_pActionMenu; +#pragma endregion + +#pragma region "Container menu" + // ********* Container Menu ********* + Glacier::ZVector3 m_pContainerMenuPos; + uint32_t m_rContainerMenu; + ZContainerMenu* m_pContainerMenu; +#pragma endregion + + Glacier::ZSDOwner m_SoundDef; int m_field210; int m_field214; int m_field218; @@ -633,4 +653,5 @@ namespace Hitman::BloodMoney char field_8FA; char field_8FB; }; + RE_VERIFY_SIZE(ZOSD, 0x8FC); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZSIMPLEHTML.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZSIMPLEHTML.h new file mode 100644 index 0000000..834ad00 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZSIMPLEHTML.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZFONT; + + struct SOffLimits + { + int32_t iTop; + int32_t iBottom; + int32_t iLeft; + int32_t iWidth; + bool bFullWidth; + }; + RE_VERIFY_SIZE(SOffLimits, 0x14); + + struct SHtmlState + { + // Size: 0x35c (860) bytes + Glacier::ZSafeStackArray<16,unsigned int> ColorStack; + Glacier::ZSafeStackArray<16,unsigned int> WidthStack; + Glacier::ZSafeStackArray<16,unsigned int> IndentStack; + Glacier::ZSafeStackArray<16,unsigned int> JustifyStack; + Glacier::ZSafeStackArray<16,unsigned int> ColumnHeightStack; + Glacier::ZSafeStackArray<16,unsigned int> ColumnTopStack; + Glacier::ZSafeStackArray<16,unsigned int> FontStack; + Glacier::ZSafeStackArray<16,unsigned int> LinespaceStack; + Glacier::ZSafeStackArray<16,unsigned int> KerningStack; + Glacier::ZSafeStackArray<16,unsigned int> GutterStack; + Glacier::ZSafeStackArray<16,unsigned int> CapsStack; + Glacier::ZSafeStackArray<16,unsigned int> TabSizeStack; + SOffLimits OffLimits; + float vPen[2]; + uint32_t iColumnLeft; + uint32_t iCurrentLine; + int32_t iBlockSkip; + ZFONT** m_pFonts; + }; + + class ZSIMPLEHTML : public ZCHAROBJ + { + public: + // const + static constexpr size_t MAX_FONTS_NR = 6; + + // vtbl (no changes) + // methods + // data + ZFONT* m_aFonts[MAX_FONTS_NR]; + uint32_t m_iNumFonts; + const char* m_szError; + }; + RE_VERIFY_SIZE(ZSIMPLEHTML, 0xC0); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZStandardMenuFactory.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZStandardMenuFactory.h index b8d3710..bdcdf73 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZStandardMenuFactory.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZStandardMenuFactory.h @@ -6,11 +6,17 @@ namespace Hitman::BloodMoney class ZStandardWindow; class ZHM3MenuElements; + struct ZListDataInterface + {}; + + struct ITableDataInterface + {}; + class ZStandardMenuFactory { public: - virtual void* GetListDataInteface(const char* dataListTypeName); - virtual void* GetTableDataInterface(const char*); // DO NOT USE THIS! NOT IMPLEMNETED IN BLOOD MONEY + virtual ZListDataInterface* GetListDataInteface(const char* dataListTypeName); + virtual ITableDataInterface* GetTableDataInterface(const char*); virtual ZStandardWindow* WindowFactory(const char* windowName, ZHM3MenuElements* menuElements); virtual ZGUIBase* GUIElementFactory(const char* elementName); }; diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZStandardWindow.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZStandardWindow.h index b96a40c..e7104d3 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZStandardWindow.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZStandardWindow.h @@ -1,9 +1,23 @@ +#pragma once + +#include +#include +#include #include -namespace Hitman::BloodMoney { - class ZStandardWindow : public IWindowInterface { +namespace Hitman::BloodMoney +{ + class ZStandardWindow : public IWindowInterface + { public: - //vftable + //vtbl //data (total size is 0x15C, base size is 0x90) + Glacier::zvector m_vecGUIElementExtraInfo; + Glacier::ZStaticVector m_vecCurrentElements; + int32_t m_iAlignmentId; + bool m_bDialogWindow; + bool m_bTRCWindow; + int m_iTRCPriority; }; + RE_VERIFY_SIZE(ZStandardWindow, 0x15C); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZTTFONT.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZTTFONT.h index d7bd9c1..583cd1a 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZTTFONT.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZTTFONT.h @@ -1,19 +1,34 @@ #pragma once +#include #include -namespace Hitman::BloodMoney { + +namespace Hitman::BloodMoney +{ + struct SFontData + { + uint32_t lFontSize; + float fAspect; + uint32_t lNumChars; + uint32_t lMaxHeight; + uint32_t lNumKerningPairs; + uint32_t lNumTextures; + }; + RE_VERIFY_SIZE(SFontData, 0x18); + class ZTTFONT : public ZFONT { public: - // vftable - // custom api + // vtbl (no changes) + // methods static ZTTFONT* Create(); // data (size is 0x98, base size is 0x88) - int m_field88; - int m_field8C; - int m_field90; - int m_field94; + uint32_t m_iDataHandle; + SFontData* m_pFontData; + SGlyph* m_pGlyphData; + void* m_pKerningTable; }; + RE_VERIFY_SIZE(ZTTFONT, 0x98); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZWINOBJ.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZWINOBJ.h index b549997..4354ac2 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZWINOBJ.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZWINOBJ.h @@ -1,14 +1,25 @@ #pragma once +#include #include #include #include +#include namespace Hitman::BloodMoney { - using SPRITETYPE = int; + enum SPRITETYPE : int + { + SPRITETYPE_ARRAY = 0x1, + SPRITETYPE_ARRAY_BOX = 0x3, + SPRITETYPE_ARRAY_BOX_SCALE = 0x4, + SPRITETYPE_ARRAY_UV = 0x5, + SPRITETYPE_ARRAY_RAW = 0x6, + SPRITETYPE_ARRAY_PARTICLE = 0x7, + }; - class ZWINOBJ : public Glacier::ZSTDOBJ { + class ZWINOBJ : public Glacier::ZSTDOBJ + { public: // vftable virtual void CreateSpriteArray(uint32_t, uint32_t, SPRITETYPE); @@ -21,16 +32,6 @@ namespace Hitman::BloodMoney virtual void RemoveGeometry(); virtual void LoadSaveGeometry(Glacier::ZPackedInput*, bool); virtual void SetDrawMode(uint32_t, int); - /** - * a2 table: - * 1 -> 0x16C012; - * 2 -> fault - * 3: -> 0x16C011; - * 4 -> fault - * 5 -> 0x16C210 - * 6 -> 0x16C211 - * other -> 0x16C010 - */ virtual int32_t CalcDrawMode(int a2, int a3); virtual void SetDrawing(); virtual void SetColor(uint32_t, bool); @@ -49,35 +50,27 @@ namespace Hitman::BloodMoney int GetTexture(unsigned int iTextureType); // data (total size is 0x88, base size is 0x10) - int m_field10; //+0x10 - int m_field14; //+0x14 - int m_field18; //+0x18 - int m_field1C; //+0x1C - int m_field20; //+0x20 - int m_field24; //+0x24 - int m_field28; //+0x28 - int m_field2C; //+0x2C - int m_field30; //+0x30 - int m_field34; //+0x34 - int m_field38; //+0x38 - int m_field3C; //+0x3C - int m_field40; //+0x40 - int m_field44; //+0x44 - int m_field48; //+0x48 - int m_field4C; //+0x4C - int m_field50; //+0x50 - int m_field54; //+0x54 - int m_field58; //+0x58 - int m_field5C; //+0x5C - int m_field60; //+0x60 - int m_field64; //+0x64 - int m_field68; //+0x68 - int m_field6C; //+0x6C - int m_field70; //+0x70 - int m_field74; //+0x74 - int m_field78; //+0x78 - int m_field7C; //+0x7C - int m_field80; //+0x80 - int m_field84; //+0x84 - }; + unsigned int m_dwFaceColor; + unsigned int m_dwDrawMode; + Glacier::ZVector2 m_v2Scale; + Glacier::SSpriteArrayElementUV *m_pSprites; + uint16_t m_iNumSprites; + uint16_t m_iNumSpriteArrays; + unsigned int *m_pPrims; + Glacier::SSpriteArray *m_pSpriteArrays; + Glacier::ZVector2 m_vAlignmentOffset; + Glacier::ZVector3 m_vLastCamPos; + Glacier::ZMat3x3 m_mCache; + Glacier::ZVector3 m_vCache; + Glacier::ZVector3 m_vCacheScale; + uint8_t m_dwAlignment; + uint8_t m_dwType; + uint8_t m_dwAmount; + uint8_t m_iPriority; + bool m_bModified; + bool m_bStaticSprites; + bool m_bAnimateAlpha; + bool m_bScalePS2_512_448; + }; // Size is 0x88 (verified) + RE_VERIFY_SIZE(ZWINOBJ, 0x88); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZWINPIC.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZWINPIC.h new file mode 100644 index 0000000..250791c --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZWINPIC.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + class ZWINPIC : public ZWINOBJ + { + public: + // vtbl + virtual void SetUV(float, float, float, float); + virtual void Mirror(bool); + + // data + uint32_t m_iOriginalSizeX; + uint32_t m_iOriginalSizeY; + uint32_t m_dwModifications; + Glacier::ZVector4 m_v4UVModified; + }; + RE_VERIFY_SIZE(ZWINPIC, 0xA4); +} diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZWinInput.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZWinInput.h index 07718da..6264612 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZWinInput.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZWinInput.h @@ -1,77 +1,63 @@ #pragma once +#include +#include + + namespace Hitman::BloodMoney { class ZWINDOWS; - namespace Action + struct SWinKey { - struct ZHandle - { - const char *hotkey; - int m_field4; - int m_field8; - }; - } + Glacier::ZHandle* pHandle; + uint32_t dwPrevState; + }; + RE_VERIFY_SIZE(SWinKey, 0x8); + + struct SAnalogKey { + // Size: 0x1c (28) bytes + + Glacier::ZHandle* pHandle; + float fActivationTime; + float fRepeatTime; + eZWUserEvents eHighEvent; + eZWUserEvents eLowEvent; + bool bSentEventLastFrame; + eZWUserEvents eLastEvent; + }; + // TODO: ^^^ Need verify size of this struct ^^^ class ZWinInput { public: - ZWINDOWS* m_parent; - Action::ZHandle m_downAction; - Action::ZHandle m_upAction; - Action::ZHandle m_leftAction; - Action::ZHandle m_rightAction; - Action::ZHandle m_selectAction; - Action::ZHandle m_select2Action; - Action::ZHandle m_select3Action; - Action::ZHandle m_select4Action; - Action::ZHandle m_cancelAction; - Action::ZHandle m_misc1Action; - Action::ZHandle m_mouseButtonAction; - Action::ZHandle m_leftMouseButtonAction; - Action::ZHandle m_rightMouseButtonAction; - Action::ZHandle m_mouseWheelUpAction; - Action::ZHandle m_mouseWheelDownAction; - Action::ZHandle m_startAction; - Action::ZHandle m_z1Action; - Action::ZHandle m_r1Action; - int field_dc; - int field_e0; - int field_e4; - int field_e8; - int field_ec; - int field_f0; - int field_f4; - int field_f8; - int field_fc; - int field_100; - int field_104; - int field_108; - int field_10c; - int field_110; - int field_114; - int field_118; - int field_11c; - int field_120; - int field_124; - int field_128; - int field_12c; - int field_130; - int field_134; - int field_138; - int field_13c; - int field_140; - int field_144; - int field_148; - int field_14c; - int field_150; - int field_154; - int field_158; - int field_15c; - int field_160; - int field_164; - int field_168; - int field_16c; + // vtbl + // data + ZWINDOWS* m_pWindows; + Glacier::ZHandle m_Down; + Glacier::ZHandle m_Up; + Glacier::ZHandle m_Left; + Glacier::ZHandle m_Right; + Glacier::ZHandle m_Select; + Glacier::ZHandle m_Select2; + Glacier::ZHandle m_Select3; + Glacier::ZHandle m_Select4; + Glacier::ZHandle m_Cancel; + Glacier::ZHandle m_Misc1; + Glacier::ZHandle m_MButton; + Glacier::ZHandle m_LButton; + Glacier::ZHandle m_RButton; + Glacier::ZHandle m_MWheelUp; + Glacier::ZHandle m_MWheelDown; + Glacier::ZHandle m_Start; + Glacier::ZHandle m_L1; + Glacier::ZHandle m_R1; + SWinKey m_aKeys[18]; + bool m_bKeyboardBinded; + bool m_bInputHandlerInstalled; + Glacier::ZHandle m_AnalogHorizontal; + Glacier::ZHandle m_AnalogVertical; + SAnalogKey m_aAnalogKeys[2]; }; + // TODO: ^^^ Need verify size and check code ^^^ } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZXMLGUISystem.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZXMLGUISystem.h index c8c2e4c..cce0b01 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZXMLGUISystem.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/ZXMLGUISystem.h @@ -4,23 +4,189 @@ #include #include #include +#include +#include +#include #include #include +namespace Glacier +{ + class ZCAMERA; + class ZGROUP; + class ZGEOM; + struct IView; +} + namespace Hitman::BloodMoney { + class ZWINGROUP; + class ZFRAME; + class ZTTFONT; + class ZMenuElements; + struct IGUIElement; + struct IWindowInterface; + + struct SMenuLayer + { + ZWINGROUP* pParent; + Glacier::ZStaticVector vReceiveAllInput; + ZFRAME* pOverlayFrame; + }; + RE_VERIFY_SIZE(SMenuLayer, 0x4C); // Verified + + struct ZMapping + { + bool m_bFlip; + bool m_bMirror; + bool m_bRunWhenPause; + float m_fCurVal; + float m_fDstVal; + float m_fStartVal; + Glacier::TIMETYPE m_StartTime; + Glacier::TIMETYPE m_TimeInterval; + + virtual float MapFunction(); + }; + RE_VERIFY_SIZE(ZMapping, 0x1C); + + struct ZEaseIn : public ZMapping + { + int32_t m_iPolyDegree; + }; + RE_VERIFY_SIZE(ZEaseIn, 0x20); + + struct ZMenu3DCam + { + enum EState + { + eANIMATE_OUT = 0, + ANIMATE_IN = 1, + ANIMATE_IN2 = 2, + IDLE = 3, + JOYSTICK = 4 + }; + + // Size: 0xac (172) bytes + Glacier::ZCAMERA* m_pCamera; + Glacier::IView* m_pIView; + Glacier::ZGEOM* m_pGeom; + Glacier::TIMETYPE m_LastActualTime; + bool m_bReserved; + ZEaseIn m_AnimateAngleY; + ZEaseIn m_AnimateAngleZ; + ZEaseIn m_AnimateCamPos; + EState m_eState; + Glacier::TIMETYPE m_LastJoystickMove; + Glacier::ZGROUP* m_pReleaseGroup; + Glacier::ZGEOM* m_pNextGeom; + float m_fDefaultCamPosX; + Glacier::ZMat3x3 m_DefaultMat; + }; + RE_VERIFY_SIZE(ZMenu3DCam, 0xAC); + + struct ZResourceManager + { + ZWINGROUP* m_pWinGroupLineObjs; + ZWINGROUP* m_pWinGroupButtons; + ZWINGROUP* m_pWinGroupSlider; + ZWINGROUP* m_pWinGroupGroups; + ZWINGROUP* m_pWinGroupGraphic; + ZWINGROUP* m_pWinGroupButtonGraphic; + ZWINGROUP* m_pWinGroupFrames; + ZWINGROUP* m_pWinGroupBackground; + ZTTFONT* m_pFonts[3]; + ZMenu3DCam m_aMenu3DCam[4]; // Count approved by ZResourceManager::CreateMenu3DViews (while loop) + }; + RE_VERIFY_SIZE(ZResourceManager, 0x2DC); + + struct SOpenWindowParams + { + // Size: 0x14 (20) bytes + bool bOpenWindow; + Glacier::zstring sWindow; + bool bPushOnStack; + bool bResetStack; + }; + + struct SCloseWindowParams + { + // Size: 0x2 (2) bytes + bool bCloseWindow; + bool bCloseAll; + }; + + struct SRollBackParams + { + // Size: 0x20 (32) bytes + bool bRollBack; + Glacier::zstring sWindow; + Glacier::zstring sPushWindow; + bool bKeepRollbackWindow; + }; + + class ZXMLGUISystem : public CWinEvent { public: - int m_field30; //0x0030 - Glacier::ZGROUP* m_windowGroups[18]; //0x0034 - - /// vftable + // types + enum EMenuLayer + { + EMENU = 0, + EDIALOG = 1, + ETRC = 2, + NUM_OF_LAYERS = 3, + }; + + // vtbl virtual void SetFocus(); virtual void AddOtherWindowCount(int); // api ZWINDOW* GetTopWindow(); + + // data + bool m_bUnpauseGame; // +0x30 + ZWINGROUP* m_pWinGroupResources; // +0x34 + Glacier::ZGROUP* m_pGroupFonts; // +0x38 + ZResourceManager m_ResourceManager; // +0x3c + int32_t m_iLastFocusedElement; // +0x318 + int32_t m_iNumOfWindows; // +0x31c + int32_t m_iNumOtherWindows; // +0x320 + IWindowInterface* m_apWindowStack[32]; // +0x324 + int32_t m_aLastIndex[32]; // +0x3a4 + ZWINGROUP* m_pWinGroupHeader; // +0x424 + ZMenuElements* m_pMenuElements; // +0x428 + int32_t m_iPlayerActivatedMenu; // +0x42c + bool m_bInsideUpdate; // +0x430 + bool m_bCloseSystem; // +0x431 + bool m_bGot3dBackground; // +0x432 + bool m_bAddBackgroundCamAnd3DCams; // +0x433 + Glacier::ZCAMERA* m_pBackgroundCam; // +0x434 + Glacier::ZCAMERA* m_pMenuCam; // +0x438 + Glacier::ZCAMERA* m_pDialogCam; // +0x43c + Glacier::ZCAMERA* m_pTRCCam; // +0x440 + SOpenWindowParams m_OpenWindowParams; // +0x444 + SCloseWindowParams m_CloseWindowParams; // +0x458 + SRollBackParams m_RollBackParams; // +0x45c + SMenuLayer m_aMenuLayer[3]; // +0x47c + EMenuLayer m_eCurrentLayer; // +0x560 + bool m_bWindowPush; // +0x564 + bool m_bRollBack; // +0x565 + RE_ADD_PADDING(4); // Idk what's happening here + IWindowInterface* m_apTRCWindows[4]; // +0x56C + int m_iNumOfTRCWindows; // +0x57C }; + RE_VERIFY_SIZE(ZXMLGUISystem, 0x580); // Verified + RE_VERIFY_OFFSET(ZXMLGUISystem, m_bUnpauseGame, 0x30); + RE_VERIFY_OFFSET(ZXMLGUISystem, m_ResourceManager, 0x3C); // Verified by ZXMLGUISystem::ZXMLGUISystem + RE_VERIFY_OFFSET(ZXMLGUISystem, m_iNumOfWindows, 0x31C); // Verified by ZXMLGUISystem::GetTopWindow + RE_VERIFY_OFFSET(ZXMLGUISystem, m_iNumOtherWindows, 0x320); // Verified by ZXMLGUISystem::AddOtherWindowCount + RE_VERIFY_OFFSET(ZXMLGUISystem, m_apWindowStack, 0x324); // Verified by ZXMLGUISystem::IsOnStack + RE_VERIFY_OFFSET(ZXMLGUISystem, m_pMenuElements, 0x428); // Verified by ZXMLGUISystem::ZXMLGUISystem + RE_VERIFY_OFFSET(ZXMLGUISystem, m_bAddBackgroundCamAnd3DCams, 0x433); // Verified by ZXMLGUISystem::Command ("CreateViews" command impl) + RE_VERIFY_OFFSET(ZXMLGUISystem, m_pTRCCam, 0x440); // Verified by ZXMLGUISystem::SetupCameras + RE_VERIFY_OFFSET(ZXMLGUISystem, m_apTRCWindows, 0x56C); // Verified by ZXMLGUISystem::IsOnStack + RE_VERIFY_OFFSET(ZXMLGUISystem, m_iNumOfTRCWindows, 0x57C); // Verified by ZXMLGUISystem::IsOnStack } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/eZWUserEvents.h b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/eZWUserEvents.h index c42a438..5f31bc6 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/UI/eZWUserEvents.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/UI/eZWUserEvents.h @@ -1,5 +1,28 @@ #pragma once -namespace Hitman::BloodMoney { - enum class eZWUserEvents; +namespace Hitman::BloodMoney +{ + enum eZWUserEvents + { + eZW_FIRST = 123, + eZW_DOWN = 123, + eZW_UP = 124, + eZW_LEFT = 125, + eZW_RIGHT = 126, + eZW_SELECT = 127, + eZW_SELECT2 = 128, + eZW_SELECT3 = 129, + eZW_SELECT4 = 130, + eZW_START = 131, + eZW_L1 = 132, + eZW_R1 = 133, + eZW_CANCEL = 134, + eZW_MISC1 = 135, + eZW_LBUTTON = 136, + eZW_RBUTTON = 137, + eZW_MBUTTON = 138, + eZW_MWHEELUP = 139, + eZW_MWHEELDOWN = 140, + eZW_CUSTOM_COUNT = 18, + }; } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZActor.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZActor.h index cf54060..76d8742 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZActor.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZActor.h @@ -2,28 +2,158 @@ #include #include +#include +#include +#include #include namespace Hitman::BloodMoney { + enum ELocomotionState { + LOCOSTATE_DISABLED = 0, + LOCOSTATE_STAND = 1, + LOCOSTATE_ACTIVEANIM = 2, + LOCOSTATE_MANUALANIM = 3, + LOCOSTATE_MOVEFORWARD = 4 + }; + + struct ZLocomotionState + { + Glacier::ZVector2 m_ActiveAnimPostTransitionDir; + struct ZTransition* m_CurrentTransition; + struct TAnimHeader* m_CurrentAnim; + Glacier::Animation::ActiveAnimation* m_ActiveAnim; + Glacier::PF4::ZMetaNode* m_LookAtTarget; + float m_LastDistanceToMotionChange; + float m_BlendOutAtFramePct; + float m_BlendOutToFramePct; + float m_BlendFrames; + float m_LastFramePrc; + float m_ExpectedMoveStopDist; + float m_ShortestMoveStopDist; + float m_MoveCycleCorrectionSpeed; + int8_t m_MoveSetNr; + int8_t m_PreferredState; + int8_t m_LastPreferredState; + int8_t m_LookMode; + int8_t m_LocomotionSetEntry; + int8_t m_LocomotionSetTransition; + int8_t m_CurrentTransitionSub; + + struct { + ELocomotionState m_State : 4; + ELocomotionState m_NextState : 4; + unsigned int m_CurrentAnimMirrored : 1; + unsigned int m_UseGroundAnimFully : 1; + unsigned int m_InControlThisFrame : 1; + unsigned int m_OffScreenLastFrame : 1; + unsigned int m_AbortTransitionOnDistanceGrow : 1; + unsigned int m_PerformQuickStart : 1; + unsigned int m_LookAtEnabled : 1; + unsigned int m_TurnToEndDir : 1; + unsigned int m_CycleCorrectionAllowPct0 : 1; + unsigned int m_CycleCorrectionAllowPct50 : 1; + }; + + // Idk, weird pad or missing data? + uint8_t pad_3F8[4]; + }; + RE_VERIFY_SIZE(ZLocomotionState, 0x48); + + struct ProgramQueEntry + { + uint8_t m_StartIndex; + uint8_t m_EndIndex; + int8_t m_Program; + int8_t m_PathAction; + }; + RE_VERIFY_SIZE(ProgramQueEntry, 0x4); + + struct ZSetBindings + { + float m_VariationSeed; + int32_t m_VariationMask; + float m_MoveSpeed; + float m_PreferredSpeed; + float m_MaxSpeed; + float m_Speed[10]; + float m_PhaseShift[10]; + float m_LongestStoppingDistance; + float m_Distance[20]; + float m_TransitionRotation[20]; + Glacier::ZVector2 m_TransitionEndDirection[20]; + float m_BlendInFromPhase[20]; + float m_BlendOutToPhase[20]; + float m_QuickStartFramePct[20]; + float m_EndFramePct[20]; + }; + RE_VERIFY_SIZE(ZSetBindings, 0x2E8); + + struct LocomotionInfo + { + float fDeltaTime; + int stateChangeCount; + bool allowActiveAnims; + bool allowActiveAnimsBase; + bool beingPushed; + float currentSpeed; + Glacier::ZVector2 currentDir; + Glacier::ZVector2 currentAcc; + float wantedSpeed; + Glacier::ZVector2 wantedDir; + float nextSpeed; + Glacier::ZVector2 nextDir; + float distanceToMotionChange; + bool directLineToWaypoint; + int stairsMode; + Glacier::ZVector3 actorPos; + Glacier::ZMat3x3 actorMat; + Glacier::ZVector2 actorDir; + Glacier::ZVector2 dirToTarget; + struct ZSet* locomotionSet; + ELocomotionState m_SwitchedFromState; + float secondsToTransfer; + float animationSpeedMultiplier; + float rotationModifier; + bool skipFramePctIncrease; + }; + RE_VERIFY_SIZE(LocomotionInfo, 0x9C); + class ZActor : public Glacier::ZLNKWHANDS { public: // pub - enum ACTORSTATE + enum ACTORSTATE : int8_t + { + ACTORSTATE_DEAD = 0, + ACTORSTATE_AWAKE = 1, + ACTORSTATE_UNCONSCIOUS = 2, + ACTORSTATE_SLEEPING = 3, + }; + + enum PATH_CANCEL_REASONS : int8_t { - STATE_0 = 0, - STATE_1 = 1, - STATE_2 = 2, - STATE_3 =3 + eNONE = 0, + eANIMATION = 1, + eMOVED_TO_POS = 2, + eREQUEST = 3, + eUNSPECIFIED = 4, }; - enum PATH_CANCEL_REASONS + enum PATHDONEFLAG : int8_t { + PATH_RESERVED = 0, + PATH_FINISHED = 1, + PATH_CANCELED = 2, + PATH_CANCELED_LOCKED_DOOR = 3, + PATH_ERROR = 4, }; enum PATH_ERRORS { + NO_PATH = 0, + EXEEDED_STOP_DIST = 1, + EXEEDED_MAX_LEN = 2, }; static constexpr Glacier::ZMSGID kAlarmMsg = 0x81A; @@ -101,343 +231,99 @@ namespace Hitman::BloodMoney // Total size is 0x900, base size is 0x3D0) Glacier::Vector3 m_ContactNormal; - int m_field3DC; - int m_field3E0; - int m_field3E4; - int m_field3E8; - int m_field3EC; - int m_field3F0; - Glacier::ZHumanBoid* m_boid; - int m_field3F8; - int m_field3FC; - int m_field400; - int m_field404; - int m_field408; - int m_field40C; - int m_field410; - int m_field414; - int m_field418; - int m_field41C; - int m_field420; - int m_field424; - int m_field428; - int m_field42C; - int m_field430; - int m_field434; - int m_field438; - int m_field43C; - int m_field440; - int m_field444; - int m_field448; - int m_field44C; - int m_field450; - int m_field454; - int m_field458; - int m_field45C; - int m_field460; - int m_field464; - int m_field468; - int m_field46C; - int m_field470; - int m_field474; - int m_field478; - int m_field47C; - bool m_MoveSetNr; - bool m_PreferredState; - bool m_LastPreferredState; - bool field_B3; - int m_field484; - int m_field488; - int m_field48C; + Glacier::Vector3 m_LastShootIntoGroundPosition; + float m_LastShootIntoGroundHeight; + float m_InterpolatedHeightError; + Glacier::ZREF m_rHero; + Glacier::ZHumanBoid* m_pkBoid; + Glacier::PF4::ZMetaNode m_Entity; + Glacier::PF4::ZMetaNode m_Reservation; + ZLocomotionState m_Locomotion; uint16_t m_iQuePos; uint16_t m_iProgramQueSize; - int m_field494; - int m_field498; - int m_field49C; - int m_field4A0; - int m_field4A4; - int m_field4A8; - int m_field4AC; - int m_field4B0; - int m_field4B4; - int m_field4B8; - int m_field4BC; - int m_field4C0; - int m_field4C4; - int m_field4C8; - int m_field4CC; - int m_field4D0; - int m_field4D4; - int m_field4D8; - int m_field4DC; - int m_field4E0; - int m_field4E4; - int m_field4E8; - int m_field4EC; - int m_field4F0; - int m_field4F4; - int m_field4F8; - int m_field4FC; - int m_field500; - int m_field504; - int m_field508; - int m_field50C; - int m_field510; - int m_field514; - int m_field518; - int m_field51C; - int m_field520; - int m_field524; - int m_field528; - int m_field52C; - int m_field530; - int m_field534; - int m_field538; - int m_field53C; - int m_field540; - int m_field544; - int m_field548; - int m_field54C; - int m_field550; - int m_field554; - int m_field558; - int m_field55C; - int m_field560; - int m_field564; - int m_field568; - int m_field56C; - int m_pPathFinder; - int m_field574; - int m_field578; - bool m_Action0; - bool m_Action1; - bool m_iEndAction; - bool field_1AF; - int m_iNextPathTarget; - int m_field584; - int m_field588; - int m_iPathfinderDoorKeyMask; - int m_field590; - int m_field594; - int m_field598; - int m_field59C; - int m_field5A0; - int m_field5A4; - int m_field5A8; - int m_field5AC; + ProgramQueEntry m_ProgramQue[40]; + Glacier::PF4::ZPath m_Path; + int8_t m_Action[2]; + int8_t m_iEndAction; + RE_ADD_PADDING(1); + int16_t m_iNextPathTarget; + RE_ADD_PADDING(2); + Glacier::REFTAB* m_pAudibleRoomList; + float m_fOldFootStepFrame; + uint32_t m_iPathfinderDoorKeyMask; + Glacier::ZVector3 m_vInitialPos; + Glacier::ZVector3 m_vInitialDir; + uint32_t m_lInsideView; + Glacier::ZREF m_rHeadTarget; float m_fMoveSpeedMultiplier; - int m_field5B4; - int m_field5B8; - Glacier::Vector3 m_vEndDir; - Glacier::Vector3 m_vEndPos; + float m_FrameTimeAccumulator; + float m_FrameTimeAccumulatorBound; + Glacier::ZVector3 m_vEndDir; + Glacier::ZVector3 m_vEndPos; float m_fEndDist; float m_fPathNotify; float m_fPathNotifyNext; - bool m_lPathDoneFlag; - bool m_ePathCancelReason; - bool m_actorState; - bool field_213; - int m_VariationSeed; - int m_VariationMask; - int m_field5EC; - int m_field5F0; - int m_field5F4; - int m_field5F8; - int m_field5FC; - int m_field600; - int m_field604; - int m_field608; - int m_field60C; - int m_field610; - int m_field614; - int m_field618; - int m_field61C; - int m_field620; - int m_field624; - int m_field628; - int m_field62C; - int m_field630; - int m_field634; - int m_field638; - int m_field63C; - int m_field640; - int m_field644; - int m_field648; - int m_field64C; - int m_field650; - int m_field654; - int m_field658; - int m_field65C; - int m_field660; - int m_field664; - int m_field668; - int m_field66C; - int m_field670; - int m_field674; - int m_field678; - int m_field67C; - int m_field680; - int m_field684; - int m_field688; - int m_field68C; - int m_field690; - int m_field694; - int m_field698; - int m_field69C; - int m_field6A0; - int m_field6A4; - int m_field6A8; - int m_field6AC; - int m_field6B0; - int m_field6B4; - int m_field6B8; - int m_field6BC; - int m_field6C0; - int m_field6C4; - int m_field6C8; - int m_field6CC; - int m_field6D0; - int m_field6D4; - int m_field6D8; - int m_field6DC; - int m_field6E0; - int m_field6E4; - int m_field6E8; - int m_field6EC; - int m_field6F0; - int m_field6F4; - int m_field6F8; - int m_field6FC; - int m_field700; - int m_field704; - int m_field708; - int m_field70C; - int m_field710; - int m_field714; - int m_field718; - int m_field71C; - int m_field720; - int m_field724; - int m_field728; - int m_field72C; - int m_field730; - int m_field734; - int m_field738; - int m_field73C; - int m_field740; - int m_field744; - int m_field748; - int m_field74C; - int m_field750; - int m_field754; - int m_field758; - int m_field75C; - int m_field760; - int m_field764; - int m_field768; - int m_field76C; - int m_field770; - int m_field774; - int m_field778; - int m_field77C; - int m_field780; - int m_field784; - int m_field788; - int m_field78C; - int m_field790; - int m_field794; - int m_field798; - int m_field79C; - int m_field7A0; - int m_field7A4; - int m_field7A8; - int m_field7AC; - int m_field7B0; - int m_field7B4; - int m_field7B8; - int m_field7BC; - int m_field7C0; - int m_field7C4; - int m_field7C8; - int m_field7CC; - int m_field7D0; - int m_field7D4; - int m_field7D8; - int m_field7DC; - int m_field7E0; - int m_field7E4; - int m_field7E8; - int m_field7EC; - int m_field7F0; - int m_field7F4; - int m_field7F8; - int m_field7FC; - int m_field800; - int m_field804; - int m_field808; - int m_field80C; - int m_field810; - int m_field814; - int m_field818; - int m_field81C; - int m_field820; - int m_field824; - int m_field828; - int m_field82C; - int m_field830; - int m_field834; - int m_field838; - int m_field83C; - int m_field840; - int m_field844; - int m_field848; - int m_field84C; - int m_field850; - int m_field854; - int m_field858; - int m_field85C; - int m_field860; - int m_field864; - int m_field868; - int m_field86C; - int m_field870; - int m_field874; - int m_field878; - int m_field87C; - int m_field880; - int m_field884; - int m_field888; - int m_field88C; - int m_field890; - int m_field894; - int m_field898; - int m_field89C; - int m_field8A0; - int m_field8A4; - int m_field8A8; - int m_field8AC; - int m_field8B0; - int m_field8B4; - int m_field8B8; - int m_field8BC; - int m_field8C0; - int m_field8C4; - int m_field8C8; - int m_field8CC; - int m_field8D0; - int m_field8D4; - bool m_field8D8; - bool m_field8D9; - bool m_field8DA; - bool m_field8DB; - int m_field8DC; - int m_lShootIntoGroundFlag; - int m_field8E4; - int m_animCurrent; // +0x8E8 - int m_field8EC; - int m_field8F0; - int m_field8F4; - int m_field8F8; - int m_field8FC; - }; + PATHDONEFLAG m_lPathDoneFlag; + PATH_CANCEL_REASONS m_ePathCancelReason; + ACTORSTATE m_ActorState; + RE_ADD_PADDING(1); + ZSetBindings m_MoveSetBindings; + float m_fCurrentBaseMoveFramePrc; + float m_fCurrentBaseMoveDuration; + float m_Banking; + + union { + unsigned int m_Mask1; + struct { + unsigned int m_bShootIntoGround : 1; + unsigned int m_bShootIntoGroundFailed : 1; + unsigned int m_bShootIntoGroundInFullbody : 1; + unsigned int m_bShootIntoDynamic : 1; + unsigned int m_bShootIntoGroundAlways : 1; + unsigned int m_bPathRequest : 1; + unsigned int m_bPathNotifySyncToCycle : 1; + unsigned int m_bPathFinderEnabled : 1; + unsigned int m_bUseEndDir : 1; + unsigned int m_bStayInsidePath : 1; + unsigned int m_bMoveBackward : 1; + unsigned int m_bDisableIdleAnimation : 1; + unsigned int m_bWounded : 1; + unsigned int m_bPositionLock : 1; + unsigned int m_bDontStop : 1; + unsigned int m_bEnableLookAt : 1; + unsigned int m_bPathDone : 1; + unsigned int m_bIgnoreReservations : 1; + unsigned int m_bUpdatePosition : 1; + unsigned int m_bIsSeeing : 1; + unsigned int m_bIsVisible : 1; + unsigned int m_bScriptUBAnimLoop : 1; + unsigned int m_bScriptUBAnimMirrored : 1; + unsigned int m_bPathNotifyMsgSent : 1; + unsigned int m_bPathDoneMsgSent : 1; + unsigned int m_bCancelPathWhenPossible : 1; + unsigned int m_bPerformedFullUpdateLastFrame : 1; + unsigned int m_bForceOnScreen : 1; + unsigned int m_bIsScared : 1; + }; + }; + + // Смещение 17504 (0x0690) - m_Mask2 и Битовые поля + union { + unsigned int m_Mask2; + struct { + unsigned char m_bScriptPaused : 1; + unsigned char m_bStopMovement : 1; + }; + }; + + uint32_t m_lShootIntoGroundFlag; + Glacier::ZREF m_rActorList; + Glacier::Animation::Header* m_pAnimUBHoldRifle; + float m_fRunDustDist; + Glacier::Animation::Header* m_pScriptUBAnimToPlay; + float m_fScriptUBAnimToPlayPrct; + int32_t m_nCurrentScriptUBAnimID; + float m_fScriptUBAnimPitch; + }; // Verified size 0x900 + RE_VERIFY_SIZE(ZActor, 0x900); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZCheatMenu.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZCheatMenu.h index 802a5f5..a053fa5 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZCheatMenu.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZCheatMenu.h @@ -1,59 +1,58 @@ #pragma once -#include -#include +#include #include +#include +#include namespace Hitman::BloodMoney { - class ZCheatMenu : public Glacier::ZEventBase - { - public: - //custom entries - enum ECheatMenuEntryType : int - { - MENU_GENERIC_INTVAL_TOGGLE = 0x0, // Int value, 0 or 1 (toggle mode) - MENU_GENERIC_FLOAT_TOGGLE = 0x1, // Float value 0.0f or 1.0f (toggle mode) - MENU_GENERIC_FLOAT_EDITABLE = 0x2, // Float value, inc 0.1f - MENU_GENERIC_FLOAT_READ_ONLY = 0x3, // Float value, read only - MENU_TOGGLE_CALLABLE_OPTION = 0x4, // pDataPtr should be a pointer to the function - MENU_TOGGLE_OPTION_2 = 0x5, // I'm not sure that this option works - MENU_ENGINE_DATABASE_FLOAT_B28 = 0x8, // Always ptr to ZEngineDatabase::m_fTimeMultiplier value! - MENU_TOGGLE_BOOL = 0x7, // Bool value - }; + class ZFRAME; + class ZCHAROBJ; - union UEntryOption { - void(__cdecl *pFunction)(void); - int* pInt; - float* pFloat; - bool* pBool; - }; + enum ECheatType + { + ct_btoggle = 0, + ct_ftoggle = 1, + ct_fvalue = 2, + ct_fivalue = 3, + ct_oneshot = 4, + ct_console = 5, // PS2 only ; Maybe in Hitman Contracts still in use? + ct_ivalue = 6, + ct_uvartoggle = 7, + ct_timemult = 8, + }; - struct SEntry + class ZCheatMenu : public CMenuWindow + { + public: + //types + struct SCheat { - ECheatMenuEntryType eType; - const char* pName; - UEntryOption uOption; + ECheatType eCheatType; + const char* szDisplayName; + union + { + const char* szCommand; + float* pFloat; + bool* pBool; + int32_t* pInt; + void* pUvarInt; + void (__cdecl* pFn)(); + uint32_t _Dummy; + }; }; + RE_VERIFY_SIZE(SCheat, 0xC); - //vftable (no changes) - + //vtbl (no changes) //data (total size is 0x78, base size is 0x30) - int m_field30; - int m_field34; - int m_field38; - int m_field3C; - char field_40; - char field_41; - char field_42; - char field_43; - ZCHAROBJ* m_pTextObj; - void *field_48; - void *field_4C; - void *field_50; - __int16 m_MSG_ShowCheatsMenu; - __int16 field_56; - void *field_58; - Glacier::REFTAB m_options; + ZCHAROBJ* m_pText; + ZFRAME* m_pFrame1; + ZFRAME* m_pFrame2; + int32_t m_iSelected; + Glacier::ZMSGID m_msgOpen; + int32_t m_iExitCountdown; + Glacier::REFTAB m_rtCommands; }; + RE_VERIFY_SIZE(ZCheatMenu, 0x78); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZCloth.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZCloth.h index b291fc5..ce67e62 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZCloth.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZCloth.h @@ -1,28 +1,54 @@ #pragma once +#include #include + namespace Hitman::BloodMoney { + enum ActorCollisionType : uint32_t + { + NONE = 0, + HERO = 1, + ALL = 2 + }; + + enum WindType : uint32_t + { + NO = 0, + STATIC = 1, + PERLIN = 2, + MOVEMENTBASED = 3, + }; + + struct ClothConstraint + { + uint16_t ix1; + uint16_t ix2; + float m_fWeightedInvMassSum; + float m_fSquare; + float m_fDoubleSquare; + }; + RE_VERIFY_SIZE(ClothConstraint, 0x10); + + // UNFINISHED! Hard class, need debug code more carefuly. Will do later class ZCloth : public Glacier::ZSTDOBJ { public: // vftable virtual void HandleTensions(float *); - virtual void ClothInitialize(bool); + virtual void Initialize(bool); // Data (total size is 0xB0, ZSTDOBJ ends at 0xC) int field_10; int field_14; - int field_18; - int field_1C; - int field_20; - int field_24; - int field_28; - int field_2C; - int field_30; - int field_34; - int field_38; + ActorCollisionType m_iActorCollision; // +0x18 + WindType m_iUseWind; // +0x1C + int m_field20; + Glacier::ZVector3 m_WindSpeed; // +0x24 + float m_fElasticity; // +0x2C + float m_fGravity; + float m_fDamping; int field_3C; int field_40; int field_44; @@ -37,8 +63,10 @@ namespace Hitman::BloodMoney int field_68; int field_6C; int field_70; - int field_74; - int field_78; + + uint32_t m_lnrBoxes; + ZGEOM** m_pBoxes; + int field_7C; int field_80; int field_84; @@ -47,10 +75,12 @@ namespace Hitman::BloodMoney int field_90; int field_94; int field_98; - int field_9C; - int field_A0; - int field_A4; - int field_A8; - int field_AC; - }; + + Glacier::ZVector3 m_OldPosition; + float m_fSyncTimeStep; + void* m_pDataBlockPtr; + }; // Total size is 0xB0 + RE_VERIFY_SIZE(ZCloth, 0xB0); // Verified + RE_VERIFY_OFFSET(ZCloth, m_WindSpeed, 0x24); + RE_VERIFY_OFFSET(ZCloth, m_fElasticity, 0x30); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZClothTracker.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZClothTracker.h index 58bb84a..772d3f5 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZClothTracker.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZClothTracker.h @@ -1,36 +1,52 @@ #pragma once -#include +#include +#include +#include +#include -namespace Hitman::BloodMoney { - class ZClothTracker : public Glacier::ZEventBase +namespace Hitman::BloodMoney +{ + struct SClothInfo { - public: - //vftable (no changes) - //api - //static api - //data (total size is 0x88, base size is 0x30) - int m_field30; - int m_field34; - int m_field38; - int m_field3C; - int m_field40; - int m_field44; - int m_field48; - int m_field4C; - int m_field50; - int m_field54; - int m_field58; - int m_field5C; - int m_field60; - int m_field64; - float m_field68; - float m_field6C; - int m_field70; - int m_field74; - int m_field78; - int m_field7C; - int m_field80; - int m_field84; + Glacier::ZREF rHitmanAs; + float fDisguiseQuality; + bool bDisguiseBlown; + bool m_bPad[3]; }; + + struct SInspector + { + Glacier::ZREF rSeerActor; + float fQuality; + struct ZHM3ActorProperties* rt_pActorProperty; + unsigned char iClothIdx; + + union { + unsigned char mask; + struct { + unsigned char bInvestigating : 1; + unsigned char bKnownCloth : 1; + unsigned char bNotorietyBlowCover : 1; + }; + }; + RE_ADD_PADDING(2); + }; + + struct ZClothTracker : public Glacier::CBaseEvent + { + Glacier::ZArray m_Clothes; + Glacier::ZArray m_Inspectors; + + float m_fInspectTime; + float m_fDiffSpeedMult; + float m_fDiffForgetMult; + float m_fDiffSeeThroughDisguiseDistance; + + int m_iNotoriety; + float m_fNotorietySpeedMult; + float m_fNotorietyDistMult; + int m_iCurrInspectCloth; + }; + RE_VERIFY_SIZE(ZClothTracker, 0x88); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3Actor.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3Actor.h index 2ab5294..43612b4 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3Actor.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3Actor.h @@ -1,17 +1,20 @@ #pragma once +#include #include #include #include #include #include #include +#include #include #include namespace Hitman::BloodMoney { - enum EActorMapRole : int { + enum EActorMapRole : int + { Civilian = 0, Enemy = 1, VIP = 2, @@ -22,6 +25,33 @@ namespace Hitman::BloodMoney Default = Civilian }; + enum eCharacterType { + eCharacterType_Civilian = 0, + eCharacterType_Enemy = 1, + eCharacterType_VIP = 2, + eCharacterType_Target = 3, + eCharacterType_Animal = 4, + eCharacterType_Policeman = 5, + eCharacterType_OptionalTarget = 6, + }; + + enum eInterestLevel { + IL_Neutral = 0, + IL_Interesting = 1, + IL_Strange = 2, + IL_Suspicious = 3, + }; + + enum eActorElevatorState { + AE_NONE = 0, + AE_WAITING_FORELEVATOR = 1, + AE_MOVE_INSIDEELEVATOR = 2, + AE_INSIDE_ELEVATOR = 3, + AE_MOVE_OUTSIDEELEVATOR = 4, + }; + + + enum EBloodSpurtType { BloodSpurt = 0x0, @@ -31,6 +61,67 @@ namespace Hitman::BloodMoney BluntImpact = 0x4, }; + enum EActorBodyPosition : int + { + eNormal = 0, + eSittingDown = 1, + eSittingDownBar = 2, + eLyingDown = 3, + eUnknown = 4, + eSittingDownBed = 5, + }; + + enum class ESittingDetails : int + { + eNone = 0, + eLeft = 1, + eCenter = 2, + eRight = 3, + }; + + enum EActorSpecies : uint8_t + { + eHuman = 0, + eDog = 1, + eRat = 2, + eCorpse = 3, + eWheelChair = 4, + }; + + class ZHM3HmAs; + class ZHM3ItemWeapon; + + struct ZDecaying + { + float value; + float m_fTim; + float m_fMax; + float m_fMin; + }; + RE_VERIFY_SIZE(ZDecaying, 0x10); + + struct SBodyInfo + { + Glacier::ZGEOM* pBody; + int16_t oldpos[3]; + bool bNude; + }; + RE_VERIFY_SIZE(SBodyInfo, 0xC); + + struct sUseElevatorInfo + { + Glacier::ZREF rFrom; + Glacier::ZREF rTo; + Glacier::ZREF rElevator; + eActorElevatorState eAEState; + Glacier::ZVector3 vLinkEndPos; + Glacier::TIMETYPE tEndPosReqTime; + int nCellIdx; + bool bMoving; + RE_ADD_PADDING(3); + }; + RE_VERIFY_SIZE(sUseElevatorInfo, 0x28); + class ZHM3Actor : public ZActor { public: @@ -75,165 +166,316 @@ namespace Hitman::BloodMoney virtual void StoreUBHoldAnims(); virtual void MapUBHoldAnimsToIdx(); virtual void GetItemAssignedUBAnim(Glacier::ZItem*); - virtual void LoadSave(Glacier::ZPackedInput*); + virtual void LoadSave_2(Glacier::ZPackedInput*); // TODO: Make properly virtual void ActivateRigidBody(Glacier::SRigidBodyVelocity const*); // api void PreparePath(); void ActivateBloodSpurt(const Glacier::Vector3* pInvDir, const Glacier::Vector3* pCollisionPos, EBloodSpurtType type); + void InitMapIcon(bool); + + // types + struct UseDoorInfo + { + Glacier::ZGEOM* m_CurrentDoorGeom; + int m_LastDoorPing; + int m_LastDirectPathQuery; + float m_HasPausedSecs; + Glacier::ZVector3 m_DoorNormal; + + union + { + uint8_t m_LoadSaveMask; + struct + { + uint8_t m_bOpenDoorAnimStarted : 1; + uint8_t m_bDoorIsDouble : 1; + uint8_t m_iMoveThroughDirection : 1; + uint8_t m_bMovingThroughDoor : 1; + uint8_t m_iIsDoorOpen : 2; + }; + }; + }; + RE_VERIFY_SIZE(UseDoorInfo, 0x20); + + union HitmanInfo + { + uint16_t m_LoadSaveMask; + struct { + uint16_t m_bCheckIfHitmanIsArmed : 1; + uint16_t m_bHitManVisiblyArmed : 1; + uint16_t m_bPreFrameUpdateDie : 1; + uint16_t m_bHitmanRunningTooLong : 1; + uint16_t m_bHitmanStealthyTooLong : 1; + uint16_t m_bHitmanIsNear : 1; + uint16_t m_bHitmanIntrudedFriskBox : 1; + uint16_t m_bDressPropertyBloodyDress : 1; + uint16_t m_bCheckLockpickingHitman : 1; + uint16_t m_bHitmanVisiblyLockpicking : 1; + uint16_t m_IsHumanShield : 1; + uint16_t m_bBulletWentThroughMe : 1; + }; + }; + RE_VERIFY_SIZE(HitmanInfo, sizeof(uint16_t)); + + struct ExtraFlags + { + union + { + uint32_t loadSaveMask2; + struct + { + uint32_t m_iTimeToNextElevatorUpdate : 8; + uint32_t m_bDieWithoutRagdollOrAnim : 1; + uint32_t m_bDieWithoutRagdollOneshot : 1; + uint32_t m_bForceDisableDragAction : 1; + uint32_t m_bUpdateElevatorState : 1; + uint32_t m_bDoNotAddActorToVisionSystem : 1; + uint32_t m_bDoNotMoveHipOutOfGeometry : 1; + uint32_t m_bDisableRagdollForShots : 1; + uint32_t m_bDragActionShown : 1; + uint32_t m_bClothActionShown : 1; + uint32_t m_bInContainer : 1; + uint32_t m_bRigidBodyInUse : 1; + uint32_t m_iLookAtTime : 3; + uint32_t m_bIsHoldingShootableItemL : 1; + uint32_t m_bIsHoldingShootableItemR : 1; + uint32_t m_bWantBloodOnHit : 1; + }; + }; + }; + RE_VERIFY_SIZE(ExtraFlags, sizeof(uint32_t)); + + struct Flags + { + union { + unsigned int m_LoadSaveMask; + struct { + unsigned int m_bScriptUbAnimActive : 1; + unsigned int m_bBloodStainDropped : 1; + unsigned int m_bWearingClothes : 1; + unsigned int m_bTakeClothesActionActive : 1; + unsigned int m_bDrageActionActive : 1; + unsigned int m_bIsAutoaimTarget : 1; + unsigned int m_bLockUbAnim : 1; + unsigned int m_bMayDisable : 1; + unsigned int m_bBodyReported : 1; + unsigned int m_bUnconscious : 1; + unsigned int m_bWeaponCreated : 1; + unsigned int m_iRagdollAtNextFrame : 2; + unsigned int m_bUseUBRagdoll : 1; + unsigned int m_bRelayShootIntoGroundCB : 1; + unsigned int m_bUseRigidBodyOnPush : 1; + unsigned int m_bNearDeath : 1; + unsigned int m_bMayBeBodyBagged : 1; + unsigned int m_bIsBodyBag : 1; + unsigned int m_bIgnoreHelpRequest : 1; + unsigned int m_bHitmanVisible : 1; + unsigned int m_bIgnoreDisguise : 1; + unsigned int m_bIsInInterruptableState : 1; + unsigned int m_bLeaveBloodTrail : 1; + unsigned int m_bIsBeingKilled : 1; + unsigned int m_bAttachToElevator : 1; + unsigned int m_bDetachFromElevator : 1; + unsigned int m_bAccidentKilled : 1; + unsigned int m_bIsSearching : 1; + unsigned int m_bMovingRagdoll : 1; + unsigned int m_bCanOpenDoors : 1; + unsigned int m_bLastDamageWeaponOwnerIsHitman: 1; + }; + }; + }; + RE_VERIFY_SIZE(Flags, sizeof(uint32_t)); // data (total size is 0xB60, base size is 0x900) - EActorMapRole m_mapIconType; //+0x900 - Glacier::ZREF m_HmAs; //+0x904 - int m_field908; //+0x908 - int m_field90C; //+0x90C - int m_field910; //+0x910 - int m_field914; //+0x914 - int m_field918; //+0x918 - int m_field91C; //+0x91C - int m_field920; //+0x920 - int m_field924; //+0x924 - int m_field928; //+0x928 - int m_field92C; //+0x92C - int m_field930; //+0x930 - int m_field934; //+0x934 - int m_field938; //+0x938 - int m_field93C; //+0x93C - int m_field940; //+0x940 - int m_field944; //+0x944 - int m_field948; //+0x948 - int m_field94C; //+0x94C - int m_field950; //+0x950 - int m_field954; //+0x954 - int m_field958; //+0x958 - int m_field95C; //+0x95C - int m_field960; //+0x960 - int m_field964; //+0x964 - int m_field968; //+0x968 - int m_field96C; //+0x96C - int m_field970; //+0x970 - int m_field974; //+0x974 - int m_field978; //+0x978 - int m_field97C; //+0x97C - int m_field980; //+0x980 - int m_field984; //+0x984 - int m_field988; //+0x988 - int m_field98C; //+0x98C - int m_field990; //+0x990 - int m_field994; //+0x994 - int m_field998; //+0x998 - int m_field99C; //+0x99C - int m_field9A0; //+0x9A0 - int m_field9A4; //+0x9A4 - int m_field9A8; //+0x9A8 - int m_field9AC; //+0x9AC - int m_field9B0; //+0x9B0 - int m_field9B4; //+0x9B4 - int m_field9B8; //+0x9B8 - int m_field9BC; //+0x9BC - int m_field9C0; //+0x9C0 - int m_field9C4; //+0x9C4 - int m_field9C8; //+0x9C8 - int m_field9CC; //+0x9CC - int m_field9D0; //+0x9D0 - int m_field9D4; //+0x9D4 - int m_field9D8; //+0x9D8 - int m_field9DC; //+0x9DC - int m_field9E0; //+0x9E0 - int m_field9E4; //+0x9E4 - int m_field9E8; //+0x9E8 - int m_field9EC; //+0x9EC - int m_animHoldToolbox; //+0x9F0 - int m_animHoldBriefcase; //+0x9F4 - int m_field9F8; //+0x9F8 - int m_animHoldCoffee; //+0x9FC - int m_fieldA00; //+0xA00 - int m_fieldA04; //+0xA04 - int m_fieldA08; //+0xA08 - int m_animHoldBeer; //+0xA0C - int m_fieldA10; //+0xA10 - int m_fieldA14; //+0xA14 - int m_fieldA18; //+0xA18 - int m_fieldA1C; //+0xA1C - int m_fieldA20; //+0xA20 - int m_fieldA24; //+0xA24 - int m_fieldA28; //+0xA28 - int m_fieldA2C; //+0xA2C - int m_fieldA30; //+0xA30 - int m_fieldA34; //+0xA34 - int m_fieldA38; //+0xA38 - int m_fieldA3C; //+0xA3C - int m_fieldA40; //+0xA40 - int m_fieldA44; //+0xA44 - int m_fieldA48; //+0xA48 - int m_fieldA4C; //+0xA4C - int m_fieldA50; //+0xA50 - int m_fieldA54; //+0xA54 - int m_fieldA58; //+0xA58 - int m_fieldA5C; //+0xA5C - int m_fieldA60; //+0xA60 - int m_fieldA64; //+0xA64 - int m_fieldA68; //+0xA68 - int m_fieldA6C; //+0xA6C - int m_fieldA70; //+0xA70 - int m_fieldA74; //+0xA74 - int m_fieldA78; //+0xA78 - int m_fieldA7C; //+0xA7C - int m_fieldA80; //+0xA80 - int m_fieldA84; //+0xA84 - int m_fieldA88; //+0xA88 - int m_fieldA8C; //+0xA8C - int m_fieldA90; //+0xA90 - int m_fieldA94; //+0xA94 - int m_fieldA98; //+0xA98 - int m_fieldA9C; //+0xA9C - int m_fieldAA0; //+0xAA0 - int m_fieldAA4; //+0xAA4 - int m_fieldAA8; //+0xAA8 - int m_fieldAAC; //+0xAAC - int m_fieldAB0; //+0xAB0 - int m_fieldAB4; //+0xAB4 - int m_fieldAB8; //+0xAB8 - int m_fieldABC; //+0xABC - int m_fieldAC0; //+0xAC0 - int m_fieldAC4; //+0xAC4 - Glacier::ZROOM* m_room; // +0xAC8 - int m_fieldACC; //+0xACC - int m_fieldAD0; //+0xAD0 - int m_fieldAD4; //+0xAD4 - int32_t m_lastLogicUpdateTick; //+0xAD8 - int m_fieldADC; //+0xADC - int m_fieldAE0; //+0xAE0 - int m_fieldAE4; //+0xAE4 - int m_fieldAE8; //+0xAE8 - int m_fieldAEC; //+0xAEC - int m_fieldAF0; //+0xAF0 - int m_fieldAF4; //+0xAF4 - int m_fieldAF8; //+0xAF8 - int m_fieldAFC; //+0xAFC - int m_fieldB00; //+0xB00 - int m_fieldB04; //+0xB04 - int m_fieldB08; //+0xB08 - int m_fieldB0C; //+0xB0C - int m_fieldB10; //+0xB10 - int m_fieldB14; //+0xB14 - int m_fieldB18; //+0xB18 - int m_fieldB1C; //+0xB1C - int m_fieldB20; //+0xB20 - int m_fieldB24; //+0xB24 - int m_fieldB28; //+0xB28 - int m_fieldB2C; //+0xB2C - int m_fieldB30; //+0xB30 - int m_fieldB34; //+0xB34 - int m_fieldB38; //+0xB38 - int m_fieldB3C; //+0xB3C - int m_fieldB40; //+0xB40 - int m_fieldB44; //+0xB44 - int m_fieldB48; //+0xB48 - int m_fieldB4C; //+0xB4C - int m_fieldB50; //+0xB50 - int m_fieldB54; //+0xB54 - int m_fieldB58; //+0xB58 + eCharacterType m_eCharacterType; //+0x900 + Glacier::ZREF m_rHitmanAs; //+0x904 + Glacier::ZREF m_rWeapon; //+0x908 + Glacier::ZREF m_rWeaponTemplate; //+0x90C + bool m_bIsInOutsideLocation; //+0x910 + bool m_bIsInWater; + RE_ADD_PADDING(2); + ZHM3ItemWeapon* m_pLastDamageFromWeapon; //+0x914 + Glacier::ZREF m_rDragTarget; //+0x918 + Glacier::ZIKLNKOBJ* m_pDragPerson; //+0x91C + int8_t m_iDragBone; //+0x920 + int8_t m_iDragParticle; + RE_ADD_PADDING(2); + float m_fStartingHitpoints; //+0x924 + float m_fHitpoints; //+0x928 + float m_fTension; //+0x92C + bool m_bDecayTension; //+0x930 + RE_ADD_PADDING(3); + float m_fRelaxedVisionRange; //+0x934 + float m_fRelaxedFOV; //+0x938 + float m_fAlertVisionRange; //+0x93C + float m_fAlertFOV; //+0x940 + ZHM3HmAs* m_pSuspectedSuit; //+0x944 + uint32_t m_lOriginalVariantId; //+0x948 + uint32_t m_lOriginalPrim; //+0x94C + float m_fHunger; //+0x950 + float m_fHungerTime; //+0x954 + float m_fThirst; //+0x958 + float m_fThirstTime; //+0x95C + float m_fToilet; //+0x960 + float m_fToiletTime; //+0x964 + float m_fInterest; //+0x968 + float m_fInterestTime; //+0x96C + ZDecaying m_PushAnnoyance; //+0x970 < APPROVED + Glacier::ZVector3 m_vLastHitPos; //+0x980 [APPROVED] + Glacier::ZVector3 m_vLastHitDir; //+0x98C [APPROVED] + float m_fLastHitForce; //+0x998 [APPROVED] + Glacier::TIMETYPE m_tBeganSeeingHitman; //+0x99C + Glacier::TIMETYPE m_tBeganSeeingHitmanRunning; //+0x9A0 + Glacier::TIMETYPE m_tFriskBoxIntrusionStartTime; //+0x9A4 + Glacier::TIMETYPE m_tBeganSeeingHitmanStealthy; //+0x9A8 + UseDoorInfo m_UseDoorInfo; //+0x9AC + internal padding up 4 bytes (+3 actually) + HitmanInfo m_HitmanInfo; // +0x9CC - use only 2 bytes + RE_ADD_PADDING(2); // ^ because this [u16->u32] + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + uint32_t m_field9D0; // Divided by uint16x2 + uint32_t m_field9D4; + + uint16_t m_LoadSaveMask; //+0x9D8 + RE_ADD_PADDING(2); + Glacier::ZREF m_rActorProperties; // +0x9DC + float m_HumanShieldWeight; // +0x9E0 Approved by in-game code + Glacier::Animation::Header* m_pScriptUbAnim; // +0x9E4 [APPROVED] + Glacier::Animation::Header* m_pSpecialPushAnim; // +0x9E8 [APPROVED] + Glacier::ZAnimVariationHandle m_pPutBodyOnTable; + RE_ADD_PADDING(2); + Glacier::Animation::Header* m_pUB_Hold_Toolbox; // +0x9F0 + Glacier::Animation::Header* m_pUB_Hold_Suitcase; // +0x9F4 + Glacier::Animation::Header* m_pUB_CarryBox; // +0x9F8 + Glacier::Animation::Header* m_pUB_HoldCoffeeCup; // +0x9FC + Glacier::Animation::Header* m_pUB_Hold_Tray; // +0xA00 + Glacier::Animation::Header* m_pUB_Hold_Camera; // +0xA04 + Glacier::Animation::Header* m_pUB_Hold_Glass; // +0xA08 + Glacier::Animation::Header* m_pUB_Hold_Bottle; // +0xA0C + Glacier::Animation::Header* m_pUB_Hold_Crate; // +0xA10 + Glacier::Animation::Header* m_pUB_Carry_Bucket; // +0xA14 + Glacier::Animation::Header* m_pUB_Carry_Bible; // +0xA18 + Glacier::Animation::Header* m_pUB_Hold_Camera_Spec;// +0xA1C + Glacier::Animation::Header* m_pUB_Hold_Cane; // +0xA20 + Glacier::Animation::Header* m_pUB_Hold_Mobile; // +0xA24 + Glacier::Animation::Header* m_pUB_Hold_Miv; // +0xA28 + Glacier::Animation::Header* m_pUB_Hold_Champagne; // +0xA2C + Glacier::Animation::Header* m_unknownAnimA30; // 0xA30 + EActorBodyPosition m_eBodyPosition; //+0xA34 + ESittingDetails m_eSittingDetails; //+0xA38 + Flags m_Flags; // +0xA3C + float m_fBaseForce; + Glacier::Animation::ActiveAnimation* m_pDeathAnim; + EActorSpecies m_eActorSpecies; //+0xA48 < CONFIRMED + SBodyInfo m_BodyArray[10]; + int8_t m_iMaxBody; + int8_t m_iStoreBody; + RE_ADD_PADDING(2); + Glacier::ZROOM* m_pCurrentRoom; // +0xAC8 + float m_BlinkCycle; //+0xACC + int8_t m_Mood; //+0xAD0 + RE_ADD_PADDING(3); + float m_MoodScale; //+0xAD4 + int8_t m_iScriptPriorityUpdate; //+0xAD8 + RE_ADD_PADDING(3); + Glacier::ZGEOM* m_pChair; //+0xADC + Glacier::ZQuat m_qUseFurniture; + Glacier::ZVector3 m_vUseFurniture; + bool m_bOnScreenLastFrame; //+0xAFC + RE_ADD_PADDING(3); + float m_fLeaveScreenTime; //+0xB00 + Glacier::ZParticleEmitter* m_pBreathEmitter; //+0xB04 + Glacier::REFTAB* m_pMouthEmitters; //+0xB08 + float m_fTimeSinceLastOneliner; //+0xB0C + bool m_bBlinkingDisabled; + bool m_bUBHoldAnimsEnabled; + RE_ADD_PADDING(2); + eInterestLevel m_eLastPushedLevel; //+0xB14 + sUseElevatorInfo m_sActorElevatorInfo; //+0xB18 + Glacier::ZREF m_rContainingElevator; //+0xB40 + Glacier::ZREF m_rOldParent; //+0xB44 + ExtraFlags m_ExtraFlags; // +0xB48 + int m_iNumVariants; // +0xB4C + bool m_bHidePrimFromCamera; // +0xB50 + RE_ADD_PADDING(3); + float m_fLastClothActionStatusChange; //+0xB54 + float m_fLastDragActionStatusChange; //+0xB58 int m_fieldB5C; //+0xB5C }; + RE_VERIFY_SIZE(ZHM3Actor, 0xB60); // Verified + RE_VERIFY_OFFSET(ZHM3Actor, m_rHitmanAs, 0x904); // Approved by ZHM3Actor__getAvailableSuitObjectID + RE_VERIFY_OFFSET(ZHM3Actor, m_rWeapon, 0x908); // Approved by ZHM3Actor::DieByForce + RE_VERIFY_OFFSET(ZHM3Actor, m_rWeaponTemplate, 0x90C); // Approved by ZHM3Actor::CreateAndHideWeapon + RE_VERIFY_OFFSET(ZHM3Actor, m_bIsInOutsideLocation, 0x910); // Approved by code + RE_VERIFY_OFFSET(ZHM3Actor, m_pLastDamageFromWeapon, 0x914); // Approved by ZHM3Actor::ShouldActorBleed + RE_VERIFY_OFFSET(ZHM3Actor, m_pDragPerson, 0x91C); // Approved by Zhm3Actor__Ishitmandraggingactor + RE_VERIFY_OFFSET(ZHM3Actor, m_fStartingHitpoints, 0x924); // Used by ZHM3Actor + RE_VERIFY_OFFSET(ZHM3Actor, m_fHitpoints, 0x928); // Approved by ZHM3Actor::OverrideHitpoints + RE_VERIFY_OFFSET(ZHM3Actor, m_lOriginalVariantId, 0x948); // Approved by ZHM3Actor::OnChangeNude (store org prim variation) + RE_VERIFY_OFFSET(ZHM3Actor, m_fHunger, 0x950); // Verified by ZHM3Actor::UpdateNeeds + RE_VERIFY_OFFSET(ZHM3Actor, m_fHungerTime, 0x954); // Verified by ZHM3Actor::UpdateNeeds + RE_VERIFY_OFFSET(ZHM3Actor, m_fThirst, 0x958); // Verified by ZHM3Actor::UpdateNeeds + RE_VERIFY_OFFSET(ZHM3Actor, m_fThirstTime, 0x95C); // Verified by ZHM3Actor::UpdateNeeds + RE_VERIFY_OFFSET(ZHM3Actor, m_fToilet, 0x960); // Verified by ZHM3Actor::UpdateNeeds + RE_VERIFY_OFFSET(ZHM3Actor, m_fToiletTime, 0x964); // Verified by ZHM3Actor::UpdateNeeds + RE_VERIFY_OFFSET(ZHM3Actor, m_fInterest, 0x968); // Verified by ZHM3Actor::UpdateNeeds + RE_VERIFY_OFFSET(ZHM3Actor, m_fInterestTime, 0x96C); // Verified by ZHM3Actor::UpdateNeeds + RE_VERIFY_OFFSET(ZHM3Actor, m_PushAnnoyance, 0x970); // Verified by ZHM3Actor::LoadSave + RE_VERIFY_OFFSET(ZHM3Actor, m_vLastHitPos, 0x980); // Verified by ZHM3Actor::OnProjectileDamage + RE_VERIFY_OFFSET(ZHM3Actor, m_vLastHitDir, 0x98C); // Verified by ZHM3Actor::OnProjectileDamage + RE_VERIFY_OFFSET(ZHM3Actor, m_fLastHitForce, 0x998); // Verified by ZHM3Actor::Initialize + RE_VERIFY_OFFSET(ZHM3Actor, m_UseDoorInfo, 0x9AC); // Verified by ZHM3Actor::LoadSave + RE_VERIFY_OFFSET(ZHM3Actor, m_HitmanInfo, 0x9CC); // runtime flags + RE_VERIFY_OFFSET(ZHM3Actor, m_rActorProperties, 0x9DC); // Verified by ZHM3Actor::ClassFrameUpdate + RE_VERIFY_OFFSET(ZHM3Actor, m_HumanShieldWeight, 0x9E0); // Verified by ZHM3Actor::sub_63BCC0 code logic + RE_VERIFY_OFFSET(ZHM3Actor, m_pScriptUbAnim, 0x9E4); // Verified by ZHM3Actor::SetScriptUBAnim + RE_VERIFY_OFFSET(ZHM3Actor, m_pSpecialPushAnim, 0x9E8); // Verified by ZHM3Actor::OnPushed + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Toolbox, 0x9F0); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Suitcase, 0x9F4); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_CarryBox, 0x9F8); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_HoldCoffeeCup, 0x9FC); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Tray, 0xA00); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Camera, 0xA04); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Glass, 0xA08); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Bottle, 0xA0C); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Crate, 0xA10); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Carry_Bucket, 0xA14); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Carry_Bible, 0xA18); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Camera_Spec, 0xA1C); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Cane, 0xA20); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Mobile, 0xA24); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Miv, 0xA28); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_pUB_Hold_Champagne, 0xA2C); // Verified by ZHM3Actor::StoreUBHoldAnims + RE_VERIFY_OFFSET(ZHM3Actor, m_eBodyPosition, 0xA34); // Verified by ZHM3Actor::LoadSave + RE_VERIFY_OFFSET(ZHM3Actor, m_eSittingDetails, 0xA38); // Verified by ZHM3Actor::LoadSave + RE_VERIFY_OFFSET(ZHM3Actor, m_Flags, 0xA3C); // Verified by ZHM3Actor::LoadSave + RE_VERIFY_OFFSET(ZHM3Actor, m_eActorSpecies, 0xA48); // Verified by ZHM3Actor::LoadSave + RE_VERIFY_OFFSET(ZHM3Actor, m_pCurrentRoom, 0xAC8); // Verified by previous R&D & ZHM3Actor::breakMovement + RE_VERIFY_OFFSET(ZHM3Actor, m_eLastPushedLevel, 0xB14); // Verified by ZHM3Actor::LoadSave + RE_VERIFY_OFFSET(ZHM3Actor, m_sActorElevatorInfo, 0xB18); // Verified by ZHM3Actor::LoadSave + RE_VERIFY_OFFSET(ZHM3Actor, m_ExtraFlags, 0xB48); // Verified by ZHM3Actor::LoadSave, ZHM3Actor::EnableDrag, ZHM3Actor::ActivateRagdoll + RE_VERIFY_OFFSET(ZHM3Actor, m_LoadSaveMask, 0x9D8); // Verified by ZHM3Actor::LoadSave + RE_VERIFY_OFFSET(ZHM3Actor, m_pBreathEmitter, 0xB04); // Verified by ZHM3Actor::AllocBreathEmitter + RE_VERIFY_OFFSET(ZHM3Actor, m_pMouthEmitters, 0xB08); // Verified by ZHM3Actor::AddMouthEmitter + RE_VERIFY_OFFSET(ZHM3Actor, m_rContainingElevator, 0xB40); // Verified by ZHM3Actor::GetElevatorDeltaY & ZHM3Actor::IsInElevator + RE_VERIFY_OFFSET(ZHM3Actor, m_iNumVariants, 0xB4C); // Verified by ZHM3Actor::OnChangeNormalCloth, ZHM3Actor::OnChangeNude + RE_VERIFY_OFFSET(ZHM3Actor, m_bHidePrimFromCamera, 0xB50); // Verified by ZHM3Actor::Initialize (set to false) + RE_VERIFY_OFFSET(ZHM3Actor, m_fLastClothActionStatusChange, 0xB54); // Verified by ZHM3Actor::HandleClothDragActions + RE_VERIFY_OFFSET(ZHM3Actor, m_fLastDragActionStatusChange, 0xB58); // Verified by ZHM3Actor::HandleClothDragActions + + /* + Unknown fields: + uint32_t m_field9D0; // Divided by uint16x2 + uint32_t m_field9D4; // idk + m_fieldB58 - Not found at all + + from ZHM3Actor::Initialize + v10 = pThis->field_9D0 & 0xFE; + LOBYTE(pThis->field_9C8) &= 0xFCu; + v11 = pThis->field_B49; + LOBYTE(pThis->field_9D0) = v10; + pThis->field_9D4 = pThis->field_9D4 & 0xFFFFFFFC | 2; +#endif + */ } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3ActorProperties.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3ActorProperties.h new file mode 100644 index 0000000..8ae9ffd --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3ActorProperties.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + + +namespace Hitman::BloodMoney +{ + /** + * I guess, this class is not used by game, but available in RTTI and looks incomplete + */ + class ZHM3ActorProperties : public Glacier::ZSTDOBJ + { + public: + // vtbl + virtual Glacier::REFTAB* GetKnownHitmanAses(); + + // data + Glacier::REFTAB* m_prtKnownHitmanAses; // 0x10 + float m_fRecognizeSpeedKnown; // 0x14 + int m_iForgetTime; // 0x18 + float m_fInspectionDistMin; // 0x1C + float m_fInspectionDistMax; // 0x20 + }; // Verified size 0x24 + RE_VERIFY_SIZE(ZHM3ActorProperties, 0x24); // Verified + RE_VERIFY_OFFSET(ZHM3ActorProperties, m_prtKnownHitmanAses, 0x10); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3BriefingControl.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3BriefingControl.h index 204febb..f88449f 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3BriefingControl.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3BriefingControl.h @@ -17,64 +17,28 @@ namespace Hitman::BloodMoney class ZHM3BriefingControl { public: - //vftable - virtual void LoadSave(Glacier::ZPackedInput* packedInput, bool a2); + virtual ~ZHM3BriefingControl(); - //api + public: //api void CompleteObjective(unsigned int iObjectiveId, bool bShowOSDNotification); void PlaySpeech(bool bRegisterSpeechAsSpoken); void StopSpeech(); - //data (total size is - int m_field4; - int m_field8; - int m_fieldC; - int m_field10; - int m_field14; - int m_field18; - int m_field1C; - int m_field20; - int m_field24; - int m_field28; - int m_field2C; - int m_field30; - Glacier::SREF m_rSpeechSoundObjectSREF; - int m_field38; - int m_field3C; - int m_field40; - int m_field44; - int m_field48; - int m_field4C; - int m_field50; - int m_field54; - int m_field58; - int m_field5C; - int m_field60; - bool m_bIsSpeechPlaying; - bool m_field65; - bool m_field66; - bool m_field67; - int m_field68; - int m_field6C; - char m_bSpoken; - char m_lObjectiveHiddenFlags; - char m_lObjectiveCompletedFlags; - char field_73; - int m_field74; - int m_field78; - int m_field7C; - int m_field80; - int m_field84; - int m_field88; - int m_field8C; - int m_field90; - int m_field94; - int m_field98; - int m_field9C; - int m_fieldA0; - int m_fieldA4; - int m_fieldA8; - int m_fieldAC; - int m_fieldB0; + public: // members + uint8_t m_aszChangedObjectiveTexts[24]; //0x0004 + uint8_t m_aszChangedObjectivePaths[24]; //0x001C + int32_t m_aiSoundRefs[12]; //0x0034 + bool m_iSpeaking; //0x0064 + int8_t m_iCurrentSpeechIdx; //0x0065 + int8_t m_iCurrentHint; //0x0066 + int8_t m_PAD67; //0x0067 + float m_fCurrentLength; //0x0068 + float m_fStartTime; //0x006C + bool m_bSpoken; //0x0070 + int8_t m_lObjectiveHiddenFlags; //0x0071 + int8_t m_lObjectiveCompletedFlags; //0x0072 + uint8_t m_PAD73; //0x0073 }; + + static_assert(sizeof(ZHM3BriefingControl) == 116, "Bad size of ZHM3BriefingControl"); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3ClipParticleControl.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3ClipParticleControl.h new file mode 100644 index 0000000..d82fff4 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3ClipParticleControl.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include + +namespace Hitman::BloodMoney +{ + class ZHM3ClipParticleControl : public Glacier::ZAllocMany + { + public: + uint32_t m_iClipNr; + }; + RE_VERIFY_SIZE(ZHM3ClipParticleControl, 0x6C); // verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3ClothBundle.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3ClothBundle.h index fd22a41..77faf05 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3ClothBundle.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3ClothBundle.h @@ -1,27 +1,33 @@ #pragma once #include +#include +#include namespace Hitman::BloodMoney { + struct SAccessoryGeom + { + Glacier::ZREF rGeom; + uint32_t iBoneId; + }; + RE_VERIFY_SIZE(SAccessoryGeom, 0x8); + class ZHM3ClothBundle : public Glacier::ZSTDOBJ { public: //vftable - virtual void CopyDataFromClothBundle(ZHM3ClothBundle* from); + void CopyData(ZGEOM const*) override; //data (total size is 0x40, base size is 0x10) - int field_10; - int field_14; - int field_18; - int field_1C; - int field_20; - int field_24; - int field_28; - int field_2C; - int field_30; - int field_34; - int field_38; - int field_3C; + Glacier::ZREF m_rHitmanAs; + bool m_bBloody; + Glacier::ZREF m_rOriginalParent; + Glacier::ZREF m_rContainingElevator; + Glacier::ZREF m_rAction; + SAccessoryGeom m_aAccessoryGeoms[3]; + int8_t m_iNumAccessoryGeoms; + }; + RE_VERIFY_SIZE(ZHM3ClothBundle, 0x40); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3CombineItems.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3CombineItems.h new file mode 100644 index 0000000..7da11b3 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3CombineItems.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace Hitman::BloodMoney +{ + struct ZHM3CombineItems : public Glacier::ZGROUP + { + Glacier::ZItemTemplate* m_pCombine1; + Glacier::ZItemTemplate* m_pCombine2; + int32_t m_iAllocNumber; + int32_t m_iSpawnedNumber; + bool m_bSpawnInInventory; + Glacier::ZREF m_rCombine1; + Glacier::ZREF m_rCombine2; + Glacier::REFTAB* m_pCombineCloneGroups; + }; + RE_VERIFY_SIZE(ZHM3CombineItems, 0x6C); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3Damage.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3Damage.h new file mode 100644 index 0000000..7359375 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3Damage.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + enum EDamageType + { + UNKNOWN = 0, + PROJECTILE = 1, + UNARMED = 2, + CHLOROFORM = 3, + STRANGULATE = 4, + EDGED = 5, + CUTTHROAT = 6, + EXPLOSIVE = 7, + CLOSECOMBAT = 8, + BLUNT = 9, + LARGEBLUNT = 10, + PUSHED = 11, + FALL = 12, + POISON = 13, + ANASTETIC = 14, + LAXATIVE_THISISNOTUSED = 15, + STRANGLE_IN_ELEVATOR = 16, + APHRODICIAC = 17, + }; + + struct ZHM3Damage + { + Glacier::THitInfo HitInfo; + Glacier::COLI m_Coli; + EDamageType m_eDamageType; + bool m_bBigForce; + float m_fBaseDamage; + uint32_t m_BodyPart; + + Glacier::ZVector3* GetHitLocation() { return &HitInfo.pColi->cp; } + Glacier::ZVector3* GetHitNormal() { return &HitInfo.pColi->ln; } + }; + RE_VERIFY_SIZE(ZHM3Damage, 0x90); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3GameData.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3GameData.h index c9197b1..b1beef2 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3GameData.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3GameData.h @@ -2,12 +2,50 @@ #include #include +#include +#include #include #include +#include #include +#include +#include +#include #define DECLARE_UNKNOWN_TYPE_PTR(name) using name = std::uintptr_t; +#define VERIFY_FIELD_POS(cls, fld, expected) static_assert(offsetof(cls, fld) == (expected), "Bad offset of " #cls "::" #fld); + +namespace Glacier +{ + class ZWINDOW; + class ZPlayer; + + class ZGameDataFactoryBase + { + public: + virtual void CreateGameData(); + virtual void DestroyGameData(); + }; + + class ZGameDataFactory : ZGameDataFactoryBase + { + }; + + class ZGameStats + { + public: + virtual ~ZGameStats(); + + public: // members + short m_iStats_CurrentShotCount; // +0x4 [Fiberwire and all attacks counted here] + short m_Padding[1]; // +0x6 + float m_iStats_LastShotTime; // +0x8 + }; + + VERIFY_FIELD_POS(ZGameStats, m_iStats_CurrentShotCount, 0x4); + VERIFY_FIELD_POS(ZGameStats, m_iStats_LastShotTime, 0x8); +} namespace Hitman::BloodMoney { @@ -16,67 +54,314 @@ namespace Hitman::BloodMoney DECLARE_UNKNOWN_TYPE_PTR(N0000163D); DECLARE_UNKNOWN_TYPE_PTR(CGlobalCom); DECLARE_UNKNOWN_TYPE_PTR(ZHM3CameraEventCameraClass); - DECLARE_UNKNOWN_TYPE_PTR(ZClothTracker); class ZHM3DialogControl; class ZHM3MenuElements; - class ZHM3Hitman3; + class ZHitman3; class ZGui; class CIngameMap; - class ZHM3BriefingControl; class ZHM3WeaponUpgradeControl; class ZHM3CameraClass; class ZBoidSystem; - class ZHM3GameStats; + + class ZHM3GameStats : public Glacier::ZGameStats + { + public: + int m_iShotsHit; // +0xC + int m_iShotCount; // +0x10 + }; + + VERIFY_FIELD_POS(ZHM3GameStats, m_iShotsHit, 0xC); + VERIFY_FIELD_POS(ZHM3GameStats, m_iShotCount, 0x10); + + enum EBriefingDetailType : int { + eBriefingTypeNoType = 0, + eBriefingTypeTarget = 1, + eBriefingTypeRetrieve = 2, + eBriefingTypeEscape = 3, + eBriefingTypeDispose = 4, + eBriefingTypeProtect = 5, + eBriefingTypeOptional = 6 + }; + + class ZLevelLinking + { + public: + EBriefingDetailType m_eBriefingDetailType; //0x0000 + void* m_pCom; //0x0004 + uint8_t m_Profile[24216]; //0x0008 + }; //Size: 0x5EA0 + + struct sDifficultySettings { + float fstanddowntime; + float ffollowtrailtime; + float fhunttargettracktime; + float fseethroughdisguisedistance; + float fseethroughdisguisespeed; + float fforgetdisguisespeed; + float frunsuspiciousrange; + float faccuracymodifier; + float fburstlength; + float frofmultiplier; + float faimspeed; + float fdrawspeedmultiplier; + float fshothearingrange; + float fscreamhearingrange; + float fcheckfootstepsbehindrange; + float factorrelaxedvisionrange; + float factorrelaxedfov; + float factoralertvisionrange; + float factoralertfov; + float ffallingdamagemultiplier; + float fusecoverpercentage; + float fbleedtodeathtime; + float fciviliansattackhmpercentage; + float fcivilianhidetime; + float flockpicktimemultiplier; + float ffriskintrusiondecaytime; + float fsmallweaponvisiblemultiplierciv; + float fsmallweaponvisiblemultipliergrd; + int ihitmanhitpoints; + int iguardhitpoints; + int icivilianhitpoints; + int itargethitpoints; + bool bautoaim; + bool bheadshotsagainsthitman; + bool bpad[2]; + float fmoneymultiplier; + float fmaxmoneymultiplier; + float fcleanupprice; + float finnocentbribeprice; + float fpolicebribeprice; + float fnewidentityprice; + float fweaponupgradeprice; + float fweaponretrieveprice; + }; + + static_assert(sizeof(sDifficultySettings) == 164, "Bad size of sDifficultySettings"); + + enum EDifficulty : uint32_t { + eeROOKIE = 0, + eNORMAL = 1, + eEXPERT = 2, + ePROFESSIONAL = 3, + + eMAX_VALUE = 4 + }; + + class ZDifficultySettings + { + public: + sDifficultySettings aSettings[EDifficulty::eMAX_VALUE]; + }; + + struct sPricesStruct { + int iObjectivePrices[13][6]; + int iTierPrices[5]; + int iTierUpgradePrice[5]; + int iExtraBriefing; + int iAdditionalInfo; + int iPlaceClothbundle; + int iPlaceHandgun; + int iPlaceSilencedHandgun; + int iPlaceSMG; + int iPlaceExtraSyringes; + int iDisablingAlarms; + int iGuardsNotFrisking; + int iRetrieveWeapons; + int iReplacementSuit; + int iInnocentDamageControl; + int iPoliceDamageControl; + int iRetrieveVideotapes; + int iBribeInnocent; + int iBribePolice; + int iNewIdentity; + }; + + // Size: 0x1A4 (420 bytes) + struct ZMoneySystem { + sPricesStruct m_sPrices; + }; + + struct sNotorietyModifiers { + int iCaughtOnTapeDisguised; + int iCaughtOnTapeNotDisguised; + int iWitness1; + int iWitness2; + int iWitness3; + int iWitness4; + int iWitnessx; + int iMaxWitnessesNormal; + int iMaxWitnessesExpert; + int iMaxWitnessesProfessional; + int iBribeInnocent; + int iBribePolice; + int iNewIdentity; + }; + + struct ZNotorietySystem + { + sNotorietyModifiers m_sNotorietyModifiers; + }; + + static_assert(sizeof(ZNotorietySystem) == 52, "Bad size of ZNotorietySystem"); + + struct ZRatingSystem + { + // There are nothing, all stored in static vars + }; + + enum EFriskOp : int + { + eeFriskOp_Attack = 0, + eFriskOp_DefendAreaNormal = 1, + eFriskOp_DefendAreaAggressive = 2, + eFriskOp_TakeWeapons = 3 + }; + + struct ZBloodTrail : public Glacier::ZSTDOBJ + { + int m_iTrailIndex; + int m_iElementNr; + bool m_bIsRegistered; + }; + + class ZTrailControl { + public: + virtual ~ZTrailControl(); + + struct ZBloodTrail* m_pTrails[5][5]; + bool m_bActiveElements[5][5]; + int m_bDecalIndex[5][5]; + bool m_bActiveTrails[5]; + short m_NumElements; + int m_currentTrail; + int m_currentElement; + int m_currentReadTrail; + int m_currentReadElement; + }; + + static_assert(sizeof(ZTrailControl) == 0x100, "Bad size of ZTrailControl"); + + enum EUpgradeType : int { + UT_Dummy = 0, UT_AmmoACP = 1, UT_AmmoArmorPiercing = 2, UT_Ammo127mm = 3, UT_AmmoMagnum = 4, + UT_AmmoFlechetteSlugs = 5, UT_AmmoGaugesSlugs = 6, UT_AmmoLowVelocity = 7, UT_Magazine = 8, + UT_Silencer1 = 9, UT_Silencer2 = 10, UT_LaserSight = 11, UT_DualAction = 12, UT_DualActionAuto = 13, + UT_DoubleCapMag = 14, UT_FullAuto = 15, UT_ReloadBoost = 16, UT_BeltFeeding = 17, UT_BiPod = 18, + UT_ScopeType1 = 19, UT_ScopeType2 = 20, UT_ScopeType3 = 21, UT_NightVision = 22, UT_Lightweight = 23, + UT_DefaultAmmo = 24, UT_DefaultNoScope = 25, UT_DefaultBarrel = 26, UT_DefaultMagazine = 27, + UT_RailMount = 28, UT_CarbonBarrel = 29, UT_Buttstock = 30, UT_Suitcase = 31, UT_DefaultButtStock = 32, + UT_DefaultGrip = 33, UT_DefaultHandguard = 34, UT_DefaultHandle = 35, UT_DefaultSight = 36, + UT_BoltAction = 37, UT_RedDotSight = 38, UT_ShortBarrel = 39, UT_PistolGrip = 40, UT_HandGuard = 41, + UT_RapidFire = 42, UT_LongSlide = 43, UT_ClipX2 = 44, UT_ClipX3 = 45, UT_ClipX4 = 46, + UT_NumUpgradeTypes = 47 + }; + + struct ZWeaponUpgradeUtils { + Glacier::REFTAB* m_pUpgradeList; + uint32_t m_ALIGN4; + unsigned long long m_lAvailableUpgradesMask; + int m_lLastUpgrade; + int m_lCurrentUpgrade; + EHM3ItemType m_eCurrentSelectedItem; + EUpgradeType m_eCurrentUpgrade; + }; + + static_assert(sizeof(ZWeaponUpgradeUtils) == 0x20, "Bad size of ZWeaponUpgradeUtils"); class ZHM3GameData final : public Glacier::ZGameData { public: + // >>>>>>>>>>> ZGameData <<<<<<<<<<< + // DronCode: Need to move that members to Glacier::ZGameData but it refs to HM3 stuff, need reverse base classes, will do it later ZBoidSystem* m_BoidSystem; //0x0004 - int32_t m_ActorsInPoolCount; //0x0008 - ZHM3Actor* m_ActorsPool[512]; //0x000C + Glacier::ZStaticVector m_ActorsPool; Glacier::ZLIST* m_AllActorsAndPlayerList; //0x080C - char pad_0x0810[0x208]; //0x0810 + Glacier::ZStaticVector m_ItemsPool; + bool m_bDisableDust; + RE_ADD_PADDING(3); Glacier::REFTAB* m_ParticleTemplatesList; //0x0A18 ZHM3MenuElements* m_MenuElements; //0x0A1C - ZHM3Hitman3* m_Hitman3; //0x0A20 (also in A40 located similar instance, it doesn't matter what I will use, but few instructions trying to talk with +A40) - int m_field0A24; //0x0A24 - int m_field0A28; //0x0A28 - int m_field0A2C; //0x0A2C + Glacier::ZPlayer* m_apPlayers[4]; ZHM3GameStats* m_GameStats; //0x0A30 - int m_field0A34; //0x0A34 - int m_field0A38; //0x0A38 - int m_field0A3C; //0x0A3C - ZHM3Hitman3* m_Hitman3_2; //0x0A40 (hitman instance too, maybe it's merged from other structure or smth like that) - Glacier::ZREF m_rPlayer; //0x0A44 (ZREF to ZHitman3 instance) + int m_pSoundDef_OSD; //0x0A34 ZSDOwner* m_pSOund + int m_pSoundDef_Effects; //0x0A38 + bool m_bGameJustLoaded; + RE_ADD_PADDING(3); + + // >>>>>>>>>>> ZHM3GameData <<<<<<<<<<< + ZHitman3* m_Hitman3; //0x0A40 + Glacier::ZREF m_rPlayer; //0x0A44 ZHM3LevelControl* m_LevelControl; //0x0A48 ZOSD* m_OSD; //0x0A4C ZGui* m_Gui; //0x0A50 CIngameMap* m_IngameMap; //0x0A54 - int m_fieldA58; //0x0A58 - CGlobalCom* m_GlobCom; //0x0A5C - char m_ProfileName[16]; //0xFC5888 - char pad_0x0A70[0x64]; //0x0A70 - int32_t m_PlayerMoney; //0x0AD4 - char pad_0AD8[24096]; //0x0AD8 - ZHM3BriefingControl* m_BriefingControl; //0x68F8 - char pad_68FC[116]; //0x68FC - ZHM3WeaponUpgradeControl* m_WeaponUpgradeControl; //0x6970 - ZHM3CameraEventCameraClass* m_CameraEventCameraClass; //0x6974 - ZHM3CameraClass* m_CameraClass; //0x6978 - int m_field697C; - int m_field6980; - int m_field6984; - int m_field6988; //0x6988 (something about materials) - int m_field698C; - int m_rActorCommunicationComponentID; //0x6990 - int m_rFightControllerComponentID; //0x6994 - int m_rCoverListComponentID; //0x6998 - ZClothTracker* m_ClothTracker; //0x699C - int m_field69A0; //0x69A0 - int m_field69A4; //0x69A4 + ZLevelLinking m_LevelLinking; + ZHM3BriefingControl m_BriefingControl; + Glacier::ZWINDOW* m_pZWindow; + ZHM3WeaponUpgradeControl* m_pWeaponUgradeControl; //0x6970 + ZHM3CameraEventCameraClass* m_pEventCamera; //0x6974 + ZHM3CameraClass* m_pMainCamera; //0x6978 + int m_pActorMoveSets; + ZDifficultySettings* m_pDifficultySettings; + ZMoneySystem* m_pMoneySystem; + ZNotorietySystem* m_pNororietySystem; + ZRatingSystem* m_pRatingSystem; + uint32_t m_rActorCommunication; + uint32_t m_rFightController; + uint32_t m_rCoverList; + ZClothTracker* m_pClothTracker; //0x699C Created on demand by ZHitman3::OnActorBlowingHitmansCover + uint32_t m_rActorFriskingHM; + EFriskOp m_eFriskOperation; //0x69A0 ZHM3DialogControl* m_DialogControl; //0x69A8 - }; + Glacier::REFTAB m_Elevators; + ZWeaponUpgradeUtils* m_pWeaponUpgradeUtils; + Glacier::REFTAB m_FriskGuards; + Glacier::REFTAB m_ItemTemplates; + float m_fTension; + float m_fTensionDelta; + Glacier::ZGROUP* m_pBodyBagGroup; + unsigned int* m_pTotalWeaponPrims; + int m_lTotalWeaponPrimsCount; + unsigned int* m_pUsedWeaponPrims; + int m_lUsedWeaponPrimsCount; + unsigned int* m_pBigWeaponPrims; + int m_lBigWeaponPrimsCount; + ZTrailControl* m_pTrailControl; + int m_iPFBodyBagBoxTypeId; + Glacier::REFTAB m_WantedPosts; + bool m_bLoadError; + bool m_bLoadErrorM00; + bool m_bForceBriefingM00; + bool m_pad6A4F; + + // Exclude anims shit + // (I Still don't know what the fuck is happening here) + struct ZExcludedAnimList { + void* m_pSentinelNode; // 0x00 + uint32_t m_iSize; // 0x04 + uint32_t m_pUnusedPadding;// 0x08 + }; + static_assert(sizeof(ZExcludedAnimList) == 12, "Bad size of ZExcludedAnimList"); + + ZExcludedAnimList m_aExcluded[4]; // 0x6A50 + + uint8_t m_bAnimContainerFlag; // 0x6A80 + char m_pad6A81; // 0x6A81 + char m_pad6A82; // 0x6A82 + char m_pad6A83; // 0x6A83 + uint32_t m_alwaysZeroed; // 0x6A84 + }; // Total size is 0x6A88 (27272) + + RE_VERIFY_SIZE(ZHM3GameData, 0x6A88); + RE_VERIFY_OFFSET(ZHM3GameData, m_apPlayers, 0x0A20); + RE_VERIFY_OFFSET(ZHM3GameData, m_ParticleTemplatesList, 0x0A18); + RE_VERIFY_OFFSET(ZHM3GameData, m_Hitman3, 0x0A40); + RE_VERIFY_OFFSET(ZHM3GameData, m_Gui, 0x0A50); + RE_VERIFY_OFFSET(ZHM3GameData, m_rActorCommunication, 0x6990); + RE_VERIFY_OFFSET(ZHM3GameData, m_pClothTracker, 0x699C); + RE_VERIFY_OFFSET(ZHM3GameData, m_DialogControl, 0x69A8); + RE_VERIFY_OFFSET(ZHM3GameData, m_pWeaponUpgradeUtils, 0x69C8); } #undef DECLARE_UNKNOWN_TYPE_PTR \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3HitEvent.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3HitEvent.h new file mode 100644 index 0000000..7200e35 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3HitEvent.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + struct ZHM3HitEvent + { + Glacier::ZVector3 fHitPos; + Glacier::ZVector3 fHitDir; + int iDamage; + Glacier::ZREF rOwner; + const char* szAnimName; + int iBoneNum; + int iDamageType; + int iBigForce; + Glacier::ZREF rWeapon; + + void InitFromHitInfo(Glacier::SHitInfo* pHitInfo) + { + fHitPos = pHitInfo->pColi->cp; + fHitDir = pHitInfo->pColi->ln; + rOwner = pHitInfo->rWeaponOwner; + rWeapon = pHitInfo->rWeapon; + } + + void InitFromDamage(ZHM3Damage* pDamage) + { + fHitPos = *pDamage->GetHitLocation(); + fHitDir = *pDamage->GetHitNormal(); + rOwner = pDamage->HitInfo.rWeaponOwner; + rWeapon = pDamage->HitInfo.rWeapon; + iDamageType = pDamage->m_eDamageType; + // It was inlined in PC, so I may miss smth + } + + void SetDamage(int value) + { + iDamage = value; + } + + void SetDamageType(int iType) + { + iDamageType = iType; + } + + void SetAnimName(const char* pzName) + { + szAnimName = pzName; + } + + void SetBoneNumber(int iBone) + { + iBoneNum = iBone; + } + }; + RE_VERIFY_SIZE(ZHM3HitEvent, 0x34); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3HmAs.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3HmAs.h index 05debcd..9019a22 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3HmAs.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHM3HmAs.h @@ -2,26 +2,37 @@ #include #include +#include #include +#include namespace Hitman::BloodMoney { + enum EDressQuality : uint32_t { + eQualityBad = 0, + eQualityGood = 1, + eQualitySuper = 2, + eQualityPerfect = 3, + eQualityHitman = 4, + }; + class ZHM3HmAs : public Glacier::ZGROUP { public: /// vftable - virtual void CopyDataFromHmAs(ZHM3HmAs* from); + virtual void CopyData(ZGEOM const*) override; virtual bool IsZoneAllowed(ESecurityZone zoneKind); /// data (total size is 0xA0, parent size is 0x4C) - int m_field4C; //copied at CopyDataFromHmAs - int m_field50; - Glacier::REFTAB m_reftab54; - int m_field70; - uint32_t m_allowedRegionsMask; - Glacier::REFTAB m_reftab78; - int m_field94; - int m_field98; - int m_field9C; + Glacier::ZREF m_rClothBundleGroup; + Glacier::ZAUDIOREF m_FootwearMaterial; + Glacier::REFTAB m_rtWeaponsAllowed; + EDressQuality m_eDressQuality; + Glacier::ZBitfield m_AllowedZones; + Glacier::REFTAB m_rtItemContainerAllowed; + int32_t m_iDisguiseGroup; + bool m_bMayUseLadders; + Glacier::ZRTString ExtraOptionName; }; + RE_VERIFY_SIZE(ZHM3HmAs, 0xA0); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZHitman3.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHitman3.h new file mode 100644 index 0000000..dc9a4c8 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZHitman3.h @@ -0,0 +1,786 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +namespace Hitman::BloodMoney +{ + // fwds + class ZHitman3; + class ZHM3Actor; + class ZHM3ItemContainer; + class ZHM3ItemTemplateWeapon; + class ZHM3ItemWeapon; + class ZHM3ItemBomb; + class ZHM3HmAs; + class ZTie; + struct ZTimeMultEffectControl; + struct ZHM3Camera; + struct ZHitman3AutoAim; + struct ZHM3MovementGuideToMatPos; + struct ZHM3MovementGuideList; + + // enums + enum eHideStuffState { + eHideNone = 0, + eHideFront = 1, + eHideBehind = 2, + eHideSide = 3, + }; + + struct SCombineItems + { + EHM3ItemType m_eItemType1; + EHM3ItemType m_eItemType2; + Glacier::ZGROUP* m_pCombineGroup; + }; + RE_VERIFY_SIZE(SCombineItems, 0xC); + + struct SNearEnemy + { + ZHM3Actor* m_pActor; + float m_fDistance; + float m_fAngle; + bool m_bVisibleOnScreen; + RE_ADD_PADDING(3); + }; + RE_VERIFY_SIZE(SNearEnemy, 0x10); + + struct SDualWeapons + { + ZHM3ItemTemplateWeapon* m_pTemplate; + ZHM3ItemWeapon* m_pRight; + ZHM3ItemWeapon* m_pLeft; + int32_t m_nRightAmmo; + int32_t m_nLeftAmmo; + }; + RE_VERIFY_SIZE(SDualWeapons, 0x14); + + struct SRailInfo + { + Glacier::ZGEOM* pRailGeom; + Glacier::ZVector3 vP1; + Glacier::ZVector3 vP2; + Glacier::ZVector3 vP3; + Glacier::ZVector3 vColiPt; + }; + RE_VERIFY_SIZE(SRailInfo, 0x34); + + // aliases + using ZStackArrayLocalizedActionNames = Glacier::ZStackArray<61, Glacier::zstring>; + + using ZStackArrayCombineItemList = Glacier::ZStackArray<10, SCombineItems>; // 124 + RE_VERIFY_SIZE(ZStackArrayCombineItemList, 124); + + using ZStackArrayNearEnemiesList = Glacier::ZStackArrayInsert<5, SNearEnemy, float>; // 104 + RE_VERIFY_SIZE(ZStackArrayNearEnemiesList, 104); + + using ZStackArrayDualWeaponsTemplateList = Glacier::ZStackArray<10, SDualWeapons>; // 204 + RE_VERIFY_SIZE(ZStackArrayDualWeaponsTemplateList, 204); + + using ZStackArrayPlantedBombs = Glacier::ZStackArray<3, ZHM3ItemBomb*>; + RE_VERIFY_SIZE(ZStackArrayPlantedBombs, 0x10); + + struct ZHM3Inventory + { + // members + Glacier::CInventory* m_pInventoryEvent; + Glacier::REFTAB* m_pInventory; + Glacier::ZGROUP* m_pWeaponsGroup; + }; + RE_VERIFY_SIZE(ZHM3Inventory, 0xC); + + class ZHM3InputControl + { + public: + // types + struct MoveFlags + { + uint16_t m_bLeanLeft : 1; + uint16_t m_bLeanRight : 1; + uint16_t m_bLeanLeftShoot : 1; + uint16_t m_bLeanRightShoot : 1; + uint16_t m_bRunToggle : 1; + uint16_t m_bMovementIncrease : 1; + uint16_t m_bMovementDecrease : 1; + uint16_t m_bCrouchSneak : 1; + uint16_t m_bRun : 1; + }; + + struct WeaponFlags + { + uint8_t m_bFire : 1; + uint8_t m_bFire2 : 1; + uint8_t m_bReload : 1; + }; + + struct CameraFlags + { + uint8_t m_bToggleCamera; + uint8_t m_bCameraZoomIn; + uint8_t m_bCameraZoomOut; + uint8_t m_bCameraZoom; + }; + + // vtbl + virtual void LoadObject(Glacier::IInputSerializerStream& stream); + virtual void SaveObject(Glacier::IOutputSerializerStream& stream); + + // members + MoveFlags m_Movements; + WeaponFlags m_Weapons; + RE_ADD_PADDING(1); + CameraFlags m_Camera; + bool m_bDropBody; + bool m_bCancelExit; + bool m_bDropItem; + bool m_bThrowItem; + bool m_bPickupItem; + bool m_bUseAction; + bool m_bActive; + RE_ADD_PADDING(1); + float m_fCutSeqTime; + float m_fThrowTime; + }; + RE_VERIFY_SIZE(ZHM3InputControl, 0x1C); + + class ZHM3MovementControl + { + public: + // vtbl + virtual void LoadObject(Glacier::IInputSerializerStream& stream); + virtual void SaveObject(Glacier::IOutputSerializerStream& stream); + + // members + bool m_bDisableMovement; + RE_ADD_PADDING(3); + Glacier::ZVector2 m_vTurn; + Glacier::ZVector2 m_vTurnMultiplier; + Glacier::ZVector3 m_vMoveSpeed; + float m_fMovementSpeedPrc; + struct ZHitman3ControlBase* m_pCurrentControl; + struct ZHitman3ControlMouseStrafe* m_pControlMouseStrafe; + struct ZHitman3ControlMouse* m_pControlMouse; + struct ZHitman3ControlConsoleStrafe* m_pControlConsoleStrafe; + struct ZHitman3ControlConsole* m_pControlConsole; + bool m_bStrafeModeActive; + bool m_bNoTurnStrafeMode; + bool m_bForceFaceCamera; + RE_ADD_PADDING(1); + float m_fTurnToWalkAngle; + struct CEaseInOut* m_pTurnEaseInOut; + }; + RE_VERIFY_SIZE(ZHM3MovementControl, 0x48); + + class ZHM3SegmentedLineColi + { + public: + Glacier::TIMETYPE m_fColiUpdateTime; + float m_fDynamicTestDistance; + bool m_bWorkColiStatic; + bool m_bWorkColiDynamic; + bool m_bAlternateDynamicStatic; + RE_ADD_PADDING(1); + int m_lTryingToHitCount; + Glacier::ZVector3 m_vStart; + Glacier::ZVector3 m_vEnd; + float m_fColiLength; + Glacier::ZVector3 m_vColiPos; + Glacier::ZVector3 m_vColiNormal; + Glacier::ZBaseGeom* m_pColiGeom; + Glacier::ZBaseGeom* m_pWorkColiGeom; + }; + RE_VERIFY_SIZE(ZHM3SegmentedLineColi, 0x4C); + + class ZHM3WeaponsControl + { + public: + // vtbl + virtual void LoadObject(Glacier::IInputSerializerStream& stream); + virtual void SaveObject(Glacier::IOutputSerializerStream& stream); + + // methods + ZHitman3* Hitman() { return m_pHitman; } + + // types + struct FireFlags { + uint16_t m_bFireWeapon : 1; + uint16_t m_bFireWeapon2 : 1; + uint16_t m_bLastFireWeapon : 1; + uint16_t m_bLastFireWeapon2 : 1; + uint16_t m_bFireWeaponRelease : 1; + uint16_t m_bFireWeapon2Release : 1; + uint16_t m_bFireWeaponTap : 1; + uint16_t m_bFireWeapon2Tap : 1; + uint16_t m_bFireLock : 1; + uint16_t m_bFireTargetCallBackWait : 1; + uint16_t m_bReloadWeapon : 1; + uint16_t m_bReloadCausedByEmptyWeapon : 1; + uint16_t m_bHumanShieldAimModeActive : 1; + uint16_t m_bEnableWeaponUse : 1; + }; + + struct DualActionFlags + { + unsigned char m_bDualActionEnabled : 1; + unsigned char m_bDualActionAutoEnabled : 1; + }; + + struct WeaponInfo + { + Glacier::ZLNKOBJ* m_pGround; + Glacier::Animation::Header* m_pAnimReloadWeapon; + Glacier::Animation::Header* m_pAnimChamberWeapon; + Glacier::Animation::Header* m_pAnimReloadOneHand; + }; + + // members + ZHitman3* m_pHitman; + Glacier::TIMETYPE m_ttLastAttackTime; + Glacier::ZMSGID m_msgGetInventoryListPtr; + FireFlags m_Flags; + WeaponInfo m_RHandWeaponInfo; + WeaponInfo m_LHandWeaponInfo; + int32_t m_iNumberOfAmmoClips; + int32_t m_iProjectilesInMagazine; + int32_t m_iPrevProjectilesInMagazine; + int32_t m_iNrAmmoProjectiles; + Glacier::ZGEOM* m_pAimLastTarget; + float m_fTargetDistance; + ZHM3SegmentedLineColi* m_pSegAimColi; + DualActionFlags m_DualFlags; + }; + RE_VERIFY_SIZE(ZHM3WeaponsControl, 0x50); + + class ZHM3ActionControl + { + public: + // vtbl + virtual void LoadObject(Glacier::IInputSerializerStream& stream); + virtual void SaveObject(Glacier::IOutputSerializerStream& stream); + + // members + ZHitman3* m_pHitman; + Glacier::ZREF m_rHitman; + EHM3Action m_eCurrentAction; + Glacier::ZGEOM* m_pCurrentActionObject; + Glacier::ZAction* m_pCurrentZAction; + Glacier::ZItem* m_pRightHandItem; + Glacier::ZItem* m_pLeftHandItem; + Glacier::ZItem* m_pCombineItem1; + Glacier::ZItem* m_pCombineItem2; + Glacier::ZGEOM* m_pCombineMaster; + Glacier::ZItemContainer* m_pItemContainer; + Glacier::ZItem* m_pPlaceRetrieveItem; + ZStackArrayLocalizedActionNames m_LocalizedActionNames; + Glacier::ZREF m_rNearestFrontEnemy; + ZHM3Actor* m_pNearestFrontEnemy; + float m_fNearestEnemyAngle; + float m_fNearestEnemyFaceHitmanAngle; + }; + RE_VERIFY_SIZE(ZHM3ActionControl, 0x324); + + struct SAccessoryGeom + { + uint32_t rGeom; + uint32_t iBoneId; + }; + RE_VERIFY_SIZE(SAccessoryGeom, 0x8); + + struct SBodyGMR + { + Glacier::ZVector3 dir; + Glacier::ZVector3 target; + float radius; + bool grabbing; + uint16_t par; + float strained; + }; + RE_VERIFY_SIZE(SBodyGMR, 0x24); + + /* + Inheritance tree: + ZHitman3: + ZPlayer -> ZLNKWHANDS -> ZCTRLIKLNKOBJ -> ZIKLNKOBJ -> ZLNKOBJ -> ZSTDOBJ -> ZGEOM -> RTP::cBase -> ZSerializable -> ZSerializableBase + ZHM3InputControl + ZHM3MovementControl + ZHM3WeaponsControl + ZHM3Inventory + ZHM3ActionControl + */ + class ZHitman3 : public Glacier::ZPlayer, public ZHM3InputControl, public ZHM3MovementControl, public ZHM3WeaponsControl, public ZHM3Inventory, public ZHM3ActionControl + { + public: + // types + struct Actions + { + bool m_bChangingClothes; + bool m_bChangingClothesAllowed; + bool m_bSneaking; + bool m_bStrangulating; + bool m_bInjecting; + bool m_bPunching; + bool m_bPushing; + bool m_bClimbingHatch; + float m_fInjectingTime; + bool m_bLockPicking; + char pad_0D[3]; + }; + RE_VERIFY_SIZE(Actions, 0x10); + + struct Enabled + { + bool m_bNightVisionEnabled; + bool m_bBinocularsEnabled; + bool m_bFacingEnabled; + }; + RE_VERIFY_SIZE(Enabled, 0x3); + + struct SMovementLast + { + bool m_bIsInMotion; + bool m_bIsWalking; + bool m_bIsRunning; + bool m_bIsCrouching; + bool m_bIsSneaking; + bool m_bIsCrouchSneaking; + bool m_bIsOnLadder; + bool m_bIsOnDrainPipe; + bool m_bIsOnGuide; + }; + RE_VERIFY_SIZE(SMovementLast, 0x9); + + struct SForceFlags + { + bool m_bForceCrouch; + bool m_bDragPosForced; + }; + RE_VERIFY_SIZE(SForceFlags, 0x2); + + // vtbl (valid & reconstructed) + virtual bool GetHideInThisView() const; + virtual void Die(bool bUnknown1, bool bUnknown2); + virtual void ActivateAnimSegmentWithCameraBone(Glacier::Animation::Header* pHeader, int iBoneIdx, float fParam1, float fParam2, float fParam3); + virtual void GetAnims(); + virtual float GetItemAssignedUBAnim(Glacier::ZItem* pItem, Glacier::Animation::Header** ppOutHeader, unsigned int* pOutIdx, float* pOutFloat); + virtual void StoreUBHoldAnims(); + virtual void MapUBHoldAnimsToIdx(); + virtual void DisableControls(bool cMode); + virtual Glacier::ZGEOM* GetNearestActionObject(); + virtual bool IsInCutsequence(); + virtual void DetachItemFromRightHand(Glacier::ZItem* pItem); + virtual void DetachItemFromLeftHand(Glacier::ZItem* pItem); + virtual void DetachItemFromHitman(Glacier::ZItem* pItem); + virtual void AttachItemToRightHand(Glacier::ZItem* pItem); + virtual void AttachItemToLeftHand(Glacier::ZItem* pItem); + virtual void AttachItemToHitman(Glacier::ZItem* pItem); + + // Test only + ZTimeMultEffectControl* m_pTimeMultEffectControl; + ZHM3Camera* m_pCameraControl; + ZHitman3AutoAim* m_pAutoAim; + bool m_bAutoAimEnabled; + char _pad1[3]; + struct ZHM3MovementGuideToMatPos* m_pMovementGuideToMatPos; + struct ZHM3MovementGuideList* m_pMovementGuideList; + unsigned int m_CurrentStatusExtended; + unsigned int m_LastStatusExtended; + unsigned int m_LastStatus; + bool m_bFakeScopeMode; + char _pad2[3]; + unsigned int m_rThis; + bool bSwapBack; + char _pad3[3]; + unsigned int m_iObjectVisibleFlags[2]; + unsigned int m_iLastObjectVisibleFlags[2]; + bool m_bIsInWater; + char _pad4[3]; + Glacier::ZVector3 m_fPelvisUpDown; + Glacier::Animation::Header* m_pAnimReloadShotgun1; + Glacier::Animation::Header* m_pAnimReloadFranchi; + Glacier::Animation::Header* m_pAnimHolsterGunSuitcase; + Glacier::Animation::Header* m_pAnimPullItemRightSuitcase; + Glacier::Animation::Header* m_pPullItemRight; + Glacier::Animation::Header* m_pAnimFirstPersonAimRifle; + Glacier::Animation::Header* m_pAnimFirstPersonAimGun; + Glacier::Animation::Header* m_pAnimFirstPersonAim2Guns; + Glacier::Animation::Header* m_pAnimAimAnimHumanShield; + Glacier::Animation::Header* m_pAnimAimAnimHumanShieldRecoil; + Glacier::Animation::Header* m_pAnimUpperBodyCutThroat; + Glacier::Animation::Header* m_pAnimGarrot_01; + Glacier::Animation::Header* m_pAnimGarrot_02; + Glacier::Animation::Header* m_pAnimGarrot_03; + Glacier::Animation::Header* m_pAnimGarrot_Costume; + Glacier::Animation::Header* m_pAnimStrangleQuick; + Glacier::Animation::Header* m_pAnimStrangleQuickHigh; + Glacier::Animation::Header* m_pAnimGarrot_Chair; + Glacier::Animation::Header* m_pAnimDieStomac; + Glacier::Animation::Header* m_pAnimStabAxe; + Glacier::Animation::Header* m_pAnimPunchDeep; + Glacier::Animation::Header* m_pAnimPunchTighten; + Glacier::Animation::Header* m_pAnimDisarm_Gun; + Glacier::Animation::Header* m_pAnimDisarm_DualGun; + Glacier::Animation::Header* m_pAnimDisarm_Riffle; + Glacier::Animation::Header* m_pAnimKnifeTighten[2]; + Glacier::Animation::Header* m_pAnimKnifeHold[2]; + Glacier::Animation::Header* m_pAnimKnifeHit01[2]; + Glacier::Animation::Header* m_pAnimKnifeHit02[2]; + Glacier::Animation::Header* m_pAnimKnifeThrowTighten; + Glacier::Animation::Header* m_pAnimKnifeMiss; + Glacier::Animation::Header* m_pAnimKnifeKill01; + Glacier::Animation::Header* m_pAnimKnifeKill02; + Glacier::Animation::Header* m_pAnimKnifeKill03; + Glacier::Animation::Header* m_pAnimKnifeKillCostume; + Glacier::Animation::Header* m_pAnimKnifeKillSitting; + Glacier::Animation::Header* m_pAnimHedgeCutterTighten[2]; + Glacier::Animation::Header* m_pAnimHedgeCutterHit[2]; + Glacier::Animation::Header* m_pAnimHedgeCutterHold[2]; + Glacier::Animation::Header* m_pAnimHedgeCutterMiss; + Glacier::Animation::Header* m_pAnimHedgeCutterKill; + Glacier::Animation::Header* m_pAnimHedgeCutterTightenBehind; + Glacier::Animation::Header* m_pAnimPickAxeTighten[2]; + Glacier::Animation::Header* m_pAnimPickAxeHit[2]; + Glacier::Animation::Header* m_pAnimPickAxeHold[2]; + Glacier::Animation::Header* m_pAnimPickAxeKill; + Glacier::Animation::Header* m_pAnimFireExtinguisherTighten[2]; + Glacier::Animation::Header* m_pAnimFireExtinguisherHit[2]; + Glacier::Animation::Header* m_pAnimFireExtinguisherHold[2]; + Glacier::Animation::Header* m_pAnimFireExtinguisherKill; + Glacier::Animation::Header* m_pAnimHammerTighten[2]; + Glacier::Animation::Header* m_pAnimHammerHit[2]; + Glacier::Animation::Header* m_pAnimHammerHold[2]; + Glacier::Animation::Header* m_pAnimHammerKill; + Glacier::Animation::Header* m_pAnimSyringeHold[2]; + Glacier::Animation::Header* m_pAnimBaseballBatTighten[2]; + Glacier::Animation::Header* m_pAnimBaseballBatHit[2]; + Glacier::Animation::Header* m_pAnimUBBaseballBatHold[2]; + Glacier::Animation::Header* m_pAnimBaseballBatKill; + Glacier::Animation::Header* m_pAnimPitchforkTighten[2]; + Glacier::Animation::Header* m_pAnimPitchforkHit[2]; + Glacier::Animation::Header* m_pAnimPitchforkHold[2]; + Glacier::Animation::Header* m_pAnimPitchforkKill; + Glacier::Animation::Header* m_pAnimScrewdriverTighten[2]; + Glacier::Animation::Header* m_pAnimScrewdriverTightenBehind; + Glacier::Animation::Header* m_pAnimScrewdriverHit[2]; + Glacier::Animation::Header* m_pAnimScrewdriverHold[2]; + Glacier::Animation::Header* m_pAnimScrewdriverKill; + Glacier::Animation::Header* m_pAnimStungunTighten[2]; + Glacier::Animation::Header* m_pAnimStungunHit[2]; + Glacier::Animation::Header* m_pAnimHoldStunGun[2]; + Glacier::Animation::Header* m_pAnimStunGunTightenBehind; + Glacier::Animation::Header* m_pAnimStungunKill; + Glacier::Animation::Header* m_pAnimShovelTighten[2]; + Glacier::Animation::Header* m_pAnimShovelHit[2]; + Glacier::Animation::Header* m_pAnimShovelHold[2]; + Glacier::Animation::Header* m_pAnimShovelKill; + Glacier::Animation::Header* m_pAnimCaneSwordTighten; + Glacier::Animation::Header* m_pAnimCaneSwordHit; + Glacier::Animation::Header* m_pAnimCaneSwordHold; + Glacier::Animation::Header* m_pAnimCaneSwordKill; + Glacier::Animation::Header* m_pAnimDragBodyLeftHand; + Glacier::Animation::Header* m_pAnimStartDragBody; + Glacier::Animation::Header* m_pAnimPickLockStart; + Glacier::Animation::Header* m_pAnimPickLockStartSuitcase; + Glacier::Animation::Header* m_pAnimPickLockLoop; + Glacier::Animation::Header* m_pAnimPickLockEnd; + Glacier::Animation::Header* m_pAnimPickLockEndSuitcase; + Glacier::Animation::Header* m_pAnimHMUnlockDoor; + Glacier::Animation::Header* m_pAnimHoldSuitcase; + Glacier::Animation::Header* m_pAnimHoldSuitcaseReload; + Glacier::Animation::Header* m_pAnimHoldSuitcaseRun; + Glacier::Animation::Header* m_pAnimHoldSuitcaseDrainPipe; + Glacier::Animation::Header* m_pAnimHoldSuitcaseCrouch; + Glacier::Animation::Header* m_pAnimHoldSuitcaseSneak; + Glacier::Animation::Header* m_pAnimStunFront; + Glacier::Animation::Header* m_pAnimDisarmTakeGun; + Glacier::Animation::Header* m_pAnimDisarmTakeGunFast; + Glacier::Animation::Header* m_pAnimChangeClothes; + Glacier::Animation::Header* m_pAnimUpperBodyMissAxe; + Glacier::Animation::Header* m_pAnimUpperBodyUseClub; + Glacier::Animation::Header* m_pAnimUpperBodyHitClub; + Glacier::Animation::Header* m_pAnimDieSequence; + Glacier::Animation::Header* m_pAnimUpperBodyHoldGun; + Glacier::Animation::Header* m_pAnimUpperBodyHold2Guns; + Glacier::Animation::Header* m_pAnimUpperBodyHoldRifle; + Glacier::Animation::Header* m_pAnimUpperBodyHoldRifleLefthand; + Glacier::Animation::Header* m_pAnimUpperBodyHoldMP5; + Glacier::Animation::Header* m_pAnimUpperBodyHoldSMGHorizontalHandle; + Glacier::Animation::Header* m_pAnimUpperBodyHoldCase; + Glacier::Animation::Header* m_pAnimUpperBodyUseGarrot; + Glacier::Animation::Header* m_pAnimUpperBodyTightenGarrot01; + Glacier::Animation::Header* m_pAnimUpperBodyTightenGarrotCrouch; + Glacier::Animation::Header* m_pAnimUpperBodyMissGarrot; + Glacier::Animation::Header* m_pAnimUpperBodyHoldFN2000; + Glacier::Animation::Header* m_pAnim1StHoldCustomSMGNoUpgrade; + Glacier::Animation::Header* m_pAnim1StRecoilCustomSMGNoUpgrade; + Glacier::Animation::Header* m_pAnim1StHoldCustomAssaultUpgrade; + Glacier::Animation::Header* m_pAnim1StRecoilCustomAssaultUpgrade; + Glacier::Animation::Header* m_pAnimUBStrechArmWhileAiming; + Glacier::Animation::Header* m_pAnim1StCHBSingleRecoilAuto; + Glacier::Animation::Header* m_pAnim1StCHBDualRecoilAuto; + Glacier::Animation::Header* m_pAnimDisposeBody1; + Glacier::Animation::Header* m_pAnimDisposeBody2; + Glacier::Animation::Header* m_pAnimDisposeBodyTable; + Glacier::Animation::Header* m_pAnimHideBodyInBed; + Glacier::Animation::Header* m_pAnimPickupDeadBody; + Glacier::Animation::Header* m_pAnimDisposeBody; + Glacier::Animation::Header* m_pAnimHoldGunBehind; + Glacier::Animation::Header* m_pAnimHoldGunFront; + Glacier::Animation::Header* m_pAnimHoldGunSide; + Glacier::Animation::Header* m_pAnimHoldKnifeBehind; + Glacier::Animation::Header* m_pAnimHoldKnifeFront; + Glacier::Animation::Header* m_pAnimHoldKnifeSide; + Glacier::Animation::Header* m_pAnimTransKnifeBehindToSide; + Glacier::Animation::Header* m_pAnimTransKnifeFrontToSide; + Glacier::Animation::Header* m_pAnimUpperBodyCarryBody; + Glacier::Animation::Header* m_pAnimThrow; + Glacier::Animation::Header* m_pAnimThrowLow; + Glacier::Animation::Header* m_pAnimThrowTighten; + Glacier::Animation::Header* m_pAnimThrowTightenBigRightHand; + Glacier::Animation::Header* m_pAnimThrowSuitcaseTighten; + Glacier::Animation::Header* m_pAnimThrowSuitcase; + Glacier::Animation::Header* m_pAnimPush; + Glacier::Animation::Header* m_pAnimSuitcaseRetrieve; + Glacier::Animation::Header* m_pAnimSuitcasePack; + Glacier::Animation::Header* m_pAnimHumanShieldGrab; + Glacier::Animation::Header* m_pAnimHumanShieldRelease; + Glacier::Animation::Header* m_pAnimHumanShieldLeftArmPose; + Glacier::Animation::Header* m_pAnimPoisonActor; + Glacier::Animation::Header* m_pAnimPoisonActorCostume; + Glacier::Animation::Header* m_pAnimPoisonActorQuick; + Glacier::Animation::Header* m_pAnimPoisonActorChair; + Glacier::Animation::Header* m_pAnimPoisonActorBed; + Glacier::Animation::Header* m_pAnimPoisonItemGround; + Glacier::Animation::Header* m_pAnimPoisonItemTable; + Glacier::Animation::Header* m_pAnimPoisonItem100cm; + Glacier::Animation::Header* m_pAnimPoisonItem120cm; + Glacier::Animation::Header* m_pAnimUseKeycard; + Glacier::Animation::Header* m_pAnimClimbHatch; + Glacier::Animation::Header* m_pAnimStartStrangleInElev; + Glacier::Animation::Header* m_pAnimUseSwitch; + Glacier::Animation::Header* m_pAnimUseFirealarm; + Glacier::Animation::Header* m_pAnimJumpBalcony; + Glacier::Animation::Header* m_pSedateCIAAgent; + Glacier::Animation::Header* m_pPutDownSuitcase; + Glacier::Animation::Header* m_pPickupSuitcaseFront; + Glacier::Animation::Header* m_pPickupSuitcaseLeft; + Glacier::Animation::Header* m_pPickupSuitcaseRight; + Glacier::Animation::Header* m_pReviveCIAAgent; + Glacier::Animation::Header* m_pDropWeigth; + Glacier::Animation::Header* m_pBreakUtilBox; + Glacier::Animation::Header* m_pPourFluidOnDevice; + Glacier::Animation::Header* m_pPoisonBottle; + Glacier::Animation::Header* m_pOpenGasAnim; + Glacier::Animation::Header* m_pLaptopAnim; + Glacier::Animation::Header* m_pHMPhoning; + Glacier::Animation::Header* m_pPickUpBox; + Glacier::Animation::Header* m_pPickUpBox75; + Glacier::Animation::Header* m_pPutDownBox; + Glacier::Animation::Header* m_pPickUpBurgers; + Glacier::Animation::Header* m_pPutDownBurgers; + Glacier::Animation::Header* m_pBoxFromElevator; + Glacier::Animation::Header* m_pBoxToElevator; + Glacier::Animation::Header* m_pAnimTurnRight; + Glacier::Animation::Header* m_pAnimTurnLeft; + Glacier::Animation::Header* m_pStandDoNothing; + Glacier::Animation::Header* m_pTriggerBombAnim; + Glacier::Animation::Header* m_pDualWeaponAimAnim; + Glacier::Animation::Header* m_pDualWeaponRecoilAnim; + Glacier::Animation::Header* m_pPackRifle; + Glacier::Animation::Header* m_pUnPackRifle; + Glacier::Animation::Header* m_pHoldCrate; + Glacier::Animation::Header* m_pHoldCake; + Glacier::Animation::Header* m_pHoldToolBox; + Glacier::Animation::Header* m_pHoldTray; + Glacier::Animation::Header* m_pHoldBottle; + Glacier::Animation::Header* m_pHoldGlass; + Glacier::Animation::Header* m_pHoldBible; + Glacier::Animation::Header* m_pHoldMobile; + Glacier::Animation::Header* m_pHoldBinoculars; + Glacier::Animation::Header* m_pHoldSausage; + Glacier::ZBlockArrayBase m_UBAnimArray; + struct ZFootPrints* m_pFootPrints; + struct ZBloodTrails* m_pBloodTrails; + Glacier::ZMSGID m_msgProjectileHit; + Glacier::ZMSGID m_msgBite; + Glacier::ZMSGID m_msgDoorLocked; + Glacier::ZMSGID m_msgOperateObject; + Glacier::ZMSGID m_msgReloadWeapon; + Glacier::ZMSGID m_msgCanOperateObject; + Glacier::ZMSGID m_msgAction_GetActionList; + Glacier::ZMSGID m_msgRequestKeyholePos; + Glacier::ZMSGID m_msgPickLockReqeust; + Glacier::ZMSGID m_msgGetCombineWithItemTemplate; + Glacier::ZMSGID m_msgCombineItems; + Glacier::ZMSGID m_msgRequestDeltaY; + Glacier::ZMSGID m_msgForceDie; + Glacier::ZMSGID m_msgActivateObject; + Glacier::ZMSGID m_msgGrab; + Glacier::ZMSGID m_msgRelease; + float m_fMapClosedTime; + Glacier::TIMETYPE m_ttDamageGraceTime; + Glacier::TIMETYPE m_ttDeathCutsequenceTime; + Glacier::TIMETYPE m_ttCrouchSneakStartTime; + Glacier::TIMETYPE m_ttLastHitAnimTime; + Glacier::TIMETYPE m_ttLastUpdateActionControl; + float m_fTurnSpeed; + float m_fHitpoints; + float m_fHitpointsMax; + float m_fAdrenalineHitpoints; + float m_fAdrenalineTimer; + bool m_bPostInit; + uint8_t m_pad469[3]; + uint32_t m_iKnifeCount; + uint32_t m_iStrangleCount; + float m_fFallingDamageMultiplier; + float m_fLockPickTimeMultiplier; + int m_iHitmanHitpoints; + bool m_bAllowHeadShotsAgainstHitman; + uint8_t m_pad47D[3]; + struct ZHM3HmAs* m_pCurrentSuit; + struct ZHM3HmAs* m_pHMAsHM; + struct ZTie* m_pTie; + SAccessoryGeom m_aAccessoryGeoms[3]; + int8_t m_iNumAccessoryGeoms; + int8_t m_iOnFirstPersonModeForceThirdPersonModeCount; + int8_t m_DontAnimateAttachers; + int8_t m_pad4AB; + ZGEOM* m_pGrab; + SBodyGMR m_GrabData; + int32_t m_BoneGrabIndex; + ZHM3Actor* m_pEscort; + bool m_bFireTargetCallBackWait; + bool m_bUseItemUBAnim; + bool m_bOneHandReloading; + bool m_bReloadIng; + Actions m_Actions; + Enabled m_Enabled; + SMovementLast m_MovementLast; + SForceFlags m_ForceFlags; + bool m_bLastCutsequence; + bool m_bVisibleToCameraUpdate; + bool m_bFirstPersonModeBones; + bool m_bCameraToggleAllowed; + bool m_pad502[2]; + ZHM3Actor* m_pHumanShieldTarget; + ZHM3Actor* m_pCurrentVictim; + ZStackArrayCombineItemList m_CombineItems; + ZStackArrayNearEnemiesList m_NearEnemiesList; + ZHM3ItemWeapon* m_pDualWeaponsPickupItem; + ZStackArrayDualWeaponsTemplateList m_DualWeaponsTemplateList; + bool m_bSuitcasePackUnpackActive; + bool m_bSuitcasePackUnpackInitialPosReached; + bool m_pad6C2[2]; + ZHM3ItemWeapon* m_pSuitcasePackUnpackItemSniper; + ZHM3ItemContainer* m_pSuitcasePackUnpackItemSuitcase; + bool m_bPackSuitcase; + bool m_pad6CD[3]; + uint32_t m_CurrentStatusBuffer[15]; + uint32_t m_CurrentStatusExtendedBuffer[15]; + Glacier::ZGROUP* m_pSuitcaseUnpackSniper; + Glacier::ZGROUP* m_pSuitcasePackSniper; + Glacier::ZGROUP* m_pPackFlightCase; + Glacier::ZGROUP* m_pUnPackFlightCase; + Glacier::TIMETYPE m_ttStartBreathTime; + float m_fBreathTime; + bool m_bBreathIn; + bool m_pad761[3]; + struct ZParticleEmitter* m_pBreathEmitter; + bool m_bIsInOutsideLocation; + bool m_pad769[3]; + ZStackArrayPlantedBombs m_PlantedBombs; + Glacier::ZGEOM* m_pLastPlaceBombGeom; + Glacier::ZItem* m_pAttachedRHandItem; + Glacier::ZROOM* m_pCurrentRoom; + ESecurityZone m_eRoomZone; + ESecurityZone m_eCustomZone; + bool m_bZoneClear; + bool m_bRequestZoneValidate; + bool m_pad792[2]; + Glacier::ZGEOM* m_pRequiredHeadwear; + Glacier::ZGEOM* m_pRequiredAttachedItem; + Glacier::ZGEOM* m_pZoneControl; + Glacier::ZROOM* m_pBackdropRoom; + Glacier::ZGEOM* m_pChuteColiGeom; + Glacier::ZGEOM* m_pBedGeom; + Glacier::ZGEOM* m_pCloset; + ZHM3Actor* m_pLastCloseCombatStunTarget; + int* m_pLastUseAnims[2]; + bool m_bPlayedReverse; + bool m_bAnimSoundStartet; + bool m_pad7BE[2]; + Glacier::ZVector3 m_vLastValidPFPos; + bool m_bIsInValidComponent; + bool m_pad7CD[3]; + ZGEOM* m_pLastDoor; + Glacier::ZVector3 m_ActorAimPoint; + Glacier::ZVector3 m_ActorAimOffset; + float m_fLightMultiplier; + float m_fVisionRangeMultiplier; + ZGEOM* m_pPickLockDoor; + bool m_bBloodyDress; + bool m_bRightDualWeaponUnequipInProgress; + bool m_bLeftDualWeaponUnequipInProgress; + bool m_pad7FB; + ZGEOM* m_pHeadWear; + ZGEOM* m_pAttachedItem; + uint32_t m_lCurrentDefIndex; + bool m_BloodTrailStartFlag; + bool m_pad809[3]; + Glacier::ZVector3 m_BloodTrailStartPos; + Glacier::TIMETYPE m_LastUpdateBloodTrails; + float m_NextWaitTimeBloodTrails; + int m_iNumTrailsInCurrentTrail; + float m_fCurrentTrailSize; + uint32_t m_rContainingElevator; + ZHM3Actor* m_pElevatorStrangleTarget; + bool m_bHMIsOnTopOfElevator; + bool m_pad831[3]; + float m_fOldMovePoolWeight; + float m_fLastEnterClosetTime; + float m_fLastExitClosetTime; + SRailInfo m_RailInfo; + bool m_bMatPosForced; + bool m_pad875[3]; + Glacier::ZVector3 m_vForcePos; + Glacier::ZMat3x3 m_mForceMat; + bool m_bDeathSequenceActive; + bool m_pad8A9[3]; + Glacier::TIMETYPE m_ttDeathSequenceStartTime; + Glacier::ZGROUP* m_pHitmanDeathSequenceIngame; + float m_fDeathSequencePostFilterNrFrames; + float m_fDeathSequenceTimeMultiplier; + float m_fDeathSequenceTimeToDie; + int32_t m_iDeathSequenceNrKills; + float m_fDeathSequenceNrKillsAbortSequence; + struct ZPostFilterAnimEvent* m_pPostFilterAnimDeathSequence; + bool m_bDiePostfilterEnabled; + bool m_pad8CD[3]; + uint32_t m_AudioEffect_Dying; + uint32_t m_AudioEffect_Sneaking; + bool m_bControlUseOneAloneDisabled; + bool m_bEnableControlUseOneAloneNextFrame; + bool m_pad8DA[2]; + struct ZSoundObject* m_pSoundObject_Sneaking; + Glacier::ZVector3 m_vForceDragpos; + bool m_bLandingOnLedge; + bool m_bTighteningFiberWire; + bool m_bMountingWallFromBelow; + bool m_bAutoCrouchWhenTighteningFiberWire; + float m_fLastHeadShotTime; + eHideStuffState m_eHideState; + eHideStuffState m_eHideAnimState; + float fLastTransTime; + + // This part is unknown and not declared in PS2/iOS builds + // I guess it's PC specific part + uint8_t m_aUnknownBytes[44]; + }; + RE_VERIFY_SIZE(ZHitman3, 0x1478); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZKnifeThrower.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZKnifeThrower.h new file mode 100644 index 0000000..607b3e2 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZKnifeThrower.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +namespace Hitman::BloodMoney +{ + struct ZKnifeThrower : public Glacier::CBaseEvent + { + public: + Glacier::ZVector3 m_vDirection; + Glacier::ZREF m_rOwner; + float m_fMoveAngle; + float m_fMoveStep; + Glacier::ZVector3 m_vTarget; + Glacier::ZVector3 m_vStartPos; + + /// Unlike PS2 build, PC build contains some additional members, which are used in the code, but their purpose is unknown yet + uint8_t m_iUnk; // Looks like ZREF to smth, idk + RE_ADD_PADDING(3); + int* m_SomeUnknownPtr; // +0x64 + }; // size is 0x68 + RE_VERIFY_SIZE(ZKnifeThrower, 0x68); + RE_VERIFY_OFFSET(ZKnifeThrower, m_vDirection, 0x30); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZPlaceBomb.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZPlaceBomb.h new file mode 100644 index 0000000..4e12303 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZPlaceBomb.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + + +namespace Hitman::BloodMoney +{ + enum EPlaceItemType + { + PLACEITEMTYPE_BOMB = 0, + PLACEITEMTYPE_SUITCASE = 1, + }; + + class ZPlaceBomb : public Glacier::CBaseEvent + { + public: + // vtbl (not confirmed) + virtual const char* GetActionName(); + virtual bool CanPlace(); + + // data + Glacier::REFTAB m_AffectedGeoms; + Glacier::ZREF m_rRigGeom; + EPlaceItemType m_iItemType; + bool m_bPickupable; + Glacier::ZAction* m_pAction; + Glacier::ZItem* m_pItem; + Glacier::Animation::Header* m_pAnim; + Glacier::Animation::Header* m_pAnim2; + int m_iCallBackFrame; + Glacier::ZRTString m_szActionName; + }; // Size 0x70 + RE_VERIFY_SIZE(ZPlaceBomb, 0x70); // Verified +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZPodiumController.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZPodiumController.h index 548c380..115ab2e 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZPodiumController.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZPodiumController.h @@ -1,29 +1,29 @@ #pragma once +#include #include #include namespace Hitman::BloodMoney { + class ZHM3LevelControlM13; + class ZPodiumController { public: - char field_0; - char field_1; - char field_2; - char field_3; - char m_field4; - char field_5; - char field_6; - char field_7; + Glacier::ZGEOM* m_pPodium; + ZHM3LevelControlM13* m_pLevelControl; bool m_bMoving; bool m_bHitmanOnTable; - bool m_fieldA; - bool m_fieldB; - int m_fMoveEndTime; - char field_10; - __declspec(align(4)) bool m_bTrapDoorClosed; - Glacier::Vector3 m_vCameraTargetPos; - Glacier::Vector3 m_vCameraFocusPos; + RE_ADD_PADDING(2); + float m_fMoveEndTime; + Glacier::ZGROUP* m_pTrapDoor; + bool m_bTrapDoorClosed; + RE_ADD_PADDING(3); + Glacier::ZVector3 m_vCameraTargetPos; + Glacier::ZVector3 m_vCameraFocusPos; }; + RE_VERIFY_SIZE(ZPodiumController, 0x30); // Verified + RE_VERIFY_OFFSET(ZPodiumController, m_vCameraTargetPos, 0x18); + RE_VERIFY_OFFSET(ZPodiumController, m_vCameraFocusPos, 0x24); } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZScriptC.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZScriptC.h new file mode 100644 index 0000000..f3ebd36 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZScriptC.h @@ -0,0 +1,136 @@ +#pragma once + +#include +#include +#include + +namespace Hitman::BloodMoney +{ + struct STATECONTROLLER; + + using ProcessMessage_t = int (*)(unsigned short, void *); + using VoidFunction_t = void (*)(); + using ScriptFunction_t = void (*)(); + + enum SAVEGAMESTATICSTYPE : uint8_t + { + SGST_RAW = 0x0, + SGST_STRING = 0x1, + SGST_THREAD = 0x2, + SGST_STATEREF = 0x3, + SGST_EVENTREF = 0x4, + SGST_END = 0x5, + }; + + struct SAVEGAMESTATICS + { + SAVEGAMESTATICSTYPE m_eType; + uint8_t m_padding[3]; + uint32_t m_lSize : 24; + void *m_pAddr; + }; + + struct FUNCTIONCONTROLLER + { + ScriptFunction_t m_pEntryPoint; + int16_t m_lInputSize; + int16_t m_lDataSize; + int32_t *m_lStringOffsets; + }; + + struct SCRIPTIMPORT + { + uint16_t m_SIT : 3; + uint16_t m_lAmount : 13; + }; + + struct SCRIPTCREATOR + { + char *m_pName; + int32_t m_lScriptVariablesSize; + int32_t m_lStateVariablesSize; + const STATECONTROLLER *m_pStateController; + const SCRIPTCREATOR *m_pParentCreator; + const void **m_pStatesVirtualTable; + ProcessMessage_t ProcessMessage; + VoidFunction_t Initialize; + const SAVEGAMESTATICS *m_pSaveGameStatics; + void (*Imports)(); + void (*StaticImports)(); + void (*UnpackResources)(); + void (*UnpackStaticResources)(); + const SCRIPTIMPORT *m_pImports; + }; + + struct MessageCue + { + MessageCue *m_pLast; + MessageCue *m_pNext; + uint16_t msg; + }; + + struct LocalVarEntry + { + const FUNCTIONCONTROLLER *m_pFunctionController; + LocalVarEntry *m_pNextVariables; + LocalVarEntry *m_pPrevVariables; + int16_t m_lFunctionIndex; + int16_t m_lExitFunctionIndex; + int16_t m_lNextVariablesSize; + int16_t m_lAlignment; + }; + + struct AsyncCall_Struct // sizeof=0xC + { + AsyncCall_Struct *m_pNext; + float m_fStoredNextRun; + LocalVarEntry *m_pLVE; + }; + + struct ScriptState // sizeof=0x40 + { // XREF: ScriptState/r + void *m_pScriptVariables; + const SCRIPTCREATOR *m_pCreator; + Glacier::ZGEOM *m_rThis; + LocalVarEntry *m_pVariables; + void *m_pStateVariables; + const STATECONTROLLER *m_pStateController; + const STATECONTROLLER *m_pPreviousStateController; + const STATECONTROLLER *m_pNextStateController; + uint16_t m_msgWaitForEvent; + uint16_t m_Flags; + AsyncCall_Struct *m_pAsyncCall; + AsyncCall_Struct *m_pAsyncCallLast; + const SCRIPTCREATOR *m_pMessageHandler; + ScriptState *m_pAlienCall; + const void **m_pFunctionsVirtualTable; + void *m_pThreadInfo; + MessageCue *m_pMessageCue; + }; + + struct ScriptStateInfo // sizeof=0x8 + { + ScriptState *m_pRootScriptState; + ScriptState *m_pCurrentScriptState; + }; + + class ZScriptC : public Glacier::ZBaseConRout + { + public: + static constexpr const char* Name = "ScriptC"; + + // vtbl unchanged + + // methods + SCRIPTCREATOR* FindScript(const char* scriptName); + SCRIPTCREATOR* CreateScript(SCRIPTCREATOR* pScriptCreator); + + public: // data + SCRIPTCREATOR *m_pScriptCreator; + ScriptStateInfo *m_pInitialScriptStateInfo; + void *m_pStoredDataBlock; + int m_msgEnterCamera; + }; + + static_assert(offsetof(ZScriptC, m_pScriptCreator) == 0x30, "Invalid offset of m_pScriptCreator (expected to be 0x30)"); +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZTie.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZTie.h index 0cb7a2a..cc5b4f2 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZTie.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZTie.h @@ -1,5 +1,6 @@ #pragma once +#include #include namespace Hitman::BloodMoney @@ -11,7 +12,11 @@ namespace Hitman::BloodMoney // api void HideTie(bool); void HideTieInMirror(bool); + // Data (total size is 0xB4, ZCloth size is 0xB0) - int field_B0; + bool m_bHidden; + bool m_bHiddenInMirror; + RE_ADD_PADDING(2); }; + RE_VERIFY_SIZE(ZTie, 0xB4); // Verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Game/ZWheelChairLock.h b/ReHitman/BloodMoney/include/BloodMoney/Game/ZWheelChairLock.h index 9c71361..2acce53 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/Game/ZWheelChairLock.h +++ b/ReHitman/BloodMoney/include/BloodMoney/Game/ZWheelChairLock.h @@ -1,11 +1,13 @@ #pragma once -#include +#include +#include +#include namespace Hitman::BloodMoney { class ZHM3Actor; - class ZWheelChairLock : public Glacier::ZEventBase { + class ZWheelChairLock : public Glacier::CBaseEvent { public: //static static constexpr Glacier::ZMSGID kDeactivateFrameUpdate = 0x915; @@ -13,9 +15,10 @@ namespace Hitman::BloodMoney { //vftable (no changes) //api //data (total size is 0x3C, base size is 0x30) - int m_rActorREF; - ZHM3Actor* m_pAttachedActor; - short m_rAnimation; - short m_field3A; - }; + Glacier::ZREF m_rActor; + Glacier::ZLNKWHANDS* m_pActor; + uint16_t m_iBoneId; + RE_ADD_PADDING(2); + }; // size is 0x3C + RE_VERIFY_SIZE(ZWheelChairLock, 0x3C); // verified } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/Patches/All/FixFuckedLoaderScreens.h b/ReHitman/BloodMoney/include/BloodMoney/Patches/All/FixFuckedLoaderScreens.h new file mode 100644 index 0000000..5fe3345 --- /dev/null +++ b/ReHitman/BloodMoney/include/BloodMoney/Patches/All/FixFuckedLoaderScreens.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +namespace Hitman::BloodMoney +{ + struct FixFuckedLoaderScreens : public BasicPatch + { + std::string_view GetName() const override { return "FixFuckedLoaderScreen"; } + bool Apply(const ModPack& modules) override; + void Revert(const ModPack& modules) override; + + private: + HF::Hook::TrampolineBasicPtr m_correctTimeCalcTrampoline; + HF::Hook::TrampolineBasicPtr m_newWaitLoopTrampoline; + }; +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/UI/BloodMoneyInspectors.h b/ReHitman/BloodMoney/include/BloodMoney/UI/BloodMoneyInspectors.h index 9217cd6..026dacc 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/UI/BloodMoneyInspectors.h +++ b/ReHitman/BloodMoney/include/BloodMoney/UI/BloodMoneyInspectors.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include @@ -31,7 +31,7 @@ namespace ImGui for (int waypointListIndex = 0; waypointListIndex < totalWaypointsListsCount; ++waypointListIndex) { - const int ZLISTEntityId = reinterpret_cast(pathFollower->m_listsOfWaypoints[waypointListIndex]); + const auto ZLISTEntityId = pathFollower->m_listsOfWaypoints[waypointListIndex]; auto pointsList = reinterpret_cast(Glacier::ZGEOM::RefToPtr(ZLISTEntityId)); if (!pointsList || !pointsList->m_entries) @@ -49,7 +49,7 @@ namespace ImGui // } // } - ImGui::Text("Waypoints List #%d : %s", (waypointListIndex+1), pointsList->m_baseGeom->entityName); + ImGui::Text("Waypoints List #%d : %s", (waypointListIndex+1), pointsList->m_baseGeom->m_Name); //const int pointsCount = pointsList->m_entries->Count(); //TODO: Continue from https://github.com/DronCode/ReHitman/blob/22fb0d77f3bfb593072bdfb8a3c380e7e2dc7c37/HM3CoreKill/HM3CoreKill/ck/HM3InGameTools.cpp#L896 } diff --git a/ReHitman/BloodMoney/include/BloodMoney/UI/DebugTools.h b/ReHitman/BloodMoney/include/BloodMoney/UI/DebugTools.h index d3c657a..571b5b1 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/UI/DebugTools.h +++ b/ReHitman/BloodMoney/include/BloodMoney/UI/DebugTools.h @@ -20,5 +20,6 @@ namespace Hitman::BloodMoney void drawLevelsTopMenu(); void drawTopMenu(); + void showUpgradesEditor(); }; } \ No newline at end of file diff --git a/ReHitman/BloodMoney/include/BloodMoney/UI/GlacierInspectors.h b/ReHitman/BloodMoney/include/BloodMoney/UI/GlacierInspectors.h index cbcbef2..013bb94 100644 --- a/ReHitman/BloodMoney/include/BloodMoney/UI/GlacierInspectors.h +++ b/ReHitman/BloodMoney/include/BloodMoney/UI/GlacierInspectors.h @@ -97,23 +97,26 @@ namespace ImGui auto st = (Glacier::EBoidState)*state; switch (st) { - case Glacier::EBoidState::Moving: - ImGui::Text("EBoidState::Moving"); + case Glacier::EBoidState::eFollowPath: + ImGui::Text("EBoidState::eFollowPath"); break; - case Glacier::EBoidState::Staying: - ImGui::Text("EBoidState::Staying"); + case Glacier::EBoidState::eControlled: + ImGui::Text("EBoidState::eControlled"); break; - case Glacier::EBoidState::ParentActorDestroyed: - ImGui::Text("EBoidState::ParentActorDestroyed (Dead)"); + case Glacier::EBoidState::eSoftObstacle: + ImGui::Text("EBoidState::eSoftObstacle"); break; - case Glacier::EBoidState::Sitting: - ImGui::Text("EBoidState::Sitting"); + case Glacier::EBoidState::eHardObstacle: + ImGui::Text("EBoidState::eHardObstacle"); break; - case Glacier::EBoidState::Unk6: - ImGui::Text("EBoidState::Unk6"); + case Glacier::EBoidState::ePassivePushable: + ImGui::Text("EBoidState::ePassivePushable"); break; - default: - ImGui::Text("Unknown EBoidState (%.8X)", st); + case Glacier::EBoidState::eInActive: + ImGui::Text("EBoidState::eInActive"); + break; + case Glacier::EBoidState::eHero: + ImGui::Text("EBoidState::eHero"); break; } } @@ -130,9 +133,9 @@ namespace ImGui return; } - ImGui::Inspector::Draw("Boid state", &boid->m_boidState); - ImGui::Inspector::Draw("Boid Position", &boid->m_Position); - ImGui::Text("Actual speed: %f / Speed: %f / Speed2: %f", boid->m_ActualSpeed, boid->m_speed, boid->m_speed2); + ImGui::Inspector::Draw("Boid state", &boid->m_eState); + ImGui::Inspector::Draw("Boid Position", &boid->m_kPosition); + ImGui::Text("Actual speed: %f / Max speed: %f", boid->m_ActualSpeed, boid->m_fMaxSpeed); } } }; @@ -147,11 +150,17 @@ namespace ImGui return; } - ImGui::Text("ID: %X", entity->m_Instance); - ImGui::Text("Name: "); ImGui::SameLine(0.f, 0.4f); ImGui::TextColored(ImVec4 { 0.f, 1.f, 0.f, 1.f }, "%s", entity->entityName); - ImGui::Inspector::Draw("Transform", &entity->m_transform); - ImGui::Inspector::Draw("Position", &entity->position); - ImGui::Text("Primitive ID: %d", entity->m_primitive); + ImGui::Text("Name: "); ImGui::SameLine(0.f, 0.4f); ImGui::TextColored(ImVec4 { 0.f, 1.f, 0.f, 1.f }, "%s", entity->m_Name); + ImGui::Inspector::Draw("Transform", &entity->m_mMat); + ImGui::Inspector::Draw("Position", &entity->m_vPos); + ImGui::Inspector::Draw("Center", &entity->m_vCen); + ImGui::DragFloat("Radius", &entity->m_fRadius); + ImGui::Text("ListID: %d", entity->m_uListID); ImGui::SameLine(); + ImGui::Text("PLLC: %d", entity->m_lPotentialLightListChange); ImGui::SameLine(); + ImGui::Text("Freeze: %d", entity->m_bFreezeLightList); + ImGui::Text("Draw id: %d", entity->m_lDrawId); ImGui::SameLine(); + ImGui::Text("Draw entry id: %d", entity->m_lDrawId); + ImGui::Text("Primitive ID: %d", entity->m_lPrim); } }; @@ -168,7 +177,7 @@ namespace ImGui ImGui::Text(" GROUP INFO "); ImGui::Separator(); - ImGui::Text("Name : %s", group->m_baseGeom->entityName); + ImGui::Text("Name : %s", group->m_baseGeom->m_Name); ImGui::Text("Depth : %d", group->GroupDepth()); // await jump to 004EA2D0 ImGui::Text("IsRoot : %s", (group->IsRoot() ? "YES" : "NO")); @@ -178,7 +187,7 @@ namespace ImGui // Show parent node if (parentGroup && ImGui::TreeNode("Parent")) { - ImGui::Inspector::Draw(parentGroup->m_baseGeom->entityName, parentGroup); + ImGui::Inspector::Draw(parentGroup->m_baseGeom->m_Name, parentGroup); ImGui::TreePop(); } } @@ -269,11 +278,6 @@ namespace ImGui } }; - template <> struct Inspector - { - static void Draw(const char* id, Glacier::ESuitMask* mask); - }; - /// BloodMoney stuff template <> struct Inspector { diff --git a/ReHitman/BloodMoney/source/BMConfigurationService.cpp b/ReHitman/BloodMoney/source/BMConfigurationService.cpp index 38f9556..4502172 100644 --- a/ReHitman/BloodMoney/source/BMConfigurationService.cpp +++ b/ReHitman/BloodMoney/source/BMConfigurationService.cpp @@ -11,6 +11,7 @@ namespace Hitman::BloodMoney std::intptr_t BMConfigurationService::BMAPI_FunctionAddress_CMetalDetector_DoAlarm = BMConfigurationService::kNotConfiguredOption; std::intptr_t BMConfigurationService::BMAPI_FunctionAddress_ZHM3Actor_PreparePath = BMConfigurationService::kNotConfiguredOption; std::intptr_t BMConfigurationService::BMAPI_FunctionAddress_ZHM3Actor_ActivateBloodSpurt = BMConfigurationService::kNotConfiguredOption; + std::intptr_t BMConfigurationService::BMAPI_FunctionAddress_ZHM3Actor_InitMapIcon = BMConfigurationService::kNotConfiguredOption; std::intptr_t BMConfigurationService::BMAPI_FunctionAddress_ZTie_HideTie = BMConfigurationService::kNotConfiguredOption; std::intptr_t BMConfigurationService::BMAPI_FunctionAddress_ZTie_HideTieInMirror = BMConfigurationService::kNotConfiguredOption; std::intptr_t BMConfigurationService::BMAPI_FunctionAddress_ZXMLGUISystem_GetTopWindow = BMConfigurationService::kNotConfiguredOption; diff --git a/ReHitman/BloodMoney/source/Client.cpp b/ReHitman/BloodMoney/source/Client.cpp index 8fd6a4f..3ff3521 100644 --- a/ReHitman/BloodMoney/source/Client.cpp +++ b/ReHitman/BloodMoney/source/Client.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace Hitman::BloodMoney @@ -162,6 +163,11 @@ namespace Hitman::BloodMoney Glacier::G1ConfigurationService::G1API_FunctionAddress_ZEventBase_ActivateTimeUpdate = 0x004E1520; Glacier::G1ConfigurationService::G1API_FunctionAddress_ZActorCommunication_RegisterRadioUser = 0x00654920; Glacier::G1ConfigurationService::G1API_FunctionAddress_ZBaseConRout_GetFactory = 0x004E15F0; + + // ZGeomBuffer + Glacier::G1ConfigurationService::G1API_FunctionAddress_ZGeomBuffer_GeomPtrToRef_ZGEOM = 0x00462A00; + Glacier::G1ConfigurationService::G1API_FunctionAddress_ZGeomBuffer_GeomPtrToRef_ZGeomBase = 0x004629E0; + #pragma endregion #pragma region BloodMoney Configuration Table BloodMoney::BMConfigurationService::BMAPI_FunctionAddress_ZPathFollower_GetClosestWaypoint = 0x00654450; @@ -173,6 +179,7 @@ namespace Hitman::BloodMoney BloodMoney::BMConfigurationService::BMAPI_FunctionAddress_CMetalDetector_DoAlarm = 0x005D5B50; BloodMoney::BMConfigurationService::BMAPI_FunctionAddress_ZHM3Actor_PreparePath = 0x00505570; BloodMoney::BMConfigurationService::BMAPI_FunctionAddress_ZHM3Actor_ActivateBloodSpurt = 0x0063D210; + BloodMoney::BMConfigurationService::BMAPI_FunctionAddress_ZHM3Actor_InitMapIcon = 0x00637460; BloodMoney::BMConfigurationService::BMAPI_FunctionAddress_ZTie_HideTie = 0x00580470; BloodMoney::BMConfigurationService::BMAPI_FunctionAddress_ZTie_HideTieInMirror = 0x00580480; BloodMoney::BMConfigurationService::BMAPI_FunctionAddress_ZXMLGUISystem_GetTopWindow = 0x005665E0; @@ -288,6 +295,7 @@ namespace Hitman::BloodMoney m_patches->RegisterPatch(); m_patches->RegisterPatch(); m_patches->RegisterPatch(); + m_patches->RegisterPatch(); // temporary disabled //m_patches->RegisterPatch(); diff --git a/ReHitman/BloodMoney/source/Debug/Gizmo/ActorDebugGizmo.cpp b/ReHitman/BloodMoney/source/Debug/Gizmo/ActorDebugGizmo.cpp index 915c31d..7561f07 100644 --- a/ReHitman/BloodMoney/source/Debug/Gizmo/ActorDebugGizmo.cpp +++ b/ReHitman/BloodMoney/source/Debug/Gizmo/ActorDebugGizmo.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -21,71 +22,65 @@ namespace Hitman::BloodMoney::Debug { void ActorDebugGizmo::OnDrawGizmo(EGizmoLayer layer, IDirect3DDevice9 *device) { - return; - /// ---- INTERFACES & DATA - auto systemInterface = Glacier::getInterface(Globals::kSysInterfaceAddr); - if (!systemInterface) return; - - auto gameData = Glacier::getInterface(Globals::kGameDataAddr); - if (!gameData || !gameData->m_Hitman3 || !gameData->m_ActorsInPoolCount) return; - - auto pCamera = reinterpret_cast(gameData->m_CameraClass); - if (!pCamera || !pCamera->IsActive()) return; - - auto pD3DDll = Glacier::getInterface(Globals::kD3DDllAddr); - if (!pD3DDll) return; - - auto pPrimControl = pD3DDll->m_primControlWintel; - if (!pPrimControl) return; - - Glacier::ZCameraSpace cameraSpace {}; - cameraSpace = pCamera; - - using vmmul_t = void(__fastcall*)(Glacier::Vector3*, Glacier::Vector3*, Glacier::ZMat3x3*); - auto vmmul = (vmmul_t)0x00435F50; - - using v3add_t = void(__fastcall*)(Glacier::ZVector3*,Glacier::ZVector3*); - auto v3add = (v3add_t)0x00428740; - - struct ZHitman3AutoAim_t { - int pad0 { 0 }; - Glacier::ZCAMERA* pCamera { nullptr }; - }; - - Glacier::ZMat3x3 mHeadMat, mPlayerMat; - Glacier::ZVector3 vHeadPos, vPlayerPos; - Glacier::ZVector2 vHeadPos4; - - auto pPlayer = reinterpret_cast(gameData->m_Hitman3); - if (!pPlayer->m_boneModify) return; - - pPlayer->GetRootCenter(&mPlayerMat, &vPlayerPos); - - // Get self bone - auto iHeadBoneIdx = pPlayer->HeadBoneIndex(); - pPlayer->GetBoneMatPos(&mHeadMat, &vHeadPos, iHeadBoneIdx); - - // Envy - ImGui::Begin("Player debug"); - { - ImGui::Text("Head bone index: %u", iHeadBoneIdx); - ImGui::InputFloat3("Head pos : ", &vHeadPos.x); - ImGui::InputFloat2("Head pos4: ", &vHeadPos4.x); - ImGui::InputFloat3("Head mat[0]: ", &mHeadMat.data[0]); - ImGui::InputFloat3("Head mat[1]: ", &mHeadMat.data[3]); - ImGui::InputFloat3("Head mat[2]: ", &mHeadMat.data[6]); - ImGui::Separator(); - ImGui::InputFloat3("Player pos: ", &vPlayerPos.x); - ImGui::InputFloat3("Player mat[0]: ", &mPlayerMat.data[0]); - ImGui::InputFloat3("Player mat[1]: ", &mPlayerMat.data[3]); - ImGui::InputFloat3("Player mat[2]: ", &mPlayerMat.data[6]); - - if (ImGui::Button("Rotate head by 90")) - { - ((void(__fastcall*)(Glacier::ZMat3x3*, int, float, float, float, float))0x00435B40)(&mHeadMat, 0, 90.f, vHeadPos.x, vHeadPos.y, vHeadPos.z); - } - } - ImGui::End(); + // if (!g_pSysInterface || !g_pGameData || !g_pGameData->m_Hitman3 || g_pGameData->m_ActorsPool.IsEmpty()) return; + + // auto pCamera = reinterpret_cast(g_pGameData->m_pMainCamera); + // if (!pCamera || !pCamera->IsActive()) return; + + // auto pD3DDll = Glacier::getInterface(Globals::kD3DDllAddr); + // if (!pD3DDll) return; + + // auto pPrimControl = pD3DDll->m_primControlWintel; + // if (!pPrimControl) return; + + // OLD CODE, Will drop later + // Glacier::ZCameraSpace cameraSpace {}; + // cameraSpace = pCamera; + // using vmmul_t = void(__fastcall*)(Glacier::Vector3*, Glacier::Vector3*, Glacier::ZMat3x3*); + // auto vmmul = (vmmul_t)0x00435F50; + + // using v3add_t = void(__fastcall*)(Glacier::ZVector3*,Glacier::ZVector3*); + // auto v3add = (v3add_t)0x00428740; + + // struct ZHitman3AutoAim_t { + // int pad0 { 0 }; + // Glacier::ZCAMERA* pCamera { nullptr }; + // }; + + // Glacier::ZMat3x3 mHeadMat, mPlayerMat; + // Glacier::ZVector3 vHeadPos, vPlayerPos; + // Glacier::ZVector2 vHeadPos4; + + // if (!g_pGameData->m_Hitman3->m_pBoneModify) return; + + + // pPlayer->GetRootCenter(&mPlayerMat, &vPlayerPos); + + // // Get self bone + // auto iHeadBoneIdx = pPlayer->HeadBoneIndex(); + // pPlayer->GetBoneMatPos(&mHeadMat, &vHeadPos, iHeadBoneIdx); + + // // Envy + // ImGui::Begin("Player debug"); + // { + // ImGui::Text("Head bone index: %u", iHeadBoneIdx); + // ImGui::InputFloat3("Head pos : ", &vHeadPos.x); + // ImGui::InputFloat2("Head pos4: ", &vHeadPos4.x); + // ImGui::InputFloat3("Head mat[0]: ", &mHeadMat.data[0]); + // ImGui::InputFloat3("Head mat[1]: ", &mHeadMat.data[3]); + // ImGui::InputFloat3("Head mat[2]: ", &mHeadMat.data[6]); + // ImGui::Separator(); + // ImGui::InputFloat3("Player pos: ", &vPlayerPos.x); + // ImGui::InputFloat3("Player mat[0]: ", &mPlayerMat.data[0]); + // ImGui::InputFloat3("Player mat[1]: ", &mPlayerMat.data[3]); + // ImGui::InputFloat3("Player mat[2]: ", &mPlayerMat.data[6]); + + // if (ImGui::Button("Rotate head by 90")) + // { + // ((void(__fastcall*)(Glacier::ZMat3x3*, int, float, float, float, float))0x00435B40)(&mHeadMat, 0, 90.f, vHeadPos.x, vHeadPos.y, vHeadPos.z); + // } + // } + // ImGui::End(); } } \ No newline at end of file diff --git a/ReHitman/BloodMoney/source/Delegates/DX9Delegate.cpp b/ReHitman/BloodMoney/source/Delegates/DX9Delegate.cpp index e465a05..68f949f 100644 --- a/ReHitman/BloodMoney/source/Delegates/DX9Delegate.cpp +++ b/ReHitman/BloodMoney/source/Delegates/DX9Delegate.cpp @@ -64,11 +64,11 @@ namespace Hitman::BloodMoney // Register widgets { - Globals::g_pDebugTools->addChild(std::make_shared()); +// Globals::g_pDebugTools->addChild(std::make_shared()); Globals::g_pDebugTools->addChild(std::make_shared()); - Globals::g_pDebugTools->addChild(std::make_shared()); - Globals::g_pDebugTools->addChild(std::make_shared()); - Globals::g_pDebugTools->addChild(std::make_shared()); +// Globals::g_pDebugTools->addChild(std::make_shared()); +// Globals::g_pDebugTools->addChild(std::make_shared()); +// Globals::g_pDebugTools->addChild(std::make_shared()); } // Register gizmos diff --git a/ReHitman/BloodMoney/source/Game/CCheat.cpp b/ReHitman/BloodMoney/source/Game/CCheat.cpp index 6738439..c2d2eda 100644 --- a/ReHitman/BloodMoney/source/Game/CCheat.cpp +++ b/ReHitman/BloodMoney/source/Game/CCheat.cpp @@ -55,7 +55,7 @@ namespace Hitman::BloodMoney { return; } - auto eWeaponType = ZHM3WeaponUpgradeControl::GetWeaponType(pAddedItem->m_baseGeom->entityName); + auto eWeaponType = ZHM3WeaponUpgradeControl::GetWeaponType(pAddedItem->m_baseGeom->m_Name); if (eWeaponType != EWeaponType::EW_UNKNOWN) { //TODO: Add fix for WA-2000 (It's not classified as 'custom' weapon but it is) auto pCustomItem = reinterpret_cast(pAddedItem); pCustomItem->SetSilencerType(ESilencerType::eSilentOver20); // Just for test @@ -72,12 +72,12 @@ namespace Hitman::BloodMoney { Glacier::ZGEOM* pCurrentGeom = nullptr; do { - pCurrentGeom = reinterpret_cast(pCurrentEnt->m_assignedTo); + pCurrentGeom = reinterpret_cast(pCurrentEnt->m_pExtraGeom); auto kZItemTemplate_Id = reinterpret_cast(0x0099BF30); auto kZItemTemplate_Mask = reinterpret_cast(0x0099BF34); const bool isItemTemplate = ((*kZItemTemplate_Mask) & pCurrentGeom->GetObjectId() )== *(kZItemTemplate_Id); - const std::string_view sCurrentItemName { pCurrentEnt->entityName }; + const std::string_view sCurrentItemName { pCurrentEnt->m_Name }; if (sCurrentItemName == sItemName) { if (!isItemTemplate) { @@ -132,12 +132,12 @@ namespace Hitman::BloodMoney { Glacier::ZGEOM* pCurrentGeom = nullptr; do { - pCurrentGeom = reinterpret_cast(pCurrentEnt->m_assignedTo); + pCurrentGeom = reinterpret_cast(pCurrentEnt->m_pExtraGeom); auto kZItemTemplate_Id = reinterpret_cast(0x0099BF30); auto kZItemTemplate_Mask = reinterpret_cast(0x0099BF34); const bool isItemTemplate = ((*kZItemTemplate_Mask) & pCurrentGeom->GetObjectId() )== *(kZItemTemplate_Id); - const std::string_view sCurrentItemName { pCurrentEnt->entityName }; + const std::string_view sCurrentItemName { pCurrentEnt->m_Name }; if (sCurrentItemName == sItemName) { if (!isItemTemplate) { diff --git a/ReHitman/BloodMoney/source/Game/Globals.cpp b/ReHitman/BloodMoney/source/Game/Globals.cpp new file mode 100644 index 0000000..fabfb2e --- /dev/null +++ b/ReHitman/BloodMoney/source/Game/Globals.cpp @@ -0,0 +1,10 @@ +#include + +// Macro to speedup codegen +#define RE_MAKE_GLOBAL(type, name, addr) type*& name = *reinterpret_cast(Hitman::BloodMoney::Globals::addr); + +RE_MAKE_GLOBAL(Glacier::ZSysInterfaceWintel, g_pSysInterface, kSysInterfaceAddr); +RE_MAKE_GLOBAL(Hitman::BloodMoney::ZHM3GameData, g_pGameData, kGameDataAddr); + +// End of globals +#undef RE_MAKE_GLOBAL \ No newline at end of file diff --git a/ReHitman/BloodMoney/source/Game/LevelControls/ZHM3LevelControl.cpp b/ReHitman/BloodMoney/source/Game/LevelControls/ZHM3LevelControl.cpp new file mode 100644 index 0000000..2a322b9 --- /dev/null +++ b/ReHitman/BloodMoney/source/Game/LevelControls/ZHM3LevelControl.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/ReHitman/BloodMoney/source/Game/UI/ZColorSet.cpp b/ReHitman/BloodMoney/source/Game/UI/ZColorSet.cpp index b2531a4..5b719ad 100644 --- a/ReHitman/BloodMoney/source/Game/UI/ZColorSet.cpp +++ b/ReHitman/BloodMoney/source/Game/UI/ZColorSet.cpp @@ -1,16 +1,9 @@ #include -namespace Hitman::BloodMoney { - uint32_t ZColorSet::GetColor(EColorIndex colorIndex) { - switch (colorIndex) { - case EColorIndex::NormalColor: - return m_NormalColor; - case EColorIndex::DisableColor: - return m_DisableColor; - case EColorIndex::FocusColor: - return m_FocusColor; - } - - return 0u; +namespace Hitman::BloodMoney +{ + uint32_t ZColorSet::GetColor(EColorIndex colorIndex) + { + return m_aiColors[colorIndex]; } } \ No newline at end of file diff --git a/ReHitman/BloodMoney/source/Game/UI/ZGUIBase.cpp b/ReHitman/BloodMoney/source/Game/UI/ZGUIBase.cpp index b1dcdf5..89a4db6 100644 --- a/ReHitman/BloodMoney/source/Game/UI/ZGUIBase.cpp +++ b/ReHitman/BloodMoney/source/Game/UI/ZGUIBase.cpp @@ -12,4 +12,9 @@ namespace Hitman::BloodMoney { ((void(__thiscall*)(ZGUIBase*,ZWINGROUP*,Glacier::Vector2*))BMConfigurationService::BMAPI_FunctionAddress_ZGUIBase_GetSize)(this, pGroup, pSize); } } + + void ZGUIBase::GetPos(Glacier::Vector2* pPos) + { + *pPos = m_v2Pos; + } } \ No newline at end of file diff --git a/ReHitman/BloodMoney/source/Game/ZHM3Actor.cpp b/ReHitman/BloodMoney/source/Game/ZHM3Actor.cpp index 7b1d6bc..bca0c0b 100644 --- a/ReHitman/BloodMoney/source/Game/ZHM3Actor.cpp +++ b/ReHitman/BloodMoney/source/Game/ZHM3Actor.cpp @@ -24,4 +24,12 @@ namespace Hitman::BloodMoney (BMConfigurationService::BMAPI_FunctionAddress_ZHM3Actor_ActivateBloodSpurt))(this, pInvDir, pCollisionPos, type); } } + + void ZHM3Actor::InitMapIcon(bool a1) + { + assert(BMConfigurationService::BMAPI_FunctionAddress_ZHM3Actor_InitMapIcon != BMConfigurationService::kNotConfiguredOption); + if (BMConfigurationService::BMAPI_FunctionAddress_ZHM3Actor_InitMapIcon != BMConfigurationService::kNotConfiguredOption) { + ((void(__thiscall*)(Hitman::BloodMoney::ZHM3Actor*, bool))(BMConfigurationService::BMAPI_FunctionAddress_ZHM3Actor_InitMapIcon))(this, a1); + } + } } \ No newline at end of file diff --git a/ReHitman/BloodMoney/source/Game/ZHM3BriefingControl.cpp b/ReHitman/BloodMoney/source/Game/ZHM3BriefingControl.cpp index 07b9e08..12cad3d 100644 --- a/ReHitman/BloodMoney/source/Game/ZHM3BriefingControl.cpp +++ b/ReHitman/BloodMoney/source/Game/ZHM3BriefingControl.cpp @@ -21,7 +21,6 @@ namespace Hitman::BloodMoney { } void ZHM3BriefingControl::StopSpeech() { - if (!m_bIsSpeechPlaying) return; assert(BMConfigurationService::BMAPI_FunctionAddress_ZHM3BriefingControl_StopSpeech != BMConfigurationService::kNotConfiguredOption); if (BMConfigurationService::BMAPI_FunctionAddress_ZHM3BriefingControl_StopSpeech != BMConfigurationService::kNotConfiguredOption) { diff --git a/ReHitman/BloodMoney/source/Game/ZHM3CombineItems.cpp b/ReHitman/BloodMoney/source/Game/ZHM3CombineItems.cpp new file mode 100644 index 0000000..59200d8 --- /dev/null +++ b/ReHitman/BloodMoney/source/Game/ZHM3CombineItems.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/ReHitman/BloodMoney/source/Game/ZKnifeThrower.cpp b/ReHitman/BloodMoney/source/Game/ZKnifeThrower.cpp new file mode 100644 index 0000000..a6f6e8d --- /dev/null +++ b/ReHitman/BloodMoney/source/Game/ZKnifeThrower.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/ReHitman/BloodMoney/source/Game/ZScriptC.cpp b/ReHitman/BloodMoney/source/Game/ZScriptC.cpp new file mode 100644 index 0000000..bdb84b4 --- /dev/null +++ b/ReHitman/BloodMoney/source/Game/ZScriptC.cpp @@ -0,0 +1,23 @@ +#include +#include +#include + +namespace Hitman::BloodMoney +{ + SCRIPTCREATOR* ZScriptC::FindScript(const char* scriptName) { + assert(Glacier::G1ConfigurationService::G1API_FunctionAddress_ZScriptC_FindScript != Glacier::G1ConfigurationService::kNotConfiguredOption); + if (Glacier::G1ConfigurationService::G1API_FunctionAddress_ZScriptC_FindScript != Glacier::G1ConfigurationService::kNotConfiguredOption) { + return ((SCRIPTCREATOR * (__thiscall*)(ZScriptC*, const char*))(Glacier::G1ConfigurationService::G1API_FunctionAddress_ZScriptC_FindScript))(this, scriptName); + } + return 0; + } + + SCRIPTCREATOR* ZScriptC::CreateScript(SCRIPTCREATOR* pScriptCreator) { + assert(Glacier::G1ConfigurationService::G1API_FunctionAddress_ZScriptC_CreateScript != Glacier::G1ConfigurationService::kNotConfiguredOption); + if (Glacier::G1ConfigurationService::G1API_FunctionAddress_ZScriptC_CreateScript != Glacier::G1ConfigurationService::kNotConfiguredOption) { + return ((SCRIPTCREATOR * (__thiscall*)(ZScriptC*, SCRIPTCREATOR*))(Glacier::G1ConfigurationService::G1API_FunctionAddress_ZScriptC_CreateScript))(this, pScriptCreator); + } + + return 0; + } +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/source/Patches/All/EnableCheatsPatch.cpp b/ReHitman/BloodMoney/source/Patches/All/EnableCheatsPatch.cpp index 7342354..d62e1ac 100644 --- a/ReHitman/BloodMoney/source/Patches/All/EnableCheatsPatch.cpp +++ b/ReHitman/BloodMoney/source/Patches/All/EnableCheatsPatch.cpp @@ -53,6 +53,9 @@ namespace Hitman::BloodMoney spdlog::info("CCheat::GiveSome patch applied"); } + // Enable first-person movement in M13 lol + process->writeMemory(0x006C9DE4, { 0xC6, 0x82, 0x4D, 0x10, 0x00, 0x00, 0x01 }); + return BasicPatch::Apply(modules); } diff --git a/ReHitman/BloodMoney/source/Patches/All/FixFuckedLoaderScreens.cpp b/ReHitman/BloodMoney/source/Patches/All/FixFuckedLoaderScreens.cpp new file mode 100644 index 0000000..94dec77 --- /dev/null +++ b/ReHitman/BloodMoney/source/Patches/All/FixFuckedLoaderScreens.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Hitman::BloodMoney +{ + static LARGE_INTEGER g_qpcLastFrame = { 0 }; + static LARGE_INTEGER g_qpcFreq = { 0 }; + + struct FakeLoaderSequence : public ZLoader_Sequence_Wintel_D3D + { + // A "brand new" delta timer calculator + void UpdateLoaderTimer() + { + if (g_qpcFreq.QuadPart == 0) + { + QueryPerformanceFrequency(&g_qpcFreq); + QueryPerformanceCounter(&g_qpcLastFrame); + m_fCurrentTime = 0.0f; + return; + } + + LARGE_INTEGER qpcCurrent; + QueryPerformanceCounter(&qpcCurrent); + + double deltaTime = (double)(qpcCurrent.QuadPart - g_qpcLastFrame.QuadPart) / (double)g_qpcFreq.QuadPart; + g_qpcLastFrame = qpcCurrent; + if (deltaTime > 0.1) + { + deltaTime = 0.016666; + } + + m_fCurrentTime += (float)deltaTime; + } + + void WaitForReady() + { + using IsFinished_t = bool(__thiscall*)(ZLoader_Sequence_Script_Reader*, float); + IsFinished_t IsFinished = (IsFinished_t)0x004679A0; + + while (!IsFinished(pReader, m_fCurrentTime)) + { + std::this_thread::yield(); + } + + g_qpcLastFrame.QuadPart = 0; + } + }; + + bool FixFuckedLoaderScreens::Apply(const ModPack& modules) + { + if (!BasicPatch::Apply(modules)) + { + return false; + } + + if (auto process = modules.process.lock()) + { + // Replace render global sleep from 10us -> 40us + process->writeMemory(0x004AEFA0, { 0x6A, 0x28 }); + + // Replace shit math to my shit math + process->fillMemory(0x004AED99, 0x90, 40); + process->writeMemory(0x004AED99, { 0x89, 0xF9 }); // mov ecx, edi + + m_correctTimeCalcTrampoline = HF::Hook::HookFunction( + process, + 0x004AED99 + 2, + &FakeLoaderSequence::UpdateLoaderTimer, + { + HF::X86::PUSH_AD + }, + { + HF::X86::POP_AD, + // pop esi + 0x5E, + // pop ebx + 0x5B + }); + m_correctTimeCalcTrampoline->setup(); + + // 3. replace in-game logic from Finish_0 to our (before WaitForSingleObject) + // next 16 bytes to NOP + process->fillMemory(0x004AE270, 0x90, 16); + // write first 2 bytes to mov ecx, esi + process->writeMemory(0x004AE270, { 0x89, 0xF1 }); // mov ecx, esi + + // Store jump to our logic + m_newWaitLoopTrampoline = HF::Hook::HookFunction(process, 0x004AE270 + 2, &FakeLoaderSequence::WaitForReady, {}, {}); + m_newWaitLoopTrampoline->setup(); + } + + return true; + } + + void FixFuckedLoaderScreens::Revert(const ModPack& modules) + { + BasicPatch::Revert(modules); + } +} \ No newline at end of file diff --git a/ReHitman/BloodMoney/source/Patches/All/InputDevicesPatches.cpp b/ReHitman/BloodMoney/source/Patches/All/InputDevicesPatches.cpp index 164372a..8e7d8b0 100644 --- a/ReHitman/BloodMoney/source/Patches/All/InputDevicesPatches.cpp +++ b/ReHitman/BloodMoney/source/Patches/All/InputDevicesPatches.cpp @@ -71,13 +71,12 @@ namespace Hitman::BloodMoney static std::unique_ptr> g_sysInputOnUpdateHook = nullptr; } - struct ZMouseWintel { - /// - /// REVERSED DATA [READ ONLY, DO NOT CHANGE THE STRUCTURE] - /// - char pad_0000[44]; //0x0000 - uint32_t m_mouseState; //0x002C - char pad_0030[60]; //0x0030 + struct ZMouseDevice : public Glacier::ZInputDevice + { + }; + + struct ZMouseWintel : public ZMouseDevice + { uint32_t m_directInput; //0x006C uint32_t m_device2; //0x0070 char pad_0074[540]; //0x0074 @@ -89,6 +88,7 @@ namespace Hitman::BloodMoney uint8_t m_midButton; //0x029E char pad_029F[177]; //0x029F }; + static_assert(offsetof(ZMouseWintel, m_directInput) == 0x6C); static int __cdecl GlacierKeyboardHandler(unsigned int key, int mask, void* pData) { // Detect pressed keys and classify 'em @@ -175,9 +175,10 @@ namespace Hitman::BloodMoney * @brief Called by Glacier when engine wants to update input devices */ bool OnUpdate() { - if (m_attachedDevicesCount) { - for (int i = 0; i < m_attachedDevicesCount; i++) { - if (!m_devices[i]) { + if (m_devicecount) { + for (int i = 0; i < m_devicecount; i++) { + if (!m_devices[i]) + { continue; } @@ -189,7 +190,7 @@ namespace Hitman::BloodMoney static bool g_kbHandlerAttached = false; if (!g_kbHandlerAttached) { - int kbDeviceIndex = GetPrimaryDevice(Glacier::EDeviceType::KEYBOARD); + int kbDeviceIndex = GetPrimaryDevice(Glacier::SysInput::EDeviceType::eKEYBOARD_TYPE); g_kbHandlerAttached = InstallHandler(kbDeviceIndex, GlacierKeyboardHandler, (void*)kbDeviceIndex); if (g_kbHandlerAttached) { spdlog::info("Keyboard handler added!"); @@ -205,7 +206,7 @@ namespace Hitman::BloodMoney private: void UpdateMouse() { - auto mouseDevice = reinterpret_cast(GetPrimaryDevicePtr(Glacier::EDeviceType::MOUSE)); + auto mouseDevice = reinterpret_cast(GetPrimaryDevicePtr(Glacier::SysInput::EDeviceType::eMOUSE_TYPE)); if (mouseDevice && Globals::g_pInputDelegate) { Globals::g_pInputDelegate->setMouseKeyState(0, mouseDevice->m_leftButton); diff --git a/ReHitman/BloodMoney/source/Patches/All/RenderScenePatch.cpp b/ReHitman/BloodMoney/source/Patches/All/RenderScenePatch.cpp index b07f0a0..aa0afd6 100644 --- a/ReHitman/BloodMoney/source/Patches/All/RenderScenePatch.cpp +++ b/ReHitman/BloodMoney/source/Patches/All/RenderScenePatch.cpp @@ -29,7 +29,7 @@ namespace Hitman::BloodMoney { return; } - auto pGeom = reinterpret_cast(pEntityLocator->m_assignedTo); + auto pGeom = reinterpret_cast(pEntityLocator->m_pExtraGeom); if (!pGeom) { return; } diff --git a/ReHitman/BloodMoney/source/Patches/All/ZHitman3Patches.cpp b/ReHitman/BloodMoney/source/Patches/All/ZHitman3Patches.cpp index 6f5b36c..3b6ddce 100644 --- a/ReHitman/BloodMoney/source/Patches/All/ZHitman3Patches.cpp +++ b/ReHitman/BloodMoney/source/Patches/All/ZHitman3Patches.cpp @@ -22,6 +22,7 @@ namespace Hitman::BloodMoney namespace Consts { static constexpr std::intptr_t kZHitman3Ctor = 0x00604CF1; + static constexpr std::intptr_t kZHM3GameDataCtor = 0x0069ED01; static constexpr std::intptr_t kZGuardQuarterControllerCtor = 0x00657BC5; static constexpr std::intptr_t kZGuardQuarterControllerDtor = 0x00657349; @@ -36,6 +37,11 @@ namespace Hitman::BloodMoney spdlog::info("ZHitman3 constructed at {:08X}", instance); } + void __stdcall OnZHM3GameDataConstructed(std::intptr_t instance) + { + spdlog::info("ZHM3GameData constructed at {:08X}", instance); + } + void __stdcall OnZGuardQuarterControllerConstructed(ZGuardQuarterController* pInstance) { spdlog::info("ZGuardQuarterController inited at {:08X}", reinterpret_cast(pInstance)); ZGuardQuarterController::g_pCurrentLevelGuardControl = pInstance; diff --git a/ReHitman/BloodMoney/source/Patches/Mods/SkinChanger.cpp b/ReHitman/BloodMoney/source/Patches/Mods/SkinChanger.cpp index 4acbe8f..80dbbff 100644 --- a/ReHitman/BloodMoney/source/Patches/Mods/SkinChanger.cpp +++ b/ReHitman/BloodMoney/source/Patches/Mods/SkinChanger.cpp @@ -36,7 +36,7 @@ namespace Hitman::BloodMoney if (gameData && msg == g_ChangeSuitMSGID) { auto playerGeom = reinterpret_cast(gameData->m_Hitman3); - reinterpret_cast(playerGeom)->CopyGeometryFrom(pSelf->m_baseGeom->m_primitive); + reinterpret_cast(playerGeom)->CopyGeometryFrom(pSelf->m_baseGeom->m_lPrim); reinterpret_cast(playerGeom)->UpdateGeometry(true); ((void(__cdecl*)(Glacier::ZGEOM*, const char*))0x005D3BA0)(pSelf, "Take clothes"); //RemoveCUIAction diff --git a/ReHitman/BloodMoney/source/UI/DebugTools.cpp b/ReHitman/BloodMoney/source/UI/DebugTools.cpp index 077da3e..b7779ff 100644 --- a/ReHitman/BloodMoney/source/UI/DebugTools.cpp +++ b/ReHitman/BloodMoney/source/UI/DebugTools.cpp @@ -1,14 +1,139 @@ #include #include + +#include +#include +#include +#include #include +#include #include +#include +#include +#include +// Items (HM3, not gamebase) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// On level stuff +#include +#include +#include +#include +#include +#include +#include +#include +#include +// Level controls +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// Loader sequence +#include +#include +// UI +#include +#include +#include +#include +#include +#include +// Need move to Glacier +#include +#include +#include +#include +#include +#include +#include // TODO: Move to UI! +#include +#include +#include +#include +#include +// Anim +#include +#include +#include +#include +// Etc #include #include #include #include - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// Materials +#include +// Items (gamebase) +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +// ZSTL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// Vehicles +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -147,9 +272,141 @@ namespace Hitman::BloodMoney ImGui::EndMainMenuBar(); } - if (showInventoryEditor) + showUpgradesEditor(); + } + + void DebugTools::showUpgradesEditor() { + static const char* upgradeNames[] = { + "UT_Dummy", "UT_AmmoACP", "UT_AmmoArmorPiercing", "UT_Ammo127mm", "UT_AmmoMagnum", + "UT_AmmoFlechetteSlugs", "UT_AmmoGaugesSlugs", "UT_AmmoLowVelocity", "UT_Magazine", + "UT_Silencer1", "UT_Silencer2", "UT_LaserSight", "UT_DualAction", "UT_DualActionAuto", + "UT_DoubleCapMag", "UT_FullAuto", "UT_ReloadBoost", "UT_BeltFeeding", "UT_BiPod", + "UT_ScopeType1", "UT_ScopeType2", "UT_ScopeType3", "UT_NightVision", "UT_Lightweight", + "UT_DefaultAmmo", "UT_DefaultNoScope", "UT_DefaultBarrel", "UT_DefaultMagazine", + "UT_RailMount", "UT_CarbonBarrel", "UT_Buttstock", "UT_Suitcase", "UT_DefaultButtStock", + "UT_DefaultGrip", "UT_DefaultHandguard", "UT_DefaultHandle", "UT_DefaultSight", + "UT_BoltAction", "UT_RedDotSight", "UT_ShortBarrel", "UT_PistolGrip", "UT_HandGuard", + "UT_RapidFire", "UT_LongSlide", "UT_ClipX2", "UT_ClipX3", "UT_ClipX4" + }; + + using ZHM3ItemTool_GetHM3ItemTemplateWeapon_t = Hitman::BloodMoney::ZHM3ItemTemplate* (__stdcall*)(Glacier::ZItem*); + using ZHM3ItemTool_IsCustomWeapon_t = bool(__cdecl*)(Hitman::BloodMoney::EHM3ItemType); + using ZHM3ItemTool_GetHM3Type_t = Hitman::BloodMoney::EHM3ItemType(__cdecl*)(Glacier::ZItem*); + using ZHM3ItemWeaponCustom_ClearUpgrades_t = int(__thiscall*)(void*); + using ZHM3ItemWeaponCustom_AddUpgrade_t = int(__thiscall*)(void*, EUpgradeType); + using ZHM3ItemWeaponCustom_ApplyUpgrades_t = void(__thiscall*)(void*, bool); + using ZHM3ItemWeaponCustom_UpdateWeaponPartDrawStatus_t = void(__thiscall*)(void*); + + auto ZHM3ItemTool_GetHM3ItemTemplateWeapon = reinterpret_cast(0x00518D00); + auto ZHM3ItemTool_IsCustomWeapon = reinterpret_cast(0x00649610); + auto ZHM3ItemTool_GetHM3Type = reinterpret_cast(0x0064D190); + auto ZHM3ItemWeaponCustom_ClearUpgrades = reinterpret_cast(0x00650520); + auto ZHM3ItemWeaponCustom_AddUpgrade = reinterpret_cast(0x0064A7C0); + auto ZHM3ItemWeaponCustom_ApplyUpgrades = reinterpret_cast(0x006505E0); + auto ZHM3ItemWeaponCustom_UpdateWeaponPartDrawStatus = reinterpret_cast(0x00650450); + + // Is game ready + auto gameData = Glacier::getInterface(Globals::kGameDataAddr); + if (!gameData || !gameData->m_Hitman3) { return; } + + auto inventory = reinterpret_cast(reinterpret_cast(gameData->m_Hitman3)->FindEvent(Glacier::CInventory::Name)); + if (!inventory) { return; } + + // State + static bool g_bShowInventoryMods = false; + static int selectedWeaponIdx = -1; + static bool selectedUpgrades[UT_NumUpgradeTypes] = { false }; + + auto* reftab = inventory->GetInventoryList(); + + if (reftab && ImGui::Begin("Upgrade editor", &g_bShowInventoryMods)) { -// showInventoryEditorWindow(&showInventoryEditor); + ImGui::Columns(2, "WeaponEditorColumns", true); + + // Left side + ImGui::Text("Custom Weapons:"); + ImGui::Separator(); + + Glacier::ZGEOM* selectedGeom = nullptr; + + for (size_t i = 0; i < reftab->Count(); ++i) + { + auto* geom = Glacier::ZGEOM::RefToPtr(reftab->GetRefNr(i)); + if (!geom) continue; + + auto type = ZHM3ItemTool_GetHM3Type(reinterpret_cast(geom)); + if (!ZHM3ItemTool_IsCustomWeapon(type)) { continue; } + + char label[128]{ '\x00' }; + snprintf(label, sizeof(label), "%s##%d", geom->m_baseGeom->m_Name, static_cast(i)); + + if (ImGui::Selectable(label, selectedWeaponIdx == static_cast(i))) { + selectedWeaponIdx = static_cast(i); + } + + if (selectedWeaponIdx == static_cast(i)) { + selectedGeom = geom; + } + } + + ImGui::NextColumn(); + + // Right side + ImGui::Text("Upgrade Setup:"); + ImGui::Separator(); + + if (selectedGeom != nullptr) + { + static int lastSelectedWeaponIdx = -1; + + if (selectedWeaponIdx != lastSelectedWeaponIdx) + { + memset(selectedUpgrades, 0, sizeof(selectedUpgrades)); + lastSelectedWeaponIdx = selectedWeaponIdx; + } + + ImGui::Text("Weapon: %s", selectedGeom->m_baseGeom->m_Name); + ImGui::Spacing(); + + ImGui::Text("Select upgrades to apply:"); + ImGui::BeginChild("UpgradesListList", ImVec2(0, -40), true); + { + for (int i = 1; i < UT_NumUpgradeTypes; ++i) + { + ImGui::Checkbox(upgradeNames[i], &selectedUpgrades[i]); + } + } + ImGui::EndChild(); + + // Apply changes + if (ImGui::Button("Apply Selected Upgrades", ImVec2(-1, 30))) + { + void* customWeaponInstance = reinterpret_cast(selectedGeom); + + // Clear upgrades + ZHM3ItemWeaponCustom_ClearUpgrades(customWeaponInstance); + + // Apply new upgrades + for (int i = 1; i < UT_NumUpgradeTypes; ++i) + { + if (selectedUpgrades[i]) + { + ZHM3ItemWeaponCustom_AddUpgrade(customWeaponInstance, static_cast(i)); + } + } + + // Update upgrades & view + ZHM3ItemWeaponCustom_ApplyUpgrades(customWeaponInstance, true); + ZHM3ItemWeaponCustom_UpdateWeaponPartDrawStatus(customWeaponInstance); + } + } + else + { + ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "Select a weapon from the left list."); + } + + ImGui::Columns(1); + ImGui::End(); } } } \ No newline at end of file diff --git a/ReHitman/BloodMoney/source/UI/DebugWidget.cpp b/ReHitman/BloodMoney/source/UI/DebugWidget.cpp index 73a40bd..7e090e0 100644 --- a/ReHitman/BloodMoney/source/UI/DebugWidget.cpp +++ b/ReHitman/BloodMoney/source/UI/DebugWidget.cpp @@ -1,4 +1,5 @@ #include +#include #include diff --git a/ReHitman/BloodMoney/source/UI/Widgets/ActorsListWidget.cpp b/ReHitman/BloodMoney/source/UI/Widgets/ActorsListWidget.cpp index 92c8bc8..57d633c 100644 --- a/ReHitman/BloodMoney/source/UI/Widgets/ActorsListWidget.cpp +++ b/ReHitman/BloodMoney/source/UI/Widgets/ActorsListWidget.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include @@ -17,9 +19,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -29,65 +31,16 @@ namespace ImGui { - void Inspector::Draw(const char* id, Glacier::ESuitMask* mask) { - switch (*mask) { - case Glacier::ESuitMask::NoActor: - ImGui::Text("ESuitMask::NoActor"); - break; - case Glacier::ESuitMask::SkinChangerNotSupported: - ImGui::Text("ESuitMask::SkinChangerNotSupported"); - break; - case Glacier::ESuitMask::Nude: - ImGui::Text("ESuitMask::Nude"); - break; - case Glacier::ESuitMask::Invisible: - ImGui::Text("ESuitMask::Invisible"); - break; - case Glacier::ESuitMask::OriginalView: - ImGui::Text("ESuitMask::OriginalView"); - break; - case Glacier::ESuitMask::Agent47_WithoutHeaddress: - ImGui::Text("ESuitMask::Agent47_WithoutHeaddress"); - break; - case Glacier::ESuitMask::Agent47_WithHeaddress: - ImGui::Text("ESuitMask::Agent47_WithHeaddress"); - break; - default: - ImGui::TextColored(ImVec4 { 1.f, 1.f, 0.f, 1.f }, "Unknown value: %d", *mask); - break; - } - } - void Inspector::Draw(const char* id, Hitman::BloodMoney::ZHM3Actor* actor) { - //ImGui::Inspector::Draw("actor.entity", actor->ActorInformation->location); + // Base actor info ImGui::Inspector::Draw("actor.entity", actor->m_baseGeom); ImGui::Separator(); - ImGui::Inspector::Draw("actor.group", actor->m_baseGeom->ParentGroup()->m_baseGeom); - ImGui::Inspector::Draw("Actor boid", actor->m_boid); - ImGui::Text("Group Info: "); - ImGui::Inspector::Draw("ActorGroup", actor->m_baseGeom->ParentGroup()); - ImGui::Inspector::Draw("Actor.PathFollower", reinterpret_cast(actor->FindEvent(Hitman::BloodMoney::ZPathFollower::Name))); - ImGui::Inspector::Draw("Actor.Inventory", reinterpret_cast(actor->FindEvent(Glacier::CInventory::Name))); - ImGui::Inspector::Draw("Actor.SuitMask", &actor->m_suitMask); - - /// ================== - { - auto gameData = Glacier::getInterface(Hitman::BloodMoney::Globals::kGameDataAddr); - if (gameData && actor->m_suitMask != Glacier::ESuitMask::NoActor && ImGui::Button("Swap bodies")) - { - auto actorGeom = reinterpret_cast(actor); - auto playerGeom = reinterpret_cast(gameData->m_Hitman3); - const int actorPrimId = actorGeom->m_baseGeom->m_primitive; - const int playerPrimId = playerGeom->m_baseGeom->m_primitive; + // Another info + ImGui::Text("m_fHitpoints: %f", actor->m_fHitpoints); + ImGui::Text("m_fTension: %f", actor->m_fTension); - reinterpret_cast(actor)->CopyGeometryFrom(playerPrimId); - reinterpret_cast(actor)->UpdateGeometry(true); - - reinterpret_cast(playerGeom)->CopyGeometryFrom(actorPrimId); - reinterpret_cast(playerGeom)->UpdateGeometry(true); - } - } + // Components // ================== { @@ -96,16 +49,64 @@ namespace ImGui using PF4_Path_Clear_t = void(__thiscall*)(std::intptr_t*); auto PF4_Path_Clear = (PF4_Path_Clear_t)0x004D8D00; - PF4_Path_Clear(&actor->m_field534); + PF4_Path_Clear(reinterpret_cast(&actor->m_Path)); actor->PreparePath(); } } + if (auto path = reinterpret_cast(reinterpret_cast(&actor->m_Path)); path && path->m_Size > 1) + { + using ZPlayer_GetCamera_t = Glacier::ZCAMERA* (__thiscall*)(int*); + using GetLocalPoint_t = void(__thiscall*)(Glacier::ZCAMERA* pCamera, Glacier::ZVector3* pInOutPoint); + using Proj2D_t = void(__thiscall*)(Glacier::ZCAMERA* pCamera, Glacier::ZVector2* pOutScreen, Glacier::ZVector3* pInLocalPoint); + + ZPlayer_GetCamera_t ZPlayer_GetCamera = (ZPlayer_GetCamera_t)0x00528AA0; + GetLocalPoint_t GetLocalPoint = (GetLocalPoint_t)0x004E6920; + Proj2D_t Proj2D = (Proj2D_t)0x004E40A0; + + auto gameData = Glacier::getInterface(Hitman::BloodMoney::Globals::kGameDataAddr); + auto cam = ZPlayer_GetCamera((int*)gameData->m_Hitman3); + Glacier::ZMat3x3 camMat; + Glacier::ZVector3 camPos; + cam->GetMatPos(&camMat, &camPos); + + for (int i = 1; i < path->m_Size; ++i) + { + ImVec2 l0, l1; + Glacier::ZVector2 v0, v1; + Glacier::ZVector3 p0, p1; + + path->GetPosition(i - 1, p0); + path->GetPosition(i - 0, p1); + + GetLocalPoint(cam, &p0); + GetLocalPoint(cam, &p1); + + Proj2D(cam, &v0, &p0); + Proj2D(cam, &v1, &p1); + + ImVec2 display_size = ImGui::GetIO().DisplaySize; + float cx = display_size.x * 0.5f; + float cy = display_size.y * 0.5f; + + float custom_scale = 2.0f; + + l0.x = cx + (v0.x * cx * custom_scale); + l0.y = cy + (v0.y * cy * custom_scale); + + l1.x = cx + (v1.x * cx * custom_scale); + l1.y = cy + (v1.y * cy * custom_scale); + + ImGui::GetForegroundDrawList()->AddLine(l0, l1, 0xFF'00'FF'FF, 2.f); + } + } + // =================== { auto gameData = Glacier::getInterface(Hitman::BloodMoney::Globals::kGameDataAddr); - if (gameData && actor->m_suitMask != Glacier::ESuitMask::NoActor && ImGui::Button("Start human shield with")) + // NOTE: Need to check ability to start human shield by another way + if (gameData && ImGui::Button("Start human shield with")) { using StartActionHumanShield_t = void(__thiscall*)(std::intptr_t*, Hitman::BloodMoney::ZHM3Actor*); auto StartActionHumanShield = (StartActionHumanShield_t)0x00600590; @@ -120,8 +121,26 @@ namespace ImGui { actor->Die(); } + + ImGui::SameLine(); } + { + if (ImGui::Button("Knockout")) + { + actor->Knockout(); + } + + ImGui::SameLine(); + } + + { + if (ImGui::Button("Revive")) + { + actor->Revive(); + } + } + // =================== { auto gameData = Glacier::getInterface(Hitman::BloodMoney::Globals::kGameDataAddr); @@ -133,67 +152,74 @@ namespace ImGui actor->SetMoveSpeedMultiplier(15.f); actor->MoveToPosition(&pos, &pos); - spdlog::info("Request to actor '{}' run to {};{};{}", actor->m_baseGeom->entityName, pos.x, pos.y, pos.z); + spdlog::info("Request to actor '{}' run to {};{};{}", actor->m_baseGeom->m_Name, pos.x, pos.y, pos.z); } } // =================== { auto gameData = Glacier::getInterface(Hitman::BloodMoney::Globals::kGameDataAddr); - if (gameData && actor->m_suitMask != Glacier::ESuitMask::NoActor && ImGui::Button("Make clone")) + // TODO: Find another way to check ability of clone op + if (gameData && ImGui::Button("Make clone")) { auto actorOwnerGroup = reinterpret_cast(actor)->m_baseGeom->ParentGroup(); auto actorRootGroup = reinterpret_cast(actorOwnerGroup)->m_baseGeom->ParentGroup(); spdlog::info("Owner: {} / Root: {}", - reinterpret_cast(actorOwnerGroup)->m_baseGeom->entityName, - reinterpret_cast(actorRootGroup)->m_baseGeom->entityName); + reinterpret_cast(actorOwnerGroup)->m_baseGeom->m_Name, + reinterpret_cast(actorRootGroup)->m_baseGeom->m_Name); Glacier::ZMat3x3 ownerMat; Glacier::ZVector3 ownerPos; + spdlog::info("<< GetMatPos"); actorOwnerGroup->GetMatPos(&ownerMat, &ownerPos); + spdlog::info("<< DuplicateInit"); auto duplicateGroup = actorOwnerGroup->DuplicateInit( actorRootGroup, &ownerMat, &ownerPos, - fmt::format("Actor!CloneOf!{}", reinterpret_cast(actorOwnerGroup)->m_baseGeom->entityName).c_str(), + fmt::format("Actor!CloneOf!{}", reinterpret_cast(actorOwnerGroup)->m_baseGeom->m_Name).c_str(), true); - auto clonedActor = reinterpret_cast(reinterpret_cast(duplicateGroup)->FindGeom("Ground", nullptr)); - - clonedActor->m_mapIconType = Hitman::BloodMoney::EActorMapRole::VIP; - using ZHM3Actor_InitMapIconFn = void(__thiscall*)(Hitman::BloodMoney::ZHM3Actor*, bool); - auto ZHM3Actor_InitMapIcon = (ZHM3Actor_InitMapIconFn)0x00637460; - ZHM3Actor_InitMapIcon(clonedActor, true); + spdlog::info("<< FindGeom(Ground)"); + auto clonedActor = reinterpret_cast(reinterpret_cast(duplicateGroup)->FindGeom("Ground", nullptr)); + + spdlog::info("ClonedActor: {:08X}", reinterpret_cast(clonedActor)); + spdlog::info("<< InitMapIcon"); + clonedActor->m_eCharacterType = Hitman::BloodMoney::eCharacterType::eCharacterType_VIP; + clonedActor->InitMapIcon(true); + spdlog::info("<< CopyPoseFrom"); reinterpret_cast(clonedActor)->CopyPoseFrom(reinterpret_cast(actor)); // Add actor to tracking list + spdlog::info("<< pTrackLinkObjects->AddGeom"); auto pTrackLinkObjects = *(Glacier::ZLIST**)0x00972DA8; pTrackLinkObjects->AddGeom(reinterpret_cast(clonedActor)); + spdlog::info("<< EnableIK"); reinterpret_cast(clonedActor)->EnableIK(); + + spdlog::info("<< EnableControls"); reinterpret_cast(clonedActor)->EnableControls(); - ((void(__cdecl*)(Glacier::ZREF, bool))0x006AA2B0)(reinterpret_cast(clonedActor)->GetRef(), true); + // Actorcommunication__Registerradiouser + spdlog::info("<< Will ask for ref"); + auto ref = reinterpret_cast(clonedActor)->GetRef(); + spdlog::info("<< Actorcommunication__Registerradiouser (ref {})", ref); + ((void(__cdecl*)(Glacier::ZREF, int))0x006AA2B0)(reinterpret_cast(clonedActor)->GetRef(), 0); - //clonedActor->SetActorState(Hitman::BloodMoney::ZActor::ACTORSTATE::STATE_0); - clonedActor->SetActorState(Hitman::BloodMoney::ZActor::ACTORSTATE::STATE_1); - //clonedActor->SetActorState(Hitman::BloodMoney::ZActor::ACTORSTATE::STATE_2); - //clonedActor->SetActorState(Hitman::BloodMoney::ZActor::ACTORSTATE::STATE_3); + spdlog::info("<< SetActorState"); + clonedActor->SetActorState(Hitman::BloodMoney::ZActor::ACTORSTATE::ACTORSTATE_SLEEPING); // ----------- PRETTY PRINT SOME INFOS ------------- spdlog::info("TRK: {:08X}", (int)pTrackLinkObjects); spdlog::info("OACT: {:08X}", (int)actor); spdlog::info("Dup: {:08X} / ADup: {:08X}", (int)duplicateGroup, (int)clonedActor); - // ----------- REGISTER ACTOR SOMEWHERE ------------ - clonedActor->SetActorState(((Hitman::BloodMoney::ZActor::ACTORSTATE(__thiscall*)(Hitman::BloodMoney::ZHM3Actor*))0x005029A0)(actor)); - -// clonedActor->m_Mask1 = actor->m_Mask1; -// clonedActor->m_field91C = actor->m_field91C; -// clonedActor->m_fieldA3C = actor->m_fieldA3C; + // Just for debug (copy state from original actor) + clonedActor->SetActorState(((Hitman::BloodMoney::ZActor::ACTORSTATE(__thiscall*)(Hitman::BloodMoney::ZHM3Actor*))0x005029A0)(actor)); // ZActor::GetActorState spdlog::info("Cloned actor ptr is {:08X}", reinterpret_cast(clonedActor)); @@ -202,10 +228,9 @@ namespace ImGui spdlog::info("OACT: {:08X}", (int)actor); spdlog::info("Dup: {:08X} / ADup: {:08X}", (int)duplicateGroup, (int)clonedActor); - Glacier::ZScriptC* pClonedActorScript = nullptr; + Hitman::BloodMoney::ZScriptC* pClonedActorScript = nullptr; Glacier::CInventory* pClonedActorInventory = nullptr; - { int* pDefaultStatus = Glacier::ZEventBase::GetDefaultStatus(); const int oldDefaultStatus = *pDefaultStatus; @@ -215,7 +240,10 @@ namespace ImGui //TODO: Here we need to fix ZGEOM vftable. One method is lost between FindEvent and AddEvent pClonedActorInventory = HF::Hook::VFHook::invoke(clonedActor, 66, "ZGEOM_Inventory"); // Add inventory - pClonedActorScript = HF::Hook::VFHook::invoke(clonedActor, 66, "ZGEOM_ScriptC"); // AddEvent + pClonedActorScript = HF::Hook::VFHook::invoke(clonedActor, 66, "ZGEOM_ScriptC"); // AddEvent + + // And PathFollower + HF::Hook::VFHook::invoke(clonedActor, 66, "ZGEOM_PathFollower"); // AddEvent // And don't forget to restore it back to avoid other issues *pDefaultStatus = oldDefaultStatus; @@ -226,20 +254,22 @@ namespace ImGui } else { spdlog::info("Created & registered ZScriptC: {:08X}", (int)pClonedActorScript); - constexpr const char* psRequiredScriptName = "Alllevels_Armed"; - int foundScript = pClonedActorScript->FindScript(psRequiredScriptName); + static const char* psRequiredScriptName = "Alllevels_Armed"; + auto* foundScript = pClonedActorScript->FindScript(psRequiredScriptName); if (!foundScript) { spdlog::error("Failed to find '{}' script!", psRequiredScriptName); } else { // And then call 'create script' - pClonedActorScript->m_pScriptsTable = pClonedActorScript->CreateScript(foundScript); - spdlog::info("AI script attached ({:08X})", pClonedActorScript->m_pScriptsTable); + spdlog::info("Script found, start attach..."); + + pClonedActorScript->m_pScriptCreator = pClonedActorScript->CreateScript(foundScript); + spdlog::info("AI script attached ({:08X})", (std::intptr_t)(pClonedActorScript->m_pScriptCreator)); // Here we need to call internal methods clonedActor->Activate(true); // Activate - pClonedActorScript->ActivateFrameUpdate(false); + pClonedActorScript->ActivateFrameUpdate(true); //pClonedActorScript->ActivateTimeUpdate(0.0f); pClonedActorScript->RegisterInstance(); @@ -260,17 +290,10 @@ namespace ImGui // And try to register this actor in ZDllSound::ActorRegister auto sysInterface = Glacier::getInterface(Hitman::BloodMoney::Globals::kSysInterfaceAddr); if (sysInterface && sysInterface->m_soundWintelDLL) { + // ZDllSound::ActorRegister ((void(__thiscall*)(int, Glacier::ZGEOM*))0x004C60E0)(sysInterface->m_soundWintelDLL, reinterpret_cast(clonedActor)); spdlog::info("Cloned actor was register in sound subsystem as sound emitter"); } - - // Try to register actor in actor communication network - constexpr auto kRadioChannelId = 3u; - - auto pActorCommunication = Glacier::ZEventBuffer::EventRefToInstance(gameData->m_rActorCommunicationComponentID); - if (pActorCommunication) { - pActorCommunication->RegisterRadioUser(clonedActor->GetRef(), kRadioChannelId); - } } } } @@ -313,12 +336,16 @@ namespace Hitman::BloodMoney //Left side static int selectedIndex = 0; + + // crash fix for level reload + if (selectedIndex >= gameData->m_ActorsPool.m_iSize) + selectedIndex = 0; + ImGui::BeginChild("$leftside", ImVec2(300, 0), true); - for (int actorIndex = 0; actorIndex < gameData->m_ActorsInPoolCount; actorIndex++) + for (int actorIndex = 0; actorIndex < gameData->m_ActorsPool.m_iSize; actorIndex++) { auto entityName = fmt::format("#{:2d} {}", - (actorIndex + 1), - gameData->m_ActorsPool[actorIndex]->m_baseGeom->ParentGroup()->m_baseGeom->entityName); + (actorIndex + 1), gameData->m_ActorsPool.m_Data[actorIndex]->m_baseGeom->ParentGroup()->m_baseGeom->m_Name); if (ImGui::Selectable(entityName.data(), selectedIndex == actorIndex)) { selectedIndex = actorIndex; @@ -328,7 +355,7 @@ namespace Hitman::BloodMoney ImGui::SameLine(); //Right side - Hitman::BloodMoney::ZHM3Actor* currentActor = gameData->m_ActorsPool[selectedIndex]; + Hitman::BloodMoney::ZHM3Actor* currentActor = gameData->m_ActorsPool.m_Data[selectedIndex]; ImGui::BeginGroup(); ImGui::BeginChild("$itemview", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); @@ -349,10 +376,10 @@ namespace Hitman::BloodMoney auto sysInterface = Glacier::getInterface(Globals::kSysInterfaceAddr); if (!sysInterface) { return; } - + auto engineDb = sysInterface->m_engineDataBase; if (!engineDb) { return; } - + auto gameData = Glacier::getInterface(Globals::kGameDataAddr); if (!gameData) @@ -361,7 +388,7 @@ namespace Hitman::BloodMoney return; } - if (!gameData->m_ActorsInPoolCount) + if (!gameData->m_ActorsPool.m_iSize) { DrawErrorDialog("NO ACTORS ON THIS SCENE"); return; diff --git a/ReHitman/BloodMoney/source/UI/Widgets/PlayerTeleportWidget.cpp b/ReHitman/BloodMoney/source/UI/Widgets/PlayerTeleportWidget.cpp index ddbffd7..9e8a96b 100644 --- a/ReHitman/BloodMoney/source/UI/Widgets/PlayerTeleportWidget.cpp +++ b/ReHitman/BloodMoney/source/UI/Widgets/PlayerTeleportWidget.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include @@ -58,7 +58,7 @@ namespace Hitman::BloodMoney { ImGui::Text("Teleport at: "); ImGui::InputFloat3("New position", reinterpret_cast(&teleportAt)); ImGui::SameLine(0.f, 5.f); if (ImGui::Button("TELEPORT")) { - hitman->MoveToMatPos(reinterpret_cast(&hitman->m_baseGeom->m_transform.data), + hitman->MoveToMatPos(reinterpret_cast(&hitman->m_baseGeom->m_mMat.data), reinterpret_cast(&teleportAt)); } @@ -78,7 +78,7 @@ namespace Hitman::BloodMoney { auto pTeleportList = Glacier::ZEventBuffer::EventRefToInstance(rTeleportListREF); if (pTeleportList) { ImGui::Separator(); - auto teleportPoints = reinterpret_cast(pTeleportList->m_geom)->m_entries; + auto teleportPoints = reinterpret_cast(pTeleportList->m_pBaseGeom)->m_entries; const int totalTeleportPoints = teleportPoints->Count(); ImGui::Text("Teleport points (%d):", totalTeleportPoints); diff --git a/ReHitman/BloodMoney/source/UI/Widgets/SandboxWidget.cpp b/ReHitman/BloodMoney/source/UI/Widgets/SandboxWidget.cpp index a0f8e61..b0459fe 100644 --- a/ReHitman/BloodMoney/source/UI/Widgets/SandboxWidget.cpp +++ b/ReHitman/BloodMoney/source/UI/Widgets/SandboxWidget.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include @@ -97,21 +97,21 @@ namespace Hitman::BloodMoney ImGui::Begin("Test script"); if (ImGui::Button("Try to dump few prims")) { - spdlog::info("Hitman prim {:08X}", (int)renderDll->m_primControlWintel->GetPrimData(reinterpret_cast(gameData->m_Hitman3)->m_baseGeom->m_primitive)); - spdlog::info("Actor[0] prim {:08X}", (int)renderDll->m_primControlWintel->GetPrimData(gameData->m_ActorsPool[0]->m_baseGeom->m_primitive)); - spdlog::info("Actor[1] prim {:08X}", (int)renderDll->m_primControlWintel->GetPrimData(gameData->m_ActorsPool[1]->m_baseGeom->m_primitive)); + spdlog::info("Hitman prim {:08X}", (int)renderDll->m_primControlWintel->GetPrimData(reinterpret_cast(gameData->m_Hitman3)->m_baseGeom->m_lPrim)); + spdlog::info("Actor[0] prim {:08X}", (int)renderDll->m_primControlWintel->GetPrimData(gameData->m_ActorsPool[0]->m_baseGeom->m_lPrim)); + spdlog::info("Actor[1] prim {:08X}", (int)renderDll->m_primControlWintel->GetPrimData(gameData->m_ActorsPool[1]->m_baseGeom->m_lPrim)); char buffer[512] { 0 }; using GetPrimStats_t = int(__thiscall*)(int, char*, int, int); auto GetPrimStats = (GetPrimStats_t)0x00487740; - auto r = GetPrimStats((int)renderDll->m_primControlWintel, &buffer[0], 511, reinterpret_cast(gameData->m_Hitman3)->m_baseGeom->m_primitive); + auto r = GetPrimStats((int)renderDll->m_primControlWintel, &buffer[0], 511, reinterpret_cast(gameData->m_Hitman3)->m_baseGeom->m_lPrim); spdlog::info("R: {:08X}| {}", r, buffer); std::memset(&buffer[0], 0x0, 512); - for (int i = 0; i < gameData->m_ActorsInPoolCount; i++) { - GetPrimStats((int)renderDll->m_primControlWintel, &buffer[0], 511, gameData->m_ActorsPool[i]->m_baseGeom->m_primitive); + for (int i = 0; i < gameData->m_ActorsPool.m_iSize; i++) { + GetPrimStats((int)renderDll->m_primControlWintel, &buffer[0], 511, gameData->m_ActorsPool[i]->m_baseGeom->m_lPrim); spdlog::info("Actor[{}]: {}", i, buffer); std::memset(&buffer[0], 0x0, 512); } @@ -187,9 +187,9 @@ namespace Hitman::BloodMoney Glacier::ZGEOM* pCurrentGeom = nullptr; do { - pCurrentGeom = reinterpret_cast(pCurrentEnt->m_assignedTo); + pCurrentGeom = pCurrentEnt->m_pExtraGeom; - const bool isAcceptable = (sEntityName.empty() ? true : (std::string_view { pCurrentEnt->entityName } == sEntityName)) && (((*pMask) & pCurrentGeom->GetObjectId()) == *(pId)); + const bool isAcceptable = (sEntityName.empty() ? true : (std::string_view { pCurrentEnt->m_Name } == sEntityName)) && (((*pMask) & pCurrentGeom->GetObjectId()) == *(pId)); if (isAcceptable) { result.emplace_back(pCurrentGeom); } @@ -223,13 +223,11 @@ namespace Hitman::BloodMoney auto pGun = reinterpret_cast(pGunItem); - spdlog::info("PWPNO: {:08X}", reinterpret_cast(pGun->GetItemTemplate())->m_pWeaponOperations); - - reinterpret_cast(pGun->GetItemTemplate())->m_pWeaponOperations = Glacier::EWeaponOperation::WO_FULLAUTO; + reinterpret_cast(pGun->GetItemTemplate())->m_WeaponOperations = Glacier::EWeaponOperation::WO_FULLAUTO; //spdlog::info("GT: {:08X}", reinterpret_cast(pGun->GetItemTemplate())->m_weaponType); - reinterpret_cast(pGun->GetItemTemplate())->m_weaponType = 0; + reinterpret_cast(pGun->GetItemTemplate())->m_eWeaponType = Glacier::WEAPONTYPE::WT_PISTOL; - pGun->m_nextOperation = Glacier::EWeaponOperation::WO_FULLAUTO; + pGun->m_eWeaponOperation = Glacier::EWeaponOperation::WO_FULLAUTO; pGun->SetProjectilesInMagazine(999); } @@ -252,7 +250,7 @@ namespace Hitman::BloodMoney if (ImGui::Button("T6")) { gameData->m_OSD->m_field8F0 = 6; } if (ImGui::Button("DEBUG")) { - spdlog::info("AUX: {:08X}", gameData->m_OSD->m_pHealthFrame); + spdlog::info("AUX: {:08X}", reinterpret_cast(gameData->m_OSD->m_pHealthFrame)); } if (ImGui::Button("Toggle AIM")) { @@ -284,7 +282,7 @@ namespace Hitman::BloodMoney auto pPrimControl = pD3DDll->m_primControlWintel; auto pActor = gameData->m_ActorsPool[0]; - const int iBonesCount = HF::Hook::VFHook::invoke(pPrimControl, 41, pActor->m_baseGeom->m_primitive); + const int iBonesCount = HF::Hook::VFHook::invoke(pPrimControl, 41, pActor->m_baseGeom->m_lPrim); spdlog::info("Bones count: {}", iBonesCount); for (int boneIx = 0; boneIx < iBonesCount; boneIx++) { @@ -308,139 +306,26 @@ namespace Hitman::BloodMoney // ((void(__thiscall*)(Hitman::BloodMoney::ZHM3LevelControl*))0x006BF540)(gameData->m_LevelControl); // } - if (ImGui::Button("Test extract vars")) { - auto& ccom = *engineDb->GetSceneCom(); - Glacier::REFTAB* ccomVars = &engineDb->GetSceneCom()->m_variables; - - for (int i = 0; i < ccomVars->Count(); i++) { - auto pEnt = reinterpret_cast(ccomVars->operator[](i)); - const char* sEntName = pEnt->GetKey(); - std::intptr_t iValue = pEnt->GetValue(); - - switch (pEnt->m_pTypeInfo->m_eKind) { - case Glacier::CCom::Ent::TypeInfo::EKind::Bool: - spdlog::info("[{}] '{}' = {}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::Char: - spdlog::info("[{}] '{}' = {}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::Long: - spdlog::info("[{}] '{}' = {}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::Float32: - spdlog::info("[{}] '{}' = {}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::Real: - spdlog::info("[{}] '{}' = {:X} (REAL)", i, sEntName, iValue); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::P: - spdlog::info("[{}] '{}' = {:X}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::Vec3: - spdlog::info("[{}] '{}' = VEC3? {:X}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::Vec3F: - spdlog::info("[{}] '{}' = VEC3F? {:X}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::Mat33: - spdlog::info("[{}] '{}' = MAT3x3? {:X}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::Mat33F: - spdlog::info("[{}] '{}' = MAT3x3F? {:X}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::Str: - spdlog::info("[{}] '{}' = {}", i, sEntName, reinterpret_cast(&iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::Blk: - spdlog::info("[{}] '{}' = BLK? {:X}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::File: - spdlog::info("[{}] '{}' = FILE? {:X}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::Data: - spdlog::info("[{}] '{}' = DATA? {:X}", i, sEntName, static_cast(iValue)); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::GREF: - spdlog::info("[{}] '{}' = {:8X} (GEOM REF)", i, sEntName, reinterpret_cast(Glacier::ZGEOM::RefToPtr(iValue))); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::GRFT: - spdlog::info("[{}] '{}' = {:8X} (REF TAB)", i, sEntName, reinterpret_cast(Glacier::ZGEOM::RefToPtr(iValue))); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::ZMSG: - spdlog::info("[{}] '{}' = {} (ZMSG)", i, sEntName, iValue); - break; - case Glacier::CCom::Ent::TypeInfo::EKind::SREF: - spdlog::info("[{}] '{}' = {:X} (SREF?)", i, sEntName, iValue); - break; - default: - spdlog::info("[{}] '{}' = {:8X}, got type mask: '{:4X}'", i, sEntName, reinterpret_cast(pEnt), pEnt->m_pTypeInfo->m_eKind); - break; - } - } - } - - if (gameData->m_Hitman3 && ImGui::Begin("Camera offset & focus demo")) - { - auto pCamera = reinterpret_cast(*reinterpret_cast(reinterpret_cast(gameData->m_Hitman3) + 0xB50)); - if (pCamera) { - ImGui::Text("Common"); - - if (pCamera->m_geom) { - if (ImGui::Button("Set")) { - reinterpret_cast(pCamera->m_geom)->m_field1C |= 0x1000000u; - } - ImGui::SameLine(0.f, 5.f); - if (ImGui::Button("UnSet")) { - reinterpret_cast(pCamera->m_geom)->m_field1C &= ~0x1000000u; - } - } - - ImGui::Checkbox("IsFreeCam", &pCamera->m_bIsFreeCam); - ImGui::Checkbox("IsActive", &pCamera->m_bIsActive); - ImGui::Checkbox("IsEnabled", &pCamera->m_bEnabled); - - ImGui::InputFloat3("m_vPos", &pCamera->m_vPos.x); - ImGui::InputFloat3("m_vPoseOffset", &pCamera->m_vPoseOffset.x); - ImGui::InputFloat3("m_vCurrentLookAtPoint", &pCamera->m_vCurrentLookAtPoint.x); - - ImGui::DragFloat("m_fAngleYaw", &pCamera->m_fAngleYaw, 0.5f, 0.f, 360.f); - ImGui::DragFloat("m_fAnglePitch", &pCamera->m_fAnglePitch, 0.5f, 0.f, 360.f); - ImGui::DragFloat("m_fAngleRoll", &pCamera->m_fAngleRoll, 0.5f, 0.f, 360.f); - - if (pCamera->m_pCameraConsole) - { - ImGui::Separator(); - - ImGui::InputFloat3("m_pCameraConsole->m_vFocalPoint", &pCamera->m_pCameraConsole->m_vFocalPoint.x); - ImGui::InputFloat3("m_pCameraConsole->m_vField17C", &pCamera->m_pCameraConsole->m_vField17C.x); - } - } else { - ImGui::TextColored(ImVec4 { 1.f, 1.f, 0.f, 1.f }, "No camera instance!"); - } - - ImGui::End(); - } - - if (gameData->m_OSD && gameData->m_OSD->m_pCheatMenu && ImGui::Begin("Cheat Menu Editor Demo")) { - if (ImGui::Button("Add menu entry")) { - Glacier::REFTAB* pEntries = &gameData->m_OSD->m_pCheatMenu->m_options; - - auto onZombieModActivation = []() { - auto gameData = Glacier::getInterface(Globals::kGameDataAddr); - if (gameData && gameData->m_LevelControl) - { - gameData->m_LevelControl->Command(0x952, nullptr); - } - }; - - auto ent = reinterpret_cast(pEntries->Add(0)); - ent->pName = "Run Zombie Mode"; - ent->eType = ZCheatMenu::ECheatMenuEntryType::MENU_TOGGLE_CALLABLE_OPTION; - ent->uOption.pFunction = onZombieModActivation; - } - - ImGui::End(); - } + // if (gameData->m_OSD && gameData->m_OSD->m_pCheatsMenu && ImGui::Begin("Cheat Menu Editor Demo")) { + // if (ImGui::Button("Add menu entry")) { + // Glacier::REFTAB* pEntries = &gameData->m_OSD->m_pCheatsMenu->m_rtCommands; + + // auto onZombieModActivation = []() { + // auto gameData = Glacier::getInterface(Globals::kGameDataAddr); + // if (gameData && gameData->m_LevelControl) + // { + // gameData->m_LevelControl->Command(0x952, nullptr); + // } + // }; + + // auto ent = reinterpret_cast(pEntries->Add(0)); + // ent->pName = "Run Zombie Mode"; + // ent->eType = ZCheatMenu::ECheatMenuEntryType::MENU_TOGGLE_CALLABLE_OPTION; + // ent->uOption.pFunction = onZombieModActivation; + // } + + // ImGui::End(); + // } ImGui::End(); } diff --git a/ReHitman/BloodMoney/source/UI/Widgets/SceneViewer.cpp b/ReHitman/BloodMoney/source/UI/Widgets/SceneViewer.cpp index 4d13442..17c451f 100644 --- a/ReHitman/BloodMoney/source/UI/Widgets/SceneViewer.cpp +++ b/ReHitman/BloodMoney/source/UI/Widgets/SceneViewer.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -33,29 +34,29 @@ namespace Hitman::BloodMoney { if (!currentGroup) return; - Glacier::ZEntityLocator* currentEntity = currentGroup->m_pEntity0; + Glacier::ZEntityLocator* currentEntity = currentGroup->m_pGroupFirst; while (currentEntity) { - auto assignedTo = reinterpret_cast(currentEntity->m_assignedTo); + auto assignedTo = reinterpret_cast(currentEntity->m_pExtraGeom); if (!assignedTo) { currentEntity = currentEntity->Next(); continue; } - ImGui::PushID(currentEntity->m_id); + ImGui::PushID(reinterpret_cast(currentEntity->m_pDynId)); - auto classInfo = assignedTo->GetOldClassInfo(); + Glacier::ZGEOMCLASSINFO* classInfo = assignedTo->GetOldClassInfo(); std::string_view type = "N/A"; std::string_view parent = "N/A"; - if (classInfo) { type = classInfo->ComplexTypeName; } + if (classInfo) { type = classInfo->m_szClassInfoName; } if (Glacier::ZCast::IsBasedOn(assignedTo)) { auto childGroup = reinterpret_cast(assignedTo); if (!childGroup) { ImGui::TextColored(ImVec4{1.f, 0.f, 0.f, 1.f}, "Bad group pointer!"); } else { - if (ImGui::TreeNode(fmt::format("Group \"{}\" (type: {} of {}, ID: {:08X})", currentEntity->entityName, type, parent, assignedTo->GetRef()).c_str())) { + if (ImGui::TreeNode(fmt::format("Group \"{}\" (type: {} of {}, ID: {:08X})", currentEntity->m_Name, type, parent, assignedTo->GetRef()).c_str())) { ImGui::Inspector::Draw("NONE", assignedTo->m_baseGeom); ImGui::Separator(); PrepareGroup(childGroup); @@ -64,25 +65,25 @@ namespace Hitman::BloodMoney } } else if (Glacier::ZCast::IsBasedOn(assignedTo)) { - if (ImGui::TreeNode(fmt::format("Actor \"{}\" (type: {} of {}, ID: {:08X})", currentEntity->entityName, type, parent, assignedTo->GetRef()).c_str())) { + if (ImGui::TreeNode(fmt::format("Actor \"{}\" (type: {} of {}, ID: {:08X})", currentEntity->m_Name, type, parent, assignedTo->GetRef()).c_str())) { ImGui::Inspector::Draw("NONE", reinterpret_cast(assignedTo)); ImGui::TreePop(); } } else if (Glacier::ZCast::IsBasedOn(assignedTo)) { - if (ImGui::TreeNode(fmt::format("ZCamera \"{}\" (type: {} of {}, ID: {:08X})", currentEntity->entityName, type, parent, assignedTo->GetRef()).c_str())) { + if (ImGui::TreeNode(fmt::format("ZCamera \"{}\" (type: {} of {}, ID: {:08X})", currentEntity->m_Name, type, parent, assignedTo->GetRef()).c_str())) { ImGui::Inspector::Draw("None", reinterpret_cast(assignedTo)); ImGui::TreePop(); } } else if (Glacier::ZCast::IsBasedOn(assignedTo)) { - if (ImGui::TreeNode(fmt::format("ZSoundObject \"{}\" (type: {} of {}, ID: {:08X})", currentEntity->entityName, type, parent, assignedTo->GetRef()).c_str())) { + if (ImGui::TreeNode(fmt::format("ZSoundObject \"{}\" (type: {} of {}, ID: {:08X})", currentEntity->m_Name, type, parent, assignedTo->GetRef()).c_str())) { ImGui::Inspector::Draw("None", reinterpret_cast(assignedTo)); ImGui::TreePop(); } } else { - if (ImGui::TreeNode(fmt::format("Entity \"{}\" (type: {} of {}, type ptr: {:08X}, ID: {:08X})", currentEntity->entityName, type, parent, (int)classInfo, assignedTo->GetRef()).c_str())) { + if (ImGui::TreeNode(fmt::format("Entity \"{}\" (type: {} of {}, type ptr: {:08X}, ID: {:08X})", currentEntity->m_Name, type, parent, (int)classInfo, assignedTo->GetRef()).c_str())) { ImGui::Inspector::Draw("NONE", currentEntity); ImGui::TreePop(); } @@ -109,7 +110,7 @@ namespace Hitman::BloodMoney ImGui::Text("Scene Inspector"); ImGui::Separator(); - PrepareGroup(engineDb->m_root); + PrepareGroup(engineDb->m_pRoot); ImGui::End(); } diff --git a/ReHitman/CMakeLists.txt b/ReHitman/CMakeLists.txt index 6f5e58c..398c8be 100644 --- a/ReHitman/CMakeLists.txt +++ b/ReHitman/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.16) +cmake_minimum_required(VERSION 4.0) project(ReHitman) set(CMAKE_CXX_STANDARD 20) diff --git a/ReHitman/Client/CMakeLists.txt b/ReHitman/Client/CMakeLists.txt index 53060c7..567d4f5 100644 --- a/ReHitman/Client/CMakeLists.txt +++ b/ReHitman/Client/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.16) +cmake_minimum_required(VERSION 4.0) project(Client) set(CMAKE_CXX_STANDARD 20) diff --git a/ReHitman/DLL/source/ReHitman.cpp b/ReHitman/DLL/source/ReHitman.cpp index d3e3edc..dd01469 100644 --- a/ReHitman/DLL/source/ReHitman.cpp +++ b/ReHitman/DLL/source/ReHitman.cpp @@ -56,7 +56,14 @@ namespace ReHitman int Core::EntryPoint(const void*) { +# ifndef NDEBUG + // TODO: This section is restricted to DEBUG builds only. + // Allocating a console window here introduces severe stutters/deadlocks, + // completely breaking the gameplay experience and ruining the "FixFuckedLoaderScreens" patch. + // This will be refactored and redesigned in the future. ReHitman::DebugConsole::Create("ReHitman | Developer Console"); +# endif + ReHitman::Logger::Setup(); CrashHandlerReporter crashHandlerReporter; diff --git a/ReHitman/Glacier/CMakeLists.txt b/ReHitman/Glacier/CMakeLists.txt index 03045e7..f1a4762 100644 --- a/ReHitman/Glacier/CMakeLists.txt +++ b/ReHitman/Glacier/CMakeLists.txt @@ -1,11 +1,20 @@ -cmake_minimum_required(VERSION 3.16) +cmake_minimum_required(VERSION 4.0) project(BloodMoney) set(CMAKE_CXX_STANDARD 20) -file(GLOB_RECURSE GLACIER_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp) +file(GLOB_RECURSE GLACIER_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/*.h) +# Game target with normal allocators add_library(Glacier STATIC ${GLACIER_SOURCES}) add_library(G1::Core ALIAS Glacier) target_include_directories(Glacier PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_link_libraries(Glacier PUBLIC HF::Core) -target_link_libraries(Glacier PUBLIC HF::Core) \ No newline at end of file +# Target for testing (STL allocators, no extra deps to game instance) +add_library(GlacierTest STATIC ${GLACIER_SOURCES}) +add_library(G1::TestCore ALIAS GlacierTest) +target_include_directories(GlacierTest PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_link_libraries(GlacierTest PUBLIC HF::Core) +target_compile_definitions(GlacierTest PUBLIC REHITMAN_TESTS) + +add_subdirectory(Tests) \ No newline at end of file diff --git a/ReHitman/Glacier/Tests/CMakeLists.txt b/ReHitman/Glacier/Tests/CMakeLists.txt new file mode 100644 index 0000000..76ef26b --- /dev/null +++ b/ReHitman/Glacier/Tests/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 4.0) +project(BloodMoney) +set(CMAKE_CXX_STANDARD 20) + +enable_testing() +file(GLOB_RECURSE GLACIER_TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/*.h) + +add_executable(GlacierTests ${GLACIER_TEST_SOURCES}) +target_include_directories(GlacierTests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) + +target_link_libraries(GlacierTests PUBLIC G1::TestCore gtest gtest_main) \ No newline at end of file diff --git a/ReHitman/Glacier/Tests/include/Tests/G1.h b/ReHitman/Glacier/Tests/include/Tests/G1.h new file mode 100644 index 0000000..e69de29 diff --git a/ReHitman/Glacier/Tests/source/ALLOCREF_Tests.cpp b/ReHitman/Glacier/Tests/source/ALLOCREF_Tests.cpp new file mode 100644 index 0000000..ee7a639 --- /dev/null +++ b/ReHitman/Glacier/Tests/source/ALLOCREF_Tests.cpp @@ -0,0 +1,152 @@ +#include +#include + +#include +#include + +using namespace Glacier; + + +TEST(ALLOCREF_Tests, InitializationAndInitialState) +{ + Glacier::ALLOCREF pool(16, 8); + + EXPECT_EQ(pool.m_lRefShift, 16); + EXPECT_EQ(pool.m_lRefAnd, 7); + EXPECT_EQ(pool.m_lActRefNr, 0); + EXPECT_EQ(pool.GetNrActiveRefs(), 0); + + unsigned int* usedRefs = pool.GetUsedRefs(); + ASSERT_NE(usedRefs, nullptr); + for (int i = 0; i < 8; ++i) + { + EXPECT_EQ(usedRefs[i], 1 << 16); + } +} + +TEST(ALLOCREF_Tests, SequentialNewRefAllocation) +{ + Glacier::ALLOCREF pool(16, 4); + + Glacier::ZREF ref0 = pool.NewRef(); + + EXPECT_EQ(ref0, 0x00010000); + EXPECT_EQ(pool.GetNrActiveRefs(), 1); + EXPECT_TRUE(pool.CheckRefActive(ref0)); + + Glacier::ZREF ref1 = pool.NewRef(); + + EXPECT_EQ(ref1, 0x00010001); + EXPECT_EQ(pool.GetNrActiveRefs(), 2); + EXPECT_TRUE(pool.CheckRefActive(ref1)); + + EXPECT_FALSE(pool.CheckRefActive(0x00020002)); +} + +TEST(ALLOCREF_Tests, FreeRefAndActivityChecks) +{ + Glacier::ALLOCREF pool(16, 4); + + Glacier::ZREF ref0 = pool.NewRef(); + Glacier::ZREF ref1 = pool.NewRef(); + + EXPECT_TRUE(pool.FreeRef(ref0)); + EXPECT_EQ(pool.GetNrActiveRefs(), 1); + + EXPECT_FALSE(pool.CheckRefActive(ref0)); + + EXPECT_FALSE(pool.FreeRef(ref0)); + + EXPECT_FALSE(pool.FreeRef(0x99999999)); +} + +TEST(ALLOCREF_Tests, RefRecyclingWithGenerationIncrement) +{ + Glacier::ALLOCREF pool(16, 4); + + Glacier::ZREF ref0 = pool.NewRef(); + Glacier::ZREF ref1 = pool.NewRef(); + + EXPECT_EQ(ref0, 0x00010000); + + EXPECT_TRUE(pool.FreeRef(ref0)); + + Glacier::ZREF recycledRef0 = pool.NewRef(); + + EXPECT_EQ(recycledRef0, 0x00020000); + EXPECT_TRUE(pool.CheckRefActive(recycledRef0)); + + EXPECT_FALSE(pool.CheckRefActive(ref0)); +} + +TEST(ALLOCREF_Tests, GetActiveRefsPopulatesReftab) +{ + Glacier::ALLOCREF pool(16, 4); + + Glacier::ZREF r0 = pool.NewRef(); + Glacier::ZREF r1 = pool.NewRef(); + Glacier::ZREF r2 = pool.NewRef(); + + pool.FreeRef(r1); + + Glacier::REFTAB* activeTable = Glacier::REFTAB::MakeReftab(10, 0); + + uint32_t activeCount = pool.GetActiveRefs(activeTable); + EXPECT_EQ(activeCount, 2); + EXPECT_EQ(activeTable->Count(), 2); + + std::vector collectedRefs; + Glacier::RefRun it; + activeTable->RunInitNxtRef(&it); + for (uint32_t val = activeTable->RunNxtRef(&it); it; val = activeTable->RunNxtRef(&it)) + { + collectedRefs.push_back(val); + } + + EXPECT_EQ(collectedRefs.size(), 2); + + EXPECT_EQ(collectedRefs[0], r0); + EXPECT_EQ(collectedRefs[1], r2); + + Glacier::REFTAB::DeleteReftab(activeTable); +} + +TEST(ALLOCREF_Tests, OutOfPoolTriggersAssert) +{ + Glacier::ALLOCREF pool(16, 2); + + pool.NewRef(); + pool.NewRef(); + + EXPECT_THROW(pool.NewRef(), std::runtime_error); +} + +TEST(ALLOCREF_Tests, StateRestorationViaSetters) +{ + Glacier::ALLOCREF pool(16, 4); + + std::vector customUsedRefs = + { + 0x000A0000, + 0x000C0000, + 0x000C0000, + 0x000E0000 + }; + pool.SetUsedRefs(customUsedRefs.data(), 4); + + Glacier::REFTAB* fakeFreeStack = Glacier::REFTAB::MakeReftab(10, 0); + fakeFreeStack->Add(2); + fakeFreeStack->Add(4); + + pool.SetRefStack(fakeFreeStack); + pool.m_lActRefNr = 4; + + EXPECT_FALSE(pool.CheckRefActive(0x000B0001)); + EXPECT_TRUE(pool.CheckRefActive(0x000A0000)); + + Glacier::ZREF recycled = pool.NewRef(); + + EXPECT_EQ(recycled, 0x000C0001); + + Glacier::REFTAB::DeleteReftab(fakeFreeStack); +} \ No newline at end of file diff --git a/ReHitman/Glacier/Tests/source/CMemPool_Tests.cpp b/ReHitman/Glacier/Tests/source/CMemPool_Tests.cpp new file mode 100644 index 0000000..413acd1 --- /dev/null +++ b/ReHitman/Glacier/Tests/source/CMemPool_Tests.cpp @@ -0,0 +1,205 @@ +#include +#include + +#include +#include + +using namespace Glacier; + +namespace +{ + static_assert(sizeof(CMemPool) == 0x18); +} + +TEST(CMemPool, DefaultConstructsEmpty) +{ + CMemPool pool; + + EXPECT_EQ(pool.m_pxPool, nullptr); + EXPECT_EQ(pool.m_pAllocTable, nullptr); + EXPECT_EQ(pool.m_iEntries, 0); + EXPECT_EQ(pool.m_iBlockSize, 0); + EXPECT_EQ(pool.m_iNumAlloc, 0); + EXPECT_FALSE(pool.m_bOwnPool); +} + +TEST(CMemPool, InitAllocatesOwnedPoolAndRoundsBlockSizeToAlignment) +{ + CMemPool pool; + + pool.Init(5, 3, 4); + + EXPECT_NE(pool.m_pxPool, nullptr); + EXPECT_NE(pool.m_pAllocTable, nullptr); + EXPECT_EQ(pool.m_iEntries, 3); + EXPECT_EQ(pool.m_iBlockSize, 8); + EXPECT_EQ(pool.m_iNumAlloc, 0); + EXPECT_TRUE(pool.m_bOwnPool); + EXPECT_EQ(pool.m_pAllocTable[0], 0u); + EXPECT_EQ(pool.m_pAllocTable[1], 1u); + EXPECT_EQ(pool.m_pAllocTable[2], 2u); +} + +TEST(CMemPool, AllocReturnsSequentialBlocksUntilExhausted) +{ + CMemPool pool; + pool.Init(5, 3, 4); + + void* first = pool.Alloc(); + void* second = pool.Alloc(); + void* third = pool.Alloc(); + void* exhausted = pool.Alloc(); + + ASSERT_NE(first, nullptr); + ASSERT_NE(second, nullptr); + ASSERT_NE(third, nullptr); + EXPECT_EQ(exhausted, nullptr); + EXPECT_EQ(pool.m_iNumAlloc, 3); + EXPECT_EQ(static_cast(second) - static_cast(first), pool.m_iBlockSize); + EXPECT_EQ(static_cast(third) - static_cast(second), pool.m_iBlockSize); +} + +TEST(CMemPool, AllocWithIndexReportsBlockIndexAndExhaustion) +{ + CMemPool pool; + pool.Init(4, 2, 4); + + int firstIndex = -99; + int secondIndex = -99; + int exhaustedIndex = -99; + + void* first = pool.Alloc(&firstIndex); + void* second = pool.Alloc(&secondIndex); + void* exhausted = pool.Alloc(&exhaustedIndex); + + EXPECT_NE(first, nullptr); + EXPECT_NE(second, nullptr); + EXPECT_EQ(exhausted, nullptr); + EXPECT_EQ(firstIndex, 0); + EXPECT_EQ(secondIndex, 1); + EXPECT_EQ(exhaustedIndex, -1); + EXPECT_EQ(pool.Alloc(nullptr), nullptr); +} + +TEST(CMemPool, DeAllocReusesReleasedBlockFirst) +{ + CMemPool pool; + pool.Init(4, 3, 4); + + void* first = pool.Alloc(); + void* second = pool.Alloc(); + void* third = pool.Alloc(); + + ASSERT_NE(first, nullptr); + ASSERT_NE(second, nullptr); + ASSERT_NE(third, nullptr); + + pool.DeAlloc(second); + + EXPECT_EQ(pool.m_iNumAlloc, 2); + EXPECT_EQ(pool.m_pAllocTable[2], 1u); + EXPECT_EQ(pool.Alloc(), second); + EXPECT_EQ(pool.m_iNumAlloc, 3); +} + +TEST(CMemPool, MultipleDeAllocationsAreReusedInLifoOrder) +{ + CMemPool pool; + pool.Init(4, 4, 4); + + void* first = pool.Alloc(); + void* second = pool.Alloc(); + void* third = pool.Alloc(); + void* fourth = pool.Alloc(); + + ASSERT_NE(first, nullptr); + ASSERT_NE(second, nullptr); + ASSERT_NE(third, nullptr); + ASSERT_NE(fourth, nullptr); + + pool.DeAlloc(second); + pool.DeAlloc(fourth); + + EXPECT_EQ(pool.Alloc(), fourth); + EXPECT_EQ(pool.Alloc(), second); + EXPECT_EQ(pool.Alloc(), nullptr); +} + +TEST(CMemPool, InitWithExternalPoolUsesProvidedMemoryAndOwnsOnlyAllocTable) +{ + alignas(4) std::array storage{}; + CMemPool pool; + + pool.Init(5, 4, storage.data(), 4); + + EXPECT_EQ(pool.m_pxPool, storage.data()); + EXPECT_NE(pool.m_pAllocTable, nullptr); + EXPECT_EQ(pool.m_iEntries, 4); + EXPECT_EQ(pool.m_iBlockSize, 8); + EXPECT_FALSE(pool.m_bOwnPool); + + int index = -1; + void* first = pool.Alloc(&index); + + EXPECT_EQ(first, storage.data()); + EXPECT_EQ(index, 0); + EXPECT_EQ(pool.Alloc(), storage.data() + 8); +} + +TEST(CMemPool, DeInitResetsStateAndCanBeCalledTwice) +{ + CMemPool pool; + pool.Init(4, 2, 4); + + pool.Alloc(); + pool.DeInit(); + + EXPECT_EQ(pool.m_pxPool, nullptr); + EXPECT_EQ(pool.m_pAllocTable, nullptr); + EXPECT_EQ(pool.m_iEntries, 0); + EXPECT_EQ(pool.m_iNumAlloc, 0); + + pool.DeInit(); + + EXPECT_EQ(pool.m_pxPool, nullptr); + EXPECT_EQ(pool.m_pAllocTable, nullptr); +} + +TEST(CMemPool, DeInitDoesNotFreeExternalPool) +{ + alignas(4) std::array storage{}; + CMemPool pool; + + pool.Init(4, 2, storage.data(), 4); + auto* allocated = static_cast(pool.Alloc()); + ASSERT_EQ(allocated, storage.data()); + allocated[0] = 0xAB; + + pool.DeInit(); + + EXPECT_EQ(storage[0], 0xABu); + EXPECT_EQ(pool.m_pxPool, nullptr); + EXPECT_EQ(pool.m_pAllocTable, nullptr); +} + +TEST(CMemPool, DeAllocNullIsNoOp) +{ + CMemPool pool; + pool.Init(4, 2, 4); + + pool.DeAlloc(nullptr); + + EXPECT_EQ(pool.m_iNumAlloc, 0); +} + +TEST(CMemPool, DeAllocBeforeInitIsNoOp) +{ + CMemPool pool; + int dummy = 0; + + pool.DeAlloc(&dummy); + + EXPECT_EQ(pool.m_iNumAlloc, 0); + EXPECT_EQ(pool.m_pxPool, nullptr); + EXPECT_EQ(pool.m_pAllocTable, nullptr); +} diff --git a/ReHitman/Glacier/Tests/source/CObjectInfo_Tests.cpp b/ReHitman/Glacier/Tests/source/CObjectInfo_Tests.cpp new file mode 100644 index 0000000..31fe715 --- /dev/null +++ b/ReHitman/Glacier/Tests/source/CObjectInfo_Tests.cpp @@ -0,0 +1,29 @@ +#include +#include + +using namespace Glacier; + +namespace +{ + static_assert(sizeof(CObjectInfo) == 0x10); +} + +TEST(CObjectInfo, IsOverlapAABBUsesHalfOpenBounds) +{ + CObjectInfo object{}; + object.iID = 1; + object.iMinX = 10; + object.iMinY = 20; + object.iMinZ = 30; + object.iMaxX = 20; + object.iMaxY = 30; + object.iMaxZ = 40; + + EXPECT_TRUE(object.IsOverlapAABB(15, 25, 35, 25, 35, 45)); + EXPECT_TRUE(object.IsOverlapAABB(0, 0, 0, 11, 21, 31)); + + EXPECT_FALSE(object.IsOverlapAABB(20, 20, 30, 25, 30, 40)); + EXPECT_FALSE(object.IsOverlapAABB(0, 0, 0, 10, 30, 40)); + EXPECT_FALSE(object.IsOverlapAABB(10, 30, 30, 20, 40, 40)); + EXPECT_FALSE(object.IsOverlapAABB(10, 20, 40, 20, 30, 50)); +} diff --git a/ReHitman/Glacier/Tests/source/CQuadtree_Tests.cpp b/ReHitman/Glacier/Tests/source/CQuadtree_Tests.cpp new file mode 100644 index 0000000..5f5345f --- /dev/null +++ b/ReHitman/Glacier/Tests/source/CQuadtree_Tests.cpp @@ -0,0 +1,361 @@ +#include +#include + +#include +#include +#include + +using namespace Glacier; + +namespace +{ + static_assert(sizeof(SRecurseAdd) == 0x1C); + static_assert(sizeof(CNodeQuad) == 0x10); + static_assert(sizeof(CQuadtreeObj) == 0x1C); + static_assert(sizeof(SOctreeChk) == 0xC); + static_assert(sizeof(SRecurseInfoCompiled) == 0x5C); + static_assert(sizeof(CQuadtree) == 0x30); + + struct QueryContext + { + std::vector Values; + }; + + bool CollectCallback(unsigned int value, SOctreeChk* info) + { + auto* context = static_cast(info->pUserData); + context->Values.push_back(value); + return true; + } + + SRecurseInfoCompiled MakeQueryInfo(QueryContext& context) + { + SRecurseInfoCompiled info{}; + info.pChkFunc = &CollectCallback; + info.pUserData = &context; + return info; + } + + bool Contains(const std::vector& values, unsigned int value) + { + return std::find(values.begin(), values.end(), value) != values.end(); + } + + void CollectObjectsFromNode(CNodeQuad* node, CMemPool* pool, std::vector& out) + { + for (auto* current = node->m_tObjectList.GetHead(); current; current = current->m_pNext) + { + out.push_back(static_cast(current)); + } + + for (int i = 0; i < 4; ++i) + { + if (node->ChildExists(i)) + { + CollectObjectsFromNode(node->GetChildPtr(pool, i), pool, out); + } + } + } + + std::vector CollectObjects(CQuadtree& tree) + { + std::vector objects; + CollectObjectsFromNode(tree.m_pRoot, &tree.m_tPool, objects); + return objects; + } + + CQuadtreeObj* FindObject(CQuadtree& tree, unsigned int id) + { + auto objects = CollectObjects(tree); + for (auto* object : objects) + { + if (object->m_tInfo.iID == id) + { + return object; + } + } + + return nullptr; + } +} + +TEST(CNodeQuad, InitRootAndChildStoresParentAndDepth) +{ + CMemPool pool; + pool.Init(sizeof(CNodeQuad), 4, 1); + + auto* root = static_cast(pool.Alloc()); + ASSERT_NE(root, nullptr); + root->Init(&pool, nullptr); + + int childBlock = -1; + auto* child = static_cast(pool.Alloc(&childBlock)); + ASSERT_NE(child, nullptr); + child->Init(&pool, root); + root->SetChild(2, static_cast(childBlock)); + + EXPECT_EQ(root->GetDepth(), 0); + EXPECT_TRUE(root->IsEmpty()); + EXPECT_FALSE(root->ChildExists(0)); + EXPECT_TRUE(root->ChildExists(2)); + EXPECT_FALSE(root->IsLeaf()); + + EXPECT_EQ(child->GetDepth(), 1); + EXPECT_EQ(child->GetParentPtr(&pool), root); + EXPECT_EQ(root->GetChildPtr(&pool, 2), child); + EXPECT_TRUE(child->IsLeaf()); +} + +TEST(CNodeQuad, AttachAndDetachMaintainObjectListAndBackPointer) +{ + CMemPool pool; + pool.Init(sizeof(CNodeQuad), 1, 1); + + auto* node = static_cast(pool.Alloc()); + ASSERT_NE(node, nullptr); + node->Init(&pool, nullptr); + + CQuadtreeObj first(10); + CQuadtreeObj second(20); + + node->Attach(&first); + node->Attach(&second); + + EXPECT_EQ(node->m_tObjectList.GetHead(), &second); + EXPECT_EQ(second.m_pNext, &first); + EXPECT_EQ(first.m_pPrev, &second); + EXPECT_EQ(first.m_pNode, node); + EXPECT_EQ(second.m_pNode, node); + EXPECT_FALSE(node->IsEmpty()); + + node->Detach(&second); + + EXPECT_EQ(node->m_tObjectList.GetHead(), &first); + EXPECT_EQ(first.m_pPrev, nullptr); + EXPECT_EQ(second.m_pNext, nullptr); + EXPECT_EQ(second.m_pPrev, nullptr); +} + +TEST(CNodeQuad, DeleteEmptySingleUnlinksChildAndReturnsPoolSlot) +{ + CMemPool pool; + pool.Init(sizeof(CNodeQuad), 4, 1); + + auto* root = static_cast(pool.Alloc()); + ASSERT_NE(root, nullptr); + root->Init(&pool, nullptr); + + int childBlock = -1; + auto* child = static_cast(pool.Alloc(&childBlock)); + ASSERT_NE(child, nullptr); + child->Init(&pool, root); + root->SetChild(1, static_cast(childBlock)); + + child->DeleteEmptySingle(&pool); + + EXPECT_FALSE(root->ChildExists(1)); + EXPECT_EQ(pool.m_iNumAlloc, 1); + EXPECT_EQ(pool.Alloc(), child); +} + +TEST(CQuadtree, ConstructorInitializesRootPoolDefaults) +{ + CQuadtree tree(16); + + ASSERT_NE(tree.m_pRoot, nullptr); + EXPECT_EQ(tree.m_iObjects, 0); + EXPECT_EQ(tree.m_fScale, 0.125f); + EXPECT_EQ(tree.m_vOrigin, ZVector3(0.0f, 0.0f, 0.0f)); + EXPECT_EQ(tree.m_pRoot->GetDepth(), 0); + EXPECT_TRUE(tree.m_pRoot->IsLeaf()); + EXPECT_EQ(tree.m_tPool.m_iEntries, 16); + EXPECT_EQ(tree.m_tPool.m_iNumAlloc, 1); +} + +TEST(CQuadtree, GetDepthMapsObjectDimensionToTreeDepth) +{ + CQuadtree tree(4); + + EXPECT_EQ(tree.GetDepth(1), 15); + EXPECT_EQ(tree.GetDepth(2), 14); + EXPECT_EQ(tree.GetDepth(3), 14); + EXPECT_EQ(tree.GetDepth(4), 13); + EXPECT_EQ(tree.GetDepth(0x4000), 1); + EXPECT_EQ(tree.GetDepth(0x8000), 0); + EXPECT_THROW(tree.GetDepth(0xFFFF), std::runtime_error); +} + +TEST(CQuadtree, ConvToOCSUsesOriginAndScale) +{ + CQuadtree tree(4); + + tree.SetOrigin(ZVector3(10.0f, 20.0f, 30.0f)); + tree.SetScale(2.0f); + + int out[3]{}; + tree.ConvToOCS(out, ZVector3(11.0f, 18.0f, 35.5f)); + + EXPECT_EQ(out[0], 32770); + EXPECT_EQ(out[1], 32764); + EXPECT_EQ(out[2], 32779); + EXPECT_THROW(tree.SetScale(0.0f), std::runtime_error); +} + +TEST(CQuadtree, AddMinMaxCreatesObjectAtExpectedLeafAndGetEverythingFindsIt) +{ + CQuadtree tree(64); + + tree.AddMinMax(100, 10, 200, 103, 13, 203, 777); + + EXPECT_EQ(tree.m_iObjects, 1); + EXPECT_GT(tree.m_tPool.m_iNumAlloc, 1); + + CQuadtreeObj* object = FindObject(tree, 777); + ASSERT_NE(object, nullptr); + ASSERT_NE(object->m_pNode, nullptr); + EXPECT_EQ(object->m_tInfo.iMinX, 100u); + EXPECT_EQ(object->m_tInfo.iMinY, 10u); + EXPECT_EQ(object->m_tInfo.iMinZ, 200u); + EXPECT_EQ(object->m_tInfo.iMaxX, 103u); + EXPECT_EQ(object->m_tInfo.iMaxY, 13u); + EXPECT_EQ(object->m_tInfo.iMaxZ, 203u); + EXPECT_EQ(object->m_pNode->GetDepth(), tree.GetDepth(4)); + EXPECT_EQ(object->m_pNode->m_tObjectList.GetHead(), object); + + QueryContext context; + auto info = MakeQueryInfo(context); + tree.GetEverything(&info); + + EXPECT_EQ(context.Values.size(), 1u); + EXPECT_TRUE(Contains(context.Values, 777)); +} + +TEST(CQuadtree, AddMinMaxFallsBackToCurrentNodeWhenPoolIsFull) +{ + CQuadtree tree(1); + + tree.AddMinMax(100, 10, 200, 103, 13, 203, 1); + + EXPECT_EQ(tree.m_iObjects, 1); + EXPECT_EQ(tree.m_tPool.m_iNumAlloc, 1); + ASSERT_NE(tree.m_pRoot->m_tObjectList.GetHead(), nullptr); + EXPECT_EQ(tree.m_pRoot->m_tObjectList.GetHead()->m_tInfo.iID, 1u); +} + +TEST(CQuadtree, CheckCubeReturnsOnlyOverlappingObjects) +{ + CQuadtree tree(128); + + tree.AddMinMax(100, 0, 100, 110, 10, 110, 1); + tree.AddMinMax(500, 0, 500, 510, 10, 510, 2); + tree.AddMinMax(1000, 0, 1000, 1010, 10, 1010, 3); + + QueryContext context; + auto info = MakeQueryInfo(context); + tree.CheckCube(&info, 90, 0, 90, 520, 20, 520); + + EXPECT_TRUE(Contains(context.Values, 1)); + EXPECT_TRUE(Contains(context.Values, 2)); + EXPECT_FALSE(Contains(context.Values, 3)); +} + +TEST(CQuadtree, AddMinMaxVectorConvertsWorldBounds) +{ + CQuadtree tree(64); + tree.SetOrigin(ZVector3(10.0f, 0.0f, 20.0f)); + tree.SetScale(2.0f); + + tree.AddMinMax(ZVector3(10.0f, 0.0f, 20.0f), ZVector3(12.0f, 4.0f, 23.0f), 99); + + CQuadtreeObj* object = FindObject(tree, 99); + ASSERT_NE(object, nullptr); + EXPECT_EQ(object->m_tInfo.iMinX, 32768u); + EXPECT_EQ(object->m_tInfo.iMinY, 32768u); + EXPECT_EQ(object->m_tInfo.iMinZ, 32768u); + EXPECT_EQ(object->m_tInfo.iMaxX, 32772u); + EXPECT_EQ(object->m_tInfo.iMaxY, 32776u); + EXPECT_EQ(object->m_tInfo.iMaxZ, 32774u); +} + +TEST(CQuadtree, DeleteRemovesObjectAndPrunesEmptyNodes) +{ + CQuadtree tree(64); + tree.AddMinMax(100, 10, 200, 103, 13, 203, 7); + + CQuadtreeObj* object = FindObject(tree, 7); + ASSERT_NE(object, nullptr); + EXPECT_GT(tree.m_tPool.m_iNumAlloc, 1); + + tree.Delete(object); + + EXPECT_EQ(tree.m_iObjects, 0); + EXPECT_EQ(tree.m_tPool.m_iNumAlloc, 1); + EXPECT_TRUE(tree.m_pRoot->IsLeaf()); + + QueryContext context; + auto info = MakeQueryInfo(context); + tree.GetEverything(&info); + EXPECT_TRUE(context.Values.empty()); +} + +TEST(CQuadtree, MoveInsideSameNodeUpdatesBoundsWithoutReinsert) +{ + CQuadtree tree(64); + tree.AddMinMax(100, 0, 100, 103, 3, 103, 42); + + CQuadtreeObj* object = FindObject(tree, 42); + ASSERT_NE(object, nullptr); + CNodeQuad* oldNode = object->m_pNode; + int oldAllocCount = tree.m_tPool.m_iNumAlloc; + + int minPos[3] = {104, 1, 104}; + int maxPos[3] = {107, 4, 107}; + tree.Move(object, minPos, maxPos); + + EXPECT_EQ(object->m_pNode, oldNode); + EXPECT_EQ(tree.m_tPool.m_iNumAlloc, oldAllocCount); + EXPECT_EQ(object->m_tInfo.iMinX, 104u); + EXPECT_EQ(object->m_tInfo.iMaxZ, 107u); +} + +TEST(CQuadtree, MoveToDifferentNodeReattachesObjectAndLeavesOldNodeEmpty) +{ + CQuadtree tree(128); + tree.AddMinMax(100, 0, 100, 103, 3, 103, 42); + + CQuadtreeObj* object = FindObject(tree, 42); + ASSERT_NE(object, nullptr); + CNodeQuad* oldNode = object->m_pNode; + + int minPos[3] = {4000, 1, 4000}; + int maxPos[3] = {4003, 4, 4003}; + tree.Move(object, minPos, maxPos); + + EXPECT_NE(object->m_pNode, oldNode); + EXPECT_EQ(object->m_pNode->m_tObjectList.GetHead(), object); + EXPECT_TRUE(oldNode->IsEmpty()); + + QueryContext context; + auto info = MakeQueryInfo(context); + tree.CheckCube(&info, 3990, 0, 3990, 4010, 10, 4010); + EXPECT_TRUE(Contains(context.Values, 42)); +} + +TEST(CQuadtree, CheckLinesegmentReportsIntersectedObjectInfoPointers) +{ + CQuadtree tree(128); + tree.SetScale(1.0f); + + tree.AddMinMax(32760, 32760, 32760, 32770, 32770, 32770, 1); + tree.AddMinMax(33000, 32760, 33000, 33010, 32770, 33010, 2); + + CQuadtreeObj* first = FindObject(tree, 1); + ASSERT_NE(first, nullptr); + + QueryContext context; + auto info = MakeQueryInfo(context); + bool hit = tree.CheckLinesegment(&info, ZVector3(-20.0f, 0.0f, -20.0f), ZVector3(20.0f, 0.0f, 20.0f)); + + EXPECT_TRUE(hit); + EXPECT_TRUE(Contains(context.Values, reinterpret_cast(&first->m_tInfo))); +} diff --git a/ReHitman/Glacier/Tests/source/LINKREFTAB_Tests.cpp b/ReHitman/Glacier/Tests/source/LINKREFTAB_Tests.cpp new file mode 100644 index 0000000..1b86deb --- /dev/null +++ b/ReHitman/Glacier/Tests/source/LINKREFTAB_Tests.cpp @@ -0,0 +1,240 @@ +#include +#include + +#include + +using namespace Glacier; + +namespace +{ + std::vector CollectForward(LINKREFTAB& tab) + { + std::vector refs; + + RefRun it; + tab.RunInitNxtRef(&it); + + while (auto* ref = tab.RunNxtRefPtr(&it)) + { + refs.push_back(*ref); + } + + return refs; + } + + std::vector CollectBackward(LINKREFTAB& tab) + { + std::vector refs; + + RefRun it; + tab.RunInitPrevRef(&it); + + while (auto* ref = tab.RunPrevRefPtr(&it)) + { + refs.push_back(*ref); + } + + return refs; + } +} + + +TEST(LINKREFTAB, InitiallyEmpty) +{ + LINKREFTAB tab(8, 0); + + EXPECT_EQ(tab.Count(), 0); + EXPECT_EQ(tab.First, nullptr); + EXPECT_EQ(tab.Last, nullptr); +} + +TEST(LINKREFTAB, AddCreatesSingleElement) +{ + LINKREFTAB tab(8, 0); + + uint32_t* ref = tab.Add(123); + + ASSERT_NE(ref, nullptr); + + EXPECT_EQ(*(ref - 1), 123u); + EXPECT_EQ(tab.Count(), 1); + + EXPECT_EQ(tab.First, tab.Last); + EXPECT_EQ(tab.First->Prev, nullptr); + EXPECT_EQ(tab.First->Next, nullptr); +} + +TEST(LINKREFTAB, ConstructorInitializesLinkSpecificStorage) +{ + LINKREFTAB tab(4, 2); + + EXPECT_EQ(tab.EleCount, 0); + EXPECT_EQ(tab.EleSize, 5u); + EXPECT_EQ(tab.BlkSize, 20u); + EXPECT_EQ(tab.Count(), 0); + EXPECT_EQ(tab.First, nullptr); + EXPECT_EQ(tab.Last, nullptr); + EXPECT_EQ(tab.FreeStack, nullptr); +} + +TEST(LINKREFTAB, AddStartAndAddEndMaintainIterationOrder) +{ + LINKREFTAB tab(8, 0); + + tab.Add(20); + tab.AddStart(10); + tab.AddEnd(30); + + EXPECT_EQ(tab.Count(), 3); + EXPECT_EQ(CollectForward(tab), (std::vector{10, 20, 30})); + EXPECT_EQ(CollectBackward(tab), (std::vector{30, 20, 10})); + + ASSERT_NE(tab.First, nullptr); + ASSERT_NE(tab.Last, nullptr); + EXPECT_EQ(tab.First->Prev, nullptr); + EXPECT_EQ(tab.Last->Next, nullptr); +} + +TEST(LINKREFTAB, InsertBeforeHandlesHeadMiddleAndNullTarget) +{ + LINKREFTAB tab(8, 0); + + tab.Add(20); + tab.Add(40); + + uint32_t* ref40 = tab.GetRefPtrNr(1); + ASSERT_NE(ref40, nullptr); + tab.InsertBefore(ref40, 30); + + uint32_t* ref20 = tab.GetRefPtrNr(0); + ASSERT_NE(ref20, nullptr); + tab.InsertBefore(ref20, 10); + + tab.InsertBefore(nullptr, 50); + + EXPECT_EQ(tab.Count(), 5); + EXPECT_EQ(CollectForward(tab), (std::vector{10, 20, 30, 40, 50})); + EXPECT_EQ(CollectBackward(tab), (std::vector{50, 40, 30, 20, 10})); +} + +TEST(LINKREFTAB, GetRefNrAndGetRefPtrNrFollowLinkedOrder) +{ + LINKREFTAB tab(2, 0); + + tab.Add(10); + tab.Add(20); + tab.AddStart(5); + tab.AddEnd(30); + + EXPECT_EQ(tab.GetRefNr(0), 5u); + EXPECT_EQ(tab.GetRefNr(1), 10u); + EXPECT_EQ(tab.GetRefNr(2), 20u); + EXPECT_EQ(tab.GetRefNr(3), 30u); + EXPECT_EQ(tab.GetRefNr(4), 0u); + + ASSERT_NE(tab.GetRefPtrNr(0), nullptr); + ASSERT_NE(tab.GetRefPtrNr(3), nullptr); + EXPECT_EQ(*tab.GetRefPtrNr(0), 5u); + EXPECT_EQ(*tab.GetRefPtrNr(3), 30u); + EXPECT_EQ(tab.GetRefPtrNr(4), nullptr); +} + +TEST(LINKREFTAB, GetPrevAndNextRefPtrReturnLinkedNeighbors) +{ + LINKREFTAB tab(8, 0); + + tab.Add(10); + tab.Add(20); + tab.Add(30); + + uint32_t* ref10 = tab.GetRefPtrNr(0); + uint32_t* ref20 = tab.GetRefPtrNr(1); + uint32_t* ref30 = tab.GetRefPtrNr(2); + + ASSERT_NE(ref10, nullptr); + ASSERT_NE(ref20, nullptr); + ASSERT_NE(ref30, nullptr); + + EXPECT_EQ(tab.GetPrevRefPtr(ref10), nullptr); + EXPECT_EQ(tab.GetNextRefPtr(ref10), ref20); + EXPECT_EQ(tab.GetPrevRefPtr(ref20), ref10); + EXPECT_EQ(tab.GetNextRefPtr(ref20), ref30); + EXPECT_EQ(tab.GetPrevRefPtr(ref30), ref20); + EXPECT_EQ(tab.GetNextRefPtr(ref30), nullptr); +} + +TEST(LINKREFTAB, RunDelRefRemovesCurrentNodeWithoutChangingStorageCount) +{ + LINKREFTAB tab(8, 0); + + tab.Add(10); + tab.Add(20); + tab.Add(30); + + RefRun it; + tab.RunInitNxtRef(&it); + ASSERT_EQ(*tab.RunNxtRefPtr(&it), 10u); + ASSERT_EQ(*tab.RunNxtRefPtr(&it), 20u); + + tab.RunDelRef(&it); + + EXPECT_EQ(tab.EleCount, 3); + EXPECT_EQ(tab.Count(), 2); + ASSERT_NE(tab.FreeStack, nullptr); + EXPECT_EQ(CollectForward(tab), (std::vector{10, 30})); + EXPECT_EQ(CollectBackward(tab), (std::vector{30, 10})); +} + +TEST(LINKREFTAB, DeletedRecordIsReusedByNextAdd) +{ + LINKREFTAB tab(8, 0); + + tab.Add(10); + tab.Add(20); + tab.Add(30); + + uint32_t* ref20 = tab.GetRefPtrNr(1); + ASSERT_NE(ref20, nullptr); + + RefRun it; + tab.RunInitNxtRef(&it); + tab.RunNxtRefPtr(&it); + tab.RunNxtRefPtr(&it); + tab.RunDelRef(&it); + + ASSERT_NE(tab.FreeStack, nullptr); + EXPECT_EQ(tab.Count(), 2); + + tab.Add(40); + + EXPECT_EQ(tab.EleCount, 3); + EXPECT_EQ(tab.Count(), 3); + EXPECT_EQ(tab.FreeStack, nullptr); + EXPECT_EQ(tab.GetRefPtrNr(2), ref20); + EXPECT_EQ(CollectForward(tab), (std::vector{10, 30, 40})); +} + +TEST(LINKREFTAB, ClearRemovesActiveAndFreeRecords) +{ + LINKREFTAB tab(8, 0); + + tab.Add(10); + tab.Add(20); + + RefRun it; + tab.RunInitNxtRef(&it); + tab.RunNxtRefPtr(&it); + tab.RunDelRef(&it); + + ASSERT_NE(tab.FreeStack, nullptr); + + tab.Clear(); + + EXPECT_EQ(tab.EleCount, 0); + EXPECT_EQ(tab.Count(), 0); + EXPECT_EQ(tab.First, nullptr); + EXPECT_EQ(tab.Last, nullptr); + EXPECT_EQ(tab.FreeStack, nullptr); + EXPECT_EQ(tab.TabFirstPtr, nullptr); + EXPECT_EQ(tab.TabBlockPtr, nullptr); +} diff --git a/ReHitman/Glacier/Tests/source/MYSTR_Tests.cpp b/ReHitman/Glacier/Tests/source/MYSTR_Tests.cpp new file mode 100644 index 0000000..c997ffc --- /dev/null +++ b/ReHitman/Glacier/Tests/source/MYSTR_Tests.cpp @@ -0,0 +1,162 @@ +#include +#include + +using namespace Glacier; + + +bool IsUsingInternalBuffer(const MYSTR& str) +{ + const char* bufferStart = str.m_Buffer; + const char* bufferEnd = str.m_Buffer + sizeof(str.m_Buffer); + return (str.String >= bufferStart && str.String < bufferEnd); +} + +TEST(MYSTR_Tests, ConstructorsAndSSOBounds) +{ + MYSTR emptyStr; + EXPECT_EQ(emptyStr.Length(), 0); + EXPECT_STREQ(emptyStr.String, ""); + EXPECT_TRUE(IsUsingInternalBuffer(emptyStr)); + + std::string shortData(123, 'a'); + MYSTR shortStr(shortData.c_str()); + EXPECT_EQ(shortStr.Length(), 123); + EXPECT_TRUE(IsUsingInternalBuffer(shortStr)); + + std::string longData(124, 'b'); + MYSTR longStr(longData.c_str()); + EXPECT_EQ(longStr.Length(), 124); + EXPECT_FALSE(IsUsingInternalBuffer(longStr)); + EXPECT_STREQ(longStr.String, longData.c_str()); + + MYSTR shortCopy(shortStr); + EXPECT_TRUE(IsUsingInternalBuffer(shortCopy)); + EXPECT_STREQ(shortCopy.String, shortData.c_str()); + + MYSTR longCopy(longStr); + EXPECT_FALSE(IsUsingInternalBuffer(longCopy)); + EXPECT_STREQ(longCopy.String, longData.c_str()); +} + +TEST(MYSTR_Tests, DestructorBehavior) +{ + { + std::string hugeData(1000, 'x'); + MYSTR hugeStr(hugeData.c_str()); + EXPECT_FALSE(IsUsingInternalBuffer(hugeStr)); + } + SUCCEED(); +} + +TEST(MYSTR_Tests, SetStringBufferSwitching) +{ + MYSTR str; + EXPECT_TRUE(IsUsingInternalBuffer(str)); + + std::string longData(300, 'c'); + str.SetString(longData.c_str()); + EXPECT_FALSE(IsUsingInternalBuffer(str)); + EXPECT_EQ(str.Length(), 300); + + str.SetString("short"); + EXPECT_TRUE(IsUsingInternalBuffer(str)); + EXPECT_STREQ(str.String, "short"); + + str.SetString(longData.c_str()); + EXPECT_FALSE(IsUsingInternalBuffer(str)); + + str.SetString(nullptr); + EXPECT_TRUE(IsUsingInternalBuffer(str)); + EXPECT_STREQ(str.String, ""); +} + +TEST(MYSTR_Tests, AssignmentOperators) +{ + MYSTR s1("Hello"); + MYSTR s2; + + s2 = s1; + EXPECT_STREQ(s2.String, "Hello"); + EXPECT_TRUE(IsUsingInternalBuffer(s2)); + + s2 = s2; + EXPECT_STREQ(s2.String, "Hello"); + + std::string longData(200, 'z'); + MYSTR sLong(longData.c_str()); + s1 = sLong; + EXPECT_FALSE(IsUsingInternalBuffer(s1)); + EXPECT_STREQ(s1.String, longData.c_str()); + + s1 = s2; + EXPECT_TRUE(IsUsingInternalBuffer(s1)); + EXPECT_STREQ(s1.String, "Hello"); +} + +TEST(MYSTR_Tests, IntegerAssignment) +{ + MYSTR str; + + str = 123456; + EXPECT_STREQ(str.String, "123456"); + EXPECT_TRUE(IsUsingInternalBuffer(str)); + + str = -98765; + EXPECT_STREQ(str.String, "-98765"); + EXPECT_TRUE(IsUsingInternalBuffer(str)); + + str = 0; + EXPECT_STREQ(str.String, "0"); + + str = 2147483647; + EXPECT_STREQ(str.String, "2147483647"); + EXPECT_TRUE(IsUsingInternalBuffer(str)); +} + +TEST(MYSTR_Tests, Concatenation) +{ + MYSTR a("Hit"); + MYSTR b("man"); + a += b; + EXPECT_STREQ(a.String, "Hitman"); + EXPECT_TRUE(IsUsingInternalBuffer(a)); + + MYSTR base(std::string(60, 'a').c_str()); + MYSTR tail(std::string(60, 'b').c_str()); + base += tail; + EXPECT_EQ(base.Length(), 120); + EXPECT_TRUE(IsUsingInternalBuffer(base)); + + base += MYSTR("break"); + EXPECT_EQ(base.Length(), 125); + EXPECT_FALSE(IsUsingInternalBuffer(base)); + + MYSTR lhs("Blood "); + MYSTR rhs("Money"); + MYSTR res = lhs + rhs; + EXPECT_STREQ(res.String, "Blood Money"); + EXPECT_TRUE(IsUsingInternalBuffer(res)); + + EXPECT_STREQ(lhs.String, "Blood "); + EXPECT_STREQ(rhs.String, "Money"); +} + +TEST(MYSTR_Tests, ToLowerMethod) +{ + MYSTR strShort("HiTMaN 47!"); + strShort.ToLower(); + EXPECT_STREQ(strShort.String, "hitman 47!"); + EXPECT_TRUE(IsUsingInternalBuffer(strShort)); + + std::string upperLong(150, 'G'); + std::string lowerLong(150, 'g'); + MYSTR strLong(upperLong.c_str()); + + strLong.ToLower(); + EXPECT_STREQ(strLong.String, lowerLong.c_str()); + EXPECT_FALSE(IsUsingInternalBuffer(strLong)); + + MYSTR empty; + empty.ToLower(); + EXPECT_STREQ(empty.String, ""); +} \ No newline at end of file diff --git a/ReHitman/Glacier/Tests/source/REFTAB32_Tests.cpp b/ReHitman/Glacier/Tests/source/REFTAB32_Tests.cpp new file mode 100644 index 0000000..db80d41 --- /dev/null +++ b/ReHitman/Glacier/Tests/source/REFTAB32_Tests.cpp @@ -0,0 +1,112 @@ +#include +#include + + +using namespace Glacier; + +class REFTAB32Test : public ::testing::Test +{ +protected: + void SetUp() override + { + pReftab = new REFTAB32(); + } + + void TearDown() override + { + delete pReftab; + } + + REFTAB32* pReftab = nullptr; +}; + +TEST_F(REFTAB32Test, ConstructorInitialization) +{ + EXPECT_EQ(pReftab->EleCount, 0); + EXPECT_EQ(pReftab->m_lRefsPrBlk, 32); + EXPECT_EQ(pReftab->EleSize, 1); + EXPECT_EQ(pReftab->BlkSize, 32); + EXPECT_EQ(pReftab->TabFirstPtr, nullptr); + EXPECT_EQ(pReftab->TabBlockPtr, nullptr); +} + +TEST_F(REFTAB32Test, SmallBufferOptimizationInternalStorage) +{ + for (int i = 0; i < 32; ++i) + { + pReftab->Add(i * 10); + } + + EXPECT_EQ(pReftab->EleCount, 32); + ASSERT_NE(pReftab->TabFirstPtr, nullptr); + + EXPECT_EQ(pReftab->TabFirstPtr, reinterpret_cast(pReftab->m_FirstTab)); + EXPECT_EQ(pReftab->TabBlockPtr, reinterpret_cast(pReftab->m_FirstTab)); +} + +TEST_F(REFTAB32Test, OverflowTriggersDynamicAllocation) +{ + for (int i = 0; i < 32; ++i) + { + pReftab->Add(i); + } + + pReftab->Add(999); + + EXPECT_EQ(pReftab->EleCount, 33); + + EXPECT_EQ(pReftab->TabFirstPtr, reinterpret_cast(pReftab->m_FirstTab)); + + ASSERT_NE(pReftab->TabBlockPtr, nullptr); + EXPECT_NE(pReftab->TabBlockPtr, reinterpret_cast(pReftab->m_FirstTab)); +} + +TEST_F(REFTAB32Test, RangeBasedForLoopCompatibility) +{ + pReftab->Add(5); + pReftab->Add(10); + pReftab->Add(15); + + int sum = 0; + + for (uint32_t value : *pReftab) + { + sum += value; + } + + EXPECT_EQ(sum, 30); +} + +TEST_F(REFTAB32Test, NativeGlacierIterationLoop) +{ + pReftab->Add(5); + pReftab->Add(10); + pReftab->Add(15); + + EXPECT_EQ(pReftab->EleCount, 3); + + RefRun it; + pReftab->RunInitNxtRef(&it); + + uint32_t* pVal1 = pReftab->RunNxtRefPtr(&it); + ASSERT_NE(pVal1, nullptr) << "First element pointer is null!"; + std::cout << "[Native Test] Element 1 Address: " << pVal1 << ", Value: " << *pVal1 << std::endl; + + uint32_t* pVal2 = pReftab->RunNxtRefPtr(&it); + ASSERT_NE(pVal2, nullptr) << "Second element pointer is null!"; + std::cout << "[Native Test] Element 2 Address: " << pVal2 << ", Value: " << *pVal2 << std::endl; + + uint32_t* pVal3 = pReftab->RunNxtRefPtr(&it); + ASSERT_NE(pVal3, nullptr) << "Third element pointer is null!"; + std::cout << "[Native Test] Element 3 Address: " << pVal3 << ", Value: " << *pVal3 << std::endl; + + uint32_t* pEnd = pReftab->RunNxtRefPtr(&it); + EXPECT_EQ(pEnd, nullptr); + + EXPECT_EQ(*pVal1, 5); + EXPECT_EQ(*pVal2, 10); + EXPECT_EQ(*pVal3, 15); + + int nativeSum = *pVal1 + *pVal2 + *pVal3; + EXPECT_EQ(nativeSum, 30); +} \ No newline at end of file diff --git a/ReHitman/Glacier/Tests/source/REFTAB_Tests.cpp b/ReHitman/Glacier/Tests/source/REFTAB_Tests.cpp new file mode 100644 index 0000000..d95ff29 --- /dev/null +++ b/ReHitman/Glacier/Tests/source/REFTAB_Tests.cpp @@ -0,0 +1,316 @@ +#include +#include + + +using namespace Glacier; + +class REFTABTest : public ::testing::Test +{ +protected: + void SetUp() override + { + pReftab = new REFTAB(4, 0); + } + + void TearDown() override + { + delete pReftab; + } + + REFTAB* pReftab = nullptr; +}; + +TEST_F(REFTABTest, ConstructorInitialization) +{ + EXPECT_EQ(pReftab->EleCount, 0); + EXPECT_EQ(pReftab->EleSize, 1); + EXPECT_EQ(pReftab->BlkSize, 4); + EXPECT_EQ(pReftab->TabFirstPtr, nullptr); + EXPECT_EQ(pReftab->TabBlockPtr, nullptr); +} + +TEST_F(REFTABTest, InsertAndIterateForward) +{ + pReftab->Add(10); + pReftab->Add(20); + pReftab->Add(30); + pReftab->Add(40); + pReftab->Add(50); + + EXPECT_EQ(pReftab->EleCount, 5); + ASSERT_NE(pReftab->TabFirstPtr, nullptr); + ASSERT_NE(pReftab->TabBlockPtr, nullptr); + EXPECT_NE(pReftab->TabFirstPtr, pReftab->TabBlockPtr); + + RefRun it; + pReftab->RunInitNxtRef(&it); + + uint32_t* pVal = nullptr; + + pVal = pReftab->RunNxtRefPtr(&it); + ASSERT_NE(pVal, nullptr); + EXPECT_EQ(*pVal, 10); + + pVal = pReftab->RunNxtRefPtr(&it); + EXPECT_EQ(*pVal, 20); + + pVal = pReftab->RunNxtRefPtr(&it); + EXPECT_EQ(*pVal, 30); + + pVal = pReftab->RunNxtRefPtr(&it); + EXPECT_EQ(*pVal, 40); + + pVal = pReftab->RunNxtRefPtr(&it); + ASSERT_NE(pVal, nullptr); + EXPECT_EQ(*pVal, 50); + + pVal = pReftab->RunNxtRefPtr(&it); + EXPECT_EQ(pVal, nullptr); +} + +TEST_F(REFTABTest, IterateBackward) +{ + pReftab->Add(100); + pReftab->Add(200); + pReftab->Add(300); + pReftab->Add(400); + pReftab->Add(500); + + RefRun it; + pReftab->RunInitPrevRef(&it); + + uint32_t* pVal = pReftab->RunPrevRefPtr(&it); + ASSERT_NE(pVal, nullptr); + EXPECT_EQ(*pVal, 500); + + pVal = pReftab->RunPrevRefPtr(&it); + ASSERT_NE(pVal, nullptr); + EXPECT_EQ(*pVal, 400); + + pVal = pReftab->RunPrevRefPtr(&it); + EXPECT_EQ(*pVal, 300); + + pVal = pReftab->RunPrevRefPtr(&it); + EXPECT_EQ(*pVal, 200); + + pVal = pReftab->RunPrevRefPtr(&it); + EXPECT_EQ(*pVal, 100); + + pVal = pReftab->RunPrevRefPtr(&it); + EXPECT_EQ(pVal, nullptr); +} + +TEST_F(REFTABTest, DeleteFromMiddleReplacesWithLast) +{ + pReftab->Add(10); + pReftab->Add(20); + pReftab->Add(30); + + RefRun it; + pReftab->RunInitNxtRef(&it); + pReftab->RunNxtRefPtr(&it); + pReftab->RunNxtRefPtr(&it); + + pReftab->RunDelRef(&it); + + EXPECT_EQ(pReftab->EleCount, 2); + + pReftab->RunInitNxtRef(&it); + EXPECT_EQ(*pReftab->RunNxtRefPtr(&it), 10); + EXPECT_EQ(*pReftab->RunNxtRefPtr(&it), 30); +} + +TEST_F(REFTABTest, DeleteVeryLastElementCleansUp) +{ + pReftab->Add(999); + + RefRun it; + pReftab->RunInitNxtRef(&it); + pReftab->RunNxtRefPtr(&it); + pReftab->RunDelRef(&it); + + EXPECT_EQ(pReftab->EleCount, 0); + EXPECT_EQ(pReftab->TabFirstPtr, nullptr); + EXPECT_EQ(pReftab->TabBlockPtr, nullptr); + EXPECT_EQ(it._RunPtr, nullptr); +} + +TEST_F(REFTABTest, ClearEmptiesContainer) +{ + pReftab->Add(10); + pReftab->Add(20); + pReftab->Add(30); + pReftab->Add(40); + pReftab->Add(50); + + pReftab->Clear(); + + EXPECT_EQ(pReftab->EleCount, 0); + EXPECT_EQ(pReftab->TabFirstPtr, nullptr); + EXPECT_EQ(pReftab->TabBlockPtr, nullptr); + + pReftab->Add(99); + EXPECT_EQ(pReftab->EleCount, 1); + ASSERT_NE(pReftab->TabFirstPtr, nullptr); + + RefRun it; + pReftab->RunInitNxtRef(&it); + EXPECT_EQ(*pReftab->RunNxtRefPtr(&it), 99); +} + +TEST_F(REFTABTest, AssertionsOnInvalidInputs) +{ + EXPECT_THROW(pReftab->RunInitNxtRef(nullptr), std::runtime_error); + EXPECT_THROW(pReftab->RunInitPrevRef(nullptr), std::runtime_error); + EXPECT_THROW(pReftab->RunNxtRefPtr(nullptr), std::runtime_error); + EXPECT_THROW(pReftab->RunPrevRefPtr(nullptr), std::runtime_error); + EXPECT_THROW(pReftab->RunToRefPtr(nullptr), std::runtime_error); + + RefRun emptyIt; + EXPECT_THROW(pReftab->RunDelRef(&emptyIt), std::runtime_error); +} + +TEST_F(REFTABTest, DeleteFirstElementReplacesWithLast) +{ + pReftab->Add(10); + pReftab->Add(20); + pReftab->Add(30); + pReftab->Add(40); + + RefRun it; + pReftab->RunInitNxtRef(&it); + pReftab->RunNxtRefPtr(&it); + + pReftab->RunDelRef(&it); + + EXPECT_EQ(pReftab->EleCount, 3); + + pReftab->RunInitNxtRef(&it); + EXPECT_EQ(*pReftab->RunNxtRefPtr(&it), 40); + EXPECT_EQ(*pReftab->RunNxtRefPtr(&it), 20); + EXPECT_EQ(*pReftab->RunNxtRefPtr(&it), 30); +} + +TEST_F(REFTABTest, DeleteElementCrossBlock) +{ + pReftab->Add(1); + pReftab->Add(2); + pReftab->Add(3); + pReftab->Add(4); + pReftab->Add(5); + pReftab->Add(6); + + RefRun it; + pReftab->RunInitNxtRef(&it); + pReftab->RunNxtRefPtr(&it); + pReftab->RunNxtRefPtr(&it); + pReftab->RunNxtRefPtr(&it); + + pReftab->RunDelRef(&it); + + EXPECT_EQ(pReftab->EleCount, 5); + + pReftab->RunInitNxtRef(&it); + EXPECT_EQ(*pReftab->RunNxtRefPtr(&it), 1); + EXPECT_EQ(*pReftab->RunNxtRefPtr(&it), 2); + EXPECT_EQ(*pReftab->RunNxtRefPtr(&it), 6); + EXPECT_EQ(*pReftab->RunNxtRefPtr(&it), 4); + EXPECT_EQ(*pReftab->RunNxtRefPtr(&it), 5); + EXPECT_EQ(pReftab->RunNxtRefPtr(&it), nullptr); +} + +TEST_F(REFTABTest, IndexOperatorAccess) +{ + for (uint32_t i = 0; i < 8; ++i) + { + pReftab->Add((i + 1) * 10); + } + + EXPECT_EQ((*pReftab)[0], 10); + EXPECT_EQ((*pReftab)[3], 40); + EXPECT_EQ((*pReftab)[4], 50); + EXPECT_EQ((*pReftab)[7], 80); + EXPECT_EQ((*pReftab)[8], 0); + EXPECT_EQ((*pReftab)[1000], 0); + EXPECT_THROW((*pReftab)[-1], std::runtime_error); +} + +TEST_F(REFTABTest, DestructorCleansUpMemory) +{ + { + REFTAB localReftab(4, 3); + + for (int i = 0; i < 100; i++) + { + localReftab.Add(i+1); + } + + EXPECT_EQ(localReftab.EleCount, 100); + } + SUCCEED(); +} + +TEST_F(REFTABTest, RangeBasedForLoop) +{ + REFTAB reftab{4,3}; + reftab.Add(11); + reftab.Add(22); + reftab.Add(33); + reftab.Add(44); + reftab.Add(55); + + std::vector extractedValues; + + for (auto value : reftab) + { + extractedValues.push_back(value); + } + + ASSERT_EQ(extractedValues.size(), 5); + EXPECT_EQ(extractedValues[0], 11); + EXPECT_EQ(extractedValues[1], 22); + EXPECT_EQ(extractedValues[2], 33); + EXPECT_EQ(extractedValues[3], 44); + EXPECT_EQ(extractedValues[4], 55); +} + +TEST_F(REFTABTest, CustomElementSizeHandling) +{ + auto* pCustomTab = new REFTAB(4, 1); + + EXPECT_EQ(pCustomTab->EleCount, 0); + EXPECT_EQ(pCustomTab->EleSize, 2); + EXPECT_EQ(pCustomTab->BlkSize, 8); + + uint32_t* pSlot1 = pCustomTab->Add(0x11111111); + ASSERT_NE(pSlot1, nullptr); + *pSlot1 = 0x22222222; + + uint32_t* pSlot2 = pCustomTab->Add(0x33333333); + ASSERT_NE(pSlot2, nullptr); + *pSlot2 = 0x44444444; + + EXPECT_EQ(pCustomTab->EleCount, 2); + + uint32_t* pStartOfElement1 = pSlot1 - 1; + uint32_t* pStartOfElement2 = pSlot2 - 1; + + EXPECT_EQ(pStartOfElement1 + pCustomTab->EleSize, pStartOfElement2); + + RefRun it; + pCustomTab->RunInitNxtRef(&it); + + uint32_t* pRead1 = pCustomTab->RunNxtRefPtr(&it); + ASSERT_NE(pRead1, nullptr); + EXPECT_EQ(pRead1[0], 0x11111111); + EXPECT_EQ(pRead1[1], 0x22222222); + + uint32_t* pRead2 = pCustomTab->RunNxtRefPtr(&it); + ASSERT_NE(pRead2, nullptr); + EXPECT_EQ(pRead2[0], 0x33333333); + EXPECT_EQ(pRead2[1], 0x44444444); + + EXPECT_EQ(pCustomTab->RunNxtRefPtr(&it), nullptr); + + delete pCustomTab; +} \ No newline at end of file diff --git a/ReHitman/Glacier/Tests/source/STATICREFTAB_Tests.cpp b/ReHitman/Glacier/Tests/source/STATICREFTAB_Tests.cpp new file mode 100644 index 0000000..0c0d081 --- /dev/null +++ b/ReHitman/Glacier/Tests/source/STATICREFTAB_Tests.cpp @@ -0,0 +1,95 @@ +#include +#include + +using namespace Glacier; + +TEST(STATICREFTAB, AddSingle) +{ + auto* tab = new STATICREFTAB(4, 5); + + EXPECT_EQ(tab->Count(), 0); + + auto* p = tab->Add(123); + + ASSERT_NE(p, nullptr); + EXPECT_EQ(tab->Count(), 1); + + delete tab; +} + +TEST(STATICREFTAB, ReuseFreedSlot) +{ + auto* tab = new STATICREFTAB(4, 5); + + auto* a = tab->Add(1); + auto* b = tab->Add(2); + + EXPECT_EQ(tab->Count(), 2); + + tab->DelRefPtr(a); + + EXPECT_EQ(tab->Count(), 1); + + auto* c = tab->Add(3); + + EXPECT_EQ(tab->Count(), 2); + EXPECT_NE(c, nullptr); + EXPECT_NE(c, b); + + delete tab; +} + +TEST(STATICREFTAB, AllocateMultipleBlocks) +{ + auto* tab = new STATICREFTAB(2, 5); + + EXPECT_EQ(tab->Count(), 0); + + tab->Add(1); + tab->Add(2); + tab->Add(3); + + EXPECT_EQ(tab->Count(), 3); + + delete tab; +} + +TEST(STATICREFTAB, DeleteEmptyBlock) +{ + auto* tab = new STATICREFTAB(2, 5); + + auto* a = tab->Add(1); + auto* b = tab->Add(2); + + EXPECT_EQ(tab->Count(), 2); + + tab->DelRefPtr(a); + EXPECT_EQ(tab->Count(), 1); + + tab->DelRefPtr(b); + EXPECT_EQ(tab->Count(), 0); + + auto* c = tab->Add(3); + + ASSERT_NE(c, nullptr); + EXPECT_EQ(tab->Count(), 1); + + delete tab; +} + +TEST(STATICREFTAB, Clear) +{ + auto* tab = new STATICREFTAB(4, 5); + + tab->Add(10); + tab->Add(20); + tab->Add(30); + + EXPECT_EQ(tab->Count(), 3); + + tab->Clear(); + + EXPECT_EQ(tab->Count(), 0); + + delete tab; +} \ No newline at end of file diff --git a/ReHitman/Glacier/Tests/source/STRREFTAB_Tests.cpp b/ReHitman/Glacier/Tests/source/STRREFTAB_Tests.cpp new file mode 100644 index 0000000..0742d29 --- /dev/null +++ b/ReHitman/Glacier/Tests/source/STRREFTAB_Tests.cpp @@ -0,0 +1,223 @@ +#include + +#include + +using namespace Glacier; + +TEST(STRREFTAB, ConstructorInitialization) +{ + STRREFTAB tab(4, 1); + + EXPECT_EQ(tab.Count(), 0u); + EXPECT_FALSE(tab.Exists("test")); + EXPECT_EQ(tab.FindStr("test"), nullptr); +} + +TEST(STRREFTAB, AddAndFind) +{ + STRREFTAB tab(4, 1); + + EXPECT_NE(tab.AddStr("Alpha"), nullptr); + EXPECT_NE(tab.FindStr("Alpha"), nullptr); + EXPECT_TRUE(tab.Exists("Alpha")); + + EXPECT_EQ(tab.Count(), 1u); +} + +TEST(STRREFTAB, AddDuplicateRejected) +{ + STRREFTAB tab(4, 1); + + EXPECT_NE(tab.AddStr("Alpha"), nullptr); + EXPECT_EQ(tab.AddStr("Alpha"), nullptr); + + EXPECT_EQ(tab.Count(), 1u); +} + +TEST(STRREFTAB, AddAlwaysAllowsDuplicates) +{ + STRREFTAB tab(4, 1); + + EXPECT_NE(tab.AddAlways("Alpha"), nullptr); + EXPECT_NE(tab.AddAlways("Alpha"), nullptr); + + EXPECT_EQ(tab.Count(), 2u); +} + +TEST(STRREFTAB, RemoveExistingString) +{ + STRREFTAB tab(4, 1); + + tab.AddStr("Alpha"); + tab.AddStr("Beta"); + tab.AddStr("Gamma"); + + tab.RemoveStr("Beta"); + + EXPECT_FALSE(tab.Exists("Beta")); + EXPECT_TRUE(tab.Exists("Alpha")); + EXPECT_TRUE(tab.Exists("Gamma")); + + EXPECT_EQ(tab.Count(), 2u); +} + +TEST(STRREFTAB, RemoveMissingStringDoesNothing) +{ + STRREFTAB tab(4, 1); + + tab.AddStr("Alpha"); + tab.AddStr("Beta"); + + tab.RemoveStr("NoSuchString"); + + EXPECT_EQ(tab.Count(), 2u); + EXPECT_TRUE(tab.Exists("Alpha")); + EXPECT_TRUE(tab.Exists("Beta")); +} + +TEST(STRREFTAB, CaseInsensitiveSearch) +{ + STRREFTAB tab(4, 1); + + tab.m_bCaseSensitive = false; + + tab.AddStr("Hello"); + + EXPECT_TRUE(tab.Exists("hello")); + EXPECT_TRUE(tab.Exists("HELLO")); + EXPECT_NE(tab.FindStr("hElLo"), nullptr); +} + +TEST(STRREFTAB, CaseSensitiveSearch) +{ + STRREFTAB tab(4, 1); + + tab.m_bCaseSensitive = true; + + tab.AddStr("Hello"); + + EXPECT_TRUE(tab.Exists("Hello")); + EXPECT_FALSE(tab.Exists("hello")); + + EXPECT_NE(tab.FindStr("Hello"), nullptr); + EXPECT_EQ(tab.FindStr("hello"), nullptr); +} + +TEST(STRREFTAB, SortAlphabetically) +{ + STRREFTAB tab(2, 1); + + tab.AddAlways("Charlie"); + tab.AddAlways("Alpha"); + tab.AddAlways("Bravo"); + + tab.Sort(); + + RefRun it; + tab.RunInitNxtRef(&it); + + EXPECT_STREQ(reinterpret_cast(tab.RunNxtRef(&it)), "Alpha"); + EXPECT_STREQ(reinterpret_cast(tab.RunNxtRef(&it)), "Bravo"); + EXPECT_STREQ(reinterpret_cast(tab.RunNxtRef(&it)), "Charlie"); +} + +TEST(STRREFTAB, SortCaseInsensitive) +{ + STRREFTAB tab(2, 1); + + tab.AddAlways("zebra"); + tab.AddAlways("Apple"); + tab.AddAlways("banana"); + + tab.Sort(); + + RefRun it; + tab.RunInitNxtRef(&it); + + EXPECT_STREQ(reinterpret_cast(tab.RunNxtRef(&it)), "Apple"); + EXPECT_STREQ(reinterpret_cast(tab.RunNxtRef(&it)), "banana"); + EXPECT_STREQ(reinterpret_cast(tab.RunNxtRef(&it)), "zebra"); +} + +TEST(STRREFTAB, SortMultipleBlocks) +{ + STRREFTAB tab(2, 1); + + tab.AddAlways("Echo"); + tab.AddAlways("Delta"); + tab.AddAlways("Charlie"); + tab.AddAlways("Bravo"); + tab.AddAlways("Alpha"); + + tab.Sort(); + + static const char* expected[] = + { + "Alpha", + "Bravo", + "Charlie", + "Delta", + "Echo" + }; + + int idx = 0; + for (auto entry : tab) + { + EXPECT_STREQ((const char*)entry, expected[idx]); + ++idx; + } + + EXPECT_EQ(idx, 5); +} + +TEST(STRREFTAB, ClearRemovesEverything) +{ + STRREFTAB tab(2, 1); + + tab.AddAlways("One"); + tab.AddAlways("Two"); + tab.AddAlways("Three"); + + tab.Clear(); + + EXPECT_EQ(tab.Count(), 0u); + EXPECT_FALSE(tab.Exists("One")); + EXPECT_EQ(tab.FindStr("Two"), nullptr); + + RefRun it; + tab.RunInitNxtRef(&it); + EXPECT_EQ(tab.RunNxtRef(&it), 0u); +} + +TEST(STRREFTAB, SortAfterDeletion) +{ + STRREFTAB tab(2, 1); + + tab.AddAlways("Delta"); + tab.AddAlways("Alpha"); + tab.AddAlways("Charlie"); + tab.AddAlways("Bravo"); + + tab.RemoveStr("Charlie"); + + tab.Sort(); + + const char* expected[] = + { + "Alpha", + "Bravo", + "Delta" + }; + + RefRun it; + tab.RunInitNxtRef(&it); + + int idx = 0; + for (auto entry : tab) + { + EXPECT_STREQ((const char*)entry, expected[idx]); + ++idx; + } + + EXPECT_EQ(idx, 3); +} \ No newline at end of file diff --git a/ReHitman/Glacier/Tests/source/SimpleXML_Tests.cpp b/ReHitman/Glacier/Tests/source/SimpleXML_Tests.cpp new file mode 100644 index 0000000..cef6d45 --- /dev/null +++ b/ReHitman/Glacier/Tests/source/SimpleXML_Tests.cpp @@ -0,0 +1,228 @@ +#include +#include + +#include +#include +#include + +using namespace Glacier; + +namespace +{ + struct XMLEvent + { + std::string Name; + bool IsStart; + std::vector> Attrs; + }; + + struct CapturingSimpleXML : SimpleXML + { + std::vector Events; + + void startElement(const char* name, const char** attrs) override + { + XMLEvent event; + event.Name = name ? name : ""; + event.IsStart = true; + + for (int i = 0; attrs && attrs[i]; i += 2) + { + event.Attrs.emplace_back(attrs[i], attrs[i + 1] ? attrs[i + 1] : ""); + } + + Events.push_back(event); + } + + void endElement(const char* name) override + { + Events.push_back({name ? name : "", false, {}}); + } + }; + + std::vector MakeBuffer(const char* xml) + { + return std::vector(xml, xml + std::strlen(xml)); + } +} + +TEST(SimpleXML, ConstructorInitializesEmptyState) +{ + SimpleXML xml; + + EXPECT_EQ(xml.m_pStart, nullptr); + EXPECT_EQ(xml.m_pEnd, nullptr); + EXPECT_EQ(xml.m_p, nullptr); + EXPECT_EQ(xml.m_Len, 0); + EXPECT_EQ(xml.m_pTag, nullptr); + EXPECT_EQ(xml.m_nAttributes, 0); + EXPECT_EQ(xml.m_Attributes[0], nullptr); +} + +TEST(SimpleXML, ParseStartAndEndElements) +{ + CapturingSimpleXML xml; + auto buffer = MakeBuffer(""); + + EXPECT_EQ(xml.XML_Parse(buffer.data(), static_cast(buffer.size()), 1), 1); + + ASSERT_EQ(xml.Events.size(), 4u); + EXPECT_TRUE(xml.Events[0].IsStart); + EXPECT_EQ(xml.Events[0].Name, "root"); + EXPECT_TRUE(xml.Events[1].IsStart); + EXPECT_EQ(xml.Events[1].Name, "child"); + EXPECT_FALSE(xml.Events[2].IsStart); + EXPECT_EQ(xml.Events[2].Name, "child"); + EXPECT_FALSE(xml.Events[3].IsStart); + EXPECT_EQ(xml.Events[3].Name, "root"); +} + +TEST(SimpleXML, ParseSelfClosingElementEmitsStartAndEnd) +{ + CapturingSimpleXML xml; + auto buffer = MakeBuffer(""); + + EXPECT_EQ(xml.XML_Parse(buffer.data(), static_cast(buffer.size()), 1), 1); + + ASSERT_EQ(xml.Events.size(), 4u); + EXPECT_EQ(xml.Events[0].Name, "root"); + EXPECT_TRUE(xml.Events[0].IsStart); + EXPECT_EQ(xml.Events[1].Name, "leaf"); + EXPECT_TRUE(xml.Events[1].IsStart); + EXPECT_EQ(xml.Events[2].Name, "leaf"); + EXPECT_FALSE(xml.Events[2].IsStart); + EXPECT_EQ(xml.Events[3].Name, "root"); + EXPECT_FALSE(xml.Events[3].IsStart); +} + +TEST(SimpleXML, ParseAttributesAndGetAttr) +{ + CapturingSimpleXML xml; + auto buffer = MakeBuffer(""); + + EXPECT_EQ(xml.XML_Parse(buffer.data(), static_cast(buffer.size()), 1), 1); + + ASSERT_GE(xml.Events.size(), 1u); + ASSERT_EQ(xml.Events[0].Attrs.size(), 3u); + + EXPECT_EQ(xml.Events[0].Attrs[0].first, "id"); + EXPECT_EQ(xml.Events[0].Attrs[0].second, "42"); + EXPECT_EQ(xml.Events[0].Attrs[1].first, "name"); + EXPECT_EQ(xml.Events[0].Attrs[1].second, "agent_47"); + EXPECT_EQ(xml.Events[0].Attrs[2].first, "value"); + EXPECT_EQ(xml.Events[0].Attrs[2].second, "hello-world"); + + const char* attrs[] = {"id", "42", "name", "agent_47", nullptr}; + EXPECT_STREQ(xml.GetAttr(attrs, "id"), "42"); + EXPECT_STREQ(xml.GetAttr(attrs, "name"), "agent_47"); + EXPECT_EQ(xml.GetAttr(attrs, "missing"), nullptr); + EXPECT_EQ(xml.GetAttr(nullptr, "id"), nullptr); + EXPECT_EQ(xml.GetAttr(attrs, nullptr), nullptr); +} + +TEST(SimpleXML, ParseQuotedAttributeKeepsLeadingQuoteLikeOriginalParser) +{ + CapturingSimpleXML xml; + auto buffer = MakeBuffer(""); + + EXPECT_EQ(xml.XML_Parse(buffer.data(), static_cast(buffer.size()), 1), 1); + + ASSERT_GE(xml.Events.size(), 1u); + ASSERT_EQ(xml.Events[0].Attrs.size(), 1u); + EXPECT_EQ(xml.Events[0].Attrs[0].first, "name"); + EXPECT_EQ(xml.Events[0].Attrs[0].second, "\"agent"); +} + +TEST(SimpleXML, CommentsAreSkippedDuringParse) +{ + CapturingSimpleXML xml; + auto buffer = MakeBuffer(""); + + EXPECT_EQ(xml.XML_Parse(buffer.data(), static_cast(buffer.size()), 1), 1); + + ASSERT_EQ(xml.Events.size(), 2u); + EXPECT_EQ(xml.Events[0].Name, "root"); + EXPECT_TRUE(xml.Events[0].IsStart); + EXPECT_EQ(xml.Events[1].Name, "root"); + EXPECT_FALSE(xml.Events[1].IsStart); +} + +TEST(SimpleXML, GetElementCanBeUsedManually) +{ + SimpleXML xml; + auto buffer = MakeBuffer(""); + + xml.m_pStart = buffer.data(); + xml.m_p = buffer.data(); + xml.m_pEnd = buffer.data() + buffer.size(); + + EXPECT_EQ(xml.getElement(), SimpleXML::XML_STARTEND); + ASSERT_NE(xml.m_pTag, nullptr); + EXPECT_STREQ(xml.m_pTag, "root"); + + EXPECT_EQ(xml.getElement(), SimpleXML::XML_START); + ASSERT_NE(xml.m_pTag, nullptr); + EXPECT_STREQ(xml.m_pTag, "tail"); + + EXPECT_EQ(xml.getElement(), SimpleXML::XML_END); + ASSERT_NE(xml.m_pTag, nullptr); + EXPECT_STREQ(xml.m_pTag, "tail"); + + EXPECT_EQ(xml.getElement(), SimpleXML::XML_ENDOFDATA); +} + +TEST(SimpleXML, MissingCommentEndThrows) +{ + CapturingSimpleXML xml; + auto buffer = MakeBuffer("