These routines are working fine now.
I'm open to suggestions and updates/tests.
It uses the extended units structure (IUnit). Header and libraries available for download
here (read also
this post).
Please do not distribute any altered code, but run it by me first.#include "RepairAI.h"
#include "OP2extra.h"
#include "IUnit.h" // extended units
int Repairs[512][7]; // contains UnitIDs of convecs repairing those buildings
// space for 512 buildings for each player
bool RepairGPs;
/*
SetupRepairAI(bool FixGPs)
Call SetupRepairAI to set up the repair-AI.
It will create a timer, and check ALL buildings for possible damage.
(if FixGPs is set to false, GPs are NOT fixed. This was added because damaged GPs
can explode when the convec is right next to it)
*/
void SetupRepairAI(bool FixGPs)
{
RepairGPs=FixGPs;
CreateTimeTrigger(1,0,500,"Repair_CheckDamage"); // check every 5 time-marks
}
/*
IsDockedWithSF(Unit convec)
Checks if the specified convec is positioned on an SF docking pad.
Docked convec will not be sent out for repairs.
*/
bool IsDockedWithSF(Unit convec)
{
Unit u;
LOCATION loc=convec.Location();
int dockpos=(Player[convec.OwnerID()].IsEden())?1:-2;
if (LocationEnumerator(LOCATION(loc.x-dockpos,loc.y-1)).GetNext(u))
return (u.GetType()==mapStructureFactory);
else return false;
}
/*
FindConvec(LOCATION loc,int playernum)
Finds the closest convec (owned by playernum).
It looks only for convecs with a distance of 2^19 of the specified location
(see wiki pages on how to calculate distance in OP2).
*/
int FindConvec(LOCATION loc,int playernum)
{
IUnit u;
map_id cargo,weapon;
ClosestEnumerator closest(loc);
unsigned long d;
while (closest.GetNext(u,d)) // get next closest IUnit
{
if (d>>19) break; // too far away -> stop loop!
if (u.OwnerID()!=playernum) continue; // not owned by this player
// is it a RepairVehicle or ConVec, and available ?
if (u.IsLive() && !u.IsBusy())
{
switch (u.GetType())
{
case mapConVec:
if (IsDockedWithSF(u)) continue; // is convec waiting for kit ?
u.GetCargo(cargo,weapon);
if (cargo==mapNone) return u.unitID; // does it have cargo ?
break;
case mapRepairVehicle:
return u.unitID;
}
}
}
return 0;
}
/*
DoCheck(int playernum)
This is the main routine for checking damages. It should be called for every AI player.
The routine stores what convecs already have repairing orders, so it does not give them
any new orders, overwriting the old ones. Vice versa: if the building is not yet 100%
repaired before the next time this routine is called, it will not send another convec
in to repair it.
It repairs any buildings that have more than 100 points damage to them, excluding
buildings that are currently being constructed or dismantled. This DOES include buildings
that are currently under attack.
*/
void DoCheck(int playernum)
{
IUnit u,convec;
int i=mapCommonOreMine-1,id;
while (++i<=mapTokamak)
{
if (!RepairGPs && (i==mapGuardPost)) // do not repair GPs
continue;
PlayerBuildingEnum enum1(playernum,(map_id)i);
while (enum1.GetNext(u)) // browse all buildings
{
if (u.GetDamage()>100) // find one that is damaged
{
if (u.IsVehicle()) continue; // only buildings !
if (u.IsLive()) switch (u.GetBusy())
{
case ctMoDevelop: // is being constructed ?
case ctMoUnDevelop: // is being dismantled ?
case ctMoDismantle:
continue; // don't repair
default:
id=Repairs[u.unitID][playernum];
if (id>0)
{
convec.SetId(id);
if ((convec.GetBusy()==ctMoRepairObj) && convec.IsLive() && (convec.GetType()==mapConVec))
continue; // building alreading being repaired
else Repairs[u.unitID][playernum]=0;
}
id=FindConvec(u.Location(),playernum); // get closest convec
if (id>0)
{
convec.SetId(id);
convec.Repair(u);
Repairs[u.unitID][playernum]=id; // remember which convec is repairing this building
}
}
}
else Repairs[u.unitID][playernum]=0;
}
}
}
/*
Repair_CheckDamage()
Main trigger response function is called every 5 time-marks, and loops through all AI players,
calling DoCheck for every player.
*/
EXPORT void Repair_CheckDamage()
{
for (int i=0; i<TethysGame::NoPlayers(); ++i)
{
if (!Player.IsHuman())
DoCheck(i);
}
}
//----------------------------------------------------------------------------------------
// RepairAI
//----------------------------------------------------------------------------------------
// SetupRepairAI:
// Calls CheckDamage every 5 gameticks to check for damaged buildings
// and have convecsc repair them.
//----------------------------------------------------------------------------------------
#ifndef REPAIRAI_H
#define REPAIRAI_H
void SetupRepairAI(bool FixGPs=false);
#endif // REPAIRAI_H
PS: sorry about the paste - the tabs don't work out that well in forum.. i'll upload the files in a minute