FG28_Kodiak |
06-26-2012 04:15 PM |
Found a problem by removing the spawnplace more than one time. :rolleyes:
Corrected Version:
Code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using maddox.GP;
using maddox.game;
using maddox.game.world;
using part;
public class Mission : AMission
{
private bool battleEnded;
internal static class ActorObservation
{
internal class ActorDetail
{
public AiActor Actor { get; set; }
private DateTime TimeStamp;
private Point3d LastPosition;
public bool Started { get; private set; }
public bool Destroyed { get; private set; }
public bool IsParachuted { get; set; }
public ActorDetail(AiActor actor)
{
Actor = actor;
TimeStamp = DateTime.Now;
LastPosition = actor.Pos();
}
public TimeSpan CheckActor()
{
TimeSpan positionNotChangedSince = new TimeSpan();
Point3d CurrentPos = Actor.Pos();
if (Actor is AiAircraft)
if ((Actor as AiAircraft).getParameter(ParameterTypes.Z_AltitudeAGL, -1) > 20)
// Plane counts as started if Altitude over Ground is larger than 20m
Started = true;
// Actor does not change Position
if (LastPosition.distance(ref CurrentPos) < 0.5 && Started)
positionNotChangedSince = DateTime.Now.Subtract(TimeStamp);
else
{
LastPosition = CurrentPos;
TimeStamp = DateTime.Now;
}
return positionNotChangedSince;
}
public void Destroy()
{
AiCart cart = Actor as AiCart;
if (cart != null)
{
cart.Destroy();
Destroyed = true;
}
}
}
private static List<ActorDetail> ActorsInGame = new List<ActorDetail>();
public static void StoreActor(AiActor actor)
{
if (actor is AiAircraft)
ActorsInGame.Add(new ActorDetail(actor));
}
public static void ForceActorDestroyNotPosChangeAfter(int seconds)
{
ActorsInGame.ForEach(item =>
{
if (item.CheckActor().TotalSeconds > seconds)
item.Destroy();
});
ActorsInGame.RemoveAll(item => item.Destroyed);
}
public static void RemoveActor(AiActor actor)
{
if (ActorsInGame.Exists(item => item.Actor == actor))
{
ActorsInGame.RemoveAll(item => item.Actor == actor);
}
}
public static void MarkAsParachuted(AiActor actor)
{
if (ActorsInGame.Exists(item => item.Actor == actor))
ActorsInGame.Find(item => item.Actor == actor).IsParachuted = true;
}
public static bool IsParachuted(AiActor actor)
{
if (ActorsInGame.Exists(item => item.Actor == actor))
return ActorsInGame.Find(item => item.Actor == actor).IsParachuted;
return false;
}
public static List<AiActor> GetStoredActors()
{
List<AiActor> actors = new List<AiActor>();
ActorsInGame.ForEach(item => actors.Add(item.Actor));
return actors;
}
}
internal class SpawnPlace
{
public int NumberOfPlanes { get; set; }
public AiBirthPlace BirthPlace { get; set; }
public IGamePlay GamePlay { get; set; }
private bool _isAvalable;
private List<AiAircraft> PlanesInUse = new List<AiAircraft>();
public SpawnPlace(IGamePlay gamePlay, AiBirthPlace birthPlace, int maxNumber)
{
GamePlay = gamePlay;
BirthPlace = birthPlace;
NumberOfPlanes = maxNumber;
if (maxNumber > 0)
_isAvalable = true;
}
public void CheckPlaneOut(AiActor actor)
{
if (actor != null && (actor is AiAircraft))
{
if (PlanesInUse.Exists(item => item == actor)) return;
PlanesInUse.Add(actor as AiAircraft);
NumberOfPlanes--;
GamePlay.gpLogServer(null, "Airfield: {0}: {1} plane(s) avaiable, {2} in use.", new object[] { BirthPlace.Name(), NumberOfPlanes, PlanesInUse.Count });
if (NumberOfPlanes <= 0 && _isAvalable)
{
foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
{
if (bp.Name().Equals(BirthPlace.Name()))
bp.destroy();
}
_isAvalable = false;
}
}
}
public void CheckPlaneIn(AiActor actor)
{
if (actor != null && actor is AiAircraft)
if (IsActorDown(actor) && CheckIsHomeBase(actor, 800.0)) // Plane landed on correct Homebase if in 800m Radius from SpawnplaceLocation
{
PlanesInUse.Remove(actor as AiAircraft);
NumberOfPlanes++;
GamePlay.gpLogServer(null, "Airfield: {0}: {1} plane(s) avaiable", new object[] { BirthPlace.Name(), NumberOfPlanes });
if (!_isAvalable)
{
GamePlay.gpPostMissionLoad(CreateBirthPlace(BirthPlace));
_isAvalable = true;
}
}
else PlanesInUse.Remove(actor as AiAircraft); // Plane is lost
}
private bool CheckIsHomeBase(AiActor actor, double maxdistance)
{
Point3d actorPos = actor.Pos();
if (PlanesInUse.Exists(item => item == actor))
{
Point3d HomeBasePos = new Point3d(BirthPlace.Pos().x, BirthPlace.Pos().y, 0.0);
if (HomeBasePos.distance(ref actorPos) < maxdistance)
return true;
}
return false;
}
private bool IsActorDown(AiActor actor)
{
AiAircraft aircraft = actor as AiAircraft;
if (aircraft != null && (aircraft.getParameter(ParameterTypes.Z_AltitudeAGL, -1) <= 2.0
&& aircraft.getParameter(ParameterTypes.Z_VelocityTAS, -1) <= 1.0))
return true;
return false;
}
public int NumberOfPlanesInUse()
{
return PlanesInUse.Count;
}
internal ISectionFile CreateBirthPlace(AiBirthPlace birthPlace)
{
ISectionFile f = GamePlay.gpCreateSectionFile();
string sect;
string key;
string value;
sect = "BirthPlace";
key = birthPlace.Name();
int setOnPark = 0;
if (birthPlace.IsSetOnPark())
setOnPark = 1;
int isParachute = 0;
if (birthPlace.IsParachute())
isParachute = 1;
string country = ".";
if (birthPlace.Country() != null)
country = birthPlace.Country();
string hierachy = ".";
if (birthPlace.Hierarchy() != null)
hierachy = birthPlace.Hierarchy();
string regiment = ".";
if (birthPlace.Regiment() != null)
regiment = birthPlace.Regiment().name();
value = " " + birthPlace.Army().ToString(CultureInfo.InvariantCulture) + " " + birthPlace.Pos().x.ToString(CultureInfo.InvariantCulture) + " "
+ birthPlace.Pos().y.ToString(CultureInfo.InvariantCulture) + " " + birthPlace.Pos().z.ToString(CultureInfo.InvariantCulture) + " "
+ birthPlace.MaxPlanes().ToString(CultureInfo.InvariantCulture) + " " + setOnPark.ToString(CultureInfo.InvariantCulture) + " "
+ isParachute.ToString(CultureInfo.InvariantCulture) + " " + country + " " + hierachy + " " + regiment;
f.add(sect, key, value);
sect = "BirthPlace0";
string[] planeSet = birthPlace.GetAircraftTypes();
if (planeSet.Length > 0)
for (int j = 0; j < planeSet.Length; j++)
{
key = planeSet[j];
value = "";
f.add(sect, key, value);
}
return f;
}
}
internal static class SpawnPlaceManagement
{
static List<SpawnPlace> _spawnPlaces = new List<SpawnPlace>();
public static IGamePlay GamePlay { get; set; }
public static void Limitations(params KeyValuePair<string, int>[] keyValuePair)
{
foreach (KeyValuePair<string, int> kvp in keyValuePair)
{
foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
{
if(kvp.Key.Equals(bp.Name()))
_spawnPlaces.Add(new SpawnPlace(GamePlay, bp, kvp.Value));
}
}
}
private static AiBirthPlace GetBirthPlaceByName(string birthPlaceName)
{
foreach (SpawnPlace sp in _spawnPlaces)
{
if (sp.BirthPlace.Name().Equals(birthPlaceName))
return sp.BirthPlace;
}
return null;
}
private static AiBirthPlace GetNearestBirthplace(AiActor actor)
{
AiBirthPlace nearestBirthplace = null;
if (actor == null) return null;
Point3d pos = actor.Pos();
if (_spawnPlaces != null)
{
foreach (SpawnPlace airport in _spawnPlaces)
{
if (nearestBirthplace != null)
{
if (nearestBirthplace.Pos().distance(ref pos) > airport.BirthPlace.Pos().distance(ref pos))
nearestBirthplace = airport.BirthPlace;
}
else nearestBirthplace = airport.BirthPlace;
}
}
return nearestBirthplace;
}
public static int CountAvailablePlanes(int army)
{
int count = 0;
_spawnPlaces.ForEach(item =>
{
if (item.BirthPlace != null)
if (item.BirthPlace.Army() == army)
count += item.NumberOfPlanes;
});
return count;
}
public static int CountPlanesInUse(int army)
{
int count = 0;
_spawnPlaces.ForEach(item =>
{
if (item.BirthPlace != null)
if (item.BirthPlace.Army() == army)
count += item.NumberOfPlanesInUse();
});
return count;
}
public static void DebugPrint()
{
_spawnPlaces.ForEach(item => GamePlay.gpLogServer(null, "BirthPlaces: {0} In Store: {1} In Use: {2}", new object[] { item.BirthPlace.Name(), item.NumberOfPlanes, item.NumberOfPlanesInUse() }));
}
public static void CheckPlaneOut(AiActor actor)
{
if (actor == null) return;
AiBirthPlace birthPlace = GetNearestBirthplace(actor);
foreach (SpawnPlace spawnPlace in _spawnPlaces)
{
if (spawnPlace.BirthPlace == birthPlace)
spawnPlace.CheckPlaneOut(actor);
}
}
public static void CheckPlaneIn(AiActor actor)
{
if (actor == null) return;
AiBirthPlace birthPlace = GetNearestBirthplace(actor);
foreach (SpawnPlace spawnPlace in _spawnPlaces)
{
if (spawnPlace.BirthPlace == birthPlace)
spawnPlace.CheckPlaneIn(actor);
}
}
}
public override void OnBattleStarted()
{
base.OnBattleStarted();
MissionNumberListener = -1;
SpawnPlaceManagement.GamePlay = GamePlay;
SpawnPlaceManagement.Limitations(
new KeyValuePair<string, int>("Spits", 10), // Name of Birthplace, Number of Max Available planes
new KeyValuePair<string, int>("Bf109E", 10)
);
}
private bool IsDestroyable(AiActor actor)
{
AiCart cart = actor as AiCart;
if (cart != null)
{
//check if a player is present in actor
for (int i = 0; i < cart.Places(); i++)
if (cart.Player(i) != null)
return false;
}
return true;
}
private void Destroy(AiActor actor)
{
AiCart cart = actor as AiCart;
if(cart != null)
cart.Destroy();
ActorObservation.RemoveActor(actor);
}
public override void OnPlaceEnter(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceEnter(player, actor, placeIndex);
SpawnPlaceManagement.CheckPlaneOut(actor);
if (player.PlacePrimary() <= 0 && player.PlaceSecondary() == -1)
{
if (actor is AiCart)
ActorObservation.StoreActor(actor);
int availablePlanes = SpawnPlaceManagement.CountAvailablePlanes(player.Army());
if (availablePlanes == 5) // Message if only 5 planes left, change to your needs
{
if (player.Army() == 1)
GamePlay.gpHUDLogCenter(null, "Attention RED only {0} planes left!", new object[] { availablePlanes } );
if (player.Army() == 2)
GamePlay.gpHUDLogCenter(null, "Attention BLUE only {0} planes left!", new object[] { availablePlanes });
}
}
}
public override void OnPersonMoved(AiPerson person, AiActor fromCart, int fromPlaceIndex)
{
base.OnPersonMoved(person, fromCart, fromPlaceIndex);
if (person.Player() != null)
if (((person.Cart() == null) && (fromCart is AiAircraft)) && (fromCart as AiAircraft).IsAirborne())
ActorObservation.MarkAsParachuted(fromCart);
}
public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave(player, actor, placeIndex);
if(IsDestroyable(actor) && !ActorObservation.IsParachuted(actor))
Destroy(actor);
}
public override void OnActorDestroyed(int missionNumber, string shortName, AiActor actor)
{
base.OnActorDestroyed(missionNumber, shortName, actor);
SpawnPlaceManagement.CheckPlaneIn(actor);
if (actor.Army() == 1 && SpawnPlaceManagement.CountAvailablePlanes(1) == 0 && SpawnPlaceManagement.CountPlanesInUse(1) == 0 && !battleEnded)
{
battleEnded = true;
GamePlay.gpHUDLogCenter(null, "Blue Wins!");
}
else if (actor.Army() == 2 && SpawnPlaceManagement.CountAvailablePlanes(2) == 0 && SpawnPlaceManagement.CountPlanesInUse(2) == 0 && !battleEnded)
{
battleEnded = true;
GamePlay.gpHUDLogCenter(null, "Red Wins");
}
}
public override void OnTickGame()
{
base.OnTickGame();
if (Time.tickCounter() % 300 == 0) // check every 10 sec
{
ActorObservation.ForceActorDestroyNotPosChangeAfter(60); // if actor not changed position destroy it after 1 min (must be started before)
}
}
}
|