//a recursive function that goes through all the junctions and adds up //all the generated/consumed power of the constructions connected to the grid private void CheckJunctions(float deltaTime, bool increaseUpdateCount = true, bool inputOnly = false) { if (increaseUpdateCount) { updateCount = 1; } connectedList.Add(this); ApplyStatusEffects(ActionType.OnActive, deltaTime, null); foreach (Connection c in PowerConnections) { var recipients = c.Recipients; foreach (Connection recipient in recipients) { if (recipient == null) { continue; } Item it = recipient.Item; if (it == null) { continue; } if (it.Condition <= 0.0f) { continue; } foreach (Powered powered in it.GetComponents <Powered>()) { if (powered == null || !powered.IsActive) { continue; } if (connectedList.Contains(powered)) { continue; } PowerTransfer powerTransfer = powered as PowerTransfer; if (powerTransfer != null) { if (this is RelayComponent == powerTransfer is RelayComponent) { if (!powerTransfer.CanTransfer) { continue; } powerTransfer.CheckJunctions(deltaTime, increaseUpdateCount, inputOnly); } else { if (!powerTransfer.CanTransfer) { continue; } powerTransfer.CheckJunctions(deltaTime, false, !c.IsOutput || inputOnly); } continue; } PowerContainer powerContainer = powered as PowerContainer; if (powerContainer != null) { if (recipient.Name == "power_in") { if (!inputOnly) { fullLoad += powerContainer.CurrPowerConsumption; } } else { fullPower += powerContainer.CurrPowerOutput; } } else { connectedList.Add(powered); //positive power consumption = the construction requires power -> increase load if (powered.CurrPowerConsumption > 0.0f) { if (!inputOnly) { fullLoad += powered.CurrPowerConsumption; } } else if (powered.CurrPowerConsumption < 0.0f) //negative power consumption = the construction is a //generator/battery or another junction box { fullPower -= powered.CurrPowerConsumption; } } } } } }
public override void Update(float deltaTime, Camera cam) { isRunning = true; float chargeRatio = charge / capacity; float gridPower = 0.0f; float gridLoad = 0.0f; foreach (Connection c in item.Connections) { if (!c.IsPower || !c.IsOutput) { continue; } foreach (Connection c2 in c.Recipients) { if (c2.Item.Condition <= 0.0f) { continue; } PowerTransfer pt = c2.Item.GetComponent <PowerTransfer>(); if (pt == null) { foreach (Powered powered in c2.Item.GetComponents <Powered>()) { if (!powered.IsActive) { continue; } gridLoad += powered.CurrPowerConsumption; } continue; } if (!pt.IsActive || !pt.CanTransfer) { continue; } gridPower -= pt.CurrPowerConsumption; gridLoad += pt.PowerLoad; } } if (chargeRatio > 0.0f) { ApplyStatusEffects(ActionType.OnActive, deltaTime, null); } if (charge >= capacity) { //rechargeVoltage = 0.0f; charge = capacity; CurrPowerConsumption = 0.0f; } else { currPowerConsumption = MathHelper.Lerp(currPowerConsumption, rechargeSpeed, 0.05f); Charge += currPowerConsumption * Math.Min(Voltage, 1.0f) / 3600.0f; } if (charge <= 0.0f) { CurrPowerOutput = 0.0f; charge = 0.0f; return; } //output starts dropping when the charge is less than 10% float maxOutputRatio = 1.0f; if (chargeRatio < 0.1f) { maxOutputRatio = Math.Max(chargeRatio * 10.0f, 0.0f); } CurrPowerOutput += (gridLoad - gridPower) * deltaTime; float maxOutput = Math.Min(MaxOutPut * maxOutputRatio, gridLoad); CurrPowerOutput = MathHelper.Clamp(CurrPowerOutput, 0.0f, maxOutput); Charge -= CurrPowerOutput / 3600.0f; item.SendSignal(0, ((int)Math.Round(Charge)).ToString(), "charge", null); item.SendSignal(0, ((int)Math.Round((Charge / capacity) * 100)).ToString(), "charge_%", null); item.SendSignal(0, ((int)Math.Round((RechargeSpeed / maxRechargeSpeed) * 100)).ToString(), "charge_rate", null); }
public override void Update(float deltaTime, Camera cam) { RefreshConnections(); if (!CanTransfer) { return; } if (isBroken) { SetAllConnectionsDirty(); isBroken = false; } if (updateCount > 0) { //this junction box has already been updated this frame updateCount--; return; } //reset and recalculate the power generated/consumed //by the constructions connected to the grid fullPower = 0.0f; fullLoad = 0.0f; connectedList.Clear(); updateCount = 0; CheckJunctions(deltaTime); foreach (Powered p in connectedList) { PowerTransfer pt = p as PowerTransfer; if (pt == null || pt.updateCount == 0) { continue; } if (pt is RelayComponent != this is RelayComponent) { continue; } pt.powerLoad += (fullLoad - pt.powerLoad) / inertia; pt.currPowerConsumption += (-fullPower - pt.currPowerConsumption) / inertia; float voltage = fullPower / Math.Max(fullLoad, 1.0f); if (this is RelayComponent) { voltage = Math.Min(voltage, 1.0f); } pt.Item.SendSignal(0, "", "power", null, voltage); pt.Item.SendSignal(0, "", "power_out", null, voltage); //Nilmod Regenerate the health of a damaged junction over time if (GameMain.NilMod.ElectricalRegenerateCondition && pt.item.Condition > 0f && pt.item.Condition < 100f) { pt.item.Condition += deltaTime * GameMain.NilMod.ElectricalRegenAmount; } //relays don't blow up if the power is higher than load, only if the output is high enough //(i.e. enough power passing through the relay) if (this is RelayComponent) { continue; } if (-pt.currPowerConsumption < Math.Max(pt.powerLoad * Rand.Range(GameMain.NilMod.ElectricalOverloadVoltRangeMin, GameMain.NilMod.ElectricalOverloadVoltRangeMax), GameMain.NilMod.ElectricalOverloadMinPower)) { continue; } //damage the item if voltage is too high //(except if running as a client) if (GameMain.Client != null) { continue; } float prevCondition = pt.item.Condition; pt.item.Condition -= deltaTime * GameMain.NilMod.ElectricalOverloadDamage; if (pt.item.Condition <= 0.0f && prevCondition > 0.0f) { #if CLIENT sparkSounds[Rand.Int(sparkSounds.Length)].Play(1.0f, 600.0f, pt.item.WorldPosition); Vector2 baseVel = Rand.Vector(300.0f); for (int i = 0; i < 10; i++) { var particle = GameMain.ParticleManager.CreateParticle("spark", pt.item.WorldPosition, baseVel + Rand.Vector(100.0f), 0.0f, item.CurrentHull); if (particle != null) { particle.Size *= Rand.Range(0.5f, 1.0f); } } #endif if ((GameMain.NilMod.ElectricalOverloadFiresChance / 100f) > 0.0f && Rand.Int((int)(1.0f / (GameMain.NilMod.ElectricalOverloadFiresChance / 100f))) == 1) { new FireSource(pt.item.WorldPosition); } } } updateCount = 0; }
public override void Update(float deltaTime, Camera cam) { if (GameMain.Server != null && nextServerLogWriteTime != null) { if (Timing.TotalTime >= (float)nextServerLogWriteTime) { GameServer.Log(lastUser + " adjusted reactor settings: " + "Temperature: " + (int)temperature + ", Fission rate: " + (int)fissionRate + ", Cooling rate: " + (int)coolingRate + ", Cooling rate: " + coolingRate + ", Shutdown temp: " + shutDownTemp + (autoTemp ? ", Autotemp ON" : ", Autotemp OFF"), ServerLog.MessageType.ItemInteraction); nextServerLogWriteTime = null; lastServerLogWriteTime = (float)Timing.TotalTime; } } ApplyStatusEffects(ActionType.OnActive, deltaTime, null); fissionRate = Math.Min(fissionRate, AvailableFuel); float heat = 80 * fissionRate * (AvailableFuel / 2000.0f); float heatDissipation = 50 * coolingRate + Math.Max(ExtraCooling, 5.0f); float deltaTemp = (((heat - heatDissipation) * 5) - temperature) / 10000.0f; Temperature = temperature + deltaTemp; if (temperature > fireTemp && temperature - deltaTemp < fireTemp) { #if CLIENT Vector2 baseVel = Rand.Vector(300.0f); for (int i = 0; i < 10; i++) { var particle = GameMain.ParticleManager.CreateParticle("spark", item.WorldPosition, baseVel + Rand.Vector(100.0f), 0.0f, item.CurrentHull); if (particle != null) { particle.Size *= Rand.Range(0.5f, 1.0f); } } #endif new FireSource(item.WorldPosition); } if (temperature > meltDownTemp) { MeltDown(); return; } load = 0.0f; List <Connection> connections = item.Connections; if (connections != null && connections.Count > 0) { foreach (Connection connection in connections) { if (!connection.IsPower) { continue; } foreach (Connection recipient in connection.Recipients) { Item it = recipient.Item as Item; if (it == null) { continue; } PowerTransfer pt = it.GetComponent <PowerTransfer>(); if (pt == null) { continue; } load = Math.Max(load, pt.PowerLoad); } } } //item.Condition -= temperature * deltaTime * 0.00005f; if (temperature > shutDownTemp) { CoolingRate += 0.5f; FissionRate -= 0.5f; } else if (autoTemp) { //take deltaTemp into account to slow down the change in temperature when getting closer to the desired value float target = temperature + deltaTemp * 100.0f; //-1.0f in order to gradually turn down both rates when the target temperature is reached FissionRate += (MathHelper.Clamp(load - target, -10.0f, 10.0f) - 1.0f) * deltaTime; CoolingRate += (MathHelper.Clamp(target - load, -5.0f, 5.0f) - 1.0f) * deltaTime; } //the power generated by the reactor is equal to the temperature currPowerConsumption = -temperature * powerPerTemp; if (item.CurrentHull != null) { //the sound can be heard from 20 000 display units away when running at full power item.CurrentHull.SoundRange = Math.Max(temperature * 2, item.CurrentHull.AiTarget.SoundRange); } #if CLIENT UpdateGraph(deltaTime); #endif ExtraCooling = 0.0f; AvailableFuel = 0.0f; item.SendSignal(0, ((int)temperature).ToString(), "temperature_out", null); sendUpdateTimer = Math.Max(sendUpdateTimer - deltaTime, 0.0f); if (unsentChanges && sendUpdateTimer <= 0.0f) { if (GameMain.Server != null) { item.CreateServerEvent(this); } #if CLIENT else if (GameMain.Client != null) { item.CreateClientEvent(this); } #endif sendUpdateTimer = NetworkUpdateInterval; unsentChanges = false; } }