home *** CD-ROM | disk | FTP | other *** search
/ PC Games.EXE 1999 January / pcgamesexe-1999-01.iso / Warzone / data1.cab / Program_Executable_Files / script / fastplay / fastdemo.slo next >
Text File  |  1998-10-27  |  35KB  |  1,153 lines

  1. //Generic script Version 1.0
  2. //For standard campaign maps
  3.  
  4. /* ********************    */
  5. /* Declared Variables     */
  6. /* ********************    */
  7.  
  8. /* Next Level stuff */
  9. public        LEVEL        NextLev;
  10.  
  11. /* CD track to play during mission */
  12. public        int        CDTrack;
  13.  
  14. /* Define Players/Enemies */
  15. public        int        numEnemies, enemy[2];
  16. private        int        targetCount[2], targetX[2][5], targetY[2][5];    //MAX targets = 4, need array one bigger!
  17. public        BOOL        allianceFlag;
  18.  
  19.  
  20. /* Starting Enemy Power */
  21. public        int        power[2];
  22.  
  23. /* Structure Limits */
  24. public        int        numStrucStats, strucLimit[5];
  25. public        STRUCTURESTAT    strucStat[5];
  26.  
  27. /* Initialisation */
  28. public        int        centreX, centreY;
  29. public        int        scrollX1, scrollX2, scrollY1, scrollY2;
  30. public        int        zoomLevel;
  31. public        int        numLZ, LZX[1], LZY[1];
  32. public        int        numTechs[2];
  33. public        RESEARCHSTAT    startTech[2][10];
  34.  
  35.  
  36. /* Briefings */
  37. public        int        numBriefs;
  38. public        INTMESSAGE    brief[2];
  39. public        INTMESSAGE    endMsg;
  40.  
  41. /* Victory Conditions */
  42. public        int        numVictory, victoryX[2], victoryY[2];
  43. public        BOOL        victory[2];
  44.  
  45. /* Objectives */
  46. public        int        numObjectives, objectiveX[3], objectiveY[3];
  47. public        INTMESSAGE    objective[3];
  48. private        BOOL        objectiveFlag[3];
  49. private        int        objectivesDone;
  50.  
  51. /* Artifacts */
  52. public        SOUND        artSnd1, artSnd2;
  53. public        int        numArt, victoryArt, artType[6], artVal[6], artX[6], artY[6];
  54. //public        INTMESSAGE    artMsg[6];
  55. public        RESEARCHSTAT    artComp[6];
  56. private        FEATURE        artID[6];
  57. private        int        artFlag[6];
  58. private        int        artCollected;
  59.  
  60. /* Enemy Base Blips */
  61. public        int        numBases, basePlayer[5];
  62. public        int        baseRegion[5], baseWav1[5], baseWav2[5];
  63. public        INTMESSAGE    baseMsg[5];
  64. private        int        baseFlag[5];
  65. private        int        basesDead;
  66.  
  67.  
  68. /* Groups */
  69. //these can be for any player!
  70. public        int        numGroups;
  71. public        int        grpType[10], grpPlayer[10], grpRegion[10], grpTimeGo[10], grpRegionGo[10], grpWhoGo[10];
  72. public        int        grpMorale[10], grpLeadership[10], grpRetreatXY[10], grpIdealSize[10];
  73. public        int        grpPosStart[10], grpPosMin[10], grpPosMax[10], grpPosStep[10], grpPosType[10];
  74. public        int        grpFactory[10];
  75. private        BOOL        grpFlagGo[10];        //keep track of already triggered groups
  76. private        GROUP        grpGroup[10], grpReinforce[10];        //the actual groups are stored in this, based on region.
  77. private        int        grpPosCurrent[10];    //keep track of current waypoint
  78. private        BOOL        grpBusy[10];        //keep track of already ordered
  79. private        int        timeGroup;        //keeps track of time since started level, for triggering groups
  80.  
  81. /* Factories */
  82. //these can be for any player!
  83. public        int        numFactories;
  84. public        int        factID[10], factAssXY[10], factTimeGo[10];
  85. public        int        factRegionGo[10], factTempMin[10], factTempMax[10];
  86. private        BOOL        factFlagGo[10];    //stores whether producing or not
  87.  
  88. /* LISTS OF STUFF (INDEXED BY ARRAY) */
  89.  
  90. public        STRUCTURE    structures[10];
  91. public        FEATURE        features[10];
  92. public        DROID        droids[10];
  93. public        TEMPLATE    templates[20];
  94. public        int        coordsX[10], coordsY[10];
  95. public        int        regionsX1[20], regionsY1[20], regionsX2[20], regionsY2[20];
  96. public        int        sectorsX1[20], sectorsY1[20], sectorsX2[20], sectorsY2[20];
  97.  
  98.  
  99.  
  100. /* 'Globals' */
  101. public        int        player;
  102. public        FEATURESTAT    crate;
  103. public        int        artRange, objectiveRange;    //artifact pickup/obj blip removal
  104. public        int        wayRange, targetRange;        //range to waypoints/range for targets
  105. public        int        targetMax;                //maximum number of targets (4)
  106. public        SOUND        wonSnd;                //mission won
  107. public        SOUND        lostSnd;                //mission lost
  108. public        SOUND        attackSnd1;                //Base Under Attack Sound
  109. public        SOUND        baseSnd[5];            //base detected/dead
  110.  
  111.  
  112. /* General variables */
  113. private        int        count, count2;                //for while loops
  114. private        DROID        testDroid, newDroid;
  115. private        STRUCTURE    newDroidFactory;            //new droid built
  116. private        int        countBriefs, temp, temp1, temp2, tempX, tempY;
  117. private        STRUCTURE    hitStruc;                //Base Under Attack
  118. private        BASEOBJ    attackerObj;            //Base Under Attack
  119. private        int        t;                    //Base Under Attack time delay for next warning
  120. private        int        enemyCount;                //for enemy base attack stuff!
  121.  
  122. /* ********************    */
  123. /* Triggers         */
  124. /* ********************    */
  125. trigger winTrig(artCollected == victoryArt, 25);
  126. trigger lostTrig(not anyDroidsLeft(player), 25);
  127. trigger objTrig        (every, 15);
  128. trigger artTrig        (every, 10);
  129. trigger baseTrig        (every, 15);
  130. trigger nextLevTrig    (every, 20);
  131. trigger gameLostTrig    (every, 20);
  132. trigger checkGroupsTrig    (every, 35);    //every 4 seconds
  133. trigger wayGroupsTrig    (every, 100);    //every 4 seconds
  134. trigger sectorGroupsTrig(every, 75);    //every 8 seconds
  135. trigger attackGroupsTrig(every, 83);    //every 8 seconds
  136. trigger targetGroupsTrig(every, 43);    //every 4 seconds
  137. trigger regionGroupsTrig(every, 11);    //every second
  138. trigger timeGroupsTrig    (every, 100);    //every 10 seconds
  139. trigger updateEnemyTrig    (every, 21);    //every 2 seconds
  140. trigger factoryProdTrig    (every, 450);    //every 45 seconds
  141. trigger droidBuiltTrig    (wait, 1);        //very quickly
  142.  
  143. /* ********************    */
  144. /* Events         */
  145. /* ********************    */
  146.  
  147. /* Declared Events */
  148. event wonYetEvnt;
  149. event lostYetEvnt;
  150. event timeUp;
  151.  
  152. /* Initialisation */
  153. event    start(CALL_GAMEINIT)
  154. {
  155. //centre view
  156.     centreViewPos(centreX, centreY);
  157. //set alliances
  158.     if (allianceFlag and numEnemies > 1)
  159.     {
  160.         count = 0;
  161.         while (count < numEnemies)
  162.         {
  163.             count2 = 0;
  164.             while (count2 < numEnemies)
  165.             {
  166.                 if (count != count2)
  167.                 {
  168.                     createAlliance(enemy[count], enemy[count2]);
  169.                 }
  170.                 count2 = count2 + 1;
  171.             }
  172.             count = count + 1;
  173.         }
  174.     }
  175.     
  176. //set scroll limits
  177.     setScrollParams(scrollX1, scrollY1, scrollX2, scrollY2);
  178.  
  179. //set radar zoom level
  180.     setRadarZoom(zoomLevel);
  181.  
  182. //set LZ and no go areas
  183.     initAllNoGoAreas();
  184.     count = 0;
  185.     while (count < numLZ)
  186.     {
  187.         setNoGoArea(LZX[count] - 1, LZY[count] - 1, LZX[count] + 1, LZY[count] + 1, count);
  188.         count = count + 1;
  189.     }
  190.  
  191. //set structure limits
  192.     count = 0;
  193.     while (count < numStrucStats)
  194.     {
  195.         setStructureLimits (strucStat[count], strucLimit[count], player);
  196.         enableStructure(strucStat[count], player);
  197.         count = count + 1;
  198.     }
  199.  
  200. //set power levels
  201.     count = 0;
  202.     while (count < numEnemies)
  203.     {
  204.     //also set technology for each enemy
  205.         count2 = 0;
  206.         while (count2 < numTechs[count])
  207.         {
  208.             completeResearch(startTech[count][count2], enemy[count]);
  209.             count2 = count2 + 1;
  210.         }
  211.         setPowerLevel(power[count], enemy[count]);
  212.         count = count + 1;
  213.     }
  214.  
  215. //show player start objectives
  216.     count = 0;
  217.     while (count < numObjectives)
  218.     {
  219.         addMessage(objective[count], PROX_MSG, player, false);
  220.         count = count + 1;
  221.     }
  222.  
  223. //Setup Artifacts already on map (NOT TESTED YET!)
  224. //setting flags incorrectly in VLO could break game!
  225.     count = 0;
  226.     while (count < numArt)
  227.     {
  228.         if (artType[count] >= 4)    //deal with no object to get artifact from
  229.         {                    //eg for extra topics given at the end?
  230.             artFlag[count] = 4;
  231.         }
  232.         if (artType[count] == 0)    //deal with artifact already on map
  233.         {
  234.             artID[count] = features[artVal[count]];
  235.             artFlag[count] = 1;
  236.         }
  237.         count = count + 1;
  238.     }
  239.  
  240. //setup groups
  241.     count = 0;
  242.     while (count < numGroups)
  243.     {
  244.         groupAddArea(grpGroup[count], grpPlayer[count], regionsX1[grpRegion[count]], regionsY1[grpRegion[count]],
  245.             regionsX2[grpRegion[count]], regionsY2[grpRegion[count]]);
  246.         grpPosCurrent[count] = grpPosStart[count];
  247.         //set morale levels
  248.         if (grpMorale[count] >= 0)
  249.         {
  250. /*
  251.         //set repair for now (run away not good enough!?)
  252.             setGroupSecondary(grpGroup[count], DSO_REPAIR_LEVEL, DSS_REPLEV_HIGH);
  253. */
  254.             //to get hill attackers to work properly
  255.             //setGroupSecondary(grpGroup[count], DSO_ATTACK_RANGE, DSS_ARANGE_LONG);
  256.  
  257.             setGroupRetreatForce(grpGroup[count], grpMorale[count]);
  258.             setGroupRetreatLeadership(grpGroup[count], grpLeadership[count]);
  259.             if (grpType[count] < 2)        //use coords for patrol/ambush/defence
  260.             {
  261.                 setGroupRetreatPoint(grpGroup[count], coordsX[grpRetreatXY[count]], coordsY[grpRetreatXY[count]]);
  262.             }
  263.             else                    //use sectors for scout/attack
  264.             {
  265.                 temp = grpRetreatXY[count];
  266.                 //order scout/attack forces to random position in this sector
  267.                 tempX = sectorsX1[temp] + random(sectorsX2[temp] - sectorsX1[temp]);
  268.                 tempY = sectorsY1[temp] + random(sectorsY2[temp] - sectorsY1[temp]);
  269.                 setGroupRetreatPoint(grpGroup[count], tempX, tempY);
  270.             }
  271.         }
  272.         //set time = 0 groups going
  273.         if (grpTimeGo[count] == timeGroup)
  274.         {
  275.             grpFlagGo[count] = TRUE;
  276.             if (grpType[count] < 2)        //use coords for patrol/ambush/defence
  277.             {
  278.                 if (grpPosStart[count] >= 0)    //cope with no start position defined
  279.                 {
  280.                     orderGroupLoc(grpGroup[count], DORDER_SCOUT, coordsX[grpPosStart[count]], coordsY[grpPosStart[count]]);
  281.                 }
  282.             }
  283.             else
  284.             {
  285.                 temp = grpPosCurrent[count];
  286.                 //order scout/attack forces to random position in this sector
  287.                 tempX = sectorsX1[temp] + random(sectorsX2[temp] - sectorsX1[temp]);
  288.                 tempY = sectorsY1[temp] + random(sectorsY2[temp] - sectorsY1[temp]);
  289.                 orderGroupLoc(grpGroup[count], DORDER_MOVE, tempX, tempY);
  290.             }
  291.         }
  292.         count = count + 1;
  293.     }
  294.     //set time = 0 factories going
  295.     count = 0;
  296.     while (count < numFactories)
  297.     {
  298.         //set assembly points, if desired
  299.         if (factAssXY[count] != -1)
  300.         {
  301.             setAssemblyPoint (structures[factID[count]], coordsX[factAssXY[count]], coordsY[factAssXY[count]]);
  302.         }
  303.         if ((factTimeGo[count] == timeGroup) and (not factFlagGo[count]))
  304.         {
  305.             factFlagGo[count] = TRUE;    //set factory to produce
  306.         }
  307.         count = count + 1;
  308.     }
  309.  
  310.  
  311. //play mission brief(s)
  312.     if (numBriefs > 0)
  313.     {
  314.         addMessage(brief[0], MISS_MSG, 0, true);
  315.         countBriefs = 1;
  316.     }
  317. }
  318.  
  319. event    briefings(CALL_VIDEO_QUIT)        //need to rework this better!!
  320. {
  321.     if (countBriefs >= numBriefs)    //last briefing?
  322.     {
  323.         //CD play disabled for Demo
  324.         //playCDAudio(CDTrack);
  325.         setEventTrigger(briefings, inactive);
  326.     }
  327.     if (countBriefs < numBriefs)        //remove last, add next?
  328.     {
  329.         removeMessage(brief[countBriefs - 1], MISS_MSG, 0);
  330.         addMessage(brief[countBriefs], MISS_MSG, 0, true);
  331.         countBriefs = countBriefs + 1;
  332.     }
  333. }
  334.  
  335.  
  336. /* Base Under Attack */
  337. event baseHit(CALL_STRUCT_ATTACKED, selectedPlayer, ref hitStruc, ref attackerObj)
  338. {
  339.     if (t>=10)
  340.     {
  341.         t=0;
  342.         playSound(attackSnd1, player);
  343.     }
  344. }
  345.  
  346. event everySec(every, 20)    //update time delay before told again (about 20 seconds)
  347. {
  348.     t=t+1;
  349. }
  350.  
  351.  
  352. /* Remove Objective Blips */
  353. event removeObjectives(objTrig)
  354. {
  355.     if (objectivesDone == numObjectives)    //all blips gone?
  356.     {
  357.         setEventTrigger(removeObjectives, inactive);
  358.     }
  359.     else
  360.     {
  361.         count = 0;
  362.         while (count < numObjectives)
  363.         {
  364.             if ((not objectiveFlag[count]) and
  365.                 (droidInRange(player, objectiveX[count], objectiveY[count], objectiveRange)))
  366.             {
  367.                 objectiveFlag[count] = TRUE;
  368.                 objectivesDone = objectivesDone + 1;
  369.                 removeMessage(objective[count], PROX_MSG, player);
  370.             }
  371.             count = count + 1;
  372.         }
  373.     }
  374. }
  375.  
  376.  
  377. /* Artifacts */
  378. //This works for artifacts from STRUCTURES, FEATURES or DROIDS as well as crates already on map!
  379. //tested for STRUCTURES, FEATURES, DROIDS and starting CRATES
  380. event artLoop(artTrig)        //update artifact list
  381. {
  382.     if (artCollected == numArt)    //all artifacts collected?
  383.     {
  384.         setEventTrigger(artLoop, inactive);
  385.     }
  386.     else
  387.     {
  388.         count = 0;
  389.         while (count < numArt)
  390.         {
  391.             if (artFlag[count] == 0)
  392.             {
  393.                 temp = 0;
  394.                 //might be a better way to do this check?
  395.                 if (artType[count] == 1)
  396.                 {
  397.                     if (structures[artVal[count]] == NULLOBJECT)    //from dead structure
  398.                     {
  399.                         temp = 1;
  400.                     }
  401.                 }
  402.                 if (artType[count] == 2)
  403.                 {
  404.                     if (features[artVal[count]] == NULLOBJECT)    //from dead feature
  405.                     {
  406.                         temp = 1;
  407.                     }
  408.                 }
  409.                 if (artType[count] == 3)
  410.                 {
  411.                     if (droids[artVal[count]] == NULLOBJECT)    //from dead droid
  412.                     {
  413.                         temp = 1;
  414.                     }
  415.                 }
  416.                 if (temp == 1)        //OK to place crate?
  417.                 {
  418.                     //place artifact crate, and allow check for prox
  419.                     artID[count] = addFeature(crate, artX[count], artY[count]);
  420.                     artFlag[count] = 1;
  421.                 }
  422.             }
  423.             if (artFlag[count] == 1)
  424.             {
  425. /* simple hack, now don't need message!
  426.                 if (droidHasSeen(artID[count], player))
  427.                 {
  428.                     addMessage(artMsg[count], PROX_MSG, player, false);
  429.                     playSound(artSnd1, player);
  430. */
  431.                     artFlag[count] = 2;
  432.                 //}
  433.             }
  434.             if (artFlag[count] == 2)
  435.             {
  436.                 if (droidInRange(player, artX[count], artY[count], artRange))
  437.                 {
  438.                     artCollected = artCollected + 1;
  439.                     artFlag[count] = 3;
  440.                     destroyFeature(artID[count]);
  441.                     playSound(artSnd2, player);
  442.                     //removeMessage(artMsg[count], PROX_MSG, player);
  443.                     enableResearch(artComp[count], player);
  444.                 }
  445.             }
  446.             if (artType[count] == 3)
  447.             {
  448.                 if (droids[artVal[count]] != NULLOBJECT)
  449.                 {
  450.                     //keep track of droid position for crate when it dies
  451.                     artX[count] = droids[artVal[count]].x;
  452.                     artY[count] = droids[artVal[count]].y;
  453.                 }
  454.             }
  455.             count = count + 1;
  456.         }
  457.     }    
  458.  
  459. }
  460.  
  461. /* Enemy Base Blips */
  462. event baseLoop(baseTrig)        //update base blips
  463. {
  464.     if (basesDead == numBases)    //all bases gone?
  465.     {
  466.         setEventTrigger(baseLoop, inactive);
  467.     }
  468.     else
  469.     {
  470.         count = 0;
  471.         while (count < numBases)
  472.         {
  473.             if (baseFlag[count] == 0)
  474.             {
  475.                 if (seenStructInArea(player, basePlayer[count], FALSE,
  476.                     regionsX1[baseRegion[count]], regionsY1[baseRegion[count]],
  477.                     regionsX2[baseRegion[count]], regionsY2[baseRegion[count]]))
  478.                 {
  479.                     addMessage(baseMsg[count], PROX_MSG, player, false);
  480.                     if (baseWav1[count] >= 0)
  481.                     {
  482.                         playSound(baseSnd[baseWav1[count]], player);
  483.                     }
  484.                     baseFlag[count] = 1;
  485.                 }
  486.             }
  487.             if (baseFlag[count] == 1)
  488.             {
  489.                 if (numStructsButNotWallsInArea(basePlayer[count],
  490.                     regionsX1[baseRegion[count]], regionsY1[baseRegion[count]],
  491.                     regionsX2[baseRegion[count]], regionsY2[baseRegion[count]])== 0)
  492.                 {
  493.                     basesDead = basesDead + 1;
  494.                     baseFlag[count] = 2;
  495.                     if (baseWav2[count] >= 0)
  496.                     {
  497.                         playSound(baseSnd[baseWav2[count]], player);
  498.                     }
  499.                     removeMessage(baseMsg[count], PROX_MSG, player);
  500.                     killStructsInArea(basePlayer[count], REF_WALL,         //remove walls and building features in base
  501.                         regionsX1[baseRegion[count]], regionsY1[baseRegion[count]],
  502.                         regionsX2[baseRegion[count]], regionsY2[baseRegion[count]],
  503.                         TRUE, TRUE);
  504.                     killStructsInArea(basePlayer[count], REF_WALLCORNER,    //remove corner walls in base
  505.                         regionsX1[baseRegion[count]], regionsY1[baseRegion[count]],
  506.                         regionsX2[baseRegion[count]], regionsY2[baseRegion[count]],
  507.                         TRUE, FALSE);
  508.  
  509.                 }
  510.             }
  511.             count = count + 1;
  512.         }
  513.     }    
  514. }
  515.  
  516.  
  517. /* Events: Win or Lose */
  518. event nextLevEvnt(inactive)        //assumes victory already checked
  519. {
  520.     flushConsoleMessages();
  521.     playSound(wonSnd,0);
  522.     pause(20);
  523.     // give all research
  524.     count = 0;
  525.     while (count < numArt)
  526.     {
  527.         enableResearch(artComp[count], 0);
  528.         count = count +1;
  529.     }
  530.     // *required for sub missions*
  531.     //setLandingZone(10, 51, 12, 53);
  532.     // *no longer need to remove briefings?*
  533.     //removeMessage(MissionBrief, MISS_MSG, player);
  534.     startMission(CAMP_EXPAND, NextLev);
  535.     //End game here for now! (don't try next mission)
  536.     //gameOver(true);
  537.  
  538.     setEventTrigger(nextLevEvnt, inactive);
  539. }
  540.  
  541. //skip to end of level
  542. event cheatEvnt(CALL_MISSION_START)    //cheat button ctrl M
  543. {
  544.     setEventTrigger(nextLevEvnt, nextLevTrig);
  545.     setEventTrigger(cheatEvnt, inactive);
  546. }
  547. event gameLost(inactive)
  548. {
  549.     addMessage(endMsg, MISS_MSG, 0, true);
  550.     gameOver(false);
  551.     setEventTrigger(gameLost, inactive);
  552. }
  553.  
  554. event lostYetEvnt(lostTrig)    //triggered on (not anyDroidsLeft(player))
  555. {
  556.     if (not anyStructButWallsLeft(player))
  557.     {
  558.         setEventTrigger(wonYetEvnt,inactive);
  559.         setEventTrigger(timeUp, inactive);
  560.         setEventTrigger(gameLost, gameLostTrig);    //waits 2 seconds before ending
  561.         //playSound(lostSnd,0);
  562.         setEventTrigger(lostYetEvnt, inactive);
  563.     }
  564. }
  565.  
  566. //out of time?
  567. event timeUp(CALL_MISSION_TIME)
  568. {
  569.     setEventTrigger(wonYetEvnt,inactive);
  570.     setEventTrigger(lostYetEvnt,inactive);
  571.     playSound(lostSnd,0);    //may want different sound, eg "Out of Time"
  572.     setEventTrigger(gameLost, gameLostTrig);    //waits 2 seconds before ending
  573.     setEventTrigger(timeUp, inactive);
  574. }
  575.  
  576. event wonYetEvnt(winTrig)     //triggered on (artCollected == victoryArt)
  577. {
  578.     temp2 = 0;    //stores number of conditions met
  579. //needs to check various victory conditions setup in VLO
  580.  
  581. //check all enemy vehicles and structures destroyed
  582.     if (victory[0])
  583.     {
  584.         count = 0;
  585.         temp = 0;
  586.         while (count < numEnemies)
  587.         {
  588.             if ((not anyDroidsLeft(enemy[count]))
  589.                 and (not anyStructButWallsLeft(enemy[count])))
  590.             {
  591.                 temp = temp + 1;
  592.             }
  593.             count = count + 1;
  594.         }
  595.         if (temp == numEnemies)
  596.         {
  597.             temp2 = temp2 + 1;
  598.         }
  599.     }
  600.  
  601. //check all player vehicles in specific area (eg LZ)
  602.     if (victory[1])
  603.     {
  604.         temp = numDroidsInArea(player, 0, 0, scrollX1 * 128, scrollY1 * 128);
  605.         if (temp == numDroidsInArea(player, victoryX[0], victoryY[0], victoryX[1], victoryY[1]))
  606.         {
  607.             if (temp != 0)
  608.             {
  609.                 temp2 = temp2 + 1;
  610.             }
  611.         }
  612.     }
  613.  
  614.  
  615.     if (temp2 == numVictory)    //victory reached?
  616.     {
  617.         setEventTrigger(lostYetEvnt, inactive);
  618.         setEventTrigger(timeUp, inactive);
  619.         setEventTrigger(nextLevEvnt, nextLevTrig);
  620.         setEventTrigger(wonYetEvnt, inactive);
  621.     }
  622. }
  623.  
  624. /* Enemy AI */
  625.  
  626. event wayGroups(wayGroupsTrig)
  627. {
  628.     count = 0;
  629.     while (count < numGroups)
  630.     {
  631.         //update groups position
  632.         if ((grpFlagGo[count]) and  (grpType[count] < 2) and (grpPosStart[count] >= 0)) //been triggered and ambush/patrol/defence?
  633.         {
  634.             //simple predefined waypoints
  635.             //has the group got to waypoint or are they mainly idle?
  636. /*
  637.             if ((grpGroup[count].members > 0) and (
  638.                 (grpGroup[count].x >= coordsX[grpPosCurrent[count]] - wayRange) and
  639.                 (grpGroup[count].y >= coordsY[grpPosCurrent[count]] - wayRange) and
  640.                 (grpGroup[count].x <= coordsX[grpPosCurrent[count]] + wayRange) and
  641.                 (grpGroup[count].y <= coordsY[grpPosCurrent[count]] + wayRange)) or
  642.                 (idleGroup(grpGroup[count]) >= grpGroup[count].members/2))
  643. */
  644.             if (grpGroup[count].members > 0)    //idle stuff taken out FOR DEMO
  645.             {
  646.                 grpBusy[count] = FALSE;            //no longer 'busy'
  647.                 temp = grpPosCurrent[count];        //store for checking difference later
  648.                 if (grpPosType[count] == 3)        //random choice
  649.                 {
  650.                     grpPosCurrent[count] = grpPosMin[count] + grpPosStep[count] * random(grpPosMax[count] - grpPosMin[count]);
  651.                 }
  652.                 else
  653.                 {
  654.                     grpPosCurrent[count] = grpPosCurrent[count] + grpPosStep[count];    //get next waypoint
  655.                 }
  656.                 if ((grpPosCurrent[count] > grpPosMax[count]) or (grpPosCurrent[count] < grpPosMin[count]))
  657.                 {
  658.                     grpPosCurrent[count] = grpPosCurrent[count] - grpPosStep[count];    //stop at last one
  659.                     if (grpPosType[count] == 1)        //loop
  660.                     {
  661.                         if (grpPosStep[count] > 0)        //+ve loop
  662.                         {
  663.                             grpPosCurrent[count] = grpPosMin[count];
  664.                         }
  665.                         else                //-ve loop
  666.                         {
  667.                             grpPosCurrent[count] = grpPosMax[count];
  668.                         }
  669.                     }
  670.                     if (grpPosType[count] == 2)        //ping pong
  671.                     {
  672.                         grpPosStep[count] = - grpPosStep[count];
  673.                         grpPosCurrent[count] = grpPosCurrent[count] + grpPosStep[count];
  674.                     }
  675.                 }
  676.                 if (grpPosCurrent[count] != temp)    //don't order again if already there!
  677.                 {
  678.                     //orderGroupLoc(grpGroup[count], DORDER_SCOUT, coordsX[grpPosCurrent[count]], coordsY[grpPosCurrent[count]]);
  679.                     orderGroupLoc(grpGroup[count], DORDER_MOVE, coordsX[grpPosCurrent[count]], coordsY[grpPosCurrent[count]]);
  680.                 }
  681.             }
  682.         }
  683.         count = count + 1;
  684.     }
  685. }
  686.  
  687.  
  688. /* SCOUTS AND TARGET FINDING DISABLED FOR DEMO
  689. event checkGroups(checkGroupsTrig)
  690. {
  691.     count = 0;
  692.     while (count < numGroups)
  693.     {
  694.         initIterateGroup(grpGroup[count]);
  695.         count2 = 0;
  696.         while (count2 < grpGroup[count].members)
  697.         {
  698.         //check for morale failed, and make retreat fully
  699.             testDroid = iterateGroup(grpGroup[count]);
  700.             if (testDroid.order == DORDER_RUN)
  701.             {
  702.                 if (grpType[count] >= 2)    //scout and attack type uses sectors
  703.                 {
  704.                     grpPosCurrent[count] = grpRetreatXY[count];    //flag retreat sector as current?
  705.                     temp = grpRetreatXY[count];
  706.                     //order scout forces to random position in this sector
  707.                     tempX = sectorsX1[temp] + random(sectorsX2[temp] - sectorsX1[temp]);
  708.                     tempY = sectorsY1[temp] + random(sectorsY2[temp] - sectorsY1[temp]);
  709.                     orderGroupLoc(grpGroup[count], DORDER_MOVE, tempX, tempY);
  710.                 }
  711.                 else
  712.                 {
  713.                     orderGroupLoc(grpGroup[count], DORDER_MOVE, coordsX[grpRetreatXY[count]], coordsY[grpRetreatXY[count]]);
  714.                 }
  715.                 grpBusy[count] = TRUE;            //mark busy (will become idle when at retreat point)
  716.                 count2 = grpGroup[count].members;    //exit loop
  717.             }
  718.             count2 = count2 + 1;
  719.         }
  720.         count = count + 1;
  721.     }
  722. }
  723.  
  724.  
  725. // not finished yet! Now includes attack groups as well as scout groups
  726. event sectorGroups(sectorGroupsTrig)
  727. {
  728.     count = 0;
  729.     while (count < numGroups)
  730.     {
  731.         if ((grpFlagGo[count]) and (grpType[count] >= 2) and (grpGroup[count].members != 0)        //set going and scout/attack type only
  732.                 and (idleGroup(grpGroup[count]) > (grpGroup[count].members / 2)))            //also not busy!    
  733.         {
  734.             grpBusy[count] = FALSE;            //no longer 'busy'?
  735. //attack group stuff
  736.             temp1 = 0;                    //just in case don't find an enemy match
  737.             if ((allianceFlag))    // and (random(numEnemies + 1) < 1))
  738.             {
  739.                 temp1 = random(numEnemies);    //allow allies targets as well!
  740.             }
  741.             else
  742.             {
  743.                 count2 = 0;
  744.                 while (count2 < numEnemies)
  745.                 {
  746.                     if (grpPlayer[count] == enemy[count2])
  747.                     {
  748.                         temp1 = count2;    //this should be enemy index number!
  749.                     }
  750.                     count2 = count2 + 1;
  751.                 }
  752.             }
  753.             if ((grpType[count] == 3) and (targetCount[temp1] > 0))        //any targets for attack groups
  754.             {
  755.                 temp2 = random(targetCount[temp1]);
  756.                 orderGroupLoc(grpGroup[count], DORDER_SCOUT, targetX[temp1][temp2], targetY[temp1][temp2]);
  757.             }
  758.             else                 //otherwise next sector
  759.             {
  760. //scout/next sector stuff
  761.                 temp = grpPosCurrent[count];    //current scout sector
  762.                 //10% chance of scouting past an occupied sector (even if valid targets exist there!)
  763.                 //put in temp1 and temp2 for legibility!
  764.                 temp1 = numStructsButNotWallsInArea(player, sectorsX1[temp], sectorsY1[temp], sectorsX2[temp], sectorsY2[temp]);
  765.                 temp2 = numDroidsInArea(player, sectorsX1[temp], sectorsY1[temp], sectorsX2[temp], sectorsY2[temp]);
  766.                 //next sector if clear of droids and structures or 10% chance
  767.                 if ((random(100) < 10) or ((temp1 == 0) and (temp2 ==0)))
  768.                 {
  769.                     //sector clear so use as a retreat point 50% chance
  770.                     if (random(100) < 50)
  771.                     {
  772.                         grpRetreatXY[count] = grpPosCurrent[count];
  773.                     }
  774.                     //get new sector (like wayGroups above!)
  775.                     if (grpPosType[count] == 3)        //random choice
  776.                     {
  777.                         grpPosCurrent[count] = grpPosMin[count] + grpPosStep[count] * random(grpPosMax[count] - grpPosMin[count]);
  778.                     }
  779.                     else
  780.                     {
  781.                         grpPosCurrent[count] = grpPosCurrent[count] + grpPosStep[count];    //get next waypoint
  782.                     }
  783.                     if ((grpPosCurrent[count] > grpPosMax[count]) or (grpPosCurrent[count] < grpPosMin[count]))
  784.                     {
  785.                         grpPosCurrent[count] = grpPosCurrent[count] - grpPosStep[count];    //stop at last one
  786.                         if (grpPosType[count] == 1)        //loop
  787.                         {
  788.                             if (grpPosStep[count] > 0)    //+ve loop
  789.                             {
  790.                                 grpPosCurrent[count] = grpPosMin[count];
  791.                             }
  792.                             else                    //-ve loop
  793.                             {
  794.                                 grpPosCurrent[count] = grpPosMax[count];
  795.                             }
  796.                         }
  797.                         if (grpPosType[count] == 2)        //ping pong
  798.                         {
  799.                             grpPosStep[count] = - grpPosStep[count];
  800.                             grpPosCurrent[count] = grpPosCurrent[count] + grpPosStep[count];
  801.                         }
  802.                     }
  803.                     //playSound(lostSnd,0);        //test
  804.                     //now order to new sector
  805.                     temp = grpPosCurrent[count];
  806.                     //order scout forces to random position in this sector
  807.                     tempX = sectorsX1[temp] + random(sectorsX2[temp] - sectorsX1[temp]);
  808.                     tempY = sectorsY1[temp] + random(sectorsY2[temp] - sectorsY1[temp]);
  809.                     orderGroupLoc(grpGroup[count], DORDER_SCOUT, tempX, tempY);    //why was this on DORDER_MOVE?
  810.                 }
  811.             }
  812.         }
  813.         count = count + 1;
  814.     }
  815. }
  816.  
  817. //not finished yet!
  818. event targetGroups(targetGroupsTrig)
  819. {
  820. //clear targets if any gone (by shuffling down array)
  821.     count = 0;
  822.     while (count < numEnemies)
  823.     {
  824.         if (targetCount[count] > 0)
  825.         {
  826.             temp = 0;
  827.             while (temp < targetCount[count])
  828.             {
  829.                 if (numStructsButNotWallsInArea(player, targetX[count][temp] - targetRange, targetY[count][temp] - targetRange,
  830.                         targetX[count][temp] + targetRange, targetY[count][temp] + targetRange) == 0)
  831.                 //(not (objectInRange(player, targetX[count][temp], targetY[count][temp], targetRange)))
  832.  
  833.                 {
  834.                     count2 = temp;
  835.                     while (count2 < targetCount[count])
  836.                     {
  837.                         targetX[count][count2] = targetX[count][count2 + 1];
  838.                         targetY[count][count2] = targetY[count][count2 + 1];
  839.                         count2 = count2 + 1;
  840.                     }
  841.                     targetCount[count] = targetCount[count] - 1;        //reduce total for this enemy
  842.                 }
  843.                 temp = temp + 1;
  844.             }
  845.         }
  846.  
  847. //flag new targets, if any (structures and droids but not walls!), at the moment for any group (not just scouts)
  848.         count2 = 0;
  849.         while (count2 < numGroups)
  850.         {
  851.             temp1 = numStructsButNotWallsInArea(player, grpGroup[count2].x - targetRange, grpGroup[count2].y - targetRange,
  852.                      grpGroup[count2].x + targetRange, grpGroup[count2].y + targetRange);
  853.             temp2 = numDroidsInArea(player,  grpGroup[count2].x - targetRange, grpGroup[count2].y - targetRange,
  854.                      grpGroup[count2].x + targetRange, grpGroup[count2].y + targetRange);
  855.  
  856.             //make sure correct player, and targets exist before logging a new one
  857.             if ((grpPlayer[count2] == enemy[count]) and (targetCount[count] < targetMax) and ((temp1 > 0) or (temp2 > 0)))
  858.                     //(objectInRange(player, grpGroup[count2].x, grpGroup[count2].y, targetRange)))
  859.             {
  860.                 //playSound(lostSnd,1);
  861.                 targetX[count][targetCount[count]] = grpGroup[count2].x;
  862.                 targetY[count][targetCount[count]] = grpGroup[count2].y;
  863.             //order group to attack! (should be following heavies)
  864.                 //orderGroupLoc(grpGroup[count2], DORDER_SCOUT, targetX[count][targetCount[count]], targetY[count][targetCount[count]]);
  865.  
  866.                 if ((grpGroup[count2].members <= temp1 + temp2) and (grpType[count2] == 2))
  867.                 //if more objects than scouts, run away!!!
  868.                 {
  869.                     //playSound(lostSnd,0);    //test!
  870.  
  871.                     //use retreat stuff instead
  872.                     orderGroup(grpGroup[count2], DORDER_RUN);    //run away for a bit (will only work with initial retreat pos?)
  873.                 }
  874.                 else if (grpType[count2] == 2)
  875.                 {
  876.                     orderGroup(grpGroup[count2], DORDER_STOP);    //stay where you are (and hopefully kill stuff) if scout group
  877.                 }
  878.                 targetCount[count] = targetCount[count] +1;
  879.             }
  880.             count2 = count2 +1;
  881.         }
  882.         count = count +1;
  883.     }
  884. }
  885. */
  886.  
  887. event factoryProdEvnt(factoryProdTrig)
  888. {
  889.     count = 0;
  890.     while (count < numFactories)
  891.     {
  892.         //turn off dead factories
  893.         if (structures[factID[count]] == NULLOBJECT)
  894.         {
  895.             factFlagGo[count] = FALSE;
  896.         }
  897.         //switched on and not producing anything?
  898.         if (factFlagGo[count])
  899.         {
  900.             if (structureIdle(structures[factID[count]]))
  901.             {
  902.                 //need to update template with technology!
  903.                 //use min and max to get random build template
  904.                 temp = random(factTempMax[count] - factTempMin[count]) + factTempMin[count];
  905.                 temp2 = random(factTempMax[count] - temp) + 1;        //build random number (less for better stuff)
  906.                 buildDroid (templates[temp], structures[factID[count]], structures[factID[count]].player, temp2);
  907.             }
  908.         }
  909.         count = count + 1;
  910.     }
  911. }
  912.  
  913. event droidBuilt(inactive)    //triggered by later callbacks
  914. {
  915. /*
  916.     //check for New Truck Built!!!!
  917.     if (newDroid.droidType == DROID_CONSTRUCT) 
  918.     {
  919.  
  920.     }
  921. */
  922.     //find factory number
  923.     temp2 = 0;        //flagged if group match found
  924.     temp = -1;        //in case not found
  925.     if (newDroidFactory != NULLOBJECT)
  926.     {
  927.         count = 0;
  928.         while (count < numFactories)
  929.         {
  930.             if (newDroidFactory == structures[factID[count]])
  931.             {
  932.                 temp = factID[count];    //count; //use factory index, not structure index
  933.             }
  934.             count = count +1;
  935.         }
  936.     }
  937.     //check thru groups to reinforce
  938.     count = 0;
  939.     while (count < numGroups)
  940.     {
  941.         if (((temp == grpFactory[count]) or (grpFactory[count] == -1))    //got match, or any factory OK?
  942.             and (grpGroup[count].members < grpIdealSize[count]))        //and needs reinforcing?
  943.         {
  944.             //add to reinforcement group
  945.             groupAddDroid(grpReinforce[count], newDroid);
  946.             //orderGroupLoc(grpReinforce[count], DORDER_MOVE, 8000, 13000);    //test for now
  947.  
  948.             //if ideal size, add to main group!
  949.             if ((grpGroup[count].members + grpReinforce[count].members) >= grpIdealSize[count])
  950.             {
  951.                 groupAddGroup(grpGroup[count], grpReinforce[count]);
  952.                 //grpPosCurrent[count] = grpPosMin[count];        //test for now so can see if added to group
  953.             }
  954.             //if group dead, add to group and reset starting sector?
  955.             if (grpGroup[count].members == 0)
  956.             {
  957.                 groupAddGroup(grpGroup[count], grpReinforce[count]);
  958.                 //set back to start sector...?
  959.                 grpPosCurrent[count] = grpPosMin[count];        //go back to min sector if starting group from scratch
  960.             }
  961.             //test order only!!!
  962.             //orderGroupLoc(grpGroup[count], DORDER_SCOUT, coordsX[grpPosCurrent[count]], coordsY[grpPosCurrent[count]]);
  963.             count = numGroups;    //exit early
  964.             temp2 = 1;
  965.         }
  966.         count = count +1;
  967.     }
  968.     //if temp2 != 0, ie not assigned to a group, put in a special group for that player, and pull out if a group can take from any and
  969.     //needs reinforcing. (another event to check thru pooled group?)
  970.     //still to be done!
  971.         
  972. }
  973.  
  974. //hack to allow CALL_NEWDROID to work with unspecified enemy players!!!!
  975. event droidBuilt1(CALL_NEWDROID, 1, ref newDroid, ref newDroidFactory)
  976. {
  977.     setEventTrigger(droidBuilt, droidBuiltTrig);
  978. }
  979.  
  980. event droidBuilt2(CALL_NEWDROID, 2, ref newDroid, ref newDroidFactory)
  981. {
  982.     setEventTrigger(droidBuilt, droidBuiltTrig);
  983. }
  984.  
  985. event droidBuilt3(CALL_NEWDROID, 3, ref newDroid, ref newDroidFactory)
  986. {
  987.     setEventTrigger(droidBuilt, droidBuiltTrig);
  988. }
  989.  
  990. event droidBuilt4(CALL_NEWDROID, 4, ref newDroid, ref newDroidFactory)
  991. {
  992.     setEventTrigger(droidBuilt, droidBuiltTrig);
  993. }
  994.  
  995. event droidBuilt5(CALL_NEWDROID, 5, ref newDroid, ref newDroidFactory)
  996. {
  997.     setEventTrigger(droidBuilt, droidBuiltTrig);
  998. }
  999.  
  1000. event droidBuilt6(CALL_NEWDROID, 6, ref newDroid, ref newDroidFactory)
  1001. {
  1002.     setEventTrigger(droidBuilt, droidBuiltTrig);
  1003. }
  1004.  
  1005. event droidBuilt7(CALL_NEWDROID, 7, ref newDroid, ref newDroidFactory)
  1006. {
  1007.     setEventTrigger(droidBuilt, droidBuiltTrig);
  1008. }
  1009.  
  1010.  
  1011. event regionGroupsEvnt(regionGroupsTrig)
  1012. {
  1013.     //check for groups
  1014.     count = 0;
  1015.     while (count < numGroups)
  1016.     {
  1017.         //region triggered? (NOT used if grpType = 1 (DEFENSIVE group). RegionGo defines area to defend instead!)
  1018.         if ((not grpFlagGo[count]) and (grpType[count] != 1) and (grpRegionGo[count] >= 0))
  1019.         {
  1020.             if (droidInArea(grpWhoGo[count],
  1021.                 regionsX1[grpRegionGo[count]], regionsY1[grpRegionGo[count]],
  1022.                 regionsX2[grpRegionGo[count]], regionsY2[grpRegionGo[count]]))
  1023.             {
  1024.                 grpFlagGo[count] = TRUE;
  1025.                 //scouts and attack forces don't use coords array, so don't bother with initial order!
  1026.                 if (grpType[count] < 2) 
  1027.                 {
  1028.                     orderGroupLoc(grpGroup[count], DORDER_SCOUT, coordsX[grpPosStart[count]], coordsY[grpPosStart[count]]);
  1029.                 }
  1030.             }
  1031.         }
  1032.         count = count + 1;
  1033.     }
  1034.     //check for factories
  1035.     count = 0;
  1036.     while (count < numFactories)
  1037.     {
  1038.         //region triggered?
  1039.         if ((not factFlagGo[count]) and (factRegionGo[count] >= 0))
  1040.         {
  1041.             if (droidInArea(player,                                    //assume Player to trigger region, rather than WhoGo[]
  1042.                 regionsX1[factRegionGo[count]], regionsY1[factRegionGo[count]],
  1043.                 regionsX2[factRegionGo[count]], regionsY2[factRegionGo[count]]))
  1044.             {
  1045.                 factFlagGo[count] = TRUE;
  1046.             }
  1047.         }
  1048.         count = count + 1;
  1049.     }
  1050. }
  1051.  
  1052. //update time count for triggering groups and factories...
  1053. event timeGroupsEvnt(timeGroupsTrig)
  1054. {
  1055.     timeGroup = timeGroup + 1;
  1056.     count = 0;
  1057.     //update groups
  1058.     while (count < numGroups)
  1059.     {
  1060.         if ((grpTimeGo[count] == timeGroup) and (not grpFlagGo[count]))
  1061.         {
  1062.             grpFlagGo[count] = TRUE;
  1063.             //scouts don't use coords array, so don't bother with initial order!
  1064.             if (grpType[count] < 2) 
  1065.             {
  1066.                 orderGroupLoc(grpGroup[count], DORDER_SCOUT, coordsX[grpPosStart[count]], coordsY[grpPosStart[count]]);
  1067.             }
  1068.         }
  1069.         count = count + 1;
  1070.     }
  1071.     //update factories
  1072.     count = 0;
  1073.     while (count < numFactories)
  1074.     {
  1075.         if ((factTimeGo[count] == timeGroup) and (not factFlagGo[count]))
  1076.         {
  1077.             factFlagGo[count] = TRUE;    //set factory to produce
  1078.         }
  1079.         count = count + 1;
  1080.     }
  1081. }
  1082.  
  1083.  
  1084. event enemyBaseHit(CALL_STRUCT_ATTACKED, enemy[enemyCount], ref hitStruc, ref attackerObj)
  1085. {
  1086.     playSound(attackSnd1, enemy[enemyCount]);    //quick check
  1087. //store attacked structure for repairing by trucks later (when no enemies nearby!)
  1088. /* still to be done
  1089.     if (hitStruc != NULLOBJECT)
  1090.     {
  1091.         //store damaged Structure for repair/rebuild later...
  1092.         temp = 0;
  1093.         count = 0;
  1094.         while (count < numDamaged[enemyCount])
  1095.         {
  1096.             if 
  1097.         }
  1098.     }
  1099. */
  1100.     if ((attackerObj != NULLOBJECT) and (hitStruc != NULLOBJECT))
  1101.     {
  1102.         count = 0;
  1103.         while (count < numGroups)
  1104.         {
  1105.             //check for defense forces that cover this region
  1106.             //but only if this structure belongs to same player as defensive group
  1107.             //and isn't already 'busy'
  1108.             if ((grpType[count] == 1) and (grpPlayer[count] == enemy[enemyCount]) and (not grpBusy[count]))
  1109.             {
  1110.                 if (grpRegionGo[count] < 0)    //cope with no region specified
  1111.                 {
  1112.                     orderGroupLoc(grpGroup[count], DORDER_SCOUT, attackerObj.x, attackerObj.y);
  1113.                     grpBusy[count] = TRUE;
  1114.                     count = numGroups;    //break out of loop, since found
  1115.                 }
  1116.                 else if ((hitStruc.x >= regionsX1[grpRegionGo[count]])
  1117.                 and    (hitStruc.x <= regionsX2[grpRegionGo[count]])
  1118.                 and    (hitStruc.y >= regionsY1[grpRegionGo[count]])
  1119.                 and    (hitStruc.y <= regionsY2[grpRegionGo[count]]))
  1120.                 {
  1121.                     orderGroupLoc(grpGroup[count], DORDER_SCOUT, attackerObj.x, attackerObj.y);
  1122.                     grpBusy[count] = TRUE;
  1123.                     count = numGroups;    //break out of loop, since found
  1124.                 }
  1125.             }
  1126.             count = count + 1;
  1127.         }
  1128.     }
  1129.  
  1130. }
  1131.  
  1132.  
  1133. //Updates enemyCount for enemyBaseHit event.
  1134. event updateEnemy(updateEnemyTrig)
  1135. {
  1136. /*
  1137.     enemyCount = enemyCount + 1;
  1138.     if (enemyCount >= numEnemies)
  1139.     {
  1140.         enemyCount = 0;
  1141.     }
  1142. */
  1143. //done this way so never invalid!
  1144.     if (enemyCount < numEnemies - 1)
  1145.     {
  1146.         enemyCount = enemyCount + 1;
  1147.     }
  1148.     else
  1149.     {
  1150.         enemyCount = 0;
  1151.     }
  1152. }
  1153.