//Generic script Version 1.0 //GenExp.slo //For start/expand campaign maps /* ******************** */ /* Declared Variables */ /* ******************** */ /* Next Level stuff */ public LEVEL NextLev; public BOOL lastLev; /* Define Players/Enemies */ public int numEnemies, enemy[2], allianceEnemy[2], alliancePlayer; 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]; /* Starting health retreat setting*/ public int healthRetreat[2], healthRetreatX[2], healthRetreatY[2]; public BOOL runOffFlag; /* Structure Limits */ public int numStrucStats, strucLimit[6]; public STRUCTURESTAT strucStat[6]; /* Initialisation */ public int centreX, centreY; public int scrollX1, scrollX2, scrollY1, scrollY2; public int zoomLevel; public int numLZ, LZX[8], LZY[8]; public int numTechs[2]; public RESEARCHSTAT startTech[2][40]; /* Transport Entry/Exit coords */ public int transX[2], transY[2]; //done in arrays so don't need to define for non submaps //transX[0] = entryX, transX[1] = exitX public INT ReinforceTime, timeLimit; public int entryX[2], entryY[2], exitX[2], exitY[2]; //enemy transport entry, exit public TEMPLATE transporter; //required for enemy transports landing private DROID transportDroid[2]; private BOOL transOnMap[2], playerTransOnMap, reinfOff; private GROUP transGroup; private INT transGroupIndex[2], transGroupPlayer, enemyLZX, enemyLZY; //used for enemy transports landing /* Videos - should only be max of two - and that's for the PSX - actually we need 8 (cam1->2)!*/ public int numVideos; public TEXTSTRING video[8]; public TEXTSTRING videoText[8]; /* Briefings */ public int numBriefs, briefVal[5]; public INTMESSAGE brief[5]; public INTMESSAGE endMsg; /* Victory Conditions */ public int numVictory, victory[4]; public BOOL linkVictory, linkFail; //extra victories checked in other scripts /* Failure Conditions */ public int fail[2]; public SOUND failSnd; public TEXTSTRING failMsg; /* Time Limit */ public BOOL noTimeLimit; //false = time limit fail OK, True = don't use time limit as fail /* Objectives */ public int numObjectives, objectiveX[4], objectiveY[4]; public INTMESSAGE objective[4]; private BOOL objectiveFlag[4]; 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[7]; public int baseRegion[7], baseWav1[7], baseWav2[7]; public INTMESSAGE baseMsg[7]; private int baseFlag[7]; private int basesDead; /* Return to LZ Stuff */ public BOOL retLZFlag; //must be set to have any affect public SOUND retLZSnd; //audio to play public INTMESSAGE retLZBlip; //LZ blip public TEXTSTRING retLZMsg; //text message "Return to LZ" /* 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[11], factAssXY[11], factTimeGo[11]; public int factRegionGo[11], factTempMin[11], factTempMax[11]; public int factEvery[11]; private BOOL factFlagGo[11]; //stores whether producing or not private int factTime[11]; //store count for next production /* LISTS OF STUFF (INDEXED BY ARRAY) */ public STRUCTURE structures[15]; public FEATURE features[10]; public DROID droids[10]; public TEMPLATE templates[20]; public int coordsX[20], coordsY[20]; 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 lostSnd; //mission lost public SOUND attackSnd1; //Base Under Attack Sound public SOUND baseSnd[5]; //base detected/dead public SOUND transSnd; //enemy transport landing public SOUND LZComp, LZClear; public int LZRange; /* General variables */ private int count, count2, count3; //for while loops private DROID testDroid, newDroid; private STRUCTURE newDroidFactory; //new droid built private int newDroidFactoryIndex; //for phantom factories private int countBriefs, temp, temp1, temp2, tempX, tempY; private int countVideos; 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! private FEATURE feature; //for building oil derricks on oil resources /* Trucks stuff */ public BOOL trucksOn; //won't work without this set to TRUE!!! public FEATURESTAT oilRes; public int truckRange, defRange; public int numDefences, numToDefend, maxDefence; //defences to build public STRUCTURESTAT defences[5], toDefend[5]; private BOOL boolResult, truckFlag; private GROUP truckGroup[2]; /* Threat Stuff */ public int threatLight, threatMedium, threatHeavy, threatRange; /* ******************** */ /* Triggers */ /* ******************** */ /* //triggers doubled (where possible) for PSX to reduce slowdown trigger winTrig (artCollected >= victoryArt, 50); trigger lostTrig (every, 50); //(not anyDroidsLeft(player), 25); trigger objTrig (every, 30); trigger artTrig (every, 20); trigger baseTrig (every, 34); trigger nextLevTrig (every, 38); trigger gameLostTrig (every, 40); trigger checkGroupsTrig (every, 70); //every 4 seconds trigger wayGroupsTrig (every, 214); //every 10ish secs seconds (so don't get clogging!) trigger sectorGroupsTrig(every, 150); //every 8 seconds trigger attackGroupsTrig(every, 166); //every 8 seconds trigger targetGroupsTrig(every, 86); //every 4 seconds trigger regionGroupsTrig(every, 22); //every second trigger timeGroupsTrig (every, 103); //every 10 seconds (made different so don't get clogging!) trigger updateEnemyTrig (every, 42); //every 2 seconds trigger factoryProdTrig (every, 97); //every 10 seconds (uses factTime to count this period and factEvery to trigger) trigger droidBuiltTrig (wait, 1); //very quickly trigger vidEndTrig (CALL_VIDEO_QUIT); trigger transLandedTrig (CALL_TRANSPORTER_LANDED, transGroup, enemy[transGroupPlayer]); trigger transGone1Trig (CALL_TRANSPORTER_OFFMAP, enemy[transGroupPlayer]); trigger buildDerrickTrig(every, 200); //every 20 seconds trigger buildDefencesTrig(every, 205); //every 20 seconds trigger checkTrucksTrig (every, 290); trigger checkLZTrig (every, 70); //for compromise/clear trigger threatGroupsTrig(every, 194); //for threat analysis */ trigger winTrig (artCollected >= victoryArt, 25); trigger lostTrig (every, 25); //(not anyDroidsLeft(player), 25); trigger objTrig (every, 15); trigger artTrig (every, 10); trigger baseTrig (every, 17); trigger nextLevTrig (every, 19); trigger gameLostTrig (every, 20); trigger checkGroupsTrig (every, 35); //every 4 seconds trigger wayGroupsTrig (every, 107); //every 10ish secs seconds (so don't get clogging!) trigger sectorGroupsTrig(every, 41); //every 4 //8 seconds trigger attackGroupsTrig(every, 45); //every 4 //8 seconds trigger targetGroupsTrig(every, 43); //every 4 seconds trigger regionGroupsTrig(every, 11); //every second trigger timeGroupsTrig (every, 100); //every 10 seconds (made different so don't get clogging!) trigger updateEnemyTrig (every, 21); //every 2 seconds trigger factoryProdTrig (every, 97); //every 10 seconds (uses factTime to count this period and factEvery to trigger) trigger droidBuiltTrig (wait, 1); //very quickly trigger vidEndTrig (CALL_VIDEO_QUIT); trigger transLandedTrig (CALL_TRANSPORTER_LANDED, transGroup, enemy[transGroupPlayer]); trigger transGone1Trig (CALL_TRANSPORTER_OFFMAP, enemy[transGroupPlayer]); trigger buildDerrickTrig(every, 200); //every 20 seconds trigger buildDefencesTrig(every, 205); //every 20 seconds trigger checkTrucksTrig (every, 290); trigger checkLZTrig (every, 35); //for compromise/clear trigger threatGroupsTrig(every, 97); //for threat analysis trigger RTLZStart(wait,0); trigger RTLZFreq(every,300); /* ******************** */ /* Events */ /* ******************** */ /* Declared Events */ event briefings; event wonYetEvnt; event lostYetEvnt; event timeUp; event droidBuilt; event transLanded; event transGone1; event buildDerrick; event checkTrucks; event LZ_OK; event LZNoGo; event periodicRTLZ; /* Initialisation */ event start(CALL_GAMEINIT) { randomiseSeed(); //set scroll limits // setScrollParams(scrollX1, scrollY1, scrollX2, scrollY2); //centre view centreViewPos(centreX, centreY); //more flexible alliance system createAlliance(player, alliancePlayer); count = 0; while (count < numEnemies) { createAlliance(enemy[count], allianceEnemy[count]); count = count + 1; } //set radar zoom level setRadarZoom(zoomLevel); //set LZ and no go areas - HAS to be done BEFORE FlyTransportersIn initAllNoGoAreas(); count = 0; while (count < numLZ) { setNoGoArea(LZX[count] - 1, LZY[count] - 1, LZX[count] + 1, LZY[count] + 1, count); count = count + 1; } //call in transport flyTransporterIn(player, transX[0], transY[0], false); setTransporterExit(player, transX[1], transY[1]); //set enemy transports if applicable count = 0; while (count < numEnemies) { if (entryX[count] != 0) //use entry exit as flag for need enemy transports { transportDroid[count] = addDroidToMissionList(transporter, enemy[count]); } count = count + 1; } //transGroupPlayer = 1; //make sure not 0!! since will control player's units if (timeLimit != 0) //to cope with map expansions after sub maps!!! { setMissionTime(timeLimit); } //set transport time if (not reinfOff) { setReinforcementTime(ReinforceTime); } //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; } //disable time fail if desired if (noTimeLimit) { setEventTrigger(timeUp, inactive); } //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 enemy players health retreat settings count = 0; while (count < numEnemies) { if (healthRetreat[count] > 0) { setRetreatHealth(enemy[count], healthRetreat[count]); setRetreatPoint(enemy[count], healthRetreatX[count], healthRetreatY[count]); } count = count + 1; } //setup groups count = 0; while (count < numGroups) { if (grpRegion[count] >= 0) { groupAddArea(grpGroup[count], enemy[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_SCOUT, tempX, tempY); //changed to SCOUT 21/01/99 } } //link to sensors for IDF groups (same index!) if (grpType[count] == -1) { orderGroupObj(grpGroup[count], DORDER_FIRESUPPORT, droids[count]); } count = count + 1; } //set time = 0 factories going count = 0; while (count < numFactories) { //set assembly points, if desired if ((factAssXY[count] != -1) and (factID[count] >= 0)) { 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; } //NEW! use trucks given as droids for each enemy //Now done after groups set up so can pull them out of existing groups if necessary! if (trucksOn) { //playSound(lostSnd, player); //test count = 0; while (count < numEnemies) { initGetFeature(oilRes, enemy[count], enemy[count]); // setup oil resource search for each enemy, so doesn't screw up! count = count + 1; } count = 0; while (droids[count] != NULLOBJECT) { if (droids[count].droidType == DROID_CONSTRUCT) { //found truck, now find owner count2 = 0; while (count2 < numEnemies) { if (droids[count].player == enemy[count2]) { groupAddDroid(truckGroup[count2], droids[count]); } count2 = count2 + 1; } } count = count + 1; } setEventTrigger (checkTrucks, checkTrucksTrig); } //END of find trucks //allow win/lose checks setEventTrigger(wonYetEvnt, winTrig); setEventTrigger(lostYetEvnt, lostTrig); //allow LZ compromised checks; if (ReinforceTime < 0) { setEventTrigger(LZNoGo,inactive); //disable checks } //default LZRange if (LZRange == 0) { LZRange = 768; //6 tiles radius if not specified } //play any video requirements before the briefings if (numVideos > 0) { playVideo(video[0], videoText[0]); countVideos = 1; //allow next video or next briefing setEventTrigger(briefings, vidEndTrig); } else { //play mission brief(s) if (numBriefs > 0) { if (briefVal[0] < 2) //cope with don't play immediately { addMessage(brief[0], MISS_MSG, 0, true); setEventTrigger(briefings, vidEndTrig); //allow next one } else { addMessage(brief[0], MISS_MSG, 0, false); if (countBriefs >= numBriefs) //last briefing? { setEventTrigger(briefings, inactive); } } countBriefs = 1; } } } event briefings(inactive) { //any more videos to play? if (countVideos < numVideos) { playVideo(video[countVideos], videoText[countVideos]); countVideos = countVideos + 1; } else { //move on to briefings if (countBriefs > 0) { if (briefVal[countBriefs - 1] == 0) //check to see if needs removing { removeMessage(brief[countBriefs - 1], MISS_MSG, 0); } } if (countBriefs >= numBriefs) //last briefing? { setEventTrigger(briefings, inactive); } if (countBriefs < numBriefs) //add next brief { if (briefVal[countBriefs] < 2) //cope with don't play immediately { addMessage(brief[countBriefs], MISS_MSG, 0, true); } else { addMessage(brief[countBriefs], MISS_MSG, 0, false); } countBriefs = countBriefs + 1; } } } /* Base Under Attack */ event baseHit(CALL_STRUCT_ATTACKED, selectedPlayer, ref hitStruc, ref attackerObj) { if (t >= 20) { t=0; if (hitStruc != NULLOBJECT) { playSoundPos(attackSnd1, selectedPlayer, hitStruc.x, hitStruc.y, hitStruc.z); //show position if still alive } else { playSound(attackSnd1, selectedPlayer); } } } 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 now don't need detected wav } if (artFlag[count] == 2) { if (droidInRange(player, artX[count], artY[count], artRange)) { artCollected = artCollected + 1; artFlag[count] = 3; //playSound(artSnd2, player); 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, enemy[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) { //playSound(baseSnd[baseWav1[count]], player); //tricky one since don't have coords! Use middle of region?? playSoundPos(baseSnd[baseWav1[count]], player, (regionsX1[baseRegion[count]] + regionsX2[baseRegion[count]]) / 2, (regionsY1[baseRegion[count]] + regionsY2[baseRegion[count]]) / 2, 0); } baseFlag[count] = 1; } } if (baseFlag[count] == 1) { if (numStructsButNotWallsInArea(enemy[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) { //playSound(baseSnd[baseWav2[count]], player); //tricky one since don't have coords! Use middle of region?? playSoundPos(baseSnd[baseWav2[count]], player, (regionsX1[baseRegion[count]] + regionsX2[baseRegion[count]]) / 2, (regionsY1[baseRegion[count]] + regionsY2[baseRegion[count]]) / 2, 0); } removeMessage(baseMsg[count], PROX_MSG, player); killStructsInArea(enemy[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(enemy[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(); pause(20); //increased to allow all audio before won // give all research count = 0; while (count < numArt) { enableResearch(artComp[count], 0); count = count +1; } //End game or next level if (lastLev) { gameOver(true); //finished game // Could call this instead with the message to play if thats what you want. // gameOverMessage(winMsg, MISS_MSG, 0, true); } else { startMission(CAMP_EXPAND, NextLev); //load next level } setEventTrigger(nextLevEvnt, inactive); } //skip to end of level event cheatEvnt(CALL_MISSION_START) //cheat button ctrl M { //special cheat destroys all enemy stuff /* DONE IN CODE NOW!! (AT LEAST ON PSX) count = 0; while (count < numEnemies) { count2 = 0; while (count2 < 20) { killStructsInArea(enemy[count], count2, scrollX1 * 128, scrollY1 * 128, scrollX2 * 128, scrollY2 * 128, FALSE, FALSE ); count2 = count2 + 1; } //forceDamageObject(droids[0], 25); //vanishUnit(droids[0]); // //remove enemy droids (no explosion) groupAddArea(grpGroup[0], enemy[count], scrollX1 * 128, scrollY1 * 128, scrollX2 * 128, scrollY2 * 128); initIterateGroup(grpGroup[0]); count2 = 0; while (count2 < grpGroup[0].members) { droids[0] = iterateGroup(grpGroup[0]); vanishUnit(droids[0]); count2 = count2 + 1; } // count = count + 1; } */ //temporarily disable next level trigger, if need to check victory conditions setEventTrigger(nextLevEvnt, nextLevTrig); setEventTrigger(cheatEvnt, inactive); } event gameLost(inactive) { // addMessage(endMsg, MISS_MSG, 0, true); // pause(10); // gameOver(false); gameOverMessage(endMsg, MISS_MSG, 0, false); setEventTrigger(gameLost, inactive); } event lostYetEvnt(inactive) //triggered on (every, 25) now, set at end of start event { temp2 = 0; //stores number of conditions met //all player stuff dead (ALWAYS LOSE!) if ((not anyDroidsLeft(player)) and (not anyStructButWallsLeft(player))) { temp2 = 1; } //all group index fail[0] at region index fail[1]? if ((fail[0] != -1) and (fail[1] != -1)) { /* DON'T use group to check (use individual droid) //now checks to see group not dead, and mid point is within region if (grpGroup[fail[0]].members != 0) { if ((grpGroup[fail[0]].x > regionsX1[fail[1]]) and (grpGroup[fail[0]].x < regionsX2[fail[1]]) and (grpGroup[fail[0]].y > regionsY1[fail[1]]) and (grpGroup[fail[0]].y < regionsY2[fail[1]])) { temp2 = 1; } } */ //now checks for a single droid referenced by fail[0] as index into droids[] if (droids[fail[0]] != NULLOBJECT) { if ((droids[fail[0]].x > regionsX1[fail[1]]) and (droids[fail[0]].x < regionsX2[fail[1]]) and (droids[fail[0]].y > regionsY1[fail[1]]) and (droids[fail[0]].y < regionsY2[fail[1]])) { playSound(failSnd, player); //let player know! addConsoleText(failMsg, player); //text version temp2 = 1; } } } /* might not need? NOT TESTED!!! //all units dead? if ((fail[2] != -1) and (not anyDroidsLeft(player))) { temp2 = 1; } //all structures dead? if ((fail[3] != -1) and (not anyStructButWallsLeft(player))) { temp2 = 1; } //certain structure gone???? */ //cope with failure set in other scripts if (linkFail and extraFailFlag) { temp2 = 1; } if (temp2 == 1) { 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(inactive) //triggered on (artCollected >= victoryArt) set at end of start event { //check for extra victory conditions set in another script if ((linkVictory and extraVictoryFlag) or (not linkVictory)) { 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] != -1) { 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 number of objectives reached if (victory[2] != -1) { count = 0; temp = 0; while (count < victory[2]) //check from objective 0 to # { if (objectiveFlag[count]) { temp = temp + 1; } count = count + 1; } if (temp >= victory[2]) { temp2 = temp2 + 1; } } //check number of bases destroyed if (victory[3] != -1) { count = 0; temp = 0; while (count < victory[3]) //check from base 0 to # { if (baseFlag[count] == 2) { temp = temp + 1; } count = count + 1; } if (temp >= victory[3]) { temp2 = temp2 + 1; } } //check ALL player vehicles in specific REGION (eg LZ) if (victory[1] != -1) { //temp = numDroidsInArea(player, scrollX1 * 128, scrollY1 * 128, scrollX2 * 128, scrollY2 * 128); temp = 1 + (9 * getDroidCount(player) / 10); //tot number of droids for player on map (NOW 90%!!) if (temp <= numDroidsInArea(player, regionsX1[victory[1]], regionsY1[victory[1]], regionsX2[victory[1]], regionsY2[victory[1]])) { if (temp != 0) { temp2 = temp2 + 1; } } else if ((retLZFlag) and (temp2 == numVictory - 1)) //if getting to region is last victory, give sound and blip { retLZFlag = FALSE; //turn off checks // playSound(retLZSnd, player); //tell player to return addMessage(retLZBlip, PROX_MSG, player, false); //give LZ blip // addConsoleText(retLZMsg, player); setEventTrigger(periodicRTLZ,RTLZStart); } } //next check goes here! //now check if number of victory conditions met if (temp2 == numVictory) //victory reached? { setEventTrigger(lostYetEvnt, inactive); setEventTrigger(timeUp, inactive); setEventTrigger(nextLevEvnt, nextLevTrig); setEventTrigger(wonYetEvnt, inactive); } } } event periodicRTLZ(inactive) { playSound(retLZSnd, player); //tell player to return showConsoleText(retLZMsg, player); setEventTrigger(periodicRTLZ,RTLZFreq); } /* 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].health * grpGroup[count].members >= healthRetreat[grpPlayer[count]] + ((grpGroup[count].members - 1) * 100)) or (healthRetreat[grpPlayer[count]] == 0)) and (idleGroup(grpGroup[count]) >= grpGroup[count].members/2)) { 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]]); //Changed to SCOUT 21/01/99 //orderGroupLoc(grpGroup[count], DORDER_MOVE, coordsX[grpPosCurrent[count]], coordsY[grpPosCurrent[count]]); } } } count = count + 1; } } /* THREAT ANALYSIS */ event threatGroups(threatGroupsTrig) { //traceOn(); count = 0; while (count < numGroups) { if (grpMorale[count] > 0) { /* temp1 = getThreatInArea(enemy[grpPlayer[count]], player, grpGroup[count].x - threatRange, grpGroup[count].y - threatRange, grpGroup[count].x + threatRange, grpGroup[count].y + threatRange, 0, 0, threatHeavy, TRUE); temp2 = getThreatInArea(player, enemy[grpPlayer[count]], grpGroup[count].x - threatRange, grpGroup[count].y - threatRange, grpGroup[count].x + threatRange, grpGroup[count].y + threatRange, 0, 0, threatHeavy, TRUE); */ temp1 = getThreatInArea(enemy[grpPlayer[count]], player, grpGroup[count].x - threatRange, grpGroup[count].y - threatRange, grpGroup[count].x + threatRange, grpGroup[count].y + threatRange, threatLight, threatMedium, threatHeavy, TRUE); temp2 = getThreatInArea(player, enemy[grpPlayer[count]], grpGroup[count].x - threatRange, grpGroup[count].y - threatRange, grpGroup[count].x + threatRange, grpGroup[count].y + threatRange, threatLight, threatMedium, threatHeavy, FALSE); if (temp1 > temp2) //does player have bigger looking force than me? { //playSound(lostSnd,0); //test initIterateGroup(grpGroup[count]); testDroid = iterateGroup(grpGroup[count]); //must check to see if group not empty! if (testDroid != NULLOBJECT) { orderDroid(testDroid, DORDER_RUN); //only need to order one (rest should follow?) } } } count = count + 1; } //traceOff(); } /* SCOUTS AND TARGET FINDING */ 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) and (not runOffFlag)) { 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]]); /* No longer allow groups that STOP at last waypoint to continue once retreated if ((grpPosType[count] == 0)) // and (grpPosStart[count] != grpPosCurrent[count])) //stop and not 1st waypoint { //need to mark that current waypoint not yet reached for STOP type grpPosCurrent[count] = grpPosCurrent[count] - grpPosStep[count]; //back to last one } */ } 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 ((grpGroup[count].health * grpGroup[count].members >= healthRetreat[grpPlayer[count]] + ((grpGroup[count].members - 1) * 100)) or (healthRetreat[grpPlayer[count]] == 0)) //health OK (Cam3 NEXUS) 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 { // grpPlayer[count] is now index to enemy[], so no need to check temp1 = grpPlayer[count]; } if ((grpType[count] == 3) and (targetCount[temp1] > 0)) //any targets for attack groups { //new targetting system //find a target in nearby vicinity resetStructTargets(); if (random(100) < 10) { setStructTarPref(ST_WALL); //pick walls occassionally } hitStruc = structTargetInArea(player, grpPlayer[count], grpGroup[count].x - targetRange, grpGroup[count].y - targetRange, grpGroup[count].x + targetRange, grpGroup[count].y + targetRange); if (hitStruc != NULLOBJECT) { orderGroupObj(grpGroup[count], DORDER_ATTACK, hitStruc); } else //go to new target { 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]) { /* OLD SYSTEM 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))) */ //New system //find a target in area resetStructTargets(); setStructTarPref(ST_WALL); //include walls always hitStruc = structTargetInArea(player, grpPlayer[count], targetX[count][temp] - targetRange, targetY[count][temp] - targetRange, targetX[count][temp] + targetRange, targetY[count][temp] + targetRange); if (hitStruc == NULLOBJECT) { 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); /* OLD SYSTEM //make sure correct player, and targets exist before logging a new one if ((grpPlayer[count2] == count) and (targetCount[count] < targetMax) and ((temp1 > 0) or (temp2 > 0))) //(objectInRange(player, grpGroup[count2].x, grpGroup[count2].y, targetRange))) */ //New System //find a target in area resetStructTargets(); if (random(100) < 10) { setStructTarPref(ST_WALL); //pick walls occassionally } hitStruc = structTargetInArea(player, grpPlayer[count2], grpGroup[count2].x - targetRange, grpGroup[count2].y - targetRange, grpGroup[count2].x + targetRange, grpGroup[count2].y + targetRange); if ((targetCount[count] < targetMax) and (hitStruc != NULLOBJECT)) { //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 more objects than scouts, run away!!! //if ((grpGroup[count2].members <= temp1 + temp2) and (grpType[count2] == 2)) //new way of running away (should be checking threat, but not yet) temp = numDroidsInArea(enemy[grpPlayer[count2]], grpGroup[count2].x - targetRange, grpGroup[count2].y - targetRange, grpGroup[count2].x + targetRange, grpGroup[count2].y + targetRange); if ((temp <= temp1 + temp2) and (grpType[count2] == 2) and (grpMorale[count2] > 0)) { //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) and ((idleGroup(grpGroup[count2]) >= grpGroup[count2].members / 2) or (random(100) < 5))) //only if not busy or small chance { //orderGroup(grpGroup[count2], DORDER_STOP); //stay where you are (and hopefully kill stuff) if scout group orderGroupObj(grpGroup[count2], DORDER_ATTACK, hitStruc); } targetCount[count] = targetCount[count] +1; } count2 = count2 +1; } count = count +1; } } event factoryProdEvnt(factoryProdTrig) { count = 0; while (count < numFactories) { //switched on? if (factFlagGo[count]) { factTime[count] = factTime[count] + 1; //time to do stuff? if (factTime[count] >= factEvery[count]) { //factTime[count] = 0; //now only done if can actually produce //normal factory? if (factID[count] >= 0) { //turn off dead factories if (structures[factID[count]] == NULLOBJECT) { factFlagGo[count] = FALSE; factEvery[count] = 32767; //make next time very large ~100 hours } //not producing anything? else 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); factTime[count] = 0; //reset time count } } //phantom factory (including transports) else if (factID[count] < 0) { //do actual adding of droids and resetting of FactTime in droidBuilt event //just set trigger and factory number here! newDroidFactoryIndex = count; newDroid = NULLOBJECT; newDroidFactory = NULLOBJECT; //so as not to confuse with a proper factory! setEventTrigger(droidBuilt, droidBuiltTrig); } } } count = count + 1; } } event droidBuilt(inactive) //triggered by later callbacks { //find factory number temp2 = 0; //flagged if group match found //temp = -1; //in case not found temp = -2; //in case not found (so doesn't use a droidfactory from another script) if (newDroidFactory != NULLOBJECT) { newDroidFactoryIndex = - 1; //not a phantom factory count = 0; while (count < numFactories) { if (factID[count] >= 0) { if (newDroidFactory == structures[factID[count]]) { //this one wrong???? //temp = factID[count]; //count; //use factory index, not structure index temp = count; //use factory index, not structure index } } count = count +1; } } else if (newDroidFactoryIndex >= 0) //deal with phantom factory { temp = newDroidFactoryIndex; } //check thru groups to reinforce count = 0; //cope with trucks being built if (newDroid != NULLOBJECT) //don't bother if phantom factory { if (newDroid.droidType == DROID_CONSTRUCT) { count2 = 0; while (count2 < numEnemies) { if (newDroid.player == enemy[count2]) { groupAddDroid(truckGroup[count2], newDroid); } count2 = count2 + 1; } count = numGroups; //skip next bit! } //cope with sensors being built and IDF groups existing else if (newDroid.droidType == DROID_SENSOR) { //now find 1st dead sensor droid slot that corresponds to an IDF group count2 = 0; while (count2 < numGroups) { if (grpType[count2] == -1) { //found an IDF group if (droids[count2] == NULLOBJECT) { droids[count2] = newDroid; orderGroupObj(grpGroup[count2], DORDER_FIRESUPPORT, droids[count2]); count2 = numGroups; //end search } } count2 = count2 + 1; } //count = numGroups; //Don't skip next bit! (needs to go into a group, unlike Trucks!) } } //end of trucks bit while (count < numGroups) { if (((temp == grpFactory[count]) or ((grpFactory[count] == -1) and (temp != -2))) //got match, or any factory in this script OK? and (grpGroup[count].members < grpIdealSize[count])) //and needs reinforcing? { //add to reinforcement group if (newDroid != NULLOBJECT) { groupAddDroid(grpReinforce[count], newDroid); } else if (newDroidFactoryIndex >= 0) //deal with phantom factory { //deal with off edge if (factID[newDroidFactoryIndex] == - 1) { factTime[newDroidFactoryIndex] = 0; //reset time count for phantom factory count2 = 0; while (count2 < 1 + factTempMax[newDroidFactoryIndex] - factTempMin[newDroidFactoryIndex]) { temp1 = factTempMin[newDroidFactoryIndex] + count2; temp2 = count2; //create more for lower template numbers, less for higher! while (temp2 < 1 + factTempMax[newDroidFactoryIndex] - factTempMin[newDroidFactoryIndex]) { newDroid = addDroid(templates[temp1], coordsX[factAssXY[newDroidFactoryIndex]], coordsY[factAssXY[newDroidFactoryIndex]], enemy[grpPlayer[count]]); if (newDroid != NULLOBJECT) { //cope with trucks if (newDroid.droidType == DROID_CONSTRUCT) { groupAddDroid(truckGroup[grpPlayer[count]], newDroid); } //cope with sensors else if (newDroid.droidType == DROID_SENSOR) { //now find 1st dead sensor droid slot that corresponds to an IDF group count3 = 0; while (count3 < numGroups) { if (grpType[count3] == -1) { //found an IDF group if (droids[count3] == NULLOBJECT) { droids[count3] = newDroid; orderGroupObj(grpGroup[count3], DORDER_FIRESUPPORT, droids[count3]); count3 = numGroups; //end search } } count3 = count3 + 1; } groupAddDroid(grpReinforce[count], newDroid); } else { groupAddDroid(grpReinforce[count], newDroid); } } temp2 = temp2 + 1; } count2 = count2 + 1; } } //deal with transport if not on map else if ((factID[newDroidFactoryIndex] == - 2) and (not transOnMap[grpPlayer[count]])) { factTime[newDroidFactoryIndex] = 0; //reset time count for phantom factory //need to check LZ has defences, otherwise turn off this phantom factory temp1 = factAssXY[newDroidFactoryIndex]; if (numStructsInArea(enemy[grpPlayer[count]], (LZX[temp1] - 4) * 128, (LZY[temp1] - 4) * 128, (LZX[temp1] + 4) * 128, (LZY[temp1] + 4) * 128) == 0) { //playSound(lostSnd, player); //test factFlagGo[newDroidFactoryIndex] = FALSE; factEvery[newDroidFactoryIndex] = 32767; //make next time very large ~100 hours } else { setNoGoArea(LZX[factAssXY[newDroidFactoryIndex]] - 1, LZY[factAssXY[newDroidFactoryIndex]] - 1, LZX[factAssXY[newDroidFactoryIndex]] + 1, LZY[factAssXY[newDroidFactoryIndex]] + 1, enemy[grpPlayer[newDroidFactoryIndex]]); //make sure got position in world coords of this LZ for playSound enemyLZX = LZX[factAssXY[newDroidFactoryIndex]] * 128; enemyLZY = LZY[factAssXY[newDroidFactoryIndex]] * 128; count2 = 0; while (count2 < 1 + factTempMax[newDroidFactoryIndex] - factTempMin[newDroidFactoryIndex]) { temp1 = factTempMin[newDroidFactoryIndex] + count2; temp2 = count2; //create more for lower template numbers, less for higher! while (temp2 < 1 + factTempMax[newDroidFactoryIndex] - factTempMin[newDroidFactoryIndex]) { newDroid = addDroidToMissionList(templates[temp1], enemy[grpPlayer[count]]); if (newDroid != NULLOBJECT AND transportDroid[grpPlayer[count]] != NULLOBJECT) { addDroidToTransporter(transportDroid[grpPlayer[count]], newDroid); } temp2 = temp2 + 1; } count2 = count2 + 1; } //call in transport setTransporterExit(enemy[grpPlayer[count]], exitX[grpPlayer[count]], exitY[grpPlayer[count]]); flyTransporterIn(enemy[grpPlayer[count]], entryX[grpPlayer[count]], entryY[grpPlayer[count]], false); transOnMap[grpPlayer[count]] = TRUE; transGroupIndex[grpPlayer[count]] = count; //store for when transport lands transGroupPlayer = grpPlayer[count]; //may mess up multiple enemies having transports? setEventTrigger(transLanded, transLandedTrig); setEventTrigger(transGone1, transGone1Trig); } } } //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 /* NEW to handle zero size groups at start with morale settings */ //set morale again so recalculates size! if (grpMorale[count] >= 0) { setGroupRetreatForce(grpGroup[count], grpMorale[count]); } /* END of NEW */ } //if ideal size, add to main group! else if (((grpGroup[count].members + grpReinforce[count].members) >= grpIdealSize[count]) or ((grpReinforce[count].members) >= 8)) //hack to make edge factories work { groupAddGroup(grpGroup[count], grpReinforce[count]); //grpPosCurrent[count] = grpPosMin[count]; //test for now so can see if added to group } //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) { newDroidFactoryIndex = - 1; //not a phantom factory setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt2(CALL_NEWDROID, 2, ref newDroid, ref newDroidFactory) { newDroidFactoryIndex = - 1; //not a phantom factory setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt3(CALL_NEWDROID, 3, ref newDroid, ref newDroidFactory) { newDroidFactoryIndex = - 1; //not a phantom factory setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt4(CALL_NEWDROID, 4, ref newDroid, ref newDroidFactory) { newDroidFactoryIndex = - 1; //not a phantom factory setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt5(CALL_NEWDROID, 5, ref newDroid, ref newDroidFactory) { newDroidFactoryIndex = - 1; //not a phantom factory setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt6(CALL_NEWDROID, 6, ref newDroid, ref newDroidFactory) { newDroidFactoryIndex = - 1; //not a phantom factory setEventTrigger(droidBuilt, droidBuiltTrig); } event droidBuilt7(CALL_NEWDROID, 7, ref newDroid, ref newDroidFactory) { newDroidFactoryIndex = - 1; //not a phantom factory setEventTrigger(droidBuilt, droidBuiltTrig); } event transLanded(inactive) //trigger set when transport called { temp = transGroupIndex[transGroupPlayer]; //to make easier to read //test sound for now //playSound(transSnd, player); //Enemy Transport Landing //need to look at enemy LZ??? playSoundPos(transSnd, player, enemyLZX, enemyLZY, 0); //check for trucks in transGroup initIterateGroup(transGroup); newDroid = iterateGroup(transGroup); while(newDroid != NULLOBJECT) { if (newDroid.droidType == DROID_CONSTRUCT) { groupAddDroid(truckGroup[transGroupPlayer], newDroid); } //check for sensors as well else if (newDroid.droidType == DROID_SENSOR) { //now find 1st dead sensor droid slot that corresponds to an IDF group count2 = 0; while (count2 < numGroups) { if (grpType[count2] == -1) { //found an IDF group if (droids[count2] == NULLOBJECT) { droids[count2] = newDroid; orderGroupObj(grpGroup[count2], DORDER_FIRESUPPORT, droids[count2]); count2 = numGroups; //end search } } count2 = count2 + 1; } } newDroid = iterateGroup(transGroup); //point to next one } //end of truck/sensor check groupAddGroup(grpReinforce[temp], transGroup); //might just want to add directly to grpGroup? //if group dead, add to group and reset starting sector? if (grpGroup[temp].members == 0) { grpPosCurrent[temp] = grpPosMin[temp]; //go back to min sector if starting group from scratch if ((grpType[temp] < 2) and (grpPosStart[temp] >= 0)) //give first orders unless scouts, since use sectors, or no waypoints defined { orderGroupLoc(grpReinforce[temp], DORDER_SCOUT, coordsX[grpPosCurrent[temp]], coordsY[grpPosCurrent[temp]]); } groupAddGroup(grpGroup[temp], grpReinforce[temp]); //set back to start sector...? /* NEW to handle zero size groups at start with morale settings */ //set morale again so recalculates size! if (grpMorale[temp] >= 0) { setGroupRetreatForce(grpGroup[temp], grpMorale[temp]); } /* END of NEW */ } //if >= ideal size add to group if ((grpGroup[temp].members + grpReinforce[temp].members) >= grpIdealSize[temp]) { if ((grpType[temp] < 2) and (grpPosStart[temp] >= 0)) //give first orders unless scouts, since use sectors, or no waypoints defined { orderGroupLoc(grpReinforce[temp], DORDER_SCOUT, coordsX[grpPosCurrent[temp]], coordsY[grpPosCurrent[temp]]); } groupAddGroup(grpGroup[temp], grpReinforce[temp]); } setEventTrigger(transLanded, transLandedTrig); } //allow next transport!! event transGone1(inactive) { transOnMap[grpPlayer[transGroupPlayer]] = FALSE; } 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) and (factTime[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; factTime[count] = factEvery[count]; //allow to produce straight away! } } 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]) and (factTime[count] == 0)) { factFlagGo[count] = TRUE; //set factory to produce factTime[count] = factEvery[count]; //allow to produce straight away! } count = count + 1; } } event enemyBaseHit(CALL_STRUCT_ATTACKED, enemy[enemyCount], ref hitStruc, ref attackerObj) { //playSound(attackSnd1, enemy[enemyCount]); //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] == 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; } } //NEW //Make specified trucks (defined as droids[]) build derricks on visible oil resources event buildDerrick(inactive) //only used if trucks found! { count = 0; while (count < numEnemies) { feature = getFeature(enemy[count]); // find unoccupied oil resource that's been seen by this enemy if(feature != NULLOBJECT) { initIterateGroup(truckGroup[count]); // find idle droids in build group. testDroid = iterateGroup(truckGroup[count]); while(testDroid != NULLOBJECT) { if ((testDroid.order == DORDER_NONE) or (testDroid.order == DORDER_RTB)) { tempX = feature.x; tempY = feature.y; orderDroidStatsLoc(testDroid, DORDER_BUILD, strucStat[1], tempX, tempY); //build a derick testDroid = NULLOBJECT; } else { testDroid = iterateGroup(truckGroup[count]); } } } else // feature is null { initGetFeature(oilRes, enemy[count], enemy[count]); // start again next time. } count = count + 1; } } //build defences around nearby defenceless structures event buildDefences(inactive) //only used if trucks found! { count = 0; while (count < numEnemies) { initIterateGroup(truckGroup[count]); // find idle droids in build group. testDroid = iterateGroup(truckGroup[count]); while(testDroid != NULLOBJECT) //NB: need to be careful don't end up in endless loop! { if ((testDroid.order == DORDER_NONE) or (testDroid.order == DORDER_RTB)) { //spare truck found, so check nearby for defendable structures count2 = 0; while (count2 < numToDefend) //list of structurestats to defend { hitStruc = structureBuiltInRange(toDefend[count2], testDroid.x, testDroid.y, truckRange, enemy[count]); if (hitStruc != NULLOBJECT) { if ((numStructsByTypeInArea(enemy[count], REF_DEFENSE, hitStruc.x - defRange, hitStruc.y - defRange, hitStruc.x + defRange, hitStruc.y + defRange) < maxDefence) and (numDefences > 0)) { tempX = hitStruc.x; tempY = hitStruc.y; temp = random(numDefences); boolResult = pickStructLocation(defences[temp], ref tempX, ref tempY, enemy[count]); if (boolResult) { orderDroidStatsLoc(testDroid, DORDER_BUILD, defences[temp], tempX, tempY); //build a defence testDroid = NULLOBJECT; count2 = numToDefend; //break loops early } } } count2 = count2 + 1; } if ((testDroid != NULLOBJECT) and (random(100) < 50)) //go back to base if couldn't build { orderDroid(testDroid, DORDER_RTB); // return to base if failed } } if (testDroid != NULLOBJECT) //get next if haven't broken out of loop { testDroid = iterateGroup(truckGroup[count]); } } count = count + 1; } } event checkTrucks(inactive) //can be whatever time necessary now! { //check for switching on trucks if (not truckFlag) { count = 0; while (count < numEnemies) { if (truckGroup[count].members > 0) { truckFlag = TRUE; } count = count + 1; } if (truckFlag) { setEventTrigger(buildDerrick, buildDerrickTrig); setEventTrigger(buildDefences, buildDefencesTrig); } } else //check for switching off trucks { count = 0; temp = 0; while (count < numEnemies) { if (truckGroup[count].members == 0) { temp = temp + 1; } count = count + 1; } if (temp == numEnemies) { //playSound(lostSnd, player); //test truckFlag = FALSE; setEventTrigger(buildDerrick, inactive); setEventTrigger(buildDefences, inactive); } } } /* Old system event sensorTarget(every, 67) { //get some kind of target if there's a sensor droid listed count = 0; temp = 0; while (droids[count] != NULLOBJECT) { if (droids[count].droidType == DROID_SENSOR) { temp = temp + 1; if ((droids[count].order == DORDER_NONE) or (droids[count].order == DORDER_SCOUT)) { //find target (use Structure limits StructureStats for now!!!!) count2 = 0; while (count2 < numStrucStats) { //use range of 1024 for now hitStruc = structureBuiltInRange(strucStat[count2], droids[count].x, droids[count].y, 1024, player); if (hitStruc != NULLOBJECT) { orderDroidObj(droids[count], DORDER_OBSERVE, hitStruc); count2 = numStrucStats; } count2 = count2 + 1; } } } count = count + 1; } if (temp == 0) { setEventTrigger(sensorTarget, inactive); } } */ //Better way of doing this (will attack allsorts of things! event sensorTarget(every, 67) { //get some kind of target if there's a sensor droid listed count = 0; while (droids[count] != NULLOBJECT) { if (droids[count].droidType == DROID_SENSOR) { if ((droids[count].order == DORDER_NONE) or (droids[count].order == DORDER_SCOUT)) { //find a target in area resetStructTargets(); if (random(100) < 10) { setStructTarPref(ST_WALL); //pick walls occassionally } hitStruc = structTargetInArea(player, droids[count].player, droids[count].x - 768, droids[count].y - 768, droids[count].x + 768, droids[count].y + 768); if (hitStruc != NULLOBJECT) { orderDroidObj(droids[count], DORDER_OBSERVE, hitStruc); } } } count = count + 1; } } /* LZ compromised stuff */ event LZNoGo(checkLZTrig) { temp = 0; //check for compromised count = 0; while (count < numEnemies) { //if (objectInArea(enemy[count], (LZX[player] * 128) - LZRange, (LZY[player] * 128) - LZRange, (LZX[player] * 128) + LZRange, (LZY[player] * 128) + LZRange)) if (droidInRange(enemy[count], (LZX[player] * 128), (LZY[player] * 128), LZRange)) { temp = temp + 1; } count = count + 1; } if ((not playerTransOnMap) and (temp > 0)) //make sure transport not already landing! { //check LZ area for enemy structures and/or vehicles (in Trigger) //playSound(LZComp, player); //"LZ Compromised" playSoundPos(LZComp, player, LZX[player] * 128, LZY[player] * 128, 0); //disable transport landing setReinforcementTime(LZ_COMPROMISED_TIME); //MAGIC NUMBER IN HERE!!! //allow check for clear! setEventTrigger(LZ_OK, checkLZTrig); setEventTrigger(LZNoGo, inactive); } } event LZ_OK(inactive) { temp = 0; //check LZ area clear of enemy structures and/or vehicles (not in Trigger) count = 0; while (count < numEnemies) { //if (objectInArea(enemy[count], (LZX[player] * 128) - LZRange, (LZY[player] * 128) - LZRange, (LZX[player] * 128) + LZRange, (LZY[player] * 128) + LZRange)) if (droidInRange(enemy[count], (LZX[player] * 128), (LZY[player] * 128), LZRange)) { temp = temp + 1; } count = count + 1; } if (temp == 0) //clear so do message { //playSound(LZClear, player); //"LZ Clear" playSoundPos(LZClear, player, LZX[player] * 128, LZY[player] * 128, 0); //allow reinforcements now LZ clear setReinforcementTime(ReinforceTime); //(set back to normal) setEventTrigger(LZNoGo, checkLZTrig); setEventTrigger(LZ_OK, inactive); } } event playerTransOn(CALL_TRANSPORTER_REINFORCE) { playerTransOnMap = TRUE; } event playerTransOff(CALL_TRANSPORTER_OFFMAP, player) { playerTransOnMap = FALSE; }