~ubuntu-branches/ubuntu/lucid/warzone2100/lucid

« back to all changes in this revision

Viewing changes to data/multiplay/skirmish/player5.slo

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger, Paul Wise, Christoph Egger
  • Date: 2009-06-29 17:12:52 UTC
  • mfrom: (1.1.11 upstream) (2.1.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090629171252-5ddnlfg3zfchrega
Tags: 2.2.1+dfsg1-1
[ Paul Wise ]
* New upstream release (Closes: #534962)
* Adjust the flex build-depends to take account of the conflict
  with all the versions of flex 2.5.34 (LP: #372872)
* Make the -music Recommends more strict, 2.1 music doesn't work
  with 2.2.
* Upstream moved the downloads to sourceforge, update the watch file
* Bump Standards-Version, no changes needed
* Drop use of dh_desktop since it no longer does anything
* Recommend the new warzone2100-video package, version 2.2 or similar
* Mention the warzone2100 crash reports in the -dbg package description

[ Christoph Egger ]
* Replace CC-2.0 graphic from cybersphinx, create a new tarball
* Add myself to uploaders

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/////////////////////////////////////////////////////////////////////
2
 
// general ai for skirmish game
3
 
/////////////////////////////////////////////////////////////////////
4
 
// Warzone2100, Pumpkin Studios,
5
 
// alex lee.98/99.
6
 
//
7
 
/////////////////////////////////////////////////////////////////////
8
 
 
9
 
//Tile in world units
10
 
#define TILE                                    128
11
 
#define NONE                                    (-1)
12
 
 
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"
18
 
 
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"
27
 
 
28
 
#define MAX_PROBABILITY                 100
29
 
 
30
 
// Base threat range in world units
31
 
#define W_BASE_THREAT_RANGE             ((17 + (mapWidth + mapHeight) / 2 / 35) * TILE)
32
 
#define ALL_ALLIES                              -1
33
 
#define MAX_PLAYERS                             8
34
 
 
35
 
#define BASE_DEFEND_DURATION    (3 * 60)
36
 
#define BASE_DEFEND_RADIUS              (15 * TILE)
37
 
 
38
 
// Delay before we repeat our request, in seconds
39
 
#define HELP_REQUEST_INTERVAL   (3 * 60)
40
 
 
41
 
//in secs
42
 
#define BEACON_TIMEOUT                  30
43
 
 
44
 
#define MAX_DROIDS                              150
45
 
 
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)
50
 
 
51
 
#define MAX_TRUCKS                              12
52
 
#define MIN_TRUCKS                              5
53
 
 
54
 
//Enter power saving mode when lower than this
55
 
#define LOW_POWER                               250
56
 
 
57
 
//Target type values
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
66
 
 
67
 
#define UNLIMITED                               (-1)
68
 
 
69
 
#define AA_THREAT_RANGE                 (TILE * 12)
70
 
 
71
 
#define MAX_DEFENDERS_RADIUS    (TILE * 40)
72
 
 
73
 
#define MAX_VTOL_DEFEND_RADIUS  (TILE * 25)
74
 
 
75
 
// AI will remember max this number of structures
76
 
#define MAX_REBUILD_STRUCT              100
77
 
 
78
 
//Total number of technology branches
79
 
#define TECHS                                   2
80
 
 
81
 
//How many best templates to choose from when deciding what template to build
82
 
#define MAX_RANDOM_TEMPLATES    4
83
 
 
84
 
 
85
 
 
86
 
public  int                             me;                     // player for this instance.
87
 
public  int                             tileExpand;                     // rate of exploration
88
 
 
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];
93
 
 
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];
98
 
 
99
 
// structures
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;
107
 
 
108
 
// unit templates
109
 
public  int                             numTemplates[TECHS];
110
 
public  TEMPLATE                tmpl[TECHS][70];
111
 
private TEMPLATE                tmplChoice[5];
112
 
 
113
 
public  TEMPLATE                cybTempl[10],superCyb[4],cybMechanic,cybEngineer;
114
 
 
115
 
public  TEMPLATE                vtols[18];
116
 
public  int                             numVtolTemplates;
117
 
 
118
 
public  TEMPLATE                sense[11];
119
 
public  int                             numSenseTemplates;
120
 
 
121
 
public  TEMPLATE                constructor,repairUnit;
122
 
public  int                             numRepairUnits;
123
 
 
124
 
//defend
125
 
private GROUP                   defendGroup;
126
 
private bool                    defendbusy;
127
 
private BASEOBJ                 defendObj;
128
 
 
129
 
public  RESEARCHSTAT    nexusDefence;
130
 
 
131
 
//build
132
 
private GROUP                   buildGroup;
133
 
private int                             buildX,buildY,buildX2,buildY2;
134
 
public  FEATURESTAT             oilRes;
135
 
 
136
 
// scout
137
 
private GROUP                   scoutGroup;
138
 
private int                             scoutX,scoutY;
139
 
private int                             scoutTLX,scoutTLY,scoutW,scoutH;
140
 
 
141
 
// attack
142
 
private GROUP                   attackGroup;
143
 
private BASEOBJ                 attackObj,allOutAttack,vtolGrAttackObj[10];
144
 
 
145
 
// vtols
146
 
private GROUP                   vtolDefendGr,vtolAttackGr[10];
147
 
 
148
 
// generic
149
 
private STRUCTURE               structure,structure2,rebuildObj[100];
150
 
private DROID                   droid;
151
 
private FEATURE                 feature;
152
 
private BASEOBJ                 baseobj,baseobj2;
153
 
private int                             count,count2,result,result2,tempx,tempy;
154
 
private bool                    boolResult,boolResult2;
155
 
 
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;
161
 
 
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];
166
 
 
167
 
/////////////////////////////////////////////////////////////////////
168
 
// triggers.
169
 
 
170
 
#region triggers
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);
220
 
 
221
 
/* Events */
222
 
event   multiMsgEv;
223
 
event   beaconEv;
224
 
event   watchBaseThreat;
225
 
event   manageAllyHelp;
226
 
event   everySecEv;
227
 
event   manageDefendLocationEv;
228
 
event   structureDestroyed;
229
 
event   rebuildStructureEv;
230
 
 
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);
293
 
#endregion triggers
294
 
 
295
 
/////////////////////////////////////////////////////////////////////
296
 
// HouseKeeping
297
 
event initialisedEvent(CALL_GAMEINIT)
298
 
{
299
 
        // initialise
300
 
        _DEBUG = FALSE;
301
 
        dbgMsgOn(me, _DEBUG);
302
 
 
303
 
        extraStruct = 0;
304
 
        numRepairUnits = 0;
305
 
        allOutAttack = NULLOBJECT;
306
 
        powerSave = FALSE;
307
 
 
308
 
        tLastHelpRequest = -1;  //when we requested help for the last time
309
 
 
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
313
 
        helpX = -1;
314
 
        helpY = -1;
315
 
 
316
 
        defendX = -1;
317
 
        defendY = -1;
318
 
        defendRadius = -1;
319
 
        tDefendStart = -1;
320
 
        tDefendTimeout = -1;
321
 
        defendMoveType = -1;            //move or scout
322
 
 
323
 
        baseRange = 4 * TILE;
324
 
 
325
 
        // set current research branch
326
 
        setTechBranch(-1);
327
 
        //setTechBranch(branchVTOL);
328
 
 
329
 
        numVtolAttackGroups = 10;
330
 
        numAttackVtols = 10;    //num vtols in an attack group
331
 
        numDefendVtols = 5;     //num vtols in an attack group
332
 
 
333
 
        // setup build 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
337
 
 
338
 
        // note where our base is.
339
 
        initIterateGroup(buildGroup);           // find idle droids in build group.
340
 
        droid = iterateGroup(buildGroup);
341
 
        if(droid != NULLOBJECT)
342
 
        {
343
 
                baseX = droid.x;
344
 
                baseY = droid.y;
345
 
 
346
 
                if(aiResponsibleForPlayer(me))
347
 
                {
348
 
                        expandBase(droid);
349
 
                }
350
 
        }
351
 
        else
352
 
        {
353
 
                baseX = (128*mapWidth)/2;
354
 
                baseY = (128*mapHeight)/2;
355
 
        }
356
 
 
357
 
        // defence.
358
 
        defendbusy = FALSE;
359
 
 
360
 
        // setup scouts
361
 
        structure = getStructure(factory, me);
362
 
        if(structure != NULLOBJECT)
363
 
        {
364
 
                scoutTLX                = structure.x;
365
 
                scoutTLY                = structure.y;
366
 
        }
367
 
        else
368
 
        {
369
 
                scoutTLX                = baseX;
370
 
                scoutTLY                = baseY;
371
 
        }
372
 
        scoutW                  = 256;
373
 
        scoutH                  = 256;
374
 
        scoutX                  = scoutTLX;
375
 
        scoutY                  = scoutTLY;
376
 
 
377
 
        // clear the alliance array...
378
 
        allianceTime[0] = 0;
379
 
        allianceTime[1] = 0;
380
 
        allianceTime[2] = 0;
381
 
        allianceTime[3] = 0;
382
 
        allianceTime[4] = 0;
383
 
        allianceTime[5] = 0;
384
 
        allianceTime[6] = 0;
385
 
        allianceTime[7] = 0;
386
 
        
387
 
        bRunning = false;
388
 
 
389
 
        if(aiResponsibleForPlayer(me))
390
 
        {
391
 
                bRunning = true;
392
 
                buildTruck();
393
 
        }
394
 
        else
395
 
        {
396
 
                shutDownAI();
397
 
        }
398
 
}
399
 
 
400
 
// decide what technology branch we will use
401
 
function void setTechBranch(int _tech)
402
 
{
403
 
        local float             _y2,_y1,_x2,_x1,_a,_y,_m,_rnd,_mapSize;
404
 
 
405
 
        _mapSize = (float)((mapWidth + mapHeight) / 2);
406
 
 
407
 
        if(_tech != -1)
408
 
        {
409
 
                curTech = _tech;
410
 
        }
411
 
        else
412
 
        {
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));
418
 
                _a = -(_m * _x1);
419
 
 
420
 
                //calculate probability for the current map
421
 
                _y = _m * _mapSize + _a;
422
 
 
423
 
                dbg("_m = " & _m & ", a = " & _a, me);
424
 
 
425
 
                _rnd = (float)random(100);
426
 
                if(_rnd  < _y)
427
 
                {
428
 
                        curTech = branchVTOL;
429
 
                        dbg("going air (" & _y & "/" & _rnd & ")", me);
430
 
                }
431
 
                else
432
 
                {
433
 
                        curTech = branchDefault;
434
 
                        dbg("going land (" & _y & "/" & _rnd & ")", me);
435
 
                }
436
 
        }
437
 
}
438
 
 
439
 
/* returns TRUE if AI is responsible for the _player */
440
 
function bool aiResponsibleForPlayer(int _player)
441
 
{
442
 
        if(not _DEBUG and ((_player == selectedPlayer) or not myResponsibility(_player)))
443
 
        {
444
 
                return FALSE;
445
 
        }
446
 
 
447
 
        return TRUE;
448
 
}
449
 
 
450
 
/////////////////////////////////////////////////////////////////////
451
 
// initial force setup thing. plonk down a force.
452
 
event givehelp(every, 100)
453
 
{
454
 
 
455
 
        if(multiPlayerBaseType == CAMP_WALLS)
456
 
        {
457
 
                // free power
458
 
                addPower(1500, me);
459
 
 
460
 
                // free droids.
461
 
                /* structure = getStructure(factory, me);
462
 
                if(structure != NULLOBJECT)
463
 
                {
464
 
                        count = 0;
465
 
                        while(count<10)
466
 
                        {
467
 
                                tempx = baseX;
468
 
                                tempy = baseY;
469
 
 
470
 
 
471
 
                                boolResult = pickStructLocation(defStructs[0], ref tempx, ref tempy,me);
472
 
                                if(boolResult == TRUE)
473
 
                                {
474
 
                                        droid = addDroid(tmpl[curTech][ random(6) ]  , tempx, tempy, me);
475
 
                                }
476
 
 
477
 
                                count = count + 1;
478
 
                        }
479
 
                } */
480
 
        }
481
 
        setEventTrigger(givehelp,       inactive);
482
 
 
483
 
}
484
 
 
485
 
/////////////////////////////////////////////////////////////////////
486
 
// keep details about the size and postion of the ai players base
487
 
event basedetails(basedetailsTr)
488
 
{
489
 
 
490
 
        // clear old extremities.
491
 
        maxy = 0;
492
 
        maxx = 0;
493
 
        miny = (mapHeight*128);
494
 
        minx = (mapWidth*128);
495
 
 
496
 
        baseRange = 4 * TILE;
497
 
 
498
 
        // now find the extremities of our vital structures.
499
 
        count = 0;
500
 
        while(count < numBaseStruct)
501
 
        {
502
 
                initEnumStruct(FALSE,baseStruct[count],me,me);
503
 
                structure= enumStruct();
504
 
                while(structure != NULLOBJECT)
505
 
                {
506
 
                        if(structure.x < minx)
507
 
                        {
508
 
                                minx = structure.x;
509
 
                        }
510
 
                        if(structure.x > maxx)
511
 
                        {
512
 
                                maxx = structure.x;
513
 
                        }
514
 
                        if(structure.y < miny)
515
 
                        {
516
 
                                miny = structure.y;
517
 
                        }
518
 
                        if(structure.y > maxy)
519
 
                        {
520
 
                                maxy = structure.y;
521
 
                        }
522
 
 
523
 
                        result = distBetweenTwoPoints(baseX, baseY, structure.x, structure.y);
524
 
 
525
 
                        if(result > baseRange){
526
 
                                baseRange = result;
527
 
                        }
528
 
 
529
 
                        structure= enumStruct();
530
 
                }
531
 
 
532
 
                count = count + 1;
533
 
        }
534
 
 
535
 
        result = 3 * 128;
536
 
        minx = minx - result;
537
 
        maxx = maxx + result;
538
 
        miny = miny - result;
539
 
        maxy = maxy + result;
540
 
 
541
 
        baseRange = baseRange + (4 * 128);
542
 
}
543
 
 
544
 
/////////////////////////////////////////////////////////////////////
545
 
// structure building rules
546
 
 
547
 
// build derricks on oil.
548
 
event buildDerrick(buildDerrickTr)
549
 
{
550
 
 
551
 
        feature = getFeature(me);                                       // find unoccupied oil resource.
552
 
        if(feature != NULLOBJECT)
553
 
        {
554
 
                buildX = feature.x;
555
 
                buildY = feature.y;
556
 
 
557
 
                // if no more than 2 units already trying to build
558
 
                initIterateGroup(buildGroup);                           // find all units in build group.
559
 
                droid = iterateGroup(buildGroup);
560
 
                count = 0;
561
 
                while(droid != NULLOBJECT)
562
 
                {
563
 
                        if((droid.orderx == buildX) and (droid.ordery == buildY))
564
 
                        {
565
 
                                count = count + 1;
566
 
                        }
567
 
                        droid = iterateGroup(buildGroup);
568
 
                }
569
 
 
570
 
                if(count < 3)
571
 
                {
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) )
576
 
                        {
577
 
                                if( (droid.order == DORDER_NONE) or (droid.order == DORDER_RTB))
578
 
                                {
579
 
                                        orderDroidStatsLoc(droid, DORDER_BUILD,derrick, buildX,buildY); //build a derick
580
 
                                        boolResult = TRUE;
581
 
                                }
582
 
                                droid = iterateGroup(buildGroup);
583
 
                        }
584
 
                }
585
 
        }
586
 
        else                                                                                    // feature is null
587
 
        {
588
 
                initGetFeature(oilRes,me,me);           // start again next time.
589
 
        }
590
 
}
591
 
 
592
 
/////////////////////////////////////////////////////////////////////
593
 
// if idle and derrick in range and no defense then build defense, else ret to base .
594
 
event buildOilDefenseOrRetreat(buildOilDefenseOrRetreatTr)
595
 
{
596
 
        local   int             _numBuilders,_maxBuilders;
597
 
 
598
 
 
599
 
        _maxBuilders = 1;
600
 
 
601
 
        // check idle.
602
 
        initIterateGroup(buildGroup);                                   // find idle droids in build group.
603
 
        droid = iterateGroup(buildGroup);
604
 
        while(droid != NULLOBJECT)
605
 
        {
606
 
                if(droid.order == DORDER_NONE)
607
 
                {
608
 
                        // if in range of a derrick
609
 
                        structure = structureBuiltInRange(derrick, droid.x, droid.y, (5*128), me);
610
 
 
611
 
                        // if inside base limits then presume ok..
612
 
                        if( structure != NULLOBJECT)
613
 
                        {
614
 
                                if((structure.x > minx) and (structure.y > miny) and (structure.x < maxx) and (structure.y <maxy))
615
 
                                {
616
 
                                        structure = NULLOBJECT;
617
 
                                }
618
 
                        }
619
 
 
620
 
                        if(structure != NULLOBJECT)
621
 
                        {
622
 
                                buildX = structure.x;
623
 
                                buildY = structure.y;
624
 
 
625
 
                                count = 0;                                                      // if derrick has no defense near it.
626
 
                                result = 0;
627
 
                                while(count < numDefStructs)
628
 
                                {
629
 
                                        structure = structureBuiltInRange(defStructs[count], buildX, buildX,(3*128), me);
630
 
                                        if(structure != NULLOBJECT)
631
 
                                        {
632
 
                                                result = result + 1;                                                    // found a defense.
633
 
                                        }
634
 
                                        count = count + 1;
635
 
                                }
636
 
 
637
 
                                // not many defenses nearby
638
 
                                if(result < 2)
639
 
                                {
640
 
                                        count = numDefStructs - 1;                                                      //pick a struct to build..
641
 
                                        count2 = 0;
642
 
                                        while( (count2 < 5) and (count >= 0) )
643
 
                                        {
644
 
                                                if( isStructureAvailable(defStructs[count],me))
645
 
                                                {
646
 
 
647
 
                                                        // don't build multiple sensors together.
648
 
                                                        if(count == 5)
649
 
                                                        {
650
 
                                                                structure = structureBuiltInRange(defStructs[count], buildX, buildY,(6*128), me);
651
 
                                                                if(structure != NULLOBJECT)
652
 
                                                                {
653
 
                                                                        count = 8;
654
 
                                                                }
655
 
                                                        }
656
 
 
657
 
                                                        structChoice[count2] = defStructs[count];
658
 
                                                        count2 = count2 + 1;
659
 
 
660
 
                                                }
661
 
                                                count = count - 1;
662
 
                                        }
663
 
                                        count =0;
664
 
                                        if(count2 > 0)
665
 
                                        {
666
 
                                                count = random(count2);                                          //count = choice!
667
 
 
668
 
                                                // pick a location
669
 
                                                boolResult = pickStructLocation(structChoice[count], ref buildX, ref buildY,me);
670
 
 
671
 
                                                _numBuilders = numBuildSameBuilding(NULLSTRUCTURESTAT, buildX, buildY);
672
 
 
673
 
                                                if((boolResult == TRUE) and (_numBuilders < _maxBuilders))
674
 
                                                {
675
 
                                                        // build it.
676
 
                                                        orderDroidStatsLoc(droid, DORDER_BUILD,structChoice[count], buildX,buildY);
677
 
                                                        _numBuilders++;
678
 
                                                }
679
 
                                        }
680
 
                                }
681
 
                                else
682
 
                                {
683
 
                                        structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me);
684
 
                                        if(structure == NULLOBJECT)
685
 
                                        {
686
 
                                                if(!insideBase(droid.x, droid.y))
687
 
                                                {
688
 
                                                        orderDroid(droid,DORDER_RTB);                           // return to base;
689
 
                                                }
690
 
                                        }
691
 
                                }
692
 
                        }
693
 
                        else
694
 
                        {
695
 
                                structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me);
696
 
                                if(structure == NULLOBJECT)
697
 
                                {
698
 
                                        if(!insideBase(droid.x, droid.y))
699
 
                                        {
700
 
                                                orderDroid(droid,DORDER_RTB);                                   // return to base;
701
 
                                        }
702
 
                                }
703
 
                        }
704
 
                }
