394 lines
11 KiB
C++
394 lines
11 KiB
C++
|
|
||
|
#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));
|
||
|
}
|