#41
|
|||
|
|||
Quote:
Thanks |
#42
|
|||
|
|||
Player Class: PlaceEnter(Actor, Placeindex)
example: player.PlaceEnter(Aircraft, 0); |
#43
|
|||
|
|||
Thanks,
|
#44
|
|||
|
|||
New/updated service vehicle, ambulance, fire truck mission plug-in
Thanks to everyone who posted about the ambulance script on this thread. I've worked on an updated version of it that is designed to work in multiuser servers (though it should work offline just as well).
- Vehicles spawn in along with you & then drive off (ie, your service vehicles just finished with getting your a/c ready, then they drive off) - When you land (full stop landing--putting chocks in will make sure) the fuel & repair trucks will come trundling up pretty soon. - Whenever you crash, even just borking up a takeoff & damaging your propeller & undercarriage, you'll soon be visited by an ambulance and a fire truck. Even if you crash out in the middle of nowhere. Only exception would be in water--they if close to the shore the emergency vehicles will do their best & drive right up to the shore. (Rescue boats will hae to come in a future version I guess. Someone to pick you up when you parachute in could be a future improvement as well.) - Vehicles mostly avoid you but if you hit them they WILL damage you. So you have to look sharp & avoid. - Vehicles travel to & from Spawn Points (ie, "Birthplace" in the .mis files) preferentially. They always travel more or less directly between the target aircraft & an area immediately around the spawn point .This gives you general control over where the vehicles appear & where they travel to/park just by moving the spawn point at your airfield in FMB. - I couldn't get the "reuse old vehicles at the same airport" code to work at all, so this simply spawns in new vehicles every time & then spawns them out after they are no longer needed. It seems to work fine so far. -You're welcome to use as is or adapt for use in your own scripts, missions, servers, etc. - It's designed to be a painless plug-in to any existing mission. It's a self-standing mission, so you just put it in your mission folder & then load it as a sub-mission during OnBattleStarted(). ZIP file with script & mission files, sample code, instructions all in one FILE: auto-generate-vehicles.cs <see separate message> The mission file is just a stub and you don't need anything in it except the headers (and maybe not even those--I haven't really experimented). It just allows your main .cs file to load the auto-vehicle-generate.cs neatly as a sub-mission. However I like to keep a minimal .mis file in place with a map, weather, etc. because then you can edit & run it easily in FMB. That is helpful for testing. Here is my sample .mis file: FILE: auto-generate-vehicles.mis Code:
[PARTS] core.100 bob.100 [MAIN] MAP Land$Online_Volcanic_Island BattleArea 6000 1700 21000 38000 1000 TIME 12 Army 1 gb Army 2 de WeatherIndex 0 CloudsHeight 1000 BreezeActivity 0 ThermalActivity 0 [GlobalWind_0] Power 0.000 0.000 0.000 BottomBound 0.00 TopBound 1500.00 GustPower 5 GustAngle 0 [splines] [CustomChiefs] [Stationary] [Buildings] [BuildingsLinks] [Airdromes] FILE: main.cs Code:
public override void OnBattleStarted() { base.OnBattleStarted(); ReadInitialSubmissions(MISSION_ID + "-auto-generate-vehicles", 0, 0); //etc . . . your code } } Code:
public void ReadInitialSubmissions(string filenameID, int timespread=60, int wait=0) { string MISSION_ID = "M001"; string USER_DOC_PATH = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // DO NOT CHANGE string CLOD_PATH = USER_DOC_PATH + @"/1C SoftClub/il-2 sturmovik cliffs of dover - MOD/"; // DO NOT CHANGE string FILE_PATH = @"missions/Multi/MyMissionFolder"; // mission install directory (CHANGE AS NEEDED - your sub-mission .mis and .cs files should be in this directory) List<string> InitSubMissions = GetFilenamesFromDirectory(CLOD_PATH + FILE_PATH, filenameID); // gets .mis files with with word filenameID in them DebugAndLog ("Debug: Loading " + InitSubMissions.Count + " missions to load. " + filenameID + " " + CLOD_PATH + FILE_PATH); foreach (string s in InitSubMissions) { //Distribute loading of initial sub-missions over the first timespread seconds //If you make each sub-mission small enough it will load without a noticeable stutter //If they are large & make a noticeable stutter, probably best to load them all very near the beginning of the mission //so that all the stutters happen at that point if ((timespread==0) && (wait==0)) { GamePlay.gpPostMissionLoad(s); DebugAndLog( s + " file Loaded"); } else { Timeout(wait + random.Next(timespread), () => { GamePlay.gpPostMissionLoad(s); }); } } } Code:
////////////////////////////////////////////////////////////////////////////////////////////////// //Listen to events of every mission public override void Init(maddox.game.ABattle battle, int missionNumber) { base.Init(battle, missionNumber); MissionNumberListener = -1; //Listen to events of every mission //This is what allows you to catch all the OnTookOff, OnAircraftDamaged, and other similar events. Vitally important to make this work! //If we load missions as sub-missions, as we often do, it is vital to have this in Init, not in "onbattlestarted" or some other place where it may never be detected or triggered if this sub-mission isn't loaded at the very start. } ////////////////////////////////////////////////////////////////////////////////////////////////// I believe that conf.ini pertains to your regular Launcher.exe process and confs.ini applies if you are running "Launcher.exe -server" as a dedicated server. Note that you will need to exit Launcher.exe, then edit and save conf.ini & confs.ini, then re-start Launcher.exe. If you don't follow this process, your conf.ini and/or confs.ini will be overwritten when Launcher.exe exits. Code:
[rts] scriptAppDomain=0 ;avoids the dreaded serialization runtime error when running server or testing missions in FMB ;per http://forum.1cpublishing.eu/showthread.php?t=34797 Again: ZIP file with script & mission files, sample code, instructions all in one Last edited by flug32; 05-23-2016 at 12:00 AM. |
#45
|
|||
|
|||
Here is part 1/2 of the actual .cs code for FILE: auto-generate-vehicles.cs
Code:
// //Various emergency & service cars script created by posters at http://forum.1cpublishing.eu/showthread.php?t=26112 and by naryv //Hacked extensively by flug //$reference parts/core/Strategy.dll //$reference parts/core/gamePlay.dll //$reference System.Core.dll using System; //using System.Core; using System.Collections; using maddox.game; using maddox.game.world; using maddox.GP; using part; using System.Collections.Generic; using System.IO; using System.Text; using System.ComponentModel; using System.Threading; using System.Diagnostics; public class Mission : AMission { public bool DEBUG=false; public int VEHICLE_LIFE_SEC = 120; public double CAR_POS_RADIUS = 80; //distance vehicles will be positioned from the center point of the Birthplace, Airfield, etc where cars are positioned public int TICKS_PER_MINUTE=1986; //empirically, based on a timeout test. This is approximate & varies slightly. //for landing or crash, they start SPAWN_START_DISTANCE_M away from the plane in the direction of the nearest BirthPlace or Airport point. They end SPAWN_END_DISTANCE_M away from the a/c. (Distances are approx., various randomness & functions added on top of these values.) public int SPAWN_START_DISTANCE_M = 100; //how far away they start from the a/c when approaching after landing public int SPAWN_END_DISTANCE_M = 20; //how close they approach you upon (eg) landing //For spawn-in, the vehicles start this close to the a/c and proceed to // the birthplace or airport point. public int SPAWN_START_DISTANCE_REVERSE_M = 12; //how close they start when spawning in onPlaceEnter private List<AiActor> actorPlaceEnterList; //HashSet doesn't work for some reason; it would be a better solution private List<AiAircraft> aircraftDamagedList; private List<AiAircraft> aircraftActiveList; maddox.game.ABattle Battle; public Mission () { //HashSet<int> evenNumbers = new HashSet<int>(); actorPlaceEnterList = new List<AiActor>(); aircraftDamagedList = new List<AiAircraft>(); aircraftActiveList = new List<AiAircraft>(); } //Listen to events of every mission public override void Init(maddox.game.ABattle battle, int missionNumber) { base.Init(battle, missionNumber); Battle=battle; MissionNumberListener = -1; //Listen to events of every mission //This is what allows you to catch all the OnTookOff, OnAircraftDamaged, and other similar events. Vitally important to make this mission/cs file work! //If we load missions as sub-missions, as we often do, it is vital to have this in Init, not in "onbattlestarted" or some other place where it may never be detected or triggered if this sub-mission isn't loaded at the very start. if (DEBUG) GamePlay.gpLogServer(null, ".Net framework: " + Environment.Version, new object[] { }); } public override void OnBattleStarted() { base.OnBattleStarted(); //MissionNumberListener = -1; } Random rnd = new Random(); [Flags] internal enum ServiceType // ??? ????????????? ??????? //note that all these types don't work; the actual type is determined by //createemrgcarmission depending on a/c type, army, and a few other things. //So it's not really determined by the settings in the curTechCar.CarType field { NONE = 0, EMERGENCY = 1, FIRE = 2, FUEL = 4, AMMO = 8, BOMBS = 16, PRISONERCAPTURE = 32, SPAWNIN = 64 } //Like AiActor or AiBirthplace but only has .Name() & .Loc() internal class BasePos { internal string _Name; internal Point3d _Pos; public BasePos (string name, Point3d pos) { if (name!=null) this._Name=name; else this._Name=""; //if (pos!=null) this._Pos=pos; //else this.Pos=new Point3d(0,0,0); } public BasePos (BasePos bp) { this._Name=bp.Name(); this._Pos=bp.Pos(); Console.WriteLine ("BasePos inited: " + this.ToString ("F2")); } //a default constructor . . . public BasePos (object o=null) { this._Name=""; this._Pos=new Point3d(0,0,0); } public string Name(string name=null) { if (name==null) return this._Name; else { this._Name=name; return null; } } public Point3d Pos(Point3d pos) { this._Pos=pos; return this._Pos; } public Point3d Pos() { return this._Pos; } public string ToString (string format){ return _Name + " " + _Pos.x.ToString( format ) + " " + _Pos.y.ToString( format ) + " " + _Pos.z.ToString( format ); } } internal class TechCars { internal AiGroundGroup TechCar { get; set; } internal BasePos basePos { get; set; } internal IRecalcPathParams cur_rp { get; set; } internal int RouteFlag = 0; internal int cartype = 0; internal int servPlaneNum = -1; internal int MAX_CARS = 100; internal ServiceType CarType { get { return (ServiceType)cartype; } set { cartype = (int)value; } } public TechCars(AiGroundGroup car, BasePos airoport, IRecalcPathParams rp) { this.TechCar = car; this.basePos = airoport; this.cur_rp = rp; Console.WriteLine("TechCars created. basePos: " + this.basePos.ToString("F2")); } } internal class PlanesQueue { internal AiAircraft aircraft { get; set; } internal BasePos basePos { get; set; } internal int state = 0; internal ServiceType State { get { return (ServiceType)state; } set { state = (int)value; } } internal int Lifetime = 0; internal float health = 1; public PlanesQueue(AiAircraft aircraft, BasePos basePos, int state) { this.aircraft = aircraft; this.basePos = basePos as BasePos; this.state = state; } } internal List<TechCars> CurTechCars = new List<TechCars>(); internal List<PlanesQueue> CurPlanesQueue = new List<PlanesQueue>(); TechCars TmpCar = null; bool MissionLoading = false; int MissionLoadingAircraftNumber = -1; internal double PseudoRnd(double MinValue, double MaxValue) { return rnd.NextDouble() * (MaxValue - MinValue) + MinValue; } public override void OnActorTaskCompleted(int missionNumber, string shortName, AiActor actor) { base.OnActorTaskCompleted(missionNumber, shortName, actor); if (DEBUG) GamePlay.gpLogServer(null, "OnActorTaskComplete", new object[] { }); AiActor ai_actor = actor as AiActor; if (ai_actor != null) { if (ai_actor is AiGroundGroup) for (int i = 0; i < CurTechCars.Count; i++) // ???? ????????????? ??????? ??????? ?? ?????????????? ????????, ????????? ?? ???????????? { if (CurTechCars[i].TechCar == ai_actor as AiGroundGroup) { //if (CurTechCars[i].RouteFlag == 1) TechCars car = CurTechCars[i] as TechCars; if (DEBUG) GamePlay.gpLogServer(null, "OnActorTaskComplete - ending plane service for " + i.ToString() + " in 120 sec.", new object[] { }); //this is basically to ensure that AI objects don't just hang around indefinitely when their tasks are done. //In normal behavior, they may complete several tasks in the course of moving abou the airport, so we don't just want //to destroy them immediately when task is done Timeout(VEHICLE_LIFE_SEC, () => { if (DEBUG) GamePlay.gpLogServer(null, "OnActorTaskComplete - ending plane service for " + i.ToString() + " now", new object[] { }); EndPlaneService(car, ai_actor as AiGroundGroup); }); } //we're just destroying them @ this point // else // CheckNotServicedPlanes(i); }; } } internal void CheckNotServicedPlanes(int techCarIndex) { for (int j = 0; j < CurPlanesQueue.Count; j++) { if (CurTechCars[techCarIndex].TechCar.IsAlive() && (CurPlanesQueue[j].basePos == CurTechCars[techCarIndex].basePos) && ((CurTechCars[techCarIndex].CarType & CurPlanesQueue[j].State) != 0) && (CurTechCars[techCarIndex].servPlaneNum == -1)) { if (SetEmrgCarRoute(j, techCarIndex)) // ?????????? ??????? ??????????? ????????? ??????? { return; } } } } //Removes the ground vehicle from the CurTechCars list & also destroys the AI object //We call it with the List item (not the index) because the index can change between call & execution, esp. if call via a timeout, which is common //We also include the TechCar field, (an AiGroundGroup) because sometimes the List item can be destroyed but the actual Ai Airgroup is still floating around undead // internal void EndPlaneService(TechCars tC, AiGroundGroup ground=null) { try { if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning now", new object[] { }); if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning " + tC.servPlaneNum.ToString(), new object[] { }); if (tC != null) { if (DEBUG) GamePlay.gpLogServer(null, " Number of objects: " + tC.TechCar.GetItems().Length, new object[] { }); //if (CurTechCars[techCarIndex].cur_rp == null) return; tC.cur_rp = null; // ?????????? ??????? //Just destroy the ground items at this point. if (tC.TechCar.GetItems() != null && tC.TechCar.GetItems().Length > 0) { if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning 1 ", new object[] { }); foreach (AiActor actor in tC.TechCar.GetItems()) { if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning 2 " , new object[] { }); (actor as AiGroundActor).Destroy(); } } CurTechCars.Remove(tC); } if (ground != null) { if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning 3 ", new object[] { }); foreach (AiActor actor in ground.GetItems()) { if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning 4 " , new object[] { }); (actor as AiGroundActor).Destroy(); } } } catch (Exception e) {System.Console.WriteLine (e.ToString());} } internal bool MoveFromRWay(int carNum) { bool result = false; if (DEBUG) GamePlay.gpLogServer(null, "Removing aircraft from runway at " + CurTechCars[carNum].basePos.Name(), new object[] { }); if ((GamePlay.gpLandType(CurTechCars[carNum].TechCar.Pos().x, CurTechCars[carNum].TechCar.Pos().y) & LandTypes.ROAD) == 0) return result; Point3d TmpPos = CurTechCars[carNum].TechCar.Pos(); while (((GamePlay.gpLandType(TmpPos.x, TmpPos.y) & LandTypes.ROAD) != 0)) { TmpPos.x += 10f; TmpPos.y += 10f; }; Point2d EmgCarStart, EmgCarFinish; EmgCarStart.x = CurTechCars[carNum].TechCar.Pos().x; EmgCarStart.y = CurTechCars[carNum].TechCar.Pos().y; EmgCarFinish.x = TmpPos.x; EmgCarFinish.y = TmpPos.y; CurTechCars[carNum].servPlaneNum = -1; CurTechCars[carNum].RouteFlag = 0; CurTechCars[carNum].cur_rp = null; CurTechCars[carNum].cur_rp = GamePlay.gpFindPath(EmgCarStart, 10f, EmgCarFinish, 10f, PathType.GROUND, CurTechCars[carNum].TechCar.Army()); result = true; return result; } public bool SetEmrgCarRoute(int aircraftNumber,int carNum) { bool result = false; if (DEBUG) GamePlay.gpLogServer(null, "Setting a Car Route "+aircraftNumber.ToString() + " " + carNum.ToString() + " at " + CurTechCars[carNum].basePos.Name() , new object[] { }); if (CurTechCars[carNum].TechCar != null) { CurTechCars[carNum].servPlaneNum = aircraftNumber; // ????????????? ????? ?????????????? ???????? if (CurTechCars[carNum].cur_rp == null) { Point2d EmgCarStart, EmgCarFinish, LandedPos; LandedPos.x = CurPlanesQueue[aircraftNumber].aircraft.Pos().x; LandedPos.y = CurPlanesQueue[aircraftNumber].aircraft.Pos().y; int Sign = ((carNum % 2) == 0) ? 2 : -2; EmgCarStart.x = CurTechCars[carNum].TechCar.Pos().x; EmgCarStart.y = CurTechCars[carNum].TechCar.Pos().y; //Drive the car from where it is to the point located in the direction of the aircraft position but 20 meters short of it. double disx, disy; disx=Math.Abs(EmgCarStart.x - LandedPos.x) - 20; if (disx<10) disx=20; disy=Math.Abs(EmgCarStart.y - EmgCarStart.y) - 20; if (disy<10) disy=20; EmgCarFinish.x = EmgCarStart.x - disx * ((EmgCarStart.x - LandedPos.x) / Math.Abs(EmgCarStart.x - LandedPos.x)); EmgCarFinish.y = EmgCarStart.x - disy * ((EmgCarStart.y - LandedPos.y) / Math.Abs(EmgCarStart.y - LandedPos.y)); //EmgCarFinish.x = LandedPos.x - PseudoRnd(0f, 1f) * ((LandedPos.x - EmgCarStart.x) / (Math.Abs(LandedPos.x - EmgCarStart.x))) - Sign; //EmgCarFinish.y = LandedPos.y - PseudoRnd(0f, 1f) * ((LandedPos.y - EmgCarStart.y) / (Math.Abs(LandedPos.y - EmgCarStart.y))) - Sign; //For spawn-in, we want the cars to start in close to the a/c & drive away CurTechCars[carNum].cur_rp = GamePlay.gpFindPath(EmgCarStart, 15f, EmgCarFinish, 15f, PathType.GROUND, CurTechCars[carNum].TechCar.Army()); if (DEBUG) GamePlay.gpLogServer(null, "Setting a Car Route "+aircraftNumber.ToString() + " " + carNum.ToString() + " " + EmgCarStart.ToString() + " to " + EmgCarFinish.ToString() + " at " + CurTechCars[carNum].basePos.Name() , new object[] { }); result = true; } } return result; } public override void OnMissionLoaded(int missionNumber) { base.OnMissionLoaded(missionNumber); if (missionNumber > 0) //whenever a new mission loads, this slurps up any matching groundcars into the curTechCars list so they can be manipulated etc //if (missionNumber==MissionNumber ) // important check! { if (DEBUG) GamePlay.gpLogServer(null, "Starting vehicle sub-mission loaded", new object[] { }); List<string> CarTypes = new List<string>(); CarTypes.Add(":0_Chief_Emrg_"); CarTypes.Add(":0_Chief_Fire_"); CarTypes.Add(":0_Chief_Fuel_"); CarTypes.Add(":0_Chief_Ammo_"); CarTypes.Add(":0_Chief_Bomb_"); CarTypes.Add(":0_Chief_Prisoner_"); AiGroundGroup MyCar = null; for (int i = 0; i < 3; i++) { for (int j = 0; j < CarTypes.Count; j++) { MyCar = GamePlay.gpActorByName(missionNumber.ToString() + CarTypes[j] + i.ToString()) as AiGroundGroup; //if (DEBUG) GamePlay.gpLogServer(null, "Creating groundcar group for " +missionNumber.ToString() + CarTypes[j] + i.ToString(), new object[] { }); if (MyCar != null) { TmpCar = new TechCars(MyCar, FindNearestAirport(MyCar), null); if (DEBUG) GamePlay.gpLogServer(null, "Creating groundcar group at " + FindNearestAirport(MyCar).Name() + " " + MissionLoadingAircraftNumber.ToString(), new object[] { }); TmpCar.CarType = (ServiceType)(1 << j); TmpCar.cur_rp = null; TmpCar.servPlaneNum=MissionLoadingAircraftNumber; if (!CurTechCars.Contains(TmpCar)) CurTechCars.Add(TmpCar); //if (CurTechCars.count < MAX_CARS) CurTechCars.Add(TmpCar); //These things are unruly, so we're setting a max life on them. Timeout(2*VEHICLE_LIFE_SEC, () => { (MyCar as AiGroundActor).Destroy(); }); MissionLoading = false; }; } } } } public override void OnTickGame() { base.OnTickGame(); //try { if ( (Time.tickCounter()) == 0) { // if (DEBUG) GamePlay.gpLogServer(null, "Ground vehicles started ", new object[] { }); } if ((Time.tickCounter() % (TICKS_PER_MINUTE/6)) == 12 ) { checkForStoppedAircraft(aircraftActiveList); } if (Time.tickCounter() % 64 == 0) { //if (DEBUG) GamePlay.gpLogServer(null, "Ground vehicles continues . . . ", new object[] { }); for (int i = 0; i < CurPlanesQueue.Count; i++) { CurPlanesQueue[i].Lifetime++; if (DEBUG) GamePlay.gpLogServer(null, "Lifetime: " + CurPlanesQueue[i].Lifetime, new object[] { }); if ((CurPlanesQueue[i].State == ServiceType.NONE) || (CurPlanesQueue[i].aircraft == null) || (CurPlanesQueue[i].Lifetime > (int)((double)VEHICLE_LIFE_SEC*TICKS_PER_MINUTE/64/60))) { foreach ( TechCars car in CurTechCars ) //don't use a for count/index loop here as we are destroying some of the objects mid-loop . . . arghh { if (car.servPlaneNum == i) { if (DEBUG) GamePlay.gpLogServer(null, "Removing ground car for plane " + car.servPlaneNum + " " + car.CarType + " in 5 seconds", new object[] { }); //EndPlaneService(j); Timeout ( 5f, () => { EndPlaneService(car, car.TechCar); }); } } CurPlanesQueue.RemoveAt(i); } }; foreach ( TechCars car in CurTechCars ) // (int i = 0; i < CurTechCars.Count; i++) //again ix-nay on the loop-for-ay . . . . { if (DEBUG) GamePlay.gpLogServer(null, "Ground car at " + car.basePos.Name(), new object[] { }); //TechCars car = CurTechCars[i]; if ((car.TechCar != null && car.cur_rp != null) && (car.cur_rp.State == RecalcPathState.SUCCESS) ) { if (car.TechCar.IsAlive()) // && (car.RouteFlag == 0)) // && (car.servPlaneNum != -1)) { car.RouteFlag = 1; car.cur_rp.Path[0].P.x = car.TechCar.Pos().x; car.cur_rp.Path[0].P.y = car.TechCar.Pos().y; car.TechCar.SetWay(car.cur_rp.Path); //if (car.servPlaneNum != -1) car.RouteFlag = 0; } //The code below avoids the current plane, right? But, I'm worried about these ground vehicles hitting **all the other planes** that might be about this particular airport . . . . maybe some fixup needed double Dist = Math.Sqrt((car.cur_rp.Path[car.cur_rp.Path.Length - 1].P.x - car.TechCar.Pos().x) * (car.cur_rp.Path[car.cur_rp.Path.Length - 1].P.x - car.TechCar.Pos().x) + (car.cur_rp.Path[car.cur_rp.Path.Length - 1].P.y - car.TechCar.Pos().y) * (car.cur_rp.Path[car.cur_rp.Path.Length - 1].P.y - car.TechCar.Pos().y)); if (car.servPlaneNum != -1) { if (Dist < ((CurPlanesQueue[car.servPlaneNum].aircraft.Type() == AircraftType.Bomber) ? 20f : 10f)) //EndPlaneService(i); EndPlaneService(car, car.TechCar); } else if (Dist < 15f) { //EndPlaneService(i); EndPlaneService(car, car.TechCar); } } if ((car.cur_rp == null) && (car.RouteFlag == 0) && (car.servPlaneNum != -1)) { //EndPlaneService(car, car.TechCar); }; if (car.servPlaneNum == -1 || car.TechCar == null) //EndPlaneService(i); //Once it is no longer serving a plane, we just zap it. EndPlaneService(car, car.TechCar); }; } //} catch (Exception e) {System.Console.WriteLine (e.ToString());} } internal BasePos FindNearestAirport(AiActor actor) { try { if (actor==null) return null; Point3d pd = actor.Pos(); if (DEBUG) GamePlay.gpLogServer(null, "Checking airport " + actor.Name(), new object[] { }); return FindNearestAirport(pd) as BasePos; } catch (Exception e) {System.Console.WriteLine (e.ToString()); BasePos ret3=null; return ret3; } } internal BasePos FindNearestAirport(Point3d pd) { try{ AiActor aMin = null; AiBirthPlace aMinB = null; double d2Min = 0; BasePos ret= new BasePos (); BasePos ret2=new BasePos (); Point3d retpd; //If we find a birthplace (ie, spawnpoint) closer than 2km we return that //otherwise we'll search all airports for something closer //And . . AiBirthPlace & AiAirport & AiActor are ALMOST the same thing but then again not quite so we have to dance a bit. aMinB=FindNearestBirthplace(pd); //if (DEBUG) GamePlay.gpLogServer(null, "Checking airport (Birthplace) found " + aMinB.Name() + " " + aMinB.Pos().distance(ref pd).ToString("F0"), new object[] { }); //if (1==0 && aMinB!= null) { if (aMinB!= null) { d2Min=aMinB.Pos().distance(ref pd); //if (DEBUG) GamePlay.gpLogServer(null, "Checking airport (Birthplace) found " + aMinB.Name() + " " + aMinB.Pos().distance(ref pd).ToString("F0") //+ " " + aMinB.Pos().ToString(), new object[] { }); if (d2Min<2000) { retpd=aMinB.Pos(); if (retpd.z==0) retpd.z = pd.z; //BirthPlaces usu. have elevation 0 which makes the ai route finder die horribly ret= new BasePos (aMinB.Name(), retpd); return ret; } } if (DEBUG) GamePlay.gpLogServer(null, "Checking airport (Birthplace) NOfound " + d2Min.ToString("F0"), new object[] { }); int n = GamePlay.gpAirports().Length; for (int i = 0; i < n; i++) { AiActor a = (AiActor)GamePlay.gpAirports()[i]; if (a==null) continue; if (!a.IsAlive()) continue; //if (DEBUG) GamePlay.gpLogServer(null, "Checking airport " + a.Name(), new object[] { }); Point3d pp; pp = a.Pos(); pd.z = pp.z; double d2 = pd.distanceSquared(ref pp); if ((aMin == null) || (d2 < d2Min) ) { aMin = a; d2Min = d2; } } if (DEBUG) GamePlay.gpLogServer(null, "CAirport Found: " + aMin.Name() + " " + aMin.Pos().ToString() + " dist " + d2Min.ToString("F2"), new object[] { }); //Hmm, with our new scheme it doesn't really matter if aMin is very //distant or what. The cars always start relatively close to the a/c //and **in the direction of** the airport, but not *at* the airport //if (d2Min > 2250000.0) // aMin = null; //return aMin as BasePos if (aMin != null) ret2= new BasePos (aMin.Name(), aMin.Pos()); if (DEBUG) GamePlay.gpLogServer(null, "CAirport Returning: " + ret2.Name() + " " + ret2.Pos().ToString() + " dist " + d2Min.ToString("F2") + " " + ret2.ToString("F0"), new object[] { }); return ret2; } catch (Exception e) {System.Console.WriteLine (e.ToString()); BasePos ret3=null; return ret3; } } public AiBirthPlace GetBirthPlaceByName(string birthPlaceName) { foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces()) { if (DEBUG) GamePlay.gpLogServer(null, "Checking airport " + bp.Name(), new object[] { }); if (bp.Name() == birthPlaceName) return bp; } return null; } public AiBirthPlace FindNearestBirthplace(AiActor actor) { //AiBirthPlace nearestBirthplace = null; //AiBirthPlace[] birthPlaces = GamePlay.gpBirthPlaces(); Point3d pos = actor.Pos(); return FindNearestBirthplace(pos); } public AiBirthPlace FindNearestBirthplace (Point3d pos) { AiBirthPlace nearestBirthplace = null; AiBirthPlace[] birthPlaces = GamePlay.gpBirthPlaces(); if (birthPlaces != null) { foreach (AiBirthPlace airport in birthPlaces) { if (nearestBirthplace != null) { //if (DEBUG) GamePlay.gpLogServer(null, "Checking airport " + airport.Name() + " " // + airport.Pos().distance(ref pos).ToString("F0"), new object[] { }); if (nearestBirthplace.Pos().distance(ref pos) > airport.Pos().distance(ref pos)) nearestBirthplace = airport; } else nearestBirthplace = airport; } } //AiActor ret=new AiActor(); //ret.Pos( nearestBirthplace.Pos()); //ret.Name(nearestBirthplace.Name()); if (DEBUG) GamePlay.gpLogServer(null, "Checking airport FOUND" + nearestBirthplace.Name() + " " + nearestBirthplace.Pos().distance(ref pos).ToString("F0"), new object[] { }); return nearestBirthplace; } //CONTINUED IN PART 2! Note that I trimmed down some comments, debugging code, etc to make it fit on the forum better. Full code is in the ZIP file with script & mission files, sample code, instructions all in one Last edited by flug32; 05-22-2016 at 08:39 AM. |
#46
|
|||
|
|||
And, here is part 2/2 of FILE: auto-generate-vehicles.cs
Code:
///TODO: This is highly repetitious & could be abstracted to a single simpler //method called 3X. Then it would be easy to add several more types of //cars etc. internal ISectionFile CreateEmrgCarMission(Point3d startPos, double fRadius, int portArmy, int planeArmy, AircraftType type, float health, Point3d aircraftPos, bool reverse=false, ServiceType planeState=ServiceType.NONE ) //Note that planeState isn't actually used below . . . health is, plus //a/c type, army, etc. { ISectionFile f = GamePlay.gpCreateSectionFile(); string sect; string key; string value, value1, value2; string ChiefName1 = "0_Chief_" + (health < 1f ? "Fire_" : "Fuel_"); string ChiefName2 = "0_Chief_" + (health < 1f ? "Emrg_" : "Ammo_"); string ChiefName3 = "0_Chief_" + (health < 1f ? "Bomb_" : "Bomb_"); //startPos=aircraftPos; //bhugh special, we're just going to spawn them in very near the actual a/c if (DEBUG) GamePlay.gpLogServer(null, "Ground car group created at " + startPos.ToString () + " for " + aircraftPos.ToString () + " " + FindNearestAirport(aircraftPos).Name(), new object[] { }); if (portArmy == planeArmy) //???? ???????? { switch (portArmy) { case 1: if (health < 1f) { sect = "CustomChiefs"; key = ""; value = "Vehicle.custom_chief_emrg_0 $core/icons/tank.mma"; //??????? f.add(sect, key, value); value = "Vehicle.custom_chief_emrg_1 $core/icons/tank.mma";//?????? f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_0"; key = "Car.Austin_K2_ATV"; value = ""; f.add(sect, key, value); key = "TrailerUnit.Fire_pump_UK2_Transport"; value = "1"; f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_1"; key = "Car.Austin_K2_Ambulance"; value = ""; f.add(sect, key, value); sect = "Chiefs"; key = "0_Chief_Fire_0"; value = "Vehicle.custom_chief_emrg_0 gb /skin0 materialsSummer_RAF"; f.add(sect, key, value); key = "0_Chief_Emrg_1"; value = "Vehicle.custom_chief_emrg_1 gb /skin0 materialsSummer_RAF"; f.add(sect, key, value); } else { sect = "CustomChiefs"; key = ""; value = "Vehicle.custom_chief_emrg_0 $core/icons/tank.mma"; f.add(sect, key, value); value = "Vehicle.custom_chief_emrg_1 $core/icons/tank.mma"; f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_0"; // ?????????? key = "Car.Albion_AM463"; value = ""; f.add(sect, key, value); if (type == AircraftType.Bomber) // ??? ???????? ?????? ??????? ? ????? ???????? { key = "Car.Fordson_N"; value = ""; f.add(sect, key, value); key = "TrailerUnit.Towed_Bowser_UK1_Transport"; value = "1"; f.add(sect, key, value); } sect = "Vehicle.custom_chief_emrg_1"; // ?????? value = ""; key = "Car.Bedford_MW_open"; f.add(sect, key, value); if (type == AircraftType.Bomber) // ??? ???????? ????? ???????? { sect = "CustomChiefs"; key = ""; value = "Vehicle.custom_chief_emrg_2 $core/icons/tank.mma"; f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_2"; value = ""; key = "Car.Fordson_N"; value = ""; f.add(sect, key, value); key = "TrailerUnit.BombLoadingCart_UK1_Transport"; value = "1"; f.add(sect, key, value); key = "TrailerUnit.BombLoadingCart_UK1_Transport"; f.add(sect, key, value); }; sect = "Chiefs"; key = "0_Chief_Fuel_0"; value = "Vehicle.custom_chief_emrg_0 gb /skin0 materialsSummer_RAF"; f.add(sect, key, value); key = "0_Chief_Ammo_1"; value = "Vehicle.custom_chief_emrg_1 gb /skin0 materialsSummer_RAF/tow00_00 1_Static"; f.add(sect, key, value); if (type == AircraftType.Bomber) { key = "0_Chief_Bomb_2"; value = "Vehicle.custom_chief_emrg_2 gb /tow01_00 2_Static/tow01_01 3_Static/tow01_02 4_Static/tow01_03 5_Static/tow02_00 6_Static/tow02_01 7_Static"; f.add(sect, key, value); } sect = "Stationary"; key = "1_Static"; value = "Stationary.Morris_CS8-Bedford_MW_CargoAmmo3 gb 0.00 0.00 0.00"; f.add(sect, key, value); if (type == AircraftType.Bomber) // ????? ?????? { key = "2_Static"; value = "Stationary.Weapons_.Bomb_B_GP_250lb_MkIV gb 0.00 0.00 0.00"; f.add(sect, key, value); key = "3_Static"; value = "Stationary.Weapons_.Bomb_B_GP_250lb_MkIV gb 0.00 0.00 0.00"; f.add(sect, key, value); key = "4_Static"; value = "Stationary.Weapons_.Bomb_B_GP_250lb_MkIV gb 0.00 0.00 0.00"; f.add(sect, key, value); key = "5_Static"; value = "Stationary.Weapons_.Bomb_B_GP_250lb_MkIV gb 0.00 0.00 0.00"; f.add(sect, key, value); key = "6_Static"; value = "Stationary.Weapons_.Bomb_B_GP_500lb_MkIV gb 0.00 0.00 0.00"; f.add(sect, key, value); key = "7_Static"; value = "Stationary.Weapons_.Bomb_B_GP_500lb_MkIV gb 0.00 0.00 0.00"; f.add(sect, key, value); }; }; break; case 2: sect = "CustomChiefs"; //??????? key = ""; value = "Vehicle.custom_chief_emrg_0 $core/icons/tank.mma"; f.add(sect, key, value); value = "Vehicle.custom_chief_emrg_1 $core/icons/tank.mma";//?????? f.add(sect, key, value); if (health < 1f) { sect = "Vehicle.custom_chief_emrg_0"; key = "Car.Renault_UE"; value = ""; f.add(sect, key, value); key = "TrailerUnit.Foam_Extinguisher_GER1_Transport"; value = "1"; f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_1"; if (PseudoRnd(0f, 1f) < 0.5f) { key = "Car.Opel_Blitz_med-tent"; } else { key = "Car.Opel_Blitz_cargo_med"; }; value = ""; f.add(sect, key, value); sect = "Chiefs"; key = "0_Chief_Fire_0";// "0_Chief_emrg"; value = "Vehicle.custom_chief_emrg_0 de "; f.add(sect, key, value); key = "0_Chief_Emrg_1";// "0_Chief_emrg"; value = "Vehicle.custom_chief_emrg_1 de "; f.add(sect, key, value); } else { sect = "Vehicle.custom_chief_emrg_0"; key = "Car.Opel_Blitz_fuel"; value = ""; f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_1"; key = "Car.Renault_UE"; f.add(sect, key, value); key = "TrailerUnit.Oil_Cart_GER1_Transport"; value = "1"; f.add(sect, key, value); key = "Car.Renault_UE"; value = ""; f.add(sect, key, value); key = "TrailerUnit.Anlasswagen_(starter)_GER1_Transport"; value = "1"; f.add(sect, key, value); if (type == AircraftType.Bomber) // ????? ?????? { sect = "CustomChiefs"; key = ""; value = "Vehicle.custom_chief_emrg_2 $core/icons/tank.mma"; f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_2"; key = "Car.Renault_UE"; value = ""; f.add(sect, key, value); key = "TrailerUnit.HydraulicBombLoader_GER1_Transport"; value = "1"; f.add(sect, key, value); key = "Car.Renault_UE"; value = ""; f.add(sect, key, value); key = "TrailerUnit.BombSled_GER1_Transport"; value = "1"; f.add(sect, key, value); } sect = "Chiefs"; key = "0_Chief_Fuel_0"; value = "Vehicle.custom_chief_emrg_0 de"; f.add(sect, key, value); key = "0_Chief_Ammo_1"; value = "Vehicle.custom_chief_emrg_1 de"; f.add(sect, key, value); if (type == AircraftType.Bomber) { key = "0_Chief_Bomb_2"; value = "Vehicle.custom_chief_emrg_2 de /tow01_00 1_Static/tow03_00 2_Static"; f.add(sect, key, value); sect = "Stationary"; key = "1_Static"; value = "Stationary.Weapons_.Bomb_B_SC-250_Type2_J de 0.00 0.00 0.00"; f.add(sect, key, value); key = "2_Static"; value = "Stationary.Weapons_.Bomb_B_SC-1000_C de 0.00 0.00 0.00"; f.add(sect, key, value); }; }; break; default: break; } } else { switch (portArmy) { case 1: if (health < 1f) { sect = "CustomChiefs"; key = ""; value = "Vehicle.custom_chief_emrg_0 $core/icons/tank.mma"; //??????? f.add(sect, key, value); value = "Vehicle.custom_chief_emrg_1 $core/icons/tank.mma";//?????? f.add(sect, key, value); value = "Vehicle.custom_chief_emrg_2 $core/icons/tank.mma";//???????? f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_0"; key = "Car.Austin_K2_ATV"; value = ""; f.add(sect, key, value); key = "TrailerUnit.Fire_pump_UK2_Transport"; value = "1"; f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_1"; key = "Car.Austin_K2_Ambulance"; value = ""; f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_2"; key = "Car.Beaverette_III"; value = ""; f.add(sect, key, value); sect = "Chiefs"; key = "0_Chief_Fire_0"; value = "Vehicle.custom_chief_emrg_0 gb /skin0 materialsSummer_RAF"; f.add(sect, key, value); key = "0_Chief_Emrg_1"; value = "Vehicle.custom_chief_emrg_1 gb /skin0 materialsSummer_RAF"; f.add(sect, key, value); key = "0_Chief_Prisoner_2"; value = "Vehicle.custom_chief_emrg_2 gb "; f.add(sect, key, value); ChiefName3 = "0_Chief_Prisoner_"; } else { sect = "CustomChiefs"; key = ""; value = "Vehicle.custom_chief_emrg_0 $core/icons/tank.mma"; //??????? f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_0"; key = "Car.Beaverette_III"; value = ""; f.add(sect, key, value); sect = "Chiefs"; key = "0_Chief_Prisoner_0"; value = "Vehicle.custom_chief_emrg_0 gb "; f.add(sect, key, value); ChiefName1 = "0_Chief_Prisoner_"; }; break; case 2: if (health < 1f) { sect = "CustomChiefs"; key = ""; value = "Vehicle.custom_chief_emrg_0 $core/icons/tank.mma"; //??????? f.add(sect, key, value); value = "Vehicle.custom_chief_emrg_1 $core/icons/tank.mma";//?????? f.add(sect, key, value); value = "Vehicle.custom_chief_emrg_2 $core/icons/tank.mma";//???????? f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_0"; key = "Car.Renault_UE"; value = ""; f.add(sect, key, value); key = "TrailerUnit.Foam_Extinguisher_GER1_Transport"; value = "1"; f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_1"; key = "Car.Opel_Blitz_cargo_med"; value = ""; f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_2"; key = "Car.SdKfz_231_6Rad"; value = ""; f.add(sect, key, value); sect = "Chiefs"; key = "0_Chief_Fire_0"; value = "Vehicle.custom_chief_emrg_0 de"; f.add(sect, key, value); key = "0_Chief_Emrg_1"; value = "Vehicle.custom_chief_emrg_1 de"; f.add(sect, key, value); key = "0_Chief_Prisoner_2"; value = "Vehicle.custom_chief_emrg_2 de /marker0 1940-42_var1"; f.add(sect, key, value); ChiefName3 = "0_Chief_Prisoner_"; } else { sect = "CustomChiefs"; key = ""; value = "Vehicle.custom_chief_emrg_0 $core/icons/tank.mma"; //??????? f.add(sect, key, value); sect = "Vehicle.custom_chief_emrg_0"; key = "Car.SdKfz_231_6Rad"; value = ""; f.add(sect, key, value); sect = "Chiefs"; key = "0_Chief_Prisoner_0"; value = "Vehicle.custom_chief_emrg_0 de /marker0 1940-42_var1"; f.add(sect, key, value); ChiefName1 = "0_Chief_Prisoner_"; }; break; default: break; }; } //Little cleanup on variables; avoid div by zero later on; route finder doesn't like it if the points are underground if (startPos.z == 0 ) startPos.z=1000; if (aircraftPos.z == 0 ) aircraftPos.z=1000; if ((startPos.x - aircraftPos.x )< 5 ) startPos.x = aircraftPos.x + 75; if ((startPos.y - aircraftPos.y )< 5 ) startPos.y = aircraftPos.y + 75; //Instead of starting way out of sight, we're going to start //in the direction of the startPos, but at distance dis, which //is closer in to the a/c Point3d closerStartPos=startPos; if (!reverse) { double dis=SPAWN_START_DISTANCE_M; closerStartPos.x = aircraftPos.x+ dis * ((startPos.x - aircraftPos.x) / Math.Abs(startPos.x - aircraftPos.x)); closerStartPos.y = aircraftPos.y + dis * ((startPos.y - aircraftPos.y) / Math.Abs(startPos.y - aircraftPos.y)); } Point3d TmpStartPos = closerStartPos; TmpStartPos.x += PseudoRnd(-30f, 30f) + fRadius; TmpStartPos.y += PseudoRnd(-30f, 30f) + fRadius; Point3d BirthPos = EmrgVehicleStartPos(TmpStartPos, startPos); double disx, disy; sect = ChiefName1+"0" + "_Road"; key = ""; value1 = BirthPos.x.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.y.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.z.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " 0 92 5 "; Console.WriteLine(value1); //BirthPos.x -= 50f * ((BirthPos.x - aircraftPos.x) / Math.Abs(BirthPos.x - aircraftPos.x)); BirthPos.y -= 50f * ((BirthPos.y - aircraftPos.y) / Math.Abs(BirthPos.y - aircraftPos.y)); double edis=SPAWN_END_DISTANCE_M; //how far away from the plane we stop, when driving in towards it. if (reverse) edis= SPAWN_START_DISTANCE_REVERSE_M; //IN CASE OF reverse we call this the 'start' distance because we are starting rather then ending here. (Thus the name, 'reverse'). This tells where the vehicles start, when starting close & then driving out away from the a/c. disx=Math.Abs(BirthPos.x - aircraftPos.x) - (edis-2); if (disx<(edis-2)) disx=(edis-2); disy=Math.Abs(BirthPos.y - aircraftPos.y) - edis; if (disy<edis) disy=edis; BirthPos.x -= disx * ((BirthPos.x - aircraftPos.x) / Math.Abs(BirthPos.x - aircraftPos.x)); BirthPos.y -= disy * ((BirthPos.y - aircraftPos.y) / Math.Abs(BirthPos.y - aircraftPos.y)); value2 = BirthPos.x.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.y.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.z.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " 0 92 5 ";; Console.WriteLine(value2); if (reverse ) { f.add(sect, key, value2); f.add(sect, key, value1); }else { f.add(sect, key, value1); f.add(sect, key, value2); } TmpStartPos = closerStartPos; TmpStartPos.x += PseudoRnd(-30f, 30f) - fRadius; TmpStartPos.y += PseudoRnd(-30f, 30f) + fRadius; BirthPos = EmrgVehicleStartPos(TmpStartPos, startPos); //BirthPos = TmpStartPos; sect = ChiefName2+"1" + "_Road"; key = ""; value1 = BirthPos.x.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.y.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.z.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " 0 92 5 "; Console.WriteLine(value1); disx=Math.Abs(BirthPos.x - aircraftPos.x) - (edis+1); if (disx<10) disx=(edis+1); disy=Math.Abs(BirthPos.y - aircraftPos.y) - (edis-2); if (disy<(edis-2)) disy=(edis-2); BirthPos.x -= disx * ((BirthPos.x - aircraftPos.x) / Math.Abs(BirthPos.x - aircraftPos.x)); BirthPos.y -= disy * ((BirthPos.y - aircraftPos.y) / Math.Abs(BirthPos.y - aircraftPos.y)); value2 = BirthPos.x.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.y.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.z.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " 0 92 5 ";; Console.WriteLine(value2); if (reverse ) { f.add(sect, key, value2); f.add(sect, key, value1); }else { f.add(sect, key, value1); f.add(sect, key, value2); } TmpStartPos = closerStartPos; TmpStartPos.x += PseudoRnd(-30f, 30f) + fRadius; TmpStartPos.y += PseudoRnd(-30f, 30f) - fRadius; BirthPos = EmrgVehicleStartPos(TmpStartPos, startPos); sect = ChiefName3 + "2" + "_Road"; key = ""; value1 = BirthPos.x.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.y.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.z.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " 0 92 5 "; Console.WriteLine(value1); disx=Math.Abs(BirthPos.x - aircraftPos.x) - (edis-1); if (disx<(edis-1)) disx=(edis-1); disy=Math.Abs(BirthPos.y - aircraftPos.y) - (edis+2); if (disy<(edis+2)) disy=(edis+2); BirthPos.x -= disx * ((BirthPos.x - aircraftPos.x) / Math.Abs(BirthPos.x - aircraftPos.x)); BirthPos.y -= disy * ((BirthPos.y - aircraftPos.y) / Math.Abs(BirthPos.y - aircraftPos.y)); value2 = BirthPos.x.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.y.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + BirthPos.z.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " 0 92 5 ";; Console.WriteLine(value2); if (reverse ) { f.add(sect, key, value2); f.add(sect, key, value1); }else { f.add(sect, key, value1); f.add(sect, key, value2); } return f; } internal Point3d EmrgVehicleStartPos(Point3d startPos, Point3d endPos) { Point3d TmpPos = startPos; while (((GamePlay.gpLandType(TmpPos.x, TmpPos.y) & LandTypes.WATER) != 0) ) { TmpPos.x -= (TmpPos.x - endPos.x) / 10f; TmpPos.y -= (TmpPos.y - endPos.y) / 10f; }; return TmpPos; } internal void CheckEmrgCarOnAirport(int aircraftNumber) { // ????????? ???? ?? ??????? ? ????????? //MissionLoading=false; //kludgy fix, this seems to be in place to avoid mission load loops or something, but it doesn't work AiGroundGroup MyCar = null; { if (DEBUG) GamePlay.gpLogServer(null, "Creating a new car group at " + CurPlanesQueue[aircraftNumber].basePos.Name() + " for " + aircraftNumber, new object[] { }); MissionLoading = true; MissionLoadingAircraftNumber=aircraftNumber; int ArmyPos = 0; if (GamePlay.gpFrontExist()) { ArmyPos = GamePlay.gpFrontArmy(CurPlanesQueue[aircraftNumber].basePos.Pos().x, CurPlanesQueue[aircraftNumber].basePos.Pos().y); } else { ArmyPos = CurPlanesQueue[aircraftNumber].aircraft.Army(); }; // ??????? ?????? ? ????????? //In case of spawn-in, we reverse the direction making it away from the plane. if (DEBUG) GamePlay.gpLogServer(null, "Creating a new car group at " + ((int)CurPlanesQueue[aircraftNumber].State).ToString()+" " + ((int)ServiceType.SPAWNIN).ToString()+ " " + ( ((int)CurPlanesQueue[aircraftNumber].State & (int)ServiceType.SPAWNIN) ==0 ).ToString(), new object[] { }); bool reverse=true; if ( ((int)CurPlanesQueue[aircraftNumber].State & (int)ServiceType.SPAWNIN) ==0 ) reverse=false; GamePlay.gpPostMissionLoad(CreateEmrgCarMission(CurPlanesQueue[aircraftNumber].basePos.Pos(), CAR_POS_RADIUS, ArmyPos, CurPlanesQueue[aircraftNumber].aircraft.Army(), CurPlanesQueue[aircraftNumber].aircraft.Type(),CurPlanesQueue[aircraftNumber].health, CurPlanesQueue[aircraftNumber].aircraft.Pos(), reverse, CurPlanesQueue[aircraftNumber].State)); } return ; } public override void OnAircraftLanded (int missionNumber, string shortName, AiAircraft aircraft) { base.OnAircraftLanded(missionNumber, shortName, aircraft); aircraftActiveList.Remove(aircraft); StartVehiclesForAircraft (aircraft ); } public override void OnAircraftCrashLanded(int missionNumber, string shortName, AiAircraft aircraft) { base.OnAircraftCrashLanded(missionNumber, shortName, aircraft); StartVehiclesForAircraft (aircraft); aircraftActiveList.Remove(aircraft); } //TODO: For bombers, this will re-spawn vehicles whenever they change places public override void OnPlaceEnter (Player player, AiActor actor, int placeIndex) { base.OnPlaceEnter(player, actor, placeIndex); AiAircraft aircraft= actor as AiAircraft; if (DEBUG) GamePlay.gpLogServer(null, "Place Enter: " + player.Name() + " " + actor.Name() + " " + placeIndex.ToString() + " " , new object[] { }); //do this only once per actor (avoids many multiple vehicle spawn-ins whwenever bomber players move between positions, triggering this OnplaceEnter repeatedly) if (!actorPlaceEnterList.Contains(actor)) { StartVehiclesForAircraft (aircraft, true ); //this is spawn-in, so we reverse vehicle direction actorPlaceEnterList.Add(actor); } } public override void OnCarter(AiActor actor, int placeIndex) { base.OnCarter(actor, placeIndex); AiAircraft aircraft= actor as AiAircraft; if (DEBUG) GamePlay.gpLogServer(null, "OnCarter: " + actor.Name() + " " + placeIndex.ToString() + " " , new object[] { }); } public override void OnPersonMoved(AiPerson person, AiActor fromCart, int fromPlaceIndex) { base.OnPersonMoved(person, fromCart, fromPlaceIndex); AiAircraft aircraft= fromCart as AiAircraft; if (DEBUG) GamePlay.gpLogServer(null, "OnPersonMoved: " + fromCart.Name() + " " + person.Name() + " " + fromPlaceIndex.ToString() + " " , new object[] { }); } public override void OnAircraftTookOff(int missionNumber, string shortName, AiAircraft aircraft) { base.OnAircraftTookOff(missionNumber, shortName, aircraft); try { //AiAircraft aircraft= actor as AiAircraft; if (DEBUG) GamePlay.gpLogServer(null, "Starting vehicle/took off", new object[] { }); if ( !isAiControlledPlane2(aircraft) && !aircraftActiveList.Contains(aircraft)) aircraftActiveList.Add(aircraft); } catch (Exception e) {System.Console.WriteLine (e.ToString());} } public override void OnAircraftDamaged(int missionNumber, string shortName, AiAircraft aircraft, AiDamageInitiator initiator, NamedDamageTypes damageType) { base.OnAircraftDamaged(missionNumber, shortName, aircraft, initiator, damageType); try { //just keep a list of all damaged aircraft if (!aircraftDamagedList.Contains(aircraft)) aircraftDamagedList.Add(aircraft); if ( !isAiControlledPlane2(aircraft) && !aircraftActiveList.Contains(aircraft)) aircraftActiveList.Add(aircraft); } catch (Exception e) {System.Console.WriteLine (e.ToString());} //add your code here } public override void OnAircraftCutLimb(int missionNumber, string shortName, AiAircraft aircraft, AiDamageInitiator initiator, LimbNames limbName) { base.OnAircraftCutLimb(missionNumber, shortName, aircraft, initiator, limbName); try { //just keep a list of all damaged aircraft if (!aircraftDamagedList.Contains(aircraft)) aircraftDamagedList.Add(aircraft); if ( !isAiControlledPlane2(aircraft) && !aircraftActiveList.Contains(aircraft)) aircraftActiveList.Add(aircraft); } catch (Exception e) {System.Console.WriteLine (e.ToString());} } public void OnAircraftStopped (AiAircraft aircraft) { try { if (aircraft != null ) { if (DEBUG) GamePlay.gpLogServer(null, "Aircraft detected as stopped/landed: " + aircraft.Player(0).Name() + " " + aircraft.Name() + " ", new object[] { }); StartVehiclesForAircraft (aircraft ); aircraftActiveList.Remove(aircraft); //The only way they can get back on the list is by taking off again. Given the way CloD works, this might not be possible if they just landed in a field or whatever. But them's the breaks . . . } } catch (Exception e) {System.Console.WriteLine (e.ToString());} } public override void OnActorDead(int missionNumber, string shortName, AiActor actor, List<DamagerScore> damages) { #region stb base.OnActorDead(missionNumber, shortName, actor, damages); try { if (actor as AiAircraft != null ) { StartVehiclesForAircraft (actor as AiAircraft ); aircraftActiveList.Remove(actor as AiAircraft); } } catch (Exception e) {System.Console.WriteLine (e.ToString());} #endregion //add your code here } public void StartVehiclesForAircraft (AiAircraft aircraft, bool spawnIn=false ) { try { if (aircraft==null || isAiControlledPlane2(aircraft) ) return; if (DEBUG) GamePlay.gpLogServer(null, "Getting Airports for startvehicles", new object[] { }); BasePos NearestAirport = new BasePos(); NearestAirport = FindNearestAirport(aircraft); if (DEBUG) GamePlay.gpLogServer(null, "Starting vehicles at " + NearestAirport.Name(), new object[] { }); if (NearestAirport != null) { PlanesQueue CurPlane = new PlanesQueue(aircraft, NearestAirport, 0); int ArmyPos = 0; CurPlane.health = (float)aircraft.getParameter(part.ParameterTypes.M_Health, -1); if (aircraftDamagedList.Contains(aircraft)) CurPlane.health /=2; //CurPlane.health=0; //testing float cdam = (float)aircraft.getParameter(part.ParameterTypes.M_CabinDamage, 1); float ndam = (float)aircraft.getParameter(part.ParameterTypes.M_NamedDamage, 1); //note that MANY of the CurPlane.States set below do not do anything //because the actual type of ai vehicle spawned is determined //in the createemrgcarmission method via various criteria including //army, health, type of plane etc but not really using the states //set here AT ALL. FYI. if (DEBUG) GamePlay.gpLogServer(null, "Health = " + CurPlane.health.ToString() + " " + cdam.ToString() + " " + ndam.ToString(), new object[] { }); if (spawnIn) CurPlane.State |= ServiceType.SPAWNIN; if (GamePlay.gpFrontExist()) { ArmyPos = GamePlay.gpFrontArmy(NearestAirport.Pos().x, NearestAirport.Pos().y); } else { ArmyPos = aircraft.Army(); }; //if (true || CurPlane.health < 1f) //testing if (CurPlane.health < 1f) { CurPlane.State |= ServiceType.EMERGENCY; CurPlane.State |= ServiceType.FIRE; } else if (aircraft.Army() == ArmyPos) { CurPlane.State |= ServiceType.FUEL; CurPlane.State |= ServiceType.AMMO; if (aircraft.Type() == AircraftType.Bomber) CurPlane.State |= ServiceType.BOMBS; CurPlane.State |= ServiceType.BOMBS; }; //if (true || !(aircraft.Army() == ArmyPos)) CurPlane.State |= ServiceType.PRISONERCAPTURE; //testing if (!(aircraft.Army() == ArmyPos)) CurPlane.State |= ServiceType.PRISONERCAPTURE; if (!CurPlanesQueue.Contains(CurPlane)) { if (DEBUG) GamePlay.gpLogServer(null, "Starting vehicles at " + NearestAirport.Name()+ " Type: " + CurPlane.State, new object[] { }); CurPlanesQueue.Add(CurPlane); CheckEmrgCarOnAirport(CurPlanesQueue.Count - 1); } else { for (int i = 0; i < CurPlanesQueue.Count; i++) if (CurPlanesQueue[i] == CurPlane) { CheckEmrgCarOnAirport(i); break; } } CurPlane = null; } } catch (Exception e) {System.Console.WriteLine (e.ToString());} } private void checkForStoppedAircraft (List <AiAircraft> aircraftList){ int a_count=0; double Z_VelocityTAS; foreach (AiAircraft a in aircraftList ) { Z_VelocityTAS = a.getParameter(part.ParameterTypes.Z_VelocityTAS, -1); //If true airspeed is 0 now, check again in 5 seconds. If still 0 we're assuming crashed and/or landed somehow. if (Z_VelocityTAS == 0) { Timeout (5, () => { Z_VelocityTAS = a.getParameter(part.ParameterTypes.Z_VelocityTAS, -1); if (Z_VelocityTAS == 0) OnAircraftStopped(a); }); } } } //Returns whether aircraft is an Ai plane (no humans in any seats) private bool isAiControlledPlane2(AiAircraft aircraft) { // returns true if specified aircraft is AI controlled with no humans aboard, otherwise false if (aircraft == null) return false; //check if a player is in any of the "places" for (int i = 0; i < aircraft.Places(); i++) { if (aircraft.Player(i) != null) return false; } return true; } private string Left(string Original, int Count) { if (Original == null || Original == string.Empty || Original.Length < Count) { return Original; } else { // Return a sub-string of the original string, starting at index 0. return Original.Substring(0, Count); } } } Last edited by flug32; 05-22-2016 at 08:39 AM. |
|
|