@jtff/miztemplate-lib 3.9.1 → 3.10.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: 2025-09-24T19:16:14+02:00-b5524b9a69fec49c33cd0e623bf6874ef56fd370 ***')
1
+ env.info('*** MOOSE GITHUB Commit Hash ID: 2025-10-23T12:10:05+02:00-0f270a6a35ebcfe2430659092d934beeb495d489 ***')
2
2
  if not MOOSE_DEVELOPMENT_FOLDER then
3
3
  MOOSE_DEVELOPMENT_FOLDER='Scripts'
4
4
  end
@@ -469,6 +469,7 @@ CH47={},
469
469
  OH58={},
470
470
  UH1H={},
471
471
  AH64D={},
472
+ UH60L={},
472
473
  }
473
474
  }
474
475
  ENUMS.Storage.weapons.nurs.SNEB_TYPE253_F1B="weapons.nurs.SNEB_TYPE253_F1B"
@@ -1172,6 +1173,24 @@ ENUMS.Storage.weapons.UH1H.M134_MiniGun_Right_Door={4,15,46,175}
1172
1173
  ENUMS.Storage.weapons.UH1H.M60_MG_Right_Door={4,15,46,177}
1173
1174
  ENUMS.Storage.weapons.UH1H.M134_MiniGun_Left_Door={4,15,46,174}
1174
1175
  ENUMS.Storage.weapons.UH1H.M60_MG_Left_Door={4,15,46,176}
1176
+ ENUMS.Storage.weapons.UH60L.M151_HYDRA={4,7,33,147}
1177
+ ENUMS.Storage.weapons.UH60L.M156_HYDRA={4,7,33,148}
1178
+ ENUMS.Storage.weapons.UH60L.M229_HYDRA={4,7,33,148}
1179
+ ENUMS.Storage.weapons.UH60L.M257_HYDRA={4,7,33,151}
1180
+ ENUMS.Storage.weapons.UH60L.M259_HYDRA={4,7,33,151}
1181
+ ENUMS.Storage.weapons.UH60L.M274_HYDRA={4,7,33,150}
1182
+ ENUMS.Storage.weapons.UH60L.M134_DOOR_GUN={4,15,46,3031}
1183
+ ENUMS.Storage.weapons.UH60L.M3M={4,15,46,2496}
1184
+ ENUMS.Storage.weapons.UH60L.M3M_DOOR_GUN={4,15,46,3032}
1185
+ ENUMS.Storage.weapons.UH60L.M60_DOOR_GUN={4,15,46,3033}
1186
+ ENUMS.Storage.weapons.UH60L.FUEL_TANK_200={1,3,43,3023}
1187
+ ENUMS.Storage.weapons.UH60L.FUEL_TANK_230={1,3,43,3024}
1188
+ ENUMS.Storage.weapons.UH60L.FUEL_TANK_450={1,3,43,3025}
1189
+ ENUMS.Storage.weapons.UH60L.FUEL_TANK_DUAL_AUX={1,3,43,3026}
1190
+ ENUMS.Storage.weapons.UH60L.CARGO_SEAT_REAR_ROW={1,3,43,3030}
1191
+ ENUMS.Storage.weapons.UH60L.CARGO_SEAT_THREE_ROWS={1,3,43,3029}
1192
+ ENUMS.Storage.weapons.UH60L.EMPTY_GUNNER_SEAT_1={1,3,43,3027}
1193
+ ENUMS.Storage.weapons.UH60L.EMPTY_GUNNER_SEAT_2={1,3,43,3028}
1175
1194
  ENUMS.Storage.weapons.OH58.FIM92={4,4,7,449}
1176
1195
  ENUMS.Storage.weapons.OH58.MG_M3P100={4,15,46,2611}
1177
1196
  ENUMS.Storage.weapons.OH58.MG_M3P200={4,15,46,2610}
@@ -2659,6 +2678,14 @@ if type_name=="UH-60L"and(unit:getDrawArgumentValue(38)>0 or unit:getDrawArgumen
2659
2678
  BASE:T(unit_name.." front door(s) are open")
2660
2679
  return true
2661
2680
  end
2681
+ if type_name=="UH-60L_DAP"and(unit:getDrawArgumentValue(401)==1 or unit:getDrawArgumentValue(402)==1)then
2682
+ BASE:T(unit_name.." cargo door is open")
2683
+ return true
2684
+ end
2685
+ if type_name=="UH-60L_DAP"and(unit:getDrawArgumentValue(38)>0 or unit:getDrawArgumentValue(400)==1)then
2686
+ BASE:T(unit_name.." front door(s) are open")
2687
+ return true
2688
+ end
2662
2689
  if type_name=="AH-64D_BLK_II"then
2663
2690
  BASE:T(unit_name.." front door(s) are open")
2664
2691
  return true
@@ -3860,7 +3887,55 @@ end
3860
3887
  UTILS.lcg.seed=(UTILS.lcg.a*UTILS.lcg.seed+UTILS.lcg.c)%UTILS.lcg.m
3861
3888
  return UTILS.lcg.seed/UTILS.lcg.m
3862
3889
  end
3863
- function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,Country,CallSign,Frequency,Modulation,ADF,SpawnRadius,VehicleTemplate,Liquids,Equipment,Airframes,F10Text,DynamicSpawns,HotStart)
3890
+ function UTILS.GenerateGridPoints(startVec2,n,spacingX,spacingY)
3891
+ local points={}
3892
+ local gridSize=math.ceil(math.sqrt(n))
3893
+ local count=0
3894
+ local n=n or 1
3895
+ local spacingX=spacingX or 100
3896
+ local spacingY=spacingY or 100
3897
+ local startX=startVec2.x or 100
3898
+ local startY=startVec2.y or 100
3899
+ for row=0,gridSize-1 do
3900
+ for col=0,gridSize-1 do
3901
+ if count>=n then
3902
+ break
3903
+ end
3904
+ local point={
3905
+ x=startX+(col*spacingX),
3906
+ y=startY+(row*spacingY)
3907
+ }
3908
+ table.insert(points,point)
3909
+ count=count+1
3910
+ end
3911
+ if count>=n then
3912
+ break
3913
+ end
3914
+ end
3915
+ return points
3916
+ end
3917
+ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,Country,CallSign,Frequency,Modulation,ADF,SpawnRadius,VehicleTemplate,Liquids,Equipment,Airframes,F10Text,DynamicSpawns,HotStart,NumberPads,SpacingX,SpacingY)
3918
+ local function PopulateStorage(Name,liquids,equip,airframes)
3919
+ local newWH=STORAGE:New(Name)
3920
+ if liquids and liquids>0 then
3921
+ newWH:SetLiquid(STORAGE.Liquid.DIESEL,liquids)
3922
+ newWH:SetLiquid(STORAGE.Liquid.GASOLINE,liquids)
3923
+ newWH:SetLiquid(STORAGE.Liquid.JETFUEL,liquids)
3924
+ newWH:SetLiquid(STORAGE.Liquid.MW50,liquids)
3925
+ end
3926
+ if equip and equip>0 then
3927
+ for cat,nitem in pairs(ENUMS.Storage.weapons)do
3928
+ for name,item in pairs(nitem)do
3929
+ newWH:SetItem(item,equip)
3930
+ end
3931
+ end
3932
+ end
3933
+ if airframes and airframes>0 then
3934
+ for typename in pairs(CSAR.AircraftType)do
3935
+ newWH:SetItem(typename,airframes)
3936
+ end
3937
+ end
3938
+ end
3864
3939
  local farplocation=Coordinate
3865
3940
  local farptype=FARPType or ENUMS.FARPType.FARP
3866
3941
  local Coalition=Coalition or coalition.side.BLUE
@@ -3878,11 +3953,29 @@ local STypeName=statictypes.TypeName
3878
3953
  local SShapeName=statictypes.ShapeName
3879
3954
  local Country=Country or(Coalition==coalition.side.BLUE and country.id.USA or country.id.RUSSIA)
3880
3955
  local ReturnObjects={}
3956
+ local NumberPads=NumberPads or 1
3957
+ local SpacingX=SpacingX or 100
3958
+ local SpacingY=SpacingY or 100
3959
+ local FarpVec2=Coordinate:GetVec2()
3960
+ if NumberPads>1 then
3961
+ local Grid=UTILS.GenerateGridPoints(FarpVec2,NumberPads,SpacingX,SpacingY)
3962
+ for id,gridpoint in ipairs(Grid)do
3963
+ local location=COORDINATE:NewFromVec2(gridpoint)
3964
+ local newfarp=SPAWNSTATIC:NewFromType(STypeName,"Heliports",Country)
3965
+ newfarp:InitShape(SShapeName)
3966
+ newfarp:InitFARP(callsign,freq,mod,DynamicSpawns,HotStart)
3967
+ local spawnedfarp=newfarp:SpawnFromCoordinate(location,0,Name.."-"..id)
3968
+ table.insert(ReturnObjects,spawnedfarp)
3969
+ PopulateStorage(Name.."-"..id,liquids,equip,airframes)
3970
+ end
3971
+ else
3881
3972
  local newfarp=SPAWNSTATIC:NewFromType(STypeName,"Heliports",Country)
3882
3973
  newfarp:InitShape(SShapeName)
3883
3974
  newfarp:InitFARP(callsign,freq,mod,DynamicSpawns,HotStart)
3884
3975
  local spawnedfarp=newfarp:SpawnFromCoordinate(farplocation,0,Name)
3885
3976
  table.insert(ReturnObjects,spawnedfarp)
