@jtff/miztemplate-lib 3.2.0 → 3.2.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.
- package/lua/lib/Moose_.lua +1864 -361
- package/lua/lib/{mist_4_5_122.lua → mist.lua} +86 -59
- package/package.json +1 -1
- package/scripts/inject-scripts.js +1 -1
package/lua/lib/Moose_.lua
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
env.info('*** MOOSE GITHUB Commit Hash ID: 2024-
|
|
1
|
+
env.info('*** MOOSE GITHUB Commit Hash ID: 2024-04-30T09:18:49+02:00-27d36f3e0d82fd46b94fb09e6ebb81b963bc40c0 ***')
|
|
2
2
|
if not MOOSE_DEVELOPMENT_FOLDER then
|
|
3
3
|
MOOSE_DEVELOPMENT_FOLDER='Scripts'
|
|
4
4
|
end
|
|
@@ -1315,9 +1315,9 @@ return s
|
|
|
1315
1315
|
end
|
|
1316
1316
|
end
|
|
1317
1317
|
end
|
|
1318
|
-
function UTILS.PrintTableToLog(table,indent)
|
|
1318
|
+
function UTILS.PrintTableToLog(table,indent,noprint)
|
|
1319
1319
|
local text="\n"
|
|
1320
|
-
if not table then
|
|
1320
|
+
if not table or type(table)~="table"then
|
|
1321
1321
|
env.warning("No table passed!")
|
|
1322
1322
|
return nil
|
|
1323
1323
|
end
|
|
@@ -1325,11 +1325,16 @@ if not indent then indent=0 end
|
|
|
1325
1325
|
for k,v in pairs(table)do
|
|
1326
1326
|
if string.find(k," ")then k='"'..k..'"'end
|
|
1327
1327
|
if type(v)=="table"then
|
|
1328
|
+
if not noprint then
|
|
1328
1329
|
env.info(string.rep(" ",indent)..tostring(k).." = {")
|
|
1330
|
+
end
|
|
1329
1331
|
text=text..string.rep(" ",indent)..tostring(k).." = {\n"
|
|
1330
1332
|
text=text..tostring(UTILS.PrintTableToLog(v,indent+1)).."\n"
|
|
1333
|
+
if not noprint then
|
|
1331
1334
|
env.info(string.rep(" ",indent).."},")
|
|
1335
|
+
end
|
|
1332
1336
|
text=text..string.rep(" ",indent).."},\n"
|
|
1337
|
+
elseif type(v)=="function"then
|
|
1333
1338
|
else
|
|
1334
1339
|
local value
|
|
1335
1340
|
if tostring(v)=="true"or tostring(v)=="false"or tonumber(v)~=nil then
|
|
@@ -1337,7 +1342,9 @@ value=v
|
|
|
1337
1342
|
else
|
|
1338
1343
|
value='"'..tostring(v)..'"'
|
|
1339
1344
|
end
|
|
1345
|
+
if not noprint then
|
|
1340
1346
|
env.info(string.rep(" ",indent)..tostring(k).." = "..tostring(value)..",\n")
|
|
1347
|
+
end
|
|
1341
1348
|
text=text..string.rep(" ",indent)..tostring(k).." = "..tostring(value)..",\n"
|
|
1342
1349
|
end
|
|
1343
1350
|
end
|
|
@@ -2402,6 +2409,10 @@ if type_name=="Bronco-OV-10A"then
|
|
|
2402
2409
|
BASE:T(unit_name.." front door(s) are open")
|
|
2403
2410
|
return true
|
|
2404
2411
|
end
|
|
2412
|
+
if type_name=="MH-60R"and(unit:getDrawArgumentValue(403)>0 or unit:getDrawArgumentValue(403)==-1)then
|
|
2413
|
+
BASE:T(unit_name.." cargo door is open")
|
|
2414
|
+
return true
|
|
2415
|
+
end
|
|
2405
2416
|
return false
|
|
2406
2417
|
end
|
|
2407
2418
|
return nil
|
|
@@ -3255,6 +3266,18 @@ end
|
|
|
3255
3266
|
function string.contains(str,value)
|
|
3256
3267
|
return string.match(str,value)
|
|
3257
3268
|
end
|
|
3269
|
+
function table.move_object(obj,from_table,to_table)
|
|
3270
|
+
local index
|
|
3271
|
+
for i,v in pairs(from_table)do
|
|
3272
|
+
if v==obj then
|
|
3273
|
+
index=i
|
|
3274
|
+
end
|
|
3275
|
+
end
|
|
3276
|
+
if index then
|
|
3277
|
+
local moved=table.remove(from_table,index)
|
|
3278
|
+
table.insert_unique(to_table,moved)
|
|
3279
|
+
end
|
|
3280
|
+
end
|
|
3258
3281
|
function table.contains(tbl,element)
|
|
3259
3282
|
if element==nil or tbl==nil then return false end
|
|
3260
3283
|
local index=1
|
|
@@ -3391,6 +3414,90 @@ end
|
|
|
3391
3414
|
function UTILS.OctalToDecimal(Number)
|
|
3392
3415
|
return tonumber(Number,8)
|
|
3393
3416
|
end
|
|
3417
|
+
function UTILS.HexToRGBA(hex_string)
|
|
3418
|
+
local hexNumber=tonumber(string.sub(hex_string,3),16)
|
|
3419
|
+
local alpha=hexNumber%256
|
|
3420
|
+
hexNumber=(hexNumber-alpha)/256
|
|
3421
|
+
local blue=hexNumber%256
|
|
3422
|
+
hexNumber=(hexNumber-blue)/256
|
|
3423
|
+
local green=hexNumber%256
|
|
3424
|
+
hexNumber=(hexNumber-green)/256
|
|
3425
|
+
local red=hexNumber%256
|
|
3426
|
+
return{R=red,G=green,B=blue,A=alpha}
|
|
3427
|
+
end
|
|
3428
|
+
function UTILS.SaveSetOfOpsGroups(Set,Path,Filename,Structured)
|
|
3429
|
+
local filename=Filename or"SetOfGroups"
|
|
3430
|
+
local data="--Save SET of groups: (name,legion,template,alttemplate,units,position.x,position.y,position.z,strucdata) "..Filename.."\n"
|
|
3431
|
+
local List=Set:GetSetObjects()
|
|
3432
|
+
for _,_group in pairs(List)do
|
|
3433
|
+
local group=_group:GetGroup()
|
|
3434
|
+
if group and group:IsAlive()then
|
|
3435
|
+
local name=group:GetName()
|
|
3436
|
+
local template=string.gsub(name,"(.AID.%d+$","")
|
|
3437
|
+
if string.find(template,"#")then
|
|
3438
|
+
template=string.gsub(name,"#(%d+)$","")
|
|
3439
|
+
end
|
|
3440
|
+
local alttemplate=_group.templatename or"none"
|
|
3441
|
+
local legiono=_group.legion
|
|
3442
|
+
local legion="none"
|
|
3443
|
+
if legiono and type(legiono)=="table"and legiono.ClassName then
|
|
3444
|
+
legion=legiono:GetName()
|
|
3445
|
+
local asset=legiono:GetAssetByName(name)
|
|
3446
|
+
alttemplate=asset.templatename
|
|
3447
|
+
end
|
|
3448
|
+
local units=group:CountAliveUnits()
|
|
3449
|
+
local position=group:GetVec3()
|
|
3450
|
+
if Structured then
|
|
3451
|
+
local structure=UTILS.GetCountPerTypeName(group)
|
|
3452
|
+
local strucdata=""
|
|
3453
|
+
for typen,anzahl in pairs(structure)do
|
|
3454
|
+
strucdata=strucdata..typen.."=="..anzahl..";"
|
|
3455
|
+
end
|
|
3456
|
+
data=string.format("%s%s,%s,%s,%s,%d,%d,%d,%d,%s\n",data,name,legion,template,alttemplate,units,position.x,position.y,position.z,strucdata)
|
|
3457
|
+
else
|
|
3458
|
+
data=string.format("%s%s,%s,%s,%s,%d,%d,%d,%d\n",data,name,legion,template,alttemplate,units,position.x,position.y,position.z)
|
|
3459
|
+
end
|
|
3460
|
+
end
|
|
3461
|
+
end
|
|
3462
|
+
local outcome=UTILS.SaveToFile(Path,Filename,data)
|
|
3463
|
+
return outcome
|
|
3464
|
+
end
|
|
3465
|
+
function UTILS.LoadSetOfOpsGroups(Path,Filename)
|
|
3466
|
+
local filename=Filename or"SetOfGroups"
|
|
3467
|
+
local datatable={}
|
|
3468
|
+
if UTILS.CheckFileExists(Path,filename)then
|
|
3469
|
+
local outcome,loadeddata=UTILS.LoadFromFile(Path,Filename)
|
|
3470
|
+
table.remove(loadeddata,1)
|
|
3471
|
+
for _id,_entry in pairs(loadeddata)do
|
|
3472
|
+
local dataset=UTILS.Split(_entry,",")
|
|
3473
|
+
local groupname=dataset[1]
|
|
3474
|
+
local legion=dataset[2]
|
|
3475
|
+
local template=dataset[3]
|
|
3476
|
+
local alttemplate=dataset[4]
|
|
3477
|
+
local size=tonumber(dataset[5])
|
|
3478
|
+
local posx=tonumber(dataset[6])
|
|
3479
|
+
local posy=tonumber(dataset[7])
|
|
3480
|
+
local posz=tonumber(dataset[8])
|
|
3481
|
+
local structure=dataset[9]
|
|
3482
|
+
local coordinate=COORDINATE:NewFromVec3({x=posx,y=posy,z=posz})
|
|
3483
|
+
if size>0 then
|
|
3484
|
+
local data={groupname=groupname,size=size,coordinate=coordinate,template=template,structure=structure,legion=legion,alttemplate=alttemplate}
|
|
3485
|
+
table.insert(datatable,data)
|
|
3486
|
+
end
|
|
3487
|
+
end
|
|
3488
|
+
else
|
|
3489
|
+
return nil
|
|
3490
|
+
end
|
|
3491
|
+
return datatable
|
|
3492
|
+
end
|
|
3493
|
+
function UTILS.ClockHeadingString(refHdg,tgtHdg)
|
|
3494
|
+
local relativeAngle=tgtHdg-refHdg
|
|
3495
|
+
if relativeAngle<0 then
|
|
3496
|
+
relativeAngle=relativeAngle+360
|
|
3497
|
+
end
|
|
3498
|
+
local clockPos=math.ceil((relativeAngle%360)/30)
|
|
3499
|
+
return clockPos.." o'clock"
|
|
3500
|
+
end
|
|
3394
3501
|
PROFILER={
|
|
3395
3502
|
ClassName="PROFILER",
|
|
3396
3503
|
Counters={},
|
|
@@ -5006,6 +5113,14 @@ end
|
|
|
5006
5113
|
_TraceClassMethod[Class].Method[Method]=true
|
|
5007
5114
|
self:I("Tracing method "..Method.." of class "..Class)
|
|
5008
5115
|
end
|
|
5116
|
+
function BASE:_Serialize(Arguments)
|
|
5117
|
+
local text=UTILS.PrintTableToLog({Arguments},0,true)
|
|
5118
|
+
text=string.gsub(text,"(\n+)","")
|
|
5119
|
+
text=string.gsub(text,"%(%(","%(")
|
|
5120
|
+
text=string.gsub(text,"%)%)","%)")
|
|
5121
|
+
text=string.gsub(text,"(%s+)"," ")
|
|
5122
|
+
return text
|
|
5123
|
+
end
|
|
5009
5124
|
function BASE:_F(Arguments,DebugInfoCurrentParam,DebugInfoFromParam)
|
|
5010
5125
|
if BASE.Debug and(_TraceAll==true)or(_TraceClass[self.ClassName]or _TraceClassMethod[self.ClassName])then
|
|
5011
5126
|
local DebugInfoCurrent=DebugInfoCurrentParam and DebugInfoCurrentParam or BASE.Debug.getinfo(2,"nl")
|
|
@@ -5023,7 +5138,7 @@ local LineFrom=0
|
|
|
5023
5138
|
if DebugInfoFrom then
|
|
5024
5139
|
LineFrom=DebugInfoFrom.currentline
|
|
5025
5140
|
end
|
|
5026
|
-
env.info(string.format("%6d(%6d)/%1s:%30s%05d.%s(%s)",LineCurrent,LineFrom,"F",self.ClassName,self.ClassID,Function,
|
|
5141
|
+
env.info(string.format("%6d(%6d)/%1s:%30s%05d.%s(%s)",LineCurrent,LineFrom,"F",self.ClassName,self.ClassID,Function,BASE:_Serialize(Arguments)))
|
|
5027
5142
|
end
|
|
5028
5143
|
end
|
|
5029
5144
|
end
|
|
@@ -5071,7 +5186,7 @@ local LineFrom=0
|
|
|
5071
5186
|
if DebugInfoFrom then
|
|
5072
5187
|
LineFrom=DebugInfoFrom.currentline
|
|
5073
5188
|
end
|
|
5074
|
-
env.info(string.format("%6d(%6d)/%1s:%30s%05d.%s",LineCurrent,LineFrom,"T",self.ClassName,self.ClassID,
|
|
5189
|
+
env.info(string.format("%6d(%6d)/%1s:%30s%05d.%s",LineCurrent,LineFrom,"T",self.ClassName,self.ClassID,BASE:_Serialize(Arguments)))
|
|
5075
5190
|
end
|
|
5076
5191
|
end
|
|
5077
5192
|
end
|
|
@@ -5117,7 +5232,7 @@ LineFrom=DebugInfoFrom.currentline
|
|
|
5117
5232
|
end
|
|
5118
5233
|
env.info(string.format("%6d(%6d)/%1s:%30s%05d.%s(%s)",LineCurrent,LineFrom,"E",self.ClassName,self.ClassID,Function,UTILS.BasicSerialize(Arguments)))
|
|
5119
5234
|
else
|
|
5120
|
-
env.info(string.format("%1s:%30s%05d(%s)","E",self.ClassName,self.ClassID,
|
|
5235
|
+
env.info(string.format("%1s:%30s%05d(%s)","E",self.ClassName,self.ClassID,BASE:_Serialize(Arguments)))
|
|
5121
5236
|
end
|
|
5122
5237
|
end
|
|
5123
5238
|
function BASE:I(Arguments)
|
|
@@ -5135,7 +5250,7 @@ LineFrom=DebugInfoFrom.currentline
|
|
|
5135
5250
|
end
|
|
5136
5251
|
env.info(string.format("%6d(%6d)/%1s:%30s%05d.%s(%s)",LineCurrent,LineFrom,"I",self.ClassName,self.ClassID,Function,UTILS.BasicSerialize(Arguments)))
|
|
5137
5252
|
else
|
|
5138
|
-
env.info(string.format("%1s:%30s%05d(%s)","I",self.ClassName,self.ClassID,
|
|
5253
|
+
env.info(string.format("%1s:%30s%05d(%s)","I",self.ClassName,self.ClassID,BASE:_Serialize(Arguments)))
|
|
5139
5254
|
end
|
|
5140
5255
|
end
|
|
5141
5256
|
ASTAR={
|
|
@@ -5503,6 +5618,7 @@ BEACON={
|
|
|
5503
5618
|
ClassName="BEACON",
|
|
5504
5619
|
Positionable=nil,
|
|
5505
5620
|
name=nil,
|
|
5621
|
+
UniqueName=0,
|
|
5506
5622
|
}
|
|
5507
5623
|
BEACON.Type={
|
|
5508
5624
|
NULL=0,
|
|
@@ -5607,6 +5723,7 @@ return self
|
|
|
5607
5723
|
end
|
|
5608
5724
|
function BEACON:AATACAN(TACANChannel,Message,Bearing,BeaconDuration)
|
|
5609
5725
|
self:F({TACANChannel,Message,Bearing,BeaconDuration})
|
|
5726
|
+
self:E("This method is DEPRECATED! Please use ActivateTACAN() instead.")
|
|
5610
5727
|
local IsValid=true
|
|
5611
5728
|
if not self.Positionable:IsAir()then
|
|
5612
5729
|
self:E({"The POSITIONABLE you want to attach the AA Tacan Beacon is not an aircraft ! The BEACON is not emitting",self.Positionable})
|
|
@@ -5661,6 +5778,7 @@ end
|
|
|
5661
5778
|
function BEACON:RadioBeacon(FileName,Frequency,Modulation,Power,BeaconDuration)
|
|
5662
5779
|
self:F({FileName,Frequency,Modulation,Power,BeaconDuration})
|
|
5663
5780
|
local IsValid=false
|
|
5781
|
+
Modulation=Modulation or radio.modulation.AM
|
|
5664
5782
|
if type(FileName)=="string"then
|
|
5665
5783
|
if FileName:find(".ogg")or FileName:find(".wav")then
|
|
5666
5784
|
if not FileName:find("l10n/DEFAULT/")then
|
|
@@ -5670,7 +5788,7 @@ IsValid=true
|
|
|
5670
5788
|
end
|
|
5671
5789
|
end
|
|
5672
5790
|
if not IsValid then
|
|
5673
|
-
self:E({"File name invalid. Maybe something wrong with the extension
|
|
5791
|
+
self:E({"File name invalid. Maybe something wrong with the extension? ",FileName})
|
|
5674
5792
|
end
|
|
5675
5793
|
if type(Frequency)~="number"and IsValid then
|
|
5676
5794
|
self:E({"Frequency invalid. ",Frequency})
|
|
@@ -5688,7 +5806,9 @@ end
|
|
|
5688
5806
|
Power=math.floor(math.abs(Power))
|
|
5689
5807
|
if IsValid then
|
|
5690
5808
|
self:T2({"Activating Beacon on ",Frequency,Modulation})
|
|
5691
|
-
|
|
5809
|
+
BEACON.UniqueName=BEACON.UniqueName+1
|
|
5810
|
+
self.BeaconName="MooseBeacon"..tostring(BEACON.UniqueName)
|
|
5811
|
+
trigger.action.radioTransmission(FileName,self.Positionable:GetPositionVec3(),Modulation,true,Frequency,Power,self.BeaconName)
|
|
5692
5812
|
if BeaconDuration then
|
|
5693
5813
|
SCHEDULER:New(nil,
|
|
5694
5814
|
function()
|
|
@@ -5696,10 +5816,11 @@ self:StopRadioBeacon()
|
|
|
5696
5816
|
end,{},BeaconDuration)
|
|
5697
5817
|
end
|
|
5698
5818
|
end
|
|
5819
|
+
return self
|
|
5699
5820
|
end
|
|
5700
5821
|
function BEACON:StopRadioBeacon()
|
|
5701
5822
|
self:F()
|
|
5702
|
-
trigger.action.stopRadioTransmission(
|
|
5823
|
+
trigger.action.stopRadioTransmission(self.BeaconName)
|
|
5703
5824
|
return self
|
|
5704
5825
|
end
|
|
5705
5826
|
function BEACON:_TACANToFrequency(TACANChannel,TACANMode)
|
|
@@ -7038,6 +7159,7 @@ Event.MarkVec3=Event.pos
|
|
|
7038
7159
|
Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos)
|
|
7039
7160
|
Event.MarkText=Event.text
|
|
7040
7161
|
Event.MarkCoalition=Event.coalition
|
|
7162
|
+
Event.IniCoalition=Event.coalition
|
|
7041
7163
|
Event.MarkGroupID=Event.groupID
|
|
7042
7164
|
end
|
|
7043
7165
|
if Event.cargo then
|
|
@@ -8726,6 +8848,7 @@ end
|
|
|
8726
8848
|
function ZONE_RADIUS:BoundZone(Points,CountryID,UnBound)
|
|
8727
8849
|
local Point={}
|
|
8728
8850
|
local Vec2=self:GetVec2()
|
|
8851
|
+
local countryID=CountryID or country.id.USA
|
|
8729
8852
|
Points=Points and Points or 360
|
|
8730
8853
|
local Angle
|
|
8731
8854
|
local RadialBase=math.pi*2
|
|
@@ -8733,7 +8856,7 @@ for Angle=0,360,(360/Points)do
|
|
|
8733
8856
|
local Radial=Angle*RadialBase/360
|
|
8734
8857
|
Point.x=Vec2.x+math.cos(Radial)*self:GetRadius()
|
|
8735
8858
|
Point.y=Vec2.y+math.sin(Radial)*self:GetRadius()
|
|
8736
|
-
local CountryName=_DATABASE.COUNTRY_NAME[
|
|
8859
|
+
local CountryName=_DATABASE.COUNTRY_NAME[countryID]
|
|
8737
8860
|
local Tire={
|
|
8738
8861
|
["country"]=CountryName,
|
|
8739
8862
|
["category"]="Fortifications",
|
|
@@ -8745,7 +8868,7 @@ local Tire={
|
|
|
8745
8868
|
["name"]=string.format("%s-Tire #%0d",self:GetName(),Angle),
|
|
8746
8869
|
["heading"]=0,
|
|
8747
8870
|
}
|
|
8748
|
-
local Group=coalition.addStaticObject(
|
|
8871
|
+
local Group=coalition.addStaticObject(countryID,Tire)
|
|
8749
8872
|
if UnBound and UnBound==true then
|
|
8750
8873
|
Group:destroy()
|
|
8751
8874
|
end
|
|
@@ -10263,7 +10386,7 @@ function ZONE_OVAL:GetRandomPointVec2()
|
|
|
10263
10386
|
return POINT_VEC2:NewFromVec2(self:GetRandomVec2())
|
|
10264
10387
|
end
|
|
10265
10388
|
function ZONE_OVAL:GetRandomPointVec3()
|
|
10266
|
-
return
|
|
10389
|
+
return POINT_VEC3:NewFromVec3(self:GetRandomVec2())
|
|
10267
10390
|
end
|
|
10268
10391
|
function ZONE_OVAL:DrawZone(Coalition,Color,Alpha,FillColor,FillAlpha,LineType)
|
|
10269
10392
|
Coalition=Coalition or self:GetDrawCoalition()
|
|
@@ -10472,6 +10595,8 @@ FLIGHTCONTROLS={},
|
|
|
10472
10595
|
OPSZONES={},
|
|
10473
10596
|
PATHLINES={},
|
|
10474
10597
|
STORAGES={},
|
|
10598
|
+
STNS={},
|
|
10599
|
+
SADL={},
|
|
10475
10600
|
}
|
|
10476
10601
|
local _DATABASECoalition=
|
|
10477
10602
|
{
|
|
@@ -10853,7 +10978,7 @@ local SpawnCategoryID=SpawnTemplate.CategoryID
|
|
|
10853
10978
|
SpawnTemplate.CoalitionID=nil
|
|
10854
10979
|
SpawnTemplate.CountryID=nil
|
|
10855
10980
|
SpawnTemplate.CategoryID=nil
|
|
10856
|
-
self:_RegisterGroupTemplate(SpawnTemplate,SpawnCoalitionID,SpawnCategoryID,SpawnCountryID)
|
|
10981
|
+
self:_RegisterGroupTemplate(SpawnTemplate,SpawnCoalitionID,SpawnCategoryID,SpawnCountryID,SpawnTemplate.name)
|
|
10857
10982
|
self:T3(SpawnTemplate)
|
|
10858
10983
|
coalition.addGroup(SpawnCountryID,SpawnCategoryID,SpawnTemplate)
|
|
10859
10984
|
SpawnTemplate.CoalitionID=SpawnCoalitionID
|
|
@@ -10916,6 +11041,26 @@ self.Templates.ClientsByName[UnitTemplate.name].CoalitionID=CoalitionSide
|
|
|
10916
11041
|
self.Templates.ClientsByName[UnitTemplate.name].CountryID=CountryID
|
|
10917
11042
|
self.Templates.ClientsByID[UnitTemplate.unitId]=UnitTemplate
|
|
10918
11043
|
end
|
|
11044
|
+
if UnitTemplate.AddPropAircraft then
|
|
11045
|
+
if UnitTemplate.AddPropAircraft.STN_L16 then
|
|
11046
|
+
local stn=UTILS.OctalToDecimal(UnitTemplate.AddPropAircraft.STN_L16)
|
|
11047
|
+
if stn==nil or stn<1 then
|
|
11048
|
+
self:E("WARNING: Invalid STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for "..UnitTemplate.name)
|
|
11049
|
+
else
|
|
11050
|
+
self.STNS[stn]=UnitTemplate.name
|
|
11051
|
+
self:I("Register STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for "..UnitTemplate.name)
|
|
11052
|
+
end
|
|
11053
|
+
end
|
|
11054
|
+
if UnitTemplate.AddPropAircraft.SADL_TN then
|
|
11055
|
+
local sadl=UTILS.OctalToDecimal(UnitTemplate.AddPropAircraft.SADL_TN)
|
|
11056
|
+
if sadl==nil or sadl<1 then
|
|
11057
|
+
self:E("WARNING: Invalid SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for "..UnitTemplate.name)
|
|
11058
|
+
else
|
|
11059
|
+
self.SADL[sadl]=UnitTemplate.name
|
|
11060
|
+
self:I("Register SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for "..UnitTemplate.name)
|
|
11061
|
+
end
|
|
11062
|
+
end
|
|
11063
|
+
end
|
|
10919
11064
|
UnitNames[#UnitNames+1]=self.Templates.Units[UnitTemplate.name].UnitName
|
|
10920
11065
|
end
|
|
10921
11066
|
self:T({Group=self.Templates.Groups[GroupTemplateName].GroupName,
|
|
@@ -10926,6 +11071,66 @@ Units=UnitNames
|
|
|
10926
11071
|
}
|
|
10927
11072
|
)
|
|
10928
11073
|
end
|
|
11074
|
+
function DATABASE:GetNextSTN(octal,unitname)
|
|
11075
|
+
local first=UTILS.OctalToDecimal(octal)or 0
|
|
11076
|
+
if self.STNS[first]==unitname then return octal end
|
|
11077
|
+
local nextoctal=77777
|
|
11078
|
+
local found=false
|
|
11079
|
+
if 32767-first<10 then
|
|
11080
|
+
first=0
|
|
11081
|
+
end
|
|
11082
|
+
for i=first+1,32767 do
|
|
11083
|
+
if self.STNS[i]==nil then
|
|
11084
|
+
found=true
|
|
11085
|
+
nextoctal=UTILS.DecimalToOctal(i)
|
|
11086
|
+
self.STNS[i]=unitname
|
|
11087
|
+
self:T("Register STN "..tostring(nextoctal).." for "..unitname)
|
|
11088
|
+
break
|
|
11089
|
+
end
|
|
11090
|
+
end
|
|
11091
|
+
if not found then
|
|
11092
|
+
self:E(string.format("WARNING: No next free STN past %05d found!",octal))
|
|
11093
|
+
local NewSTNS={}
|
|
11094
|
+
for _id,_name in pairs(self.STNS)do
|
|
11095
|
+
if self.UNITS[_name]~=nil then
|
|
11096
|
+
NewSTNS[_id]=_name
|
|
11097
|
+
end
|
|
11098
|
+
end
|
|
11099
|
+
self.STNS=nil
|
|
11100
|
+
self.STNS=NewSTNS
|
|
11101
|
+
end
|
|
11102
|
+
return nextoctal
|
|
11103
|
+
end
|
|
11104
|
+
function DATABASE:GetNextSADL(octal,unitname)
|
|
11105
|
+
local first=UTILS.OctalToDecimal(octal)or 0
|
|
11106
|
+
if self.SADL[first]==unitname then return octal end
|
|
11107
|
+
local nextoctal=7777
|
|
11108
|
+
local found=false
|
|
11109
|
+
if 4095-first<10 then
|
|
11110
|
+
first=0
|
|
11111
|
+
end
|
|
11112
|
+
for i=first+1,4095 do
|
|
11113
|
+
if self.STNS[i]==nil then
|
|
11114
|
+
found=true
|
|
11115
|
+
nextoctal=UTILS.DecimalToOctal(i)
|
|
11116
|
+
self.SADL[i]=unitname
|
|
11117
|
+
self:T("Register SADL "..tostring(nextoctal).." for "..unitname)
|
|
11118
|
+
break
|
|
11119
|
+
end
|
|
11120
|
+
end
|
|
11121
|
+
if not found then
|
|
11122
|
+
self:E(string.format("WARNING: No next free SADL past %04d found!",octal))
|
|
11123
|
+
local NewSTNS={}
|
|
11124
|
+
for _id,_name in pairs(self.SADL)do
|
|
11125
|
+
if self.UNITS[_name]~=nil then
|
|
11126
|
+
NewSTNS[_id]=_name
|
|
11127
|
+
end
|
|
11128
|
+
end
|
|
11129
|
+
self.SADL=nil
|
|
11130
|
+
self.SADL=NewSTNS
|
|
11131
|
+
end
|
|
11132
|
+
return nextoctal
|
|
11133
|
+
end
|
|
10929
11134
|
function DATABASE:GetGroupTemplate(GroupName)
|
|
10930
11135
|
local GroupTemplate=self.Templates.Groups[GroupName].Template
|
|
10931
11136
|
GroupTemplate.SpawnCoalitionID=self.Templates.Groups[GroupName].CoalitionID
|
|
@@ -11208,7 +11413,7 @@ return playername
|
|
|
11208
11413
|
end
|
|
11209
11414
|
if Event.IniUnit then
|
|
11210
11415
|
if Event.IniObjectCategory==1 then
|
|
11211
|
-
local PlayerName=Event.IniUnit:GetPlayerName()or FindPlayerName(Event.IniUnitName)
|
|
11416
|
+
local PlayerName=Event.IniPlayerName or Event.IniUnit:GetPlayerName()or FindPlayerName(Event.IniUnitName)
|
|
11212
11417
|
if PlayerName then
|
|
11213
11418
|
self:I(string.format("Player '%s' left unit %s",tostring(PlayerName),tostring(Event.IniUnitName)))
|
|
11214
11419
|
local Settings=SETTINGS:Set(PlayerName)
|
|
@@ -11896,6 +12101,7 @@ Countries=nil,
|
|
|
11896
12101
|
GroupPrefixes=nil,
|
|
11897
12102
|
Zones=nil,
|
|
11898
12103
|
Functions=nil,
|
|
12104
|
+
Alive=nil,
|
|
11899
12105
|
},
|
|
11900
12106
|
FilterMeta={
|
|
11901
12107
|
Coalitions={
|
|
@@ -12102,6 +12308,10 @@ Active=Active or not(Active==false)
|
|
|
12102
12308
|
self.Filter.Active=Active
|
|
12103
12309
|
return self
|
|
12104
12310
|
end
|
|
12311
|
+
function SET_GROUP:FilterAlive()
|
|
12312
|
+
self.Filter.Alive=true
|
|
12313
|
+
return self
|
|
12314
|
+
end
|
|
12105
12315
|
function SET_GROUP:FilterStart()
|
|
12106
12316
|
if _DATABASE then
|
|
12107
12317
|
self:_FilterStart()
|
|
@@ -12337,6 +12547,14 @@ end
|
|
|
12337
12547
|
function SET_GROUP:IsIncludeObject(MGroup)
|
|
12338
12548
|
self:F2(MGroup)
|
|
12339
12549
|
local MGroupInclude=true
|
|
12550
|
+
if self.Filter.Alive==true then
|
|
12551
|
+
local MGroupAlive=false
|
|
12552
|
+
self:F({Active=self.Filter.Active})
|
|
12553
|
+
if MGroup and MGroup:IsAlive()then
|
|
12554
|
+
MGroupAlive=true
|
|
12555
|
+
end
|
|
12556
|
+
MGroupInclude=MGroupInclude and MGroupAlive
|
|
12557
|
+
end
|
|
12340
12558
|
if self.Filter.Active~=nil then
|
|
12341
12559
|
local MGroupActive=false
|
|
12342
12560
|
self:F({Active=self.Filter.Active})
|
|
@@ -12861,7 +13079,7 @@ local heading=self:GetHeading()or 0
|
|
|
12861
13079
|
local velocity=self:GetVelocity()or 0
|
|
12862
13080
|
Coordinate:SetHeading(heading)
|
|
12863
13081
|
Coordinate:SetVelocity(velocity)
|
|
12864
|
-
self:
|
|
13082
|
+
self:T(UTILS.PrintTableToLog(Coordinate))
|
|
12865
13083
|
end
|
|
12866
13084
|
return Coordinate
|
|
12867
13085
|
end
|
|
@@ -13728,7 +13946,7 @@ self:I("_EventPlayerEnterUnit")
|
|
|
13728
13946
|
if Event.IniDCSUnit then
|
|
13729
13947
|
if Event.IniObjectCategory==Object.Category.UNIT and Event.IniGroup and Event.IniGroup:IsGround()then
|
|
13730
13948
|
local ObjectName,Object=self:AddInDatabase(Event)
|
|
13731
|
-
self:
|
|
13949
|
+
self:T(ObjectName,UTILS.PrintTableToLog(Object))
|
|
13732
13950
|
if Object and self:IsIncludeObject(Object)then
|
|
13733
13951
|
self:Add(ObjectName,Object)
|
|
13734
13952
|
end
|
|
@@ -15951,6 +16169,7 @@ return umin
|
|
|
15951
16169
|
end
|
|
15952
16170
|
function COORDINATE:DistanceFromPointVec2(PointVec2Reference)
|
|
15953
16171
|
self:F2(PointVec2Reference)
|
|
16172
|
+
if not PointVec2Reference then return math.huge end
|
|
15954
16173
|
local Distance=((PointVec2Reference.x-self.x)^2+(PointVec2Reference.z-self.z)^2)^0.5
|
|
15955
16174
|
self:T2(Distance)
|
|
15956
16175
|
return Distance
|
|
@@ -17154,17 +17373,18 @@ local coord=COORDINATE:NewFromVec2({x=point.x,y=point.z})
|
|
|
17154
17373
|
return coord
|
|
17155
17374
|
end
|
|
17156
17375
|
function COORDINATE:NewFromMGRS(UTMZone,MGRSDigraph,Easting,Northing)
|
|
17157
|
-
if string.len(Easting)<5 then Easting=Easting..string.rep("0",5-string.len(Easting))end
|
|
17158
|
-
if string.len(Northing)<5 then Northing=Northing..string.rep("0",5-string.len(Northing))end
|
|
17376
|
+
if string.len(Easting)<5 then Easting=tostring(Easting..string.rep("0",5-string.len(Easting)))end
|
|
17377
|
+
if string.len(Northing)<5 then Northing=tostring(Northing..string.rep("0",5-string.len(Northing)))end
|
|
17159
17378
|
local MGRS={
|
|
17160
17379
|
UTMZone=UTMZone,
|
|
17161
17380
|
MGRSDigraph=MGRSDigraph,
|
|
17162
|
-
Easting=Easting,
|
|
17163
|
-
Northing=Northing,
|
|
17381
|
+
Easting=tostring(Easting),
|
|
17382
|
+
Northing=tostring(Northing),
|
|
17164
17383
|
}
|
|
17165
17384
|
local lat,lon=coord.MGRStoLL(MGRS)
|
|
17166
17385
|
local point=coord.LLtoLO(lat,lon,0)
|
|
17167
17386
|
local coord=COORDINATE:NewFromVec2({x=point.x,y=point.z})
|
|
17387
|
+
return coord
|
|
17168
17388
|
end
|
|
17169
17389
|
function COORDINATE:ToStringFromRP(ReferenceCoord,ReferenceName,Controllable,Settings,MagVar)
|
|
17170
17390
|
self:F2({ReferenceCoord=ReferenceCoord,ReferenceName=ReferenceName})
|
|
@@ -18408,7 +18628,7 @@ BASE:I("ERROR: in function NewFromTemplate, required parameter SpawnTemplatePref
|
|
|
18408
18628
|
return nil
|
|
18409
18629
|
end
|
|
18410
18630
|
if SpawnTemplate then
|
|
18411
|
-
self.SpawnTemplate=SpawnTemplate
|
|
18631
|
+
self.SpawnTemplate=UTILS.DeepCopy(SpawnTemplate)
|
|
18412
18632
|
self.SpawnTemplatePrefix=SpawnTemplatePrefix
|
|
18413
18633
|
self.SpawnAliasPrefix=SpawnAliasPrefix or SpawnTemplatePrefix
|
|
18414
18634
|
self.SpawnTemplate.name=SpawnTemplatePrefix
|
|
@@ -18525,6 +18745,56 @@ self.SpawnInitSkill="High"
|
|
|
18525
18745
|
end
|
|
18526
18746
|
return self
|
|
18527
18747
|
end
|
|
18748
|
+
function SPAWN:InitSTN(Octal)
|
|
18749
|
+
self:F({Octal=Octal})
|
|
18750
|
+
self.SpawnInitSTN=Octal or 77777
|
|
18751
|
+
local num=UTILS.OctalToDecimal(Octal)
|
|
18752
|
+
if num==nil or num<1 then
|
|
18753
|
+
self:E("WARNING - STN "..tostring(Octal).." is not valid!")
|
|
18754
|
+
return self
|
|
18755
|
+
end
|
|
18756
|
+
if _DATABASE.STNS[num]~=nil then
|
|
18757
|
+
self:E("WARNING - STN already assigned: "..tostring(Octal).." is used for ".._DATABASE.STNS[Octal])
|
|
18758
|
+
end
|
|
18759
|
+
return self
|
|
18760
|
+
end
|
|
18761
|
+
function SPAWN:InitSADL(Octal)
|
|
18762
|
+
self:F({Octal=Octal})
|
|
18763
|
+
self.SpawnInitSADL=Octal or 7777
|
|
18764
|
+
local num=UTILS.OctalToDecimal(Octal)
|
|
18765
|
+
if num==nil or num<1 then
|
|
18766
|
+
self:E("WARNING - SADL "..tostring(Octal).." is not valid!")
|
|
18767
|
+
return self
|
|
18768
|
+
end
|
|
18769
|
+
if _DATABASE.SADL[num]~=nil then
|
|
18770
|
+
self:E("WARNING - SADL already assigned: "..tostring(Octal).." is used for ".._DATABASE.SADL[Octal])
|
|
18771
|
+
end
|
|
18772
|
+
return self
|
|
18773
|
+
end
|
|
18774
|
+
function SPAWN:InitSpeedMps(MPS)
|
|
18775
|
+
self:F({MPS=MPS})
|
|
18776
|
+
if MPS==nil or tonumber(MPS)<0 then
|
|
18777
|
+
MPS=125
|
|
18778
|
+
end
|
|
18779
|
+
self.InitSpeed=MPS
|
|
18780
|
+
return self
|
|
18781
|
+
end
|
|
18782
|
+
function SPAWN:InitSpeedKnots(Knots)
|
|
18783
|
+
self:F({Knots=Knots})
|
|
18784
|
+
if Knots==nil or tonumber(Knots)<0 then
|
|
18785
|
+
Knots=300
|
|
18786
|
+
end
|
|
18787
|
+
self.InitSpeed=UTILS.KnotsToMps(Knots)
|
|
18788
|
+
return self
|
|
18789
|
+
end
|
|
18790
|
+
function SPAWN:InitSpeedKph(KPH)
|
|
18791
|
+
self:F({KPH=KPH})
|
|
18792
|
+
if KPH==nil or tonumber(KPH)<0 then
|
|
18793
|
+
KPH=UTILS.KnotsToKmph(300)
|
|
18794
|
+
end
|
|
18795
|
+
self.InitSpeed=UTILS.KmphToMps(KPH)
|
|
18796
|
+
return self
|
|
18797
|
+
end
|
|
18528
18798
|
function SPAWN:InitRadioCommsOnOff(switch)
|
|
18529
18799
|
self:F({switch=switch})
|
|
18530
18800
|
self.SpawnInitRadio=switch or true
|
|
@@ -18761,6 +19031,18 @@ function SPAWN:InitDelayOff()
|
|
|
18761
19031
|
return self:InitDelayOnOff(false)
|
|
18762
19032
|
end
|
|
18763
19033
|
end
|
|
19034
|
+
function SPAWN:InitHiddenOnMap()
|
|
19035
|
+
self.SpawnHiddenOnMap=true
|
|
19036
|
+
return self
|
|
19037
|
+
end
|
|
19038
|
+
function SPAWN:InitHiddenOnMFD()
|
|
19039
|
+
self.SpawnHiddenOnMFD=true
|
|
19040
|
+
return self
|
|
19041
|
+
end
|
|
19042
|
+
function SPAWN:InitHiddenOnPlanner()
|
|
19043
|
+
self.SpawnHiddenOnPlanner=true
|
|
19044
|
+
return self
|
|
19045
|
+
end
|
|
18764
19046
|
function SPAWN:Spawn()
|
|
18765
19047
|
self:F({self.SpawnTemplatePrefix,self.SpawnIndex,self.AliveUnits})
|
|
18766
19048
|
if self.SpawnInitAirbase then
|
|
@@ -18953,6 +19235,15 @@ end
|
|
|
18953
19235
|
if self.SpawnInitModu then
|
|
18954
19236
|
SpawnTemplate.modulation=self.SpawnInitModu
|
|
18955
19237
|
end
|
|
19238
|
+
if self.SpawnHiddenOnPlanner then
|
|
19239
|
+
SpawnTemplate.hiddenOnPlanner=true
|
|
19240
|
+
end
|
|
19241
|
+
if self.SpawnHiddenOnMFD then
|
|
19242
|
+
SpawnTemplate.hiddenOnMFD=true
|
|
19243
|
+
end
|
|
19244
|
+
if self.SpawnHiddenOnMap then
|
|
19245
|
+
SpawnTemplate.hidden=true
|
|
19246
|
+
end
|
|
18956
19247
|
SpawnTemplate.CategoryID=self.SpawnInitCategory or SpawnTemplate.CategoryID
|
|
18957
19248
|
SpawnTemplate.CountryID=self.SpawnInitCountry or SpawnTemplate.CountryID
|
|
18958
19249
|
SpawnTemplate.CoalitionID=self.SpawnInitCoalition or SpawnTemplate.CoalitionID
|
|
@@ -18981,6 +19272,7 @@ self.SpawnHookScheduler:Schedule(nil,self.SpawnFunctionHook,{self.SpawnGroups[se
|
|
|
18981
19272
|
end
|
|
18982
19273
|
end
|
|
18983
19274
|
self.SpawnGroups[self.SpawnIndex].Spawned=true
|
|
19275
|
+
self.SpawnGroups[self.SpawnIndex].Group.TemplateDonor=self.SpawnTemplatePrefix
|
|
18984
19276
|
return self.SpawnGroups[self.SpawnIndex].Group
|
|
18985
19277
|
else
|
|
18986
19278
|
end
|
|
@@ -19786,8 +20078,17 @@ SpawnTemplate.units[UnitID].unitId=nil
|
|
|
19786
20078
|
end
|
|
19787
20079
|
else
|
|
19788
20080
|
for UnitID=1,#SpawnTemplate.units do
|
|
19789
|
-
local
|
|
20081
|
+
local SpawnInitKeepUnitIFF=false
|
|
20082
|
+
if string.find(SpawnTemplate.units[UnitID].name,"#IFF_",1,true)then
|
|
20083
|
+
SpawnInitKeepUnitIFF=true
|
|
20084
|
+
end
|
|
20085
|
+
local UnitPrefix,Rest
|
|
20086
|
+
if SpawnInitKeepUnitIFF==false then
|
|
20087
|
+
UnitPrefix,Rest=string.match(SpawnTemplate.units[UnitID].name,"^([^#]+)#?"):gsub("^%s*(.-)%s*$","%1")
|
|
19790
20088
|
self:T({UnitPrefix,Rest})
|
|
20089
|
+
else
|
|
20090
|
+
UnitPrefix=SpawnTemplate.units[UnitID].name
|
|
20091
|
+
end
|
|
19791
20092
|
SpawnTemplate.units[UnitID].name=string.format('%s#%03d-%02d',UnitPrefix,SpawnIndex,UnitID)
|
|
19792
20093
|
SpawnTemplate.units[UnitID].unitId=nil
|
|
19793
20094
|
end
|
|
@@ -19859,32 +20160,54 @@ elseif type(Callsign)=="number"then
|
|
|
19859
20160
|
SpawnTemplate.units[UnitID].callsign=Callsign+SpawnIndex
|
|
19860
20161
|
end
|
|
19861
20162
|
end
|
|
20163
|
+
if self.InitSpeed then
|
|
20164
|
+
SpawnTemplate.units[UnitID].speed=self.InitSpeed
|
|
20165
|
+
end
|
|
19862
20166
|
local AddProps=SpawnTemplate.units[UnitID].AddPropAircraft
|
|
19863
20167
|
if AddProps then
|
|
19864
20168
|
if SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 then
|
|
20169
|
+
if self.SpawnInitSTN then
|
|
20170
|
+
local octal=self.SpawnInitSTN
|
|
20171
|
+
if UnitID>1 then
|
|
20172
|
+
octal=_DATABASE:GetNextSTN(self.SpawnInitSTN,SpawnTemplate.units[UnitID].name)
|
|
20173
|
+
end
|
|
20174
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16=string.format("%05d",octal)
|
|
20175
|
+
else
|
|
19865
20176
|
if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16)~=nil then
|
|
19866
20177
|
local octal=SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16
|
|
19867
|
-
local
|
|
19868
|
-
|
|
20178
|
+
local num=UTILS.OctalToDecimal(octal)
|
|
20179
|
+
if _DATABASE.STNS[num]~=nil or UnitID>1 then
|
|
20180
|
+
octal=_DATABASE:GetNextSTN(octal,SpawnTemplate.units[UnitID].name)
|
|
20181
|
+
end
|
|
20182
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16=string.format("%05d",octal)
|
|
19869
20183
|
else
|
|
19870
|
-
local
|
|
19871
|
-
STN=STN+UnitID-1
|
|
19872
|
-
local OSTN=UTILS.DecimalToOctal(STN)
|
|
20184
|
+
local OSTN=_DATABASE:GetNextSTN(1,SpawnTemplate.units[UnitID].name)
|
|
19873
20185
|
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16=string.format("%05d",OSTN)
|
|
19874
20186
|
end
|
|
19875
20187
|
end
|
|
20188
|
+
end
|
|
19876
20189
|
if SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN then
|
|
20190
|
+
if self.SpawnInitSADL then
|
|
20191
|
+
local octal=self.SpawnInitSADL
|
|
20192
|
+
if UnitID>1 then
|
|
20193
|
+
octal=_DATABASE:GetNextSADL(self.SpawnInitSADL,SpawnTemplate.units[UnitID].name)
|
|
20194
|
+
end
|
|
20195
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN=string.format("%04d",octal)
|
|
20196
|
+
else
|
|
19877
20197
|
if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN)~=nil then
|
|
19878
20198
|
local octal=SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN
|
|
19879
|
-
local
|
|
19880
|
-
|
|
20199
|
+
local num=UTILS.OctalToDecimal(octal)
|
|
20200
|
+
self.SpawnInitSADL=num
|
|
20201
|
+
if _DATABASE.SADL[num]~=nil or UnitID>1 then
|
|
20202
|
+
octal=_DATABASE:GetNextSADL(self.SpawnInitSADL,SpawnTemplate.units[UnitID].name)
|
|
20203
|
+
end
|
|
20204
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN=string.format("%04d",octal)
|
|
19881
20205
|
else
|
|
19882
|
-
local
|
|
19883
|
-
STN=STN+UnitID-1
|
|
19884
|
-
local OSTN=UTILS.DecimalToOctal(STN)
|
|
20206
|
+
local OSTN=_DATABASE:GetNextSADL(1,SpawnTemplate.units[UnitID].name)
|
|
19885
20207
|
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN=string.format("%04d",OSTN)
|
|
19886
20208
|
end
|
|
19887
20209
|
end
|
|
20210
|
+
end
|
|
19888
20211
|
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber and type(Callsign)~="number"then
|
|
19889
20212
|
SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber=SpawnTemplate.units[UnitID].callsign[2]..SpawnTemplate.units[UnitID].callsign[3]
|
|
19890
20213
|
end
|
|
@@ -20648,7 +20971,7 @@ MARKEROPS_BASE={
|
|
|
20648
20971
|
ClassName="MARKEROPS",
|
|
20649
20972
|
Tag="mytag",
|
|
20650
20973
|
Keywords={},
|
|
20651
|
-
version="0.1.
|
|
20974
|
+
version="0.1.3",
|
|
20652
20975
|
debug=false,
|
|
20653
20976
|
Casesensitive=true,
|
|
20654
20977
|
}
|
|
@@ -20688,26 +21011,27 @@ local coordtext=coord:ToStringLLDDM()
|
|
|
20688
21011
|
local text=tostring(Event.text)
|
|
20689
21012
|
local m=MESSAGE:New(string.format("Mark added at %s with text: %s",coordtext,text),10,"Info",false):ToAll()
|
|
20690
21013
|
end
|
|
21014
|
+
local coalition=Event.MarkCoalition
|
|
20691
21015
|
if Event.id==world.event.S_EVENT_MARK_ADDED then
|
|
20692
|
-
self:T({event="S_EVENT_MARK_ADDED",carrier=
|
|
21016
|
+
self:T({event="S_EVENT_MARK_ADDED",carrier=Event.IniGroupName,vec3=Event.pos})
|
|
20693
21017
|
local Eventtext=tostring(Event.text)
|
|
20694
21018
|
if Eventtext~=nil then
|
|
20695
21019
|
if self:_MatchTag(Eventtext)then
|
|
20696
21020
|
local matchtable=self:_MatchKeywords(Eventtext)
|
|
20697
|
-
self:MarkAdded(Eventtext,matchtable,coord)
|
|
21021
|
+
self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition)
|
|
20698
21022
|
end
|
|
20699
21023
|
end
|
|
20700
21024
|
elseif Event.id==world.event.S_EVENT_MARK_CHANGE then
|
|
20701
|
-
self:T({event="S_EVENT_MARK_CHANGE",carrier=
|
|
21025
|
+
self:T({event="S_EVENT_MARK_CHANGE",carrier=Event.IniGroupName,vec3=Event.pos})
|
|
20702
21026
|
local Eventtext=tostring(Event.text)
|
|
20703
21027
|
if Eventtext~=nil then
|
|
20704
21028
|
if self:_MatchTag(Eventtext)then
|
|
20705
21029
|
local matchtable=self:_MatchKeywords(Eventtext)
|
|
20706
|
-
self:MarkChanged(Eventtext,matchtable,coord,Event.idx)
|
|
21030
|
+
self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition)
|
|
20707
21031
|
end
|
|
20708
21032
|
end
|
|
20709
21033
|
elseif Event.id==world.event.S_EVENT_MARK_REMOVED then
|
|
20710
|
-
self:T({event="S_EVENT_MARK_REMOVED",carrier=
|
|
21034
|
+
self:T({event="S_EVENT_MARK_REMOVED",carrier=Event.IniGroupName,vec3=Event.pos})
|
|
20711
21035
|
local Eventtext=tostring(Event.text)
|
|
20712
21036
|
if Eventtext~=nil then
|
|
20713
21037
|
if self:_MatchTag(Eventtext)then
|
|
@@ -20741,10 +21065,10 @@ end
|
|
|
20741
21065
|
end
|
|
20742
21066
|
return matchtable
|
|
20743
21067
|
end
|
|
20744
|
-
function MARKEROPS_BASE:onbeforeMarkAdded(From,Event,To,Text,Keywords,Coord)
|
|
21068
|
+
function MARKEROPS_BASE:onbeforeMarkAdded(From,Event,To,Text,Keywords,Coord,MarkerID,CoalitionNumber)
|
|
20745
21069
|
self:T({self.lid,From,Event,To,Text,Keywords,Coord:ToStringLLDDM()})
|
|
20746
21070
|
end
|
|
20747
|
-
function MARKEROPS_BASE:onbeforeMarkChanged(From,Event,To,Text,Keywords,Coord)
|
|
21071
|
+
function MARKEROPS_BASE:onbeforeMarkChanged(From,Event,To,Text,Keywords,Coord,MarkerID,CoalitionNumber)
|
|
20748
21072
|
self:T({self.lid,From,Event,To,Text,Keywords,Coord:ToStringLLDDM()})
|
|
20749
21073
|
end
|
|
20750
21074
|
function MARKEROPS_BASE:onbeforeMarkDeleted(From,Event,To)
|
|
@@ -23225,7 +23549,7 @@ local TaskRoute=PatrolGroup:TaskFunction("CONTROLLABLE.PatrolRoute")
|
|
|
23225
23549
|
self:F({Waypoints=Waypoints})
|
|
23226
23550
|
local Waypoint=Waypoints[#Waypoints]
|
|
23227
23551
|
PatrolGroup:SetTaskWaypoint(Waypoint,TaskRoute)
|
|
23228
|
-
PatrolGroup:Route(Waypoints)
|
|
23552
|
+
PatrolGroup:Route(Waypoints,2)
|
|
23229
23553
|
end
|
|
23230
23554
|
end
|
|
23231
23555
|
function CONTROLLABLE:PatrolRouteRandom(Speed,Formation,ToWaypoint)
|
|
@@ -24183,6 +24507,9 @@ return nil
|
|
|
24183
24507
|
end
|
|
24184
24508
|
function CONTROLLABLE:WayPointFunction(WayPoint,WayPointIndex,WayPointFunction,...)
|
|
24185
24509
|
self:F2({WayPoint,WayPointIndex,WayPointFunction})
|
|
24510
|
+
if not self.WayPoints then
|
|
24511
|
+
self:WayPointInitialize()
|
|
24512
|
+
end
|
|
24186
24513
|
table.insert(self.WayPoints[WayPoint].task.params.tasks,WayPointIndex)
|
|
24187
24514
|
self.WayPoints[WayPoint].task.params.tasks[WayPointIndex]=self:TaskFunction(WayPointFunction,arg)
|
|
24188
24515
|
return self
|
|
@@ -24306,6 +24633,49 @@ self:SetOption(AI.Option.Air.id.RADAR_USING,3)
|
|
|
24306
24633
|
end
|
|
24307
24634
|
return self
|
|
24308
24635
|
end
|
|
24636
|
+
function CONTROLLABLE:SetOptionWaypointPassReport(OnOff)
|
|
24637
|
+
self:F2({self.ControllableName})
|
|
24638
|
+
local onoff=(OnOff==nil or OnOff==true)and false or true
|
|
24639
|
+
if self:IsAir()then
|
|
24640
|
+
self:SetOption(AI.Option.Air.id.PROHIBIT_WP_PASS_REPORT,onoff)
|
|
24641
|
+
end
|
|
24642
|
+
return self
|
|
24643
|
+
end
|
|
24644
|
+
function CONTROLLABLE:SetOptionRadioSilence(OnOff)
|
|
24645
|
+
local onoff=(OnOff==true or OnOff==nil)and true or false
|
|
24646
|
+
self:F2({self.ControllableName})
|
|
24647
|
+
if self:IsAir()then
|
|
24648
|
+
self:SetOption(AI.Option.Air.id.SILENCE,onoff)
|
|
24649
|
+
end
|
|
24650
|
+
return self
|
|
24651
|
+
end
|
|
24652
|
+
function CONTROLLABLE:SetOptionRadioContact(Objects)
|
|
24653
|
+
self:F2({self.ControllableName})
|
|
24654
|
+
if not Objects then Objects={"Air"}end
|
|
24655
|
+
if type(Objects)~="table"then Objects={Objects}end
|
|
24656
|
+
if self:IsAir()then
|
|
24657
|
+
self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_CONTACT,Objects)
|
|
24658
|
+
end
|
|
24659
|
+
return self
|
|
24660
|
+
end
|
|
24661
|
+
function CONTROLLABLE:SetOptionRadioEngage(Objects)
|
|
24662
|
+
self:F2({self.ControllableName})
|
|
24663
|
+
if not Objects then Objects={"Air"}end
|
|
24664
|
+
if type(Objects)~="table"then Objects={Objects}end
|
|
24665
|
+
if self:IsAir()then
|
|
24666
|
+
self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_ENGAGE,Objects)
|
|
24667
|
+
end
|
|
24668
|
+
return self
|
|
24669
|
+
end
|
|
24670
|
+
function CONTROLLABLE:SetOptionRadioKill(Objects)
|
|
24671
|
+
self:F2({self.ControllableName})
|
|
24672
|
+
if not Objects then Objects={"Air"}end
|
|
24673
|
+
if type(Objects)~="table"then Objects={Objects}end
|
|
24674
|
+
if self:IsAir()then
|
|
24675
|
+
self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_KILL,Objects)
|
|
24676
|
+
end
|
|
24677
|
+
return self
|
|
24678
|
+
end
|
|
24309
24679
|
function CONTROLLABLE:RelocateGroundRandomInRadius(speed,radius,onroad,shortcut,formation,onland)
|
|
24310
24680
|
self:F2({self.ControllableName})
|
|
24311
24681
|
local _coord=self:GetCoordinate()
|
|
@@ -25377,7 +25747,7 @@ end
|
|
|
25377
25747
|
function GROUP:IsActive()
|
|
25378
25748
|
self:F2(self.GroupName)
|
|
25379
25749
|
local DCSGroup=self:GetDCSObject()
|
|
25380
|
-
if DCSGroup then
|
|
25750
|
+
if DCSGroup and DCSGroup:isExist()then
|
|
25381
25751
|
local unit=DCSGroup:getUnit(1)
|
|
25382
25752
|
if unit then
|
|
25383
25753
|
local GroupIsActive=unit:isActive()
|
|
@@ -25835,7 +26205,7 @@ function GROUP:GetCoordinate()
|
|
|
25835
26205
|
local Units=self:GetUnits()or{}
|
|
25836
26206
|
for _,_unit in pairs(Units)do
|
|
25837
26207
|
local FirstUnit=_unit
|
|
25838
|
-
if FirstUnit then
|
|
26208
|
+
if FirstUnit and FirstUnit:IsAlive()then
|
|
25839
26209
|
local FirstUnitCoordinate=FirstUnit:GetCoordinate()
|
|
25840
26210
|
if FirstUnitCoordinate then
|
|
25841
26211
|
local Heading=self:GetHeading()
|
|
@@ -25844,6 +26214,18 @@ return FirstUnitCoordinate
|
|
|
25844
26214
|
end
|
|
25845
26215
|
end
|
|
25846
26216
|
end
|
|
26217
|
+
local DCSGroup=Group.getByName(self.GroupName)
|
|
26218
|
+
local DCSUnits=DCSGroup:getUnits()or{}
|
|
26219
|
+
for _,_unit in pairs(DCSUnits)do
|
|
26220
|
+
if Object.isExist(_unit)then
|
|
26221
|
+
local position=_unit:getPosition()
|
|
26222
|
+
local point=position.p~=nil and position.p or _unit:GetPoint()
|
|
26223
|
+
if point then
|
|
26224
|
+
local coord=COORDINATE:NewFromVec3(point)
|
|
26225
|
+
return coord
|
|
26226
|
+
end
|
|
26227
|
+
end
|
|
26228
|
+
end
|
|
25847
26229
|
BASE:E({"Cannot GetCoordinate",Group=self,Alive=self:IsAlive()})
|
|
25848
26230
|
end
|
|
25849
26231
|
function GROUP:GetRandomVec3(Radius)
|
|
@@ -26705,6 +27087,9 @@ end
|
|
|
26705
27087
|
return self
|
|
26706
27088
|
end
|
|
26707
27089
|
function GROUP:SetCommandInvisible(switch)
|
|
27090
|
+
return self:CommandSetInvisible(switch)
|
|
27091
|
+
end
|
|
27092
|
+
function GROUP:CommandSetInvisible(switch)
|
|
26708
27093
|
self:F2(self.GroupName)
|
|
26709
27094
|
if switch==nil then
|
|
26710
27095
|
switch=false
|
|
@@ -26714,6 +27099,9 @@ self:SetCommand(SetInvisible)
|
|
|
26714
27099
|
return self
|
|
26715
27100
|
end
|
|
26716
27101
|
function GROUP:SetCommandImmortal(switch)
|
|
27102
|
+
return self:CommandSetImmortal(switch)
|
|
27103
|
+
end
|
|
27104
|
+
function GROUP:CommandSetImmortal(switch)
|
|
26717
27105
|
self:F2(self.GroupName)
|
|
26718
27106
|
if switch==nil then
|
|
26719
27107
|
switch=false
|
|
@@ -27445,7 +27833,9 @@ local ThreatLevels={
|
|
|
27445
27833
|
}
|
|
27446
27834
|
if Attributes["Fighters"]then ThreatLevel=10
|
|
27447
27835
|
elseif Attributes["Multirole fighters"]then ThreatLevel=9
|
|
27836
|
+
elseif Attributes["Interceptors"]then ThreatLevel=9
|
|
27448
27837
|
elseif Attributes["Battleplanes"]then ThreatLevel=8
|
|
27838
|
+
elseif Attributes["Battle airplanes"]then ThreatLevel=8
|
|
27449
27839
|
elseif Attributes["Attack helicopters"]then ThreatLevel=7
|
|
27450
27840
|
elseif Attributes["Strategic bombers"]then ThreatLevel=6
|
|
27451
27841
|
elseif Attributes["Bombers"]then ThreatLevel=5
|
|
@@ -28075,6 +28465,25 @@ SpawnStatic:SpawnFromCoordinate(Coordinate,Heading,self.StaticName)
|
|
|
28075
28465
|
end
|
|
28076
28466
|
return self
|
|
28077
28467
|
end
|
|
28468
|
+
function STATIC:FindByMatching(Pattern)
|
|
28469
|
+
local GroupFound=nil
|
|
28470
|
+
for name,static in pairs(_DATABASE.STATICS)do
|
|
28471
|
+
if string.match(name,Pattern)then
|
|
28472
|
+
GroupFound=static
|
|
28473
|
+
break
|
|
28474
|
+
end
|
|
28475
|
+
end
|
|
28476
|
+
return GroupFound
|
|
28477
|
+
end
|
|
28478
|
+
function STATIC:FindAllByMatching(Pattern)
|
|
28479
|
+
local GroupsFound={}
|
|
28480
|
+
for name,static in pairs(_DATABASE.STATICS)do
|
|
28481
|
+
if string.match(name,Pattern)then
|
|
28482
|
+
GroupsFound[#GroupsFound+1]=static
|
|
28483
|
+
end
|
|
28484
|
+
end
|
|
28485
|
+
return GroupsFound
|
|
28486
|
+
end
|
|
28078
28487
|
AIRBASE={
|
|
28079
28488
|
ClassName="AIRBASE",
|
|
28080
28489
|
CategoryName={
|
|
@@ -28085,152 +28494,155 @@ CategoryName={
|
|
|
28085
28494
|
activerwyno=nil,
|
|
28086
28495
|
}
|
|
28087
28496
|
AIRBASE.Caucasus={
|
|
28497
|
+
["Anapa_Vityazevo"]="Anapa-Vityazevo",
|
|
28498
|
+
["Batumi"]="Batumi",
|
|
28499
|
+
["Beslan"]="Beslan",
|
|
28088
28500
|
["Gelendzhik"]="Gelendzhik",
|
|
28089
|
-
["Krasnodar_Pashkovsky"]="Krasnodar-Pashkovsky",
|
|
28090
|
-
["Sukhumi_Babushara"]="Sukhumi-Babushara",
|
|
28091
28501
|
["Gudauta"]="Gudauta",
|
|
28092
|
-
["Batumi"]="Batumi",
|
|
28093
|
-
["Senaki_Kolkhi"]="Senaki-Kolkhi",
|
|
28094
28502
|
["Kobuleti"]="Kobuleti",
|
|
28095
|
-
["Kutaisi"]="Kutaisi",
|
|
28096
|
-
["Tbilisi_Lochini"]="Tbilisi-Lochini",
|
|
28097
|
-
["Soganlug"]="Soganlug",
|
|
28098
|
-
["Vaziani"]="Vaziani",
|
|
28099
|
-
["Anapa_Vityazevo"]="Anapa-Vityazevo",
|
|
28100
28503
|
["Krasnodar_Center"]="Krasnodar-Center",
|
|
28101
|
-
["
|
|
28504
|
+
["Krasnodar_Pashkovsky"]="Krasnodar-Pashkovsky",
|
|
28102
28505
|
["Krymsk"]="Krymsk",
|
|
28506
|
+
["Kutaisi"]="Kutaisi",
|
|
28103
28507
|
["Maykop_Khanskaya"]="Maykop-Khanskaya",
|
|
28104
|
-
["Sochi_Adler"]="Sochi-Adler",
|
|
28105
28508
|
["Mineralnye_Vody"]="Mineralnye Vody",
|
|
28106
|
-
["Nalchik"]="Nalchik",
|
|
28107
28509
|
["Mozdok"]="Mozdok",
|
|
28108
|
-
["
|
|
28510
|
+
["Nalchik"]="Nalchik",
|
|
28511
|
+
["Novorossiysk"]="Novorossiysk",
|
|
28512
|
+
["Senaki_Kolkhi"]="Senaki-Kolkhi",
|
|
28513
|
+
["Sochi_Adler"]="Sochi-Adler",
|
|
28514
|
+
["Soganlug"]="Soganlug",
|
|
28515
|
+
["Sukhumi_Babushara"]="Sukhumi-Babushara",
|
|
28516
|
+
["Tbilisi_Lochini"]="Tbilisi-Lochini",
|
|
28517
|
+
["Vaziani"]="Vaziani",
|
|
28109
28518
|
}
|
|
28110
28519
|
AIRBASE.Nevada={
|
|
28111
|
-
["
|
|
28112
|
-
["
|
|
28113
|
-
["
|
|
28114
|
-
["Nellis_AFB"]="Nellis",
|
|
28115
|
-
["Beatty_Airport"]="Beatty",
|
|
28116
|
-
["Boulder_City_Airport"]="Boulder City",
|
|
28520
|
+
["Beatty"]="Beatty",
|
|
28521
|
+
["Boulder_City"]="Boulder City",
|
|
28522
|
+
["Creech"]="Creech",
|
|
28117
28523
|
["Echo_Bay"]="Echo Bay",
|
|
28118
|
-
["
|
|
28119
|
-
["
|
|
28120
|
-
["
|
|
28524
|
+
["Groom_Lake"]="Groom Lake",
|
|
28525
|
+
["Henderson_Executive"]="Henderson Executive",
|
|
28526
|
+
["Jean"]="Jean",
|
|
28527
|
+
["Laughlin"]="Laughlin",
|
|
28121
28528
|
["Lincoln_County"]="Lincoln County",
|
|
28529
|
+
["McCarran_International"]="McCarran International",
|
|
28122
28530
|
["Mesquite"]="Mesquite",
|
|
28123
|
-
["
|
|
28531
|
+
["Mina"]="Mina",
|
|
28532
|
+
["Nellis"]="Nellis",
|
|
28124
28533
|
["North_Las_Vegas"]="North Las Vegas",
|
|
28125
|
-
["
|
|
28126
|
-
["
|
|
28127
|
-
["
|
|
28534
|
+
["Pahute_Mesa"]="Pahute Mesa",
|
|
28535
|
+
["Tonopah"]="Tonopah",
|
|
28536
|
+
["Tonopah_Test_Range"]="Tonopah Test Range",
|
|
28128
28537
|
}
|
|
28129
28538
|
AIRBASE.Normandy={
|
|
28130
|
-
["
|
|
28131
|
-
["
|
|
28132
|
-
["
|
|
28133
|
-
["
|
|
28134
|
-
["Brucheville"]="Brucheville",
|
|
28135
|
-
["Meautis"]="Meautis",
|
|
28136
|
-
["Cricqueville_en_Bessin"]="Cricqueville-en-Bessin",
|
|
28137
|
-
["Lessay"]="Lessay",
|
|
28138
|
-
["Sainte_Laurent_sur_Mer"]="Sainte-Laurent-sur-Mer",
|
|
28139
|
-
["Biniville"]="Biniville",
|
|
28140
|
-
["Cardonville"]="Cardonville",
|
|
28141
|
-
["Deux_Jumeaux"]="Deux Jumeaux",
|
|
28142
|
-
["Chippelle"]="Chippelle",
|
|
28143
|
-
["Beuzeville"]="Beuzeville",
|
|
28539
|
+
["Abbeville_Drucat"]="Abbeville Drucat",
|
|
28540
|
+
["Amiens_Glisy"]="Amiens-Glisy",
|
|
28541
|
+
["Argentan"]="Argentan",
|
|
28542
|
+
["Avranches_Le_Val_Saint_Pere"]="Avranches Le Val-Saint-Pere",
|
|
28144
28543
|
["Azeville"]="Azeville",
|
|
28145
|
-
["
|
|
28146
|
-
["Le_Molay"]="Le Molay",
|
|
28147
|
-
["Longues_sur_Mer"]="Longues-sur-Mer",
|
|
28148
|
-
["Carpiquet"]="Carpiquet",
|
|
28544
|
+
["Barville"]="Barville",
|
|
28149
28545
|
["Bazenville"]="Bazenville",
|
|
28150
|
-
["
|
|
28546
|
+
["Beaumont_le_Roger"]="Beaumont-le-Roger",
|
|
28547
|
+
["Beauvais_Tille"]="Beauvais-Tille",
|
|
28151
28548
|
["Beny_sur_Mer"]="Beny-sur-Mer",
|
|
28152
|
-
["
|
|
28153
|
-
["
|
|
28154
|
-
["
|
|
28155
|
-
["
|
|
28549
|
+
["Bernay_Saint_Martin"]="Bernay Saint Martin",
|
|
28550
|
+
["Beuzeville"]="Beuzeville",
|
|
28551
|
+
["Biggin_Hill"]="Biggin Hill",
|
|
28552
|
+
["Biniville"]="Biniville",
|
|
28553
|
+
["Broglie"]="Broglie",
|
|
28554
|
+
["Brucheville"]="Brucheville",
|
|
28555
|
+
["Cardonville"]="Cardonville",
|
|
28556
|
+
["Carpiquet"]="Carpiquet",
|
|
28156
28557
|
["Chailey"]="Chailey",
|
|
28157
|
-
["
|
|
28158
|
-
["Funtington"]="Funtington",
|
|
28159
|
-
["Tangmere"]="Tangmere",
|
|
28160
|
-
["Ford"]="Ford",
|
|
28161
|
-
["Argentan"]="Argentan",
|
|
28162
|
-
["Goulet"]="Goulet",
|
|
28163
|
-
["Barville"]="Barville",
|
|
28164
|
-
["Essay"]="Essay",
|
|
28165
|
-
["Hauterive"]="Hauterive",
|
|
28166
|
-
["Lymington"]="Lymington",
|
|
28167
|
-
["Vrigny"]="Vrigny",
|
|
28168
|
-
["Odiham"]="Odiham",
|
|
28558
|
+
["Chippelle"]="Chippelle",
|
|
28169
28559
|
["Conches"]="Conches",
|
|
28170
|
-
["West_Malling"]="West Malling",
|
|
28171
|
-
["Villacoublay"]="Villacoublay",
|
|
28172
|
-
["Kenley"]="Kenley",
|
|
28173
|
-
["Beauvais_Tille"]="Beauvais-Tille",
|
|
28174
28560
|
["Cormeilles_en_Vexin"]="Cormeilles-en-Vexin",
|
|
28175
28561
|
["Creil"]="Creil",
|
|
28176
|
-
["
|
|
28177
|
-
["
|
|
28562
|
+
["Cretteville"]="Cretteville",
|
|
28563
|
+
["Cricqueville_en_Bessin"]="Cricqueville-en-Bessin",
|
|
28564
|
+
["Deanland"]="Deanland",
|
|
28565
|
+
["Deauville"]="Deauville",
|
|
28566
|
+
["Detling"]="Detling",
|
|
28567
|
+
["Deux_Jumeaux"]="Deux Jumeaux",
|
|
28178
28568
|
["Dinan_Trelivan"]="Dinan-Trelivan",
|
|
28179
|
-
["
|
|
28180
|
-
["
|
|
28569
|
+
["Dunkirk_Mardyck"]="Dunkirk-Mardyck",
|
|
28570
|
+
["Essay"]="Essay",
|
|
28571
|
+
["Evreux"]="Evreux",
|
|
28181
28572
|
["Farnborough"]="Farnborough",
|
|
28573
|
+
["Fecamp_Benouville"]="Fecamp-Benouville",
|
|
28574
|
+
["Flers"]="Flers",
|
|
28575
|
+
["Ford"]="Ford",
|
|
28182
28576
|
["Friston"]="Friston",
|
|
28183
|
-
["
|
|
28184
|
-
["
|
|
28185
|
-
["
|
|
28577
|
+
["Funtington"]="Funtington",
|
|
28578
|
+
["Goulet"]="Goulet",
|
|
28579
|
+
["Gravesend"]="Gravesend",
|
|
28580
|
+
["Guyancourt"]="Guyancourt",
|
|
28581
|
+
["Hauterive"]="Hauterive",
|
|
28582
|
+
["Heathrow"]="Heathrow",
|
|
28583
|
+
["High_Halden"]="High Halden",
|
|
28584
|
+
["Kenley"]="Kenley",
|
|
28585
|
+
["Lantheuil"]="Lantheuil",
|
|
28586
|
+
["Le_Molay"]="Le Molay",
|
|
28587
|
+
["Lessay"]="Lessay",
|
|
28588
|
+
["Lignerolles"]="Lignerolles",
|
|
28589
|
+
["Longues_sur_Mer"]="Longues-sur-Mer",
|
|
28590
|
+
["Lonrai"]="Lonrai",
|
|
28591
|
+
["Lymington"]="Lymington",
|
|
28592
|
+
["Lympne"]="Lympne",
|
|
28593
|
+
["Manston"]="Manston",
|
|
28594
|
+
["Maupertus"]="Maupertus",
|
|
28595
|
+
["Meautis"]="Meautis",
|
|
28596
|
+
["Merville_Calonne"]="Merville Calonne",
|
|
28597
|
+
["Needs_Oar_Point"]="Needs Oar Point",
|
|
28598
|
+
["Odiham"]="Odiham",
|
|
28186
28599
|
["Orly"]="Orly",
|
|
28187
|
-
["
|
|
28188
|
-
["
|
|
28600
|
+
["Picauville"]="Picauville",
|
|
28601
|
+
["Poix"]="Poix",
|
|
28189
28602
|
["Ronai"]="Ronai",
|
|
28190
28603
|
["Rouen_Boos"]="Rouen-Boos",
|
|
28191
|
-
["
|
|
28192
|
-
["Saint_Aubin"]="Saint-Aubin",
|
|
28193
|
-
["Flers"]="Flers",
|
|
28194
|
-
["Avranches_Le_Val_Saint_Pere"]="Avranches Le Val-Saint-Pere",
|
|
28195
|
-
["Gravesend"]="Gravesend",
|
|
28196
|
-
["Beaumont_le_Roger"]="Beaumont-le-Roger",
|
|
28197
|
-
["Broglie"]="Broglie",
|
|
28198
|
-
["Bernay_Saint_Martin"]="Bernay Saint Martin",
|
|
28604
|
+
["Rucqueville"]="Rucqueville",
|
|
28199
28605
|
["Saint_Andre_de_lEure"]="Saint-Andre-de-lEure",
|
|
28200
|
-
["
|
|
28201
|
-
["Manston"]="Manston",
|
|
28202
|
-
["Detling"]="Detling",
|
|
28203
|
-
["Lympne"]="Lympne",
|
|
28204
|
-
["Abbeville_Drucat"]="Abbeville Drucat",
|
|
28205
|
-
["Merville_Calonne"]="Merville Calonne",
|
|
28606
|
+
["Saint_Aubin"]="Saint-Aubin",
|
|
28206
28607
|
["Saint_Omer_Wizernes"]="Saint-Omer Wizernes",
|
|
28608
|
+
["Saint_Pierre_du_Mont"]="Saint Pierre du Mont",
|
|
28609
|
+
["Sainte_Croix_sur_Mer"]="Sainte-Croix-sur-Mer",
|
|
28610
|
+
["Sainte_Laurent_sur_Mer"]="Sainte-Laurent-sur-Mer",
|
|
28611
|
+
["Sommervieu"]="Sommervieu",
|
|
28612
|
+
["Stoney_Cross"]="Stoney Cross",
|
|
28613
|
+
["Tangmere"]="Tangmere",
|
|
28614
|
+
["Triqueville"]="Triqueville",
|
|
28615
|
+
["Villacoublay"]="Villacoublay",
|
|
28616
|
+
["Vrigny"]="Vrigny",
|
|
28617
|
+
["West_Malling"]="West Malling",
|
|
28207
28618
|
}
|
|
28208
28619
|
AIRBASE.PersianGulf={
|
|
28209
|
-
["
|
|
28210
|
-
["
|
|
28211
|
-
["
|
|
28212
|
-
["
|
|
28213
|
-
["
|
|
28620
|
+
["Abu_Dhabi_Intl"]="Abu Dhabi Intl",
|
|
28621
|
+
["Abu_Musa_Island"]="Abu Musa Island",
|
|
28622
|
+
["Al_Ain_Intl"]="Al Ain Intl",
|
|
28623
|
+
["Al_Bateen"]="Al-Bateen",
|
|
28624
|
+
["Al_Dhafra_AFB"]="Al Dhafra AFB",
|
|
28214
28625
|
["Al_Maktoum_Intl"]="Al Maktoum Intl",
|
|
28215
|
-
["
|
|
28626
|
+
["Al_Minhad_AFB"]="Al Minhad AFB",
|
|
28216
28627
|
["Bandar_Abbas_Intl"]="Bandar Abbas Intl",
|
|
28217
28628
|
["Bandar_Lengeh"]="Bandar Lengeh",
|
|
28218
|
-
["
|
|
28629
|
+
["Bandar_e_Jask"]="Bandar-e-Jask",
|
|
28219
28630
|
["Dubai_Intl"]="Dubai Intl",
|
|
28220
28631
|
["Fujairah_Intl"]="Fujairah Intl",
|
|
28221
28632
|
["Havadarya"]="Havadarya",
|
|
28222
|
-
["
|
|
28223
|
-
["
|
|
28633
|
+
["Jiroft"]="Jiroft",
|
|
28634
|
+
["Kerman"]="Kerman",
|
|
28224
28635
|
["Khasab"]="Khasab",
|
|
28225
|
-
["
|
|
28226
|
-
["
|
|
28227
|
-
["
|
|
28228
|
-
["
|
|
28636
|
+
["Kish_Intl"]="Kish Intl",
|
|
28637
|
+
["Lar"]="Lar",
|
|
28638
|
+
["Lavan_Island"]="Lavan Island",
|
|
28639
|
+
["Liwa_AFB"]="Liwa AFB",
|
|
28229
28640
|
["Qeshm_Island"]="Qeshm Island",
|
|
28230
|
-
["
|
|
28231
|
-
["
|
|
28641
|
+
["Quasoura_airport"]="Quasoura_airport",
|
|
28642
|
+
["Ras_Al_Khaimah_Intl"]="Ras Al Khaimah Intl",
|
|
28643
|
+
["Sas_Al_Nakheel"]="Sas Al Nakheel",
|
|
28232
28644
|
["Sharjah_Intl"]="Sharjah Intl",
|
|
28233
|
-
["
|
|
28645
|
+
["Shiraz_Intl"]="Shiraz Intl",
|
|
28234
28646
|
["Sir_Abu_Nuayr"]="Sir Abu Nuayr",
|
|
28235
28647
|
["Sirri_Island"]="Sirri Island",
|
|
28236
28648
|
["Tunb_Island_AFB"]="Tunb Island AFB",
|
|
@@ -28238,156 +28650,163 @@ AIRBASE.PersianGulf={
|
|
|
28238
28650
|
}
|
|
28239
28651
|
AIRBASE.TheChannel={
|
|
28240
28652
|
["Abbeville_Drucat"]="Abbeville Drucat",
|
|
28241
|
-
["Merville_Calonne"]="Merville Calonne",
|
|
28242
|
-
["Saint_Omer_Longuenesse"]="Saint Omer Longuenesse",
|
|
28243
|
-
["Dunkirk_Mardyck"]="Dunkirk Mardyck",
|
|
28244
|
-
["Manston"]="Manston",
|
|
28245
|
-
["Hawkinge"]="Hawkinge",
|
|
28246
|
-
["Lympne"]="Lympne",
|
|
28247
|
-
["Detling"]="Detling",
|
|
28248
|
-
["High_Halden"]="High Halden",
|
|
28249
28653
|
["Biggin_Hill"]="Biggin Hill",
|
|
28654
|
+
["Detling"]="Detling",
|
|
28655
|
+
["Dunkirk_Mardyck"]="Dunkirk Mardyck",
|
|
28250
28656
|
["Eastchurch"]="Eastchurch",
|
|
28657
|
+
["Hawkinge"]="Hawkinge",
|
|
28251
28658
|
["Headcorn"]="Headcorn",
|
|
28659
|
+
["High_Halden"]="High Halden",
|
|
28660
|
+
["Lympne"]="Lympne",
|
|
28661
|
+
["Manston"]="Manston",
|
|
28662
|
+
["Merville_Calonne"]="Merville Calonne",
|
|
28663
|
+
["Saint_Omer_Longuenesse"]="Saint Omer Longuenesse",
|
|
28252
28664
|
}
|
|
28253
28665
|
AIRBASE.Syria={
|
|
28254
|
-
["
|
|
28255
|
-
["
|
|
28256
|
-
["
|
|
28257
|
-
["Marj_as_Sultan_North"]="Marj as Sultan North",
|
|
28258
|
-
["Eyn_Shemer"]="Eyn Shemer",
|
|
28259
|
-
["Incirlik"]="Incirlik",
|
|
28260
|
-
["Damascus"]="Damascus",
|
|
28261
|
-
["Bassel_Al_Assad"]="Bassel Al-Assad",
|
|
28262
|
-
["Rosh_Pina"]="Rosh Pina",
|
|
28263
|
-
["Aleppo"]="Aleppo",
|
|
28264
|
-
["Al_Qusayr"]="Al Qusayr",
|
|
28265
|
-
["Wujah_Al_Hajar"]="Wujah Al Hajar",
|
|
28666
|
+
["Abu_al_Duhur"]="Abu al-Duhur",
|
|
28667
|
+
["Adana_Sakirpasa"]="Adana Sakirpasa",
|
|
28668
|
+
["Akrotiri"]="Akrotiri",
|
|
28266
28669
|
["Al_Dumayr"]="Al-Dumayr",
|
|
28670
|
+
["Al_Qusayr"]="Al Qusayr",
|
|
28671
|
+
["Aleppo"]="Aleppo",
|
|
28672
|
+
["Amman"]="Amman",
|
|
28673
|
+
["An_Nasiriyah"]="An Nasiriyah",
|
|
28674
|
+
["At_Tanf"]="At Tanf",
|
|
28675
|
+
["Bassel_Al_Assad"]="Bassel Al-Assad",
|
|
28676
|
+
["Beirut_Rafic_Hariri"]="Beirut-Rafic Hariri",
|
|
28677
|
+
["Damascus"]="Damascus",
|
|
28678
|
+
["Deir_ez_Zor"]="Deir ez-Zor",
|
|
28679
|
+
["Ercan"]="Ercan",
|
|
28680
|
+
["Eyn_Shemer"]="Eyn Shemer",
|
|
28681
|
+
["Gaziantep"]="Gaziantep",
|
|
28267
28682
|
["Gazipasa"]="Gazipasa",
|
|
28268
|
-
["
|
|
28269
|
-
["
|
|
28270
|
-
["
|
|
28271
|
-
["
|
|
28272
|
-
["
|
|
28683
|
+
["Gecitkale"]="Gecitkale",
|
|
28684
|
+
["H3"]="H3",
|
|
28685
|
+
["H3_Northwest"]="H3 Northwest",
|
|
28686
|
+
["H3_Southwest"]="H3 Southwest",
|
|
28687
|
+
["H4"]="H4",
|
|
28273
28688
|
["Haifa"]="Haifa",
|
|
28689
|
+
["Hama"]="Hama",
|
|
28690
|
+
["Hatay"]="Hatay",
|
|
28691
|
+
["Herzliya"]="Herzliya",
|
|
28692
|
+
["Incirlik"]="Incirlik",
|
|
28693
|
+
["Jirah"]="Jirah",
|
|
28274
28694
|
["Khalkhalah"]="Khalkhalah",
|
|
28275
|
-
["
|
|
28695
|
+
["Kharab_Ishk"]="Kharab Ishk",
|
|
28696
|
+
["King_Abdullah_II"]="King Abdullah II",
|
|
28697
|
+
["King_Hussein_Air_College"]="King Hussein Air College",
|
|
28698
|
+
["Kingsfield"]="Kingsfield",
|
|
28699
|
+
["Kiryat_Shmona"]="Kiryat Shmona",
|
|
28700
|
+
["Kuweires"]="Kuweires",
|
|
28276
28701
|
["Lakatamia"]="Lakatamia",
|
|
28277
|
-
["Rayak"]="Rayak",
|
|
28278
28702
|
["Larnaca"]="Larnaca",
|
|
28703
|
+
["Marj_Ruhayyil"]="Marj Ruhayyil",
|
|
28704
|
+
["Marj_as_Sultan_North"]="Marj as Sultan North",
|
|
28705
|
+
["Marj_as_Sultan_South"]="Marj as Sultan South",
|
|
28706
|
+
["Megiddo"]="Megiddo",
|
|
28279
28707
|
["Mezzeh"]="Mezzeh",
|
|
28280
|
-
["Gecitkale"]="Gecitkale",
|
|
28281
|
-
["Akrotiri"]="Akrotiri",
|
|
28282
|
-
["Naqoura"]="Naqoura",
|
|
28283
|
-
["Gaziantep"]="Gaziantep",
|
|
28284
|
-
["Sayqal"]="Sayqal",
|
|
28285
|
-
["Tiyas"]="Tiyas",
|
|
28286
|
-
["Shayrat"]="Shayrat",
|
|
28287
|
-
["Taftanaz"]="Taftanaz",
|
|
28288
|
-
["H4"]="H4",
|
|
28289
|
-
["King_Hussein_Air_College"]="King Hussein Air College",
|
|
28290
|
-
["Rene_Mouawad"]="Rene Mouawad",
|
|
28291
|
-
["Jirah"]="Jirah",
|
|
28292
|
-
["Ramat_David"]="Ramat David",
|
|
28293
|
-
["Qabr_as_Sitt"]="Qabr as Sitt",
|
|
28294
28708
|
["Minakh"]="Minakh",
|
|
28295
|
-
["
|
|
28709
|
+
["Muwaffaq_Salti"]="Muwaffaq Salti",
|
|
28710
|
+
["Naqoura"]="Naqoura",
|
|
28711
|
+
["Nicosia"]="Nicosia",
|
|
28296
28712
|
["Palmyra"]="Palmyra",
|
|
28297
|
-
["
|
|
28298
|
-
["
|
|
28299
|
-
["
|
|
28300
|
-
["
|
|
28301
|
-
["
|
|
28302
|
-
["
|
|
28303
|
-
["
|
|
28304
|
-
["
|
|
28305
|
-
["H3"]="H3",
|
|
28306
|
-
["H3_Northwest"]="H3 Northwest",
|
|
28307
|
-
["H3_Southwest"]="H3 Southwest",
|
|
28308
|
-
["Kharab_Ishk"]="Kharab Ishk",
|
|
28713
|
+
["Paphos"]="Paphos",
|
|
28714
|
+
["Pinarbashi"]="Pinarbashi",
|
|
28715
|
+
["Prince_Hassan"]="Prince Hassan",
|
|
28716
|
+
["Qabr_as_Sitt"]="Qabr as Sitt",
|
|
28717
|
+
["Ramat_David"]="Ramat David",
|
|
28718
|
+
["Rayak"]="Rayak",
|
|
28719
|
+
["Rene_Mouawad"]="Rene Mouawad",
|
|
28720
|
+
["Rosh_Pina"]="Rosh Pina",
|
|
28309
28721
|
["Ruwayshid"]="Ruwayshid",
|
|
28310
28722
|
["Sanliurfa"]="Sanliurfa",
|
|
28723
|
+
["Sayqal"]="Sayqal",
|
|
28724
|
+
["Shayrat"]="Shayrat",
|
|
28725
|
+
["Tabqa"]="Tabqa",
|
|
28726
|
+
["Taftanaz"]="Taftanaz",
|
|
28311
28727
|
["Tal_Siman"]="Tal Siman",
|
|
28312
|
-
["
|
|
28728
|
+
["Tha_lah"]="Tha'lah",
|
|
28729
|
+
["Tiyas"]="Tiyas",
|
|
28730
|
+
["Wujah_Al_Hajar"]="Wujah Al Hajar",
|
|
28313
28731
|
}
|
|
28314
28732
|
AIRBASE.MarianaIslands={
|
|
28315
|
-
["Rota_Intl"]="Rota Intl",
|
|
28316
28733
|
["Andersen_AFB"]="Andersen AFB",
|
|
28317
28734
|
["Antonio_B_Won_Pat_Intl"]="Antonio B. Won Pat Intl",
|
|
28318
|
-
["
|
|
28319
|
-
["Tinian_Intl"]="Tinian Intl",
|
|
28735
|
+
["North_West_Field"]="North West Field",
|
|
28320
28736
|
["Olf_Orote"]="Olf Orote",
|
|
28321
28737
|
["Pagan_Airstrip"]="Pagan Airstrip",
|
|
28322
|
-
["
|
|
28738
|
+
["Rota_Intl"]="Rota Intl",
|
|
28739
|
+
["Saipan_Intl"]="Saipan Intl",
|
|
28740
|
+
["Tinian_Intl"]="Tinian Intl",
|
|
28323
28741
|
}
|
|
28324
28742
|
AIRBASE.SouthAtlantic={
|
|
28325
|
-
["
|
|
28743
|
+
["Almirante_Schroeders"]="Almirante Schroeders",
|
|
28744
|
+
["Caleta_Tortel"]="Caleta Tortel",
|
|
28745
|
+
["Comandante_Luis_Piedrabuena"]="Comandante Luis Piedrabuena",
|
|
28746
|
+
["Cullen"]="Cullen",
|
|
28747
|
+
["El_Calafate"]="El Calafate",
|
|
28748
|
+
["Franco_Bianco"]="Franco Bianco",
|
|
28749
|
+
["Gobernador_Gregores"]="Gobernador Gregores",
|
|
28750
|
+
["Goose_Green"]="Goose Green",
|
|
28751
|
+
["Gull_Point"]="Gull Point",
|
|
28752
|
+
["Hipico_Flying_Club"]="Hipico Flying Club",
|
|
28326
28753
|
["Mount_Pleasant"]="Mount Pleasant",
|
|
28327
|
-
["
|
|
28328
|
-
["Rio_Grande"]="Rio Grande",
|
|
28329
|
-
["Rio_Gallegos"]="Rio Gallegos",
|
|
28330
|
-
["Ushuaia"]="Ushuaia",
|
|
28331
|
-
["Ushuaia_Helo_Port"]="Ushuaia Helo Port",
|
|
28332
|
-
["Punta_Arenas"]="Punta Arenas",
|
|
28754
|
+
["O_Higgins"]="O'Higgins",
|
|
28333
28755
|
["Pampa_Guanaco"]="Pampa Guanaco",
|
|
28334
|
-
["
|
|
28335
|
-
["
|
|
28756
|
+
["Port_Stanley"]="Port Stanley",
|
|
28757
|
+
["Porvenir"]="Porvenir",
|
|
28336
28758
|
["Puerto_Natales"]="Puerto Natales",
|
|
28337
|
-
["El_Calafate"]="El Calafate",
|
|
28338
28759
|
["Puerto_Santa_Cruz"]="Puerto Santa Cruz",
|
|
28339
|
-
["
|
|
28340
|
-
["
|
|
28341
|
-
["Porvenir_Airfield"]="Porvenir Airfield",
|
|
28342
|
-
["Almirante_Schroeders"]="Almirante Schroeders",
|
|
28343
|
-
["Rio_Turbio"]="Rio Turbio",
|
|
28760
|
+
["Puerto_Williams"]="Puerto Williams",
|
|
28761
|
+
["Punta_Arenas"]="Punta Arenas",
|
|
28344
28762
|
["Rio_Chico"]="Rio Chico",
|
|
28345
|
-
["
|
|
28346
|
-
["
|
|
28347
|
-
["
|
|
28348
|
-
["
|
|
28349
|
-
["
|
|
28350
|
-
["
|
|
28351
|
-
["
|
|
28352
|
-
["
|
|
28763
|
+
["Rio_Gallegos"]="Rio Gallegos",
|
|
28764
|
+
["Rio_Grande"]="Rio Grande",
|
|
28765
|
+
["Rio_Turbio"]="Rio Turbio",
|
|
28766
|
+
["San_Carlos_FOB"]="San Carlos FOB",
|
|
28767
|
+
["San_Julian"]="San Julian",
|
|
28768
|
+
["Tolhuin"]="Tolhuin",
|
|
28769
|
+
["Ushuaia"]="Ushuaia",
|
|
28770
|
+
["Ushuaia_Helo_Port"]="Ushuaia Helo Port",
|
|
28353
28771
|
}
|
|
28354
28772
|
AIRBASE.Sinai={
|
|
28355
|
-
["
|
|
28773
|
+
["Abu_Rudeis"]="Abu Rudeis",
|
|
28356
28774
|
["Abu_Suwayr"]="Abu Suwayr",
|
|
28357
|
-
["Sde_Dov"]="Sde Dov",
|
|
28358
|
-
["AzZaqaziq"]="AzZaqaziq",
|
|
28359
|
-
["Hatzor"]="Hatzor",
|
|
28360
|
-
["Kedem"]="Kedem",
|
|
28361
|
-
["Nevatim"]="Nevatim",
|
|
28362
|
-
["Cairo_International_Airport"]="Cairo International Airport",
|
|
28363
28775
|
["Al_Ismailiyah"]="Al Ismailiyah",
|
|
28776
|
+
["Al_Mansurah"]="Al Mansurah",
|
|
28364
28777
|
["As_Salihiyah"]="As Salihiyah",
|
|
28365
|
-
["
|
|
28778
|
+
["AzZaqaziq"]="AzZaqaziq",
|
|
28779
|
+
["Baluza"]="Baluza",
|
|
28780
|
+
["Ben_Gurion"]="Ben-Gurion",
|
|
28366
28781
|
["Bilbeis_Air_Base"]="Bilbeis Air Base",
|
|
28367
|
-
["
|
|
28368
|
-
["
|
|
28782
|
+
["Bir_Hasanah"]="Bir Hasanah",
|
|
28783
|
+
["Cairo_International_Airport"]="Cairo International Airport",
|
|
28784
|
+
["Cairo_West"]="Cairo West",
|
|
28785
|
+
["Difarsuwar_Airfield"]="Difarsuwar Airfield",
|
|
28369
28786
|
["El_Arish"]="El Arish",
|
|
28370
|
-
["
|
|
28787
|
+
["El_Gora"]="El Gora",
|
|
28788
|
+
["Fayed"]="Fayed",
|
|
28789
|
+
["Hatzerim"]="Hatzerim",
|
|
28790
|
+
["Hatzor"]="Hatzor",
|
|
28791
|
+
["Inshas_Airbase"]="Inshas Airbase",
|
|
28792
|
+
["Kedem"]="Kedem",
|
|
28793
|
+
["Kibrit_Air_Base"]="Kibrit Air Base",
|
|
28371
28794
|
["Melez"]="Melez",
|
|
28372
|
-
["
|
|
28795
|
+
["Nevatim"]="Nevatim",
|
|
28796
|
+
["Ovda"]="Ovda",
|
|
28373
28797
|
["Palmahim"]="Palmahim",
|
|
28374
|
-
["
|
|
28375
|
-
["
|
|
28376
|
-
["Difarsuwar_Airfield"]="Difarsuwar Airfield",
|
|
28377
|
-
["Wadi_al_Jandali"]="Wadi al Jandali",
|
|
28798
|
+
["Ramon_Airbase"]="Ramon Airbase",
|
|
28799
|
+
["Sde_Dov"]="Sde Dov",
|
|
28378
28800
|
["St_Catherine"]="St Catherine",
|
|
28379
28801
|
["Tel_Nof"]="Tel Nof",
|
|
28380
|
-
["
|
|
28381
|
-
["Inshas_Airbase"]="Inshas Airbase",
|
|
28382
|
-
["Ben_Gurion"]="Ben-Gurion",
|
|
28383
|
-
["Bir_Hasanah"]="Bir Hasanah",
|
|
28384
|
-
["Cairo_West"]="Cairo West",
|
|
28802
|
+
["Wadi_al_Jandali"]="Wadi al Jandali",
|
|
28385
28803
|
}
|
|
28386
28804
|
AIRBASE.TerminalType={
|
|
28387
28805
|
Runway=16,
|
|
28388
28806
|
HelicopterOnly=40,
|
|
28389
28807
|
Shelter=68,
|
|
28390
28808
|
OpenMed=72,
|
|
28809
|
+
SmallSizeFighter=100,
|
|
28391
28810
|
OpenBig=104,
|
|
28392
28811
|
OpenMedOrBig=176,
|
|
28393
28812
|
HelicopterUsable=216,
|
|
@@ -28946,7 +29365,7 @@ if Term_Type==AIRBASE.TerminalType.OpenMed or Term_Type==AIRBASE.TerminalType.Op
|
|
|
28946
29365
|
match=true
|
|
28947
29366
|
end
|
|
28948
29367
|
elseif termtype==AIRBASE.TerminalType.FighterAircraft then
|
|
28949
|
-
if Term_Type==AIRBASE.TerminalType.OpenMed or Term_Type==AIRBASE.TerminalType.OpenBig or Term_Type==AIRBASE.TerminalType.Shelter then
|
|
29368
|
+
if Term_Type==AIRBASE.TerminalType.OpenMed or Term_Type==AIRBASE.TerminalType.OpenBig or Term_Type==AIRBASE.TerminalType.Shelter or Term_Type==AIRBASE.TerminalType.SmallSizeFighter then
|
|
28950
29369
|
match=true
|
|
28951
29370
|
end
|
|
28952
29371
|
end
|
|
@@ -29730,6 +30149,9 @@ self.desc=WeaponObject:getDesc()
|
|
|
29730
30149
|
self.category=self.desc.category
|
|
29731
30150
|
if self:IsMissile()and self.desc.missileCategory then
|
|
29732
30151
|
self.categoryMissile=self.desc.missileCategory
|
|
30152
|
+
if self.desc.guidance then
|
|
30153
|
+
self.guidance=self.desc.guidance
|
|
30154
|
+
end
|
|
29733
30155
|
end
|
|
29734
30156
|
self.typeName=WeaponObject:getTypeName()or"Unknown Type"
|
|
29735
30157
|
self.name=WeaponObject:getName()
|
|
@@ -29944,6 +30366,15 @@ end
|
|
|
29944
30366
|
function WEAPON:IsTorpedo()
|
|
29945
30367
|
return self.category==Weapon.Category.TORPEDO
|
|
29946
30368
|
end
|
|
30369
|
+
function WEAPON:IsFoxOne()
|
|
30370
|
+
return self.guidance==Weapon.GuidanceType.RADAR_SEMI_ACTIVE
|
|
30371
|
+
end
|
|
30372
|
+
function WEAPON:IsFoxTwo()
|
|
30373
|
+
return self.guidance==Weapon.GuidanceType.IR
|
|
30374
|
+
end
|
|
30375
|
+
function WEAPON:IsFoxThree()
|
|
30376
|
+
return self.guidance==Weapon.GuidanceType.RADAR_ACTIVE
|
|
30377
|
+
end
|
|
29947
30378
|
function WEAPON:Destroy(Delay)
|
|
29948
30379
|
if Delay and Delay>0 then
|
|
29949
30380
|
self:ScheduleOnce(Delay,WEAPON.Destroy,self,0)
|
|
@@ -30409,7 +30840,7 @@ end
|
|
|
30409
30840
|
function NET.Lua2Json(Lua)
|
|
30410
30841
|
return net.lua2json(Lua)
|
|
30411
30842
|
end
|
|
30412
|
-
function NET.
|
|
30843
|
+
function NET.Json2Lua(Json)
|
|
30413
30844
|
return net.json2lua(Json)
|
|
30414
30845
|
end
|
|
30415
30846
|
function NET:DoStringIn(State,DoString)
|
|
@@ -31959,7 +32390,7 @@ ClassName="SCORING",
|
|
|
31959
32390
|
ClassID=0,
|
|
31960
32391
|
Players={},
|
|
31961
32392
|
AutoSave=true,
|
|
31962
|
-
version="1.
|
|
32393
|
+
version="1.18.4"
|
|
31963
32394
|
}
|
|
31964
32395
|
local _SCORINGCoalition={
|
|
31965
32396
|
[1]="Red",
|
|
@@ -31972,7 +32403,7 @@ local _SCORINGCategory={
|
|
|
31972
32403
|
[Unit.Category.SHIP]="Ship",
|
|
31973
32404
|
[Unit.Category.STRUCTURE]="Structure",
|
|
31974
32405
|
}
|
|
31975
|
-
function SCORING:New(GameName)
|
|
32406
|
+
function SCORING:New(GameName,SavePath,AutoSave)
|
|
31976
32407
|
local self=BASE:Inherit(self,BASE:New())
|
|
31977
32408
|
if GameName then
|
|
31978
32409
|
self.GameName=GameName
|
|
@@ -32005,7 +32436,8 @@ self:_AddPlayerFromUnit(PlayerUnit)
|
|
|
32005
32436
|
self:SetScoringMenu(PlayerUnit:GetGroup())
|
|
32006
32437
|
end
|
|
32007
32438
|
end)
|
|
32008
|
-
self.
|
|
32439
|
+
self.AutoSavePath=SavePath
|
|
32440
|
+
self.AutoSave=AutoSave or true
|
|
32009
32441
|
self:OpenCSV(GameName)
|
|
32010
32442
|
return self
|
|
32011
32443
|
end
|
|
@@ -32049,6 +32481,21 @@ self.ScoringObjects[UnitName]=Score
|
|
|
32049
32481
|
end
|
|
32050
32482
|
return self
|
|
32051
32483
|
end
|
|
32484
|
+
function SCORING:AddScoreSetGroup(Set,Score)
|
|
32485
|
+
local set=Set:GetSetObjects()
|
|
32486
|
+
for _,_group in pairs(set)do
|
|
32487
|
+
if _group and _group:IsAlive()then
|
|
32488
|
+
self:AddScoreGroup(_group,Score)
|
|
32489
|
+
end
|
|
32490
|
+
end
|
|
32491
|
+
local function AddScore(group)
|
|
32492
|
+
self:AddScoreGroup(group,Score)
|
|
32493
|
+
end
|
|
32494
|
+
function Set:OnAfterAdded(From,Event,To,ObjectName,Object)
|
|
32495
|
+
AddScore(Object)
|
|
32496
|
+
end
|
|
32497
|
+
return self
|
|
32498
|
+
end
|
|
32052
32499
|
function SCORING:AddZoneScore(ScoreZone,Score)
|
|
32053
32500
|
local ZoneName=ScoreZone:GetName()
|
|
32054
32501
|
self.ScoringZones[ZoneName]={}
|
|
@@ -32380,7 +32827,7 @@ PlayerHit.TimeStamp=PlayerHit.TimeStamp or 0
|
|
|
32380
32827
|
PlayerHit.UNIT=PlayerHit.UNIT or TargetUNIT
|
|
32381
32828
|
if PlayerHit.UNIT.ThreatType==nil then
|
|
32382
32829
|
PlayerHit.ThreatLevel,PlayerHit.ThreatType=PlayerHit.UNIT:GetThreatLevel()
|
|
32383
|
-
if PlayerHit.ThreatType==nil then
|
|
32830
|
+
if PlayerHit.ThreatType==nil or PlayerHit.ThreatType==""then
|
|
32384
32831
|
PlayerHit.ThreatLevel=1
|
|
32385
32832
|
PlayerHit.ThreatType="Unknown"
|
|
32386
32833
|
end
|
|
@@ -32572,16 +33019,15 @@ self:F({ThreatLevel=ThreatPenalty,ThreatLevelTarget=ThreatLevelTarget,ThreatType
|
|
|
32572
33019
|
Player.Penalty=Player.Penalty+ThreatPenalty
|
|
32573
33020
|
TargetDestroy.Penalty=TargetDestroy.Penalty+ThreatPenalty
|
|
32574
33021
|
TargetDestroy.PenaltyDestroy=TargetDestroy.PenaltyDestroy+1
|
|
32575
|
-
self:OnKillPvP(Player,TargetPlayerName,true,TargetThreatLevel,Player.ThreatLevel,ThreatPenalty)
|
|
32576
33022
|
if Player.HitPlayers[TargetPlayerName]then
|
|
32577
|
-
self:OnKillPvP(
|
|
33023
|
+
self:OnKillPvP(PlayerName,TargetPlayerName,true)
|
|
32578
33024
|
MESSAGE:NewType(self.DisplayMessagePrefix.."Player '"..PlayerName.."' destroyed friendly player '"..TargetPlayerName.."' "..TargetUnitCategory.." ( "..ThreatTypeTarget.." ) "..
|
|
32579
33025
|
"Penalty: -"..ThreatPenalty.." = "..Player.Score-Player.Penalty,
|
|
32580
33026
|
MESSAGE.Type.Information)
|
|
32581
33027
|
:ToAllIf(self:IfMessagesDestroy()and self:IfMessagesToAll())
|
|
32582
33028
|
:ToCoalitionIf(InitCoalition,self:IfMessagesDestroy()and self:IfMessagesToCoalition())
|
|
32583
33029
|
else
|
|
32584
|
-
self:OnKillPvE(
|
|
33030
|
+
self:OnKillPvE(PlayerName,TargetUnitName,true,TargetThreatLevel,Player.ThreatLevel,ThreatPenalty)
|
|
32585
33031
|
MESSAGE:NewType(self.DisplayMessagePrefix.."Player '"..PlayerName.."' destroyed friendly target "..TargetUnitCategory.." ( "..ThreatTypeTarget.." ) "..
|
|
32586
33032
|
"Penalty: -"..ThreatPenalty.." = "..Player.Score-Player.Penalty,
|
|
32587
33033
|
MESSAGE.Type.Information)
|
|
@@ -32605,14 +33051,14 @@ Player.PlayerKills=Player.PlayerKills+1
|
|
|
32605
33051
|
else
|
|
32606
33052
|
Player.PlayerKills=1
|
|
32607
33053
|
end
|
|
32608
|
-
self:OnKillPvP(
|
|
33054
|
+
self:OnKillPvP(PlayerName,TargetPlayerName,false,TargetThreatLevel,Player.ThreatLevel,ThreatScore)
|
|
32609
33055
|
MESSAGE:NewType(self.DisplayMessagePrefix.."Player '"..PlayerName.."' destroyed enemy player '"..TargetPlayerName.."' "..TargetUnitCategory.." ( "..ThreatTypeTarget.." ) "..
|
|
32610
33056
|
"Score: +"..ThreatScore.." = "..Player.Score-Player.Penalty,
|
|
32611
33057
|
MESSAGE.Type.Information)
|
|
32612
33058
|
:ToAllIf(self:IfMessagesDestroy()and self:IfMessagesToAll())
|
|
32613
33059
|
:ToCoalitionIf(InitCoalition,self:IfMessagesDestroy()and self:IfMessagesToCoalition())
|
|
32614
33060
|
else
|
|
32615
|
-
self:OnKillPvE(
|
|
33061
|
+
self:OnKillPvE(PlayerName,TargetUnitName,false,TargetThreatLevel,Player.ThreatLevel,ThreatScore)
|
|
32616
33062
|
MESSAGE:NewType(self.DisplayMessagePrefix.."Player '"..PlayerName.."' destroyed enemy "..TargetUnitCategory.." ( "..ThreatTypeTarget.." ) "..
|
|
32617
33063
|
"Score: +"..ThreatScore.." = "..Player.Score-Player.Penalty,
|
|
32618
33064
|
MESSAGE.Type.Information)
|
|
@@ -32954,10 +33400,11 @@ end
|
|
|
32954
33400
|
end
|
|
32955
33401
|
function SCORING:OpenCSV(ScoringCSV)
|
|
32956
33402
|
self:F(ScoringCSV)
|
|
32957
|
-
if lfs and io and os and self.AutoSave then
|
|
33403
|
+
if lfs and io and os and self.AutoSave==true then
|
|
32958
33404
|
if ScoringCSV then
|
|
32959
33405
|
self.ScoringCSV=ScoringCSV
|
|
32960
|
-
local
|
|
33406
|
+
local path=self.AutoSavePath or lfs.writedir()..[[Logs\]]
|
|
33407
|
+
local fdir=path..self.ScoringCSV.." "..os.date("%Y-%m-%d %H-%M-%S")..".csv"
|
|
32961
33408
|
self.CSVFile,self.err=io.open(fdir,"w+")
|
|
32962
33409
|
if not self.CSVFile then
|
|
32963
33410
|
error("Error: Cannot open CSV file in "..lfs.writedir())
|
|
@@ -33036,9 +33483,9 @@ function SCORING:SwitchAutoSave(OnOff)
|
|
|
33036
33483
|
self.AutoSave=OnOff
|
|
33037
33484
|
return self
|
|
33038
33485
|
end
|
|
33039
|
-
function SCORING:OnKillPvP(
|
|
33486
|
+
function SCORING:OnKillPvP(PlayerName,TargetPlayerName,IsTeamKill,TargetThreatLevel,PlayerThreatLevel,Score)
|
|
33040
33487
|
end
|
|
33041
|
-
function SCORING:OnKillPvE(
|
|
33488
|
+
function SCORING:OnKillPvE(PlayerName,TargetUnitName,IsTeamKill,TargetThreatLevel,PlayerThreatLevel,Score)
|
|
33042
33489
|
end
|
|
33043
33490
|
CLEANUP_AIRBASE={
|
|
33044
33491
|
ClassName="CLEANUP_AIRBASE",
|
|
@@ -33528,7 +33975,6 @@ predpos:MarkToAll(string.format("height=%dm | heading=%d | velocity=%ddeg | Ropt
|
|
|
33528
33975
|
targetzone:DrawZone(coalition.side.BLUE,{0,0,1},0.2,nil,nil,3,true)
|
|
33529
33976
|
end
|
|
33530
33977
|
local seadset=SET_GROUP:New():FilterPrefixes(self.SEADGroupPrefixes):FilterZones({targetzone}):FilterOnce()
|
|
33531
|
-
local tgtcoord=targetzone:GetRandomPointVec2()
|
|
33532
33978
|
local tgtgrp=seadset:GetRandom()
|
|
33533
33979
|
local _targetgroup=nil
|
|
33534
33980
|
local _targetgroupname="none"
|
|
@@ -57204,7 +57650,7 @@ local rho=groovedata.Rho
|
|
|
57204
57650
|
local lineupError=groovedata.LUE
|
|
57205
57651
|
local glideslopeError=groovedata.GSE
|
|
57206
57652
|
local AoA=groovedata.AoA
|
|
57207
|
-
if rho<=RXX and playerData.step==AIRBOSS.PatternStep.GROOVE_XX and(math.abs(groovedata.Roll)<=4.0
|
|
57653
|
+
if rho<=RXX and playerData.step==AIRBOSS.PatternStep.GROOVE_XX and(math.abs(groovedata.Roll)<=4.0 and playerData.unit:IsInZone(self:_GetZoneLineup()))then
|
|
57208
57654
|
playerData.TIG0=timer.getTime()
|
|
57209
57655
|
self:RadioTransmission(self.LSORadio,self.LSOCall.CALLTHEBALL,nil,nil,nil,true)
|
|
57210
57656
|
playerData.Tlso=timer.getTime()
|
|
@@ -64426,6 +64872,8 @@ HasBeenDropped=false,
|
|
|
64426
64872
|
PerCrateMass=0,
|
|
64427
64873
|
Stock=nil,
|
|
64428
64874
|
Mark=nil,
|
|
64875
|
+
DontShowInMenu=false,
|
|
64876
|
+
Location=nil,
|
|
64429
64877
|
}
|
|
64430
64878
|
CTLD_CARGO.Enum={
|
|
64431
64879
|
VEHICLE="Vehicle",
|
|
@@ -64436,7 +64884,7 @@ REPAIR="Repair",
|
|
|
64436
64884
|
ENGINEERS="Engineers",
|
|
64437
64885
|
STATIC="Static",
|
|
64438
64886
|
}
|
|
64439
|
-
function CTLD_CARGO:New(ID,Name,Templates,Sorte,HasBeenMoved,LoadDirectly,CratesNeeded,Positionable,Dropped,PerCrateMass,Stock,Subcategory)
|
|
64887
|
+
function CTLD_CARGO:New(ID,Name,Templates,Sorte,HasBeenMoved,LoadDirectly,CratesNeeded,Positionable,Dropped,PerCrateMass,Stock,Subcategory,DontShowInMenu,Location)
|
|
64440
64888
|
local self=BASE:Inherit(self,BASE:New())
|
|
64441
64889
|
self:T({ID,Name,Templates,Sorte,HasBeenMoved,LoadDirectly,CratesNeeded,Positionable,Dropped})
|
|
64442
64890
|
self.ID=ID or math.random(100000,1000000)
|
|
@@ -64452,8 +64900,16 @@ self.PerCrateMass=PerCrateMass or 0
|
|
|
64452
64900
|
self.Stock=Stock or nil
|
|
64453
64901
|
self.Mark=nil
|
|
64454
64902
|
self.Subcategory=Subcategory or"Other"
|
|
64903
|
+
self.DontShowInMenu=DontShowInMenu or false
|
|
64904
|
+
if type(Location)=="string"then
|
|
64905
|
+
Location=ZONE:New(Location)
|
|
64906
|
+
end
|
|
64907
|
+
self.Location=Location
|
|
64455
64908
|
return self
|
|
64456
64909
|
end
|
|
64910
|
+
function CTLD_CARGO:GetLocation()
|
|
64911
|
+
return self.Location
|
|
64912
|
+
end
|
|
64457
64913
|
function CTLD_CARGO:GetID()
|
|
64458
64914
|
return self.ID
|
|
64459
64915
|
end
|
|
@@ -64763,10 +65219,12 @@ CTLD.UnitTypeCapabilities={
|
|
|
64763
65219
|
["Mi-24V"]={type="Mi-24V",crates=true,troops=true,cratelimit=2,trooplimit=8,length=18,cargoweightlimit=700},
|
|
64764
65220
|
["Hercules"]={type="Hercules",crates=true,troops=true,cratelimit=7,trooplimit=64,length=25,cargoweightlimit=19000},
|
|
64765
65221
|
["UH-60L"]={type="UH-60L",crates=true,troops=true,cratelimit=2,trooplimit=20,length=16,cargoweightlimit=3500},
|
|
65222
|
+
["MH-60R"]={type="MH-60R",crates=true,troops=true,cratelimit=2,trooplimit=20,length=16,cargoweightlimit=3500},
|
|
65223
|
+
["SH-60B"]={type="SH-60B",crates=true,troops=true,cratelimit=2,trooplimit=20,length=16,cargoweightlimit=3500},
|
|
64766
65224
|
["AH-64D_BLK_II"]={type="AH-64D_BLK_II",crates=false,troops=true,cratelimit=0,trooplimit=2,length=17,cargoweightlimit=200},
|
|
64767
65225
|
["Bronco-OV-10A"]={type="Bronco-OV-10A",crates=false,troops=true,cratelimit=0,trooplimit=5,length=13,cargoweightlimit=1450},
|
|
64768
65226
|
}
|
|
64769
|
-
CTLD.version="1.0.
|
|
65227
|
+
CTLD.version="1.0.51"
|
|
64770
65228
|
function CTLD:New(Coalition,Prefixes,Alias)
|
|
64771
65229
|
local self=BASE:Inherit(self,FSM:New())
|
|
64772
65230
|
BASE:T({Coalition,Prefixes,Alias})
|
|
@@ -65269,7 +65727,9 @@ local distancekeys={}
|
|
|
65269
65727
|
local extractdistance=self.CrateDistance*self.ExtractFactor
|
|
65270
65728
|
for k,v in pairs(self.DroppedTroops)do
|
|
65271
65729
|
local distance=self:_GetDistance(v:GetCoordinate(),unitcoord)
|
|
65272
|
-
|
|
65730
|
+
local TNow=timer.getTime()
|
|
65731
|
+
local vtime=v.ExtractTime or TNow-310
|
|
65732
|
+
if distance<=extractdistance and distance~=-1 and(TNow-vtime>300)then
|
|
65273
65733
|
nearestGroup=v
|
|
65274
65734
|
nearestGroupIndex=k
|
|
65275
65735
|
nearestDistance=distance
|
|
@@ -65312,22 +65772,36 @@ loaded.Cargo={}
|
|
|
65312
65772
|
end
|
|
65313
65773
|
if troopsize+numberonboard>trooplimit then
|
|
65314
65774
|
self:_SendMessage("Sorry, we\'re crammed already!",10,false,Group)
|
|
65775
|
+
nearestGroup.ExtractTime=0
|
|
65315
65776
|
else
|
|
65316
65777
|
self.CargoCounter=self.CargoCounter+1
|
|
65778
|
+
nearestGroup.ExtractTime=timer.getTime()
|
|
65317
65779
|
local loadcargotype=CTLD_CARGO:New(self.CargoCounter,Cargotype.Name,Cargotype.Templates,Cargotype.CargoType,true,true,Cargotype.CratesNeeded,nil,nil,Cargotype.PerCrateMass)
|
|
65318
65780
|
self:T({cargotype=loadcargotype})
|
|
65781
|
+
local running=math.floor(nearestDistance/4)+10
|
|
65319
65782
|
loaded.Troopsloaded=loaded.Troopsloaded+troopsize
|
|
65320
65783
|
table.insert(loaded.Cargo,loadcargotype)
|
|
65321
65784
|
self.Loaded_Cargo[unitname]=loaded
|
|
65322
|
-
self:_SendMessage
|
|
65785
|
+
self:ScheduleOnce(running,self._SendMessage,self,"Troops boarded!",10,false,Group)
|
|
65786
|
+
self:_SendMessage("Troops boarding!",10,false,Group)
|
|
65323
65787
|
self:_UpdateUnitCargoMass(Unit)
|
|
65324
|
-
self:__TroopsExtracted(
|
|
65788
|
+
self:__TroopsExtracted(running,Group,Unit,nearestGroup)
|
|
65789
|
+
local coord=Unit:GetCoordinate()or Group:GetCoordinate()
|
|
65790
|
+
local Point
|
|
65791
|
+
if coord then
|
|
65792
|
+
local heading=unit:GetHeading()or 0
|
|
65793
|
+
local Angle=math.floor((heading+160)%360)
|
|
65794
|
+
Point=coord:Translate(8,Angle):GetVec2()
|
|
65795
|
+
if Point then
|
|
65796
|
+
nearestGroup:RouteToVec2(Point,4)
|
|
65797
|
+
end
|
|
65798
|
+
end
|
|
65325
65799
|
if type(Cargotype.Templates)=="table"and Cargotype.Templates[2]then
|
|
65326
65800
|
for _,_key in pairs(Cargotype.Templates)do
|
|
65327
65801
|
table.insert(secondarygroups,_key)
|
|
65328
65802
|
end
|
|
65329
65803
|
end
|
|
65330
|
-
nearestGroup:Destroy(false)
|
|
65804
|
+
nearestGroup:Destroy(false,running)
|
|
65331
65805
|
end
|
|
65332
65806
|
end
|
|
65333
65807
|
end
|
|
@@ -65336,7 +65810,7 @@ for _,_group in pairs(nearestList)do
|
|
|
65336
65810
|
if _group and _group:IsAlive()then
|
|
65337
65811
|
local groupname=string.match(_group:GetName(),"(.+)-(.+)$")
|
|
65338
65812
|
if _name==groupname then
|
|
65339
|
-
_group:Destroy(false)
|
|
65813
|
+
_group:Destroy(false,15)
|
|
65340
65814
|
end
|
|
65341
65815
|
end
|
|
65342
65816
|
end
|
|
@@ -65378,6 +65852,16 @@ if not inzone then
|
|
|
65378
65852
|
self:_SendMessage("You are not close enough to a logistics zone!",10,false,Group)
|
|
65379
65853
|
if not self.debug then return self end
|
|
65380
65854
|
end
|
|
65855
|
+
local location=Cargo:GetLocation()
|
|
65856
|
+
if location then
|
|
65857
|
+
local unitcoord=Unit:GetCoordinate()or Group:GetCoordinate()
|
|
65858
|
+
if unitcoord then
|
|
65859
|
+
if not location:IsCoordinateInZone(unitcoord)then
|
|
65860
|
+
self:_SendMessage("The requested cargo is not available in this zone!",10,false,Group)
|
|
65861
|
+
if not self.debug then return self end
|
|
65862
|
+
end
|
|
65863
|
+
end
|
|
65864
|
+
end
|
|
65381
65865
|
local capabilities=self:_GetUnitCapabilities(Unit)
|
|
65382
65866
|
local canloadcratesno=capabilities.cratelimit
|
|
65383
65867
|
local loaddist=self.CrateDistance or 35
|
|
@@ -65928,9 +66412,9 @@ end
|
|
|
65928
66412
|
function CTLD:_GetUnitPositions(Coordinate,Radius,Heading,Template)
|
|
65929
66413
|
local Positions={}
|
|
65930
66414
|
local template=_DATABASE:GetGroupTemplate(Template)
|
|
65931
|
-
UTILS.PrintTableToLog(template)
|
|
65932
66415
|
local numbertroops=#template.units
|
|
65933
|
-
local
|
|
66416
|
+
local slightshift=math.abs(math.random(0,200)/100)
|
|
66417
|
+
local newcenter=Coordinate:Translate(Radius+slightshift,((Heading+270)%360))
|
|
65934
66418
|
for i=1,360,math.floor(360/numbertroops)do
|
|
65935
66419
|
local phead=((Heading+270+i)%360)
|
|
65936
66420
|
local post=newcenter:Translate(Radius,phead)
|
|
@@ -65942,7 +66426,6 @@ heading=phead,
|
|
|
65942
66426
|
}
|
|
65943
66427
|
table.insert(Positions,p1t)
|
|
65944
66428
|
end
|
|
65945
|
-
UTILS.PrintTableToLog(Positions)
|
|
65946
66429
|
return Positions
|
|
65947
66430
|
end
|
|
65948
66431
|
function CTLD:_UnloadTroops(Group,Unit)
|
|
@@ -66479,16 +66962,22 @@ end
|
|
|
66479
66962
|
for _,_entry in pairs(self.Cargo_Troops)do
|
|
66480
66963
|
local entry=_entry
|
|
66481
66964
|
local subcat=entry.Subcategory
|
|
66965
|
+
local noshow=entry.DontShowInMenu
|
|
66966
|
+
if not noshow then
|
|
66482
66967
|
menucount=menucount+1
|
|
66483
66968
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,entry.Name,subcatmenus[subcat],self._LoadTroops,self,_group,_unit,entry)
|
|
66484
66969
|
end
|
|
66970
|
+
end
|
|
66485
66971
|
else
|
|
66486
66972
|
for _,_entry in pairs(self.Cargo_Troops)do
|
|
66487
66973
|
local entry=_entry
|
|
66974
|
+
local noshow=entry.DontShowInMenu
|
|
66975
|
+
if not noshow then
|
|
66488
66976
|
menucount=menucount+1
|
|
66489
66977
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,entry.Name,troopsmenu,self._LoadTroops,self,_group,_unit,entry)
|
|
66490
66978
|
end
|
|
66491
66979
|
end
|
|
66980
|
+
end
|
|
66492
66981
|
local unloadmenu1=MENU_GROUP_COMMAND:New(_group,"Drop troops",toptroops,self._UnloadTroops,self,_group,_unit):Refresh()
|
|
66493
66982
|
local extractMenu1=MENU_GROUP_COMMAND:New(_group,"Extract troops",toptroops,self._ExtractTroops,self,_group,_unit):Refresh()
|
|
66494
66983
|
end
|
|
@@ -66505,33 +66994,61 @@ end
|
|
|
66505
66994
|
for _,_entry in pairs(self.Cargo_Crates)do
|
|
66506
66995
|
local entry=_entry
|
|
66507
66996
|
local subcat=entry.Subcategory
|
|
66997
|
+
local noshow=entry.DontShowInMenu
|
|
66998
|
+
local zone=entry.Location
|
|
66999
|
+
if not noshow then
|
|
66508
67000
|
menucount=menucount+1
|
|
66509
67001
|
local menutext=string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
|
|
67002
|
+
if zone then
|
|
67003
|
+
menutext=string.format("Crate %s (%dkg)[R]",entry.Name,entry.PerCrateMass or 0)
|
|
67004
|
+
end
|
|
66510
67005
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates,self,_group,_unit,entry)
|
|
66511
67006
|
end
|
|
67007
|
+
end
|
|
66512
67008
|
for _,_entry in pairs(self.Cargo_Statics)do
|
|
66513
67009
|
local entry=_entry
|
|
66514
67010
|
local subcat=entry.Subcategory
|
|
67011
|
+
local noshow=entry.DontShowInMenu
|
|
67012
|
+
local zone=entry.Location
|
|
67013
|
+
if not noshow then
|
|
66515
67014
|
menucount=menucount+1
|
|
66516
67015
|
local menutext=string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
|
|
67016
|
+
if zone then
|
|
67017
|
+
menutext=string.format("Crate %s (%dkg)[R]",entry.Name,entry.PerCrateMass or 0)
|
|
67018
|
+
end
|
|
66517
67019
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates,self,_group,_unit,entry)
|
|
66518
67020
|
end
|
|
67021
|
+
end
|
|
66519
67022
|
else
|
|
66520
67023
|
for _,_entry in pairs(self.Cargo_Crates)do
|
|
66521
67024
|
local entry=_entry
|
|
67025
|
+
local noshow=entry.DontShowInMenu
|
|
67026
|
+
local zone=entry.Location
|
|
67027
|
+
if not noshow then
|
|
66522
67028
|
menucount=menucount+1
|
|
66523
67029
|
local menutext=string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
|
|
67030
|
+
if zone then
|
|
67031
|
+
menutext=string.format("Crate %s (%dkg)[R]",entry.Name,entry.PerCrateMass or 0)
|
|
67032
|
+
end
|
|
66524
67033
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates,self,_group,_unit,entry)
|
|
66525
67034
|
end
|
|
67035
|
+
end
|
|
66526
67036
|
for _,_entry in pairs(self.Cargo_Statics)do
|
|
66527
67037
|
local entry=_entry
|
|
67038
|
+
local noshow=entry.DontShowInMenu
|
|
67039
|
+
local zone=entry.Location
|
|
67040
|
+
if not noshow then
|
|
66528
67041
|
menucount=menucount+1
|
|
66529
67042
|
local menutext=string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
|
|
67043
|
+
if zone then
|
|
67044
|
+
menutext=string.format("Crate %s (%dkg)[R]",entry.Name,entry.PerCrateMass or 0)
|
|
67045
|
+
end
|
|
66530
67046
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates,self,_group,_unit,entry)
|
|
66531
67047
|
end
|
|
66532
67048
|
end
|
|
67049
|
+
end
|
|
66533
67050
|
listmenu=MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates,self._ListCratesNearby,self,_group,_unit)
|
|
66534
|
-
removecrates=MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu,self._RemoveCratesNearby,self,_group,_unit)
|
|
67051
|
+
local removecrates=MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu,self._RemoveCratesNearby,self,_group,_unit)
|
|
66535
67052
|
local unloadmenu=MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates,self._UnloadCrates,self,_group,_unit)
|
|
66536
67053
|
if not self.nobuildmenu then
|
|
66537
67054
|
local buildmenu=MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates,self._BuildCrates,self,_group,_unit)
|
|
@@ -66580,23 +67097,23 @@ local cargo=CTLD_CARGO:New(self.CargoCounter,Name,Templates,Type,false,true,NoTr
|
|
|
66580
67097
|
table.insert(self.Cargo_Troops,cargo)
|
|
66581
67098
|
return self
|
|
66582
67099
|
end
|
|
66583
|
-
function CTLD:AddCratesCargo(Name,Templates,Type,NoCrates,PerCrateMass,Stock,SubCategory)
|
|
67100
|
+
function CTLD:AddCratesCargo(Name,Templates,Type,NoCrates,PerCrateMass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66584
67101
|
self:T(self.lid.." AddCratesCargo")
|
|
66585
67102
|
if not self:_CheckTemplates(Templates)then
|
|
66586
67103
|
self:E(self.lid.."Crates Cargo for "..Name.." has missing template(s)!")
|
|
66587
67104
|
return self
|
|
66588
67105
|
end
|
|
66589
67106
|
self.CargoCounter=self.CargoCounter+1
|
|
66590
|
-
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,Templates,Type,false,false,NoCrates,nil,nil,PerCrateMass,Stock,SubCategory)
|
|
67107
|
+
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,Templates,Type,false,false,NoCrates,nil,nil,PerCrateMass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66591
67108
|
table.insert(self.Cargo_Crates,cargo)
|
|
66592
67109
|
return self
|
|
66593
67110
|
end
|
|
66594
|
-
function CTLD:AddStaticsCargo(Name,Mass,Stock,SubCategory)
|
|
67111
|
+
function CTLD:AddStaticsCargo(Name,Mass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66595
67112
|
self:T(self.lid.." AddStaticsCargo")
|
|
66596
67113
|
self.CargoCounter=self.CargoCounter+1
|
|
66597
67114
|
local type=CTLD_CARGO.Enum.STATIC
|
|
66598
67115
|
local template=STATIC:FindByName(Name,true):GetTypeName()
|
|
66599
|
-
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,Stock,SubCategory)
|
|
67116
|
+
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66600
67117
|
table.insert(self.Cargo_Statics,cargo)
|
|
66601
67118
|
return self
|
|
66602
67119
|
end
|
|
@@ -66608,14 +67125,14 @@ local template=STATIC:FindByName(Name,true):GetTypeName()
|
|
|
66608
67125
|
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,1)
|
|
66609
67126
|
return cargo
|
|
66610
67127
|
end
|
|
66611
|
-
function CTLD:AddCratesRepair(Name,Template,Type,NoCrates,PerCrateMass,Stock,SubCategory)
|
|
67128
|
+
function CTLD:AddCratesRepair(Name,Template,Type,NoCrates,PerCrateMass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66612
67129
|
self:T(self.lid.." AddCratesRepair")
|
|
66613
67130
|
if not self:_CheckTemplates(Template)then
|
|
66614
67131
|
self:E(self.lid.."Repair Cargo for "..Name.." has a missing template!")
|
|
66615
67132
|
return self
|
|
66616
67133
|
end
|
|
66617
67134
|
self.CargoCounter=self.CargoCounter+1
|
|
66618
|
-
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,Template,Type,false,false,NoCrates,nil,nil,PerCrateMass,Stock,SubCategory)
|
|
67135
|
+
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,Template,Type,false,false,NoCrates,nil,nil,PerCrateMass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66619
67136
|
table.insert(self.Cargo_Crates,cargo)
|
|
66620
67137
|
return self
|
|
66621
67138
|
end
|
|
@@ -68437,7 +68954,8 @@ CSAR.AircraftType["Bell-47"]=2
|
|
|
68437
68954
|
CSAR.AircraftType["UH-60L"]=10
|
|
68438
68955
|
CSAR.AircraftType["AH-64D_BLK_II"]=2
|
|
68439
68956
|
CSAR.AircraftType["Bronco-OV-10A"]=2
|
|
68440
|
-
CSAR.
|
|
68957
|
+
CSAR.AircraftType["MH-60R"]=10
|
|
68958
|
+
CSAR.version="1.0.21"
|
|
68441
68959
|
function CSAR:New(Coalition,Template,Alias)
|
|
68442
68960
|
local self=BASE:Inherit(self,FSM:New())
|
|
68443
68961
|
BASE:T({Coalition,Template,Alias})
|
|
@@ -68549,7 +69067,7 @@ self.SRSchannel=300
|
|
|
68549
69067
|
self.SRSModulation=radio.modulation.AM
|
|
68550
69068
|
self.SRSport=5002
|
|
68551
69069
|
self.SRSCulture="en-GB"
|
|
68552
|
-
self.SRSVoice=
|
|
69070
|
+
self.SRSVoice=MSRS.Voices.Google.Standard.en_GB_Standard_B
|
|
68553
69071
|
self.SRSGPathToCredentials=nil
|
|
68554
69072
|
self.SRSVolume=1.0
|
|
68555
69073
|
self.SRSGender="male"
|
|
@@ -68925,7 +69443,7 @@ return self
|
|
|
68925
69443
|
end
|
|
68926
69444
|
if _place:GetCoalition()==self.coalition or _place:GetCoalition()==coalition.side.NEUTRAL then
|
|
68927
69445
|
self:__Landed(2,_event.IniUnitName,_place)
|
|
68928
|
-
self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true)
|
|
69446
|
+
self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true,true)
|
|
68929
69447
|
else
|
|
68930
69448
|
self:T(string.format("Airfield %d, Unit %d",_place:GetCoalition(),_unit:GetCoalition()))
|
|
68931
69449
|
end
|
|
@@ -69148,6 +69666,7 @@ local _found,_pilotable=self:_CheckNameInDownedPilots(_woundedGroupName)
|
|
|
69148
69666
|
local _pilotName=_pilotable.desc
|
|
69149
69667
|
local _reset=true
|
|
69150
69668
|
if(_distance<500)then
|
|
69669
|
+
self:T(self.lid.."[Pickup Debug] Helo closer than 500m: ".._lookupKeyHeli)
|
|
69151
69670
|
if self.heliCloseMessage[_lookupKeyHeli]==nil then
|
|
69152
69671
|
if self.autosmoke==true then
|
|
69153
69672
|
self:_DisplayMessageToSAR(_heliUnit,string.format("%s: %s. You\'re close now! Land or hover at the smoke.",self:_GetCustomCallSign(_heliName),_pilotName),self.messageTime,false,true)
|
|
@@ -69156,11 +69675,15 @@ self:_DisplayMessageToSAR(_heliUnit,string.format("%s: %s. You\'re close now! La
|
|
|
69156
69675
|
end
|
|
69157
69676
|
self.heliCloseMessage[_lookupKeyHeli]=true
|
|
69158
69677
|
end
|
|
69678
|
+
self:T(self.lid.."[Pickup Debug] Checking landed vs Hover for ".._lookupKeyHeli)
|
|
69159
69679
|
if not _heliUnit:InAir()then
|
|
69680
|
+
self:T(self.lid.."[Pickup Debug] Helo landed: ".._lookupKeyHeli)
|
|
69160
69681
|
if self.pilotRuntoExtractPoint==true then
|
|
69161
69682
|
if(_distance<self.extractDistance)then
|
|
69162
69683
|
local _time=self.landedStatus[_lookupKeyHeli]
|
|
69684
|
+
self:T(self.lid.."[Pickup Debug] Check pilot running or arrived ".._lookupKeyHeli)
|
|
69163
69685
|
if _time==nil then
|
|
69686
|
+
self:T(self.lid.."[Pickup Debug] Pilot running not arrived yet ".._lookupKeyHeli)
|
|
69164
69687
|
self.landedStatus[_lookupKeyHeli]=math.floor((_distance-self.loadDistance)/3.6)
|
|
69165
69688
|
_time=self.landedStatus[_lookupKeyHeli]
|
|
69166
69689
|
_woundedGroup:OptionAlarmStateGreen()
|
|
@@ -69170,11 +69693,15 @@ else
|
|
|
69170
69693
|
_time=self.landedStatus[_lookupKeyHeli]-10
|
|
69171
69694
|
self.landedStatus[_lookupKeyHeli]=_time
|
|
69172
69695
|
end
|
|
69696
|
+
self:T(self.lid.."[Pickup Debug] Pilot close enough? ".._lookupKeyHeli)
|
|
69173
69697
|
if _distance<self.loadDistance+5 or _distance<=13 then
|
|
69698
|
+
self:T(self.lid.."[Pickup Debug] Pilot close enough - YES ".._lookupKeyHeli)
|
|
69174
69699
|
if self.pilotmustopendoors and(self:_IsLoadingDoorOpen(_heliName)==false)then
|
|
69175
69700
|
self:_DisplayMessageToSAR(_heliUnit,"Open the door to let me in!",self.messageTime,true,true)
|
|
69701
|
+
self:T(self.lid.."[Pickup Debug] Door closed, try again next loop ".._lookupKeyHeli)
|
|
69176
69702
|
return false
|
|
69177
69703
|
else
|
|
69704
|
+
self:T(self.lid.."[Pickup Debug] Pick up Pilot ".._lookupKeyHeli)
|
|
69178
69705
|
self.landedStatus[_lookupKeyHeli]=nil
|
|
69179
69706
|
self:_PickupUnit(_heliUnit,_pilotName,_woundedGroup,_woundedGroupName)
|
|
69180
69707
|
return true
|
|
@@ -69182,28 +69709,36 @@ end
|
|
|
69182
69709
|
end
|
|
69183
69710
|
end
|
|
69184
69711
|
else
|
|
69712
|
+
self:T(self.lid.."[Pickup Debug] Helo landed, pilot NOT set to run to helo ".._lookupKeyHeli)
|
|
69185
69713
|
if(_distance<self.loadDistance)then
|
|
69714
|
+
self:T(self.lid.."[Pickup Debug] Helo close enough, door check ".._lookupKeyHeli)
|
|
69186
69715
|
if self.pilotmustopendoors and(self:_IsLoadingDoorOpen(_heliName)==false)then
|
|
69716
|
+
self:T(self.lid.."[Pickup Debug] Door closed, try again next loop ".._lookupKeyHeli)
|
|
69187
69717
|
self:_DisplayMessageToSAR(_heliUnit,"Open the door to let me in!",self.messageTime,true,true)
|
|
69188
69718
|
return false
|
|
69189
69719
|
else
|
|
69720
|
+
self:T(self.lid.."[Pickup Debug] Pick up Pilot ".._lookupKeyHeli)
|
|
69190
69721
|
self:_PickupUnit(_heliUnit,_pilotName,_woundedGroup,_woundedGroupName)
|
|
69191
69722
|
return true
|
|
69192
69723
|
end
|
|
69193
69724
|
end
|
|
69194
69725
|
end
|
|
69195
69726
|
else
|
|
69727
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering".._lookupKeyHeli)
|
|
69196
69728
|
local _unitsInHelicopter=self:_PilotsOnboard(_heliName)
|
|
69197
69729
|
local _maxUnits=self.AircraftType[_heliUnit:GetTypeName()]
|
|
69198
69730
|
if _maxUnits==nil then
|
|
69199
69731
|
_maxUnits=self.max_units
|
|
69200
69732
|
end
|
|
69733
|
+
self:T(self.lid.."[Pickup Debug] Check capacity and close enough for winching ".._lookupKeyHeli)
|
|
69201
69734
|
if _heliUnit:InAir()and _unitsInHelicopter+1<=_maxUnits then
|
|
69202
69735
|
if _distance<self.rescuehoverdistance then
|
|
69736
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering close enough ".._lookupKeyHeli)
|
|
69203
69737
|
local leaderheight=_woundedLeader:GetHeight()
|
|
69204
69738
|
if leaderheight<0 then leaderheight=0 end
|
|
69205
69739
|
local _height=_heliUnit:GetHeight()-leaderheight
|
|
69206
69740
|
if _height<=self.rescuehoverheight then
|
|
69741
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering low enough ".._lookupKeyHeli)
|
|
69207
69742
|
local _time=self.hoverStatus[_lookupKeyHeli]
|
|
69208
69743
|
if _time==nil then
|
|
69209
69744
|
self.hoverStatus[_lookupKeyHeli]=10
|
|
@@ -69212,21 +69747,28 @@ else
|
|
|
69212
69747
|
_time=self.hoverStatus[_lookupKeyHeli]-10
|
|
69213
69748
|
self.hoverStatus[_lookupKeyHeli]=_time
|
|
69214
69749
|
end
|
|
69750
|
+
self:T(self.lid.."[Pickup Debug] Check hover timer ".._lookupKeyHeli)
|
|
69215
69751
|
if _time>0 then
|
|
69752
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering not long enough ".._lookupKeyHeli)
|
|
69216
69753
|
self:_DisplayMessageToSAR(_heliUnit,"Hovering above ".._pilotName..". \n\nHold hover for ".._time.." seconds to winch them up. \n\nIf the countdown stops you\'re too far away!",self.messageTime,true)
|
|
69217
69754
|
else
|
|
69755
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering long enough - door check ".._lookupKeyHeli)
|
|
69218
69756
|
if self.pilotmustopendoors and(self:_IsLoadingDoorOpen(_heliName)==false)then
|
|
69219
69757
|
self:_DisplayMessageToSAR(_heliUnit,"Open the door to let me in!",self.messageTime,true,true)
|
|
69758
|
+
self:T(self.lid.."[Pickup Debug] Door closed, try again next loop ".._lookupKeyHeli)
|
|
69220
69759
|
return false
|
|
69221
69760
|
else
|
|
69222
69761
|
self.hoverStatus[_lookupKeyHeli]=nil
|
|
69223
69762
|
self:_PickupUnit(_heliUnit,_pilotName,_woundedGroup,_woundedGroupName)
|
|
69763
|
+
self:T(self.lid.."[Pickup Debug] Pilot picked up ".._lookupKeyHeli)
|
|
69224
69764
|
return true
|
|
69225
69765
|
end
|
|
69226
69766
|
end
|
|
69227
69767
|
_reset=false
|
|
69228
69768
|
else
|
|
69769
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering too high ".._lookupKeyHeli)
|
|
69229
69770
|
self:_DisplayMessageToSAR(_heliUnit,"Too high to winch ".._pilotName.." \nReduce height and hover for 10 seconds!",self.messageTime,true,true)
|
|
69771
|
+
self:T(self.lid.."[Pickup Debug] Hovering too high, try again next loop ".._lookupKeyHeli)
|
|
69230
69772
|
return false
|
|
69231
69773
|
end
|
|
69232
69774
|
end
|
|
@@ -69242,7 +69784,7 @@ else
|
|
|
69242
69784
|
return false
|
|
69243
69785
|
end
|
|
69244
69786
|
end
|
|
69245
|
-
function CSAR:_ScheduledSARFlight(heliname,groupname,isairport)
|
|
69787
|
+
function CSAR:_ScheduledSARFlight(heliname,groupname,isairport,noreschedule)
|
|
69246
69788
|
self:T(self.lid.." _ScheduledSARFlight")
|
|
69247
69789
|
self:T({heliname,groupname})
|
|
69248
69790
|
local _heliUnit=self:_GetSARHeli(heliname)
|
|
@@ -69256,17 +69798,25 @@ return
|
|
|
69256
69798
|
end
|
|
69257
69799
|
local _dist=self:_GetClosestMASH(_heliUnit)
|
|
69258
69800
|
if _dist==-1 then
|
|
69801
|
+
self:T(self.lid.."[Drop off debug] Check distance to MASH for "..heliname.." Distance can not be determined!")
|
|
69259
69802
|
return
|
|
69260
69803
|
end
|
|
69804
|
+
self:T(self.lid.."[Drop off debug] Check distance to MASH for "..heliname.." Distance km: "..math.floor(_dist/1000))
|
|
69261
69805
|
if(_dist<self.FARPRescueDistance or isairport)and _heliUnit:InAir()==false then
|
|
69806
|
+
self:T(self.lid.."[Drop off debug] Distance ok, door check")
|
|
69262
69807
|
if self.pilotmustopendoors and self:_IsLoadingDoorOpen(heliname)==false then
|
|
69263
69808
|
self:_DisplayMessageToSAR(_heliUnit,"Open the door to let me out!",self.messageTime,true,true)
|
|
69809
|
+
self:T(self.lid.."[Drop off debug] Door closed, try again next loop")
|
|
69264
69810
|
else
|
|
69811
|
+
self:T(self.lid.."[Drop off debug] Rescued!")
|
|
69265
69812
|
self:_RescuePilots(_heliUnit)
|
|
69266
69813
|
return
|
|
69267
69814
|
end
|
|
69268
69815
|
end
|
|
69269
|
-
|
|
69816
|
+
if not noreschedule then
|
|
69817
|
+
self:__Returning(5,heliname,_woundedGroupName,isairport)
|
|
69818
|
+
self:ScheduleOnce(5,self._ScheduledSARFlight,self,heliname,groupname,isairport,noreschedule)
|
|
69819
|
+
end
|
|
69270
69820
|
return self
|
|
69271
69821
|
end
|
|
69272
69822
|
function CSAR:_RescuePilots(_heliUnit)
|
|
@@ -69308,7 +69858,6 @@ self.msrs:SetCoordinate(coord)
|
|
|
69308
69858
|
end
|
|
69309
69859
|
_text=string.gsub(_text,"km"," kilometer")
|
|
69310
69860
|
_text=string.gsub(_text,"nm"," nautical miles")
|
|
69311
|
-
self:I("Voice = "..self.SRSVoice)
|
|
69312
69861
|
self.SRSQueue:NewTransmission(_text,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,self.SRSVoice,volume,label,coord)
|
|
69313
69862
|
end
|
|
69314
69863
|
return self
|
|
@@ -69670,7 +70219,7 @@ self:T(self.lid.." _RefreshRadioBeacons")
|
|
|
69670
70219
|
if self:_CountActiveDownedPilots()>0 then
|
|
69671
70220
|
local PilotTable=self.downedPilots
|
|
69672
70221
|
for _,_pilot in pairs(PilotTable)do
|
|
69673
|
-
self:T({_pilot})
|
|
70222
|
+
self:T({_pilot.name})
|
|
69674
70223
|
local pilot=_pilot
|
|
69675
70224
|
local group=pilot.group
|
|
69676
70225
|
local frequency=pilot.frequency or 0
|
|
@@ -69872,7 +70421,6 @@ return self
|
|
|
69872
70421
|
end
|
|
69873
70422
|
function CSAR:onbeforeReturning(From,Event,To,Heliname,Woundedgroupname,IsAirPort)
|
|
69874
70423
|
self:T({From,Event,To,Heliname,Woundedgroupname})
|
|
69875
|
-
self:_ScheduledSARFlight(Heliname,Woundedgroupname,IsAirPort)
|
|
69876
70424
|
return self
|
|
69877
70425
|
end
|
|
69878
70426
|
function CSAR:onbeforeRescued(From,Event,To,HeliUnit,HeliName,PilotsSaved)
|
|
@@ -70279,7 +70827,7 @@ local DistanceFromHomeBase=self.HomeAirbase:GetCoordinate():Get2DDistance(self.C
|
|
|
70279
70827
|
if not self:Is("Holding")and not self:Is("Returning")then
|
|
70280
70828
|
local DistanceFromHomeBase=self.HomeAirbase:GetCoordinate():Get2DDistance(self.Controllable:GetCoordinate())
|
|
70281
70829
|
if DistanceFromHomeBase>self.DisengageRadius then
|
|
70282
|
-
self:
|
|
70830
|
+
self:T(self.Controllable:GetName().." is too far from home base, RTB!")
|
|
70283
70831
|
self:Hold(300)
|
|
70284
70832
|
RTB=false
|
|
70285
70833
|
end
|
|
@@ -70288,10 +70836,10 @@ if not self:Is("Fuel")and not self:Is("Home")and not self:is("Refuelling")then
|
|
|
70288
70836
|
local Fuel=self.Controllable:GetFuelMin()
|
|
70289
70837
|
if Fuel<self.FuelThresholdPercentage then
|
|
70290
70838
|
if self.TankerName then
|
|
70291
|
-
self:
|
|
70839
|
+
self:T(self.Controllable:GetName().." is out of fuel: "..Fuel.." ... Refuelling at Tanker!")
|
|
70292
70840
|
self:Refuel()
|
|
70293
70841
|
else
|
|
70294
|
-
self:
|
|
70842
|
+
self:T(self.Controllable:GetName().." is out of fuel: "..Fuel.." ... RTB!")
|
|
70295
70843
|
local OldAIControllable=self.Controllable
|
|
70296
70844
|
local OrbitTask=OldAIControllable:TaskOrbitCircle(math.random(self.PatrolFloorAltitude,self.PatrolCeilingAltitude),self.PatrolMinSpeed)
|
|
70297
70845
|
local TimedOrbitTask=OldAIControllable:TaskControlled(OrbitTask,OldAIControllable:TaskCondition(nil,nil,nil,nil,self.OutOfFuelOrbitTime,nil))
|
|
@@ -70308,7 +70856,7 @@ end
|
|
|
70308
70856
|
local Damage=self.Controllable:GetLife()
|
|
70309
70857
|
local InitialLife=self.Controllable:GetLife0()
|
|
70310
70858
|
if(Damage/InitialLife)<self.PatrolDamageThreshold then
|
|
70311
|
-
self:
|
|
70859
|
+
self:T(self.Controllable:GetName().." is damaged: "..Damage.." ... RTB!")
|
|
70312
70860
|
self:Damaged()
|
|
70313
70861
|
RTB=true
|
|
70314
70862
|
self:SetStatusOff()
|
|
@@ -70323,7 +70871,7 @@ if self.IdleCount>=10 then
|
|
|
70323
70871
|
if Damage~=InitialLife then
|
|
70324
70872
|
self:Damaged()
|
|
70325
70873
|
else
|
|
70326
|
-
self:
|
|
70874
|
+
self:T(self.Controllable:GetName().." control lost! ")
|
|
70327
70875
|
self:LostControl()
|
|
70328
70876
|
end
|
|
70329
70877
|
else
|
|
@@ -70369,6 +70917,7 @@ self:ClearTargetDistance()
|
|
|
70369
70917
|
AIGroup:OptionProhibitAfterburner(true)
|
|
70370
70918
|
local EngageRoute={}
|
|
70371
70919
|
local FromCoord=AIGroup:GetCoordinate()
|
|
70920
|
+
if not FromCoord then return end
|
|
70372
70921
|
local ToTargetCoord=self.HomeAirbase:GetCoordinate()
|
|
70373
70922
|
local ToTargetVec3=ToTargetCoord:GetVec3()
|
|
70374
70923
|
ToTargetVec3.y=ToTargetCoord:GetLandHeight()+3000
|
|
@@ -70383,12 +70932,12 @@ local RTBSpeed=math.random(self.RTBMinSpeed,self.RTBMaxSpeed)
|
|
|
70383
70932
|
local Distance=FromCoord:Get2DDistance(ToTargetCoord2)
|
|
70384
70933
|
local ToAirbaseCoord=ToTargetCoord2
|
|
70385
70934
|
if Distance<5000 then
|
|
70386
|
-
self:
|
|
70935
|
+
self:T("RTB and near the airbase!")
|
|
70387
70936
|
self:Home()
|
|
70388
70937
|
return
|
|
70389
70938
|
end
|
|
70390
70939
|
if not AIGroup:InAir()==true then
|
|
70391
|
-
self:
|
|
70940
|
+
self:T("Not anymore in the air, considered Home.")
|
|
70392
70941
|
self:Home()
|
|
70393
70942
|
return
|
|
70394
70943
|
end
|
|
@@ -70418,15 +70967,17 @@ end
|
|
|
70418
70967
|
end
|
|
70419
70968
|
function AI_AIR:onafterHome(AIGroup,From,Event,To)
|
|
70420
70969
|
self:F({AIGroup,From,Event,To})
|
|
70421
|
-
self:
|
|
70970
|
+
self:T("Group "..self.Controllable:GetName().." ... Home! ( "..self:GetState().." )")
|
|
70422
70971
|
if AIGroup and AIGroup:IsAlive()then
|
|
70423
70972
|
end
|
|
70424
70973
|
end
|
|
70425
70974
|
function AI_AIR:onafterHold(AIGroup,From,Event,To,HoldTime)
|
|
70426
70975
|
self:F({AIGroup,From,Event,To})
|
|
70427
|
-
self:
|
|
70976
|
+
self:T("Group "..self.Controllable:GetName().." ... Holding! ( "..self:GetState().." )")
|
|
70428
70977
|
if AIGroup and AIGroup:IsAlive()then
|
|
70429
|
-
local
|
|
70978
|
+
local Coordinate=AIGroup:GetCoordinate()
|
|
70979
|
+
if Coordinate==nil then return end
|
|
70980
|
+
local OrbitTask=AIGroup:TaskOrbitCircle(math.random(self.PatrolFloorAltitude,self.PatrolCeilingAltitude),self.PatrolMinSpeed,Coordinate)
|
|
70430
70981
|
local TimedOrbitTask=AIGroup:TaskControlled(OrbitTask,AIGroup:TaskCondition(nil,nil,nil,nil,HoldTime,nil))
|
|
70431
70982
|
local RTBTask=AIGroup:TaskFunction("AI_AIR.RTBHold",self)
|
|
70432
70983
|
local OrbitHoldTask=AIGroup:TaskOrbitCircle(4000,self.PatrolMinSpeed)
|
|
@@ -70434,7 +70985,7 @@ AIGroup:SetTask(AIGroup:TaskCombo({TimedOrbitTask,RTBTask,OrbitHoldTask}),1)
|
|
|
70434
70985
|
end
|
|
70435
70986
|
end
|
|
70436
70987
|
function AI_AIR.Resume(AIGroup,Fsm)
|
|
70437
|
-
AIGroup:
|
|
70988
|
+
AIGroup:T({"AI_AIR.Resume:",AIGroup:GetName()})
|
|
70438
70989
|
if AIGroup:IsAlive()then
|
|
70439
70990
|
Fsm:__RTB(Fsm.TaskDelay)
|
|
70440
70991
|
end
|
|
@@ -70444,7 +70995,7 @@ self:F({AIGroup,From,Event,To})
|
|
|
70444
70995
|
if AIGroup and AIGroup:IsAlive()then
|
|
70445
70996
|
local Tanker=GROUP:FindByName(self.TankerName)
|
|
70446
70997
|
if Tanker and Tanker:IsAlive()and Tanker:IsAirPlane()then
|
|
70447
|
-
self:
|
|
70998
|
+
self:T("Group "..self.Controllable:GetName().." ... Refuelling! State="..self:GetState()..", Refuelling tanker "..self.TankerName)
|
|
70448
70999
|
local RefuelRoute={}
|
|
70449
71000
|
local FromRefuelCoord=AIGroup:GetCoordinate()
|
|
70450
71001
|
local ToRefuelCoord=Tanker:GetCoordinate()
|
|
@@ -70657,13 +71208,13 @@ end
|
|
|
70657
71208
|
end
|
|
70658
71209
|
end
|
|
70659
71210
|
function AI_AIR_ENGAGE.___EngageRoute(AIGroup,Fsm,AttackSetUnit)
|
|
70660
|
-
Fsm:
|
|
71211
|
+
Fsm:T(string.format("AI_AIR_ENGAGE.___EngageRoute: %s",tostring(AIGroup:GetName())))
|
|
70661
71212
|
if AIGroup and AIGroup:IsAlive()then
|
|
70662
71213
|
Fsm:__EngageRoute(Fsm.TaskDelay or 0.1,AttackSetUnit)
|
|
70663
71214
|
end
|
|
70664
71215
|
end
|
|
70665
71216
|
function AI_AIR_ENGAGE:onafterEngageRoute(DefenderGroup,From,Event,To,AttackSetUnit)
|
|
70666
|
-
self:
|
|
71217
|
+
self:T({DefenderGroup,From,Event,To,AttackSetUnit})
|
|
70667
71218
|
local DefenderGroupName=DefenderGroup:GetName()
|
|
70668
71219
|
self.AttackSetUnit=AttackSetUnit
|
|
70669
71220
|
local AttackCount=AttackSetUnit:CountAlive()
|
|
@@ -70673,7 +71224,11 @@ local EngageAltitude=math.random(self.EngageFloorAltitude,self.EngageCeilingAlti
|
|
|
70673
71224
|
local EngageSpeed=math.random(self.EngageMinSpeed,self.EngageMaxSpeed)
|
|
70674
71225
|
local DefenderCoord=DefenderGroup:GetPointVec3()
|
|
70675
71226
|
DefenderCoord:SetY(EngageAltitude)
|
|
70676
|
-
local TargetCoord=AttackSetUnit:
|
|
71227
|
+
local TargetCoord=AttackSetUnit:GetRandomSurely():GetPointVec3()
|
|
71228
|
+
if TargetCoord==nil then
|
|
71229
|
+
self:Return()
|
|
71230
|
+
return
|
|
71231
|
+
end
|
|
70677
71232
|
TargetCoord:SetY(EngageAltitude)
|
|
70678
71233
|
local TargetDistance=DefenderCoord:Get2DDistance(TargetCoord)
|
|
70679
71234
|
local EngageDistance=(DefenderGroup:IsHelicopter()and 5000)or(DefenderGroup:IsAirPlane()and 10000)
|
|
@@ -70697,12 +71252,12 @@ DefenderGroup:Route(EngageRoute,self.TaskDelay or 0.1)
|
|
|
70697
71252
|
end
|
|
70698
71253
|
end
|
|
70699
71254
|
else
|
|
70700
|
-
self:
|
|
71255
|
+
self:T(DefenderGroupName..": No targets found -> Going RTB")
|
|
70701
71256
|
self:Return()
|
|
70702
71257
|
end
|
|
70703
71258
|
end
|
|
70704
71259
|
function AI_AIR_ENGAGE.___Engage(AIGroup,Fsm,AttackSetUnit)
|
|
70705
|
-
Fsm:
|
|
71260
|
+
Fsm:T(string.format("AI_AIR_ENGAGE.___Engage: %s",tostring(AIGroup:GetName())))
|
|
70706
71261
|
if AIGroup and AIGroup:IsAlive()then
|
|
70707
71262
|
local delay=Fsm.TaskDelay or 0.1
|
|
70708
71263
|
Fsm:__Engage(delay,AttackSetUnit)
|
|
@@ -70720,7 +71275,7 @@ local EngageAltitude=math.random(self.EngageFloorAltitude or 500,self.EngageCeil
|
|
|
70720
71275
|
local EngageSpeed=math.random(self.EngageMinSpeed,self.EngageMaxSpeed)
|
|
70721
71276
|
local DefenderCoord=DefenderGroup:GetPointVec3()
|
|
70722
71277
|
DefenderCoord:SetY(EngageAltitude)
|
|
70723
|
-
local TargetCoord=AttackSetUnit:
|
|
71278
|
+
local TargetCoord=AttackSetUnit:GetRandomSurely():GetPointVec3()
|
|
70724
71279
|
if not TargetCoord then
|
|
70725
71280
|
self:Return()
|
|
70726
71281
|
return
|
|
@@ -70740,12 +71295,12 @@ EngageRoute[#EngageRoute+1]=ToWP
|
|
|
70740
71295
|
if TargetDistance<=EngageDistance*9 then
|
|
70741
71296
|
local AttackUnitTasks=self:CreateAttackUnitTasks(AttackSetUnit,DefenderGroup,EngageAltitude)
|
|
70742
71297
|
if#AttackUnitTasks==0 then
|
|
70743
|
-
self:
|
|
71298
|
+
self:T(DefenderGroupName..": No valid targets found -> Going RTB")
|
|
70744
71299
|
self:Return()
|
|
70745
71300
|
return
|
|
70746
71301
|
else
|
|
70747
71302
|
local text=string.format("%s: Engaging targets at distance %.2f NM",DefenderGroupName,UTILS.MetersToNM(TargetDistance))
|
|
70748
|
-
self:
|
|
71303
|
+
self:T(text)
|
|
70749
71304
|
DefenderGroup:OptionROEOpenFire()
|
|
70750
71305
|
DefenderGroup:OptionROTEvadeFire()
|
|
70751
71306
|
DefenderGroup:OptionKeepWeaponsOnThreat()
|
|
@@ -70757,7 +71312,7 @@ EngageRoute[#EngageRoute].task=DefenderGroup:TaskCombo(AttackTasks)
|
|
|
70757
71312
|
DefenderGroup:Route(EngageRoute,self.TaskDelay or 0.1)
|
|
70758
71313
|
end
|
|
70759
71314
|
else
|
|
70760
|
-
self:
|
|
71315
|
+
self:T(DefenderGroupName..": No targets found -> returning.")
|
|
70761
71316
|
self:Return()
|
|
70762
71317
|
return
|
|
70763
71318
|
end
|
|
@@ -71018,12 +71573,12 @@ end
|
|
|
71018
71573
|
end
|
|
71019
71574
|
function AI_A2A_DISPATCHER:OnEventBaseCaptured(EventData)
|
|
71020
71575
|
local AirbaseName=EventData.PlaceName
|
|
71021
|
-
self:
|
|
71576
|
+
self:T("Captured "..AirbaseName)
|
|
71022
71577
|
for SquadronName,Squadron in pairs(self.DefenderSquadrons)do
|
|
71023
71578
|
if Squadron.AirbaseName==AirbaseName then
|
|
71024
71579
|
Squadron.ResourceCount=-999
|
|
71025
71580
|
Squadron.Captured=true
|
|
71026
|
-
self:
|
|
71581
|
+
self:T("Squadron "..SquadronName.." captured.")
|
|
71027
71582
|
end
|
|
71028
71583
|
end
|
|
71029
71584
|
end
|
|
@@ -71260,7 +71815,7 @@ Cap.PatrolCeilingAltitude=PatrolCeilingAltitude
|
|
|
71260
71815
|
Cap.PatrolAltType=PatrolAltType
|
|
71261
71816
|
Cap.EngageAltType=EngageAltType
|
|
71262
71817
|
self:SetSquadronCapInterval(SquadronName,self.DefenderDefault.CapLimit,self.DefenderDefault.CapMinSeconds,self.DefenderDefault.CapMaxSeconds,1)
|
|
71263
|
-
self:
|
|
71818
|
+
self:T({CAP={SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,Zone,PatrolMinSpeed,PatrolMaxSpeed,PatrolFloorAltitude,PatrolCeilingAltitude,PatrolAltType,EngageAltType}})
|
|
71264
71819
|
local RecceSet=self.Detection:GetDetectionSet()
|
|
71265
71820
|
RecceSet:FilterPrefixes(DefenderSquadron.TemplatePrefixes)
|
|
71266
71821
|
RecceSet:FilterStart()
|
|
@@ -71378,7 +71933,7 @@ Intercept.EngageMaxSpeed=EngageMaxSpeed
|
|
|
71378
71933
|
Intercept.EngageFloorAltitude=EngageFloorAltitude
|
|
71379
71934
|
Intercept.EngageCeilingAltitude=EngageCeilingAltitude
|
|
71380
71935
|
Intercept.EngageAltType=EngageAltType
|
|
71381
|
-
self:
|
|
71936
|
+
self:T({GCI={SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
71382
71937
|
end
|
|
71383
71938
|
function AI_A2A_DISPATCHER:SetSquadronGci(SquadronName,EngageMinSpeed,EngageMaxSpeed)
|
|
71384
71939
|
self.DefenderSquadrons[SquadronName]=self.DefenderSquadrons[SquadronName]or{}
|
|
@@ -72255,22 +72810,22 @@ table.insert(AirbaseNames,AirbaseName)
|
|
|
72255
72810
|
end
|
|
72256
72811
|
end
|
|
72257
72812
|
self.Templates=SET_GROUP:New():FilterPrefixes(TemplatePrefixes):FilterOnce()
|
|
72258
|
-
self:
|
|
72259
|
-
self:
|
|
72813
|
+
self:T({Airbases=AirbaseNames})
|
|
72814
|
+
self:T("Defining Templates for Airbases ...")
|
|
72260
72815
|
for AirbaseID,AirbaseName in pairs(AirbaseNames)do
|
|
72261
72816
|
local Airbase=_DATABASE:FindAirbase(AirbaseName)
|
|
72262
72817
|
local AirbaseName=Airbase:GetName()
|
|
72263
72818
|
local AirbaseCoord=Airbase:GetCoordinate()
|
|
72264
72819
|
local AirbaseZone=ZONE_RADIUS:New("Airbase",AirbaseCoord:GetVec2(),3000)
|
|
72265
72820
|
local Templates=nil
|
|
72266
|
-
self:
|
|
72821
|
+
self:T({Airbase=AirbaseName})
|
|
72267
72822
|
for TemplateID,Template in pairs(self.Templates:GetSet())do
|
|
72268
72823
|
local Template=Template
|
|
72269
72824
|
local TemplateCoord=Template:GetCoordinate()
|
|
72270
72825
|
if AirbaseZone:IsVec2InZone(TemplateCoord:GetVec2())then
|
|
72271
72826
|
Templates=Templates or{}
|
|
72272
72827
|
table.insert(Templates,Template:GetName())
|
|
72273
|
-
self:
|
|
72828
|
+
self:T({Template=Template:GetName()})
|
|
72274
72829
|
end
|
|
72275
72830
|
end
|
|
72276
72831
|
if Templates then
|
|
@@ -72280,12 +72835,12 @@ end
|
|
|
72280
72835
|
self.CAPTemplates=SET_GROUP:New()
|
|
72281
72836
|
self.CAPTemplates:FilterPrefixes(CapPrefixes)
|
|
72282
72837
|
self.CAPTemplates:FilterOnce()
|
|
72283
|
-
self:
|
|
72838
|
+
self:T("Setting up CAP ...")
|
|
72284
72839
|
for CAPID,CAPTemplate in pairs(self.CAPTemplates:GetSet())do
|
|
72285
72840
|
local CAPZone=ZONE_POLYGON:New(CAPTemplate:GetName(),CAPTemplate)
|
|
72286
72841
|
local AirbaseDistance=99999999
|
|
72287
72842
|
local AirbaseClosest=nil
|
|
72288
|
-
self:
|
|
72843
|
+
self:T({CAPZoneGroup=CAPID})
|
|
72289
72844
|
for AirbaseID,AirbaseName in pairs(AirbaseNames)do
|
|
72290
72845
|
local Airbase=_DATABASE:FindAirbase(AirbaseName)
|
|
72291
72846
|
local AirbaseName=Airbase:GetName()
|
|
@@ -72293,7 +72848,7 @@ local AirbaseCoord=Airbase:GetCoordinate()
|
|
|
72293
72848
|
local Squadron=self.DefenderSquadrons[AirbaseName]
|
|
72294
72849
|
if Squadron then
|
|
72295
72850
|
local Distance=AirbaseCoord:Get2DDistance(CAPZone:GetCoordinate())
|
|
72296
|
-
self:
|
|
72851
|
+
self:T({AirbaseDistance=Distance})
|
|
72297
72852
|
if Distance<AirbaseDistance then
|
|
72298
72853
|
AirbaseDistance=Distance
|
|
72299
72854
|
AirbaseClosest=Airbase
|
|
@@ -72301,19 +72856,19 @@ end
|
|
|
72301
72856
|
end
|
|
72302
72857
|
end
|
|
72303
72858
|
if AirbaseClosest then
|
|
72304
|
-
self:
|
|
72859
|
+
self:T({CAPAirbase=AirbaseClosest:GetName()})
|
|
72305
72860
|
self:SetSquadronCap(AirbaseClosest:GetName(),CAPZone,6000,10000,500,800,800,1200,"RADIO")
|
|
72306
72861
|
self:SetSquadronCapInterval(AirbaseClosest:GetName(),CapLimit,300,600,1)
|
|
72307
72862
|
end
|
|
72308
72863
|
end
|
|
72309
|
-
self:
|
|
72864
|
+
self:T("Setting up GCI ...")
|
|
72310
72865
|
for AirbaseID,AirbaseName in pairs(AirbaseNames)do
|
|
72311
72866
|
local Airbase=_DATABASE:FindAirbase(AirbaseName)
|
|
72312
72867
|
local AirbaseName=Airbase:GetName()
|
|
72313
72868
|
local Squadron=self.DefenderSquadrons[AirbaseName]
|
|
72314
72869
|
self:F({Airbase=AirbaseName})
|
|
72315
72870
|
if Squadron then
|
|
72316
|
-
self:
|
|
72871
|
+
self:T({GCIAirbase=AirbaseName})
|
|
72317
72872
|
self:SetSquadronGci(AirbaseName,800,1200)
|
|
72318
72873
|
end
|
|
72319
72874
|
end
|
|
@@ -72476,7 +73031,7 @@ DefenderSquadron.Resource={}
|
|
|
72476
73031
|
for Resource=1,DefenderSquadron.ResourceCount or 0 do
|
|
72477
73032
|
self:ResourcePark(DefenderSquadron)
|
|
72478
73033
|
end
|
|
72479
|
-
self:
|
|
73034
|
+
self:T("Parked resources for squadron "..DefenderSquadron.Name)
|
|
72480
73035
|
end
|
|
72481
73036
|
end
|
|
72482
73037
|
function AI_A2G_DISPATCHER:Lock(DetectedItemIndex)
|
|
@@ -72520,12 +73075,12 @@ end
|
|
|
72520
73075
|
end
|
|
72521
73076
|
function AI_A2G_DISPATCHER:OnEventBaseCaptured(EventData)
|
|
72522
73077
|
local AirbaseName=EventData.PlaceName
|
|
72523
|
-
self:
|
|
73078
|
+
self:T("Captured "..AirbaseName)
|
|
72524
73079
|
for SquadronName,Squadron in pairs(self.DefenderSquadrons)do
|
|
72525
73080
|
if Squadron.AirbaseName==AirbaseName then
|
|
72526
73081
|
Squadron.ResourceCount=-999
|
|
72527
73082
|
Squadron.Captured=true
|
|
72528
|
-
self:
|
|
73083
|
+
self:T("Squadron "..SquadronName.." captured.")
|
|
72529
73084
|
end
|
|
72530
73085
|
end
|
|
72531
73086
|
end
|
|
@@ -72546,7 +73101,7 @@ if DefenderSize==1 then
|
|
|
72546
73101
|
self:RemoveDefenderFromSquadron(Squadron,Defender)
|
|
72547
73102
|
end
|
|
72548
73103
|
DefenderUnit:Destroy()
|
|
72549
|
-
self:ResourcePark(Squadron
|
|
73104
|
+
self:ResourcePark(Squadron)
|
|
72550
73105
|
return
|
|
72551
73106
|
end
|
|
72552
73107
|
if DefenderUnit:GetLife()~=DefenderUnit:GetLife0()then
|
|
@@ -72569,7 +73124,7 @@ if DefenderSize==1 then
|
|
|
72569
73124
|
self:RemoveDefenderFromSquadron(Squadron,Defender)
|
|
72570
73125
|
end
|
|
72571
73126
|
DefenderUnit:Destroy()
|
|
72572
|
-
self:ResourcePark(Squadron
|
|
73127
|
+
self:ResourcePark(Squadron)
|
|
72573
73128
|
end
|
|
72574
73129
|
end
|
|
72575
73130
|
end
|
|
@@ -72592,7 +73147,7 @@ self.DisengageRadius=DisengageRadius or 300000
|
|
|
72592
73147
|
return self
|
|
72593
73148
|
end
|
|
72594
73149
|
function AI_A2G_DISPATCHER:SetDefenseRadius(DefenseRadius)
|
|
72595
|
-
self.DefenseRadius=DefenseRadius or
|
|
73150
|
+
self.DefenseRadius=DefenseRadius or 40000
|
|
72596
73151
|
self.Detection:SetAcceptRange(self.DefenseRadius)
|
|
72597
73152
|
return self
|
|
72598
73153
|
end
|
|
@@ -72861,7 +73416,7 @@ Sead.EngageFloorAltitude=EngageFloorAltitude or 500
|
|
|
72861
73416
|
Sead.EngageCeilingAltitude=EngageCeilingAltitude or 1000
|
|
72862
73417
|
Sead.EngageAltType=EngageAltType
|
|
72863
73418
|
Sead.Defend=true
|
|
72864
|
-
self:
|
|
73419
|
+
self:T({SEAD={SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72865
73420
|
return self
|
|
72866
73421
|
end
|
|
72867
73422
|
function AI_A2G_DISPATCHER:SetSquadronSead(SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude)
|
|
@@ -72888,7 +73443,7 @@ SeadPatrol.PatrolAltType=PatrolAltType
|
|
|
72888
73443
|
SeadPatrol.EngageAltType=EngageAltType
|
|
72889
73444
|
SeadPatrol.Patrol=true
|
|
72890
73445
|
self:SetSquadronPatrolInterval(SquadronName,self.DefenderDefault.PatrolLimit,self.DefenderDefault.PatrolMinSeconds,self.DefenderDefault.PatrolMaxSeconds,1,"SEAD")
|
|
72891
|
-
self:
|
|
73446
|
+
self:T({SEAD={Zone:GetName(),PatrolMinSpeed,PatrolMaxSpeed,PatrolFloorAltitude,PatrolCeilingAltitude,PatrolAltType,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72892
73447
|
end
|
|
72893
73448
|
function AI_A2G_DISPATCHER:SetSquadronSeadPatrol(SquadronName,Zone,FloorAltitude,CeilingAltitude,PatrolMinSpeed,PatrolMaxSpeed,EngageMinSpeed,EngageMaxSpeed,AltType)
|
|
72894
73449
|
self:SetSquadronSeadPatrol2(SquadronName,Zone,PatrolMinSpeed,PatrolMaxSpeed,FloorAltitude,CeilingAltitude,AltType,EngageMinSpeed,EngageMaxSpeed,FloorAltitude,CeilingAltitude,AltType)
|
|
@@ -72904,7 +73459,7 @@ Cas.EngageFloorAltitude=EngageFloorAltitude or 500
|
|
|
72904
73459
|
Cas.EngageCeilingAltitude=EngageCeilingAltitude or 1000
|
|
72905
73460
|
Cas.EngageAltType=EngageAltType
|
|
72906
73461
|
Cas.Defend=true
|
|
72907
|
-
self:
|
|
73462
|
+
self:T({CAS={SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72908
73463
|
return self
|
|
72909
73464
|
end
|
|
72910
73465
|
function AI_A2G_DISPATCHER:SetSquadronCas(SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude)
|
|
@@ -72931,7 +73486,7 @@ CasPatrol.PatrolAltType=PatrolAltType
|
|
|
72931
73486
|
CasPatrol.EngageAltType=EngageAltType
|
|
72932
73487
|
CasPatrol.Patrol=true
|
|
72933
73488
|
self:SetSquadronPatrolInterval(SquadronName,self.DefenderDefault.PatrolLimit,self.DefenderDefault.PatrolMinSeconds,self.DefenderDefault.PatrolMaxSeconds,1,"CAS")
|
|
72934
|
-
self:
|
|
73489
|
+
self:T({CAS={Zone:GetName(),PatrolMinSpeed,PatrolMaxSpeed,PatrolFloorAltitude,PatrolCeilingAltitude,PatrolAltType,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72935
73490
|
end
|
|
72936
73491
|
function AI_A2G_DISPATCHER:SetSquadronCasPatrol(SquadronName,Zone,FloorAltitude,CeilingAltitude,PatrolMinSpeed,PatrolMaxSpeed,EngageMinSpeed,EngageMaxSpeed,AltType)
|
|
72937
73492
|
self:SetSquadronCasPatrol2(SquadronName,Zone,PatrolMinSpeed,PatrolMaxSpeed,FloorAltitude,CeilingAltitude,AltType,EngageMinSpeed,EngageMaxSpeed,FloorAltitude,CeilingAltitude,AltType)
|
|
@@ -72947,7 +73502,7 @@ Bai.EngageFloorAltitude=EngageFloorAltitude or 500
|
|
|
72947
73502
|
Bai.EngageCeilingAltitude=EngageCeilingAltitude or 1000
|
|
72948
73503
|
Bai.EngageAltType=EngageAltType
|
|
72949
73504
|
Bai.Defend=true
|
|
72950
|
-
self:
|
|
73505
|
+
self:T({BAI={SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72951
73506
|
return self
|
|
72952
73507
|
end
|
|
72953
73508
|
function AI_A2G_DISPATCHER:SetSquadronBai(SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude)
|
|
@@ -72974,7 +73529,7 @@ BaiPatrol.PatrolAltType=PatrolAltType
|
|
|
72974
73529
|
BaiPatrol.EngageAltType=EngageAltType
|
|
72975
73530
|
BaiPatrol.Patrol=true
|
|
72976
73531
|
self:SetSquadronPatrolInterval(SquadronName,self.DefenderDefault.PatrolLimit,self.DefenderDefault.PatrolMinSeconds,self.DefenderDefault.PatrolMaxSeconds,1,"BAI")
|
|
72977
|
-
self:
|
|
73532
|
+
self:T({BAI={Zone:GetName(),PatrolMinSpeed,PatrolMaxSpeed,PatrolFloorAltitude,PatrolCeilingAltitude,PatrolAltType,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72978
73533
|
end
|
|
72979
73534
|
function AI_A2G_DISPATCHER:SetSquadronBaiPatrol(SquadronName,Zone,FloorAltitude,CeilingAltitude,PatrolMinSpeed,PatrolMaxSpeed,EngageMinSpeed,EngageMaxSpeed,AltType)
|
|
72980
73535
|
self:SetSquadronBaiPatrol2(SquadronName,Zone,PatrolMinSpeed,PatrolMaxSpeed,FloorAltitude,CeilingAltitude,AltType,EngageMinSpeed,EngageMaxSpeed,FloorAltitude,CeilingAltitude,AltType)
|
|
@@ -73514,7 +74069,7 @@ local DefenderName=DefenderGroup:GetCallsign()
|
|
|
73514
74069
|
local Dispatcher=AI_A2G_Fsm:GetDispatcher()
|
|
73515
74070
|
local Squadron=Dispatcher:GetSquadronFromDefender(DefenderGroup)
|
|
73516
74071
|
if Squadron then
|
|
73517
|
-
local FirstUnit=AttackSetUnit:
|
|
74072
|
+
local FirstUnit=AttackSetUnit:GetRandomSurely()
|
|
73518
74073
|
local Coordinate=FirstUnit:GetCoordinate()
|
|
73519
74074
|
if self.SetSendPlayerMessages then
|
|
73520
74075
|
Dispatcher:MessageToPlayers(Squadron,DefenderName..", on route to ground target at "..Coordinate:ToStringA2G(DefenderGroup),DefenderGroup)
|
|
@@ -74333,7 +74888,7 @@ if self.Controllable and self.Controllable:IsAlive()then
|
|
|
74333
74888
|
local RTB=false
|
|
74334
74889
|
local Fuel=self.Controllable:GetFuelMin()
|
|
74335
74890
|
if Fuel<self.PatrolFuelThresholdPercentage then
|
|
74336
|
-
self:
|
|
74891
|
+
self:T(self.Controllable:GetName().." is out of fuel:"..Fuel..", RTB!")
|
|
74337
74892
|
local OldAIControllable=self.Controllable
|
|
74338
74893
|
local OrbitTask=OldAIControllable:TaskOrbitCircle(math.random(self.PatrolFloorAltitude,self.PatrolCeilingAltitude),self.PatrolMinSpeed)
|
|
74339
74894
|
local TimedOrbitTask=OldAIControllable:TaskControlled(OrbitTask,OldAIControllable:TaskCondition(nil,nil,nil,nil,self.PatrolOutOfFuelOrbitTime,nil))
|
|
@@ -74343,7 +74898,7 @@ else
|
|
|
74343
74898
|
end
|
|
74344
74899
|
local Damage=self.Controllable:GetLife()
|
|
74345
74900
|
if Damage<=self.PatrolDamageThreshold then
|
|
74346
|
-
self:
|
|
74901
|
+
self:T(self.Controllable:GetName().." is damaged:"..Damage..", RTB!")
|
|
74347
74902
|
RTB=true
|
|
74348
74903
|
end
|
|
74349
74904
|
if RTB==true then
|
|
@@ -76509,11 +77064,11 @@ function AI_ESCORT_DISPATCHER:OnEventExit(EventData)
|
|
|
76509
77064
|
local PlayerGroupName=EventData.IniGroupName
|
|
76510
77065
|
local PlayerGroup=EventData.IniGroup
|
|
76511
77066
|
local PlayerUnit=EventData.IniUnit
|
|
76512
|
-
self:
|
|
76513
|
-
self:
|
|
76514
|
-
self:
|
|
76515
|
-
self:
|
|
76516
|
-
self:
|
|
77067
|
+
self:T({EscortAirbase=self.EscortAirbase})
|
|
77068
|
+
self:T({PlayerGroupName=PlayerGroupName})
|
|
77069
|
+
self:T({PlayerGroup=PlayerGroup})
|
|
77070
|
+
self:T({FirstGroup=self.CarrierSet:GetFirst()})
|
|
77071
|
+
self:T({FindGroup=self.CarrierSet:FindGroup(PlayerGroupName)})
|
|
76517
77072
|
if self.CarrierSet:FindGroup(PlayerGroupName)then
|
|
76518
77073
|
if self.AI_Escorts[PlayerGroupName]then
|
|
76519
77074
|
self.AI_Escorts[PlayerGroupName]:Stop()
|
|
@@ -76525,16 +77080,16 @@ function AI_ESCORT_DISPATCHER:OnEventBirth(EventData)
|
|
|
76525
77080
|
local PlayerGroupName=EventData.IniGroupName
|
|
76526
77081
|
local PlayerGroup=EventData.IniGroup
|
|
76527
77082
|
local PlayerUnit=EventData.IniUnit
|
|
76528
|
-
self:
|
|
76529
|
-
self:
|
|
76530
|
-
self:
|
|
76531
|
-
self:
|
|
76532
|
-
self:
|
|
77083
|
+
self:T({EscortAirbase=self.EscortAirbase})
|
|
77084
|
+
self:T({PlayerGroupName=PlayerGroupName})
|
|
77085
|
+
self:T({PlayerGroup=PlayerGroup})
|
|
77086
|
+
self:T({FirstGroup=self.CarrierSet:GetFirst()})
|
|
77087
|
+
self:T({FindGroup=self.CarrierSet:FindGroup(PlayerGroupName)})
|
|
76533
77088
|
if self.CarrierSet:FindGroup(PlayerGroupName)then
|
|
76534
77089
|
if not self.AI_Escorts[PlayerGroupName]then
|
|
76535
77090
|
local LeaderUnit=PlayerUnit
|
|
76536
77091
|
local EscortGroup=self.EscortSpawn:SpawnAtAirbase(self.EscortAirbase,SPAWN.Takeoff.Hot)
|
|
76537
|
-
self:
|
|
77092
|
+
self:T({EscortGroup=EscortGroup})
|
|
76538
77093
|
self:ScheduleOnce(1,
|
|
76539
77094
|
function(EscortGroup)
|
|
76540
77095
|
local EscortSet=SET_GROUP:New()
|
|
@@ -76833,7 +77388,7 @@ if Carrier and Carrier:IsAlive()then
|
|
|
76833
77388
|
for _,CarrierUnit in pairs(Carrier:GetUnits())do
|
|
76834
77389
|
local CarrierUnit=CarrierUnit
|
|
76835
77390
|
local IsEmpty=CarrierUnit:IsCargoEmpty()
|
|
76836
|
-
self:
|
|
77391
|
+
self:T({IsEmpty=IsEmpty})
|
|
76837
77392
|
if not IsEmpty then
|
|
76838
77393
|
AllUnloaded=false
|
|
76839
77394
|
break
|
|
@@ -77921,7 +78476,7 @@ break
|
|
|
77921
78476
|
else
|
|
77922
78477
|
local text=string.format("WARNING: Cargo %s is too heavy to be loaded into transport. Cargo weight %.1f > %.1f load capacity of carrier %s.",
|
|
77923
78478
|
tostring(Cargo:GetName()),Cargo:GetWeight(),LargestLoadCapacity,tostring(Carrier:GetName()))
|
|
77924
|
-
self:
|
|
78479
|
+
self:T(text)
|
|
77925
78480
|
end
|
|
77926
78481
|
end
|
|
77927
78482
|
end
|
|
@@ -78527,6 +79082,954 @@ end
|
|
|
78527
79082
|
)
|
|
78528
79083
|
end
|
|
78529
79084
|
end
|
|
79085
|
+
SHAPE_BASE={
|
|
79086
|
+
ClassName="SHAPE_BASE",
|
|
79087
|
+
Name="",
|
|
79088
|
+
CenterVec2=nil,
|
|
79089
|
+
Points={},
|
|
79090
|
+
Coords={},
|
|
79091
|
+
MarkIDs={},
|
|
79092
|
+
ColorString="",
|
|
79093
|
+
ColorRGBA={}
|
|
79094
|
+
}
|
|
79095
|
+
function SHAPE_BASE:New()
|
|
79096
|
+
local self=BASE:Inherit(self,BASE:New())
|
|
79097
|
+
return self
|
|
79098
|
+
end
|
|
79099
|
+
function SHAPE_BASE:FindOnMap(shape_name)
|
|
79100
|
+
local self=BASE:Inherit(self,BASE:New())
|
|
79101
|
+
local found=false
|
|
79102
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79103
|
+
for _,object in pairs(layer["objects"])do
|
|
79104
|
+
if object["name"]==shape_name then
|
|
79105
|
+
self.Name=object["name"]
|
|
79106
|
+
self.CenterVec2={x=object["mapX"],y=object["mapY"]}
|
|
79107
|
+
self.ColorString=object["colorString"]
|
|
79108
|
+
self.ColorRGBA=UTILS.HexToRGBA(self.ColorString)
|
|
79109
|
+
found=true
|
|
79110
|
+
end
|
|
79111
|
+
end
|
|
79112
|
+
end
|
|
79113
|
+
if not found then
|
|
79114
|
+
self:E("Can't find a shape with name "..shape_name)
|
|
79115
|
+
end
|
|
79116
|
+
return self
|
|
79117
|
+
end
|
|
79118
|
+
function SHAPE_BASE:GetAllShapes(filter)
|
|
79119
|
+
filter=filter or""
|
|
79120
|
+
local return_shapes={}
|
|
79121
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79122
|
+
for _,object in pairs(layer["objects"])do
|
|
79123
|
+
if string.contains(object["name"],filter)then
|
|
79124
|
+
table.add(return_shapes,object)
|
|
79125
|
+
end
|
|
79126
|
+
end
|
|
79127
|
+
end
|
|
79128
|
+
return return_shapes
|
|
79129
|
+
end
|
|
79130
|
+
function SHAPE_BASE:Offset(new_vec2)
|
|
79131
|
+
local offset_vec2=UTILS.Vec2Subtract(new_vec2,self.CenterVec2)
|
|
79132
|
+
self.CenterVec2=new_vec2
|
|
79133
|
+
if self.ClassName=="POLYGON"then
|
|
79134
|
+
for _,point in pairs(self.Points)do
|
|
79135
|
+
point.x=point.x+offset_vec2.x
|
|
79136
|
+
point.y=point.y+offset_vec2.y
|
|
79137
|
+
end
|
|
79138
|
+
end
|
|
79139
|
+
end
|
|
79140
|
+
function SHAPE_BASE:GetName()
|
|
79141
|
+
return self.Name
|
|
79142
|
+
end
|
|
79143
|
+
function SHAPE_BASE:GetColorString()
|
|
79144
|
+
return self.ColorString
|
|
79145
|
+
end
|
|
79146
|
+
function SHAPE_BASE:GetColorRGBA()
|
|
79147
|
+
return self.ColorRGBA
|
|
79148
|
+
end
|
|
79149
|
+
function SHAPE_BASE:GetColorRed()
|
|
79150
|
+
return self.ColorRGBA.R
|
|
79151
|
+
end
|
|
79152
|
+
function SHAPE_BASE:GetColorGreen()
|
|
79153
|
+
return self.ColorRGBA.G
|
|
79154
|
+
end
|
|
79155
|
+
function SHAPE_BASE:GetColorBlue()
|
|
79156
|
+
return self.ColorRGBA.B
|
|
79157
|
+
end
|
|
79158
|
+
function SHAPE_BASE:GetColorAlpha()
|
|
79159
|
+
return self.ColorRGBA.A
|
|
79160
|
+
end
|
|
79161
|
+
function SHAPE_BASE:GetCenterVec2()
|
|
79162
|
+
return self.CenterVec2
|
|
79163
|
+
end
|
|
79164
|
+
function SHAPE_BASE:GetCenterCoordinate()
|
|
79165
|
+
return COORDINATE:NewFromVec2(self.CenterVec2)
|
|
79166
|
+
end
|
|
79167
|
+
function SHAPE_BASE:GetCoordinate()
|
|
79168
|
+
return self:GetCenterCoordinate()
|
|
79169
|
+
end
|
|
79170
|
+
function SHAPE_BASE:ContainsPoint(_)
|
|
79171
|
+
self:E("This needs to be set in the derived class")
|
|
79172
|
+
end
|
|
79173
|
+
function SHAPE_BASE:ContainsUnit(unit_name)
|
|
79174
|
+
local unit=UNIT:FindByName(unit_name)
|
|
79175
|
+
if unit==nil or not unit:IsAlive()then
|
|
79176
|
+
return false
|
|
79177
|
+
end
|
|
79178
|
+
if self:ContainsPoint(unit:GetVec2())then
|
|
79179
|
+
return true
|
|
79180
|
+
end
|
|
79181
|
+
return false
|
|
79182
|
+
end
|
|
79183
|
+
function SHAPE_BASE:ContainsAnyOfGroup(group_name)
|
|
79184
|
+
local group=GROUP:FindByName(group_name)
|
|
79185
|
+
if group==nil or not group:IsAlive()then
|
|
79186
|
+
return false
|
|
79187
|
+
end
|
|
79188
|
+
for _,unit in pairs(group:GetUnits())do
|
|
79189
|
+
if self:ContainsPoint(unit:GetVec2())then
|
|
79190
|
+
return true
|
|
79191
|
+
end
|
|
79192
|
+
end
|
|
79193
|
+
return false
|
|
79194
|
+
end
|
|
79195
|
+
function SHAPE_BASE:ContainsAllOfGroup(group_name)
|
|
79196
|
+
local group=GROUP:FindByName(group_name)
|
|
79197
|
+
if group==nil or not group:IsAlive()then
|
|
79198
|
+
return false
|
|
79199
|
+
end
|
|
79200
|
+
for _,unit in pairs(group:GetUnits())do
|
|
79201
|
+
if not self:ContainsPoint(unit:GetVec2())then
|
|
79202
|
+
return false
|
|
79203
|
+
end
|
|
79204
|
+
end
|
|
79205
|
+
return true
|
|
79206
|
+
end
|
|
79207
|
+
CIRCLE={
|
|
79208
|
+
ClassName="CIRCLE",
|
|
79209
|
+
Radius=nil,
|
|
79210
|
+
}
|
|
79211
|
+
function CIRCLE:FindOnMap(shape_name)
|
|
79212
|
+
local self=BASE:Inherit(self,SHAPE_BASE:FindOnMap(shape_name))
|
|
79213
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79214
|
+
for _,object in pairs(layer["objects"])do
|
|
79215
|
+
if string.find(object["name"],shape_name,1,true)then
|
|
79216
|
+
if object["polygonMode"]=="circle"then
|
|
79217
|
+
self.Radius=object["radius"]
|
|
79218
|
+
end
|
|
79219
|
+
end
|
|
79220
|
+
end
|
|
79221
|
+
end
|
|
79222
|
+
return self
|
|
79223
|
+
end
|
|
79224
|
+
function CIRCLE:Find(shape_name)
|
|
79225
|
+
return _DATABASE:FindShape(shape_name)
|
|
79226
|
+
end
|
|
79227
|
+
function CIRCLE:New(vec2,radius)
|
|
79228
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
79229
|
+
self.CenterVec2=vec2
|
|
79230
|
+
self.Radius=radius
|
|
79231
|
+
return self
|
|
79232
|
+
end
|
|
79233
|
+
function CIRCLE:GetRadius()
|
|
79234
|
+
return self.Radius
|
|
79235
|
+
end
|
|
79236
|
+
function CIRCLE:ContainsPoint(point)
|
|
79237
|
+
if((point.x-self.CenterVec2.x)^2+(point.y-self.CenterVec2.y)^2)^0.5<=self.Radius then
|
|
79238
|
+
return true
|
|
79239
|
+
end
|
|
79240
|
+
return false
|
|
79241
|
+
end
|
|
79242
|
+
function CIRCLE:PointInSector(point,sector_start,sector_end,center,radius)
|
|
79243
|
+
center=center or self.CenterVec2
|
|
79244
|
+
radius=radius or self.Radius
|
|
79245
|
+
local function are_clockwise(v1,v2)
|
|
79246
|
+
return-v1.x*v2.y+v1.y*v2.x>0
|
|
79247
|
+
end
|
|
79248
|
+
local function is_in_radius(rp)
|
|
79249
|
+
return rp.x*rp.x+rp.y*rp.y<=radius^2
|
|
79250
|
+
end
|
|
79251
|
+
local rel_pt={
|
|
79252
|
+
x=point.x-center.x,
|
|
79253
|
+
y=point.y-center.y
|
|
79254
|
+
}
|
|
79255
|
+
local rel_sector_start={
|
|
79256
|
+
x=sector_start.x-center.x,
|
|
79257
|
+
y=sector_start.y-center.y,
|
|
79258
|
+
}
|
|
79259
|
+
local rel_sector_end={
|
|
79260
|
+
x=sector_end.x-center.x,
|
|
79261
|
+
y=sector_end.y-center.y,
|
|
79262
|
+
}
|
|
79263
|
+
return not are_clockwise(rel_sector_start,rel_pt)and
|
|
79264
|
+
are_clockwise(rel_sector_end,rel_pt)and
|
|
79265
|
+
is_in_radius(rel_pt,radius)
|
|
79266
|
+
end
|
|
79267
|
+
function CIRCLE:UnitInSector(unit_name,sector_start,sector_end,center,radius)
|
|
79268
|
+
center=center or self.CenterVec2
|
|
79269
|
+
radius=radius or self.Radius
|
|
79270
|
+
if self:PointInSector(UNIT:FindByName(unit_name):GetVec2(),sector_start,sector_end,center,radius)then
|
|
79271
|
+
return true
|
|
79272
|
+
end
|
|
79273
|
+
return false
|
|
79274
|
+
end
|
|
79275
|
+
function CIRCLE:AnyOfGroupInSector(group_name,sector_start,sector_end,center,radius)
|
|
79276
|
+
center=center or self.CenterVec2
|
|
79277
|
+
radius=radius or self.Radius
|
|
79278
|
+
for _,unit in pairs(GROUP:FindByName(group_name):GetUnits())do
|
|
79279
|
+
if self:PointInSector(unit:GetVec2(),sector_start,sector_end,center,radius)then
|
|
79280
|
+
return true
|
|
79281
|
+
end
|
|
79282
|
+
end
|
|
79283
|
+
return false
|
|
79284
|
+
end
|
|
79285
|
+
function CIRCLE:AllOfGroupInSector(group_name,sector_start,sector_end,center,radius)
|
|
79286
|
+
center=center or self.CenterVec2
|
|
79287
|
+
radius=radius or self.Radius
|
|
79288
|
+
for _,unit in pairs(GROUP:FindByName(group_name):GetUnits())do
|
|
79289
|
+
if not self:PointInSector(unit:GetVec2(),sector_start,sector_end,center,radius)then
|
|
79290
|
+
return false
|
|
79291
|
+
end
|
|
79292
|
+
end
|
|
79293
|
+
return true
|
|
79294
|
+
end
|
|
79295
|
+
function CIRCLE:UnitInRadius(unit_name,center,radius)
|
|
79296
|
+
center=center or self.CenterVec2
|
|
79297
|
+
radius=radius or self.Radius
|
|
79298
|
+
if UTILS.IsInRadius(center,UNIT:FindByName(unit_name):GetVec2(),radius)then
|
|
79299
|
+
return true
|
|
79300
|
+
end
|
|
79301
|
+
return false
|
|
79302
|
+
end
|
|
79303
|
+
function CIRCLE:AnyOfGroupInRadius(group_name,center,radius)
|
|
79304
|
+
center=center or self.CenterVec2
|
|
79305
|
+
radius=radius or self.Radius
|
|
79306
|
+
for _,unit in pairs(GROUP:FindByName(group_name):GetUnits())do
|
|
79307
|
+
if UTILS.IsInRadius(center,unit:GetVec2(),radius)then
|
|
79308
|
+
return true
|
|
79309
|
+
end
|
|
79310
|
+
end
|
|
79311
|
+
return false
|
|
79312
|
+
end
|
|
79313
|
+
function CIRCLE:AllOfGroupInRadius(group_name,center,radius)
|
|
79314
|
+
center=center or self.CenterVec2
|
|
79315
|
+
radius=radius or self.Radius
|
|
79316
|
+
for _,unit in pairs(GROUP:FindByName(group_name):GetUnits())do
|
|
79317
|
+
if not UTILS.IsInRadius(center,unit:GetVec2(),radius)then
|
|
79318
|
+
return false
|
|
79319
|
+
end
|
|
79320
|
+
end
|
|
79321
|
+
return true
|
|
79322
|
+
end
|
|
79323
|
+
function CIRCLE:GetRandomVec2()
|
|
79324
|
+
local angle=math.random()*2*math.pi
|
|
79325
|
+
local rx=math.random(0,self.Radius)*math.cos(angle)+self.CenterVec2.x
|
|
79326
|
+
local ry=math.random(0,self.Radius)*math.sin(angle)+self.CenterVec2.y
|
|
79327
|
+
return{x=rx,y=ry}
|
|
79328
|
+
end
|
|
79329
|
+
function CIRCLE:GetRandomVec2OnBorder()
|
|
79330
|
+
local angle=math.random()*2*math.pi
|
|
79331
|
+
local rx=self.Radius*math.cos(angle)+self.CenterVec2.x
|
|
79332
|
+
local ry=self.Radius*math.sin(angle)+self.CenterVec2.y
|
|
79333
|
+
return{x=rx,y=ry}
|
|
79334
|
+
end
|
|
79335
|
+
function CIRCLE:GetBoundingBox()
|
|
79336
|
+
local min_x=self.CenterVec2.x-self.Radius
|
|
79337
|
+
local min_y=self.CenterVec2.y-self.Radius
|
|
79338
|
+
local max_x=self.CenterVec2.x+self.Radius
|
|
79339
|
+
local max_y=self.CenterVec2.y+self.Radius
|
|
79340
|
+
return{
|
|
79341
|
+
{x=min_x,y=min_x},{x=max_x,y=min_y},{x=max_x,y=max_y},{x=min_x,y=max_y}
|
|
79342
|
+
}
|
|
79343
|
+
end
|
|
79344
|
+
CUBE={
|
|
79345
|
+
ClassName="CUBE",
|
|
79346
|
+
Points={},
|
|
79347
|
+
Coords={}
|
|
79348
|
+
}
|
|
79349
|
+
function CUBE:New(p1,p2,p3,p4,p5,p6,p7,p8)
|
|
79350
|
+
local self=BASE:Inherit(self,SHAPE_BASE)
|
|
79351
|
+
self.Points={p1,p2,p3,p4,p5,p6,p7,p8}
|
|
79352
|
+
for _,point in spairs(self.Points)do
|
|
79353
|
+
table.insert(self.Coords,COORDINATE:NewFromVec3(point))
|
|
79354
|
+
end
|
|
79355
|
+
return self
|
|
79356
|
+
end
|
|
79357
|
+
function CUBE:GetCenter()
|
|
79358
|
+
local center={x=0,y=0,z=0}
|
|
79359
|
+
for _,point in pairs(self.Points)do
|
|
79360
|
+
center.x=center.x+point.x
|
|
79361
|
+
center.y=center.y+point.y
|
|
79362
|
+
center.z=center.z+point.z
|
|
79363
|
+
end
|
|
79364
|
+
center.x=center.x/8
|
|
79365
|
+
center.y=center.y/8
|
|
79366
|
+
center.z=center.z/8
|
|
79367
|
+
return center
|
|
79368
|
+
end
|
|
79369
|
+
function CUBE:ContainsPoint(point,cube_points)
|
|
79370
|
+
cube_points=cube_points or self.Points
|
|
79371
|
+
local min_x,min_y,min_z=math.huge,math.huge,math.huge
|
|
79372
|
+
local max_x,max_y,max_z=-math.huge,-math.huge,-math.huge
|
|
79373
|
+
for _,p in ipairs(cube_points)do
|
|
79374
|
+
if p.x<min_x then min_x=p.x end
|
|
79375
|
+
if p.y<min_y then min_y=p.y end
|
|
79376
|
+
if p.z<min_z then min_z=p.z end
|
|
79377
|
+
if p.x>max_x then max_x=p.x end
|
|
79378
|
+
if p.y>max_y then max_y=p.y end
|
|
79379
|
+
if p.z>max_z then max_z=p.z end
|
|
79380
|
+
end
|
|
79381
|
+
return point.x>=min_x and point.x<=max_x and point.y>=min_y and point.y<=max_y and point.z>=min_z and point.z<=max_z
|
|
79382
|
+
end
|
|
79383
|
+
LINE={
|
|
79384
|
+
ClassName="LINE",
|
|
79385
|
+
Points={},
|
|
79386
|
+
Coords={},
|
|
79387
|
+
}
|
|
79388
|
+
function LINE:FindOnMap(line_name)
|
|
79389
|
+
local self=BASE:Inherit(self,SHAPE_BASE:FindOnMap(line_name))
|
|
79390
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79391
|
+
for _,object in pairs(layer["objects"])do
|
|
79392
|
+
if object["name"]==line_name then
|
|
79393
|
+
if object["primitiveType"]=="Line"then
|
|
79394
|
+
for _,point in UTILS.spairs(object["points"])do
|
|
79395
|
+
local p={x=object["mapX"]+point["x"],
|
|
79396
|
+
y=object["mapY"]+point["y"]}
|
|
79397
|
+
local coord=COORDINATE:NewFromVec2(p)
|
|
79398
|
+
table.insert(self.Points,p)
|
|
79399
|
+
table.insert(self.Coords,coord)
|
|
79400
|
+
end
|
|
79401
|
+
end
|
|
79402
|
+
end
|
|
79403
|
+
end
|
|
79404
|
+
end
|
|
79405
|
+
self:I(#self.Points)
|
|
79406
|
+
if#self.Points==0 then
|
|
79407
|
+
return nil
|
|
79408
|
+
end
|
|
79409
|
+
self.MarkIDs={}
|
|
79410
|
+
return self
|
|
79411
|
+
end
|
|
79412
|
+
function LINE:Find(shape_name)
|
|
79413
|
+
return _DATABASE:FindShape(shape_name)
|
|
79414
|
+
end
|
|
79415
|
+
function LINE:New(...)
|
|
79416
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
79417
|
+
self.Points={...}
|
|
79418
|
+
self:I(self.Points)
|
|
79419
|
+
for _,point in UTILS.spairs(self.Points)do
|
|
79420
|
+
table.insert(self.Coords,COORDINATE:NewFromVec2(point))
|
|
79421
|
+
end
|
|
79422
|
+
return self
|
|
79423
|
+
end
|
|
79424
|
+
function LINE:NewFromCircle(center_point,radius,angle_degrees)
|
|
79425
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
79426
|
+
self.CenterVec2=center_point
|
|
79427
|
+
local angleRadians=math.rad(angle_degrees)
|
|
79428
|
+
local point1={
|
|
79429
|
+
x=center_point.x+radius*math.cos(angleRadians),
|
|
79430
|
+
y=center_point.y+radius*math.sin(angleRadians)
|
|
79431
|
+
}
|
|
79432
|
+
local point2={
|
|
79433
|
+
x=center_point.x+radius*math.cos(angleRadians+math.pi),
|
|
79434
|
+
y=center_point.y+radius*math.sin(angleRadians+math.pi)
|
|
79435
|
+
}
|
|
79436
|
+
for _,point in pairs{point1,point2}do
|
|
79437
|
+
table.insert(self.Points,point)
|
|
79438
|
+
table.insert(self.Coords,COORDINATE:NewFromVec2(point))
|
|
79439
|
+
end
|
|
79440
|
+
return self
|
|
79441
|
+
end
|
|
79442
|
+
function LINE:Coordinates()
|
|
79443
|
+
return self.Coords
|
|
79444
|
+
end
|
|
79445
|
+
function LINE:GetStartCoordinate()
|
|
79446
|
+
return self.Coords[1]
|
|
79447
|
+
end
|
|
79448
|
+
function LINE:GetEndCoordinate()
|
|
79449
|
+
return self.Coords[#self.Coords]
|
|
79450
|
+
end
|
|
79451
|
+
function LINE:GetStartPoint()
|
|
79452
|
+
return self.Points[1]
|
|
79453
|
+
end
|
|
79454
|
+
function LINE:GetEndPoint()
|
|
79455
|
+
return self.Points[#self.Points]
|
|
79456
|
+
end
|
|
79457
|
+
function LINE:GetLength()
|
|
79458
|
+
local total_length=0
|
|
79459
|
+
for i=1,#self.Points-1 do
|
|
79460
|
+
local x1,y1=self.Points[i]["x"],self.Points[i]["y"]
|
|
79461
|
+
local x2,y2=self.Points[i+1]["x"],self.Points[i+1]["y"]
|
|
79462
|
+
local segment_length=math.sqrt((x2-x1)^2+(y2-y1)^2)
|
|
79463
|
+
total_length=total_length+segment_length
|
|
79464
|
+
end
|
|
79465
|
+
return total_length
|
|
79466
|
+
end
|
|
79467
|
+
function LINE:GetRandomPoint(points)
|
|
79468
|
+
points=points or self.Points
|
|
79469
|
+
local rand=math.random()
|
|
79470
|
+
local random_x=points[1].x+rand*(points[2].x-points[1].x)
|
|
79471
|
+
local random_y=points[1].y+rand*(points[2].y-points[1].y)
|
|
79472
|
+
return{x=random_x,y=random_y}
|
|
79473
|
+
end
|
|
79474
|
+
function LINE:GetHeading(points)
|
|
79475
|
+
points=points or self.Points
|
|
79476
|
+
local angle=math.atan2(points[2].y-points[1].y,points[2].x-points[1].x)
|
|
79477
|
+
angle=math.deg(angle)
|
|
79478
|
+
if angle<0 then
|
|
79479
|
+
angle=angle+360
|
|
79480
|
+
end
|
|
79481
|
+
return angle
|
|
79482
|
+
end
|
|
79483
|
+
function LINE:GetIndividualParts()
|
|
79484
|
+
local parts={}
|
|
79485
|
+
if#self.Points==2 then
|
|
79486
|
+
parts={self}
|
|
79487
|
+
end
|
|
79488
|
+
for i=1,#self.Points-1 do
|
|
79489
|
+
local p1=self.Points[i]
|
|
79490
|
+
local p2=self.Points[i%#self.Points+1]
|
|
79491
|
+
table.add(parts,LINE:New(p1,p2))
|
|
79492
|
+
end
|
|
79493
|
+
return parts
|
|
79494
|
+
end
|
|
79495
|
+
function LINE:GetPointsInbetween(amount,start_point,end_point)
|
|
79496
|
+
start_point=start_point or self:GetStartPoint()
|
|
79497
|
+
end_point=end_point or self:GetEndPoint()
|
|
79498
|
+
if amount==0 then return{start_point,end_point}end
|
|
79499
|
+
amount=amount+1
|
|
79500
|
+
local points={}
|
|
79501
|
+
local difference={x=end_point.x-start_point.x,y=end_point.y-start_point.y}
|
|
79502
|
+
local divided={x=difference.x/amount,y=difference.y/amount}
|
|
79503
|
+
for j=0,amount do
|
|
79504
|
+
local part_pos={x=divided.x*j,y=divided.y*j}
|
|
79505
|
+
local point={x=start_point.x+part_pos.x,y=start_point.y+part_pos.y}
|
|
79506
|
+
table.insert(points,point)
|
|
79507
|
+
end
|
|
79508
|
+
return points
|
|
79509
|
+
end
|
|
79510
|
+
function LINE:GetCoordinatesInBetween(amount,start_point,end_point)
|
|
79511
|
+
local coords={}
|
|
79512
|
+
for _,pt in pairs(self:GetPointsInbetween(amount,start_point,end_point))do
|
|
79513
|
+
table.add(coords,COORDINATE:NewFromVec2(pt))
|
|
79514
|
+
end
|
|
79515
|
+
return coords
|
|
79516
|
+
end
|
|
79517
|
+
function LINE:GetRandomPoint(start_point,end_point)
|
|
79518
|
+
start_point=start_point or self:GetStartPoint()
|
|
79519
|
+
end_point=end_point or self:GetEndPoint()
|
|
79520
|
+
local fraction=math.random()
|
|
79521
|
+
local difference={x=end_point.x-start_point.x,y=end_point.y-start_point.y}
|
|
79522
|
+
local part_pos={x=difference.x*fraction,y=difference.y*fraction}
|
|
79523
|
+
local random_point={x=start_point.x+part_pos.x,y=start_point.y+part_pos.y}
|
|
79524
|
+
return random_point
|
|
79525
|
+
end
|
|
79526
|
+
function LINE:GetRandomCoordinate(start_point,end_point)
|
|
79527
|
+
start_point=start_point or self:GetStartPoint()
|
|
79528
|
+
end_point=end_point or self:GetEndPoint()
|
|
79529
|
+
return COORDINATE:NewFromVec2(self:GetRandomPoint(start_point,end_point))
|
|
79530
|
+
end
|
|
79531
|
+
function LINE:GetPointsBetweenAsSineWave(amount,start_point,end_point,frequency,phase,amplitude)
|
|
79532
|
+
amount=amount or 20
|
|
79533
|
+
start_point=start_point or self:GetStartPoint()
|
|
79534
|
+
end_point=end_point or self:GetEndPoint()
|
|
79535
|
+
frequency=frequency or 1
|
|
79536
|
+
phase=phase or 0
|
|
79537
|
+
amplitude=amplitude or 100
|
|
79538
|
+
local points={}
|
|
79539
|
+
local function sine_wave(x)
|
|
79540
|
+
return amplitude*math.sin(2*math.pi*frequency*(x-start_point.x)+phase)
|
|
79541
|
+
end
|
|
79542
|
+
local x=start_point.x
|
|
79543
|
+
local step=(end_point.x-start_point.x)/20
|
|
79544
|
+
for _=1,amount do
|
|
79545
|
+
local y=sine_wave(x)
|
|
79546
|
+
x=x+step
|
|
79547
|
+
table.add(points,{x=x,y=y})
|
|
79548
|
+
end
|
|
79549
|
+
return points
|
|
79550
|
+
end
|
|
79551
|
+
function LINE:GetBoundingBox()
|
|
79552
|
+
local min_x,min_y,max_x,max_y=self.Points[1].x,self.Points[1].y,self.Points[2].x,self.Points[2].y
|
|
79553
|
+
for i=2,#self.Points do
|
|
79554
|
+
local x,y=self.Points[i].x,self.Points[i].y
|
|
79555
|
+
if x<min_x then
|
|
79556
|
+
min_x=x
|
|
79557
|
+
end
|
|
79558
|
+
if y<min_y then
|
|
79559
|
+
min_y=y
|
|
79560
|
+
end
|
|
79561
|
+
if x>max_x then
|
|
79562
|
+
max_x=x
|
|
79563
|
+
end
|
|
79564
|
+
if y>max_y then
|
|
79565
|
+
max_y=y
|
|
79566
|
+
end
|
|
79567
|
+
end
|
|
79568
|
+
return{
|
|
79569
|
+
{x=min_x,y=min_x},{x=max_x,y=min_y},{x=max_x,y=max_y},{x=min_x,y=max_y}
|
|
79570
|
+
}
|
|
79571
|
+
end
|
|
79572
|
+
function LINE:Draw()
|
|
79573
|
+
for i=1,#self.Coords-1 do
|
|
79574
|
+
local c1=self.Coords[i]
|
|
79575
|
+
local c2=self.Coords[i%#self.Coords+1]
|
|
79576
|
+
table.add(self.MarkIDs,c1:LineToAll(c2))
|
|
79577
|
+
end
|
|
79578
|
+
end
|
|
79579
|
+
function LINE:RemoveDraw()
|
|
79580
|
+
for _,mark_id in pairs(self.MarkIDs)do
|
|
79581
|
+
UTILS.RemoveMark(mark_id)
|
|
79582
|
+
end
|
|
79583
|
+
end
|
|
79584
|
+
OVAL={
|
|
79585
|
+
ClassName="OVAL",
|
|
79586
|
+
MajorAxis=nil,
|
|
79587
|
+
MinorAxis=nil,
|
|
79588
|
+
Angle=0,
|
|
79589
|
+
DrawPoly=nil
|
|
79590
|
+
}
|
|
79591
|
+
function OVAL:FindOnMap(shape_name)
|
|
79592
|
+
local self=BASE:Inherit(self,SHAPE_BASE:FindOnMap(shape_name))
|
|
79593
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79594
|
+
for _,object in pairs(layer["objects"])do
|
|
79595
|
+
if string.find(object["name"],shape_name,1,true)then
|
|
79596
|
+
if object["polygonMode"]=="oval"then
|
|
79597
|
+
self.CenterVec2={x=object["mapX"],y=object["mapY"]}
|
|
79598
|
+
self.MajorAxis=object["r1"]
|
|
79599
|
+
self.MinorAxis=object["r2"]
|
|
79600
|
+
self.Angle=object["angle"]
|
|
79601
|
+
end
|
|
79602
|
+
end
|
|
79603
|
+
end
|
|
79604
|
+
end
|
|
79605
|
+
return self
|
|
79606
|
+
end
|
|
79607
|
+
function OVAL:Find(shape_name)
|
|
79608
|
+
return _DATABASE:FindShape(shape_name)
|
|
79609
|
+
end
|
|
79610
|
+
function OVAL:New(vec2,major_axis,minor_axis,angle)
|
|
79611
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
79612
|
+
self.CenterVec2=vec2
|
|
79613
|
+
self.MajorAxis=major_axis
|
|
79614
|
+
self.MinorAxis=minor_axis
|
|
79615
|
+
self.Angle=angle or 0
|
|
79616
|
+
return self
|
|
79617
|
+
end
|
|
79618
|
+
function OVAL:GetMajorAxis()
|
|
79619
|
+
return self.MajorAxis
|
|
79620
|
+
end
|
|
79621
|
+
function OVAL:GetMinorAxis()
|
|
79622
|
+
return self.MinorAxis
|
|
79623
|
+
end
|
|
79624
|
+
function OVAL:GetAngle()
|
|
79625
|
+
return self.Angle
|
|
79626
|
+
end
|
|
79627
|
+
function OVAL:SetMajorAxis(value)
|
|
79628
|
+
self.MajorAxis=value
|
|
79629
|
+
end
|
|
79630
|
+
function OVAL:SetMinorAxis(value)
|
|
79631
|
+
self.MinorAxis=value
|
|
79632
|
+
end
|
|
79633
|
+
function OVAL:SetAngle(value)
|
|
79634
|
+
self.Angle=value
|
|
79635
|
+
end
|
|
79636
|
+
function OVAL:ContainsPoint(point)
|
|
79637
|
+
local cos,sin=math.cos,math.sin
|
|
79638
|
+
local dx=point.x-self.CenterVec2.x
|
|
79639
|
+
local dy=point.y-self.CenterVec2.y
|
|
79640
|
+
local rx=dx*cos(self.Angle)+dy*sin(self.Angle)
|
|
79641
|
+
local ry=-dx*sin(self.Angle)+dy*cos(self.Angle)
|
|
79642
|
+
return rx*rx/(self.MajorAxis*self.MajorAxis)+ry*ry/(self.MinorAxis*self.MinorAxis)<=1
|
|
79643
|
+
end
|
|
79644
|
+
function OVAL:GetRandomVec2()
|
|
79645
|
+
local theta=math.rad(self.Angle)
|
|
79646
|
+
local random_point=math.sqrt(math.random())
|
|
79647
|
+
local phi=math.random()*2*math.pi
|
|
79648
|
+
local x_c=random_point*math.cos(phi)
|
|
79649
|
+
local y_c=random_point*math.sin(phi)
|
|
79650
|
+
local x_e=x_c*self.MajorAxis
|
|
79651
|
+
local y_e=y_c*self.MinorAxis
|
|
79652
|
+
local rx=(x_e*math.cos(theta)-y_e*math.sin(theta))+self.CenterVec2.x
|
|
79653
|
+
local ry=(x_e*math.sin(theta)+y_e*math.cos(theta))+self.CenterVec2.y
|
|
79654
|
+
return{x=rx,y=ry}
|
|
79655
|
+
end
|
|
79656
|
+
function OVAL:GetBoundingBox()
|
|
79657
|
+
local min_x=self.CenterVec2.x-self.MajorAxis
|
|
79658
|
+
local min_y=self.CenterVec2.y-self.MinorAxis
|
|
79659
|
+
local max_x=self.CenterVec2.x+self.MajorAxis
|
|
79660
|
+
local max_y=self.CenterVec2.y+self.MinorAxis
|
|
79661
|
+
return{
|
|
79662
|
+
{x=min_x,y=min_x},{x=max_x,y=min_y},{x=max_x,y=max_y},{x=min_x,y=max_y}
|
|
79663
|
+
}
|
|
79664
|
+
end
|
|
79665
|
+
function OVAL:Draw()
|
|
79666
|
+
self.DrawPoly=POLYGON:NewFromPoints(self:PointsOnEdge(20))
|
|
79667
|
+
self.DrawPoly:Draw(true)
|
|
79668
|
+
end
|
|
79669
|
+
function OVAL:RemoveDraw()
|
|
79670
|
+
self.DrawPoly:RemoveDraw()
|
|
79671
|
+
end
|
|
79672
|
+
function OVAL:PointsOnEdge(num_points)
|
|
79673
|
+
num_points=num_points or 20
|
|
79674
|
+
local points={}
|
|
79675
|
+
local dtheta=2*math.pi/num_points
|
|
79676
|
+
for i=0,num_points-1 do
|
|
79677
|
+
local theta=i*dtheta
|
|
79678
|
+
local x=self.CenterVec2.x+self.MajorAxis*math.cos(theta)*math.cos(self.Angle)-self.MinorAxis*math.sin(theta)*math.sin(self.Angle)
|
|
79679
|
+
local y=self.CenterVec2.y+self.MajorAxis*math.cos(theta)*math.sin(self.Angle)+self.MinorAxis*math.sin(theta)*math.cos(self.Angle)
|
|
79680
|
+
table.insert(points,{x=x,y=y})
|
|
79681
|
+
end
|
|
79682
|
+
return points
|
|
79683
|
+
end
|
|
79684
|
+
POLYGON={
|
|
79685
|
+
ClassName="POLYGON",
|
|
79686
|
+
Points={},
|
|
79687
|
+
Coords={},
|
|
79688
|
+
Triangles={},
|
|
79689
|
+
SurfaceArea=0,
|
|
79690
|
+
TriangleMarkIDs={},
|
|
79691
|
+
OutlineMarkIDs={},
|
|
79692
|
+
Angle=nil,
|
|
79693
|
+
Heading=nil
|
|
79694
|
+
}
|
|
79695
|
+
function POLYGON:FindOnMap(shape_name)
|
|
79696
|
+
local self=BASE:Inherit(self,SHAPE_BASE:FindOnMap(shape_name))
|
|
79697
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79698
|
+
for _,object in pairs(layer["objects"])do
|
|
79699
|
+
if object["name"]==shape_name then
|
|
79700
|
+
if(object["primitiveType"]=="Line"and object["closed"]==true)or(object["polygonMode"]=="free")then
|
|
79701
|
+
for _,point in UTILS.spairs(object["points"])do
|
|
79702
|
+
local p={x=object["mapX"]+point["x"],
|
|
79703
|
+
y=object["mapY"]+point["y"]}
|
|
79704
|
+
local coord=COORDINATE:NewFromVec2(p)
|
|
79705
|
+
self.Points[#self.Points+1]=p
|
|
79706
|
+
self.Coords[#self.Coords+1]=coord
|
|
79707
|
+
end
|
|
79708
|
+
elseif object["polygonMode"]=="rect"then
|
|
79709
|
+
local angle=object["angle"]
|
|
79710
|
+
local half_width=object["width"]/2
|
|
79711
|
+
local half_height=object["height"]/2
|
|
79712
|
+
local p1=UTILS.RotatePointAroundPivot({x=self.CenterVec2.x-half_height,y=self.CenterVec2.y+half_width},self.CenterVec2,angle)
|
|
79713
|
+
local p2=UTILS.RotatePointAroundPivot({x=self.CenterVec2.x+half_height,y=self.CenterVec2.y+half_width},self.CenterVec2,angle)
|
|
79714
|
+
local p3=UTILS.RotatePointAroundPivot({x=self.CenterVec2.x+half_height,y=self.CenterVec2.y-half_width},self.CenterVec2,angle)
|
|
79715
|
+
local p4=UTILS.RotatePointAroundPivot({x=self.CenterVec2.x-half_height,y=self.CenterVec2.y-half_width},self.CenterVec2,angle)
|
|
79716
|
+
self.Points={p1,p2,p3,p4}
|
|
79717
|
+
for _,point in pairs(self.Points)do
|
|
79718
|
+
self.Coords[#self.Coords+1]=COORDINATE:NewFromVec2(point)
|
|
79719
|
+
end
|
|
79720
|
+
elseif object["polygonMode"]=="arrow"then
|
|
79721
|
+
for _,point in UTILS.spairs(object["points"])do
|
|
79722
|
+
local p={x=object["mapX"]+point["x"],
|
|
79723
|
+
y=object["mapY"]+point["y"]}
|
|
79724
|
+
local coord=COORDINATE:NewFromVec2(p)
|
|
79725
|
+
self.Points[#self.Points+1]=p
|
|
79726
|
+
self.Coords[#self.Coords+1]=coord
|
|
79727
|
+
end
|
|
79728
|
+
self.Angle=object["angle"]
|
|
79729
|
+
self.Heading=UTILS.ClampAngle(self.Angle+90)
|
|
79730
|
+
end
|
|
79731
|
+
end
|
|
79732
|
+
end
|
|
79733
|
+
end
|
|
79734
|
+
if#self.Points==0 then
|
|
79735
|
+
return nil
|
|
79736
|
+
end
|
|
79737
|
+
self.CenterVec2=self:GetCentroid()
|
|
79738
|
+
self.Triangles=self:Triangulate()
|
|
79739
|
+
self.SurfaceArea=self:__CalculateSurfaceArea()
|
|
79740
|
+
self.TriangleMarkIDs={}
|
|
79741
|
+
self.OutlineMarkIDs={}
|
|
79742
|
+
return self
|
|
79743
|
+
end
|
|
79744
|
+
function POLYGON:FromZone(zone_name)
|
|
79745
|
+
for _,zone in pairs(env.mission.triggers.zones)do
|
|
79746
|
+
if zone["name"]==zone_name then
|
|
79747
|
+
return POLYGON:New(unpack(zone["verticies"]or{}))
|
|
79748
|
+
end
|
|
79749
|
+
end
|
|
79750
|
+
end
|
|
79751
|
+
function POLYGON:Find(shape_name)
|
|
79752
|
+
return _DATABASE:FindShape(shape_name)
|
|
79753
|
+
end
|
|
79754
|
+
function POLYGON:New(...)
|
|
79755
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
79756
|
+
self.Points={...}
|
|
79757
|
+
self.Coords={}
|
|
79758
|
+
for _,point in UTILS.spairs(self.Points)do
|
|
79759
|
+
table.insert(self.Coords,COORDINATE:NewFromVec2(point))
|
|
79760
|
+
end
|
|
79761
|
+
self.Triangles=self:Triangulate()
|
|
79762
|
+
self.SurfaceArea=self:__CalculateSurfaceArea()
|
|
79763
|
+
return self
|
|
79764
|
+
end
|
|
79765
|
+
function POLYGON:GetCentroid()
|
|
79766
|
+
local function sum(t)
|
|
79767
|
+
local total=0
|
|
79768
|
+
for _,value in pairs(t)do
|
|
79769
|
+
total=total+value
|
|
79770
|
+
end
|
|
79771
|
+
return total
|
|
79772
|
+
end
|
|
79773
|
+
local x_values={}
|
|
79774
|
+
local y_values={}
|
|
79775
|
+
local length=table.length(self.Points)
|
|
79776
|
+
for _,point in pairs(self.Points)do
|
|
79777
|
+
table.insert(x_values,point.x)
|
|
79778
|
+
table.insert(y_values,point.y)
|
|
79779
|
+
end
|
|
79780
|
+
local x=sum(x_values)/length
|
|
79781
|
+
local y=sum(y_values)/length
|
|
79782
|
+
return{
|
|
79783
|
+
["x"]=x,
|
|
79784
|
+
["y"]=y
|
|
79785
|
+
}
|
|
79786
|
+
end
|
|
79787
|
+
function POLYGON:GetCoordinates()
|
|
79788
|
+
return self.Coords
|
|
79789
|
+
end
|
|
79790
|
+
function POLYGON:GetStartCoordinate()
|
|
79791
|
+
return self.Coords[1]
|
|
79792
|
+
end
|
|
79793
|
+
function POLYGON:GetEndCoordinate()
|
|
79794
|
+
return self.Coords[#self.Coords]
|
|
79795
|
+
end
|
|
79796
|
+
function POLYGON:GetStartPoint()
|
|
79797
|
+
return self.Points[1]
|
|
79798
|
+
end
|
|
79799
|
+
function POLYGON:GetEndPoint()
|
|
79800
|
+
return self.Points[#self.Points]
|
|
79801
|
+
end
|
|
79802
|
+
function POLYGON:GetPoints()
|
|
79803
|
+
return self.Points
|
|
79804
|
+
end
|
|
79805
|
+
function POLYGON:GetSurfaceArea()
|
|
79806
|
+
return self.SurfaceArea
|
|
79807
|
+
end
|
|
79808
|
+
function POLYGON:GetBoundingBox()
|
|
79809
|
+
local min_x,min_y,max_x,max_y=self.Points[1].x,self.Points[1].y,self.Points[1].x,self.Points[1].y
|
|
79810
|
+
for i=2,#self.Points do
|
|
79811
|
+
local x,y=self.Points[i].x,self.Points[i].y
|
|
79812
|
+
if x<min_x then
|
|
79813
|
+
min_x=x
|
|
79814
|
+
end
|
|
79815
|
+
if y<min_y then
|
|
79816
|
+
min_y=y
|
|
79817
|
+
end
|
|
79818
|
+
if x>max_x then
|
|
79819
|
+
max_x=x
|
|
79820
|
+
end
|
|
79821
|
+
if y>max_y then
|
|
79822
|
+
max_y=y
|
|
79823
|
+
end
|
|
79824
|
+
end
|
|
79825
|
+
return{
|
|
79826
|
+
{x=min_x,y=min_x},{x=max_x,y=min_y},{x=max_x,y=max_y},{x=min_x,y=max_y}
|
|
79827
|
+
}
|
|
79828
|
+
end
|
|
79829
|
+
function POLYGON:Triangulate(points)
|
|
79830
|
+
points=points or self.Points
|
|
79831
|
+
local triangles={}
|
|
79832
|
+
local function get_orientation(shape_points)
|
|
79833
|
+
local sum=0
|
|
79834
|
+
for i=1,#shape_points do
|
|
79835
|
+
local j=i%#shape_points+1
|
|
79836
|
+
sum=sum+(shape_points[j].x-shape_points[i].x)*(shape_points[j].y+shape_points[i].y)
|
|
79837
|
+
end
|
|
79838
|
+
return sum>=0 and"clockwise"or"counter-clockwise"
|
|
79839
|
+
end
|
|
79840
|
+
local function ensure_clockwise(shape_points)
|
|
79841
|
+
local orientation=get_orientation(shape_points)
|
|
79842
|
+
if orientation=="counter-clockwise"then
|
|
79843
|
+
local reversed={}
|
|
79844
|
+
for i=#shape_points,1,-1 do
|
|
79845
|
+
table.insert(reversed,shape_points[i])
|
|
79846
|
+
end
|
|
79847
|
+
return reversed
|
|
79848
|
+
end
|
|
79849
|
+
return shape_points
|
|
79850
|
+
end
|
|
79851
|
+
local function is_clockwise(p1,p2,p3)
|
|
79852
|
+
local cross_product=(p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x)
|
|
79853
|
+
return cross_product<0
|
|
79854
|
+
end
|
|
79855
|
+
local function divide_recursively(shape_points)
|
|
79856
|
+
if#shape_points==3 then
|
|
79857
|
+
table.insert(triangles,TRIANGLE:New(shape_points[1],shape_points[2],shape_points[3]))
|
|
79858
|
+
elseif#shape_points>3 then
|
|
79859
|
+
for i,p1 in ipairs(shape_points)do
|
|
79860
|
+
local p2=shape_points[(i%#shape_points)+1]
|
|
79861
|
+
local p3=shape_points[(i+1)%#shape_points+1]
|
|
79862
|
+
local triangle=TRIANGLE:New(p1,p2,p3)
|
|
79863
|
+
local is_ear=true
|
|
79864
|
+
if not is_clockwise(p1,p2,p3)then
|
|
79865
|
+
is_ear=false
|
|
79866
|
+
else
|
|
79867
|
+
for _,point in ipairs(shape_points)do
|
|
79868
|
+
if point~=p1 and point~=p2 and point~=p3 and triangle:ContainsPoint(point)then
|
|
79869
|
+
is_ear=false
|
|
79870
|
+
break
|
|
79871
|
+
end
|
|
79872
|
+
end
|
|
79873
|
+
end
|
|
79874
|
+
if is_ear then
|
|
79875
|
+
local is_valid_triangle=true
|
|
79876
|
+
for _,point in ipairs(points)do
|
|
79877
|
+
if point~=p1 and point~=p2 and point~=p3 and triangle:ContainsPoint(point)then
|
|
79878
|
+
is_valid_triangle=false
|
|
79879
|
+
break
|
|
79880
|
+
end
|
|
79881
|
+
end
|
|
79882
|
+
if is_valid_triangle then
|
|
79883
|
+
table.insert(triangles,triangle)
|
|
79884
|
+
local remaining_points={}
|
|
79885
|
+
for j,point in ipairs(shape_points)do
|
|
79886
|
+
if point~=p2 then
|
|
79887
|
+
table.insert(remaining_points,point)
|
|
79888
|
+
end
|
|
79889
|
+
end
|
|
79890
|
+
divide_recursively(remaining_points)
|
|
79891
|
+
break
|
|
79892
|
+
end
|
|
79893
|
+
end
|
|
79894
|
+
end
|
|
79895
|
+
end
|
|
79896
|
+
end
|
|
79897
|
+
points=ensure_clockwise(points)
|
|
79898
|
+
divide_recursively(points)
|
|
79899
|
+
return triangles
|
|
79900
|
+
end
|
|
79901
|
+
function POLYGON:CovarianceMatrix()
|
|
79902
|
+
local cx,cy=self:GetCentroid()
|
|
79903
|
+
local covXX,covYY,covXY=0,0,0
|
|
79904
|
+
for _,p in ipairs(self.points)do
|
|
79905
|
+
covXX=covXX+(p.x-cx)^2
|
|
79906
|
+
covYY=covYY+(p.y-cy)^2
|
|
79907
|
+
covXY=covXY+(p.x-cx)*(p.y-cy)
|
|
79908
|
+
end
|
|
79909
|
+
covXX=covXX/(#self.points-1)
|
|
79910
|
+
covYY=covYY/(#self.points-1)
|
|
79911
|
+
covXY=covXY/(#self.points-1)
|
|
79912
|
+
return covXX,covYY,covXY
|
|
79913
|
+
end
|
|
79914
|
+
function POLYGON:Direction()
|
|
79915
|
+
local covXX,covYY,covXY=self:CovarianceMatrix()
|
|
79916
|
+
local theta=0.5*math.atan2(2*covXY,covXX-covYY)
|
|
79917
|
+
return math.cos(theta),math.sin(theta)
|
|
79918
|
+
end
|
|
79919
|
+
function POLYGON:GetRandomVec2()
|
|
79920
|
+
local weights={}
|
|
79921
|
+
for _,triangle in pairs(self.Triangles)do
|
|
79922
|
+
weights[triangle]=triangle.SurfaceArea/self.SurfaceArea
|
|
79923
|
+
end
|
|
79924
|
+
local random_weight=math.random()
|
|
79925
|
+
local accumulated_weight=0
|
|
79926
|
+
for triangle,weight in pairs(weights)do
|
|
79927
|
+
accumulated_weight=accumulated_weight+weight
|
|
79928
|
+
if accumulated_weight>=random_weight then
|
|
79929
|
+
return triangle:GetRandomVec2()
|
|
79930
|
+
end
|
|
79931
|
+
end
|
|
79932
|
+
end
|
|
79933
|
+
function POLYGON:GetRandomNonWeightedVec2()
|
|
79934
|
+
return self.Triangles[math.random(1,#self.Triangles)]:GetRandomVec2()
|
|
79935
|
+
end
|
|
79936
|
+
function POLYGON:ContainsPoint(point,polygon_points)
|
|
79937
|
+
local x=point.x
|
|
79938
|
+
local y=point.y
|
|
79939
|
+
polygon_points=polygon_points or self.Points
|
|
79940
|
+
local counter=0
|
|
79941
|
+
local num_points=#polygon_points
|
|
79942
|
+
for current_index=1,num_points do
|
|
79943
|
+
local next_index=(current_index%num_points)+1
|
|
79944
|
+
local current_x,current_y=polygon_points[current_index].x,polygon_points[current_index].y
|
|
79945
|
+
local next_x,next_y=polygon_points[next_index].x,polygon_points[next_index].y
|
|
79946
|
+
if((current_y>y)~=(next_y>y))and(x<(next_x-current_x)*(y-current_y)/(next_y-current_y)+current_x)then
|
|
79947
|
+
counter=counter+1
|
|
79948
|
+
end
|
|
79949
|
+
end
|
|
79950
|
+
return counter%2==1
|
|
79951
|
+
end
|
|
79952
|
+
function POLYGON:Draw(include_inner_triangles)
|
|
79953
|
+
include_inner_triangles=include_inner_triangles or false
|
|
79954
|
+
for i=1,#self.Coords do
|
|
79955
|
+
local c1=self.Coords[i]
|
|
79956
|
+
local c2=self.Coords[i%#self.Coords+1]
|
|
79957
|
+
table.add(self.OutlineMarkIDs,c1:LineToAll(c2))
|
|
79958
|
+
end
|
|
79959
|
+
if include_inner_triangles then
|
|
79960
|
+
for _,triangle in ipairs(self.Triangles)do
|
|
79961
|
+
triangle:Draw()
|
|
79962
|
+
end
|
|
79963
|
+
end
|
|
79964
|
+
end
|
|
79965
|
+
function POLYGON:RemoveDraw()
|
|
79966
|
+
for _,triangle in pairs(self.Triangles)do
|
|
79967
|
+
triangle:RemoveDraw()
|
|
79968
|
+
end
|
|
79969
|
+
for _,mark_id in pairs(self.OutlineMarkIDs)do
|
|
79970
|
+
UTILS.RemoveMark(mark_id)
|
|
79971
|
+
end
|
|
79972
|
+
end
|
|
79973
|
+
function POLYGON:__CalculateSurfaceArea()
|
|
79974
|
+
local area=0
|
|
79975
|
+
for _,triangle in pairs(self.Triangles)do
|
|
79976
|
+
area=area+triangle.SurfaceArea
|
|
79977
|
+
end
|
|
79978
|
+
return area
|
|
79979
|
+
end
|
|
79980
|
+
TRIANGLE={
|
|
79981
|
+
ClassName="TRIANGLE",
|
|
79982
|
+
Points={},
|
|
79983
|
+
Coords={},
|
|
79984
|
+
SurfaceArea=0
|
|
79985
|
+
}
|
|
79986
|
+
function TRIANGLE:New(p1,p2,p3)
|
|
79987
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
79988
|
+
self.Points={p1,p2,p3}
|
|
79989
|
+
local center_x=(p1.x+p2.x+p3.x)/3
|
|
79990
|
+
local center_y=(p1.y+p2.y+p3.y)/3
|
|
79991
|
+
self.CenterVec2={x=center_x,y=center_y}
|
|
79992
|
+
for _,pt in pairs({p1,p2,p3})do
|
|
79993
|
+
table.add(self.Coords,COORDINATE:NewFromVec2(pt))
|
|
79994
|
+
end
|
|
79995
|
+
self.SurfaceArea=math.abs((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))*0.5
|
|
79996
|
+
self.MarkIDs={}
|
|
79997
|
+
return self
|
|
79998
|
+
end
|
|
79999
|
+
function TRIANGLE:ContainsPoint(pt,points)
|
|
80000
|
+
points=points or self.Points
|
|
80001
|
+
local function sign(p1,p2,p3)
|
|
80002
|
+
return(p1.x-p3.x)*(p2.y-p3.y)-(p2.x-p3.x)*(p1.y-p3.y)
|
|
80003
|
+
end
|
|
80004
|
+
local d1=sign(pt,self.Points[1],self.Points[2])
|
|
80005
|
+
local d2=sign(pt,self.Points[2],self.Points[3])
|
|
80006
|
+
local d3=sign(pt,self.Points[3],self.Points[1])
|
|
80007
|
+
local has_neg=(d1<0)or(d2<0)or(d3<0)
|
|
80008
|
+
local has_pos=(d1>0)or(d2>0)or(d3>0)
|
|
80009
|
+
return not(has_neg and has_pos)
|
|
80010
|
+
end
|
|
80011
|
+
function TRIANGLE:GetRandomVec2(points)
|
|
80012
|
+
points=points or self.Points
|
|
80013
|
+
local pt={math.random(),math.random()}
|
|
80014
|
+
table.sort(pt)
|
|
80015
|
+
local s=pt[1]
|
|
80016
|
+
local t=pt[2]-pt[1]
|
|
80017
|
+
local u=1-pt[2]
|
|
80018
|
+
return{x=s*points[1].x+t*points[2].x+u*points[3].x,
|
|
80019
|
+
y=s*points[1].y+t*points[2].y+u*points[3].y}
|
|
80020
|
+
end
|
|
80021
|
+
function TRIANGLE:Draw()
|
|
80022
|
+
for i=1,#self.Coords do
|
|
80023
|
+
local c1=self.Coords[i]
|
|
80024
|
+
local c2=self.Coords[i%#self.Coords+1]
|
|
80025
|
+
table.add(self.MarkIDs,c1:LineToAll(c2))
|
|
80026
|
+
end
|
|
80027
|
+
end
|
|
80028
|
+
function TRIANGLE:RemoveDraw()
|
|
80029
|
+
for _,mark_id in pairs(self.MarkIDs)do
|
|
80030
|
+
UTILS.RemoveMark(mark_id)
|
|
80031
|
+
end
|
|
80032
|
+
end
|
|
78530
80033
|
do
|
|
78531
80034
|
USERSOUND={
|
|
78532
80035
|
ClassName="USERSOUND",
|
|
@@ -79788,7 +81291,7 @@ end
|
|
|
79788
81291
|
function MSRS:SetVoiceProvider(Voice,Provider)
|
|
79789
81292
|
self:F({Voice=Voice,Provider=Provider})
|
|
79790
81293
|
self.poptions=self.poptions or{}
|
|
79791
|
-
self.poptions[Provider or self:GetProvider()]=Voice
|
|
81294
|
+
self.poptions[Provider or self:GetProvider()].voice=Voice
|
|
79792
81295
|
return self
|
|
79793
81296
|
end
|
|
79794
81297
|
function MSRS:SetVoiceWindows(Voice)
|
|
@@ -82636,7 +84139,7 @@ local ActRouteTarget=ProcessUnit:GetProcess("Engaging","RouteToTargetZone")
|
|
|
82636
84139
|
return ActRouteTarget:GetZone()
|
|
82637
84140
|
end
|
|
82638
84141
|
function TASK_A2G:SetGoalTotal()
|
|
82639
|
-
self.GoalTotal=self.TargetSetUnit:
|
|
84142
|
+
self.GoalTotal=self.TargetSetUnit:CountAlive()
|
|
82640
84143
|
end
|
|
82641
84144
|
function TASK_A2G:GetGoalTotal()
|
|
82642
84145
|
return self.GoalTotal
|
|
@@ -82649,7 +84152,7 @@ return Distance
|
|
|
82649
84152
|
end
|
|
82650
84153
|
function TASK_A2G:onafterGoal(TaskUnit,From,Event,To)
|
|
82651
84154
|
local TargetSetUnit=self.TargetSetUnit
|
|
82652
|
-
if TargetSetUnit:
|
|
84155
|
+
if TargetSetUnit:CountAlive()==0 then
|
|
82653
84156
|
self:Success()
|
|
82654
84157
|
end
|
|
82655
84158
|
self:__Goal(-10)
|
|
@@ -82667,7 +84170,7 @@ ThreatLevel,ThreatText=self.TargetSetUnit:CalculateThreatLevelA2G()
|
|
|
82667
84170
|
end
|
|
82668
84171
|
self.TaskInfo:AddThreat(ThreatText,ThreatLevel,10,"MOD",true)
|
|
82669
84172
|
if self.Detection then
|
|
82670
|
-
local DetectedItemsCount=self.TargetSetUnit:
|
|
84173
|
+
local DetectedItemsCount=self.TargetSetUnit:CountAlive()
|
|
82671
84174
|
local ReportTypes=REPORT:New()
|
|
82672
84175
|
local TargetTypes={}
|
|
82673
84176
|
for TargetUnitName,TargetUnit in pairs(self.TargetSetUnit:GetSet())do
|
|
@@ -82680,7 +84183,7 @@ end
|
|
|
82680
84183
|
self.TaskInfo:AddTargetCount(DetectedItemsCount,11,"O",true)
|
|
82681
84184
|
self.TaskInfo:AddTargets(DetectedItemsCount,ReportTypes:Text(", "),20,"D",true)
|
|
82682
84185
|
else
|
|
82683
|
-
local DetectedItemsCount=self.TargetSetUnit:
|
|
84186
|
+
local DetectedItemsCount=self.TargetSetUnit:CountAlive()
|
|
82684
84187
|
local DetectedItemsTypes=self.TargetSetUnit:GetTypeNames()
|
|
82685
84188
|
self.TaskInfo:AddTargetCount(DetectedItemsCount,11,"O",true)
|
|
82686
84189
|
self.TaskInfo:AddTargets(DetectedItemsCount,DetectedItemsTypes,20,"D",true)
|