I have here a checker which enables and disables alarms [they have scripts which check the values it sets]. Shouldn’t be too bad right, there’s only two?
Progression is Off < Minor Online < Minor + Major Online.
Problem is, the if statement is just a mess. I’m certain I can simplify this but I’m having a mind blank.
Any ideas?
Here’s the two sections. Brace yourself because it’s hideous.
Thermals.UpdateMonitors = function()
local Temp = Core.Temperature
local Pump1 = Core.PumpA
local Pump2 = Core.PumpB
local Fans = Core.Fans
TempMonitor.TempLabel.Text = tostring(Temp).." °C"
if Temp >= MeltdownValue and CurrentState ~= 'Meltdown' then
CurrentState = 'Meltdown'
Thermals.Data.Running = false
CoreEvents.MeltDeltDownYesICanSpeel:Fire("Meltdown")
TempMonitor.StatLabel.Text = "Meltdown"
TempMonitor.StatLabel.TextColor3 = Color3.fromRGB(255, 0, 0)
elseif Temp >= OverheatValue and CurrentState ~= 'Overheat' and Temp <= MeltdownValue then
CurrentState = 'Overheat'
TempMonitor.StatLabel.Text = "Overheat"
TempMonitor.StatLabel.TextColor3 = Color3.fromRGB(255, 85, 0)
elseif Temp >= UnstableValue and CurrentState ~= 'Unstable' and Temp <= OverheatValue then
CurrentState = 'Unstable'
TempMonitor.StatLabel.Text = "Unstable"
TempMonitor.StatLabel.TextColor3 = Color3.fromRGB(255, 170, 0)
elseif Temp <= UnstableValue and CurrentState ~= 'Stable' then
CurrentState = 'Stable'
TempMonitor.StatLabel.Text = "Stable"
TempMonitor.StatLabel.TextColor3 = Color3.fromRGB(0, 170, 0)
end
Thermals.DoAlarmChecks()
end
local Alarm1 = Interfaces:WaitForChild("Alarms"):WaitForChild("Minor")
local Alarm2 = Interfaces:WaitForChild("Alarms"):WaitForChild("Major")
local AlarmStat = 'Stable'
Thermals.DoAlarmChecks = function()
local Temp = Core.Temperature
if Temp >= OverheatValue and AlarmStat ~= "Start_Running_Guys" then
AlarmStat = "Start_Running_Guys"
if AlarmsOn == false then
AlarmsOn = true
CoreEvents.Alarms:Fire("Meltdown")
end
if Alarm1.Active.Value == false or Alarm2.Active.Value == false then
Alarm1.Active.Value = true
Alarm2.Active.Value = true
end
elseif Temp >= UnstableValue and AlarmStat ~= "Unstable" and Temp <= OverheatValue then
AlarmStat = "Unstable"
if AlarmsOn == true then
AlarmsOn = false
CoreEvents.Alarms:Fire("Offline")
end
if Alarm1.Active.Value == false then
Alarm1.Active.Value = true
end
if Alarm2.Active.Value == true then
Alarm2.Active.Value = false
end
elseif Temp <= UnstableValue and AlarmStat ~= "Stable" then
AlarmStat = "Stable"
if AlarmsOn == true then
AlarmsOn = false
CoreEvents.Alarms:Fire("Offline")
end
if Alarm1.Active.Value == true or Alarm2.Active.Value == true then
Alarm1.Active.Value = false
Alarm2.Active.Value = false
end
end
end
AlarmStat is a form of debounce, without it the alarms were toggled every cycle, when they should have remained on.
The two alarms are also defined at the beginning of DoAlarmChecks()
They both contain values called ‘Active’.
Wouldn’t be that worried but this runs every 5 seconds after Temperature is calculated.
I hope this is an a solid optimization for the first script. You’ll get the second one back soon. So, this can either work well or make me look like a fool (because I can’t test the code and perhaps spot obvious mistakes).
Here you go (OOF):
local Thermals = {}
-- All states share the same color function.
local function changeColor(state, color)
TempMonitor.StatLabel.Text = state
TempMonitor.StatLabel.TextColor3 = color
end
Thermals.stateActions = {
['Meltdown'] = function(state)
if (CurrentState ~= state) then
CurrentState = state
Thermals.Data.Running = false
CoreEvents.MeltDeltDownYesICanSpeel:Fire('Meltdown')
changeColor(CurrentState, Color3.fromRGB(255, 0, 0))
end
end;
['Overheat'] = function(state)
if (CurrentState ~= state) then
CurrentState = state
changeColor(CurrentState, Color3.fromRGB(255, 85, 0))
end
end;
['Unstable'] = function(state)
if (CurrentState ~= state) then
CurrentState = state
changeColor(CurrentState, Color3.fromRGB(255, 170, 0))
end
end;
['Stable'] = function(state)
if (CurrentState ~= state) then
CurrentState = state
changeColor(CurrentState, Color3.fromRGB(0, 170, 0))
end
end;
}
-- IMPORTANT: Start with critical temperature, because
-- we are comparing values from highest to lowest!
Thermals.TEMPERATURES = {
{MeltdownValue, Thermals.stateActions.Meltdown};
{OverheatValue, Thermals.stateActions.Overheat};
{UnstableValue, Thermals.stateActions.Unstable};
}
function Thermals.updateMonitors()
local Temp = Core.Temperature
local Pump1 = Core.PumpA
local Pump2 = Core.PumpB
local Fans = Core.Fans
TempMonitor.TempLabel.Text = tostring(Temp).." °C"
for i, state in ipairs(Thermals.TEMPERATURES) do
if (Temp >= state[1]) then
-- Call the method and send it's name as an argument.
state[2](state[1])
else
Thermals.stateActions.Stable('Stable')
end
end
Thermals.DoAlarmChecks()
end
Since these two scripts are actually one script broken into two parts, you can check the states instead of checking temperature values. Each time state changes, alarms adapt.
local Alarm1 = Interfaces:WaitForChild('Alarms'):WaitForChild('Minor')
local Alarm2 = Interfaces:WaitForChild('Alarms'):WaitForChild('Major')
local AlarmStat = 'Stable'
local alarmStates = {
['Meltdown'] = {'Start_Running_Guys'};
['Overheat'] = {'Start_Running_Guys'};
}
function Thermals.DoAlarmChecks(state)
if (AlarmStat ~= state) then
AlarmStat = alarmStates[state] or state
if (AlarmStat == 'Start_Running_Guys') then
if (AlarmsOn) then AlarmsOn = true; CoreEvents.Alarms:Fire('Meltdown') end
Alarm1.Active.Value = true; Alarm2.Active.Value = true
else
AlarmsOn = false
Alarm2.Active.Value = false
CoreEvents.Alarms:Fire('Offline')
if (AlarmStat == 'Unstable') then
Alarm1.Active.Value = true
else
Alarm1.Active.Value = false
end
end
end
end
No problem! Please tell me if something doesn’t work right so we can correct it and correct the post too. Maybe you can optimize this even more. The script eventually got a form of module script, so I suggest you make necessary changes, add a return statement at the end and put the whole code in module script.
I did get one error, but I believe I can quickly fix that since it’s a ‘nil value’. I’ll replace some stuff and get back to you.
Fixed it, was just a lowercase ‘u’ on UpdateMonitors()
The module functions as intended, only bug is that where the status should update to ‘Unstable’ it switched to the temperature unit.
I can fix that though, thank you for the help!
Excuse me for late replying. Now I updated the previous post with the other part of the script. Keep in mind that this can be optimized even further, but better optimization requires changes in your system. For example, is table with alarm states really needed, or can you use values?
I tried some other ways of ‘debouncing’ it, but as there’s two alarms and they’re manipulated in multiple places it immidiately shut off the alarms after enabling them. I’m alright with having longer sections considering this script is the longest one anyway, it’s bound to be memory intensive no matter what I do with it.
Thanks for all the help! I need to use arrays more.
I don’t think your script is as performance demanding as you believe. However, instead of routinely checking the temperature in time intervals, perhaps listen for property changes by using :GetPropertyChangedSignal(). That way your script will only run when temperature changes. Currently, state actions are activated each time loop runs. What you can do alternatively is compare current state and the state temperature allows, and execute the rest of the code only in case state changes.
The temperature is changed within the Thermal System, every 5 seconds. It’s the script I use to calculate the change in temperature when coolant, fan level, etc are factored in.