@jtff/miztemplate-lib 3.9.0 → 3.9.2

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-11T05:13:50+02:00-cda1432d048f5a8946e42833f7f560db16f57248 ***')
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
@@ -7726,10 +7800,12 @@ if Event.id==EVENTS.LandingAfterEjection then
7726
7800
  else
7727
7801
  if Event.place:isExist()and Object.getCategory(Event.place)~=Object.Category.SCENERY then
7728
7802
  Event.Place=AIRBASE:Find(Event.place)
7803
+ if Event.Place then
7729
7804
  Event.PlaceName=Event.Place:GetName()
7730
7805
  end
7731
7806
  end
7732
7807
  end
7808
+ end
7733
7809
  if Event.idx then
7734
7810
  Event.MarkID=Event.idx
7735
7811
  Event.MarkVec3=Event.pos
@@ -9553,10 +9629,9 @@ radius=ZoneRadius,
9553
9629
  }
9554
9630
  }
9555
9631
  local function EvaluateZone(ZoneObject)
9556
- if ZoneObject then
9632
+ if ZoneObject and self:IsVec3InZone(ZoneObject:getPoint())then
9557
9633
  local ObjectCategory=Object.getCategory(ZoneObject)
9558
9634
  if(ObjectCategory==Object.Category.UNIT and ZoneObject:isExist()and ZoneObject:isActive())or(ObjectCategory==Object.Category.STATIC and ZoneObject:isExist())then
9559
- local CoalitionDCSUnit=ZoneObject:getCoalition()
9560
9635
  local Include=false
9561
9636
  if not UnitCategories then
9562
9637
  Include=true
@@ -9918,6 +9993,16 @@ self.LastVec2=ZoneUNIT:GetVec2()
9918
9993
  _EVENTDISPATCHER:CreateEventNewZone(self)
9919
9994
  return self
9920
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
9921
10006
  function ZONE_UNIT:GetVec2()
9922
10007
  local ZoneVec2=self.ZoneUNIT:GetVec2()
9923
10008
  if ZoneVec2 then
@@ -9979,6 +10064,17 @@ ZoneVec2=self._.ZoneVec2Cache
9979
10064
  end
9980
10065
  return ZoneVec2
9981
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
9982
10078
  function ZONE_GROUP:GetRandomVec2()
9983
10079
  local Point={}
9984
10080
  local Vec2=self._.ZoneGROUP:GetVec2()
@@ -10607,10 +10703,9 @@ radius=ZoneRadius,
10607
10703
  }
10608
10704
  }
10609
10705
  local function EvaluateZone(ZoneObject)
10610
- if ZoneObject then
10706
+ if ZoneObject and self:IsVec3InZone(ZoneObject:getPoint())then
10611
10707
  local ObjectCategory=Object.getCategory(ZoneObject)
10612
10708
  if(ObjectCategory==Object.Category.UNIT and ZoneObject:isExist()and ZoneObject:isActive())or(ObjectCategory==Object.Category.STATIC and ZoneObject:isExist())then
10613
- local CoalitionDCSUnit=ZoneObject:getCoalition()
10614
10709
  local Include=false
10615
10710
  if not UnitCategories then
10616
10711
  Include=true
@@ -10629,7 +10724,7 @@ self.ScanData.Coalitions[CoalitionDCSUnit]=true
10629
10724
  self.ScanData.Units[ZoneObject]=ZoneObject
10630
10725
  end
10631
10726
  end
10632
- if ObjectCategory==Object.Category.SCENERY and self:IsVec3InZone(ZoneObject:getPoint())then
10727
+ if ObjectCategory==Object.Category.SCENERY then
10633
10728
  local SceneryType=ZoneObject:getTypeName()
10634
10729
  local SceneryName=ZoneObject:getName()
10635
10730
  self.ScanData.Scenery[SceneryType]=self.ScanData.Scenery[SceneryType]or{}
@@ -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
@@ -30291,19 +30444,25 @@ AIRBASE.Afghanistan={
30291
30444
  ["Urgoon_Heliport"]="Urgoon Heliport",
30292
30445
  }
30293
30446
  AIRBASE.Iraq={
30294
- ["Baghdad_International_Airport"]="Baghdad International Airport",
30295
- ["Sulaimaniyah_International_Airport"]="Sulaimaniyah International Airport",
30296
- ["Al_Sahra_Airport"]="Al-Sahra Airport",
30297
- ["Erbil_International_Airport"]="Erbil International Airport",
30298
- ["Al_Taji_Airport"]="Al-Taji Airport",
30299
30447
  ["Al_Asad_Airbase"]="Al-Asad Airbase",
30448
+ ["Al_Kut_Airport"]="Al-Kut Airport",
30449
+ ["Al_Sahra_Airport"]="Al-Sahra Airport",
30300
30450
  ["Al_Salam_Airbase"]="Al-Salam Airbase",
30451
+ ["Al_Taji_Airport"]="Al-Taji Airport",
30452
+ ["Al_Taquddum_Airport"]="Al-Taquddum Airport",
30453
+ ["Baghdad_International_Airport"]="Baghdad International Airport",
30301
30454
  ["Balad_Airbase"]="Balad Airbase",
30302
- ["Kirkuk_International_Airport"]="Kirkuk International Airport",
30303
30455
  ["Bashur_Airport"]="Bashur Airport",
30304
- ["Al_Taquddum_Airport"]="Al-Taquddum Airport",
30305
- ["Qayyarah_Airfield_West"]="Qayyarah Airfield West",
30456
+ ["Erbil_International_Airport"]="Erbil International Airport",
30457
+ ["H2_Airbase"]="H-2 Airbase",
30458
+ ["H3_Main_Airbase"]="H-3 Main Airbase",
30459
+ ["H3_Northwest_Airbase"]="H-3 Northwest Airbase",
30460
+ ["H3_Southwest_Airbase"]="H-3 Southwest Airbase",
30306
30461
  ["K1_Base"]="K1 Base",
30462
+ ["Kirkuk_International_Airport"]="Kirkuk International Airport",
30463
+ ["Mosul_International_Airport"]="Mosul International Airport",
30464
+ ["Qayyarah_Airfield_West"]="Qayyarah Airfield West",
30465
+ ["Sulaimaniyah_International_Airport"]="Sulaimaniyah International Airport",
30307
30466
  }
30308
30467
  AIRBASE.GermanyCW={
30309
30468
  ["Airracing_Frankfurt"]="Airracing Frankfurt",
@@ -30576,6 +30735,13 @@ end
30576
30735
  self:T2(string.format("Registered airbase %s",tostring(self.AirbaseName)))
30577
30736
  return self
30578
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
30579
30745
  function AIRBASE:_GetCategory()
30580
30746
  local name=self.AirbaseName
30581
30747
  local static=StaticObject.getByName(name)
@@ -32985,7 +33151,7 @@ self:SetLiquid(lqno,lqam)
32985
33151
  end
32986
33152
  end
32987
33153
  else
32988
- self:E("File for Liquids could not be found: "..tostring(Path).."\\"..tostring(Filename"_Liquids.csv"))
33154
+ self:E("File for Liquids could not be found: "..tostring(Path).."\\"..tostring(Filename).."_Liquids.csv")
32989
33155
  end
32990
33156
  end
32991
33157
  if self:IsLimitedAircraft()then
@@ -33003,7 +33169,7 @@ self:SetAmount(acname,acnumber)
33003
33169
  end
33004
33170
  end
33005
33171
  else
33006
- self:E("File for Aircraft could not be found: "..tostring(Path).."\\"..tostring(Filename"_Aircraft.csv"))
33172
+ self:E("File for Aircraft could not be found: "..tostring(Path).."\\"..tostring(Filename).."_Aircraft.csv")
33007
33173
  end
33008
33174
  end
33009
33175
  if self:IsLimitedWeapons()then
@@ -33032,7 +33198,7 @@ end
33032
33198
  end
33033
33199
  end
33034
33200
  else
33035
- self:E("File for Weapons could not be found: "..tostring(Path).."\\"..tostring(Filename"_Weapons.csv"))
33201
+ self:E("File for Weapons could not be found: "..tostring(Path).."\\"..tostring(Filename).."_Weapons.csv")
33036
33202
  end
33037
33203
  end
33038
33204
  return self
@@ -33103,6 +33269,8 @@ REMOVED="REMOVED",
33103
33269
  }
33104
33270
  DYNAMICCARGO.AircraftTypes={
33105
33271
  ["CH-47Fbl1"]="CH-47Fbl1",
33272
+ ["Mi-8MTV2"]="CH-47Fbl1",
33273
+ ["Mi-8MT"]="CH-47Fbl1",
33106
33274
  }
33107
33275
  DYNAMICCARGO.AircraftDimensions={
33108
33276
  ["CH-47Fbl1"]={
@@ -33111,8 +33279,20 @@ DYNAMICCARGO.AircraftDimensions={
33111
33279
  ["length"]=11,
33112
33280
  ["ropelength"]=30,
33113
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
+ },
33114
33294
  }
33115
- DYNAMICCARGO.version="0.0.7"
33295
+ DYNAMICCARGO.version="0.0.9"
33116
33296
  function DYNAMICCARGO:Register(CargoName)
33117
33297
  local self=BASE:Inherit(self,POSITIONABLE:New(CargoName))
33118
33298
  self.StaticName=CargoName
@@ -34725,7 +34905,9 @@ end
34725
34905
  end)
34726
34906
  self.AutoSavePath=SavePath
34727
34907
  self.AutoSave=AutoSave or true
34908
+ if self.AutoSave==true then
34728
34909
  self:OpenCSV(GameName)
34910
+ end
34729
34911
  return self
34730
34912
  end
34731
34913
  function SCORING:SetDisplayMessagePrefix(DisplayMessagePrefix)
@@ -35749,7 +35931,7 @@ TargetUnitCoalition=TargetUnitCoalition or""
35749
35931
  TargetUnitCategory=TargetUnitCategory or""
35750
35932
  TargetUnitType=TargetUnitType or""
35751
35933
  TargetUnitName=TargetUnitName or""
35752
- 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
35753
35935
  self.CSVFile:write(
35754
35936
  '"'..self.GameName..'"'..','..
35755
35937
  '"'..self.RunTime..'"'..','..
@@ -40445,22 +40627,22 @@ RAT.markerid=0
40445
40627
  RAT.MenuF10=nil
40446
40628
  RAT.id="RAT | "
40447
40629
  RAT.version={
40448
- version="2.3.9",
40630
+ version="3.0.0",
40449
40631
  print=true,
40450
40632
  }
40451
40633
  function RAT:New(groupname,alias)
40452
- BASE:F({groupname=groupname,alias=alias})
40453
40634
  self=BASE:Inherit(self,SPAWN:NewWithAlias(groupname,alias))
40635
+ self.lid=string.format("RAT %s | ",alias or groupname)
40454
40636
  if RAT.version.print then
40455
- env.info(RAT.id.."Version "..RAT.version.version)
40637
+ env.info(self.lid.."Version "..RAT.version.version)
40456
40638
  RAT.version.print=false
40457
40639
  end
40458
- 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))
40459
40641
  alias=alias or groupname
40460
40642
  self.alias=alias
40461
40643
  local DCSgroup=Group.getByName(groupname)
40462
40644
  if DCSgroup==nil then
40463
- 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))
40464
40646
  return nil
40465
40647
  end
40466
40648
  self.templategroup=GROUP:FindByName(groupname)
@@ -40470,6 +40652,36 @@ self:_InitAircraft(DCSgroup)
40470
40652
  self:_GetAirportsOfMap()
40471
40653
  return self
40472
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
40473
40685
  function RAT:Spawn(naircraft)
40474
40686
  if self.spawninitialized==true then
40475
40687
  self:E("ERROR: Spawn function should only be called once per RAT object! Exiting and returning nil.")
@@ -40479,7 +40691,7 @@ self.spawninitialized=true
40479
40691
  end
40480
40692
  self.ngroups=naircraft or 1
40481
40693
  if self.ATCswitch and not RAT.ATC.init then
40482
- self:_ATCInit(self.airports_map)
40694
+ RAT._ATCInit(self.airports_map)
40483
40695
  end
40484
40696
  if self.f10menu and not RAT.MenuF10 then
40485
40697
  RAT.MenuF10=MENU_MISSION:New("RAT")
@@ -40585,7 +40797,7 @@ text=text..string.format("- %s\n",livery)
40585
40797
  end
40586
40798
  end
40587
40799
  text=text..string.format("******************************************************\n")
40588
- self:T(RAT.id..text)
40800
+ self:T(self.lid..text)
40589
40801
  if self.f10menu then
40590
40802
  self.Menu[self.SubMenuName]=MENU_MISSION:New(self.SubMenuName,RAT.MenuF10)
40591
40803
  self.Menu[self.SubMenuName]["groups"]=MENU_MISSION:New("Groups",self.Menu[self.SubMenuName])
@@ -40599,7 +40811,7 @@ if self.takeoff==RAT.wp.runway and not self.random_departure then
40599
40811
  dt=math.max(dt,180)
40600
40812
  end
40601
40813
  local Tstop=Tstart+dt*(self.ngroups-1)
40602
- 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)
40603
40815
  self:HandleEvent(EVENTS.Birth,self._OnBirth)
40604
40816
  self:HandleEvent(EVENTS.EngineStartup,self._OnEngineStartup)
40605
40817
  self:HandleEvent(EVENTS.Takeoff,self._OnTakeoff)
@@ -40611,9 +40823,9 @@ self:HandleEvent(EVENTS.Hit,self._OnHit)
40611
40823
  if self.ngroups==0 then
40612
40824
  return nil
40613
40825
  end
40614
- 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)
40615
40827
  if self.uncontrolled and self.activate_uncontrolled then
40616
- 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)
40617
40829
  end
40618
40830
  return true
40619
40831
  end
@@ -40629,12 +40841,12 @@ end
40629
40841
  end
40630
40842
  if self.Ndeparture_Zones>0 and self.takeoff~=RAT.wp.air then
40631
40843
  self.takeoff=RAT.wp.air
40632
- 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))
40633
40845
  end
40634
40846
  if self.Ndeparture_Airports==0 and self.Ndeparture_Zone==0 then
40635
40847
  self.random_departure=true
40636
40848
  local text=string.format("No airports or zones found given in SetDeparture(). Enabling random departure airports for RAT group %s!",self.alias)
40637
- self:E(RAT.id.."ERROR: "..text)
40849
+ self:E(self.lid.."ERROR: "..text)
40638
40850
  MESSAGE:New(text,30):ToAll()
40639
40851
  end
40640
40852
  end
@@ -40649,17 +40861,17 @@ end
40649
40861
  if self.Ndestination_Zones>0 and self.landing~=RAT.wp.air and not self.returnzone then
40650
40862
  self.landing=RAT.wp.air
40651
40863
  self.destinationzone=true
40652
- 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!")
40653
40865
  end
40654
40866
  if self.Ndestination_Airports==0 and self.Ndestination_Zones==0 then
40655
40867
  self.random_destination=true
40656
40868
  local text="No airports or zones found given in SetDestination(). Enabling random destination airports!"