705
 
                droid = iterateGroup(buildGroup);
706
 
        }
707
 
}
708
 
 
709
 
/////////////////////////////////////////////////////////////////////
710
 
//mortar etc.. rules. build sensor towers and emplacements.
711
 
event incendry(incendryTr)
712
 
{
713
 
 
714
 
        initEnumStruct(FALSE,sensorTower,me,me);
715
 
 
716
 
        count = 0;
717
 
        structure = enumStruct();
718
 
        while(structure != NULLOBJECT)
719
 
        {
720
 
                count = count + 1;
721
 
                structure = enumStruct();
722
 
        }
723
 
 
724
 
        if(count < (gameTime/4200) )            // every 7 mins
725
 
        {
726
 
                // if not found build a sensor tower.
727
 
                // find a place to build.
728
 
                buildX = 0;
729
 
                buildY = 0;
730
 
                initEnumStruct(FALSE,derrick,me,me);
731
 
                structure= enumStruct();
732
 
                while(structure != NULLOBJECT)
733
 
                {
734
 
                        count = 0;
735
 
                        result = 0;
736
 
                        while(count < numDefStructs)
737
 
                        {
738
 
                                structure2 = structureBuiltInRange(defStructs[count], structure.x, structure.y,(4*128), me);
739
 
                                if(structure2 != NULLOBJECT)
740
 
                                {
741
 
                                        result = result + 1;
742
 
                                }
743
 
                                count = count + 1;
744
 
                        }
745
 
 
746
 
                        // check for sensor nearby,
747
 
                        structure2 = structureBuiltInRange(sensorTower, structure.x, structure.y,(5*128), me);
748
 
                        if(structure2 != NULLOBJECT)
749
 
                        {
750
 
                                result = 4;
751
 
                        }
752
 
 
753
 
                        if(result < 3)
754
 
                        {
755
 
                                buildX = structure.x;
756
 
                                buildY = structure.y;
757
 
                                structure = NULLOBJECT;
758
 
                        }
759
 
                        else
760
 
                        {
761
 
                                structure = enumStruct();
762
 
                        }
763
 
                }
764
 
 
765
 
                if(buildX != 0)
766
 
                {
767
 
                        boolResult = pickStructLocation(sensorTower, ref buildX, ref buildY,me);        // pick spot.
768
 
                        if(boolResult == TRUE)
769
 
                        {
770
 
                                // find unit
771
 
                                initIterateGroup(buildGroup);
772
 
                                droid = iterateGroup(buildGroup);
773
 
                                while(droid != NULLOBJECT)
774
 
                                {
775
 
                                        if(droid.order == DORDER_NONE or droid.order == DORDER_RTB)
776
 
                                        {
777
 
                                                orderDroidStatsLoc(droid, DORDER_BUILD,sensorTower, buildX,buildY);
778
 
                                                droid = NULLOBJECT;
779
 
                                        }
780
 
                                        else
781
 
                                        {
782
 
                                                droid = iterateGroup(buildGroup);
783
 
                                        }
784
 
                                }
785
 
                        }
786
 
                }
787
 
        }
788
 
        else
789
 
        {
790
 
                // find a sensor tower with least incencdry structs around it..
791
 
                buildX = 0;
792
 
                buildY = 0;
793
 
 
794
 
                initEnumStruct(FALSE,sensorTower,me,me);
795
 
                structure= enumStruct();
796
 
                count = 999;
797
 
                while(structure != NULLOBJECT)
798
 
                {
799
 
                        // count incendrys near this tower.
800
 
                        result = 0;
801
 
                        count2 = 0;
802
 
                        while(count2 < numIncendrys)
803
 
                        {
804
 
                                structure2 = structureBuiltInRange(incendrys[count2], structure.x, structure.y,(4*128), me);
805
 
                                if(structure2 != NULLOBJECT)
806
 
                                {
807
 
                                        result = result + 1;
808
 
                                }
809
 
                                count2 = count2 + 1;
810
 
                        }
811
 
 
812
 
                        if((result < 6) and (result < count))           // lowest found yet. only sites with <6 too.
813
 
                        {
814
 
                                buildX = structure.x;
815
 
                                buildY = structure.y;
816
 
                                count  = result;
817
 
                        }
818
 
                        structure = enumStruct();
819
 
                }
820
 
 
821
 
                if(buildX != 0)
822
 
                {
823
 
 
824
 
                        // choose a device
825
 
                        count = numIncendrys - 1;
826
 
                        result = 99;
827
 
                        while(count >= 0 )
828
 
                        {
829
 
                                if(isStructureAvailable(incendrys[count],me))
830
 
                                {
831
 
                                        result = count;
832
 
                                        count = -1;
833
 
                                }
834
 
                                else
835
 
                                {
836
 
                                        count = count - 1;
837
 
                                }
838
 
                        }
839
 
 
840
 
 
841
 
                        // find a unit and build an incendry device.
842
 
                        if(result != 99)
843
 
                        {
844
 
                                boolResult = pickStructLocation(incendrys[result], ref buildX, ref buildY,me);  // pick spot.
845
 
                                if(boolResult == TRUE)
846
 
                                {
847
 
                                        initIterateGroup(buildGroup);
848
 
                                        droid = iterateGroup(buildGroup);
849
 
 
850
 
                                        boolResult = (numBuildSameBuilding(incendrys[result], buildX, buildY) > 0);     //anyone building there already?
851
 
 
852
 
                                        while(droid != NULLOBJECT and (not boolResult))
853
 
                                        {
854
 
                                                if(droid.order == DORDER_NONE or droid.order == DORDER_RTB)
855
 
                                                {
856
 
                                                        orderDroidStatsLoc(droid, DORDER_BUILD,incendrys[result], buildX,buildY);
857
 
                                                        boolResult = TRUE;      //only 1 truck
858
 
                                                }
859
 
                                                droid = iterateGroup(buildGroup);
860
 
                                        }
861
 
                                }
862
 
                        }
863
 
                }
864
 
        }
865
 
}
866
 
 
867
 
 
868
 
 
869
 
 
870
 
 
871
 
 
872
 
/////////////////////////////////////////////////////////////////////
873
 
// build a power gen for every 4 derricks. VITAL!
874
 
event buildPowerGenerators(buildPowerGeneratorsTr)
875
 
{
876
 
 
877
 
        initEnumStruct(FALSE,derrick,me,me);                                    // count = numderricks
878
 
        structure= enumStruct();
879
 
        count    = 0;
880
 
        while(structure != NULLOBJECT)
881
 
        {
882
 
                count = count + 1;
883
 
                structure= enumStruct();
884
 
        }
885
 
 
886
 
        initEnumStruct(FALSE,powGen,me,me);                                     // count2 = numpowgens
887
 
        structure= enumStruct();
888
 
        count2   = 0;
889
 
        while(structure != NULLOBJECT)
890
 
        {
891
 
                count2 = count2 + 1;
892
 
                structure= enumStruct();
893
 
        }
894
 
 
895
 
        if( (count2 * 4) < count )                                                              // if we need powergen
896
 
        {
897
 
                buildX = baseX;                                                                         // try build powergen.
898
 
                buildY = baseY;
899
 
                boolResult = pickStructLocation(powGen, ref buildX, ref buildY,me);
900
 
                if(boolResult == TRUE)
901
 
                {
902
 
                        initIterateGroup(buildGroup);
903
 
                        droid = iterateGroup(buildGroup);
904
 
                        while(droid != NULLOBJECT)
905
 
                        {
906
 
                                if(droid.order == DORDER_NONE or droid.order == DORDER_RTB)
907
 
                                {
908
 
                                        orderDroidStatsLoc(droid, DORDER_BUILD,powGen, buildX,buildY);
909
 
                                }
910
 
                                droid = iterateGroup(buildGroup);
911
 
                        }
912
 
 
913
 
                }
914
 
        }
915
 
}
916
 
 
917
 
 
918
 
/////////////////////////////////////////////////////////////////////
919
 
// ensure we have everything in the vital structs list.
920
 
event buildBase(buildBaseTr)
921
 
{
922
 
        local   int             _numBuilders,_maxBuilders;
923
 
 
924
 
 
925
 
        if( idleGroup(buildGroup) >= (buildGroup.members/2) )
926
 
        {
927
 
                count = 0;
928
 
                while(count < numStructs)
929
 
                {
930
 
                        // check that struct.
931
 
                        structure = getStructure(structs[count],me);
932
 
                        if(structure == NULLOBJECT)                             // if missing build it.
933
 
                        {
934
 
                                if(isStructureAvailable(structs[count],me))
935
 
                                {
936
 
                                        buildX = baseX;                                         // pick a location
937
 
                                        buildY = baseY;
938
 
                                        boolResult = pickStructLocationB(structs[count], ref buildX, ref buildY,me,0);
939
 
                                        if(boolResult == TRUE)
940
 
                                        {
941
 
                                                _maxBuilders = 2;
942
 
                                                _numBuilders = numBuildSameBuilding(structs[count], buildX, buildY);
943
 
 
944
 
                                                initIterateGroup(buildGroup);                           // find idle droids in build group.
945
 
                                                droid = iterateGroup(buildGroup);
946
 
                                                while((droid != NULLOBJECT) and (_numBuilders < _maxBuilders))
947
 
                                                {
948
 
                                                        if((droid.order == DORDER_NONE) or (droid.order == DORDER_RTB))
949
 
                                                        {
950
 
                                                                orderDroidStatsLoc(droid, DORDER_BUILD,structs[count], buildX,buildY);  // build it
951
 
                                                                _numBuilders++;
952
 
                                                        }
953
 
                                                        droid = iterateGroup(buildGroup);
954
 
                                                }
955
 
                                        }
956
 
                                }
957
 
                        }
958
 
                        count = count + 1;
959
 
                }
960
 
        }
961
 
}
962
 
 
963
 
/////////////////////////////////////////////////////////////////////
964
 
//  build other stuff, grow the base slowly...
965
 
event buildExpand( buildExpandTr )
966
 
{
967
 
        expandBase(NULLOBJECT);
968
 
}
969
 
 
970
 
function void expandBase(DROID _truck)
971
 
{
972
 
        local   int             _numBuilders,_maxBuilders;
973
 
 
974
 
        if(extraStruct == numExtraStructs[curTech])     // loop round
975
 
        {
976
 
                extraStruct = 0;
977
 
        }
978
 
 
979
 
        if(isStructureAvailable(extraStructs[curTech][extraStruct],me))
980
 
        {
981
 
                buildX = baseX;                                         // pick a location
982
 
                buildY = baseY;
983
 
                boolResult = pickStructLocationB(extraStructs[curTech][extraStruct], ref buildX, ref buildY,me,0);
984
 
 
985
 
                if(boolResult == TRUE)
986
 
                {
987
 
                        _numBuilders = numBuildSameBuilding(extraStructs[curTech][extraStruct], buildX, buildY);
988
 
                        _maxBuilders = 2;
989
 
 
990
 
                        if(_truck != NULLOBJECT)
991
 
                        {
992
 
                                if((_truck.order != DORDER_BUILD) and (_truck.order != DORDER_LINEBUILD))
993
 
                                {
994
 
                                        orderDroidStatsLoc(_truck, DORDER_BUILD,extraStructs[curTech][extraStruct], buildX,buildY);// build it.
995
 
                                        _numBuilders++;
996
 
                                }
997
 
                        }
998
 
                        else
999
 
                        {
1000
 
                                initIterateGroup(buildGroup);                           // find idle droids in build group.
1001
 
                                droid = iterateGroup(buildGroup);
1002
 
                                while((droid != NULLOBJECT) and (_numBuilders < _maxBuilders))
1003
 
                                {
1004
 
                                        if((droid.order != DORDER_BUILD) and (droid.order != DORDER_LINEBUILD))
1005
 
                                        {
1006
 
                                                orderDroidStatsLoc(droid, DORDER_BUILD,extraStructs[curTech][extraStruct], buildX,buildY);// build it.
1007
 
                                                _numBuilders++;
1008
 
                                        }
1009
 
                                        droid = iterateGroup(buildGroup);
1010
 
                                }
1011
 
                        }
1012
 
                }
1013
 
        }
1014
 
 
1015
 
        extraStruct = extraStruct + 1;
1016
 
}
1017
 
 
1018
 
 
1019
 
/////////////////////////////////////////////////////////////////////
1020
 
//      Structure (fac/res/pow) upgrades
1021
 
event upgradeStructures(upgradeStructuresTr )
1022
 
{
1023
 
 
1024
 
        initIterateGroup(buildGroup);                           // find idle droids in build group.
1025
 
        droid = iterateGroup(buildGroup);
1026
 
        while(droid != NULLOBJECT)
1027
 
        {
1028
 
                if((droid.order != DORDER_BUILD) and (droid.order != DORDER_LINEBUILD))
1029
 
                {
1030
 
                        boolResult = FALSE;
1031
 
 
1032
 
                        if(curTech == branchDefault)
1033
 
                        {
1034
 
                                //powergen
1035
 
                                boolResult = upgradePowGen(droid, 2);
1036
 
 
1037
 
                                //factory
1038
 
                                if(droid.order != DORDER_BUILD){
1039
 
                                        boolResult = upgradeFactory(droid, 3);
1040
 
                                }
1041
 
 
1042
 
                                //research
1043
 
                                if(droid.order != DORDER_BUILD){
1044
 
                                        boolResult = upgradeResearch(droid, 1);
1045
 
                                }
1046
 
 
1047
 
                                //vtol Factory
1048
 
                                if(droid.order != DORDER_BUILD){
1049
 
                                        boolResult = upgradeVtolFactory(droid, 1);
1050
 
                                }
1051
 
                        }
1052
 
                        else if(curTech == branchVTOL)
1053
 
                        {
1054
 
                                //powergen
1055
 
                                boolResult = upgradePowGen(droid, 2);
1056
 
 
1057
 
                                //vtol Factory
1058
 
                                if(droid.order != DORDER_BUILD){
1059
 
                                        boolResult = upgradeVtolFactory(droid, 3);
1060
 
                                }
1061
 
 
1062
 
                                //factory
1063
 
                                if(droid.order != DORDER_BUILD){
1064
 
                                        boolResult = upgradeFactory(droid, 2);
1065
 
                                }
1066
 
 
1067
 
                                //research
1068
 
                                if(droid.order != DORDER_BUILD){
1069
 
                                        boolResult = upgradeResearch(droid, 1);
1070
 
                                }
1071
 
                        }
1072
 
                }
1073
 
                droid = iterateGroup(buildGroup);
1074
 
        }
1075
 
}
1076
 
 
1077
 
function bool upgradeFactory(DROID _truck, int _maxBuilders)
1078
 
{
1079
 
        local   STRUCTURE       _factory;
1080
 
 
1081
 
        initEnumStruct(FALSE,factory,me,me);
1082
 
        _factory = enumStruct();
1083
 
        while(_factory != NULLOBJECT)
1084
 
        {
1085
 
                // if upgrade is available && struct is not upgraded
1086
 
                if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(_factory) < 2 ))
1087
 
                {
1088
 
                        if((numBuildSameBuilding(facModule, _factory.x, _factory.y) +
1089
 
                            numBuildSameBuilding(vtolFactory, _factory.x, _factory.y)) < _maxBuilders)
1090
 
                        {
1091
 
                                orderDroidStatsLoc(_truck, DORDER_BUILD,facModule, _factory.x,_factory.y);      // upgrade it.
1092
 
                                return TRUE;
1093
 
                        }
1094
 
                }
1095
 
                _factory = enumStruct();
1096
 
        }
1097
 
 
1098
 
        return FALSE;
1099
 
}
1100
 
 
1101
 
function bool upgradeVtolFactory(DROID _truck, int _maxBuilders)
1102
 
{
1103
 
        local   STRUCTURE       _factory;
1104
 
 
1105
 
        initEnumStruct(FALSE,vtolFactory,me,me);
1106
 
        _factory = enumStruct();
1107
 
        while(_factory != NULLOBJECT)
1108
 
        {
1109
 
                // if upgrade is available && struct is not upgraded
1110
 
                if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(_factory) < 2 ))
1111
 
                {
1112
 
                        if((numBuildSameBuilding(facModule, _factory.x, _factory.y) +
1113
 
                            numBuildSameBuilding(factory, _factory.x, _factory.y)) < _maxBuilders)
1114
 
                        {
1115
 
                                orderDroidStatsLoc(_truck, DORDER_BUILD,facModule, _factory.x,_factory.y);      // upgrade it.
1116
 
                                return TRUE;
1117
 
                        }
1118
 
                }
1119
 
                _factory = enumStruct();
1120
 
        }
1121
 
 
1122
 
        return FALSE;
1123
 
}
1124
 
 
1125
 
function bool upgradeResearch(DROID _truck, int _maxBuilders)
1126
 
{
1127
 
        local   STRUCTURE       _resFac;
1128
 
 
1129
 
        initEnumStruct(FALSE,resLab,me,me);
1130
 
        _resFac = enumStruct();
1131
 
        while(_resFac != NULLOBJECT)
1132
 
        {
1133
 
                // if upgrade is available && struct is not upgraded
1134
 
                if( isStructureAvailable(resModule,me) and (not testStructureModule(me, _resFac, 0)))
1135
 
                {
1136
 
                        if((numBuildSameBuilding(resModule, _resFac.x, _resFac.y) +
1137
 
                            numBuildSameBuilding(resLab, _resFac.x, _resFac.y)) < _maxBuilders)
1138
 
                        {
1139
 
                                orderDroidStatsLoc(_truck, DORDER_BUILD,resModule, _resFac.x,_resFac.y);        // upgrade it.
1140
 
                                return TRUE;
1141
 
                        }
1142
 
                }
1143
 
                _resFac = enumStruct();
1144
 
        }
1145
 
 
1146
 
        return FALSE;
1147
 
}
1148
 
 
1149
 
function bool upgradePowGen(DROID _truck, int _maxBuilders)
1150
 
