diff --git a/CTLD.lua b/CTLD.lua index 3ef3f15..b77a47c 100644 --- a/CTLD.lua +++ b/CTLD.lua @@ -13,9 +13,10 @@ Contributors: - Steggles - https://github.com/Bob7heBuilder - Version: 1.41 - 11/11/2015 - Added new callback interface + Version: 1.42 - 11/11/2015 - Added new callback interface - Added Different Pickup Groups for F10 and for the spawn group command - EWR now activates + - Bug fix for AI Group Load ]] @@ -1423,7 +1424,7 @@ function ctld.loadTroops(_heli, _troops, _numberOrTemplate) local _onboard = ctld.inTransitTroops[_heli:getName()] --number doesnt apply to vehicles - if _numberOrTemplate == nil then + if _numberOrTemplate == nil or (type(_numberOrTemplate) ~= "table" and type(_numberOrTemplate) ~= "number") then _numberOrTemplate = ctld.numberOfTroops end @@ -3848,36 +3849,45 @@ function ctld.checkAIStatus() timer.scheduleFunction(ctld.checkAIStatus, nil, timer.getTime() + 2) + for _, _unitName in pairs(ctld.transportPilotNames) do + local status, error = pcall(function() - local _unit = ctld.getTransportUnit(_unitName) + local _unit = ctld.getTransportUnit(_unitName) - -- no player name means AI! - if _unit ~= nil and _unit:getPlayerName() == nil then - local _zone = ctld.inPickupZone(_unit) + -- no player name means AI! + if _unit ~= nil and _unit:getPlayerName() == nil then + local _zone = ctld.inPickupZone(_unit) + -- env.error("Checking.. ".._unit:getName()) + if _zone.inZone == true and not ctld.troopsOnboard(_unit, true) then + -- env.error("in zone, loading.. ".._unit:getName()) + ctld.loadTroopsFromZone({ _unitName, true,"",true }) - if _zone.inZone == true and not ctld.troopsOnboard(_unit, true) then + elseif ctld.inDropoffZone(_unit) and ctld.troopsOnboard(_unit, true) then + -- env.error("in dropoff zone, unloading.. ".._unit:getName()) + ctld.unloadTroops( { _unitName, true }) + end - ctld.loadTroopsFromZone({ _unitName, true,"",true }) + if ctld.unitCanCarryVehicles(_unit) then - elseif ctld.inDropoffZone(_unit) and ctld.troopsOnboard(_unit, true) then + if _zone.inZone == true and not ctld.troopsOnboard(_unit, false) then - ctld.unloadTroops( { _unitName, true }) - end + ctld.loadTroopsFromZone({ _unitName, false,"",true }) - if ctld.unitCanCarryVehicles(_unit) then + elseif ctld.inDropoffZone(_unit) and ctld.troopsOnboard(_unit, false) then - if _zone.inZone == true and not ctld.troopsOnboard(_unit, false) then - - ctld.loadTroopsFromZone({ _unitName, false,"",true }) - - elseif ctld.inDropoffZone(_unit) and ctld.troopsOnboard(_unit, false) then - - ctld.unloadTroops( { _unitName, false }) + ctld.unloadTroops( { _unitName, false }) + end end end + end) + + if (not status) then + env.error(string.format("Error with ai status: %s", error), false) end end + + end @@ -5039,7 +5049,7 @@ end timer.scheduleFunction(ctld.refreshSmoke, nil, timer.getTime() + 5) timer.scheduleFunction(ctld.addF10MenuOptions, nil, timer.getTime() + 5) -timer.scheduleFunction(ctld.checkAIStatus, nil, timer.getTime() + 5) +timer.scheduleFunction(ctld.checkAIStatus, nil, timer.getTime() + 1) timer.scheduleFunction(ctld.checkTransportStatus, nil, timer.getTime() + 5) timer.scheduleFunction(ctld.refreshRadioBeacons, nil, timer.getTime() + 5) diff --git a/Pickup-Dropoff-Demo.miz b/Pickup-Dropoff-Demo.miz index 38fd6ab..c3a0c39 100644 Binary files a/Pickup-Dropoff-Demo.miz and b/Pickup-Dropoff-Demo.miz differ diff --git a/mist.lua b/mist.lua index 84fca47..ad4d2d0 100644 --- a/mist.lua +++ b/mist.lua @@ -15,242 +15,242 @@ mist = {} -- don't change these mist.majorVersion = 4 mist.minorVersion = 0 -mist.build = 55 +mist.build = 57 -------------------------------------------------------------------------------------------------------------- -- the main area do local coroutines = {} - + local tempSpawnedUnits = {} -- birth events added here local mistAddedObjects = {} -- mist.dynAdd unit data added here local mistAddedGroups = {} -- mist.dynAdd groupdata added here local writeGroups = {} local lastUpdateTime = 0 - + local function update_alive_units() -- coroutine function - local lalive_units = mist.DBs.aliveUnits -- local references for faster execution - local lunits = mist.DBs.unitsByNum - local ldeepcopy = mist.utils.deepCopy - local lUnit = Unit - local lremovedAliveUnits = mist.DBs.removedAliveUnits - local updatedUnits = {} - - if #lunits > 0 then - local units_per_run = math.ceil(#lunits/20) - if units_per_run < 5 then - units_per_run = 5 - end - - for i = 1, #lunits do - if lunits[i].category ~= 'static' then -- can't get statics with Unit.getByName :( - local unit = lUnit.getByName(lunits[i].unitName) - if unit then - --print('unit named ' .. lunits[i].unitName .. ' alive!') - local pos = unit:getPosition() - local newtbl = ldeepcopy(lunits[i]) - if pos then - newtbl['pos'] = pos.p + local lalive_units = mist.DBs.aliveUnits -- local references for faster execution + local lunits = mist.DBs.unitsByNum + local ldeepcopy = mist.utils.deepCopy + local lUnit = Unit + local lremovedAliveUnits = mist.DBs.removedAliveUnits + local updatedUnits = {} + + if #lunits > 0 then + local units_per_run = math.ceil(#lunits/20) + if units_per_run < 5 then + units_per_run = 5 + end + + for i = 1, #lunits do + if lunits[i].category ~= 'static' then -- can't get statics with Unit.getByName :( + local unit = lUnit.getByName(lunits[i].unitName) + if unit then + --print('unit named ' .. lunits[i].unitName .. ' alive!') + local pos = unit:getPosition() + local newtbl = ldeepcopy(lunits[i]) + if pos then + newtbl['pos'] = pos.p + end + newtbl['unit'] = unit + --newtbl['rt_id'] = unit.id_ + lalive_units[unit.id_] = newtbl + updatedUnits[unit.id_] = true + end + end + if i%units_per_run == 0 then + --print('yielding at: ' .. tostring(i)) + coroutine.yield() + --print('resuming at: ' .. tostring(i)) end - newtbl['unit'] = unit - --newtbl['rt_id'] = unit.id_ - lalive_units[unit.id_] = newtbl - updatedUnits[unit.id_] = true end - end - if i%units_per_run == 0 then - --print('yielding at: ' .. tostring(i)) - coroutine.yield() - --print('resuming at: ' .. tostring(i)) - end - end - -- All units updated, remove any "alive" units that were not updated- they are dead! - for unit_id, unit in pairs(lalive_units) do - if not updatedUnits[unit_id] then - lremovedAliveUnits[unit_id] = unit - lalive_units[unit_id] = nil + -- All units updated, remove any "alive" units that were not updated- they are dead! + for unit_id, unit in pairs(lalive_units) do + if not updatedUnits[unit_id] then + lremovedAliveUnits[unit_id] = unit + lalive_units[unit_id] = nil + end end end end - end - + local function dbUpdate(event) local newTable = {} - + newTable['startTime'] = 0 - + if type(event) == 'string' then -- if name of an object. - local newObject - local newType = 'group' - if Group.getByName(event) then - newObject = Group.getByName(event) - elseif StaticObject.getByName(event) then - newObject = StaticObject.getByName(event) - newType = 'static' - -- env.info('its static') - else - env.info('WTF') - return false - end + local newObject + local newType = 'group' + if Group.getByName(event) then + newObject = Group.getByName(event) + elseif StaticObject.getByName(event) then + newObject = StaticObject.getByName(event) + newType = 'static' + -- env.info('its static') + else + env.info('WTF') + return false + end + - - - newTable.name = newObject:getName() - newTable.groupId = tonumber(newObject:getID()) - newTable.groupName = newObject:getName() - local unitOneRef - if newType == 'static' then - unitOneRef = newObject - newTable.countryId = tonumber(newObject:getCountry()) - newTable.coalitionId = tonumber(newObject:getCoalition()) - newTable.category = 'static' - else - unitOneRef = newObject:getUnits() - newTable.countryId = tonumber(unitOneRef[1]:getCountry()) - newTable.coalitionId = tonumber(unitOneRef[1]:getCoalition()) - newTable.category = tonumber(newObject:getCategory()) - end - for countryData, countryId in pairs(country.id) do - if newTable.country and string.upper(countryData) == string.upper(newTable.country) or countryId == newTable.countryId then - newTable['countryId'] = countryId - newTable['country'] = string.lower(countryData) - for coaData, coaId in pairs(coalition.side) do - if coaId == coalition.getCountryCoalition(countryId) then - newTable['coalition'] = string.lower(coaData) + + newTable.name = newObject:getName() + newTable.groupId = tonumber(newObject:getID()) + newTable.groupName = newObject:getName() + local unitOneRef + if newType == 'static' then + unitOneRef = newObject + newTable.countryId = tonumber(newObject:getCountry()) + newTable.coalitionId = tonumber(newObject:getCoalition()) + newTable.category = 'static' + else + unitOneRef = newObject:getUnits() + newTable.countryId = tonumber(unitOneRef[1]:getCountry()) + newTable.coalitionId = tonumber(unitOneRef[1]:getCoalition()) + newTable.category = tonumber(newObject:getCategory()) + end + for countryData, countryId in pairs(country.id) do + if newTable.country and string.upper(countryData) == string.upper(newTable.country) or countryId == newTable.countryId then + newTable['countryId'] = countryId + newTable['country'] = string.lower(countryData) + for coaData, coaId in pairs(coalition.side) do + if coaId == coalition.getCountryCoalition(countryId) then + newTable['coalition'] = string.lower(coaData) + end end end end - end - for catData, catId in pairs(Unit.Category) do - if newType == 'group' and Group.getByName(newTable.groupName):isExist() then - if catId == Group.getByName(newTable.groupName):getCategory() then - newTable['category'] = string.lower(catData) + for catData, catId in pairs(Unit.Category) do + if newType == 'group' and Group.getByName(newTable.groupName):isExist() then + if catId == Group.getByName(newTable.groupName):getCategory() then + newTable['category'] = string.lower(catData) + end + elseif newType == 'static' and StaticObject.getByName(newTable.groupName):isExist() then + if catId == StaticObject.getByName(newTable.groupName):getCategory() then + newTable['category'] = string.lower(catData) + end + end - elseif newType == 'static' and StaticObject.getByName(newTable.groupName):isExist() then - if catId == StaticObject.getByName(newTable.groupName):getCategory() then - newTable['category'] = string.lower(catData) + end + local gfound = false + for index, data in pairs(mistAddedGroups) do + if mist.stringMatch(data.name, newTable.groupName) == true then + gfound = true + newTable.task = data.task + newTable.modulation = data.modulation + newTable.uncontrolled = data.uncontrolled + newTable.radioSet = data.radioSet + newTable.hidden = data.hidden + newTable.startTime = data.start_time + mistAddedGroups[index] = nil end - end - end - local gfound = false - for index, data in pairs(mistAddedGroups) do - if mist.stringMatch(data.name, newTable.groupName) == true then - gfound = true - newTable.task = data.task - newTable.modulation = data.modulation - newTable.uncontrolled = data.uncontrolled - newTable.radioSet = data.radioSet - newTable.hidden = data.hidden - newTable.startTime = data.start_time - mistAddedGroups[index] = nil + + if gfound == false then + newTable.uncontrolled = false + newTable.hidden = false end - end + + newTable.units = {} + if newType == 'group' then + for unitId, unitData in pairs(unitOneRef) do + newTable.units[unitId] = {} + newTable.units[unitId].unitName = unitData:getName() + + newTable.units[unitId].x = mist.utils.round(unitData:getPosition().p.x) + newTable.units[unitId].y = mist.utils.round(unitData:getPosition().p.z) + newTable.units[unitId].point = {} + newTable.units[unitId].point.x = newTable.units[unitId].x + newTable.units[unitId].point.y = newTable.units[unitId].y + newTable.units[unitId].alt = mist.utils.round(unitData:getPosition().p.y) + newTable.units[unitId].speed = mist.vec.mag(unitData:getVelocity()) + + newTable.units[unitId].heading = mist.getHeading(unitData, true) - if gfound == false then - newTable.uncontrolled = false - newTable.hidden = false - end - - newTable.units = {} - if newType == 'group' then - for unitId, unitData in pairs(unitOneRef) do - newTable.units[unitId] = {} - newTable.units[unitId].unitName = unitData:getName() - - newTable.units[unitId].x = mist.utils.round(unitData:getPosition().p.x) - newTable.units[unitId].y = mist.utils.round(unitData:getPosition().p.z) - newTable.units[unitId].point = {} - newTable.units[unitId].point.x = newTable.units[unitId].x - newTable.units[unitId].point.y = newTable.units[unitId].y - newTable.units[unitId].alt = mist.utils.round(unitData:getPosition().p.y) - newTable.units[unitId].speed = mist.vec.mag(unitData:getVelocity()) - - newTable.units[unitId].heading = mist.getHeading(unitData, true) - - newTable.units[unitId].type = unitData:getTypeName() - newTable.units[unitId].unitId = tonumber(unitData:getID()) - - - newTable.units[unitId].groupName = newTable.groupName - newTable.units[unitId].groupId = newTable.groupId - newTable.units[unitId].countryId = newTable.countryId - newTable.units[unitId].coalitionId = newTable.coalitionId - newTable.units[unitId].coalition = newTable.coalition - newTable.units[unitId].country = newTable.country - local found = false + newTable.units[unitId].type = unitData:getTypeName() + newTable.units[unitId].unitId = tonumber(unitData:getID()) + + + newTable.units[unitId].groupName = newTable.groupName + newTable.units[unitId].groupId = newTable.groupId + newTable.units[unitId].countryId = newTable.countryId + newTable.units[unitId].coalitionId = newTable.coalitionId + newTable.units[unitId].coalition = newTable.coalition + newTable.units[unitId].country = newTable.country + local found = false + for index, data in pairs(mistAddedObjects) do + if mist.stringMatch(data.name, newTable.units[unitId].unitName) == true then + found = true + newTable.units[unitId].livery_id = data.livery_id + newTable.units[unitId].skill = data.skill + newTable.units[unitId].alt_type = data.alt_type + newTable.units[unitId].callsign = data.callsign + newTable.units[unitId].psi = data.psi + mistAddedObjects[index] = nil + end + if found == false then + newTable.units[unitId].skill = "High" + newTable.units[unitId].alt_type = "BARO" + end + end + + end + else -- its a static + newTable.category = 'static' + newTable.units[1] = {} + newTable.units[1].unitName = newObject:getName() + newTable.units[1].category = 'static' + newTable.units[1].x = mist.utils.round(newObject:getPosition().p.x) + newTable.units[1].y = mist.utils.round(newObject:getPosition().p.z) + newTable.units[1].point = {} + newTable.units[1].point.x = newTable.units[1].x + newTable.units[1].point.y = newTable.units[1].y + newTable.units[1].alt = mist.utils.round(newObject:getPosition().p.y) + newTable.units[1].heading = mist.getHeading(newObject, true) + newTable.units[1].type = newObject:getTypeName() + newTable.units[1].unitId = tonumber(newObject:getID()) + newTable.units[1].groupName = newTable.name + newTable.units[1].groupId = newTable.groupId + newTable.units[1].countryId = newTable.countryId + newTable.units[1].country = newTable.country + newTable.units[1].coalitionId = newTable.coalitionId + newTable.units[1].coalition = newTable.coalition + if newObject:getCategory() == 6 and newObject:getCargoDisplayName() then + local mass = newObject:getCargoDisplayName() + mass = string.gsub(mass, ' ', '') + mass = string.gsub(mass, 'kg', '') + newTable.units[1].mass = tonumber(mass) + newTable.units[1].categoryStatic = 'Cargos' + newTable.units[1].canCargo = true + newTable.units[1].shape_name = 'ab-212_cargo' + end + + ----- search mist added objects for extra data if applicable for index, data in pairs(mistAddedObjects) do - if mist.stringMatch(data.name, newTable.units[unitId].unitName) == true then - found = true - newTable.units[unitId].livery_id = data.livery_id - newTable.units[unitId].skill = data.skill - newTable.units[unitId].alt_type = data.alt_type - newTable.units[unitId].callsign = data.callsign - newTable.units[unitId].psi = data.psi + if mist.stringMatch(data.name, newTable.units[1].unitName) == true then + newTable.units[1].shape_name = data.shape_name -- for statics + newTable.units[1].livery_id = data.livery_id + newTable.units[1].airdromeId = data.airdromeId + newTable.units[1].mass = data.mass + newTable.units[1].canCargo = data.canCargo + newTable.units[1].categoryStatic = data.categoryStatic + newTable.units[1].type = 'cargo1' mistAddedObjects[index] = nil end - if found == false then - newTable.units[unitId].skill = "High" - newTable.units[unitId].alt_type = "BARO" - end end - - end - else -- its a static - newTable.category = 'static' - newTable.units[1] = {} - newTable.units[1].unitName = newObject:getName() - newTable.units[1].category = 'static' - newTable.units[1].x = mist.utils.round(newObject:getPosition().p.x) - newTable.units[1].y = mist.utils.round(newObject:getPosition().p.z) - newTable.units[1].point = {} - newTable.units[1].point.x = newTable.units[1].x - newTable.units[1].point.y = newTable.units[1].y - newTable.units[1].alt = mist.utils.round(newObject:getPosition().p.y) - newTable.units[1].heading = mist.getHeading(newObject, true) - newTable.units[1].type = newObject:getTypeName() - newTable.units[1].unitId = tonumber(newObject:getID()) - newTable.units[1].groupName = newTable.name - newTable.units[1].groupId = newTable.groupId - newTable.units[1].countryId = newTable.countryId - newTable.units[1].country = newTable.country - newTable.units[1].coalitionId = newTable.coalitionId - newTable.units[1].coalition = newTable.coalition - if newObject:getCategory() == 6 and newObject:getCargoDisplayName() then - local mass = newObject:getCargoDisplayName() - mass = string.gsub(mass, ' ', '') - mass = string.gsub(mass, 'kg', '') - newTable.units[1].mass = tonumber(mass) - newTable.units[1].categoryStatic = 'Cargos' - newTable.units[1].canCargo = true - newTable.units[1].shape_name = 'ab-212_cargo' - end - - ----- search mist added objects for extra data if applicable - for index, data in pairs(mistAddedObjects) do - if mist.stringMatch(data.name, newTable.units[1].unitName) == true then - newTable.units[1].shape_name = data.shape_name -- for statics - newTable.units[1].livery_id = data.livery_id - newTable.units[1].airdromeId = data.airdromeId - newTable.units[1].mass = data.mass - newTable.units[1].canCargo = data.canCargo - newTable.units[1].categoryStatic = data.categoryStatic - newTable.units[1].type = 'cargo1' - mistAddedObjects[index] = nil end end - end - end - + newTable['timeAdded'] = timer.getAbsTime() -- only on the dynGroupsAdded table. For other reference, see start time --mist.debug.dumpDBs() --end - + return newTable end + - - + local function checkSpawnedEvents() if #tempSpawnedUnits > 0 then local groupsToAdd = {} @@ -267,36 +267,36 @@ do local found = false for index, name in pairs(groupsToAdd) do if spawnedObj:getCategory() == 1 then -- normal groups - if mist.stringMatch(spawnedObj:getGroup():getName(), name) == true then - found = true - break - end + if mist.stringMatch(spawnedObj:getGroup():getName(), name) == true then + found = true + break + end elseif spawnedObj:getCategory() == 3 or spawnedObj:getCategory() == 6 then -- static objects - if mist.stringMatch(spawnedObj:getName(), name) == true then - found = true - break - end + if mist.stringMatch(spawnedObj:getName(), name) == true then + found = true + break + end end end -- for some reason cargo objects are returning as category == 6. if found == false then if spawnedObj:getCategory() == 1 then -- normal groups - groupsToAdd[#groupsToAdd + 1] = spawnedObj:getGroup():getName() + groupsToAdd[#groupsToAdd + 1] = spawnedObj:getGroup():getName() elseif spawnedObj:getCategory() == 3 or spawnedObj:getCategory() == 6 then -- static objects - groupsToAdd[#groupsToAdd + 1] = spawnedObj:getName() + groupsToAdd[#groupsToAdd + 1] = spawnedObj:getName() end end end - + table.remove(ltemp, x) - if x%updatesPerRun == 0 then + if x%updatesPerRun == 0 then coroutine.yield() - end - + end + end - - + + if #groupsToAdd > 0 then for groupId, groupName in pairs(groupsToAdd) do if not mist.DBs.groupsByName[groupName] or mist.DBs.groupsByName[groupName] and mist.DBs.groupsByName[groupName].startTime + 10 < timer.getAbsTime() then @@ -306,8 +306,8 @@ do end end end - - + + local function updateDBTables() local i = 0 for index, newTable in pairs(writeGroups) do @@ -321,7 +321,7 @@ do local ldeepCopy = mist.utils.deepCopy for x = 1, i do local newTable = writeGroups[x] - local mistCategory + local mistCategory if type(newTable.category) == 'string' then mistCategory = string.lower(newTable.category) end @@ -337,19 +337,19 @@ do newTable['category'] = mistCategory elseif string.upper(newTable['category']) == 'SHIP' then mistCategory = 'ship' - newTable['category'] = mistCategory + newTable['category'] = mistCategory end for newId, newUnitData in pairs(newTable.units) do newUnitData.category = mistCategory if newUnitData.unitId then - mist.DBs.unitsById[tonumber(newUnitData.unitId)] = ldeepCopy(newUnitData) + mist.DBs.unitsById[tonumber(newUnitData.unitId)] = ldeepCopy(newUnitData) end - + mist.DBs.unitsByName[newUnitData.unitName] = ldeepCopy(newUnitData) mist.DBs.unitsByCat[mistCategory][#mist.DBs.unitsByCat[mistCategory] + 1] = ldeepCopy(newUnitData) - mist.DBs.unitsByNum[#mist.DBs.unitsByNum + 1] = ldeepCopy(newUnitData) + mist.DBs.unitsByNum[#mist.DBs.unitsByNum + 1] = ldeepCopy(newUnitData) end - -- this is a really annoying DB to populate. Gotta create new tables in case its missing + -- this is a really annoying DB to populate. Gotta create new tables in case its missing if not mist.DBs.units[newTable.coalition] then mist.DBs.units[newTable.coalition] = {} end @@ -362,16 +362,16 @@ do mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory] = {} end mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory][#mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory] + 1] = ldeepCopy(newTable) - + if newTable.groupId then mist.DBs.groupsById[newTable.groupId] = ldeepCopy(newTable) end - + mist.DBs.groupsByName[newTable.name] = ldeepCopy(newTable) mist.DBs.dynGroupsAdded[#mist.DBs.dynGroupsAdded + 1] = ldeepCopy(newTable) - + writeGroups[x] = nil - if x%savesPerRun == 0 then + if x%savesPerRun == 0 then coroutine.yield() end end @@ -380,65 +380,65 @@ do end end end - + local update_alive_units_counter = 0 local write_DB_table_counter = 0 local check_spawn_events_counter = 0 - + -- THE MAIN FUNCTION -- Accessed 100 times/sec. mist.main = function() timer.scheduleFunction(mist.main, {}, timer.getTime() + 0.01) --reschedule first in case of Lua error ---------------------------------------------------------------------------------------------------------- --area to add new stuff in write_DB_table_counter = write_DB_table_counter + 1 - if write_DB_table_counter == 10 then - + if write_DB_table_counter == 10 then + write_DB_table_counter = 0 - + if not coroutines.updateDBTables then coroutines['updateDBTables'] = coroutine.create(updateDBTables) end - + coroutine.resume(coroutines.updateDBTables) - + if coroutine.status(coroutines.updateDBTables) == 'dead' then coroutines.updateDBTables = nil end end check_spawn_events_counter = check_spawn_events_counter + 1 - if check_spawn_events_counter == 10 then - + if check_spawn_events_counter == 10 then + check_spawn_events_counter = 0 - + if not coroutines.checkSpawnedEvents then coroutines['checkSpawnedEvents'] = coroutine.create(checkSpawnedEvents) end - + coroutine.resume(coroutines.checkSpawnedEvents) - + if coroutine.status(coroutines.checkSpawnedEvents) == 'dead' then coroutines.checkSpawnedEvents = nil end end - + ----------------------------------------------------------------------------------------------------------- --updating alive units update_alive_units_counter = update_alive_units_counter + 1 - if update_alive_units_counter == 5 then + if update_alive_units_counter == 5 then update_alive_units_counter = 0 - + if not coroutines.update_alive_units then coroutines['update_alive_units'] = coroutine.create(update_alive_units) end - + coroutine.resume(coroutines.update_alive_units) - + if coroutine.status(coroutines.update_alive_units) == 'dead' then coroutines.update_alive_units = nil end end - + mist.do_scheduled_functions() end -- end of mist.main -------------------------------------------- @@ -446,11 +446,11 @@ do local mistGpId = 7000 local mistUnitId = 7000 local mistDynAddIndex = 1 - - - mist.nextGroupId = 1 - mist.nextUnitId = 1 - + + + mist.nextGroupId = 1 + mist.nextUnitId = 1 + mist.getNextUnitId = function() mist.nextUnitId = mist.nextUnitId + 1 if mist.nextUnitId > 6900 then @@ -458,7 +458,7 @@ do end return mist.nextUnitId end - + mist.getNextGroupId = function() mist.nextGroupId = mist.nextGroupId + 1 if mist.nextGroupId > 6900 then @@ -466,20 +466,20 @@ do end return mist.nextGroupId end - + mist.getLastDBUpdateTime = function() return lastUpdateTime end - + local function groupSpawned(event) if event.id == world.event.S_EVENT_BIRTH and timer.getTime0() < timer.getAbsTime()then -- dont need to add units spawned in at the start of the mission if mist is loaded in init line - table.insert(tempSpawnedUnits,(event.initiator)) + table.insert(tempSpawnedUnits,(event.initiator)) end end - - - + + + mist.dynAddStatic = function(staticObj) local newObj = {} newObj.groupId = staticObj.groupId @@ -492,37 +492,39 @@ do newObj.name = staticObj.name newObj.dead = staticObj.dead newObj.country = staticObj.country + newObj.countryId = staticObj.countryId newObj.clone = staticObj.clone newObj.shape_name = staticObj.shape_name newObj.canCargo = staticObj.canCargo newObj.mass = staticObj.mass newObj.categoryStatic = staticObj.categoryStatic if staticObj.units then -- if its mist format - newObj.groupId = staticObj.units[1].groupId - newObj.category = staticObj.units[1].category - newObj.type = staticObj.units[1].type - newObj.unitId = staticObj.units[1].unitId - newObj.y = staticObj.units[1].y - newObj.x = staticObj.units[1].x - newObj.heading = staticObj.units[1].heading - newObj.name = staticObj.units[1].name - newObj.dead = staticObj.units[1].dead - newObj.country = staticObj.units[1].country - newObj.shape_name = staticObj.units[1].shape_name - newObj.canCargo = staticObj.units[1].canCargo - newObj.mass = staticObj.units[1].mass - newObj.categoryStatic = staticObj.units[1].categoryStatic + newObj.groupId = staticObj.units[1].groupId + newObj.category = staticObj.units[1].category + newObj.type = staticObj.units[1].type + newObj.unitId = staticObj.units[1].unitId + newObj.y = staticObj.units[1].y + newObj.x = staticObj.units[1].x + newObj.heading = staticObj.units[1].heading + newObj.name = staticObj.units[1].name + newObj.dead = staticObj.units[1].dead + newObj.country = staticObj.units[1].country + newObj.countryId = staticObj.units[1].countryId + newObj.shape_name = staticObj.units[1].shape_name + newObj.canCargo = staticObj.units[1].canCargo + newObj.mass = staticObj.units[1].mass + newObj.categoryStatic = staticObj.units[1].categoryStatic end - - - newObj.country = staticObj.country - + if not newObj.country then return false end - - local newCountry - for countryName, countryId in pairs(country.id) do + + local newCountry = newObj.country + if newObj.countryId then + newCountry = newObj.countryId + end + for countryId, countryName in pairs(country.name) do if type(newObj.country) == 'string' then if tostring(countryName) == string.upper(newObj.country) then newCountry = countryName @@ -533,30 +535,30 @@ do end end end - + if newObj.clone or not newObj.groupId then - mistGpId = mistGpId + 1 + mistGpId = mistGpId + 1 newObj.groupId = mistGpId end - + if newObj.clone or not newObj.unitId then - mistUnitId = mistUnitId + 1 + mistUnitId = mistUnitId + 1 newObj.unitId = mistUnitId end - + if newObj.clone or not newObj.name then mistDynAddIndex = mistDynAddIndex + 1 newObj.name = (newCountry .. ' static ' .. mistDynAddIndex) end - + if not newObj.dead then newObj.dead = false end - + if not newObj.heading then newObj.heading = math.random(360) end - + if newObj.categoryStatic then newObj.category = newObj.categoryStatic end @@ -568,21 +570,26 @@ do coalition.addStaticObject(country.id[newCountry], newObj) return newObj - end + end return false end mist.dynAdd = function(newGroup) -- same as coalition.add function in SSE. checks the passed data to see if its valid. - --Will generate groupId, groupName, unitId, and unitName if needed - -- +--Will generate groupId, groupName, unitId, and unitName if needed +-- + + - - --env.info('dynAdd') + --mist.debug.writeData(mist.utils.serialize,{'msg', newGroup}, 'newGroupOrig.lua') local cntry = newGroup.country + if newGroup.countryId then + cntry = newGroup.countryId + end + local groupType = newGroup.category local newCountry = '' -- validate data - for countryName, countryId in pairs(country.id) do + for countryId, countryName in pairs(country.name) do if type(cntry) == 'string' then if tostring(countryName) == string.upper(cntry) then newCountry = countryName @@ -593,11 +600,11 @@ do end end end - + if newCountry == '' then return false end - + local newCat = '' for catName, catId in pairs(Unit.Category) do if type(groupType) == 'string' then @@ -609,15 +616,14 @@ do newCat = catName end end - + if catName == 'GROUND_UNIT' and (string.upper(groupType) == 'VEHICLE' or string.upper(groupType) == 'GROUND') then newCat = 'GROUND_UNIT' elseif catName == 'AIRPLANE' and string.upper(groupType) == 'PLANE' then newCat = 'AIRPLANE' end end - - local typeName + local typeName if newCat == 'GROUND_UNIT' then typeName = ' gnd ' elseif newCat == 'AIRPLANE' then @@ -629,10 +635,9 @@ do elseif newCat == 'BUILDING' then typeName = ' bld ' end - if newGroup.clone or not newGroup.groupId then mistDynAddIndex = mistDynAddIndex + 1 - mistGpId = mistGpId + 1 + mistGpId = mistGpId + 1 newGroup.groupId = mistGpId end if newGroup.groupName or newGroup.name then @@ -642,19 +647,19 @@ do newGroup['name'] = newGroup.name end end - + if newGroup.clone and mist.DBs.groupsByName[newGroup.name] or not newGroup.name then newGroup['name'] = tostring(tostring(cntry) .. tostring(typeName) .. mistDynAddIndex) end - + if not newGroup.hidden then newGroup.hidden = false end - + if not newGroup.visible then newGroup.visible = false end - + if (newGroup.start_time and type(newGroup.start_time) ~= 'number') or not newGroup.start_time then if newGroup.startTime then newGroup.start_time = mist.utils.round(newGroup.startTime) @@ -662,11 +667,12 @@ do newGroup.start_time = 0 end end + + for unitIndex, unitData in pairs(newGroup.units) do - local originalName = newGroup.units[unitIndex].unitName or newGroup.units[unitIndex].name if newGroup.clone or not unitData.unitId then - mistUnitId = mistUnitId + 1 + mistUnitId = mistUnitId + 1 newGroup.units[unitIndex]['unitId'] = mistUnitId end if newGroup.units[unitIndex].unitName or newGroup.units[unitIndex].name then @@ -679,11 +685,11 @@ do if newGroup.clone or not unitData.name then newGroup.units[unitIndex].name = tostring(newGroup.name .. ' unit' .. unitIndex) end - - if not unitData.skill then + + if not unitData.skill then newGroup.units[unitIndex].skill = 'Random' end - + if not unitData.alt then if newCat == 'AIRPLANE' then newGroup.units[unitIndex].alt = 2000 @@ -695,13 +701,13 @@ do newGroup.units[unitIndex].speed = 60 else --[[env.info('check height') - newGroup.units[unitIndex].alt = land.getHeight({x = newGroup.units[unitIndex].x, y = newGroup.units[unitIndex].y}) - newGroup.units[unitIndex].alt_type = 'BARO']] + newGroup.units[unitIndex].alt = land.getHeight({x = newGroup.units[unitIndex].x, y = newGroup.units[unitIndex].y}) + newGroup.units[unitIndex].alt_type = 'BARO']] end - + end - + if newCat == 'AIRPLANE' or newCat == 'HELICOPTER' then if newGroup.units[unitIndex].alt_type and newGroup.units[unitIndex].alt_type ~= 'BARO' or not newGroup.units[unitIndex].alt_type then newGroup.units[unitIndex].alt_type = 'RADIO' @@ -720,7 +726,6 @@ do mistAddedObjects[#mistAddedObjects + 1] = mist.utils.deepCopy(newGroup.units[unitIndex]) end mistAddedGroups[#mistAddedGroups + 1] = mist.utils.deepCopy(newGroup) - if newGroup.route and not newGroup.route.points then if not newGroup.route.points and newGroup.route[1] then local copyRoute = newGroup.route @@ -729,42 +734,42 @@ do end end newGroup.country = newCountry - - + + --mist.debug.writeData(mist.utils.serialize,{'msg', newGroup}, 'newGroup.lua') - + -- sanitize table newGroup.groupName = nil newGroup.clone = nil newGroup.category = nil newGroup.country = nil - + newGroup.tasks = {} - + for unitIndex, unitData in pairs(newGroup.units) do newGroup.units[unitIndex].unitName = nil end - + coalition.addGroup(country.id[newCountry], Unit.Category[newCat], newGroup) - + return newGroup - + end - --------------------------------------------------------------------------------------------- - --Modified Slmod task scheduler, superior to timer.scheduleFunction - +--------------------------------------------------------------------------------------------- +--Modified Slmod task scheduler, superior to timer.scheduleFunction + local Tasks = {} local task_id = 0 --[[ mist.scheduleFunction: - int id = mist.schedule_task(f function, vars table, t number, rep number, st number) - id - integer id of this function task - f - function to run - vars - table of vars for that function - t - time to run function - rep - time between repetitions of this function (OPTIONAL) - st - time when repetitions of this function will stop automatically (OPTIONAL) - ]] + int id = mist.schedule_task(f function, vars table, t number, rep number, st number) + id - integer id of this function task + f - function to run + vars - table of vars for that function + t - time to run function + rep - time between repetitions of this function (OPTIONAL) + st - time when repetitions of this function will stop automatically (OPTIONAL) + ]] mist.scheduleFunction = function(f, vars, t, rep, st) --verify correct types assert(type(f) == 'function', 'variable 1, expected function, got ' .. type(f)) @@ -779,7 +784,7 @@ do table.insert(Tasks, {f = f, vars = vars, t = t, rep = rep, st = st, id = task_id}) return task_id end - + -- removes a scheduled function based on the function's id. returns true if successful, false if not successful. mist.removeFunction = function(id) local i = 1 @@ -798,20 +803,20 @@ do local i = 1 while i <= #Tasks do if not Tasks[i].rep then -- not a repeated process - if Tasks[i].t <= timer.getTime() then - local Task = Tasks[i] -- local reference - table.remove(Tasks, i) - local err, errmsg = pcall(Task.f, unpack(Task.vars, 1, table.maxn(Task.vars))) - if not err then - env.info('mist.scheduleFunction, error in scheduled function: ' .. errmsg) + if Tasks[i].t <= timer.getTime() then + local Task = Tasks[i] -- local reference + table.remove(Tasks, i) + local err, errmsg = pcall(Task.f, unpack(Task.vars, 1, table.maxn(Task.vars))) + if not err then + env.info('mist.scheduleFunction, error in scheduled function: ' .. errmsg) + end + --Task.f(unpack(Task.vars, 1, table.maxn(Task.vars))) -- do the task, do not increment i + else + i = i + 1 end - --Task.f(unpack(Task.vars, 1, table.maxn(Task.vars))) -- do the task, do not increment i - else - i = i + 1 - end else if Tasks[i].st and Tasks[i].st <= timer.getTime() then --if a stoptime was specified, and the stop time exceeded - table.remove(Tasks, i) -- stop time exceeded, do not execute, do not increment i + table.remove(Tasks, i) -- stop time exceeded, do not execute, do not increment i elseif Tasks[i].t <= timer.getTime() then local Task = Tasks[i] -- local reference Task.t = timer.getTime() + Task.rep --schedule next run @@ -828,21 +833,21 @@ do end end - + local idNum = 0 --Simplified event handler mist.addEventHandler = function(f) --id is optional! - local handler = {} - idNum = idNum + 1 - handler.id = idNum - handler.f = f - handler.onEvent = function(self, event) - self.f(event) - end - world.addEventHandler(handler) - return handler.id + local handler = {} + idNum = idNum + 1 + handler.id = idNum + handler.f = f + handler.onEvent = function(self, event) + self.f(event) + end + world.addEventHandler(handler) + return handler.id end mist.removeEventHandler = function(id) @@ -853,11 +858,11 @@ do end end return false - end + end mist.addEventHandler(groupSpawned) - -- mist.scheduleFunction(checkSpawnedEvents, {}, timer.getTime() + 5, 1) - +-- mist.scheduleFunction(checkSpawnedEvents, {}, timer.getTime() + 5, 1) + end ------------------------------------------------------------------------------------------------------------ @@ -927,7 +932,7 @@ end function mist.utils.makeVec3GL(Vec2, offset) local adj = offset or 0 - + if not Vec2.z then return {x = Vec2.x, y = (land.getHeight(Vec2) + adj), z = Vec2.y} else @@ -1001,8 +1006,8 @@ end -- From http://lua-users.org/wiki/SimpleRound -- use negative idp for rounding ahead of decimal place, positive for rounding after decimal place mist.utils.round = function(num, idp) - local mult = 10^(idp or 0) - return math.floor(num * mult + 0.5) / mult + local mult = 10^(idp or 0) + return math.floor(num * mult + 0.5) / mult end -- porting in Slmod's dostring @@ -1038,12 +1043,12 @@ function mist.utils.typeCheck(fname, type_tbl, var_tbl) --print(type_key) --print('type_val:') --print(type_val) - + --type_key can be a table of accepted keys- so try to find one that is not nil local type_key_str = '' local act_key = type_key -- actual key within var_tbl - necessary to use for multiple possible key variables. Initialize to type_key if type(type_key) == 'table' then - + for i = 1, #type_key do if i ~= 1 then type_key_str = type_key_str .. '/' @@ -1056,21 +1061,21 @@ function mist.utils.typeCheck(fname, type_tbl, var_tbl) else type_key_str = tostring(type_key) end - + local err_msg = 'Error in function ' .. fname .. ', parameter "' .. type_key_str .. '", expected: ' local passed_check = false - + if type(type_tbl[type_key]) == 'table' then --print('err_msg, before and after:') --print(err_msg) for j = 1, #type_tbl[type_key] do - + if j == 1 then err_msg = err_msg .. type_tbl[type_key][j] else err_msg = err_msg .. ' or ' .. type_tbl[type_key][j] end - + if type(var_tbl[act_key]) == type_tbl[type_key][j] then passed_check = true end @@ -1083,11 +1088,11 @@ function mist.utils.typeCheck(fname, type_tbl, var_tbl) --print(err_msg) if type(var_tbl[act_key]) == type_tbl[type_key] then passed_check = true - + end - + end - + if not passed_check then err_msg = err_msg .. ', got ' .. type(var_tbl[act_key]) return false, err_msg @@ -1107,63 +1112,63 @@ mist.utils.basicSerialize = function(s) s = string.format('%q', s) return s end - end + end end --porting in Slmod's serialize_slmod mist.utils.serialize = function(name, value, level) -----Based on ED's serialize_simple2 local basicSerialize = function (o) - if type(o) == "number" then - return tostring(o) - elseif type(o) == "boolean" then - return tostring(o) - else -- assume it is a string + if type(o) == "number" then + return tostring(o) + elseif type(o) == "boolean" then + return tostring(o) + else -- assume it is a string return mist.utils.basicSerialize(o) - end + end end - + local serialize_to_t = function (name, value, level) - ----Based on ED's serialize_simple2 + ----Based on ED's serialize_simple2 - local var_str_tbl = {} - if level == nil then level = "" end - if level ~= "" then level = level.." " end - - table.insert(var_str_tbl, level .. name .. " = ") - - if type(value) == "number" or type(value) == "string" or type(value) == "boolean" then - table.insert(var_str_tbl, basicSerialize(value) .. ",\n") - elseif type(value) == "table" then - table.insert(var_str_tbl, "\n"..level.."{\n") - - for k,v in pairs(value) do -- serialize its fields + local var_str_tbl = {} + if level == nil then level = "" end + if level ~= "" then level = level.." " end + + table.insert(var_str_tbl, level .. name .. " = ") + + if type(value) == "number" or type(value) == "string" or type(value) == "boolean" then + table.insert(var_str_tbl, basicSerialize(value) .. ",\n") + elseif type(value) == "table" then + table.insert(var_str_tbl, "\n"..level.."{\n") + + for k,v in pairs(value) do -- serialize its fields local key if type(k) == "number" then - key = string.format("[%s]", k) + key = string.format("[%s]", k) else - key = string.format("[%q]", k) + key = string.format("[%q]", k) end table.insert(var_str_tbl, mist.utils.serialize(key, v, level.." ")) - end - if level == "" then - table.insert(var_str_tbl, level.."} -- end of "..name.."\n") + end + if level == "" then + table.insert(var_str_tbl, level.."} -- end of "..name.."\n") - else - table.insert(var_str_tbl, level.."}, -- end of "..name.."\n") + else + table.insert(var_str_tbl, level.."}, -- end of "..name.."\n") - end - else - env.info("Cannot serialize a "..type(value)) - end - return var_str_tbl + end + else + env.info("Cannot serialize a "..type(value)) + end + return var_str_tbl end - + local t_str = serialize_to_t(name, value, level) - + return table.concat(t_str) end @@ -1176,10 +1181,10 @@ mist.utils.serializeWithCycles = function(name, value, saved) elseif type(o) == "boolean" then return tostring(o) else -- assume it is a string - return mist.utils.basicSerialize(o) + return mist.utils.basicSerialize(o) end end - + local t_str = {} saved = saved or {} -- initial value if ((type(value) == 'string') or (type(value) == 'number') or (type(value) == 'table') or (type(value) == 'boolean')) then @@ -1189,13 +1194,13 @@ mist.utils.serializeWithCycles = function(name, value, saved) else if saved[value] then -- value already saved? - table.insert(t_str, saved[value] .. "\n") + table.insert(t_str, saved[value] .. "\n") else saved[value] = name -- save name for next time table.insert(t_str, "{}\n") for k,v in pairs(value) do -- save its fields - local fieldname = string.format("%s[%s]", name, basicSerialize(k)) - table.insert(t_str, mist.utils.serializeWithCycles(fieldname, v, saved)) + local fieldname = string.format("%s[%s]", name, basicSerialize(k)) + table.insert(t_str, mist.utils.serializeWithCycles(fieldname, v, saved)) end end end @@ -1207,111 +1212,111 @@ end -- porting in Slmod's serialize_slmod2 mist.utils.oneLineSerialize = function(tbl) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function -if type(tbl) == 'table' then --function only works for tables! + if type(tbl) == 'table' then --function only works for tables! -local tbl_str = {} + local tbl_str = {} -tbl_str[#tbl_str + 1] = '{ ' - -for ind,val in pairs(tbl) do -- serialize its fields -if type(ind) == "number" then - tbl_str[#tbl_str + 1] = '[' - tbl_str[#tbl_str + 1] = tostring(ind) - tbl_str[#tbl_str + 1] = '] = ' -else --must be a string -tbl_str[#tbl_str + 1] = '[' -tbl_str[#tbl_str + 1] = mist.utils.basicSerialize(ind) -tbl_str[#tbl_str + 1] = '] = ' -end - -if ((type(val) == 'number') or (type(val) == 'boolean')) then - tbl_str[#tbl_str + 1] = tostring(val) - tbl_str[#tbl_str + 1] = ', ' -elseif type(val) == 'string' then - tbl_str[#tbl_str + 1] = mist.utils.basicSerialize(val) - tbl_str[#tbl_str + 1] = ', ' -elseif type(val) == 'nil' then -- won't ever happen, right? -tbl_str[#tbl_str + 1] = 'nil, ' -elseif type(val) == 'table' then - tbl_str[#tbl_str + 1] = mist.utils.oneLineSerialize(val) - tbl_str[#tbl_str + 1] = ', ' --I think this is right, I just added it -else - env.info('unable to serialize value type ' .. mist.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind)) -end - -end -tbl_str[#tbl_str + 1] = '}' -return table.concat(tbl_str) -end + tbl_str[#tbl_str + 1] = '{ ' + + for ind,val in pairs(tbl) do -- serialize its fields + if type(ind) == "number" then + tbl_str[#tbl_str + 1] = '[' + tbl_str[#tbl_str + 1] = tostring(ind) + tbl_str[#tbl_str + 1] = '] = ' + else --must be a string + tbl_str[#tbl_str + 1] = '[' + tbl_str[#tbl_str + 1] = mist.utils.basicSerialize(ind) + tbl_str[#tbl_str + 1] = '] = ' + end + + if ((type(val) == 'number') or (type(val) == 'boolean')) then + tbl_str[#tbl_str + 1] = tostring(val) + tbl_str[#tbl_str + 1] = ', ' + elseif type(val) == 'string' then + tbl_str[#tbl_str + 1] = mist.utils.basicSerialize(val) + tbl_str[#tbl_str + 1] = ', ' + elseif type(val) == 'nil' then -- won't ever happen, right? + tbl_str[#tbl_str + 1] = 'nil, ' + elseif type(val) == 'table' then + tbl_str[#tbl_str + 1] = mist.utils.oneLineSerialize(val) + tbl_str[#tbl_str + 1] = ', ' --I think this is right, I just added it + else + env.info('unable to serialize value type ' .. mist.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind)) + end + + end + tbl_str[#tbl_str + 1] = '}' + return table.concat(tbl_str) + end end --Function to create string for viewing the contents of a table -NOT for serialization mist.utils.tableShow = function(tbl, loc, indent, tableshow_tbls) --based on serialize_slmod, this is a _G serialization -tableshow_tbls = tableshow_tbls or {} --create table of tables -loc = loc or "" -indent = indent or "" -if type(tbl) == 'table' then --function only works for tables! -tableshow_tbls[tbl] = loc + tableshow_tbls = tableshow_tbls or {} --create table of tables + loc = loc or "" + indent = indent or "" + if type(tbl) == 'table' then --function only works for tables! + tableshow_tbls[tbl] = loc + + local tbl_str = {} -local tbl_str = {} - -tbl_str[#tbl_str + 1] = indent .. '{\n' - -for ind,val in pairs(tbl) do -- serialize its fields -if type(ind) == "number" then - tbl_str[#tbl_str + 1] = indent - tbl_str[#tbl_str + 1] = loc .. '[' - tbl_str[#tbl_str + 1] = tostring(ind) - tbl_str[#tbl_str + 1] = '] = ' -else - tbl_str[#tbl_str + 1] = indent - tbl_str[#tbl_str + 1] = loc .. '[' - tbl_str[#tbl_str + 1] = mist.utils.basicSerialize(ind) - tbl_str[#tbl_str + 1] = '] = ' -end - -if ((type(val) == 'number') or (type(val) == 'boolean')) then - tbl_str[#tbl_str + 1] = tostring(val) - tbl_str[#tbl_str + 1] = ',\n' -elseif type(val) == 'string' then - tbl_str[#tbl_str + 1] = mist.utils.basicSerialize(val) - tbl_str[#tbl_str + 1] = ',\n' -elseif type(val) == 'nil' then -- won't ever happen, right? -tbl_str[#tbl_str + 1] = 'nil,\n' -elseif type(val) == 'table' then - if tableshow_tbls[val] then - tbl_str[#tbl_str + 1] = tostring(val) .. ' already defined: ' .. tableshow_tbls[val] .. ',\n' - else - tableshow_tbls[val] = loc .. '[' .. mist.utils.basicSerialize(ind) .. ']' - tbl_str[#tbl_str + 1] = tostring(val) .. ' ' - tbl_str[#tbl_str + 1] = mist.utils.tableShow(val, loc .. '[' .. mist.utils.basicSerialize(ind).. ']', indent .. ' ', tableshow_tbls) - tbl_str[#tbl_str + 1] = ',\n' - end -elseif type(val) == 'function' then - if debug and debug.getinfo then - local fcnname = tostring(val) - local info = debug.getinfo(val, "S") - if info.what == "C" then - tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', C function') .. ',\n' - else - if (string.sub(info.source, 1, 2) == [[./]]) then - tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')' .. info.source) ..',\n' + tbl_str[#tbl_str + 1] = indent .. '{\n' + + for ind,val in pairs(tbl) do -- serialize its fields + if type(ind) == "number" then + tbl_str[#tbl_str + 1] = indent + tbl_str[#tbl_str + 1] = loc .. '[' + tbl_str[#tbl_str + 1] = tostring(ind) + tbl_str[#tbl_str + 1] = '] = ' else - tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')') ..',\n' + tbl_str[#tbl_str + 1] = indent + tbl_str[#tbl_str + 1] = loc .. '[' + tbl_str[#tbl_str + 1] = mist.utils.basicSerialize(ind) + tbl_str[#tbl_str + 1] = '] = ' + end + + if ((type(val) == 'number') or (type(val) == 'boolean')) then + tbl_str[#tbl_str + 1] = tostring(val) + tbl_str[#tbl_str + 1] = ',\n' + elseif type(val) == 'string' then + tbl_str[#tbl_str + 1] = mist.utils.basicSerialize(val) + tbl_str[#tbl_str + 1] = ',\n' + elseif type(val) == 'nil' then -- won't ever happen, right? + tbl_str[#tbl_str + 1] = 'nil,\n' + elseif type(val) == 'table' then + if tableshow_tbls[val] then + tbl_str[#tbl_str + 1] = tostring(val) .. ' already defined: ' .. tableshow_tbls[val] .. ',\n' + else + tableshow_tbls[val] = loc .. '[' .. mist.utils.basicSerialize(ind) .. ']' + tbl_str[#tbl_str + 1] = tostring(val) .. ' ' + tbl_str[#tbl_str + 1] = mist.utils.tableShow(val, loc .. '[' .. mist.utils.basicSerialize(ind).. ']', indent .. ' ', tableshow_tbls) + tbl_str[#tbl_str + 1] = ',\n' + end + elseif type(val) == 'function' then + if debug and debug.getinfo then + local fcnname = tostring(val) + local info = debug.getinfo(val, "S") + if info.what == "C" then + tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', C function') .. ',\n' + else + if (string.sub(info.source, 1, 2) == [[./]]) then + tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')' .. info.source) ..',\n' + else + tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')') ..',\n' + end + end + + else + tbl_str[#tbl_str + 1] = 'a function,\n' + end + else + tbl_str[#tbl_str + 1] = 'unable to serialize value type ' .. mist.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind) end end - - else - tbl_str[#tbl_str + 1] = 'a function,\n' + + tbl_str[#tbl_str + 1] = indent .. '}' + return table.concat(tbl_str) end -else - tbl_str[#tbl_str + 1] = 'unable to serialize value type ' .. mist.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind) -end -end - -tbl_str[#tbl_str + 1] = indent .. '}' -return table.concat(tbl_str) -end end mist.debug = {} @@ -1386,7 +1391,7 @@ mist.vec.mag = function(vec) return (vec.x^2 + vec.y^2 + vec.z^2)^0.5 end -mist.vec.getUnitVec = function(vec) +mist.vec.getUnitVec = function(vec) local mag = mist.vec.mag(vec) return { x = vec.x/mag, y = vec.y/mag, z = vec.z/mag } end @@ -1397,12 +1402,12 @@ end --------------------------------------------------------------------------------------------------------------------------- -- acc- the accuracy of each easting/northing. 0, 1, 2, 3, 4, or 5. -mist.tostringMGRS = function(MGRS, acc) +mist.tostringMGRS = function(MGRS, acc) if acc == 0 then return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph else - return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph .. ' ' .. string.format('%0' .. acc .. 'd', mist.utils.round(MGRS.Easting/(10^(5-acc)), 0)) - .. ' ' .. string.format('%0' .. acc .. 'd', mist.utils.round(MGRS.Northing/(10^(5-acc)), 0)) + return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph .. ' ' .. string.format('%0' .. acc .. 'd', mist.utils.round(MGRS.Easting/(10^(5-acc)), 0)) + .. ' ' .. string.format('%0' .. acc .. 'd', mist.utils.round(MGRS.Northing/(10^(5-acc)), 0)) end end @@ -1414,121 +1419,121 @@ So: 42.32 - acc of 2. ]] mist.tostringLL = function(lat, lon, acc, DMS) - + local latHemi, lonHemi if lat > 0 then latHemi = 'N' else latHemi = 'S' end - + if lon > 0 then lonHemi = 'E' else lonHemi = 'W' end - + lat = math.abs(lat) lon = math.abs(lon) - + local latDeg = math.floor(lat) local latMin = (lat - latDeg)*60 - + local lonDeg = math.floor(lon) local lonMin = (lon - lonDeg)*60 - + if DMS then -- degrees, minutes, and seconds. - local oldLatMin = latMin - latMin = math.floor(latMin) - local latSec = mist.utils.round((oldLatMin - latMin)*60, acc) - - local oldLonMin = lonMin - lonMin = math.floor(lonMin) - local lonSec = mist.utils.round((oldLonMin - lonMin)*60, acc) - - if latSec == 60 then - latSec = 0 - latMin = latMin + 1 - end - - if lonSec == 60 then - lonSec = 0 - lonMin = lonMin + 1 - end - - local secFrmtStr -- create the formatting string for the seconds place - if acc <= 0 then -- no decimal place. - secFrmtStr = '%02d' - else - local width = 3 + acc -- 01.310 - that's a width of 6, for example. - secFrmtStr = '%0' .. width .. '.' .. acc .. 'f' - end - - return string.format('%02d', latDeg) .. ' ' .. string.format('%02d', latMin) .. '\' ' .. string.format(secFrmtStr, latSec) .. '"' .. latHemi .. ' ' - .. string.format('%02d', lonDeg) .. ' ' .. string.format('%02d', lonMin) .. '\' ' .. string.format(secFrmtStr, lonSec) .. '"' .. lonHemi + local oldLatMin = latMin + latMin = math.floor(latMin) + local latSec = mist.utils.round((oldLatMin - latMin)*60, acc) + + local oldLonMin = lonMin + lonMin = math.floor(lonMin) + local lonSec = mist.utils.round((oldLonMin - lonMin)*60, acc) + + if latSec == 60 then + latSec = 0 + latMin = latMin + 1 + end + + if lonSec == 60 then + lonSec = 0 + lonMin = lonMin + 1 + end + + local secFrmtStr -- create the formatting string for the seconds place + if acc <= 0 then -- no decimal place. + secFrmtStr = '%02d' + else + local width = 3 + acc -- 01.310 - that's a width of 6, for example. + secFrmtStr = '%0' .. width .. '.' .. acc .. 'f' + end + + return string.format('%02d', latDeg) .. ' ' .. string.format('%02d', latMin) .. '\' ' .. string.format(secFrmtStr, latSec) .. '"' .. latHemi .. ' ' + .. string.format('%02d', lonDeg) .. ' ' .. string.format('%02d', lonMin) .. '\' ' .. string.format(secFrmtStr, lonSec) .. '"' .. lonHemi else -- degrees, decimal minutes. - latMin = mist.utils.round(latMin, acc) - lonMin = mist.utils.round(lonMin, acc) - - if latMin == 60 then - latMin = 0 - latDeg = latDeg + 1 - end - - if lonMin == 60 then - lonMin = 0 - lonDeg = lonDeg + 1 - end - - local minFrmtStr -- create the formatting string for the minutes place - if acc <= 0 then -- no decimal place. - minFrmtStr = '%02d' - else - local width = 3 + acc -- 01.310 - that's a width of 6, for example. - minFrmtStr = '%0' .. width .. '.' .. acc .. 'f' - end - - return string.format('%02d', latDeg) .. ' ' .. string.format(minFrmtStr, latMin) .. '\'' .. latHemi .. ' ' - .. string.format('%02d', lonDeg) .. ' ' .. string.format(minFrmtStr, lonMin) .. '\'' .. lonHemi - + latMin = mist.utils.round(latMin, acc) + lonMin = mist.utils.round(lonMin, acc) + + if latMin == 60 then + latMin = 0 + latDeg = latDeg + 1 + end + + if lonMin == 60 then + lonMin = 0 + lonDeg = lonDeg + 1 + end + + local minFrmtStr -- create the formatting string for the minutes place + if acc <= 0 then -- no decimal place. + minFrmtStr = '%02d' + else + local width = 3 + acc -- 01.310 - that's a width of 6, for example. + minFrmtStr = '%0' .. width .. '.' .. acc .. 'f' + end + + return string.format('%02d', latDeg) .. ' ' .. string.format(minFrmtStr, latMin) .. '\'' .. latHemi .. ' ' + .. string.format('%02d', lonDeg) .. ' ' .. string.format(minFrmtStr, lonMin) .. '\'' .. lonHemi + end end --[[ required: az - radian required: dist - meters - optional: alt - meters (set to false or nil if you don't want to use it). - optional: metric - set true to get dist and alt in km and m. - precision will always be nearest degree and NM or km.]] + optional: alt - meters (set to false or nil if you don't want to use it). + optional: metric - set true to get dist and alt in km and m. + precision will always be nearest degree and NM or km.]] mist.tostringBR = function(az, dist, alt, metric) az = mist.utils.round(mist.utils.toDegree(az), 0) - + if metric then dist = mist.utils.round(dist/1000, 0) else dist = mist.utils.round(mist.utils.metersToNM(dist), 0) end - + local s = string.format('%03d', az) .. ' for ' .. dist - + if alt then if metric then s = s .. ' at ' .. mist.utils.round(alt, 0) else s = s .. ' at ' .. mist.utils.round(mist.utils.metersToFeet(alt), 0) end - end + end return s end mist.getNorthCorrection = function(point) --gets the correction needed for true north -if not point.z then --Vec2; convert to Vec3 -point.z = point.y -point.y = 0 -end -local lat, lon = coord.LOtoLL(point) -local north_posit = coord.LLtoLO(lat + 1, lon) -return math.atan2(north_posit.z - point.z, north_posit.x - point.x) + if not point.z then --Vec2; convert to Vec3 + point.z = point.y + point.y = 0 + end + local lat, lon = coord.LOtoLL(point) + local north_posit = coord.LLtoLO(lat + 1, lon) + return math.atan2(north_posit.z - point.z, north_posit.x - point.x) end mist.getUnitSkill = function(unitName) @@ -1545,42 +1550,42 @@ end function mist.getGroupPoints(groupIdent) -- if groupname exists in env.mission, then returns table of the group's points in numerical order, such as: { [1] = {x = 299435.224, y = -1146632.6773}, [2] = { x = 663324.6563, y = 322424.1112}} --- refactor to search by groupId and allow groupId and groupName as inputs -local gpId = groupIdent -if type(groupIdent) == 'string' and not tonumber(groupIdent) then - gpId = mist.DBs.MEgroupsByName[groupIdent].groupId -end - -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 == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" then -- only these types have points - 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 - if group_data and group_data.groupId == gpId then -- this is the group we are looking for - if group_data.route and group_data.route.points and #group_data.route.points > 0 then - local points = {} - for point_num, point in pairs(group_data.route.points) do - if not point.point then - points[point_num] = { x = point.x, y = point.y } - else - points[point_num] = point.point --it's possible that the ME could move to the point = Vec2 notation. - end - end - return points - end - return - end --if group_data and group_data.name and group_data.name == 'groupname' - 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 + -- refactor to search by groupId and allow groupId and groupName as inputs + local gpId = groupIdent + if type(groupIdent) == 'string' and not tonumber(groupIdent) then + gpId = mist.DBs.MEgroupsByName[groupIdent].groupId + end + + 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 == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" then -- only these types have points + 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 + if group_data and group_data.groupId == gpId then -- this is the group we are looking for + if group_data.route and group_data.route.points and #group_data.route.points > 0 then + local points = {} + for point_num, point in pairs(group_data.route.points) do + if not point.point then + points[point_num] = { x = point.x, y = point.y } + else + points[point_num] = point.point --it's possible that the ME could move to the point = Vec2 notation. + end + end + return points + end + return + end --if group_data and group_data.name and group_data.name == 'groupname' + 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 @@ -1588,92 +1593,92 @@ end --[[ table attitude = getAttitude(string unitname) -- will work on any unit, even if not an aircraft. attitude = { - Heading = number, -- in radians, range of 0 to 2*pi, relative to true north - Pitch = number, -- in radians, range of -pi/2 to pi/2 - Roll = number, -- in radians, range of 0 to 2*pi, right roll is positive direction - - --Yaw, AoA, ClimbAngle - relative to earth reference- DOES NOT TAKE INTO ACCOUNT WIND. - Yaw = number, -- in radians, range of -pi to pi, right yaw is positive direction - AoA = number, -- in radians, range of -pi to pi, rotation of aircraft to the right in comparison to flight direction being positive - ClimbAngle = number, -- in radians, range of -pi/2 to pi/2 - - --Maybe later? - AxialVel = table, velocity of the aircraft transformed into directions of aircraft axes - Speed = number -- absolute velocity in meters/sec + Heading = number, -- in radians, range of 0 to 2*pi, relative to true north + Pitch = number, -- in radians, range of -pi/2 to pi/2 + Roll = number, -- in radians, range of 0 to 2*pi, right roll is positive direction + + --Yaw, AoA, ClimbAngle - relative to earth reference- DOES NOT TAKE INTO ACCOUNT WIND. + Yaw = number, -- in radians, range of -pi to pi, right yaw is positive direction + AoA = number, -- in radians, range of -pi to pi, rotation of aircraft to the right in comparison to flight direction being positive + ClimbAngle = number, -- in radians, range of -pi/2 to pi/2 + + --Maybe later? + AxialVel = table, velocity of the aircraft transformed into directions of aircraft axes + Speed = number -- absolute velocity in meters/sec - } + } ]] function mist.getAttitude(unit) local unitpos = unit:getPosition() if unitpos then - + local Heading = math.atan2(unitpos.x.z, unitpos.x.x) - + Heading = Heading + mist.getNorthCorrection(unitpos.p) - + if Heading < 0 then Heading = Heading + 2*math.pi -- put heading in range of 0 to 2*pi end ---- heading complete.---- - + local Pitch = math.asin(unitpos.x.y) ---- pitch complete.---- - + -- now get roll: --maybe not the best way to do it, but it works. - + --first, make a vector that is perpendicular to y and unitpos.x with cross product local cp = mist.vec.cp(unitpos.x, {x = 0, y = 1, z = 0}) - + --now, get dot product of of this cross product with unitpos.z local dp = mist.vec.dp(cp, unitpos.z) - + --now get the magnitude of the roll (magnitude of the angle between two vectors is acos(vec1.vec2/|vec1||vec2|) local Roll = math.acos(dp/(mist.vec.mag(cp)*mist.vec.mag(unitpos.z))) --now, have to get sign of roll. -- by convention, making right roll positive -- to get sign of roll, use the y component of unitpos.z. For right roll, y component is negative. - + if unitpos.z.y > 0 then -- left roll, flip the sign of the roll - Roll = -Roll + Roll = -Roll end ---- roll complete. ---- - + --now, work on yaw, AoA, climb, and abs velocity local Yaw local AoA local ClimbAngle - + -- get unit velocity local unitvel = unit:getVelocity() if mist.vec.mag(unitvel) ~= 0 then --must have non-zero velocity! - local AxialVel = {} --unit velocity transformed into aircraft axes directions - - --transform velocity components in direction of aircraft axes. - AxialVel.x = mist.vec.dp(unitpos.x, unitvel) - AxialVel.y = mist.vec.dp(unitpos.y, unitvel) - AxialVel.z = mist.vec.dp(unitpos.z, unitvel) - - --Yaw is the angle between unitpos.x and the x and z velocities - --define right yaw as positive - Yaw = math.acos(mist.vec.dp({x = 1, y = 0, z = 0}, {x = AxialVel.x, y = 0, z = AxialVel.z})/mist.vec.mag({x = AxialVel.x, y = 0, z = AxialVel.z})) - - --now set correct direction: - if AxialVel.z > 0 then - Yaw = -Yaw - end - - -- AoA is angle between unitpos.x and the x and y velocities - AoA = math.acos(mist.vec.dp({x = 1, y = 0, z = 0}, {x = AxialVel.x, y = AxialVel.y, z = 0})/mist.vec.mag({x = AxialVel.x, y = AxialVel.y, z = 0})) - - --now set correct direction: - if AxialVel.y > 0 then - AoA = -AoA - end - - ClimbAngle = math.asin(unitvel.y/mist.vec.mag(unitvel)) + local AxialVel = {} --unit velocity transformed into aircraft axes directions + + --transform velocity components in direction of aircraft axes. + AxialVel.x = mist.vec.dp(unitpos.x, unitvel) + AxialVel.y = mist.vec.dp(unitpos.y, unitvel) + AxialVel.z = mist.vec.dp(unitpos.z, unitvel) + + --Yaw is the angle between unitpos.x and the x and z velocities + --define right yaw as positive + Yaw = math.acos(mist.vec.dp({x = 1, y = 0, z = 0}, {x = AxialVel.x, y = 0, z = AxialVel.z})/mist.vec.mag({x = AxialVel.x, y = 0, z = AxialVel.z})) + + --now set correct direction: + if AxialVel.z > 0 then + Yaw = -Yaw + end + + -- AoA is angle between unitpos.x and the x and y velocities + AoA = math.acos(mist.vec.dp({x = 1, y = 0, z = 0}, {x = AxialVel.x, y = AxialVel.y, z = 0})/mist.vec.mag({x = AxialVel.x, y = AxialVel.y, z = 0})) + + --now set correct direction: + if AxialVel.y > 0 then + AoA = -AoA + end + + ClimbAngle = math.asin(unitvel.y/mist.vec.mag(unitvel)) end return { Heading = Heading, Pitch = Pitch, Roll = Roll, Yaw = Yaw, AoA = AoA, ClimbAngle = ClimbAngle} else @@ -1707,22 +1712,22 @@ function mist.getRoll(unit) if unitpos then -- now get roll: --maybe not the best way to do it, but it works. - + --first, make a vector that is perpendicular to y and unitpos.x with cross product local cp = mist.vec.cp(unitpos.x, {x = 0, y = 1, z = 0}) - + --now, get dot product of of this cross product with unitpos.z local dp = mist.vec.dp(cp, unitpos.z) - + --now get the magnitude of the roll (magnitude of the angle between two vectors is acos(vec1.vec2/|vec1||vec2|) local Roll = math.acos(dp/(mist.vec.mag(cp)*mist.vec.mag(unitpos.z))) --now, have to get sign of roll. -- by convention, making right roll positive -- to get sign of roll, use the y component of unitpos.z. For right roll, y component is negative. - + if unitpos.z.y > 0 then -- left roll, flip the sign of the roll - Roll = -Roll + Roll = -Roll end return Roll end @@ -1734,22 +1739,22 @@ function mist.getYaw(unit) -- get unit velocity local unitvel = unit:getVelocity() if mist.vec.mag(unitvel) ~= 0 then --must have non-zero velocity! - local AxialVel = {} --unit velocity transformed into aircraft axes directions - - --transform velocity components in direction of aircraft axes. - AxialVel.x = mist.vec.dp(unitpos.x, unitvel) - AxialVel.y = mist.vec.dp(unitpos.y, unitvel) - AxialVel.z = mist.vec.dp(unitpos.z, unitvel) - - --Yaw is the angle between unitpos.x and the x and z velocities - --define right yaw as positive - local Yaw = math.acos(mist.vec.dp({x = 1, y = 0, z = 0}, {x = AxialVel.x, y = 0, z = AxialVel.z})/mist.vec.mag({x = AxialVel.x, y = 0, z = AxialVel.z})) - - --now set correct direction: - if AxialVel.z > 0 then - Yaw = -Yaw - end - return Yaw + local AxialVel = {} --unit velocity transformed into aircraft axes directions + + --transform velocity components in direction of aircraft axes. + AxialVel.x = mist.vec.dp(unitpos.x, unitvel) + AxialVel.y = mist.vec.dp(unitpos.y, unitvel) + AxialVel.z = mist.vec.dp(unitpos.z, unitvel) + + --Yaw is the angle between unitpos.x and the x and z velocities + --define right yaw as positive + local Yaw = math.acos(mist.vec.dp({x = 1, y = 0, z = 0}, {x = AxialVel.x, y = 0, z = AxialVel.z})/mist.vec.mag({x = AxialVel.x, y = 0, z = AxialVel.z})) + + --now set correct direction: + if AxialVel.z > 0 then + Yaw = -Yaw + end + return Yaw end end end @@ -1759,21 +1764,21 @@ function mist.getAoA(unit) if unitpos then local unitvel = unit:getVelocity() if mist.vec.mag(unitvel) ~= 0 then --must have non-zero velocity! - local AxialVel = {} --unit velocity transformed into aircraft axes directions - - --transform velocity components in direction of aircraft axes. - AxialVel.x = mist.vec.dp(unitpos.x, unitvel) - AxialVel.y = mist.vec.dp(unitpos.y, unitvel) - AxialVel.z = mist.vec.dp(unitpos.z, unitvel) - - -- AoA is angle between unitpos.x and the x and y velocities - local AoA = math.acos(mist.vec.dp({x = 1, y = 0, z = 0}, {x = AxialVel.x, y = AxialVel.y, z = 0})/mist.vec.mag({x = AxialVel.x, y = AxialVel.y, z = 0})) - - --now set correct direction: - if AxialVel.y > 0 then - AoA = -AoA - end - return AoA + local AxialVel = {} --unit velocity transformed into aircraft axes directions + + --transform velocity components in direction of aircraft axes. + AxialVel.x = mist.vec.dp(unitpos.x, unitvel) + AxialVel.y = mist.vec.dp(unitpos.y, unitvel) + AxialVel.z = mist.vec.dp(unitpos.z, unitvel) + + -- AoA is angle between unitpos.x and the x and y velocities + local AoA = math.acos(mist.vec.dp({x = 1, y = 0, z = 0}, {x = AxialVel.x, y = AxialVel.y, z = 0})/mist.vec.mag({x = AxialVel.x, y = AxialVel.y, z = 0})) + + --now set correct direction: + if AxialVel.y > 0 then + AoA = -AoA + end + return AoA end end end @@ -1783,7 +1788,7 @@ function mist.getClimbAngle(unit) if unitpos then local unitvel = unit:getVelocity() if mist.vec.mag(unitvel) ~= 0 then --must have non-zero velocity! - return math.asin(unitvel.y/mist.vec.mag(unitvel)) + return math.asin(unitvel.y/mist.vec.mag(unitvel)) end end end @@ -1793,8 +1798,8 @@ mist.DBs = {} mist.DBs.missionData = {} ----------------------------------------- -if env.mission then - +if env.mission then + mist.DBs.missionData['startTime'] = env.mission.start_time mist.DBs.missionData['theatre'] = env.mission.theatre mist.DBs.missionData['version'] = env.mission.version @@ -1809,7 +1814,7 @@ if env.mission then mist.DBs.missionData.bullseye.red['y'] = env.mission.coalition.red.bullseye.y mist.DBs.missionData.bullseye.blue['x'] = env.mission.coalition.blue.bullseye.x mist.DBs.missionData.bullseye.blue['y'] = env.mission.coalition.blue.bullseye.y - + end ---------------------------------------- @@ -1826,151 +1831,151 @@ if env.mission.triggers and env.mission.triggers.zones then zone['point']['x'] = zone_data.x zone['point']['y'] = 0 zone['point']['z'] = zone_data.y - + mist.DBs.zonesByName[zone_data.name] = zone mist.DBs.zonesByNum[#mist.DBs.zonesByNum + 1] = mist.utils.deepCopy(zone) --[[deepcopy so that the zone in zones_by_name and the zone in - zones_by_num se are different objects.. don't want them linked.]] + zones_by_num se are different objects.. don't want them linked.]] end end end mist.DBs.navPoints = {} mist.DBs.units = {} ---Build mist.db.units and mist.DBs.navPoints + --Build mist.db.units and mist.DBs.navPoints 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 mist.DBs.units[coa_name] = {} - + ---------------------------------------------- -- build nav points DB mist.DBs.navPoints[coa_name] = {} if coa_data.nav_points then --navpoints - --mist.debug.writeData (mist.utils.serialize,{'NavPoints',coa_data.nav_points}, 'NavPoints.txt') - for nav_ind, nav_data in pairs(coa_data.nav_points) do + --mist.debug.writeData (mist.utils.serialize,{'NavPoints',coa_data.nav_points}, 'NavPoints.txt') + for nav_ind, nav_data in pairs(coa_data.nav_points) do + + if type(nav_data) == 'table' then + mist.DBs.navPoints[coa_name][nav_ind] = mist.utils.deepCopy(nav_data) - if type(nav_data) == 'table' then - mist.DBs.navPoints[coa_name][nav_ind] = mist.utils.deepCopy(nav_data) - - mist.DBs.navPoints[coa_name][nav_ind]['name'] = nav_data.callsignStr -- name is a little bit more self-explanatory. - mist.DBs.navPoints[coa_name][nav_ind]['point'] = {} -- point is used by SSE, support it. - mist.DBs.navPoints[coa_name][nav_ind]['point']['x'] = nav_data.x - mist.DBs.navPoints[coa_name][nav_ind]['point']['y'] = 0 - mist.DBs.navPoints[coa_name][nav_ind]['point']['z'] = nav_data.y + mist.DBs.navPoints[coa_name][nav_ind]['name'] = nav_data.callsignStr -- name is a little bit more self-explanatory. + mist.DBs.navPoints[coa_name][nav_ind]['point'] = {} -- point is used by SSE, support it. + mist.DBs.navPoints[coa_name][nav_ind]['point']['x'] = nav_data.x + mist.DBs.navPoints[coa_name][nav_ind]['point']['y'] = 0 + mist.DBs.navPoints[coa_name][nav_ind]['point']['z'] = nav_data.y + end end end - end - ------------------------------------------------- + ------------------------------------------------- if coa_data.country then --there is a country table - for cntry_id, cntry_data in pairs(coa_data.country) do + for cntry_id, cntry_data in pairs(coa_data.country) do + + local countryName = string.lower(cntry_data.name) + mist.DBs.units[coa_name][countryName] = {} + mist.DBs.units[coa_name][countryName]["countryId"] = cntry_data.id - local countryName = string.lower(cntry_data.name) - mist.DBs.units[coa_name][countryName] = {} - mist.DBs.units[coa_name][countryName]["countryId"] = cntry_data.id + if type(cntry_data) == 'table' then --just making sure + + for obj_type_name, obj_type_data in pairs(cntry_data) do + + 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 --should be an unncessary check + + local category = obj_type_name + + 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! + + mist.DBs.units[coa_name][countryName][category] = {} + + for group_num, group_data in pairs(obj_type_data.group) do + + if group_data and group_data.units and type(group_data.units) == 'table' then --making sure again- this is a valid group + + mist.DBs.units[coa_name][countryName][category][group_num] = {} + local groupName = group_data.name + if env.mission.version > 7 then + groupName = env.getValueDictByKey(groupName) + end + mist.DBs.units[coa_name][countryName][category][group_num]["groupName"] = groupName + mist.DBs.units[coa_name][countryName][category][group_num]["groupId"] = group_data.groupId + mist.DBs.units[coa_name][countryName][category][group_num]["category"] = category + mist.DBs.units[coa_name][countryName][category][group_num]["coalition"] = coa_name + mist.DBs.units[coa_name][countryName][category][group_num]["country"] = countryName + mist.DBs.units[coa_name][countryName][category][group_num]["countryId"] = cntry_data.id + mist.DBs.units[coa_name][countryName][category][group_num]["startTime"] = group_data.start_time + mist.DBs.units[coa_name][countryName][category][group_num]["task"] = group_data.task + mist.DBs.units[coa_name][countryName][category][group_num]["hidden"] = group_data.hidden + + mist.DBs.units[coa_name][countryName][category][group_num]["units"] = {} + + mist.DBs.units[coa_name][countryName][category][group_num]["radioSet"] = group_data.radioSet + mist.DBs.units[coa_name][countryName][category][group_num]["uncontrolled"] = group_data.uncontrolled + mist.DBs.units[coa_name][countryName][category][group_num]["frequency"] = group_data.frequency + mist.DBs.units[coa_name][countryName][category][group_num]["modulation"] = group_data.modulation - if type(cntry_data) == 'table' then --just making sure + for unit_num, unit_data in pairs(group_data.units) do + local units_tbl = mist.DBs.units[coa_name][countryName][category][group_num]["units"] --pointer to the units table for this group + + units_tbl[unit_num] = {} + if env.mission.version > 7 then + units_tbl[unit_num]["unitName"] = env.getValueDictByKey(unit_data.name) + else + units_tbl[unit_num]["unitName"] = unit_data.name + end + units_tbl[unit_num]["type"] = unit_data.type + units_tbl[unit_num]["skill"] = unit_data.skill --will be nil for statics + units_tbl[unit_num]["unitId"] = unit_data.unitId + units_tbl[unit_num]["category"] = category + units_tbl[unit_num]["coalition"] = coa_name + units_tbl[unit_num]["country"] = countryName + units_tbl[unit_num]["countryId"] = cntry_data.id + units_tbl[unit_num]["heading"] = unit_data.heading + units_tbl[unit_num]["playerCanDrive"] = unit_data.playerCanDrive + units_tbl[unit_num]["alt"] = unit_data.alt + units_tbl[unit_num]["alt_type"] = unit_data.alt_type + units_tbl[unit_num]["speed"] = unit_data.speed + units_tbl[unit_num]["livery_id"] = unit_data.livery_id + if unit_data.point then --ME currently does not work like this, but it might one day + units_tbl[unit_num]["point"] = unit_data.point + else + units_tbl[unit_num]["point"] = {} + units_tbl[unit_num]["point"]["x"] = unit_data.x + units_tbl[unit_num]["point"]["y"] = unit_data.y + end + units_tbl[unit_num]['x'] = unit_data.x + units_tbl[unit_num]['y'] = unit_data.y + + units_tbl[unit_num]["callsign"] = unit_data.callsign + units_tbl[unit_num]["onboard_num"] = unit_data.onboard_num + units_tbl[unit_num]["hardpoint_racks"] = unit_data.hardpoint_racks + units_tbl[unit_num]["psi"] = unit_data.psi - for obj_type_name, obj_type_data in pairs(cntry_data) do - - 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 --should be an unncessary check - - local category = obj_type_name - - 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! - - mist.DBs.units[coa_name][countryName][category] = {} - - for group_num, group_data in pairs(obj_type_data.group) do - - if group_data and group_data.units and type(group_data.units) == 'table' then --making sure again- this is a valid group - - mist.DBs.units[coa_name][countryName][category][group_num] = {} - local groupName = group_data.name - if env.mission.version > 7 then - groupName = env.getValueDictByKey(groupName) - end - mist.DBs.units[coa_name][countryName][category][group_num]["groupName"] = groupName - mist.DBs.units[coa_name][countryName][category][group_num]["groupId"] = group_data.groupId - mist.DBs.units[coa_name][countryName][category][group_num]["category"] = category - mist.DBs.units[coa_name][countryName][category][group_num]["coalition"] = coa_name - mist.DBs.units[coa_name][countryName][category][group_num]["country"] = countryName - mist.DBs.units[coa_name][countryName][category][group_num]["countryId"] = cntry_data.id - mist.DBs.units[coa_name][countryName][category][group_num]["startTime"] = group_data.start_time - mist.DBs.units[coa_name][countryName][category][group_num]["task"] = group_data.task - mist.DBs.units[coa_name][countryName][category][group_num]["hidden"] = group_data.hidden - - mist.DBs.units[coa_name][countryName][category][group_num]["units"] = {} - - mist.DBs.units[coa_name][countryName][category][group_num]["radioSet"] = group_data.radioSet - mist.DBs.units[coa_name][countryName][category][group_num]["uncontrolled"] = group_data.uncontrolled - mist.DBs.units[coa_name][countryName][category][group_num]["frequency"] = group_data.frequency - mist.DBs.units[coa_name][countryName][category][group_num]["modulation"] = group_data.modulation - - for unit_num, unit_data in pairs(group_data.units) do - local units_tbl = mist.DBs.units[coa_name][countryName][category][group_num]["units"] --pointer to the units table for this group - - units_tbl[unit_num] = {} - if env.mission.version > 7 then - units_tbl[unit_num]["unitName"] = env.getValueDictByKey(unit_data.name) - else - units_tbl[unit_num]["unitName"] = unit_data.name - end - units_tbl[unit_num]["type"] = unit_data.type - units_tbl[unit_num]["skill"] = unit_data.skill --will be nil for statics - units_tbl[unit_num]["unitId"] = unit_data.unitId - units_tbl[unit_num]["category"] = category - units_tbl[unit_num]["coalition"] = coa_name - units_tbl[unit_num]["country"] = countryName - units_tbl[unit_num]["countryId"] = cntry_data.id - units_tbl[unit_num]["heading"] = unit_data.heading - units_tbl[unit_num]["playerCanDrive"] = unit_data.playerCanDrive - units_tbl[unit_num]["alt"] = unit_data.alt - units_tbl[unit_num]["alt_type"] = unit_data.alt_type - units_tbl[unit_num]["speed"] = unit_data.speed - units_tbl[unit_num]["livery_id"] = unit_data.livery_id - if unit_data.point then --ME currently does not work like this, but it might one day - units_tbl[unit_num]["point"] = unit_data.point - else - units_tbl[unit_num]["point"] = {} - units_tbl[unit_num]["point"]["x"] = unit_data.x - units_tbl[unit_num]["point"]["y"] = unit_data.y - end - units_tbl[unit_num]['x'] = unit_data.x - units_tbl[unit_num]['y'] = unit_data.y - - units_tbl[unit_num]["callsign"] = unit_data.callsign - units_tbl[unit_num]["onboard_num"] = unit_data.onboard_num - units_tbl[unit_num]["hardpoint_racks"] = unit_data.hardpoint_racks - units_tbl[unit_num]["psi"] = unit_data.psi - - - units_tbl[unit_num]["groupName"] = groupName - units_tbl[unit_num]["groupId"] = group_data.groupId - - if unit_data.AddPropAircraft then - units_tbl[unit_num]["AddPropAircraft"] = unit_data.AddPropAircraft - end - - if category == 'static' then - units_tbl[unit_num]["categoryStatic"] = unit_data.category - units_tbl[unit_num]["shape_name"] = unit_data.shape_name - if unit_data.mass then - units_tbl[unit_num]["mass"] = unit_data.mass - end - - if unit_data.canCargo then - units_tbl[unit_num]["canCargo"] = unit_data.canCargo - end - end - - end --for unit_num, unit_data in pairs(group_data.units) do - end --if group_data and group_data.units 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 --if type(cntry_data) == 'table' then - end --for cntry_id, cntry_data in pairs(coa_data.country) do + + units_tbl[unit_num]["groupName"] = groupName + units_tbl[unit_num]["groupId"] = group_data.groupId + + if unit_data.AddPropAircraft then + units_tbl[unit_num]["AddPropAircraft"] = unit_data.AddPropAircraft + end + + if category == 'static' then + units_tbl[unit_num]["categoryStatic"] = unit_data.category + units_tbl[unit_num]["shape_name"] = unit_data.shape_name + if unit_data.mass then + units_tbl[unit_num]["mass"] = unit_data.mass + end + + if unit_data.canCargo then + units_tbl[unit_num]["canCargo"] = unit_data.canCargo + end + end + + end --for unit_num, unit_data in pairs(group_data.units) do + end --if group_data and group_data.units 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 --if type(cntry_data) == 'table' then + 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 @@ -2000,16 +2005,16 @@ mist.DBs.aliveUnits = {} -- will be filled in by the "update_alive_units" corou mist.DBs.removedAliveUnits = {} -- will be filled in by the "update_alive_units" coroutine in mist.main. -- create mist.DBs.oldAliveUnits -- do --- local intermediate_alive_units = {} -- between 0 and 0.5 secs old --- local function make_old_alive_units() -- called every 0.5 secs, makes the old_alive_units DB which is just a copy of alive_units that is 0.5 to 1 sec old --- if intermediate_alive_units then --- mist.DBs.oldAliveUnits = mist.utils.deepCopy(intermediate_alive_units) --- end --- intermediate_alive_units = mist.utils.deepCopy(mist.DBs.aliveUnits) --- timer.scheduleFunction(make_old_alive_units, nil, timer.getTime() + 0.5) --- end - --- make_old_alive_units() + -- local intermediate_alive_units = {} -- between 0 and 0.5 secs old + -- local function make_old_alive_units() -- called every 0.5 secs, makes the old_alive_units DB which is just a copy of alive_units that is 0.5 to 1 sec old + -- if intermediate_alive_units then + -- mist.DBs.oldAliveUnits = mist.utils.deepCopy(intermediate_alive_units) + -- end + -- intermediate_alive_units = mist.utils.deepCopy(mist.DBs.aliveUnits) + -- timer.scheduleFunction(make_old_alive_units, nil, timer.getTime() + 0.5) + -- end + + -- make_old_alive_units() -- end @@ -2020,23 +2025,27 @@ for coa_name, coa_data in pairs(mist.DBs.units) do if type(category_data) == 'table' then for group_ind, group_data in pairs(category_data) do if type(group_data) == 'table' and group_data.units and type(group_data.units) == 'table' and #group_data.units > 0 then -- OCD paradigm programming - mist.DBs.groupsByName[group_data.groupName] = mist.utils.deepCopy(group_data) - mist.DBs.groupsById[group_data.groupId] = mist.utils.deepCopy(group_data) - for unit_ind, unit_data in pairs(group_data.units) do - mist.DBs.unitsByName[unit_data.unitName] = mist.utils.deepCopy(unit_data) - mist.DBs.unitsById[unit_data.unitId] = mist.utils.deepCopy(unit_data) - - mist.DBs.unitsByCat[unit_data.category] = mist.DBs.unitsByCat[unit_data.category] or {} -- future-proofing against new categories... - table.insert(mist.DBs.unitsByCat[unit_data.category], mist.utils.deepCopy(unit_data)) - --print('inserting ' .. unit_data.unitName) - table.insert(mist.DBs.unitsByNum, mist.utils.deepCopy(unit_data)) - - if unit_data.skill and (unit_data.skill == "Client" or unit_data.skill == "Player") then - mist.DBs.humansByName[unit_data.unitName] = mist.utils.deepCopy(unit_data) - mist.DBs.humansById[unit_data.unitId] = mist.utils.deepCopy(unit_data) + mist.DBs.groupsByName[group_data.groupName] = mist.utils.deepCopy(group_data) + mist.DBs.groupsById[group_data.groupId] = mist.utils.deepCopy(group_data) + for unit_ind, unit_data in pairs(group_data.units) do + mist.DBs.unitsByName[unit_data.unitName] = mist.utils.deepCopy(unit_data) + mist.DBs.unitsById[unit_data.unitId] = mist.utils.deepCopy(unit_data) + + mist.DBs.unitsByCat[unit_data.category] = mist.DBs.unitsByCat[unit_data.category] or {} -- future-proofing against new categories... + table.insert(mist.DBs.unitsByCat[unit_data.category], mist.utils.deepCopy(unit_data)) + --print('inserting ' .. unit_data.unitName) + table.insert(mist.DBs.unitsByNum, mist.utils.deepCopy(unit_data)) + + if unit_data.skill and (unit_data.skill == "Client" or unit_data.skill == "Player") then + mist.DBs.humansByName[unit_data.unitName] = mist.utils.deepCopy(unit_data) + mist.DBs.humansById[unit_data.unitId] = mist.utils.deepCopy(unit_data) + --if Unit.getByName(unit_data.unitName) then + -- mist.DBs.activeHumans[unit_data.unitName] = mist.utils.deepCopy(unit_data) + -- mist.DBs.activeHumans[unit_data.unitName].playerName = Unit.getByName(unit_data.unitName):getPlayerName() + --end + end end end - end end end end @@ -2071,7 +2080,7 @@ mist.DBs.deadObjects = {} do local mt = {} - + mt.__newindex = function(t, key, val) --------------------------------------------------------------- local original_key = key --only for duplicate runtime IDs. @@ -2082,7 +2091,7 @@ do key_ind = key_ind + 1 end --------------------------------------------------------------- - + if mist.DBs.aliveUnits and mist.DBs.aliveUnits[val.object.id_] then --print('object found in alive_units') val['objectData'] = mist.utils.deepCopy(mist.DBs.aliveUnits[val.object.id_]) @@ -2091,38 +2100,38 @@ do val['objectPos'] = pos.p end val['objectType'] = mist.DBs.aliveUnits[val.object.id_].category - + elseif mist.DBs.removedAliveUnits and mist.DBs.removedAliveUnits[val.object.id_] then -- it didn't exist in alive_units, check old_alive_units - --print('object found in old_alive_units') - val['objectData'] = mist.utils.deepCopy(mist.DBs.removedAliveUnits[val.object.id_]) - local pos = Object.getPosition(val.object) - if pos then - val['objectPos'] = pos.p - end - val['objectType'] = mist.DBs.removedAliveUnits[val.object.id_].category - + --print('object found in old_alive_units') + val['objectData'] = mist.utils.deepCopy(mist.DBs.removedAliveUnits[val.object.id_]) + local pos = Object.getPosition(val.object) + if pos then + val['objectPos'] = pos.p + end + val['objectType'] = mist.DBs.removedAliveUnits[val.object.id_].category + else --attempt to determine if static object... - --print('object not found in alive units or old alive units') - local pos = Object.getPosition(val.object) - if pos then - local static_found = false - for ind, static in pairs(mist.DBs.unitsByCat['static']) do - if ((pos.p.x - static.point.x)^2 + (pos.p.z - static.point.y)^2)^0.5 < 0.1 then --really, it should be zero... - --print('correlated dead static object to position') - val['objectData'] = static - val['objectPos'] = pos.p - val['objectType'] = 'static' - static_found = true - break + --print('object not found in alive units or old alive units') + local pos = Object.getPosition(val.object) + if pos then + local static_found = false + for ind, static in pairs(mist.DBs.unitsByCat['static']) do + if ((pos.p.x - static.point.x)^2 + (pos.p.z - static.point.y)^2)^0.5 < 0.1 then --really, it should be zero... + --print('correlated dead static object to position') + val['objectData'] = static + val['objectPos'] = pos.p + val['objectType'] = 'static' + static_found = true + break + end end + if not static_found then + val['objectPos'] = pos.p + val['objectType'] = 'building' + end + else + val['objectType'] = 'unknown' end - if not static_found then - val['objectPos'] = pos.p - val['objectType'] = 'building' - end - else - val['objectType'] = 'unknown' - end end rawset(t, key, val) end @@ -2131,15 +2140,15 @@ do end -- Event handler to start creating the dead_objects table -do +do local function addDeadObject(event) if event.id == world.event.S_EVENT_DEAD or event.id == world.event.S_EVENT_CRASH then if event.initiator and event.initiator.id_ and event.initiator.id_ > 0 then - + local id = event.initiator.id_ -- initial ID, could change if there is a duplicate id_ already dead. local val = {object = event.initiator} -- the new entry in mist.DBs.deadObjects. - + --------------------------------------------------------------- local original_id = id --only for duplicate runtime IDs. local id_ind = 1 @@ -2149,7 +2158,7 @@ do id_ind = id_ind + 1 end --------------------------------------------------------------- - + if mist.DBs.aliveUnits and mist.DBs.aliveUnits[val.object.id_] then --print('object found in alive_units') val['objectData'] = mist.utils.deepCopy(mist.DBs.aliveUnits[val.object.id_]) @@ -2158,38 +2167,41 @@ do val['objectPos'] = pos.p end val['objectType'] = mist.DBs.aliveUnits[val.object.id_].category - + --[[if mist.DBs.activeHumans[Unit.getName(val.object)] then + --trigger.action.outText('remove via death: ' .. Unit.getName(val.object),20) + mist.DBs.activeHumans[Unit.getName(val.object)] = nil + end]] elseif mist.DBs.removedAliveUnits and mist.DBs.removedAliveUnits[val.object.id_] then -- it didn't exist in alive_units, check old_alive_units - --print('object found in old_alive_units') - val['objectData'] = mist.utils.deepCopy(mist.DBs.removedAliveUnits[val.object.id_]) - local pos = Object.getPosition(val.object) - if pos then - val['objectPos'] = pos.p - end - val['objectType'] = mist.DBs.removedAliveUnits[val.object.id_].category - + --print('object found in old_alive_units') + val['objectData'] = mist.utils.deepCopy(mist.DBs.removedAliveUnits[val.object.id_]) + local pos = Object.getPosition(val.object) + if pos then + val['objectPos'] = pos.p + end + val['objectType'] = mist.DBs.removedAliveUnits[val.object.id_].category + else --attempt to determine if static object... - --print('object not found in alive units or old alive units') - local pos = Object.getPosition(val.object) - if pos then - local static_found = false - for ind, static in pairs(mist.DBs.unitsByCat['static']) do - if ((pos.p.x - static.point.x)^2 + (pos.p.z - static.point.y)^2)^0.5 < 0.1 then --really, it should be zero... - --print('correlated dead static object to position') - val['objectData'] = static - val['objectPos'] = pos.p - val['objectType'] = 'static' - static_found = true - break + --print('object not found in alive units or old alive units') + local pos = Object.getPosition(val.object) + if pos then + local static_found = false + for ind, static in pairs(mist.DBs.unitsByCat['static']) do + if ((pos.p.x - static.point.x)^2 + (pos.p.z - static.point.y)^2)^0.5 < 0.1 then --really, it should be zero... + --print('correlated dead static object to position') + val['objectData'] = static + val['objectPos'] = pos.p + val['objectType'] = 'static' + static_found = true + break + end end + if not static_found then + val['objectPos'] = pos.p + val['objectType'] = 'building' + end + else + val['objectType'] = 'unknown' end - if not static_found then - val['objectPos'] = pos.p - val['objectType'] = 'building' - end - else - val['objectType'] = 'unknown' - end end mist.DBs.deadObjects[id] = val @@ -2197,29 +2209,29 @@ do end end - + mist.addEventHandler(addDeadObject) - - - --[[local function addClientsToActive(event) - if event.id == world.event.S_EVENT_PLAYER_ENTER_UNIT then - if not mist.DBs.activeHumans[Unit.getName(event.initiator)] then - local newU = mist.utils.deepCopy(mist.DBs.unitsByName[Unit.getName(event.initiator)]) - if Unit.getPlayerName(event.initiator) then - newU.playerName = Unit.getPlayerName(event.initiator) - end - mist.DBs.activeHumans[Unit.getName(event.initiator)] = newU - end - elseif event.id == world.event.S_EVENT_PLAYER_LEAVE_UNIT or event.id == world.event.S_EVENT_DEATH then - if mist.DBs.activeHumans[Unit.getName(event.initiator)] then - mist.DBs.activeHumans[Unit.getName(event.initiator)] = nil - end - elseif event.id == world.event.S_EVENT_BIRTH then -- do client check - - end - end - - mist.addEventHandler(addClientsToActive)]] + + --[[ + local function addClientsToActive(event) + if event.id == world.event.S_EVENT_PLAYER_ENTER_UNIT or event.id == world.event.S_EVENT_BIRTH then + env.info(mist.utils.tableShow(event)) + if Unit.getPlayerName(event.initiator) then + env.info(Unit.getPlayerName(event.initiator)) + local newU = mist.utils.deepCopy(mist.DBs.unitsByName[Unit.getName(event.initiator)]) + newU.playerName = Unit.getPlayerName(event.initiator) + mist.DBs.activeHumans[Unit.getName(event.initiator)] = newU + --trigger.action.outText('added: ' .. Unit.getName(event.initiator), 20) + end + elseif event.id == world.event.S_EVENT_PLAYER_LEAVE_UNIT and event.initiator then + if mist.DBs.activeHumans[Unit.getName(event.initiator)] then + mist.DBs.activeHumans[Unit.getName(event.initiator)] = nil + -- trigger.action.outText('removed via control: ' .. Unit.getName(event.initiator), 20) + end + end + end + + mist.addEventHandler(addClientsToActive)]] end @@ -2228,7 +2240,7 @@ end function mist.makeUnitTable(tbl) - --[[ +--[[ Prefixes: "[-u]" - subtract this unit if its in the table "[g]" - add this group to the table @@ -2310,160 +2322,161 @@ Country names to be used in [c] and [-c] short-cuts: for i = 1, #tbl do local unit = tbl[i] if unit:sub(1,4) == '[-u]' then --subtract a unit - if units_by_name[unit:sub(5)] then -- 5 to end - units_by_name[unit:sub(5)] = nil --remove - end + if units_by_name[unit:sub(5)] then -- 5 to end + units_by_name[unit:sub(5)] = nil --remove + end elseif unit:sub(1,3) == '[g]' then -- add a group - for coa, coa_tbl in pairs(l_munits) do - for country, country_table in pairs(coa_tbl) do - for unit_type, unit_type_tbl in pairs(country_table) do - if type(unit_type_tbl) == 'table' then - for group_ind, group_tbl in pairs(unit_type_tbl) do - if type(group_tbl) == 'table' and group_tbl.groupName == unit:sub(4) then -- index 4 to end - for unit_ind, unit in pairs(group_tbl.units) do - units_by_name[unit.unitName] = true --add - end + for coa, coa_tbl in pairs(l_munits) do + for country, country_table in pairs(coa_tbl) do + for unit_type, unit_type_tbl in pairs(country_table) do + if type(unit_type_tbl) == 'table' then + for group_ind, group_tbl in pairs(unit_type_tbl) do + if type(group_tbl) == 'table' and group_tbl.groupName == unit:sub(4) then -- index 4 to end + for unit_ind, unit in pairs(group_tbl.units) do + units_by_name[unit.unitName] = true --add + end + end end end end end end - end elseif unit:sub(1,4) == '[-g]' then -- subtract a group - for coa, coa_tbl in pairs(l_munits) do - for country, country_table in pairs(coa_tbl) do - for unit_type, unit_type_tbl in pairs(country_table) do - if type(unit_type_tbl) == 'table' then - for group_ind, group_tbl in pairs(unit_type_tbl) do - if type(group_tbl) == 'table' and group_tbl.groupName == unit:sub(5) then -- index 5 to end - for unit_ind, unit in pairs(group_tbl.units) do - if units_by_name[unit.unitName] then - units_by_name[unit.unitName] = nil --remove + for coa, coa_tbl in pairs(l_munits) do + for country, country_table in pairs(coa_tbl) do + for unit_type, unit_type_tbl in pairs(country_table) do + if type(unit_type_tbl) == 'table' then + for group_ind, group_tbl in pairs(unit_type_tbl) do + if type(group_tbl) == 'table' and group_tbl.groupName == unit:sub(5) then -- index 5 to end + for unit_ind, unit in pairs(group_tbl.units) do + if units_by_name[unit.unitName] then + units_by_name[unit.unitName] = nil --remove + end + end end end - end end end end end - end elseif unit:sub(1,3) == '[c]' then -- add a country - local category = '' - local country_start = 4 - if unit:sub(4,15) == '[helicopter]' then - category = 'helicopter' - country_start = 16 - elseif unit:sub(4,10) == '[plane]' then - category = 'plane' - country_start = 11 - elseif unit:sub(4,9) == '[ship]' then - category = 'ship' - country_start = 10 - elseif unit:sub(4,12) == '[vehicle]' then - category = 'vehicle' - country_start = 13 - end - for coa, coa_tbl in pairs(l_munits) do - for country, country_table in pairs(coa_tbl) do - if country == string.lower(unit:sub(country_start)) then -- match - for unit_type, unit_type_tbl in pairs(country_table) do - if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then - for group_ind, group_tbl in pairs(unit_type_tbl) do - if type(group_tbl) == 'table' then - for unit_ind, unit in pairs(group_tbl.units) do - units_by_name[unit.unitName] = true --add + local category = '' + local country_start = 4 + if unit:sub(4,15) == '[helicopter]' then + category = 'helicopter' + country_start = 16 + elseif unit:sub(4,10) == '[plane]' then + category = 'plane' + country_start = 11 + elseif unit:sub(4,9) == '[ship]' then + category = 'ship' + country_start = 10 + elseif unit:sub(4,12) == '[vehicle]' then + category = 'vehicle' + country_start = 13 + end + for coa, coa_tbl in pairs(l_munits) do + for country, country_table in pairs(coa_tbl) do + if country == string.lower(unit:sub(country_start)) then -- match + for unit_type, unit_type_tbl in pairs(country_table) do + if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then + for group_ind, group_tbl in pairs(unit_type_tbl) do + if type(group_tbl) == 'table' then + for unit_ind, unit in pairs(group_tbl.units) do + units_by_name[unit.unitName] = true --add + end + end end end end end end - end end - end elseif unit:sub(1,4) == '[-c]' then -- subtract a country - local category = '' - local country_start = 5 - if unit:sub(5,16) == '[helicopter]' then - category = 'helicopter' - country_start = 17 - elseif unit:sub(5,11) == '[plane]' then - category = 'plane' - country_start = 12 - elseif unit:sub(5,10) == '[ship]' then - category = 'ship' - country_start = 11 - elseif unit:sub(5,13) == '[vehicle]' then - category = 'vehicle' - country_start = 14 - end - for coa, coa_tbl in pairs(l_munits) do - for country, country_table in pairs(coa_tbl) do - if country == string.lower(unit:sub(country_start)) then -- match - for unit_type, unit_type_tbl in pairs(country_table) do - if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then - for group_ind, group_tbl in pairs(unit_type_tbl) do - if type(group_tbl) == 'table' then - for unit_ind, unit in pairs(group_tbl.units) do - if units_by_name[unit.unitName] then - units_by_name[unit.unitName] = nil --remove + local category = '' + local country_start = 5 + if unit:sub(5,16) == '[helicopter]' then + category = 'helicopter' + country_start = 17 + elseif unit:sub(5,11) == '[plane]' then + category = 'plane' + country_start = 12 + elseif unit:sub(5,10) == '[ship]' then + category = 'ship' + country_start = 11 + elseif unit:sub(5,13) == '[vehicle]' then + category = 'vehicle' + country_start = 14 + end + for coa, coa_tbl in pairs(l_munits) do + for country, country_table in pairs(coa_tbl) do + if country == string.lower(unit:sub(country_start)) then -- match + for unit_type, unit_type_tbl in pairs(country_table) do + if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then + for group_ind, group_tbl in pairs(unit_type_tbl) do + if type(group_tbl) == 'table' then + for unit_ind, unit in pairs(group_tbl.units) do + if units_by_name[unit.unitName] then + units_by_name[unit.unitName] = nil --remove + end + end end end end end end end - end end - end elseif unit:sub(1,6) == '[blue]' then -- add blue coalition - local category = '' - if unit:sub(7) == '[helicopter]' then - category = 'helicopter' - elseif unit:sub(7) == '[plane]' then - category = 'plane' - elseif unit:sub(7) == '[ship]' then - category = 'ship' - elseif unit:sub(7) == '[vehicle]' then - category = 'vehicle' - end - for coa, coa_tbl in pairs(l_munits) do - if coa == 'blue' then - for country, country_table in pairs(coa_tbl) do - for unit_type, unit_type_tbl in pairs(country_table) do - if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then - for group_ind, group_tbl in pairs(unit_type_tbl) do - if type(group_tbl) == 'table' then - for unit_ind, unit in pairs(group_tbl.units) do - units_by_name[unit.unitName] = true --add + local category = '' + if unit:sub(7) == '[helicopter]' then + category = 'helicopter' + elseif unit:sub(7) == '[plane]' then + category = 'plane' + elseif unit:sub(7) == '[ship]' then + category = 'ship' + elseif unit:sub(7) == '[vehicle]' then + category = 'vehicle' + end + for coa, coa_tbl in pairs(l_munits) do + if coa == 'blue' then + for country, country_table in pairs(coa_tbl) do + for unit_type, unit_type_tbl in pairs(country_table) do + if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then + for group_ind, group_tbl in pairs(unit_type_tbl) do + if type(group_tbl) == 'table' then + for unit_ind, unit in pairs(group_tbl.units) do + units_by_name[unit.unitName] = true --add + end end end end end end end - end - end + end elseif unit:sub(1,7) == '[-blue]' then -- subtract blue coalition - local category = '' - if unit:sub(8) == '[helicopter]' then - category = 'helicopter' - elseif unit:sub(8) == '[plane]' then - category = 'plane' - elseif unit:sub(8) == '[ship]' then - category = 'ship' - elseif unit:sub(8) == '[vehicle]' then - category = 'vehicle' - end - for coa, coa_tbl in pairs(l_munits) do - if coa == 'blue' then - for country, country_table in pairs(coa_tbl) do - for unit_type, unit_type_tbl in pairs(country_table) do - if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then - for group_ind, group_tbl in pairs(unit_type_tbl) do - if type(group_tbl) == 'table' then - for unit_ind, unit in pairs(group_tbl.units) do - if units_by_name[unit.unitName] then - units_by_name[unit.unitName] = nil --remove + local category = '' + if unit:sub(8) == '[helicopter]' then + category = 'helicopter' + elseif unit:sub(8) == '[plane]' then + category = 'plane' + elseif unit:sub(8) == '[ship]' then + category = 'ship' + elseif unit:sub(8) == '[vehicle]' then + category = 'vehicle' + end + for coa, coa_tbl in pairs(l_munits) do + if coa == 'blue' then + for country, country_table in pairs(coa_tbl) do + for unit_type, unit_type_tbl in pairs(country_table) do + if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then + for group_ind, group_tbl in pairs(unit_type_tbl) do + if type(group_tbl) == 'table' then + for unit_ind, unit in pairs(group_tbl.units) do + if units_by_name[unit.unitName] then + units_by_name[unit.unitName] = nil --remove + end end end end @@ -2471,28 +2484,28 @@ Country names to be used in [c] and [-c] short-cuts: end end end - end - end + end elseif unit:sub(1,5) == '[red]' then -- add red coalition - local category = '' - if unit:sub(6) == '[helicopter]' then - category = 'helicopter' - elseif unit:sub(6) == '[plane]' then - category = 'plane' - elseif unit:sub(6) == '[ship]' then - category = 'ship' - elseif unit:sub(6) == '[vehicle]' then - category = 'vehicle' - end - for coa, coa_tbl in pairs(l_munits) do - if coa == 'red' then - for country, country_table in pairs(coa_tbl) do - for unit_type, unit_type_tbl in pairs(country_table) do - if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then - for group_ind, group_tbl in pairs(unit_type_tbl) do - if type(group_tbl) == 'table' then - for unit_ind, unit in pairs(group_tbl.units) do - units_by_name[unit.unitName] = true --add + local category = '' + if unit:sub(6) == '[helicopter]' then + category = 'helicopter' + elseif unit:sub(6) == '[plane]' then + category = 'plane' + elseif unit:sub(6) == '[ship]' then + category = 'ship' + elseif unit:sub(6) == '[vehicle]' then + category = 'vehicle' + end + for coa, coa_tbl in pairs(l_munits) do + if coa == 'red' then + for country, country_table in pairs(coa_tbl) do + for unit_type, unit_type_tbl in pairs(country_table) do + if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then + for group_ind, group_tbl in pairs(unit_type_tbl) do + if type(group_tbl) == 'table' then + for unit_ind, unit in pairs(group_tbl.units) do + units_by_name[unit.unitName] = true --add + end end end end @@ -2500,23 +2513,77 @@ Country names to be used in [c] and [-c] short-cuts: end end end - end elseif unit:sub(1,6) == '[-red]' then -- subtract red coalition - local category = '' - if unit:sub(7) == '[helicopter]' then - category = 'helicopter' - elseif unit:sub(7) == '[plane]' then - category = 'plane' - elseif unit:sub(7) == '[ship]' then - category = 'ship' - elseif unit:sub(7) == '[vehicle]' then - category = 'vehicle' - end - for coa, coa_tbl in pairs(l_munits) do - if coa == 'red' then + local category = '' + if unit:sub(7) == '[helicopter]' then + category = 'helicopter' + elseif unit:sub(7) == '[plane]' then + category = 'plane' + elseif unit:sub(7) == '[ship]' then + category = 'ship' + elseif unit:sub(7) == '[vehicle]' then + category = 'vehicle' + end + for coa, coa_tbl in pairs(l_munits) do + if coa == 'red' then + for country, country_table in pairs(coa_tbl) do + for unit_type, unit_type_tbl in pairs(country_table) do + if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then + for group_ind, group_tbl in pairs(unit_type_tbl) do + if type(group_tbl) == 'table' then + for unit_ind, unit in pairs(group_tbl.units) do + if units_by_name[unit.unitName] then + units_by_name[unit.unitName] = nil --remove + end + end + end + end + end + end + end + end + end + elseif unit:sub(1,5) == '[all]' then -- add all of a certain category (or all categories) + local category = '' + if unit:sub(6) == '[helicopter]' then + category = 'helicopter' + elseif unit:sub(6) == '[plane]' then + category = 'plane' + elseif unit:sub(6) == '[ship]' then + category = 'ship' + elseif unit:sub(6) == '[vehicle]' then + category = 'vehicle' + end + for coa, coa_tbl in pairs(l_munits) do for country, country_table in pairs(coa_tbl) do for unit_type, unit_type_tbl in pairs(country_table) do - if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then + if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then + for group_ind, group_tbl in pairs(unit_type_tbl) do + if type(group_tbl) == 'table' then + for unit_ind, unit in pairs(group_tbl.units) do + units_by_name[unit.unitName] = true --add + end + end + end + end + end + end + end + elseif unit:sub(1,6) == '[-all]' then -- subtract all of a certain category (or all categories) + local category = '' + if unit:sub(7) == '[helicopter]' then + category = 'helicopter' + elseif unit:sub(7) == '[plane]' then + category = 'plane' + elseif unit:sub(7) == '[ship]' then + category = 'ship' + elseif unit:sub(7) == '[vehicle]' then + category = 'vehicle' + end + for coa, coa_tbl in pairs(l_munits) do + for country, country_table in pairs(coa_tbl) do + for unit_type, unit_type_tbl in pairs(country_table) do + if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then for group_ind, group_tbl in pairs(unit_type_tbl) do if type(group_tbl) == 'table' then for unit_ind, unit in pairs(group_tbl.units) do @@ -2529,83 +2596,28 @@ Country names to be used in [c] and [-c] short-cuts: end end end - end - end - elseif unit:sub(1,5) == '[all]' then -- add all of a certain category (or all categories) - local category = '' - if unit:sub(6) == '[helicopter]' then - category = 'helicopter' - elseif unit:sub(6) == '[plane]' then - category = 'plane' - elseif unit:sub(6) == '[ship]' then - category = 'ship' - elseif unit:sub(6) == '[vehicle]' then - category = 'vehicle' - end - for coa, coa_tbl in pairs(l_munits) do - for country, country_table in pairs(coa_tbl) do - for unit_type, unit_type_tbl in pairs(country_table) do - if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then - for group_ind, group_tbl in pairs(unit_type_tbl) do - if type(group_tbl) == 'table' then - for unit_ind, unit in pairs(group_tbl.units) do - units_by_name[unit.unitName] = true --add - end - end - end - end - end - end - end - elseif unit:sub(1,6) == '[-all]' then -- subtract all of a certain category (or all categories) - local category = '' - if unit:sub(7) == '[helicopter]' then - category = 'helicopter' - elseif unit:sub(7) == '[plane]' then - category = 'plane' - elseif unit:sub(7) == '[ship]' then - category = 'ship' - elseif unit:sub(7) == '[vehicle]' then - category = 'vehicle' - end - for coa, coa_tbl in pairs(l_munits) do - for country, country_table in pairs(coa_tbl) do - for unit_type, unit_type_tbl in pairs(country_table) do - if type(unit_type_tbl) == 'table' and (category == '' or unit_type == category) then - for group_ind, group_tbl in pairs(unit_type_tbl) do - if type(group_tbl) == 'table' then - for unit_ind, unit in pairs(group_tbl.units) do - if units_by_name[unit.unitName] then - units_by_name[unit.unitName] = nil --remove - end - end - end - end - end - end - end - end + end else -- just a regular unit - units_by_name[unit] = true --add + units_by_name[unit] = true --add end end - + local units_tbl = {} -- indexed sequentially for unit_name, val in pairs(units_by_name) do - if val then + if val then units_tbl[#units_tbl + 1] = unit_name -- add all the units to the table end end - - + + units_tbl['processed'] = timer.getTime() --add the processed flag return units_tbl end -mist.getDeadMapObjsInZones = function(zone_names) - -- zone_names: table of zone names - -- returns: table of dead map objects (indexed numerically) +mist.getDeadMapObjsInZones = function(zone_names) +-- zone_names: table of zone names +-- returns: table of dead map objects (indexed numerically) local map_objs = {} local zones = {} for i = 1, #zone_names do @@ -2615,26 +2627,26 @@ mist.getDeadMapObjsInZones = function(zone_names) end for obj_id, obj in pairs(mist.DBs.deadObjects) do if obj.objectType and obj.objectType == 'building' then --dead map object - for i = 1, #zones do - if ((zones[i].point.x - obj.objectPos.x)^2 + (zones[i].point.z - obj.objectPos.z)^2)^0.5 <= zones[i].radius then - map_objs[#map_objs + 1] = mist.utils.deepCopy(obj) + for i = 1, #zones do + if ((zones[i].point.x - obj.objectPos.x)^2 + (zones[i].point.z - obj.objectPos.z)^2)^0.5 <= zones[i].radius then + map_objs[#map_objs + 1] = mist.utils.deepCopy(obj) + end end end - end end return map_objs end -mist.getDeadMapObjsInPolygonZone = function(zone) - -- zone_names: table of zone names - -- returns: table of dead map objects (indexed numerically) +mist.getDeadMapObjsInPolygonZone = function(zone) +-- zone_names: table of zone names +-- returns: table of dead map objects (indexed numerically) local map_objs = {} for obj_id, obj in pairs(mist.DBs.deadObjects) do if obj.objectType and obj.objectType == 'building' then --dead map object - if mist.pointInPolygon(obj.objectPos, zone) then - map_objs[#map_objs + 1] = mist.utils.deepCopy(obj) - end + if mist.pointInPolygon(obj.objectPos, zone) then + map_objs[#map_objs + 1] = mist.utils.deepCopy(obj) + end end end return map_objs @@ -2643,7 +2655,7 @@ end mist.flagFunc = {} mist.flagFunc.mapobjs_dead_zones = function(vars) - --[[vars needs to be: +--[[vars needs to be: zones = table or string, flag = number, stopflag = number or nil, @@ -2653,14 +2665,14 @@ AND used by function, initial_number ]] - -- type_tbl +-- type_tbl local type_tbl = { [{'zones', 'zone'}] = {'table', 'string'}, - flag = {'number', 'string'}, - stopflag = {'number', 'string', 'nil'}, + flag = {'number', 'string'}, + stopflag = {'number', 'string', 'nil'}, [{'req_num', 'reqnum'}] = {'number', 'nil'}, } - + local err, errmsg = mist.utils.typeCheck('mist.flagFunc.mapobjs_dead_zones', type_tbl, vars) assert(err, errmsg) local zones = vars.zones or vars.zone @@ -2668,15 +2680,15 @@ initial_number local stopflag = vars.stopflag or -1 local req_num = vars.req_num or vars.reqnum or 1 local initial_number = vars.initial_number - + if type(zones) == 'string' then zones = {zones} end - - if not initial_number then + + if not initial_number then initial_number = #mist.getDeadMapObjsInZones(zones) end - + if stopflag == -1 or (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then if (#mist.getDeadMapObjsInZones(zones) - initial_number) >= req_num and trigger.misc.getUserFlag(flag) == 0 then trigger.action.setUserFlag(flag, true) @@ -2690,7 +2702,7 @@ end mist.flagFunc.mapobjs_dead_polygon = function(vars) - --[[vars needs to be: +--[[vars needs to be: zone = table, flag = number, stopflag = number or nil, @@ -2700,14 +2712,14 @@ AND used by function, initial_number ]] - -- type_tbl +-- type_tbl local type_tbl = { [{'zone', 'polyzone'}] = 'table', - flag = {'number', 'string'}, - stopflag = {'number', 'string', 'nil'}, + flag = {'number', 'string'}, + stopflag = {'number', 'string', 'nil'}, [{'req_num', 'reqnum'}] = {'number', 'nil'}, } - + local err, errmsg = mist.utils.typeCheck('mist.flagFunc.mapobjs_dead_polygon', type_tbl, vars) assert(err, errmsg) local zone = vars.zone or vars.polyzone @@ -2715,11 +2727,11 @@ initial_number local stopflag = vars.stopflag or -1 local req_num = vars.req_num or vars.reqnum or 1 local initial_number = vars.initial_number - - if not initial_number then + + if not initial_number then initial_number = #mist.getDeadMapObjsInPolygonZone(zone) end - + if stopflag == -1 or (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then if (#mist.getDeadMapObjsInPolygonZone(zone) - initial_number) >= req_num and trigger.misc.getUserFlag(flag) == 0 then trigger.action.setUserFlag(flag, true) @@ -2733,62 +2745,62 @@ end function mist.pointInPolygon(point, poly, maxalt) --raycasting point in polygon. Code from http://softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm ---[[local type_tbl = { - point = {'table'}, - poly = {'table'}, - maxalt = {'number', 'nil'}, - } - - local err, errmsg = mist.utils.typeCheck('mist.pointInPolygon', type_tbl, {point, poly, maxalt}) - assert(err, errmsg) - ]] -point = mist.utils.makeVec3(point) -local px = point.x -local pz = point.z -local cn = 0 -local newpoly = mist.utils.deepCopy(poly) - -if not maxalt or (point.y <= maxalt) then - local polysize = #newpoly - newpoly[#newpoly + 1] = newpoly[1] - - newpoly[1] = mist.utils.makeVec3(newpoly[1]) - - for k = 1, polysize do - newpoly[k+1] = mist.utils.makeVec3(newpoly[k+1]) - if ((newpoly[k].z <= pz) and (newpoly[k+1].z > pz)) or ((newpoly[k].z > pz) and (newpoly[k+1].z <= pz)) then - local vt = (pz - newpoly[k].z) / (newpoly[k+1].z - newpoly[k].z) - if (px < newpoly[k].x + vt*(newpoly[k+1].x - newpoly[k].x)) then - cn = cn + 1 + --[[local type_tbl = { + point = {'table'}, + poly = {'table'}, + maxalt = {'number', 'nil'}, + } + + local err, errmsg = mist.utils.typeCheck('mist.pointInPolygon', type_tbl, {point, poly, maxalt}) + assert(err, errmsg) + ]] + point = mist.utils.makeVec3(point) + local px = point.x + local pz = point.z + local cn = 0 + local newpoly = mist.utils.deepCopy(poly) + + if not maxalt or (point.y <= maxalt) then + local polysize = #newpoly + newpoly[#newpoly + 1] = newpoly[1] + + newpoly[1] = mist.utils.makeVec3(newpoly[1]) + + for k = 1, polysize do + newpoly[k+1] = mist.utils.makeVec3(newpoly[k+1]) + if ((newpoly[k].z <= pz) and (newpoly[k+1].z > pz)) or ((newpoly[k].z > pz) and (newpoly[k+1].z <= pz)) then + local vt = (pz - newpoly[k].z) / (newpoly[k+1].z - newpoly[k].z) + if (px < newpoly[k].x + vt*(newpoly[k+1].x - newpoly[k].x)) then + cn = cn + 1 + end end end + + return cn%2 == 1 + else + return false end - - return cn%2 == 1 -else - return false -end end mist.getUnitsInPolygon = function (unit_names, polyZone, max_alt) local units = {} - + for i = 1, #unit_names do units[#units + 1] = Unit.getByName(unitNames[i]) end - + local inZoneUnits = {} for i =1, #units do if units[i]:isActive() and mist.pointInPolygon(units[i]:getPosition().p, polyZone, max_alt) then inZoneUnits[inZoneUnits + 1] = units[i] end end - + return inZoneUnits end function mist.flagFunc.units_in_polygon(vars) - --[[vars needs to be: +--[[vars needs to be: units = table, zone = table, flag = number, @@ -2799,19 +2811,19 @@ req_num = number or nil toggle = boolean or nil unitTableDef = table or nil ]] - -- type_tbl +-- type_tbl local type_tbl = { - [{'units', 'unit'}] = 'table', - [{'zone', 'polyzone'}] = 'table', - flag = {'number', 'string'}, - stopflag = {'number', 'string', 'nil'}, - [{'maxalt', 'alt'}] = {'number', 'nil'}, - interval = {'number', 'nil'}, + [{'units', 'unit'}] = 'table', + [{'zone', 'polyzone'}] = 'table', + flag = {'number', 'string'}, + stopflag = {'number', 'string', 'nil'}, + [{'maxalt', 'alt'}] = {'number', 'nil'}, + interval = {'number', 'nil'}, [{'req_num', 'reqnum'}] = {'number', 'nil'}, - toggle = {'boolean', 'nil'}, + toggle = {'boolean', 'nil'}, unitTableDef = {'table', 'nil'}, } - + local err, errmsg = mist.utils.typeCheck('mist.flagFunc.units_in_polygon', type_tbl, vars) assert(err, errmsg) local units = vars.units or vars.unit @@ -2823,13 +2835,13 @@ unitTableDef = table or nil local req_num = vars.req_num or vars.reqnum or 1 local toggle = vars.toggle or nil local unitTableDef = vars.unitTableDef - + if not units.processed then unitTableDef = mist.utils.deepCopy(units) end - + if (units.processed and units.processed < mist.getLastDBUpdateTime()) or not units.processed then -- run unit table short cuts - units = mist.makeUnitTable(unitTableDef) + units = mist.makeUnitTable(unitTableDef) end if stopflag == -1 or (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == 0) then @@ -2855,14 +2867,14 @@ unitTableDef = table or nil mist.scheduleFunction(mist.flagFunc.units_in_polygon, {{units = units, zone = zone, flag = flag, stopflag = stopflag, interval = interval, req_num = req_num, maxalt = maxalt, toggle = toggle, unitTableDef = unitTableDef}}, timer.getTime() + interval) end end - + end function mist.getUnitsInZones(unit_names, zone_names, zone_type) - + zone_type = zone_type or 'cylinder' if zone_type == 'c' or zone_type == 'cylindrical' or zone_type == 'C' then zone_type = 'cylinder' @@ -2870,7 +2882,7 @@ function mist.getUnitsInZones(unit_names, zone_names, zone_type) if zone_type == 's' or zone_type == 'spherical' or zone_type == 'S' then zone_type = 'sphere' end - + assert(zone_type == 'cylinder' or zone_type == 'sphere', 'invalid zone_type: ' .. tostring(zone_type)) local units = {} @@ -2882,24 +2894,24 @@ function mist.getUnitsInZones(unit_names, zone_names, zone_type) units[#units + 1] = unit end end - - + + for k = 1, #zone_names do local zone = trigger.misc.getZone(zone_names[k]) if zone then zones[#zones + 1] = {radius = zone.radius, x = zone.point.x, y = zone.point.y, z = zone.point.z} end end - + local in_zone_units = {} - + for units_ind = 1, #units do for zones_ind = 1, #zones do if zone_type == 'sphere' then --add land height value for sphere zone type - local alt = land.getHeight({x = zones[zones_ind].x, y = zones[zones_ind].z}) - if alt then - zones[zones_ind].y = alt - end + local alt = land.getHeight({x = zones[zones_ind].x, y = zones[zones_ind].z}) + if alt then + zones[zones_ind].y = alt + end end local unit_pos = units[units_ind]:getPosition().p if unit_pos and units[units_ind]:isActive() == true then @@ -2919,28 +2931,28 @@ end function mist.flagFunc.units_in_zones(vars) --[[vars needs to be: - units = table, - zones = table, - flag = number, - stopflag = number or nil, - zone_type = string or nil, - req_num = number or nil, - interval = number or nil - toggle = boolean or nil - ]] + units = table, + zones = table, + flag = number, + stopflag = number or nil, + zone_type = string or nil, + req_num = number or nil, + interval = number or nil + toggle = boolean or nil + ]] -- type_tbl local type_tbl = { - units = 'table', - zones = 'table', - flag = {'number', 'string'}, - stopflag = {'number', 'string', 'nil'}, - [{'zone_type', 'zonetype'}] = {'string', 'nil'}, + units = 'table', + zones = 'table', + flag = {'number', 'string'}, + stopflag = {'number', 'string', 'nil'}, + [{'zone_type', 'zonetype'}] = {'string', 'nil'}, [{'req_num', 'reqnum'}] = {'number', 'nil'}, interval = {'number', 'nil'}, toggle = {'boolean', 'nil'}, unitTableDef = {'table', 'nil'}, } - + local err, errmsg = mist.utils.typeCheck('mist.flagFunc.units_in_zones', type_tbl, vars) assert(err, errmsg) local units = vars.units @@ -2952,35 +2964,35 @@ function mist.flagFunc.units_in_zones(vars) local interval = vars.interval or 1 local toggle = vars.toggle or nil local unitTableDef = vars.unitTableDef - + if not units.processed then unitTableDef = mist.utils.deepCopy(units) end - + if (units.processed and units.processed < mist.getLastDBUpdateTime()) or not units.processed then -- run unit table short cuts - units = mist.makeUnitTable(unitTableDef) + units = mist.makeUnitTable(unitTableDef) end - + if stopflag == -1 or (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then - + local in_zone_units = mist.getUnitsInZones(units, zones, zone_type) - + if #in_zone_units >= req_num and trigger.misc.getUserFlag(flag) == 0 then trigger.action.setUserFlag(flag, true) elseif #in_zone_units < req_num and toggle then trigger.action.setUserFlag(flag, false) - end + end -- do another check in case stopflag was set true by this function if (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then mist.scheduleFunction(mist.flagFunc.units_in_zones, {{units = units, zones = zones, flag = flag, stopflag = stopflag, zone_type = zone_type, req_num = req_num, interval = interval, toggle = toggle, unitTableDef = unitTableDef}}, timer.getTime() + interval) end end - + end function mist.getUnitsInMovingZones(unit_names, zone_unit_names, radius, zone_type) - + zone_type = zone_type or 'cylinder' if zone_type == 'c' or zone_type == 'cylindrical' or zone_type == 'C' then zone_type = 'cylinder' @@ -2988,7 +3000,7 @@ function mist.getUnitsInMovingZones(unit_names, zone_unit_names, radius, zone_ty if zone_type == 's' or zone_type == 'spherical' or zone_type == 'S' then zone_type = 'sphere' end - + assert(zone_type == 'cylinder' or zone_type == 'sphere', 'invalid zone_type: ' .. tostring(zone_type)) local units = {} @@ -3000,7 +3012,7 @@ function mist.getUnitsInMovingZones(unit_names, zone_unit_names, radius, zone_ty units[#units + 1] = unit end end - + for k = 1, #zone_unit_names do local unit = Unit.getByName(zone_unit_names[k]) if unit then @@ -3009,7 +3021,7 @@ function mist.getUnitsInMovingZones(unit_names, zone_unit_names, radius, zone_ty end local in_zone_units = {} - + for units_ind = 1, #units do for zone_units_ind = 1, #zone_units do local unit_pos = units[units_ind]:getPosition().p @@ -3032,30 +3044,31 @@ end function mist.flagFunc.units_in_moving_zones(vars) --[[vars needs to be: - units = table, - zone_units = table, - radius = number, - flag = number, - stopflag = number or nil, - zone_type = string or nil, - req_num = number or nil, - interval = number or nil - toggle = boolean or nil - ]] + units = table, + zone_units = table, + radius = number, + flag = number, + stopflag = number or nil, + zone_type = string or nil, + req_num = number or nil, + interval = number or nil + toggle = boolean or nil + ]] -- type_tbl local type_tbl = { - units = 'table', - [{'zone_units', 'zoneunits'}] = 'table', + units = 'table', + [{'zone_units', 'zoneunits'}] = 'table', radius = 'number', - flag = {'number', 'string'}, - stopflag = {'number', 'string', 'nil'}, - [{'zone_type', 'zonetype'}] = {'string', 'nil'}, + flag = {'number', 'string'}, + stopflag = {'number', 'string', 'nil'}, + [{'zone_type', 'zonetype'}] = {'string', 'nil'}, [{'req_num', 'reqnum'}] = {'number', 'nil'}, interval = {'number', 'nil'}, toggle = {'boolean', 'nil'}, unitTableDef = {'table', 'nil'}, + zUnitTableDef = {'table', 'nil'}, } - + local err, errmsg = mist.utils.typeCheck('mist.flagFunc.units_in_moving_zones', type_tbl, vars) assert(err, errmsg) local units = vars.units @@ -3068,39 +3081,48 @@ function mist.flagFunc.units_in_moving_zones(vars) local interval = vars.interval or 1 local toggle = vars.toggle or nil local unitTableDef = vars.unitTableDef - + local zUnitTableDef = vars.zUnitTableDef + if not units.processed then unitTableDef = mist.utils.deepCopy(units) end - + + if not zone_units.processed then + zUnitTableDef = mist.utils.deepCopy(zone_units) + end + if (units.processed and units.processed < mist.getLastDBUpdateTime()) or not units.processed then -- run unit table short cuts - units = mist.makeUnitTable(unitTableDef) + units = mist.makeUnitTable(unitTableDef) + end + + if (zone_units.processed and zone_units.processed < mist.getLastDBUpdateTime()) or not zone_units.processed then -- run unit table short cuts + zone_units = mist.makeUnitTable(zUnitTableDef) end if stopflag == -1 or (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then - + local in_zone_units = mist.getUnitsInMovingZones(units, zone_units, radius, zone_type) - + if #in_zone_units >= req_num and trigger.misc.getUserFlag(flag) == 0 then trigger.action.setUserFlag(flag, true) elseif #in_zone_units < req_num and toggle then trigger.action.setUserFlag(flag, false) - end + end -- do another check in case stopflag was set true by this function if (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then - mist.scheduleFunction(mist.flagFunc.units_in_moving_zones, {{units = units, zone_units = zone_units, radius = radius, flag = flag, stopflag = stopflag, zone_type = zone_type, req_num = req_num, interval = interval, toggle = toggle}}, timer.getTime() + interval) + mist.scheduleFunction(mist.flagFunc.units_in_moving_zones, {{units = units, zone_units = zone_units, radius = radius, flag = flag, stopflag = stopflag, zone_type = zone_type, req_num = req_num, interval = interval, toggle = toggle, unitTableDef = unitTableDef, zUnitTableDef = zUnitTableDef}}, timer.getTime() + interval) end end - + end mist.getUnitsLOS = function(unitset1, altoffset1, unitset2, altoffset2, radius) radius = radius or math.huge - + local unit_info1 = {} local unit_info2 = {} - + -- get the positions all in one step, saves execution time. for unitset1_ind = 1, #unitset1 do local unit1 = Unit.getByName(unitset1[unitset1_ind]) @@ -3110,7 +3132,7 @@ mist.getUnitsLOS = function(unitset1, altoffset1, unitset2, altoffset2, radius) unit_info1[#unit_info1]["pos"] = unit1:getPosition().p end end - + for unitset2_ind = 1, #unitset2 do local unit2 = Unit.getByName(unitset2[unitset2_ind]) if unit2 and unit2:isActive() == true then @@ -3126,28 +3148,28 @@ mist.getUnitsLOS = function(unitset1, altoffset1, unitset2, altoffset2, radius) local unit_added = false for unit2_ind = 1, #unit_info2 do if radius == math.huge or (mist.vec.mag(mist.vec.sub(unit_info1[unit1_ind].pos, unit_info2[unit2_ind].pos)) < radius) then -- inside radius - local point1 = { x = unit_info1[unit1_ind].pos.x, y = unit_info1[unit1_ind].pos.y + altoffset1, z = unit_info1[unit1_ind].pos.z} - local point2 = { x = unit_info2[unit2_ind].pos.x, y = unit_info2[unit2_ind].pos.y + altoffset2, z = unit_info2[unit2_ind].pos.z} - if land.isVisible(point1, point2) then - if unit_added == false then - unit_added = true - LOS_data[#LOS_data + 1] = {} - LOS_data[#LOS_data]['unit'] = unit_info1[unit1_ind].unit - LOS_data[#LOS_data]['vis'] = {} - LOS_data[#LOS_data]['vis'][#LOS_data[#LOS_data]['vis'] + 1] = unit_info2[unit2_ind].unit - else - LOS_data[#LOS_data]['vis'][#LOS_data[#LOS_data]['vis'] + 1] = unit_info2[unit2_ind].unit + local point1 = { x = unit_info1[unit1_ind].pos.x, y = unit_info1[unit1_ind].pos.y + altoffset1, z = unit_info1[unit1_ind].pos.z} + local point2 = { x = unit_info2[unit2_ind].pos.x, y = unit_info2[unit2_ind].pos.y + altoffset2, z = unit_info2[unit2_ind].pos.z} + if land.isVisible(point1, point2) then + if unit_added == false then + unit_added = true + LOS_data[#LOS_data + 1] = {} + LOS_data[#LOS_data]['unit'] = unit_info1[unit1_ind].unit + LOS_data[#LOS_data]['vis'] = {} + LOS_data[#LOS_data]['vis'][#LOS_data[#LOS_data]['vis'] + 1] = unit_info2[unit2_ind].unit + else + LOS_data[#LOS_data]['vis'][#LOS_data[#LOS_data]['vis'] + 1] = unit_info2[unit2_ind].unit + end end end - end end end - + return LOS_data end mist.flagFunc.units_LOS = function(vars) - --[[vars needs to be: +--[[vars needs to be: unitset1 = table, altoffset1 = number, unitset2 = table, @@ -3159,22 +3181,22 @@ interval = number or nil, req_num = number or nil toggle = boolean or nil ]] - -- type_tbl +-- type_tbl local type_tbl = { - [{'unitset1', 'units1'}] = 'table', - [{'altoffset1', 'alt1'}] = 'number', - [{'unitset2', 'units2'}] = 'table', - [{'altoffset2', 'alt2'}] = 'number', - flag = {'number', 'string'}, - stopflag = {'number', 'string', 'nil'}, - [{'req_num', 'reqnum'}] = {'number', 'nil'}, - interval = {'number', 'nil'}, + [{'unitset1', 'units1'}] = 'table', + [{'altoffset1', 'alt1'}] = 'number', + [{'unitset2', 'units2'}] = 'table', + [{'altoffset2', 'alt2'}] = 'number', + flag = {'number', 'string'}, + stopflag = {'number', 'string', 'nil'}, + [{'req_num', 'reqnum'}] = {'number', 'nil'}, + interval = {'number', 'nil'}, radius = {'number', 'nil'}, toggle = {'boolean', 'nil'}, unitTableDef1 = {'table', 'nil'}, unitTableDef2 = {'table', 'nil'}, } - + local err, errmsg = mist.utils.typeCheck('mist.flagFunc.units_LOS', type_tbl, vars) assert(err, errmsg) local unitset1 = vars.unitset1 or vars.units1 @@ -3189,33 +3211,33 @@ toggle = boolean or nil local toggle = vars.toggle or nil local unitTableDef1 = vars.unitTableDef1 local unitTableDef2 = vars.unitTableDef2 - + if not unitset1.processed then unitTableDef1 = mist.utils.deepCopy(unitset1) end - + if not unitset2.processed then unitTableDef2 = mist.utils.deepCopy(unitset2) end - + if (unitset1.processed and unitset1.processed < mist.getLastDBUpdateTime()) or not unitset1.processed then -- run unit table short cuts - units = mist.makeUnitTable(unitTableDef1) + unitset1 = mist.makeUnitTable(unitTableDef1) end - + if (unitset2.processed and unitset2.processed < mist.getLastDBUpdateTime()) or not unitset2.processed then -- run unit table short cuts - units = mist.makeUnitTable(unitTableDef2) + unitset2 = mist.makeUnitTable(unitTableDef2) end - - + + if stopflag == -1 or (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then - + local unitLOSdata = mist.getUnitsLOS(unitset1, altoffset1, unitset2, altoffset2, radius) - + if #unitLOSdata >= req_num and trigger.misc.getUserFlag(flag) == 0 then trigger.action.setUserFlag(flag, true) elseif #unitLOSdata < req_num and toggle then trigger.action.setUserFlag(flag, false) - end + end -- do another check in case stopflag was set true by this function if (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then mist.scheduleFunction(mist.flagFunc.units_LOS, {{unitset1 = unitset1, altoffset1 = altoffset1, unitset2 = unitset2, altoffset2 = altoffset2, flag = flag, stopflag = stopflag, radius = radius, req_num = req_num, interval = interval, toggle = toggle, unitTableDef1 = unitTableDef1, unitTableDef2 = unitTableDef2}}, timer.getTime() + interval) @@ -3224,7 +3246,7 @@ toggle = boolean or nil end mist.flagFunc.group_alive = function(vars) - --[[vars +--[[vars groupName flag toggle @@ -3233,23 +3255,23 @@ stopFlag ]] local type_tbl = { - [{'group', 'groupname', 'gp', 'groupName'}] = 'string', - flag = {'number', 'string'}, - stopflag = {'number', 'string', 'nil'}, - interval = {'number', 'nil'}, - toggle = {'boolean', 'nil'}, + [{'group', 'groupname', 'gp', 'groupName'}] = 'string', + flag = {'number', 'string'}, + stopflag = {'number', 'string', 'nil'}, + interval = {'number', 'nil'}, + toggle = {'boolean', 'nil'}, } - + local err, errmsg = mist.utils.typeCheck('mist.flagFunc.group_alive', type_tbl, vars) assert(err, errmsg) - + local groupName = vars.groupName or vars.group or vars.gp or vars.Groupname local flag = vars.flag local stopflag = vars.stopflag or -1 local interval = vars.interval or 1 local toggle = vars.toggle or nil - - + + if stopflag == -1 or (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then if Group.getByName(groupName) and Group.getByName(groupName):isExist() == true and #Group.getByName(groupName):getUnits() > 0 then if trigger.misc.getUserFlag(flag) == 0 then @@ -3261,7 +3283,7 @@ stopFlag end end end - + if (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then mist.scheduleFunction(mist.flagFunc.group_alive, {{groupName = groupName, flag = flag, stopflag = stopflag, interval = interval, toggle = toggle}}, timer.getTime() + interval) end @@ -3270,23 +3292,23 @@ end mist.flagFunc.group_dead = function(vars) local type_tbl = { - [{'group', 'groupname', 'gp', 'groupName'}] = 'string', - flag = {'number', 'string'}, - stopflag = {'number', 'string', 'nil'}, - interval = {'number', 'nil'}, - toggle = {'boolean', 'nil'}, + [{'group', 'groupname', 'gp', 'groupName'}] = 'string', + flag = {'number', 'string'}, + stopflag = {'number', 'string', 'nil'}, + interval = {'number', 'nil'}, + toggle = {'boolean', 'nil'}, } - + local err, errmsg = mist.utils.typeCheck('mist.flagFunc.group_dead', type_tbl, vars) assert(err, errmsg) - + local groupName = vars.groupName or vars.group or vars.gp or vars.Groupname local flag = vars.flag local stopflag = vars.stopflag or -1 local interval = vars.interval or 1 local toggle = vars.toggle or nil - - + + if stopflag == -1 or (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then if (Group.getByName(groupName) and Group.getByName(groupName):isExist() == false) or (Group.getByName(groupName) and #Group.getByName(groupName):getUnits() < 1) or not Group.getByName(groupName) then if trigger.misc.getUserFlag(flag) == 0 then @@ -3298,7 +3320,7 @@ mist.flagFunc.group_dead = function(vars) end end end - + if (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then mist.scheduleFunction(mist.flagFunc.group_dead, {{groupName = groupName, flag = flag, stopflag = stopflag, interval = interval, toggle = toggle}}, timer.getTime() + interval) end @@ -3306,25 +3328,25 @@ end mist.flagFunc.group_alive_less_than = function(vars) local type_tbl = { - [{'group', 'groupname', 'gp', 'groupName'}] = 'string', - percent = 'number', - flag = {'number', 'string'}, - stopflag = {'number', 'string', 'nil'}, - interval = {'number', 'nil'}, - toggle = {'boolean', 'nil'}, + [{'group', 'groupname', 'gp', 'groupName'}] = 'string', + percent = 'number', + flag = {'number', 'string'}, + stopflag = {'number', 'string', 'nil'}, + interval = {'number', 'nil'}, + toggle = {'boolean', 'nil'}, } - + local err, errmsg = mist.utils.typeCheck('mist.flagFunc.group_alive_less_than', type_tbl, vars) assert(err, errmsg) - + local groupName = vars.groupName or vars.group or vars.gp or vars.Groupname local flag = vars.flag local percent = vars.percent local stopflag = vars.stopflag or -1 local interval = vars.interval or 1 local toggle = vars.toggle or nil - - + + if stopflag == -1 or (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then if Group.getByName(groupName) and Group.getByName(groupName):isExist() == true then if Group.getByName(groupName):getSize()/Group.getByName(groupName):getInitialSize() < percent/100 then @@ -3342,7 +3364,7 @@ mist.flagFunc.group_alive_less_than = function(vars) end end end - + if (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then mist.scheduleFunction(mist.flagFunc.group_alive_less_than, {{groupName = groupName, flag = flag, stopflag = stopflag, interval = interval, toggle = toggle, percent = percent}}, timer.getTime() + interval) end @@ -3350,25 +3372,25 @@ end mist.flagFunc.group_alive_more_than = function(vars) local type_tbl = { - [{'group', 'groupname', 'gp', 'groupName'}] = 'string', - percent = 'number', - flag = {'number', 'string'}, - stopflag = {'number', 'string', 'nil'}, - interval = {'number', 'nil'}, - toggle = {'boolean', 'nil'}, + [{'group', 'groupname', 'gp', 'groupName'}] = 'string', + percent = 'number', + flag = {'number', 'string'}, + stopflag = {'number', 'string', 'nil'}, + interval = {'number', 'nil'}, + toggle = {'boolean', 'nil'}, } - + local err, errmsg = mist.utils.typeCheck('mist.flagFunc.group_alive_more_than', type_tbl, vars) assert(err, errmsg) - + local groupName = vars.groupName or vars.group or vars.gp or vars.Groupname local flag = vars.flag local percent = vars.percent local stopflag = vars.stopflag or -1 local interval = vars.interval or 1 local toggle = vars.toggle or nil - - + + if stopflag == -1 or (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then if Group.getByName(groupName) and Group.getByName(groupName):isExist() == true then if Group.getByName(groupName):getSize()/Group.getByName(groupName):getInitialSize() > percent/100 then @@ -3381,12 +3403,12 @@ mist.flagFunc.group_alive_more_than = function(vars) end end else --- just in case - if toggle and trigger.misc.getUserFlag(flag) == 1 then - trigger.action.setUserFlag(flag, false) - end + if toggle and trigger.misc.getUserFlag(flag) == 1 then + trigger.action.setUserFlag(flag, false) + end end end - + if (type(trigger.misc.getUserFlag(stopflag)) == 'number' and trigger.misc.getUserFlag(stopflag) == 0) or (type(trigger.misc.getUserFlag(stopflag)) == 'boolean' and trigger.misc.getUserFlag(stopflag) == false) then mist.scheduleFunction(mist.flagFunc.group_alive_more_than, {{groupName = groupName, flag = flag, stopflag = stopflag, interval = interval, toggle = toggle, percent = percent}}, timer.getTime() + interval) end @@ -3398,7 +3420,7 @@ end mist.getAvgPos = function(unitNames) local avgX, avgY, avgZ, totNum = 0, 0, 0, 0 for i = 1, #unitNames do - local unit + local unit if Unit.getByName(unitNames[i]) then unit = Unit.getByName(unitNames[i]) elseif StaticObject.getByName(unitNames[i]) then @@ -3407,12 +3429,12 @@ mist.getAvgPos = function(unitNames) if unit then local pos = unit:getPosition().p if pos then -- you never know O.o - avgX = avgX + pos.x - avgY = avgY + pos.y - avgZ = avgZ + pos.z - totNum = totNum + 1 + avgX = avgX + pos.x + avgY = avgY + pos.y + avgZ = avgZ + pos.z + totNum = totNum + 1 end - end + end end if totNum ~= 0 then return {x = avgX/totNum, y = avgY/totNum, z = avgZ/totNum} @@ -3427,7 +3449,7 @@ mist.getAvgGroupPos = function(groupName) for i = 1, #groupName:getSize() do table.insert(units, groupName.getUnit(i):getName()) end - + return mist.getAvgPos(units) end @@ -3447,43 +3469,43 @@ mist.demos.printFlightData = function(unit) local Yaw = angles.Yaw local AoA = angles.AoA local ClimbAngle = angles.ClimbAngle - + if not Heading then Heading = 'NA' else Heading = string.format('%12.2f', mist.utils.toDegree(Heading)) end - + if not Pitch then Pitch = 'NA' else Pitch = string.format('%12.2f', mist.utils.toDegree(Pitch)) end - - if not Roll then + + if not Roll then Roll = 'NA' else Roll = string.format('%12.2f', mist.utils.toDegree(Roll)) end - + local AoAplusYaw = 'NA' if AoA and Yaw then AoAplusYaw = string.format('%12.2f', mist.utils.toDegree((AoA^2 + Yaw^2)^0.5)) end - + if not Yaw then Yaw = 'NA' else Yaw = string.format('%12.2f', mist.utils.toDegree(Yaw)) end - + if not AoA then AoA = 'NA' else AoA = string.format('%12.2f', mist.utils.toDegree(AoA)) end - - if not ClimbAngle then + + if not ClimbAngle then ClimbAngle = 'NA' else ClimbAngle = string.format('%12.2f', mist.utils.toDegree(ClimbAngle)) @@ -3492,8 +3514,8 @@ mist.demos.printFlightData = function(unit) local unitVel = unit:getVelocity() local curTime = timer.getTime() local absVel = string.format('%12.2f', mist.vec.mag(unitVel)) - - + + local unitAcc = 'NA' local Gs = 'NA' local axialGs = 'NA' @@ -3502,32 +3524,32 @@ mist.demos.printFlightData = function(unit) local xAcc = (unitVel.x - prevVel.x)/(curTime - prevTime) local yAcc = (unitVel.y - prevVel.y)/(curTime - prevTime) local zAcc = (unitVel.z - prevVel.z)/(curTime - prevTime) - + unitAcc = string.format('%12.2f', mist.vec.mag({x = xAcc, y = yAcc, z = zAcc})) Gs = string.format('%12.2f', mist.vec.mag({x = xAcc, y = yAcc + 9.81, z = zAcc})/9.81) axialGs = string.format('%12.2f', mist.vec.dp({x = xAcc, y = yAcc + 9.81, z = zAcc}, unitPos.x)/9.81) transGs = string.format('%12.2f', mist.vec.mag(mist.vec.cp({x = xAcc, y = yAcc + 9.81, z = zAcc}, unitPos.x))/9.81) end - + local E = 0.5*mist.vec.mag(unitVel)^2 + 9.81*unitPos.p.y - + local energy = string.format('%12.2e', E) - + local dEdt = 'NA' if prevE and prevTime then dEdt = string.format('%12.2e', (E - prevE)/(curTime - prevTime)) end - + trigger.action.outText(string.format('%-25s', 'Heading: ') .. Heading .. ' degrees\n' .. string.format('%-25s', 'Roll: ') .. Roll .. ' degrees\n' .. string.format('%-25s', 'Pitch: ') .. Pitch - .. ' degrees\n' .. string.format('%-25s', 'Yaw: ') .. Yaw .. ' degrees\n' .. string.format('%-25s', 'AoA: ') .. AoA .. ' degrees\n' .. string.format('%-25s', 'AoA plus Yaw: ') .. AoAplusYaw .. ' degrees\n' .. string.format('%-25s', 'Climb Angle: ') .. - ClimbAngle .. ' degrees\n' .. string.format('%-25s', 'Absolute Velocity: ') .. absVel .. ' m/s\n' .. string.format('%-25s', 'Absolute Acceleration: ') .. unitAcc ..' m/s^2\n' - .. string.format('%-25s', 'Axial G loading: ') .. axialGs .. ' g\n' .. string.format('%-25s', 'Transverse G loading: ') .. transGs .. ' g\n' .. string.format('%-25s', 'Absolute G loading: ') .. Gs .. ' g\n' .. string.format('%-25s', 'Energy: ') .. energy .. ' J/kg\n' .. string.format('%-25s', 'dE/dt: ') .. dEdt .. - ' J/(kg*s)', 1) + .. ' degrees\n' .. string.format('%-25s', 'Yaw: ') .. Yaw .. ' degrees\n' .. string.format('%-25s', 'AoA: ') .. AoA .. ' degrees\n' .. string.format('%-25s', 'AoA plus Yaw: ') .. AoAplusYaw .. ' degrees\n' .. string.format('%-25s', 'Climb Angle: ') .. + ClimbAngle .. ' degrees\n' .. string.format('%-25s', 'Absolute Velocity: ') .. absVel .. ' m/s\n' .. string.format('%-25s', 'Absolute Acceleration: ') .. unitAcc ..' m/s^2\n' + .. string.format('%-25s', 'Axial G loading: ') .. axialGs .. ' g\n' .. string.format('%-25s', 'Transverse G loading: ') .. transGs .. ' g\n' .. string.format('%-25s', 'Absolute G loading: ') .. Gs .. ' g\n' .. string.format('%-25s', 'Energy: ') .. energy .. ' J/kg\n' .. string.format('%-25s', 'dE/dt: ') .. dEdt .. + ' J/(kg*s)', 1) return unitVel, E, curTime end end - + local function frameFinder(unit, prevVel, prevE, prevTime) if unit:isExist() then local currVel = unit:getVelocity() @@ -3537,15 +3559,15 @@ mist.demos.printFlightData = function(unit) mist.scheduleFunction(frameFinder, {unit, prevVel, prevE, prevTime}, timer.getTime() + 0.005) -- it can't go this fast, limited to the 100 times a sec check right now. end end - - + + local curVel = unit:getVelocity() local curTime = timer.getTime() local curE = 0.5*mist.vec.mag(curVel)^2 + 9.81*unit:getPosition().p.y frameFinder(unit, curVel, curE, curTime) - + end - + end -------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------- @@ -3560,14 +3582,14 @@ mist.air.fixedWing = {} mist.air.heli = {} mist.goRoute = function(group, path) - local misTask = { - id = 'Mission', - params = { - route = { + local misTask = { + id = 'Mission', + params = { + route = { points = mist.utils.deepCopy(path), - }, + }, }, - } + } if type(group) == 'string' then group = Group.getByName(group) end @@ -3584,58 +3606,58 @@ mist.goRoute = function(group, path) end function mist.getGroupRoute(groupIdent, task) -- same as getGroupPoints but returns speed and formation type along with vec2 of point} --- refactor to search by groupId and allow groupId and groupName as inputs -local gpId = groupIdent -if type(groupIdent) == 'string' and not tonumber(groupIdent) then - gpId = mist.DBs.MEgroupsByName[groupIdent].groupId -end - -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 == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" then -- only these types have points - 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 - if group_data and group_data.groupId == gpId then -- this is the group we are looking for - if group_data.route and group_data.route.points and #group_data.route.points > 0 then - local points = {} - - for point_num, point in pairs(group_data.route.points) do - local routeData = {} - if not point.point then - routeData.x = point.x - routeData.y = point.y - else - routeData.point = point.point --it's possible that the ME could move to the point = Vec2 notation. - end - routeData.form = point.action - routeData.speed = point.speed - routeData.alt = point.alt - routeData.alt_type = point.alt_type - routeData.airdromeId = point.airdromeId - routeData.helipadId = point.helipadId - routeData.type = point.type - routeData.action = point.action - if task then - routeData.task = point.task - end - points[point_num] = routeData - end - - return points - end - return - end --if group_data and group_data.name and group_data.name == 'groupname' - 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 + -- refactor to search by groupId and allow groupId and groupName as inputs + local gpId = groupIdent + if type(groupIdent) == 'string' and not tonumber(groupIdent) then + gpId = mist.DBs.MEgroupsByName[groupIdent].groupId + end + + 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 == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" then -- only these types have points + 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 + if group_data and group_data.groupId == gpId then -- this is the group we are looking for + if group_data.route and group_data.route.points and #group_data.route.points > 0 then + local points = {} + + for point_num, point in pairs(group_data.route.points) do + local routeData = {} + if not point.point then + routeData.x = point.x + routeData.y = point.y + else + routeData.point = point.point --it's possible that the ME could move to the point = Vec2 notation. + end + routeData.form = point.action + routeData.speed = point.speed + routeData.alt = point.alt + routeData.alt_type = point.alt_type + routeData.airdromeId = point.airdromeId + routeData.helipadId = point.helipadId + routeData.type = point.type + routeData.action = point.action + if task then + routeData.task = point.task + end + points[point_num] = routeData + end + + return points + end + return + end --if group_data and group_data.name and group_data.name == 'groupname' + 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 @@ -3648,28 +3670,28 @@ mist.ground.buildWP = function(point, overRideForm, overRideSpeed) local wp = {} wp.x = point.x - + if point.z then wp.y = point.z else wp.y = point.y end local form, speed - - if point.speed and not overRideSpeed then + + if point.speed and not overRideSpeed then wp.speed = point.speed elseif type(overRideSpeed) == 'number' then wp.speed = overRideSpeed else wp.speed = mist.utils.kmphToMps(20) end - + if point.form and not overRideForm then form = point.form - else + else form = overRideForm end - + if not form then wp.action = 'Cone' else @@ -3697,7 +3719,7 @@ mist.ground.buildWP = function(point, overRideForm, overRideSpeed) wp.type = 'Turning Point' - return wp + return wp end @@ -3705,19 +3727,19 @@ mist.fixedWing.buildWP = function(point, WPtype, speed, alt, altType) local wp = {} wp.x = point.x - + if point.z then wp.y = point.z else wp.y = point.y end - + if alt and type(alt) == 'number' then wp.alt = alt else wp.alt = 2000 end - + if altType then altType = string.lower(altType) if altType == 'radio' or altType == 'agl' then @@ -3728,21 +3750,21 @@ mist.fixedWing.buildWP = function(point, WPtype, speed, alt, altType) else wp.alt_type = 'RADIO' end - - if point.speed then + + if point.speed then speed = point.speed end - + if point.type then WPtype = point.type end - + if not speed then wp.speed = mist.utils.kmphToMps(500) else wp.speed = speed end - + if not WPtype then wp.action = 'Turning Point' else @@ -3755,28 +3777,28 @@ mist.fixedWing.buildWP = function(point, WPtype, speed, alt, altType) wp.action = 'Turning Point' end end - + wp.type = 'Turning Point' - return wp + return wp end mist.heli.buildWP = function(point, WPtype, speed, alt, altType) local wp = {} wp.x = point.x - + if point.z then wp.y = point.z else wp.y = point.y end - + if alt and type(alt) == 'number' then wp.alt = alt else wp.alt = 500 end - + if altType then altType = string.lower(altType) if altType == 'radio' or altType == 'agl' then @@ -3787,21 +3809,21 @@ mist.heli.buildWP = function(point, WPtype, speed, alt, altType) else wp.alt_type = 'RADIO' end - - if point.speed then + + if point.speed then speed = point.speed end - + if point.type then WPtype = point.type end - + if not speed then wp.speed = mist.utils.kmphToMps(200) else wp.speed = speed end - + if not WPtype then wp.action = 'Turning Point' else @@ -3814,9 +3836,9 @@ mist.heli.buildWP = function(point, WPtype, speed, alt, altType) wp.action = 'Turning Point' end end - + wp.type = 'Turning Point' - return wp + return wp end @@ -3830,21 +3852,21 @@ end function mist.getRandPointInCircle(point, radius, innerRadius) local theta = 2*math.pi*math.random() local rad = math.random() + math.random() - if rad > 1 then + if rad > 1 then rad = 2 - rad end - + local radMult if innerRadius and innerRadius <= radius then radMult = (radius - innerRadius)*rad + innerRadius else radMult = radius*rad end - + if not point.z then --might as well work with vec2/3 - point.z = point.y + point.z = point.y end - + local rndCoord if radius > 0 then rndCoord = {x = math.cos(theta)*radMult + point.x, y = math.sin(theta)*radMult + point.z} @@ -3870,27 +3892,27 @@ mist.groupToRandomPoint = function(vars) local heading = vars.heading or math.random()*2*math.pi local headingDegrees = vars.headingDegrees local speed = vars.speed or mist.utils.kmphToMps(20) - - + + local useRoads if not vars.disableRoads then useRoads = true else useRoads = false end - + local path = {} - + if headingDegrees then heading = headingDegrees*math.pi/180 end - + if heading >= 2*math.pi then heading = heading - 2*math.pi end - + local rndCoord = mist.getRandPointInCircle(point, radius, innerRadius) - + local offset = {} local posStart = mist.getLeadPos(group) @@ -3898,20 +3920,20 @@ mist.groupToRandomPoint = function(vars) offset.z = mist.utils.round(math.cos(heading + (math.pi/2)) * 50 + rndCoord.y, 3) path[#path + 1] = mist.ground.buildWP(posStart, form, speed) - + if useRoads == true and ((point.x - posStart.x)^2 + (point.z - posStart.z)^2)^0.5 > radius * 1.3 then path[#path + 1] = mist.ground.buildWP({['x'] = posStart.x + 11, ['z'] = posStart.z + 11}, 'off_road', speed) path[#path + 1] = mist.ground.buildWP(posStart, 'on_road', speed) path[#path + 1] = mist.ground.buildWP(offset, 'on_road', speed) - else + else path[#path + 1] = mist.ground.buildWP({['x'] = posStart.x + 25, ['z'] = posStart.z + 25}, form, speed) end - + path[#path + 1] = mist.ground.buildWP(offset, form, speed) path[#path + 1] = mist.ground.buildWP(rndCoord, form, speed) - + mist.goRoute(group, path) - + return end @@ -3919,7 +3941,7 @@ mist.groupRandomDistSelf = function(gpData, dist, form, heading, speed) local pos = mist.getLeadPos(gpData) local fakeZone = {} fakeZone.radius = dist or math.random(300, 1000) - fakeZone.point = {x = pos.x, y, pos.y, z = pos.z} + fakeZone.point = {x = pos.x, y = pos.y, z = pos.z} mist.groupToRandomZone(gpData, fakeZone, form, heading, speed) return @@ -3929,7 +3951,7 @@ mist.groupToRandomZone = function(gpData, zone, form, heading, speed) if type(gpData) == 'string' then gpData = Group.getByName(gpData) end - + if type(zone) == 'string' then zone = trigger.misc.getZone(zone) elseif type(zone) == 'table' and not zone.radius then @@ -3939,7 +3961,7 @@ mist.groupToRandomZone = function(gpData, zone, form, heading, speed) if speed then speed = mist.utils.kmphToMps(speed) end - + local vars = {} vars.group = gpData vars.radius = zone.radius @@ -3947,39 +3969,39 @@ mist.groupToRandomZone = function(gpData, zone, form, heading, speed) vars.headingDegrees = heading vars.speed = speed vars.point = mist.utils.zoneToVec3(zone) - + mist.groupToRandomPoint(vars) return end mist.isTerrainValid = function(coord, terrainTypes) -- vec2/3 and enum or table of acceptable terrain types -if coord.z then - coord.y = coord.z -end -local typeConverted = {} - -if type(terrainTypes) == 'string' then -- if its a string it does this check -for constId, constData in pairs(land.SurfaceType) do - if string.lower(constId) == string.lower(terrainTypes) or string.lower(constData) == string.lower(terrainTypes) then - table.insert(typeConverted, constId) + if coord.z then + coord.y = coord.z end -end -elseif type(terrainTypes) == 'table' then -- if its a table it does this check -for typeId, typeData in pairs(terrainTypes) do - for constId, constData in pairs(land.SurfaceType) do - if string.lower(constId) == string.lower(typeData) or string.lower(constData) == string.lower(typeId) then - table.insert(typeConverted, constId) + local typeConverted = {} + + if type(terrainTypes) == 'string' then -- if its a string it does this check + for constId, constData in pairs(land.SurfaceType) do + if string.lower(constId) == string.lower(terrainTypes) or string.lower(constData) == string.lower(terrainTypes) then + table.insert(typeConverted, constId) + end + end + elseif type(terrainTypes) == 'table' then -- if its a table it does this check + for typeId, typeData in pairs(terrainTypes) do + for constId, constData in pairs(land.SurfaceType) do + if string.lower(constId) == string.lower(typeData) or string.lower(constData) == string.lower(typeId) then + table.insert(typeConverted, constId) + end + end end end -end -end -for validIndex, validData in pairs(typeConverted) do - if land.getSurfaceType(coord) == land.SurfaceType[validData] then - return true + for validIndex, validData in pairs(typeConverted) do + if land.getSurfaceType(coord) == land.SurfaceType[validData] then + return true + end end -end -return false + return false end mist.terrainHeightDiff = function(coord, searchSize) @@ -3991,14 +4013,14 @@ mist.terrainHeightDiff = function(coord, searchSize) if type(coord) == 'string' then coord = mist.utils.zoneToVec3(coord) end - + coord = mist.utils.makeVec2(coord) - + samples[#samples + 1] = land.getHeight(coord) for i = 0, 360, 30 do samples[#samples + 1] = land.getHeight({x = (coord.x + (math.sin(math.rad(i))*searchRadius)), y = (coord.y + (math.cos(math.rad(i))*searchRadius))}) if searchRadius >= 20 then -- if search radius is sorta large, take a sample halfway between center and outer edge - samples[#samples + 1] = land.getHeight({x = (coord.x + (math.sin(math.rad(i))*(searchRadius/2))), y = (coord.y + (math.cos(math.rad(i))*(searchRadius/2)))}) + samples[#samples + 1] = land.getHeight({x = (coord.x + (math.sin(math.rad(i))*(searchRadius/2))), y = (coord.y + (math.cos(math.rad(i))*(searchRadius/2)))}) end end local tMax, tMin = 0, 1000000 @@ -4022,7 +4044,7 @@ mist.groupToPoint = function(gpData, point, form, heading, speed, useRoads) if speed then speed = mist.utils.kmphToMps(speed) end - + local vars = {} vars.group = gpData vars.form = form @@ -4031,30 +4053,30 @@ mist.groupToPoint = function(gpData, point, form, heading, speed, useRoads) vars.disableRoads = useRoads vars.point = mist.utils.zoneToVec3(point) mist.groupToRandomPoint(vars) - + return end mist.getLeadPos = function(group) if type(group) == 'string' then -- group name - group = Group.getByName(group) + group = Group.getByName(group) end - + local units = group:getUnits() - + local leader = units[1] if not Unit.isExist(leader) then -- SHOULD be good, but if there is a bug, this code future-proofs it then. - local lowestInd = math.huge - for ind, unit in pairs(units) do - if Unit.isExist(unit) and ind < lowestInd then - lowestInd = ind - return unit:getPosition().p + local lowestInd = math.huge + for ind, unit in pairs(units) do + if Unit.isExist(unit) and ind < lowestInd then + lowestInd = ind + return unit:getPosition().p + end end end - end if leader and Unit.isExist(leader) then -- maybe a little too paranoid now... - return leader:getPosition().p + return leader:getPosition().p end end @@ -4076,37 +4098,39 @@ do local messageID = 0 local displayActive = false local displayFuncId = 0 - + local caSlots = false local caMSGtoGroup = false - - for index, value in pairs(env.mission.groundControl) do - if type(value) == 'table' then - for roleName, roleVal in pairs(value) do - for rIndex, rVal in pairs(roleVal) do - if rIndex == 'red' or rIndex == 'blue' then - if env.mission.groundControl[index][roleName][rIndex] > 0 then - caSlots = true - break + + if env.mission.groundControl then -- just to be sure? + for index, value in pairs(env.mission.groundControl) do + if type(value) == 'table' then + for roleName, roleVal in pairs(value) do + for rIndex, rVal in pairs(roleVal) do + if rIndex == 'red' or rIndex == 'blue' then + if env.mission.groundControl[index][roleName][rIndex] > 0 then + caSlots = true + break + end end end end + elseif type(value) == 'boolean' and value == true then + caSlots = true + break end - elseif type(value) == 'boolean' and value == true then - caSlots = true - break end end - + local function mistdisplayV5() - --[[thoughts to improve upon - event handler based activeClients table. - display messages only when there is an update - possibly co-routine it. + --[[thoughts to improve upon + event handler based activeClients table. + display messages only when there is an update + possibly co-routine it. ]] end - - local function mistdisplayV4() + + local function mistdisplayV4() local activeClients = {} for clientId, clientData in pairs(mist.DBs.humansById) do @@ -4114,12 +4138,12 @@ do activeClients[clientData.groupId] = clientData.groupName end end - + --[[if caSlots == true and caMSGtoGroup == true then - - end]] - + + end]] + if #messageList > 0 then if displayActive == false then displayActive = true @@ -4127,7 +4151,7 @@ do --mist.debug.writeData(mist.utils.serialize,{'msg', messageList}, 'messageList.lua') local msgTableText = {} local msgTableSound = {} - + for messageId, messageData in pairs(messageList) do if messageData.displayedFor > messageData.displayTime then messageData:remove() -- now using the remove/destroy function. @@ -4137,55 +4161,55 @@ do end local nextSound = 1000 local soundIndex = 0 - + if messageData.multSound and #messageData.multSound > 0 then for index, sData in pairs(messageData.multSound) do if sData.time <= messageData.displayedFor and sData.played == false and sData.time < nextSound then -- find index of the next sound to be played - nextSound = sData.time - soundIndex = index + nextSound = sData.time + soundIndex = index end end if soundIndex ~= 0 then messageData.multSound[soundIndex].played = true end end - + for recIndex, recData in pairs(messageData.msgFor) do -- iterate recipiants - if recData == 'RED' or recData == 'BLUE' or activeClients[recData] then -- rec exists - if messageData.text then -- text - if not msgTableText[recData] then -- create table entry for text - msgTableText[recData] = {} - msgTableText[recData].text = {} - if recData == 'RED' or recData == 'BLUE' then - msgTableText[recData].text[1] = '-------Combined Arms Message-------- \n' + if recData == 'RED' or recData == 'BLUE' or activeClients[recData] then -- rec exists + if messageData.text then -- text + if not msgTableText[recData] then -- create table entry for text + msgTableText[recData] = {} + msgTableText[recData].text = {} + if recData == 'RED' or recData == 'BLUE' then + msgTableText[recData].text[1] = '-------Combined Arms Message-------- \n' + end + msgTableText[recData].text[#msgTableText[recData].text + 1] = messageData.text + msgTableText[recData].displayTime = messageData.displayTime - messageData.displayedFor + else -- add to table entry and adjust display time if needed + if recData == 'RED' or recData == 'BLUE' then + msgTableText[recData].text[#msgTableText[recData].text + 1] = '\n ---------------- Combined Arms Message: \n' + else + msgTableText[recData].text[#msgTableText[recData].text + 1] = '\n ---------------- \n' + end + msgTableText[recData].text[#msgTableText[recData].text + 1] = messageData.text + if msgTableText[recData].displayTime < messageData.displayTime - messageData.displayedFor then + msgTableText[recData].displayTime = messageData.displayTime - messageData.displayedFor + else + msgTableText[recData].displayTime = 1 + end + end + end + if soundIndex ~= 0 then + msgTableSound[recData] = messageData.multSound[soundIndex].file + end + end end - msgTableText[recData].text[#msgTableText[recData].text + 1] = messageData.text - msgTableText[recData].displayTime = messageData.displayTime - messageData.displayedFor - else -- add to table entry and adjust display time if needed - if recData == 'RED' or recData == 'BLUE' then - msgTableText[recData].text[#msgTableText[recData].text + 1] = '\n ---------------- Combined Arms Message: \n' - else - msgTableText[recData].text[#msgTableText[recData].text + 1] = '\n ---------------- \n' - end - msgTableText[recData].text[#msgTableText[recData].text + 1] = messageData.text - if msgTableText[recData].displayTime < messageData.displayTime - messageData.displayedFor then - msgTableText[recData].displayTime = messageData.displayTime - messageData.displayedFor - else - msgTableText[recData].displayTime = 1 - end - end - end - if soundIndex ~= 0 then - msgTableSound[recData] = messageData.multSound[soundIndex].file - end - end - end - - + + end end ------- new display - + if caSlots == true and caMSGtoGroup == false then if msgTableText['RED'] then trigger.action.outTextForCoalition(coalition.side.RED, table.concat(msgTableText['RED'].text), msgTableText['RED'].displayTime, true) @@ -4193,13 +4217,12 @@ do end if msgTableText['BLUE'] then trigger.action.outTextForCoalition(coalition.side.BLUE, table.concat(msgTableText['BLUE'].text), msgTableText['BLUE'].displayTime, true) - end end - + for index, msgData in pairs(msgTableText) do if type(index) == 'number' then -- its a groupNumber - trigger.action.outTextForGroup(index, table.concat(msgData.text), msgData.displayTime, true) + trigger.action.outTextForGroup(index, table.concat(msgData.text), msgData.displayTime, true) end end --- new audio @@ -4209,20 +4232,20 @@ do if msgTableSound['BLUE'] then trigger.action.outSoundForCoalition(coalition.side.BLUE, msgTableSound['BLUE']) end - - + + for index, file in pairs(msgTableSound) do if type(index) == 'number' then -- its a groupNumber - trigger.action.outSoundForGroup(index, file) + trigger.action.outSoundForGroup(index, file) end end else mist.removeFunction(displayFuncId) - displayActive = false + displayActive = false end - + end - + local typeBase = { ['Mi-8MT'] = {'Mi-8MTV2', 'Mi-8MTV', 'Mi-8'}, ['MiG-21Bis'] = {'Mig-21'}, @@ -4230,23 +4253,23 @@ do ['FW-190D9'] = {'FW-190'}, ['Bf-109K-4'] = {'Bf-109'}, } - + --[[mist.setCAGroupMSG = function(val) - if type(val) == 'boolean' then - caMSGtoGroup = val - return true - end - return false - end]] + if type(val) == 'boolean' then + caMSGtoGroup = val + return true + end + return false + end]] mist.message = { - + add = function(vars) local function msgSpamFilter(recList, spamBlockOn) for id, name in pairs(recList) do if name == spamBlockOn then - -- env.info('already on recList') + -- env.info('already on recList') return recList end end @@ -4254,19 +4277,19 @@ do table.insert(recList, spamBlockOn) return recList end - + --[[ - local vars = {} - vars.text = 'Hello World' - vars.displayTime = 20 - vars.msgFor = {coa = {'red'}, countries = {'Ukraine', 'Georgia'}, unitTypes = {'A-10C'}} - mist.message.add(vars) - - Displays the message for all red coalition players. Players belonging to Ukraine and Georgia, and all A-10Cs on the map - - ]] - + local vars = {} + vars.text = 'Hello World' + vars.displayTime = 20 + vars.msgFor = {coa = {'red'}, countries = {'Ukraine', 'Georgia'}, unitTypes = {'A-10C'}} + mist.message.add(vars) + Displays the message for all red coalition players. Players belonging to Ukraine and Georgia, and all A-10Cs on the map + + ]] + + local new = {} new.text = vars.text -- The actual message new.displayTime = vars.displayTime -- How long will the message appear for @@ -4274,29 +4297,29 @@ do new.name = vars.name -- ID to overwrite the older message (if it exists) Basically it replaces a message that is displayed with new text. new.addedAt = timer.getTime() new.update = true - + if vars.multSound and vars.multSound[1] then new.multSound = vars.multSound - else + else new.multSound = {} end - + if vars.sound or vars.fileName then -- converts old sound file system into new multSound format - local sound = vars.sound - if vars.fileName then - sound = vars.fileName + local sound = vars.sound + if vars.fileName then + sound = vars.fileName + end + new.multSound[#new.multSound+1] = {time = 0.1, file = sound} end - new.multSound[#new.multSound+1] = {time = 0.1, file = sound} - end - + if #new.multSound > 0 then for i, data in pairs(new.multSound) do data.played = false end end - + local newMsgFor = {} -- list of all groups message displays for - for forIndex, forData in pairs(vars.msgFor) do + for forIndex, forData in pairs(vars.msgFor) do for list, listData in pairs(forData) do for clientId, clientData in pairs(mist.DBs.humansById) do forIndex = string.lower(forIndex) @@ -4304,8 +4327,8 @@ do listData = string.lower(listData) end if (forIndex == 'coa' and (listData == string.lower(clientData.coalition) or listData == 'all')) or (forIndex == 'countries' and string.lower(clientData.country) == listData) or (forIndex == 'units' and string.lower(clientData.unitName) == listData) then -- - newMsgFor = msgSpamFilter(newMsgFor, clientData.groupId) -- so units dont get the same message twice if complex rules are given - --table.insert(newMsgFor, clientId) + newMsgFor = msgSpamFilter(newMsgFor, clientData.groupId) -- so units dont get the same message twice if complex rules are given + --table.insert(newMsgFor, clientId) elseif forIndex == 'unittypes' then for typeId, typeData in pairs(listData) do local found = false @@ -4314,12 +4337,12 @@ do if mist.matchString(list, clientDataVal) == true or list == 'all' then local sString = typeData for rName, pTbl in pairs(typeBase) do -- just a quick check to see if the user may have meant something and got the specific type of the unit wrong - for pIndex, pName in pairs(pTbl) do - if mist.stringMatch(sString, pName) then - sString = rName + for pIndex, pName in pairs(pTbl) do + if mist.stringMatch(sString, pName) then + sString = rName + end end end - end if sString == clientData.type then found = true newMsgFor = msgSpamFilter(newMsgFor, clientData.groupId) -- sends info oto other function to see if client is already recieving the current message. @@ -4328,7 +4351,7 @@ do end end if found == true then -- shouldn't this be elsewhere too? - break + break end end end @@ -4339,22 +4362,20 @@ do if string.lower(forIndex) == 'coa' or string.lower(forIndex) == 'ca' then if listData == string.lower(coaData) or listData == 'all' then newMsgFor = msgSpamFilter(newMsgFor, coaData) - --table.insert(newMsgFor, coaData) - -- added redca or blueca to list end end end end - end - + end + if #newMsgFor > 0 then new.msgFor = newMsgFor -- I swear its not confusing - + else return false end - - + + if vars.name and type(vars.name) == 'string' then for i = 1, #messageList do if messageList[i].name then @@ -4372,48 +4393,48 @@ do end end end - + messageID = messageID + 1 new.messageID = messageID --mist.debug.writeData(mist.utils.serialize,{'msg', new}, 'newMsg.lua') - + messageList[#messageList + 1] = new - + local mt = { __index = mist.message} - setmetatable(new, mt) + setmetatable(new, mt) if displayActive == false then displayActive = true displayFuncId = mist.scheduleFunction(mistdisplayV4, {}, timer.getTime() + messageDisplayRate, messageDisplayRate) end - + return messageID - + end, - + remove = function(self) -- Now a self variable; the former functionality taken up by mist.message.removeById. - for i, msgData in pairs(messageList) do - if messageList[i] == self then - table.remove(messageList, i) - return true --removal successful + for i, msgData in pairs(messageList) do + if messageList[i] == self then + table.remove(messageList, i) + return true --removal successful + end end - end - return false -- removal not successful this script fails at life! + return false -- removal not successful this script fails at life! end, - + removeById = function(id) -- This function is NOT passed a self variable; it is the remove by id function. - for i, msgData in pairs(messageList) do - if messageList[i].messageID == id then - table.remove(messageList, i) - return true --removal successful + for i, msgData in pairs(messageList) do + if messageList[i].messageID == id then + table.remove(messageList, i) + return true --removal successful + end end - end - return false -- removal not successful this script fails at life! + return false -- removal not successful this script fails at life! end, - } - + } + end -- End of message system -------------------------------------------------------------------------------------------------------------------------------------------- @@ -4530,7 +4551,7 @@ mist.getLeadingPos = function(vars) if vars.headingDegrees then heading = mist.utils.toRadian(vars.headingDegrees) end - + local unitPosTbl = {} for i = 1, #units do local unit = Unit.getByName(units[i]) @@ -4539,37 +4560,37 @@ mist.getLeadingPos = function(vars) end end if #unitPosTbl > 0 then -- one more more units found. - -- first, find the unit most in the heading direction - local maxPos = -math.huge - - local maxPosInd -- maxPos - the furthest in direction defined by heading; maxPosInd = - for i = 1, #unitPosTbl do - local rotatedVec2 = mist.vec.rotateVec2(mist.utils.makeVec2(unitPosTbl[i]), heading) - if (not maxPos) or maxPos < rotatedVec2.x then - maxPos = rotatedVec2.x - maxPosInd = i - end - end - - --now, get all the units around this unit... - local avgPos - if radius then - local maxUnitPos = unitPosTbl[maxPosInd] - local avgx, avgy, avgz, totNum = 0, 0, 0, 0 + -- first, find the unit most in the heading direction + local maxPos = -math.huge + + local maxPosInd -- maxPos - the furthest in direction defined by heading; maxPosInd = for i = 1, #unitPosTbl do - if mist.utils.get2DDist(maxUnitPos, unitPosTbl[i]) <= radius then - avgx = avgx + unitPosTbl[i].x - avgy = avgy + unitPosTbl[i].y - avgz = avgz + unitPosTbl[i].z - totNum = totNum + 1 + local rotatedVec2 = mist.vec.rotateVec2(mist.utils.makeVec2(unitPosTbl[i]), heading) + if (not maxPos) or maxPos < rotatedVec2.x then + maxPos = rotatedVec2.x + maxPosInd = i end end - avgPos = { x = avgx/totNum, y = avgy/totNum, z = avgz/totNum} - else - avgPos = unitPosTbl[maxPosInd] - end - - return avgPos + + --now, get all the units around this unit... + local avgPos + if radius then + local maxUnitPos = unitPosTbl[maxPosInd] + local avgx, avgy, avgz, totNum = 0, 0, 0, 0 + for i = 1, #unitPosTbl do + if mist.utils.get2DDist(maxUnitPos, unitPosTbl[i]) <= radius then + avgx = avgx + unitPosTbl[i].x + avgy = avgy + unitPosTbl[i].y + avgz = avgz + unitPosTbl[i].z + totNum = totNum + 1 + end + end + avgPos = { x = avgx/totNum, y = avgy/totNum, z = avgz/totNum} + else + avgPos = unitPosTbl[maxPosInd] + end + + return avgPos end end @@ -4624,7 +4645,7 @@ mist.getLeadingBRString = function(vars) local ref = vars.ref local alt = vars.alt local metric = vars.metric - + local vec = {x = pos.x - ref.x, y = pos.y - ref.y, z = pos.z - ref.z} local dir = mist.utils.getDir(vec, ref) local dist = mist.utils.get2DDist(pos, ref) @@ -4636,9 +4657,9 @@ mist.getLeadingBRString = function(vars) end --[[ vars for mist.message.add - vars.text = 'Hello World' - vars.displayTime = 20 - vars.msgFor = {coa = {'red'}, countries = {'Ukraine', 'Georgia'}, unitTypes = {'A-10C'}} + vars.text = 'Hello World' + vars.displayTime = 20 + vars.msgFor = {coa = {'red'}, countries = {'Ukraine', 'Georgia'}, unitTypes = {'A-10C'}} ]] @@ -4655,14 +4676,14 @@ mist.msgMGRS = function(vars) local text = vars.text local displayTime = vars.displayTime local msgFor = vars.msgFor - + local s = mist.getMGRSString{units = units, acc = acc} local newText if text then if string.find(text, '%%s') then -- look for %s - newText = string.format(text, s) -- insert the coordinates into the message + newText = string.format(text, s) -- insert the coordinates into the message else -- else, just append to the end. - newText = text .. s + newText = text .. s end else newText = s @@ -4689,19 +4710,19 @@ mist.msgLL = function(vars) local text = vars.text local displayTime = vars.displayTime local msgFor = vars.msgFor - + local s = mist.getLLString{units = units, acc = acc, DMS = DMS} local newText if text then if string.find(text, '%%s') then -- look for %s - newText = string.format(text, s) -- insert the coordinates into the message + newText = string.format(text, s) -- insert the coordinates into the message else -- else, just append to the end. - newText = text .. s + newText = text .. s end else newText = s end - + mist.message.add{ text = newText, displayTime = displayTime, @@ -4728,19 +4749,19 @@ mist.msgBR = function(vars) local text = vars.text local displayTime = vars.displayTime local msgFor = vars.msgFor - + local s = mist.getBRString{units = units, ref = ref, alt = alt, metric = metric} local newText if text then if string.find(text, '%%s') then -- look for %s - newText = string.format(text, s) -- insert the coordinates into the message + newText = string.format(text, s) -- insert the coordinates into the message else -- else, just append to the end. - newText = text .. s + newText = text .. s end else newText = s end - + mist.message.add{ text = newText, displayTime = displayTime, @@ -4804,26 +4825,26 @@ vars.msgFor - scope ]] mist.msgLeadingMGRS = function(vars) local units = vars.units -- technically, I don't really need to do this, but it helps readability. - local heading = vars.heading + local heading = vars.heading local radius = vars.radius local headingDegrees = vars.headingDegrees local acc = vars.acc local text = vars.text local displayTime = vars.displayTime local msgFor = vars.msgFor - + local s = mist.getLeadingMGRSString{units = units, heading = heading, radius = radius, headingDegrees = headingDegrees, acc = acc} local newText if text then if string.find(text, '%%s') then -- look for %s - newText = string.format(text, s) -- insert the coordinates into the message + newText = string.format(text, s) -- insert the coordinates into the message else -- else, just append to the end. - newText = text .. s + newText = text .. s end else newText = s end - + mist.message.add{ text = newText, displayTime = displayTime, @@ -4845,7 +4866,7 @@ vars.msgFor - scope ]] mist.msgLeadingLL = function(vars) local units = vars.units -- technically, I don't really need to do this, but it helps readability. - local heading = vars.heading + local heading = vars.heading local radius = vars.radius local headingDegrees = vars.headingDegrees local acc = vars.acc @@ -4853,20 +4874,20 @@ mist.msgLeadingLL = function(vars) local text = vars.text local displayTime = vars.displayTime local msgFor = vars.msgFor - + local s = mist.getLeadingLLString{units = units, heading = heading, radius = radius, headingDegrees = headingDegrees, acc = acc, DMS = DMS} local newText - + if text then if string.find(text, '%%s') then -- look for %s - newText = string.format(text, s) -- insert the coordinates into the message + newText = string.format(text, s) -- insert the coordinates into the message else -- else, just append to the end. - newText = text .. s + newText = text .. s end else newText = s end - + mist.message.add{ text = newText, displayTime = displayTime, @@ -4889,7 +4910,7 @@ vars.msgFor - scope ]] mist.msgLeadingBR = function(vars) local units = vars.units -- technically, I don't really need to do this, but it helps readability. - local heading = vars.heading + local heading = vars.heading local radius = vars.radius local headingDegrees = vars.headingDegrees local metric = vars.metric @@ -4898,20 +4919,20 @@ mist.msgLeadingBR = function(vars) local text = vars.text local displayTime = vars.displayTime local msgFor = vars.msgFor - + local s = mist.getLeadingBRString{units = units, heading = heading, radius = radius, headingDegrees = headingDegrees, metric = metric, alt = alt, ref = ref} local newText - + if text then if string.find(text, '%%s') then -- look for %s - newText = string.format(text, s) -- insert the coordinates into the message + newText = string.format(text, s) -- insert the coordinates into the message else -- else, just append to the end. - newText = text .. s + newText = text .. s end else newText = s end - + mist.message.add{ text = newText, displayTime = displayTime, @@ -4927,11 +4948,11 @@ end -- start of sct Merge do -- all function uses of group and unit Ids must be in this do statement - - + + mist.groupTableCheck = function(groupData) local isOk = false - + if groupData.country then isOk = true end @@ -4949,13 +4970,13 @@ mist.groupTableCheck = function(groupData) else isOk = false end - + return isOk -end +end mist.getCurrentGroupData = function(gpName) local dbData = mist.getGroupData(gpName) - + if Group.getByName(gpName) and Group.getByName(gpName):isExist() == true then local newGroup = Group.getByName(gpName) local newData = {} @@ -4964,7 +4985,7 @@ mist.getCurrentGroupData = function(gpName) newData.category = newGroup:getCategory() newData.groupName = gpName newData.hidden = dbData.hidden - + if newData.category == 2 then newData.category = 'vehicle' elseif newData.category == 3 then @@ -4981,7 +5002,7 @@ mist.getCurrentGroupData = function(gpName) newData.units[unitNum]['y'] = unitData:getPosition().p.z newData.units[unitNum]["type"] = unitData:getTypeName() newData.units[unitNum]["skill"] = mist.getUnitSkill(unitData:getName()) - + -- get velocity needed newData.units[unitNum]["unitName"] = unitData:getName() newData.units[unitNum]["heading"] = mist.getHeading(unitData, true) -- added to DBs @@ -4997,7 +5018,7 @@ mist.getCurrentGroupData = function(gpName) dbData.units[1].y = staticObj:getPosition().p.z dbData.units[1].alt = staticObj:getPosition().p.y dbData.units[1].heading = mist.getHeading(staticObj, true) - + return dbData end @@ -5009,8 +5030,8 @@ mist.getGroupData = function(gpName) if mist.DBs.groupsByName[gpName] then newData = mist.utils.deepCopy(mist.DBs.groupsByName[gpName]) found = true - end - + end + if found == false then for groupName, groupData in pairs(mist.DBs.groupsByName) do if mist.stringMatch(groupName, gpName) == true then @@ -5021,7 +5042,7 @@ mist.getGroupData = function(gpName) end end end - + local payloads if newData.category == 'plane' or newData.category == 'helicopter' then payloads = mist.getGroupPayload(newData.groupName) @@ -5031,7 +5052,7 @@ mist.getGroupData = function(gpName) for unitNum, unitData in pairs(newData.units) do newData.units[unitNum] = {} - + newData.units[unitNum]["unitId"] = unitData.unitId --newData.units[unitNum]['point'] = unitData.point newData.units[unitNum]['x'] = unitData.point.x @@ -5044,8 +5065,8 @@ mist.getGroupData = function(gpName) newData.units[unitNum]["unitName"] = unitData.unitName newData.units[unitNum]["heading"] = unitData.heading -- added to DBs newData.units[unitNum]["playerCanDrive"] = unitData.playerCanDrive -- added to DBs - - + + if newData.category == 'plane' or newData.category == 'helicopter' then newData.units[unitNum]["payload"] = payloads[unitNum] newData.units[unitNum]['livery_id'] = unitData.livery_id @@ -5060,8 +5081,8 @@ mist.getGroupData = function(gpName) newData.units[unitNum]['shape_name'] = unitData.shape_name end end - - return newData + + return newData else env.info(gpName .. ' not found in mist.getGroupData') return @@ -5069,35 +5090,35 @@ mist.getGroupData = function(gpName) end mist.getPayload = function(unitIdent) - -- refactor to search by groupId and allow groupId and groupName as inputs + -- refactor to search by groupId and allow groupId and groupName as inputs local unitId = unitIdent if type(unitIdent) == 'string' and not tonumber(unitIdent) then unitId = mist.DBs.MEunitsByName[unitIdent].unitId end local gpId = mist.DBs.MEunitsById[unitId].groupId - + if gpId and unitId then 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_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 == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" then -- only these types have points - 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 - if group_data and group_data.groupId == gpId then - for unitIndex, unitData in pairs(group_data.units) do --group index - if unitData.unitId == unitId then - return unitData.payload - end + 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 == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" then -- only these types have points + 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 + if group_data and group_data.groupId == gpId then + for unitIndex, unitData in pairs(group_data.units) do --group index + if unitData.unitId == unitId then + return unitData.payload + end + end + end + end end end end - end - end end end - end end end else @@ -5105,7 +5126,7 @@ mist.getPayload = function(unitIdent) return false end env.info('mist.getPayload, payload not found') - return + return end mist.getGroupPayload = function(groupIdent) @@ -5113,29 +5134,29 @@ mist.getGroupPayload = function(groupIdent) if type(groupIdent) == 'string' and not tonumber(groupIdent) then gpId = mist.DBs.MEgroupsByName[groupIdent].groupId end - + if gpId then 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_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 == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" then -- only these types have points - 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 - if group_data and group_data.groupId == gpId then - local payloads = {} - for unitIndex, unitData in pairs(group_data.units) do --group index - payloads[unitIndex] = unitData.payload + 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 == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" then -- only these types have points + 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 + if group_data and group_data.groupId == gpId then + local payloads = {} + for unitIndex, unitData in pairs(group_data.units) do --group index + payloads[unitIndex] = unitData.payload + end + return payloads + end + end end - return payloads end end - end - end end end - end end end else @@ -5143,145 +5164,144 @@ mist.getGroupPayload = function(groupIdent) return false end env.info('mist.getGroupPayload, payload not found') - return + return end mist.teleportToPoint = function(vars) -- main teleport function that all of teleport/respawn functions call -local point = vars.point - -local gpName -if vars.gpName then - gpName = vars.gpName -elseif vars.groupName then - gpName = vars.groupName -else - env.info('teleportToPoint missing either vars.groupName or vars.gpName') -end - -local action = vars.action - -local disperse = vars.disperse or false -local maxDisp = vars.maxDisp -if not vars.maxDisp then - maxDisp = 200 -else - maxDisp = vars.maxDisp -end -local radius = vars.radius or 0 -local innerRadius = vars.innerRadius - -local route = vars.route -local dbData = false - -local newGroupData -if gpName and not vars.groupData then - if string.lower(action) == 'teleport' or string.lower(action) == 'tele' then - newGroupData = mist.getCurrentGroupData(gpName) - elseif string.lower(action) == 'respawn' then - newGroupData = mist.getGroupData(gpName) - dbData = true - elseif string.lower(action) == 'clone' then - newGroupData = mist.getGroupData(gpName) - newGroupData.clone = 'order66' - dbData = true + local point = vars.point + + local gpName + if vars.gpName then + gpName = vars.gpName + elseif vars.groupName then + gpName = vars.groupName + else + env.info('teleportToPoint missing either vars.groupName or vars.gpName') + end + + local action = vars.action + + local disperse = vars.disperse or false + local maxDisp = vars.maxDisp + if not vars.maxDisp then + maxDisp = 200 + else + maxDisp = vars.maxDisp + end + local radius = vars.radius or 0 + local innerRadius = vars.innerRadius + + local route = vars.route + local dbData = false + + local newGroupData + if gpName and not vars.groupData then + if string.lower(action) == 'teleport' or string.lower(action) == 'tele' then + newGroupData = mist.getCurrentGroupData(gpName) + elseif string.lower(action) == 'respawn' then + newGroupData = mist.getGroupData(gpName) + dbData = true + elseif string.lower(action) == 'clone' then + newGroupData = mist.getGroupData(gpName) + newGroupData.clone = 'order66' + dbData = true + else + action = 'tele' + newGroupData = mist.getCurrentGroupData(gpName) + end else action = 'tele' - newGroupData = mist.getCurrentGroupData(gpName) - end -else - action = 'tele' - newGroupData = vars.groupData -end - -local diff = {['x'] = 0, ['y'] = 0} -local newCoord, origCoord -if point then - local valid = false - - local validTerrain - if string.lower(newGroupData.category) == 'ship' then - validTerrain = {'SHALLOW_WATER' , 'WATER'} - elseif string.lower(newGroupData.category) == 'vehicle' then - validTerrain = {'LAND', 'ROAD'} - else - validTerrain = {'LAND', 'ROAD', 'SHALLOW_WATER', 'WATER', 'RUNWAY'} + newGroupData = vars.groupData end - for i = 1, 100 do - newCoord = mist.getRandPointInCircle(point, radius, innerRadius) - if mist.isTerrainValid(newCoord, validTerrain) then - origCoord = mist.utils.deepCopy(newCoord) - diff = {['x'] = (newCoord.x - newGroupData.units[1].x), ['y'] = (newCoord.y - newGroupData.units[1].y)} - valid = true - break - end - end - if valid == false then - env.info('mist.teleportToPoint; vars.point not a valid coordinate') - return false - end -end -if not newGroupData.country and mist.DBs.groupsByName[newGroupData.groupName].country then - newGroupData.country = mist.DBs.groupsByName[newGroupData.groupName].country -end -if not newGroupData.category and mist.DBs.groupsByName[newGroupData.groupName].category then - newGroupData.category = mist.DBs.groupsByName[newGroupData.groupName].category -end - -for unitNum, unitData in pairs(newGroupData.units) do - if disperse then - if maxDisp and type(maxDisp) == 'number' and unitNum ~= 1 then - newCoord = mist.getRandPointInCircle(origCoord, maxDisp) - --else - --newCoord = mist.getRandPointInCircle(zone.point, zone.radius) - end - - newGroupData.units[unitNum]['x'] = newCoord.x - newGroupData.units[unitNum]['y'] = newCoord.y - else - newGroupData.units[unitNum]["x"] = unitData.x + diff.x - newGroupData.units[unitNum]["y"] = unitData.y + diff.y - end + local diff = {['x'] = 0, ['y'] = 0} + local newCoord, origCoord if point then - if (newGroupData.category == 'plane' or newGroupData.category == 'helicopter') then - if point.z and point.y > 0 and point.y > land.getHeight({newGroupData.units[unitNum]["x"], newGroupData.units[unitNum]["y"]}) + 10 then - newGroupData.units[unitNum]["alt"] = point.y - else - if newGroupData.category == 'plane' then - newGroupData.units[unitNum]["alt"] = land.getHeight({newGroupData.units[unitNum]["x"], newGroupData.units[unitNum]["y"]}) + math.random(300, 9000) + local valid = false + + local validTerrain + if string.lower(newGroupData.category) == 'ship' then + validTerrain = {'SHALLOW_WATER' , 'WATER'} + elseif string.lower(newGroupData.category) == 'vehicle' then + validTerrain = {'LAND', 'ROAD'} + else + validTerrain = {'LAND', 'ROAD', 'SHALLOW_WATER', 'WATER', 'RUNWAY'} + end + + for i = 1, 100 do + newCoord = mist.getRandPointInCircle(point, radius, innerRadius) + if mist.isTerrainValid(newCoord, validTerrain) then + origCoord = mist.utils.deepCopy(newCoord) + diff = {['x'] = (newCoord.x - newGroupData.units[1].x), ['y'] = (newCoord.y - newGroupData.units[1].y)} + valid = true + break + end + end + if valid == false then + env.info('mist.teleportToPoint; vars.point not a valid coordinate') + return false + end + end + if not newGroupData.country and mist.DBs.groupsByName[newGroupData.groupName].country then + newGroupData.country = mist.DBs.groupsByName[newGroupData.groupName].country + end + if not newGroupData.category and mist.DBs.groupsByName[newGroupData.groupName].category then + newGroupData.category = mist.DBs.groupsByName[newGroupData.groupName].category + end + + for unitNum, unitData in pairs(newGroupData.units) do + if disperse then + if maxDisp and type(maxDisp) == 'number' and unitNum ~= 1 then + newCoord = mist.getRandPointInCircle(origCoord, maxDisp) + --else + --newCoord = mist.getRandPointInCircle(zone.point, zone.radius) + end + + newGroupData.units[unitNum]['x'] = newCoord.x + newGroupData.units[unitNum]['y'] = newCoord.y + else + newGroupData.units[unitNum]["x"] = unitData.x + diff.x + newGroupData.units[unitNum]["y"] = unitData.y + diff.y + end + if point then + if (newGroupData.category == 'plane' or newGroupData.category == 'helicopter') then + if point.z and point.y > 0 and point.y > land.getHeight({newGroupData.units[unitNum]["x"], newGroupData.units[unitNum]["y"]}) + 10 then + newGroupData.units[unitNum]["alt"] = point.y else - newGroupData.units[unitNum]["alt"] = land.getHeight({newGroupData.units[unitNum]["x"], newGroupData.units[unitNum]["y"]}) + math.random(200, 3000) + if newGroupData.category == 'plane' then + newGroupData.units[unitNum]["alt"] = land.getHeight({newGroupData.units[unitNum]["x"], newGroupData.units[unitNum]["y"]}) + math.random(300, 9000) + else + newGroupData.units[unitNum]["alt"] = land.getHeight({newGroupData.units[unitNum]["x"], newGroupData.units[unitNum]["y"]}) + math.random(200, 3000) + end end end end end -end - -if newGroupData.start_time then - newGroupData.startTime = newGroupData.start_time -end - -if newGroupData.startTime and newGroupData.startTime ~= 0 and dbData == true then - local timeDif = timer.getAbsTime() - timer.getTime0() - if timeDif > newGroupData.startTime then - newGroupData.startTime = 0 - else - newGroupData.startTime = newGroupData.startTime - timeDif + + if newGroupData.start_time then + newGroupData.startTime = newGroupData.start_time + end + + if newGroupData.startTime and newGroupData.startTime ~= 0 and dbData == true then + local timeDif = timer.getAbsTime() - timer.getTime0() + if timeDif > newGroupData.startTime then + newGroupData.startTime = 0 + else + newGroupData.startTime = newGroupData.startTime - timeDif + end + end -end - -if route then - newGroupData.route = route -end ---mist.debug.writeData(mist.utils.serialize,{'teleportToPoint', newGroupData}, 'newGroupData.lua') -if string.lower(newGroupData.category) == 'static' then - return mist.dynAddStatic(newGroupData) -end - -return mist.dynAdd(newGroupData) - + if route then + newGroupData.route = route + end + --mist.debug.writeData(mist.utils.serialize,{'teleportToPoint', newGroupData}, 'newGroupData.lua') + if string.lower(newGroupData.category) == 'static' then + return mist.dynAddStatic(newGroupData) + end + return mist.dynAdd(newGroupData) + end mist.respawnInZone = function(gpName, zone, disperse, maxDisp) @@ -5293,7 +5313,7 @@ mist.respawnInZone = function(gpName, zone, disperse, maxDisp) else gpName = tostring(gpName) end - + if type(zone) == 'string' then zone = trigger.misc.getZone(zone) elseif type(zone) == 'table' and not zone.radius then @@ -5310,13 +5330,13 @@ mist.respawnInZone = function(gpName, zone, disperse, maxDisp) end mist.cloneInZone = function(gpName, zone, disperse, maxDisp) - + if type(gpName) == 'table' then gpName = gpName:getName() else gpName = tostring(gpName) end - + if type(zone) == 'string' then zone = trigger.misc.getZone(zone) elseif type(zone) == 'table' and not zone.radius then @@ -5333,26 +5353,26 @@ mist.cloneInZone = function(gpName, zone, disperse, maxDisp) end mist.teleportInZone = function(gpName, zone, disperse, maxDisp) -- groupName, zoneName or table of Zone Names, keepForm is a boolean -if type(gpName) == 'table' and gpName:getName() then - gpName = gpName:getName() -else - gpName = tostring(gpName) -end - -if type(zone) == 'string' then - zone = trigger.misc.getZone(zone) -elseif type(zone) == 'table' and not zone.radius then - zone = trigger.misc.getZone(zone[math.random(1, #zone)]) -end - -local vars = {} -vars.gpName = gpName -vars.action = 'tele' -vars.point = zone.point -vars.radius = zone.radius -vars.disperse = disperse -vars.maxDisp = maxDisp -return mist.teleportToPoint(vars) + if type(gpName) == 'table' and gpName:getName() then + gpName = gpName:getName() + else + gpName = tostring(gpName) + end + + if type(zone) == 'string' then + zone = trigger.misc.getZone(zone) + elseif type(zone) == 'table' and not zone.radius then + zone = trigger.misc.getZone(zone[math.random(1, #zone)]) + end + + local vars = {} + vars.gpName = gpName + vars.action = 'tele' + vars.point = zone.point + vars.radius = zone.radius + vars.disperse = disperse + vars.maxDisp = maxDisp + return mist.teleportToPoint(vars) end mist.respawnGroup = function(gpName, task) @@ -5391,7 +5411,7 @@ mist.teleportGroup = function(gpName, task) vars.action = 'teleport' if task and type(task) ~= 'number' then vars.route = mist.getGroupRoute(gpName, 'task') - end + end local newGroup = mist.teleportToPoint(vars) if task and type(task) == 'number' then local newRoute = mist.getGroupRoute(gpName, 'task') @@ -5401,41 +5421,41 @@ mist.teleportGroup = function(gpName, task) end mist.spawnRandomizedGroup = function(groupName, vars) -- need to debug -if Group.getByName(groupName) and Group.getByName(groupName):isExist() == true then - local gpData = mist.getGroupData(groupName) - gpData.units = mist.randomizeGroupOrder(gpData.units, vars) - gpData.route = mist.getGroupRoute(groupName, 'task') - - mist.dynAdd(gpData) + if Group.getByName(groupName) and Group.getByName(groupName):isExist() == true then + local gpData = mist.getGroupData(groupName) + gpData.units = mist.randomizeGroupOrder(gpData.units, vars) + gpData.route = mist.getGroupRoute(groupName, 'task') + + mist.dynAdd(gpData) + end + + return true end - -return true -end - + mist.randomizeNumTable = function(vars) local newTable = {} - + local excludeIndex = {} local randomTable = {} - + if vars and vars.exclude and type(vars.exclude) == 'table' then for index, data in pairs(vars.exclude) do excludeIndex[data] = true - end + end end - + local low, hi, size - + if vars.size then size = vars.size end - + if vars and vars.lowerLimit and type(vars.lowerLimit) == 'number' then low = mist.utils.round(vars.lowerLimit) else low = 1 end - + if vars and vars.upperLimit and type(vars.upperLimit) == 'number' then hi = mist.utils.round(vars.upperLimit) else @@ -5451,7 +5471,7 @@ mist.randomizeNumTable = function(vars) end if not excludeIndex[i] then table.insert(choices, i) - else + else newTable[i] = i end end @@ -5473,68 +5493,68 @@ mist.randomizeNumTable = function(vars) found = true end excludeIndex[x] = true - + end newTable[num] = x end --[[ - for i = 1, #newTable do - env.info(newTable[i]) - end - ]] + for i = 1, #newTable do + env.info(newTable[i]) + end + ]] return newTable end -mist.randomizeGroupOrder = function(passedUnits, vars) +mist.randomizeGroupOrder = function(passedUnits, vars) -- figure out what to exclude, and send data to other func local units = passedUnits - + if passedUnits.units then units = passUnits.units end - + local exclude = {} local excludeNum = {} if vars and vars.excludeType and type(vars.excludeType) == 'table' then - exclude = vars.excludeType + exclude = vars.excludeType end - + if vars and vars.excludeNum and type(vars.excludeNum) == 'table' then - excludeNum = vars.excludeNum + excludeNum = vars.excludeNum end - + local low, hi - + if vars and vars.lowerLimit and type(vars.lowerLimit) == 'number' then low = mist.utils.round(vars.lowerLimit) else low = 1 end - + if vars and vars.upperLimit and type(vars.upperLimit) == 'number' then hi = mist.utils.round(vars.upperLimit) else hi = #units end - + local excludeNum = {} for unitIndex, unitData in pairs(units) do if unitIndex >= low and unitIndex <= hi then -- if within range - local found = false - if #exclude > 0 then - for excludeType, index in pairs(exclude) do -- check if excluded - if mist.stringMatch(excludeType, unitData.type) then -- if excluded - excludeNum[unitIndex] = unitIndex - found = true + local found = false + if #exclude > 0 then + for excludeType, index in pairs(exclude) do -- check if excluded + if mist.stringMatch(excludeType, unitData.type) then -- if excluded + excludeNum[unitIndex] = unitIndex + found = true + end + end end - end - end else -- unitIndex is either to low, or to high: added to exclude list - excludeNum[unitIndex] = unitId + excludeNum[unitIndex] = unitId end - end - + end + local newGroup = {} local newOrder = mist.randomizeNumTable({exclude = excludeNum, size = #units}) @@ -5548,21 +5568,21 @@ mist.randomizeGroupOrder = function(passedUnits, vars) newGroup[i].unitIndex = mist.utils.deepCopy(unitData.unitIndex) -- replaces the units data with a new type end end - end + end return newGroup -end +end mist.ground.patrolRoute = function(vars) - - + + local tempRoute = {} local useRoute = {} local gpData = vars.gpData if type(gpData) == 'string' then gpData = Group.getByName(gpData) end - - local useGroupRoute + + local useGroupRoute if not vars.useGroupRoute then useGroupRoute = vars.gpData else @@ -5579,22 +5599,22 @@ mist.ground.patrolRoute = function(vars) useRoute[1] = mist.ground.buildWP(posStart, useRoute[1].action, useRoute[1].speed) routeProvided = true end - - + + local overRideSpeed = vars.speed or 'default' - local pType = vars.pType + local pType = vars.pType local offRoadForm = vars.offRoadForm or 'default' local onRoadForm = vars.onRoadForm or 'default' - + if routeProvided == false and #tempRoute > 0 then local posStart = mist.getLeadPos(gpData) - - + + useRoute[#useRoute + 1] = mist.ground.buildWP(posStart, offRoadForm, overRideSpeed) for i = 1, #tempRoute do local tempForm = tempRoute[i].action local tempSpeed = tempRoute[i].speed - + if offRoadForm == 'default' then tempForm = tempRoute[i].action end @@ -5606,25 +5626,25 @@ mist.ground.patrolRoute = function(vars) else tempForm = offRoadForm end - + if type(overRideSpeed) == 'number' then tempSpeed = overRideSpeed end - - + + useRoute[#useRoute + 1] = mist.ground.buildWP(tempRoute[i], tempForm, tempSpeed) end - + if pType and string.lower(pType) == 'doubleback' then local curRoute = mist.utils.deepCopy(useRoute) for i = #curRoute, 2, -1 do useRoute[#useRoute + 1] = mist.ground.buildWP(curRoute[i], curRoute[i].action, curRoute[i].speed) end end - + useRoute[1].action = useRoute[#useRoute].action -- make it so the first WP matches the last WP end - + local cTask3 = {} local newPatrol = {} newPatrol.route = useRoute @@ -5634,38 +5654,38 @@ mist.ground.patrolRoute = function(vars) cTask3[#cTask3 + 1] = ')' cTask3 = table.concat(cTask3) local tempTask = { - id = 'WrappedAction', - params = { + id = 'WrappedAction', + params = { action = { id = 'Script', params = { - command = cTask3, - + command = cTask3, + }, }, }, } - + useRoute[#useRoute].task = tempTask mist.goRoute(gpData, useRoute) - + return end mist.ground.patrol = function(gpData, pType, form, speed) local vars = {} - + if type(gpData) == 'table' and gpData:getName() then gpData = gpData:getName() end - + vars.useGroupRoute = gpData vars.gpData = gpData vars.pType = pType vars.offRoadForm = form vars.speed = speed - + mist.ground.patrolRoute(vars) return @@ -5673,29 +5693,29 @@ end mist.random = function(firstNum, secondNum) -- no support for decimals -local lowNum, highNum -if not secondNum then - highNum = firstNum - lowNum = 1 -else - lowNum = firstNum - highNum = secondNum -end -local total = 1 -if math.abs(highNum - lowNum + 1) < 50 then -- if total values is less than 50 -total = math.modf(50/math.abs(highNum - lowNum + 1)) -- make x copies required to be above 50 -end -local choices = {} -for i = 1, total do -- iterate required number of times -for x = lowNum, highNum do -- iterate between the range -choices[#choices +1] = x -- add each entry to a table -end -end -local rtnVal = math.random(#choices) -- will now do a math.random of at least 50 choices -for i = 1, 10 do - rtnVal = math.random(#choices) -- iterate a few times for giggles -end -return choices[rtnVal] + local lowNum, highNum + if not secondNum then + highNum = firstNum + lowNum = 1 + else + lowNum = firstNum + highNum = secondNum + end + local total = 1 + if math.abs(highNum - lowNum + 1) < 50 then -- if total values is less than 50 + total = math.modf(50/math.abs(highNum - lowNum + 1)) -- make x copies required to be above 50 + end + local choices = {} + for i = 1, total do -- iterate required number of times + for x = lowNum, highNum do -- iterate between the range + choices[#choices +1] = x -- add each entry to a table + end + end + local rtnVal = math.random(#choices) -- will now do a math.random of at least 50 choices + for i = 1, 10 do + rtnVal = math.random(#choices) -- iterate a few times for giggles + end + return choices[rtnVal] end @@ -5711,7 +5731,7 @@ mist.stringMatch = function(s1, s2, bool) s1 = string.lower(s1) s2 = string.lower(s2) end - + if s1 == s2 then return true else @@ -5731,7 +5751,7 @@ mist.time = {} -- if present current time in mil time is returned -- if number or table the time is converted into mil tim mist.time.convertToSec = function(timeTable) - + timeInSec = 0 if timeTable and type(timeTable) == 'number' then timeInSec = timeTable @@ -5748,7 +5768,7 @@ mist.time.convertToSec = function(timeTable) if timeTable.s and type(timeTable.s) == 'number' then timeInSec = timeInSec + timeTable.s end - + end return timeInSec end @@ -5756,29 +5776,29 @@ end mist.time.getDHMS = function(timeInSec) if timeInSec and type(timeInSec) == 'number' then local tbl = {d = 0, h = 0, m = 0, s = 0} - if timeInSec > 86400 then - while timeInSec > 86400 do - tbl.d = tbl.d + 1 - timeInSec = timeInSec - 86400 + if timeInSec > 86400 then + while timeInSec > 86400 do + tbl.d = tbl.d + 1 + timeInSec = timeInSec - 86400 + end end - end - if timeInSec > 3600 then - while timeInSec > 3600 do - tbl.h = tbl.h + 1 - timeInSec = timeInSec - 3600 + if timeInSec > 3600 then + while timeInSec > 3600 do + tbl.h = tbl.h + 1 + timeInSec = timeInSec - 3600 + end end - end - if timeInSec > 60 then - while timeInSec > 60 do - tbl.m = tbl.m + 1 - timeInSec = timeInSec - 60 + if timeInSec > 60 then + while timeInSec > 60 do + tbl.m = tbl.m + 1 + timeInSec = timeInSec - 60 + end end - end - tbl.s = timeInSec + tbl.s = timeInSec return tbl else env.info('mist.time.getDHMS didnt recieve number') - return + return end end @@ -5789,9 +5809,9 @@ mist.getMilString = function(theTime) else timeInSec = mist.utils.round(timer.getAbsTime(), 0) end - + local DHMS = mist.time.getDHMS(timeInSec) - + return tostring(string.format('%02d', DHMS.h) .. string.format('%02d',DHMS.m)) end @@ -5807,7 +5827,7 @@ mist.getClockString = function(theTime, hour) if DHMS.h > 12 then DHMS.h = DHMS.h - 12 return tostring(string.format('%02d', DHMS.h) .. ':' .. string.format('%02d',DHMS.m) .. ':' .. string.format('%02d',DHMS.s) .. ' PM') - else + else return tostring(string.format('%02d', DHMS.h) .. ':' .. string.format('%02d',DHMS.m) .. ':' .. string.format('%02d',DHMS.s) .. ' AM') end else @@ -5831,12 +5851,12 @@ mist.time.getDate = function(convert) if convert and type(convert) == 'number' then timeInSec = convert end - + while start < timeInSec do - + if date.d == cal[date.m] then --if y % 4 >= 0 and i == 2 then -- for leap year. DCS doesnt do leapyear, but I am keeping the code dormant because maybe with WW2 the mission year may become relevant - + --else date.m = date.m + 1 date.d = 0 @@ -5859,76 +5879,76 @@ mist.time.relativeToStart = function(time) end mist.getDateString = function(rtnType, murica, oTime) -- returns date based on time -local word = {'January', 'Feburary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' } -- 'etc -local curTime = 0 -if oTime then - curTime = oTime -else - curTime = mist.utils.round(timer.getAbsTime()) -end -local tbl = mist.time.getDate(curTime) - -if rtnType then - if murica then - return tostring(word[tbl.m] .. ' ' .. tbl.d .. ' ' .. tbl.y) - else - return tostring(tbl.d .. ' ' .. word[tbl.m] .. ' ' .. tbl.y) + local word = {'January', 'Feburary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' } -- 'etc + local curTime = 0 + if oTime then + curTime = oTime + else + curTime = mist.utils.round(timer.getAbsTime()) end -else - if murica then - return tostring(tbl.m .. '.' .. tbl.d .. '.' .. tbl.y) + local tbl = mist.time.getDate(curTime) + + if rtnType then + if murica then + return tostring(word[tbl.m] .. ' ' .. tbl.d .. ' ' .. tbl.y) + else + return tostring(tbl.d .. ' ' .. word[tbl.m] .. ' ' .. tbl.y) + end else - return tostring(tbl.d .. '.' .. tbl.m .. '.' .. tbl.y) + if murica then + return tostring(tbl.m .. '.' .. tbl.d .. '.' .. tbl.y) + else + return tostring(tbl.d .. '.' .. tbl.m .. '.' .. tbl.y) + end end end -end --WIP mist.time.milToGame = function(milString, rtnType) --converts a military time. By default returns the abosolute time that event would occur. With optional value it returns how many seconds from time of call till that time. -local curTime = mist.utils.round(timer.getAbsTime()) -local milTimeInSec = 0 + local curTime = mist.utils.round(timer.getAbsTime()) + local milTimeInSec = 0 -if milString and type(milString) == 'string' and string.len(milString) >= 4 then - local hr = tonumber(string.sub(milString, 1, 2)) - local mi = tonumber(string.sub(milString, 3)) - milTimeInSec = milTimeInSec + (mi*60) + (hr*3600) -elseif milString and type(milString) == 'table' and (milString.d or milString.h or milString.m or milString.s) then - milTimeInSec = mist.time.convertToSec(milString) -end - -local startTime = timer.getTime0() -local daysOffset = 0 -if startTime > 86400 then - daysOffset = mist.utils.round(startTime/86400) - if daysOffset > 0 then - milTimeInSec = milTimeInSec *daysOffset + if milString and type(milString) == 'string' and string.len(milString) >= 4 then + local hr = tonumber(string.sub(milString, 1, 2)) + local mi = tonumber(string.sub(milString, 3)) + milTimeInSec = milTimeInSec + (mi*60) + (hr*3600) + elseif milString and type(milString) == 'table' and (milString.d or milString.h or milString.m or milString.s) then + milTimeInSec = mist.time.convertToSec(milString) end -end - -if curTime > milTimeInSec then - milTimeInSec = milTimeInSec + 86400 -end -if rtnType then - milTimeInSec = milTimeInSec - startTime -end -return milTimeInSec + + local startTime = timer.getTime0() + local daysOffset = 0 + if startTime > 86400 then + daysOffset = mist.utils.round(startTime/86400) + if daysOffset > 0 then + milTimeInSec = milTimeInSec *daysOffset + end + end + + if curTime > milTimeInSec then + milTimeInSec = milTimeInSec + 86400 + end + if rtnType then + milTimeInSec = milTimeInSec - startTime + end + return milTimeInSec end mist.DBs.const = {} --[[ - ['LAND'] = 1, - ['SHALLOW_WATER'] = 2, - ['WATER'] = 3, - ['ROAD'] = 4, - ['RUNWAY'] = 5 + ['LAND'] = 1, + ['SHALLOW_WATER'] = 2, + ['WATER'] = 3, + ['ROAD'] = 4, + ['RUNWAY'] = 5 ]] --[[mist.DBs.const.ME_SSE_terms = { - ['ME'] = { - ['vehicle'] = {'GROUND', 'GROUND_UNIT'}, - ['plane'] = {'AIRPLANE'}, - }, - ['SSE'] = { - }, + ['ME'] = { + ['vehicle'] = {'GROUND', 'GROUND_UNIT'}, + ['plane'] = {'AIRPLANE'}, + }, + ['SSE'] = { + }, }]] @@ -5942,8 +5962,8 @@ mist.DBs.const.callsigns = { -- not accessible by SSE, must use static list :-/ ['Overlord'] = 1, ['Magic'] = 2, ['Wizard'] = 3, - ['Focus'] = 4, - ['Darkstar'] = 5, + ['Focus'] = 4, + ['Darkstar'] = 5, }, ['TANKER'] = { ['Texaco'] = 1, @@ -5953,8 +5973,8 @@ mist.DBs.const.callsigns = { -- not accessible by SSE, must use static list :-/ ['JTAC'] = { ['Axeman'] = 1, ['Darknight'] = 2, - ['Warrior'] = 3, - ['Pointer'] = 4, + ['Warrior'] = 3, + ['Pointer'] = 4, ['Eyeball'] = 5, ['Moonbeam'] = 6, ['Whiplash'] = 7, @@ -5965,29 +5985,29 @@ mist.DBs.const.callsigns = { -- not accessible by SSE, must use static list :-/ ['Playboy'] = 12, ['Hammer'] = 13, ['Jaguar'] = 14, - ['Deathstar'] = 15, + ['Deathstar'] = 15, ['Anvil'] = 16, - ['Firefly'] = 17, + ['Firefly'] = 17, ['Mantis'] = 18, ['Badger'] = 19, }, ['aircraft'] = { ['Enfield'] = 1, ['Springfield'] = 2, - ['Uzi'] = 3, + ['Uzi'] = 3, ['Colt'] = 4, - ['Dodge'] = 5, + ['Dodge'] = 5, ['Ford'] = 6, ['Chevy'] = 7, ['Pontiac'] = 8, }, - + ['unique'] = { ['A10'] = { ['Hawg'] = 9, ['Boar'] = 10, ['Pig'] = 11, - ['Tusk'] = 12, + ['Tusk'] = 12, ['rules'] = { ['canUseAircraft'] = true, ['appliesTo'] = { @@ -6001,15 +6021,15 @@ mist.DBs.const.callsigns = { -- not accessible by SSE, must use static list :-/ } --[[ scope: - { - units = {...}, -- unit names. - coa = {...}, -- coa names - countries = {...}, -- country names - CA = {...}, -- looks just like coa. - unitTypes = { red = {}, blue = {}, all = {}, Russia = {},} - } - - + { + units = {...}, -- unit names. + coa = {...}, -- coa names + countries = {...}, -- country names + CA = {...}, -- looks just like coa. + unitTypes = { red = {}, blue = {}, all = {}, Russia = {},} + } + + scope examples: { units = { 'Hawg11', 'Hawg12' }, CA = {'blue'} } @@ -6022,4 +6042,4 @@ scope examples: ]] end mist.main() -env.info(('Mist version ' .. mist.majorVersion .. '.' .. mist.minorVersion .. '.' .. mist.build .. ' loaded.')) +env.info(('Mist version ' .. mist.majorVersion .. '.' .. mist.minorVersion .. '.' .. mist.build .. ' loaded.')) \ No newline at end of file diff --git a/test-mission.miz b/test-mission.miz index 2c3b09b..55627ac 100644 Binary files a/test-mission.miz and b/test-mission.miz differ