40657
- self:E(RAT.id.."ERROR: "..text)
40869
+ self:E(self.lid.."ERROR: "..text)
40658
40870
  MESSAGE:New(text,30):ToAll()
40659
40871
  end
40660
40872
  end
40661
40873
  if self.destinationzone and self.returnzone then
40662
- 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.")
40663
40875
  self.returnzone=false
40664
40876
  end
40665
40877
  if self.returnzone and self.takeoff==RAT.wp.air then
@@ -40808,7 +41020,7 @@ names=departurenames
40808
41020
  elseif type(departurenames)=="string"then
40809
41021
  names={departurenames}
40810
41022
  else
40811
- 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()!")
40812
41024
  end
40813
41025
  for _,name in pairs(names)do
40814
41026
  if self:_AirportExists(name)then
@@ -40816,7 +41028,7 @@ table.insert(self.departure_ports,name)
40816
41028
  elseif self:_ZoneExists(name)then
40817
41029
  table.insert(self.departure_ports,name)
40818
41030
  else
40819
- 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)
40820
41032
  end
40821
41033
  end
40822
41034
  return self
@@ -40830,7 +41042,7 @@ names=destinationnames
40830
41042
  elseif type(destinationnames)=="string"then
40831
41043
  names={destinationnames}
40832
41044
  else
40833
- 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()!")
40834
41046
  end
40835
41047
  for _,name in pairs(names)do
40836
41048
  if self:_AirportExists(name)then
@@ -40838,7 +41050,7 @@ table.insert(self.destination_ports,name)
40838
41050
  elseif self:_ZoneExists(name)then
40839
41051
  table.insert(self.destination_ports,name)
40840
41052
  else
40841
- 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)
40842
41054
  end
40843
41055
  end
40844
41056
  return self
@@ -40943,12 +41155,14 @@ interval=interval or 5
40943
41155
  self.spawninterval=math.max(0.5,interval)
40944
41156
  return self
40945
41157
  end
41158
+ function RAT:SetSpawnLimit(Nmax)
41159
+ self.NspawnMax=Nmax
41160
+ return self
41161
+ end
40946
41162
  function RAT:RespawnAfterLanding(delay)
40947
41163
  self:F2(delay)
40948
- delay=delay or 180
40949
41164
  self.respawn_at_landing=true
40950
- delay=math.max(1.0,delay)
40951
- self.respawn_delay=delay
41165
+ self:SetRespawnDelay(delay)
40952
41166
  return self
40953
41167
  end
40954
41168
  function RAT:SetRespawnDelay(delay)
@@ -41012,10 +41226,6 @@ self.checkontop=switch
41012
41226
  self.ontopradius=radius or 2
41013
41227
  return self
41014
41228
  end
41015
- function RAT:ParkingSpotDB(switch)
41016
- self:E("RAT ParkingSpotDB function is obsolete and will be removed soon!")
41017
- return self
41018
- end
41019
41229
  function RAT:RadioON()
41020
41230
  self:F2()
41021
41231
  self.radio=true
@@ -41265,7 +41475,7 @@ elseif DCScategory==Group.Category.HELICOPTER then
41265
41475
  self.category=RAT.cat.heli
41266
41476
  else
41267
41477
  self.category="other"
41268
- 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!")
41269
41479
  end
41270
41480
  self.aircraft.type=DCStype
41271
41481
  self.aircraft.fuel=DCSunit:getFuel()
@@ -41304,10 +41514,16 @@ text=text..string.format("Max range = %6.1f km\n",self.aircraft.Rmax/1000)
41304
41514
  text=text..string.format("Eff range = %6.1f km (with 95 percent initial fuel amount)\n",self.aircraft.Reff/1000)
41305
41515
  text=text..string.format("Ceiling = %6.1f km = FL%3.0f\n",self.aircraft.ceiling/1000,self.aircraft.ceiling/RAT.unit.FL2m)
41306
41516
  text=text..string.format("******************************************************\n")
41307
- self:T(RAT.id..text)
41517
+ self:T(self.lid..text)
41308
41518
  end
41309
41519
  function RAT:_SpawnWithRoute(_departure,_destination,_takeoff,_landing,_livery,_waypoint,_lastpos,_nrespawn,parkingdata)
41310
- 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
41311
41527
  local takeoff=self.takeoff
41312
41528
  local landing=self.landing
41313
41529
  if _takeoff then
@@ -41324,7 +41540,7 @@ local nrespawn=0
41324
41540
  if _nrespawn then
41325
41541
  nrespawn=_nrespawn
41326
41542
  end
41327
- 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)
41328
41544
  if not(departure and destination and waypoints)then
41329
41545
  return nil
41330
41546
  end
@@ -41334,101 +41550,210 @@ livery=_livery
41334
41550
  elseif self.livery then
41335
41551
  livery=self.livery[math.random(#self.livery)]
41336
41552
  local text=string.format("Chosen livery for group %s: %s",self:_AnticipatedGroupName(),livery)
41337
- self:T(RAT.id..text)
41553
+ self:T(self.lid..text)
41338
41554
  else
41339
41555
  livery=nil
41340
41556
  end
41341
- 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)
41342
41564
  if not successful then
41343
41565
  return nil
41344
41566
  end
41345
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
41346
41574
  self.alive=self.alive+1
41347
- 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))
41348
41576
  if self.ATCswitch and landing==RAT.wp.landing then
41577
+ local airbasename=destination:GetName()
41349
41578
  if self.returnzone then
41350
- self:_ATCAddFlight(group:GetName(),departure:GetName())
41351
- else
41352
- self:_ATCAddFlight(group:GetName(),destination:GetName())
41579
+ airbasename=departure:GetName()
41580
+ end
41581
+ if not self:_IsFlightControlAirbase(airbasename)then
41582
+ self:_ATCAddFlight(groupname,airbasename)
41353
41583
  end
41354
41584
  end
41355
41585
  if self.placemarkers then
41356
- 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)
41357
41592
  end
41358
41593
  if self.invisible then
41359
- self:_CommandInvisible(group,true)
41594
+ flightgroup:SetDefaultInvisible(true)
41595
+ flightgroup:SwitchInvisible(true)
41360
41596
  end
41361
41597
  if self.immortal then
41362
- self:_CommandImmortal(group,true)
41598
+ flightgroup:SetDefaultImmortal(true)
41599
+ flightgroup:SwitchImmortal(true)
41363
41600
  end
41364
41601
  if self.eplrs then
41365
- group:CommandEPLRS(true,1)
41366
- end
41367
- self:_SetROE(group,self.roe)
41368
- self:_SetROT(group,self.rot)
41369
- self.ratcraft[self.SpawnIndex]={}
41370
- self.ratcraft[self.SpawnIndex]["group"]=group
41371
- self.ratcraft[self.SpawnIndex]["destination"]=destination
41372
- self.ratcraft[self.SpawnIndex]["departure"]=departure
41373
- self.ratcraft[self.SpawnIndex]["waypoints"]=waypoints
41374
- self.ratcraft[self.SpawnIndex]["airborne"]=group:InAir()
41375
- self.ratcraft[self.SpawnIndex]["nunits"]=group:GetInitialSize()
41376
- if group:InAir()then
41377
- self.ratcraft[self.SpawnIndex]["Tground"]=nil
41378
- self.ratcraft[self.SpawnIndex]["Pground"]=nil
41379
- self.ratcraft[self.SpawnIndex]["Uground"]=nil
41380
- self.ratcraft[self.SpawnIndex]["Tlastcheck"]=nil
41381
- else
41382
- self.ratcraft[self.SpawnIndex]["Tground"]=timer.getTime()
41383
- self.ratcraft[self.SpawnIndex]["Pground"]=group:GetCoordinate()
41384
- self.ratcraft[self.SpawnIndex]["Uground"]={}
41385
- for _,_unit in pairs(group:GetUnits())do
41386
- local _unitname=_unit:GetName()
41387
- self.ratcraft[self.SpawnIndex]["Uground"][_unitname]=_unit:GetCoordinate()
41388
- end
41389
- self.ratcraft[self.SpawnIndex]["Tlastcheck"]=timer.getTime()
41390
- end
41391
- self.ratcraft[self.SpawnIndex]["P0"]=group:GetCoordinate()
41392
- self.ratcraft[self.SpawnIndex]["Pnow"]=group:GetCoordinate()
41393
- self.ratcraft[self.SpawnIndex]["Distance"]=0
41394
- self.ratcraft[self.SpawnIndex].takeoff=takeoff
41395
- self.ratcraft[self.SpawnIndex].landing=landing
41396
- self.ratcraft[self.SpawnIndex].wpholding=WPholding
41397
- self.ratcraft[self.SpawnIndex].wpfinal=WPfinal
41398
- self.ratcraft[self.SpawnIndex].active=not self.uncontrolled
41399
- self.ratcraft[self.SpawnIndex]["status"]=RAT.status.Spawned
41400
- self.ratcraft[self.SpawnIndex].livery=livery
41401
- self.ratcraft[self.SpawnIndex].despawnme=false
41402
- 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
41403
41628
  if self.f10menu then
41404
41629
  local name=self.aircraft.type.." ID "..tostring(self.SpawnIndex)
41405
41630
  self.Menu[self.SubMenuName].groups[self.SpawnIndex]=MENU_MISSION:New(name,self.Menu[self.SubMenuName].groups)
41406
41631
  self.Menu[self.SubMenuName].groups[self.SpawnIndex]["roe"]=MENU_MISSION:New("Set ROE",self.Menu[self.SubMenuName].groups[self.SpawnIndex])
41407
- MENU_MISSION_COMMAND:New("Weapons hold",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["roe"],self._SetROE,self,group,RAT.ROE.weaponhold)
41408
- MENU_MISSION_COMMAND:New("Weapons free",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["roe"],self._SetROE,self,group,RAT.ROE.weaponfree)
41409
- 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)
41410
41635
  self.Menu[self.SubMenuName].groups[self.SpawnIndex]["rot"]=MENU_MISSION:New("Set ROT",self.Menu[self.SubMenuName].groups[self.SpawnIndex])
41411
- MENU_MISSION_COMMAND:New("No reaction",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["rot"],self._SetROT,self,group,RAT.ROT.noreaction)
41412
- MENU_MISSION_COMMAND:New("Passive defense",self.Menu[self.SubMenuName].groups[self.SpawnIndex]["rot"],self._SetROT,self,group,RAT.ROT.passive)
41413
- 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)
41414
41639
  MENU_MISSION_COMMAND:New("Despawn group",self.Menu[self.SubMenuName].groups[self.SpawnIndex],self._Despawn,self,group)
41415
41640
  MENU_MISSION_COMMAND:New("Place markers",self.Menu[self.SubMenuName].groups[self.SpawnIndex],self._PlaceMarkers,self,waypoints,self.SpawnIndex)
41416
41641
  MENU_MISSION_COMMAND:New("Status report",self.Menu[self.SubMenuName].groups[self.SpawnIndex],self.Status,self,true,self.SpawnIndex)
41417
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
41418
41700
  return self.SpawnIndex
41419
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
41420
41717
  function RAT:ClearForLanding(name)
41421
41718
  trigger.action.setUserFlag(name,1)
41422
41719
  local flagvalue=trigger.misc.getUserFlag(name)
41423
- self:T(RAT.id.."ATC: User flag value (landing) for "..name.." set to "..flagvalue)
41424
- end
41425
- function RAT:_Respawn(index,lastpos,delay)
41426
- local departure=self.ratcraft[index].departure
41427
- local destination=self.ratcraft[index].destination
41428
- local takeoff=self.ratcraft[index].takeoff
41429
- local landing=self.ratcraft[index].landing
41430
- local livery=self.ratcraft[index].livery
41431
- 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)
41432
41757
  local _departure=nil
41433
41758
  local _destination=nil
41434
41759
  local _takeoff=nil
@@ -41439,7 +41764,7 @@ local _lastpos=nil
41439
41764
  if self.continuejourney then
41440
41765
  _departure=destination:GetName()
41441
41766
  _livery=livery
41442
- 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
41443
41768
  if destination:GetCategory()==4 then
41444
41769
  _lastpos=lastpos
41445
41770
  end
@@ -41502,28 +41827,31 @@ if _takeoff==RAT.wp.air and(self.continuejourney or self.commute)then
41502
41827
  _lastwp=lastwp
41503
41828
  end
41504
41829
  self:T2({departure=_departure,destination=_destination,takeoff=_takeoff,landing=_landing,livery=_livery,lastwp=_lastwp})
41505
- local respawndelay
41506
- if delay then
41507
- respawndelay=delay
41508
- elseif self.respawn_delay then
41509
- respawndelay=self.respawn_delay+3
41510
- else
41511
- respawndelay=3
41512
- end
41513
- local arg={}
41514
- arg.self=self
41515
- arg.departure=_departure
41516
- arg.destination=_destination
41517
- arg.takeoff=_takeoff
41518
- arg.landing=_landing
41519
- arg.livery=_livery
41520
- arg.lastwp=_lastwp
41521
- arg.lastpos=_lastpos
41522
- self:T(RAT.id..string.format("%s delayed respawn in %.1f seconds.",self.alias,respawndelay))
41523
- SCHEDULER:New(nil,self._SpawnWithRouteTimer,{arg},respawndelay)
41524
- end
41525
- function RAT._SpawnWithRouteTimer(arg)
41526
- 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
41527
41855
  end
41528
41856
  function RAT:_SetRoute(takeoff,landing,_departure,_destination,_waypoint)
41529
41857
  local VxCruiseMax
@@ -41553,7 +41881,7 @@ elseif self:_ZoneExists(_departure)then
41553
41881
  departure=ZONE:FindByName(_departure)
41554
41882
  else
41555
41883
  local text=string.format("ERROR! Specified departure airport %s does not exist for %s.",_departure,self.alias)
41556
- self:E(RAT.id..text)
41884
+ self:E(self.lid..text)
41557
41885
  end
41558
41886
  else
41559
41887
  departure=self:_PickDeparture(takeoff)
@@ -41563,7 +41891,7 @@ end
41563
41891
  end
41564
41892
  if not departure then
41565
41893
  local text=string.format("ERROR! No valid departure airport could be found for %s.",self.alias)
41566
- self:E(RAT.id..text)
41894
+ self:E(self.lid..text)
41567
41895
  return nil
41568
41896
  end
41569
41897
  local Pdeparture
@@ -41611,7 +41939,7 @@ mindist=Dtot
41611
41939
  end
41612
41940
  mindist=math.max(self.mindist,mindist)
41613
41941
  local text=string.format("Adjusting min distance to %d km (for given min FL%03d)",mindist/1000,self.FLminuser/RAT.unit.FL2m)
41614
- self:T(RAT.id..text)
41942
+ self:T(self.lid..text)
41615
41943
  end
41616
41944
  local destination=nil
41617
41945
  if _destination then
@@ -41624,7 +41952,7 @@ elseif self:_ZoneExists(_destination)then
41624
41952
  destination=ZONE:FindByName(_destination)
41625
41953
  else
41626
41954
  local text=string.format("ERROR: Specified destination airport/zone %s does not exist for %s!",_destination,self.alias)
41627
- self:E(RAT.id.."ERROR: "..text)
41955
+ self:E(self.lid.."ERROR: "..text)
41628
41956
  end