{
1151
 
        local   STRUCTURE       _powGen;
1152
 
 
1153
 
        initEnumStruct(FALSE,powGen,me,me);
1154
 
        _powGen = enumStruct();
1155
 
        while(_powGen != NULLOBJECT)
1156
 
        {
1157
 
                // if upgrade is available && struct is not upgraded
1158
 
                if( isStructureAvailable(powModule,me) and (not testStructureModule(me, _powGen, 0)))
1159
 
                {
1160
 
                        if((numBuildSameBuilding(powModule, _powGen.x,_powGen.y) +
1161
 
                            numBuildSameBuilding(powGen, _powGen.x,_powGen.y)) < _maxBuilders)
1162
 
                        {
1163
 
                                orderDroidStatsLoc(_truck, DORDER_BUILD, powModule, _powGen.x,_powGen.y);       // upgrade it.
1164
 
                                return TRUE;
1165
 
                        }
1166
 
                }
1167
 
                _powGen = enumStruct();
1168
 
        }
1169
 
 
1170
 
        return FALSE;
1171
 
}
1172
 
 
1173
 
 
1174
 
/////////////////////////////////////////////////////////////////////
1175
 
//      Finish Building Part Built Structures
1176
 
event finishStructs(finishStructsTr)
1177
 
{
1178
 
        initEnumStruct(TRUE,factory,me,me);
1179
 
        structure= enumStruct();
1180
 
        while(structure != NULLOBJECT)
1181
 
        {
1182
 
                if(not structureComplete(structure))
1183
 
                {
1184
 
                        initIterateGroup(buildGroup);                           // find idle droids in build group.
1185
 
                        droid = iterateGroup(buildGroup);
1186
 
                        while(droid != NULLOBJECT)
1187
 
                        {
1188
 
                                if((droid.order != DORDER_BUILD) and (droid.order != DORDER_LINEBUILD))
1189
 
                                {
1190
 
                                        orderDroidObj(droid,DORDER_HELPBUILD,structure);
1191
 
                                }
1192
 
                                droid = iterateGroup(buildGroup);
1193
 
                        }
1194
 
                }
1195
 
                structure= enumStruct();
1196
 
        }
1197
 
}
1198
 
 
1199
 
 
1200
 
/////////////////////////////////////////////////////////////////////
1201
 
//  fortify base by builiding defensive structs on the edge of the base.
1202
 
// rewrote fortify to use scrSkDefenseLocation(baseX,baseY,me);
1203
 
 
1204
 
event newfortify(fortifyTr)
1205
 
{
1206
 
        local   int             _numBuilders,_maxBuilders;
1207
 
 
1208
 
        _maxBuilders = 1;
1209
 
 
1210
 
        if(numGroupSameOrder(buildGroup, DORDER_LINEBUILD) >= _maxBuilders)
1211
 
        {
1212
 
                exit;
1213
 
        }
1214
 
 
1215
 
        boolResult = FALSE;
1216
 
        initIterateGroup(buildGroup);                           // find idle an idle veh.in build group.
1217
 
        droid = iterateGroup(buildGroup);
1218
 
        while((boolResult == FALSE) and (droid != NULLOBJECT))
1219
 
        {
1220
 
                if((droid.order != DORDER_BUILD) and (droid.order != DORDER_LINEBUILD))
1221
 
                {
1222
 
                        boolResult = TRUE;                                      // dont do this again!
1223
 
 
1224
 
                        tempx = baseX;
1225
 
                        tempy = baseY;
1226
 
 
1227
 
                        // choose a suitable turret.
1228
 
                        count = numWallWeaps - 1;
1229
 
                        count2 = 0;
1230
 
                        while( (count2 < 3) and (count >= 0) )
1231
 
                        {
1232
 
                                if( isStructureAvailable(wallWeaps[count],me))
1233
 
                                {
1234
 
                                        structChoice[count2] = wallWeaps[count];
1235
 
                                        count2 = count2 + 1;
1236
 
                                }
1237
 
                                count = count - 1;
1238
 
                        }
1239
 
                        count =0;
1240
 
                        if((count2 > 0) and (_numBuilders < _maxBuilders))
1241
 
                        {
1242
 
                                count = random(count2);
1243
 
                                skDefenseLocationB(ref tempx,ref tempy,wall,structChoice[count],droid,me);
1244
 
                                _numBuilders++;
1245
 
                        }
1246
 
 
1247
 
                }
1248
 
                droid = iterateGroup(buildGroup);
1249
 
 
1250
 
        }
1251
 
}
1252
 
 
1253
 
 
1254
 
/////////////////////////////////////////////////////////////////////
1255
 
// droid building rules
1256
 
/////////////////////////////////////////////////////////////////////
1257
 
// deal with a droid being built
1258
 
event droidBuiltAssign(droidBuiltTr)
1259
 
{
1260
 
        if(isVtol(droid))
1261
 
        {
1262
 
                if(vtolDefendGr.members < numDefendVtols)
1263
 
                {
1264
 
                        groupAddDroid(vtolDefendGr, droid);
1265
 
                }
1266
 
                else
1267
 
                {
1268
 
                        count = 0;
1269
 
                        while(count < numVtolAttackGroups)
1270
 
                        {
1271
 
                                if(vtolAttackGr[count].members < numAttackVtols)
1272
 
                                {
1273
 
                                        dbg("added new vtol to group " & count, me);
1274
 
                                        groupAddDroid(vtolAttackGr[count], droid);
1275
 
                                        count = numVtolAttackGroups;
1276
 
                                }
1277
 
                                count++;
1278
 
                        }
1279
 
                }
1280
 
        }
1281
 
        else if((droid.droidType != DROID_TRANSPORTER) and (droid.droidType != DROID_COMMAND))
1282
 
        {
1283
 
 
1284
 
                if((droid.droidType == DROID_REPAIR)
1285
 
                        or (droid.droidType == DROID_CYBORG_REPAIR))
1286
 
                {
1287
 
                        numRepairUnits = numRepairUnits + 1;
1288
 
                }
1289
 
                
1290
 
                if((droid.droidType == DROID_CONSTRUCT)
1291
 
                        or (droid.droidType == DROID_CYBORG_CONSTRUCT))                         // if constructor droid
1292
 
                {
1293
 
                        groupAddDroid(buildGroup, droid);
1294
 
                }
1295
 
                else
1296
 
                {
1297
 
                        if(droid.droidType == DROID_CYBORG)
1298
 
                        {
1299
 
                                groupAddDroid(defendGroup, droid);
1300
 
                        }
1301
 
                        else
1302
 
                        {
1303
 
                                if(scoutGroup.members < numScouts[curTech])
1304
 
                                {
1305
 
                                        groupAddDroid(scoutGroup, droid);
1306
 
                                }
1307
 
                                else if(attackGroup.members < numAttackers[curTech])
1308
 
                                {
1309
 
                                        groupAddDroid(attackGroup, droid);
1310
 
                                }
1311
 
                                else if( defendGroup.members < numDefenders[curTech])
1312
 
                                {
1313
 
                                        groupAddDroid(defendGroup, droid);
1314
 
                                }
1315
 
                                else
1316
 
                                {
1317
 
                                        if(scoutGroup.members < maxScouts[curTech])
1318
 
                                        {
1319
 
                                                groupAddDroid(scoutGroup, droid);
1320
 
                                        }
1321
 
                                        else if(attackGroup.members < maxAttackers[curTech])
1322
 
                                        {
1323
 
                                                groupAddDroid(attackGroup, droid);
1324
 
                                        }
1325
 
                                        else if( defendGroup.members < maxDefenders[curTech])
1326
 
                                        {
1327
 
                                                groupAddDroid(defendGroup, droid);
1328
 
                                        }
1329
 
                                        else    //make them attack
1330
 
                                        {
1331
 
                                                groupAddDroid(attackGroup, droid);
1332
 
                                        }
1333
 
                                }
1334
 
                        }
1335
 
                }
1336
 
        }
1337
 
}
1338
 
 
1339
 
//When droid built: set droid retreat level and start building next droid
1340
 
event droidBuilt(droidBuiltTr)
1341
 
{
1342
 
        local STRUCTURE _repairFacility;
1343
 
 
1344
 
        if(!isVtol(droid))
1345
 
        {
1346
 
                _repairFacility = getStructure(repairFacility,me);
1347
 
                if(_repairFacility == NULLOBJECT)
1348
 
                {
1349
 
                        setDroidSecondary(droid,DSO_REPAIR_LEVEL, DSS_REPLEV_NEVER);
1350
 
                }
1351
 
                else
1352
 
                {
1353
 
                        setDroidSecondary(droid,DSO_REPAIR_LEVEL, DSS_REPLEV_LOW);
1354
 
                }
1355
 
        }
1356
 
 
1357
 
        /* Start building next droid */
1358
 
        if(structure != NULLOBJECT)
1359
 
        {
1360
 
                if(structure.stattype == REF_FACTORY)
1361
 
                {
1362
 
                        factoryBuildDroid(structure);
1363
 
                }
1364
 
                else if(structure.stattype == REF_CYBORG_FACTORY)
1365
 
                {
1366
 
                        cybFactorBuildCyborg(structure);
1367
 
                }
1368
 
                else if(structure.stattype == REF_VTOL_FACTORY)
1369
 
                {
1370
 
                        vtolFactoryBuildVtol(structure);
1371
 
                }
1372
 
        }
1373
 
}
1374
 
 
1375
 
/* Gets triggered when structure was built */
1376
 
event structBuilt(structBuiltTr)
1377
 
{
1378
 
        local   FEATURE _oilResource;
1379
 
        local   int             _count,_count2;
1380
 
 
1381
 
        if(structure == NULLOBJECT || droid == NULLOBJECT){
1382
 
                exit;
1383
 
        }
1384
 
 
1385
 
        /* factory or factory module */
1386
 
        if(structure.stattype == REF_FACTORY)
1387
 
        {
1388
 
                if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(structure) < 2 ))
1389
 
                {
1390
 
                        orderDroidStatsLoc(droid, DORDER_BUILD,facModule, structure.x,structure.y);     // upgrade it.
1391
 
                }
1392
 
        }
1393
 
        /* vtol factory or vtol factory module */
1394
 
        else if(structure.stattype == REF_VTOL_FACTORY)
1395
 
        {
1396
 
                if( isStructureAvailable(facModule,me) and (skGetFactoryCapacity(structure) < 2 ))
1397
 
                {
1398
 
                        orderDroidStatsLoc(droid, DORDER_BUILD,facModule, structure.x,structure.y);     // upgrade it.
1399
 
                }
1400
 
        }
1401
 
        else if(structure.stattype == REF_RESOURCE_EXTRACTOR)
1402
 
        {
1403
 
                /* get next oil resource nearby */
1404
 
                _oilResource = closestOil(structure.x, structure.y, TRUE);
1405
 
 
1406
 
                if(_oilResource != NULLOBJECT)
1407
 
                {
1408
 
                        if(distBetweenTwoPoints(_oilResource.x, _oilResource.y, structure.x, structure.y) < MORE_OIL_RANGE)     //not too far away
1409
 
                        {
1410
 
                                dbg("structBuilt: more oil", me);
1411
 
                                orderDroidStatsLoc(droid, DORDER_BUILD, derrick, _oilResource.x, _oilResource.y);       //build a derick
1412
 
                        }
1413
 
                }
1414
 
        }
1415
 
 
1416
 
        //see if we have just rebuilt a destroyed structure
1417
 
        _count = 0;
1418
 
        while(_count < countRebuildStruct)
1419
 
        {
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))
1425
 
                   ))
1426
 
                {
1427
 
                        dbg("finished rebuilding destroyed structure - " & _count, me);
1428
 
 
1429
 
                        //resort destroyed structures
1430
 
                        _count2 = _count;
1431
 
                        while(_count2 < (countRebuildStruct - 1))
1432
 
                        {
1433
 
                                rebuildStructX[_count2] = rebuildStructX[_count2 + 1];
1434
 
                                rebuildStructY[_count2] = rebuildStructY[_count2 + 1];
1435
 
                                rebuildStructStat[_count2] = rebuildStructStat[_count2 + 1];
1436
 
 
1437
 
                                _count2++;
1438
 
                        }
1439
 
 
1440
 
                        //clear last entry
1441
 
                        rebuildStructX[countRebuildStruct - 1] = 0;
1442
 
                        rebuildStructY[countRebuildStruct - 1] = 0;
1443
 
                        rebuildStructStat[countRebuildStruct - 1] = NULLSTRUCTURESTAT;
1444
 
 
1445
 
                        countRebuildStruct--;   //we just built one structure
1446
 
 
1447
 
                        //_count = countRebuildStruct;  //exit outer loop
1448
 
                }
1449
 
                _count++;
1450
 
        }
1451
 
}
1452
 
 
1453
 
/////////////////////////////////////////////////////////////////////
1454
 
// deal with attacks.
1455
 
event droidDestroyed(droidDestroyedTr)
1456
 
{
1457
 
 
1458
 
        if(droid.droidType == DROID_REPAIR)
1459
 
        {
1460
 
                numRepairUnits = numRepairUnits - 1;
1461
 
        }
1462
 
 
1463
 
        if(droid.droidType == DROID_CONSTRUCT)                                  // if constructor droid
1464
 
        {
1465
 
                initEnumStruct(FALSE,factory,me,me);
1466
 
                structure= enumStruct();                                                        // find factory.
1467
 
 
1468
 
                if( (structure != NULLOBJECT) and (getDroidCount(me) < MAX_DROIDS) )
1469
 
                {
1470
 
                        buildDroid(constructor, structure, me, 1);      // build constructor
1471
 
                }
1472
 
 
1473
 
        }
1474
 
}
1475
 
 
1476
 
 
1477
 
/////////////////////////////////////////////////////////////////////
1478
 
// build more con droids.
1479
 
event conDroids(conDroidsTr)
1480
 
{
1481
 
 
1482
 
        buildTruck();
1483
 
 
1484
 
}
1485
 
 
1486
 
/* function void buildTruck()
1487
 
{
1488
 
        local   int                     _maxTrucks;
1489
 
        local   STRUCTURE               _factory;
1490
 
        local   int             _numBuilding,_haveTrucks,_maxTruckFactories,_totalTrucks;
1491
 
 
1492
 
        _maxTrucks = MAX_TRUCKS;
1493
 
        if(powerSave){
1494
 
                _maxTrucks = MIN_TRUCKS;
1495
 
        }
1496
 
 
1497
 
        _maxTruckFactories = 3;                 //max factories to use for truck production
1498
 
 
1499
 
        _haveTrucks = buildGroup.members;
1500
 
        
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
1504
 
 
1505
 
        _totalTrucks = _numBuilding + _haveTrucks;
1506
 
 
1507
 
        initEnumStruct(FALSE,factory,me,me);
1508
 
        _factory = enumStruct();                                                        // find factory.
1509
 
        while((_factory != NULLOBJECT) and (_numBuilding < _maxTruckFactories)
1510
 
                and (_totalTrucks < _maxTrucks))
1511
 
        {
1512
 
                if(structureComplete(_factory))
1513
 
                {
1514
 
                        if(getDroidCount(me) < MAX_DROIDS)
1515
 
                        {
1516
 
                                buildDroid(constructor, _factory, me, 1);       // build constructor
1517
 
                                _numBuilding++;
1518
 
                                _totalTrucks++;
1519
 
                        }
1520
 
                }
1521
 
 
1522
 
                _factory = enumStruct();
1523
 
        }
1524
 
} */
1525
 
 
1526
 
function void buildTruck()
1527
 
{
1528
 
        local   int                     _maxTrucks;
1529
 
        local   STRUCTURE       _factory;
1530
 
        local   int             _numBuilding,_haveTrucks,_maxTruckFactories,_totalTrucks;
1531
 
        local   bool            _bStartedBuilding;
1532
 
 
1533
 
        _maxTrucks = MAX_TRUCKS;
1534
 
        if(powerSave){
1535
 
                _maxTrucks = MIN_TRUCKS;
1536
 
        }
1537
 
 
1538
 
        _maxTruckFactories = 3;                 //max factories to use for truck production
1539
 
 
1540
 
        _haveTrucks = buildGroup.members;
1541
 
        
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
1545
 
 
1546
 
        _totalTrucks = _numBuilding + _haveTrucks;
1547
 
        
1548
 
        initEnumStruct(FALSE,factory,me,me);
1549
 
        _factory = enumStruct();
1550
 
        
1551
 
        while((_factory != NULLOBJECT) and (_numBuilding < _maxTruckFactories)
1552
 
                and (_totalTrucks < _maxTrucks))
1553
 
        {
1554
 
                //Try to build a truck
1555
 
                _bStartedBuilding = buildUnit(constructor, _factory, factory, FALSE);   //build truck even if not idle
1556
 
                
1557
 
                //Update statistics if started building a truck
1558
 
                if(_bStartedBuilding)
1559
 
                {
1560
 
                        _numBuilding++;
1561
 
                        _totalTrucks++;
1562
 
                }
1563
 
                
1564
 
                _factory = enumStruct();
1565
 
        }
1566
 
        
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))
1571
 
        {
1572
 
                //Try to build a truck
1573
 
                if( skCanBuildTemplate(me,_factory, cybEngineer) )      //make sure we have researched cyb engineer
1574
 
                {
1575
 
                        _bStartedBuilding = buildUnit(cybEngineer, _factory, cybFactory, FALSE);        //build a cyb eng even if not idle
1576
 
                        
1577
 
                        //Update statistics if started building a cyborg engineer
1578
 
                        if(_bStartedBuilding)
1579
 
                        {
1580
 
                                _numBuilding++;
1581
 
                                _totalTrucks++;
1582
 
                        }
1583
 
                }
1584
 
 
1585
 
                _factory = enumStruct();
1586
 
        }
1587
 
}
1588
 
 
1589
 
 
1590
 
//Build a droid
1591
 
function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly)
1592
 
{
1593
 
        //Factory was not provided, find an factory
1594
 
        if(_factory == NULLOBJECT)
1595
 
        {
1596
 
                _factory = findIdleStructure(_factoryType, _bIdleOnly);
1597
 
        }
1598
 
 
1599
 
        //Build if got a factory
1600
 
        if(_factory != NULLOBJECT)
1601
 
        {
1602
 
                if(structureComplete(_factory) and (getDroidCount(me) < MAX_DROIDS))
1603
 
                {
1604
 
                        if( !(_bIdleOnly and !structureIdle(_factory)) )        //don't build if only allowed to build whe idle and fac is not idle
1605
 
                        {
1606
 
                                buildDroid(_tankTemplate, _factory, me, 1);     // build a tank
1607
 
                                return TRUE;    //success
1608
 
                        }
1609
 
                }
1610
 
        }
1611
 
 
1612
 
        return FALSE;           //failed
1613
 
}
1614
 
 
1615
 
//Returns an idle structure of the provided type or NULLOBJECT if none found
1616
 
function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly)
1617
 
{
1618
 
        local   STRUCTURE       _structure;
1619
 
 
1620
 
        initEnumStruct(FALSE,_structType,me,me);
1621
 
        _structure = enumStruct();
1622
 
        while(_structure != NULLOBJECT)
1623
 
        {
1624
 
                if(structureComplete(_structure))
1625
 
                {
1626
 
                        if( !(_bIdleOnly and !structureIdle(_structure)) )
1627
 
                        {
1628
 
                                return _structure;
1629
 
                        }
1630
 
                }
1631
 
 
1632
 
                _structure = enumStruct();
1633
 
        }
1634
 
        
1635
 
        return NULLOBJECT;      //none found
1636
 
}
1637
 
 
1638
 
/////////////////////////////////////////////////////////////////////
1639
 
// build repair droids.
1640
 
event repairDroids(repairDroidsTr)
1641
 
