Code:
public static class TF_GamePlay : IGamePlay
{
public static Point3d[] gpGetGroundActorPoints(this IGamePlay GP, AiGroundActorType type)
{ // Purpose: Returns an array of 3d point locations for all the specified
// groundactor types.
// Use: GamePlay.GetGroundActorPoints(type);
List<Point3d> result = new List<Point3d>();
List<AiGroundActor> groundactors = new List<AiGroundActor>(GP.gpGetGroundActors());
for (int i = 0; i < groundactors.Count; i++)
{
if (groundactors[i].Type() == type) result.Add(groundactors[i].Pos());
}
return result.ToArray();
}
public static Point3d[] gpGetGroundActorPoints(this IGamePlay GP, AiGroundActorType type, int army)
{ // Purpose: Returns an array of 3d point locations for all the specified
// groundactor types in the specified army.
// Use: GamePlay.GetGroundActorPoints(type, army);
List<Point3d> result = new List<Point3d>();
List<AiGroundActor> groundactors = new List<AiGroundActor>(GP.gpGetGroundActors());
for (int i = 0; i < groundactors.Count; i++)
{
if (groundactors[i].Type() == type && groundactors[i].Army() == army)
result.Add(groundactors[i].Pos());
}
return result.ToArray();
}
public static AiActor gpGetActorAtPoint(this IGamePlay GP, Point3d point)
{ // Purpose: Returns the AiActor located at the specified point.
// Returns null if no actor at the point.
// Use: GamePlay.gpGetActorAtPoint(point);
AiActor result = null;
List<AiActor> actors = new List<AiActor>(GP.gpGetActors());
for (int i = 0; i < actors.Count; i++)
{
if (actors[i].Pos().distance(ref point) < 3) return actors[i] as AiActor;
}
return result;
}
public static GroundStationary gpGetGroundStationaryAtPoint(this IGamePlay GP, Point2d point)
{ // Purpose: Returns the groundstationary object located at the specified point.
// Returns null if no stationary object at the point.
// Use: GamePlay.gpGetActorAtPoint(point);
GroundStationary result = null;
List<GroundStationary> stationaries = new List<GroundStationary>(GP.gpGroundStationarys());
for (int i = 0; i < stationaries.Count; i++)
{
Point2d P = new Point2d(stationaries[i].pos.x, stationaries[i].pos.y);
if (P.distance(ref point) < 3)
return stationaries[i] as GroundStationary;
}
return result;
}
public static AiActor[] gpGetActors(this IGamePlay GP)
{ // Purpose: Returns an array of all the AiActors in the game.
// Use: GamePlay.gpGetAllAiActors();
List<AiActor> result = new List<AiActor>();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
// ground actors
List<AiGroundGroup> gg = new List<AiGroundGroup>(GP.gpGroundGroups(armies[i]));
for (int j = 0; j < gg.Count; j++)
{
List<AiActor> act = new List<AiActor>(gg[j].GetItems());
for (int k = 0; k < act.Count; k++)
result.Add(act[k] as AiActor);
}
// air actors
List<AiAirGroup> airgroups = new List<AiAirGroup>(GP.gpAirGroups(armies[i]));
for (int j = 0; j < airgroups.Count; j++)
{
List<AiActor> act = new List<AiActor>(airgroups[j].GetItems());
for (int k = 0; k < act.Count; k++)
result.Add(act[k] as AiActor);
}
}
return result.ToArray();
}
public static AiActor[] gpGetActors(this IGamePlay GP, int army)
{ // Purpose: Returns an array of all the AiActors in the
// specified army in the game.
// Use: GamePlay.gpGetAllAiActors();
List<AiActor> result = new List<AiActor>();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
// ground actors
List<AiGroundGroup> gg = new List<AiGroundGroup>(GP.gpGroundGroups(armies[i]));
for (int j = 0; j < gg.Count; j++)
{
List<AiActor> act = new List<AiActor>(gg[j].GetItems());
for (int k = 0; k < act.Count; k++)
{
if (act[k].Army() == army) result.Add(act[k] as AiActor);
}
}
// air actors
List<AiAirGroup> airgroups = new List<AiAirGroup>(GP.gpAirGroups(armies[i]));
for (int j = 0; j < airgroups.Count; j++)
{
List<AiActor> act = new List<AiActor>(airgroups[j].GetItems());
for (int k = 0; k < act.Count; k++)
{
if (act[k].Army() == army) result.Add(act[k] as AiActor);
}
}
}
return result.ToArray();
}
public static AiGroundActor[] gpGetGroundActors(this IGamePlay GP)
{ // Purpose: Returns an array of all ground actors in the game.
// Use: GamePlay.gpGroundActors();
List<AiGroundActor> result = new List<AiGroundActor>();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
List<AiGroundGroup> gg = new List<AiGroundGroup>(GP.gpGroundGroups(armies[i]));
for (int j = 0; j < gg.Count; j++)
{
List<AiActor> act = new List<AiActor>(gg[j].GetItems());
for (int k = 0; k < act.Count; k++)
result.Add(act[k] as AiGroundActor);
}
}
return result.ToArray();
}
public static AiGroundActor[] gpGetGroundActors(this IGamePlay GP, int army)
{ // Purpose: Returns an array of all ground actors in the game.
// Use: GamePlay.gpGroundActors();
List<AiGroundActor> result = new List<AiGroundActor>();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
List<AiGroundGroup> gg = new List<AiGroundGroup>(GP.gpGroundGroups(armies[i]));
for (int j = 0; j < gg.Count; j++)
{
List<AiActor> act = new List<AiActor>(gg[j].GetItems());
for (int k = 0; k < act.Count; k++)
{
if (act[k].Army() == army) result.Add(act[k] as AiGroundActor);
}
}
}
return result.ToArray();
}
public static double gpGetObjectRotation(this IGamePlay GP, string missionfile, double x, double y)
{ // Purpose: Returns the rotation angle of the object located at
// at the specified x, y coordinates
// Use: GamePlay.gpGetObjectRotation(missionfile, x, y);
double rotation = -1;
Point2d P = new Point2d(x, y);
Point2d C = new Point2d();
System.IO.StreamReader file = new System.IO.StreamReader(missionfile); // open the mission file for processing
string line;
while ((line = file.ReadLine()) != null) // read mission file one line at a time
{
line = line.Trim();
if (line.StartsWith("Static"))
{
string[] part = line.Split(' ');
rotation = Convert.ToDouble(part[5]);
C = new Point2d(Convert.ToDouble(part[3]), Convert.ToDouble(part[4]));
if (P.distance(ref C) <= 1) return rotation;
}
}
file.Close();
return rotation;
}
public static Regiment[] gpRegiments(this IGamePlay GamePlay)
{ // Purpose: Returns all the regiments in the game as a Regiment array.
// Use: GamePlay.gpRegiments();
List<Regiment> result = new List<Regiment>();
List<AiBirthPlace> BPs = new List<AiBirthPlace>(GamePlay.gpBirthPlaces());
for (int i = 0; i < BPs.Count; i++) result.Add(BPs[i].Regiment());
return result.ToArray();
}
public static Regiment[] gpRegiments(this IGamePlay GamePlay, int army)
{ // Purpose: Returns all the regiments for specified army as a Regiment array..
// Use: GamePlay.gpRegiments(army);
List<Regiment> result = new List<Regiment>();
List<AiBirthPlace> BPs = new List<AiBirthPlace>(GamePlay.gpBirthPlaces(army));
for (int i = 0; i < BPs.Count; i++) result.Add(BPs[i].Regiment());
return result.ToArray();
}
public static string[] gpArmyNames(this IGamePlay GamePlay)
{ // Purpose: Returns the names of all the armies in the game as a string array.
// Use: GamePlay.gpArmyNames();
List<string> result = new List<string>();
List<int> Armies = new List<int>(GamePlay.gpArmies());
for (int i = 0; i < Armies.Count; i++)
{
result.Add(GamePlay.gpArmyName(1));
}
return result.ToArray();
}
public static AiBirthPlace[] gpBirthPlaces(this IGamePlay GamePlay)
{ // Purpose: Returns all birthplaces/spawnbases in the game as a birthplace array.
// Use: GamePlay.gpBirthPlaces();
List<AiBirthPlace> result = new List<AiBirthPlace>();
List<AiBirthPlace> birthplaces = new List<AiBirthPlace>(GamePlay.gpBirthPlaces());
for (int j = 0; j < birthplaces.Count; j++)
result.Add(birthplaces[j]);
return result.ToArray();
}
public static AiBirthPlace[] gpBirthPlaces(this IGamePlay GamePlay, int army)
{ // Purpose: Returns all birthplaces/spawnbases for the specified army as a birthplace array.
// Use: GamePlay.gpBirthPlaces(army);
List<AiBirthPlace> result = new List<AiBirthPlace>();
List<AiBirthPlace> birthplaces = new List<AiBirthPlace>(GamePlay.gpBirthPlaces());
for (int j = 0; j < birthplaces.Count; j++)
{
if (birthplaces[j].Army() == army) result.Add(birthplaces[j]);
}
return result.ToArray();
}
public static int gpNumberOfPlayers(this IGamePlay GamePlay)
{ // Purpose: Returns the number of human players in the game.
// Use: GamePlay.NumberOfPlayers();
int result = 0;
// on Dedi the server:
if (GamePlay.gpPlayer() != null)
{
result = 1;
}
else
{ //rest of the crowd
if (GamePlay.gpRemotePlayers() != null || GamePlay.gpRemotePlayers().Length > 0)
{
return GamePlay.gpRemotePlayers().ToList().Count;
}
}
return result;
}
public static int gpNumberOfPlayers(this IGamePlay GamePlay, int army)
{ // Purpose: Returns the number of human players in the game in the
// specified army.
// Use: GamePlay.NumberOfPlayers(army);
int result = 0;
// on Dedi the server:
if (GamePlay.gpPlayer() != null)
{
if (GamePlay.gpPlayer().Army() == army) return 1;
result = 0;
}
else
{ //rest of the crowd
if (GamePlay.gpRemotePlayers() != null || GamePlay.gpRemotePlayers().Length > 0)
{
List<Player> players = new List<Player>(GamePlay.gpRemotePlayers());
for (int i = 0; i < players.Count; i++)
{
if (players[i].Army() == army) result += 1;
}
}
}
return result;
}
public static void gpSendChatMessageTo(this IGamePlay GamePlay, int army, string msg, object[] parms)
{ // Purpose: Send specified chat message to all players in specified army.
// Use: GamePlay.sendChatMessageTo();
List<Player> Players = new List<Player>();
// on Dedi the server:
if (GamePlay.gpPlayer() != null)
{
if (GamePlay.gpPlayer().Army() == army || army == -1)
Players.Add(GamePlay.gpPlayer());
} //rest of the crowd
if (GamePlay.gpRemotePlayers() != null || GamePlay.gpRemotePlayers().Length > 0)
{
foreach (Player p in GamePlay.gpRemotePlayers())
{
if (p.Army() == army || army == -1)
Players.Add(p);
}
}
if (Players != null && Players.Count > 0)
GamePlay.gpLogServer(Players.ToArray(), msg, parms);
}
public static void gpSayToArmy(this IGamePlay IG, int army, string msg)
{ // Purpose: Specified voice message to specified army.
// Use: GamePlay.gpSayToArmy();
try
{
foreach (AiAirGroup g in IG.gpAirGroups(army))
{
bool SaidToGroup = false;
foreach (AiActor a in g.GetItems())
{
if (SaidToGroup == true) break; // speech already said to group
SaidToGroup = true;
(a as AiAircraft).SayToGroup((a as AiAircraft).AirGroup(), msg);
}
}
}
catch { }
}
public static void gpShowAircraftIcons(this IGamePlay IG)
{ // Purpose: Show aircraft icons on the mini-map.
// Use: GamePlay.gpShowAircraftIcons();
List<AiAirGroup> airgroups = new List<AiAirGroup>(IG.gpAllGameAirgroups());
List<GPUserLabel> labels = new List<GPUserLabel>();
for (int i = 0; i < airgroups.Count; i++)
{
Point2d P = new Point2d(airgroups[i].Pos().x, airgroups[i].Pos().y);
string I = airgroups[i].ID().ToString();
string T = Convert.ToDouble(IG.gpTime()).ToString("HH:mm");
string N = airgroups[i].NOfAirc.ToString();
string A = airgroups[i].Altitude().ToString();
string H = airgroups[i].Heading().ToString();
string text = string.Concat("[", I,"] N:", N, " Alt:", A, " Hdg:", H);
GPUserLabel l;
l.pos = P;
l.Text = text;
l.time = Convert.ToDouble(IG.gpTime());
l.type = (int)GPUserIconType.Plane;
labels.Add(l);
}
List<Player> players = new List<Player>(IG.gpAllPlayers());
for (int i = 0; i < players.Count; i++)
{
for (int j = 0; j < labels.Count; j++)
{
GPUserLabel label = labels[j];
GPUserLabel lbl = IG.gpMakeUserLabel(label.pos, players[i], label.Text, label.time,
(int)GPUserIconType.Plane);
}
}
}
public static void gpSayEnemyPlanes(this IGamePlay IG, AiAirGroup airgroup, int army)
{ // Purpose: Voice announcement of specified airgroup to specified army.
// Use: GamePlay.gpSayEnemyPlanes(army, airgroup);
try
{
Random random = new Random(Guid.NewGuid().GetHashCode());
//Random random = new Random(Guid.NewGuid().GetHashCode());
// number of aircraft in groups of 5
IG.gpSayToArmy(army, (airgroup.NOfAirc).ToString()); // announce aircraft count
List<string> EnemyPlanesVoice = new List<string>
{
"Aicraft_a",
"Enemy_planes"
};
int i = random.Next(EnemyPlanesVoice.Count);
IG.gpSayToArmy(army, (EnemyPlanesVoice[i]).ToString()); // announce aircraft
}
catch { }
}
public static bool gpIsBirthPlace(this IGamePlay IG, AiAirport airport)
{ // Purpose: Returns true if the specified airport is a birthplace/spawnbase.
// Use: GamePlay.IsBirthPlace(airport);
bool result = false;
foreach (AiBirthPlace bp in IG.gpBirthPlaces())
{
Point3d p = bp.Pos();
if (airport.Pos().distance(ref p) <= airport.CoverageR() ||
airport.Pos().distance(ref p) <= airport.FieldR())
result = true;
}
return result;
}
public static int gpGetArmyAtPoint(this IGamePlay GP, double x, double y)
{ // Purpose: Returns the army number at the specified map point (x, y).
// Use: GamePlay.GetArmyAtPoint(x, y);
int result = -1;
result = GP.gpFrontArmy(x, y);
return result;
}
public static AiAirGroup[] gpAirGroups(this IGamePlay GP)
{ // Purpose: Returns all game airgroups as an airgroup array.
// Use: GamePlay.gpAllGameAirgroups();
List<AiAirGroup> result = new List<AiAirGroup>();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
List<AiAirGroup> airgroups = new List<AiAirGroup>(GP.gpAirGroups(i));
result.AddRange(airgroups);
}
return result.ToArray();
}
public static bool gpIsLandTypeWater(this IGamePlay IG, Point3d point)
{ // Purpose: Returns true if the specified point is in/over water.
// Use: GamePlay.gpIsLandTypeWater();
return (IG.gpLandType(point.x, point.y) == LandTypes.WATER);
}
public static bool gpIsLandTypeCity(this IGamePlay IG, Point3d point)
{ // Purpose: Returns true if the specified point is in/over a city.
// Use: GamePlay.gpIsLandTypeCity();
return (IG.gpLandType(point.x, point.y) == LandTypes.CITY);
}
public static Player[] gpAllPlayers(this IGamePlay GP)
{ // Purpose: Returns all humans players as a player array.
// Use: GamePlay.gpAllPlayers();
return GP.gpRemotePlayers();
}
public static Player[] gpAllPlayers(this IGamePlay GP, int army)
{ // Purpose: Returns all human players in the specified army as a player array.
// Use: GamePlay.gpAllPlayers();
List<Player> result = new List<Player>();
List<Player> players = new List<Player>(GP.gpRemotePlayers());
for (int i = 0; i < players.Count; i++)
{
if (players[i].Army() == army) result.Add(players[i]);
}
return result.ToArray();
}
public static AiAircraft[] gpAllAiAircraft(this IGamePlay GP)
{ // Purpose: Returns all Ai controlled (no humans aboard) aircraft as an array.
// Use: GamePlay.gpAllAiAiAircraft();
List<AiAircraft> result = new List<AiAircraft>();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
List<AiAirGroup> airgroups = new List<AiAirGroup>(GP.gpAirGroups(i));
for (int j = 0; j < airgroups.Count; j++)
{
List<AiActor> actors = new List<AiActor>(airgroups[j].GetItems());
for (int k = 0; k < actors.Count; k++)
{
AiAircraft ac = actors[k] as AiAircraft;
if (ac != null && ac.IsAiControlled()) result.Add(ac);
}
}
}
return result.ToArray();
}
public static AiAircraft[] gpAllAiAircraft(this IGamePlay GP, int army)
{ // Purpose: Returns all Ai controlled (no humans aboard) aircraft as an array.
// Use: GamePlay.gpAllAiAiAircraft();
List<AiAircraft> result = new List<AiAircraft>();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
List<AiAirGroup> airgroups = new List<AiAirGroup>(GP.gpAirGroups(i));
for (int j = 0; j < airgroups.Count; j++)
{
List<AiActor> actors = new List<AiActor>(airgroups[j].GetItems());
for (int k = 0; k < actors.Count; k++)
{
AiAircraft ac = actors[k] as AiAircraft;
if (ac != null && ac.IsAiControlled() && ac.Army() == army)
result.Add(ac);
}
}
}
return result.ToArray();
}
public static AiAircraft[] gpAllPlayerAircraft(this IGamePlay GP)
{ // Purpose: Returns all the aircraft with human players as an array.
// Use: GamePlay.gpAllPlayerAircraft();
List<AiAircraft> result = new List<AiAircraft>();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
List<AiAirGroup> airgroups = new List<AiAirGroup>(GP.gpAirGroups(i));
for (int j = 0; j < airgroups.Count; j++)
{
List<AiActor> actors = new List<AiActor>(airgroups[j].GetItems());
for (int k = 0; k < actors.Count; k++)
{
AiAircraft ac = actors[k] as AiAircraft;
if (ac != null && !ac.IsAiControlled()) result.Add(ac);
}
}
}
return result.ToArray();
}
public static AiAircraft[] gpAllPlayerAircraft(this IGamePlay GP, int army)
{ // Purpose: Returns all the aircraft with human players as an array.
// Use: GamePlay.gpAllPlayerAircraft();
List<AiAircraft> result = new List<AiAircraft>();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
List<AiAirGroup> airgroups = new List<AiAirGroup>(GP.gpAirGroups(i));
for (int j = 0; j < airgroups.Count; j++)
{
List<AiActor> actors = new List<AiActor>(airgroups[j].GetItems());
for (int k = 0; k < actors.Count; k++)
{
AiAircraft ac = actors[k] as AiAircraft;
if (ac != null && !ac.IsAiControlled() && ac.Army() == army)
result.Add(ac);
}
}
}
return result.ToArray();
}
public static AiAircraft[] gpAllAircraft(this IGamePlay GP)
{ // Purpose: Returns all the game aircraft as an array.
// Use: GamePlay.gpAllGameAircraft();
List<AiAircraft> result = new List<AiAircraft>();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
List<AiAirGroup> airgroups = new List<AiAirGroup>(GP.gpAirGroups(i));
for (int j = 0; j < airgroups.Count; j++)
{
List<AiActor> actors = new List<AiActor>(airgroups[j].GetItems());
for (int k = 0; k < actors.Count; k++)
{
AiAircraft ac = actors[k] as AiAircraft;
if (ac != null) result.Add(ac);
}
}
}
return result.ToArray();
}
public static AiAircraft[] gpAllAircraft(this IGamePlay GP, int army)
{ // Purpose: Returns all the game aircraft (Ai & human) as an array.
// Use: GamePlay.gpAllGameAircraft();
List<AiAircraft> result = new List<AiAircraft>();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
List<AiAirGroup> airgroups = new List<AiAirGroup>(GP.gpAirGroups(i));
for (int j = 0; j < airgroups.Count; j++)
{
List<AiActor> actors = new List<AiActor>(airgroups[j].GetItems());
for (int k = 0; k < actors.Count; k++)
{
AiAircraft ac = actors[k] as AiAircraft;
if (ac != null && ac.Army() == army) result.Add(ac);
}
}
}
return result.ToArray();
}
public static void gpSayEnemyGroupAltitude(this IGamePlay GP, AiAirGroup airgroup, string msg)
{ // Purpose: Stated voice announcement to specified airgroup.
// Use: GamePlay.gpSayEnemyGroupAltitude(airgroup, message);
double alt = airgroup.Altitude();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
foreach (AiAirGroup g in GP.gpAirGroups(i))
{
bool SaidToGroup = false;
foreach (AiActor a in g.GetItems())
{
if (SaidToGroup == true) break; // speech already said to group
SaidToGroup = true;
(a as AiAircraft).SayToGroup((a as AiAircraft).AirGroup(), msg);
}
}
}
}
public static AiAirport[] gpAirports(this IGamePlay GP, int army)
{ // Purpose: Returns all the game airports as an AiAirport array.
// Optionally can specify an army.
// Use: GamePlay.gpAirports(army)
List<AiAirport> result = new List<AiAirport>();
List<AiAirport> BP = new List<AiAirport>(GP.gpAirports());
for (int i = 0; i < BP.Count; i++)
{
if (BP[i].Army() == army) result.Add(BP[i]);
}
return result.ToArray();
}
public static AiAirport gpGetRandomAirfield(this IGamePlay GP)
{ // Purpose: Returns a random airport.
// Use: GamePlay.gpGetRandomAirfield()
Random random = new Random(Guid.NewGuid().GetHashCode());
List<AiAirport> AP = new List<AiAirport>(GP.gpAirports());
return AP[random.Next(AP.Count)];
}
public static AiAirport gpGetRandomAirfield(this IGamePlay GP, int army)
{
Random random = new Random(Guid.NewGuid().GetHashCode());
List<AiAirport> BP = new List<AiAirport>(GP.gpAirports(army));
AiAirport B = BP[random.Next(BP.Count)];
int n = 0;
while (B.Army() != army)
{
B = BP[random.Next(BP.Count)];
n += 1;
}
if (n >= 1000) throw new Exception(string.Format(
"gpRandomAirfield: No airport found for army {0}",
new object[] { army.ToString() }));
{
};
return B;
}
public static AiAirport gpGetRandomAirfield(this IGamePlay GP, Point2d centre, double radius)
{
Random random = new Random(Guid.NewGuid().GetHashCode());
List<AiAirport> BP = new List<AiAirport>(GP.gpAirports());
AiAirport B = BP[random.Next(BP.Count)];
Point2d P = new Point2d(B.Pos().x, B.Pos().y);
Point2d C = new Point2d(centre.x, centre.y);
int n = 0;
while ((C.distance(ref P) > radius) || n < 1000)
{
B = BP[random.Next(BP.Count)];
n += 1;
}
if (n >= 1000) throw new Exception(string.Format(
"gpRandomAirfield: No airfield found within {0} of point {1}-{2}",
new object[] { radius.ToString(), centre.x.ToString(), centre.y.ToString() }));
{
};
return B;
}
public static AiAirport gpGetRandomAirfield(this IGamePlay GP, Point3d centre, double radius)
{
return GP.gpGetRandomAirfield(new Point2d(centre.x, centre.y), radius);
}
public static AiBirthPlace gpGetRandomBirthplace(this IGamePlay GP)
{
Random random = new Random(Guid.NewGuid().GetHashCode());
List<AiBirthPlace> BP = new List<AiBirthPlace>(GP.gpBirthPlaces());
return BP[random.Next(BP.Count)];
}
public static AiBirthPlace gpGetRandomBirthplace(this IGamePlay GP, int army)
{
Random random = new Random(Guid.NewGuid().GetHashCode());
List<AiBirthPlace> BP = new List<AiBirthPlace>(GP.gpBirthPlaces());
AiBirthPlace B = BP[random.Next(BP.Count)];
int n = 0;
while (B.Army() != army)
{
B = BP[random.Next(BP.Count)];
n += 1;
}
if (n >= 1000) throw new Exception(string.Format(
"gpRandomBirthplace: No birthplace found for army {0}",
new object[] {army.ToString()}));
{
};
return B;
}
public static AiBirthPlace gpGetRandomBirthplace(this IGamePlay GP, Point2d centre, double radius)
{
Random random = new Random(Guid.NewGuid().GetHashCode());
List<AiBirthPlace> BP = new List<AiBirthPlace>(GP.gpBirthPlaces());
AiBirthPlace B = BP[random.Next(BP.Count)];
Point2d P = new Point2d(B.Pos().x, B.Pos().y);
int n = 0;
while ((centre.distance(ref P) > radius) || n < 1000)
{
B = BP[random.Next(BP.Count)];
n += 1;
}
if (n >= 1000) throw new Exception(string.Format(
"gpRandomBirthplace: No birthplace found within {0} of point {1}-{2}",
new object[] { radius.ToString(), centre.x.ToString(), centre.y.ToString() }));
{
};
return B;
}
public static AiBirthPlace gpGetNearestBirthplace(this IGamePlay GP, Point3d point)
{ // Purpose: Returns the nearest birthplace to the specified point.
// Use: GamePlay.gpNearestBirthplace(location);
AiBirthPlace NearestBirthplace = null;
AiBirthPlace[] BirthPlaces = GP.gpBirthPlaces();
if (BirthPlaces != null)
{
foreach (AiBirthPlace bp in BirthPlaces)
{
if (NearestBirthplace != null)
{
if (bp.Pos().distance(ref point) < NearestBirthplace.Pos().distance(ref point))
NearestBirthplace = bp;
}
else
{
NearestBirthplace = bp;
}
}
}
return NearestBirthplace;
}
public static AiAirport gpGetNearestAirfield(this IGamePlay GP, Point3d point)
{ // Purpose: Returns the nearest airfield to the specified actor.
// Use: GamePlay.gpNearestAirfield(actor);
AiAirport NearestAirfield = null;
List<AiAirport> airports = new List<AiAirport>(GP.gpAirports());
for (int i = 0; i < airports.Count; i++)
{
AiAirport ThisAirport = airports[i];
if (ThisAirport.Pos().distance(ref point) < NearestAirfield.Pos().distance(ref point))
NearestAirfield = ThisAirport;
}
return NearestAirfield;
}
public static AiAirport gpGetNearestAirfield(this IGamePlay GP, Point2d point)
{ // Purpose: Returns the nearest airfield to the specified actor.
// Use: GamePlay.gpNearestAirfield(point);
return GP.gpGetNearestAirfield(new Point3d(point.x, point.y, 0));
}
public static AiAirport gpGetNearestFriendlyAirfield(this IGamePlay GP, object obj)
{ // Purpose: Returns the nearest friendly airfield to the specified game object.
// Use: GamePlay.gpNearestFriendlyAirfield(actor);
AiAirport NearestAirfield = null;
Point3d P = new Point3d();
int TheArmy = -1;
if (obj is AiActor)
{
TheArmy = (obj as AiActor).Army();
P = (obj as AiActor).Pos();
}
else if (obj is AiAircraft)
{
TheArmy = (obj as AiAircraft).Army();
P = (obj as AiAircraft).Pos();
}
else if (obj is AiGroundActor)
{
TheArmy = (obj as AiGroundActor).Army();
P = (obj as AiGroundActor).Pos();
}
else if (obj is GroundStationary)
{
TheArmy = (obj as GroundStationary).Army();
P = (obj as GroundStationary).pos;
}
else { };
List<AiAirport> airports = new List<AiAirport>(GP.gpAirports(TheArmy));
for (int i = 0; i < airports.Count; i++)
{
AiAirport ThisAirport = airports[i];
if (ThisAirport.Pos().distance(ref P) < NearestAirfield.Pos().distance(ref P))
NearestAirfield = ThisAirport;
}
return NearestAirfield;
}
public static AiAirport gpGetNearestEnemyAirfield(this IGamePlay GP, object obj)
{ // Purpose: Returns the nearest enemy airfield to the specified actor.
// Use: GamePlay.gpNearestEnemyAirfield(actor);
AiAirport NearestAirfield = null;
Point3d P = new Point3d();
int TheArmy = -1;
if (obj is AiActor)
{
TheArmy = (obj as AiActor).Army();
P = (obj as AiActor).Pos();
}
else if (obj is AiAircraft)
{
TheArmy = (obj as AiAircraft).Army();
P = (obj as AiAircraft).Pos();
}
else if (obj is AiGroundActor)
{
TheArmy = (obj as AiGroundActor).Army();
P = (obj as AiGroundActor).Pos();
}
else if (obj is GroundStationary)
{
TheArmy = (obj as GroundStationary).Army();
P = (obj as GroundStationary).pos;
}
else { };
List<AiAirport> airports = new List<AiAirport>(GP.gpAirports());
for (int i = 0; i < airports.Count; i++)
{
AiAirport ThisAirport = airports[i];
if (ThisAirport.Army() != TheArmy)
{
if (ThisAirport.Pos().distance(ref P) < NearestAirfield.Pos().distance(ref P))
NearestAirfield = ThisAirport;
}
}
return NearestAirfield;
}
public static Player gpGetNearestPlayer(this IGamePlay GP, AiActor actor)
{ // Purpose: Returns the nearest human player to the specified actor.
// Excludes other humans in the same AiCart (aircraft)
// Use: GamePlay.gpNearestPlayer(actor);
Player NearestPlayer = null;
Point3d P = actor.Pos();
AiCart ActorCart = (actor as AiPerson).Cart();
List<Player> players = new List<Player>(GP.gpRemotePlayers());
for (int i = 0; i < players.Count; i++)
{
Player ThisPlayer = players[i];
AiCart ThisPlayerCart = (ThisPlayer as AiPerson).Cart();
if (ThisPlayer.Place().Pos().distance(ref P) < NearestPlayer.Place().Pos().distance(ref P)
&& ThisPlayer.Place() != actor
&& ThisPlayer != null
&& ActorCart != ThisPlayerCart)
NearestPlayer = ThisPlayer;
}
return NearestPlayer;
}
public static Player gpGetNearestPlayer(this IGamePlay GP, AiPerson person)
{ // Purpose: Returns the nearest human player to the specified person.
// Use: GamePlay.gpNearestPlayer(person);
return GP.gpGetNearestPlayer(person.Player().Place());
}
public static Player gpGetNearestPlayer(this IGamePlay GP, Player player)
{ // Purpose: Returns the nearest human player to the specified player.
// Use: GamePlay.gpNearestPlayer(player);
return GP.gpGetNearestPlayer(player.Place());
}
public static AiAircraft gpGetNearestAircraft(this IGamePlay GP, AiActor actor)
{ // Purpose: Returns the nearest aircraft to the specified point.
// Use: GamePlay.gpNearestAircraft(point);
AiAircraft NearestAircraft = null;
Point3d P = actor.Pos();
List<AiAircraft> aircrafts = new List<AiAircraft>(GP.gpAllAiAircraft());
for (int i = 0; i < aircrafts.Count; i++)
{
AiAircraft aircraft = aircrafts[i] as AiAircraft;
if (aircraft != null)
{
if (NearestAircraft == null) NearestAircraft = aircraft;
if (aircraft.Pos().distance(ref P) < NearestAircraft.Pos().distance(ref P))
NearestAircraft = aircraft;
}
}
return NearestAircraft;
}
public static AiAircraft gpGetNearestFriendlyAircraft(this IGamePlay GP, AiActor actor)
{ // Purpose: Returns the nearest frinedly aircraft to the specified actor.
// Use: GamePlay.gpNearestFriendlyAircraft(actor);
AiAircraft NearestAircraft = null;
Point3d P = actor.Pos();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
List<AiAirGroup> ag = new List<AiAirGroup>(GP.gpAirGroups(armies[i]));
for (int j = 0; j < ag.Count; j++)
{
List<AiActor> actors = new List<AiActor>(ag[j].GetItems());
for (int k = 0; k < actors.Count; k++)
{
AiAircraft aircraft = actors[k] as AiAircraft;
if (aircraft != null && aircraft.Army() == actor.Army())
{
if (aircraft.Pos().distance(ref P) < NearestAircraft.Pos().distance(ref P))
NearestAircraft = aircraft;
}
}
}
}
return NearestAircraft;
}
public static AiAircraft gpGetNearestEnemyAircraft(this IGamePlay GP, AiActor actor)
{ // Purpose: Returns the nearest enemy aircraft to the specified actor.
// Use: GamePlay.gpNearestEnemyAircraft(actor);
AiAircraft NearestAircraft = null;
Point3d P = actor.Pos();
List<int> armies = new List<int>(GP.gpArmies());
for (int i = 0; i < armies.Count; i++)
{
List<AiAirGroup> ag = new List<AiAirGroup>(GP.gpAirGroups(armies[i]));
for (int j = 0; j < ag.Count; j++)
{
List<AiActor> actors = new List<AiActor>(ag[j].GetItems());
for (int k = 0; k < actors.Count; k++)
{
AiAircraft aircraft = actors[k] as AiAircraft;
if (aircraft != null && aircraft.Army() != actor.Army())
{
if (aircraft.Pos().distance(ref P) < NearestAircraft.Pos().distance(ref P))
NearestAircraft = aircraft;
}
}
}
}
return NearestAircraft;
}
public static void gpPlaneTypesInBirthplaceLabels(this IGamePlay GP)
{ // Purpose: Adds available plane types in the all spawn-base map labels.
// Use: GamePlay.PutPlaneTypesInBirthplaceLabels();
gpPlaneTypesInBirthplaceLabels(GP, GP.gpBirthPlaces());
}
public static void gpPlaneTypesInBirthplaceLabels(this IGamePlay GP, AiBirthPlace birthplace)
{ // Purpose: Puts plane types in the specified spawn-base map labels.
// Use: GamePlay.gpPutPlaneTypesInBirthplaceLabels(birthplaces);
AiBirthPlace[] bps = null;
bps[0] = birthplace;
gpPlaneTypesInBirthplaceLabels(GP, bps);
}
private static void gpPlaneTypesInBirthplaceLabels(this IGamePlay GP, AiBirthPlace[] birthplaces)
{ // Purpose: Puts plane types in the specified spawn-bases map labels.
// Use: GamePlay.gpPutPlaneTypesInBirthplaceLabels(birthplaces);
foreach (AiBirthPlace bp in birthplaces)
{
string OldMapLabel = bp.Name();
string[] Planeset = bp.GetAircraftTypes();
string[] words = bp.Name().Trim().Split('(');
string MapLabel = words[0] + " (";
foreach (string aircraftname in Planeset)
{
if (aircraftname.Contains("Spit")) MapLabel = MapLabel + "Spitfire, ";
if (aircraftname.Contains("Hurr")) MapLabel = MapLabel + "Hurricane, ";
if (aircraftname.Contains("Blenheim")) MapLabel = MapLabel + "Blenheim, ";
if (aircraftname.Contains("DH82A ")) MapLabel = MapLabel + "Tiger Moth, ";
if (aircraftname.Contains("88")) MapLabel = MapLabel + "Ju88, ";
if (aircraftname.Contains("87")) MapLabel = MapLabel + "Ju87, ";
if (aircraftname.Contains("109")) MapLabel = MapLabel + "Bf109, ";
if (aircraftname.Contains("BR")) MapLabel = MapLabel + "BR20, ";
if (aircraftname.Contains("G50")) MapLabel = MapLabel + "G50, ";
if (aircraftname.Contains("111")) MapLabel = MapLabel + "He111, ";
if (aircraftname.Contains("110")) MapLabel = MapLabel + "Bf110, ";
if (aircraftname.Contains("CR")) MapLabel = MapLabel + "CR42, ";
}
MapLabel = MapLabel.Remove(MapLabel.LastIndexOf(',')) + ")"; ; // get last occurance of , character
GP.gpRenameBirthplace(bp, MapLabel);
}
}
public static AircraftType[] gpAircraftTypes(this IGamePlay GP, AiBirthPlace birthplace)
{ // Purpose: Returns the AircraftTypes for the specified birthplace.
// Use: GamePlay.gpAircraftTypes(birthplace);
List<string> types = new List<string>(birthplace.GetAircraftTypes());
HashSet<AircraftType> result = new HashSet<AircraftType>();
for (int i = 0; i < types.Count; i++)
{
string aircraftname = types[i];
if (aircraftname.Contains("Spit")) result.Add(AircraftType.Fighter);
if (aircraftname.Contains("Hurr")) result.Add(AircraftType.Fighter);
if (aircraftname.Contains("Blenheim")) result.Add(AircraftType.Bomber);
if (aircraftname.Contains("DH82A ")) result.Add(AircraftType.Fighter);
if (aircraftname.Contains("88")) result.Add(AircraftType.DiveBomber);
if (aircraftname.Contains("87")) result.Add(AircraftType.DiveBomber);
if (aircraftname.Contains("109")) result.Add(AircraftType.Fighter);
if (aircraftname.Contains("BR")) result.Add(AircraftType.Bomber);
if (aircraftname.Contains("G50")) result.Add(AircraftType.Fighter);
if (aircraftname.Contains("111")) result.Add(AircraftType.Bomber);
if (aircraftname.Contains("110")) result.Add(AircraftType.HeavyFighter);
if (aircraftname.Contains("CR")) result.Add(AircraftType.Fighter);
}
return result.ToArray();
}
public static bool gpHasAircraftType(this IGamePlay GP, AiBirthPlace birthplace, AircraftType type)
{ // Purpose: Returns true if the specified birthplace planeset has the specified aircrafttype.
// Use: GamePlay.gpAircraftTypes(birthplace, aircraftype);
return GP.gpAircraftTypes(birthplace).Contains(type);
}
public static bool gpHasAntiairDefence(this IGamePlay GP, AiAirport airport)
{ // Purpose: Returns true if the specified airport has antiaircraft defences.
// Use: GamePlay.gpHasAntiairDefence(birthplace);
List<GroundStationary> gs = new List<GroundStationary>(GP.gpGroundStationarys());
for (int j = 0; j < gs.Count; j++)
{
Point3d p = airport.Pos();
if (gs[j].pos.distance(ref p) < airport.CoverageR() &&
(gs[j].Type == AiGroundActorType.AAGun ||
gs[j].Type == AiGroundActorType.Balloon))
return true;
}
return false;
}
public static bool gpHasAntiairDefence(this IGamePlay GP, Point2d centre, double radius)
{ // Purpose: Returns true if there are antiaircraft defences with circle with
// specified centre & radius.
// Use: GamePlay.gpHasAntiairDefence(birthplace);
List<GroundStationary> gs = new List<GroundStationary>(GP.gpGroundStationarys());
for (int j = 0; j < gs.Count; j++)
{
Point2d P = new Point2d(gs[j].pos.x, gs[j].pos.y);
if (P.distance(ref centre) < radius &&
(gs[j].Type == AiGroundActorType.AAGun ||
gs[j].Type == AiGroundActorType.Balloon))
return true;
}
return false;
}
public static void gpRenameBirthplace(this IGamePlay GP, AiBirthPlace birthplace, string name)
{ // Purpose: Renames the specified birthplace/spawnpoint.
// Use: GamePlay.gpRenameSpawnbase(birthplace, name);
try
{
ISectionFile f = GP.gpCreateSectionFile();
string line = '"' + name + '"' + birthplace.Army().ToString() + " " + birthplace.Pos().x.ToString() + " " +
birthplace.Pos().y.ToString() + " 0 " + birthplace.MaxPlanes().ToString() + " " + "1" + " " +
"1" + " " + birthplace.Country() + " " + birthplace.Hierarchy() + " " + birthplace.Regiment();
f.add("BirthPlace", line, null); // write a line of text to the file
string[] planeset = birthplace.GetAircraftTypes();
foreach (string aircraft in planeset) f.add("BirthPlace0", aircraft, null);
birthplace.destroy();
GP.gpPostMissionLoad(f);
}
catch (NullReferenceException n)
{ }
catch (Exception e)
{
Console.WriteLine("ERROR: [gpRenameSpawnbase] " + e.Message);
}
}
public static void gpCreateBirthplace(this IGamePlay GP, Point3d point,
string[] aircrafttype, string name, int army, double spawnheight,
int maxplanes, int parachute, int parked, string country,
string heirarchy, Regiment regiment)
{ // Purpose: Creates a new birthplace/spawnbase at the specified point.
// Use: GamePlay.gpRenameSpawnbase(birthplace, name);
if (heirarchy == "") heirarchy = ".";
if (country == "De" || country == "DE" || country.Contains("germany") || country.Contains("axis") || country.Contains("blue")) country = "de";
if (country == "Gb" || country == "GB" || country.Contains("britain") || country.Contains("allie") || country.Contains("red")) country = "gb";
ISectionFile f = GP.gpCreateSectionFile();
string line = '"' + name + '"' + army.ToString() + " " + point.x.ToString("000000") + " " +
point.y.ToString("000000") + " " + spawnheight.ToString("0000") + " " + maxplanes + " " + parachute + " " +
parked + " " + country + " " + heirarchy + " " + regiment;
f.add("BirthPlace", line, null);
foreach (string aircraft in aircrafttype) f.add("BirthPlace0", aircraft, null);
GP.gpPostMissionLoad(f);
}
public enum Effect
{
SmokeSmall,
SmokeLarge,
FireSmall,
FireLarge,
BombCraterSmall,
BombCraterMedium,
BombCraterLarge
}
public static void gpCreateEffect(this IGamePlay GP, Effect effect, double x, double y, double DurationSecs)
{ // Purpose: Spawns the specified effect at the specified map location for specified number of seconds.
// Use: GamePlay.gpCreateEffect(effect, x, y, DurationSecs);
Random random = new Random(Guid.NewGuid().GetHashCode());
AMission AM = GP as AMission;
string eff = null;
switch (effect)
{
case Effect.FireLarge: // fire & grey smoke
/*
Static3 Smoke.Environment.Smoke2 nn 75862.56 180485.61 0.00 /height 13.00
Static2 Smoke.Environment.Smoke1 nn 75900.77 180501.92 0.00 /height 13.00
Static1 Smoke.Environment.BuildingFireSmall nn 75954.15 180521.39 0.00 /height 13.00
Static0 Smoke.Environment.BuildingFireBig nn 76004.80 180546.89 0.00 /height 13.05
* */
eff = " Smoke.Environment.BuildingFireBig";
break;
case Effect.FireSmall: // fire & grey smoke
eff = " Smoke.Environment.BuildingFireSmall";
break;
case Effect.SmokeLarge: // smokeA black smoke & fire
eff = " Smoke.Environment.Smoke1";
break;
case Effect.SmokeSmall:// smokeB black smoke
eff = " Smoke.Environment.Smoke2";
break;
case Effect.BombCraterLarge:
// make bomb crater TF 4.0
// Static0 Stationary.Environment.BombCrater_firmSoil_mediumkg nn 251217.50 257427.39 -520.00
// Static2 Stationary.Environment.BombCrater_firmSoil_largekg nn 251211.73 257398.98 -520.00
// Static1 Stationary.Environment.BombCrater_firmSoil_smallkg nn 251256.22 257410.66 -520.00
eff = " Stationary.Environment.BombCrater_firmSoil_largekg";
break;
case Effect.BombCraterMedium:
eff = " Stationary.Environment.BombCrater_firmSoil_mediumkg";
break;
case Effect.BombCraterSmall:
eff = " Stationary.Environment.BombCrater_firmSoil_smallkg";
break;
default:
break;
}
if (GP != null && AM != null && !string.IsNullOrEmpty(eff))
{
ISectionFile f = GP.gpCreateSectionFile();
// Static0 Smoke.Environment.BuildingFireBig nn 76004.80 180546.89 0.00 /height 13.05
string s = string.Concat(eff, " nn ", x.ToString("#0.00"), " ",
y.ToString("#0.00"), " ", random.Next(1, 178 + 1).ToString("#0.00"), " /height 13.5");
f.add("Stationary", "Static0", s);
GP.gpPostMissionLoad(f);
if (DurationSecs < double.MaxValue)
{
AM.Timeout(DurationSecs, () =>
{
List<GroundStationary> gs = new List<GroundStationary>(GP.gpGroundStationarys(x, y, 2));
for (int i = 0; i < gs.Count; i++)
{
if (gs[i].Title.Contains(eff.Trim().Split('.')[2]))
{
Point2d P = new Point2d(gs[i].pos.x, gs[i].pos.y);
GP.gpRemoveGroundStationarys(P, 2);
}
}
});
}
}
}
public static void gpCreateCityFire(this IGamePlay GP, double x, double y, double DurationSecs)
{ // Purpose: Spawns a fire at specified map location if that location is in a city.
// Fires in a city have a chance to spread throughout the city.
// Use: GamePlay.gpCreateCityFire(x, y, DurationSecs);
Random random = new Random(Guid.NewGuid().GetHashCode());
AMission AM = GP as AMission;
if (AM != null && GP != null && GP.gpLandType(x, y) == LandTypes.CITY)
{ // fire spreads in cities
GP.gpCreateEffect(Effect.FireLarge, x, y, DurationSecs);
List<GroundStationary> gs = new List<GroundStationary>(GP.gpGroundStationarys(x, y, 5000));
for (int i = 0; i < gs.Count; i++)
{ // find a point 30 - 80m way
Point2d p = new Point2d(
(random.NextDouble() * (80 - 30) + 30) * Math.Cos(random.Next()),
(random.NextDouble() * (80 - 30) + 30) * Math.Sin(random.Next()));
if (gs[i].Title.Contains("BuildingFireBig") &&
(random.NextDouble() < 0.50 && GP.gpLandType(p.x, p.y) == LandTypes.CITY))
{ // 50% chance of fire to spread
AM.Timeout((DurationSecs / 4), () =>
{
GP.gpCreateCityFire(p.x, p.y, DurationSecs);
});
}
}
}
}
public static void gpRemoveGroundStationarys(this IGamePlay IG, Point2d centre, double radius)
{ // Purpose: Removes ground stationary objects within a circle with centre x, y
// and radius from the game.
// Use: GamePlay.gpRemoveGroundStationarys(x, y, radius);
foreach (GroundStationary gs in IG.gpGroundStationarys(centre.x, centre.y, radius)) gs.Destroy();
}
public static AiAirWayPoint[] gpFlightLandAt(this IGamePlay GP, AiAirGroup airgroup, AiAirport airport)
{ // Purpose: Set the airgroup to land at the specified airport.
// Use: airgroup.LandAt(airport);
Random random = new Random(Guid.NewGuid().GetHashCode());
List<AiWayPoint> ways = new List<AiWayPoint>(airgroup.GetWay());
List<AiAirWayPoint> NewWays = new List<AiAirWayPoint>();
double x;
double y;
// current waypoint
AiAirWayPoint AWP = null;
AWP.P = airgroup.Pos();
AWP.Speed = airgroup.AirSpeedTAS();
AWP.Action = AiAirWayPointType.NORMFLY;
NewWays.Add(AWP);
// third last waypoint to maintain aircraft height
Point3d p = airport.Pos();
double dist = (airgroup.Pos().distance(ref p));
double StartDescendDist = 10000;
if (dist > StartDescendDist)
{
double fi = Math.Atan2(airgroup.Pos().y - airport.Pos().y, airgroup.Pos().x - airport.Pos().x);
x = airport.Pos().x + StartDescendDist * Math.Cos(fi);
y = airport.Pos().y + StartDescendDist * Math.Sin(fi);
AWP.P = new Point3d(x, y, airgroup.Altitude());
AWP.Speed = airgroup.AirSpeedTAS();
AWP.Action = AiAirWayPointType.NORMFLY;
NewWays.Add(AWP);
}
// second last waypoint over airfield
x = airport.Pos().x + airport.CoverageR() * Math.Cos(random.Next());
y = airport.Pos().y + airport.CoverageR() * Math.Sin(random.Next());
double SecondLastWWayMax = 1200;
double SecondLastWayMin = 500;
double z = random.NextDouble() * (SecondLastWWayMax - SecondLastWayMin) + SecondLastWayMin;
if (airgroup.Altitude() <= SecondLastWayMin) z = airgroup.Altitude();
AWP.P = new Point3d(x, y, z);
AWP.Speed = airgroup.AirSpeedTAS();
AWP.Action = AiAirWayPointType.NORMFLY;
NewWays.Add(AWP);
// landing waypoint
AWP.P = new Point3d(airport.Pos().x, airport.Pos().y, airport.Pos().x);
AWP.Speed = airgroup.AirSpeedTAS();
AWP.Action = AiAirWayPointType.LANDING;
NewWays.Add(AWP);
return NewWays.ToArray();
// give the new paypoints
//airgroup.SetWay(NewWays.ToArray());
}
public static AiAirWayPoint[] gpFlightTakeoffFrom(this IGamePlay GP, AiAirGroup airgroup, AiBirthPlace birthplace)
{ // Purpose: Set the airgroup to takeoff from the specified airport.
// Use: airgroup.TakeoffFrom(airport);
Random random = new Random(Guid.NewGuid().GetHashCode());
//List<AiWayPoint> ways = new List<AiWayPoint>(airgroup.GetWay());
List<AiAirWayPoint> NewWays = new List<AiAirWayPoint>();
double x;
double y;
Point2d P1 = new Point2d(birthplace.Pos().x, birthplace.Pos().y);
Point2d P2 = new Point2d();
// takeoff waypoint
AiAirWayPoint AWP = null;
AWP.P = birthplace.Pos();
AWP.Speed = 300;
AWP.Action = AiAirWayPointType.TAKEOFF;
NewWays.Add(AWP);
// 2nd waypoint
double MinDist = 5000;
double MaxDist = 7500;
var angle = random.NextDouble() * Math.PI * 2;
var radius = random.NextDouble() * MaxDist;
x = birthplace.Pos().x + radius * Math.Cos(angle);
y = birthplace.Pos().y + radius * Math.Sin(angle);
P2 = new Point2d(x, y);
while (P1.distance(ref P2) < MinDist)
{
angle = random.NextDouble() * Math.PI * 2;
radius = random.NextDouble() * MaxDist;
x = birthplace.Pos().x + radius * Math.Cos(angle);
y = birthplace.Pos().y + radius * Math.Sin(angle);
P2 = new Point2d(x, y);
}
double alt = random.NextDouble() * 3000;
while (alt < 1000) alt = random.NextDouble() * 3000;
AWP.P = new Point3d(x, y, alt);
AWP.Speed = 300;
AWP.Action = AiAirWayPointType.NORMFLY;
return NewWays.ToArray();
}
public enum PathType
{
Simple,
Direct,
None,
Complex
}
public static AiAirWayPoint[] gpFlightFromTo(this IGamePlay GP, AiAirGroup airgroup, Point3d pointA, Point3d pointB, TF_GamePlay.PathType type)
{ // Purpose: Set the airgroup to fly from pointA to pointB.
// Use: airgroup.gpFlightFromTo(pointA, pointB);
List<AiAirWayPoint> NewWays = new List<AiAirWayPoint>();
AiAirWayPoint AWP = null;
List<Point3d> ways = new List<Point3d>(LevyFlight(pointA, pointB, type));
for (int i = 0; i < ways.Count; i++)
{
AWP.P = ways[i];
AWP.Speed = 300;
AWP.Action = AiAirWayPointType.NORMFLY;
NewWays.Add(AWP);
}
return NewWays.ToArray();
}
private static Point3d[] LevyFlight(Point3d pointA, Point3d pointB, PathType type)
{ // Lévy flight from point A to point B
// ref: https://en.wikipedia.org/wiki/L%C3%A9vy_flight
Random random = new Random(Guid.NewGuid().GetHashCode());
double alpha = 1.5;
List<Point3d> path = new List<Point3d>();
Point3d P = pointA;
path.Add(P);
bool done = false;
double FinalLeg = 10000;
switch (type)
{
case PathType.None:
FinalLeg = pointB.distance(ref pointA);
break;
case PathType.Complex:
FinalLeg = 10000;
break;
}
while (!done)
{
double theta = random.NextDouble() * 2 * Math.PI;
double f = Math.Pow(random.NextDouble(), (-1 / alpha));
P = new Point3d(path[path.Count].x + f * Math.Cos(theta),
path[path.Count].y + f * Math.Sin(theta),
path[path.Count].z);
while (pointB.distance(ref P) > path[path.Count].distance(ref pointB))
{
theta = random.NextDouble() * 2 * Math.PI;
f = Math.Pow(random.NextDouble(), (-1 / alpha));
P = new Point3d(path[path.Count].x + f * Math.Cos(theta),
path[path.Count].y + f * Math.Sin(theta),
path[path.Count].z);
}
if (pointB.distance(ref P) > FinalLeg)
{
path.Add(P);
}
else
{
path.Add(pointB);
done = true;
}
}
path.Add(P);
// post hoc altitude interpolation
double dAlt = pointB.z - pointA.z;
if (dAlt != 0)
{
for (int i = 0; i < path.Count; i++)
{
P = path[i];
P.z = P.z / dAlt / path.Count;
path[i] = P;
}
}
return path.ToArray();
}
private double BearingBetweenTwoPoints(Point3d pointA, Point3d pointB)
{
double dx = pointB.x - pointA.x;
double dy = pointB.y - pointA.y;
return Math.Atan2(dy, dx) * 180.0 / Math.PI;
}
public static void gpMakeFlightPath(this IGamePlay GP, AiAirGroup airgroup, AiAirWayPoint[] ways)
{ // Purpose: Set the airgroup with the specified waypoints.
// Use: airgroup.gpFlightFromTo(pointA, pointB);
airgroup.SetWay(ways);
}
public static void gpMakeFlightPath(this IGamePlay GP, AiAirGroup airgroup, List<AiAirWayPoint[]> ways)
{
List<AiAirWayPoint> result = new List<AiAirWayPoint>();
for (int i = 0; i < ways.Count; i++)
result.AddRange(new List<AiAirWayPoint>(ways[i]));
gpMakeFlightPath(GP, airgroup, result.ToArray());
}
}
Bookmarks