DCS_MissionDev/DCS_Caucasus/F99th-Battle of Gori/F99thServiceMonitorV1.4.2.lua
2024-11-12 14:18:28 -06:00

464 lines
19 KiB
Lua

--Verion 1.4.2
ProviderChecker = {}
-- Best to leave this on for the most part.
ProviderChecker.TankerFuelChecking = true
-- Only necessary to set if you don't set them to invicible
ProviderChecker.TankerKilledTimer = 60
-- Good to set even if you are using Fuel Check, in case it lands for some weird AI reason.
ProviderChecker.TankerRTBTimer = 60
-- If you want it to respawn when fuel state reaches 20%, instead of having it RTB all the way to base.
ProviderChecker.AWACFuelChecking = true
-- Killed Timer is the time delay to respawn for killed in seconds. Minimum of 5 seconds, anything less will default to 5 seconds
ProviderChecker.AWACKilledTimer = 600
-- RTB Timer is time delay to respawn from landing. Can be 0
ProviderChecker.AWACRTBTimer = 60
ProviderChecker.AWACSeventHandler = {}
ProviderChecker.TankereventHandler = {}
ProviderChecker.TankerTable = {}
ProviderChecker.AwacsTable = {}
ProviderChecker.TankerRefuelingCountBlueFor = 0
ProviderChecker.TankerRefuelingCountRedFor = 0
--Tankers waiting for respawn
ProviderChecker.TankerStandbyTable= {}
function ProviderChecker.TankerRadioStatus(radio_coalition)
local coalition_side = ""
if radio_coalition == 1 then
coalition_side = coalition_side .. "red"
elseif radio_coalition == 2 then
coalition_side = coalition_side .. "blue"
end
local tanker_status_start = "===========================\n"
local tanker_status_end = "==========================="
local tanker_status_mid = ""
for fueler, params in pairs(ProviderChecker.TankerTable) do
if params.coalition == coalition_side then
if params.has_tasking then
local m_tanker_id = Group.getByName(params.name)
local m_tanker_radio = params.radio_freqeuncy
local m_tanker_units = m_tanker_id:getUnits()
local m_tanker_unit = m_tanker_units[1]
local m_tanker_callsign = m_tanker_unit:getCallsign()
local m_tanker_channel = params.channel
local m_tanker_mode = params.modeChannel
local m_tanker_ac_type = m_tanker_unit:getTypeName()
tanker_status_mid = tanker_status_mid .. "Tanker: " .. m_tanker_callsign .. " Radio: " .. m_tanker_radio ..
" TACAN: " .. m_tanker_channel .. m_tanker_mode .. " Aircraft: " .. m_tanker_ac_type .. "\n"
else
local m_tanker_id = Group.getByName(params.name)
local m_tanker_radio = params.radio_freqeuncy
local m_tanker_units = m_tanker_id:getUnits()
local m_tanker_unit = m_tanker_units[1]
local m_tanker_callsign = m_tanker_unit:getCallsign()
tanker_status_mid = tanker_status_mid .. "Tanker: " .. m_tanker_callsign .. " Radio: " .. m_tanker_radio ..
" TACAN: N/A" .. " Aircraft: " .. m_tanker_ac_type .. "\n"
end
end
end
local out_message = tanker_status_start .. tanker_status_mid .. tanker_status_end
trigger.action.outTextForCoalition(radio_coalition, out_message, 30, true)
end
function ProviderChecker.RefreshTACAN(_nil,time)
for fueler, params in pairs(ProviderChecker.TankerTable) do
if params.has_tasking then
local tanker_id = Group.getByName(params.name)
if tanker_id then
local tanker_controller = tanker_id:getController()
local tanker_tacan = {
id = 'ActivateBeacon',
params = {
["type"] = params.type,
["AA"] = params.AA,
["unitId"] = tanker_id,
["modeChannel"] = params.modeChannel,
["channel"] = params.channel,
["system"] = params.system,
["callsign"] = params.callsign,
["bearing"] = params.bearing,
["frequency"] = params.frequency,
}
}
tanker_controller:setCommand(tanker_tacan)
end
end
end
return time + 10
end
--Will Eventually consoldate these to one function. Pass type (awacs or tanker) as argument.
function ProviderChecker.SpawnNewTanker(_unit, time)
--respawn uses the same name, and tankers are tracked by name instead of ID. Will change this for AWACS in future update.
NewGroup = mist.respawnGroup(_unit,true)
NewName = NewGroup.units[1].name
NewUnit = Unit.getByName(NewName)
tanker_controller = NewUnit:getController()
for tanker, params in pairs(ProviderChecker.TankerTable) do
if params.name == NewName then
local frequency = tonumber(params.radio_freqeuncy) * 1000000
SetFrequency = {
id = 'SetFrequency',
params = {
frequency = frequency,
modulation = 0,
}
}
tanker_controller:setCommand(SetFrequency)
trigger.action.outTextForCoalition(NewUnit:getCoalition(),"Tanker " ..NewUnit:getCallsign().. " is back online!", 10, false)
end
end
return nil
end
function ProviderChecker.SpawnNewAwacs(_unit, time)
NewGroup = mist.respawnGroup(_unit,true)
NewName = NewGroup.units[1].name
NewUnit = Unit.getByName(NewName)
awacs_controller = NewUnit:getController()
for awacs, params in pairs(ProviderChecker.AwacsTable) do
if params.name == NewName then
local frequency = tonumber(params.radio_freqeuncy) * 1000000
SetFrequency = {
id = 'SetFrequency',
params = {
frequency = frequency,
modulation = 0,
}
}
awacs_controller:setCommand(SetFrequency)
trigger.action.outTextForCoalition(NewUnit:getCoalition(),"AWACS " .. NewUnit:getCallsign() .. " is back online!", 10, false)
end
end
return nil
end
--due to how scheduled functions work, I need to create a class to handle this. Will upgrade later next revision.
function ProviderChecker.checkTankerFuel(_nil,time)
for fueler, params in pairs(ProviderChecker.TankerTable) do
local fueler_group_name = params.name
local fueler_group = Group.getByName(fueler_group_name)
if fueler_group then
local fueler_units = fueler_group:getUnits()
local fueler_id = fueler_units[1]
local fueler_fuel = fueler_id:getFuel()
if fueler_fuel < 0.20 then
if params.coalition == "blue" then
if ProviderChecker.TankerRefuelingCountBlueFor < 1 then
trigger.action.outTextForCoalition(
fueler_id:getCoalition(),
"Tanker " .. fueler_id:getCallsign() .. " Is out of Fuel. Respawning in 5 seconds",
10
)
timer.scheduleFunction(ProviderChecker.SpawnNewTanker, fueler_group_name, timer.getTime() + 5)
elseif ProviderChecker.TankerRefuelingCountBlueFor > 0 then
trigger.action.outTextForCoalition(
fueler_id:getCoalition(),
"Tanker " .. fueler_id:getCallsign() .. " fuel at less than 20%. Will respawn when no aircraft are refueling",
10
)
end
elseif params.coalition == "red" then
if ProviderChecker.TankerRefuelingCountRedFor < 1 then
trigger.action.outTextForCoalition(
fueler_id:getCoalition(),
"Tanker " .. fueler_id:getCallsign() .. " Is out of Fuel. Respawning in 5 seconds",
10
)
timer.scheduleFunction(ProviderChecker.SpawnNewTanker, fueler_group_name, timer.getTime() + 5)
elseif ProviderChecker.TankerRefuelingCountRedFor > 0 then
trigger.action.outTextForCoalition(
fueler_id:getCoalition(),
"Tanker " .. fueler_id:getCallsign() .. " fuel at less than 20%. Will respawn when no aircraft are refueling",
10
)
end
end
elseif fueler_fuel < 0.22 then
trigger.action.outTextForCoalition(
fueler_id:getCoalition(),
"Tanker " .. fueler_id:getCallsign() .. " at 25%. Will respawn at 20% if no aircraft are refueling",
10
)
end
end
end
return time + 120
end
function ProviderChecker.checkAWACSFuel(_nil,time)
--Due to the respawn and scheduledFunction limitations, Checking Refuel requires imediate respawn, else it would loop to respawn again and again.
for awacs, params in pairs(ProviderChecker.AwacsTable) do
local awacs_group_name = params.name
local awacs_group = Group.getByName(awacs_group_name)
if awacs_group then
local awacs_units = awacs_group:getUnits()
local awacs_id = awacs_units[1]
local awacs_fuel = awacs_id:getFuel()
if awacs_fuel < 0.30 then
if params.coalition == "blue" then
trigger.action.outTextForCoalition(
awacs_id:getCoalition(),
"AWACS " .. awacs_id:getCallsign() .. " Is out of Fuel. Respawning in 5 seconds",
10
)
timer.scheduleFunction(ProviderChecker.SpawnNewAwacs, awacs_group_name, timer.getTime() + 5)
elseif params.coalition == "red" then
trigger.action.outTextForCoalition(
awacs_id:getCoalition(),
"AWACS " .. awacs_id:getCallsign() .. " Is out of Fuel. Respawning in 5 seconds",
10
)
timer.scheduleFunction(ProviderChecker.SpawnNewAwacs, awacs_group_name, timer.getTime() + 5)
end
end
end
end
return time + 120
end
function ProviderChecker.TankereventHandler:onEvent(_event)
-- Adds up the number of units taking fuel because the event handler is based on unit taking fuel, not giving fuel
-- Solution to this later will be check nearest unit of type tanker and create a "class" out of that.
if (_event.id == 7) and _event.initiator then
local refueling_unit = _event.initiator
local refueling_unit_coalition = refueling_unit:getCoalition()
if refueling_unit_coalition == 2 then
ProviderChecker.TankerRefuelingCountBlueFor = ProviderChecker.TankerRefuelingCountBlueFor + 1
elseif refueling_unit_coalition == 1 then
ProviderChecker.TankerRefuelingCountRedFor = ProviderChecker.TankerRefuelingCountRedFor + 1
end
end
-- Removes the number of units taking fuel
if (_event.id == 14) and _event.initiator then
local refueling_unit = _event.initiator
local refueling_unit_coalition = refueling_unit:getCoalition()
if refueling_unit_coalition == 2 then
ProviderChecker.TankerRefuelingCountBlueFor = ProviderChecker.TankerRefuelingCountBlueFor - 1
elseif refueling_unit_coalition == 1 then
ProviderChecker.TankerRefuelingCountRedFor = ProviderChecker.TankerRefuelingCountRedFor - 1
end
end
-- Checks if tanker landed.
if (_event.id == 4) and _event.initiator then
if _event.initiator then
local LandedUnit = _event.initiator
local LandedUnitName = LandedUnit:getName()
local LandedUnitInfo = Unit.getGroup(LandedUnit)
local LandedUnitGroupName = LandedUnitInfo:getName()
for fueler, params in pairs(ProviderChecker.TankerTable) do
if LandedUnitGroupName == params.name then
if ProviderChecker.TankerRTBTimer > 5 then
trigger.action.outTextForCoalition(
LandedUnit:getCoalition(),
"Tanker " .. LandedUnit:getCallsign() .. " Landed - Respawning in " .. (ProviderChecker.TankerRTBTimer / 60) .. " minutes", 10, false)
timer.scheduleFunction(ProviderChecker.SpawnNewTanker, LandedUnitGroupName, timer.getTime() + ProviderChecker.TankerRTBTimer)
else
trigger.action.outTextForCoalition(
LandedUnit:getCoalition(),
"Tanker " .. LandedUnit:getCallsign() .. " Landed - Respawning", 10, false)
timer.scheduleFunction(ProviderChecker.SpawnNewTanker, LandedUnitGroupName, timer.getTime() + 5)
end
end
end
end
end
if (_event.id == 5) and _event.initiator then
local DeadUnit = _event.initiator
local DeadUnitName = DeadUnit:getName()
local DeadUnitInfo = Unit.getGroup(DeadUnit)
local DeadUnitGroupName = DeadUnitInfo:getName()
for fueler, params in pairs(ProviderChecker.TankerTable) do
if DeadUnitGroupName == params.name then
if ProviderChecker.TankerKilledTimer > 5 then
trigger.action.outTextForCoalition(
DeadUnit:getCoalition(),
"Tanker " .. DeadUnit:getCallsign() .. " has crashed! Replacement will be on station in " .. (ProviderChecker.TankerKilledTimer / 60) .. " minutes", 10, false)
timer.scheduleFunction(ProviderChecker.SpawnNewTanker, DeadUnitGroupName, timer.getTime() + ProviderChecker.TankerKilledTimer)
else
trigger.action.outTextForCoalition(
DeadUnit:getCoalition(),
"Tanker " .. LandedUnit:getCallsign() .. " has crashed! Replacement will be on station in 5 Seconds", 10,false)
timer.scheduleFunction(ProviderChecker.SpawnNewTanker, DeadUnitGroupName, timer.getTime() + 5)
end
end
end
end
end
function ProviderChecker.AWACSeventHandler:onEvent(_event)
-- Checks if tanker landed.
if (_event.id == 4) and _event.initiator then
local LandedUnit = _event.initiator
local LandedUnitName = LandedUnit:getName()
local LandedUnitInfo = Unit.getGroup(LandedUnit)
local LandedUnitGroupName = LandedUnitInfo:getName()
for awacs, params in pairs(ProviderChecker.AwacsTable) do
if LandedUnitGroupName == params.name then
if ProviderChecker.AWACRTBTimer > 5 then
trigger.action.outTextForCoalition(
LandedUnit:getCoalition(),
"AWACS " .. LandedUnit:getCallsign() .. " Landed - Respawning in " .. (ProviderChecker.AWACRTBTimer / 60) .. " minutes", 10, false)
timer.scheduleFunction(ProviderChecker.SpawnNewAwacs, LandedUnitGroupName, timer.getTime() + ProviderChecker.AWACRTBTimer)
else
trigger.action.outTextForCoalition(
LandedUnit:getCoalition(),
"AWACS " .. LandedUnit:getCallsign() .. " Landed - Respawning", 10, false)
timer.scheduleFunction(ProviderChecker.SpawnNewAwacs, LandedUnitGroupName, timer.getTime() + 5)
end
end
end
end
if (_event.id == 5) and _event.initiator then
local DeadUnit = _event.initiator
local DeadUnitName = DeadUnit:getName()
local DeadUnitInfo = Unit.getGroup(DeadUnit)
local DeadUnitGroupName = DeadUnitInfo:getName()
for awacs, params in pairs(ProviderChecker.AwacsTable) do
if DeadUnitGroupName == params.name then
if ProviderChecker.AWACKilledTimer > 5 then
trigger.action.outTextForCoalition(
DeadUnit:getCoalition(),
"AWACS " .. DeadUnit:getCallsign() .. " has been shot down! Replacement will be on station in " .. (ProviderChecker.AWACKilledTimer / 60) .. " minutes", 10, false)
timer.scheduleFunction(ProviderChecker.SpawnNewAwacs, DeadUnitGroupName, timer.getTime() + ProviderChecker.AWACKilledTimer)
else
trigger.action.outTextForCoalition(
DeadUnit:getCoalition(),
"AWACS " .. DeadUnit:getCallsign() .. " has been shot down! Replacement will be on station in 5 Seconds", 10,false)
timer.scheduleFunction(ProviderChecker.SpawnNewAwacs, DeadUnitGroupName, timer.getTime() + 5)
end
end
end
end
end
-- function ProviderChecker.ServiceCheckerMsg()
function ProviderChecker.GetServicesList()
-- You can -only- get TACAN data from the mission file. So since MIST respawn uses the same TACANs on respawn,
-- I can pull from the mission file and refresh that way
for coa_name, coa_data in pairs(env.mission.coalition) do
if (coa_name == 'red' or coa_name == 'blue') and type(coa_data) == 'table' then
if coa_data.country then --there is a country table
for cntry_id, cntry_data in pairs(coa_data.country) do
for obj_type_name, obj_type_data in pairs(cntry_data) do
if obj_type_name == "plane" then
if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then --there's a group!
for group_num, group_data in pairs(obj_type_data.group) do
group_Id = group_data.groupId
group_radio = group_data.frequency
group_name = env.getValueDictByKey(group_data.name)
if group_data.task == "Refueling" then
if group_data["units"][1]["type"] ~= "IL-78M" then
if group_data.tasks and group_data.tasks.parmas then
for tasks_id, tasks_data in pairs(group_data.tasks) do
if tasks_data.params and tasks_data.params.action and tasks_data.params.action.params then
tasks_data.params.action.params["coalition"] = coa_name
tasks_data.params.action.params["radio_freqeuncy"] = group_radio
tasks_data.params.action.params["name"] = group_name
tasks_data.params.action.params["has_tasking"] = true
ProviderChecker.TankerTable[group_Id] = tasks_data.params.action.params
end --if task_data.params
end -- for tasks_id, tasks_data
-- Because for some weird ass reason, the tasks will be blank so I need to pull them from waypoints instead
elseif group_data.route.points then
for point_id, point_params in pairs(group_data.route.points) do
if point_params.task then
for tasks_id, tasks_data in pairs(point_params.task.params.tasks) do
if tasks_data.params and tasks_data.params.action and tasks_data.params.action.id == "ActivateBeacon" then
tasks_data.params.action.params["coalition"] = coa_name
tasks_data.params.action.params["radio_freqeuncy"] = group_radio
tasks_data.params.action.params["name"] = group_name
tasks_data.params.action.params["has_tasking"] = true
ProviderChecker.TankerTable[group_Id] = tasks_data.params.action.params
end -- if tasks_data.params and
end -- for tasks_id, tasks_data in
end --if point_params.task
end -- for point_id, point_params
end -- if group_data.tasks then
else
ProviderChecker.TankerTable[group_Id] = {}
ProviderChecker.TankerTable[group_Id]["coalition"] = coa_name
ProviderChecker.TankerTable[group_Id]["radio_freqeuncy"] = group_radio
ProviderChecker.TankerTable[group_Id]["name"] = group_name
ProviderChecker.TankerTable[group_Id]["has_tasking"] = false
end -- group_data["units"][1]["type"] ~= "IL-78M" then
elseif group_data.task == "AWACS" then
ProviderChecker.AwacsTable[group_Id] = {}
ProviderChecker.AwacsTable[group_Id]["coalition"] = coa_name
ProviderChecker.AwacsTable[group_Id]["radio_freqeuncy"] = group_radio
ProviderChecker.AwacsTable[group_Id]["name"] = group_name
ProviderChecker.AwacsTable[group_Id]["modeChannel"] = "N/A"
ProviderChecker.AwacsTable[group_Id]["callsign"] = "N/A"
end --if group_data.tas == "Refueling then"
end --for group_num, group_data in pairs(obj_type_data.group) do
end --if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then
end --if obj_type_name == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" or obj_type_name == "static" then
end --for obj_type_name, obj_type_data in pairs(cntry_data) do
end --for cntry_id, cntry_data in pairs(coa_data.country) do
end --if coa_data.country then --there is a country table
end --if coa_name == 'red' or coa_name == 'blue' and type(coa_data) == 'table' then
end --for coa_name, coa_data in pairs(mission.coalition) do
end
world.addEventHandler(ProviderChecker.AWACSeventHandler)
env.info("F99th AWACS Checker event handler added")
world.addEventHandler(ProviderChecker.TankereventHandler)
env.info("F99th Tanker Checker event handler added")
ProviderChecker.GetServicesList()
timer.scheduleFunction(ProviderChecker.RefreshTACAN, nil, timer.getTime() + 10)
missionCommands.addCommandForCoalition(2,"Get Tanker Info",nil, ProviderChecker.TankerRadioStatus,2)
missionCommands.addCommandForCoalition(1,"Get Tanker Info",nil, ProviderChecker.TankerRadioStatus,1)
if ProviderChecker.TankerFuelChecking then
timer.scheduleFunction(ProviderChecker.checkTankerFuel, nil, timer.getTime() + 120)
end
if ProviderChecker.AWACFuelChecking then
timer.scheduleFunction(ProviderChecker.checkAWACSFuel, nil, timer.getTime() + 120)
end