{
1642
 
 
1643
 
        // if we're running low on repair droids, build some..
1644
 
        if(numRepairUnits <3)
1645
 
        {
1646
 
                initEnumStruct(FALSE,factory,me,me);
1647
 
                structure= enumStruct();                                                        // find factory.
1648
 
                if( (structure != NULLOBJECT) and (getDroidCount(me) < MAX_DROIDS) )
1649
 
                {
1650
 
                        buildDroid(repairUnit, structure, me, 1);       // build repairunit.
1651
 
                }
1652
 
        }
1653
 
 
1654
 
}
1655
 
 
1656
 
 
1657
 
/////////////////////////////////////////////////////////////////////
1658
 
event factoryEvent(factoryEventTr)
1659
 
{
1660
 
 
1661
 
        // for each factory....
1662
 
        initEnumStruct(FALSE,factory,me,me);
1663
 
        structure = enumStruct();                                                               // find factory.
1664
 
        if(getDroidCount(me) < MAX_DROIDS)
1665
 
        {
1666
 
                while(structure != NULLOBJECT)
1667
 
                {
1668
 
                        if( structureIdle(structure) )
1669
 
                        {
1670
 
                                factoryBuildDroid(structure);
1671
 
                        }
1672
 
 
1673
 
                        structure = enumStruct();
1674
 
                }
1675
 
        }
1676
 
}
1677
 
 
1678
 
function bool needTank()
1679
 
{
1680
 
        if((defendGroup.members < maxDefenders[curTech]) or (maxDefenders[curTech] == UNLIMITED))
1681
 
        {
1682
 
                return TRUE;
1683
 
        }
1684
 
 
1685
 
        if((scoutGroup.members < maxScouts[curTech]) or (maxScouts[curTech] == UNLIMITED))
1686
 
        {
1687
 
                return TRUE;
1688
 
        }
1689
 
 
1690
 
        if((attackGroup.members < maxAttackers[curTech]) or (maxAttackers[curTech] == UNLIMITED))
1691
 
        {
1692
 
                return TRUE;
1693
 
        }
1694
 
 
1695
 
        return FALSE;
1696
 
}
1697
 
 
1698
 
function void factoryBuildDroid(STRUCTURE _factory)
1699
 
{
1700
 
        local int _count,_count2;
1701
 
 
1702
 
        if(_factory == NULLOBJECT){
1703
 
                dbg("factoryBuildDroid: factory is NULLOBJECT", me);
1704
 
                return;
1705
 
        }
1706
 
 
1707
 
        if(not needTank())
1708
 
        {
1709
 
                //dbg("NEED NO TANKS!! " & maxDefenders[curTech], me);
1710
 
                return;
1711
 
        }
1712
 
 
1713
 
        if( structureIdle(_factory) )
1714
 
        {
1715
 
                _count = numTemplates[curTech] - 1;
1716
 
                _count2 = 0;
1717
 
                while( (_count2 < MAX_RANDOM_TEMPLATES) and (_count >= 0) )
1718
 
                {
1719
 
                        if( skCanBuildTemplate(me,_factory, tmpl[curTech][_count]) )
1720
 
                        {
1721
 
                                tmplChoice[_count2] = tmpl[curTech][_count];
1722
 
                                _count2 = _count2 + 1;
1723
 
                        }
1724
 
                        _count = _count - 1;
1725
 
                }
1726
 
 
1727
 
                if(_count2 > 0)
1728
 
                {
1729
 
                        buildDroid(tmplChoice[random(_count2)],_factory,me,1);
1730
 
                }
1731
 
        }
1732
 
        else
1733
 
        {
1734
 
                dbg("factoryBuildDroid: factory is busy", me);
1735
 
        }
1736
 
}
1737
 
 
1738
 
/////////////////////////////////////////////////////////////////////
1739
 
// put cyborg factories to work
1740
 
event cyborgFactoryEvent(cyborgFactoryEventTr)
1741
 
{
1742
 
 
1743
 
        if(not ((defendGroup.members < maxCyborgs[curTech]) or (maxCyborgs[curTech] == UNLIMITED)))
1744
 
        {
1745
 
                exit;           //we need no cyborgs
1746
 
        }
1747
 
 
1748
 
        initEnumStruct(FALSE,cybFactory,me,me);
1749
 
        structure= enumStruct();                                                                // find factory.
1750
 
 
1751
 
        while(structure != NULLOBJECT)
1752
 
        {
1753
 
                if( structureIdle(structure) == TRUE)
1754
 
                {
1755
 
                        cybFactorBuildCyborg(structure);
1756
 
                }
1757
 
                structure= enumStruct();                                                        // find factory.
1758
 
        }
1759
 
}
1760
 
 
1761
 
function void cybFactorBuildCyborg(STRUCTURE _factory)
1762
 
{
1763
 
        if(_factory == NULLOBJECT){
1764
 
                dbg("cybFactorBuildCyborg: factory is NULLOBJECT", me);
1765
 
                return;
1766
 
        }
1767
 
 
1768
 
        if( structureIdle(_factory) )
1769
 
        {
1770
 
                if( (defendGroup.members < maxCyborgs[curTech]) and (getDroidCount(me) < MAX_DROIDS) )
1771
 
                {
1772
 
                        if(random(5) == 1)
1773
 
                        {
1774
 
                                buildDroid(cybMechanic,_factory,me,1);
1775
 
                        }
1776
 
                        else
1777
 
                        {
1778
 
                                count = 3;
1779
 
                                count2 = 0;
1780
 
                                while( count >= 0 )
1781
 
                                {
1782
 
                                        if( skCanBuildTemplate(me,_factory, superCyb[count]) )
1783
 
                                        {
1784
 
                                                tmplChoice[count2] = superCyb[count];
1785
 
                                                count2 = count2 + 1;
1786
 
                                        }
1787
 
                                        count = count - 1;
1788
 
                                }
1789
 
 
1790
 
                                if(count2 > 0)
1791
 
                                {
1792
 
                                        buildDroid(tmplChoice[random(count2)],_factory,me,1);
1793
 
                                }
1794
 
                                else    //try light cyborgs
1795
 
                                {
1796
 
                                        count = numLightCyborgs - 1;
1797
 
                                        count2 = 0;
1798
 
                                        while( (count >= 0) and (count2 < 2) )
1799
 
                                        {
1800
 
                                                if( skCanBuildTemplate(me,_factory, cybTempl[count]) )
1801
 
                                                {
1802
 
                                                        tmplChoice[count2] = cybTempl[count];
1803
 
                                                        count2++;
1804
 
                                                }
1805
 
                                                count--;
1806
 
                                        }
1807
 
                                        if(count2 > 0)
1808
 
                                        {
1809
 
                                                buildDroid(tmplChoice[random(count2)], _factory, me, 1);
1810
 
                                        }
1811
 
                                }
1812
 
                        }
1813
 
 
1814
 
                }
1815
 
        }
1816
 
}
1817
 
 
1818
 
/////////////////////////////////////////////////////////////////////
1819
 
/////////////////////////////////////////////////////////////////////
1820
 
// scouting rules
1821
 
 
1822
 
// scout an area
1823
 
event chooseScoutArea(chooseScoutAreaTr)
1824
 
{
1825
 
        scoutX = scoutTLX + random(scoutW);
1826
 
        scoutY = scoutTLY + random(scoutH);
1827
 
}
1828
 
 
1829
 
/////////////////////////////////////////////////////////////////////
1830
 
// visit new places
1831
 
 
1832
 
event expandScoutArea(expandScoutAreaTr)
1833
 
{
1834
 
 
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));
1840
 
 
1841
 
        // check & restrain.
1842
 
        if(scoutTLX <1)
1843
 
        {
1844
 
                scoutTLX = 1;
1845
 
        }
1846
 
        if(scoutTLY <1)
1847
 
        {
1848
 
                scoutTLY = 1;
1849
 
        }
1850
 
 
1851
 
        if(scoutTLX >(mapWidth*128))
1852
 
        {
1853
 
                scoutTLX = (mapWidth*128) - 128;
1854
 
        }
1855
 
        if(scoutTLY >(mapHeight*128))
1856
 
        {
1857
 
                scoutTLY = (128*mapHeight) - 128;
1858
 
        }
1859
 
 
1860
 
        if( (scoutTLX + scoutW) > (128 * mapWidth) )
1861
 
        {
1862
 
                scoutW = ( (128 * mapWidth) - scoutTLX) - 128;
1863
 
        }
1864
 
        if( (scoutTLY + scoutH) > (128 *mapHeight) )
1865
 
        {
1866
 
                scoutH = ( (128*mapHeight) - scoutTLY) - 128;
1867
 
        }
1868
 
}
1869
 
 
1870
 
/////////////////////////////////////////////////////////////////////
1871
 
// order scouts
1872
 
 
1873
 
event scoutMain(scoutMainTr)
1874
 
{
1875
 
        // find any new scouts
1876
 
        // if scouts aren't busy, send them to a new spot.
1877
 
        if( idleGroup(scoutGroup) >= (scoutGroup.members /2) )
1878
 
        {
1879
 
                orderGroupLoc(scoutGroup, DORDER_MOVE,scoutX,scoutY);
1880
 
        }
1881
 
}
1882
 
 
1883
 
/////////////////////////////////////////////////////////////////////
1884
 
// process new visibility reports
1885
 
event newObjectReport(newObjectReportTr)
1886
 
{
1887
 
        if(!friendlyPlayer(baseobj.player))
1888
 
        {
1889
 
                if(targetTypeValue(baseobj) > targetTypeValue(attackObj))
1890
 
                {
1891
 
                        attackObj = baseobj;// got a new unseen  target from a scout.
1892
 
 
1893
 
                        if(     attackObj.type == OBJ_STRUCTURE)
1894
 
                        {
1895
 
                                if(not allianceExistsBetween(attackObj.player,me))      // an enemy
1896
 
                                {
1897
 
                                        structure = objToStructure(attackObj);
1898
 
                                        if(structure.stat == factory)
1899
 
                                        {
1900
 
                                                allOutAttack = attackObj;
1901
 
                                        }
1902
 
                                }
1903
 
                        }
1904
 
                }
1905
 
        }
1906
 
}
1907
 
 
1908
 
function int targetTypeValue(BASEOBJ _target)
1909
 
{
1910
 
        local STRUCTURE _strTarget;
1911
 
 
1912
 
        if(_target == NULLOBJECT){
1913
 
                return NO_TARGET_VALUE;
1914
 
        }
1915
 
 
1916
 
        if(_target.type == OBJ_DROID)
1917
 
        {
1918
 
                return DROID_TARGET_VALUE;
1919
 
        }
1920
 
        else if(_target.type == OBJ_STRUCTURE)
1921
 
        {
1922
 
                _strTarget = objToStructure(_target);
1923
 
 
1924
 
                if(_strTarget.stattype == REF_DEFENSE)
1925
 
                {
1926
 
                        return DEFENSE_TARGET_VALUE;
1927
 
                }
1928
 
                else if(_strTarget.stattype == REF_RESEARCH or
1929
 
                                _strTarget.stattype == REF_POWER_GEN)
1930
 
                {
1931
 
                        return RESEARCH_TARGET_VALUE;
1932
 
                }
1933
 
                else if(_strTarget.stattype == REF_HQ or
1934
 
                                _strTarget.stattype == REF_COMMAND_CONTROL)
1935
 
                {
1936
 
                        return HQ_TARGET_VALUE;
1937
 
                }
1938
 
                else if(_strTarget.stattype == REF_RESOURCE_EXTRACTOR)
1939
 
                {
1940
 
                        return OIL_TARGET_VALUE;
1941
 
                }
1942
 
                else if(_strTarget.stattype == REF_FACTORY or
1943
 
                                _strTarget.stattype == REF_CYBORG_FACTORY or
1944
 
                                _strTarget.stattype == REF_VTOL_FACTORY)
1945
 
                {
1946
 
                        return FACTORY_TARGET_VALUE;
1947
 
                }
1948
 
                else    //walls, rearm pads etc
1949
 
                {
1950
 
                        return OTHER_TARGET_VALUE;
1951
 
                }
1952
 
        }
1953
 
 
1954
 
        return NO_TARGET_VALUE;
1955
 
}
1956
 
 
1957
 
 
1958
 
/////////////////////////////////////////////////////////////////////
1959
 
/////////////////////////////////////////////////////////////////////
1960
 
// spy technologies
1961
 
//event takeover( CALL_UNITTAKEOVER , ref droid  )
1962
 
 
1963
 
event takeover(takeoverTr)
1964
 
{
1965
 
        if( droid.player == me )
1966
 
        {
1967
 
                if(droid.droidType == DROID_CONSTRUCT or
1968
 
                                droid.droidType == DROID_CYBORG_CONSTRUCT)
1969
 
                {
1970
 
                        groupAddDroid( buildGroup, droid );
1971
 
                }
1972
 
                else if (droid.droidType != DROID_TRANSPORTER
1973
 
                      && droid.droidType != DROID_COMMAND)
1974
 
                {
1975
 
                        groupAddDroid( attackGroup, droid );
1976
 
                }
1977
 
        }
1978
 
}
1979
 
 
1980
 
event takeoverDefend(takeoverTr)
1981
 
{
1982
 
        if( droid.player != me )
1983
 
        {
1984
 
                completeResearch(nexusDefence,me);
1985
 
                setEventTrigger(takeoverDefend, inactive);
1986
 
        }
1987
 
}
1988
 
 
1989
 
 
1990
 
event useLassat(useLassatTr)
1991
 
{
1992
 
 
1993
 
        // find my lassat
1994
 
        // fire it at my attack objective.
1995
 
        if(allOutAttack != NULLOBJECT)
1996
 
        {
1997
 
                initEnumStruct(FALSE,lassat,me,me);
1998
 
                structure= enumStruct();
1999
 
                while(structure != NULLOBJECT)
2000
 
                {
2001
 
                        if(structureComplete(structure) == TRUE)
2002
 
                        {
2003
 
                                skFireLassat(me,allOutAttack);
2004
 
                        }
2005
 
                        structure= enumStruct();
2006
 
                }
2007
 
        }
2008
 
}
2009
 
 
2010
 
/////////////////////////////////////////////////////////////////////
2011
 
/////////////////////////////////////////////////////////////////////
2012
 
// attack rules
2013
 
 
2014
 
event findEnemy(attackStuffTr)
2015
 
{
2016
 
        if(attackObj == NULLOBJECT)
2017
 
        {
2018
 
                count = random(8);
2019
 
                count2 = 100;
2020
 
                while( friendlyPlayer(count) && (count2 > 0) )
2021
 
                {
2022
 
                        count = random(8);
2023
 
                        count2--;
2024
 
                }
2025
 
 
2026
 
                if(!friendlyPlayer(count))
2027
 
                {
2028
 
                        baseobj = skLocateEnemy(count);
2029
 
                        if(baseobj != NULLOBJECT)
2030
 
                        {
2031
 
                                attackObj =     baseobj;
2032
 
 
2033
 
                                // set allOutAttack to attackObj only if attackObj is a more valuable target than allOutAttack
2034
 
                                if(targetTypeValue(attackObj) > targetTypeValue(allOutAttack))
2035
 
                                {
2036
 
                                        allOutAttack = attackObj;
2037
 
                                }
2038
 
                        }
2039
 
                }
2040
 
        }
2041
 
}
2042
 
 
2043
 
/////////////////////////////////////////////////////////////////////
2044
 
// send attack team out to cause trouble near things scout found.
2045
 
event attackStuff(attackStuffTr)
2046
 
{
2047
 
        if( idleGroup(attackGroup) >= (attackGroup.members / 2))
2048
 
        {
2049
 
                if( (attackObj != NULLOBJECT) and (not helpingAlly()) )
2050
 
                {
2051
 
                        if (not allianceExistsBetween(me, attackObj.player))
2052
 
                        {
2053
 
                                if(attackGroup.members > (6 + random(6)) )
2054
 
                                {
2055
 
                                        orderGroupLoc(attackGroup, DORDER_SCOUT, attackObj.x, attackObj.y);
2056
 
                                }
2057
 
 
2058
 
                                // make scouts attack too
2059
 
                                if( idleGroup(scoutGroup) >= (scoutGroup.members / 2) )
2060
 
                                {
2061
 
                                        orderGroupLoc(scoutGroup, DORDER_SCOUT, attackObj.x, attackObj.y);
2062
 
                                }
2063
 
                        }
2064
 
                }
2065
 
        }
2066
 
}
2067
 
 
2068
 
/////////////////////////////////////////////////////////////////////
2069
 
event doAllOutAttack(allOutAttackTr)
2070
 
{
2071
 
        if( idleGroup(attackGroup) >= (attackGroup.members / 3))        // make sure at least 30% are idle
2072
 
        {
2073
 
                if( (allOutAttack != NULLOBJECT) and (not helpingAlly()) )
2074
 
                {
2075
 
                        if( !friendlyPlayer(allOutAttack.player) )
2076
 
                        {
2077
 
                                if( getDroidCount(me) > 40)     // plenty of units.
2078
 
                                {
2079
 
                                        orderGroupObj(attackGroup, DORDER_ATTACK,allOutAttack);
2080
 
                                        //orderGroupLoc(defendGroup, DORDER_SCOUT,allOutAttack.x,allOutAttack.y);
2081
 
                                        orderGroupLoc(scoutGroup,  DORDER_SCOUT,allOutAttack.x,allOutAttack.y);
2082
 
                                }
2083
 
                        }
2084
 
                        else
2085
 
                        {
2086
 
                                allOutAttack = NULLOBJECT;
2087
 
                        }
2088
 
                }
2089
 
        }
2090
 
}
2091
 
 
2092
 
/////////////////////////////////////////////////////////////////////
2093
 
/////////////////////////////////////////////////////////////////////
2094
 
// defending rules
2095
 
 
2096
 
// defend attacked objects.
2097
 
event defendWatch(defendWatchTr)
2098
 
{
2099
 
        if(baseobj != NULLOBJECT)
2100
 
        {
2101
 
                if(!friendlyPlayer(baseobj.player))
2102
 
                {
2103
 
                        if(not isHumanPlayer(baseobj.player) )  // new in wdg1 dont allout attack a pc player   //TODO:is this check needed?
2104
 
                        {
2105
 
                                if(distBetweenTwoPoints(baseobj.x, baseobj.y, baseX, baseY) <= MAX_DEFENDERS_RADIUS)    //don't go too far away from the base
2106
 
                                {
2107
 
                                        defendObj = baseobj;
2108
 
                                        defendbusy = TRUE;
2109
 
                                        // if not too busy, attack.
2110
 
                                        if( idleGroup(defendGroup) >= (defendGroup.members / 2) )
2111
 
                                        {
2112
 
                                                orderGroupLoc(defendGroup, DORDER_MOVE,defendObj.x,defendObj.y);        //cyborg mechanics can't attack (won't move)
2113
 
                                                //orderGroupObj(defendGroup, DORDER_ATTACK, defendObj);
2114
 
                                        }
2115
 
 
2116
 
                                        if( idleGroup(scoutGroup) >= (scoutGroup.members / 2) )
2117
 
                                        {
2118
 
                                                orderGroupLoc(scoutGroup, DORDER_MOVE,scoutX,scoutY);
2119
 
                                        }
2120
 
                                }
2121
 
 
2122
 
                        }
2123
 
                }
2124
 
        }
2125
 
}
2126
 
 
2127
 
