Fulqrum Publishing Home   |   Register   |   Today Posts   |   Members   |   UserCP   |   Calendar   |   Search   |   FAQ

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

 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
  #33  
Old 06-28-2012, 01:46 PM
FG28_Kodiak FG28_Kodiak is offline
Approved Member
 
Join Date: Dec 2009
Location: Swabia->Bavaria->Germany
Posts: 884
Default SpawnPlace Managment

So new Version. Now it's possible to limit every PlaneType seperately, it's now possible to transfer one Airplane from one Birthplace to an other (the other must be specify in the Birthcontrol). It's also possible to resupply the places.

Version to test:
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 AiBirthPlace BirthPlace { get; set; }
        public IGamePlay GamePlay { get; set; }
        private bool _isAvalable;
        private bool _transferAllowed;
        private Dictionary<string, int> Store = new Dictionary<string, int>();
        private List<AiAircraft> PlanesInUse = new List<AiAircraft>();

        public SpawnPlace(IGamePlay gamePlay, AiBirthPlace birthPlace, bool transferAllowed, Dictionary<string, int> stores)
        {
            GamePlay = gamePlay;
            BirthPlace = birthPlace;
            _transferAllowed = transferAllowed;
            if (stores != null)
            {
                Store = stores;

                if (stores.Count > 0)
                    _isAvalable = true;
            }
        }

        public int CountAllAvailablePlanes()
        {
            int count = 0;

            foreach (KeyValuePair<string, int> kvp in Store)
                count += kvp.Value;
         
            return count;
        }

        public int NumberOfPlanesInUse()
        {
            return PlanesInUse.Count;
        }

        public void CheckPlaneOut(AiActor actor)
        {
            AiAircraft aircraft = actor as AiAircraft;

            if (aircraft != null)
            {
                if (PlanesInUse.Exists(item => item == aircraft)) return;

                PlanesInUse.Add(aircraft);

                int numberOfPlanes = 0;

                string storedPlaneName = aircraft.InternalTypeName().Replace("bob:", "");

                if (Store.TryGetValue(storedPlaneName, out numberOfPlanes))
                {
                    if (numberOfPlanes > 0)
                    {
                        numberOfPlanes--;
                        Store[storedPlaneName] = numberOfPlanes;
                        ShowStorage();
                    }
                }

                if (numberOfPlanes <= 0)
                {
                    foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
                    {
                        if (bp.Name().Equals(BirthPlace.Name()))
                        {
                            bp.destroy();
                        }
                    }

                    ISectionFile newBirthPlace = RecreateBirthPlace(BirthPlace, GetAircrafts());

                    if (newBirthPlace != null)
                    {
                        GamePlay.gpPostMissionLoad(newBirthPlace);
                    }
                }
            }
        }


        public void CheckPlaneIn(AiActor actor)
        {
            AiAircraft aircraft = actor as AiAircraft;
            bool recreateBirthplace = false;
            int numberOfPlanes;

            if (aircraft != null)
            {
                if (IsActorDown(actor) && CheckIsHomeBase(actor, 800.0)) // Plane landed on correct Homebase if in 800m Radius from SpawnplaceLocation
                {
                    PlanesInUse.Remove(actor as AiAircraft);

                    string storedPlaneName = aircraft.InternalTypeName().Replace("bob:", "");
                    
                    if (Store.TryGetValue(storedPlaneName, out numberOfPlanes))
                    {
                        if (numberOfPlanes <= 0)
                            recreateBirthplace = true;

                        numberOfPlanes++;
                        Store[storedPlaneName] = numberOfPlanes;
                        ShowStorage();

                    }
                }
                else if (IsActorDown(actor) && CheckBase(actor, 800.0) && _transferAllowed) //Plane is landed on other existing Base
                {
                    BirthControl.RemoveActor(actor); // Remove the actor from other Birthplace

                    GamePlay.gpLogServer(null, "Gelandet auf fremden Platz", null);

                    string storedPlaneName = aircraft.InternalTypeName().Replace("bob:", "");

                    if (Store.TryGetValue(storedPlaneName, out numberOfPlanes))
                    {
                        if (numberOfPlanes <= 0)
                            recreateBirthplace = true;

                        numberOfPlanes++;
                        Store[storedPlaneName] = numberOfPlanes;
                        ShowStorage();

                    }
                    else
                    {
                        Store.Add(storedPlaneName, 1);
                        recreateBirthplace = true;
                        ShowStorage();
                    }
                }
                else PlanesInUse.Remove(actor as AiAircraft); // Plane is lost

                if (recreateBirthplace)
                {
                    foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
                        if (bp.Name().Equals(BirthPlace.Name()))
                            bp.destroy();

                    ISectionFile newBirthPlace = RecreateBirthPlace(BirthPlace, GetAircrafts());

                    if (newBirthPlace != null)
                        GamePlay.gpPostMissionLoad(newBirthPlace);
                }
            }
        }

        public void RemoveActor(AiActor actor)
        {
            AiAircraft aircraft = actor as AiAircraft;

            if (aircraft != null)
                if (PlanesInUse.Exists(item => item == aircraft))
                    PlanesInUse.Remove(aircraft);
        }



        public void ResupplyAll(int nrOfAdditionalPlanes, int nrOfMaxPlanes)
        {
            List<string> keyList = new List<string>();
            bool recreateBirthplace = false;

            keyList.AddRange(Store.Keys);

            foreach (string st in keyList)
            {
                int value = 0;

                if (Store.TryGetValue(st, out value))
                {
                    if (value <= 0) 
                        recreateBirthplace = true;
                    value += nrOfAdditionalPlanes;

                    if (value > nrOfMaxPlanes)
                        value = nrOfMaxPlanes;

                    Store[st] = value;
                }
            }

            if(recreateBirthplace)
            {
                foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
                    if (bp.Name().Equals(BirthPlace.Name()))
                        bp.destroy();

                ISectionFile newBirthPlace = RecreateBirthPlace(BirthPlace, GetAircrafts());

                if (newBirthPlace != null)
                    GamePlay.gpPostMissionLoad(newBirthPlace);
            }

            ShowStorage();

        }


        public void Resupply(string planeName, int nrOfAdditionalPlanes, int nrOfMaxPlanes)
        {
            int value = 0;
            bool recreateBirthplace = false;

            if (Store.TryGetValue(planeName, out value))
            {
                if (value <= 0)
                    recreateBirthplace = true;

                value += nrOfAdditionalPlanes;

                if(value > nrOfMaxPlanes)
                    value = nrOfMaxPlanes;

                Store[planeName] = value;
            }
            else
            {
                recreateBirthplace = true;
                Store.Add(planeName, nrOfAdditionalPlanes);
            }

            if (recreateBirthplace)
            {
                foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
                    if (bp.Name().Equals(BirthPlace.Name()))
                        bp.destroy();

                ISectionFile newBirthPlace = RecreateBirthPlace(BirthPlace, GetAircrafts());

                if (newBirthPlace != null)
                    GamePlay.gpPostMissionLoad(newBirthPlace);
            }

            ShowStorage();
        }


        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 CheckBase(AiActor actor, double maxdistance)
        {
            Point3d actorPos = actor.Pos();

            Point3d BasePos = new Point3d(BirthPlace.Pos().x, BirthPlace.Pos().y, 0.0);
            if (BasePos.distance(ref actorPos) < maxdistance && actor.Army() == BirthPlace.Army())
                return true;

            return false;
        }

        private string ParsePlaneType(string planeName)
        {

            if (planeName.StartsWith("bob:Aircraft."))
                return planeName.Replace("bob:Aircraft.", "");

            if (planeName.StartsWith("Aircraft."))
                return planeName.Replace("Aircraft.", "");

            return planeName;
        }

        private string[] GetAircrafts()
        {

            List<string> aircrafts = new List<string>();

            foreach (KeyValuePair<string, int> kvp in Store)
            {
                if (kvp.Value > 0)
                {
                    if (!aircrafts.Exists(item => item == kvp.Key))
                    {
                        aircrafts.Add(kvp.Key);
                    }
                }
            }
            return aircrafts.ToArray();
        }

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

        private ISectionFile RecreateBirthPlace(AiBirthPlace birthPlace, string[] aircraftTypes)
        {
            if (aircraftTypes == null || aircraftTypes.Length == 0)
                return null;

            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 = aircraftTypes;
            if (planeSet.Length > 0)
                for (int j = 0; j < planeSet.Length; j++)
                {
                    key = planeSet[j];
                    value = "";
                    f.add(sect, key, value);
                }

            return f;
        }

        private void ShowStorage()
        {
            List<Player> players = new List<Player>();

            if (GamePlay.gpPlayer() != null)
                players.Add(GamePlay.gpPlayer());
            if (GamePlay.gpRemotePlayers() != null)
                players.AddRange(GamePlay.gpRemotePlayers());

            players.RemoveAll(item => item.Army() != BirthPlace.Army());

            if (players.Count > 0)
            {
                GamePlay.gpLogServer(players.ToArray(), "Available on Airfield {0}:", new object[] { BirthPlace.Name() });
                foreach (KeyValuePair<string, int> kvp in Store)
                {
                    GamePlay.gpLogServer(players.ToArray(), "{0} {1}", new object[] { kvp.Value, ParsePlaneType(kvp.Key) });
                }
            }
        }
    } 


    internal static class BirthControl
    {
        private static List<SpawnPlace> _spawnPlaces = new List<SpawnPlace>();
        public static IGamePlay GamePlay { get; set; }


        public static void Limitations(bool transferAllowed, params KeyValuePair<string, Dictionary<string, int>>[] keyValuePair)
        {
            foreach (KeyValuePair<string, Dictionary<string, int>> kvp in keyValuePair)
            {
                foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
                {
                    if (kvp.Key.Equals(bp.Name()))
                        _spawnPlaces.Add(new SpawnPlace(GamePlay, bp, transferAllowed, kvp.Value));
                }
            }
        }


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

        internal static void RemoveActor(AiActor actor)
        {
            foreach (SpawnPlace sp in _spawnPlaces)
                sp.RemoveActor(actor);
        }

        public static int CountAvailablePlanes(int army)
        {
            int count = 0;

            _spawnPlaces.ForEach(item =>
            {
                if (item.BirthPlace != null)
                    if (item.BirthPlace.Army() == army)
                        count += item.CountAllAvailablePlanes();
            });

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


        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 void Resupply(string birthPlace, string planeType, int nrOfAdditionalPlanes, int nrOfMaxPlanes)
        {
            _spawnPlaces.ForEach(item =>
                                     {
                                         if (item.BirthPlace.Name().Equals(birthPlace))
                                             item.Resupply(planeType, nrOfAdditionalPlanes, nrOfMaxPlanes);
                                     });
        }



        public static void Resupply(string birthPlace, int nrOfAdditionalPlanes, int nrOfMaxPlanes)
        {
            _spawnPlaces.ForEach(item =>
            {
                if (item.BirthPlace.Name().Equals(birthPlace))
                    item.ResupplyAll(nrOfAdditionalPlanes, nrOfMaxPlanes);
            });
        }



        public static void ResupplyAll(int nrOfAdditionalPlanes, int nrOfMaxPlanes)
        {
            _spawnPlaces.ForEach(item => item.ResupplyAll(nrOfAdditionalPlanes, nrOfMaxPlanes));
        }

    }


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


    #region Overrides
    public override void OnBattleStarted()
    {
        base.OnBattleStarted();

        MissionNumberListener = -1;

        BirthControl.GamePlay = GamePlay;

        BirthControl.Limitations(true, new KeyValuePair<string, Dictionary<string, int>>("GermanPlace", new Dictionary<string, int>
                                                                                                      {
                                                                                                          {"Aircraft.Bf-109E-1", 10},
                                                                                                          {"Aircraft.Bf-109E-3", 5},
                                                                                                          {"Aircraft.Bf-109E-4", 5}
                                                                                                      }),
                                 new KeyValuePair<string, Dictionary<string, int>>("GermanPlace2", new Dictionary<string, int>
                                                                                                      {
                                                                                                          {"Aircraft.Bf-109E-1", 10},
                                                                                                          {"Aircraft.Bf-109E-3", 5}
                                                                                                      }),
                                 new KeyValuePair<string, Dictionary<string, int>>("BritishPlace", new Dictionary<string, int>
                                                                                                      {
                                                                                                          {"Aircraft.SpitfireMkIa", 10},
                                                                                                          {"Aircraft.SpitfireMkIIa", 5},
                                                                                                          {"Aircraft.HurricaneMkI", 20}
                                                                                                      }));
    }


    
    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 OnPlaceEnter(Player player, AiActor actor, int placeIndex)
    {
        base.OnPlaceEnter(player, actor, placeIndex);

        BirthControl.CheckPlaneOut(actor);

        if (player.PlacePrimary() <= 0 && player.PlaceSecondary() == -1)
        {
            if (actor is AiCart)
                ActorObservation.StoreActor(actor);
        }
    }


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

        BirthControl.CheckPlaneIn(actor);

        if (actor.Army() == 1 && BirthControl.CountAvailablePlanes(1) == 0 && BirthControl.CountPlanesInUse(1) == 0 && !battleEnded)
        {
            battleEnded = true;
            GamePlay.gpHUDLogCenter(null, "Blue Wins!");
        }
        else if (actor.Army() == 2 && BirthControl.CountAvailablePlanes(2) == 0 && BirthControl.CountPlanesInUse(2) == 0 && !battleEnded)
        {
            battleEnded = true;
            GamePlay.gpHUDLogCenter(null, "Red Wins");
        }
    }


    public override void OnTickGame()
    {
        base.OnTickGame();

        
        if (Time.tickCounter() % 216000 == 215999) // Two hours
        {
            BirthControl.ResupplyAll(4, 10); // All SpawnPlaces get resupply
            //BirthControl.Resupply("GermanPlace", 4, 10); // Resupply only the GermanPlace Spawnplace
            //BirthControl.Resupply("GermanPlace", "Aircraft.Bf-109E-4", 4, 10); // Resupply only the AircraftType Bf109E-4 on GermanPlace
        }

        if (Time.tickCounter() % 300 == 299) // check every 10 sec
        {
            ActorObservation.ForceActorDestroyNotPosChangeAfter(60); // if actor not changed position destroy it after 1 min (must be started before)
        }
    }
    #endregion
}
Simple Sample Mission in attachment.
Attached Files
File Type: zip BirthplacePlaneLimits.zip (4.9 KB, 5 views)
Reply With Quote
 


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

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

Forum Jump


All times are GMT. The time now is 11:43 AM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Copyright © 2007 Fulqrum Publishing. All rights reserved.