From OPU Wiki
// Requires extended unit function library: http://www.wiki.outpost-universe.net/Op2extra
/* Note: Notice that I used '<IUnit.h>' instead of ' "IUnit.h" '.
This is because I had the file in my SDK lib folder.
If you just have it as part of your project, use ' #include "IUnit.h" ' instead. */
#include <IUnit.h>
// These are used to let us access more information about a tile than OP2 wants us to.
unsigned char *setTileLoc = (unsigned char *)0x00476D32;
unsigned char oldSetTile[] =
{
0x25, 0xE0, 0xFF, 0x00, 0x00, // and eax, 0FFE0h
0xC1, 0xE8, 0x05 // shr eax, 5
};
unsigned char newSetTile[] =
{
0x90, 0x90, 0x90, 0x90, 0x90, // nop * 5
0x90, 0x90, 0x90 // nop * 3
};
struct mapCell
{
int cellType:5;
int tileIndex:11;
int unitID:11;
int lava:1;
int lavaPossible:1;
int expand:1;
int microbe:1;
int wallBuilding:1;
};
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
DWORD oldAttr;
if (fdwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hinstDLL);
// Modify the SetTile code for our purposes
VirtualProtect(setTileLoc, sizeof(newSetTile), PAGE_EXECUTE_READWRITE, &oldAttr);
memcpy(setTileLoc, newSetTile, sizeof(newSetTile));
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
// Put the old SetTile code back
memcpy(setTileLoc, oldSetTile, sizeof(newSetTile));
}
return TRUE;
}
/* Note: This function is a tad bit flawed... it only retrieves the hit points of that unit for player 0.
Not a problem for structures, though. */
int GetHitPoints(Unit &unit)
{
int unitObj = *((int*)0x54F848) + (120*unit.unitID);
int hp = 0;
__asm
{
mov ecx, unitObj
mov eax, [ecx]
call [eax]
add eax, 8
mov eax, [eax]
mov hp, eax
}
return hp;
}
void AIProc()
{
{
for (int i = 0; i < TethysGame::NoPlayers(); i++)
{
// This kills off any buildings that get infected with blight
IUnit curUnit;
PlayerBuildingEnum unitEnum(i, mapNone);
// Enumerate all structures for player 0
while (unitEnum.GetNext(curUnit))
{
mapCell cell;
// Get the tile data for the unit's location
int tile = GameMap::GetTile(curUnit.Location());
// Do some magic and convert it to a usable form.
memcpy(&cell, &tile, 4);
// If the blight has infected the tile, kill the unit.
if (cell.expand || cell.microbe) {
curUnit.SetDamage(curUnit.GetDamage()+7+TethysGame::GetRand(5));
if (curUnit.GetDamage() >= GetHitPoints(curUnit)) // WHY CAN'T UNITS JUST AUTOMATICALLY DIE WHEN THEY REACH 0 HP?!
curUnit.DoDeath();
}
}
}
}