41629
41957
  else
41630
41958
  local random=self.random_destination
@@ -41642,13 +41970,13 @@ end
41642
41970
  if not destination then
41643
41971
  local text=string.format("No valid destination airport could be found for %s!",self.alias)
41644
41972
  MESSAGE:New(text,60):ToAll()
41645
- self:E(RAT.id.."ERROR: "..text)
41973
+ self:E(self.lid.."ERROR: "..text)
41646
41974
  return nil
41647
41975
  end
41648
41976
  if destination:GetName()==departure:GetName()then
41649
41977
  local text=string.format("%s: Destination and departure are identical. Airport/zone %s.",self.alias,destination:GetName())
41650
41978
  MESSAGE:New(text,30):ToAll()
41651
- self:E(RAT.id.."ERROR: "..text)
41979
+ self:E(self.lid.."ERROR: "..text)
41652
41980
  end
41653
41981
  local Preturn
41654
41982
  local destination_returnzone
@@ -41829,93 +42157,90 @@ text=text..string.format("h_climb_max = %6.1f m\n",h_climb_max)
41829
42157
  text=text..string.format("h_descent_max = %6.1f m\n",h_descent_max)
41830
42158
  end
41831
42159
  text=text..string.format("******************************************************\n")
41832
- self:T2(RAT.id..text)
42160
+ self:T2(self.lid..text)
41833
42161
  if d_cruise<0 then
41834
42162
  d_cruise=100
41835
42163
  end
41836
42164
  local wp={}
41837
42165
  local c={}
42166
+ local waypointdescriptions={}
42167
+ local waypointstatus={}
41838
42168
  local wpholding=nil
41839
42169
  local wpfinal=nil