/////////////////////////////////////////////////////////////////////
2128
 
// defenders  return after they are finished.
2129
 
event defendReturn(defendReturnTr)
2130
 
{
2131
 
        if( defendbusy and (idleGroup(defendGroup) == (defendGroup.members - defendGroup.members / 12)))
2132
 
        {
2133
 
                // find a place with no structures nearby
2134
 
                buildX = baseX;
2135
 
                buildY = baseY;
2136
 
                pickStructLocationB(powGen, ref buildX, ref buildY, me, 0);
2137
 
 
2138
 
                orderGroupLoc(defendGroup, DORDER_MOVE,buildX,buildY);
2139
 
                defendbusy = FALSE;
2140
 
        }
2141
 
}
2142
 
 
2143
 
//returns number of non-idle structures of a certain type
2144
 
function int numStructBusyByType(STRUCTURESTAT _busyStructType)
2145
 
{
2146
 
        local   int _result;
2147
 
 
2148
 
        initEnumStruct(FALSE,_busyStructType,me,me);
2149
 
        structure = enumStruct();
2150
 
        _result = 0;
2151
 
        while(structure != NULLOBJECT)
2152
 
        {
2153
 
                if(structureComplete(structure))
2154
 
                {
2155
 
                        if(not structureIdle(structure))
2156
 
                        {
2157
 
                                _result++;
2158
 
                        }
2159
 
                }
2160
 
                structure = enumStruct();
2161
 
        }
2162
 
 
2163
 
        return _result;
2164
 
}
2165
 
 
2166
 
/////////////////////////////////////////////////////////////////////
2167
 
/////////////////////////////////////////////////////////////////////
2168
 
// Research Rules Now does true research.
2169
 
// do research
2170
 
 
2171
 
event doResearch(doResearchTr)
2172
 
{
2173
 
        local   int             _techIndex,_numResearching;
2174
 
 
2175
 
        _techIndex = 0; //research start
2176
 
        _numResearching = numStructBusyByType(resLab);
2177
 
 
2178
 
        // for every research lab do this..
2179
 
        initEnumStruct(FALSE,resLab,me,me);
2180
 
        structure= enumStruct();
2181
 
        count = 0;
2182
 
        while(structure != NULLOBJECT)
2183
 
        {
2184
 
                boolResult = FALSE;             //haven't started research for the current resFac
2185
 
 
2186
 
                if(structureIdle(structure))
2187
 
                {
2188
 
                        if(structureComplete(structure))
2189
 
                        {
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
2192
 
                                {
2193
 
                                        _techIndex = findResearch(_techIndex, curTech);
2194
 
                                        if(_techIndex > NONE)
2195
 
                                        {
2196
 
                                                boolResult = pursueResearch(structure,me,tech[curTech][_techIndex]);
2197
 
 
2198
 
                                                _techIndex++;   //try nect research next time if needed
2199
 
                                                _numResearching++;
2200
 
                                        }
2201
 
                                }
2202
 
 
2203
 
                                // do common research
2204
 
                                if(not boolResult)      //didn't start branch research
2205
 
                                {
2206
 
                                        if((maxIdleRes[curTech] == UNLIMITED) or (_numResearching < maxIdleRes[curTech]))
2207
 
                                        {
2208
 
                                                skDoResearch(structure,me,0);
2209
 
                                                _numResearching++;
2210
 
                                        }
2211
 
                                }
2212
 
                        }
2213
 
                }
2214
 
 
2215
 
                structure = enumStruct();
2216
 
        }
2217
 
}
2218
 
 
2219
 
// find next available research of our research branch
2220
 
function int findResearch(int _searchStart, int _techTree)
2221
 
{
2222
 
        local   int     _result;
2223
 
 
2224
 
        ASSERT(_searchStart >= 0, "findResearch: _searchStart < 0", me);
2225
 
        ASSERT(_techTree >= 0, "findResearch: _techTree < 0", me);
2226
 
 
2227
 
        _result = _searchStart;
2228
 
        while(_result < techCount[_techTree])
2229
 
        {
2230
 
                if((not researchFinished(tech[_techTree][_result], me)) and (not researchStarted(tech[_techTree][_result], me)))
2231
 
                {
2232
 
                        return _result;         //found research
2233
 
                }
2234
 
                _result++;
2235
 
        }
2236
 
 
2237
 
        return NONE;            //not found
2238
 
}
2239
 
 
2240
 
/////////////////////////////////////////////////////////////////////
2241
 
/////////////////////////////////////////////////////////////////////
2242
 
// Alliance Rules
2243
 
 
2244
 
// form alliances
2245
 
event formAllianceEvent(formAllianceEventTr)
2246
 
{
2247
 
 
2248
 
        count = 0;
2249
 
        while(count < MAX_PLAYERS)
2250
 
        {
2251
 
                if( count != me )                                                                                               // if not the only other player and rand2
2252
 
                {
2253
 
                        if((getDroidCount(me) > 1) and (getDroidCount(count) > 1) )     // not dead
2254
 
                        {
2255
 
                                if(random(28) == 1)                                                                                     // bit random
2256
 
                                {
2257
 
                                        if(not isHumanPlayer(count))                                                    // not human
2258
 
                                        {
2259
 
                                                createAlliance(me,count);
2260
 
                                                allianceTime[count] = gameTime;
2261
 
                                        }
2262
 
                                }
2263
 
                        }
2264
 
                }
2265
 
                count = count + 1;
2266
 
        }
2267
 
}
2268
 
 
2269
 
/////////////////////////////////////////////////////////////////////
2270
 
// break the alliance too.
2271
 
event breakAllianceEvent(breakAllianceEventTr)
2272
 
{
2273
 
        count = 0;
2274
 
        while(count<multiPlayerMaxPlayers)
2275
 
        {
2276
 
                if( count != me)
2277
 
                {
2278
 
                        if((getDroidCount(me) > 1) and (getDroidCount(count) > 1) )     // not dead
2279
 
                        {
2280
 
                                if(allianceExistsBetween(me,count) )
2281
 
                                {
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.
2284
 
                                        {
2285
 
                                                allianceTime[count] = gameTime;
2286
 
                                                breakAlliance(me,count);
2287
 
                                        }
2288
 
 
2289
 
                                        // rules for breaking alliances with humans.
2290
 
                                        // built within my base
2291
 
                                        if(numStructsInArea(count,minx,miny,maxx,maxy) > 1)
2292
 
                                        {
2293
 
                                                allianceTime[count] = gameTime;
2294
 
                                                breakAlliance(me,count);
2295
 
                                        }
2296
 
 
2297
 
                                        // you've got lots of units in my area.
2298
 
                                        if(numDroidsInArea(count,minx,miny,maxx,maxy) > 3)
2299
 
                                        {
2300
 
                                                allianceTime[count] = gameTime;
2301
 
                                                breakAlliance(me,count);
2302
 
                                        }
2303
 
 
2304
 
                                        // you've wiped out one of my allies ??.
2305
 
                                }
2306
 
                        }
2307
 
                }
2308
 
                count = count + 1;
2309
 
        }
2310
 
}
2311
 
 
2312
 
/////////////////////////////////////////////////////////////////////
2313
 
event formHumanAlliances(humanAllianceTr)
2314
 
{
2315
 
        if(count2 == me) // offered to me.
2316
 
        {
2317
 
                result = 0;
2318
 
                result2 = 0;
2319
 
                while(result < multiPlayerMaxPlayers)
2320
 
                {
2321
 
                        if(allianceExistsBetween(count,result))
2322
 
                        {
2323
 
                                result2 = result2 + 1;
2324
 
                        }
2325
 
                        result = result + 1;
2326
 
                }
2327
 
                if( result2 < ((multiPlayerMaxPlayers / 2) - 1) )       // not too many already
2328
 
                {
2329
 
                        //not too soon.
2330
 
                        if((allianceTime[count] == 0) or (gameTime - allianceTime[count] > 1200))
2331
 
                        {
2332
 
                                result = 0;                                                             // check forming wont end the game
2333
 
                                result2 = 0;
2334
 
                                while(result < multiPlayerMaxPlayers)
2335
 
                                {
2336
 
                                        while(result2 < multiPlayerMaxPlayers)
2337
 
                                        {
2338
 
                                                if((not allianceExistsBetween(result,result2)) and (getDroidCount(result) > 0) and (getDroidCount(result2) > 0) and (result != result2) )
2339
 
                                                {
2340
 
                                                        if( ((result == count and result2 == count2) or (result2 == count2 and result == count)) )      // ignore the outcome of this alliance
2341
 
                                                        {
2342
 
                                                                createAlliance(me,count);
2343
 
                                                                allianceTime[count] = gameTime;
2344
 
                                                        }
2345
 
                                                }
2346
 
                                                result2 = result2 + 1;
2347
 
                                        }
2348
 
                                        result = result + 1;
2349
 
                                }
2350
 
                        }
2351
 
 
2352
 
                }
2353
 
        }
2354
 
}
2355
 
 
2356
 
/////////////////////////////////////////////////////////////////////
2357
 
/////////////////////////////////////////////////////////////////////
2358
 
// Consolidate Rules
2359
 
 
2360
 
// bring forces back together to consolidate attacks
2361
 
event consolidateEvent(consolidateEventTr)
2362
 
{
2363
 
        if(not helpingAlly())
2364
 
        {
2365
 
                if(random(3) == 1)                              // order all droids home to rejoin forces.!
2366
 
                {
2367
 
                        // find a place with no structures nearby
2368
 
                        buildX = baseX;
2369
 
                        buildY = baseY;
2370
 
                        pickStructLocationB(powGen, ref buildX, ref buildY, me, 0);
2371
 
 
2372
 
                        orderGroupLoc(scoutGroup, DORDER_MOVE,buildX,buildY);
2373
 
                        orderGroupLoc(defendGroup, DORDER_MOVE,buildX,buildY);
2374
 
                }
2375
 
 
2376
 
/*
2377
 
                if(attackObj != NULLOBJECT)     // consolidate any ongoing attack.
2378
 
                {
2379
 
                        if(!friendlyPlayer(attackObj.player))
2380
 
                        {
2381
 
                                orderGroupLoc(attackGroup, DORDER_SCOUT, attackObj.x, attackObj.y);
2382
 
                        }
2383
 
                        else
2384
 
                        {
2385
 
                                attackObj = NULLOBJECT;
2386
 
                        }
2387
 
                }
2388
 
                else if(allOutAttack == NULLOBJECT) //make sure not allOutAttacking
2389
 
                {
2390
 
 
2391
 
                        // find a place with no structures nearby
2392
 
                        buildX = baseX;
2393
 
                        buildY = baseY;
2394
 
                        pickStructLocationB(powGen, ref buildX, ref buildY, me, 0);
2395
 
 
2396
 
                        orderGroupLoc(attackGroup, DORDER_MOVE,buildX,buildY);
2397
 
                }
2398
 
*/
2399
 
        }
2400
 
}
2401
 
 
2402
 
/////////////////////////////////////////////////////////////////////
2403
 
/////////////////////////////////////////////////////////////////////
2404
 
// power management.
2405
 
 
2406
 
// if running low on power put some power eating stuff on hold for a while.
2407
 
event managePower(managePowerTr)
2408
 
{
2409
 
        if( playerPower(me) < LOW_POWER )       // turn off some events.
2410
 
        {
2411
 
                powerSave = TRUE;
2412
 
 
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.
2417
 
        }
2418
 
        else
2419
 
        {
2420
 
                if(powerSave == TRUE)           // turn events back on.
2421
 
                {
2422
 
                        powerSave = FALSE;
2423
 
 
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.
2428
 
                }
2429
 
        }
2430
 
}
2431
 
/////////////////////////////////////////////////////////////////////
2432
 
 
2433
 
event difficultyModifier(difficultyModifierTr)
2434
 
{
2435
 
        if(not isHumanPlayer(me))
2436
 
        {
2437
 
                skDifficultyModifier(me);
2438
 
        }
2439
 
}
2440
 
 
2441
 
/////////////////////////////////////////////////////////////////////
2442
 
// vtols.
2443
 
/////////////////////////////////////////////////////////////////////
2444
 
// build vtol strucutures.
2445
 
event vtolStructs(inactive)
2446
 
{
2447
 
        local   int             _maxTrucks,_numTrucks,_maxBuildTrucks,_minBuildTrucks;
2448
 
        local   int             _numVtolFacs,_numRearmPads;
2449
 
 
2450
 
        // got any idle trucks?
2451
 
        if(idleGroup(buildGroup) < 1){
2452
 
                exit;
2453
 
        }
2454
 
 
2455
 
        // see how many vtol factories we already have
2456
 
        _numVtolFacs = getNumStructures(vtolFactory,me);
2457
 
        _numRearmPads = getNumStructures(vtolPad,me);
2458
 
 
2459
 
        //see if we have enough rearm pads
2460
 
        if( _numRearmPads * 4 / 3 <= totalVtols() )
2461
 
        {
2462
 
                dbg("NEED REARM PADS", me);
2463
 
                buildRearmPads();
2464
 
        }
2465
 
 
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));
2470
 
 
2471
 
        if(_numVtolFacs < maxVtolFacs[curTech])                 // if not enough
2472
 
        {
2473
 
                // build factory
2474
 
                buildX = baseX;                                                         // pick a location
2475
 
                buildY = baseY;
2476
 
                boolResult = pickStructLocation(vtolFactory, ref buildX, ref buildY,me);
2477
 
                if(boolResult == TRUE)
2478
 
                {
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))
2483
 
                        {
2484
 
                                if( (droid.order == DORDER_NONE) or (droid.order == DORDER_RTB))
2485
 
                                {
2486
 
                                        orderDroidStatsLoc(droid, DORDER_BUILD,vtolFactory, buildX,buildY);
2487
 
                                        _numTrucks++;
2488
 
                                }
2489
 
                                droid = iterateGroup(buildGroup);
2490
 
                        }
2491
 
                }
2492
 
        }
2493
 
}
2494
 
 
2495
 
//counts vtols
2496
 
function int totalVtols()
2497
 
{
2498
 
        local   int             _vtolGroup,_totalVtols;
2499
 
 
2500
 
        _totalVtols = 0;
2501
 
        _vtolGroup = 0;
2502
 
        while(_vtolGroup < numVtolAttackGroups)
2503
 
        {
2504
 
                _totalVtols = _totalVtols + vtolAttackGr[_vtolGroup].members;
2505
 
                _vtolGroup++;
2506
 
        }
2507
 
 
2508
 
        _totalVtols = _totalVtols + vtolDefendGr.members;
2509
 
 
2510
 
        return _totalVtols;
2511
 
}
2512
 
 
2513
 
function void buildRearmPads()
2514
 
{
2515
 
        local   int             _buildX,_buildY;
2516
 
        local   DROID   _truck;
2517
 
        local   bool    _buildOK;
2518
 
 
2519
 
        if(!isStructureAvailable(vtolPad,me)){
2520
 
                return;
2521
 
        }
2522
 
 
2523
 
        // build vtol rearm pads.
2524
 
        _buildX = baseX;                                                                // pick a location
2525
 
        _buildY = baseY;
2526
 
 
2527
 
        _buildOK = pickStructLocation(vtolPad, ref _buildX, ref _buildY,me);
2528
 
        if(_buildOK)
2529
 
        {
2530
 
                initIterateGroup(buildGroup);                   // find idle droids in build group.
2531
 
                _truck = iterateGroup(buildGroup);
2532
 
                _buildOK = FALSE;
2533
 
                while(_truck != NULLOBJECT and _buildOK == FALSE)
2534
 
                {
2535
 
                        if((_truck.order != DORDER_BUILD) and (_truck.order != DORDER_LINEBUILD))
2536
 
                        {
2537
 
                                orderDroidStatsLoc(_truck, DORDER_BUILD,vtolPad, _buildX,_buildY);
2538
 
                                _buildOK = TRUE;
2539
 
                        }
2540
 
                        _truck = iterateGroup(buildGroup);
2541
 
                }
2542
 
        }
2543
 
}
2544
 
 
2545
 
 
2546
 
/////////////////////////////////////////////////////////////////////
2547
 
// build vtols.
2548
 
 
2549
 
event buildVtols(inactive)
2550
 
{
2551
 
 
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);
2555
 
                exit;
2556
 
        }
2557
 
 
2558
 
        // build vtols
2559
 
        initEnumStruct(FALSE,vtolFactory,me,me);
2560
 
        structure = enumStruct();
2561
 
        while(structure != NULLOBJECT)
2562
 
        {
2563
 
                if(structureIdle(structure))    // if factory idle
2564
 
                {
2565
 
                        vtolFactoryBuildVtol(structure);
2566
 
                }
2567
 
 
2568
 
                structure = enumStruct();
2569
 
        }
2570
 
}
2571
 
 
2572
 
 
2573
 
function void vtolFactoryBuildVtol(STRUCTURE _factory)
2574
 
{
2575
 
        local   int             _numTemplates,_bestTemplates;
2576
 
 
2577
 
        if(_factory == NULLOBJECT){
2578
 
                return;
2579
 
        }
2580
 
 
2581
 
        if( structureIdle(_factory) )
2582
 
        {
2583
 
                _numTemplates = numVtolTemplates - 1;
2584
 
                _bestTemplates = 0;
2585
 
                while( (_bestTemplates < 3) and (_numTemplates >= 0) )
2586
 
                {
2587
 
                        if( skCanBuildTemplate(me,_factory, vtols[_numTemplates]) )
2588
 
                        {
2589
 
                                tmplChoice[_bestTemplates] = vtols[_numTemplates];
2590
 
                                _bestTemplates++;
2591
 
                        }
2592
 
                        _numTemplates--;
2593
 
                }
2594
 
 
2595
 
                if(_bestTemplates > 0)
2596
 
                {
2597
 
                        buildDroid(tmplChoice[random(_bestTemplates)],_factory,me,1);
2598
 
                }
2599
 
        }
2600
 
}
2601
 
 
2602
 
/////////////////////////////////////////////////////////////////////
2603
 
// attack with vtols.
2604
 
 
2605
 
event vtolAttack(inactive)
2606
 
