mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added ability to delete original cloned units
Mostly useful to group units together
This commit is contained in:
@@ -1,39 +1,50 @@
|
||||
local version = "v0.4.4-alpha"
|
||||
|
||||
local debug = true
|
||||
local debug = true -- True enables debug printing using DCS messages
|
||||
|
||||
-- .dll related variables
|
||||
Olympus.OlympusDLL = nil
|
||||
Olympus.DLLsloaded = false
|
||||
Olympus.OlympusModPath = os.getenv('DCSOLYMPUS_PATH')..'\\bin\\'
|
||||
|
||||
-- Logger reference
|
||||
Olympus.log = mist.Logger:new("Olympus", 'info')
|
||||
|
||||
Olympus.unitCounter = 1
|
||||
Olympus.spawnDatabase = {}
|
||||
|
||||
-- Data structures for transfer to .dll
|
||||
Olympus.missionData = {}
|
||||
Olympus.unitsData = {}
|
||||
Olympus.weaponsData = {}
|
||||
|
||||
Olympus.unitIndex = 0
|
||||
Olympus.unitStep = 50
|
||||
Olympus.units = {}
|
||||
-- Units data structures
|
||||
Olympus.unitCounter = 1 -- Counter to generate unique names
|
||||
Olympus.spawnDatabase = {} -- Database of spawn options, used for units cloning
|
||||
Olympus.unitIndex = 0 -- Counter used to spread the computational load of data retrievial from DCS
|
||||
Olympus.unitStep = 50 -- Max number of units that get updated each cycle
|
||||
Olympus.units = {} -- Table holding references to all the currently existing units
|
||||
|
||||
Olympus.weaponIndex = 0
|
||||
Olympus.weaponStep = 50
|
||||
Olympus.weapons = {}
|
||||
Olympus.weaponIndex = 0 -- Counter used to spread the computational load of data retrievial from DCS
|
||||
Olympus.weaponStep = 50 -- Max number of weapons that get updated each cycle
|
||||
Olympus.weapons = {} -- Table holding references to all the currently existing weapons
|
||||
|
||||
-- Miscellaneous initializations
|
||||
Olympus.missionStartTime = DCS.getRealTime()
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- Olympus functions
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- Print a debug message if the debug option is true
|
||||
function Olympus.debug(message, displayFor)
|
||||
if debug == true then
|
||||
trigger.action.outText(message, displayFor)
|
||||
end
|
||||
end
|
||||
|
||||
-- Print a notify message
|
||||
function Olympus.notify(message, displayFor)
|
||||
trigger.action.outText(message, displayFor)
|
||||
end
|
||||
|
||||
-- Loads the olympus .dll
|
||||
function Olympus.loadDLLs()
|
||||
-- Add the .dll paths
|
||||
package.cpath = package.cpath..';'..Olympus.OlympusModPath..'?.dll;'
|
||||
@@ -52,6 +63,7 @@ function Olympus.getUnitByID(ID)
|
||||
return Olympus.units[ID];
|
||||
end
|
||||
|
||||
-- Gets the ID of the first country that belongs to a coalition
|
||||
function Olympus.getCountryIDByCoalition(coalitionString)
|
||||
for countryName, countryId in pairs(country.id) do
|
||||
if coalition.getCountryCoalition(countryId) == Olympus.getCoalitionIDByCoalition(coalitionString) then
|
||||
@@ -61,6 +73,7 @@ function Olympus.getCountryIDByCoalition(coalitionString)
|
||||
return 0
|
||||
end
|
||||
|
||||
-- Gets the coalition ID of a coalition
|
||||
function Olympus.getCoalitionIDByCoalition(coalitionString)
|
||||
local coalitionID = 0
|
||||
if coalitionString == "red" then
|
||||
@@ -71,6 +84,7 @@ function Olympus.getCoalitionIDByCoalition(coalitionString)
|
||||
return coalitionID
|
||||
end
|
||||
|
||||
-- Gets the coalition name from the coalition ID
|
||||
function Olympus.getCoalitionByCoalitionID(coalitionID)
|
||||
local coalitionString = "neutral"
|
||||
if coalitionID == 1 then
|
||||
@@ -81,7 +95,7 @@ function Olympus.getCoalitionByCoalitionID(coalitionID)
|
||||
return coalitionString
|
||||
end
|
||||
|
||||
-- Builds a valid task depending on the provided options
|
||||
-- Builds a valid enroute task depending on the provided options
|
||||
function Olympus.buildEnrouteTask(options)
|
||||
local task = nil
|
||||
-- Engage specific target by ID. Checks if target exists.
|
||||
@@ -111,11 +125,13 @@ function Olympus.buildEnrouteTask(options)
|
||||
return task
|
||||
end
|
||||
|
||||
-- Builds a valid task depending on the provided options
|
||||
-- Builds a valid main task depending on the provided options
|
||||
function Olympus.buildTask(groupName, options)
|
||||
local task = nil
|
||||
|
||||
local group = Group.getByName(groupName)
|
||||
|
||||
-- Combo tasks require nested tables
|
||||
if (Olympus.isArray(options)) then
|
||||
local tasks = {}
|
||||
for idx, subOptions in pairs(options) do
|
||||
@@ -129,6 +145,7 @@ function Olympus.buildTask(groupName, options)
|
||||
}
|
||||
Olympus.debug(Olympus.serializeTable(task), 30)
|
||||
else
|
||||
-- Follow a unit in formation with a given offset
|
||||
if options['id'] == 'FollowUnit' and options['leaderID'] and options['offset'] then
|
||||
local leader = Olympus.getUnitByID(options['leaderID'])
|
||||
if leader and leader:isExist() then
|
||||
@@ -142,11 +159,13 @@ function Olympus.buildTask(groupName, options)
|
||||
}
|
||||
}
|
||||
end
|
||||
-- Go refuel to the nearest tanker. If the unit can't refuel it will RTB
|
||||
elseif options['id'] == 'Refuel' then
|
||||
task = {
|
||||
id = 'Refueling',
|
||||
params = {}
|
||||
}
|
||||
-- Orbit in place at a given altitude and with a given pattern
|
||||
elseif options['id'] == 'Orbit' then
|
||||
task = {
|
||||
id = 'Orbit',
|
||||
@@ -173,6 +192,7 @@ function Olympus.buildTask(groupName, options)
|
||||
if options['speed'] then
|
||||
task['params']['speed'] = options['speed']
|
||||
end
|
||||
-- Bomb a specific location
|
||||
elseif options['id'] == 'Bombing' and options['lat'] and options['lng'] then
|
||||
local point = coord.LLtoLO(options['lat'], options['lng'], 0)
|
||||
task = {
|
||||
@@ -182,6 +202,7 @@ function Olympus.buildTask(groupName, options)
|
||||
attackQty = 1
|
||||
}
|
||||
}
|
||||
-- Perform carpet bombing at a specific location
|
||||
elseif options['id'] == 'CarpetBombing' and options['lat'] and options['lng'] then
|
||||
local point = coord.LLtoLO(options['lat'], options['lng'], 0)
|
||||
task = {
|
||||
@@ -196,14 +217,7 @@ function Olympus.buildTask(groupName, options)
|
||||
attackQtyLimit = true
|
||||
}
|
||||
}
|
||||
elseif options['id'] == 'AttackMapObject' and options['lat'] and options['lng'] then
|
||||
local point = coord.LLtoLO(options['lat'], options['lng'], 0)
|
||||
task = {
|
||||
id = 'AttackMapObject',
|
||||
params = {
|
||||
point = {x = point.x, y = point.z}
|
||||
}
|
||||
}
|
||||
-- Fire at a specific point
|
||||
elseif options['id'] == 'FireAtPoint' and options['lat'] and options['lng'] and options['radius'] then
|
||||
local point = coord.LLtoLO(options['lat'], options['lng'], 0)
|
||||
task = {
|
||||
@@ -226,22 +240,17 @@ function Olympus.move(groupName, lat, lng, altitude, altitudeType, speed, speedT
|
||||
if category == "Aircraft" then
|
||||
local startPoint = mist.getLeadPos(group)
|
||||
local endPoint = coord.LLtoLO(lat, lng, 0)
|
||||
|
||||
-- 'AGL' mode does not appear to work in the buildWP function. This is a crude approximation
|
||||
if altitudeType == "AGL" then
|
||||
altitude = land.getHeight({x = endPoint.x, y = endPoint.z}) + altitude
|
||||
end
|
||||
|
||||
local path = {}
|
||||
if taskOptions and taskOptions['id'] == 'Land' then
|
||||
path = {
|
||||
[1] = mist.fixedWing.buildWP(startPoint, turningPoint, speed, altitude, 'BARO'),
|
||||
[2] = mist.fixedWing.buildWP(endPoint, landing, speed, 0, 'AGL')
|
||||
}
|
||||
else
|
||||
path = {
|
||||
[1] = mist.fixedWing.buildWP(startPoint, turningPoint, speed, altitude, 'BARO'),
|
||||
[2] = mist.fixedWing.buildWP(endPoint, turningPoint, speed, altitude, 'BARO')
|
||||
}
|
||||
end
|
||||
-- Create the path
|
||||
local path = {
|
||||
[1] = mist.fixedWing.buildWP(startPoint, turningPoint, speed, altitude, 'BARO'),
|
||||
[2] = mist.fixedWing.buildWP(endPoint, turningPoint, speed, altitude, 'BARO')
|
||||
}
|
||||
|
||||
-- If a task exists assign it to the controller
|
||||
if taskOptions then
|
||||
@@ -270,22 +279,16 @@ function Olympus.move(groupName, lat, lng, altitude, altitudeType, speed, speedT
|
||||
local startPoint = mist.getLeadPos(group)
|
||||
local endPoint = coord.LLtoLO(lat, lng, 0)
|
||||
|
||||
-- 'AGL' mode does not appear to work in the buildWP function. This is a crude approximation
|
||||
if altitudeType == "AGL" then
|
||||
altitude = land.getHeight({x = endPoint.x, y = endPoint.z}) + altitude
|
||||
end
|
||||
|
||||
local path = {}
|
||||
if taskOptions and taskOptions['id'] == 'Land' then
|
||||
path = {
|
||||
[1] = mist.heli.buildWP(startPoint, turningPoint, speed, altitude, 'BARO'),
|
||||
[2] = mist.heli.buildWP(endPoint, landing, speed, 0, 'AGL')
|
||||
}
|
||||
else
|
||||
path = {
|
||||
[1] = mist.heli.buildWP(startPoint, turningPoint, speed, altitude, 'BARO'),
|
||||
[2] = mist.heli.buildWP(endPoint, turningPoint, speed, altitude, 'BARO')
|
||||
}
|
||||
end
|
||||
-- Create the path
|
||||
local path = {
|
||||
[1] = mist.heli.buildWP(startPoint, turningPoint, speed, altitude, 'BARO'),
|
||||
[2] = mist.heli.buildWP(endPoint, turningPoint, speed, altitude, 'BARO')
|
||||
}
|
||||
|
||||
-- If a task exists assign it to the controller
|
||||
if taskOptions then
|
||||
@@ -315,13 +318,12 @@ function Olympus.move(groupName, lat, lng, altitude, altitudeType, speed, speedT
|
||||
local endPoint = coord.LLtoLO(lat, lng, 0)
|
||||
local bearing = math.atan2(endPoint.z - startPoint.z, endPoint.x - startPoint.x)
|
||||
|
||||
vars =
|
||||
{
|
||||
group = group,
|
||||
point = endPoint,
|
||||
heading = bearing,
|
||||
speed = speed
|
||||
}
|
||||
vars = {
|
||||
group = group,
|
||||
point = endPoint,
|
||||
heading = bearing,
|
||||
speed = speed
|
||||
}
|
||||
|
||||
if taskOptions and taskOptions['id'] == 'FollowRoads' and taskOptions['value'] == true then
|
||||
vars["disableRoads"] = false
|
||||
@@ -331,21 +333,20 @@ function Olympus.move(groupName, lat, lng, altitude, altitudeType, speed, speedT
|
||||
end
|
||||
|
||||
mist.groupToRandomPoint(vars)
|
||||
Olympus.debug("Olympus.move executed succesfully on GroundUnit", 2)
|
||||
Olympus.debug("Olympus.move executed successfully on GroundUnit", 2)
|
||||
elseif category == "NavyUnit" then
|
||||
local startPoint = mist.getLeadPos(group)
|
||||
local endPoint = coord.LLtoLO(lat, lng, 0)
|
||||
local bearing = math.atan2(endPoint.z - startPoint.z, endPoint.x - startPoint.x)
|
||||
|
||||
vars =
|
||||
{
|
||||
group = group,
|
||||
point = endPoint,
|
||||
heading = bearing,
|
||||
speed = speed
|
||||
}
|
||||
vars = {
|
||||
group = group,
|
||||
point = endPoint,
|
||||
heading = bearing,
|
||||
speed = speed
|
||||
}
|
||||
mist.groupToRandomPoint(vars)
|
||||
Olympus.debug("Olympus.move executed succesfully on NavyUnit", 2)
|
||||
Olympus.debug("Olympus.move executed successfully on NavyUnit", 2)
|
||||
else
|
||||
Olympus.debug("Olympus.move not implemented yet for " .. category, 2)
|
||||
end
|
||||
@@ -379,6 +380,19 @@ function Olympus.explosion(intensity, lat, lng)
|
||||
end
|
||||
|
||||
-- Spawns a new unit or group
|
||||
-- Spawn table contains the following parameters
|
||||
-- category: (string), either Aircraft, Helicopter, GroundUnit or NavyUnit
|
||||
-- coalition: (string)
|
||||
-- country: (string)
|
||||
-- airbaseName: (string, optional) only for air units
|
||||
-- units: (array) Array of units to spawn. All units will be in the same group. Each unit element must contain:
|
||||
-- unitType: (string) DCS Name of the unit
|
||||
-- lat: (number)
|
||||
-- lng: (number)
|
||||
-- alt: (number, optional) only for air units
|
||||
-- loadout: (string, optional) only for air units, must be one of the loadouts defined in unitPayloads.lua
|
||||
-- payload: (table, optional) overrides loadout, specifies directly the loadout of the unit
|
||||
-- liveryID: (string, optional)
|
||||
function Olympus.spawnUnits(spawnTable)
|
||||
Olympus.debug("Olympus.spawnUnits " .. Olympus.serializeTable(spawnTable), 2)
|
||||
|
||||
@@ -386,6 +400,7 @@ function Olympus.spawnUnits(spawnTable)
|
||||
local route = nil
|
||||
local category = nil
|
||||
|
||||
-- Generate the units table and rout as per DCS requirements
|
||||
if spawnTable.category == 'Aircraft' then
|
||||
unitsTable = Olympus.generateAirUnitsTable(spawnTable.units)
|
||||
route = Olympus.generateAirUnitsRoute(spawnTable)
|
||||
@@ -402,6 +417,7 @@ function Olympus.spawnUnits(spawnTable)
|
||||
category = 'ship'
|
||||
end
|
||||
|
||||
-- It the unit country is not specified, get a country that belongs to the coalition
|
||||
local countryID = 0
|
||||
if spawnTable.country == nil or spawnTable.country == "" then
|
||||
countryID = Olympus.getCountryIDByCoalition(spawnTable.coalition)
|
||||
@@ -414,6 +430,7 @@ function Olympus.spawnUnits(spawnTable)
|
||||
Olympus.addToDatabase(unitTable)
|
||||
end
|
||||
|
||||
-- Spawn the new group
|
||||
local vars =
|
||||
{
|
||||
units = unitsTable,
|
||||
@@ -429,7 +446,7 @@ function Olympus.spawnUnits(spawnTable)
|
||||
Olympus.debug("Olympus.spawnUnits completed succesfully", 2)
|
||||
end
|
||||
|
||||
-- Generates unit table for a air unit.
|
||||
-- Generates unit table for air units
|
||||
function Olympus.generateAirUnitsTable(units)
|
||||
local unitsTable = {}
|
||||
for idx, unit in pairs(units) do
|
||||
@@ -440,6 +457,7 @@ function Olympus.generateAirUnitsTable(units)
|
||||
unit.heading = 0
|
||||
end
|
||||
|
||||
-- Define the loadout
|
||||
if payload == nil then
|
||||
if loadout and loadout ~= "" and Olympus.unitPayloads[unit.unitType][loadout] then
|
||||
payload = Olympus.unitPayloads[unit.unitType][loadout]
|
||||
@@ -448,6 +466,7 @@ function Olympus.generateAirUnitsTable(units)
|
||||
end
|
||||
end
|
||||
|
||||
-- Generate the unit table
|
||||
local spawnLocation = mist.utils.makeVec3GL(coord.LLtoLO(unit.lat, unit.lng, 0))
|
||||
unitsTable[#unitsTable + 1] =
|
||||
{
|
||||
@@ -593,13 +612,17 @@ function Olympus.generateNavyUnitsTable(units)
|
||||
return unitsTable
|
||||
end
|
||||
|
||||
-- Add the unit data to the database, used for unit cloning
|
||||
function Olympus.addToDatabase(unitTable)
|
||||
-- Add the unit data to the database, used for unit cloning
|
||||
Olympus.spawnDatabase[unitTable.name] = unitTable
|
||||
end
|
||||
|
||||
-- Clones a unit by ID. Will clone the unit with the same original payload as the source unit. TODO: only works on Olympus unit not ME units (TO BE VERIFIED).
|
||||
function Olympus.clone(cloneTable)
|
||||
-- cloneTable is an array of element, each of which contains
|
||||
-- ID: (number) ID of the unit to clone
|
||||
-- lat: (number)
|
||||
-- lng: (number)
|
||||
function Olympus.clone(cloneTable, deleteOriginal)
|
||||
Olympus.debug("Olympus.clone " .. Olympus.serializeTable(cloneTable), 2)
|
||||
|
||||
local unitsTable = {}
|
||||
@@ -607,6 +630,7 @@ function Olympus.clone(cloneTable)
|
||||
local category = nil
|
||||
local route = {}
|
||||
|
||||
-- All the units in the table will be cloned in a single group
|
||||
for idx, cloneData in pairs(cloneTable) do
|
||||
local ID = cloneData.ID
|
||||
local unit = Olympus.getUnitByID(ID)
|
||||
@@ -676,6 +700,10 @@ function Olympus.clone(cloneTable)
|
||||
|
||||
unitsTable[#unitsTable + 1] = mist.utils.deepCopy(unitTable)
|
||||
end
|
||||
|
||||
if deleteOriginal then
|
||||
Olympus.delete(ID, false)
|
||||
end
|
||||
end
|
||||
|
||||
local vars =
|
||||
@@ -701,6 +729,7 @@ function Olympus.clone(cloneTable)
|
||||
Olympus.debug("Olympus.clone completed successfully", 2)
|
||||
end
|
||||
|
||||
-- Delete a unit by ID, optionally use an explosion
|
||||
function Olympus.delete(ID, explosion)
|
||||
Olympus.debug("Olympus.delete " .. ID .. " " .. tostring(explosion), 2)
|
||||
local unit = Olympus.getUnitByID(ID)
|
||||
@@ -715,6 +744,7 @@ function Olympus.delete(ID, explosion)
|
||||
end
|
||||
end
|
||||
|
||||
-- Set a DCS main task to a group
|
||||
function Olympus.setTask(groupName, taskOptions)
|
||||
Olympus.debug("Olympus.setTask " .. groupName .. " " .. Olympus.serializeTable(taskOptions), 2)
|
||||
local group = Group.getByName(groupName)
|
||||
@@ -728,6 +758,7 @@ function Olympus.setTask(groupName, taskOptions)
|
||||
end
|
||||
end
|
||||
|
||||
-- Reset the dask of a group
|
||||
function Olympus.resetTask(groupName)
|
||||
Olympus.debug("Olympus.resetTask " .. groupName, 2)
|
||||
local group = Group.getByName(groupName)
|
||||
@@ -737,6 +768,7 @@ function Olympus.resetTask(groupName)
|
||||
end
|
||||
end
|
||||
|
||||
-- Give a group a command
|
||||
function Olympus.setCommand(groupName, command)
|
||||
Olympus.debug("Olympus.setCommand " .. groupName .. " " .. Olympus.serializeTable(command), 2)
|
||||
local group = Group.getByName(groupName)
|
||||
@@ -746,6 +778,7 @@ function Olympus.setCommand(groupName, command)
|
||||
end
|
||||
end
|
||||
|
||||
-- Set an option of a group
|
||||
function Olympus.setOption(groupName, optionID, optionValue)
|
||||
Olympus.debug("Olympus.setOption " .. groupName .. " " .. optionID .. " " .. tostring(optionValue), 2)
|
||||
local group = Group.getByName(groupName)
|
||||
@@ -755,6 +788,7 @@ function Olympus.setOption(groupName, optionID, optionValue)
|
||||
end
|
||||
end
|
||||
|
||||
-- Disable the AI of a group on or off entirely
|
||||
function Olympus.setOnOff(groupName, onOff)
|
||||
Olympus.debug("Olympus.setOnOff " .. groupName .. " " .. tostring(onOff), 2)
|
||||
local group = Group.getByName(groupName)
|
||||
@@ -764,6 +798,7 @@ function Olympus.setOnOff(groupName, onOff)
|
||||
end
|
||||
end
|
||||
|
||||
-- This function is periodically called to collect the data of all the existing units in the mission to be transmitted to the olympus.dll
|
||||
function Olympus.setUnitsData(arg, time)
|
||||
-- Units data
|
||||
local units = {}
|
||||
@@ -773,9 +808,11 @@ function Olympus.setUnitsData(arg, time)
|
||||
local index = 0
|
||||
for ID, unit in pairs(Olympus.units) do
|
||||
index = index + 1
|
||||
-- Only the indexes between startIndex and endIndex are handled. This is a simple way to spread the update load over many cycles
|
||||
if index > startIndex then
|
||||
if unit ~= nil then
|
||||
local table = {}
|
||||
local table = {}
|
||||
|
||||
-- Get the object category in Olympus name
|
||||
local objectCategory = unit:getCategory()
|
||||
if objectCategory == Object.Category.UNIT then
|
||||
@@ -845,6 +882,7 @@ function Olympus.setUnitsData(arg, time)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- If the unit reference is nil it means the unit no longer exits
|
||||
units[ID] = {isAlive = false}
|
||||
Olympus.units[ID] = nil
|
||||
end
|
||||
@@ -853,6 +891,8 @@ function Olympus.setUnitsData(arg, time)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Reset the counter
|
||||
if index ~= endIndex then
|
||||
Olympus.unitIndex = 0
|
||||
else
|
||||
@@ -866,6 +906,7 @@ function Olympus.setUnitsData(arg, time)
|
||||
return time + 0.05
|
||||
end
|
||||
|
||||
-- This function is periodically called to collect the data of all the existing weapons in the mission to be transmitted to the olympus.dll
|
||||
function Olympus.setWeaponsData(arg, time)
|
||||
-- Weapons data
|
||||
local weapons = {}
|
||||
@@ -875,6 +916,8 @@ function Olympus.setWeaponsData(arg, time)
|
||||
local index = 0
|
||||
for ID, weapon in pairs(Olympus.weapons) do
|
||||
index = index + 1
|
||||
|
||||
-- Only the indexes between startIndex and endIndex are handled. This is a simple way to spread the update load over many cycles
|
||||
if index > startIndex then
|
||||
if weapon ~= nil then
|
||||
local table = {}
|
||||
@@ -915,6 +958,7 @@ function Olympus.setWeaponsData(arg, time)
|
||||
weapons[ID] = table
|
||||
end
|
||||
else
|
||||
-- If the weapon reference is nil it means the unit no longer exits
|
||||
weapons[ID] = {isAlive = false}
|
||||
Olympus.weapons[ID] = nil
|
||||
end
|
||||
@@ -923,6 +967,8 @@ function Olympus.setWeaponsData(arg, time)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Reset the counter
|
||||
if index ~= endIndex then
|
||||
Olympus.weaponIndex = 0
|
||||
else
|
||||
@@ -990,9 +1036,10 @@ function Olympus.setMissionData(arg, time)
|
||||
Olympus.missionData["mission"] = mission
|
||||
|
||||
Olympus.OlympusDLL.setMissionData()
|
||||
return time + 1
|
||||
return time + 1 -- For perfomance reasons weapons are updated once every second
|
||||
end
|
||||
|
||||
-- Initializes the units table with all the existing ME units
|
||||
function Olympus.initializeUnits()
|
||||
if mist and mist.DBs and mist.DBs.MEunitsById then
|
||||
for id, unitsTable in pairs(mist.DBs.MEunitsById) do
|
||||
@@ -1008,6 +1055,9 @@ function Olympus.initializeUnits()
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- Olympus utility functions
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function Olympus.serializeTable(val, name, skipnewlines, depth)
|
||||
skipnewlines = skipnewlines or false
|
||||
depth = depth or 0
|
||||
|
||||
Reference in New Issue
Block a user