3977
+ PopulateStorage(Name,liquids,equip,airframes)
3978
+ end
3886
3979
  local FARPStaticObjectsNato={
3887
3980
  ["FUEL"]={TypeName="FARP Fuel Depot",ShapeName="GSM Rus",Category="Fortifications"},
3888
3981
  ["AMMO"]={TypeName="FARP Ammo Dump Coating",ShapeName="SetkaKP",Category="Fortifications"},
@@ -3911,25 +4004,6 @@ vehicles:InitDelayOff()
3911
4004
  local spawnedvehicle=vehicles:SpawnFromCoordinate(vcoordinate)
3912
4005
  table.insert(ReturnObjects,spawnedvehicle)
3913
4006
  end
3914
- local newWH=STORAGE:New(Name)
3915
- if liquids and liquids>0 then
3916
- newWH:SetLiquid(STORAGE.Liquid.DIESEL,liquids)
3917
- newWH:SetLiquid(STORAGE.Liquid.GASOLINE,liquids)
3918
- newWH:SetLiquid(STORAGE.Liquid.JETFUEL,liquids)
3919
- newWH:SetLiquid(STORAGE.Liquid.MW50,liquids)
3920
- end
3921
- if equip and equip>0 then
3922
- for cat,nitem in pairs(ENUMS.Storage.weapons)do
3923
- for name,item in pairs(nitem)do
3924
- newWH:SetItem(item,equip)
3925
- end
3926
- end
3927
- end
3928
- if airframes and airframes>0 then
3929
- for typename in pairs(CSAR.AircraftType)do
3930
- newWH:SetItem(typename,airframes)
3931
- end
3932
- end
3933
4007
  local ADFName
3934
4008
  if ADF and type(ADF)=="number"then
3935
4009
  local ADFFreq=ADF*1000
@@ -9919,6 +9993,16 @@ self.LastVec2=ZoneUNIT:GetVec2()
9919
9993
  _EVENTDISPATCHER:CreateEventNewZone(self)
9920
9994
  return self
9921
9995
  end
9996
+ function ZONE_UNIT:UpdateFromUnit(Unit)
9997
+ if Unit and Unit:IsAlive()then
9998
+ local vec2=Unit:GetVec2()
9999
+ self.LastVec2=vec2
10000
+ elseif self.ZoneUNIT and self.ZoneUNIT:IsAlive()then
10001
+ local ZoneVec2=self.ZoneUNIT:GetVec2()
10002
+ self.LastVec2=ZoneVec2
10003
+ end
10004
+ return self
10005
+ end
9922
10006
  function ZONE_UNIT:GetVec2()
9923
10007
  local ZoneVec2=self.ZoneUNIT:GetVec2()
9924
10008
  if ZoneVec2 then
@@ -9980,6 +10064,17 @@ ZoneVec2=self._.ZoneVec2Cache
9980
10064
  end
9981
10065
  return ZoneVec2
9982
10066
  end
10067
+ function ZONE_GROUP:UpdateFromGroup(Group)
10068
+ if Group and Group:IsAlive()then
10069
+ local vec2=Group:GetVec2()
10070
+ self.Vec2=vec2
10071
+ elseif self._.ZoneGROUP and self._.ZoneGROUP:IsAlive()then
10072
+ local ZoneVec2=self._.ZoneGROUP:GetVec2()
10073
+ self.Vec2=ZoneVec2
10074
+ self._.ZoneVec2Cache=ZoneVec2
10075
+ end
10076
+ return self
10077
+ end
9983
10078
  function ZONE_GROUP:GetRandomVec2()
9984
10079
  local Point={}
9985
10080
  local Vec2=self._.ZoneGROUP:GetVec2()
@@ -11392,11 +11487,17 @@ local ZoneName=objectData.name or"Unknown rect Polygon Drawing"
11392
11487
  local vec2={x=objectData.mapX,y=objectData.mapY}
11393
11488
  local w=objectData.width
11394
11489
  local h=objectData.height
11395
- local points={}
11396
- points[1]={x=vec2.x-h/2,y=vec2.y+w/2}
11397
- points[2]={x=vec2.x+h/2,y=vec2.y+w/2}
11398
- points[3]={x=vec2.x+h/2,y=vec2.y-w/2}
11399
- points[4]={x=vec2.x-h/2,y=vec2.y-w/2}
11490
+ local rotation=UTILS.ToRadian(objectData.angle or 0)
11491
+ local sinRot=math.sin(rotation)
11492
+ local cosRot=math.cos(rotation)
11493
+ local dx=h/2
11494
+ local dy=w/2
11495
+ local points={
11496
+ {x=-dx*cosRot-(-dy*sinRot)+vec2.x,y=-dx*sinRot+(-dy*cosRot)+vec2.y},
11497
+ {x=dx*cosRot-(-dy*sinRot)+vec2.x,y=dx*sinRot+(-dy*cosRot)+vec2.y},
11498
+ {x=dx*cosRot-(dy*sinRot)+vec2.x,y=dx*sinRot+(dy*cosRot)+vec2.y},
11499
+ {x=-dx*cosRot-(dy*sinRot)+vec2.x,y=-dx*sinRot+(dy*cosRot)+vec2.y},
11500
+ }
11400
11501
  self:I(string.format("Register ZONE: %s (Polygon (rect) drawing with %d vertices)",ZoneName,#points))
11401
11502
  local Zone=ZONE_POLYGON:NewFromPointsArray(ZoneName,points)
11402
11503
  Zone:SetColor({1,0,0},0.15)
@@ -16160,6 +16261,18 @@ self:Remove(RemoveGroupName)
16160
16261
  end
16161
16262
  return self
16162
16263
  end
16264
+ function SET_OPSGROUP:CountAlive()
16265
+ local CountG=0
16266
+ local CountU=0
16267
+ local Set=self:GetSet()
16268
+ for GroupID,GroupData in pairs(Set)do
16269
+ if GroupData and GroupData:IsAlive()then
16270
+ CountG=CountG+1
16271
+ CountU=CountU+GroupData:GetGroup():CountAliveUnits()
16272
+ end
16273
+ end
16274
+ return CountG,CountU
16275
+ end
16163
16276
  function SET_OPSGROUP:FindGroup(GroupName)
16164
16277
  local GroupFound=self.Set[GroupName]
16165
16278
  return GroupFound
@@ -21705,7 +21818,7 @@ self:ScheduleOnce(0.3,self.SpawnFunctionHook,mystatic,unpack(self.SpawnFunctionA
21705
21818
  end
21706
21819
  if self.StaticCopyFrom~=nil then
21707
21820
  mystatic.StaticCopyFrom=self.StaticCopyFrom
21708
- if not _DATABASE.Templates.Statics[Template.name]then
21821
+ end
21709
21822
  local TemplateGroup={}
21710
21823
  TemplateGroup.units={}
21711
21824
  TemplateGroup.units[1]=Template
@@ -21713,8 +21826,6 @@ TemplateGroup.x=Template.x
21713
21826
  TemplateGroup.y=Template.y
21714
21827
  TemplateGroup.name=Template.name
21715
21828
  _DATABASE:_RegisterStaticTemplate(TemplateGroup,self.CoalitionID,self.CategoryID,CountryID)
21716
- end
21717
- end
21718
21829
  return mystatic
21719
21830
  end
21720
21831
  TIMER={
@@ -22624,6 +22735,7 @@ function POSITIONABLE:GetCoord()
22624
22735
  local DCSPositionable=self:GetDCSObject()
22625
22736
  if DCSPositionable then
22626
22737
  local PositionableVec3=self:GetVec3()
22738
+ if PositionableVec3 then
22627
22739
  if self.coordinate then
22628
22740
  self.coordinate:UpdateFromVec3(PositionableVec3)
22629
22741
  else
@@ -22631,6 +22743,7 @@ self.coordinate=COORDINATE:NewFromVec3(PositionableVec3)
22631
22743
  end
22632
22744
  return self.coordinate
22633
22745
  end
22746
+ end
22634
22747
  BASE:E({"Cannot GetCoordinate",Positionable=self,Alive=self:IsAlive()})
22635
22748
  return nil
22636
22749
  end
@@ -25673,6 +25786,46 @@ return self
25673
25786
  end
25674
25787
  return nil
25675
25788
  end
25789
+ function CONTROLLABLE:OptionAAAMinFiringHeightMeters(meters)
25790
+ self:F2({self.ControllableName})
25791
+ local meters=meters or 20
25792
+ local DCSControllable=self:GetDCSObject()
25793
+ if DCSControllable then
25794
+ local Controller=self:_GetController()
25795
+ if Controller then
25796
+ if self:IsGround()then
25797
+ self:SetOption(27,meters)
25798
+ end
25799
+ end
25800
+ return self
25801
+ end
25802
+ return nil
25803
+ end
25804
+ function CONTROLLABLE:OptionAAAMaxFiringHeightMeters(meters)
25805
+ self:F2({self.ControllableName})
25806
+ local meters=meters or 1000
25807
+ local DCSControllable=self:GetDCSObject()
25808
+ if DCSControllable then
25809
+ local Controller=self:_GetController()
25810
+ if Controller then
25811
+ if self:IsGround()then
25812
+ self:SetOption(29,meters)
25813
+ end
25814
+ end
25815
+ return self
25816
+ end
25817
+ return nil
25818
+ end
25819
+ function CONTROLLABLE:OptionAAAMinFiringHeightFeet(feet)
25820
+ self:F2({self.ControllableName})
25821
+ local feet=feet or 60
25822
+ return self:OptionAAAMinFiringHeightMeters(UTILS.FeetToMeters(feet))
25823
+ end
25824
+ function CONTROLLABLE:OptionAAAMaxFiringHeightfeet(feet)
25825
+ self:F2({self.ControllableName})
25826
+ local feet=feet or 3000
25827
+ return self:OptionAAAMaxFiringHeightMeters(UTILS.FeetToMeters(feet))
25828
+ end
25676
25829
  function CONTROLLABLE:OptionEngageRange(EngageRange)
25677
25830
  self:F2({self.ControllableName})
25678
25831
  EngageRange=EngageRange or 100
@@ -30582,6 +30735,13 @@ end
30582
30735
  self:T2(string.format("Registered airbase %s",tostring(self.AirbaseName)))
30583
30736
  return self
30584
30737
  end
30738
+ function AIRBASE:GetVec2()
30739
+ local runways=self:GetRunways()
30740
+ if runways and#runways>0 then
30741
+ return runways[1].center:GetVec2()
30742
+ end
30743
+ return self:GetCoordinate():GetVec2()
30744
+ end
30585
30745
  function AIRBASE:_GetCategory()
30586
30746
  local name=self.AirbaseName
30587
30747
  local static=StaticObject.getByName(name)
@@ -33109,6 +33269,8 @@ REMOVED="REMOVED",
33109
33269
  }
33110
33270
  DYNAMICCARGO.AircraftTypes={
33111
33271
  ["CH-47Fbl1"]="CH-47Fbl1",
33272
+ ["Mi-8MTV2"]="CH-47Fbl1",
33273
+ ["Mi-8MT"]="CH-47Fbl1",
33112
33274
  }
33113
33275
  DYNAMICCARGO.AircraftDimensions={
33114
33276
  ["CH-47Fbl1"]={
@@ -33117,8 +33279,20 @@ DYNAMICCARGO.AircraftDimensions={
33117
33279
  ["length"]=11,
33118
33280
  ["ropelength"]=30,
33119
33281
  },
33282
+ ["Mi-8MTV2"]={
33283
+ ["width"]=6,
33284
+ ["height"]=6,
33285
+ ["length"]=15,
33286
+ ["ropelength"]=30,
33287
+ },
33288
+ ["Mi-8MT"]={
33289
+ ["width"]=6,
33290
+ ["height"]=6,
33291
+ ["length"]=15,
33292
+ ["ropelength"]=30,
33293
+ },
33120
33294
  }
33121
- DYNAMICCARGO.version="0.0.7"
33295
+ DYNAMICCARGO.version="0.0.9"
33122
33296
  function DYNAMICCARGO:Register(CargoName)
33123
33297
  local self=BASE:Inherit(self,POSITIONABLE:New(CargoName))
33124
33298
  self.StaticName=CargoName
@@ -34731,7 +34905,9 @@ end
34731
34905
  end)
34732
34906
  self.AutoSavePath=SavePath
34733
34907
  self.AutoSave=AutoSave or true
34908
+ if self.AutoSave==true then
34734
34909
  self:OpenCSV(GameName)
34910
+ end
34735
34911
  return self
34736
34912
  end
34737
34913
  function SCORING:SetDisplayMessagePrefix(DisplayMessagePrefix)
@@ -35755,7 +35931,7 @@ TargetUnitCoalition=TargetUnitCoalition or""
35755
35931
  TargetUnitCategory=TargetUnitCategory or""
35756
35932
  TargetUnitType=TargetUnitType or""
35757
35933
  TargetUnitName=TargetUnitName or""
35758
- if lfs and io and os and self.AutoSave then
35934
+ if lfs and io and os and self.AutoSave==true and self.CSVFile~=nil then
35759
35935
  self.CSVFile:write(
35760
35936
  '"'..self.GameName..'"'..','..
35761
35937
  '"'..self.RunTime..'"'..','..
@@ -40451,22 +40627,22 @@ RAT.markerid=0
40451
40627
  RAT.MenuF10=nil
40452
40628
  RAT.id="RAT | "
40453
40629
  RAT.version={
40454
- version="2.3.9",
40630
+ version="3.0.0",
40455
40631
  print=true,
40456
40632
  }
40457
40633
  function RAT:New(groupname,alias)
40458
- BASE:F({groupname=groupname,alias=alias})
40459
40634
  self=BASE:Inherit(self,SPAWN:NewWithAlias(groupname,alias))
40635
+ self.lid=string.format("RAT %s | ",alias or groupname)
40460
40636
  if RAT.version.print then
40461
- env.info(RAT.id.."Version "..RAT.version.version)
40637
+ env.info(self.lid.."Version "..RAT.version.version)
40462
40638
  RAT.version.print=false
40463
40639
  end
40464
- self:F(RAT.id..string.format("Creating new RAT object from template: %s.",groupname))
40640
+ self:F(self.lid..string.format("Creating new RAT object from template: %s.",groupname))
40465
40641
  alias=alias or groupname
40466
40642
  self.alias=alias
40467
40643
  local DCSgroup=Group.getByName(groupname)
40468
40644
  if DCSgroup==nil then
40469
- self:E(RAT.id..string.format("ERROR: Group with name %s does not exist in the mission editor!",groupname))
40645
+ self:E(self.lid..string.format("ERROR: Group with name %s does not exist in the mission editor!",groupname))
40470
40646
  return nil
40471
40647
  end
40472
40648
  self.templategroup=GROUP:FindByName(groupname)
@@ -40476,6 +40652,36 @@ self:_InitAircraft(DCSgroup)
40476
40652
  self:_GetAirportsOfMap()
40477
40653
  return self
40478
40654
  end
40655
+ function RAT:Stop(delay)
40656
+ self:T3(self.lid..string.format("Stopping RAT! Delay %s sec!",tostring(delay)))
40657
+ if delay and delay>0 then
40658
+ self:T2(self.lid..string.format("Stopping RAT in %d sec!",delay))
40659
+ self:ScheduleOnce(delay,RAT.Stop,self)
40660
+ else
40661
+ self:T(self.lid.."Stopping RAT: Clearing schedulers and unhandling events!")
40662
+ if self.sid_Activate then
40663
+ self.Scheduler:ScheduleStop(self.sid_Activate)
40664
+ end
40665
+ if self.sid_Spawn then
40666
+ self.Scheduler:ScheduleStop(self.sid_Spawn)
40667
+ end
40668
+ if self.sid_Status then
40669
+ self.Scheduler:ScheduleStop(self.sid_Status)
40670
+ end
40671
+ if self.Scheduler then
40672
+ self.Scheduler:Clear()
40673
+ end
40674
+ self.norespawn=true
40675
+ self:UnHandleEvent(EVENTS.Birth)
40676
+ self:UnHandleEvent(EVENTS.EngineStartup)
40677
+ self:UnHandleEvent(EVENTS.Takeoff)
40678
+ self:UnHandleEvent(EVENTS.Land)
40679
+ self:UnHandleEvent(EVENTS.EngineShutdown)
40680
+ self:UnHandleEvent(EVENTS.Dead)
40681
+ self:UnHandleEvent(EVENTS.Crash)
40682
+ self:UnHandleEvent(EVENTS.Hit)
40683
+ end
40684
+ end
40479
40685
  function RAT:Spawn(naircraft)
40480
40686
  if self.spawninitialized==true then
40481
40687
  self:E("ERROR: Spawn function should only be called once per RAT object! Exiting and returning nil.")
@@ -40485,7 +40691,7 @@ self.spawninitialized=true
40485
40691
  end
40486
40692
  self.ngroups=naircraft or 1
40487
40693
  if self.ATCswitch and not RAT.ATC.init then
40488
- self:_ATCInit(self.airports_map)
40694
+ RAT._ATCInit(self.airports_map)
40489
40695
  end
40490
40696
  if self.f10menu and not RAT.MenuF10 then
40491
40697
  RAT.MenuF10=MENU_MISSION:New("RAT")
@@ -40591,7 +40797,7 @@ text=text..string.format("- %s\n",livery)
40591
40797
  end
40592
40798
  end
40593
40799
  text=text..string.format("******************************************************\n")
40594
- self:T(RAT.id..text)
40800
+ self:T(self.lid..text)
40595
40801
  if self.f10menu then
40596
40802
  self.Menu[self.SubMenuName]=MENU_MISSION:New(self.SubMenuName,RAT.MenuF10)
40597
40803
  self.Menu[self.SubMenuName]["groups"]=MENU_MISSION:New("Groups",self.Menu[self.SubMenuName])
@@ -40605,7 +40811,7 @@ if self.takeoff==RAT.wp.runway and not self.random_departure then
40605
40811
  dt=math.max(dt,180)
40606
40812
  end
40607
40813
  local Tstop=Tstart+dt*(self.ngroups-1)
40608
- SCHEDULER:New(nil,self.Status,{self},Tstart+1,self.statusinterval)
40814
+ self.sid_Status=self:ScheduleRepeat(Tstart+1,self.statusinterval,nil,nil,RAT.Status,self)
40609
40815
  self:HandleEvent(EVENTS.Birth,self._OnBirth)
40610
40816
  self:HandleEvent(EVENTS.EngineStartup,self._OnEngineStartup)
40611
40817
  self:HandleEvent(EVENTS.Takeoff,self._OnTakeoff)
@@ -40617,9 +40823,9 @@ self:HandleEvent(EVENTS.Hit,self._OnHit)
40617
40823
  if self.ngroups==0 then
40618
40824
  return nil
40619
40825
  end
40620
- SCHEDULER:New(nil,self._SpawnWithRoute,{self},Tstart,dt,0.0,Tstop)
40826
+ self.sid_Spawn=self:ScheduleRepeat(Tstart,dt,0.0,Tstop,RAT._SpawnWithRoute,self)
40621
40827
  if self.uncontrolled and self.activate_uncontrolled then
40622
- SCHEDULER:New(nil,self._ActivateUncontrolled,{self},self.activate_delay,self.activate_delta,self.activate_frand)
40828
+ self.sid_Activate=self:ScheduleRepeat(self.activate_delay,self.activate_delta,self.activate_frand,nil,RAT._ActivateUncontrolled,self)
40623
40829
  end
40624
40830
  return true
40625
40831
  end
@@ -40635,12 +40841,12 @@ end
40635
40841
  end
40636
40842
  if self.Ndeparture_Zones>0 and self.takeoff~=RAT.wp.air then
40637
40843
  self.takeoff=RAT.wp.air
40638
- self:E(RAT.id..string.format("ERROR: At least one zone defined as departure and takeoff is NOT set to air. Enabling air start for RAT group %s!",self.alias))
40844
+ self:E(self.lid..string.format("WARNING: At least one zone defined as departure and takeoff is NOT set to air. Enabling air start for RAT group %s!",self.alias))
40639
40845
  end
40640
40846
  if self.Ndeparture_Airports==0 and self.Ndeparture_Zone==0 then
40641
40847
  self.random_departure=true
40642
40848
  local text=string.format("No airports or zones found given in SetDeparture(). Enabling random departure airports for RAT group %s!",self.alias)
40643
- self:E(RAT.id.."ERROR: "..text)
40849
+ self:E(self.lid.."ERROR: "..text)
40644
40850
  MESSAGE:New(text,30):ToAll()
40645
40851
  end
40646
40852
  end
@@ -40655,17 +40861,17 @@ end
40655
40861
  if self.Ndestination_Zones>0 and self.landing~=RAT.wp.air and not self.returnzone then
40656
40862
  self.landing=RAT.wp.air
40657
40863
  self.destinationzone=true
40658
- self:E(RAT.id.."ERROR: At least one zone defined as destination and landing is NOT set to air. Enabling destination zone!")
40864
+ self:E(self.lid.."WARNING: At least one zone defined as destination and landing is NOT set to air. Enabling destination zone!")
40659
40865
  end
40660
40866
  if self.Ndestination_Airports==0 and self.Ndestination_Zones==0 then
40661
40867
  self.random_destination=true
40662
40868
  local text="No airports or zones found given in SetDestination(). Enabling random destination airports!"
40663
- self:E(RAT.id.."ERROR: "..text)
40869
+ self:E(self.lid.."ERROR: "..text)
40664
40870
  MESSAGE:New(text,30):ToAll()
40665
40871
  end
40666
40872
  end
40667
40873
  if self.destinationzone and self.returnzone then
40668
- self:E(RAT.id.."ERROR: Destination zone _and_ return to zone not possible! Disabling return to zone.")
40874
+ self:E(self.lid.."ERROR: Destination zone _and_ return to zone not possible! Disabling return to zone.")
40669
40875
  self.returnzone=false
40670
40876
  end
40671
40877
  if self.returnzone and self.takeoff==RAT.wp.air then
@@ -40814,7 +41020,7 @@ names=departurenames
40814
41020
  elseif type(departurenames)=="string"then
40815
41021
  names={departurenames}
40816
41022
  else
40817
- self:E(RAT.id.."ERROR: Input parameter must be a string or a table in SetDeparture()!")
41023
+ self:E(self.lid.."ERROR: Input parameter must be a string or a table in SetDeparture()!")
40818
41024
  end
40819
41025
  for _,name in pairs(names)do
40820
41026
  if self:_AirportExists(name)then
@@ -40822,7 +41028,7 @@ table.insert(self.departure_ports,name)
40822
41028
  elseif self:_ZoneExists(name)then
40823
41029
  table.insert(self.departure_ports,name)
40824
41030
  else
40825
- self:E(RAT.id.."ERROR: No departure airport or zone found with name "..name)
41031
+ self:E(self.lid.."ERROR: No departure airport or zone found with name "..name)
40826
41032
  end
40827
41033
  end
40828
41034
  return self
@@ -40836,7 +41042,7 @@ names=destinationnames
40836
41042
  elseif type(destinationnames)=="string"then
40837
41043
  names={destinationnames}
40838
41044
  else
40839
- self:E(RAT.id.."ERROR: Input parameter must be a string or a table in SetDestination()!")
41045
+ self:E(self.lid.."ERROR: Input parameter must be a string or a table in SetDestination()!")
40840
41046
  end
40841
41047
  for _,name in pairs(names)do
40842
41048
  if self:_AirportExists(name)then
@@ -40844,7 +41050,7 @@ table.insert(self.destination_ports,name)
40844
41050
  elseif self:_ZoneExists(name)then
40845
41051
  table.insert(self.destination_ports,name)
40846
41052
  else
40847
- self:E(RAT.id.."ERROR: No destination airport or zone found with name "..name)
41053
+ self:E(self.lid.."ERROR: No destination airport or zone found with name "..name)
40848
41054
  end
40849
41055
  end
40850
41056
  return self
@@ -40949,12 +41155,14 @@ interval=interval or 5
40949
41155
  self.spawninterval=math.max(0.5,interval)
40950
41156
  return self
40951
41157
  end
41158
+ function RAT:SetSpawnLimit(Nmax)
41159
+ self.NspawnMax=Nmax
41160
+ return self
41161
+ end
40952
41162
  function RAT:RespawnAfterLanding(delay)
40953
41163
  self:F2(delay)
40954
- delay=delay or 180
40955
41164
  self.respawn_at_landing=true
40956
- delay=math.max(1.0,delay)
40957
- self.respawn_delay=delay
41165
+ self:SetRespawnDelay(delay)
40958
41166
  return self
40959
41167
  end
40960
41168
  function RAT:SetRespawnDelay(delay)
@@ -41018,10 +41226,6 @@ self.checkontop=switch
41018
41226
  self.ontopradius=radius or 2
41019
41227
  return self
41020
41228
  end
41021
- function RAT:ParkingSpotDB(switch)
41022
- self:E("RAT ParkingSpotDB function is obsolete and will be removed soon!")
41023
- return self
41024
- end
41025
41229
  function RAT:RadioON()
41026
41230
  self:F2()
41027
41231
  self.radio=true
@@ -41271,7 +41475,7 @@ elseif DCScategory==Group.Category.HELICOPTER then
41271
41475
  self.category=RAT.cat.heli
41272
41476
  else
41273
41477
  self.category="other"
41274
- self:E(RAT.id.."ERROR: Group of RAT is neither airplane nor helicopter!")
41478
+ self:E(self.lid.."ERROR: Group of RAT is neither airplane nor helicopter!")
41275
41479
  end
41276
41480
  self.aircraft.type=DCStype
41277
41481
  self.aircraft.fuel=DCSunit:getFuel()
@@ -41310,10 +41514,16 @@ text=text..string.format("Max range = %6.1f km\n",self.aircraft.Rmax/1000)
41310
41514
  text=text..string.format("Eff range = %6.1f km (with 95 percent initial fuel amount)\n",self.aircraft.Reff/1000)
41311
41515
  text=text..string.format("Ceiling = %6.1f km = FL%3.0f\n",self.aircraft.ceiling/1000,self.aircraft.ceiling/RAT.unit.FL2m)
41312
41516
  text=text..string.format("******************************************************\n")
41313
- self:T(RAT.id..text)
41517
+ self:T(self.lid..text)
41314
41518
  end
41315
41519
  function RAT:_SpawnWithRoute(_departure,_destination,_takeoff,_landing,_livery,_waypoint,_lastpos,_nrespawn,parkingdata)
41316
- self:F({rat=RAT.id,departure=_departure,destination=_destination,takeoff=_takeoff,landing=_landing,livery=_livery,waypoint=_waypoint,lastpos=_lastpos,nrespawn=_nrespawn})
41520
+ self:F({rat=self.lid,departure=_departure,destination=_destination,takeoff=_takeoff,landing=_landing,livery=_livery,waypoint=_waypoint,lastpos=_lastpos,nrespawn=_nrespawn})
41521
+ if self.NspawnMax and self.SpawnIndex>=self.NspawnMax then
41522
+ self:T(self.lid..string.format("Max limit of spawns reached %d >= %d! Will not spawn any more groups",self.NspawnMax,self.SpawnIndex))
41523
+ return
41524
+ else
41525
+ self:T2(self.lid..string.format("Spawning with spawn index=%d",self.SpawnIndex))
41526
+ end
41317
41527
  local takeoff=self.takeoff
41318
41528
  local landing=self.landing
41319
41529
  if _takeoff then
@@ -41330,7 +41540,7 @@ local nrespawn=0
41330
41540
  if _nrespawn then
41331
41541
  nrespawn=_nrespawn
41332
41542
  end
41333
- local departure,destination,waypoints,WPholding,WPfinal=self:_SetRoute(takeoff,landing,_departure,_destination,_waypoint)
41543
+ local departure,destination,waypoints,wpdesc,wpstatus=self:_SetRoute(takeoff,landing,_departure,_destination,_waypoint)
41334
41544
  if not(departure and destination and waypoints)then
41335
41545
  return nil
41336
41546
  end
@@ -41340,101 +41550,210 @@ livery=_livery
41340
41550
  elseif self.livery then
41341
41551
  livery=self.livery[math.random(#self.livery)]
41342
41552
  local text=string.format("Chosen livery for group %s: %s",self:_AnticipatedGroupName(),livery)
41343
- self:T(RAT.id..text)
41553
+ self:T(self.lid..text)
41344
41554
  else
41345
41555
  livery=nil
41346
41556
  end
41347
- local successful=self:_ModifySpawnTemplate(waypoints,livery,_lastpos,departure,takeoff,parkingdata)
41557
+ local uncontrolled=self.uncontrolled
41558
+ local isFlightcontrol=self:_IsFlightControlAirbase(departure)
41559
+ if takeoff~=RAT.wp.air and departure and isFlightcontrol then
41560
+ takeoff=RAT.wp.cold
41561
+ uncontrolled=true
41562
+ end
41563
+ local successful=self:_ModifySpawnTemplate(waypoints,livery,_lastpos,departure,takeoff,parkingdata,uncontrolled)
41348
41564
  if not successful then
41349
41565
  return nil
41350
41566
  end
41351
41567
  local group=self:SpawnWithIndex(self.SpawnIndex)
41568
+ local groupname=group:GetName()
41569
+ local flightgroup=FLIGHTGROUP:New(group)
41570
+ if self.ATCswitch then
41571
+ flightgroup.holdtime=nil
41572
+ end
41573
+ flightgroup.stuckDespawn=false
41352
41574
  self.alive=self.alive+1
41353
- self:T(RAT.id..string.format("Alive groups counter now = %d.",self.alive))
41575
+ self:T(self.lid..string.format("Alive groups counter now = %d.",self.alive))
41354
41576
  if self.ATCswitch and landing==RAT.wp.landing then
41577
+ local airbasename=destination:GetName()
41355
41578
  if self.returnzone then
41356
- self:_ATCAddFlight(group:GetName(),departure:GetName())
41357
- else
41358
- self:_ATCAddFlight(group:GetName(),destination:GetName())
41579
+ airbasename=departure:GetName()
41580
+ end
41581
+ if not self:_IsFlightControlAirbase(airbasename)then
41582
+ self:_ATCAddFlight(groupname,airbasename)
41359
41583
  end
41360
41584
  end
41361
41585
  if self.placemarkers then
41362
- self:_PlaceMarkers(waypoints,self.SpawnIndex)
41586
+ self:_PlaceMarkers(waypoints,wpdesc,self.SpawnIndex)
41587
+ end
41588
+ if isFlightcontrol and not self.activate_uncontrolled then
41589
+ local N=math.random(120)
41590
+ self:T(self.lid..string.format("Flight will be ready for takeoff in %d seconds",N))
41591
+ flightgroup:SetReadyForTakeoff(true,N)
41363
41592
  end
41364
41593
  if self.invisible then
41365
- self:_CommandInvisible(group,true)
41594
+ flightgroup:SetDefaultInvisible(true)
41595
+ flightgroup:SwitchInvisible(true)
41366
41596
  end
41367
41597
  if self.immortal then
41368
- self:_CommandImmortal(group,true)
41598
+ flightgroup:SetDefaultImmortal(true)
41599
+ flightgroup:SwitchImmortal(true)
41369
41600
  end
41370
41601
  if self.eplrs then
41371
- group:CommandEPLRS(true,1)
41372
- end
41373
- self:_SetROE(group,self.roe)
41374
- self:_SetROT(group,self.rot)
41375
- self.ratcraft[self.SpawnIndex]={}
41376
- self.ratcraft[self.SpawnIndex]["group"]=group
41377
- self.ratcraft[self.SpawnIndex]["destination"]=destination
41378
- self.ratcraft[self.SpawnIndex]["departure"]=departure
41379
- self.ratcraft[self.SpawnIndex]["waypoints"]=waypoints
41380
- self.ratcraft[self.SpawnIndex]["airborne"]=group:InAir()
41381
- self.ratcraft[self.SpawnIndex]["nunits"]=group:GetInitialSize()
41382
- if group:InAir()then
41383
- self.ratcraft[self.SpawnIndex]["Tground"]=nil
41384
- self.ratcraft[self.SpawnIndex]["Pground"]=nil
41385
- self.ratcraft[self.SpawnIndex]["Uground"]=nil
41386
- self.ratcraft[self.SpawnIndex]["Tlastcheck"]=nil
41387
- else
41388
- self.ratcraft[self.SpawnIndex]["Tground"]=timer.getTime()
41389
- self.ratcraft[self.SpawnIndex]["Pground"]=group:GetCoordinate()
41390
- self.ratcraft[self.SpawnIndex]["Uground"]={}
41391
- for _,_unit in pairs(group:GetUnits())do
41392
- local _unitname=_unit:GetName()
41393
- self.ratcraft[self.SpawnIndex]["Uground"][_unitname]=_unit:GetCoordinate()
41394
- end
41395
- self.ratcraft[self.SpawnIndex]["Tlastcheck"]=timer.getTime()
41396
- end
41397
- self.ratcraft[self.SpawnIndex]["P0"]=group:GetCoordinate()
41398
- self.ratcraft[self.SpawnIndex]["Pnow"]=group:GetCoordinate()
41399
- self.ratcraft[self.SpawnIndex]["Distance"]=0
41400
- self.ratcraft[self.SpawnIndex].takeoff=takeoff
41401
- self.ratcraft[self.SpawnIndex].landing=landing
41402
- self.ratcraft[self.SpawnIndex].wpholding=WPholding
41403
- self.ratcraft[self.SpawnIndex].wpfinal=WPfinal
41404
- self.ratcraft[self.SpawnIndex].active=not self.uncontrolled
41405
- self.ratcraft[self.SpawnIndex]["status"]=RAT.status.Spawned
41406
- self.ratcraft[self.SpawnIndex].livery=livery
41407
- self.ratcraft[self.SpawnIndex].despawnme=false
41408
- self.ratcraft[self.SpawnIndex].nrespawn=nrespawn
41602
+ flightgroup:SetDefaultEPLRS(true)
41603
+ flightgroup:SwitchEPLRS(true)
41604
+ end
41605
+ self:_SetROE(flightgroup,self.roe)
41606
+ self:_SetROT(flightgroup,self.rot)
41607
+ local ratcraft={}
41608
+ ratcraft.index=self.SpawnIndex
41609
+ ratcraft.group=group
41610
+ ratcraft.flightgroup=flightgroup
41611
+ ratcraft.destination=destination
41612
+ ratcraft.departure=departure
41613
+ ratcraft.waypoints=waypoints
41614
+ ratcraft.airborne=group:InAir()
41615
+ ratcraft.nunits=group:GetInitialSize()
41616
+ ratcraft.Pnow=group:GetCoordinate()
41617
+ ratcraft.Distance=0
41618
+ ratcraft.takeoff=takeoff
41619
+ ratcraft.landing=landing
41620
+ ratcraft.wpdesc=wpdesc
41621
+ ratcraft.wpstatus=wpstatus
41622
+ ratcraft.active=not uncontrolled
41623
+ ratcraft.status=RAT.status.Spawned
41624
+ ratcraft.livery=livery
41625
+ ratcraft.despawnme=false
41626
+ ratcraft.nrespawn=nrespawn
41627
+ self.ratcraft[self.SpawnIndex]=ratcraft
41409
41628
  if self.f10menu then
41410
41629
  local name=self.aircraft.type.." ID "..tostring(self.SpawnIndex)
41411
41630
  self.Menu[self.SubMenuName].groups[self.SpawnIndex]=MENU_MISSION:New(name,self.Menu[self.SubMenuName].groups)
41412
41631
  self.Menu[self.SubMenuName].groups[self.SpawnIndex]["roe"]=MENU_MISSION:New("Set ROE",self.Menu[self.SubMenuName].groups[self.SpawnIndex])
41413
- MENU_MISSION_COMMAND:New("Weapons hold",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["roe"],self._SetROE,self,group,RAT.ROE.weaponhold)
41414
- MENU_MISSION_COMMAND:New("Weapons free",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["roe"],self._SetROE,self,group,RAT.ROE.weaponfree)
41415
- MENU_MISSION_COMMAND:New("Return fire",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["roe"],self._SetROE,self,group,RAT.ROE.returnfire)
41632
+ MENU_MISSION_COMMAND:New("Weapons hold",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["roe"],self._SetROE,self,flightgroup,RAT.ROE.weaponhold)
41633
+ MENU_MISSION_COMMAND:New("Weapons free",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["roe"],self._SetROE,self,flightgroup,RAT.ROE.weaponfree)
41634
+ MENU_MISSION_COMMAND:New("Return fire",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["roe"],self._SetROE,self,flightgroup,RAT.ROE.returnfire)
41416
41635
  self.Menu[self.SubMenuName].groups[self.SpawnIndex]["rot"]=MENU_MISSION:New("Set ROT",self.Menu[self.SubMenuName].groups[self.SpawnIndex])
41417
- MENU_MISSION_COMMAND:New("No reaction",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["rot"],self._SetROT,self,group,RAT.ROT.noreaction)
41418
- MENU_MISSION_COMMAND:New("Passive defense",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["rot"],self._SetROT,self,group,RAT.ROT.passive)
41419
- MENU_MISSION_COMMAND:New("Evade on fire",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["rot"],self._SetROT,self,group,RAT.ROT.evade)
41636
+ MENU_MISSION_COMMAND:New("No reaction",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["rot"],self._SetROT,self,flightgroup,RAT.ROT.noreaction)
41637
+ MENU_MISSION_COMMAND:New("Passive defense",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["rot"],self._SetROT,self,flightgroup,RAT.ROT.passive)
41638
+ MENU_MISSION_COMMAND:New("Evade on fire",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["rot"],self._SetROT,self,flightgroup,RAT.ROT.evade)
41420
41639
  MENU_MISSION_COMMAND:New("Despawn group",self.Menu[self.SubMenuName].groups[self.SpawnIndex],self._Despawn,self,group)
41421
41640
  MENU_MISSION_COMMAND:New("Place markers",self.Menu[self.SubMenuName].groups[self.SpawnIndex],self._PlaceMarkers,self,waypoints,self.SpawnIndex)
41422
41641
  MENU_MISSION_COMMAND:New("Status report",self.Menu[self.SubMenuName].groups[self.SpawnIndex],self.Status,self,true,self.SpawnIndex)
41423
41642
  end
41643
+ function flightgroup.OnAfterPassingWaypoint(Flightgroup,From,Event,To,Waypoint)
41644
+ local waypoint=Waypoint
41645
+ local flightgroup=Flightgroup
41646
+ local wpid=waypoint.uid
41647
+ local ratcraft=self:_GetRatcraftFromGroup(flightgroup.group)
41648
+ local wpdescription=tostring(ratcraft.wpdesc[wpid])
41649
+ local wpstatus=ratcraft.wpstatus[wpid]
41650
+ self:T(self.lid..string.format("RAT passed waypoint %s [uid=%d]: %s [status=%s]",waypoint.name,wpid,wpdescription,wpstatus))
41651
+ self:_SetStatus(group,wpstatus)
41652
+ if waypoint.uid==3 then
41653
+ end
41654
+ end
41655
+ function flightgroup.OnAfterPassedFinalWaypoint(flightgroup,From,Event,To)
41656
+ self:T(self.lid..string.format("RAT passed FINAL waypoint"))
41657
+ local ratcraft=self:_GetRatcraftFromGroup(flightgroup.group)
41658
+ local text=string.format("Flight %s arrived at final destination %s.",group:GetName(),destination:GetName())
41659
+ MESSAGE:New(text,10):ToAllIf(self.reportstatus)
41660
+ self:T(self.lid..text)
41661
+ if landing==RAT.wp.air then
41662
+ local text=string.format("Activating despawn switch for flight %s! Group will be detroyed soon.",group:GetName())
41663
+ MESSAGE:New(text,10):ToAllIf(self.Debug)
41664
+ self:T(self.lid..text)
41665
+ ratcraft.despawnme=true
41666
+ end
41667
+ end
41668
+ function flightgroup.OnAfterRTB(flightgroup,From,Event,To,airbase,SpeedTo,SpeedHold,SpeedLand)
41669
+ self:T(self.lid..string.format("RAT group is RTB"))
41670
+ end
41671
+ function flightgroup.OnAfterHolding(Flightgroup,From,Event,To)
41672
+ local flightgroup=Flightgroup
41673
+ local ratcraft=self:_GetRatcraftFromGroup(flightgroup.group)
41674
+ local destinationname=ratcraft.destination:GetName()
41675
+ local text=string.format("Flight %s to %s ATC: Holding and awaiting landing clearance.",groupname,destinationname)
41676
+ self:T(self.lid..text)
41677
+ MESSAGE:New(text,10):ToAllIf(self.reportstatus)
41678
+ local fc=_DATABASE:GetFlightControl(destinationname)
41679
+ if self.ATCswitch and not fc then
41680
+ self:T(self.lid..string.format("RAT group is HOLDING ==> ATCRegisterFlight"))
41681
+ if self.f10menu then
41682
+ MENU_MISSION_COMMAND:New("Clear for landing",self.Menu[self.SubMenuName].groups[self.SpawnIndex],flightgroup.ClearToLand,flightgroup)
41683
+ end
41684
+ RAT._ATCRegisterFlight(groupname,timer.getTime())
41685
+ end
41686
+ end
41687
+ function flightgroup.OnAfterLanded(Flightgroup,From,Event,To,Airport)
41688
+ self:T(self.lid..string.format("RAT group landed at airbase"))
41689
+ end
41690
+ function flightgroup.OnAfterArrived(Flightgroup,From,Event,To)
41691
+ self:T(self.lid..string.format("RAT group arrived"))
41692
+ end
41693
+ function flightgroup.OnAfterStuck(Flightgroup,From,Event,To,Stucktime)
41694
+ local flightgroup=Flightgroup
41695
+ self:T(self.lid..string.format("Group %s got stuck for %d seconds",flightgroup:GetName(),Stucktime))
41696
+ if Stucktime>10*60 then
41697
+ self:_Respawn(flightgroup.group)
41698
+ end
41699
+ end
41424
41700
  return self.SpawnIndex
41425
41701
  end
41702
+ function RAT:_IsFlightControlAirbase(airbase)
41703
+ if type(airbase)=="table"then
41704
+ airbase=airbase:GetName()
41705
+ end
41706
+ if airbase then
41707
+ local fc=_DATABASE:GetFlightControl(airbase)
41708
+ if fc then
41709
+ self:T(self.lid..string.format("Airbase %s has a FLIGHTCONTROL running",airbase))
41710
+ return true
41711
+ else
41712
+ return false
41713
+ end
41714
+ end
41715
+ return nil
41716
+ end
41426
41717
  function RAT:ClearForLanding(name)
41427
41718
  trigger.action.setUserFlag(name,1)
41428
41719
  local flagvalue=trigger.misc.getUserFlag(name)
41429
- self:T(RAT.id.."ATC: User flag value (landing) for "..name.." set to "..flagvalue)
41430
- end
41431
- function RAT:_Respawn(index,lastpos,delay)
41432
- local departure=self.ratcraft[index].departure
41433
- local destination=self.ratcraft[index].destination
41434
- local takeoff=self.ratcraft[index].takeoff
41435
- local landing=self.ratcraft[index].landing
41436
- local livery=self.ratcraft[index].livery
41437
- local lastwp=self.ratcraft[index].waypoints[#self.ratcraft[index].waypoints]
41720
+ self:T(self.lid.."ATC: User flag value (landing) for "..name.." set to "..flagvalue)
41721
+ end
41722
+ function RAT:_Respawn(group,lastpos,delay)
41723
+ if delay and delay>0 then
41724
+ self:ScheduleOnce(delay,RAT._Respawn,self,group,lastpos,0)
41725
+ else
41726
+ if group then
41727
+ self:T(self.lid..string.format("Respawning ratcraft from group %s",group:GetName()))
41728
+ else
41729
+ self:E(self.lid..string.format("ERROR: group is nil in _Respawn!"))
41730
+ return nil
41731
+ end
41732
+ local ratcraft=self:_GetRatcraftFromGroup(group)
41733
+ lastpos=lastpos or group:GetCoordinate()
41734
+ local departure=ratcraft.departure
41735
+ local destination=ratcraft.destination
41736
+ local takeoff=ratcraft.takeoff
41737
+ local landing=ratcraft.landing
41738
+ local livery=ratcraft.livery
41739
+ local lastwp=ratcraft.waypoints[#ratcraft.waypoints]
41740
+ local flightgroup=ratcraft.flightgroup
41741
+ local parkingdata=nil
41742
+ if self.continuejourney or self.commute then
41743
+ for _,_element in pairs(flightgroup.elements)do
41744
+ local element=_element
41745
+ if element.parking then
41746
+ if parkingdata==nil then
41747
+ parkingdata={}
41748
+ end
41749
+ self:T(self.lid..string.format("Element %s was parking at spot id=%d",element.name,element.parking.TerminalID))
41750
+ table.insert(parkingdata,UTILS.DeepCopy(element.parking))
41751
+ else
41752
+ self:E(self.lid..string.format("WARNING: Element %s did NOT have a not parking spot!",tostring(element.name)))
41753
+ end
41754
+ end
41755
+ end
41756
+ self:_Despawn(ratcraft.group)
41438
41757
  local _departure=nil
41439
41758
  local _destination=nil
41440
41759
  local _takeoff=nil
@@ -41445,7 +41764,7 @@ local _lastpos=nil
41445
41764
  if self.continuejourney then
41446
41765
  _departure=destination:GetName()
41447
41766
  _livery=livery
41448
- if landing==RAT.wp.landing and lastpos and not(self.respawn_at_landing or self.respawn_after_takeoff)then
41767
+ if landing==RAT.wp.landing and not(self.respawn_at_landing or self.respawn_after_takeoff)then
41449
41768
  if destination:GetCategory()==4 then
41450
41769
  _lastpos=lastpos
41451
41770
  end
@@ -41508,28 +41827,31 @@ if _takeoff==RAT.wp.air and(self.continuejourney or self.commute)then
41508
41827
  _lastwp=lastwp
41509
41828
  end
41510
41829
  self:T2({departure=_departure,destination=_destination,takeoff=_takeoff,landing=_landing,livery=_livery,lastwp=_lastwp})
41511
- local respawndelay
41512
- if delay then
41513
- respawndelay=delay
41514
- elseif self.respawn_delay then
41515
- respawndelay=self.respawn_delay+3
41516
- else
41517
- respawndelay=3
41518
- end
41519
- local arg={}
41520
- arg.self=self
41521
- arg.departure=_departure
41522
- arg.destination=_destination
41523
- arg.takeoff=_takeoff
41524
- arg.landing=_landing
41525
- arg.livery=_livery
41526
- arg.lastwp=_lastwp
41527
- arg.lastpos=_lastpos
41528
- self:T(RAT.id..string.format("%s delayed respawn in %.1f seconds.",self.alias,respawndelay))
41529
- SCHEDULER:New(nil,self._SpawnWithRouteTimer,{arg},respawndelay)
41530
- end
41531
- function RAT._SpawnWithRouteTimer(arg)
41532
- RAT._SpawnWithRoute(arg.self,arg.departure,arg.destination,arg.takeoff,arg.landing,arg.livery,arg.lastwp,arg.lastpos)
41830
+ local respawndelay=self.respawn_delay or 1
41831
+ self:T(self.lid..string.format("%s delayed respawn in %.1f seconds.",self.alias,respawndelay))
41832
+ self:ScheduleOnce(respawndelay,RAT._SpawnWithRoute,self,_departure,_destination,_takeoff,_landing,_livery,nil,_lastpos,nil,parkingdata)
41833
+ end
41834
+ end
41835
+ function RAT:_Despawn(group,delay)
41836
+ if delay and delay>0 then
41837
+ self:ScheduleOnce(delay,RAT._Despawn,self,group,0)
41838
+ else
41839
+ if group then
41840
+ local index=self:GetSpawnIndexFromGroup(group)
41841
+ if index then
41842
+ self:T(self.lid..string.format("Despawning group %s (index=%d)",group:GetName(),index))
41843
+ local ratcraft=self.ratcraft[index]
41844
+ ratcraft.flightgroup:Despawn()
41845
+ ratcraft.flightgroup:__Stop(0.1)
41846
+ self.ratcraft[index].group=nil
41847
+ self.ratcraft[index]["status"]="Dead"
41848
+ self.ratcraft[index]=nil
41849
+ if self.f10menu and self.SubMenuName~=nil then
41850
+ self.Menu[self.SubMenuName]["groups"][index]:Remove()
41851
+ end
41852
+ end
41853
+ end
41854
+ end
41533
41855
  end
41534
41856
  function RAT:_SetRoute(takeoff,landing,_departure,_destination,_waypoint)
41535
41857
  local VxCruiseMax
@@ -41559,7 +41881,7 @@ elseif self:_ZoneExists(_departure)then
41559
41881
  departure=ZONE:FindByName(_departure)
41560
41882
  else
41561
41883
  local text=string.format("ERROR! Specified departure airport %s does not exist for %s.",_departure,self.alias)
41562
- self:E(RAT.id..text)
41884
+ self:E(self.lid..text)
41563
41885
  end
41564
41886
  else
41565
41887
  departure=self:_PickDeparture(takeoff)
@@ -41569,7 +41891,7 @@ end
41569
41891
  end
41570
41892
  if not departure then
41571
41893
  local text=string.format("ERROR! No valid departure airport could be found for %s.",self.alias)
41572
- self:E(RAT.id..text)
41894
+ self:E(self.lid..text)
41573
41895
  return nil
41574
41896
  end
41575
41897
  local Pdeparture
@@ -41617,7 +41939,7 @@ mindist=Dtot
41617
41939
  end
41618
41940
  mindist=math.max(self.mindist,mindist)
41619
41941
  local text=string.format("Adjusting min distance to %d km (for given min FL%03d)",mindist/1000,self.FLminuser/RAT.unit.FL2m)
41620
- self:T(RAT.id..text)
41942
+ self:T(self.lid..text)
41621
41943
  end
41622
41944
  local destination=nil
41623
41945
  if _destination then
@@ -41630,7 +41952,7 @@ elseif self:_ZoneExists(_destination)then
41630
41952
  destination=ZONE:FindByName(_destination)
41631
41953
  else
41632
41954
  local text=string.format("ERROR: Specified destination airport/zone %s does not exist for %s!",_destination,self.alias)
41633
- self:E(RAT.id.."ERROR: "..text)
41955
+ self:E(self.lid.."ERROR: "..text)
41634
41956
  end
41635
41957
  else
41636
41958
  local random=self.random_destination
@@ -41648,13 +41970,13 @@ end
41648
41970
  if not destination then
41649
41971
  local text=string.format("No valid destination airport could be found for %s!",self.alias)
41650
41972
  MESSAGE:New(text,60):ToAll()
41651
- self:E(RAT.id.."ERROR: "..text)
41973
+ self:E(self.lid.."ERROR: "..text)
41652
41974
  return nil
41653
41975
  end
41654
41976
  if destination:GetName()==departure:GetName()then
41655
41977
  local text=string.format("%s: Destination and departure are identical. Airport/zone %s.",self.alias,destination:GetName())
41656
41978
  MESSAGE:New(text,30):ToAll()
41657
- self:E(RAT.id.."ERROR: "..text)
41979
+ self:E(self.lid.."ERROR: "..text)
41658
41980
  end
41659
41981
  local Preturn
41660
41982
  local destination_returnzone
@@ -41835,93 +42157,90 @@ text=text..string.format("h_climb_max = %6.1f m\n",h_climb_max)
41835
42157
  text=text..string.format("h_descent_max = %6.1f m\n",h_descent_max)
41836
42158
  end
41837
42159
  text=text..string.format("******************************************************\n")
41838
- self:T2(RAT.id..text)
42160
+ self:T2(self.lid..text)
41839
42161
  if d_cruise<0 then
41840
42162
  d_cruise=100
41841
42163
  end
41842
42164
  local wp={}
41843
42165
  local c={}
42166
+ local waypointdescriptions={}
42167
+ local waypointstatus={}
41844
42168
  local wpholding=nil
41845
42169
  local wpfinal=nil
41846
42170
  c[#c+1]=Pdeparture
41847
42171
  wp[#wp+1]=self:_Waypoint(#wp+1,"Departure",takeoff,c[#wp+1],VxClimb,H_departure,departure)
41848
- self.waypointdescriptions[#wp]="Departure"
41849
- self.waypointstatus[#wp]=RAT.status.Departure
42172
+ waypointdescriptions[#wp]="Departure"
42173
+ waypointstatus[#wp]=RAT.status.Departure
41850
42174
  if takeoff==RAT.wp.air then
41851
42175
  if d_climb<5000 or d_cruise<5000 then
41852
42176
  d_cruise=d_cruise+d_climb
41853
42177
  else
41854
42178
  c[#c+1]=c[#c]:Translate(d_climb,heading)
41855
42179
  wp[#wp+1]=self:_Waypoint(#wp+1,"Begin of Cruise",RAT.wp.cruise,c[#wp+1],VxCruise,FLcruise)
41856
- self.waypointdescriptions[#wp]="Begin of Cruise"
41857
- self.waypointstatus[#wp]=RAT.status.Cruise
42180
+ waypointdescriptions[#wp]="Begin of Cruise"
42181
+ waypointstatus[#wp]=RAT.status.Cruise
41858
42182
  end
41859
42183
  else
41860
42184
  c[#c+1]=c[#c]:Translate(d_climb/2,heading)
41861
42185
  c[#c+1]=c[#c]:Translate(d_climb/2,heading)
41862
42186
  wp[#wp+1]=self:_Waypoint(#wp+1,"Climb",RAT.wp.climb,c[#wp+1],VxClimb,H_departure+(FLcruise-H_departure)/2)
41863
- self.waypointdescriptions[#wp]="Climb"
41864
- self.waypointstatus[#wp]=RAT.status.Climb
42187
+ waypointdescriptions[#wp]="Climb"
42188
+ waypointstatus[#wp]=RAT.status.Climb
41865
42189
  wp[#wp+1]=self:_Waypoint(#wp+1,"Begin of Cruise",RAT.wp.cruise,c[#wp+1],VxCruise,FLcruise)
41866
- self.waypointdescriptions[#wp]="Begin of Cruise"
41867
- self.waypointstatus[#wp]=RAT.status.Cruise
42190
+ waypointdescriptions[#wp]="Begin of Cruise"
42191
+ waypointstatus[#wp]=RAT.status.Cruise
41868
42192
  end
41869
42193
  if self.returnzone then
41870
42194
  c[#c+1]=Preturn
41871
42195
  wp[#wp+1]=self:_Waypoint(#wp+1,"Return Zone",RAT.wp.cruise,c[#wp+1],VxCruise,FLcruise)
41872
- self.waypointdescriptions[#wp]="Return Zone"
41873
- self.waypointstatus[#wp]=RAT.status.Uturn
42196
+ waypointdescriptions[#wp]="Return Zone"
42197
+ waypointstatus[#wp]=RAT.status.Uturn
41874
42198
  end
41875
42199
  if landing==RAT.wp.air then
41876
42200
  c[#c+1]=Pdestination
41877
42201
  wp[#wp+1]=self:_Waypoint(#wp+1,"Final Destination",RAT.wp.finalwp,c[#wp+1],VxCruise,FLcruise)
41878
- self.waypointdescriptions[#wp]="Final Destination"
41879
- self.waypointstatus[#wp]=RAT.status.Destination
42202
+ waypointdescriptions[#wp]="Final Destination"
42203
+ waypointstatus[#wp]=RAT.status.Destination
41880
42204
  elseif self.returnzone then
41881
42205
  c[#c+1]=c[#c]:Translate(d_cruise/2,heading-180)
41882
42206
  wp[#wp+1]=self:_Waypoint(#wp+1,"End of Cruise",RAT.wp.cruise,c[#wp+1],VxCruise,FLcruise)
41883
- self.waypointdescriptions[#wp]="End of Cruise"
41884
- self.waypointstatus[#wp]=RAT.status.Descent
42207
+ waypointdescriptions[#wp]="End of Cruise"
42208
+ waypointstatus[#wp]=RAT.status.Descent
41885
42209
  else
41886
42210
  c[#c+1]=c[#c]:Translate(d_cruise,heading)
41887
42211
  wp[#wp+1]=self:_Waypoint(#wp+1,"End of Cruise",RAT.wp.cruise,c[#wp+1],VxCruise,FLcruise)
41888
- self.waypointdescriptions[#wp]="End of Cruise"
41889
- self.waypointstatus[#wp]=RAT.status.Descent
42212
+ waypointdescriptions[#wp]="End of Cruise"
42213
+ waypointstatus[#wp]=RAT.status.Descent
41890
42214
  end
41891
42215
  if landing==RAT.wp.landing then
41892
42216
  if self.returnzone then
41893
42217
  c[#c+1]=c[#c]:Translate(d_descent/2,heading-180)
41894
42218
  wp[#wp+1]=self:_Waypoint(#wp+1,"Descent",RAT.wp.descent,c[#wp+1],VxDescent,FLcruise-(FLcruise-(h_holding+H_holding))/2)
41895
- self.waypointdescriptions[#wp]="Descent"
41896
- self.waypointstatus[#wp]=RAT.status.DescentHolding
42219
+ waypointdescriptions[#wp]="Descent"
42220
+ waypointstatus[#wp]=RAT.status.DescentHolding
41897
42221
  else
41898
42222
  c[#c+1]=c[#c]:Translate(d_descent/2,heading)
41899
42223
  wp[#wp+1]=self:_Waypoint(#wp+1,"Descent",RAT.wp.descent,c[#wp+1],VxDescent,FLcruise-(FLcruise-(h_holding+H_holding))/2)
41900
- self.waypointdescriptions[#wp]="Descent"
41901
- self.waypointstatus[#wp]=RAT.status.DescentHolding
42224
+ waypointdescriptions[#wp]="Descent"
42225
+ waypointstatus[#wp]=RAT.status.DescentHolding
41902
42226
  end
41903
42227
  end
41904
42228
  if landing==RAT.wp.landing then
41905
- c[#c+1]=Pholding
41906
- wp[#wp+1]=self:_Waypoint(#wp+1,"Holding Point",RAT.wp.holding,c[#wp+1],VxHolding,H_holding+h_holding)
41907
- self.waypointdescriptions[#wp]="Holding Point"
41908
- self.waypointstatus[#wp]=RAT.status.Holding
41909
- wpholding=#wp
41910
42229
  c[#c+1]=Pdestination
41911
42230
  wp[#wp+1]=self:_Waypoint(#wp+1,"Final Destination",landing,c[#wp+1],VxFinal,H_destination,destination)
41912
- self.waypointdescriptions[#wp]="Final Destination"
41913
- self.waypointstatus[#wp]=RAT.status.Destination
42231
+ waypointdescriptions[#wp]="Final Destination"
42232
+ waypointstatus[#wp]=RAT.status.Destination
41914
42233
  end
41915
42234
  wpfinal=#wp
41916
42235
  local waypoints={}
41917
42236
  for _,p in ipairs(wp)do
41918
42237
  table.insert(waypoints,p)
41919
42238
  end
41920
- self:_Routeinfo(waypoints,"Waypoint info in set_route:")
42239
+ self:_Routeinfo(waypoints,"Waypoint info in set_route:",waypointdescriptions)
41921
42240
  if self.returnzone then
41922
- return departure,destination_returnzone,waypoints,wpholding,wpfinal
42241
+ return departure,destination_returnzone,waypoints,waypointdescriptions,waypointstatus
41923
42242
  else
41924
- return departure,destination,waypoints,wpholding,wpfinal
42243
+ return departure,destination,waypoints,waypointdescriptions,waypointstatus
41925
42244
  end
41926
42245
  end
41927
42246
  function RAT:_PickDeparture(takeoff)
@@ -41964,17 +42283,17 @@ elseif self:_ZoneExists(name)then
41964
42283
  if takeoff==RAT.wp.air then
41965
42284
  dep=ZONE:FindByName(name)
41966
42285
  else
41967
- self:E(RAT.id..string.format("ERROR! Takeoff is not in air. Cannot use %s as departure.",name))
42286
+ self:E(self.lid..string.format("ERROR! Takeoff is not in air. Cannot use %s as departure.",name))
41968
42287
  end
41969
42288
  else
41970
- self:E(RAT.id..string.format("ERROR: No airport or zone found with name %s.",name))
42289
+ self:E(self.lid..string.format("ERROR: No airport or zone found with name %s.",name))
41971
42290
  end
41972
42291
  if dep then
41973
42292
  table.insert(departures,dep)
41974
42293
  end
41975
42294
  end
41976
42295
  end
41977
- self:T(RAT.id..string.format("Number of possible departures for %s= %d",self.alias,#departures))
42296
+ self:T(self.lid..string.format("Number of possible departures for %s= %d",self.alias,#departures))
41978
42297
  local departure=departures[math.random(#departures)]
41979
42298
  local text
41980
42299
  if departure and departure:GetName()then
@@ -41983,9 +42302,9 @@ text=string.format("%s: Chosen departure zone: %s",self.alias,departure:GetName(
41983
42302
  else
41984
42303
  text=string.format("%s: Chosen departure airport: %s (ID %d)",self.alias,departure:GetName(),departure:GetID())
41985
42304
  end
41986
- self:T(RAT.id..text)
42305
+ self:T(self.lid..text)
41987
42306
  else
41988
- self:E(RAT.id..string.format("ERROR! No departure airport or zone found for %s.",self.alias))
42307
+ self:E(self.lid..string.format("ERROR! No departure airport or zone found for %s.",self.alias))
41989
42308
  departure=nil
41990
42309
  end
41991
42310
  return departure
@@ -42036,10 +42355,10 @@ elseif self:_ZoneExists(name)then
42036
42355
  if landing==RAT.wp.air then
42037
42356
  dest=ZONE:FindByName(name)
42038
42357
  else
42039
- self:E(RAT.id..string.format("ERROR! Landing is not in air. Cannot use zone %s as destination!",name))
42358
+ self:E(self.lid..string.format("ERROR! Landing is not in air. Cannot use zone %s as destination!",name))
42040
42359
  end
42041
42360
  else
42042
- self:E(RAT.id..string.format("ERROR! No airport or zone found with name %s",name))
42361
+ self:E(self.lid..string.format("ERROR! No airport or zone found with name %s",name))
42043
42362
  end
42044
42363
  if dest then
42045
42364
  local distance=q:Get2DDistance(dest:GetCoordinate())
@@ -42047,13 +42366,13 @@ if distance>=minrange and distance<=maxrange then
42047
42366
  table.insert(destinations,dest)
42048
42367
  else
42049
42368
  local text=string.format("Destination %s is ouside range. Distance = %5.1f km, min = %5.1f km, max = %5.1f km.",name,distance,minrange,maxrange)
42050
- self:T(RAT.id..text)
42369
+ self:T(self.lid..text)
42051
42370
  end
42052
42371
  end
42053
42372
  end
42054
42373
  end
42055
42374
  end
42056
- self:T(RAT.id..string.format("Number of possible destinations = %s.",#destinations))
42375
+ self:T(self.lid..string.format("Number of possible destinations = %s.",#destinations))
42057
42376
  if#destinations>0 then
42058
42377
  local function compare(a,b)
42059
42378
  local qa=q:Get2DDistance(a:GetCoordinate())
@@ -42073,9 +42392,9 @@ text=string.format("%s: Chosen destination zone: %s.",self.alias,destination:Get
42073
42392
  else
42074
42393
  text=string.format("%s Chosen destination airport: %s (ID %d).",self.alias,destination:GetName(),destination:GetID())
42075
42394
  end
42076
- self:T(RAT.id..text)
42395
+ self:T(self.lid..text)
42077
42396
  else
42078
- self:E(RAT.id.."ERROR! No destination airport or zone found.")
42397
+ self:E(self.lid.."ERROR! No destination airport or zone found.")
42079
42398
  destination=nil
42080
42399
  end
42081
42400
  return destination
@@ -42127,9 +42446,9 @@ local _myab=AIRBASE:FindByName(_name)
42127
42446
  if _myab then
42128
42447
  table.insert(self.airports_map,_myab)
42129
42448
  local text="MOOSE: Airport ID = ".._myab:GetID().." and Name = ".._myab:GetName()..", Category = ".._myab:GetCategory()..", TypeName = ".._myab:GetTypeName()
42130
- self:T(RAT.id..text)
42449
+ self:T(self.lid..text)
42131
42450
  else
42132
- self:E(RAT.id..string.format("WARNING: Airbase %s does not exsist as MOOSE object!",tostring(_name)))
42451
+ self:E(self.lid..string.format("WARNING: Airbase %s does not exsist as MOOSE object!",tostring(_name)))
42133
42452
  end
42134
42453
  end
42135
42454
  end
@@ -42151,31 +42470,26 @@ end
42151
42470
  if#self.airports==0 then
42152
42471
  local text=string.format("No possible departure/destination airports found for RAT %s.",tostring(self.alias))
42153
42472
  MESSAGE:New(text,10):ToAll()
42154
- self:E(RAT.id..text)
42473
+ self:E(self.lid..text)
42155
42474
  end
42156
42475
  end
42157
42476
  function RAT:Status(message,forID)
42158
- if message==nil then
42159
- message=false
42160
- end
42161
- if forID==nil then
42162
- forID=false
42163
- end
42477
+ self:T(self.lid.."Checking status")
42164
42478
  local Tnow=timer.getTime()
42165
42479
  local nalive=0
42166
- for spawnindex,ratcraft in ipairs(self.ratcraft)do
42480
+ for spawnindex,_ratcraft in pairs(self.ratcraft)do
42481
+ local ratcraft=_ratcraft
42482
+ self:T(self.lid..string.format("Ratcraft Index=%s",tostring(spawnindex)))
42167
42483
  local group=ratcraft.group
42168
- if group and group:IsAlive()and(group:GetCoordinate()or group:GetVec3())then
42484
+ if group and group:IsAlive()then
42169
42485
  nalive=nalive+1
42486
+ self:T(self.lid..string.format("Ratcraft Index=%s is ALIVE",tostring(spawnindex)))
42170
42487
  local prefix=self:_GetPrefixFromGroup(group)
42171
42488
  local life=self:_GetLife(group)
42172
42489
  local fuel=group:GetFuel()*100.0
42173
42490
  local airborne=group:InAir()
42174
- local coords=group:GetCoordinate()or group:GetVec3()
42175
- local alt=1000
42176
- if coords then
42177
- alt=coords.y or 1000
42178
- end
42491
+ local coords=group:GetCoordinate()
42492
+ local alt=coords~=nil and coords.y or 1000
42179
42493
  local departure=ratcraft.departure:GetName()
42180
42494
  local destination=ratcraft.destination:GetName()
42181
42495
  local type=self.aircraft.type
@@ -42183,52 +42497,16 @@ local status=ratcraft.status
42183
42497
  local active=ratcraft.active
42184
42498
  local Nunits=ratcraft.nunits
42185
42499
  local N0units=group:GetInitialSize()
42186
- local Tg=0
42187
- local Dg=0
42188
- local dTlast=0
42189
- local stationary=false
42190
- if airborne then
42191
- ratcraft["Tground"]=nil
42192
- ratcraft["Pground"]=nil
42193
- ratcraft["Uground"]=nil
42194
- ratcraft["Tlastcheck"]=nil
42195
- else
42196
- if ratcraft["Tground"]then
42197
- Tg=Tnow-ratcraft["Tground"]
42198
- Dg=coords:Get2DDistance(ratcraft["Pground"])
42199
- dTlast=Tnow-ratcraft["Tlastcheck"]
42200
- if dTlast>self.Tinactive then
42201
- for _,_unit in pairs(group:GetUnits())do
42202
- if _unit and _unit:IsAlive()then
42203
- local unitname=_unit:GetName()
42204
- local unitcoord=_unit:GetCoordinate()
42205
- local Ug=unitcoord:Get2DDistance(ratcraft.Uground[unitname])
42206
- self:T2(RAT.id..string.format("Unit %s travelled distance on ground %.1f m since %d seconds.",unitname,Ug,dTlast))
42207
- if Ug<50 and active and status~=RAT.status.EventBirth then
42208
- stationary=true
42209
- end
42210
- ratcraft["Uground"][unitname]=unitcoord
42211
- end
42212
- end
42213
- ratcraft["Tlastcheck"]=Tnow
42214
- ratcraft["Pground"]=coords
42215
- end
42216
- else
42217
- ratcraft["Tground"]=Tnow
42218
- ratcraft["Tlastcheck"]=Tnow
42219
- ratcraft["Pground"]=coords
42220
- ratcraft["Uground"]={}
42221
- for _,_unit in pairs(group:GetUnits())do
42222
- local unitname=_unit:GetName()
42223
- ratcraft.Uground[unitname]=_unit:GetCoordinate()
42500
+ local Dtravel=0
42501
+ if coords and ratcraft.Pnow then
42502
+ local Dtravel=coords:Get2DDistance(ratcraft.Pnow)
42503
+ ratcraft.Pnow=coords
42224
42504
  end
42505
+ ratcraft.Distance=ratcraft.Distance+Dtravel
42506
+ local Ddestination=-1
42507
+ if ratcraft.Pnow then
42508
+ Ddestination=ratcraft.Pnow:Get2DDistance(ratcraft.destination:GetCoordinate())
42225
42509
  end
42226
- end
42227
- local Pn=coords
42228
- local Dtravel=Pn:Get2DDistance(ratcraft["Pnow"])
42229
- ratcraft["Pnow"]=Pn
42230
- ratcraft["Distance"]=ratcraft["Distance"]+Dtravel
42231
- local Ddestination=Pn:Get2DDistance(ratcraft.destination:GetCoordinate())
42232
42510
  if(forID and spawnindex==forID)or(not forID)then
42233
42511
  local text=string.format("ID %i of flight %s",spawnindex,prefix)
42234
42512
  if N0units>1 then
@@ -42249,53 +42527,46 @@ text=text.." [airborne]\n"
42249
42527
  else
42250
42528
  text=text.." [on ground]\n"
42251
42529
  end
42252
- text=text..string.format("Fuel = %3.0f %%\n",fuel)
42253
- text=text..string.format("Life = %3.0f %%\n",life)
42254
- text=text..string.format("FL%03d = %i m ASL\n",alt/RAT.unit.FL2m,alt)
42255
- text=text..string.format("Distance travelled = %6.1f km\n",ratcraft["Distance"]/1000)
42256
- text=text..string.format("Distance to destination = %6.1f km",Ddestination/1000)
42257
- if not airborne then
42258
- text=text..string.format("\nTime on ground = %6.0f seconds\n",Tg)
42259
- text=text..string.format("Position change = %8.1f m since %3.0f seconds.",Dg,dTlast)
42260
- end
42261
- self:T(RAT.id..text)
42530
+ text=text..string.format("Fuel = %3.0f %%\n",fuel)
42531
+ text=text..string.format("Life = %3.0f %%\n",life)
42532
+ text=text..string.format("FL%03d = %i m ASL\n",alt/RAT.unit.FL2m,alt)
42533
+ text=text..string.format("Distance travelled = %6.1f km\n",ratcraft["Distance"]/1000)
42534
+ text=text..string.format("Distance to dest = %6.1f km",Ddestination/1000)
42535
+ self:T(self.lid..text)
42262
42536
  if message then
42263
42537
  MESSAGE:New(text,20):ToAll()
42264
42538
  end
42265
42539
  end
42266
- if not airborne then
42267
- if stationary then
42268
- local text=string.format("Group %s is despawned after being %d seconds inaktive on ground.",self.alias,dTlast)
42269
- self:T(RAT.id..text)
42270
- self:_Despawn(group)
42271
- end
42272
- if life<10 and Dtravel<100 then
42273
- local text=string.format("Damaged group %s is despawned. Life = %3.0f",self.alias,life)
42274
- self:T(RAT.id..text)
42275
- self:_Despawn(group)
42276
- end
42277
- end
42278
42540
  if ratcraft.despawnme then
42279
- local text=string.format("Flight %s will be despawned NOW!",self.alias)
42280
- self:T(RAT.id..text)
42281
- if(not self.norespawn)and(not self.respawn_after_takeoff)then
42282
- local idx=self:GetSpawnIndexFromGroup(group)
42283
- local coord=group:GetCoordinate()
42284
- self:_Respawn(idx,coord,0)
42285
- end
42541
+ if self.norespawn or self.respawn_after_takeoff then
42286
42542
  if self.despawnair then
42287
- self:_Despawn(group,0)
42543
+ self:T(self.lid..string.format("[STATUS despawnme] Flight %s will be despawned NOW and NO new group is created!",self.alias))
42544
+ self:_Despawn(group)
42545
+ end
42546
+ else
42547
+ self:T(self.lid..string.format("[STATUS despawnme] Flight %s will be despawned NOW and a new group is respawned!",self.alias))
42548
+ self:_Respawn(group)
42288
42549
  end
42289
42550
  end
42290
42551
  else
42291
- local text=string.format("Group does not exist in loop ratcraft status.")
42292
- self:T2(RAT.id..text)
42552
+ local text=string.format("Group does not exist in loop ratcraft status for spawn index=%d",spawnindex)
42553
+ self:T2(self.lid..text)
42554
+ self:T2(ratcraft)
42293
42555
  end
42294
42556
  end
42295
42557
  local text=string.format("Alive groups of %s: %d, nalive=%d/%d",self.alias,self.alive,nalive,self.ngroups)
42296
- self:T(RAT.id..text)
42558
+ self:T(self.lid..text)
42297
42559
  MESSAGE:New(text,20):ToAllIf(message and not forID)
42298
42560
  end
42561
+ function RAT:_RemoveRatcraft(ratcraft)
42562
+ self.ratcraft[ratcraft.index]=nil
42563
+ return self
42564
+ end
42565
+ function RAT:_GetRatcraftFromGroup(group)
42566
+ local index=self:GetSpawnIndexFromGroup(group)
42567
+ local ratcraft=self.ratcraft[index]
42568
+ return ratcraft
42569
+ end
42299
42570
  function RAT:_GetLife(group)
42300
42571
  local life=0.0
42301
42572
  if group and group:IsAlive()then
@@ -42303,48 +42574,56 @@ local unit=group:GetUnit(1)
42303
42574
  if unit then
42304
42575
  life=unit:GetLife()/unit:GetLife0()*100
42305
42576
  else
42306
- self:T2(RAT.id.."ERROR! Unit does not exist in RAT_Getlife(). Returning zero.")
42577
+ self:T2(self.lid.."ERROR! Unit does not exist in RAT_Getlife(). Returning zero.")
42307
42578
  end
42308
42579
  else
42309
- self:T2(RAT.id.."ERROR! Group does not exist in RAT_Getlife(). Returning zero.")
42580
+ self:T2(self.lid.."ERROR! Group does not exist in RAT_Getlife(). Returning zero.")
42310
42581
  end
42311
42582
  return life
42312
42583
  end
42313
42584
  function RAT:_SetStatus(group,status)
42314
42585
  if group and group:IsAlive()then
42315
- local index=self:GetSpawnIndexFromGroup(group)
42316
- if self.ratcraft[index]then
42317
- self.ratcraft[index].status=status
42586
+ local ratcraft=self:_GetRatcraftFromGroup(group)
42587
+ if ratcraft then
42588
+ ratcraft.status=status
42318
42589
  local no1=status==RAT.status.Departure
42319
42590
  local no2=status==RAT.status.EventBirthAir
42320
42591
  local no3=status==RAT.status.Holding
42321
- local text=string.format("Flight %s: %s.",group:GetName(),status)
42322
- self:T(RAT.id..text)
42592
+ local text=string.format("Flight %s: %s",group:GetName(),status)
42593
+ self:T(self.lid..text)
42323
42594
  if not(no1 or no2 or no3)then
42324
42595
  MESSAGE:New(text,10):ToAllIf(self.reportstatus)
42325
42596
  end
42326
42597
  end
42327
42598
  end
42328
42599
  end
42329
- function RAT:GetStatus(group)
42330
- if group and group:IsAlive()then
42600
+ function RAT:_GetRatcraftFromGroup(group)
42601
+ if group then
42331
42602
  local index=self:GetSpawnIndexFromGroup(group)
42332
42603
  if self.ratcraft[index]then
42333
- return self.ratcraft[index].status
42604
+ return self.ratcraft[index]
42605
+ end
42606
+ end
42607
+ return nil
42608
+ end
42609
+ function RAT:GetStatus(group)
42610
+ if group and group:IsAlive()then
42611
+ local ratcraft=self:_GetRatcraftFromGroup(group)
42612
+ if ratcraft then
42613
+ return ratcraft.status
42334
42614
  end
42335
42615
  end
42336
42616
  return"nonexistant"
42337
42617
  end
42338
42618
  function RAT:_OnBirth(EventData)
42339
42619
  self:F3(EventData)
42340
- self:T3(RAT.id.."Captured event birth!")
42620
+ self:T3(self.lid.."Captured event birth!")
42341
42621
  local SpawnGroup=EventData.IniGroup
42342
42622
  if SpawnGroup then
42343
42623
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42344
- if EventPrefix then
42345
- if EventPrefix==self.alias then
42624
+ if EventPrefix and EventPrefix==self.alias then
42346
42625
  local text="Event: Group "..SpawnGroup:GetName().." was born."
42347
- self:T(RAT.id..text)
42626
+ self:T(self.lid..text)
42348
42627
  local status="unknown in birth"
42349
42628
  if SpawnGroup:InAir()then
42350
42629
  status=RAT.status.EventBirthAir
@@ -42355,12 +42634,13 @@ status=RAT.status.EventBirth
42355
42634
  end
42356
42635
  self:_SetStatus(SpawnGroup,status)
42357
42636
  local i=self:GetSpawnIndexFromGroup(SpawnGroup)
42358
- local _departure=self.ratcraft[i].departure:GetName()
42359
- local _destination=self.ratcraft[i].destination:GetName()
42360
- local _nrespawn=self.ratcraft[i].nrespawn
42361
- local _takeoff=self.ratcraft[i].takeoff
42362
- local _landing=self.ratcraft[i].landing
42363
- local _livery=self.ratcraft[i].livery
42637
+ local ratcraft=self.ratcraft[i]
42638
+ local _departure=ratcraft.departure:GetName()
42639
+ local _destination=ratcraft.destination:GetName()
42640
+ local _nrespawn=ratcraft.nrespawn
42641
+ local _takeoff=ratcraft.takeoff
42642
+ local _landing=ratcraft.landing
42643
+ local _livery=ratcraft.livery
42364
42644
  local _airbase=AIRBASE:FindByName(_departure)
42365
42645
  local onrunway=false
42366
42646
  if _airbase then
@@ -42371,7 +42651,7 @@ end
42371
42651
  if onrunway then
42372
42652
  local text=string.format("ERROR: RAT group of %s was spawned on runway. Group #%d will be despawned immediately!",self.alias,i)
42373
42653
  MESSAGE:New(text,30):ToAllIf(self.Debug)
42374
- self:E(RAT.id..text)
42654
+ self:E(self.lid..text)
42375
42655
  if self.Debug then
42376
42656
  SpawnGroup:FlareRed()
42377
42657
  end
@@ -42380,13 +42660,13 @@ if(self.Ndeparture_Airports>=2 or self.random_departure)and _nrespawn<self.onrun
42380
42660
  _nrespawn=_nrespawn+1
42381
42661
  text=string.format("Try spawning new aircraft of group %s at another location. Attempt %d of max %d.",self.alias,_nrespawn,self.onrunwaymaxretry)
42382
42662
  MESSAGE:New(text,10):ToAllIf(self.Debug)
42383
- self:T(RAT.id..text)
42663
+ self:T(self.lid..text)
42384
42664
  self:_SpawnWithRoute(nil,nil,nil,nil,nil,nil,nil,_nrespawn)
42385
42665
  else
42386
42666
  if self.respawn_inair and not self.uncontrolled then
42387
42667
  text=string.format("Spawning new aircraft of group %s in air since no parking slot is available at %s.",self.alias,_departure)
42388
42668
  MESSAGE:New(text,10):ToAll()
42389
- self:T(RAT.id..text)
42669
+ self:T(self.lid..text)
42390
42670
  self:_SpawnWithRoute(_departure,_destination,RAT.wp.air,_landing,_livery)
42391
42671
  end
42392
42672
  end
@@ -42398,28 +42678,26 @@ end
42398
42678
  if ontop then
42399
42679
  local text=string.format("ERROR: Group of %s was spawned on top of another unit. Group #%d will be despawned immediately!",self.alias,i)
42400
42680
  MESSAGE:New(text,30):ToAllIf(self.Debug)
42401
- self:T(RAT.id..text)
42681
+ self:T(self.lid..text)
42402
42682
  if self.Debug then
42403
42683
  SpawnGroup:FlareYellow()
42404
42684
  end
42405
42685
  self:_Despawn(SpawnGroup)
42406
42686
  end
42407
42687
  end
42408
- end
42409
42688
  else
42410
- self:T2(RAT.id.."ERROR: Group does not exist in RAT:_OnBirth().")
42689
+ self:T2(self.lid.."ERROR: Group does not exist in RAT:_OnBirth().")
42411
42690
  end
42412
42691
  end
42413
42692
  function RAT:_OnEngineStartup(EventData)
42414
42693
  self:F3(EventData)
42415
- self:T3(RAT.id.."Captured event EngineStartup!")
42694
+ self:T3(self.lid.."Captured event EngineStartup!")
42416
42695
  local SpawnGroup=EventData.IniGroup
42417
42696
  if SpawnGroup then
42418
42697
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42419
- if EventPrefix then
42420
- if EventPrefix==self.alias then
42698
+ if EventPrefix and EventPrefix==self.alias then
42421
42699
  local text="Event: Group "..SpawnGroup:GetName().." started engines."
42422
- self:T(RAT.id..text)
42700
+ self:T(self.lid..text)
42423
42701
  local status
42424
42702
  if SpawnGroup:InAir()then
42425
42703
  status=RAT.status.EventEngineStartAir
@@ -42428,61 +42706,54 @@ status=RAT.status.EventEngineStart
42428
42706
  end
42429
42707
  self:_SetStatus(SpawnGroup,status)
42430
42708
  end
42431
- end
42432
42709
  else
42433
- self:T2(RAT.id.."ERROR: Group does not exist in RAT:_EngineStartup().")
42710
+ self:T2(self.lid.."ERROR: Group does not exist in RAT:_EngineStartup().")
42434
42711
  end
42435
42712
  end
42436
42713
  function RAT:_OnTakeoff(EventData)
42437
42714
  local SpawnGroup=EventData.IniGroup
42438
42715
  if SpawnGroup then
42439
42716
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42440
- if EventPrefix then
42441
- if EventPrefix==self.alias then
42717
+ if EventPrefix and EventPrefix==self.alias then
42442
42718
  local text="Event: Group "..SpawnGroup:GetName().." is airborne."
42443
- self:T(RAT.id..text)
42719
+ self:T(self.lid..text)
42444
42720
  local status=RAT.status.EventTakeoff
42445
42721
  self:_SetStatus(SpawnGroup,status)
42446
42722
  if self.respawn_after_takeoff then
42447
42723
  text="Event: Group "..SpawnGroup:GetName().." will be respawned after takeoff."
42448
- self:T(RAT.id..text)
42724
+ self:T(self.lid..text)
42449
42725
  self:_SpawnWithRoute(nil,nil,nil,nil,nil,nil,nil,nil)
42450
42726
  end
42451
42727
  end
42452
- end
42453
42728
  else
42454
- self:T2(RAT.id.."ERROR: Group does not exist in RAT:_OnTakeoff().")
42729
+ self:T2(self.lid.."ERROR: Group does not exist in RAT:_OnTakeoff().")
42455
42730
  end
42456
42731
  end
42457
42732
  function RAT:_OnLand(EventData)
42458
42733
  local SpawnGroup=EventData.IniGroup
42459
42734
  if SpawnGroup then
42460
42735
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42461
- if EventPrefix then
42462
- if EventPrefix==self.alias then
42463
- local text="Event: Group "..SpawnGroup:GetName().." landed."
42464
- self:T(RAT.id..text)
42736
+ if EventPrefix and EventPrefix==self.alias then
42737
+ local text="Event: Group "..SpawnGroup:GetName().." landed"
42738
+ self:T(self.lid..text)
42465
42739
  local status=RAT.status.EventLand
42466
42740
  self:_SetStatus(SpawnGroup,status)
42467
42741
  if self.ATCswitch then
42468
- RAT:_ATCFlightLanded(SpawnGroup:GetName())
42742
+ RAT._ATCFlightLanded(SpawnGroup:GetName())
42469
42743
  end
42470
42744
  if self.respawn_at_landing and not self.norespawn then
42471
- text="Event: Group "..SpawnGroup:GetName().." will be respawned."
42472
- self:T(RAT.id..text)
42473
- local idx=self:GetSpawnIndexFromGroup(SpawnGroup)
42474
- local coord=SpawnGroup:GetCoordinate()
42475
- self:_Respawn(idx,coord)
42476
- end
42745
+ text="Event: Group "..SpawnGroup:GetName().." will be respawned"
42746
+ self:T(self.lid..text)
42747
+ self:_Respawn(SpawnGroup)
42477
42748
  end
42478
42749
  end
42479
42750
  else
42480
- self:T2(RAT.id.."ERROR: Group does not exist in RAT:_OnLand().")
42751
+ self:T2(self.lid.."ERROR: Group does not exist in RAT:_OnLand()")
42481
42752
  end
42482
42753
  end
42483
42754
  function RAT:_OnEngineShutdown(EventData)
42484
42755
  self:F3(EventData)
42485
- self:T3(RAT.id.."Captured event EngineShutdown!")
42756
+ self:T3(self.lid.."Captured event EngineShutdown!")
42486
42757
  local SpawnGroup=EventData.IniGroup
42487
42758
  if SpawnGroup then
42488
42759
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
@@ -42490,35 +42761,34 @@ if EventPrefix and EventPrefix==self.alias then
42490
42761
  if not SpawnGroup:InAir()then
42491
42762
  local currentstate=self:GetStatus(SpawnGroup)
42492
42763
  local text=string.format("Event: Unit %s of group %s shut down its engines. Current state %s.",EventData.IniUnitName,SpawnGroup:GetName(),currentstate)
42493
- self:T(RAT.id..text)
42764
+ self:T(self.lid..text)
42494
42765
  if currentstate~=RAT.status.EventEngineShutdown and currentstate~="Dead"then
42495
42766
  local status=RAT.status.EventEngineShutdown
42496
42767
  self:_SetStatus(SpawnGroup,status)
42497
42768
  if not self.respawn_at_landing and not self.norespawn then
42498
42769
  text=string.format("Event: Group %s will be respawned. Current state %s => new state %s.",SpawnGroup:GetName(),currentstate,status)
42499
- self:T(RAT.id..text)
42500
- local idx=self:GetSpawnIndexFromGroup(SpawnGroup)
42501
- local coord=SpawnGroup:GetCoordinate()
42502
- self:_Respawn(idx,coord)
42503
- end
42504
- text="Event: Group "..SpawnGroup:GetName().." will be destroyed now."
42505
- self:T(RAT.id..text)
42770
+ self:T(self.lid..text)
42771
+ self:_Respawn(SpawnGroup,nil,3)
42772
+ else
42773
+ text="Event: Group "..SpawnGroup:GetName().." will be destroyed now"
42774
+ self:T(self.lid..text)
42506
42775
  self:_Despawn(SpawnGroup)
42507
42776
  end
42508
42777
  end
42509
42778
  end
42779
+ end
42510
42780
  else
42511
- self:T2(RAT.id.."ERROR: Group does not exist in RAT:_OnEngineShutdown().")
42781
+ self:T2(self.lid.."ERROR: Group does not exist in RAT:_OnEngineShutdown().")
42512
42782
  end
42513
42783
  end
42514
42784
  function RAT:_OnHit(EventData)
42515
42785
  self:F3(EventData)
42516
- self:T(RAT.id..string.format("Captured event Hit by %s! Initiator %s. Target %s",self.alias,tostring(EventData.IniUnitName),tostring(EventData.TgtUnitName)))
42786
+ self:T(self.lid..string.format("Captured event Hit by %s! Initiator %s. Target %s",self.alias,tostring(EventData.IniUnitName),tostring(EventData.TgtUnitName)))
42517
42787
  local SpawnGroup=EventData.TgtGroup
42518
42788
  if SpawnGroup then
42519
42789
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42520
42790
  if EventPrefix and EventPrefix==self.alias then
42521
- self:T(RAT.id..string.format("Event: Group %s was hit. Unit %s.",SpawnGroup:GetName(),tostring(EventData.TgtUnitName)))
42791
+ self:T(self.lid..string.format("Event: Group %s was hit. Unit %s.",SpawnGroup:GetName(),tostring(EventData.TgtUnitName)))
42522
42792
  local text=string.format("%s, unit %s was hit!",self.alias,EventData.TgtUnitName)
42523
42793
  MESSAGE:New(text,10):ToAllIf(self.reportstatus or self.Debug)
42524
42794
  end
@@ -42526,7 +42796,7 @@ end
42526
42796
  end
42527
42797
  function RAT:_OnDeadOrCrash(EventData)
42528
42798
  self:F3(EventData)
42529
- self:T3(RAT.id.."Captured event DeadOrCrash!")
42799
+ self:T3(self.lid.."Captured event DeadOrCrash!")
42530
42800
  local SpawnGroup=EventData.IniGroup
42531
42801
  if SpawnGroup then
42532
42802
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
@@ -42534,7 +42804,7 @@ if EventPrefix then
42534
42804
  if EventPrefix==self.alias then
42535
42805
  self.alive=self.alive-1
42536
42806
  local text=string.format("Event: Group %s crashed or died. Alive counter = %d.",SpawnGroup:GetName(),self.alive)
42537
- self:T(RAT.id..text)
42807
+ self:T(self.lid..text)
42538
42808
  if EventData.id==world.event.S_EVENT_CRASH then
42539
42809
  self:_OnCrash(EventData)
42540
42810
  elseif EventData.id==world.event.S_EVENT_DEAD then
@@ -42546,98 +42816,50 @@ end
42546
42816
  end
42547
42817
  function RAT:_OnDead(EventData)
42548
42818
  self:F3(EventData)
42549
- self:T3(RAT.id.."Captured event Dead!")
42819
+ self:T3(self.lid.."Captured event Dead!")
42550
42820
  local SpawnGroup=EventData.IniGroup
42551
42821
  if SpawnGroup then
42552
42822
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42553
42823
  if EventPrefix then
42554
42824
  if EventPrefix==self.alias then
42555
42825
  local text=string.format("Event: Group %s died. Unit %s.",SpawnGroup:GetName(),EventData.IniUnitName)
42556
- self:T(RAT.id..text)
42826
+ self:T(self.lid..text)
42557
42827
  local status=RAT.status.EventDead
42558
42828
  self:_SetStatus(SpawnGroup,status)
42559
42829
  end
42560
42830
  end
42561
42831
  else
42562
- self:T2(RAT.id.."ERROR: Group does not exist in RAT:_OnDead().")
42832
+ self:T2(self.lid.."ERROR: Group does not exist in RAT:_OnDead().")
42563
42833
  end
42564
42834
  end
42565
42835
  function RAT:_OnCrash(EventData)
42566
42836
  self:F3(EventData)
42567
- self:T3(RAT.id.."Captured event Crash!")
42837
+ self:T3(self.lid.."Captured event Crash!")
42568
42838
  local SpawnGroup=EventData.IniGroup
42569
42839
  if SpawnGroup then
42570
42840
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42571
42841
  if EventPrefix and EventPrefix==self.alias then
42572
- local _i=self:GetSpawnIndexFromGroup(SpawnGroup)
42573
- self.ratcraft[_i].nunits=self.ratcraft[_i].nunits-1
42574
- local _n=self.ratcraft[_i].nunits
42842
+ local ratcraft=self:_GetRatcraftFromGroup(SpawnGroup)
42843
+ if ratcraft then
42844
+ ratcraft.nunits=ratcraft.nunits-1
42575
42845
  local _n0=SpawnGroup:GetInitialSize()
42576
- local text=string.format("Event: Group %s crashed. Unit %s. Units still alive %d of %d.",SpawnGroup:GetName(),EventData.IniUnitName,_n,_n0)
42577
- self:T(RAT.id..text)
42846
+ local text=string.format("Event: Group %s crashed. Unit %s. Units still alive %d of %d.",SpawnGroup:GetName(),EventData.IniUnitName,ratcraft.nunits,_n0)
42847
+ self:T(self.lid..text)
42578
42848
  local status=RAT.status.EventCrash
42579
42849
  self:_SetStatus(SpawnGroup,status)
42580
- if _n==0 and self.respawn_after_crash and not self.norespawn then
42581
- local text=string.format("No units left of group %s. Group will be respawned now.",SpawnGroup:GetName())
42582
- self:T(RAT.id..text)
42583
- local idx=self:GetSpawnIndexFromGroup(SpawnGroup)
42584
- local coord=SpawnGroup:GetCoordinate()
42585
- self:_Respawn(idx,coord)
42586
- end
42850
+ if ratcraft.nunits==0 and self.respawn_after_crash and not self.norespawn then
42851
+ self:T(self.lid..string.format("No units left of group %s. Group will be respawned now.",SpawnGroup:GetName()))
42852
+ self:_Respawn(SpawnGroup)
42587
42853
  end
42588
42854
  else
42589
- if self.Debug then
42590
- self:E(RAT.id.."ERROR: Group does not exist in RAT:_OnCrash().")
42855
+ self:E(self.lid..string.format("ERROR: Could not find ratcraft object for crashed group %s!",SpawnGroup:GetName()))
42591
42856
  end
42592
42857
  end
42858
+ else
42859
+ if self.Debug then
42860
+ self:E(self.lid.."ERROR: Group does not exist in RAT:_OnCrash()!")
42593
42861
  end
42594
- function RAT:_Despawn(group,delay)
42595
- if group~=nil then
42596
- local index=self:GetSpawnIndexFromGroup(group)
42597
- if index~=nil then
42598
- self.ratcraft[index].group=nil
42599
- self.ratcraft[index]["status"]="Dead"
42600
- local despawndelay=0
42601
- if delay then
42602
- despawndelay=delay
42603
- elseif self.respawn_delay then
42604
- despawndelay=self.respawn_delay
42605
- end
42606
- self:T(RAT.id..string.format("%s delayed despawn in %.1f seconds.",self.alias,despawndelay))
42607
- SCHEDULER:New(nil,self._Destroy,{self,group},despawndelay)
42608
- if self.f10menu and self.SubMenuName~=nil then
42609
- self.Menu[self.SubMenuName]["groups"][index]:Remove()
42610
- end
42611
- end
42612
- end
42613
- end
42614
- function RAT:_Destroy(group)
42615
- self:F2(group)
42616
- local DCSGroup=group:GetDCSObject()
42617
- if DCSGroup and DCSGroup:isExist()then
42618
- local triggerdead=true
42619
- for _,DCSUnit in pairs(DCSGroup:getUnits())do
42620
- if DCSUnit then
42621
- if triggerdead then
42622
- self:_CreateEventDead(timer.getTime(),DCSUnit)
42623
- triggerdead=false
42624
- end
42625
- _DATABASE:DeleteUnit(DCSUnit:getName())
42626
- end
42627
- end
42628
- DCSGroup:destroy()
42629
- DCSGroup=nil
42630
42862
  end
42631
- return nil
42632
- end
42633
- function RAT:_CreateEventDead(EventTime,Initiator)
42634
- self:F({EventTime,Initiator})
42635
- local Event={
42636
- id=world.event.S_EVENT_DEAD,
42637
- time=EventTime,
42638
- initiator=Initiator,
42639
- }
42640
- world.onEvent(Event)
42641
42863
  end
42642
42864
  function RAT:_Waypoint(index,description,Type,Coord,Speed,Altitude,Airport)
42643
42865
  local _Altitude=Altitude or Coord.y
@@ -42690,7 +42912,7 @@ _Type="Turning Point"
42690
42912
  _Action="Turning Point"
42691
42913
  _alttype="BARO"
42692
42914
  else
42693
- self:E(RAT.id.."ERROR: Unknown waypoint type in RAT:Waypoint() function!")
42915
+ self:E(self.lid.."ERROR: Unknown waypoint type in RAT:Waypoint() function!")
42694
42916
  _Type="Turning Point"
42695
42917
  _Action="Turning Point"
42696
42918
  _alttype="RADIO"
@@ -42715,7 +42937,7 @@ else
42715
42937
  text=text..string.format("No airport/zone specified\n")
42716
42938
  end
42717
42939
  text=text.."******************************************************\n"
42718
- self:T2(RAT.id..text)
42940
+ self:T2(self.lid..text)
42719
42941
  local RoutePoint={}
42720
42942
  RoutePoint.x=Coord.x
42721
42943
  RoutePoint.y=Coord.z
@@ -42740,30 +42962,12 @@ RoutePoint.helipadId=AirbaseID
42740
42962
  elseif AirbaseCategory==Airbase.Category.AIRDROME then
42741
42963
  RoutePoint.airdromeId=AirbaseID
42742
42964
  else
42743
- self:T(RAT.id.."Unknown Airport category in _Waypoint()!")
42965
+ self:T(self.lid.."Unknown Airport category in _Waypoint()!")
42744
42966
  end
42745
42967
  end
42746
- RoutePoint.properties={
42747
- ["vnav"]=1,
42748
- ["scale"]=0,
42749
- ["angle"]=0,
42750
- ["vangle"]=0,
42751
- ["steer"]=2,
42752
- }
42753
- local TaskCombo={}
42754
- local TaskHolding=self:_TaskHolding({x=Coord.x,y=Coord.z},Altitude,Speed,self:_Randomize(90,0.9))
42755
- local TaskWaypoint=self:_TaskFunction("RAT._WaypointFunction",self,index)
42756
- RoutePoint.task={}
42757
- RoutePoint.task.id="ComboTask"
42758
- RoutePoint.task.params={}
42759
- TaskCombo[#TaskCombo+1]=TaskWaypoint
42760
- if Type==RAT.wp.holding then
42761
- TaskCombo[#TaskCombo+1]=TaskHolding
42762
- end
42763
- RoutePoint.task.params.tasks=TaskCombo
42764
42968
  return RoutePoint
42765
42969
  end
42766
- function RAT:_Routeinfo(waypoints,comment)
42970
+ function RAT:_Routeinfo(waypoints,comment,waypointdescriptions)
42767
42971
  local text=string.format("\n******************************************************\n")
42768
42972
  text=text..string.format("Template = %s\n",self.SpawnTemplatePrefix)
42769
42973
  if comment then
@@ -42772,7 +42976,7 @@ end
42772
42976
  text=text..string.format("Number of waypoints = %i\n",#waypoints)
42773
42977
  for i=1,#waypoints do
42774
42978
  local p=waypoints[i]
42775
- text=text..string.format("WP #%i: x = %6.1f km, y = %6.1f km, alt = %6.1f m %s\n",i-1,p.x/1000,p.y/1000,p.alt,self.waypointdescriptions[i])
42979
+ text=text..string.format("WP #%i: x = %6.1f km, y = %6.1f km, alt = %6.1f m %s\n",i-1,p.x/1000,p.y/1000,p.alt,waypointdescriptions[i])
42776
42980
  end
42777
42981
  local total=0.0
42778
42982
  for i=1,#waypoints-1 do
@@ -42785,115 +42989,27 @@ local y2=point2.y
42785
42989
  local d=math.sqrt((x1-x2)^2+(y1-y2)^2)
42786
42990
  local heading=self:_Course(point1,point2)
42787
42991
  total=total+d
42788
- text=text..string.format("Distance from WP %i-->%i = %6.1f km. Heading = %03d : %s - %s\n",i-1,i,d/1000,heading,self.waypointdescriptions[i],self.waypointdescriptions[i+1])
42992
+ text=text..string.format("Distance from WP %i-->%i = %6.1f km. Heading = %03d : %s - %s\n",i-1,i,d/1000,heading,waypointdescriptions[i],waypointdescriptions[i+1])
42789
42993
  end
42790
42994
  text=text..string.format("Total distance = %6.1f km\n",total/1000)
42791
42995
  text=text..string.format("******************************************************\n")
42792
- self:T2(RAT.id..text)
42996
+ self:T2(self.lid..text)
42793
42997
  return total
42794
42998
  end
42795
- function RAT:_TaskHolding(P1,Altitude,Speed,Duration)
42796
- local dx=3000
42797
- local dy=0
42798
- if self.category==RAT.cat.heli then
42799
- dx=200
42800
- dy=0
42801
- end
42802
- local P2={}
42803
- P2.x=P1.x+dx
42804
- P2.y=P1.y+dy
42805
- local Task={
42806
- id='Orbit',
42807
- params={
42808
- pattern=AI.Task.OrbitPattern.RACE_TRACK,
42809
- point=P1,
42810
- point2=P2,
42811
- speed=Speed,
42812
- altitude=Altitude
42813
- }
42814
- }
42815
- local DCSTask={}
42816
- DCSTask.id="ControlledTask"
42817
- DCSTask.params={}
42818
- DCSTask.params.task=Task
42819
- if self.ATCswitch then
42820
- local userflagname=string.format("%s#%03d",self.alias,self.SpawnIndex+1)
42821
- local maxholdingduration=60*120
42822
- DCSTask.params.stopCondition={userFlag=userflagname,userFlagValue=1,duration=maxholdingduration}
42823
- else
42824
- DCSTask.params.stopCondition={duration=Duration}
42825
- end
42826
- return DCSTask
42827
- end
42828
- function RAT._WaypointFunction(group,rat,wp)
42829
- local Tnow=timer.getTime()
42830
- local sdx=rat:GetSpawnIndexFromGroup(group)
42831
- local departure=rat.ratcraft[sdx].departure:GetName()
42832
- local destination=rat.ratcraft[sdx].destination:GetName()
42833
- local landing=rat.ratcraft[sdx].landing
42834
- local WPholding=rat.ratcraft[sdx].wpholding
42835
- local WPfinal=rat.ratcraft[sdx].wpfinal
42836
- local text
42837
- text=string.format("Flight %s passing waypoint #%d %s.",group:GetName(),wp,rat.waypointdescriptions[wp])
42838
- BASE.T(rat,RAT.id..text)
42839
- local status=rat.waypointstatus[wp]
42840
- rat:_SetStatus(group,status)
42841
- if wp==WPholding then
42842
- text=string.format("Flight %s to %s ATC: Holding and awaiting landing clearance.",group:GetName(),destination)
42843
- MESSAGE:New(text,10):ToAllIf(rat.reportstatus)
42844
- if rat.ATCswitch then
42845
- if rat.f10menu then
42846
- MENU_MISSION_COMMAND:New("Clear for landing",rat.Menu[rat.SubMenuName].groups[sdx],rat.ClearForLanding,rat,group:GetName())
42847
- end
42848
- rat._ATCRegisterFlight(rat,group:GetName(),Tnow)
42849
- end
42850
- end
42851
- if wp==WPfinal then
42852
- text=string.format("Flight %s arrived at final destination %s.",group:GetName(),destination)
42853
- MESSAGE:New(text,10):ToAllIf(rat.reportstatus)
42854
- BASE.T(rat,RAT.id..text)
42855
- if landing==RAT.wp.air then
42856
- text=string.format("Activating despawn switch for flight %s! Group will be detroyed soon.",group:GetName())
42857
- MESSAGE:New(text,10):ToAllIf(rat.Debug)
42858
- BASE.T(rat,RAT.id..text)
42859
- rat.ratcraft[sdx].despawnme=true
42860
- end
42861
- end
42862
- end
42863
- function RAT:_TaskFunction(FunctionString,...)
42864
- self:F2({FunctionString,arg})
42865
- local DCSTask
42866
- local ArgumentKey
42867
- local templatename=self.templategroup:GetName()
42868
- local groupname=self:_AnticipatedGroupName()
42869
- local DCSScript={}
42870
- DCSScript[#DCSScript+1]="local MissionControllable = GROUP:FindByName(\""..groupname.."\") "
42871
- DCSScript[#DCSScript+1]="local RATtemplateControllable = GROUP:FindByName(\""..templatename.."\") "
42872
- if arg and arg.n>0 then
42873
- ArgumentKey='_'..tostring(arg):match("table: (.*)")
42874
- self.templategroup:SetState(self.templategroup,ArgumentKey,arg)
42875
- DCSScript[#DCSScript+1]="local Arguments = RATtemplateControllable:GetState(RATtemplateControllable, '"..ArgumentKey.."' ) "
42876
- DCSScript[#DCSScript+1]=FunctionString.."( MissionControllable, unpack( Arguments ) )"
42877
- else
42878
- DCSScript[#DCSScript+1]=FunctionString.."( MissionControllable )"
42879
- end
42880
- DCSTask=self.templategroup:TaskWrappedAction(self.templategroup:CommandDoScript(table.concat(DCSScript)))
42881
- return DCSTask
42882
- end
42883
42999
  function RAT:_AnticipatedGroupName(index)
42884
43000
  local index=index or self.SpawnIndex+1
42885
43001
  return string.format("%s#%03d",self.alias,index)
42886
43002
  end
42887
43003
  function RAT:_ActivateUncontrolled()
42888
- self:F()
42889
43004
  local idx={}
42890
43005
  local rat={}
42891
43006
  local nactive=0
42892
- for spawnindex,ratcraft in pairs(self.ratcraft)do
43007
+ for spawnindex,_ratcraft in pairs(self.ratcraft)do
43008
+ local ratcraft=_ratcraft
42893
43009
  local group=ratcraft.group
42894
43010
  if group and group:IsAlive()then
42895
- local text=string.format("Uncontrolled: Group = %s (spawnindex = %d), active = %s.",ratcraft.group:GetName(),spawnindex,tostring(ratcraft.active))
42896
- self:T2(RAT.id..text)
43011
+ local text=string.format("Uncontrolled: Group = %s (spawnindex = %d), active = %s",ratcraft.group:GetName(),spawnindex,tostring(ratcraft.active))
43012
+ self:T2(self.lid..text)
42897
43013
  if ratcraft.active then
42898
43014
  nactive=nactive+1
42899
43015
  else
@@ -42901,24 +43017,28 @@ table.insert(idx,spawnindex)
42901
43017
  end
42902
43018
  end
42903
43019
  end
42904
- local text=string.format("Uncontrolled: Ninactive = %d, Nactive = %d (of max %d).",#idx,nactive,self.activate_max)
42905
- self:T(RAT.id..text)
43020
+ local text=string.format("Uncontrolled: Ninactive = %d, Nactive = %d (of max %d)",#idx,nactive,self.activate_max)
43021
+ self:T(self.lid..text)
42906
43022
  if#idx>0 and nactive<self.activate_max then
42907
43023
  local index=idx[math.random(#idx)]
42908
- local group=self.ratcraft[index].group
42909
- self:_CommandStartUncontrolled(group)
43024
+ local ratcraft=self.ratcraft[index]
43025
+ local group=ratcraft.group
43026
+ local departureAirbase=self:_GetDepartureAirbase(ratcraft)
43027
+ local departureFlightControl=nil
43028
+ if departureAirbase then
43029
+ departureFlightControl=_DATABASE:GetFlightControl(departureAirbase:GetName())
42910
43030
  end
43031
+ if departureFlightControl then
43032
+ self:T(self.lid..string.format("RAT group %s is ready for takeoff",group:GetName()))
43033
+ ratcraft.flightgroup:SetReadyForTakeoff(true)
43034
+ else
43035
+ self:T(self.lid..string.format("RAT group %s is switching to controlled now",group:GetName()))
43036
+ ratcraft.flightgroup:StartUncontrolled()
42911
43037
  end
42912
- function RAT:_CommandStartUncontrolled(group)
42913
- self:F(group)
42914
- local StartCommand={id='Start',params={}}
42915
- local text=string.format("Uncontrolled: Activating group %s.",group:GetName())
42916
- self:T(RAT.id..text)
42917
- group:SetCommand(StartCommand)
42918
- local index=self:GetSpawnIndexFromGroup(group)
42919
- self.ratcraft[index].active=true
43038
+ ratcraft.active=true
42920
43039
  self:_SetStatus(group,RAT.status.EventBirth)
42921
43040
  end
43041
+ end
42922
43042
  function RAT:_CommandInvisible(group,switch)
42923
43043
  local SetInvisible={id='SetInvisible',params={value=switch}}
42924
43044
  group:SetCommand(SetInvisible)
@@ -42955,7 +43075,7 @@ if DCSuniti and DCSuniti:isExist()and DCSunitj and DCSunitj:isExist()then
42955
43075
  local _dist=uniti:GetCoordinate():Get3DDistance(unitj:GetCoordinate())
42956
43076
  if _dist<distmin then
42957
43077
  if(not uniti:InAir())and(not unitj:InAir())then
42958
- self:T(RAT.id..string.format("Unit %s is on top of unit %s. Distance %.2f m.",namei,namej,_dist))
43078
+ self:T(self.lid..string.format("Unit %s is on top of unit %s. Distance %.2f m.",namei,namej,_dist))
42959
43079
  return true
42960
43080
  end
42961
43081
  end
@@ -42987,6 +43107,21 @@ end
42987
43107
  end
42988
43108
  return false
42989
43109
  end
43110
+ function RAT:_GetDestinationAirbase(ratcraft)
43111
+ if ratcraft and ratcraft.destination then
43112
+ local airbase=AIRBASE:FindByName(ratcraft.destination)
43113
+ return airbase
43114
+ end
43115
+ return nil
43116
+ end
43117
+ function RAT:_GetDepartureAirbase(ratcraft)
43118
+ if ratcraft and ratcraft.departure then
43119
+ local name=ratcraft.departure:GetName()
43120
+ local airbase=AIRBASE:FindByName(name)
43121
+ return airbase
43122
+ end
43123
+ return nil
43124
+ end
42990
43125
  function RAT:_AirportExists(name)
42991
43126
  for _,airport in pairs(self.airports_map)do
42992
43127
  if airport:GetName()==name then
@@ -43002,25 +43137,31 @@ return true
43002
43137
  end
43003
43138
  return false
43004
43139
  end
43005
- function RAT:_SetROE(group,roe)
43006
- self:T(RAT.id.."Setting ROE to "..roe.." for group "..group:GetName())
43007
- if self.roe==RAT.ROE.returnfire then
43008
- group:OptionROEReturnFire()
43009
- elseif self.roe==RAT.ROE.weaponfree then
43010
- group:OptionROEWeaponFree()
43140
+ function RAT:_SetROE(flightgroup,roe)
43141
+ roe=roe or self.roe
43142
+ self:T(self.lid.."Setting ROE to "..roe.." for group "..flightgroup:GetName())
43143
+ local _roe=ENUMS.ROE.WeaponHold
43144
+ if roe==RAT.ROE.returnfire then
43145
+ _roe=ENUMS.ROE.ReturnFire
43146
+ elseif roe==RAT.ROE.weaponfree then
43147
+ _roe=ENUMS.ROE.OpenFireWeaponFree
43011
43148
  else
43012
- group:OptionROEHoldFire()
43013
43149
  end
43150
+ flightgroup:SetDefaultROE(_roe)
43151
+ flightgroup:SwitchROE(_roe)
43014
43152
  end
43015
- function RAT:_SetROT(group,rot)
43016
- self:T(RAT.id.."Setting ROT to "..rot.." for group "..group:GetName())
43017
- if self.rot==RAT.ROT.passive then
43018
- group:OptionROTPassiveDefense()
43019
- elseif self.rot==RAT.ROT.evade then
43020
- group:OptionROTEvadeFire()
43153
+ function RAT:_SetROT(flightgroup,rot)
43154
+ rot=rot or self.rot
43155
+ self:T(self.lid.."Setting ROT to "..rot.." for group "..flightgroup:GetName())
43156
+ local _rot=ENUMS.ROT.NoReaction
43157
+ if rot==RAT.ROT.passive then
43158
+ _rot=ENUMS.ROT.PassiveDefense
43159
+ elseif rot==RAT.ROT.evade then
43160
+ _rot=ENUMS.ROT.EvadeFire
43021
43161
  else
43022
- group:OptionROTNoReaction()
43023
43162
  end
43163
+ flightgroup:SetDefaultROT(_rot)
43164
+ flightgroup:SwitchROT(_rot)
43024
43165
  end
43025
43166
  function RAT:_SetCoalitionTable()
43026
43167
  if self.friendly==RAT.coal.neutral then
@@ -43030,7 +43171,7 @@ self.ctable={self.coalition,coalition.side.NEUTRAL}
43030
43171
  elseif self.friendly==RAT.coal.sameonly then
43031
43172
  self.ctable={self.coalition}
43032
43173
  else
43033
- self:E(RAT.id.."ERROR: Unknown friendly coalition in _SetCoalitionTable(). Defaulting to NEUTRAL.")
43174
+ self:E(self.lid.."ERROR: Unknown friendly coalition in _SetCoalitionTable(). Defaulting to NEUTRAL.")
43034
43175
  self.ctable={self.coalition,coalition.side.NEUTRAL}
43035
43176
  end
43036
43177
  end
@@ -43080,16 +43221,16 @@ end
43080
43221
  local r=math.random(min,max)
43081
43222
  if self.Debug then
43082
43223
  local text=string.format("Random: value = %6.2f, fac = %4.2f, min = %6.2f, max = %6.2f, r = %6.2f",value,fac,min,max,r)
43083
- self:T3(RAT.id..text)
43224
+ self:T3(self.lid..text)
43084
43225
  end
43085
43226
  return r
43086
43227
  end
43087
- function RAT:_PlaceMarkers(waypoints,index)
43228
+ function RAT:_PlaceMarkers(waypoints,waypointdescriptions,index)
43088
43229
  for i=1,#waypoints do
43089
- self:_SetMarker(self.waypointdescriptions[i],waypoints[i],index)
43230
+ self:_SetMarker(waypointdescriptions[i],waypoints[i],index)
43090
43231
  if self.Debug then
43091
- local text=string.format("Marker at waypoint #%d: %s for flight #%d",i,self.waypointdescriptions[i],index)
43092
- self:T2(RAT.id..text)
43232
+ local text=string.format("Marker at waypoint #%d: %s for flight #%d",i,waypointdescriptions[i],index)
43233
+ self:T2(self.lid..text)
43093
43234
  end
43094
43235
  end
43095
43236
  end
@@ -43098,7 +43239,7 @@ RAT.markerid=RAT.markerid+1
43098
43239
  self.markerids[#self.markerids+1]=RAT.markerid
43099
43240
  if self.Debug then
43100
43241
  local text2=string.format("%s: placing marker with ID %d and text %s",self.alias,RAT.markerid,text)
43101
- self:T2(RAT.id..text2)
43242
+ self:T2(self.lid..text2)
43102
43243
  end
43103
43244
  local vec={x=wp.x,y=wp.alt,z=wp.y}
43104
43245
  local flight=self:GetGroupFromIndex(index):GetName()
@@ -43113,7 +43254,7 @@ for k,v in ipairs(self.markerids)do
43113
43254
  self.markerids[k]=nil
43114
43255
  end
43115
43256
  end
43116
- function RAT:_ModifySpawnTemplate(waypoints,livery,spawnplace,departure,takeoff,parkingdata)
43257
+ function RAT:_ModifySpawnTemplate(waypoints,livery,spawnplace,departure,takeoff,parkingdata,uncontrolled)
43117
43258
  self:F2({waypoints=waypoints,livery=livery,spawnplace=spawnplace,departure=departure,takeoff=takeoff,parking=parkingdata})
43118
43259
  local PointVec3=COORDINATE:New(waypoints[1].x,waypoints[1].alt,waypoints[1].y)
43119
43260
  if spawnplace then
@@ -43147,8 +43288,7 @@ if self:_GetSpawnIndex(self.SpawnIndex+1)then
43147
43288
  local SpawnTemplate=self.SpawnGroups[self.SpawnIndex].SpawnTemplate
43148
43289
  if SpawnTemplate then
43149
43290
  self:T(SpawnTemplate)
43150
- if self.uncontrolled then
43151
- self.SpawnUnControlled=true
43291
+ if self.uncontrolled or uncontrolled then
43152
43292
  SpawnTemplate.uncontrolled=true
43153
43293
  end
43154
43294
  local nunits=#SpawnTemplate.units
@@ -43167,25 +43307,27 @@ local scanstatics=true
43167
43307
  local scanscenery=self.parkingscanscenery
43168
43308
  local verysafe=self.parkingverysafe
43169
43309
  if spawnonship or spawnonfarp or spawnonrunway then
43170
- self:T(RAT.id..string.format("Group %s is spawned on farp/ship/runway %s.",self.alias,departure:GetName()))
43310
+ self:T(self.lid..string.format("Group %s is spawned on farp/ship/runway %s.",self.alias,departure:GetName()))
43171
43311
  nfree=departure:GetFreeParkingSpotsNumber(termtype,true)
43172
43312
  spots=departure:GetFreeParkingSpotsTable(termtype,true)
43313
+ self:T(self.lid..string.format("Free nfree=%d nspots=%d",nfree,#spots))
43173
43314
  elseif parkingdata~=nil then
43315
+ self:T2("Spawning with explicit parking data")
43174
43316
  nfree=#parkingdata
43175
43317
  spots=parkingdata
43176
43318
  else
43177
43319
  if self.category==RAT.cat.heli then
43178
43320
  if termtype==nil then
43179
- self:T(RAT.id..string.format("Helo group %s is spawned at %s using terminal type %d.",self.alias,departure:GetName(),AIRBASE.TerminalType.HelicopterOnly))
43321
+ self:T(self.lid..string.format("Helo group %s is spawned at %s using terminal type %d.",self.alias,departure:GetName(),AIRBASE.TerminalType.HelicopterOnly))
43180
43322
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.HelicopterOnly,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43181
43323
  nfree=#spots
43182
43324
  if nfree<nunits then
43183
- self:T(RAT.id..string.format("Helo group %s is spawned at %s using terminal type %d.",self.alias,departure:GetName(),AIRBASE.TerminalType.HelicopterUsable))
43325
+ self:T(self.lid..string.format("Helo group %s is spawned at %s using terminal type %d.",self.alias,departure:GetName(),AIRBASE.TerminalType.HelicopterUsable))
43184
43326
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.HelicopterUsable,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43185
43327
  nfree=#spots
43186
43328
  end
43187
43329
  else
43188
- self:T(RAT.id..string.format("Helo group %s is at %s using terminal type %d.",self.alias,departure:GetName(),termtype))
43330
+ self:T(self.lid..string.format("Helo group %s is at %s using terminal type %d.",self.alias,departure:GetName(),termtype))
43189
43331
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,termtype,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43190
43332
  nfree=#spots
43191
43333
  end
@@ -43194,33 +43336,35 @@ if termtype==nil then
43194
43336
  local bomber=TemplateUnit:HasAttribute("Bombers")
43195
43337
  local transport=TemplateUnit:HasAttribute("Transports")
43196
43338
  if bomber or transport then
43197
- self:T(RAT.id..string.format("Transport/bomber group %s is spawned at %s using terminal type %d.",self.alias,departure:GetName(),AIRBASE.TerminalType.OpenBig))
43339
+ self:T(self.lid..string.format("Transport/bomber group %s is spawned at %s using terminal type %d.",self.alias,departure:GetName(),AIRBASE.TerminalType.OpenBig))
43198
43340
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.OpenBig,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43199
43341
  nfree=#spots
43200
43342
  if nfree<nunits then
43201
- self:T(RAT.id..string.format("Transport/bomber group %s is at %s using terminal type %d.",self.alias,departure:GetName(),AIRBASE.TerminalType.OpenMed))
43343
+ self:T(self.lid..string.format("Transport/bomber group %s is at %s using terminal type %d.",self.alias,departure:GetName(),AIRBASE.TerminalType.OpenMed))
43202
43344
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.OpenMed,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43203
43345
  nfree=#spots
43204
43346
  end
43205
43347
  else
43206
- self:T(RAT.id..string.format("Fighter group %s is spawned at %s using terminal type %d.",self.alias,departure:GetName(),AIRBASE.TerminalType.FighterAircraft))
43348
+ self:T(self.lid..string.format("Fighter group %s is spawned at %s using terminal type %d.",self.alias,departure:GetName(),AIRBASE.TerminalType.FighterAircraft))
43207
43349
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.FighterAircraft,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43208
43350
  nfree=#spots
43209
43351
  end
43210
43352
  else
43211
- self:T(RAT.id..string.format("Plane group %s is spawned at %s using terminal type %d.",self.alias,departure:GetName(),termtype))
43353
+ self:T(self.lid..string.format("Plane group %s is spawned at %s using terminal type %d.",self.alias,departure:GetName(),termtype))
43212
43354
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,termtype,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43213
43355
  nfree=#spots
43214
43356
  end
43215
43357
  end
43216
43358
  end
43359
+ if false then
43217
43360
  local parkingdata=departure:GetParkingSpotsTable(termtype)
43218
- self:T2(RAT.id..string.format("Parking at %s, terminal type %s:",departure:GetName(),tostring(termtype)))
43361
+ self:T2(self.lid..string.format("Parking at %s, terminal type %s:",departure:GetName(),tostring(termtype)))
43219
43362
  for _,_spot in pairs(parkingdata)do
43220
- self:T2(RAT.id..string.format("%s, Termin Index = %3d, Term Type = %03d, Free = %5s, TOAC = %5s, Term ID0 = %3d, Dist2Rwy = %4d",
43363
+ self:T2(self.lid..string.format("%s, Termin Index = %3d, Term Type = %03d, Free = %5s, TOAC = %5s, Term ID0 = %3d, Dist2Rwy = %4d",
43221
43364
  departure:GetName(),_spot.TerminalID,_spot.TerminalType,tostring(_spot.Free),tostring(_spot.TOAC),_spot.TerminalID0,_spot.DistToRwy))
43222
43365
  end
43223
- self:T(RAT.id..string.format("%s at %s: free parking spots = %d - number of units = %d",self.alias,departure:GetName(),nfree,nunits))
43366
+ self:T(self.lid..string.format("%s at %s: free parking spots = %d - number of units = %d",self.alias,departure:GetName(),nfree,nunits))
43367
+ end
43224
43368
  local _notenough=false
43225
43369
  if spawnonship or spawnonfarp or spawnonrunway then
43226
43370
  if nfree>=1 then
@@ -43244,7 +43388,7 @@ end
43244
43388
  end
43245
43389
  if _notenough then
43246
43390
  if self.respawn_inair and not self.SpawnUnControlled then
43247
- self:E(RAT.id..string.format("WARNING: Group %s has no parking spots at %s ==> air start!",self.SpawnTemplatePrefix,departure:GetName()))
43391
+ self:E(self.lid..string.format("WARNING: Group %s has no parking spots at %s ==> air start!",self.SpawnTemplatePrefix,departure:GetName()))
43248
43392
  spawnonground=false
43249
43393
  spawnonship=false
43250
43394
  spawnonfarp=false
@@ -43259,7 +43403,7 @@ else
43259
43403
  PointVec3.y=PointVec3:GetLandHeight()+math.random(500,3000)
43260
43404
  end
43261
43405
  else
43262
- self:E(RAT.id..string.format("WARNING: Group %s has no parking spots at %s ==> No emergency air start or uncontrolled spawning ==> No spawn!",self.SpawnTemplatePrefix,departure:GetName()))
43406
+ self:E(self.lid..string.format("WARNING: Group %s has no parking spots at %s ==> No emergency air start or uncontrolled spawning ==> No spawn!",self.SpawnTemplatePrefix,departure:GetName()))
43263
43407
  return nil
43264
43408
  end
43265
43409
  end
@@ -43275,18 +43419,18 @@ local TX=PointVec3.x+(SX-BX)
43275
43419
  local TY=PointVec3.z+(SY-BY)
43276
43420
  if spawnonground then
43277
43421
  if spawnonship or spawnonfarp or spawnonrunway or automatic then
43278
- self:T(RAT.id..string.format("RAT group %s spawning at farp, ship or runway %s.",self.alias,departure:GetName()))
43422
+ self:T(self.lid..string.format("RAT group %s spawning at farp, ship or runway %s.",self.alias,departure:GetName()))
43279
43423
  SpawnTemplate.units[UnitID].x=PointVec3.x
43280
43424
  SpawnTemplate.units[UnitID].y=PointVec3.z
43281
43425
  SpawnTemplate.units[UnitID].alt=PointVec3.y
43282
43426
  else
43283
- self:T(RAT.id..string.format("RAT group %s spawning at airbase %s on parking spot id %d",self.alias,departure:GetName(),parkingindex[UnitID]))
43427
+ self:T(self.lid..string.format("RAT group %s spawning at airbase %s on parking spot id %d",self.alias,departure:GetName(),parkingindex[UnitID]))
43284
43428
  SpawnTemplate.units[UnitID].x=parkingspots[UnitID].x
43285
43429
  SpawnTemplate.units[UnitID].y=parkingspots[UnitID].z
43286
43430
  SpawnTemplate.units[UnitID].alt=parkingspots[UnitID].y
43287
43431
  end
43288
43432
  else
43289
- self:T(RAT.id..string.format("RAT group %s spawning in air at %s.",self.alias,departure:GetName()))
43433
+ self:T(self.lid..string.format("RAT group %s spawning in air at %s.",self.alias,departure:GetName()))
43290
43434
  SpawnTemplate.units[UnitID].x=TX
43291
43435
  SpawnTemplate.units[UnitID].y=TY
43292
43436
  SpawnTemplate.units[UnitID].alt=PointVec3.y
@@ -43300,8 +43444,8 @@ UnitTemplate.parking_id=nil
43300
43444
  if parkingindex[UnitID]and not automatic then
43301
43445
  UnitTemplate.parking=parkingindex[UnitID]
43302
43446
  end
43303
- self:T2(RAT.id..string.format("RAT group %s unit number %d: Parking = %s",self.alias,UnitID,tostring(UnitTemplate.parking)))
43304
- self:T2(RAT.id..string.format("RAT group %s unit number %d: Parking ID = %s",self.alias,UnitID,tostring(UnitTemplate.parking_id)))
43447
+ self:T2(self.lid..string.format("RAT group %s unit number %d: Parking = %s",self.alias,UnitID,tostring(UnitTemplate.parking)))
43448
+ self:T2(self.lid..string.format("RAT group %s unit number %d: Parking ID = %s",self.alias,UnitID,tostring(UnitTemplate.parking_id)))
43305
43449
  SpawnTemplate.units[UnitID].heading=heading
43306
43450
  SpawnTemplate.units[UnitID].psi=-heading
43307
43451
  if livery then
@@ -43338,149 +43482,167 @@ end
43338
43482
  end
43339
43483
  return true
43340
43484
  end
43341
- function RAT:_ATCInit(airports_map)
43485
+ function RAT._ATCInit(airports_map)
43342
43486
  if not RAT.ATC.init then
43343
- local text
43344
- text="Starting RAT ATC.\nSimultanious = "..RAT.ATC.Nclearance.."\n".."Delay = "..RAT.ATC.delay
43345
- BASE:T(RAT.id..text)
43346
- RAT.ATC.init=true
43487
+ local text="Starting RAT ATC.\nSimultanious = "..RAT.ATC.Nclearance.."\n".."Delay = "..RAT.ATC.delay
43488
+ BASE:I(RAT.id..text)
43347
43489
  for _,ap in pairs(airports_map)do
43348
- local name=ap:GetName()
43349
- RAT.ATC.airport[name]={}
43350
- RAT.ATC.airport[name].queue={}
43351
- RAT.ATC.airport[name].busy=false
43352
- RAT.ATC.airport[name].onfinal={}
43353
- RAT.ATC.airport[name].Nonfinal=0
43354
- RAT.ATC.airport[name].traffic=0
43355
- RAT.ATC.airport[name].Tlastclearance=nil
43356
- end
43357
- SCHEDULER:New(nil,RAT._ATCCheck,{self},5,15)
43358
- SCHEDULER:New(nil,RAT._ATCStatus,{self},5,60)
43490
+ local airbase=ap
43491
+ local name=airbase:GetName()
43492
+ local fc=_DATABASE:GetFlightControl(name)
43493
+ if not fc then
43494
+ local airport={}
43495
+ airport.queue={}
43496
+ airport.busy=false
43497
+ airport.onfinal={}
43498
+ airport.Nonfinal=0
43499
+ airport.traffic=0
43500
+ airport.Tlastclearance=nil
43501
+ RAT.ATC.airport[name]=airport
43502
+ end
43503
+ end
43504
+ SCHEDULER:New(nil,RAT._ATCCheck,{},5,15)
43505
+ SCHEDULER:New(nil,RAT._ATCStatus,{},5,60)
43359
43506
  RAT.ATC.T0=timer.getTime()
43360
43507
  end
43508
+ RAT.ATC.init=true
43361
43509
  end
43362
43510
  function RAT:_ATCAddFlight(name,dest)
43363
- BASE:T(string.format("%sATC %s: Adding flight %s with destination %s.",RAT.id,dest,name,dest))
43364
- RAT.ATC.flight[name]={}
43365
- RAT.ATC.flight[name].destination=dest
43366
- RAT.ATC.flight[name].Tarrive=-1
43367
- RAT.ATC.flight[name].holding=-1
43368
- RAT.ATC.flight[name].Tonfinal=-1
43369
- end
43370
- function RAT:_ATCDelFlight(t,entry)
43511
+ BASE:I(RAT.id..string.format("ATC %s: Adding flight %s with destination %s.",dest,name,dest))
43512
+ local flight={}
43513
+ flight.destination=dest
43514
+ flight.Tarrive=-1
43515
+ flight.holding=-1
43516
+ flight.Tarrive=-1
43517
+ RAT.ATC.flight[name]=flight
43518
+ end
43519
+ function RAT._ATCDelFlight(t,entry)
43371
43520
  for k,_ in pairs(t)do
43372
43521
  if k==entry then
43522
+ BASE:I(RAT.id..string.format("Removing flight %s from queue",entry))
43373
43523
  t[entry]=nil
43374
43524
  end
43375
43525
  end
43376
43526
  end
43377
- function RAT:_ATCRegisterFlight(name,time)
43378
- BASE:T(RAT.id.."Flight "..name.." registered at ATC for landing clearance.")
43527
+ function RAT._ATCRegisterFlight(name,time)
43528
+ BASE:I(RAT.id..string.format("Flight %s registered at ATC for landing clearance.",name))
43379
43529
  RAT.ATC.flight[name].Tarrive=time
43380
43530
  RAT.ATC.flight[name].holding=0
43381
43531
  end
43382
- function RAT:_ATCStatus()
43532
+ function RAT._ATCStatus()
43383
43533
  local Tnow=timer.getTime()
43384
- for name,_ in pairs(RAT.ATC.flight)do
43534
+ for name,_flight in pairs(RAT.ATC.flight)do
43535
+ local flight=_flight
43385
43536
  local hold=RAT.ATC.flight[name].holding
43386
43537
  local dest=RAT.ATC.flight[name].destination
43538
+ local airport=RAT.ATC.airport[dest]
43539
+ if airport then
43387
43540
  if hold>=0 then
43388
43541
  local busy="Runway state is unknown"
43389
- if RAT.ATC.airport[dest].Nonfinal>0 then
43390
- busy="Runway is occupied by "..RAT.ATC.airport[dest].Nonfinal
43542
+ if airport.Nonfinal>0 then
43543
+ busy="Runway is occupied by "..airport.Nonfinal
43391
43544
  else
43392
43545
  busy="Runway is currently clear"
43393
43546
  end
43394
43547
  local text=string.format("ATC %s: Flight %s is holding for %i:%02d. %s.",dest,name,hold/60,hold%60,busy)
43395
- BASE:T(RAT.id..text)
43548
+ BASE:I(RAT.id..text)
43396
43549
  elseif hold==RAT.ATC.onfinal then
43397
- local Tfinal=Tnow-RAT.ATC.flight[name].Tonfinal
43550
+ local Tfinal=Tnow-flight.Tonfinal
43398
43551
  local text=string.format("ATC %s: Flight %s is on final. Waiting %i:%02d for landing event.",dest,name,Tfinal/60,Tfinal%60)
43399
- BASE:T(RAT.id..text)
43552
+ BASE:I(RAT.id..text)
43400
43553
  elseif hold==RAT.ATC.unregistered then
43401
43554
  else
43402
43555
  BASE:E(RAT.id.."ERROR: Unknown holding time in RAT:_ATCStatus().")
43403
43556
  end
43557
+ else
43404
43558
  end
43405
43559
  end
43406
- function RAT:_ATCCheck()
43407
- RAT:_ATCQueue()
43408
- local Tnow=timer.getTime()
43409
- for name,_ in pairs(RAT.ATC.airport)do
43410
- for qID,flight in ipairs(RAT.ATC.airport[name].queue)do
43411
- local nqueue=#RAT.ATC.airport[name].queue
43412
- local landing1
43413
- if RAT.ATC.airport[name].Tlastclearance then
43414
- landing1=(Tnow-RAT.ATC.airport[name].Tlastclearance>RAT.ATC.delay)and RAT.ATC.airport[name].Nonfinal<RAT.ATC.Nclearance
43415
- else
43416
- landing1=false
43417
43560
  end
43418
- local landing2=RAT.ATC.airport[name].Nonfinal==0
43561
+ function RAT._ATCCheck()
43562
+ RAT._ATCQueue()
43563
+ local Tnow=timer.getTime()
43564
+ for airportname,_airport in pairs(RAT.ATC.airport)do
43565
+ local airport=_airport
43566
+ for qID,flightname in pairs(airport.queue)do
43567
+ local flight=RAT.ATC.flight[flightname]
43568
+ local nqueue=#airport.queue
43569
+ local landing1=false
43570
+ if airport.Tlastclearance then
43571
+ landing1=(Tnow-airport.Tlastclearance>RAT.ATC.delay)and airport.Nonfinal<RAT.ATC.Nclearance
43572
+ end
43573
+ local landing2=airport.Nonfinal==0
43419
43574
  if not landing1 and not landing2 then
43420
- RAT.ATC.flight[flight].holding=Tnow-RAT.ATC.flight[flight].Tarrive
43421
- local text=string.format("ATC %s: Flight %s runway is busy. You are #%d of %d in landing queue. Your holding time is %i:%02d.",name,flight,qID,nqueue,RAT.ATC.flight[flight].holding/60,RAT.ATC.flight[flight].holding%60)
43422
- BASE:T(RAT.id..text)
43575
+ flight.holding=Tnow-flight.Tarrive
43576
+ local text=string.format("ATC %s: Flight %s runway is busy. You are #%d of %d in landing queue. Your holding time is %i:%02d.",
43577
+ airportname,flightname,qID,nqueue,flight.holding/60,flight.holding%60)
43578
+ BASE:I(RAT.id..text)
43423
43579
  else
43424
- local text=string.format("ATC %s: Flight %s was cleared for landing. Your holding time was %i:%02d.",name,flight,RAT.ATC.flight[flight].holding/60,RAT.ATC.flight[flight].holding%60)
43425
- BASE:T(RAT.id..text)
43426
- RAT:_ATCClearForLanding(name,flight)
43580
+ local text=string.format("ATC %s: Flight %s was cleared for landing. Your holding time was %i:%02d.",
43581
+ airportname,flightname,flight.holding/60,flight.holding%60)
43582
+ BASE:I(RAT.id..text)
43583
+ RAT._ATCClearForLanding(airportname,flightname)
43584
+ end
43427
43585
  end
43428
43586
  end
43587
+ RAT._ATCQueue()
43429
43588
  end
43430
- RAT:_ATCQueue()
43589
+ function RAT._ATCClearForLanding(airportname,flightname)
43590
+ local flightgroup=_DATABASE:FindOpsGroup(flightname)
43591
+ if flightgroup then
43592
+ flightgroup:ClearToLand()
43593
+ local flight=RAT.ATC.flight[flightname]
43594
+ flight.holding=RAT.ATC.onfinal
43595
+ flight.Tonfinal=timer.getTime()
43596
+ local airport=RAT.ATC.airport[airportname]
43597
+ airport.busy=true
43598
+ airport.onfinal[flightname]=flight
43599
+ airport.Nonfinal=airport.Nonfinal+1
43600
+ airport.Tlastclearance=timer.getTime()
43601
+ BASE:I(RAT.id..string.format("ATC %s: Flight %s cleared for landing",airportname,flightname))
43602
+ if string.find(flightname,"#")then
43603
+ flightname=string.match(flightname,"^(.+)#")
43431
43604
  end
43432
- function RAT:_ATCClearForLanding(airport,flight)
43433
- RAT.ATC.flight[flight].holding=RAT.ATC.onfinal
43434
- RAT.ATC.airport[airport].busy=true
43435
- RAT.ATC.airport[airport].onfinal[flight]=flight
43436
- RAT.ATC.airport[airport].Nonfinal=RAT.ATC.airport[airport].Nonfinal+1
43437
- RAT.ATC.airport[airport].Tlastclearance=timer.getTime()
43438
- RAT.ATC.flight[flight].Tonfinal=timer.getTime()
43439
- trigger.action.setUserFlag(flight,1)
43440
- local flagvalue=trigger.misc.getUserFlag(flight)
43441
- local text1=string.format("ATC %s: Flight %s cleared for landing (flag=%d).",airport,flight,flagvalue)
43442
- if string.find(flight,"#")then
43443
- flight=string.match(flight,"^(.+)#")
43605
+ local text=string.format("ATC %s: Flight %s you are cleared for landing.",airportname,flightname)
43606
+ MESSAGE:New(text,10):ToAllIf(RAT.ATC.messages)
43607
+ else
43608
+ BASE:E("Could not clear flight for landing!")
43444
43609
  end
43445
- local text2=string.format("ATC %s: Flight %s you are cleared for landing.",airport,flight)
43446
- BASE:T(RAT.id..text1)
43447
- MESSAGE:New(text2,10):ToAllIf(RAT.ATC.messages)
43448
43610
  end
43449
- function RAT:_ATCFlightLanded(name)
43450
- if RAT.ATC.flight[name]then
43451
- local dest=RAT.ATC.flight[name].destination
43611
+ function RAT._ATCFlightLanded(name)
43612
+ local flight=RAT.ATC.flight[name]
43613
+ if flight then
43614
+ local dest=flight.destination
43452
43615
  local Tnow=timer.getTime()
43453
- local Tfinal=Tnow-RAT.ATC.flight[name].Tonfinal
43454
- local Thold=RAT.ATC.flight[name].Tonfinal-RAT.ATC.flight[name].Tarrive
43455
- RAT.ATC.airport[dest].busy=false
43456
- RAT.ATC.airport[dest].onfinal[name]=nil
43457
- RAT.ATC.airport[dest].Nonfinal=RAT.ATC.airport[dest].Nonfinal-1
43458
- RAT:_ATCDelFlight(RAT.ATC.flight,name)
43459
- RAT.ATC.airport[dest].traffic=RAT.ATC.airport[dest].traffic+1
43460
- local TrafficPerHour=RAT.ATC.airport[dest].traffic/(timer.getTime()-RAT.ATC.T0)*3600
43461
- local text1=string.format("ATC %s: Flight %s landed. Tholding = %i:%02d, Tfinal = %i:%02d.",dest,name,Thold/60,Thold%60,Tfinal/60,Tfinal%60)
43462
- local text2=string.format("ATC %s: Number of flights still on final %d.",dest,RAT.ATC.airport[dest].Nonfinal)
43463
- local text3=string.format("ATC %s: Traffic report: Number of planes landed in total %d. Flights/hour = %3.2f.",dest,RAT.ATC.airport[dest].traffic,TrafficPerHour)
43616
+ local Tfinal=Tnow-flight.Tonfinal
43617
+ local Thold=flight.Tonfinal-flight.Tarrive
43618
+ local airport=RAT.ATC.airport[dest]
43619
+ airport.busy=false
43620
+ airport.onfinal[name]=nil
43621
+ airport.Nonfinal=airport.Nonfinal-1
43622
+ RAT._ATCDelFlight(RAT.ATC.flight,name)
43623
+ airport.traffic=airport.traffic+1
43624
+ local TrafficPerHour=airport.traffic/(timer.getTime()-RAT.ATC.T0)*3600
43625
+ BASE:I(RAT.id..string.format("ATC %s: Flight %s landed. Tholding = %i:%02d, Tfinal = %i:%02d.",dest,name,Thold/60,Thold%60,Tfinal/60,Tfinal%60))
43626
+ BASE:I(RAT.id..string.format("ATC %s: Number of flights still on final %d.",dest,airport.Nonfinal))
43627
+ BASE:I(RAT.id..string.format("ATC %s: Traffic report: Number of planes landed in total %d. Flights/hour = %3.2f.",dest,airport.traffic,TrafficPerHour))
43464
43628
  if string.find(name,"#")then
43465
43629
  name=string.match(name,"^(.+)#")
43466
43630
  end
43467
- local text4=string.format("ATC %s: Flight %s landed. Welcome to %s.",dest,name,dest)
43468
- BASE:T(RAT.id..text1)
43469
- BASE:T(RAT.id..text2)
43470
- BASE:T(RAT.id..text3)
43471
- MESSAGE:New(text4,10):ToAllIf(RAT.ATC.messages)
43631
+ local text=string.format("ATC %s: Flight %s landed. Welcome to %s.",dest,name,dest)
43632
+ MESSAGE:New(text,10):ToAllIf(RAT.ATC.messages)
43472
43633
  end
43473
43634
  end
43474
- function RAT:_ATCQueue()
43635
+ function RAT._ATCQueue()
43636
+ local Tnow=timer.getTime()
43475
43637
  for airport,_ in pairs(RAT.ATC.airport)do
43476
43638
  local _queue={}
43477
- for name,_ in pairs(RAT.ATC.flight)do
43478
- local Tnow=timer.getTime()
43479
- if RAT.ATC.flight[name].holding>=0 then
43480
- RAT.ATC.flight[name].holding=Tnow-RAT.ATC.flight[name].Tarrive
43639
+ for name,_flight in pairs(RAT.ATC.flight)do
43640
+ local flight=_flight
43641
+ if flight.holding>=0 then
43642
+ flight.holding=Tnow-flight.Tarrive
43481
43643
  end
43482
- local hold=RAT.ATC.flight[name].holding
43483
- local dest=RAT.ATC.flight[name].destination
43644
+ local hold=flight.holding
43645
+ local dest=flight.destination
43484
43646
  if hold>=0 and airport==dest then
43485
43647
  _queue[#_queue+1]={name,hold}
43486
43648
  end
@@ -43514,7 +43676,7 @@ RATMANAGER.id="RATMANAGER | "
43514
43676
  function RATMANAGER:New(ntot)
43515
43677
  local self=BASE:Inherit(self,BASE:New())
43516
43678
  self.ntot=ntot or 1
43517
- self:E(RATMANAGER.id..string.format("Creating manager for %d groups.",ntot))
43679
+ self:I(RATMANAGER.id..string.format("Creating manager for %d groups",ntot))
43518
43680
  return self
43519
43681
  end
43520
43682
  function RATMANAGER:Add(ratobject,min)
@@ -43531,7 +43693,8 @@ ratobject:Spawn(0)
43531
43693
  return self
43532
43694
  end
43533
43695
  function RATMANAGER:Start(delay)
43534
- local delay=delay or 5
43696
+ delay=delay or 5
43697
+ if delay and delay>0 then
43535
43698
  local text=string.format(RATMANAGER.id.."RAT manager will be started in %d seconds.\n",delay)
43536
43699
  text=text..string.format("Managed groups:\n")
43537
43700
  for i=1,self.nrat do
@@ -43539,10 +43702,8 @@ text=text..string.format("- %s with min groups %d\n",self.name[i],self.min[i])
43539
43702
  end
43540
43703
  text=text..string.format("Number of constantly alive groups %d",self.ntot)
43541
43704
  self:E(text)
43542
- SCHEDULER:New(nil,self._Start,{self},delay)
43543
- return self
43544
- end
43545
- function RATMANAGER:_Start()
43705
+ self:ScheduleOnce(delay,RATMANAGER.Start,self,0)
43706
+ else
43546
43707
  local n=0
43547
43708
  for i=1,self.nrat do
43548
43709
  n=n+self.min[i]
@@ -43553,30 +43714,32 @@ local time=0.0
43553
43714
  for i=1,self.nrat do
43554
43715
  for j=1,N[i]do
43555
43716
  time=time+self.dTspawn
43556
- SCHEDULER:New(nil,RAT._SpawnWithRoute,{self.rat[i]},time)
43717
+ self:ScheduleOnce(time,RAT._SpawnWithRoute,self.rat[i])
43557
43718
  end
43558
43719
  end
43559
43720
  for i=1,self.nrat do
43560
- if self.rat[i].uncontrolled and self.rat[i].activate_uncontrolled then
43561
- local Tactivate=math.max(time+1,self.rat[i].activate_delay)
43562
- SCHEDULER:New(self.rat[i],self.rat[i]._ActivateUncontrolled,{self.rat[i]},Tactivate,self.rat[i].activate_delta,self.rat[i].activate_frand)
43721
+ local rat=self.rat[i]
43722
+ if rat.uncontrolled and rat.activate_uncontrolled then
43723
+ local Tactivate=math.max(time+1,rat.activate_delay)
43724
+ self:ScheduleRepeat(Tactivate,rat.activate_delta,rat.activate_frand,nil,rat._ActivateUncontrolled,rat)
43563
43725
  end
43564
43726
  end
43565
43727
  local TstartManager=math.max(time+1,self.Tcheck)
43566
43728
  self.manager,self.managerid=SCHEDULER:New(self,self._Manage,{self},TstartManager,self.Tcheck)
43567
43729
  local text=string.format(RATMANAGER.id.."Starting RAT manager with scheduler ID %s in %d seconds. Repeat interval %d seconds.",self.managerid,TstartManager,self.Tcheck)
43568
- self:E(text)
43730
+ self:I(text)
43731
+ end
43569
43732
  return self
43570
43733
  end
43571
43734
  function RATMANAGER:Stop(delay)
43572
43735
  delay=delay or 1
43573
- self:E(string.format(RATMANAGER.id.."Manager will be stopped in %d seconds.",delay))
43574
- SCHEDULER:New(nil,self._Stop,{self},delay)
43575
- return self
43576
- end
43577
- function RATMANAGER:_Stop()
43578
- self:E(string.format(RATMANAGER.id.."Stopping manager with scheduler ID %s.",self.managerid))
43736
+ if delay and delay>0 then
43737
+ self:I(RATMANAGER.id..string.format("Manager will be stopped in %d seconds.",delay))
43738
+ self:ScheduleOnce(delay,RATMANAGER.Stop,self,0)
43739
+ else
43740
+ self:I(RATMANAGER.id..string.format("Stopping manager with scheduler ID %s",self.managerid))
43579
43741
  self.manager:Stop(self.managerid)
43742
+ end
43580
43743
  return self
43581
43744
  end
43582
43745
  function RATMANAGER:SetTcheck(dt)
@@ -43589,15 +43752,14 @@ return self
43589
43752
  end
43590
43753
  function RATMANAGER:_Manage()
43591
43754
  local ntot=self:_Count()
43592
- local text=string.format("Number of alive groups %d. New groups to be spawned %d.",ntot,self.ntot-ntot)
43593
- self:T(RATMANAGER.id..text)
43755
+ self:T(RATMANAGER.id..string.format("Number of alive groups %d. New groups to be spawned %d.",ntot,self.ntot-ntot))
43594
43756
  local N=self:_RollDice(self.nrat,self.ntot,self.min,self.alive)
43595
43757
  local time=0.0
43596
43758
  for i=1,self.nrat do
43597
43759
  for j=1,N[i]do
43598
43760
  time=time+self.dTspawn
43599
43761
  self.planned[i]=self.planned[i]+1
43600
- SCHEDULER:New(nil,RATMANAGER._Spawn,{self,i},time)
43762
+ self:ScheduleOnce(time,RATMANAGER._Spawn,self,i)
43601
43763
  end
43602
43764
  end
43603
43765
  end
@@ -59420,6 +59582,7 @@ brc=self:GetBRCintoWind(self.recoverywindow.SPEED)
59420
59582
  end
59421
59583
  flight.Tcharlie=self:_GetCharlieTime(flight)
59422
59584
  local Ccharlie=UTILS.SecondsToClock(flight.Tcharlie)
59585
+ brc=brc%360
59423
59586
  self:_MarshalCallArrived(flight.onboard,flight.case,brc,alt,Ccharlie,P)
59424
59587
  if self.TACANon and(not flight.ai)and flight.difficulty==AIRBOSS.Difficulty.EASY then
59425
59588
  local radial=self:GetRadial(flight.case,true,true,true)
@@ -59783,7 +59946,7 @@ playerData.stable=false
59783
59946
  playerData.landed=false
59784
59947
  playerData.Tlso=timer.getTime()
59785
59948
  playerData.Tgroove=nil
59786
- playerData.TIG0=nil
59949
+ playerData.TIG0=0
59787
59950
  playerData.wire=nil
59788
59951
  playerData.flag=-100
59789
59952
  playerData.debriefschedulerID=nil
@@ -60813,77 +60976,9 @@ if self:_CheckAbort(X,Z,self.BreakEntry)then
60813
60976
  self:_AbortPattern(playerData,X,Z,self.BreakEntry,true)
60814
60977
  return
60815
60978
  end
60816
- local stern=self:_GetSternCoord()
60817
- local coord=playerData.unit:GetCoordinate()
60818
- local dist=coord:Get2DDistance(stern)
60819
- local playerCallsign=playerData.unit:GetCallsign()
60820
- local playerName=playerData.name
60821
- local unit=playerData.unit
60822
- local unitClient=Unit.getByName(unit:GetName())
60823
- local hookArgument=unitClient:getDrawArgumentValue(25)
60824
- local hookArgument_Tomcat=unitClient:getDrawArgumentValue(1305)
60825
- local speedMPS=playerData.unit:GetVelocityMPS()
60826
- local speedKTS=UTILS.MpsToKnots(speedMPS)
60827
- local player_alt=playerData.unit:GetAltitude()
60828
- player_alt_feet=player_alt*3.28
60829
- player_alt_feet=player_alt_feet/10
60830
- player_alt_feet=math.floor(player_alt_feet)*10
60831
- local player_velocity_round=speedKTS*1.00
60832
- player_velocity_round=player_velocity_round/10
60833
- player_velocity_round=math.floor(player_velocity_round)*10
60834
- local player_alt_feet=player_alt*3.28
60835
- player_alt_feet=player_alt_feet/10
60836
- player_alt_feet=math.floor(player_alt_feet)*10
60837
- local Play_SH_Sound=USERSOUND:New("Airboss Soundfiles/GreatBallsOfFire.ogg")
60838
- local Play_666SH_Sound=USERSOUND:New("Airboss Soundfiles/Runninwiththedevil.ogg")
60839
- local playerType=playerData.actype
60840
- if dist<1000 and clientSHBFlag==false then
60841
- if speedKTS>450 and speedKTS<590 then
60842
- if player_alt_feet<1500 then
60843
- if hookArgument>0 or hookArgument_Tomcat>0 then
60844
- playerData.shb=true
60845
- trigger.action.outText(playerName..' performing a Sierra Hotel Break in a '..playerType,10)
60846
- local sh_message_to_discord=('**'..playerName..' is performing a Sierra Hotel Break in a '..playerType..' at '..player_velocity_round..' knots and '..player_alt_feet..' feet!**')
60847
- HypeMan.sendBotMessage(sh_message_to_discord)
60848
- Play_SH_Sound:ToAll()
60849
- clientSHBFlag=true
60850
- else
60851
- playerData.shb=false
60852
- end
60853
- else
60854
- end
60855
- elseif speedKTS>589 then
60856
- if player_alt_feet<625 and player_alt_feet>575 then
60857
- if hookArgument>0 or hookArgument_Tomcat>0 then
60858
- playerData.shb=true
60859
- trigger.action.outText(playerName..' performing a 666 Sierra Hotel Break in a '..playerType,10)
60860
- local sh_message_to_discord=('**'..playerName..' is performing a 666 Sierra Hotel Break in a '..playerType..' at '..player_velocity_round..' knots and '..player_alt_feet..' feet!**')
60861
- HypeMan.sendBotMessage(sh_message_to_discord)
60862
- Play_666SH_Sound:ToAll()
60863
- clientSHBFlag=true
60864
- else
60865
- playerData.shb=false
60866
- end
60867
- else
60868
- if hookArgument>0 or hookArgument_Tomcat>0 then
60869
- playerData.shb=true
60870
- trigger.action.outText(playerName..' performing a Sierra Hotel Break in a '..playerType,10)
60871
- local sh_message_to_discord=('**'..playerName..' is performing a Sierra Hotel Break in a '..playerType..' at '..player_velocity_round..' knots and '..player_alt_feet..' feet!**')
60872
- HypeMan.sendBotMessage(sh_message_to_discord)
60873
- Play_SH_Sound:ToAll()
60874
- clientSHBFlag=true
60875
- else
60876
- playerData.shb=false
60877
- end
60878
- end
60879
- else
60880
- end
60881
- else
60882
- end
60883
60979
  if self:_CheckLimits(X,Z,self.BreakEntry)then
60884
60980
  self:_PlayerHint(playerData)
60885
60981
  self:_SetPlayerStep(playerData,AIRBOSS.PatternStep.EARLYBREAK)
60886
- clientSHBFlag=false
60887
60982
  end
60888
60983
  end
60889
60984
  function AIRBOSS:_Break(playerData,part)
@@ -61171,19 +61266,19 @@ end
61171
61266
  if rho>=RAR and rho<=RIM then
61172
61267
  if gd.LUE>0.22 and lineupError<-0.22 then
61173
61268
  env.info" Drift Right across centre ==> DR-"
61174
- gd.Drift=" DR"
61269
+ gd.Drift="DR"
61175
61270
  self:T(self.lid..string.format("Got Drift Right across centre step %s, d=%.3f: Max LUE=%.3f, lower LUE=%.3f",gs,d,gd.LUE,lineupError))
61176
61271
  elseif gd.LUE<-0.22 and lineupError>0.22 then
61177
61272
  env.info" Drift Left ==> DL-"
61178
- gd.Drift=" DL"
61273
+ gd.Drift="DL"
61179
61274
  self:T(self.lid..string.format("Got Drift Left across centre at step %s, d=%.3f: Min LUE=%.3f, lower LUE=%.3f",gs,d,gd.LUE,lineupError))
61180
61275
  elseif gd.LUE>0.13 and lineupError<-0.14 then
61181
61276
  env.info" Little Drift Right across centre ==> (DR-)"
61182
- gd.Drift=" (DR)"
61277
+ gd.Drift="(DR)"
61183
61278
  self:T(self.lid..string.format("Got Little Drift Right across centre at step %s, d=%.3f: Max LUE=%.3f, lower LUE=%.3f",gs,d,gd.LUE,lineupError))
61184
61279
  elseif gd.LUE<-0.13 and lineupError>0.14 then
61185
61280
  env.info" Little Drift Left across centre ==> (DL-)"
61186
- gd.Drift=" (DL)"
61281
+ gd.Drift="(DL)"
61187
61282
  self:E(self.lid..string.format("Got Little Drift Left across centre at step %s, d=%.3f: Min LUE=%.3f, lower LUE=%.3f",gs,d,gd.LUE,lineupError))
61188
61283
  end
61189
61284
  end
@@ -61982,9 +62077,7 @@ local hdg=self.carrier:GetHeading()
61982
62077
  if magnetic then
61983
62078
  hdg=hdg-self.magvar
61984
62079
  end
61985
- if hdg<0 then
61986
- hdg=hdg+360
61987
- end
62080
+ hdg=hdg%360
61988
62081
  return hdg
61989
62082
  end
61990
62083
  function AIRBOSS:GetBRC()
@@ -62083,7 +62176,7 @@ theta=math.asin(vdeck*math.sin(alpha)/vwind)
62083
62176
  v=vdeck*math.cos(alpha)-vwind*math.cos(theta)
62084
62177
  end
62085
62178
  local magvar=magnetic and self.magvar or 0
62086
- local intowind=self:GetHeadingIntoWind_old(vdeck)
62179
+ local intowind=self:GetHeadingIntoWind_old(vdeck,magnetic)
62087
62180
  return intowind,v
62088
62181
  end
62089
62182
  function AIRBOSS:GetBRCintoWind(vdeck)
@@ -62274,7 +62367,7 @@ return select(2,string.gsub(base,pattern,""))
62274
62367
  end
62275
62368
  local TIG=""
62276
62369
  if playerData.Tgroove and playerData.Tgroove<=360 and playerData.case<3 then
62277
- TIG=self:_EvalGrooveTime(playerData)
62370
+ TIG=self:_EvalGrooveTime(playerData)or"N/A"
62278
62371
  end
62279
62372
  local GXX,nXX=self:_Flightdata2Text(playerData,AIRBOSS.GroovePos.XX)
62280
62373
  local GIM,nIM=self:_Flightdata2Text(playerData,AIRBOSS.GroovePos.IM)
@@ -62396,14 +62489,8 @@ grade="CUT"
62396
62489
  points=0.0
62397
62490
  end
62398
62491
  end
62399
- if playerData.wire==1 and points>1 then
62400
- if points==4 then
62401
- points=3
62402
- grade="(OK)"
62403
- elseif points==3 then
62404
- points=2
62405
- grade="--"
62406
- end
62492
+ if playerData.wire==1 and points>=3 and N>4 then
62493
+ points=points-1
62407
62494
  end
62408
62495
  env.info("Returning: "..grade.." "..points.." "..G)
62409
62496
  return grade,points,G
@@ -62451,6 +62538,7 @@ O=little("OS")
62451
62538
  end
62452
62539
  end
62453
62540
  local S=nil
62541
+ local A=nil
62454
62542
  if step~=AIRBOSS.PatternStep.GROOVE_IW then
62455
62543
  if AIRBOSS.PatternStep.GROOVE_AR and playerData.waveoff==true and playerData.owo==true then
62456
62544
  else
@@ -62467,7 +62555,6 @@ S="F"
62467
62555
  elseif AOA<acaoa.OnSpeedMin then
62468
62556
  S=little("F")
62469
62557
  end
62470
- local A=nil
62471
62558
  if GSE>self.gle.HIGH then
62472
62559
  A=underline("H")
62473
62560
  elseif GSE>self.gle.High then
@@ -69139,6 +69226,7 @@ CTLD.UnitTypeCapabilities={
69139
69226
  ["Mi-24V"]={type="Mi-24V",crates=true,troops=true,cratelimit=2,trooplimit=8,length=18,cargoweightlimit=700},
69140
69227
  ["Hercules"]={type="Hercules",crates=true,troops=true,cratelimit=7,trooplimit=64,length=25,cargoweightlimit=19000},
69141
69228
  ["UH-60L"]={type="UH-60L",crates=true,troops=true,cratelimit=2,trooplimit=20,length=16,cargoweightlimit=3500},
69229
+ ["UH-60L_DAP"]={type="UH-60L_DAP",crates=false,troops=true,cratelimit=0,trooplimit=2,length=16,cargoweightlimit=500},
69142
69230
  ["MH-60R"]={type="MH-60R",crates=true,troops=true,cratelimit=2,trooplimit=20,length=16,cargoweightlimit=3500},
69143
69231
  ["SH-60B"]={type="SH-60B",crates=true,troops=true,cratelimit=2,trooplimit=20,length=16,cargoweightlimit=3500},
69144
69232
  ["AH-64D_BLK_II"]={type="AH-64D_BLK_II",crates=false,troops=true,cratelimit=0,trooplimit=2,length=17,cargoweightlimit=200},
@@ -69154,7 +69242,7 @@ CTLD.FixedWingTypes={
69154
69242
  ["Bronco"]="Bronco",
69155
69243
  ["Mosquito"]="Mosquito",
69156
69244
  }
69157
- CTLD.version="1.3.37"
69245
+ CTLD.version="1.3.38"
69158
69246
  function CTLD:New(Coalition,Prefixes,Alias)
69159
69247
  local self=BASE:Inherit(self,FSM:New())
69160
69248
  BASE:T({Coalition,Prefixes,Alias})
@@ -69256,6 +69344,7 @@ self.dropAsCargoCrate=false
69256
69344
  self.smokedistance=2000
69257
69345
  self.movetroopstowpzone=true
69258
69346
  self.movetroopsdistance=5000
69347
+ self.returntroopstobase=true
69259
69348
  self.troopdropzoneradius=100
69260
69349
  self.VehicleMoveFormation=AI.Task.VehicleFormation.VEE
69261
69350
  self.enableHercules=false
@@ -70360,6 +70449,7 @@ self:_UpdateUnitCargoMass(Unit)
70360
70449
  self:_RefreshDropCratesMenu(Group,Unit)
70361
70450
  self:_RefreshLoadCratesMenu(Group,Unit)
70362
70451
  self:_CleanupTrackedCrates(crateidsloaded)
70452
+ self:__CratesPickedUp(1,Group,Unit,loaded.Cargo)
70363
70453
  end
70364
70454
  end
70365
70455
  return self
@@ -70627,7 +70717,7 @@ if not inzone then
70627
70717
  inzone,zonename,zone,distance=self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
70628
70718
  end
70629
70719
  if inzone then
70630
- droppingatbase=true
70720
+ droppingatbase=self.returntroopstobase
70631
70721
  end
70632
70722
  local hoverunload=self:IsCorrectHover(Unit)
70633
70723
  local IsHerc=self:IsFixedWing(Unit)
@@ -71358,7 +71448,7 @@ end
71358
71448
  end
71359
71449
  end
71360
71450
  else
71361
- if self.usesubcats then
71451
+ if self.usesubcats==true then
71362
71452
  local subcatmenus={}
71363
71453
  for catName,_ in pairs(self.subcats)do
71364
71454
  subcatmenus[catName]=MENU_GROUP:New(_group,catName,cratesmenu)
@@ -71817,7 +71907,7 @@ if not inzone then
71817
71907
  inzone,zonename,zone,distance=self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
71818
71908
  end
71819
71909
  if inzone then
71820
- droppingatbase=true
71910
+ droppingatbase=self.returntroopstobase
71821
71911
  end
71822
71912
  if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName())then
71823
71913
  self:_SendMessage("You need to open the door(s) to unload troops!",10,false,Group)
@@ -72198,7 +72288,12 @@ self:E(self.lid.."**** Ship does not exist: "..Name)
72198
72288
  return self
72199
72289
  end
72200
72290
  end
72201
- local ctldzone={}
72291
+ local exists=true
72292
+ local ctldzone=self:GetCTLDZone(Name,Type)
72293
+ if not ctldzone then
72294
+ exists=false
72295
+ ctldzone={}
72296
+ end
72202
72297
  ctldzone.active=Active or false
72203
72298
  ctldzone.color=Color or SMOKECOLOR.Red
72204
72299
  ctldzone.name=Name or"NONE"
@@ -72221,9 +72316,45 @@ if Type==CTLD.CargoZoneType.SHIP then
72221
72316
  ctldzone.shiplength=Shiplength or 100
72222
72317
  ctldzone.shipwidth=Shipwidth or 10
72223
72318
  end
72319
+ if not exists then
72224
72320
  self:AddZone(ctldzone)
72321
+ end
72225
72322
  return self
72226
72323
  end
72324
+ function CTLD:GetCTLDZone(Name,Type)
72325
+ if Type==CTLD.CargoZoneType.LOAD then
72326
+ for _,z in pairs(self.pickupZones)do
72327
+ if z.name==Name then
72328
+ return z
72329
+ end
72330
+ end
72331
+ elseif Type==CTLD.CargoZoneType.DROP then
72332
+ for _,z in pairs(self.dropOffZones)do
72333
+ if z.name==Name then
72334
+ return z
72335
+ end
72336
+ end
72337
+ elseif Type==CTLD.CargoZoneType.SHIP then
72338
+ for _,z in pairs(self.shipZones)do
72339
+ if z.name==Name then
72340
+ return z
72341
+ end
72342
+ end
72343
+ elseif Type==CTLD.CargoZoneType.BEACON then
72344
+ for _,z in pairs(self.droppedBeacons)do
72345
+ if z.name==Name then
72346
+ return z
72347
+ end
72348
+ end
72349
+ else
72350
+ for _,z in pairs(self.wpZones)do
72351
+ if z.name==Name then
72352
+ return z
72353
+ end
72354
+ end
72355
+ end
72356
+ return nil
72357
+ end
72227
72358
  function CTLD:AddCTLDZoneFromAirbase(AirbaseName,Type,Color,Active,HasBeacon)
72228
72359
  self:T(self.lid.." AddCTLDZoneFromAirbase")
72229
72360
  local AFB=AIRBASE:FindByName(AirbaseName)
@@ -74217,13 +74348,14 @@ CSAR.AircraftType["Mi-24P"]=8
74217
74348
  CSAR.AircraftType["Mi-24V"]=8
74218
74349
  CSAR.AircraftType["Bell-47"]=2
74219
74350
  CSAR.AircraftType["UH-60L"]=10
74351
+ CSAR.AircraftType["UH-60L_DAP"]=2
74220
74352
  CSAR.AircraftType["AH-64D_BLK_II"]=2
74221
74353
  CSAR.AircraftType["Bronco-OV-10A"]=2
74222
74354
  CSAR.AircraftType["MH-60R"]=10
74223
74355
  CSAR.AircraftType["OH-6A"]=2
74224
74356
  CSAR.AircraftType["OH58D"]=2
74225
74357
  CSAR.AircraftType["CH-47Fbl1"]=31
74226
- CSAR.version="1.0.33"
74358
+ CSAR.version="1.0.34"
74227
74359
  function CSAR:New(Coalition,Template,Alias)
74228
74360
  local self=BASE:Inherit(self,FSM:New())
74229
74361
  BASE:T({Coalition,Template,Alias})
@@ -74669,11 +74801,11 @@ return self
74669
74801
  end
74670
74802
  local initdcscoord=nil
74671
74803
  local initcoord=nil
74672
- if _event.id==EVENTS.Ejection then
74804
+ if _event.id==EVENTS.Ejection and _event.TgtDCSUnit then
74673
74805
  initdcscoord=_event.TgtDCSUnit:getPoint()
74674
74806
  initcoord=COORDINATE:NewFromVec3(initdcscoord)
74675
74807
  self:T({initdcscoord})
74676
- else
74808
+ elseif _event.IniDCSUnit then
74677
74809
  initdcscoord=_event.IniDCSUnit:getPoint()
74678
74810
  initcoord=COORDINATE:NewFromVec3(initdcscoord)
74679
74811
  self:T({initdcscoord})
@@ -74736,7 +74868,10 @@ return self
74736
74868
  end
74737
74869
  if _place:GetCoalition()==self.coalition or _place:GetCoalition()==coalition.side.NEUTRAL then
74738
74870
  self:__Landed(2,_event.IniUnitName,_place)
74739
- self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true,true)
74871
+ local IsHeloBase=false
74872
+ local ABName=_place:GetName()
74873
+ if ABName and string.find(ABName,"^H")then IsHeloBase=true end
74874
+ self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true,true,IsHeloBase)
74740
74875
  else
74741
74876
  self:T(string.format("Airfield %d, Unit %d",_place:GetCoalition(),_unit:GetCoalition()))
74742
74877
  end
@@ -75091,7 +75226,7 @@ else
75091
75226
  return false
75092
75227
  end
75093
75228
  end
75094
- function CSAR:_ScheduledSARFlight(heliname,groupname,isairport,noreschedule)
75229
+ function CSAR:_ScheduledSARFlight(heliname,groupname,isairport,noreschedule,IsHeloBase)
75095
75230
  self:T(self.lid.." _ScheduledSARFlight")
75096
75231
  self:T({heliname,groupname})
75097
75232
  local _heliUnit=self:_GetSARHeli(heliname)
@@ -75109,7 +75244,7 @@ self:T(self.lid.."[Drop off debug] Check distance to MASH for "..heliname.." Dis
75109
75244
  return
75110
75245
  end
75111
75246
  self:T(self.lid.."[Drop off debug] Check distance to MASH for "..heliname.." Distance km: "..math.floor(_dist/1000))
75112
- if(_dist<self.FARPRescueDistance or isairport)and _heliUnit:InAir()==false then
75247
+ if(_dist<self.FARPRescueDistance or isairport)and((_heliUnit:InAir()==false)or(IsHeloBase==true))then
75113
75248
  self:T(self.lid.."[Drop off debug] Distance ok, door check")
75114
75249
  if self.pilotmustopendoors and self:_IsLoadingDoorOpen(heliname)==false then
75115
75250
  self:_DisplayMessageToSAR(_heliUnit,"Open the door to let me out!",self.messageTime,true,true)
@@ -75122,7 +75257,7 @@ end
75122
75257
  end
75123
75258
  if not noreschedule then
75124
75259
  self:__Returning(5,heliname,_woundedGroupName,isairport)
75125
- self:ScheduleOnce(5,self._ScheduledSARFlight,self,heliname,groupname,isairport,noreschedule)
75260
+ self:ScheduleOnce(5,self._ScheduledSARFlight,self,heliname,groupname,isairport,noreschedule,IsHeloBase)
75126
75261
  end
75127
75262
  return self
75128
75263
  end