41840
42170
  c[#c+1]=Pdeparture
41841
42171
  wp[#wp+1]=self:_Waypoint(#wp+1,"Departure",takeoff,c[#wp+1],VxClimb,H_departure,departure)
41842
- self.waypointdescriptions[#wp]="Departure"
41843
- self.waypointstatus[#wp]=RAT.status.Departure
42172
+ waypointdescriptions[#wp]="Departure"
42173
+ waypointstatus[#wp]=RAT.status.Departure
41844
42174
  if takeoff==RAT.wp.air then
41845
42175
  if d_climb<5000 or d_cruise<5000 then
41846
42176
  d_cruise=d_cruise+d_climb
41847
42177
  else
41848
42178
  c[#c+1]=c[#c]:Translate(d_climb,heading)
41849
42179
  wp[#wp+1]=self:_Waypoint(#wp+1,"Begin of Cruise",RAT.wp.cruise,c[#wp+1],VxCruise,FLcruise)
41850
- self.waypointdescriptions[#wp]="Begin of Cruise"
41851
- self.waypointstatus[#wp]=RAT.status.Cruise
42180
+ waypointdescriptions[#wp]="Begin of Cruise"
42181
+ waypointstatus[#wp]=RAT.status.Cruise
41852
42182
  end
41853
42183
  else
41854
42184
  c[#c+1]=c[#c]:Translate(d_climb/2,heading)
41855
42185
  c[#c+1]=c[#c]:Translate(d_climb/2,heading)
41856
42186
  wp[#wp+1]=self:_Waypoint(#wp+1,"Climb",RAT.wp.climb,c[#wp+1],VxClimb,H_departure+(FLcruise-H_departure)/2)
41857
- self.waypointdescriptions[#wp]="Climb"
41858
- self.waypointstatus[#wp]=RAT.status.Climb
42187
+ waypointdescriptions[#wp]="Climb"
42188
+ waypointstatus[#wp]=RAT.status.Climb
41859
42189
  wp[#wp+1]=self:_Waypoint(#wp+1,"Begin of Cruise",RAT.wp.cruise,c[#wp+1],VxCruise,FLcruise)
41860
- self.waypointdescriptions[#wp]="Begin of Cruise"
41861
- self.waypointstatus[#wp]=RAT.status.Cruise
42190
+ waypointdescriptions[#wp]="Begin of Cruise"
42191
+ waypointstatus[#wp]=RAT.status.Cruise
41862
42192
  end
41863
42193
  if self.returnzone then
41864
42194
  c[#c+1]=Preturn
41865
42195
  wp[#wp+1]=self:_Waypoint(#wp+1,"Return Zone",RAT.wp.cruise,c[#wp+1],VxCruise,FLcruise)
41866
- self.waypointdescriptions[#wp]="Return Zone"
41867
- self.waypointstatus[#wp]=RAT.status.Uturn
42196
+ waypointdescriptions[#wp]="Return Zone"
42197
+ waypointstatus[#wp]=RAT.status.Uturn
41868
42198
  end
41869
42199
  if landing==RAT.wp.air then
41870
42200
  c[#c+1]=Pdestination
41871
42201
  wp[#wp+1]=self:_Waypoint(#wp+1,"Final Destination",RAT.wp.finalwp,c[#wp+1],VxCruise,FLcruise)
41872
- self.waypointdescriptions[#wp]="Final Destination"
41873
- self.waypointstatus[#wp]=RAT.status.Destination
42202
+ waypointdescriptions[#wp]="Final Destination"
42203
+ waypointstatus[#wp]=RAT.status.Destination
41874
42204
  elseif self.returnzone then
41875
42205
  c[#c+1]=c[#c]:Translate(d_cruise/2,heading-180)
41876
42206
  wp[#wp+1]=self:_Waypoint(#wp+1,"End of Cruise",RAT.wp.cruise,c[#wp+1],VxCruise,FLcruise)
41877
- self.waypointdescriptions[#wp]="End of Cruise"
41878
- self.waypointstatus[#wp]=RAT.status.Descent
42207
+ waypointdescriptions[#wp]="End of Cruise"
42208
+ waypointstatus[#wp]=RAT.status.Descent
41879
42209
  else
41880
42210
  c[#c+1]=c[#c]:Translate(d_cruise,heading)
41881
42211
  wp[#wp+1]=self:_Waypoint(#wp+1,"End of Cruise",RAT.wp.cruise,c[#wp+1],VxCruise,FLcruise)
41882
- self.waypointdescriptions[#wp]="End of Cruise"
41883
- self.waypointstatus[#wp]=RAT.status.Descent
42212
+ waypointdescriptions[#wp]="End of Cruise"
42213
+ waypointstatus[#wp]=RAT.status.Descent
41884
42214
  end
41885
42215
  if landing==RAT.wp.landing then
41886
42216
  if self.returnzone then
41887
42217
  c[#c+1]=c[#c]:Translate(d_descent/2,heading-180)
41888
42218
  wp[#wp+1]=self:_Waypoint(#wp+1,"Descent",RAT.wp.descent,c[#wp+1],VxDescent,FLcruise-(FLcruise-(h_holding+H_holding))/2)
41889
- self.waypointdescriptions[#wp]="Descent"
41890
- self.waypointstatus[#wp]=RAT.status.DescentHolding
42219
+ waypointdescriptions[#wp]="Descent"
42220
+ waypointstatus[#wp]=RAT.status.DescentHolding
41891
42221
  else
41892
42222
  c[#c+1]=c[#c]:Translate(d_descent/2,heading)
41893
42223
  wp[#wp+1]=self:_Waypoint(#wp+1,"Descent",RAT.wp.descent,c[#wp+1],VxDescent,FLcruise-(FLcruise-(h_holding+H_holding))/2)
41894
- self.waypointdescriptions[#wp]="Descent"
41895
- self.waypointstatus[#wp]=RAT.status.DescentHolding
42224
+ waypointdescriptions[#wp]="Descent"
42225
+ waypointstatus[#wp]=RAT.status.DescentHolding
41896
42226
  end
41897
42227
  end
41898
42228
  if landing==RAT.wp.landing then
41899
- c[#c+1]=Pholding
41900
- wp[#wp+1]=self:_Waypoint(#wp+1,"Holding Point",RAT.wp.holding,c[#wp+1],VxHolding,H_holding+h_holding)
41901
- self.waypointdescriptions[#wp]="Holding Point"
41902
- self.waypointstatus[#wp]=RAT.status.Holding
41903
- wpholding=#wp
41904
42229
  c[#c+1]=Pdestination
41905
42230
  wp[#wp+1]=self:_Waypoint(#wp+1,"Final Destination",landing,c[#wp+1],VxFinal,H_destination,destination)
41906
- self.waypointdescriptions[#wp]="Final Destination"
41907
- self.waypointstatus[#wp]=RAT.status.Destination
42231
+ waypointdescriptions[#wp]="Final Destination"
42232
+ waypointstatus[#wp]=RAT.status.Destination
41908
42233
  end
41909
42234
  wpfinal=#wp
41910
42235
  local waypoints={}
41911
42236
  for _,p in ipairs(wp)do
41912
42237
  table.insert(waypoints,p)
41913
42238
  end
41914
- self:_Routeinfo(waypoints,"Waypoint info in set_route:")
42239
+ self:_Routeinfo(waypoints,"Waypoint info in set_route:",waypointdescriptions)
41915
42240
  if self.returnzone then
41916
- return departure,destination_returnzone,waypoints,wpholding,wpfinal
42241
+ return departure,destination_returnzone,waypoints,waypointdescriptions,waypointstatus
41917
42242
  else
41918
- return departure,destination,waypoints,wpholding,wpfinal
42243
+ return departure,destination,waypoints,waypointdescriptions,waypointstatus
41919
42244
  end
41920
42245
  end
41921
42246
  function RAT:_PickDeparture(takeoff)
@@ -41958,17 +42283,17 @@ elseif self:_ZoneExists(name)then
41958
42283
  if takeoff==RAT.wp.air then
41959
42284
  dep=ZONE:FindByName(name)
41960
42285
  else
41961
- 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))
41962
42287
  end
41963
42288
  else
41964
- 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))
41965
42290
  end
41966
42291
  if dep then
41967
42292
  table.insert(departures,dep)
41968
42293
  end
41969
42294
  end
41970
42295
  end
41971
- 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))
41972
42297
  local departure=departures[math.random(#departures)]
41973
42298
  local text
41974
42299
  if departure and departure:GetName()then
@@ -41977,9 +42302,9 @@ text=string.format("%s: Chosen departure zone: %s",self.alias,departure:GetName(
41977
42302
  else
41978
42303
  text=string.format("%s: Chosen departure airport: %s (ID %d)",self.alias,departure:GetName(),departure:GetID())
41979
42304
  end
41980
- self:T(RAT.id..text)
42305
+ self:T(self.lid..text)
41981
42306
  else
41982
- 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))
41983
42308
  departure=nil
41984
42309
  end
41985
42310
  return departure
@@ -42030,10 +42355,10 @@ elseif self:_ZoneExists(name)then
42030
42355
  if landing==RAT.wp.air then
42031
42356
  dest=ZONE:FindByName(name)
42032
42357
  else
42033
- 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))
42034
42359
  end
42035
42360
  else
42036
- 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))
42037
42362
  end
42038
42363
  if dest then
42039
42364
  local distance=q:Get2DDistance(dest:GetCoordinate())
@@ -42041,13 +42366,13 @@ if distance>=minrange and distance<=maxrange then
42041
42366
  table.insert(destinations,dest)
42042
42367
  else
42043
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)
42044
- self:T(RAT.id..text)
42369
+ self:T(self.lid..text)
42045
42370
  end
42046
42371
  end
42047
42372
  end
42048
42373
  end
42049
42374
  end
42050
- 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))
42051
42376
  if#destinations>0 then
42052
42377
  local function compare(a,b)
42053
42378
  local qa=q:Get2DDistance(a:GetCoordinate())
@@ -42067,9 +42392,9 @@ text=string.format("%s: Chosen destination zone: %s.",self.alias,destination:Get
42067
42392
  else
42068
42393
  text=string.format("%s Chosen destination airport: %s (ID %d).",self.alias,destination:GetName(),destination:GetID())
42069
42394
  end
42070
- self:T(RAT.id..text)
42395
+ self:T(self.lid..text)
42071
42396
  else
42072
- self:E(RAT.id.."ERROR! No destination airport or zone found.")
42397
+ self:E(self.lid.."ERROR! No destination airport or zone found.")
42073
42398
  destination=nil
42074
42399
  end
42075
42400
  return destination
@@ -42121,9 +42446,9 @@ local _myab=AIRBASE:FindByName(_name)
42121
42446
  if _myab then
42122
42447
  table.insert(self.airports_map,_myab)
42123
42448
  local text="MOOSE: Airport ID = ".._myab:GetID().." and Name = ".._myab:GetName()..", Category = ".._myab:GetCategory()..", TypeName = ".._myab:GetTypeName()
42124
- self:T(RAT.id..text)
42449
+ self:T(self.lid..text)
42125
42450
  else
42126
- 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)))
42127
42452
  end
42128
42453
  end
42129
42454
  end
@@ -42145,31 +42470,26 @@ end
42145
42470
  if#self.airports==0 then
42146
42471
  local text=string.format("No possible departure/destination airports found for RAT %s.",tostring(self.alias))
42147
42472
  MESSAGE:New(text,10):ToAll()
42148
- self:E(RAT.id..text)
42473
+ self:E(self.lid..text)
42149
42474
  end
42150
42475
  end
42151
42476
  function RAT:Status(message,forID)
42152
- if message==nil then
42153
- message=false
42154
- end
42155
- if forID==nil then
42156
- forID=false
42157
- end
42477
+ self:T(self.lid.."Checking status")
42158
42478
  local Tnow=timer.getTime()
42159
42479
  local nalive=0
42160
- 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)))
42161
42483
  local group=ratcraft.group
42162
- if group and group:IsAlive()and(group:GetCoordinate()or group:GetVec3())then
42484
+ if group and group:IsAlive()then
42163
42485
  nalive=nalive+1
42486
+ self:T(self.lid..string.format("Ratcraft Index=%s is ALIVE",tostring(spawnindex)))
42164
42487
  local prefix=self:_GetPrefixFromGroup(group)
42165
42488
  local life=self:_GetLife(group)
42166
42489
  local fuel=group:GetFuel()*100.0
42167
42490
  local airborne=group:InAir()
42168
- local coords=group:GetCoordinate()or group:GetVec3()
42169
- local alt=1000
42170
- if coords then
42171
- alt=coords.y or 1000
42172
- end
42491
+ local coords=group:GetCoordinate()
42492
+ local alt=coords~=nil and coords.y or 1000
42173
42493
  local departure=ratcraft.departure:GetName()
42174
42494
  local destination=ratcraft.destination:GetName()
42175
42495
  local type=self.aircraft.type
@@ -42177,52 +42497,16 @@ local status=ratcraft.status
42177
42497
  local active=ratcraft.active
42178
42498
  local Nunits=ratcraft.nunits
42179
42499
  local N0units=group:GetInitialSize()
42180
- local Tg=0
42181
- local Dg=0
42182
- local dTlast=0
42183
- local stationary=false
42184
- if airborne then
42185
- ratcraft["Tground"]=nil
42186
- ratcraft["Pground"]=nil
42187
- ratcraft["Uground"]=nil
42188
- ratcraft["Tlastcheck"]=nil
42189
- else
42190
- if ratcraft["Tground"]then
42191
- Tg=Tnow-ratcraft["Tground"]
42192
- Dg=coords:Get2DDistance(ratcraft["Pground"])
42193
- dTlast=Tnow-ratcraft["Tlastcheck"]
42194
- if dTlast>self.Tinactive then
42195
- for _,_unit in pairs(group:GetUnits())do
42196
- if _unit and _unit:IsAlive()then
42197
- local unitname=_unit:GetName()
42198
- local unitcoord=_unit:GetCoordinate()
42199
- local Ug=unitcoord:Get2DDistance(ratcraft.Uground[unitname])
42200
- self:T2(RAT.id..string.format("Unit %s travelled distance on ground %.1f m since %d seconds.",unitname,Ug,dTlast))
42201
- if Ug<50 and active and status~=RAT.status.EventBirth then
42202
- stationary=true
42500
+ local Dtravel=0
42501
+ if coords and ratcraft.Pnow then
42502
+ local Dtravel=coords:Get2DDistance(ratcraft.Pnow)
42503
+ ratcraft.Pnow=coords
42203
42504
  end
42204
- ratcraft["Uground"][unitname]=unitcoord
42505
+ ratcraft.Distance=ratcraft.Distance+Dtravel
42506
+ local Ddestination=-1
42507
+ if ratcraft.Pnow then
42508
+ Ddestination=ratcraft.Pnow:Get2DDistance(ratcraft.destination:GetCoordinate())
42205
42509
  end
42206
- end
42207
- ratcraft["Tlastcheck"]=Tnow
42208
- ratcraft["Pground"]=coords
42209
- end
42210
- else
42211
- ratcraft["Tground"]=Tnow
42212
- ratcraft["Tlastcheck"]=Tnow
42213
- ratcraft["Pground"]=coords
42214
- ratcraft["Uground"]={}
42215
- for _,_unit in pairs(group:GetUnits())do
42216
- local unitname=_unit:GetName()
42217
- ratcraft.Uground[unitname]=_unit:GetCoordinate()
42218
- end
42219
- end
42220
- end
42221
- local Pn=coords
42222
- local Dtravel=Pn:Get2DDistance(ratcraft["Pnow"])
42223
- ratcraft["Pnow"]=Pn
42224
- ratcraft["Distance"]=ratcraft["Distance"]+Dtravel
42225
- local Ddestination=Pn:Get2DDistance(ratcraft.destination:GetCoordinate())
42226
42510
  if(forID and spawnindex==forID)or(not forID)then
42227
42511
  local text=string.format("ID %i of flight %s",spawnindex,prefix)
42228
42512
  if N0units>1 then
@@ -42243,53 +42527,46 @@ text=text.." [airborne]\n"
42243
42527
  else
42244
42528
  text=text.." [on ground]\n"
42245
42529
  end
42246
- text=text..string.format("Fuel = %3.0f %%\n",fuel)
42247
- text=text..string.format("Life = %3.0f %%\n",life)
42248
- text=text..string.format("FL%03d = %i m ASL\n",alt/RAT.unit.FL2m,alt)
42249
- text=text..string.format("Distance travelled = %6.1f km\n",ratcraft["Distance"]/1000)
42250
- text=text..string.format("Distance to destination = %6.1f km",Ddestination/1000)
42251
- if not airborne then
42252
- text=text..string.format("\nTime on ground = %6.0f seconds\n",Tg)
42253
- text=text..string.format("Position change = %8.1f m since %3.0f seconds.",Dg,dTlast)
42254
- end
42255
- 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)
42256
42536
  if message then
42257
42537
  MESSAGE:New(text,20):ToAll()
42258
42538
  end
42259
42539
  end
42260
- if not airborne then
42261
- if stationary then
42262
- local text=string.format("Group %s is despawned after being %d seconds inaktive on ground.",self.alias,dTlast)
42263
- self:T(RAT.id..text)
42264
- self:_Despawn(group)
42265
- end
42266
- if life<10 and Dtravel<100 then
42267
- local text=string.format("Damaged group %s is despawned. Life = %3.0f",self.alias,life)
42268
- self:T(RAT.id..text)
42269
- self:_Despawn(group)
42270
- end
42271
- end
42272
42540
  if ratcraft.despawnme then
42273
- local text=string.format("Flight %s will be despawned NOW!",self.alias)
42274
- self:T(RAT.id..text)
42275
- if(not self.norespawn)and(not self.respawn_after_takeoff)then
42276
- local idx=self:GetSpawnIndexFromGroup(group)
42277
- local coord=group:GetCoordinate()
42278
- self:_Respawn(idx,coord,0)
42279
- end
42541
+ if self.norespawn or self.respawn_after_takeoff then
42280
42542
  if self.despawnair then
42281
- 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)
42282
42549
  end
42283
42550
  end
42284
42551
  else
42285
- local text=string.format("Group does not exist in loop ratcraft status.")
42286
- 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)
42287
42555
  end
42288
42556
  end
42289
42557
  local text=string.format("Alive groups of %s: %d, nalive=%d/%d",self.alias,self.alive,nalive,self.ngroups)
42290
- self:T(RAT.id..text)
42558
+ self:T(self.lid..text)
42291
42559
  MESSAGE:New(text,20):ToAllIf(message and not forID)
42292
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
42293
42570
  function RAT:_GetLife(group)
42294
42571
  local life=0.0
42295
42572
  if group and group:IsAlive()then
@@ -42297,48 +42574,56 @@ local unit=group:GetUnit(1)
42297
42574
  if unit then
42298
42575
  life=unit:GetLife()/unit:GetLife0()*100
42299
42576
  else
42300
- 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.")
42301
42578
  end
42302
42579
  else
42303
- 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.")
42304
42581
  end
42305
42582
  return life
42306
42583
  end
42307
42584
  function RAT:_SetStatus(group,status)
42308
42585
  if group and group:IsAlive()then
42309
- local index=self:GetSpawnIndexFromGroup(group)
42310
- if self.ratcraft[index]then
42311
- self.ratcraft[index].status=status
42586
+ local ratcraft=self:_GetRatcraftFromGroup(group)
42587
+ if ratcraft then
42588
+ ratcraft.status=status
42312
42589
  local no1=status==RAT.status.Departure
42313
42590
  local no2=status==RAT.status.EventBirthAir
42314
42591
  local no3=status==RAT.status.Holding
42315
- local text=string.format("Flight %s: %s.",group:GetName(),status)
42316
- self:T(RAT.id..text)
42592
+ local text=string.format("Flight %s: %s",group:GetName(),status)
42593
+ self:T(self.lid..text)
42317
42594
  if not(no1 or no2 or no3)then
42318
42595
  MESSAGE:New(text,10):ToAllIf(self.reportstatus)
42319
42596
  end
42320
42597
  end
42321
42598
  end
42322
42599
  end
42323
- function RAT:GetStatus(group)
42324
- if group and group:IsAlive()then
42600
+ function RAT:_GetRatcraftFromGroup(group)
42601
+ if group then
42325
42602
  local index=self:GetSpawnIndexFromGroup(group)
42326
42603
  if self.ratcraft[index]then
42327
- 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
42328
42614
  end
42329
42615
  end
42330
42616
  return"nonexistant"
42331
42617
  end
42332
42618
  function RAT:_OnBirth(EventData)
42333
42619
  self:F3(EventData)
42334
- self:T3(RAT.id.."Captured event birth!")
42620
+ self:T3(self.lid.."Captured event birth!")
42335
42621
  local SpawnGroup=EventData.IniGroup
42336
42622
  if SpawnGroup then
42337
42623
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42338
- if EventPrefix then
42339
- if EventPrefix==self.alias then
42624
+ if EventPrefix and EventPrefix==self.alias then
42340
42625
  local text="Event: Group "..SpawnGroup:GetName().." was born."
42341
- self:T(RAT.id..text)
42626
+ self:T(self.lid..text)
42342
42627
  local status="unknown in birth"
42343
42628
  if SpawnGroup:InAir()then
42344
42629
  status=RAT.status.EventBirthAir
@@ -42349,12 +42634,13 @@ status=RAT.status.EventBirth
42349
42634
  end
42350
42635
  self:_SetStatus(SpawnGroup,status)
42351
42636
  local i=self:GetSpawnIndexFromGroup(SpawnGroup)
42352
- local _departure=self.ratcraft[i].departure:GetName()
42353
- local _destination=self.ratcraft[i].destination:GetName()
42354
- local _nrespawn=self.ratcraft[i].nrespawn
42355
- local _takeoff=self.ratcraft[i].takeoff
42356
- local _landing=self.ratcraft[i].landing
42357
- 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
42358
42644
  local _airbase=AIRBASE:FindByName(_departure)
42359
42645
  local onrunway=false
42360
42646
  if _airbase then
@@ -42365,7 +42651,7 @@ end
42365
42651
  if onrunway then
42366
42652
  local text=string.format("ERROR: RAT group of %s was spawned on runway. Group #%d will be despawned immediately!",self.alias,i)
42367
42653
  MESSAGE:New(text,30):ToAllIf(self.Debug)
42368
- self:E(RAT.id..text)
42654
+ self:E(self.lid..text)
42369
42655
  if self.Debug then
42370
42656
  SpawnGroup:FlareRed()
42371
42657
  end
@@ -42374,13 +42660,13 @@ if(self.Ndeparture_Airports>=2 or self.random_departure)and _nrespawn<self.onrun
42374
42660
  _nrespawn=_nrespawn+1
42375
42661
  text=string.format("Try spawning new aircraft of group %s at another location. Attempt %d of max %d.",self.alias,_nrespawn,self.onrunwaymaxretry)
42376
42662
  MESSAGE:New(text,10):ToAllIf(self.Debug)
42377
- self:T(RAT.id..text)
42663
+ self:T(self.lid..text)
42378
42664
  self:_SpawnWithRoute(nil,nil,nil,nil,nil,nil,nil,_nrespawn)
42379
42665
  else
42380
42666
  if self.respawn_inair and not self.uncontrolled then
42381
42667
  text=string.format("Spawning new aircraft of group %s in air since no parking slot is available at %s.",self.alias,_departure)
42382
42668
  MESSAGE:New(text,10):ToAll()
42383
- self:T(RAT.id..text)
42669
+ self:T(self.lid..text)
42384
42670
  self:_SpawnWithRoute(_departure,_destination,RAT.wp.air,_landing,_livery)
42385
42671
  end
42386
42672
  end
@@ -42392,28 +42678,26 @@ end
42392
42678
  if ontop then
42393
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)
42394
42680
  MESSAGE:New(text,30):ToAllIf(self.Debug)
42395
- self:T(RAT.id..text)
42681
+ self:T(self.lid..text)
42396
42682
  if self.Debug then
42397
42683
  SpawnGroup:FlareYellow()
42398
42684
  end
42399
42685
  self:_Despawn(SpawnGroup)
42400
42686
  end
42401
42687
  end
42402
- end
42403
42688
  else
42404
- 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().")
42405
42690
  end
42406
42691
  end
42407
42692
  function RAT:_OnEngineStartup(EventData)
42408
42693
  self:F3(EventData)
42409
- self:T3(RAT.id.."Captured event EngineStartup!")
42694
+ self:T3(self.lid.."Captured event EngineStartup!")
42410
42695
  local SpawnGroup=EventData.IniGroup
42411
42696
  if SpawnGroup then
42412
42697
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42413
- if EventPrefix then
42414
- if EventPrefix==self.alias then
42698
+ if EventPrefix and EventPrefix==self.alias then
42415
42699
  local text="Event: Group "..SpawnGroup:GetName().." started engines."
42416
- self:T(RAT.id..text)
42700
+ self:T(self.lid..text)
42417
42701
  local status
42418
42702
  if SpawnGroup:InAir()then
42419
42703
  status=RAT.status.EventEngineStartAir
@@ -42422,61 +42706,54 @@ status=RAT.status.EventEngineStart
42422
42706
  end
42423
42707
  self:_SetStatus(SpawnGroup,status)
42424
42708
  end
42425
- end
42426
42709
  else
42427
- 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().")
42428
42711
  end
42429
42712
  end
42430
42713
  function RAT:_OnTakeoff(EventData)
42431
42714
  local SpawnGroup=EventData.IniGroup
42432
42715
  if SpawnGroup then
42433
42716
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42434
- if EventPrefix then
42435
- if EventPrefix==self.alias then
42717
+ if EventPrefix and EventPrefix==self.alias then
42436
42718
  local text="Event: Group "..SpawnGroup:GetName().." is airborne."
42437
- self:T(RAT.id..text)
42719
+ self:T(self.lid..text)
42438
42720
  local status=RAT.status.EventTakeoff
42439
42721
  self:_SetStatus(SpawnGroup,status)
42440
42722
  if self.respawn_after_takeoff then
42441
42723
  text="Event: Group "..SpawnGroup:GetName().." will be respawned after takeoff."
42442
- self:T(RAT.id..text)
42724
+ self:T(self.lid..text)
42443
42725
  self:_SpawnWithRoute(nil,nil,nil,nil,nil,nil,nil,nil)
42444
42726
  end
42445
42727
  end
42446
- end
42447
42728
  else
42448
- 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().")
42449
42730
  end
42450
42731
  end
42451
42732
  function RAT:_OnLand(EventData)
42452
42733
  local SpawnGroup=EventData.IniGroup
42453
42734
  if SpawnGroup then
42454
42735
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42455
- if EventPrefix then
42456
- if EventPrefix==self.alias then
42457
- local text="Event: Group "..SpawnGroup:GetName().." landed."
42458
- 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)
42459
42739
  local status=RAT.status.EventLand
42460
42740
  self:_SetStatus(SpawnGroup,status)
42461
42741
  if self.ATCswitch then
42462
- RAT:_ATCFlightLanded(SpawnGroup:GetName())
42742
+ RAT._ATCFlightLanded(SpawnGroup:GetName())
42463
42743
  end
42464
42744
  if self.respawn_at_landing and not self.norespawn then
42465
- text="Event: Group "..SpawnGroup:GetName().." will be respawned."
42466
- self:T(RAT.id..text)
42467
- local idx=self:GetSpawnIndexFromGroup(SpawnGroup)
42468
- local coord=SpawnGroup:GetCoordinate()
42469
- self:_Respawn(idx,coord)
42470
- end
42745
+ text="Event: Group "..SpawnGroup:GetName().." will be respawned"
42746
+ self:T(self.lid..text)
42747
+ self:_Respawn(SpawnGroup)
42471
42748
  end
42472
42749
  end
42473
42750
  else
42474
- 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()")
42475
42752
  end
42476
42753
  end
42477
42754
  function RAT:_OnEngineShutdown(EventData)
42478
42755
  self:F3(EventData)
42479
- self:T3(RAT.id.."Captured event EngineShutdown!")
42756
+ self:T3(self.lid.."Captured event EngineShutdown!")
42480
42757
  local SpawnGroup=EventData.IniGroup
42481
42758
  if SpawnGroup then
42482
42759
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
@@ -42484,35 +42761,34 @@ if EventPrefix and EventPrefix==self.alias then
42484
42761
  if not SpawnGroup:InAir()then
42485
42762
  local currentstate=self:GetStatus(SpawnGroup)
42486
42763
  local text=string.format("Event: Unit %s of group %s shut down its engines. Current state %s.",EventData.IniUnitName,SpawnGroup:GetName(),currentstate)
42487
- self:T(RAT.id..text)
42764
+ self:T(self.lid..text)
42488
42765
  if currentstate~=RAT.status.EventEngineShutdown and currentstate~="Dead"then
42489
42766
  local status=RAT.status.EventEngineShutdown
42490
42767
  self:_SetStatus(SpawnGroup,status)
42491
42768
  if not self.respawn_at_landing and not self.norespawn then
42492
42769
  text=string.format("Event: Group %s will be respawned. Current state %s => new state %s.",SpawnGroup:GetName(),currentstate,status)
42493
- self:T(RAT.id..text)
42494
- local idx=self:GetSpawnIndexFromGroup(SpawnGroup)
42495
- local coord=SpawnGroup:GetCoordinate()
42496
- self:_Respawn(idx,coord)
42497
- end
42498
- text="Event: Group "..SpawnGroup:GetName().." will be destroyed now."
42499
- 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)
42500
42775
  self:_Despawn(SpawnGroup)
42501
42776
  end
42502
42777
  end
42503
42778
  end
42779
+ end
42504
42780
  else
42505
- 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().")
42506
42782
  end
42507
42783
  end
42508
42784
  function RAT:_OnHit(EventData)
42509
42785
  self:F3(EventData)
42510
- 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)))
42511
42787
  local SpawnGroup=EventData.TgtGroup
42512
42788
  if SpawnGroup then
42513
42789
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42514
42790
  if EventPrefix and EventPrefix==self.alias then
42515
- 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)))
42516
42792
  local text=string.format("%s, unit %s was hit!",self.alias,EventData.TgtUnitName)
42517
42793
  MESSAGE:New(text,10):ToAllIf(self.reportstatus or self.Debug)
42518
42794
  end
@@ -42520,7 +42796,7 @@ end
42520
42796
  end
42521
42797
  function RAT:_OnDeadOrCrash(EventData)
42522
42798
  self:F3(EventData)
42523
- self:T3(RAT.id.."Captured event DeadOrCrash!")
42799
+ self:T3(self.lid.."Captured event DeadOrCrash!")
42524
42800
  local SpawnGroup=EventData.IniGroup
42525
42801
  if SpawnGroup then
42526
42802
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
@@ -42528,7 +42804,7 @@ if EventPrefix then
42528
42804
  if EventPrefix==self.alias then
42529
42805
  self.alive=self.alive-1
42530
42806
  local text=string.format("Event: Group %s crashed or died. Alive counter = %d.",SpawnGroup:GetName(),self.alive)
42531
- self:T(RAT.id..text)
42807
+ self:T(self.lid..text)
42532
42808
  if EventData.id==world.event.S_EVENT_CRASH then
42533
42809
  self:_OnCrash(EventData)
42534
42810
  elseif EventData.id==world.event.S_EVENT_DEAD then
@@ -42540,98 +42816,50 @@ end
42540
42816
  end
42541
42817
  function RAT:_OnDead(EventData)
42542
42818
  self:F3(EventData)
42543
- self:T3(RAT.id.."Captured event Dead!")
42819
+ self:T3(self.lid.."Captured event Dead!")
42544
42820
  local SpawnGroup=EventData.IniGroup
42545
42821
  if SpawnGroup then
42546
42822
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42547
42823
  if EventPrefix then
42548
42824
  if EventPrefix==self.alias then
42549
42825
  local text=string.format("Event: Group %s died. Unit %s.",SpawnGroup:GetName(),EventData.IniUnitName)
42550
- self:T(RAT.id..text)
42826
+ self:T(self.lid..text)
42551
42827
  local status=RAT.status.EventDead
42552
42828
  self:_SetStatus(SpawnGroup,status)
42553
42829
  end
42554
42830
  end
42555
42831
  else
42556
- 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().")
42557
42833
  end
42558
42834
  end
42559
42835
  function RAT:_OnCrash(EventData)
42560
42836
  self:F3(EventData)
42561
- self:T3(RAT.id.."Captured event Crash!")
42837
+ self:T3(self.lid.."Captured event Crash!")
42562
42838
  local SpawnGroup=EventData.IniGroup
42563
42839
  if SpawnGroup then
42564
42840
  local EventPrefix=self:_GetPrefixFromGroup(SpawnGroup)
42565
42841
  if EventPrefix and EventPrefix==self.alias then
42566
- local _i=self:GetSpawnIndexFromGroup(SpawnGroup)
42567
- self.ratcraft[_i].nunits=self.ratcraft[_i].nunits-1
42568
- local _n=self.ratcraft[_i].nunits
42842
+ local ratcraft=self:_GetRatcraftFromGroup(SpawnGroup)
42843
+ if ratcraft then
42844
+ ratcraft.nunits=ratcraft.nunits-1
42569
42845
  local _n0=SpawnGroup:GetInitialSize()
42570
- local text=string.format("Event: Group %s crashed. Unit %s. Units still alive %d of %d.",SpawnGroup:GetName(),EventData.IniUnitName,_n,_n0)
42571
- 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)
42572
42848
  local status=RAT.status.EventCrash
42573
42849
  self:_SetStatus(SpawnGroup,status)
42574
- if _n==0 and self.respawn_after_crash and not self.norespawn then
42575
- local text=string.format("No units left of group %s. Group will be respawned now.",SpawnGroup:GetName())
42576
- self:T(RAT.id..text)
42577
- local idx=self:GetSpawnIndexFromGroup(SpawnGroup)
42578
- local coord=SpawnGroup:GetCoordinate()
42579
- self:_Respawn(idx,coord)
42580
- 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)
42581
42853
  end
42582
42854
  else
42583
- if self.Debug then
42584
- self:E(RAT.id.."ERROR: Group does not exist in RAT:_OnCrash().")
42585
- end
42586
- end
42587
- end
42588
- function RAT:_Despawn(group,delay)
42589
- if group~=nil then
42590
- local index=self:GetSpawnIndexFromGroup(group)
42591
- if index~=nil then
42592
- self.ratcraft[index].group=nil
42593
- self.ratcraft[index]["status"]="Dead"
42594
- local despawndelay=0
42595
- if delay then
42596
- despawndelay=delay
42597
- elseif self.respawn_delay then
42598
- despawndelay=self.respawn_delay
42599
- end
42600
- self:T(RAT.id..string.format("%s delayed despawn in %.1f seconds.",self.alias,despawndelay))
42601
- SCHEDULER:New(nil,self._Destroy,{self,group},despawndelay)
42602
- if self.f10menu and self.SubMenuName~=nil then
42603
- self.Menu[self.SubMenuName]["groups"][index]:Remove()
42604
- end
42605
- end
42606
- end
42607
- end
42608
- function RAT:_Destroy(group)
42609
- self:F2(group)
42610
- local DCSGroup=group:GetDCSObject()
42611
- if DCSGroup and DCSGroup:isExist()then
42612
- local triggerdead=true
42613
- for _,DCSUnit in pairs(DCSGroup:getUnits())do
42614
- if DCSUnit then
42615
- if triggerdead then
42616
- self:_CreateEventDead(timer.getTime(),DCSUnit)
42617
- triggerdead=false
42618
- end
42619
- _DATABASE:DeleteUnit(DCSUnit:getName())
42855
+ self:E(self.lid..string.format("ERROR: Could not find ratcraft object for crashed group %s!",SpawnGroup:GetName()))
42620
42856
  end
42621
42857
  end
42622
- DCSGroup:destroy()
42623
- DCSGroup=nil
42858
+ else
42859
+ if self.Debug then
42860
+ self:E(self.lid.."ERROR: Group does not exist in RAT:_OnCrash()!")
42624
42861
  end
42625
- return nil
42626
42862
  end
42627
- function RAT:_CreateEventDead(EventTime,Initiator)
42628
- self:F({EventTime,Initiator})
42629
- local Event={
42630
- id=world.event.S_EVENT_DEAD,
42631
- time=EventTime,
42632
- initiator=Initiator,
42633
- }
42634
- world.onEvent(Event)
42635
42863
  end
42636
42864
  function RAT:_Waypoint(index,description,Type,Coord,Speed,Altitude,Airport)
42637
42865
  local _Altitude=Altitude or Coord.y
@@ -42684,7 +42912,7 @@ _Type="Turning Point"
42684
42912
  _Action="Turning Point"
42685
42913
  _alttype="BARO"
42686
42914
  else
42687
- 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!")
42688
42916
  _Type="Turning Point"
42689
42917
  _Action="Turning Point"
42690
42918
  _alttype="RADIO"
@@ -42709,7 +42937,7 @@ else
42709
42937
  text=text..string.format("No airport/zone specified\n")
42710
42938
  end
42711
42939
  text=text.."******************************************************\n"
42712
- self:T2(RAT.id..text)
42940
+ self:T2(self.lid..text)
42713
42941
  local RoutePoint={}
42714
42942
  RoutePoint.x=Coord.x
42715
42943
  RoutePoint.y=Coord.z
@@ -42734,30 +42962,12 @@ RoutePoint.helipadId=AirbaseID
42734
42962
  elseif AirbaseCategory==Airbase.Category.AIRDROME then
42735
42963
  RoutePoint.airdromeId=AirbaseID
42736
42964
  else
42737
- self:T(RAT.id.."Unknown Airport category in _Waypoint()!")
42738
- end
42965
+ self:T(self.lid.."Unknown Airport category in _Waypoint()!")
42739
42966
  end
42740
- RoutePoint.properties={
42741
- ["vnav"]=1,
42742
- ["scale"]=0,
42743
- ["angle"]=0,
42744
- ["vangle"]=0,
42745
- ["steer"]=2,
42746
- }
42747
- local TaskCombo={}
42748
- local TaskHolding=self:_TaskHolding({x=Coord.x,y=Coord.z},Altitude,Speed,self:_Randomize(90,0.9))
42749
- local TaskWaypoint=self:_TaskFunction("RAT._WaypointFunction",self,index)
42750
- RoutePoint.task={}
42751
- RoutePoint.task.id="ComboTask"
42752
- RoutePoint.task.params={}
42753
- TaskCombo[#TaskCombo+1]=TaskWaypoint
42754
- if Type==RAT.wp.holding then
42755
- TaskCombo[#TaskCombo+1]=TaskHolding
42756
42967
  end
42757
- RoutePoint.task.params.tasks=TaskCombo
42758
42968
  return RoutePoint
42759
42969
  end
42760
- function RAT:_Routeinfo(waypoints,comment)
42970
+ function RAT:_Routeinfo(waypoints,comment,waypointdescriptions)
42761
42971
  local text=string.format("\n******************************************************\n")
42762
42972
  text=text..string.format("Template = %s\n",self.SpawnTemplatePrefix)
42763
42973
  if comment then
@@ -42766,7 +42976,7 @@ end
42766
42976
  text=text..string.format("Number of waypoints = %i\n",#waypoints)
42767
42977
  for i=1,#waypoints do
42768
42978
  local p=waypoints[i]
42769
- 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])
42770
42980
  end
42771
42981
  local total=0.0
42772
42982
  for i=1,#waypoints-1 do
@@ -42779,115 +42989,27 @@ local y2=point2.y
42779
42989
  local d=math.sqrt((x1-x2)^2+(y1-y2)^2)
42780
42990
  local heading=self:_Course(point1,point2)
42781
42991
  total=total+d
42782
- 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])
42783
42993
  end
42784
42994
  text=text..string.format("Total distance = %6.1f km\n",total/1000)
42785
42995
  text=text..string.format("******************************************************\n")
42786
- self:T2(RAT.id..text)
42996
+ self:T2(self.lid..text)
42787
42997
  return total
42788
42998
  end
42789
- function RAT:_TaskHolding(P1,Altitude,Speed,Duration)
42790
- local dx=3000
42791
- local dy=0
42792
- if self.category==RAT.cat.heli then
42793
- dx=200
42794
- dy=0
42795
- end
42796
- local P2={}
42797
- P2.x=P1.x+dx
42798
- P2.y=P1.y+dy
42799
- local Task={
42800
- id='Orbit',
42801
- params={
42802
- pattern=AI.Task.OrbitPattern.RACE_TRACK,
42803
- point=P1,
42804
- point2=P2,
42805
- speed=Speed,
42806
- altitude=Altitude
42807
- }
42808
- }
42809
- local DCSTask={}
42810
- DCSTask.id="ControlledTask"
42811
- DCSTask.params={}
42812
- DCSTask.params.task=Task
42813
- if self.ATCswitch then
42814
- local userflagname=string.format("%s#%03d",self.alias,self.SpawnIndex+1)
42815
- local maxholdingduration=60*120
42816
- DCSTask.params.stopCondition={userFlag=userflagname,userFlagValue=1,duration=maxholdingduration}
42817
- else
42818
- DCSTask.params.stopCondition={duration=Duration}
42819
- end
42820
- return DCSTask
42821
- end
42822
- function RAT._WaypointFunction(group,rat,wp)
42823
- local Tnow=timer.getTime()
42824
- local sdx=rat:GetSpawnIndexFromGroup(group)
42825
- local departure=rat.ratcraft[sdx].departure:GetName()
42826
- local destination=rat.ratcraft[sdx].destination:GetName()
42827
- local landing=rat.ratcraft[sdx].landing
42828
- local WPholding=rat.ratcraft[sdx].wpholding
42829
- local WPfinal=rat.ratcraft[sdx].wpfinal
42830
- local text
42831
- text=string.format("Flight %s passing waypoint #%d %s.",group:GetName(),wp,rat.waypointdescriptions[wp])
42832
- BASE.T(rat,RAT.id..text)
42833
- local status=rat.waypointstatus[wp]
42834
- rat:_SetStatus(group,status)
42835
- if wp==WPholding then
42836
- text=string.format("Flight %s to %s ATC: Holding and awaiting landing clearance.",group:GetName(),destination)
42837
- MESSAGE:New(text,10):ToAllIf(rat.reportstatus)
42838
- if rat.ATCswitch then
42839
- if rat.f10menu then
42840
- MENU_MISSION_COMMAND:New("Clear for landing",rat.Menu[rat.SubMenuName].groups[sdx],rat.ClearForLanding,rat,group:GetName())
42841
- end
42842
- rat._ATCRegisterFlight(rat,group:GetName(),Tnow)
42843
- end
42844
- end
42845
- if wp==WPfinal then
42846
- text=string.format("Flight %s arrived at final destination %s.",group:GetName(),destination)
42847
- MESSAGE:New(text,10):ToAllIf(rat.reportstatus)
42848
- BASE.T(rat,RAT.id..text)
42849
- if landing==RAT.wp.air then
42850
- text=string.format("Activating despawn switch for flight %s! Group will be detroyed soon.",group:GetName())
42851
- MESSAGE:New(text,10):ToAllIf(rat.Debug)
42852
- BASE.T(rat,RAT.id..text)
42853
- rat.ratcraft[sdx].despawnme=true
42854
- end
42855
- end
42856
- end
42857
- function RAT:_TaskFunction(FunctionString,...)
42858
- self:F2({FunctionString,arg})
42859
- local DCSTask
42860
- local ArgumentKey
42861
- local templatename=self.templategroup:GetName()
42862
- local groupname=self:_AnticipatedGroupName()
42863
- local DCSScript={}
42864
- DCSScript[#DCSScript+1]="local MissionControllable = GROUP:FindByName(\""..groupname.."\") "
42865
- DCSScript[#DCSScript+1]="local RATtemplateControllable = GROUP:FindByName(\""..templatename.."\") "
42866
- if arg and arg.n>0 then
42867
- ArgumentKey='_'..tostring(arg):match("table: (.*)")
42868
- self.templategroup:SetState(self.templategroup,ArgumentKey,arg)
42869
- DCSScript[#DCSScript+1]="local Arguments = RATtemplateControllable:GetState(RATtemplateControllable, '"..ArgumentKey.."' ) "
42870
- DCSScript[#DCSScript+1]=FunctionString.."( MissionControllable, unpack( Arguments ) )"
42871
- else
42872
- DCSScript[#DCSScript+1]=FunctionString.."( MissionControllable )"
42873
- end
42874
- DCSTask=self.templategroup:TaskWrappedAction(self.templategroup:CommandDoScript(table.concat(DCSScript)))
42875
- return DCSTask
42876
- end
42877
42999
  function RAT:_AnticipatedGroupName(index)
42878
43000
  local index=index or self.SpawnIndex+1
42879
43001
  return string.format("%s#%03d",self.alias,index)
42880
43002
  end
42881
43003
  function RAT:_ActivateUncontrolled()
42882
- self:F()
42883
43004
  local idx={}
42884
43005
  local rat={}
42885
43006
  local nactive=0
42886
- for spawnindex,ratcraft in pairs(self.ratcraft)do
43007
+ for spawnindex,_ratcraft in pairs(self.ratcraft)do
43008
+ local ratcraft=_ratcraft
42887
43009
  local group=ratcraft.group
42888
43010
  if group and group:IsAlive()then
42889
- local text=string.format("Uncontrolled: Group = %s (spawnindex = %d), active = %s.",ratcraft.group:GetName(),spawnindex,tostring(ratcraft.active))
42890
- 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)
42891
43013
  if ratcraft.active then
42892
43014
  nactive=nactive+1
42893
43015
  else
@@ -42895,24 +43017,28 @@ table.insert(idx,spawnindex)
42895
43017
  end
42896
43018
  end
42897
43019
  end
42898
- local text=string.format("Uncontrolled: Ninactive = %d, Nactive = %d (of max %d).",#idx,nactive,self.activate_max)
42899
- 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)
42900
43022
  if#idx>0 and nactive<self.activate_max then
42901
43023
  local index=idx[math.random(#idx)]
42902
- local group=self.ratcraft[index].group
42903
- 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())
42904
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()
42905
43037
  end
42906
- function RAT:_CommandStartUncontrolled(group)
42907
- self:F(group)
42908
- local StartCommand={id='Start',params={}}
42909
- local text=string.format("Uncontrolled: Activating group %s.",group:GetName())
42910
- self:T(RAT.id..text)
42911
- group:SetCommand(StartCommand)
42912
- local index=self:GetSpawnIndexFromGroup(group)
42913
- self.ratcraft[index].active=true
43038
+ ratcraft.active=true
42914
43039
  self:_SetStatus(group,RAT.status.EventBirth)
42915
43040
  end
43041
+ end
42916
43042
  function RAT:_CommandInvisible(group,switch)
42917
43043
  local SetInvisible={id='SetInvisible',params={value=switch}}
42918
43044
  group:SetCommand(SetInvisible)
@@ -42949,7 +43075,7 @@ if DCSuniti and DCSuniti:isExist()and DCSunitj and DCSunitj:isExist()then
42949
43075
  local _dist=uniti:GetCoordinate():Get3DDistance(unitj:GetCoordinate())
42950
43076
  if _dist<distmin then
42951
43077
  if(not uniti:InAir())and(not unitj:InAir())then
42952
- 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))
42953
43079
  return true
42954
43080
  end
42955
43081
  end
@@ -42981,6 +43107,21 @@ end
42981
43107
  end
42982
43108
  return false
42983
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
42984
43125
  function RAT:_AirportExists(name)
42985
43126
  for _,airport in pairs(self.airports_map)do
42986
43127
  if airport:GetName()==name then
@@ -42996,25 +43137,31 @@ return true
42996
43137
  end
42997
43138
  return false
42998
43139
  end
42999
- function RAT:_SetROE(group,roe)
43000
- self:T(RAT.id.."Setting ROE to "..roe.." for group "..group:GetName())
43001
- if self.roe==RAT.ROE.returnfire then
43002
- group:OptionROEReturnFire()
43003
- elseif self.roe==RAT.ROE.weaponfree then
43004
- 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
43005
43148
  else
43006
- group:OptionROEHoldFire()
43007
43149
  end
43150
+ flightgroup:SetDefaultROE(_roe)
43151
+ flightgroup:SwitchROE(_roe)
43008
43152
  end
43009
- function RAT:_SetROT(group,rot)
43010
- self:T(RAT.id.."Setting ROT to "..rot.." for group "..group:GetName())
43011
- if self.rot==RAT.ROT.passive then
43012
- group:OptionROTPassiveDefense()
43013
- elseif self.rot==RAT.ROT.evade then
43014
- 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
43015
43161
  else
43016
- group:OptionROTNoReaction()
43017
43162
  end
43163
+ flightgroup:SetDefaultROT(_rot)
43164
+ flightgroup:SwitchROT(_rot)
43018
43165
  end
43019
43166
  function RAT:_SetCoalitionTable()
43020
43167
  if self.friendly==RAT.coal.neutral then
@@ -43024,7 +43171,7 @@ self.ctable={self.coalition,coalition.side.NEUTRAL}
43024
43171
  elseif self.friendly==RAT.coal.sameonly then
43025
43172
  self.ctable={self.coalition}
43026
43173
  else
43027
- 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.")
43028
43175
  self.ctable={self.coalition,coalition.side.NEUTRAL}
43029
43176
  end
43030
43177
  end
@@ -43074,16 +43221,16 @@ end
43074
43221
  local r=math.random(min,max)
43075
43222
  if self.Debug then
43076
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)
43077
- self:T3(RAT.id..text)
43224
+ self:T3(self.lid..text)
43078
43225
  end
43079
43226
  return r
43080
43227
  end
43081
- function RAT:_PlaceMarkers(waypoints,index)
43228
+ function RAT:_PlaceMarkers(waypoints,waypointdescriptions,index)
43082
43229
  for i=1,#waypoints do
43083
- self:_SetMarker(self.waypointdescriptions[i],waypoints[i],index)
43230
+ self:_SetMarker(waypointdescriptions[i],waypoints[i],index)
43084
43231
  if self.Debug then
43085
- local text=string.format("Marker at waypoint #%d: %s for flight #%d",i,self.waypointdescriptions[i],index)
43086
- 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)
43087
43234
  end
43088
43235
  end
43089
43236
  end
@@ -43092,7 +43239,7 @@ RAT.markerid=RAT.markerid+1
43092
43239
  self.markerids[#self.markerids+1]=RAT.markerid
43093
43240
  if self.Debug then
43094
43241
  local text2=string.format("%s: placing marker with ID %d and text %s",self.alias,RAT.markerid,text)
43095
- self:T2(RAT.id..text2)
43242
+ self:T2(self.lid..text2)
43096
43243
  end
43097
43244
  local vec={x=wp.x,y=wp.alt,z=wp.y}
43098
43245
  local flight=self:GetGroupFromIndex(index):GetName()
@@ -43107,7 +43254,7 @@ for k,v in ipairs(self.markerids)do
43107
43254
  self.markerids[k]=nil
43108
43255
  end
43109
43256
  end
43110
- function RAT:_ModifySpawnTemplate(waypoints,livery,spawnplace,departure,takeoff,parkingdata)
43257
+ function RAT:_ModifySpawnTemplate(waypoints,livery,spawnplace,departure,takeoff,parkingdata,uncontrolled)
43111
43258
  self:F2({waypoints=waypoints,livery=livery,spawnplace=spawnplace,departure=departure,takeoff=takeoff,parking=parkingdata})
43112
43259
  local PointVec3=COORDINATE:New(waypoints[1].x,waypoints[1].alt,waypoints[1].y)
43113
43260
  if spawnplace then
@@ -43141,8 +43288,7 @@ if self:_GetSpawnIndex(self.SpawnIndex+1)then
43141
43288
  local SpawnTemplate=self.SpawnGroups[self.SpawnIndex].SpawnTemplate
43142
43289
  if SpawnTemplate then
43143
43290
  self:T(SpawnTemplate)
43144
- if self.uncontrolled then
43145
- self.SpawnUnControlled=true
43291
+ if self.uncontrolled or uncontrolled then
43146
43292
  SpawnTemplate.uncontrolled=true
43147
43293
  end
43148
43294
  local nunits=#SpawnTemplate.units
@@ -43161,25 +43307,27 @@ local scanstatics=true
43161
43307
  local scanscenery=self.parkingscanscenery
43162
43308
  local verysafe=self.parkingverysafe
43163
43309
  if spawnonship or spawnonfarp or spawnonrunway then
43164
- 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()))
43165
43311
  nfree=departure:GetFreeParkingSpotsNumber(termtype,true)
43166
43312
  spots=departure:GetFreeParkingSpotsTable(termtype,true)
43313
+ self:T(self.lid..string.format("Free nfree=%d nspots=%d",nfree,#spots))
43167
43314
  elseif parkingdata~=nil then
43315
+ self:T2("Spawning with explicit parking data")
43168
43316
  nfree=#parkingdata
43169
43317
  spots=parkingdata
43170
43318
  else
43171
43319
  if self.category==RAT.cat.heli then
43172
43320
  if termtype==nil then
43173
- 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))
43174
43322
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.HelicopterOnly,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43175
43323
  nfree=#spots
43176
43324
  if nfree<nunits then
43177
- 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))
43178
43326
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.HelicopterUsable,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43179
43327
  nfree=#spots
43180
43328
  end
43181
43329
  else
43182
- 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))
43183
43331
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,termtype,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43184
43332
  nfree=#spots
43185
43333
  end
@@ -43188,33 +43336,35 @@ if termtype==nil then
43188
43336
  local bomber=TemplateUnit:HasAttribute("Bombers")
43189
43337
  local transport=TemplateUnit:HasAttribute("Transports")
43190
43338
  if bomber or transport then
43191
- 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))
43192
43340
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.OpenBig,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43193
43341
  nfree=#spots
43194
43342
  if nfree<nunits then
43195
- 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))
43196
43344
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.OpenMed,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43197
43345
  nfree=#spots
43198
43346
  end
43199
43347
  else
43200
- 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))
43201
43349
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,AIRBASE.TerminalType.FighterAircraft,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43202
43350
  nfree=#spots
43203
43351
  end
43204
43352
  else
43205
- 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))
43206
43354
  spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup,termtype,scanradius,scanunits,scanstatics,scanscenery,verysafe,nunits)
43207
43355
  nfree=#spots
43208
43356
  end
43209
43357
  end
43210
43358
  end
43359
+ if false then
43211
43360
  local parkingdata=departure:GetParkingSpotsTable(termtype)
43212
- 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)))
43213
43362
  for _,_spot in pairs(parkingdata)do
43214
- 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",
43215
43364
  departure:GetName(),_spot.TerminalID,_spot.TerminalType,tostring(_spot.Free),tostring(_spot.TOAC),_spot.TerminalID0,_spot.DistToRwy))
43216
43365
  end
43217
- 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
43218
43368
  local _notenough=false
43219
43369
  if spawnonship or spawnonfarp or spawnonrunway then
43220
43370
  if nfree>=1 then
@@ -43238,7 +43388,7 @@ end
43238
43388
  end
43239
43389
  if _notenough then
43240
43390
  if self.respawn_inair and not self.SpawnUnControlled then
43241
- 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()))
43242
43392
  spawnonground=false
43243
43393
  spawnonship=false
43244
43394
  spawnonfarp=false
@@ -43253,7 +43403,7 @@ else
43253
43403
  PointVec3.y=PointVec3:GetLandHeight()+math.random(500,3000)
43254
43404
  end
43255
43405
  else
43256
- 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()))
43257
43407
  return nil
43258
43408
  end
43259
43409
  end
@@ -43269,18 +43419,18 @@ local TX=PointVec3.x+(SX-BX)
43269
43419
  local TY=PointVec3.z+(SY-BY)
43270
43420
  if spawnonground then
43271
43421
  if spawnonship or spawnonfarp or spawnonrunway or automatic then
43272
- 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()))
43273
43423
  SpawnTemplate.units[UnitID].x=PointVec3.x
43274
43424
  SpawnTemplate.units[UnitID].y=PointVec3.z
43275
43425
  SpawnTemplate.units[UnitID].alt=PointVec3.y
43276
43426
  else
43277
- 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]))
43278
43428
  SpawnTemplate.units[UnitID].x=parkingspots[UnitID].x
43279
43429
  SpawnTemplate.units[UnitID].y=parkingspots[UnitID].z
43280
43430
  SpawnTemplate.units[UnitID].alt=parkingspots[UnitID].y
43281
43431
  end
43282
43432
  else
43283
- 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()))
43284
43434
  SpawnTemplate.units[UnitID].x=TX
43285
43435
  SpawnTemplate.units[UnitID].y=TY
43286
43436
  SpawnTemplate.units[UnitID].alt=PointVec3.y
@@ -43294,8 +43444,8 @@ UnitTemplate.parking_id=nil
43294
43444
  if parkingindex[UnitID]and not automatic then
43295
43445
  UnitTemplate.parking=parkingindex[UnitID]
43296
43446
  end
43297
- self:T2(RAT.id..string.format("RAT group %s unit number %d: Parking = %s",self.alias,UnitID,tostring(UnitTemplate.parking)))
43298
- 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)))
43299
43449
  SpawnTemplate.units[UnitID].heading=heading
43300
43450
  SpawnTemplate.units[UnitID].psi=-heading
43301
43451
  if livery then
@@ -43332,149 +43482,167 @@ end
43332
43482
  end
43333
43483
  return true
43334
43484
  end
43335
- function RAT:_ATCInit(airports_map)
43485
+ function RAT._ATCInit(airports_map)
43336
43486
  if not RAT.ATC.init then
43337
- local text
43338
- text="Starting RAT ATC.\nSimultanious = "..RAT.ATC.Nclearance.."\n".."Delay = "..RAT.ATC.delay
43339
- BASE:T(RAT.id..text)
43340
- 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)
43341
43489
  for _,ap in pairs(airports_map)do
43342
- local name=ap:GetName()
43343
- RAT.ATC.airport[name]={}
43344
- RAT.ATC.airport[name].queue={}
43345
- RAT.ATC.airport[name].busy=false
43346
- RAT.ATC.airport[name].onfinal={}
43347
- RAT.ATC.airport[name].Nonfinal=0
43348
- RAT.ATC.airport[name].traffic=0
43349
- RAT.ATC.airport[name].Tlastclearance=nil
43350
- end
43351
- SCHEDULER:New(nil,RAT._ATCCheck,{self},5,15)
43352
- 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)
43353
43506
  RAT.ATC.T0=timer.getTime()
43354
43507
  end
43508
+ RAT.ATC.init=true
43355
43509
  end
43356
43510
  function RAT:_ATCAddFlight(name,dest)
43357
- BASE:T(string.format("%sATC %s: Adding flight %s with destination %s.",RAT.id,dest,name,dest))
43358
- RAT.ATC.flight[name]={}
43359
- RAT.ATC.flight[name].destination=dest
43360
- RAT.ATC.flight[name].Tarrive=-1
43361
- RAT.ATC.flight[name].holding=-1
43362
- RAT.ATC.flight[name].Tonfinal=-1
43363
- end
43364
- 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)
43365
43520
  for k,_ in pairs(t)do
43366
43521
  if k==entry then
43522
+ BASE:I(RAT.id..string.format("Removing flight %s from queue",entry))
43367
43523
  t[entry]=nil
43368
43524
  end
43369
43525
  end
43370
43526
  end
43371
- function RAT:_ATCRegisterFlight(name,time)
43372
- 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))
43373
43529
  RAT.ATC.flight[name].Tarrive=time
43374
43530
  RAT.ATC.flight[name].holding=0
43375
43531
  end
43376
- function RAT:_ATCStatus()
43532
+ function RAT._ATCStatus()
43377
43533
  local Tnow=timer.getTime()
43378
- for name,_ in pairs(RAT.ATC.flight)do
43534
+ for name,_flight in pairs(RAT.ATC.flight)do
43535
+ local flight=_flight
43379
43536
  local hold=RAT.ATC.flight[name].holding
43380
43537
  local dest=RAT.ATC.flight[name].destination
43538
+ local airport=RAT.ATC.airport[dest]
43539
+ if airport then
43381
43540
  if hold>=0 then
43382
43541
  local busy="Runway state is unknown"
43383
- if RAT.ATC.airport[dest].Nonfinal>0 then
43384
- busy="Runway is occupied by "..RAT.ATC.airport[dest].Nonfinal
43542
+ if airport.Nonfinal>0 then
43543
+ busy="Runway is occupied by "..airport.Nonfinal
43385
43544
  else
43386
43545
  busy="Runway is currently clear"
43387
43546
  end
43388
43547
  local text=string.format("ATC %s: Flight %s is holding for %i:%02d. %s.",dest,name,hold/60,hold%60,busy)
43389
- BASE:T(RAT.id..text)
43548
+ BASE:I(RAT.id..text)
43390
43549
  elseif hold==RAT.ATC.onfinal then
43391
- local Tfinal=Tnow-RAT.ATC.flight[name].Tonfinal
43550
+ local Tfinal=Tnow-flight.Tonfinal
43392
43551
  local text=string.format("ATC %s: Flight %s is on final. Waiting %i:%02d for landing event.",dest,name,Tfinal/60,Tfinal%60)
43393
- BASE:T(RAT.id..text)
43552
+ BASE:I(RAT.id..text)
43394
43553
  elseif hold==RAT.ATC.unregistered then
43395
43554
  else
43396
43555
  BASE:E(RAT.id.."ERROR: Unknown holding time in RAT:_ATCStatus().")
43397
43556
  end
43557
+ else
43398
43558
  end
43399
43559
  end
43400
- function RAT:_ATCCheck()
43401
- RAT:_ATCQueue()
43402
- local Tnow=timer.getTime()
43403
- for name,_ in pairs(RAT.ATC.airport)do
43404
- for qID,flight in ipairs(RAT.ATC.airport[name].queue)do
43405
- local nqueue=#RAT.ATC.airport[name].queue
43406
- local landing1
43407
- if RAT.ATC.airport[name].Tlastclearance then
43408
- landing1=(Tnow-RAT.ATC.airport[name].Tlastclearance>RAT.ATC.delay)and RAT.ATC.airport[name].Nonfinal<RAT.ATC.Nclearance
43409
- else
43410
- landing1=false
43411
43560
  end
43412
- 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
43413
43574
  if not landing1 and not landing2 then
43414
- RAT.ATC.flight[flight].holding=Tnow-RAT.ATC.flight[flight].Tarrive
43415
- 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)
43416
- 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)
43417
43579
  else
