//SLO file for setting up the Transporter to return and re-fill //Also handles VTOL attacks with no visibility //cam2EndX.SLO //uses copy of genbet.slo plus some modifications! /* ******************** */ /* Declared Variables */ /* ******************** */ /* Next Level stuff */ public LEVEL NextLev; /* 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 transX[2], transY[2]; //done in arrays so don't need to define for non submaps //transX[0] = entryX, transX[1] = exitX /* Briefings */ public int numBriefs, briefVal[5]; public INTMESSAGE brief[5]; public INTMESSAGE endMsg; /* Time Limit */ public INT ReinforceTime, timeLimit; /* 'Globals' */ public int player, enemy[1]; public SOUND lostSnd; //mission lost public TEMPLATE transporter; /* General variables */ private int count, count2; //for while loops private int countBriefs, temp, temp1, temp2, tempX, tempY; private BOOL winFlag; //Starting Tech for Enemy public int numTechs; public RESEARCHSTAT startTech[37]; /* VTOLS */ private int group; private BASEOBJ viewerObj, targetObj; private DROID droid; private int clusterID; public int padPlayer; //VTOL groups and targets public int numVTOL; public int VTOLsize[2], groupX[5], groupY[5]; public TEMPLATE templatesVTOL[2][2]; public int targetObjType[2], startTime[2], everyTime[2]; private GROUP VTOLgroup[2]; private BASEOBJ attackObj[2]; private int attackCluster[2], countTime[2]; // where the vtols return to and vanish public int vanishX,vanishY; public int baseX1, baseY1, baseX2, baseY2; /* Ground forces */ /* 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 private DROID testDroid, newDroid; private STRUCTURE newDroidFactory; //new droid built private int newDroidFactoryIndex; //for phantom factories /*lists */ public TEMPLATE templates[20]; public int coordsX[20], coordsY[20]; /*transports */ public int entryX[2], entryY[2], exitX[2], exitY[2]; //enemy transport entry, exit public SOUND transSnd; //enemy transport 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 /* ******************** */ /* Triggers */ /* ******************** */ trigger gameLostTrig(every, 20); trigger winLoseTrig(every, 5); trigger vidTrig(CALL_VIDEO_QUIT); /* ground forces */ trigger wayGroupsTrig (every, 107); //every 10ish secs seconds (so don't get clogging!) trigger timeGroupsTrig (every, 100); //every 10 seconds (made different so don't get clogging!) trigger factoryProdTrig (every, 97); //every 10 seconds (uses factTime to count this period and factEvery to trigger) trigger droidBuiltTrig (wait, 1); //very quickly trigger transLandedTrig (CALL_TRANSPORTER_LANDED, transGroup, enemy[transGroupPlayer]); trigger transGone1Trig (CALL_TRANSPORTER_OFFMAP, enemy[transGroupPlayer]); /* ******************** */ /* Events */ /* ******************** */ /* Declared Events */ event briefings; event timeUp; event droidBuilt; event transLanded; event transGone1; /* Initialisation */ event start(CALL_GAMEINIT) { //set up so that when Transporter gets to the edge of the map, it will empty and return setDroidsToSafetyFlag(true); randomiseSeed(); //centre view centreViewPos(centreX, centreY); //set scroll limits // setScrollParams(scrollX1, scrollY1, scrollX2, scrollY2); //set radar zoom level setRadarZoom(zoomLevel); //set Mission time limit setMissionTime(timeLimit); //set LZ and no go areas - shouldn't need to do this any more - it is until all NoGoAreas are saved in the save game info //The LZ can now be set up just before FlyTransporterIn() 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; } //give Enemy Starting Tech count = 0; while (count < numTechs) { completeResearch(startTech[count], enemy[0]); count = count + 1; } //place transport addDroid(transporter,(LZX[0] * 128) + 64, (LZY[0] * 128) + 64,player); setTransporterExit(player, transX[1], transY[1]); setReinforcementTime(ReinforceTime); /* VTOLS */ setVTOLReturnPos(padPlayer, vanishX,vanishY); count = 0; while (count < numVTOL) { countTime[count] = startTime[count]; count = count + 1; } /* Ground Forces */ //setup groups count = 0; while (count < numGroups) { grpPosCurrent[count] = grpPosStart[count]; //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]]); } } } count = count + 1; } //set time = 0 factories going count = 0; while (count < numFactories) { 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) { if (briefVal[0] < 2) //cope with don't play immediately { addMessage(brief[0], MISS_MSG, 0, true); } else { addMessage(brief[0], MISS_MSG, 0, false); if (countBriefs >= numBriefs) //last briefing? { setEventTrigger(briefings, inactive); } } countBriefs = 1; } } event briefings(CALL_VIDEO_QUIT) //need to rework this better!! { 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; } } event launched(CALL_LAUNCH_TRANSPORTER) { //allow win if player has launched transport winFlag = TRUE; setEventTrigger(launched, inactive); } //need an event to check all player stuff isn't dead, once got transport taken off CALLBACK //for losing event gameLost(inactive) { // addMessage(endMsg, MISS_MSG, 0, true); // pause(10); // gameOver(false); gameOverMessage(endMsg, MISS_MSG, 0, false); setEventTrigger(gameLost, inactive); } event nextLevEvnt(CALL_START_NEXT_LEVEL) { //need to check if the player has got any transporter's out since this callback will //be called from the code if the transporter is sitting idle and all the player's units are destroyed if (winFlag) { //play outro addMessage(brief[2], MISS_MSG, 0, true); //pause(1); startMission(OFF_KEEP, NextLev); } else { setEventTrigger(gameLost, gameLostTrig); } setEventTrigger(nextLevEvnt, inactive); } //out of time? event timeUp(CALL_MISSION_TIME) { //see if player has 'won' if (winFlag) { //play outro addMessage(brief[2], MISS_MSG, 0, true); //pause(1); //go to next mission //setEventTrigger(nextLevEvnt, winLoseTrig); //this causes it to crash! startMission(OFF_KEEP, NextLev); } else { setEventTrigger(gameLost, gameLostTrig); } setEventTrigger(timeUp, inactive); } event lostYetEvnt(every, 53) { if (not anyDroidsLeft(player)) { if (not anyStructButWallsLeft(player)) { //won or lost? setEventTrigger(lostYetEvnt, inactive); if (winFlag) { //setEventTrigger(nextLevEvnt, winLoseTrig); //this causes it to crash! startMission(OFF_KEEP, NextLev); } else { setEventTrigger(launched,inactive); setEventTrigger(gameLost, gameLostTrig); //waits 2 seconds before ending } } } } /* VTOLS ATTACK */ // do VTOL reinforcements (startTime, everyTime) event addVTOL(every, 107) //every 10secs { group = 0; while (group < numVTOL) { countTime[group] = countTime[group] - 1; if (countTime[group] <= 0) { countTime[group] = everyTime[group]; //set back to every temp = VTOLgroup[group].members; if ((temp == 0) and (attackObj[group] != NULLOBJECT)) // creating a group at the edge of the map { debugBox(100); count = 0; temp = VTOLsize[group] - VTOLgroup[group].members; temp1 = random(5); //choose random start coord while (count < temp) { droid = addDroid(templatesVTOL[group][random(2)], groupX[temp1], groupY[temp1], padPlayer); if (droid != NULLOBJECT) { groupAddDroid(VTOLgroup[group], droid); } count = count + 1; } if (attackObj[group] != NULLOBJECT) { debugBox(101); orderGroupObj(VTOLgroup[group], DORDER_ATTACK, attackObj[group]); } } } group = group + 1; } } event vtolOffMap(CALL_VTOL_OFF_MAP, padPlayer, ref droid) { // vtol has reached the edge of the map - vanish them vanishUnit(droid); } event getTargets(every, 67) { group = 0; while (group < numVTOL) { //check if a group is idle and give a new target if (attackObj[group] == NULLOBJECT) { //find a target in area if (targetObjType[group] == 1) { resetStructTargets(); setStructTarIgnore(ST_WALL); setStructTarPref(ST_FACTORY); setStructTarPref(ST_CYBORG_FACTORY); setStructTarPref(ST_VTOL_FACTORY); setStructTarPref(ST_RESEARCH); setStructTarPref(ST_POWER_GEN); setStructTarPref(ST_HQ); attackObj[group] = structTargetInArea(player, padPlayer, baseX1, baseY1, baseX2, baseY2); } else if (targetObjType[group] == 0) { resetDroidTargets(); setDroidTarIgnore(DT_SUPER_HEAVY); //ignore transport attackObj[group] = droidTargetInArea(player, padPlayer, baseX1, baseY1, baseX2, baseY2); } if (attackObj[group] != NULLOBJECT) { orderGroupObj(VTOLgroup[group], DORDER_ATTACK, attackObj[group]); } } group = group + 1; } } /* Ground Force attacks */ 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 (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; } } 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]) { //phantom factory (including transports) 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 (newDroidFactoryIndex >= 0) //deal with phantom factory { temp = newDroidFactoryIndex; } //check thru groups to reinforce count = 0; 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) { 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) { 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 } //if ideal size, add to main group! else 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 } //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! } event droidBuilt2(CALL_NEWDROID, 2, 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); 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...? } //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; } //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; } }