Diff
checker
Texto
Texto
Imágenes
Documentos
Excel
Carpetas
Legal
Enterprise
Aplicación de escritorio
Precios
Iniciar sesión
Descargar Diffchecker Desktop
Comparar texto
Encuentra la diferencia entre dos archivos de texto
Herramientas
Historial
Editor live
Ocultar sin cambios
Sin ajuste de línea
Vista
Dividido
Unificado
Nivel de detalle
Inteligente
Palabra
Letra
Resaltado de sintaxis
Elegir sintaxis
Ignorar
Transformar texto
Ir al primer cambio
Editar entrada
Diffchecker Desktop
La forma más segura de usar Diffchecker. ¡Obtén la app de Diffchecker Desktop: tus diffs nunca salen de tu computadora!
Obtener Desktop
Untitled diff
Creado
hace 9 años
El diff nunca expira
Borrar
Exportar
Compartir
Explicar
33 eliminaciones
Líneas
Total
Eliminado
Caracteres
Total
Eliminado
Para continuar usando esta función, actualice a
Diff
checker
Pro
Ver precios
835 líneas
Copiar todo
32 adiciones
Líneas
Total
Añadido
Caracteres
Total
Añadido
Para continuar usando esta función, actualice a
Diff
checker
Pro
Ver precios
834 líneas
Copiar todo
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// general ai for skirmish game
// general ai for skirmish game
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// Warzone2100, Pumpkin Studios,
// Warzone2100, Pumpkin Studios,
// alex lee.98/99.
// alex lee.98/99.
//
//
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
//Tile in world units
//Tile in world units
#define TILE 128
#define TILE 128
#define NONE (-1)
#define NONE (-1)
// These are final rules of the lexical parser
// These are final rules of the lexical parser
#define R_REQUEST_HELP "help me"
#define R_REQUEST_HELP "help me"
#define R_REQUEST_BEACON "drop a beacon"
#define R_REQUEST_BEACON "drop a beacon"
#define R_REPORT_SAFETY "i'm ok"
#define R_REPORT_SAFETY "i'm ok"
#define R_REQUEST_ALLY "ally me"
#define R_REQUEST_ALLY "ally me"
// These are our own messages - lexical parser should be able to handle them
// These are our own messages - lexical parser should be able to handle them
#define M_REQUEST_HELP "help me!!"
#define M_REQUEST_HELP "help me!!"
#define M_REQUEST_BEACON "drop a beacon"
#define M_REQUEST_BEACON "drop a beacon"
#define M_AFFIRMATIVE_OK "ok"
#define M_AFFIRMATIVE_OK "ok"
#define M_AFFIRMATIVE_ROGER "roger"
#define M_AFFIRMATIVE_ROGER "roger"
#define M_ANNOYED "bug off"
#define M_ANNOYED "bug off"
#define M_HELPERS_KILLED "that was all I had.."
#define M_HELPERS_KILLED "that was all I had.."
#define M_HELP_NO_UNITS "I don't have anything"
#define M_HELP_NO_UNITS "I don't have anything"
#define MAX_PROBABILITY 100
#define MAX_PROBABILITY 100
// Base threat range in world units
// Base threat range in world units
#define W_BASE_THREAT_RANGE ((17 + (mapWidth + mapHeight) / 2 / 35) * TILE)
#define W_BASE_THREAT_RANGE ((17 + (mapWidth + mapHeight) / 2 / 35) * TILE)
#define ALL_ALLIES -1
#define ALL_ALLIES -1
#define BASE_DEFEND_DURATION (3 * 60)
#define BASE_DEFEND_DURATION (3 * 60)
// Delay before we repeat our request, in seconds
// Delay before we repeat our request, in seconds
#define HELP_REQUEST_INTERVAL (3 * 60)
#define HELP_REQUEST_INTERVAL (3 * 60)
//in secs
//in secs
#define BEACON_TIMEOUT 30
#define BEACON_TIMEOUT 30
#define MAX_DROIDS 150
#define MAX_DROIDS 150
//range for trucks to look for more oil
//range for trucks to look for more oil
#define MORE_OIL_RANGE (10 * TILE)
#define MORE_OIL_RANGE (10 * TILE)
//don't try to build on oil if there's threat within this range
//don't try to build on oil if there's threat within this range
#define OIL_THREAT_RANGE (9 * TILE)
#define OIL_THREAT_RANGE (9 * TILE)
Copiar
Copiado
Copiar
Copiado
#define MAX_TRUCKS
12
#define MAX_TRUCKS
15
#define MIN_TRUCKS
5
#define MIN_TRUCKS
12
//Enter power saving mode when lower than this
//Enter power saving mode when lower than this
#define LOW_POWER 250
#define LOW_POWER 250
//Target type values
//Target type values
#define NO_TARGET_VALUE 0
#define NO_TARGET_VALUE 0
#define DROID_TARGET_VALUE 1
#define DROID_TARGET_VALUE 1
#define OTHER_TARGET_VALUE 2
#define OTHER_TARGET_VALUE 2
#define DEFENSE_TARGET_VALUE 3
#define DEFENSE_TARGET_VALUE 3
#define RESEARCH_TARGET_VALUE 4
#define RESEARCH_TARGET_VALUE 4
#define HQ_TARGET_VALUE 5
#define HQ_TARGET_VALUE 5
#define OIL_TARGET_VALUE 6
#define OIL_TARGET_VALUE 6
#define FACTORY_TARGET_VALUE 7
#define FACTORY_TARGET_VALUE 7
#define UNLIMITED (-1)
#define UNLIMITED (-1)
#define AA_THREAT_RANGE (TILE * 12)
#define AA_THREAT_RANGE (TILE * 12)
#define MAX_DEFENDERS_RADIUS (TILE * 40)
#define MAX_DEFENDERS_RADIUS (TILE * 40)
#define MAX_VTOL_DEFEND_RADIUS (TILE * 25)
#define MAX_VTOL_DEFEND_RADIUS (TILE * 25)
// AI will remember max this number of structures
// AI will remember max this number of structures
#define MAX_REBUILD_STRUCT 100
#define MAX_REBUILD_STRUCT 100
//Total number of technology branches
//Total number of technology branches
#define TECHS 2
#define TECHS 2
//How many best templates to choose from when deciding what template to build
//How many best templates to choose from when deciding what template to build
Copiar
Copiado
Copiar
Copiado
#define MAX_RANDOM_TEMPLATES
4
#define MAX_RANDOM_TEMPLATES
6
private int me; // player for this instance.
private int me; // player for this instance.
public int tileExpand; // rate of exploration
public int tileExpand; // rate of exploration
public int numScouts[TECHS],maxScouts[TECHS]; // aim for...
public int numScouts[TECHS],maxScouts[TECHS]; // aim for...
public int numDefenders[TECHS],maxDefenders[TECHS];
public int numDefenders[TECHS],maxDefenders[TECHS];
public int numAttackers[TECHS],maxAttackers[TECHS];
public int numAttackers[TECHS],maxAttackers[TECHS];
public int numCyborgs[TECHS],maxCyborgs[TECHS];
public int numCyborgs[TECHS],maxCyborgs[TECHS];
public int branchDefault,branchVTOL,techCount[TECHS],maxVtolFacs[TECHS],maxIdleRes[TECHS],
public int branchDefault,branchVTOL,techCount[TECHS],maxVtolFacs[TECHS],maxIdleRes[TECHS],
maxVTOLs[TECHS],numVtolTargets,vtolTargetWeight[10],numRebuildStat[TECHS];
maxVTOLs[TECHS],numVtolTargets,vtolTargetWeight[10],numRebuildStat[TECHS];
public RESEARCHSTAT tech[TECHS][30]; //technology for different research branches
public RESEARCHSTAT tech[TECHS][30]; //technology for different research branches
public STRUCTURESTAT vtolTarget[10],rebuildStat[TECHS][2];
public STRUCTURESTAT vtolTarget[10],rebuildStat[TECHS][2];
// structures
// structures
private int baseX,baseY,minx,miny,maxx,maxy;
private int baseX,baseY,minx,miny,maxx,maxy;
public int numStructs,numIncendrys,numDefStructs,numExtraStructs[TECHS],numWallWeaps,numBaseStruct,numLightCyborgs,numFundamental;
public int numStructs,numIncendrys,numDefStructs,numExtraStructs[TECHS],numWallWeaps,numBaseStruct,numLightCyborgs,numFundamental;
private STRUCTURESTAT structChoice[5];
private STRUCTURESTAT structChoice[5];
Copiar
Copiado
Copiar
Copiado
public STRUCTURESTAT incendrys[
8
],structs[13],defStructs[26],extraStructs[TECHS][6],wallWeaps[11];
public STRUCTURESTAT incendrys[
10
],structs[13],defStructs[26],extraStructs[TECHS][6],wallWeaps[11];
public STRUCTURESTAT sensorTower,wall,cornerWall,resLab,powGen,playerHQ,lassat,factory,derrick,cybFactory,
public STRUCTURESTAT sensorTower,wall,cornerWall,resLab,powGen,playerHQ,lassat,factory,derrick,cybFactory,
Copiar
Copiado
Copiar
Copiado
vtolDefStruct[
5
],vtolPad,vtolFactory,uplink,baseStruct[8];
vtolDefStruct[
9
],vtolPad,vtolFactory,uplink,baseStruct[8];
public STRUCTURESTAT powModule,facModule,resModule,vtolModule;
public STRUCTURESTAT powModule,facModule,resModule,vtolModule;
public int extraStruct;
public int extraStruct;
// unit templates
// unit templates
public int numTemplates[TECHS];
public int numTemplates[TECHS];
public TEMPLATE tmpl[TECHS][70];
public TEMPLATE tmpl[TECHS][70];
Copiar
Copiado
Copiar
Copiado
private TEMPLATE tmplChoice[
5
];
private TEMPLATE tmplChoice[
67
];
Copiar
Copiado
Copiar
Copiado
public TEMPLATE cybTempl[
10
],superCyb[
4
],cybMechanic,cybEngineer,hovertruck;
public TEMPLATE cybTempl[
7
],superCyb[
21
],cybMechanic,cybEngineer,hovertruck;
Copiar
Copiado
Copiar
Copiado
public TEMPLATE vtols[
18
];
public TEMPLATE vtols[
20
];
public int numVtolTemplates;
public int numVtolTemplates;
Copiar
Copiado
Copiar
Copiado
public TEMPLATE sense[
11
];
public TEMPLATE sense[
8
];
public int numSenseTemplates;
public int numSenseTemplates;
Copiar
Copiado
Copiar
Copiado
public TEMPLATE constructor,repair
;
public TEMPLATE constructor,repair
[7]
;
public int numRepairUnits;
public int numRepairUnits;
Copiar
Copiado
Copiar
Copiado
public int numSensorUnits;
public int numRepairTemplates;
//defend
//defend
private GROUP defendGroup;
private GROUP defendGroup;
private bool defendbusy;
private bool defendbusy;
private BASEOBJ defendObj;
private BASEOBJ defendObj;
public RESEARCHSTAT nexusDefence;
public RESEARCHSTAT nexusDefence;
private RESEARCHSTAT research;
private RESEARCHSTAT research;
//build
//build
private GROUP buildGroup;
private GROUP buildGroup;
private int buildX,buildY,buildX2,buildY2;
private int buildX,buildY,buildX2,buildY2;
public FEATURESTAT oilRes;
public FEATURESTAT oilRes;
// scout
// scout
private GROUP scoutGroup;
private GROUP scoutGroup;
private int scoutX,scoutY;
private int scoutX,scoutY;
private int scoutTLX,scoutTLY,scoutW,scoutH;
private int scoutTLX,scoutTLY,scoutW,scoutH;
// attack
// attack
private GROUP attackGroup;
private GROUP attackGroup;
Copiar
Copiado
Copiar
Copiado
private BASEOBJ attackObj,allOutAttack,vtolGrAttackObj[
10
];
private BASEOBJ attackObj,allOutAttack,vtolGrAttackObj[
39
];
// vtols
// vtols
private GROUP vtolDefendGr,vtolAttackGr[10];
private GROUP vtolDefendGr,vtolAttackGr[10];
// generic
// generic
private STRUCTURE structure,structure2,rebuildObj[100];
private STRUCTURE structure,structure2,rebuildObj[100];
private DROID droid;
private DROID droid;
private FEATURE feature;
private FEATURE feature;
private BASEOBJ baseobj,baseobj2;
private BASEOBJ baseobj,baseobj2;
private int count,count2,result,result2,tempx,tempy;
private int count,count2,result,result2,tempx,tempy;
private bool boolResult,boolResult2;
private bool boolResult,boolResult2;
private bool powerSave,_DEBUG,bRunning;
private bool powerSave,_DEBUG,bRunning;
// Hopefully this will be at least as large as MAX_PLAYERS... Why can't I just use MAX_PLAYERS as the array size?!
// Hopefully this will be at least as large as MAX_PLAYERS... Why can't I just use MAX_PLAYERS as the array size?!
// P.S. And why can't I put a comment on the same line as a #define??!! Gah, who cares if the lua2 branch works, lets switch to it, anyway.
// P.S. And why can't I put a comment on the same line as a #define??!! Gah, who cares if the lua2 branch works, lets switch to it, anyway.
#define MAX_PLAYERS_HACK 17
#define MAX_PLAYERS_HACK 17
private int allianceTime[MAX_PLAYERS_HACK];
private int allianceTime[MAX_PLAYERS_HACK];
private int sender,x,y,beaconX[8],beaconY[8],tBeacon[8],
private int sender,x,y,beaconX[8],beaconY[8],tBeacon[8],
tLastHelpRequest,lastHelpPlayer,tHelp,tHelpTimeout,helpX,helpY;
tLastHelpRequest,lastHelpPlayer,tHelp,tHelpTimeout,helpX,helpY;
private string message;
private string message;
private int defendX,defendY,__defendRadiusUnused,tDefendStart,tDefendTimeout,
private int defendX,defendY,__defendRadiusUnused,tDefendStart,tDefendTimeout,
defendMoveType,baseRange,curTech,numVtolAttackGroups,numAttackVtols,
defendMoveType,baseRange,curTech,numVtolAttackGroups,numAttackVtols,
numDefendVtols,rebuildStructX[MAX_REBUILD_STRUCT],rebuildStructY[MAX_REBUILD_STRUCT],countRebuildStruct;
numDefendVtols,rebuildStructX[MAX_REBUILD_STRUCT],rebuildStructY[MAX_REBUILD_STRUCT],countRebuildStruct;
private STRUCTURESTAT rebuildStructStat[MAX_REBUILD_STRUCT];
private STRUCTURESTAT rebuildStructStat[MAX_REBUILD_STRUCT];
private STRUCTURESTAT fundamentalBeingBuilt;
private STRUCTURESTAT fundamentalBeingBuilt;
private int order; // callback global
private int order; // callback global
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// triggers.
// triggers.
#region triggers
#region triggers
trigger reachedTr (CALL_DROID_REACH_LOCATION, me, ref droid, ref order);
trigger reachedTr (CALL_DROID_REACH_LOCATION, me, ref droid, ref order);
Copiar
Copiado
Copiar
Copiado
trigger buildExpandTr (every,
6
00);
trigger buildExpandTr (every,
3
00);
trigger fortifyTr (every,
1000
);
trigger fortifyTr (every,
400
);
trigger upgradeStructuresTr (every,
360
);
trigger upgradeStructuresTr (every,
50
);
trigger conDroidsTr (every,
9
00); // was 1400
trigger conDroidsTr (every,
2
00); // was 1400
trigger repairDroidsTr (every,
2600
);
trigger repairDroidsTr (every,
400);
trigger sensorDroidsTr (every, 400
);
trigger basedetailsTr (every, 600 );
trigger basedetailsTr (every, 600 );
trigger buildDerrickTr (every, 80 );
trigger buildDerrickTr (every, 80 );
Copiar
Copiado
Copiar
Copiado
trigger buildOilDefenseOrRetreatTr (every,
120
);
trigger buildOilDefenseOrRetreatTr (every,
200
);
trigger incendryTr (every,
25
0 );
trigger incendryTr (every,
12
0 );
trigger buildPowerGeneratorsTr (every, 80 );
trigger buildPowerGeneratorsTr (every, 80 );
trigger buildBaseTr (every, 150 );
trigger buildBaseTr (every, 150 );
trigger finishStructsTr (every, 210);
trigger finishStructsTr (every, 210);
trigger droidBuiltTr (CALL_NEWDROID,me, ref droid,ref structure);
trigger droidBuiltTr (CALL_NEWDROID,me, ref droid,ref structure);
trigger structBuiltTr (CALL_STRUCTBUILT, me, ref droid, ref structure);
trigger structBuiltTr (CALL_STRUCTBUILT, me, ref droid, ref structure);
trigger droidDestroyedTr (CALL_DROID_DESTROYED, me, ref droid);
trigger droidDestroyedTr (CALL_DROID_DESTROYED, me, ref droid);
trigger structureDestroyedTr (CALL_STRUCT_DESTROYED, me, ref structure);
trigger structureDestroyedTr (CALL_STRUCT_DESTROYED, me, ref structure);
trigger rebuildStructureTr (every, 50);
trigger rebuildStructureTr (every, 50);
trigger consolidateEventTr (every, 3100);
trigger consolidateEventTr (every, 3100);
Copiar
Copiado
Copiar
Copiado
trigger factoryEventTr (every,
170
);
trigger factoryEventTr (every,
90
);
trigger cyborgFactoryEventTr (every,
170
);
trigger cyborgFactoryEventTr (every,
90
);
trigger chooseScoutAreaTr (every, 200 );
trigger chooseScoutAreaTr (every, 200 );
trigger expandScoutAreaTr (every, 600 );
trigger expandScoutAreaTr (every, 600 );
trigger scoutMainTr (every, 150 );
trigger scoutMainTr (every, 150 );
trigger newObjectReportTr (CALL_OBJ_SEEN, me, ref baseobj, ref baseobj2);
trigger newObjectReportTr (CALL_OBJ_SEEN, me, ref baseobj, ref baseobj2);
Copiar
Copiado
Copiar
Copiado
trigger attackStuffTr (every,
3
00 );
trigger attackStuffTr (every,
2
00 );
trigger allOutAttackTr (every,
4
000);
trigger allOutAttackTr (every,
2
000);
trigger defendWatchTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
trigger defendWatchTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
Copiar
Copiado
Copiar
Copiado
trigger defendReturnTr (every,
500
);
trigger defendReturnTr (every,
100000
);
trigger doResearchTr (CALL_RESEARCHCOMPLETED, ref research, ref structure, me);
trigger doResearchTr (CALL_RESEARCHCOMPLETED, ref research, ref structure, me);
trigger vtolDefendTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
trigger vtolDefendTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
Copiar
Copiado
Copiar
Copiado
trigger vtolStructsTr (every,
290
);
trigger vtolStructsTr (every,
600
);
trigger buildVtolsTr (every,
360
);
trigger buildVtolsTr (every,
180
);
trigger vtolAttackTr (every, 1
5
0);
trigger vtolAttackTr (every, 1
0);
trigger vtolEnablerTr (every, 700);
trigger vtolEnablerTr (every, 700);
trigger takeoverTr (CALL_UNITTAKEOVER, ref droid);
trigger takeoverTr (CALL_UNITTAKEOVER, ref droid);
trigger useLassatTr (every, 3000);
trigger useLassatTr (every, 3000);
trigger reassignTr (CALL_PLAYERLEFT,ref count);
trigger reassignTr (CALL_PLAYERLEFT,ref count);
trigger formAllianceEventTr (every,170);
trigger formAllianceEventTr (every,170);
trigger breakAllianceEventTr (every,3000);
trigger breakAllianceEventTr (every,3000);
trigger difficultyModifierTr (every,600);
trigger difficultyModifierTr (every,600);
trigger humanAllianceTr (CALL_ALLIANCEOFFER,ref count, ref count2);
trigger humanAllianceTr (CALL_ALLIANCEOFFER,ref count, ref count2);
trigger multiMsgTr (CALL_AI_MSG, me, ref sender, ref message);
trigger multiMsgTr (CALL_AI_MSG, me, ref sender, ref message);
trigger beaconTr (CALL_BEACON, me, ref sender, ref x, ref y, ref message);
trigger beaconTr (CALL_BEACON, me, ref sender, ref x, ref y, ref message);
trigger consoleTr (CALL_CONSOLE, ref sender, ref message);
trigger consoleTr (CALL_CONSOLE, ref sender, ref message);
trigger watchBaseThreatTr (every, 120);
trigger watchBaseThreatTr (every, 120);
trigger manageAllyHelpTr (every, 80);
trigger manageAllyHelpTr (every, 80);
trigger everySec (every, 10);
trigger everySec (every, 10);
trigger manageDefendLocationTr (every, 70);
trigger manageDefendLocationTr (every, 70);
trigger startLevelTr (CALL_START_NEXT_LEVEL);
trigger startLevelTr (CALL_START_NEXT_LEVEL);
trigger chainloadTr (wait, 1);
trigger chainloadTr (wait, 1);
trigger slowloadTr (wait, 13);
trigger slowloadTr (wait, 13);
Copiar
Copiado
Copiar
Copiado
trigger checkResearchTr (every,
400
);
trigger checkResearchTr (every,
50
);
/* Events */
/* Events */
event conDroids;
event conDroids;
event multiMsgEv;
event multiMsgEv;
event beaconEv;
event beaconEv;
event watchBaseThreat;
event watchBaseThreat;
event manageAllyHelp;
event manageAllyHelp;
event everySecEv;
event everySecEv;
event manageDefendLocationEv;
event manageDefendLocationEv;
event structureDestroyed;
event structureDestroyed;
event rebuildStructureEv;
event rebuildStructureEv;
event doResearch;
event doResearch;
event buildDerrick;
event buildDerrick;
/* Function prototypes */
/* Function prototypes */
function bool haveBeacon(int _player);
function bool haveBeacon(int _player);
function bool beaconTimeout(int _player);
function bool beaconTimeout(int _player);
function void processCommand(string _message, int _sender, bool _bBlipMessage);
function void processCommand(string _message, int _sender, bool _bBlipMessage);
function bool haveHelpers();
function bool haveHelpers();
function bool attemptToHelp(int _playerToHelp, int _x, int _y);
function bool attemptToHelp(int _playerToHelp, int _x, int _y);
function void helpPlayer(int _playerToHelp, int _helpX, int _helpY);
function void helpPlayer(int _playerToHelp, int _helpX, int _helpY);
function bool canStopHelpingAlly();
function bool canStopHelpingAlly();
function void stopHelpingAlly();
function void stopHelpingAlly();
function bool helpingAlly();
function bool helpingAlly();
function bool helpAllyTimeout();
function bool helpAllyTimeout();
function void requestHelp(int _helpX, int _helpY);
function void requestHelp(int _helpX, int _helpY);
function void doRequestHelp(int _helpX, int _helpY);
function void doRequestHelp(int _helpX, int _helpY);
function bool allyBaseAtLoc(int _ally, int _x, int _y);
function bool allyBaseAtLoc(int _ally, int _x, int _y);
function void messagePlayer(int _playerToMessage, string _message, int _probability);
function void messagePlayer(int _playerToMessage, string _message, int _probability);
function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message);
function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message);
function bool canSeeAllies();
function bool canSeeAllies();
function bool baseInTrouble();
function bool baseInTrouble();
function string m_affirmative();
function string m_affirmative();
function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, bool _bMove);
function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, bool _bMove);
function void stopDefendingLocation();
function void stopDefendingLocation();
function bool defendingLocation();
function bool defendingLocation();
function bool defendLocationTimeout();
function bool defendLocationTimeout();
function bool friendlyPlayer(int _playerToCheck);
function bool friendlyPlayer(int _playerToCheck);
function void factoryBuildDroid(STRUCTURE _factory);
function void factoryBuildDroid(STRUCTURE _factory);
function void cybFactorBuildCyborg(STRUCTURE _factory);
function void cybFactorBuildCyborg(STRUCTURE _factory);
function void vtolFactoryBuildVtol(STRUCTURE _factory);
function void vtolFactoryBuildVtol(STRUCTURE _factory);
function bool insideBase(int _x, int _y);
function bool insideBase(int _x, int _y);
function int numAlliesInBase(bool _bVtols);
function int numAlliesInBase(bool _bVtols);
function int numEnemiesInBase(bool _bVtols);
function int numEnemiesInBase(bool _bVtols);
function bool defendingOwnBase();
function bool defendingOwnBase();
function int targetTypeValue(BASEOBJ _target);
function int targetTypeValue(BASEOBJ _target);
function int numBitsSet(int _integer);
function int numBitsSet(int _integer);
function int findResearch(int _searchStart, int _techTree);
function int findResearch(int _searchStart, int _techTree);
function bool upgradeFactory(DROID _truck, int _maxBuilders);
function bool upgradeFactory(DROID _truck, int _maxBuilders);
function bool upgradeVtolFactory(DROID _truck, int _maxBuilders);
function bool upgradeVtolFactory(DROID _truck, int _maxBuilders);
function bool upgradeResearch(DROID _truck, int _maxBuilders);
function bool upgradeResearch(DROID _truck, int _maxBuilders);
function bool upgradePowGen(DROID _truck, int _maxBuilders);
function bool upgradePowGen(DROID _truck, int _maxBuilders);
function void buildRearmPads();
function void buildRearmPads();
function int numEnemyAAInRange(int _x, int _y, int _range);
function int numEnemyAAInRange(int _x, int _y, int _range);
function BASEOBJ chooseVtolTarget(bool bExclusiveTarget);
function BASEOBJ chooseVtolTarget(bool bExclusiveTarget);
function int getVtolTargetWeight(BASEOBJ _target);
function int getVtolTargetWeight(BASEOBJ _target);
function bool vtolTargetAssigned(BASEOBJ _target);
function bool vtolTargetAssigned(BASEOBJ _target);
function int numBuildSameBuilding(STRUCTURESTAT _checkStat, int _x, int _y);
function int numBuildSameBuilding(STRUCTURESTAT _checkStat, int _x, int _y);
function int totalVtols();
function int totalVtols();
function bool needTank();
function bool needTank();
function void setTechBranch(int _tech);
function void setTechBranch(int _tech);
function DROID closestIdleTruck(int _x, int _y);
function DROID closestIdleTruck(int _x, int _y);
function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat);
function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat);
function void rebuildStructures();
function void rebuildStructures();
function BASEOBJ chooseVtolDefenceTarget(int _x, int _y, int _range, bool bExclusiveTarget);
function BASEOBJ chooseVtolDefenceTarget(int _x, int _y, int _range, bool bExclusiveTarget);
function int numGroupSameOrder(GROUP _group, int _orderIndex);
function int numGroupSameOrder(GROUP _group, int _orderIndex);
function void rearrangeAttackVtols();
function void rearrangeAttackVtols();
function int numStructBusyByType(STRUCTURESTAT _busyStructType);
function int numStructBusyByType(STRUCTURESTAT _busyStructType);
function bool aiResponsibleForPlayer(int _player);
function bool aiResponsibleForPlayer(int _player);
function void reassignAI();
function void reassignAI();
function void shutDownAI();
function void shutDownAI();
function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly);
function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly);
function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly);
function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly);
#endregion triggers
#endregion triggers
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// HouseKeeping
// HouseKeeping
event initialisedEvent(CALL_GAMEINIT)
event initialisedEvent(CALL_GAMEINIT)
{
{
local int player;
local int player;
// initialise
// initialise
me = getPlayer("Nexus");
me = getPlayer("Nexus");
_DEBUG = FALSE;
_DEBUG = FALSE;
dbgMsgOn(me, _DEBUG);
dbgMsgOn(me, _DEBUG);
extraStruct = 0;
extraStruct = 0;
numRepairUnits = 0;
numRepairUnits = 0;
Copiar
Copiado
Copiar
Copiado
numSensorUnits = 0;
allOutAttack = NULLOBJECT;
allOutAttack = NULLOBJECT;
tLastHelpRequest = -1; //when we requested help for the last time
tLastHelpRequest = -1; //when we requested help for the last time
lastHelpPlayer = -1; //we are not currently helping anyone
lastHelpPlayer = -1; //we are not currently helping anyone
tHelp = -1; //when we started helping last time
tHelp = -1; //when we started helping last time
tHelpTimeout = -1; //time when help times out
tHelpTimeout = -1; //time when help times out
helpX = -1;
helpX = -1;
helpY = -1;
helpY = -1;
defendX = -1;
defendX = -1;
defendY = -1;
defendY = -1;
tDefendStart = -1;
tDefendStart = -1;
tDefendTimeout = -1;
tDefendTimeout = -1;
defendMoveType = -1; //move or scout
defendMoveType = -1; //move or scout
baseRange = 4 * TILE;
baseRange = 4 * TILE;
// set current research branch
// set current research branch
setTechBranch(-1);
setTechBranch(-1);
numVtolAttackGroups = 10;
numVtolAttackGroups = 10;
numAttackVtols = 10; //num vtols in an attack group
numAttackVtols = 10; //num vtols in an attack group
numDefendVtols = 5; //num vtols in an attack group
numDefendVtols = 5; //num vtols in an attack group
// setup build group - all initial droids are in buildgroup!
// setup build group - all initial droids are in buildgroup!
groupAddArea(buildGroup, me, 0, 0, (mapWidth*128), (mapHeight*128));
groupAddArea(buildGroup, me, 0, 0, (mapWidth*128), (mapHeight*128));
// note where our base is.
// note where our base is.
getPlayerStartPosition(me, ref baseX, ref baseY);
getPlayerStartPosition(me, ref baseX, ref baseY);
// defence.
// defence.
defendbusy = FALSE;
defendbusy = FALSE;
// setup scouts
// setup scouts
structure = getStructure(factory, me);
structure = getStructure(factory, me);
if(structure != NULLOBJECT)
if(structure != NULLOBJECT)
{
{
scoutTLX = structure.x;
scoutTLX = structure.x;
scoutTLY = structure.y;
scoutTLY = structure.y;
}
}
else
else
{
{
scoutTLX = baseX;
scoutTLX = baseX;
scoutTLY = baseY;
scoutTLY = baseY;
}
}
scoutW = 256;
scoutW = 256;
scoutH = 256;
scoutH = 256;
scoutX = scoutTLX;
scoutX = scoutTLX;
scoutY = scoutTLY;
scoutY = scoutTLY;
// clear the alliance array...
// clear the alliance array...
player = 0;
player = 0;
while (player != MAX_PLAYERS)
while (player != MAX_PLAYERS)
{
{
allianceTime[player] = 0;
allianceTime[player] = 0;
player = player + 1;
player = player + 1;
}
}
fundamentalBeingBuilt = derrick; // to avoid ever being null
fundamentalBeingBuilt = derrick; // to avoid ever being null
if(aiResponsibleForPlayer(me))
if(aiResponsibleForPlayer(me))
{
{
bRunning = true;
bRunning = true;
}
}
else
else
{
{
bRunning = false;
bRunning = false;
shutDownAI();
shutDownAI();
}
}
}
}
// check whether we have at least one structure of that type
// check whether we have at least one structure of that type
function bool haveStructure(STRUCTURESTAT type)
function bool haveStructure(STRUCTURESTAT type)
{
{
return getStructure(type, me) != NULLOBJECT;
return getStructure(type, me) != NULLOBJECT;
}
}
// check if we are getting any income
// check if we are getting any income
function bool havePowerSource()
function bool havePowerSource()
{
{
// we don't check buildings being finished here
// we don't check buildings being finished here
return haveStructure(powGen) and haveStructure(derrick);
return haveStructure(powGen) and haveStructure(derrick);
}
}
// I am not sure why we need this hack, but the AI can still end up not researching anything at times
// I am not sure why we need this hack, but the AI can still end up not researching anything at times
event checkResearch(checkResearchTr)
event checkResearch(checkResearchTr)
{
{
setEventTrigger(doResearch, chainloadTr);
setEventTrigger(doResearch, chainloadTr);
}
}
function void dbgPlr(string message)
function void dbgPlr(string message)
{
{
setEventTrigger(doResearch, chainloadTr);
setEventTrigger(doResearch, chainloadTr);
if (me == selectedPlayer)
if (me == selectedPlayer)
{
{
console(message);
console(message);
}
}
}
}
function void dbgObj(DROID obj, string message)
function void dbgObj(DROID obj, string message)
{
{
if (obj.selected)
if (obj.selected)
{
{
console(message);
console(message);
}
}
}
}
function bool conCanHelp(DROID mydroid, int bx, int by)
function bool conCanHelp(DROID mydroid, int bx, int by)
{
{
return (mydroid.order != DORDER_HELPBUILD and mydroid.order != DORDER_BUILD and mydroid.order != DORDER_LINEBUILD and droidCanReach(mydroid, bx, by));
return (mydroid.order != DORDER_HELPBUILD and mydroid.order != DORDER_BUILD and mydroid.order != DORDER_LINEBUILD and droidCanReach(mydroid, bx, by));
}
}
// Build something in main base, grab trucks to do it within tiles range
// Build something in main base, grab trucks to do it within tiles range
function bool grabTrucksAndBuild(int range, STRUCTURESTAT bstats, int maxBlockingTiles)
function bool grabTrucksAndBuild(int range, STRUCTURESTAT bstats, int maxBlockingTiles)
{
{
local DROID mydroid, closestDroid;
local DROID mydroid, closestDroid;
local int closestDist, currDist, numHelpDroids, tilerange, bx, by;
local int closestDist, currDist, numHelpDroids, tilerange, bx, by;
initIterateGroup(buildGroup); // find idle droids in build group.
initIterateGroup(buildGroup); // find idle droids in build group.
mydroid = iterateGroup(buildGroup);
mydroid = iterateGroup(buildGroup);
closestDist = 99999;
closestDist = 99999;
closestDroid = NULLOBJECT;
closestDroid = NULLOBJECT;
numHelpDroids = 0;
numHelpDroids = 0;
tilerange = range * TILE;
tilerange = range * TILE;
while (mydroid != NULLOBJECT)
while (mydroid != NULLOBJECT)
{
{
if (conCanHelp(mydroid, baseX, baseY))
if (conCanHelp(mydroid, baseX, baseY))
{
{
bx = baseX;
bx = baseX;
by = baseY;
by = baseY;
if (pickDroidStructLocation(mydroid, bstats, ref bx, ref by, me, maxBlockingTiles))
if (pickDroidStructLocation(mydroid, bstats, ref bx, ref by, me, maxBlockingTiles))
{
{
currDist = distBetweenTwoPoints(bx, by, mydroid.x, mydroid.y);
currDist = distBetweenTwoPoints(bx, by, mydroid.x, mydroid.y);
if (currDist < tilerange)
if (currDist < tilerange)
{
{
orderDroidStatsLoc(mydroid, DORDER_BUILD, bstats, bx, by); // close, so help build it
orderDroidStatsLoc(mydroid, DORDER_BUILD, bstats, bx, by); // close, so help build it
numHelpDroids = numHelpDroids + 1;
numHelpDroids = numHelpDroids + 1;
}
}
else if (currDist < closestDist)
else if (currDist < closestDist)
{
{
closestDroid = mydroid; // record this droid as being closest so far
closestDroid = mydroid; // record this droid as being closest so far
closestDist = currDist;
closestDist = currDist;
}
}
}
}
}
}
mydroid = iterateGroup(buildGroup);
mydroid = iterateGroup(buildGroup);
}
}
if (numHelpDroids == 0 and closestDroid != NULLOBJECT) // found none within help radius, so force someone to go long distance traveling
if (numHelpDroids == 0 and closestDroid != NULLOBJECT) // found none within help radius, so force someone to go long distance traveling
{
{
orderDroidStatsLoc(closestDroid, DORDER_BUILD, bstats, bx, by); // you, book a plane ticket and go!
orderDroidStatsLoc(closestDroid, DORDER_BUILD, bstats, bx, by); // you, book a plane ticket and go!
return true;
return true;
}
}
return (numHelpDroids > 0);
return (numHelpDroids > 0);
}
}
event arrived(reachedTr)
event arrived(reachedTr)
{
{
local bool found;
local bool found;
local STRUCTURESTAT myChoice;
local STRUCTURESTAT myChoice;
if (droid.droidType == DROID_CONSTRUCT or droid.droidType == DROID_CYBORG_CONSTRUCT)
if (droid.droidType == DROID_CONSTRUCT or droid.droidType == DROID_CYBORG_CONSTRUCT)
{
{
dbgObj(droid, "Failed to build where we should - attempt to screw up enemy oil derrick");
dbgObj(droid, "Failed to build where we should - attempt to screw up enemy oil derrick");
// Check if at oil well, and it was taken by enemy
// Check if at oil well, and it was taken by enemy
structure = structureBuiltInRange(derrick, droid.x, droid.y, (5 * 128), -1);
structure = structureBuiltInRange(derrick, droid.x, droid.y, (5 * 128), -1);
if (structure != NULLOBJECT)
if (structure != NULLOBJECT)
{
{
if (not friendlyPlayer(structure.player) and droid.health == 100)
if (not friendlyPlayer(structure.player) and droid.health == 100)
{
{
// Ok, at enemy derrick, and nobody has hurt us yet. Start being nasty.
// Ok, at enemy derrick, and nobody has hurt us yet. Start being nasty.
count = 0;
count = 0;
found = false;
found = false;
// find simplest/cheapest one available to build
// find simplest/cheapest one available to build
while (count < numDefStructs and not found)
while (count < numDefStructs and not found)
{
{
if (isStructureAvailable(defStructs[count], me))
if (isStructureAvailable(defStructs[count], me))
{
{
found = true;
found = true;
}
}
else
else
{
{
count++;
count++;
}
}
}
}
if (found)
if (found)
{
{
buildX = droid.x;
buildX = droid.x;
buildY = droid.y;
buildY = droid.y;
if (pickDroidStructLocation(droid, defStructs[count], ref buildX, ref buildY, me, -1))
if (pickDroidStructLocation(droid, defStructs[count], ref buildX, ref buildY, me, -1))
{
{
orderDroidStatsLoc(droid, DORDER_BUILD, defStructs[count], buildX, buildY);
orderDroidStatsLoc(droid, DORDER_BUILD, defStructs[count], buildX, buildY);
}
}
else
else
{
{
dbgObj(droid, "Wanted to be nasty, but found nowhere to build defense");
dbgObj(droid, "Wanted to be nasty, but found nowhere to build defense");
orderDroid(droid, DORDER_RTB); // nothing more to do here.
orderDroid(droid, DORDER_RTB); // nothing more to do here.
}
}
}
}
else
else
{
{
dbgObj(droid, "Wanted to be nasty, but had nothing nasty to build - returning to base");
dbgObj(droid, "Wanted to be nasty, but had nothing nasty to build - returning to base");
orderDroid(droid, DORDER_RTB); // oh, well. nothing more to do here.
orderDroid(droid, DORDER_RTB); // oh, well. nothing more to do here.
}
}
exit;
exit;
}
}
else if (droid.health < 100 and !insideBase(droid.x, droid.y))
else if (droid.health < 100 and !insideBase(droid.x, droid.y))
{
{
orderDroid(droid, DORDER_RTR); // bolt back to base now!
orderDroid(droid, DORDER_RTR); // bolt back to base now!
exit;
exit;
}
}
}
}
}
}
}
}
event buildFundamentals(inactive)
event buildFundamentals(inactive)
{
{
count = 0;
count = 0;
while (count < numFundamental)
while (count < numFundamental)
{
{
// check that struct.
// check that struct.
structure = getStructure(structs[count], me);
structure = getStructure(structs[count], me);
if (structure == NULLOBJECT) // if missing build it.
if (structure == NULLOBJECT) // if missing build it.
{
{
if (isStructureAvailable(structs[count], me))
if (isStructureAvailable(structs[count], me))
{
{
if (grabTrucksAndBuild(12, structs[count], 0))
if (grabTrucksAndBuild(12, structs[count], 0))
{
{
exit; // no need to check more
exit; // no need to check more
}
}
}
}
}
}
count = count + 1;
count = count + 1;
}
}
fundamentalBeingBuilt = derrick;
fundamentalBeingBuilt = derrick;
setEventTrigger(buildFundamentals, inactive);
setEventTrigger(buildFundamentals, inactive);
}
}
event startLevel(startLevelTr)
event startLevel(startLevelTr)
{
{
setEventTrigger(buildFundamentals, slowloadTr);
setEventTrigger(buildFundamentals, slowloadTr);
setEventTrigger(conDroids, chainloadTr);
setEventTrigger(conDroids, chainloadTr);
setEventTrigger(doResearch, chainloadTr);
setEventTrigger(doResearch, chainloadTr);
setEventTrigger(buildDerrick, slowloadTr);
setEventTrigger(buildDerrick, slowloadTr);
setEventTrigger(startLevel, inactive);
setEventTrigger(startLevel, inactive);
}
}
// decide what technology branch we will use
// decide what technology branch we will use
function void setTechBranch(int _tech)
function void setTechBranch(int _tech)
{
{
local float _y2,_y1,_x2,_x1,_a,_y,_m,_rnd,_mapSize;
local float _y2,_y1,_x2,_x1,_a,_y,_m,_rnd,_mapSize;
_mapSize = (float)((mapWidth + mapHeight) / 2);
_mapSize = (float)((mapWidth + mapHeight) / 2);
if(_tech != -1)
if(_tech != -1)
{
{
curTech = _tech;
curTech = _tech;
}
}
else
else
{
{
//probability to choose vtol branch for map size 90 = 0; probability for map size 200 = 45
//probability to choose vtol branch for map size 90 = 0; probability for map size 200 = 45
//build a linear function: y = ((y2 - y1) / (x2 - x1)) * x + a depending on two values given (short: y = mx+a)
//build a linear function: y = ((y2 - y1) / (x2 - x1)) * x + a depending on two values given (short: y = mx+a)
_x1 = 90.0; _y1 = 0.0;
_x1 = 90.0; _y1 = 0.0;
_x2 = 200.0; _y2 = 45.0;
_x2 = 200.0; _y2 = 45.0;
_m = ((_y2 - _y1) / (_x2 - _x1));
_m = ((_y2 - _y1) / (_x2 - _x1));
_a = -(_m * _x1);
_a = -(_m * _x1);
//calculate probability for the current map
//calculate probability for the current map
_y = _m * _mapSize + _a;
_y = _m * _mapSize + _a;
dbg("_m = " & _m & ", a = " & _a, me);
dbg("_m = " & _m & ", a = " & _a, me);
_rnd = (float)random(100);
_rnd = (float)random(100);
if(_rnd < _y)
if(_rnd < _y)
{
{
curTech = branchVTOL;
curTech = branchVTOL;
dbg("going air (" & _y & "/" & _rnd & ")", me);
dbg("going air (" & _y & "/" & _rnd & ")", me);
}
}
else
else
{
{
curTech = branchDefault;
curTech = branchDefault;
dbg("going land (" & _y & "/" & _rnd & ")", me);
dbg("going land (" & _y & "/" & _rnd & ")", me);
}
}
}
}
}
}
/* returns TRUE if AI is responsible for the _player */
/* returns TRUE if AI is responsible for the _player */
function bool aiResponsibleForPlayer(int _player)
function bool aiResponsibleForPlayer(int _player)
{
{
if(not _DEBUG and ((_player == selectedPlayer) or not myResponsibility(_player)))
if(not _DEBUG and ((_player == selectedPlayer) or not myResponsibility(_player)))
{
{
return FALSE;
return FALSE;
}
}
return TRUE;
return TRUE;
}
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// keep details about the size and postion of the ai players base
// keep details about the size and postion of the ai players base
event basedetails(basedetailsTr)
event basedetails(basedetailsTr)
{
{
// clear old extremities.
// clear old extremities.
maxy = 0;
maxy = 0;
maxx = 0;
maxx = 0;
miny = (mapHeight*128);
miny = (mapHeight*128);
minx = (mapWidth*128);
minx = (mapWidth*128);
baseRange = 4 * TILE;
baseRange = 4 * TILE;
// now find the extremities of our vital structures.
// now find the extremities of our vital structures.
count = 0;
count = 0;
while(count < numBaseStruct)
while(count < numBaseStruct)
{
{
initEnumStruct(FALSE,baseStruct[count],me,me);
initEnumStruct(FALSE,baseStruct[count],me,me);
structure= enumStruct();
structure= enumStruct();
while(structure != NULLOBJECT)
while(structure != NULLOBJECT)
{
{
if(structure.x < minx)
if(structure.x < minx)
{
{
minx = structure.x;
minx = structure.x;
}
}
if(structure.x > maxx)
if(structure.x > maxx)
{
{
maxx = structure.x;
maxx = structure.x;
}
}
if(structure.y < miny)
if(structure.y < miny)
{
{
miny = structure.y;
miny = structure.y;
}
}
if(structure.y > maxy)
if(structure.y > maxy)
{
{
maxy = structure.y;
maxy = structure.y;
}
}
result = distBetweenTwoPoints(baseX, baseY, structure.x, structure.y);
result = distBetweenTwoPoints(baseX, baseY, structure.x, structure.y);
if(result > baseRange){
if(result > baseRange){
baseRange = result;
baseRange = result;
}
}
structure= enumStruct();
structure= enumStruct();
}
}
count = count + 1;
count = count + 1;
}
}
result = 3 * 128;
result = 3 * 128;
minx = minx - result;
minx = minx - result;
maxx = maxx + result;
maxx = maxx + result;
miny = miny - result;
miny = miny - result;
maxy = maxy + result;
maxy = maxy + result;
baseRange = baseRange + (4 * 128);
baseRange = baseRange + (4 * 128);
}
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// structure building rules
// structure building rules
// build derricks on oil.
// build derricks on oil.
event buildDerrick(buildDerrickTr)
event buildDerrick(buildDerrickTr)
{
{
local bool foundOne, _same;
local bool foundOne, _same;
local FEATURE _oil, _closestOil;
local FEATURE _oil, _closestOil;
local int _bestDist, _newDist;
local int _bestDist, _newDist;
local DROID _search;
local DROID _search;
// what if we can't waste power on building derricks because we don't have a gen yet?
// what if we can't waste power on building derricks because we don't have a gen yet?
if (playerPower(me) < 300 and haveStructure(derrick) and not haveStructure(powGen))
if (playerPower(me) < 300 and haveStructure(derrick) and not haveStructure(powGen))
{
{
setEventTrigger(buildDerrick, slowloadTr);
setEventTrigger(buildDerrick, slowloadTr);
exit;
exit;
}
}
_bestDist = 99999;
_bestDist = 99999;
_closestOil = NULLOBJECT;
_closestOil = NULLOBJECT;
foundOne = false;
foundOne = false;
initIterateGroup(buildGroup); // find all units in build group
initIterateGroup(buildGroup); // find all units in build group
droid = iterateGroup(buildGroup);
droid = iterateGroup(buildGroup);
while (droid != NULLOBJECT && !foundOne)
while (droid != NULLOBJECT && !foundOne)
{
{
if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD)
if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD)
{
{
foundOne = true;
foundOne = true;
}
}
else
else
{
{
droid = iterateGroup(buildGroup);
droid = iterateGroup(buildGroup);
}
}
}
}
if (droid != NULLOBJECT)
if (droid != NULLOBJECT)
{
{
initGetFeature(oilRes, -1, me);
initGetFeature(oilRes, -1, me);
_oil = getFeatureB(me);
_oil = getFeatureB(me);
while (_oil != NULLOBJECT)
while (_oil != NULLOBJECT)
{
{
_newDist = distBetweenTwoPoints(droid.x, droid.y, _oil.x, _oil.y);
_newDist = distBetweenTwoPoints(droid.x, droid.y, _oil.x, _oil.y);
_same = false;
_same = false;
if (_newDist < _bestDist and droidCanReach(droid, _oil.x, _oil.y)) // this one is closer
if (_newDist < _bestDist and droidCanReach(droid, _oil.x, _oil.y)) // this one is closer
{
{
if (!threatInRange(me, _oil.x, _oil.y, OIL_THREAT_RANGE, FALSE))
if (!threatInRange(me, _oil.x, _oil.y, OIL_THREAT_RANGE, FALSE))
{
{
initIterateGroup(buildGroup); // find all units in build group.
initIterateGroup(buildGroup); // find all units in build group.
_search = iterateGroup(buildGroup);
_search = iterateGroup(buildGroup);
foundOne = false;
foundOne = false;
while (_search != NULLOBJECT && !foundOne)
while (_search != NULLOBJECT && !foundOne)
{
{
if (_search.orderx == _oil.x and _search.ordery == _oil.y and _search != droid)
if (_search.orderx == _oil.x and _search.ordery == _oil.y and _search != droid)
{
{
_same = true;
_same = true;
foundOne = true;
foundOne = true;
}
}
_search = iterateGroup(buildGroup);
_search = iterateGroup(buildGroup);
}
}
if (!_same) // do not go to same spot as another droid
if (!_same) // do not go to same spot as another droid
{
{
_bestDist = _newDist;
_bestDist = _newDist;
_closestOil = _oil;
_closestOil = _oil;
}
}
}
}
}
}
_oil = getFeatureB(me);
_oil = getFeatureB(me);
}
}
if (_closestOil != NULLOBJECT)
if (_closestOil != NULLOBJECT)
{
{
orderDroidStatsLoc(droid, DORDER_BUILD, derrick, _closestOil.x, _closestOil.y); // build a derick
orderDroidStatsLoc(droid, DORDER_BUILD, derrick, _closestOil.x, _closestOil.y); // build a derick
if (idleGroup(buildGroup) > 0)
if (idleGroup(buildGroup) > 0)
{
{
setEventTrigger(buildDerrick, slowloadTr); // do it again for next droid
setEventTrigger(buildDerrick, slowloadTr); // do it again for next droid
exit;
exit;
}
}
}
}
}
}
setEventTrigger(buildDerrick, buildDerrickTr);
setEventTrigger(buildDerrick, buildDerrickTr);
}
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// if idle and derrick in range and no defense then build defense, else ret to base .
// if idle and derrick in range and no defense then build defense, else ret to base .
event buildOilDefenseOrRetreat(buildOilDefenseOrRetreatTr)
event buildOilDefenseOrRetreat(buildOilDefenseOrRetreatTr)
{
{
local int _numBuilders,_maxBuilders;
local int _numBuilders,_maxBuilders;
_maxBuilders = 1;
_maxBuilders = 1;
// check idle.
// check idle.
initIterateGroup(buildGroup); // find idle droids in build group.
initIterateGroup(buildGroup); // find idle droids in build group.
droid = iterateGroup(buildGroup);
droid = iterateGroup(buildGroup);
while(droid != NULLOBJECT)
while(droid != NULLOBJECT)
{
{
if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD)
if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD)
{
{
// if in range of a derrick
// if in range of a derrick
structure = structureBuiltInRange(derrick, droid.x, droid.y, (5*128), me);
structure = structureBuiltInRange(derrick, droid.x, droid.y, (5*128), me);
// if inside base limits then presume ok..
// if inside base limits then presume ok..
if( structure != NULLOBJECT)
if( structure != NULLOBJECT)
{
{
if((structure.x > minx) and (structure.y > miny) and (structure.x < maxx) and (structure.y <maxy))
if((structure.x > minx) and (structure.y > miny) and (structure.x < maxx) and (structure.y <maxy))
{
{
structure = NULLOBJECT;
structure = NULLOBJECT;
}
}
}
}
if(structure != NULLOBJECT)
if(structure != NULLOBJECT)
{
{
buildX = structure.x;
buildX = structure.x;
buildY = structure.y;
buildY = structure.y;
// not many defenses nearby
// not many defenses nearby
if(numFriendlyWeapStructsInRange(me, buildX, buildY, (3*128), FALSE) < 2)
if(numFriendlyWeapStructsInRange(me, buildX, buildY, (3*128), FALSE) < 2)
{
{
count = numDefStructs - 1; //pick a struct to build..
count = numDefStructs - 1; //pick a struct to build..
count2 = 0;
count2 = 0;
while( (count2 < 5) and (count >= 0) )
while( (count2 < 5) and (count >= 0) )
{
{
if( isStructureAvailable(defStructs[count],me))
if( isStructureAvailable(defStructs[count],me))
{
{
structChoice[count2] = defStructs[count];
structChoice[count2] = defStructs[count];
count2 = count2 + 1;
count2 = count2 + 1;
}
}
count = count - 1;
count = count - 1;
}
}
count =0;
count =0;
if(count2 > 0)
if(count2 > 0)
{
{
count = random(count2); //count = choice!
count = random(count2); //count = choice!
// pick a location
// pick a location
boolResult = pickDroidStructLocation(droid, structChoice[count], ref buildX, ref buildY, me, -1);
boolResult = pickDroidStructLocation(droid, structChoice[count], ref buildX, ref buildY, me, -1);
_numBuilders = numBuildSameBuilding(NULLSTRUCTURESTAT, buildX, buildY);
_numBuilders = numBuildSameBuilding(NULLSTRUCTURESTAT, buildX, buildY);
if((boolResult == TRUE) and (_numBuilders < _maxBuilders) and droidCanReach(droid, buildX, buildY))
if((boolResult == TRUE) and (_numBuilders < _maxBuilders) and droidCanReach(droid, buildX, buildY))
{
{
// build it.
// build it.
orderDroidStatsLoc(droid, DORDER_BUILD,structChoice[count], buildX,buildY);
orderDroidStatsLoc(droid, DORDER_BUILD,structChoice[count], buildX,buildY);
_numBuilders++;
_numBuilders++;
}
}
}
}
}
}
else
else
{
{
structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me);
structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me);
if(structure == NULLOBJECT)
if(structure == NULLOBJECT)
{
{
if(!insideBase(droid.x, droid.y))
if(!insideBase(droid.x, droid.y))
{
{
orderDroid(droid,DORDER_RTB); // return to base;
orderDroid(droid,DORDER_RTB); // return to base;
}
}
}
}
}
}
}
}
else
else
{
{
Copiar
Copiado
Copiar
Copiado
structure = structureBuiltInRange(playerHQ,
droid.x, droid.y, (5*128), me);
structure = structureBuiltInRange(playerHQ,
dr
if(structure == NULLOBJECT)
{
if(!insideBase(droid.x, droid.y))
{
orderD
Diferencias guardadas
Texto original
Abrir archivo
///////////////////////////////////////////////////////////////////// // general ai for skirmish game ///////////////////////////////////////////////////////////////////// // Warzone2100, Pumpkin Studios, // alex lee.98/99. // ///////////////////////////////////////////////////////////////////// //Tile in world units #define TILE 128 #define NONE (-1) // These are final rules of the lexical parser #define R_REQUEST_HELP "help me" #define R_REQUEST_BEACON "drop a beacon" #define R_REPORT_SAFETY "i'm ok" #define R_REQUEST_ALLY "ally me" // These are our own messages - lexical parser should be able to handle them #define M_REQUEST_HELP "help me!!" #define M_REQUEST_BEACON "drop a beacon" #define M_AFFIRMATIVE_OK "ok" #define M_AFFIRMATIVE_ROGER "roger" #define M_ANNOYED "bug off" #define M_HELPERS_KILLED "that was all I had.." #define M_HELP_NO_UNITS "I don't have anything" #define MAX_PROBABILITY 100 // Base threat range in world units #define W_BASE_THREAT_RANGE ((17 + (mapWidth + mapHeight) / 2 / 35) * TILE) #define ALL_ALLIES -1 #define BASE_DEFEND_DURATION (3 * 60) // Delay before we repeat our request, in seconds #define HELP_REQUEST_INTERVAL (3 * 60) //in secs #define BEACON_TIMEOUT 30 #define MAX_DROIDS 150 //range for trucks to look for more oil #define MORE_OIL_RANGE (10 * TILE) //don't try to build on oil if there's threat within this range #define OIL_THREAT_RANGE (9 * TILE) #define MAX_TRUCKS 12 #define MIN_TRUCKS 5 //Enter power saving mode when lower than this #define LOW_POWER 250 //Target type values #define NO_TARGET_VALUE 0 #define DROID_TARGET_VALUE 1 #define OTHER_TARGET_VALUE 2 #define DEFENSE_TARGET_VALUE 3 #define RESEARCH_TARGET_VALUE 4 #define HQ_TARGET_VALUE 5 #define OIL_TARGET_VALUE 6 #define FACTORY_TARGET_VALUE 7 #define UNLIMITED (-1) #define AA_THREAT_RANGE (TILE * 12) #define MAX_DEFENDERS_RADIUS (TILE * 40) #define MAX_VTOL_DEFEND_RADIUS (TILE * 25) // AI will remember max this number of structures #define MAX_REBUILD_STRUCT 100 //Total number of technology branches #define TECHS 2 //How many best templates to choose from when deciding what template to build #define MAX_RANDOM_TEMPLATES 4 private int me; // player for this instance. public int tileExpand; // rate of exploration public int numScouts[TECHS],maxScouts[TECHS]; // aim for... public int numDefenders[TECHS],maxDefenders[TECHS]; public int numAttackers[TECHS],maxAttackers[TECHS]; public int numCyborgs[TECHS],maxCyborgs[TECHS]; public int branchDefault,branchVTOL,techCount[TECHS],maxVtolFacs[TECHS],maxIdleRes[TECHS], maxVTOLs[TECHS],numVtolTargets,vtolTargetWeight[10],numRebuildStat[TECHS]; public RESEARCHSTAT tech[TECHS][30]; //technology for different research branches public STRUCTURESTAT vtolTarget[10],rebuildStat[TECHS][2]; // structures private int baseX,baseY,minx,miny,maxx,maxy; public int numStructs,numIncendrys,numDefStructs,numExtraStructs[TECHS],numWallWeaps,numBaseStruct,numLightCyborgs,numFundamental; private STRUCTURESTAT structChoice[5]; public STRUCTURESTAT incendrys[8],structs[13],defStructs[26],extraStructs[TECHS][6],wallWeaps[11]; public STRUCTURESTAT sensorTower,wall,cornerWall,resLab,powGen,playerHQ,lassat,factory,derrick,cybFactory, vtolDefStruct[5],vtolPad,vtolFactory,uplink,baseStruct[8]; public STRUCTURESTAT powModule,facModule,resModule,vtolModule; public int extraStruct; // unit templates public int numTemplates[TECHS]; public TEMPLATE tmpl[TECHS][70]; private TEMPLATE tmplChoice[5]; public TEMPLATE cybTempl[10],superCyb[4],cybMechanic,cybEngineer,hovertruck; public TEMPLATE vtols[18]; public int numVtolTemplates; public TEMPLATE sense[11]; public int numSenseTemplates; public TEMPLATE constructor,repair; public int numRepairUnits; //defend private GROUP defendGroup; private bool defendbusy; private BASEOBJ defendObj; public RESEARCHSTAT nexusDefence; private RESEARCHSTAT research; //build private GROUP buildGroup; private int buildX,buildY,buildX2,buildY2; public FEATURESTAT oilRes; // scout private GROUP scoutGroup; private int scoutX,scoutY; private int scoutTLX,scoutTLY,scoutW,scoutH; // attack private GROUP attackGroup; private BASEOBJ attackObj,allOutAttack,vtolGrAttackObj[10]; // vtols private GROUP vtolDefendGr,vtolAttackGr[10]; // generic private STRUCTURE structure,structure2,rebuildObj[100]; private DROID droid; private FEATURE feature; private BASEOBJ baseobj,baseobj2; private int count,count2,result,result2,tempx,tempy; private bool boolResult,boolResult2; private bool powerSave,_DEBUG,bRunning; // Hopefully this will be at least as large as MAX_PLAYERS... Why can't I just use MAX_PLAYERS as the array size?! // P.S. And why can't I put a comment on the same line as a #define??!! Gah, who cares if the lua2 branch works, lets switch to it, anyway. #define MAX_PLAYERS_HACK 17 private int allianceTime[MAX_PLAYERS_HACK]; private int sender,x,y,beaconX[8],beaconY[8],tBeacon[8], tLastHelpRequest,lastHelpPlayer,tHelp,tHelpTimeout,helpX,helpY; private string message; private int defendX,defendY,__defendRadiusUnused,tDefendStart,tDefendTimeout, defendMoveType,baseRange,curTech,numVtolAttackGroups,numAttackVtols, numDefendVtols,rebuildStructX[MAX_REBUILD_STRUCT],rebuildStructY[MAX_REBUILD_STRUCT],countRebuildStruct; private STRUCTURESTAT rebuildStructStat[MAX_REBUILD_STRUCT]; private STRUCTURESTAT fundamentalBeingBuilt; private int order; // callback global ///////////////////////////////////////////////////////////////////// // triggers. #region triggers trigger reachedTr (CALL_DROID_REACH_LOCATION, me, ref droid, ref order); trigger buildExpandTr (every, 600); trigger fortifyTr (every, 1000); trigger upgradeStructuresTr (every, 360); trigger conDroidsTr (every, 900); // was 1400 trigger repairDroidsTr (every, 2600); trigger basedetailsTr (every, 600 ); trigger buildDerrickTr (every, 80 ); trigger buildOilDefenseOrRetreatTr (every, 120 ); trigger incendryTr (every, 250 ); trigger buildPowerGeneratorsTr (every, 80 ); trigger buildBaseTr (every, 150 ); trigger finishStructsTr (every, 210); trigger droidBuiltTr (CALL_NEWDROID,me, ref droid,ref structure); trigger structBuiltTr (CALL_STRUCTBUILT, me, ref droid, ref structure); trigger droidDestroyedTr (CALL_DROID_DESTROYED, me, ref droid); trigger structureDestroyedTr (CALL_STRUCT_DESTROYED, me, ref structure); trigger rebuildStructureTr (every, 50); trigger consolidateEventTr (every, 3100); trigger factoryEventTr (every, 170 ); trigger cyborgFactoryEventTr (every, 170 ); trigger chooseScoutAreaTr (every, 200 ); trigger expandScoutAreaTr (every, 600 ); trigger scoutMainTr (every, 150 ); trigger newObjectReportTr (CALL_OBJ_SEEN, me, ref baseobj, ref baseobj2); trigger attackStuffTr (every, 300 ); trigger allOutAttackTr (every, 4000); trigger defendWatchTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj); trigger defendReturnTr (every, 500 ); trigger doResearchTr (CALL_RESEARCHCOMPLETED, ref research, ref structure, me); trigger vtolDefendTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj); trigger vtolStructsTr (every, 290); trigger buildVtolsTr (every, 360); trigger vtolAttackTr (every, 150); trigger vtolEnablerTr (every, 700); trigger takeoverTr (CALL_UNITTAKEOVER, ref droid); trigger useLassatTr (every, 3000); trigger reassignTr (CALL_PLAYERLEFT,ref count); trigger formAllianceEventTr (every,170); trigger breakAllianceEventTr (every,3000); trigger difficultyModifierTr (every,600); trigger humanAllianceTr (CALL_ALLIANCEOFFER,ref count, ref count2); trigger multiMsgTr (CALL_AI_MSG, me, ref sender, ref message); trigger beaconTr (CALL_BEACON, me, ref sender, ref x, ref y, ref message); trigger consoleTr (CALL_CONSOLE, ref sender, ref message); trigger watchBaseThreatTr (every, 120); trigger manageAllyHelpTr (every, 80); trigger everySec (every, 10); trigger manageDefendLocationTr (every, 70); trigger startLevelTr (CALL_START_NEXT_LEVEL); trigger chainloadTr (wait, 1); trigger slowloadTr (wait, 13); trigger checkResearchTr (every, 400); /* Events */ event conDroids; event multiMsgEv; event beaconEv; event watchBaseThreat; event manageAllyHelp; event everySecEv; event manageDefendLocationEv; event structureDestroyed; event rebuildStructureEv; event doResearch; event buildDerrick; /* Function prototypes */ function bool haveBeacon(int _player); function bool beaconTimeout(int _player); function void processCommand(string _message, int _sender, bool _bBlipMessage); function bool haveHelpers(); function bool attemptToHelp(int _playerToHelp, int _x, int _y); function void helpPlayer(int _playerToHelp, int _helpX, int _helpY); function bool canStopHelpingAlly(); function void stopHelpingAlly(); function bool helpingAlly(); function bool helpAllyTimeout(); function void requestHelp(int _helpX, int _helpY); function void doRequestHelp(int _helpX, int _helpY); function bool allyBaseAtLoc(int _ally, int _x, int _y); function void messagePlayer(int _playerToMessage, string _message, int _probability); function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message); function bool canSeeAllies(); function bool baseInTrouble(); function string m_affirmative(); function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, bool _bMove); function void stopDefendingLocation(); function bool defendingLocation(); function bool defendLocationTimeout(); function bool friendlyPlayer(int _playerToCheck); function void factoryBuildDroid(STRUCTURE _factory); function void cybFactorBuildCyborg(STRUCTURE _factory); function void vtolFactoryBuildVtol(STRUCTURE _factory); function bool insideBase(int _x, int _y); function int numAlliesInBase(bool _bVtols); function int numEnemiesInBase(bool _bVtols); function bool defendingOwnBase(); function int targetTypeValue(BASEOBJ _target); function int numBitsSet(int _integer); function int findResearch(int _searchStart, int _techTree); function bool upgradeFactory(DROID _truck, int _maxBuilders); function bool upgradeVtolFactory(DROID _truck, int _maxBuilders); function bool upgradeResearch(DROID _truck, int _maxBuilders); function bool upgradePowGen(DROID _truck, int _maxBuilders); function void buildRearmPads(); function int numEnemyAAInRange(int _x, int _y, int _range); function BASEOBJ chooseVtolTarget(bool bExclusiveTarget); function int getVtolTargetWeight(BASEOBJ _target); function bool vtolTargetAssigned(BASEOBJ _target); function int numBuildSameBuilding(STRUCTURESTAT _checkStat, int _x, int _y); function int totalVtols(); function bool needTank(); function void setTechBranch(int _tech); function DROID closestIdleTruck(int _x, int _y); function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat); function void rebuildStructures(); function BASEOBJ chooseVtolDefenceTarget(int _x, int _y, int _range, bool bExclusiveTarget); function int numGroupSameOrder(GROUP _group, int _orderIndex); function void rearrangeAttackVtols(); function int numStructBusyByType(STRUCTURESTAT _busyStructType); function bool aiResponsibleForPlayer(int _player); function void reassignAI(); function void shutDownAI(); function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly); function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly); #endregion triggers ///////////////////////////////////////////////////////////////////// // HouseKeeping event initialisedEvent(CALL_GAMEINIT) { local int player; // initialise me = getPlayer("Nexus"); _DEBUG = FALSE; dbgMsgOn(me, _DEBUG); extraStruct = 0; numRepairUnits = 0; allOutAttack = NULLOBJECT; tLastHelpRequest = -1; //when we requested help for the last time lastHelpPlayer = -1; //we are not currently helping anyone tHelp = -1; //when we started helping last time tHelpTimeout = -1; //time when help times out helpX = -1; helpY = -1; defendX = -1; defendY = -1; tDefendStart = -1; tDefendTimeout = -1; defendMoveType = -1; //move or scout baseRange = 4 * TILE; // set current research branch setTechBranch(-1); numVtolAttackGroups = 10; numAttackVtols = 10; //num vtols in an attack group numDefendVtols = 5; //num vtols in an attack group // setup build group - all initial droids are in buildgroup! groupAddArea(buildGroup, me, 0, 0, (mapWidth*128), (mapHeight*128)); // note where our base is. getPlayerStartPosition(me, ref baseX, ref baseY); // defence. defendbusy = FALSE; // setup scouts structure = getStructure(factory, me); if(structure != NULLOBJECT) { scoutTLX = structure.x; scoutTLY = structure.y; } else { scoutTLX = baseX; scoutTLY = baseY; } scoutW = 256; scoutH = 256; scoutX = scoutTLX; scoutY = scoutTLY; // clear the alliance array... player = 0; while (player != MAX_PLAYERS) { allianceTime[player] = 0; player = player + 1; } fundamentalBeingBuilt = derrick; // to avoid ever being null if(aiResponsibleForPlayer(me)) { bRunning = true; } else { bRunning = false; shutDownAI(); } } // check whether we have at least one structure of that type function bool haveStructure(STRUCTURESTAT type) { return getStructure(type, me) != NULLOBJECT; } // check if we are getting any income function bool havePowerSource() { // we don't check buildings being finished here return haveStructure(powGen) and haveStructure(derrick); } // I am not sure why we need this hack, but the AI can still end up not researching anything at times event checkResearch(checkResearchTr) { setEventTrigger(doResearch, chainloadTr); } function void dbgPlr(string message) { setEventTrigger(doResearch, chainloadTr); if (me == selectedPlayer) { console(message); } } function void dbgObj(DROID obj, string message) { if (obj.selected) { console(message); } } function bool conCanHelp(DROID mydroid, int bx, int by) { return (mydroid.order != DORDER_HELPBUILD and mydroid.order != DORDER_BUILD and mydroid.order != DORDER_LINEBUILD and droidCanReach(mydroid, bx, by)); } // Build something in main base, grab trucks to do it within tiles range function bool grabTrucksAndBuild(int range, STRUCTURESTAT bstats, int maxBlockingTiles) { local DROID mydroid, closestDroid; local int closestDist, currDist, numHelpDroids, tilerange, bx, by; initIterateGroup(buildGroup); // find idle droids in build group. mydroid = iterateGroup(buildGroup); closestDist = 99999; closestDroid = NULLOBJECT; numHelpDroids = 0; tilerange = range * TILE; while (mydroid != NULLOBJECT) { if (conCanHelp(mydroid, baseX, baseY)) { bx = baseX; by = baseY; if (pickDroidStructLocation(mydroid, bstats, ref bx, ref by, me, maxBlockingTiles)) { currDist = distBetweenTwoPoints(bx, by, mydroid.x, mydroid.y); if (currDist < tilerange) { orderDroidStatsLoc(mydroid, DORDER_BUILD, bstats, bx, by); // close, so help build it numHelpDroids = numHelpDroids + 1; } else if (currDist < closestDist) { closestDroid = mydroid; // record this droid as being closest so far closestDist = currDist; } } } mydroid = iterateGroup(buildGroup); } if (numHelpDroids == 0 and closestDroid != NULLOBJECT) // found none within help radius, so force someone to go long distance traveling { orderDroidStatsLoc(closestDroid, DORDER_BUILD, bstats, bx, by); // you, book a plane ticket and go! return true; } return (numHelpDroids > 0); } event arrived(reachedTr) { local bool found; local STRUCTURESTAT myChoice; if (droid.droidType == DROID_CONSTRUCT or droid.droidType == DROID_CYBORG_CONSTRUCT) { dbgObj(droid, "Failed to build where we should - attempt to screw up enemy oil derrick"); // Check if at oil well, and it was taken by enemy structure = structureBuiltInRange(derrick, droid.x, droid.y, (5 * 128), -1); if (structure != NULLOBJECT) { if (not friendlyPlayer(structure.player) and droid.health == 100) { // Ok, at enemy derrick, and nobody has hurt us yet. Start being nasty. count = 0; found = false; // find simplest/cheapest one available to build while (count < numDefStructs and not found) { if (isStructureAvailable(defStructs[count], me)) { found = true; } else { count++; } } if (found) { buildX = droid.x; buildY = droid.y; if (pickDroidStructLocation(droid, defStructs[count], ref buildX, ref buildY, me, -1)) { orderDroidStatsLoc(droid, DORDER_BUILD, defStructs[count], buildX, buildY); } else { dbgObj(droid, "Wanted to be nasty, but found nowhere to build defense"); orderDroid(droid, DORDER_RTB); // nothing more to do here. } } else { dbgObj(droid, "Wanted to be nasty, but had nothing nasty to build - returning to base"); orderDroid(droid, DORDER_RTB); // oh, well. nothing more to do here. } exit; } else if (droid.health < 100 and !insideBase(droid.x, droid.y)) { orderDroid(droid, DORDER_RTR); // bolt back to base now! exit; } } } } event buildFundamentals(inactive) { count = 0; while (count < numFundamental) { // check that struct. structure = getStructure(structs[count], me); if (structure == NULLOBJECT) // if missing build it. { if (isStructureAvailable(structs[count], me)) { if (grabTrucksAndBuild(12, structs[count], 0)) { exit; // no need to check more } } } count = count + 1; } fundamentalBeingBuilt = derrick; setEventTrigger(buildFundamentals, inactive); } event startLevel(startLevelTr) { setEventTrigger(buildFundamentals, slowloadTr); setEventTrigger(conDroids, chainloadTr); setEventTrigger(doResearch, chainloadTr); setEventTrigger(buildDerrick, slowloadTr); setEventTrigger(startLevel, inactive); } // decide what technology branch we will use function void setTechBranch(int _tech) { local float _y2,_y1,_x2,_x1,_a,_y,_m,_rnd,_mapSize; _mapSize = (float)((mapWidth + mapHeight) / 2); if(_tech != -1) { curTech = _tech; } else { //probability to choose vtol branch for map size 90 = 0; probability for map size 200 = 45 //build a linear function: y = ((y2 - y1) / (x2 - x1)) * x + a depending on two values given (short: y = mx+a) _x1 = 90.0; _y1 = 0.0; _x2 = 200.0; _y2 = 45.0; _m = ((_y2 - _y1) / (_x2 - _x1)); _a = -(_m * _x1); //calculate probability for the current map _y = _m * _mapSize + _a; dbg("_m = " & _m & ", a = " & _a, me); _rnd = (float)random(100); if(_rnd < _y) { curTech = branchVTOL; dbg("going air (" & _y & "/" & _rnd & ")", me); } else { curTech = branchDefault; dbg("going land (" & _y & "/" & _rnd & ")", me); } } } /* returns TRUE if AI is responsible for the _player */ function bool aiResponsibleForPlayer(int _player) { if(not _DEBUG and ((_player == selectedPlayer) or not myResponsibility(_player))) { return FALSE; } return TRUE; } ///////////////////////////////////////////////////////////////////// // keep details about the size and postion of the ai players base event basedetails(basedetailsTr) { // clear old extremities. maxy = 0; maxx = 0; miny = (mapHeight*128); minx = (mapWidth*128); baseRange = 4 * TILE; // now find the extremities of our vital structures. count = 0; while(count < numBaseStruct) { initEnumStruct(FALSE,baseStruct[count],me,me); structure= enumStruct(); while(structure != NULLOBJECT) { if(structure.x < minx) { minx = structure.x; } if(structure.x > maxx) { maxx = structure.x; } if(structure.y < miny) { miny = structure.y; } if(structure.y > maxy) { maxy = structure.y; } result = distBetweenTwoPoints(baseX, baseY, structure.x, structure.y); if(result > baseRange){ baseRange = result; } structure= enumStruct(); } count = count + 1; } result = 3 * 128; minx = minx - result; maxx = maxx + result; miny = miny - result; maxy = maxy + result; baseRange = baseRange + (4 * 128); } ///////////////////////////////////////////////////////////////////// // structure building rules // build derricks on oil. event buildDerrick(buildDerrickTr) { local bool foundOne, _same; local FEATURE _oil, _closestOil; local int _bestDist, _newDist; local DROID _search; // what if we can't waste power on building derricks because we don't have a gen yet? if (playerPower(me) < 300 and haveStructure(derrick) and not haveStructure(powGen)) { setEventTrigger(buildDerrick, slowloadTr); exit; } _bestDist = 99999; _closestOil = NULLOBJECT; foundOne = false; initIterateGroup(buildGroup); // find all units in build group droid = iterateGroup(buildGroup); while (droid != NULLOBJECT && !foundOne) { if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD) { foundOne = true; } else { droid = iterateGroup(buildGroup); } } if (droid != NULLOBJECT) { initGetFeature(oilRes, -1, me); _oil = getFeatureB(me); while (_oil != NULLOBJECT) { _newDist = distBetweenTwoPoints(droid.x, droid.y, _oil.x, _oil.y); _same = false; if (_newDist < _bestDist and droidCanReach(droid, _oil.x, _oil.y)) // this one is closer { if (!threatInRange(me, _oil.x, _oil.y, OIL_THREAT_RANGE, FALSE)) { initIterateGroup(buildGroup); // find all units in build group. _search = iterateGroup(buildGroup); foundOne = false; while (_search != NULLOBJECT && !foundOne) { if (_search.orderx == _oil.x and _search.ordery == _oil.y and _search != droid) { _same = true; foundOne = true; } _search = iterateGroup(buildGroup); } if (!_same) // do not go to same spot as another droid { _bestDist = _newDist; _closestOil = _oil; } } } _oil = getFeatureB(me); } if (_closestOil != NULLOBJECT) { orderDroidStatsLoc(droid, DORDER_BUILD, derrick, _closestOil.x, _closestOil.y); // build a derick if (idleGroup(buildGroup) > 0) { setEventTrigger(buildDerrick, slowloadTr); // do it again for next droid exit; } } } setEventTrigger(buildDerrick, buildDerrickTr); } ///////////////////////////////////////////////////////////////////// // if idle and derrick in range and no defense then build defense, else ret to base . event buildOilDefenseOrRetreat(buildOilDefenseOrRetreatTr) { local int _numBuilders,_maxBuilders; _maxBuilders = 1; // check idle. initIterateGroup(buildGroup); // find idle droids in build group. droid = iterateGroup(buildGroup); while(droid != NULLOBJECT) { if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD) { // if in range of a derrick structure = structureBuiltInRange(derrick, droid.x, droid.y, (5*128), me); // if inside base limits then presume ok.. if( structure != NULLOBJECT) { if((structure.x > minx) and (structure.y > miny) and (structure.x < maxx) and (structure.y <maxy)) { structure = NULLOBJECT; } } if(structure != NULLOBJECT) { buildX = structure.x; buildY = structure.y; // not many defenses nearby if(numFriendlyWeapStructsInRange(me, buildX, buildY, (3*128), FALSE) < 2) { count = numDefStructs - 1; //pick a struct to build.. count2 = 0; while( (count2 < 5) and (count >= 0) ) { if( isStructureAvailable(defStructs[count],me)) { structChoice[count2] = defStructs[count]; count2 = count2 + 1; } count = count - 1; } count =0; if(count2 > 0) { count = random(count2); //count = choice! // pick a location boolResult = pickDroidStructLocation(droid, structChoice[count], ref buildX, ref buildY, me, -1); _numBuilders = numBuildSameBuilding(NULLSTRUCTURESTAT, buildX, buildY); if((boolResult == TRUE) and (_numBuilders < _maxBuilders) and droidCanReach(droid, buildX, buildY)) { // build it. orderDroidStatsLoc(droid, DORDER_BUILD,structChoice[count], buildX,buildY); _numBuilders++; } } } else { structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me); if(structure == NULLOBJECT) { if(!insideBase(droid.x, droid.y)) { orderDroid(droid,DORDER_RTB); // return to base; } } } } else { structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me); if(structure == NULLOBJECT) { if(!insideBase(droid.x, droid.y)) { orderDroid(droid,DORDER_RTB); // return to base; } } } } droid = iterateGroup(buildGroup); } } ///////////////////////////////////////////////////////////////////// //mortar etc.. rules. build sensor towers and emplacements. event incendry(incendryTr) { if (not isStructureAvailable(sensorTower, me)) { exit; } initEnumStruct(FALSE,sensorTower,me,me); count = 0; structure = enumStruct(); while(structure != NULLOBJECT) { count = count + 1; structure = enumStruct(); } if (count < (gameTime/4200)) // every 7 mins { // if not found build a sensor tower. // find a place to build. buildX = 0; buildY = 0; initEnumStruct(FALSE,derrick,me,me); structure= enumStruct(); while(structure != NULLOBJECT) { count = 0; result = 0; while(count < numDefStructs) { structure2 = structureBuiltInRange(defStructs[count], structure.x, structure.y,(4*128), me); if(structure2 != NULLOBJECT) { result = result + 1; } count = count + 1; } // check for sensor nearby, structure2 = structureBuiltInRange(sensorTower, structure.x, structure.y,(5*128), me); if(structure2 != NULLOBJECT) { result = 4; } if(result < 3) { buildX = structure.x; buildY = structure.y; structure = NULLOBJECT; } else { structure = enumStruct(); } } if(buildX != 0) { boolResult = pickStructLocation(sensorTower, ref buildX, ref buildY,me); // pick spot. if(boolResult == TRUE) { // find unit initIterateGroup(buildGroup); droid = iterateGroup(buildGroup); while(droid != NULLOBJECT) { if ((droid.order == DORDER_NONE or droid.order == DORDER_RTB) and droidCanReach(droid, buildX, buildY)) { orderDroidStatsLoc(droid, DORDER_BUILD, sensorTower, buildX, buildY); droid = NULLOBJECT; } else { droid = iterateGroup(buildGroup); } } } } } else { // find a sensor tower with least incencdry structs around it.. buildX = 0; buildY = 0; initEnumStruct(FALSE,sensorTower,me,me); structure= enumStruct(); count = 999; while(structure != NULLOBJECT) { // count incendrys near this tower. result = 0; count2 = 0; while(count2 < numIncendrys) { structure2 = structureBuiltInRange(incendrys[count2], structure.x, structure.y,(4*128), me); if(structure2 != NULLOBJECT) { result = result + 1; } count2 = count2 + 1; } if((result < 6) and (result < count)) // lowest found yet. only sites with <6 too. { buildX = structure.x; buildY = structure.y; count = result; } structure = enumStruct(); } if(buildX != 0) { // choose a device count = numIncendrys - 1; result = 99; while(count >= 0 ) { if(isStructureAvailable(incendrys[count],me)) { result = count; count = -1; } else { count = count - 1; } } // find a unit and build an incendry device. if(result != 99) { boolResult = pickStructLocation(incendrys[result], ref buildX, ref buildY,me); // pick spot. if(boolResult == TRUE) { initIterateGroup(buildGroup); droid = iterateGroup(buildGroup); boolResult = (numBuildSameBuilding(incendrys[result], buildX, buildY) > 0); //anyone building there already? while(droid != NULLOBJECT and (not boolResult)) { if ((droid.order == DORDER_NONE or droid.order == DORDER_RTB) and droidCanReach(droid, buildX, buildY)) { orderDroidStatsLoc(droid, DORDER_BUILD,incendrys[result], buildX,buildY); boolResult = TRUE; //only 1 truck } droid = iterateGroup(buildGroup); } } } } } } ///////////////////////////////////////////////////////////////////// // build a power gen for every 4 derricks. VITAL! event buildPowerGenerators(buildPowerGeneratorsTr) { if (!isStructureAvailable(powGen, me)) { exit; } initEnumStruct(FALSE,derrick,me,me); // count = numderricks structure= enumStruct(); count = 0; while(structure != NULLOBJECT) { count = count + 1; structure= enumStruct(); } initEnumStruct(FALSE,powGen,me,me); // count2 = numpowgens structure= enumStruct(); count2 = 0; while(structure != NULLOBJECT) { count2 = count2 + 1; structure= enumStruct(); } if( (count2 * 4) < count ) // if we need powergen { initIterateGroup(buildGroup); droid = iterateGroup(buildGroup); while(droid != NULLOBJECT) { if (droid.order != DORDER_HELPBUILD and droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD) { buildX = baseX; // try build powergen. buildY = baseY; if (pickDroidStructLocation(droid, powGen, ref buildX, ref buildY, me, 1)) { orderDroidStatsLoc(droid, DORDER_BUILD, powGen, buildX,buildY); } } droid = iterateGroup(buildGroup); } } } ///////////////////////////////////////////////////////////////////// // ensure we have everything in the vital structs list. event buildBase(buildBaseTr) { if (idleGroup(buildGroup) >= (buildGroup.members / 2)) { count = 0; while(count < numStructs) { // check that struct. structure = getStructure(structs[count],me); if(structure == NULLOBJECT) // if missing build it. { if(isStructureAvailable(structs[count],me)) { if (grabTrucksAndBuild(10, structs[count], 0)) { exit; // done here } } } count = count + 1; } } } ///////////////////////////////////////////////////////////////////// // build other stuff, grow the base slowly... event buildExpand( buildExpandTr ) { if (playerPower(me) < LOW_POWER) { exit; // do not expand base with low power } if(extraStruct == numExtraStructs[curTech]) // loop round { extraStruct = 0; } if(isStructureAvailable(extraStructs[curTech][extraStruct],me)) { if (not grabTrucksAndBuild(10, extraStructs[curTech][extraStruct], 0)) { dbg("Failed to build expand", me); } } extraStruct = extraStruct + 1; } ///////////////////////////////////////////////////////////////////// // Structure (fac/res/pow) upgrades event upgradeStructures(upgradeStructuresTr ) { if (not havePowerSource()) { exit; } initIterateGroup(buildGroup); // find idle droids in build group. droid = iterateGroup(buildGroup); while(droid != NULLOBJECT) { if ((droid.order != DORDER_BUILD) and (droid.order != DORDER_LINEBUILD)) { boolResult = FALSE; if(curTech == branchDefault) { //powergen boolResult = upgradePowGen(droid, 2); //factory if(droid.order != DORDER_BUILD){ boolResult = upgradeFactory(droid, 3); } //research if(droid.order != DORDER_BUILD){ boolResult = upgradeResearch(droid, 1); } //vtol Factory if(droid.order != DORDER_BUILD){ boolResult = upgradeVtolFactory(droid, 1); } } else if(curTech == branchVTOL) { //powergen boolResult = upgradePowGen(droid, 2); //vtol Factory if(droid.order != DORDER_BUILD){ boolResult = upgradeVtolFactory(droid, 3); } //factory if(droid.order != DORDER_BUILD){ boolResult = upgradeFactory(droid, 2); } //research if(droid.order != DORDER_BUILD){ boolResult = upgradeResearch(droid, 1); } } } droid = iterateGroup(buildGroup); } } function bool upgradeFactory(DROID _truck, int _maxBuilders) { local STRUCTURE _factory; initEnumStruct(FALSE,factory,me,me); _factory = enumStruct(); while(_factory != NULLOBJECT) { // if upgrade is available && struct is not upgraded if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(_factory) < 2 ) and droidCanReach(_truck, _factory.x, _factory.y)) { if((numBuildSameBuilding(facModule, _factory.x, _factory.y) + numBuildSameBuilding(vtolFactory, _factory.x, _factory.y)) < _maxBuilders) { orderDroidStatsLoc(_truck, DORDER_BUILD,facModule, _factory.x,_factory.y); // upgrade it. return TRUE; } } _factory = enumStruct(); } return FALSE; } function bool upgradeVtolFactory(DROID _truck, int _maxBuilders) { local STRUCTURE _factory; initEnumStruct(FALSE,vtolFactory,me,me); _factory = enumStruct(); while(_factory != NULLOBJECT) { // if upgrade is available && struct is not upgraded if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(_factory) < 2 ) and droidCanReach(_truck, _factory.x, _factory.y)) { if((numBuildSameBuilding(facModule, _factory.x, _factory.y) + numBuildSameBuilding(factory, _factory.x, _factory.y)) < _maxBuilders) { orderDroidStatsLoc(_truck, DORDER_BUILD,facModule, _factory.x,_factory.y); // upgrade it. return TRUE; } } _factory = enumStruct(); } return FALSE; } function bool upgradeResearch(DROID _truck, int _maxBuilders) { local STRUCTURE _resFac; initEnumStruct(FALSE,resLab,me,me); _resFac = enumStruct(); while(_resFac != NULLOBJECT) { // if upgrade is available && struct is not upgraded if( isStructureAvailable(resModule,me) and (not testStructureModule(me, _resFac, 0)) and droidCanReach(_truck, _resFac.x, _resFac.y)) { if((numBuildSameBuilding(resModule, _resFac.x, _resFac.y) + numBuildSameBuilding(resLab, _resFac.x, _resFac.y)) < _maxBuilders) { orderDroidStatsLoc(_truck, DORDER_BUILD,resModule, _resFac.x,_resFac.y); // upgrade it. return TRUE; } } _resFac = enumStruct(); } return FALSE; } function bool upgradePowGen(DROID _truck, int _maxBuilders) { local STRUCTURE _powGen; initEnumStruct(FALSE,powGen,me,me); _powGen = enumStruct(); while(_powGen != NULLOBJECT) { // if upgrade is available && struct is not upgraded if( isStructureAvailable(powModule,me) and (not testStructureModule(me, _powGen, 0)) and droidCanReach(_truck, _powGen.x, _powGen.y)) { if((numBuildSameBuilding(powModule, _powGen.x,_powGen.y) + numBuildSameBuilding(powGen, _powGen.x,_powGen.y)) < _maxBuilders) { orderDroidStatsLoc(_truck, DORDER_BUILD, powModule, _powGen.x,_powGen.y); // upgrade it. return TRUE; } } _powGen = enumStruct(); } return FALSE; } ///////////////////////////////////////////////////////////////////// // Finish Building Part Built Structures event finishStructs(finishStructsTr) { initEnumStruct(TRUE,factory,me,me); structure= enumStruct(); while(structure != NULLOBJECT) { if(not structureComplete(structure)) { initIterateGroup(buildGroup); // find idle droids in build group. droid = iterateGroup(buildGroup); while(droid != NULLOBJECT) { if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droidCanReach(droid, structure.x, structure.y) and distBetweenTwoPoints(droid.x, droid.y, structure.x, structure.y) < 20 * TILE) { orderDroidObj(droid,DORDER_HELPBUILD,structure); } droid = iterateGroup(buildGroup); } } structure= enumStruct(); } } ///////////////////////////////////////////////////////////////////// // fortify base by builiding defensive structs on the edge of the base. // rewrote fortify to use scrSkDefenseLocation(baseX,baseY,me); event newfortify(fortifyTr) { local int _numBuilders,_maxBuilders; _maxBuilders = 1; if(numGroupSameOrder(buildGroup, DORDER_LINEBUILD) >= _maxBuilders) { exit; } boolResult = FALSE; initIterateGroup(buildGroup); // find idle an idle veh.in build group. droid = iterateGroup(buildGroup); while((boolResult == FALSE) and (droid != NULLOBJECT)) { if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD) { boolResult = TRUE; // dont do this again! tempx = baseX; tempy = baseY; // choose a suitable turret. count = numWallWeaps - 1; count2 = 0; while( (count2 < 3) and (count >= 0) ) { if( isStructureAvailable(wallWeaps[count],me)) { structChoice[count2] = wallWeaps[count]; count2 = count2 + 1; } count = count - 1; } count =0; if((count2 > 0) and (_numBuilders < _maxBuilders)) { count = random(count2); skDefenseLocationB(ref tempx,ref tempy,wall,structChoice[count],droid,me); _numBuilders++; } } droid = iterateGroup(buildGroup); } } ///////////////////////////////////////////////////////////////////// // droid building rules ///////////////////////////////////////////////////////////////////// // deal with a droid being built event droidBuiltAssign(droidBuiltTr) { if(isVtol(droid)) { if(vtolDefendGr.members < numDefendVtols) { groupAddDroid(vtolDefendGr, droid); } else { count = 0; while(count < numVtolAttackGroups) { if(vtolAttackGr[count].members < numAttackVtols) { dbg("added new vtol to group " & count, me); groupAddDroid(vtolAttackGr[count], droid); count = numVtolAttackGroups; } count++; } } } else if((droid.droidType != DROID_TRANSPORTER) and (droid.droidType != DROID_COMMAND)) { if((droid.droidType == DROID_REPAIR) or (droid.droidType == DROID_CYBORG_REPAIR)) { numRepairUnits = numRepairUnits + 1; } if((droid.droidType == DROID_CONSTRUCT) or (droid.droidType == DROID_CYBORG_CONSTRUCT)) // if constructor droid { groupAddDroid(buildGroup, droid); } else { if(droid.droidType == DROID_CYBORG) { groupAddDroid(defendGroup, droid); } else { if(scoutGroup.members < numScouts[curTech]) { groupAddDroid(scoutGroup, droid); } else if(attackGroup.members < numAttackers[curTech]) { groupAddDroid(attackGroup, droid); } else if( defendGroup.members < numDefenders[curTech]) { groupAddDroid(defendGroup, droid); } else { if(scoutGroup.members < maxScouts[curTech]) { groupAddDroid(scoutGroup, droid); } else if(attackGroup.members < maxAttackers[curTech]) { groupAddDroid(attackGroup, droid); } else if( defendGroup.members < maxDefenders[curTech]) { groupAddDroid(defendGroup, droid); } else //make them attack { groupAddDroid(attackGroup, droid); } } } } } } //When droid built: check emergency jobs, start building next droid event droidBuilt(droidBuiltTr) { local STRUCTURE _fundie; /* Start building next droid */ if(structure != NULLOBJECT) { // derrick works as NULL here, as NULLSTAT does not seem to work if (droid.droidType == DROID_CONSTRUCT and fundamentalBeingBuilt != derrick) { _fundie = getStructure(fundamentalBeingBuilt, me); if (_fundie != NULLOBJECT) { if (not structureComplete(_fundie)) { orderDroidObj(droid, DORDER_HELPBUILD, _fundie); } } } if (droid.droidType == DROID_CONSTRUCT && structure.stattype == REF_FACTORY) { setEventTrigger(conDroids, chainloadTr); // consider building more } // Continue building new droids right away else if(structure.stattype == REF_FACTORY) { factoryBuildDroid(structure); } else if(structure.stattype == REF_CYBORG_FACTORY) { cybFactorBuildCyborg(structure); } else if(structure.stattype == REF_VTOL_FACTORY) { vtolFactoryBuildVtol(structure); } } } /* Gets triggered when structure was built */ event structBuilt(structBuiltTr) { local FEATURE _oilResource; local int _count,_count2; if (structure == NULLOBJECT || droid == NULLOBJECT) { exit; } /* factory or factory module */ if(structure.stattype == REF_FACTORY) { if (isStructureAvailable(facModule, me) and (skGetFactoryCapacity(structure) < 2 ) and (getDroidCount(me) > 4)) { orderDroidStatsLoc(droid, DORDER_BUILD,facModule, structure.x,structure.y); // upgrade it. } else { setEventTrigger(conDroids, chainloadTr); } } /* vtol factory or vtol factory module */ else if(structure.stattype == REF_VTOL_FACTORY) { if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(structure) < 2 )) { orderDroidStatsLoc(droid, DORDER_BUILD,facModule, structure.x,structure.y); // upgrade it. } } else if(structure.stattype == REF_RESOURCE_EXTRACTOR) { setEventTrigger(buildDerrick, chainloadTr); exit; } else if (structure.stattype == REF_RESEARCH) { if (isStructureAvailable(resModule, me)) { orderDroidStatsLoc(droid, DORDER_BUILD, resModule, structure.x, structure.y); // upgrade it. } else { setEventTrigger(doResearch, chainloadTr); } } else if (structure.stattype == REF_POWER_GEN) { if (isStructureAvailable(powModule, me)) { orderDroidStatsLoc(droid, DORDER_BUILD, powModule, structure.x, structure.y); // upgrade it. } } // Check if available trucks need to build more absolute necessities right away. We need a trigger here because // droids involved in building have not yet come out of their build orders. setEventTrigger(buildFundamentals, slowloadTr); //see if we have just rebuilt a destroyed structure _count = 0; while(_count < countRebuildStruct) { if(structure.x == rebuildStructX[_count] and structure.y == rebuildStructY[_count] and ( (structure.stat == rebuildStructStat[_count]) or //walls can end up as corner walls ( (structure.stat == wall or structure.stat == cornerWall) and (rebuildStructStat[_count] == wall or rebuildStructStat[_count] == cornerWall)) )) { dbg("finished rebuilding destroyed structure - " & _count, me); //resort destroyed structures _count2 = _count; while(_count2 < (countRebuildStruct - 1)) { rebuildStructX[_count2] = rebuildStructX[_count2 + 1]; rebuildStructY[_count2] = rebuildStructY[_count2 + 1]; rebuildStructStat[_count2] = rebuildStructStat[_count2 + 1]; _count2++; } //clear last entry rebuildStructX[countRebuildStruct - 1] = 0; rebuildStructY[countRebuildStruct - 1] = 0; rebuildStructStat[countRebuildStruct - 1] = NULLSTRUCTURESTAT; countRebuildStruct--; //we just built one structure //_count = countRebuildStruct; //exit outer loop } _count++; } } ///////////////////////////////////////////////////////////////////// // deal with attacks. event droidDestroyed(droidDestroyedTr) { if(droid.droidType == DROID_REPAIR) { numRepairUnits = numRepairUnits - 1; } if(droid.droidType == DROID_CONSTRUCT) // if constructor droid { initEnumStruct(FALSE,factory,me,me); structure= enumStruct(); // find factory. if( (structure != NULLOBJECT) and (getDroidCount(me) < MAX_DROIDS) ) { buildDroid(constructor, structure, me, 1); // build constructor } } } ///////////////////////////////////////////////////////////////////// // build more con droids. event conDroids(conDroidsTr) { local int _maxTrucks; local STRUCTURE _factory; local int _numBuilding,_haveTrucks,_maxTruckFactories,_totalTrucks; local bool _bStartedBuilding; _maxTrucks = MAX_TRUCKS; if (playerPower(me) < LOW_POWER) { _maxTrucks = MIN_TRUCKS; } _maxTruckFactories = 3; //max factories to use for truck production _haveTrucks = buildGroup.members; //Find out how many trucks and combat engineers are already in production _numBuilding = numTemplatesInProduction(constructor,me); //trucks _numBuilding = _numBuilding + numTemplatesInProduction(cybEngineer,me); //engineers _totalTrucks = _numBuilding + _haveTrucks; initEnumStruct(FALSE,factory,me,me); _factory = enumStruct(); while ((_factory != NULLOBJECT) and (_numBuilding < _maxTruckFactories) and (_totalTrucks < _maxTrucks)) { //Try to build a truck if (skCanBuildTemplate(me, _factory, hovertruck)) { _bStartedBuilding = buildUnit(hovertruck, _factory, factory, FALSE); //build truck even if not idle } else { _bStartedBuilding = buildUnit(constructor, _factory, factory, FALSE); //build truck even if not idle } //Update statistics if started building a truck if(_bStartedBuilding) { _numBuilding++; _totalTrucks++; } _factory = enumStruct(); } //build cyborg engineers if needed, no building structure limit here initEnumStruct(FALSE,cybFactory,me,me); _factory = enumStruct(); while((_factory != NULLOBJECT) and (_totalTrucks < _maxTrucks)) { //Try to build a truck if( skCanBuildTemplate(me,_factory, cybEngineer) ) //make sure we have researched cyb engineer { _bStartedBuilding = buildUnit(cybEngineer, _factory, cybFactory, FALSE); //build a cyb eng even if not idle //Update statistics if started building a cyborg engineer if(_bStartedBuilding) { _numBuilding++; _totalTrucks++; } } _factory = enumStruct(); } setEventTrigger(conDroids, conDroidsTr); } //Build a droid function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly) { //Factory was not provided, find an factory if(_factory == NULLOBJECT) { _factory = findIdleStructure(_factoryType, _bIdleOnly); } //Build if got a factory if(_factory != NULLOBJECT) { if(structureComplete(_factory) and (getDroidCount(me) < MAX_DROIDS)) { if( !(_bIdleOnly and !structureIdle(_factory)) ) //don't build if only allowed to build whe idle and fac is not idle { buildDroid(_tankTemplate, _factory, me, 1); // build a tank return TRUE; //success } } } return FALSE; //failed } //Returns an idle structure of the provided type or NULLOBJECT if none found function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly) { local STRUCTURE _structure; initEnumStruct(FALSE,_structType,me,me); _structure = enumStruct(); while(_structure != NULLOBJECT) { if(structureComplete(_structure)) { if( !(_bIdleOnly and !structureIdle(_structure)) ) { return _structure; } } _structure = enumStruct(); } return NULLOBJECT; //none found } ///////////////////////////////////////////////////////////////////// // build repair droids. event repairDroids(repairDroidsTr) { // if we're running low on repair droids, build some.. if(numRepairUnits <3) { initEnumStruct(FALSE,factory,me,me); structure= enumStruct(); // find factory. if (structure != NULLOBJECT) { if ((getDroidCount(me) < MAX_DROIDS) and (skCanBuildTemplate(me, structure, repairUnit))) { buildDroid(repairUnit, structure, me, 1); // build repairunit. } } } } ///////////////////////////////////////////////////////////////////// event factoryEvent(factoryEventTr) { // for each factory.... initEnumStruct(FALSE,factory,me,me); structure = enumStruct(); // find factory. if(getDroidCount(me) < MAX_DROIDS) { while(structure != NULLOBJECT) { if( structureIdle(structure) ) { factoryBuildDroid(structure); } structure = enumStruct(); } } } function bool needTank() { if(not havePowerSource()) { return FALSE; } if((defendGroup.members < maxDefenders[curTech]) or (maxDefenders[curTech] == UNLIMITED)) { return TRUE; } if((scoutGroup.members < maxScouts[curTech]) or (maxScouts[curTech] == UNLIMITED)) { return TRUE; } if((attackGroup.members < maxAttackers[curTech]) or (maxAttackers[curTech] == UNLIMITED)) { return TRUE; } return FALSE; } function void factoryBuildDroid(STRUCTURE _factory) { local int _count,_count2; if(_factory == NULLOBJECT){ dbg("factoryBuildDroid: factory is NULLOBJECT", me); return; } if(not needTank()) { //dbg("NEED NO TANKS!! " & maxDefenders[curTech], me); return; } if( structureIdle(_factory) ) { _count = numTemplates[curTech] - 1; _count2 = 0; while( (_count2 < MAX_RANDOM_TEMPLATES) and (_count >= 0) ) { if( skCanBuildTemplate(me,_factory, tmpl[curTech][_count]) ) { tmplChoice[_count2] = tmpl[curTech][_count]; _count2 = _count2 + 1; } _count = _count - 1; } if(_count2 > 0) { buildDroid(tmplChoice[random(_count2)],_factory,me,1); } } else { dbg("factoryBuildDroid: factory is busy", me); } } ///////////////////////////////////////////////////////////////////// // put cyborg factories to work event cyborgFactoryEvent(cyborgFactoryEventTr) { if(not ((defendGroup.members < maxCyborgs[curTech]) or (maxCyborgs[curTech] == UNLIMITED))) { exit; //we need no cyborgs } initEnumStruct(FALSE,cybFactory,me,me); structure= enumStruct(); // find factory. while(structure != NULLOBJECT) { if( structureIdle(structure) == TRUE) { cybFactorBuildCyborg(structure); } structure= enumStruct(); // find factory. } } function void cybFactorBuildCyborg(STRUCTURE _factory) { if(_factory == NULLOBJECT){ dbg("cybFactorBuildCyborg: factory is NULLOBJECT", me); return; } if( structureIdle(_factory) ) { if( (defendGroup.members < maxCyborgs[curTech]) and (getDroidCount(me) < MAX_DROIDS) ) { if(random(5) == 1) { buildDroid(cybMechanic,_factory,me,1); } else { count = 3; count2 = 0; while( count >= 0 ) { if( skCanBuildTemplate(me,_factory, superCyb[count]) ) { tmplChoice[count2] = superCyb[count]; count2 = count2 + 1; } count = count - 1; } if(count2 > 0) { buildDroid(tmplChoice[random(count2)],_factory,me,1); } else //try light cyborgs { count = numLightCyborgs - 1; count2 = 0; while( (count >= 0) and (count2 < 2) ) { if( skCanBuildTemplate(me,_factory, cybTempl[count]) ) { tmplChoice[count2] = cybTempl[count]; count2++; } count--; } if(count2 > 0) { buildDroid(tmplChoice[random(count2)], _factory, me, 1); } } } } } } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // scouting rules // scout an area event chooseScoutArea(chooseScoutAreaTr) { scoutX = scoutTLX + random(scoutW); scoutY = scoutTLY + random(scoutH); } ///////////////////////////////////////////////////////////////////// // visit new places event expandScoutArea(expandScoutAreaTr) { //expand the scouting area slightly scoutTLX = scoutTLX - ((mapWidth*128)/ tileExpand); scoutTLY = scoutTLY - ((mapHeight*128)/ tileExpand); scoutW = scoutW + (2*((mapWidth*128)/ tileExpand)); scoutH = scoutH + (2*((mapHeight*128)/ tileExpand)); // check & restrain. if(scoutTLX <1) { scoutTLX = 1; } if(scoutTLY <1) { scoutTLY = 1; } if(scoutTLX >(mapWidth*128)) { scoutTLX = (mapWidth*128) - 128; } if(scoutTLY >(mapHeight*128)) { scoutTLY = (128*mapHeight) - 128; } if( (scoutTLX + scoutW) > (128 * mapWidth) ) { scoutW = ( (128 * mapWidth) - scoutTLX) - 128; } if( (scoutTLY + scoutH) > (128 *mapHeight) ) { scoutH = ( (128*mapHeight) - scoutTLY) - 128; } } ///////////////////////////////////////////////////////////////////// // order scouts event scoutMain(scoutMainTr) { // find any new scouts // if scouts aren't busy, send them to a new spot. if( idleGroup(scoutGroup) >= (scoutGroup.members /2) ) { orderGroupLoc(scoutGroup, DORDER_MOVE,scoutX,scoutY); } } ///////////////////////////////////////////////////////////////////// // process new visibility reports event newObjectReport(newObjectReportTr) { if(!friendlyPlayer(baseobj.player)) { if(targetTypeValue(baseobj) > targetTypeValue(attackObj)) { attackObj = baseobj;// got a new unseen target from a scout. if( attackObj.type == OBJ_STRUCTURE) { if(not allianceExistsBetween(attackObj.player,me)) // an enemy { structure = objToStructure(attackObj); if(structure.stat == factory) { allOutAttack = attackObj; } } } } } } function int targetTypeValue(BASEOBJ _target) { local STRUCTURE _strTarget; if(_target == NULLOBJECT){ return NO_TARGET_VALUE; } if(_target.type == OBJ_DROID) { return DROID_TARGET_VALUE; } else if(_target.type == OBJ_STRUCTURE) { _strTarget = objToStructure(_target); if(_strTarget.stattype == REF_DEFENSE) { return DEFENSE_TARGET_VALUE; } else if(_strTarget.stattype == REF_RESEARCH or _strTarget.stattype == REF_POWER_GEN) { return RESEARCH_TARGET_VALUE; } else if(_strTarget.stattype == REF_HQ or _strTarget.stattype == REF_COMMAND_CONTROL) { return HQ_TARGET_VALUE; } else if(_strTarget.stattype == REF_RESOURCE_EXTRACTOR) { return OIL_TARGET_VALUE; } else if(_strTarget.stattype == REF_FACTORY or _strTarget.stattype == REF_CYBORG_FACTORY or _strTarget.stattype == REF_VTOL_FACTORY) { return FACTORY_TARGET_VALUE; } else //walls, rearm pads etc { return OTHER_TARGET_VALUE; } } return NO_TARGET_VALUE; } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // spy technologies //event takeover( CALL_UNITTAKEOVER , ref droid ) event takeover(takeoverTr) { if( droid.player == me ) { if(droid.droidType == DROID_CONSTRUCT or droid.droidType == DROID_CYBORG_CONSTRUCT) { groupAddDroid( buildGroup, droid ); } else if (droid.droidType != DROID_TRANSPORTER && droid.droidType != DROID_COMMAND) { groupAddDroid( attackGroup, droid ); } } } event takeoverDefend(takeoverTr) { if( droid.player != me ) { completeResearch(nexusDefence,me); setEventTrigger(takeoverDefend, inactive); } } event useLassat(useLassatTr) { // find my lassat // fire it at my attack objective. if(allOutAttack != NULLOBJECT) { initEnumStruct(FALSE,lassat,me,me); structure= enumStruct(); while(structure != NULLOBJECT) { if(structureComplete(structure) == TRUE) { skFireLassat(me,allOutAttack); } structure= enumStruct(); } } } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // attack rules event findEnemy(attackStuffTr) { if(attackObj == NULLOBJECT) { count = random(8); count2 = 100; while( friendlyPlayer(count) && (count2 > 0) ) { count = random(8); count2--; } if(!friendlyPlayer(count)) { baseobj = skLocateEnemy(count); if(baseobj != NULLOBJECT) { attackObj = baseobj; // set allOutAttack to attackObj only if attackObj is a more valuable target than allOutAttack if(targetTypeValue(attackObj) > targetTypeValue(allOutAttack)) { allOutAttack = attackObj; } } } } } ///////////////////////////////////////////////////////////////////// // send attack team out to cause trouble near things scout found. event attackStuff(attackStuffTr) { if( idleGroup(attackGroup) >= (attackGroup.members / 2)) { if( (attackObj != NULLOBJECT) and (not helpingAlly()) ) { if (not allianceExistsBetween(me, attackObj.player)) { if(attackGroup.members > (6 + random(6)) ) { orderGroupLoc(attackGroup, DORDER_SCOUT, attackObj.x, attackObj.y); } // make scouts attack too if( idleGroup(scoutGroup) >= (scoutGroup.members / 2) ) { orderGroupLoc(scoutGroup, DORDER_SCOUT, attackObj.x, attackObj.y); } } } } } ///////////////////////////////////////////////////////////////////// event doAllOutAttack(allOutAttackTr) { if (idleGroup(attackGroup) >= (attackGroup.members / 3)) // make sure at least 30% are idle { if ((allOutAttack != NULLOBJECT) and (not helpingAlly())) { if (!friendlyPlayer(allOutAttack.player)) { if (getDroidCount(me) > 40) // plenty of units. { orderGroupObj(attackGroup, DORDER_ATTACK, allOutAttack); orderGroupLoc(scoutGroup, DORDER_SCOUT, allOutAttack.x, allOutAttack.y); } } else { allOutAttack = NULLOBJECT; } } } } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // defending rules // defend attacked objects. event defendWatch(defendWatchTr) { if (baseobj != NULLOBJECT) { if(!friendlyPlayer(baseobj.player)) { if(distBetweenTwoPoints(baseobj.x, baseobj.y, baseX, baseY) <= MAX_DEFENDERS_RADIUS) //don't go too far away from the base { defendObj = baseobj; defendbusy = TRUE; // if not too busy, attack. if (idleGroup(defendGroup) >= (defendGroup.members / 2)) { orderGroupLoc(defendGroup, DORDER_MOVE,defendObj.x,defendObj.y); //cyborg mechanics can't attack (won't move) } if (idleGroup(scoutGroup) >= (scoutGroup.members / 2)) { orderGroupLoc(scoutGroup, DORDER_MOVE,scoutX,scoutY); } } } } } ///////////////////////////////////////////////////////////////////// // defenders return after they are finished. event defendReturn(defendReturnTr) { if( defendbusy and (idleGroup(defendGroup) == (defendGroup.members - defendGroup.members / 12))) { // find a place with no structures nearby buildX = baseX; buildY = baseY; pickStructLocationB(powGen, ref buildX, ref buildY, me, 0); orderGroupLoc(defendGroup, DORDER_MOVE,buildX,buildY); defendbusy = FALSE; } } //returns number of non-idle structures of a certain type function int numStructBusyByType(STRUCTURESTAT _busyStructType) { local int _result; initEnumStruct(FALSE,_busyStructType,me,me); structure = enumStruct(); _result = 0; while(structure != NULLOBJECT) { if(structureComplete(structure)) { if(not structureIdle(structure)) { _result++; } } structure = enumStruct(); } return _result; } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // Research Rules Now does true research. // do research event doResearch(doResearchTr) { local int _techIndex,_numResearching; // don't throw in half of your money on research in T3 no bases when we don't have any income yet if (isStructureAvailable(facModule,me) and not havePowerSource()) { setEventTrigger(doResearch, doResearchTr); exit; } _techIndex = 0; //research start _numResearching = numStructBusyByType(resLab); // for every research lab do this.. initEnumStruct(FALSE,resLab,me,me); structure= enumStruct(); count = 0; while(structure != NULLOBJECT) { boolResult = FALSE; //haven't started research for the current resFac if(structureIdle(structure)) { if(structureComplete(structure)) { // first research all technologies necessary for the current research branch while(not boolResult and _techIndex != NONE) //not started researching and still branch tech left to try { _techIndex = findResearch(_techIndex, curTech); if(_techIndex > NONE) { boolResult = pursueResearch(structure,me,tech[curTech][_techIndex]); _techIndex++; //try nect research next time if needed _numResearching++; } } // do common research if(not boolResult) //didn't start branch research { if((maxIdleRes[curTech] == UNLIMITED) or (_numResearching < maxIdleRes[curTech])) { skDoResearch(structure,me,0); _numResearching++; } } } } structure = enumStruct(); } setEventTrigger(doResearch, doResearchTr); } // find next available research of our research branch function int findResearch(int _searchStart, int _techTree) { local int _result; ASSERT(_searchStart >= 0, "findResearch: _searchStart < 0", me); ASSERT(_techTree >= 0, "findResearch: _techTree < 0", me); _result = _searchStart; while(_result < techCount[_techTree]) { if((not researchFinished(tech[_techTree][_result], me)) and (not researchStarted(tech[_techTree][_result], me))) { return _result; //found research } _result++; } return NONE; //not found } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // Alliance Rules // form alliances event formAllianceEvent(formAllianceEventTr) { count = 0; while(count < MAX_PLAYERS) { if( count != me ) // if not the only other player and rand2 { if((getDroidCount(me) > 1) and (getDroidCount(count) > 1) ) // not dead { if(random(28) == 1) // bit random { if(not isHumanPlayer(count)) // not human { createAlliance(me,count); allianceTime[count] = gameTime; } } } } count = count + 1; } } ///////////////////////////////////////////////////////////////////// // break the alliance too. event breakAllianceEvent(breakAllianceEventTr) { count = 0; while(count<multiPlayerMaxPlayers) { if( count != me) { if((getDroidCount(me) > 1) and (getDroidCount(count) > 1) ) // not dead { if(allianceExistsBetween(me,count) ) { // check if we're in alliance with any other players. if( (random(30) == 1) and ( (gameTime - allianceTime[count]) > 6000) ) // rand and more than 10 minutes. { allianceTime[count] = gameTime; breakAlliance(me,count); } // rules for breaking alliances with humans. // built within my base if(numStructsInArea(count,minx,miny,maxx,maxy) > 1) { allianceTime[count] = gameTime; breakAlliance(me,count); } // you've got lots of units in my area. if(numDroidsInArea(count,minx,miny,maxx,maxy) > 3) { allianceTime[count] = gameTime; breakAlliance(me,count); } // you've wiped out one of my allies ??. } } } count = count + 1; } } ///////////////////////////////////////////////////////////////////// event formHumanAlliances(humanAllianceTr) { if(count2 == me) // offered to me. { result = 0; result2 = 0; while(result < multiPlayerMaxPlayers) { if(allianceExistsBetween(count,result)) { result2 = result2 + 1; } result = result + 1; } if( result2 < ((multiPlayerMaxPlayers / 2) - 1) ) // not too many already { //not too soon. if((allianceTime[count] == 0) or (gameTime - allianceTime[count] > 1200)) { result = 0; // check forming wont end the game result2 = 0; while(result < multiPlayerMaxPlayers) { while(result2 < multiPlayerMaxPlayers) { if((not allianceExistsBetween(result,result2)) and (getDroidCount(result) > 0) and (getDroidCount(result2) > 0) and (result != result2) ) { if( ((result == count and result2 == count2) or (result2 == count2 and result == count)) ) // ignore the outcome of this alliance { createAlliance(me,count); allianceTime[count] = gameTime; } } result2 = result2 + 1; } result = result + 1; } } } } } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // Consolidate Rules // bring forces back together to consolidate attacks event consolidateEvent(consolidateEventTr) { if(not helpingAlly()) { if(random(3) == 1) // order all droids home to rejoin forces.! { // find a place with no structures nearby buildX = baseX; buildY = baseY; pickStructLocationB(powGen, ref buildX, ref buildY, me, 0); orderGroupLoc(scoutGroup, DORDER_MOVE,buildX,buildY); orderGroupLoc(defendGroup, DORDER_MOVE,buildX,buildY); } /* if(attackObj != NULLOBJECT) // consolidate any ongoing attack. { if(!friendlyPlayer(attackObj.player)) { orderGroupLoc(attackGroup, DORDER_SCOUT, attackObj.x, attackObj.y); } else { attackObj = NULLOBJECT; } } else if(allOutAttack == NULLOBJECT) //make sure not allOutAttacking { // find a place with no structures nearby buildX = baseX; buildY = baseY; pickStructLocationB(powGen, ref buildX, ref buildY, me, 0); orderGroupLoc(attackGroup, DORDER_MOVE,buildX,buildY); } */ } } ///////////////////////////////////////////////////////////////////// event difficultyModifier(difficultyModifierTr) { if(not isHumanPlayer(me)) { skDifficultyModifier(me); } } ///////////////////////////////////////////////////////////////////// // vtols. ///////////////////////////////////////////////////////////////////// // build vtol strucutures. event vtolStructs(inactive) { local int _numVtolFacs,_numRearmPads; // got any idle trucks? if (idleGroup(buildGroup) < 1) { exit; } // see how many vtol factories we already have _numVtolFacs = getNumStructures(vtolFactory,me); _numRearmPads = getNumStructures(vtolPad,me); //see if we have enough rearm pads if( _numRearmPads * 4 / 3 <= totalVtols() ) { dbg("NEED REARM PADS", me); buildRearmPads(); } if (_numVtolFacs > 0 and playerPower(me) < LOW_POWER) { exit; // Throttle expansion to avoid waste } if (isStructureAvailable(vtolFactory, me) and _numVtolFacs < maxVtolFacs[curTech]) // if not enough { if (not grabTrucksAndBuild(8, vtolFactory, 1)) { dbg("Failed to build Vtol fac", me); } } } //counts vtols function int totalVtols() { local int _vtolGroup,_totalVtols; _totalVtols = 0; _vtolGroup = 0; while(_vtolGroup < numVtolAttackGroups) { _totalVtols = _totalVtols + vtolAttackGr[_vtolGroup].members; _vtolGroup++; } _totalVtols = _totalVtols + vtolDefendGr.members; return _totalVtols; } function void buildRearmPads() { if (isStructureAvailable(vtolPad, me)) { if (not grabTrucksAndBuild(4, vtolPad, -1)) { dbg("Failed to build vtol pad", me); } } } ///////////////////////////////////////////////////////////////////// // build vtols. event buildVtols(inactive) { // got enough vtols? if((vtolDefendGr.members >= maxVTOLs[curTech]) or (getDroidCount(me) >= MAX_DROIDS)){ dbg("CAN'T BUILD VTOLS - TOO MANY UNITS", me); exit; } // build vtols initEnumStruct(FALSE,vtolFactory,me,me); structure = enumStruct(); while(structure != NULLOBJECT) { if(structureIdle(structure)) // if factory idle { vtolFactoryBuildVtol(structure); } structure = enumStruct(); } } function void vtolFactoryBuildVtol(STRUCTURE _factory) { local int _numTemplates,_bestTemplates; if(_factory == NULLOBJECT){ return; } if( structureIdle(_factory) ) { _numTemplates = numVtolTemplates - 1; _bestTemplates = 0; while( (_bestTemplates < 3) and (_numTemplates >= 0) ) { if( skCanBuildTemplate(me,_factory, vtols[_numTemplates]) ) { tmplChoice[_bestTemplates] = vtols[_numTemplates]; _bestTemplates++; } _numTemplates--; } if(_bestTemplates > 0) { buildDroid(tmplChoice[random(_bestTemplates)],_factory,me,1); } } } ///////////////////////////////////////////////////////////////////// // attack with vtols. event vtolAttack(inactive) { local int _groupIndex,_newTargetWeight,_oldTargetWeight; local BASEOBJ _newTarget; local bool _bHaveDefendTarget; local DROID _droid; // if vtol group is not busy.. if( (idleGroup(vtolDefendGr) >= (vtolDefendGr.members / 2)) and (vtolDefendGr.members >= 2) ) { if(attackObj != NULLOBJECT) { if(!friendlyPlayer(attackObj.player)) { orderGroupObj(vtolDefendGr, DORDER_ATTACK, attackObj); // get the attack target. } else { attackObj = NULLOBJECT; } } else { if(defendObj != NULLOBJECT) { orderGroupObj(vtolDefendGr, DORDER_ATTACK,defendObj); // get the defend target } } } //make sure attack vtol groups are not cluttered rearrangeAttackVtols(); //attack vtols _groupIndex = 0; while(_groupIndex < numVtolAttackGroups) { if(vtolAttackGr[_groupIndex].members > 0) { // if our base is in trouble see if we have a target in the base // don't choose new target if already have one _bHaveDefendTarget = FALSE; if((vtolGrAttackObj[_groupIndex] != NULLOBJECT)) { if(defendingOwnBase() and (distBetweenTwoPoints(baseX, baseY, vtolGrAttackObj[_groupIndex].x, vtolGrAttackObj[_groupIndex].y) <= MAX_VTOL_DEFEND_RADIUS)) { _bHaveDefendTarget = TRUE; } else //reset target if it's not worth it { //we don't want to attack enemy heavy tanks outside of our base if(vtolGrAttackObj[_groupIndex].type == OBJ_DROID) { _droid = objToDroid(vtolGrAttackObj[_groupIndex]); if(_droid.droidType != DROID_CONSTRUCT) { vtolGrAttackObj[_groupIndex] = NULLOBJECT; //reset target _bHaveDefendTarget = FALSE; } } } } //find target in our base if our base is in trouble if(!_bHaveDefendTarget and defendingOwnBase()) { vtolGrAttackObj[_groupIndex] = chooseVtolDefenceTarget(baseX, baseY, MAX_VTOL_DEFEND_RADIUS, FALSE); if(vtolGrAttackObj[_groupIndex] != NULLOBJECT) { dbg("assigned new defence target for group " & _groupIndex, me); _bHaveDefendTarget = TRUE; } } //attack rules if(!_bHaveDefendTarget and (idleGroup(vtolAttackGr[_groupIndex]) >= (vtolAttackGr[_groupIndex].members / 2)) and (vtolAttackGr[_groupIndex].members >= (numAttackVtols * 2 / 3))) { _newTarget = NULLOBJECT; //reset attack targets once in a while if(vtolGrAttackObj[_groupIndex] != NULLOBJECT) { if(random(10) > 7) { vtolGrAttackObj[_groupIndex] = NULLOBJECT; } } //now try to find an attack target if we have no defence target //find best attack target _newTarget = chooseVtolTarget(TRUE); //search for an exclusive target if(_newTarget == NULLOBJECT) { _newTarget = chooseVtolTarget(FALSE); //search for any target } _newTargetWeight = getVtolTargetWeight(_newTarget); _oldTargetWeight = getVtolTargetWeight(vtolGrAttackObj[_groupIndex]); // new one or a much better one if((_newTargetWeight >= (_oldTargetWeight + 20)) or (vtolGrAttackObj[_groupIndex] == NULLOBJECT )) { dbg("choosing new attack object for " & _groupIndex, me); vtolGrAttackObj[_groupIndex] = _newTarget; } } //see if this group has something to attack if(vtolGrAttackObj[_groupIndex] != NULLOBJECT) { if(!friendlyPlayer(vtolGrAttackObj[_groupIndex].player)) { dbg("VTOL Group " & _groupIndex & " attacking", me); if(_DEBUG and (_groupIndex == 0)) { dropBeacon(getPlayerName(me), me, me, vtolGrAttackObj[_groupIndex].x, vtolGrAttackObj[_groupIndex].y, 0); } orderGroupObj(vtolAttackGr[_groupIndex], DORDER_ATTACK, vtolGrAttackObj[_groupIndex]); } else { vtolGrAttackObj[_groupIndex] = NULLOBJECT; } } } _groupIndex++; } } //make sure vtol groups are not cluttered function void rearrangeAttackVtols() { local int _emptyGr,_fillGr; local DROID _droid; _emptyGr = 0; while(_emptyGr < numVtolAttackGroups) { if((vtolAttackGr[_emptyGr].members < numAttackVtols) and //this group is not full (vtolAttackGr[_emptyGr].members > 0)) { //try to make full groups by moving vtols from the last groups _fillGr = _emptyGr + 1; //start from the next group while((_fillGr < numVtolAttackGroups) and (vtolAttackGr[_emptyGr].members < numAttackVtols)) { initIterateGroup(vtolAttackGr[_fillGr]); _droid = iterateGroup(vtolAttackGr[_fillGr]); while((_droid != NULLOBJECT) and (vtolAttackGr[_emptyGr].members < numAttackVtols)) { groupAddDroid(vtolAttackGr[_emptyGr], _droid); //refill the group _droid = iterateGroup(vtolAttackGr[_fillGr]); } _fillGr++; } } _emptyGr++; } } function BASEOBJ chooseVtolDefenceTarget(int _x, int _y, int _range, bool bExclusiveTarget) { local BASEOBJ _target; _target = getClosestEnemy(_x, _y, _range, FALSE, FALSE, me); // make sure no one else is targeting it already if we want exclusive targets if(bExclusiveTarget and vtolTargetAssigned(_target)) { _target = NULLOBJECT; } return _target; } function BASEOBJ chooseVtolTarget(bool bExclusiveTarget) { local int _structTypeIndex,_enemy; local int _bestScore,_tempScore; local BASEOBJ _bestTarget; local STRUCTURE _structure; _bestScore = 0; _bestTarget = NULLOBJECT; _enemy = 0; while(_enemy < MAX_PLAYERS) { if(!friendlyPlayer(_enemy)) { _structTypeIndex = 0; while(_structTypeIndex < numVtolTargets) { initEnumStruct(FALSE,vtolTarget[_structTypeIndex],_enemy,me); _structure = enumStruct(); while(_structure != NULLOBJECT) { // in case we don't want all groups to attack the same target if(not (bExclusiveTarget and vtolTargetAssigned(_structure)) ) { _tempScore = getVtolTargetWeight(_structure); //see if this one is better if(_tempScore > _bestScore) { _bestScore = _tempScore; _bestTarget = _structure; } } _structure = enumStruct(); } _structTypeIndex++; } } _enemy++; } return _bestTarget; } function int getVtolTargetWeight(BASEOBJ _target) { local int _AAPenalty,_numAA,_range,_targetWeight; local int _targetType; local STRUCTURE _structTarget; if(_target == NULLOBJECT) { return 0; } if(_target.type != OBJ_STRUCTURE) { return 0; } _structTarget = objToStructure(_target); _targetWeight = 0; _AAPenalty = 9; //penalty per aa defense _range = AA_THREAT_RANGE; // count enemy AA _numAA = numEnemyAAInRange(_structTarget.x, _structTarget.y, _range); // find tyrget type from stats _targetType = 0; while(_targetType < numVtolTargets) { if(_structTarget.stat == vtolTarget[_targetType]) { _targetWeight = vtolTargetWeight[_targetType] - (_numAA * _AAPenalty); _targetType = numVtolTargets; //exit loop } _targetType++; } // incomplete structures get lower weight if(!structureComplete(_structTarget)) { _targetWeight = _targetWeight / 10; } return _targetWeight; } function int numEnemyAAInRange(int _x, int _y, int _range) { local int _enemy,_numAA; _numAA = 0; _enemy = 0; while(_enemy < MAX_PLAYERS) { if(!friendlyPlayer(_enemy)) { _numAA = _numAA + numAAinRange(_enemy, me, _x, _y, _range); } _enemy++; } return _numAA; } // see if a particular target is already assigned to one of the VTOL attack groups function bool vtolTargetAssigned(BASEOBJ _target) { local int _groupIndex; if(_target == NULLOBJECT) { return FALSE; } _groupIndex = 0; while(_groupIndex < numVtolAttackGroups) { if(_target == vtolGrAttackObj[_groupIndex]) { return TRUE; } _groupIndex++; } return FALSE; } ///////////////////////////////////////////////////////////////////// // watch for incoming vtols event vtolDefend(vtolDefendTr) { local int _numBuilders,_maxBuilders; if(baseobj != NULLOBJECT) { if(baseobj.type == OBJ_DROID) { if(isVtol(objToDroid(baseobj))) { _numBuilders = 0; _maxBuilders = 2; // build defenses. initIterateGroup(buildGroup); // find idle droids in build group. droid = iterateGroup(buildGroup); while( droid != NULLOBJECT) { if( (structure != NULLOBJECT) and (droid.order != DORDER_BUILD) ) { buildX = structure.x; buildY = structure.y; // if ! vtol defense already built... //find best defense we can build. count = 0; count2 = -1; while( count < 5) { if(isStructureAvailable(vtolDefStruct[count],me)) { count2 = count; } count = count + 1; } if(count2 != (-1) ) { boolResult = pickDroidStructLocation(droid, vtolDefStruct[count2], ref buildX, ref buildY, me, 1); if (boolResult == TRUE and (_numBuilders < _maxBuilders)) // build a vtol defense near the attacked struct... { orderDroidStatsLoc(droid, DORDER_BUILD,vtolDefStruct[count2],buildX,buildY); _numBuilders++; } } } droid = iterateGroup(buildGroup); } } } } } ///////////////////////////////////////////////////////////////////// event vtolEnabler(vtolEnablerTr) { if( skVtolEnableCheck(me) ) // check to see if we have vtol technologies. { setEventTrigger(vtolEnabler,inactive); // turn off this event. setEventTrigger(vtolStructs,vtolStructsTr); // activate other vtol functions.. setEventTrigger(buildVtols, buildVtolsTr); setEventTrigger(vtolAttack, vtolAttackTr); dbg("----I CAN USE VTOLS----", me); } } ///////////////////////////////////////////////////////////////////// // HouseKeeping function void shutDownAI() { bRunning = false; setEventTrigger(basedetails, inactive); setEventTrigger(buildDerrick, inactive); setEventTrigger(buildOilDefenseOrRetreat, inactive); setEventTrigger(incendry, inactive); setEventTrigger(buildPowerGenerators, inactive); setEventTrigger(buildBase, inactive); setEventTrigger(buildExpand,inactive); setEventTrigger(upgradeStructures,inactive); setEventTrigger(finishStructs, inactive); setEventTrigger(newfortify, inactive); setEventTrigger(droidBuiltAssign, inactive); setEventTrigger(droidBuilt, inactive); setEventTrigger(structBuilt,inactive); setEventTrigger(droidDestroyed,inactive); setEventTrigger(conDroids,inactive); setEventTrigger(repairDroids,inactive); setEventTrigger(factoryEvent, inactive); setEventTrigger(cyborgFactoryEvent, inactive); setEventTrigger(chooseScoutArea, inactive); setEventTrigger(expandScoutArea, inactive); setEventTrigger(scoutMain, inactive); setEventTrigger(newObjectReport, inactive); setEventTrigger(takeover, inactive); setEventTrigger(takeoverDefend, inactive); setEventTrigger(useLassat, inactive); setEventTrigger(findEnemy, inactive); setEventTrigger(attackStuff, inactive); setEventTrigger(defendWatch, inactive); setEventTrigger(defendReturn, inactive); setEventTrigger(doResearch, inactive); setEventTrigger(formAllianceEvent, inactive); setEventTrigger(breakAllianceEvent, inactive); setEventTrigger(formHumanAlliances, inactive); setEventTrigger(consolidateEvent, inactive); setEventTrigger(vtolStructs,inactive); setEventTrigger(buildVtols,inactive); setEventTrigger(vtolAttack,inactive); setEventTrigger(vtolDefend,inactive); setEventTrigger(vtolEnabler,inactive); setEventTrigger(beaconEv, inactive); setEventTrigger(multiMsgEv, inactive); setEventTrigger(manageAllyHelp, inactive); setEventTrigger(everySecEv, inactive); setEventTrigger(watchBaseThreat, inactive); setEventTrigger(manageDefendLocationEv, inactive); setEventTrigger(structureDestroyed,inactive); setEventTrigger(rebuildStructureEv,inactive); setEventTrigger(startLevel, inactive); setEventTrigger(arrived, inactive); setEventTrigger(checkResearch, inactive); } function void reassignAI() { bRunning = true; setEventTrigger(basedetails,basedetailsTr); setEventTrigger(buildDerrick,buildDerrickTr); setEventTrigger(buildOilDefenseOrRetreat,buildOilDefenseOrRetreatTr); setEventTrigger(incendry,incendryTr); setEventTrigger(buildPowerGenerators,buildPowerGeneratorsTr); setEventTrigger(buildBase,buildBaseTr ); setEventTrigger(buildExpand,buildExpandTr ); setEventTrigger(upgradeStructures,upgradeStructuresTr ); setEventTrigger(finishStructs,finishStructsTr ); setEventTrigger(newfortify,fortifyTr ); setEventTrigger(droidBuiltAssign,droidBuiltTr); setEventTrigger(droidBuilt,droidBuiltTr); setEventTrigger(droidDestroyed,droidDestroyedTr); setEventTrigger(conDroids,conDroidsTr); setEventTrigger(repairDroids,repairDroidsTr); setEventTrigger(factoryEvent,factoryEventTr); setEventTrigger(cyborgFactoryEvent,cyborgFactoryEventTr); setEventTrigger(chooseScoutArea,chooseScoutAreaTr); setEventTrigger(expandScoutArea,expandScoutAreaTr); setEventTrigger(scoutMain,scoutMainTr); setEventTrigger(newObjectReport,newObjectReportTr); setEventTrigger(takeover,takeoverTr); setEventTrigger(useLassat,useLassatTr); setEventTrigger(findEnemy,attackStuffTr); setEventTrigger(attackStuff,attackStuffTr); setEventTrigger(doAllOutAttack,allOutAttackTr); setEventTrigger(defendWatch,defendWatchTr); setEventTrigger(defendReturn,defendReturnTr); setEventTrigger(doResearch,doResearchTr); setEventTrigger(formAllianceEvent,formAllianceEventTr); setEventTrigger(breakAllianceEvent,breakAllianceEventTr); setEventTrigger(consolidateEvent,consolidateEventTr); setEventTrigger(vtolStructs,inactive); setEventTrigger(buildVtols,inactive); //setEventTrigger(vtolAttack,inactive); setEventTrigger(vtolAttack, vtolAttackTr); setEventTrigger(vtolDefend,vtolDefendTr); setEventTrigger(vtolEnabler,vtolEnablerTr); setEventTrigger(formHumanAlliances,humanAllianceTr); setEventTrigger(multiMsgEv, multiMsgTr); setEventTrigger(beaconEv, beaconTr); setEventTrigger(watchBaseThreat, watchBaseThreatTr); setEventTrigger(manageAllyHelp, manageAllyHelpTr); setEventTrigger(everySecEv, everySec); //setEventTrigger(manageDefendLocationEv, manageDefendLocationTr); setEventTrigger(structBuilt, structBuiltTr); setEventTrigger(structureDestroyed, structureDestroyedTr); setEventTrigger(rebuildStructureEv, rebuildStructureTr); setEventTrigger(startLevel, startLevelTr); setEventTrigger(arrived, reachedTr); setEventTrigger(checkResearch, checkResearchTr); } /* Returns true if we just received a beacon from a certain player */ function bool haveBeacon(int _player) { if((tBeacon[_player] > 0) and (not beaconTimeout(_player))) { return TRUE; //have beacon for this player } return FALSE; } /* See if last beacon was placed long ago */ function bool beaconTimeout(int _player) { if((tBeacon[_player] > 0) and ((tBeacon[_player] + BEACON_TIMEOUT) < (gameTime / 10))) //not too long ago { return TRUE; //this beacon is still 'fresh' } return FALSE; } /* Deal with beacons */ event beaconEv(beaconTr) { local int _players; local string _processedString; if(_DEBUG) debug(me & ") beaconEv: from " & sender); ASSERT(sender >= 0 and sender < MAX_PLAYERS, "beaconEv: sender out of bounds: " & sender , me); beaconX[sender] = x; beaconY[sender] = y; tBeacon[sender] = gameTime / 10; processCommand(message, sender, TRUE); } /* Deal with a chat message */ event multiMsgEv(multiMsgTr) { if(_DEBUG) debug(me & ") multiMsgEv: from " & sender); if(not allianceExistsBetween(me, sender)){ exit; } if(sender == me){ exit; } processCommand(message, sender, FALSE); } /* Process multiplayer messages */ function void processCommand(string _message, int _sender, bool _bBlipMessage) { local int _numMsgs,_curMsg,_addressedPlayers,_x,_y; local string _msg,_processedString; /* Extract semantic information */ _curMsg = 0; _numMsgs = processChatMsg(_message); debug(me & ") processCommand: '" & _message & "' from " & _sender); dbg("processCommand: '" & _message & "' from " & _sender, me); dbg("got " & _numMsgs & " commands", me); /* Process all messages */ while(_curMsg < _numMsgs) { if(chatCmdIsPlayerAddressed(_curMsg, me)) { dbg("i'm addressed", me); _msg = getChatCmdDescription(_curMsg); /* Someone requested help */ if(_msg == R_REQUEST_HELP) { dbg("'help' command", me); if(haveBeacon(_sender)) { dbg("got beacon", me); _x = beaconX[_sender]; _y = beaconY[_sender]; if(attemptToHelp(_sender, _x, _y)) { messagePlayer(ALL_ALLIES, m_affirmative(), MAX_PROBABILITY); } } else { /* Ask player to drop a beacon so we would know where to help */ _addressedPlayers = setBit(0, _sender, TRUE); messagePlayerAddressed(ALL_ALLIES, _addressedPlayers, R_REQUEST_BEACON); } } /* Someone requested a beacon from us - * did we request help and our beacon timed out?? */ else if(_msg == M_REQUEST_BEACON) { /* If our base is really in trouble drop a beacon for the requester again */ if(baseInTrouble()){ dropBeacon(getPlayerName(me), _sender, me, baseX, baseY, 0); } } else if(_msg == R_REPORT_SAFETY) { dbg("helping " & lastHelpPlayer, me); /* Make sure we were helping him */ if(helpingAlly() and (lastHelpPlayer == _sender)) { stopHelpingAlly(); messagePlayer(ALL_ALLIES, m_affirmative(), MAX_PROBABILITY); } else if(defendingOwnBase()) //if we are in trouble re-request help { requestHelp(baseX, baseY); } } else { dbg("unknown message", me); } } else { dbg("i'm not addressed", me); } _curMsg++; } } function bool attemptToHelp(int _playerToHelp, int _x, int _y) { local bool _bHelpingMyself; if(_playerToHelp < 0 or _playerToHelp >= MAX_PLAYERS){ return FALSE; } if(_x <= 0 or _y <= 0){ return FALSE; } dbg("attemptToHelp - checking", me); _bHelpingMyself = (_playerToHelp == me); /* Can only help allies and myself */ if(not friendlyPlayer(_playerToHelp)){ return FALSE; } if(_bHelpingMyself or !helpingAlly() or (lastHelpPlayer == _playerToHelp) ) //if not helping any other ally or it's me who needs help { dbg("not busy helping", me); if(haveHelpers() or _DEBUG) { dbg("got attackers", me); //if(allyBaseAtLoc(_playerToHelp, _x, _y)) //is he just trying to misuse us? //{ helpPlayer(_playerToHelp, _x, _y); return TRUE; //} //else //{ // dbg("ally needs no help", me); // messagePlayer(ALL_ALLIES, M_ANNOYED, MAX_PROBABILITY / 2); //} } else { messagePlayer(ALL_ALLIES, M_HELP_NO_UNITS, MAX_PROBABILITY); } } else if((lastHelpPlayer >= 0) and (lastHelpPlayer < MAX_PLAYERS)) { if(!_bHelpingMyself){ messagePlayer(ALL_ALLIES, "helping " & getPlayerName(lastHelpPlayer) & " already", MAX_PROBABILITY); } } return FALSE; } /* Start helping player */ function void helpPlayer(int _playerToHelp, int _helpX, int _helpY) { local int _tTravelTime; dbg("helping " & _playerToHelp, me); if(_DEBUG) debug(me & ") helpPlayer: '" & _playerToHelp); /* Move scoutes to attackers */ groupAddGroup(attackGroup, scoutGroup); //Calculate travel time, assume ~ 150 tiles in 4 minutes if(attackGroup.members == 0){ _tTravelTime = (int)((float)(distBetweenTwoPoints(baseX, baseY, _helpX, _helpY) / 128 ) * 1.7); }else{ _tTravelTime = (int)((float)(distBetweenTwoPoints(attackGroup.x, attackGroup.y, _helpX, _helpY) / 128 ) * 1.7); } tHelp = gameTime / 10; tHelpTimeout = (gameTime / 10) + BASE_DEFEND_DURATION + _tTravelTime; lastHelpPlayer = _playerToHelp; helpX = _helpX; helpY = _helpY; /* Scouts and attackers go to help */ defendLocation(_helpX, _helpY, tHelpTimeout, (_playerToHelp == me)); } /* Returns a random affirmative responce */ function string m_affirmative() { local int _rnd; _rnd = random(4); if(_rnd == 3) { return M_AFFIRMATIVE_ROGER; } return M_AFFIRMATIVE_OK; } /* See if there are any base structures belonging to ally at a certain location */ function bool allyBaseAtLoc(int _ally, int _x, int _y) { local int _structIndex; if(_x <= 0 or _y <= 0){ return FALSE; } if(_ally < 0 or _ally >= MAX_PLAYERS){ return FALSE; } _structIndex = 0; while(_structIndex < numBaseStruct) { if(numStructsByStatInRange(baseStruct[_structIndex], _x, _y, (7 * 128), me, _ally) > 0 ) { return TRUE; } _structIndex++; } return FALSE; } event manageAllyHelp(manageAllyHelpTr) { if(helpingAlly()) { if(canStopHelpingAlly()) { stopHelpingAlly(); } } } event everySecEv(everySec) { /* Check if we were helping long enough */ if(helpingAlly()) { if(helpAllyTimeout()) { stopHelpingAlly(); } } if(defendingLocation()) { if(defendLocationTimeout()) { stopDefendingLocation(); } } } /* Do we have any units we can send to help ally ? */ function bool haveHelpers() { if(attackGroup.members == 0){ return FALSE; } return TRUE; } function bool helpingAlly() { if(lastHelpPlayer >= 0){ return TRUE; } return FALSE; } /* Returns true if we were helping long enough */ function bool helpAllyTimeout() { if(tHelpTimeout < (gameTime / 10) ){ return TRUE; } return FALSE; } function bool canStopHelpingAlly() { if(lastHelpPlayer < 0) { ASSERT(FALSE, "canStopHelpingAlly: lastHelpPlayer < 0", me); return TRUE; } /* Were helping long enough or someone's backstabbing */ if(!friendlyPlayer(lastHelpPlayer)){ return TRUE; } /* Nothing to defend anymore */ //if(!allyBaseAtLoc(lastHelpPlayer, helpX, helpY)){ // return TRUE; //} return FALSE; } function void stopHelpingAlly() { dbg("stopped helping", me); tHelp = -1; tHelpTimeout = -1; lastHelpPlayer = -1; helpX = -1; helpY = -1; stopDefendingLocation(); } /* Send a multiplayer message to an ally */ function void messagePlayer(int _playerToMessage, string _message, int _probability) { local int _player; ASSERT(_playerToMessage >= -1 && _playerToMessage < MAX_PLAYERS, "messagePlayer: player out of bounds: " & _playerToMessage, me); // throw the dice if( random(MAX_PROBABILITY) >= _probability ){ return; } _player = 0; if(_playerToMessage == ALL_ALLIES) //everyone { while(_player < MAX_PLAYERS) { /* Send message (allies only)) */ if(allianceExistsBetween(me, _player)) { msg(_message, me, _player); } _player++; } } else //a certain player { /* Send message (allies only)) */ if(allianceExistsBetween(me, _playerToMessage)) { msg(_message, me, _playerToMessage); } } } function int numBitsSet(int _integer) { local int _position,_result; _position = 0; _result = 0; while(_position < 8) { if(getBit(_integer, _position)) { _result++; } _position++; } return _result; } /* Send a multiplayer message, addressing some player(s) */ function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message) { local int _player,_totalAddressed,_curAddressed; local string _adrMessage; _totalAddressed = numBitsSet(_playersToAddress); ASSERT(_totalAddressed > 0, "messagePlayerAddressed: no players addressed", me); _adrMessage = " "; _player = 0; _curAddressed = 0; while(_player < MAX_PLAYERS) { if(getBit(_playersToAddress, _player)) { _curAddressed++; _adrMessage = _adrMessage & getPlayerName(_player); //if(_totalAddressed == 1){ //one only // _adrMessage = getPlayerName(_player); //}else if(_totalAddressed > 1) { if(_curAddressed == _totalAddressed){ //end _adrMessage = _adrMessage & " and " & getPlayerName(_player); }else{ _adrMessage = _adrMessage & ", " & getPlayerName(_player); } } } _player++; } _message = _adrMessage & " " & _message; //Now send the message to all players addressed messagePlayer(_playerToMessage, _message, MAX_PROBABILITY); } /* Returns true if we can see our allies on the map */ function bool canSeeAllies() { local STRUCTURE _uplink; /* Can see allies when team mode is on */ if(multiPlayerAlliancesType == ALLIANCES_TEAMS) { return TRUE; } /* Can see whole map if we have uplink */ _uplink = getStructure(uplink, me); if(_uplink != NULLOBJECT) { /* Make sure finished building */ if(structureComplete(_uplink)) { return TRUE; } } return FALSE; } function bool defendingOwnBase() { if(helpingAlly() && lastHelpPlayer == me){ return TRUE; } return FALSE; } /* Call for help when our base is in danger */ event watchBaseThreat(watchBaseThreatTr) { /* See if we can stop defending */ if(defendingOwnBase()) { if(numEnemiesInBase(FALSE) == 0) { stopHelpingAlly(); //stop defending our own base /* Let allies know we don't need their help anymore */ messagePlayer(ALL_ALLIES, R_REPORT_SAFETY, MAX_PROBABILITY); exit; } } /* See if our base is in trouble and we need help */ if(baseInTrouble()) { if(!defendingOwnBase()) //make sure not already defending the base { if(_DEBUG) debug(me & ") watchBaseThreat: base in trouble"); dbg("watchBaseThreat: base in trouble", me); /* Bring our forces back if needed */ if(helpingAlly()) { stopHelpingAlly(); } /* Defend my own base */ helpPlayer(me, baseX, baseY); } /* Request help once in a while */ requestHelp(baseX, baseY); exit; } } function int numAlliesInBase(bool _bVtols) { local int _numAllies; _numAllies = numFriendlyWeapDroidsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, _bVtols); _numAllies = _numAllies + numFriendlyWeapStructsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, true) / 3; return _numAllies; } function int numEnemiesInBase(bool _bVtols) { local int _numEnemies; _numEnemies = numEnemyWeapDroidsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, _bVtols); _numEnemies = _numEnemies + numEnemyWeapStructsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, true) / 4; return _numEnemies; } /* Returns true if our base is in trouble */ function bool baseInTrouble() { local int _enemyForce,_friendlyForce; _friendlyForce = numAlliesInBase(FALSE); _enemyForce = numEnemiesInBase(FALSE); /* See if we are in trouble */ if((_enemyForce > 0) && (_enemyForce >= _friendlyForce)){ dbg("baseInTrouble: " & _enemyForce & " >= " & _friendlyForce, me); return TRUE; } return FALSE; } /* Request help from allies */ function void requestHelp(int _helpX, int _helpY) { /* Don't do this too frequently */ if(tLastHelpRequest + HELP_REQUEST_INTERVAL > (gameTime / 10) ){ return; } doRequestHelp(_helpX, _helpY); } function void doRequestHelp(int _helpX, int _helpY) { local int _ally; /* Remember when we requested help last time */ tLastHelpRequest = gameTime / 10; /* Drop beacon for all allies so they would know where to help */ _ally = 0; while(_ally < MAX_PLAYERS) { if(allianceExistsBetween(me, _ally)){ if(_DEBUG) debug(me & ") requestHelp: " & _ally); dropBeacon(getPlayerName(me), _ally, me, _helpX, _helpY, 0); } _ally++; } /* Now send message with help request */ messagePlayer(ALL_ALLIES, M_REQUEST_HELP, MAX_PROBABILITY); } function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, bool _bMove) { local int defendRadius; defendRadius = 15 * TILE; dbg("starting defending for " & _tDefendTimeout - (gameTime / 10) & " secs, with defend radius " & defendRadius, me); defendX = _defendX; defendY = _defendY; tDefendStart = gameTime / 10; /* Should already include travel time */ tDefendTimeout = _tDefendTimeout; /* See if we have to move or scout */ defendMoveType = DORDER_SCOUT; if(_bMove){ defendMoveType = DORDER_MOVE; } /* Send attackers */ if(attackGroup.members > 0) { if(distBetweenTwoPoints(attackGroup.x, attackGroup.y, _defendX, _defendY) > defendRadius) { orderGroupLoc(attackGroup, defendMoveType, _defendX, _defendY); } } setEventTrigger(manageDefendLocationEv, manageDefendLocationTr); } function void stopDefendingLocation() { dbg("stopped defending location", me); defendX = -1; defendY = -1; tDefendStart = -1; tDefendTimeout = -1; defendMoveType = -1; setEventTrigger(manageDefendLocationEv, inactive); orderGroupLoc(attackGroup, DORDER_SCOUT,baseX,baseY); } function bool defendingLocation() { if(defendX > 0 and defendY > 0){ return TRUE; } return FALSE; } event manageDefendLocationEv(inactive) { local int defendRadius; local DROID _droid; if (not defendingLocation()) { exit; } defendRadius = 15 * TILE; dbg("manageDefendLocationEv", me); ASSERT(defendMoveType == DORDER_MOVE || defendMoveType == DORDER_SCOUT, "manageDefendLocationEv: wrong move order:" & defendMoveType, me); ASSERT(defendX > 0 && defendY > 0, "manageDefendLocationEv: x/y coordinates:" & defendX & "/" & defendY, me); /* Collect attackers */ initIterateGroup(attackGroup); _droid = iterateGroup(attackGroup); while(_droid != NULLOBJECT) { if(distBetweenTwoPoints(_droid.x,_droid.y,defendX,defendY) > defendRadius) //too far from defend location { if(distBetweenTwoPoints(_droid.orderx,_droid.ordery,defendX,defendY) > defendRadius) //not already on its way to the defend location { orderDroidLoc(_droid, defendMoveType, defendX, defendY); } } _droid = iterateGroup(attackGroup); } } function bool defendLocationTimeout() { if(tDefendTimeout < (gameTime / 10) ){ return TRUE; } return FALSE; } /* Returns true if player in question is my ally or if it's me */ function bool friendlyPlayer(int _playerToCheck) { if(allianceExistsBetween(_playerToCheck, me) or (_playerToCheck == me)){ return TRUE; } return FALSE; } function bool insideBase(int _x, int _y) { if(_x < minx){ return FALSE; } if(_x > maxx){ return FALSE; } if(_y < miny){ return FALSE; } if(_y > maxy){ return FALSE; } return TRUE; } event watchMenu(everySec) { if(_DEBUG) { if(vtolGrAttackObj[0] == NULLOBJECT){ setDebugMenuEntry("0 - " & vtolAttackGr[0].members, 0); }else{ setDebugMenuEntry("0 " & vtolAttackGr[0].members & " - " & (vtolGrAttackObj[0].x / TILE) & "-" & (vtolGrAttackObj[0].y / TILE), 0); } if(vtolGrAttackObj[1] == NULLOBJECT){ setDebugMenuEntry("1 - " & vtolAttackGr[1].members, 1); }else{ setDebugMenuEntry("1 " & vtolAttackGr[1].members & " - " & (vtolGrAttackObj[1].x / TILE) & "-" & (vtolGrAttackObj[1].y / TILE), 1); } if(vtolGrAttackObj[2] == NULLOBJECT){ setDebugMenuEntry("2 - " & vtolAttackGr[2].members, 2); }else{ setDebugMenuEntry("2 " & vtolAttackGr[2].members & " - " & (vtolGrAttackObj[2].x / TILE) & "-" & (vtolGrAttackObj[2].y / TILE), 2); } if(vtolGrAttackObj[3] == NULLOBJECT){ setDebugMenuEntry("3 - " & vtolAttackGr[3].members, 3); }else{ setDebugMenuEntry("3 " & vtolAttackGr[3].members & " - " & (vtolGrAttackObj[3].x / TILE) & "-" & (vtolGrAttackObj[3].y / TILE), 3); } if(vtolGrAttackObj[4] == NULLOBJECT){ setDebugMenuEntry("4 - " & vtolAttackGr[4].members, 4); }else{ setDebugMenuEntry("4 " & vtolAttackGr[4].members & " - " & (vtolGrAttackObj[4].x / TILE) & "-" & (vtolGrAttackObj[4].y / TILE), 4); } if(vtolGrAttackObj[5] == NULLOBJECT){ setDebugMenuEntry("5 - " & vtolAttackGr[5].members, 5); }else{ setDebugMenuEntry("5 " & vtolAttackGr[5].members & " - " & (vtolGrAttackObj[5].x / TILE) & "-" & (vtolGrAttackObj[5].y / TILE), 5); } /* setDebugMenuEntry("total " & countRebuildStruct, 0); setDebugMenuEntry("x1=" & rebuildStructX[0], 1); setDebugMenuEntry("y1=" & rebuildStructY[0], 2); setDebugMenuEntry("x2=" & rebuildStructX[1], 3); setDebugMenuEntry("y2=" & rebuildStructY[1], 4); setDebugMenuEntry("x3=" & rebuildStructX[2], 5); setDebugMenuEntry("y3=" & rebuildStructY[2], 6); setDebugMenuEntry("x4=" & rebuildStructX[3], 7); setDebugMenuEntry("y4=" & rebuildStructY[3], 8);*/ } } //--------------------------------------------------------------- //Returns how many droids are already on the way to build the //same structure on the same spot (like helpbuild) //--------------------------------------------------------------- function int numBuildSameBuilding(STRUCTURESTAT _checkStat, int _x, int _y) { local int _numSameBuilding; local DROID _truck; _numSameBuilding = 0; initIterateGroup(buildGroup); _truck = iterateGroup(buildGroup); while(_truck != NULLOBJECT) { if((_truck.order == DORDER_BUILD) or (_truck.order == DORDER_HELPBUILD) or (_truck.order == DORDER_LINEBUILD)) { if((_checkStat == NULLSTRUCTURESTAT) or (_truck.stat == _checkStat)) //Same struct type { //Within some range if((_x < 0) or (distBetweenTwoPoints(_x, _y, _truck.orderx , _truck.ordery) <= TILE)) { _numSameBuilding++; } } } _truck = iterateGroup(buildGroup); } return _numSameBuilding; } // returns number of droids in a certain group with the same order function int numGroupSameOrder(GROUP _group, int _orderIndex) { local int _numDroids; local DROID _droid; _numDroids = 0; initIterateGroup(_group); _droid = iterateGroup(_group); while(_droid != NULLOBJECT) { if(_droid.order == _orderIndex) //right order type { _numDroids++; } _droid = iterateGroup(_group); } return _numDroids; } // Remember certain destroyed structures so we can rebuild them later event structureDestroyed(structureDestroyedTr) { local int _count; // add certain structures to the rebuild list _count = 0; while(_count < numRebuildStat[curTech]) { if(structure.stat == rebuildStat[curTech][_count]) { if(countRebuildStruct < MAX_REBUILD_STRUCT) { rebuildStructX[countRebuildStruct] = structure.x; rebuildStructY[countRebuildStruct] = structure.y; rebuildStructStat[countRebuildStruct] = structure.stat; countRebuildStruct++; dbg("remembered structure (" & countRebuildStruct & ") - " & structure.x & "/" & structure.y, me); exit; } } _count++; } } // Rebuild structures that were destroyed event rebuildStructureEv(rebuildStructureTr) { rebuildStructures(); } function void rebuildStructures() { local int _count,_threatRange,_x,_y; local DROID _truck; local STRUCTURESTAT _stat; _threatRange = (TILE * 8); _count = 0; while(_count < countRebuildStruct) { if(!threatInRange(me, rebuildStructX[_count], rebuildStructY[_count], _threatRange, FALSE)) { if(getTileStructure(_x / TILE, _y / TILE) == NULLOBJECT) { _stat = rebuildStructStat[_count]; _x = rebuildStructX[_count]; _y = rebuildStructY[_count]; if (isStructureAvailable(_stat, me)) { _truck = closestIdleTruck(_x, _y); if (_truck != NULLOBJECT) { if (numBuildSameBuilding(_stat, _x, _y) == 0) //make sure no one is building already { buildOnExactLocation(_truck, _x, _y, _stat); } } } } } _count++; } } function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat) { local int _newX,_newY; if(_truck == NULLOBJECT) { return; } _newX = _x; _newY = _y; if (pickDroidStructLocation(_truck, _stat, ref _newX, ref _newY, me, -1)) { dbg("trying to rebuild on (" & _newX & "/" & _newY & ")", me); if ((_x != _newX) or (_y != _newY)) { return; } orderDroidStatsLoc(_truck, DORDER_BUILD, _stat, _x, _y); //dbg("rebuilding structure after!! (" & _x & "/" & _y & ")", me); } } // Get idle truck closest to some location function DROID closestIdleTruck(int _x, int _y) { local DROID _closestTruck, _tempTruck; local int _closestDist, _tempDist; _closestTruck = NULLOBJECT; _closestDist = 99999; initIterateGroup(buildGroup); _tempTruck = iterateGroup(buildGroup); while(_tempTruck != NULLOBJECT) { if((_tempTruck.order == DORDER_NONE) or (_tempTruck.order == DORDER_RTB)) { _tempDist = distBetweenTwoPoints(_x, _y, _tempTruck.x, _tempTruck.y); if(_tempDist < _closestDist) { _closestDist = _tempDist; _closestTruck = _tempTruck; } } _tempTruck = iterateGroup(buildGroup); } return _closestTruck; } event consoleEv(consoleTr) { //turn on 'autogame' if(message == "autogame on" && (sender == me)) { if(debugModeEnabled()) { if(myResponsibility(me)) { if(not bRunning) //make sure current machine is responsible for this AI and it's not already active { console(getPlayerName(me) & " is active"); reassignAI(); setEventTrigger(startLevel, chainloadTr); } } } } //turn off 'autogames' if(message == "autogame off" && debugModeEnabled() && (sender == me)) { if(bRunning) //make sure this AI is active { console(getPlayerName(me) & " is deactivated"); shutDownAI(); } } if(message == "aidebug on") { console(getPlayerName(me) & " ai debug is on"); _DEBUG = TRUE; dbgMsgOn(me, _DEBUG); } else if(message == "aidebug off") { console(getPlayerName(me) & " ai debug is off"); _DEBUG = FALSE; dbgMsgOn(me, _DEBUG); } }
Texto modificado
Abrir archivo
///////////////////////////////////////////////////////////////////// // general ai for skirmish game ///////////////////////////////////////////////////////////////////// // Warzone2100, Pumpkin Studios, // alex lee.98/99. // ///////////////////////////////////////////////////////////////////// //Tile in world units #define TILE 128 #define NONE (-1) // These are final rules of the lexical parser #define R_REQUEST_HELP "help me" #define R_REQUEST_BEACON "drop a beacon" #define R_REPORT_SAFETY "i'm ok" #define R_REQUEST_ALLY "ally me" // These are our own messages - lexical parser should be able to handle them #define M_REQUEST_HELP "help me!!" #define M_REQUEST_BEACON "drop a beacon" #define M_AFFIRMATIVE_OK "ok" #define M_AFFIRMATIVE_ROGER "roger" #define M_ANNOYED "bug off" #define M_HELPERS_KILLED "that was all I had.." #define M_HELP_NO_UNITS "I don't have anything" #define MAX_PROBABILITY 100 // Base threat range in world units #define W_BASE_THREAT_RANGE ((17 + (mapWidth + mapHeight) / 2 / 35) * TILE) #define ALL_ALLIES -1 #define BASE_DEFEND_DURATION (3 * 60) // Delay before we repeat our request, in seconds #define HELP_REQUEST_INTERVAL (3 * 60) //in secs #define BEACON_TIMEOUT 30 #define MAX_DROIDS 150 //range for trucks to look for more oil #define MORE_OIL_RANGE (10 * TILE) //don't try to build on oil if there's threat within this range #define OIL_THREAT_RANGE (9 * TILE) #define MAX_TRUCKS 15 #define MIN_TRUCKS 12 //Enter power saving mode when lower than this #define LOW_POWER 250 //Target type values #define NO_TARGET_VALUE 0 #define DROID_TARGET_VALUE 1 #define OTHER_TARGET_VALUE 2 #define DEFENSE_TARGET_VALUE 3 #define RESEARCH_TARGET_VALUE 4 #define HQ_TARGET_VALUE 5 #define OIL_TARGET_VALUE 6 #define FACTORY_TARGET_VALUE 7 #define UNLIMITED (-1) #define AA_THREAT_RANGE (TILE * 12) #define MAX_DEFENDERS_RADIUS (TILE * 40) #define MAX_VTOL_DEFEND_RADIUS (TILE * 25) // AI will remember max this number of structures #define MAX_REBUILD_STRUCT 100 //Total number of technology branches #define TECHS 2 //How many best templates to choose from when deciding what template to build #define MAX_RANDOM_TEMPLATES 6 private int me; // player for this instance. public int tileExpand; // rate of exploration public int numScouts[TECHS],maxScouts[TECHS]; // aim for... public int numDefenders[TECHS],maxDefenders[TECHS]; public int numAttackers[TECHS],maxAttackers[TECHS]; public int numCyborgs[TECHS],maxCyborgs[TECHS]; public int branchDefault,branchVTOL,techCount[TECHS],maxVtolFacs[TECHS],maxIdleRes[TECHS], maxVTOLs[TECHS],numVtolTargets,vtolTargetWeight[10],numRebuildStat[TECHS]; public RESEARCHSTAT tech[TECHS][30]; //technology for different research branches public STRUCTURESTAT vtolTarget[10],rebuildStat[TECHS][2]; // structures private int baseX,baseY,minx,miny,maxx,maxy; public int numStructs,numIncendrys,numDefStructs,numExtraStructs[TECHS],numWallWeaps,numBaseStruct,numLightCyborgs,numFundamental; private STRUCTURESTAT structChoice[5]; public STRUCTURESTAT incendrys[10],structs[13],defStructs[26],extraStructs[TECHS][6],wallWeaps[11]; public STRUCTURESTAT sensorTower,wall,cornerWall,resLab,powGen,playerHQ,lassat,factory,derrick,cybFactory, vtolDefStruct[9],vtolPad,vtolFactory,uplink,baseStruct[8]; public STRUCTURESTAT powModule,facModule,resModule,vtolModule; public int extraStruct; // unit templates public int numTemplates[TECHS]; public TEMPLATE tmpl[TECHS][70]; private TEMPLATE tmplChoice[67]; public TEMPLATE cybTempl[7],superCyb[21],cybMechanic,cybEngineer,hovertruck; public TEMPLATE vtols[20]; public int numVtolTemplates; public TEMPLATE sense[8]; public int numSenseTemplates; public TEMPLATE constructor,repair[7]; public int numRepairUnits; public int numSensorUnits; public int numRepairTemplates; //defend private GROUP defendGroup; private bool defendbusy; private BASEOBJ defendObj; public RESEARCHSTAT nexusDefence; private RESEARCHSTAT research; //build private GROUP buildGroup; private int buildX,buildY,buildX2,buildY2; public FEATURESTAT oilRes; // scout private GROUP scoutGroup; private int scoutX,scoutY; private int scoutTLX,scoutTLY,scoutW,scoutH; // attack private GROUP attackGroup; private BASEOBJ attackObj,allOutAttack,vtolGrAttackObj[39]; // vtols private GROUP vtolDefendGr,vtolAttackGr[10]; // generic private STRUCTURE structure,structure2,rebuildObj[100]; private DROID droid; private FEATURE feature; private BASEOBJ baseobj,baseobj2; private int count,count2,result,result2,tempx,tempy; private bool boolResult,boolResult2; private bool powerSave,_DEBUG,bRunning; // Hopefully this will be at least as large as MAX_PLAYERS... Why can't I just use MAX_PLAYERS as the array size?! // P.S. And why can't I put a comment on the same line as a #define??!! Gah, who cares if the lua2 branch works, lets switch to it, anyway. #define MAX_PLAYERS_HACK 17 private int allianceTime[MAX_PLAYERS_HACK]; private int sender,x,y,beaconX[8],beaconY[8],tBeacon[8], tLastHelpRequest,lastHelpPlayer,tHelp,tHelpTimeout,helpX,helpY; private string message; private int defendX,defendY,__defendRadiusUnused,tDefendStart,tDefendTimeout, defendMoveType,baseRange,curTech,numVtolAttackGroups,numAttackVtols, numDefendVtols,rebuildStructX[MAX_REBUILD_STRUCT],rebuildStructY[MAX_REBUILD_STRUCT],countRebuildStruct; private STRUCTURESTAT rebuildStructStat[MAX_REBUILD_STRUCT]; private STRUCTURESTAT fundamentalBeingBuilt; private int order; // callback global ///////////////////////////////////////////////////////////////////// // triggers. #region triggers trigger reachedTr (CALL_DROID_REACH_LOCATION, me, ref droid, ref order); trigger buildExpandTr (every, 300); trigger fortifyTr (every, 400); trigger upgradeStructuresTr (every, 50); trigger conDroidsTr (every, 200); // was 1400 trigger repairDroidsTr (every, 400); trigger sensorDroidsTr (every, 400); trigger basedetailsTr (every, 600 ); trigger buildDerrickTr (every, 80 ); trigger buildOilDefenseOrRetreatTr (every, 200 ); trigger incendryTr (every, 120 ); trigger buildPowerGeneratorsTr (every, 80 ); trigger buildBaseTr (every, 150 ); trigger finishStructsTr (every, 210); trigger droidBuiltTr (CALL_NEWDROID,me, ref droid,ref structure); trigger structBuiltTr (CALL_STRUCTBUILT, me, ref droid, ref structure); trigger droidDestroyedTr (CALL_DROID_DESTROYED, me, ref droid); trigger structureDestroyedTr (CALL_STRUCT_DESTROYED, me, ref structure); trigger rebuildStructureTr (every, 50); trigger consolidateEventTr (every, 3100); trigger factoryEventTr (every, 90 ); trigger cyborgFactoryEventTr (every, 90 ); trigger chooseScoutAreaTr (every, 200 ); trigger expandScoutAreaTr (every, 600 ); trigger scoutMainTr (every, 150 ); trigger newObjectReportTr (CALL_OBJ_SEEN, me, ref baseobj, ref baseobj2); trigger attackStuffTr (every, 200 ); trigger allOutAttackTr (every, 2000); trigger defendWatchTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj); trigger defendReturnTr (every, 100000 ); trigger doResearchTr (CALL_RESEARCHCOMPLETED, ref research, ref structure, me); trigger vtolDefendTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj); trigger vtolStructsTr (every, 600); trigger buildVtolsTr (every, 180); trigger vtolAttackTr (every, 10); trigger vtolEnablerTr (every, 700); trigger takeoverTr (CALL_UNITTAKEOVER, ref droid); trigger useLassatTr (every, 3000); trigger reassignTr (CALL_PLAYERLEFT,ref count); trigger formAllianceEventTr (every,170); trigger breakAllianceEventTr (every,3000); trigger difficultyModifierTr (every,600); trigger humanAllianceTr (CALL_ALLIANCEOFFER,ref count, ref count2); trigger multiMsgTr (CALL_AI_MSG, me, ref sender, ref message); trigger beaconTr (CALL_BEACON, me, ref sender, ref x, ref y, ref message); trigger consoleTr (CALL_CONSOLE, ref sender, ref message); trigger watchBaseThreatTr (every, 120); trigger manageAllyHelpTr (every, 80); trigger everySec (every, 10); trigger manageDefendLocationTr (every, 70); trigger startLevelTr (CALL_START_NEXT_LEVEL); trigger chainloadTr (wait, 1); trigger slowloadTr (wait, 13); trigger checkResearchTr (every, 50); /* Events */ event conDroids; event multiMsgEv; event beaconEv; event watchBaseThreat; event manageAllyHelp; event everySecEv; event manageDefendLocationEv; event structureDestroyed; event rebuildStructureEv; event doResearch; event buildDerrick; /* Function prototypes */ function bool haveBeacon(int _player); function bool beaconTimeout(int _player); function void processCommand(string _message, int _sender, bool _bBlipMessage); function bool haveHelpers(); function bool attemptToHelp(int _playerToHelp, int _x, int _y); function void helpPlayer(int _playerToHelp, int _helpX, int _helpY); function bool canStopHelpingAlly(); function void stopHelpingAlly(); function bool helpingAlly(); function bool helpAllyTimeout(); function void requestHelp(int _helpX, int _helpY); function void doRequestHelp(int _helpX, int _helpY); function bool allyBaseAtLoc(int _ally, int _x, int _y); function void messagePlayer(int _playerToMessage, string _message, int _probability); function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message); function bool canSeeAllies(); function bool baseInTrouble(); function string m_affirmative(); function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, bool _bMove); function void stopDefendingLocation(); function bool defendingLocation(); function bool defendLocationTimeout(); function bool friendlyPlayer(int _playerToCheck); function void factoryBuildDroid(STRUCTURE _factory); function void cybFactorBuildCyborg(STRUCTURE _factory); function void vtolFactoryBuildVtol(STRUCTURE _factory); function bool insideBase(int _x, int _y); function int numAlliesInBase(bool _bVtols); function int numEnemiesInBase(bool _bVtols); function bool defendingOwnBase(); function int targetTypeValue(BASEOBJ _target); function int numBitsSet(int _integer); function int findResearch(int _searchStart, int _techTree); function bool upgradeFactory(DROID _truck, int _maxBuilders); function bool upgradeVtolFactory(DROID _truck, int _maxBuilders); function bool upgradeResearch(DROID _truck, int _maxBuilders); function bool upgradePowGen(DROID _truck, int _maxBuilders); function void buildRearmPads(); function int numEnemyAAInRange(int _x, int _y, int _range); function BASEOBJ chooseVtolTarget(bool bExclusiveTarget); function int getVtolTargetWeight(BASEOBJ _target); function bool vtolTargetAssigned(BASEOBJ _target); function int numBuildSameBuilding(STRUCTURESTAT _checkStat, int _x, int _y); function int totalVtols(); function bool needTank(); function void setTechBranch(int _tech); function DROID closestIdleTruck(int _x, int _y); function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat); function void rebuildStructures(); function BASEOBJ chooseVtolDefenceTarget(int _x, int _y, int _range, bool bExclusiveTarget); function int numGroupSameOrder(GROUP _group, int _orderIndex); function void rearrangeAttackVtols(); function int numStructBusyByType(STRUCTURESTAT _busyStructType); function bool aiResponsibleForPlayer(int _player); function void reassignAI(); function void shutDownAI(); function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly); function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly); #endregion triggers ///////////////////////////////////////////////////////////////////// // HouseKeeping event initialisedEvent(CALL_GAMEINIT) { local int player; // initialise me = getPlayer("Nexus"); _DEBUG = FALSE; dbgMsgOn(me, _DEBUG); extraStruct = 0; numRepairUnits = 0; numSensorUnits = 0; allOutAttack = NULLOBJECT; tLastHelpRequest = -1; //when we requested help for the last time lastHelpPlayer = -1; //we are not currently helping anyone tHelp = -1; //when we started helping last time tHelpTimeout = -1; //time when help times out helpX = -1; helpY = -1; defendX = -1; defendY = -1; tDefendStart = -1; tDefendTimeout = -1; defendMoveType = -1; //move or scout baseRange = 4 * TILE; // set current research branch setTechBranch(-1); numVtolAttackGroups = 10; numAttackVtols = 10; //num vtols in an attack group numDefendVtols = 5; //num vtols in an attack group // setup build group - all initial droids are in buildgroup! groupAddArea(buildGroup, me, 0, 0, (mapWidth*128), (mapHeight*128)); // note where our base is. getPlayerStartPosition(me, ref baseX, ref baseY); // defence. defendbusy = FALSE; // setup scouts structure = getStructure(factory, me); if(structure != NULLOBJECT) { scoutTLX = structure.x; scoutTLY = structure.y; } else { scoutTLX = baseX; scoutTLY = baseY; } scoutW = 256; scoutH = 256; scoutX = scoutTLX; scoutY = scoutTLY; // clear the alliance array... player = 0; while (player != MAX_PLAYERS) { allianceTime[player] = 0; player = player + 1; } fundamentalBeingBuilt = derrick; // to avoid ever being null if(aiResponsibleForPlayer(me)) { bRunning = true; } else { bRunning = false; shutDownAI(); } } // check whether we have at least one structure of that type function bool haveStructure(STRUCTURESTAT type) { return getStructure(type, me) != NULLOBJECT; } // check if we are getting any income function bool havePowerSource() { // we don't check buildings being finished here return haveStructure(powGen) and haveStructure(derrick); } // I am not sure why we need this hack, but the AI can still end up not researching anything at times event checkResearch(checkResearchTr) { setEventTrigger(doResearch, chainloadTr); } function void dbgPlr(string message) { setEventTrigger(doResearch, chainloadTr); if (me == selectedPlayer) { console(message); } } function void dbgObj(DROID obj, string message) { if (obj.selected) { console(message); } } function bool conCanHelp(DROID mydroid, int bx, int by) { return (mydroid.order != DORDER_HELPBUILD and mydroid.order != DORDER_BUILD and mydroid.order != DORDER_LINEBUILD and droidCanReach(mydroid, bx, by)); } // Build something in main base, grab trucks to do it within tiles range function bool grabTrucksAndBuild(int range, STRUCTURESTAT bstats, int maxBlockingTiles) { local DROID mydroid, closestDroid; local int closestDist, currDist, numHelpDroids, tilerange, bx, by; initIterateGroup(buildGroup); // find idle droids in build group. mydroid = iterateGroup(buildGroup); closestDist = 99999; closestDroid = NULLOBJECT; numHelpDroids = 0; tilerange = range * TILE; while (mydroid != NULLOBJECT) { if (conCanHelp(mydroid, baseX, baseY)) { bx = baseX; by = baseY; if (pickDroidStructLocation(mydroid, bstats, ref bx, ref by, me, maxBlockingTiles)) { currDist = distBetweenTwoPoints(bx, by, mydroid.x, mydroid.y); if (currDist < tilerange) { orderDroidStatsLoc(mydroid, DORDER_BUILD, bstats, bx, by); // close, so help build it numHelpDroids = numHelpDroids + 1; } else if (currDist < closestDist) { closestDroid = mydroid; // record this droid as being closest so far closestDist = currDist; } } } mydroid = iterateGroup(buildGroup); } if (numHelpDroids == 0 and closestDroid != NULLOBJECT) // found none within help radius, so force someone to go long distance traveling { orderDroidStatsLoc(closestDroid, DORDER_BUILD, bstats, bx, by); // you, book a plane ticket and go! return true; } return (numHelpDroids > 0); } event arrived(reachedTr) { local bool found; local STRUCTURESTAT myChoice; if (droid.droidType == DROID_CONSTRUCT or droid.droidType == DROID_CYBORG_CONSTRUCT) { dbgObj(droid, "Failed to build where we should - attempt to screw up enemy oil derrick"); // Check if at oil well, and it was taken by enemy structure = structureBuiltInRange(derrick, droid.x, droid.y, (5 * 128), -1); if (structure != NULLOBJECT) { if (not friendlyPlayer(structure.player) and droid.health == 100) { // Ok, at enemy derrick, and nobody has hurt us yet. Start being nasty. count = 0; found = false; // find simplest/cheapest one available to build while (count < numDefStructs and not found) { if (isStructureAvailable(defStructs[count], me)) { found = true; } else { count++; } } if (found) { buildX = droid.x; buildY = droid.y; if (pickDroidStructLocation(droid, defStructs[count], ref buildX, ref buildY, me, -1)) { orderDroidStatsLoc(droid, DORDER_BUILD, defStructs[count], buildX, buildY); } else { dbgObj(droid, "Wanted to be nasty, but found nowhere to build defense"); orderDroid(droid, DORDER_RTB); // nothing more to do here. } } else { dbgObj(droid, "Wanted to be nasty, but had nothing nasty to build - returning to base"); orderDroid(droid, DORDER_RTB); // oh, well. nothing more to do here. } exit; } else if (droid.health < 100 and !insideBase(droid.x, droid.y)) { orderDroid(droid, DORDER_RTR); // bolt back to base now! exit; } } } } event buildFundamentals(inactive) { count = 0; while (count < numFundamental) { // check that struct. structure = getStructure(structs[count], me); if (structure == NULLOBJECT) // if missing build it. { if (isStructureAvailable(structs[count], me)) { if (grabTrucksAndBuild(12, structs[count], 0)) { exit; // no need to check more } } } count = count + 1; } fundamentalBeingBuilt = derrick; setEventTrigger(buildFundamentals, inactive); } event startLevel(startLevelTr) { setEventTrigger(buildFundamentals, slowloadTr); setEventTrigger(conDroids, chainloadTr); setEventTrigger(doResearch, chainloadTr); setEventTrigger(buildDerrick, slowloadTr); setEventTrigger(startLevel, inactive); } // decide what technology branch we will use function void setTechBranch(int _tech) { local float _y2,_y1,_x2,_x1,_a,_y,_m,_rnd,_mapSize; _mapSize = (float)((mapWidth + mapHeight) / 2); if(_tech != -1) { curTech = _tech; } else { //probability to choose vtol branch for map size 90 = 0; probability for map size 200 = 45 //build a linear function: y = ((y2 - y1) / (x2 - x1)) * x + a depending on two values given (short: y = mx+a) _x1 = 90.0; _y1 = 0.0; _x2 = 200.0; _y2 = 45.0; _m = ((_y2 - _y1) / (_x2 - _x1)); _a = -(_m * _x1); //calculate probability for the current map _y = _m * _mapSize + _a; dbg("_m = " & _m & ", a = " & _a, me); _rnd = (float)random(100); if(_rnd < _y) { curTech = branchVTOL; dbg("going air (" & _y & "/" & _rnd & ")", me); } else { curTech = branchDefault; dbg("going land (" & _y & "/" & _rnd & ")", me); } } } /* returns TRUE if AI is responsible for the _player */ function bool aiResponsibleForPlayer(int _player) { if(not _DEBUG and ((_player == selectedPlayer) or not myResponsibility(_player))) { return FALSE; } return TRUE; } ///////////////////////////////////////////////////////////////////// // keep details about the size and postion of the ai players base event basedetails(basedetailsTr) { // clear old extremities. maxy = 0; maxx = 0; miny = (mapHeight*128); minx = (mapWidth*128); baseRange = 4 * TILE; // now find the extremities of our vital structures. count = 0; while(count < numBaseStruct) { initEnumStruct(FALSE,baseStruct[count],me,me); structure= enumStruct(); while(structure != NULLOBJECT) { if(structure.x < minx) { minx = structure.x; } if(structure.x > maxx) { maxx = structure.x; } if(structure.y < miny) { miny = structure.y; } if(structure.y > maxy) { maxy = structure.y; } result = distBetweenTwoPoints(baseX, baseY, structure.x, structure.y); if(result > baseRange){ baseRange = result; } structure= enumStruct(); } count = count + 1; } result = 3 * 128; minx = minx - result; maxx = maxx + result; miny = miny - result; maxy = maxy + result; baseRange = baseRange + (4 * 128); } ///////////////////////////////////////////////////////////////////// // structure building rules // build derricks on oil. event buildDerrick(buildDerrickTr) { local bool foundOne, _same; local FEATURE _oil, _closestOil; local int _bestDist, _newDist; local DROID _search; // what if we can't waste power on building derricks because we don't have a gen yet? if (playerPower(me) < 300 and haveStructure(derrick) and not haveStructure(powGen)) { setEventTrigger(buildDerrick, slowloadTr); exit; } _bestDist = 99999; _closestOil = NULLOBJECT; foundOne = false; initIterateGroup(buildGroup); // find all units in build group droid = iterateGroup(buildGroup); while (droid != NULLOBJECT && !foundOne) { if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD) { foundOne = true; } else { droid = iterateGroup(buildGroup); } } if (droid != NULLOBJECT) { initGetFeature(oilRes, -1, me); _oil = getFeatureB(me); while (_oil != NULLOBJECT) { _newDist = distBetweenTwoPoints(droid.x, droid.y, _oil.x, _oil.y); _same = false; if (_newDist < _bestDist and droidCanReach(droid, _oil.x, _oil.y)) // this one is closer { if (!threatInRange(me, _oil.x, _oil.y, OIL_THREAT_RANGE, FALSE)) { initIterateGroup(buildGroup); // find all units in build group. _search = iterateGroup(buildGroup); foundOne = false; while (_search != NULLOBJECT && !foundOne) { if (_search.orderx == _oil.x and _search.ordery == _oil.y and _search != droid) { _same = true; foundOne = true; } _search = iterateGroup(buildGroup); } if (!_same) // do not go to same spot as another droid { _bestDist = _newDist; _closestOil = _oil; } } } _oil = getFeatureB(me); } if (_closestOil != NULLOBJECT) { orderDroidStatsLoc(droid, DORDER_BUILD, derrick, _closestOil.x, _closestOil.y); // build a derick if (idleGroup(buildGroup) > 0) { setEventTrigger(buildDerrick, slowloadTr); // do it again for next droid exit; } } } setEventTrigger(buildDerrick, buildDerrickTr); } ///////////////////////////////////////////////////////////////////// // if idle and derrick in range and no defense then build defense, else ret to base . event buildOilDefenseOrRetreat(buildOilDefenseOrRetreatTr) { local int _numBuilders,_maxBuilders; _maxBuilders = 1; // check idle. initIterateGroup(buildGroup); // find idle droids in build group. droid = iterateGroup(buildGroup); while(droid != NULLOBJECT) { if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD) { // if in range of a derrick structure = structureBuiltInRange(derrick, droid.x, droid.y, (5*128), me); // if inside base limits then presume ok.. if( structure != NULLOBJECT) { if((structure.x > minx) and (structure.y > miny) and (structure.x < maxx) and (structure.y <maxy)) { structure = NULLOBJECT; } } if(structure != NULLOBJECT) { buildX = structure.x; buildY = structure.y; // not many defenses nearby if(numFriendlyWeapStructsInRange(me, buildX, buildY, (3*128), FALSE) < 2) { count = numDefStructs - 1; //pick a struct to build.. count2 = 0; while( (count2 < 5) and (count >= 0) ) { if( isStructureAvailable(defStructs[count],me)) { structChoice[count2] = defStructs[count]; count2 = count2 + 1; } count = count - 1; } count =0; if(count2 > 0) { count = random(count2); //count = choice! // pick a location boolResult = pickDroidStructLocation(droid, structChoice[count], ref buildX, ref buildY, me, -1); _numBuilders = numBuildSameBuilding(NULLSTRUCTURESTAT, buildX, buildY); if((boolResult == TRUE) and (_numBuilders < _maxBuilders) and droidCanReach(droid, buildX, buildY)) { // build it. orderDroidStatsLoc(droid, DORDER_BUILD,structChoice[count], buildX,buildY); _numBuilders++; } } } else { structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me); if(structure == NULLOBJECT) { if(!insideBase(droid.x, droid.y)) { orderDroid(droid,DORDER_RTB); // return to base; } } } } else { structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me); if(structure == NULLOBJECT) { if(!insideBase(droid.x, droid.y)) { orderDroid(droid,DORDER_RTB); // return to base; } } } } droid = iterateGroup(buildGroup); } } ///////////////////////////////////////////////////////////////////// //mortar etc.. rules. build sensor towers and emplacements. event incendry(incendryTr) { if (not isStructureAvailable(sensorTower, me)) { exit; } initEnumStruct(FALSE,sensorTower,me,me); count = 0; structure = enumStruct(); while(structure != NULLOBJECT) { count = count + 1; structure = enumStruct(); } if (count < (gameTime/600)) // every 7 mins { // if not found build a sensor tower. // find a place to build. buildX = 0; buildY = 0; initEnumStruct(FALSE,derrick,me,me); structure= enumStruct(); while(structure != NULLOBJECT) { count = 0; result = 0; while(count < numDefStructs) { structure2 = structureBuiltInRange(defStructs[count], structure.x, structure.y,(4*128), me); if(structure2 != NULLOBJECT) { result = result + 1; } count = count + 1; } // check for sensor nearby, structure2 = structureBuiltInRange(sensorTower, structure.x, structure.y,(5*128), me); if(structure2 != NULLOBJECT) { result = 4; } if(result < 3) { buildX = structure.x; buildY = structure.y; structure = NULLOBJECT; } else { structure = enumStruct(); } } if(buildX != 0) { boolResult = pickStructLocation(sensorTower, ref buildX, ref buildY,me); // pick spot. if(boolResult == TRUE) { // find unit initIterateGroup(buildGroup); droid = iterateGroup(buildGroup); while(droid != NULLOBJECT) { if ((droid.order == DORDER_NONE or droid.order == DORDER_RTB) and droidCanReach(droid, buildX, buildY)) { orderDroidStatsLoc(droid, DORDER_BUILD, sensorTower, buildX, buildY); droid = NULLOBJECT; } else { droid = iterateGroup(buildGroup); } } } } } else { // find a sensor tower with least incencdry structs around it.. buildX = 0; buildY = 0; initEnumStruct(FALSE,sensorTower,me,me); structure= enumStruct(); count = 999; while(structure != NULLOBJECT) { // count incendrys near this tower. result = 0; count2 = 0; while(count2 < numIncendrys) { structure2 = structureBuiltInRange(incendrys[count2], structure.x, structure.y,(4*128), me); if(structure2 != NULLOBJECT) { result = result + 1; } count2 = count2 + 1; } if((result < 6) and (result < count)) // lowest found yet. only sites with <6 too. { buildX = structure.x; buildY = structure.y; count = result; } structure = enumStruct(); } if(buildX != 0) { // choose a device count = numIncendrys - 1; result = 99; while(count >= 0 ) { if(isStructureAvailable(incendrys[count],me)) { result = count; count = -1; } else { count = count - 1; } } // find a unit and build an incendry device. if(result != 99) { boolResult = pickStructLocation(incendrys[result], ref buildX, ref buildY,me); // pick spot. if(boolResult == TRUE) { initIterateGroup(buildGroup); droid = iterateGroup(buildGroup); boolResult = (numBuildSameBuilding(incendrys[result], buildX, buildY) > 0); //anyone building there already? while(droid != NULLOBJECT and (not boolResult)) { if ((droid.order == DORDER_NONE or droid.order == DORDER_RTB) and droidCanReach(droid, buildX, buildY)) { orderDroidStatsLoc(droid, DORDER_BUILD,incendrys[result], buildX,buildY); boolResult = TRUE; //only 1 truck } droid = iterateGroup(buildGroup); } } } } } } ///////////////////////////////////////////////////////////////////// // build a power gen for every 4 derricks. VITAL! event buildPowerGenerators(buildPowerGeneratorsTr) { if (!isStructureAvailable(powGen, me)) { exit; } initEnumStruct(FALSE,derrick,me,me); // count = numderricks structure= enumStruct(); count = 0; while(structure != NULLOBJECT) { count = count + 1; structure= enumStruct(); } initEnumStruct(FALSE,powGen,me,me); // count2 = numpowgens structure= enumStruct(); count2 = 0; while(structure != NULLOBJECT) { count2 = count2 + 1; structure= enumStruct(); } if( (count2 * 4) < count ) // if we need powergen { initIterateGroup(buildGroup); droid = iterateGroup(buildGroup); while(droid != NULLOBJECT) { if (droid.order != DORDER_HELPBUILD and droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD) { buildX = baseX; // try build powergen. buildY = baseY; if (pickDroidStructLocation(droid, powGen, ref buildX, ref buildY, me, 1)) { orderDroidStatsLoc(droid, DORDER_BUILD, powGen, buildX,buildY); } } droid = iterateGroup(buildGroup); } } } ///////////////////////////////////////////////////////////////////// // ensure we have everything in the vital structs list. event buildBase(buildBaseTr) { if (idleGroup(buildGroup) >= (buildGroup.members / 2)) { count = 0; while(count < numStructs) { // check that struct. structure = getStructure(structs[count],me); if(structure == NULLOBJECT) // if missing build it. { if(isStructureAvailable(structs[count],me)) { if (grabTrucksAndBuild(10, structs[count], 0)) { exit; // done here } } } count = count + 1; } } } ///////////////////////////////////////////////////////////////////// // build other stuff, grow the base slowly... event buildExpand( buildExpandTr ) { if (playerPower(me) < LOW_POWER) { exit; // do not expand base with low power } if(extraStruct == numExtraStructs[curTech]) // loop round { extraStruct = 0; } if(isStructureAvailable(extraStructs[curTech][extraStruct],me)) { if (not grabTrucksAndBuild(10, extraStructs[curTech][extraStruct], 0)) { dbg("Failed to build expand", me); } } extraStruct = extraStruct + 1; } ///////////////////////////////////////////////////////////////////// // Structure (fac/res/pow) upgrades event upgradeStructures(upgradeStructuresTr ) { if (not havePowerSource()) { exit; } initIterateGroup(buildGroup); // find idle droids in build group. droid = iterateGroup(buildGroup); while(droid != NULLOBJECT) { if ((droid.order != DORDER_BUILD) and (droid.order != DORDER_LINEBUILD)) { boolResult = FALSE; if(curTech == branchDefault) { //powergen boolResult = upgradePowGen(droid, 4); //factory if(droid.order != DORDER_BUILD){ boolResult = upgradeFactory(droid, 4); } //research if(droid.order != DORDER_BUILD){ boolResult = upgradeResearch(droid, 4); } //vtol Factory if(droid.order != DORDER_BUILD){ boolResult = upgradeVtolFactory(droid, 4); } } else if(curTech == branchVTOL) { //powergen boolResult = upgradePowGen(droid, 4); //vtol Factory if(droid.order != DORDER_BUILD){ boolResult = upgradeVtolFactory(droid, 4); } //factory if(droid.order != DORDER_BUILD){ boolResult = upgradeFactory(droid, 4); } //research if(droid.order != DORDER_BUILD){ boolResult = upgradeResearch(droid, 4); } } } droid = iterateGroup(buildGroup); } } function bool upgradeFactory(DROID _truck, int _maxBuilders) { local STRUCTURE _factory; initEnumStruct(FALSE,factory,me,me); _factory = enumStruct(); while(_factory != NULLOBJECT) { // if upgrade is available && struct is not upgraded if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(_factory) < 2 ) and droidCanReach(_truck, _factory.x, _factory.y)) { if((numBuildSameBuilding(facModule, _factory.x, _factory.y) + numBuildSameBuilding(vtolFactory, _factory.x, _factory.y)) < _maxBuilders) { orderDroidStatsLoc(_truck, DORDER_BUILD,facModule, _factory.x,_factory.y); // upgrade it. return TRUE; } } _factory = enumStruct(); } return FALSE; } function bool upgradeVtolFactory(DROID _truck, int _maxBuilders) { local STRUCTURE _factory; initEnumStruct(FALSE,vtolFactory,me,me); _factory = enumStruct(); while(_factory != NULLOBJECT) { // if upgrade is available && struct is not upgraded if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(_factory) < 2 ) and droidCanReach(_truck, _factory.x, _factory.y)) { if((numBuildSameBuilding(facModule, _factory.x, _factory.y) + numBuildSameBuilding(factory, _factory.x, _factory.y)) < _maxBuilders) { orderDroidStatsLoc(_truck, DORDER_BUILD,facModule, _factory.x,_factory.y); // upgrade it. return TRUE; } } _factory = enumStruct(); } return FALSE; } function bool upgradeResearch(DROID _truck, int _maxBuilders) { local STRUCTURE _resFac; initEnumStruct(FALSE,resLab,me,me); _resFac = enumStruct(); while(_resFac != NULLOBJECT) { // if upgrade is available && struct is not upgraded if( isStructureAvailable(resModule,me) and (not testStructureModule(me, _resFac, 0)) and droidCanReach(_truck, _resFac.x, _resFac.y)) { if((numBuildSameBuilding(resModule, _resFac.x, _resFac.y) + numBuildSameBuilding(resLab, _resFac.x, _resFac.y)) < _maxBuilders) { orderDroidStatsLoc(_truck, DORDER_BUILD,resModule, _resFac.x,_resFac.y); // upgrade it. return TRUE; } } _resFac = enumStruct(); } return FALSE; } function bool upgradePowGen(DROID _truck, int _maxBuilders) { local STRUCTURE _powGen; initEnumStruct(FALSE,powGen,me,me); _powGen = enumStruct(); while(_powGen != NULLOBJECT) { // if upgrade is available && struct is not upgraded if( isStructureAvailable(powModule,me) and (not testStructureModule(me, _powGen, 0)) and droidCanReach(_truck, _powGen.x, _powGen.y)) { if((numBuildSameBuilding(powModule, _powGen.x,_powGen.y) + numBuildSameBuilding(powGen, _powGen.x,_powGen.y)) < _maxBuilders) { orderDroidStatsLoc(_truck, DORDER_BUILD, powModule, _powGen.x,_powGen.y); // upgrade it. return TRUE; } } _powGen = enumStruct(); } return FALSE; } ///////////////////////////////////////////////////////////////////// // Finish Building Part Built Structures event finishStructs(finishStructsTr) { initEnumStruct(TRUE,factory,me,me); structure= enumStruct(); while(structure != NULLOBJECT) { if(not structureComplete(structure)) { initIterateGroup(buildGroup); // find idle droids in build group. droid = iterateGroup(buildGroup); while(droid != NULLOBJECT) { if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droidCanReach(droid, structure.x, structure.y) and distBetweenTwoPoints(droid.x, droid.y, structure.x, structure.y) < 20 * TILE) { orderDroidObj(droid,DORDER_HELPBUILD,structure); } droid = iterateGroup(buildGroup); } } structure= enumStruct(); } } ///////////////////////////////////////////////////////////////////// // fortify base by builiding defensive structs on the edge of the base. // rewrote fortify to use scrSkDefenseLocation(baseX,baseY,me); event newfortify(fortifyTr) { local int _numBuilders,_maxBuilders; _maxBuilders = 1; if(numGroupSameOrder(buildGroup, DORDER_LINEBUILD) >= _maxBuilders) { exit; } boolResult = FALSE; initIterateGroup(buildGroup); // find idle an idle veh.in build group. droid = iterateGroup(buildGroup); while((boolResult == FALSE) and (droid != NULLOBJECT)) { if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD) { boolResult = TRUE; // dont do this again! tempx = baseX; tempy = baseY; // choose a suitable turret. count = numWallWeaps - 1; count2 = 0; while( (count2 < 3) and (count >= 0) ) { if( isStructureAvailable(wallWeaps[count],me)) { structChoice[count2] = wallWeaps[count]; count2 = count2 + 1; } count = count - 1; } count =0; if((count2 > 0) and (_numBuilders < _maxBuilders)) { count = random(count2); skDefenseLocationB(ref tempx,ref tempy,wall,structChoice[count],droid,me); _numBuilders++; } } droid = iterateGroup(buildGroup); } } ///////////////////////////////////////////////////////////////////// // droid building rules ///////////////////////////////////////////////////////////////////// // deal with a droid being built event droidBuiltAssign(droidBuiltTr) { if(isVtol(droid)) { if(vtolDefendGr.members < numDefendVtols) { groupAddDroid(vtolDefendGr, droid); } else { count = 0; while(count < numVtolAttackGroups) { if(vtolAttackGr[count].members < numAttackVtols) { dbg("added new vtol to group " & count, me); groupAddDroid(vtolAttackGr[count], droid); count = numVtolAttackGroups; } count++; } } } else if((droid.droidType != DROID_TRANSPORTER) and (droid.droidType != DROID_COMMAND)) { if((droid.droidType == DROID_REPAIR) or (droid.droidType == DROID_CYBORG_REPAIR)) { numRepairUnits = numRepairUnits + 1; } if(droid.droidType == DROID_SENSOR) { numSensorUnits = numSensorUnits + 1; } if((droid.droidType == DROID_CONSTRUCT) or (droid.droidType == DROID_CYBORG_CONSTRUCT)) // if constructor droid { groupAddDroid(buildGroup, droid); } else { if(droid.droidType == DROID_CYBORG) { groupAddDroid(attackGroup, droid); } else { if(scoutGroup.members < numScouts[curTech]) { groupAddDroid(scoutGroup, droid); } else if(attackGroup.members < numAttackers[curTech]) { groupAddDroid(attackGroup, droid); } else if( defendGroup.members < numDefenders[curTech]) { groupAddDroid(defendGroup, droid); } else { if(scoutGroup.members < maxScouts[curTech]) { groupAddDroid(scoutGroup, droid); } else if(attackGroup.members < maxAttackers[curTech]) { groupAddDroid(attackGroup, droid); } else if( defendGroup.members < maxDefenders[curTech]) { groupAddDroid(defendGroup, droid); } else //make them attack { groupAddDroid(attackGroup, droid); } } } } } } //When droid built: check emergency jobs, start building next droid event droidBuilt(droidBuiltTr) { local STRUCTURE _fundie; /* Start building next droid */ if(structure != NULLOBJECT) { // derrick works as NULL here, as NULLSTAT does not seem to work if (droid.droidType == DROID_CONSTRUCT and fundamentalBeingBuilt != derrick) { _fundie = getStructure(fundamentalBeingBuilt, me); if (_fundie != NULLOBJECT) { if (not structureComplete(_fundie)) { orderDroidObj(droid, DORDER_HELPBUILD, _fundie); } } } if (droid.droidType == DROID_CONSTRUCT && structure.stattype == REF_FACTORY) { setEventTrigger(conDroids, chainloadTr); // consider building more } // Continue building new droids right away else if(structure.stattype == REF_FACTORY) { factoryBuildDroid(structure); } else if(structure.stattype == REF_CYBORG_FACTORY) { cybFactorBuildCyborg(structure); } else if(structure.stattype == REF_VTOL_FACTORY) { vtolFactoryBuildVtol(structure); } } } /* Gets triggered when structure was built */ event structBuilt(structBuiltTr) { local FEATURE _oilResource; local int _count,_count2; if (structure == NULLOBJECT || droid == NULLOBJECT) { exit; } /* factory or factory module */ if(structure.stattype == REF_FACTORY) { if (isStructureAvailable(facModule, me) and (skGetFactoryCapacity(structure) < 2 ) and (getDroidCount(me) > 4)) { orderDroidStatsLoc(droid, DORDER_BUILD,facModule, structure.x,structure.y); // upgrade it. } else { setEventTrigger(conDroids, chainloadTr); } } /* vtol factory or vtol factory module */ else if(structure.stattype == REF_VTOL_FACTORY) { if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(structure) < 2 )) { orderDroidStatsLoc(droid, DORDER_BUILD,facModule, structure.x,structure.y); // upgrade it. } } else if(structure.stattype == REF_RESOURCE_EXTRACTOR) { setEventTrigger(buildDerrick, chainloadTr); exit; } else if (structure.stattype == REF_RESEARCH) { if (isStructureAvailable(resModule, me)) { orderDroidStatsLoc(droid, DORDER_BUILD, resModule, structure.x, structure.y); // upgrade it. } else { setEventTrigger(doResearch, chainloadTr); } } else if (structure.stattype == REF_POWER_GEN) { if (isStructureAvailable(powModule, me)) { orderDroidStatsLoc(droid, DORDER_BUILD, powModule, structure.x, structure.y); // upgrade it. } } // Check if available trucks need to build more absolute necessities right away. We need a trigger here because // droids involved in building have not yet come out of their build orders. setEventTrigger(buildFundamentals, slowloadTr); //see if we have just rebuilt a destroyed structure _count = 0; while(_count < countRebuildStruct) { if(structure.x == rebuildStructX[_count] and structure.y == rebuildStructY[_count] and ( (structure.stat == rebuildStructStat[_count]) or //walls can end up as corner walls ( (structure.stat == wall or structure.stat == cornerWall) and (rebuildStructStat[_count] == wall or rebuildStructStat[_count] == cornerWall)) )) { dbg("finished rebuilding destroyed structure - " & _count, me); //resort destroyed structures _count2 = _count; while(_count2 < (countRebuildStruct - 1)) { rebuildStructX[_count2] = rebuildStructX[_count2 + 1]; rebuildStructY[_count2] = rebuildStructY[_count2 + 1]; rebuildStructStat[_count2] = rebuildStructStat[_count2 + 1]; _count2++; } //clear last entry rebuildStructX[countRebuildStruct - 1] = 0; rebuildStructY[countRebuildStruct - 1] = 0; rebuildStructStat[countRebuildStruct - 1] = NULLSTRUCTURESTAT; countRebuildStruct--; //we just built one structure //_count = countRebuildStruct; //exit outer loop } _count++; } } ///////////////////////////////////////////////////////////////////// // deal with attacks. event droidDestroyed(droidDestroyedTr) { if(droid.droidType == DROID_REPAIR) { numRepairUnits = numRepairUnits - 1; } if(droid.droidType == DROID_SENSOR) { numSensorUnits = numSensorUnits - 1; } if(droid.droidType == DROID_CONSTRUCT) // if constructor droid { initEnumStruct(FALSE,factory,me,me); structure= enumStruct(); // find factory. if( (structure != NULLOBJECT) and (getDroidCount(me) < MAX_DROIDS) ) { buildDroid(constructor, structure, me, 1); // build constructor } } } ///////////////////////////////////////////////////////////////////// // build more con droids. event conDroids(conDroidsTr) { local int _maxTrucks; local STRUCTURE _factory; local int _numBuilding,_haveTrucks,_maxTruckFactories,_totalTrucks; local bool _bStartedBuilding; _maxTrucks = MAX_TRUCKS; if (playerPower(me) < LOW_POWER) { _maxTrucks = MIN_TRUCKS; } _maxTruckFactories = 3; //max factories to use for truck production _haveTrucks = buildGroup.members; //Find out how many trucks and combat engineers are already in production _numBuilding = numTemplatesInProduction(constructor,me); //trucks _numBuilding = _numBuilding + numTemplatesInProduction(cybEngineer,me); //engineers _totalTrucks = _numBuilding + _haveTrucks; initEnumStruct(FALSE,factory,me,me); _factory = enumStruct(); while ((_factory != NULLOBJECT) and (_numBuilding < _maxTruckFactories) and (_totalTrucks < _maxTrucks)) { //Try to build a truck if (skCanBuildTemplate(me, _factory, hovertruck)) { _bStartedBuilding = buildUnit(hovertruck, _factory, factory, FALSE); //build truck even if not idle } else { _bStartedBuilding = buildUnit(constructor, _factory, factory, FALSE); //build truck even if not idle } //Update statistics if started building a truck if(_bStartedBuilding) { _numBuilding++; _totalTrucks++; } _factory = enumStruct(); } //build cyborg engineers if needed, no building structure limit here initEnumStruct(FALSE,cybFactory,me,me); _factory = enumStruct(); while((_factory != NULLOBJECT) and (_totalTrucks < _maxTrucks)) { //Try to build a truck if( skCanBuildTemplate(me,_factory, cybEngineer) ) //make sure we have researched cyb engineer { _bStartedBuilding = buildUnit(cybEngineer, _factory, cybFactory, FALSE); //build a cyb eng even if not idle //Update statistics if started building a cyborg engineer if(_bStartedBuilding) { _numBuilding++; _totalTrucks++; } } _factory = enumStruct(); } setEventTrigger(conDroids, conDroidsTr); } //Build a droid function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly) { //Factory was not provided, find an factory if(_factory == NULLOBJECT) { _factory = findIdleStructure(_factoryType, _bIdleOnly); } //Build if got a factory if(_factory != NULLOBJECT) { if(structureComplete(_factory) and (getDroidCount(me) < MAX_DROIDS)) { if( !(_bIdleOnly and !structureIdle(_factory)) ) //don't build if only allowed to build whe idle and fac is not idle { buildDroid(_tankTemplate, _factory, me, 1); // build a tank return TRUE; //success } } } return FALSE; //failed } //Returns an idle structure of the provided type or NULLOBJECT if none found function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly) { local STRUCTURE _structure; initEnumStruct(FALSE,_structType,me,me); _structure = enumStruct(); while(_structure != NULLOBJECT) { if(structureComplete(_structure)) { if( !(_bIdleOnly and !structureIdle(_structure)) ) { return _structure; } } _structure = enumStruct(); } return NULLOBJECT; //none found } ///////////////////////////////////////////////////////////////////// // build repair droids. event repairDroids(repairDroidsTr) { // if we're running low on repair droids, build some.. if(numRepairUnits <8 and (playerPower(me) > LOW_POWER)) { if(random(10) <= 3) { initEnumStruct(FALSE,factory,me,me); structure= enumStruct(); // find factory. if (structure != NULLOBJECT) { count = 6; while( count >= 0 ) { if ((getDroidCount(me) < MAX_DROIDS) and (skCanBuildTemplate(me, structure, repair[count])) ) { buildDroid(repair[count], structure, me, 1); // build repairunit. count = -1; } count = count - 1; } } } else { initEnumStruct(FALSE,cybFactory,me,me); structure= enumStruct(); // find factory. if (structure != NULLOBJECT) { count = 6; while( count >= 0 ) { if ((getDroidCount(me) < MAX_DROIDS) and (skCanBuildTemplate(me, structure, repair[count])) ) { buildDroid(repair[count], structure, me, 1); // build repairunit. count = -1; } count = count - 1; } } } } } ///////////////////////////////////////////////////////////////////// // build sensor droids. event sensorDroids(sensorDroidsTr) { if(numSensorUnits <3 and (playerPower(me) > LOW_POWER)) { initEnumStruct(FALSE,factory,me,me); structure= enumStruct(); if(structure != NULLOBJECT) { count = 7; while( count >= 0 ) { if((getDroidCount(me) < MAX_DROIDS) and (skCanBuildTemplate(me, structure, sense[count])) ) { count2 = 0; count2 = count - 1; if(random(10) <= 5 and count2 >= 0) { if(skCanBuildTemplate(me, structure, sense[count2])) { buildDroid(sense[count2], structure, me, 1); count = -1; } else { buildDroid(sense[count], structure, me, 1); count = -1; } } else { buildDroid(sense[count], structure, me, 1); count = -1; } } count = count - 1; } } } } ///////////////////////////////////////////////////////////////////// event factoryEvent(factoryEventTr) { // for each factory.... initEnumStruct(FALSE,factory,me,me); structure = enumStruct(); // find factory. if(getDroidCount(me) < MAX_DROIDS) { while(structure != NULLOBJECT) { if( structureIdle(structure) ) { factoryBuildDroid(structure); } structure = enumStruct(); } } } function bool needTank() { if(not havePowerSource()) { return FALSE; } if((defendGroup.members < maxDefenders[curTech]) or (maxDefenders[curTech] == UNLIMITED)) { return TRUE; } if((scoutGroup.members < maxScouts[curTech]) or (maxScouts[curTech] == UNLIMITED)) { return TRUE; } if((attackGroup.members < maxAttackers[curTech]) or (maxAttackers[curTech] == UNLIMITED)) { return TRUE; } return FALSE; } function void factoryBuildDroid(STRUCTURE _factory) { local int _count,_count2; if(_factory == NULLOBJECT){ dbg("factoryBuildDroid: factory is NULLOBJECT", me); return; } if(not needTank()) { //dbg("NEED NO TANKS!! " & maxDefenders[curTech], me); return; } if( structureIdle(_factory) and (playerPower(me) > LOW_POWER)) { _count = numTemplates[curTech] - 1; _count2 = 0; while( (_count2 < MAX_RANDOM_TEMPLATES) and (_count >= 0) ) { if( skCanBuildTemplate(me,_factory, tmpl[curTech][_count]) ) { tmplChoice[_count2] = tmpl[curTech][_count]; _count2 = _count2 + 1; } _count = _count - 1; } if(_count2 > 0) { buildDroid(tmplChoice[random(_count2)],_factory,me,1); } } else { dbg("factoryBuildDroid: factory is busy", me); } } ///////////////////////////////////////////////////////////////////// // put cyborg factories to work event cyborgFactoryEvent(cyborgFactoryEventTr) { if(not ((defendGroup.members < maxCyborgs[curTech]) or (maxCyborgs[curTech] == UNLIMITED))) { exit; //we need no cyborgs } initEnumStruct(FALSE,cybFactory,me,me); structure= enumStruct(); // find factory. while(structure != NULLOBJECT) { if( structureIdle(structure) == TRUE) { cybFactorBuildCyborg(structure); } structure= enumStruct(); // find factory. } } function void cybFactorBuildCyborg(STRUCTURE _factory) { if(_factory == NULLOBJECT){ dbg("cybFactorBuildCyborg: factory is NULLOBJECT", me); return; } if( structureIdle(_factory) and (playerPower(me) > LOW_POWER)) { if( (defendGroup.members < maxCyborgs[curTech]) and (getDroidCount(me) < MAX_DROIDS) ) { count = 20; count2 = 0; while( count >= 0 ) { if( skCanBuildTemplate(me,_factory, superCyb[count]) ) { tmplChoice[count2] = superCyb[count]; count2 = count2 + 1; } count = count - 1; } if(count2 > 0) { buildDroid(tmplChoice[random(count2)],_factory,me,1); } else //try light cyborgs { count = numLightCyborgs - 1; count2 = 0; while( (count >= 0) and (count2 < 2) ) { if( skCanBuildTemplate(me,_factory, cybTempl[count]) ) { tmplChoice[count2] = cybTempl[count]; count2++; } count--; } if(count2 > 0) { buildDroid(tmplChoice[random(count2)], _factory, me, 1); } } } } } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // scouting rules // scout an area event chooseScoutArea(chooseScoutAreaTr) { scoutX = scoutTLX + random(scoutW); scoutY = scoutTLY + random(scoutH); } ///////////////////////////////////////////////////////////////////// // visit new places event expandScoutArea(expandScoutAreaTr) { //expand the scouting area slightly scoutTLX = scoutTLX - ((mapWidth*128)/ tileExpand); scoutTLY = scoutTLY - ((mapHeight*128)/ tileExpand); scoutW = scoutW + (2*((mapWidth*128)/ tileExpand)); scoutH = scoutH + (2*((mapHeight*128)/ tileExpand)); // check & restrain. if(scoutTLX <1) { scoutTLX = 1; } if(scoutTLY <1) { scoutTLY = 1; } if(scoutTLX >(mapWidth*128)) { scoutTLX = (mapWidth*128) - 128; } if(scoutTLY >(mapHeight*128)) { scoutTLY = (128*mapHeight) - 128; } if( (scoutTLX + scoutW) > (128 * mapWidth) ) { scoutW = ( (128 * mapWidth) - scoutTLX) - 128; } if( (scoutTLY + scoutH) > (128 *mapHeight) ) { scoutH = ( (128*mapHeight) - scoutTLY) - 128; } } ///////////////////////////////////////////////////////////////////// // order scouts event scoutMain(scoutMainTr) { // find any new scouts // if scouts aren't busy, send them to a new spot. if( idleGroup(scoutGroup) >= (scoutGroup.members /2) ) { orderGroupLoc(scoutGroup, DORDER_MOVE,scoutX,scoutY); } } ///////////////////////////////////////////////////////////////////// // process new visibility reports event newObjectReport(newObjectReportTr) { if(!friendlyPlayer(baseobj.player)) { if(targetTypeValue(baseobj) > targetTypeValue(attackObj)) { attackObj = baseobj;// got a new unseen target from a scout. if( attackObj.type == OBJ_STRUCTURE) { if(not allianceExistsBetween(attackObj.player,me)) // an enemy { structure = objToStructure(attackObj); if(structure.stat == factory) { allOutAttack = attackObj; } } } } } } function int targetTypeValue(BASEOBJ _target) { local STRUCTURE _strTarget; if(_target == NULLOBJECT){ return NO_TARGET_VALUE; } if(_target.type == OBJ_DROID) { return DROID_TARGET_VALUE; } else if(_target.type == OBJ_STRUCTURE) { _strTarget = objToStructure(_target); if(_strTarget.stattype == REF_DEFENSE) { return DEFENSE_TARGET_VALUE; } else if(_strTarget.stattype == REF_RESEARCH or _strTarget.stattype == REF_POWER_GEN) { return RESEARCH_TARGET_VALUE; } else if(_strTarget.stattype == REF_HQ or _strTarget.stattype == REF_COMMAND_CONTROL) { return HQ_TARGET_VALUE; } else if(_strTarget.stattype == REF_RESOURCE_EXTRACTOR) { return OIL_TARGET_VALUE; } else if(_strTarget.stattype == REF_FACTORY or _strTarget.stattype == REF_CYBORG_FACTORY or _strTarget.stattype == REF_VTOL_FACTORY) { return FACTORY_TARGET_VALUE; } else //walls, rearm pads etc { return OTHER_TARGET_VALUE; } } return NO_TARGET_VALUE; } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // spy technologies //event takeover( CALL_UNITTAKEOVER , ref droid ) event takeover(takeoverTr) { if( droid.player == me ) { if(droid.droidType == DROID_CONSTRUCT or droid.droidType == DROID_CYBORG_CONSTRUCT) { groupAddDroid( buildGroup, droid ); } else if (droid.droidType != DROID_TRANSPORTER && droid.droidType != DROID_COMMAND) { groupAddDroid( attackGroup, droid ); } } } event takeoverDefend(takeoverTr) { if( droid.player != me ) { completeResearch(nexusDefence,me); setEventTrigger(takeoverDefend, inactive); } } event useLassat(useLassatTr) { // find my lassat // fire it at my attack objective. if(allOutAttack != NULLOBJECT) { initEnumStruct(FALSE,lassat,me,me); structure= enumStruct(); while(structure != NULLOBJECT) { if(structureComplete(structure) == TRUE) { skFireLassat(me,allOutAttack); } structure= enumStruct(); } } } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // attack rules event findEnemy(attackStuffTr) { if(attackObj == NULLOBJECT) { count = random(8); count2 = 100; while( friendlyPlayer(count) && (count2 > 0) ) { count = random(8); count2--; } if(!friendlyPlayer(count)) { baseobj = skLocateEnemy(count); if(baseobj != NULLOBJECT) { attackObj = baseobj; // set allOutAttack to attackObj only if attackObj is a more valuable target than allOutAttack if(targetTypeValue(attackObj) > targetTypeValue(allOutAttack)) { allOutAttack = attackObj; } } } } } ///////////////////////////////////////////////////////////////////// // send attack team out to cause trouble near things scout found. event attackStuff(attackStuffTr) { if( idleGroup(attackGroup) >= (attackGroup.members / 2)) { if( (attackObj != NULLOBJECT) and (not helpingAlly()) ) { if (not allianceExistsBetween(me, attackObj.player)) { if(attackGroup.members > (6 + random(6)) ) { orderGroupLoc(attackGroup, DORDER_SCOUT, attackObj.x, attackObj.y); } // make scouts attack too if( idleGroup(scoutGroup) >= (scoutGroup.members / 2) ) { orderGroupLoc(scoutGroup, DORDER_SCOUT, attackObj.x, attackObj.y); } } } } } ///////////////////////////////////////////////////////////////////// event doAllOutAttack(allOutAttackTr) { if (idleGroup(attackGroup) >= (attackGroup.members / 3)) // make sure at least 30% are idle { if ((allOutAttack != NULLOBJECT) and (not helpingAlly())) { if (!friendlyPlayer(allOutAttack.player)) { if (getDroidCount(me) > 40) // plenty of units. { orderGroupObj(attackGroup, DORDER_ATTACK, allOutAttack); orderGroupLoc(scoutGroup, DORDER_SCOUT, allOutAttack.x, allOutAttack.y); } } else { allOutAttack = NULLOBJECT; } } } } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // defending rules // defend attacked objects. event defendWatch(defendWatchTr) { if (baseobj != NULLOBJECT) { if(!friendlyPlayer(baseobj.player)) { if(distBetweenTwoPoints(baseobj.x, baseobj.y, baseX, baseY) <= MAX_DEFENDERS_RADIUS) //don't go too far away from the base { defendObj = baseobj; defendbusy = TRUE; // if not too busy, attack. if (idleGroup(defendGroup) >= (defendGroup.members / 2)) { orderGroupLoc(defendGroup, DORDER_MOVE,defendObj.x,defendObj.y); //cyborg mechanics can't attack (won't move) } if (idleGroup(scoutGroup) >= (scoutGroup.members / 2)) { orderGroupLoc(scoutGroup, DORDER_MOVE,scoutX,scoutY); } } } } } ///////////////////////////////////////////////////////////////////// // defenders return after they are finished. event defendReturn(defendReturnTr) { if( defendbusy and (idleGroup(defendGroup) == (defendGroup.members - defendGroup.members / 12))) { // find a place with no structures nearby buildX = baseX; buildY = baseY; pickStructLocationB(powGen, ref buildX, ref buildY, me, 0); orderGroupLoc(defendGroup, DORDER_MOVE,buildX,buildY); defendbusy = FALSE; } } //returns number of non-idle structures of a certain type function int numStructBusyByType(STRUCTURESTAT _busyStructType) { local int _result; initEnumStruct(FALSE,_busyStructType,me,me); structure = enumStruct(); _result = 0; while(structure != NULLOBJECT) { if(structureComplete(structure)) { if(not structureIdle(structure)) { _result++; } } structure = enumStruct(); } return _result; } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // Research Rules Now does true research. // do research event doResearch(doResearchTr) { local int _techIndex,_numResearching; // don't throw in half of your money on research in T3 no bases when we don't have any income yet if (isStructureAvailable(facModule,me) and not havePowerSource()) { setEventTrigger(doResearch, doResearchTr); exit; } _techIndex = 0; //research start _numResearching = numStructBusyByType(resLab); // for every research lab do this.. initEnumStruct(FALSE,resLab,me,me); structure= enumStruct(); count = 0; while(structure != NULLOBJECT) { boolResult = FALSE; //haven't started research for the current resFac if(structureIdle(structure)) { if(structureComplete(structure)) { // first research all technologies necessary for the current research branch while(not boolResult and _techIndex != NONE) //not started researching and still branch tech left to try { _techIndex = findResearch(_techIndex, curTech); if(_techIndex > NONE) { boolResult = pursueResearch(structure,me,tech[curTech][_techIndex]); _techIndex++; //try nect research next time if needed _numResearching++; } } // do common research if(not boolResult) //didn't start branch research { if((maxIdleRes[curTech] == UNLIMITED) or (_numResearching < maxIdleRes[curTech])) { skDoResearch(structure,me,0); _numResearching++; } } } } structure = enumStruct(); } setEventTrigger(doResearch, doResearchTr); } // find next available research of our research branch function int findResearch(int _searchStart, int _techTree) { local int _result; ASSERT(_searchStart >= 0, "findResearch: _searchStart < 0", me); ASSERT(_techTree >= 0, "findResearch: _techTree < 0", me); _result = _searchStart; while(_result < techCount[_techTree]) { if((not researchFinished(tech[_techTree][_result], me)) and (not researchStarted(tech[_techTree][_result], me))) { return _result; //found research } _result++; } return NONE; //not found } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // Alliance Rules // form alliances event formAllianceEvent(formAllianceEventTr) { count = 0; while(count < MAX_PLAYERS) { if( count != me ) // if not the only other player and rand2 { if((getDroidCount(me) > 1) and (getDroidCount(count) > 1) ) // not dead { if(random(28) == 1) // bit random { if(not isHumanPlayer(count)) // not human { createAlliance(me,count); allianceTime[count] = gameTime; } } } } count = count + 1; } } ///////////////////////////////////////////////////////////////////// // break the alliance too. event breakAllianceEvent(breakAllianceEventTr) { count = 0; while(count<multiPlayerMaxPlayers) { if( count != me) { if((getDroidCount(me) > 1) and (getDroidCount(count) > 1) ) // not dead { if(allianceExistsBetween(me,count) ) { // check if we're in alliance with any other players. if( (random(30) == 1) and ( (gameTime - allianceTime[count]) > 6000) ) // rand and more than 10 minutes. { allianceTime[count] = gameTime; breakAlliance(me,count); } // rules for breaking alliances with humans. // built within my base if(numStructsInArea(count,minx,miny,maxx,maxy) > 1) { allianceTime[count] = gameTime; breakAlliance(me,count); } // you've got lots of units in my area. if(numDroidsInArea(count,minx,miny,maxx,maxy) > 3) { allianceTime[count] = gameTime; breakAlliance(me,count); } // you've wiped out one of my allies ??. } } } count = count + 1; } } ///////////////////////////////////////////////////////////////////// event formHumanAlliances(humanAllianceTr) { if(count2 == me) // offered to me. { result = 0; result2 = 0; while(result < multiPlayerMaxPlayers) { if(allianceExistsBetween(count,result)) { result2 = result2 + 1; } result = result + 1; } if( result2 < ((multiPlayerMaxPlayers / 2) - 1) ) // not too many already { //not too soon. if((allianceTime[count] == 0) or (gameTime - allianceTime[count] > 1200)) { result = 0; // check forming wont end the game result2 = 0; while(result < multiPlayerMaxPlayers) { while(result2 < multiPlayerMaxPlayers) { if((not allianceExistsBetween(result,result2)) and (getDroidCount(result) > 0) and (getDroidCount(result2) > 0) and (result != result2) ) { if( ((result == count and result2 == count2) or (result2 == count2 and result == count)) ) // ignore the outcome of this alliance { createAlliance(me,count); allianceTime[count] = gameTime; } } result2 = result2 + 1; } result = result + 1; } } } } } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // Consolidate Rules // bring forces back together to consolidate attacks event consolidateEvent(consolidateEventTr) { if(not helpingAlly()) { if(random(7) == 1) // order all droids home to rejoin forces.! { // find a place with no structures nearby buildX = baseX; buildY = baseY; pickStructLocationB(powGen, ref buildX, ref buildY, me, 0); orderGroupLoc(scoutGroup, DORDER_MOVE,buildX,buildY); orderGroupLoc(defendGroup, DORDER_MOVE,buildX,buildY); } /* if(attackObj != NULLOBJECT) // consolidate any ongoing attack. { if(!friendlyPlayer(attackObj.player)) { orderGroupLoc(attackGroup, DORDER_SCOUT, attackObj.x, attackObj.y); } else { attackObj = NULLOBJECT; } } else if(allOutAttack == NULLOBJECT) //make sure not allOutAttacking { // find a place with no structures nearby buildX = baseX; buildY = baseY; pickStructLocationB(powGen, ref buildX, ref buildY, me, 0); orderGroupLoc(attackGroup, DORDER_MOVE,buildX,buildY); } */ } } ///////////////////////////////////////////////////////////////////// event difficultyModifier(difficultyModifierTr) { if(not isHumanPlayer(me)) { skDifficultyModifier(me); } } ///////////////////////////////////////////////////////////////////// // vtols. ///////////////////////////////////////////////////////////////////// // build vtol strucutures. event vtolStructs(inactive) { local int _numVtolFacs,_numRearmPads; // got any idle trucks? if (idleGroup(buildGroup) < 1) { exit; } // see how many vtol factories we already have _numVtolFacs = getNumStructures(vtolFactory,me); _numRearmPads = getNumStructures(vtolPad,me); //see if we have enough rearm pads if( _numRearmPads * 4 / 3 <= totalVtols() ) { dbg("NEED REARM PADS", me); buildRearmPads(); } if (_numVtolFacs > 0 and playerPower(me) < LOW_POWER) { exit; // Throttle expansion to avoid waste } if (isStructureAvailable(vtolFactory, me) and _numVtolFacs < maxVtolFacs[curTech]) // if not enough { if (not grabTrucksAndBuild(8, vtolFactory, 1)) { dbg("Failed to build Vtol fac", me); } } } //counts vtols function int totalVtols() { local int _vtolGroup,_totalVtols; _totalVtols = 0; _vtolGroup = 0; while(_vtolGroup < numVtolAttackGroups) { _totalVtols = _totalVtols + vtolAttackGr[_vtolGroup].members; _vtolGroup++; } _totalVtols = _totalVtols + vtolDefendGr.members; return _totalVtols; } function void buildRearmPads() { if (isStructureAvailable(vtolPad, me)) { if (not grabTrucksAndBuild(4, vtolPad, -1)) { dbg("Failed to build vtol pad", me); } } } ///////////////////////////////////////////////////////////////////// // build vtols. event buildVtols(inactive) { // got enough vtols? if((vtolDefendGr.members >= maxVTOLs[curTech]) or (getDroidCount(me) >= MAX_DROIDS)){ dbg("CAN'T BUILD VTOLS - TOO MANY UNITS", me); exit; } if(playerPower(me) > LOW_POWER) { // build vtols initEnumStruct(FALSE,vtolFactory,me,me); structure = enumStruct(); while(structure != NULLOBJECT) { if(structureIdle(structure)) // if factory idle { vtolFactoryBuildVtol(structure); } structure = enumStruct(); } } } function void vtolFactoryBuildVtol(STRUCTURE _factory) { local int _numTemplates,_bestTemplates; if(_factory == NULLOBJECT){ return; } if( structureIdle(_factory) ) { _numTemplates = numVtolTemplates - 1; _bestTemplates = 0; while( (_bestTemplates < 3) and (_numTemplates >= 0) ) { if( skCanBuildTemplate(me,_factory, vtols[_numTemplates]) ) { tmplChoice[_bestTemplates] = vtols[_numTemplates]; _bestTemplates++; } _numTemplates--; } if(_bestTemplates > 0) { buildDroid(tmplChoice[random(_bestTemplates)],_factory,me,1); } } } ///////////////////////////////////////////////////////////////////// // attack with vtols. event vtolAttack(inactive) { local int _groupIndex,_newTargetWeight,_oldTargetWeight; local BASEOBJ _newTarget; local bool _bHaveDefendTarget; local DROID _droid; // if vtol group is not busy.. if( (idleGroup(vtolDefendGr) >= (vtolDefendGr.members / 2)) and (vtolDefendGr.members >= 2) ) { if(attackObj != NULLOBJECT) { if(!friendlyPlayer(attackObj.player)) { orderGroupObj(vtolDefendGr, DORDER_ATTACK, attackObj); // get the attack target. } else { attackObj = NULLOBJECT; } } else { if(defendObj != NULLOBJECT) { orderGroupObj(vtolDefendGr, DORDER_ATTACK,defendObj); // get the defend target } } } //make sure attack vtol groups are not cluttered rearrangeAttackVtols(); //attack vtols _groupIndex = 0; while(_groupIndex < numVtolAttackGroups) { if(vtolAttackGr[_groupIndex].members > 0) { // if our base is in trouble see if we have a target in the base // don't choose new target if already have one _bHaveDefendTarget = FALSE; if((vtolGrAttackObj[_groupIndex] != NULLOBJECT)) { if(defendingOwnBase() and (distBetweenTwoPoints(baseX, baseY, vtolGrAttackObj[_groupIndex].x, vtolGrAttackObj[_groupIndex].y) <= MAX_VTOL_DEFEND_RADIUS)) { _bHaveDefendTarget = TRUE; } // else //reset target if it's not worth it // { // //we don't want to attack enemy heavy tanks outside of our base // if(vtolGrAttackObj[_groupIndex].type == OBJ_DROID) // { // _droid = objToDroid(vtolGrAttackObj[_groupIndex]); // if(_droid.droidType != DROID_CONSTRUCT) // { // vtolGrAttackObj[_groupIndex] = NULLOBJECT; //reset target // _bHaveDefendTarget = FALSE; // } // } // } } //find target in our base if our base is in trouble if(!_bHaveDefendTarget and defendingOwnBase()) { vtolGrAttackObj[_groupIndex] = chooseVtolDefenceTarget(baseX, baseY, MAX_VTOL_DEFEND_RADIUS, FALSE); if(vtolGrAttackObj[_groupIndex] != NULLOBJECT) { dbg("assigned new defence target for group " & _groupIndex, me); _bHaveDefendTarget = TRUE; } } //attack rules if(!_bHaveDefendTarget and (idleGroup(vtolAttackGr[_groupIndex]) >= (vtolAttackGr[_groupIndex].members / 2)) and (vtolAttackGr[_groupIndex].members >= (numAttackVtols * 2 / 3))) { _newTarget = NULLOBJECT; //reset attack targets once in a while if(vtolGrAttackObj[_groupIndex] != NULLOBJECT) { if(random(10) > 7) { vtolGrAttackObj[_groupIndex] = NULLOBJECT; } } //now try to find an attack target if we have no defence target //find best attack target _newTarget = chooseVtolTarget(TRUE); //search for an exclusive target if(_newTarget == NULLOBJECT) { _newTarget = chooseVtolTarget(FALSE); //search for any target } _newTargetWeight = getVtolTargetWeight(_newTarget); _oldTargetWeight = getVtolTargetWeight(vtolGrAttackObj[_groupIndex]); // new one or a much better one if((_newTargetWeight >= (_oldTargetWeight + 20)) or (vtolGrAttackObj[_groupIndex] == NULLOBJECT )) { dbg("choosing new attack object for " & _groupIndex, me); vtolGrAttackObj[_groupIndex] = _newTarget; } } //see if this group has something to attack if(vtolGrAttackObj[_groupIndex] != NULLOBJECT) { if(!friendlyPlayer(vtolGrAttackObj[_groupIndex].player)) { dbg("VTOL Group " & _groupIndex & " attacking", me); if(_DEBUG and (_groupIndex == 0)) { dropBeacon(getPlayerName(me), me, me, vtolGrAttackObj[_groupIndex].x, vtolGrAttackObj[_groupIndex].y, 0); } orderGroupObj(vtolAttackGr[_groupIndex], DORDER_ATTACK, vtolGrAttackObj[_groupIndex]); } else { vtolGrAttackObj[_groupIndex] = NULLOBJECT; } } } _groupIndex++; } } //make sure vtol groups are not cluttered function void rearrangeAttackVtols() { local int _emptyGr,_fillGr; local DROID _droid; _emptyGr = 0; while(_emptyGr < numVtolAttackGroups) { if((vtolAttackGr[_emptyGr].members < numAttackVtols) and //this group is not full (vtolAttackGr[_emptyGr].members > 0)) { //try to make full groups by moving vtols from the last groups _fillGr = _emptyGr + 1; //start from the next group while((_fillGr < numVtolAttackGroups) and (vtolAttackGr[_emptyGr].members < numAttackVtols)) { initIterateGroup(vtolAttackGr[_fillGr]); _droid = iterateGroup(vtolAttackGr[_fillGr]); while((_droid != NULLOBJECT) and (vtolAttackGr[_emptyGr].members < numAttackVtols)) { groupAddDroid(vtolAttackGr[_emptyGr], _droid); //refill the group _droid = iterateGroup(vtolAttackGr[_fillGr]); } _fillGr++; } } _emptyGr++; } } function BASEOBJ chooseVtolDefenceTarget(int _x, int _y, int _range, bool bExclusiveTarget) { local BASEOBJ _target; _target = getClosestEnemy(_x, _y, _range, FALSE, FALSE, me); // make sure no one else is targeting it already if we want exclusive targets if(bExclusiveTarget and vtolTargetAssigned(_target)) { _target = NULLOBJECT; } return _target; } function BASEOBJ chooseVtolTarget(bool bExclusiveTarget) { local int _structTypeIndex,_enemy; local int _bestScore,_tempScore; local BASEOBJ _bestTarget; local STRUCTURE _structure; _bestScore = 0; _bestTarget = NULLOBJECT; _enemy = 0; while(_enemy < MAX_PLAYERS) { if(!friendlyPlayer(_enemy)) { _structTypeIndex = 0; while(_structTypeIndex < numVtolTargets) { initEnumStruct(FALSE,vtolTarget[_structTypeIndex],_enemy,me); _structure = enumStruct(); while(_structure != NULLOBJECT) { // in case we don't want all groups to attack the same target if(not (bExclusiveTarget and vtolTargetAssigned(_structure)) ) { _tempScore = getVtolTargetWeight(_structure); //see if this one is better if(_tempScore > _bestScore) { _bestScore = _tempScore; _bestTarget = _structure; } } _structure = enumStruct(); } _structTypeIndex++; } } _enemy++; } return _bestTarget; } function int getVtolTargetWeight(BASEOBJ _target) { local int _AAPenalty,_numAA,_range,_targetWeight; local int _targetType; local STRUCTURE _structTarget; if(_target == NULLOBJECT) { return 0; } if(_target.type != OBJ_STRUCTURE) { return 0; } _structTarget = objToStructure(_target); _targetWeight = 0; _AAPenalty = 9; //penalty per aa defense _range = AA_THREAT_RANGE; // count enemy AA _numAA = numEnemyAAInRange(_structTarget.x, _structTarget.y, _range); // find tyrget type from stats _targetType = 0; while(_targetType < numVtolTargets) { if(_structTarget.stat == vtolTarget[_targetType]) { _targetWeight = vtolTargetWeight[_targetType] - (_numAA * _AAPenalty); _targetType = numVtolTargets; //exit loop } _targetType++; } // incomplete structures get lower weight if(!structureComplete(_structTarget)) { _targetWeight = _targetWeight / 10; } return _targetWeight; } function int numEnemyAAInRange(int _x, int _y, int _range) { local int _enemy,_numAA; _numAA = 0; _enemy = 0; while(_enemy < MAX_PLAYERS) { if(!friendlyPlayer(_enemy)) { _numAA = _numAA + numAAinRange(_enemy, me, _x, _y, _range); } _enemy++; } return _numAA; } // see if a particular target is already assigned to one of the VTOL attack groups function bool vtolTargetAssigned(BASEOBJ _target) { local int _groupIndex; if(_target == NULLOBJECT) { return FALSE; } _groupIndex = 0; while(_groupIndex < numVtolAttackGroups) { if(_target == vtolGrAttackObj[_groupIndex]) { return TRUE; } _groupIndex++; } return FALSE; } ///////////////////////////////////////////////////////////////////// // watch for incoming vtols event vtolDefend(vtolDefendTr) { local int _numBuilders,_maxBuilders; if(baseobj != NULLOBJECT) { if(baseobj.type == OBJ_DROID) { if(isVtol(objToDroid(baseobj))) { _numBuilders = 0; _maxBuilders = 2; // build defenses. initIterateGroup(buildGroup); // find idle droids in build group. droid = iterateGroup(buildGroup); while( droid != NULLOBJECT) { if( (structure != NULLOBJECT) and (droid.order != DORDER_BUILD) ) { buildX = structure.x; buildY = structure.y; // if ! vtol defense already built... //find best defense we can build. count = 0; count2 = -1; while( count < 9) { if(isStructureAvailable(vtolDefStruct[count],me)) { count2 = count; } count = count + 1; } if(count2 != (-1) ) { boolResult = pickDroidStructLocation(droid, vtolDefStruct[count2], ref buildX, ref buildY, me, 1); if (boolResult == TRUE and (_numBuilders < _maxBuilders)) // build a vtol defense near the attacked struct... { orderDroidStatsLoc(droid, DORDER_BUILD,vtolDefStruct[count2],buildX,buildY); _numBuilders++; } } } droid = iterateGroup(buildGroup); } } } } } ///////////////////////////////////////////////////////////////////// event vtolEnabler(vtolEnablerTr) { if( skVtolEnableCheck(me) ) // check to see if we have vtol technologies. { setEventTrigger(vtolEnabler,inactive); // turn off this event. setEventTrigger(vtolStructs,vtolStructsTr); // activate other vtol functions.. setEventTrigger(buildVtols, buildVtolsTr); setEventTrigger(vtolAttack, vtolAttackTr); dbg("----I CAN USE VTOLS----", me); } } ///////////////////////////////////////////////////////////////////// // HouseKeeping function void shutDownAI() { bRunning = false; setEventTrigger(basedetails, inactive); setEventTrigger(buildDerrick, inactive); setEventTrigger(buildOilDefenseOrRetreat, inactive); setEventTrigger(incendry, inactive); setEventTrigger(buildPowerGenerators, inactive); setEventTrigger(buildBase, inactive); setEventTrigger(buildExpand,inactive); setEventTrigger(upgradeStructures,inactive); setEventTrigger(finishStructs, inactive); setEventTrigger(newfortify, inactive); setEventTrigger(droidBuiltAssign, inactive); setEventTrigger(droidBuilt, inactive); setEventTrigger(structBuilt,inactive); setEventTrigger(droidDestroyed,inactive); setEventTrigger(conDroids,inactive); setEventTrigger(repairDroids,inactive); setEventTrigger(sensorDroids,inactive); setEventTrigger(factoryEvent, inactive); setEventTrigger(cyborgFactoryEvent, inactive); setEventTrigger(chooseScoutArea, inactive); setEventTrigger(expandScoutArea, inactive); setEventTrigger(scoutMain, inactive); setEventTrigger(newObjectReport, inactive); setEventTrigger(takeover, inactive); setEventTrigger(takeoverDefend, inactive); setEventTrigger(useLassat, inactive); setEventTrigger(findEnemy, inactive); setEventTrigger(attackStuff, inactive); setEventTrigger(defendWatch, inactive); setEventTrigger(defendReturn, inactive); setEventTrigger(doResearch, inactive); setEventTrigger(formAllianceEvent, inactive); setEventTrigger(breakAllianceEvent, inactive); setEventTrigger(formHumanAlliances, inactive); setEventTrigger(consolidateEvent, inactive); setEventTrigger(vtolStructs,inactive); setEventTrigger(buildVtols,inactive); setEventTrigger(vtolAttack,inactive); setEventTrigger(vtolDefend,inactive); setEventTrigger(vtolEnabler,inactive); setEventTrigger(beaconEv, inactive); setEventTrigger(multiMsgEv, inactive); setEventTrigger(manageAllyHelp, inactive); setEventTrigger(everySecEv, inactive); setEventTrigger(watchBaseThreat, inactive); setEventTrigger(manageDefendLocationEv, inactive); setEventTrigger(structureDestroyed,inactive); setEventTrigger(rebuildStructureEv,inactive); setEventTrigger(startLevel, inactive); setEventTrigger(arrived, inactive); setEventTrigger(checkResearch, inactive); } function void reassignAI() { bRunning = true; setEventTrigger(basedetails,basedetailsTr); setEventTrigger(buildDerrick,buildDerrickTr); setEventTrigger(buildOilDefenseOrRetreat,buildOilDefenseOrRetreatTr); setEventTrigger(incendry,incendryTr); setEventTrigger(buildPowerGenerators,buildPowerGeneratorsTr); setEventTrigger(buildBase,buildBaseTr ); setEventTrigger(buildExpand,buildExpandTr ); setEventTrigger(upgradeStructures,upgradeStructuresTr ); setEventTrigger(finishStructs,finishStructsTr ); setEventTrigger(newfortify,fortifyTr ); setEventTrigger(droidBuiltAssign,droidBuiltTr); setEventTrigger(droidBuilt,droidBuiltTr); setEventTrigger(droidDestroyed,droidDestroyedTr); setEventTrigger(conDroids,conDroidsTr); setEventTrigger(repairDroids,repairDroidsTr); setEventTrigger(sensorDroids,sensorDroidsTr); setEventTrigger(factoryEvent,factoryEventTr); setEventTrigger(cyborgFactoryEvent,cyborgFactoryEventTr); setEventTrigger(chooseScoutArea,chooseScoutAreaTr); setEventTrigger(expandScoutArea,expandScoutAreaTr); setEventTrigger(scoutMain,scoutMainTr); setEventTrigger(newObjectReport,newObjectReportTr); setEventTrigger(takeover,takeoverTr); setEventTrigger(useLassat,useLassatTr); setEventTrigger(findEnemy,attackStuffTr); setEventTrigger(attackStuff,attackStuffTr); setEventTrigger(doAllOutAttack,allOutAttackTr); setEventTrigger(defendWatch,defendWatchTr); setEventTrigger(defendReturn,defendReturnTr); setEventTrigger(doResearch,doResearchTr); setEventTrigger(formAllianceEvent,formAllianceEventTr); setEventTrigger(breakAllianceEvent,breakAllianceEventTr); setEventTrigger(consolidateEvent,consolidateEventTr); setEventTrigger(vtolStructs,inactive); setEventTrigger(buildVtols,inactive); setEventTrigger(vtolAttack,inactive); setEventTrigger(vtolAttack, vtolAttackTr); setEventTrigger(vtolDefend,vtolDefendTr); setEventTrigger(vtolEnabler,vtolEnablerTr); setEventTrigger(formHumanAlliances,humanAllianceTr); setEventTrigger(multiMsgEv, multiMsgTr); setEventTrigger(beaconEv, beaconTr); setEventTrigger(watchBaseThreat, watchBaseThreatTr); setEventTrigger(manageAllyHelp, manageAllyHelpTr); setEventTrigger(everySecEv, everySec); setEventTrigger(manageDefendLocationEv, manageDefendLocationTr); setEventTrigger(structBuilt, structBuiltTr); setEventTrigger(structureDestroyed, structureDestroyedTr); setEventTrigger(rebuildStructureEv, rebuildStructureTr); setEventTrigger(startLevel, startLevelTr); setEventTrigger(arrived, reachedTr); setEventTrigger(checkResearch, checkResearchTr); } /* Returns true if we just received a beacon from a certain player */ function bool haveBeacon(int _player) { if((tBeacon[_player] > 0) and (not beaconTimeout(_player))) { return TRUE; //have beacon for this player } return FALSE; } /* See if last beacon was placed long ago */ function bool beaconTimeout(int _player) { if((tBeacon[_player] > 0) and ((tBeacon[_player] + BEACON_TIMEOUT) < (gameTime / 10))) //not too long ago { return TRUE; //this beacon is still 'fresh' } return FALSE; } /* Deal with beacons */ event beaconEv(beaconTr) { local int _players; local string _processedString; if(_DEBUG) debug(me & ") beaconEv: from " & sender); ASSERT(sender >= 0 and sender < MAX_PLAYERS, "beaconEv: sender out of bounds: " & sender , me); beaconX[sender] = x; beaconY[sender] = y; tBeacon[sender] = gameTime / 10; processCommand(message, sender, TRUE); } /* Deal with a chat message */ event multiMsgEv(multiMsgTr) { if(_DEBUG) debug(me & ") multiMsgEv: from " & sender); if(not allianceExistsBetween(me, sender)){ exit; } if(sender == me){ exit; } processCommand(message, sender, FALSE); } /* Process multiplayer messages */ function void processCommand(string _message, int _sender, bool _bBlipMessage) { local int _numMsgs,_curMsg,_addressedPlayers,_x,_y; local string _msg,_processedString; /* Extract semantic information */ _curMsg = 0; _numMsgs = processChatMsg(_message); debug(me & ") processCommand: '" & _message & "' from " & _sender); dbg("processCommand: '" & _message & "' from " & _sender, me); dbg("got " & _numMsgs & " commands", me); /* Process all messages */ while(_curMsg < _numMsgs) { if(chatCmdIsPlayerAddressed(_curMsg, me)) { dbg("i'm addressed", me); _msg = getChatCmdDescription(_curMsg); /* Someone requested help */ if(_msg == R_REQUEST_HELP) { dbg("'help' command", me); if(haveBeacon(_sender)) { dbg("got beacon", me); _x = beaconX[_sender]; _y = beaconY[_sender]; if(attemptToHelp(_sender, _x, _y)) { messagePlayer(ALL_ALLIES, m_affirmative(), MAX_PROBABILITY); } } else { /* Ask player to drop a beacon so we would know where to help */ _addressedPlayers = setBit(0, _sender, TRUE); messagePlayerAddressed(ALL_ALLIES, _addressedPlayers, R_REQUEST_BEACON); } } /* Someone requested a beacon from us - * did we request help and our beacon timed out?? */ else if(_msg == M_REQUEST_BEACON) { /* If our base is really in trouble drop a beacon for the requester again */ if(baseInTrouble()){ dropBeacon(getPlayerName(me), _sender, me, baseX, baseY, 0); } } else if(_msg == R_REPORT_SAFETY) { dbg("helping " & lastHelpPlayer, me); /* Make sure we were helping him */ if(helpingAlly() and (lastHelpPlayer == _sender)) { stopHelpingAlly(); messagePlayer(ALL_ALLIES, m_affirmative(), MAX_PROBABILITY); } else if(defendingOwnBase()) //if we are in trouble re-request help { requestHelp(baseX, baseY); } } else { dbg("unknown message", me); } } else { dbg("i'm not addressed", me); } _curMsg++; } } function bool attemptToHelp(int _playerToHelp, int _x, int _y) { local bool _bHelpingMyself; if(_playerToHelp < 0 or _playerToHelp >= MAX_PLAYERS){ return FALSE; } if(_x <= 0 or _y <= 0){ return FALSE; } dbg("attemptToHelp - checking", me); _bHelpingMyself = (_playerToHelp == me); /* Can only help allies and myself */ if(not friendlyPlayer(_playerToHelp)){ return FALSE; } if(_bHelpingMyself or !helpingAlly() or (lastHelpPlayer == _playerToHelp) ) //if not helping any other ally or it's me who needs help { dbg("not busy helping", me); if(haveHelpers() or _DEBUG) { dbg("got attackers", me); //if(allyBaseAtLoc(_playerToHelp, _x, _y)) //is he just trying to misuse us? //{ helpPlayer(_playerToHelp, _x, _y); return TRUE; //} //else //{ // dbg("ally needs no help", me); // messagePlayer(ALL_ALLIES, M_ANNOYED, MAX_PROBABILITY / 2); //} } else { messagePlayer(ALL_ALLIES, M_HELP_NO_UNITS, MAX_PROBABILITY); } } else if((lastHelpPlayer >= 0) and (lastHelpPlayer < MAX_PLAYERS)) { if(!_bHelpingMyself){ messagePlayer(ALL_ALLIES, "helping " & getPlayerName(lastHelpPlayer) & " already", MAX_PROBABILITY); } } return FALSE; } /* Start helping player */ function void helpPlayer(int _playerToHelp, int _helpX, int _helpY) { local int _tTravelTime; dbg("helping " & _playerToHelp, me); if(_DEBUG) debug(me & ") helpPlayer: '" & _playerToHelp); /* Move scoutes to attackers */ groupAddGroup(attackGroup, scoutGroup); //Calculate travel time, assume ~ 150 tiles in 4 minutes if(attackGroup.members == 0){ _tTravelTime = (int)((float)(distBetweenTwoPoints(baseX, baseY, _helpX, _helpY) / 128 ) * 1.7); }else{ _tTravelTime = (int)((float)(distBetweenTwoPoints(attackGroup.x, attackGroup.y, _helpX, _helpY) / 128 ) * 1.7); } tHelp = gameTime / 10; tHelpTimeout = (gameTime / 10) + BASE_DEFEND_DURATION + _tTravelTime; lastHelpPlayer = _playerToHelp; helpX = _helpX; helpY = _helpY; /* Scouts and attackers go to help */ defendLocation(_helpX, _helpY, tHelpTimeout, (_playerToHelp == me)); } /* Returns a random affirmative responce */ function string m_affirmative() { local int _rnd; _rnd = random(4); if(_rnd == 3) { return M_AFFIRMATIVE_ROGER; } return M_AFFIRMATIVE_OK; } /* See if there are any base structures belonging to ally at a certain location */ function bool allyBaseAtLoc(int _ally, int _x, int _y) { local int _structIndex; if(_x <= 0 or _y <= 0){ return FALSE; } if(_ally < 0 or _ally >= MAX_PLAYERS){ return FALSE; } _structIndex = 0; while(_structIndex < numBaseStruct) { if(numStructsByStatInRange(baseStruct[_structIndex], _x, _y, (7 * 128), me, _ally) > 0 ) { return TRUE; } _structIndex++; } return FALSE; } event manageAllyHelp(manageAllyHelpTr) { if(helpingAlly()) { if(canStopHelpingAlly()) { stopHelpingAlly(); } } } event everySecEv(everySec) { /* Check if we were helping long enough */ if(helpingAlly()) { if(helpAllyTimeout()) { stopHelpingAlly(); } } if(defendingLocation()) { if(defendLocationTimeout()) { stopDefendingLocation(); } } } /* Do we have any units we can send to help ally ? */ function bool haveHelpers() { if(attackGroup.members == 0){ return FALSE; } return TRUE; } function bool helpingAlly() { if(lastHelpPlayer >= 0){ return TRUE; } return FALSE; } /* Returns true if we were helping long enough */ function bool helpAllyTimeout() { if(tHelpTimeout < (gameTime / 10) ){ return TRUE; } return FALSE; } function bool canStopHelpingAlly() { if(lastHelpPlayer < 0) { ASSERT(FALSE, "canStopHelpingAlly: lastHelpPlayer < 0", me); return TRUE; } /* Were helping long enough or someone's backstabbing */ if(!friendlyPlayer(lastHelpPlayer)){ return TRUE; } /* Nothing to defend anymore */ //if(!allyBaseAtLoc(lastHelpPlayer, helpX, helpY)){ // return TRUE; //} return FALSE; } function void stopHelpingAlly() { dbg("stopped helping", me); tHelp = -1; tHelpTimeout = -1; lastHelpPlayer = -1; helpX = -1; helpY = -1; stopDefendingLocation(); } /* Send a multiplayer message to an ally */ function void messagePlayer(int _playerToMessage, string _message, int _probability) { local int _player; ASSERT(_playerToMessage >= -1 && _playerToMessage < MAX_PLAYERS, "messagePlayer: player out of bounds: " & _playerToMessage, me); // throw the dice if( random(MAX_PROBABILITY) >= _probability ){ return; } _player = 0; if(_playerToMessage == ALL_ALLIES) //everyone { while(_player < MAX_PLAYERS) { /* Send message (allies only)) */ if(allianceExistsBetween(me, _player)) { msg(_message, me, _player); } _player++; } } else //a certain player { /* Send message (allies only)) */ if(allianceExistsBetween(me, _playerToMessage)) { msg(_message, me, _playerToMessage); } } } function int numBitsSet(int _integer) { local int _position,_result; _position = 0; _result = 0; while(_position < 8) { if(getBit(_integer, _position)) { _result++; } _position++; } return _result; } /* Send a multiplayer message, addressing some player(s) */ function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message) { local int _player,_totalAddressed,_curAddressed; local string _adrMessage; _totalAddressed = numBitsSet(_playersToAddress); ASSERT(_totalAddressed > 0, "messagePlayerAddressed: no players addressed", me); _adrMessage = " "; _player = 0; _curAddressed = 0; while(_player < MAX_PLAYERS) { if(getBit(_playersToAddress, _player)) { _curAddressed++; _adrMessage = _adrMessage & getPlayerName(_player); //if(_totalAddressed == 1){ //one only // _adrMessage = getPlayerName(_player); //}else if(_totalAddressed > 1) { if(_curAddressed == _totalAddressed){ //end _adrMessage = _adrMessage & " and " & getPlayerName(_player); }else{ _adrMessage = _adrMessage & ", " & getPlayerName(_player); } } } _player++; } _message = _adrMessage & " " & _message; //Now send the message to all players addressed messagePlayer(_playerToMessage, _message, MAX_PROBABILITY); } /* Returns true if we can see our allies on the map */ function bool canSeeAllies() { local STRUCTURE _uplink; /* Can see allies when team mode is on */ if(multiPlayerAlliancesType == ALLIANCES_TEAMS) { return TRUE; } /* Can see whole map if we have uplink */ _uplink = getStructure(uplink, me); if(_uplink != NULLOBJECT) { /* Make sure finished building */ if(structureComplete(_uplink)) { return TRUE; } } return FALSE; } function bool defendingOwnBase() { if(helpingAlly() && lastHelpPlayer == me){ return TRUE; } return FALSE; } /* Call for help when our base is in danger */ event watchBaseThreat(watchBaseThreatTr) { /* See if we can stop defending */ if(defendingOwnBase()) { if(numEnemiesInBase(FALSE) == 0) { stopHelpingAlly(); //stop defending our own base /* Let allies know we don't need their help anymore */ messagePlayer(ALL_ALLIES, R_REPORT_SAFETY, MAX_PROBABILITY); exit; } } /* See if our base is in trouble and we need help */ if(baseInTrouble()) { if(!defendingOwnBase()) //make sure not already defending the base { if(_DEBUG) debug(me & ") watchBaseThreat: base in trouble"); dbg("watchBaseThreat: base in trouble", me); /* Bring our forces back if needed */ if(helpingAlly()) { stopHelpingAlly(); } /* Defend my own base */ helpPlayer(me, baseX, baseY); } /* Request help once in a while */ requestHelp(baseX, baseY); exit; } } function int numAlliesInBase(bool _bVtols) { local int _numAllies; _numAllies = numFriendlyWeapDroidsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, _bVtols); _numAllies = _numAllies + numFriendlyWeapStructsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, true) / 3; return _numAllies; } function int numEnemiesInBase(bool _bVtols) { local int _numEnemies; _numEnemies = numEnemyWeapDroidsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, _bVtols); _numEnemies = _numEnemies + numEnemyWeapStructsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, true) / 4; return _numEnemies; } /* Returns true if our base is in trouble */ function bool baseInTrouble() { local int _enemyForce,_friendlyForce; _friendlyForce = numAlliesInBase(FALSE); _enemyForce = numEnemiesInBase(FALSE); /* See if we are in trouble */ if((_enemyForce > 0) && (_enemyForce >= _friendlyForce)){ dbg("baseInTrouble: " & _enemyForce & " >= " & _friendlyForce, me); return TRUE; } return FALSE; } /* Request help from allies */ function void requestHelp(int _helpX, int _helpY) { /* Don't do this too frequently */ if(tLastHelpRequest + HELP_REQUEST_INTERVAL > (gameTime / 10) ){ return; } doRequestHelp(_helpX, _helpY); } function void doRequestHelp(int _helpX, int _helpY) { local int _ally; /* Remember when we requested help last time */ tLastHelpRequest = gameTime / 10; /* Drop beacon for all allies so they would know where to help */ _ally = 0; while(_ally < MAX_PLAYERS) { if(allianceExistsBetween(me, _ally)){ if(_DEBUG) debug(me & ") requestHelp: " & _ally); dropBeacon(getPlayerName(me), _ally, me, _helpX, _helpY, 0); } _ally++; } /* Now send message with help request */ messagePlayer(ALL_ALLIES, M_REQUEST_HELP, MAX_PROBABILITY); } function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, bool _bMove) { local int defendRadius; defendRadius = 25 * TILE; dbg("starting defending for " & _tDefendTimeout - (gameTime / 10) & " secs, with defend radius " & defendRadius, me); defendX = _defendX; defendY = _defendY; tDefendStart = gameTime / 10; /* Should already include travel time */ tDefendTimeout = _tDefendTimeout; /* See if we have to move or scout */ defendMoveType = DORDER_SCOUT; if(_bMove){ defendMoveType = DORDER_MOVE; } /* Send attackers */ if(attackGroup.members > 0) { if(distBetweenTwoPoints(attackGroup.x, attackGroup.y, _defendX, _defendY) > defendRadius) { orderGroupLoc(attackGroup, defendMoveType, _defendX, _defendY); } } setEventTrigger(manageDefendLocationEv, manageDefendLocationTr); } function void stopDefendingLocation() { dbg("stopped defending location", me); defendX = -1; defendY = -1; tDefendStart = -1; tDefendTimeout = -1; defendMoveType = -1; setEventTrigger(manageDefendLocationEv, inactive); orderGroupLoc(attackGroup, DORDER_SCOUT,baseX,baseY); } function bool defendingLocation() { if(defendX > 0 and defendY > 0){ return TRUE; } return FALSE; } event manageDefendLocationEv(inactive) { local int defendRadius; local DROID _droid; if (not defendingLocation()) { exit; } defendRadius = 15 * TILE; dbg("manageDefendLocationEv", me); ASSERT(defendMoveType == DORDER_MOVE || defendMoveType == DORDER_SCOUT, "manageDefendLocationEv: wrong move order:" & defendMoveType, me); ASSERT(defendX > 0 && defendY > 0, "manageDefendLocationEv: x/y coordinates:" & defendX & "/" & defendY, me); /* Collect attackers */ initIterateGroup(attackGroup); _droid = iterateGroup(attackGroup); while(_droid != NULLOBJECT) { if(distBetweenTwoPoints(_droid.x,_droid.y,defendX,defendY) > defendRadius) //too far from defend location { if(distBetweenTwoPoints(_droid.orderx,_droid.ordery,defendX,defendY) > defendRadius) //not already on its way to the defend location { orderDroidLoc(_droid, defendMoveType, defendX, defendY); } } _droid = iterateGroup(attackGroup); } } function bool defendLocationTimeout() { if(tDefendTimeout < (gameTime / 10) ){ return TRUE; } return FALSE; } /* Returns true if player in question is my ally or if it's me */ function bool friendlyPlayer(int _playerToCheck) { if(allianceExistsBetween(_playerToCheck, me) or (_playerToCheck == me)){ return TRUE; } return FALSE; } function bool insideBase(int _x, int _y) { if(_x < minx){ return FALSE; } if(_x > maxx){ return FALSE; } if(_y < miny){ return FALSE; } if(_y > maxy){ return FALSE; } return TRUE; } event watchMenu(everySec) { if(_DEBUG) { if(vtolGrAttackObj[0] == NULLOBJECT){ setDebugMenuEntry("0 - " & vtolAttackGr[0].members, 0); }else{ setDebugMenuEntry("0 " & vtolAttackGr[0].members & " - " & (vtolGrAttackObj[0].x / TILE) & "-" & (vtolGrAttackObj[0].y / TILE), 0); } if(vtolGrAttackObj[1] == NULLOBJECT){ setDebugMenuEntry("1 - " & vtolAttackGr[1].members, 1); }else{ setDebugMenuEntry("1 " & vtolAttackGr[1].members & " - " & (vtolGrAttackObj[1].x / TILE) & "-" & (vtolGrAttackObj[1].y / TILE), 1); } if(vtolGrAttackObj[2] == NULLOBJECT){ setDebugMenuEntry("2 - " & vtolAttackGr[2].members, 2); }else{ setDebugMenuEntry("2 " & vtolAttackGr[2].members & " - " & (vtolGrAttackObj[2].x / TILE) & "-" & (vtolGrAttackObj[2].y / TILE), 2); } if(vtolGrAttackObj[3] == NULLOBJECT){ setDebugMenuEntry("3 - " & vtolAttackGr[3].members, 3); }else{ setDebugMenuEntry("3 " & vtolAttackGr[3].members & " - " & (vtolGrAttackObj[3].x / TILE) & "-" & (vtolGrAttackObj[3].y / TILE), 3); } if(vtolGrAttackObj[4] == NULLOBJECT){ setDebugMenuEntry("4 - " & vtolAttackGr[4].members, 4); }else{ setDebugMenuEntry("4 " & vtolAttackGr[4].members & " - " & (vtolGrAttackObj[4].x / TILE) & "-" & (vtolGrAttackObj[4].y / TILE), 4); } if(vtolGrAttackObj[5] == NULLOBJECT){ setDebugMenuEntry("5 - " & vtolAttackGr[5].members, 5); }else{ setDebugMenuEntry("5 " & vtolAttackGr[5].members & " - " & (vtolGrAttackObj[5].x / TILE) & "-" & (vtolGrAttackObj[5].y / TILE), 5); } if(vtolGrAttackObj[6] == NULLOBJECT){ setDebugMenuEntry("6 - " & vtolAttackGr[6].members, 6); }else{ setDebugMenuEntry("6 " & vtolAttackGr[6].members & " - " & (vtolGrAttackObj[6].x / TILE) & "-" & (vtolGrAttackObj[6].y / TILE), 6); } if(vtolGrAttackObj[7] == NULLOBJECT){ setDebugMenuEntry("7 - " & vtolAttackGr[7].members, 7); }else{ setDebugMenuEntry("7 " & vtolAttackGr[7].members & " - " & (vtolGrAttackObj[7].x / TILE) & "-" & (vtolGrAttackObj[7].y / TILE), 7); } if(vtolGrAttackObj[8] == NULLOBJECT){ setDebugMenuEntry("8 - " & vtolAttackGr[8].members, 8); }else{ setDebugMenuEntry("8 " & vtolAttackGr[8].members & " - " & (vtolGrAttackObj[8].x / TILE) & "-" & (vtolGrAttackObj[8].y / TILE), 8); } if(vtolGrAttackObj[9] == NULLOBJECT){ setDebugMenuEntry("9 - " & vtolAttackGr[9].members, 9); }else{ setDebugMenuEntry("9 " & vtolAttackGr[9].members & " - " & (vtolGrAttackObj[9].x / TILE) & "-" & (vtolGrAttackObj[9].y / TILE), 9); } if(vtolGrAttackObj[10] == NULLOBJECT){ setDebugMenuEntry("10 - " & vtolAttackGr[10].members, 10); }else{ setDebugMenuEntry("10 " & vtolAttackGr[10].members & " - " & (vtolGrAttackObj[10].x / TILE) & "-" & (vtolGrAttackObj[10].y / TILE), 10); } if(vtolGrAttackObj[11] == NULLOBJECT){ setDebugMenuEntry("11 - " & vtolAttackGr[11].members, 11); }else{ setDebugMenuEntry("11 " & vtolAttackGr[11].members & " - " & (vtolGrAttackObj[11].x / TILE) & "-" & (vtolGrAttackObj[11].y / TILE), 11); } if(vtolGrAttackObj[12] == NULLOBJECT){ setDebugMenuEntry("12 - " & vtolAttackGr[12].members, 12); }else{ setDebugMenuEntry("12 " & vtolAttackGr[12].members & " - " & (vtolGrAttackObj[12].x / TILE) & "-" & (vtolGrAttackObj[12].y / TILE), 12); } if(vtolGrAttackObj[13] == NULLOBJECT){ setDebugMenuEntry("13 - " & vtolAttackGr[13].members, 13); }else{ setDebugMenuEntry("13 " & vtolAttackGr[13].members & " - " & (vtolGrAttackObj[13].x / TILE) & "-" & (vtolGrAttackObj[13].y / TILE), 13); } if(vtolGrAttackObj[14] == NULLOBJECT){ setDebugMenuEntry("14 - " & vtolAttackGr[14].members, 14); }else{ setDebugMenuEntry("14 " & vtolAttackGr[14].members & " - " & (vtolGrAttackObj[14].x / TILE) & "-" & (vtolGrAttackObj[14].y / TILE), 14); } if(vtolGrAttackObj[15] == NULLOBJECT){ setDebugMenuEntry("15 - " & vtolAttackGr[15].members, 15); }else{ setDebugMenuEntry("15 " & vtolAttackGr[15].members & " - " & (vtolGrAttackObj[15].x / TILE) & "-" & (vtolGrAttackObj[15].y / TILE), 15); } if(vtolGrAttackObj[16] == NULLOBJECT){ setDebugMenuEntry("16 - " & vtolAttackGr[16].members, 16); }else{ setDebugMenuEntry("16 " & vtolAttackGr[16].members & " - " & (vtolGrAttackObj[16].x / TILE) & "-" & (vtolGrAttackObj[16].y / TILE), 16); } if(vtolGrAttackObj[17] == NULLOBJECT){ setDebugMenuEntry("17 - " & vtolAttackGr[17].members, 17); }else{ setDebugMenuEntry("17 " & vtolAttackGr[17].members & " - " & (vtolGrAttackObj[17].x / TILE) & "-" & (vtolGrAttackObj[17].y / TILE), 17); } if(vtolGrAttackObj[18] == NULLOBJECT){ setDebugMenuEntry("18 - " & vtolAttackGr[18].members, 18); }else{ setDebugMenuEntry("18 " & vtolAttackGr[18].members & " - " & (vtolGrAttackObj[18].x / TILE) & "-" & (vtolGrAttackObj[18].y / TILE), 18); } if(vtolGrAttackObj[19] == NULLOBJECT){ setDebugMenuEntry("19 - " & vtolAttackGr[19].members, 19); }else{ setDebugMenuEntry("19 " & vtolAttackGr[19].members & " - " & (vtolGrAttackObj[19].x / TILE) & "-" & (vtolGrAttackObj[19].y / TILE), 19); } if(vtolGrAttackObj[20] == NULLOBJECT){ setDebugMenuEntry("20 - " & vtolAttackGr[20].members, 20); }else{ setDebugMenuEntry("20 " & vtolAttackGr[20].members & " - " & (vtolGrAttackObj[20].x / TILE) & "-" & (vtolGrAttackObj[20].y / TILE), 20); } if(vtolGrAttackObj[21] == NULLOBJECT){ setDebugMenuEntry("21 - " & vtolAttackGr[21].members, 21); }else{ setDebugMenuEntry("21 " & vtolAttackGr[21].members & " - " & (vtolGrAttackObj[21].x / TILE) & "-" & (vtolGrAttackObj[21].y / TILE), 21); } if(vtolGrAttackObj[22] == NULLOBJECT){ setDebugMenuEntry("22 - " & vtolAttackGr[22].members, 22); }else{ setDebugMenuEntry("22 " & vtolAttackGr[22].members & " - " & (vtolGrAttackObj[22].x / TILE) & "-" & (vtolGrAttackObj[22].y / TILE), 22); } if(vtolGrAttackObj[23] == NULLOBJECT){ setDebugMenuEntry("23 - " & vtolAttackGr[23].members, 23); }else{ setDebugMenuEntry("23 " & vtolAttackGr[23].members & " - " & (vtolGrAttackObj[23].x / TILE) & "-" & (vtolGrAttackObj[23].y / TILE), 23); } if(vtolGrAttackObj[24] == NULLOBJECT){ setDebugMenuEntry("24 - " & vtolAttackGr[24].members, 24); }else{ setDebugMenuEntry("24 " & vtolAttackGr[24].members & " - " & (vtolGrAttackObj[24].x / TILE) & "-" & (vtolGrAttackObj[24].y / TILE), 24); } if(vtolGrAttackObj[25] == NULLOBJECT){ setDebugMenuEntry("25 - " & vtolAttackGr[25].members, 25); }else{ setDebugMenuEntry("25 " & vtolAttackGr[25].members & " - " & (vtolGrAttackObj[25].x / TILE) & "-" & (vtolGrAttackObj[25].y / TILE), 25); } if(vtolGrAttackObj[26] == NULLOBJECT){ setDebugMenuEntry("26 - " & vtolAttackGr[26].members, 26); }else{ setDebugMenuEntry("26 " & vtolAttackGr[26].members & " - " & (vtolGrAttackObj[26].x / TILE) & "-" & (vtolGrAttackObj[26].y / TILE), 26); } if(vtolGrAttackObj[27] == NULLOBJECT){ setDebugMenuEntry("27 - " & vtolAttackGr[27].members, 27); }else{ setDebugMenuEntry("27 " & vtolAttackGr[27].members & " - " & (vtolGrAttackObj[27].x / TILE) & "-" & (vtolGrAttackObj[27].y / TILE), 27); } if(vtolGrAttackObj[28] == NULLOBJECT){ setDebugMenuEntry("28 - " & vtolAttackGr[28].members, 28); }else{ setDebugMenuEntry("28 " & vtolAttackGr[28].members & " - " & (vtolGrAttackObj[28].x / TILE) & "-" & (vtolGrAttackObj[28].y / TILE), 28); } if(vtolGrAttackObj[29] == NULLOBJECT){ setDebugMenuEntry("29 - " & vtolAttackGr[29].members, 29); }else{ setDebugMenuEntry("29 " & vtolAttackGr[29].members & " - " & (vtolGrAttackObj[29].x / TILE) & "-" & (vtolGrAttackObj[29].y / TILE), 29); } if(vtolGrAttackObj[30] == NULLOBJECT){ setDebugMenuEntry("30 - " & vtolAttackGr[30].members, 30); }else{ setDebugMenuEntry("30 " & vtolAttackGr[30].members & " - " & (vtolGrAttackObj[30].x / TILE) & "-" & (vtolGrAttackObj[30].y / TILE), 30); } if(vtolGrAttackObj[31] == NULLOBJECT){ setDebugMenuEntry("31 - " & vtolAttackGr[31].members, 31); }else{ setDebugMenuEntry("31 " & vtolAttackGr[31].members & " - " & (vtolGrAttackObj[31].x / TILE) & "-" & (vtolGrAttackObj[31].y / TILE), 31); } if(vtolGrAttackObj[32] == NULLOBJECT){ setDebugMenuEntry("32 - " & vtolAttackGr[32].members, 32); }else{ setDebugMenuEntry("32 " & vtolAttackGr[32].members & " - " & (vtolGrAttackObj[32].x / TILE) & "-" & (vtolGrAttackObj[32].y / TILE), 32); } if(vtolGrAttackObj[33] == NULLOBJECT){ setDebugMenuEntry("33 - " & vtolAttackGr[33].members, 33); }else{ setDebugMenuEntry("33 " & vtolAttackGr[33].members & " - " & (vtolGrAttackObj[33].x / TILE) & "-" & (vtolGrAttackObj[33].y / TILE), 33); } if(vtolGrAttackObj[34] == NULLOBJECT){ setDebugMenuEntry("34 - " & vtolAttackGr[34].members, 34); }else{ setDebugMenuEntry("34 " & vtolAttackGr[34].members & " - " & (vtolGrAttackObj[34].x / TILE) & "-" & (vtolGrAttackObj[34].y / TILE), 34); } if(vtolGrAttackObj[35] == NULLOBJECT){ setDebugMenuEntry("35 - " & vtolAttackGr[35].members, 35); }else{ setDebugMenuEntry("35 " & vtolAttackGr[35].members & " - " & (vtolGrAttackObj[35].x / TILE) & "-" & (vtolGrAttackObj[35].y / TILE), 35); } if(vtolGrAttackObj[36] == NULLOBJECT){ setDebugMenuEntry("36 - " & vtolAttackGr[36].members, 36); }else{ setDebugMenuEntry("36 " & vtolAttackGr[36].members & " - " & (vtolGrAttackObj[36].x / TILE) & "-" & (vtolGrAttackObj[36].y / TILE), 36); } if(vtolGrAttackObj[37] == NULLOBJECT){ setDebugMenuEntry("37 - " & vtolAttackGr[37].members, 37); }else{ setDebugMenuEntry("37 " & vtolAttackGr[37].members & " - " & (vtolGrAttackObj[37].x / TILE) & "-" & (vtolGrAttackObj[37].y / TILE), 37); } if(vtolGrAttackObj[38] == NULLOBJECT){ setDebugMenuEntry("38 - " & vtolAttackGr[38].members, 38); }else{ setDebugMenuEntry("38 " & vtolAttackGr[38].members & " - " & (vtolGrAttackObj[38].x / TILE) & "-" & (vtolGrAttackObj[38].y / TILE), 38); } if(vtolGrAttackObj[39] == NULLOBJECT){ setDebugMenuEntry("39 - " & vtolAttackGr[39].members, 39); }else{ setDebugMenuEntry("39 " & vtolAttackGr[39].members & " - " & (vtolGrAttackObj[39].x / TILE) & "-" & (vtolGrAttackObj[39].y / TILE), 39); } /* setDebugMenuEntry("total " & countRebuildStruct, 0); setDebugMenuEntry("x1=" & rebuildStructX[0], 1); setDebugMenuEntry("y1=" & rebuildStructY[0], 2); setDebugMenuEntry("x2=" & rebuildStructX[1], 3); setDebugMenuEntry("y2=" & rebuildStructY[1], 4); setDebugMenuEntry("x3=" & rebuildStructX[2], 5); setDebugMenuEntry("y3=" & rebuildStructY[2], 6); setDebugMenuEntry("x4=" & rebuildStructX[3], 7); setDebugMenuEntry("y4=" & rebuildStructY[3], 8);*/ } } //--------------------------------------------------------------- //Returns how many droids are already on the way to build the //same structure on the same spot (like helpbuild) //--------------------------------------------------------------- function int numBuildSameBuilding(STRUCTURESTAT _checkStat, int _x, int _y) { local int _numSameBuilding; local DROID _truck; _numSameBuilding = 0; initIterateGroup(buildGroup); _truck = iterateGroup(buildGroup); while(_truck != NULLOBJECT) { if((_truck.order == DORDER_BUILD) or (_truck.order == DORDER_HELPBUILD) or (_truck.order == DORDER_LINEBUILD)) { if((_checkStat == NULLSTRUCTURESTAT) or (_truck.stat == _checkStat)) //Same struct type { //Within some range if((_x < 0) or (distBetweenTwoPoints(_x, _y, _truck.orderx , _truck.ordery) <= TILE)) { _numSameBuilding++; } } } _truck = iterateGroup(buildGroup); } return _numSameBuilding; } // returns number of droids in a certain group with the same order function int numGroupSameOrder(GROUP _group, int _orderIndex) { local int _numDroids; local DROID _droid; _numDroids = 0; initIterateGroup(_group); _droid = iterateGroup(_group); while(_droid != NULLOBJECT) { if(_droid.order == _orderIndex) //right order type { _numDroids++; } _droid = iterateGroup(_group); } return _numDroids; } // Remember certain destroyed structures so we can rebuild them later event structureDestroyed(structureDestroyedTr) { local int _count; // add certain structures to the rebuild list _count = 0; while(_count < numRebuildStat[curTech]) { if(structure.stat == rebuildStat[curTech][_count]) { if(countRebuildStruct < MAX_REBUILD_STRUCT) { rebuildStructX[countRebuildStruct] = structure.x; rebuildStructY[countRebuildStruct] = structure.y; rebuildStructStat[countRebuildStruct] = structure.stat; countRebuildStruct++; dbg("remembered structure (" & countRebuildStruct & ") - " & structure.x & "/" & structure.y, me); exit; } } _count++; } } // Rebuild structures that were destroyed event rebuildStructureEv(rebuildStructureTr) { rebuildStructures(); } function void rebuildStructures() { local int _count,_threatRange,_x,_y; local DROID _truck; local STRUCTURESTAT _stat; _threatRange = (TILE * 8); _count = 0; while(_count < countRebuildStruct) { if(!threatInRange(me, rebuildStructX[_count], rebuildStructY[_count], _threatRange, FALSE)) { if(getTileStructure(_x / TILE, _y / TILE) == NULLOBJECT) { _stat = rebuildStructStat[_count]; _x = rebuildStructX[_count]; _y = rebuildStructY[_count]; if (isStructureAvailable(_stat, me)) { _truck = closestIdleTruck(_x, _y); if (_truck != NULLOBJECT) { if (numBuildSameBuilding(_stat, _x, _y) == 0) //make sure no one is building already { buildOnExactLocation(_truck, _x, _y, _stat); } } } } } _count++; } } function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat) { local int _newX,_newY; if(_truck == NULLOBJECT) { return; } _newX = _x; _newY = _y; if (pickDroidStructLocation(_truck, _stat, ref _newX, ref _newY, me, -1)) { dbg("trying to rebuild on (" & _newX & "/" & _newY & ")", me); if ((_x != _newX) or (_y != _newY)) { return; } orderDroidStatsLoc(_truck, DORDER_BUILD, _stat, _x, _y); //dbg("rebuilding structure after!! (" & _x & "/" & _y & ")", me); } } // Get idle truck closest to some location function DROID closestIdleTruck(int _x, int _y) { local DROID _closestTruck, _tempTruck; local int _closestDist, _tempDist; _closestTruck = NULLOBJECT; _closestDist = 99999; initIterateGroup(buildGroup); _tempTruck = iterateGroup(buildGroup); while(_tempTruck != NULLOBJECT) { if((_tempTruck.order == DORDER_NONE) or (_tempTruck.order == DORDER_RTB)) { _tempDist = distBetweenTwoPoints(_x, _y, _tempTruck.x, _tempTruck.y); if(_tempDist < _closestDist) { _closestDist = _tempDist; _closestTruck = _tempTruck; } } _tempTruck = iterateGroup(buildGroup); } return _closestTruck; } event consoleEv(consoleTr) { //turn on 'autogame' if(message == "autogame on" && (sender == me)) { if(debugModeEnabled()) { if(myResponsibility(me)) { if(not bRunning) //make sure current machine is responsible for this AI and it's not already active { console(getPlayerName(me) & " is active"); reassignAI(); setEventTrigger(startLevel, chainloadTr); } } } } //turn off 'autogames' if(message == "autogame off" && debugModeEnabled() && (sender == me)) { if(bRunning) //make sure this AI is active { console(getPlayerName(me) & " is deactivated"); shutDownAI(); } } if(message == "aidebug on") { console(getPlayerName(me) & " ai debug is on"); _DEBUG = TRUE; dbgMsgOn(me, _DEBUG); } else if(message == "aidebug off") { console(getPlayerName(me) & " ai debug is off"); _DEBUG = FALSE; dbgMsgOn(me, _DEBUG); } }
Encontrar la diferencia