private IEnumerator RedirectAfterShipmentRefusal(HashSet <FreightAreaIn> toIgnore)
    {
        FreightAreaIn bestWarehouse = null;

        for (int i = 0; i < 3 && bestWarehouse == null; i++) //TODO possibilité d'un peu de random sur ce 3, arbitraire
        {
            if (i > 0)
            {
                yield return(new WaitForSeconds(Random.Range(0.5f, 3.0f - i)));
            }
            Cell <FreightAreaIn> coroutineRslt = new Cell <FreightAreaIn>();
            RoadData             occupiedRoad  = GetComponent <RoadRouteManager>().occupiedRoad;

            yield return(StartCoroutine(occupiedRoad.FindNearestFreeWarehouseFor(shipment, coroutineRslt, toIgnore)));

            bestWarehouse = coroutineRslt.value;
        }

        RoadRouteManager routeManager = GetComponent <RoadRouteManager>();

        if (bestWarehouse != null)
        {
            routeManager.MoveTo(bestWarehouse.road);
            destination = bestWarehouse.GetComponentInParent <BuildingStock>();
        }
        else
        {
            destination = origin;
            routeManager.MoveTo(destination.freightAreaData.freightAreaIn.road);
        }

        yield return(null);
    }
Example #2
0
    private IEnumerator SortAvailableKeepAsideOrderManagersByDistance(Cell <PriorityQueue <float, KeepAsideOrderManager> > rslt)
    {
        StockManager stockManager = GameManager.instance.cityBuilderData.stockManager;

        PriorityQueue <float, KeepAsideOrderManager> rsltQueue           = new PriorityQueue <float, KeepAsideOrderManager>();
        IEnumerator <KeepAsideOrderManager>          keepAsideEnumerator = stockManager.AllKeepAsideOrderManagers();

        while (keepAsideEnumerator.MoveNext())
        {
            KeepAsideOrderManager keepAsideManager = keepAsideEnumerator.Current;

            if (keepAsideManager != null)//On vérifie s'il n'a pas été détruit
            {
                float distance = Vector2.Distance(transform.position, keepAsideManager.transform.position);

                if (distance <= keepAsideManager.availabilityRange)//Pour éviter les calculs inutiles ; si ce n'est pas le cas, il est de toute façon trop loin
                {
                    FreightAreaIn  inArea  = keepAsideManager.freightAreaData.freightAreaIn;
                    FreightAreaOut outHome = freightAreaData.freightAreaOut;

                    float roadDistance = RoadsPathfinding.RealDistanceBetween(inArea.road, outHome.road);

                    if (roadDistance > 0.0f && roadDistance <= keepAsideManager.availabilityRange)
                    {
                        rsltQueue.Push(roadDistance, keepAsideManager);
                    }
                }
            }

            yield return(null);
        }

        rslt.value = rsltQueue;
    }
Example #3
0
    private IEnumerator SearchHomeCoroutine()
    {
        GameObject _goalGameObject = Utils.GetNearestObjectWithPath(GetComponent <RoadRouteManager>().occupiedRoad, "Home", _visitedHomes);
        Home       _goal           = _goalGameObject == null ? null : _goalGameObject.GetComponent <Home>();

        if (_goal != null)
        {
            _visitedHomes.Add(_goal.gameObject); //Cette maison existe et est testée.//TODO Ajoute un peu trop facilement à visitedHomes dans le cas où une maison évolue. (cfr bug faux boss de fin de la veille mia!) plus défensif!!!

            if (_goal.HaveFreeRooms())           //si elle a de la place
            {
                //On y va
                FreightAreaIn goalFA = _goal.GetComponent <FreightAreaData>().freightAreaIn;
                GetComponent <RoadRouteManager>().MoveTo(goalFA.GetComponent <RoadData>());
                _homeSearchTries++;

                yield return(new WaitUntil(() => _goal == null || GetComponent <RoadRouteManager>().occupiedRoad == goalFA.road));

                if (_goal != null && _goal.MoveIn())
                {
                    goalFA.road.roadLock.UnlockFor(GetComponent <MoveManager>().orientation, gameObject);
                    GameObject.Destroy(gameObject);
                    yield break;
                }
            }
            //!HaveFreeRooms || !MoveIn
            _currentRoutine = StartCoroutine(SearchOtherHome());
        }
        else
        {
            _homeSearchTries++;
            _currentRoutine = StartCoroutine(SearchOtherHome());
        }
    }
    /**
     * Déclenche (via une coroutine) le mouvement du transporteur vers la maison la
     * plus proche (sur le réseau routier), où il sera détruit (utile pour se
     * débarrasser des transporteurs dont le bâtiment principal est détruit).
     * Le stock sera alors perdu. Si aucune maison n'est disponible, le
     * transporteur ne bouge pas, et la coroutine va continuer d'attendre une
     * maison vers laquelle se rendre.
     **/
    private IEnumerator GoHome()
    {
        RoadRouteManager roadRouteManager = GetComponent <RoadRouteManager>();

        while (true)
        {
            //TODO utiliser un findNearestObjectWithPath (Utils) pour être plus générique.
            GameObject[] homesArray = GameObject.FindGameObjectsWithTag("Home");

            float         minDistance   = 0.0f;
            FreightAreaIn nearestHomeIn = null;
            foreach (GameObject home in homesArray)
            {
                FreightAreaIn homeIn = home.GetComponent <BuildingStock>().freightAreaData.freightAreaIn;

                float distance = RoadsPathfinding.RealDistanceBetween(homeIn.road, roadRouteManager.occupiedRoad);
                if (distance > 0.0f && (nearestHomeIn == null || minDistance > distance))
                {
                    minDistance   = distance;
                    nearestHomeIn = homeIn;
                }
                yield return(null);
            }

            if (nearestHomeIn != null)//Sinon, c'est qu'il n'y a AUCUNE maison satisfaisante, et la boucle principale se charge de relancer la recherche
            {
                destination = nearestHomeIn.GetComponentInParent <BuildingStock>();
                roadRouteManager.MoveTo(destination.freightAreaData.freightAreaIn.road, Random.Range(0.5f, 3.0f), null);
                yield break;
            }

            yield return(null);
        }
    }
