/// <summary> /// Logs the transfer offers. /// </summary> /// <param name="direction">The direction.</param> /// <param name="offers">The offers.</param> /// <param name="count">The count.</param> /// <param name="amount">The amount.</param> /// <param name="buildings">The buildings.</param> /// <param name="material">The material.</param> private static void DebugListLog( string direction, TransferManager.TransferOffer[] offers, ushort[] count, int[] amount, Building[] buildings, TransferManager.TransferReason material) { for (int priority = 0; priority < 8; priority++) { int index = ((int)material * 8) + priority; for (int i = 0; i < count[index]; i++) { Log.InfoList info = new Log.InfoList(); TransferManager.TransferOffer offer = offers[(index * 256) + i]; info.Add("Active", offer.Active); info.Add("Amount", offer.Amount); info.Add("Priority", offer.Priority); info.Add("Vehicle", offer.Vehicle, VehicleHelper.GetVehicleName(offer.Vehicle)); info.Add("Citizen", offer.Citizen, CitizenHelper.GetCitizenName(offer.Citizen)); info.Add("TransportLine", offer.TransportLine, TransportLineHelper.GetLineName(offer.TransportLine)); info.Add("Building", offer.Building, BuildingHelper.GetBuildingName(offer.Building), BuildingHelper.GetDistrictName(offer.Building)); if (buildings != null && offer.Building > 0 && buildings[offer.Building].Info != null && (buildings[offer.Building].m_flags & Building.Flags.Created) == Building.Flags.Created) { info.Add("Garbage", buildings[offer.Building].m_garbageBuffer); info.Add("Dead", buildings[offer.Building].m_deathProblemTimer); } Log.DevDebug(typeof(TransferManagerHelper), "DebugListLog", direction, material, info); } } }
/// <summary> /// Helper method for adding the given offer to the offers array. /// </summary> /// <param name="material"></param> /// <param name="offer"></param> /// <param name="amounts"></param> /// <param name="count"></param> /// <param name="offers"></param> private static void AddOffer(TransferManager.TransferReason material, TransferManager.TransferOffer offer, int[] amount, ushort[] count, TransferManager.TransferOffer[] offers) { for (int priority = offer.Priority; priority >= 0; --priority) { int index1 = (int)material * 8 + priority; int num = count[index1]; for (int index2 = 0; index2 < num; index2++) { int index3 = index1 * 256 + index2; if (offers[index3].m_object == offer.m_object) { // Found an existing offer. return; } } // If we reached here, we need to add a new offer. if (num < 256) { offers[index1 * 256 + num] = offer; count[index1] = (ushort)(num + 1); amount[(int)material] += offer.Amount; return; } } }
public override void StartTransfer(ushort vehicleID, ref Vehicle data, TransferManager.TransferReason material, TransferManager.TransferOffer offer) { if ((data.m_flags & Vehicle.Flags.TransferToTarget) != 0) { base.StartTransfer(vehicleID, ref data, material, offer); return; } Debug.Log("Starting Transfer"); try { districtNo[vehicleID] = Singleton <DistrictManager> .instance.GetDistrict(Singleton <BuildingManager> .instance.m_buildings.m_buffer[data.m_sourceBuilding].m_position); currentClaim[vehicleID] = DeathRegistry.GetDeathClaim(districtNo[vehicleID], data.GetLastFramePosition()); } catch (Exception E) { return; } if (currentClaim[vehicleID] == null) { return; } Debug.Log("Successful!"); TransferManager.TransferOffer betterOffer = new TransferManager.TransferOffer(); betterOffer.Active = true; betterOffer.Amount = 0; betterOffer.Building = currentClaim[vehicleID].buildingID; betterOffer.Citizen = currentClaim[vehicleID].citizenID; base.StartTransfer(vehicleID, ref data, material, betterOffer); }
/// <summary> /// Helper method for dumping the contents of an offer, for debugging purposes. /// </summary> /// <param name="offer"></param> /// <param name="material"></param> /// <returns></returns> public static string ToString(ref TransferManager.TransferOffer offer, TransferManager.TransferReason material) { var outsideOfferText = TransferManagerInfo.IsOutsideOffer(ref offer) ? "(O)" : ""; if (offer.NetSegment != 0) { return($"Id=S{offer.NetSegment}, (Amt,Mat,Pri,Exc,Act)=({offer.Amount},{material},{offer.Priority},{offer.Exclude},{offer.Active})"); } if (offer.Vehicle != 0) { var homeBuilding = VehicleManager.instance.m_vehicles.m_buffer[offer.Vehicle].m_sourceBuilding; return($"Id=V{offer.Vehicle}, Home=B{homeBuilding}{outsideOfferText}, (Amt,Mat,Pri,Exc,Act)=({offer.Amount},{material},{offer.Priority},{offer.Exclude},{offer.Active})"); } if (offer.Citizen != 0) { var homeBuilding = CitizenManager.instance.m_citizens.m_buffer[offer.Citizen].m_homeBuilding; return($"Id=C{offer.Citizen}, Home=B{homeBuilding}{outsideOfferText}, (Amt,Mat,Pri,Exc,Act)=({offer.Amount},{material},{offer.Priority},{offer.Exclude},{offer.Active})"); } if (offer.Building != 0) { return($"Id=B{offer.Building}{outsideOfferText}, (Amt,Mat,Pri,Exc,Act)=({offer.Amount},{material},{offer.Priority},{offer.Exclude},{offer.Active})"); } return($"Id=0, (Amt,Mat,Pri,Exc,Act)=({offer.Amount},{material},{offer.Priority},{offer.Exclude},{offer.Active})"); }
public static bool Prefix(ushort vehicleID, ref Vehicle data, TransferManager.TransferReason material, TransferManager.TransferOffer offer) { Debug.Log("Start Transfer Called"); Debug.Log("Start Transfer Called"); return(DistrictHelper.CanTransfer(data.m_sourceBuilding, material, offer)); }
private static bool Prefix(TransferManager.TransferReason material, ref TransferManager.TransferOffer offer) { switch (material) { case TransferManager.TransferReason.Entertainment: case TransferManager.TransferReason.EntertainmentB: case TransferManager.TransferReason.EntertainmentC: case TransferManager.TransferReason.EntertainmentD: case TransferManager.TransferReason.TouristA: case TransferManager.TransferReason.TouristB: case TransferManager.TransferReason.TouristC: case TransferManager.TransferReason.TouristD: return(RealTimeAI.IsEntertainmentTarget(offer.Building)); case TransferManager.TransferReason.Shopping: case TransferManager.TransferReason.ShoppingB: case TransferManager.TransferReason.ShoppingC: case TransferManager.TransferReason.ShoppingD: case TransferManager.TransferReason.ShoppingE: case TransferManager.TransferReason.ShoppingF: case TransferManager.TransferReason.ShoppingG: case TransferManager.TransferReason.ShoppingH: return(RealTimeAI.IsShoppingTarget(offer.Building)); case TransferManager.TransferReason.ParkMaintenance: return(RealTimeAI.IsBuildingActive(offer.Building)); default: return(true); } }
/// <summary> /// Point of note: This is a static function whereas the original function uses __thiscall. /// On x64 machines only __fastcall is left, which means that the first parameter lives in /// RCX - which conveniently conincides with the register usually used for the this-ptr /// (at least on Windows). /// </summary> /// <param name="manager"></param> /// <param name="material"></param> /// <param name="offer"></param> public static void AddIncomingOffer(TransferManager manager, TransferManager.TransferReason material, TransferManager.TransferOffer offer) { // note: do NOT just use // DebugOutputPanel.AddMessage // here. This method is called so frequently that it will actually crash the game. if (!_init) { _init = true; Init(); } DebugLog.LogToFileOnly("AddIncomingOffer for " + material + " from " + Environment.StackTrace); for (int priority = offer.Priority; priority >= 0; --priority) { int index = (int)material * 8 + priority; int count = _incomingCount[index]; if (count < 256) { _incomingOffers[index * 256 + count] = offer; _incomingCount[index] = (ushort)(count + 1); _incomingAmount[(int)material] += offer.Amount; break; } } }
private static bool StartTransferPre( DepotAI __instance, ref ushort buildingID, ref Building data, TransferManager.TransferReason reason, TransferManager.TransferOffer offer) { var lineID = offer.TransportLine; //TODO: fish boats? //TODO: also check reason? - see DepotAI var info = TransportManager.instance.m_lines.m_buffer[lineID].Info; if (lineID <= 0 || info?.m_class == null || info.m_class.m_service == ItemClass.Service.Disaster) { return(true); //if it's not a proper transport line, let's not modify the behavior } var depot = CachedTransportLineData._lineData[lineID].Depot; if (!DepotUtil.ValidateDepotAndFindNewIfNeeded(lineID, ref depot, info)) { if (depot == 0) { Debug.LogWarning($"IPT2: No proper depot was found for line {lineID}!"); CachedTransportLineData.ClearEnqueuedVehicles(lineID); return(false); } Debug.LogWarning($"IPT2: Invalid or no depot was selected for line {lineID}, resetting to : {depot}!"); CachedTransportLineData.ClearEnqueuedVehicles(lineID); return(false); } if (depot == buildingID) { if (SimHelper.SimulationTime < CachedTransportLineData.GetNextSpawnTime(lineID)) { return(false); //if we need to wait before spawn, let's wait } if (!DepotUtil.CanAddVehicle(depot, ref BuildingManager.instance.m_buildings.m_buffer[depot], info)) { CachedTransportLineData.ClearEnqueuedVehicles(lineID); return(false); } CachedTransportLineData.SetNextSpawnTime(lineID, SimHelper.SimulationTime + OptionsWrapper <Settings> .Options.SpawnTimeInterval); } else { Debug.Log("IPT2: Redirecting from " + buildingID + " to " + depot); __instance.StartTransfer(depot, ref BuildingManager.instance.m_buildings.m_buffer[depot], reason, offer); return(false); } return(true); }
public static void ProcessCityResourceDepartmentBuildingOutgoing(ushort buildingID, ref Building buildingData) { int num27 = 0; int num28 = 0; int num29 = 0; int value = 0; TransferManager.TransferReason outgoingTransferReason = default(TransferManager.TransferReason); //constructionResource System.Random rand = new System.Random(); outgoingTransferReason = (TransferManager.TransferReason) 124; if (outgoingTransferReason != TransferManager.TransferReason.None) { CaculationVehicle.CustomCalculateOwnVehicles(buildingID, ref buildingData, outgoingTransferReason, ref num27, ref num28, ref num29, ref value); buildingData.m_tempExport = (byte)Mathf.Clamp(value, (int)buildingData.m_tempExport, 255); } if (buildingData.m_fireIntensity == 0 && outgoingTransferReason != TransferManager.TransferReason.None && buildingData.m_flags.IsFlagSet(Building.Flags.Completed)) { int num36 = 20; int customBuffer = MainDataStore.constructionResourceBuffer[buildingID]; if (customBuffer >= 8000 && num27 < num36) { TransferManager.TransferOffer offer2 = default(TransferManager.TransferOffer); offer2.Priority = rand.Next(8); offer2.Building = buildingID; offer2.Position = buildingData.m_position; offer2.Amount = Mathf.Min(customBuffer / 8000, num36 - num27); offer2.Active = true; Singleton <TransferManager> .instance.AddOutgoingOffer(outgoingTransferReason, offer2); } } //operationResource outgoingTransferReason = (TransferManager.TransferReason) 125; if (outgoingTransferReason != TransferManager.TransferReason.None) { CaculationVehicle.CustomCalculateOwnVehicles(buildingID, ref buildingData, outgoingTransferReason, ref num27, ref num28, ref num29, ref value); buildingData.m_tempExport = (byte)Mathf.Clamp(value, (int)buildingData.m_tempExport, 255); } if (buildingData.m_fireIntensity == 0 && outgoingTransferReason != TransferManager.TransferReason.None && buildingData.m_flags.IsFlagSet(Building.Flags.Completed)) { int num36 = 20; int customBuffer = MainDataStore.operationResourceBuffer[buildingID]; if (customBuffer >= 8000 && num27 < num36) { TransferManager.TransferOffer offer2 = default(TransferManager.TransferOffer); offer2.Priority = rand.Next(8); offer2.Building = buildingID; offer2.Position = buildingData.m_position; offer2.Amount = Mathf.Min((customBuffer) / 8000, num36 - num27); offer2.Active = true; Singleton <TransferManager> .instance.AddOutgoingOffer(outgoingTransferReason, offer2); } } }
public static void CommonBuildingAIReleaseBuildingPostfix(ushort buildingID) { MainDataStore.petrolBuffer[buildingID] = 0; MainDataStore.tempVehicleForFuelCount[buildingID] = 0; MainDataStore.finalVehicleForFuelCount[buildingID] = 0; TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Building = buildingID; Singleton <TransferManager> .instance.RemoveOutgoingOffer((TransferManager.TransferReason) 112, offer); }
public static void FindVisitPlace(uint citizenID, ushort sourceBuilding, TransferManager.TransferReason reason) { TransferManager.TransferOffer offer = default; offer.Priority = Singleton <SimulationManager> .instance.m_randomizer.Int32(7u); offer.Citizen = citizenID; offer.Position = Singleton <BuildingManager> .instance.m_buildings.m_buffer[sourceBuilding].m_position; offer.Amount = 1; offer.Active = true; Singleton <TransferManager> .instance.AddIncomingOffer(reason, offer); }
public static void Postfix(ushort buildingID) { MainDataStore.petrolBuffer[buildingID] = 0; MainDataStore.resourceCategory[buildingID] = 0; MainDataStore.finalVehicleForFuelCount[buildingID] = 0; TransferManager.TransferOffer offer = default; offer.Building = buildingID; Singleton <TransferManager> .instance.RemoveOutgoingOffer((TransferManager.TransferReason) 126, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer((TransferManager.TransferReason) 127, offer); }
private static bool IsSameLocation( ref TransferManager.TransferOffer requestOffer, ref TransferManager.TransferOffer responseOffer) { if (requestOffer.m_object == responseOffer.m_object) { return(true); } var requestHomeBuilding = TransferManagerInfo.GetHomeBuilding(ref requestOffer); var responseHomeBuilding = TransferManagerInfo.GetHomeBuilding(ref responseOffer); if (requestHomeBuilding == responseHomeBuilding) { return(true); } // Don't match a guest vehicle to its host building. For instance, Taxi stands. if (responseOffer.Vehicle != 0 && BuildingManager.instance.m_buildings.m_buffer[requestHomeBuilding].m_guestVehicles != 0) { var vehicleID = BuildingManager.instance.m_buildings.m_buffer[requestHomeBuilding].m_guestVehicles; int num = 0; while (vehicleID != 0) { if (responseOffer.Vehicle == vehicleID) { return(true); } vehicleID = VehicleManager.instance.m_vehicles.m_buffer[vehicleID].m_nextGuestVehicle; ++num; if (++num > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + System.Environment.StackTrace); break; } } } // Don't match outside connections that are too close to each other. if (TransferManagerInfo.IsOutsideBuilding(requestHomeBuilding) && TransferManagerInfo.IsOutsideBuilding(responseHomeBuilding)) { var requestPosition = BuildingManager.instance.m_buildings.m_buffer[requestHomeBuilding].m_position; var responsePosition = BuildingManager.instance.m_buildings.m_buffer[responseHomeBuilding].m_position; var distanceSquared = Vector3.SqrMagnitude(responsePosition - requestPosition); return(distanceSquared <= 100000); } return(false); }
public static void ProcessBuildingConstruction(ushort buildingID, ref Building buildingData, ref Building.Frame frameData) { if (MainDataStore.constructionResourceBuffer[buildingID] < 8000 && (!ResourceBuildingAI.IsSpecialBuilding(buildingID))) { System.Random rand = new System.Random(); if (buildingData.m_flags.IsFlagSet(Building.Flags.Created) && (!buildingData.m_flags.IsFlagSet(Building.Flags.Completed)) && (!buildingData.m_flags.IsFlagSet(Building.Flags.Deleted))) { frameData.m_constructState = 10; int num27 = 0; int num28 = 0; int num29 = 0; int value = 0; int num34 = 0; TransferManager.TransferReason incomingTransferReason = default(TransferManager.TransferReason); //construction resource incomingTransferReason = (TransferManager.TransferReason) 124; num27 = 0; num28 = 0; num29 = 0; value = 0; num34 = 0; if (incomingTransferReason != TransferManager.TransferReason.None) { CaculationVehicle.CustomCalculateGuestVehicles(buildingID, ref buildingData, incomingTransferReason, ref num27, ref num28, ref num29, ref value); buildingData.m_tempImport = (byte)Mathf.Clamp(value, (int)buildingData.m_tempImport, 255); } num34 = 8000 - MainDataStore.constructionResourceBuffer[buildingID] - num29; if (num34 > 0) { TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Priority = rand.Next(8); if ((buildingData.Info.m_class.m_service != ItemClass.Service.Residential) && (buildingData.Info.m_class.m_service != ItemClass.Service.Industrial) && (buildingData.Info.m_class.m_service != ItemClass.Service.Commercial) && (buildingData.Info.m_class.m_service != ItemClass.Service.Office)) { offer.Priority = 7; } offer.Building = buildingID; offer.Position = buildingData.m_position; offer.Amount = 1; offer.Active = false; Singleton <TransferManager> .instance.AddIncomingOffer(incomingTransferReason, offer); } } } else { if (!ResourceBuildingAI.IsSpecialBuilding(buildingID) && buildingData.m_flags.IsFlagSet(Building.Flags.Completed)) { MainDataStore.constructionResourceBuffer[buildingID] = 0; } } }
/// <summary> /// Makes an offer. /// </summary> /// <param name="targetBuildingId">The target building identifier.</param> /// <param name="targetCitizenId">The target citizen identifier.</param> /// <returns>The offer.</returns> public static TransferManager.TransferOffer MakeOffer(ushort targetBuildingId, uint targetCitizenId) { TransferManager.TransferOffer offer = new TransferManager.TransferOffer(); if (targetCitizenId == 0) { offer.Building = targetBuildingId; } else { offer.Citizen = targetCitizenId; } return(offer); }
/// <summary> /// Returns true if we can potentially match the two given offers. /// </summary> /// <returns></returns> private static bool IsValidDistrictOffer( TransferManager.TransferReason material, ref TransferManager.TransferOffer requestOffer, int requestPriority, ref TransferManager.TransferOffer responseOffer, int responsePriority) { var requestBuilding = TransferManagerInfo.GetHomeBuilding(ref requestOffer); var responseBuilding = TransferManagerInfo.GetHomeBuilding(ref responseOffer); if (responseBuilding == 0) { Logger.LogMaterial( $"TransferManager::IsValidDistrictOffer: {Utils.ToString(ref responseOffer, material)}, not a district services building", material); return(false); } // Special logic if both buildings are warehouses. Used to prevent goods from being shuffled back and forth between warehouses. if (BuildingManager.instance.m_buildings.m_buffer[requestBuilding].Info.GetAI() is WarehouseAI && BuildingManager.instance.m_buildings.m_buffer[responseBuilding].Info.GetAI() is WarehouseAI) { return(false); } if (Constraints.OutputAllLocalAreas(responseBuilding)) { Logger.LogMaterial( $"TransferManager::IsValidDistrictOffer: {Utils.ToString(ref responseOffer, material)}, serves all local areas", material); return(true); } // The call to TransferManagerInfo.GetDistrict applies to offers that are come from buildings, service // vehicles, citizens, AND segments. The latter needs to be considered for road maintenance. var requestDistrictPark = TransferManagerInfo.GetDistrictPark(material, ref requestOffer); var responseDistrictParksServed = Constraints.OutputDistrictParkServiced(responseBuilding); if (requestDistrictPark.IsServedBy(responseDistrictParksServed)) { Logger.LogMaterial( $"TransferManager::IsValidDistrictOffer: {Utils.ToString(ref responseOffer, material)}, serves district {requestDistrictPark.Name}", material); return(true); } Logger.LogMaterial( $"TransferManager::IsValidDistrictOffer: {Utils.ToString(ref responseOffer, material)}, not valid", material); return(false); }
public static bool Prefix(ushort buildingID, ref Building data, TransferManager.TransferReason material, TransferManager.TransferOffer offer) { if (DistrictHelper.BuildingTransfer(buildingID, material, offer)) { DebugHelper.Log($"Transfer Request Accepted."); return(true); } BuildingHelper.MoveRequest(buildingID, ref data, material, offer); { DebugHelper.Log("Moving Transfer Request."); return(false); } }
public static void Postfix(ushort buildingID, ref Building data) { MainDataStore.foodBuffer[buildingID] = 0; MainDataStore.lumberBuffer[buildingID] = 0; MainDataStore.petrolBuffer[buildingID] = 0; MainDataStore.coalBuffer[buildingID] = 0; MainDataStore.constructionResourceBuffer[buildingID] = 0; MainDataStore.operationResourceBuffer[buildingID] = 0; MainDataStore.resourceCategory[buildingID] = 0; TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Building = buildingID; Singleton <TransferManager> .instance.RemoveOutgoingOffer((TransferManager.TransferReason) 124, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer((TransferManager.TransferReason) 125, offer); }
public static void ProcessPlayerBuildingOperation(ushort buildingID, ref Building buildingData) { if (buildingData.m_fireIntensity == 0 && buildingData.m_flags.IsFlagSet(Building.Flags.Completed)) { int num27 = 0; int num28 = 0; int num29 = 0; int value = 0; int num34 = 0; TransferManager.TransferReason incomingTransferReason = default(TransferManager.TransferReason); //operation resource incomingTransferReason = (TransferManager.TransferReason) 125; num27 = 0; num28 = 0; num29 = 0; value = 0; num34 = 0; if (incomingTransferReason != TransferManager.TransferReason.None) { CaculationVehicle.CustomCalculateGuestVehicles(buildingID, ref buildingData, incomingTransferReason, ref num27, ref num28, ref num29, ref value); buildingData.m_tempImport = (byte)Mathf.Clamp(value, (int)buildingData.m_tempImport, 255); } num34 = 15000 - MainDataStore.operationResourceBuffer[buildingID] - num29; if (num34 > 0) { TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); //Higher priority for Electricity and Water sevice. if (buildingData.Info.m_class.m_service == ItemClass.Service.Water || buildingData.Info.m_class.m_service == ItemClass.Service.Electricity || buildingData.Info.m_class.m_service == ItemClass.Service.Garbage) { offer.Priority = num34 / 1000; } else { offer.Priority = num34 / 3000; } if (offer.Priority > 7) { offer.Priority = 7; } offer.Building = buildingID; offer.Position = buildingData.m_position; offer.Amount = 1; offer.Active = false; Singleton <TransferManager> .instance.AddIncomingOffer(incomingTransferReason, offer); } } }
// TODO: inherit CarAI private void RemoveOffers(ushort vehicleID, ref Vehicle data) { if ((data.m_flags & Vehicle.Flags.WaitingTarget) != Vehicle.Flags.None) { TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Vehicle = vehicleID; if ((data.m_flags & Vehicle.Flags.TransferToSource) != Vehicle.Flags.None) { Singleton <TransferManager> .instance.RemoveIncomingOffer((TransferManager.TransferReason) data.m_transferType, offer); } else if ((data.m_flags & Vehicle.Flags.TransferToTarget) != Vehicle.Flags.None) { Singleton <TransferManager> .instance.RemoveOutgoingOffer((TransferManager.TransferReason) data.m_transferType, offer); } } }
public static bool Prefix(ushort buildingID, ref Building data, TransferManager.TransferReason reason, TransferManager.TransferOffer offer) { Debug.Log("Start Transfer Called"); if (DistrictHelper.CanTransfer(buildingID, reason, offer)) { Debug.Log("Transfer Request Accepted."); return(true); } BuildingHelper.MoveRequest(buildingID, ref data, reason, offer); { Debug.Log("Moving Transfer Request."); return(false); } }
public static bool Prefix(TransferManager.TransferReason material, ref TransferManager.TransferOffer offer) { Logger.LogMaterial($"TransferManager::AddIncomingOffer: {Utils.ToString(ref offer, material)}!", material); // Inactive outside connections should not be adding offers ... if (OutsideConnectionInfo.IsInvalidIncomingOutsideConnection(offer.Building)) { Logger.LogMaterial($"TransferManager::AddIncomingOffer: Disallowing outside connection B{offer.Building} because of missing cargo buildings!", material); return(false); } if (!(TransferManagerInfo.IsDistrictOffer(material) || TransferManagerInfo.IsSupplyChainOffer(material))) { // Fix for certain assets that have sub buildings that should not be making offers ... if (offer.Building != 0 && BuildingManager.instance.m_buildings.m_buffer[offer.Building].m_parentBuilding != 0) { if (material == TransferManager.TransferReason.ParkMaintenance) { Logger.LogMaterial($"TransferManager::AddIncomingOffer: Filtering out subBuilding {Utils.ToString(ref offer, material)}!", material); return(false); } } return(true); } if (material == TransferManager.TransferReason.Taxi && offer.Citizen != 0) { var instance = CitizenManager.instance.m_citizens.m_buffer[offer.Citizen].m_instance; var targetBuilding = CitizenManager.instance.m_instances.m_buffer[instance].m_targetBuilding; var targetPosition = BuildingManager.instance.m_buildings.m_buffer[targetBuilding].m_position; if (!TaxiMod.CanUseTaxis(offer.Position, targetPosition)) { Logger.LogMaterial($"TransferManager::AddIncomingOffer: Filtering out {Utils.ToString(ref offer, material)}!", material); var instanceId = CitizenManager.instance.m_citizens.m_buffer[offer.Citizen].m_instance; CitizenManager.instance.m_instances.m_buffer[instanceId].m_flags &= ~CitizenInstance.Flags.WaitingTaxi; CitizenManager.instance.m_instances.m_buffer[instanceId].m_flags |= CitizenInstance.Flags.BoredOfWaiting; CitizenManager.instance.m_instances.m_buffer[instanceId].m_flags |= CitizenInstance.Flags.CannotUseTaxi; CitizenManager.instance.m_instances.m_buffer[instanceId].m_waitCounter = byte.MaxValue; return(false); } } TransferManagerAddOffer.ModifyOffer(material, ref offer); return(true); }
public static bool Prefix(ref TransferManager.TransferReason material, ref TransferManager.TransferOffer offer) { Logger.LogMaterial($"TransferManager::AddOutgoingOffer: {Utils.ToString(ref offer, material)}!", material); // Inactive outside connections should not be adding offers ... if (OutsideConnectionInfo.IsInvalidOutgoingOutsideConnection(offer.Building)) { Logger.LogMaterial($"TransferManager::AddOutgoingOffer: Disallowing outside connection B{offer.Building} because of missing cargo buildings!", material); return(false); } // Change these offers ... a bug in the base game. Citizens should not offer health care services. if ((material == TransferManager.TransferReason.ElderCare || material == TransferManager.TransferReason.ChildCare) && offer.Citizen != 0) { offer.Active = true; TransferManager.instance.AddIncomingOffer(material, offer); return(false); } // Too many requests for helicopters ... if (material == TransferManager.TransferReason.Sick2) { if (Singleton <SimulationManager> .instance.m_randomizer.Int32(10U) != 0) { material = TransferManager.TransferReason.Sick; } } if (!(TransferManagerInfo.IsDistrictOffer(material) || TransferManagerInfo.IsSupplyChainOffer(material))) { // Fix for certain assets that have sub buildings that should not be making offers ... if (offer.Building != 0 && BuildingManager.instance.m_buildings.m_buffer[offer.Building].m_parentBuilding != 0) { if (material == TransferManager.TransferReason.ParkMaintenance) { Logger.LogMaterial($"TransferManager::AddOutgoingOffer: Filtering out subBuilding {Utils.ToString(ref offer, material)}!", material); return(false); } } return(true); } TransferManagerAddOffer.ModifyOffer(material, ref offer); return(true); }
public static void Prefix(ref TransferManager.TransferReason material, ref TransferManager.TransferOffer offer) { if (!CustomTransferManager._init) { CustomTransferManager.Init(); CustomTransferManager._init = true; } //If no HelicopterDepot, change offer type. if (!HelicopterDepotAISimulationStepPatch.haveFireHelicopterDepotFinal) { if (material == TransferManager.TransferReason.Fire2) { material = TransferManager.TransferReason.Fire; } } }
public static bool Prefix(TransferManager.TransferReason material, TransferManager.TransferOffer offerOut, TransferManager.TransferOffer offerIn, int delta) { bool offerOutActive = offerOut.Active; if (offerOutActive && offerOut.Building != 0) { Array16 <Building> buildings = Singleton <BuildingManager> .instance.m_buildings; ushort building = offerOut.Building; offerIn.Amount = delta; if ((material == TransferManager.TransferReason.DeadMove || material == TransferManager.TransferReason.GarbageMove) && Singleton <BuildingManager> .instance.m_buildings.m_buffer[offerOut.Building].m_flags.IsFlagSet(Building.Flags.Untouchable)) { StartMoreTransfer(building, ref buildings.m_buffer[(int)building], material, offerIn); return(false); } } return(true); }
public override void BuildingDeactivated(ushort buildingID, ref Building data) { TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Building = buildingID; for (int i = 0; i < m_incomingResources.Length; i++) { if (m_incomingResources[i] != TransferManager.TransferReason.None) { Singleton <TransferManager> .instance.RemoveIncomingOffer(m_incomingResources[i], offer); } } Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.Entertainment, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.EntertainmentB, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.EntertainmentC, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.EntertainmentD, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.TouristA, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.TouristB, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.TouristC, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.TouristD, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.Shopping, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.ShoppingB, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.ShoppingC, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.ShoppingD, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.ShoppingE, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.ShoppingF, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.ShoppingG, offer); Singleton <TransferManager> .instance.RemoveOutgoingOffer(TransferManager.TransferReason.ShoppingH, offer); base.BuildingDeactivated(buildingID, ref data); }
public void DispatchIdleVehicle() { Building[] buildings = Singleton <BuildingManager> .instance.m_buildings.m_buffer; Building me = buildings[_buildingID]; if ((me.m_flags & Building.Flags.Active) == Building.Flags.None && me.m_productionRate == 0) { return; } if ((me.m_flags & Building.Flags.Downgrading) != Building.Flags.None) { return; } if (me.Info.m_buildingAI.IsFull(_buildingID, ref buildings[_buildingID])) { return; } int max, now; CaluculateWorkingVehicles(out max, out now); if (now >= max) { return; } ushort target = GetUnclaimedTarget(); if (target == 0) { return; } TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Building = target; offer.Position = buildings[target].m_position; me.Info.m_buildingAI.StartTransfer( _buildingID, ref buildings[_buildingID], TransferManager.TransferReason.Garbage, offer ); }
/// <summary> /// Sets the priority of outside connection offers to 0, while ensuring that local offers have priority 1 /// or greater. /// </summary> /// <remarks> /// We are a modifying the priority of offers as a way of prioritizing the local supply chain, and only /// resorting to outside connections if materials cannot be found locally. /// </remarks> /// <param name="material"></param> /// <param name="offer"></param> public static void ModifyOffer(TransferManager.TransferReason material, ref TransferManager.TransferOffer offer) { var isOutsideOffer = TransferManagerInfo.IsOutsideOffer(ref offer); if (isOutsideOffer) { offer.Priority = 0; } else { offer.Priority = Mathf.Clamp(offer.Priority + 1, 1, 7); } if (offer.Vehicle != 0) { offer.Priority = 7; } }
private static bool Prefix(TransferManager.TransferReason material, ref TransferManager.TransferOffer offer) { switch (material) { case TransferManager.TransferReason.Entertainment: case TransferManager.TransferReason.EntertainmentB: case TransferManager.TransferReason.EntertainmentC: case TransferManager.TransferReason.EntertainmentD: case TransferManager.TransferReason.TouristA: case TransferManager.TransferReason.TouristB: case TransferManager.TransferReason.TouristC: case TransferManager.TransferReason.TouristD: return(RealTimeAI?.IsEntertainmentTarget(offer.Building) ?? true); default: return(true); } }
public static bool Prefix(ushort buildingID, ref Building data, TransferManager.TransferReason material, TransferManager.TransferOffer offer) { Debug.Log("Start Transfer Called"); if (DistrictHelper.CanTransfer(buildingID, material, offer)) { Debug.Log( $"Transfer Request Accepted from {DistrictManager.instance.GetDistrictName(DistrictManager.instance.GetDistrict(data.m_position))}"); return(true); } BuildingHelper.MoveRequest(buildingID, ref data, material, offer); { Debug.Log( $"Moving Transfer Request from {DistrictManager.instance.GetDistrictName(DistrictManager.instance.GetDistrict(data.m_position))}"); return(false); } }
/// <summary> /// Starts the transfer. /// </summary> /// <param name="vehicleId">The vehicle identifier.</param> /// <param name="vehicle">The vehicle.</param> /// <param name="material">The material.</param> /// <param name="targetBuildingId">The target building identifier.</param> /// <param name="targetCitizenId">The target citizen identifier.</param> /// <returns>True on success.</returns> private static bool StartTransfer(ushort vehicleId, ref Vehicle vehicle, TransferManager.TransferReason material, ushort targetBuildingId, uint targetCitizenId) { TransferManager.TransferOffer offer = new TransferManager.TransferOffer() { Building = targetBuildingId, Citizen = targetCitizenId, }; vehicle.m_flags &= ~Vehicle.Flags.GoingBack; vehicle.m_flags |= Vehicle.Flags.WaitingTarget; // Cast AI as games original AI so detoured methods are called, but not methods from not replaced classes. if (Global.Settings.AssignmentCompatibilityMode == ServiceDispatcherSettings.ModCompatibilityMode.UseInstanciatedClassMethods || !Global.Settings.AllowReflection()) { vehicle.Info.m_vehicleAI.StartTransfer(vehicleId, ref vehicle, material, offer); } else if (vehicle.Info.m_vehicleAI is HearseAI) { ((HearseAI)vehicle.Info.m_vehicleAI.CastTo<HearseAI>()).StartTransfer(vehicleId, ref vehicle, material, offer); } else if (vehicle.Info.m_vehicleAI is GarbageTruckAI) { ((GarbageTruckAI)vehicle.Info.m_vehicleAI.CastTo<GarbageTruckAI>()).StartTransfer(vehicleId, ref vehicle, material, offer); } else if (vehicle.Info.m_vehicleAI is AmbulanceAI) { ((AmbulanceAI)vehicle.Info.m_vehicleAI.CastTo<AmbulanceAI>()).StartTransfer(vehicleId, ref vehicle, material, offer); } else { vehicle.Info.m_vehicleAI.StartTransfer(vehicleId, ref vehicle, material, offer); } return vehicle.m_targetBuilding == targetBuildingId && (targetCitizenId == 0 || Singleton<CitizenManager>.instance.m_citizens.m_buffer[targetCitizenId].m_vehicle == vehicleId); }
private bool FindHospital(uint citizenID, ushort sourceBuilding, TransferManager.TransferReason reason) { if (reason == TransferManager.TransferReason.Dead) { if (Singleton<UnlockManager>.instance.Unlocked(UnlockManager.Feature.DeathCare)) { return true; } ReleaseCitizen(citizenID); return false; } if (Singleton<UnlockManager>.instance.Unlocked(ItemClass.Service.HealthCare)) { TransferManager.TransferOffer offer = new TransferManager.TransferOffer { Priority = 6, Citizen = citizenID, Position = Singleton<BuildingManager>.instance.m_buildings.m_buffer[sourceBuilding].m_position, Amount = 1, Active = Singleton<SimulationManager>.instance.m_randomizer.Int32(2) == 0 }; Singleton<TransferManager>.instance.AddOutgoingOffer(reason, offer); return true; } ReleaseCitizen(citizenID); return false; }
private void UpdateWorkplace(uint citizenID, ref Citizen data) { if ((data.m_workBuilding == 0) && (data.m_homeBuilding != 0)) { Vector3 position = Singleton<BuildingManager>.instance.m_buildings.m_buffer[data.m_homeBuilding].m_position; DistrictManager instance = Singleton<DistrictManager>.instance; byte district = instance.GetDistrict(position); DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[district].m_servicePolicies; int age = data.Age; TransferManager.TransferReason none = TransferManager.TransferReason.None; switch (Citizen.GetAgeGroup(age)) { case Citizen.AgeGroup.Child: if (!data.Education1) { none = TransferManager.TransferReason.Student1; } break; case Citizen.AgeGroup.Teen: if (!data.Education2) { none = TransferManager.TransferReason.Student2; } break; case Citizen.AgeGroup.Young: case Citizen.AgeGroup.Adult: if (!data.Education3) { none = TransferManager.TransferReason.Student3; } break; } if (((data.Unemployed != 0) && (data.m_homeBuilding != 0)) && ((((servicePolicies & DistrictPolicies.Services.EducationBoost) == DistrictPolicies.Services.None) || (none != TransferManager.TransferReason.Student3)) || ((age % 5) > 2))) { TransferManager.TransferOffer offer = new TransferManager.TransferOffer { Priority = Singleton<SimulationManager>.instance.m_randomizer.Int32(8), Citizen = citizenID, Position = position, Amount = 1, Active = true }; switch (data.EducationLevel) { case Citizen.Education.Uneducated: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Worker0, offer); break; case Citizen.Education.OneSchool: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Worker1, offer); break; case Citizen.Education.TwoSchools: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Worker2, offer); break; case Citizen.Education.ThreeSchools: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Worker3, offer); break; } } if (none != TransferManager.TransferReason.None && (none != TransferManager.TransferReason.Student3 || (servicePolicies & DistrictPolicies.Services.SchoolsOut) == DistrictPolicies.Services.None || age % 5 > 1)) { TransferManager.TransferOffer offer2 = new TransferManager.TransferOffer { Priority = Singleton<SimulationManager>.instance.m_randomizer.Int32(8), Citizen = citizenID, Position = position, Amount = 1, Active = true }; Singleton<TransferManager>.instance.AddOutgoingOffer(none, offer2); } } }
private void UpdateHome(uint citizenID, ref Citizen data) { if ((data.m_homeBuilding == 0) && ((data.m_flags & Citizen.Flags.DummyTraffic) == Citizen.Flags.None)) { TransferManager.TransferOffer offer = new TransferManager.TransferOffer { Priority = 7, Citizen = citizenID, Amount = 1, Active = true }; if (data.m_workBuilding != 0) { BuildingManager instance = Singleton<BuildingManager>.instance; offer.Position = instance.m_buildings.m_buffer[data.m_workBuilding].m_position; } else { offer.PositionX = Singleton<SimulationManager>.instance.m_randomizer.Int32(0x100); offer.PositionZ = Singleton<SimulationManager>.instance.m_randomizer.Int32(0x100); } if (Singleton<SimulationManager>.instance.m_randomizer.Int32(2) == 0) { switch (data.EducationLevel) { case Citizen.Education.Uneducated: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Single0, offer); break; case Citizen.Education.OneSchool: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Single1, offer); break; case Citizen.Education.TwoSchools: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Single2, offer); break; case Citizen.Education.ThreeSchools: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Single3, offer); break; } } else { switch (data.EducationLevel) { case Citizen.Education.Uneducated: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Single0B, offer); break; case Citizen.Education.OneSchool: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Single1B, offer); break; case Citizen.Education.TwoSchools: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Single2B, offer); break; case Citizen.Education.ThreeSchools: Singleton<TransferManager>.instance.AddOutgoingOffer(TransferManager.TransferReason.Single3B, offer); break; } } } }
/// <summary> /// Starts the transfer. /// </summary> /// <param name="serviceBuildingId">The building identifier.</param> /// <param name="building">The building.</param> /// <param name="material">The material.</param> /// <param name="targetBuildingId">The target building identifier.</param> /// <param name="targetCitizenId">The target citizen identifier.</param> /// <param name="vehicleId">The vehicle identifier.</param> /// <returns>Vehicle info for the created vehicle.</returns> /// <exception cref="Exception">Loop counter too high.</exception> public static VehicleInfo StartTransfer(ushort serviceBuildingId, ref Building building, TransferManager.TransferReason material, ushort targetBuildingId, uint targetCitizenId, out ushort vehicleId) { if (building.Info.m_buildingAI is HospitalAI && targetCitizenId == 0) { return VehicleHelper.CreateServiceVehicle(serviceBuildingId, material, targetBuildingId, targetCitizenId, out vehicleId); } Vehicle[] vehicles = Singleton<VehicleManager>.instance.m_vehicles.m_buffer; Citizen[] citizens = Singleton<CitizenManager>.instance.m_citizens.m_buffer; TransferManager.TransferOffer offer = new TransferManager.TransferOffer() { Building = targetBuildingId, Citizen = targetCitizenId, }; // Cast AI as games original AI so detoured methods are called, but not methods from not replaced classes. if (Global.Settings.CreationCompatibilityMode == ServiceDispatcherSettings.ModCompatibilityMode.UseInstanciatedClassMethods || !Global.Settings.AllowReflection()) { building.Info.m_buildingAI.StartTransfer(serviceBuildingId, ref building, material, offer); } else if (building.Info.m_buildingAI is CemeteryAI) { ((CemeteryAI)building.Info.m_buildingAI.CastTo<CemeteryAI>()).StartTransfer(serviceBuildingId, ref building, material, offer); } else if (building.Info.m_buildingAI is LandfillSiteAI) { ((LandfillSiteAI)building.Info.m_buildingAI.CastTo<LandfillSiteAI>()).StartTransfer(serviceBuildingId, ref building, material, offer); } else if (building.Info.m_buildingAI is HospitalAI) { ((HospitalAI)building.Info.m_buildingAI.CastTo<HospitalAI>()).StartTransfer(serviceBuildingId, ref building, material, offer); } else { building.Info.m_buildingAI.StartTransfer(serviceBuildingId, ref building, material, offer); } int count = 0; vehicleId = building.m_ownVehicles; while (vehicleId != 0) { if (vehicles[vehicleId].m_targetBuilding == targetBuildingId && (targetCitizenId == 0 || citizens[targetCitizenId].m_vehicle == vehicleId)) { return vehicles[vehicleId].Info; } if (count >= ushort.MaxValue) { throw new Exception("Loop counter too high"); } count++; vehicleId = vehicles[vehicleId].m_nextOwnVehicle; } return null; }