protected virtual void OnConduitUpdate(float data) { if (!FlowMgr.HasConduit(this.InputCell) || !FlowMgr.HasConduit(this.OutputCell)) { } else { ConduitFlow.Conduit conduit = FlowMgr.GetConduit(this.InputCell); ConduitFlow.ConduitContents contents = conduit.GetContents(FlowMgr); float massSrc = Mathf.Min(contents.mass, this.DesiredFlow); if (massSrc > 0) { int disease_count = (int)((massSrc / contents.mass) * contents.diseaseCount); var massMoved = FlowMgr.AddElement(this.OutputCell, contents.element, massSrc, contents.temperature, contents.diseaseIdx, disease_count); MassMoved += massMoved; if (massMoved > 0) { FlowMgr.RemoveElement(this.InputCell, massMoved); DesiredFlow -= massMoved; } } } this.UpdateAnim(); }
// Tries to request fluid for current requestor in specified list of Warp Gates // returns false when all providers are dry at the moment and no more fluid can be transfered in this channel private static bool RequestFluid(ValvesList warpGates) { var requestor = warpGates.getCurrentRequestor(); var provider = warpGates.getNextProvider(); var start = provider; if (null == provider || null == requestor) { return(false); } int toCell = requestor.GetOutputCell(); var flowManager = warpGates.FlowManager; // Fill input cell from various providers, in case when provider's conduit is not full do { int fromCell = provider.GetInputCell(); if (provider != requestor) { ConduitFlow.Conduit providerConduit = flowManager.GetConduit(fromCell); ConduitFlow.ConduitContents providerContents = providerConduit.GetContents(flowManager); if (!SimHashes.Vacuum.Equals(providerContents.element)) { ConduitFlow.Conduit requestorConduit = flowManager.GetConduit(toCell); ConduitFlow.ConduitContents requestorContents = requestorConduit.GetContents(flowManager); #if DEBUG Logger.LogFormat("Trying to move {0} kg. of {1} from {2} to {3}", providerContents.mass, providerContents.element, fromCell, toCell); Logger.LogFormat("Requestor contents is: {0} kg. of {1}", requestorContents.mass, requestorContents.element); #endif if (requestorContents.mass < 1f && requestorContents.element != providerContents.element && requestorContents.element != SimHashes.Vacuum) { flowManager.RemoveElement(requestorConduit, requestorContents.mass); } float addedMass = flowManager.AddElement(toCell, providerContents.element, providerContents.mass, providerContents.temperature, providerContents.diseaseIdx, providerContents.diseaseCount); Game.Instance.accumulators.Accumulate(provider.AccumulatorHandle, addedMass); if (addedMass > 0f) { #if DEBUG Logger.LogFormat("Moved {0} kg. from {1} to {2}", addedMass, fromCell, toCell); #endif ConduitFlow.ConduitContents removed = flowManager.RemoveElement(providerConduit, addedMass); Game.Instance.accumulators.Accumulate(requestor.AccumulatorHandle, addedMass); } } } if (flowManager.IsConduitFull(toCell)) { return(true); } provider = warpGates.getNextProvider(); } while (provider != start); return(false); }
private void AddAudioSource(ConduitFlow.Conduit conduit, Vector3 camera_pos) { using (new KProfiler.Region("AddAudioSource", null)) { UtilityNetwork network = flowManager.GetNetwork(conduit); if (network != null) { Vector3 vector = Grid.CellToPosCCC(conduit.GetCell(flowManager), Grid.SceneLayer.Building); float num = Vector3.SqrMagnitude(vector - camera_pos); bool flag = false; for (int i = 0; i < audioInfo.Count; i++) { AudioInfo value = audioInfo[i]; if (value.networkID == network.id) { if (num < value.distance) { value.distance = num; value.position = vector; audioInfo[i] = value; } flag = true; break; } } if (!flag) { AudioInfo item = default(AudioInfo); item.networkID = network.id; item.position = vector; item.distance = num; item.blobCount = 0; audioInfo.Add(item); } } } }
private void ConduitUpdate(float dt) { //If the building is broken, nothing normally stops it from operating! if (gameObject.GetComponent <BuildingHP>().HitPoints == 0) { return; } ConduitFlow manager = Conduit.GetFlowManager(valveBase.conduitType); ConduitFlow.Conduit inputConduit = manager.GetConduit(InputCell); ConduitFlow.Conduit outputConduit = manager.GetConduit(OutputCell); if (!manager.HasConduit(InputCell) || !manager.HasConduit(OutputCell)) { valveBase.UpdateAnim(); } else { ConduitFlow.ConduitContents inputContents = inputConduit.GetContents(manager); if (!bufferMode) { float valveFlow = valveBase.CurrentFlow * dt; float maxFlow; float temp; SimHashes element; byte diseaseIdx; float ratio; int disease_count; bool fromStorage = false; Tag storedTag = Tag.Invalid; if (!storage.IsEmpty()) { //If there is still mass within the storage but we are not in buffer mode, take nothing in until the storage is emptied! (while still following the limit mode settings) fromStorage = true; GameObject item = storage.items.FirstOrDefault(); PrimaryElement storedPrimary = item.GetComponent <PrimaryElement>(); maxFlow = Mathf.Min(valveFlow, storedPrimary.Mass); element = storedPrimary.ElementID; temp = storedPrimary.Temperature; diseaseIdx = storedPrimary.DiseaseIdx; ratio = maxFlow / storedPrimary.Mass; disease_count = (int)(ratio * (float)storedPrimary.DiseaseCount); storedTag = storedPrimary.Element.tag; } else { maxFlow = Mathf.Min(inputContents.mass, valveBase.CurrentFlow * dt); element = inputContents.element; temp = inputContents.temperature; diseaseIdx = inputContents.diseaseIdx; ratio = maxFlow / inputContents.mass; disease_count = (int)(ratio * (float)inputContents.diseaseCount); } if (maxFlow > 0f) { float movableMass = manager.AddElement(OutputCell, element, maxFlow, temp, diseaseIdx, disease_count); Game.Instance.accumulators.Accumulate(flowAccumulator, movableMass); if (movableMass > 0f) { //If we took the mass from storage, make sure we use the right function if (!fromStorage) { manager.RemoveElement(InputCell, movableMass); } else { storage.ConsumeIgnoringDisease(storedTag, movableMass); } } } } else { float availableInput = inputContents.mass; GameObject storedItem = storage.items.FirstOrDefault(); Element storedElement = storedItem?.GetComponent <PrimaryElement>().Element; float storedMass = storedItem != null?storedItem.GetComponent <PrimaryElement>().Mass : 0f; float maxOutputCapacity = Integration.GetMaxCapacityAt(OutputCell, valveBase.conduitType); //Override the set current flow if the output pipe cannot support a flow that large. This prevents the valve from storing, for example, 3KG, when it can only output 1KG at a time. float minimumOutput = Mathf.Min(maxOutputCapacity, valveBase.CurrentFlow); storage.capacityKg = maxOutputCapacity; float movableToStorage = Mathf.Min(availableInput, storage.RemainingCapacity()); if (movableToStorage > 0f) { Element inputElement = ElementLoader.FindElementByHash(inputContents.element); float ratio = movableToStorage / inputContents.mass; int transferredDisease = (int)((float)inputContents.diseaseCount * ratio); if (inputElement == storedElement || storedItem == null) { if (valveBase.conduitType == ConduitType.Gas) { storage.AddGasChunk(inputContents.element, movableToStorage, inputContents.temperature, inputContents.diseaseIdx, transferredDisease, false); } else { storage.AddLiquid(inputContents.element, movableToStorage, inputContents.temperature, inputContents.diseaseIdx, transferredDisease, false); } storedMass += movableToStorage; if (storedItem == null) { storedElement = inputElement; } } else { //The input has a different element than what is in storage! Deal damage and remove however much mass attempted to flow into the valve. Trigger(-794517298, new BuildingHP.DamageSourceInfo { damage = 1, source = STRINGS.BUILDINGS.DAMAGESOURCES.BAD_INPUT_ELEMENT, popString = STRINGS.UI.GAMEOBJECTEFFECTS.DAMAGE_POPS.WRONG_ELEMENT }); SimMessages.AddRemoveSubstance(Grid.PosToCell(base.transform.GetPosition()), inputContents.element, CellEventLogger.Instance.ConduitConsumerWrongElement, movableToStorage, inputContents.temperature, inputContents.diseaseIdx, transferredDisease); } manager.RemoveElement(InputCell, movableToStorage); } ConduitFlow.ConduitContents outputContents = outputConduit.GetContents(manager); float initialOutputMass = outputContents.mass; Element outputElement = ElementLoader.FindElementByHash(outputContents.element); //If we can create a packet of at least size CurrentFlow, including if we combined the valve's output into what is already in the output conduit //Debug.Log($"[TogglableValve] InitialOut: {initialOutputMass}, StoredMass: {storedMass}, MinimumOutput: {minimumOutput}, MaxOutputCapacity: {maxOutputCapacity}, AvailableInput: {availableInput}, MovableToStorage: {movableToStorage}"); if (initialOutputMass + storedMass >= minimumOutput && (storedElement == outputElement || outputElement == null || outputElement.id == SimHashes.Vacuum)) { float movableToOut = Mathf.Min(storedMass, maxOutputCapacity - initialOutputMass); if (movableToOut > 0f) { PrimaryElement storedPrimary = storage.items.FirstOrDefault()?.GetComponent <PrimaryElement>(); float ratio = movableToOut / storedMass; int transferredDisease = (int)((float)storedPrimary.DiseaseCount * ratio); float totalMovedOut = manager.AddElement(OutputCell, storedPrimary.ElementID, storedMass, storedPrimary.Temperature, storedPrimary.DiseaseIdx, transferredDisease); Game.Instance.accumulators.Accumulate(flowAccumulator, totalMovedOut); if (totalMovedOut > 0f) { storage.ConsumeIgnoringDisease(storedPrimary.Element.tag, totalMovedOut); } } } } valveBase.UpdateAnim(); } }
public void Run(RenderMeshContext context) { Element element = null; for (int i = start; i != end; i++) { ConduitFlow.Conduit conduit = context.outer.flowManager.soaInfo.GetConduit(context.visible_conduits[i]); ConduitFlow.ConduitFlowInfo lastFlowInfo = conduit.GetLastFlowInfo(context.outer.flowManager); ConduitFlow.ConduitContents initialContents = conduit.GetInitialContents(context.outer.flowManager); if (lastFlowInfo.contents.mass > 0f) { int cell = conduit.GetCell(context.outer.flowManager); int cellFromDirection = ConduitFlow.GetCellFromDirection(cell, lastFlowInfo.direction); Vector2I v = Grid.CellToXY(cell); Vector2I vector2I = Grid.CellToXY(cellFromDirection); Vector2 pos = (cell != -1) ? Vector2.Lerp(new Vector2((float)v.x, (float)v.y), new Vector2((float)vector2I.x, (float)vector2I.y), context.lerp_percent) : ((Vector2)v); Color32 cellTintColour = context.outer.GetCellTintColour(cell); Color32 cellTintColour2 = context.outer.GetCellTintColour(cellFromDirection); Color32 color = Color32.Lerp(cellTintColour, cellTintColour2, context.lerp_percent); bool highlight = false; if (context.outer.showContents) { if (lastFlowInfo.contents.mass >= initialContents.mass) { moving_balls.Add(new Ball(lastFlowInfo.direction, pos, color, context.outer.tuning.size, false, false)); } if (element == null || lastFlowInfo.contents.element != element.id) { element = ElementLoader.FindElementByHash(lastFlowInfo.contents.element); } } else { element = null; int num = Grid.PosToCell(new Vector3(pos.x + GRID_OFFSET.x, pos.y + GRID_OFFSET.y, 0f)); highlight = (num == context.outer.highlightedCell); } Color32 contentsColor = context.outer.GetContentsColor(element, color); float num2 = 1f; if (context.outer.showContents || lastFlowInfo.contents.mass < initialContents.mass) { num2 = context.outer.CalculateMassScale(lastFlowInfo.contents.mass); } moving_balls.Add(new Ball(lastFlowInfo.direction, pos, contentsColor, context.outer.tuning.size * num2, true, highlight)); moving_conduits.Add(conduit); } if (initialContents.mass > lastFlowInfo.contents.mass && initialContents.mass > 0f) { int cell2 = conduit.GetCell(context.outer.flowManager); Vector2I v2 = Grid.CellToXY(cell2); Vector2 pos2 = v2; float mass = initialContents.mass - lastFlowInfo.contents.mass; bool highlight2 = false; Color32 cellTintColour3 = context.outer.GetCellTintColour(cell2); float num3 = context.outer.CalculateMassScale(mass); if (context.outer.showContents) { static_balls.Add(new Ball(ConduitFlow.FlowDirections.None, pos2, cellTintColour3, context.outer.tuning.size * num3, false, false)); if (element == null || initialContents.element != element.id) { element = ElementLoader.FindElementByHash(initialContents.element); } } else { element = null; highlight2 = (cell2 == context.outer.highlightedCell); } Color32 contentsColor2 = context.outer.GetContentsColor(element, cellTintColour3); static_balls.Add(new Ball(ConduitFlow.FlowDirections.None, pos2, contentsColor2, context.outer.tuning.size * num3, true, highlight2)); } } }
private static void PushFluid(List <ValveBaseExt> requesters, List <ValveBaseExt> providers) { foreach (var provider in providers) { if (!provider.isValidProvider()) { continue; } Logger.LogFormat("-----WarpSpaceManager.RequestFluid start for channel: {0}", provider.Channel); var flowManager = provider.FlowManager; int fromCell = provider.ValveBase.GetInputCell(); ConduitFlow.Conduit providerConduit = flowManager.GetConduit(fromCell); ConduitFlow.ConduitContents providerContents = providerConduit.GetContents(flowManager); if (SimHashes.Vacuum.Equals(providerContents.element)) { continue; } var matchedRequesters = requesters.Where(x => x.Channel == provider.Channel).ToList(); if (matchedRequesters.Count == 0) { continue; } var splitMass = providerContents.mass / matchedRequesters.Count(); Logger.Log(String.Format("WarpSpaceManager.RequestFluid splitMass: {0}", splitMass)); Logger.Log(String.Format("WarpSpaceManager.RequestFluid matchedRequesters: {0}", matchedRequesters.Count)); foreach (var requester in matchedRequesters) { if (!requester.isValidRequestor()) { continue; } int toCell = requester.ValveBase.GetOutputCell(); ConduitFlow.Conduit requestorConduit = flowManager.GetConduit(toCell); ConduitFlow.ConduitContents requestorContents = requestorConduit.GetContents(flowManager); if (requestorContents.mass < 1f && requestorContents.element != providerContents.element && requestorContents.element != SimHashes.Vacuum) { Logger.LogFormat("Removing contents is: {0} kg. of {1}", requestorContents.mass, requestorContents.element); flowManager.RemoveElement(requestorConduit, requestorContents.mass); } float addedMass = flowManager.AddElement(toCell, providerContents.element, splitMass, providerContents.temperature, providerContents.diseaseIdx, providerContents.diseaseCount); Game.Instance.accumulators.Accumulate(provider.ValveBase.AccumulatorHandle, addedMass); Logger.LogFormat($@"Requestor Info requester mass: {requestorContents.mass} requester element: {requestorContents.element} provider mass: {providerContents.mass} provider element: {providerContents.element} provider split: {splitMass} added mass: {addedMass} \r\n "); if (addedMass > 0f) { ConduitFlow.ConduitContents removed = flowManager.RemoveElement(providerConduit, addedMass); Game.Instance.accumulators.Accumulate(requester.ValveBase.AccumulatorHandle, addedMass); Logger.LogFormat("Moved {0} kg. from {1} to {2}. ", addedMass, fromCell, toCell); } else { Logger.Log(String.Format("WarpSpaceManager.RequestFluid No mass moved")); } } Logger.LogFormat("-----WarpSpaceManager.RequestFluid end for channel: {0}", provider.Channel); } Logger.LogFormat("WarpSpaceManager.RequestFluid end"); }
private static bool Prefix(ValveBase __instance, float dt) { Debug.Log(" === ValveBase.ConduitUpdate(" + dt + ") Prefix " + __instance.conduitType); if (__instance.conduitType != (ConduitType)100 && __instance.conduitType != (ConduitType)101) { return(true); } FieldInfo fi1 = AccessTools.Field(typeof(ValveBase), "inputCell"); FieldInfo fi2 = AccessTools.Field(typeof(ValveBase), "outputCell"); FieldInfo fi3 = AccessTools.Field(typeof(ValveBase), "flowAccumulator"); //Debug.Log("ConduitUpdate " + dt); ConduitFlow flowManager = Conduit.GetFlowManager(__instance.conduitType); ConduitFlow.Conduit conduit = flowManager.GetConduit((int)fi1.GetValue(__instance)); if (!flowManager.HasConduit((int)fi1.GetValue(__instance)) || !flowManager.HasConduit((int)fi2.GetValue(__instance))) { __instance.UpdateAnim(); } if ((int)fi1.GetValue(__instance) > 0 && flowManager.HasConduit((int)fi1.GetValue(__instance)) && ((int)fi2.GetValue(__instance) > 0 && !flowManager.HasConduit((int)fi2.GetValue(__instance)))) { ConduitFlow.ConduitContents contents = conduit.GetContents(flowManager); //float num = Mathf.Min(contents.mass, this.currentFlow * dt); FieldInfo fi = AccessTools.Field(typeof(ValveBase), "currentFlow"); //float num = Mathf.Min(contents.mass, (float)fi.GetValue(this) * dt); float num = Mathf.Min(contents.mass, 10f * dt); Debug.Log("ConduitUpdate " + num); if (num > 0f) { float num2 = num / contents.mass; int disease_count = (int)(num2 * (float)contents.diseaseCount); Debug.Log("List " + num); LiquidWarpData.LiquidPackets.Add(new PacketData((int)__instance.conduitType, (float)fi.GetValue(__instance), (int)fi2.GetValue(__instance), contents.element, num, contents.temperature, contents.diseaseIdx, disease_count)); //float num3 = flowManager.AddElement(this.outputCell, contents.element, num, contents.temperature, contents.diseaseIdx, disease_count); //Game.Instance.accumulators.Accumulate(this.flowAccumulator, num3); //float num3 = Mathf.Min(num, 10f - contents.mass); float num3 = num; if (num3 > 0f) { flowManager.RemoveElement((int)fi1.GetValue(__instance), num3); } } __instance.UpdateAnim(); return(false); } if ((int)fi2.GetValue(__instance) > 0 && flowManager.HasConduit((int)fi2.GetValue(__instance))) { ConduitFlow.Conduit conduitO = flowManager.GetConduit((int)fi2.GetValue(__instance)); FieldInfo fi = AccessTools.Field(typeof(ValveBase), "currentFlow"); PacketData toRemove = null; foreach (PacketData packet in LiquidWarpData.LiquidPackets) { Debug.Log("currentFlow = " + (float)fi.GetValue(__instance) + ", packet.currentFlow = " + packet.current_flow); if ((float)fi.GetValue(__instance) == packet.current_flow && (int)__instance.conduitType == packet.content_type) { float num3 = flowManager.AddElement((int)fi2.GetValue(__instance), packet.element, packet.mass, packet.temperature, packet.disease_idx, packet.disease_count); Debug.Log("Adding Element to pipe: " + packet.mass + "," + num3); Game.Instance.accumulators.Accumulate((HandleVector <int> .Handle)fi3.GetValue(__instance), num3); toRemove = packet; break; } } if (toRemove != null) { LiquidWarpData.LiquidPackets.Remove(toRemove); toRemove = null; } __instance.UpdateAnim(); return(false); } return(false); }