protected override void OnPrefabInit() { base.OnPrefabInit(); //Add an inert input and output port to the building. Inert ports do not automatically perform any behavior such as automatically taking in, outtputing, or filtering. The behavior is expected to be implemented by the Building when //using inert ports. inputPort = multiIn.AddInputPortInert(conduitType, inputOffset); outputPort = multiOut.AddOutputPortInert(conduitType, outputOffset); //We can use input or output port, since they both give us the same manager. IConduitFlow conduitFlow = inputPort.GetConduitManager(); //Buildings such as pipes, bridges, valves, and shutoffs have a default priority, meaning they execute after consumers but before dispensers. conduitFlow.AddConduitUpdater(OnConduitTick, ConduitFlowPriority.Default); }
private bool OutputPipeIsEmpty() { if (ignoreFullPipe) { return(true); } bool result = true; if (connected) { IConduitFlow conduitFlow = GetConduitFlow(); result = conduitFlow.IsConduitEmpty(utilityCell); } return(result); }
private void UpdateConduitBlockedStatus(bool force = false) { IConduitFlow flowManager = this.GetConduitManager(); bool isEmpty = flowManager.IsConduitEmpty(portCell); if (force || isEmpty != PreviouslyEmpty) { operational.SetFlag(outputEmptyFlag, isEmpty); PreviouslyEmpty = isEmpty; StatusItem conduitBlockedMultiples = Db.Get().BuildingStatusItems.ConduitBlockedMultiples; bool guidExists = ConduitBlockedStatusItemGuid != Guid.Empty; if (isEmpty == guidExists) { ConduitBlockedStatusItemGuid = selectable.ToggleStatusItem(conduitBlockedMultiples, ConduitBlockedStatusItemGuid, !isEmpty); } } }
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. } } } } }
protected override void ConduitTick(float delta) { UpdateConduitBlockedStatus(); bool dispensed = false; if (!operational.IsOperational && !AlwaysDispense) { return; } foreach (GameObject item in storage.items) { if (item.GetComponent <PrimaryElement>()?.Element.id == SimHashes.Water) { item.AddOrGet <Pickupable>(); } } PrimaryElement element = FindSuitableElement(); if (element != null) { element.KeepZeroMassObject = true; IConduitFlow iConduitManager = GetConduitManager(); if (iConduitManager == null) { Debug.LogError($"[MultiIO] OutputPort.ConduitTick(): iConduitManager is null"); } //Solid Conduits do not use the same kind of flow manager, so the code must be separated if (ConduitType == ConduitType.Solid) { SolidConduitFlow solidManager = iConduitManager as SolidConduitFlow; if (solidManager == null) { Debug.LogError($"[MultiIO] OutputPort.ConduitTick(): solidManager is null"); } //Solid conveyor only needs to take elements with a Pikcupable component. The only difference between Water and Bottled Water is a Pikcupable component. Pickupable pickup = element.gameObject.GetComponent <Pickupable>(); if (pickup == null) { return; } if (pickup.PrimaryElement.Mass > SolidOutputMax) { pickup = pickup.Take(SolidOutputMax); } solidManager.AddPickupable(portCell, pickup); dispensed = true; } else if (ConduitType == ConduitType.Liquid || ConduitType == ConduitType.Gas) { ConduitFlow conduitManager = iConduitManager as ConduitFlow; if (conduitManager == null) { Debug.LogError($"[MutiIO] OutputPort.ConduitTick(): conduitManager is null"); return; } float amountMoved = conduitManager.AddElement(portCell, element.ElementID, element.Mass, element.Temperature, element.DiseaseIdx, element.DiseaseCount); if (amountMoved > 0f) { float movedRatio = amountMoved / element.Mass; int movedDisease = (int)(movedRatio * (float)element.DiseaseCount); element.ModifyDiseaseCount(-movedDisease, "ConduitDispenser.ConduitUpdate"); element.Mass -= amountMoved; _parent.Trigger((int)GameHashes.OnStorageChange, element.gameObject); dispensed = true; } } } isDispensing = dispensed; }