43418
- 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)
43419
- BASE:T(RAT.id..text)
43420
- 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)
43421
43584
  end
43422
43585
  end
43423
43586
  end
43424
- RAT:_ATCQueue()
43587
+ RAT._ATCQueue()
43425
43588
  end
43426
- function RAT:_ATCClearForLanding(airport,flight)
43427
- RAT.ATC.flight[flight].holding=RAT.ATC.onfinal
43428
- RAT.ATC.airport[airport].busy=true
43429
- RAT.ATC.airport[airport].onfinal[flight]=flight
43430
- RAT.ATC.airport[airport].Nonfinal=RAT.ATC.airport[airport].Nonfinal+1
43431
- RAT.ATC.airport[airport].Tlastclearance=timer.getTime()
43432
- RAT.ATC.flight[flight].Tonfinal=timer.getTime()
43433
- trigger.action.setUserFlag(flight,1)
43434
- local flagvalue=trigger.misc.getUserFlag(flight)
43435
- local text1=string.format("ATC %s: Flight %s cleared for landing (flag=%d).",airport,flight,flagvalue)
43436
- if string.find(flight,"#")then
43437
- flight=string.match(flight,"^(.+)#")
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,"^(.+)#")
43438
43604
  end
43439
- local text2=string.format("ATC %s: Flight %s you are cleared for landing.",airport,flight)
43440
- BASE:T(RAT.id..text1)
43441
- MESSAGE:New(text2,10):ToAllIf(RAT.ATC.messages)
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!")
43442
43609
  end
