public void EmptyPipeContents() { int cell = Grid.PosToCell(base.transform.GetPosition()); ConduitFlow.ConduitContents conduitContents = GetFlowManager().RemoveElement(cell, float.PositiveInfinity); elapsedTime = 0f; if (conduitContents.mass > 0f && conduitContents.element != SimHashes.Vacuum) { IChunkManager instance; switch (conduit.type) { case ConduitType.Gas: instance = GasSourceManager.Instance; break; case ConduitType.Liquid: instance = LiquidSourceManager.Instance; break; default: throw new ArgumentException(); } instance.CreateChunk(conduitContents.element, conduitContents.mass, conduitContents.temperature, conduitContents.diseaseIdx, conduitContents.diseaseCount, Grid.CellToPosCCC(cell, Grid.SceneLayer.Ore)); } }
private void ConduitUpdate(float dt) { ConduitFlow flowManager = Conduit.GetFlowManager(portInfo.conduitType); if (flowManager.HasConduit(inputCell)) { ConduitFlow.ConduitContents contents = flowManager.GetContents(inputCell); if (!(contents.mass <= 0f)) { int cell = outputCell; ConduitFlow.ConduitContents contents2 = flowManager.GetContents(cell); if (contents2.mass > 0f) { cell = secondaryOutput.Cell; contents2 = flowManager.GetContents(cell); } if (contents2.mass <= 0f) { float num = flowManager.AddElement(cell, contents.element, contents.mass, contents.temperature, contents.diseaseIdx, contents.diseaseCount); if (num > 0f) { flowManager.RemoveElement(inputCell, num); } } } } }
public static bool Prefix(float dt, ValveBase __instance, float ___currentFlow, int ___outputCell, int ___inputCell, HandleVector <int> .Handle ___flowAccumulator) { ConduitFlow flowManager = Conduit.GetFlowManager(__instance.conduitType); if (!flowManager.HasConduit(___inputCell) || !flowManager.HasConduit(___outputCell)) { __instance.UpdateAnim(); } else { ConduitFlow.ConduitContents input_content = flowManager.GetConduit(___inputCell).GetContents(flowManager); ConduitFlow.ConduitContents output_content = flowManager.GetConduit(___outputCell).GetContents(flowManager); float mass_input = Mathf.Min(input_content.mass, ___currentFlow * dt); float mass_output = output_content.mass; float mass_limit = Mathf.Max(___currentFlow - mass_output, 0); // mass on output cannot exceed flow setting mass_input = Mathf.Min(mass_input, mass_limit); // set new input mass if (mass_input > 0f) { float disease_percent = mass_input / input_content.mass; int disease_count = (int)(disease_percent * input_content.diseaseCount); float mass_moved = flowManager.AddElement(___outputCell, input_content.element, mass_input, input_content.temperature, input_content.diseaseIdx, disease_count); Game.Instance.accumulators.Accumulate(___flowAccumulator, mass_moved); if (mass_moved > 0f) { flowManager.RemoveElement(___inputCell, mass_moved); } } __instance.UpdateAnim(); } return(false); }
void InputPort2ConduitUpdate(float dt) { if (!this.Operational.IsOperational) { return; } var conduitMgr = this.GetConduitManager(); var input2Content = conduitMgr.GetContents(InputPort2Cell); float massMoved = Mathf.Min(input2Content.mass, this.StorageRemainingCapacity); if (massMoved <= 0) { return; } ConduitFlow.ConduitContents conduitContents = conduitMgr.RemoveElement(this.InputPort2Cell, massMoved); int disease_count = (int)(input2Content.diseaseCount * (massMoved / input2Content.mass)); switch (this.InputPort2ConduitType) { case ConduitType.Gas: this.Storage.AddGasChunk(input2Content.element, massMoved, input2Content.temperature, input2Content.diseaseIdx, disease_count, this.KeepZeroMassObject, false); break; case ConduitType.Liquid: this.Storage.AddLiquid(input2Content.element, massMoved, input2Content.temperature, input2Content.diseaseIdx, disease_count, this.KeepZeroMassObject, false); break; } }
protected override void UpdateVisualState(bool force = false) { if (wasOn != switchedOn || force) { wasOn = switchedOn; if (switchedOn) { animController.Play(ConduitSensor.ON_ANIMS, KAnim.PlayMode.Loop); int cell = Grid.PosToCell(this); ConduitFlow flowManager = Conduit.GetFlowManager(conduitType); ConduitFlow.ConduitContents contents = flowManager.GetContents(cell); Color32 c = Color.white; if (contents.diseaseIdx != 255) { Disease disease = Db.Get().Diseases[contents.diseaseIdx]; c = disease.overlayColour; } animController.SetSymbolTint(TINT_SYMBOL, c); } else { animController.Play(ConduitSensor.OFF_ANIMS, KAnim.PlayMode.Once); } } }
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(); }
public void SetData(HandleVector <int> .Handle handle, ref ConduitFlow.ConduitContents contents) { if (handle.IsValid()) { temperatures[Sim.GetHandleIndex(handle.index)] = contents.temperature; ConduitTemperatureManager_Set(handle.index, contents.temperature, contents.mass, (int)contents.element); } }
private static ConduitFlow.ConduitContents SetMaxFlow(ConduitFlow.ConduitContents contents, ConduitBridge bridge, ConduitFlow manager) { if (bridge.GetComponent <BuildingHP>().HitPoints == 0) { //does not actually remove mass from the conduit, just changes what the bridge sees contents.RemoveMass(contents.mass); return(contents); } int outputCell = (int)bridgeOutputCell.GetValue(bridge); GameObject outputObject = Grid.Objects[outputCell, Integration.layers[(int)bridge.type]]; if (outputObject == null) { return(contents); } Pressurized pressure = bridge.GetComponent <Pressurized>(); float capacity; if (!Pressurized.IsDefault(pressure)) { capacity = pressure.Info.Capacity; } else { capacity = (float)maxMass.GetValue(manager); } //If the ConduitBridge is not supposed to support the amount of fluid currently in the contents, only make the bridge's intended max visible //Also immediately deal damage if the current contents are higher than the intended max. if (capacity < contents.mass) { float initial = contents.mass; float removed = contents.RemoveMass(initial - capacity); float ratio = removed / initial; contents.diseaseCount = (int)((float)contents.diseaseCount * ratio); BuildingHP.DamageSourceInfo damage = Integration.GetPressureDamage(); bridge.Trigger((int)GameHashes.DoBuildingDamage, damage); } { float targetCapacity; Pressurized outPressure = outputObject.GetComponent <Pressurized>(); if (!Pressurized.IsDefault(outPressure)) { targetCapacity = outPressure.Info.Capacity; } else { targetCapacity = (float)maxMass.GetValue(manager); } if (contents.mass > targetCapacity * 2) { BuildingHP.DamageSourceInfo damage = Integration.GetPressureDamage(); outputObject.Trigger((int)GameHashes.DoBuildingDamage, damage); } } return(contents); }
// 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); }
public void SetData(HandleVector <int> .Handle handle, ref ConduitFlow.ConduitContents contents) { Data data = GetData(handle); data.diseaseCount = contents.diseaseCount; if (contents.diseaseIdx != data.diseaseIdx) { data.diseaseIdx = contents.diseaseIdx; byte elem_idx = (byte)ElementLoader.GetElementIndex(contents.element); data.growthInfo = GetGrowthInfo(contents.diseaseIdx, elem_idx); } SetData(handle, data); }
private bool SetContents(int cell, ConduitType conduitType, Element element, float mass, float temperature, byte diseaseIdx, int diseaseCount) { if (conduitType == ConduitType.Solid) { var conduitFlow = Game.Instance.solidConduitFlow; if (!conduitFlow.HasConduit(cell)) { return(false); } mass = Mathf.Clamp(mass, 0, MAX_SOLID_MASS); var res = element.substance.SpawnResource(Vector3.zero, mass, temperature, diseaseIdx, diseaseCount); var pc = res.GetComponent <Pickupable>(); var p = conduitFlow.RemovePickupable(cell); if (p != null) { DestroyPickupable(p); } conduitFlow.SetContents(cell, pc); updateSolidFlowVisualization = true; } else { ConduitFlow conduitFlow = conduitType == ConduitType.Liqud ? Game.Instance.liquidConduitFlow : Game.Instance.gasConduitFlow; if (!conduitFlow.HasConduit(cell)) { return(false); } var maxMass = conduitType == ConduitType.Liqud ? MAX_LIQUID_MASS : MAX_GAS_MASS; mass = Mathf.Clamp(mass, 0, maxMass); var contents = new ConduitFlow.ConduitContents(element.id, mass, temperature, diseaseIdx, diseaseCount); conduitFlow.SetContents(cell, contents); if (conduitType == ConduitType.Liqud) { updateLiquidFlowVisualization = true; } else { updateGasFlowVisualization = true; } } return(true); }
private void OnConduitTick(float dt) { bool value = false; if (this.operational.IsOperational) { ConduitFlow gasFlow = Conduit.GetFlowManager(this.portInfo.conduitType); ConduitFlow.ConduitContents contentsI1 = gasFlow.GetContents(this.inputCell1); ConduitFlow.ConduitContents contentsI2 = gasFlow.GetContents(this.inputCell2); //Debug.Log("contentsI1.mass: " + contentsI1.mass); //Debug.Log("contentsI2.mass: " + contentsI2.mass); //int num = (contents.element != this.filteredElem) ? this.outputCell : this.filteredCell; ConduitFlow.ConduitContents contentsO = gasFlow.GetContents(this.outputCell); if (contentsI1.element != SimHashes.Hydrogen || contentsI2.element != SimHashes.Oxygen) { base.Trigger((int)GameHashes.DoBuildingDamage, new BuildingHP.DamageSourceInfo { damage = 1, source = STRINGS.BUILDINGS.DAMAGESOURCES.BAD_INPUT_ELEMENT, popString = STRINGS.UI.GAMEOBJECTEFFECTS.DAMAGE_POPS.WRONG_ELEMENT }); gasFlow.RemoveElement(this.inputCell1, 0.111999989f); gasFlow.RemoveElement(this.inputCell2, 0.888f); } else { if (contentsI1.mass > 0.111999989f && contentsI2.mass > 0.888f && contentsO.mass <= 0f) { value = true; //float num2 = flowManager.AddElement(num, contents.element, contents.mass, contents.temperature, contents.diseaseIdx, contents.diseaseCount); float outputTemperature = contentsI1.temperature * 0.111999989f + contentsI2.temperature * 0.888f; //Debug.Log("outputTemperature: " + outputTemperature); ConduitFlow liquidFlow = Conduit.GetFlowManager(ConduitType.Liquid); float num2 = liquidFlow.AddElement(this.outputCell, SimHashes.Water, 1f, outputTemperature, contentsI1.diseaseIdx, 0); if (num2 > 0f) { gasFlow.RemoveElement(this.inputCell1, 0.111999989f); gasFlow.RemoveElement(this.inputCell2, 0.888f); } } } } this.operational.SetActive(value, false); }
protected override void ConduitUpdate(float dt) { ConduitFlow flowManager = Conduit.GetFlowManager(conduitType); int cell = Grid.PosToCell(base.transform.GetPosition()); ConduitFlow.ConduitContents contents = flowManager.GetContents(cell); if (base.IsSwitchedOn) { if (contents.element != desiredElement) { Toggle(); } } else if (contents.element == desiredElement) { Toggle(); } }
private void ConduitUpdate(float dt) { ConduitFlow flowManager = Conduit.GetFlowManager(type); if (flowManager.HasConduit(inputCell)) { ConduitFlow.ConduitContents contents = flowManager.GetContents(inputCell); if (contents.mass > 0f) { float num = flowManager.AddElement(outputCell, contents.element, contents.mass, contents.temperature, contents.diseaseIdx, contents.diseaseCount); if (num > 0f) { flowManager.RemoveElement(inputCell, num); Game.Instance.accumulators.Accumulate(accumulator, contents.mass); } } } }
private static ConduitFlow.ConduitContents SetMaxFlow(ConduitFlow.ConduitContents contents, ConduitBridge bridge, ConduitFlow manager) { //If the bridge is broken, prevent the bridge from operating by limiting what it sees. if (bridge.GetComponent <BuildingHP>().HitPoints == 0) { //does not actually remove mass from the conduit, just causes the bridge to assume there is no mass available to move. contents.RemoveMass(contents.mass); return(contents); } GameObject outputObject; int outputCell = (int)bridgeOutputCell.GetValue(bridge); float targetCapacity = Integration.GetMaxCapacityWithObject(outputCell, bridge.type, out outputObject, false); if (outputObject == null) { return(contents); } float capacity = Pressurized.GetMaxCapacity(bridge.GetComponent <Pressurized>()); //If the ConduitBridge is not supposed to support the amount of fluid currently in the contents, only make the bridge's intended max visible //Also immediately deal damage if the current contents are higher than 110% of the intended max (110% is set because at 100%, a system with no pressurized pipes would seem to randomly deal damage as if the contents // were barely over 100% if (contents.mass > capacity) { if (contents.mass > capacity * 1.1) { Integration.DoPressureDamage(bridge.gameObject); } float initial = contents.mass; float removed = contents.RemoveMass(initial - capacity); float ratio = removed / initial; contents.diseaseCount = (int)((float)contents.diseaseCount * ratio); } if (contents.mass > targetCapacity * 2 && UnityEngine.Random.Range(0f, 1f) < 0.33f) { Integration.DoPressureDamage(outputObject); } return(contents); }
private void OnConduitTick(float dt) { bool value = false; if (this.operational.IsOperational) { ConduitFlow flowManager = Conduit.GetFlowManager(this.portInfo.conduitType); ConduitFlow.ConduitContents contents = flowManager.GetContents(this.inputCell); //int num = (contents.element != this.filteredElem) ? this.outputCell : this.filteredCell; ConduitFlow.ConduitContents contentsO = flowManager.GetContents(this.outputCell); ConduitFlow.ConduitContents contents2 = flowManager.GetContents(this.sInputCell); if (contents.mass > 0.111999989f && contents2.mass > 0.888f && contentsO.mass <= 0f) { if (contents.element != SimHashes.Hydrogen || contents2.element != SimHashes.Oxygen) { base.Trigger(-794517298, new BuildingHP.DamageSourceInfo { damage = 1, source = STRINGS.BUILDINGS.DAMAGESOURCES.BAD_INPUT_ELEMENT, popString = STRINGS.UI.GAMEOBJECTEFFECTS.DAMAGE_POPS.WRONG_ELEMENT }); flowManager.RemoveElement(this.inputCell, 0.111999989f); flowManager.RemoveElement(this.sInputCell, 0.888f); } else { value = true; //float num2 = flowManager.AddElement(num, contents.element, contents.mass, contents.temperature, contents.diseaseIdx, contents.diseaseCount); float num2 = flowManager.AddElement(this.outputCell, SimHashes.Steam, 1f, 523.15f, contents.diseaseIdx, 0); if (num2 > 0f) { flowManager.RemoveElement(this.inputCell, 0.111999989f); flowManager.RemoveElement(this.sInputCell, 0.888f); } } } } this.operational.SetActive(value, false); }
static void Postfix(BuildingStatusItems __instance) { __instance.Pipe.resolveStringCallback = delegate(string str, object data) { Conduit obj = (Conduit)data; int cell2 = Grid.PosToCell(obj); ConduitFlow.ConduitContents contents2 = obj.GetFlowManager().GetContents(cell2); string text3 = BUILDING.STATUSITEMS.PIPECONTENTS.EMPTY; if (contents2.mass > 0f) { Element element3 = ElementLoader.FindElementByHash(contents2.element); text3 = string.Format(BUILDING.STATUSITEMS.PIPECONTENTS.CONTENTS, GameUtil.GetFormattedMass(contents2.mass), element3.name, GameUtil.GetFormattedTemperature(contents2.temperature)); if (contents2.diseaseIdx != byte.MaxValue) { text3 += string.Format(BUILDING.STATUSITEMS.PIPECONTENTS.CONTENTS_WITH_DISEASE, GameUtil.GetFormattedDisease(contents2.diseaseIdx, contents2.diseaseCount, color: true)); } } str = str.Replace("{Contents}", text3); return(str); }; }
private static ConduitFlow.ConduitContents OperationalValveOverPressure(ConduitFlow.ConduitContents contents, ValveBase valveBase, ConduitFlow flowManager) { OperationalValve op; if (op = valveBase as OperationalValve) { if (op.CurrentFlow > 0f) { int outputCell = (int)valveBaseOutputCell.GetValue(valveBase); GameObject outputObject; float outputCapacity = Integration.GetMaxCapacityWithObject(outputCell, valveBase.conduitType, out outputObject); float inputMass = contents.mass; //If there is greater than 200% of the outputs capacity inside the shutoff valves input pipe, deal overpressure damage 33% of the time. if (inputMass > (outputCapacity * 2) && UnityEngine.Random.Range(0f, 1f) < 0.33f) { Integration.DoPressureDamage(outputObject); } } } //since this patch consumed the contents variable on the stack, return the contents back to prevent issues with the next code statement in IL return(contents); }
private void OnConduitTick(float dt) { bool value = false; UpdateConduitBlockedStatus(); if (operational.IsOperational) { ConduitFlow flowManager = Conduit.GetFlowManager(portInfo.conduitType); ConduitFlow.ConduitContents contents = flowManager.GetContents(inputCell); int num = (contents.element != filteredElem) ? outputCell : filteredCell; ConduitFlow.ConduitContents contents2 = flowManager.GetContents(num); if (contents.mass > 0f && contents2.mass <= 0f) { value = true; float num2 = flowManager.AddElement(num, contents.element, contents.mass, contents.temperature, contents.diseaseIdx, contents.diseaseCount); if (num2 > 0f) { flowManager.RemoveElement(inputCell, num2); } } } operational.SetActive(value, false); }
//Since our input/output ports are inert, we must define the behavior of the ports ourself. //float dt is the amount of time that has passed. typically not used as far as i am aware, likely always just 1 (1 second) private void OnConduitTick(float dt) { //The ConduitFlow task is an overarching flow manager for a specific conduit type. If our bridge is a liquid bridge, we will get the liquid manager. ConduitFlow flowManager = Conduit.GetFlowManager(conduitType); //If there is a pipe connected to the location of the input port, and a pipe connected to the location of the output port if (flowManager.HasConduit(inputPort.GetPortCell()) && flowManager.HasConduit(outputPort.GetPortCell())) { //Get the contents of the input pipe ConduitFlow.ConduitContents contents = flowManager.GetContents(inputPort.GetPortCell()); if (contents.mass > 0f) { //The AddElement method will attempt to move as much fluid from the input to the output as it can, and will return the amount successfully moved (if any). //This method also handles things such as merging disease amounts and temperature based on how much is moved float amountMOved = flowManager.AddElement(outputPort.GetPortCell(), contents.element, contents.mass, contents.temperature, contents.diseaseIdx, contents.diseaseCount); if (amountMOved > 0f) { //RemoveElement, similar to AddElement, automatically reduces the disease count (if any germs are present) flowManager.RemoveElement(inputPort.GetPortCell(), amountMOved); } } } }
private void ConduitUpdate(float dt) { ConduitFlow flowManager = Conduit.GetFlowManager(this.conduitType); if (!flowManager.HasConduit(this.inputCell) || !flowManager.HasConduit(this.outputCell)) { this.UpdateAnim(); } else { ConduitFlow.ConduitContents input_content = flowManager.GetConduit(this.inputCell).GetContents(flowManager); ConduitFlow.ConduitContents output_content = flowManager.GetConduit(this.outputCell).GetContents(flowManager); float mass_input = Mathf.Min(input_content.mass, this.CurrentFlow * dt); float mass_output = output_content.mass; if (limitPressure) { float mass_limit = Mathf.Max(this.CurrentFlow - mass_output, 0); // mass on output cannot exceed flow setting mass_input = Mathf.Min(mass_input, mass_limit); // set new input mass } if (mass_input > 0f) { float disease_percent = mass_input / input_content.mass; int disease_count = (int)(disease_percent * input_content.diseaseCount); float mass_moved = flowManager.AddElement(this.outputCell, input_content.element, mass_input, input_content.temperature, input_content.diseaseIdx, disease_count); Game.Instance.accumulators.Accumulate(this.flowAccumulator, mass_moved); if (mass_moved > 0f) { flowManager.RemoveElement(this.inputCell, mass_moved); } } this.UpdateAnim(); } }
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(); } }
protected override void ConduitTick(float delta) { if (!AlwaysConsume && !operational.IsOperational) { return; } IConduitFlow conduitFlow = GetConduitManager(); if (ConduitType != ConduitType.Solid) { ConduitFlow mngr = conduitFlow as ConduitFlow; ConduitFlow.ConduitContents contents = mngr.GetContents(portCell); if (contents.mass <= 0) { return; } Element element = ElementLoader.FindElementByHash(contents.element); bool matchesTag = StoreTag == GameTags.Any || element.HasTag(StoreTag); float rateAmount = ConsumptionRate * delta; float maxTake = 0f; float storageContains = storage.MassStored(); float storageLeft = storage.capacityKg - storageContains; float portContains = StoreTag == GameTags.Any ? storageContains : storage.GetMassAvailable(StoreTag); float portLeft = MaximumStore - portContains; maxTake = Mathf.Min(storageLeft, portLeft); maxTake = Mathf.Min(rateAmount, maxTake); float removed = 0f; if (maxTake > 0f) { ConduitFlow.ConduitContents removedContents = mngr.RemoveElement(portCell, maxTake); removed = removedContents.mass; LastConsumedElement = removedContents.element; float ratio = removed / contents.mass; if (!matchesTag) { BuildingHP.DamageSourceInfo damage = new BuildingHP.DamageSourceInfo { damage = 1, source = BUILDINGS.DAMAGESOURCES.BAD_INPUT_ELEMENT, popString = UI.GAMEOBJECTEFFECTS.DAMAGE_POPS.WRONG_ELEMENT }; Trigger((int)GameHashes.DoBuildingDamage, damage); if (WrongElement == WrongElementResult.Dump) { int buildingCell = Grid.PosToCell(_parent.transform.GetPosition()); SimMessages.AddRemoveSubstance(buildingCell, contents.element, CellEventLogger.Instance.ConduitConsumerWrongElement, removed, contents.temperature, contents.diseaseIdx, contents.diseaseIdx); return; } } if (ConduitType == ConduitType.Gas) { if (!element.IsGas) { Debug.LogWarning($"[MultIO] Gas input port attempted to consume non gass: {element.id.ToString()}"); } else { storage.AddGasChunk(element.id, removed, contents.temperature, contents.diseaseIdx, contents.diseaseCount, KeepZeroMassObject, false); } } else if (ConduitType == ConduitType.Liquid) { if (!element.IsLiquid) { Debug.LogWarning($"[MultIO] Liquid input port attempted to consume non liquid: {element.id.ToString()}"); } else { storage.AddLiquid(element.id, removed, contents.temperature, contents.diseaseIdx, contents.diseaseCount, KeepZeroMassObject, false); } } } } else { SolidConduitFlow mngr = conduitFlow as SolidConduitFlow; SolidConduitFlow.ConduitContents contents = mngr.GetContents(portCell); if (contents.pickupableHandle.IsValid() && (AlwaysConsume || operational.IsOperational)) { float stored = StoreTag == GameTags.Any ? storage.MassStored() : storage.GetMassAvailable(StoreTag); float maxStorage = Mathf.Min(storage.capacityKg, MaximumStore); float availableStorage = Mathf.Max(0f, maxStorage - stored); if (availableStorage > 0f) { Pickupable tmp = mngr.GetPickupable(contents.pickupableHandle); bool matchesTag = StoreTag == GameTags.Any || tmp.HasTag(StoreTag); if (matchesTag) { if (tmp.PrimaryElement.Mass <= stored || tmp.PrimaryElement.Mass > maxStorage) { Pickupable take = mngr.RemovePickupable(portCell); if (take != null) { storage.Store(take.gameObject, true); } } } else { Pickupable take = mngr.RemovePickupable(portCell); take.transform.SetPosition(Grid.CellToPos(portCell)); //TODO: Add a PopFX. Likely will not do damage. } } } } }
private void Consume(float dt, ConduitFlow conduit_mgr) { this.IsSatisfied = false; if (this.building.Def.CanMove) { this.utilityCell = this.GetInputCell(); } if (!this.IsConnected) { return; } ConduitFlow.ConduitContents contents = conduit_mgr.GetContents(this.utilityCell); if ((double)contents.mass <= 0.0) { return; } this.IsSatisfied = true; if (!this.alwaysConsume && !this.operational.IsOperational) { return; } float delta = Mathf.Min(this.ConsumptionRate * dt, this.space_remaining_kg); float mass = 0.0f; if ((double)delta > 0.0) { ConduitFlow.ConduitContents conduitContents = conduit_mgr.RemoveElement(this.utilityCell, delta); mass = conduitContents.mass; this.lastConsumedElement = conduitContents.element; } bool flag = ElementLoader.FindElementByHash(contents.element).HasTag(this.capacityTag); if ((double)mass > 0.0 && this.capacityTag != GameTags.Any && !flag) { this.Trigger(-794517298, (object)new BuildingHP.DamageSourceInfo() { damage = 1, source = (string)BUILDINGS.DAMAGESOURCES.BAD_INPUT_ELEMENT, popString = (string)UI.GAMEOBJECTEFFECTS.DAMAGE_POPS.WRONG_ELEMENT }); } if (flag || this.wrongElementResult == ConduitConsumer2.WrongElementResult.Store || (contents.element == SimHashes.Vacuum || this.capacityTag == GameTags.Any)) { if ((double)mass <= 0.0) { return; } int disease_count = (int)((double)contents.diseaseCount * ((double)mass / (double)contents.mass)); Element elementByHash = ElementLoader.FindElementByHash(contents.element); switch (this.conduitType) { case ConduitType.Gas: if (elementByHash.IsGas) { this.storage.AddGasChunk(contents.element, mass, contents.temperature, contents.diseaseIdx, disease_count, this.keepZeroMassObject, false); break; } Debug.LogWarning((object)("Gas conduit consumer consuming non gas: " + elementByHash.id.ToString())); break; case ConduitType.Liquid: if (elementByHash.IsLiquid) { this.storage.AddLiquid(contents.element, mass, contents.temperature, contents.diseaseIdx, disease_count, this.keepZeroMassObject, false); break; } Debug.LogWarning((object)("Liquid conduit consumer consuming non liquid: " + elementByHash.id.ToString())); break; } } else { if ((double)mass <= 0.0 || this.wrongElementResult != ConduitConsumer2.WrongElementResult.Dump) { return; } int disease_count = (int)((double)contents.diseaseCount * ((double)mass / (double)contents.mass)); SimMessages.AddRemoveSubstance(Grid.PosToCell(this.transform.GetPosition()), contents.element, CellEventLogger.Instance.ConduitConsumerWrongElement, mass, contents.temperature, contents.diseaseIdx, disease_count, true, -1); } }
private void Consume(float dt, ConduitFlow conduit_mgr) { if (this.building.Def.CanMove) { this.utilityCell = this.GetInputCell(); } if (this.IsConnected) { ConduitFlow.ConduitContents contents = conduit_mgr.GetContents(this.utilityCell); if (contents.mass > 0f) { this.IsSatisfied = true; if (this.alwaysConsume || this.operational.IsOperational) { float num = (!(this.capacityTag != GameTags.Any)) ? this.storage.MassStored() : this.storage.GetMassAvailable(this.capacityTag); float b = Mathf.Min(this.storage.RemainingCapacity(), this.capacityKG - num); float num2 = this.ConsumptionRate * dt; num2 = Mathf.Min(num2, b); float num3 = 0f; if (num2 > 0f) { num3 = conduit_mgr.RemoveElement(this.utilityCell, num2).mass; } Element element = ElementLoader.FindElementByHash(contents.element); bool flag = element.HasTag(this.capacityTag); if (num3 > 0f && this.capacityTag != GameTags.Any && !flag) { base.Trigger(-794517298, new BuildingHP.DamageSourceInfo { damage = 1, source = BUILDINGS.DAMAGESOURCES.BAD_INPUT_ELEMENT, popString = UI.GAMEOBJECTEFFECTS.DAMAGE_POPS.WRONG_ELEMENT }); } if (flag || this.wrongElementResult == ConduitConsumer.WrongElementResult.Store || contents.element == SimHashes.Vacuum || this.capacityTag == GameTags.Any) { if (num3 > 0f) { int disease_count = (int)((float)contents.diseaseCount * (num3 / contents.mass)); Element element2 = ElementLoader.FindElementByHash(contents.element); ConduitType conduitType = this.conduitType; if (conduitType != ConduitType.Liquid) { if (conduitType == ConduitType.Gas) { if (element2.IsGas) { this.storage.AddGasChunk(contents.element, num3, contents.temperature, contents.diseaseIdx, disease_count, this.keepZeroMassObject, false); } else { global::Debug.LogWarning("Gas conduit consumer consuming non gas: " + element2.id.ToString()); } } } else if (element2.IsLiquid) { this.storage.AddLiquid(contents.element, num3, contents.temperature, contents.diseaseIdx, disease_count, this.keepZeroMassObject, false); } else { global::Debug.LogWarning("Liquid conduit consumer consuming non liquid: " + element2.id.ToString()); } } } else if (num3 > 0f && this.wrongElementResult == ConduitConsumer.WrongElementResult.Dump) { int disease_count2 = (int)((float)contents.diseaseCount * (num3 / contents.mass)); int gameCell = Grid.PosToCell(base.transform.GetPosition()); SimMessages.AddRemoveSubstance(gameCell, contents.element, CellEventLogger.Instance.ConduitConsumerWrongElement, num3, contents.temperature, contents.diseaseIdx, disease_count2, true, -1); } } } else { this.IsSatisfied = false; } } else { this.IsSatisfied = false; } }
private void ConduitUpdate(float dt) { ConduitFlow flowManager = Conduit.GetFlowManager(type); if (!flowManager.HasConduit(inputCell)) { return; } if (IsOperational) { ConduitFlow.ConduitContents contents = flowManager.GetContents(inputCell); if (contents.mass <= 0.0) { return; } ConduitFlow.ConduitContents contentOutput1 = flowManager.GetContents(outputCell); ConduitFlow.ConduitContents contentOutput2 = flowManager.GetContents(secondaryOutputCell); var maxMass = Traverse.Create(flowManager).Field("MaxMass").GetValue <float>(); //type == ConduitType.Liquid ? 10f : 1f; var halfMass = contents.mass / 2f; var willFitInOutput1 = maxMass - contentOutput1.mass; var willFitInOutput2 = maxMass - contentOutput2.mass; float delta1 = 0; float delta2 = 0; if (Math.Abs(willFitInOutput1) < 0.001f && Math.Abs(willFitInOutput2) < 0.001f) { //do nothing } else if (!flowManager.HasConduit(secondaryOutputCell)) { delta1 = flowManager.AddElement(outputCell, contents.element, contents.mass, contents.temperature, contents.diseaseIdx, contents.diseaseCount); } else if (!flowManager.HasConduit(outputCell)) { delta2 = flowManager.AddElement(secondaryOutputCell, contents.element, contents.mass, contents.temperature, contents.diseaseIdx, contents.diseaseCount); } else if (willFitInOutput1 >= halfMass && willFitInOutput2 >= halfMass) { delta1 = flowManager.AddElement(outputCell, contents.element, halfMass, contents.temperature, contents.diseaseIdx, contents.diseaseCount / 2); delta2 = flowManager.AddElement(secondaryOutputCell, contents.element, halfMass, contents.temperature, contents.diseaseIdx, contents.diseaseCount / 2); } else if (willFitInOutput1 < halfMass) { var overflowOutput1 = halfMass - willFitInOutput1; var ratio = (halfMass - overflowOutput1) / halfMass; delta1 = flowManager.AddElement(outputCell, contents.element, halfMass - overflowOutput1, contents.temperature, contents.diseaseIdx, (int)((contents.diseaseCount / 2f) * ratio)); delta2 = flowManager.AddElement(secondaryOutputCell, contents.element, halfMass + overflowOutput1, contents.temperature, contents.diseaseIdx, (int)((contents.diseaseCount / 2f) * (1f / ratio))); } else { var overflowOutput2 = halfMass - willFitInOutput2; var ratio = (halfMass - overflowOutput2) / halfMass; delta1 = flowManager.AddElement(secondaryOutputCell, contents.element, halfMass - overflowOutput2, contents.temperature, contents.diseaseIdx, (int)((contents.diseaseCount / 2f) * ratio)); delta2 = flowManager.AddElement(outputCell, contents.element, halfMass + overflowOutput2, contents.temperature, contents.diseaseIdx, (int)((contents.diseaseCount / 2f) * (1f / ratio))); } flowManager.RemoveElement(inputCell, delta1); flowManager.RemoveElement(inputCell, delta2); Game.Instance.accumulators.Accumulate(accumulator, contents.mass); } }
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); }
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"); }
public HandleVector <int> .Handle Allocate(ConduitType conduit_type, int conduit_idx, HandleVector <int> .Handle conduit_structure_temperature_handle, ref ConduitFlow.ConduitContents contents) { StructureTemperaturePayload payload = GameComps.StructureTemperatures.GetPayload(conduit_structure_temperature_handle); Element element = payload.primaryElement.Element; BuildingDef def = payload.building.Def; float conduit_heat_capacity = def.MassForTemperatureModification * element.specificHeatCapacity; float conduit_thermal_conductivity = element.thermalConductivity * def.ThermalConductivity; int num = ConduitTemperatureManager_Add(contents.temperature, contents.mass, (int)contents.element, payload.simHandleCopy, conduit_heat_capacity, conduit_thermal_conductivity, def.ThermalConductivity < 1f); HandleVector <int> .Handle result = default(HandleVector <int> .Handle); result.index = num; int handleIndex = Sim.GetHandleIndex(num); if (handleIndex + 1 > temperatures.Length) { Array.Resize(ref temperatures, (handleIndex + 1) * 2); Array.Resize(ref conduitInfo, (handleIndex + 1) * 2); } temperatures[handleIndex] = contents.temperature; conduitInfo[handleIndex] = new ConduitInfo { type = conduit_type, idx = conduit_idx }; return(result); }
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)); } } }