Example #5
0
    /**
     * Coroutine de commande des ressources auprès du système de stockage.
     * Cette coroutine se charge en continu de commander auprès des entrepôts à
     * proximité les ressources nécessaires pour remplir le stock alloué au buffer
     * de consommation.
     **/
    private IEnumerator ResourceOrdererCoroutine()
    {
        FreightAreaIn freightIn = _currentStock.freightAreaData.freightAreaIn;

        while (requirements.Length > 0)
        {
            Cell <PriorityQueue <float, OrderManager> > rslt = new Cell <PriorityQueue <float, OrderManager> >();
            yield return(StartCoroutine(freightIn.road.SortOrderManagersByDistance(rslt)));

            PriorityQueue <float, OrderManager> sortedOrderManagers = rslt.value;

            foreach (ResourceShipment requirement in requirements)
            {
                foreach (OrderManager orderManager in sortedOrderManagers)
                {
                    string resourceName = requirement.resourceName;
                    if (_resourcesToOrder[resourceName] == 0)
                    {
                        break;
                    }

                    int orderedAmount = orderManager.Order(resourceName, _resourcesToOrder[resourceName], _currentStock);
                    _resourcesToOrder[resourceName] -= orderedAmount;

                    yield return(null);
                }
            }
        }
    }
Example #6
0
    public void ConnectFreightTo(Agora agora)
    {
        FreightAreaData      agoraFreight          = agora.GetComponent <FreightAreaData>();
        FreightAreaIn        agoraAreaIn           = agoraFreight.freightAreaIn;
        FreightAreaOut       agoraAreaOut          = agoraFreight.freightAreaOut;
        HashSet <Collider2D> agoraTreatedColliders = agoraFreight.treatedColliders;

        FreightAreaData freightData = GetComponent <FreightAreaData>();

        freightData.freightAreaIn    = agoraAreaIn;
        freightData.freightAreaOut   = agoraAreaOut;
        freightData.treatedColliders = agoraTreatedColliders;
    }
Example #7
0
    public IEnumerator goOnTour(List <GameObject> toVisit)
    {
        if (prefecture != null)
        {
            List <GameObject> toReVisit = new List <GameObject>();
            toVisit.Remove(prefecture);
            _tour = TSP.GetItinary(prefecture, toVisit);
            GameObject _currentDestination;
            while (!_tour.IsEmpty())
            {
                _continueTour        = false;
                _tryAgainToVisitHome = 50;

                _currentDestination = _tour.Pop();
                goalFA = _currentDestination.GetComponentInChildren <FreightAreaIn>();
                if (goalFA != null && RoadsPathfinding.RealDistanceBetween(GetComponent <RoadRouteManager>().occupiedRoad, goalFA.road) != -1)
                //Il existe encore une route vers ce batiment
                {
                    GetComponent <RoadRouteManager>().MoveTo(goalFA.road);
                    yield return(new WaitUntil(() => _continueTour || goalFA == null || gameObject.GetComponent <RoadRouteManager>().occupiedRoad == goalFA.road));

                    if (goalFA != null && _continueTour)//On a pas pu atteindre la maison et on a choisi de la skipper
                    {
                        toReVisit.Add(goalFA.gameObject);
                    }
                    if (goalFA != null && !_continueTour)
                    {
                        Building building = _currentDestination.GetComponent <Building>();
                        if (building != null)
                        {
                            building.RestoreHealth();
                        }
                        GetComponent <SpriteRenderer>().enabled = false;//TODO il est toujours sur la FA et donc le lock est toujours activé !
                        yield return(new WaitForSeconds(Random.Range(2.0f, 5.0f)));

                        GetComponent <SpriteRenderer>().enabled = true;
                    }
                }
            }
            if (toReVisit.Count != 0 && _trytoRevisitCount-- != 0)
            {
                StartCoroutine(goOnTour(toReVisit));
            }
            else
            {
                StartCoroutine(GoBack());
            }
        }
    }
