@jtff/miztemplate-lib 3.2.1 → 3.2.3
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 +1883 -362
- 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-05-04T14:54:20+02:00-044fb66ca064687a743791e5a4a5d02c109ca9c1 ***')
|
|
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
|
|
@@ -18644,11 +18914,12 @@ self.SpawnRandomCallsign=true
|
|
|
18644
18914
|
return self
|
|
18645
18915
|
end
|
|
18646
18916
|
function SPAWN:InitCallSign(ID,Name,Minor,Major)
|
|
18917
|
+
local Name=Name or"Enfield"
|
|
18647
18918
|
self.SpawnInitCallSign=true
|
|
18648
18919
|
self.SpawnInitCallSignID=ID or 1
|
|
18649
18920
|
self.SpawnInitCallSignMinor=Minor or 1
|
|
18650
18921
|
self.SpawnInitCallSignMajor=Major or 1
|
|
18651
|
-
self.SpawnInitCallSignName=string.lower(Name)
|
|
18922
|
+
self.SpawnInitCallSignName=string.lower(Name):gsub("^%l",string.upper)
|
|
18652
18923
|
return self
|
|
18653
18924
|
end
|
|
18654
18925
|
function SPAWN:InitPositionCoordinate(Coordinate)
|
|
@@ -18761,6 +19032,18 @@ function SPAWN:InitDelayOff()
|
|
|
18761
19032
|
return self:InitDelayOnOff(false)
|
|
18762
19033
|
end
|
|
18763
19034
|
end
|
|
19035
|
+
function SPAWN:InitHiddenOnMap()
|
|
19036
|
+
self.SpawnHiddenOnMap=true
|
|
19037
|
+
return self
|
|
19038
|
+
end
|
|
19039
|
+
function SPAWN:InitHiddenOnMFD()
|
|
19040
|
+
self.SpawnHiddenOnMFD=true
|
|
19041
|
+
return self
|
|
19042
|
+
end
|
|
19043
|
+
function SPAWN:InitHiddenOnPlanner()
|
|
19044
|
+
self.SpawnHiddenOnPlanner=true
|
|
19045
|
+
return self
|
|
19046
|
+
end
|
|
18764
19047
|
function SPAWN:Spawn()
|
|
18765
19048
|
self:F({self.SpawnTemplatePrefix,self.SpawnIndex,self.AliveUnits})
|
|
18766
19049
|
if self.SpawnInitAirbase then
|
|
@@ -18953,6 +19236,15 @@ end
|
|
|
18953
19236
|
if self.SpawnInitModu then
|
|
18954
19237
|
SpawnTemplate.modulation=self.SpawnInitModu
|
|
18955
19238
|
end
|
|
19239
|
+
if self.SpawnHiddenOnPlanner then
|
|
19240
|
+
SpawnTemplate.hiddenOnPlanner=true
|
|
19241
|
+
end
|
|
19242
|
+
if self.SpawnHiddenOnMFD then
|
|
19243
|
+
SpawnTemplate.hiddenOnMFD=true
|
|
19244
|
+
end
|
|
19245
|
+
if self.SpawnHiddenOnMap then
|
|
19246
|
+
SpawnTemplate.hidden=true
|
|
19247
|
+
end
|
|
18956
19248
|
SpawnTemplate.CategoryID=self.SpawnInitCategory or SpawnTemplate.CategoryID
|
|
18957
19249
|
SpawnTemplate.CountryID=self.SpawnInitCountry or SpawnTemplate.CountryID
|
|
18958
19250
|
SpawnTemplate.CoalitionID=self.SpawnInitCoalition or SpawnTemplate.CoalitionID
|
|
@@ -18981,6 +19273,7 @@ self.SpawnHookScheduler:Schedule(nil,self.SpawnFunctionHook,{self.SpawnGroups[se
|
|
|
18981
19273
|
end
|
|
18982
19274
|
end
|
|
18983
19275
|
self.SpawnGroups[self.SpawnIndex].Spawned=true
|
|
19276
|
+
self.SpawnGroups[self.SpawnIndex].Group.TemplateDonor=self.SpawnTemplatePrefix
|
|
18984
19277
|
return self.SpawnGroups[self.SpawnIndex].Group
|
|
18985
19278
|
else
|
|
18986
19279
|
end
|
|
@@ -19786,8 +20079,17 @@ SpawnTemplate.units[UnitID].unitId=nil
|
|
|
19786
20079
|
end
|
|
19787
20080
|
else
|
|
19788
20081
|
for UnitID=1,#SpawnTemplate.units do
|
|
19789
|
-
local
|
|
20082
|
+
local SpawnInitKeepUnitIFF=false
|
|
20083
|
+
if string.find(SpawnTemplate.units[UnitID].name,"#IFF_",1,true)then
|
|
20084
|
+
SpawnInitKeepUnitIFF=true
|
|
20085
|
+
end
|
|
20086
|
+
local UnitPrefix,Rest
|
|
20087
|
+
if SpawnInitKeepUnitIFF==false then
|
|
20088
|
+
UnitPrefix,Rest=string.match(SpawnTemplate.units[UnitID].name,"^([^#]+)#?"):gsub("^%s*(.-)%s*$","%1")
|
|
19790
20089
|
self:T({UnitPrefix,Rest})
|
|
20090
|
+
else
|
|
20091
|
+
UnitPrefix=SpawnTemplate.units[UnitID].name
|
|
20092
|
+
end
|
|
19791
20093
|
SpawnTemplate.units[UnitID].name=string.format('%s#%03d-%02d',UnitPrefix,SpawnIndex,UnitID)
|
|
19792
20094
|
SpawnTemplate.units[UnitID].unitId=nil
|
|
19793
20095
|
end
|
|
@@ -19859,32 +20161,54 @@ elseif type(Callsign)=="number"then
|
|
|
19859
20161
|
SpawnTemplate.units[UnitID].callsign=Callsign+SpawnIndex
|
|
19860
20162
|
end
|
|
19861
20163
|
end
|
|
20164
|
+
if self.InitSpeed then
|
|
20165
|
+
SpawnTemplate.units[UnitID].speed=self.InitSpeed
|
|
20166
|
+
end
|
|
19862
20167
|
local AddProps=SpawnTemplate.units[UnitID].AddPropAircraft
|
|
19863
20168
|
if AddProps then
|
|
19864
20169
|
if SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 then
|
|
20170
|
+
if self.SpawnInitSTN then
|
|
20171
|
+
local octal=self.SpawnInitSTN
|
|
20172
|
+
if UnitID>1 then
|
|
20173
|
+
octal=_DATABASE:GetNextSTN(self.SpawnInitSTN,SpawnTemplate.units[UnitID].name)
|
|
20174
|
+
end
|
|
20175
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16=string.format("%05d",octal)
|
|
20176
|
+
else
|
|
19865
20177
|
if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16)~=nil then
|
|
19866
20178
|
local octal=SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16
|
|
19867
|
-
local
|
|
19868
|
-
|
|
20179
|
+
local num=UTILS.OctalToDecimal(octal)
|
|
20180
|
+
if _DATABASE.STNS[num]~=nil or UnitID>1 then
|
|
20181
|
+
octal=_DATABASE:GetNextSTN(octal,SpawnTemplate.units[UnitID].name)
|
|
20182
|
+
end
|
|
20183
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16=string.format("%05d",octal)
|
|
19869
20184
|
else
|
|
19870
|
-
local
|
|
19871
|
-
STN=STN+UnitID-1
|
|
19872
|
-
local OSTN=UTILS.DecimalToOctal(STN)
|
|
20185
|
+
local OSTN=_DATABASE:GetNextSTN(1,SpawnTemplate.units[UnitID].name)
|
|
19873
20186
|
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16=string.format("%05d",OSTN)
|
|
19874
20187
|
end
|
|
19875
20188
|
end
|
|
20189
|
+
end
|
|
19876
20190
|
if SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN then
|
|
20191
|
+
if self.SpawnInitSADL then
|
|
20192
|
+
local octal=self.SpawnInitSADL
|
|
20193
|
+
if UnitID>1 then
|
|
20194
|
+
octal=_DATABASE:GetNextSADL(self.SpawnInitSADL,SpawnTemplate.units[UnitID].name)
|
|
20195
|
+
end
|
|
20196
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN=string.format("%04d",octal)
|
|
20197
|
+
else
|
|
19877
20198
|
if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN)~=nil then
|
|
19878
20199
|
local octal=SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN
|
|
19879
|
-
local
|
|
19880
|
-
|
|
20200
|
+
local num=UTILS.OctalToDecimal(octal)
|
|
20201
|
+
self.SpawnInitSADL=num
|
|
20202
|
+
if _DATABASE.SADL[num]~=nil or UnitID>1 then
|
|
20203
|
+
octal=_DATABASE:GetNextSADL(self.SpawnInitSADL,SpawnTemplate.units[UnitID].name)
|
|
20204
|
+
end
|
|
20205
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN=string.format("%04d",octal)
|
|
19881
20206
|
else
|
|
19882
|
-
local
|
|
19883
|
-
STN=STN+UnitID-1
|
|
19884
|
-
local OSTN=UTILS.DecimalToOctal(STN)
|
|
20207
|
+
local OSTN=_DATABASE:GetNextSADL(1,SpawnTemplate.units[UnitID].name)
|
|
19885
20208
|
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN=string.format("%04d",OSTN)
|
|
19886
20209
|
end
|
|
19887
20210
|
end
|
|
20211
|
+
end
|
|
19888
20212
|
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber and type(Callsign)~="number"then
|
|
19889
20213
|
SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber=SpawnTemplate.units[UnitID].callsign[2]..SpawnTemplate.units[UnitID].callsign[3]
|
|
19890
20214
|
end
|
|
@@ -20648,7 +20972,7 @@ MARKEROPS_BASE={
|
|
|
20648
20972
|
ClassName="MARKEROPS",
|
|
20649
20973
|
Tag="mytag",
|
|
20650
20974
|
Keywords={},
|
|
20651
|
-
version="0.1.
|
|
20975
|
+
version="0.1.3",
|
|
20652
20976
|
debug=false,
|
|
20653
20977
|
Casesensitive=true,
|
|
20654
20978
|
}
|
|
@@ -20688,26 +21012,27 @@ local coordtext=coord:ToStringLLDDM()
|
|
|
20688
21012
|
local text=tostring(Event.text)
|
|
20689
21013
|
local m=MESSAGE:New(string.format("Mark added at %s with text: %s",coordtext,text),10,"Info",false):ToAll()
|
|
20690
21014
|
end
|
|
21015
|
+
local coalition=Event.MarkCoalition
|
|
20691
21016
|
if Event.id==world.event.S_EVENT_MARK_ADDED then
|
|
20692
|
-
self:T({event="S_EVENT_MARK_ADDED",carrier=
|
|
21017
|
+
self:T({event="S_EVENT_MARK_ADDED",carrier=Event.IniGroupName,vec3=Event.pos})
|
|
20693
21018
|
local Eventtext=tostring(Event.text)
|
|
20694
21019
|
if Eventtext~=nil then
|
|
20695
21020
|
if self:_MatchTag(Eventtext)then
|
|
20696
21021
|
local matchtable=self:_MatchKeywords(Eventtext)
|
|
20697
|
-
self:MarkAdded(Eventtext,matchtable,coord)
|
|
21022
|
+
self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition)
|
|
20698
21023
|
end
|
|
20699
21024
|
end
|
|
20700
21025
|
elseif Event.id==world.event.S_EVENT_MARK_CHANGE then
|
|
20701
|
-
self:T({event="S_EVENT_MARK_CHANGE",carrier=
|
|
21026
|
+
self:T({event="S_EVENT_MARK_CHANGE",carrier=Event.IniGroupName,vec3=Event.pos})
|
|
20702
21027
|
local Eventtext=tostring(Event.text)
|
|
20703
21028
|
if Eventtext~=nil then
|
|
20704
21029
|
if self:_MatchTag(Eventtext)then
|
|
20705
21030
|
local matchtable=self:_MatchKeywords(Eventtext)
|
|
20706
|
-
self:MarkChanged(Eventtext,matchtable,coord,Event.idx)
|
|
21031
|
+
self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition)
|
|
20707
21032
|
end
|
|
20708
21033
|
end
|
|
20709
21034
|
elseif Event.id==world.event.S_EVENT_MARK_REMOVED then
|
|
20710
|
-
self:T({event="S_EVENT_MARK_REMOVED",carrier=
|
|
21035
|
+
self:T({event="S_EVENT_MARK_REMOVED",carrier=Event.IniGroupName,vec3=Event.pos})
|
|
20711
21036
|
local Eventtext=tostring(Event.text)
|
|
20712
21037
|
if Eventtext~=nil then
|
|
20713
21038
|
if self:_MatchTag(Eventtext)then
|
|
@@ -20741,10 +21066,10 @@ end
|
|
|
20741
21066
|
end
|
|
20742
21067
|
return matchtable
|
|
20743
21068
|
end
|
|
20744
|
-
function MARKEROPS_BASE:onbeforeMarkAdded(From,Event,To,Text,Keywords,Coord)
|
|
21069
|
+
function MARKEROPS_BASE:onbeforeMarkAdded(From,Event,To,Text,Keywords,Coord,MarkerID,CoalitionNumber)
|
|
20745
21070
|
self:T({self.lid,From,Event,To,Text,Keywords,Coord:ToStringLLDDM()})
|
|
20746
21071
|
end
|
|
20747
|
-
function MARKEROPS_BASE:onbeforeMarkChanged(From,Event,To,Text,Keywords,Coord)
|
|
21072
|
+
function MARKEROPS_BASE:onbeforeMarkChanged(From,Event,To,Text,Keywords,Coord,MarkerID,CoalitionNumber)
|
|
20748
21073
|
self:T({self.lid,From,Event,To,Text,Keywords,Coord:ToStringLLDDM()})
|
|
20749
21074
|
end
|
|
20750
21075
|
function MARKEROPS_BASE:onbeforeMarkDeleted(From,Event,To)
|
|
@@ -23225,7 +23550,7 @@ local TaskRoute=PatrolGroup:TaskFunction("CONTROLLABLE.PatrolRoute")
|
|
|
23225
23550
|
self:F({Waypoints=Waypoints})
|
|
23226
23551
|
local Waypoint=Waypoints[#Waypoints]
|
|
23227
23552
|
PatrolGroup:SetTaskWaypoint(Waypoint,TaskRoute)
|
|
23228
|
-
PatrolGroup:Route(Waypoints)
|
|
23553
|
+
PatrolGroup:Route(Waypoints,2)
|
|
23229
23554
|
end
|
|
23230
23555
|
end
|
|
23231
23556
|
function CONTROLLABLE:PatrolRouteRandom(Speed,Formation,ToWaypoint)
|
|
@@ -24183,6 +24508,9 @@ return nil
|
|
|
24183
24508
|
end
|
|
24184
24509
|
function CONTROLLABLE:WayPointFunction(WayPoint,WayPointIndex,WayPointFunction,...)
|
|
24185
24510
|
self:F2({WayPoint,WayPointIndex,WayPointFunction})
|
|
24511
|
+
if not self.WayPoints then
|
|
24512
|
+
self:WayPointInitialize()
|
|
24513
|
+
end
|
|
24186
24514
|
table.insert(self.WayPoints[WayPoint].task.params.tasks,WayPointIndex)
|
|
24187
24515
|
self.WayPoints[WayPoint].task.params.tasks[WayPointIndex]=self:TaskFunction(WayPointFunction,arg)
|
|
24188
24516
|
return self
|
|
@@ -24306,6 +24634,49 @@ self:SetOption(AI.Option.Air.id.RADAR_USING,3)
|
|
|
24306
24634
|
end
|
|
24307
24635
|
return self
|
|
24308
24636
|
end
|
|
24637
|
+
function CONTROLLABLE:SetOptionWaypointPassReport(OnOff)
|
|
24638
|
+
self:F2({self.ControllableName})
|
|
24639
|
+
local onoff=(OnOff==nil or OnOff==true)and false or true
|
|
24640
|
+
if self:IsAir()then
|
|
24641
|
+
self:SetOption(AI.Option.Air.id.PROHIBIT_WP_PASS_REPORT,onoff)
|
|
24642
|
+
end
|
|
24643
|
+
return self
|
|
24644
|
+
end
|
|
24645
|
+
function CONTROLLABLE:SetOptionRadioSilence(OnOff)
|
|
24646
|
+
local onoff=(OnOff==true or OnOff==nil)and true or false
|
|
24647
|
+
self:F2({self.ControllableName})
|
|
24648
|
+
if self:IsAir()then
|
|
24649
|
+
self:SetOption(AI.Option.Air.id.SILENCE,onoff)
|
|
24650
|
+
end
|
|
24651
|
+
return self
|
|
24652
|
+
end
|
|
24653
|
+
function CONTROLLABLE:SetOptionRadioContact(Objects)
|
|
24654
|
+
self:F2({self.ControllableName})
|
|
24655
|
+
if not Objects then Objects={"Air"}end
|
|
24656
|
+
if type(Objects)~="table"then Objects={Objects}end
|
|
24657
|
+
if self:IsAir()then
|
|
24658
|
+
self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_CONTACT,Objects)
|
|
24659
|
+
end
|
|
24660
|
+
return self
|
|
24661
|
+
end
|
|
24662
|
+
function CONTROLLABLE:SetOptionRadioEngage(Objects)
|
|
24663
|
+
self:F2({self.ControllableName})
|
|
24664
|
+
if not Objects then Objects={"Air"}end
|
|
24665
|
+
if type(Objects)~="table"then Objects={Objects}end
|
|
24666
|
+
if self:IsAir()then
|
|
24667
|
+
self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_ENGAGE,Objects)
|
|
24668
|
+
end
|
|
24669
|
+
return self
|
|
24670
|
+
end
|
|
24671
|
+
function CONTROLLABLE:SetOptionRadioKill(Objects)
|
|
24672
|
+
self:F2({self.ControllableName})
|
|
24673
|
+
if not Objects then Objects={"Air"}end
|
|
24674
|
+
if type(Objects)~="table"then Objects={Objects}end
|
|
24675
|
+
if self:IsAir()then
|
|
24676
|
+
self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_KILL,Objects)
|
|
24677
|
+
end
|
|
24678
|
+
return self
|
|
24679
|
+
end
|
|
24309
24680
|
function CONTROLLABLE:RelocateGroundRandomInRadius(speed,radius,onroad,shortcut,formation,onland)
|
|
24310
24681
|
self:F2({self.ControllableName})
|
|
24311
24682
|
local _coord=self:GetCoordinate()
|
|
@@ -25377,7 +25748,7 @@ end
|
|
|
25377
25748
|
function GROUP:IsActive()
|
|
25378
25749
|
self:F2(self.GroupName)
|
|
25379
25750
|
local DCSGroup=self:GetDCSObject()
|
|
25380
|
-
if DCSGroup then
|
|
25751
|
+
if DCSGroup and DCSGroup:isExist()then
|
|
25381
25752
|
local unit=DCSGroup:getUnit(1)
|
|
25382
25753
|
if unit then
|
|
25383
25754
|
local GroupIsActive=unit:isActive()
|
|
@@ -25835,7 +26206,7 @@ function GROUP:GetCoordinate()
|
|
|
25835
26206
|
local Units=self:GetUnits()or{}
|
|
25836
26207
|
for _,_unit in pairs(Units)do
|
|
25837
26208
|
local FirstUnit=_unit
|
|
25838
|
-
if FirstUnit then
|
|
26209
|
+
if FirstUnit and FirstUnit:IsAlive()then
|
|
25839
26210
|
local FirstUnitCoordinate=FirstUnit:GetCoordinate()
|
|
25840
26211
|
if FirstUnitCoordinate then
|
|
25841
26212
|
local Heading=self:GetHeading()
|
|
@@ -25844,6 +26215,18 @@ return FirstUnitCoordinate
|
|
|
25844
26215
|
end
|
|
25845
26216
|
end
|
|
25846
26217
|
end
|
|
26218
|
+
local DCSGroup=Group.getByName(self.GroupName)
|
|
26219
|
+
local DCSUnits=DCSGroup:getUnits()or{}
|
|
26220
|
+
for _,_unit in pairs(DCSUnits)do
|
|
26221
|
+
if Object.isExist(_unit)then
|
|
26222
|
+
local position=_unit:getPosition()
|
|
26223
|
+
local point=position.p~=nil and position.p or _unit:GetPoint()
|
|
26224
|
+
if point then
|
|
26225
|
+
local coord=COORDINATE:NewFromVec3(point)
|
|
26226
|
+
return coord
|
|
26227
|
+
end
|
|
26228
|
+
end
|
|
26229
|
+
end
|
|
25847
26230
|
BASE:E({"Cannot GetCoordinate",Group=self,Alive=self:IsAlive()})
|
|
25848
26231
|
end
|
|
25849
26232
|
function GROUP:GetRandomVec3(Radius)
|
|
@@ -26705,6 +27088,9 @@ end
|
|
|
26705
27088
|
return self
|
|
26706
27089
|
end
|
|
26707
27090
|
function GROUP:SetCommandInvisible(switch)
|
|
27091
|
+
return self:CommandSetInvisible(switch)
|
|
27092
|
+
end
|
|
27093
|
+
function GROUP:CommandSetInvisible(switch)
|
|
26708
27094
|
self:F2(self.GroupName)
|
|
26709
27095
|
if switch==nil then
|
|
26710
27096
|
switch=false
|
|
@@ -26714,6 +27100,9 @@ self:SetCommand(SetInvisible)
|
|
|
26714
27100
|
return self
|
|
26715
27101
|
end
|
|
26716
27102
|
function GROUP:SetCommandImmortal(switch)
|
|
27103
|
+
return self:CommandSetImmortal(switch)
|
|
27104
|
+
end
|
|
27105
|
+
function GROUP:CommandSetImmortal(switch)
|
|
26717
27106
|
self:F2(self.GroupName)
|
|
26718
27107
|
if switch==nil then
|
|
26719
27108
|
switch=false
|
|
@@ -27445,7 +27834,9 @@ local ThreatLevels={
|
|
|
27445
27834
|
}
|
|
27446
27835
|
if Attributes["Fighters"]then ThreatLevel=10
|
|
27447
27836
|
elseif Attributes["Multirole fighters"]then ThreatLevel=9
|
|
27837
|
+
elseif Attributes["Interceptors"]then ThreatLevel=9
|
|
27448
27838
|
elseif Attributes["Battleplanes"]then ThreatLevel=8
|
|
27839
|
+
elseif Attributes["Battle airplanes"]then ThreatLevel=8
|
|
27449
27840
|
elseif Attributes["Attack helicopters"]then ThreatLevel=7
|
|
27450
27841
|
elseif Attributes["Strategic bombers"]then ThreatLevel=6
|
|
27451
27842
|
elseif Attributes["Bombers"]then ThreatLevel=5
|
|
@@ -28075,6 +28466,25 @@ SpawnStatic:SpawnFromCoordinate(Coordinate,Heading,self.StaticName)
|
|
|
28075
28466
|
end
|
|
28076
28467
|
return self
|
|
28077
28468
|
end
|
|
28469
|
+
function STATIC:FindByMatching(Pattern)
|
|
28470
|
+
local GroupFound=nil
|
|
28471
|
+
for name,static in pairs(_DATABASE.STATICS)do
|
|
28472
|
+
if string.match(name,Pattern)then
|
|
28473
|
+
GroupFound=static
|
|
28474
|
+
break
|
|
28475
|
+
end
|
|
28476
|
+
end
|
|
28477
|
+
return GroupFound
|
|
28478
|
+
end
|
|
28479
|
+
function STATIC:FindAllByMatching(Pattern)
|
|
28480
|
+
local GroupsFound={}
|
|
28481
|
+
for name,static in pairs(_DATABASE.STATICS)do
|
|
28482
|
+
if string.match(name,Pattern)then
|
|
28483
|
+
GroupsFound[#GroupsFound+1]=static
|
|
28484
|
+
end
|
|
28485
|
+
end
|
|
28486
|
+
return GroupsFound
|
|
28487
|
+
end
|
|
28078
28488
|
AIRBASE={
|
|
28079
28489
|
ClassName="AIRBASE",
|
|
28080
28490
|
CategoryName={
|
|
@@ -28085,152 +28495,155 @@ CategoryName={
|
|
|
28085
28495
|
activerwyno=nil,
|
|
28086
28496
|
}
|
|
28087
28497
|
AIRBASE.Caucasus={
|
|
28498
|
+
["Anapa_Vityazevo"]="Anapa-Vityazevo",
|
|
28499
|
+
["Batumi"]="Batumi",
|
|
28500
|
+
["Beslan"]="Beslan",
|
|
28088
28501
|
["Gelendzhik"]="Gelendzhik",
|
|
28089
|
-
["Krasnodar_Pashkovsky"]="Krasnodar-Pashkovsky",
|
|
28090
|
-
["Sukhumi_Babushara"]="Sukhumi-Babushara",
|
|
28091
28502
|
["Gudauta"]="Gudauta",
|
|
28092
|
-
["Batumi"]="Batumi",
|
|
28093
|
-
["Senaki_Kolkhi"]="Senaki-Kolkhi",
|
|
28094
28503
|
["Kobuleti"]="Kobuleti",
|
|
28095
|
-
["Kutaisi"]="Kutaisi",
|
|
28096
|
-
["Tbilisi_Lochini"]="Tbilisi-Lochini",
|
|
28097
|
-
["Soganlug"]="Soganlug",
|
|
28098
|
-
["Vaziani"]="Vaziani",
|
|
28099
|
-
["Anapa_Vityazevo"]="Anapa-Vityazevo",
|
|
28100
28504
|
["Krasnodar_Center"]="Krasnodar-Center",
|
|
28101
|
-
["
|
|
28505
|
+
["Krasnodar_Pashkovsky"]="Krasnodar-Pashkovsky",
|
|
28102
28506
|
["Krymsk"]="Krymsk",
|
|
28507
|
+
["Kutaisi"]="Kutaisi",
|
|
28103
28508
|
["Maykop_Khanskaya"]="Maykop-Khanskaya",
|
|
28104
|
-
["Sochi_Adler"]="Sochi-Adler",
|
|
28105
28509
|
["Mineralnye_Vody"]="Mineralnye Vody",
|
|
28106
|
-
["Nalchik"]="Nalchik",
|
|
28107
28510
|
["Mozdok"]="Mozdok",
|
|
28108
|
-
["
|
|
28511
|
+
["Nalchik"]="Nalchik",
|
|
28512
|
+
["Novorossiysk"]="Novorossiysk",
|
|
28513
|
+
["Senaki_Kolkhi"]="Senaki-Kolkhi",
|
|
28514
|
+
["Sochi_Adler"]="Sochi-Adler",
|
|
28515
|
+
["Soganlug"]="Soganlug",
|
|
28516
|
+
["Sukhumi_Babushara"]="Sukhumi-Babushara",
|
|
28517
|
+
["Tbilisi_Lochini"]="Tbilisi-Lochini",
|
|
28518
|
+
["Vaziani"]="Vaziani",
|
|
28109
28519
|
}
|
|
28110
28520
|
AIRBASE.Nevada={
|
|
28111
|
-
["
|
|
28112
|
-
["
|
|
28113
|
-
["
|
|
28114
|
-
["Nellis_AFB"]="Nellis",
|
|
28115
|
-
["Beatty_Airport"]="Beatty",
|
|
28116
|
-
["Boulder_City_Airport"]="Boulder City",
|
|
28521
|
+
["Beatty"]="Beatty",
|
|
28522
|
+
["Boulder_City"]="Boulder City",
|
|
28523
|
+
["Creech"]="Creech",
|
|
28117
28524
|
["Echo_Bay"]="Echo Bay",
|
|
28118
|
-
["
|
|
28119
|
-
["
|
|
28120
|
-
["
|
|
28525
|
+
["Groom_Lake"]="Groom Lake",
|
|
28526
|
+
["Henderson_Executive"]="Henderson Executive",
|
|
28527
|
+
["Jean"]="Jean",
|
|
28528
|
+
["Laughlin"]="Laughlin",
|
|
28121
28529
|
["Lincoln_County"]="Lincoln County",
|
|
28530
|
+
["McCarran_International"]="McCarran International",
|
|
28122
28531
|
["Mesquite"]="Mesquite",
|
|
28123
|
-
["
|
|
28532
|
+
["Mina"]="Mina",
|
|
28533
|
+
["Nellis"]="Nellis",
|
|
28124
28534
|
["North_Las_Vegas"]="North Las Vegas",
|
|
28125
|
-
["
|
|
28126
|
-
["
|
|
28127
|
-
["
|
|
28535
|
+
["Pahute_Mesa"]="Pahute Mesa",
|
|
28536
|
+
["Tonopah"]="Tonopah",
|
|
28537
|
+
["Tonopah_Test_Range"]="Tonopah Test Range",
|
|
28128
28538
|
}
|
|
28129
28539
|
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",
|
|
28540
|
+
["Abbeville_Drucat"]="Abbeville Drucat",
|
|
28541
|
+
["Amiens_Glisy"]="Amiens-Glisy",
|
|
28542
|
+
["Argentan"]="Argentan",
|
|
28543
|
+
["Avranches_Le_Val_Saint_Pere"]="Avranches Le Val-Saint-Pere",
|
|
28144
28544
|
["Azeville"]="Azeville",
|
|
28145
|
-
["
|
|
28146
|
-
["Le_Molay"]="Le Molay",
|
|
28147
|
-
["Longues_sur_Mer"]="Longues-sur-Mer",
|
|
28148
|
-
["Carpiquet"]="Carpiquet",
|
|
28545
|
+
["Barville"]="Barville",
|
|
28149
28546
|
["Bazenville"]="Bazenville",
|
|
28150
|
-
["
|
|
28547
|
+
["Beaumont_le_Roger"]="Beaumont-le-Roger",
|
|
28548
|
+
["Beauvais_Tille"]="Beauvais-Tille",
|
|
28151
28549
|
["Beny_sur_Mer"]="Beny-sur-Mer",
|
|
28152
|
-
["
|
|
28153
|
-
["
|
|
28154
|
-
["
|
|
28155
|
-
["
|
|
28550
|
+
["Bernay_Saint_Martin"]="Bernay Saint Martin",
|
|
28551
|
+
["Beuzeville"]="Beuzeville",
|
|
28552
|
+
["Biggin_Hill"]="Biggin Hill",
|
|
28553
|
+
["Biniville"]="Biniville",
|
|
28554
|
+
["Broglie"]="Broglie",
|
|
28555
|
+
["Brucheville"]="Brucheville",
|
|
28556
|
+
["Cardonville"]="Cardonville",
|
|
28557
|
+
["Carpiquet"]="Carpiquet",
|
|
28156
28558
|
["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",
|
|
28559
|
+
["Chippelle"]="Chippelle",
|
|
28169
28560
|
["Conches"]="Conches",
|
|
28170
|
-
["West_Malling"]="West Malling",
|
|
28171
|
-
["Villacoublay"]="Villacoublay",
|
|
28172
|
-
["Kenley"]="Kenley",
|
|
28173
|
-
["Beauvais_Tille"]="Beauvais-Tille",
|
|
28174
28561
|
["Cormeilles_en_Vexin"]="Cormeilles-en-Vexin",
|
|
28175
28562
|
["Creil"]="Creil",
|
|
28176
|
-
["
|
|
28177
|
-
["
|
|
28563
|
+
["Cretteville"]="Cretteville",
|
|
28564
|
+
["Cricqueville_en_Bessin"]="Cricqueville-en-Bessin",
|
|
28565
|
+
["Deanland"]="Deanland",
|
|
28566
|
+
["Deauville"]="Deauville",
|
|
28567
|
+
["Detling"]="Detling",
|
|
28568
|
+
["Deux_Jumeaux"]="Deux Jumeaux",
|
|
28178
28569
|
["Dinan_Trelivan"]="Dinan-Trelivan",
|
|
28179
|
-
["
|
|
28180
|
-
["
|
|
28570
|
+
["Dunkirk_Mardyck"]="Dunkirk-Mardyck",
|
|
28571
|
+
["Essay"]="Essay",
|
|
28572
|
+
["Evreux"]="Evreux",
|
|
28181
28573
|
["Farnborough"]="Farnborough",
|
|
28574
|
+
["Fecamp_Benouville"]="Fecamp-Benouville",
|
|
28575
|
+
["Flers"]="Flers",
|
|
28576
|
+
["Ford"]="Ford",
|
|
28182
28577
|
["Friston"]="Friston",
|
|
28183
|
-
["
|
|
28184
|
-
["
|
|
28185
|
-
["
|
|
28578
|
+
["Funtington"]="Funtington",
|
|
28579
|
+
["Goulet"]="Goulet",
|
|
28580
|
+
["Gravesend"]="Gravesend",
|
|
28581
|
+
["Guyancourt"]="Guyancourt",
|
|
28582
|
+
["Hauterive"]="Hauterive",
|
|
28583
|
+
["Heathrow"]="Heathrow",
|
|
28584
|
+
["High_Halden"]="High Halden",
|
|
28585
|
+
["Kenley"]="Kenley",
|
|
28586
|
+
["Lantheuil"]="Lantheuil",
|
|
28587
|
+
["Le_Molay"]="Le Molay",
|
|
28588
|
+
["Lessay"]="Lessay",
|
|
28589
|
+
["Lignerolles"]="Lignerolles",
|
|
28590
|
+
["Longues_sur_Mer"]="Longues-sur-Mer",
|
|
28591
|
+
["Lonrai"]="Lonrai",
|
|
28592
|
+
["Lymington"]="Lymington",
|
|
28593
|
+
["Lympne"]="Lympne",
|
|
28594
|
+
["Manston"]="Manston",
|
|
28595
|
+
["Maupertus"]="Maupertus",
|
|
28596
|
+
["Meautis"]="Meautis",
|
|
28597
|
+
["Merville_Calonne"]="Merville Calonne",
|
|
28598
|
+
["Needs_Oar_Point"]="Needs Oar Point",
|
|
28599
|
+
["Odiham"]="Odiham",
|
|
28186
28600
|
["Orly"]="Orly",
|
|
28187
|
-
["
|
|
28188
|
-
["
|
|
28601
|
+
["Picauville"]="Picauville",
|
|
28602
|
+
["Poix"]="Poix",
|
|
28189
28603
|
["Ronai"]="Ronai",
|
|
28190
28604
|
["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",
|
|
28605
|
+
["Rucqueville"]="Rucqueville",
|
|
28199
28606
|
["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",
|
|
28607
|
+
["Saint_Aubin"]="Saint-Aubin",
|
|
28206
28608
|
["Saint_Omer_Wizernes"]="Saint-Omer Wizernes",
|
|
28609
|
+
["Saint_Pierre_du_Mont"]="Saint Pierre du Mont",
|
|
28610
|
+
["Sainte_Croix_sur_Mer"]="Sainte-Croix-sur-Mer",
|
|
28611
|
+
["Sainte_Laurent_sur_Mer"]="Sainte-Laurent-sur-Mer",
|
|
28612
|
+
["Sommervieu"]="Sommervieu",
|
|
28613
|
+
["Stoney_Cross"]="Stoney Cross",
|
|
28614
|
+
["Tangmere"]="Tangmere",
|
|
28615
|
+
["Triqueville"]="Triqueville",
|
|
28616
|
+
["Villacoublay"]="Villacoublay",
|
|
28617
|
+
["Vrigny"]="Vrigny",
|
|
28618
|
+
["West_Malling"]="West Malling",
|
|
28207
28619
|
}
|
|
28208
28620
|
AIRBASE.PersianGulf={
|
|
28209
|
-
["
|
|
28210
|
-
["
|
|
28211
|
-
["
|
|
28212
|
-
["
|
|
28213
|
-
["
|
|
28621
|
+
["Abu_Dhabi_Intl"]="Abu Dhabi Intl",
|
|
28622
|
+
["Abu_Musa_Island"]="Abu Musa Island",
|
|
28623
|
+
["Al_Ain_Intl"]="Al Ain Intl",
|
|
28624
|
+
["Al_Bateen"]="Al-Bateen",
|
|
28625
|
+
["Al_Dhafra_AFB"]="Al Dhafra AFB",
|
|
28214
28626
|
["Al_Maktoum_Intl"]="Al Maktoum Intl",
|
|
28215
|
-
["
|
|
28627
|
+
["Al_Minhad_AFB"]="Al Minhad AFB",
|
|
28216
28628
|
["Bandar_Abbas_Intl"]="Bandar Abbas Intl",
|
|
28217
28629
|
["Bandar_Lengeh"]="Bandar Lengeh",
|
|
28218
|
-
["
|
|
28630
|
+
["Bandar_e_Jask"]="Bandar-e-Jask",
|
|
28219
28631
|
["Dubai_Intl"]="Dubai Intl",
|
|
28220
28632
|
["Fujairah_Intl"]="Fujairah Intl",
|
|
28221
28633
|
["Havadarya"]="Havadarya",
|
|
28222
|
-
["
|
|
28223
|
-
["
|
|
28634
|
+
["Jiroft"]="Jiroft",
|
|
28635
|
+
["Kerman"]="Kerman",
|
|
28224
28636
|
["Khasab"]="Khasab",
|
|
28225
|
-
["
|
|
28226
|
-
["
|
|
28227
|
-
["
|
|
28228
|
-
["
|
|
28637
|
+
["Kish_Intl"]="Kish Intl",
|
|
28638
|
+
["Lar"]="Lar",
|
|
28639
|
+
["Lavan_Island"]="Lavan Island",
|
|
28640
|
+
["Liwa_AFB"]="Liwa AFB",
|
|
28229
28641
|
["Qeshm_Island"]="Qeshm Island",
|
|
28230
|
-
["
|
|
28231
|
-
["
|
|
28642
|
+
["Quasoura_airport"]="Quasoura_airport",
|
|
28643
|
+
["Ras_Al_Khaimah_Intl"]="Ras Al Khaimah Intl",
|
|
28644
|
+
["Sas_Al_Nakheel"]="Sas Al Nakheel",
|
|
28232
28645
|
["Sharjah_Intl"]="Sharjah Intl",
|
|
28233
|
-
["
|
|
28646
|
+
["Shiraz_Intl"]="Shiraz Intl",
|
|
28234
28647
|
["Sir_Abu_Nuayr"]="Sir Abu Nuayr",
|
|
28235
28648
|
["Sirri_Island"]="Sirri Island",
|
|
28236
28649
|
["Tunb_Island_AFB"]="Tunb Island AFB",
|
|
@@ -28238,156 +28651,178 @@ AIRBASE.PersianGulf={
|
|
|
28238
28651
|
}
|
|
28239
28652
|
AIRBASE.TheChannel={
|
|
28240
28653
|
["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
28654
|
["Biggin_Hill"]="Biggin Hill",
|
|
28655
|
+
["Detling"]="Detling",
|
|
28656
|
+
["Dunkirk_Mardyck"]="Dunkirk Mardyck",
|
|
28250
28657
|
["Eastchurch"]="Eastchurch",
|
|
28658
|
+
["Hawkinge"]="Hawkinge",
|
|
28251
28659
|
["Headcorn"]="Headcorn",
|
|
28660
|
+
["High_Halden"]="High Halden",
|
|
28661
|
+
["Lympne"]="Lympne",
|
|
28662
|
+
["Manston"]="Manston",
|
|
28663
|
+
["Merville_Calonne"]="Merville Calonne",
|
|
28664
|
+
["Saint_Omer_Longuenesse"]="Saint Omer Longuenesse",
|
|
28252
28665
|
}
|
|
28253
28666
|
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",
|
|
28667
|
+
["Abu_al_Duhur"]="Abu al-Duhur",
|
|
28668
|
+
["Adana_Sakirpasa"]="Adana Sakirpasa",
|
|
28669
|
+
["Akrotiri"]="Akrotiri",
|
|
28266
28670
|
["Al_Dumayr"]="Al-Dumayr",
|
|
28671
|
+
["Al_Qusayr"]="Al Qusayr",
|
|
28672
|
+
["Aleppo"]="Aleppo",
|
|
28673
|
+
["Amman"]="Amman",
|
|
28674
|
+
["An_Nasiriyah"]="An Nasiriyah",
|
|
28675
|
+
["At_Tanf"]="At Tanf",
|
|
28676
|
+
["Bassel_Al_Assad"]="Bassel Al-Assad",
|
|
28677
|
+
["Beirut_Rafic_Hariri"]="Beirut-Rafic Hariri",
|
|
28678
|
+
["Damascus"]="Damascus",
|
|
28679
|
+
["Deir_ez_Zor"]="Deir ez-Zor",
|
|
28680
|
+
["Ercan"]="Ercan",
|
|
28681
|
+
["Eyn_Shemer"]="Eyn Shemer",
|
|
28682
|
+
["Gaziantep"]="Gaziantep",
|
|
28267
28683
|
["Gazipasa"]="Gazipasa",
|
|
28268
|
-
["
|
|
28269
|
-
["
|
|
28270
|
-
["
|
|
28271
|
-
["
|
|
28272
|
-
["
|
|
28684
|
+
["Gecitkale"]="Gecitkale",
|
|
28685
|
+
["H3"]="H3",
|
|
28686
|
+
["H3_Northwest"]="H3 Northwest",
|
|
28687
|
+
["H3_Southwest"]="H3 Southwest",
|
|
28688
|
+
["H4"]="H4",
|
|
28273
28689
|
["Haifa"]="Haifa",
|
|
28690
|
+
["Hama"]="Hama",
|
|
28691
|
+
["Hatay"]="Hatay",
|
|
28692
|
+
["Herzliya"]="Herzliya",
|
|
28693
|
+
["Incirlik"]="Incirlik",
|
|
28694
|
+
["Jirah"]="Jirah",
|
|
28274
28695
|
["Khalkhalah"]="Khalkhalah",
|
|
28275
|
-
["
|
|
28696
|
+
["Kharab_Ishk"]="Kharab Ishk",
|
|
28697
|
+
["King_Abdullah_II"]="King Abdullah II",
|
|
28698
|
+
["King_Hussein_Air_College"]="King Hussein Air College",
|
|
28699
|
+
["Kingsfield"]="Kingsfield",
|
|
28700
|
+
["Kiryat_Shmona"]="Kiryat Shmona",
|
|
28701
|
+
["Kuweires"]="Kuweires",
|
|
28276
28702
|
["Lakatamia"]="Lakatamia",
|
|
28277
|
-
["Rayak"]="Rayak",
|
|
28278
28703
|
["Larnaca"]="Larnaca",
|
|
28704
|
+
["Marj_Ruhayyil"]="Marj Ruhayyil",
|
|
28705
|
+
["Marj_as_Sultan_North"]="Marj as Sultan North",
|
|
28706
|
+
["Marj_as_Sultan_South"]="Marj as Sultan South",
|
|
28707
|
+
["Megiddo"]="Megiddo",
|
|
28279
28708
|
["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
28709
|
["Minakh"]="Minakh",
|
|
28295
|
-
["
|
|
28710
|
+
["Muwaffaq_Salti"]="Muwaffaq Salti",
|
|
28711
|
+
["Naqoura"]="Naqoura",
|
|
28712
|
+
["Nicosia"]="Nicosia",
|
|
28296
28713
|
["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",
|
|
28714
|
+
["Paphos"]="Paphos",
|
|
28715
|
+
["Pinarbashi"]="Pinarbashi",
|
|
28716
|
+
["Prince_Hassan"]="Prince Hassan",
|
|
28717
|
+
["Qabr_as_Sitt"]="Qabr as Sitt",
|
|
28718
|
+
["Ramat_David"]="Ramat David",
|
|
28719
|
+
["Rayak"]="Rayak",
|
|
28720
|
+
["Rene_Mouawad"]="Rene Mouawad",
|
|
28721
|
+
["Rosh_Pina"]="Rosh Pina",
|
|
28309
28722
|
["Ruwayshid"]="Ruwayshid",
|
|
28310
28723
|
["Sanliurfa"]="Sanliurfa",
|
|
28724
|
+
["Sayqal"]="Sayqal",
|
|
28725
|
+
["Shayrat"]="Shayrat",
|
|
28726
|
+
["Tabqa"]="Tabqa",
|
|
28727
|
+
["Taftanaz"]="Taftanaz",
|
|
28311
28728
|
["Tal_Siman"]="Tal Siman",
|
|
28312
|
-
["
|
|
28729
|
+
["Tha_lah"]="Tha'lah",
|
|
28730
|
+
["Tiyas"]="Tiyas",
|
|
28731
|
+
["Wujah_Al_Hajar"]="Wujah Al Hajar",
|
|
28313
28732
|
}
|
|
28314
28733
|
AIRBASE.MarianaIslands={
|
|
28315
|
-
["Rota_Intl"]="Rota Intl",
|
|
28316
28734
|
["Andersen_AFB"]="Andersen AFB",
|
|
28317
28735
|
["Antonio_B_Won_Pat_Intl"]="Antonio B. Won Pat Intl",
|
|
28318
|
-
["
|
|
28319
|
-
["Tinian_Intl"]="Tinian Intl",
|
|
28736
|
+
["North_West_Field"]="North West Field",
|
|
28320
28737
|
["Olf_Orote"]="Olf Orote",
|
|
28321
28738
|
["Pagan_Airstrip"]="Pagan Airstrip",
|
|
28322
|
-
["
|
|
28739
|
+
["Rota_Intl"]="Rota Intl",
|
|
28740
|
+
["Saipan_Intl"]="Saipan Intl",
|
|
28741
|
+
["Tinian_Intl"]="Tinian Intl",
|
|
28323
28742
|
}
|
|
28324
28743
|
AIRBASE.SouthAtlantic={
|
|
28325
|
-
["
|
|
28744
|
+
["Almirante_Schroeders"]="Almirante Schroeders",
|
|
28745
|
+
["Caleta_Tortel"]="Caleta Tortel",
|
|
28746
|
+
["Comandante_Luis_Piedrabuena"]="Comandante Luis Piedrabuena",
|
|
28747
|
+
["Cullen"]="Cullen",
|
|
28748
|
+
["El_Calafate"]="El Calafate",
|
|
28749
|
+
["Franco_Bianco"]="Franco Bianco",
|
|
28750
|
+
["Gobernador_Gregores"]="Gobernador Gregores",
|
|
28751
|
+
["Goose_Green"]="Goose Green",
|
|
28752
|
+
["Gull_Point"]="Gull Point",
|
|
28753
|
+
["Hipico_Flying_Club"]="Hipico Flying Club",
|
|
28326
28754
|
["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",
|
|
28755
|
+
["O_Higgins"]="O'Higgins",
|
|
28333
28756
|
["Pampa_Guanaco"]="Pampa Guanaco",
|
|
28334
|
-
["
|
|
28335
|
-
["
|
|
28757
|
+
["Port_Stanley"]="Port Stanley",
|
|
28758
|
+
["Porvenir"]="Porvenir",
|
|
28336
28759
|
["Puerto_Natales"]="Puerto Natales",
|
|
28337
|
-
["El_Calafate"]="El Calafate",
|
|
28338
28760
|
["Puerto_Santa_Cruz"]="Puerto Santa Cruz",
|
|
28339
|
-
["
|
|
28340
|
-
["
|
|
28341
|
-
["Porvenir_Airfield"]="Porvenir Airfield",
|
|
28342
|
-
["Almirante_Schroeders"]="Almirante Schroeders",
|
|
28343
|
-
["Rio_Turbio"]="Rio Turbio",
|
|
28761
|
+
["Puerto_Williams"]="Puerto Williams",
|
|
28762
|
+
["Punta_Arenas"]="Punta Arenas",
|
|
28344
28763
|
["Rio_Chico"]="Rio Chico",
|
|
28345
|
-
["
|
|
28346
|
-
["
|
|
28347
|
-
["
|
|
28348
|
-
["
|
|
28349
|
-
["
|
|
28350
|
-
["
|
|
28351
|
-
["
|
|
28352
|
-
["
|
|
28764
|
+
["Rio_Gallegos"]="Rio Gallegos",
|
|
28765
|
+
["Rio_Grande"]="Rio Grande",
|
|
28766
|
+
["Rio_Turbio"]="Rio Turbio",
|
|
28767
|
+
["San_Carlos_FOB"]="San Carlos FOB",
|
|
28768
|
+
["San_Julian"]="San Julian",
|
|
28769
|
+
["Tolhuin"]="Tolhuin",
|
|
28770
|
+
["Ushuaia"]="Ushuaia",
|
|
28771
|
+
["Ushuaia_Helo_Port"]="Ushuaia Helo Port",
|
|
28353
28772
|
}
|
|
28354
28773
|
AIRBASE.Sinai={
|
|
28355
|
-
["
|
|
28774
|
+
["Abu_Rudeis"]="Abu Rudeis",
|
|
28356
28775
|
["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
28776
|
["Al_Ismailiyah"]="Al Ismailiyah",
|
|
28777
|
+
["Al_Mansurah"]="Al Mansurah",
|
|
28364
28778
|
["As_Salihiyah"]="As Salihiyah",
|
|
28365
|
-
["
|
|
28779
|
+
["AzZaqaziq"]="AzZaqaziq",
|
|
28780
|
+
["Baluza"]="Baluza",
|
|
28781
|
+
["Ben_Gurion"]="Ben-Gurion",
|
|
28366
28782
|
["Bilbeis_Air_Base"]="Bilbeis Air Base",
|
|
28367
|
-
["
|
|
28368
|
-
["
|
|
28783
|
+
["Bir_Hasanah"]="Bir Hasanah",
|
|
28784
|
+
["Cairo_International_Airport"]="Cairo International Airport",
|
|
28785
|
+
["Cairo_West"]="Cairo West",
|
|
28786
|
+
["Difarsuwar_Airfield"]="Difarsuwar Airfield",
|
|
28369
28787
|
["El_Arish"]="El Arish",
|
|
28370
|
-
["
|
|
28788
|
+
["El_Gora"]="El Gora",
|
|
28789
|
+
["Fayed"]="Fayed",
|
|
28790
|
+
["Hatzerim"]="Hatzerim",
|
|
28791
|
+
["Hatzor"]="Hatzor",
|
|
28792
|
+
["Inshas_Airbase"]="Inshas Airbase",
|
|
28793
|
+
["Kedem"]="Kedem",
|
|
28794
|
+
["Kibrit_Air_Base"]="Kibrit Air Base",
|
|
28371
28795
|
["Melez"]="Melez",
|
|
28372
|
-
["
|
|
28796
|
+
["Nevatim"]="Nevatim",
|
|
28797
|
+
["Ovda"]="Ovda",
|
|
28373
28798
|
["Palmahim"]="Palmahim",
|
|
28374
|
-
["
|
|
28375
|
-
["
|
|
28376
|
-
["Difarsuwar_Airfield"]="Difarsuwar Airfield",
|
|
28377
|
-
["Wadi_al_Jandali"]="Wadi al Jandali",
|
|
28799
|
+
["Ramon_Airbase"]="Ramon Airbase",
|
|
28800
|
+
["Sde_Dov"]="Sde Dov",
|
|
28378
28801
|
["St_Catherine"]="St Catherine",
|
|
28379
28802
|
["Tel_Nof"]="Tel Nof",
|
|
28380
|
-
["
|
|
28381
|
-
|
|
28382
|
-
|
|
28383
|
-
["
|
|
28384
|
-
["
|
|
28803
|
+
["Wadi_al_Jandali"]="Wadi al Jandali",
|
|
28804
|
+
}
|
|
28805
|
+
AIRBASE.Kola={
|
|
28806
|
+
["Bas_100"]="Bas 100",
|
|
28807
|
+
["Bodo"]="Bodo",
|
|
28808
|
+
["Jokkmokk"]="Jokkmokk",
|
|
28809
|
+
["Kalixfors"]="Kalixfors",
|
|
28810
|
+
["Kemi_Tornio"]="Kemi Tornio",
|
|
28811
|
+
["Kiruna"]="Kiruna",
|
|
28812
|
+
["Lakselv"]="Lakselv",
|
|
28813
|
+
["Monchegorsk"]="Monchegorsk",
|
|
28814
|
+
["Murmansk_International"]="Murmansk International",
|
|
28815
|
+
["Olenegorsk"]="Olenegorsk",
|
|
28816
|
+
["Rovaniemi"]="Rovaniemi",
|
|
28817
|
+
["Severomorsk1"]="Severomorsk1",
|
|
28818
|
+
["Severomorsk3"]="Severomorsk3",
|
|
28385
28819
|
}
|
|
28386
28820
|
AIRBASE.TerminalType={
|
|
28387
28821
|
Runway=16,
|
|
28388
28822
|
HelicopterOnly=40,
|
|
28389
28823
|
Shelter=68,
|
|
28390
28824
|
OpenMed=72,
|
|
28825
|
+
SmallSizeFighter=100,
|
|
28391
28826
|
OpenBig=104,
|
|
28392
28827
|
OpenMedOrBig=176,
|
|
28393
28828
|
HelicopterUsable=216,
|
|
@@ -28946,7 +29381,7 @@ if Term_Type==AIRBASE.TerminalType.OpenMed or Term_Type==AIRBASE.TerminalType.Op
|
|
|
28946
29381
|
match=true
|
|
28947
29382
|
end
|
|
28948
29383
|
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
|
|
29384
|
+
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
29385
|
match=true
|
|
28951
29386
|
end
|
|
28952
29387
|
end
|
|
@@ -29730,6 +30165,9 @@ self.desc=WeaponObject:getDesc()
|
|
|
29730
30165
|
self.category=self.desc.category
|
|
29731
30166
|
if self:IsMissile()and self.desc.missileCategory then
|
|
29732
30167
|
self.categoryMissile=self.desc.missileCategory
|
|
30168
|
+
if self.desc.guidance then
|
|
30169
|
+
self.guidance=self.desc.guidance
|
|
30170
|
+
end
|
|
29733
30171
|
end
|
|
29734
30172
|
self.typeName=WeaponObject:getTypeName()or"Unknown Type"
|
|
29735
30173
|
self.name=WeaponObject:getName()
|
|
@@ -29944,6 +30382,15 @@ end
|
|
|
29944
30382
|
function WEAPON:IsTorpedo()
|
|
29945
30383
|
return self.category==Weapon.Category.TORPEDO
|
|
29946
30384
|
end
|
|
30385
|
+
function WEAPON:IsFoxOne()
|
|
30386
|
+
return self.guidance==Weapon.GuidanceType.RADAR_SEMI_ACTIVE
|
|
30387
|
+
end
|
|
30388
|
+
function WEAPON:IsFoxTwo()
|
|
30389
|
+
return self.guidance==Weapon.GuidanceType.IR
|
|
30390
|
+
end
|
|
30391
|
+
function WEAPON:IsFoxThree()
|
|
30392
|
+
return self.guidance==Weapon.GuidanceType.RADAR_ACTIVE
|
|
30393
|
+
end
|
|
29947
30394
|
function WEAPON:Destroy(Delay)
|
|
29948
30395
|
if Delay and Delay>0 then
|
|
29949
30396
|
self:ScheduleOnce(Delay,WEAPON.Destroy,self,0)
|
|
@@ -30409,7 +30856,7 @@ end
|
|
|
30409
30856
|
function NET.Lua2Json(Lua)
|
|
30410
30857
|
return net.lua2json(Lua)
|
|
30411
30858
|
end
|
|
30412
|
-
function NET.
|
|
30859
|
+
function NET.Json2Lua(Json)
|
|
30413
30860
|
return net.json2lua(Json)
|
|
30414
30861
|
end
|
|
30415
30862
|
function NET:DoStringIn(State,DoString)
|
|
@@ -31959,7 +32406,7 @@ ClassName="SCORING",
|
|
|
31959
32406
|
ClassID=0,
|
|
31960
32407
|
Players={},
|
|
31961
32408
|
AutoSave=true,
|
|
31962
|
-
version="1.
|
|
32409
|
+
version="1.18.4"
|
|
31963
32410
|
}
|
|
31964
32411
|
local _SCORINGCoalition={
|
|
31965
32412
|
[1]="Red",
|
|
@@ -31972,7 +32419,7 @@ local _SCORINGCategory={
|
|
|
31972
32419
|
[Unit.Category.SHIP]="Ship",
|
|
31973
32420
|
[Unit.Category.STRUCTURE]="Structure",
|
|
31974
32421
|
}
|
|
31975
|
-
function SCORING:New(GameName)
|
|
32422
|
+
function SCORING:New(GameName,SavePath,AutoSave)
|
|
31976
32423
|
local self=BASE:Inherit(self,BASE:New())
|
|
31977
32424
|
if GameName then
|
|
31978
32425
|
self.GameName=GameName
|
|
@@ -32005,7 +32452,8 @@ self:_AddPlayerFromUnit(PlayerUnit)
|
|
|
32005
32452
|
self:SetScoringMenu(PlayerUnit:GetGroup())
|
|
32006
32453
|
end
|
|
32007
32454
|
end)
|
|
32008
|
-
self.
|
|
32455
|
+
self.AutoSavePath=SavePath
|
|
32456
|
+
self.AutoSave=AutoSave or true
|
|
32009
32457
|
self:OpenCSV(GameName)
|
|
32010
32458
|
return self
|
|
32011
32459
|
end
|
|
@@ -32049,6 +32497,21 @@ self.ScoringObjects[UnitName]=Score
|
|
|
32049
32497
|
end
|
|
32050
32498
|
return self
|
|
32051
32499
|
end
|
|
32500
|
+
function SCORING:AddScoreSetGroup(Set,Score)
|
|
32501
|
+
local set=Set:GetSetObjects()
|
|
32502
|
+
for _,_group in pairs(set)do
|
|
32503
|
+
if _group and _group:IsAlive()then
|
|
32504
|
+
self:AddScoreGroup(_group,Score)
|
|
32505
|
+
end
|
|
32506
|
+
end
|
|
32507
|
+
local function AddScore(group)
|
|
32508
|
+
self:AddScoreGroup(group,Score)
|
|
32509
|
+
end
|
|
32510
|
+
function Set:OnAfterAdded(From,Event,To,ObjectName,Object)
|
|
32511
|
+
AddScore(Object)
|
|
32512
|
+
end
|
|
32513
|
+
return self
|
|
32514
|
+
end
|
|
32052
32515
|
function SCORING:AddZoneScore(ScoreZone,Score)
|
|
32053
32516
|
local ZoneName=ScoreZone:GetName()
|
|
32054
32517
|
self.ScoringZones[ZoneName]={}
|
|
@@ -32380,7 +32843,7 @@ PlayerHit.TimeStamp=PlayerHit.TimeStamp or 0
|
|
|
32380
32843
|
PlayerHit.UNIT=PlayerHit.UNIT or TargetUNIT
|
|
32381
32844
|
if PlayerHit.UNIT.ThreatType==nil then
|
|
32382
32845
|
PlayerHit.ThreatLevel,PlayerHit.ThreatType=PlayerHit.UNIT:GetThreatLevel()
|
|
32383
|
-
if PlayerHit.ThreatType==nil then
|
|
32846
|
+
if PlayerHit.ThreatType==nil or PlayerHit.ThreatType==""then
|
|
32384
32847
|
PlayerHit.ThreatLevel=1
|
|
32385
32848
|
PlayerHit.ThreatType="Unknown"
|
|
32386
32849
|
end
|
|
@@ -32572,16 +33035,15 @@ self:F({ThreatLevel=ThreatPenalty,ThreatLevelTarget=ThreatLevelTarget,ThreatType
|
|
|
32572
33035
|
Player.Penalty=Player.Penalty+ThreatPenalty
|
|
32573
33036
|
TargetDestroy.Penalty=TargetDestroy.Penalty+ThreatPenalty
|
|
32574
33037
|
TargetDestroy.PenaltyDestroy=TargetDestroy.PenaltyDestroy+1
|
|
32575
|
-
self:OnKillPvP(Player,TargetPlayerName,true,TargetThreatLevel,Player.ThreatLevel,ThreatPenalty)
|
|
32576
33038
|
if Player.HitPlayers[TargetPlayerName]then
|
|
32577
|
-
self:OnKillPvP(
|
|
33039
|
+
self:OnKillPvP(PlayerName,TargetPlayerName,true)
|
|
32578
33040
|
MESSAGE:NewType(self.DisplayMessagePrefix.."Player '"..PlayerName.."' destroyed friendly player '"..TargetPlayerName.."' "..TargetUnitCategory.." ( "..ThreatTypeTarget.." ) "..
|
|
32579
33041
|
"Penalty: -"..ThreatPenalty.." = "..Player.Score-Player.Penalty,
|
|
32580
33042
|
MESSAGE.Type.Information)
|
|
32581
33043
|
:ToAllIf(self:IfMessagesDestroy()and self:IfMessagesToAll())
|
|
32582
33044
|
:ToCoalitionIf(InitCoalition,self:IfMessagesDestroy()and self:IfMessagesToCoalition())
|
|
32583
33045
|
else
|
|
32584
|
-
self:OnKillPvE(
|
|
33046
|
+
self:OnKillPvE(PlayerName,TargetUnitName,true,TargetThreatLevel,Player.ThreatLevel,ThreatPenalty)
|
|
32585
33047
|
MESSAGE:NewType(self.DisplayMessagePrefix.."Player '"..PlayerName.."' destroyed friendly target "..TargetUnitCategory.." ( "..ThreatTypeTarget.." ) "..
|
|
32586
33048
|
"Penalty: -"..ThreatPenalty.." = "..Player.Score-Player.Penalty,
|
|
32587
33049
|
MESSAGE.Type.Information)
|
|
@@ -32605,14 +33067,14 @@ Player.PlayerKills=Player.PlayerKills+1
|
|
|
32605
33067
|
else
|
|
32606
33068
|
Player.PlayerKills=1
|
|
32607
33069
|
end
|
|
32608
|
-
self:OnKillPvP(
|
|
33070
|
+
self:OnKillPvP(PlayerName,TargetPlayerName,false,TargetThreatLevel,Player.ThreatLevel,ThreatScore)
|
|
32609
33071
|
MESSAGE:NewType(self.DisplayMessagePrefix.."Player '"..PlayerName.."' destroyed enemy player '"..TargetPlayerName.."' "..TargetUnitCategory.." ( "..ThreatTypeTarget.." ) "..
|
|
32610
33072
|
"Score: +"..ThreatScore.." = "..Player.Score-Player.Penalty,
|
|
32611
33073
|
MESSAGE.Type.Information)
|
|
32612
33074
|
:ToAllIf(self:IfMessagesDestroy()and self:IfMessagesToAll())
|
|
32613
33075
|
:ToCoalitionIf(InitCoalition,self:IfMessagesDestroy()and self:IfMessagesToCoalition())
|
|
32614
33076
|
else
|
|
32615
|
-
self:OnKillPvE(
|
|
33077
|
+
self:OnKillPvE(PlayerName,TargetUnitName,false,TargetThreatLevel,Player.ThreatLevel,ThreatScore)
|
|
32616
33078
|
MESSAGE:NewType(self.DisplayMessagePrefix.."Player '"..PlayerName.."' destroyed enemy "..TargetUnitCategory.." ( "..ThreatTypeTarget.." ) "..
|
|
32617
33079
|
"Score: +"..ThreatScore.." = "..Player.Score-Player.Penalty,
|
|
32618
33080
|
MESSAGE.Type.Information)
|
|
@@ -32954,10 +33416,11 @@ end
|
|
|
32954
33416
|
end
|
|
32955
33417
|
function SCORING:OpenCSV(ScoringCSV)
|
|
32956
33418
|
self:F(ScoringCSV)
|
|
32957
|
-
if lfs and io and os and self.AutoSave then
|
|
33419
|
+
if lfs and io and os and self.AutoSave==true then
|
|
32958
33420
|
if ScoringCSV then
|
|
32959
33421
|
self.ScoringCSV=ScoringCSV
|
|
32960
|
-
local
|
|
33422
|
+
local path=self.AutoSavePath or lfs.writedir()..[[Logs\]]
|
|
33423
|
+
local fdir=path..self.ScoringCSV.." "..os.date("%Y-%m-%d %H-%M-%S")..".csv"
|
|
32961
33424
|
self.CSVFile,self.err=io.open(fdir,"w+")
|
|
32962
33425
|
if not self.CSVFile then
|
|
32963
33426
|
error("Error: Cannot open CSV file in "..lfs.writedir())
|
|
@@ -33036,9 +33499,9 @@ function SCORING:SwitchAutoSave(OnOff)
|
|
|
33036
33499
|
self.AutoSave=OnOff
|
|
33037
33500
|
return self
|
|
33038
33501
|
end
|
|
33039
|
-
function SCORING:OnKillPvP(
|
|
33502
|
+
function SCORING:OnKillPvP(PlayerName,TargetPlayerName,IsTeamKill,TargetThreatLevel,PlayerThreatLevel,Score)
|
|
33040
33503
|
end
|
|
33041
|
-
function SCORING:OnKillPvE(
|
|
33504
|
+
function SCORING:OnKillPvE(PlayerName,TargetUnitName,IsTeamKill,TargetThreatLevel,PlayerThreatLevel,Score)
|
|
33042
33505
|
end
|
|
33043
33506
|
CLEANUP_AIRBASE={
|
|
33044
33507
|
ClassName="CLEANUP_AIRBASE",
|
|
@@ -33528,7 +33991,6 @@ predpos:MarkToAll(string.format("height=%dm | heading=%d | velocity=%ddeg | Ropt
|
|
|
33528
33991
|
targetzone:DrawZone(coalition.side.BLUE,{0,0,1},0.2,nil,nil,3,true)
|
|
33529
33992
|
end
|
|
33530
33993
|
local seadset=SET_GROUP:New():FilterPrefixes(self.SEADGroupPrefixes):FilterZones({targetzone}):FilterOnce()
|
|
33531
|
-
local tgtcoord=targetzone:GetRandomPointVec2()
|
|
33532
33994
|
local tgtgrp=seadset:GetRandom()
|
|
33533
33995
|
local _targetgroup=nil
|
|
33534
33996
|
local _targetgroupname="none"
|
|
@@ -57204,7 +57666,7 @@ local rho=groovedata.Rho
|
|
|
57204
57666
|
local lineupError=groovedata.LUE
|
|
57205
57667
|
local glideslopeError=groovedata.GSE
|
|
57206
57668
|
local AoA=groovedata.AoA
|
|
57207
|
-
if rho<=RXX and playerData.step==AIRBOSS.PatternStep.GROOVE_XX and(math.abs(groovedata.Roll)<=4.0
|
|
57669
|
+
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
57670
|
playerData.TIG0=timer.getTime()
|
|
57209
57671
|
self:RadioTransmission(self.LSORadio,self.LSOCall.CALLTHEBALL,nil,nil,nil,true)
|
|
57210
57672
|
playerData.Tlso=timer.getTime()
|
|
@@ -64426,6 +64888,8 @@ HasBeenDropped=false,
|
|
|
64426
64888
|
PerCrateMass=0,
|
|
64427
64889
|
Stock=nil,
|
|
64428
64890
|
Mark=nil,
|
|
64891
|
+
DontShowInMenu=false,
|
|
64892
|
+
Location=nil,
|
|
64429
64893
|
}
|
|
64430
64894
|
CTLD_CARGO.Enum={
|
|
64431
64895
|
VEHICLE="Vehicle",
|
|
@@ -64436,7 +64900,7 @@ REPAIR="Repair",
|
|
|
64436
64900
|
ENGINEERS="Engineers",
|
|
64437
64901
|
STATIC="Static",
|
|
64438
64902
|
}
|
|
64439
|
-
function CTLD_CARGO:New(ID,Name,Templates,Sorte,HasBeenMoved,LoadDirectly,CratesNeeded,Positionable,Dropped,PerCrateMass,Stock,Subcategory)
|
|
64903
|
+
function CTLD_CARGO:New(ID,Name,Templates,Sorte,HasBeenMoved,LoadDirectly,CratesNeeded,Positionable,Dropped,PerCrateMass,Stock,Subcategory,DontShowInMenu,Location)
|
|
64440
64904
|
local self=BASE:Inherit(self,BASE:New())
|
|
64441
64905
|
self:T({ID,Name,Templates,Sorte,HasBeenMoved,LoadDirectly,CratesNeeded,Positionable,Dropped})
|
|
64442
64906
|
self.ID=ID or math.random(100000,1000000)
|
|
@@ -64452,8 +64916,16 @@ self.PerCrateMass=PerCrateMass or 0
|
|
|
64452
64916
|
self.Stock=Stock or nil
|
|
64453
64917
|
self.Mark=nil
|
|
64454
64918
|
self.Subcategory=Subcategory or"Other"
|
|
64919
|
+
self.DontShowInMenu=DontShowInMenu or false
|
|
64920
|
+
if type(Location)=="string"then
|
|
64921
|
+
Location=ZONE:New(Location)
|
|
64922
|
+
end
|
|
64923
|
+
self.Location=Location
|
|
64455
64924
|
return self
|
|
64456
64925
|
end
|
|
64926
|
+
function CTLD_CARGO:GetLocation()
|
|
64927
|
+
return self.Location
|
|
64928
|
+
end
|
|
64457
64929
|
function CTLD_CARGO:GetID()
|
|
64458
64930
|
return self.ID
|
|
64459
64931
|
end
|
|
@@ -64763,10 +65235,13 @@ CTLD.UnitTypeCapabilities={
|
|
|
64763
65235
|
["Mi-24V"]={type="Mi-24V",crates=true,troops=true,cratelimit=2,trooplimit=8,length=18,cargoweightlimit=700},
|
|
64764
65236
|
["Hercules"]={type="Hercules",crates=true,troops=true,cratelimit=7,trooplimit=64,length=25,cargoweightlimit=19000},
|
|
64765
65237
|
["UH-60L"]={type="UH-60L",crates=true,troops=true,cratelimit=2,trooplimit=20,length=16,cargoweightlimit=3500},
|
|
65238
|
+
["MH-60R"]={type="MH-60R",crates=true,troops=true,cratelimit=2,trooplimit=20,length=16,cargoweightlimit=3500},
|
|
65239
|
+
["SH-60B"]={type="SH-60B",crates=true,troops=true,cratelimit=2,trooplimit=20,length=16,cargoweightlimit=3500},
|
|
64766
65240
|
["AH-64D_BLK_II"]={type="AH-64D_BLK_II",crates=false,troops=true,cratelimit=0,trooplimit=2,length=17,cargoweightlimit=200},
|
|
64767
65241
|
["Bronco-OV-10A"]={type="Bronco-OV-10A",crates=false,troops=true,cratelimit=0,trooplimit=5,length=13,cargoweightlimit=1450},
|
|
65242
|
+
["OH-6A"]={type="OH-6A",crates=false,troops=true,cratelimit=0,trooplimit=4,length=7,cargoweightlimit=550},
|
|
64768
65243
|
}
|
|
64769
|
-
CTLD.version="1.0.
|
|
65244
|
+
CTLD.version="1.0.52"
|
|
64770
65245
|
function CTLD:New(Coalition,Prefixes,Alias)
|
|
64771
65246
|
local self=BASE:Inherit(self,FSM:New())
|
|
64772
65247
|
BASE:T({Coalition,Prefixes,Alias})
|
|
@@ -65269,7 +65744,9 @@ local distancekeys={}
|
|
|
65269
65744
|
local extractdistance=self.CrateDistance*self.ExtractFactor
|
|
65270
65745
|
for k,v in pairs(self.DroppedTroops)do
|
|
65271
65746
|
local distance=self:_GetDistance(v:GetCoordinate(),unitcoord)
|
|
65272
|
-
|
|
65747
|
+
local TNow=timer.getTime()
|
|
65748
|
+
local vtime=v.ExtractTime or TNow-310
|
|
65749
|
+
if distance<=extractdistance and distance~=-1 and(TNow-vtime>300)then
|
|
65273
65750
|
nearestGroup=v
|
|
65274
65751
|
nearestGroupIndex=k
|
|
65275
65752
|
nearestDistance=distance
|
|
@@ -65312,22 +65789,36 @@ loaded.Cargo={}
|
|
|
65312
65789
|
end
|
|
65313
65790
|
if troopsize+numberonboard>trooplimit then
|
|
65314
65791
|
self:_SendMessage("Sorry, we\'re crammed already!",10,false,Group)
|
|
65792
|
+
nearestGroup.ExtractTime=0
|
|
65315
65793
|
else
|
|
65316
65794
|
self.CargoCounter=self.CargoCounter+1
|
|
65795
|
+
nearestGroup.ExtractTime=timer.getTime()
|
|
65317
65796
|
local loadcargotype=CTLD_CARGO:New(self.CargoCounter,Cargotype.Name,Cargotype.Templates,Cargotype.CargoType,true,true,Cargotype.CratesNeeded,nil,nil,Cargotype.PerCrateMass)
|
|
65318
65797
|
self:T({cargotype=loadcargotype})
|
|
65798
|
+
local running=math.floor(nearestDistance/4)+10
|
|
65319
65799
|
loaded.Troopsloaded=loaded.Troopsloaded+troopsize
|
|
65320
65800
|
table.insert(loaded.Cargo,loadcargotype)
|
|
65321
65801
|
self.Loaded_Cargo[unitname]=loaded
|
|
65322
|
-
self:_SendMessage
|
|
65802
|
+
self:ScheduleOnce(running,self._SendMessage,self,"Troops boarded!",10,false,Group)
|
|
65803
|
+
self:_SendMessage("Troops boarding!",10,false,Group)
|
|
65323
65804
|
self:_UpdateUnitCargoMass(Unit)
|
|
65324
|
-
self:__TroopsExtracted(
|
|
65805
|
+
self:__TroopsExtracted(running,Group,Unit,nearestGroup)
|
|
65806
|
+
local coord=Unit:GetCoordinate()or Group:GetCoordinate()
|
|
65807
|
+
local Point
|
|
65808
|
+
if coord then
|
|
65809
|
+
local heading=unit:GetHeading()or 0
|
|
65810
|
+
local Angle=math.floor((heading+160)%360)
|
|
65811
|
+
Point=coord:Translate(8,Angle):GetVec2()
|
|
65812
|
+
if Point then
|
|
65813
|
+
nearestGroup:RouteToVec2(Point,4)
|
|
65814
|
+
end
|
|
65815
|
+
end
|
|
65325
65816
|
if type(Cargotype.Templates)=="table"and Cargotype.Templates[2]then
|
|
65326
65817
|
for _,_key in pairs(Cargotype.Templates)do
|
|
65327
65818
|
table.insert(secondarygroups,_key)
|
|
65328
65819
|
end
|
|
65329
65820
|
end
|
|
65330
|
-
nearestGroup:Destroy(false)
|
|
65821
|
+
nearestGroup:Destroy(false,running)
|
|
65331
65822
|
end
|
|
65332
65823
|
end
|
|
65333
65824
|
end
|
|
@@ -65336,7 +65827,7 @@ for _,_group in pairs(nearestList)do
|
|
|
65336
65827
|
if _group and _group:IsAlive()then
|
|
65337
65828
|
local groupname=string.match(_group:GetName(),"(.+)-(.+)$")
|
|
65338
65829
|
if _name==groupname then
|
|
65339
|
-
_group:Destroy(false)
|
|
65830
|
+
_group:Destroy(false,15)
|
|
65340
65831
|
end
|
|
65341
65832
|
end
|
|
65342
65833
|
end
|
|
@@ -65378,6 +65869,16 @@ if not inzone then
|
|
|
65378
65869
|
self:_SendMessage("You are not close enough to a logistics zone!",10,false,Group)
|
|
65379
65870
|
if not self.debug then return self end
|
|
65380
65871
|
end
|
|
65872
|
+
local location=Cargo:GetLocation()
|
|
65873
|
+
if location then
|
|
65874
|
+
local unitcoord=Unit:GetCoordinate()or Group:GetCoordinate()
|
|
65875
|
+
if unitcoord then
|
|
65876
|
+
if not location:IsCoordinateInZone(unitcoord)then
|
|
65877
|
+
self:_SendMessage("The requested cargo is not available in this zone!",10,false,Group)
|
|
65878
|
+
if not self.debug then return self end
|
|
65879
|
+
end
|
|
65880
|
+
end
|
|
65881
|
+
end
|
|
65381
65882
|
local capabilities=self:_GetUnitCapabilities(Unit)
|
|
65382
65883
|
local canloadcratesno=capabilities.cratelimit
|
|
65383
65884
|
local loaddist=self.CrateDistance or 35
|
|
@@ -65928,9 +66429,9 @@ end
|
|
|
65928
66429
|
function CTLD:_GetUnitPositions(Coordinate,Radius,Heading,Template)
|
|
65929
66430
|
local Positions={}
|
|
65930
66431
|
local template=_DATABASE:GetGroupTemplate(Template)
|
|
65931
|
-
UTILS.PrintTableToLog(template)
|
|
65932
66432
|
local numbertroops=#template.units
|
|
65933
|
-
local
|
|
66433
|
+
local slightshift=math.abs(math.random(0,200)/100)
|
|
66434
|
+
local newcenter=Coordinate:Translate(Radius+slightshift,((Heading+270)%360))
|
|
65934
66435
|
for i=1,360,math.floor(360/numbertroops)do
|
|
65935
66436
|
local phead=((Heading+270+i)%360)
|
|
65936
66437
|
local post=newcenter:Translate(Radius,phead)
|
|
@@ -65942,7 +66443,6 @@ heading=phead,
|
|
|
65942
66443
|
}
|
|
65943
66444
|
table.insert(Positions,p1t)
|
|
65944
66445
|
end
|
|
65945
|
-
UTILS.PrintTableToLog(Positions)
|
|
65946
66446
|
return Positions
|
|
65947
66447
|
end
|
|
65948
66448
|
function CTLD:_UnloadTroops(Group,Unit)
|
|
@@ -66479,16 +66979,22 @@ end
|
|
|
66479
66979
|
for _,_entry in pairs(self.Cargo_Troops)do
|
|
66480
66980
|
local entry=_entry
|
|
66481
66981
|
local subcat=entry.Subcategory
|
|
66982
|
+
local noshow=entry.DontShowInMenu
|
|
66983
|
+
if not noshow then
|
|
66482
66984
|
menucount=menucount+1
|
|
66483
66985
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,entry.Name,subcatmenus[subcat],self._LoadTroops,self,_group,_unit,entry)
|
|
66484
66986
|
end
|
|
66987
|
+
end
|
|
66485
66988
|
else
|
|
66486
66989
|
for _,_entry in pairs(self.Cargo_Troops)do
|
|
66487
66990
|
local entry=_entry
|
|
66991
|
+
local noshow=entry.DontShowInMenu
|
|
66992
|
+
if not noshow then
|
|
66488
66993
|
menucount=menucount+1
|
|
66489
66994
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,entry.Name,troopsmenu,self._LoadTroops,self,_group,_unit,entry)
|
|
66490
66995
|
end
|
|
66491
66996
|
end
|
|
66997
|
+
end
|
|
66492
66998
|
local unloadmenu1=MENU_GROUP_COMMAND:New(_group,"Drop troops",toptroops,self._UnloadTroops,self,_group,_unit):Refresh()
|
|
66493
66999
|
local extractMenu1=MENU_GROUP_COMMAND:New(_group,"Extract troops",toptroops,self._ExtractTroops,self,_group,_unit):Refresh()
|
|
66494
67000
|
end
|
|
@@ -66505,33 +67011,61 @@ end
|
|
|
66505
67011
|
for _,_entry in pairs(self.Cargo_Crates)do
|
|
66506
67012
|
local entry=_entry
|
|
66507
67013
|
local subcat=entry.Subcategory
|
|
67014
|
+
local noshow=entry.DontShowInMenu
|
|
67015
|
+
local zone=entry.Location
|
|
67016
|
+
if not noshow then
|
|
66508
67017
|
menucount=menucount+1
|
|
66509
67018
|
local menutext=string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
|
|
67019
|
+
if zone then
|
|
67020
|
+
menutext=string.format("Crate %s (%dkg)[R]",entry.Name,entry.PerCrateMass or 0)
|
|
67021
|
+
end
|
|
66510
67022
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates,self,_group,_unit,entry)
|
|
66511
67023
|
end
|
|
67024
|
+
end
|
|
66512
67025
|
for _,_entry in pairs(self.Cargo_Statics)do
|
|
66513
67026
|
local entry=_entry
|
|
66514
67027
|
local subcat=entry.Subcategory
|
|
67028
|
+
local noshow=entry.DontShowInMenu
|
|
67029
|
+
local zone=entry.Location
|
|
67030
|
+
if not noshow then
|
|
66515
67031
|
menucount=menucount+1
|
|
66516
67032
|
local menutext=string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
|
|
67033
|
+
if zone then
|
|
67034
|
+
menutext=string.format("Crate %s (%dkg)[R]",entry.Name,entry.PerCrateMass or 0)
|
|
67035
|
+
end
|
|
66517
67036
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates,self,_group,_unit,entry)
|
|
66518
67037
|
end
|
|
67038
|
+
end
|
|
66519
67039
|
else
|
|
66520
67040
|
for _,_entry in pairs(self.Cargo_Crates)do
|
|
66521
67041
|
local entry=_entry
|
|
67042
|
+
local noshow=entry.DontShowInMenu
|
|
67043
|
+
local zone=entry.Location
|
|
67044
|
+
if not noshow then
|
|
66522
67045
|
menucount=menucount+1
|
|
66523
67046
|
local menutext=string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
|
|
67047
|
+
if zone then
|
|
67048
|
+
menutext=string.format("Crate %s (%dkg)[R]",entry.Name,entry.PerCrateMass or 0)
|
|
67049
|
+
end
|
|
66524
67050
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates,self,_group,_unit,entry)
|
|
66525
67051
|
end
|
|
67052
|
+
end
|
|
66526
67053
|
for _,_entry in pairs(self.Cargo_Statics)do
|
|
66527
67054
|
local entry=_entry
|
|
67055
|
+
local noshow=entry.DontShowInMenu
|
|
67056
|
+
local zone=entry.Location
|
|
67057
|
+
if not noshow then
|
|
66528
67058
|
menucount=menucount+1
|
|
66529
67059
|
local menutext=string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0)
|
|
67060
|
+
if zone then
|
|
67061
|
+
menutext=string.format("Crate %s (%dkg)[R]",entry.Name,entry.PerCrateMass or 0)
|
|
67062
|
+
end
|
|
66530
67063
|
menus[menucount]=MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates,self,_group,_unit,entry)
|
|
66531
67064
|
end
|
|
66532
67065
|
end
|
|
67066
|
+
end
|
|
66533
67067
|
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)
|
|
67068
|
+
local removecrates=MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu,self._RemoveCratesNearby,self,_group,_unit)
|
|
66535
67069
|
local unloadmenu=MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates,self._UnloadCrates,self,_group,_unit)
|
|
66536
67070
|
if not self.nobuildmenu then
|
|
66537
67071
|
local buildmenu=MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates,self._BuildCrates,self,_group,_unit)
|
|
@@ -66580,23 +67114,23 @@ local cargo=CTLD_CARGO:New(self.CargoCounter,Name,Templates,Type,false,true,NoTr
|
|
|
66580
67114
|
table.insert(self.Cargo_Troops,cargo)
|
|
66581
67115
|
return self
|
|
66582
67116
|
end
|
|
66583
|
-
function CTLD:AddCratesCargo(Name,Templates,Type,NoCrates,PerCrateMass,Stock,SubCategory)
|
|
67117
|
+
function CTLD:AddCratesCargo(Name,Templates,Type,NoCrates,PerCrateMass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66584
67118
|
self:T(self.lid.." AddCratesCargo")
|
|
66585
67119
|
if not self:_CheckTemplates(Templates)then
|
|
66586
67120
|
self:E(self.lid.."Crates Cargo for "..Name.." has missing template(s)!")
|
|
66587
67121
|
return self
|
|
66588
67122
|
end
|
|
66589
67123
|
self.CargoCounter=self.CargoCounter+1
|
|
66590
|
-
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,Templates,Type,false,false,NoCrates,nil,nil,PerCrateMass,Stock,SubCategory)
|
|
67124
|
+
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,Templates,Type,false,false,NoCrates,nil,nil,PerCrateMass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66591
67125
|
table.insert(self.Cargo_Crates,cargo)
|
|
66592
67126
|
return self
|
|
66593
67127
|
end
|
|
66594
|
-
function CTLD:AddStaticsCargo(Name,Mass,Stock,SubCategory)
|
|
67128
|
+
function CTLD:AddStaticsCargo(Name,Mass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66595
67129
|
self:T(self.lid.." AddStaticsCargo")
|
|
66596
67130
|
self.CargoCounter=self.CargoCounter+1
|
|
66597
67131
|
local type=CTLD_CARGO.Enum.STATIC
|
|
66598
67132
|
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)
|
|
67133
|
+
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66600
67134
|
table.insert(self.Cargo_Statics,cargo)
|
|
66601
67135
|
return self
|
|
66602
67136
|
end
|
|
@@ -66608,14 +67142,14 @@ local template=STATIC:FindByName(Name,true):GetTypeName()
|
|
|
66608
67142
|
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,1)
|
|
66609
67143
|
return cargo
|
|
66610
67144
|
end
|
|
66611
|
-
function CTLD:AddCratesRepair(Name,Template,Type,NoCrates,PerCrateMass,Stock,SubCategory)
|
|
67145
|
+
function CTLD:AddCratesRepair(Name,Template,Type,NoCrates,PerCrateMass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66612
67146
|
self:T(self.lid.." AddCratesRepair")
|
|
66613
67147
|
if not self:_CheckTemplates(Template)then
|
|
66614
67148
|
self:E(self.lid.."Repair Cargo for "..Name.." has a missing template!")
|
|
66615
67149
|
return self
|
|
66616
67150
|
end
|
|
66617
67151
|
self.CargoCounter=self.CargoCounter+1
|
|
66618
|
-
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,Template,Type,false,false,NoCrates,nil,nil,PerCrateMass,Stock,SubCategory)
|
|
67152
|
+
local cargo=CTLD_CARGO:New(self.CargoCounter,Name,Template,Type,false,false,NoCrates,nil,nil,PerCrateMass,Stock,SubCategory,DontShowInMenu,Location)
|
|
66619
67153
|
table.insert(self.Cargo_Crates,cargo)
|
|
66620
67154
|
return self
|
|
66621
67155
|
end
|
|
@@ -68437,7 +68971,9 @@ CSAR.AircraftType["Bell-47"]=2
|
|
|
68437
68971
|
CSAR.AircraftType["UH-60L"]=10
|
|
68438
68972
|
CSAR.AircraftType["AH-64D_BLK_II"]=2
|
|
68439
68973
|
CSAR.AircraftType["Bronco-OV-10A"]=2
|
|
68440
|
-
CSAR.
|
|
68974
|
+
CSAR.AircraftType["MH-60R"]=10
|
|
68975
|
+
CSAR.AircraftType["OH-6A"]=2
|
|
68976
|
+
CSAR.version="1.0.22"
|
|
68441
68977
|
function CSAR:New(Coalition,Template,Alias)
|
|
68442
68978
|
local self=BASE:Inherit(self,FSM:New())
|
|
68443
68979
|
BASE:T({Coalition,Template,Alias})
|
|
@@ -68549,7 +69085,7 @@ self.SRSchannel=300
|
|
|
68549
69085
|
self.SRSModulation=radio.modulation.AM
|
|
68550
69086
|
self.SRSport=5002
|
|
68551
69087
|
self.SRSCulture="en-GB"
|
|
68552
|
-
self.SRSVoice=
|
|
69088
|
+
self.SRSVoice=MSRS.Voices.Google.Standard.en_GB_Standard_B
|
|
68553
69089
|
self.SRSGPathToCredentials=nil
|
|
68554
69090
|
self.SRSVolume=1.0
|
|
68555
69091
|
self.SRSGender="male"
|
|
@@ -68925,7 +69461,7 @@ return self
|
|
|
68925
69461
|
end
|
|
68926
69462
|
if _place:GetCoalition()==self.coalition or _place:GetCoalition()==coalition.side.NEUTRAL then
|
|
68927
69463
|
self:__Landed(2,_event.IniUnitName,_place)
|
|
68928
|
-
self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true)
|
|
69464
|
+
self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true,true)
|
|
68929
69465
|
else
|
|
68930
69466
|
self:T(string.format("Airfield %d, Unit %d",_place:GetCoalition(),_unit:GetCoalition()))
|
|
68931
69467
|
end
|
|
@@ -69148,6 +69684,7 @@ local _found,_pilotable=self:_CheckNameInDownedPilots(_woundedGroupName)
|
|
|
69148
69684
|
local _pilotName=_pilotable.desc
|
|
69149
69685
|
local _reset=true
|
|
69150
69686
|
if(_distance<500)then
|
|
69687
|
+
self:T(self.lid.."[Pickup Debug] Helo closer than 500m: ".._lookupKeyHeli)
|
|
69151
69688
|
if self.heliCloseMessage[_lookupKeyHeli]==nil then
|
|
69152
69689
|
if self.autosmoke==true then
|
|
69153
69690
|
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 +69693,15 @@ self:_DisplayMessageToSAR(_heliUnit,string.format("%s: %s. You\'re close now! La
|
|
|
69156
69693
|
end
|
|
69157
69694
|
self.heliCloseMessage[_lookupKeyHeli]=true
|
|
69158
69695
|
end
|
|
69696
|
+
self:T(self.lid.."[Pickup Debug] Checking landed vs Hover for ".._lookupKeyHeli)
|
|
69159
69697
|
if not _heliUnit:InAir()then
|
|
69698
|
+
self:T(self.lid.."[Pickup Debug] Helo landed: ".._lookupKeyHeli)
|
|
69160
69699
|
if self.pilotRuntoExtractPoint==true then
|
|
69161
69700
|
if(_distance<self.extractDistance)then
|
|
69162
69701
|
local _time=self.landedStatus[_lookupKeyHeli]
|
|
69702
|
+
self:T(self.lid.."[Pickup Debug] Check pilot running or arrived ".._lookupKeyHeli)
|
|
69163
69703
|
if _time==nil then
|
|
69704
|
+
self:T(self.lid.."[Pickup Debug] Pilot running not arrived yet ".._lookupKeyHeli)
|
|
69164
69705
|
self.landedStatus[_lookupKeyHeli]=math.floor((_distance-self.loadDistance)/3.6)
|
|
69165
69706
|
_time=self.landedStatus[_lookupKeyHeli]
|
|
69166
69707
|
_woundedGroup:OptionAlarmStateGreen()
|
|
@@ -69170,11 +69711,15 @@ else
|
|
|
69170
69711
|
_time=self.landedStatus[_lookupKeyHeli]-10
|
|
69171
69712
|
self.landedStatus[_lookupKeyHeli]=_time
|
|
69172
69713
|
end
|
|
69714
|
+
self:T(self.lid.."[Pickup Debug] Pilot close enough? ".._lookupKeyHeli)
|
|
69173
69715
|
if _distance<self.loadDistance+5 or _distance<=13 then
|
|
69716
|
+
self:T(self.lid.."[Pickup Debug] Pilot close enough - YES ".._lookupKeyHeli)
|
|
69174
69717
|
if self.pilotmustopendoors and(self:_IsLoadingDoorOpen(_heliName)==false)then
|
|
69175
69718
|
self:_DisplayMessageToSAR(_heliUnit,"Open the door to let me in!",self.messageTime,true,true)
|
|
69719
|
+
self:T(self.lid.."[Pickup Debug] Door closed, try again next loop ".._lookupKeyHeli)
|
|
69176
69720
|
return false
|
|
69177
69721
|
else
|
|
69722
|
+
self:T(self.lid.."[Pickup Debug] Pick up Pilot ".._lookupKeyHeli)
|
|
69178
69723
|
self.landedStatus[_lookupKeyHeli]=nil
|
|
69179
69724
|
self:_PickupUnit(_heliUnit,_pilotName,_woundedGroup,_woundedGroupName)
|
|
69180
69725
|
return true
|
|
@@ -69182,28 +69727,36 @@ end
|
|
|
69182
69727
|
end
|
|
69183
69728
|
end
|
|
69184
69729
|
else
|
|
69730
|
+
self:T(self.lid.."[Pickup Debug] Helo landed, pilot NOT set to run to helo ".._lookupKeyHeli)
|
|
69185
69731
|
if(_distance<self.loadDistance)then
|
|
69732
|
+
self:T(self.lid.."[Pickup Debug] Helo close enough, door check ".._lookupKeyHeli)
|
|
69186
69733
|
if self.pilotmustopendoors and(self:_IsLoadingDoorOpen(_heliName)==false)then
|
|
69734
|
+
self:T(self.lid.."[Pickup Debug] Door closed, try again next loop ".._lookupKeyHeli)
|
|
69187
69735
|
self:_DisplayMessageToSAR(_heliUnit,"Open the door to let me in!",self.messageTime,true,true)
|
|
69188
69736
|
return false
|
|
69189
69737
|
else
|
|
69738
|
+
self:T(self.lid.."[Pickup Debug] Pick up Pilot ".._lookupKeyHeli)
|
|
69190
69739
|
self:_PickupUnit(_heliUnit,_pilotName,_woundedGroup,_woundedGroupName)
|
|
69191
69740
|
return true
|
|
69192
69741
|
end
|
|
69193
69742
|
end
|
|
69194
69743
|
end
|
|
69195
69744
|
else
|
|
69745
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering".._lookupKeyHeli)
|
|
69196
69746
|
local _unitsInHelicopter=self:_PilotsOnboard(_heliName)
|
|
69197
69747
|
local _maxUnits=self.AircraftType[_heliUnit:GetTypeName()]
|
|
69198
69748
|
if _maxUnits==nil then
|
|
69199
69749
|
_maxUnits=self.max_units
|
|
69200
69750
|
end
|
|
69751
|
+
self:T(self.lid.."[Pickup Debug] Check capacity and close enough for winching ".._lookupKeyHeli)
|
|
69201
69752
|
if _heliUnit:InAir()and _unitsInHelicopter+1<=_maxUnits then
|
|
69202
69753
|
if _distance<self.rescuehoverdistance then
|
|
69754
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering close enough ".._lookupKeyHeli)
|
|
69203
69755
|
local leaderheight=_woundedLeader:GetHeight()
|
|
69204
69756
|
if leaderheight<0 then leaderheight=0 end
|
|
69205
69757
|
local _height=_heliUnit:GetHeight()-leaderheight
|
|
69206
69758
|
if _height<=self.rescuehoverheight then
|
|
69759
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering low enough ".._lookupKeyHeli)
|
|
69207
69760
|
local _time=self.hoverStatus[_lookupKeyHeli]
|
|
69208
69761
|
if _time==nil then
|
|
69209
69762
|
self.hoverStatus[_lookupKeyHeli]=10
|
|
@@ -69212,21 +69765,28 @@ else
|
|
|
69212
69765
|
_time=self.hoverStatus[_lookupKeyHeli]-10
|
|
69213
69766
|
self.hoverStatus[_lookupKeyHeli]=_time
|
|
69214
69767
|
end
|
|
69768
|
+
self:T(self.lid.."[Pickup Debug] Check hover timer ".._lookupKeyHeli)
|
|
69215
69769
|
if _time>0 then
|
|
69770
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering not long enough ".._lookupKeyHeli)
|
|
69216
69771
|
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
69772
|
else
|
|
69773
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering long enough - door check ".._lookupKeyHeli)
|
|
69218
69774
|
if self.pilotmustopendoors and(self:_IsLoadingDoorOpen(_heliName)==false)then
|
|
69219
69775
|
self:_DisplayMessageToSAR(_heliUnit,"Open the door to let me in!",self.messageTime,true,true)
|
|
69776
|
+
self:T(self.lid.."[Pickup Debug] Door closed, try again next loop ".._lookupKeyHeli)
|
|
69220
69777
|
return false
|
|
69221
69778
|
else
|
|
69222
69779
|
self.hoverStatus[_lookupKeyHeli]=nil
|
|
69223
69780
|
self:_PickupUnit(_heliUnit,_pilotName,_woundedGroup,_woundedGroupName)
|
|
69781
|
+
self:T(self.lid.."[Pickup Debug] Pilot picked up ".._lookupKeyHeli)
|
|
69224
69782
|
return true
|
|
69225
69783
|
end
|
|
69226
69784
|
end
|
|
69227
69785
|
_reset=false
|
|
69228
69786
|
else
|
|
69787
|
+
self:T(self.lid.."[Pickup Debug] Helo hovering too high ".._lookupKeyHeli)
|
|
69229
69788
|
self:_DisplayMessageToSAR(_heliUnit,"Too high to winch ".._pilotName.." \nReduce height and hover for 10 seconds!",self.messageTime,true,true)
|
|
69789
|
+
self:T(self.lid.."[Pickup Debug] Hovering too high, try again next loop ".._lookupKeyHeli)
|
|
69230
69790
|
return false
|
|
69231
69791
|
end
|
|
69232
69792
|
end
|
|
@@ -69242,7 +69802,7 @@ else
|
|
|
69242
69802
|
return false
|
|
69243
69803
|
end
|
|
69244
69804
|
end
|
|
69245
|
-
function CSAR:_ScheduledSARFlight(heliname,groupname,isairport)
|
|
69805
|
+
function CSAR:_ScheduledSARFlight(heliname,groupname,isairport,noreschedule)
|
|
69246
69806
|
self:T(self.lid.." _ScheduledSARFlight")
|
|
69247
69807
|
self:T({heliname,groupname})
|
|
69248
69808
|
local _heliUnit=self:_GetSARHeli(heliname)
|
|
@@ -69256,17 +69816,25 @@ return
|
|
|
69256
69816
|
end
|
|
69257
69817
|
local _dist=self:_GetClosestMASH(_heliUnit)
|
|
69258
69818
|
if _dist==-1 then
|
|
69819
|
+
self:T(self.lid.."[Drop off debug] Check distance to MASH for "..heliname.." Distance can not be determined!")
|
|
69259
69820
|
return
|
|
69260
69821
|
end
|
|
69822
|
+
self:T(self.lid.."[Drop off debug] Check distance to MASH for "..heliname.." Distance km: "..math.floor(_dist/1000))
|
|
69261
69823
|
if(_dist<self.FARPRescueDistance or isairport)and _heliUnit:InAir()==false then
|
|
69824
|
+
self:T(self.lid.."[Drop off debug] Distance ok, door check")
|
|
69262
69825
|
if self.pilotmustopendoors and self:_IsLoadingDoorOpen(heliname)==false then
|
|
69263
69826
|
self:_DisplayMessageToSAR(_heliUnit,"Open the door to let me out!",self.messageTime,true,true)
|
|
69827
|
+
self:T(self.lid.."[Drop off debug] Door closed, try again next loop")
|
|
69264
69828
|
else
|
|
69829
|
+
self:T(self.lid.."[Drop off debug] Rescued!")
|
|
69265
69830
|
self:_RescuePilots(_heliUnit)
|
|
69266
69831
|
return
|
|
69267
69832
|
end
|
|
69268
69833
|
end
|
|
69269
|
-
|
|
69834
|
+
if not noreschedule then
|
|
69835
|
+
self:__Returning(5,heliname,_woundedGroupName,isairport)
|
|
69836
|
+
self:ScheduleOnce(5,self._ScheduledSARFlight,self,heliname,groupname,isairport,noreschedule)
|
|
69837
|
+
end
|
|
69270
69838
|
return self
|
|
69271
69839
|
end
|
|
69272
69840
|
function CSAR:_RescuePilots(_heliUnit)
|
|
@@ -69308,7 +69876,6 @@ self.msrs:SetCoordinate(coord)
|
|
|
69308
69876
|
end
|
|
69309
69877
|
_text=string.gsub(_text,"km"," kilometer")
|
|
69310
69878
|
_text=string.gsub(_text,"nm"," nautical miles")
|
|
69311
|
-
self:I("Voice = "..self.SRSVoice)
|
|
69312
69879
|
self.SRSQueue:NewTransmission(_text,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,self.SRSVoice,volume,label,coord)
|
|
69313
69880
|
end
|
|
69314
69881
|
return self
|
|
@@ -69670,7 +70237,7 @@ self:T(self.lid.." _RefreshRadioBeacons")
|
|
|
69670
70237
|
if self:_CountActiveDownedPilots()>0 then
|
|
69671
70238
|
local PilotTable=self.downedPilots
|
|
69672
70239
|
for _,_pilot in pairs(PilotTable)do
|
|
69673
|
-
self:T({_pilot})
|
|
70240
|
+
self:T({_pilot.name})
|
|
69674
70241
|
local pilot=_pilot
|
|
69675
70242
|
local group=pilot.group
|
|
69676
70243
|
local frequency=pilot.frequency or 0
|
|
@@ -69872,7 +70439,6 @@ return self
|
|
|
69872
70439
|
end
|
|
69873
70440
|
function CSAR:onbeforeReturning(From,Event,To,Heliname,Woundedgroupname,IsAirPort)
|
|
69874
70441
|
self:T({From,Event,To,Heliname,Woundedgroupname})
|
|
69875
|
-
self:_ScheduledSARFlight(Heliname,Woundedgroupname,IsAirPort)
|
|
69876
70442
|
return self
|
|
69877
70443
|
end
|
|
69878
70444
|
function CSAR:onbeforeRescued(From,Event,To,HeliUnit,HeliName,PilotsSaved)
|
|
@@ -70279,7 +70845,7 @@ local DistanceFromHomeBase=self.HomeAirbase:GetCoordinate():Get2DDistance(self.C
|
|
|
70279
70845
|
if not self:Is("Holding")and not self:Is("Returning")then
|
|
70280
70846
|
local DistanceFromHomeBase=self.HomeAirbase:GetCoordinate():Get2DDistance(self.Controllable:GetCoordinate())
|
|
70281
70847
|
if DistanceFromHomeBase>self.DisengageRadius then
|
|
70282
|
-
self:
|
|
70848
|
+
self:T(self.Controllable:GetName().." is too far from home base, RTB!")
|
|
70283
70849
|
self:Hold(300)
|
|
70284
70850
|
RTB=false
|
|
70285
70851
|
end
|
|
@@ -70288,10 +70854,10 @@ if not self:Is("Fuel")and not self:Is("Home")and not self:is("Refuelling")then
|
|
|
70288
70854
|
local Fuel=self.Controllable:GetFuelMin()
|
|
70289
70855
|
if Fuel<self.FuelThresholdPercentage then
|
|
70290
70856
|
if self.TankerName then
|
|
70291
|
-
self:
|
|
70857
|
+
self:T(self.Controllable:GetName().." is out of fuel: "..Fuel.." ... Refuelling at Tanker!")
|
|
70292
70858
|
self:Refuel()
|
|
70293
70859
|
else
|
|
70294
|
-
self:
|
|
70860
|
+
self:T(self.Controllable:GetName().." is out of fuel: "..Fuel.." ... RTB!")
|
|
70295
70861
|
local OldAIControllable=self.Controllable
|
|
70296
70862
|
local OrbitTask=OldAIControllable:TaskOrbitCircle(math.random(self.PatrolFloorAltitude,self.PatrolCeilingAltitude),self.PatrolMinSpeed)
|
|
70297
70863
|
local TimedOrbitTask=OldAIControllable:TaskControlled(OrbitTask,OldAIControllable:TaskCondition(nil,nil,nil,nil,self.OutOfFuelOrbitTime,nil))
|
|
@@ -70308,7 +70874,7 @@ end
|
|
|
70308
70874
|
local Damage=self.Controllable:GetLife()
|
|
70309
70875
|
local InitialLife=self.Controllable:GetLife0()
|
|
70310
70876
|
if(Damage/InitialLife)<self.PatrolDamageThreshold then
|
|
70311
|
-
self:
|
|
70877
|
+
self:T(self.Controllable:GetName().." is damaged: "..Damage.." ... RTB!")
|
|
70312
70878
|
self:Damaged()
|
|
70313
70879
|
RTB=true
|
|
70314
70880
|
self:SetStatusOff()
|
|
@@ -70323,7 +70889,7 @@ if self.IdleCount>=10 then
|
|
|
70323
70889
|
if Damage~=InitialLife then
|
|
70324
70890
|
self:Damaged()
|
|
70325
70891
|
else
|
|
70326
|
-
self:
|
|
70892
|
+
self:T(self.Controllable:GetName().." control lost! ")
|
|
70327
70893
|
self:LostControl()
|
|
70328
70894
|
end
|
|
70329
70895
|
else
|
|
@@ -70369,6 +70935,7 @@ self:ClearTargetDistance()
|
|
|
70369
70935
|
AIGroup:OptionProhibitAfterburner(true)
|
|
70370
70936
|
local EngageRoute={}
|
|
70371
70937
|
local FromCoord=AIGroup:GetCoordinate()
|
|
70938
|
+
if not FromCoord then return end
|
|
70372
70939
|
local ToTargetCoord=self.HomeAirbase:GetCoordinate()
|
|
70373
70940
|
local ToTargetVec3=ToTargetCoord:GetVec3()
|
|
70374
70941
|
ToTargetVec3.y=ToTargetCoord:GetLandHeight()+3000
|
|
@@ -70383,12 +70950,12 @@ local RTBSpeed=math.random(self.RTBMinSpeed,self.RTBMaxSpeed)
|
|
|
70383
70950
|
local Distance=FromCoord:Get2DDistance(ToTargetCoord2)
|
|
70384
70951
|
local ToAirbaseCoord=ToTargetCoord2
|
|
70385
70952
|
if Distance<5000 then
|
|
70386
|
-
self:
|
|
70953
|
+
self:T("RTB and near the airbase!")
|
|
70387
70954
|
self:Home()
|
|
70388
70955
|
return
|
|
70389
70956
|
end
|
|
70390
70957
|
if not AIGroup:InAir()==true then
|
|
70391
|
-
self:
|
|
70958
|
+
self:T("Not anymore in the air, considered Home.")
|
|
70392
70959
|
self:Home()
|
|
70393
70960
|
return
|
|
70394
70961
|
end
|
|
@@ -70418,15 +70985,17 @@ end
|
|
|
70418
70985
|
end
|
|
70419
70986
|
function AI_AIR:onafterHome(AIGroup,From,Event,To)
|
|
70420
70987
|
self:F({AIGroup,From,Event,To})
|
|
70421
|
-
self:
|
|
70988
|
+
self:T("Group "..self.Controllable:GetName().." ... Home! ( "..self:GetState().." )")
|
|
70422
70989
|
if AIGroup and AIGroup:IsAlive()then
|
|
70423
70990
|
end
|
|
70424
70991
|
end
|
|
70425
70992
|
function AI_AIR:onafterHold(AIGroup,From,Event,To,HoldTime)
|
|
70426
70993
|
self:F({AIGroup,From,Event,To})
|
|
70427
|
-
self:
|
|
70994
|
+
self:T("Group "..self.Controllable:GetName().." ... Holding! ( "..self:GetState().." )")
|
|
70428
70995
|
if AIGroup and AIGroup:IsAlive()then
|
|
70429
|
-
local
|
|
70996
|
+
local Coordinate=AIGroup:GetCoordinate()
|
|
70997
|
+
if Coordinate==nil then return end
|
|
70998
|
+
local OrbitTask=AIGroup:TaskOrbitCircle(math.random(self.PatrolFloorAltitude,self.PatrolCeilingAltitude),self.PatrolMinSpeed,Coordinate)
|
|
70430
70999
|
local TimedOrbitTask=AIGroup:TaskControlled(OrbitTask,AIGroup:TaskCondition(nil,nil,nil,nil,HoldTime,nil))
|
|
70431
71000
|
local RTBTask=AIGroup:TaskFunction("AI_AIR.RTBHold",self)
|
|
70432
71001
|
local OrbitHoldTask=AIGroup:TaskOrbitCircle(4000,self.PatrolMinSpeed)
|
|
@@ -70434,7 +71003,7 @@ AIGroup:SetTask(AIGroup:TaskCombo({TimedOrbitTask,RTBTask,OrbitHoldTask}),1)
|
|
|
70434
71003
|
end
|
|
70435
71004
|
end
|
|
70436
71005
|
function AI_AIR.Resume(AIGroup,Fsm)
|
|
70437
|
-
AIGroup:
|
|
71006
|
+
AIGroup:T({"AI_AIR.Resume:",AIGroup:GetName()})
|
|
70438
71007
|
if AIGroup:IsAlive()then
|
|
70439
71008
|
Fsm:__RTB(Fsm.TaskDelay)
|
|
70440
71009
|
end
|
|
@@ -70444,7 +71013,7 @@ self:F({AIGroup,From,Event,To})
|
|
|
70444
71013
|
if AIGroup and AIGroup:IsAlive()then
|
|
70445
71014
|
local Tanker=GROUP:FindByName(self.TankerName)
|
|
70446
71015
|
if Tanker and Tanker:IsAlive()and Tanker:IsAirPlane()then
|
|
70447
|
-
self:
|
|
71016
|
+
self:T("Group "..self.Controllable:GetName().." ... Refuelling! State="..self:GetState()..", Refuelling tanker "..self.TankerName)
|
|
70448
71017
|
local RefuelRoute={}
|
|
70449
71018
|
local FromRefuelCoord=AIGroup:GetCoordinate()
|
|
70450
71019
|
local ToRefuelCoord=Tanker:GetCoordinate()
|
|
@@ -70657,13 +71226,13 @@ end
|
|
|
70657
71226
|
end
|
|
70658
71227
|
end
|
|
70659
71228
|
function AI_AIR_ENGAGE.___EngageRoute(AIGroup,Fsm,AttackSetUnit)
|
|
70660
|
-
Fsm:
|
|
71229
|
+
Fsm:T(string.format("AI_AIR_ENGAGE.___EngageRoute: %s",tostring(AIGroup:GetName())))
|
|
70661
71230
|
if AIGroup and AIGroup:IsAlive()then
|
|
70662
71231
|
Fsm:__EngageRoute(Fsm.TaskDelay or 0.1,AttackSetUnit)
|
|
70663
71232
|
end
|
|
70664
71233
|
end
|
|
70665
71234
|
function AI_AIR_ENGAGE:onafterEngageRoute(DefenderGroup,From,Event,To,AttackSetUnit)
|
|
70666
|
-
self:
|
|
71235
|
+
self:T({DefenderGroup,From,Event,To,AttackSetUnit})
|
|
70667
71236
|
local DefenderGroupName=DefenderGroup:GetName()
|
|
70668
71237
|
self.AttackSetUnit=AttackSetUnit
|
|
70669
71238
|
local AttackCount=AttackSetUnit:CountAlive()
|
|
@@ -70673,7 +71242,11 @@ local EngageAltitude=math.random(self.EngageFloorAltitude,self.EngageCeilingAlti
|
|
|
70673
71242
|
local EngageSpeed=math.random(self.EngageMinSpeed,self.EngageMaxSpeed)
|
|
70674
71243
|
local DefenderCoord=DefenderGroup:GetPointVec3()
|
|
70675
71244
|
DefenderCoord:SetY(EngageAltitude)
|
|
70676
|
-
local TargetCoord=AttackSetUnit:
|
|
71245
|
+
local TargetCoord=AttackSetUnit:GetRandomSurely():GetPointVec3()
|
|
71246
|
+
if TargetCoord==nil then
|
|
71247
|
+
self:Return()
|
|
71248
|
+
return
|
|
71249
|
+
end
|
|
70677
71250
|
TargetCoord:SetY(EngageAltitude)
|
|
70678
71251
|
local TargetDistance=DefenderCoord:Get2DDistance(TargetCoord)
|
|
70679
71252
|
local EngageDistance=(DefenderGroup:IsHelicopter()and 5000)or(DefenderGroup:IsAirPlane()and 10000)
|
|
@@ -70697,12 +71270,12 @@ DefenderGroup:Route(EngageRoute,self.TaskDelay or 0.1)
|
|
|
70697
71270
|
end
|
|
70698
71271
|
end
|
|
70699
71272
|
else
|
|
70700
|
-
self:
|
|
71273
|
+
self:T(DefenderGroupName..": No targets found -> Going RTB")
|
|
70701
71274
|
self:Return()
|
|
70702
71275
|
end
|
|
70703
71276
|
end
|
|
70704
71277
|
function AI_AIR_ENGAGE.___Engage(AIGroup,Fsm,AttackSetUnit)
|
|
70705
|
-
Fsm:
|
|
71278
|
+
Fsm:T(string.format("AI_AIR_ENGAGE.___Engage: %s",tostring(AIGroup:GetName())))
|
|
70706
71279
|
if AIGroup and AIGroup:IsAlive()then
|
|
70707
71280
|
local delay=Fsm.TaskDelay or 0.1
|
|
70708
71281
|
Fsm:__Engage(delay,AttackSetUnit)
|
|
@@ -70720,7 +71293,7 @@ local EngageAltitude=math.random(self.EngageFloorAltitude or 500,self.EngageCeil
|
|
|
70720
71293
|
local EngageSpeed=math.random(self.EngageMinSpeed,self.EngageMaxSpeed)
|
|
70721
71294
|
local DefenderCoord=DefenderGroup:GetPointVec3()
|
|
70722
71295
|
DefenderCoord:SetY(EngageAltitude)
|
|
70723
|
-
local TargetCoord=AttackSetUnit:
|
|
71296
|
+
local TargetCoord=AttackSetUnit:GetRandomSurely():GetPointVec3()
|
|
70724
71297
|
if not TargetCoord then
|
|
70725
71298
|
self:Return()
|
|
70726
71299
|
return
|
|
@@ -70740,12 +71313,12 @@ EngageRoute[#EngageRoute+1]=ToWP
|
|
|
70740
71313
|
if TargetDistance<=EngageDistance*9 then
|
|
70741
71314
|
local AttackUnitTasks=self:CreateAttackUnitTasks(AttackSetUnit,DefenderGroup,EngageAltitude)
|
|
70742
71315
|
if#AttackUnitTasks==0 then
|
|
70743
|
-
self:
|
|
71316
|
+
self:T(DefenderGroupName..": No valid targets found -> Going RTB")
|
|
70744
71317
|
self:Return()
|
|
70745
71318
|
return
|
|
70746
71319
|
else
|
|
70747
71320
|
local text=string.format("%s: Engaging targets at distance %.2f NM",DefenderGroupName,UTILS.MetersToNM(TargetDistance))
|
|
70748
|
-
self:
|
|
71321
|
+
self:T(text)
|
|
70749
71322
|
DefenderGroup:OptionROEOpenFire()
|
|
70750
71323
|
DefenderGroup:OptionROTEvadeFire()
|
|
70751
71324
|
DefenderGroup:OptionKeepWeaponsOnThreat()
|
|
@@ -70757,7 +71330,7 @@ EngageRoute[#EngageRoute].task=DefenderGroup:TaskCombo(AttackTasks)
|
|
|
70757
71330
|
DefenderGroup:Route(EngageRoute,self.TaskDelay or 0.1)
|
|
70758
71331
|
end
|
|
70759
71332
|
else
|
|
70760
|
-
self:
|
|
71333
|
+
self:T(DefenderGroupName..": No targets found -> returning.")
|
|
70761
71334
|
self:Return()
|
|
70762
71335
|
return
|
|
70763
71336
|
end
|
|
@@ -71018,12 +71591,12 @@ end
|
|
|
71018
71591
|
end
|
|
71019
71592
|
function AI_A2A_DISPATCHER:OnEventBaseCaptured(EventData)
|
|
71020
71593
|
local AirbaseName=EventData.PlaceName
|
|
71021
|
-
self:
|
|
71594
|
+
self:T("Captured "..AirbaseName)
|
|
71022
71595
|
for SquadronName,Squadron in pairs(self.DefenderSquadrons)do
|
|
71023
71596
|
if Squadron.AirbaseName==AirbaseName then
|
|
71024
71597
|
Squadron.ResourceCount=-999
|
|
71025
71598
|
Squadron.Captured=true
|
|
71026
|
-
self:
|
|
71599
|
+
self:T("Squadron "..SquadronName.." captured.")
|
|
71027
71600
|
end
|
|
71028
71601
|
end
|
|
71029
71602
|
end
|
|
@@ -71260,7 +71833,7 @@ Cap.PatrolCeilingAltitude=PatrolCeilingAltitude
|
|
|
71260
71833
|
Cap.PatrolAltType=PatrolAltType
|
|
71261
71834
|
Cap.EngageAltType=EngageAltType
|
|
71262
71835
|
self:SetSquadronCapInterval(SquadronName,self.DefenderDefault.CapLimit,self.DefenderDefault.CapMinSeconds,self.DefenderDefault.CapMaxSeconds,1)
|
|
71263
|
-
self:
|
|
71836
|
+
self:T({CAP={SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,Zone,PatrolMinSpeed,PatrolMaxSpeed,PatrolFloorAltitude,PatrolCeilingAltitude,PatrolAltType,EngageAltType}})
|
|
71264
71837
|
local RecceSet=self.Detection:GetDetectionSet()
|
|
71265
71838
|
RecceSet:FilterPrefixes(DefenderSquadron.TemplatePrefixes)
|
|
71266
71839
|
RecceSet:FilterStart()
|
|
@@ -71378,7 +71951,7 @@ Intercept.EngageMaxSpeed=EngageMaxSpeed
|
|
|
71378
71951
|
Intercept.EngageFloorAltitude=EngageFloorAltitude
|
|
71379
71952
|
Intercept.EngageCeilingAltitude=EngageCeilingAltitude
|
|
71380
71953
|
Intercept.EngageAltType=EngageAltType
|
|
71381
|
-
self:
|
|
71954
|
+
self:T({GCI={SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
71382
71955
|
end
|
|
71383
71956
|
function AI_A2A_DISPATCHER:SetSquadronGci(SquadronName,EngageMinSpeed,EngageMaxSpeed)
|
|
71384
71957
|
self.DefenderSquadrons[SquadronName]=self.DefenderSquadrons[SquadronName]or{}
|
|
@@ -72255,22 +72828,22 @@ table.insert(AirbaseNames,AirbaseName)
|
|
|
72255
72828
|
end
|
|
72256
72829
|
end
|
|
72257
72830
|
self.Templates=SET_GROUP:New():FilterPrefixes(TemplatePrefixes):FilterOnce()
|
|
72258
|
-
self:
|
|
72259
|
-
self:
|
|
72831
|
+
self:T({Airbases=AirbaseNames})
|
|
72832
|
+
self:T("Defining Templates for Airbases ...")
|
|
72260
72833
|
for AirbaseID,AirbaseName in pairs(AirbaseNames)do
|
|
72261
72834
|
local Airbase=_DATABASE:FindAirbase(AirbaseName)
|
|
72262
72835
|
local AirbaseName=Airbase:GetName()
|
|
72263
72836
|
local AirbaseCoord=Airbase:GetCoordinate()
|
|
72264
72837
|
local AirbaseZone=ZONE_RADIUS:New("Airbase",AirbaseCoord:GetVec2(),3000)
|
|
72265
72838
|
local Templates=nil
|
|
72266
|
-
self:
|
|
72839
|
+
self:T({Airbase=AirbaseName})
|
|
72267
72840
|
for TemplateID,Template in pairs(self.Templates:GetSet())do
|
|
72268
72841
|
local Template=Template
|
|
72269
72842
|
local TemplateCoord=Template:GetCoordinate()
|
|
72270
72843
|
if AirbaseZone:IsVec2InZone(TemplateCoord:GetVec2())then
|
|
72271
72844
|
Templates=Templates or{}
|
|
72272
72845
|
table.insert(Templates,Template:GetName())
|
|
72273
|
-
self:
|
|
72846
|
+
self:T({Template=Template:GetName()})
|
|
72274
72847
|
end
|
|
72275
72848
|
end
|
|
72276
72849
|
if Templates then
|
|
@@ -72280,12 +72853,12 @@ end
|
|
|
72280
72853
|
self.CAPTemplates=SET_GROUP:New()
|
|
72281
72854
|
self.CAPTemplates:FilterPrefixes(CapPrefixes)
|
|
72282
72855
|
self.CAPTemplates:FilterOnce()
|
|
72283
|
-
self:
|
|
72856
|
+
self:T("Setting up CAP ...")
|
|
72284
72857
|
for CAPID,CAPTemplate in pairs(self.CAPTemplates:GetSet())do
|
|
72285
72858
|
local CAPZone=ZONE_POLYGON:New(CAPTemplate:GetName(),CAPTemplate)
|
|
72286
72859
|
local AirbaseDistance=99999999
|
|
72287
72860
|
local AirbaseClosest=nil
|
|
72288
|
-
self:
|
|
72861
|
+
self:T({CAPZoneGroup=CAPID})
|
|
72289
72862
|
for AirbaseID,AirbaseName in pairs(AirbaseNames)do
|
|
72290
72863
|
local Airbase=_DATABASE:FindAirbase(AirbaseName)
|
|
72291
72864
|
local AirbaseName=Airbase:GetName()
|
|
@@ -72293,7 +72866,7 @@ local AirbaseCoord=Airbase:GetCoordinate()
|
|
|
72293
72866
|
local Squadron=self.DefenderSquadrons[AirbaseName]
|
|
72294
72867
|
if Squadron then
|
|
72295
72868
|
local Distance=AirbaseCoord:Get2DDistance(CAPZone:GetCoordinate())
|
|
72296
|
-
self:
|
|
72869
|
+
self:T({AirbaseDistance=Distance})
|
|
72297
72870
|
if Distance<AirbaseDistance then
|
|
72298
72871
|
AirbaseDistance=Distance
|
|
72299
72872
|
AirbaseClosest=Airbase
|
|
@@ -72301,19 +72874,19 @@ end
|
|
|
72301
72874
|
end
|
|
72302
72875
|
end
|
|
72303
72876
|
if AirbaseClosest then
|
|
72304
|
-
self:
|
|
72877
|
+
self:T({CAPAirbase=AirbaseClosest:GetName()})
|
|
72305
72878
|
self:SetSquadronCap(AirbaseClosest:GetName(),CAPZone,6000,10000,500,800,800,1200,"RADIO")
|
|
72306
72879
|
self:SetSquadronCapInterval(AirbaseClosest:GetName(),CapLimit,300,600,1)
|
|
72307
72880
|
end
|
|
72308
72881
|
end
|
|
72309
|
-
self:
|
|
72882
|
+
self:T("Setting up GCI ...")
|
|
72310
72883
|
for AirbaseID,AirbaseName in pairs(AirbaseNames)do
|
|
72311
72884
|
local Airbase=_DATABASE:FindAirbase(AirbaseName)
|
|
72312
72885
|
local AirbaseName=Airbase:GetName()
|
|
72313
72886
|
local Squadron=self.DefenderSquadrons[AirbaseName]
|
|
72314
72887
|
self:F({Airbase=AirbaseName})
|
|
72315
72888
|
if Squadron then
|
|
72316
|
-
self:
|
|
72889
|
+
self:T({GCIAirbase=AirbaseName})
|
|
72317
72890
|
self:SetSquadronGci(AirbaseName,800,1200)
|
|
72318
72891
|
end
|
|
72319
72892
|
end
|
|
@@ -72476,7 +73049,7 @@ DefenderSquadron.Resource={}
|
|
|
72476
73049
|
for Resource=1,DefenderSquadron.ResourceCount or 0 do
|
|
72477
73050
|
self:ResourcePark(DefenderSquadron)
|
|
72478
73051
|
end
|
|
72479
|
-
self:
|
|
73052
|
+
self:T("Parked resources for squadron "..DefenderSquadron.Name)
|
|
72480
73053
|
end
|
|
72481
73054
|
end
|
|
72482
73055
|
function AI_A2G_DISPATCHER:Lock(DetectedItemIndex)
|
|
@@ -72520,12 +73093,12 @@ end
|
|
|
72520
73093
|
end
|
|
72521
73094
|
function AI_A2G_DISPATCHER:OnEventBaseCaptured(EventData)
|
|
72522
73095
|
local AirbaseName=EventData.PlaceName
|
|
72523
|
-
self:
|
|
73096
|
+
self:T("Captured "..AirbaseName)
|
|
72524
73097
|
for SquadronName,Squadron in pairs(self.DefenderSquadrons)do
|
|
72525
73098
|
if Squadron.AirbaseName==AirbaseName then
|
|
72526
73099
|
Squadron.ResourceCount=-999
|
|
72527
73100
|
Squadron.Captured=true
|
|
72528
|
-
self:
|
|
73101
|
+
self:T("Squadron "..SquadronName.." captured.")
|
|
72529
73102
|
end
|
|
72530
73103
|
end
|
|
72531
73104
|
end
|
|
@@ -72546,7 +73119,7 @@ if DefenderSize==1 then
|
|
|
72546
73119
|
self:RemoveDefenderFromSquadron(Squadron,Defender)
|
|
72547
73120
|
end
|
|
72548
73121
|
DefenderUnit:Destroy()
|
|
72549
|
-
self:ResourcePark(Squadron
|
|
73122
|
+
self:ResourcePark(Squadron)
|
|
72550
73123
|
return
|
|
72551
73124
|
end
|
|
72552
73125
|
if DefenderUnit:GetLife()~=DefenderUnit:GetLife0()then
|
|
@@ -72569,7 +73142,7 @@ if DefenderSize==1 then
|
|
|
72569
73142
|
self:RemoveDefenderFromSquadron(Squadron,Defender)
|
|
72570
73143
|
end
|
|
72571
73144
|
DefenderUnit:Destroy()
|
|
72572
|
-
self:ResourcePark(Squadron
|
|
73145
|
+
self:ResourcePark(Squadron)
|
|
72573
73146
|
end
|
|
72574
73147
|
end
|
|
72575
73148
|
end
|
|
@@ -72592,7 +73165,7 @@ self.DisengageRadius=DisengageRadius or 300000
|
|
|
72592
73165
|
return self
|
|
72593
73166
|
end
|
|
72594
73167
|
function AI_A2G_DISPATCHER:SetDefenseRadius(DefenseRadius)
|
|
72595
|
-
self.DefenseRadius=DefenseRadius or
|
|
73168
|
+
self.DefenseRadius=DefenseRadius or 40000
|
|
72596
73169
|
self.Detection:SetAcceptRange(self.DefenseRadius)
|
|
72597
73170
|
return self
|
|
72598
73171
|
end
|
|
@@ -72861,7 +73434,7 @@ Sead.EngageFloorAltitude=EngageFloorAltitude or 500
|
|
|
72861
73434
|
Sead.EngageCeilingAltitude=EngageCeilingAltitude or 1000
|
|
72862
73435
|
Sead.EngageAltType=EngageAltType
|
|
72863
73436
|
Sead.Defend=true
|
|
72864
|
-
self:
|
|
73437
|
+
self:T({SEAD={SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72865
73438
|
return self
|
|
72866
73439
|
end
|
|
72867
73440
|
function AI_A2G_DISPATCHER:SetSquadronSead(SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude)
|
|
@@ -72888,7 +73461,7 @@ SeadPatrol.PatrolAltType=PatrolAltType
|
|
|
72888
73461
|
SeadPatrol.EngageAltType=EngageAltType
|
|
72889
73462
|
SeadPatrol.Patrol=true
|
|
72890
73463
|
self:SetSquadronPatrolInterval(SquadronName,self.DefenderDefault.PatrolLimit,self.DefenderDefault.PatrolMinSeconds,self.DefenderDefault.PatrolMaxSeconds,1,"SEAD")
|
|
72891
|
-
self:
|
|
73464
|
+
self:T({SEAD={Zone:GetName(),PatrolMinSpeed,PatrolMaxSpeed,PatrolFloorAltitude,PatrolCeilingAltitude,PatrolAltType,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72892
73465
|
end
|
|
72893
73466
|
function AI_A2G_DISPATCHER:SetSquadronSeadPatrol(SquadronName,Zone,FloorAltitude,CeilingAltitude,PatrolMinSpeed,PatrolMaxSpeed,EngageMinSpeed,EngageMaxSpeed,AltType)
|
|
72894
73467
|
self:SetSquadronSeadPatrol2(SquadronName,Zone,PatrolMinSpeed,PatrolMaxSpeed,FloorAltitude,CeilingAltitude,AltType,EngageMinSpeed,EngageMaxSpeed,FloorAltitude,CeilingAltitude,AltType)
|
|
@@ -72904,7 +73477,7 @@ Cas.EngageFloorAltitude=EngageFloorAltitude or 500
|
|
|
72904
73477
|
Cas.EngageCeilingAltitude=EngageCeilingAltitude or 1000
|
|
72905
73478
|
Cas.EngageAltType=EngageAltType
|
|
72906
73479
|
Cas.Defend=true
|
|
72907
|
-
self:
|
|
73480
|
+
self:T({CAS={SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72908
73481
|
return self
|
|
72909
73482
|
end
|
|
72910
73483
|
function AI_A2G_DISPATCHER:SetSquadronCas(SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude)
|
|
@@ -72931,7 +73504,7 @@ CasPatrol.PatrolAltType=PatrolAltType
|
|
|
72931
73504
|
CasPatrol.EngageAltType=EngageAltType
|
|
72932
73505
|
CasPatrol.Patrol=true
|
|
72933
73506
|
self:SetSquadronPatrolInterval(SquadronName,self.DefenderDefault.PatrolLimit,self.DefenderDefault.PatrolMinSeconds,self.DefenderDefault.PatrolMaxSeconds,1,"CAS")
|
|
72934
|
-
self:
|
|
73507
|
+
self:T({CAS={Zone:GetName(),PatrolMinSpeed,PatrolMaxSpeed,PatrolFloorAltitude,PatrolCeilingAltitude,PatrolAltType,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72935
73508
|
end
|
|
72936
73509
|
function AI_A2G_DISPATCHER:SetSquadronCasPatrol(SquadronName,Zone,FloorAltitude,CeilingAltitude,PatrolMinSpeed,PatrolMaxSpeed,EngageMinSpeed,EngageMaxSpeed,AltType)
|
|
72937
73510
|
self:SetSquadronCasPatrol2(SquadronName,Zone,PatrolMinSpeed,PatrolMaxSpeed,FloorAltitude,CeilingAltitude,AltType,EngageMinSpeed,EngageMaxSpeed,FloorAltitude,CeilingAltitude,AltType)
|
|
@@ -72947,7 +73520,7 @@ Bai.EngageFloorAltitude=EngageFloorAltitude or 500
|
|
|
72947
73520
|
Bai.EngageCeilingAltitude=EngageCeilingAltitude or 1000
|
|
72948
73521
|
Bai.EngageAltType=EngageAltType
|
|
72949
73522
|
Bai.Defend=true
|
|
72950
|
-
self:
|
|
73523
|
+
self:T({BAI={SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72951
73524
|
return self
|
|
72952
73525
|
end
|
|
72953
73526
|
function AI_A2G_DISPATCHER:SetSquadronBai(SquadronName,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude)
|
|
@@ -72974,7 +73547,7 @@ BaiPatrol.PatrolAltType=PatrolAltType
|
|
|
72974
73547
|
BaiPatrol.EngageAltType=EngageAltType
|
|
72975
73548
|
BaiPatrol.Patrol=true
|
|
72976
73549
|
self:SetSquadronPatrolInterval(SquadronName,self.DefenderDefault.PatrolLimit,self.DefenderDefault.PatrolMinSeconds,self.DefenderDefault.PatrolMaxSeconds,1,"BAI")
|
|
72977
|
-
self:
|
|
73550
|
+
self:T({BAI={Zone:GetName(),PatrolMinSpeed,PatrolMaxSpeed,PatrolFloorAltitude,PatrolCeilingAltitude,PatrolAltType,EngageMinSpeed,EngageMaxSpeed,EngageFloorAltitude,EngageCeilingAltitude,EngageAltType}})
|
|
72978
73551
|
end
|
|
72979
73552
|
function AI_A2G_DISPATCHER:SetSquadronBaiPatrol(SquadronName,Zone,FloorAltitude,CeilingAltitude,PatrolMinSpeed,PatrolMaxSpeed,EngageMinSpeed,EngageMaxSpeed,AltType)
|
|
72980
73553
|
self:SetSquadronBaiPatrol2(SquadronName,Zone,PatrolMinSpeed,PatrolMaxSpeed,FloorAltitude,CeilingAltitude,AltType,EngageMinSpeed,EngageMaxSpeed,FloorAltitude,CeilingAltitude,AltType)
|
|
@@ -73514,7 +74087,7 @@ local DefenderName=DefenderGroup:GetCallsign()
|
|
|
73514
74087
|
local Dispatcher=AI_A2G_Fsm:GetDispatcher()
|
|
73515
74088
|
local Squadron=Dispatcher:GetSquadronFromDefender(DefenderGroup)
|
|
73516
74089
|
if Squadron then
|
|
73517
|
-
local FirstUnit=AttackSetUnit:
|
|
74090
|
+
local FirstUnit=AttackSetUnit:GetRandomSurely()
|
|
73518
74091
|
local Coordinate=FirstUnit:GetCoordinate()
|
|
73519
74092
|
if self.SetSendPlayerMessages then
|
|
73520
74093
|
Dispatcher:MessageToPlayers(Squadron,DefenderName..", on route to ground target at "..Coordinate:ToStringA2G(DefenderGroup),DefenderGroup)
|
|
@@ -74333,7 +74906,7 @@ if self.Controllable and self.Controllable:IsAlive()then
|
|
|
74333
74906
|
local RTB=false
|
|
74334
74907
|
local Fuel=self.Controllable:GetFuelMin()
|
|
74335
74908
|
if Fuel<self.PatrolFuelThresholdPercentage then
|
|
74336
|
-
self:
|
|
74909
|
+
self:T(self.Controllable:GetName().." is out of fuel:"..Fuel..", RTB!")
|
|
74337
74910
|
local OldAIControllable=self.Controllable
|
|
74338
74911
|
local OrbitTask=OldAIControllable:TaskOrbitCircle(math.random(self.PatrolFloorAltitude,self.PatrolCeilingAltitude),self.PatrolMinSpeed)
|
|
74339
74912
|
local TimedOrbitTask=OldAIControllable:TaskControlled(OrbitTask,OldAIControllable:TaskCondition(nil,nil,nil,nil,self.PatrolOutOfFuelOrbitTime,nil))
|
|
@@ -74343,7 +74916,7 @@ else
|
|
|
74343
74916
|
end
|
|
74344
74917
|
local Damage=self.Controllable:GetLife()
|
|
74345
74918
|
if Damage<=self.PatrolDamageThreshold then
|
|
74346
|
-
self:
|
|
74919
|
+
self:T(self.Controllable:GetName().." is damaged:"..Damage..", RTB!")
|
|
74347
74920
|
RTB=true
|
|
74348
74921
|
end
|
|
74349
74922
|
if RTB==true then
|
|
@@ -76509,11 +77082,11 @@ function AI_ESCORT_DISPATCHER:OnEventExit(EventData)
|
|
|
76509
77082
|
local PlayerGroupName=EventData.IniGroupName
|
|
76510
77083
|
local PlayerGroup=EventData.IniGroup
|
|
76511
77084
|
local PlayerUnit=EventData.IniUnit
|
|
76512
|
-
self:
|
|
76513
|
-
self:
|
|
76514
|
-
self:
|
|
76515
|
-
self:
|
|
76516
|
-
self:
|
|
77085
|
+
self:T({EscortAirbase=self.EscortAirbase})
|
|
77086
|
+
self:T({PlayerGroupName=PlayerGroupName})
|
|
77087
|
+
self:T({PlayerGroup=PlayerGroup})
|
|
77088
|
+
self:T({FirstGroup=self.CarrierSet:GetFirst()})
|
|
77089
|
+
self:T({FindGroup=self.CarrierSet:FindGroup(PlayerGroupName)})
|
|
76517
77090
|
if self.CarrierSet:FindGroup(PlayerGroupName)then
|
|
76518
77091
|
if self.AI_Escorts[PlayerGroupName]then
|
|
76519
77092
|
self.AI_Escorts[PlayerGroupName]:Stop()
|
|
@@ -76525,16 +77098,16 @@ function AI_ESCORT_DISPATCHER:OnEventBirth(EventData)
|
|
|
76525
77098
|
local PlayerGroupName=EventData.IniGroupName
|
|
76526
77099
|
local PlayerGroup=EventData.IniGroup
|
|
76527
77100
|
local PlayerUnit=EventData.IniUnit
|
|
76528
|
-
self:
|
|
76529
|
-
self:
|
|
76530
|
-
self:
|
|
76531
|
-
self:
|
|
76532
|
-
self:
|
|
77101
|
+
self:T({EscortAirbase=self.EscortAirbase})
|
|
77102
|
+
self:T({PlayerGroupName=PlayerGroupName})
|
|
77103
|
+
self:T({PlayerGroup=PlayerGroup})
|
|
77104
|
+
self:T({FirstGroup=self.CarrierSet:GetFirst()})
|
|
77105
|
+
self:T({FindGroup=self.CarrierSet:FindGroup(PlayerGroupName)})
|
|
76533
77106
|
if self.CarrierSet:FindGroup(PlayerGroupName)then
|
|
76534
77107
|
if not self.AI_Escorts[PlayerGroupName]then
|
|
76535
77108
|
local LeaderUnit=PlayerUnit
|
|
76536
77109
|
local EscortGroup=self.EscortSpawn:SpawnAtAirbase(self.EscortAirbase,SPAWN.Takeoff.Hot)
|
|
76537
|
-
self:
|
|
77110
|
+
self:T({EscortGroup=EscortGroup})
|
|
76538
77111
|
self:ScheduleOnce(1,
|
|
76539
77112
|
function(EscortGroup)
|
|
76540
77113
|
local EscortSet=SET_GROUP:New()
|
|
@@ -76833,7 +77406,7 @@ if Carrier and Carrier:IsAlive()then
|
|
|
76833
77406
|
for _,CarrierUnit in pairs(Carrier:GetUnits())do
|
|
76834
77407
|
local CarrierUnit=CarrierUnit
|
|
76835
77408
|
local IsEmpty=CarrierUnit:IsCargoEmpty()
|
|
76836
|
-
self:
|
|
77409
|
+
self:T({IsEmpty=IsEmpty})
|
|
76837
77410
|
if not IsEmpty then
|
|
76838
77411
|
AllUnloaded=false
|
|
76839
77412
|
break
|
|
@@ -77921,7 +78494,7 @@ break
|
|
|
77921
78494
|
else
|
|
77922
78495
|
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
78496
|
tostring(Cargo:GetName()),Cargo:GetWeight(),LargestLoadCapacity,tostring(Carrier:GetName()))
|
|
77924
|
-
self:
|
|
78497
|
+
self:T(text)
|
|
77925
78498
|
end
|
|
77926
78499
|
end
|
|
77927
78500
|
end
|
|
@@ -78527,6 +79100,954 @@ end
|
|
|
78527
79100
|
)
|
|
78528
79101
|
end
|
|
78529
79102
|
end
|
|
79103
|
+
SHAPE_BASE={
|
|
79104
|
+
ClassName="SHAPE_BASE",
|
|
79105
|
+
Name="",
|
|
79106
|
+
CenterVec2=nil,
|
|
79107
|
+
Points={},
|
|
79108
|
+
Coords={},
|
|
79109
|
+
MarkIDs={},
|
|
79110
|
+
ColorString="",
|
|
79111
|
+
ColorRGBA={}
|
|
79112
|
+
}
|
|
79113
|
+
function SHAPE_BASE:New()
|
|
79114
|
+
local self=BASE:Inherit(self,BASE:New())
|
|
79115
|
+
return self
|
|
79116
|
+
end
|
|
79117
|
+
function SHAPE_BASE:FindOnMap(shape_name)
|
|
79118
|
+
local self=BASE:Inherit(self,BASE:New())
|
|
79119
|
+
local found=false
|
|
79120
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79121
|
+
for _,object in pairs(layer["objects"])do
|
|
79122
|
+
if object["name"]==shape_name then
|
|
79123
|
+
self.Name=object["name"]
|
|
79124
|
+
self.CenterVec2={x=object["mapX"],y=object["mapY"]}
|
|
79125
|
+
self.ColorString=object["colorString"]
|
|
79126
|
+
self.ColorRGBA=UTILS.HexToRGBA(self.ColorString)
|
|
79127
|
+
found=true
|
|
79128
|
+
end
|
|
79129
|
+
end
|
|
79130
|
+
end
|
|
79131
|
+
if not found then
|
|
79132
|
+
self:E("Can't find a shape with name "..shape_name)
|
|
79133
|
+
end
|
|
79134
|
+
return self
|
|
79135
|
+
end
|
|
79136
|
+
function SHAPE_BASE:GetAllShapes(filter)
|
|
79137
|
+
filter=filter or""
|
|
79138
|
+
local return_shapes={}
|
|
79139
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79140
|
+
for _,object in pairs(layer["objects"])do
|
|
79141
|
+
if string.contains(object["name"],filter)then
|
|
79142
|
+
table.add(return_shapes,object)
|
|
79143
|
+
end
|
|
79144
|
+
end
|
|
79145
|
+
end
|
|
79146
|
+
return return_shapes
|
|
79147
|
+
end
|
|
79148
|
+
function SHAPE_BASE:Offset(new_vec2)
|
|
79149
|
+
local offset_vec2=UTILS.Vec2Subtract(new_vec2,self.CenterVec2)
|
|
79150
|
+
self.CenterVec2=new_vec2
|
|
79151
|
+
if self.ClassName=="POLYGON"then
|
|
79152
|
+
for _,point in pairs(self.Points)do
|
|
79153
|
+
point.x=point.x+offset_vec2.x
|
|
79154
|
+
point.y=point.y+offset_vec2.y
|
|
79155
|
+
end
|
|
79156
|
+
end
|
|
79157
|
+
end
|
|
79158
|
+
function SHAPE_BASE:GetName()
|
|
79159
|
+
return self.Name
|
|
79160
|
+
end
|
|
79161
|
+
function SHAPE_BASE:GetColorString()
|
|
79162
|
+
return self.ColorString
|
|
79163
|
+
end
|
|
79164
|
+
function SHAPE_BASE:GetColorRGBA()
|
|
79165
|
+
return self.ColorRGBA
|
|
79166
|
+
end
|
|
79167
|
+
function SHAPE_BASE:GetColorRed()
|
|
79168
|
+
return self.ColorRGBA.R
|
|
79169
|
+
end
|
|
79170
|
+
function SHAPE_BASE:GetColorGreen()
|
|
79171
|
+
return self.ColorRGBA.G
|
|
79172
|
+
end
|
|
79173
|
+
function SHAPE_BASE:GetColorBlue()
|
|
79174
|
+
return self.ColorRGBA.B
|
|
79175
|
+
end
|
|
79176
|
+
function SHAPE_BASE:GetColorAlpha()
|
|
79177
|
+
return self.ColorRGBA.A
|
|
79178
|
+
end
|
|
79179
|
+
function SHAPE_BASE:GetCenterVec2()
|
|
79180
|
+
return self.CenterVec2
|
|
79181
|
+
end
|
|
79182
|
+
function SHAPE_BASE:GetCenterCoordinate()
|
|
79183
|
+
return COORDINATE:NewFromVec2(self.CenterVec2)
|
|
79184
|
+
end
|
|
79185
|
+
function SHAPE_BASE:GetCoordinate()
|
|
79186
|
+
return self:GetCenterCoordinate()
|
|
79187
|
+
end
|
|
79188
|
+
function SHAPE_BASE:ContainsPoint(_)
|
|
79189
|
+
self:E("This needs to be set in the derived class")
|
|
79190
|
+
end
|
|
79191
|
+
function SHAPE_BASE:ContainsUnit(unit_name)
|
|
79192
|
+
local unit=UNIT:FindByName(unit_name)
|
|
79193
|
+
if unit==nil or not unit:IsAlive()then
|
|
79194
|
+
return false
|
|
79195
|
+
end
|
|
79196
|
+
if self:ContainsPoint(unit:GetVec2())then
|
|
79197
|
+
return true
|
|
79198
|
+
end
|
|
79199
|
+
return false
|
|
79200
|
+
end
|
|
79201
|
+
function SHAPE_BASE:ContainsAnyOfGroup(group_name)
|
|
79202
|
+
local group=GROUP:FindByName(group_name)
|
|
79203
|
+
if group==nil or not group:IsAlive()then
|
|
79204
|
+
return false
|
|
79205
|
+
end
|
|
79206
|
+
for _,unit in pairs(group:GetUnits())do
|
|
79207
|
+
if self:ContainsPoint(unit:GetVec2())then
|
|
79208
|
+
return true
|
|
79209
|
+
end
|
|
79210
|
+
end
|
|
79211
|
+
return false
|
|
79212
|
+
end
|
|
79213
|
+
function SHAPE_BASE:ContainsAllOfGroup(group_name)
|
|
79214
|
+
local group=GROUP:FindByName(group_name)
|
|
79215
|
+
if group==nil or not group:IsAlive()then
|
|
79216
|
+
return false
|
|
79217
|
+
end
|
|
79218
|
+
for _,unit in pairs(group:GetUnits())do
|
|
79219
|
+
if not self:ContainsPoint(unit:GetVec2())then
|
|
79220
|
+
return false
|
|
79221
|
+
end
|
|
79222
|
+
end
|
|
79223
|
+
return true
|
|
79224
|
+
end
|
|
79225
|
+
CIRCLE={
|
|
79226
|
+
ClassName="CIRCLE",
|
|
79227
|
+
Radius=nil,
|
|
79228
|
+
}
|
|
79229
|
+
function CIRCLE:FindOnMap(shape_name)
|
|
79230
|
+
local self=BASE:Inherit(self,SHAPE_BASE:FindOnMap(shape_name))
|
|
79231
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79232
|
+
for _,object in pairs(layer["objects"])do
|
|
79233
|
+
if string.find(object["name"],shape_name,1,true)then
|
|
79234
|
+
if object["polygonMode"]=="circle"then
|
|
79235
|
+
self.Radius=object["radius"]
|
|
79236
|
+
end
|
|
79237
|
+
end
|
|
79238
|
+
end
|
|
79239
|
+
end
|
|
79240
|
+
return self
|
|
79241
|
+
end
|
|
79242
|
+
function CIRCLE:Find(shape_name)
|
|
79243
|
+
return _DATABASE:FindShape(shape_name)
|
|
79244
|
+
end
|
|
79245
|
+
function CIRCLE:New(vec2,radius)
|
|
79246
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
79247
|
+
self.CenterVec2=vec2
|
|
79248
|
+
self.Radius=radius
|
|
79249
|
+
return self
|
|
79250
|
+
end
|
|
79251
|
+
function CIRCLE:GetRadius()
|
|
79252
|
+
return self.Radius
|
|
79253
|
+
end
|
|
79254
|
+
function CIRCLE:ContainsPoint(point)
|
|
79255
|
+
if((point.x-self.CenterVec2.x)^2+(point.y-self.CenterVec2.y)^2)^0.5<=self.Radius then
|
|
79256
|
+
return true
|
|
79257
|
+
end
|
|
79258
|
+
return false
|
|
79259
|
+
end
|
|
79260
|
+
function CIRCLE:PointInSector(point,sector_start,sector_end,center,radius)
|
|
79261
|
+
center=center or self.CenterVec2
|
|
79262
|
+
radius=radius or self.Radius
|
|
79263
|
+
local function are_clockwise(v1,v2)
|
|
79264
|
+
return-v1.x*v2.y+v1.y*v2.x>0
|
|
79265
|
+
end
|
|
79266
|
+
local function is_in_radius(rp)
|
|
79267
|
+
return rp.x*rp.x+rp.y*rp.y<=radius^2
|
|
79268
|
+
end
|
|
79269
|
+
local rel_pt={
|
|
79270
|
+
x=point.x-center.x,
|
|
79271
|
+
y=point.y-center.y
|
|
79272
|
+
}
|
|
79273
|
+
local rel_sector_start={
|
|
79274
|
+
x=sector_start.x-center.x,
|
|
79275
|
+
y=sector_start.y-center.y,
|
|
79276
|
+
}
|
|
79277
|
+
local rel_sector_end={
|
|
79278
|
+
x=sector_end.x-center.x,
|
|
79279
|
+
y=sector_end.y-center.y,
|
|
79280
|
+
}
|
|
79281
|
+
return not are_clockwise(rel_sector_start,rel_pt)and
|
|
79282
|
+
are_clockwise(rel_sector_end,rel_pt)and
|
|
79283
|
+
is_in_radius(rel_pt,radius)
|
|
79284
|
+
end
|
|
79285
|
+
function CIRCLE:UnitInSector(unit_name,sector_start,sector_end,center,radius)
|
|
79286
|
+
center=center or self.CenterVec2
|
|
79287
|
+
radius=radius or self.Radius
|
|
79288
|
+
if self:PointInSector(UNIT:FindByName(unit_name):GetVec2(),sector_start,sector_end,center,radius)then
|
|
79289
|
+
return true
|
|
79290
|
+
end
|
|
79291
|
+
return false
|
|
79292
|
+
end
|
|
79293
|
+
function CIRCLE:AnyOfGroupInSector(group_name,sector_start,sector_end,center,radius)
|
|
79294
|
+
center=center or self.CenterVec2
|
|
79295
|
+
radius=radius or self.Radius
|
|
79296
|
+
for _,unit in pairs(GROUP:FindByName(group_name):GetUnits())do
|
|
79297
|
+
if self:PointInSector(unit:GetVec2(),sector_start,sector_end,center,radius)then
|
|
79298
|
+
return true
|
|
79299
|
+
end
|
|
79300
|
+
end
|
|
79301
|
+
return false
|
|
79302
|
+
end
|
|
79303
|
+
function CIRCLE:AllOfGroupInSector(group_name,sector_start,sector_end,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 not self:PointInSector(unit:GetVec2(),sector_start,sector_end,center,radius)then
|
|
79308
|
+
return false
|
|
79309
|
+
end
|
|
79310
|
+
end
|
|
79311
|
+
return true
|
|
79312
|
+
end
|
|
79313
|
+
function CIRCLE:UnitInRadius(unit_name,center,radius)
|
|
79314
|
+
center=center or self.CenterVec2
|
|
79315
|
+
radius=radius or self.Radius
|
|
79316
|
+
if UTILS.IsInRadius(center,UNIT:FindByName(unit_name):GetVec2(),radius)then
|
|
79317
|
+
return true
|
|
79318
|
+
end
|
|
79319
|
+
return false
|
|
79320
|
+
end
|
|
79321
|
+
function CIRCLE:AnyOfGroupInRadius(group_name,center,radius)
|
|
79322
|
+
center=center or self.CenterVec2
|
|
79323
|
+
radius=radius or self.Radius
|
|
79324
|
+
for _,unit in pairs(GROUP:FindByName(group_name):GetUnits())do
|
|
79325
|
+
if UTILS.IsInRadius(center,unit:GetVec2(),radius)then
|
|
79326
|
+
return true
|
|
79327
|
+
end
|
|
79328
|
+
end
|
|
79329
|
+
return false
|
|
79330
|
+
end
|
|
79331
|
+
function CIRCLE:AllOfGroupInRadius(group_name,center,radius)
|
|
79332
|
+
center=center or self.CenterVec2
|
|
79333
|
+
radius=radius or self.Radius
|
|
79334
|
+
for _,unit in pairs(GROUP:FindByName(group_name):GetUnits())do
|
|
79335
|
+
if not UTILS.IsInRadius(center,unit:GetVec2(),radius)then
|
|
79336
|
+
return false
|
|
79337
|
+
end
|
|
79338
|
+
end
|
|
79339
|
+
return true
|
|
79340
|
+
end
|
|
79341
|
+
function CIRCLE:GetRandomVec2()
|
|
79342
|
+
local angle=math.random()*2*math.pi
|
|
79343
|
+
local rx=math.random(0,self.Radius)*math.cos(angle)+self.CenterVec2.x
|
|
79344
|
+
local ry=math.random(0,self.Radius)*math.sin(angle)+self.CenterVec2.y
|
|
79345
|
+
return{x=rx,y=ry}
|
|
79346
|
+
end
|
|
79347
|
+
function CIRCLE:GetRandomVec2OnBorder()
|
|
79348
|
+
local angle=math.random()*2*math.pi
|
|
79349
|
+
local rx=self.Radius*math.cos(angle)+self.CenterVec2.x
|
|
79350
|
+
local ry=self.Radius*math.sin(angle)+self.CenterVec2.y
|
|
79351
|
+
return{x=rx,y=ry}
|
|
79352
|
+
end
|
|
79353
|
+
function CIRCLE:GetBoundingBox()
|
|
79354
|
+
local min_x=self.CenterVec2.x-self.Radius
|
|
79355
|
+
local min_y=self.CenterVec2.y-self.Radius
|
|
79356
|
+
local max_x=self.CenterVec2.x+self.Radius
|
|
79357
|
+
local max_y=self.CenterVec2.y+self.Radius
|
|
79358
|
+
return{
|
|
79359
|
+
{x=min_x,y=min_x},{x=max_x,y=min_y},{x=max_x,y=max_y},{x=min_x,y=max_y}
|
|
79360
|
+
}
|
|
79361
|
+
end
|
|
79362
|
+
CUBE={
|
|
79363
|
+
ClassName="CUBE",
|
|
79364
|
+
Points={},
|
|
79365
|
+
Coords={}
|
|
79366
|
+
}
|
|
79367
|
+
function CUBE:New(p1,p2,p3,p4,p5,p6,p7,p8)
|
|
79368
|
+
local self=BASE:Inherit(self,SHAPE_BASE)
|
|
79369
|
+
self.Points={p1,p2,p3,p4,p5,p6,p7,p8}
|
|
79370
|
+
for _,point in spairs(self.Points)do
|
|
79371
|
+
table.insert(self.Coords,COORDINATE:NewFromVec3(point))
|
|
79372
|
+
end
|
|
79373
|
+
return self
|
|
79374
|
+
end
|
|
79375
|
+
function CUBE:GetCenter()
|
|
79376
|
+
local center={x=0,y=0,z=0}
|
|
79377
|
+
for _,point in pairs(self.Points)do
|
|
79378
|
+
center.x=center.x+point.x
|
|
79379
|
+
center.y=center.y+point.y
|
|
79380
|
+
center.z=center.z+point.z
|
|
79381
|
+
end
|
|
79382
|
+
center.x=center.x/8
|
|
79383
|
+
center.y=center.y/8
|
|
79384
|
+
center.z=center.z/8
|
|
79385
|
+
return center
|
|
79386
|
+
end
|
|
79387
|
+
function CUBE:ContainsPoint(point,cube_points)
|
|
79388
|
+
cube_points=cube_points or self.Points
|
|
79389
|
+
local min_x,min_y,min_z=math.huge,math.huge,math.huge
|
|
79390
|
+
local max_x,max_y,max_z=-math.huge,-math.huge,-math.huge
|
|
79391
|
+
for _,p in ipairs(cube_points)do
|
|
79392
|
+
if p.x<min_x then min_x=p.x end
|
|
79393
|
+
if p.y<min_y then min_y=p.y end
|
|
79394
|
+
if p.z<min_z then min_z=p.z end
|
|
79395
|
+
if p.x>max_x then max_x=p.x end
|
|
79396
|
+
if p.y>max_y then max_y=p.y end
|
|
79397
|
+
if p.z>max_z then max_z=p.z end
|
|
79398
|
+
end
|
|
79399
|
+
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
|
|
79400
|
+
end
|
|
79401
|
+
LINE={
|
|
79402
|
+
ClassName="LINE",
|
|
79403
|
+
Points={},
|
|
79404
|
+
Coords={},
|
|
79405
|
+
}
|
|
79406
|
+
function LINE:FindOnMap(line_name)
|
|
79407
|
+
local self=BASE:Inherit(self,SHAPE_BASE:FindOnMap(line_name))
|
|
79408
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79409
|
+
for _,object in pairs(layer["objects"])do
|
|
79410
|
+
if object["name"]==line_name then
|
|
79411
|
+
if object["primitiveType"]=="Line"then
|
|
79412
|
+
for _,point in UTILS.spairs(object["points"])do
|
|
79413
|
+
local p={x=object["mapX"]+point["x"],
|
|
79414
|
+
y=object["mapY"]+point["y"]}
|
|
79415
|
+
local coord=COORDINATE:NewFromVec2(p)
|
|
79416
|
+
table.insert(self.Points,p)
|
|
79417
|
+
table.insert(self.Coords,coord)
|
|
79418
|
+
end
|
|
79419
|
+
end
|
|
79420
|
+
end
|
|
79421
|
+
end
|
|
79422
|
+
end
|
|
79423
|
+
self:I(#self.Points)
|
|
79424
|
+
if#self.Points==0 then
|
|
79425
|
+
return nil
|
|
79426
|
+
end
|
|
79427
|
+
self.MarkIDs={}
|
|
79428
|
+
return self
|
|
79429
|
+
end
|
|
79430
|
+
function LINE:Find(shape_name)
|
|
79431
|
+
return _DATABASE:FindShape(shape_name)
|
|
79432
|
+
end
|
|
79433
|
+
function LINE:New(...)
|
|
79434
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
79435
|
+
self.Points={...}
|
|
79436
|
+
self:I(self.Points)
|
|
79437
|
+
for _,point in UTILS.spairs(self.Points)do
|
|
79438
|
+
table.insert(self.Coords,COORDINATE:NewFromVec2(point))
|
|
79439
|
+
end
|
|
79440
|
+
return self
|
|
79441
|
+
end
|
|
79442
|
+
function LINE:NewFromCircle(center_point,radius,angle_degrees)
|
|
79443
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
79444
|
+
self.CenterVec2=center_point
|
|
79445
|
+
local angleRadians=math.rad(angle_degrees)
|
|
79446
|
+
local point1={
|
|
79447
|
+
x=center_point.x+radius*math.cos(angleRadians),
|
|
79448
|
+
y=center_point.y+radius*math.sin(angleRadians)
|
|
79449
|
+
}
|
|
79450
|
+
local point2={
|
|
79451
|
+
x=center_point.x+radius*math.cos(angleRadians+math.pi),
|
|
79452
|
+
y=center_point.y+radius*math.sin(angleRadians+math.pi)
|
|
79453
|
+
}
|
|
79454
|
+
for _,point in pairs{point1,point2}do
|
|
79455
|
+
table.insert(self.Points,point)
|
|
79456
|
+
table.insert(self.Coords,COORDINATE:NewFromVec2(point))
|
|
79457
|
+
end
|
|
79458
|
+
return self
|
|
79459
|
+
end
|
|
79460
|
+
function LINE:Coordinates()
|
|
79461
|
+
return self.Coords
|
|
79462
|
+
end
|
|
79463
|
+
function LINE:GetStartCoordinate()
|
|
79464
|
+
return self.Coords[1]
|
|
79465
|
+
end
|
|
79466
|
+
function LINE:GetEndCoordinate()
|
|
79467
|
+
return self.Coords[#self.Coords]
|
|
79468
|
+
end
|
|
79469
|
+
function LINE:GetStartPoint()
|
|
79470
|
+
return self.Points[1]
|
|
79471
|
+
end
|
|
79472
|
+
function LINE:GetEndPoint()
|
|
79473
|
+
return self.Points[#self.Points]
|
|
79474
|
+
end
|
|
79475
|
+
function LINE:GetLength()
|
|
79476
|
+
local total_length=0
|
|
79477
|
+
for i=1,#self.Points-1 do
|
|
79478
|
+
local x1,y1=self.Points[i]["x"],self.Points[i]["y"]
|
|
79479
|
+
local x2,y2=self.Points[i+1]["x"],self.Points[i+1]["y"]
|
|
79480
|
+
local segment_length=math.sqrt((x2-x1)^2+(y2-y1)^2)
|
|
79481
|
+
total_length=total_length+segment_length
|
|
79482
|
+
end
|
|
79483
|
+
return total_length
|
|
79484
|
+
end
|
|
79485
|
+
function LINE:GetRandomPoint(points)
|
|
79486
|
+
points=points or self.Points
|
|
79487
|
+
local rand=math.random()
|
|
79488
|
+
local random_x=points[1].x+rand*(points[2].x-points[1].x)
|
|
79489
|
+
local random_y=points[1].y+rand*(points[2].y-points[1].y)
|
|
79490
|
+
return{x=random_x,y=random_y}
|
|
79491
|
+
end
|
|
79492
|
+
function LINE:GetHeading(points)
|
|
79493
|
+
points=points or self.Points
|
|
79494
|
+
local angle=math.atan2(points[2].y-points[1].y,points[2].x-points[1].x)
|
|
79495
|
+
angle=math.deg(angle)
|
|
79496
|
+
if angle<0 then
|
|
79497
|
+
angle=angle+360
|
|
79498
|
+
end
|
|
79499
|
+
return angle
|
|
79500
|
+
end
|
|
79501
|
+
function LINE:GetIndividualParts()
|
|
79502
|
+
local parts={}
|
|
79503
|
+
if#self.Points==2 then
|
|
79504
|
+
parts={self}
|
|
79505
|
+
end
|
|
79506
|
+
for i=1,#self.Points-1 do
|
|
79507
|
+
local p1=self.Points[i]
|
|
79508
|
+
local p2=self.Points[i%#self.Points+1]
|
|
79509
|
+
table.add(parts,LINE:New(p1,p2))
|
|
79510
|
+
end
|
|
79511
|
+
return parts
|
|
79512
|
+
end
|
|
79513
|
+
function LINE:GetPointsInbetween(amount,start_point,end_point)
|
|
79514
|
+
start_point=start_point or self:GetStartPoint()
|
|
79515
|
+
end_point=end_point or self:GetEndPoint()
|
|
79516
|
+
if amount==0 then return{start_point,end_point}end
|
|
79517
|
+
amount=amount+1
|
|
79518
|
+
local points={}
|
|
79519
|
+
local difference={x=end_point.x-start_point.x,y=end_point.y-start_point.y}
|
|
79520
|
+
local divided={x=difference.x/amount,y=difference.y/amount}
|
|
79521
|
+
for j=0,amount do
|
|
79522
|
+
local part_pos={x=divided.x*j,y=divided.y*j}
|
|
79523
|
+
local point={x=start_point.x+part_pos.x,y=start_point.y+part_pos.y}
|
|
79524
|
+
table.insert(points,point)
|
|
79525
|
+
end
|
|
79526
|
+
return points
|
|
79527
|
+
end
|
|
79528
|
+
function LINE:GetCoordinatesInBetween(amount,start_point,end_point)
|
|
79529
|
+
local coords={}
|
|
79530
|
+
for _,pt in pairs(self:GetPointsInbetween(amount,start_point,end_point))do
|
|
79531
|
+
table.add(coords,COORDINATE:NewFromVec2(pt))
|
|
79532
|
+
end
|
|
79533
|
+
return coords
|
|
79534
|
+
end
|
|
79535
|
+
function LINE:GetRandomPoint(start_point,end_point)
|
|
79536
|
+
start_point=start_point or self:GetStartPoint()
|
|
79537
|
+
end_point=end_point or self:GetEndPoint()
|
|
79538
|
+
local fraction=math.random()
|
|
79539
|
+
local difference={x=end_point.x-start_point.x,y=end_point.y-start_point.y}
|
|
79540
|
+
local part_pos={x=difference.x*fraction,y=difference.y*fraction}
|
|
79541
|
+
local random_point={x=start_point.x+part_pos.x,y=start_point.y+part_pos.y}
|
|
79542
|
+
return random_point
|
|
79543
|
+
end
|
|
79544
|
+
function LINE:GetRandomCoordinate(start_point,end_point)
|
|
79545
|
+
start_point=start_point or self:GetStartPoint()
|
|
79546
|
+
end_point=end_point or self:GetEndPoint()
|
|
79547
|
+
return COORDINATE:NewFromVec2(self:GetRandomPoint(start_point,end_point))
|
|
79548
|
+
end
|
|
79549
|
+
function LINE:GetPointsBetweenAsSineWave(amount,start_point,end_point,frequency,phase,amplitude)
|
|
79550
|
+
amount=amount or 20
|
|
79551
|
+
start_point=start_point or self:GetStartPoint()
|
|
79552
|
+
end_point=end_point or self:GetEndPoint()
|
|
79553
|
+
frequency=frequency or 1
|
|
79554
|
+
phase=phase or 0
|
|
79555
|
+
amplitude=amplitude or 100
|
|
79556
|
+
local points={}
|
|
79557
|
+
local function sine_wave(x)
|
|
79558
|
+
return amplitude*math.sin(2*math.pi*frequency*(x-start_point.x)+phase)
|
|
79559
|
+
end
|
|
79560
|
+
local x=start_point.x
|
|
79561
|
+
local step=(end_point.x-start_point.x)/20
|
|
79562
|
+
for _=1,amount do
|
|
79563
|
+
local y=sine_wave(x)
|
|
79564
|
+
x=x+step
|
|
79565
|
+
table.add(points,{x=x,y=y})
|
|
79566
|
+
end
|
|
79567
|
+
return points
|
|
79568
|
+
end
|
|
79569
|
+
function LINE:GetBoundingBox()
|
|
79570
|
+
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
|
|
79571
|
+
for i=2,#self.Points do
|
|
79572
|
+
local x,y=self.Points[i].x,self.Points[i].y
|
|
79573
|
+
if x<min_x then
|
|
79574
|
+
min_x=x
|
|
79575
|
+
end
|
|
79576
|
+
if y<min_y then
|
|
79577
|
+
min_y=y
|
|
79578
|
+
end
|
|
79579
|
+
if x>max_x then
|
|
79580
|
+
max_x=x
|
|
79581
|
+
end
|
|
79582
|
+
if y>max_y then
|
|
79583
|
+
max_y=y
|
|
79584
|
+
end
|
|
79585
|
+
end
|
|
79586
|
+
return{
|
|
79587
|
+
{x=min_x,y=min_x},{x=max_x,y=min_y},{x=max_x,y=max_y},{x=min_x,y=max_y}
|
|
79588
|
+
}
|
|
79589
|
+
end
|
|
79590
|
+
function LINE:Draw()
|
|
79591
|
+
for i=1,#self.Coords-1 do
|
|
79592
|
+
local c1=self.Coords[i]
|
|
79593
|
+
local c2=self.Coords[i%#self.Coords+1]
|
|
79594
|
+
table.add(self.MarkIDs,c1:LineToAll(c2))
|
|
79595
|
+
end
|
|
79596
|
+
end
|
|
79597
|
+
function LINE:RemoveDraw()
|
|
79598
|
+
for _,mark_id in pairs(self.MarkIDs)do
|
|
79599
|
+
UTILS.RemoveMark(mark_id)
|
|
79600
|
+
end
|
|
79601
|
+
end
|
|
79602
|
+
OVAL={
|
|
79603
|
+
ClassName="OVAL",
|
|
79604
|
+
MajorAxis=nil,
|
|
79605
|
+
MinorAxis=nil,
|
|
79606
|
+
Angle=0,
|
|
79607
|
+
DrawPoly=nil
|
|
79608
|
+
}
|
|
79609
|
+
function OVAL:FindOnMap(shape_name)
|
|
79610
|
+
local self=BASE:Inherit(self,SHAPE_BASE:FindOnMap(shape_name))
|
|
79611
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79612
|
+
for _,object in pairs(layer["objects"])do
|
|
79613
|
+
if string.find(object["name"],shape_name,1,true)then
|
|
79614
|
+
if object["polygonMode"]=="oval"then
|
|
79615
|
+
self.CenterVec2={x=object["mapX"],y=object["mapY"]}
|
|
79616
|
+
self.MajorAxis=object["r1"]
|
|
79617
|
+
self.MinorAxis=object["r2"]
|
|
79618
|
+
self.Angle=object["angle"]
|
|
79619
|
+
end
|
|
79620
|
+
end
|
|
79621
|
+
end
|
|
79622
|
+
end
|
|
79623
|
+
return self
|
|
79624
|
+
end
|
|
79625
|
+
function OVAL:Find(shape_name)
|
|
79626
|
+
return _DATABASE:FindShape(shape_name)
|
|
79627
|
+
end
|
|
79628
|
+
function OVAL:New(vec2,major_axis,minor_axis,angle)
|
|
79629
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
79630
|
+
self.CenterVec2=vec2
|
|
79631
|
+
self.MajorAxis=major_axis
|
|
79632
|
+
self.MinorAxis=minor_axis
|
|
79633
|
+
self.Angle=angle or 0
|
|
79634
|
+
return self
|
|
79635
|
+
end
|
|
79636
|
+
function OVAL:GetMajorAxis()
|
|
79637
|
+
return self.MajorAxis
|
|
79638
|
+
end
|
|
79639
|
+
function OVAL:GetMinorAxis()
|
|
79640
|
+
return self.MinorAxis
|
|
79641
|
+
end
|
|
79642
|
+
function OVAL:GetAngle()
|
|
79643
|
+
return self.Angle
|
|
79644
|
+
end
|
|
79645
|
+
function OVAL:SetMajorAxis(value)
|
|
79646
|
+
self.MajorAxis=value
|
|
79647
|
+
end
|
|
79648
|
+
function OVAL:SetMinorAxis(value)
|
|
79649
|
+
self.MinorAxis=value
|
|
79650
|
+
end
|
|
79651
|
+
function OVAL:SetAngle(value)
|
|
79652
|
+
self.Angle=value
|
|
79653
|
+
end
|
|
79654
|
+
function OVAL:ContainsPoint(point)
|
|
79655
|
+
local cos,sin=math.cos,math.sin
|
|
79656
|
+
local dx=point.x-self.CenterVec2.x
|
|
79657
|
+
local dy=point.y-self.CenterVec2.y
|
|
79658
|
+
local rx=dx*cos(self.Angle)+dy*sin(self.Angle)
|
|
79659
|
+
local ry=-dx*sin(self.Angle)+dy*cos(self.Angle)
|
|
79660
|
+
return rx*rx/(self.MajorAxis*self.MajorAxis)+ry*ry/(self.MinorAxis*self.MinorAxis)<=1
|
|
79661
|
+
end
|
|
79662
|
+
function OVAL:GetRandomVec2()
|
|
79663
|
+
local theta=math.rad(self.Angle)
|
|
79664
|
+
local random_point=math.sqrt(math.random())
|
|
79665
|
+
local phi=math.random()*2*math.pi
|
|
79666
|
+
local x_c=random_point*math.cos(phi)
|
|
79667
|
+
local y_c=random_point*math.sin(phi)
|
|
79668
|
+
local x_e=x_c*self.MajorAxis
|
|
79669
|
+
local y_e=y_c*self.MinorAxis
|
|
79670
|
+
local rx=(x_e*math.cos(theta)-y_e*math.sin(theta))+self.CenterVec2.x
|
|
79671
|
+
local ry=(x_e*math.sin(theta)+y_e*math.cos(theta))+self.CenterVec2.y
|
|
79672
|
+
return{x=rx,y=ry}
|
|
79673
|
+
end
|
|
79674
|
+
function OVAL:GetBoundingBox()
|
|
79675
|
+
local min_x=self.CenterVec2.x-self.MajorAxis
|
|
79676
|
+
local min_y=self.CenterVec2.y-self.MinorAxis
|
|
79677
|
+
local max_x=self.CenterVec2.x+self.MajorAxis
|
|
79678
|
+
local max_y=self.CenterVec2.y+self.MinorAxis
|
|
79679
|
+
return{
|
|
79680
|
+
{x=min_x,y=min_x},{x=max_x,y=min_y},{x=max_x,y=max_y},{x=min_x,y=max_y}
|
|
79681
|
+
}
|
|
79682
|
+
end
|
|
79683
|
+
function OVAL:Draw()
|
|
79684
|
+
self.DrawPoly=POLYGON:NewFromPoints(self:PointsOnEdge(20))
|
|
79685
|
+
self.DrawPoly:Draw(true)
|
|
79686
|
+
end
|
|
79687
|
+
function OVAL:RemoveDraw()
|
|
79688
|
+
self.DrawPoly:RemoveDraw()
|
|
79689
|
+
end
|
|
79690
|
+
function OVAL:PointsOnEdge(num_points)
|
|
79691
|
+
num_points=num_points or 20
|
|
79692
|
+
local points={}
|
|
79693
|
+
local dtheta=2*math.pi/num_points
|
|
79694
|
+
for i=0,num_points-1 do
|
|
79695
|
+
local theta=i*dtheta
|
|
79696
|
+
local x=self.CenterVec2.x+self.MajorAxis*math.cos(theta)*math.cos(self.Angle)-self.MinorAxis*math.sin(theta)*math.sin(self.Angle)
|
|
79697
|
+
local y=self.CenterVec2.y+self.MajorAxis*math.cos(theta)*math.sin(self.Angle)+self.MinorAxis*math.sin(theta)*math.cos(self.Angle)
|
|
79698
|
+
table.insert(points,{x=x,y=y})
|
|
79699
|
+
end
|
|
79700
|
+
return points
|
|
79701
|
+
end
|
|
79702
|
+
POLYGON={
|
|
79703
|
+
ClassName="POLYGON",
|
|
79704
|
+
Points={},
|
|
79705
|
+
Coords={},
|
|
79706
|
+
Triangles={},
|
|
79707
|
+
SurfaceArea=0,
|
|
79708
|
+
TriangleMarkIDs={},
|
|
79709
|
+
OutlineMarkIDs={},
|
|
79710
|
+
Angle=nil,
|
|
79711
|
+
Heading=nil
|
|
79712
|
+
}
|
|
79713
|
+
function POLYGON:FindOnMap(shape_name)
|
|
79714
|
+
local self=BASE:Inherit(self,SHAPE_BASE:FindOnMap(shape_name))
|
|
79715
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
79716
|
+
for _,object in pairs(layer["objects"])do
|
|
79717
|
+
if object["name"]==shape_name then
|
|
79718
|
+
if(object["primitiveType"]=="Line"and object["closed"]==true)or(object["polygonMode"]=="free")then
|
|
79719
|
+
for _,point in UTILS.spairs(object["points"])do
|
|
79720
|
+
local p={x=object["mapX"]+point["x"],
|
|
79721
|
+
y=object["mapY"]+point["y"]}
|
|
79722
|
+
local coord=COORDINATE:NewFromVec2(p)
|
|
79723
|
+
self.Points[#self.Points+1]=p
|
|
79724
|
+
self.Coords[#self.Coords+1]=coord
|
|
79725
|
+
end
|
|
79726
|
+
elseif object["polygonMode"]=="rect"then
|
|
79727
|
+
local angle=object["angle"]
|
|
79728
|
+
local half_width=object["width"]/2
|
|
79729
|
+
local half_height=object["height"]/2
|
|
79730
|
+
local p1=UTILS.RotatePointAroundPivot({x=self.CenterVec2.x-half_height,y=self.CenterVec2.y+half_width},self.CenterVec2,angle)
|
|
79731
|
+
local p2=UTILS.RotatePointAroundPivot({x=self.CenterVec2.x+half_height,y=self.CenterVec2.y+half_width},self.CenterVec2,angle)
|
|
79732
|
+
local p3=UTILS.RotatePointAroundPivot({x=self.CenterVec2.x+half_height,y=self.CenterVec2.y-half_width},self.CenterVec2,angle)
|
|
79733
|
+
local p4=UTILS.RotatePointAroundPivot({x=self.CenterVec2.x-half_height,y=self.CenterVec2.y-half_width},self.CenterVec2,angle)
|
|
79734
|
+
self.Points={p1,p2,p3,p4}
|
|
79735
|
+
for _,point in pairs(self.Points)do
|
|
79736
|
+
self.Coords[#self.Coords+1]=COORDINATE:NewFromVec2(point)
|
|
79737
|
+
end
|
|
79738
|
+
elseif object["polygonMode"]=="arrow"then
|
|
79739
|
+
for _,point in UTILS.spairs(object["points"])do
|
|
79740
|
+
local p={x=object["mapX"]+point["x"],
|
|
79741
|
+
y=object["mapY"]+point["y"]}
|
|
79742
|
+
local coord=COORDINATE:NewFromVec2(p)
|
|
79743
|
+
self.Points[#self.Points+1]=p
|
|
79744
|
+
self.Coords[#self.Coords+1]=coord
|
|
79745
|
+
end
|
|
79746
|
+
self.Angle=object["angle"]
|
|
79747
|
+
self.Heading=UTILS.ClampAngle(self.Angle+90)
|
|
79748
|
+
end
|
|
79749
|
+
end
|
|
79750
|
+
end
|
|
79751
|
+
end
|
|
79752
|
+
if#self.Points==0 then
|
|
79753
|
+
return nil
|
|
79754
|
+
end
|
|
79755
|
+
self.CenterVec2=self:GetCentroid()
|
|
79756
|
+
self.Triangles=self:Triangulate()
|
|
79757
|
+
self.SurfaceArea=self:__CalculateSurfaceArea()
|
|
79758
|
+
self.TriangleMarkIDs={}
|
|
79759
|
+
self.OutlineMarkIDs={}
|
|
79760
|
+
return self
|
|
79761
|
+
end
|
|
79762
|
+
function POLYGON:FromZone(zone_name)
|
|
79763
|
+
for _,zone in pairs(env.mission.triggers.zones)do
|
|
79764
|
+
if zone["name"]==zone_name then
|
|
79765
|
+
return POLYGON:New(unpack(zone["verticies"]or{}))
|
|
79766
|
+
end
|
|
79767
|
+
end
|
|
79768
|
+
end
|
|
79769
|
+
function POLYGON:Find(shape_name)
|
|
79770
|
+
return _DATABASE:FindShape(shape_name)
|
|
79771
|
+
end
|
|
79772
|
+
function POLYGON:New(...)
|
|
79773
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
79774
|
+
self.Points={...}
|
|
79775
|
+
self.Coords={}
|
|
79776
|
+
for _,point in UTILS.spairs(self.Points)do
|
|
79777
|
+
table.insert(self.Coords,COORDINATE:NewFromVec2(point))
|
|
79778
|
+
end
|
|
79779
|
+
self.Triangles=self:Triangulate()
|
|
79780
|
+
self.SurfaceArea=self:__CalculateSurfaceArea()
|
|
79781
|
+
return self
|
|
79782
|
+
end
|
|
79783
|
+
function POLYGON:GetCentroid()
|
|
79784
|
+
local function sum(t)
|
|
79785
|
+
local total=0
|
|
79786
|
+
for _,value in pairs(t)do
|
|
79787
|
+
total=total+value
|
|
79788
|
+
end
|
|
79789
|
+
return total
|
|
79790
|
+
end
|
|
79791
|
+
local x_values={}
|
|
79792
|
+
local y_values={}
|
|
79793
|
+
local length=table.length(self.Points)
|
|
79794
|
+
for _,point in pairs(self.Points)do
|
|
79795
|
+
table.insert(x_values,point.x)
|
|
79796
|
+
table.insert(y_values,point.y)
|
|
79797
|
+
end
|
|
79798
|
+
local x=sum(x_values)/length
|
|
79799
|
+
local y=sum(y_values)/length
|
|
79800
|
+
return{
|
|
79801
|
+
["x"]=x,
|
|
79802
|
+
["y"]=y
|
|
79803
|
+
}
|
|
79804
|
+
end
|
|
79805
|
+
function POLYGON:GetCoordinates()
|
|
79806
|
+
return self.Coords
|
|
79807
|
+
end
|
|
79808
|
+
function POLYGON:GetStartCoordinate()
|
|
79809
|
+
return self.Coords[1]
|
|
79810
|
+
end
|
|
79811
|
+
function POLYGON:GetEndCoordinate()
|
|
79812
|
+
return self.Coords[#self.Coords]
|
|
79813
|
+
end
|
|
79814
|
+
function POLYGON:GetStartPoint()
|
|
79815
|
+
return self.Points[1]
|
|
79816
|
+
end
|
|
79817
|
+
function POLYGON:GetEndPoint()
|
|
79818
|
+
return self.Points[#self.Points]
|
|
79819
|
+
end
|
|
79820
|
+
function POLYGON:GetPoints()
|
|
79821
|
+
return self.Points
|
|
79822
|
+
end
|
|
79823
|
+
function POLYGON:GetSurfaceArea()
|
|
79824
|
+
return self.SurfaceArea
|
|
79825
|
+
end
|
|
79826
|
+
function POLYGON:GetBoundingBox()
|
|
79827
|
+
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
|
|
79828
|
+
for i=2,#self.Points do
|
|
79829
|
+
local x,y=self.Points[i].x,self.Points[i].y
|
|
79830
|
+
if x<min_x then
|
|
79831
|
+
min_x=x
|
|
79832
|
+
end
|
|
79833
|
+
if y<min_y then
|
|
79834
|
+
min_y=y
|
|
79835
|
+
end
|
|
79836
|
+
if x>max_x then
|
|
79837
|
+
max_x=x
|
|
79838
|
+
end
|
|
79839
|
+
if y>max_y then
|
|
79840
|
+
max_y=y
|
|
79841
|
+
end
|
|
79842
|
+
end
|
|
79843
|
+
return{
|
|
79844
|
+
{x=min_x,y=min_x},{x=max_x,y=min_y},{x=max_x,y=max_y},{x=min_x,y=max_y}
|
|
79845
|
+
}
|
|
79846
|
+
end
|
|
79847
|
+
function POLYGON:Triangulate(points)
|
|
79848
|
+
points=points or self.Points
|
|
79849
|
+
local triangles={}
|
|
79850
|
+
local function get_orientation(shape_points)
|
|
79851
|
+
local sum=0
|
|
79852
|
+
for i=1,#shape_points do
|
|
79853
|
+
local j=i%#shape_points+1
|
|
79854
|
+
sum=sum+(shape_points[j].x-shape_points[i].x)*(shape_points[j].y+shape_points[i].y)
|
|
79855
|
+
end
|
|
79856
|
+
return sum>=0 and"clockwise"or"counter-clockwise"
|
|
79857
|
+
end
|
|
79858
|
+
local function ensure_clockwise(shape_points)
|
|
79859
|
+
local orientation=get_orientation(shape_points)
|
|
79860
|
+
if orientation=="counter-clockwise"then
|
|
79861
|
+
local reversed={}
|
|
79862
|
+
for i=#shape_points,1,-1 do
|
|
79863
|
+
table.insert(reversed,shape_points[i])
|
|
79864
|
+
end
|
|
79865
|
+
return reversed
|
|
79866
|
+
end
|
|
79867
|
+
return shape_points
|
|
79868
|
+
end
|
|
79869
|
+
local function is_clockwise(p1,p2,p3)
|
|
79870
|
+
local cross_product=(p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x)
|
|
79871
|
+
return cross_product<0
|
|
79872
|
+
end
|
|
79873
|
+
local function divide_recursively(shape_points)
|
|
79874
|
+
if#shape_points==3 then
|
|
79875
|
+
table.insert(triangles,TRIANGLE:New(shape_points[1],shape_points[2],shape_points[3]))
|
|
79876
|
+
elseif#shape_points>3 then
|
|
79877
|
+
for i,p1 in ipairs(shape_points)do
|
|
79878
|
+
local p2=shape_points[(i%#shape_points)+1]
|
|
79879
|
+
local p3=shape_points[(i+1)%#shape_points+1]
|
|
79880
|
+
local triangle=TRIANGLE:New(p1,p2,p3)
|
|
79881
|
+
local is_ear=true
|
|
79882
|
+
if not is_clockwise(p1,p2,p3)then
|
|
79883
|
+
is_ear=false
|
|
79884
|
+
else
|
|
79885
|
+
for _,point in ipairs(shape_points)do
|
|
79886
|
+
if point~=p1 and point~=p2 and point~=p3 and triangle:ContainsPoint(point)then
|
|
79887
|
+
is_ear=false
|
|
79888
|
+
break
|
|
79889
|
+
end
|
|
79890
|
+
end
|
|
79891
|
+
end
|
|
79892
|
+
if is_ear then
|
|
79893
|
+
local is_valid_triangle=true
|
|
79894
|
+
for _,point in ipairs(points)do
|
|
79895
|
+
if point~=p1 and point~=p2 and point~=p3 and triangle:ContainsPoint(point)then
|
|
79896
|
+
is_valid_triangle=false
|
|
79897
|
+
break
|
|
79898
|
+
end
|
|
79899
|
+
end
|
|
79900
|
+
if is_valid_triangle then
|
|
79901
|
+
table.insert(triangles,triangle)
|
|
79902
|
+
local remaining_points={}
|
|
79903
|
+
for j,point in ipairs(shape_points)do
|
|
79904
|
+
if point~=p2 then
|
|
79905
|
+
table.insert(remaining_points,point)
|
|
79906
|
+
end
|
|
79907
|
+
end
|
|
79908
|
+
divide_recursively(remaining_points)
|
|
79909
|
+
break
|
|
79910
|
+
end
|
|
79911
|
+
end
|
|
79912
|
+
end
|
|
79913
|
+
end
|
|
79914
|
+
end
|
|
79915
|
+
points=ensure_clockwise(points)
|
|
79916
|
+
divide_recursively(points)
|
|
79917
|
+
return triangles
|
|
79918
|
+
end
|
|
79919
|
+
function POLYGON:CovarianceMatrix()
|
|
79920
|
+
local cx,cy=self:GetCentroid()
|
|
79921
|
+
local covXX,covYY,covXY=0,0,0
|
|
79922
|
+
for _,p in ipairs(self.points)do
|
|
79923
|
+
covXX=covXX+(p.x-cx)^2
|
|
79924
|
+
covYY=covYY+(p.y-cy)^2
|
|
79925
|
+
covXY=covXY+(p.x-cx)*(p.y-cy)
|
|
79926
|
+
end
|
|
79927
|
+
covXX=covXX/(#self.points-1)
|
|
79928
|
+
covYY=covYY/(#self.points-1)
|
|
79929
|
+
covXY=covXY/(#self.points-1)
|
|
79930
|
+
return covXX,covYY,covXY
|
|
79931
|
+
end
|
|
79932
|
+
function POLYGON:Direction()
|
|
79933
|
+
local covXX,covYY,covXY=self:CovarianceMatrix()
|
|
79934
|
+
local theta=0.5*math.atan2(2*covXY,covXX-covYY)
|
|
79935
|
+
return math.cos(theta),math.sin(theta)
|
|
79936
|
+
end
|
|
79937
|
+
function POLYGON:GetRandomVec2()
|
|
79938
|
+
local weights={}
|
|
79939
|
+
for _,triangle in pairs(self.Triangles)do
|
|
79940
|
+
weights[triangle]=triangle.SurfaceArea/self.SurfaceArea
|
|
79941
|
+
end
|
|
79942
|
+
local random_weight=math.random()
|
|
79943
|
+
local accumulated_weight=0
|
|
79944
|
+
for triangle,weight in pairs(weights)do
|
|
79945
|
+
accumulated_weight=accumulated_weight+weight
|
|
79946
|
+
if accumulated_weight>=random_weight then
|
|
79947
|
+
return triangle:GetRandomVec2()
|
|
79948
|
+
end
|
|
79949
|
+
end
|
|
79950
|
+
end
|
|
79951
|
+
function POLYGON:GetRandomNonWeightedVec2()
|
|
79952
|
+
return self.Triangles[math.random(1,#self.Triangles)]:GetRandomVec2()
|
|
79953
|
+
end
|
|
79954
|
+
function POLYGON:ContainsPoint(point,polygon_points)
|
|
79955
|
+
local x=point.x
|
|
79956
|
+
local y=point.y
|
|
79957
|
+
polygon_points=polygon_points or self.Points
|
|
79958
|
+
local counter=0
|
|
79959
|
+
local num_points=#polygon_points
|
|
79960
|
+
for current_index=1,num_points do
|
|
79961
|
+
local next_index=(current_index%num_points)+1
|
|
79962
|
+
local current_x,current_y=polygon_points[current_index].x,polygon_points[current_index].y
|
|
79963
|
+
local next_x,next_y=polygon_points[next_index].x,polygon_points[next_index].y
|
|
79964
|
+
if((current_y>y)~=(next_y>y))and(x<(next_x-current_x)*(y-current_y)/(next_y-current_y)+current_x)then
|
|
79965
|
+
counter=counter+1
|
|
79966
|
+
end
|
|
79967
|
+
end
|
|
79968
|
+
return counter%2==1
|
|
79969
|
+
end
|
|
79970
|
+
function POLYGON:Draw(include_inner_triangles)
|
|
79971
|
+
include_inner_triangles=include_inner_triangles or false
|
|
79972
|
+
for i=1,#self.Coords do
|
|
79973
|
+
local c1=self.Coords[i]
|
|
79974
|
+
local c2=self.Coords[i%#self.Coords+1]
|
|
79975
|
+
table.add(self.OutlineMarkIDs,c1:LineToAll(c2))
|
|
79976
|
+
end
|
|
79977
|
+
if include_inner_triangles then
|
|
79978
|
+
for _,triangle in ipairs(self.Triangles)do
|
|
79979
|
+
triangle:Draw()
|
|
79980
|
+
end
|
|
79981
|
+
end
|
|
79982
|
+
end
|
|
79983
|
+
function POLYGON:RemoveDraw()
|
|
79984
|
+
for _,triangle in pairs(self.Triangles)do
|
|
79985
|
+
triangle:RemoveDraw()
|
|
79986
|
+
end
|
|
79987
|
+
for _,mark_id in pairs(self.OutlineMarkIDs)do
|
|
79988
|
+
UTILS.RemoveMark(mark_id)
|
|
79989
|
+
end
|
|
79990
|
+
end
|
|
79991
|
+
function POLYGON:__CalculateSurfaceArea()
|
|
79992
|
+
local area=0
|
|
79993
|
+
for _,triangle in pairs(self.Triangles)do
|
|
79994
|
+
area=area+triangle.SurfaceArea
|
|
79995
|
+
end
|
|
79996
|
+
return area
|
|
79997
|
+
end
|
|
79998
|
+
TRIANGLE={
|
|
79999
|
+
ClassName="TRIANGLE",
|
|
80000
|
+
Points={},
|
|
80001
|
+
Coords={},
|
|
80002
|
+
SurfaceArea=0
|
|
80003
|
+
}
|
|
80004
|
+
function TRIANGLE:New(p1,p2,p3)
|
|
80005
|
+
local self=BASE:Inherit(self,SHAPE_BASE:New())
|
|
80006
|
+
self.Points={p1,p2,p3}
|
|
80007
|
+
local center_x=(p1.x+p2.x+p3.x)/3
|
|
80008
|
+
local center_y=(p1.y+p2.y+p3.y)/3
|
|
80009
|
+
self.CenterVec2={x=center_x,y=center_y}
|
|
80010
|
+
for _,pt in pairs({p1,p2,p3})do
|
|
80011
|
+
table.add(self.Coords,COORDINATE:NewFromVec2(pt))
|
|
80012
|
+
end
|
|
80013
|
+
self.SurfaceArea=math.abs((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))*0.5
|
|
80014
|
+
self.MarkIDs={}
|
|
80015
|
+
return self
|
|
80016
|
+
end
|
|
80017
|
+
function TRIANGLE:ContainsPoint(pt,points)
|
|
80018
|
+
points=points or self.Points
|
|
80019
|
+
local function sign(p1,p2,p3)
|
|
80020
|
+
return(p1.x-p3.x)*(p2.y-p3.y)-(p2.x-p3.x)*(p1.y-p3.y)
|
|
80021
|
+
end
|
|
80022
|
+
local d1=sign(pt,self.Points[1],self.Points[2])
|
|
80023
|
+
local d2=sign(pt,self.Points[2],self.Points[3])
|
|
80024
|
+
local d3=sign(pt,self.Points[3],self.Points[1])
|
|
80025
|
+
local has_neg=(d1<0)or(d2<0)or(d3<0)
|
|
80026
|
+
local has_pos=(d1>0)or(d2>0)or(d3>0)
|
|
80027
|
+
return not(has_neg and has_pos)
|
|
80028
|
+
end
|
|
80029
|
+
function TRIANGLE:GetRandomVec2(points)
|
|
80030
|
+
points=points or self.Points
|
|
80031
|
+
local pt={math.random(),math.random()}
|
|
80032
|
+
table.sort(pt)
|
|
80033
|
+
local s=pt[1]
|
|
80034
|
+
local t=pt[2]-pt[1]
|
|
80035
|
+
local u=1-pt[2]
|
|
80036
|
+
return{x=s*points[1].x+t*points[2].x+u*points[3].x,
|
|
80037
|
+
y=s*points[1].y+t*points[2].y+u*points[3].y}
|
|
80038
|
+
end
|
|
80039
|
+
function TRIANGLE:Draw()
|
|
80040
|
+
for i=1,#self.Coords do
|
|
80041
|
+
local c1=self.Coords[i]
|
|
80042
|
+
local c2=self.Coords[i%#self.Coords+1]
|
|
80043
|
+
table.add(self.MarkIDs,c1:LineToAll(c2))
|
|
80044
|
+
end
|
|
80045
|
+
end
|
|
80046
|
+
function TRIANGLE:RemoveDraw()
|
|
80047
|
+
for _,mark_id in pairs(self.MarkIDs)do
|
|
80048
|
+
UTILS.RemoveMark(mark_id)
|
|
80049
|
+
end
|
|
80050
|
+
end
|
|
78530
80051
|
do
|
|
78531
80052
|
USERSOUND={
|
|
78532
80053
|
ClassName="USERSOUND",
|
|
@@ -79788,7 +81309,7 @@ end
|
|
|
79788
81309
|
function MSRS:SetVoiceProvider(Voice,Provider)
|
|
79789
81310
|
self:F({Voice=Voice,Provider=Provider})
|
|
79790
81311
|
self.poptions=self.poptions or{}
|
|
79791
|
-
self.poptions[Provider or self:GetProvider()]=Voice
|
|
81312
|
+
self.poptions[Provider or self:GetProvider()].voice=Voice
|
|
79792
81313
|
return self
|
|
79793
81314
|
end
|
|
79794
81315
|
function MSRS:SetVoiceWindows(Voice)
|
|
@@ -82636,7 +84157,7 @@ local ActRouteTarget=ProcessUnit:GetProcess("Engaging","RouteToTargetZone")
|
|
|
82636
84157
|
return ActRouteTarget:GetZone()
|
|
82637
84158
|
end
|
|
82638
84159
|
function TASK_A2G:SetGoalTotal()
|
|
82639
|
-
self.GoalTotal=self.TargetSetUnit:
|
|
84160
|
+
self.GoalTotal=self.TargetSetUnit:CountAlive()
|
|
82640
84161
|
end
|
|
82641
84162
|
function TASK_A2G:GetGoalTotal()
|
|
82642
84163
|
return self.GoalTotal
|
|
@@ -82649,7 +84170,7 @@ return Distance
|
|
|
82649
84170
|
end
|
|
82650
84171
|
function TASK_A2G:onafterGoal(TaskUnit,From,Event,To)
|
|
82651
84172
|
local TargetSetUnit=self.TargetSetUnit
|
|
82652
|
-
if TargetSetUnit:
|
|
84173
|
+
if TargetSetUnit:CountAlive()==0 then
|
|
82653
84174
|
self:Success()
|
|
82654
84175
|
end
|
|
82655
84176
|
self:__Goal(-10)
|
|
@@ -82667,7 +84188,7 @@ ThreatLevel,ThreatText=self.TargetSetUnit:CalculateThreatLevelA2G()
|
|
|
82667
84188
|
end
|
|
82668
84189
|
self.TaskInfo:AddThreat(ThreatText,ThreatLevel,10,"MOD",true)
|
|
82669
84190
|
if self.Detection then
|
|
82670
|
-
local DetectedItemsCount=self.TargetSetUnit:
|
|
84191
|
+
local DetectedItemsCount=self.TargetSetUnit:CountAlive()
|
|
82671
84192
|
local ReportTypes=REPORT:New()
|
|
82672
84193
|
local TargetTypes={}
|
|
82673
84194
|
for TargetUnitName,TargetUnit in pairs(self.TargetSetUnit:GetSet())do
|
|
@@ -82680,7 +84201,7 @@ end
|
|
|
82680
84201
|
self.TaskInfo:AddTargetCount(DetectedItemsCount,11,"O",true)
|
|
82681
84202
|
self.TaskInfo:AddTargets(DetectedItemsCount,ReportTypes:Text(", "),20,"D",true)
|
|
82682
84203
|
else
|
|
82683
|
-
local DetectedItemsCount=self.TargetSetUnit:
|
|
84204
|
+
local DetectedItemsCount=self.TargetSetUnit:CountAlive()
|
|
82684
84205
|
local DetectedItemsTypes=self.TargetSetUnit:GetTypeNames()
|
|
82685
84206
|
self.TaskInfo:AddTargetCount(DetectedItemsCount,11,"O",true)
|
|
82686
84207
|
self.TaskInfo:AddTargets(DetectedItemsCount,DetectedItemsTypes,20,"D",true)
|