warzone2100/data/script/text/cam2endx.slo

728 lines
21 KiB
Plaintext

//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;
}
}