View Single Post
  #45  
Old 05-22-2016, 07:11 AM
flug32 flug32 is offline
Approved Member
 
Join Date: Feb 2016
Posts: 4
Default

Quote:
Originally Posted by flug32 View Post
FILE: auto-generate-vehicles.cs

<see separate message>
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!
CODE 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 07:39 AM.
Reply With Quote