Blighted Structure Decay Code

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();
            }
        }
    }
}

Personal tools