From ff98559fb6c5c51c85234d89916c60bc3e3f18ad Mon Sep 17 00:00:00 2001 From: Jonathan Toppins Date: Fri, 18 Aug 2023 16:30:49 -0400 Subject: [PATCH] settings: refactor theater settings Add the ability to have per airframe payload limits and ato. Also, extend the ui table to support various unit settings: pressure, altitude, speed, temperature, and position coordinates format. --- .../settings/airframecost.cfg | 3 + .../Caucasus_dctdemo/settings/ato.cfg | 3 + .../settings/payloadlimits.cfg | 8 +- .../theaters/Caucasus_dctdemo/settings/ui.cfg | 13 +- src/dct/data/playerui.lua | 119 +++++++ src/dct/data/restrictedweapons.lua | 15 + src/dct/libs/utils.lua | 17 +- src/dct/settings/theater.lua | 313 ++++++++++-------- src/dct/templates/checkers/CheckPlayer.lua | 81 ++++- src/dct/templates/checkers/CheckSquadron.lua | 17 +- src/dct/ui/human.lua | 32 +- tests/test-configs.lua | 2 +- 12 files changed, 458 insertions(+), 165 deletions(-) create mode 100644 data/DCT/theaters/Caucasus_dctdemo/settings/airframecost.cfg create mode 100644 data/DCT/theaters/Caucasus_dctdemo/settings/ato.cfg create mode 100644 src/dct/data/playerui.lua create mode 100644 src/dct/data/restrictedweapons.lua diff --git a/data/DCT/theaters/Caucasus_dctdemo/settings/airframecost.cfg b/data/DCT/theaters/Caucasus_dctdemo/settings/airframecost.cfg new file mode 100644 index 00000000..f89bec1d --- /dev/null +++ b/data/DCT/theaters/Caucasus_dctdemo/settings/airframecost.cfg @@ -0,0 +1,3 @@ +cost = { + ["FA-18C_hornet"] = 5, +} diff --git a/data/DCT/theaters/Caucasus_dctdemo/settings/ato.cfg b/data/DCT/theaters/Caucasus_dctdemo/settings/ato.cfg new file mode 100644 index 00000000..a980417f --- /dev/null +++ b/data/DCT/theaters/Caucasus_dctdemo/settings/ato.cfg @@ -0,0 +1,3 @@ +ato = { + ["FA-18C_hornet"] = { "CAS", "cap", "strike", }, +} diff --git a/data/DCT/theaters/Caucasus_dctdemo/settings/payloadlimits.cfg b/data/DCT/theaters/Caucasus_dctdemo/settings/payloadlimits.cfg index 7d4f711f..20d021a0 100644 --- a/data/DCT/theaters/Caucasus_dctdemo/settings/payloadlimits.cfg +++ b/data/DCT/theaters/Caucasus_dctdemo/settings/payloadlimits.cfg @@ -1,2 +1,6 @@ -aa = 20 -ag = 60 \ No newline at end of file +payloadlimits = { + ["FA-18C_hornet"] = { + aa = 20, + ag = 60, + }, +} \ No newline at end of file diff --git a/data/DCT/theaters/Caucasus_dctdemo/settings/ui.cfg b/data/DCT/theaters/Caucasus_dctdemo/settings/ui.cfg index ae1247be..cad3aeda 100644 --- a/data/DCT/theaters/Caucasus_dctdemo/settings/ui.cfg +++ b/data/DCT/theaters/Caucasus_dctdemo/settings/ui.cfg @@ -1,9 +1,6 @@ -gridfmt = { - ["Ka-50"] = "dms", -} - -ato = { - ["F-16C_50"] = {"strike", "cap"}, - ["A-10A"] = {"cas",}, - --["F-5E"] = {"novalidmission",}, +ui = { + ["FA-18C_hornet"] = { + gridfmt = "dms", + altfmt = "meter", + }, } diff --git a/src/dct/data/playerui.lua b/src/dct/data/playerui.lua new file mode 100644 index 00000000..4141f49b --- /dev/null +++ b/src/dct/data/playerui.lua @@ -0,0 +1,119 @@ +-- SPDX-License-Identifier: LGPL-3.0 + +--- Default aircraft-specific settings. + +local function UNITS_IMPERIAL_MBAR_DDM() + return { + ["gridfmt"] = "ddm", + ["pressurefmt"] = "mbar", + } +end + +local function UNITS_IMPERIAL_MGRS() + return { + ["gridfmt"] = "mgrs", + } +end + +local function UNITS_METRIC() + return { + ["distfmt"] = "kilometer", + ["altfmt"] = "meter", + ["speedfmt"] = "kph", + ["tempfmt"] = "C", + } +end + +local function UNITS_METRIC_HPA() + local u = UNITS_METRIC() + u.pressurefmt = "hpa" + return u +end + +local function UNITS_METRIC_INHG() + local u = UNITS_METRIC() + u.pressurefmt = "inhg" + return u +end + +local function UNITS_METRIC_MMHG() + local u = UNITS_METRIC() + u.pressurefmt = "mmhg" + return u +end + +local function UNITS_METRIC_MMHG_DDM() + local u = UNITS_METRIC() + u.pressurefmt = "mmhg" + u.gridfmt = "ddm" + return u +end + +local playeruicfg = { + ["A-10A"] = UNITS_IMPERIAL_MGRS(), + ["A-10C"] = UNITS_IMPERIAL_MGRS(), + ["A-10C_2"] = UNITS_IMPERIAL_MGRS(), + ["AH-64D_BLK_II"] = { + gridfmt = "mgrs", + distfmt = "kilometer", + }, + ["AJS37"] = UNITS_METRIC_HPA(), + ["Bf-109K-4"] = UNITS_METRIC_HPA(), + ["F-5E-3"] = { + gridfmt = "ddm", + }, + ["F-14A-95-GR"] = { + gridfmt = "ddm", + }, + ["F-14A-135-GR"] = { + gridfmt = "ddm", + }, + ["F-14B"] = { + gridfmt = "ddm", + }, + ["F-15ESE"] = { + gridfmt = "ddm", + }, + ["F-16C_50"] = { + gridfmt = "ddm", + }, + ["FA-18C_hornet"] = { + gridfmt = "ddm", + }, + ["FW-190A8"] = UNITS_METRIC_HPA(), + ["FW-190D9"] = UNITS_METRIC_HPA(), + ["I-16"] = UNITS_METRIC_MMHG(), + ["Ka-50"] = UNITS_METRIC_MMHG_DDM(), + ["Ka-50_3"] = { + gridfmt = "ddm", + }, + ["M-2000C"] = UNITS_IMPERIAL_MBAR_DDM(), + ["Mi-8MT"] = UNITS_METRIC_MMHG_DDM(), + ["Mi-24P"] = UNITS_METRIC_MMHG(), + ["Mirage-F1BE"] = UNITS_IMPERIAL_MBAR_DDM(), + ["Mirage-F1CE"] = UNITS_IMPERIAL_MBAR_DDM(), + ["Mirage-F1EE"] = UNITS_IMPERIAL_MBAR_DDM(), + ["Mirage-F1M"] = UNITS_IMPERIAL_MBAR_DDM(), + ["MiG-15bis"] = UNITS_METRIC_MMHG(), + ["MiG-19P"] = UNITS_METRIC_MMHG(), + ["MiG-21Bis"] = UNITS_METRIC_MMHG(), + ["MiG-29A"] = UNITS_METRIC_MMHG(), + ["MiG-29S"] = UNITS_METRIC_MMHG(), + ["MiG-29G"] = UNITS_METRIC_INHG(), + ["SA342M"] = { + gridfmt = "ddm", + }, + ["SA342L"] = { + gridfmt = "ddm", + }, + ["Su-25"] = UNITS_METRIC_MMHG(), + ["Su-25T"] = UNITS_METRIC_MMHG(), + ["Su-27"] = UNITS_METRIC_MMHG(), + ["Su-33"] = UNITS_METRIC_HPA(), + ["Yak-52"] = UNITS_METRIC_MMHG(), + ["UH-1H"] = { + gridfmt = "ddm", + }, +} + +return playeruicfg diff --git a/src/dct/data/restrictedweapons.lua b/src/dct/data/restrictedweapons.lua new file mode 100644 index 00000000..d9199a76 --- /dev/null +++ b/src/dct/data/restrictedweapons.lua @@ -0,0 +1,15 @@ +-- SPDX-License-Identifier: LGPL-3.0 + +--- Default restricted weapons. +local enum = require("dct.enum") + +return { + ["RN-24"] = { + ["cost"] = enum.WPNINFCOST, + ["category"] = enum.weaponCategory.AG, + }, + ["RN-28"] = { + ["cost"] = enum.WPNINFCOST, + ["category"] = enum.weaponCategory.AG, + }, +} diff --git a/src/dct/libs/utils.lua b/src/dct/libs/utils.lua index b5699809..29b4ec6b 100644 --- a/src/dct/libs/utils.lua +++ b/src/dct/libs/utils.lua @@ -132,11 +132,26 @@ function utils.not_playergroup(grp) return not isplayer end +function utils.check_ato(mlist) + local ntbl = {} + + for _, v in pairs(mlist) do + local mtype = enum.missionType[string.upper(v)] + + if mtype == nil then + return false, string.format( + "invalid mission type: %s", v) + end + ntbl[mtype] = true + end + return true, ntbl +end + function utils.set_ato(sqdn, flight) local sqdnato = sqdn:getDescKey("ato") -- mixed flights are not allowed in DCS local actype = next(flight:getDescKey("unitTypeCnt")) - local globalato = dct.settings.ui.ato[actype] + local globalato = dct.settings.ato[actype] if next(sqdnato) ~= nil then flight:setDescKey("ato", libsutils.shallowclone(sqdnato)) diff --git a/src/dct/settings/theater.lua b/src/dct/settings/theater.lua index c5f9466c..6484cee4 100644 --- a/src/dct/settings/theater.lua +++ b/src/dct/settings/theater.lua @@ -4,64 +4,88 @@ -- Provides config facilities. --]] -local utils = require("libs.utils") -local enum = require("dct.enum") -local dctutils = require("dct.libs.utils") -local uihuman = require("dct.ui.human") - -local function validate_weapon_restrictions(cfgdata, tbl) - local path = cfgdata.file - local keys = { - [1] = { - ["name"] = "cost", - ["type"] = "number", - }, - [2] = { - ["name"] = "category", - ["type"] = "string", - ["check"] = function (keydata, t) - if enum.weaponCategory[string.upper(t[keydata.name])] ~= nil then - t[keydata.name] = - enum.weaponCategory[string.upper(t[keydata.name])] - return true +local class = require("libs.namedclass") +local utils = require("libs.utils") +local dctenum = require("dct.enum") +local dctutils = require("dct.libs.utils") +local uihuman = require("dct.ui.human") +local Checker = require("dct.templates.checkers.Check") + +local defaultpayload = {} +for _, v in pairs(dctenum.weaponCategory) do + defaultpayload[v] = dctenum.WPNINFCOST - 1 +end + +local CheckPerEntry = class("CheckPerEntry", Checker) +function CheckPerEntry:check(data) + for key, val in pairs(data) do + local ok, errkey, msg = Checker.check(self, val) + if not ok then + return false, string.format( + "%s: invalid `%s` %s", tostring(key), + tostring(errkey), tostring(msg)) end - return false - end, - }, - } - for _, wpndata in pairs(tbl) do - wpndata.path = path - utils.checkkeys(keys, wpndata) - wpndata.path = nil + end + return true +end + +local function validate_weapon_restrictions(cfg, tbl) + local check = CheckPerEntry(nil, { + ["cost"] = { + ["nodoc"] = true, + ["type"] = Checker.valuetype.INT, + }, + ["category"] = { + ["nodoc"] = true, + ["type"] = Checker.valuetype.TABLEKEYS, + ["values"] = dctenum.weaponCategory, + }, + }) + + local ok, msg = check:check(tbl) + if not ok then + error(string.format("%s; file: %s", msg, cfg.file)) end return tbl end -local function validate_payload_limits(cfgdata, tbl) +--- validates payload limits configuration +-- This is per airframe with a "default" entry in case an airframe is +-- not defined. The default is unlimited. +local function validate_payload_limits(cfg, tbl) local newlimits = {} - for wpncat, val in pairs(tbl) do - local w = enum.weaponCategory[string.upper(wpncat)] - assert(w ~= nil, - string.format("invalid weapon category '%s'; file: %s", - wpncat, cfgdata.file)) - newlimits[w] = val + + for planetype, limits in pairs(tbl) do + newlimits[planetype] = {} + local tmptbl = {} + + for wpncat, val in pairs(limits) do + local w = dctenum.weaponCategory[string.upper(wpncat)] + + if w == nil then + error(string.format( + "invalid weapon category '%s' - ".. + "plane type %s; file: %s", + wpncat, planetype, cfg.file)) + end + tmptbl[w] = val + end + utils.mergetables(newlimits[planetype], defaultpayload) + utils.mergetables(newlimits[planetype], tmptbl) end + newlimits["default"] = defaultpayload return newlimits end -local function validate_codenamedb(cfgdata, tbl) +local function validate_codenamedb(cfg, tbl) local newtbl = {} for key, list in pairs(tbl) do local newkey - assert(type(key) == "string", - string.format("invalid codename category '%s'; file: %s", - key, cfgdata.file)) - local upper = string.upper(key) - local k = enum.assetType[upper] + local k = dctenum.assetType[upper] if k == nil then - k = enum.assetTypeDeprecated[upper] + k = dctenum.assetTypeDeprecated[upper] end if k ~= nil then @@ -69,74 +93,102 @@ local function validate_codenamedb(cfgdata, tbl) elseif key == "default" then newkey = key else - assert(nil, - string.format("invalid codename category '%s'; file: %s", - key, cfgdata.file)) + error(string.format("invalid codename category ".. + "'%s'; file: %s", key, cfg.file)) + end + + if type(list) ~= "table" then + error(string.format("invalid codename value for ".. + "category '%s', must be a table; file: %s", + key, cfg.file)) end - assert(type(list) == "table", - string.format("invalid codename value for category ".. - "'%s', must be a table; file: %s", key, cfgdata.file)) newtbl[newkey] = list end return newtbl end -local function gridfmt_transform(tbl) - local ntbl = {} - for k, v in pairs(tbl) do - if type(v) == "number" then - ntbl[k] = v - else - ntbl[k] = uihuman.posfmt[string.upper(v)] - assert(ntbl[k] ~= nil, "invalid grid format for "..k) - end - end - return ntbl -end +local function validate_ui(cfg, tbl) + local check = CheckPerEntry(nil, { + ["gridfmt"] = { + ["nodoc"] = true, + ["type"] = Checker.valuetype.TABLEKEYS, + ["values"] = uihuman.posfmt, + ["default"] = uihuman.posfmt.DMS, + }, + ["distfmt"] = { + ["nodoc"] = true, + ["type"] = Checker.valuetype.TABLEKEYS, + ["values"] = uihuman.distancefmt, + ["default"] = uihuman.distancefmt.NAUTICALMILE, + }, + ["altfmt"] = { + ["nodoc"] = true, + ["type"] = Checker.valuetype.TABLEKEYS, + ["values"] = uihuman.altfmt, + ["default"] = uihuman.altfmt.FEET, + }, + ["speedfmt"] = { + ["nodoc"] = true, + ["type"] = Checker.valuetype.TABLEKEYS, + ["values"] = uihuman.speedfmt, + ["default"] = uihuman.speedfmt.KNOTS, + }, + ["pressurefmt"] = { + ["nodoc"] = true, + ["type"] = Checker.valuetype.TABLEKEYS, + ["values"] = uihuman.pressurefmt, + ["default"] = uihuman.pressurefmt.INHG, + }, + ["tempfmt"] = { + ["nodoc"] = true, + ["type"] = Checker.valuetype.TABLEKEYS, + ["values"] = uihuman.tempfmt, + ["default"] = uihuman.tempfmt.F, + }, + }) + local newtbl = {} -local function ato_transform(tbl) - local ntbl = {} - for ac, mlist in pairs(tbl) do - ntbl[ac] = {} - for _, v in pairs(mlist) do - local mtype = string.upper(v) - local mval = enum.missionType[mtype] - assert(mval ~= nil, - string.format("invalid mission type: %s for ac: %s", - v, ac)) - ntbl[ac][mtype] = mval - end - end - return ntbl -end + utils.mergetables(newtbl, cfg.default) + utils.mergetables(newtbl, tbl) -local function validate_ui(cfgdata, tbl) - local newtbl = {} - utils.mergetables(newtbl, cfgdata.default) - for k, v in pairs(tbl) do - utils.mergetables(newtbl[k], v) - if k == "gridfmt" then - newtbl[k] = gridfmt_transform(newtbl[k]) - elseif k == "ato" then - newtbl[k] = ato_transform(newtbl[k]) - end + local ok, msg = check:check(newtbl) + if not ok then + error(string.format("%s; file: %s", msg, cfg.file)) end return newtbl end -local function validate_blast_effects(cfgdata, tbl) +local function merge_defaults(cfgdata, tbl) local newtbl = {} newtbl = utils.mergetables(newtbl, cfgdata.default) newtbl = utils.mergetables(newtbl, tbl) return newtbl end -local function validate_agents(cfgdata, tbl) - local newtbl = {} +local function validate_ato(cfg, tbl) + local ntbl = {} - newtbl = utils.mergetables(newtbl, cfgdata.default) - newtbl = utils.mergetables(newtbl, tbl) - return newtbl + for ac, mlist in pairs(tbl) do + local ok, nlist = dctutils.check_ato(mlist) + + if not ok then + error(string.format("%s; aircraft: %s; file: %s", + nlist, ac, cfg.file)) + end + ntbl[ac] = nlist + end + return ntbl +end + +local function validate_cost(cfg, tbl) + for ac, cost in pairs(tbl) do + if type(cost) ~= "number" then + error(string.format( + "cost not a number; aircraft: %s; file: %s", + ac, cfg.file)) + end + end + return tbl end -- We have a few levels of configuration: @@ -146,78 +198,59 @@ end -- simple algorithm; assign the defaults, then apply the server and -- theater configs local function theatercfgs(config) - local defaultpayload = {} - for _,v in pairs(enum.weaponCategory) do - defaultpayload[v] = enum.WPNINFCOST - 1 - end - + local basepath = utils.join_paths(config.server.theaterpath, + "settings") local cfgs = { { ["name"] = "restrictedweapons", - ["file"] = config.server.theaterpath..utils.sep.."settings".. - utils.sep.."restrictedweapons.cfg", + ["file"] = utils.join_paths(basepath, + "restrictedweapons.cfg"), ["cfgtblname"] = "restrictedweapons", ["validate"] = validate_weapon_restrictions, - ["default"] = { - ["RN-24"] = { - ["cost"] = enum.WPNINFCOST, - ["category"] = enum.weaponCategory.AG, - }, - ["RN-28"] = { - ["cost"] = enum.WPNINFCOST, - ["category"] = enum.weaponCategory.AG, - }, - }, + ["default"] = require("dct.data.restrictedweapons"), ["env"] = { - ["INFCOST"] = enum.WPNINFCOST, + ["INFCOST"] = dctenum.WPNINFCOST, }, }, { ["name"] = "payloadlimits", - ["file"] = config.server.theaterpath..utils.sep.."settings".. - utils.sep.."payloadlimits.cfg", + ["file"] = utils.join_paths(basepath, + "payloadlimits.cfg"), + ["cfgtblname"] = "payloadlimits", ["validate"] = validate_payload_limits, - ["default"] = defaultpayload, }, { ["name"] = "codenamedb", - ["file"] = config.server.theaterpath..utils.sep.."settings".. - utils.sep.."codenamedb.cfg", + ["file"] = utils.join_paths(basepath, + "codenamedb.cfg"), ["validate"] = validate_codenamedb, ["default"] = require("dct.data.codenamedb"), }, { ["name"] = "ui", - ["file"] = config.server.theaterpath..utils.sep.."settings".. - utils.sep.."ui.cfg", + ["file"] = utils.join_paths(basepath, "ui.cfg"), ["validate"] = validate_ui, - ["default"] = { - ["gridfmt"] = { - -- default is DMS, no need to list - ["Ka-50"] = uihuman.posfmt.DDM, - ["Mi-8MT"] = uihuman.posfmt.DDM, - ["SA342M"] = uihuman.posfmt.DDM, - ["SA342L"] = uihuman.posfmt.DDM, - ["UH-1H"] = uihuman.posfmt.DDM, - ["A-10A"] = uihuman.posfmt.MGRS, - ["A-10C"] = uihuman.posfmt.MGRS, - ["A-10C_2"] = uihuman.posfmt.MGRS, - ["F-5E-3"] = uihuman.posfmt.DDM, - ["F-16C_50"] = uihuman.posfmt.DDM, - ["FA-18C_hornet"] = uihuman.posfmt.DDM, - ["M-2000C"] = uihuman.posfmt.DDM, - }, - ["ato"] = {}, - }, + ["cfgtblname"] = "ui", + ["default"] = require("dct.data.playerui"), }, { ["name"] = "blasteffects", - ["file"] = config.server.theaterpath..utils.sep.."settings".. - utils.sep.."blasteffects.cfg", - ["validate"] = validate_blast_effects, + ["file"] = utils.join_paths(basepath, + "blasteffects.cfg"), + ["validate"] = merge_defaults, ["default"] = require("dct.data.blasteffects"), }, { ["name"] = "agents", - ["file"] = config.server.theaterpath..utils.sep.. - "settings"..utils.sep.."agents.cfg", - ["validate"] = validate_agents, + ["file"] = utils.join_paths(basepath, "agents.cfg"), + ["validate"] = merge_defaults, ["default"] = require("dct.data.agents"), + }, { + ["name"] = "ato", + ["file"] = utils.join_paths(basepath, "ato.cfg"), + ["validate"] = validate_ato, + ["cfgtblname"] = "ato", + }, { + ["name"] = "airframecost", + ["file"] = utils.join_paths(basepath, + "airframecost.cfg"), + ["validate"] = validate_cost, + ["cfgtblname"] = "cost", }, } diff --git a/src/dct/templates/checkers/CheckPlayer.lua b/src/dct/templates/checkers/CheckPlayer.lua index 28763904..b7f20336 100644 --- a/src/dct/templates/checkers/CheckPlayer.lua +++ b/src/dct/templates/checkers/CheckPlayer.lua @@ -2,7 +2,9 @@ local class = require("libs.namedclass") local dctenum = require("dct.enum") +local uihuman = require("dct.ui.human") local Check = require("dct.templates.checkers.Check") +local settings = dct.settings --- @class CheckPlayer @@ -30,6 +32,60 @@ function CheckPlayer:__init() ["description"] = "The squadron the slot is associated with", }, + ["ato"] = { + ["nodoc"] = true, + ["agent"] = true, + ["type"] = Check.valuetype.TABLE, + ["default"] = {}, + }, + ["payloadlimits"] = { + ["nodoc"] = true, + ["agent"] = true, + ["type"] = Check.valuetype.TABLE, + ["default"] = settings.payloadlimits["default"], + }, + ["gridfmt"] = { + ["nodoc"] = true, + ["agent"] = true, + ["type"] = Check.valuetype.TABLEKEYS, + ["values"] = uihuman.posfmt, + ["default"] = uihuman.posfmt.DMS, + }, + ["distfmt"] = { + ["nodoc"] = true, + ["agent"] = true, + ["type"] = Check.valuetype.TABLEKEYS, + ["values"] = uihuman.distancefmt, + ["default"] = uihuman.distancefmt.NAUTICALMILE, + }, + ["altfmt"] = { + ["nodoc"] = true, + ["agent"] = true, + ["type"] = Check.valuetype.TABLEKEYS, + ["values"] = uihuman.altfmt, + ["default"] = uihuman.altfmt.FEET, + }, + ["speedfmt"] = { + ["nodoc"] = true, + ["agent"] = true, + ["type"] = Check.valuetype.TABLEKEYS, + ["values"] = uihuman.speedfmt, + ["default"] = uihuman.speedfmt.KNOTS, + }, + ["pressurefmt"] = { + ["nodoc"] = true, + ["agent"] = true, + ["type"] = Check.valuetype.TABLEKEYS, + ["values"] = uihuman.pressurefmt, + ["default"] = uihuman.pressurefmt.INHG, + }, + ["tempfmt"] = { + ["nodoc"] = true, + ["agent"] = true, + ["type"] = Check.valuetype.TABLEKEYS, + ["values"] = uihuman.tempfmt, + ["default"] = uihuman.tempfmt.F, + }, }) end @@ -41,7 +97,30 @@ function CheckPlayer:check(data) data.overwrite = false data.rename = false - return Check.check(self, data) + if next(data.tpldata) == nil then + return true + end + + local ok, msg = Check.check(self, data) + if not ok then + return ok, msg + end + + local actype = data.tpldata[1]["data"].units[1].type + local ui = settings.ui[actype] + + data.ato = settings.ato[actype] or data.ato + data.payloadlimits = settings.payloadlimits[actype] or + data.payloadlimits + data.cost = settings.airframecost[actype] or data.cost + + if ui ~= nil then + for k, v in pairs(ui) do + data[k] = v + end + end + + return true end return CheckPlayer diff --git a/src/dct/templates/checkers/CheckSquadron.lua b/src/dct/templates/checkers/CheckSquadron.lua index cebdc684..9050ff44 100644 --- a/src/dct/templates/checkers/CheckSquadron.lua +++ b/src/dct/templates/checkers/CheckSquadron.lua @@ -4,6 +4,7 @@ local class = require("libs.namedclass") local dctenum = require("dct.enum") +local dctutils = require("dct.libs.utils") local Check = require("dct.templates.checkers.Check") local issquadron = { @@ -174,18 +175,12 @@ function CheckSquadron:checkTpldata(data) end function CheckSquadron:checkATO(data) - local msnlist = {} - - for _, msntype in pairs(data.ato) do - local msnstr = string.upper(msntype) - if type(msntype) ~= "string" or - dctenum.missionType[msnstr] == nil then - return false, "ato", - "invalid mission type: "..tostring(msnstr) - end - msnlist[dctenum.missionType[msnstr]] = true + local ok, tbl = dctutils.check_ato(data.ato) + + if not ok then + return ok, "ato", tbl end - data.ato = msnlist + data.ato = tbl return true end diff --git a/src/dct/ui/human.lua b/src/dct/ui/human.lua index 0d951f49..61b39d16 100644 --- a/src/dct/ui/human.lua +++ b/src/dct/ui/human.lua @@ -68,18 +68,42 @@ local speedfmt = { ["MPH"] = 3, } --- converts meters per second to X speed +--- converts meters per second to X speed local speed_conversion = { [speedfmt.KNOTS] = conversion_entry(1.94384, "kts"), [speedfmt.KPH] = conversion_entry(3.6, "kph"), [speedfmt.MPH] = conversion_entry(2.23694, "mph"), } +local tempfmt = { + ["K"] = 1, + ["F"] = 2, + ["C"] = 3, +} + +--- converts kelvins to X temp +local temp_conversion = { + [tempfmt.K] = conversion_entry(1, "K"), + [tempfmt.C] = { + ["symbol"] = "C", + ["convert"] = function (value) + return value - 273.15 + end, + }, + [tempfmt.F] = { + ["symbol"] = "F", + ["convert"] = function (value) + return (value - 273.15) * 9/5 + 32 + end, + }, +} + local unitstype = { ["SPEED"] = 1, ["DISTANCE"] = 2, ["ALTITUDE"] = 3, ["PRESSURE"] = 4, + ["TEMP"] = 5, } local conversiontbl = { @@ -87,6 +111,7 @@ local conversiontbl = { [unitstype.DISTANCE] = distance_conversion, [unitstype.ALTITUDE] = altitude_conversion, [unitstype.PRESSURE] = pressure_conversion, + [unitstype.TEMP] = temp_conversion, } --- Filter out facts that are not considered targets. @@ -156,6 +181,8 @@ human.altfmt = altfmt human.pressurefmt = pressurefmt human.distancefmt = distancefmt human.speedfmt = speedfmt +human.tempfmt = tempfmt +human.units = unitstype function human.convert(value, utype, tounit) local converttbl = conversiontbl[utype] @@ -170,6 +197,9 @@ function human.convert(value, utype, tounit) return nil end + if type(totbl.convert) == "function" then + return totbl.convert(value), totbl.symbol + end return value * totbl.ratio, totbl.symbol end diff --git a/tests/test-configs.lua b/tests/test-configs.lua index 6c1e42b2..fa13be18 100755 --- a/tests/test-configs.lua +++ b/tests/test-configs.lua @@ -3,5 +3,5 @@ require("dcttestlibs") require("dct") -assert(dct.settings.ui.gridfmt["Ka-50"] == 3, "ka-50 error") +assert(dct.settings.ui["Ka-50"].gridfmt == 2, "ka-50 error") os.exit(0)