@jtff/miztemplate-lib 3.2.3 → 3.3.0

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.
@@ -1,4 +1,4 @@
1
- env.info('*** MOOSE GITHUB Commit Hash ID: 2024-05-04T14:54:20+02:00-044fb66ca064687a743791e5a4a5d02c109ca9c1 ***')
1
+ env.info('*** MOOSE GITHUB Commit Hash ID: 2024-08-12T11:39:03+02:00-a54944b0214abee2fc0206e8a246bbe9f36c41d3 ***')
2
2
  if not MOOSE_DEVELOPMENT_FOLDER then
3
3
  MOOSE_DEVELOPMENT_FOLDER='Scripts'
4
4
  end
@@ -1044,7 +1044,9 @@ TheChannel="TheChannel",
1044
1044
  Syria="Syria",
1045
1045
  MarianaIslands="MarianaIslands",
1046
1046
  Falklands="Falklands",
1047
- Sinai="SinaiMap"
1047
+ Sinai="SinaiMap",
1048
+ Kola="Kola",
1049
+ Afghanistan="Afghanistan",
1048
1050
  }
1049
1051
  CALLSIGN={
1050
1052
  Aircraft={
@@ -1165,6 +1167,44 @@ Trash=10,
1165
1167
  Cargo=11,
1166
1168
  Ascot=12,
1167
1169
  },
1170
+ AH64={
1171
+ Army_Air=9,
1172
+ Apache=10,
1173
+ Crow=11,
1174
+ Sioux=12,
1175
+ Gatling=13,
1176
+ Gunslinger=14,
1177
+ Hammerhead=15,
1178
+ Bootleg=16,
1179
+ Palehorse=17,
1180
+ Carnivor=18,
1181
+ Saber=19,
1182
+ },
1183
+ Kiowa={
1184
+ Anvil=1,
1185
+ Azrael=2,
1186
+ BamBam=3,
1187
+ Blackjack=4,
1188
+ Bootleg=5,
1189
+ BurninStogie=6,
1190
+ Chaos=7,
1191
+ CrazyHorse=8,
1192
+ Crusader=9,
1193
+ Darkhorse=10,
1194
+ Eagle=11,
1195
+ Lighthorse=12,
1196
+ Mustang=13,
1197
+ Outcast=14,
1198
+ Palehorse=15,
1199
+ Pegasus=16,
1200
+ Pistol=17,
1201
+ Roughneck=18,
1202
+ Saber=19,
1203
+ Shamus=20,
1204
+ Spur=21,
1205
+ Stetson=22,
1206
+ Wrath=23,
1207
+ },
1168
1208
  }
