#pragma once #include "Defines.hpp" namespace PatchFix { namespace Accessors { enum GameState { GAMESTATE_IN_GAME = 6 }; enum UnitType { UNITTYPE_COMMANDER, UNITTYPE_BUILDER, UNITTYPE_FIGHTER, UNITTYPE_STRUCTURE, UNITTYPE_AIRCRAFT, UNITTYPE_HOVERCRAFT, UNITTYPE_GROUND }; enum UnitInfoMask_0 { BUILDER = 0x40, FIGHTER = 0x2, CANMOVE = 0x1 }; enum UnitInfoMask_1 { SHOWPLAYERNAME = 0x20000, COMMANDER = 0x40000 }; const DwordPtr TADynMemStructAddr = (DwordPtr)0x511DE8; const DwordPtr TAProgramStructAddr = (DwordPtr)0x51FBD0; const Dword TAGameStateOffsetDword = 0x391F1; const Dword TAMapPathfindingStructOffsetDword = 0x14207; const Dword TAPlayerStructOffsetDword = 0x1B63; const Dword TAGameTimeOffset = 0x38A47; const Dword TAPlayerStructSize = 0x14B; const Dword TAPlayerStructPlayerTypeOffset = 0x73; const Dword TAPlayerStructResourcesOffset = 0x8C; const Dword TAPlayerStructResourceMetalIncomeOffset = 0x10; const Dword TAPlayerStructResourceMetalDrainOffset = 0x14; const Dword TAPlayerStructResourceEnergyIncomeOffset = 0x4; const Dword TAPlayerStructResourceEnergyDrainOffset = 0x8; const Dword TAPlayerStructResourceMetalAmountOffset = 0xC; const Dword TAPlayerStructResourceEnergyAmountOffset = 0x0; const Dword TAPlayerStructResourceMetalStorageTotalOffset = 0x1C; const Dword TAPlayerStructResourceEnergyStorageTotalOffset = 0x18; const Dword TAPlayerStructStartUnitsPtrOffset = 0x67; const Dword TAPlayerStructEndUnitsPtrOffset = 0x6B; const Dword TAUnitStructSize = 0x118; const Dword TAUnitStructInGameIndexOffset = 0xA8; const Dword TAUnitStructHealthOffset = 0x108; const Dword TAUnitsBeginOffset = 0x14357; const Dword TAUnitsEndOffset = 0x1435B; Dword GetGameState(); DwordPtr GetMapPathfindingStruct(); DwordPtr GetTAProgramStruct(); DwordPtr GetOffscreenSurface(); BytePtr GetOffscreenStartPixelsPtr(); Dword GetScreenWidth(); Dword GetScreenHeight(); Dword GetTotalPlayersCount(); DwordPtr GetPlayerPtrByIndex(Dword Index); Dword GetPlayerActiveByIndex(Dword Index); float GetPlayerMetalIncome(Dword Index); float GetPlayerMetalDrain(Dword Index); float GetPlayerEnergyIncome(Dword Index); float GetPlayerEnergyDrain(Dword Index); float GetPlayerMetalAmount(Dword Index); float GetPlayerEnergyAmount(Dword Index); float GetPlayerMetalStorageTotal(Dword Index); float GetPlayerEnergyStorageTotal(Dword Index); short GetUnitIndexByUnitType(Dword Index, Dword UnitType); DwordPtr GetUnitPtrByUnitIndex(Dword Index); Dword GetGameTime(); } } Dword PatchFix::Accessors::GetGameState() { return *((DwordPtr)((BytePtr)*TADynMemStructAddr + TAGameStateOffsetDword)); } DwordPtr PatchFix::Accessors::GetMapPathfindingStruct() { return (DwordPtr)(*((DwordPtr)((BytePtr)*TADynMemStructAddr + TAMapPathfindingStructOffsetDword))); } DwordPtr PatchFix::Accessors::GetTAProgramStruct() { return (DwordPtr)((BytePtr)*TAProgramStructAddr); } DwordPtr PatchFix::Accessors::GetOffscreenSurface() { DwordPtr TAProgramStructPtr = GetTAProgramStruct(); return (DwordPtr)*((BytePtr)TAProgramStructPtr + 0xBC); } BytePtr PatchFix::Accessors::GetOffscreenStartPixelsPtr() { DwordPtr OffscreenSurfacePtr = GetOffscreenSurface(); return ((BytePtr)OffscreenSurfacePtr + 48); } Dword PatchFix::Accessors::GetScreenWidth() { return *((BytePtr)TAProgramStructAddr + 0xD4); } Dword PatchFix::Accessors::GetScreenHeight() { return *((BytePtr)TAProgramStructAddr + 0xD8); } Dword PatchFix::Accessors::GetTotalPlayersCount() { Dword Result = 0; for (Dword I = 0; I < 10; I++) { if (((Dword)(*(((BytePtr)*TADynMemStructAddr + TAPlayerStructOffsetDword) + I * TAPlayerStructSize + TAPlayerStructPlayerTypeOffset))) > 0) { Result++; } } return Result; } DwordPtr PatchFix::Accessors::GetPlayerPtrByIndex(Dword Index) { return ((DwordPtr)((BytePtr)*TADynMemStructAddr + TAPlayerStructOffsetDword + Index * TAPlayerStructSize)); } Dword PatchFix::Accessors::GetPlayerActiveByIndex(Dword Index) { Dword Result = 0; DwordPtr PlayerPtrByIndex = GetPlayerPtrByIndex(Index); if (((Dword)(*((BytePtr)PlayerPtrByIndex + TAPlayerStructPlayerTypeOffset))) > 0) { return 1; // Player Is Active } return 0; // Player Is Not Active } float PatchFix::Accessors::GetPlayerMetalIncome(Dword Index) { DwordPtr PlayerPtrByIndex = GetPlayerPtrByIndex(Index); return *((FloatPtr)((BytePtr)PlayerPtrByIndex + TAPlayerStructResourcesOffset + TAPlayerStructResourceMetalIncomeOffset)); } float PatchFix::Accessors::GetPlayerMetalDrain(Dword Index) { DwordPtr PlayerPtrByIndex = GetPlayerPtrByIndex(Index); return *((FloatPtr)((BytePtr)PlayerPtrByIndex + TAPlayerStructResourcesOffset + TAPlayerStructResourceMetalDrainOffset)); } float PatchFix::Accessors::GetPlayerEnergyIncome(Dword Index) { DwordPtr PlayerPtrByIndex = GetPlayerPtrByIndex(Index); return *((FloatPtr)((BytePtr)PlayerPtrByIndex + TAPlayerStructResourcesOffset + TAPlayerStructResourceEnergyIncomeOffset)); } float PatchFix::Accessors::GetPlayerEnergyDrain(Dword Index) { DwordPtr PlayerPtrByIndex = GetPlayerPtrByIndex(Index); return *((FloatPtr)((BytePtr)PlayerPtrByIndex + TAPlayerStructResourcesOffset + TAPlayerStructResourceEnergyDrainOffset)); } float PatchFix::Accessors::GetPlayerMetalAmount(Dword Index) { DwordPtr PlayerPtrByIndex = GetPlayerPtrByIndex(Index); return *((FloatPtr)((BytePtr)PlayerPtrByIndex + TAPlayerStructResourcesOffset + TAPlayerStructResourceMetalAmountOffset)); } float PatchFix::Accessors::GetPlayerEnergyAmount(Dword Index) { DwordPtr PlayerPtrByIndex = GetPlayerPtrByIndex(Index); return *((FloatPtr)((BytePtr)PlayerPtrByIndex + TAPlayerStructResourcesOffset + TAPlayerStructResourceEnergyAmountOffset)); } float PatchFix::Accessors::GetPlayerMetalStorageTotal(Dword Index) { DwordPtr PlayerPtrByIndex = GetPlayerPtrByIndex(Index); return *((FloatPtr)((BytePtr)PlayerPtrByIndex + TAPlayerStructResourcesOffset + TAPlayerStructResourceMetalStorageTotalOffset)); } float PatchFix::Accessors::GetPlayerEnergyStorageTotal(Dword Index) { DwordPtr PlayerPtrByIndex = GetPlayerPtrByIndex(Index); return *((FloatPtr)((BytePtr)PlayerPtrByIndex + TAPlayerStructResourcesOffset + TAPlayerStructResourceEnergyStorageTotalOffset)); } short PatchFix::Accessors::GetUnitIndexByUnitType(Dword Index, Dword UnitType) { DwordPtr PlayerPtrByIndex = GetPlayerPtrByIndex(Index); BytePtr PlayerUnitsStartPtr = (BytePtr)*(DwordPtr)((BytePtr)PlayerPtrByIndex + TAPlayerStructStartUnitsPtrOffset); BytePtr PlayerUnitsEndPtr = (BytePtr)*(DwordPtr)((BytePtr)PlayerPtrByIndex + TAPlayerStructEndUnitsPtrOffset); BytePtr PlayerCurrentUnit = PlayerUnitsStartPtr; short PlayerCurrentUnitHealth; DwordPtr PlayerCurrentUnitInfo; Dword UnitMaskToCheck = 0; Dword UnitMaskToCheck2 = 0; short UnitIndex = 0; if (UnitType == UNITTYPE_COMMANDER) { while (PlayerCurrentUnit < PlayerUnitsEndPtr) { PlayerCurrentUnitHealth = *(short*)((BytePtr)PlayerCurrentUnit + TAUnitStructHealthOffset); if (PlayerCurrentUnitHealth > 0) { PlayerCurrentUnitInfo = (DwordPtr)*(DwordPtr)((BytePtr)PlayerCurrentUnit + 0x92); UnitMaskToCheck = *(DwordPtr)((BytePtr)PlayerCurrentUnitInfo + 0x245); if ( ((UnitMaskToCheck & UnitInfoMask_1::SHOWPLAYERNAME) != 0) && ((UnitMaskToCheck & UnitInfoMask_1::COMMANDER) != 0) ) { UnitIndex = *(short*)((BytePtr)PlayerCurrentUnit + 0xA8); break; } } PlayerCurrentUnit += TAUnitStructSize; } } else if (UnitType == UNITTYPE_BUILDER) { while (PlayerCurrentUnit < PlayerUnitsEndPtr) { PlayerCurrentUnitHealth = *(short*)((BytePtr)PlayerCurrentUnit + TAUnitStructHealthOffset); if (PlayerCurrentUnitHealth > 0) { PlayerCurrentUnitInfo = (DwordPtr)*(DwordPtr)((BytePtr)PlayerCurrentUnit + 0x92); UnitMaskToCheck = *(DwordPtr)((BytePtr)PlayerCurrentUnitInfo + 0x241); UnitMaskToCheck2 = *(DwordPtr)((BytePtr)PlayerCurrentUnitInfo + 0x245); if ( ((UnitMaskToCheck & UnitInfoMask_0::BUILDER) != 0) && ((UnitMaskToCheck2 & UnitInfoMask_1::SHOWPLAYERNAME) == 0) && ((UnitMaskToCheck2 & UnitInfoMask_1::COMMANDER) == 0) ) { UnitIndex = *(short*)((BytePtr)PlayerCurrentUnit + 0xA8); break; } } PlayerCurrentUnit += TAUnitStructSize; } } else if (UnitType == UNITTYPE_FIGHTER) { while (PlayerCurrentUnit < PlayerUnitsEndPtr) { PlayerCurrentUnitHealth = *(short*)((BytePtr)PlayerCurrentUnit + TAUnitStructHealthOffset); if (PlayerCurrentUnitHealth > 0) { PlayerCurrentUnitInfo = (DwordPtr)*(DwordPtr)((BytePtr)PlayerCurrentUnit + 0x92); UnitMaskToCheck = *(DwordPtr)((BytePtr)PlayerCurrentUnitInfo + 0x241); UnitMaskToCheck2 = *(DwordPtr)((BytePtr)PlayerCurrentUnitInfo + 0x245); if ( ((UnitMaskToCheck & UnitInfoMask_0::FIGHTER) != 0) && ((UnitMaskToCheck2 & UnitInfoMask_1::SHOWPLAYERNAME) == 0) && ((UnitMaskToCheck2 & UnitInfoMask_1::COMMANDER) == 0) ) { UnitIndex = *(short*)((BytePtr)PlayerCurrentUnit + 0xA8); break; } } PlayerCurrentUnit += TAUnitStructSize; } } else if (UnitType == UNITTYPE_STRUCTURE) { while (PlayerCurrentUnit < PlayerUnitsEndPtr) { PlayerCurrentUnitHealth = *(short*)((BytePtr)PlayerCurrentUnit + TAUnitStructHealthOffset); if (PlayerCurrentUnitHealth > 0) { PlayerCurrentUnitInfo = (DwordPtr)*(DwordPtr)((BytePtr)PlayerCurrentUnit + 0x92); UnitMaskToCheck = *(DwordPtr)((BytePtr)PlayerCurrentUnitInfo + 0x241); UnitMaskToCheck2 = *(DwordPtr)((BytePtr)PlayerCurrentUnitInfo + 0x245); if ( ((UnitMaskToCheck & UnitInfoMask_0::CANMOVE) == 0) && ((UnitMaskToCheck2 & UnitInfoMask_1::SHOWPLAYERNAME) == 0) && ((UnitMaskToCheck2 & UnitInfoMask_1::COMMANDER) == 0) ) { UnitIndex = *(short*)((BytePtr)PlayerCurrentUnit + 0xA8); break; } } PlayerCurrentUnit += TAUnitStructSize; } } return UnitIndex; } // This can easily be made more efficient by just calculating the index times unit struct from units start array DwordPtr PatchFix::Accessors::GetUnitPtrByUnitIndex(Dword Index) { BytePtr UnitsArrayBegin = (BytePtr)*(DwordPtr)((BytePtr)*TADynMemStructAddr + TAUnitsBeginOffset); BytePtr UnitsArrayEnd = (BytePtr)*(DwordPtr)((BytePtr)*TADynMemStructAddr + TAUnitsEndOffset); BytePtr CurrentUnit = UnitsArrayBegin; short CurrentUnitHealth; short UnitIndex; while (CurrentUnit < UnitsArrayEnd) { CurrentUnitHealth = *((BytePtr)CurrentUnit + TAUnitStructHealthOffset); if (CurrentUnitHealth > 0) { UnitIndex = *((BytePtr)CurrentUnit + 0xA8); if (Index == UnitIndex) { break; } } CurrentUnit += TAUnitStructSize; } return (DwordPtr)CurrentUnit; } Dword PatchFix::Accessors::GetGameTime() { return *((DwordPtr)((BytePtr)*TADynMemStructAddr + TAGameTimeOffset)); }