43443
- function RAT:_ATCFlightLanded(name)
43444
- if RAT.ATC.flight[name]then
43445
- local dest=RAT.ATC.flight[name].destination
43610
+ end
43611
+ function RAT._ATCFlightLanded(name)
43612
+ local flight=RAT.ATC.flight[name]
43613
+ if flight then
43614
+ local dest=flight.destination
43446
43615
  local Tnow=timer.getTime()
43447
- local Tfinal=Tnow-RAT.ATC.flight[name].Tonfinal
43448
- local Thold=RAT.ATC.flight[name].Tonfinal-RAT.ATC.flight[name].Tarrive
43449
- RAT.ATC.airport[dest].busy=false
43450
- RAT.ATC.airport[dest].onfinal[name]=nil
43451
- RAT.ATC.airport[dest].Nonfinal=RAT.ATC.airport[dest].Nonfinal-1
43452
- RAT:_ATCDelFlight(RAT.ATC.flight,name)
43453
- RAT.ATC.airport[dest].traffic=RAT.ATC.airport[dest].traffic+1
43454
- local TrafficPerHour=RAT.ATC.airport[dest].traffic/(timer.getTime()-RAT.ATC.T0)*3600
43455
- 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)
43456
- local text2=string.format("ATC %s: Number of flights still on final %d.",dest,RAT.ATC.airport[dest].Nonfinal)
43457
- 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))
43458
43628
  if string.find(name,"#")then