{
2607
 
        local           int                     _groupIndex,_newTargetWeight,_oldTargetWeight;
2608
 
        local           BASEOBJ         _newTarget;
2609
 
        local           bool            _bHaveDefendTarget;
2610
 
        local           DROID           _droid;
2611
 
 
2612
 
        // if vtol group is not busy..
2613
 
        if(  (idleGroup(vtolDefendGr) >= (vtolDefendGr.members / 2)) and (vtolDefendGr.members >= 2) )
2614
 
        {
2615
 
                if(attackObj != NULLOBJECT)
2616
 
                {
2617
 
                        if(!friendlyPlayer(attackObj.player))
2618
 
                        {
2619
 
                                orderGroupObj(vtolDefendGr, DORDER_ATTACK, attackObj);  // get the attack target.
2620
 
                        }
2621
 
                        else
2622
 
                        {
2623
 
                                attackObj = NULLOBJECT;
2624
 
                        }
2625
 
                }
2626
 
                else
2627
 
                {
2628
 
                        if(defendObj != NULLOBJECT)
2629
 
                        {
2630
 
                                if(not isHumanPlayer(defendObj.player) )        // new in wdg1  //TODO:is this check needed?
2631
 
                                {
2632
 
                                        orderGroupObj(vtolDefendGr, DORDER_ATTACK,defendObj);           // get the defend target
2633
 
                                }
2634
 
                        }
2635
 
                }
2636
 
        }
2637
 
 
2638
 
        //make sure attack vtol groups are not cluttered
2639
 
        rearrangeAttackVtols();
2640
 
 
2641
 
        //attack vtols
2642
 
        _groupIndex = 0;
2643
 
        while(_groupIndex < numVtolAttackGroups)
2644
 
        {
2645
 
                if(vtolAttackGr[_groupIndex].members > 0)
2646
 
                {
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))
2651
 
                        {
2652
 
                                if(defendingOwnBase() and
2653
 
                                        (distBetweenTwoPoints(baseX, baseY, vtolGrAttackObj[_groupIndex].x, vtolGrAttackObj[_groupIndex].y) <= MAX_VTOL_DEFEND_RADIUS))
2654
 
                                {
2655
 
                                        _bHaveDefendTarget = TRUE;
2656
 
                                }
2657
 
                                else    //reset target if it's not worth it
2658
 
                                {
2659
 
                                        //we don't want to attack enemy heavy tanks outside of our base
2660
 
                                        if(vtolGrAttackObj[_groupIndex].type == OBJ_DROID)
2661
 
                                        {
2662
 
                                                _droid = objToDroid(vtolGrAttackObj[_groupIndex]);
2663
 
                                                if(_droid.droidType != DROID_CONSTRUCT)
2664
 
                                                {
2665
 
                                                        vtolGrAttackObj[_groupIndex] = NULLOBJECT;      //reset target
2666
 
                                                        _bHaveDefendTarget = FALSE;
2667
 
                                                }
2668
 
                                        }
2669
 
                                }
2670
 
                        }
2671
 
 
2672
 
                        //find target in our base if our base is in trouble
2673
 
                        if(!_bHaveDefendTarget and defendingOwnBase())
2674
 
                        {
2675
 
                                vtolGrAttackObj[_groupIndex] = chooseVtolDefenceTarget(baseX, baseY, MAX_VTOL_DEFEND_RADIUS, FALSE);
2676
 
 
2677
 
                                if(vtolGrAttackObj[_groupIndex] != NULLOBJECT)
2678
 
                                {
2679
 
                                        dbg("assigned new defence target for group " & _groupIndex, me);
2680
 
                                        _bHaveDefendTarget = TRUE;
2681
 
                                }
2682
 
                        }
2683
 
 
2684
 
                        //attack rules
2685
 
                        if(!_bHaveDefendTarget and (idleGroup(vtolAttackGr[_groupIndex]) >= (vtolAttackGr[_groupIndex].members / 2)) and
2686
 
                        (vtolAttackGr[_groupIndex].members >= (numAttackVtols * 2 / 3)))
2687
 
                        {
2688
 
                                _newTarget = NULLOBJECT;
2689
 
 
2690
 
                                //reset attack targets once in a while
2691
 
                                if(vtolGrAttackObj[_groupIndex] != NULLOBJECT)
2692
 
                                {
2693
 
                                        if(random(10) > 7)
2694
 
                                        {
2695
 
                                                vtolGrAttackObj[_groupIndex] = NULLOBJECT;
2696
 
                                        }
2697
 
                                }
2698
 
 
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)
2703
 
                                {
2704
 
                                        _newTarget = chooseVtolTarget(FALSE);   //search for any target
2705
 
                                }
2706
 
 
2707
 
                                _newTargetWeight = getVtolTargetWeight(_newTarget);
2708
 
                                _oldTargetWeight = getVtolTargetWeight(vtolGrAttackObj[_groupIndex]);
2709
 
 
2710
 
                                // new one or a much better one
2711
 
                                if((_newTargetWeight >= (_oldTargetWeight + 20)) or
2712
 
                                        (vtolGrAttackObj[_groupIndex] == NULLOBJECT ))
2713
 
                                {
2714
 
                                        dbg("choosing new attack object for " & _groupIndex, me);
2715
 
                                        vtolGrAttackObj[_groupIndex] = _newTarget;
2716
 
                                }
2717
 
                        }
2718
 
 
2719
 
                        //see if this group has something to attack
2720
 
                        if(vtolGrAttackObj[_groupIndex] != NULLOBJECT)
2721
 
                        {
2722
 
                                if(!friendlyPlayer(vtolGrAttackObj[_groupIndex].player))
2723
 
                                {
2724
 
                                        dbg("VTOL Group " & _groupIndex & " attacking", me);
2725
 
 
2726
 
                                        if(_DEBUG and (_groupIndex == 0))
2727
 
                                        {
2728
 
                                                dropBeacon(getPlayerName(me), me, me, vtolGrAttackObj[_groupIndex].x, vtolGrAttackObj[_groupIndex].y, 0);
2729
 
                                        }
2730
 
 
2731
 
                                        orderGroupObj(vtolAttackGr[_groupIndex], DORDER_ATTACK, vtolGrAttackObj[_groupIndex]);
2732
 
                                }
2733
 
                                else
2734
 
                                {
2735
 
                                        vtolGrAttackObj[_groupIndex] = NULLOBJECT;
2736
 
                                }
2737
 
                        }
2738
 
                }
2739
 
 
2740
 
                _groupIndex++;
2741
 
        }
2742
 
}
2743
 
 
2744
 
//make sure vtol groups are not cluttered
2745
 
function void rearrangeAttackVtols()
2746
 
{
2747
 
        local   int             _emptyGr,_fillGr;
2748
 
        local   DROID   _droid;
2749
 
 
2750
 
        _emptyGr = 0;
2751
 
        while(_emptyGr < numVtolAttackGroups)
2752
 
        {
2753
 
                if((vtolAttackGr[_emptyGr].members < numAttackVtols) and        //this group is not full
2754
 
                        (vtolAttackGr[_emptyGr].members > 0))
2755
 
                {
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))
2760
 
                        {
2761
 
                                initIterateGroup(vtolAttackGr[_fillGr]);
2762
 
                                _droid = iterateGroup(vtolAttackGr[_fillGr]);
2763
 
                                while((_droid != NULLOBJECT) and
2764
 
                                        (vtolAttackGr[_emptyGr].members < numAttackVtols))
2765
 
                                {
2766
 
                                        groupAddDroid(vtolAttackGr[_emptyGr], _droid);  //refill the group
2767
 
                                        _droid = iterateGroup(vtolAttackGr[_fillGr]);
2768
 
                                }
2769
 
 
2770
 
                                _fillGr++;
2771
 
                        }
2772
 
                }
2773
 
                _emptyGr++;
2774
 
        }
2775
 
}
2776
 
 
2777
 
function BASEOBJ chooseVtolDefenceTarget(int _x, int _y, int _range, bool bExclusiveTarget)
2778
 
{
2779
 
        local   BASEOBJ         _target;
2780
 
 
2781
 
        _target = getClosestEnemy(_x, _y, _range, FALSE, FALSE, me);
2782
 
 
2783
 
        // make sure no one else is targeting it already if we want exclusive targets
2784
 
        if(bExclusiveTarget and vtolTargetAssigned(_target))
2785
 
        {
2786
 
                _target = NULLOBJECT;
2787
 
        }
2788
 
 
2789
 
        return _target;
2790
 
}
2791
 
 
2792
 
function BASEOBJ chooseVtolTarget(bool bExclusiveTarget)
2793
 
{
2794
 
        local   int                             _structTypeIndex,_enemy;
2795
 
        local   int                             _bestScore,_tempScore;
2796
 
        local   BASEOBJ                 _bestTarget;
2797
 
        local   STRUCTURE               _structure;
2798
 
 
2799
 
        _bestScore = 0;
2800
 
        _bestTarget = NULLOBJECT;
2801
 
 
2802
 
        _enemy = 0;
2803
 
        while(_enemy < MAX_PLAYERS)
2804
 
        {
2805
 
                if(!friendlyPlayer(_enemy))
2806
 
                {
2807
 
                        _structTypeIndex = 0;
2808
 
                        while(_structTypeIndex < numVtolTargets)
2809
 
                        {
2810
 
                                initEnumStruct(FALSE,vtolTarget[_structTypeIndex],_enemy,me);
2811
 
                                _structure = enumStruct();
2812
 
                                while(_structure != NULLOBJECT)
2813
 
                                {
2814
 
 
2815
 
                                        // in case we don't want all groups to attack the same target
2816
 
                                        if(not (bExclusiveTarget and vtolTargetAssigned(_structure)) )
2817
 
                                        {
2818
 
                                                _tempScore = getVtolTargetWeight(_structure);
2819
 
 
2820
 
                                                //see if this one is better
2821
 
                                                if(_tempScore > _bestScore)
2822
 
                                                {
2823
 
                                                        _bestScore = _tempScore;
2824
 
                                                        _bestTarget = _structure;
2825
 
                                                }
2826
 
                                        }
2827
 
 
2828
 
                                        _structure = enumStruct();
2829
 
                                }
2830
 
 
2831
 
                                _structTypeIndex++;
2832
 
                        }
2833
 
                }
2834
 
                _enemy++;
2835
 
        }
2836
 
 
2837
 
        return _bestTarget;
2838
 
}
2839
 
 
2840
 
function int getVtolTargetWeight(BASEOBJ _target)
2841
 
{
2842
 
        local   int             _AAPenalty,_numAA,_range,_targetWeight;
2843
 
        local   int             _targetType;
2844
 
        local   STRUCTURE       _structTarget;
2845
 
 
2846
 
        if(_target == NULLOBJECT)
2847
 
        {
2848
 
                return 0;
2849
 
        }
2850
 
 
2851
 
        if(_target.type != OBJ_STRUCTURE)
2852
 
        {
2853
 
                return 0;
2854
 
        }
2855
 
 
2856
 
        _structTarget = objToStructure(_target);
2857
 
 
2858
 
        _targetWeight = 0;
2859
 
 
2860
 
        _AAPenalty = 9;                 //penalty per aa defense
2861
 
        _range = AA_THREAT_RANGE;
2862
 
 
2863
 
        // count enemy AA
2864
 
        _numAA = numEnemyAAInRange(_structTarget.x, _structTarget.y, _range);
2865
 
 
2866
 
        // find tyrget type from stats
2867
 
        _targetType = 0;
2868
 
        while(_targetType < numVtolTargets)
2869
 
        {
2870
 
                if(_structTarget.stat == vtolTarget[_targetType])
2871
 
                {
2872
 
                        _targetWeight = vtolTargetWeight[_targetType] - (_numAA * _AAPenalty);
2873
 
 
2874
 
                        _targetType = numVtolTargets;   //exit loop
2875
 
                }
2876
 
                _targetType++;
2877
 
        }
2878
 
 
2879
 
        // incomplete structures get lower weight
2880
 
        if(!structureComplete(_structTarget))
2881
 
        {
2882
 
                _targetWeight = _targetWeight / 10;
2883
 
        }
2884
 
 
2885
 
        return _targetWeight;
2886
 
}
2887
 
 
2888
 
function int numEnemyAAInRange(int _x, int _y, int _range)
2889
 
{
2890
 
        local int _enemy,_numAA;
2891
 
 
2892
 
        _numAA = 0;
2893
 
        _enemy = 0;
2894
 
        while(_enemy < MAX_PLAYERS)
2895
 
        {
2896
 
                if(!friendlyPlayer(_enemy))
2897
 
                {
2898
 
                        _numAA = _numAA + numAAinRange(_enemy, me, _x, _y, _range);
2899
 
                }
2900
 
                _enemy++;
2901
 
        }
2902
 
 
2903
 
        return _numAA;
2904
 
}
2905
 
 
2906
 
// see if a particular target is already assigned to one of the VTOL attack groups
2907
 
function bool vtolTargetAssigned(BASEOBJ _target)
2908
 
{
2909
 
        local int _groupIndex;
2910
 
 
2911
 
        if(_target == NULLOBJECT)
2912
 
        {
2913
 
                return FALSE;
2914
 
        }
2915
 
 
2916
 
        _groupIndex = 0;
2917
 
        while(_groupIndex < numVtolAttackGroups)
2918
 
        {
2919
 
                if(_target == vtolGrAttackObj[_groupIndex])
2920
 
                {
2921
 
                        return TRUE;
2922
 
                }
2923
 
 
2924
 
                _groupIndex++;
2925
 
        }
2926
 
 
2927
 
        return FALSE;
2928
 
}
2929
 
 
2930
 
/////////////////////////////////////////////////////////////////////
2931
 
// watch for incoming vtols
2932
 
event vtolDefend(vtolDefendTr)
2933
 
{
2934
 
        local   int             _numBuilders,_maxBuilders;
2935
 
 
2936
 
 
2937
 
//              boolResult2 = FALSE;                                    // if attacked by a vtol.
2938
 
        if(baseobj != NULLOBJECT)
2939
 
        {
2940
 
                if(baseobj.type == OBJ_DROID)
2941
 
                {
2942
 
                        if(isVtol(objToDroid(baseobj)))
2943
 
                        {
2944
 
                                // activate other vtol functions..
2945
 
                                setEventTrigger(vtolStructs,vtolStructsTr);
2946
 
                                setEventTrigger(buildVtols,     buildVtolsTr);
2947
 
                                setEventTrigger(vtolAttack,     vtolAttackTr);
2948
 
 
2949
 
                                _numBuilders = 0;
2950
 
                                _maxBuilders = 2;
2951
 
 
2952
 
                                // build defenses.
2953
 
                                initIterateGroup(buildGroup);           // find idle droids in build group.
2954
 
                                droid = iterateGroup(buildGroup);
2955
 
//                                      while( (boolResult2 != TRUE) and (droid != NULLOBJECT))
2956
 
                                while( droid != NULLOBJECT)
2957
 
                                {
2958
 
                                        if( (structure != NULLOBJECT) and (droid.order != DORDER_BUILD) )
2959
 
                                        {
2960
 
                                                buildX = structure.x;
2961
 
                                                buildY = structure.y;
2962
 
                                                //      if ! vtol defense already built...
2963
 
 
2964
 
                                                //find best defense we can build.
2965
 
                                                count = 0;
2966
 
                                                count2 = -1;
2967
 
                                                while( count < 5)
2968
 
                                                {
2969
 
                                                        if(isStructureAvailable(vtolDefStruct[count],me))
2970
 
                                                        {
2971
 
                                                                count2 = count;
2972
 
                                                        }
2973
 
                                                        count = count + 1;
2974
 
                                                }
2975
 
                                                if(count2 != (-1) )
2976
 
                                                {
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...
2979
 
                                                        {
2980
 
                                                                orderDroidStatsLoc(droid, DORDER_BUILD,vtolDefStruct[count2],buildX,buildY);
2981
 
                                                                _numBuilders++;
2982
 
//                                                                      boolResult2 = TRUE;
2983
 
                                                        }
2984
 
                                                }
2985
 
 
2986
 
                                        }
2987
 
                                        droid = iterateGroup(buildGroup);
2988
 
                                }
2989
 
                        }
2990
 
                }
2991
 
        }
2992
 
}
2993
 
 
2994
 
/////////////////////////////////////////////////////////////////////
2995
 
event vtolEnabler(vtolEnablerTr)
2996
 
{
2997
 
        if( skVtolEnableCheck(me) )                                     // check to see if we have vtol technologies.
2998
 
        {
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);
3004
 
        }
3005
 
}
3006
 
 
3007
 
/////////////////////////////////////////////////////////////////////
3008
 
// HouseKeeping
3009
 
 
3010
 
function void shutDownAI()
3011
 
{
3012
 
        bRunning = false;
3013
 
 
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);
3062
 
}
3063
 
 
3064
 
event reassignPlayers(reassignTr)
3065
 
{
3066
 
        if(count == me)
3067
 
        {
3068
 
                dbg(" AI 5 is reassigningAI to dropped player ", me);
3069
 
                //reassignAI();
3070
 
        }
3071
 
}
3072
 
 
3073
 
function void reassignAI()
3074
 
{
3075
 
        bRunning = true;
3076
 
 
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);
3125
 
}
3126
 
 
3127
 
/* Returns true if we just received a beacon from a certain player */
3128
 
function bool haveBeacon(int _player)
3129
 
{
3130
 
                if((tBeacon[_player] > 0) and (not beaconTimeout(_player)))
3131
 
                {
3132
 
                        return TRUE;    //have beacon for this player
3133
 
                }
3134
 
 
3135
 
                return FALSE;
3136
 
}
3137
 
 
3138
 
/* See if last beacon was placed long ago */
3139
 
function bool beaconTimeout(int _player)
3140
 
{
3141
 
        if((tBeacon[_player] > 0) and
3142
 
                ((tBeacon[_player] + BEACON_TIMEOUT) < (gameTime / 10)))        //not too long ago
3143
 
        {
3144
 
                return TRUE;    //this beacon is still 'fresh'
3145
 
        }
3146
 
 
3147
 
        return FALSE;
3148
 
}
3149
 
 
3150
 
/* Deal with beacons */
3151
 
event beaconEv(beaconTr)
3152
 
{
3153
 
        local   int                     _players;
3154
 
        local   string          _processedString;
3155
 
 
3156
 
        if(_DEBUG)
3157
 
                debug(me & ") beaconEv: from " & sender);
3158
 
 
3159
 
        ASSERT(sender >= 0 and sender < 8,
3160
 
                "beaconEv: sender out of bounds: " & sender , me);
3161
 
 
3162
 
        beaconX[sender] = x;
3163
 
        beaconY[sender] = y;
3164
 
        tBeacon[sender] = gameTime / 10;
3165
 
 
3166
 
        processCommand(message, sender, TRUE);
3167
 
}
3168
 
 
3169
 
/* Deal with a chat message */
3170
 
event multiMsgEv(multiMsgTr)
3171
 
{
3172
 
        if(_DEBUG)
3173
 
                debug(me & ") multiMsgEv: from " & sender);
3174
 
 
3175
 
        if(not allianceExistsBetween(me, sender)){
3176
 
                exit;
3177
 
        }
3178
 
 
3179
 
        if(sender == me){
3180
 
                exit;
3181
 
        }
3182
 
 
3183
 
        processCommand(message, sender, FALSE);
3184
 
}
3185
 
 
3186
 
/* Process multiplayer messages */
3187
 
function void processCommand(string _message, int _sender, bool _bBlipMessage)
3188
 