Example #8
0
    /**
     * Coroutine à lancer pour effectuer une recherche parmi les entrepôts disponibles
     * quel est le plus proche remplissant une condition donnée. Pour les calculs
     * de distance, ce sont ici les freight area d'ENTREE (in) qui sont utilisées, ATTENTION!
     **/
    public static IEnumerator FindNearestWarehouseSatisfyingCondition(RoadData startPoint, Func <Warehouse, bool> acceptanceFunction, Cell <Warehouse> rslt, HashSet <FreightAreaIn> toIgnore)
    {
        PriorityQueue <float, Warehouse> sortedWarehouses = new PriorityQueue <float, Warehouse>();
        IEnumerator <Warehouse>          allWarehouses    = GameManager.instance.cityBuilderData.stockManager.AllWarehouses();

        while (allWarehouses.MoveNext())
        {
            Warehouse warehouse = allWarehouses.Current;

            if (warehouse != null)// Car il peut avoir été détruit depuis le début de la coroutine !
            {
                FreightAreaIn warehouseIn = warehouse.orderManager.freightAreaData.freightAreaIn;
                if (!toIgnore.Contains(warehouseIn) && acceptanceFunction(warehouse))
                {
                    float distanceToWarehouse = Vector2.Distance(warehouseIn.transform.position, startPoint.transform.position);
                    sortedWarehouses.Push(distanceToWarehouse, warehouse);
                }
            }
        }

        if (!sortedWarehouses.IsEmpty())
        {
            Warehouse bestWarehouse = sortedWarehouses.Pop();
            float     pathDistance  = RoadsPathfinding.RealDistanceBetween(startPoint, bestWarehouse.orderManager.freightAreaData.freightAreaIn.road);

            yield return(null);

            while (!sortedWarehouses.IsEmpty() && (pathDistance > sortedWarehouses.LowestKey() || pathDistance < 0.0f))
            {
                Warehouse nearestAsTheCrowFlies = sortedWarehouses.Pop();
                float     newPathDistance       = RoadsPathfinding.RealDistanceBetween(startPoint, nearestAsTheCrowFlies.orderManager.freightAreaData.freightAreaIn.road);
                if (newPathDistance >= 0.0f && (newPathDistance < pathDistance || pathDistance < 0.0f))
                {
                    pathDistance  = newPathDistance;
                    bestWarehouse = nearestAsTheCrowFlies;
                }
                yield return(null);
            }

            if (pathDistance >= 0.0f)
            {
                rslt.value = bestWarehouse;
            }
        }
    }
Example #9
0
    private IEnumerator ManageWarehouseDispatching()
    {
        FreightAreaData freightData    = _currentStock.freightAreaData;
        RoadLock        freightOutLock = freightData.freightAreaOut.road.roadLock;

        while (true)
        {
            if (!orderManager.SendOrderIfPossible() && _warehouseOrders.Count <= WAREHOUSE_ORDERS_LIMIT) //L'appel à la méthode envoie une commande si elle retourne true, d'où l'aspect un peu étrange de la condition
            {
                foreach (ResourceShipment productionShipment in production)                              //TODO: si on produit plusieurs ressources et qu'on veut définir l'ordre dans lequel elles partent, c'est ici
                {
                    int resourceStock = _currentStock.StockFor(productionShipment.resourceName);

                    for (int i = 0; i < freightData.availableCarriers && resourceStock > 0; i++)
                    {
                        int amountToShip            = Math.Min(freightData.carrierPrefab.capacity, resourceStock);
                        ResourceShipment     toShip = new ResourceShipment(productionShipment.resourceName, amountToShip);
                        Cell <FreightAreaIn> nestedCoroutineReturnHelper = new Cell <FreightAreaIn>();

                        yield return(StartCoroutine(freightData.freightAreaOut.road.FindNearestFreeWarehouseFor(toShip, nestedCoroutineReturnHelper, new HashSet <FreightAreaIn>())));

                        FreightAreaIn nearestFreeWarehouse = nestedCoroutineReturnHelper.value;

                        if (nearestFreeWarehouse != null)
                        {
                            while (!freightOutLock.IsFree(Orientation.SOUTH))//TODO orientation
                            {
                                yield return(new WaitForSeconds(0.2f));
                            }

                            _warehouseOrders.Enqueue(new ResourceOrder(new ResourceShipment(productionShipment.resourceName, amountToShip), nearestFreeWarehouse.GetComponentInParent <BuildingStock>()));
                        }

                        resourceStock = _currentStock.StockFor(productionShipment.resourceName);
                    }
                }
            }

            yield return(new WaitForSeconds(0.5f));
        }
    }
