Here is an improved version of "MissionNetworkBattle05.cpp" which is also known as "Blake's Mission". This derives from LAC Version 8.95. None of the Version 8.95 logic is changed, but I corrected some confusing language in some comment text and significantly expanded other comment areas.
(I plan to make similar improvements to the source code commentary for all of the other "MissionNetworkBattleXX.cpp" files as time permits.)
////Thisfileimplements"MissionNetworkBattle05".////Theoriginalversionofthisfileimplementsthemissionasafunctionalduplicate//ofourwell-known,long-stable"MissionNetworkBattle01",butbyalteringthe//codewithinthisfile,profoundchangescanbemade.Itiseasytochangethe//terrainstyleandtoexperimentwithvariousweathereffects,ortorestrict//thechoiceofaircraft.Itisalsoeasytoaddadditionalmissionobjects,like//oneormoreadditionalbattleships.Thesecanbe"animated"sothattheymove//aroundaccordingtotheadvanceoftime.////Developersfamiliarwiththefree,well-known"Blender"graphicrendering//applicationcouldcreate3dmodelsofaircraftcarriers,otherships,or//anti-aircraftgunswhichcouldthenbeusedinnewversionsofthismission.////Moreadvancedideasmightincludeaddingadditional"HQ"airfieldswhichmustbe//destroyedbeforeeitherteamcanclaimvictory.Orvictorycouldbebasedon//somecompletelydifferentconcept,likesomespecificnumberofair-to-air//victoriesforonesideorforanindividualplayer,ordestructionofthree//battleships,etc.////Developersareessentiallyunrestrictedinthedesignofmissionsderiving//fromthisframework.////Throughoutthiscode,itwillbehelpfultoknowthatsyntaxlike"tl->x",//or"tl->y",or"tl->z"referstothephysicallocationofanobjectin//xyzcoordinates,wherethe"y"coordinaterepresentsaltitude.Thinkof//"tl"as"translate"inthiscontext.Youwillusethissyntaxtoplace//objectsoraircraftwithintheterrain.////Manyelementsofthismissioncodeinteractwithpre-written,fullydebugged//functionsoutsidethescopeofthisfile.Sometimesthesefunctionsare//invokeddirectlyincodethatcanbeseenhere,butsometimesthese//externalfuncionsareinvokedindirectly,bysettingoradjustingthe//valueofsomeglobalvariablethatactsto"trigger"them.Byfollowing//thelogicpatternsvisibleinthisfile,missiondesignerscanusethose//externaltoolsinsimilarways.////MissiondesignerswishingtomodifythismissionshouldNOTchangeany//othersourcecodefilesunlesstheycoordinatewiththeprimaryLAC//designer,sinceanysuchchangeswillaffectotherbehavior.//////Mission-specificcodecommenceshere://MissionNetworkBattle05::MissionNetworkBattle05(){////Thiscodeisexecutedassoonastheplayerselectsthismission//fromthemainmenu.Itisresponsiblefordisplayoftheassociated,//mission-specificmenutext.Italsosetsuptherequirednetwork//configuration,andassociatedtimersfornetworkevents.////Setupmenusystemtoallowtheplayertoreadadescription//ofthemissionandselectappropriateaircraftand//munitions.AlsoopenthenecessaryUDPsocketsfor//outgoingandincomingtraffic://display((char*)"MissionNetworkBattle05::MissionNetworkBattle05()",LOG_MOST);id=MISSION_NETWORKBATTLE05;if((NetworkMode&1)==0){strncpy(name,"WRONG NETWORK MODE!",1024);strncpy(briefing,"FOR CLIENT/SERVER MODE, LACCONFIG.TXT FILE MUST SET MODE\nTO AN ODD NUMBER.",1024);}else{strncpy(name,"BLAKE'S MISSION: AIR SUPERIORITY",1024);strncpy(briefing,"2 TO 10 NETWORK PLAYERS IN 2 TEAMS. ONLY FIGHTER AIRCRAFT ARE\nPERMITTED. THIS SIMPLE MISSION IS ONLY FOR FIGHTER VERSUS FIGHTER\nDOGFIGHTS. THERE ARE NO GROUND GUNS. LAND ON ANY FLAT GROUND\nTO REFUEL, REARM, & REPAIR. NO JETS, ROCKETS, OR TAIL GUNS.",1024);}selfighter[0]=DefaultAircraft;selweapons=0;////CalculateareasonablevalueforNetworkReceiveTimerInterval,//basedonthevalueofNetworkTransmitTimerIntervalasconfigured//withinthe"LacConfig.txt"file.WeoughttocheckforInPackets//morefrequentlythanwearesendingOutPackets,bytheratioof//possibleplayersinthemission.Thusinthiscase,wherewe//couldhaveasmanyastenplayersinthemission,wewillcheck//forInPacketsabouttwelvetimesasfrequentlyaswesend//OutPacketsasfollows://NetworkReceiveTimerInterval=NetworkTransmitTimerInterval/12;//LoadServerIpAddress();//GetPeerIPaddressfromLacConfig.txt////Turnofftheglobal"NetworkOpponent"flaguntilaremotepeerconnects//fromthenetwork.Thisflagwillbeactivatedifandwhen//incomingUDPpacketsareeverreceivedfromasentient://NetworkOpponent=0;//StartmissionwithAIManeuoveringopponent.////Configurethenetworkinpreparationforonlinework.////(Youdon't want to make any changes in this area unless you//knowwhatyouaredoingandarealreadycomfortablewiththe//UDPprotocolandtheDNSsystem.)//if((NetworkMode&1)==1){//ClientServermoderequiresonlyasingleUDPport,usedbothforsendingandreceivingdisplay((char*)"Attempting MissionNetworkBattle05 in ClientServer Network mode.",LOG_NET);if(OpenClientUdpSocket()==0){//GethereifwewereabletoopentherequiredClientServerUDPSocketdisplay((char*)"MissionNetworkBattle05 ClientServer mode succesfully opened ClientUDP socket",LOG_NET);ConfigureClientUdpSocket();}else{//GethereifwewereunabletoopentherequiredClientUDPsocketdisplay((char*)"MissionNetworkBattle05 ClientServer mode unable to open ClientUDP socket.",LOG_NET);}}else{display((char*)"Incorrect network mode configured in LacConfig.txt file.",LOG_ERROR);sound->setVolume(SOUND_BEEP1,126);sound->play(SOUND_BEEP1,false);}////Nowswitchtheuser's "Mumble" application to the appropriate channel://event_CommsMacro17();}//endMissionNetworkBattle05::MissionNetworkBattle05()voidMissionNetworkBattle05::start(){NoMissionHasYetCommenced=false;////Thiscodegetsexecutedonlyoncepermission,asitstartsup.////Initializethelandscape,placetheplayerwithinit,and//optimizecockpitinstruments.Thenloadarmamentforall//peersandspawntheAIaircraftforthemission.////if(!(NetworkMode&16)){//GethereifLACisNOTconfiguredtoignoreespeakpopen("espeak -p 10 -a 66 -s 160 \"Welcome to Blake's Mission! This is a very simple, fighter versus fighter mission. You can land on any flat ground for refuel, re-arm, and repair services.\"","r");}//Initializethe"mission state",whichistrackedintheglobalvariable"MissionStateNetworkBattle".//Thatvaluewillincreaseatcarefullyselectedtimeintervals,andisusedtotriggertime-dependent//missionevents,likesnippetsofaudionarrationthatcanhelptheplayergetorientedto//themission's design:MissionStateNetworkBattle=0;display((char*)"MissionNetworkBattle05::start()",LOG_MOST);////Nowinitializeafewothermission-specificvariables://NetworkPlayerKilled=false;inti,i2;camera=0;//Placeplayerincockpit,lookingforwardheading=220;//Initialdirectionoftravel////Makesurethevalueof"MyNetworkId"isappropriate,andchange//ittoavaluebetween1and10ifnecessary://if((MyNetworkId==0)||(MyNetworkId>MaxPlayersInCurrentMission)){//Gethereif"MyNetworkId"hasnotyetbeeninitializedorifitsvalueistoohighMyNetworkId=myrandom(MaxPlayersInCurrentMission);//RandomizeMyNetworkIdMyNetworkId++;}////Nowconfiguretheweatherconditionsforthemission://day=1;clouds=2;//1,2,or3.weather=WEATHER_SUNNY;//Otherweatheravailable.Backspacepasttheunderscore,thenreplaceunderscoreforprompts.sungamma=25;//Adjustbrightnessofsunandsubtleshading,especiallywatertextures.25isnice.////Nowgeneratethelandscape,hereafternamedsimply"l"://if(l!=NULL){//Ifwealreadyhavelandscape"l",deleteitdeletel;}////Thenextlineofcodecanurgeformationofanyofvariousstylesoflandscape.//Theoriginaltemplateforthismissionused"LANDSCAPE_ALPINE_SEA"forthis,but//wesubsequentlychangeditto"LANDSCAPE_ALPINE_EROSION"instead.////IfyoueditthatkeywordinsideCodeblocks,itwillsuggestalternativesthat//willcausegenerationofdesert,forest,arctic,orotherlandscapes.//l=newGLLandscape(space,LANDSCAPE_ALPINE_EROSION,NULL);////Nowcalibratethealtimetersoitgoesto"0"atsealevel.Ifyouchangethe//landscapestyleyouwillprobablyneedtoexperimentwithittodeterminethe//rightvalueof"SeaLevel"accordingtoappearancesasyoufly:SeaLevel=100.0;//CalibratesRADARandaltimetertoabout"0"atsealevel.Adjustasneededfordifferentterrains.400yieldsabout19000ft.200yieldsabout10000ft.////Nowusethelandscape's "flatten()" function to landscape a long, flat runway, at landscape XY//coordinatesdesignatedbytheglobalfloating-pointvariables"AirfieldXMin","AirfieldYMin":////(NotethatyouwillneedtochangetheXYvaluesof"AirfieldXMin"and"AirfieldYMin"inmain.cpp//ifyourlandscapeterrainforcesrelocationofyourairfields.)//l->flatten(AirfieldXMin+28.0,AirfieldYMin+4,29.2,5);//Flattenrunway29.2unitslong,5unitswidel->flatten(AirfieldXMin+46,AirfieldYMin+5,7,6);//Flattenadjacenttarmacarea7unitslong,6unitswide////Over-ridesomedefaultsintheMissionObjectMap,sincethis//missionwilluseadifferentcombinationofmissionobjects://MissionObjectBunkerBlue1=0;MissionObjectBunkerRed1=0;MissionObjectRadarHqRed=0;MissionObjectRadarHqBlue=0;MissionObjectHqBlue=0;MissionObjectHqRed=0;////NowinsertRedTeam"Airfield00"structuresontothelandscapenearitsrunway,treatingthosestructuresasif//theywereanyothermissionobjectsotheycanbedamagedand/ordestroyed.ThiswillbetheHQ//airfieldfortheRedTeam,followedbyotherRedTeamobjects://MissionObjectHqRed=29;//UpdateMissionObjectMapintn=MissionObjectHqRed;//RedTeamHQairfieldfacilities//NotethattheAirfieldisspecialinthatlogicinothersourcecodefilesmakesprovisionsto//periodicallytransmititsstatustotheserver.ThreeDObjects[n]->tl->x=AirfieldXMin+46.5;ThreeDObjects[n]->tl->z=AirfieldYMin+8;//AirfieldXandZpositionshavebeenset,butwemustwaituntillaterbeforewecansetY(altitude)...ThreeDObjects[n]->target=ThreeDObjects[0];//Airfieldsdon't need a "target".ThreeDObjects[n]->o=&model_Airfield00;//Loadthe3dmodelforgenerationofitsappearanceThreeDObjects[n]->newinit(STATIC_AIRFIELD00,0,400);ThreeDObjects[n]->Durability=ThreeDObjects[n]->maxDurability;//SetinitialairfieldDurabilityThreeDObjects[n]->zoom=6.0;//Scaleairfieldtoanice,prominentsize.MissionObjectRadarHqRed=27;//UpdateMissionObjectMapn=MissionObjectRadarHqRed;//RedTeamRectangularRADARReflectorThreeDObjects[n]->tl->x=AirfieldXMin+41.0;ThreeDObjects[n]->tl->z=AirfieldYMin+6.2;ThreeDObjects[n]->target=ThreeDObjects[0];ThreeDObjects[n]->o=&model_RadarReflector;ThreeDObjects[n]->newinit(STATIC_RADARREFLECTOR,0,400);ThreeDObjects[n]->impact=0.0;ThreeDObjects[n]->party=1;ThreeDObjects[n]->Durability=ThreeDObjects[n]->maxDurability;ThreeDObjects[n]->zoom=0.66;////NowinsertBlueTeam"Airfield00"structuresontothelandscapenearitsrunway,treatingthosestructuresasif//theywereanyothermissionobjectsotheycanbedamagedand/ordestroyed.ThiswillbetheHQ//airfieldfortheRedTeam,followedbyotherRedTeamobjects://MissionObjectHqBlue=28;//UpdateMissionObjectMapn=MissionObjectHqBlue;//BlueTeamHQairfieldFacilities//NotethattheAirfieldisspecialinthatlogicinothersourcecodefilesmakesprovisionsto//periodicallytransmititsstatustotheserver.ThreeDObjects[n]->tl->x=-304;ThreeDObjects[n]->tl->z=11.0;//AirfieldXandZpositionshavebeenset,butwemustwaituntillaterbeforewecansetY(altitude)...ThreeDObjects[n]->target=ThreeDObjects[0];//Airfieldsdon't need a "target".ThreeDObjects[n]->o=&model_Airfield00;ThreeDObjects[n]->newinit(STATIC_AIRFIELD00,0,400);ThreeDObjects[n]->Durability=ThreeDObjects[n]->maxDurability;ThreeDObjects[n]->zoom=6.0;MissionObjectRadarHqBlue=26;//UpdateMissionObjectMapn=MissionObjectRadarHqBlue;//BlueTeamRectangularRADARReflector.Carefullyplaceitsxzdirectlyatoptheairfieldtower.ThreeDObjects[n]->tl->x=AirfieldXMin-470.58;//-470.5endsupwiththetowerjustbarelywithintheconvexreflector.ThreeDObjects[n]->tl->z=AirfieldYMin+6.25;ThreeDObjects[n]->target=ThreeDObjects[0];ThreeDObjects[n]->o=&model_RadarReflector;ThreeDObjects[n]->newinit(STATIC_RADARREFLECTOR,0,400);ThreeDObjects[n]->impact=0.0;ThreeDObjects[n]->Durability=ThreeDObjects[n]->maxDurability;ThreeDObjects[n]->zoom=0.66;////Justafew"housekeeping details now, in preparation for running the mission://playerInit();PlayerAircraftType=fplayer->id;MissionRunning=false;//Semaphore.Setonfirstpassthroughmissionprocesstimer().fplayer->phi=270;//Player's initial direction of travel. (270 = straight West.)////Thiscouldbeahandyplacetoupdateourlogfileandgeneratearun-timestatusupdate://display((char*)"MissionNetworkBattle05::start setting PlayerAircraftType to: ",LOG_MOST);sprintf(DebugBuf,"%d",PlayerAircraftType);display(DebugBuf,LOG_MOST);//InitializeallcockpitinstrumentstoastablestartingpointHudOnOff=1;//StartoutwithHUDon.IffOnOff=0;//InitializeIFFtooff.MapViewOnOff=0;//MakesurewehaveMapViewoffatstart.RadarOnOff=0;//InitializeRADARtooff.RadarZoom=1;//SetRADARRangeto50milesforthismission.ScreenFOVx=1.0;//ResetviewzoomtonormalScreenFOVy=1.0;//Resetviewzoomtonormal//Nowoptimizeallcockpitinstrumentsforthismissionevent_IffOnOff();//TurnonIFFforthismission.if(!HudLadderBarsOnOff){//TurnonHUDLadderbarsforthismissionevent_HudLadderBarsOnOff();}event_ZoomFovOut();//Startwithwidefieldofview.event_ZoomFovOut();MaxPlayersInCurrentMission=10;////SpawntenshinynewAIaircraft,DefaultingtoA6M2"Zeroes".//Throughoutthismission,arrivingUDPInPacketsrepresenting//flightbyremote,network-accessiblepeerclientcopiesofLAC//areacceptedandexamined,andtheactivitiesthey//describeareappliedtotheactiveAIaircraftdesignated//withineachreceivedInPacket.//for(i=1;i<=10;i++){//Initializeopponents.Lastargumenttonewinit(),//althoughitisnamed"intelligence"inthecode,//determinestheirstupidity.Lowermeansmore//effective.400isaprettygoodvalue.1200makes//themquitedumb.//ThreeDObjects[i]->newinit(FIGHTER_F4F,0,400);//Preserveaircrafttypeforlatercomparisontodetectchanges.MissionNetworkBattle05PriorAircraft[i]=FIGHTER_F4F;////The"ThreeDObjects[]"arraymanagesalloftheactive//missionobjects,anditcontainsanentryforeachof//thetenmissionaircraft,plusairfields,radartowers,//ships,artillerybatteries,etc..Eachofthefirstten//entriesisusedforthemissionaircraftandconsequently//associatedwithamultitudeofflight"attributes",each//ofwhichisaccessedthroughasyntaxlikethis:"->".////Forexample,the"Sentient"attributecountsupward//whenanaircrafthasreceivedalotofnetworkpackets//influencingitspositionandindicatingthatitis//beingflownbyalivinghumanconnectedviathe//Internet.Ontheotherhand,the"Sentient"attribute//countsdownwardwiththeroutinepassageoftime.//Accordingly,a"Sentient"valueof"0"indicatesthat//thecorrespondingaircraftisa"bot"thatisnot//influencedbyanetwork-connectedhuman.////Chooseappropriatestartingvaluesforthemostimportant//attributesofall10missionaircraft://ThreeDObjects[i]->target=NULL;//Bestifbotsdon't have a target...ThreeDObjects[i]->o=&model_figAO;//Loadtheappropriate3dmodelforappearanceofbot//Positionfightersinscatteredxzlocations:ThreeDObjects[i]->tl->x=-200+(myrandom(400)-200)+(150*SIN(i*360/11));ThreeDObjects[i]->tl->z=200+(myrandom(400)-200)+(150*COS(i*360/11));ThreeDObjects[i]->ammo=1600;//Botsstartoutwith1600machinegunbulletsThreeDObjects[i]->Sentient=0;//AllfightersarebotsuntilastreamofInPacketsrevealsthemtobeSentient.ThreeDObjects[i]->MyMissionPlayerNumber=i;//Assignall10playerstheir"MyMissionPlayerNumber"(usedelsewhere)////Thisisanothergoodplacetoupdateourdiagnosticreportingandlogwithdetailsaboutourbots://sprintf(DebugBuf,"MissionNetworkBattle05::start() initializing Bot #%d",i);display(DebugBuf,LOG_MOST);sprintf(DebugBuf,"MissionNetworkBattle05::start() ThreeDObjects [i]->MyMissionPlayerNumber = %d",ThreeDObjects[i]->MyMissionPlayerNumber);display(DebugBuf,LOG_MOST);////Nowmakesurenoneofthemissionaircraftisluggingmissilesorbombs://for(i2=0;i2<missiletypes;i2++){//examineevery"hardpoint"oneachaircraftThreeDObjects[i]->missiles[i2]=0;//Startoutluggingnoordnanceanywhere.}}//Endofloopthatspawnsandconfiguresall10missionbots.////Justafewmore"housekeeping"itemstomakesurethismissionalwaysstartsout//inthesamewaywithstablecounters,timers,ordnance,etc.://texttimer=0;MissionOutPacketCount=0;MissionIdNegotiationCount=0;NetworkTransmitTimer=-1000;//Don't send any OutPackets for the first 1 second of the mission.ConfigureOrdnanceForOnlineMissions();UpdateOnlineScoreLogFileWithNewSorties();ArmPlayerAtRequestedField();////Nowgivetheplayerastartingxzpositionbasedonhisteamaffiliation://thatthelogiccanalwaysrefertotheplayeras"fplayer"andassociated//attributescanbeaccessedthroughsyntaxlike"fplayer->"etc.//if(MyNetworkId%2){//@GethereifplayerisonRedTeamdisplay((char*)"MissionNetworkBattle05: Spawning player at 500, 15000",LOG_MOST);fplayer->tl->x=500;//@was-340fplayer->tl->z=15000.00;}else{//@GethereifplayerisonBlueTeamdisplay((char*)"MissionNetworkBattle05: Spawning player at -500, 15000",LOG_MOST);fplayer->tl->x=-500;//@was-340fplayer->tl->z=15000.00;}//Ensureaircraftisreadyforcombat////Donottrytounderstandorchangethis"ThrustReadiness"logic.Itis//purposelyundocumentedandisusedbytheserverforsomesecret,anti-//cheatinglogic://ThrustReadiness=((float)fplayer->DefensiveLethality+fplayer->maxthrust+fplayer->RollRate+fplayer->manoeverability+fplayer->maxDurability+fplayer->maxgamma+(float)fplayer->statLethality+fplayer->StaticDrag+fplayer->SpeedBrakePower+fplayer->MaxFullPowerAltRatio+fplayer->inertia+fplayer->deadweight+fplayer->CompressibilitySpeed+fplayer->CompressibilitySpeedWithSpeedBrakes+fplayer->StallSpeed+fplayer->ServiceCeilingAltitude);if(fplayer->WepCapable){ThrustReadiness+=200;}if(ThrustReadiness<1000){display((char*)"Error. Selected Aircraft ThrustReadiness is insufficient.",LOG_MOST);game_quit();//Airplaneperformanceparametersdidn't load properly.}}//endMissionNetworkBattle05::start()intMissionNetworkBattle05::processtimer(Uint32dt){//Gethereeveryfewmillisecondsduringthismission.////Thisfunctionistheheartandsoulofthemission.////Thisfunctionmustbecodedforspeedandefficiency,since//itiscalledconstantly,asfrequentlyaspossible,foras//longastheplayerremainsinflightinthismission.////Thisbigfunctioncontrolsalloftheactionanddynamic//elementsofthemission.Everythingthatisanimatedor//dynamiciscontrolledhere,asthelogicprocessesthis//functionoverandoveragain,asfastasitcango.////LocalVariablesusedthroughoutthisfunction://inti;intMissionAircraftNumber;intBytesReceived=0;////Tobegin,weupdatealltimersandinitiatetimer-dependent//logicasnecessary.////Theamountoftimeinmillisecondssincethelast//commencementofthisfunctionisspecifiedbytheUnsigned//integerinputparameternamed"dt",sowewillalways//increaseordecreaseourtimersbytheamountspecifiedin"dt".//Thevalueof"dt"isalsoavailableas"DeltaTime".//////Nowadvanceafewofthetimersthatwillbeusedthroughout//thismission://MissionNetworkBattle05Timer+=DeltaTime;//AdvancebymillisecondsMissionNetworkBattleRadarTimer+=DeltaTime;//AdvancebymillisecondsMumbleTimeRemainingBeforeChannelReset-=DeltaTime;//Thisonecountsdown.if(!MissionRunning){//GethereifthisistheFIRSTpassthroughprocesstimer().////ThisblockofcodeisexecutedonlyONCE,atthebeginningofthemission.////Setupplayerdetailsthatcannotbesetupinmissionstart().DegradeFlightModelDueToOrdnanceLoad();//Ifluggingheavyweapons,diminishclimbratefplayer->FuelLevel=96.0;//Starttheplayeroutwithjust6%fuelasthismissioncommences.////Thismissionprohibitsuseofheavybombers,mediumbombers,oranyotheraircraftwitha//tailgunner.ThemainmenusystemallowstheplayertoSELECTthoseaircraft,but//wewilldenythemfuelhere://if(fplayer->missiles[0]>=4){//Gethereifthisisamediumorheavybomber.Cutfuelenoughtopreventreachingnextairfield.fplayer->FuelLevel=1.0;}if(fplayer->missiles[0]>=12){//Gethereifthisisaheavybomber.Cutfuelenoughtopreventreachingnextairfield.fplayer->FuelLevel=0.5;}////NowdeterminewhethertheplayerentersthemissionflyingstraightEastorstraight//West,dependingonhisteamaffiliation.Previouslogicassumedtheplayerjoinedthe//BlueTeam.Ifhe'as actually on the RedTeam, we need to reverse his compass heading,//accessedas"fplayer->phi"://if(fplayer->party==1){//Redteam.Needtoreversecompassdirectiontoflytowardaction.fplayer->phi-=180;}/***Thefollowingblockofcodeattemptstocausetheplayerto*spawnwithzeroairspeed.Itworks,butitisn't sufficient*becausesomethingelsecausesairspeedtobuildbackto*about160MPHwithinaboutonesecondafterspawning.**However,itmaybeusefulinthefuture,soitoughtto*bepreserved.*/fplayer->realspeed=0.0;fplayer->InertiallyDampenedPlayerSpeed=0.0;ClearSpeedHistoryArrayFlag=true;fplayer->accx=0.0;fplayer->accy=0.0;fplayer->accz=0.0;////Duetothequirkywayobjectsarepositionedasamissioncommences,this//isthefirstreasonableopportunitytoadjustthealtitudeofmission//objectspopulatingourlandscape.Adjustthemallaccordingtothe//terrainuponwhichtheyarelocated.Thislogicisassistedbytwo//handyterrainfunctions,named"getHeight()"and"getExactHeight()".//Eachexpectstwoinputparametersdesignatingaspecificterrain//locationinXZcoordinates,andeachreturnsthealtitudeofthe//terrainatthatpoint,whichequatestotheassociatedYcoordinate.////Ifyoumakesignificantchangestoterrainaltitudes,youmayneed//toadjustthefollowingcodeaccordingtoyourownobservations//inflighttopreventmissionobjectsfromfloatingabovethe//landscapeorsinkingoutofsightbelowground.////Playeraircraftaltitudeatstartupshouldbeverylowaboveground.fplayer->tl->y=l->getHeight(AirfieldXMin,AirfieldYMin);fplayer->tl->y+=25.0;//Raiseplayeraircraft60unitsin"y"//AirfieldBlueHQfacilitiesaltitudeThreeDObjects[MissionObjectRadarHqBlue]->tl->y=l->getExactHeight(AirfieldXMin-470.58,AirfieldYMin+6.25);//BlueTeamRadarReflectorThreeDObjects[MissionObjectRadarHqBlue]->tl->y+=3.0;ThreeDObjects[MissionObjectHqBlue]->tl->y=l->getHeight(-304,11);ThreeDObjects[MissionObjectHqBlue]->tl->y+=0.90;//BlueTeamairfieldfacilitiesgetraised0.90units//AirfieldRedHQfacilitiesaltitudeThreeDObjects[MissionObjectRadarHqRed]->tl->y=l->getExactHeight(AirfieldXMin+41.0,AirfieldXMin+6.2);//RedTeamRadarReflectorThreeDObjects[MissionObjectRadarHqRed]->tl->y+=5.6;ThreeDObjects[MissionObjectHqRed]->tl->y=l->getHeight(AirfieldXMin+46.5,AirfieldYMin+8);ThreeDObjects[MissionObjectHqRed]->tl->y+=0.90;//RedTeamairfieldfacilitiesgetraised0.90units.//Makesureplayerstartsoutwithlandinggearandflapsretractedinanyaircraftthatpermitsretractionfplayer->UndercarriageLevel=0;fplayer->FlapsLevel=0;//fplayer->FlapsLevel=1;for(i=1;i<=10;i++){//StartalltenbotsatmediumaltitudeThreeDObjects[i]->tl->y+=150;}////Preventeffectiveuseofanybomberaircraftinthismission://if((fplayer->id==BOMBER_B17)||(fplayer->id==BOMBER_B24)||(fplayer->id==BOMBER_JU87)||(fplayer->id==BOMBER_G5M)||(fplayer->id==BOMBER_B25)||(fplayer->id==BOMBER_B26)||(fplayer->id==BOMBER_LANCASTER)||(fplayer->id==BOMBER_B29)||(fplayer->id==BOMBER_B5N)||(fplayer->id==BOMBER_DAUNTLESS)||(fplayer->id==BOMBER_DORNIER)||(fplayer->id==BOMBER_HE111)||(fplayer->id==BOMBER_JU88)||(fplayer->id==BOMBER_SB2C)||(fplayer->id==BOMBER_TBF)||(fplayer->id==FIGHTER_D3A)||(fplayer->id==FIGHTER_ME110)||(fplayer->id==FIGHTER_IL2)||(fplayer->id==FIGHTER_ME163)||(fplayer->id==FIGHTER_HAWK)){//Gethereifplayerisattemptingtoflyabomber,jet,orrocket.sprintf(SystemMessageBufferA,"THIS MISSION FORBIDS THIS AIRCRAFT. OUT OF FUEL!");NewSystemMessageNeedsScrolling=true;sound->setVolume(SOUND_BEEP1,60);//@Medium-volumebeepsound->play(SOUND_BEEP1,false);fplayer->Durability=fplayer->Durability*0.1;//Inflictheavydamageonplayerifhe's in a forbidden bomberfplayer->FuelLevel=0;}////NowmakesureplayeraircraftisNOTluggingmissilesorbombs://for(i=0;i<missiletypes;i++){//examineevery"hardpoint"oneachaircraftThreeDObjects[0]->missiles[i]=0;//Startoutluggingnoordnanceanywhere.}MissionRunning=true;//Fornextpass,Signalthatthisstartuploophasalreadybeendone.}//EndblockofcodeusedonlyONCE,atverybeginningofthemission.//////Continuemainlineofprocesstimer()code.ThisgetsexecutedmanytimespersecondwhileMissionruns.//timer+=dt;//Advancemissiontimer.////Thenextfewblocksofcodewillplayvariousaudiomessages//atthebeginningofthemissiontohelptheplayerbecome//oriented.Individualeventsarerepeatedduringeachofseveral//valuesof"MissionStateNetworkBattle".Those"states",inturn,//areadvancedstep-by-stepas"timer"advancesbeyondvarious//boundaryvalues.////Missiondesignersshouldavoidcreatinganyadditionalaudio//soundfilesbecausetheyuseupalotofRAMandtheir//creationisbeyondthescopeofsimplemissiondesign,//requiringalotofcomplicatedsteps.////However,Missiondesignerscaneasilyskipsomeofthe//followingaudiomessages,changethemtootherpre-existing//soudnclips,orchangethetimingallotedforeach.////Playerscanalsoeasilyinvoketext-to-speechaudio//throughthe"espeak"application,sincemostLACplayers//havebeeninstallingespeakaccordingtoourrecommendations.////Allofthislogicisdominatedbythevalueof"timer",//whichtriggerstransitionsamongimportantvaluesof//"MissionStateNetworkBattle",whichwasjustadvanced//bythepriorlineofcode.Itaccumulatesthetime//durationofthemissioninmilliseconds.//if(timer>10000&&MissionStateNetworkBattle==0&&NetworkTransmitTimer>=NetworkTransmitTimerInterval){//Onlygethereonce,10secondsintothemission,aswe've just begun transmitting OutPackets//withanavailablesettingforMyNetworkId.Vocalize"Red"or"Blue"accordingtoplayer's//teamaffiliation:if(MyNetworkId%2){//GethereifMyNetworkIdisanoddnumber//Vocalize"RED"sound->setVolume(SOUND_RED,126);sound->play(SOUND_RED,false);}else{//Vocalize"BLUE"sound->setVolume(SOUND_BLUE,126);sound->play(SOUND_BLUE,false);}MissionStateNetworkBattle=1;//ThisMissionStateisdone.Advancetonext.PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==1&&(timer>PriorStateEndTimer+600)){//Onlygethereonce,600msafterMissionStateNetworkBattle//advancesto"1"://if(!RadarOnOff){//IfplayerhasnotalreadyactivatedRADAR,toitforhim:event_RadarOnOff();}//Nowvocalizetheplayer's "MyNetworkId" value, a single//digitbetween"1"and"10".Thisispartofthemission's//audiogreetingfortheplayerduringthefirstfewseconds:switch(MyNetworkId){case1:{sound->setVolume(SOUND_DIGIT001,126);sound->play(SOUND_DIGIT001,false);break;}case2:{sound->setVolume(SOUND_DIGIT002,126);sound->play(SOUND_DIGIT002,false);break;}case3:{sound->setVolume(SOUND_DIGIT003,126);sound->play(SOUND_DIGIT003,false);break;}case4:{sound->setVolume(SOUND_DIGIT004,126);sound->play(SOUND_DIGIT004,false);break;}case5:{sound->setVolume(SOUND_DIGIT005,126);sound->play(SOUND_DIGIT005,false);break;}case6:{sound->setVolume(SOUND_DIGIT006,126);sound->play(SOUND_DIGIT006,false);break;}case7:{sound->setVolume(SOUND_DIGIT007,126);sound->play(SOUND_DIGIT007,false);break;}case8:{sound->setVolume(SOUND_DIGIT008,126);sound->play(SOUND_DIGIT008,false);break;}case9:{sound->setVolume(SOUND_DIGIT009,126);sound->play(SOUND_DIGIT009,false);break;}case10:{sound->setVolume(SOUND_DIGIT010,126);sound->play(SOUND_DIGIT010,false);break;}default:{break;}}MissionStateNetworkBattle=2;//ThisMissionStateisdone.Advancetonext.PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==2&&(timer>PriorStateEndTimer+1100)){//Onlygethereonce,1100msafterMissionStateNetworkBattle//advancesto"2":////Thisisagoodplacetodegradefuel,ammo,andordnanceaccordingto//therepairstateofourHQairfield,sothatnewplayers,justentering//thebattleinalate-waraircraft,willsufferdegredation,but//iftheyenterthebattleinanearly-waraircraft,nosuchdegredation//isasserted:Updatecockpit"SystemMessagePanel"accordingly://sound->setVolume(SOUND_YOUHAVEAUTHORITYTOPROCEED,126);sound->play(SOUND_YOUHAVEAUTHORITYTOPROCEED,false);MissionStateNetworkBattle=3;PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==3&&(timer>PriorStateEndTimer+2700)){//Onlygethereonce,2700msafterMissionStateNetworkBattle//advancesto"3"://Vocalize"Weapons Free"sound->setVolume(SOUND_WEAPONSFREE,126);sound->play(SOUND_WEAPONSFREE,false);MissionStateNetworkBattle=4;PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==4&&(timer>PriorStateEndTimer+3000)){//Onlygethereonce,3000msafterMissionStateNetworkBattle//advancesto"4":////Vocalize"Mission telemetry available from LAC server at"sound->setVolume(SOUND_BEEP1,20);sound->play(SOUND_BEEP1,false);sprintf(SystemMessageBufferA,"LAC SERVER IS AT LACSERVER2.LINUXAIRCOMBAT.COM");NewSystemMessageNeedsScrolling=true;sound->setVolume(SOUND_MISSIONTELEMETRYAVAILABLEFROMLACSERVERAT,126);sound->play(SOUND_MISSIONTELEMETRYAVAILABLEFROMLACSERVERAT,false);MissionStateNetworkBattle=5;PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==5&&(timer>PriorStateEndTimer+3300)){//Onlygethereonce,3300msafterMissionStateNetworkBattle//advancesto"5"://Vocalize"Linux Air Combat dot com"sound->setVolume(SOUND_BOSENETDOTNODASHIPDOTBIZ,126);sound->play(SOUND_BOSENETDOTNODASHIPDOTBIZ,false);MissionStateNetworkBattle=6;PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==6&&(timer>PriorStateEndTimer+3700)){//Onlygethereonce,3700msafterMissionStateNetworkBattle//advancesto"6":////Vocalize"Global assignment audio at"sound->setVolume(SOUND_BEEP1,20);sound->play(SOUND_BEEP1,false);sprintf(SystemMessageBufferA,"TUNE MUMBLE RADIO: LACSERVER2.LINUXAIRCOMBAT.COM");NewSystemMessageNeedsScrolling=true;sound->setVolume(SOUND_GLOBALASSIGNMENTAUDIOATMUMBLE,126);sound->play(SOUND_GLOBALASSIGNMENTAUDIOATMUMBLE,false);MissionStateNetworkBattle=7;PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==7&&(timer>PriorStateEndTimer+2500)){//Onlygethereonce,2500msafterMissionStateNetworkBattle//advancesto"7":////Vocalize"Linux Air Combat.com"sound->setVolume(SOUND_BOSENETDOTNODASHIPDOTBIZ,126);sound->play(SOUND_BOSENETDOTNODASHIPDOTBIZ,false);MissionStateNetworkBattle=8;PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==8&&(timer>PriorStateEndTimer+3500)){//Onlygethereonce,3500msafterMissionStateNetworkBattle//advancesto"8":////Vocalize"Mission comms on channel"sound->setVolume(SOUND_MISSIONCOMMSONCHANNEL,126);sound->play(SOUND_MISSIONCOMMSONCHANNEL,false);MissionStateNetworkBattle=9;PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==9&&(timer>PriorStateEndTimer+2000)){//Onlygethereonce,2000msafterMissionStateNetworkBattle//advancesto"9":////Vocalize"Linux Air Combat"sound->setVolume(SOUND_LINUXAIRCOMBAT,126);sound->play(SOUND_LINUXAIRCOMBAT,false);MissionStateNetworkBattle=10;PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==10&&(timer>PriorStateEndTimer+1500)){//Onlygethereonce,1500msafterMissionStateNetworkBattle//advancesto"10":////Vocalize"MissionNetworkBattle01"sound->setVolume(SOUND_MISSIONNETWORKBATTLE01,126);sound->play(SOUND_MISSIONNETWORKBATTLE01,false);MissionStateNetworkBattle=11;PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==11&&(timer>PriorStateEndTimer+2500)){//Onlygethereonce,2500msafterMissionStateNetworkBattle//advancesto"11":////Vocalize"Squad comms on subchannel"sound->setVolume(SOUND_SQUADCOMMSONSUBCHANNEL,126);sound->play(SOUND_SQUADCOMMSONSUBCHANNEL,false);MissionStateNetworkBattle=12;PriorStateEndTimer=timer;}if(MissionStateNetworkBattle==12&&(timer>PriorStateEndTimer+2500)){//Onlygethereonce,2500msafterMissionStateNetworkBattle//advancesto"12":////Vocalize"Red"or"Blue"accordingtoplayer's team affiliation:sound->setVolume(SOUND_RED,126);if(MyNetworkId%2){sound->setVolume(SOUND_RED,126);sound->play(SOUND_RED,false);}else{sound->setVolume(SOUND_BLUE,126);sound->play(SOUND_BLUE,false);}MissionStateNetworkBattle=13;PriorStateEndTimer=timer;}////MissionDesigners:Ifyouwanttoinsertadditional,timed,one-timesteps//intoyourmission,youcancontinuethepatternofthe12prior//"MissionStateNetworkBattle"blockswithadditional,similarblockshere.////Youcouldcreateasmanynewstateblocks,eachactivatedaccordingto//thepatternoftheabove12blocksastimeand"MissionStateNetworkBattle"//advance,asyouwant.Withineachblockyouhavealotoffreedom//tohandleanyone-timeeventyoucanimagine.////YoucouldeasilyputnewmessagesintotheSystemMessagePaneland/or//playorreplayadditionalsoundfilesorbeeps,text-to-voicemessages,//oryoucouldchangethedirectionoftravelofships,destroyorrepair//objects,changeMumblechannels,etc.////Now,aftercheckingtoseeifweneedtoprocessanyone-time"MissionState"//events,weneedtoloopthroughallMissionaircraftanddeterminewhether//weshouldre-spawnanythathavebeendestroyed.Also,preserveeachaircraft//typepriortoarrivalofthenextInPacket.//for(MissionAircraftNumber=1;MissionAircraftNumber<=10;MissionAircraftNumber++){//Examineall10aircraftandconsiderreplacinganythathaveexploded.if(ThreeDObjects[0]->explode>500*timestep){//Player's aircraft exploded more than 500 ms ago but has not been re-spawned and//playerhasn't pressed <ESC>.display((char*)"MissionNetworkBattle05::processtimer(): Player plane is dead and player has waited for program to exit. Invoking game_quit().",LOG_MOST);game_quit();//Playerplaneisdeadandplayerhaswaitedforprogramtoexit.}if(ThreeDObjects[0]->explode>450*timestep){//Player's aircraft exploded recently and he is almost out of time to press <ESC> before program exits.sound->setVolume(SOUND_BEEP1,20);//beepsoftlysound->play(SOUND_BEEP1,false);}if(!ThreeDObjects[MissionAircraftNumber]->active&&(myrandom(10000)>9990)){//Gethere0.5%ofthetimeafteranyotherplaneexplodesorcrashes.Re-spawndestroyedaircraft.////Thisisahandyplacetologsomerun-timediagnostics://sprintf(DebugBuf,"MissionNetworkBattle05::ProcessTimer() re-spawning aircraft #%d.",MissionAircraftNumber);display(DebugBuf,LOG_MOST);////Wemayneedsomeextrastepsifthisaircraftwasflown//bya"Sentient"player.////Atthispointwemaywanttowaitforoneortwopacket//periodssince,duetonetworklatencyandthenormaltime//betweenourOutPackets,theremotepeerwon't learn of//hisdeathinstantly.Althoughtheremotepeerwillstop//sendingpacketsonceheknowshe's dead, during the//interimwemustexpecthimtosendoneortwomore//packetsasifhe's still alive. If we generate and//positionourreplacementbotbeforetheremotepeerstops//sendingpackets,thenthearrivalofjustoneofthose//packetswillcauseournewbottoinstantlyleaptothe//XYZpositionlastoccupiedbytheremotepeerand//continuefromthere.That's NOT what we want because//itwouldmakeitlooklikeourVictimdidn't really die!//Accordingly,wewanttosettheglobal"NetworkReceiveTimer"//backto-400mstomakeitwaitawhile,andwewanttoforce//thelocationofthere-spawnedaircraftawayfromthe//priorpositionasfollows://if(ThreeDObjects[MissionAircraftNumber]->Sentient>3){//GethereifthedestroyedaircraftwaspilotedbyaSentient.Someextrastepsareneeded.GetNetworkApiPacket();//ThrowawayanyInPacketthathasalreadysneakedin....DiscardAnyInPacketsInQueue();//RemoveanystaleinpacketsthatmightotherwisecorruptourrespawningparametersInPacket.UdpObjXPosition-=300;//MakeSUREnoInPacketplacesreplacementbotnearby.InPacket.UdpObjZPosition-=300;//MakeSUREnoInPacketplacesreplacementbotnearby.NetworkReceiveTimer=-400;//Wait400msbeforegettingnextInPacket//Preservethisaircrafttypeforlatercomparisontodetectfuturechanges:MissionNetworkBattle05PriorAircraft[MissionAircraftNumber]=ThreeDObjects[MissionAircraftNumber]->id;}//Endofspecial,additionaltimingandpositionlogicforrespawningaformerly"Sentient"player////Nowtakeallstepsnecessarytore-spawnanewaircrafttoreplace//theonethatwasdestroyed://ThreeDObjects[MissionAircraftNumber]->newinit(FIGHTER_A6M2,i+1,400);//Forthismission,botsarealwaysinA6M2"Zeroes".ThreeDObjects[MissionAircraftNumber]->id=FIGHTER_A6M2;ThreeDObjects[MissionAircraftNumber]->Durability=ThreeDObjects[MissionAircraftNumber]->maxDurability;//RepairthenewaircraftThreeDObjects[MissionAircraftNumber]->immunity=50*timestep;//MakethisnewaircraftinvulnerableforthefirstfewsecondsThreeDObjects[MissionAircraftNumber]->activate();//ActivatethatnewaircraftThreeDObjects[MissionAircraftNumber]->killed=false;//Advertisethatheisalive.ThreeDObjects[MissionAircraftNumber]->ammo=1600;//Botsget1600bulletseach.ThreeDObjects[MissionAircraftNumber]->MyMissionPlayerNumber=MissionAircraftNumber;//Makemyplayernumbergloballyvisible////Movethisnewaircrafttoanew,randompositionintheneighborhood,atleast200unitsremovedfrompriorposition://ThreeDObjects[MissionAircraftNumber]->tl->x=200+(myrandom(20)-10);ThreeDObjects[MissionAircraftNumber]->tl->z=200+(myrandom(20)-10);ThreeDObjects[MissionAircraftNumber]->tl->y=l->getHeight(ThreeDObjects[MissionAircraftNumber]->tl->x,ThreeDObjects[MissionAircraftNumber]->tl->z);ThreeDObjects[MissionAircraftNumber]->tl->y+=260+(myrandom(80)-40);ThreeDObjects[MissionAircraftNumber]->Sentient=0;//Resetthe"Sentient"attributeofthisnewaircraft(allstartoutasbots)ThreeDObjects[MissionAircraftNumber]->thrustUp();//GivethisbotsomethrustThreeDObjects[MissionAircraftNumber]->thrustUp();//AndevenabitMOREthrust....////Thisisagoodpointtogeneratesomerun-timediagnosticreportingandupdateourlogfileaboutthisnewaircraft://sprintf(DebugBuf,"MissionNetworkBattle05::processTimer() spawning new aircraft %d at X=%f Y=%f Z=%f",MissionAircraftNumber,ThreeDObjects[MissionAircraftNumber]->tl->x,ThreeDObjects[MissionAircraftNumber]->tl->y,ThreeDObjects[MissionAircraftNumber]->tl->z);display(DebugBuf,LOG_MOST);//NowmakesureournewaircraftisNOTlugginganymissilesorbombs:for(i=0;i<missiletypes;i++){ThreeDObjects[MissionAircraftNumber]->missiles[i]=0;}//Thisaircraftmaystillbeintheprocessofexploding.Weshouldstopthat:ThreeDObjects[MissionAircraftNumber]->explode=0;//Stoptheexplosion.//BotsbehavebestiftheydoNOThaveatarget:ThreeDObjects[MissionAircraftNumber]->target=NULL;}//Endoflogicthatreplacesdestroyedaircrafttokeepthemissionrunningforawhile.}//Endofloopthatexamineseachmissionaircrafttopreservetheirtypeandrespawnthosedestroyed.//Checktoseeiftheplayer's aircraft has been destroyed:if(!ThreeDObjects[0]->active){//Getherewhenevertheplayer's aircraft has been destroyed.NetworkPlayerKilled=true;//Stopthisaircraftfromgeneratinganysounds:sound->stop(SOUND_PLANE1);sound->stop(SOUND_PLANE2);sound->stop(SOUND_WINDNOISE);WindNoiseOn=false;}if(MumbleTimeRemainingBeforeChannelReset<1000){//Gethereifit's been too long since our last Mumble commandif(MumbleManagement){event_CommsMacro17();//ResetplayertoproperMumbleTeamCastchannel//NowformatamessagetobedisplayedontheCockpit's "SystemMessage Panel":sprintf(SystemMessageBufferA,"MUMBLE RESET TO TEAMCAST CHANNEL.");//Andinformcockpit.cpptoscrollournewmessageintoview:NewSystemMessageNeedsScrolling=true;sound->setVolume(SOUND_BEEP1,60);//@Medium-volumebeepsound->play(SOUND_BEEP1,false);}else{//GethereifuserdisabledLAC's management of Mumble channel changes.////WecannotcommandMumbletochangechannels,butweknowthat//alloftheotherteammembershaveprobablychangedchannels,and//it's a good idea to inform the player about that://MumbleChannelPresumed=95;//@SignalcockpitMumblePanelif(!(NetworkMode&16)){//GethereifMumblevocalizationisNOTdisabled.popen("espeak -p 10 -a 66 -s 160 \"Team is switching back to the TeamCast Channel.\"","r");}sprintf(SystemMessageBufferA,"TEAM SWITCHING TO TEAMCAST CHANNEL.");//Andinformcockpit.cpptoscrollournewmessageintoview:NewSystemMessageNeedsScrolling=true;}//NowmakesurewewilldothisagainafteraLONGtime,toforce//everybodytomonitortheappropriateMumblechannelperiodically:MumbleTimeRemainingBeforeChannelReset=10000000;//10,000seconds}if(MissionNetworkBattleRadarTimer>100){//Gethere10times/second.MissionNetworkBattleRadarTimer=0;//Resetthistimerinpreparationfornexttime...////Thisloopisahandyplaceforanyspecialcodethatneedsto//beactivatedperiodicallyforsmoothmotion,likemoving//carriersortestingtoseeiftheoperatorhasactivated//"Autopilot",etc://AutoPilot();//Ifplayerhasrequested"AutoPilot",holdthisaltitude.}//Endloopthatgetsexecuted10timespersecond.if(MissionNetworkBattle05Timer>1000){//Gethereonceeverysecond.MissionNetworkBattle05Timer=0;////Thisloopisahandyplacetoprocesseventsthatdon't need//attentionveryoften,likecheckingfor"Fratricide"andgradually//"aging"slowprocesseslike"GoodMenuBehavior"and"Sentient"//level.//if(OnTheGround){//@IflandedANYWHEREsafely,attemptsomeminorrepairsforthedistressedpilotif(fplayer->realspeed<((fplayer->StallSpeed)*0.2)){//@Gethereifgroundspeedisverylow.Commencerepairs,refuel,etc.if(fplayer->FuelLevel<95){fplayer->FuelLevel=(0.25+(fplayer->FuelLevel*1.01));}if(fplayer->ammo<1600){fplayer->ammo=(1.0+(fplayer->ammo*1.05));}if(fplayer->Durability<fplayer->maxDurability){fplayer->Durability*=1.01;}if(fplayer->Durability>fplayer->maxDurability){fplayer->Durability=fplayer->maxDurability;}}else{//@Gethereifgroundspeedisstilltoohighforgroundservicesif(!fplayer->UndercarriageLevel){//@Gethereiflandinggearisnotextended.Accumulatedamagefplayer->Durability*=0.7;fplayer->Durability-=((fplayer->maxDurability)/3.0);//Makesureitcangonegative.}}}MilestoneCorrectionCheck();////CheckforrecentFratricideinfractions://if(FratricideShameFactor<60000.0){//GethereifrepentenceisstillpossibleFratricideShameFactor*=0.80;//Shamedoesn't last forever...if(FratricideShameFactor<=50){//Gethereifit's been a long time since shameful activityFratricideShameFactor=0;//Eraseanyremainingshame....}}if(FratricideShameFactor>50){//GethereifweshouldbeashamedofourselvesforfratricideIffOnOff=0;//Punishmentforrecent,possiblyinnocent,fratricideattempt(s)//FormatamessagefordisplayoncockpitSystemMessagePanel:sprintf(SystemMessageBufferA,"IFF DEACTIVATED");//Nowsetaflagtoinformcockpit.cpptoscrollthatmessageintoview:NewSystemMessageNeedsScrolling=true;}if(FratricideShameFactor>40000){//GethereifweshouldbeashamedofourselvesforfratricideIffOnOff=0;//Punishmentforrecent,veryseriousfratricideattempt(s)RadarOnOff=0;//MorepunishmentHudOnOff=0;//Morepunishment//FormatamessagefordisplayoncockpitSystemMessagePanel:sprintf(SystemMessageBufferA,"IFF, RADAR, & TACTICAL STATUS DEACTIVATED");//Nowsetaflagtoinformcockpit.cpptoscrollthatmessageintoview:NewSystemMessageNeedsScrolling=true;}////LAC's online missions use the value of "Sentient" to determine whether//amissionaircraftisbeingflownbyahumanorifitisabot.Higher//numbersof"Sentient"mean,withincreasingprobability,thatthe//correspondingaircrafthasrecentlybeenflownbyahuman.Lower//valuesof"Sentient"meanthatithasbeenalongtimesinceahuman//controlledthecorrespondingaircraft,soitsrecentmovementshave//beendrivenbylocal"bot"logic". This is a handy place to diminish//thevalueof"Sentient"forallaircraftsothatitwilleventually//"expire"downtowardzero.(Notethateveryaircraftinthemissionis//assigneda"Sentient"attribute,andthatthevalueof"Sentient"is//incrementedbymission.cpp's "LoadVariablesFromNetworkApiPacket()"//functioneverytimeanetworkInPacketisreceivedforeachaircraft.//ThoseInPacketsarrive5timespersecondfromeverynearbyaircraft//flownbyareal,livehumanopponent,sothisvalueof"Sentient"will//generallybequitehigh.Itonlygetsdownbelowzeroafterthelogic//inthis"once-per-second"loopslowlycountsitdownor"expires"it://intAircraftCount;for(AircraftCount=0;AircraftCount<=10;AircraftCount++){//Examineeveryaircraftinthemissionif(ThreeDObjects[AircraftCount]->Sentient>1){//IfthisaircraftwasflownbyaSentientrecentlyThreeDObjects[AircraftCount]->Sentient--;//"Age"theSentientvaluesoitexpiresifnotrefreshedbymoreInPackets}}if(GoodMenuBehavior>1){//GoodMenuBehaviordosen't last forever.GoodMenuBehavior--;if(GoodMenuBehavior<2){ReturnedToCombat=false;//"ReturnedToCombat"signalsotherlogic,possiblytoguardagainstcheating.}}if(ReturnedToCombat&&GoodMenuBehavior<2){//Gethereiftheplayerpreviouslypressed<ESC>thenreturnedtoflight,buthasnotyetbeenfullypunishedsound->play(SOUND_BEEP1,false);fplayer->Durability*=0.05;//Punishplayerwithalotofnewdamagefplayer->Durability--;sprintf(SystemMessageBufferA,"ABUSE OF <ESC> DETECTED.");NewSystemMessageNeedsScrolling=true;if(!(NetworkMode&16)){//Gethereiftheuserhasnotdisabledespeakpopen("espeak -p 130 -a 127 -s 165 \"Escape abuse detected.\"","r");}}if(MissionIdNegotiationCount>32){//Gethereifwe've been unable to negotiate unique value for "MyNetworkId" after 32 attemptssound->setVolume(SOUND_BEEP1,20);//andbeepsoftlysound->play(SOUND_BEEP1,false);sprintf(SystemMessageBufferA,"THIS MISSION IS FULL. TRY ANOTHER.");NewSystemMessageNeedsScrolling=true;}RepairDamagedAirfields();//Goodtodothisonceeachsecond.}//endof(MissionNetworkBattle05Timer>1000)BattleDamageRiskTimer+=DeltaTime;if((BattleDamageRiskTimer>5000)||(BattleDamageRiskTimer>(abs)(myrandom(131072)))){//Gethereatleastevery5seconds,orpossiblysoonerbyrandomchanceBattleDamageRiskTimer=0;CalcDamageRiskFromNearbyOpposition();//DetermineifwesufferdamagefromenemybombersorairfieldThreeDObjects[0]->Durability-=CalculatedDamageDueToCurrentRisk;//Admitdamageforriskwetook.if(CalculatedDamageDueToCurrentRisk>0){//Gethereonceeverytimewesuffernewdamage.Logit...sprintf(DebugBuf,"MissionNetworkBattle05::processTimer() fplayer->Durability is now %f.",fplayer->Durability);display(DebugBuf,LOG_MOST);if(fplayer->Durability<0){//Gethereifdamagefromlocallymanagedairfieldsorbomberskilledus.UpdateOnlineScoreLogFileWithCalculatedRisks();//Logit...}}CalculatedDamageDueToCurrentRisk=0;//Afteradmittingthatdamageamount,clearit.}MissionTenSecondTimer+=DeltaTime;if(MissionTenSecondTimer>10000){//Gethereonceevery10secondsMissionTenSecondTimer=0;//Willexpireagainin10moreseconds////Insertanymission-specificcodeherethatmightbeappropriatefor//attentionjustonceeverytenseconds://}StaticObjectUpdateTimer+=DeltaTime;if(StaticObjectUpdateTimer>2000){//Getherewhenit's time to update network peers regarding any damaged airfields, etc.floatTempFloat1;StaticObjectUpdateTimer=0;//Resetthistimerforoverflowin2moreseconds.////Gethereaboutonceevery2seconds.////Nowcheckthe"Durability"attributeofstatic3dobjects(likeairfieldfacilities)//toseeifonecanbefoundthathassustainedbattledamage.Ifso,invertthevalue//ofthatDurabilityattribute(resultinginanegativenumber)sothatotherlogicwill//transmitandinterpretitasanabsolutevalueinsteadofarelativedamagevalue.////ThisisbecauseLAC's "classic" missions use negative "Durability" numbers as a special//signaltooneanother.Anegative"Durability"indicatesbroadcastorreceptionof//thetrue,currentmaintenancestateofoneofthemissionresourcefacilities.Positive//values,ontheotherhand,indicateaCHANGEindurabilityinsteadoftheactual,//correct,currentvalue.Fromtimetotime,eachLACclienttransmitsthesenegative//numbersas"static updates"sothatotherscanknowifamissionobjectismoredamaged//thantheythought.Thisblockoflogic,invokedaboutonceinfourseconds,checksall//importantmissionresourcestoseeifoneisdamaged.Ifso,oncein4seconds,itsvalue//isconvertedintoanegativenumberandtransmittedtotheserver,whichrelaysitoutto//allothernearbyplayers.Otherlogicreceivesthesenegativenumbersand,ifamission//resource(likeanairfield,battleship,artillerybattery,aircraftcarrier,ornaval//destroyer)wasmoredamagedthanpreviouslyknown,thenewvalueover-writestheold//value.ThisisoneofTWOmeansbywhichdamageispropogated.Theothermeanscomes//aboutmorefrequently:Atleast5timespersecond,everyplayersendsan"OutPacket"//totheserveradvertisinghisposition,orientation,speed,andotherdetails.Those//packetscanalso"claim"tohavedamagedotherplayersormissionobjects.That's how//youtakeandreceivemostbattledamage.////Airfielddamageiscomplicated,becauseyoucan"claim"tohavedamagedanairfield,//butyouarealsomakingrepairstoyourownairfieldatvariousrates.Accordingly,//theexchangeofnetworkpacketsimplementskindofanonline"debate"aboutthe//trueairfieldstrength.Theultimatestrengthresultsfromakindofacompromise//amongalloftheseclaimsandstaticupdates.Duringalloftheseupdatesand//exchanges,therecipientofanynewairfieldstatusinformationisalwaysrequired//toaccepttheWORSTstatus,soifanybodyknowsofanyNEWdamage,notpreviously//knowntoothers,itprevailsoveranystaleinformation.//StaticUpdateSwitcher++;if(StaticUpdateSwitcher==1){//Gethereifit's time to handle MissionObjectHqBlueif(ThreeDObjects[MissionObjectHqBlue]->active){//GethereifthisobjecthasNOTbeendestroyed.IssueStaticupdateofitsstatus.TempFloat1=ThreeDObjects[MissionObjectHqBlue]->Durability;TempFloat1*=-1.0;//MakeitanegativenumbertotriggerstatictransmissionlogicThreeDObjects[MissionObjectHqBlue]->DamageInNetQueue=TempFloat1;}else{//@GethereifthisMissionObjecthasbeendestroyed.//Informallotherplayerstodrainitsrepairstatedownto0.01:ThreeDObjects[MissionObjectHqBlue]->DamageInNetQueue=-0.01;}}elseif(StaticUpdateSwitcher==2){//Gethereifit's time to handle MissionObjectHqRedif(ThreeDObjects[MissionObjectHqRed]->active){//GethereifthisobjecthasNOTbeendestroyed.IssueStaticupdateofitsstatus.TempFloat1=ThreeDObjects[MissionObjectHqRed]->Durability;TempFloat1*=-1.0;//MakeitanegativenumbertotriggerstatictransmissionlogicThreeDObjects[MissionObjectHqRed]->DamageInNetQueue=TempFloat1;}else{//@GethereifthisMissionObjecthasbeendestroyed.//Informallotherplayerstodrainitsrepairstatedownto0.01:ThreeDObjects[MissionObjectHqRed]->DamageInNetQueue=-0.01;}}if(StaticUpdateSwitcher>6){//Gethereifwe've exausted all of this mission'suseinstancesof"StaticUpdateSwitcher".Resetit:StaticUpdateSwitcher=0;}}////UpdateNetworkReceiveTimeranddetermineifit's now time//tocheckforarrivalofanewNetworkApiUDPpacket://NetworkReceiveTimer+=dt;if(NetworkReceiveTimer>NetworkReceiveTimerInterval){//GethereeverytimeNetworkReceiveTimerexpires.CheckfornewInPacket:NetworkReceiveTimer=0;//Resettimerinpreparationfornextexpiration.BytesReceived=GetNetworkApiPacket();if(BytesReceived==sizeof(LacUdpApiPacket)){//GethereifanewInPackethasarrived.//Reportthisforrun-timedebuggingandlogitinlogfile:display((char*)"MissionNetworkBattle05 BytesReceived=",LOG_NET);sprintf(DebugBuf,"%i",BytesReceived);display(DebugBuf,LOG_NET);//NowprocessthatInPacket,extractingeverythingofvaluefromit:LoadVariablesFromNetworkApiPacket(timer);if(MissionNetworkBattle05PriorAircraft[InPacket.UdpObjPlayerNumber]!=InPacket.UdpObjVehicle){//Gethereifthisnetworkpeerisinadifferenttypeofaircraft////Nowwemusttellhigher-levellogicaboutthenewaircrafttype.Thisis//associatedasthe"id"attributeofeachmissionobject,andis//trackedwithinthe"ThreeDObjects[]"arrayasfollows://ThreeDObjects[InPacket.UdpObjPlayerNumber]->id=(int)InPacket.UdpObjVehicle;////Andsincethisremoteplayerisnowinadifferenttypeofaircraft,we//nowneedtoreinitializehimasfollows://ThreeDObjects[InPacket.UdpObjPlayerNumber]->newinit(ThreeDObjects[InPacket.UdpObjPlayerNumber]->id,0,400);}//NowpreservethisInPacket's aircraft type for comparison with the next InPacket for this player:MissionNetworkBattle05PriorAircraft[InPacket.UdpObjPlayerNumber]=InPacket.UdpObjVehicle;}//end"Get here if a new InPacket has arrived".}//EndoflogicthathandlesexpirationofNetworkReceiveTimer.////UpdateNetworkTransmitTimeranddetermineifit's now time//tosendanewNetworkApiUDPpacket://NetworkTransmitTimer+=dt;if(NetworkTransmitTimer>NetworkTransmitTimerInterval&&!NetworkPlayerKilled){//Gethereifwe're alive and it'stimetosendanewnetworkAPIpacket.NetworkTransmitTimer=0;//Findoutifwe've damaged anything since our last OutPacket:MissionNetworkBattle05RetrieveFirstDamageDescription();//OK,nowourOutPacketisready.Transmitit:SendNetworkApiPacket();}////Checkformission-endingconditions.ThismissionendswheneitherRedTeamorBlueTeam//destroystheopposingHQairfieldandtheopposingAirfield#1://staticboolBlueHqAlive=true;staticboolRedHqAlive=true;staticboolBlueAirfield2Alive=true;staticboolRedAirfield2Alive=true;staticboolBlueTeamHasWonTheBattle=false;staticboolRedTeamHasWonTheBattle=false;if(ThreeDObjects[MissionObjectHqBlue]->active){BlueHqAlive=true;}else{BlueHqAlive=false;}if(ThreeDObjects[MissionObjectHqRed]->active){RedHqAlive=true;}else{RedHqAlive=false;}if((BlueHqAlive==false)&&(BlueAirfield2Alive==false)){BlueTeamHasWonTheBattle=true;}if((RedHqAlive==false)&&(RedAirfield2Alive==false)){RedTeamHasWonTheBattle=true;}if(BlueTeamHasWonTheBattle||RedTeamHasWonTheBattle){//GethereifoneofthetwoteamshaswonthebattlestaticboolCountdownLatch1=false;staticboolCountdownLatch2=false;MissionEndingTimer-=dt;//Diminishbymillisecondsif(MissionEndingTimer<-200&&CountdownLatch1==false){//Gethere5secondsaftereitherteamwinsthebattle.display((char*)"MissionNetworkBattle05::processtimer() Playing audio file MissionEndingInstrumental.wav",LOG_MOST);sound->play(SOUND_MISSIONENDINGINSTRUMENTAL,false);CountdownLatch1=true;//Preventimmediaterestartofthataudiofile.}if(MissionEndingTimer<-1000&&CountdownLatch2==false){//Gethere10secondsaftereitherteamwinsthebattle.display((char*)"MissionNetworkBattle05::processtimer() Playing audio file MissionEndingIn15SecCountdown.wav",LOG_MOST);sound->play(SOUND_MISSIONENDINGIN15SECCOUNTDOWN,false);if(!(NetworkMode&16)){popen("espeak -p 10 -a 66 -s 140 \"Mission ending in 15 seconds.\"","r");}CountdownLatch2=true;//Preventimmediaterestartofthataudiofile.MissionEndingTimer2=17000;//Allow17secondsfornextphase.}}if(MissionEndingTimer2){//Getheremanytimes,butonlyafterthe"countdown warning audio"hasbegunplaying.MissionEndingTimer2-=dt;//Diminishbymillisecondsif(MissionEndingTimer2<1000){//Gethere16secondsafter"Countdown warning audio"started.//Allconditionstoforciblyendmissionaresatisfieddisplay((char*)"MissionNetworkBattle05::processtimer(): Mission ending now.",LOG_MOST);fplayer->Durability=-1.0;//SignalDestructionofplayerandendthemission.}}return0;}//endMissionNetworkBattle05::processtimer(Uint32dt)////Thisfunctionisnolongerimportant.EarlierversionsofLACusedthis//functiontoinsertpromptingtextattimedintervals,butmorerecent//missionshaven't been using this file. Developers need not add anything//here.//voidMissionNetworkBattle05::draw(){if(timer>=0&&timer<=50*timestep){font1->drawTextCentered(0,12,-2,name,&textcolor);}}//endMissionNetworkBattle05::draw()////MissionNetworkBattle05RetrieveFirstDamageDescription()////Thisfunctionwillsearchthe"DamageInNetQueue"memberamongallmissionobjects.//Ifnoneofthemhavesustainedanydamage,itwillsetthenewglobalinteger//"MissionAircraftDamaged"to0anditwillalsosetthenewglobalfloatvariable//"DamageToClaim"to0.0andreturnfalse.Ontheotherhand,assoonasitfinds//anyobjectwithdamage,itcopiesthefloating-pointdamagevalueinto"DamageToClaim",//clearsouttheassociated"DamageInNetQueue",storestheassociatedmissionaircraft//numberin"MissionAircraftDamaged",andreturnstrue.////Missiondesigners:Youprobablydon't want to change any of this logic!//boolMissionNetworkBattle05RetrieveFirstDamageDescription(){intMission3dObject;display((char*)"MissionNetworkBattle05RetrieveFirstDamageDescription()",LOG_NET);for(Mission3dObject=1;Mission3dObject<=10;Mission3dObject++){//LoopthroughallmissionaircraftEXCEPTThreeDObjects[0],whichrepresentsthehumanplayer.if(ThreeDObjects[Mission3dObject]->DamageInNetQueue>0.0){//Gethereassoonaswefindanydamagetoclaim.Clientswillsubtractthedamageamounttheyreceive.DamageToClaim=ThreeDObjects[Mission3dObject]->DamageInNetQueue;//PositivevaluesignalsnewdamageThreeDObjects[Mission3dObject]->DamageInNetQueue=0.0;MissionAircraftDamaged=Mission3dObject;returntrue;}if(ThreeDObjects[Mission3dObject]->DamageInNetQueue<0.0){//Gethereifit's time to transmit a static damage value. Clients will update damage to received value.DamageToClaim=ThreeDObjects[Mission3dObject]->DamageInNetQueue;//NegativevaluesignalsstaticupdateThreeDObjects[Mission3dObject]->DamageInNetQueue=0.0;MissionAircraftDamaged=Mission3dObject;returntrue;}}//GethereifwehavenodamagetoclaimMissionAircraftDamaged=0;DamageToClaim=0.0;return(false);}//endMissionNetworkBattle05RetrieveFirstDamageDescription()
Last edit: bbosen 2023-02-21
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Here is an improved version of "MissionNetworkBattle05.cpp" which is also known as "Blake's Mission". This derives from LAC Version 8.95. None of the Version 8.95 logic is changed, but I corrected some confusing language in some comment text and significantly expanded other comment areas.
(I plan to make similar improvements to the source code commentary for all of the other "MissionNetworkBattleXX.cpp" files as time permits.)
Last edit: bbosen 2023-02-21