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); }
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; }
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); } }
/** * 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); } } } }
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; }
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()); } } }
/** * 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; } } }
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)); } }
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>(); }
/** * 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)); } }
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); }