Example #10
0
    protected void Awake()
    {
        /*
         * Les conditions sur l'assignation des freightArea permet de les setter à des
         * objets définis dans un autre Awake s'exécutant avant celui-ci (ce qui peut
         * être très utile pour les marchands d'agora, afin d'éviter les problèmes si,
         * comme dans le test, ils sont déjà présents dans le préfab instancié).
         */
        if (freightAreaIn == null)
        {
            freightAreaIn = GetComponentInChildren <FreightAreaIn>();
        }

        if (freightAreaOut == null)
        {
            freightAreaOut = GetComponentInChildren <FreightAreaOut>();
        }

        _availableCarriers = carriersNber;
        parentStock        = GetComponent <BuildingStock>();
    }
Example #11
0
    /**
     * Coroutine se chargeant d'envoyer tout ce qui a été produit par le bâtiment
     * et se trouve contenu dans son stock à l'entrepôt le plus proche capable
     * de l'accueillir ou à un bâtiment l'ayant commandé. Tout cela se voit bien
     * entendu diviser entre les transporteurs
     * disponibles pour le bâtiment.
     **/
    private IEnumerator ManageProductionStorage()
    {
        FreightAreaData freightData = orderManager.freightAreaData;

        while (true)
        {
            if (!orderManager.SendOrderIfPossible() && !orderManager.OrdersToTreat() && _warehouseOrders.Count > 0)//L'appel à la méthode envoie une commande si elle retourne true, d'où l'aspect un peu étrange de la condition
            {
                ResourceOrder    warehouseOrder = _warehouseOrders.Dequeue();
                ResourceShipment orderShipment  = warehouseOrder.shipment;

                FreightAreaIn destinationIn = warehouseOrder.deliveryPlace.freightAreaData.freightAreaIn;
                if (orderManager.stock.StockFor(orderShipment.resourceName) >= orderShipment.amount && RoadsPathfinding.RouteStar(destinationIn.road, freightData.freightAreaOut.road, 10, Orientation.SOUTH) != null)//TODO orientation
                {
                    _currentStock.RemoveFromStock(orderShipment.resourceName, orderShipment.amount);
                    freightData.SendCarrier(warehouseOrder.deliveryPlace, Orientation.SOUTH, orderShipment);//TODO orientation
                }
            }

            yield return(new WaitForSeconds(0.5f));
        }
    }
Example #12
0
    public bool SendOrderIfPossible()
    {
        FreightAreaOut freightOut = freightAreaData.freightAreaOut;

        if (freightAreaData.availableCarriers > 0 && OrdersToTreat() && freightOut.road.roadLock.IsFree(Orientation.SOUTH))//TODO orientation (opposée à celle du bâtiment)
        {
            ResourceOrder toTreat = NextOrder();

            FreightAreaIn destinationIn = toTreat.deliveryPlace.freightAreaData.freightAreaIn;
            if (RoadsPathfinding.RouteStar(destinationIn.road, freightOut.road, 10, Orientation.SOUTH) != null)//TODO orientation
            {
                MarkAsTreated(toTreat);
                freightAreaData.SendCarrier(toTreat.deliveryPlace, Orientation.SOUTH, toTreat.shipment);//TODO orientation (opposée à celle du bâtiment)

                return(true);
            }
            else //Si la destination n'est pas raccordée au réseau routier, on annule sa commande et on l'en notifie
            {
                toTreat.deliveryPlace.freightAreaData.parentStock.GetComponent <ResourceConsumer>().CancelResourceOrder(toTreat.shipment);
            }
        }

        return(false);
    }
 protected void Start()
 {
     freightAreaIn = freightAreaData.freightAreaIn;
     freightAreaIn.inEvent.AddListener(OnFreightAreaEntered);
 }