@jtff/miztemplate-lib 3.1.6 → 3.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -35,7 +35,7 @@ mist = {}
35
35
  -- don't change these
36
36
  mist.majorVersion = 4
37
37
  mist.minorVersion = 5
38
- mist.build = 107
38
+ mist.build = 122
39
39
 
40
40
  -- forward declaration of log shorthand
41
41
  local log
@@ -64,8 +64,8 @@ do -- the main scope
64
64
  local updateAliveUnitsCounter = 0
65
65
  local updateTenthSecond = 0
66
66
 
67
- local mistGpId = 7000
68
- local mistUnitId = 7000
67
+ local mistGpId = 70000
68
+ local mistUnitId = 70000
69
69
  local mistDynAddIndex = {[' air '] = 0, [' hel '] = 0, [' gnd '] = 0, [' bld '] = 0, [' static '] = 0, [' shp '] = 0}
70
70
 
71
71
  local scheduledTasks = {}
@@ -75,7 +75,7 @@ do -- the main scope
75
75
  mist.nextGroupId = 1
76
76
  mist.nextUnitId = 1
77
77
 
78
-
78
+
79
79
 
80
80
  local function initDBs() -- mist.DBs scope
81
81
  mist.DBs = {}
@@ -92,48 +92,11 @@ do -- the main scope
92
92
  mist.DBs.missionData.files[#mist.DBs.missionData.files + 1] = mist.utils.deepCopy(fIndex)
93
93
  end
94
94
  end
95
- -- if we add more coalition specific data then bullsye should be categorized by coaliton. For now its just the bullseye table
95
+ -- if we add more coalition specific data then bullseye should be categorized by coaliton. For now its just the bullseye table
96
96
  mist.DBs.missionData.bullseye = {}
97
+ mist.DBs.missionData.countries = {}
97
98
  end
98
99
 
99
- mist.DBs.zonesByName = {}
100
- mist.DBs.zonesByNum = {}
101
-
102
-
103
- if env.mission.triggers and env.mission.triggers.zones then
104
- for zone_ind, zone_data in pairs(env.mission.triggers.zones) do
105
- if type(zone_data) == 'table' then
106
- local zone = mist.utils.deepCopy(zone_data)
107
- zone.point = {} -- point is used by SSE
108
- zone.point.x = zone_data.x
109
- zone.point.y = 0
110
- zone.point.z = zone_data.y
111
- zone.properties = {}
112
- if zone_data.properties then
113
- for propInd, prop in pairs(zone_data.properties) do
114
- if prop.value and type(prop.value) == 'string' and prop.value ~= "" then
115
- zone.properties[prop.key] = prop.value
116
- end
117
- end
118
- end
119
- if zone.verticies then -- trust but verify
120
- local r = 0
121
- for i = 1, #zone.verticies do
122
- local dist = mist.utils.get2DDist(zone.point, zone.verticies[i])
123
- if dist > r then
124
- r = mist.utils.deepCopy(dist)
125
- end
126
- end
127
- zone.radius = r
128
-
129
- end
130
-
131
- mist.DBs.zonesByName[zone_data.name] = zone
132
- mist.DBs.zonesByNum[#mist.DBs.zonesByNum + 1] = mist.utils.deepCopy(zone) --[[deepcopy so that the zone in zones_by_name and the zone in
133
- zones_by_num se are different objects.. don't want them linked.]]
134
- end
135
- end
136
- end
137
100
 
138
101
  mist.DBs.drawingByName = {}
139
102
  mist.DBs.drawingIndexed = {}
@@ -213,6 +176,16 @@ do -- the main scope
213
176
 
214
177
  end
215
178
 
179
+ local abRef = {units = {}, airbase = {}}
180
+ for ind, val in pairs(world.getAirbases()) do
181
+ local cat = "airbase"
182
+ if Airbase.getDesc(val).category > 0 then
183
+ cat = "units"
184
+ end
185
+ abRef[cat][tonumber(val:getID())] = {name = val:getName()}
186
+
187
+ end
188
+
216
189
 
217
190
  mist.DBs.navPoints = {}
218
191
  mist.DBs.units = {}
@@ -222,6 +195,7 @@ do -- the main scope
222
195
  if string.lower(coa_name_miz) == 'neutrals' then
223
196
  coa_name = 'neutral'
224
197
  end
198
+ local coaEnum = coalition.side[string.upper(coa_name)]
225
199
  if type(coa_data) == 'table' then
226
200
  mist.DBs.units[coa_name] = {}
227
201
 
@@ -254,6 +228,7 @@ do -- the main scope
254
228
  if cntry_data.id and country.names[cntry_data.id] then
255
229
  countryName = string.lower(country.names[cntry_data.id])
256
230
  end
231
+ mist.DBs.missionData.countries[countryName] = coa_name
257
232
  mist.DBs.units[coa_name][countryName] = {}
258
233
  mist.DBs.units[coa_name][countryName].countryId = cntry_data.id
259
234
 
@@ -270,7 +245,18 @@ do -- the main scope
270
245
  mist.DBs.units[coa_name][countryName][category] = {}
271
246
 
272
247
  for group_num, group_data in pairs(obj_cat_data.group) do
273
-
248
+ local helipadId
249
+ local airdromeId
250
+
251
+ if group_data.route and group_data.route.points and group_data.route.points[1] then
252
+ if group_data.route.points[1].airdromeId then
253
+ airdromeId = group_data.route.points[1].airdromeId
254
+ --table.insert(abRef.airbase[group_data.route.points[1].airdromeId], group_data.groupId)
255
+ elseif group_data.route.points[1].helipadId then
256
+ helipadId = group_data.route.points[1].helipadId
257
+ --table.insert(abRef.units[group_data.route.points[1].helipadId], group_data.groupId)
258
+ end
259
+ end
274
260
  if group_data and group_data.units and type(group_data.units) == 'table' then --making sure again- this is a valid group
275
261
 
276
262
  mist.DBs.units[coa_name][countryName][category][group_num] = {}
@@ -282,6 +268,7 @@ do -- the main scope
282
268
  mist.DBs.units[coa_name][countryName][category][group_num].groupId = group_data.groupId
283
269
  mist.DBs.units[coa_name][countryName][category][group_num].category = category
284
270
  mist.DBs.units[coa_name][countryName][category][group_num].coalition = coa_name
271
+ mist.DBs.units[coa_name][countryName][category][group_num].coalitionId = coaEnum
285
272
  mist.DBs.units[coa_name][countryName][category][group_num].country = countryName
286
273
  mist.DBs.units[coa_name][countryName][category][group_num].countryId = cntry_data.id
287
274
  mist.DBs.units[coa_name][countryName][category][group_num].startTime = group_data.start_time
@@ -309,6 +296,8 @@ do -- the main scope
309
296
  units_tbl[unit_num].unitId = unit_data.unitId
310
297
  units_tbl[unit_num].category = category
311
298
  units_tbl[unit_num].coalition = coa_name
299
+ units_tbl[unit_num].coalitionId = coaEnum
300
+
312
301
  units_tbl[unit_num].country = countryName
313
302
  units_tbl[unit_num].countryId = cntry_data.id
314
303
  units_tbl[unit_num].heading = unit_data.heading
@@ -331,11 +320,17 @@ do -- the main scope
331
320
  units_tbl[unit_num].onboard_num = unit_data.onboard_num
332
321
  units_tbl[unit_num].hardpoint_racks = unit_data.hardpoint_racks
333
322
  units_tbl[unit_num].psi = unit_data.psi
334
-
323
+
324
+ if helipadId then
325
+ units_tbl[unit_num].helipadId = mist.utils.deepCopy(helipadId)
326
+ end
327
+ if airdromeId then
328
+ units_tbl[unit_num].airdromeId = mist.utils.deepCopy(airdromeId)
329
+ end
335
330
 
336
331
  units_tbl[unit_num].groupName = groupName
337
332
  units_tbl[unit_num].groupId = group_data.groupId
338
-
333
+ units_tbl[unit_num].linkUnit = unit_data.linkUnit
339
334
  if unit_data.AddPropAircraft then
340
335
  units_tbl[unit_num].AddPropAircraft = unit_data.AddPropAircraft
341
336
  end
@@ -343,7 +338,13 @@ do -- the main scope
343
338
  if category == 'static' then
344
339
  units_tbl[unit_num].categoryStatic = unit_data.category
345
340
  units_tbl[unit_num].shape_name = unit_data.shape_name
346
- units_tbl[unit_num].linkUnit = unit_data.linkUnit
341
+ if group_data.linkOffset then
342
+ if group_data.route and group_data.route.points and group_data.route.points[1] and group_data.route.points[1].linkUnit then
343
+ units_tbl[unit_num].linkUnit = group_data.route.points[1].linkUnit
344
+ end
345
+ units_tbl[unit_num].offset = unit_data.offsets
346
+ end
347
+
347
348
  if unit_data.mass then
348
349
  units_tbl[unit_num].mass = unit_data.mass
349
350
  end
@@ -351,6 +352,13 @@ do -- the main scope
351
352
  if unit_data.canCargo then
352
353
  units_tbl[unit_num].canCargo = unit_data.canCargo
353
354
  end
355
+
356
+ if unit_data.category == "Heliports" then
357
+ if not abRef.units[unit_data.unitId] then
358
+ abRef.units[unit_data.unitId] = {name = unit_data.name}
359
+ end
360
+
361
+ end
354
362
  end
355
363
 
356
364
  end --for unit_num, unit_data in pairs(group_data.units) do
@@ -390,6 +398,36 @@ do -- the main scope
390
398
  mist.DBs.removedAliveUnits = {} -- will be filled in by the "updateAliveUnits" coroutine in mist.main.
391
399
 
392
400
  mist.DBs.const = {}
401
+
402
+ mist.DBs.const.nato = {
403
+ a = "alpha",
404
+ b = "bravo",
405
+ c = "charlie",
406
+ d = "delta",
407
+ e = "echo",
408
+ f = "foxtrot",
409
+ g = "golf",
410
+ h = "hotel",
411
+ i = "india",
412
+ j = "juliett",
413
+ k = "kilo",
414
+ l = "lima",
415
+ m = "mike",
416
+ n = "november",
417
+ o = "oscar",
418
+ p = "papa",
419
+ q = "quebec",
420
+ r = "romeo",
421
+ s = "sierra",
422
+ t = "tango",
423
+ u = "uniform",
424
+ v = "victor",
425
+ w = "whiskey",
426
+ x = "xray",
427
+ y = "yankee",
428
+ z = "zulu",
429
+
430
+ }
393
431
 
394
432
  -- not accessible by SSE, must use static list :-/
395
433
  mist.DBs.const.callsigns = {
@@ -697,6 +735,10 @@ do -- the main scope
697
735
  -- end
698
736
 
699
737
  --Build DBs
738
+
739
+ --dbLog:echo(abRef)
740
+ mist.DBs.spawnsByBase = {}
741
+
700
742
  for coa_name, coa_data in pairs(mist.DBs.units) do
701
743
  for cntry_name, cntry_data in pairs(coa_data) do
702
744
  for category_name, category_data in pairs(cntry_data) do
@@ -706,22 +748,41 @@ do -- the main scope
706
748
  mist.DBs.groupsByName[group_data.groupName] = mist.utils.deepCopy(group_data)
707
749
  mist.DBs.groupsById[group_data.groupId] = mist.utils.deepCopy(group_data)
708
750
  for unit_ind, unit_data in pairs(group_data.units) do
709
- mist.DBs.unitsByName[unit_data.unitName] = mist.utils.deepCopy(unit_data)
710
- mist.DBs.unitsById[unit_data.unitId] = mist.utils.deepCopy(unit_data)
751
+ local copy = mist.utils.deepCopy(unit_data)
752
+ local num = #mist.DBs.unitsByNum + 1
753
+ copy.dbNum = num
754
+
755
+ mist.DBs.unitsByName[unit_data.unitName] = mist.utils.deepCopy(copy)
756
+ mist.DBs.unitsById[unit_data.unitId] = mist.utils.deepCopy(copy)
711
757
 
712
758
  mist.DBs.unitsByCat[unit_data.category] = mist.DBs.unitsByCat[unit_data.category] or {} -- future-proofing against new categories...
713
- table.insert(mist.DBs.unitsByCat[unit_data.category], mist.utils.deepCopy(unit_data))
759
+ table.insert(mist.DBs.unitsByCat[unit_data.category], mist.utils.deepCopy(copy))
714
760
  --dbLog:info('inserting $1', unit_data.unitName)
715
- table.insert(mist.DBs.unitsByNum, mist.utils.deepCopy(unit_data))
761
+ table.insert(mist.DBs.unitsByNum, mist.utils.deepCopy(copy))
716
762
 
717
763
  if unit_data.skill and (unit_data.skill == "Client" or unit_data.skill == "Player") then
718
- mist.DBs.humansByName[unit_data.unitName] = mist.utils.deepCopy(unit_data)
719
- mist.DBs.humansById[unit_data.unitId] = mist.utils.deepCopy(unit_data)
764
+ mist.DBs.humansByName[unit_data.unitName] = mist.utils.deepCopy(copy)
765
+ mist.DBs.humansById[unit_data.unitId] = mist.utils.deepCopy(copy)
720
766
  --if Unit.getByName(unit_data.unitName) then
721
767
  -- mist.DBs.activeHumans[unit_data.unitName] = mist.utils.deepCopy(unit_data)
722
768
  -- mist.DBs.activeHumans[unit_data.unitName].playerName = Unit.getByName(unit_data.unitName):getPlayerName()
723
769
  --end
724
770
  end
771
+ if unit_data.airdromeId then
772
+ --log:echo(unit_data.airdromeId)
773
+ --log:echo(abRef.airbase[unit_data.airdromeId])
774
+ if not mist.DBs.spawnsByBase[abRef.airbase[unit_data.airdromeId].name] then
775
+ mist.DBs.spawnsByBase[abRef.airbase[unit_data.airdromeId].name] = {}
776
+ end
777
+ table.insert(mist.DBs.spawnsByBase[abRef.airbase[unit_data.airdromeId].name], unit_data.unitName)
778
+ end
779
+ if unit_data.helipadId and abRef.units[unit_data.helipadId] and abRef.units[unit_data.helipadId].name then
780
+ if not mist.DBs.spawnsByBase[abRef.units[unit_data.helipadId].name] then
781
+ mist.DBs.spawnsByBase[abRef.units[unit_data.helipadId].name] = {}
782
+ end
783
+ table.insert(mist.DBs.spawnsByBase[abRef.units[unit_data.helipadId].name], unit_data.unitName)
784
+ end
785
+
725
786
  end
726
787
  end
727
788
  end
@@ -729,7 +790,60 @@ do -- the main scope
729
790
  end
730
791
  end
731
792
  end
793
+
794
+ mist.DBs.zonesByName = {}
795
+ mist.DBs.zonesByNum = {}
732
796
 
797
+ if env.mission.triggers and env.mission.triggers.zones then
798
+ for zone_ind, zone_data in pairs(env.mission.triggers.zones) do
799
+ if type(zone_data) == 'table' then
800
+ local zone = mist.utils.deepCopy(zone_data)
801
+ --log:warn(zone)
802
+ zone.point = {} -- point is used by SSE
803
+ zone.point.x = zone_data.x
804
+ zone.point.y = land.getHeight({x = zone_data.x, y = zone_data.y})
805
+ zone.point.z = zone_data.y
806
+ zone.properties = {}
807
+ if zone_data.properties then
808
+ for propInd, prop in pairs(zone_data.properties) do
809
+ if prop.value and tostring(prop.value) ~= "" then
810
+ zone.properties[prop.key] = prop.value
811
+ end
812
+ end
813
+ end
814
+ if zone.verticies then -- trust but verify
815
+ local r = 0
816
+ for i = 1, #zone.verticies do
817
+ local dist = mist.utils.get2DDist(zone.point, zone.verticies[i])
818
+ if dist > r then
819
+ r = mist.utils.deepCopy(dist)
820
+ end
821
+ end
822
+ zone.radius = r
823
+
824
+ end
825
+ if zone.linkUnit then
826
+ local uRef = mist.DBs.unitsByName[zone.linkUnit]
827
+ if uRef then
828
+ if zone.verticies then
829
+ local offset = {}
830
+ for i = 1, #zone.verticies do
831
+ table.insert(offset, {dist = mist.utils.get2DDist(uRef.point, zone.verticies[i]), heading = mist.getHeadingPoints(uRef.point, zone.verticies[i]) + uRef.heading})
832
+ end
833
+ zone.offset = offset
834
+ else
835
+ zone.offset = {dist = mist.utils.get2DDist(uRef.point, zone.point), heading = mist.getHeadingPoints(uRef.point, zone.point) + uRef.heading}
836
+ end
837
+ end
838
+ end
839
+
840
+ mist.DBs.zonesByName[zone_data.name] = zone
841
+ mist.DBs.zonesByNum[#mist.DBs.zonesByNum + 1] = mist.utils.deepCopy(zone) --[[deepcopy so that the zone in zones_by_name and the zone in
842
+ zones_by_num se are different objects.. don't want them linked.]]
843
+ end
844
+ end
845
+ end
846
+
733
847
  --DynDBs
734
848
  mist.DBs.MEunits = mist.utils.deepCopy(mist.DBs.units)
735
849
  mist.DBs.MEunitsByName = mist.utils.deepCopy(mist.DBs.unitsByName)
@@ -789,6 +903,7 @@ do -- the main scope
789
903
  if not static_found then
790
904
  val.objectPos = pos.p
791
905
  val.objectType = 'building'
906
+ val.typeName = Object.getTypeName(val.object)
792
907
  end
793
908
  else
794
909
  val.objectType = 'unknown'
@@ -803,10 +918,10 @@ do -- the main scope
803
918
  do -- mist unitID funcs
804
919
  for id, idData in pairs(mist.DBs.unitsById) do
805
920
  if idData.unitId > mist.nextUnitId then
806
- mist.nextUnitId = mist.utils.deepCopy(idData.unitId)
921
+ mist.nextUnitId = mist.utils.deepCopy(idData.unitId)
807
922
  end
808
923
  if idData.groupId > mist.nextGroupId then
809
- mist.nextGroupId = mist.utils.deepCopy(idData.groupId)
924
+ mist.nextGroupId = mist.utils.deepCopy(idData.groupId)
810
925
  end
811
926
  end
812
927
  end
@@ -815,6 +930,7 @@ do -- the main scope
815
930
  end
816
931
 
817
932
  local function updateAliveUnits() -- coroutine function
933
+ --log:warn("updateALiveUnits")
818
934
  local lalive_units = mist.DBs.aliveUnits -- local references for faster execution
819
935
  local lunits = mist.DBs.unitsByNum
820
936
  local ldeepcopy = mist.utils.deepCopy
@@ -831,7 +947,7 @@ do -- the main scope
831
947
  for i = 1, #lunits do
832
948
  if lunits[i].category ~= 'static' then -- can't get statics with Unit.getByName :(
833
949
  local unit = lUnit.getByName(lunits[i].unitName)
834
- if unit then
950
+ if unit and unit:isExist() == true then
835
951
  ----dbLog:info("unit named $1 alive!", lunits[i].unitName) -- spammy
836
952
  local pos = unit:getPosition()
837
953
  local newtbl = ldeepcopy(lunits[i])
@@ -845,6 +961,7 @@ do -- the main scope
845
961
  end
846
962
  end
847
963
  if i%units_per_run == 0 then
964
+ --log:warn("yield: $1", i)
848
965
  coroutine.yield()
849
966
  end
850
967
  end
@@ -858,9 +975,10 @@ do -- the main scope
858
975
  end
859
976
  end
860
977
 
861
- local function dbUpdate(event, objType)
862
- --dbLog:info('dbUpdate')
978
+ local function dbUpdate(event, oType, origGroupName)
979
+ --dbLog:info('dbUpdate: $1', event)
863
980
  local newTable = {}
981
+ local objType = oType
864
982
  newTable.startTime = 0
865
983
  if type(event) == 'string' then -- if name of an object.
866
984
  local newObject
@@ -868,15 +986,16 @@ do -- the main scope
868
986
  newObject = Group.getByName(event)
869
987
  elseif StaticObject.getByName(event) then
870
988
  newObject = StaticObject.getByName(event)
989
+ objType = "static"
871
990
  -- log:info('its static')
872
991
  else
873
992
  log:warn('$1 is not a Group or Static Object. This should not be possible. Sent category is: $2', event, objType)
874
993
  return false
875
994
  end
876
-
877
- newTable.name = newObject:getName()
995
+ local objName = newObject:getName()
996
+ newTable.name = origGroupName or objName
878
997
  newTable.groupId = tonumber(newObject:getID())
879
- newTable.groupName = newObject:getName()
998
+ newTable.groupName = origGroupName or objName
880
999
  local unitOneRef
881
1000
  if objType == 'static' then
882
1001
  unitOneRef = newObject
@@ -888,7 +1007,7 @@ do -- the main scope
888
1007
  if #unitOneRef > 0 and unitOneRef[1] and type(unitOneRef[1]) == 'table' then
889
1008
  newTable.countryId = tonumber(unitOneRef[1]:getCountry())
890
1009
  newTable.coalitionId = tonumber(unitOneRef[1]:getCoalition())
891
- newTable.category = tonumber(newObject:getCategory())
1010
+ newTable.category = tonumber(Object.getCategory(newObject))
892
1011
  else
893
1012
  log:warn('getUnits failed to return on $1 ; Built Data: $2.', event, newTable)
894
1013
  return false
@@ -939,15 +1058,16 @@ do -- the main scope
939
1058
  newTable.units = {}
940
1059
  if objType == 'group' then
941
1060
  for unitId, unitData in pairs(unitOneRef) do
1061
+ local point = unitData:getPoint()
942
1062
  newTable.units[unitId] = {}
943
1063
  newTable.units[unitId].unitName = unitData:getName()
944
1064
 
945
- newTable.units[unitId].x = mist.utils.round(unitData:getPosition().p.x)
946
- newTable.units[unitId].y = mist.utils.round(unitData:getPosition().p.z)
1065
+ newTable.units[unitId].x = mist.utils.round(point.x)
1066
+ newTable.units[unitId].y = mist.utils.round(point.z)
947
1067
  newTable.units[unitId].point = {}
948
1068
  newTable.units[unitId].point.x = newTable.units[unitId].x
949
1069
  newTable.units[unitId].point.y = newTable.units[unitId].y
950
- newTable.units[unitId].alt = mist.utils.round(unitData:getPosition().p.y)
1070
+ newTable.units[unitId].alt = mist.utils.round(point.y)
951
1071
  newTable.units[unitId].speed = mist.vec.mag(unitData:getVelocity())
952
1072
 
953
1073
  newTable.units[unitId].heading = mist.getHeading(unitData, true)
@@ -985,15 +1105,16 @@ do -- the main scope
985
1105
  end
986
1106
  else -- its a static
987
1107
  newTable.category = 'static'
1108
+ local point = newObject:getPoint()
988
1109
  newTable.units[1] = {}
989
1110
  newTable.units[1].unitName = newObject:getName()
990
1111
  newTable.units[1].category = 'static'
991
- newTable.units[1].x = mist.utils.round(newObject:getPosition().p.x)
992
- newTable.units[1].y = mist.utils.round(newObject:getPosition().p.z)
1112
+ newTable.units[1].x = mist.utils.round(point.x)
1113
+ newTable.units[1].y = mist.utils.round(point.z)
993
1114
  newTable.units[1].point = {}
994
1115
  newTable.units[1].point.x = newTable.units[1].x
995
1116
  newTable.units[1].point.y = newTable.units[1].y
996
- newTable.units[1].alt = mist.utils.round(newObject:getPosition().p.y)
1117
+ newTable.units[1].alt = mist.utils.round(point.y)
997
1118
  newTable.units[1].heading = mist.getHeading(newObject, true)
998
1119
  newTable.units[1].type = newObject:getTypeName()
999
1120
  newTable.units[1].unitId = tonumber(newObject:getID())
@@ -1003,7 +1124,7 @@ do -- the main scope
1003
1124
  newTable.units[1].country = newTable.country
1004
1125
  newTable.units[1].coalitionId = newTable.coalitionId
1005
1126
  newTable.units[1].coalition = newTable.coalition
1006
- if newObject:getCategory() == 6 and newObject:getCargoDisplayName() then
1127
+ if Object.getCategory(newObject) == 6 and newObject:getCargoDisplayName() then
1007
1128
  local mass = newObject:getCargoDisplayName()
1008
1129
  mass = string.gsub(mass, ' ', '')
1009
1130
  mass = string.gsub(mass, 'kg', '')
@@ -1061,9 +1182,10 @@ do -- the main scope
1061
1182
  --dbLog:info('iterate')
1062
1183
  for name, gData in pairs(tempSpawnedGroups) do
1063
1184
  --env.info(name)
1064
- --dbLog:info(gData)
1185
+ --dbLog:warn(gData)
1065
1186
  local updated = false
1066
1187
  local stillExists = false
1188
+ local staticGroupName
1067
1189
  if not gData.checked then
1068
1190
  tempSpawnedGroups[name].checked = true -- so if there was an error it will get cleared.
1069
1191
  local _g = gData.gp or Group.getByName(name)
@@ -1073,7 +1195,7 @@ do -- the main scope
1073
1195
  local dbTable = mist.DBs.groupsByName[name]
1074
1196
  --dbLog:info(dbTable)
1075
1197
  if gData.type ~= 'static' then
1076
- -- dbLog:info('Not static')
1198
+ --dbLog:info('Not static')
1077
1199
 
1078
1200
  if _g and _g:isExist() == true then
1079
1201
  stillExists = true
@@ -1091,22 +1213,32 @@ do -- the main scope
1091
1213
  end
1092
1214
  end
1093
1215
  --dbLog:info('Updated: $1', updated)
1094
- if updated == false and gData.type ~= 'static' then -- time to check units
1095
- --dbLog:info('No Group Mismatch, Check Units')
1096
- if _g and _g:isExist() == true then
1097
- stillExists = true
1098
- for index, uObject in pairs(_g:getUnits()) do
1099
- --dbLog:info(index)
1100
- if mist.DBs.unitsByName[uObject:getName()] then
1101
- --dbLog:info('UnitByName table exists')
1102
- local uTable = mist.DBs.unitsByName[uObject:getName()]
1103
- if tonumber(uObject:getID()) ~= uTable.unitId or uObject:getTypeName() ~= uTable.type then
1104
- --dbLog:info('Unit Data mismatch')
1105
- updated = true
1106
- break
1216
+ if updated == false then
1217
+ if gData.type ~= 'static' then -- time to check units
1218
+ -- dbLog:info('No Group Mismatch, Check Units')
1219
+ if _g and _g:isExist() == true then
1220
+ stillExists = true
1221
+ for index, uObject in pairs(_g:getUnits()) do
1222
+ -- dbLog:info(index)
1223
+ if mist.DBs.unitsByName[uObject:getName()] then
1224
+ --dbLog:info('UnitByName table exists')
1225
+ local uTable = mist.DBs.unitsByName[uObject:getName()]
1226
+ if tonumber(uObject:getID()) ~= uTable.unitId or uObject:getTypeName() ~= uTable.type then
1227
+ --dbLog:info('Unit Data mismatch')
1228
+ updated = true
1229
+ break
1230
+ end
1107
1231
  end
1108
1232
  end
1109
1233
  end
1234
+ else -- it is a static object
1235
+ local ref = mist.DBs.unitsByName[name]
1236
+ if ref then
1237
+ staticGroupName = ref.groupName
1238
+ else
1239
+ stillExists = true
1240
+ end
1241
+
1110
1242
  end
1111
1243
  else
1112
1244
  stillExists = true
@@ -1114,7 +1246,7 @@ do -- the main scope
1114
1246
 
1115
1247
  if stillExists == true and (updated == true or not mist.DBs.groupsByName[name]) then
1116
1248
  --dbLog:info('Get Table')
1117
- local dbData = dbUpdate(name, gData.type)
1249
+ local dbData = dbUpdate(name, gData.type, staticGroupName)
1118
1250
  if dbData and type(dbData) == 'table' then
1119
1251
  writeGroups[#writeGroups+1] = {data = dbData, isUpdated = updated}
1120
1252
  end
@@ -1127,116 +1259,177 @@ do -- the main scope
1127
1259
  end
1128
1260
  end
1129
1261
 
1130
- local function updateDBTables()
1131
- local i = #writeGroups
1132
-
1133
- local savesPerRun = math.ceil(i/10)
1134
- if savesPerRun < 5 then
1135
- savesPerRun = 5
1262
+ local updateChecker = {}
1263
+
1264
+
1265
+ local function writeDBTables(newEntry)
1266
+ local ldeepCopy = mist.utils.deepCopy
1267
+ local newTable = newEntry.data
1268
+ --dbLog:info(newTable)
1269
+
1270
+ local state = 0
1271
+ if updateChecker[newTable.name] then
1272
+ dbLog:warn("Failed to add to database: $1. Stopped at state: $2", newTable.name, updateChecker[newTable.name])
1273
+ return false
1274
+ else
1275
+ --dbLog:info('define default state')
1276
+ updateChecker[newTable.name] = 0
1277
+ --dbLog:info('define default state1')
1278
+ state = updateChecker[newTable.name]
1279
+ --dbLog:info('define default state2')
1136
1280
  end
1137
- if i > 0 then
1138
- --dbLog:info('updateDBTables')
1139
- local ldeepCopy = mist.utils.deepCopy
1140
- for x = 1, i do
1141
- --dbLog:info(writeGroups[x])
1142
- local newTable = writeGroups[x].data
1143
- local updated = writeGroups[x].isUpdated
1144
- local mistCategory
1145
- if type(newTable.category) == 'string' then
1146
- mistCategory = string.lower(newTable.category)
1147
- end
1148
-
1149
- if string.upper(newTable.category) == 'GROUND_UNIT' then
1150
- mistCategory = 'vehicle'
1151
- newTable.category = mistCategory
1152
- elseif string.upper(newTable.category) == 'AIRPLANE' then
1153
- mistCategory = 'plane'
1154
- newTable.category = mistCategory
1155
- elseif string.upper(newTable.category) == 'HELICOPTER' then
1156
- mistCategory = 'helicopter'
1157
- newTable.category = mistCategory
1158
- elseif string.upper(newTable.category) == 'SHIP' then
1159
- mistCategory = 'ship'
1160
- newTable.category = mistCategory
1161
- end
1162
- --dbLog:info('Update unitsBy')
1163
- for newId, newUnitData in pairs(newTable.units) do
1164
- --dbLog:info(newId)
1165
- newUnitData.category = mistCategory
1166
- if newUnitData.unitId then
1167
- --dbLog:info('byId')
1168
- mist.DBs.unitsById[tonumber(newUnitData.unitId)] = ldeepCopy(newUnitData)
1169
- end
1170
- --dbLog:info(updated)
1171
- if mist.DBs.unitsByName[newUnitData.unitName] and updated == true then--if unit existed before and something was updated, write over the entry for a given unit name just in case.
1172
- --dbLog:info('Updating Unit Tables')
1173
- for i = 1, #mist.DBs.unitsByCat[mistCategory] do
1174
- if mist.DBs.unitsByCat[mistCategory][i].unitName == newUnitData.unitName then
1175
- --dbLog:info('Entry Found, Rewriting for unitsByCat')
1176
- mist.DBs.unitsByCat[mistCategory][i] = ldeepCopy(newUnitData)
1177
- break
1178
- end
1179
- end
1180
- for i = 1, #mist.DBs.unitsByNum do
1181
- if mist.DBs.unitsByNum[i].unitName == newUnitData.unitName then
1182
- --dbLog:info('Entry Found, Rewriting for unitsByNum')
1183
- mist.DBs.unitsByNum[i] = ldeepCopy(newUnitData)
1184
- break
1185
- end
1186
- end
1187
-
1188
- else
1189
- --dbLog:info('Unitname not in use, add as normal')
1190
- mist.DBs.unitsByCat[mistCategory][#mist.DBs.unitsByCat[mistCategory] + 1] = ldeepCopy(newUnitData)
1191
- mist.DBs.unitsByNum[#mist.DBs.unitsByNum + 1] = ldeepCopy(newUnitData)
1281
+
1282
+ local updated = newEntry.isUpdated
1283
+ local mistCategory
1284
+ --dbLog:info('define categoryy')
1285
+ if type(newTable.category) == 'string' then
1286
+ mistCategory = string.lower(newTable.category)
1287
+ end
1288
+
1289
+ if string.upper(newTable.category) == 'GROUND_UNIT' then
1290
+ mistCategory = 'vehicle'
1291
+ newTable.category = mistCategory
1292
+ elseif string.upper(newTable.category) == 'AIRPLANE' then
1293
+ mistCategory = 'plane'
1294
+ newTable.category = mistCategory
1295
+ elseif string.upper(newTable.category) == 'HELICOPTER' then
1296
+ mistCategory = 'helicopter'
1297
+ newTable.category = mistCategory
1298
+ elseif string.upper(newTable.category) == 'SHIP' then
1299
+ mistCategory = 'ship'
1300
+ newTable.category = mistCategory
1301
+ end
1302
+ --dbLog:info('Update unitsBy')
1303
+ state = 1
1304
+ for newId, newUnitData in pairs(newTable.units) do
1305
+ --dbLog:info(newId)
1306
+ newUnitData.category = mistCategory
1307
+
1308
+ --dbLog:info(updated)
1309
+ if mist.DBs.unitsByName[newUnitData.unitName] and updated == true then --if unit existed before and something was updated, write over the entry for a given unit name just in case.
1310
+ state = 1.1
1311
+ --dbLog:info('Updating Unit Tables')
1312
+ local refNum = mist.DBs.unitsByName[newUnitData.unitName].dbNum
1313
+ for i = 1, #mist.DBs.unitsByCat[mistCategory] do
1314
+ if mist.DBs.unitsByCat[mistCategory][i].unitName == newUnitData.unitName then
1315
+ --dbLog:info('Entry Found, Rewriting for unitsByCat')
1316
+ mist.DBs.unitsByCat[mistCategory][i] = ldeepCopy(newUnitData)
1317
+ break
1192
1318
  end
1193
- mist.DBs.unitsByName[newUnitData.unitName] = ldeepCopy(newUnitData)
1194
-
1195
-
1196
- end
1197
- -- this is a really annoying DB to populate. Gotta create new tables in case its missing
1198
- --dbLog:info('write mist.DBs.units')
1199
- if not mist.DBs.units[newTable.coalition] then
1200
- mist.DBs.units[newTable.coalition] = {}
1201
- end
1202
-
1203
- if not mist.DBs.units[newTable.coalition][newTable.country] then
1204
- mist.DBs.units[newTable.coalition][(newTable.country)] = {}
1205
- mist.DBs.units[newTable.coalition][(newTable.country)].countryId = newTable.countryId
1206
- end
1207
- if not mist.DBs.units[newTable.coalition][newTable.country][mistCategory] then
1208
- mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory] = {}
1209
1319
  end
1210
-
1211
- if updated == true then
1212
- --dbLog:info('Updating DBsUnits')
1213
- for i = 1, #mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory] do
1214
- if mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory][i].groupName == newTable.groupName then
1215
- --dbLog:info('Entry Found, Rewriting')
1216
- mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory][i] = ldeepCopy(newTable)
1320
+ state = 1.2
1321
+ --dbLog:info('updateByNum')
1322
+ if refNum then -- easy way
1323
+ --dbLog:info('refNum exists, Rewriting for unitsByCat')
1324
+ mist.DBs.unitsByNum[refNum] = ldeepCopy(newUnitData)
1325
+ else --- the hard way
1326
+ --dbLog:info('iterate unitsByNum')
1327
+ for i = 1, #mist.DBs.unitsByNum do
1328
+ if mist.DBs.unitsByNum[i].unitName == newUnitData.unitName then
1329
+ --dbLog:info('Entry Found, Rewriting for unitsByNum')
1330
+ mist.DBs.unitsByNum[i] = ldeepCopy(newUnitData)
1217
1331
  break
1218
1332
  end
1219
1333
  end
1220
- else
1221
- mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory][#mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory] + 1] = ldeepCopy(newTable)
1222
1334
  end
1223
-
1224
-
1225
- if newTable.groupId then
1226
- mist.DBs.groupsById[newTable.groupId] = ldeepCopy(newTable)
1335
+ else
1336
+ state = 1.3
1337
+ --dbLog:info('Unitname not in use, add as normal')
1338
+ newUnitData.dbNum = #mist.DBs.unitsByNum + 1
1339
+ mist.DBs.unitsByCat[mistCategory][#mist.DBs.unitsByCat[mistCategory] + 1] = ldeepCopy(newUnitData)
1340
+ mist.DBs.unitsByNum[#mist.DBs.unitsByNum + 1] = ldeepCopy(newUnitData)
1341
+ end
1342
+ if newUnitData.unitId then
1343
+ --dbLog:info('byId')
1344
+ mist.DBs.unitsById[tonumber(newUnitData.unitId)] = ldeepCopy(newUnitData)
1345
+ end
1346
+ mist.DBs.unitsByName[newUnitData.unitName] = ldeepCopy(newUnitData)
1347
+ end
1348
+ -- this is a really annoying DB to populate. Gotta create new tables in case its missing
1349
+ --dbLog:info('write mist.DBs.units')
1350
+ state = 2
1351
+ if not mist.DBs.units[newTable.coalition] then
1352
+ mist.DBs.units[newTable.coalition] = {}
1353
+ end
1354
+ state = 3
1355
+ if not mist.DBs.units[newTable.coalition][newTable.country] then
1356
+ mist.DBs.units[newTable.coalition][(newTable.country)] = {}
1357
+ mist.DBs.units[newTable.coalition][(newTable.country)].countryId = newTable.countryId
1358
+ end
1359
+ state = 4
1360
+ if not mist.DBs.units[newTable.coalition][newTable.country][mistCategory] then
1361
+ mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory] = {}
1362
+ end
1363
+ state = 5
1364
+ if updated == true then
1365
+ --dbLog:info('Updating DBsUnits')
1366
+ for i = 1, #mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory] do
1367
+ if mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory][i].groupName == newTable.groupName then
1368
+ --dbLog:info('Entry Found, Rewriting')
1369
+ mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory][i] = ldeepCopy(newTable)
1370
+ break
1227
1371
  end
1372
+ end
1373
+ else
1374
+ --dbLog:info('adding to DBs Units')
1375
+ mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory][#mist.DBs.units[newTable.coalition][(newTable.country)][mistCategory] + 1] = ldeepCopy(newTable)
1376
+ end
1377
+ state = 6
1378
+
1379
+ if newTable.groupId then
1380
+ --dbLog:info('Make groupsById')
1381
+ mist.DBs.groupsById[newTable.groupId] = ldeepCopy(newTable)
1382
+ end
1383
+ --dbLog:info('make groupsByName')
1384
+ mist.DBs.groupsByName[newTable.name] = ldeepCopy(newTable)
1385
+ --dbLog:info('add to dynGroups')
1386
+ mist.DBs.dynGroupsAdded[#mist.DBs.dynGroupsAdded + 1] = ldeepCopy(newTable)
1387
+ --dbLog:info('clear entry')
1388
+ updateChecker[newTable.name] = nil
1389
+ --dbLog:info('return')
1390
+ return true
1391
+ end
1392
+
1393
+ function mist.forceAddToDB(object)
1394
+ -- object is static object or group.
1395
+ -- call dbUpdate to get the table
1396
+
1397
+ local tbl = dbUpdate(object)
1398
+ if tbl then
1399
+ local res = writeDBTables(tbl)
1400
+ if not res then
1401
+ log:warn("Failed to force add to DBs: $1", object)
1402
+ end
1403
+ end
1404
+ -- call writeDBTables with that table.
1405
+ end
1406
+
1407
+ local function updateDBTables()
1408
+ local i = #writeGroups
1228
1409
 
1229
- mist.DBs.groupsByName[newTable.name] = ldeepCopy(newTable)
1230
- mist.DBs.dynGroupsAdded[#mist.DBs.dynGroupsAdded + 1] = ldeepCopy(newTable)
1231
-
1232
- writeGroups[x] = nil
1233
- if x%savesPerRun == 0 then
1234
- coroutine.yield()
1410
+ local savesPerRun = math.ceil(i/10)
1411
+ if savesPerRun < 5 then
1412
+ savesPerRun = 5
1413
+ end
1414
+ if i > 0 then
1415
+ --dbLog:info('updateDBTables: $1', #writeGroups)
1416
+
1417
+ for x = 1, i do
1418
+ local res = writeDBTables(writeGroups[x])
1419
+ if res and res == true then
1420
+ --dbLog:info('result: complete')
1421
+ writeGroups[x] = nil
1422
+ else
1423
+ writeGroups[x] = nil
1235
1424
  end
1236
1425
  end
1426
+ if x%savesPerRun == 0 then
1427
+ coroutine.yield()
1428
+ end
1237
1429
  if timer.getTime() > lastUpdateTime then
1238
1430
  lastUpdateTime = timer.getTime()
1239
1431
  end
1432
+
1240
1433
  --dbLog:info('endUpdateTables')
1241
1434
  end
1242
1435
  end
@@ -1244,13 +1437,7 @@ do -- the main scope
1244
1437
  local function groupSpawned(event)
1245
1438
  -- dont need to add units spawned in at the start of the mission if mist is loaded in init line
1246
1439
  if event.id == world.event.S_EVENT_BIRTH and timer.getTime0() < timer.getAbsTime() then
1247
- --log:info('unitSpawnEvent')
1248
- --log:info(event)
1249
- --log:info(event.initiator:getTypeName())
1250
- --table.insert(tempSpawnedUnits,(event.initiator))
1251
- -------
1252
- -- New functionality below.
1253
- -------
1440
+
1254
1441
  if Object.getCategory(event.initiator) == 1 and not Unit.getPlayerName(event.initiator) then -- simple player check, will need to later check to see if unit was spawned with a player in a flight
1255
1442
  --log:info('Object is a Unit')
1256
1443
  if Unit.getGroup(event.initiator) then
@@ -1265,7 +1452,15 @@ do -- the main scope
1265
1452
  log:error('Group not accessible by unit in event handler. This is a DCS bug')
1266
1453
  end
1267
1454
  elseif Object.getCategory(event.initiator) == 3 or Object.getCategory(event.initiator) == 6 then
1268
- --log:info('Object is Static')
1455
+ --log:info('staticSpawnEvent')
1456
+ --log:info(event)
1457
+ --log:info(event.initiator:getTypeName())
1458
+ --table.insert(tempSpawnedUnits,(event.initiator))
1459
+ -------
1460
+ -- New functionality below.
1461
+ -------
1462
+ --log:info(event.initiator:getName())
1463
+ --log:info('Object is Static')
1269
1464
  tempSpawnedGroups[StaticObject.getName(event.initiator)] = {type = 'static'}
1270
1465
  tempSpawnGroupsCounter = tempSpawnGroupsCounter + 1
1271
1466
  end
@@ -1277,8 +1472,9 @@ do -- the main scope
1277
1472
  local function doScheduledFunctions()
1278
1473
  local i = 1
1279
1474
  while i <= #scheduledTasks do
1475
+ local refTime = timer.getTime()
1280
1476
  if not scheduledTasks[i].rep then -- not a repeated process
1281
- if scheduledTasks[i].t <= timer.getTime() then
1477
+ if scheduledTasks[i].t <= refTime then
1282
1478
  local task = scheduledTasks[i] -- local reference
1283
1479
  table.remove(scheduledTasks, i)
1284
1480
  local err, errmsg = pcall(task.f, unpack(task.vars, 1, table.maxn(task.vars)))
@@ -1290,9 +1486,9 @@ do -- the main scope
1290
1486
  i = i + 1
1291
1487
  end
1292
1488
  else
1293
- if scheduledTasks[i].st and scheduledTasks[i].st <= timer.getTime() then --if a stoptime was specified, and the stop time exceeded
1489
+ if scheduledTasks[i].st and scheduledTasks[i].st <= refTime then --if a stoptime was specified, and the stop time exceeded
1294
1490
  table.remove(scheduledTasks, i) -- stop time exceeded, do not execute, do not increment i
1295
- elseif scheduledTasks[i].t <= timer.getTime() then
1491
+ elseif scheduledTasks[i].t <= refTime then
1296
1492
  local task = scheduledTasks[i] -- local reference
1297
1493
  task.t = timer.getTime() + task.rep --schedule next run
1298
1494
  local err, errmsg = pcall(task.f, unpack(task.vars, 1, table.maxn(task.vars)))
@@ -1363,6 +1559,7 @@ do -- the main scope
1363
1559
  if not static_found then
1364
1560
  val.objectPos = pos.p
1365
1561
  val.objectType = 'building'
1562
+ val.typeName = Object.getTypeName(val.object)
1366
1563
  end
1367
1564
  else
1368
1565
  val.objectType = 'unknown'
@@ -1440,7 +1637,7 @@ do -- the main scope
1440
1637
 
1441
1638
  -- create logger
1442
1639
  mist.log = mist.Logger:new("MIST", mistSettings.logLevel)
1443
- dbLog = mist.Logger:new('MISTDB', 'warn')
1640
+ dbLog = mist.Logger:new('MISTDB', mistSettings.dbLog)
1444
1641
 
1445
1642
  log = mist.log -- log shorthand
1446
1643
  -- set warning log level, showing only
@@ -1502,7 +1699,7 @@ do -- the main scope
1502
1699
  coroutines.updateAliveUnits = nil
1503
1700
  end
1504
1701
  end
1505
-
1702
+
1506
1703
  doScheduledFunctions()
1507
1704
  end -- end of mist.main
1508
1705
 
@@ -1536,8 +1733,9 @@ do -- the main scope
1536
1733
  -- @todo write good docs
1537
1734
  -- @tparam table staticObj table containing data needed for the object creation
1538
1735
  function mist.dynAddStatic(n)
1539
- --log:info(newObj)
1736
+
1540
1737
  local newObj = mist.utils.deepCopy(n)
1738
+ log:warn(newObj)
1541
1739
  if newObj.units and newObj.units[1] then -- if its mist format
1542
1740
  for entry, val in pairs(newObj.units[1]) do
1543
1741
  if newObj[entry] and newObj[entry] ~= val or not newObj[entry] then
@@ -1595,7 +1793,7 @@ do -- the main scope
1595
1793
  end
1596
1794
 
1597
1795
  if not newObj.heading then
1598
- newObj.heading = math.random(360)
1796
+ newObj.heading = math.rad(math.random(360))
1599
1797
  end
1600
1798
 
1601
1799
  if newObj.categoryStatic then
@@ -1805,8 +2003,9 @@ do -- the main scope
1805
2003
 
1806
2004
  -- update and verify any self tasks
1807
2005
  if newGroup.route and newGroup.route.points then
2006
+ --log:warn(newGroup.route.points)
1808
2007
  for i, pData in pairs(newGroup.route.points) do
1809
- if pData.task and pData.task.params and pData.task.params.tasks and #pData.task.params.tasks > 0 then
2008
+ if pData.task and pData.task.params and pData.task.params.tasks and #pData.task.params.tasks > 0 then
1810
2009
  for tIndex, tData in pairs(pData.task.params.tasks) do
1811
2010
  if tData.params and tData.params.action then
1812
2011
  if tData.params.action.id == "EPLRS" then
@@ -2033,7 +2232,12 @@ do
2033
2232
  if metric then
2034
2233
  s = s .. ' at ' .. mist.utils.round(alt, 0)
2035
2234
  else
2036
- s = s .. ' at ' .. mist.utils.round(mist.utils.metersToFeet(alt), 0)
2235
+ s = s .. ' at '
2236
+ local rounded = mist.utils.round(mist.utils.metersToFeet(alt/1000), 0)
2237
+ s = s .. rounded
2238
+ if rounded > 0 then
2239
+ s = s .. "000"
2240
+ end
2037
2241
  end
2038
2242
  end
2039
2243
  return s
@@ -2827,11 +3031,11 @@ end
2827
3031
 
2828
3032
  function mist.getUnitsByAttribute(att, rnum, id)
2829
3033
  local cEntry = {}
2830
- cEntry.typeName = att.type or att.typeName or att.typename
3034
+ cEntry.type = att.type or att.typeName or att.typename
2831
3035
  cEntry.country = att.country
2832
3036
  cEntry.coalition = att.coalition
2833
3037
  cEntry.skill = att.skill
2834
- cEntry.categry = att.category
3038
+ cEntry.category = att.category
2835
3039
 
2836
3040
  local num = rnum or 1
2837
3041
 
@@ -2852,6 +3056,7 @@ function mist.getUnitsByAttribute(att, rnum, id)
2852
3056
  end
2853
3057
  end
2854
3058
  else
3059
+
2855
3060
  if uData[cName] and uData[cName] == cVal then
2856
3061
  matched = matched + 1
2857
3062
  end
@@ -2877,11 +3082,11 @@ end
2877
3082
 
2878
3083
  function mist.getGroupsByAttribute(att, rnum, id)
2879
3084
  local cEntry = {}
2880
- cEntry.typeName = att.type or att.typeName or att.typename
3085
+ cEntry.type = att.type or att.typeName or att.typename
2881
3086
  cEntry.country = att.country
2882
3087
  cEntry.coalition = att.coalition
2883
3088
  cEntry.skill = att.skill
2884
- cEntry.categry = att.category
3089
+ cEntry.category = att.category
2885
3090
 
2886
3091
  local num = rnum or 1
2887
3092
 
@@ -2894,7 +3099,7 @@ function mist.getGroupsByAttribute(att, rnum, id)
2894
3099
  for cName, cVal in pairs(cEntry) do
2895
3100
  if type(cVal) == 'table' then
2896
3101
  for sName, sVal in pairs(cVal) do
2897
- if cName == 'skill' or cName == 'typeName' then
3102
+ if cName == 'skill' or cName == 'type' then
2898
3103
  local lMatch = 0
2899
3104
  for uId, uData in pairs(gData.units) do
2900
3105
  if (uData[cName] and uData[cName] == sVal) or (gData[cName] and gData[cName] == sName) then
@@ -2912,7 +3117,7 @@ function mist.getGroupsByAttribute(att, rnum, id)
2912
3117
  end
2913
3118
  end
2914
3119
  else
2915
- if cName == 'skill' or cName == 'typeName' then
3120
+ if cName == 'skill' or cName == 'type' then
2916
3121
  local lMatch = 0
2917
3122
  for uId, uData in pairs(gData.units) do
2918
3123
  if (uData[cName] and uData[cName] == sVal) then
@@ -2945,7 +3150,33 @@ function mist.getGroupsByAttribute(att, rnum, id)
2945
3150
 
2946
3151
  end
2947
3152
 
2948
- function mist.getDeadMapObjsInZones(zone_names)
3153
+ function mist.getDeadMapObjectsFromPoint(p, radius, filters)
3154
+ local map_objs = {}
3155
+ local fCheck = filters or {}
3156
+ local filter = {}
3157
+ local r = radius or p.radius or 100
3158
+ local point = mist.utils.makeVec3(p)
3159
+ local filterSize = 0
3160
+ for fInd, fVal in pairs(fCheck) do
3161
+ filterSize = filterSize + 1
3162
+ filter[string.lower(fInd)] = true
3163
+ filter[string.lower(fVal)] = true
3164
+
3165
+ end
3166
+ for obj_id, obj in pairs(mist.DBs.deadObjects) do
3167
+ log:warn(obj)
3168
+ if obj.objectType and obj.objectType == 'building' then --dead map object
3169
+ if ((point.x - obj.objectPos.x)^2 + (point.z - obj.objectPos.z)^2)^0.5 <= r then
3170
+ if filterSize == 0 or (obj.typeName and filter[string.lower(obj.typeName)])then
3171
+ map_objs[#map_objs + 1] = mist.utils.deepCopy(obj)
3172
+ end
3173
+ end
3174
+ end
3175
+ end
3176
+ return map_objs
3177
+ end
3178
+
3179
+ function mist.getDeadMapObjsInZones(zone_names, filters)
2949
3180
  -- zone_names: table of zone names
2950
3181
  -- returns: table of dead map objects (indexed numerically)
2951
3182
  local map_objs = {}
@@ -2955,25 +3186,32 @@ function mist.getDeadMapObjsInZones(zone_names)
2955
3186
  zones[#zones + 1] = mist.DBs.zonesByName[zone_names[i]]
2956
3187
  end
2957
3188
  end
2958
- for obj_id, obj in pairs(mist.DBs.deadObjects) do
2959
- if obj.objectType and obj.objectType == 'building' then --dead map object
2960
- for i = 1, #zones do
2961
- if ((zones[i].point.x - obj.objectPos.x)^2 + (zones[i].point.z - obj.objectPos.z)^2)^0.5 <= zones[i].radius then
2962
- map_objs[#map_objs + 1] = mist.utils.deepCopy(obj)
2963
- end
2964
- end
2965
- end
2966
- end
3189
+ for i = 1, #zones do
3190
+ local rtn = mist.getDeadMapObjectsFromPoint(zones[i], nil, filters)
3191
+ for j = 1, #rtn do
3192
+ map_objs[#map_objs + 1] = rtn[j]
3193
+ end
3194
+ end
3195
+
2967
3196
  return map_objs
2968
3197
  end
2969
3198
 
2970
- function mist.getDeadMapObjsInPolygonZone(zone)
3199
+ function mist.getDeadMapObjsInPolygonZone(zone, filters)
2971
3200
  -- zone_names: table of zone names
2972
3201
  -- returns: table of dead map objects (indexed numerically)
3202
+ local filter = {}
3203
+ local fCheck = filters or {}
3204
+ local filterSize = 0
3205
+ for fInd, fVal in pairs(fCheck) do
3206
+ filterSize = filterSize + 1
3207
+ filter[string.lower(fInd)] = true
3208
+ filter[string.lower(fVal)] = true
3209
+
3210
+ end
2973
3211
  local map_objs = {}
2974
3212
  for obj_id, obj in pairs(mist.DBs.deadObjects) do
2975
3213
  if obj.objectType and obj.objectType == 'building' then --dead map object
2976
- if mist.pointInPolygon(obj.objectPos, zone) then
3214
+ if mist.pointInPolygon(obj.objectPos, zone) and (filterSize == 0 or filter[string.lower(obj.objectData.type)]) then
2977
3215
  map_objs[#map_objs + 1] = mist.utils.deepCopy(obj)
2978
3216
  end
2979
3217
  end
@@ -3096,7 +3334,7 @@ function mist.shape.getPointOnSegment(point, seg, isSeg)
3096
3334
 
3097
3335
 
3098
3336
  local cx, cy = p.x - s1.x, p.y - s1.y
3099
- local dx, dy = s2.x - s1.x, s2.x - s1.y
3337
+ local dx, dy = s2.x - s1.x, s2.y - s1.y
3100
3338
  local d = (dx*dx + dy*dy)
3101
3339
 
3102
3340
  if d == 0 then
@@ -3114,11 +3352,17 @@ function mist.shape.getPointOnSegment(point, seg, isSeg)
3114
3352
  end
3115
3353
 
3116
3354
 
3117
- function mist.shape.segmentIntersect(segA, segB)
3118
- local dx1, dy1 = segA[2].x - segA[1].x, segA[2] - segA[1].y
3119
- local dx2, dy2 = segB[2].x - segB[1].x, segB[2] - segB[1].y
3355
+
3356
+ function mist.shape.segmentIntersect(seg1, seg2)
3357
+ local segA = {mist.utils.makeVec2(seg1[1]), mist.utils.makeVec2(seg1[2])}
3358
+ local segB = {mist.utils.makeVec2(seg2[1]), mist.utils.makeVec2(seg2[2])}
3359
+
3360
+ local dx1, dy1 = segA[2].x - segA[1].x, segA[2].y - segA[1].y
3361
+ local dx2, dy2 = segB[2].x - segB[1].x, segB[2].y - segB[1].y
3120
3362
  local dx3, dy3 = segA[1].x - segB[1].x, segA[1].y - segB[1].y
3363
+
3121
3364
  local d = dx1*dy2 - dy1*dx2
3365
+
3122
3366
  if d == 0 then
3123
3367
  return false
3124
3368
  end
@@ -3131,7 +3375,7 @@ function mist.shape.segmentIntersect(segA, segB)
3131
3375
  return false
3132
3376
  end
3133
3377
  -- point of intersection
3134
- return true, segA[1].x + t1*dx1, segA[1].y + t1*dy1
3378
+ return true, {x = segA[1].x + t1*dx1, y = segA[1].y + t1*dy1}
3135
3379
  end
3136
3380
 
3137
3381
 
@@ -3187,8 +3431,8 @@ function mist.getUnitsInPolygon(unit_names, polyZone, max_alt)
3187
3431
  local inZoneUnits = {}
3188
3432
  for i =1, #units do
3189
3433
  local lUnit = units[i]
3190
- local lCat = lUnit:getCategory()
3191
- if ((lCat == 1 and lUnit:isActive()) or lCat ~= 1) and mist.pointInPolygon(lUnit:getPosition().p, polyZone, max_alt) then
3434
+ local lCat = Object.getCategory(lUnit)
3435
+ if lUnit:isExist() == true and ((lCat == 1 and lUnit:isActive()) or lCat ~= 1) and mist.pointInPolygon(lUnit:getPosition().p, polyZone, max_alt) then
3192
3436
  inZoneUnits[#inZoneUnits + 1] = lUnit
3193
3437
  end
3194
3438
  end
@@ -3216,7 +3460,7 @@ function mist.getUnitsInZones(unit_names, zone_names, zone_type)
3216
3460
  for k = 1, #unit_names do
3217
3461
 
3218
3462
  local unit = Unit.getByName(unit_names[k]) or StaticObject.getByName(unit_names[k])
3219
- if unit then
3463
+ if unit and unit:isExist() == true then
3220
3464
  units[#units + 1] = unit
3221
3465
  end
3222
3466
  end
@@ -3233,7 +3477,7 @@ function mist.getUnitsInZones(unit_names, zone_names, zone_type)
3233
3477
  for units_ind = 1, #units do
3234
3478
  local lUnit = units[units_ind]
3235
3479
  local unit_pos = lUnit:getPosition().p
3236
- local lCat = lUnit:getCategory()
3480
+ local lCat = Object.getCategory(lUnit)
3237
3481
  for zones_ind = 1, #zones do
3238
3482
  if zone_type == 'sphere' then --add land height value for sphere zone type
3239
3483
  local alt = land.getHeight({x = zones[zones_ind].x, y = zones[zones_ind].z})
@@ -3280,14 +3524,14 @@ function mist.getUnitsInMovingZones(unit_names, zone_unit_names, radius, zone_ty
3280
3524
 
3281
3525
  for k = 1, #unit_names do
3282
3526
  local unit = Unit.getByName(unit_names[k]) or StaticObject.getByName(unit_names[k])
3283
- if unit then
3527
+ if unit and unit:isExist() == true then
3284
3528
  units[#units + 1] = unit
3285
3529
  end
3286
3530
  end
3287
3531
 
3288
3532
  for k = 1, #zone_unit_names do
3289
3533
  local unit = Unit.getByName(zone_unit_names[k]) or StaticObject.getByName(zone_unit_names[k])
3290
- if unit then
3534
+ if unit and unit:isExist() == true then
3291
3535
  zone_units[#zone_units + 1] = unit
3292
3536
  end
3293
3537
  end
@@ -3296,7 +3540,7 @@ function mist.getUnitsInMovingZones(unit_names, zone_unit_names, radius, zone_ty
3296
3540
 
3297
3541
  for units_ind = 1, #units do
3298
3542
  local lUnit = units[units_ind]
3299
- local lCat = lUnit:getCategory()
3543
+ local lCat = Object.getCategory(lUnit)
3300
3544
  local unit_pos = lUnit:getPosition().p
3301
3545
  for zone_units_ind = 1, #zone_units do
3302
3546
 
@@ -3324,8 +3568,8 @@ function mist.getUnitsLOS(unitset1, altoffset1, unitset2, altoffset2, radius)
3324
3568
  -- get the positions all in one step, saves execution time.
3325
3569
  for unitset1_ind = 1, #unitset1 do
3326
3570
  local unit1 = Unit.getByName(unitset1[unitset1_ind])
3327
- local lCat = unit1:getCategory()
3328
- if unit1 and ((lCat == 1 and unit1:isActive()) or lCat ~= 1) then
3571
+ local lCat = Object.getCategory(unit1)
3572
+ if unit1 and ((lCat == 1 and unit1:isActive()) or lCat ~= 1) and unit:isExist() == true then
3329
3573
  unit_info1[#unit_info1 + 1] = {}
3330
3574
  unit_info1[#unit_info1].unit = unit1
3331
3575
  unit_info1[#unit_info1].pos = unit1:getPosition().p
@@ -3334,8 +3578,8 @@ function mist.getUnitsLOS(unitset1, altoffset1, unitset2, altoffset2, radius)
3334
3578
 
3335
3579
  for unitset2_ind = 1, #unitset2 do
3336
3580
  local unit2 = Unit.getByName(unitset2[unitset2_ind])
3337
- local lCat = unit2:getCategory()
3338
- if unit2 and ((lCat == 1 and unit2:isActive()) or lCat ~= 1) then
3581
+ local lCat = Object.getCategory(unit2)
3582
+ if unit2 and ((lCat == 1 and unit2:isActive()) or lCat ~= 1) and unit:isExist() == true then
3339
3583
  unit_info2[#unit_info2 + 1] = {}
3340
3584
  unit_info2[#unit_info2].unit = unit2
3341
3585
  unit_info2[#unit_info2].pos = unit2:getPosition().p
@@ -3395,7 +3639,7 @@ function mist.getAvgPos(unitNames)
3395
3639
  elseif StaticObject.getByName(unitNames[i]) then
3396
3640
  unit = StaticObject.getByName(unitNames[i])
3397
3641
  end
3398
- if unit then
3642
+ if unit and unit:isExist() == true then
3399
3643
  local pos = unit:getPosition().p
3400
3644
  if pos then -- you never know O.o
3401
3645
  avgX = avgX + pos.x
@@ -3764,7 +4008,7 @@ do -- group functions scope
3764
4008
 
3765
4009
  --- Returns group data table of give group.
3766
4010
  function mist.getCurrentGroupData(gpName)
3767
- local dbData = mist.getGroupData(gpName)
4011
+ local dbData = mist.getGroupData(gpName) or {}
3768
4012
 
3769
4013
  if Group.getByName(gpName) and Group.getByName(gpName):isExist() == true then
3770
4014
  local newGroup = Group.getByName(gpName)
@@ -3800,23 +4044,24 @@ do -- group functions scope
3800
4044
  newData.units[unitNum].callsign = unitData:getCallsign()
3801
4045
  newData.units[unitNum].unitName = uName
3802
4046
  end
3803
-
3804
- newData.units[unitNum].x = unitData:getPosition().p.x
3805
- newData.units[unitNum].y = unitData:getPosition().p.z
4047
+ local pos = unitData:getPosition()
4048
+ newData.units[unitNum].x = pos.p.x
4049
+ newData.units[unitNum].y = pos.p.z
3806
4050
  newData.units[unitNum].point = {x = newData.units[unitNum].x, y = newData.units[unitNum].y}
3807
- newData.units[unitNum].heading = mist.getHeading(unitData, true) -- added to DBs
3808
- newData.units[unitNum].alt = unitData:getPosition().p.y
4051
+ newData.units[unitNum].heading = math.atan2(pos.x.z, pos.x.x)
4052
+ newData.units[unitNum].alt = pos.p.y
3809
4053
  newData.units[unitNum].speed = mist.vec.mag(unitData:getVelocity())
3810
4054
 
3811
4055
  end
3812
4056
 
3813
4057
  return newData
3814
- elseif StaticObject.getByName(gpName) and StaticObject.getByName(gpName):isExist() == true then
4058
+ elseif StaticObject.getByName(gpName) and StaticObject.getByName(gpName):isExist() == true and dbData.units then
3815
4059
  local staticObj = StaticObject.getByName(gpName)
3816
- dbData.units[1].x = staticObj:getPosition().p.x
3817
- dbData.units[1].y = staticObj:getPosition().p.z
3818
- dbData.units[1].alt = staticObj:getPosition().p.y
3819
- dbData.units[1].heading = mist.getHeading(staticObj, true)
4060
+ local pos =staticObj:getPosition()
4061
+ dbData.units[1].x = pos.p.x
4062
+ dbData.units[1].y = pos.p.z
4063
+ dbData.units[1].alt = pos.p.y
4064
+ dbData.units[1].heading = math.atan2(pos.x.z, pos.x.x)
3820
4065
 
3821
4066
  return dbData
3822
4067
  end
@@ -3903,40 +4148,48 @@ do -- group functions scope
3903
4148
  unitId = mist.DBs.MEunitsByName[unitIdent].unitId
3904
4149
  else
3905
4150
  log:error("Unit not found in mist.DBs.MEunitsByName: $1", unitIdent)
4151
+ return {}
3906
4152
  end
3907
- end
3908
- local gpId = mist.DBs.MEunitsById[unitId].groupId
3909
-
3910
- if gpId and unitId then
3911
- for coa_name, coa_data in pairs(env.mission.coalition) do
3912
- if (coa_name == 'red' or coa_name == 'blue') and type(coa_data) == 'table' then
3913
- if coa_data.country then --there is a country table
3914
- for cntry_id, cntry_data in pairs(coa_data.country) do
3915
- for obj_cat_name, obj_cat_data in pairs(cntry_data) do
3916
- if obj_cat_name == "helicopter" or obj_cat_name == "ship" or obj_cat_name == "plane" or obj_cat_name == "vehicle" then -- only these types have points
3917
- if ((type(obj_cat_data) == 'table') and obj_cat_data.group and (type(obj_cat_data.group) == 'table') and (#obj_cat_data.group > 0)) then --there's a group!
3918
- for group_num, group_data in pairs(obj_cat_data.group) do
3919
- if group_data and group_data.groupId == gpId then
3920
- for unitIndex, unitData in pairs(group_data.units) do --group index
3921
- if unitData.unitId == unitId then
3922
- return unitData.payload
3923
- end
3924
- end
3925
- end
3926
- end
3927
- end
3928
- end
3929
- end
3930
- end
3931
- end
3932
- end
3933
- end
4153
+ elseif type(unitIdent) == "number" and not mist.DBs.MEunitsById[unitIdent] then
4154
+ log:error("Unit not found in mist.DBs.MEunitsBId: $1", unitIdent)
4155
+ return {}
4156
+ end
4157
+ local ref = mist.DBs.MEunitsById[unitId]
4158
+
4159
+ if ref then
4160
+ local gpId = mist.DBs.MEunitsById[unitId].groupId
4161
+
4162
+ if gpId and unitId then
4163
+ for coa_name, coa_data in pairs(env.mission.coalition) do
4164
+ if (coa_name == 'red' or coa_name == 'blue') and type(coa_data) == 'table' then
4165
+ if coa_data.country then --there is a country table
4166
+ for cntry_id, cntry_data in pairs(coa_data.country) do
4167
+ for obj_cat_name, obj_cat_data in pairs(cntry_data) do
4168
+ if obj_cat_name == "helicopter" or obj_cat_name == "ship" or obj_cat_name == "plane" or obj_cat_name == "vehicle" then -- only these types have points
4169
+ if ((type(obj_cat_data) == 'table') and obj_cat_data.group and (type(obj_cat_data.group) == 'table') and (#obj_cat_data.group > 0)) then --there's a group!
4170
+ for group_num, group_data in pairs(obj_cat_data.group) do
4171
+ if group_data and group_data.groupId == gpId then
4172
+ for unitIndex, unitData in pairs(group_data.units) do --group index
4173
+ if unitData.unitId == unitId then
4174
+ return unitData.payload
4175
+ end
4176
+ end
4177
+ end
4178
+ end
4179
+ end
4180
+ end
4181
+ end
4182
+ end
4183
+ end
4184
+ end
4185
+ end
4186
+ end
3934
4187
  else
3935
4188
  log:error('Need string or number. Got: $1', type(unitIdent))
3936
- return false
4189
+ return {}
3937
4190
  end
3938
4191
  log:warn("Couldn't find payload for unit: $1", unitIdent)
3939
- return
4192
+ return {}
3940
4193
  end
3941
4194
 
3942
4195
  function mist.getGroupPayload(groupIdent)
@@ -3946,6 +4199,7 @@ do -- group functions scope
3946
4199
  gpId = mist.DBs.MEgroupsByName[groupIdent].groupId
3947
4200
  else
3948
4201
  log:error('$1 not found in mist.DBs.MEgroupsByName', groupIdent)
4202
+ return {}
3949
4203
  end
3950
4204
  end
3951
4205
 
@@ -3975,10 +4229,10 @@ do -- group functions scope
3975
4229
  end
3976
4230
  else
3977
4231
  log:error('Need string or number. Got: $1', type(groupIdent))
3978
- return false
4232
+ return {}
3979
4233
  end
3980
4234
  log:warn("Couldn't find payload for group: $1", groupIdent)
3981
- return
4235
+ return {}
3982
4236
  end
3983
4237
 
3984
4238
  function mist.getGroupTable(groupIdent)
@@ -4001,7 +4255,10 @@ do -- group functions scope
4001
4255
  if ((type(obj_cat_data) == 'table') and obj_cat_data.group and (type(obj_cat_data.group) == 'table') and (#obj_cat_data.group > 0)) then --there's a group!
4002
4256
  for group_num, group_data in pairs(obj_cat_data.group) do
4003
4257
  if group_data and group_data.groupId == gpId then
4004
- return group_data
4258
+ local gp = mist.utils.deepCopy(group_data)
4259
+ gp.category = obj_cat_name
4260
+ gp.country = cntry_data.id
4261
+ return gp
4005
4262
  end
4006
4263
  end
4007
4264
  end
@@ -4033,7 +4290,7 @@ do -- group functions scope
4033
4290
  elseif vars.groupName then
4034
4291
  gpName = vars.groupName
4035
4292
  else
4036
- log:error('Missing field groupName or gpName in variable table')
4293
+ log:error('Missing field groupName or gpName in variable table. Table: $1', vars)
4037
4294
  end
4038
4295
 
4039
4296
  --[[New vars to add, mostly for when called via inZone functions
@@ -5167,21 +5424,21 @@ do -- mist.util scope
5167
5424
  -- borrowed from slmod
5168
5425
  -- @param var variable to serialize
5169
5426
  -- @treturn string variable serialized to string
5170
- function mist.utils.basicSerialize(var)
5171
- if var == nil then
5172
- return "\"\""
5173
- else
5174
- if ((type(var) == 'number') or
5175
- (type(var) == 'boolean') or
5176
- (type(var) == 'function') or
5177
- (type(var) == 'table') or
5178
- (type(var) == 'userdata') ) then
5179
- return tostring(var)
5180
- elseif type(var) == 'string' then
5181
- var = string.format('%q', var)
5182
- return var
5183
- end
5184
- end
5427
+ function mist.utils.basicSerialize(var)
5428
+ if var == nil then
5429
+ return "\"\""
5430
+ else
5431
+ if ((type(var) == 'number') or
5432
+ (type(var) == 'boolean') or
5433
+ (type(var) == 'function') or
5434
+ (type(var) == 'table') or
5435
+ (type(var) == 'userdata') ) then
5436
+ return tostring(var)
5437
+ elseif type(var) == 'string' then
5438
+ var = string.format('%q', var)
5439
+ return var
5440
+ end
5441
+ end
5185
5442
  end
5186
5443
 
5187
5444
  --- Serialize value
@@ -5332,6 +5589,123 @@ function mist.utils.oneLineSerialize(tbl)
5332
5589
  end
5333
5590
  end
5334
5591
 
5592
+ function mist.utils.tableShowSorted(tbls, v)
5593
+ local vars = v or {}
5594
+ local loc = vars.loc or ""
5595
+ local indent = vars.indent or ""
5596
+ local tableshow_tbls = vars.tableshow_tbls or {}
5597
+ local tbl = tbls or {}
5598
+
5599
+ if type(tbl) == 'table' then --function only works for tables!
5600
+ tableshow_tbls[tbl] = loc
5601
+
5602
+ local tbl_str = {}
5603
+
5604
+ tbl_str[#tbl_str + 1] = indent .. '{\n'
5605
+
5606
+ local sorted = {}
5607
+ local function byteCompare(str1, str2)
5608
+ local shorter = string.len(str1)
5609
+ if shorter > string.len(str2) then
5610
+ shorter = string.len(str2)
5611
+ end
5612
+ for i = 1, shorter do
5613
+ local b1 = string.byte(str1, i)
5614
+ local b2 = string.byte(str2, i)
5615
+
5616
+ if b1 < b2 then
5617
+ return true
5618
+ elseif b1 > b2 then
5619
+ return false
5620
+ end
5621
+
5622
+ end
5623
+ return false
5624
+ end
5625
+ for ind, val in pairs(tbl) do -- serialize its fields
5626
+ local indS = tostring(ind)
5627
+ local ins = {ind = indS, val = val}
5628
+ local index
5629
+ if #sorted > 0 then
5630
+ local found = false
5631
+ for i = 1, #sorted do
5632
+ if byteCompare(indS, tostring(sorted[i].ind)) == true then
5633
+ index = i
5634
+ break
5635
+ end
5636
+
5637
+ end
5638
+ end
5639
+ if index then
5640
+ table.insert(sorted, index, ins)
5641
+ else
5642
+ table.insert(sorted, ins)
5643
+ end
5644
+
5645
+ end
5646
+ --log:warn(sorted)
5647
+ for i = 1, #sorted do
5648
+ local ind = sorted[i].ind
5649
+ local val = sorted[i].val
5650
+
5651
+ if type(ind) == "number" then
5652
+ tbl_str[#tbl_str + 1] = indent
5653
+ tbl_str[#tbl_str + 1] = loc .. '['
5654
+ tbl_str[#tbl_str + 1] = tostring(ind)
5655
+ tbl_str[#tbl_str + 1] = '] = '
5656
+ else
5657
+ tbl_str[#tbl_str + 1] = indent
5658
+ tbl_str[#tbl_str + 1] = loc .. '['
5659
+ tbl_str[#tbl_str + 1] = mist.utils.basicSerialize(ind)
5660
+ tbl_str[#tbl_str + 1] = '] = '
5661
+ end
5662
+
5663
+ if ((type(val) == 'number') or (type(val) == 'boolean')) then
5664
+ tbl_str[#tbl_str + 1] = tostring(val)
5665
+ tbl_str[#tbl_str + 1] = ',\n'
5666
+ elseif type(val) == 'string' then
5667
+ tbl_str[#tbl_str + 1] = mist.utils.basicSerialize(val)
5668
+ tbl_str[#tbl_str + 1] = ',\n'
5669
+ elseif type(val) == 'nil' then -- won't ever happen, right?
5670
+ tbl_str[#tbl_str + 1] = 'nil,\n'
5671
+ elseif type(val) == 'table' then
5672
+ if tableshow_tbls[val] then
5673
+ tbl_str[#tbl_str + 1] = ' already defined: ' .. tableshow_tbls[val] .. ',\n'
5674
+ else
5675
+ tableshow_tbls[val] = loc .. '["' .. ind .. '"]'
5676
+ --tbl_str[#tbl_str + 1] = tostring(val) .. ' '
5677
+ tbl_str[#tbl_str + 1] = mist.utils.tableShowSorted(val, {loc = loc .. '["' .. ind .. '"]', indent = indent .. ' ', tableshow_tbls = tableshow_tbls})
5678
+ tbl_str[#tbl_str + 1] = ',\n'
5679
+ end
5680
+ elseif type(val) == 'function' then
5681
+ if debug and debug.getinfo then
5682
+ local fcnname = tostring(val)
5683
+ local info = debug.getinfo(val, "S")
5684
+ if info.what == "C" then
5685
+ tbl_str[#tbl_str + 1] = ', C function\n'
5686
+ else
5687
+ if (string.sub(info.source, 1, 2) == [[./]]) then
5688
+ tbl_str[#tbl_str + 1] = string.format('%q', 'function, defined in (' .. '-' .. info.lastlinedefined .. ')' .. info.source) ..',\n'
5689
+ else
5690
+ tbl_str[#tbl_str + 1] = string.format('%q', 'function, defined in (' .. '-' .. info.lastlinedefined .. ')') ..',\n'
5691
+ end
5692
+ end
5693
+
5694
+ else
5695
+ tbl_str[#tbl_str + 1] = 'a function,\n'
5696
+ end
5697
+ else
5698
+ tbl_str[#tbl_str + 1] = 'unable to serialize value type ' .. mist.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind)
5699
+ end
5700
+ end
5701
+
5702
+ tbl_str[#tbl_str + 1] = indent .. '}'
5703
+ return table.concat(tbl_str)
5704
+ end
5705
+
5706
+
5707
+ end
5708
+
5335
5709
  --- Returns table in a easy readable string representation.
5336
5710
  -- this function is not meant for serialization because it uses
5337
5711
  -- newlines for better readability.
@@ -5351,7 +5725,7 @@ function mist.utils.tableShow(tbl, loc, indent, tableshow_tbls) --based on seria
5351
5725
 
5352
5726
  tbl_str[#tbl_str + 1] = indent .. '{\n'
5353
5727
 
5354
- for ind,val in pairs(tbl) do -- serialize its fields
5728
+ for ind, val in pairs(tbl) do
5355
5729
  if type(ind) == "number" then
5356
5730
  tbl_str[#tbl_str + 1] = indent
5357
5731
  tbl_str[#tbl_str + 1] = loc .. '['
@@ -5451,10 +5825,10 @@ do -- mist.debug scope
5451
5825
  g.country.by_idx = nil
5452
5826
  g.country.by_country = nil
5453
5827
 
5454
- f:write(mist.utils.tableShow(g))
5828
+ f:write(mist.utils.tableShowSorted(g))
5455
5829
  else
5456
5830
 
5457
- f:write(mist.utils.tableShow(_G))
5831
+ f:write(mist.utils.tableShowSorted(_G))
5458
5832
  end
5459
5833
  f:close()
5460
5834
  log:info('Wrote debug data to $1', fdir)
@@ -5906,7 +6280,7 @@ unitTableDef = table or nil
5906
6280
  local num_in_zone = 0
5907
6281
  for i = 1, #units do
5908
6282
  local unit = Unit.getByName(units[i]) or StaticObject.getByName(units[i])
5909
- if unit then
6283
+ if unit and unit:isExist() == true then
5910
6284
  local pos = unit:getPosition().p
5911
6285
  if mist.pointInPolygon(pos, zone, maxalt) then
5912
6286
  num_in_zone = num_in_zone + 1
@@ -6368,7 +6742,8 @@ do -- mist.msg scope
6368
6742
  local caSlots = false
6369
6743
  local caMSGtoGroup = false
6370
6744
  local anyUpdate = false
6371
- local lastMessageTime = nil
6745
+ local anySound = false
6746
+ local lastMessageTime = math.huge
6372
6747
 
6373
6748
  if env.mission.groundControl then -- just to be sure?
6374
6749
  for index, value in pairs(env.mission.groundControl) do
@@ -6390,12 +6765,12 @@ do -- mist.msg scope
6390
6765
  end
6391
6766
 
6392
6767
  local function mistdisplayV5()
6393
- --log:warn("mistdisplayV5: $1", timer.getTime())
6768
+ log:warn("mistdisplayV5: $1", timer.getTime())
6394
6769
 
6395
6770
  local clearView = true
6396
6771
  if #messageList > 0 then
6397
- --log:warn('Updates: $1', anyUpdate)
6398
- if anyUpdate == true then
6772
+ log:warn('Updates: $1', anyUpdate)
6773
+ if anyUpdate == true or anySound == true then
6399
6774
  local activeClients = {}
6400
6775
 
6401
6776
  for clientId, clientData in pairs(mist.DBs.humansById) do
@@ -6403,7 +6778,7 @@ do -- mist.msg scope
6403
6778
  activeClients[clientData.groupId] = clientData.groupName
6404
6779
  end
6405
6780
  end
6406
- anyUpdate = false
6781
+
6407
6782
  if displayActive == false then
6408
6783
  displayActive = true
6409
6784
  end
@@ -6412,21 +6787,24 @@ do -- mist.msg scope
6412
6787
  local msgTableSound = {}
6413
6788
  local curTime = timer.getTime()
6414
6789
  for mInd, messageData in pairs(messageList) do
6415
- --log:warn(messageData)
6790
+ log:warn(messageData)
6416
6791
  if messageData.displayTill < curTime then
6792
+ log:warn('remove')
6417
6793
  messageData:remove() -- now using the remove/destroy function.
6418
6794
  else
6419
6795
  if messageData.displayedFor then
6420
6796
  messageData.displayedFor = curTime - messageData.addedAt
6421
6797
  end
6422
- local nextSound = 1000
6798
+
6423
6799
  local soundIndex = 0
6424
-
6800
+ local refSound = 100000
6425
6801
  if messageData.multSound and #messageData.multSound > 0 then
6802
+ anySound = true
6426
6803
  for index, sData in pairs(messageData.multSound) do
6427
- if sData.time <= messageData.displayedFor and sData.played == false and sData.time < nextSound then -- find index of the next sound to be played
6428
- nextSound = sData.time
6804
+ if sData.time <= messageData.displayedFor and sData.played == false and sData.time < refSound then -- find index of the next sound to be played
6805
+ refSound = sData.time
6429
6806
  soundIndex = index
6807
+
6430
6808
  end
6431
6809
  end
6432
6810
  if soundIndex ~= 0 then
@@ -6471,20 +6849,21 @@ do -- mist.msg scope
6471
6849
 
6472
6850
  end
6473
6851
  ------- new display
6852
+ if anyUpdate == true then
6853
+ if caSlots == true and caMSGtoGroup == false then
6854
+ if msgTableText.RED then
6855
+ trigger.action.outTextForCoalition(coalition.side.RED, table.concat(msgTableText.RED.text), msgTableText.RED.displayTime, clearView)
6474
6856
 
6475
- if caSlots == true and caMSGtoGroup == false then
6476
- if msgTableText.RED then
6477
- trigger.action.outTextForCoalition(coalition.side.RED, table.concat(msgTableText.RED.text), msgTableText.RED.displayTime, clearView)
6478
-
6479
- end
6480
- if msgTableText.BLUE then
6481
- trigger.action.outTextForCoalition(coalition.side.BLUE, table.concat(msgTableText.BLUE.text), msgTableText.BLUE.displayTime, clearView)
6857
+ end
6858
+ if msgTableText.BLUE then
6859
+ trigger.action.outTextForCoalition(coalition.side.BLUE, table.concat(msgTableText.BLUE.text), msgTableText.BLUE.displayTime, clearView)
6860
+ end
6482
6861
  end
6483
- end
6484
6862
 
6485
- for index, msgData in pairs(msgTableText) do
6486
- if type(index) == 'number' then -- its a groupNumber
6487
- trigger.action.outTextForGroup(index, table.concat(msgData.text), msgData.displayTime, clearView)
6863
+ for index, msgData in pairs(msgTableText) do
6864
+ if type(index) == 'number' then -- its a groupNumber
6865
+ trigger.action.outTextForGroup(index, table.concat(msgData.text), msgData.displayTime, clearView)
6866
+ end
6488
6867
  end
6489
6868
  end
6490
6869
  --- new audio
@@ -6502,7 +6881,10 @@ do -- mist.msg scope
6502
6881
  end
6503
6882
  end
6504
6883
 
6505
- end
6884
+ end
6885
+
6886
+ anyUpdate = false
6887
+ anySound = false
6506
6888
 
6507
6889
  else
6508
6890
  mist.removeFunction(displayFuncId)
@@ -6676,6 +7058,7 @@ end]]
6676
7058
  new.displayTill = timer.getTime() + vars.displayTime
6677
7059
  new.name = vars.name -- ID to overwrite the older message (if it exists) Basically it replaces a message that is displayed with new text.
6678
7060
  new.addedAt = timer.getTime()
7061
+ new.clearView = vars.clearView or true
6679
7062
  --log:warn('New Message: $1', new.text)
6680
7063
 
6681
7064
  if vars.multSound and vars.multSound[1] then
@@ -6764,7 +7147,6 @@ end]]
6764
7147
  messageList[i].displayTill = timer.getTime() + messageList[i].displayTime
6765
7148
  messageList[i].displayedFor = 0
6766
7149
  messageList[i].addedAt = timer.getTime()
6767
- messageList[i].sound = new.sound
6768
7150
  messageList[i].text = new.text
6769
7151
  messageList[i].msgFor = new.msgFor
6770
7152
  messageList[i].multSound = new.multSound
@@ -6789,7 +7171,7 @@ end]]
6789
7171
 
6790
7172
  if displayActive == false then
6791
7173
  displayActive = true
6792
- displayFuncId = mist.scheduleFunction(mistdisplayV5, {}, timer.getTime() + messageDisplayRate, messageDisplayRate)
7174
+ displayFuncId = mist.scheduleFunction(mistdisplayV4, {}, timer.getTime() + messageDisplayRate, messageDisplayRate)
6793
7175
  end
6794
7176
 
6795
7177
  return messageID
@@ -7268,7 +7650,7 @@ do
7268
7650
  local altNames = {['poly'] = 7, ['lines'] = 1, ['polygon'] = 7 }
7269
7651
 
7270
7652
  local function draw(s)
7271
- --log:warn(s)
7653
+ --log:warn(s)
7272
7654
  if type(s) == 'table' then
7273
7655
  local mType = s.markType
7274
7656
  if mType == 'panel' then
@@ -7373,7 +7755,7 @@ do
7373
7755
  --log:info('create maker DB: $1', e.idx)
7374
7756
  mist.DBs.markList[e.idx] = {time = e.time, pos = e.pos, groupId = e.groupId, mType = 'panel', text = e.text, markId = e.idx, coalition = e.coalition}
7375
7757
  if e.unit then
7376
- mist.DBs.markList[e.idx].unit = e.initiaor:getName()
7758
+ mist.DBs.markList[e.idx].unit = e.intiator:getName()
7377
7759
  end
7378
7760
  --log:info(mist.marker.list[e.idx])
7379
7761
  end
@@ -7472,7 +7854,7 @@ do
7472
7854
  local coa = -1
7473
7855
  local usedId = 0
7474
7856
 
7475
-
7857
+ pos = mist.utils.deepCopy(pos)
7476
7858
 
7477
7859
  if id then
7478
7860
  if type(id) ~= 'number' then
@@ -8594,7 +8976,7 @@ do -- group tasks scope
8594
8976
  break
8595
8977
  end
8596
8978
  if j == 100 then
8597
- newCoord = mist.getRandPointInCircle(avg, 50000)
8979
+ newCoord = mist.getRandPointInCircle(avg, radius)
8598
8980
  log:warn("Failed to find point in poly; Giving random point from center of the poly")
8599
8981
  end
8600
8982
  end
@@ -8602,13 +8984,13 @@ do -- group tasks scope
8602
8984
  end
8603
8985
 
8604
8986
  function mist.getWindBearingAndVel(p)
8605
- local point = mist.utils.makeVec3(o)
8987
+ local point = mist.utils.makeVec3(p)
8606
8988
  local gLevel = land.getHeight({x = point.x, y = point.z})
8607
8989
  if point.y <= gLevel then
8608
8990
  point.y = gLevel + 10
8609
8991
  end
8610
8992
  local t = atmosphere.getWind(point)
8611
- local bearing = math.tan(t.z/t.x)
8993
+ local bearing = math.atan2(t.z, t.x)
8612
8994
  local vel = math.sqrt(t.x^2 + t.z^2)
8613
8995
  return bearing, vel
8614
8996
 
@@ -8788,36 +9170,54 @@ do -- group tasks scope
8788
9170
  end
8789
9171
 
8790
9172
  function mist.getLeadPos(group)
8791
- if type(group) == 'string' then -- group name
8792
- group = Group.getByName(group)
8793
- end
9173
+ local gObj
9174
+ if type(group) == 'string' then -- group name
9175
+ gObj = Group.getByName(group)
9176
+ elseif type(group) == "table" then
9177
+ gObj = group
9178
+ end
8794
9179
 
8795
- local units = group:getUnits()
8796
-
8797
- local leader = units[1]
8798
- if Unit.getLife(leader) == 0 or not Unit.isExist(leader) then -- SHOULD be good, but if there is a bug, this code future-proofs it then.
8799
- local lowestInd = math.huge
8800
- for ind, unit in pairs(units) do
8801
- if Unit.isExist(unit) and ind < lowestInd then
8802
- lowestInd = ind
8803
- return unit:getPosition().p
8804
- end
8805
- end
8806
- end
8807
- if leader and Unit.isExist(leader) then -- maybe a little too paranoid now...
8808
- return leader:getPosition().p
8809
- end
9180
+ if gObj then
9181
+ local units = gObj:getUnits()
9182
+
9183
+ local leader = units[1]
9184
+ if leader then
9185
+ if Unit.isExist(leader) then
9186
+ return leader:getPoint()
9187
+ elseif #units > 1 then
9188
+ for i = 2, #units do
9189
+ if Unit.isExist(units[i]) then
9190
+ return units[i]:getPoint()
9191
+ end
9192
+ end
9193
+
9194
+ end
9195
+ end
9196
+ end
9197
+ log:error("Group passed to mist.getLeadPos might be dead: $1", group)
8810
9198
  end
8811
9199
 
8812
9200
  function mist.groupIsDead(groupName) -- copy more or less from on station
8813
- if Group.getByName(groupName) then
8814
- local gp = Group.getByName(groupName)
9201
+ local gp = Group.getByName(groupName)
9202
+ if gp then
8815
9203
  if #gp:getUnits() > 0 or gp:isExist() == true then
8816
9204
  return false
8817
9205
  end
8818
9206
  end
8819
9207
  return true
8820
9208
  end
9209
+
9210
+ function mist.pointInZone(point, zone)
9211
+ local ref = mist.utils.deepCopy(zone)
9212
+ if type(zone) == 'string' then
9213
+ ref = mist.DBs.zonesByName[zone]
9214
+ end
9215
+ if ref.verticies then
9216
+ return mist.pointInPolygon(point, ref.verticies)
9217
+ else
9218
+ return mist.utils.get2DDist(point, ref.point) < ref.radius
9219
+ end
9220
+ end
8821
9221
 
8822
9222
  end
8823
9223
 
@@ -8937,10 +9337,10 @@ do -- mist.Logger scope
8937
9337
  -- @usage -- log everything
8938
9338
  --myLogger:setLevel(3)
8939
9339
  function mist.Logger:setLevel(level)
8940
- if not level then
8941
- self.level = 2
8942
- else
9340
+ self.level = 2
9341
+ if level then
8943
9342
  if type(level) == 'string' then
9343
+ level = string.lower(level)
8944
9344
  if level == 'none' or level == 'off' then
8945
9345
  self.level = 0
8946
9346
  elseif level == 'error' then
@@ -8952,8 +9352,6 @@ do -- mist.Logger scope
8952
9352
  end
8953
9353
  elseif type(level) == 'number' then
8954
9354
  self.level = level
8955
- else
8956
- self.level = 2
8957
9355
  end
8958
9356
  end
8959
9357
  end
@@ -9025,6 +9423,30 @@ do -- mist.Logger scope
9025
9423
  end
9026
9424
  end
9027
9425
  end
9426
+ --- Logs a message, disregarding the log level and displays a message out text box.
9427
+ -- @tparam string text the text with keywords to substitute.
9428
+ -- @param ... variables to be used for substitution.
9429
+ -- @usage myLogger:msg("Always logged!")
9430
+
9431
+ function mist.Logger:echo(text, ...)
9432
+ text = formatText(text, unpack(arg))
9433
+ if text:len() > 4000 then
9434
+ local texts = splitText(text)
9435
+ for i = 1, #texts do
9436
+ if i == 1 then
9437
+ env.info(self.tag .. '|' .. texts[i])
9438
+ else
9439
+ env.info(texts[i])
9440
+ end
9441
+ end
9442
+ else
9443
+ env.info(self.tag .. '|' .. text)
9444
+ end
9445
+ trigger.action.outText(text, 30)
9446
+ end
9447
+
9448
+
9449
+
9028
9450
 
9029
9451
  --- Logs a warning.
9030
9452
  -- logs a message prefixed with this loggers tag to dcs.log as