{
3189
 
        local   int             _numMsgs,_curMsg,_addressedPlayers,_x,_y;
3190
 
        local   string          _msg,_processedString;
3191
 
 
3192
 
        /* Extract semantic information */
3193
 
        _curMsg = 0;
3194
 
        _numMsgs = processChatMsg(_message);
3195
 
 
3196
 
        debug(me & ") processCommand: '" & _message & "' from " & _sender);
3197
 
        dbg("processCommand: '" & _message & "' from " & _sender, me);
3198
 
        dbg("got " & _numMsgs & " commands", me);
3199
 
 
3200
 
        /* Process all messages */
3201
 
        while(_curMsg < _numMsgs)
3202
 
        {
3203
 
                if(chatCmdIsPlayerAddressed(_curMsg, me))
3204
 
                {
3205
 
                        dbg("i'm addressed", me);
3206
 
                        _msg = getChatCmdDescription(_curMsg);
3207
 
 
3208
 
                        /* Someone requested help */
3209
 
                        if(_msg == R_REQUEST_HELP)
3210
 
                        {
3211
 
                                dbg("'help' command", me);
3212
 
 
3213
 
                                if(haveBeacon(_sender))
3214
 
                                {
3215
 
                                        dbg("got beacon", me);
3216
 
 
3217
 
                                        _x = beaconX[_sender];
3218
 
                                        _y = beaconY[_sender];
3219
 
 
3220
 
                                        if(attemptToHelp(_sender, _x, _y))
3221
 
                                        {
3222
 
                                                messagePlayer(ALL_ALLIES, m_affirmative(), MAX_PROBABILITY);
3223
 
                                        }
3224
 
                                }
3225
 
                                else
3226
 
                                {
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);
3230
 
                                }
3231
 
                        }
3232
 
                        /* Someone requested a beacon from us -
3233
 
                         * did we request help and our beacon timed out??
3234
 
                         */
3235
 
                        else if(_msg == M_REQUEST_BEACON)
3236
 
                        {
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);
3240
 
                                }
3241
 
                        }
3242
 
                        else if(_msg == R_REPORT_SAFETY)
3243
 
                        {
3244
 
                                dbg("helping " & lastHelpPlayer, me);
3245
 
 
3246
 
                                /* Make sure we were helping him */
3247
 
                                if(helpingAlly() and (lastHelpPlayer == _sender))
3248
 
                                {
3249
 
                                        stopHelpingAlly();
3250
 
                                        messagePlayer(ALL_ALLIES, m_affirmative(), MAX_PROBABILITY);
3251
 
                                }
3252
 
                                else if(defendingOwnBase())     //if we are in trouble re-request help
3253
 
                                {
3254
 
                                        requestHelp(baseX, baseY);
3255
 
                                }
3256
 
                        }
3257
 
                        else
3258
 
                        {
3259
 
                                dbg("unknown message", me);
3260
 
                        }
3261
 
 
3262
 
                }
3263
 
                else
3264
 
                {
3265
 
                        dbg("i'm not addressed", me);
3266
 
                }
3267
 
 
3268
 
                _curMsg++;
3269
 
        }
3270
 
}
3271
 
 
3272
 
function bool attemptToHelp(int _playerToHelp, int _x, int _y)
3273
 
{
3274
 
        local bool _bHelpingMyself;
3275
 
 
3276
 
        if(_playerToHelp < 0 or _playerToHelp >= MAX_PLAYERS){
3277
 
                return FALSE;
3278
 
        }
3279
 
 
3280
 
        if(_x <= 0 or _y <= 0){
3281
 
                return FALSE;
3282
 
        }
3283
 
 
3284
 
        dbg("attemptToHelp - checking", me);
3285
 
 
3286
 
        _bHelpingMyself = (_playerToHelp == me);
3287
 
 
3288
 
        /* Can only help allies and myself */
3289
 
        if(not friendlyPlayer(_playerToHelp)){
3290
 
                return FALSE;
3291
 
        }
3292
 
 
3293
 
        if(_bHelpingMyself or !helpingAlly() or (lastHelpPlayer == _playerToHelp) )     //if not helping any other ally or it's me who needs help
3294
 
        {
3295
 
                dbg("not busy helping", me);
3296
 
 
3297
 
                if(haveHelpers() or _DEBUG)
3298
 
                {
3299
 
                        dbg("got attackers", me);
3300
 
                        if(allyBaseAtLoc(_playerToHelp, _x, _y))        //is he just trying to misuse us?
3301
 
                        {
3302
 
                                helpPlayer(_playerToHelp, _x, _y);
3303
 
                                return TRUE;
3304
 
                        }
3305
 
                        else
3306
 
                        {
3307
 
                                dbg("ally needs no help", me);
3308
 
                                messagePlayer(ALL_ALLIES, M_ANNOYED, MAX_PROBABILITY / 2);
3309
 
                        }
3310
 
                }
3311
 
                else
3312
 
                {
3313
 
                        messagePlayer(ALL_ALLIES, M_HELP_NO_UNITS, MAX_PROBABILITY);
3314
 
                }
3315
 
        }
3316
 
        else if((lastHelpPlayer >= 0) and (lastHelpPlayer < MAX_PLAYERS))
3317
 
        {
3318
 
                if(!_bHelpingMyself){
3319
 
                        messagePlayer(ALL_ALLIES, "helping " & getPlayerName(lastHelpPlayer) & " already", MAX_PROBABILITY);
3320
 
                }
3321
 
        }
3322
 
 
3323
 
        return FALSE;
3324
 
}
3325
 
 
3326
 
/* Start helping player */
3327
 
function void helpPlayer(int _playerToHelp, int _helpX, int _helpY)
3328
 
{
3329
 
        local int _tTravelTime;
3330
 
 
3331
 
        dbg("helping " & _playerToHelp, me);
3332
 
 
3333
 
        if(_DEBUG)
3334
 
                debug(me & ") helpPlayer: '" & _playerToHelp);
3335
 
 
3336
 
        /* Move scoutes to attackers */
3337
 
        groupAddGroup(attackGroup, scoutGroup);
3338
 
 
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);
3342
 
        }else{
3343
 
                _tTravelTime = (int)((float)(distBetweenTwoPoints(attackGroup.x, attackGroup.y, _helpX, _helpY) / 128 ) * 1.7);
3344
 
        }
3345
 
 
3346
 
        tHelp = gameTime / 10;
3347
 
        tHelpTimeout = (gameTime / 10) + BASE_DEFEND_DURATION + _tTravelTime;
3348
 
        lastHelpPlayer = _playerToHelp;
3349
 
        helpX = _helpX;
3350
 
        helpY = _helpY;
3351
 
 
3352
 
        /* Scouts and attackers go to help */
3353
 
        defendLocation(_helpX, _helpY, tHelpTimeout, BASE_DEFEND_RADIUS, (_playerToHelp == me));
3354
 
}
3355
 
 
3356
 
/* Returns a random affirmative responce */
3357
 
function string m_affirmative()
3358
 
{
3359
 
        local int _rnd;
3360
 
 
3361
 
        _rnd = random(4);
3362
 
        if(_rnd == 3)
3363
 
        {
3364
 
                return M_AFFIRMATIVE_ROGER;
3365
 
        }
3366
 
 
3367
 
        return M_AFFIRMATIVE_OK;
3368
 
}
3369
 
 
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)
3372
 
{
3373
 
        local int _structIndex;
3374
 
 
3375
 
        if(_x <= 0 or _y <= 0){
3376
 
                return FALSE;
3377
 
        }
3378
 
 
3379
 
        if(_ally < 0 or _ally >= MAX_PLAYERS){
3380
 
                return FALSE;
3381
 
        }
3382
 
 
3383
 
        _structIndex = 0;
3384
 
        while(_structIndex < numBaseStruct)
3385
 
        {
3386
 
                if(numStructsByStatInRange(baseStruct[_structIndex], _x, _y, (7 * 128), me, _ally) > 0 )
3387
 
                {
3388
 
                        return TRUE;
3389
 
                }
3390
 
 
3391
 
                _structIndex++;
3392
 
        }
3393
 
 
3394
 
        return FALSE;
3395
 
}
3396
 
 
3397
 
event manageAllyHelp(manageAllyHelpTr)
3398
 
{
3399
 
        if(helpingAlly())
3400
 
        {
3401
 
                if(canStopHelpingAlly())
3402
 
                {
3403
 
                        stopHelpingAlly();
3404
 
                }
3405
 
                //else
3406
 
                //{
3407
 
                //      /* See if all units we sent were killed */
3408
 
                //      if(not haveHelpers())
3409
 
                //      {
3410
 
                //              if(random(4) == 0)
3411
 
                //              {
3412
 
                //                      messagePlayer(lastHelpPlayer, M_HELPERS_KILLED);
3413
 
                //              }
3414
 
 
3415
 
                //              if(not attemptToHelp(lastHelpPlayer, helpX, helpY))
3416
 
                //              {
3417
 
                //                      dbg("NO UNITS, STOPPED HELPING", me);
3418
 
                //                      stopHelpingAlly();              //don't make sense to try again
3419
 
                //              }
3420
 
                //              else
3421
 
                //              {
3422
 
                //                      dbg("SENDING REINFORCEMENTS", me);
3423
 
                //              }
3424
 
                //      }
3425
 
                //}
3426
 
        }
3427
 
}
3428
 
 
3429
 
event everySecEv(everySec)
3430
 
{
3431
 
        /* Check if we were helping long enough */
3432
 
        if(helpingAlly())
3433
 
        {
3434
 
                if(helpAllyTimeout())
3435
 
                {
3436
 
                        stopHelpingAlly();
3437
 
                }
3438
 
        }
3439
 
 
3440
 
        if(defendingLocation())
3441
 
        {
3442
 
                if(defendLocationTimeout())
3443
 
                {
3444
 
                        stopDefendingLocation();
3445
 
                }
3446
 
        }
3447
 
}
3448
 
 
3449
 
/* Do we have any units we can send to help ally ? */
3450
 
function bool haveHelpers()
3451
 
{
3452
 
        if(attackGroup.members == 0){
3453
 
                return FALSE;
3454
 
        }
3455
 
 
3456
 
        return TRUE;
3457
 
}
3458
 
 
3459
 
function bool helpingAlly()
3460
 
{
3461
 
        if(lastHelpPlayer >= 0){
3462
 
                return TRUE;
3463
 
        }
3464
 
 
3465
 
        return FALSE;
3466
 
}
3467
 
 
3468
 
/* Returns true if we were helping long enough */
3469
 
function bool helpAllyTimeout()
3470
 
{
3471
 
        if(tHelpTimeout < (gameTime / 10) ){
3472
 
                return TRUE;
3473
 
        }
3474
 
 
3475
 
        return FALSE;
3476
 
}
3477
 
 
3478
 
function bool canStopHelpingAlly()
3479
 
{
3480
 
        if(lastHelpPlayer < 0)
3481
 
        {
3482
 
                ASSERT(FALSE, "canStopHelpingAlly: lastHelpPlayer < 0", me);
3483
 
                return TRUE;
3484
 
        }
3485
 
 
3486
 
        /* Were helping long enough or someone's backstabbing */
3487
 
        if(!friendlyPlayer(lastHelpPlayer)){
3488
 
                return TRUE;
3489
 
        }
3490
 
 
3491
 
        /* Nothing to defend anymore */
3492
 
        if(!allyBaseAtLoc(lastHelpPlayer, helpX, helpY)){
3493
 
                return TRUE;
3494
 
        }
3495
 
 
3496
 
        return FALSE;
3497
 
}
3498
 
 
3499
 
function void stopHelpingAlly()
3500
 
{
3501
 
        dbg("stopped helping", me);
3502
 
 
3503
 
        tHelp = -1;
3504
 
        tHelpTimeout = -1;
3505
 
        lastHelpPlayer = -1;
3506
 
        helpX = -1;
3507
 
        helpY = -1;
3508
 
 
3509
 
        stopDefendingLocation();
3510
 
}
3511
 
 
3512
 
/* Send a multiplayer message to an ally */
3513
 
function void messagePlayer(int _playerToMessage, string _message, int _probability)
3514
 
{
3515
 
        local int       _player;
3516
 
 
3517
 
        ASSERT(_playerToMessage >= -1 && _playerToMessage < MAX_PLAYERS,
3518
 
                "messagePlayer: player out of bounds: " & _playerToMessage, me);
3519
 
 
3520
 
        // throw the dice
3521
 
        if( random(MAX_PROBABILITY) >= _probability ){
3522
 
                return;
3523
 
        }
3524
 
 
3525
 
        _player = 0;
3526
 
        if(_playerToMessage == ALL_ALLIES)      //everyone
3527
 
        {
3528
 
                while(_player < MAX_PLAYERS)
3529
 
                {
3530
 
                        /* Send message (allies only)) */
3531
 
                        if(allianceExistsBetween(me, _player))
3532
 
                        {
3533
 
                                msg(_message, me, _player);
3534
 
                        }
3535
 
 
3536
 
                        _player++;
3537
 
                }
3538
 
        }
3539
 
        else    //a certain player
3540
 
        {
3541
 
                /* Send message (allies only)) */
3542
 
                if(allianceExistsBetween(me, _playerToMessage))
3543
 
                {
3544
 
                        msg(_message, me, _playerToMessage);
3545
 
                }
3546
 
        }
3547
 
}
3548
 
 
3549
 
function int numBitsSet(int _integer)
3550
 
{
3551
 
        local   int             _position,_result;
3552
 
 
3553
 
        _position = 0;
3554
 
        _result = 0;
3555
 
        while(_position < 8)
3556
 
        {
3557
 
                if(getBit(_integer, _position))
3558
 
                {
3559
 
                        _result++;
3560
 
                }
3561
 
                _position++;
3562
 
        }
3563
 
 
3564
 
        return _result;
3565
 
}
3566
 
 
3567
 
/* Send a multiplayer message, addressing some player(s) */
3568
 
function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message)
3569
 
{
3570
 
        local   int             _player,_totalAddressed,_curAddressed;
3571
 
        local   string  _adrMessage;
3572
 
 
3573
 
        _totalAddressed = numBitsSet(_playersToAddress);
3574
 
 
3575
 
        ASSERT(_totalAddressed > 0, "messagePlayerAddressed: no players addressed", me);
3576
 
 
3577
 
        _adrMessage = " ";
3578
 
 
3579
 
        _player = 0;
3580
 
        _curAddressed = 0;
3581
 
        while(_player < MAX_PLAYERS)
3582
 
        {
3583
 
                if(getBit(_playersToAddress, _player))
3584
 
                {
3585
 
                        _curAddressed++;
3586
 
 
3587
 
                        _adrMessage = _adrMessage & getPlayerName(_player);
3588
 
 
3589
 
                        //if(_totalAddressed == 1){     //one only
3590
 
                        //      _adrMessage = getPlayerName(_player);
3591
 
                        //}else
3592
 
 
3593
 
                        if(_totalAddressed > 1)
3594
 
                        {
3595
 
                                if(_curAddressed == _totalAddressed){           //end
3596
 
                                        _adrMessage = _adrMessage & " and " & getPlayerName(_player);
3597
 
                                }else{
3598
 
                                        _adrMessage = _adrMessage & ", " & getPlayerName(_player);
3599
 
                                }
3600
 
                        }
3601
 
 
3602
 
                }
3603
 
                _player++;
3604
 
        }
3605
 
 
3606
 
        _message = _adrMessage &  " " & _message;
3607
 
 
3608
 
        //Now send the message to all players addressed
3609
 
        messagePlayer(_playerToMessage, _message, MAX_PROBABILITY);
3610
 
}
3611
 
 
3612
 
/* Returns true if we can see our allies on the map */
3613
 
function bool canSeeAllies()
3614
 
{
3615
 
        local STRUCTURE _uplink;
3616
 
 
3617
 
        /* Can see allies when team mode is on */
3618
 
        if(multiPlayerAlliancesType == ALLIANCES_TEAMS)
3619
 
        {
3620
 
                return TRUE;
3621
 
        }
3622
 
 
3623
 
        /* Can see whole map if we have uplink */
3624
 
        _uplink = getStructure(uplink, me);
3625
 
        if(_uplink != NULLOBJECT)
3626
 
        {
3627
 
                /* Make sure finished building */
3628
 
                if(structureComplete(_uplink))
3629
 
                {
3630
 
                        return TRUE;
3631
 
                }
3632
 
        }
3633
 
 
3634
 
        return FALSE;
3635
 
}
3636
 
 
3637
 
function bool defendingOwnBase()
3638
 
{
3639
 
        if(helpingAlly() && lastHelpPlayer == me){
3640
 
                return TRUE;
3641
 
        }
3642
 
 
3643
 
        return FALSE;
3644
 
}
3645
 
 
3646
 
/* Call for help when our base is in danger */
3647
 
event watchBaseThreat(watchBaseThreatTr)
3648
 
{
3649
 
        /* See if we can stop defending */
3650
 
        if(defendingOwnBase())
3651
 
        {
3652
 
                if(numEnemiesInBase(FALSE) == 0)
3653
 
                {
3654
 
                        stopHelpingAlly();      //stop defending our own base
3655
 
 
3656
 
                        /* Let allies know we don't need their help anymore */
3657
 
                        messagePlayer(ALL_ALLIES, R_REPORT_SAFETY, MAX_PROBABILITY);
3658
 
                        exit;
3659
 
                }
3660
 
        }
3661
 
 
3662
 
        /* See if our base is in trouble and we need help */
3663
 
        if(baseInTrouble())
3664
 
        {
3665
 
                if(!defendingOwnBase()) //make sure not already defending the base
3666
 
                {
3667
 
                        if(_DEBUG)
3668
 
                                debug(me & ") watchBaseThreat: base in trouble");
3669
 
 
3670
 
                        dbg("watchBaseThreat: base in trouble", me);
3671
 
 
3672
 
                        /* Bring our forces back if needed */
3673
 
                        if(helpingAlly())
3674
 
                        {
3675
 
                                stopHelpingAlly();
3676
 
                        }
3677
 
 
3678
 
                        /* Defend my own base */
3679
 
                        helpPlayer(me, baseX, baseY);
3680
 
                }
3681
 
 
3682
 
                /* Request help once in a while */
3683
 
                requestHelp(baseX, baseY);
3684
 
                exit;
3685
 
        }
3686
 
}
3687
 
 
3688
 
function int numAlliesInBase(bool _bVtols)
3689
 
{
3690
 
        local int _numAllies;
3691
 
 
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;
3695
 
 
3696
 
        return _numAllies;
3697
 
}
3698
 
 
3699
 
function int numEnemiesInBase(bool _bVtols)
3700
 
{
3701
 
        local int _numEnemies;
3702
 
 
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;
3706
 
 
3707
 
        return _numEnemies;
3708
 
}
3709
 
 
3710
 
/* Returns true if our base is in trouble */
3711
 
function bool baseInTrouble()
3712
 
{
3713
 
        local int _enemyForce,_friendlyForce;
3714
 
 
3715
 
        _friendlyForce = numAlliesInBase(FALSE);
3716
 
        _enemyForce = numEnemiesInBase(FALSE);
3717
 
 
3718
 
        /* See if we are in trouble */
3719
 
        if((_enemyForce > 0) && (_enemyForce >= _friendlyForce)){
3720
 
                dbg("baseInTrouble: " & _enemyForce & " >= " & _friendlyForce, me);
3721
 
                return TRUE;
3722
 
        }
3723
 
 
3724
 
        return FALSE;
3725
 
}
3726
 
 
3727
 
/* Request help from allies */
3728
 
function void requestHelp(int _helpX, int _helpY)
3729
 
{
3730
 
        /* Don't do this too frequently */
3731
 
        if(tLastHelpRequest + HELP_REQUEST_INTERVAL > (gameTime / 10) ){
3732
 
                return;
3733
 
        }
3734
 
 
3735
 
        doRequestHelp(_helpX, _helpY);
3736
 
}
3737
 
 
3738
 
function void doRequestHelp(int _helpX, int _helpY)
3739
 