43459
43629
  name=string.match(name,"^(.+)#")
43460
43630
  end
43461
- local text4=string.format("ATC %s: Flight %s landed. Welcome to %s.",dest,name,dest)
43462
- BASE:T(RAT.id..text1)
43463
- BASE:T(RAT.id..text2)
43464
- BASE:T(RAT.id..text3)
43465
- 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)
43466
43633
  end
43467
43634
  end
43468
- function RAT:_ATCQueue()
43635
+ function RAT._ATCQueue()
43636
+ local Tnow=timer.getTime()
43469
43637
  for airport,_ in pairs(RAT.ATC.airport)do
43470
43638
  local _queue={}
43471
- for name,_ in pairs(RAT.ATC.flight)do
43472
- local Tnow=timer.getTime()
43473
- if RAT.ATC.flight[name].holding>=0 then
43474
- 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
43475
43643
  end
43476
- local hold=RAT.ATC.flight[name].holding
43477
- local dest=RAT.ATC.flight[name].destination
43644
+ local hold=flight.holding
43645
+ local dest=flight.destination
43478
43646
  if hold>=0 and airport==dest then
43479
43647
  _queue[#_queue+1]={name,hold}
43480
43648
  end
@@ -43508,7 +43676,7 @@ RATMANAGER.id="RATMANAGER | "
43508
43676
  function RATMANAGER:New(ntot)
43509
43677
  local self=BASE:Inherit(self,BASE:New())
43510
43678
  self.ntot=ntot or 1
43511
- 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))
43512
43680
  return self
43513
43681
  end
43514
43682
  function RATMANAGER:Add(ratobject,min)
@@ -43525,7 +43693,8 @@ ratobject:Spawn(0)
43525
43693
  return self
43526
43694
  end
43527
43695
  function RATMANAGER:Start(delay)
43528
- local delay=delay or 5
43696
+ delay=delay or 5
43697
+ if delay and delay>0 then
43529
43698
  local text=string.format(RATMANAGER.id.."RAT manager will be started in %d seconds.\n",delay)
43530
43699
  text=text..string.format("Managed groups:\n")
43531
43700
  for i=1,self.nrat do
@@ -43533,10 +43702,8 @@ text=text..string.format("- %s with min groups %d\n",self.name[i],self.min[i])
43533
43702
  end
43534
43703
  text=text..string.format("Number of constantly alive groups %d",self.ntot)
43535
43704
  self:E(text)
43536
- SCHEDULER:New(nil,self._Start,{self},delay)
43537
- return self
43538
- end
43539
- function RATMANAGER:_Start()
43705
+ self:ScheduleOnce(delay,RATMANAGER.Start,self,0)
43706
+ else
43540
43707
  local n=0
43541
43708
  for i=1,self.nrat do
43542
43709
  n=n+self.min[i]
@@ -43547,30 +43714,32 @@ local time=0.0
43547
43714
  for i=1,self.nrat do
43548
43715
  for j=1,N[i]do
43549
43716
  time=time+self.dTspawn
43550
- SCHEDULER:New(nil,RAT._SpawnWithRoute,{self.rat[i]},time)
43717
+ self:ScheduleOnce(time,RAT._SpawnWithRoute,self.rat[i])
43551
43718
  end
43552
43719
  end
43553
43720
  for i=1,self.nrat do
43554
- if self.rat[i].uncontrolled and self.rat[i].activate_uncontrolled then
43555
- local Tactivate=math.max(time+1,self.rat[i].activate_delay)
43556
- 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)
43557
43725
  end
43558
43726
  end
43559
43727
  local TstartManager=math.max(time+1,self.Tcheck)
43560
43728
  self.manager,self.managerid=SCHEDULER:New(self,self._Manage,{self},TstartManager,self.Tcheck)
43561
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)
43562
- self:E(text)
43730
+ self:I(text)
43731
+ end
43563
43732
  return self
43564
43733
  end
43565
43734
  function RATMANAGER:Stop(delay)
43566
43735
  delay=delay or 1
43567
- self:E(string.format(RATMANAGER.id.."Manager will be stopped in %d seconds.",delay))
43568
- SCHEDULER:New(nil,self._Stop,{self},delay)
43569
- return self
43570
- end
43571
- function RATMANAGER:_Stop()
43572
- 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))
43573
43741
  self.manager:Stop(self.managerid)
43742
+ end
43574
43743
  return self
43575
43744
  end
43576
43745
  function RATMANAGER:SetTcheck(dt)
@@ -43583,15 +43752,14 @@ return self
43583
43752
  end
43584
43753
  function RATMANAGER:_Manage()
43585
43754
  local ntot=self:_Count()
43586
- local text=string.format("Number of alive groups %d. New groups to be spawned %d.",ntot,self.ntot-ntot)
43587
- 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))
43588
43756
  local N=self:_RollDice(self.nrat,self.ntot,self.min,self.alive)
43589
43757
  local time=0.0
43590
43758
  for i=1,self.nrat do
43591
43759
  for j=1,N[i]do
43592
43760
  time=time+self.dTspawn
43593
43761
  self.planned[i]=self.planned[i]+1
43594
- SCHEDULER:New(nil,RATMANAGER._Spawn,{self,i},time)
43762
+ self:ScheduleOnce(time,RATMANAGER._Spawn,self,i)
43595
43763
  end
43596
43764
  end
43597
43765
  end
@@ -59414,6 +59582,7 @@ brc=self:GetBRCintoWind(self.recoverywindow.SPEED)
59414
59582
  end
59415
59583
  flight.Tcharlie=self:_GetCharlieTime(flight)
59416
59584
  local Ccharlie=UTILS.SecondsToClock(flight.Tcharlie)
59585
+ brc=brc%360
59417
59586
  self:_MarshalCallArrived(flight.onboard,flight.case,brc,alt,Ccharlie,P)
59418
59587
  if self.TACANon and(not flight.ai)and flight.difficulty==AIRBOSS.Difficulty.EASY then
59419
59588
  local radial=self:GetRadial(flight.case,true,true,true)
@@ -59777,7 +59946,7 @@ playerData.stable=false
59777
59946
  playerData.landed=false
59778
59947
  playerData.Tlso=timer.getTime()
59779
59948
  playerData.Tgroove=nil
59780
- playerData.TIG0=nil
59949
+ playerData.TIG0=0
59781
59950
  playerData.wire=nil
59782
59951
  playerData.flag=-100
59783
59952
  playerData.debriefschedulerID=nil
@@ -60807,77 +60976,9 @@ if self:_CheckAbort(X,Z,self.BreakEntry)then
60807
60976
  self:_AbortPattern(playerData,X,Z,self.BreakEntry,true)
60808
60977
  return
60809
60978
  end
