1
/////////////////////////////////////////////////////////////////////
2
// general ai for skirmish game
3
/////////////////////////////////////////////////////////////////////
4
// Warzone2100, Pumpkin Studios,
7
/////////////////////////////////////////////////////////////////////
13
// These are final rules of the lexical parser
14
#define R_REQUEST_HELP "help me"
15
#define R_REQUEST_BEACON "drop a beacon"
16
#define R_REPORT_SAFETY "i'm ok"
17
#define R_REQUEST_ALLY "ally me"
19
// These are our own messages - lexical parser should be able to handle them
20
#define M_REQUEST_HELP "help me!!"
21
#define M_REQUEST_BEACON "drop a beacon"
22
#define M_AFFIRMATIVE_OK "ok"
23
#define M_AFFIRMATIVE_ROGER "roger"
24
#define M_ANNOYED "bug off"
25
#define M_HELPERS_KILLED "that was all I had.."
26
#define M_HELP_NO_UNITS "I don't have anything"
28
#define MAX_PROBABILITY 100
30
// Base threat range in world units
31
#define W_BASE_THREAT_RANGE ((17 + (mapWidth + mapHeight) / 2 / 35) * TILE)
35
#define BASE_DEFEND_DURATION (3 * 60)
36
#define BASE_DEFEND_RADIUS (15 * TILE)
38
// Delay before we repeat our request, in seconds
39
#define HELP_REQUEST_INTERVAL (3 * 60)
42
#define BEACON_TIMEOUT 30
44
#define MAX_DROIDS 150
46
//range for trucks to look for more oil
47
#define MORE_OIL_RANGE (10 * TILE)
48
//don't try to build on oil if there's threat within this range
49
#define OIL_THREAT_RANGE (9 * TILE)
54
//Enter power saving mode when lower than this
58
#define NO_TARGET_VALUE 0
59
#define DROID_TARGET_VALUE 1
60
#define OTHER_TARGET_VALUE 2
61
#define DEFENSE_TARGET_VALUE 3
62
#define RESEARCH_TARGET_VALUE 4
63
#define HQ_TARGET_VALUE 5
64
#define OIL_TARGET_VALUE 6
65
#define FACTORY_TARGET_VALUE 7
67
#define UNLIMITED (-1)
69
#define AA_THREAT_RANGE (TILE * 12)
71
#define MAX_DEFENDERS_RADIUS (TILE * 40)
73
#define MAX_VTOL_DEFEND_RADIUS (TILE * 25)
75
// AI will remember max this number of structures
76
#define MAX_REBUILD_STRUCT 100
78
//Total number of technology branches
81
//How many best templates to choose from when deciding what template to build
82
#define MAX_RANDOM_TEMPLATES 4
86
public int me; // player for this instance.
87
public int tileExpand; // rate of exploration
89
public int numScouts[TECHS],maxScouts[TECHS]; // aim for...
90
public int numDefenders[TECHS],maxDefenders[TECHS];
91
public int numAttackers[TECHS],maxAttackers[TECHS];
92
public int numCyborgs[TECHS],maxCyborgs[TECHS];
94
public int branchDefault,branchVTOL,techCount[TECHS],maxVtolFacs[TECHS],maxIdleRes[TECHS],
95
maxVTOLs[TECHS],numVtolTargets,vtolTargetWeight[10],numRebuildStat[TECHS];
96
public RESEARCHSTAT tech[TECHS][30]; //technology for different research branches
97
public STRUCTURESTAT vtolTarget[10],rebuildStat[TECHS][2];
100
private int baseX,baseY,minx,miny,maxx,maxy;
101
public int numStructs,numIncendrys,numDefStructs,numExtraStructs[TECHS],numWallWeaps,numBaseStruct,numLightCyborgs;
102
public STRUCTURESTAT incendrys[8],structs[13],defStructs[26],extraStructs[TECHS][6],structChoice[5],wallWeaps[11];
103
public STRUCTURESTAT sensorTower,wall,cornerWall,resLab,powGen,playerHQ,lassat,factory,derrick,cybFactory,
104
vtolDefStruct[5],vtolPad,vtolFactory,repairFacility,uplink,baseStruct[8];
105
public STRUCTURESTAT powModule,facModule,resModule,vtolModule;
106
public int extraStruct;
109
public int numTemplates[TECHS];
110
public TEMPLATE tmpl[TECHS][70];
111
private TEMPLATE tmplChoice[5];
113
public TEMPLATE cybTempl[10],superCyb[4],cybMechanic,cybEngineer;
115
public TEMPLATE vtols[18];
116
public int numVtolTemplates;
118
public TEMPLATE sense[11];
119
public int numSenseTemplates;
121
public TEMPLATE constructor,repairUnit;
122
public int numRepairUnits;
125
private GROUP defendGroup;
126
private bool defendbusy;
127
private BASEOBJ defendObj;
129
public RESEARCHSTAT nexusDefence;
132
private GROUP buildGroup;
133
private int buildX,buildY,buildX2,buildY2;
134
public FEATURESTAT oilRes;
137
private GROUP scoutGroup;
138
private int scoutX,scoutY;
139
private int scoutTLX,scoutTLY,scoutW,scoutH;
142
private GROUP attackGroup;
143
private BASEOBJ attackObj,allOutAttack,vtolGrAttackObj[10];
146
private GROUP vtolDefendGr,vtolAttackGr[10];
149
private STRUCTURE structure,structure2,rebuildObj[100];
151
private FEATURE feature;
152
private BASEOBJ baseobj,baseobj2;
153
private int count,count2,result,result2,tempx,tempy;
154
private bool boolResult,boolResult2;
156
private bool powerSave,_DEBUG,bRunning;
157
private int allianceTime[8];
158
private int sender,x,y,beaconX[8],beaconY[8],tBeacon[8],
159
tLastHelpRequest,lastHelpPlayer,tHelp,tHelpTimeout,helpX,helpY;
160
private string message;
162
private int defendX,defendY,defendRadius,tDefendStart,tDefendTimeout,
163
defendMoveType,baseRange,curTech,numVtolAttackGroups,numAttackVtols,
164
numDefendVtols,rebuildStructX[MAX_REBUILD_STRUCT],rebuildStructY[MAX_REBUILD_STRUCT],countRebuildStruct;
165
private STRUCTURESTAT rebuildStructStat[MAX_REBUILD_STRUCT];
167
/////////////////////////////////////////////////////////////////////
171
trigger buildExpandTr (every, 600);
172
trigger fortifyTr (every, 1000);
173
trigger upgradeStructuresTr (every, 400 );
174
trigger conDroidsTr (every, 900); // was 1400
175
trigger repairDroidsTr (every, 2600);
176
trigger managePowerTr (every, 1500);
177
trigger basedetailsTr (every, 600 );
178
trigger buildDerrickTr (every, 80 );
179
trigger buildOilDefenseOrRetreatTr (every, 120 );
180
trigger incendryTr (every, 250 );
181
trigger buildPowerGeneratorsTr (every, 80 );
182
trigger buildBaseTr (every, 150 );
183
trigger finishStructsTr (every, 400 );
184
trigger droidBuiltTr (CALL_NEWDROID,me, ref droid,ref structure);
185
trigger structBuiltTr (CALL_STRUCTBUILT, me, ref droid, ref structure);
186
trigger droidDestroyedTr (CALL_DROID_DESTROYED, me, ref droid);
187
trigger structureDestroyedTr (CALL_STRUCT_DESTROYED, me, ref structure);
188
trigger rebuildStructureTr (every, 50);
189
trigger consolidateEventTr (every, 3100);
190
trigger factoryEventTr (every, 170 );
191
trigger cyborgFactoryEventTr (every, 170 );
192
trigger chooseScoutAreaTr (every, 200 );
193
trigger expandScoutAreaTr (every, 600 );
194
trigger scoutMainTr (every, 150 );
195
trigger newObjectReportTr (CALL_OBJ_SEEN, me, ref baseobj, ref baseobj2);
196
trigger attackStuffTr (every, 300 );
197
trigger allOutAttackTr (every, 4000);
198
trigger defendWatchTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
199
trigger defendReturnTr (every, 500 );
200
trigger doResearchTr (every, 400 );
201
trigger vtolDefendTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
202
trigger vtolStructsTr (every, 290);
203
trigger buildVtolsTr (every, 360);
204
trigger vtolAttackTr (every, 150);
205
trigger vtolEnablerTr (every, 700);
206
trigger takeoverTr (CALL_UNITTAKEOVER, ref droid);
207
trigger useLassatTr (every, 3000);
208
trigger reassignTr (CALL_PLAYERLEFT,ref count);
209
trigger formAllianceEventTr (every,170);
210
trigger breakAllianceEventTr (every,3000);
211
trigger difficultyModifierTr (every,600);
212
trigger humanAllianceTr (CALL_ALLIANCEOFFER,ref count, ref count2);
213
trigger multiMsgTr (CALL_AI_MSG, me, ref sender, ref message);
214
trigger beaconTr (CALL_BEACON, me, ref sender, ref x, ref y, ref message);
215
trigger consoleTr (CALL_CONSOLE, ref sender, ref message);
216
trigger watchBaseThreatTr (every, 120);
217
trigger manageAllyHelpTr (every, 80);
218
trigger everySec (every, 10);
219
trigger manageDefendLocationTr (every, 70);
224
event watchBaseThreat;
225
event manageAllyHelp;
227
event manageDefendLocationEv;
228
event structureDestroyed;
229
event rebuildStructureEv;
231
/* Function prototypes */
232
function bool haveBeacon(int _player);
233
function bool beaconTimeout(int _player);
234
function void processCommand(string _message, int _sender, bool _bBlipMessage);
235
function bool haveHelpers();
236
function bool attemptToHelp(int _playerToHelp, int _x, int _y);
237
function void helpPlayer(int _playerToHelp, int _helpX, int _helpY);
238
function bool canStopHelpingAlly();
239
function void stopHelpingAlly();
240
function bool helpingAlly();
241
function bool helpAllyTimeout();
242
function void requestHelp(int _helpX, int _helpY);
243
function void doRequestHelp(int _helpX, int _helpY);
244
function bool allyBaseAtLoc(int _ally, int _x, int _y);
245
function void messagePlayer(int _playerToMessage, string _message, int _probability);
246
function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message);
247
function bool canSeeAllies();
248
function bool baseInTrouble();
249
function string m_affirmative();
250
function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, int _defendRadius, bool _bMove);
251
function void stopDefendingLocation();
252
function bool defendingLocation();
253
function bool defendLocationTimeout();
254
function bool friendlyPlayer(int _playerToCheck);
255
function void factoryBuildDroid(STRUCTURE _factory);
256
function void cybFactorBuildCyborg(STRUCTURE _factory);
257
function void vtolFactoryBuildVtol(STRUCTURE _factory);
258
function bool insideBase(int _x, int _y);
259
function FEATURE closestOil(int _x, int _y, bool _bAvoidThreat);
260
function int numAlliesInBase(bool _bVtols);
261
function int numEnemiesInBase(bool _bVtols);
262
function bool defendingOwnBase();
263
function int targetTypeValue(BASEOBJ _target);
264
function int numBitsSet(int _integer);
265
function int findResearch(int _searchStart, int _techTree);
266
function bool upgradeFactory(DROID _truck, int _maxBuilders);
267
function bool upgradeVtolFactory(DROID _truck, int _maxBuilders);
268
function bool upgradeResearch(DROID _truck, int _maxBuilders);
269
function bool upgradePowGen(DROID _truck, int _maxBuilders);
270
function void buildRearmPads();
271
function int numEnemyAAInRange(int _x, int _y, int _range);
272
function BASEOBJ chooseVtolTarget(bool bExclusiveTarget);
273
function int getVtolTargetWeight(BASEOBJ _target);
274
function bool vtolTargetAssigned(BASEOBJ _target);
275
function void buildTruck();
276
function int numBuildSameBuilding(STRUCTURESTAT _checkStat, int _x, int _y);
277
function void expandBase(DROID _truck);
278
function int totalVtols();
279
function bool needTank();
280
function void setTechBranch(int _tech);
281
function DROID closestIdleTruck(int _x, int _y);
282
function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat);
283
function void rebuildStructures();
284
function BASEOBJ chooseVtolDefenceTarget(int _x, int _y, int _range, bool bExclusiveTarget);
285
function int numGroupSameOrder(GROUP _group, int _orderIndex);
286
function void rearrangeAttackVtols();
287
function int numStructBusyByType(STRUCTURESTAT _busyStructType);
288
function bool aiResponsibleForPlayer(int _player);
289
function void reassignAI();
290
function void shutDownAI();
291
function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly);
292
function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly);
295
/////////////////////////////////////////////////////////////////////
297
event initialisedEvent(CALL_GAMEINIT)
301
dbgMsgOn(me, _DEBUG);
305
allOutAttack = NULLOBJECT;
308
tLastHelpRequest = -1; //when we requested help for the last time
310
lastHelpPlayer = -1; //we are not currently helping anyone
311
tHelp = -1; //when we started helping last time
312
tHelpTimeout = -1; //time when help times out
321
defendMoveType = -1; //move or scout
323
baseRange = 4 * TILE;
325
// set current research branch
327
//setTechBranch(branchVTOL);
329
numVtolAttackGroups = 10;
330
numAttackVtols = 10; //num vtols in an attack group
331
numDefendVtols = 5; //num vtols in an attack group
334
//all initial droids are in buildgroup!
335
groupAddArea(buildGroup, me, 0, 0, (mapWidth*128), (mapHeight*128));
336
initGetFeature(oilRes,me,me); // use bucket = player
338
// note where our base is.
339
initIterateGroup(buildGroup); // find idle droids in build group.
340
droid = iterateGroup(buildGroup);
341
if(droid != NULLOBJECT)
346
if(aiResponsibleForPlayer(me))
353
baseX = (128*mapWidth)/2;
354
baseY = (128*mapHeight)/2;
361
structure = getStructure(factory, me);
362
if(structure != NULLOBJECT)
364
scoutTLX = structure.x;
365
scoutTLY = structure.y;
377
// clear the alliance array...
389
if(aiResponsibleForPlayer(me))
400
// decide what technology branch we will use
401
function void setTechBranch(int _tech)
403
local float _y2,_y1,_x2,_x1,_a,_y,_m,_rnd,_mapSize;
405
_mapSize = (float)((mapWidth + mapHeight) / 2);
413
//probability to choose vtol branch for map size 90 = 0; probability for map size 200 = 45
414
//build a linear function: y = ((y2 - y1) / (x2 - x1)) * x + a depending on two values given (short: y = mx+a)
415
_x1 = 90.0; _y1 = 0.0;
416
_x2 = 200.0; _y2 = 45.0;
417
_m = ((_y2 - _y1) / (_x2 - _x1));
420
//calculate probability for the current map
421
_y = _m * _mapSize + _a;
423
dbg("_m = " & _m & ", a = " & _a, me);
425
_rnd = (float)random(100);
428
curTech = branchVTOL;
429
dbg("going air (" & _y & "/" & _rnd & ")", me);
433
curTech = branchDefault;
434
dbg("going land (" & _y & "/" & _rnd & ")", me);
439
/* returns TRUE if AI is responsible for the _player */
440
function bool aiResponsibleForPlayer(int _player)
442
if(not _DEBUG and ((_player == selectedPlayer) or not myResponsibility(_player)))
450
/////////////////////////////////////////////////////////////////////
451
// initial force setup thing. plonk down a force.
452
event givehelp(every, 100)
455
if(multiPlayerBaseType == CAMP_WALLS)
461
/* structure = getStructure(factory, me);
462
if(structure != NULLOBJECT)
471
boolResult = pickStructLocation(defStructs[0], ref tempx, ref tempy,me);
472
if(boolResult == TRUE)
474
droid = addDroid(tmpl[curTech][ random(6) ] , tempx, tempy, me);
481
setEventTrigger(givehelp, inactive);
485
/////////////////////////////////////////////////////////////////////
486
// keep details about the size and postion of the ai players base
487
event basedetails(basedetailsTr)
490
// clear old extremities.
493
miny = (mapHeight*128);
494
minx = (mapWidth*128);
496
baseRange = 4 * TILE;
498
// now find the extremities of our vital structures.
500
while(count < numBaseStruct)
502
initEnumStruct(FALSE,baseStruct[count],me,me);
503
structure= enumStruct();
504
while(structure != NULLOBJECT)
506
if(structure.x < minx)
510
if(structure.x > maxx)
514
if(structure.y < miny)
518
if(structure.y > maxy)
523
result = distBetweenTwoPoints(baseX, baseY, structure.x, structure.y);
525
if(result > baseRange){
529
structure= enumStruct();
536
minx = minx - result;
537
maxx = maxx + result;
538
miny = miny - result;
539
maxy = maxy + result;
541
baseRange = baseRange + (4 * 128);
544
/////////////////////////////////////////////////////////////////////
545
// structure building rules
547
// build derricks on oil.
548
event buildDerrick(buildDerrickTr)
551
feature = getFeature(me); // find unoccupied oil resource.
552
if(feature != NULLOBJECT)
557
// if no more than 2 units already trying to build
558
initIterateGroup(buildGroup); // find all units in build group.
559
droid = iterateGroup(buildGroup);
561
while(droid != NULLOBJECT)
563
if((droid.orderx == buildX) and (droid.ordery == buildY))
567
droid = iterateGroup(buildGroup);
572
initIterateGroup(buildGroup); // find all units in build group.
573
droid = iterateGroup(buildGroup);
574
boolResult = FALSE; // only send 1 droid to each derrick
575
while( (boolResult == FALSE) and (droid != NULLOBJECT) )
577
if( (droid.order == DORDER_NONE) or (droid.order == DORDER_RTB))
579
orderDroidStatsLoc(droid, DORDER_BUILD,derrick, buildX,buildY); //build a derick
582
droid = iterateGroup(buildGroup);
586
else // feature is null
588
initGetFeature(oilRes,me,me); // start again next time.
592
/////////////////////////////////////////////////////////////////////
593
// if idle and derrick in range and no defense then build defense, else ret to base .
594
event buildOilDefenseOrRetreat(buildOilDefenseOrRetreatTr)
596
local int _numBuilders,_maxBuilders;
602
initIterateGroup(buildGroup); // find idle droids in build group.
603
droid = iterateGroup(buildGroup);
604
while(droid != NULLOBJECT)
606
if(droid.order == DORDER_NONE)
608
// if in range of a derrick
609
structure = structureBuiltInRange(derrick, droid.x, droid.y, (5*128), me);
611
// if inside base limits then presume ok..
612
if( structure != NULLOBJECT)
614
if((structure.x > minx) and (structure.y > miny) and (structure.x < maxx) and (structure.y <maxy))
616
structure = NULLOBJECT;
620
if(structure != NULLOBJECT)
622
buildX = structure.x;
623
buildY = structure.y;
625
count = 0; // if derrick has no defense near it.
627
while(count < numDefStructs)
629
structure = structureBuiltInRange(defStructs[count], buildX, buildX,(3*128), me);
630
if(structure != NULLOBJECT)
632
result = result + 1; // found a defense.
637
// not many defenses nearby
640
count = numDefStructs - 1; //pick a struct to build..
642
while( (count2 < 5) and (count >= 0) )
644
if( isStructureAvailable(defStructs[count],me))
647
// don't build multiple sensors together.
650
structure = structureBuiltInRange(defStructs[count], buildX, buildY,(6*128), me);
651
if(structure != NULLOBJECT)
657
structChoice[count2] = defStructs[count];
666
count = random(count2); //count = choice!
669
boolResult = pickStructLocation(structChoice[count], ref buildX, ref buildY,me);
671
_numBuilders = numBuildSameBuilding(NULLSTRUCTURESTAT, buildX, buildY);
673
if((boolResult == TRUE) and (_numBuilders < _maxBuilders))
676
orderDroidStatsLoc(droid, DORDER_BUILD,structChoice[count], buildX,buildY);
683
structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me);
684
if(structure == NULLOBJECT)
686
if(!insideBase(droid.x, droid.y))
688
orderDroid(droid,DORDER_RTB); // return to base;
695
structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me);
696
if(structure == NULLOBJECT)
698
if(!insideBase(droid.x, droid.y))
700
orderDroid(droid,DORDER_RTB); // return to base;
705
droid = iterateGroup(buildGroup);
709
/////////////////////////////////////////////////////////////////////
710
//mortar etc.. rules. build sensor towers and emplacements.
711
event incendry(incendryTr)
714
initEnumStruct(FALSE,sensorTower,me,me);
717
structure = enumStruct();
718
while(structure != NULLOBJECT)
721
structure = enumStruct();
724
if(count < (gameTime/4200) ) // every 7 mins
726
// if not found build a sensor tower.
727
// find a place to build.
730
initEnumStruct(FALSE,derrick,me,me);
731
structure= enumStruct();
732
while(structure != NULLOBJECT)
736
while(count < numDefStructs)
738
structure2 = structureBuiltInRange(defStructs[count], structure.x, structure.y,(4*128), me);
739
if(structure2 != NULLOBJECT)
746
// check for sensor nearby,
747
structure2 = structureBuiltInRange(sensorTower, structure.x, structure.y,(5*128), me);
748
if(structure2 != NULLOBJECT)
755
buildX = structure.x;
756
buildY = structure.y;
757
structure = NULLOBJECT;
761
structure = enumStruct();
767
boolResult = pickStructLocation(sensorTower, ref buildX, ref buildY,me); // pick spot.
768
if(boolResult == TRUE)
771
initIterateGroup(buildGroup);
772
droid = iterateGroup(buildGroup);
773
while(droid != NULLOBJECT)
775
if(droid.order == DORDER_NONE or droid.order == DORDER_RTB)
777
orderDroidStatsLoc(droid, DORDER_BUILD,sensorTower, buildX,buildY);
782
droid = iterateGroup(buildGroup);
790
// find a sensor tower with least incencdry structs around it..
794
initEnumStruct(FALSE,sensorTower,me,me);
795
structure= enumStruct();
797
while(structure != NULLOBJECT)
799
// count incendrys near this tower.
802
while(count2 < numIncendrys)
804
structure2 = structureBuiltInRange(incendrys[count2], structure.x, structure.y,(4*128), me);
805
if(structure2 != NULLOBJECT)
812
if((result < 6) and (result < count)) // lowest found yet. only sites with <6 too.
814
buildX = structure.x;
815
buildY = structure.y;
818
structure = enumStruct();
825
count = numIncendrys - 1;
829
if(isStructureAvailable(incendrys[count],me))
841
// find a unit and build an incendry device.
844
boolResult = pickStructLocation(incendrys[result], ref buildX, ref buildY,me); // pick spot.
845
if(boolResult == TRUE)
847
initIterateGroup(buildGroup);
848
droid = iterateGroup(buildGroup);
850
boolResult = (numBuildSameBuilding(incendrys[result], buildX, buildY) > 0); //anyone building there already?
852
while(droid != NULLOBJECT and (not boolResult))
854
if(droid.order == DORDER_NONE or droid.order == DORDER_RTB)
856
orderDroidStatsLoc(droid, DORDER_BUILD,incendrys[result], buildX,buildY);
857
boolResult = TRUE; //only 1 truck
859
droid = iterateGroup(buildGroup);
872
/////////////////////////////////////////////////////////////////////
873
// build a power gen for every 4 derricks. VITAL!
874
event buildPowerGenerators(buildPowerGeneratorsTr)
877
initEnumStruct(FALSE,derrick,me,me); // count = numderricks
878
structure= enumStruct();
880
while(structure != NULLOBJECT)
883
structure= enumStruct();
886
initEnumStruct(FALSE,powGen,me,me); // count2 = numpowgens
887
structure= enumStruct();
889
while(structure != NULLOBJECT)
892
structure= enumStruct();
895
if( (count2 * 4) < count ) // if we need powergen
897
buildX = baseX; // try build powergen.
899
boolResult = pickStructLocation(powGen, ref buildX, ref buildY,me);
900
if(boolResult == TRUE)
902
initIterateGroup(buildGroup);
903
droid = iterateGroup(buildGroup);
904
while(droid != NULLOBJECT)
906
if(droid.order == DORDER_NONE or droid.order == DORDER_RTB)
908
orderDroidStatsLoc(droid, DORDER_BUILD,powGen, buildX,buildY);
910
droid = iterateGroup(buildGroup);
918
/////////////////////////////////////////////////////////////////////
919
// ensure we have everything in the vital structs list.
920
event buildBase(buildBaseTr)
922
local int _numBuilders,_maxBuilders;
925
if( idleGroup(buildGroup) >= (buildGroup.members/2) )
928
while(count < numStructs)
930
// check that struct.
931
structure = getStructure(structs[count],me);
932
if(structure == NULLOBJECT) // if missing build it.
934
if(isStructureAvailable(structs[count],me))
936
buildX = baseX; // pick a location
938
boolResult = pickStructLocationB(structs[count], ref buildX, ref buildY,me,0);
939
if(boolResult == TRUE)
942
_numBuilders = numBuildSameBuilding(structs[count], buildX, buildY);
944
initIterateGroup(buildGroup); // find idle droids in build group.
945
droid = iterateGroup(buildGroup);
946
while((droid != NULLOBJECT) and (_numBuilders < _maxBuilders))
948
if((droid.order == DORDER_NONE) or (droid.order == DORDER_RTB))
950
orderDroidStatsLoc(droid, DORDER_BUILD,structs[count], buildX,buildY); // build it
953
droid = iterateGroup(buildGroup);
963
/////////////////////////////////////////////////////////////////////
964
// build other stuff, grow the base slowly...
965
event buildExpand( buildExpandTr )
967
expandBase(NULLOBJECT);
970
function void expandBase(DROID _truck)
972
local int _numBuilders,_maxBuilders;
974
if(extraStruct == numExtraStructs[curTech]) // loop round
979
if(isStructureAvailable(extraStructs[curTech][extraStruct],me))
981
buildX = baseX; // pick a location
983
boolResult = pickStructLocationB(extraStructs[curTech][extraStruct], ref buildX, ref buildY,me,0);
985
if(boolResult == TRUE)
987
_numBuilders = numBuildSameBuilding(extraStructs[curTech][extraStruct], buildX, buildY);
990
if(_truck != NULLOBJECT)
992
if((_truck.order != DORDER_BUILD) and (_truck.order != DORDER_LINEBUILD))
994
orderDroidStatsLoc(_truck, DORDER_BUILD,extraStructs[curTech][extraStruct], buildX,buildY);// build it.
1000
initIterateGroup(buildGroup); // find idle droids in build group.
1001
droid = iterateGroup(buildGroup);
1002
while((droid != NULLOBJECT) and (_numBuilders < _maxBuilders))
1004
if((droid.order != DORDER_BUILD) and (droid.order != DORDER_LINEBUILD))
1006
orderDroidStatsLoc(droid, DORDER_BUILD,extraStructs[curTech][extraStruct], buildX,buildY);// build it.
1009
droid = iterateGroup(buildGroup);
1015
extraStruct = extraStruct + 1;
1019
/////////////////////////////////////////////////////////////////////
1020
// Structure (fac/res/pow) upgrades
1021
event upgradeStructures(upgradeStructuresTr )
1024
initIterateGroup(buildGroup); // find idle droids in build group.
1025
droid = iterateGroup(buildGroup);
1026
while(droid != NULLOBJECT)
1028
if((droid.order != DORDER_BUILD) and (droid.order != DORDER_LINEBUILD))
1032
if(curTech == branchDefault)
1035
boolResult = upgradePowGen(droid, 2);
1038
if(droid.order != DORDER_BUILD){
1039
boolResult = upgradeFactory(droid, 3);
1043
if(droid.order != DORDER_BUILD){
1044
boolResult = upgradeResearch(droid, 1);
1048
if(droid.order != DORDER_BUILD){
1049
boolResult = upgradeVtolFactory(droid, 1);
1052
else if(curTech == branchVTOL)
1055
boolResult = upgradePowGen(droid, 2);
1058
if(droid.order != DORDER_BUILD){
1059
boolResult = upgradeVtolFactory(droid, 3);
1063
if(droid.order != DORDER_BUILD){
1064
boolResult = upgradeFactory(droid, 2);
1068
if(droid.order != DORDER_BUILD){
1069
boolResult = upgradeResearch(droid, 1);
1073
droid = iterateGroup(buildGroup);
1077
function bool upgradeFactory(DROID _truck, int _maxBuilders)
1079
local STRUCTURE _factory;
1081
initEnumStruct(FALSE,factory,me,me);
1082
_factory = enumStruct();
1083
while(_factory != NULLOBJECT)
1085
// if upgrade is available && struct is not upgraded
1086
if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(_factory) < 2 ))
1088
if((numBuildSameBuilding(facModule, _factory.x, _factory.y) +
1089
numBuildSameBuilding(vtolFactory, _factory.x, _factory.y)) < _maxBuilders)
1091
orderDroidStatsLoc(_truck, DORDER_BUILD,facModule, _factory.x,_factory.y); // upgrade it.
1095
_factory = enumStruct();
1101
function bool upgradeVtolFactory(DROID _truck, int _maxBuilders)
1103
local STRUCTURE _factory;
1105
initEnumStruct(FALSE,vtolFactory,me,me);
1106
_factory = enumStruct();
1107
while(_factory != NULLOBJECT)
1109
// if upgrade is available && struct is not upgraded
1110
if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(_factory) < 2 ))
1112
if((numBuildSameBuilding(facModule, _factory.x, _factory.y) +
1113
numBuildSameBuilding(factory, _factory.x, _factory.y)) < _maxBuilders)
1115
orderDroidStatsLoc(_truck, DORDER_BUILD,facModule, _factory.x,_factory.y); // upgrade it.
1119
_factory = enumStruct();
1125
function bool upgradeResearch(DROID _truck, int _maxBuilders)
1127
local STRUCTURE _resFac;
1129
initEnumStruct(FALSE,resLab,me,me);
1130
_resFac = enumStruct();
1131
while(_resFac != NULLOBJECT)
1133
// if upgrade is available && struct is not upgraded
1134
if( isStructureAvailable(resModule,me) and (not testStructureModule(me, _resFac, 0)))
1136
if((numBuildSameBuilding(resModule, _resFac.x, _resFac.y) +
1137
numBuildSameBuilding(resLab, _resFac.x, _resFac.y)) < _maxBuilders)
1139
orderDroidStatsLoc(_truck, DORDER_BUILD,resModule, _resFac.x,_resFac.y); // upgrade it.
1143
_resFac = enumStruct();
1149
function bool upgradePowGen(DROID _truck, int _maxBuilders)
1151
local STRUCTURE _powGen;
1153
initEnumStruct(FALSE,powGen,me,me);
1154
_powGen = enumStruct();
1155
while(_powGen != NULLOBJECT)
1157
// if upgrade is available && struct is not upgraded
1158
if( isStructureAvailable(powModule,me) and (not testStructureModule(me, _powGen, 0)))
1160
if((numBuildSameBuilding(powModule, _powGen.x,_powGen.y) +
1161
numBuildSameBuilding(powGen, _powGen.x,_powGen.y)) < _maxBuilders)
1163
orderDroidStatsLoc(_truck, DORDER_BUILD, powModule, _powGen.x,_powGen.y); // upgrade it.
1167
_powGen = enumStruct();
1174
/////////////////////////////////////////////////////////////////////
1175
// Finish Building Part Built Structures
1176
event finishStructs(finishStructsTr)
1178
initEnumStruct(TRUE,factory,me,me);
1179
structure= enumStruct();
1180
while(structure != NULLOBJECT)
1182
if(not structureComplete(structure))
1184
initIterateGroup(buildGroup); // find idle droids in build group.
1185
droid = iterateGroup(buildGroup);
1186
while(droid != NULLOBJECT)
1188
if((droid.order != DORDER_BUILD) and (droid.order != DORDER_LINEBUILD))
1190
orderDroidObj(droid,DORDER_HELPBUILD,structure);
1192
droid = iterateGroup(buildGroup);
1195
structure= enumStruct();
1200
/////////////////////////////////////////////////////////////////////
1201
// fortify base by builiding defensive structs on the edge of the base.
1202
// rewrote fortify to use scrSkDefenseLocation(baseX,baseY,me);
1204
event newfortify(fortifyTr)
1206
local int _numBuilders,_maxBuilders;
1210
if(numGroupSameOrder(buildGroup, DORDER_LINEBUILD) >= _maxBuilders)
1216
initIterateGroup(buildGroup); // find idle an idle veh.in build group.
1217
droid = iterateGroup(buildGroup);
1218
while((boolResult == FALSE) and (droid != NULLOBJECT))
1220
if((droid.order != DORDER_BUILD) and (droid.order != DORDER_LINEBUILD))
1222
boolResult = TRUE; // dont do this again!
1227
// choose a suitable turret.
1228
count = numWallWeaps - 1;
1230
while( (count2 < 3) and (count >= 0) )
1232
if( isStructureAvailable(wallWeaps[count],me))
1234
structChoice[count2] = wallWeaps[count];
1235
count2 = count2 + 1;
1240
if((count2 > 0) and (_numBuilders < _maxBuilders))
1242
count = random(count2);
1243
skDefenseLocationB(ref tempx,ref tempy,wall,structChoice[count],droid,me);
1248
droid = iterateGroup(buildGroup);
1254
/////////////////////////////////////////////////////////////////////
1255
// droid building rules
1256
/////////////////////////////////////////////////////////////////////
1257
// deal with a droid being built
1258
event droidBuiltAssign(droidBuiltTr)
1262
if(vtolDefendGr.members < numDefendVtols)
1264
groupAddDroid(vtolDefendGr, droid);
1269
while(count < numVtolAttackGroups)
1271
if(vtolAttackGr[count].members < numAttackVtols)
1273
dbg("added new vtol to group " & count, me);
1274
groupAddDroid(vtolAttackGr[count], droid);
1275
count = numVtolAttackGroups;
1281
else if((droid.droidType != DROID_TRANSPORTER) and (droid.droidType != DROID_COMMAND))
1284
if((droid.droidType == DROID_REPAIR)
1285
or (droid.droidType == DROID_CYBORG_REPAIR))
1287
numRepairUnits = numRepairUnits + 1;
1290
if((droid.droidType == DROID_CONSTRUCT)
1291
or (droid.droidType == DROID_CYBORG_CONSTRUCT)) // if constructor droid
1293
groupAddDroid(buildGroup, droid);
1297
if(droid.droidType == DROID_CYBORG)
1299
groupAddDroid(defendGroup, droid);
1303
if(scoutGroup.members < numScouts[curTech])
1305
groupAddDroid(scoutGroup, droid);
1307
else if(attackGroup.members < numAttackers[curTech])
1309
groupAddDroid(attackGroup, droid);
1311
else if( defendGroup.members < numDefenders[curTech])
1313
groupAddDroid(defendGroup, droid);
1317
if(scoutGroup.members < maxScouts[curTech])
1319
groupAddDroid(scoutGroup, droid);
1321
else if(attackGroup.members < maxAttackers[curTech])
1323
groupAddDroid(attackGroup, droid);
1325
else if( defendGroup.members < maxDefenders[curTech])
1327
groupAddDroid(defendGroup, droid);
1329
else //make them attack
1331
groupAddDroid(attackGroup, droid);
1339
//When droid built: set droid retreat level and start building next droid
1340
event droidBuilt(droidBuiltTr)
1342
local STRUCTURE _repairFacility;
1346
_repairFacility = getStructure(repairFacility,me);
1347
if(_repairFacility == NULLOBJECT)
1349
setDroidSecondary(droid,DSO_REPAIR_LEVEL, DSS_REPLEV_NEVER);
1353
setDroidSecondary(droid,DSO_REPAIR_LEVEL, DSS_REPLEV_LOW);
1357
/* Start building next droid */
1358
if(structure != NULLOBJECT)
1360
if(structure.stattype == REF_FACTORY)
1362
factoryBuildDroid(structure);
1364
else if(structure.stattype == REF_CYBORG_FACTORY)
1366
cybFactorBuildCyborg(structure);
1368
else if(structure.stattype == REF_VTOL_FACTORY)
1370
vtolFactoryBuildVtol(structure);
1375
/* Gets triggered when structure was built */
1376
event structBuilt(structBuiltTr)
1378
local FEATURE _oilResource;
1379
local int _count,_count2;
1381
if(structure == NULLOBJECT || droid == NULLOBJECT){
1385
/* factory or factory module */
1386
if(structure.stattype == REF_FACTORY)
1388
if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(structure) < 2 ))
1390
orderDroidStatsLoc(droid, DORDER_BUILD,facModule, structure.x,structure.y); // upgrade it.
1393
/* vtol factory or vtol factory module */
1394
else if(structure.stattype == REF_VTOL_FACTORY)
1396
if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(structure) < 2 ))
1398
orderDroidStatsLoc(droid, DORDER_BUILD,facModule, structure.x,structure.y); // upgrade it.
1401
else if(structure.stattype == REF_RESOURCE_EXTRACTOR)
1403
/* get next oil resource nearby */
1404
_oilResource = closestOil(structure.x, structure.y, TRUE);
1406
if(_oilResource != NULLOBJECT)
1408
if(distBetweenTwoPoints(_oilResource.x, _oilResource.y, structure.x, structure.y) < MORE_OIL_RANGE) //not too far away
1410
dbg("structBuilt: more oil", me);
1411
orderDroidStatsLoc(droid, DORDER_BUILD, derrick, _oilResource.x, _oilResource.y); //build a derick
1416
//see if we have just rebuilt a destroyed structure
1418
while(_count < countRebuildStruct)
1420
if(structure.x == rebuildStructX[_count] and
1421
structure.y == rebuildStructY[_count] and
1422
( (structure.stat == rebuildStructStat[_count]) or //walls can end up as corner walls
1423
( (structure.stat == wall or structure.stat == cornerWall) and
1424
(rebuildStructStat[_count] == wall or rebuildStructStat[_count] == cornerWall))
1427
dbg("finished rebuilding destroyed structure - " & _count, me);
1429
//resort destroyed structures
1431
while(_count2 < (countRebuildStruct - 1))
1433
rebuildStructX[_count2] = rebuildStructX[_count2 + 1];
1434
rebuildStructY[_count2] = rebuildStructY[_count2 + 1];
1435
rebuildStructStat[_count2] = rebuildStructStat[_count2 + 1];
1441
rebuildStructX[countRebuildStruct - 1] = 0;
1442
rebuildStructY[countRebuildStruct - 1] = 0;
1443
rebuildStructStat[countRebuildStruct - 1] = NULLSTRUCTURESTAT;
1445
countRebuildStruct--; //we just built one structure
1447
//_count = countRebuildStruct; //exit outer loop
1453
/////////////////////////////////////////////////////////////////////
1454
// deal with attacks.
1455
event droidDestroyed(droidDestroyedTr)
1458
if(droid.droidType == DROID_REPAIR)
1460
numRepairUnits = numRepairUnits - 1;
1463
if(droid.droidType == DROID_CONSTRUCT) // if constructor droid
1465
initEnumStruct(FALSE,factory,me,me);
1466
structure= enumStruct(); // find factory.
1468
if( (structure != NULLOBJECT) and (getDroidCount(me) < MAX_DROIDS) )
1470
buildDroid(constructor, structure, me, 1); // build constructor
1477
/////////////////////////////////////////////////////////////////////
1478
// build more con droids.
1479
event conDroids(conDroidsTr)
1486
/* function void buildTruck()
1488
local int _maxTrucks;
1489
local STRUCTURE _factory;
1490
local int _numBuilding,_haveTrucks,_maxTruckFactories,_totalTrucks;
1492
_maxTrucks = MAX_TRUCKS;
1494
_maxTrucks = MIN_TRUCKS;
1497
_maxTruckFactories = 3; //max factories to use for truck production
1499
_haveTrucks = buildGroup.members;
1501
// Find out how many trucks and combat engineers are already in production
1502
_numBuilding = numTemplatesInProduction(constructor,me); //trucks
1503
_numBuilding = _numBuilding + numTemplatesInProduction(cybEngineer,me); //engineers
1505
_totalTrucks = _numBuilding + _haveTrucks;
1507
initEnumStruct(FALSE,factory,me,me);
1508
_factory = enumStruct(); // find factory.
1509
while((_factory != NULLOBJECT) and (_numBuilding < _maxTruckFactories)
1510
and (_totalTrucks < _maxTrucks))
1512
if(structureComplete(_factory))
1514
if(getDroidCount(me) < MAX_DROIDS)
1516
buildDroid(constructor, _factory, me, 1); // build constructor
1522
_factory = enumStruct();
1526
function void buildTruck()
1528
local int _maxTrucks;
1529
local STRUCTURE _factory;
1530
local int _numBuilding,_haveTrucks,_maxTruckFactories,_totalTrucks;
1531
local bool _bStartedBuilding;
1533
_maxTrucks = MAX_TRUCKS;
1535
_maxTrucks = MIN_TRUCKS;
1538
_maxTruckFactories = 3; //max factories to use for truck production
1540
_haveTrucks = buildGroup.members;
1542
//Find out how many trucks and combat engineers are already in production
1543
_numBuilding = numTemplatesInProduction(constructor,me); //trucks
1544
_numBuilding = _numBuilding + numTemplatesInProduction(cybEngineer,me); //engineers
1546
_totalTrucks = _numBuilding + _haveTrucks;
1548
initEnumStruct(FALSE,factory,me,me);
1549
_factory = enumStruct();
1551
while((_factory != NULLOBJECT) and (_numBuilding < _maxTruckFactories)
1552
and (_totalTrucks < _maxTrucks))
1554
//Try to build a truck
1555
_bStartedBuilding = buildUnit(constructor, _factory, factory, FALSE); //build truck even if not idle
1557
//Update statistics if started building a truck
1558
if(_bStartedBuilding)
1564
_factory = enumStruct();
1567
//build cyborg engineers if needed, no building structure limit here
1568
initEnumStruct(FALSE,cybFactory,me,me);
1569
_factory = enumStruct();
1570
while((_factory != NULLOBJECT) and (_totalTrucks < _maxTrucks))
1572
//Try to build a truck
1573
if( skCanBuildTemplate(me,_factory, cybEngineer) ) //make sure we have researched cyb engineer
1575
_bStartedBuilding = buildUnit(cybEngineer, _factory, cybFactory, FALSE); //build a cyb eng even if not idle
1577
//Update statistics if started building a cyborg engineer
1578
if(_bStartedBuilding)
1585
_factory = enumStruct();
1591
function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly)
1593
//Factory was not provided, find an factory
1594
if(_factory == NULLOBJECT)
1596
_factory = findIdleStructure(_factoryType, _bIdleOnly);
1599
//Build if got a factory
1600
if(_factory != NULLOBJECT)
1602
if(structureComplete(_factory) and (getDroidCount(me) < MAX_DROIDS))
1604
if( !(_bIdleOnly and !structureIdle(_factory)) ) //don't build if only allowed to build whe idle and fac is not idle
1606
buildDroid(_tankTemplate, _factory, me, 1); // build a tank
1607
return TRUE; //success
1612
return FALSE; //failed
1615
//Returns an idle structure of the provided type or NULLOBJECT if none found
1616
function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly)
1618
local STRUCTURE _structure;
1620
initEnumStruct(FALSE,_structType,me,me);
1621
_structure = enumStruct();
1622
while(_structure != NULLOBJECT)
1624
if(structureComplete(_structure))
1626
if( !(_bIdleOnly and !structureIdle(_structure)) )
1632
_structure = enumStruct();
1635
return NULLOBJECT; //none found
1638
/////////////////////////////////////////////////////////////////////
1639
// build repair droids.
1640
event repairDroids(repairDroidsTr)
1643
// if we're running low on repair droids, build some..
1644
if(numRepairUnits <3)
1646
initEnumStruct(FALSE,factory,me,me);
1647
structure= enumStruct(); // find factory.
1648
if( (structure != NULLOBJECT) and (getDroidCount(me) < MAX_DROIDS) )
1650
buildDroid(repairUnit, structure, me, 1); // build repairunit.
1657
/////////////////////////////////////////////////////////////////////
1658
event factoryEvent(factoryEventTr)
1661
// for each factory....
1662
initEnumStruct(FALSE,factory,me,me);
1663
structure = enumStruct(); // find factory.
1664
if(getDroidCount(me) < MAX_DROIDS)
1666
while(structure != NULLOBJECT)
1668
if( structureIdle(structure) )
1670
factoryBuildDroid(structure);
1673
structure = enumStruct();
1678
function bool needTank()
1680
if((defendGroup.members < maxDefenders[curTech]) or (maxDefenders[curTech] == UNLIMITED))
1685
if((scoutGroup.members < maxScouts[curTech]) or (maxScouts[curTech] == UNLIMITED))
1690
if((attackGroup.members < maxAttackers[curTech]) or (maxAttackers[curTech] == UNLIMITED))
1698
function void factoryBuildDroid(STRUCTURE _factory)
1700
local int _count,_count2;
1702
if(_factory == NULLOBJECT){
1703
dbg("factoryBuildDroid: factory is NULLOBJECT", me);
1709
//dbg("NEED NO TANKS!! " & maxDefenders[curTech], me);
1713
if( structureIdle(_factory) )
1715
_count = numTemplates[curTech] - 1;
1717
while( (_count2 < MAX_RANDOM_TEMPLATES) and (_count >= 0) )
1719
if( skCanBuildTemplate(me,_factory, tmpl[curTech][_count]) )
1721
tmplChoice[_count2] = tmpl[curTech][_count];
1722
_count2 = _count2 + 1;
1724
_count = _count - 1;
1729
buildDroid(tmplChoice[random(_count2)],_factory,me,1);
1734
dbg("factoryBuildDroid: factory is busy", me);
1738
/////////////////////////////////////////////////////////////////////
1739
// put cyborg factories to work
1740
event cyborgFactoryEvent(cyborgFactoryEventTr)
1743
if(not ((defendGroup.members < maxCyborgs[curTech]) or (maxCyborgs[curTech] == UNLIMITED)))
1745
exit; //we need no cyborgs
1748
initEnumStruct(FALSE,cybFactory,me,me);
1749
structure= enumStruct(); // find factory.
1751
while(structure != NULLOBJECT)
1753
if( structureIdle(structure) == TRUE)
1755
cybFactorBuildCyborg(structure);
1757
structure= enumStruct(); // find factory.
1761
function void cybFactorBuildCyborg(STRUCTURE _factory)
1763
if(_factory == NULLOBJECT){
1764
dbg("cybFactorBuildCyborg: factory is NULLOBJECT", me);
1768
if( structureIdle(_factory) )
1770
if( (defendGroup.members < maxCyborgs[curTech]) and (getDroidCount(me) < MAX_DROIDS) )
1774
buildDroid(cybMechanic,_factory,me,1);
1782
if( skCanBuildTemplate(me,_factory, superCyb[count]) )
1784
tmplChoice[count2] = superCyb[count];
1785
count2 = count2 + 1;
1792
buildDroid(tmplChoice[random(count2)],_factory,me,1);
1794
else //try light cyborgs
1796
count = numLightCyborgs - 1;
1798
while( (count >= 0) and (count2 < 2) )
1800
if( skCanBuildTemplate(me,_factory, cybTempl[count]) )
1802
tmplChoice[count2] = cybTempl[count];
1809
buildDroid(tmplChoice[random(count2)], _factory, me, 1);
1818
/////////////////////////////////////////////////////////////////////
1819
/////////////////////////////////////////////////////////////////////
1823
event chooseScoutArea(chooseScoutAreaTr)
1825
scoutX = scoutTLX + random(scoutW);
1826
scoutY = scoutTLY + random(scoutH);
1829
/////////////////////////////////////////////////////////////////////
1832
event expandScoutArea(expandScoutAreaTr)
1835
//expand the scouting area slightly
1836
scoutTLX = scoutTLX - ((mapWidth*128)/ tileExpand);
1837
scoutTLY = scoutTLY - ((mapHeight*128)/ tileExpand);
1838
scoutW = scoutW + (2*((mapWidth*128)/ tileExpand));
1839
scoutH = scoutH + (2*((mapHeight*128)/ tileExpand));
1841
// check & restrain.
1851
if(scoutTLX >(mapWidth*128))
1853
scoutTLX = (mapWidth*128) - 128;
1855
if(scoutTLY >(mapHeight*128))
1857
scoutTLY = (128*mapHeight) - 128;
1860
if( (scoutTLX + scoutW) > (128 * mapWidth) )
1862
scoutW = ( (128 * mapWidth) - scoutTLX) - 128;
1864
if( (scoutTLY + scoutH) > (128 *mapHeight) )
1866
scoutH = ( (128*mapHeight) - scoutTLY) - 128;
1870
/////////////////////////////////////////////////////////////////////
1873
event scoutMain(scoutMainTr)
1875
// find any new scouts
1876
// if scouts aren't busy, send them to a new spot.
1877
if( idleGroup(scoutGroup) >= (scoutGroup.members /2) )
1879
orderGroupLoc(scoutGroup, DORDER_MOVE,scoutX,scoutY);
1883
/////////////////////////////////////////////////////////////////////
1884
// process new visibility reports
1885
event newObjectReport(newObjectReportTr)
1887
if(!friendlyPlayer(baseobj.player))
1889
if(targetTypeValue(baseobj) > targetTypeValue(attackObj))
1891
attackObj = baseobj;// got a new unseen target from a scout.
1893
if( attackObj.type == OBJ_STRUCTURE)
1895
if(not allianceExistsBetween(attackObj.player,me)) // an enemy
1897
structure = objToStructure(attackObj);
1898
if(structure.stat == factory)
1900
allOutAttack = attackObj;
1908
function int targetTypeValue(BASEOBJ _target)
1910
local STRUCTURE _strTarget;
1912
if(_target == NULLOBJECT){
1913
return NO_TARGET_VALUE;
1916
if(_target.type == OBJ_DROID)
1918
return DROID_TARGET_VALUE;
1920
else if(_target.type == OBJ_STRUCTURE)
1922
_strTarget = objToStructure(_target);
1924
if(_strTarget.stattype == REF_DEFENSE)
1926
return DEFENSE_TARGET_VALUE;
1928
else if(_strTarget.stattype == REF_RESEARCH or
1929
_strTarget.stattype == REF_POWER_GEN)
1931
return RESEARCH_TARGET_VALUE;
1933
else if(_strTarget.stattype == REF_HQ or
1934
_strTarget.stattype == REF_COMMAND_CONTROL)
1936
return HQ_TARGET_VALUE;
1938
else if(_strTarget.stattype == REF_RESOURCE_EXTRACTOR)
1940
return OIL_TARGET_VALUE;
1942
else if(_strTarget.stattype == REF_FACTORY or
1943
_strTarget.stattype == REF_CYBORG_FACTORY or
1944
_strTarget.stattype == REF_VTOL_FACTORY)
1946
return FACTORY_TARGET_VALUE;
1948
else //walls, rearm pads etc
1950
return OTHER_TARGET_VALUE;
1954
return NO_TARGET_VALUE;
1958
/////////////////////////////////////////////////////////////////////
1959
/////////////////////////////////////////////////////////////////////
1961
//event takeover( CALL_UNITTAKEOVER , ref droid )
1963
event takeover(takeoverTr)
1965
if( droid.player == me )
1967
if(droid.droidType == DROID_CONSTRUCT or
1968
droid.droidType == DROID_CYBORG_CONSTRUCT)
1970
groupAddDroid( buildGroup, droid );
1972
else if (droid.droidType != DROID_TRANSPORTER
1973
&& droid.droidType != DROID_COMMAND)
1975
groupAddDroid( attackGroup, droid );
1980
event takeoverDefend(takeoverTr)
1982
if( droid.player != me )
1984
completeResearch(nexusDefence,me);
1985
setEventTrigger(takeoverDefend, inactive);
1990
event useLassat(useLassatTr)
1994
// fire it at my attack objective.
1995
if(allOutAttack != NULLOBJECT)
1997
initEnumStruct(FALSE,lassat,me,me);
1998
structure= enumStruct();
1999
while(structure != NULLOBJECT)
2001
if(structureComplete(structure) == TRUE)
2003
skFireLassat(me,allOutAttack);
2005
structure= enumStruct();
2010
/////////////////////////////////////////////////////////////////////
2011
/////////////////////////////////////////////////////////////////////
2014
event findEnemy(attackStuffTr)
2016
if(attackObj == NULLOBJECT)
2020
while( friendlyPlayer(count) && (count2 > 0) )
2026
if(!friendlyPlayer(count))
2028
baseobj = skLocateEnemy(count);
2029
if(baseobj != NULLOBJECT)
2031
attackObj = baseobj;
2033
// set allOutAttack to attackObj only if attackObj is a more valuable target than allOutAttack
2034
if(targetTypeValue(attackObj) > targetTypeValue(allOutAttack))
2036
allOutAttack = attackObj;
2043
/////////////////////////////////////////////////////////////////////
2044
// send attack team out to cause trouble near things scout found.
2045
event attackStuff(attackStuffTr)
2047
if( idleGroup(attackGroup) >= (attackGroup.members / 2))
2049
if( (attackObj != NULLOBJECT) and (not helpingAlly()) )
2051
if (not allianceExistsBetween(me, attackObj.player))
2053
if(attackGroup.members > (6 + random(6)) )
2055
orderGroupLoc(attackGroup, DORDER_SCOUT, attackObj.x, attackObj.y);
2058
// make scouts attack too
2059
if( idleGroup(scoutGroup) >= (scoutGroup.members / 2) )
2061
orderGroupLoc(scoutGroup, DORDER_SCOUT, attackObj.x, attackObj.y);
2068
/////////////////////////////////////////////////////////////////////
2069
event doAllOutAttack(allOutAttackTr)
2071
if( idleGroup(attackGroup) >= (attackGroup.members / 3)) // make sure at least 30% are idle
2073
if( (allOutAttack != NULLOBJECT) and (not helpingAlly()) )
2075
if( !friendlyPlayer(allOutAttack.player) )
2077
if( getDroidCount(me) > 40) // plenty of units.
2079
orderGroupObj(attackGroup, DORDER_ATTACK,allOutAttack);
2080
//orderGroupLoc(defendGroup, DORDER_SCOUT,allOutAttack.x,allOutAttack.y);
2081
orderGroupLoc(scoutGroup, DORDER_SCOUT,allOutAttack.x,allOutAttack.y);
2086
allOutAttack = NULLOBJECT;
2092
/////////////////////////////////////////////////////////////////////
2093
/////////////////////////////////////////////////////////////////////
2096
// defend attacked objects.
2097
event defendWatch(defendWatchTr)
2099
if(baseobj != NULLOBJECT)
2101
if(!friendlyPlayer(baseobj.player))
2103
if(not isHumanPlayer(baseobj.player) ) // new in wdg1 dont allout attack a pc player //TODO:is this check needed?
2105
if(distBetweenTwoPoints(baseobj.x, baseobj.y, baseX, baseY) <= MAX_DEFENDERS_RADIUS) //don't go too far away from the base
2107
defendObj = baseobj;
2109
// if not too busy, attack.
2110
if( idleGroup(defendGroup) >= (defendGroup.members / 2) )
2112
orderGroupLoc(defendGroup, DORDER_MOVE,defendObj.x,defendObj.y); //cyborg mechanics can't attack (won't move)
2113
//orderGroupObj(defendGroup, DORDER_ATTACK, defendObj);
2116
if( idleGroup(scoutGroup) >= (scoutGroup.members / 2) )
2118
orderGroupLoc(scoutGroup, DORDER_MOVE,scoutX,scoutY);
2127
/////////////////////////////////////////////////////////////////////
2128
// defenders return after they are finished.
2129
event defendReturn(defendReturnTr)
2131
if( defendbusy and (idleGroup(defendGroup) == (defendGroup.members - defendGroup.members / 12)))
2133
// find a place with no structures nearby
2136
pickStructLocationB(powGen, ref buildX, ref buildY, me, 0);
2138
orderGroupLoc(defendGroup, DORDER_MOVE,buildX,buildY);
2143
//returns number of non-idle structures of a certain type
2144
function int numStructBusyByType(STRUCTURESTAT _busyStructType)
2148
initEnumStruct(FALSE,_busyStructType,me,me);
2149
structure = enumStruct();
2151
while(structure != NULLOBJECT)
2153
if(structureComplete(structure))
2155
if(not structureIdle(structure))
2160
structure = enumStruct();
2166
/////////////////////////////////////////////////////////////////////
2167
/////////////////////////////////////////////////////////////////////
2168
// Research Rules Now does true research.
2171
event doResearch(doResearchTr)
2173
local int _techIndex,_numResearching;
2175
_techIndex = 0; //research start
2176
_numResearching = numStructBusyByType(resLab);
2178
// for every research lab do this..
2179
initEnumStruct(FALSE,resLab,me,me);
2180
structure= enumStruct();
2182
while(structure != NULLOBJECT)
2184
boolResult = FALSE; //haven't started research for the current resFac
2186
if(structureIdle(structure))
2188
if(structureComplete(structure))
2190
// first research all technologies necessary for the current research branch
2191
while(not boolResult and _techIndex != NONE) //not started researching and still branch tech left to try
2193
_techIndex = findResearch(_techIndex, curTech);
2194
if(_techIndex > NONE)
2196
boolResult = pursueResearch(structure,me,tech[curTech][_techIndex]);
2198
_techIndex++; //try nect research next time if needed
2203
// do common research
2204
if(not boolResult) //didn't start branch research
2206
if((maxIdleRes[curTech] == UNLIMITED) or (_numResearching < maxIdleRes[curTech]))
2208
skDoResearch(structure,me,0);
2215
structure = enumStruct();
2219
// find next available research of our research branch
2220
function int findResearch(int _searchStart, int _techTree)
2224
ASSERT(_searchStart >= 0, "findResearch: _searchStart < 0", me);
2225
ASSERT(_techTree >= 0, "findResearch: _techTree < 0", me);
2227
_result = _searchStart;
2228
while(_result < techCount[_techTree])
2230
if((not researchFinished(tech[_techTree][_result], me)) and (not researchStarted(tech[_techTree][_result], me)))
2232
return _result; //found research
2237
return NONE; //not found
2240
/////////////////////////////////////////////////////////////////////
2241
/////////////////////////////////////////////////////////////////////
2245
event formAllianceEvent(formAllianceEventTr)
2249
while(count < MAX_PLAYERS)
2251
if( count != me ) // if not the only other player and rand2
2253
if((getDroidCount(me) > 1) and (getDroidCount(count) > 1) ) // not dead
2255
if(random(28) == 1) // bit random
2257
if(not isHumanPlayer(count)) // not human
2259
createAlliance(me,count);
2260
allianceTime[count] = gameTime;
2269
/////////////////////////////////////////////////////////////////////
2270
// break the alliance too.
2271
event breakAllianceEvent(breakAllianceEventTr)
2274
while(count<multiPlayerMaxPlayers)
2278
if((getDroidCount(me) > 1) and (getDroidCount(count) > 1) ) // not dead
2280
if(allianceExistsBetween(me,count) )
2282
// check if we're in alliance with any other players.
2283
if( (random(30) == 1) and ( (gameTime - allianceTime[count]) > 6000) ) // rand and more than 10 minutes.
2285
allianceTime[count] = gameTime;
2286
breakAlliance(me,count);
2289
// rules for breaking alliances with humans.
2290
// built within my base
2291
if(numStructsInArea(count,minx,miny,maxx,maxy) > 1)
2293
allianceTime[count] = gameTime;
2294
breakAlliance(me,count);
2297
// you've got lots of units in my area.
2298
if(numDroidsInArea(count,minx,miny,maxx,maxy) > 3)
2300
allianceTime[count] = gameTime;
2301
breakAlliance(me,count);
2304
// you've wiped out one of my allies ??.
2312
/////////////////////////////////////////////////////////////////////
2313
event formHumanAlliances(humanAllianceTr)
2315
if(count2 == me) // offered to me.
2319
while(result < multiPlayerMaxPlayers)
2321
if(allianceExistsBetween(count,result))
2323
result2 = result2 + 1;
2325
result = result + 1;
2327
if( result2 < ((multiPlayerMaxPlayers / 2) - 1) ) // not too many already
2330
if((allianceTime[count] == 0) or (gameTime - allianceTime[count] > 1200))
2332
result = 0; // check forming wont end the game
2334
while(result < multiPlayerMaxPlayers)
2336
while(result2 < multiPlayerMaxPlayers)
2338
if((not allianceExistsBetween(result,result2)) and (getDroidCount(result) > 0) and (getDroidCount(result2) > 0) and (result != result2) )
2340
if( ((result == count and result2 == count2) or (result2 == count2 and result == count)) ) // ignore the outcome of this alliance
2342
createAlliance(me,count);
2343
allianceTime[count] = gameTime;
2346
result2 = result2 + 1;
2348
result = result + 1;
2356
/////////////////////////////////////////////////////////////////////
2357
/////////////////////////////////////////////////////////////////////
2358
// Consolidate Rules
2360
// bring forces back together to consolidate attacks
2361
event consolidateEvent(consolidateEventTr)
2363
if(not helpingAlly())
2365
if(random(3) == 1) // order all droids home to rejoin forces.!
2367
// find a place with no structures nearby
2370
pickStructLocationB(powGen, ref buildX, ref buildY, me, 0);
2372
orderGroupLoc(scoutGroup, DORDER_MOVE,buildX,buildY);
2373
orderGroupLoc(defendGroup, DORDER_MOVE,buildX,buildY);
2377
if(attackObj != NULLOBJECT) // consolidate any ongoing attack.
2379
if(!friendlyPlayer(attackObj.player))
2381
orderGroupLoc(attackGroup, DORDER_SCOUT, attackObj.x, attackObj.y);
2385
attackObj = NULLOBJECT;
2388
else if(allOutAttack == NULLOBJECT) //make sure not allOutAttacking
2391
// find a place with no structures nearby
2394
pickStructLocationB(powGen, ref buildX, ref buildY, me, 0);
2396
orderGroupLoc(attackGroup, DORDER_MOVE,buildX,buildY);
2402
/////////////////////////////////////////////////////////////////////
2403
/////////////////////////////////////////////////////////////////////
2404
// power management.
2406
// if running low on power put some power eating stuff on hold for a while.
2407
event managePower(managePowerTr)
2409
if( playerPower(me) < LOW_POWER ) // turn off some events.
2413
// setEventTrigger(fortify, inactive); // stop building defenses.
2414
setEventTrigger(upgradeStructures, inactive); // stop building oil defenses.
2415
// setEventTrigger(buildExpand, inactive); // stop building extra buildings.
2416
// setEventTrigger(conDroids, inactive); // stop building more construct droids.
2420
if(powerSave == TRUE) // turn events back on.
2424
// setEventTrigger(fortify, fortifyTr); // building defenses.
2425
setEventTrigger(upgradeStructures, upgradeStructuresTr);// building oil defenses.
2426
// setEventTrigger(buildExpand, buildExpandTr); // building extra buildings.
2427
// setEventTrigger(conDroids, conDroidsTr); // building more construct droids.
2431
/////////////////////////////////////////////////////////////////////
2433
event difficultyModifier(difficultyModifierTr)
2435
if(not isHumanPlayer(me))
2437
skDifficultyModifier(me);
2441
/////////////////////////////////////////////////////////////////////
2443
/////////////////////////////////////////////////////////////////////
2444
// build vtol strucutures.
2445
event vtolStructs(inactive)
2447
local int _maxTrucks,_numTrucks,_maxBuildTrucks,_minBuildTrucks;
2448
local int _numVtolFacs,_numRearmPads;
2450
// got any idle trucks?
2451
if(idleGroup(buildGroup) < 1){
2455
// see how many vtol factories we already have
2456
_numVtolFacs = getNumStructures(vtolFactory,me);
2457
_numRearmPads = getNumStructures(vtolPad,me);
2459
//see if we have enough rearm pads
2460
if( _numRearmPads * 4 / 3 <= totalVtols() )
2462
dbg("NEED REARM PADS", me);
2466
// calculate how many trucks we want to use for construction
2467
_minBuildTrucks = 1;
2468
_maxBuildTrucks = 3;
2469
_maxTrucks = min(_maxBuildTrucks, max(_minBuildTrucks, idleGroup(buildGroup) / 2));
2471
if(_numVtolFacs < maxVtolFacs[curTech]) // if not enough
2474
buildX = baseX; // pick a location
2476
boolResult = pickStructLocation(vtolFactory, ref buildX, ref buildY,me);
2477
if(boolResult == TRUE)
2479
initIterateGroup(buildGroup); // find idle droids in build group.
2480
droid = iterateGroup(buildGroup);
2481
_numTrucks = 0; // only send _maxTrucks to do the job
2482
while( (_numTrucks < _maxTrucks) and (droid != NULLOBJECT))
2484
if( (droid.order == DORDER_NONE) or (droid.order == DORDER_RTB))
2486
orderDroidStatsLoc(droid, DORDER_BUILD,vtolFactory, buildX,buildY);
2489
droid = iterateGroup(buildGroup);
2496
function int totalVtols()
2498
local int _vtolGroup,_totalVtols;
2502
while(_vtolGroup < numVtolAttackGroups)
2504
_totalVtols = _totalVtols + vtolAttackGr[_vtolGroup].members;
2508
_totalVtols = _totalVtols + vtolDefendGr.members;
2513
function void buildRearmPads()
2515
local int _buildX,_buildY;
2517
local bool _buildOK;
2519
if(!isStructureAvailable(vtolPad,me)){
2523
// build vtol rearm pads.
2524
_buildX = baseX; // pick a location
2527
_buildOK = pickStructLocation(vtolPad, ref _buildX, ref _buildY,me);
2530
initIterateGroup(buildGroup); // find idle droids in build group.
2531
_truck = iterateGroup(buildGroup);
2533
while(_truck != NULLOBJECT and _buildOK == FALSE)
2535
if((_truck.order != DORDER_BUILD) and (_truck.order != DORDER_LINEBUILD))
2537
orderDroidStatsLoc(_truck, DORDER_BUILD,vtolPad, _buildX,_buildY);
2540
_truck = iterateGroup(buildGroup);
2546
/////////////////////////////////////////////////////////////////////
2549
event buildVtols(inactive)
2552
// got enough vtols?
2553
if((vtolDefendGr.members >= maxVTOLs[curTech]) or (getDroidCount(me) >= MAX_DROIDS)){
2554
dbg("CAN'T BUILD VTOLS - TOO MANY UNITS", me);
2559
initEnumStruct(FALSE,vtolFactory,me,me);
2560
structure = enumStruct();
2561
while(structure != NULLOBJECT)
2563
if(structureIdle(structure)) // if factory idle
2565
vtolFactoryBuildVtol(structure);
2568
structure = enumStruct();
2573
function void vtolFactoryBuildVtol(STRUCTURE _factory)
2575
local int _numTemplates,_bestTemplates;
2577
if(_factory == NULLOBJECT){
2581
if( structureIdle(_factory) )
2583
_numTemplates = numVtolTemplates - 1;
2585
while( (_bestTemplates < 3) and (_numTemplates >= 0) )
2587
if( skCanBuildTemplate(me,_factory, vtols[_numTemplates]) )
2589
tmplChoice[_bestTemplates] = vtols[_numTemplates];
2595
if(_bestTemplates > 0)
2597
buildDroid(tmplChoice[random(_bestTemplates)],_factory,me,1);
2602
/////////////////////////////////////////////////////////////////////
2603
// attack with vtols.
2605
event vtolAttack(inactive)
2607
local int _groupIndex,_newTargetWeight,_oldTargetWeight;
2608
local BASEOBJ _newTarget;
2609
local bool _bHaveDefendTarget;
2612
// if vtol group is not busy..
2613
if( (idleGroup(vtolDefendGr) >= (vtolDefendGr.members / 2)) and (vtolDefendGr.members >= 2) )
2615
if(attackObj != NULLOBJECT)
2617
if(!friendlyPlayer(attackObj.player))
2619
orderGroupObj(vtolDefendGr, DORDER_ATTACK, attackObj); // get the attack target.
2623
attackObj = NULLOBJECT;
2628
if(defendObj != NULLOBJECT)
2630
if(not isHumanPlayer(defendObj.player) ) // new in wdg1 //TODO:is this check needed?
2632
orderGroupObj(vtolDefendGr, DORDER_ATTACK,defendObj); // get the defend target
2638
//make sure attack vtol groups are not cluttered
2639
rearrangeAttackVtols();
2643
while(_groupIndex < numVtolAttackGroups)
2645
if(vtolAttackGr[_groupIndex].members > 0)
2647
// if our base is in trouble see if we have a target in the base
2648
// don't choose new target if already have one
2649
_bHaveDefendTarget = FALSE;
2650
if((vtolGrAttackObj[_groupIndex] != NULLOBJECT))
2652
if(defendingOwnBase() and
2653
(distBetweenTwoPoints(baseX, baseY, vtolGrAttackObj[_groupIndex].x, vtolGrAttackObj[_groupIndex].y) <= MAX_VTOL_DEFEND_RADIUS))
2655
_bHaveDefendTarget = TRUE;
2657
else //reset target if it's not worth it
2659
//we don't want to attack enemy heavy tanks outside of our base
2660
if(vtolGrAttackObj[_groupIndex].type == OBJ_DROID)
2662
_droid = objToDroid(vtolGrAttackObj[_groupIndex]);
2663
if(_droid.droidType != DROID_CONSTRUCT)
2665
vtolGrAttackObj[_groupIndex] = NULLOBJECT; //reset target
2666
_bHaveDefendTarget = FALSE;
2672
//find target in our base if our base is in trouble
2673
if(!_bHaveDefendTarget and defendingOwnBase())
2675
vtolGrAttackObj[_groupIndex] = chooseVtolDefenceTarget(baseX, baseY, MAX_VTOL_DEFEND_RADIUS, FALSE);
2677
if(vtolGrAttackObj[_groupIndex] != NULLOBJECT)
2679
dbg("assigned new defence target for group " & _groupIndex, me);
2680
_bHaveDefendTarget = TRUE;
2685
if(!_bHaveDefendTarget and (idleGroup(vtolAttackGr[_groupIndex]) >= (vtolAttackGr[_groupIndex].members / 2)) and
2686
(vtolAttackGr[_groupIndex].members >= (numAttackVtols * 2 / 3)))
2688
_newTarget = NULLOBJECT;
2690
//reset attack targets once in a while
2691
if(vtolGrAttackObj[_groupIndex] != NULLOBJECT)
2695
vtolGrAttackObj[_groupIndex] = NULLOBJECT;
2699
//now try to find an attack target if we have no defence target
2700
//find best attack target
2701
_newTarget = chooseVtolTarget(TRUE); //search for an exclusive target
2702
if(_newTarget == NULLOBJECT)
2704
_newTarget = chooseVtolTarget(FALSE); //search for any target
2707
_newTargetWeight = getVtolTargetWeight(_newTarget);
2708
_oldTargetWeight = getVtolTargetWeight(vtolGrAttackObj[_groupIndex]);
2710
// new one or a much better one
2711
if((_newTargetWeight >= (_oldTargetWeight + 20)) or
2712
(vtolGrAttackObj[_groupIndex] == NULLOBJECT ))
2714
dbg("choosing new attack object for " & _groupIndex, me);
2715
vtolGrAttackObj[_groupIndex] = _newTarget;
2719
//see if this group has something to attack
2720
if(vtolGrAttackObj[_groupIndex] != NULLOBJECT)
2722
if(!friendlyPlayer(vtolGrAttackObj[_groupIndex].player))
2724
dbg("VTOL Group " & _groupIndex & " attacking", me);
2726
if(_DEBUG and (_groupIndex == 0))
2728
dropBeacon(getPlayerName(me), me, me, vtolGrAttackObj[_groupIndex].x, vtolGrAttackObj[_groupIndex].y, 0);
2731
orderGroupObj(vtolAttackGr[_groupIndex], DORDER_ATTACK, vtolGrAttackObj[_groupIndex]);
2735
vtolGrAttackObj[_groupIndex] = NULLOBJECT;
2744
//make sure vtol groups are not cluttered
2745
function void rearrangeAttackVtols()
2747
local int _emptyGr,_fillGr;
2751
while(_emptyGr < numVtolAttackGroups)
2753
if((vtolAttackGr[_emptyGr].members < numAttackVtols) and //this group is not full
2754
(vtolAttackGr[_emptyGr].members > 0))
2756
//try to make full groups by moving vtols from the last groups
2757
_fillGr = _emptyGr + 1; //start from the next group
2758
while((_fillGr < numVtolAttackGroups) and
2759
(vtolAttackGr[_emptyGr].members < numAttackVtols))
2761
initIterateGroup(vtolAttackGr[_fillGr]);
2762
_droid = iterateGroup(vtolAttackGr[_fillGr]);
2763
while((_droid != NULLOBJECT) and
2764
(vtolAttackGr[_emptyGr].members < numAttackVtols))
2766
groupAddDroid(vtolAttackGr[_emptyGr], _droid); //refill the group
2767
_droid = iterateGroup(vtolAttackGr[_fillGr]);
2777
function BASEOBJ chooseVtolDefenceTarget(int _x, int _y, int _range, bool bExclusiveTarget)
2779
local BASEOBJ _target;
2781
_target = getClosestEnemy(_x, _y, _range, FALSE, FALSE, me);
2783
// make sure no one else is targeting it already if we want exclusive targets
2784
if(bExclusiveTarget and vtolTargetAssigned(_target))
2786
_target = NULLOBJECT;
2792
function BASEOBJ chooseVtolTarget(bool bExclusiveTarget)
2794
local int _structTypeIndex,_enemy;
2795
local int _bestScore,_tempScore;
2796
local BASEOBJ _bestTarget;
2797
local STRUCTURE _structure;
2800
_bestTarget = NULLOBJECT;
2803
while(_enemy < MAX_PLAYERS)
2805
if(!friendlyPlayer(_enemy))
2807
_structTypeIndex = 0;
2808
while(_structTypeIndex < numVtolTargets)
2810
initEnumStruct(FALSE,vtolTarget[_structTypeIndex],_enemy,me);
2811
_structure = enumStruct();
2812
while(_structure != NULLOBJECT)
2815
// in case we don't want all groups to attack the same target
2816
if(not (bExclusiveTarget and vtolTargetAssigned(_structure)) )
2818
_tempScore = getVtolTargetWeight(_structure);
2820
//see if this one is better
2821
if(_tempScore > _bestScore)
2823
_bestScore = _tempScore;
2824
_bestTarget = _structure;
2828
_structure = enumStruct();
2840
function int getVtolTargetWeight(BASEOBJ _target)
2842
local int _AAPenalty,_numAA,_range,_targetWeight;
2843
local int _targetType;
2844
local STRUCTURE _structTarget;
2846
if(_target == NULLOBJECT)
2851
if(_target.type != OBJ_STRUCTURE)
2856
_structTarget = objToStructure(_target);
2860
_AAPenalty = 9; //penalty per aa defense
2861
_range = AA_THREAT_RANGE;
2864
_numAA = numEnemyAAInRange(_structTarget.x, _structTarget.y, _range);
2866
// find tyrget type from stats
2868
while(_targetType < numVtolTargets)
2870
if(_structTarget.stat == vtolTarget[_targetType])
2872
_targetWeight = vtolTargetWeight[_targetType] - (_numAA * _AAPenalty);
2874
_targetType = numVtolTargets; //exit loop
2879
// incomplete structures get lower weight
2880
if(!structureComplete(_structTarget))
2882
_targetWeight = _targetWeight / 10;
2885
return _targetWeight;
2888
function int numEnemyAAInRange(int _x, int _y, int _range)
2890
local int _enemy,_numAA;
2894
while(_enemy < MAX_PLAYERS)
2896
if(!friendlyPlayer(_enemy))
2898
_numAA = _numAA + numAAinRange(_enemy, me, _x, _y, _range);
2906
// see if a particular target is already assigned to one of the VTOL attack groups
2907
function bool vtolTargetAssigned(BASEOBJ _target)
2909
local int _groupIndex;
2911
if(_target == NULLOBJECT)
2917
while(_groupIndex < numVtolAttackGroups)
2919
if(_target == vtolGrAttackObj[_groupIndex])
2930
/////////////////////////////////////////////////////////////////////
2931
// watch for incoming vtols
2932
event vtolDefend(vtolDefendTr)
2934
local int _numBuilders,_maxBuilders;
2937
// boolResult2 = FALSE; // if attacked by a vtol.
2938
if(baseobj != NULLOBJECT)
2940
if(baseobj.type == OBJ_DROID)
2942
if(isVtol(objToDroid(baseobj)))
2944
// activate other vtol functions..
2945
setEventTrigger(vtolStructs,vtolStructsTr);
2946
setEventTrigger(buildVtols, buildVtolsTr);
2947
setEventTrigger(vtolAttack, vtolAttackTr);
2953
initIterateGroup(buildGroup); // find idle droids in build group.
2954
droid = iterateGroup(buildGroup);
2955
// while( (boolResult2 != TRUE) and (droid != NULLOBJECT))
2956
while( droid != NULLOBJECT)
2958
if( (structure != NULLOBJECT) and (droid.order != DORDER_BUILD) )
2960
buildX = structure.x;
2961
buildY = structure.y;
2962
// if ! vtol defense already built...
2964
//find best defense we can build.
2969
if(isStructureAvailable(vtolDefStruct[count],me))
2977
boolResult = pickStructLocation(vtolDefStruct[count2], ref buildX, ref buildY,me);
2978
if((boolResult == TRUE) and (_numBuilders < _maxBuilders)) // build a vtol defense near the attacked struct...
2980
orderDroidStatsLoc(droid, DORDER_BUILD,vtolDefStruct[count2],buildX,buildY);
2982
// boolResult2 = TRUE;
2987
droid = iterateGroup(buildGroup);
2994
/////////////////////////////////////////////////////////////////////
2995
event vtolEnabler(vtolEnablerTr)
2997
if( skVtolEnableCheck(me) ) // check to see if we have vtol technologies.
2999
setEventTrigger(vtolEnabler,inactive); // turn off this event.
3000
setEventTrigger(vtolStructs,vtolStructsTr); // activate other vtol functions..
3001
setEventTrigger(buildVtols, buildVtolsTr);
3002
setEventTrigger(vtolAttack, vtolAttackTr);
3003
dbg("----I CAN USE VTOLS----", me);
3007
/////////////////////////////////////////////////////////////////////
3010
function void shutDownAI()
3014
setEventTrigger(givehelp, inactive);
3015
setEventTrigger(basedetails, inactive);
3016
setEventTrigger(buildDerrick, inactive);
3017
setEventTrigger(buildOilDefenseOrRetreat, inactive);
3018
setEventTrigger(incendry, inactive);
3019
setEventTrigger(buildPowerGenerators, inactive);
3020
setEventTrigger(buildBase, inactive);
3021
setEventTrigger(buildExpand,inactive);
3022
setEventTrigger(upgradeStructures,inactive);
3023
setEventTrigger(finishStructs, inactive);
3024
setEventTrigger(newfortify, inactive);
3025
setEventTrigger(droidBuilt, inactive);
3026
setEventTrigger(structBuilt,inactive);
3027
setEventTrigger(droidDestroyed,inactive);
3028
setEventTrigger(conDroids,inactive);
3029
setEventTrigger(repairDroids,inactive);
3030
setEventTrigger(factoryEvent, inactive);
3031
setEventTrigger(cyborgFactoryEvent, inactive);
3032
setEventTrigger(chooseScoutArea, inactive);
3033
setEventTrigger(expandScoutArea, inactive);
3034
setEventTrigger(scoutMain, inactive);
3035
setEventTrigger(newObjectReport, inactive);
3036
setEventTrigger(takeover, inactive);
3037
setEventTrigger(takeoverDefend, inactive);
3038
setEventTrigger(useLassat, inactive);
3039
setEventTrigger(findEnemy, inactive);
3040
setEventTrigger(attackStuff, inactive);
3041
setEventTrigger(defendWatch, inactive);
3042
setEventTrigger(defendReturn, inactive);
3043
setEventTrigger(doResearch, inactive);
3044
setEventTrigger(formAllianceEvent, inactive);
3045
setEventTrigger(breakAllianceEvent, inactive);
3046
setEventTrigger(formHumanAlliances, inactive);
3047
setEventTrigger(consolidateEvent, inactive);
3048
setEventTrigger(managePower, inactive);
3049
setEventTrigger(vtolStructs,inactive);
3050
setEventTrigger(buildVtols,inactive);
3051
setEventTrigger(vtolAttack,inactive);
3052
setEventTrigger(vtolDefend,inactive);
3053
setEventTrigger(vtolEnabler,inactive);
3054
setEventTrigger(beaconEv, inactive);
3055
setEventTrigger(multiMsgEv, inactive);
3056
setEventTrigger(manageAllyHelp, inactive);
3057
setEventTrigger(everySecEv, inactive);
3058
setEventTrigger(watchBaseThreat, inactive);
3059
setEventTrigger(manageDefendLocationEv, inactive);
3060
setEventTrigger(structureDestroyed,inactive);
3061
setEventTrigger(rebuildStructureEv,inactive);
3064
event reassignPlayers(reassignTr)
3068
dbg(" AI 5 is reassigningAI to dropped player ", me);
3073
function void reassignAI()
3077
setEventTrigger(basedetails,basedetailsTr);
3078
setEventTrigger(buildDerrick,buildDerrickTr);
3079
setEventTrigger(buildOilDefenseOrRetreat,buildOilDefenseOrRetreatTr);
3080
setEventTrigger(incendry,incendryTr);
3081
setEventTrigger(buildPowerGenerators,buildPowerGeneratorsTr);
3082
setEventTrigger(buildBase,buildBaseTr );
3083
setEventTrigger(buildExpand,buildExpandTr );
3084
setEventTrigger(upgradeStructures,upgradeStructuresTr );
3085
setEventTrigger(finishStructs,finishStructsTr );
3086
setEventTrigger(newfortify,fortifyTr );
3087
setEventTrigger(droidBuilt,droidBuiltTr);
3088
setEventTrigger(droidDestroyed,droidDestroyedTr);
3089
setEventTrigger(conDroids,conDroidsTr);
3090
setEventTrigger(repairDroids,repairDroidsTr);
3091
setEventTrigger(factoryEvent,factoryEventTr);
3092
setEventTrigger(cyborgFactoryEvent,cyborgFactoryEventTr);
3093
setEventTrigger(chooseScoutArea,chooseScoutAreaTr);
3094
setEventTrigger(expandScoutArea,expandScoutAreaTr);
3095
setEventTrigger(scoutMain,scoutMainTr);
3096
setEventTrigger(newObjectReport,newObjectReportTr);
3097
setEventTrigger(takeover,takeoverTr);
3098
setEventTrigger(useLassat,useLassatTr);
3099
setEventTrigger(findEnemy,attackStuffTr);
3100
setEventTrigger(attackStuff,attackStuffTr);
3101
setEventTrigger(doAllOutAttack,allOutAttackTr);
3102
setEventTrigger(defendWatch,defendWatchTr);
3103
setEventTrigger(defendReturn,defendReturnTr);
3104
setEventTrigger(doResearch,doResearchTr);
3105
setEventTrigger(formAllianceEvent,formAllianceEventTr);
3106
setEventTrigger(breakAllianceEvent,breakAllianceEventTr);
3107
setEventTrigger(consolidateEvent,consolidateEventTr);
3108
setEventTrigger(managePower,managePowerTr);
3109
setEventTrigger(vtolStructs,inactive);
3110
setEventTrigger(buildVtols,inactive);
3111
//setEventTrigger(vtolAttack,inactive);
3112
setEventTrigger(vtolAttack, vtolAttackTr);
3113
setEventTrigger(vtolDefend,vtolDefendTr);
3114
setEventTrigger(vtolEnabler,vtolEnablerTr);
3115
setEventTrigger(formHumanAlliances,humanAllianceTr);
3116
setEventTrigger(multiMsgEv, multiMsgTr);
3117
setEventTrigger(beaconEv, beaconTr);
3118
setEventTrigger(watchBaseThreat, watchBaseThreatTr);
3119
setEventTrigger(manageAllyHelp, manageAllyHelpTr);
3120
setEventTrigger(everySecEv, everySec);
3121
//setEventTrigger(manageDefendLocationEv, manageDefendLocationTr);
3122
setEventTrigger(structBuilt, structBuiltTr);
3123
setEventTrigger(structureDestroyed, structureDestroyedTr);
3124
setEventTrigger(rebuildStructureEv, rebuildStructureTr);
3127
/* Returns true if we just received a beacon from a certain player */
3128
function bool haveBeacon(int _player)
3130
if((tBeacon[_player] > 0) and (not beaconTimeout(_player)))
3132
return TRUE; //have beacon for this player
3138
/* See if last beacon was placed long ago */
3139
function bool beaconTimeout(int _player)
3141
if((tBeacon[_player] > 0) and
3142
((tBeacon[_player] + BEACON_TIMEOUT) < (gameTime / 10))) //not too long ago
3144
return TRUE; //this beacon is still 'fresh'
3150
/* Deal with beacons */
3151
event beaconEv(beaconTr)
3154
local string _processedString;
3157
debug(me & ") beaconEv: from " & sender);
3159
ASSERT(sender >= 0 and sender < 8,
3160
"beaconEv: sender out of bounds: " & sender , me);
3162
beaconX[sender] = x;
3163
beaconY[sender] = y;
3164
tBeacon[sender] = gameTime / 10;
3166
processCommand(message, sender, TRUE);
3169
/* Deal with a chat message */
3170
event multiMsgEv(multiMsgTr)
3173
debug(me & ") multiMsgEv: from " & sender);
3175
if(not allianceExistsBetween(me, sender)){
3183
processCommand(message, sender, FALSE);
3186
/* Process multiplayer messages */
3187
function void processCommand(string _message, int _sender, bool _bBlipMessage)
3189
local int _numMsgs,_curMsg,_addressedPlayers,_x,_y;
3190
local string _msg,_processedString;
3192
/* Extract semantic information */
3194
_numMsgs = processChatMsg(_message);
3196
debug(me & ") processCommand: '" & _message & "' from " & _sender);
3197
dbg("processCommand: '" & _message & "' from " & _sender, me);
3198
dbg("got " & _numMsgs & " commands", me);
3200
/* Process all messages */
3201
while(_curMsg < _numMsgs)
3203
if(chatCmdIsPlayerAddressed(_curMsg, me))
3205
dbg("i'm addressed", me);
3206
_msg = getChatCmdDescription(_curMsg);
3208
/* Someone requested help */
3209
if(_msg == R_REQUEST_HELP)
3211
dbg("'help' command", me);
3213
if(haveBeacon(_sender))
3215
dbg("got beacon", me);
3217
_x = beaconX[_sender];
3218
_y = beaconY[_sender];
3220
if(attemptToHelp(_sender, _x, _y))
3222
messagePlayer(ALL_ALLIES, m_affirmative(), MAX_PROBABILITY);
3227
/* Ask player to drop a beacon so we would know where to help */
3228
_addressedPlayers = setBit(0, _sender, TRUE);
3229
messagePlayerAddressed(ALL_ALLIES, _addressedPlayers, R_REQUEST_BEACON);
3232
/* Someone requested a beacon from us -
3233
* did we request help and our beacon timed out??
3235
else if(_msg == M_REQUEST_BEACON)
3237
/* If our base is really in trouble drop a beacon for the requester again */
3238
if(baseInTrouble()){
3239
dropBeacon(getPlayerName(me), _sender, me, baseX, baseY, 0);
3242
else if(_msg == R_REPORT_SAFETY)
3244
dbg("helping " & lastHelpPlayer, me);
3246
/* Make sure we were helping him */
3247
if(helpingAlly() and (lastHelpPlayer == _sender))
3250
messagePlayer(ALL_ALLIES, m_affirmative(), MAX_PROBABILITY);
3252
else if(defendingOwnBase()) //if we are in trouble re-request help
3254
requestHelp(baseX, baseY);
3259
dbg("unknown message", me);
3265
dbg("i'm not addressed", me);
3272
function bool attemptToHelp(int _playerToHelp, int _x, int _y)
3274
local bool _bHelpingMyself;
3276
if(_playerToHelp < 0 or _playerToHelp >= MAX_PLAYERS){
3280
if(_x <= 0 or _y <= 0){
3284
dbg("attemptToHelp - checking", me);
3286
_bHelpingMyself = (_playerToHelp == me);
3288
/* Can only help allies and myself */
3289
if(not friendlyPlayer(_playerToHelp)){
3293
if(_bHelpingMyself or !helpingAlly() or (lastHelpPlayer == _playerToHelp) ) //if not helping any other ally or it's me who needs help
3295
dbg("not busy helping", me);
3297
if(haveHelpers() or _DEBUG)
3299
dbg("got attackers", me);
3300
if(allyBaseAtLoc(_playerToHelp, _x, _y)) //is he just trying to misuse us?
3302
helpPlayer(_playerToHelp, _x, _y);
3307
dbg("ally needs no help", me);
3308
messagePlayer(ALL_ALLIES, M_ANNOYED, MAX_PROBABILITY / 2);
3313
messagePlayer(ALL_ALLIES, M_HELP_NO_UNITS, MAX_PROBABILITY);
3316
else if((lastHelpPlayer >= 0) and (lastHelpPlayer < MAX_PLAYERS))
3318
if(!_bHelpingMyself){
3319
messagePlayer(ALL_ALLIES, "helping " & getPlayerName(lastHelpPlayer) & " already", MAX_PROBABILITY);
3326
/* Start helping player */
3327
function void helpPlayer(int _playerToHelp, int _helpX, int _helpY)
3329
local int _tTravelTime;
3331
dbg("helping " & _playerToHelp, me);
3334
debug(me & ") helpPlayer: '" & _playerToHelp);
3336
/* Move scoutes to attackers */
3337
groupAddGroup(attackGroup, scoutGroup);
3339
//Calculate travel time, assume ~ 150 tiles in 4 minutes
3340
if(attackGroup.members == 0){
3341
_tTravelTime = (int)((float)(distBetweenTwoPoints(baseX, baseY, _helpX, _helpY) / 128 ) * 1.7);
3343
_tTravelTime = (int)((float)(distBetweenTwoPoints(attackGroup.x, attackGroup.y, _helpX, _helpY) / 128 ) * 1.7);
3346
tHelp = gameTime / 10;
3347
tHelpTimeout = (gameTime / 10) + BASE_DEFEND_DURATION + _tTravelTime;
3348
lastHelpPlayer = _playerToHelp;
3352
/* Scouts and attackers go to help */
3353
defendLocation(_helpX, _helpY, tHelpTimeout, BASE_DEFEND_RADIUS, (_playerToHelp == me));
3356
/* Returns a random affirmative responce */
3357
function string m_affirmative()
3364
return M_AFFIRMATIVE_ROGER;
3367
return M_AFFIRMATIVE_OK;
3370
/* See if there are any base structures belonging to ally at a certain location */
3371
function bool allyBaseAtLoc(int _ally, int _x, int _y)
3373
local int _structIndex;
3375
if(_x <= 0 or _y <= 0){
3379
if(_ally < 0 or _ally >= MAX_PLAYERS){
3384
while(_structIndex < numBaseStruct)
3386
if(numStructsByStatInRange(baseStruct[_structIndex], _x, _y, (7 * 128), me, _ally) > 0 )
3397
event manageAllyHelp(manageAllyHelpTr)
3401
if(canStopHelpingAlly())
3407
// /* See if all units we sent were killed */
3408
// if(not haveHelpers())
3410
// if(random(4) == 0)
3412
// messagePlayer(lastHelpPlayer, M_HELPERS_KILLED);
3415
// if(not attemptToHelp(lastHelpPlayer, helpX, helpY))
3417
// dbg("NO UNITS, STOPPED HELPING", me);
3418
// stopHelpingAlly(); //don't make sense to try again
3422
// dbg("SENDING REINFORCEMENTS", me);
3429
event everySecEv(everySec)
3431
/* Check if we were helping long enough */
3434
if(helpAllyTimeout())
3440
if(defendingLocation())
3442
if(defendLocationTimeout())
3444
stopDefendingLocation();
3449
/* Do we have any units we can send to help ally ? */
3450
function bool haveHelpers()
3452
if(attackGroup.members == 0){
3459
function bool helpingAlly()
3461
if(lastHelpPlayer >= 0){
3468
/* Returns true if we were helping long enough */
3469
function bool helpAllyTimeout()
3471
if(tHelpTimeout < (gameTime / 10) ){
3478
function bool canStopHelpingAlly()
3480
if(lastHelpPlayer < 0)
3482
ASSERT(FALSE, "canStopHelpingAlly: lastHelpPlayer < 0", me);
3486
/* Were helping long enough or someone's backstabbing */
3487
if(!friendlyPlayer(lastHelpPlayer)){
3491
/* Nothing to defend anymore */
3492
if(!allyBaseAtLoc(lastHelpPlayer, helpX, helpY)){
3499
function void stopHelpingAlly()
3501
dbg("stopped helping", me);
3505
lastHelpPlayer = -1;
3509
stopDefendingLocation();
3512
/* Send a multiplayer message to an ally */
3513
function void messagePlayer(int _playerToMessage, string _message, int _probability)
3517
ASSERT(_playerToMessage >= -1 && _playerToMessage < MAX_PLAYERS,
3518
"messagePlayer: player out of bounds: " & _playerToMessage, me);
3521
if( random(MAX_PROBABILITY) >= _probability ){
3526
if(_playerToMessage == ALL_ALLIES) //everyone
3528
while(_player < MAX_PLAYERS)
3530
/* Send message (allies only)) */
3531
if(allianceExistsBetween(me, _player))
3533
msg(_message, me, _player);
3539
else //a certain player
3541
/* Send message (allies only)) */
3542
if(allianceExistsBetween(me, _playerToMessage))
3544
msg(_message, me, _playerToMessage);
3549
function int numBitsSet(int _integer)
3551
local int _position,_result;
3555
while(_position < 8)
3557
if(getBit(_integer, _position))
3567
/* Send a multiplayer message, addressing some player(s) */
3568
function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message)
3570
local int _player,_totalAddressed,_curAddressed;
3571
local string _adrMessage;
3573
_totalAddressed = numBitsSet(_playersToAddress);
3575
ASSERT(_totalAddressed > 0, "messagePlayerAddressed: no players addressed", me);
3581
while(_player < MAX_PLAYERS)
3583
if(getBit(_playersToAddress, _player))
3587
_adrMessage = _adrMessage & getPlayerName(_player);
3589
//if(_totalAddressed == 1){ //one only
3590
// _adrMessage = getPlayerName(_player);
3593
if(_totalAddressed > 1)
3595
if(_curAddressed == _totalAddressed){ //end
3596
_adrMessage = _adrMessage & " and " & getPlayerName(_player);
3598
_adrMessage = _adrMessage & ", " & getPlayerName(_player);
3606
_message = _adrMessage & " " & _message;
3608
//Now send the message to all players addressed
3609
messagePlayer(_playerToMessage, _message, MAX_PROBABILITY);
3612
/* Returns true if we can see our allies on the map */
3613
function bool canSeeAllies()
3615
local STRUCTURE _uplink;
3617
/* Can see allies when team mode is on */
3618
if(multiPlayerAlliancesType == ALLIANCES_TEAMS)
3623
/* Can see whole map if we have uplink */
3624
_uplink = getStructure(uplink, me);
3625
if(_uplink != NULLOBJECT)
3627
/* Make sure finished building */
3628
if(structureComplete(_uplink))
3637
function bool defendingOwnBase()
3639
if(helpingAlly() && lastHelpPlayer == me){
3646
/* Call for help when our base is in danger */
3647
event watchBaseThreat(watchBaseThreatTr)
3649
/* See if we can stop defending */
3650
if(defendingOwnBase())
3652
if(numEnemiesInBase(FALSE) == 0)
3654
stopHelpingAlly(); //stop defending our own base
3656
/* Let allies know we don't need their help anymore */
3657
messagePlayer(ALL_ALLIES, R_REPORT_SAFETY, MAX_PROBABILITY);
3662
/* See if our base is in trouble and we need help */
3665
if(!defendingOwnBase()) //make sure not already defending the base
3668
debug(me & ") watchBaseThreat: base in trouble");
3670
dbg("watchBaseThreat: base in trouble", me);
3672
/* Bring our forces back if needed */
3678
/* Defend my own base */
3679
helpPlayer(me, baseX, baseY);
3682
/* Request help once in a while */
3683
requestHelp(baseX, baseY);
3688
function int numAlliesInBase(bool _bVtols)
3690
local int _numAllies;
3692
_numAllies = numFriendlyWeapDroidsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, _bVtols);
3693
_numAllies = _numAllies +
3694
numFriendlyWeapStructsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, true) / 3;
3699
function int numEnemiesInBase(bool _bVtols)
3701
local int _numEnemies;
3703
_numEnemies = numEnemyWeapDroidsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, _bVtols);
3704
_numEnemies = _numEnemies +
3705
numEnemyWeapStructsInRange(me, baseX, baseY, W_BASE_THREAT_RANGE, true) / 4;
3710
/* Returns true if our base is in trouble */
3711
function bool baseInTrouble()
3713
local int _enemyForce,_friendlyForce;
3715
_friendlyForce = numAlliesInBase(FALSE);
3716
_enemyForce = numEnemiesInBase(FALSE);
3718
/* See if we are in trouble */
3719
if((_enemyForce > 0) && (_enemyForce >= _friendlyForce)){
3720
dbg("baseInTrouble: " & _enemyForce & " >= " & _friendlyForce, me);
3727
/* Request help from allies */
3728
function void requestHelp(int _helpX, int _helpY)
3730
/* Don't do this too frequently */
3731
if(tLastHelpRequest + HELP_REQUEST_INTERVAL > (gameTime / 10) ){
3735
doRequestHelp(_helpX, _helpY);
3738
function void doRequestHelp(int _helpX, int _helpY)
3742
/* Remember when we requested help last time */
3743
tLastHelpRequest = gameTime / 10;
3745
/* Drop beacon for all allies so they would know where to help */
3747
while(_ally < MAX_PLAYERS)
3749
if(allianceExistsBetween(me, _ally)){
3751
debug(me & ") requestHelp: " & _ally);
3753
dropBeacon(getPlayerName(me), _ally, me, _helpX, _helpY, 0);
3758
/* Now send message with help request */
3759
messagePlayer(ALL_ALLIES, M_REQUEST_HELP, MAX_PROBABILITY);
3762
function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, int _defendRadius, bool _bMove)
3764
dbg("starting defending for " & _tDefendTimeout - (gameTime / 10) & " secs, with defend radius " & _defendRadius, me);
3766
ASSERT(_defendRadius >= TILE,
3767
"defendLocation: defendRadius too low:" & _defendRadius, me);
3772
defendRadius = _defendRadius;
3773
tDefendStart = gameTime / 10;
3775
/* Should already include travel time */
3776
tDefendTimeout = _tDefendTimeout;
3778
/* See if we have to move or scout */
3779
defendMoveType = DORDER_SCOUT;
3781
defendMoveType = DORDER_MOVE;
3784
/* Send attackers */
3785
if(attackGroup.members > 0)
3787
if(distBetweenTwoPoints(attackGroup.x, attackGroup.y, _defendX, _defendY) > _defendRadius)
3789
orderGroupLoc(attackGroup, defendMoveType, _defendX, _defendY);
3793
setEventTrigger(manageDefendLocationEv, manageDefendLocationTr);
3796
function void stopDefendingLocation()
3798
dbg("stopped defending location", me);
3806
tDefendTimeout = -1;
3808
defendMoveType = -1;
3810
setEventTrigger(manageDefendLocationEv, inactive);
3812
orderGroupLoc(attackGroup, DORDER_SCOUT,baseX,baseY);
3815
function bool defendingLocation()
3817
if(defendX > 0 and defendY > 0){
3824
event manageDefendLocationEv(inactive)
3828
dbg("manageDefendLocationEv", me);
3830
ASSERT(defendRadius >= TILE,
3831
"manageDefendLocationEv: defendRadius too low:" & defendRadius, me);
3833
ASSERT(defendMoveType == DORDER_MOVE || defendMoveType == DORDER_SCOUT,
3834
"manageDefendLocationEv: wrong move order:" & defendMoveType, me);
3836
ASSERT(defendX > 0 && defendY > 0,
3837
"manageDefendLocationEv: x/y coordinates:" & defendX & "/" & defendY, me);
3839
if(!(defendX > 0 && defendY > 0)){
3840
dbg("not defending???????", me);
3841
exit; //not defending?
3844
/* Collect attackers */
3845
initIterateGroup(attackGroup);
3846
_droid = iterateGroup(attackGroup);
3847
while(_droid != NULLOBJECT)
3849
if(distBetweenTwoPoints(_droid.x,_droid.y,defendX,defendY) > defendRadius) //too far from defend location
3851
if(distBetweenTwoPoints(_droid.orderx,_droid.ordery,defendX,defendY) > defendRadius) //not already on its way to the defend location
3853
orderDroidLoc(_droid, defendMoveType, defendX, defendY);
3856
_droid = iterateGroup(attackGroup);
3860
function bool defendLocationTimeout()
3862
if(tDefendTimeout < (gameTime / 10) ){
3869
/* Returns true if player in question is my ally or if it's me */
3870
function bool friendlyPlayer(int _playerToCheck)
3872
if(allianceExistsBetween(_playerToCheck, me) or (_playerToCheck == me)){
3879
function bool insideBase(int _x, int _y)
3900
function FEATURE closestOil(int _x, int _y, bool _bAvoidThreat)
3902
local FEATURE _oil,_closestOil;
3903
local int _bestDist,_newDist;
3906
_closestOil = NULLOBJECT;
3908
initGetFeature(oilRes,me,me);
3909
_oil = getFeatureB(me);
3910
while(_oil != NULLOBJECT)
3912
_newDist = distBetweenTwoPoints(_x, _y, _oil.x, _oil.y);
3914
if(_newDist < _bestDist) //this one is closer
3916
if( !(_bAvoidThreat && threatInRange(me, _oil.x, _oil.y, OIL_THREAT_RANGE, FALSE)) )
3918
_bestDist = _newDist;
3922
_oil = getFeatureB(me);
3928
event keyPressed(CALL_KEY_PRESSED, ref count, ref count2)
3930
if(count == KEY_P and (count2 == KEY_RCTRL or count2 == KEY_LCTRL))
3935
console("add power");
3940
event watchMenu(everySec)
3944
if(vtolGrAttackObj[0] == NULLOBJECT){
3945
setDebugMenuEntry("0 - " & vtolAttackGr[0].members, 0);
3947
setDebugMenuEntry("0 " & vtolAttackGr[0].members & " - " & (vtolGrAttackObj[0].x / TILE) & "-" & (vtolGrAttackObj[0].y / TILE), 0);
3950
if(vtolGrAttackObj[1] == NULLOBJECT){
3951
setDebugMenuEntry("1 - " & vtolAttackGr[1].members, 1);
3953
setDebugMenuEntry("1 " & vtolAttackGr[1].members & " - " & (vtolGrAttackObj[1].x / TILE) & "-" & (vtolGrAttackObj[1].y / TILE), 1);
3956
if(vtolGrAttackObj[2] == NULLOBJECT){
3957
setDebugMenuEntry("2 - " & vtolAttackGr[2].members, 2);
3959
setDebugMenuEntry("2 " & vtolAttackGr[2].members & " - " & (vtolGrAttackObj[2].x / TILE) & "-" & (vtolGrAttackObj[2].y / TILE), 2);
3962
if(vtolGrAttackObj[3] == NULLOBJECT){
3963
setDebugMenuEntry("3 - " & vtolAttackGr[3].members, 3);
3965
setDebugMenuEntry("3 " & vtolAttackGr[3].members & " - " & (vtolGrAttackObj[3].x / TILE) & "-" & (vtolGrAttackObj[3].y / TILE), 3);
3968
if(vtolGrAttackObj[4] == NULLOBJECT){
3969
setDebugMenuEntry("4 - " & vtolAttackGr[4].members, 4);
3971
setDebugMenuEntry("4 " & vtolAttackGr[4].members & " - " & (vtolGrAttackObj[4].x / TILE) & "-" & (vtolGrAttackObj[4].y / TILE), 4);
3974
if(vtolGrAttackObj[5] == NULLOBJECT){
3975
setDebugMenuEntry("5 - " & vtolAttackGr[5].members, 5);
3977
setDebugMenuEntry("5 " & vtolAttackGr[5].members & " - " & (vtolGrAttackObj[5].x / TILE) & "-" & (vtolGrAttackObj[5].y / TILE), 5);
3981
setDebugMenuEntry("total " & countRebuildStruct, 0);
3982
setDebugMenuEntry("x1=" & rebuildStructX[0], 1);
3983
setDebugMenuEntry("y1=" & rebuildStructY[0], 2);
3984
setDebugMenuEntry("x2=" & rebuildStructX[1], 3);
3985
setDebugMenuEntry("y2=" & rebuildStructY[1], 4);
3986
setDebugMenuEntry("x3=" & rebuildStructX[2], 5);
3987
setDebugMenuEntry("y3=" & rebuildStructY[2], 6);
3988
setDebugMenuEntry("x4=" & rebuildStructX[3], 7);
3989
setDebugMenuEntry("y4=" & rebuildStructY[3], 8);*/
3993
//---------------------------------------------------------------
3994
//Returns how many droids are already on the way to build the
3995
//same structure on the same spot (like helpbuild)
3996
//---------------------------------------------------------------
3997
function int numBuildSameBuilding(STRUCTURESTAT _checkStat, int _x, int _y)
3999
local int _numSameBuilding;
4002
_numSameBuilding = 0;
4004
initIterateGroup(buildGroup);
4005
_truck = iterateGroup(buildGroup);
4006
while(_truck != NULLOBJECT)
4008
if((_truck.order == DORDER_BUILD) or (_truck.order == DORDER_HELPBUILD) or (_truck.order == DORDER_LINEBUILD))
4010
if((_checkStat == NULLSTRUCTURESTAT) or (_truck.stat == _checkStat)) //Same struct type
4013
if((_x < 0) or (distBetweenTwoPoints(_x, _y, _truck.orderx , _truck.ordery) <= TILE))
4019
_truck = iterateGroup(buildGroup);
4022
return _numSameBuilding;
4025
// returns number of droids in a certain group with the same order
4026
function int numGroupSameOrder(GROUP _group, int _orderIndex)
4028
local int _numDroids;
4033
initIterateGroup(_group);
4034
_droid = iterateGroup(_group);
4035
while(_droid != NULLOBJECT)
4037
if(_droid.order == _orderIndex) //right order type
4041
_droid = iterateGroup(_group);
4047
// Remember certain destroyed structures so we can rebuild them later
4048
event structureDestroyed(structureDestroyedTr)
4053
// add certain structures to the rebuild list
4055
while(_count < numRebuildStat[curTech])
4057
if(structure.stat == rebuildStat[curTech][_count])
4059
if(countRebuildStruct < MAX_REBUILD_STRUCT)
4061
rebuildStructX[countRebuildStruct] = structure.x;
4062
rebuildStructY[countRebuildStruct] = structure.y;
4063
rebuildStructStat[countRebuildStruct] = structure.stat;
4064
countRebuildStruct++;
4066
dbg("remembered structure (" & countRebuildStruct & ") - " & structure.x & "/" & structure.y, me);
4075
// Rebuild structures that were destroyed
4076
event rebuildStructureEv(rebuildStructureTr)
4078
rebuildStructures();
4081
function void rebuildStructures()
4083
local int _count,_threatRange,_x,_y;
4085
local STRUCTURESTAT _stat;
4087
_threatRange = (TILE * 8);
4090
while(_count < countRebuildStruct)
4092
if(!threatInRange(me, rebuildStructX[_count], rebuildStructY[_count], _threatRange, FALSE))
4094
if(getTileStructure(_x / TILE, _y / TILE) == NULLOBJECT)
4096
_stat = rebuildStructStat[_count];
4097
_x = rebuildStructX[_count];
4098
_y = rebuildStructY[_count];
4100
_truck = closestIdleTruck(_x, _y);
4102
if(_truck != NULLOBJECT)
4104
if(numBuildSameBuilding(_stat, _x, _y) == 0) //make sure no one is building already
4106
buildOnExactLocation(_truck, _x, _y, _stat);
4115
function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat)
4117
local int _newX,_newY;
4119
if(_truck == NULLOBJECT)
4127
if(pickStructLocationB(_stat, ref _newX, ref _newY, me, -1))
4129
dbg("trying to rebuild on (" & _newX & "/" & _newY & ")", me);
4131
if((_x != _newX) or (_y != _newY))
4136
orderDroidStatsLoc(_truck, DORDER_BUILD, _stat, _x, _y);
4137
//dbg("rebuilding structure after!! (" & _x & "/" & _y & ")", me);
4141
// Get idle truck closest to some location
4142
function DROID closestIdleTruck(int _x, int _y)
4144
local DROID _closestTruck, _tempTruck;
4145
local int _closestDist, _tempDist;
4147
_closestTruck = NULLOBJECT;
4148
_closestDist = 99999;
4150
initIterateGroup(buildGroup);
4151
_tempTruck = iterateGroup(buildGroup);
4152
while(_tempTruck != NULLOBJECT)
4154
if((_tempTruck.order == DORDER_NONE) or (_tempTruck.order == DORDER_RTB))
4156
_tempDist = distBetweenTwoPoints(_x, _y, _tempTruck.x, _tempTruck.y);
4157
if(_tempDist < _closestDist)
4159
_closestDist = _tempDist;
4160
_closestTruck = _tempTruck;
4163
_tempTruck = iterateGroup(buildGroup);
4166
return _closestTruck;
4169
event consoleEv(consoleTr)
4171
//turn on 'autogame'
4172
if(message == "autogame on" && (sender == me))
4174
if(debugModeEnabled())
4176
if(myResponsibility(me))
4178
if(not bRunning) //make sure current machine is responsible for this AI and it's not already active
4180
console(getPlayerName(me) & " is active");
4188
//turn off 'autogames'
4189
if(message == "autogame off" && debugModeEnabled() && (sender == me))
4191
if(bRunning) //make sure this AI is active
4193
console(getPlayerName(me) & " is deactivated");
4199
if(message == "aidebug on")
4201
console(getPlayerName(me) & " ai debug is on");
4203
dbgMsgOn(me, _DEBUG);
4205
else if(message == "aidebug off")
4207
console(getPlayerName(me) & " ai debug is off");
4209
dbgMsgOn(me, _DEBUG);