{
3740
 
        local int _ally;
3741
 
 
3742
 
        /* Remember when we requested help last time */
3743
 
        tLastHelpRequest = gameTime / 10;
3744
 
 
3745
 
        /* Drop beacon for all allies so they would know where to help */
3746
 
        _ally = 0;
3747
 
        while(_ally < MAX_PLAYERS)
3748
 
        {
3749
 
                if(allianceExistsBetween(me, _ally)){
3750
 
                        if(_DEBUG)
3751
 
                                debug(me & ") requestHelp: " & _ally);
3752
 
 
3753
 
                        dropBeacon(getPlayerName(me), _ally, me, _helpX, _helpY, 0);
3754
 
                }
3755
 
                _ally++;
3756
 
        }
3757
 
 
3758
 
        /* Now send message with help request */
3759
 
        messagePlayer(ALL_ALLIES, M_REQUEST_HELP, MAX_PROBABILITY);
3760
 
}
3761
 
 
3762
 
function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, int _defendRadius, bool _bMove)
3763
 
{
3764
 
        dbg("starting defending for " & _tDefendTimeout - (gameTime / 10) & " secs, with defend radius " & _defendRadius, me);
3765
 
 
3766
 
        ASSERT(_defendRadius >= TILE,
3767
 
                "defendLocation: defendRadius too low:" & _defendRadius, me);
3768
 
 
3769
 
        defendX = _defendX;
3770
 
        defendY = _defendY;
3771
 
 
3772
 
        defendRadius = _defendRadius;
3773
 
        tDefendStart = gameTime / 10;
3774
 
 
3775
 
        /* Should already include travel time */
3776
 
        tDefendTimeout = _tDefendTimeout;
3777
 
 
3778
 
        /* See if we have to move or scout */
3779
 
        defendMoveType = DORDER_SCOUT;
3780
 
        if(_bMove){
3781
 
                defendMoveType = DORDER_MOVE;
3782
 
        }
3783
 
 
3784
 
        /* Send attackers */
3785
 
        if(attackGroup.members > 0)
3786
 
        {
3787
 
                if(distBetweenTwoPoints(attackGroup.x, attackGroup.y, _defendX, _defendY) > _defendRadius)
3788
 
                {
3789
 
                        orderGroupLoc(attackGroup, defendMoveType, _defendX, _defendY);
3790
 
                }
3791
 
        }
3792
 
 
3793
 
        setEventTrigger(manageDefendLocationEv, manageDefendLocationTr);
3794
 
}
3795
 
 
3796
 
function void stopDefendingLocation()
3797
 
{
3798
 
        dbg("stopped defending location", me);
3799
 
 
3800
 
        defendX = -1;
3801
 
        defendY = -1;
3802
 
 
3803
 
        defendRadius = -1;
3804
 
 
3805
 
        tDefendStart = -1;
3806
 
        tDefendTimeout = -1;
3807
 
 
3808
 
        defendMoveType = -1;
3809
 
 
3810
 
        setEventTrigger(manageDefendLocationEv, inactive);
3811
 
 
3812
 
        orderGroupLoc(attackGroup, DORDER_SCOUT,baseX,baseY);
3813
 
}
3814
 
 
3815
 
function bool defendingLocation()
3816
 
{
3817
 
        if(defendX > 0 and defendY > 0){
3818
 
                return TRUE;
3819
 
        }
3820
 
 
3821
 
        return FALSE;
3822
 
}
3823
 
 
3824
 
event manageDefendLocationEv(inactive)
3825
 
{
3826
 
        local DROID _droid;
3827
 
 
3828
 
        dbg("manageDefendLocationEv", me);
3829
 
 
3830
 
        ASSERT(defendRadius >= TILE,
3831
 
                "manageDefendLocationEv: defendRadius too low:" & defendRadius, me);
3832
 
 
3833
 
        ASSERT(defendMoveType == DORDER_MOVE || defendMoveType == DORDER_SCOUT,
3834
 
                "manageDefendLocationEv: wrong move order:" & defendMoveType, me);
3835
 
 
3836
 
        ASSERT(defendX > 0 && defendY > 0,
3837
 
                "manageDefendLocationEv: x/y coordinates:" & defendX & "/" & defendY, me);
3838
 
 
3839
 
        if(!(defendX > 0 && defendY > 0)){
3840
 
                dbg("not defending???????", me);
3841
 
                exit;           //not defending?
3842
 
        }
3843
 
 
3844
 
        /* Collect attackers */
3845
 
        initIterateGroup(attackGroup);
3846
 
        _droid = iterateGroup(attackGroup);
3847
 
        while(_droid != NULLOBJECT)
3848
 
        {
3849
 
                if(distBetweenTwoPoints(_droid.x,_droid.y,defendX,defendY) > defendRadius)      //too far from defend location
3850
 
                {
3851
 
                        if(distBetweenTwoPoints(_droid.orderx,_droid.ordery,defendX,defendY) > defendRadius)    //not already on its way to the defend location
3852
 
                        {
3853
 
                                orderDroidLoc(_droid, defendMoveType, defendX, defendY);
3854
 
                        }
3855
 
                }
3856
 
                _droid = iterateGroup(attackGroup);
3857
 
        }
3858
 
}
3859
 
 
3860
 
function bool defendLocationTimeout()
3861
 
{
3862
 
        if(tDefendTimeout < (gameTime / 10) ){
3863
 
                return TRUE;
3864
 
        }
3865
 
 
3866
 
        return FALSE;
3867
 
}
3868
 
 
3869
 
/* Returns true if player in question is my ally or if it's me */
3870
 
function bool friendlyPlayer(int _playerToCheck)
3871
 
{
3872
 
        if(allianceExistsBetween(_playerToCheck, me) or (_playerToCheck == me)){
3873
 
                return TRUE;
3874
 
        }
3875
 
 
3876
 
        return FALSE;
3877
 
}
3878
 
 
3879
 
function bool insideBase(int _x, int _y)
3880
 
{
3881
 
        if(_x < minx){
3882
 
                return FALSE;
3883
 
        }
3884
 
 
3885
 
        if(_x > maxx){
3886
 
                return FALSE;
3887
 
        }
3888
 
 
3889
 
        if(_y < miny){
3890
 
                return FALSE;
3891
 
        }
3892
 
 
3893
 
        if(_y > maxy){
3894
 
                return FALSE;
3895
 
        }
3896
 
 
3897
 
        return TRUE;
3898
 
}
3899
 
 
3900
 
function FEATURE closestOil(int _x, int _y, bool _bAvoidThreat)
3901
 
{
3902
 
        local FEATURE   _oil,_closestOil;
3903
 
        local int               _bestDist,_newDist;
3904
 
 
3905
 
        _bestDist = 99999;
3906
 
        _closestOil = NULLOBJECT;
3907
 
 
3908
 
        initGetFeature(oilRes,me,me);
3909
 
        _oil = getFeatureB(me);
3910
 
        while(_oil != NULLOBJECT)
3911
 
        {
3912
 
                _newDist = distBetweenTwoPoints(_x, _y, _oil.x, _oil.y);
3913
 
 
3914
 
                if(_newDist < _bestDist)        //this one is closer
3915
 
                {
3916
 
                        if( !(_bAvoidThreat && threatInRange(me, _oil.x, _oil.y, OIL_THREAT_RANGE, FALSE)) )
3917
 
                        {
3918
 
                                _bestDist = _newDist;
3919
 
                                _closestOil = _oil;
3920
 
                        }
3921
 
                }
3922
 
                _oil = getFeatureB(me);
3923
 
        }
3924
 
 
3925
 
        return _closestOil;
3926
 
}
3927
 
 
3928
 
event keyPressed(CALL_KEY_PRESSED, ref count, ref count2)
3929
 
{
3930
 
        if(count == KEY_P and (count2 == KEY_RCTRL or count2 == KEY_LCTRL))
3931
 
        {
3932
 
                if(_DEBUG)
3933
 
                {
3934
 
                        addPower(1000, me);
3935
 
                        console("add power");
3936
 
                }
3937
 
        }
3938
 
}
3939
 
 
3940
 
event watchMenu(everySec)
3941
 
{
3942
 
        if(_DEBUG)
3943
 
        {
3944
 
                if(vtolGrAttackObj[0] == NULLOBJECT){
3945
 
                        setDebugMenuEntry("0 - " & vtolAttackGr[0].members, 0);
3946
 
                }else{
3947
 
                        setDebugMenuEntry("0 " & vtolAttackGr[0].members & " - " & (vtolGrAttackObj[0].x / TILE) & "-" & (vtolGrAttackObj[0].y / TILE), 0);
3948
 
                }
3949
 
 
3950
 
                if(vtolGrAttackObj[1] == NULLOBJECT){
3951
 
                        setDebugMenuEntry("1 - " & vtolAttackGr[1].members, 1);
3952
 
                }else{
3953
 
                        setDebugMenuEntry("1 " & vtolAttackGr[1].members & " - " & (vtolGrAttackObj[1].x / TILE) & "-" & (vtolGrAttackObj[1].y / TILE), 1);
3954
 
                }
3955
 
 
3956
 
                if(vtolGrAttackObj[2] == NULLOBJECT){
3957
 
                        setDebugMenuEntry("2 - " & vtolAttackGr[2].members, 2);
3958
 
                }else{
3959
 
                        setDebugMenuEntry("2 " & vtolAttackGr[2].members & " - " & (vtolGrAttackObj[2].x / TILE) & "-" & (vtolGrAttackObj[2].y / TILE), 2);
3960
 
                }
3961
 
 
3962
 
                if(vtolGrAttackObj[3] == NULLOBJECT){
3963
 
                        setDebugMenuEntry("3 - " & vtolAttackGr[3].members, 3);
3964
 
                }else{
3965
 
                        setDebugMenuEntry("3 " & vtolAttackGr[3].members & " - " & (vtolGrAttackObj[3].x / TILE) & "-" & (vtolGrAttackObj[3].y / TILE), 3);
3966
 
                }
3967
 
 
3968
 
                if(vtolGrAttackObj[4] == NULLOBJECT){
3969
 
                        setDebugMenuEntry("4 - " & vtolAttackGr[4].members, 4);
3970
 
                }else{
3971
 
                        setDebugMenuEntry("4 " & vtolAttackGr[4].members & " - " & (vtolGrAttackObj[4].x / TILE) & "-" & (vtolGrAttackObj[4].y / TILE), 4);
3972
 
                }
3973
 
 
3974
 
                if(vtolGrAttackObj[5] == NULLOBJECT){
3975
 
                        setDebugMenuEntry("5 - " & vtolAttackGr[5].members, 5);
3976
 
                }else{
3977
 
                        setDebugMenuEntry("5 " & vtolAttackGr[5].members & " - " & (vtolGrAttackObj[5].x / TILE) & "-" & (vtolGrAttackObj[5].y / TILE), 5);
3978
 
                }
3979
 
 
3980
 
        /*
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);*/
3990
 
        }
3991
 
}
3992
 
 
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)
3998
 
{
3999
 
        local   int             _numSameBuilding;
4000
 
        local   DROID   _truck;
4001
 
 
4002
 
        _numSameBuilding = 0;
4003
 
 
4004
 
        initIterateGroup(buildGroup);
4005
 
        _truck = iterateGroup(buildGroup);
4006
 
        while(_truck != NULLOBJECT)
4007
 
        {
4008
 
                if((_truck.order == DORDER_BUILD) or (_truck.order == DORDER_HELPBUILD) or (_truck.order == DORDER_LINEBUILD))
4009
 
                {
4010
 
                        if((_checkStat == NULLSTRUCTURESTAT) or (_truck.stat == _checkStat))    //Same struct type
4011
 
                        {
4012
 
                                //Within some range
4013
 
                                if((_x < 0) or (distBetweenTwoPoints(_x, _y, _truck.orderx , _truck.ordery) <= TILE))
4014
 
                                {
4015
 
                                        _numSameBuilding++;
4016
 
                                }
4017
 
                        }
4018
 
                }
4019
 
                _truck = iterateGroup(buildGroup);
4020
 
        }
4021
 
 
4022
 
        return _numSameBuilding;
4023
 
}
4024
 
 
4025
 
// returns number of droids in a certain group with the same order
4026
 
function int numGroupSameOrder(GROUP _group, int _orderIndex)
4027
 
{
4028
 
        local           int             _numDroids;
4029
 
        local           DROID           _droid;
4030
 
 
4031
 
        _numDroids = 0;
4032
 
 
4033
 
        initIterateGroup(_group);
4034
 
        _droid = iterateGroup(_group);
4035
 
        while(_droid != NULLOBJECT)
4036
 
        {
4037
 
                if(_droid.order == _orderIndex) //right order type
4038
 
                {
4039
 
                        _numDroids++;
4040
 
                }
4041
 
                _droid = iterateGroup(_group);
4042
 
        }
4043
 
 
4044
 
        return _numDroids;
4045
 
}
4046
 
 
4047
 
// Remember certain destroyed structures so we can rebuild them later
4048
 
event structureDestroyed(structureDestroyedTr)
4049
 
{
4050
 
        local   int     _count;
4051
 
 
4052
 
 
4053
 
        // add certain structures to the rebuild list
4054
 
        _count = 0;
4055
 
        while(_count < numRebuildStat[curTech])
4056
 
        {
4057
 
                if(structure.stat == rebuildStat[curTech][_count])
4058
 
                {
4059
 
                        if(countRebuildStruct < MAX_REBUILD_STRUCT)
4060
 
                        {
4061
 
                                rebuildStructX[countRebuildStruct] = structure.x;
4062
 
                                rebuildStructY[countRebuildStruct] = structure.y;
4063
 
                                rebuildStructStat[countRebuildStruct] = structure.stat;
4064
 
                                countRebuildStruct++;
4065
 
 
4066
 
                                dbg("remembered structure (" & countRebuildStruct & ") - " & structure.x & "/" & structure.y, me);
4067
 
 
4068
 
                                exit;
4069
 
                        }
4070
 
                }
4071
 
                _count++;
4072
 
        }
4073
 
}
4074
 
 
4075
 
// Rebuild structures that were destroyed
4076
 
event rebuildStructureEv(rebuildStructureTr)
4077
 
{
4078
 
        rebuildStructures();
4079
 
}
4080
 
 
4081
 
function void rebuildStructures()
4082
 
{
4083
 
        local   int                             _count,_threatRange,_x,_y;
4084
 
        local   DROID                   _truck;
4085
 
        local   STRUCTURESTAT   _stat;
4086
 
 
4087
 
        _threatRange = (TILE * 8);
4088
 
 
4089
 
        _count = 0;
4090
 
        while(_count < countRebuildStruct)
4091
 
        {
4092
 
                if(!threatInRange(me, rebuildStructX[_count], rebuildStructY[_count], _threatRange, FALSE))
4093
 
                {
4094
 
                        if(getTileStructure(_x / TILE, _y  / TILE) == NULLOBJECT)
4095
 
                        {
4096
 
                                _stat = rebuildStructStat[_count];
4097
 
                                _x = rebuildStructX[_count];
4098
 
                                _y = rebuildStructY[_count];
4099
 
 
4100
 
                                _truck = closestIdleTruck(_x, _y);
4101
 
 
4102
 
                                if(_truck != NULLOBJECT)
4103
 
                                {
4104
 
                                        if(numBuildSameBuilding(_stat, _x, _y) == 0)    //make sure no one is building already
4105
 
                                        {
4106
 
                                                buildOnExactLocation(_truck, _x, _y, _stat);
4107
 
                                        }
4108
 
                                }
4109
 
                        }
4110
 
                }
4111
 
                _count++;
4112
 
        }
4113
 
}
4114
 
 
4115
 
function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat)
4116
 
{
4117
 
        local   int     _newX,_newY;
4118
 
 
4119
 
        if(_truck == NULLOBJECT)
4120
 
        {
4121
 
                return;
4122
 
        }
4123
 
 
4124
 
        _newX = _x;
4125
 
        _newY = _y;
4126
 
 
4127
 
        if(pickStructLocationB(_stat, ref _newX, ref _newY, me, -1))
4128
 
        {
4129
 
                dbg("trying to rebuild on (" & _newX & "/" & _newY & ")", me);
4130
 
 
4131
 
                if((_x != _newX) or (_y != _newY))
4132
 
                {
4133
 
                        return;
4134
 
                }
4135
 
 
4136
 
                orderDroidStatsLoc(_truck, DORDER_BUILD, _stat, _x, _y);
4137
 
                //dbg("rebuilding structure after!! (" & _x & "/" & _y & ")", me);
4138
 
        }
4139
 
}
4140
 
 
4141
 
// Get idle truck closest to some location
4142
 
function DROID closestIdleTruck(int _x, int _y)
4143
 
{
4144
 
        local DROID _closestTruck, _tempTruck;
4145
 
        local int _closestDist, _tempDist;
4146
 
 
4147
 
        _closestTruck = NULLOBJECT;
4148
 
        _closestDist = 99999;
4149
 
 
4150
 
        initIterateGroup(buildGroup);
4151
 
        _tempTruck = iterateGroup(buildGroup);
4152
 
        while(_tempTruck != NULLOBJECT)
4153
 
        {
4154
 
                if((_tempTruck.order == DORDER_NONE) or (_tempTruck.order == DORDER_RTB))
4155
 
                {
4156
 
                        _tempDist = distBetweenTwoPoints(_x, _y, _tempTruck.x, _tempTruck.y);
4157
 
                        if(_tempDist < _closestDist)
4158
 
                        {
4159
 
                                _closestDist = _tempDist;
4160
 
                                _closestTruck = _tempTruck;
4161
 
                        }
4162
 
                }
4163
 
                _tempTruck = iterateGroup(buildGroup);
4164
 
        }
4165
 
 
4166
 
        return _closestTruck;
4167
 
}
4168
 
 
4169
 
event consoleEv(consoleTr)
4170
 
{
4171
 
        //turn on 'autogame'
4172
 
        if(message == "autogame on" && (sender == me))
4173
 
        {
4174
 
                if(debugModeEnabled())
4175
 
                {
4176
 
                        if(myResponsibility(me))
4177
 
                        {
4178
 
                                if(not bRunning)                //make sure current machine is responsible for this AI and it's not already active
4179
 
                                {
4180
 
                                        console(getPlayerName(me) & " is active");
4181
 
 
4182
 
                                        reassignAI();
4183
 
                                }
4184
 
                        }
4185
 
                }
4186
 
        }
4187
 
 
4188
 
        //turn off 'autogames'
4189
 
        if(message == "autogame off" && debugModeEnabled()  && (sender == me))
4190
 
        {
4191
 
                if(bRunning)            //make sure this AI is active
4192
 
                {
4193
 
                        console(getPlayerName(me) & " is deactivated");
4194
 
                        
4195
 
                        shutDownAI();
4196
 
                }
4197
 
        }
4198
 
 
4199
 
        if(message == "aidebug on")
4200
 
        {
4201
 
                console(getPlayerName(me) & " ai debug is on");
4202
 
                _DEBUG = TRUE;
4203
 
                dbgMsgOn(me, _DEBUG);
4204
 
        }
4205
 
        else if(message == "aidebug off")
4206
 
        {
4207
 
                console(getPlayerName(me) & " ai debug is off");
4208
 
                _DEBUG = FALSE;
4209
 
                dbgMsgOn(me, _DEBUG);
4210
 
        }
4211
 
}