//Generic script Version 1.0 //For standard campaign maps /* ******************** */ /* Declared Variables */ /* ******************** */ /* Next Level stuff */ public LEVEL NextLev; /* Define Players/Enemies */ public int numEnemies, enemy[2]; private int targetCount[2], targetX[2][5], targetY[2][5]; //MAX targets = 4, need array one bigger! public BOOL allianceFlag; /* Starting Enemy Power */ public int power[2]; /* Structure Limits */ public int numStrucStats, strucLimit[5]; public STRUCTURESTAT strucStat[5]; /* Initialisation */ public int centreX, centreY; public int scrollX1, scrollX2, scrollY1, scrollY2; public int zoomLevel; public int numLZ, LZX[1], LZY[1]; public int numTechs[2]; public RESEARCHSTAT startTech[2][10]; /* Briefings */ public int numBriefs; public INTMESSAGE brief[2]; public INTMESSAGE endMsg, winMsg; /* Victory Conditions */ public int numVictory, victoryX[2], victoryY[2]; public BOOL victory[2]; /* Objectives */ public int numObjectives, objectiveX[3], objectiveY[3]; public INTMESSAGE objective[3]; private BOOL objectiveFlag[3]; private int objectivesDone; /* Artifacts */ public SOUND artSnd1, artSnd2; public int numArt, victoryArt, artType[6], artVal[6], artX[6], artY[6]; //public INTMESSAGE artMsg[6]; public RESEARCHSTAT artComp[6]; private FEATURE artID[6]; private int artFlag[6]; private int artCollected; /* Enemy Base Blips */ public int numBases, basePlayer[5]; public int baseRegion[5], baseWav1[5], baseWav2[5]; public INTMESSAGE baseMsg[5]; private int baseFlag[5]; private int basesDead; private int iMidX, iMidY; /* Groups */ //these can be for any player! public int numGroups; public int grpType[10], grpPlayer[10], grpRegion[10], grpTimeGo[10], grpRegionGo[10], grpWhoGo[10]; public int grpMorale[10], grpLeadership[10], grpRetreatXY[10], grpIdealSize[10]; public int grpPosStart[10], grpPosMin[10], grpPosMax[10], grpPosStep[10], grpPosType[10]; public int grpFactory[10]; private BOOL grpFlagGo[10]; //keep track of already triggered groups private GROUP grpGroup[10], grpReinforce[10]; //the actual groups are stored in this, based on region. private int grpPosCurrent[10]; //keep track of current waypoint private BOOL grpBusy[10]; //keep track of already ordered private int timeGroup; //keeps track of time since started level, for triggering groups /* Factories */ //these can be for any player! public int numFactories; public int factID[10], factAssXY[10], factTimeGo[10]; public int factRegionGo[10], factTempMin[10], factTempMax[10]; private BOOL factFlagGo[10]; //stores whether producing or not /* LISTS OF STUFF (INDEXED BY ARRAY) */ public STRUCTURE structures[10]; public FEATURE features[10]; public DROID droids[10]; public TEMPLATE templates[20]; public int coordsX[10], coordsY[10]; public int regionsX1[20], regionsY1[20], regionsX2[20], regionsY2[20]; public int sectorsX1[20], sectorsY1[20], sectorsX2[20], sectorsY2[20]; /* 'Globals' */ public int player; public FEATURESTAT crate; public int artRange, objectiveRange; //artifact pickup/obj blip removal public int wayRange, targetRange; //range to waypoints/range for targets public int targetMax; //maximum number of targets (4) public SOUND wonSnd; //mission won public SOUND lostSnd; //mission lost public SOUND attackSnd1; //Base Under Attack Sound public SOUND baseSnd[5]; //base detected/dead /* General variables */ private int count, count2; //for while loops private DROID testDroid, newDroid; private STRUCTURE newDroidFactory; //new droid built private int countBriefs, temp, temp1, temp2, tempX, tempY; private STRUCTURE hitStruc; //Base Under Attack private BASEOBJ attackerObj; //Base Under Attack private int t; //Base Under Attack time delay for next warning private int enemyCount; //for enemy base attack stuff! /* ******************** */ /* Triggers */ /* ******************** */ trigger winTrig(artCollected == victoryArt, 25); trigger lostTrig(not anyDroidsLeft(player), 25); trigger objTrig (every, 15); trigger artTrig (every, 10); trigger baseTrig (every, 15); trigger nextLevTrig (every, 20); trigger gameLostTrig (every, 20); trigger checkGroupsTrig (every, 35); //every 4 seconds trigger wayGroupsTrig (every, 100); //every 4 seconds trigger sectorGroupsTrig(every, 75); //every 8 seconds trigger attackGroupsTrig(every, 83); //every 8 seconds trigger targetGroupsTrig(every, 43); //every 4 seconds trigger regionGroupsTrig(every, 11); //every second trigger timeGroupsTrig (every, 100); //every 10 seconds trigger updateEnemyTrig (every, 21); //every 2 seconds trigger factoryProdTrig (every, 450); //every 45 seconds trigger droidBuiltTrig (wait, 1); //very quickly /* ******************** */ /* Events */ /* ******************** */ /* Declared Events */ event wonYetEvnt; event lostYetEvnt; event timeUp; /* Initialisation */ event start(CALL_GAMEINIT) { //centre view centreViewPos(centreX, centreY); //set alliances if (allianceFlag and numEnemies > 1) { count = 0; while (count < numEnemies) { count2 = 0; while (count2 < numEnemies) { if (count != count2) { createAlliance(enemy[count], enemy[count2]); } count2 = count2 + 1; } count = count + 1; } } //set scroll limits setScrollParams(scrollX1, scrollY1, scrollX2, scrollY2); //set radar zoom level setRadarZoom(zoomLevel); //set LZ and no go areas initAllNoGoAreas(); count = 0; while (count < numLZ) { setNoGoArea(LZX[count] - 1, LZY[count] - 1, LZX[count] + 1, LZY[count] + 1, count); count = count + 1; } //set structure limits count = 0; while (count < numStrucStats) { setStructureLimits (strucStat[count], strucLimit[count], player); enableStructure(strucStat[count], player); count = count + 1; } //set power levels count = 0; while (count < numEnemies) { //also set technology for each enemy count2 = 0; while (count2 < numTechs[count]) { completeResearch(startTech[count][count2], enemy[count]); count2 = count2 + 1; } setPowerLevel(power[count], enemy[count]); count = count + 1; } //show player start objectives count = 0; while (count < numObjectives) { addMessage(objective[count], PROX_MSG, player, false); count = count + 1; } //Setup Artifacts already on map (NOT TESTED YET!) //setting flags incorrectly in VLO could break game! count = 0; while (count < numArt) { if (artType[count] >= 4) //deal with no object to get artifact from { //eg for extra topics given at the end? artFlag[count] = 4; } if (artType[count] == 0) //deal with artifact already on map { artID[count] = features[artVal[count]]; artFlag[count] = 1; } count = count + 1; } //setup groups count = 0; while (count < numGroups) { groupAddArea(grpGroup[count], grpPlayer[count], regionsX1[grpRegion[count]], regionsY1[grpRegion[count]], regionsX2[grpRegion[count]], regionsY2[grpRegion[count]]); grpPosCurrent[count] = grpPosStart[count]; //set morale levels if (grpMorale[count] >= 0) { /* //set repair for now (run away not good enough!?) setGroupSecondary(grpGroup[count], DSO_REPAIR_LEVEL, DSS_REPLEV_HIGH); */ //to get hill attackers to work properly //setGroupSecondary(grpGroup[count], DSO_ATTACK_RANGE, DSS_ARANGE_LONG); setGroupRetreatForce(grpGroup[count], grpMorale[count]); setGroupRetreatLeadership(grpGroup[count], grpLeadership[count]); if (grpType[count] < 2) //use coords for patrol/ambush/defence { setGroupRetreatPoint(grpGroup[count], coordsX[grpRetreatXY[count]], coordsY[grpRetreatXY[count]]); } else //use sectors for scout/attack { temp = grpRetreatXY[count]; //order scout/attack forces to random position in this sector tempX = sectorsX1[temp] + random(sectorsX2[temp] - sectorsX1[temp]); tempY = sectorsY1[temp] + random(sectorsY2[temp] - sectorsY1[temp]); setGroupRetreatPoint(grpGroup[count], tempX, tempY); } } //set time = 0 groups going if (grpTimeGo[count] == timeGroup) { grpFlagGo[count] = TRUE; if (grpType[count] < 2) //use coords for patrol/ambush/defence { if (grpPosStart[count] >= 0) //cope with no start position defined { orderGroupLoc(grpGroup[count], DORDER_SCOUT, coordsX[grpPosStart[count]], coordsY[grpPosStart[count]]); } } else { temp = grpPosCurrent[count]; //order scout/attack forces to random position in this sector tempX = sectorsX1[temp] + random(sectorsX2[temp] - sectorsX1[temp]); tempY = sectorsY1[temp] + random(sectorsY2[temp] - sectorsY1[temp]); orderGroupLoc(grpGroup[count], DORDER_MOVE, tempX, tempY); } } count = count + 1; } //set time = 0 factories going count = 0; while (count < numFactories) { //set assembly points, if desired if (factAssXY[count] != -1) { setAssemblyPoint (structures[factID[count]], coordsX[factAssXY[count]], coordsY[factAssXY[count]]); } if ((factTimeGo[count] == timeGroup) and (not factFlagGo[count])) { factFlagGo[count] = TRUE; //set factory to produce } count = count + 1; } //play mission brief(s) if (numBriefs > 0) { addMessage(brief[0], MISS_MSG, 0, true); countBriefs = 1; } } event briefings(CALL_VIDEO_QUIT) //need to rework this better!! { if (countBriefs >= numBriefs) //last briefing? { setEventTrigger(briefings, inactive); } if (countBriefs < numBriefs) //remove last, add next? { removeMessage(brief[countBriefs - 1], MISS_MSG, 0); addMessage(brief[countBriefs], MISS_MSG, 0, true); countBriefs = countBriefs + 1; } } /* Base Under Attack */ event baseHit(CALL_STRUCT_ATTACKED, selectedPlayer, ref hitStruc, ref attackerObj) { if (t>=10) { t=0; playSoundPos(attackSnd1, player, hitStruc.x, hitStruc.y, hitStruc.z); } } event everySec(every, 20) //update time delay before told again (about 20 seconds) { t=t+1; } /* Remove Objective Blips */ event removeObjectives(objTrig) { if (objectivesDone == numObjectives) //all blips gone? { setEventTrigger(removeObjectives, inactive); } else { count = 0; while (count < numObjectives) { if ((not objectiveFlag[count]) and (droidInRange(player, objectiveX[count], objectiveY[count], objectiveRange))) { objectiveFlag[count] = TRUE; objectivesDone = objectivesDone + 1; removeMessage(objective[count], PROX_MSG, player); } count = count + 1; } } } /* Artifacts */ //This works for artifacts from STRUCTURES, FEATURES or DROIDS as well as crates already on map! //tested for STRUCTURES, FEATURES, DROIDS and starting CRATES event artLoop(artTrig) //update artifact list { if (artCollected == numArt) //all artifacts collected? { setEventTrigger(artLoop, inactive); } else { count = 0; while (count < numArt) { if (artFlag[count] == 0) { temp = 0; //might be a better way to do this check? if (artType[count] == 1) { if (structures[artVal[count]] == NULLOBJECT) //from dead structure { temp = 1; } } if (artType[count] == 2) { if (features[artVal[count]] == NULLOBJECT) //from dead feature { temp = 1; } } if (artType[count] == 3) { if (droids[artVal[count]] == NULLOBJECT) //from dead droid { temp = 1; } } if (temp == 1) //OK to place crate? { //place artifact crate, and allow check for prox artID[count] = addFeature(crate, artX[count], artY[count]); artFlag[count] = 1; } } if (artFlag[count] == 1) { artFlag[count] = 2; //hack since don't use script for detected.wav } if (artFlag[count] == 2) { if (droidInRange(player, artX[count], artY[count], artRange)) { artCollected = artCollected + 1; artFlag[count] = 3; playSoundPos(artSnd2, player, artID[count].x, artID[count].y, artID[count].z); destroyFeature(artID[count]); //removeMessage(artMsg[count], PROX_MSG, player); enableResearch(artComp[count], player); } } if (artType[count] == 3) { if (droids[artVal[count]] != NULLOBJECT) { //keep track of droid position for crate when it dies artX[count] = droids[artVal[count]].x; artY[count] = droids[artVal[count]].y; } } count = count + 1; } } } /* Enemy Base Blips */ event baseLoop(baseTrig) //update base blips { if (basesDead == numBases) //all bases gone? { setEventTrigger(baseLoop, inactive); } else { count = 0; while (count < numBases) { if (baseFlag[count] == 0) { if (seenStructInArea(player, basePlayer[count], FALSE, regionsX1[baseRegion[count]], regionsY1[baseRegion[count]], regionsX2[baseRegion[count]], regionsY2[baseRegion[count]])) { addMessage(baseMsg[count], PROX_MSG, player, false); if (baseWav1[count] >= 0) { iMidX = (regionsX1[baseRegion[count]]+regionsX2[baseRegion[count]])/2; iMidY = (regionsY1[baseRegion[count]]+regionsY2[baseRegion[count]])/2; playSoundPos(baseSnd[baseWav1[count]], player, iMidX, iMidY, 0 ); } baseFlag[count] = 1; } } if (baseFlag[count] == 1) { if (numStructsButNotWallsInArea(basePlayer[count], regionsX1[baseRegion[count]], regionsY1[baseRegion[count]], regionsX2[baseRegion[count]], regionsY2[baseRegion[count]])== 0) { basesDead = basesDead + 1; baseFlag[count] = 2; if (baseWav2[count] >= 0) { iMidX = (regionsX1[baseRegion[count]]+regionsX2[baseRegion[count]])/2; iMidY = (regionsY1[baseRegion[count]]+regionsY2[baseRegion[count]])/2; playSoundPos(baseSnd[baseWav2[count]], player, iMidX, iMidY, 0 ); //playSound(baseSnd[baseWav2[count]], player); } removeMessage(baseMsg[count], PROX_MSG, player); killStructsInArea(basePlayer[count], REF_WALL, //remove walls and building features in base regionsX1[baseRegion[count]], regionsY1[baseRegion[count]], regionsX2[baseRegion[count]], regionsY2[baseRegion[count]], TRUE, TRUE); killStructsInArea(basePlayer[count], REF_WALLCORNER, //remove corner walls in base regionsX1[baseRegion[count]], regionsY1[baseRegion[count]], regionsX2[baseRegion[count]], regionsY2[baseRegion[count]], TRUE, FALSE); } } count = count + 1; } } } /* Events: Win or Lose */ event nextLevEvnt(inactive) //assumes victory already checked { flushConsoleMessages(); playSound(wonSnd,0); pause(20); // give all research count = 0; while (count < numArt) { enableResearch(artComp[count], 0); count = count +1; } // *required for sub missions* //setLandingZone(10, 51, 12, 53); // *no longer need to remove briefings?* //removeMessage(MissionBrief, MISS_MSG, player); //startMission(CAMP_EXPAND, NextLev); //End game here for now! (don't try next mission) gameOverMessage(winMsg, MISS_MSG, 0, true); setEventTrigger(nextLevEvnt, inactive); } //skip to end of level event cheatEvnt(CALL_MISSION_START) //cheat button ctrl M { setEventTrigger(nextLevEvnt, nextLevTrig); setEventTrigger(cheatEvnt, inactive); } event gameLost(inactive) { // addMessage(endMsg, MISS_MSG, 0, true); // gameOver(false); gameOverMessage(endMsg, MISS_MSG, 0, FALSE); setEventTrigger(gameLost, inactive); } event lostYetEvnt(lostTrig) //triggered on (not anyDroidsLeft(player)) { if (not anyStructButWallsLeft(player)) { setEventTrigger(wonYetEvnt,inactive); setEventTrigger(timeUp, inactive); setEventTrigger(gameLost, gameLostTrig); //waits 2 seconds before ending //playSound(lostSnd,0); setEventTrigger(lostYetEvnt, inactive); } } //out of time? event timeUp(CALL_MISSION_TIME) { setEventTrigger(wonYetEvnt,inactive); setEventTrigger(lostYetEvnt,inactive); playSound(lostSnd,0); //may want different sound, eg "Out of Time" setEventTrigger(gameLost, gameLostTrig); //waits 2 seconds before ending setEventTrigger(timeUp, inactive); } event wonYetEvnt(winTrig) //triggered on (artCollected == victoryArt) { temp2 = 0; //stores number of conditions met //needs to check various victory conditions setup in VLO //check all enemy vehicles and structures destroyed if (victory[0]) { count = 0; temp = 0; while (count < numEnemies) { if ((not anyDroidsLeft(enemy[count])) and (not anyStructButWallsLeft(enemy[count]))) { temp = temp + 1; } count = count + 1; } if (temp == numEnemies) { temp2 = temp2 + 1; } } //check all player vehicles in specific area (eg LZ) if (victory[1]) { temp = numDroidsInArea(player, 0, 0, scrollX1 * 128, scrollY1 * 128); if (temp == numDroidsInArea(player, victoryX[0], victoryY[0], victoryX[1], victoryY[1])) { if (temp != 0) { temp2 = temp2 + 1; } } } if (temp2 == numVictory) //victory reached? { setEventTrigger(lostYetEvnt, inactive); setEventTrigger(timeUp, inactive); setEventTrigger(nextLevEvnt, nextLevTrig); setEventTrigger(wonYetEvnt, inactive); } } /* Enemy AI */ event wayGroups(wayGroupsTrig) { count = 0; while (count < numGroups) { //update groups position if ((grpFlagGo[count]) and (grpType[count] < 2) and (grpPosStart[count] >= 0)) //been triggered and ambush/patrol/defence? { //simple predefined waypoints //has the group got to waypoint or are they mainly idle? /* if ((grpGroup[count].members > 0) and ( (grpGroup[count].x >= coordsX[grpPosCurrent[count]] - wayRange) and (grpGroup[count].y >= coordsY[grpPosCurrent[count]] - wayRange) and (grpGroup[count].x <= coordsX[grpPosCurrent[count]] + wayRange) and (grpGroup[count].y <= coordsY[grpPosCurrent[count]] + wayRange)) or (idleGroup(grpGroup[count]) >= grpGroup[count].members/2)) */ if (grpGroup[count].members > 0) //idle stuff taken out FOR DEMO { grpBusy[count] = FALSE; //no longer 'busy' temp = grpPosCurrent[count]; //store for checking difference later if (grpPosType[count] == 3) //random choice { grpPosCurrent[count] = grpPosMin[count] + grpPosStep[count] * random(grpPosMax[count] - grpPosMin[count]); } else { grpPosCurrent[count] = grpPosCurrent[count] + grpPosStep[count]; //get next waypoint } if ((grpPosCurrent[count] > grpPosMax[count]) or (grpPosCurrent[count] < grpPosMin[count])) { grpPosCurrent[count] = grpPosCurrent[count] - grpPosStep[count]; //stop at last one if (grpPosType[count] == 1) //loop { if (grpPosStep[count] > 0) //+ve loop { grpPosCurrent[count] = grpPosMin[count]; } else //-ve loop { grpPosCurrent[count] = grpPosMax[count]; } } if (grpPosType[count] == 2) //ping pong { grpPosStep[count] = - grpPosStep[count]; grpPosCurrent[count] = grpPosCurrent[count] + grpPosStep[count]; } } if (grpPosCurrent[count] != temp) //don't order again if already there! { //orderGroupLoc(grpGroup[count], DORDER_SCOUT, coordsX[grpPosCurrent[count]], coordsY[grpPosCurrent[count]]); orderGroupLoc(grpGroup[count], DORDER_MOVE, coordsX[grpPosCurrent[count]], coordsY[grpPosCurrent[count]]); } } } count = count + 1; } } /* SCOUTS AND TARGET FINDING DISABLED FOR DEMO event checkGroups(checkGroupsTrig) { count = 0; while (count < numGroups) { initIterateGroup(grpGroup[count]); count2 = 0; while (count2 < grpGroup[count].members) { //check for morale failed, and make retreat fully testDroid = iterateGroup(grpGroup[count]); if (testDroid.order == DORDER_RUN) { if (grpType[count] >= 2) //scout and attack type uses sectors { grpPosCurrent[count] = grpRetreatXY[count]; //flag retreat sector as current? temp = grpRetreatXY[count]; //order scout forces to random position in this sector tempX = sectorsX1[temp] + random(sectorsX2[temp] - sectorsX1[temp]); tempY = sectorsY1[temp] + random(sectorsY2[temp] - sectorsY1[temp]); orderGroupLoc(grpGroup[count], DORDER_MOVE, tempX, tempY); } else { orderGroupLoc(grpGroup[count], DORDER_MOVE, coordsX[grpRetreatXY[count]], coordsY[grpRetreatXY[count]]); } grpBusy[count] = TRUE; //mark busy (will become idle when at retreat point) count2 = grpGroup[count].members; //exit loop } count2 = count2 + 1; } count = count + 1; } } // not finished yet! Now includes attack groups as well as scout groups event sectorGroups(sectorGroupsTrig) { count = 0; while (count < numGroups) { if ((grpFlagGo[count]) and (grpType[count] >= 2) and (grpGroup[count].members != 0) //set going and scout/attack type only and (idleGroup(grpGroup[count]) > (grpGroup[count].members / 2))) //also not busy! { grpBusy[count] = FALSE; //no longer 'busy'? //attack group stuff temp1 = 0; //just in case don't find an enemy match if ((allianceFlag)) // and (random(numEnemies + 1) < 1)) { temp1 = random(numEnemies); //allow allies targets as well! } else { count2 = 0; while (count2 < numEnemies) { if (grpPlayer[count] == enemy[count2]) { temp1 = count2; //this should be enemy index number! } count2 = count2 + 1; } } if ((grpType[count] == 3) and (targetCount[temp1] > 0)) //any targets for attack groups { temp2 = random(targetCount[temp1]); orderGroupLoc(grpGroup[count], DORDER_SCOUT, targetX[temp1][temp2], targetY[temp1][temp2]); } else //otherwise next sector { //scout/next sector stuff temp = grpPosCurrent[count]; //current scout sector //10% chance of scouting past an occupied sector (even if valid targets exist there!) //put in temp1 and temp2 for legibility! temp1 = numStructsButNotWallsInArea(player, sectorsX1[temp], sectorsY1[temp], sectorsX2[temp], sectorsY2[temp]); temp2 = numDroidsInArea(player, sectorsX1[temp], sectorsY1[temp], sectorsX2[temp], sectorsY2[temp]); //next sector if clear of droids and structures or 10% chance if ((random(100) < 10) or ((temp1 == 0) and (temp2 ==0))) { //sector clear so use as a retreat point 50% chance if (random(100) < 50) { grpRetreatXY[count] = grpPosCurrent[count]; } //get new sector (like wayGroups above!) if (grpPosType[count] == 3) //random choice { grpPosCurrent[count] = grpPosMin[count] + grpPosStep[count] * random(grpPosMax[count] - grpPosMin[count]); } else { grpPosCurrent[count] = grpPosCurrent[count] + grpPosStep[count]; //get next waypoint } if ((grpPosCurrent[count] > grpPosMax[count]) or (grpPosCurrent[count] < grpPosMin[count])) { grpPosCurrent[count] = grpPosCurrent[count] - grpPosStep[count]; //stop at last one if (grpPosType[count] == 1) //loop { if (grpPosStep[count] > 0) //+ve loop { grpPosCurrent[count] = grpPosMin[count]; } else //-ve loop { grpPosCurrent[count] = grpPosMax[count]; } } if (grpPosType[count] == 2) //ping pong { grpPosStep[count] = - grpPosStep[count]; grpPosCurrent[count] = grpPosCurrent[count] + grpPosStep[count]; } } //playSound(lostSnd,0); //test //now order to new sector temp = grpPosCurrent[count]; //order scout forces to random position in this sector tempX = sectorsX1[temp] + random(sectorsX2[temp] - sectorsX1[temp]); tempY = sectorsY1[temp] + random(sectorsY2[temp] - sectorsY1[temp]); orderGroupLoc(grpGroup[count], DORDER_SCOUT, tempX, tempY); //why was this on DORDER_MOVE? } } } count = count + 1; } } //not finished yet! event targetGroups(targetGroupsTrig) { //clear targets if any gone (by shuffling down array) count = 0; while (count < numEnemies) { if (targetCount[count] > 0) { temp = 0; while (temp < targetCount[count]) { if (numStructsButNotWallsInArea(player, targetX[count][temp] - targetRange, targetY[count][temp] - targetRange, targetX[count][temp] + targetRange, targetY[count][temp] + targetRange) == 0) //(not (objectInRange(player, targetX[count][temp], targetY[count][temp], targetRange))) { count2 = temp; while (count2 < targetCount[count]) { targetX[count][count2] = targetX[count][count2 + 1]; targetY[count][count2] = targetY[count][count2 + 1]; count2 = count2 + 1; } targetCount[count] = targetCount[count] - 1; //reduce total for this enemy } temp = temp + 1; } } //flag new targets, if any (structures and droids but not walls!), at the moment for any group (not just scouts) count2 = 0; while (count2 < numGroups) { temp1 = numStructsButNotWallsInArea(player, grpGroup[count2].x - targetRange, grpGroup[count2].y - targetRange, grpGroup[count2].x + targetRange, grpGroup[count2].y + targetRange); temp2 = numDroidsInArea(player, grpGroup[count2].x - targetRange, grpGroup[count2].y - targetRange, grpGroup[count2].x + targetRange, grpGroup[count2].y + targetRange); //make sure correct player, and targets exist before logging a new one if ((grpPlayer[count2] == enemy[count]) and (targetCount[count] < targetMax) and ((temp1 > 0) or (temp2 > 0))) //(objectInRange(player, grpGroup[count2].x, grpGroup[count2].y, targetRange))) { //playSound(lostSnd,1); targetX[count][targetCount[count]] = grpGroup[count2].x; targetY[count][targetCount[count]] = grpGroup[count2].y; //order group to attack! (should be following heavies) //orderGroupLoc(grpGroup[count2], DORDER_SCOUT, targetX[count][targetCount[count]], targetY[count][targetCount[count]]); if ((grpGroup[count2].members <= temp1 + temp2) and (grpType[count2] == 2)) //if more objects than scouts, run away!!! { //playSound(lostSnd,0); //test! //use retreat stuff instead orderGroup(grpGroup[count2], DORDER_RUN); //run away for a bit (will only work with initial retreat pos?) } else if (grpType[count2] == 2) { orderGroup(grpGroup[count2], DORDER_STOP); //stay where you are (and hopefully kill stuff) if scout group } targetCount[count] = targetCount[count] +1; } count2 = count2 +1; } count = count +1; } } */ event factoryProdEvnt(factoryProdTrig) { count = 0; while (count < numFactories) { //turn off dead factories if (structures[factID[count]] == NULLOBJECT) { factFlagGo[count] = FALSE; } //switched on and not producing anything? if (factFlagGo[count]) { if (structureIdle(structures[factID[count]])) { //need to update template with technology! //use min and max to get random build template temp = random(factTempMax[count] - factTempMin[count]) + factTempMin[count]; temp2 = random(factTempMax[count] - temp) + 1; //build random number (less for better stuff) buildDroid (templates[temp], structures[factID[count]], structures[factID[count]].player, temp2); } } count = count + 1; } } event droidBuilt(inactive) //triggered by later callbacks { /* //check for New Truck Built!!!! if (newDroid.droidType == DROID_CONSTRUCT) { } */ //find factory number temp2 = 0; //flagged if group match found temp = -1; //in case not found if (newDroidFactory != NULLOBJECT) { count = 0; while (count < numFactories) { if (newDroidFactory == structures[factID[count]]) { temp = factID[count]; //count; //use factory index, not structure index } count = count +1; } } //check thru groups to reinforce count = 0; while (count < numGroups) { if (((temp == grpFactory[count]) or (grpFactory[count] == -1)) //got match, or any factory OK? and (grpGroup[count].members < grpIdealSize[count])) //and needs reinforcing? { //add to reinforcement group groupAddDroid(grpReinforce[count], newDroid); //orderGroupLoc(grpReinforce[count], DORDER_MOVE, 8000, 13000); //test for now //if ideal size, add to main group! if ((grpGroup[count].members + grpReinforce[count].members) >= grpIdealSize[count]) { groupAddGroup(grpGroup[count], grpReinforce[count]); //grpPosCurrent[count] = grpPosMin[count]; //test for now so can see if added to group } //if group dead, add to group and reset starting sector? if (grpGroup[count].members == 0) { groupAddGroup(grpGroup[count], grpReinforce[count]); //set back to start sector...? grpPosCurrent[count] = grpPosMin[count]; //go back to min sector if starting group from scratch } //test order only!!! //orderGroupLoc(grpGroup[count], DORDER_SCOUT, coordsX[grpPosCurrent[count]], coordsY[grpPosCurrent[count]]); count = numGroups; //exit early temp2 = 1; } count = count +1; } //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 //needs reinforcing. (another event to check thru pooled group?) //still to be done! } //hack to allow CALL_NEWDROID to work with unspecified enemy players!!!! event droidBuilt1(CALL_NEWDROID, 1, ref newDroid, ref newDroidFactory) { setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt2(CALL_NEWDROID, 2, ref newDroid, ref newDroidFactory) { setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt3(CALL_NEWDROID, 3, ref newDroid, ref newDroidFactory) { setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt4(CALL_NEWDROID, 4, ref newDroid, ref newDroidFactory) { setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt5(CALL_NEWDROID, 5, ref newDroid, ref newDroidFactory) { setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt6(CALL_NEWDROID, 6, ref newDroid, ref newDroidFactory) { setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt7(CALL_NEWDROID, 7, ref newDroid, ref newDroidFactory) { setEventTrigger(droidBuilt, droidBuiltTrig); } event regionGroupsEvnt(regionGroupsTrig) { //check for groups count = 0; while (count < numGroups) { //region triggered? (NOT used if grpType = 1 (DEFENSIVE group). RegionGo defines area to defend instead!) if ((not grpFlagGo[count]) and (grpType[count] != 1) and (grpRegionGo[count] >= 0)) { if (droidInArea(grpWhoGo[count], regionsX1[grpRegionGo[count]], regionsY1[grpRegionGo[count]], regionsX2[grpRegionGo[count]], regionsY2[grpRegionGo[count]])) { grpFlagGo[count] = TRUE; //scouts and attack forces don't use coords array, so don't bother with initial order! if (grpType[count] < 2) { orderGroupLoc(grpGroup[count], DORDER_SCOUT, coordsX[grpPosStart[count]], coordsY[grpPosStart[count]]); } } } count = count + 1; } //check for factories count = 0; while (count < numFactories) { //region triggered? if ((not factFlagGo[count]) and (factRegionGo[count] >= 0)) { if (droidInArea(player, //assume Player to trigger region, rather than WhoGo[] regionsX1[factRegionGo[count]], regionsY1[factRegionGo[count]], regionsX2[factRegionGo[count]], regionsY2[factRegionGo[count]])) { factFlagGo[count] = TRUE; } } count = count + 1; } } //update time count for triggering groups and factories... event timeGroupsEvnt(timeGroupsTrig) { timeGroup = timeGroup + 1; count = 0; //update groups while (count < numGroups) { if ((grpTimeGo[count] == timeGroup) and (not grpFlagGo[count])) { grpFlagGo[count] = TRUE; //scouts don't use coords array, so don't bother with initial order! if (grpType[count] < 2) { orderGroupLoc(grpGroup[count], DORDER_SCOUT, coordsX[grpPosStart[count]], coordsY[grpPosStart[count]]); } } count = count + 1; } //update factories count = 0; while (count < numFactories) { if ((factTimeGo[count] == timeGroup) and (not factFlagGo[count])) { factFlagGo[count] = TRUE; //set factory to produce } count = count + 1; } } event enemyBaseHit(CALL_STRUCT_ATTACKED, enemy[enemyCount], ref hitStruc, ref attackerObj) { //playSoundPos(attackSnd1, enemy[enemyCount], hitStruc.x, hitStruc.y, hitStruc.z); //quick check //store attacked structure for repairing by trucks later (when no enemies nearby!) /* still to be done if (hitStruc != NULLOBJECT) { //store damaged Structure for repair/rebuild later... temp = 0; count = 0; while (count < numDamaged[enemyCount]) { if } } */ if ((attackerObj != NULLOBJECT) and (hitStruc != NULLOBJECT)) { count = 0; while (count < numGroups) { //check for defense forces that cover this region //but only if this structure belongs to same player as defensive group //and isn't already 'busy' if ((grpType[count] == 1) and (grpPlayer[count] == enemy[enemyCount]) and (not grpBusy[count])) { if (grpRegionGo[count] < 0) //cope with no region specified { orderGroupLoc(grpGroup[count], DORDER_SCOUT, attackerObj.x, attackerObj.y); grpBusy[count] = TRUE; count = numGroups; //break out of loop, since found } else if ((hitStruc.x >= regionsX1[grpRegionGo[count]]) and (hitStruc.x <= regionsX2[grpRegionGo[count]]) and (hitStruc.y >= regionsY1[grpRegionGo[count]]) and (hitStruc.y <= regionsY2[grpRegionGo[count]])) { orderGroupLoc(grpGroup[count], DORDER_SCOUT, attackerObj.x, attackerObj.y); grpBusy[count] = TRUE; count = numGroups; //break out of loop, since found } } count = count + 1; } } } //Updates enemyCount for enemyBaseHit event. event updateEnemy(updateEnemyTrig) { /* enemyCount = enemyCount + 1; if (enemyCount >= numEnemies) { enemyCount = 0; } */ //done this way so never invalid! if (enemyCount < numEnemies - 1) { enemyCount = enemyCount + 1; } else { enemyCount = 0; } }