![]() |
|
|
|
#1
|
|||
|
|||
|
Here is part 1/2 of the actual .cs code for FILE: auto-generate-vehicles.cs
Code:
//
//Various emergency & service cars script created by posters at http://forum.1cpublishing.eu/showthread.php?t=26112 and by naryv
//Hacked extensively by flug
//$reference parts/core/Strategy.dll
//$reference parts/core/gamePlay.dll
//$reference System.Core.dll
using System;
//using System.Core;
using System.Collections;
using maddox.game;
using maddox.game.world;
using maddox.GP;
using part;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.ComponentModel;
using System.Threading;
using System.Diagnostics;
public class Mission : AMission
{
public bool DEBUG=false;
public int VEHICLE_LIFE_SEC = 120;
public double CAR_POS_RADIUS = 80; //distance vehicles will be positioned from the center point of the Birthplace, Airfield, etc where cars are positioned
public int TICKS_PER_MINUTE=1986; //empirically, based on a timeout test. This is approximate & varies slightly.
//for landing or crash, they start SPAWN_START_DISTANCE_M away from the plane in the direction of the nearest BirthPlace or Airport point. They end SPAWN_END_DISTANCE_M away from the a/c. (Distances are approx., various randomness & functions added on top of these values.)
public int SPAWN_START_DISTANCE_M = 100; //how far away they start from the a/c when approaching after landing
public int SPAWN_END_DISTANCE_M = 20; //how close they approach you upon (eg) landing
//For spawn-in, the vehicles start this close to the a/c and proceed to
// the birthplace or airport point.
public int SPAWN_START_DISTANCE_REVERSE_M = 12; //how close they start when spawning in onPlaceEnter
private List<AiActor> actorPlaceEnterList; //HashSet doesn't work for some reason; it would be a better solution
private List<AiAircraft> aircraftDamagedList;
private List<AiAircraft> aircraftActiveList;
maddox.game.ABattle Battle;
public Mission () {
//HashSet<int> evenNumbers = new HashSet<int>();
actorPlaceEnterList = new List<AiActor>();
aircraftDamagedList = new List<AiAircraft>();
aircraftActiveList = new List<AiAircraft>();
}
//Listen to events of every mission
public override void Init(maddox.game.ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
Battle=battle;
MissionNumberListener = -1; //Listen to events of every mission
//This is what allows you to catch all the OnTookOff, OnAircraftDamaged, and other similar events. Vitally important to make this mission/cs file work!
//If we load missions as sub-missions, as we often do, it is vital to have this in Init, not in "onbattlestarted" or some other place where it may never be detected or triggered if this sub-mission isn't loaded at the very start.
if (DEBUG) GamePlay.gpLogServer(null, ".Net framework: " + Environment.Version, new object[] { });
}
public override void OnBattleStarted()
{
base.OnBattleStarted();
//MissionNumberListener = -1;
}
Random rnd = new Random();
[Flags]
internal enum ServiceType // ??? ????????????? ???????
//note that all these types don't work; the actual type is determined by
//createemrgcarmission depending on a/c type, army, and a few other things.
//So it's not really determined by the settings in the curTechCar.CarType field
{
NONE = 0,
EMERGENCY = 1,
FIRE = 2,
FUEL = 4,
AMMO = 8,
BOMBS = 16,
PRISONERCAPTURE = 32,
SPAWNIN = 64
}
//Like AiActor or AiBirthplace but only has .Name() & .Loc()
internal class BasePos
{
internal string _Name;
internal Point3d _Pos;
public BasePos (string name, Point3d pos)
{
if (name!=null)
this._Name=name;
else this._Name="";
//if (pos!=null)
this._Pos=pos;
//else this.Pos=new Point3d(0,0,0);
}
public BasePos (BasePos bp)
{
this._Name=bp.Name();
this._Pos=bp.Pos();
Console.WriteLine ("BasePos inited: " + this.ToString ("F2"));
}
//a default constructor . . .
public BasePos (object o=null)
{
this._Name="";
this._Pos=new Point3d(0,0,0);
}
public string Name(string name=null) {
if (name==null) return this._Name;
else {
this._Name=name;
return null;
}
}
public Point3d Pos(Point3d pos) {
this._Pos=pos;
return this._Pos;
}
public Point3d Pos() {
return this._Pos;
}
public string ToString (string format){
return _Name + " "
+ _Pos.x.ToString( format ) + " "
+ _Pos.y.ToString( format ) + " "
+ _Pos.z.ToString( format );
}
}
internal class TechCars
{
internal AiGroundGroup TechCar { get; set; }
internal BasePos basePos { get; set; }
internal IRecalcPathParams cur_rp { get; set; }
internal int RouteFlag = 0;
internal int cartype = 0;
internal int servPlaneNum = -1;
internal int MAX_CARS = 100;
internal ServiceType CarType { get { return (ServiceType)cartype; } set { cartype = (int)value; } }
public TechCars(AiGroundGroup car, BasePos airoport, IRecalcPathParams rp)
{
this.TechCar = car;
this.basePos = airoport;
this.cur_rp = rp;
Console.WriteLine("TechCars created. basePos: " + this.basePos.ToString("F2"));
}
}
internal class PlanesQueue {
internal AiAircraft aircraft { get; set; }
internal BasePos basePos { get; set; }
internal int state = 0;
internal ServiceType State { get { return (ServiceType)state; } set { state = (int)value; } }
internal int Lifetime = 0;
internal float health = 1;
public PlanesQueue(AiAircraft aircraft, BasePos basePos, int state)
{
this.aircraft = aircraft;
this.basePos = basePos as BasePos;
this.state = state;
}
}
internal List<TechCars> CurTechCars = new List<TechCars>();
internal List<PlanesQueue> CurPlanesQueue = new List<PlanesQueue>();
TechCars TmpCar = null;
bool MissionLoading = false;
int MissionLoadingAircraftNumber = -1;
internal double PseudoRnd(double MinValue, double MaxValue)
{
return rnd.NextDouble() * (MaxValue - MinValue) + MinValue;
}
public override void OnActorTaskCompleted(int missionNumber, string shortName, AiActor actor)
{
base.OnActorTaskCompleted(missionNumber, shortName, actor);
if (DEBUG) GamePlay.gpLogServer(null, "OnActorTaskComplete", new object[] { });
AiActor ai_actor = actor as AiActor;
if (ai_actor != null)
{
if (ai_actor is AiGroundGroup)
for (int i = 0; i < CurTechCars.Count; i++) // ???? ????????????? ??????? ??????? ?? ?????????????? ????????, ????????? ?? ????????????
{
if (CurTechCars[i].TechCar == ai_actor as AiGroundGroup) {
//if (CurTechCars[i].RouteFlag == 1)
TechCars car = CurTechCars[i] as TechCars;
if (DEBUG) GamePlay.gpLogServer(null, "OnActorTaskComplete - ending plane service for " + i.ToString() + " in 120 sec.", new object[] { });
//this is basically to ensure that AI objects don't just hang around indefinitely when their tasks are done.
//In normal behavior, they may complete several tasks in the course of moving abou the airport, so we don't just want
//to destroy them immediately when task is done
Timeout(VEHICLE_LIFE_SEC, () =>
{
if (DEBUG) GamePlay.gpLogServer(null, "OnActorTaskComplete - ending plane service for " + i.ToString() + " now", new object[] { });
EndPlaneService(car, ai_actor as AiGroundGroup);
});
}
//we're just destroying them @ this point
// else
// CheckNotServicedPlanes(i);
};
}
}
internal void CheckNotServicedPlanes(int techCarIndex)
{
for (int j = 0; j < CurPlanesQueue.Count; j++)
{
if (CurTechCars[techCarIndex].TechCar.IsAlive() && (CurPlanesQueue[j].basePos == CurTechCars[techCarIndex].basePos) && ((CurTechCars[techCarIndex].CarType & CurPlanesQueue[j].State) != 0) && (CurTechCars[techCarIndex].servPlaneNum == -1))
{
if (SetEmrgCarRoute(j, techCarIndex)) // ?????????? ??????? ??????????? ????????? ???????
{
return;
}
}
}
}
//Removes the ground vehicle from the CurTechCars list & also destroys the AI object
//We call it with the List item (not the index) because the index can change between call & execution, esp. if call via a timeout, which is common
//We also include the TechCar field, (an AiGroundGroup) because sometimes the List item can be destroyed but the actual Ai Airgroup is still floating around undead
//
internal void EndPlaneService(TechCars tC, AiGroundGroup ground=null)
{
try
{
if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning now", new object[] { });
if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning " + tC.servPlaneNum.ToString(), new object[] { });
if (tC != null) {
if (DEBUG) GamePlay.gpLogServer(null, " Number of objects: " + tC.TechCar.GetItems().Length, new object[] { });
//if (CurTechCars[techCarIndex].cur_rp == null) return;
tC.cur_rp = null; // ?????????? ???????
//Just destroy the ground items at this point.
if (tC.TechCar.GetItems() != null && tC.TechCar.GetItems().Length > 0)
{
if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning 1 ", new object[] { });
foreach (AiActor actor in tC.TechCar.GetItems())
{
if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning 2 " , new object[] { });
(actor as AiGroundActor).Destroy();
}
}
CurTechCars.Remove(tC);
}
if (ground != null) {
if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning 3 ", new object[] { });
foreach (AiActor actor in ground.GetItems())
{
if (DEBUG) GamePlay.gpLogServer(null, "EndPlaneService/despawning 4 " , new object[] { });
(actor as AiGroundActor).Destroy();
}
}
}
catch (Exception e) {System.Console.WriteLine (e.ToString());}
}
internal bool MoveFromRWay(int carNum)
{
bool result = false;
if (DEBUG) GamePlay.gpLogServer(null, "Removing aircraft from runway at " + CurTechCars[carNum].basePos.Name(), new object[] { });
if ((GamePlay.gpLandType(CurTechCars[carNum].TechCar.Pos().x, CurTechCars[carNum].TechCar.Pos().y) & LandTypes.ROAD) == 0)
return result;
Point3d TmpPos = CurTechCars[carNum].TechCar.Pos();
while (((GamePlay.gpLandType(TmpPos.x, TmpPos.y) & LandTypes.ROAD) != 0))
{
TmpPos.x += 10f;
TmpPos.y += 10f;
};
Point2d EmgCarStart, EmgCarFinish;
EmgCarStart.x = CurTechCars[carNum].TechCar.Pos().x; EmgCarStart.y = CurTechCars[carNum].TechCar.Pos().y;
EmgCarFinish.x = TmpPos.x; EmgCarFinish.y = TmpPos.y;
CurTechCars[carNum].servPlaneNum = -1;
CurTechCars[carNum].RouteFlag = 0;
CurTechCars[carNum].cur_rp = null;
CurTechCars[carNum].cur_rp = GamePlay.gpFindPath(EmgCarStart, 10f, EmgCarFinish, 10f, PathType.GROUND, CurTechCars[carNum].TechCar.Army());
result = true;
return result;
}
public bool SetEmrgCarRoute(int aircraftNumber,int carNum)
{
bool result = false;
if (DEBUG) GamePlay.gpLogServer(null, "Setting a Car Route "+aircraftNumber.ToString() + " " + carNum.ToString() + " at " + CurTechCars[carNum].basePos.Name() , new object[] { });
if (CurTechCars[carNum].TechCar != null)
{
CurTechCars[carNum].servPlaneNum = aircraftNumber; // ????????????? ????? ?????????????? ????????
if (CurTechCars[carNum].cur_rp == null)
{
Point2d EmgCarStart, EmgCarFinish, LandedPos;
LandedPos.x = CurPlanesQueue[aircraftNumber].aircraft.Pos().x; LandedPos.y = CurPlanesQueue[aircraftNumber].aircraft.Pos().y;
int Sign = ((carNum % 2) == 0) ? 2 : -2;
EmgCarStart.x = CurTechCars[carNum].TechCar.Pos().x; EmgCarStart.y = CurTechCars[carNum].TechCar.Pos().y;
//Drive the car from where it is to the point located in the direction of the aircraft position but 20 meters short of it.
double disx, disy;
disx=Math.Abs(EmgCarStart.x - LandedPos.x) - 20;
if (disx<10) disx=20;
disy=Math.Abs(EmgCarStart.y - EmgCarStart.y) - 20;
if (disy<10) disy=20;
EmgCarFinish.x = EmgCarStart.x - disx * ((EmgCarStart.x - LandedPos.x) / Math.Abs(EmgCarStart.x - LandedPos.x)); EmgCarFinish.y = EmgCarStart.x - disy * ((EmgCarStart.y - LandedPos.y) / Math.Abs(EmgCarStart.y - LandedPos.y));
//EmgCarFinish.x = LandedPos.x - PseudoRnd(0f, 1f) * ((LandedPos.x - EmgCarStart.x) / (Math.Abs(LandedPos.x - EmgCarStart.x))) - Sign;
//EmgCarFinish.y = LandedPos.y - PseudoRnd(0f, 1f) * ((LandedPos.y - EmgCarStart.y) / (Math.Abs(LandedPos.y - EmgCarStart.y))) - Sign;
//For spawn-in, we want the cars to start in close to the a/c & drive away
CurTechCars[carNum].cur_rp = GamePlay.gpFindPath(EmgCarStart, 15f, EmgCarFinish, 15f, PathType.GROUND, CurTechCars[carNum].TechCar.Army());
if (DEBUG) GamePlay.gpLogServer(null, "Setting a Car Route "+aircraftNumber.ToString() + " " + carNum.ToString() + " " + EmgCarStart.ToString() + " to " + EmgCarFinish.ToString() + " at " + CurTechCars[carNum].basePos.Name() , new object[] { });
result = true;
}
}
return result;
}
public override void OnMissionLoaded(int missionNumber)
{
base.OnMissionLoaded(missionNumber);
if (missionNumber > 0) //whenever a new mission loads, this slurps up any matching groundcars into the curTechCars list so they can be manipulated etc
//if (missionNumber==MissionNumber ) // important check!
{
if (DEBUG) GamePlay.gpLogServer(null, "Starting vehicle sub-mission loaded", new object[] { });
List<string> CarTypes = new List<string>();
CarTypes.Add(":0_Chief_Emrg_");
CarTypes.Add(":0_Chief_Fire_");
CarTypes.Add(":0_Chief_Fuel_");
CarTypes.Add(":0_Chief_Ammo_");
CarTypes.Add(":0_Chief_Bomb_");
CarTypes.Add(":0_Chief_Prisoner_");
AiGroundGroup MyCar = null;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < CarTypes.Count; j++)
{
MyCar = GamePlay.gpActorByName(missionNumber.ToString() + CarTypes[j] + i.ToString()) as AiGroundGroup;
//if (DEBUG) GamePlay.gpLogServer(null, "Creating groundcar group for " +missionNumber.ToString() + CarTypes[j] + i.ToString(), new object[] { });
if (MyCar != null)
{
TmpCar = new TechCars(MyCar, FindNearestAirport(MyCar), null);
if (DEBUG) GamePlay.gpLogServer(null, "Creating groundcar group at " + FindNearestAirport(MyCar).Name() + " " + MissionLoadingAircraftNumber.ToString(), new object[] { });
TmpCar.CarType = (ServiceType)(1 << j);
TmpCar.cur_rp = null;
TmpCar.servPlaneNum=MissionLoadingAircraftNumber;
if (!CurTechCars.Contains(TmpCar))
CurTechCars.Add(TmpCar);
//if (CurTechCars.count < MAX_CARS) CurTechCars.Add(TmpCar);
//These things are unruly, so we're setting a max life on them.
Timeout(2*VEHICLE_LIFE_SEC, () =>
{
(MyCar as AiGroundActor).Destroy();
});
MissionLoading = false;
};
}
}
}
}
public override void OnTickGame() {
base.OnTickGame();
//try {
if ( (Time.tickCounter()) == 0) {
// if (DEBUG) GamePlay.gpLogServer(null, "Ground vehicles started ", new object[] { });
}
if ((Time.tickCounter() % (TICKS_PER_MINUTE/6)) == 12 ) {
checkForStoppedAircraft(aircraftActiveList);
}
if (Time.tickCounter() % 64 == 0)
{
//if (DEBUG) GamePlay.gpLogServer(null, "Ground vehicles continues . . . ", new object[] { });
for (int i = 0; i < CurPlanesQueue.Count; i++)
{
CurPlanesQueue[i].Lifetime++;
if (DEBUG) GamePlay.gpLogServer(null, "Lifetime: " + CurPlanesQueue[i].Lifetime, new object[] { });
if ((CurPlanesQueue[i].State == ServiceType.NONE) || (CurPlanesQueue[i].aircraft == null) || (CurPlanesQueue[i].Lifetime > (int)((double)VEHICLE_LIFE_SEC*TICKS_PER_MINUTE/64/60)))
{
foreach ( TechCars car in CurTechCars ) //don't use a for count/index loop here as we are destroying some of the objects mid-loop . . . arghh
{
if (car.servPlaneNum == i) {
if (DEBUG) GamePlay.gpLogServer(null, "Removing ground car for plane " + car.servPlaneNum + " " + car.CarType + " in 5 seconds", new object[] { });
//EndPlaneService(j);
Timeout ( 5f, () => { EndPlaneService(car, car.TechCar); });
}
}
CurPlanesQueue.RemoveAt(i);
}
};
foreach ( TechCars car in CurTechCars ) // (int i = 0; i < CurTechCars.Count; i++) //again ix-nay on the loop-for-ay . . . .
{
if (DEBUG) GamePlay.gpLogServer(null, "Ground car at " + car.basePos.Name(), new object[] { });
//TechCars car = CurTechCars[i];
if ((car.TechCar != null && car.cur_rp != null) && (car.cur_rp.State == RecalcPathState.SUCCESS) )
{
if (car.TechCar.IsAlive()) // && (car.RouteFlag == 0)) // && (car.servPlaneNum != -1))
{
car.RouteFlag = 1;
car.cur_rp.Path[0].P.x = car.TechCar.Pos().x; car.cur_rp.Path[0].P.y = car.TechCar.Pos().y;
car.TechCar.SetWay(car.cur_rp.Path);
//if (car.servPlaneNum != -1) car.RouteFlag = 0;
}
//The code below avoids the current plane, right? But, I'm worried about these ground vehicles hitting **all the other planes** that might be about this particular airport . . . . maybe some fixup needed
double Dist = Math.Sqrt((car.cur_rp.Path[car.cur_rp.Path.Length - 1].P.x - car.TechCar.Pos().x) * (car.cur_rp.Path[car.cur_rp.Path.Length - 1].P.x - car.TechCar.Pos().x) + (car.cur_rp.Path[car.cur_rp.Path.Length - 1].P.y - car.TechCar.Pos().y) * (car.cur_rp.Path[car.cur_rp.Path.Length - 1].P.y - car.TechCar.Pos().y));
if (car.servPlaneNum != -1)
{
if (Dist < ((CurPlanesQueue[car.servPlaneNum].aircraft.Type() == AircraftType.Bomber) ? 20f : 10f))
//EndPlaneService(i);
EndPlaneService(car, car.TechCar);
}
else if (Dist < 15f)
{
//EndPlaneService(i);
EndPlaneService(car, car.TechCar);
}
}
if ((car.cur_rp == null) && (car.RouteFlag == 0) && (car.servPlaneNum != -1))
{
//EndPlaneService(car, car.TechCar);
};
if (car.servPlaneNum == -1 || car.TechCar == null)
//EndPlaneService(i); //Once it is no longer serving a plane, we just zap it.
EndPlaneService(car, car.TechCar);
};
}
//} catch (Exception e) {System.Console.WriteLine (e.ToString());}
}
internal BasePos FindNearestAirport(AiActor actor)
{
try
{
if (actor==null) return null;
Point3d pd = actor.Pos();
if (DEBUG) GamePlay.gpLogServer(null, "Checking airport " + actor.Name(), new object[] { });
return FindNearestAirport(pd) as BasePos;
}
catch (Exception e) {System.Console.WriteLine (e.ToString()); BasePos ret3=null; return ret3; }
}
internal BasePos FindNearestAirport(Point3d pd)
{
try{
AiActor aMin = null;
AiBirthPlace aMinB = null;
double d2Min = 0;
BasePos ret= new BasePos ();
BasePos ret2=new BasePos ();
Point3d retpd;
//If we find a birthplace (ie, spawnpoint) closer than 2km we return that
//otherwise we'll search all airports for something closer
//And . . AiBirthPlace & AiAirport & AiActor are ALMOST the same thing but then again not quite so we have to dance a bit.
aMinB=FindNearestBirthplace(pd);
//if (DEBUG) GamePlay.gpLogServer(null, "Checking airport (Birthplace) found " + aMinB.Name() + " " + aMinB.Pos().distance(ref pd).ToString("F0"), new object[] { });
//if (1==0 && aMinB!= null) {
if (aMinB!= null) {
d2Min=aMinB.Pos().distance(ref pd);
//if (DEBUG) GamePlay.gpLogServer(null, "Checking airport (Birthplace) found " + aMinB.Name() + " " + aMinB.Pos().distance(ref pd).ToString("F0")
//+ " " + aMinB.Pos().ToString(), new object[] { });
if (d2Min<2000) {
retpd=aMinB.Pos();
if (retpd.z==0) retpd.z = pd.z; //BirthPlaces usu. have elevation 0 which makes the ai route finder die horribly
ret= new BasePos (aMinB.Name(), retpd);
return ret;
}
}
if (DEBUG) GamePlay.gpLogServer(null, "Checking airport (Birthplace) NOfound " + d2Min.ToString("F0"), new object[] { });
int n = GamePlay.gpAirports().Length;
for (int i = 0; i < n; i++)
{
AiActor a = (AiActor)GamePlay.gpAirports()[i];
if (a==null) continue;
if (!a.IsAlive()) continue;
//if (DEBUG) GamePlay.gpLogServer(null, "Checking airport " + a.Name(), new object[] { });
Point3d pp;
pp = a.Pos();
pd.z = pp.z;
double d2 = pd.distanceSquared(ref pp);
if ((aMin == null) || (d2 < d2Min) )
{
aMin = a;
d2Min = d2;
}
}
if (DEBUG) GamePlay.gpLogServer(null, "CAirport Found: " + aMin.Name() + " " + aMin.Pos().ToString() + " dist " + d2Min.ToString("F2"), new object[] { });
//Hmm, with our new scheme it doesn't really matter if aMin is very
//distant or what. The cars always start relatively close to the a/c
//and **in the direction of** the airport, but not *at* the airport
//if (d2Min > 2250000.0)
// aMin = null;
//return aMin as BasePos
if (aMin != null) ret2= new BasePos (aMin.Name(), aMin.Pos());
if (DEBUG) GamePlay.gpLogServer(null, "CAirport Returning: " + ret2.Name() + " " + ret2.Pos().ToString() + " dist " + d2Min.ToString("F2") + " " + ret2.ToString("F0"), new object[] { });
return ret2;
}
catch (Exception e) {System.Console.WriteLine (e.ToString()); BasePos ret3=null; return ret3; }
}
public AiBirthPlace GetBirthPlaceByName(string birthPlaceName)
{
foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
{
if (DEBUG) GamePlay.gpLogServer(null, "Checking airport " + bp.Name(), new object[] { });
if (bp.Name() == birthPlaceName)
return bp;
}
return null;
}
public AiBirthPlace FindNearestBirthplace(AiActor actor)
{
//AiBirthPlace nearestBirthplace = null;
//AiBirthPlace[] birthPlaces = GamePlay.gpBirthPlaces();
Point3d pos = actor.Pos();
return FindNearestBirthplace(pos);
}
public AiBirthPlace FindNearestBirthplace (Point3d pos)
{
AiBirthPlace nearestBirthplace = null;
AiBirthPlace[] birthPlaces = GamePlay.gpBirthPlaces();
if (birthPlaces != null)
{
foreach (AiBirthPlace airport in birthPlaces)
{
if (nearestBirthplace != null)
{
//if (DEBUG) GamePlay.gpLogServer(null, "Checking airport " + airport.Name() + " "
// + airport.Pos().distance(ref pos).ToString("F0"), new object[] { });
if (nearestBirthplace.Pos().distance(ref pos) > airport.Pos().distance(ref pos))
nearestBirthplace = airport;
}
else nearestBirthplace = airport;
}
}
//AiActor ret=new AiActor();
//ret.Pos( nearestBirthplace.Pos());
//ret.Name(nearestBirthplace.Name());
if (DEBUG) GamePlay.gpLogServer(null, "Checking airport FOUND" + nearestBirthplace.Name() + " "
+ nearestBirthplace.Pos().distance(ref pos).ToString("F0"), new object[] { });
return nearestBirthplace;
}
//CONTINUED IN PART 2!
Note that I trimmed down some comments, debugging code, etc to make it fit on the forum better. Full code is in the ZIP file with script & mission files, sample code, instructions all in one Last edited by flug32; 05-22-2016 at 08:39 AM. |
|
#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);
}
}
}
Last edited by flug32; 05-22-2016 at 08:39 AM. |
![]() |
|
|