60810
- local stern=self:_GetSternCoord()
60811
- local coord=playerData.unit:GetCoordinate()
60812
- local dist=coord:Get2DDistance(stern)
60813
- local playerCallsign=playerData.unit:GetCallsign()
60814
- local playerName=playerData.name
60815
- local unit=playerData.unit
60816
- local unitClient=Unit.getByName(unit:GetName())
60817
- local hookArgument=unitClient:getDrawArgumentValue(25)
60818
- local hookArgument_Tomcat=unitClient:getDrawArgumentValue(1305)
60819
- local speedMPS=playerData.unit:GetVelocityMPS()
60820
- local speedKTS=UTILS.MpsToKnots(speedMPS)
60821
- local player_alt=playerData.unit:GetAltitude()
60822
- player_alt_feet=player_alt*3.28
60823
- player_alt_feet=player_alt_feet/10
60824
- player_alt_feet=math.floor(player_alt_feet)*10
60825
- local player_velocity_round=speedKTS*1.00
60826
- player_velocity_round=player_velocity_round/10
60827
- player_velocity_round=math.floor(player_velocity_round)*10
60828
- local 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 Play_SH_Sound=USERSOUND:New("Airboss Soundfiles/GreatBallsOfFire.ogg")
60832
- local Play_666SH_Sound=USERSOUND:New("Airboss Soundfiles/Runninwiththedevil.ogg")
60833
- local playerType=playerData.actype
60834
- if dist<1000 and clientSHBFlag==false then
60835
- if speedKTS>450 and speedKTS<590 then
60836
- if player_alt_feet<1500 then
60837
- if hookArgument>0 or hookArgument_Tomcat>0 then
60838
- playerData.shb=true
60839
- trigger.action.outText(playerName..' performing a Sierra Hotel Break in a '..playerType,10)
60840
- 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!**')
60841
- HypeMan.sendBotMessage(sh_message_to_discord)
60842
- Play_SH_Sound:ToAll()
60843
- clientSHBFlag=true
60844
- else
60845
- playerData.shb=false
60846
- end
60847
- else
60848
- end
60849
- elseif speedKTS>589 then
60850
- if player_alt_feet<625 and player_alt_feet>575 then
60851
- if hookArgument>0 or hookArgument_Tomcat>0 then
60852
- playerData.shb=true
60853
- trigger.action.outText(playerName..' performing a 666 Sierra Hotel Break in a '..playerType,10)
60854
- 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!**')
60855
- HypeMan.sendBotMessage(sh_message_to_discord)
60856
- Play_666SH_Sound:ToAll()
60857
- clientSHBFlag=true
60858
- else
60859
- playerData.shb=false
60860
- end
60861
- else
60862
- if hookArgument>0 or hookArgument_Tomcat>0 then
60863
- playerData.shb=true
60864
- trigger.action.outText(playerName..' performing a Sierra Hotel Break in a '..playerType,10)
60865
- 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!**')
60866
- HypeMan.sendBotMessage(sh_message_to_discord)
60867
- Play_SH_Sound:ToAll()
60868
- clientSHBFlag=true
60869
- else
60870
- playerData.shb=false
60871
- end
60872
- end
60873
- else
60874
- end
60875
- else
60876
- end
60877
60979
  if self:_CheckLimits(X,Z,self.BreakEntry)then
60878
60980
  self:_PlayerHint(playerData)
60879
60981
  self:_SetPlayerStep(playerData,AIRBOSS.PatternStep.EARLYBREAK)
60880
- clientSHBFlag=false
60881
60982
  end
60882
60983
  end
60883
60984
  function AIRBOSS:_Break(playerData,part)
@@ -61165,19 +61266,19 @@ end
61165
61266
  if rho>=RAR and rho<=RIM then
61166
61267
  if gd.LUE>0.22 and lineupError<-0.22 then
61167
61268
  env.info" Drift Right across centre ==> DR-"
61168
- gd.Drift=" DR"
61269
+ gd.Drift="DR"
61169
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))
61170
61271
  elseif gd.LUE<-0.22 and lineupError>0.22 then
61171
61272
  env.info" Drift Left ==> DL-"
61172
- gd.Drift=" DL"
61273
+ gd.Drift="DL"
61173
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))
61174
61275
  elseif gd.LUE>0.13 and lineupError<-0.14 then
61175
61276
  env.info" Little Drift Right across centre ==> (DR-)"
61176
- gd.Drift=" (DR)"
61277
+ gd.Drift="(DR)"
61177
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))
61178
61279
  elseif gd.LUE<-0.13 and lineupError>0.14 then
61179
61280
  env.info" Little Drift Left across centre ==> (DL-)"
61180
- gd.Drift=" (DL)"
61281
+ gd.Drift="(DL)"
61181
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))
61182
61283
  end
61183
61284
  end
@@ -61976,9 +62077,7 @@ local hdg=self.carrier:GetHeading()
61976
62077
  if magnetic then
61977
62078
  hdg=hdg-self.magvar
61978
62079
  end
61979
- if hdg<0 then
61980
- hdg=hdg+360
61981
- end
62080
+ hdg=hdg%360
61982
62081
  return hdg
61983
62082
  end
61984
62083
  function AIRBOSS:GetBRC()
@@ -62077,7 +62176,7 @@ theta=math.asin(vdeck*math.sin(alpha)/vwind)
62077
62176
  v=vdeck*math.cos(alpha)-vwind*math.cos(theta)
62078
62177
  end
62079
62178
  local magvar=magnetic and self.magvar or 0
62080
- local intowind=self:GetHeadingIntoWind_old(vdeck)
62179
+ local intowind=self:GetHeadingIntoWind_old(vdeck,magnetic)
62081
62180
  return intowind,v
62082
62181
  end
62083
62182
  function AIRBOSS:GetBRCintoWind(vdeck)
@@ -62268,7 +62367,7 @@ return select(2,string.gsub(base,pattern,""))
62268
62367
  end
62269
62368
  local TIG=""
62270
62369
  if playerData.Tgroove and playerData.Tgroove<=360 and playerData.case<3 then
62271
- TIG=self:_EvalGrooveTime(playerData)
62370
+ TIG=self:_EvalGrooveTime(playerData)or"N/A"
62272
62371
  end
62273
62372
  local GXX,nXX=self:_Flightdata2Text(playerData,AIRBOSS.GroovePos.XX)
62274
62373
  local GIM,nIM=self:_Flightdata2Text(playerData,AIRBOSS.GroovePos.IM)
@@ -62390,14 +62489,8 @@ grade="CUT"
62390
62489
  points=0.0
62391
62490
  end
62392
62491
  end
62393
- if playerData.wire==1 and points>1 then
62394
- if points==4 then
62395
- points=3
62396
- grade="(OK)"
62397
- elseif points==3 then
62398
- points=2
62399
- grade="--"
62400
- end
62492
+ if playerData.wire==1 and points>=3 and N>4 then
62493
+ points=points-1
62401
62494
  end
62402
62495
  env.info("Returning: "..grade.." "..points.." "..G)
62403
62496
  return grade,points,G
@@ -62445,6 +62538,7 @@ O=little("OS")
62445
62538
  end
62446
62539
  end
62447
62540
  local S=nil
62541
+ local A=nil
62448
62542
  if step~=AIRBOSS.PatternStep.GROOVE_IW then
62449
62543
  if AIRBOSS.PatternStep.GROOVE_AR and playerData.waveoff==true and playerData.owo==true then
62450
62544
  else
@@ -62461,7 +62555,6 @@ S="F"
62461
62555
  elseif AOA<acaoa.OnSpeedMin then
62462
62556
  S=little("F")
62463
62557
  end
62464
- local A=nil
62465
62558
  if GSE>self.gle.HIGH then
62466
62559
  A=underline("H")
62467
62560
  elseif GSE>self.gle.High then
@@ -69133,6 +69226,7 @@ CTLD.UnitTypeCapabilities={
69133
69226
  ["Mi-24V"]={type="Mi-24V",crates=true,troops=true,cratelimit=2,trooplimit=8,length=18,cargoweightlimit=700},
69134
69227
  ["Hercules"]={type="Hercules",crates=true,troops=true,cratelimit=7,trooplimit=64,length=25,cargoweightlimit=19000},
69135
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},
69136
69230
  ["MH-60R"]={type="MH-60R",crates=true,troops=true,cratelimit=2,trooplimit=20,length=16,cargoweightlimit=3500},
69137
69231
  ["SH-60B"]={type="SH-60B",crates=true,troops=true,cratelimit=2,trooplimit=20,length=16,cargoweightlimit=3500},
69138
69232
  ["AH-64D_BLK_II"]={type="AH-64D_BLK_II",crates=false,troops=true,cratelimit=0,trooplimit=2,length=17,cargoweightlimit=200},
@@ -69148,7 +69242,7 @@ CTLD.FixedWingTypes={
69148
69242
  ["Bronco"]="Bronco",
69149
69243
  ["Mosquito"]="Mosquito",
69150
69244
  }
69151
- CTLD.version="1.3.37"
69245
+ CTLD.version="1.3.38"
69152
69246
  function CTLD:New(Coalition,Prefixes,Alias)
69153
69247
  local self=BASE:Inherit(self,FSM:New())
69154
69248
  BASE:T({Coalition,Prefixes,Alias})
@@ -69250,6 +69344,7 @@ self.dropAsCargoCrate=false
69250
69344
  self.smokedistance=2000
69251
69345
  self.movetroopstowpzone=true
69252
69346
  self.movetroopsdistance=5000
69347
+ self.returntroopstobase=true
69253
69348
  self.troopdropzoneradius=100
69254
69349
  self.VehicleMoveFormation=AI.Task.VehicleFormation.VEE
69255
69350
  self.enableHercules=false
@@ -70354,6 +70449,7 @@ self:_UpdateUnitCargoMass(Unit)
70354
70449
  self:_RefreshDropCratesMenu(Group,Unit)
70355
70450
  self:_RefreshLoadCratesMenu(Group,Unit)
70356
70451
  self:_CleanupTrackedCrates(crateidsloaded)
70452
+ self:__CratesPickedUp(1,Group,Unit,loaded.Cargo)
70357
70453
  end
70358
70454
  end
70359
70455
  return self
@@ -70621,7 +70717,7 @@ if not inzone then
70621
70717
  inzone,zonename,zone,distance=self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
70622
70718
  end
70623
70719
  if inzone then
70624
- droppingatbase=true
70720
+ droppingatbase=self.returntroopstobase
70625
70721
  end
70626
70722
  local hoverunload=self:IsCorrectHover(Unit)
70627
70723
  local IsHerc=self:IsFixedWing(Unit)
@@ -71352,7 +71448,7 @@ end
71352
71448
  end
71353
71449
  end
71354
71450
  else
71355
- if self.usesubcats then
71451
+ if self.usesubcats==true then
71356
71452
  local subcatmenus={}
71357
71453
  for catName,_ in pairs(self.subcats)do
71358
71454
  subcatmenus[catName]=MENU_GROUP:New(_group,catName,cratesmenu)
@@ -71811,7 +71907,7 @@ if not inzone then
71811
71907
  inzone,zonename,zone,distance=self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
71812
71908
  end
71813
71909
  if inzone then
71814
- droppingatbase=true
71910
+ droppingatbase=self.returntroopstobase
71815
71911
  end
71816
71912
  if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName())then
71817
71913
  self:_SendMessage("You need to open the door(s) to unload troops!",10,false,Group)
@@ -72192,7 +72288,12 @@ self:E(self.lid.."**** Ship does not exist: "..Name)
72192
72288
  return self
72193
72289
  end
72194
72290
  end
72195
- 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
72196
72297
  ctldzone.active=Active or false
72197
72298
  ctldzone.color=Color or SMOKECOLOR.Red
72198
72299
  ctldzone.name=Name or"NONE"
@@ -72215,9 +72316,45 @@ if Type==CTLD.CargoZoneType.SHIP then
72215
72316
  ctldzone.shiplength=Shiplength or 100
72216
72317
  ctldzone.shipwidth=Shipwidth or 10
72217
72318
  end
72319
+ if not exists then
72218
72320
  self:AddZone(ctldzone)
72321
+ end
72219
72322
  return self
72220
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
72221
72358
  function CTLD:AddCTLDZoneFromAirbase(AirbaseName,Type,Color,Active,HasBeacon)
72222
72359
  self:T(self.lid.." AddCTLDZoneFromAirbase")
72223
72360
  local AFB=AIRBASE:FindByName(AirbaseName)
@@ -74211,13 +74348,14 @@ CSAR.AircraftType["Mi-24P"]=8
74211
74348
  CSAR.AircraftType["Mi-24V"]=8
74212
74349
  CSAR.AircraftType["Bell-47"]=2
74213
74350
  CSAR.AircraftType["UH-60L"]=10
74351
+ CSAR.AircraftType["UH-60L_DAP"]=2
74214
74352
  CSAR.AircraftType["AH-64D_BLK_II"]=2
74215
74353
  CSAR.AircraftType["Bronco-OV-10A"]=2
74216
74354
  CSAR.AircraftType["MH-60R"]=10
74217
74355
  CSAR.AircraftType["OH-6A"]=2
74218
74356
  CSAR.AircraftType["OH58D"]=2
74219
74357
  CSAR.AircraftType["CH-47Fbl1"]=31
74220
- CSAR.version="1.0.33"
74358
+ CSAR.version="1.0.34"
74221
74359
  function CSAR:New(Coalition,Template,Alias)
74222
74360
  local self=BASE:Inherit(self,FSM:New())
74223
74361
  BASE:T({Coalition,Template,Alias})
@@ -74663,11 +74801,11 @@ return self
74663
74801
  end
74664
74802
  local initdcscoord=nil
74665
74803
  local initcoord=nil
74666
- if _event.id==EVENTS.Ejection then
74804
+ if _event.id==EVENTS.Ejection and _event.TgtDCSUnit then
74667
74805
  initdcscoord=_event.TgtDCSUnit:getPoint()
74668
74806
  initcoord=COORDINATE:NewFromVec3(initdcscoord)
74669
74807
  self:T({initdcscoord})
74670
- else
74808
+ elseif _event.IniDCSUnit then
74671
74809
  initdcscoord=_event.IniDCSUnit:getPoint()
74672
74810
  initcoord=COORDINATE:NewFromVec3(initdcscoord)
74673
74811
  self:T({initdcscoord})
@@ -74730,7 +74868,10 @@ return self
74730
74868
  end
74731
74869
  if _place:GetCoalition()==self.coalition or _place:GetCoalition()==coalition.side.NEUTRAL then
74732
74870
  self:__Landed(2,_event.IniUnitName,_place)
74733
- 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)
74734
74875
  else
74735
74876
  self:T(string.format("Airfield %d, Unit %d",_place:GetCoalition(),_unit:GetCoalition()))
74736
74877
  end
@@ -75085,7 +75226,7 @@ else
75085
75226
  return false
75086
75227
  end
75087
75228
  end
75088
- function CSAR:_ScheduledSARFlight(heliname,groupname,isairport,noreschedule)
75229
+ function CSAR:_ScheduledSARFlight(heliname,groupname,isairport,noreschedule,IsHeloBase)
75089
75230
  self:T(self.lid.." _ScheduledSARFlight")
75090
75231
  self:T({heliname,groupname})
75091
75232
  local _heliUnit=self:_GetSARHeli(heliname)
@@ -75103,7 +75244,7 @@ self:T(self.lid.."[Drop off debug] Check distance to MASH for "..heliname.." Dis
75103
75244
  return
75104
75245
  end
75105
75246
  self:T(self.lid.."[Drop off debug] Check distance to MASH for "..heliname.." Distance km: "..math.floor(_dist/1000))
75106
- 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
75107
75248
  self:T(self.lid.."[Drop off debug] Distance ok, door check")
75108
75249
  if self.pilotmustopendoors and self:_IsLoadingDoorOpen(heliname)==false then
75109
75250
  self:_DisplayMessageToSAR(_heliUnit,"Open the door to let me out!",self.messageTime,true,true)
@@ -75116,7 +75257,7 @@ end
75116
75257
  end
75117
75258
  if not noreschedule then
75118
75259
  self:__Returning(5,heliname,_woundedGroupName,isairport)
75119
- self:ScheduleOnce(5,self._ScheduledSARFlight,self,heliname,groupname,isairport,noreschedule)
75260
+ self:ScheduleOnce(5,self._ScheduledSARFlight,self,heliname,groupname,isairport,noreschedule,IsHeloBase)
75120
75261
  end
75121
75262
  return self
75122
75263
  end