1169
1209
  UTILS={
1170
1210
  _MarkID=1
@@ -1315,6 +1355,11 @@ return s
1315
1355
  end
1316
1356
  end
1317
1357
  end
1358
+ function UTILS.TableLength(T)
1359
+ local count=0
1360
+ for _ in pairs(T or{})do count=count+1 end
1361
+ return count
1362
+ end
1318
1363
  function UTILS.PrintTableToLog(table,indent,noprint)
1319
1364
  local text="\n"
1320
1365
  if not table or type(table)~="table"then
@@ -1324,7 +1369,7 @@ end
1324
1369
  if not indent then indent=0 end
1325
1370
  for k,v in pairs(table)do
1326
1371
  if string.find(k," ")then k='"'..k..'"'end
1327
- if type(v)=="table"then
1372
+ if type(v)=="table"and UTILS.TableLength(v)>0 then
1328
1373
  if not noprint then
1329
1374
  env.info(string.rep(" ",indent)..tostring(k).." = {")
1330
1375
  end
@@ -2070,6 +2115,10 @@ elseif map==DCSMAP.Falklands then
2070
2115
  declination=12
2071
2116
  elseif map==DCSMAP.Sinai then
2072
2117
  declination=4.8
2118
+ elseif map==DCSMAP.Kola then
2119
+ declination=15
2120
+ elseif map==DCSMAP.Afghanistan then
2121
+ declination=3
2073
2122
  else
2074
2123
  declination=0
2075
2124
  end
@@ -2207,6 +2256,16 @@ if value==Callsign then
2207
2256
  return name
2208
2257
  end
2209
2258
  end
2259
+ for name,value in pairs(CALLSIGN.AH64)do
2260
+ if value==Callsign then
2261
+ return name
2262
+ end
2263
+ end
2264
+ for name,value in pairs(CALLSIGN.Kiowa)do
2265
+ if value==Callsign then
2266
+ return name
2267
+ end
2268
+ end
2210
2269
  return"Ghostrider"
2211
2270
  end
2212
2271
  function UTILS.GMTToLocalTimeDifference()
@@ -2229,6 +2288,10 @@ elseif theatre==DCSMAP.Falklands then
2229
2288
  return-3
2230
2289
  elseif theatre==DCSMAP.Sinai then
2231
2290
  return 2
2291
+ elseif theatre==DCSMAP.Kola then
2292
+ return 3
2293
+ elseif theatre==DCSMAP.Afghanistan then
2294
+ return 4.5
2232
2295
  else
2233
2296
  BASE:E(string.format("ERROR: Unknown Map %s in UTILS.GMTToLocal function. Returning 0",tostring(theatre)))
2234
2297
  return 0
@@ -2413,6 +2476,14 @@ if type_name=="MH-60R"and(unit:getDrawArgumentValue(403)>0 or unit:getDrawArgume
2413
2476
  BASE:T(unit_name.." cargo door is open")
2414
2477
  return true
2415
2478
  end
2479
+ if type_name=="OH-58D"and(unit:getDrawArgumentValue(35)>0 or unit:getDrawArgumentValue(421)==-1)then
2480
+ BASE:T(unit_name.." cargo door is open")
2481
+ return true
2482
+ end
2483
+ if type_name=="CH-47Fbl1"and(unit:getDrawArgumentValue(86)>0.5)then
2484
+ BASE:T(unit_name.." rear cargo door is open")
2485
+ return true
2486
+ end
2416
2487
  return false
2417
2488
  end
2418
2489
  return nil
@@ -2688,6 +2759,9 @@ local group=_group
2688
2759
  if group and group:IsAlive()then
2689
2760
  local name=group:GetName()
2690
2761
  local template=string.gsub(name,"-(.+)$","")
2762
+ if string.find(name,"AID")then
2763
+ template=string.gsub(name,"(.AID.%d+$","")
2764
+ end
2691
2765
  if string.find(template,"#")then
2692
2766
  template=string.gsub(name,"#(%d+)$","")
2693
2767
  end
@@ -3498,6 +3572,95 @@ end
3498
3572
  local clockPos=math.ceil((relativeAngle%360)/30)
3499
3573
  return clockPos.." o'clock"
3500
3574
  end
3575
+ function UTILS.MGRSStringToSRSFriendly(Text,Slow)
3576
+ local Text=string.gsub(Text,"MGRS ","")
3577
+ Text=string.gsub(Text,"%s+","")
3578
+ Text=string.gsub(Text,"([%a%d])","%1;")
3579
+ Text=string.gsub(Text,"A","Alpha")
3580
+ Text=string.gsub(Text,"B","Bravo")
3581
+ Text=string.gsub(Text,"C","Charlie")
3582
+ Text=string.gsub(Text,"D","Delta")
3583
+ Text=string.gsub(Text,"E","Echo")
3584
+ Text=string.gsub(Text,"F","Foxtrot")
3585
+ Text=string.gsub(Text,"G","Golf")
3586
+ Text=string.gsub(Text,"H","Hotel")
3587
+ Text=string.gsub(Text,"I","India")
3588
+ Text=string.gsub(Text,"J","Juliett")
3589
+ Text=string.gsub(Text,"K","Kilo")
3590
+ Text=string.gsub(Text,"L","Lima")
3591
+ Text=string.gsub(Text,"M","Mike")
3592
+ Text=string.gsub(Text,"N","November")
3593
+ Text=string.gsub(Text,"O","Oscar")
3594
+ Text=string.gsub(Text,"P","Papa")
3595
+ Text=string.gsub(Text,"Q","Quebec")
3596
+ Text=string.gsub(Text,"R","Romeo")
3597
+ Text=string.gsub(Text,"S","Sierra")
3598
+ Text=string.gsub(Text,"T","Tango")
3599
+ Text=string.gsub(Text,"U","Uniform")
3600
+ Text=string.gsub(Text,"V","Victor")
3601
+ Text=string.gsub(Text,"W","Whiskey")
3602
+ Text=string.gsub(Text,"X","Xray")
3603
+ Text=string.gsub(Text,"Y","Yankee")
3604
+ Text=string.gsub(Text,"Z","Zulu")
3605
+ Text=string.gsub(Text,"0","zero")
3606
+ Text=string.gsub(Text,"9","niner")
3607
+ if Slow then
3608
+ Text='<prosody rate="slow">'..Text..'</prosody>'
3609
+ end
3610
+ Text="MGRS;"..Text
3611
+ return Text
3612
+ end
3613
+ function UTILS.ReadCSV(filename)
3614
+ if not UTILS.FileExists(filename)then
3615
+ env.error("File does not exist")
3616
+ return nil
3617
+ end
3618
+ local function _loadfile(filename)
3619
+ local f=io.open(filename,"rb")
3620
+ if f then
3621
+ local data=f:read("*all")
3622
+ f:close()
3623
+ return data
3624
+ else
3625
+ BASE:E(string.format("WARNING: Could read data from file %s!",tostring(filename)))
3626
+ return nil
3627
+ end
3628
+ end
3629
+ local data=_loadfile(filename)
3630
+ local lines=UTILS.Split(data,"\n")
3631
+ for _,line in pairs(lines)do
3632
+ line=string.gsub(line,"[\n\r]","")
3633
+ end
3634
+ local sep=";"
3635
+ local columns=UTILS.Split(lines[1],sep)
3636
+ table.remove(lines,1)
3637
+ local csvdata={}
3638
+ for i,line in pairs(lines)do
3639
+ line=string.gsub(line,"[\n\r]","")
3640
+ local row={}
3641
+ for j,value in pairs(UTILS.Split(line,sep))do
3642
+ local key=string.gsub(columns[j],"[\n\r]","")
3643
+ row[key]=value
3644
+ end
3645
+ table.insert(csvdata,row)
3646
+ end
3647
+ return csvdata
3648
+ end
3649
+ function UTILS.LCGRandomSeed(seed)
3650
+ UTILS.lcg={
3651
+ seed=seed or math.random(1,2^32-1),
3652
+ a=1664525,
3653
+ c=1013904223,
3654
+ m=2^32
3655
+ }
3656
+ end
3657
+ function UTILS.LCGRandom()
3658
+ if UTILS.lcg==nil then
3659
+ UTILS.LCGRandomSeed()
3660
+ end
3661
+ UTILS.lcg.seed=(UTILS.lcg.a*UTILS.lcg.seed+UTILS.lcg.c)%UTILS.lcg.m
3662
+ return UTILS.lcg.seed/UTILS.lcg.m
3663
+ end
3501
3664
  PROFILER={
3502
3665
  ClassName="PROFILER",
3503
3666
  Counters={},
@@ -4789,7 +4952,7 @@ message.volume=Volume
4789
4952
  self:SendTable(message)
4790
4953
  return self
4791
4954
  end
4792
- local _TraceOnOff=true
4955
+ local _TraceOnOff=false
4793
4956
  local _TraceLevel=1
4794
4957
  local _TraceAll=false
4795
4958
  local _TraceClass={}
@@ -5143,7 +5306,7 @@ end
5143
5306
  end
5144
5307
  end
5145
5308
  function BASE:F(Arguments)
5146
- if BASE.Debug and _TraceOnOff then
5309
+ if BASE.Debug and _TraceOnOff==true then
5147
5310
  local DebugInfoCurrent=BASE.Debug.getinfo(2,"nl")
5148
5311
  local DebugInfoFrom=BASE.Debug.getinfo(3,"l")
5149
5312
  if _TraceLevel>=1 then
@@ -5152,7 +5315,7 @@ end
5152
5315
  end
5153
5316
  end
5154
5317
  function BASE:F2(Arguments)
5155
- if BASE.Debug and _TraceOnOff then
5318
+ if BASE.Debug and _TraceOnOff==true and _TraceLevel>=2 then
5156
5319
  local DebugInfoCurrent=BASE.Debug.getinfo(2,"nl")
5157
5320
  local DebugInfoFrom=BASE.Debug.getinfo(3,"l")
5158
5321
  if _TraceLevel>=2 then
@@ -5161,7 +5324,7 @@ end
5161
5324
  end
5162
5325
  end
5163
5326
  function BASE:F3(Arguments)
5164
- if BASE.Debug and _TraceOnOff then
5327
+ if BASE.Debug and _TraceOnOff==true and _TraceLevel>=3 then
5165
5328
  local DebugInfoCurrent=BASE.Debug.getinfo(2,"nl")
5166
5329
  local DebugInfoFrom=BASE.Debug.getinfo(3,"l")
5167
5330
  if _TraceLevel>=3 then
@@ -5191,7 +5354,7 @@ end
5191
5354
  end
5192
5355
  end
5193
5356
  function BASE:T(Arguments)
5194
- if BASE.Debug and _TraceOnOff then
5357
+ if BASE.Debug and _TraceOnOff==true then
5195
5358
  local DebugInfoCurrent=BASE.Debug.getinfo(2,"nl")
5196
5359
  local DebugInfoFrom=BASE.Debug.getinfo(3,"l")
5197
5360
  if _TraceLevel>=1 then
@@ -5200,7 +5363,7 @@ end
5200
5363
  end
5201
5364
  end
5202
5365
  function BASE:T2(Arguments)
5203
- if BASE.Debug and _TraceOnOff then
5366
+ if BASE.Debug and _TraceOnOff==true and _TraceLevel>=2 then
5204
5367
  local DebugInfoCurrent=BASE.Debug.getinfo(2,"nl")
5205
5368
  local DebugInfoFrom=BASE.Debug.getinfo(3,"l")
5206
5369
  if _TraceLevel>=2 then
@@ -5209,7 +5372,7 @@ end
5209
5372
  end
5210
5373
  end
5211
5374
  function BASE:T3(Arguments)
5212
- if BASE.Debug and _TraceOnOff then
5375
+ if BASE.Debug and _TraceOnOff==true and _TraceLevel>=3 then
5213
5376
  local DebugInfoCurrent=BASE.Debug.getinfo(2,"nl")
5214
5377
  local DebugInfoFrom=BASE.Debug.getinfo(3,"l")
5215
5378
  if _TraceLevel>=3 then
@@ -6409,14 +6572,18 @@ UnitDeleteTask=world.event.S_EVENT_UNIT_DELETE_TASK or-1,
6409
6572
  SimulationStart=world.event.S_EVENT_SIMULATION_START or-1,
6410
6573
  WeaponRearm=world.event.S_EVENT_WEAPON_REARM or-1,
6411
6574
  WeaponDrop=world.event.S_EVENT_WEAPON_DROP or-1,
6412
- UnitTaskTimeout=world.event.S_EVENT_UNIT_TASK_TIMEOUT or-1,
6575
+ UnitTaskComplete=world.event.S_EVENT_UNIT_TASK_COMPLETE or-1,
6413
6576
  UnitTaskStage=world.event.S_EVENT_UNIT_TASK_STAGE or-1,
6414
- MacSubtaskScore=world.event.S_EVENT_MAC_SUBTASK_SCORE or-1,
6415
6577
  MacExtraScore=world.event.S_EVENT_MAC_EXTRA_SCORE or-1,
6416
6578
  MissionRestart=world.event.S_EVENT_MISSION_RESTART or-1,
6417
6579
  MissionWinner=world.event.S_EVENT_MISSION_WINNER or-1,
6418
- PostponedTakeoff=world.event.S_EVENT_POSTPONED_TAKEOFF or-1,
6419
- PostponedLand=world.event.S_EVENT_POSTPONED_LAND or-1,
6580
+ RunwayTakeoff=world.event.S_EVENT_RUNWAY_TAKEOFF or-1,
6581
+ RunwayTouch=world.event.S_EVENT_RUNWAY_TOUCH or-1,
6582
+ MacLMSRestart=world.event.S_EVENT_MAC_LMS_RESTART or-1,
6583
+ SimulationFreeze=world.event.S_EVENT_SIMULATION_FREEZE or-1,
6584
+ SimulationUnfreeze=world.event.S_EVENT_SIMULATION_UNFREEZE or-1,
6585
+ HumanAircraftRepairStart=world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_START or-1,
6586
+ HumanAircraftRepairFinish=world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH or-1,
6420
6587
  }
6421
6588
  local _EVENTMETA={
6422
6589
  [world.event.S_EVENT_SHOT]={
@@ -6730,24 +6897,12 @@ Side="I",
6730
6897
  Event="OnEventWeaponDrop",
6731
6898
  Text="S_EVENT_WEAPON_DROP"
6732
6899
  },
6733
- [EVENTS.UnitTaskTimeout]={
6734
- Order=1,
6735
- Side="I",
6736
- Event="OnEventUnitTaskTimeout",
6737
- Text="S_EVENT_UNIT_TASK_TIMEOUT "
6738
- },
6739
6900
  [EVENTS.UnitTaskStage]={
6740
6901
  Order=1,
6741
6902
  Side="I",
6742
6903
  Event="OnEventUnitTaskStage",
6743
6904
  Text="S_EVENT_UNIT_TASK_STAGE "
6744
6905
  },
6745
- [EVENTS.MacSubtaskScore]={
6746
- Order=1,
6747
- Side="I",
6748
- Event="OnEventMacSubtaskScore",
6749
- Text="S_EVENT_MAC_SUBTASK_SCORE"
6750
- },
6751
6906
  [EVENTS.MacExtraScore]={
6752
6907
  Order=1,
6753
6908
  Side="I",
@@ -6766,17 +6921,47 @@ Side="I",
6766
6921
  Event="OnEventMissionWinner",
6767
6922
  Text="S_EVENT_MISSION_WINNER"
6768
6923
  },
6769
- [EVENTS.PostponedTakeoff]={
6924
+ [EVENTS.RunwayTakeoff]={
6925
+ Order=1,
6926
+ Side="I",
6927
+ Event="OnEventRunwayTakeoff",
6928
+ Text="S_EVENT_RUNWAY_TAKEOFF"
6929
+ },
6930
+ [EVENTS.RunwayTouch]={
6931
+ Order=1,
6932
+ Side="I",
6933
+ Event="OnEventRunwayTouch",
6934
+ Text="S_EVENT_RUNWAY_TOUCH"
6935
+ },
6936
+ [EVENTS.MacLMSRestart]={
6937
+ Order=1,
6938
+ Side="I",
6939
+ Event="OnEventMacLMSRestart",
6940
+ Text="S_EVENT_MAC_LMS_RESTART"
6941
+ },
6942
+ [EVENTS.SimulationFreeze]={
6770
6943
  Order=1,
6771
6944
  Side="I",
6772
- Event="OnEventPostponedTakeoff",
6773
- Text="S_EVENT_POSTPONED_TAKEOFF"
6945
+ Event="OnEventSimulationFreeze",
6946
+ Text="S_EVENT_SIMULATION_FREEZE"
6774
6947
  },
6775
- [EVENTS.PostponedLand]={
6948
+ [EVENTS.SimulationUnfreeze]={
6776
6949
  Order=1,
6777
6950
  Side="I",
6778
- Event="OnEventPostponedLand",
6779
- Text="S_EVENT_POSTPONED_LAND"
6951
+ Event="OnEventSimulationUnfreeze",
6952
+ Text="S_EVENT_SIMULATION_UNFREEZE"
6953
+ },
6954
+ [EVENTS.HumanAircraftRepairStart]={
6955
+ Order=1,
6956
+ Side="I",
6957
+ Event="OnEventHumanAircraftRepairStart",
6958
+ Text="S_EVENT_HUMAN_AIRCRAFT_REPAIR_START"
6959
+ },
6960
+ [EVENTS.HumanAircraftRepairFinish]={
6961
+ Order=1,
6962
+ Side="I",
6963
+ Event="OnEventHumanAircraftRepairFinish",
6964
+ Text="S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH"
6780
6965
  },
6781
6966
  }
6782
6967
  function EVENT:New()
@@ -7099,7 +7284,7 @@ Event.TgtCategory=Event.TgtDCSUnit:getDesc().category
7099
7284
  Event.TgtTypeName=Event.TgtDCSUnit:getTypeName()
7100
7285
  elseif Event.TgtObjectCategory==Object.Category.STATIC then
7101
7286
  Event.TgtDCSUnit=Event.target
7102
- if Event.target:isExist()and Event.id~=33 then
7287
+ if Event.target.isExist and Event.target:isExist()and Event.id~=33 then
7103
7288
  Event.TgtDCSUnitName=Event.TgtDCSUnit:getName()
7104
7289
  if Event.TgtDCSUnitName and Event.TgtDCSUnitName~=""then
7105
7290
  Event.TgtUnitName=Event.TgtDCSUnitName
@@ -7135,14 +7320,14 @@ Event.TgtCategory=Event.TgtDCSUnit:getDesc().category
7135
7320
  Event.TgtTypeName=Event.TgtDCSUnit:getTypeName()
7136
7321
  end
7137
7322
  end
7138
- if Event.weapon then
7323
+ if Event.weapon and type(Event.weapon)=="table"then
7139
7324
  Event.Weapon=Event.weapon
7140
- Event.WeaponName=Event.Weapon:getTypeName()
7325
+ Event.WeaponName=Event.weapon:isExist()and Event.weapon:getTypeName()or"Unknown Weapon"
7141
7326
  Event.WeaponUNIT=CLIENT:Find(Event.Weapon,'',true)
7142
7327
  Event.WeaponPlayerName=Event.WeaponUNIT and Event.Weapon.getPlayerName and Event.Weapon:getPlayerName()
7143
- Event.WeaponCoalition=Event.WeaponUNIT and Event.Weapon:getCoalition()
7144
- Event.WeaponCategory=Event.WeaponUNIT and Event.Weapon:getDesc().category
7145
- Event.WeaponTypeName=Event.WeaponUNIT and Event.Weapon:getTypeName()
7328
+ Event.WeaponCoalition=Event.WeaponUNIT and Event.Weapon.getCoalition and Event.Weapon:getCoalition()
7329
+ Event.WeaponCategory=Event.WeaponUNIT and Event.Weapon.getDesc and Event.Weapon:getDesc().category
7330
+ Event.WeaponTypeName=Event.WeaponUNIT and Event.Weapon.getTypeName and Event.Weapon:getTypeName()
7146
7331
  end
7147
7332
  if Event.place then
7148
7333
  if Event.id==EVENTS.LandingAfterEjection then
@@ -7588,8 +7773,7 @@ end
7588
7773
  function SETTINGS:SetPlayerMenu(PlayerUnit)
7589
7774
  if _SETTINGS.ShowPlayerMenu==true then
7590
7775
  local PlayerGroup=PlayerUnit:GetGroup()
7591
- local PlayerName=PlayerUnit:GetPlayerName()
7592
- local PlayerNames=PlayerGroup:GetPlayerNames()
7776
+ local PlayerName=PlayerUnit:GetPlayerName()or"None"
7593
7777
  local PlayerMenu=MENU_GROUP:New(PlayerGroup,'Settings "'..PlayerName..'"')
7594
7778
  self.PlayerMenu=PlayerMenu
7595
7779
  self:T(string.format("Setting menu for player %s",tostring(PlayerName)))
@@ -8395,6 +8579,7 @@ return self
8395
8579
  end
8396
8580
  end
8397
8581
  function MENU_GROUP_DELAYED:Set()
8582
+ if not self.GroupID then return end
8398
8583
  do
8399
8584
  if not self.MenuSet then
8400
8585
  missionCommands.addSubMenuForGroup(self.GroupID,self.MenuText,self.MenuParentPath)
@@ -9013,7 +9198,7 @@ local FoundUnit=UNIT:FindByName(UnitObject:getName())
9013
9198
  if FoundUnit then
9014
9199
  SetUnit:AddUnit(FoundUnit)
9015
9200
  else
9016
- local FoundStatic=STATIC:FindByName(UnitObject:getName())
9201
+ local FoundStatic=STATIC:FindByName(UnitObject:getName(),false)
9017
9202
  if FoundStatic then
9018
9203
  SetUnit:AddUnit(FoundStatic)
9019
9204
  end
@@ -9991,10 +10176,18 @@ for _,object in pairs(layer["objects"])do
9991
10176
  if object["name"]==DrawingName then
9992
10177
  if(object["primitiveType"]=="Line"and object["closed"]==true)or(object["polygonMode"]=="free")then
9993
10178
  for _,point in UTILS.spairs(object["points"])do
10179
+ local skip=false
9994
10180
  local p={x=object["mapX"]+point["x"],
9995
10181
  y=object["mapY"]+point["y"]}
10182
+ for _,pt in pairs(points)do
10183
+ if pt.x==p.x and pt.y==p.y then
10184
+ skip=true
10185
+ end
10186
+ end
10187
+ if not skip then
9996
10188
  table.add(points,p)
9997
10189
  end
10190
+ end
9998
10191
  elseif object["polygonMode"]=="rect"then
9999
10192
  local angle=object["angle"]
10000
10193
  local half_width=object["width"]/2
@@ -10620,6 +10813,7 @@ self:HandleEvent(EVENTS.PlayerEnterUnit,self._EventOnPlayerEnterUnit)
10620
10813
  self:HandleEvent(EVENTS.Dead,self._EventOnDeadOrCrash)
10621
10814
  self:HandleEvent(EVENTS.Crash,self._EventOnDeadOrCrash)
10622
10815
  self:HandleEvent(EVENTS.RemoveUnit,self._EventOnDeadOrCrash)
10816
+ self:HandleEvent(EVENTS.UnitLost,self._EventOnDeadOrCrash)
10623
10817
  self:HandleEvent(EVENTS.Hit,self.AccountHits)
10624
10818
  self:HandleEvent(EVENTS.NewCargo)
10625
10819
  self:HandleEvent(EVENTS.DeleteCargo)
@@ -10637,14 +10831,15 @@ function DATABASE:FindUnit(UnitName)
10637
10831
  local UnitFound=self.UNITS[UnitName]
10638
10832
  return UnitFound
10639
10833
  end
10640
- function DATABASE:AddUnit(DCSUnitName)
10641
- if not self.UNITS[DCSUnitName]then
10834
+ function DATABASE:AddUnit(DCSUnitName,force)
10835
+ if not self.UNITS[DCSUnitName]or force==true then
10642
10836
  self:T({"Add UNIT:",DCSUnitName})
10643
10837
  self.UNITS[DCSUnitName]=UNIT:Register(DCSUnitName)
10644
10838
  end
10645
10839
  return self.UNITS[DCSUnitName]
10646
10840
  end
10647
10841
  function DATABASE:DeleteUnit(DCSUnitName)
10842
+ self:T("DeleteUnit "..tostring(DCSUnitName))
10648
10843
  self.UNITS[DCSUnitName]=nil
10649
10844
  end
10650
10845
  function DATABASE:AddStatic(DCSStaticName)
@@ -10928,18 +11123,22 @@ function DATABASE:FindClient(ClientName)
10928
11123
  local ClientFound=self.CLIENTS[ClientName]
10929
11124
  return ClientFound
10930
11125
  end
10931
- function DATABASE:AddClient(ClientName)
10932
- if not self.CLIENTS[ClientName]then
11126
+ function DATABASE:AddClient(ClientName,Force)
11127
+ if not self.CLIENTS[ClientName]or Force==true then
10933
11128
  self.CLIENTS[ClientName]=CLIENT:Register(ClientName)
10934
11129
  end
10935
11130
  return self.CLIENTS[ClientName]
10936
11131
  end
10937
11132
  function DATABASE:FindGroup(GroupName)
10938
11133
  local GroupFound=self.GROUPS[GroupName]
11134
+ if GroupFound==nil and GroupName~=nil and self.Templates.Groups[GroupName]==nil then
11135
+ self:_RegisterDynamicGroup(GroupName)
11136
+ return self.GROUPS[GroupName]
11137
+ end
10939
11138
  return GroupFound
10940
11139
  end
10941
- function DATABASE:AddGroup(GroupName)
10942
- if not self.GROUPS[GroupName]then
11140
+ function DATABASE:AddGroup(GroupName,force)
11141
+ if not self.GROUPS[GroupName]or force==true then
10943
11142
  self:T({"Add GROUP:",GroupName})
10944
11143
  self.GROUPS[GroupName]=GROUP:Register(GroupName)
10945
11144
  end
@@ -11132,10 +11331,13 @@ end
11132
11331
  return nextoctal
11133
11332
  end
11134
11333
  function DATABASE:GetGroupTemplate(GroupName)
11135
- local GroupTemplate=self.Templates.Groups[GroupName].Template
11334
+ local GroupTemplate=nil
11335
+ if self.Templates.Groups[GroupName]then
11336
+ GroupTemplate=self.Templates.Groups[GroupName].Template
11136
11337
  GroupTemplate.SpawnCoalitionID=self.Templates.Groups[GroupName].CoalitionID
11137
11338
  GroupTemplate.SpawnCategoryID=self.Templates.Groups[GroupName].CategoryID
11138
11339
  GroupTemplate.SpawnCountryID=self.Templates.Groups[GroupName].CountryID
11340
+ end
11139
11341
  return GroupTemplate
11140
11342
  end
11141
11343
  function DATABASE:_RegisterStaticTemplate(StaticTemplate,CoalitionID,CategoryID,CountryID)
@@ -11161,6 +11363,34 @@ Country=self.Templates.Statics[StaticTemplateName].CountryID
11161
11363
  self:AddStatic(StaticTemplateName)
11162
11364
  return self
11163
11365
  end
11366
+ function DATABASE:_GetGenericStaticCargoGroupTemplate(Name,Typename,Mass,Coalition,Country)
11367
+ local StaticTemplate={}
11368
+ StaticTemplate.name=Name or"None"
11369
+ StaticTemplate.units={[1]={
11370
+ name=Name,
11371
+ resourcePayload={
11372
+ ["weapons"]={},
11373
+ ["aircrafts"]={},
11374
+ ["gasoline"]=0,
11375
+ ["diesel"]=0,
11376
+ ["methanol_mixture"]=0,
11377
+ ["jet_fuel"]=0,
11378
+ },
11379
+ ["mass"]=Mass or 0,
11380
+ ["category"]="Cargos",
11381
+ ["canCargo"]=true,
11382
+ ["type"]=Typename or"container_cargo",
11383
+ ["rate"]=100,
11384
+ ["y"]=0,
11385
+ ["x"]=0,
11386
+ ["heading"]=0,
11387
+ }}
11388
+ StaticTemplate.CategoryID="static"
11389
+ StaticTemplate.CoalitionID=Coalition or coalition.side.BLUE
11390
+ StaticTemplate.CountryID=Country or country.id.GERMANY
11391
+ UTILS.PrintTableToLog(StaticTemplate)
11392
+ return StaticTemplate
11393
+ end
11164
11394
  function DATABASE:GetStaticGroupTemplate(StaticName)
11165
11395
  if self.Templates.Statics[StaticName]then
11166
11396
  local StaticTemplate=self.Templates.Statics[StaticName].GroupTemplate
@@ -11204,14 +11434,26 @@ return nil
11204
11434
  end
11205
11435
  end
11206
11436
  function DATABASE:GetCoalitionFromClientTemplate(ClientName)
11437
+ if self.Templates.ClientsByName[ClientName]then
11207
11438
  return self.Templates.ClientsByName[ClientName].CoalitionID
11208
11439
  end
11440
+ self:E("ERROR: Template does not exist for client "..tostring(ClientName))
11441
+ return nil
11442
+ end
11209
11443
  function DATABASE:GetCategoryFromClientTemplate(ClientName)
11444
+ if self.Templates.ClientsByName[ClientName]then
11210
11445
  return self.Templates.ClientsByName[ClientName].CategoryID
11211
11446
  end
11447
+ self:E("ERROR: Template does not exist for client "..tostring(ClientName))
11448
+ return nil
11449
+ end
11212
11450
  function DATABASE:GetCountryFromClientTemplate(ClientName)
11451
+ if self.Templates.ClientsByName[ClientName]then
11213
11452
  return self.Templates.ClientsByName[ClientName].CountryID
11214
11453
  end
11454
+ self:E("ERROR: Template does not exist for client "..tostring(ClientName))
11455
+ return nil
11456
+ end
11215
11457
  function DATABASE:GetCoalitionFromAirbase(AirbaseName)
11216
11458
  return self.AIRBASES[AirbaseName]:GetCoalition()
11217
11459
  end
@@ -11235,6 +11477,22 @@ end
11235
11477
  end
11236
11478
  return self
11237
11479
  end
11480
+ function DATABASE:_RegisterDynamicGroup(Groupname)
11481
+ local DCSGroup=Group.getByName(Groupname)
11482
+ if DCSGroup and DCSGroup:isExist()then
11483
+ local DCSGroupName=DCSGroup:getName()
11484
+ self:I(string.format("Register Group: %s",tostring(DCSGroupName)))
11485
+ self:AddGroup(DCSGroupName,true)
11486
+ for DCSUnitId,DCSUnit in pairs(DCSGroup:getUnits())do
11487
+ local DCSUnitName=DCSUnit:getName()
11488
+ self:I(string.format("Register Unit: %s",tostring(DCSUnitName)))
11489
+ self:AddUnit(DCSUnitName,true)
11490
+ end
11491
+ else
11492
+ self:E({"Group does not exist: ",DCSGroup})
11493
+ end
11494
+ return self
11495
+ end
11238
11496
  function DATABASE:_RegisterGroupsAndUnits()
11239
11497
  local CoalitionsData={GroupsRed=coalition.getGroups(coalition.side.RED),GroupsBlue=coalition.getGroups(coalition.side.BLUE),GroupsNeutral=coalition.getGroups(coalition.side.NEUTRAL)}
11240
11498
  for CoalitionId,CoalitionData in pairs(CoalitionsData)do
@@ -11323,24 +11581,27 @@ end
11323
11581
  end
11324
11582
  end
11325
11583
  if Event.IniObjectCategory==Object.Category.UNIT then
11326
- Event.IniUnit=self:FindUnit(Event.IniDCSUnitName)
11327
11584
  Event.IniGroup=self:FindGroup(Event.IniDCSGroupName)
11585
+ Event.IniUnit=self:FindUnit(Event.IniDCSUnitName)
11328
11586
  local client=self.CLIENTS[Event.IniDCSUnitName]
11329
11587
  if client then
11330
11588
  end
11331
11589
  local PlayerName=Event.IniUnit:GetPlayerName()
11332
11590
  if PlayerName then
11333
11591
  self:I(string.format("Player '%s' joined unit '%s' of group '%s'",tostring(PlayerName),tostring(Event.IniDCSUnitName),tostring(Event.IniDCSGroupName)))
11334
- if not client then
11335
- client=self:AddClient(Event.IniDCSUnitName)
11592
+ if client==nil or(client and client:CountPlayers()==0)then
11593
+ client=self:AddClient(Event.IniDCSUnitName,true)
11336
11594
  end
11337
11595
  client:AddPlayer(PlayerName)
11338
11596
  if not self.PLAYERS[PlayerName]then
11339
11597
  self:AddPlayer(Event.IniUnitName,PlayerName)
11340
11598
  end
11599
+ local function SetPlayerSettings(self,PlayerName,IniUnit)
11341
11600
  local Settings=SETTINGS:Set(PlayerName)
11342
- Settings:SetPlayerMenu(Event.IniUnit)
11343
- self:CreateEventPlayerEnterAircraft(Event.IniUnit)
11601
+ Settings:SetPlayerMenu(IniUnit)
11602
+ self:CreateEventPlayerEnterAircraft(IniUnit)
11603
+ end
11604
+ self:ScheduleOnce(1,SetPlayerSettings,self,PlayerName,Event.IniUnit)
11344
11605
  end
11345
11606
  end
11346
11607
  end
@@ -11363,7 +11624,7 @@ end
11363
11624
  else
11364
11625
  if Event.IniObjectCategory==1 then
11365
11626
  if self.UNITS[Event.IniDCSUnitName]then
11366
- self:DeleteUnit(Event.IniDCSUnitName)
11627
+ self:ScheduleOnce(1,self.DeleteUnit,self,Event.IniDCSUnitName)
11367
11628
  end
11368
11629
  local client=self.CLIENTS[name]
11369
11630
  if client then
@@ -12319,6 +12580,8 @@ self:HandleEvent(EVENTS.Birth,self._EventOnBirth)
12319
12580
  self:HandleEvent(EVENTS.Dead,self._EventOnDeadOrCrash)
12320
12581
  self:HandleEvent(EVENTS.Crash,self._EventOnDeadOrCrash)
12321
12582
  self:HandleEvent(EVENTS.RemoveUnit,self._EventOnDeadOrCrash)
12583
+ self:HandleEvent(EVENTS.UnitLost,self._EventOnDeadOrCrash)
12584
+ self:HandleEvent(EVENTS.PlayerLeaveUnit,self._EventOnDeadOrCrash)
12322
12585
  if self.Filter.Zones then
12323
12586
  self.ZoneTimer=TIMER:New(self._ContinousZoneFilter,self)
12324
12587
  local timing=self.ZoneTimerInterval or 30
@@ -12337,6 +12600,7 @@ self:UnHandleEvent(EVENTS.Birth)
12337
12600
  self:UnHandleEvent(EVENTS.Dead)
12338
12601
  self:UnHandleEvent(EVENTS.Crash)
12339
12602
  self:UnHandleEvent(EVENTS.RemoveUnit)
12603
+ self:UnHandleEvent(EVENTS.UnitLost)
12340
12604
  if self.Filter.Zones and self.ZoneTimer and self.ZoneTimer:IsRunning()then
12341
12605
  self.ZoneTimer:Stop()
12342
12606
  end
@@ -12627,14 +12891,17 @@ local gmin=nil
12627
12891
  for GroupID,GroupData in pairs(Set)do
12628
12892
  local group=GroupData
12629
12893
  if group and group:IsAlive()and(Coalitions==nil or UTILS.IsAnyInTable(Coalitions,group:GetCoalition()))then
12630
- local coord=group:GetCoord()
12631
- local d=UTILS.VecDist3D(Coordinate,coord)
12894
+ local coord=group:GetCoordinate()
12895
+ local d
12896
+ if coord~=nil then
12897
+ d=UTILS.VecDist3D(Coordinate,coord)
12632
12898
  if d<dmin then
12633
12899
  dmin=d
12634
12900
  gmin=group
12635
12901
  end
12636
12902
  end
12637
12903
  end
12904
+ end
12638
12905
  return gmin,dmin
12639
12906
  end
12640
12907
  function SET_GROUP:SetCargoBayWeightLimit()
@@ -12788,6 +13055,18 @@ Active=Active or not(Active==false)
12788
13055
  self.Filter.Active=Active
12789
13056
  return self
12790
13057
  end
13058
+ function SET_UNIT:FilterAlive()
13059
+ self:FilterFunction(
13060
+ function(unit)
13061
+ if unit and unit:IsExist()and unit:IsAlive()then
13062
+ return true
13063
+ else
13064
+ return false
13065
+ end
13066
+ end
13067
+ )
13068
+ return self
13069
+ end
12791
13070
  function SET_UNIT:FilterHasRadar(RadarTypes)
12792
13071
  self.Filter.RadarTypes=self.Filter.RadarTypes or{}
12793
13072
  if type(RadarTypes)~="table"then
@@ -12856,6 +13135,7 @@ self:HandleEvent(EVENTS.Birth,self._EventOnBirth)
12856
13135
  self:HandleEvent(EVENTS.Dead,self._EventOnDeadOrCrash)
12857
13136
  self:HandleEvent(EVENTS.Crash,self._EventOnDeadOrCrash)
12858
13137
  self:HandleEvent(EVENTS.RemoveUnit,self._EventOnDeadOrCrash)
13138
+ self:HandleEvent(EVENTS.UnitLost,self._EventOnDeadOrCrash)
12859
13139
  if self.Filter.Zones then
12860
13140
  self.ZoneTimer=TIMER:New(self._ContinousZoneFilter,self)
12861
13141
  local timing=self.ZoneTimerInterval or 30
@@ -13882,6 +14162,18 @@ Active=Active or not(Active==false)
13882
14162
  self.Filter.Active=Active
13883
14163
  return self
13884
14164
  end
14165
+ function SET_CLIENT:FilterAlive()
14166
+ self:FilterFunction(
14167
+ function(unit)
14168
+ if unit and unit:IsExist()and unit:IsAlive()then
14169
+ return true
14170
+ else
14171
+ return false
14172
+ end
14173
+ end
14174
+ )
14175
+ return self
14176
+ end
13885
14177
  function SET_CLIENT:FilterZones(Zones)
13886
14178
  if not self.Filter.Zones then
13887
14179
  self.Filter.Zones={}
@@ -14039,8 +14331,11 @@ if self.Filter.Coalitions and MClientInclude then
14039
14331
  local MClientCoalition=false
14040
14332
  for CoalitionID,CoalitionName in pairs(self.Filter.Coalitions)do
14041
14333
  local ClientCoalitionID=_DATABASE:GetCoalitionFromClientTemplate(MClientName)
14334
+ if ClientCoalitionID==nil and MClient:IsAlive()~=nil then
14335
+ ClientCoalitionID=MClient:GetCoalition()
14336
+ end
14042
14337
  self:T3({"Coalition:",ClientCoalitionID,self.FilterMeta.Coalitions[CoalitionName],CoalitionName})
14043
- if self.FilterMeta.Coalitions[CoalitionName]and self.FilterMeta.Coalitions[CoalitionName]==ClientCoalitionID then
14338
+ if self.FilterMeta.Coalitions[CoalitionName]and ClientCoalitionID and self.FilterMeta.Coalitions[CoalitionName]==ClientCoalitionID then
14044
14339
  MClientCoalition=true
14045
14340
  end
14046
14341
  end
@@ -14051,11 +14346,20 @@ if self.Filter.Categories and MClientInclude then
14051
14346
  local MClientCategory=false
14052
14347
  for CategoryID,CategoryName in pairs(self.Filter.Categories)do
14053
14348
  local ClientCategoryID=_DATABASE:GetCategoryFromClientTemplate(MClientName)
14349
+ local UnitCategory=0
14350
+ if ClientCategoryID==nil and MClient:IsExist()then
14351
+ ClientCategoryID,UnitCategory=MClient:GetCategory()
14352
+ self:T3({"Category:",UnitCategory,self.FilterMeta.Categories[CategoryName],CategoryName})
14353
+ if self.FilterMeta.Categories[CategoryName]and UnitCategory and self.FilterMeta.Categories[CategoryName]==UnitCategory then
14354
+ MClientCategory=true
14355
+ end
14356
+ else
14054
14357
  self:T3({"Category:",ClientCategoryID,self.FilterMeta.Categories[CategoryName],CategoryName})
14055
- if self.FilterMeta.Categories[CategoryName]and self.FilterMeta.Categories[CategoryName]==ClientCategoryID then
14358
+ if self.FilterMeta.Categories[CategoryName]and ClientCategoryID and self.FilterMeta.Categories[CategoryName]==ClientCategoryID then
14056
14359
  MClientCategory=true
14057
14360
  end
14058
14361
  end
14362
+ end
14059
14363
  self:T({"Evaluated Category",MClientCategory})
14060
14364
  MClientInclude=MClientInclude and MClientCategory
14061
14365
  end
@@ -14074,8 +14378,11 @@ if self.Filter.Countries and MClientInclude then
14074
14378
  local MClientCountry=false
14075
14379
  for CountryID,CountryName in pairs(self.Filter.Countries)do
14076
14380
  local ClientCountryID=_DATABASE:GetCountryFromClientTemplate(MClientName)
14381
+ if ClientCountryID==nil and MClient:IsAlive()~=nil then
14382
+ ClientCountryID=MClient:GetCountry()
14383
+ end
14077
14384
  self:T3({"Country:",ClientCountryID,country.id[CountryName],CountryName})
14078
- if country.id[CountryName]and country.id[CountryName]==ClientCountryID then
14385
+ if country.id[CountryName]and ClientCountryID and country.id[CountryName]==ClientCountryID then
14079
14386
  MClientCountry=true
14080
14387
  end
14081
14388
  end
@@ -14314,27 +14621,39 @@ self:F2(MClient)
14314
14621
  local MClientInclude=true
14315
14622
  if MClient then
14316
14623
  local MClientName=MClient.UnitName
14317
- if self.Filter.Coalitions then
14624
+ if self.Filter.Coalitions and MClientInclude then
14318
14625
  local MClientCoalition=false
14319
14626
  for CoalitionID,CoalitionName in pairs(self.Filter.Coalitions)do
14320
14627
  local ClientCoalitionID=_DATABASE:GetCoalitionFromClientTemplate(MClientName)
14628
+ if ClientCoalitionID==nil and MClient:IsAlive()~=nil then
14629
+ ClientCoalitionID=MClient:GetCoalition()
14630
+ end
14321
14631
  self:T3({"Coalition:",ClientCoalitionID,self.FilterMeta.Coalitions[CoalitionName],CoalitionName})
14322
- if self.FilterMeta.Coalitions[CoalitionName]and self.FilterMeta.Coalitions[CoalitionName]==ClientCoalitionID then
14632
+ if self.FilterMeta.Coalitions[CoalitionName]and ClientCoalitionID and self.FilterMeta.Coalitions[CoalitionName]==ClientCoalitionID then
14323
14633
  MClientCoalition=true
14324
14634
  end
14325
14635
  end
14326
14636
  self:T({"Evaluated Coalition",MClientCoalition})
14327
14637
  MClientInclude=MClientInclude and MClientCoalition
14328
14638
  end
14329
- if self.Filter.Categories then
14639
+ if self.Filter.Categories and MClientInclude then
14330
14640
  local MClientCategory=false
14331
14641
  for CategoryID,CategoryName in pairs(self.Filter.Categories)do
14332
14642
  local ClientCategoryID=_DATABASE:GetCategoryFromClientTemplate(MClientName)
14643
+ local UnitCategory=0
14644
+ if ClientCategoryID==nil and MClient:IsExist()then
14645
+ ClientCategoryID,UnitCategory=MClient:GetCategory()
14646
+ self:T3({"Category:",UnitCategory,self.FilterMeta.Categories[CategoryName],CategoryName})
14647
+ if self.FilterMeta.Categories[CategoryName]and UnitCategory and self.FilterMeta.Categories[CategoryName]==UnitCategory then
14648
+ MClientCategory=true
14649
+ end
14650
+ else
14333
14651
  self:T3({"Category:",ClientCategoryID,self.FilterMeta.Categories[CategoryName],CategoryName})
14334
- if self.FilterMeta.Categories[CategoryName]and self.FilterMeta.Categories[CategoryName]==ClientCategoryID then
14652
+ if self.FilterMeta.Categories[CategoryName]and ClientCategoryID and self.FilterMeta.Categories[CategoryName]==ClientCategoryID then
14335
14653
  MClientCategory=true
14336
14654
  end
14337
14655
  end
14656
+ end
14338
14657
  self:T({"Evaluated Category",MClientCategory})
14339
14658
  MClientInclude=MClientInclude and MClientCategory
14340
14659
  end
@@ -15573,6 +15892,7 @@ self:HandleEvent(EVENTS.Birth,self._EventOnBirth)
15573
15892
  self:HandleEvent(EVENTS.Dead,self._EventOnDeadOrCrash)
15574
15893
  self:HandleEvent(EVENTS.Crash,self._EventOnDeadOrCrash)
15575
15894
  self:HandleEvent(EVENTS.RemoveUnit,self._EventOnDeadOrCrash)
15895
+ self:HandleEvent(EVENTS.UnitLost,self._EventOnDeadOrCrash)
15576
15896
  end
15577
15897
  return self
15578
15898
  end
@@ -17159,6 +17479,8 @@ local Latitude,Longitude=self:GetLLDDM()
17159
17479
  local Tdiff=UTILS.GMTToLocalTimeDifference()
17160
17480
  local sunrise=UTILS.GetSunRiseAndSet(DayOfYear,Latitude,Longitude,true,Tdiff)
17161
17481
  local sunset=UTILS.GetSunRiseAndSet(DayOfYear,Latitude,Longitude,false,Tdiff)
17482
+ if sunrise=="N/R"then return false end
17483
+ if sunrise=="N/S"then return true end
17162
17484
  local time=UTILS.ClockToSeconds(clock)
17163
17485
  if time>sunrise and time<=sunset then
17164
17486
  return true
@@ -17830,19 +18152,7 @@ return self
17830
18152
  end
17831
18153
  function MESSAGE:ToClient(Client,Settings)
17832
18154
  self:F(Client)
17833
- if Client and Client:GetClientGroupID()then
17834
- if self.MessageType then
17835
- local Settings=Settings or(Client and _DATABASE:GetPlayerSettings(Client:GetPlayerName()))or _SETTINGS
17836
- self.MessageDuration=Settings:GetMessageTime(self.MessageType)
17837
- self.MessageCategory=""
17838
- end
17839
- local Unit=Client:GetClient()
17840
- if self.MessageDuration~=0 then
17841
- local ClientGroupID=Client:GetClientGroupID()
17842
- self:T(self.MessageCategory..self.MessageText:gsub("\n$",""):gsub("\n$","").." / "..self.MessageDuration)
17843
- trigger.action.outTextForUnit(Unit:GetID(),self.MessageCategory..self.MessageText:gsub("\n$",""):gsub("\n$",""),self.MessageDuration,self.ClearScreen)
17844
- end
17845
- end
18155
+ self:ToUnit(Client,Settings)
17846
18156
  return self
17847
18157
  end
17848
18158
  function MESSAGE:ToGroup(Group,Settings)
@@ -17980,9 +18290,9 @@ _MESSAGESRS.MSRS:SetProviderOptionsGoogle(PathToCredentials)
17980
18290
  _MESSAGESRS.MSRS:SetProvider(MSRS.Provider.GOOGLE)
17981
18291
  end
17982
18292
  _MESSAGESRS.label=Label or MSRS.Label or"MESSAGE"
17983
- _MESSAGESRS.MSRS:SetLabel(Label or"MESSAGE")
18293
+ _MESSAGESRS.MSRS:SetLabel(_MESSAGESRS.label)
17984
18294
  _MESSAGESRS.port=Port or MSRS.port or 5002
17985
- _MESSAGESRS.MSRS:SetPort(Port or 5002)
18295
+ _MESSAGESRS.MSRS:SetPort(_MESSAGESRS.port)
17986
18296
  _MESSAGESRS.volume=Volume or MSRS.volume or 1
17987
18297
  _MESSAGESRS.MSRS:SetVolume(_MESSAGESRS.volume)
17988
18298
  if Voice then _MESSAGESRS.MSRS:SetVoice(Voice)end
@@ -18538,7 +18848,6 @@ Cold=4,
18538
18848
  }
18539
18849
  function SPAWN:New(SpawnTemplatePrefix)
18540
18850
  local self=BASE:Inherit(self,BASE:New())
18541
- self:F({SpawnTemplatePrefix})
18542
18851
  local TemplateGroup=GROUP:FindByName(SpawnTemplatePrefix)
18543
18852
  if TemplateGroup then
18544
18853
  self.SpawnTemplatePrefix=SpawnTemplatePrefix
@@ -18580,7 +18889,6 @@ return self
18580
18889
  end
18581
18890
  function SPAWN:NewWithAlias(SpawnTemplatePrefix,SpawnAliasPrefix)
18582
18891
  local self=BASE:Inherit(self,BASE:New())
18583
- self:F({SpawnTemplatePrefix,SpawnAliasPrefix})
18584
18892
  local TemplateGroup=GROUP:FindByName(SpawnTemplatePrefix)
18585
18893
  if TemplateGroup then
18586
18894
  self.SpawnTemplatePrefix=SpawnTemplatePrefix
@@ -18622,7 +18930,6 @@ return self
18622
18930
  end
18623
18931
  function SPAWN:NewFromTemplate(SpawnTemplate,SpawnTemplatePrefix,SpawnAliasPrefix,NoMooseNamingPostfix)
18624
18932
  local self=BASE:Inherit(self,BASE:New())
18625
- self:F({SpawnTemplate,SpawnTemplatePrefix,SpawnAliasPrefix})
18626
18933
  if SpawnTemplatePrefix==nil or SpawnTemplatePrefix==""then
18627
18934
  BASE:I("ERROR: in function NewFromTemplate, required parameter SpawnTemplatePrefix is not set")
18628
18935
  return nil
@@ -18671,7 +18978,6 @@ self.SpawnHookScheduler=SCHEDULER:New(nil)
18671
18978
  return self
18672
18979
  end
18673
18980
  function SPAWN:InitLimit(SpawnMaxUnitsAlive,SpawnMaxGroups)
18674
- self:F({self.SpawnTemplatePrefix,SpawnMaxUnitsAlive,SpawnMaxGroups})
18675
18981
  self.SpawnInitLimit=true
18676
18982
  self.SpawnMaxUnitsAlive=SpawnMaxUnitsAlive
18677
18983
  self.SpawnMaxGroups=SpawnMaxGroups
@@ -18681,24 +18987,21 @@ end
18681
18987
  return self
18682
18988
  end
18683
18989
  function SPAWN:InitKeepUnitNames(KeepUnitNames)
18684
- self:F()
18685
- self.SpawnInitKeepUnitNames=KeepUnitNames or true
18990
+ self.SpawnInitKeepUnitNames=false
18991
+ if KeepUnitNames==true then self.SpawnInitKeepUnitNames=true end
18686
18992
  return self
18687
18993
  end
18688
18994
  function SPAWN:InitLateActivated(LateActivated)
18689
- self:F()
18690
18995
  self.LateActivated=LateActivated or true
18691
18996
  return self
18692
18997
  end
18693
18998
  function SPAWN:InitAirbase(AirbaseName,Takeoff,TerminalType)
18694
- self:F()
18695
18999
  self.SpawnInitAirbase=AIRBASE:FindByName(AirbaseName)
18696
19000
  self.SpawnInitTakeoff=Takeoff or SPAWN.Takeoff.Hot
18697
19001
  self.SpawnInitTerminalType=TerminalType
18698
19002
  return self
18699
19003
  end
18700
19004
  function SPAWN:InitHeading(HeadingMin,HeadingMax)
18701
- self:F()
18702
19005
  self.SpawnInitHeadingMin=HeadingMin
18703
19006
  self.SpawnInitHeadingMax=HeadingMax
18704
19007
  return self
@@ -18716,22 +19019,18 @@ self.SpawnInitCoalition=Coalition
18716
19019
  return self
18717
19020
  end
18718
19021
  function SPAWN:InitCountry(Country)
18719
- self:F()
18720
19022
  self.SpawnInitCountry=Country
18721
19023
  return self
18722
19024
  end
18723
19025
  function SPAWN:InitCategory(Category)
18724
- self:F()
18725
19026
  self.SpawnInitCategory=Category
18726
19027
  return self
18727
19028
  end
18728
19029
  function SPAWN:InitLivery(Livery)
18729
- self:F({livery=Livery})
18730
19030
  self.SpawnInitLivery=Livery
18731
19031
  return self
18732
19032
  end
18733
19033
  function SPAWN:InitSkill(Skill)
18734
- self:F({skill=Skill})
18735
19034
  if Skill:lower()=="average"then
18736
19035
  self.SpawnInitSkill="Average"
18737
19036
  elseif Skill:lower()=="good"then
@@ -18746,7 +19045,6 @@ end
18746
19045
  return self
18747
19046
  end
18748
19047
  function SPAWN:InitSTN(Octal)
18749
- self:F({Octal=Octal})
18750
19048
  self.SpawnInitSTN=Octal or 77777
18751
19049
  local num=UTILS.OctalToDecimal(Octal)
18752
19050
  if num==nil or num<1 then
@@ -18759,7 +19057,6 @@ end
18759
19057
  return self
18760
19058
  end
18761
19059
  function SPAWN:InitSADL(Octal)
18762
- self:F({Octal=Octal})
18763
19060
  self.SpawnInitSADL=Octal or 7777
18764
19061
  local num=UTILS.OctalToDecimal(Octal)
18765
19062
  if num==nil or num<1 then
@@ -18772,7 +19069,6 @@ end
18772
19069
  return self
18773
19070
  end
18774
19071
  function SPAWN:InitSpeedMps(MPS)
18775
- self:F({MPS=MPS})
18776
19072
  if MPS==nil or tonumber(MPS)<0 then
18777
19073
  MPS=125
18778
19074
  end
@@ -18780,7 +19076,6 @@ self.InitSpeed=MPS
18780
19076
  return self
18781
19077
  end
18782
19078
  function SPAWN:InitSpeedKnots(Knots)
18783
- self:F({Knots=Knots})
18784
19079
  if Knots==nil or tonumber(Knots)<0 then
18785
19080
  Knots=300
18786
19081
  end
@@ -18788,7 +19083,6 @@ self.InitSpeed=UTILS.KnotsToMps(Knots)
18788
19083
  return self
18789
19084
  end
18790
19085
  function SPAWN:InitSpeedKph(KPH)
18791
- self:F({KPH=KPH})
18792
19086
  if KPH==nil or tonumber(KPH)<0 then
18793
19087
  KPH=UTILS.KnotsToKmph(300)
18794
19088
  end
@@ -18796,17 +19090,14 @@ self.InitSpeed=UTILS.KmphToMps(KPH)
18796
19090
  return self
18797
19091
  end
18798
19092
  function SPAWN:InitRadioCommsOnOff(switch)
18799
- self:F({switch=switch})
18800
19093
  self.SpawnInitRadio=switch or true
18801
19094
  return self
18802
19095
  end
18803
19096
  function SPAWN:InitRadioFrequency(frequency)
18804
- self:F({frequency=frequency})
18805
19097
  self.SpawnInitFreq=frequency
18806
19098
  return self
18807
19099
  end
18808
19100
  function SPAWN:InitRadioModulation(modulation)
18809
- self:F({modulation=modulation})
18810
19101
  if modulation and modulation:lower()=="fm"then
18811
19102
  self.SpawnInitModu=radio.modulation.FM
18812
19103
  else
@@ -18823,7 +19114,6 @@ self.SpawnInitModexPostfix=postfix
18823
19114
  return self
18824
19115
  end
18825
19116
  function SPAWN:InitRandomizeRoute(SpawnStartPoint,SpawnEndPoint,SpawnRadius,SpawnHeight)
18826
- self:F({self.SpawnTemplatePrefix,SpawnStartPoint,SpawnEndPoint,SpawnRadius,SpawnHeight})
18827
19117
  self.SpawnRandomizeRoute=true
18828
19118
  self.SpawnRandomizeRouteStartPoint=SpawnStartPoint
18829
19119
  self.SpawnRandomizeRouteEndPoint=SpawnEndPoint
@@ -18835,7 +19125,6 @@ end
18835
19125
  return self
18836
19126
  end
18837
19127
  function SPAWN:InitRandomizePosition(RandomizePosition,OuterRadius,InnerRadius)
18838
- self:F({self.SpawnTemplatePrefix,RandomizePosition,OuterRadius,InnerRadius})
18839
19128
  self.SpawnRandomizePosition=RandomizePosition or false
18840
19129
  self.SpawnRandomizePositionOuterRadius=OuterRadius or 0
18841
19130
  self.SpawnRandomizePositionInnerRadius=InnerRadius or 0
@@ -18845,7 +19134,6 @@ end
18845
19134
  return self
18846
19135
  end
18847
19136
  function SPAWN:InitRandomizeUnits(RandomizeUnits,OuterRadius,InnerRadius)
18848
- self:F({self.SpawnTemplatePrefix,RandomizeUnits,OuterRadius,InnerRadius})
18849
19137
  self.SpawnRandomizeUnits=RandomizeUnits or false
18850
19138
  self.SpawnOuterRadius=OuterRadius or 0
18851
19139
  self.SpawnInnerRadius=InnerRadius or 0
@@ -18855,19 +19143,16 @@ end
18855
19143
  return self
18856
19144
  end
18857
19145
  function SPAWN:InitSetUnitRelativePositions(Positions)
18858
- self:F({self.SpawnTemplatePrefix,Positions})
18859
19146
  self.SpawnUnitsWithRelativePositions=true
18860
19147
  self.UnitsRelativePositions=Positions
18861
19148
  return self
18862
19149
  end
18863
19150
  function SPAWN:InitSetUnitAbsolutePositions(Positions)
18864
- self:F({self.SpawnTemplatePrefix,Positions})
18865
19151
  self.SpawnUnitsWithAbsolutePositions=true
18866
19152
  self.UnitsAbsolutePositions=Positions
18867
19153
  return self
18868
19154
  end
18869
19155
  function SPAWN:InitRandomizeTemplate(SpawnTemplatePrefixTable)
18870
- self:F({self.SpawnTemplatePrefix,SpawnTemplatePrefixTable})
18871
19156
  local temptable={}
18872
19157
  for _,_temp in pairs(SpawnTemplatePrefixTable)do
18873
19158
  temptable[#temptable+1]=_temp
@@ -18880,24 +19165,20 @@ end
18880
19165
  return self
18881
19166
  end
18882
19167
  function SPAWN:InitRandomizeTemplateSet(SpawnTemplateSet)
18883
- self:F({self.SpawnTemplatePrefix})
18884
19168
  local setnames=SpawnTemplateSet:GetSetNames()
18885
19169
  self:InitRandomizeTemplate(setnames)
18886
19170
  return self
18887
19171
  end
18888
19172
  function SPAWN:InitRandomizeTemplatePrefixes(SpawnTemplatePrefixes)
18889
- self:F({self.SpawnTemplatePrefix})
18890
19173
  local SpawnTemplateSet=SET_GROUP:New():FilterPrefixes(SpawnTemplatePrefixes):FilterOnce()
18891
19174
  self:InitRandomizeTemplateSet(SpawnTemplateSet)
18892
19175
  return self
18893
19176
  end
18894
19177
  function SPAWN:InitGrouping(Grouping)
18895
- self:F({self.SpawnTemplatePrefix,Grouping})
18896
19178
  self.SpawnGrouping=Grouping
18897
19179
  return self
18898
19180
  end
18899
19181
  function SPAWN:InitRandomizeZones(SpawnZoneTable)
18900
- self:F({self.SpawnTemplatePrefix,SpawnZoneTable})
18901
19182
  local temptable={}
18902
19183
  for _,_temp in pairs(SpawnZoneTable)do
18903
19184
  temptable[#temptable+1]=_temp
@@ -18923,59 +19204,54 @@ self.SpawnInitCallSignName=string.lower(Name):gsub("^%l",string.upper)
18923
19204
  return self
18924
19205
  end
18925
19206
  function SPAWN:InitPositionCoordinate(Coordinate)
18926
- self:T({self.SpawnTemplatePrefix,Coordinate:GetVec2()})
19207
+ self:T2({self.SpawnTemplatePrefix,Coordinate:GetVec2()})
18927
19208
  self:InitPositionVec2(Coordinate:GetVec2())
18928
19209
  return self
18929
19210
  end
18930
19211
  function SPAWN:InitPositionVec2(Vec2)
18931
- self:T({self.SpawnTemplatePrefix,Vec2})
19212
+ self:T2({self.SpawnTemplatePrefix,Vec2})
18932
19213
  self.SpawnInitPosition=Vec2
18933
19214
  self.SpawnFromNewPosition=true
18934
- self:I("MaxGroups:"..self.SpawnMaxGroups)
19215
+ self:T2("MaxGroups:"..self.SpawnMaxGroups)
18935
19216
  for SpawnGroupID=1,self.SpawnMaxGroups do
18936
19217
  self:_SetInitialPosition(SpawnGroupID)
18937
19218
  end
18938
19219
  return self
18939
19220
  end
18940
19221
  function SPAWN:InitRepeat()
18941
- self:F({self.SpawnTemplatePrefix,self.SpawnIndex})
18942
19222
  self.Repeat=true
18943
19223
  self.RepeatOnEngineShutDown=false
18944
19224
  self.RepeatOnLanding=true
18945
19225
  return self
18946
19226
  end
18947
19227
  function SPAWN:InitRepeatOnLanding()
18948
- self:F({self.SpawnTemplatePrefix})
18949
19228
  self:InitRepeat()
18950
19229
  self.RepeatOnEngineShutDown=false
18951
19230
  self.RepeatOnLanding=true
18952
19231
  return self
18953
19232
  end
18954
19233
  function SPAWN:InitRepeatOnEngineShutDown()
18955
- self:F({self.SpawnTemplatePrefix})
18956
19234
  self:InitRepeat()
18957
19235
  self.RepeatOnEngineShutDown=true
18958
19236
  self.RepeatOnLanding=false
18959
19237
  return self
18960
19238
  end
18961
19239
  function SPAWN:InitCleanUp(SpawnCleanUpInterval)
18962
- self:F({self.SpawnTemplatePrefix,SpawnCleanUpInterval})
18963
19240
  self.SpawnCleanUpInterval=SpawnCleanUpInterval
18964
19241
  self.SpawnCleanUpTimeStamps={}
18965
19242
  local SpawnGroup,SpawnCursor=self:GetFirstAliveGroup()
18966
- self:T({"CleanUp Scheduler:",SpawnGroup})
19243
+ self:T2({"CleanUp Scheduler:",SpawnGroup})
18967
19244
  self.CleanUpScheduler=SCHEDULER:New(self,self._SpawnCleanUpScheduler,{},1,SpawnCleanUpInterval,0.2)
18968
19245
  return self
18969
19246
  end
18970
19247
  function SPAWN:InitArray(SpawnAngle,SpawnWidth,SpawnDeltaX,SpawnDeltaY)
18971
- self:F({self.SpawnTemplatePrefix,SpawnAngle,SpawnWidth,SpawnDeltaX,SpawnDeltaY})
18972
19248
  self.SpawnVisible=true
18973
19249
  local SpawnX=0
18974
19250
  local SpawnY=0
18975
19251
  local SpawnXIndex=0
18976
19252
  local SpawnYIndex=0
18977
19253
  for SpawnGroupID=1,self.SpawnMaxGroups do
18978
- self:T({SpawnX,SpawnY,SpawnXIndex,SpawnYIndex})
19254
+ self:T2({SpawnX,SpawnY,SpawnXIndex,SpawnYIndex})
18979
19255
  self.SpawnGroups[SpawnGroupID].Visible=true
18980
19256
  self.SpawnGroups[SpawnGroupID].Spawned=false
18981
19257
  SpawnXIndex=SpawnXIndex+1
@@ -18992,9 +19268,9 @@ self.SpawnGroups[SpawnGroupID].SpawnTemplate.lateActivation=true
18992
19268
  self.SpawnGroups[SpawnGroupID].SpawnTemplate.visible=true
18993
19269
  self.SpawnGroups[SpawnGroupID].Visible=true
18994
19270
  self:HandleEvent(EVENTS.Birth,self._OnBirth)
18995
- self:HandleEvent(EVENTS.Dead,self._OnDeadOrCrash)
18996
19271
  self:HandleEvent(EVENTS.Crash,self._OnDeadOrCrash)
18997
19272
  self:HandleEvent(EVENTS.RemoveUnit,self._OnDeadOrCrash)
19273
+ self:HandleEvent(EVENTS.UnitLost,self._OnDeadOrCrash)
18998
19274
  if self.Repeat then
18999
19275
  self:HandleEvent(EVENTS.Takeoff,self._OnTakeOff)
19000
19276
  self:HandleEvent(EVENTS.Land,self._OnLand)
@@ -19008,6 +19284,19 @@ SpawnY=SpawnYIndex*SpawnDeltaY
19008
19284
  end
19009
19285
  return self
19010
19286
  end
19287
+ function SPAWN:StopRepeat()
19288
+ if self.Repeat then
19289
+ self:UnHandleEvent(EVENTS.Takeoff)
19290
+ self:UnHandleEvent(EVENTS.Land)
19291
+ end
19292
+ if self.RepeatOnEngineShutDown then
19293
+ self:UnHandleEvent(EVENTS.EngineShutdown)
19294
+ end
19295
+ self.Repeat=false
19296
+ self.RepeatOnEngineShutDown=false
19297
+ self.RepeatOnLanding=false
19298
+ return self
19299
+ end
19011
19300
  do
19012
19301
  function SPAWN:InitAIOnOff(AIOnOff)
19013
19302
  self.AIOnOff=AIOnOff
@@ -19032,8 +19321,8 @@ function SPAWN:InitDelayOff()
19032
19321
  return self:InitDelayOnOff(false)
19033
19322
  end
19034
19323
  end
19035
- function SPAWN:InitHiddenOnMap()
19036
- self.SpawnHiddenOnMap=true
19324
+ function SPAWN:InitHiddenOnMap(OnOff)
19325
+ self.SpawnHiddenOnMap=OnOff==false and false or true
19037
19326
  return self
19038
19327
  end
19039
19328
  function SPAWN:InitHiddenOnMFD()
@@ -19045,7 +19334,6 @@ self.SpawnHiddenOnPlanner=true
19045
19334
  return self
19046
19335
  end
19047
19336
  function SPAWN:Spawn()
19048
- self:F({self.SpawnTemplatePrefix,self.SpawnIndex,self.AliveUnits})
19049
19337
  if self.SpawnInitAirbase then
19050
19338
  return self:SpawnAtAirbase(self.SpawnInitAirbase,self.SpawnInitTakeoff,nil,self.SpawnInitTerminalType)
19051
19339
  else
@@ -19053,7 +19341,6 @@ return self:SpawnWithIndex(self.SpawnIndex+1)
19053
19341
  end
19054
19342
  end
19055
19343
  function SPAWN:ReSpawn(SpawnIndex)
19056
- self:F({self.SpawnTemplatePrefix,SpawnIndex})
19057
19344
  if not SpawnIndex then
19058
19345
  SpawnIndex=1
19059
19346
  end
@@ -19070,17 +19357,29 @@ if SpawnGroup and WayPoints then
19070
19357
  SpawnGroup:WayPointInitialize(WayPoints)
19071
19358
  SpawnGroup:WayPointExecute(1,5)
19072
19359
  end
19073
- if SpawnGroup.ReSpawnFunction then
19360
+ if SpawnGroup and SpawnGroup.ReSpawnFunction then
19074
19361
  SpawnGroup:ReSpawnFunction()
19075
19362
  end
19076
- SpawnGroup:ResetEvents()
19363
+ if SpawnGroup then SpawnGroup:ResetEvents()end
19077
19364
  return SpawnGroup
19078
19365
  end
19079
19366
  function SPAWN:SetSpawnIndex(SpawnIndex)
19080
19367
  self.SpawnIndex=SpawnIndex or 0
19081
19368
  end
19082
19369
  function SPAWN:SpawnWithIndex(SpawnIndex,NoBirth)
19083
- self:F2({SpawnTemplatePrefix=self.SpawnTemplatePrefix,SpawnIndex=SpawnIndex,AliveUnits=self.AliveUnits,SpawnMaxGroups=self.SpawnMaxGroups})
19370
+ local set=SET_GROUP:New():FilterAlive():FilterPrefixes({self.SpawnTemplatePrefix,self.SpawnAliasPrefix}):FilterOnce()
19371
+ local aliveunits=0
19372
+ set:ForEachGroupAlive(
19373
+ function(grp)
19374
+ aliveunits=aliveunits+grp:CountAliveUnits()
19375
+ end
19376
+ )
19377
+ if aliveunits~=self.AliveUnits then
19378
+ self.AliveUnits=aliveunits
19379
+ self:T2("***** self.AliveUnits accounting failure! Corrected! *****")
19380
+ end
19381
+ set=nil
19382
+ self:T2({SpawnTemplatePrefix=self.SpawnTemplatePrefix,SpawnIndex=SpawnIndex,AliveUnits=self.AliveUnits,SpawnMaxGroups=self.SpawnMaxGroups})
19084
19383
  if self:_GetSpawnIndex(SpawnIndex)then
19085
19384
  if self.SpawnFromNewPosition then
19086
19385
  self:_SetInitialPosition(SpawnIndex)
@@ -19090,10 +19389,10 @@ self.SpawnGroups[self.SpawnIndex].Group:Activate()
19090
19389
  else
19091
19390
  local SpawnTemplate=self.SpawnGroups[self.SpawnIndex].SpawnTemplate
19092
19391
  local SpawnZone=self.SpawnGroups[self.SpawnIndex].SpawnZone
19093
- self:T(SpawnTemplate.name)
19392
+ self:T2(SpawnTemplate.name)
19094
19393
  if SpawnTemplate then
19095
19394
  local PointVec3=POINT_VEC3:New(SpawnTemplate.route.points[1].x,SpawnTemplate.route.points[1].alt,SpawnTemplate.route.points[1].y)
19096
- self:T({"Current point of ",self.SpawnTemplatePrefix,PointVec3})
19395
+ self:T2({"Current point of ",self.SpawnTemplatePrefix,PointVec3})
19097
19396
  if self.SpawnRandomizePosition then
19098
19397
  local RandomVec2=PointVec3:GetRandomVec2InRadius(self.SpawnRandomizePositionOuterRadius,self.SpawnRandomizePositionInnerRadius)
19099
19398
  local CurrentX=SpawnTemplate.units[1].x
@@ -19103,7 +19402,7 @@ SpawnTemplate.y=RandomVec2.y
19103
19402
  for UnitID=1,#SpawnTemplate.units do
19104
19403
  SpawnTemplate.units[UnitID].x=SpawnTemplate.units[UnitID].x+(RandomVec2.x-CurrentX)
19105
19404
  SpawnTemplate.units[UnitID].y=SpawnTemplate.units[UnitID].y+(RandomVec2.y-CurrentY)
19106
- self:T('SpawnTemplate.units['..UnitID..'].x = '..SpawnTemplate.units[UnitID].x..', SpawnTemplate.units['..UnitID..'].y = '..SpawnTemplate.units[UnitID].y)
19405
+ self:T2('SpawnTemplate.units['..UnitID..'].x = '..SpawnTemplate.units[UnitID].x..', SpawnTemplate.units['..UnitID..'].y = '..SpawnTemplate.units[UnitID].y)
19107
19406
  end
19108
19407
  end
19109
19408
  if self.SpawnRandomizeUnits then
@@ -19117,18 +19416,16 @@ if not inZone then
19117
19416
  RandomVec2=PointVec3:GetRandomVec2InRadius(self.SpawnOuterRadius,self.SpawnInnerRadius)
19118
19417
  numTries=numTries+1
19119
19418
  inZone=SpawnZone:IsVec2InZone(RandomVec2)
19120
- self:I("Retrying "..numTries.."spawn "..SpawnTemplate.name.." in Zone "..SpawnZone:GetName().."!")
19121
- self:I(SpawnZone)
19122
19419
  end
19123
19420
  end
19124
19421
  if(not inZone)then
19125
- self:I("Could not place unit within zone and within radius!")
19422
+ self:T2("Could not place unit within zone and within radius!")
19126
19423
  RandomVec2=SpawnZone:GetRandomVec2()
19127
19424
  end
19128
19425
  end
19129
19426
  SpawnTemplate.units[UnitID].x=RandomVec2.x
19130
19427
  SpawnTemplate.units[UnitID].y=RandomVec2.y
19131
- self:T('SpawnTemplate.units['..UnitID..'].x = '..SpawnTemplate.units[UnitID].x..', SpawnTemplate.units['..UnitID..'].y = '..SpawnTemplate.units[UnitID].y)
19428
+ self:T2('SpawnTemplate.units['..UnitID..'].x = '..SpawnTemplate.units[UnitID].x..', SpawnTemplate.units['..UnitID..'].y = '..SpawnTemplate.units[UnitID].y)
19132
19429
  end
19133
19430
  end
19134
19431
  local function _Heading(courseDeg)
@@ -19243,7 +19540,7 @@ if self.SpawnHiddenOnMFD then
19243
19540
  SpawnTemplate.hiddenOnMFD=true
19244
19541
  end
19245
19542
  if self.SpawnHiddenOnMap then
19246
- SpawnTemplate.hidden=true
19543
+ SpawnTemplate.hidden=self.SpawnHiddenOnMap
19247
19544
  end
19248
19545
  SpawnTemplate.CategoryID=self.SpawnInitCategory or SpawnTemplate.CategoryID
19249
19546
  SpawnTemplate.CountryID=self.SpawnInitCountry or SpawnTemplate.CountryID
@@ -19252,8 +19549,8 @@ end
19252
19549
  if not NoBirth then
19253
19550
  self:HandleEvent(EVENTS.Birth,self._OnBirth)
19254
19551
  end
19255
- self:HandleEvent(EVENTS.Dead,self._OnDeadOrCrash)
19256
19552
  self:HandleEvent(EVENTS.Crash,self._OnDeadOrCrash)
19553
+ self:HandleEvent(EVENTS.UnitLost,self._OnDeadOrCrash)
19257
19554
  self:HandleEvent(EVENTS.RemoveUnit,self._OnDeadOrCrash)
19258
19555
  if self.Repeat then
19259
19556
  self:HandleEvent(EVENTS.Takeoff,self._OnTakeOff)
@@ -19280,7 +19577,6 @@ end
19280
19577
  return nil
19281
19578
  end
19282
19579
  function SPAWN:SpawnScheduled(SpawnTime,SpawnTimeVariation,WithDelay)
19283
- self:F({SpawnTime,SpawnTimeVariation})
19284
19580
  local SpawnTime=SpawnTime or 60
19285
19581
  local SpawnTimeVariation=SpawnTimeVariation or 0.5
19286
19582
  if SpawnTime~=nil and SpawnTimeVariation~=nil then
@@ -19293,17 +19589,14 @@ end
19293
19589
  return self
19294
19590
  end
19295
19591
  function SPAWN:SpawnScheduleStart()
19296
- self:F({self.SpawnTemplatePrefix})
19297
19592
  self.SpawnScheduler:Start()
19298
19593
  return self
19299
19594
  end
19300
19595
  function SPAWN:SpawnScheduleStop()
19301
- self:F({self.SpawnTemplatePrefix})
19302
19596
  self.SpawnScheduler:Stop()
19303
19597
  return self
19304
19598
  end
19305
19599
  function SPAWN:OnSpawnGroup(SpawnCallBackFunction,...)
19306
- self:F("OnSpawnGroup")
19307
19600
  self.SpawnFunctionHook=SpawnCallBackFunction
19308
19601
  self.SpawnFunctionArguments={}
19309
19602
  if arg then
@@ -19312,21 +19605,17 @@ end
19312
19605
  return self
19313
19606
  end
19314
19607
  function SPAWN:SpawnAtAirbase(SpawnAirbase,Takeoff,TakeoffAltitude,TerminalType,EmergencyAirSpawn,Parkingdata)
19315
- self:F({self.SpawnTemplatePrefix,SpawnAirbase,Takeoff,TakeoffAltitude,TerminalType})
19316
19608
  local PointVec3=SpawnAirbase:GetCoordinate()
19317
19609
  self:T2(PointVec3)
19318
19610
  Takeoff=Takeoff or SPAWN.Takeoff.Hot
19319
19611
  if EmergencyAirSpawn==nil then
19320
19612
  EmergencyAirSpawn=true
19321
19613
  end
19322
- self:F({SpawnIndex=self.SpawnIndex})
19323
19614
  if self:_GetSpawnIndex(self.SpawnIndex+1)then
19324
19615
  local SpawnTemplate=self.SpawnGroups[self.SpawnIndex].SpawnTemplate
19325
- self:F({SpawnTemplate=SpawnTemplate})
19326
19616
  if SpawnTemplate then
19327
19617
  local GroupAlive=self:GetGroupFromIndex(self.SpawnIndex)
19328
- self:F({GroupAlive=GroupAlive})
19329
- self:T({"Current point of ",self.SpawnTemplatePrefix,SpawnAirbase})
19618
+ self:T2({"Current point of ",self.SpawnTemplatePrefix,SpawnAirbase})
19330
19619
  local TemplateGroup=GROUP:FindByName(self.SpawnTemplatePrefix)
19331
19620
  local TemplateUnit=TemplateGroup:GetUnit(1)
19332
19621
  local group=TemplateGroup
@@ -19343,7 +19632,6 @@ SpawnPoint.helipadId=nil
19343
19632
  SpawnPoint.airdromeId=nil
19344
19633
  local AirbaseID=SpawnAirbase:GetID()
19345
19634
  local AirbaseCategory=SpawnAirbase:GetAirbaseCategory()
19346
- self:F({AirbaseCategory=AirbaseCategory})
19347
19635
  if AirbaseCategory==Airbase.Category.SHIP then
19348
19636
  SpawnPoint.linkUnit=AirbaseID
19349
19637
  SpawnPoint.helipadId=AirbaseID
@@ -19357,7 +19645,7 @@ SpawnPoint.alt=0
19357
19645
  SpawnPoint.type=GROUPTEMPLATE.Takeoff[Takeoff][1]
19358
19646
  SpawnPoint.action=GROUPTEMPLATE.Takeoff[Takeoff][2]
19359
19647
  local spawnonground=not(Takeoff==SPAWN.Takeoff.Air)
19360
- self:T({spawnonground=spawnonground,TOtype=Takeoff,TOair=Takeoff==SPAWN.Takeoff.Air})
19648
+ self:T2({spawnonground=spawnonground,TOtype=Takeoff,TOair=Takeoff==SPAWN.Takeoff.Air})
19361
19649
  local spawnonship=false
19362
19650
  local spawnonfarp=false
19363
19651
  local spawnonrunway=false
@@ -19395,43 +19683,43 @@ local scanstatics=true
19395
19683
  local scanscenery=false
19396
19684
  local verysafe=false
19397
19685
  if spawnonship or spawnonfarp or spawnonrunway then
19398
- self:T(string.format("Group %s is spawned on farp/ship/runway %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
19686
+ self:T2(string.format("Group %s is spawned on farp/ship/runway %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
19399
19687
  nfree=SpawnAirbase:GetFreeParkingSpotsNumber(termtype,true)
19400
19688
  spots=SpawnAirbase:GetFreeParkingSpotsTable(termtype,true)
19401
19689
  else
19402
19690
  if ishelo then
19403
19691
  if termtype==nil then
19404
- self:T(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.HelicopterOnly))
19692
+ self:T2(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.HelicopterOnly))
19405
19693
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.HelicopterOnly,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19406
19694
  nfree=#spots
19407
19695
  if nfree<nunits then
19408
- self:T(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.HelicopterUsable))
19696
+ self:T2(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.HelicopterUsable))
19409
19697
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.HelicopterUsable,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19410
19698
  nfree=#spots
19411
19699
  end
19412
19700
  else
19413
- self:T(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),termtype))
19701
+ self:T2(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),termtype))
19414
19702
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,termtype,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19415
19703
  nfree=#spots
19416
19704
  end
19417
19705
  else
19418
19706
  if termtype==nil then
19419
19707
  if isbomber or istransport or istanker or isawacs then
19420
- self:T(string.format("Transport/bomber group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.OpenBig))
19708
+ self:T2(string.format("Transport/bomber group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.OpenBig))
19421
19709
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.OpenBig,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19422
19710
  nfree=#spots
19423
19711
  if nfree<nunits then
19424
- self:T(string.format("Transport/bomber group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.OpenMedOrBig))
19712
+ self:T2(string.format("Transport/bomber group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.OpenMedOrBig))
19425
19713
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.OpenMedOrBig,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19426
19714
  nfree=#spots
19427
19715
  end
19428
19716
  else
19429
- self:T(string.format("Fighter group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.FighterAircraft))
19717
+ self:T2(string.format("Fighter group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.FighterAircraft))
19430
19718
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.FighterAircraft,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19431
19719
  nfree=#spots
19432
19720
  end
19433
19721
  else
19434
- self:T(string.format("Plane group %s is at %s using terminal type %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),tostring(termtype)))
19722
+ self:T2(string.format("Plane group %s is at %s using terminal type %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),tostring(termtype)))
19435
19723
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,termtype,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19436
19724
  nfree=#spots
19437
19725
  end
@@ -19504,18 +19792,18 @@ local TX=PointVec3.x+(SX-BX)
19504
19792
  local TY=PointVec3.z+(SY-BY)
19505
19793
  if spawnonground then
19506
19794
  if spawnonship or spawnonfarp or spawnonrunway then
19507
- self:T(string.format("Group %s spawning at farp, ship or runway %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
19795
+ self:T2(string.format("Group %s spawning at farp, ship or runway %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
19508
19796
  SpawnTemplate.units[UnitID].x=PointVec3.x
19509
19797
  SpawnTemplate.units[UnitID].y=PointVec3.z
19510
19798
  SpawnTemplate.units[UnitID].alt=PointVec3.y
19511
19799
  else
19512
- self:T(string.format("Group %s spawning at airbase %s on parking spot id %d",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),parkingindex[UnitID]))
19800
+ self:T2(string.format("Group %s spawning at airbase %s on parking spot id %d",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),parkingindex[UnitID]))
19513
19801
  SpawnTemplate.units[UnitID].x=parkingspots[UnitID].x
19514
19802
  SpawnTemplate.units[UnitID].y=parkingspots[UnitID].z
19515
19803
  SpawnTemplate.units[UnitID].alt=parkingspots[UnitID].y
19516
19804
  end
19517
19805
  else
19518
- self:T(string.format("Group %s spawning in air at %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
19806
+ self:T2(string.format("Group %s spawning in air at %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
19519
19807
  SpawnTemplate.units[UnitID].x=TX
19520
19808
  SpawnTemplate.units[UnitID].y=TY
19521
19809
  SpawnTemplate.units[UnitID].alt=PointVec3.y
@@ -19525,8 +19813,8 @@ UnitTemplate.parking_id=nil
19525
19813
  if parkingindex[UnitID]then
19526
19814
  UnitTemplate.parking=parkingindex[UnitID]
19527
19815
  end
19528
- self:T(string.format("Group %s unit number %d: Parking = %s",self.SpawnTemplatePrefix,UnitID,tostring(UnitTemplate.parking)))
19529
- self:T(string.format("Group %s unit number %d: Parking ID = %s",self.SpawnTemplatePrefix,UnitID,tostring(UnitTemplate.parking_id)))
19816
+ self:T2(string.format("Group %s unit number %d: Parking = %s",self.SpawnTemplatePrefix,UnitID,tostring(UnitTemplate.parking)))
19817
+ self:T2(string.format("Group %s unit number %d: Parking ID = %s",self.SpawnTemplatePrefix,UnitID,tostring(UnitTemplate.parking_id)))
19530
19818
  self:T2('After Translation SpawnTemplate.units['..UnitID..'].x = '..SpawnTemplate.units[UnitID].x..', SpawnTemplate.units['..UnitID..'].y = '..SpawnTemplate.units[UnitID].y)
19531
19819
  end
19532
19820
  end
@@ -19551,7 +19839,6 @@ end
19551
19839
  return nil
19552
19840
  end
19553
19841
  function SPAWN:SpawnAtParkingSpot(Airbase,Spots,Takeoff)
19554
- self:F({Airbase=Airbase,Spots=Spots,Takeoff=Takeoff})
19555
19842
  if type(Spots)~="table"then
19556
19843
  Spots={Spots}
19557
19844
  end
@@ -19570,7 +19857,7 @@ for _,TerminalID in pairs(Spots)do
19570
19857
  local spot=Airbase:GetParkingSpotData(TerminalID)
19571
19858
  self:T2({spot=spot})
19572
19859
  if spot and spot.Free then
19573
- self:T(string.format("Adding parking spot ID=%d TermType=%d",spot.TerminalID,spot.TerminalType))
19860
+ self:T2(string.format("Adding parking spot ID=%d TermType=%d",spot.TerminalID,spot.TerminalType))
19574
19861
  table.insert(Parkingdata,spot)
19575
19862
  end
19576
19863
  end
@@ -19585,14 +19872,13 @@ end
19585
19872
  return nil
19586
19873
  end
19587
19874
  function SPAWN:ParkAircraft(SpawnAirbase,TerminalType,Parkingdata,SpawnIndex)
19588
- self:F({SpawnIndex=SpawnIndex,SpawnMaxGroups=self.SpawnMaxGroups})
19589
19875
  local PointVec3=SpawnAirbase:GetCoordinate()
19590
19876
  self:T2(PointVec3)
19591
19877
  local Takeoff=SPAWN.Takeoff.Cold
19592
19878
  local SpawnTemplate=self.SpawnGroups[SpawnIndex].SpawnTemplate
19593
19879
  if SpawnTemplate then
19594
19880
  local GroupAlive=self:GetGroupFromIndex(SpawnIndex)
19595
- self:T({"Current point of ",self.SpawnTemplatePrefix,SpawnAirbase})
19881
+ self:T2({"Current point of ",self.SpawnTemplatePrefix,SpawnAirbase})
19596
19882
  local TemplateGroup=GROUP:FindByName(self.SpawnTemplatePrefix)
19597
19883
  local TemplateUnit=TemplateGroup:GetUnit(1)
19598
19884
  local ishelo=TemplateUnit:HasAttribute("Helicopters")
@@ -19606,7 +19892,6 @@ SpawnPoint.helipadId=nil
19606
19892
  SpawnPoint.airdromeId=nil
19607
19893
  local AirbaseID=SpawnAirbase:GetID()
19608
19894
  local AirbaseCategory=SpawnAirbase:GetAirbaseCategory()
19609
- self:F({AirbaseCategory=AirbaseCategory})
19610
19895
  if AirbaseCategory==Airbase.Category.SHIP then
19611
19896
  SpawnPoint.linkUnit=AirbaseID
19612
19897
  SpawnPoint.helipadId=AirbaseID
@@ -19620,7 +19905,7 @@ SpawnPoint.alt=0
19620
19905
  SpawnPoint.type=GROUPTEMPLATE.Takeoff[Takeoff][1]
19621
19906
  SpawnPoint.action=GROUPTEMPLATE.Takeoff[Takeoff][2]
19622
19907
  local spawnonground=not(Takeoff==SPAWN.Takeoff.Air)
19623
- self:T({spawnonground=spawnonground,TOtype=Takeoff,TOair=Takeoff==SPAWN.Takeoff.Air})
19908
+ self:T2({spawnonground=spawnonground,TOtype=Takeoff,TOair=Takeoff==SPAWN.Takeoff.Air})
19624
19909
  local spawnonship=false
19625
19910
  local spawnonfarp=false
19626
19911
  local spawnonrunway=false
@@ -19647,43 +19932,43 @@ local scanstatics=true
19647
19932
  local scanscenery=false
19648
19933
  local verysafe=false
19649
19934
  if spawnonship or spawnonfarp or spawnonrunway then
19650
- self:T(string.format("Group %s is spawned on farp/ship/runway %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
19935
+ self:T2(string.format("Group %s is spawned on farp/ship/runway %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
19651
19936
  nfree=SpawnAirbase:GetFreeParkingSpotsNumber(termtype,true)
19652
19937
  spots=SpawnAirbase:GetFreeParkingSpotsTable(termtype,true)
19653
19938
  else
19654
19939
  if ishelo then
19655
19940
  if termtype==nil then
19656
- self:T(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.HelicopterOnly))
19941
+ self:T2(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.HelicopterOnly))
19657
19942
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.HelicopterOnly,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19658
19943
  nfree=#spots
19659
19944
  if nfree<nunits then
19660
- self:T(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.HelicopterUsable))
19945
+ self:T2(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.HelicopterUsable))
19661
19946
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.HelicopterUsable,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19662
19947
  nfree=#spots
19663
19948
  end
19664
19949
  else
19665
- self:T(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),termtype))
19950
+ self:T2(string.format("Helo group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),termtype))
19666
19951
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,termtype,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19667
19952
  nfree=#spots
19668
19953
  end
19669
19954
  else
19670
19955
  if termtype==nil then
19671
19956
  if isbomber or istransport then
19672
- self:T(string.format("Transport/bomber group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.OpenBig))
19957
+ self:T2(string.format("Transport/bomber group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.OpenBig))
19673
19958
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.OpenBig,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19674
19959
  nfree=#spots
19675
19960
  if nfree<nunits then
19676
- self:T(string.format("Transport/bomber group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.OpenMedOrBig))
19961
+ self:T2(string.format("Transport/bomber group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.OpenMedOrBig))
19677
19962
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.OpenMedOrBig,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19678
19963
  nfree=#spots
19679
19964
  end
19680
19965
  else
19681
- self:T(string.format("Fighter group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.FighterAircraft))
19966
+ self:T2(string.format("Fighter group %s is at %s using terminal type %d.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),AIRBASE.TerminalType.FighterAircraft))
19682
19967
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.FighterAircraft,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19683
19968
  nfree=#spots
19684
19969
  end
19685
19970
  else
19686
- self:T(string.format("Plane group %s is at %s using terminal type %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),tostring(termtype)))
19971
+ self:T2(string.format("Plane group %s is at %s using terminal type %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),tostring(termtype)))
19687
19972
  spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup,termtype,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits,Parkingdata)
19688
19973
  nfree=#spots
19689
19974
  end
@@ -19722,7 +20007,6 @@ end
19722
20007
  if not SpawnTemplate.parked then
19723
20008
  SpawnTemplate.parked=true
19724
20009
  for UnitID=1,nunits do
19725
- self:F('Before Translation SpawnTemplate.units['..UnitID..'].x = '..SpawnTemplate.units[UnitID].x..', SpawnTemplate.units['..UnitID..'].y = '..SpawnTemplate.units[UnitID].y)
19726
20010
  local UnitTemplate=SpawnTemplate.units[UnitID]
19727
20011
  local SX=UnitTemplate.x
19728
20012
  local SY=UnitTemplate.y
@@ -19732,18 +20016,18 @@ local TX=PointVec3.x+(SX-BX)
19732
20016
  local TY=PointVec3.z+(SY-BY)
19733
20017
  if spawnonground then
19734
20018
  if spawnonship or spawnonfarp or spawnonrunway then
19735
- self:T(string.format("Group %s spawning at farp, ship or runway %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
20019
+ self:T2(string.format("Group %s spawning at farp, ship or runway %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
19736
20020
  SpawnTemplate.units[UnitID].x=PointVec3.x
19737
20021
  SpawnTemplate.units[UnitID].y=PointVec3.z
19738
20022
  SpawnTemplate.units[UnitID].alt=PointVec3.y
19739
20023
  else
19740
- self:T(string.format("Group %s spawning at airbase %s on parking spot id %d",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),parkingindex[UnitID]))
20024
+ self:T2(string.format("Group %s spawning at airbase %s on parking spot id %d",self.SpawnTemplatePrefix,SpawnAirbase:GetName(),parkingindex[UnitID]))
19741
20025
  SpawnTemplate.units[UnitID].x=parkingspots[UnitID].x
19742
20026
  SpawnTemplate.units[UnitID].y=parkingspots[UnitID].z
19743
20027
  SpawnTemplate.units[UnitID].alt=parkingspots[UnitID].y
19744
20028
  end
19745
20029
  else
19746
- self:T(string.format("Group %s spawning in air at %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
20030
+ self:T2(string.format("Group %s spawning in air at %s.",self.SpawnTemplatePrefix,SpawnAirbase:GetName()))
19747
20031
  SpawnTemplate.units[UnitID].x=TX
19748
20032
  SpawnTemplate.units[UnitID].y=TY
19749
20033
  SpawnTemplate.units[UnitID].alt=PointVec3.y
@@ -19776,7 +20060,6 @@ end
19776
20060
  end
19777
20061
  end
19778
20062
  function SPAWN:ParkAtAirbase(SpawnAirbase,TerminalType,Parkingdata)
19779
- self:F({self.SpawnTemplatePrefix,SpawnAirbase,TerminalType})
19780
20063
  self:ParkAircraft(SpawnAirbase,TerminalType,Parkingdata,1)
19781
20064
  for SpawnIndex=2,self.SpawnMaxGroups do
19782
20065
  self:ParkAircraft(SpawnAirbase,TerminalType,Parkingdata,SpawnIndex)
@@ -19785,7 +20068,6 @@ self:SetSpawnIndex(0)
19785
20068
  return nil
19786
20069
  end
19787
20070
  function SPAWN:SpawnFromVec3(Vec3,SpawnIndex)
19788
- self:F({self.SpawnTemplatePrefix,Vec3,SpawnIndex})
19789
20071
  local PointVec3=POINT_VEC3:NewFromVec3(Vec3)
19790
20072
  self:T2(PointVec3)
19791
20073
  if SpawnIndex then
@@ -19795,7 +20077,7 @@ end
19795
20077
  if self:_GetSpawnIndex(SpawnIndex)then
19796
20078
  local SpawnTemplate=self.SpawnGroups[self.SpawnIndex].SpawnTemplate
19797
20079
  if SpawnTemplate then
19798
- self:T({"Current point of ",self.SpawnTemplatePrefix,Vec3})
20080
+ self:T2({"Current point of ",self.SpawnTemplatePrefix,Vec3})
19799
20081
  local TemplateHeight=SpawnTemplate.route and SpawnTemplate.route.points[1].alt or nil
19800
20082
  SpawnTemplate.route=SpawnTemplate.route or{}
19801
20083
  SpawnTemplate.route.points=SpawnTemplate.route.points or{}
@@ -19815,7 +20097,7 @@ SpawnTemplate.units[UnitID].y=TY
19815
20097
  if SpawnTemplate.CategoryID~=Group.Category.SHIP then
19816
20098
  SpawnTemplate.units[UnitID].alt=Vec3.y or TemplateHeight
19817
20099
  end
19818
- self:T('After Translation SpawnTemplate.units['..UnitID..'].x = '..SpawnTemplate.units[UnitID].x..', SpawnTemplate.units['..UnitID..'].y = '..SpawnTemplate.units[UnitID].y)
20100
+ self:T2('After Translation SpawnTemplate.units['..UnitID..'].x = '..SpawnTemplate.units[UnitID].x..', SpawnTemplate.units['..UnitID..'].y = '..SpawnTemplate.units[UnitID].y)
19819
20101
  end
19820
20102
  SpawnTemplate.route.points[1].x=Vec3.x
19821
20103
  SpawnTemplate.route.points[1].y=Vec3.z
@@ -19831,15 +20113,12 @@ end
19831
20113
  return nil
19832
20114
  end
19833
20115
  function SPAWN:SpawnFromCoordinate(Coordinate,SpawnIndex)
19834
- self:F({self.SpawnTemplatePrefix,SpawnIndex})
19835
20116
  return self:SpawnFromVec3(Coordinate:GetVec3(),SpawnIndex)
19836
20117
  end
19837
20118
  function SPAWN:SpawnFromPointVec3(PointVec3,SpawnIndex)
19838
- self:F({self.SpawnTemplatePrefix,SpawnIndex})
19839
20119
  return self:SpawnFromVec3(PointVec3:GetVec3(),SpawnIndex)
19840
20120
  end
19841
20121
  function SPAWN:SpawnFromVec2(Vec2,MinHeight,MaxHeight,SpawnIndex)
19842
- self:F({self.SpawnTemplatePrefix,self.SpawnIndex,Vec2,MinHeight,MaxHeight,SpawnIndex})
19843
20122
  local Height=nil
19844
20123
  if MinHeight and MaxHeight then
19845
20124
  Height=math.random(MinHeight,MaxHeight)
@@ -19847,25 +20126,21 @@ end
19847
20126
  return self:SpawnFromVec3({x=Vec2.x,y=Height,z=Vec2.y},SpawnIndex)
19848
20127
  end
19849
20128
  function SPAWN:SpawnFromPointVec2(PointVec2,MinHeight,MaxHeight,SpawnIndex)
19850
- self:F({self.SpawnTemplatePrefix,self.SpawnIndex})
19851
20129
  return self:SpawnFromVec2(PointVec2:GetVec2(),MinHeight,MaxHeight,SpawnIndex)
19852
20130
  end
19853
20131
  function SPAWN:SpawnFromUnit(HostUnit,MinHeight,MaxHeight,SpawnIndex)
19854
- self:F({self.SpawnTemplatePrefix,HostUnit,MinHeight,MaxHeight,SpawnIndex})
19855
20132
  if HostUnit and HostUnit:IsAlive()~=nil then
19856
20133
  return self:SpawnFromVec2(HostUnit:GetVec2(),MinHeight,MaxHeight,SpawnIndex)
19857
20134
  end
19858
20135
  return nil
19859
20136
  end
19860
20137
  function SPAWN:SpawnFromStatic(HostStatic,MinHeight,MaxHeight,SpawnIndex)
19861
- self:F({self.SpawnTemplatePrefix,HostStatic,MinHeight,MaxHeight,SpawnIndex})
19862
20138
  if HostStatic and HostStatic:IsAlive()then
19863
20139
  return self:SpawnFromVec2(HostStatic:GetVec2(),MinHeight,MaxHeight,SpawnIndex)
19864
20140
  end
19865
20141
  return nil
19866
20142
  end
19867
20143
  function SPAWN:SpawnInZone(Zone,RandomizeGroup,MinHeight,MaxHeight,SpawnIndex)
19868
- self:F({self.SpawnTemplatePrefix,Zone,RandomizeGroup,MinHeight,MaxHeight,SpawnIndex})
19869
20144
  if Zone then
19870
20145
  if RandomizeGroup then
19871
20146
  return self:SpawnFromVec2(Zone:GetRandomVec2(),MinHeight,MaxHeight,SpawnIndex)
@@ -19891,22 +20166,20 @@ end
19891
20166
  return nil
19892
20167
  end
19893
20168
  function SPAWN:SpawnGroupName(SpawnIndex)
19894
- self:F({self.SpawnTemplatePrefix,SpawnIndex})
19895
20169
  local SpawnPrefix=self.SpawnTemplatePrefix
19896
20170
  if self.SpawnAliasPrefix then
19897
20171
  SpawnPrefix=self.SpawnAliasPrefix
19898
20172
  end
19899
20173
  if SpawnIndex then
19900
20174
  local SpawnName=string.format('%s#%03d',SpawnPrefix,SpawnIndex)
19901
- self:T(SpawnName)
20175
+ self:T2(SpawnName)
19902
20176
  return SpawnName
19903
20177
  else
19904
- self:T(SpawnPrefix)
20178
+ self:T2(SpawnPrefix)
19905
20179
  return SpawnPrefix
19906
20180
  end
19907
20181
  end
19908
20182
  function SPAWN:GetFirstAliveGroup()
19909
- self:F({self.SpawnTemplatePrefix,self.SpawnAliasPrefix})
19910
20183
  for SpawnIndex=1,self.SpawnCount do
19911
20184
  local SpawnGroup=self:GetGroupFromIndex(SpawnIndex)
19912
20185
  if SpawnGroup and SpawnGroup:IsAlive()then
@@ -19916,7 +20189,6 @@ end
19916
20189
  return nil,nil
19917
20190
  end
19918
20191
  function SPAWN:GetNextAliveGroup(SpawnIndexStart)
19919
- self:F({self.SpawnTemplatePrefix,self.SpawnAliasPrefix,SpawnIndexStart})
19920
20192
  SpawnIndexStart=SpawnIndexStart+1
19921
20193
  for SpawnIndex=SpawnIndexStart,self.SpawnCount do
19922
20194
  local SpawnGroup=self:GetGroupFromIndex(SpawnIndex)
@@ -19927,7 +20199,6 @@ end
19927
20199
  return nil,nil
19928
20200
  end
19929
20201
  function SPAWN:GetLastAliveGroup()
19930
- self:F({self.SpawnTemplatePrefix,self.SpawnAliasPrefix})
19931
20202
  for SpawnIndex=self.SpawnCount,1,-1 do
19932
20203
  local SpawnGroup=self:GetGroupFromIndex(SpawnIndex)
19933
20204
  if SpawnGroup and SpawnGroup:IsAlive()then
@@ -19939,7 +20210,6 @@ self.SpawnIndex=nil
19939
20210
  return nil
19940
20211
  end
19941
20212
  function SPAWN:GetGroupFromIndex(SpawnIndex)
19942
- self:F({self.SpawnTemplatePrefix,self.SpawnAliasPrefix,SpawnIndex})
19943
20213
  if not SpawnIndex then
19944
20214
  SpawnIndex=1
19945
20215
  end
@@ -19969,18 +20239,15 @@ end
19969
20239
  return nil
19970
20240
  end
19971
20241
  function SPAWN:GetSpawnIndexFromGroup(SpawnGroup)
19972
- self:F2({self.SpawnTemplatePrefix,self.SpawnAliasPrefix,SpawnGroup})
19973
20242
  local IndexString=string.match(SpawnGroup:GetName(),"#(%d*)$"):sub(2)
19974
20243
  local Index=tonumber(IndexString)
19975
20244
  self:T3(IndexString,Index)
19976
20245
  return Index
19977
20246
  end
19978
20247
  function SPAWN:_GetLastIndex()
19979
- self:F({self.SpawnTemplatePrefix,self.SpawnAliasPrefix})
19980
20248
  return self.SpawnMaxGroups
19981
20249
  end
19982
20250
  function SPAWN:_InitializeSpawnGroups(SpawnIndex)
19983
- self:F3({self.SpawnTemplatePrefix,self.SpawnAliasPrefix,SpawnIndex})
19984
20251
  if not self.SpawnGroups[SpawnIndex]then
19985
20252
  self.SpawnGroups[SpawnIndex]={}
19986
20253
  self.SpawnGroups[SpawnIndex].Visible=false
@@ -20011,7 +20278,6 @@ return nil
20011
20278
  end
20012
20279
  end
20013
20280
  function SPAWN:_GetGroupCountryID(SpawnPrefix)
20014
- self:F({self.SpawnTemplatePrefix,self.SpawnAliasPrefix,SpawnPrefix})
20015
20281
  local TemplateGroup=Group.getByName(SpawnPrefix)
20016
20282
  if TemplateGroup then
20017
20283
  local TemplateUnits=TemplateGroup:getUnits()
@@ -20021,13 +20287,11 @@ return nil
20021
20287
  end
20022
20288
  end
20023
20289
  function SPAWN:_GetTemplate(SpawnTemplatePrefix)
20024
- self:F({self.SpawnTemplatePrefix,self.SpawnAliasPrefix,SpawnTemplatePrefix})
20025
20290
  local SpawnTemplate=nil
20026
20291
  if _DATABASE.Templates.Groups[SpawnTemplatePrefix]==nil then
20027
20292
  error('No Template exists for SpawnTemplatePrefix = '..SpawnTemplatePrefix)
20028
20293
  end
20029
20294
  local Template=_DATABASE.Templates.Groups[SpawnTemplatePrefix].Template
20030
- self:F({Template=Template})
20031
20295
  SpawnTemplate=UTILS.DeepCopy(_DATABASE.Templates.Groups[SpawnTemplatePrefix].Template)
20032
20296
  if SpawnTemplate==nil then
20033
20297
  error('No Template returned for SpawnTemplatePrefix = '..SpawnTemplatePrefix)
@@ -20036,7 +20300,6 @@ self:T3({SpawnTemplate})
20036
20300
  return SpawnTemplate
20037
20301
  end
20038
20302
  function SPAWN:_Prepare(SpawnTemplatePrefix,SpawnIndex)
20039
- self:F({self.SpawnTemplatePrefix,self.SpawnAliasPrefix})
20040
20303
  local SpawnTemplate
20041
20304
  if self.TweakedTemplate~=nil and self.TweakedTemplate==true then
20042
20305
  BASE:I("WARNING: You are using a tweaked template.")
@@ -20058,7 +20321,6 @@ SpawnTemplate.visible=false
20058
20321
  end
20059
20322
  if self.SpawnGrouping then
20060
20323
  local UnitAmount=#SpawnTemplate.units
20061
- self:F({UnitAmount=UnitAmount,SpawnGrouping=self.SpawnGrouping})
20062
20324
  if UnitAmount>self.SpawnGrouping then
20063
20325
  for UnitID=self.SpawnGrouping+1,UnitAmount do
20064
20326
  SpawnTemplate.units[UnitID]=nil
@@ -20074,7 +20336,9 @@ end
20074
20336
  end
20075
20337
  if self.SpawnInitKeepUnitNames==false then
20076
20338
  for UnitID=1,#SpawnTemplate.units do
20339
+ if not string.find(SpawnTemplate.units[UnitID].name,"#IFF_",1,true)then
20077
20340
  SpawnTemplate.units[UnitID].name=string.format(SpawnTemplate.name..'-%02d',UnitID)
20341
+ end
20078
20342
  SpawnTemplate.units[UnitID].unitId=nil
20079
20343
  end
20080
20344
  else
@@ -20086,11 +20350,9 @@ end
20086
20350
  local UnitPrefix,Rest
20087
20351
  if SpawnInitKeepUnitIFF==false then
20088
20352
  UnitPrefix,Rest=string.match(SpawnTemplate.units[UnitID].name,"^([^#]+)#?"):gsub("^%s*(.-)%s*$","%1")
20089
- self:T({UnitPrefix,Rest})
20090
- else
20091
- UnitPrefix=SpawnTemplate.units[UnitID].name
20092
- end
20093
20353
  SpawnTemplate.units[UnitID].name=string.format('%s#%03d-%02d',UnitPrefix,SpawnIndex,UnitID)
20354
+ self:T2({UnitPrefix,Rest})
20355
+ end
20094
20356
  SpawnTemplate.units[UnitID].unitId=nil
20095
20357
  end
20096
20358
  end
@@ -20248,7 +20510,6 @@ self:T3({"Template:",SpawnTemplate})
20248
20510
  return SpawnTemplate
20249
20511
  end
20250
20512
  function SPAWN:_RandomizeRoute(SpawnIndex)
20251
- self:F({self.SpawnTemplatePrefix,SpawnIndex,self.SpawnRandomizeRoute,self.SpawnRandomizeRouteStartPoint,self.SpawnRandomizeRouteEndPoint,self.SpawnRandomizeRouteRadius})
20252
20513
  if self.SpawnRandomizeRoute then
20253
20514
  local SpawnTemplate=self.SpawnGroups[SpawnIndex].SpawnTemplate
20254
20515
  local RouteCount=#SpawnTemplate.route.points
@@ -20262,14 +20523,13 @@ end
20262
20523
  else
20263
20524
  SpawnTemplate.route.points[t].alt=nil
20264
20525
  end
20265
- self:T('SpawnTemplate.route.points['..t..'].x = '..SpawnTemplate.route.points[t].x..', SpawnTemplate.route.points['..t..'].y = '..SpawnTemplate.route.points[t].y)
20526
+ self:T2('SpawnTemplate.route.points['..t..'].x = '..SpawnTemplate.route.points[t].x..', SpawnTemplate.route.points['..t..'].y = '..SpawnTemplate.route.points[t].y)
20266
20527
  end
20267
20528
  end
20268
20529
  self:_RandomizeZones(SpawnIndex)
20269
20530
  return self
20270
20531
  end
20271
20532
  function SPAWN:_RandomizeTemplate(SpawnIndex)
20272
- self:F({self.SpawnTemplatePrefix,SpawnIndex,self.SpawnRandomizeTemplate})
20273
20533
  if self.SpawnRandomizeTemplate then
20274
20534
  self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix=self.SpawnTemplatePrefixTable[math.random(1,#self.SpawnTemplatePrefixTable)]
20275
20535
  self.SpawnGroups[SpawnIndex].SpawnTemplate=self:_Prepare(self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix,SpawnIndex)
@@ -20290,21 +20550,21 @@ self:_RandomizeRoute(SpawnIndex)
20290
20550
  return self
20291
20551
  end
20292
20552
  function SPAWN:_SetInitialPosition(SpawnIndex)
20293
- self:T({self.SpawnTemplatePrefix,SpawnIndex,self.SpawnRandomizeZones})
20553
+ self:T2({self.SpawnTemplatePrefix,SpawnIndex,self.SpawnRandomizeZones})
20294
20554
  if self.SpawnFromNewPosition then
20295
- self:T("Preparing Spawn at Vec2 ",self.SpawnInitPosition)
20555
+ self:T2("Preparing Spawn at Vec2 ",self.SpawnInitPosition)
20296
20556
  local SpawnVec2=self.SpawnInitPosition
20297
- self:T({SpawnVec2=SpawnVec2})
20557
+ self:T2({SpawnVec2=SpawnVec2})
20298
20558
  local SpawnTemplate=self.SpawnGroups[SpawnIndex].SpawnTemplate
20299
20559
  SpawnTemplate.route=SpawnTemplate.route or{}
20300
20560
  SpawnTemplate.route.points=SpawnTemplate.route.points or{}
20301
20561
  SpawnTemplate.route.points[1]=SpawnTemplate.route.points[1]or{}
20302
20562
  SpawnTemplate.route.points[1].x=SpawnTemplate.route.points[1].x or 0
20303
20563
  SpawnTemplate.route.points[1].y=SpawnTemplate.route.points[1].y or 0
20304
- self:T({Route=SpawnTemplate.route})
20564
+ self:T2({Route=SpawnTemplate.route})
20305
20565
  for UnitID=1,#SpawnTemplate.units do
20306
20566
  local UnitTemplate=SpawnTemplate.units[UnitID]
20307
- self:T('Before Translation SpawnTemplate.units['..UnitID..'].x = '..UnitTemplate.x..', SpawnTemplate.units['..UnitID..'].y = '..UnitTemplate.y)
20567
+ self:T2('Before Translation SpawnTemplate.units['..UnitID..'].x = '..UnitTemplate.x..', SpawnTemplate.units['..UnitID..'].y = '..UnitTemplate.y)
20308
20568
  local SX=UnitTemplate.x
20309
20569
  local SY=UnitTemplate.y
20310
20570
  local BX=SpawnTemplate.route.points[1].x
@@ -20313,7 +20573,7 @@ local TX=SpawnVec2.x+(SX-BX)
20313
20573
  local TY=SpawnVec2.y+(SY-BY)
20314
20574
  UnitTemplate.x=TX
20315
20575
  UnitTemplate.y=TY
20316
- self:T('After Translation SpawnTemplate.units['..UnitID..'].x = '..UnitTemplate.x..', SpawnTemplate.units['..UnitID..'].y = '..UnitTemplate.y)
20576
+ self:T2('After Translation SpawnTemplate.units['..UnitID..'].x = '..UnitTemplate.x..', SpawnTemplate.units['..UnitID..'].y = '..UnitTemplate.y)
20317
20577
  end
20318
20578
  SpawnTemplate.route.points[1].x=SpawnVec2.x
20319
20579
  SpawnTemplate.route.points[1].y=SpawnVec2.y
@@ -20323,24 +20583,23 @@ end
20323
20583
  return self
20324
20584
  end
20325
20585
  function SPAWN:_RandomizeZones(SpawnIndex)
20326
- self:F({self.SpawnTemplatePrefix,SpawnIndex,self.SpawnRandomizeZones})
20327
20586
  if self.SpawnRandomizeZones then
20328
20587
  local SpawnZone=nil
20329
20588
  while not SpawnZone do
20330
- self:T({SpawnZoneTableCount=#self.SpawnZoneTable,self.SpawnZoneTable})
20589
+ self:T2({SpawnZoneTableCount=#self.SpawnZoneTable,self.SpawnZoneTable})
20331
20590
  local ZoneID=math.random(#self.SpawnZoneTable)
20332
- self:T(ZoneID)
20591
+ self:T2(ZoneID)
20333
20592
  SpawnZone=self.SpawnZoneTable[ZoneID]:GetZoneMaybe()
20334
20593
  end
20335
- self:T("Preparing Spawn in Zone",SpawnZone:GetName())
20594
+ self:T2("Preparing Spawn in Zone",SpawnZone:GetName())
20336
20595
  local SpawnVec2=SpawnZone:GetRandomVec2()
20337
- self:T({SpawnVec2=SpawnVec2})
20596
+ self:T2({SpawnVec2=SpawnVec2})
20338
20597
  local SpawnTemplate=self.SpawnGroups[SpawnIndex].SpawnTemplate
20339
20598
  self.SpawnGroups[SpawnIndex].SpawnZone=SpawnZone
20340
- self:T({Route=SpawnTemplate.route})
20599
+ self:T2({Route=SpawnTemplate.route})
20341
20600
  for UnitID=1,#SpawnTemplate.units do
20342
20601
  local UnitTemplate=SpawnTemplate.units[UnitID]
20343
- self:T('Before Translation SpawnTemplate.units['..UnitID..'].x = '..UnitTemplate.x..', SpawnTemplate.units['..UnitID..'].y = '..UnitTemplate.y)
20602
+ self:T2('Before Translation SpawnTemplate.units['..UnitID..'].x = '..UnitTemplate.x..', SpawnTemplate.units['..UnitID..'].y = '..UnitTemplate.y)
20344
20603
  local SX=UnitTemplate.x
20345
20604
  local SY=UnitTemplate.y
20346
20605
  local BX=SpawnTemplate.route.points[1].x
@@ -20349,7 +20608,7 @@ local TX=SpawnVec2.x+(SX-BX)
20349
20608
  local TY=SpawnVec2.y+(SY-BY)
20350
20609
  UnitTemplate.x=TX
20351
20610
  UnitTemplate.y=TY
20352
- self:T('After Translation SpawnTemplate.units['..UnitID..'].x = '..UnitTemplate.x..', SpawnTemplate.units['..UnitID..'].y = '..UnitTemplate.y)
20611
+ self:T2('After Translation SpawnTemplate.units['..UnitID..'].x = '..UnitTemplate.x..', SpawnTemplate.units['..UnitID..'].y = '..UnitTemplate.y)
20353
20612
  end
20354
20613
  SpawnTemplate.x=SpawnVec2.x
20355
20614
  SpawnTemplate.y=SpawnVec2.y
@@ -20359,7 +20618,6 @@ end
20359
20618
  return self
20360
20619
  end
20361
20620
  function SPAWN:_TranslateRotate(SpawnIndex,SpawnRootX,SpawnRootY,SpawnX,SpawnY,SpawnAngle)
20362
- self:F({self.SpawnTemplatePrefix,SpawnIndex,SpawnRootX,SpawnRootY,SpawnX,SpawnY,SpawnAngle})
20363
20621
  local TranslatedX=SpawnX
20364
20622
  local TranslatedY=SpawnY
20365
20623
  local RotatedX=-TranslatedX*math.cos(math.rad(SpawnAngle))+TranslatedY*math.sin(math.rad(SpawnAngle))
@@ -20379,10 +20637,10 @@ end
20379
20637
  return self
20380
20638
  end
20381
20639
  function SPAWN:_GetSpawnIndex(SpawnIndex)
20382
- self:F2({self.SpawnTemplatePrefix,SpawnIndex,self.SpawnMaxGroups,self.SpawnMaxUnitsAlive,self.AliveUnits,#self.SpawnTemplate.units})
20640
+ self:T2({template=self.SpawnTemplatePrefix,SpawnIndex=SpawnIndex,SpawnMaxGroups=self.SpawnMaxGroups,SpawnMaxUnitsAlive=self.SpawnMaxUnitsAlive,AliveUnits=self.AliveUnits,TemplateUnits=#self.SpawnTemplate.units})
20383
20641
  if(self.SpawnMaxGroups==0)or(SpawnIndex<=self.SpawnMaxGroups)then
20384
20642
  if(self.SpawnMaxUnitsAlive==0)or(self.AliveUnits+#self.SpawnTemplate.units<=self.SpawnMaxUnitsAlive)or self.UnControlled==true then
20385
- self:F({SpawnCount=self.SpawnCount,SpawnIndex=SpawnIndex})
20643
+ self:T2({SpawnCount=self.SpawnCount,SpawnIndex=SpawnIndex})
20386
20644
  if SpawnIndex and SpawnIndex>=self.SpawnCount+1 then
20387
20645
  self.SpawnCount=self.SpawnCount+1
20388
20646
  SpawnIndex=self.SpawnCount
@@ -20400,59 +20658,58 @@ end
20400
20658
  return self.SpawnIndex
20401
20659
  end
20402
20660
  function SPAWN:_OnBirth(EventData)
20403
- self:F(self.SpawnTemplatePrefix)
20404
20661
  local SpawnGroup=EventData.IniGroup
20405
20662
  if SpawnGroup then
20406
20663
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
20407
20664
  if EventPrefix then
20408
- self:T({"Birth Event:",EventPrefix,self.SpawnTemplatePrefix})
20665
+ self:T2({"Birth Event:",EventPrefix,self.SpawnTemplatePrefix})
20409
20666
  if EventPrefix==self.SpawnTemplatePrefix or(self.SpawnAliasPrefix and EventPrefix==self.SpawnAliasPrefix)then
20410
20667
  self.AliveUnits=self.AliveUnits+1
20411
- self:T("Alive Units: "..self.AliveUnits)
20668
+ self:T2("Alive Units: "..self.AliveUnits)
20412
20669
  end
20413
20670
  end
20414
20671
  end
20415
20672
  end
20416
20673
  function SPAWN:_OnDeadOrCrash(EventData)
20417
- self:F(self.SpawnTemplatePrefix)
20674
+ self:T2("Dead or crash event ID "..tostring(EventData.id or 0))
20675
+ self:T2("Dead or crash event for "..tostring(EventData.IniUnitName or"none"))
20418
20676
  local unit=UNIT:FindByName(EventData.IniUnitName)
20419
20677
  if unit then
20420
20678
  local EventPrefix=self:_GetPrefixFromGroupName(unit.GroupName)
20421
20679
  if EventPrefix then
20422
- self:T({"Dead event: "..EventPrefix})
20423
- if EventPrefix==self.SpawnTemplatePrefix or(self.SpawnAliasPrefix and EventPrefix==self.SpawnAliasPrefix)then
20680
+ self:T2({"Dead event: "..EventPrefix})
20681
+ self:T2(string.format("EventPrefix = %s | SpawnAliasPrefix = %s | Old AliveUnits = %d",EventPrefix or"",self.SpawnAliasPrefix or"",self.AliveUnits or 0))
20682
+ if EventPrefix==self.SpawnTemplatePrefix or(self.SpawnAliasPrefix and EventPrefix==self.SpawnAliasPrefix)and self.AliveUnits>0 then
20424
20683
  self.AliveUnits=self.AliveUnits-1
20425
- self:T("Alive Units: "..self.AliveUnits)
20426
20684
  end
20685
+ self:T2("New Alive Units: "..self.AliveUnits)
20427
20686
  end
20428
20687
  end
20429
20688
  end
20430
20689
  function SPAWN:_OnTakeOff(EventData)
20431
- self:F(self.SpawnTemplatePrefix)
20432
20690
  local SpawnGroup=EventData.IniGroup
20433
20691
  if SpawnGroup then
20434
20692
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
20435
20693
  if EventPrefix then
20436
- self:T({"TakeOff event: "..EventPrefix})
20694
+ self:T2({"TakeOff event: "..EventPrefix})
20437
20695
  if EventPrefix==self.SpawnTemplatePrefix or(self.SpawnAliasPrefix and EventPrefix==self.SpawnAliasPrefix)then
20438
- self:T("self.Landed = false")
20696
+ self:T2("self.Landed = false")
20439
20697
  SpawnGroup:SetState(SpawnGroup,"Spawn_Landed",false)
20440
20698
  end
20441
20699
  end
20442
20700
  end
20443
20701
  end
20444
20702
  function SPAWN:_OnLand(EventData)
20445
- self:F(self.SpawnTemplatePrefix)
20446
20703
  local SpawnGroup=EventData.IniGroup
20447
20704
  if SpawnGroup then
20448
20705
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
20449
20706
  if EventPrefix then
20450
- self:T({"Land event: "..EventPrefix})
20707
+ self:T2({"Land event: "..EventPrefix})
20451
20708
  if EventPrefix==self.SpawnTemplatePrefix or(self.SpawnAliasPrefix and EventPrefix==self.SpawnAliasPrefix)then
20452
20709
  SpawnGroup:SetState(SpawnGroup,"Spawn_Landed",true)
20453
20710
  if self.RepeatOnLanding then
20454
20711
  local SpawnGroupIndex=self:GetSpawnIndexFromGroup(SpawnGroup)
20455
- self:T({"Landed:","ReSpawn:",SpawnGroup:GetName(),SpawnGroupIndex})
20712
+ self:T2({"Landed:","ReSpawn:",SpawnGroup:GetName(),SpawnGroupIndex})
20456
20713
  SCHEDULER:New(nil,self.ReSpawn,{self,SpawnGroupIndex},3)
20457
20714
  end
20458
20715
  end
@@ -20460,17 +20717,16 @@ end
20460
20717
  end
20461
20718
  end
20462
20719
  function SPAWN:_OnEngineShutDown(EventData)
20463
- self:F(self.SpawnTemplatePrefix)
20464
20720
  local SpawnGroup=EventData.IniGroup
20465
20721
  if SpawnGroup then
20466
20722
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
20467
20723
  if EventPrefix then
20468
- self:T({"EngineShutdown event: "..EventPrefix})
20724
+ self:T2({"EngineShutdown event: "..EventPrefix})
20469
20725
  if EventPrefix==self.SpawnTemplatePrefix or(self.SpawnAliasPrefix and EventPrefix==self.SpawnAliasPrefix)then
20470
20726
  local Landed=SpawnGroup:GetState(SpawnGroup,"Spawn_Landed")
20471
20727
  if Landed and self.RepeatOnEngineShutDown then
20472
20728
  local SpawnGroupIndex=self:GetSpawnIndexFromGroup(SpawnGroup)
20473
- self:T({"EngineShutDown: ","ReSpawn:",SpawnGroup:GetName(),SpawnGroupIndex})
20729
+ self:T2({"EngineShutDown: ","ReSpawn:",SpawnGroup:GetName(),SpawnGroupIndex})
20474
20730
  SCHEDULER:New(nil,self.ReSpawn,{self,SpawnGroupIndex},3)
20475
20731
  end
20476
20732
  end
@@ -20483,9 +20739,8 @@ self:Spawn()
20483
20739
  return true
20484
20740
  end
20485
20741
  function SPAWN:_SpawnCleanUpScheduler()
20486
- self:F({"CleanUp Scheduler:",self.SpawnTemplatePrefix})
20487
20742
  local SpawnGroup,SpawnCursor=self:GetFirstAliveGroup()
20488
- self:T({"CleanUp Scheduler:",SpawnGroup,SpawnCursor})
20743
+ self:T2({"CleanUp Scheduler:",SpawnGroup,SpawnCursor})
20489
20744
  local IsHelo=false
20490
20745
  while SpawnGroup do
20491
20746
  IsHelo=SpawnGroup:IsHelicopter()
@@ -20495,14 +20750,14 @@ local SpawnUnit=UnitData
20495
20750
  local SpawnUnitName=SpawnUnit:GetName()
20496
20751
  self.SpawnCleanUpTimeStamps[SpawnUnitName]=self.SpawnCleanUpTimeStamps[SpawnUnitName]or{}
20497
20752
  local Stamp=self.SpawnCleanUpTimeStamps[SpawnUnitName]
20498
- self:T({SpawnUnitName,Stamp})
20753
+ self:T2({SpawnUnitName,Stamp})
20499
20754
  if Stamp.Vec2 then
20500
20755
  if(SpawnUnit:InAir()==false and SpawnUnit:GetVelocityKMH()<1)or IsHelo then
20501
20756
  local NewVec2=SpawnUnit:GetVec2()or{x=0,y=0}
20502
20757
  if(Stamp.Vec2.x==NewVec2.x and Stamp.Vec2.y==NewVec2.y)or(SpawnUnit:GetLife()<=1)then
20503
20758
  if Stamp.Time+self.SpawnCleanUpInterval<timer.getTime()then
20504
- self:T({"CleanUp Scheduler:","ReSpawning:",SpawnGroup:GetName()})
20505
- self:ReSpawn(SpawnCursor)
20759
+ self:T2({"CleanUp Scheduler:","ReSpawning:",SpawnGroup:GetName()})
20760
+ SCHEDULER:New(nil,self.ReSpawn,{self,SpawnCursor},3)
20506
20761
  Stamp.Vec2=nil
20507
20762
  Stamp.Time=nil
20508
20763
  end
@@ -20527,7 +20782,7 @@ end
20527
20782
  end
20528
20783
  end
20529
20784
  SpawnGroup,SpawnCursor=self:GetNextAliveGroup(SpawnCursor)
20530
- self:T({"CleanUp Scheduler:",SpawnGroup,SpawnCursor})
20785
+ self:T2({"CleanUp Scheduler:",SpawnGroup,SpawnCursor})
20531
20786
  end
20532
20787
  return true
20533
20788
  end
@@ -20564,10 +20819,47 @@ self.InitStaticType=StaticType
20564
20819
  self.InitStaticCategory=StaticCategory
20565
20820
  self.CountryID=CountryID or country.id.USA
20566
20821
  self.SpawnTemplatePrefix=self.InitStaticType
20822
+ self.TemplateStaticUnit={}
20567
20823
  self.InitStaticCoordinate=COORDINATE:New(0,0,0)
20568
20824
  self.InitStaticHeading=0
20569
20825
  return self
20570
20826
  end
20827
+ function SPAWNSTATIC:_InitResourceTable(CombinedWeight)
20828
+ if not self.TemplateStaticUnit.resourcePayload then
20829
+ self.TemplateStaticUnit.resourcePayload={
20830
+ ["weapons"]={},
20831
+ ["aircrafts"]={},
20832
+ ["gasoline"]=0,
20833
+ ["diesel"]=0,
20834
+ ["methanol_mixture"]=0,
20835
+ ["jet_fuel"]=0,
20836
+ }
20837
+ end
20838
+ self:InitCargo(true)
20839
+ self:InitCargoMass(CombinedWeight or 1)
20840
+ return self
20841
+ end
20842
+ function SPAWNSTATIC:AddCargoResource(Type,Name,Amount,CombinedWeight)
20843
+ if not self.TemplateStaticUnit.resourcePayload then
20844
+ self:_InitResourceTable(CombinedWeight)
20845
+ end
20846
+ if Type==STORAGE.Type.LIQUIDS and type(Name)=="string"then
20847
+ self.TemplateStaticUnit.resourcePayload[Name]=Amount
20848
+ else
20849
+ self.TemplateStaticUnit.resourcePayload[Type]={
20850
+ [Name]={
20851
+ ["amount"]=Amount,
20852
+ }
20853
+ }
20854
+ end
20855
+ UTILS.PrintTableToLog(self.TemplateStaticUnit)
20856
+ return self
20857
+ end
20858
+ function SPAWNSTATIC:ResetCargoResources()
20859
+ self.TemplateStaticUnit.resourcePayload=nil
20860
+ self:_InitResourceTable()
20861
+ return self
20862
+ end
20571
20863
  function SPAWNSTATIC:InitCoordinate(Coordinate)
20572
20864
  self.InitStaticCoordinate=Coordinate
20573
20865
  return self
@@ -20622,6 +20914,15 @@ self.InitOffsetY=OffsetY or 0
20622
20914
  self.InitOffsetAngle=OffsetAngle or 0
20623
20915
  return self
20624
20916
  end
20917
+ function SPAWNSTATIC:OnSpawnStatic(SpawnCallBackFunction,...)
20918
+ self:F("OnSpawnStatic")
20919
+ self.SpawnFunctionHook=SpawnCallBackFunction
20920
+ self.SpawnFunctionArguments={}
20921
+ if arg then
20922
+ self.SpawnFunctionArguments=arg
20923
+ end
20924
+ return self
20925
+ end
20625
20926
  function SPAWNSTATIC:Spawn(Heading,NewName)
20626
20927
  if Heading then
20627
20928
  self.InitStaticHeading=Heading
@@ -20725,6 +21026,9 @@ self:T("Spawning Static")
20725
21026
  self:T2({Template=Template})
20726
21027
  Static=coalition.addStaticObject(CountryID,Template)
20727
21028
  end
21029
+ if self.SpawnFunctionHook then
21030
+ self:ScheduleOnce(0.3,self.SpawnFunctionHook,mystatic,unpack(self.SpawnFunctionArguments))
21031
+ end
20728
21032
  return mystatic
20729
21033
  end
20730
21034
  TIMER={
@@ -21388,11 +21692,11 @@ function IDENTIFIABLE:GetCategory()
21388
21692
  self:F2(self.ObjectName)
21389
21693
  local DCSObject=self:GetDCSObject()
21390
21694
  if DCSObject then
21391
- local ObjectCategory=DCSObject:getCategory()
21695
+ local ObjectCategory,UnitCategory=DCSObject:getCategory()
21392
21696
  self:T3(ObjectCategory)
21393
- return ObjectCategory
21697
+ return ObjectCategory,UnitCategory
21394
21698
  end
21395
- return nil
21699
+ return nil,nil
21396
21700
  end
21397
21701
  function IDENTIFIABLE:GetCategoryName()
21398
21702
  local DCSIdentifiable=self:GetDCSObject()
@@ -23239,20 +23543,25 @@ lastWptIndex=LastWptNumber
23239
23543
  }
23240
23544
  return DCSTask
23241
23545
  end
23242
- function CONTROLLABLE:TaskLandAtVec2(Vec2,Duration)
23546
+ function CONTROLLABLE:TaskLandAtVec2(Vec2,Duration,CombatLanding,DirectionAfterLand)
23243
23547
  local DCSTask={
23244
23548
  id='Land',
23245
23549
  params={
23246
23550
  point=Vec2,
23247
23551
  durationFlag=Duration and true or false,
23248
23552
  duration=Duration,
23553
+ combatLandingFlag=CombatLanding==true and true or false,
23249
23554
  },
23250
23555
  }
23556
+ if DirectionAfterLand~=nil and type(DirectionAfterLand)=="number"then
23557
+ DCSTask.params.directionEnabled=true
23558
+ DCSTask.params.direction=math.rad(DirectionAfterLand)
23559
+ end
23251
23560
  return DCSTask
23252
23561
  end
23253
- function CONTROLLABLE:TaskLandAtZone(Zone,Duration,RandomPoint)
23562
+ function CONTROLLABLE:TaskLandAtZone(Zone,Duration,RandomPoint,CombatLanding,DirectionAfterLand)
23254
23563
  local Point=RandomPoint and Zone:GetRandomVec2()or Zone:GetVec2()
23255
- local DCSTask=CONTROLLABLE.TaskLandAtVec2(self,Point,Duration)
23564
+ local DCSTask=CONTROLLABLE.TaskLandAtVec2(self,Point,Duration,CombatLanding,DirectionAfterLand)
23256
23565
  return DCSTask
23257
23566
  end
23258
23567
  function CONTROLLABLE:TaskFollow(FollowControllable,Vec3,LastWaypointIndex)
@@ -24459,6 +24768,30 @@ self:SetOption(AI.Option.Air.id.PROHIBIT_AB,Prohibit)
24459
24768
  end
24460
24769
  return self
24461
24770
  end
24771
+ function CONTROLLABLE:OptionEvasionOfARM(Seconds)
24772
+ self:F2({self.ControllableName})
24773
+ local DCSControllable=self:GetDCSObject()
24774
+ if DCSControllable then
24775
+ local Controller=self:_GetController()
24776
+ if self:IsGround()then
24777
+ if Seconds==nil then Seconds=false end
24778
+ Controller:setOption(AI.Option.Ground.id.EVASION_OF_ARM,Seconds)
24779
+ end
24780
+ end
24781
+ return self
24782
+ end
24783
+ function CONTROLLABLE:OptionFormationInterval(meters)
24784
+ self:F2({self.ControllableName})
24785
+ local DCSControllable=self:GetDCSObject()
24786
+ if DCSControllable then
24787
+ local Controller=self:_GetController()
24788
+ if self:IsGround()then
24789
+ if meters==nil or meters>100 or meters<0 then meters=50 end
24790
+ Controller:setOption(30,meters)
24791
+ end
24792
+ end
24793
+ return self
24794
+ end
24462
24795
  function CONTROLLABLE:OptionECM(ECMvalue)
24463
24796
  self:F2({self.ControllableName})
24464
24797
  local DCSControllable=self:GetDCSObject()
@@ -25715,6 +26048,7 @@ local DCSGroup=Group.getByName(self.GroupName)
25715
26048
  if DCSGroup then
25716
26049
  return DCSGroup
25717
26050
  end
26051
+ self:T2(string.format("ERROR: Could not get DCS group object of group %s because DCS object could not be found!",tostring(self.GroupName)))
25718
26052
  return nil
25719
26053
  end
25720
26054
  function GROUP:GetPositionVec3()
@@ -26216,6 +26550,7 @@ end
26216
26550
  end
26217
26551
  end
26218
26552
  local DCSGroup=Group.getByName(self.GroupName)
26553
+ if DCSGroup then
26219
26554
  local DCSUnits=DCSGroup:getUnits()or{}
26220
26555
  for _,_unit in pairs(DCSUnits)do
26221
26556
  if Object.isExist(_unit)then
@@ -26227,6 +26562,7 @@ return coord
26227
26562
  end
26228
26563
  end
26229
26564
  end
26565
+ end
26230
26566
  BASE:E({"Cannot GetCoordinate",Group=self,Alive=self:IsAlive()})
26231
26567
  end
26232
26568
  function GROUP:GetRandomVec3(Radius)
@@ -26542,7 +26878,11 @@ return nil
26542
26878
  end
26543
26879
  function GROUP:GetTemplate()
26544
26880
  local GroupName=self:GetName()
26545
- return UTILS.DeepCopy(_DATABASE:GetGroupTemplate(GroupName))
26881
+ local template=_DATABASE:GetGroupTemplate(GroupName)
26882
+ if template then
26883
+ return UTILS.DeepCopy(template)
26884
+ end
26885
+ return nil
26546
26886
  end
26547
26887
  function GROUP:GetTemplateRoutePoints()
26548
26888
  local GroupName=self:GetName()
@@ -27050,7 +27390,7 @@ function GROUP:GetPlayerNames()
27050
27390
  local HasPlayers=false
27051
27391
  local PlayerNames={}
27052
27392
  local Units=self:GetUnits()
27053
- for UnitID,UnitData in pairs(Units)do
27393
+ for UnitID,UnitData in pairs(Units or{})do
27054
27394
  local Unit=UnitData
27055
27395
  local PlayerName=Unit:GetPlayerName()
27056
27396
  if PlayerName and PlayerName~=""then
@@ -27432,7 +27772,16 @@ end
27432
27772
  function UNIT:IsPlayer()
27433
27773
  local group=self:GetGroup()
27434
27774
  if not group then return false end
27435
- local units=group:GetTemplate().units
27775
+ local template=group:GetTemplate()
27776
+ if(template==nil)or(template.units==nil)then
27777
+ local DCSObject=self:GetDCSObject()
27778
+ if DCSObject then
27779
+ if DCSObject:getPlayerName()~=nil then return true else return false end
27780
+ else
27781
+ return false
27782
+ end
27783
+ end
27784
+ local units=template.units
27436
27785
  for _,unit in pairs(units)do
27437
27786
  if unit.name==self:GetName()and(unit.skill=="Client"or unit.skill=="Player")then
27438
27787
  return true
@@ -27610,6 +27959,8 @@ local nrockets=0
27610
27959
  local nmissiles=0
27611
27960
  local nbombs=0
27612
27961
  local narti=0
27962
+ local nAPshells=0
27963
+ local nHEshells=0
27613
27964
  local unit=self
27614
27965
  local ammotable=unit:GetAmmo()
27615
27966
  if ammotable then
@@ -27627,6 +27978,12 @@ nshells=nshells+Nammo
27627
27978
  if ammotable[w].desc.warhead and ammotable[w].desc.warhead.explosiveMass and ammotable[w].desc.warhead.explosiveMass>0 then
27628
27979
  narti=narti+Nammo
27629
27980
  end
27981
+ if ammotable[w].desc.typeName and string.find(ammotable[w].desc.typeName,"_AP",1,true)then
27982
+ nAPshells=nAPshells+Nammo
27983
+ end
27984
+ if ammotable[w].desc.typeName and string.find(ammotable[w].desc.typeName,"_HE",1,true)then
27985
+ nHEshells=nHEshells+Nammo
27986
+ end
27630
27987
  elseif Category==Weapon.Category.ROCKET then
27631
27988
  nrockets=nrockets+Nammo
27632
27989
  elseif Category==Weapon.Category.BOMB then
@@ -27649,7 +28006,31 @@ end
27649
28006
  end
27650
28007
  end
27651
28008
  nammo=nshells+nrockets+nmissiles+nbombs
27652
- return nammo,nshells,nrockets,nbombs,nmissiles,narti
28009
+ return nammo,nshells,nrockets,nbombs,nmissiles,narti,nAPshells,nHEshells
28010
+ end
28011
+ function UNIT:HasAPShells()
28012
+ local _,_,_,_,_,_,shells=self:GetAmmunition()
28013
+ if shells>0 then return true else return false end
28014
+ end
28015
+ function UNIT:GetAPShells()
28016
+ local _,_,_,_,_,_,shells=self:GetAmmunition()
28017
+ return shells or 0
28018
+ end
28019
+ function UNIT:GetHEShells()
28020
+ local _,_,_,_,_,_,_,shells=self:GetAmmunition()
28021
+ return shells or 0
28022
+ end
28023
+ function UNIT:HasHEShells()
28024
+ local _,_,_,_,_,_,_,shells=self:GetAmmunition()
28025
+ if shells>0 then return true else return false end
28026
+ end
28027
+ function UNIT:HasArtiShells()
28028
+ local _,_,_,_,_,shells=self:GetAmmunition()
28029
+ if shells>0 then return true else return false end
28030
+ end
28031
+ function UNIT:GetArtiShells()
28032
+ local _,_,_,_,_,shells=self:GetAmmunition()
28033
+ return shells or 0
27653
28034
  end
27654
28035
  function UNIT:GetSensors()
27655
28036
  self:F2(self.UnitName)
@@ -27789,17 +28170,17 @@ if Descriptor then
27789
28170
  local Attributes=Descriptor.attributes
27790
28171
  if self:IsGround()then
27791
28172
  local ThreatLevels={
27792
- "Unarmed",
27793
- "Infantry",
27794
- "Old Tanks & APCs",
27795
- "Tanks & IFVs without ATGM",
27796
- "Tanks & IFV with ATGM",
27797
- "Modern Tanks",
27798
- "AAA",
27799
- "IR Guided SAMs",
27800
- "SR SAMs",
27801
- "MR SAMs",
27802
- "LR SAMs"
28173
+ [1]="Unarmed",
28174
+ [2]="Infantry",
28175
+ [3]="Old Tanks & APCs",
28176
+ [4]="Tanks & IFVs without ATGM",
28177
+ [5]="Tanks & IFV with ATGM",
28178
+ [6]="Modern Tanks",
28179
+ [7]="AAA",
28180
+ [8]="IR Guided SAMs",
28181
+ [9]="SR SAMs",
28182
+ [10]="MR SAMs",
28183
+ [11]="LR SAMs"
27803
28184
  }
27804
28185
  if Attributes["LR SAM"]then ThreatLevel=10
27805
28186
  elseif Attributes["MR SAM"]then ThreatLevel=9
@@ -27820,17 +28201,17 @@ ThreatText=ThreatLevels[ThreatLevel+1]
27820
28201
  end
27821
28202
  if self:IsAir()then
27822
28203
  local ThreatLevels={
27823
- "Unarmed",
27824
- "Tanker",
27825
- "AWACS",
27826
- "Transport Helicopter",
27827
- "UAV",
27828
- "Bomber",
27829
- "Strategic Bomber",
27830
- "Attack Helicopter",
27831
- "Battleplane",
27832
- "Multirole Fighter",
27833
- "Fighter"
28204
+ [1]="Unarmed",
28205
+ [2]="Tanker",
28206
+ [3]="AWACS",
28207
+ [4]="Transport Helicopter",
28208
+ [5]="UAV",
28209
+ [6]="Bomber",
28210
+ [7]="Strategic Bomber",
28211
+ [8]="Attack Helicopter",
28212
+ [9]="Battleplane",
28213
+ [10]="Multirole Fighter",
28214
+ [11]="Fighter"
27834
28215
  }
27835
28216
  if Attributes["Fighters"]then ThreatLevel=10
27836
28217
  elseif Attributes["Multirole fighters"]then ThreatLevel=9
@@ -27849,17 +28230,17 @@ ThreatText=ThreatLevels[ThreatLevel+1]
27849
28230
  end
27850
28231
  if self:IsShip()then
27851
28232
  local ThreatLevels={
27852
- "Unarmed ship",
27853
- "Light armed ships",
27854
- "Corvettes",
27855
- "",
27856
- "Frigates",
27857
- "",
27858
- "Cruiser",
27859
- "",
27860
- "Destroyer",
27861
- "",
27862
- "Aircraft Carrier"
28233
+ [1]="Unarmed ship",
28234
+ [2]="Light armed ships",
28235
+ [3]="Corvettes",
28236
+ [4]="",
28237
+ [5]="Frigates",
28238
+ [6]="",
28239
+ [7]="Cruiser",
28240
+ [8]="",
28241
+ [9]="Destroyer",
28242
+ [10]="",
28243
+ [11]="Aircraft Carrier"
27863
28244
  }
27864
28245
  if Attributes["Aircraft Carriers"]then ThreatLevel=10
27865
28246
  elseif Attributes["Destroyers"]then ThreatLevel=8
@@ -28130,6 +28511,9 @@ function CLIENT:AddPlayer(PlayerName)
28130
28511
  table.insert(self.Players,PlayerName)
28131
28512
  return self
28132
28513
  end
28514
+ function CLIENT:CountPlayers()
28515
+ return#self.Players or 0
28516
+ end
28133
28517
  function CLIENT:GetPlayers()
28134
28518
  return self.Players
28135
28519
  end
@@ -28198,7 +28582,7 @@ self.AliveCheckScheduler:NoTrace()
28198
28582
  return self
28199
28583
  end
28200
28584
  function CLIENT:_AliveCheckScheduler(SchedulerName)
28201
- self:F3({SchedulerName,self.ClientName,self.ClientAlive2,self.ClientBriefingShown,self.ClientCallBack})
28585
+ self:T2({SchedulerName,self.ClientName,self.ClientAlive2,self.ClientBriefingShown,self.ClientCallBack})
28202
28586
  if self:IsAlive()then
28203
28587
  if self.ClientAlive2==false then
28204
28588
  self:ShowBriefing()
@@ -28485,6 +28869,20 @@ end
28485
28869
  end
28486
28870
  return GroupsFound
28487
28871
  end
28872
+ function STATIC:GetStaticStorage()
28873
+ local name=self:GetName()
28874
+ local storage=STORAGE:NewFromStaticCargo(name)
28875
+ return storage
28876
+ end
28877
+ function STATIC:GetCargoWeight()
28878
+ local DCSObject=StaticObject.getByName(self.StaticName)
28879
+ local mass=-1
28880
+ if DCSObject then
28881
+ mass=DCSObject:getCargoWeight()or 0
28882
+ local masstxt=DCSObject:getCargoDisplayName()or"none"
28883
+ end
28884
+ return mass
28885
+ end
28488
28886
  AIRBASE={
28489
28887
  ClassName="AIRBASE",
28490
28888
  CategoryName={
@@ -28742,7 +29140,6 @@ AIRBASE.MarianaIslands={
28742
29140
  }
28743
29141
  AIRBASE.SouthAtlantic={
28744
29142
  ["Almirante_Schroeders"]="Almirante Schroeders",
28745
- ["Caleta_Tortel"]="Caleta Tortel",
28746
29143
  ["Comandante_Luis_Piedrabuena"]="Comandante Luis Piedrabuena",
28747
29144
  ["Cullen"]="Cullen",
28748
29145
  ["El_Calafate"]="El Calafate",
@@ -28773,49 +29170,84 @@ AIRBASE.SouthAtlantic={
28773
29170
  AIRBASE.Sinai={
28774
29171
  ["Abu_Rudeis"]="Abu Rudeis",
28775
29172
  ["Abu_Suwayr"]="Abu Suwayr",
29173
+ ["Al_Bahr_al_Ahmar"]="Al Bahr al Ahmar",
28776
29174
  ["Al_Ismailiyah"]="Al Ismailiyah",
29175
+ ["Al_Khatatbah"]="Al Khatatbah",
28777
29176
  ["Al_Mansurah"]="Al Mansurah",
29177
+ ["Al_Rahmaniyah_Air_Base"]="Al Rahmaniyah Air Base",
28778
29178
  ["As_Salihiyah"]="As Salihiyah",
28779
29179
  ["AzZaqaziq"]="AzZaqaziq",
28780
29180
  ["Baluza"]="Baluza",
28781
29181
  ["Ben_Gurion"]="Ben-Gurion",
29182
+ ["Beni_Suef"]="Beni Suef",
28782
29183
  ["Bilbeis_Air_Base"]="Bilbeis Air Base",
28783
29184
  ["Bir_Hasanah"]="Bir Hasanah",
29185
+ ["Birma_Air_Base"]="Birma Air Base",
29186
+ ["Borj_El_Arab_International_Airport"]="Borj El Arab International Airport",
28784
29187
  ["Cairo_International_Airport"]="Cairo International Airport",
28785
29188
  ["Cairo_West"]="Cairo West",
28786
29189
  ["Difarsuwar_Airfield"]="Difarsuwar Airfield",
28787
29190
  ["El_Arish"]="El Arish",
28788
29191
  ["El_Gora"]="El Gora",
29192
+ ["El_Minya"]="El Minya",
28789
29193
  ["Fayed"]="Fayed",
29194
+ ["Gebel_El_Basur_Air_Base"]="Gebel El Basur Air Base",
28790
29195
  ["Hatzerim"]="Hatzerim",
28791
29196
  ["Hatzor"]="Hatzor",
29197
+ ["Hurghada_International_Airport"]="Hurghada International Airport",
28792
29198
  ["Inshas_Airbase"]="Inshas Airbase",
29199
+ ["Jiyanklis_Air_Base"]="Jiyanklis Air Base",
28793
29200
  ["Kedem"]="Kedem",
28794
29201
  ["Kibrit_Air_Base"]="Kibrit Air Base",
29202
+ ["Kom_Awshim"]="Kom Awshim",
28795
29203
  ["Melez"]="Melez",
28796
29204
  ["Nevatim"]="Nevatim",
28797
29205
  ["Ovda"]="Ovda",
28798
- ["Palmahim"]="Palmahim",
29206
+ ["Palmachim"]="Palmachim",
29207
+ ["Quwaysina"]="Quwaysina",
28799
29208
  ["Ramon_Airbase"]="Ramon Airbase",
29209
+ ["Ramon_International_Airport"]="Ramon International Airport",
28800
29210
  ["Sde_Dov"]="Sde Dov",
29211
+ ["Sharm_El_Sheikh_International_Airport"]="Sharm El Sheikh International Airport",
28801
29212
  ["St_Catherine"]="St Catherine",
28802
29213
  ["Tel_Nof"]="Tel Nof",
29214
+ ["Wadi_Abu_Rish"]="Wadi Abu Rish",
28803
29215
  ["Wadi_al_Jandali"]="Wadi al Jandali",
28804
29216
  }
28805
29217
  AIRBASE.Kola={
28806
- ["Bas_100"]="Bas 100",
29218
+ ["Banak"]="Banak",
28807
29219
  ["Bodo"]="Bodo",
28808
29220
  ["Jokkmokk"]="Jokkmokk",
28809
29221
  ["Kalixfors"]="Kalixfors",
28810
29222
  ["Kemi_Tornio"]="Kemi Tornio",
28811
29223
  ["Kiruna"]="Kiruna",
28812
- ["Lakselv"]="Lakselv",
28813
29224
  ["Monchegorsk"]="Monchegorsk",
28814
29225
  ["Murmansk_International"]="Murmansk International",
28815
- ["Olenegorsk"]="Olenegorsk",
29226
+ ["Olenya"]="Olenya",
28816
29227
  ["Rovaniemi"]="Rovaniemi",
28817
- ["Severomorsk1"]="Severomorsk1",
28818
- ["Severomorsk3"]="Severomorsk3",
29228
+ ["Severomorsk_1"]="Severomorsk-1",
29229
+ ["Severomorsk_3"]="Severomorsk-3",
29230
+ ["Vuojarvi"]="Vuojarvi",
29231
+ ["Kirkenes"]="Kirkenes",
29232
+ ["Kallax"]="Kallax",
29233
+ ["Vidsel"]="Vidsel",
29234
+ }
29235
+ AIRBASE.Afghanistan={
29236
+ ["Bost"]="Bost",
29237
+ ["Camp_Bastion"]="Camp Bastion",
29238
+ ["Camp_Bastion_Heliport"]="Camp Bastion Heliport",
29239
+ ["Chaghcharan"]="Chaghcharan",
29240
+ ["Dwyer"]="Dwyer",
29241
+ ["Farah"]="Farah",
29242
+ ["Herat"]="Herat",
29243
+ ["Kandahar"]="Kandahar",
29244
+ ["Kandahar_Heliport"]="Kandahar Heliport",
29245
+ ["Maymana_Zahiraddin_Faryabi"]="Maymana Zahiraddin Faryabi",
29246
+ ["Nimroz"]="Nimroz",
29247
+ ["Qala_i_Naw"]="Qala i Naw",
29248
+ ["Shindand"]="Shindand",
29249
+ ["Shindand_Heliport"]="Shindand Heliport",
29250
+ ["Tarinkot"]="Tarinkot",
28819
29251
  }
28820
29252
  AIRBASE.TerminalType={
28821
29253
  Runway=16,
@@ -29173,7 +29605,7 @@ function AIRBASE:GetFreeParkingSpotsTable(termtype,allowTOAC)
29173
29605
  local parkingfree=self:GetParkingData(true)
29174
29606
  local freespots={}
29175
29607
  for _,_spot in pairs(parkingfree)do
29176
- if AIRBASE._CheckTerminalType(_spot.Term_Type,termtype)and _spot.Term_Index>0 then
29608
+ if AIRBASE._CheckTerminalType(_spot.Term_Type,termtype)then
29177
29609
  if(allowTOAC and allowTOAC==true)or _spot.TO_AC==false then
29178
29610
  local spot=self:_GetParkingSpotByID(_spot.Term_Index)
29179
29611
  spot.Free=true
@@ -30927,7 +31359,18 @@ GASOLINE=1,
30927
31359
  MW50=2,
30928
31360
  DIESEL=3,
30929
31361
  }
30930
- STORAGE.version="0.0.1"
31362
+ STORAGE.LiquidName={
31363
+ GASOLINE="gasoline",
31364
+ DIESEL="diesel",
31365
+ MW50="methanol_mixture",
31366
+ JETFUEL="jet_fuel",
31367
+ }
31368
+ STORAGE.Type={
31369
+ WEAPONS="weapons",
31370
+ LIQUIDS="liquids",
31371
+ AIRCRAFT="aircrafts",
31372
+ }
31373
+ STORAGE.version="0.0.3"
30931
31374
  function STORAGE:New(AirbaseName)
30932
31375
  local self=BASE:Inherit(self,BASE:New())
30933
31376
  self.airbase=Airbase.getByName(AirbaseName)
@@ -30937,6 +31380,15 @@ end
30937
31380
  self.lid=string.format("STORAGE %s",AirbaseName)
30938
31381
  return self
30939
31382
  end
31383
+ function STORAGE:NewFromStaticCargo(StaticCargoName)
31384
+ local self=BASE:Inherit(self,BASE:New())
31385
+ self.airbase=StaticObject.getByName(StaticCargoName)
31386
+ if Airbase.getWarehouse then
31387
+ self.warehouse=Warehouse.getCargoAsWarehouse(self.airbase)
31388
+ end
31389
+ self.lid=string.format("STORAGE %s",StaticCargoName)
31390
+ return self
31391
+ end
30940
31392
  function STORAGE:FindByName(AirbaseName)
30941
31393
  local storage=_DATABASE:FindStorage(AirbaseName)
30942
31394
  return storage
@@ -31037,7 +31489,7 @@ local unlimited=false
31037
31489
  if N>0 then
31038
31490
  self:RemoveAmount(Type,1)
31039
31491
  local n=self:GetAmount(Type)
31040
- unlimited=n==N
31492
+ unlimited=unlimited or n>2^29 or n==N
31041
31493
  if not unlimited then
31042
31494
  self:AddAmount(Type,1)
31043
31495
  end
@@ -35822,7 +36274,7 @@ function DETECTION_BASE:onafterStart(From,Event,To)
35822
36274
  self:__Detect(1)
35823
36275
  end
35824
36276
  function DETECTION_BASE:onafterDetect(From,Event,To)
35825
- local DetectDelay=0.1
36277
+ local DetectDelay=0.15
35826
36278
  self.DetectionCount=0
35827
36279
  self.DetectionRun=0
35828
36280
  self:UnIdentifyAllDetectedObjects()
@@ -35853,13 +36305,15 @@ self.DetectionSet:ForEachGroupAlive(IteratorFunction,arg)
35853
36305
  return self
35854
36306
  end
35855
36307
  function DETECTION_BASE:onafterDetection(From,Event,To,Detection,DetectionTimeStamp)
36308
+ self:T({DetectedObjects=self.DetectedObjects})
35856
36309
  self.DetectionRun=self.DetectionRun+1
35857
36310
  local HasDetectedObjects=false
35858
36311
  if Detection and Detection:IsAlive()then
36312
+ self:T({"DetectionGroup is Alive",Detection:GetName()})
35859
36313
  local DetectionGroupName=Detection:GetName()
35860
36314
  local DetectionUnit=Detection:GetUnit(1)
35861
36315
  local DetectedUnits={}
35862
- local DetectedTargets=Detection:GetDetectedTargets(
36316
+ local DetectedTargets=DetectionUnit:GetDetectedTargets(
35863
36317
  self.DetectVisual,
35864
36318
  self.DetectOptical,
35865
36319
  self.DetectRadar,
@@ -35867,7 +36321,6 @@ self.DetectIRST,
35867
36321
  self.DetectRWR,
35868
36322
  self.DetectDLINK
35869
36323
  )
35870
- self:F({DetectedTargets=DetectedTargets})
35871
36324
  for DetectionObjectID,Detection in pairs(DetectedTargets)do
35872
36325
  local DetectedObject=Detection.object
35873
36326
  if DetectedObject and DetectedObject:isExist()and DetectedObject.id_<50000000 then
@@ -37796,7 +38249,6 @@ local DetectedItem=self.Detection:GetDetectedItemByIndex(Index)
37796
38249
  local TargetSetUnit=self.Detection:GetDetectedItemSet(DetectedItem)
37797
38250
  local MarkingCount=0
37798
38251
  local MarkedTypes={}
37799
- TargetSetUnit:Flush(self)
37800
38252
  for TargetUnit,RecceData in pairs(self.Recces)do
37801
38253
  local Recce=RecceData
37802
38254
  self:F({TargetUnit=TargetUnit,Recce=Recce:GetName()})
@@ -37821,6 +38273,7 @@ break
37821
38273
  end
37822
38274
  end
37823
38275
  end
38276
+ if TargetSetUnit==nil then return end
37824
38277
  if self.AutoLase or(not self.AutoLase and(self.LaseStart+Duration>=timer.getTime()))then
37825
38278
  TargetSetUnit:ForEachUnitPerThreatLevel(10,0,
37826
38279
  function(TargetUnit)
@@ -37847,14 +38300,15 @@ self.LaserCodesUsed[LaserCode]=LaserCodeIndex
37847
38300
  local Spot=RecceUnit:LaseUnit(TargetUnit,LaserCode,Duration)
37848
38301
  local AttackSet=self.AttackSet
37849
38302
  local DesignateName=self.DesignateName
38303
+ local typename=TargetUnit:GetTypeName()
37850
38304
  function Spot:OnAfterDestroyed(From,Event,To)
37851
- self.Recce:MessageToSetGroup("Target "..TargetUnit:GetTypeName().." destroyed. "..TargetSetUnit:Count().." targets left.",
38305
+ self.Recce:MessageToSetGroup("Target "..typename.." destroyed. "..TargetSetUnit:CountAlive().." targets left.",
37852
38306
  5,AttackSet,self.DesignateName)
37853
38307
  end
37854
38308
  self.Recces[TargetUnit]=RecceUnit
37855
38309
  MarkingCount=MarkingCount+1
37856
38310
  local TargetUnitType=TargetUnit:GetTypeName()
37857
- RecceUnit:MessageToSetGroup("Marking "..TargetUnit:GetTypeName().." with laser "..RecceUnit:GetSpot().LaserCode.." for "..Duration.."s.",
38311
+ RecceUnit:MessageToSetGroup("Marking "..TargetUnitType.." with laser "..RecceUnit:GetSpot().LaserCode.." for "..Duration.."s.",
37858
38312
  10,self.AttackSet,DesignateName)
37859
38313
  if not MarkedTypes[TargetUnitType]then
37860
38314
  MarkedTypes[TargetUnitType]=true
@@ -37965,9 +38419,11 @@ end
37965
38419
  end
37966
38420
  end
37967
38421
  function DESIGNATE:onafterDoneSmoking(From,Event,To,Index)
38422
+ if self.Designating[Index]~=nil then
37968
38423
  self.Designating[Index]=string.gsub(self.Designating[Index],"S","")
37969
38424
  self:SetDesignateMenu()
37970
38425
  end
38426
+ end
37971
38427
  function DESIGNATE:onafterDoneIlluminating(From,Event,To,Index)
37972
38428
  self.Designating[Index]=string.gsub(self.Designating[Index],"I","")
37973
38429
  self:SetDesignateMenu()
@@ -38982,6 +39438,10 @@ elseif DCStype=="Mirage-F1CE"then
38982
39438
  self.aircraft.length=16
38983
39439
  self.aircraft.height=5
38984
39440
  self.aircraft.width=9
39441
+ elseif DCStype=="Saab340"then
39442
+ self.aircraft.length=19.73
39443
+ self.aircraft.height=6.97
39444
+ self.aircraft.width=21.44
38985
39445
  end
38986
39446
  self.aircraft.box=math.max(self.aircraft.length,self.aircraft.width)
38987
39447
  local text=string.format("\n******************************************************\n")
@@ -41489,7 +41949,7 @@ IRExitRange={filename="IR-ExitRange.ogg",duration=3.10},
41489
41949
  RANGE.Names={}
41490
41950
  RANGE.MenuF10={}
41491
41951
  RANGE.MenuF10Root=nil
41492
- RANGE.version="2.7.3"
41952
+ RANGE.version="2.8.0"
41493
41953
  function RANGE:New(RangeName,Coalition)
41494
41954
  local self=BASE:Inherit(self,FSM:New())
41495
41955
  self.rangename=RangeName or"Practice Range"
@@ -41555,32 +42015,32 @@ end
41555
42015
  if self.rangecontrolfreq and not self.useSRS then
41556
42016
  self.rangecontrol=RADIOQUEUE:New(self.rangecontrolfreq,nil,self.rangename)
41557
42017
  self.rangecontrol.schedonce=true
41558
- self.rangecontrol:SetDigit(0,RANGE.Sound.RC0.filename,RANGE.Sound.RC0.duration,self.soundpath)
41559
- self.rangecontrol:SetDigit(1,RANGE.Sound.RC1.filename,RANGE.Sound.RC1.duration,self.soundpath)
41560
- self.rangecontrol:SetDigit(2,RANGE.Sound.RC2.filename,RANGE.Sound.RC2.duration,self.soundpath)
41561
- self.rangecontrol:SetDigit(3,RANGE.Sound.RC3.filename,RANGE.Sound.RC3.duration,self.soundpath)
41562
- self.rangecontrol:SetDigit(4,RANGE.Sound.RC4.filename,RANGE.Sound.RC4.duration,self.soundpath)
41563
- self.rangecontrol:SetDigit(5,RANGE.Sound.RC5.filename,RANGE.Sound.RC5.duration,self.soundpath)
41564
- self.rangecontrol:SetDigit(6,RANGE.Sound.RC6.filename,RANGE.Sound.RC6.duration,self.soundpath)
41565
- self.rangecontrol:SetDigit(7,RANGE.Sound.RC7.filename,RANGE.Sound.RC7.duration,self.soundpath)
41566
- self.rangecontrol:SetDigit(8,RANGE.Sound.RC8.filename,RANGE.Sound.RC8.duration,self.soundpath)
41567
- self.rangecontrol:SetDigit(9,RANGE.Sound.RC9.filename,RANGE.Sound.RC9.duration,self.soundpath)
42018
+ self.rangecontrol:SetDigit(0,self.Sound.RC0.filename,self.Sound.RC0.duration,self.soundpath)
42019
+ self.rangecontrol:SetDigit(1,self.Sound.RC1.filename,self.Sound.RC1.duration,self.soundpath)
42020
+ self.rangecontrol:SetDigit(2,self.Sound.RC2.filename,self.Sound.RC2.duration,self.soundpath)
42021
+ self.rangecontrol:SetDigit(3,self.Sound.RC3.filename,self.Sound.RC3.duration,self.soundpath)
42022
+ self.rangecontrol:SetDigit(4,self.Sound.RC4.filename,self.Sound.RC4.duration,self.soundpath)
42023
+ self.rangecontrol:SetDigit(5,self.Sound.RC5.filename,self.Sound.RC5.duration,self.soundpath)
42024
+ self.rangecontrol:SetDigit(6,self.Sound.RC6.filename,self.Sound.RC6.duration,self.soundpath)
42025
+ self.rangecontrol:SetDigit(7,self.Sound.RC7.filename,self.Sound.RC7.duration,self.soundpath)
42026
+ self.rangecontrol:SetDigit(8,self.Sound.RC8.filename,self.Sound.RC8.duration,self.soundpath)
42027
+ self.rangecontrol:SetDigit(9,self.Sound.RC9.filename,self.Sound.RC9.duration,self.soundpath)
41568
42028
  self.rangecontrol:SetSenderCoordinate(self.location)
41569
42029
  self.rangecontrol:SetSenderUnitName(self.rangecontrolrelayname)
41570
42030
  self.rangecontrol:Start(1,0.1)
41571
42031
  if self.instructorfreq and not self.useSRS then
41572
42032
  self.instructor=RADIOQUEUE:New(self.instructorfreq,nil,self.rangename)
41573
42033
  self.instructor.schedonce=true
41574
- self.instructor:SetDigit(0,RANGE.Sound.IR0.filename,RANGE.Sound.IR0.duration,self.soundpath)
41575
- self.instructor:SetDigit(1,RANGE.Sound.IR1.filename,RANGE.Sound.IR1.duration,self.soundpath)
41576
- self.instructor:SetDigit(2,RANGE.Sound.IR2.filename,RANGE.Sound.IR2.duration,self.soundpath)
41577
- self.instructor:SetDigit(3,RANGE.Sound.IR3.filename,RANGE.Sound.IR3.duration,self.soundpath)
41578
- self.instructor:SetDigit(4,RANGE.Sound.IR4.filename,RANGE.Sound.IR4.duration,self.soundpath)
41579
- self.instructor:SetDigit(5,RANGE.Sound.IR5.filename,RANGE.Sound.IR5.duration,self.soundpath)
41580
- self.instructor:SetDigit(6,RANGE.Sound.IR6.filename,RANGE.Sound.IR6.duration,self.soundpath)
41581
- self.instructor:SetDigit(7,RANGE.Sound.IR7.filename,RANGE.Sound.IR7.duration,self.soundpath)
41582
- self.instructor:SetDigit(8,RANGE.Sound.IR8.filename,RANGE.Sound.IR8.duration,self.soundpath)
41583
- self.instructor:SetDigit(9,RANGE.Sound.IR9.filename,RANGE.Sound.IR9.duration,self.soundpath)
42034
+ self.instructor:SetDigit(0,self.Sound.IR0.filename,self.Sound.IR0.duration,self.soundpath)
42035
+ self.instructor:SetDigit(1,self.Sound.IR1.filename,self.Sound.IR1.duration,self.soundpath)
42036
+ self.instructor:SetDigit(2,self.Sound.IR2.filename,self.Sound.IR2.duration,self.soundpath)
42037
+ self.instructor:SetDigit(3,self.Sound.IR3.filename,self.Sound.IR3.duration,self.soundpath)
42038
+ self.instructor:SetDigit(4,self.Sound.IR4.filename,self.Sound.IR4.duration,self.soundpath)
42039
+ self.instructor:SetDigit(5,self.Sound.IR5.filename,self.Sound.IR5.duration,self.soundpath)
42040
+ self.instructor:SetDigit(6,self.Sound.IR6.filename,self.Sound.IR6.duration,self.soundpath)
42041
+ self.instructor:SetDigit(7,self.Sound.IR7.filename,self.Sound.IR7.duration,self.soundpath)
42042
+ self.instructor:SetDigit(8,self.Sound.IR8.filename,self.Sound.IR8.duration,self.soundpath)
42043
+ self.instructor:SetDigit(9,self.Sound.IR9.filename,self.Sound.IR9.duration,self.soundpath)
41584
42044
  self.instructor:SetSenderCoordinate(self.location)
41585
42045
  self.instructor:SetSenderUnitName(self.instructorrelayname)
41586
42046
  self.instructor:Start(1,0.1)
@@ -41596,7 +42056,11 @@ self:_SmokeStrafeTargets()
41596
42056
  self:_SmokeStrafeTargetBoxes()
41597
42057
  self.rangezone:SmokeZone(SMOKECOLOR.White)
41598
42058
  end
41599
- self:__Status(-60)
42059
+ self:__Status(-10)
42060
+ end
42061
+ function RANGE:SetMenuRoot(menu)
42062
+ self.menuF10root=menu
42063
+ return self
41600
42064
  end
41601
42065
  function RANGE:SetMaxStrafeAlt(maxalt)
41602
42066
  self.strafemaxalt=maxalt or RANGE.Defaults.strafemaxalt
@@ -41662,6 +42126,9 @@ self.location=coordinate
41662
42126
  return self
41663
42127
  end
41664
42128
  function RANGE:SetRangeZone(zone)
42129
+ if zone and type(zone)=="string"then
42130
+ zone=ZONE:FindByName(zone)
42131
+ end
41665
42132
  self.rangezone=zone
41666
42133
  return self
41667
42134
  end
@@ -41741,8 +42208,10 @@ self.instructmsrs:SetLabel("RANGEI")
41741
42208
  self.instructmsrs:SetVolume(Volume or 1.0)
41742
42209
  self.instructsrsQ=MSRSQUEUE:New("INSTRUCT")
41743
42210
  if PathToGoogleKey then
41744
- self.controlmsrs:SetGoogle(PathToGoogleKey)
41745
- self.instructmsrs:SetGoogle(PathToGoogleKey)
42211
+ self.controlmsrs:SetProviderOptionsGoogle(PathToGoogleKey,PathToGoogleKey)
42212
+ self.controlmsrs:SetProvider(MSRS.Provider.GOOGLE)
42213
+ self.instructmsrs:SetProviderOptionsGoogle(PathToGoogleKey,PathToGoogleKey)
42214
+ self.instructmsrs:SetProvider(MSRS.Provider.GOOGLE)
41746
42215
  end
41747
42216
  else
41748
42217
  self:E(self.lid..string.format("ERROR: No SRS path specified!"))
@@ -41803,6 +42272,31 @@ self.soundpath=tostring(path or"Range Soundfiles/")
41803
42272
  self:I(self.lid..string.format("Setting sound files path to %s",self.soundpath))
41804
42273
  return self
41805
42274
  end
42275
+ function RANGE:SetSoundfilesInfo(csvfile)
42276
+ local function getSound(filename)
42277
+ for key,_soundfile in pairs(self.Sound)do
42278
+ local soundfile=_soundfile
42279
+ if filename==soundfile.filename then
42280
+ return soundfile
42281
+ end
42282
+ end
42283
+ return nil
42284
+ end
42285
+ local data=UTILS.ReadCSV(csvfile)
42286
+ if data then
42287
+ for i,sound in pairs(data)do
42288
+ local soundfile=getSound(sound.filename..".ogg")
42289
+ if soundfile then
42290
+ soundfile.duration=tonumber(sound.duration)
42291
+ else
42292
+ self:E(string.format("ERROR: Could not get info for sound file %s",sound.filename))
42293
+ end
42294
+ end
42295
+ else
42296
+ self:E(string.format("ERROR: Could not read sound csv file!"))
42297
+ end
42298
+ return self
42299
+ end
41806
42300
  function RANGE:AddStrafePit(targetnames,boxlength,boxwidth,heading,inverseheading,goodpass,foulline)
41807
42301
  self:F({targetnames=targetnames,boxlength=boxlength,boxwidth=boxwidth,heading=heading,inverseheading=inverseheading,goodpass=goodpass,foulline=foulline})
41808
42302
  if type(targetnames)~="table"then
@@ -41984,6 +42478,9 @@ return self
41984
42478
  end
41985
42479
  function RANGE:AddBombingTargetGroup(group,goodhitrange,randommove)
41986
42480
  self:F({group=group,goodhitrange=goodhitrange,randommove=randommove})
42481
+ if group and type(group)=="string"then
42482
+ group=GROUP:FindByName(group)
42483
+ end
41987
42484
  if group then
41988
42485
  local _units=group:GetUnits()
41989
42486
  for _,_unit in pairs(_units)do
@@ -42197,7 +42694,7 @@ if self.rangecontrol then
42197
42694
  if self.useSRS then
42198
42695
  self.controlsrsQ:NewTransmission(_message,nil,self.controlmsrs,nil,1)
42199
42696
  else
42200
- self.rangecontrol:NewTransmission(RANGE.Sound.RCWeaponImpactedTooFar.filename,RANGE.Sound.RCWeaponImpactedTooFar.duration,self.soundpath,nil,nil,_message,self.subduration)
42697
+ self.rangecontrol:NewTransmission(self.Sound.RCWeaponImpactedTooFar.filename,self.Sound.RCWeaponImpactedTooFar.duration,self.soundpath,nil,nil,_message,self.subduration)
42201
42698
  end
42202
42699
  end
42203
42700
  else
@@ -42268,13 +42765,13 @@ local group=player.client:GetGroup()
42268
42765
  self.instructsrsQ:NewTransmission(ttstext,nil,self.instructmsrs,nil,1,{group},text,10)
42269
42766
  else
42270
42767
  local RF=UTILS.Split(string.format("%.3f",self.rangecontrolfreq),".")
42271
- self.instructor:NewTransmission(RANGE.Sound.IREnterRange.filename,RANGE.Sound.IREnterRange.duration,self.soundpath)
42768
+ self.instructor:NewTransmission(self.Sound.IREnterRange.filename,self.Sound.IREnterRange.duration,self.soundpath)
42272
42769
  self.instructor:Number2Transmission(RF[1])
42273
42770
  if tonumber(RF[2])>0 then
42274
- self.instructor:NewTransmission(RANGE.Sound.IRDecimal.filename,RANGE.Sound.IRDecimal.duration,self.soundpath)
42771
+ self.instructor:NewTransmission(self.Sound.IRDecimal.filename,self.Sound.IRDecimal.duration,self.soundpath)
42275
42772
  self.instructor:Number2Transmission(RF[2])
42276
42773
  end
42277
- self.instructor:NewTransmission(RANGE.Sound.IRMegaHertz.filename,RANGE.Sound.IRMegaHertz.duration,self.soundpath)
42774
+ self.instructor:NewTransmission(self.Sound.IRMegaHertz.filename,self.Sound.IRMegaHertz.duration,self.soundpath)
42278
42775
  end
42279
42776
  end
42280
42777
  end
@@ -42296,7 +42793,7 @@ text=text.."!"
42296
42793
  end
42297
42794
  self.instructsrsQ:NewTransmission(text,nil,self.instructmsrs,nil,1,{player.client:GetGroup()},text,10)
42298
42795
  else
42299
- self.instructor:NewTransmission(RANGE.Sound.IRExitRange.filename,RANGE.Sound.IRExitRange.duration,self.soundpath)
42796
+ self.instructor:NewTransmission(self.Sound.IRExitRange.filename,self.Sound.IRExitRange.duration,self.soundpath)
42300
42797
  end
42301
42798
  end
42302
42799
  end
@@ -42317,20 +42814,20 @@ if self.useSRS then
42317
42814
  local group=player.client:GetGroup()
42318
42815
  self.controlsrsQ:NewTransmission(text,nil,self.controlmsrs,nil,1,{group},text,10)
42319
42816
  else
42320
- self.rangecontrol:NewTransmission(RANGE.Sound.RCImpact.filename,RANGE.Sound.RCImpact.duration,self.soundpath,nil,nil,text,self.subduration)
42817
+ self.rangecontrol:NewTransmission(self.Sound.RCImpact.filename,self.Sound.RCImpact.duration,self.soundpath,nil,nil,text,self.subduration)
42321
42818
  self.rangecontrol:Number2Transmission(string.format("%03d",result.radial),nil,0.1)
42322
- self.rangecontrol:NewTransmission(RANGE.Sound.RCDegrees.filename,RANGE.Sound.RCDegrees.duration,self.soundpath)
42323
- self.rangecontrol:NewTransmission(RANGE.Sound.RCFor.filename,RANGE.Sound.RCFor.duration,self.soundpath)
42819
+ self.rangecontrol:NewTransmission(self.Sound.RCDegrees.filename,self.Sound.RCDegrees.duration,self.soundpath)
42820
+ self.rangecontrol:NewTransmission(self.Sound.RCFor.filename,self.Sound.RCFor.duration,self.soundpath)
42324
42821
  self.rangecontrol:Number2Transmission(string.format("%d",UTILS.MetersToFeet(result.distance)))
42325
- self.rangecontrol:NewTransmission(RANGE.Sound.RCFeet.filename,RANGE.Sound.RCFeet.duration,self.soundpath)
42822
+ self.rangecontrol:NewTransmission(self.Sound.RCFeet.filename,self.Sound.RCFeet.duration,self.soundpath)
42326
42823
  if result.quality=="POOR"then
42327
- self.rangecontrol:NewTransmission(RANGE.Sound.RCPoorHit.filename,RANGE.Sound.RCPoorHit.duration,self.soundpath,nil,0.5)
42824
+ self.rangecontrol:NewTransmission(self.Sound.RCPoorHit.filename,self.Sound.RCPoorHit.duration,self.soundpath,nil,0.5)
42328
42825
  elseif result.quality=="INEFFECTIVE"then
42329
- self.rangecontrol:NewTransmission(RANGE.Sound.RCIneffectiveHit.filename,RANGE.Sound.RCIneffectiveHit.duration,self.soundpath,nil,0.5)
42826
+ self.rangecontrol:NewTransmission(self.Sound.RCIneffectiveHit.filename,self.Sound.RCIneffectiveHit.duration,self.soundpath,nil,0.5)
42330
42827
  elseif result.quality=="GOOD"then
42331
- self.rangecontrol:NewTransmission(RANGE.Sound.RCGoodHit.filename,RANGE.Sound.RCGoodHit.duration,self.soundpath,nil,0.5)
42828
+ self.rangecontrol:NewTransmission(self.Sound.RCGoodHit.filename,self.Sound.RCGoodHit.duration,self.soundpath,nil,0.5)
42332
42829
  elseif result.quality=="EXCELLENT"then
42333
- self.rangecontrol:NewTransmission(RANGE.Sound.RCExcellentHit.filename,RANGE.Sound.RCExcellentHit.duration,self.soundpath,nil,0.5)
42830
+ self.rangecontrol:NewTransmission(self.Sound.RCExcellentHit.filename,self.Sound.RCExcellentHit.duration,self.soundpath,nil,0.5)
42334
42831
  end
42335
42832
  end
42336
42833
  end
@@ -42370,7 +42867,7 @@ else
42370
42867
  self:E(self.lid..string.format("ERROR: Could not save results to file %s",tostring(filename)))
42371
42868
  end
42372
42869
  end
42373
- local path=lfs.writedir()..[[Logs\]]
42870
+ local path=self.targetpath or lfs.writedir()..[[Logs\]]
42374
42871
  local filename=path..string.format("RANGE-%s_BombingResults.csv",self.rangename)
42375
42872
  local scores="Name,Pass,Target,Distance,Radial,Quality,Weapon,Airframe,Mission Time"
42376
42873
  for playername,results in pairs(self.bombPlayerResults)do
@@ -42409,7 +42906,7 @@ self:E(self.lid..string.format("WARNING: Could not load player results from file
42409
42906
  return nil
42410
42907
  end
42411
42908
  end
42412
- local path=lfs.writedir()..[[Logs\]]
42909
+ local path=self.targetpath or lfs.writedir()..[[Logs\]]
42413
42910
  local filename=path..string.format("RANGE-%s_BombingResults.csv",self.rangename)
42414
42911
  local text=string.format("Loading player bomb results from file %s",filename)
42415
42912
  self:I(self.lid..text)
@@ -42833,7 +43330,7 @@ local group=_unit:GetGroup()
42833
43330
  local text="You left the strafing zone too quickly! No score!"
42834
43331
  self.controlsrsQ:NewTransmission(text,nil,self.controlmsrs,nil,1)
42835
43332
  else
42836
- self.rangecontrol:NewTransmission(RANGE.Sound.RCLeftStrafePitTooQuickly.filename,RANGE.Sound.RCLeftStrafePitTooQuickly.duration,self.soundpath)
43333
+ self.rangecontrol:NewTransmission(self.Sound.RCLeftStrafePitTooQuickly.filename,self.Sound.RCLeftStrafePitTooQuickly.duration,self.soundpath)
42837
43334
  end
42838
43335
  end
42839
43336
  else
@@ -42851,23 +43348,23 @@ end
42851
43348
  local resulttext=""
42852
43349
  if _result.pastfoulline==true then
42853
43350
  resulttext="* INVALID - PASSED FOUL LINE *"
42854
- _sound=RANGE.Sound.RCPoorPass
43351
+ _sound=self.Sound.RCPoorPass
42855
43352
  else
42856
43353
  if accur>=90 then
42857
43354
  resulttext="DEADEYE PASS"
42858
- _sound=RANGE.Sound.RCExcellentPass
43355
+ _sound=self.Sound.RCExcellentPass
42859
43356
  elseif accur>=75 then
42860
43357
  resulttext="EXCELLENT PASS"
42861
- _sound=RANGE.Sound.RCExcellentPass
43358
+ _sound=self.Sound.RCExcellentPass
42862
43359
  elseif accur>=50 then
42863
43360
  resulttext="GOOD PASS"
42864
- _sound=RANGE.Sound.RCGoodPass
43361
+ _sound=self.Sound.RCGoodPass
42865
43362
  elseif accur>=25 then
42866
43363
  resulttext="INEFFECTIVE PASS"
42867
- _sound=RANGE.Sound.RCIneffectivePass
43364
+ _sound=self.Sound.RCIneffectivePass
42868
43365
  else
42869
43366
  resulttext="POOR PASS"
42870
- _sound=RANGE.Sound.RCPoorPass
43367
+ _sound=self.Sound.RCPoorPass
42871
43368
  end
42872
43369
  end
42873
43370
  local _text=string.format("%s, hits on target %s: %d",self:_myname(_unitName),_result.zone.name,_result.hits)
@@ -42902,14 +43399,14 @@ if self.rangecontrol then
42902
43399
  if self.useSRS then
42903
43400
  self.controlsrsQ:NewTransmission(ttstext,nil,self.controlmsrs,nil,1)
42904
43401
  else
42905
- self.rangecontrol:NewTransmission(RANGE.Sound.RCHitsOnTarget.filename,RANGE.Sound.RCHitsOnTarget.duration,self.soundpath)
43402
+ self.rangecontrol:NewTransmission(self.Sound.RCHitsOnTarget.filename,self.Sound.RCHitsOnTarget.duration,self.soundpath)
42906
43403
  self.rangecontrol:Number2Transmission(string.format("%d",_result.hits))
42907
43404
  if shots and accur then
42908
- self.rangecontrol:NewTransmission(RANGE.Sound.RCTotalRoundsFired.filename,RANGE.Sound.RCTotalRoundsFired.duration,self.soundpath,nil,0.2)
43405
+ self.rangecontrol:NewTransmission(self.Sound.RCTotalRoundsFired.filename,self.Sound.RCTotalRoundsFired.duration,self.soundpath,nil,0.2)
42909
43406
  self.rangecontrol:Number2Transmission(string.format("%d",shots),nil,0.2)
42910
- self.rangecontrol:NewTransmission(RANGE.Sound.RCAccuracy.filename,RANGE.Sound.RCAccuracy.duration,self.soundpath,nil,0.2)
43407
+ self.rangecontrol:NewTransmission(self.Sound.RCAccuracy.filename,self.Sound.RCAccuracy.duration,self.soundpath,nil,0.2)
42911
43408
  self.rangecontrol:Number2Transmission(string.format("%d",UTILS.Round(accur,0)))
42912
- self.rangecontrol:NewTransmission(RANGE.Sound.RCPercent.filename,RANGE.Sound.RCPercent.duration,self.soundpath)
43409
+ self.rangecontrol:NewTransmission(self.Sound.RCPercent.filename,self.Sound.RCPercent.duration,self.soundpath)
42913
43410
  end
42914
43411
  self.rangecontrol:NewTransmission(_sound.filename,_sound.duration,self.soundpath,nil,0.5)
42915
43412
  end
@@ -42933,7 +43430,7 @@ if self.rangecontrol then
42933
43430
  if self.useSRS then
42934
43431
  self.controlsrsQ:NewTransmission(_msg,nil,self.controlmsrs,nil,1)
42935
43432
  else
42936
- self.rangecontrol:NewTransmission(RANGE.Sound.RCRollingInOnStrafeTarget.filename,RANGE.Sound.RCRollingInOnStrafeTarget.duration,self.soundpath)
43433
+ self.rangecontrol:NewTransmission(self.Sound.RCRollingInOnStrafeTarget.filename,self.Sound.RCRollingInOnStrafeTarget.duration,self.soundpath)
42937
43434
  end
42938
43435
  end
42939
43436
  self:_DisplayMessageToGroup(_unit,_msg,10,true)
@@ -42953,15 +43450,21 @@ local _gid=group:GetID()
42953
43450
  if group and _gid then
42954
43451
  if not self.MenuAddedTo[_gid]then
42955
43452
  self.MenuAddedTo[_gid]=true
42956
- local _rangePath=nil
42957
- if RANGE.MenuF10Root then
42958
- _rangePath=MENU_GROUP:New(group,"On the Range")
43453
+ local _rootMenu=nil
43454
+ if self.menuF10root then
43455
+ _rootMenu=self.menuF10root
43456
+ self:T2(self.lid..string.format("Creating F10 menu for group %s",group:GetName()))
43457
+ elseif RANGE.MenuF10Root then
43458
+ _rootMenu=RANGE.MenuF10Root
42959
43459
  else
42960
43460
  if RANGE.MenuF10[_gid]==nil then
42961
- RANGE.MenuF10[_gid]=MENU_GROUP:New(group,"On the Range")
43461
+ self:T2(self.lid..string.format("Creating F10 menu 'On the Range' for group %s",group:GetName()))
43462
+ else
43463
+ self:T2(self.lid..string.format("F10 menu 'On the Range' already EXISTS for group %s",group:GetName()))
42962
43464
  end
42963
- _rangePath=MENU_GROUP:New(group,self.rangename,RANGE.MenuF10[_gid])
43465
+ _rootMenu=RANGE.MenuF10[_gid]or MENU_GROUP:New(group,"On the Range")
42964
43466
  end
43467
+ local _rangePath=MENU_GROUP:New(group,self.rangename,_rootMenu)
42965
43468
  local _statsPath=MENU_GROUP:New(group,"Statistics",_rangePath)
42966
43469
  local _markPath=MENU_GROUP:New(group,"Mark Targets",_rangePath)
42967
43470
  local _settingsPath=MENU_GROUP:New(group,"My Settings",_rangePath)
@@ -43216,12 +43719,12 @@ local text=""
43216
43719
  if self.targetsheet then
43217
43720
  playerData.targeton=not playerData.targeton
43218
43721
  if playerData and playerData.targeton==true then
43219
- text=string.format("roger, your targetsheets are now SAVED.")
43722
+ text=string.format("Roger, your targetsheets are now SAVED.")
43220
43723
  else
43221
- text=string.format("affirm, your targetsheets are NOT SAVED.")
43724
+ text=string.format("Affirm, your targetsheets are NOT SAVED.")
43222
43725
  end
43223
43726
  else
43224
- text="negative, target sheet data recorder is broken on this range."
43727
+ text="Negative, target sheet data recorder is broken on this range."
43225
43728
  end
43226
43729
  self:_DisplayMessageToGroup(unit,text,5,false,false)
43227
43730
  end
@@ -43861,7 +44364,7 @@ maxrange=32000,
43861
44364
  reloadtime=540,
43862
44365
  },
43863
44366
  }
43864
- ARTY.version="1.3.0"
44367
+ ARTY.version="1.3.1"
43865
44368
  function ARTY:New(group,alias)
43866
44369
  local self=BASE:Inherit(self,FSM_CONTROLLABLE:New())
43867
44370
  if type(group)=="string"then
@@ -44324,7 +44827,7 @@ self:_EventFromTo("onafterStart",Event,From,To)
44324
44827
  local text=string.format("Started ARTY version %s for group %s.",ARTY.version,Controllable:GetName())
44325
44828
  self:I(self.lid..text)
44326
44829
  MESSAGE:New(text,5):ToAllIf(self.Debug)
44327
- self.Nammo0,self.Nshells0,self.Nrockets0,self.Nmissiles0=self:GetAmmo(self.Debug)
44830
+ self.Nammo0,self.Nshells0,self.Nrockets0,self.Nmissiles0,self.Narty0=self:GetAmmo(self.Debug)
44328
44831
  if self.nukerange==nil then
44329
44832
  self.nukerange=1500/75000*self.nukewarhead
44330
44833
  end
@@ -44485,7 +44988,7 @@ function ARTY:_StatusReport(display)
44485
44988
  if display==nil then
44486
44989
  display=false
44487
44990
  end
44488
- local Nammo,Nshells,Nrockets,Nmissiles=self:GetAmmo()
44991
+ local Nammo,Nshells,Nrockets,Nmissiles,Narty=self:GetAmmo()
44489
44992
  local Nnukes=self.Nukes
44490
44993
  local Nillu=self.Nillu
44491
44994
  local Nsmoke=self.Nsmoke
@@ -44496,7 +44999,7 @@ text=text..string.format("ARTY group = %s\n",self.groupname)
44496
44999
  text=text..string.format("Clock = %s\n",Clock)
44497
45000
  text=text..string.format("FSM state = %s\n",self:GetState())
44498
45001
  text=text..string.format("Total ammo count = %d\n",Nammo)
44499
- text=text..string.format("Number of shells = %d\n",Nshells)
45002
+ text=text..string.format("Number of shells = %d\n",Narty)
44500
45003
  text=text..string.format("Number of rockets = %d\n",Nrockets)
44501
45004
  text=text..string.format("Number of missiles = %d\n",Nmissiles)
44502
45005
  text=text..string.format("Number of nukes = %d\n",Nnukes)
@@ -44589,7 +45092,7 @@ weapon:SetFuncTrack(ARTY._FuncTrack,self,target)
44589
45092
  weapon:SetFuncImpact(ARTY._FuncImpact,self,target)
44590
45093
  weapon:StartTrack(2)
44591
45094
  end
44592
- local _nammo,_nshells,_nrockets,_nmissiles=self:GetAmmo()
45095
+ local _nammo,_nshells,_nrockets,_nmissiles,_narty=self:GetAmmo()
44593
45096
  if self.currentTarget.weapontype==ARTY.WeaponType.TacticalNukes then
44594
45097
  self.Nukes=self.Nukes-1
44595
45098
  end
@@ -44606,7 +45109,7 @@ _outofammo=true
44606
45109
  end
44607
45110
  local _partlyoutofammo=self:_CheckOutOfAmmo({self.currentTarget})
44608
45111
  local _weapontype=self:_WeaponTypeName(self.currentTarget.weapontype)
44609
- self:T(self.lid..string.format("Group %s ammo: total=%d, shells=%d, rockets=%d, missiles=%d",self.groupname,_nammo,_nshells,_nrockets,_nmissiles))
45112
+ self:T(self.lid..string.format("Group %s ammo: total=%d, shells=%d, rockets=%d, missiles=%d",self.groupname,_nammo,_narty,_nrockets,_nmissiles))
44610
45113
  self:T(self.lid..string.format("Group %s uses weapontype %s for current target.",self.groupname,_weapontype))
44611
45114
  local _ceasefire=false
44612
45115
  local _relocate=false
@@ -44874,7 +45377,7 @@ end
44874
45377
  end
44875
45378
  function ARTY:onafterStatus(Controllable,From,Event,To)
44876
45379
  self:_EventFromTo("onafterStatus",Event,From,To)
44877
- local nammo,nshells,nrockets,nmissiles=self:GetAmmo()
45380
+ local nammo,nshells,nrockets,nmissiles,narty=self:GetAmmo()
44878
45381
  if self.iscargo and self.cargogroup then
44879
45382
  if self.cargogroup:IsLoaded()and not self:is("InTransit")then
44880
45383
  self:T(self.lid..string.format("Group %s has been loaded into a carrier and is now transported.",self.alias))
@@ -44885,7 +45388,7 @@ self:UnLoaded()
44885
45388
  end
44886
45389
  end
44887
45390
  local fsmstate=self:GetState()
44888
- self:T(self.lid..string.format("Status %s, Ammo total=%d: shells=%d [smoke=%d, illu=%d, nukes=%d*%.3f kT], rockets=%d, missiles=%d",fsmstate,nammo,nshells,self.Nsmoke,self.Nillu,self.Nukes,self.nukewarhead/1000000,nrockets,nmissiles))
45391
+ self:T(self.lid..string.format("Status %s, Ammo total=%d: shells=%d [smoke=%d, illu=%d, nukes=%d*%.3f kT], rockets=%d, missiles=%d",fsmstate,nammo,narty,self.Nsmoke,self.Nillu,self.Nukes,self.nukewarhead/1000000,nrockets,nmissiles))
44889
45392
  if self.Controllable and self.Controllable:IsAlive()then
44890
45393
  if self.Debug then
44891
45394
  self:_StatusReport()
@@ -44937,10 +45440,14 @@ elseif _timedTarget then
44937
45440
  if self.currentTarget then
44938
45441
  self:CeaseFire(self.currentTarget)
44939
45442
  end
45443
+ if self:is("CombatReady")then
44940
45444
  self:OpenFire(_timedTarget)
45445
+ end
44941
45446
  elseif _normalTarget then
45447
+ if self:is("CombatReady")then
44942
45448
  self:OpenFire(_normalTarget)
44943
45449
  end
45450
+ end
44944
45451
  local gotsome=false
44945
45452
  if#self.targets>0 then
44946
45453
  for i=1,#self.targets do
@@ -45010,14 +45517,14 @@ self.currentTarget=target
45010
45517
  self.currentTarget.Tassigned=timer.getTime()
45011
45518
  end
45012
45519
  local range=Controllable:GetCoordinate():Get2DDistance(target.coord)
45013
- local Nammo,Nshells,Nrockets,Nmissiles=self:GetAmmo()
45014
- local nfire=Nammo
45520
+ local Nammo,Nshells,Nrockets,Nmissiles,Narty=self:GetAmmo()
45521
+ local nfire=Narty
45015
45522
  local _type="shots"
45016
45523
  if target.weapontype==ARTY.WeaponType.Auto then
45017
- nfire=Nammo
45524
+ nfire=Narty
45018
45525
  _type="shots"
45019
45526
  elseif target.weapontype==ARTY.WeaponType.Cannon then
45020
- nfire=Nshells
45527
+ nfire=Narty
45021
45528
  _type="shells"
45022
45529
  elseif target.weapontype==ARTY.WeaponType.TacticalNukes then
45023
45530
  nfire=self.Nukes
@@ -45158,7 +45665,7 @@ end
45158
45665
  end
45159
45666
  function ARTY:_CheckRearmed()
45160
45667
  self:F2()
45161
- local nammo,nshells,nrockets,nmissiles=self:GetAmmo()
45668
+ local nammo,nshells,nrockets,nmissiles,narty=self:GetAmmo()
45162
45669
  local units=self.Controllable:GetUnits()
45163
45670
  local nunits=0
45164
45671
  if units then
@@ -45268,10 +45775,13 @@ local group=self.Controllable
45268
45775
  if weapontype==ARTY.WeaponType.TacticalNukes or weapontype==ARTY.WeaponType.IlluminationShells or weapontype==ARTY.WeaponType.SmokeShells then
45269
45776
  weapontype=ARTY.WeaponType.Cannon
45270
45777
  end
45778
+ if group:HasTask()then
45779
+ group:ClearTasks()
45780
+ end
45271
45781
  group:OptionROEOpenFire()
45272
45782
  local vec2=coord:GetVec2()
45273
45783
  local fire=group:TaskFireAtPoint(vec2,radius,nshells,weapontype)
45274
- group:SetTask(fire)
45784
+ group:SetTask(fire,1)
45275
45785
  end
45276
45786
  function ARTY:_AttackGroup(target)
45277
45787
  local group=self.Controllable
@@ -45279,10 +45789,13 @@ local weapontype=target.weapontype
45279
45789
  if weapontype==ARTY.WeaponType.TacticalNukes or weapontype==ARTY.WeaponType.IlluminationShells or weapontype==ARTY.WeaponType.SmokeShells then
45280
45790
  weapontype=ARTY.WeaponType.Cannon
45281
45791
  end
45792
+ if group:HasTask()then
45793
+ group:ClearTasks()
45794
+ end
45282
45795
  group:OptionROEOpenFire()
45283
45796
  local targetgroup=GROUP:FindByName(target.name)
45284
45797
  local fire=group:TaskAttackGroup(targetgroup,weapontype,AI.Task.WeaponExpend.ONE,1)
45285
- group:SetTask(fire)
45798
+ group:SetTask(fire,1)
45286
45799
  end
45287
45800
  function ARTY:_NuclearBlast(_coord)
45288
45801
  local S0=self.nukewarhead
@@ -45401,6 +45914,7 @@ local nammo=0
45401
45914
  local nshells=0
45402
45915
  local nrockets=0
45403
45916
  local nmissiles=0
45917
+ local nartyshells=0
45404
45918
  local units=self.Controllable:GetUnits()
45405
45919
  if units==nil then
45406
45920
  return nammo,nshells,nrockets,nmissiles
@@ -45468,6 +45982,8 @@ end
45468
45982
  end
45469
45983
  if _gotshell then
45470
45984
  nshells=nshells+Nammo
45985
+ local _,_,_,_,_,shells=unit:GetAmmunition()
45986
+ nartyshells=nartyshells+shells
45471
45987
  text=text..string.format("- %d shells of type %s\n",Nammo,_weaponName)
45472
45988
  elseif _gotrocket then
45473
45989
  nrockets=nrockets+Nammo
@@ -45491,7 +46007,7 @@ MESSAGE:New(text,10):ToAllIf(display)
45491
46007
  end
45492
46008
  end
45493
46009
  nammo=nshells+nrockets+nmissiles
45494
- return nammo,nshells,nrockets,nmissiles
46010
+ return nammo,nshells,nrockets,nmissiles,nartyshells
45495
46011
  end
45496
46012
  function ARTY:_MissileCategoryName(categorynumber)
45497
46013
  local cat="unknown"
@@ -45940,7 +46456,8 @@ local dt=Tnow-self.currentTarget.Tassigned
45940
46456
  if self.Nshots==0 then
45941
46457
  self:T(self.lid..string.format("%s, waiting for %d seconds for first shot on target %s.",self.groupname,dt,name))
45942
46458
  end
45943
- if dt>self.WaitForShotTime and(self.Nshots==0 or self.currentTarget.nshells>=self.Nshots)then
46459
+ self:T(string.format("dt = %d WaitTime = %d | shots = %d TargetShells = %d",dt,self.WaitForShotTime,self.Nshots,self.currentTarget.nshells))
46460
+ if(dt>self.WaitForShotTime and self.Nshots==0)or(self.currentTarget.nshells<=self.Nshots)then
45944
46461
  self:T(self.lid..string.format("%s, no shot event after %d seconds. Removing current target %s from list.",self.groupname,self.WaitForShotTime,name))
45945
46462
  self:CeaseFire(self.currentTarget)
45946
46463
  self:RemoveTarget(name)
@@ -45974,13 +46491,13 @@ self:T2(self.lid..string.format("WARNING: Move with name %s could not be found.
45974
46491
  return nil
45975
46492
  end
45976
46493
  function ARTY:_CheckOutOfAmmo(targets)
45977
- local _nammo,_nshells,_nrockets,_nmissiles=self:GetAmmo()
46494
+ local _nammo,_nshells,_nrockets,_nmissiles,_narty=self:GetAmmo()
45978
46495
  local _partlyoutofammo=false
45979
46496
  for _,Target in pairs(targets)do
45980
46497
  if Target.weapontype==ARTY.WeaponType.Auto and _nammo==0 then
45981
46498
  self:T(self.lid..string.format("Group %s, auto weapon requested for target %s but all ammo is empty.",self.groupname,Target.name))
45982
46499
  _partlyoutofammo=true
45983
- elseif Target.weapontype==ARTY.WeaponType.Cannon and _nshells==0 then
46500
+ elseif Target.weapontype==ARTY.WeaponType.Cannon and _narty==0 then
45984
46501
  self:T(self.lid..string.format("Group %s, cannons requested for target %s but shells empty.",self.groupname,Target.name))
45985
46502
  _partlyoutofammo=true
45986
46503
  elseif Target.weapontype==ARTY.WeaponType.TacticalNukes and self.Nukes<=0 then
@@ -46003,12 +46520,12 @@ end
46003
46520
  return _partlyoutofammo
46004
46521
  end
46005
46522
  function ARTY:_CheckWeaponTypeAvailable(target)
46006
- local Nammo,Nshells,Nrockets,Nmissiles=self:GetAmmo()
46523
+ local Nammo,Nshells,Nrockets,Nmissiles,Narty=self:GetAmmo()
46007
46524
  local nfire=Nammo
46008
46525
  if target.weapontype==ARTY.WeaponType.Auto then
46009
46526
  nfire=Nammo
46010
46527
  elseif target.weapontype==ARTY.WeaponType.Cannon then
46011
- nfire=Nshells
46528
+ nfire=Narty
46012
46529
  elseif target.weapontype==ARTY.WeaponType.TacticalNukes then
46013
46530
  nfire=self.Nukes
46014
46531
  elseif target.weapontype==ARTY.WeaponType.IlluminationShells then
@@ -50384,6 +50901,7 @@ if not self.allowSpawnOnClientSpots then
50384
50901
  local clients=_DATABASE.CLIENTS
50385
50902
  for clientname,client in pairs(clients)do
50386
50903
  local template=_DATABASE:GetGroupTemplateFromUnitName(clientname)
50904
+ if template then
50387
50905
  local units=template.units
50388
50906
  for i,unit in pairs(units)do
50389
50907
  local coord=COORDINATE:New(unit.x,unit.alt,unit.y)
@@ -50391,6 +50909,7 @@ coords[unit.name]=coord
50391
50909
  end
50392
50910
  end
50393
50911
  end
50912
+ end
50394
50913
  return coords
50395
50914
  end
50396
50915
  local parkingdata=airbase.parking
@@ -51993,6 +52512,7 @@ SuppressedGroups={},
51993
52512
  automode=true,
51994
52513
  autoshorad=true,
51995
52514
  ShoradGroupSet=nil,
52515
+ checkforfriendlies=false,
51996
52516
  }
51997
52517
  MANTIS.AdvancedState={
51998
52518
  GREEN=0,
@@ -52081,6 +52601,7 @@ MANTIS.SamDataCH={
52081
52601
  do
52082
52602
  function MANTIS:New(name,samprefix,ewrprefix,hq,coalition,dynamic,awacs,EmOnOff,Padding,Zones)
52083
52603
  local self=BASE:Inherit(self,FSM:New())
52604
+ self.name=name or"mymantis"
52084
52605
  self.SAM_Templates_Prefix=samprefix or"Red SAM"
52085
52606
  self.EWR_Templates_Prefix=ewrprefix or"Red EWR"
52086
52607
  self.HQ_Template_CC=hq or nil
@@ -52181,7 +52702,7 @@ end
52181
52702
  if self.HQ_Template_CC then
52182
52703
  self.HQ_CC=GROUP:FindByName(self.HQ_Template_CC)
52183
52704
  end
52184
- self.version="0.8.16"
52705
+ self.version="0.8.18"
52185
52706
  self:I(string.format("***** Starting MANTIS Version %s *****",self.version))
52186
52707
  self:SetStartState("Stopped")
52187
52708
  self:AddTransition("Stopped","Start","Running")
@@ -52518,6 +53039,10 @@ local set=dectset
52518
53039
  if dlink then
52519
53040
  set=self:_PreFilterHeight(height)
52520
53041
  end
53042
+ local friendlyset
53043
+ if self.checkforfriendlies==true then
53044
+ friendlyset=SET_GROUP:New():FilterCoalitions(self.Coalition):FilterCategories({"plane","helicopter"}):FilterFunction(function(grp)if grp and grp:InAir()then return true else return false end end):FilterOnce()
53045
+ end
52521
53046
  for _,_coord in pairs(set)do
52522
53047
  local coord=_coord
52523
53048
  local targetdistance=samcoordinate:DistanceFromPointVec2(coord)
@@ -52539,7 +53064,14 @@ local text=string.format("Checking SAM at %s | Targetdist %d | Rad %d | Inrange
52539
53064
  local m=MESSAGE:New(text,10,"Check"):ToAllIf(self.debug)
52540
53065
  self:T(self.lid..text)
52541
53066
  end
52542
- if targetdistance<=rad and zonecheck then
53067
+ local nofriendlies=true
53068
+ if self.checkforfriendlies==true then
53069
+ local closestfriend,distance=friendlyset:GetClosestGroup(samcoordinate)
53070
+ if closestfriend and distance and distance<rad then
53071
+ nofriendlies=false
53072
+ end
53073
+ end
53074
+ if targetdistance<=rad and zonecheck==true and nofriendlies==true then
52543
53075
  return true,targetdistance
52544
53076
  end
52545
53077
  end
@@ -53476,6 +54008,313 @@ end
53476
54008
  return self
53477
54009
  end
53478
54010
  end
54011
+ CLIENTWATCH={}
54012
+ CLIENTWATCH.ClassName="CLIENTWATCH"
54013
+ CLIENTWATCH.Debug=false
54014
+ CLIENTWATCH.lid=nil
54015
+ CLIENTWATCHTools={}
54016
+ CLIENTWATCH.version="1.0.1"
54017
+ function CLIENTWATCH:New(client)
54018
+ local self=BASE:Inherit(self,FSM:New())
54019
+ self:SetStartState("Idle")
54020
+ self:AddTransition("*","Spawn","*")
54021
+ if type(client)=="table"or type(client)=="string"then
54022
+ if type(client)=="table"then
54023
+ if client.ClassName=="CLIENT"then
54024
+ self.ClientName=client:GetName()
54025
+ self:HandleEvent(EVENTS.Birth)
54026
+ function self:OnEventBirth(eventdata)
54027
+ if self.Debug then UTILS.PrintTableToLog(eventdata)end
54028
+ if eventdata.IniCategory and eventdata.IniCategory<=1 then
54029
+ if self.ClientName==eventdata.IniUnitName then
54030
+ local clientObject=CLIENTWATCHTools:_newClient(eventdata)
54031
+ self:Spawn(clientObject)
54032
+ end
54033
+ end
54034
+ end
54035
+ else
54036
+ local tableValid=true
54037
+ for _,entry in pairs(client)do
54038
+ if type(entry)~="string"then
54039
+ tableValid=false
54040
+ self:E({"The base handler failed to start because at least one entry in param1's table is not a string!",InvalidEntry=entry})
54041
+ return nil
54042
+ end
54043
+ end
54044
+ if tableValid then
54045
+ self:HandleEvent(EVENTS.Birth)
54046
+ function self:OnEventBirth(eventdata)
54047
+ if self.Debug then UTILS.PrintTableToLog(eventdata)end
54048
+ for _,entry in pairs(client)do
54049
+ if eventdata.IniCategory and eventdata.IniCategory<=1 then
54050
+ if string.match(eventdata.IniUnitName,entry)or string.match(eventdata.IniGroupName,entry)then
54051
+ local clientObject=CLIENTWATCHTools:_newClient(eventdata)
54052
+ self:Spawn(clientObject)
54053
+ break
54054
+ end
54055
+ end
54056
+ end
54057
+ end
54058
+ end
54059
+ end
54060
+ else
54061
+ self:HandleEvent(EVENTS.Birth)
54062
+ function self:OnEventBirth(eventdata)
54063
+ if self.Debug then UTILS.PrintTableToLog(eventdata)end
54064
+ if eventdata.IniCategory and eventdata.IniCategory<=1 then
54065
+ if string.match(eventdata.IniUnitName,client)or string.match(eventdata.IniGroupName,client)then
54066
+ local clientObject=CLIENTWATCHTools:_newClient(eventdata)
54067
+ self:Spawn(clientObject)
54068
+ end
54069
+ end
54070
+ end
54071
+ end
54072
+ else
54073
+ self:E({"The base handler failed to start because param1 is not a CLIENT object or a prefix string!",param1=client})
54074
+ return nil
54075
+ end
54076
+ return self
54077
+ end
54078
+ function CLIENTWATCHTools:_newClient(eventdata)
54079
+ local self=BASE:Inherit(self,FSM:New())
54080
+ self:SetStartState("Alive")
54081
+ self:AddTransition("Alive","Despawn","Dead")
54082
+ self.Unit=eventdata.IniUnit
54083
+ self.Group=self.Unit:GetGroup()
54084
+ self.Client=self.Unit:GetClient()
54085
+ self.PlayerName=self.Unit:GetPlayerName()
54086
+ self.UnitName=self.Unit:GetName()
54087
+ self.GroupName=self.Group:GetName()
54088
+ self:AddTransition("*","Hit","*")
54089
+ self:AddTransition("*","Kill","*")
54090
+ self:AddTransition("*","Score","*")
54091
+ self:AddTransition("*","Shot","*")
54092
+ self:AddTransition("*","ShootingStart","*")
54093
+ self:AddTransition("*","ShootingEnd","*")
54094
+ self:AddTransition("*","Land","*")
54095
+ self:AddTransition("*","Takeoff","*")
54096
+ self:AddTransition("*","RunwayTakeoff","*")
54097
+ self:AddTransition("*","RunwayTouch","*")
54098
+ self:AddTransition("*","Refueling","*")
54099
+ self:AddTransition("*","RefuelingStop","*")
54100
+ self:AddTransition("*","PlayerLeaveUnit","*")
54101
+ self:AddTransition("*","Crash","*")
54102
+ self:AddTransition("*","Dead","*")
54103
+ self:AddTransition("*","PilotDead","*")
54104
+ self:AddTransition("*","UnitLost","*")
54105
+ self:AddTransition("*","Ejection","*")
54106
+ self:AddTransition("*","HumanFailure","*")
54107
+ self:AddTransition("*","HumanAircraftRepairFinish","*")
54108
+ self:AddTransition("*","HumanAircraftRepairStart","*")
54109
+ self:AddTransition("*","EngineShutdown","*")
54110
+ self:AddTransition("*","EngineStartup","*")
54111
+ self:AddTransition("*","WeaponAdd","*")
54112
+ self:AddTransition("*","WeaponDrop","*")
54113
+ self:AddTransition("*","WeaponRearm","*")
54114
+ self:HandleEvent(EVENTS.Hit)
54115
+ self:HandleEvent(EVENTS.Kill)
54116
+ self:HandleEvent(EVENTS.Score)
54117
+ self:HandleEvent(EVENTS.Shot)
54118
+ self:HandleEvent(EVENTS.ShootingStart)
54119
+ self:HandleEvent(EVENTS.ShootingEnd)
54120
+ self:HandleEvent(EVENTS.Land)
54121
+ self:HandleEvent(EVENTS.Takeoff)
54122
+ self:HandleEvent(EVENTS.RunwayTakeoff)
54123
+ self:HandleEvent(EVENTS.RunwayTouch)
54124
+ self:HandleEvent(EVENTS.Refueling)
54125
+ self:HandleEvent(EVENTS.RefuelingStop)
54126
+ self:HandleEvent(EVENTS.PlayerLeaveUnit)
54127
+ self:HandleEvent(EVENTS.Crash)
54128
+ self:HandleEvent(EVENTS.Dead)
54129
+ self:HandleEvent(EVENTS.PilotDead)
54130
+ self:HandleEvent(EVENTS.UnitLost)
54131
+ self:HandleEvent(EVENTS.Ejection)
54132
+ self:HandleEvent(EVENTS.HumanFailure)
54133
+ self:HandleEvent(EVENTS.HumanAircraftRepairFinish)
54134
+ self:HandleEvent(EVENTS.HumanAircraftRepairStart)
54135
+ self:HandleEvent(EVENTS.EngineShutdown)
54136
+ self:HandleEvent(EVENTS.EngineStartup)
54137
+ self:HandleEvent(EVENTS.WeaponAdd)
54138
+ self:HandleEvent(EVENTS.WeaponDrop)
54139
+ self:HandleEvent(EVENTS.WeaponRearm)
54140
+ function self:OnEventHit(EventData)
54141
+ if EventData.TgtUnitName==self.UnitName then
54142
+ self:Hit(EventData)
54143
+ end
54144
+ end
54145
+ function self:OnEventKill(EventData)
54146
+ if EventData.IniUnitName==self.UnitName then
54147
+ self:Kill(EventData)
54148
+ end
54149
+ end
54150
+ function self:OnEventScore(EventData)
54151
+ if EventData.IniUnitName==self.UnitName then
54152
+ self:Score(EventData)
54153
+ end
54154
+ end
54155
+ function self:OnEventShot(EventData)
54156
+ if EventData.IniUnitName==self.UnitName then
54157
+ self:Shot(EventData)
54158
+ end
54159
+ end
54160
+ function self:OnEventShootingStart(EventData)
54161
+ if EventData.IniUnitName==self.UnitName then
54162
+ self:ShootingStart(EventData)
54163
+ end
54164
+ end
54165
+ function self:OnEventShootingEnd(EventData)
54166
+ if EventData.IniUnitName==self.UnitName then
54167
+ self:ShootingEnd(EventData)
54168
+ end
54169
+ end
54170
+ function self:OnEventLand(EventData)
54171
+ if EventData.IniUnitName==self.UnitName then
54172
+ self:Land(EventData)
54173
+ end
54174
+ end
54175
+ function self:OnEventTakeoff(EventData)
54176
+ if EventData.IniUnitName==self.UnitName then
54177
+ self:Takeoff(EventData)
54178
+ end
54179
+ end
54180
+ function self:OnEventRunwayTakeoff(EventData)
54181
+ if EventData.IniUnitName==self.UnitName then
54182
+ self:RunwayTakeoff(EventData)
54183
+ end
54184
+ end
54185
+ function self:OnEventRunwayTouch(EventData)
54186
+ if EventData.IniUnitName==self.UnitName then
54187
+ self:RunwayTouch(EventData)
54188
+ end
54189
+ end
54190
+ function self:OnEventRefueling(EventData)
54191
+ if EventData.IniUnitName==self.UnitName then
54192
+ self:Refueling(EventData)
54193
+ end
54194
+ end
54195
+ function self:OnEventRefuelingStop(EventData)
54196
+ if EventData.IniUnitName==self.UnitName then
54197
+ self:RefuelingStop(EventData)
54198
+ end
54199
+ end
54200
+ function self:OnEventPlayerLeaveUnit(EventData)
54201
+ if EventData.IniUnitName==self.UnitName then
54202
+ self:PlayerLeaveUnit(EventData)
54203
+ self._deadRoutine()
54204
+ end
54205
+ end
54206
+ function self:OnEventCrash(EventData)
54207
+ if EventData.IniUnitName==self.UnitName then
54208
+ self:Crash(EventData)
54209
+ self._deadRoutine()
54210
+ end
54211
+ end
54212
+ function self:OnEventDead(EventData)
54213
+ if EventData.IniUnitName==self.UnitName then
54214
+ self:Dead(EventData)
54215
+ self._deadRoutine()
54216
+ end
54217
+ end
54218
+ function self:OnEventPilotDead(EventData)
54219
+ if EventData.IniUnitName==self.UnitName then
54220
+ self:PilotDead(EventData)
54221
+ self._deadRoutine()
54222
+ end
54223
+ end
54224
+ function self:OnEventUnitLost(EventData)
54225
+ if EventData.IniUnitName==self.UnitName then
54226
+ self:UnitLost(EventData)
54227
+ self._deadRoutine()
54228
+ end
54229
+ end
54230
+ function self:OnEventEjection(EventData)
54231
+ if EventData.IniUnitName==self.UnitName then
54232
+ self:Ejection(EventData)
54233
+ self._deadRoutine()
54234
+ end
54235
+ end
54236
+ function self:OnEventHumanFailure(EventData)
54237
+ if EventData.IniUnitName==self.UnitName then
54238
+ self:HumanFailure(EventData)
54239
+ if not self.Unit:IsAlive()then
54240
+ self._deadRoutine()
54241
+ end
54242
+ end
54243
+ end
54244
+ function self:OnEventHumanAircraftRepairFinish(EventData)
54245
+ if EventData.IniUnitName==self.UnitName then
54246
+ self:HumanAircraftRepairFinish(EventData)
54247
+ end
54248
+ end
54249
+ function self:OnEventHumanAircraftRepairStart(EventData)
54250
+ if EventData.IniUnitName==self.UnitName then
54251
+ self:HumanAircraftRepairStart(EventData)
54252
+ end
54253
+ end
54254
+ function self:OnEventEngineShutdown(EventData)
54255
+ if EventData.IniUnitName==self.UnitName then
54256
+ self:EngineShutdown(EventData)
54257
+ end
54258
+ end
54259
+ function self:OnEventEngineStartup(EventData)
54260
+ if EventData.IniUnitName==self.UnitName then
54261
+ self:EngineStartup(EventData)
54262
+ end
54263
+ end
54264
+ function self:OnEventWeaponAdd(EventData)
54265
+ if EventData.IniUnitName==self.UnitName then
54266
+ self:WeaponAdd(EventData)
54267
+ end
54268
+ end
54269
+ function self:OnEventWeaponDrop(EventData)
54270
+ if EventData.IniUnitName==self.UnitName then
54271
+ self:WeaponDrop(EventData)
54272
+ end
54273
+ end
54274
+ function self:OnEventWeaponRearm(EventData)
54275
+ if EventData.IniUnitName==self.UnitName then
54276
+ self:WeaponRearm(EventData)
54277
+ end
54278
+ end
54279
+ self.FallbackTimer=TIMER:New(function()
54280
+ if not self.Unit:IsAlive()then
54281
+ self._deadRoutine()
54282
+ end
54283
+ end)
54284
+ self.FallbackTimer:Start(5,5)
54285
+ function self._deadRoutine()
54286
+ self:UnHandleEvent(EVENTS.Hit)
54287
+ self:UnHandleEvent(EVENTS.Kill)
54288
+ self:UnHandleEvent(EVENTS.Score)
54289
+ self:UnHandleEvent(EVENTS.Shot)
54290
+ self:UnHandleEvent(EVENTS.ShootingStart)
54291
+ self:UnHandleEvent(EVENTS.ShootingEnd)
54292
+ self:UnHandleEvent(EVENTS.Land)
54293
+ self:UnHandleEvent(EVENTS.Takeoff)
54294
+ self:UnHandleEvent(EVENTS.RunwayTakeoff)
54295
+ self:UnHandleEvent(EVENTS.RunwayTouch)
54296
+ self:UnHandleEvent(EVENTS.Refueling)
54297
+ self:UnHandleEvent(EVENTS.RefuelingStop)
54298
+ self:UnHandleEvent(EVENTS.PlayerLeaveUnit)
54299
+ self:UnHandleEvent(EVENTS.Crash)
54300
+ self:UnHandleEvent(EVENTS.Dead)
54301
+ self:UnHandleEvent(EVENTS.PilotDead)
54302
+ self:UnHandleEvent(EVENTS.UnitLost)
54303
+ self:UnHandleEvent(EVENTS.Ejection)
54304
+ self:UnHandleEvent(EVENTS.HumanFailure)
54305
+ self:UnHandleEvent(EVENTS.HumanAircraftRepairFinish)
54306
+ self:UnHandleEvent(EVENTS.HumanAircraftRepairStart)
54307
+ self:UnHandleEvent(EVENTS.EngineShutdown)
54308
+ self:UnHandleEvent(EVENTS.EngineStartup)
54309
+ self:UnHandleEvent(EVENTS.WeaponAdd)
54310
+ self:UnHandleEvent(EVENTS.WeaponDrop)
54311
+ self:UnHandleEvent(EVENTS.WeaponRearm)
54312
+ self.FallbackTimer:Stop()
54313
+ self:Despawn()
54314
+ end
54315
+ self:I({"CLIENT SPAWN EVENT",PlayerName=self.PlayerName,UnitName=self.UnitName,GroupName=self.GroupName})
54316
+ return self
54317
+ end
53479
54318
  AIRBOSS={
53480
54319
  ClassName="AIRBOSS",
53481
54320
  Debug=false,
@@ -54018,6 +54857,13 @@ function AIRBOSS:SetLSOCallInterval(TimeInterval)
54018
54857
  self.LSOdT=TimeInterval or 4
54019
54858
  return self
54020
54859
  end
54860
+ function AIRBOSS:SetIntoWindLegacy(SwitchOn)
54861
+ if SwitchOn==nil then
54862
+ SwitchOn=true
54863
+ end
54864
+ self.intowindold=SwitchOn
54865
+ return self
54866
+ end
54021
54867
  function AIRBOSS:SetAirbossNiceGuy(Switch)
54022
54868
  if Switch==true or Switch==nil then
54023
54869
  self.airbossnice=true
@@ -54482,6 +55328,9 @@ local eta=UTILS.SecondsToClock(self:_GetETAatNextWP())
54482
55328
  local hdg=self:GetHeading()
54483
55329
  local pos=self:GetCoordinate()
54484
55330
  local speed=self.carrier:GetVelocityKNOTS()
55331
+ if require then
55332
+ self.magvar=pos:GetMagneticDeclination()
55333
+ end
54485
55334
  local collision=false
54486
55335
  local holdtime=0
54487
55336
  if self.holdtimestamp then
@@ -55399,6 +56248,7 @@ HAWKEYE={file="PILOT-Hawkeye",suffix="ogg",loud=false,subtitle="",duration=0.63,
55399
56248
  TOMCAT={file="PILOT-Tomcat",suffix="ogg",loud=false,subtitle="",duration=0.66,subduration=5},
55400
56249
  HORNET={file="PILOT-Hornet",suffix="ogg",loud=false,subtitle="",duration=0.56,subduration=5},
55401
56250
  VIKING={file="PILOT-Viking",suffix="ogg",loud=false,subtitle="",duration=0.61,subduration=5},
56251
+ GREYHOUND={file="PILOT-Greyhound",suffix="ogg",loud=false,subtitle="",duration=0.61,subduration=5},
55402
56252
  BALL={file="PILOT-Ball",suffix="ogg",loud=false,subtitle="",duration=0.50,subduration=5},
55403
56253
  BINGOFUEL={file="PILOT-BingoFuel",suffix="ogg",loud=false,subtitle="",duration=0.80},
55404
56254
  GASATDIVERT={file="PILOT-GasAtDivert",suffix="ogg",loud=false,subtitle="",duration=1.80},
@@ -56026,7 +56876,7 @@ or flight.actype==AIRBOSS.AircraftCarrier.RHINOE
56026
56876
  or flight.actype==AIRBOSS.AircraftCarrier.RHINOF
56027
56877
  or flight.actype==AIRBOSS.AircraftCarrier.GROWLER then
56028
56878
  Speed=UTILS.KnotsToKmph(200)
56029
- elseif flight.actype==AIRBOSS.AircraftCarrier.E2D then
56879
+ elseif flight.actype==AIRBOSS.AircraftCarrier.E2D or flight.actype==AIRBOSS.AircraftCarrier.C2A then
56030
56880
  Speed=UTILS.KnotsToKmph(150)
56031
56881
  elseif flight.actype==AIRBOSS.AircraftCarrier.F14A_AI or flight.actype==AIRBOSS.AircraftCarrier.F14A or flight.actype==AIRBOSS.AircraftCarrier.F14B then
56032
56882
  Speed=UTILS.KnotsToKmph(175)
@@ -58483,7 +59333,14 @@ local vpp=UTILS.VecDot(vT,zc)
58483
59333
  local vabs=UTILS.VecNorm(vT)
58484
59334
  return-vpa,vpp,vabs
58485
59335
  end
58486
- function AIRBOSS:GetHeadingIntoWind_old(magnetic,coord)
59336
+ function AIRBOSS:GetHeadingIntoWind(vdeck,magnetic,coord)
59337
+ if self.intowindold then
59338
+ return self:GetHeadingIntoWind_old(vdeck,magnetic,coord)
59339
+ else
59340
+ return self:GetHeadingIntoWind_new(vdeck,magnetic,coord)
59341
+ end
59342
+ end
59343
+ function AIRBOSS:GetHeadingIntoWind_old(vdeck,magnetic,coord)
58487
59344
  local function adjustDegreesForWindSpeed(windSpeed)
58488
59345
  local degreesAdjustment=0
58489
59346
  if windSpeed>0 and windSpeed<3 then
@@ -58510,9 +59367,10 @@ end
58510
59367
  if intowind<0 then
58511
59368
  intowind=intowind+360
58512
59369
  end
58513
- return intowind
59370
+ local vtot=math.max(vdeck-UTILS.MpsToKnots(vwind),4)
59371
+ return intowind,vtot
58514
59372
  end
58515
- function AIRBOSS:GetHeadingIntoWind(vdeck,magnetic,coord)
59373
+ function AIRBOSS:GetHeadingIntoWind_new(vdeck,magnetic,coord)
58516
59374
  local Offset=self.carrierparam.rwyangle or 0
58517
59375
  local windfrom,vwind=self:GetWind(18,nil,coord)
58518
59376
  local Vmin=4
@@ -59846,6 +60704,8 @@ elseif actype==AIRBOSS.AircraftCarrier.AV8B then
59846
60704
  nickname="Harrier"
59847
60705
  elseif actype==AIRBOSS.AircraftCarrier.E2D then
59848
60706
  nickname="Hawkeye"
60707
+ elseif actype==AIRBOSS.AircraftCarrier.C2A then
60708
+ nickname="Greyhound"
59849
60709
  elseif actype==AIRBOSS.AircraftCarrier.F14A_AI or actype==AIRBOSS.AircraftCarrier.F14A or actype==AIRBOSS.AircraftCarrier.F14B then
59850
60710
  nickname="Tomcat"
59851
60711
  elseif actype==AIRBOSS.AircraftCarrier.FA18C or actype==AIRBOSS.AircraftCarrier.HORNET then
@@ -59865,8 +60725,10 @@ end
59865
60725
  function AIRBOSS:_GetOnboardNumbers(group,playeronly)
59866
60726
  local groupname=group:GetName()
59867
60727
  local text=string.format("Onboard numbers of group %s:",groupname)
59868
- local units=group:GetTemplate().units
60728
+ local template=group:GetTemplate()
59869
60729
  local numbers={}
60730
+ if template then
60731
+ local units=template.units
59870
60732
  for _,unit in pairs(units)do
59871
60733
  local n=tostring(unit.onboard_num)
59872
60734
  local name=unit.name
@@ -59878,6 +60740,17 @@ end
59878
60740
  numbers[name]=n
59879
60741
  end
59880
60742
  self:T2(self.lid..text)
60743
+ else
60744
+ if playeronly then
60745
+ return 101
60746
+ else
60747
+ local units=group:GetUnits()
60748
+ for i,_unit in pairs(units)do
60749
+ local name=_unit:GetName()
60750
+ numbers[name]=100+i
60751
+ end
60752
+ end
60753
+ end
59881
60754
  return numbers
59882
60755
  end
59883
60756
  function AIRBOSS:_GetTowerFrequency()
@@ -63234,6 +64107,8 @@ SinaiMap=true,
63234
64107
  }
63235
64108
  ATIS.Sound={
63236
64109
  ActiveRunway={filename="ActiveRunway.ogg",duration=0.99},
64110
+ ActiveRunwayDeparture={filename="ActiveRunwayDeparture.ogg",duration=0.99},
64111
+ ActiveRunwayArrival={filename="ActiveRunwayArrival.ogg",duration=0.99},
63237
64112
  AdviceOnInitial={filename="AdviceOnInitial.ogg",duration=3.00},
63238
64113
  Airport={filename="Airport.ogg",duration=0.66},
63239
64114
  Altimeter={filename="Altimeter.ogg",duration=0.68},
@@ -63545,11 +64420,46 @@ function ATIS:SetLocale(locale)
63545
64420
  self.locale=string.lower(locale)
63546
64421
  return self
63547
64422
  end
63548
- function ATIS:SetSoundfilesPath(path)
63549
- self.soundpath=tostring(path or"ATIS Soundfiles/")
64423
+ function ATIS:SetSoundfilesPath(pathMain,pathAirports,pathNato)
64424
+ self.soundpath=tostring(pathMain or"ATIS Soundfiles/")
64425
+ if pathAirports==nil then
64426
+ self.soundpathAirports=self.soundpath..env.mission.theatre.."/"
64427
+ else
64428
+ self.soundpathAirports=pathAirports
64429
+ end
64430
+ if pathNato==nil then
64431
+ self.soundpathNato=self.soundpath.."NATO Alphabet/"
64432
+ else
64433
+ self.soundpathNato=pathNato
64434
+ end
63550
64435
  self:T(self.lid..string.format("Setting sound files path to %s",self.soundpath))
63551
64436
  return self
63552
64437
  end
64438
+ function ATIS:SetSoundfilesInfo(csvfile)
64439
+ local function getSound(filename)
64440
+ for key,_soundfile in pairs(self.Sound)do
64441
+ local soundfile=_soundfile
64442
+ if filename==soundfile.filename then
64443
+ return soundfile
64444
+ end
64445
+ end
64446
+ return nil
64447
+ end
64448
+ local data=UTILS.ReadCSV(csvfile)
64449
+ if data then
64450
+ for i,sound in pairs(data)do
64451
+ local soundfile=getSound(sound.filename..".ogg")
64452
+ if soundfile then
64453
+ soundfile.duration=tonumber(sound.duration)
64454
+ else
64455
+ self:E(string.format("ERROR: Could not get info for sound file %s",sound.filename))
64456
+ end
64457
+ end
64458
+ else
64459
+ self:E(string.format("ERROR: Could not read sound csv file!"))
64460
+ end
64461
+ return self
64462
+ end
63553
64463
  function ATIS:SetRadioRelayUnitName(unitname)
63554
64464
  self.relayunitname=unitname
63555
64465
  self:T(self.lid..string.format("Setting radio relay unit to %s",self.relayunitname))
@@ -63833,16 +64743,16 @@ self.radioqueue=RADIOQUEUE:New(self.frequency,self.modulation,string.format("ATI
63833
64743
  self.radioqueue:SetSenderCoordinate(self.airbase:GetCoordinate())
63834
64744
  self.radioqueue:SetSenderUnitName(self.relayunitname)
63835
64745
  self.radioqueue:SetRadioPower(self.power)
63836
- self.radioqueue:SetDigit(0,ATIS.Sound.N0.filename,ATIS.Sound.N0.duration,self.soundpath)
63837
- self.radioqueue:SetDigit(1,ATIS.Sound.N1.filename,ATIS.Sound.N1.duration,self.soundpath)
63838
- self.radioqueue:SetDigit(2,ATIS.Sound.N2.filename,ATIS.Sound.N2.duration,self.soundpath)
63839
- self.radioqueue:SetDigit(3,ATIS.Sound.N3.filename,ATIS.Sound.N3.duration,self.soundpath)
63840
- self.radioqueue:SetDigit(4,ATIS.Sound.N4.filename,ATIS.Sound.N4.duration,self.soundpath)
63841
- self.radioqueue:SetDigit(5,ATIS.Sound.N5.filename,ATIS.Sound.N5.duration,self.soundpath)
63842
- self.radioqueue:SetDigit(6,ATIS.Sound.N6.filename,ATIS.Sound.N6.duration,self.soundpath)
63843
- self.radioqueue:SetDigit(7,ATIS.Sound.N7.filename,ATIS.Sound.N7.duration,self.soundpath)
63844
- self.radioqueue:SetDigit(8,ATIS.Sound.N8.filename,ATIS.Sound.N8.duration,self.soundpath)
63845
- self.radioqueue:SetDigit(9,ATIS.Sound.N9.filename,ATIS.Sound.N9.duration,self.soundpath)
64746
+ self.radioqueue:SetDigit(0,self.Sound.N0.filename,self.Sound.N0.duration,self.soundpath)
64747
+ self.radioqueue:SetDigit(1,self.Sound.N1.filename,self.Sound.N1.duration,self.soundpath)
64748
+ self.radioqueue:SetDigit(2,self.Sound.N2.filename,self.Sound.N2.duration,self.soundpath)
64749
+ self.radioqueue:SetDigit(3,self.Sound.N3.filename,self.Sound.N3.duration,self.soundpath)
64750
+ self.radioqueue:SetDigit(4,self.Sound.N4.filename,self.Sound.N4.duration,self.soundpath)
64751
+ self.radioqueue:SetDigit(5,self.Sound.N5.filename,self.Sound.N5.duration,self.soundpath)
64752
+ self.radioqueue:SetDigit(6,self.Sound.N6.filename,self.Sound.N6.duration,self.soundpath)
64753
+ self.radioqueue:SetDigit(7,self.Sound.N7.filename,self.Sound.N7.duration,self.soundpath)
64754
+ self.radioqueue:SetDigit(8,self.Sound.N8.filename,self.Sound.N8.duration,self.soundpath)
64755
+ self.radioqueue:SetDigit(9,self.Sound.N9.filename,self.Sound.N9.duration,self.soundpath)
63846
64756
  self.radioqueue:Start(1,0.1)
63847
64757
  end
63848
64758
  self:HandleEvent(EVENTS.BaseCaptured)
@@ -64044,7 +64954,35 @@ local cloudceil=clouds.base+clouds.thickness
64044
64954
  local clouddens=clouds.density
64045
64955
  local cloudspreset=clouds.preset or"Nothing"
64046
64956
  local precepitation=0
64047
- if cloudspreset:find("Preset10")then
64957
+ if cloudspreset:find("RainyPreset1")then
64958
+ clouddens=9
64959
+ if temperature>5 then
64960
+ precepitation=1
64961
+ else
64962
+ precepitation=3
64963
+ end
64964
+ elseif cloudspreset:find("RainyPreset2")then
64965
+ clouddens=9
64966
+ if temperature>5 then
64967
+ precepitation=1
64968
+ else
64969
+ precepitation=3
64970
+ end
64971
+ elseif cloudspreset:find("RainyPreset3")then
64972
+ clouddens=9
64973
+ if temperature>5 then
64974
+ precepitation=1
64975
+ else
64976
+ precepitation=3
64977
+ end
64978
+ elseif cloudspreset:find("RainyPreset")then
64979
+ clouddens=9
64980
+ if temperature>5 then
64981
+ precepitation=1
64982
+ else
64983
+ precepitation=3
64984
+ end
64985
+ elseif cloudspreset:find("Preset10")then
64048
64986
  clouddens=4
64049
64987
  elseif cloudspreset:find("Preset11")then
64050
64988
  clouddens=4
@@ -64098,34 +65036,8 @@ elseif cloudspreset:find("Preset8")then
64098
65036
  clouddens=4
64099
65037
  elseif cloudspreset:find("Preset9")then
64100
65038
  clouddens=4
64101
- elseif cloudspreset:find("RainyPreset")then
64102
- clouddens=9
64103
- if temperature>5 then
64104
- precepitation=1
64105
65039
  else
64106
- precepitation=3
64107
- end
64108
- elseif cloudspreset:find("RainyPreset1")then
64109
- clouddens=9
64110
- if temperature>5 then
64111
- precepitation=1
64112
- else
64113
- precepitation=3
64114
- end
64115
- elseif cloudspreset:find("RainyPreset2")then
64116
- clouddens=9
64117
- if temperature>5 then
64118
- precepitation=1
64119
- else
64120
- precepitation=3
64121
- end
64122
- elseif cloudspreset:find("RainyPreset3")then
64123
- clouddens=9
64124
- if temperature>5 then
64125
- precepitation=1
64126
- else
64127
- precepitation=3
64128
- end
65040
+ self:E(string.format("WARNING! Unknown weather preset: %s",tostring(cloudspreset)))
64129
65041
  end
64130
65042
  local CLOUDBASE=string.format("%d",UTILS.MetersToFeet(cloudbase))
64131
65043
  local CLOUDCEIL=string.format("%d",UTILS.MetersToFeet(cloudceil))
@@ -64140,25 +65052,25 @@ CLOUDBASE1000,CLOUDBASE0100=self:_GetThousandsAndHundreds(cloudbase)
64140
65052
  CLOUDCEIL1000,CLOUDCEIL0100=self:_GetThousandsAndHundreds(cloudceil)
64141
65053
  end
64142
65054
  local CloudCover={}
64143
- CloudCover=ATIS.Sound.CloudsNotAvailable
65055
+ CloudCover=self.Sound.CloudsNotAvailable
64144
65056
  local CLOUDSsub=self.gettext:GetEntry("NOCLOUDINFO",self.locale)
64145
65057
  if static then
64146
65058
  if clouddens>=9 then
64147
- CloudCover=ATIS.Sound.CloudsOvercast
65059
+ CloudCover=self.Sound.CloudsOvercast
64148
65060
  CLOUDSsub=self.gettext:GetEntry("OVERCAST",self.locale)
64149
65061
  elseif clouddens>=7 then
64150
- CloudCover=ATIS.Sound.CloudsBroken
65062
+ CloudCover=self.Sound.CloudsBroken
64151
65063
  CLOUDSsub=self.gettext:GetEntry("BROKEN",self.locale)
64152
65064
  elseif clouddens>=4 then
64153
- CloudCover=ATIS.Sound.CloudsScattered
65065
+ CloudCover=self.Sound.CloudsScattered
64154
65066
  CLOUDSsub=self.gettext:GetEntry("SCATTERED",self.locale)
64155
65067
  elseif clouddens>=1 then
64156
- CloudCover=ATIS.Sound.CloudsFew
65068
+ CloudCover=self.Sound.CloudsFew
64157
65069
  CLOUDSsub=self.gettext:GetEntry("FEWCLOUDS",self.locale)
64158
65070
  else
64159
65071
  CLOUDBASE=nil
64160
65072
  CLOUDCEIL=nil
64161
- CloudCover=ATIS.Sound.CloudsNo
65073
+ CloudCover=self.Sound.CloudsNo
64162
65074
  CLOUDSsub=self.gettext:GetEntry("NOCLOUDS",self.locale)
64163
65075
  end
64164
65076
  end
@@ -64171,38 +65083,38 @@ then
64171
65083
  subtitle=subtitle.." "..self.gettext:GetEntry("AIRPORT",self.locale)
64172
65084
  end
64173
65085
  if not self.useSRS then
64174
- self.radioqueue:NewTransmission(string.format("%s/%s.ogg",self.theatre,self.airbasename),3.0,self.soundpath,nil,nil,subtitle,self.subduration)
65086
+ self.radioqueue:NewTransmission(string.format("%s.ogg",self.airbasename),3.0,self.soundpathAirports,nil,nil,subtitle,self.subduration)
64175
65087
  end
64176
65088
  local alltext=subtitle
64177
65089
  local information=self.gettext:GetEntry("INFORMATION",self.locale)
64178
65090
  subtitle=string.format("%s %s",information,NATO)
64179
65091
  local _INFORMATION=subtitle
64180
65092
  if not self.useSRS then
64181
- self:Transmission(ATIS.Sound.Information,0.5,subtitle)
64182
- self.radioqueue:NewTransmission(string.format("NATO Alphabet/%s.ogg",NATO),0.75,self.soundpath)
65093
+ self:Transmission(self.Sound.Information,0.5,subtitle)
65094
+ self.radioqueue:NewTransmission(string.format("%s.ogg",NATO),0.75,self.soundpathNato)
64183
65095
  end
64184
65096
  alltext=alltext..";\n"..subtitle
64185
65097
  subtitle=string.format("%s Zulu",ZULU)
64186
65098
  if not self.useSRS then
64187
65099
  self.radioqueue:Number2Transmission(ZULU,nil,0.5)
64188
- self:Transmission(ATIS.Sound.Zulu,0.2,subtitle)
65100
+ self:Transmission(self.Sound.Zulu,0.2,subtitle)
64189
65101
  end
64190
65102
  alltext=alltext..";\n"..subtitle
64191
65103
  if not self.zulutimeonly then
64192
65104
  local sunrise=self.gettext:GetEntry("SUNRISEAT",self.locale)
64193
65105
  subtitle=string.format(sunrise,SUNRISE)
64194
65106
  if not self.useSRS then
64195
- self:Transmission(ATIS.Sound.SunriseAt,0.5,subtitle)
65107
+ self:Transmission(self.Sound.SunriseAt,0.5,subtitle)
64196
65108
  self.radioqueue:Number2Transmission(SUNRISE,nil,0.2)
64197
- self:Transmission(ATIS.Sound.TimeLocal,0.2)
65109
+ self:Transmission(self.Sound.TimeLocal,0.2)
64198
65110
  end
64199
65111
  alltext=alltext..";\n"..subtitle
64200
65112
  local sunset=self.gettext:GetEntry("SUNSETAT",self.locale)
64201
65113
  subtitle=string.format(sunset,SUNSET)
64202
65114
  if not self.useSRS then
64203
- self:Transmission(ATIS.Sound.SunsetAt,0.5,subtitle)
65115
+ self:Transmission(self.Sound.SunsetAt,0.5,subtitle)
64204
65116
  self.radioqueue:Number2Transmission(SUNSET,nil,0.5)
64205
- self:Transmission(ATIS.Sound.TimeLocal,0.2)
65117
+ self:Transmission(self.Sound.TimeLocal,0.2)
64206
65118
  end
64207
65119
  alltext=alltext..";\n"..subtitle
64208
65120
  end
@@ -64221,17 +65133,17 @@ subtitle=subtitle..", "..self.gettext:GetEntry("GUSTING",self.locale)
64221
65133
  end
64222
65134
  local _WIND=subtitle
64223
65135
  if not self.useSRS then
64224
- self:Transmission(ATIS.Sound.WindFrom,1.0,subtitle)
65136
+ self:Transmission(self.Sound.WindFrom,1.0,subtitle)
64225
65137
  self.radioqueue:Number2Transmission(WINDFROM)
64226
- self:Transmission(ATIS.Sound.At,0.2)
65138
+ self:Transmission(self.Sound.At,0.2)
64227
65139
  self.radioqueue:Number2Transmission(WINDSPEED)
64228
65140
  if self.metric then
64229
- self:Transmission(ATIS.Sound.MetersPerSecond,0.2)
65141
+ self:Transmission(self.Sound.MetersPerSecond,0.2)
64230
65142
  else
64231
- self:Transmission(ATIS.Sound.Knots,0.2)
65143
+ self:Transmission(self.Sound.Knots,0.2)
64232
65144
  end
64233
65145
  if turbulence>0 then
64234
- self:Transmission(ATIS.Sound.Gusting,0.2)
65146
+ self:Transmission(self.Sound.Gusting,0.2)
64235
65147
  end
64236
65148
  end
64237
65149
  alltext=alltext..";\n"..subtitle
@@ -64243,12 +65155,12 @@ local visi=self.gettext:GetEntry("VISISM",self.locale)
64243
65155
  subtitle=string.format(visi,VISIBILITY)
64244
65156
  end
64245
65157
  if not self.useSRS then
64246
- self:Transmission(ATIS.Sound.Visibilty,1.0,subtitle)
65158
+ self:Transmission(self.Sound.Visibilty,1.0,subtitle)
64247
65159
  self.radioqueue:Number2Transmission(VISIBILITY)
64248
65160
  if self.metric then
64249
- self:Transmission(ATIS.Sound.Kilometers,0.2)
65161
+ self:Transmission(self.Sound.Kilometers,0.2)
64250
65162
  else
64251
- self:Transmission(ATIS.Sound.StatuteMiles,0.2)
65163
+ self:Transmission(self.Sound.StatuteMiles,0.2)
64252
65164
  end
64253
65165
  end
64254
65166
  alltext=alltext..";\n"..subtitle
@@ -64289,21 +65201,21 @@ if wp then
64289
65201
  local phenos=self.gettext:GetEntry("PHENOMENA",self.locale)
64290
65202
  subtitle=string.format("%s: %s",phenos,wpsub)
64291
65203
  if not self.useSRS then
64292
- self:Transmission(ATIS.Sound.WeatherPhenomena,1.0,subtitle)
65204
+ self:Transmission(self.Sound.WeatherPhenomena,1.0,subtitle)
64293
65205
  if precepitation==1 then
64294
- self:Transmission(ATIS.Sound.Rain,0.5)
65206
+ self:Transmission(self.Sound.Rain,0.5)
64295
65207
  elseif precepitation==2 then
64296
- self:Transmission(ATIS.Sound.ThunderStorm,0.5)
65208
+ self:Transmission(self.Sound.ThunderStorm,0.5)
64297
65209
  elseif precepitation==3 then
64298
- self:Transmission(ATIS.Sound.Snow,0.5)
65210
+ self:Transmission(self.Sound.Snow,0.5)
64299
65211
  elseif precepitation==4 then
64300
- self:Transmission(ATIS.Sound.SnowStorm,0.5)
65212
+ self:Transmission(self.Sound.SnowStorm,0.5)
64301
65213
  end
64302
65214
  if fog then
64303
- self:Transmission(ATIS.Sound.Fog,0.5)
65215
+ self:Transmission(self.Sound.Fog,0.5)
64304
65216
  end
64305
65217
  if dust then
64306
- self:Transmission(ATIS.Sound.Dust,0.5)
65218
+ self:Transmission(self.Sound.Dust,0.5)
64307
65219
  end
64308
65220
  end
64309
65221
  alltext=alltext..";\n"..subtitle
@@ -64322,28 +65234,28 @@ local cloudbase=self.gettext:GetEntry("CLOUDBASEFT",self.locale)
64322
65234
  subtitle=string.format(cloudbase,cbase,cceil)
64323
65235
  end
64324
65236
  if not self.useSRS then
64325
- self:Transmission(ATIS.Sound.CloudBase,1.0,subtitle)
65237
+ self:Transmission(self.Sound.CloudBase,1.0,subtitle)
64326
65238
  if tonumber(CLOUDBASE1000)>0 then
64327
65239
  self.radioqueue:Number2Transmission(CLOUDBASE1000)
64328
- self:Transmission(ATIS.Sound.Thousand,0.1)
65240
+ self:Transmission(self.Sound.Thousand,0.1)
64329
65241
  end
64330
65242
  if tonumber(CLOUDBASE0100)>0 then
64331
65243
  self.radioqueue:Number2Transmission(CLOUDBASE0100)
64332
- self:Transmission(ATIS.Sound.Hundred,0.1)
65244
+ self:Transmission(self.Sound.Hundred,0.1)
64333
65245
  end
64334
- self:Transmission(ATIS.Sound.CloudCeiling,0.5)
65246
+ self:Transmission(self.Sound.CloudCeiling,0.5)
64335
65247
  if tonumber(CLOUDCEIL1000)>0 then
64336
65248
  self.radioqueue:Number2Transmission(CLOUDCEIL1000)
64337
- self:Transmission(ATIS.Sound.Thousand,0.1)
65249
+ self:Transmission(self.Sound.Thousand,0.1)
64338
65250
  end
64339
65251
  if tonumber(CLOUDCEIL0100)>0 then
64340
65252
  self.radioqueue:Number2Transmission(CLOUDCEIL0100)
64341
- self:Transmission(ATIS.Sound.Hundred,0.1)
65253
+ self:Transmission(self.Sound.Hundred,0.1)
64342
65254
  end
64343
65255
  if self.metric then
64344
- self:Transmission(ATIS.Sound.Meters,0.1)
65256
+ self:Transmission(self.Sound.Meters,0.1)
64345
65257
  else
64346
- self:Transmission(ATIS.Sound.Feet,0.1)
65258
+ self:Transmission(self.Sound.Feet,0.1)
64347
65259
  end
64348
65260
  end
64349
65261
  end
@@ -64365,15 +65277,15 @@ end
64365
65277
  end
64366
65278
  local _TEMPERATURE=subtitle
64367
65279
  if not self.useSRS then
64368
- self:Transmission(ATIS.Sound.Temperature,1.0,subtitle)
65280
+ self:Transmission(self.Sound.Temperature,1.0,subtitle)
64369
65281
  if temperature<0 then
64370
- self:Transmission(ATIS.Sound.Minus,0.2)
65282
+ self:Transmission(self.Sound.Minus,0.2)
64371
65283
  end
64372
65284
  self.radioqueue:Number2Transmission(TEMPERATURE)
64373
65285
  if self.TDegF then
64374
- self:Transmission(ATIS.Sound.DegreesFahrenheit,0.2)
65286
+ self:Transmission(self.Sound.DegreesFahrenheit,0.2)
64375
65287
  else
64376
- self:Transmission(ATIS.Sound.DegreesCelsius,0.2)
65288
+ self:Transmission(self.Sound.DegreesCelsius,0.2)
64377
65289
  end
64378
65290
  end
64379
65291
  alltext=alltext..";\n"..subtitle
@@ -64393,15 +65305,15 @@ end
64393
65305
  end
64394
65306
  local _DEWPOINT=subtitle
64395
65307
  if not self.useSRS then
64396
- self:Transmission(ATIS.Sound.DewPoint,1.0,subtitle)
65308
+ self:Transmission(self.Sound.DewPoint,1.0,subtitle)
64397
65309
  if dewpoint<0 then
64398
- self:Transmission(ATIS.Sound.Minus,0.2)
65310
+ self:Transmission(self.Sound.Minus,0.2)
64399
65311
  end
64400
65312
  self.radioqueue:Number2Transmission(DEWPOINT)
64401
65313
  if self.TDegF then
64402
- self:Transmission(ATIS.Sound.DegreesFahrenheit,0.2)
65314
+ self:Transmission(self.Sound.DegreesFahrenheit,0.2)
64403
65315
  else
64404
- self:Transmission(ATIS.Sound.DegreesCelsius,0.2)
65316
+ self:Transmission(self.Sound.DegreesCelsius,0.2)
64405
65317
  end
64406
65318
  end
64407
65319
  alltext=alltext..";\n"..subtitle
@@ -64436,30 +65348,30 @@ end
64436
65348
  end
64437
65349
  local _ALTIMETER=subtitle
64438
65350
  if not self.useSRS then
64439
- self:Transmission(ATIS.Sound.Altimeter,1.0,subtitle)
65351
+ self:Transmission(self.Sound.Altimeter,1.0,subtitle)
64440
65352
  if not self.qnhonly then
64441
- self:Transmission(ATIS.Sound.QNH,0.5)
65353
+ self:Transmission(self.Sound.QNH,0.5)
64442
65354
  end
64443
65355
  self.radioqueue:Number2Transmission(QNH[1])
64444
65356
  if ATIS.ICAOPhraseology[UTILS.GetDCSMap()]then
64445
- self:Transmission(ATIS.Sound.Decimal,0.2)
65357
+ self:Transmission(self.Sound.Decimal,0.2)
64446
65358
  end
64447
65359
  self.radioqueue:Number2Transmission(QNH[2])
64448
65360
  if not self.qnhonly then
64449
- self:Transmission(ATIS.Sound.QFE,0.75)
65361
+ self:Transmission(self.Sound.QFE,0.75)
64450
65362
  self.radioqueue:Number2Transmission(QFE[1])
64451
65363
  if ATIS.ICAOPhraseology[UTILS.GetDCSMap()]then
64452
- self:Transmission(ATIS.Sound.Decimal,0.2)
65364
+ self:Transmission(self.Sound.Decimal,0.2)
64453
65365
  end
64454
65366
  self.radioqueue:Number2Transmission(QFE[2])
64455
65367
  end
64456
65368
  if self.PmmHg then
64457
- self:Transmission(ATIS.Sound.MillimetersOfMercury,0.1)
65369
+ self:Transmission(self.Sound.MillimetersOfMercury,0.1)
64458
65370
  else
64459
65371
  if self.metric then
64460
- self:Transmission(ATIS.Sound.HectoPascal,0.1)
65372
+ self:Transmission(self.Sound.HectoPascal,0.1)
64461
65373
  else
64462
- self:Transmission(ATIS.Sound.InchesOfMercury,0.1)
65374
+ self:Transmission(self.Sound.InchesOfMercury,0.1)
64463
65375
  end
64464
65376
  end
64465
65377
  end
@@ -64467,7 +65379,7 @@ alltext=alltext..";\n"..subtitle
64467
65379
  local _RUNACT
64468
65380
  if not self.ATISforFARPs then
64469
65381
  local subtitle=""
64470
- if runwayLanding then
65382
+ if runwayLanding and runwayLanding~=runwayTakeoff then
64471
65383
  local actrun=self.gettext:GetEntry("ACTIVELANDING",self.locale)
64472
65384
  subtitle=string.format("%s %s",actrun,runwayLanding)
64473
65385
  if rwyLandingLeft==true then
@@ -64476,6 +65388,15 @@ elseif rwyLandingLeft==false then
64476
65388
  subtitle=subtitle.." "..self.gettext:GetEntry("RIGHT",self.locale)
64477
65389
  end
64478
65390
  alltext=alltext..";\n"..subtitle
65391
+ if not self.useSRS then
65392
+ self:Transmission(self.Sound.ActiveRunwayArrival,1.0,subtitle)
65393
+ self.radioqueue:Number2Transmission(runwayLanding)
65394
+ if rwyLandingLeft==true then
65395
+ self:Transmission(self.Sound.Left,0.2)
65396
+ elseif rwyLandingLeft==false then
65397
+ self:Transmission(self.Sound.Right,0.2)
65398
+ end
65399
+ end
64479
65400
  end
64480
65401
  if runwayTakeoff then
64481
65402
  local actrun=self.gettext:GetEntry("ACTIVERUN",self.locale)
@@ -64485,17 +65406,18 @@ subtitle=subtitle.." "..self.gettext:GetEntry("LEFT",self.locale)
64485
65406
  elseif rwyTakeoffLeft==false then
64486
65407
  subtitle=subtitle.." "..self.gettext:GetEntry("RIGHT",self.locale)
64487
65408
  end
64488
- end
64489
- _RUNACT=subtitle
65409
+ alltext=alltext..";\n"..subtitle
64490
65410
  if not self.useSRS then
64491
- self:Transmission(ATIS.Sound.ActiveRunway,1.0,subtitle)
64492
- self.radioqueue:Number2Transmission(runwayLanding)
64493
- if rwyLandingLeft==true then
64494
- self:Transmission(ATIS.Sound.Left,0.2)
64495
- elseif rwyLandingLeft==false then
64496
- self:Transmission(ATIS.Sound.Right,0.2)
65411
+ self:Transmission(self.Sound.ActiveRunwayDeparture,1.0,subtitle)
65412
+ self.radioqueue:Number2Transmission(runwayTakeoff)
65413
+ if rwyTakeoffLeft==true then
65414
+ self:Transmission(self.Sound.Left,0.2)
65415
+ elseif rwyTakeoffLeft==false then
65416
+ self:Transmission(self.Sound.Right,0.2)
65417
+ end
64497
65418
  end
64498
65419
  end
65420
+ _RUNACT=subtitle
64499
65421
  alltext=alltext..";\n"..subtitle
64500
65422
  if self.rwylength then
64501
65423
  local runact=self.airbase:GetActiveRunway(self.runwaym2t)
@@ -64514,19 +65436,19 @@ else
64514
65436
  subtitle=subtitle.." "..feet
64515
65437
  end
64516
65438
  if not self.useSRS then
64517
- self:Transmission(ATIS.Sound.RunwayLength,1.0,subtitle)
65439
+ self:Transmission(self.Sound.RunwayLength,1.0,subtitle)
64518
65440
  if tonumber(L1000)>0 then
64519
65441
  self.radioqueue:Number2Transmission(L1000)
64520
- self:Transmission(ATIS.Sound.Thousand,0.1)
65442
+ self:Transmission(self.Sound.Thousand,0.1)
64521
65443
  end
64522
65444
  if tonumber(L0100)>0 then
64523
65445
  self.radioqueue:Number2Transmission(L0100)
64524
- self:Transmission(ATIS.Sound.Hundred,0.1)
65446
+ self:Transmission(self.Sound.Hundred,0.1)
64525
65447
  end
64526
65448
  if self.metric then
64527
- self:Transmission(ATIS.Sound.Meters,0.1)
65449
+ self:Transmission(self.Sound.Meters,0.1)
64528
65450
  else
64529
- self:Transmission(ATIS.Sound.Feet,0.1)
65451
+ self:Transmission(self.Sound.Feet,0.1)
64530
65452
  end
64531
65453
  end
64532
65454
  alltext=alltext..";\n"..subtitle
@@ -64548,19 +65470,19 @@ else
64548
65470
  subtitle=subtitle.." "..feet
64549
65471
  end
64550
65472
  if not self.useSRS then
64551
- self:Transmission(ATIS.Sound.Elevation,1.0,subtitle)
65473
+ self:Transmission(self.Sound.Elevation,1.0,subtitle)
64552
65474
  if tonumber(L1000)>0 then
64553
65475
  self.radioqueue:Number2Transmission(L1000)
64554
- self:Transmission(ATIS.Sound.Thousand,0.1)
65476
+ self:Transmission(self.Sound.Thousand,0.1)
64555
65477
  end
64556
65478
  if tonumber(L0100)>0 then
64557
65479
  self.radioqueue:Number2Transmission(L0100)
64558
- self:Transmission(ATIS.Sound.Hundred,0.1)
65480
+ self:Transmission(self.Sound.Hundred,0.1)
64559
65481
  end
64560
65482
  if self.metric then
64561
- self:Transmission(ATIS.Sound.Meters,0.1)
65483
+ self:Transmission(self.Sound.Meters,0.1)
64562
65484
  else
64563
- self:Transmission(ATIS.Sound.Feet,0.1)
65485
+ self:Transmission(self.Sound.Feet,0.1)
64564
65486
  end
64565
65487
  end
64566
65488
  alltext=alltext..";\n"..subtitle
@@ -64576,16 +65498,16 @@ end
64576
65498
  local twrfrq=self.gettext:GetEntry("TOWERFREQ",self.locale)
64577
65499
  subtitle=string.format("%s %s",twrfrq,freqs)
64578
65500
  if not self.useSRS then
64579
- self:Transmission(ATIS.Sound.TowerFrequency,1.0,subtitle)
65501
+ self:Transmission(self.Sound.TowerFrequency,1.0,subtitle)
64580
65502
  for _,freq in pairs(self.towerfrequency)do
64581
65503
  local f=string.format("%.3f",freq)
64582
65504
  f=UTILS.Split(f,".")
64583
65505
  self.radioqueue:Number2Transmission(f[1],nil,0.5)
64584
65506
  if tonumber(f[2])>0 then
64585
- self:Transmission(ATIS.Sound.Decimal,0.2)
65507
+ self:Transmission(self.Sound.Decimal,0.2)
64586
65508
  self.radioqueue:Number2Transmission(f[2])
64587
65509
  end
64588
- self:Transmission(ATIS.Sound.MegaHertz,0.2)
65510
+ self:Transmission(self.Sound.MegaHertz,0.2)
64589
65511
  end
64590
65512
  end
64591
65513
  alltext=alltext..";\n"..subtitle
@@ -64595,15 +65517,15 @@ if ils then
64595
65517
  local ilstxt=self.gettext:GetEntry("ILSFREQ",self.locale)
64596
65518
  subtitle=string.format("%s %.2f MHz",ilstxt,ils.frequency)
64597
65519
  if not self.useSRS then
64598
- self:Transmission(ATIS.Sound.ILSFrequency,1.0,subtitle)
65520
+ self:Transmission(self.Sound.ILSFrequency,1.0,subtitle)
64599
65521
  local f=string.format("%.2f",ils.frequency)
64600
65522
  f=UTILS.Split(f,".")
64601
65523
  self.radioqueue:Number2Transmission(f[1],nil,0.5)
64602
65524
  if tonumber(f[2])>0 then
64603
- self:Transmission(ATIS.Sound.Decimal,0.2)
65525
+ self:Transmission(self.Sound.Decimal,0.2)
64604
65526
  self.radioqueue:Number2Transmission(f[2])
64605
65527
  end
64606
- self:Transmission(ATIS.Sound.MegaHertz,0.2)
65528
+ self:Transmission(self.Sound.MegaHertz,0.2)
64607
65529
  end
64608
65530
  alltext=alltext..";\n"..subtitle
64609
65531
  end
@@ -64612,15 +65534,15 @@ if ndb then
64612
65534
  local ndbtxt=self.gettext:GetEntry("OUTERNDB",self.locale)
64613
65535
  subtitle=string.format("%s %.2f MHz",ndbtxt,ndb.frequency)
64614
65536
  if not self.useSRS then
64615
- self:Transmission(ATIS.Sound.OuterNDBFrequency,1.0,subtitle)
65537
+ self:Transmission(self.Sound.OuterNDBFrequency,1.0,subtitle)
64616
65538
  local f=string.format("%.2f",ndb.frequency)
64617
65539
  f=UTILS.Split(f,".")
64618
65540
  self.radioqueue:Number2Transmission(f[1],nil,0.5)
64619
65541
  if tonumber(f[2])>0 then
64620
- self:Transmission(ATIS.Sound.Decimal,0.2)
65542
+ self:Transmission(self.Sound.Decimal,0.2)
64621
65543
  self.radioqueue:Number2Transmission(f[2])
64622
65544
  end
64623
- self:Transmission(ATIS.Sound.MegaHertz,0.2)
65545
+ self:Transmission(self.Sound.MegaHertz,0.2)
64624
65546
  end
64625
65547
  alltext=alltext..";\n"..subtitle
64626
65548
  end
@@ -64629,15 +65551,15 @@ if ndb then
64629
65551
  local ndbtxt=self.gettext:GetEntry("INNERNDB",self.locale)
64630
65552
  subtitle=string.format("%s %.2f MHz",ndbtxt,ndb.frequency)
64631
65553
  if not self.useSRS then
64632
- self:Transmission(ATIS.Sound.InnerNDBFrequency,1.0,subtitle)
65554
+ self:Transmission(self.Sound.InnerNDBFrequency,1.0,subtitle)
64633
65555
  local f=string.format("%.2f",ndb.frequency)
64634
65556
  f=UTILS.Split(f,".")
64635
65557
  self.radioqueue:Number2Transmission(f[1],nil,0.5)
64636
65558
  if tonumber(f[2])>0 then
64637
- self:Transmission(ATIS.Sound.Decimal,0.2)
65559
+ self:Transmission(self.Sound.Decimal,0.2)
64638
65560
  self.radioqueue:Number2Transmission(f[2])
64639
65561
  end
64640
- self:Transmission(ATIS.Sound.MegaHertz,0.2)
65562
+ self:Transmission(self.Sound.MegaHertz,0.2)
64641
65563
  end
64642
65564
  alltext=alltext..";\n"..subtitle
64643
65565
  end
@@ -64649,15 +65571,15 @@ if self.useSRS then
64649
65571
  subtitle=string.format("%s %.2f MHz",vorttstxt,self.vor)
64650
65572
  end
64651
65573
  if not self.useSRS then
64652
- self:Transmission(ATIS.Sound.VORFrequency,1.0,subtitle)
65574
+ self:Transmission(self.Sound.VORFrequency,1.0,subtitle)
64653
65575
  local f=string.format("%.2f",self.vor)
64654
65576
  f=UTILS.Split(f,".")
64655
65577
  self.radioqueue:Number2Transmission(f[1],nil,0.5)
64656
65578
  if tonumber(f[2])>0 then
64657
- self:Transmission(ATIS.Sound.Decimal,0.2)
65579
+ self:Transmission(self.Sound.Decimal,0.2)
64658
65580
  self.radioqueue:Number2Transmission(f[2])
64659
65581
  end
64660
- self:Transmission(ATIS.Sound.MegaHertz,0.2)
65582
+ self:Transmission(self.Sound.MegaHertz,0.2)
64661
65583
  end
64662
65584
  alltext=alltext..";\n"..subtitle
64663
65585
  end
@@ -64665,9 +65587,9 @@ if self.tacan then
64665
65587
  local tactxt=self.gettext:GetEntry("TACANCH",self.locale)
64666
65588
  subtitle=string.format(tactxt,self.tacan)
64667
65589
  if not self.useSRS then
64668
- self:Transmission(ATIS.Sound.TACANChannel,1.0,subtitle)
65590
+ self:Transmission(self.Sound.TACANChannel,1.0,subtitle)
64669
65591
  self.radioqueue:Number2Transmission(tostring(self.tacan),nil,0.2)
64670
- self.radioqueue:NewTransmission("NATO Alphabet/Xray.ogg",0.75,self.soundpath,nil,0.2)
65592
+ self.radioqueue:NewTransmission("Xray.ogg",0.75,self.soundpathNato,nil,0.2)
64671
65593
  end
64672
65594
  alltext=alltext..";\n"..subtitle
64673
65595
  end
@@ -64675,7 +65597,7 @@ if self.rsbn then
64675
65597
  local rsbntxt=self.gettext:GetEntry("RSBNCH",self.locale)
64676
65598
  subtitle=string.format("%s %d",rsbntxt,self.rsbn)
64677
65599
  if not self.useSRS then
64678
- self:Transmission(ATIS.Sound.RSBNChannel,1.0,subtitle)
65600
+ self:Transmission(self.Sound.RSBNChannel,1.0,subtitle)
64679
65601
  self.radioqueue:Number2Transmission(tostring(self.rsbn),nil,0.2)
64680
65602
  end
64681
65603
  alltext=alltext..";\n"..subtitle
@@ -64685,7 +65607,7 @@ if ndb then
64685
65607
  local prmtxt=self.gettext:GetEntry("PRMGCH",self.locale)
64686
65608
  subtitle=string.format("%s %d",prmtxt,ndb.frequency)
64687
65609
  if not self.useSRS then
64688
- self:Transmission(ATIS.Sound.PRMGChannel,1.0,subtitle)
65610
+ self:Transmission(self.Sound.PRMGChannel,1.0,subtitle)
64689
65611
  self.radioqueue:Number2Transmission(tostring(ndb.frequency),nil,0.5)
64690
65612
  end
64691
65613
  alltext=alltext..";\n"..subtitle
@@ -64696,8 +65618,8 @@ end
64696
65618
  local advtxt=self.gettext:GetEntry("ADVISE",self.locale)
64697
65619
  subtitle=string.format("%s %s",advtxt,NATO)
64698
65620
  if not self.useSRS then
64699
- self:Transmission(ATIS.Sound.AdviceOnInitial,0.5,subtitle)
64700
- self.radioqueue:NewTransmission(string.format("NATO Alphabet/%s.ogg",NATO),0.75,self.soundpath)
65621
+ self:Transmission(self.Sound.AdviceOnInitial,0.5,subtitle)
65622
+ self.radioqueue:NewTransmission(string.format("%s.ogg",NATO),0.75,self.soundpathNato)
64701
65623
  end
64702
65624
  alltext=alltext..";\n"..subtitle
64703
65625
  self:Report(alltext)
@@ -64734,7 +65656,7 @@ text=string.gsub(text,"(%d+)(%.)(%d+)","%1 "..delimiter.." %3")
64734
65656
  end
64735
65657
  local text=string.gsub(text,";"," . ")
64736
65658
  self:T("SRS TTS: "..text)
64737
- local duration=STTS.getSpeechTime(text,0.95)
65659
+ local duration=MSRS.getSpeechTime(text,0.95)
64738
65660
  self.msrsQ:NewTransmission(text,duration,self.msrs,nil,2)
64739
65661
  self.SRSText=text
64740
65662
  end
@@ -64917,12 +65839,20 @@ self.Stock=Stock or nil
64917
65839
  self.Mark=nil
64918
65840
  self.Subcategory=Subcategory or"Other"
64919
65841
  self.DontShowInMenu=DontShowInMenu or false
65842
+ self.ResourceMap=nil
64920
65843
  if type(Location)=="string"then
64921
65844
  Location=ZONE:New(Location)
64922
65845
  end
64923
65846
  self.Location=Location
64924
65847
  return self
64925
65848
  end
65849
+ function CTLD_CARGO:SetStaticResourceMap(ResourceMap)
65850
+ self.ResourceMap=ResourceMap
65851
+ return self
65852
+ end
65853
+ function CTLD_CARGO:GetStaticResourceMap()
65854
+ return self.ResourceMap
65855
+ end
64926
65856
  function CTLD_CARGO:GetLocation()
64927
65857
  return self.Location
64928
65858
  end
@@ -65240,8 +66170,10 @@ CTLD.UnitTypeCapabilities={
65240
66170
  ["AH-64D_BLK_II"]={type="AH-64D_BLK_II",crates=false,troops=true,cratelimit=0,trooplimit=2,length=17,cargoweightlimit=200},
65241
66171
  ["Bronco-OV-10A"]={type="Bronco-OV-10A",crates=false,troops=true,cratelimit=0,trooplimit=5,length=13,cargoweightlimit=1450},
65242
66172
  ["OH-6A"]={type="OH-6A",crates=false,troops=true,cratelimit=0,trooplimit=4,length=7,cargoweightlimit=550},
66173
+ ["OH-58D"]={type="OH58D",crates=false,troops=false,cratelimit=0,trooplimit=0,length=14,cargoweightlimit=400},
66174
+ ["CH-47Fbl1"]={type="CH-47Fbl1",crates=true,troops=true,cratelimit=4,trooplimit=31,length=20,cargoweightlimit=8000},
65243
66175
  }
65244
- CTLD.version="1.0.52"
66176
+ CTLD.version="1.0.58"
65245
66177
  function CTLD:New(Coalition,Prefixes,Alias)
65246
66178
  local self=BASE:Inherit(self,FSM:New())
65247
66179
  BASE:T({Coalition,Prefixes,Alias})
@@ -65364,6 +66296,7 @@ self.subcatsTroop={}
65364
66296
  self.nobuildinloadzones=true
65365
66297
  self.movecratesbeforebuild=true
65366
66298
  self.surfacetypes={land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.RUNWAY,land.SurfaceType.SHALLOW_WATER}
66299
+ self.enableChinookGCLoading=true
65367
66300
  local AliaS=string.gsub(self.alias," ","_")
65368
66301
  self.filename=string.format("CTLD_%s_Persist.csv",AliaS)
65369
66302
  self.allowcratepickupagain=true
@@ -65431,7 +66364,7 @@ self.PlayerTaskQueue:Push(PlayerTask,PlayerTask.PlayerTaskNr)
65431
66364
  return self
65432
66365
  end
65433
66366
  function CTLD:_EventHandler(EventData)
65434
- self:T(string.format("%s Event = %d",self.lid,EventData.id))
66367
+ self:I(string.format("%s Event = %d",self.lid,EventData.id))
65435
66368
  local event=EventData
65436
66369
  if event.id==EVENTS.PlayerEnterAircraft or event.id==EVENTS.PlayerEnterUnit then
65437
66370
  local _coalition=event.IniCoalition
@@ -65453,11 +66386,29 @@ self.Loaded_Cargo[unitname]=nil
65453
66386
  self:_RefreshF10Menus()
65454
66387
  end
65455
66388
  return
65456
- elseif event.id==EVENTS.PlayerLeaveUnit then
66389
+ elseif event.id==EVENTS.PlayerLeaveUnit or event.id==EVENTS.UnitLost then
65457
66390
  local unitname=event.IniUnitName or"none"
65458
66391
  self.CtldUnits[unitname]=nil
65459
66392
  self.Loaded_Cargo[unitname]=nil
65460
66393
  self.MenusDone[unitname]=nil
66394
+ elseif event.id==EVENTS.Birth and event.IniObjectCategory==6 and string.match(event.IniUnitName,".+|%d%d:%d%d|PKG%d+")then
66395
+ local function RegisterDynamicCargo()
66396
+ local static=_DATABASE:AddStatic(event.IniUnitName)
66397
+ if static then
66398
+ static.DCSCargoObject=event.IniDCSUnit
66399
+ local Mass=event.IniDCSUnit:getCargoWeight()
66400
+ local country=event.IniDCSUnit:getCountry()
66401
+ local template=_DATABASE:_GetGenericStaticCargoGroupTemplate(event.IniUnitName,event.IniTypeName,Mass,event.IniCoalition,country)
66402
+ _DATABASE:_RegisterStaticTemplate(template,event.IniCoalition,"static",country)
66403
+ self:I("**** Ground crew created static cargo added: "..event.IniUnitName.." | Weight in kgs: "..Mass)
66404
+ local cargotype=self:AddStaticsCargo(event.IniUnitName,Mass,1,nil,true)
66405
+ self.CrateCounter=self.CrateCounter+1
66406
+ self.Spawned_Crates[self.CrateCounter]=static
66407
+ cargotype.Positionable=static
66408
+ table.insert(self.Spawned_Cargo,cargotype)
66409
+ end
66410
+ end
66411
+ self:ScheduleOnce(0.5,RegisterDynamicCargo)
65461
66412
  end
65462
66413
  return self
65463
66414
  end
@@ -65888,6 +66839,7 @@ self:_SendMessage("There are enough crates nearby already! Take care of those fi
65888
66839
  return self
65889
66840
  end
65890
66841
  local IsHerc=self:IsHercules(Unit)
66842
+ local IsHook=self:IsHook(Unit)
65891
66843
  local cargotype=Cargo
65892
66844
  local number=number or cargotype:GetCratesNeeded()
65893
66845
  local cratesneeded=cargotype:GetCratesNeeded()
@@ -65908,7 +66860,7 @@ local cratedistance=0
65908
66860
  local rheading=0
65909
66861
  local angleOffNose=0
65910
66862
  local addon=0
65911
- if IsHerc then
66863
+ if IsHerc or IsHook then
65912
66864
  addon=180
65913
66865
  end
65914
66866
  for i=1,number do
@@ -65952,17 +66904,25 @@ local dist=shipcoord:Get2DDistance(unitcoord)
65952
66904
  dist=dist-(20+math.random(1,10))
65953
66905
  local width=width/2
65954
66906
  local Offy=math.random(-width,width)
65955
- self.Spawned_Crates[self.CrateCounter]=SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry)
66907
+ local spawnstatic=SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry)
65956
66908
  :InitCargoMass(cgomass)
65957
66909
  :InitCargo(self.enableslingload)
65958
66910
  :InitLinkToUnit(Ship,dist,Offy,0)
65959
- :Spawn(270,cratealias)
66911
+ if isstatic then
66912
+ local map=cargotype:GetStaticResourceMap()
66913
+ spawnstatic.TemplateStaticUnit.resourcePayload=map
66914
+ end
66915
+ self.Spawned_Crates[self.CrateCounter]=spawnstatic:Spawn(270,cratealias)
65960
66916
  else
65961
- self.Spawned_Crates[self.CrateCounter]=SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry)
66917
+ local spawnstatic=SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry)
65962
66918
  :InitCoordinate(cratecoord)
65963
66919
  :InitCargoMass(cgomass)
65964
66920
  :InitCargo(self.enableslingload)
65965
- :Spawn(270,cratealias)
66921
+ if isstatic then
66922
+ local map=cargotype:GetStaticResourceMap()
66923
+ spawnstatic.TemplateStaticUnit.resourcePayload=map
66924
+ end
66925
+ self.Spawned_Crates[self.CrateCounter]=spawnstatic:Spawn(270,cratealias)
65966
66926
  end
65967
66927
  local templ=cargotype:GetTemplates()
65968
66928
  local sorte=cargotype:GetType()
@@ -65971,9 +66931,13 @@ self.CargoCounter=self.CargoCounter+1
65971
66931
  local realcargo=nil
65972
66932
  if drop then
65973
66933
  realcargo=CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,true,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],true,cargotype.PerCrateMass,nil,subcat)
66934
+ local map=cargotype:GetStaticResourceMap()
66935
+ realcargo:SetStaticResourceMap(map)
65974
66936
  table.insert(droppedcargo,realcargo)
65975
66937
  else
65976
66938
  realcargo=CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,false,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],false,cargotype.PerCrateMass,nil,subcat)
66939
+ local map=cargotype:GetStaticResourceMap()
66940
+ realcargo:SetStaticResourceMap(map)
65977
66941
  end
65978
66942
  table.insert(self.Spawned_Cargo,realcargo)
65979
66943
  end
@@ -66015,14 +66979,17 @@ if isstatic then
66015
66979
  basetype=cratetemplate
66016
66980
  end
66017
66981
  self.CrateCounter=self.CrateCounter+1
66018
- self.Spawned_Crates[self.CrateCounter]=SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry)
66982
+ local spawnstatic=SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry)
66019
66983
  :InitCargoMass(cgomass)
66020
66984
  :InitCargo(self.enableslingload)
66021
66985
  :InitCoordinate(cratecoord)
66022
- :Spawn(270,cratealias)
66986
+ if isstatic then
66987
+ local map=cargotype:GetStaticResourceMap()
66988
+ spawnstatic.TemplateStaticUnit.resourcePayload=map
66989
+ end
66990
+ self.Spawned_Crates[self.CrateCounter]=spawnstatic:Spawn(270,cratealias)
66023
66991
  local templ=cargotype:GetTemplates()
66024
66992
  local sorte=cargotype:GetType()
66025
- self.CargoCounter=self.CargoCounter+1
66026
66993
  cargotype.Positionable=self.Spawned_Crates[self.CrateCounter]
66027
66994
  table.insert(self.Spawned_Cargo,cargotype)
66028
66995
  return self
@@ -66036,8 +67003,8 @@ end
66036
67003
  function CTLD:_ListCratesNearby(_group,_unit)
66037
67004
  self:T(self.lid.." _ListCratesNearby")
66038
67005
  local finddist=self.CrateDistance or 35
66039
- local crates,number=self:_FindCratesNearby(_group,_unit,finddist,true)
66040
- if number>0 then
67006
+ local crates,number,loadedbygc,indexgc=self:_FindCratesNearby(_group,_unit,finddist,true)
67007
+ if number>0 or indexgc>0 then
66041
67008
  local text=REPORT:New("Crates Found Nearby:")
66042
67009
  text:Add("------------------------------------------------------------")
66043
67010
  for _,_entry in pairs(crates)do
@@ -66054,6 +67021,19 @@ if text:GetCount()==1 then
66054
67021
  text:Add(" N O N E")
66055
67022
  end
66056
67023
  text:Add("------------------------------------------------------------")
67024
+ if indexgc>0 then
67025
+ text:Add("Probably ground crew loaded (F8)")
67026
+ for _,_entry in pairs(loadedbygc)do
67027
+ local entry=_entry
67028
+ local name=entry:GetName()
67029
+ local dropped=entry:WasDropped()
67030
+ if dropped then
67031
+ text:Add(string.format("Dropped crate for %s, %dkg",name,entry.PerCrateMass))
67032
+ else
67033
+ text:Add(string.format("Crate for %s, %dkg",name,entry.PerCrateMass))
67034
+ end
67035
+ end
67036
+ end
66057
67037
  self:_SendMessage(text:Text(),30,true,_group)
66058
67038
  else
66059
67039
  self:_SendMessage(string.format("No (loadable) crates within %d meters!",finddist),10,false,_group)
@@ -66114,12 +67094,15 @@ local finddist=_dist
66114
67094
  local location=_group:GetCoordinate()
66115
67095
  local existingcrates=self.Spawned_Cargo
66116
67096
  local index=0
67097
+ local indexg=0
66117
67098
  local found={}
67099
+ local LoadedbyGC={}
66118
67100
  local loadedmass=0
66119
67101
  local unittype="none"
66120
67102
  local capabilities={}
66121
67103
  local maxmass=2000
66122
67104
  local maxloadable=2000
67105
+ local IsNoHook=not self:IsHook(_unit)
66123
67106
  if not _ignoreweight then
66124
67107
  maxloadable=self:_GetMaxLoadableMass(_unit)
66125
67108
  end
@@ -66127,20 +67110,46 @@ self:T(self.lid.." Max loadable mass: "..maxloadable)
66127
67110
  for _,_cargoobject in pairs(existingcrates)do
66128
67111
  local cargo=_cargoobject
66129
67112
  local static=cargo:GetPositionable()
66130
- local staticid=cargo:GetID()
66131
67113
  local weight=cargo:GetMass()
67114
+ local staticid=cargo:GetID()
66132
67115
  self:T(self.lid.." Found cargo mass: "..weight)
66133
- if static and static:IsAlive()then
66134
- local staticpos=static:GetCoordinate()
67116
+ local cargoalive=false
67117
+ local dcsunit=nil
67118
+ local dcsunitpos=nil
67119
+ if static and static.DCSCargoObject then
67120
+ dcsunit=Unit.getByName(static.StaticName)
67121
+ if dcsunit then
67122
+ cargoalive=dcsunit:isExist()~=nil and true or false
67123
+ end
67124
+ if cargoalive==true then
67125
+ local dcsvec3=dcsunit:getPoint()or dcsunit:getPosition().p or{x=0,y=0,z=0}
67126
+ self:T({dcsvec3=dcsunit:getPoint(),dcspos=dcsunit:getPosition().p})
67127
+ if dcsvec3 then
67128
+ dcsunitpos=COORDINATE:New(dcsvec3.x,dcsvec3.z,dcsvec3.y)
67129
+ end
67130
+ end
67131
+ end
67132
+ if static and(static:IsAlive()or cargoalive)then
67133
+ local staticpos=static:GetCoordinate()or dcsunitpos
67134
+ local landheight=staticpos:GetLandHeight()
67135
+ local agl=staticpos.y-landheight
67136
+ agl=UTILS.Round(agl,2)
67137
+ local GCloaded=agl>0 and true or false
67138
+ if IsNoHook==true then GCloaded=false end
66135
67139
  local distance=self:_GetDistance(location,staticpos)
66136
- if distance<=finddist and static and(weight<=maxloadable or _ignoreweight)then
67140
+ self:T({name=static:GetName(),IsNoHook=IsNoHook,agl=agl,GCloaded=GCloaded,distance=string.format("%.2f",distance or 0)})
67141
+ if(not GCloaded)and distance<=finddist and static and(weight<=maxloadable or _ignoreweight)then
66137
67142
  index=index+1
66138
67143
  table.insert(found,staticid,cargo)
66139
67144
  maxloadable=maxloadable-weight
66140
67145
  end
67146
+ if GCloaded==true and distance<10 and static then
67147
+ indexg=indexg+1
67148
+ table.insert(LoadedbyGC,staticid,cargo)
66141
67149
  end
66142
67150
  end
66143
- return found,index
67151
+ end
67152
+ return found,index,LoadedbyGC,indexg
66144
67153
  end
66145
67154
  function CTLD:_LoadCratesNearby(Group,Unit)
66146
67155
  self:T(self.lid.." _LoadCratesNearby")
@@ -66153,6 +67162,10 @@ local cancrates=capabilities.crates
66153
67162
  local cratelimit=capabilities.cratelimit
66154
67163
  local grounded=not self:IsUnitInAir(Unit)
66155
67164
  local canhoverload=self:CanHoverLoad(Unit)
67165
+ if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName())then
67166
+ self:_SendMessage("You need to open the door(s) to load cargo!",10,false,Group)
67167
+ if not self.debug then return self end
67168
+ end
66156
67169
  if not cancrates then
66157
67170
  self:_SendMessage("Sorry this chopper cannot carry crates!",10,false,Group)
66158
67171
  elseif self.forcehoverload and not canhoverload then
@@ -66294,7 +67307,9 @@ local cratelimit=capabilities.cratelimit
66294
67307
  local loadedcargo=self.Loaded_Cargo[unitname]or{}
66295
67308
  local loadedmass=self:_GetUnitCargoMass(Unit)
66296
67309
  local maxloadable=self:_GetMaxLoadableMass(Unit)
66297
- if self.Loaded_Cargo[unitname]then
67310
+ local finddist=self.CrateDistance or 35
67311
+ local _,_,loadedgc,loadedno=self:_FindCratesNearby(Group,Unit,finddist,true)
67312
+ if self.Loaded_Cargo[unitname]or loadedno>0 then
66298
67313
  local no_troops=loadedcargo.Troopsloaded or 0
66299
67314
  local no_crates=loadedcargo.Cratesloaded or 0
66300
67315
  local cargotable=loadedcargo.Cargo or{}
@@ -66316,7 +67331,7 @@ end
66316
67331
  report:Add("------------------------------------------------------------")
66317
67332
  report:Add(" -- CRATES --")
66318
67333
  local cratecount=0
66319
- for _,_cargo in pairs(cargotable)do
67334
+ for _,_cargo in pairs(cargotable or{})do
66320
67335
  local cargo=_cargo
66321
67336
  local type=cargo:GetType()
66322
67337
  if(type~=CTLD_CARGO.Enum.TROOPS and type~=CTLD_CARGO.Enum.ENGINEERS)and(not cargo:WasDropped()or self.allowcratepickupagain)then
@@ -66327,6 +67342,18 @@ end
66327
67342
  if cratecount==0 then
66328
67343
  report:Add(" N O N E")
66329
67344
  end
67345
+ if loadedno>0 then
67346
+ report:Add("------------------------------------------------------------")
67347
+ report:Add(" -- CRATES loaded via F8 --")
67348
+ for _,_cargo in pairs(loadedgc or{})do
67349
+ local cargo=_cargo
67350
+ local type=cargo:GetType()
67351
+ if(type~=CTLD_CARGO.Enum.TROOPS and type~=CTLD_CARGO.Enum.ENGINEERS)then
67352
+ report:Add(string.format("Crate: %s size 1",cargo:GetName()))
67353
+ loadedmass=loadedmass+cargo:GetMass()
67354
+ end
67355
+ end
67356
+ end
66330
67357
  report:Add("------------------------------------------------------------")
66331
67358
  report:Add("Total Mass: "..loadedmass.." kg. Loadable: "..maxloadable.." kg.")
66332
67359
  local text=report:Text()
@@ -66426,6 +67453,13 @@ else
66426
67453
  return false
66427
67454
  end
66428
67455
  end
67456
+ function CTLD:IsHook(Unit)
67457
+ if string.find(Unit:GetTypeName(),"CH.47")then
67458
+ return true
67459
+ else
67460
+ return false
67461
+ end
67462
+ end
66429
67463
  function CTLD:_GetUnitPositions(Coordinate,Radius,Heading,Template)
66430
67464
  local Positions={}
66431
67465
  local template=_DATABASE:GetGroupTemplate(Template)
@@ -66462,7 +67496,8 @@ droppingatbase=true
66462
67496
  end
66463
67497
  local hoverunload=self:IsCorrectHover(Unit)
66464
67498
  local IsHerc=self:IsHercules(Unit)
66465
- if IsHerc then
67499
+ local IsHook=self:IsHook(Unit)
67500
+ if IsHerc and(not IsHook)then
66466
67501
  hoverunload=self:IsCorrectFlightParameters(Unit)
66467
67502
  end
66468
67503
  local grounded=not self:IsUnitInAir(Unit)
@@ -66519,7 +67554,7 @@ end
66519
67554
  end
66520
67555
  else
66521
67556
  self:_SendMessage("Troops have returned to base!",10,false,Group)
66522
- self:__TroopsRTB(1,Group,Unit)
67557
+ self:__TroopsRTB(1,Group,Unit,zonename,zone)
66523
67558
  end
66524
67559
  local loaded={}
66525
67560
  loaded.Troopsloaded=0
@@ -66570,9 +67605,14 @@ return self
66570
67605
  end
66571
67606
  end
66572
67607
  end
67608
+ if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName())then
67609
+ self:_SendMessage("You need to open the door(s) to drop cargo!",10,false,Group)
67610
+ if not self.debug then return self end
67611
+ end
66573
67612
  local hoverunload=self:IsCorrectHover(Unit)
66574
67613
  local IsHerc=self:IsHercules(Unit)
66575
- if IsHerc then
67614
+ local IsHook=self:IsHook(Unit)
67615
+ if IsHerc and(not IsHook)then
66576
67616
  hoverunload=self:IsCorrectFlightParameters(Unit)
66577
67617
  end
66578
67618
  local grounded=not self:IsUnitInAir(Unit)
@@ -66856,7 +67896,7 @@ self:T(self.lid.." _MoveGroupToZone")
66856
67896
  local groupname=Group:GetName()or"none"
66857
67897
  local groupcoord=Group:GetCoordinate()
66858
67898
  local outcome,name,zone,distance=self:IsUnitInZone(Group,CTLD.CargoZoneType.MOVE)
66859
- if(distance<=self.movetroopsdistance)and zone then
67899
+ if(distance<=self.movetroopsdistance)and outcome==true and zone~=nil then
66860
67900
  local groupname=Group:GetName()
66861
67901
  local zonecoord=zone:GetRandomCoordinate(20,125)
66862
67902
  local coordinate=zonecoord:GetVec2()
@@ -66900,7 +67940,7 @@ local PlayerSet=self.PilotGroups
66900
67940
  local PlayerTable=PlayerSet:GetSetObjects()
66901
67941
  local _UnitList={}
66902
67942
  for _key,_group in pairs(PlayerTable)do
66903
- local _unit=_group:GetUnit(1)
67943
+ local _unit=_group:GetFirstUnitAlive()
66904
67944
  if _unit then
66905
67945
  if _unit:IsAlive()and _unit:IsPlayer()then
66906
67946
  if _unit:IsHelicopter()or(self:IsHercules(_unit)and self.enableHercules)then
@@ -66946,6 +67986,8 @@ local unittype=_unit:GetTypeName()
66946
67986
  local capabilities=self:_GetUnitCapabilities(_unit)
66947
67987
  local cantroops=capabilities.troops
66948
67988
  local cancrates=capabilities.crates
67989
+ local isHook=self:IsHook(_unit)
67990
+ local nohookswitch=not(isHook and self.enableChinookGCLoading)
66949
67991
  local topmenu=MENU_GROUP:New(_group,"CTLD",nil)
66950
67992
  local toptroops=nil
66951
67993
  local topcrates=nil
@@ -66999,7 +68041,9 @@ local unloadmenu1=MENU_GROUP_COMMAND:New(_group,"Drop troops",toptroops,self._Un
66999
68041
  local extractMenu1=MENU_GROUP_COMMAND:New(_group,"Extract troops",toptroops,self._ExtractTroops,self,_group,_unit):Refresh()
67000
68042
  end
67001
68043
  if cancrates then
68044
+ if nohookswitch then
67002
68045
  local loadmenu=MENU_GROUP_COMMAND:New(_group,"Load crates",topcrates,self._LoadCratesNearby,self,_group,_unit)
68046
+ end
67003
68047
  local cratesmenu=MENU_GROUP:New(_group,"Get Crates",topcrates)
67004
68048
  local packmenu=MENU_GROUP_COMMAND:New(_group,"Pack crates",topcrates,self._PackCratesNearby,self,_group,_unit)
67005
68049
  local removecratesmenu=MENU_GROUP:New(_group,"Remove crates",topcrates)
@@ -67066,11 +68110,14 @@ end
67066
68110
  end
67067
68111
  listmenu=MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates,self._ListCratesNearby,self,_group,_unit)
67068
68112
  local removecrates=MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu,self._RemoveCratesNearby,self,_group,_unit)
67069
- local unloadmenu=MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates,self._UnloadCrates,self,_group,_unit)
68113
+ local unloadmenu
68114
+ if nohookswitch then
68115
+ unloadmenu=MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates,self._UnloadCrates,self,_group,_unit)
68116
+ end
67070
68117
  if not self.nobuildmenu then
67071
68118
  local buildmenu=MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates,self._BuildCrates,self,_group,_unit)
67072
68119
  local repairmenu=MENU_GROUP_COMMAND:New(_group,"Repair",topcrates,self._RepairCrates,self,_group,_unit):Refresh()
67073
- else
68120
+ elseif unloadmenu then
67074
68121
  unloadmenu:Refresh()
67075
68122
  end
67076
68123
  end
@@ -67130,16 +68177,28 @@ self:T(self.lid.." AddStaticsCargo")
67130
68177
  self.CargoCounter=self.CargoCounter+1
67131
68178
  local type=CTLD_CARGO.Enum.STATIC
67132
68179
  local template=STATIC:FindByName(Name,true):GetTypeName()
68180
+ local unittemplate=_DATABASE:GetStaticUnitTemplate(Name)
68181
+ local ResourceMap=nil
68182
+ if unittemplate and unittemplate.resourcePayload then
68183
+ ResourceMap=UTILS.DeepCopy(unittemplate.resourcePayload)
68184
+ end
67133
68185
  local cargo=CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,Stock,SubCategory,DontShowInMenu,Location)
68186
+ cargo:SetStaticResourceMap(ResourceMap)
67134
68187
  table.insert(self.Cargo_Statics,cargo)
67135
- return self
68188
+ return cargo
67136
68189
  end
67137
68190
  function CTLD:GetStaticsCargoFromTemplate(Name,Mass)
67138
68191
  self:T(self.lid.." GetStaticsCargoFromTemplate")
67139
68192
  self.CargoCounter=self.CargoCounter+1
67140
68193
  local type=CTLD_CARGO.Enum.STATIC
67141
68194
  local template=STATIC:FindByName(Name,true):GetTypeName()
68195
+ local unittemplate=_DATABASE:GetStaticUnitTemplate(Name)
68196
+ local ResourceMap=nil
68197
+ if unittemplate and unittemplate.resourcePayload then
68198
+ ResourceMap=UTILS.DeepCopy(unittemplate.resourcePayload)
68199
+ end
67142
68200
  local cargo=CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,1)
68201
+ cargo:SetStaticResourceMap(ResourceMap)
67143
68202
  return cargo
67144
68203
  end
67145
68204
  function CTLD:AddCratesRepair(Name,Template,Type,NoCrates,PerCrateMass,Stock,SubCategory,DontShowInMenu,Location)
@@ -67487,10 +68546,9 @@ zoneradius=2000
67487
68546
  zonewidth=zoneradius
67488
68547
  end
67489
68548
  local distance=self:_GetDistance(zonecoord,unitcoord)
67490
- if zone:IsVec2InZone(unitVec2)and active then
68549
+ self:T("Distance Zone: "..distance)
68550
+ if(zone:IsVec2InZone(unitVec2)or Zonetype==CTLD.CargoZoneType.MOVE)and active==true and maxdist>distance then
67491
68551
  outcome=true
67492
- end
67493
- if maxdist>distance then
67494
68552
  maxdist=distance
67495
68553
  zoneret=zone
67496
68554
  zonenameret=zonename
@@ -68113,6 +69171,8 @@ end
68113
69171
  self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler)
68114
69172
  self:HandleEvent(EVENTS.PlayerEnterUnit,self._EventHandler)
68115
69173
  self:HandleEvent(EVENTS.PlayerLeaveUnit,self._EventHandler)
69174
+ self:HandleEvent(EVENTS.UnitLost,self._EventHandler)
69175
+ self:HandleEvent(EVENTS.Birth,self._EventHandler)
68116
69176
  self:__Status(-5)
68117
69177
  if self.enableLoadSave then
68118
69178
  local interval=self.saveinterval
@@ -68252,7 +69312,7 @@ self:_MoveGroupToZone(Vehicle)
68252
69312
  end
68253
69313
  return self
68254
69314
  end
68255
- function CTLD:onbeforeTroopsRTB(From,Event,To,Group,Unit)
69315
+ function CTLD:onbeforeTroopsRTB(From,Event,To,Group,Unit,ZoneName,ZoneObject)
68256
69316
  self:T({From,Event,To})
68257
69317
  return self
68258
69318
  end
@@ -68502,6 +69562,8 @@ cargotemplates=UTILS.Split(cargotemplates,";")
68502
69562
  injectstatic=CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass)
68503
69563
  elseif cargotype==CTLD_CARGO.Enum.STATIC or cargotype==CTLD_CARGO.Enum.REPAIR then
68504
69564
  injectstatic=CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass)
69565
+ local map=cargotype:GetStaticResourceMap()
69566
+ injectstatic:SetStaticResourceMap(map)
68505
69567
  end
68506
69568
  if injectstatic then
68507
69569
  self:InjectStatics(dropzone,injectstatic)
@@ -68704,6 +69766,8 @@ local theStatic=SPAWNSTATIC:NewFromType(basetype,"Cargos",self.cratecountry)
68704
69766
  :Spawn(270,_name.."-Container-"..math.random(1,100000))
68705
69767
  self.CTLD.Spawned_Crates[self.CTLD.CrateCounter]=theStatic
68706
69768
  local newCargo=CTLD_CARGO:New(self.CTLD.CargoCounter,theCargo.Name,theCargo.Templates,theCargo.CargoType,true,false,theCargo.CratesNeeded,self.CTLD.Spawned_Crates[self.CTLD.CrateCounter],true,theCargo.PerCrateMass,nil,theCargo.Subcategory)
69769
+ local map=theCargo:GetStaticResourceMap()
69770
+ newCargo:SetStaticResourceMap(map)
68707
69771
  table.insert(self.CTLD.Spawned_Cargo,newCargo)
68708
69772
  newCargo:SetWasDropped(true)
68709
69773
  newCargo:SetHasMoved(true)
@@ -68973,7 +70037,9 @@ CSAR.AircraftType["AH-64D_BLK_II"]=2
68973
70037
  CSAR.AircraftType["Bronco-OV-10A"]=2
68974
70038
  CSAR.AircraftType["MH-60R"]=10
68975
70039
  CSAR.AircraftType["OH-6A"]=2
68976
- CSAR.version="1.0.22"
70040
+ CSAR.AircraftType["OH-58D"]=2
70041
+ CSAR.AircraftType["CH-47Fbl1"]=31
70042
+ CSAR.version="1.0.26"
68977
70043
  function CSAR:New(Coalition,Template,Alias)
68978
70044
  local self=BASE:Inherit(self,FSM:New())
68979
70045
  BASE:T({Coalition,Template,Alias})
@@ -69173,7 +70239,6 @@ local _spawnedGroup=SPAWN
69173
70239
  :NewWithAlias(template,alias)
69174
70240
  :InitCoalition(coalition)
69175
70241
  :InitCountry(country)
69176
- :InitAIOnOff(pilotcacontrol)
69177
70242
  :InitDelayOff()
69178
70243
  :SpawnFromCoordinate(point)
69179
70244
  return _spawnedGroup,alias
@@ -69495,10 +70560,24 @@ local _leadername=_leader:GetName()
69495
70560
  if not _nomessage then
69496
70561
  if _freq~=0 then
69497
70562
  local _text=string.format("%s requests SAR at %s, beacon at %.2f KHz",_groupName,_coordinatesText,_freqk)
70563
+ if self.coordtype~=2 then
69498
70564
  self:_DisplayToAllSAR(_text,self.coalition,self.messageTime)
69499
70565
  else
70566
+ self:_DisplayToAllSAR(_text,self.coalition,self.messageTime,false,true)
70567
+ local coordtext=UTILS.MGRSStringToSRSFriendly(_coordinatesText,true)
70568
+ local _text=string.format("%s requests SAR at %s, beacon at %.2f kilo hertz",_groupName,coordtext,_freqk)
70569
+ self:_DisplayToAllSAR(_text,self.coalition,self.messageTime,true,false)
70570
+ end
70571
+ else
69500
70572
  local _text=string.format("Pickup Zone at %s.",_coordinatesText)
70573
+ if self.coordtype~=2 then
69501
70574
  self:_DisplayToAllSAR(_text,self.coalition,self.messageTime)
70575
+ else
70576
+ self:_DisplayToAllSAR(_text,self.coalition,self.messageTime,false,true)
70577
+ local coordtext=UTILS.MGRSStringToSRSFriendly(_coordinatesText,true)
70578
+ local _text=string.format("Pickup Zone at %s.",coordtext)
70579
+ self:_DisplayToAllSAR(_text,self.coalition,self.messageTime,true,false)
70580
+ end
69502
70581
  end
69503
70582
  end
69504
70583
  for _,_heliName in pairs(self.csarUnits)do
@@ -70003,23 +71082,26 @@ self:_DisplayMessageToSAR(_heli,string.format("No Pilots within %s",dtext),self.
70003
71082
  end
70004
71083
  return self
70005
71084
  end
70006
- function CSAR:_DisplayToAllSAR(_message,_side,_messagetime)
71085
+ function CSAR:_DisplayToAllSAR(_message,_side,_messagetime,ToSRS,ToScreen)
70007
71086
  self:T(self.lid.." _DisplayToAllSAR")
70008
71087
  local messagetime=_messagetime or self.messageTime
70009
- if self.msrs then
71088
+ self:T({_message,ToSRS=ToSRS,ToScreen=ToScreen})
71089
+ if self.msrs and(ToSRS==true or ToSRS==nil)then
70010
71090
  local voice=self.CSARVoice or MSRS.Voices.Google.Standard.en_GB_Standard_F
70011
71091
  if self.msrs:GetProvider()==MSRS.Provider.WINDOWS then
70012
71092
  voice=self.CSARVoiceMS or MSRS.Voices.Microsoft.Hedda
70013
71093
  end
70014
- self:I("Voice = "..voice)
71094
+ self:F("Voice = "..voice)
70015
71095
  self.SRSQueue:NewTransmission(_message,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,voice,volume,label,self.coordinate)
70016
71096
  end
71097
+ if ToScreen==true or ToScreen==nil then
70017
71098
  for _,_unitName in pairs(self.csarUnits)do
70018
71099
  local _unit=self:_GetSARHeli(_unitName)
70019
71100
  if _unit and not self.suppressmessages then
70020
71101
  self:_DisplayMessageToSAR(_unit,_message,_messagetime)
70021
71102
  end
70022
71103
  end
71104
+ end
70023
71105
  return self
70024
71106
  end
70025
71107
  function CSAR:_Reqsmoke(_unitName)
@@ -70122,7 +71204,7 @@ local allheligroupset=self.allheligroupset
70122
71204
  local _allHeliGroups=allheligroupset:GetSetObjects()
70123
71205
  local _UnitList={}
70124
71206
  for _key,_group in pairs(_allHeliGroups)do
70125
- local _unit=_group:GetUnit(1)
71207
+ local _unit=_group:GetFirstUnitAlive()
70126
71208
  if _unit then
70127
71209
  if _unit:IsAlive()and _unit:IsPlayer()then
70128
71210
  local unitName=_unit:GetName()
@@ -80183,6 +81265,9 @@ function SOUNDFILE:GetFileName()
80183
81265
  return self.filename
80184
81266
  end
80185
81267
  function SOUNDFILE:SetDuration(Duration)
81268
+ if Duration and type(Duration)=="string"then
81269
+ Duration=tonumber(Duration)
81270
+ end
80186
81271
  self.duration=Duration or 3
80187
81272
  return self
80188
81273
  end
@@ -80213,7 +81298,7 @@ ClassName="SOUNDTEXT",
80213
81298
  function SOUNDTEXT:New(Text,Duration)
80214
81299
  local self=BASE:Inherit(self,BASE:New())
80215
81300
  self:SetText(Text)
80216
- self:SetDuration(Duration or STTS.getSpeechTime(Text))
81301
+ self:SetDuration(Duration or MSRS.getSpeechTime(Text))
80217
81302
  self:T(string.format("New SOUNDTEXT: text=%s, duration=%.1f sec",self.text,self.duration))
80218
81303
  return self
80219
81304
  end
@@ -80248,6 +81333,7 @@ SubtitleDuration=0,
80248
81333
  Power=100,
80249
81334
  Loop=false,
80250
81335
  alias=nil,
81336
+ moduhasbeenset=false,
80251
81337
  }
80252
81338
  function RADIO:New(Positionable)
80253
81339
  local self=BASE:Inherit(self,BASE:New())
@@ -80283,12 +81369,13 @@ end
80283
81369
  function RADIO:SetFrequency(Frequency)
80284
81370
  self:F2(Frequency)
80285
81371
  if type(Frequency)=="number"then
80286
- self.Frequency=Frequency*1000000
81372
+ self.Frequency=Frequency
81373
+ self.HertzFrequency=Frequency*1000000
80287
81374
  if self.Positionable.ClassName=="UNIT"or self.Positionable.ClassName=="GROUP"then
80288
81375
  local commandSetFrequency={
80289
81376
  id="SetFrequency",
80290
81377
  params={
80291
- frequency=self.Frequency,
81378
+ frequency=self.HertzFrequency,
80292
81379
  modulation=self.Modulation,
80293
81380
  }
80294
81381
  }
@@ -80305,6 +81392,10 @@ self:F2(Modulation)
80305
81392
  if type(Modulation)=="number"then
80306
81393
  if Modulation==radio.modulation.AM or Modulation==radio.modulation.FM then
80307
81394
  self.Modulation=Modulation
81395
+ if self.moduhasbeenset==false and Modulation==radio.modulation.FM then
81396
+ self:SetFrequency(self.Frequency)
81397
+ end
81398
+ self.moduhasbeenset=true
80308
81399
  return self
80309
81400
  end
80310
81401
  end
@@ -80510,7 +81601,7 @@ self:E(self.lid.."ERROR: No duration of transmission specified.")
80510
81601
  return nil
80511
81602
  end
80512
81603
  if type(duration)~="number"then
80513
- self:E(self.lid.."ERROR: Duration specified is NOT a number.")
81604
+ self:E(self.lid..string.format("ERROR: Duration specified is NOT a number but type=%s. Filename=%s, duration=%s",type(duration),tostring(filename),tostring(duration)))
80514
81605
  return nil
80515
81606
  end
80516
81607
  local transmission={}
@@ -80554,6 +81645,7 @@ end
80554
81645
  return wait
80555
81646
  end
80556
81647
  function RADIOQUEUE:Broadcast(transmission)
81648
+ self:T("Broadcast")
80557
81649
  if((transmission.soundfile and transmission.soundfile.useSRS)or transmission.soundtext)and self.msrs then
80558
81650
  self:_BroadcastSRS(transmission)
80559
81651
  return
@@ -80592,7 +81684,7 @@ local text=string.format("file=%s, freq=%.2f MHz, duration=%.2f sec, subtitle=%s
80592
81684
  MESSAGE:New(text,2,"RADIOQUEUE "..self.alias):ToAll()
80593
81685
  end
80594
81686
  else
80595
- self:T(self.lid..string.format("Broadcasting via trigger.action.radioTransmission()."))
81687
+ self:T(self.lid..string.format("Broadcasting via trigger.action.radioTransmission()"))
80596
81688
  local vec3=nil
80597
81689
  if self.sendername then
80598
81690
  vec3=self:_GetRadioSenderCoord()
@@ -80608,6 +81700,8 @@ if self.Debugmode then
80608
81700
  local text=string.format("file=%s, freq=%.2f MHz, duration=%.2f sec, subtitle=%s",filename,self.frequency/1000000,transmission.duration,transmission.subtitle or"")
80609
81701
  MESSAGE:New(string.format(text,filename,transmission.duration,transmission.subtitle or""),5,"RADIOQUEUE "..self.alias):ToAll()
80610
81702
  end
81703
+ else
81704
+ self:E("ERROR: Could not get vec3 to determine transmission origin! Did you specify a sender and is it still alive?")
80611
81705
  end
80612
81706
  end
80613
81707
  end