1C Home   |   Register   |   Today Posts   |   Members   |   UserCP   |   Calendar   |   Search   |   FAQ

Go Back   Official 1C Company forum > 1C Publishing > IL-2 Sturmovik: Cliffs of Dover > FMB, Mission & Campaign builder Discussions

Reply
 
Thread Tools Display Modes
  #41  
Old 01-18-2012, 07:07 PM
AKA_Scorp AKA_Scorp is offline
Member
 
Join Date: Jan 2011
Posts: 31
Default

Quote:
Originally Posted by Ataros View Post
Load a ready submission which contains an aircraft or dynamical create a submission file with a script and then load it. Check out how naryv creates tanks in his examples attached in a sticky thread above.
OK, I can see the principle of the section file and how to create a sub mission from script. I'm sure I could put in static objects, chiefs and AI flights but how do I force a human pilot into an aircraft at a specific coordinate?

Thanks
Reply With Quote
  #42  
Old 01-18-2012, 07:12 PM
FG28_Kodiak FG28_Kodiak is offline
Senior Member
 
Join Date: Dec 2009
Location: Swabia->Bavaria->Germany
Posts: 884
Default

Player Class: PlaceEnter(Actor, Placeindex)
example:
player.PlaceEnter(Aircraft, 0);
Reply With Quote
  #43  
Old 01-18-2012, 07:41 PM
AKA_Scorp AKA_Scorp is offline
Member
 
Join Date: Jan 2011
Posts: 31
Default

Quote:
Originally Posted by FG28_Kodiak View Post
Player Class: PlaceEnter(Actor, Placeindex)
example:
player.PlaceEnter(Aircraft, 0);
Thanks,
Reply With Quote
  #44  
Old 05-22-2016, 08:01 AM
flug32 flug32 is offline
Approved Member
 
Join Date: Feb 2016
Posts: 4
Thumbs up 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]
In the MAIN mission script file you have something like this:
FILE: main.cs
Code:
  public override void OnBattleStarted()
    {
        base.OnBattleStarted();
        ReadInitialSubmissions(MISSION_ID + "-auto-generate-vehicles", 0, 0); 
        //etc . . . your code

     }
        
    }
Here is the ReadInitialSubmission script I use:

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

    }
You need to be sure that event triggers are enabled--and enabled in the right place. Similar code is already in auto-vehicle-generate.cs but I think perhaps you also need it in your main mission cs file. (In any event, if you've been trying to use triggers and having trouble, not having this flag set correctly, or setting it to late in the startup process, might be your problem.)

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.
    }

 //////////////////////////////////////////////////////////////////////////////////////////////////
Last, you must have lines like the following in the [rts] section of both your conf.ini and confs.ini file.

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
Lastly, thanks to everyone who has been posting here and in other forums. The code above includes tons of techniques and snippets borrowed from here and there. All horrible hacks and terrible formatting are my own

Again: ZIP file with script & mission files, sample code, instructions all in one

Last edited by flug32; 05-23-2016 at 12:00 AM.
Reply With Quote
  #45  
Old 05-22-2016, 08: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 08:39 AM.
Reply With Quote
  #46  
Old 05-22-2016, 08:14 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
CODE CONTINUED IN PART 2!
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);
        }
     }       
}
ZIP file with script & mission files, sample code, instructions all in one

Last edited by flug32; 05-22-2016 at 08:39 AM.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 12:11 PM.

Based on a design by: Miner Skinz.com

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
Copyright © 2007 1C Company. All rights reserved.