@jtff/miztemplate-lib 3.1.6 → 3.1.8
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 +1309 -144
- package/lua/lib/{mist_4_5_107.lua → mist_4_5_122.lua} +773 -351
- 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: 2023-
|
|
1
|
+
env.info('*** MOOSE GITHUB Commit Hash ID: 2023-12-10T14:37:41+01:00-c089e56060974539e58a346665f7536a2898c4cf ***')
|
|
2
2
|
env.info('*** MOOSE STATIC INCLUDE START *** ')
|
|
3
3
|
ENUMS={}
|
|
4
4
|
env.setErrorMessageBoxEnabled(false)
|
|
@@ -416,6 +416,12 @@ Reaper="MQ-9",
|
|
|
416
416
|
Predator="MQ-1A",
|
|
417
417
|
}
|
|
418
418
|
}
|
|
419
|
+
ENUMS.Link16Power={
|
|
420
|
+
none=0,
|
|
421
|
+
low=1,
|
|
422
|
+
medium=2,
|
|
423
|
+
high=3,
|
|
424
|
+
}
|
|
419
425
|
ENUMS.Storage={
|
|
420
426
|
weapons={
|
|
421
427
|
missiles={},
|
|
@@ -1277,21 +1283,33 @@ end
|
|
|
1277
1283
|
end
|
|
1278
1284
|
end
|
|
1279
1285
|
function UTILS.PrintTableToLog(table,indent)
|
|
1286
|
+
local text="\n"
|
|
1280
1287
|
if not table then
|
|
1281
|
-
|
|
1282
|
-
return
|
|
1288
|
+
env.warning("No table passed!")
|
|
1289
|
+
return nil
|
|
1283
1290
|
end
|
|
1284
1291
|
if not indent then indent=0 end
|
|
1285
1292
|
for k,v in pairs(table)do
|
|
1293
|
+
if string.find(k," ")then k='"'..k..'"'end
|
|
1286
1294
|
if type(v)=="table"then
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1295
|
+
env.info(string.rep(" ",indent)..tostring(k).." = {")
|
|
1296
|
+
text=text..string.rep(" ",indent)..tostring(k).." = {\n"
|
|
1297
|
+
text=text..tostring(UTILS.PrintTableToLog(v,indent+1)).."\n"
|
|
1298
|
+
env.info(string.rep(" ",indent).."},")
|
|
1299
|
+
text=text..string.rep(" ",indent).."},\n"
|
|
1300
|
+
else
|
|
1301
|
+
local value
|
|
1302
|
+
if tostring(v)=="true"or tostring(v)=="false"or tonumber(v)~=nil then
|
|
1303
|
+
value=v
|
|
1290
1304
|
else
|
|
1291
|
-
|
|
1305
|
+
value='"'..tostring(v)..'"'
|
|
1292
1306
|
end
|
|
1307
|
+
env.info(string.rep(" ",indent)..tostring(k).." = "..tostring(value)..",\n")
|
|
1308
|
+
text=text..string.rep(" ",indent)..tostring(k).." = "..tostring(value)..",\n"
|
|
1293
1309
|
end
|
|
1294
1310
|
end
|
|
1311
|
+
return text
|
|
1312
|
+
end
|
|
1295
1313
|
function UTILS.TableShow(tbl,loc,indent,tableshow_tbls)
|
|
1296
1314
|
tableshow_tbls=tableshow_tbls or{}
|
|
1297
1315
|
loc=loc or""
|
|
@@ -1817,9 +1835,15 @@ end
|
|
|
1817
1835
|
function UTILS.VecSubstract(a,b)
|
|
1818
1836
|
return{x=a.x-b.x,y=a.y-b.y,z=a.z-b.z}
|
|
1819
1837
|
end
|
|
1838
|
+
function UTILS.VecSubtract(a,b)
|
|
1839
|
+
return UTILS.VecSubstract(a,b)
|
|
1840
|
+
end
|
|
1820
1841
|
function UTILS.Vec2Substract(a,b)
|
|
1821
1842
|
return{x=a.x-b.x,y=a.y-b.y}
|
|
1822
1843
|
end
|
|
1844
|
+
function UTILS.Vec2Subtract(a,b)
|
|
1845
|
+
return UTILS.Vec2Substract(a,b)
|
|
1846
|
+
end
|
|
1823
1847
|
function UTILS.VecAdd(a,b)
|
|
1824
1848
|
return{x=a.x+b.x,y=a.y+b.y,z=a.z+b.z}
|
|
1825
1849
|
end
|
|
@@ -2479,7 +2503,7 @@ filename=path.."\\"..filename
|
|
|
2479
2503
|
end
|
|
2480
2504
|
local exists=UTILS.CheckFileExists(Path,Filename)
|
|
2481
2505
|
if not exists then
|
|
2482
|
-
BASE:
|
|
2506
|
+
BASE:I(string.format("ERROR: File %s does not exist!",filename))
|
|
2483
2507
|
return false
|
|
2484
2508
|
end
|
|
2485
2509
|
local file=assert(io.open(filename,"rb"))
|
|
@@ -2991,6 +3015,300 @@ point_four:LineToAll(point_three,coalition,color,alpha,lineType)
|
|
|
2991
3015
|
circle_center_fix_four:CircleToAll(UTILS.NMToMeters(turn_radius),coalition,color,alpha,nil,0,lineType)
|
|
2992
3016
|
circle_center_two_three:CircleToAll(UTILS.NMToMeters(turn_radius),coalition,color,alpha,nil,0,lineType)
|
|
2993
3017
|
end
|
|
3018
|
+
function UTILS.TimeNow()
|
|
3019
|
+
return UTILS.SecondsToClock(timer.getAbsTime(),false,false)
|
|
3020
|
+
end
|
|
3021
|
+
function UTILS.TimeDifferenceInSeconds(start_time,end_time)
|
|
3022
|
+
return UTILS.ClockToSeconds(end_time)-UTILS.ClockToSeconds(start_time)
|
|
3023
|
+
end
|
|
3024
|
+
function UTILS.TimeLaterThan(time_string)
|
|
3025
|
+
if timer.getAbsTime()>UTILS.ClockToSeconds(time_string)then
|
|
3026
|
+
return true
|
|
3027
|
+
end
|
|
3028
|
+
return false
|
|
3029
|
+
end
|
|
3030
|
+
function UTILS.TimeBefore(time_string)
|
|
3031
|
+
if timer.getAbsTime()<UTILS.ClockToSeconds(time_string)then
|
|
3032
|
+
return true
|
|
3033
|
+
end
|
|
3034
|
+
return false
|
|
3035
|
+
end
|
|
3036
|
+
function UTILS.CombineTimeStrings(time_string_01,time_string_02)
|
|
3037
|
+
local hours1,minutes1,seconds1=time_string_01:match("(%d+):(%d+):(%d+)")
|
|
3038
|
+
local hours2,minutes2,seconds2=time_string_02:match("(%d+):(%d+):(%d+)")
|
|
3039
|
+
local total_seconds=tonumber(seconds1)+tonumber(seconds2)+tonumber(minutes1)*60+tonumber(minutes2)*60+tonumber(hours1)*3600+tonumber(hours2)*3600
|
|
3040
|
+
total_seconds=total_seconds%(24*3600)
|
|
3041
|
+
if total_seconds<0 then
|
|
3042
|
+
total_seconds=total_seconds+24*3600
|
|
3043
|
+
end
|
|
3044
|
+
local hours=math.floor(total_seconds/3600)
|
|
3045
|
+
total_seconds=total_seconds-hours*3600
|
|
3046
|
+
local minutes=math.floor(total_seconds/60)
|
|
3047
|
+
local seconds=total_seconds%60
|
|
3048
|
+
return string.format("%02d:%02d:%02d",hours,minutes,seconds)
|
|
3049
|
+
end
|
|
3050
|
+
function UTILS.SubtractTimeStrings(time_string_01,time_string_02)
|
|
3051
|
+
local hours1,minutes1,seconds1=time_string_01:match("(%d+):(%d+):(%d+)")
|
|
3052
|
+
local hours2,minutes2,seconds2=time_string_02:match("(%d+):(%d+):(%d+)")
|
|
3053
|
+
local total_seconds=tonumber(seconds1)-tonumber(seconds2)+tonumber(minutes1)*60-tonumber(minutes2)*60+tonumber(hours1)*3600-tonumber(hours2)*3600
|
|
3054
|
+
total_seconds=total_seconds%(24*3600)
|
|
3055
|
+
if total_seconds<0 then
|
|
3056
|
+
total_seconds=total_seconds+24*3600
|
|
3057
|
+
end
|
|
3058
|
+
local hours=math.floor(total_seconds/3600)
|
|
3059
|
+
total_seconds=total_seconds-hours*3600
|
|
3060
|
+
local minutes=math.floor(total_seconds/60)
|
|
3061
|
+
local seconds=total_seconds%60
|
|
3062
|
+
return string.format("%02d:%02d:%02d",hours,minutes,seconds)
|
|
3063
|
+
end
|
|
3064
|
+
function UTILS.TimeBetween(start_time,end_time)
|
|
3065
|
+
return UTILS.TimeLaterThan(start_time)and UTILS.TimeBefore(end_time)
|
|
3066
|
+
end
|
|
3067
|
+
function UTILS.PercentageChance(chance)
|
|
3068
|
+
chance=chance or math.random(0,100)
|
|
3069
|
+
chance=UTILS.Clamp(chance,0,100)
|
|
3070
|
+
local percentage=math.random(0,100)
|
|
3071
|
+
if percentage<chance then
|
|
3072
|
+
return true
|
|
3073
|
+
end
|
|
3074
|
+
return false
|
|
3075
|
+
end
|
|
3076
|
+
function UTILS.Clamp(value,min,max)
|
|
3077
|
+
if value<min then value=min end
|
|
3078
|
+
if value>max then value=max end
|
|
3079
|
+
return value
|
|
3080
|
+
end
|
|
3081
|
+
function UTILS.ClampAngle(value)
|
|
3082
|
+
if value>360 then return value-360 end
|
|
3083
|
+
if value<0 then return value+360 end
|
|
3084
|
+
return value
|
|
3085
|
+
end
|
|
3086
|
+
function UTILS.RemapValue(value,old_min,old_max,new_min,new_max)
|
|
3087
|
+
new_min=new_min or 0
|
|
3088
|
+
new_max=new_max or 100
|
|
3089
|
+
local old_range=old_max-old_min
|
|
3090
|
+
local new_range=new_max-new_min
|
|
3091
|
+
local percentage=(value-old_min)/old_range
|
|
3092
|
+
return(new_range*percentage)+new_min
|
|
3093
|
+
end
|
|
3094
|
+
function UTILS.RandomPointInTriangle(pt1,pt2,pt3)
|
|
3095
|
+
local pt={math.random(),math.random()}
|
|
3096
|
+
table.sort(pt)
|
|
3097
|
+
local s=pt[1]
|
|
3098
|
+
local t=pt[2]-pt[1]
|
|
3099
|
+
local u=1-pt[2]
|
|
3100
|
+
return{x=s*pt1.x+t*pt2.x+u*pt3.x,
|
|
3101
|
+
y=s*pt1.y+t*pt2.y+u*pt3.y}
|
|
3102
|
+
end
|
|
3103
|
+
function UTILS.AngleBetween(angle,min,max)
|
|
3104
|
+
angle=(360+(angle%360))%360
|
|
3105
|
+
min=(360+min%360)%360
|
|
3106
|
+
max=(360+max%360)%360
|
|
3107
|
+
if min<max then return min<=angle and angle<=max end
|
|
3108
|
+
return min<=angle or angle<=max
|
|
3109
|
+
end
|
|
3110
|
+
function UTILS.WriteJSON(data,file_path)
|
|
3111
|
+
package.path=package.path..";.\\Scripts\\?.lua"
|
|
3112
|
+
local JSON=require("json")
|
|
3113
|
+
local pretty_json_text=JSON:encode_pretty(data)
|
|
3114
|
+
local write_file=io.open(file_path,"w")
|
|
3115
|
+
write_file:write(pretty_json_text)
|
|
3116
|
+
write_file:close()
|
|
3117
|
+
end
|
|
3118
|
+
function UTILS.ReadJSON(file_path)
|
|
3119
|
+
package.path=package.path..";.\\Scripts\\?.lua"
|
|
3120
|
+
local JSON=require("json")
|
|
3121
|
+
local read_file=io.open(file_path,"r")
|
|
3122
|
+
local contents=read_file:read("*a")
|
|
3123
|
+
io.close(read_file)
|
|
3124
|
+
return JSON:decode(contents)
|
|
3125
|
+
end
|
|
3126
|
+
function UTILS.GetZoneProperties(zone_name)
|
|
3127
|
+
local return_table={}
|
|
3128
|
+
for _,zone in pairs(env.mission.triggers.zones)do
|
|
3129
|
+
if zone["name"]==zone_name then
|
|
3130
|
+
if table.length(zone["properties"])>0 then
|
|
3131
|
+
for _,property in pairs(zone["properties"])do
|
|
3132
|
+
return_table[property["key"]]=property["value"]
|
|
3133
|
+
end
|
|
3134
|
+
return return_table
|
|
3135
|
+
else
|
|
3136
|
+
BASE:I(string.format("%s doesn't have any properties",zone_name))
|
|
3137
|
+
return{}
|
|
3138
|
+
end
|
|
3139
|
+
end
|
|
3140
|
+
end
|
|
3141
|
+
end
|
|
3142
|
+
function UTILS.RotatePointAroundPivot(point,pivot,angle)
|
|
3143
|
+
local radians=math.rad(angle)
|
|
3144
|
+
local x=point.x-pivot.x
|
|
3145
|
+
local y=point.y-pivot.y
|
|
3146
|
+
local rotated_x=x*math.cos(radians)-y*math.sin(radians)
|
|
3147
|
+
local rotatex_y=x*math.sin(radians)+y*math.cos(radians)
|
|
3148
|
+
local original_x=rotated_x+pivot.x
|
|
3149
|
+
local original_y=rotatex_y+pivot.y
|
|
3150
|
+
return{x=original_x,y=original_y}
|
|
3151
|
+
end
|
|
3152
|
+
function UTILS.UniqueName(base)
|
|
3153
|
+
base=base or""
|
|
3154
|
+
local ran=tostring(math.random(0,1000000))
|
|
3155
|
+
if base==""then
|
|
3156
|
+
return ran
|
|
3157
|
+
end
|
|
3158
|
+
return base.."_"..ran
|
|
3159
|
+
end
|
|
3160
|
+
function string.startswith(str,value)
|
|
3161
|
+
return string.sub(str,1,string.len(value))==value
|
|
3162
|
+
end
|
|
3163
|
+
function string.endswith(str,value)
|
|
3164
|
+
return value==""or str:sub(-#value)==value
|
|
3165
|
+
end
|
|
3166
|
+
function string.split(input,separator)
|
|
3167
|
+
local parts={}
|
|
3168
|
+
for part in input:gmatch("[^"..separator.."]+")do
|
|
3169
|
+
table.insert(parts,part)
|
|
3170
|
+
end
|
|
3171
|
+
return parts
|
|
3172
|
+
end
|
|
3173
|
+
function string.contains(str,value)
|
|
3174
|
+
return string.match(str,value)
|
|
3175
|
+
end
|
|
3176
|
+
function table.contains(tbl,element)
|
|
3177
|
+
if element==nil or tbl==nil then return false end
|
|
3178
|
+
local index=1
|
|
3179
|
+
while tbl[index]do
|
|
3180
|
+
if tbl[index]==element then
|
|
3181
|
+
return true
|
|
3182
|
+
end
|
|
3183
|
+
index=index+1
|
|
3184
|
+
end
|
|
3185
|
+
return false
|
|
3186
|
+
end
|
|
3187
|
+
function table.contains_key(tbl,key)
|
|
3188
|
+
if tbl[key]~=nil then return true else return false end
|
|
3189
|
+
end
|
|
3190
|
+
function table.insert_unique(tbl,element)
|
|
3191
|
+
if element==nil or tbl==nil then return end
|
|
3192
|
+
if not table.contains(tbl,element)then
|
|
3193
|
+
table.insert(tbl,element)
|
|
3194
|
+
end
|
|
3195
|
+
end
|
|
3196
|
+
function table.remove_by_value(tbl,element)
|
|
3197
|
+
local indices_to_remove={}
|
|
3198
|
+
local index=1
|
|
3199
|
+
for _,value in pairs(tbl)do
|
|
3200
|
+
if value==element then
|
|
3201
|
+
table.insert(indices_to_remove,index)
|
|
3202
|
+
end
|
|
3203
|
+
index=index+1
|
|
3204
|
+
end
|
|
3205
|
+
for _,idx in pairs(indices_to_remove)do
|
|
3206
|
+
table.remove(tbl,idx)
|
|
3207
|
+
end
|
|
3208
|
+
end
|
|
3209
|
+
function table.remove_key(table,key)
|
|
3210
|
+
local element=table[key]
|
|
3211
|
+
table[key]=nil
|
|
3212
|
+
return element
|
|
3213
|
+
end
|
|
3214
|
+
function table.index_of(table,element)
|
|
3215
|
+
for i,v in ipairs(table)do
|
|
3216
|
+
if v==element then
|
|
3217
|
+
return i
|
|
3218
|
+
end
|
|
3219
|
+
end
|
|
3220
|
+
return nil
|
|
3221
|
+
end
|
|
3222
|
+
function table.length(T)
|
|
3223
|
+
local count=0
|
|
3224
|
+
for _ in pairs(T)do count=count+1 end
|
|
3225
|
+
return count
|
|
3226
|
+
end
|
|
3227
|
+
function table.slice(tbl,first,last)
|
|
3228
|
+
local sliced={}
|
|
3229
|
+
local start=first or 1
|
|
3230
|
+
local stop=last or table.length(tbl)
|
|
3231
|
+
local count=1
|
|
3232
|
+
for key,value in pairs(tbl)do
|
|
3233
|
+
if count>=start and count<=stop then
|
|
3234
|
+
sliced[key]=value
|
|
3235
|
+
end
|
|
3236
|
+
count=count+1
|
|
3237
|
+
end
|
|
3238
|
+
return sliced
|
|
3239
|
+
end
|
|
3240
|
+
function table.count_value(tbl,value)
|
|
3241
|
+
local count=0
|
|
3242
|
+
for _,item in pairs(tbl)do
|
|
3243
|
+
if item==value then count=count+1 end
|
|
3244
|
+
end
|
|
3245
|
+
return count
|
|
3246
|
+
end
|
|
3247
|
+
function table.combine(t1,t2)
|
|
3248
|
+
if t1==nil and t2==nil then
|
|
3249
|
+
BASE:E("Both tables were empty!")
|
|
3250
|
+
end
|
|
3251
|
+
if t1==nil then return t2 end
|
|
3252
|
+
if t2==nil then return t1 end
|
|
3253
|
+
for i=1,#t2 do
|
|
3254
|
+
t1[#t1+1]=t2[i]
|
|
3255
|
+
end
|
|
3256
|
+
return t1
|
|
3257
|
+
end
|
|
3258
|
+
function table.merge(t1,t2)
|
|
3259
|
+
for k,v in pairs(t2)do
|
|
3260
|
+
if(type(v)=="table")and(type(t1[k]or false)=="table")then
|
|
3261
|
+
table.merge(t1[k],t2[k])
|
|
3262
|
+
else
|
|
3263
|
+
t1[k]=v
|
|
3264
|
+
end
|
|
3265
|
+
end
|
|
3266
|
+
return t1
|
|
3267
|
+
end
|
|
3268
|
+
function table.add(tbl,item)
|
|
3269
|
+
tbl[#tbl+1]=item
|
|
3270
|
+
end
|
|
3271
|
+
function table.shuffle(tbl)
|
|
3272
|
+
local new_table={}
|
|
3273
|
+
for _,value in ipairs(tbl)do
|
|
3274
|
+
local pos=math.random(1,#new_table+1)
|
|
3275
|
+
table.insert(new_table,pos,value)
|
|
3276
|
+
end
|
|
3277
|
+
return new_table
|
|
3278
|
+
end
|
|
3279
|
+
function table.find_key_value_pair(tbl,key,value)
|
|
3280
|
+
for k,v in pairs(tbl)do
|
|
3281
|
+
if type(v)=="table"then
|
|
3282
|
+
local result=table.find_key_value_pair(v,key,value)
|
|
3283
|
+
if result~=nil then
|
|
3284
|
+
return result
|
|
3285
|
+
end
|
|
3286
|
+
elseif k==key and v==value then
|
|
3287
|
+
return tbl
|
|
3288
|
+
end
|
|
3289
|
+
end
|
|
3290
|
+
return nil
|
|
3291
|
+
end
|
|
3292
|
+
function UTILS.DecimalToOctal(Number)
|
|
3293
|
+
if Number<8 then return Number end
|
|
3294
|
+
local number=tonumber(Number)
|
|
3295
|
+
local octal=""
|
|
3296
|
+
local n=1
|
|
3297
|
+
while number>7 do
|
|
3298
|
+
local number1=number%8
|
|
3299
|
+
octal=string.format("%d",number1)..octal
|
|
3300
|
+
local number2=math.abs(number/8)
|
|
3301
|
+
if number2<8 then
|
|
3302
|
+
octal=string.format("%d",number2)..octal
|
|
3303
|
+
end
|
|
3304
|
+
number=number2
|
|
3305
|
+
n=n+1
|
|
3306
|
+
end
|
|
3307
|
+
return tonumber(octal)
|
|
3308
|
+
end
|
|
3309
|
+
function UTILS.OctalToDecimal(Number)
|
|
3310
|
+
return tonumber(Number,8)
|
|
3311
|
+
end
|
|
2994
3312
|
PROFILER={
|
|
2995
3313
|
ClassName="PROFILER",
|
|
2996
3314
|
Counters={},
|
|
@@ -5888,6 +6206,14 @@ UnitDeleteTask=world.event.S_EVENT_UNIT_DELETE_TASK or-1,
|
|
|
5888
6206
|
SimulationStart=world.event.S_EVENT_SIMULATION_START or-1,
|
|
5889
6207
|
WeaponRearm=world.event.S_EVENT_WEAPON_REARM or-1,
|
|
5890
6208
|
WeaponDrop=world.event.S_EVENT_WEAPON_DROP or-1,
|
|
6209
|
+
UnitTaskTimeout=world.event.S_EVENT_UNIT_TASK_TIMEOUT or-1,
|
|
6210
|
+
UnitTaskStage=world.event.S_EVENT_UNIT_TASK_STAGE or-1,
|
|
6211
|
+
MacSubtaskScore=world.event.S_EVENT_MAC_SUBTASK_SCORE or-1,
|
|
6212
|
+
MacExtraScore=world.event.S_EVENT_MAC_EXTRA_SCORE or-1,
|
|
6213
|
+
MissionRestart=world.event.S_EVENT_MISSION_RESTART or-1,
|
|
6214
|
+
MissionWinner=world.event.S_EVENT_MISSION_WINNER or-1,
|
|
6215
|
+
PostponedTakeoff=world.event.S_EVENT_POSTPONED_TAKEOFF or-1,
|
|
6216
|
+
PostponedLand=world.event.S_EVENT_POSTPONED_LAND or-1,
|
|
5891
6217
|
}
|
|
5892
6218
|
local _EVENTMETA={
|
|
5893
6219
|
[world.event.S_EVENT_SHOT]={
|
|
@@ -6201,6 +6527,54 @@ Side="I",
|
|
|
6201
6527
|
Event="OnEventWeaponDrop",
|
|
6202
6528
|
Text="S_EVENT_WEAPON_DROP"
|
|
6203
6529
|
},
|
|
6530
|
+
[EVENTS.UnitTaskTimeout]={
|
|
6531
|
+
Order=1,
|
|
6532
|
+
Side="I",
|
|
6533
|
+
Event="OnEventUnitTaskTimeout",
|
|
6534
|
+
Text="S_EVENT_UNIT_TASK_TIMEOUT "
|
|
6535
|
+
},
|
|
6536
|
+
[EVENTS.UnitTaskStage]={
|
|
6537
|
+
Order=1,
|
|
6538
|
+
Side="I",
|
|
6539
|
+
Event="OnEventUnitTaskStage",
|
|
6540
|
+
Text="S_EVENT_UNIT_TASK_STAGE "
|
|
6541
|
+
},
|
|
6542
|
+
[EVENTS.MacSubtaskScore]={
|
|
6543
|
+
Order=1,
|
|
6544
|
+
Side="I",
|
|
6545
|
+
Event="OnEventMacSubtaskScore",
|
|
6546
|
+
Text="S_EVENT_MAC_SUBTASK_SCORE"
|
|
6547
|
+
},
|
|
6548
|
+
[EVENTS.MacExtraScore]={
|
|
6549
|
+
Order=1,
|
|
6550
|
+
Side="I",
|
|
6551
|
+
Event="OnEventMacExtraScore",
|
|
6552
|
+
Text="S_EVENT_MAC_EXTRA_SCOREP"
|
|
6553
|
+
},
|
|
6554
|
+
[EVENTS.MissionRestart]={
|
|
6555
|
+
Order=1,
|
|
6556
|
+
Side="I",
|
|
6557
|
+
Event="OnEventMissionRestart",
|
|
6558
|
+
Text="S_EVENT_MISSION_RESTART"
|
|
6559
|
+
},
|
|
6560
|
+
[EVENTS.MissionWinner]={
|
|
6561
|
+
Order=1,
|
|
6562
|
+
Side="I",
|
|
6563
|
+
Event="OnEventMissionWinner",
|
|
6564
|
+
Text="S_EVENT_MISSION_WINNER"
|
|
6565
|
+
},
|
|
6566
|
+
[EVENTS.PostponedTakeoff]={
|
|
6567
|
+
Order=1,
|
|
6568
|
+
Side="I",
|
|
6569
|
+
Event="OnEventPostponedTakeoff",
|
|
6570
|
+
Text="S_EVENT_POSTPONED_TAKEOFF"
|
|
6571
|
+
},
|
|
6572
|
+
[EVENTS.PostponedLand]={
|
|
6573
|
+
Order=1,
|
|
6574
|
+
Side="I",
|
|
6575
|
+
Event="OnEventPostponedLand",
|
|
6576
|
+
Text="S_EVENT_POSTPONED_LAND"
|
|
6577
|
+
},
|
|
6204
6578
|
}
|
|
6205
6579
|
function EVENT:New()
|
|
6206
6580
|
local self=BASE:Inherit(self,BASE:New())
|
|
@@ -6524,11 +6898,13 @@ elseif Event.TgtObjectCategory==Object.Category.STATIC then
|
|
|
6524
6898
|
Event.TgtDCSUnit=Event.target
|
|
6525
6899
|
if Event.target:isExist()and Event.id~=33 then
|
|
6526
6900
|
Event.TgtDCSUnitName=Event.TgtDCSUnit:getName()
|
|
6901
|
+
if Event.TgtDCSUnitName and Event.TgtDCSUnitName~=""then
|
|
6527
6902
|
Event.TgtUnitName=Event.TgtDCSUnitName
|
|
6528
6903
|
Event.TgtUnit=STATIC:FindByName(Event.TgtDCSUnitName,false)
|
|
6529
6904
|
Event.TgtCoalition=Event.TgtDCSUnit:getCoalition()
|
|
6530
6905
|
Event.TgtCategory=Event.TgtDCSUnit:getDesc().category
|
|
6531
6906
|
Event.TgtTypeName=Event.TgtDCSUnit:getTypeName()
|
|
6907
|
+
end
|
|
6532
6908
|
else
|
|
6533
6909
|
Event.TgtDCSUnitName=string.format("No target object for Event ID %s",tostring(Event.id))
|
|
6534
6910
|
Event.TgtUnitName=Event.TgtDCSUnitName
|
|
@@ -6560,7 +6936,7 @@ if Event.weapon then
|
|
|
6560
6936
|
Event.Weapon=Event.weapon
|
|
6561
6937
|
Event.WeaponName=Event.Weapon:getTypeName()
|
|
6562
6938
|
Event.WeaponUNIT=CLIENT:Find(Event.Weapon,'',true)
|
|
6563
|
-
Event.WeaponPlayerName=Event.WeaponUNIT and Event.Weapon:getPlayerName()
|
|
6939
|
+
Event.WeaponPlayerName=Event.WeaponUNIT and Event.Weapon.getPlayerName and Event.Weapon:getPlayerName()
|
|
6564
6940
|
Event.WeaponCoalition=Event.WeaponUNIT and Event.Weapon:getCoalition()
|
|
6565
6941
|
Event.WeaponCategory=Event.WeaponUNIT and Event.Weapon:getDesc().category
|
|
6566
6942
|
Event.WeaponTypeName=Event.WeaponUNIT and Event.Weapon:getTypeName()
|
|
@@ -6568,7 +6944,7 @@ end
|
|
|
6568
6944
|
if Event.place then
|
|
6569
6945
|
if Event.id==EVENTS.LandingAfterEjection then
|
|
6570
6946
|
else
|
|
6571
|
-
if Event.place:isExist()and Event.place
|
|
6947
|
+
if Event.place:isExist()and Object.getCategory(Event.place)~=Object.Category.SCENERY then
|
|
6572
6948
|
Event.Place=AIRBASE:Find(Event.place)
|
|
6573
6949
|
Event.PlaceName=Event.Place:GetName()
|
|
6574
6950
|
end
|
|
@@ -8108,7 +8484,13 @@ if Delay and Delay>0 then
|
|
|
8108
8484
|
self:ScheduleOnce(Delay,ZONE_BASE.UndrawZone,self)
|
|
8109
8485
|
else
|
|
8110
8486
|
if self.DrawID then
|
|
8487
|
+
if type(self.DrawID)~="table"then
|
|
8111
8488
|
UTILS.RemoveMark(self.DrawID)
|
|
8489
|
+
else
|
|
8490
|
+
for _,mark_id in pairs(self.DrawID)do
|
|
8491
|
+
UTILS.RemoveMark(mark_id)
|
|
8492
|
+
end
|
|
8493
|
+
end
|
|
8112
8494
|
end
|
|
8113
8495
|
end
|
|
8114
8496
|
return self
|
|
@@ -8368,7 +8750,7 @@ radius=ZoneRadius,
|
|
|
8368
8750
|
}
|
|
8369
8751
|
local function EvaluateZone(ZoneObject)
|
|
8370
8752
|
if ZoneObject then
|
|
8371
|
-
local ObjectCategory=
|
|
8753
|
+
local ObjectCategory=Object.getCategory(ZoneObject)
|
|
8372
8754
|
if(ObjectCategory==Object.Category.UNIT and ZoneObject:isExist()and ZoneObject:isActive())or(ObjectCategory==Object.Category.STATIC and ZoneObject:isExist())then
|
|
8373
8755
|
local CoalitionDCSUnit=ZoneObject:getCoalition()
|
|
8374
8756
|
local Include=false
|
|
@@ -8823,8 +9205,68 @@ local PointVec2=POINT_VEC2:NewFromVec2(self:GetRandomVec2())
|
|
|
8823
9205
|
self:T3({PointVec2})
|
|
8824
9206
|
return PointVec2
|
|
8825
9207
|
end
|
|
9208
|
+
_ZONE_TRIANGLE={
|
|
9209
|
+
ClassName="ZONE_TRIANGLE",
|
|
9210
|
+
Points={},
|
|
9211
|
+
Coords={},
|
|
9212
|
+
CenterVec2={x=0,y=0},
|
|
9213
|
+
SurfaceArea=0,
|
|
9214
|
+
DrawIDs={}
|
|
9215
|
+
}
|
|
9216
|
+
function _ZONE_TRIANGLE:New(p1,p2,p3)
|
|
9217
|
+
local self=BASE:Inherit(self,ZONE_BASE:New())
|
|
9218
|
+
self.Points={p1,p2,p3}
|
|
9219
|
+
local center_x=(p1.x+p2.x+p3.x)/3
|
|
9220
|
+
local center_y=(p1.y+p2.y+p3.y)/3
|
|
9221
|
+
self.CenterVec2={x=center_x,y=center_y}
|
|
9222
|
+
for _,pt in pairs({p1,p2,p3})do
|
|
9223
|
+
table.add(self.Coords,COORDINATE:NewFromVec2(pt))
|
|
9224
|
+
end
|
|
9225
|
+
self.SurfaceArea=math.abs((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))*0.5
|
|
9226
|
+
return self
|
|
9227
|
+
end
|
|
9228
|
+
function _ZONE_TRIANGLE:ContainsPoint(pt,points)
|
|
9229
|
+
points=points or self.Points
|
|
9230
|
+
local function sign(p1,p2,p3)
|
|
9231
|
+
return(p1.x-p3.x)*(p2.y-p3.y)-(p2.x-p3.x)*(p1.y-p3.y)
|
|
9232
|
+
end
|
|
9233
|
+
local d1=sign(pt,self.Points[1],self.Points[2])
|
|
9234
|
+
local d2=sign(pt,self.Points[2],self.Points[3])
|
|
9235
|
+
local d3=sign(pt,self.Points[3],self.Points[1])
|
|
9236
|
+
local has_neg=(d1<0)or(d2<0)or(d3<0)
|
|
9237
|
+
local has_pos=(d1>0)or(d2>0)or(d3>0)
|
|
9238
|
+
return not(has_neg and has_pos)
|
|
9239
|
+
end
|
|
9240
|
+
function _ZONE_TRIANGLE:GetRandomVec2(points)
|
|
9241
|
+
points=points or self.Points
|
|
9242
|
+
local pt={math.random(),math.random()}
|
|
9243
|
+
table.sort(pt)
|
|
9244
|
+
local s=pt[1]
|
|
9245
|
+
local t=pt[2]-pt[1]
|
|
9246
|
+
local u=1-pt[2]
|
|
9247
|
+
return{x=s*points[1].x+t*points[2].x+u*points[3].x,
|
|
9248
|
+
y=s*points[1].y+t*points[2].y+u*points[3].y}
|
|
9249
|
+
end
|
|
9250
|
+
function _ZONE_TRIANGLE:Draw(Coalition,Color,Alpha,FillColor,FillAlpha,LineType,ReadOnly)
|
|
9251
|
+
Coalition=Coalition or-1
|
|
9252
|
+
Color=Color or{1,0,0}
|
|
9253
|
+
Alpha=Alpha or 1
|
|
9254
|
+
FillColor=FillColor or Color
|
|
9255
|
+
if not FillColor then UTILS.DeepCopy(Color)end
|
|
9256
|
+
FillAlpha=FillAlpha or Alpha
|
|
9257
|
+
if not FillAlpha then FillAlpha=1 end
|
|
9258
|
+
for i=1,#self.Coords do
|
|
9259
|
+
local c1=self.Coords[i]
|
|
9260
|
+
local c2=self.Coords[i%#self.Coords+1]
|
|
9261
|
+
table.add(self.DrawIDs,c1:LineToAll(c2,Coalition,Color,Alpha,LineType,ReadOnly))
|
|
9262
|
+
end
|
|
9263
|
+
return self.DrawIDs
|
|
9264
|
+
end
|
|
8826
9265
|
ZONE_POLYGON_BASE={
|
|
8827
9266
|
ClassName="ZONE_POLYGON_BASE",
|
|
9267
|
+
_Triangles={},
|
|
9268
|
+
SurfaceArea=0,
|
|
9269
|
+
DrawID={}
|
|
8828
9270
|
}
|
|
8829
9271
|
function ZONE_POLYGON_BASE:New(ZoneName,PointsArray)
|
|
8830
9272
|
local self=BASE:Inherit(self,ZONE_BASE:New(ZoneName))
|
|
@@ -8836,9 +9278,84 @@ self._.Polygon[i]={}
|
|
|
8836
9278
|
self._.Polygon[i].x=PointsArray[i].x
|
|
8837
9279
|
self._.Polygon[i].y=PointsArray[i].y
|
|
8838
9280
|
end
|
|
9281
|
+
self._Triangles=self:_Triangulate()
|
|
9282
|
+
self.SurfaceArea=self:_CalculateSurfaceArea()
|
|
8839
9283
|
end
|
|
8840
9284
|
return self
|
|
8841
9285
|
end
|
|
9286
|
+
function ZONE_POLYGON_BASE:_Triangulate()
|
|
9287
|
+
local points=self._.Polygon
|
|
9288
|
+
local triangles={}
|
|
9289
|
+
local function get_orientation(shape_points)
|
|
9290
|
+
local sum=0
|
|
9291
|
+
for i=1,#shape_points do
|
|
9292
|
+
local j=i%#shape_points+1
|
|
9293
|
+
sum=sum+(shape_points[j].x-shape_points[i].x)*(shape_points[j].y+shape_points[i].y)
|
|
9294
|
+
end
|
|
9295
|
+
return sum>=0 and"clockwise"or"counter-clockwise"
|
|
9296
|
+
end
|
|
9297
|
+
local function ensure_clockwise(shape_points)
|
|
9298
|
+
local orientation=get_orientation(shape_points)
|
|
9299
|
+
if orientation=="counter-clockwise"then
|
|
9300
|
+
local reversed={}
|
|
9301
|
+
for i=#shape_points,1,-1 do
|
|
9302
|
+
table.insert(reversed,shape_points[i])
|
|
9303
|
+
end
|
|
9304
|
+
return reversed
|
|
9305
|
+
end
|
|
9306
|
+
return shape_points
|
|
9307
|
+
end
|
|
9308
|
+
local function is_clockwise(p1,p2,p3)
|
|
9309
|
+
local cross_product=(p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x)
|
|
9310
|
+
return cross_product<0
|
|
9311
|
+
end
|
|
9312
|
+
local function divide_recursively(shape_points)
|
|
9313
|
+
if#shape_points==3 then
|
|
9314
|
+
table.insert(triangles,_ZONE_TRIANGLE:New(shape_points[1],shape_points[2],shape_points[3]))
|
|
9315
|
+
elseif#shape_points>3 then
|
|
9316
|
+
for i,p1 in ipairs(shape_points)do
|
|
9317
|
+
local p2=shape_points[(i%#shape_points)+1]
|
|
9318
|
+
local p3=shape_points[(i+1)%#shape_points+1]
|
|
9319
|
+
local triangle=_ZONE_TRIANGLE:New(p1,p2,p3)
|
|
9320
|
+
local is_ear=true
|
|
9321
|
+
if not is_clockwise(p1,p2,p3)then
|
|
9322
|
+
is_ear=false
|
|
9323
|
+
else
|
|
9324
|
+
for _,point in ipairs(shape_points)do
|
|
9325
|
+
if point~=p1 and point~=p2 and point~=p3 and triangle:ContainsPoint(point)then
|
|
9326
|
+
is_ear=false
|
|
9327
|
+
break
|
|
9328
|
+
end
|
|
9329
|
+
end
|
|
9330
|
+
end
|
|
9331
|
+
if is_ear then
|
|
9332
|
+
local is_valid_triangle=true
|
|
9333
|
+
for _,point in ipairs(points)do
|
|
9334
|
+
if point~=p1 and point~=p2 and point~=p3 and triangle:ContainsPoint(point)then
|
|
9335
|
+
is_valid_triangle=false
|
|
9336
|
+
break
|
|
9337
|
+
end
|
|
9338
|
+
end
|
|
9339
|
+
if is_valid_triangle then
|
|
9340
|
+
table.insert(triangles,triangle)
|
|
9341
|
+
local remaining_points={}
|
|
9342
|
+
for j,point in ipairs(shape_points)do
|
|
9343
|
+
if point~=p2 then
|
|
9344
|
+
table.insert(remaining_points,point)
|
|
9345
|
+
end
|
|
9346
|
+
end
|
|
9347
|
+
divide_recursively(remaining_points)
|
|
9348
|
+
break
|
|
9349
|
+
end
|
|
9350
|
+
else
|
|
9351
|
+
end
|
|
9352
|
+
end
|
|
9353
|
+
end
|
|
9354
|
+
end
|
|
9355
|
+
points=ensure_clockwise(points)
|
|
9356
|
+
divide_recursively(points)
|
|
9357
|
+
return triangles
|
|
9358
|
+
end
|
|
8842
9359
|
function ZONE_POLYGON_BASE:UpdateFromVec2(Vec2Array)
|
|
8843
9360
|
self._.Polygon={}
|
|
8844
9361
|
for i=1,#Vec2Array do
|
|
@@ -8846,6 +9363,8 @@ self._.Polygon[i]={}
|
|
|
8846
9363
|
self._.Polygon[i].x=Vec2Array[i].x
|
|
8847
9364
|
self._.Polygon[i].y=Vec2Array[i].y
|
|
8848
9365
|
end
|
|
9366
|
+
self._Triangles=self:_Triangulate()
|
|
9367
|
+
self.SurfaceArea=self:_CalculateSurfaceArea()
|
|
8849
9368
|
return self
|
|
8850
9369
|
end
|
|
8851
9370
|
function ZONE_POLYGON_BASE:UpdateFromVec3(Vec3Array)
|
|
@@ -8855,8 +9374,17 @@ self._.Polygon[i]={}
|
|
|
8855
9374
|
self._.Polygon[i].x=Vec3Array[i].x
|
|
8856
9375
|
self._.Polygon[i].y=Vec3Array[i].z
|
|
8857
9376
|
end
|
|
9377
|
+
self._Triangles=self:_Triangulate()
|
|
9378
|
+
self.SurfaceArea=self:_CalculateSurfaceArea()
|
|
8858
9379
|
return self
|
|
8859
9380
|
end
|
|
9381
|
+
function ZONE_POLYGON_BASE:_CalculateSurfaceArea()
|
|
9382
|
+
local area=0
|
|
9383
|
+
for _,triangle in pairs(self._Triangles)do
|
|
9384
|
+
area=area+triangle.SurfaceArea
|
|
9385
|
+
end
|
|
9386
|
+
return area
|
|
9387
|
+
end
|
|
8860
9388
|
function ZONE_POLYGON_BASE:GetVec2()
|
|
8861
9389
|
self:F(self.ZoneName)
|
|
8862
9390
|
local Bounds=self:GetBoundingSquare()
|
|
@@ -8939,32 +9467,42 @@ i=i+1
|
|
|
8939
9467
|
end
|
|
8940
9468
|
return self
|
|
8941
9469
|
end
|
|
8942
|
-
function ZONE_POLYGON_BASE:DrawZone(Coalition,Color,Alpha,FillColor,FillAlpha,LineType,ReadOnly)
|
|
9470
|
+
function ZONE_POLYGON_BASE:DrawZone(Coalition,Color,Alpha,FillColor,FillAlpha,LineType,ReadOnly,IncludeTriangles)
|
|
8943
9471
|
if self._.Polygon and#self._.Polygon>=3 then
|
|
8944
|
-
local coordinate=COORDINATE:NewFromVec2(self._.Polygon[1])
|
|
8945
9472
|
Coalition=Coalition or self:GetDrawCoalition()
|
|
8946
9473
|
self:SetDrawCoalition(Coalition)
|
|
8947
9474
|
Color=Color or self:GetColorRGB()
|
|
8948
9475
|
Alpha=Alpha or 1
|
|
8949
9476
|
self:SetColor(Color,Alpha)
|
|
8950
9477
|
FillColor=FillColor or self:GetFillColorRGB()
|
|
8951
|
-
if not FillColor then
|
|
9478
|
+
if not FillColor then
|
|
9479
|
+
UTILS.DeepCopy(Color)
|
|
9480
|
+
end
|
|
8952
9481
|
FillAlpha=FillAlpha or self:GetFillColorAlpha()
|
|
8953
|
-
if not FillAlpha then
|
|
9482
|
+
if not FillAlpha then
|
|
9483
|
+
FillAlpha=0.15
|
|
9484
|
+
end
|
|
8954
9485
|
self:SetFillColor(FillColor,FillAlpha)
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
local
|
|
8959
|
-
self.DrawID
|
|
9486
|
+
IncludeTriangles=IncludeTriangles or false
|
|
9487
|
+
if IncludeTriangles then
|
|
9488
|
+
for _,triangle in pairs(self._Triangles)do
|
|
9489
|
+
local draw_ids=triangle:Draw()
|
|
9490
|
+
table.combine(self.DrawID,draw_ids)
|
|
9491
|
+
end
|
|
8960
9492
|
else
|
|
8961
|
-
local
|
|
8962
|
-
|
|
8963
|
-
|
|
9493
|
+
local coords=self:GetVerticiesCoordinates()
|
|
9494
|
+
for i=1,#coords do
|
|
9495
|
+
local c1=coords[i]
|
|
9496
|
+
local c2=coords[i%#coords+1]
|
|
9497
|
+
table.add(self.DrawID,c1:LineToAll(c2,Coalition,Color,Alpha,LineType,ReadOnly))
|
|
9498
|
+
end
|
|
8964
9499
|
end
|
|
8965
9500
|
end
|
|
8966
9501
|
return self
|
|
8967
9502
|
end
|
|
9503
|
+
function ZONE_POLYGON_BASE:GetSurfaceArea()
|
|
9504
|
+
return self.SurfaceArea
|
|
9505
|
+
end
|
|
8968
9506
|
function ZONE_POLYGON_BASE:GetRadius()
|
|
8969
9507
|
local center=self:GetVec2()
|
|
8970
9508
|
local radius=0
|
|
@@ -9073,17 +9611,18 @@ local InZone=self:IsVec2InZone({x=Vec3.x,y=Vec3.z})
|
|
|
9073
9611
|
return InZone
|
|
9074
9612
|
end
|
|
9075
9613
|
function ZONE_POLYGON_BASE:GetRandomVec2()
|
|
9076
|
-
local
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9614
|
+
local weights={}
|
|
9615
|
+
for _,triangle in pairs(self._Triangles)do
|
|
9616
|
+
weights[triangle]=triangle.SurfaceArea/self.SurfaceArea
|
|
9617
|
+
end
|
|
9618
|
+
local random_weight=math.random()
|
|
9619
|
+
local accumulated_weight=0
|
|
9620
|
+
for triangle,weight in pairs(weights)do
|
|
9621
|
+
accumulated_weight=accumulated_weight+weight
|
|
9622
|
+
if accumulated_weight>=random_weight then
|
|
9623
|
+
return triangle:GetRandomVec2()
|
|
9082
9624
|
end
|
|
9083
|
-
n=n+1
|
|
9084
9625
|
end
|
|
9085
|
-
self:E("Could not find a random point in the polygon zone!")
|
|
9086
|
-
return nil
|
|
9087
9626
|
end
|
|
9088
9627
|
function ZONE_POLYGON_BASE:GetRandomPointVec2()
|
|
9089
9628
|
self:F2()
|
|
@@ -9162,6 +9701,7 @@ i=i+1
|
|
|
9162
9701
|
end
|
|
9163
9702
|
return self
|
|
9164
9703
|
end
|
|
9704
|
+
do
|
|
9165
9705
|
ZONE_POLYGON={
|
|
9166
9706
|
ClassName="ZONE_POLYGON",
|
|
9167
9707
|
}
|
|
@@ -9186,6 +9726,36 @@ self:F({GroupName,ZoneGroup,self._.Polygon})
|
|
|
9186
9726
|
_EVENTDISPATCHER:CreateEventNewZone(self)
|
|
9187
9727
|
return self
|
|
9188
9728
|
end
|
|
9729
|
+
function ZONE_POLYGON:NewFromDrawing(DrawingName)
|
|
9730
|
+
local points={}
|
|
9731
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
9732
|
+
for _,object in pairs(layer["objects"])do
|
|
9733
|
+
if object["name"]==DrawingName then
|
|
9734
|
+
if(object["primitiveType"]=="Line"and object["closed"]==true)or(object["polygonMode"]=="free")then
|
|
9735
|
+
for _,point in UTILS.spairs(object["points"])do
|
|
9736
|
+
local p={x=object["mapX"]+point["x"],
|
|
9737
|
+
y=object["mapY"]+point["y"]}
|
|
9738
|
+
table.add(points,p)
|
|
9739
|
+
end
|
|
9740
|
+
elseif object["polygonMode"]=="rect"then
|
|
9741
|
+
local angle=object["angle"]
|
|
9742
|
+
local half_width=object["width"]/2
|
|
9743
|
+
local half_height=object["height"]/2
|
|
9744
|
+
local center={x=object["mapX"],y=object["mapY"]}
|
|
9745
|
+
local p1=UTILS.RotatePointAroundPivot({x=center.x-half_height,y=center.y+half_width},center,angle)
|
|
9746
|
+
local p2=UTILS.RotatePointAroundPivot({x=center.x+half_height,y=center.y+half_width},center,angle)
|
|
9747
|
+
local p3=UTILS.RotatePointAroundPivot({x=center.x+half_height,y=center.y-half_width},center,angle)
|
|
9748
|
+
local p4=UTILS.RotatePointAroundPivot({x=center.x-half_height,y=center.y-half_width},center,angle)
|
|
9749
|
+
points={p1,p2,p3,p4}
|
|
9750
|
+
else
|
|
9751
|
+
end
|
|
9752
|
+
end
|
|
9753
|
+
end
|
|
9754
|
+
end
|
|
9755
|
+
local self=BASE:Inherit(self,ZONE_POLYGON_BASE:New(DrawingName,points))
|
|
9756
|
+
_EVENTDISPATCHER:CreateEventNewZone(self)
|
|
9757
|
+
return self
|
|
9758
|
+
end
|
|
9189
9759
|
function ZONE_POLYGON:FindByName(ZoneName)
|
|
9190
9760
|
local ZoneFound=_DATABASE:FindZone(ZoneName)
|
|
9191
9761
|
return ZoneFound
|
|
@@ -9212,7 +9782,7 @@ radius=ZoneRadius,
|
|
|
9212
9782
|
}
|
|
9213
9783
|
local function EvaluateZone(ZoneObject)
|
|
9214
9784
|
if ZoneObject then
|
|
9215
|
-
local ObjectCategory=
|
|
9785
|
+
local ObjectCategory=Object.getCategory(ZoneObject)
|
|
9216
9786
|
if(ObjectCategory==Object.Category.UNIT and ZoneObject:isExist()and ZoneObject:isActive())or(ObjectCategory==Object.Category.STATIC and ZoneObject:isExist())then
|
|
9217
9787
|
local CoalitionDCSUnit=ZoneObject:getCoalition()
|
|
9218
9788
|
local Include=false
|
|
@@ -9372,6 +9942,7 @@ end
|
|
|
9372
9942
|
function ZONE_POLYGON:IsNoneInZone()
|
|
9373
9943
|
return self:CountScannedCoalitions()==0
|
|
9374
9944
|
end
|
|
9945
|
+
end
|
|
9375
9946
|
do
|
|
9376
9947
|
ZONE_ELASTIC={
|
|
9377
9948
|
ClassName="ZONE_ELASTIC",
|
|
@@ -9465,6 +10036,124 @@ table.remove(h,#h)
|
|
|
9465
10036
|
return h
|
|
9466
10037
|
end
|
|
9467
10038
|
end
|
|
10039
|
+
ZONE_OVAL={
|
|
10040
|
+
ClassName="OVAL",
|
|
10041
|
+
ZoneName="",
|
|
10042
|
+
MajorAxis=nil,
|
|
10043
|
+
MinorAxis=nil,
|
|
10044
|
+
Angle=0,
|
|
10045
|
+
DrawPoly=nil
|
|
10046
|
+
}
|
|
10047
|
+
function ZONE_OVAL:New(name,vec2,major_axis,minor_axis,angle)
|
|
10048
|
+
self=BASE:Inherit(self,ZONE_BASE:New())
|
|
10049
|
+
self.ZoneName=name
|
|
10050
|
+
self.CenterVec2=vec2
|
|
10051
|
+
self.MajorAxis=major_axis
|
|
10052
|
+
self.MinorAxis=minor_axis
|
|
10053
|
+
self.Angle=angle or 0
|
|
10054
|
+
_DATABASE:AddZone(name,self)
|
|
10055
|
+
return self
|
|
10056
|
+
end
|
|
10057
|
+
function ZONE_OVAL:NewFromDrawing(DrawingName)
|
|
10058
|
+
self=BASE:Inherit(self,ZONE_BASE:New(DrawingName))
|
|
10059
|
+
for _,layer in pairs(env.mission.drawings.layers)do
|
|
10060
|
+
for _,object in pairs(layer["objects"])do
|
|
10061
|
+
if string.find(object["name"],DrawingName,1,true)then
|
|
10062
|
+
if object["polygonMode"]=="oval"then
|
|
10063
|
+
self.CenterVec2={x=object["mapX"],y=object["mapY"]}
|
|
10064
|
+
self.MajorAxis=object["r1"]
|
|
10065
|
+
self.MinorAxis=object["r2"]
|
|
10066
|
+
self.Angle=object["angle"]
|
|
10067
|
+
end
|
|
10068
|
+
end
|
|
10069
|
+
end
|
|
10070
|
+
end
|
|
10071
|
+
_DATABASE:AddZone(DrawingName,self)
|
|
10072
|
+
return self
|
|
10073
|
+
end
|
|
10074
|
+
function ZONE_OVAL:GetMajorAxis()
|
|
10075
|
+
return self.MajorAxis
|
|
10076
|
+
end
|
|
10077
|
+
function ZONE_OVAL:GetMinorAxis()
|
|
10078
|
+
return self.MinorAxis
|
|
10079
|
+
end
|
|
10080
|
+
function ZONE_OVAL:GetAngle()
|
|
10081
|
+
return self.Angle
|
|
10082
|
+
end
|
|
10083
|
+
function ZONE_OVAL:GetVec2()
|
|
10084
|
+
return self.CenterVec2
|
|
10085
|
+
end
|
|
10086
|
+
function ZONE_OVAL:IsVec2InZone(vec2)
|
|
10087
|
+
local cos,sin=math.cos,math.sin
|
|
10088
|
+
local dx=vec2.x-self.CenterVec2.x
|
|
10089
|
+
local dy=vec2.y-self.CenterVec2.y
|
|
10090
|
+
local rx=dx*cos(self.Angle)+dy*sin(self.Angle)
|
|
10091
|
+
local ry=-dx*sin(self.Angle)+dy*cos(self.Angle)
|
|
10092
|
+
return rx*rx/(self.MajorAxis*self.MajorAxis)+ry*ry/(self.MinorAxis*self.MinorAxis)<=1
|
|
10093
|
+
end
|
|
10094
|
+
function ZONE_OVAL:GetBoundingSquare()
|
|
10095
|
+
local min_x=self.CenterVec2.x-self.MajorAxis
|
|
10096
|
+
local min_y=self.CenterVec2.y-self.MinorAxis
|
|
10097
|
+
local max_x=self.CenterVec2.x+self.MajorAxis
|
|
10098
|
+
local max_y=self.CenterVec2.y+self.MinorAxis
|
|
10099
|
+
return{
|
|
10100
|
+
{x=min_x,y=min_x},{x=max_x,y=min_y},{x=max_x,y=max_y},{x=min_x,y=max_y}
|
|
10101
|
+
}
|
|
10102
|
+
end
|
|
10103
|
+
function ZONE_OVAL:PointsOnEdge(num_points)
|
|
10104
|
+
num_points=num_points or 40
|
|
10105
|
+
local points={}
|
|
10106
|
+
local dtheta=2*math.pi/num_points
|
|
10107
|
+
for i=0,num_points-1 do
|
|
10108
|
+
local theta=i*dtheta
|
|
10109
|
+
local x=self.CenterVec2.x+self.MajorAxis*math.cos(theta)*math.cos(self.Angle)-self.MinorAxis*math.sin(theta)*math.sin(self.Angle)
|
|
10110
|
+
local y=self.CenterVec2.y+self.MajorAxis*math.cos(theta)*math.sin(self.Angle)+self.MinorAxis*math.sin(theta)*math.cos(self.Angle)
|
|
10111
|
+
table.insert(points,{x=x,y=y})
|
|
10112
|
+
end
|
|
10113
|
+
return points
|
|
10114
|
+
end
|
|
10115
|
+
function ZONE_OVAL:GetRandomVec2()
|
|
10116
|
+
local theta=math.rad(self.Angle)
|
|
10117
|
+
local random_point=math.sqrt(math.random())
|
|
10118
|
+
local phi=math.random()*2*math.pi
|
|
10119
|
+
local x_c=random_point*math.cos(phi)
|
|
10120
|
+
local y_c=random_point*math.sin(phi)
|
|
10121
|
+
local x_e=x_c*self.MajorAxis
|
|
10122
|
+
local y_e=y_c*self.MinorAxis
|
|
10123
|
+
local rx=(x_e*math.cos(theta)-y_e*math.sin(theta))+self.CenterVec2.x
|
|
10124
|
+
local ry=(x_e*math.sin(theta)+y_e*math.cos(theta))+self.CenterVec2.y
|
|
10125
|
+
return{x=rx,y=ry}
|
|
10126
|
+
end
|
|
10127
|
+
function ZONE_OVAL:GetRandomPointVec2()
|
|
10128
|
+
return POINT_VEC2:NewFromVec2(self:GetRandomVec2())
|
|
10129
|
+
end
|
|
10130
|
+
function ZONE_OVAL:GetRandomPointVec3()
|
|
10131
|
+
return POINT_VEC2:NewFromVec3(self:GetRandomVec2())
|
|
10132
|
+
end
|
|
10133
|
+
function ZONE_OVAL:DrawZone(Coalition,Color,Alpha,FillColor,FillAlpha,LineType)
|
|
10134
|
+
Coalition=Coalition or self:GetDrawCoalition()
|
|
10135
|
+
self:SetDrawCoalition(Coalition)
|
|
10136
|
+
Color=Color or self:GetColorRGB()
|
|
10137
|
+
Alpha=Alpha or 1
|
|
10138
|
+
self:SetColor(Color,Alpha)
|
|
10139
|
+
FillColor=FillColor or self:GetFillColorRGB()
|
|
10140
|
+
if not FillColor then
|
|
10141
|
+
UTILS.DeepCopy(Color)
|
|
10142
|
+
end
|
|
10143
|
+
FillAlpha=FillAlpha or self:GetFillColorAlpha()
|
|
10144
|
+
if not FillAlpha then
|
|
10145
|
+
FillAlpha=0.15
|
|
10146
|
+
end
|
|
10147
|
+
LineType=LineType or 1
|
|
10148
|
+
self:SetFillColor(FillColor,FillAlpha)
|
|
10149
|
+
self.DrawPoly=ZONE_POLYGON:NewFromPointsArray(self.ZoneName,self:PointsOnEdge(80))
|
|
10150
|
+
self.DrawPoly:DrawZone(Coalition,Color,Alpha,FillColor,FillAlpha,LineType)
|
|
10151
|
+
end
|
|
10152
|
+
function ZONE_OVAL:UndrawZone()
|
|
10153
|
+
if self.DrawPoly then
|
|
10154
|
+
self.DrawPoly:UndrawZone()
|
|
10155
|
+
end
|
|
10156
|
+
end
|
|
9468
10157
|
do
|
|
9469
10158
|
ZONE_AIRBASE={
|
|
9470
10159
|
ClassName="ZONE_AIRBASE",
|
|
@@ -10776,7 +11465,10 @@ self:T3({LastObject})
|
|
|
10776
11465
|
return LastObject
|
|
10777
11466
|
end
|
|
10778
11467
|
function SET_BASE:GetRandom()
|
|
10779
|
-
local tablemax=
|
|
11468
|
+
local tablemax=0
|
|
11469
|
+
for _,_ind in pairs(self.Index)do
|
|
11470
|
+
tablemax=tablemax+1
|
|
11471
|
+
end
|
|
10780
11472
|
local RandomItem=self.Set[self.Index[math.random(1,tablemax)]]
|
|
10781
11473
|
self:T3({RandomItem})
|
|
10782
11474
|
return RandomItem
|
|
@@ -11691,6 +12383,16 @@ end
|
|
|
11691
12383
|
end
|
|
11692
12384
|
return CountU
|
|
11693
12385
|
end
|
|
12386
|
+
function SET_UNIT:GetAliveSet()
|
|
12387
|
+
local AliveSet=SET_UNIT:New()
|
|
12388
|
+
for GroupName,GroupObject in pairs(self.Set)do
|
|
12389
|
+
local GroupObject=GroupObject
|
|
12390
|
+
if GroupObject and GroupObject:IsAlive()then
|
|
12391
|
+
AliveSet:Add(GroupName,GroupObject)
|
|
12392
|
+
end
|
|
12393
|
+
end
|
|
12394
|
+
return AliveSet.Set or{},AliveSet
|
|
12395
|
+
end
|
|
11694
12396
|
function SET_UNIT:_ContinousZoneFilter()
|
|
11695
12397
|
local Database=_DATABASE.UNITS
|
|
11696
12398
|
for ObjectName,Object in pairs(Database)do
|
|
@@ -11915,40 +12617,41 @@ self:F({MaxThreatLevelA2G=MaxThreatLevelA2G,MaxThreatText=MaxThreatText})
|
|
|
11915
12617
|
return MaxThreatLevelA2G,MaxThreatText
|
|
11916
12618
|
end
|
|
11917
12619
|
function SET_UNIT:GetCoordinate()
|
|
11918
|
-
local
|
|
11919
|
-
local
|
|
11920
|
-
local
|
|
11921
|
-
local
|
|
11922
|
-
local
|
|
11923
|
-
|
|
11924
|
-
local
|
|
11925
|
-
|
|
11926
|
-
|
|
11927
|
-
local MovingCount=0
|
|
11928
|
-
for UnitName,UnitData in pairs(self:GetSet())do
|
|
11929
|
-
local Unit=UnitData
|
|
11930
|
-
local Coordinate=Unit:GetCoordinate()
|
|
11931
|
-
x1=(Coordinate.x<x1)and Coordinate.x or x1
|
|
11932
|
-
x2=(Coordinate.x>x2)and Coordinate.x or x2
|
|
11933
|
-
y1=(Coordinate.y<y1)and Coordinate.y or y1
|
|
11934
|
-
y2=(Coordinate.y>y2)and Coordinate.y or y2
|
|
11935
|
-
z1=(Coordinate.y<z1)and Coordinate.z or z1
|
|
11936
|
-
z2=(Coordinate.y>z2)and Coordinate.z or z2
|
|
11937
|
-
local Velocity=Coordinate:GetVelocity()
|
|
11938
|
-
if Velocity~=0 then
|
|
11939
|
-
MaxVelocity=(MaxVelocity<Velocity)and Velocity or MaxVelocity
|
|
11940
|
-
local Heading=Coordinate:GetHeading()
|
|
11941
|
-
AvgHeading=AvgHeading and(AvgHeading+Heading)or Heading
|
|
11942
|
-
MovingCount=MovingCount+1
|
|
12620
|
+
local function GetSetVec3(units)
|
|
12621
|
+
local x=0
|
|
12622
|
+
local y=0
|
|
12623
|
+
local z=0
|
|
12624
|
+
local n=0
|
|
12625
|
+
for _,unit in pairs(units)do
|
|
12626
|
+
local vec3=nil
|
|
12627
|
+
if unit and unit:IsAlive()then
|
|
12628
|
+
vec3=unit:GetVec3()
|
|
11943
12629
|
end
|
|
12630
|
+
if vec3 then
|
|
12631
|
+
x=x+vec3.x
|
|
12632
|
+
y=y+vec3.y
|
|
12633
|
+
z=z+vec3.z
|
|
12634
|
+
n=n+1
|
|
12635
|
+
end
|
|
12636
|
+
end
|
|
12637
|
+
if n>0 then
|
|
12638
|
+
local Vec3={x=x/n,y=y/n,z=z/n}
|
|
12639
|
+
return Vec3
|
|
12640
|
+
end
|
|
12641
|
+
return nil
|
|
12642
|
+
end
|
|
12643
|
+
local Coordinate=nil
|
|
12644
|
+
local Vec3=GetSetVec3(self.Set)
|
|
12645
|
+
if Vec3 then
|
|
12646
|
+
Coordinate=COORDINATE:NewFromVec3(Vec3)
|
|
12647
|
+
end
|
|
12648
|
+
if Coordinate then
|
|
12649
|
+
local heading=self:GetHeading()or 0
|
|
12650
|
+
local velocity=self:GetVelocity()or 0
|
|
12651
|
+
Coordinate:SetHeading(heading)
|
|
12652
|
+
Coordinate:SetVelocity(velocity)
|
|
12653
|
+
self:I(UTILS.PrintTableToLog(Coordinate))
|
|
11944
12654
|
end
|
|
11945
|
-
AvgHeading=AvgHeading and(AvgHeading/MovingCount)
|
|
11946
|
-
Coordinate.x=(x2-x1)/2+x1
|
|
11947
|
-
Coordinate.y=(y2-y1)/2+y1
|
|
11948
|
-
Coordinate.z=(z2-z1)/2+z1
|
|
11949
|
-
Coordinate:SetHeading(AvgHeading)
|
|
11950
|
-
Coordinate:SetVelocity(MaxVelocity)
|
|
11951
|
-
self:F({Coordinate=Coordinate})
|
|
11952
12655
|
return Coordinate
|
|
11953
12656
|
end
|
|
11954
12657
|
function SET_UNIT:GetVelocity()
|
|
@@ -12805,6 +13508,31 @@ self:_FilterStart()
|
|
|
12805
13508
|
end
|
|
12806
13509
|
return self
|
|
12807
13510
|
end
|
|
13511
|
+
function SET_CLIENT:_EventPlayerEnterUnit(Event)
|
|
13512
|
+
self:I("_EventPlayerEnterUnit")
|
|
13513
|
+
if Event.IniDCSUnit then
|
|
13514
|
+
if Event.IniObjectCategory==1 and Event.IniGroup and Event.IniGroup:IsGround()then
|
|
13515
|
+
local ObjectName,Object=self:AddInDatabase(Event)
|
|
13516
|
+
self:I(ObjectName,UTILS.PrintTableToLog(Object))
|
|
13517
|
+
if Object and self:IsIncludeObject(Object)then
|
|
13518
|
+
self:Add(ObjectName,Object)
|
|
13519
|
+
end
|
|
13520
|
+
end
|
|
13521
|
+
end
|
|
13522
|
+
return self
|
|
13523
|
+
end
|
|
13524
|
+
function SET_CLIENT:_EventPlayerLeaveUnit(Event)
|
|
13525
|
+
self:I("_EventPlayerLeaveUnit")
|
|
13526
|
+
if Event.IniDCSUnit then
|
|
13527
|
+
if Event.IniObjectCategory==1 and Event.IniGroup and Event.IniGroup:IsGround()then
|
|
13528
|
+
local ObjectName,Object=self:FindInDatabase(Event)
|
|
13529
|
+
if ObjectName then
|
|
13530
|
+
self:Remove(ObjectName)
|
|
13531
|
+
end
|
|
13532
|
+
end
|
|
13533
|
+
end
|
|
13534
|
+
return self
|
|
13535
|
+
end
|
|
12808
13536
|
function SET_CLIENT:AddInDatabase(Event)
|
|
12809
13537
|
self:F3({Event})
|
|
12810
13538
|
return Event.IniDCSUnitName,self.Database[Event.IniDCSUnitName]
|
|
@@ -14886,7 +15614,7 @@ local gotunits=false
|
|
|
14886
15614
|
local gotscenery=false
|
|
14887
15615
|
local function EvaluateZone(ZoneObject)
|
|
14888
15616
|
if ZoneObject then
|
|
14889
|
-
local ObjectCategory=
|
|
15617
|
+
local ObjectCategory=Object.getCategory(ZoneObject)
|
|
14890
15618
|
if ObjectCategory==Object.Category.UNIT and ZoneObject:isExist()then
|
|
14891
15619
|
table.insert(Units,UNIT:Find(ZoneObject))
|
|
14892
15620
|
gotunits=true
|
|
@@ -16113,6 +16841,9 @@ end
|
|
|
16113
16841
|
end
|
|
16114
16842
|
return BRAANATO
|
|
16115
16843
|
end
|
|
16844
|
+
function COORDINATE.GetBullseyeCoordinate(Coalition)
|
|
16845
|
+
return COORDINATE:NewFromVec3(coalition.getMainRefPoint(Coalition))
|
|
16846
|
+
end
|
|
16116
16847
|
function COORDINATE:ToStringBULLS(Coalition,Settings,MagVar)
|
|
16117
16848
|
local BullsCoordinate=COORDINATE:NewFromVec3(coalition.getMainRefPoint(Coalition))
|
|
16118
16849
|
local DirectionVec3=BullsCoordinate:GetDirectionVec3(self)
|
|
@@ -16692,7 +17423,7 @@ end
|
|
|
16692
17423
|
if CoalitionSide then
|
|
16693
17424
|
if self.MessageDuration~=0 then
|
|
16694
17425
|
self:T(self.MessageCategory..self.MessageText:gsub("\n$",""):gsub("\n$","").." / "..self.MessageDuration)
|
|
16695
|
-
trigger.action.outTextForCoalition(CoalitionSide,self.MessageText:gsub("\n$",""):gsub("\n$",""),self.MessageDuration,self.ClearScreen)
|
|
17426
|
+
trigger.action.outTextForCoalition(CoalitionSide,self.MessageCategory..self.MessageText:gsub("\n$",""):gsub("\n$",""),self.MessageDuration,self.ClearScreen)
|
|
16696
17427
|
end
|
|
16697
17428
|
end
|
|
16698
17429
|
self.CoalitionSide=CoalitionSide
|
|
@@ -16736,29 +17467,40 @@ return self
|
|
|
16736
17467
|
end
|
|
16737
17468
|
_MESSAGESRS={}
|
|
16738
17469
|
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate)
|
|
16739
|
-
_MESSAGESRS.MSRS=MSRS:New(PathToSRS,Frequency,Modulation,Volume)
|
|
16740
|
-
_MESSAGESRS.
|
|
17470
|
+
_MESSAGESRS.MSRS=MSRS:New(PathToSRS,Frequency or 243,Modulation or radio.modulation.AM,Volume)
|
|
17471
|
+
_MESSAGESRS.frequency=Frequency
|
|
17472
|
+
_MESSAGESRS.modulation=Modulation or radio.modulation.AM
|
|
17473
|
+
_MESSAGESRS.MSRS:SetCoalition(Coalition or coalition.side.NEUTRAL)
|
|
17474
|
+
_MESSAGESRS.coalition=Coalition or coalition.side.NEUTRAL
|
|
17475
|
+
_MESSAGESRS.coordinate=Coordinate
|
|
16741
17476
|
_MESSAGESRS.MSRS:SetCoordinate(Coordinate)
|
|
16742
17477
|
_MESSAGESRS.MSRS:SetCulture(Culture)
|
|
16743
|
-
_MESSAGESRS.Culture=Culture
|
|
17478
|
+
_MESSAGESRS.Culture=Culture or"en-GB"
|
|
16744
17479
|
_MESSAGESRS.MSRS:SetGender(Gender)
|
|
16745
|
-
_MESSAGESRS.Gender=Gender
|
|
17480
|
+
_MESSAGESRS.Gender=Gender or"female"
|
|
16746
17481
|
_MESSAGESRS.MSRS:SetGoogle(PathToCredentials)
|
|
17482
|
+
_MESSAGESRS.google=PathToCredentials
|
|
16747
17483
|
_MESSAGESRS.MSRS:SetLabel(Label or"MESSAGE")
|
|
16748
|
-
_MESSAGESRS.
|
|
16749
|
-
_MESSAGESRS.MSRS:
|
|
16750
|
-
_MESSAGESRS.
|
|
17484
|
+
_MESSAGESRS.label=Label or"MESSAGE"
|
|
17485
|
+
_MESSAGESRS.MSRS:SetPort(Port or 5002)
|
|
17486
|
+
_MESSAGESRS.port=Port or 5002
|
|
17487
|
+
_MESSAGESRS.volume=Volume or 1
|
|
17488
|
+
_MESSAGESRS.MSRS:SetVolume(_MESSAGESRS.volume)
|
|
17489
|
+
if Voice then _MESSAGESRS.MSRS:SetVoice(Voice)end
|
|
17490
|
+
_MESSAGESRS.voice=Voice
|
|
16751
17491
|
_MESSAGESRS.SRSQ=MSRSQUEUE:New(Label or"MESSAGE")
|
|
16752
|
-
env.info(_MESSAGESRS.MSRS.provider,false)
|
|
16753
17492
|
end
|
|
16754
17493
|
function MESSAGE:ToSRS(frequency,modulation,gender,culture,voice,coalition,volume,coordinate)
|
|
17494
|
+
local tgender=gender or _MESSAGESRS.Gender
|
|
16755
17495
|
if _MESSAGESRS.SRSQ then
|
|
16756
|
-
|
|
17496
|
+
if voice then
|
|
17497
|
+
_MESSAGESRS.MSRS:SetVoice(voice or _MESSAGESRS.voice)
|
|
17498
|
+
end
|
|
16757
17499
|
if coordinate then
|
|
16758
17500
|
_MESSAGESRS.MSRS:SetCoordinate(coordinate)
|
|
16759
17501
|
end
|
|
16760
17502
|
local category=string.gsub(self.MessageCategory,":","")
|
|
16761
|
-
_MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,nil,nil,nil,nil,nil,frequency,modulation,gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,
|
|
17503
|
+
_MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,nil,nil,nil,nil,nil,frequency or _MESSAGESRS.frequency,modulation or _MESSAGESRS.modulation,gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,nil,volume or _MESSAGESRS.volume,category,coordinate or _MESSAGESRS.coordinate)
|
|
16762
17504
|
end
|
|
16763
17505
|
return self
|
|
16764
17506
|
end
|
|
@@ -17328,6 +18070,7 @@ self.SpawnInitModexPrefix=nil
|
|
|
17328
18070
|
self.SpawnInitModexPostfix=nil
|
|
17329
18071
|
self.SpawnInitAirbase=nil
|
|
17330
18072
|
self.TweakedTemplate=false
|
|
18073
|
+
self.SpawnRandomCallsign=false
|
|
17331
18074
|
self.SpawnGroups={}
|
|
17332
18075
|
else
|
|
17333
18076
|
error("SPAWN:New: There is no group declared in the mission editor with SpawnTemplatePrefix = '"..SpawnTemplatePrefix.."'")
|
|
@@ -17617,6 +18360,18 @@ self:_RandomizeZones(SpawnGroupID)
|
|
|
17617
18360
|
end
|
|
17618
18361
|
return self
|
|
17619
18362
|
end
|
|
18363
|
+
function SPAWN:InitRandomizeCallsign()
|
|
18364
|
+
self.SpawnRandomCallsign=true
|
|
18365
|
+
return self
|
|
18366
|
+
end
|
|
18367
|
+
function SPAWN:InitCallSign(ID,Name,Minor,Major)
|
|
18368
|
+
self.SpawnInitCallSign=true
|
|
18369
|
+
self.SpawnInitCallSignID=ID or 1
|
|
18370
|
+
self.SpawnInitCallSignMinor=Minor or 1
|
|
18371
|
+
self.SpawnInitCallSignMajor=Major or 1
|
|
18372
|
+
self.SpawnInitCallSignName=string.lower(Name)or"enfield"
|
|
18373
|
+
return self
|
|
18374
|
+
end
|
|
17620
18375
|
function SPAWN:InitPositionCoordinate(Coordinate)
|
|
17621
18376
|
self:T({self.SpawnTemplatePrefix,Coordinate:GetVec2()})
|
|
17622
18377
|
self:InitPositionVec2(Coordinate:GetVec2())
|
|
@@ -18738,19 +19493,133 @@ SpawnTemplate.units[UnitID].name=string.format('%s#%03d-%02d',UnitPrefix,SpawnIn
|
|
|
18738
19493
|
SpawnTemplate.units[UnitID].unitId=nil
|
|
18739
19494
|
end
|
|
18740
19495
|
end
|
|
19496
|
+
if self.SpawnRandomCallsign and SpawnTemplate.units[1].callsign then
|
|
19497
|
+
if type(SpawnTemplate.units[1].callsign)~="number"then
|
|
19498
|
+
local min=1
|
|
19499
|
+
local max=8
|
|
19500
|
+
local ctable=CALLSIGN.Aircraft
|
|
19501
|
+
if string.find(SpawnTemplate.units[1].type,"A-10",1,true)then
|
|
19502
|
+
max=12
|
|
19503
|
+
end
|
|
19504
|
+
if string.find(SpawnTemplate.units[1].type,"18",1,true)then
|
|
19505
|
+
min=9
|
|
19506
|
+
max=20
|
|
19507
|
+
ctable=CALLSIGN.F18
|
|
19508
|
+
end
|
|
19509
|
+
if string.find(SpawnTemplate.units[1].type,"16",1,true)then
|
|
19510
|
+
min=9
|
|
19511
|
+
max=20
|
|
19512
|
+
ctable=CALLSIGN.F16
|
|
19513
|
+
end
|
|
19514
|
+
if SpawnTemplate.units[1].type=="F-15E"then
|
|
19515
|
+
min=9
|
|
19516
|
+
max=18
|
|
19517
|
+
ctable=CALLSIGN.F15E
|
|
19518
|
+
end
|
|
19519
|
+
local callsignnr=math.random(min,max)
|
|
19520
|
+
local callsignname="Enfield"
|
|
19521
|
+
for name,value in pairs(ctable)do
|
|
19522
|
+
if value==callsignnr then
|
|
19523
|
+
callsignname=name
|
|
19524
|
+
end
|
|
19525
|
+
end
|
|
19526
|
+
for UnitID=1,#SpawnTemplate.units do
|
|
19527
|
+
SpawnTemplate.units[UnitID].callsign[1]=callsignnr
|
|
19528
|
+
SpawnTemplate.units[UnitID].callsign[2]=UnitID
|
|
19529
|
+
SpawnTemplate.units[UnitID].callsign[3]="1"
|
|
19530
|
+
SpawnTemplate.units[UnitID].callsign["name"]=tostring(callsignname)..tostring(UnitID).."1"
|
|
19531
|
+
end
|
|
19532
|
+
else
|
|
19533
|
+
for UnitID=1,#SpawnTemplate.units do
|
|
19534
|
+
SpawnTemplate.units[UnitID].callsign=math.random(1,999)
|
|
19535
|
+
end
|
|
19536
|
+
end
|
|
19537
|
+
end
|
|
19538
|
+
if self.SpawnInitCallSign then
|
|
19539
|
+
for UnitID=1,#SpawnTemplate.units do
|
|
19540
|
+
local Callsign=SpawnTemplate.units[UnitID].callsign
|
|
19541
|
+
if Callsign and type(Callsign)~="number"then
|
|
19542
|
+
SpawnTemplate.units[UnitID].callsign[1]=self.SpawnInitCallSignID
|
|
19543
|
+
SpawnTemplate.units[UnitID].callsign[2]=self.SpawnInitCallSignMinor
|
|
19544
|
+
SpawnTemplate.units[UnitID].callsign[3]=self.SpawnInitCallSignMajor
|
|
19545
|
+
SpawnTemplate.units[UnitID].callsign["name"]=string.format("%s%d%d",self.SpawnInitCallSignName,self.SpawnInitCallSignMinor,self.SpawnInitCallSignMajor)
|
|
19546
|
+
end
|
|
19547
|
+
end
|
|
19548
|
+
end
|
|
18741
19549
|
for UnitID=1,#SpawnTemplate.units do
|
|
18742
19550
|
local Callsign=SpawnTemplate.units[UnitID].callsign
|
|
18743
19551
|
if Callsign then
|
|
18744
|
-
if type(Callsign)~="number"then
|
|
19552
|
+
if type(Callsign)~="number"and not self.SpawnInitCallSign then
|
|
18745
19553
|
Callsign[2]=((SpawnIndex-1)%10)+1
|
|
18746
19554
|
local CallsignName=SpawnTemplate.units[UnitID].callsign["name"]
|
|
18747
19555
|
CallsignName=string.match(CallsignName,"^(%a+)")
|
|
18748
19556
|
local CallsignLen=CallsignName:len()
|
|
19557
|
+
SpawnTemplate.units[UnitID].callsign[2]=UnitID
|
|
18749
19558
|
SpawnTemplate.units[UnitID].callsign["name"]=CallsignName:sub(1,CallsignLen)..SpawnTemplate.units[UnitID].callsign[2]..SpawnTemplate.units[UnitID].callsign[3]
|
|
18750
|
-
|
|
19559
|
+
elseif type(Callsign)=="number"then
|
|
18751
19560
|
SpawnTemplate.units[UnitID].callsign=Callsign+SpawnIndex
|
|
18752
19561
|
end
|
|
18753
19562
|
end
|
|
19563
|
+
local AddProps=SpawnTemplate.units[UnitID].AddPropAircraft
|
|
19564
|
+
if AddProps then
|
|
19565
|
+
if SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 then
|
|
19566
|
+
if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16)~=nil then
|
|
19567
|
+
local octal=SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16
|
|
19568
|
+
local decimal=UTILS.OctalToDecimal(octal)+UnitID-1
|
|
19569
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16=string.format("%05d",UTILS.DecimalToOctal(decimal))
|
|
19570
|
+
else
|
|
19571
|
+
local STN=math.floor(UTILS.RandomGaussian(4088/2,nil,1000,4088))
|
|
19572
|
+
STN=STN+UnitID-1
|
|
19573
|
+
local OSTN=UTILS.DecimalToOctal(STN)
|
|
19574
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16=string.format("%05d",OSTN)
|
|
19575
|
+
end
|
|
19576
|
+
end
|
|
19577
|
+
if SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN then
|
|
19578
|
+
if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN)~=nil then
|
|
19579
|
+
local octal=SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN
|
|
19580
|
+
local decimal=UTILS.OctalToDecimal(octal)+UnitID-1
|
|
19581
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN=string.format("%04d",UTILS.DecimalToOctal(decimal))
|
|
19582
|
+
else
|
|
19583
|
+
local STN=math.floor(UTILS.RandomGaussian(504/2,nil,100,504))
|
|
19584
|
+
STN=STN+UnitID-1
|
|
19585
|
+
local OSTN=UTILS.DecimalToOctal(STN)
|
|
19586
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN=string.format("%04d",OSTN)
|
|
19587
|
+
end
|
|
19588
|
+
end
|
|
19589
|
+
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber and type(Callsign)~="number"then
|
|
19590
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber=SpawnTemplate.units[UnitID].callsign[2]..SpawnTemplate.units[UnitID].callsign[3]
|
|
19591
|
+
end
|
|
19592
|
+
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignLabel and type(Callsign)~="number"then
|
|
19593
|
+
local CallsignName=SpawnTemplate.units[UnitID].callsign["name"]
|
|
19594
|
+
CallsignName=string.match(CallsignName,"^(%a+)")
|
|
19595
|
+
local label="NY"
|
|
19596
|
+
if not string.find(CallsignName," ")then
|
|
19597
|
+
label=string.upper(string.match(CallsignName,"^%a")..string.match(CallsignName,"%a$"))
|
|
19598
|
+
end
|
|
19599
|
+
SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignLabel=label
|
|
19600
|
+
end
|
|
19601
|
+
if SpawnTemplate.units[UnitID].datalinks and SpawnTemplate.units[UnitID].datalinks.Link16 and SpawnTemplate.units[UnitID].datalinks.Link16.settings then
|
|
19602
|
+
SpawnTemplate.units[UnitID].datalinks.Link16.settings.flightLead=UnitID==1 and true or false
|
|
19603
|
+
end
|
|
19604
|
+
if SpawnTemplate.units[UnitID].datalinks and SpawnTemplate.units[UnitID].datalinks.SADL and SpawnTemplate.units[UnitID].datalinks.SADL.settings then
|
|
19605
|
+
SpawnTemplate.units[UnitID].datalinks.SADL.settings.flightLead=UnitID==1 and true or false
|
|
19606
|
+
end
|
|
19607
|
+
end
|
|
19608
|
+
end
|
|
19609
|
+
for UnitID=1,#SpawnTemplate.units do
|
|
19610
|
+
if SpawnTemplate.units[UnitID].datalinks and SpawnTemplate.units[UnitID].datalinks.Link16 and SpawnTemplate.units[UnitID].datalinks.Link16.network then
|
|
19611
|
+
local team={}
|
|
19612
|
+
local isF16=string.find(SpawnTemplate.units[UnitID].type,"F-16",1,true)and true or false
|
|
19613
|
+
for ID=1,#SpawnTemplate.units do
|
|
19614
|
+
local member={}
|
|
19615
|
+
member.missionUnitId=ID
|
|
19616
|
+
if isF16 then
|
|
19617
|
+
member.TDOA=true
|
|
19618
|
+
end
|
|
19619
|
+
table.insert(team,member)
|
|
19620
|
+
end
|
|
19621
|
+
SpawnTemplate.units[UnitID].datalinks.Link16.network.teamMembers=team
|
|
19622
|
+
end
|
|
18754
19623
|
end
|
|
18755
19624
|
self:T3({"Template:",SpawnTemplate})
|
|
18756
19625
|
return SpawnTemplate
|
|
@@ -19437,11 +20306,11 @@ function SPOT:onafterLasing(From,Event,To)
|
|
|
19437
20306
|
self:T({From,Event,To})
|
|
19438
20307
|
if self.Lasing then
|
|
19439
20308
|
if self.Target and self.Target:IsAlive()then
|
|
19440
|
-
self.SpotIR:setPoint(self.Target:GetPointVec3():AddY(1):AddY(math.random(-100,100)/
|
|
20309
|
+
self.SpotIR:setPoint(self.Target:GetPointVec3():AddY(1):AddY(math.random(-100,100)/200):AddX(math.random(-100,100)/200):GetVec3())
|
|
19441
20310
|
self.SpotLaser:setPoint(self.Target:GetPointVec3():AddY(1):GetVec3())
|
|
19442
20311
|
self:__Lasing(0.2)
|
|
19443
20312
|
elseif self.TargetCoord then
|
|
19444
|
-
local irvec3={x=self.TargetCoord.x+math.random(-100,100)/
|
|
20313
|
+
local irvec3={x=self.TargetCoord.x+math.random(-100,100)/200,y=self.TargetCoord.y+math.random(-100,100)/200,z=self.TargetCoord.z}
|
|
19445
20314
|
local lsvec3={x=self.TargetCoord.x,y=self.TargetCoord.y,z=self.TargetCoord.z}
|
|
19446
20315
|
self.SpotIR:setPoint(irvec3)
|
|
19447
20316
|
self.SpotLaser:setPoint(lsvec3)
|
|
@@ -19824,7 +20693,7 @@ OBJECT={
|
|
|
19824
20693
|
ClassName="OBJECT",
|
|
19825
20694
|
ObjectName="",
|
|
19826
20695
|
}
|
|
19827
|
-
function OBJECT:New(ObjectName
|
|
20696
|
+
function OBJECT:New(ObjectName)
|
|
19828
20697
|
local self=BASE:Inherit(self,BASE:New())
|
|
19829
20698
|
self:F2(ObjectName)
|
|
19830
20699
|
self.ObjectName=ObjectName
|
|
@@ -19836,7 +20705,7 @@ if DCSObject then
|
|
|
19836
20705
|
local ObjectID=DCSObject:getID()
|
|
19837
20706
|
return ObjectID
|
|
19838
20707
|
end
|
|
19839
|
-
|
|
20708
|
+
self:E({"Cannot GetID",Name=self.ObjectName,Class=self:GetClassName()})
|
|
19840
20709
|
return nil
|
|
19841
20710
|
end
|
|
19842
20711
|
function OBJECT:Destroy()
|
|
@@ -19845,7 +20714,7 @@ if DCSObject then
|
|
|
19845
20714
|
DCSObject:destroy(false)
|
|
19846
20715
|
return true
|
|
19847
20716
|
end
|
|
19848
|
-
|
|
20717
|
+
self:E({"Cannot Destroy",Name=self.ObjectName,Class=self:GetClassName()})
|
|
19849
20718
|
return nil
|
|
19850
20719
|
end
|
|
19851
20720
|
IDENTIFIABLE={
|
|
@@ -23055,7 +23924,7 @@ if DCSControllable then
|
|
|
23055
23924
|
local Controller=self:_GetController()
|
|
23056
23925
|
if Controller then
|
|
23057
23926
|
if self:IsAir()then
|
|
23058
|
-
self:SetOption(AI.Option.Air.
|
|
23927
|
+
self:SetOption(AI.Option.Air.id.MISSILE_ATTACK,range)
|
|
23059
23928
|
end
|
|
23060
23929
|
end
|
|
23061
23930
|
return self
|
|
@@ -24577,6 +25446,7 @@ if vec3 then
|
|
|
24577
25446
|
local coord=COORDINATE:NewFromVec3(vec3)
|
|
24578
25447
|
local Heading=self:GetHeading()
|
|
24579
25448
|
coord.Heading=Heading
|
|
25449
|
+
return coord
|
|
24580
25450
|
else
|
|
24581
25451
|
BASE:E({"Cannot GetAverageCoordinate",Group=self,Alive=self:IsAlive()})
|
|
24582
25452
|
return nil
|
|
@@ -25553,6 +26423,34 @@ local tankertask=self:EnRouteTaskTanker()
|
|
|
25553
26423
|
self:PushTask(tankertask,delay+2)
|
|
25554
26424
|
return self
|
|
25555
26425
|
end
|
|
26426
|
+
function GROUP:GetGroupSTN()
|
|
26427
|
+
local tSTN={}
|
|
26428
|
+
local units=self:GetUnits()
|
|
26429
|
+
local gname=self:GetName()
|
|
26430
|
+
gname=string.gsub(gname,"(#%d+)$","")
|
|
26431
|
+
local report=REPORT:New()
|
|
26432
|
+
report:Add("Link16 S/TN Report")
|
|
26433
|
+
report:Add("Group: "..gname)
|
|
26434
|
+
report:Add("==================")
|
|
26435
|
+
for _,_unit in pairs(units)do
|
|
26436
|
+
local unit=_unit
|
|
26437
|
+
if unit and unit:IsAlive()then
|
|
26438
|
+
local STN,VCL,VCN,Lead=unit:GetSTN()
|
|
26439
|
+
local name=unit:GetName()
|
|
26440
|
+
tSTN[name]={
|
|
26441
|
+
STN=STN,
|
|
26442
|
+
VCL=VCL,
|
|
26443
|
+
VCN=VCN,
|
|
26444
|
+
Lead=Lead,
|
|
26445
|
+
}
|
|
26446
|
+
local lead=Lead==true and"(*)"or""
|
|
26447
|
+
report:Add(string.format("| %s%s %s %s",tostring(VCL),tostring(VCN),tostring(STN),lead))
|
|
26448
|
+
end
|
|
26449
|
+
end
|
|
26450
|
+
report:Add("==================")
|
|
26451
|
+
local text=report:Text()
|
|
26452
|
+
return tSTN,text
|
|
26453
|
+
end
|
|
25556
26454
|
UNIT={
|
|
25557
26455
|
ClassName="UNIT",
|
|
25558
26456
|
UnitName=nil,
|
|
@@ -26347,6 +27245,30 @@ local name=self.UnitName
|
|
|
26347
27245
|
local skill=_DATABASE.Templates.Units[name].Template.skill or"Random"
|
|
26348
27246
|
return skill
|
|
26349
27247
|
end
|
|
27248
|
+
function UNIT:GetSTN()
|
|
27249
|
+
self:F2(self.UnitName)
|
|
27250
|
+
local STN=nil
|
|
27251
|
+
local VCL=nil
|
|
27252
|
+
local VCN=nil
|
|
27253
|
+
local FGL=false
|
|
27254
|
+
local template=self:GetTemplate()
|
|
27255
|
+
if template.AddPropAircraft then
|
|
27256
|
+
if template.AddPropAircraft.STN_L16 then
|
|
27257
|
+
STN=template.AddPropAircraft.STN_L16
|
|
27258
|
+
elseif template.AddPropAircraft.SADL_TN then
|
|
27259
|
+
STN=template.AddPropAircraft.SADL_TN
|
|
27260
|
+
end
|
|
27261
|
+
VCN=template.AddPropAircraft.VoiceCallsignNumber
|
|
27262
|
+
VCL=template.AddPropAircraft.VoiceCallsignLabel
|
|
27263
|
+
end
|
|
27264
|
+
if template.datalinks and template.datalinks.Link16 and template.datalinks.Link16.settings then
|
|
27265
|
+
FGL=template.datalinks.Link16.settings.flightLead
|
|
27266
|
+
end
|
|
27267
|
+
if template.datalinks and template.datalinks.SADL and template.datalinks.SADL.settings then
|
|
27268
|
+
FGL=template.datalinks.SADL.settings.flightLead
|
|
27269
|
+
end
|
|
27270
|
+
return STN,VCL,VCN,FGL
|
|
27271
|
+
end
|
|
26350
27272
|
CLIENT={
|
|
26351
27273
|
ClassName="CLIENT",
|
|
26352
27274
|
ClientName=nil,
|
|
@@ -26870,6 +27792,13 @@ AIRBASE.Normandy={
|
|
|
26870
27792
|
["Broglie"]="Broglie",
|
|
26871
27793
|
["Bernay_Saint_Martin"]="Bernay Saint Martin",
|
|
26872
27794
|
["Saint_Andre_de_lEure"]="Saint-Andre-de-lEure",
|
|
27795
|
+
["Biggin_Hill"]="Biggin Hill",
|
|
27796
|
+
["Manston"]="Manston",
|
|
27797
|
+
["Detling"]="Detling",
|
|
27798
|
+
["Lympne"]="Lympne",
|
|
27799
|
+
["Abbeville_Drucat"]="Abbeville Drucat",
|
|
27800
|
+
["Merville_Calonne"]="Merville Calonne",
|
|
27801
|
+
["Saint_Omer_Wizernes"]="Saint-Omer Wizernes",
|
|
26873
27802
|
}
|
|
26874
27803
|
AIRBASE.PersianGulf={
|
|
26875
27804
|
["Abu_Dhabi_International_Airport"]="Abu Dhabi Intl",
|
|
@@ -27140,7 +28069,7 @@ end
|
|
|
27140
28069
|
function AIRBASE:GetWarehouse()
|
|
27141
28070
|
local warehouse=nil
|
|
27142
28071
|
local airbase=self:GetDCSObject()
|
|
27143
|
-
if airbase then
|
|
28072
|
+
if airbase and Airbase.getWarehouse then
|
|
27144
28073
|
warehouse=airbase:getWarehouse()
|
|
27145
28074
|
end
|
|
27146
28075
|
return warehouse
|
|
@@ -28390,6 +29319,13 @@ self.launcherUnit=UNIT:Find(self.launcher)
|
|
|
28390
29319
|
end
|
|
28391
29320
|
self.coordinate=COORDINATE:NewFromVec3(self.launcher:getPoint())
|
|
28392
29321
|
self.lid=string.format("[%s] %s | ",self.typeName,self.name)
|
|
29322
|
+
if self.launcherUnit then
|
|
29323
|
+
self.releaseHeading=self.launcherUnit:GetHeading()
|
|
29324
|
+
self.releaseAltitudeASL=self.launcherUnit:GetAltitude()
|
|
29325
|
+
self.releaseAltitudeAGL=self.launcherUnit:GetAltitude(true)
|
|
29326
|
+
self.releaseCoordinate=self.launcherUnit:GetCoordinate()
|
|
29327
|
+
self.releasePitch=self.launcherUnit:GetPitch()
|
|
29328
|
+
end
|
|
28393
29329
|
self:SetTimeStepTrack()
|
|
28394
29330
|
self:SetDistanceInterceptPoint()
|
|
28395
29331
|
local text=string.format("Weapon v%s\nName=%s, TypeName=%s, Category=%s, Coalition=%d, Country=%d, Launcher=%s",
|
|
@@ -28445,7 +29381,7 @@ local target=nil
|
|
|
28445
29381
|
if self.weapon then
|
|
28446
29382
|
local object=self.weapon:getTarget()
|
|
28447
29383
|
if object then
|
|
28448
|
-
local category=
|
|
29384
|
+
local category=Object.getCategory(object)
|
|
28449
29385
|
local name=object:getName()
|
|
28450
29386
|
self:T(self.lid..string.format("Got Target Object %s, category=%d",object:getName(),category))
|
|
28451
29387
|
if category==Object.Category.UNIT then
|
|
@@ -28535,6 +29471,26 @@ end
|
|
|
28535
29471
|
function WEAPON:GetImpactCoordinate()
|
|
28536
29472
|
return self.impactCoord
|
|
28537
29473
|
end
|
|
29474
|
+
function WEAPON:GetReleaseHeading(AccountForMagneticInclination)
|
|
29475
|
+
AccountForMagneticInclination=AccountForMagneticInclination or true
|
|
29476
|
+
if AccountForMagneticInclination then return UTILS.ClampAngle(self.releaseHeading-UTILS.GetMagneticDeclination())else return UTILS.ClampAngle(self.releaseHeading)end
|
|
29477
|
+
end
|
|
29478
|
+
function WEAPON:GetReleaseAltitudeASL()
|
|
29479
|
+
return self.releaseAltitudeASL
|
|
29480
|
+
end
|
|
29481
|
+
function WEAPON:GetReleaseAltitudeAGL()
|
|
29482
|
+
return self.releaseAltitudeAGL
|
|
29483
|
+
end
|
|
29484
|
+
function WEAPON:GetReleaseCoordinate()
|
|
29485
|
+
return self.releaseCoordinate
|
|
29486
|
+
end
|
|
29487
|
+
function WEAPON:GetReleasePitch()
|
|
29488
|
+
return self.releasePitch
|
|
29489
|
+
end
|
|
29490
|
+
function WEAPON:GetImpactHeading(AccountForMagneticInclination)
|
|
29491
|
+
AccountForMagneticInclination=AccountForMagneticInclination or true
|
|
29492
|
+
if AccountForMagneticInclination then return UTILS.ClampAngle(self.impactHeading-UTILS.GetMagneticDeclination())else return self.impactHeading end
|
|
29493
|
+
end
|
|
28538
29494
|
function WEAPON:InAir()
|
|
28539
29495
|
local inAir=nil
|
|
28540
29496
|
if self.weapon then
|
|
@@ -28606,6 +29562,7 @@ if status then
|
|
|
28606
29562
|
self.pos3=pos3
|
|
28607
29563
|
self.vec3=UTILS.DeepCopy(self.pos3.p)
|
|
28608
29564
|
self.coordinate:UpdateFromVec3(self.vec3)
|
|
29565
|
+
self.last_velocity=self.weapon:getVelocity()
|
|
28609
29566
|
self.tracking=true
|
|
28610
29567
|
if self.trackFunc then
|
|
28611
29568
|
self.trackFunc(self,unpack(self.trackArg))
|
|
@@ -28633,6 +29590,7 @@ self:I(self.lid..string.format("FF d(ip, vec3)=%.3f meters",d))
|
|
|
28633
29590
|
end
|
|
28634
29591
|
self.impactVec3=ip or self.vec3
|
|
28635
29592
|
self.impactCoord=COORDINATE:NewFromVec3(self.vec3)
|
|
29593
|
+
self.impactHeading=UTILS.VecHdg(self.last_velocity)
|
|
28636
29594
|
if self.impactMark then
|
|
28637
29595
|
self.impactCoord:MarkToAll(string.format("Impact point of weapon %s\ntype=%s\nlauncher=%s",self.name,self.typeName,self.launcherName))
|
|
28638
29596
|
end
|
|
@@ -29102,7 +30060,9 @@ STORAGE.version="0.0.1"
|
|
|
29102
30060
|
function STORAGE:New(AirbaseName)
|
|
29103
30061
|
local self=BASE:Inherit(self,BASE:New())
|
|
29104
30062
|
self.airbase=Airbase.getByName(AirbaseName)
|
|
30063
|
+
if Airbase.getWarehouse then
|
|
29105
30064
|
self.warehouse=self.airbase:getWarehouse()
|
|
30065
|
+
end
|
|
29106
30066
|
self.lid=string.format("STORAGE %s",AirbaseName)
|
|
29107
30067
|
return self
|
|
29108
30068
|
end
|
|
@@ -32248,7 +33208,7 @@ self:__CalculateHitZone(20,SEADWeapon,pos0,fheight,SEADGroup,SEADWeaponName)
|
|
|
32248
33208
|
end
|
|
32249
33209
|
return self
|
|
32250
33210
|
end
|
|
32251
|
-
local targetcat=
|
|
33211
|
+
local targetcat=Object.getCategory(_target)
|
|
32252
33212
|
local _targetUnit=nil
|
|
32253
33213
|
local _targetgroup=nil
|
|
32254
33214
|
self:T(string.format("*** Targetcat = %d",targetcat))
|
|
@@ -33391,7 +34351,7 @@ AirbaseNames=nil,
|
|
|
33391
34351
|
}
|
|
33392
34352
|
function ATC_GROUND:New(Airbases,AirbaseList)
|
|
33393
34353
|
local self=BASE:Inherit(self,BASE:New())
|
|
33394
|
-
self:
|
|
34354
|
+
self:T({self.ClassName,Airbases})
|
|
33395
34355
|
self.Airbases=Airbases
|
|
33396
34356
|
self.AirbaseList=AirbaseList
|
|
33397
34357
|
self.SetClient=SET_CLIENT:New():FilterCategories("plane"):FilterStart()
|
|
@@ -33470,7 +34430,7 @@ function(Client)
|
|
|
33470
34430
|
if Client:IsAlive()then
|
|
33471
34431
|
local IsOnGround=Client:InAir()==false
|
|
33472
34432
|
for AirbaseID,AirbaseMeta in pairs(self.Airbases)do
|
|
33473
|
-
self:
|
|
34433
|
+
self:T(AirbaseID,AirbaseMeta.KickSpeed)
|
|
33474
34434
|
if AirbaseMeta.Monitor==true and Client:IsInZone(AirbaseMeta.ZoneBoundary)then
|
|
33475
34435
|
local NotInRunwayZone=true
|
|
33476
34436
|
for ZoneRunwayID,ZoneRunway in pairs(AirbaseMeta.ZoneRunways)do
|
|
@@ -33479,7 +34439,7 @@ end
|
|
|
33479
34439
|
if NotInRunwayZone then
|
|
33480
34440
|
if IsOnGround then
|
|
33481
34441
|
local Taxi=Client:GetState(self,"Taxi")
|
|
33482
|
-
self:
|
|
34442
|
+
self:T(Taxi)
|
|
33483
34443
|
if Taxi==false then
|
|
33484
34444
|
local Velocity=VELOCITY:New(AirbaseMeta.KickSpeed or self.KickSpeed)
|
|
33485
34445
|
Client:Message("Welcome to "..AirbaseID..". The maximum taxiing speed is "..
|
|
@@ -33599,12 +34559,18 @@ KickSpeed=nil,
|
|
|
33599
34559
|
}
|
|
33600
34560
|
function ATC_GROUND_UNIVERSAL:New(AirbaseList)
|
|
33601
34561
|
local self=BASE:Inherit(self,BASE:New())
|
|
33602
|
-
self:
|
|
34562
|
+
self:T({self.ClassName})
|
|
33603
34563
|
self.Airbases={}
|
|
33604
34564
|
for _name,_ in pairs(_DATABASE.AIRBASES)do
|
|
33605
34565
|
self.Airbases[_name]={}
|
|
33606
34566
|
end
|
|
33607
34567
|
self.AirbaseList=AirbaseList
|
|
34568
|
+
if not self.AirbaseList then
|
|
34569
|
+
self.AirbaseList={}
|
|
34570
|
+
for _name,_ in pairs(_DATABASE.AIRBASES)do
|
|
34571
|
+
self.AirbaseList[_name]=_name
|
|
34572
|
+
end
|
|
34573
|
+
end
|
|
33608
34574
|
self.SetClient=SET_CLIENT:New():FilterCategories("plane"):FilterStart()
|
|
33609
34575
|
for AirbaseID,Airbase in pairs(self.Airbases)do
|
|
33610
34576
|
if Airbase.ZoneBoundary then
|
|
@@ -33703,12 +34669,13 @@ self:SetMaximumKickSpeed(UTILS.MiphToMps(MaximumKickSpeedMiph),Airbase)
|
|
|
33703
34669
|
return self
|
|
33704
34670
|
end
|
|
33705
34671
|
function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
|
34672
|
+
self:I("_AirbaseMonitor")
|
|
33706
34673
|
self.SetClient:ForEachClient(
|
|
33707
34674
|
function(Client)
|
|
33708
34675
|
if Client:IsAlive()then
|
|
33709
34676
|
local IsOnGround=Client:InAir()==false
|
|
33710
34677
|
for AirbaseID,AirbaseMeta in pairs(self.Airbases)do
|
|
33711
|
-
self:
|
|
34678
|
+
self:T(AirbaseID,AirbaseMeta.KickSpeed)
|
|
33712
34679
|
if AirbaseMeta.Monitor==true and Client:IsInZone(AirbaseMeta.ZoneBoundary)then
|
|
33713
34680
|
local NotInRunwayZone=true
|
|
33714
34681
|
if AirbaseMeta.ZoneRunways then
|
|
@@ -33720,7 +34687,7 @@ end
|
|
|
33720
34687
|
if NotInRunwayZone then
|
|
33721
34688
|
if IsOnGround then
|
|
33722
34689
|
local Taxi=Client:GetState(self,"Taxi")
|
|
33723
|
-
self:
|
|
34690
|
+
self:T(Taxi)
|
|
33724
34691
|
if Taxi==false then
|
|
33725
34692
|
local Velocity=VELOCITY:New(AirbaseMeta.KickSpeed or self.KickSpeed)
|
|
33726
34693
|
Client:Message("Welcome to "..AirbaseID..". The maximum taxiing speed is "..
|
|
@@ -33832,7 +34799,7 @@ return true
|
|
|
33832
34799
|
end
|
|
33833
34800
|
function ATC_GROUND_UNIVERSAL:Start(RepeatScanSeconds)
|
|
33834
34801
|
RepeatScanSeconds=RepeatScanSeconds or 0.05
|
|
33835
|
-
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,
|
|
34802
|
+
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,RepeatScanSeconds)
|
|
33836
34803
|
return self
|
|
33837
34804
|
end
|
|
33838
34805
|
ATC_GROUND_CAUCASUS={
|
|
@@ -33846,7 +34813,7 @@ return self
|
|
|
33846
34813
|
end
|
|
33847
34814
|
function ATC_GROUND_CAUCASUS:Start(RepeatScanSeconds)
|
|
33848
34815
|
RepeatScanSeconds=RepeatScanSeconds or 0.05
|
|
33849
|
-
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,
|
|
34816
|
+
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,RepeatScanSeconds)
|
|
33850
34817
|
end
|
|
33851
34818
|
ATC_GROUND_NEVADA={
|
|
33852
34819
|
ClassName="ATC_GROUND_NEVADA",
|
|
@@ -33859,7 +34826,7 @@ return self
|
|
|
33859
34826
|
end
|
|
33860
34827
|
function ATC_GROUND_NEVADA:Start(RepeatScanSeconds)
|
|
33861
34828
|
RepeatScanSeconds=RepeatScanSeconds or 0.05
|
|
33862
|
-
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,
|
|
34829
|
+
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,RepeatScanSeconds)
|
|
33863
34830
|
end
|
|
33864
34831
|
ATC_GROUND_NORMANDY={
|
|
33865
34832
|
ClassName="ATC_GROUND_NORMANDY",
|
|
@@ -33872,7 +34839,7 @@ return self
|
|
|
33872
34839
|
end
|
|
33873
34840
|
function ATC_GROUND_NORMANDY:Start(RepeatScanSeconds)
|
|
33874
34841
|
RepeatScanSeconds=RepeatScanSeconds or 0.05
|
|
33875
|
-
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,
|
|
34842
|
+
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,RepeatScanSeconds)
|
|
33876
34843
|
end
|
|
33877
34844
|
ATC_GROUND_PERSIANGULF={
|
|
33878
34845
|
ClassName="ATC_GROUND_PERSIANGULF",
|
|
@@ -33884,20 +34851,20 @@ self:SetMaximumKickSpeedKmph(150)
|
|
|
33884
34851
|
end
|
|
33885
34852
|
function ATC_GROUND_PERSIANGULF:Start(RepeatScanSeconds)
|
|
33886
34853
|
RepeatScanSeconds=RepeatScanSeconds or 0.05
|
|
33887
|
-
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,
|
|
34854
|
+
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,RepeatScanSeconds)
|
|
33888
34855
|
end
|
|
33889
34856
|
ATC_GROUND_MARIANAISLANDS={
|
|
33890
34857
|
ClassName="ATC_GROUND_MARIANAISLANDS",
|
|
33891
34858
|
}
|
|
33892
34859
|
function ATC_GROUND_MARIANAISLANDS:New(AirbaseNames)
|
|
33893
|
-
local self=BASE:Inherit(self,ATC_GROUND_UNIVERSAL:New(
|
|
34860
|
+
local self=BASE:Inherit(self,ATC_GROUND_UNIVERSAL:New(AirbaseNames))
|
|
33894
34861
|
self:SetKickSpeedKmph(50)
|
|
33895
34862
|
self:SetMaximumKickSpeedKmph(150)
|
|
33896
34863
|
return self
|
|
33897
34864
|
end
|
|
33898
34865
|
function ATC_GROUND_MARIANAISLANDS:Start(RepeatScanSeconds)
|
|
33899
34866
|
RepeatScanSeconds=RepeatScanSeconds or 0.05
|
|
33900
|
-
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,
|
|
34867
|
+
self.AirbaseMonitor=SCHEDULER:New(self,self._AirbaseMonitor,{self},0,RepeatScanSeconds)
|
|
33901
34868
|
end
|
|
33902
34869
|
do
|
|
33903
34870
|
DETECTION_BASE={
|
|
@@ -34050,6 +35017,28 @@ DetectionAccepted=false
|
|
|
34050
35017
|
end
|
|
34051
35018
|
end
|
|
34052
35019
|
end
|
|
35020
|
+
if self.RadarBlur then
|
|
35021
|
+
MESSAGE:New("Radar Blur",10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
|
35022
|
+
local minheight=self.RadarBlurMinHeight or 250
|
|
35023
|
+
local thresheight=self.RadarBlurThresHeight or 90
|
|
35024
|
+
local thresblur=self.RadarBlurThresBlur or 85
|
|
35025
|
+
local dist=math.floor(Distance)
|
|
35026
|
+
if dist<=20 then
|
|
35027
|
+
thresheight=(((dist*dist)/400)*thresheight)
|
|
35028
|
+
thresblur=(((dist*dist)/400)*thresblur)
|
|
35029
|
+
end
|
|
35030
|
+
local fheight=math.floor(math.random(1,10000)/100)
|
|
35031
|
+
local fblur=math.floor(math.random(1,10000)/100)
|
|
35032
|
+
local unit=UNIT:FindByName(DetectedObjectName)
|
|
35033
|
+
if unit and unit:IsAlive()then
|
|
35034
|
+
local AGL=unit:GetAltitude(true)
|
|
35035
|
+
MESSAGE:New("Unit "..DetectedObjectName.." is at "..math.floor(AGL).."m. Distance "..math.floor(Distance).."km.",10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
|
35036
|
+
MESSAGE:New(string.format("fheight = %d/%d | fblur = %d/%d",fheight,thresheight,fblur,thresblur),10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
|
35037
|
+
if fblur>thresblur then DetectionAccepted=false end
|
|
35038
|
+
if AGL<=minheight and fheight<thresheight then DetectionAccepted=false end
|
|
35039
|
+
MESSAGE:New("Detection Accepted = "..tostring(DetectionAccepted),10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
|
35040
|
+
end
|
|
35041
|
+
end
|
|
34053
35042
|
if not self.DetectedObjects[DetectedObjectName]and TargetIsVisible and self.DistanceProbability then
|
|
34054
35043
|
local DistanceFactor=Distance/4
|
|
34055
35044
|
local DistanceProbabilityReversed=(1-self.DistanceProbability)*DistanceFactor
|
|
@@ -34210,6 +35199,13 @@ self._.FilterCategories[FilterCategories]=FilterCategories
|
|
|
34210
35199
|
end
|
|
34211
35200
|
return self
|
|
34212
35201
|
end
|
|
35202
|
+
function DETECTION_BASE:SetRadarBlur(minheight,thresheight,thresblur)
|
|
35203
|
+
self.RadarBlur=true
|
|
35204
|
+
self.RadarBlurMinHeight=minheight or 250
|
|
35205
|
+
self.RadarBlurThresHeight=thresheight or 90
|
|
35206
|
+
self.RadarBlurThresBlur=thresblur or 85
|
|
35207
|
+
return self
|
|
35208
|
+
end
|
|
34213
35209
|
end
|
|
34214
35210
|
do
|
|
34215
35211
|
function DETECTION_BASE:SetRefreshTimeInterval(RefreshTimeInterval)
|
|
@@ -39511,6 +40507,7 @@ soundpath="Range Soundfiles/",
|
|
|
39511
40507
|
targetsheet=nil,
|
|
39512
40508
|
targetpath=nil,
|
|
39513
40509
|
targetprefix=nil,
|
|
40510
|
+
Coalition=nil,
|
|
39514
40511
|
}
|
|
39515
40512
|
RANGE.Defaults={
|
|
39516
40513
|
goodhitrange=25,
|
|
@@ -39580,10 +40577,11 @@ IRExitRange={filename="IR-ExitRange.ogg",duration=3.10},
|
|
|
39580
40577
|
RANGE.Names={}
|
|
39581
40578
|
RANGE.MenuF10={}
|
|
39582
40579
|
RANGE.MenuF10Root=nil
|
|
39583
|
-
RANGE.version="2.7.
|
|
39584
|
-
function RANGE:New(RangeName)
|
|
40580
|
+
RANGE.version="2.7.3"
|
|
40581
|
+
function RANGE:New(RangeName,Coalition)
|
|
39585
40582
|
local self=BASE:Inherit(self,FSM:New())
|
|
39586
40583
|
self.rangename=RangeName or"Practice Range"
|
|
40584
|
+
self.Coalition=Coalition
|
|
39587
40585
|
self.lid=string.format("RANGE %s | ",self.rangename)
|
|
39588
40586
|
local text=string.format("Script version %s - creating new RANGE object %s.",RANGE.version,self.rangename)
|
|
39589
40587
|
self:I(self.lid..text)
|
|
@@ -39838,6 +40836,10 @@ end
|
|
|
39838
40836
|
return self
|
|
39839
40837
|
end
|
|
39840
40838
|
function RANGE:SetSRSRangeControl(frequency,modulation,voice,culture,gender,relayunitname)
|
|
40839
|
+
if not self.instructmsrs then
|
|
40840
|
+
self:E(self.lid.."Use myrange:SetSRS() once first before using myrange:SetSRSRangeControl!")
|
|
40841
|
+
return self
|
|
40842
|
+
end
|
|
39841
40843
|
self.rangecontrolfreq=frequency or 256
|
|
39842
40844
|
self.controlmsrs:SetFrequencies(self.rangecontrolfreq)
|
|
39843
40845
|
self.controlmsrs:SetModulations(modulation or radio.modulation.AM)
|
|
@@ -39853,6 +40855,10 @@ end
|
|
|
39853
40855
|
return self
|
|
39854
40856
|
end
|
|
39855
40857
|
function RANGE:SetSRSRangeInstructor(frequency,modulation,voice,culture,gender,relayunitname)
|
|
40858
|
+
if not self.instructmsrs then
|
|
40859
|
+
self:E(self.lid.."Use myrange:SetSRS() once first before using myrange:SetSRSRangeInstructor!")
|
|
40860
|
+
return self
|
|
40861
|
+
end
|
|
39856
40862
|
self.instructorfreq=frequency or 305
|
|
39857
40863
|
self.instructmsrs:SetFrequencies(self.instructorfreq)
|
|
39858
40864
|
self.instructmsrs:SetModulations(modulation or radio.modulation.AM)
|
|
@@ -40118,7 +41124,13 @@ local _callsign=_unit:GetCallsign()
|
|
|
40118
41124
|
local text=string.format("Player %s, callsign %s entered unit %s (UID %d) of group %s (GID %d)",_playername,_callsign,_unitName,_uid,_group:GetName(),_gid)
|
|
40119
41125
|
self:T(self.lid..text)
|
|
40120
41126
|
self.strafeStatus[_uid]=nil
|
|
41127
|
+
if self.Coalition then
|
|
41128
|
+
if EventData.IniCoalition==self.Coalition then
|
|
40121
41129
|
self:ScheduleOnce(0.1,self._AddF10Commands,self,_unitName)
|
|
41130
|
+
end
|
|
41131
|
+
else
|
|
41132
|
+
self:ScheduleOnce(0.1,self._AddF10Commands,self,_unitName)
|
|
41133
|
+
end
|
|
40122
41134
|
self.PlayerSettings[_playername]={}
|
|
40123
41135
|
self.PlayerSettings[_playername].smokebombimpact=self.defaultsmokebomb
|
|
40124
41136
|
self.PlayerSettings[_playername].flaredirecthits=false
|
|
@@ -48155,11 +49167,22 @@ local _assetattribute
|
|
|
48155
49167
|
local _assetcategory
|
|
48156
49168
|
local _assetairstart=false
|
|
48157
49169
|
if _nassets>0 then
|
|
49170
|
+
local asset=_assets[1]
|
|
48158
49171
|
_assetattribute=_assets[1].attribute
|
|
48159
49172
|
_assetcategory=_assets[1].category
|
|
48160
49173
|
_assetairstart=_assets[1].takeoffType and _assets[1].takeoffType==COORDINATE.WaypointType.TurningPoint or false
|
|
48161
49174
|
if _assetcategory==Group.Category.AIRPLANE or _assetcategory==Group.Category.HELICOPTER then
|
|
48162
49175
|
if self.airbase and self.airbase:GetCoalition()==self:GetCoalition()then
|
|
49176
|
+
if self.airbase.storage then
|
|
49177
|
+
local nS=self.airbase.storage:GetAmount(asset.unittype)
|
|
49178
|
+
local nA=asset.nunits*request.nasset
|
|
49179
|
+
if nS<nA then
|
|
49180
|
+
local text=string.format("Warehouse %s: Request denied! DCS Warehouse has only %d assets of type %s ==> NOT enough to spawn the requested %d asset units (%d groups)",
|
|
49181
|
+
self.alias,nS,asset.unittype,nA,request.nasset)
|
|
49182
|
+
self:_InfoMessage(text,5)
|
|
49183
|
+
return false
|
|
49184
|
+
end
|
|
49185
|
+
end
|
|
48163
49186
|
if self:IsRunwayOperational()or _assetairstart then
|
|
48164
49187
|
if _assetairstart then
|
|
48165
49188
|
else
|
|
@@ -48221,6 +49244,7 @@ local text=string.format("Warehouse %s: Request denied! Not close enough to spaw
|
|
|
48221
49244
|
self:_InfoMessage(text,5)
|
|
48222
49245
|
return false
|
|
48223
49246
|
end
|
|
49247
|
+
elseif _assetcategory==Group.Category.AIRPLANE or _assetcategory==Group.Category.HELICOPTER then
|
|
48224
49248
|
end
|
|
48225
49249
|
end
|
|
48226
49250
|
request.cargoassets=_assets
|
|
@@ -50089,7 +51113,9 @@ MANTIS.SamData={
|
|
|
50089
51113
|
["SA-20A"]={Range=150,Blindspot=5,Height=27,Type="Long",Radar="S-300PMU1"},
|
|
50090
51114
|
["SA-20B"]={Range=200,Blindspot=4,Height=27,Type="Long",Radar="S-300PMU2"},
|
|
50091
51115
|
["HQ-2"]={Range=50,Blindspot=6,Height=35,Type="Medium",Radar="HQ_2_Guideline_LN"},
|
|
50092
|
-
["SHORAD"]={Range=3,Blindspot=0,Height=3,Type="Short",Radar="Igla"}
|
|
51116
|
+
["SHORAD"]={Range=3,Blindspot=0,Height=3,Type="Short",Radar="Igla"},
|
|
51117
|
+
["TAMIR IDFA"]={Range=20,Blindspot=0.6,Height=12.3,Type="Short",Radar="IRON_DOME_LN"},
|
|
51118
|
+
["STUNNER IDFA"]={Range=250,Blindspot=1,Height=45,Type="Long",Radar="DAVID_SLING_LN"},
|
|
50093
51119
|
}
|
|
50094
51120
|
MANTIS.SamDataHDS={
|
|
50095
51121
|
["SA-2 HDS"]={Range=56,Blindspot=7,Height=30,Type="Medium",Radar="V759"},
|
|
@@ -50237,7 +51263,7 @@ end
|
|
|
50237
51263
|
if self.HQ_Template_CC then
|
|
50238
51264
|
self.HQ_CC=GROUP:FindByName(self.HQ_Template_CC)
|
|
50239
51265
|
end
|
|
50240
|
-
self.version="0.8.
|
|
51266
|
+
self.version="0.8.15"
|
|
50241
51267
|
self:I(string.format("***** Starting MANTIS Version %s *****",self.version))
|
|
50242
51268
|
self:SetStartState("Stopped")
|
|
50243
51269
|
self:AddTransition("Stopped","Start","Running")
|
|
@@ -50268,11 +51294,13 @@ local radius=radius or 5000
|
|
|
50268
51294
|
self.grouping=radius
|
|
50269
51295
|
return self
|
|
50270
51296
|
end
|
|
50271
|
-
function MANTIS:AddScootZones(ZoneSet,Number)
|
|
51297
|
+
function MANTIS:AddScootZones(ZoneSet,Number,Random,Formation)
|
|
50272
51298
|
self:T(self.lid.." AddScootZones")
|
|
50273
51299
|
self.SkateZones=ZoneSet
|
|
50274
51300
|
self.SkateNumber=Number or 3
|
|
50275
51301
|
self.shootandscoot=true
|
|
51302
|
+
self.ScootRandom=Random
|
|
51303
|
+
self.ScootFormation=Formation or"Cone"
|
|
50276
51304
|
return self
|
|
50277
51305
|
end
|
|
50278
51306
|
function MANTIS:AddZones(AcceptZones,RejectZones,ConflictZones)
|
|
@@ -50972,8 +52000,8 @@ self.ShoradLink=true
|
|
|
50972
52000
|
self.Shorad.Groupset=self.ShoradGroupSet
|
|
50973
52001
|
self.Shorad.debug=self.debug
|
|
50974
52002
|
end
|
|
50975
|
-
if self.shootandscoot and self.SkateZones then
|
|
50976
|
-
self.Shorad:AddScootZones(self.SkateZones,self.SkateNumber or 3)
|
|
52003
|
+
if self.shootandscoot and self.SkateZones and self.Shorad then
|
|
52004
|
+
self.Shorad:AddScootZones(self.SkateZones,self.SkateNumber or 3,self.ScootRandom,self.ScootFormation)
|
|
50977
52005
|
end
|
|
50978
52006
|
self:__Status(-math.random(1,10))
|
|
50979
52007
|
return self
|
|
@@ -51080,6 +52108,9 @@ UseEmOnOff=true,
|
|
|
51080
52108
|
shootandscoot=false,
|
|
51081
52109
|
SkateNumber=3,
|
|
51082
52110
|
SkateZones=nil,
|
|
52111
|
+
minscootdist=100,
|
|
52112
|
+
minscootdist=3000,
|
|
52113
|
+
scootrandomcoord=false,
|
|
51083
52114
|
}
|
|
51084
52115
|
do
|
|
51085
52116
|
SHORAD.Harms={
|
|
@@ -51123,7 +52154,7 @@ self.DefenseLowProb=70
|
|
|
51123
52154
|
self.DefenseHighProb=90
|
|
51124
52155
|
self.UseEmOnOff=true
|
|
51125
52156
|
if UseEmOnOff==false then self.UseEmOnOff=UseEmOnOff end
|
|
51126
|
-
self:I("*** SHORAD - Started Version 0.3.
|
|
52157
|
+
self:I("*** SHORAD - Started Version 0.3.4")
|
|
51127
52158
|
self.lid=string.format("SHORAD %s | ",self.name)
|
|
51128
52159
|
self:_InitState()
|
|
51129
52160
|
self:HandleEvent(EVENTS.Shot,self.HandleEventShot)
|
|
@@ -51153,11 +52184,13 @@ math.random()
|
|
|
51153
52184
|
end
|
|
51154
52185
|
return self
|
|
51155
52186
|
end
|
|
51156
|
-
function SHORAD:AddScootZones(ZoneSet,Number)
|
|
52187
|
+
function SHORAD:AddScootZones(ZoneSet,Number,Random,Formation)
|
|
51157
52188
|
self:T(self.lid.." AddScootZones")
|
|
51158
52189
|
self.SkateZones=ZoneSet
|
|
51159
52190
|
self.SkateNumber=Number or 3
|
|
51160
52191
|
self.shootandscoot=true
|
|
52192
|
+
self.scootrandomcoord=Random
|
|
52193
|
+
self.scootformation=Formation or"Cone"
|
|
51161
52194
|
return self
|
|
51162
52195
|
end
|
|
51163
52196
|
function SHORAD:SwitchDebug(onoff)
|
|
@@ -51421,8 +52454,8 @@ end
|
|
|
51421
52454
|
function SHORAD:onafterShootAndScoot(From,Event,To,Shorad)
|
|
51422
52455
|
self:T({From,Event,To})
|
|
51423
52456
|
local possibleZones={}
|
|
51424
|
-
local mindist=100
|
|
51425
|
-
local maxdist=3000
|
|
52457
|
+
local mindist=self.minscootdist or 100
|
|
52458
|
+
local maxdist=self.maxscootdist or 3000
|
|
51426
52459
|
if Shorad and Shorad:IsAlive()then
|
|
51427
52460
|
local NowCoord=Shorad:GetCoordinate()
|
|
51428
52461
|
for _,_zone in pairs(self.SkateZones.Set)do
|
|
@@ -51438,7 +52471,11 @@ local rand=math.floor(math.random(1,#possibleZones*1000)/1000+0.5)
|
|
|
51438
52471
|
if rand==0 then rand=1 end
|
|
51439
52472
|
self:T(self.lid.." ShootAndScoot to zone "..rand)
|
|
51440
52473
|
local ToCoordinate=possibleZones[rand]:GetCoordinate()
|
|
51441
|
-
|
|
52474
|
+
if self.scootrandomcoord then
|
|
52475
|
+
ToCoordinate=possibleZones[rand]:GetRandomCoordinate(nil,nil,{land.SurfaceType.LAND,land.SurfaceType.ROAD})
|
|
52476
|
+
end
|
|
52477
|
+
local formation=self.scootformation or"Cone"
|
|
52478
|
+
Shorad:RouteGroundTo(ToCoordinate,20,formation,1)
|
|
51442
52479
|
end
|
|
51443
52480
|
end
|
|
51444
52481
|
return self
|
|
@@ -51469,7 +52506,7 @@ self:__CalculateHitZone(20,ShootingWeapon,pos0,fheight,EventData.IniGroup)
|
|
|
51469
52506
|
end
|
|
51470
52507
|
return self
|
|
51471
52508
|
end
|
|
51472
|
-
local targetcat=
|
|
52509
|
+
local targetcat=Object.getCategory(targetdata)
|
|
51473
52510
|
self:T(string.format("Target Category (3=STATIC, 1=UNIT)= %s",tostring(targetcat)))
|
|
51474
52511
|
self:T({targetdata})
|
|
51475
52512
|
local targetunit=nil
|
|
@@ -61519,7 +62556,7 @@ DELIMITER="Punto",
|
|
|
61519
62556
|
}
|
|
61520
62557
|
ATIS.locale="en"
|
|
61521
62558
|
_ATIS={}
|
|
61522
|
-
ATIS.version="0.10.
|
|
62559
|
+
ATIS.version="0.10.4"
|
|
61523
62560
|
function ATIS:New(AirbaseName,Frequency,Modulation)
|
|
61524
62561
|
local self=BASE:Inherit(self,FSM:New())
|
|
61525
62562
|
self.airbasename=AirbaseName
|
|
@@ -61828,7 +62865,16 @@ self:E(self.lid..string.format("EXPERIMENTAL: Starting ATIS for Helipad %s! SRS
|
|
|
61828
62865
|
self.ATISforFARPs=true
|
|
61829
62866
|
self.useSRS=true
|
|
61830
62867
|
end
|
|
62868
|
+
if type(self.frequency)=="table"then
|
|
62869
|
+
local frequency=table.concat(self.frequency,"/")
|
|
62870
|
+
local modulation=self.modulation
|
|
62871
|
+
if type(self.modulation)=="table"then
|
|
62872
|
+
modulation=table.concat(self.modulation,"/")
|
|
62873
|
+
end
|
|
62874
|
+
self:I(self.lid..string.format("Starting ATIS v%s for airbase %s on %s MHz Modulation=%s",ATIS.version,self.airbasename,frequency,modulation))
|
|
62875
|
+
else
|
|
61831
62876
|
self:I(self.lid..string.format("Starting ATIS v%s for airbase %s on %.3f MHz Modulation=%d",ATIS.version,self.airbasename,self.frequency,self.modulation))
|
|
62877
|
+
end
|
|
61832
62878
|
if not self.useSRS then
|
|
61833
62879
|
self.radioqueue=RADIOQUEUE:New(self.frequency,self.modulation,string.format("ATIS %s",self.airbasename))
|
|
61834
62880
|
self.radioqueue:SetSenderCoordinate(self.airbase:GetCoordinate())
|
|
@@ -61860,7 +62906,17 @@ if ru then
|
|
|
61860
62906
|
relayunitstatus=tostring(ru:IsAlive())
|
|
61861
62907
|
end
|
|
61862
62908
|
end
|
|
61863
|
-
local text=
|
|
62909
|
+
local text=""
|
|
62910
|
+
if type(self.frequency)=="table"then
|
|
62911
|
+
local frequency=table.concat(self.frequency,"/")
|
|
62912
|
+
local modulation=self.modulation
|
|
62913
|
+
if type(self.modulation)=="table"then
|
|
62914
|
+
modulation=table.concat(self.modulation,"/")
|
|
62915
|
+
end
|
|
62916
|
+
text=string.format("State %s: Freq=%s MHz %s",fsmstate,frequency,modulation)
|
|
62917
|
+
else
|
|
62918
|
+
text=string.format("State %s: Freq=%.3f MHz %s",fsmstate,self.frequency,UTILS.GetModulationName(self.modulation))
|
|
62919
|
+
end
|
|
61864
62920
|
if self.useSRS then
|
|
61865
62921
|
text=text..string.format(", SRS path=%s (%s), gender=%s, culture=%s, voice=%s",tostring(self.msrs.path),tostring(self.msrs.port),tostring(self.msrs.gender),tostring(self.msrs.culture),tostring(self.msrs.voice))
|
|
61866
62922
|
else
|
|
@@ -62457,7 +63513,7 @@ end
|
|
|
62457
63513
|
alltext=alltext..";\n"..subtitle
|
|
62458
63514
|
local _RUNACT
|
|
62459
63515
|
if not self.ATISforFARPs then
|
|
62460
|
-
local subtitle
|
|
63516
|
+
local subtitle=""
|
|
62461
63517
|
if runwayLanding then
|
|
62462
63518
|
local actrun=self.gettext:GetEntry("ACTIVELANDING",self.locale)
|
|
62463
63519
|
subtitle=string.format("%s %s",actrun,runwayLanding)
|
|
@@ -62745,7 +63801,17 @@ function ATIS:UpdateMarker(information,runact,wind,altimeter,temperature)
|
|
|
62745
63801
|
if self.markerid then
|
|
62746
63802
|
self.airbase:GetCoordinate():RemoveMark(self.markerid)
|
|
62747
63803
|
end
|
|
62748
|
-
local text=
|
|
63804
|
+
local text=""
|
|
63805
|
+
if type(self.frequency)=="table"then
|
|
63806
|
+
local frequency=table.concat(self.frequency,"/")
|
|
63807
|
+
local modulation=self.modulation
|
|
63808
|
+
if type(modulation)=="table"then
|
|
63809
|
+
modulation=table.concat(self.modulation,"/")
|
|
63810
|
+
end
|
|
63811
|
+
text=string.format("ATIS on %s %s, %s:\n",tostring(frequency),tostring(modulation),tostring(information))
|
|
63812
|
+
else
|
|
63813
|
+
text=string.format("ATIS on %.3f %s, %s:\n",self.frequency,UTILS.GetModulationName(self.modulation),tostring(information))
|
|
63814
|
+
end
|
|
62749
63815
|
text=text..string.format("%s\n",tostring(runact))
|
|
62750
63816
|
text=text..string.format("%s\n",tostring(wind))
|
|
62751
63817
|
text=text..string.format("%s\n",tostring(altimeter))
|
|
@@ -63192,7 +64258,7 @@ MOVE="move",
|
|
|
63192
64258
|
SHIP="ship",
|
|
63193
64259
|
BEACON="beacon",
|
|
63194
64260
|
}
|
|
63195
|
-
CTLD.
|
|
64261
|
+
CTLD.UnitTypeCapabilities={
|
|
63196
64262
|
["SA342Mistral"]={type="SA342Mistral",crates=false,troops=true,cratelimit=0,trooplimit=4,length=12,cargoweightlimit=400},
|
|
63197
64263
|
["SA342L"]={type="SA342L",crates=false,troops=true,cratelimit=0,trooplimit=2,length=12,cargoweightlimit=400},
|
|
63198
64264
|
["SA342M"]={type="SA342M",crates=false,troops=true,cratelimit=0,trooplimit=4,length=12,cargoweightlimit=400},
|
|
@@ -63209,7 +64275,7 @@ CTLD.UnitTypes={
|
|
|
63209
64275
|
["AH-64D_BLK_II"]={type="AH-64D_BLK_II",crates=false,troops=true,cratelimit=0,trooplimit=2,length=17,cargoweightlimit=200},
|
|
63210
64276
|
["Bronco-OV-10A"]={type="Bronco-OV-10A",crates=false,troops=true,cratelimit=0,trooplimit=5,length=13,cargoweightlimit=1450},
|
|
63211
64277
|
}
|
|
63212
|
-
CTLD.version="1.0.
|
|
64278
|
+
CTLD.version="1.0.44"
|
|
63213
64279
|
function CTLD:New(Coalition,Prefixes,Alias)
|
|
63214
64280
|
local self=BASE:Inherit(self,FSM:New())
|
|
63215
64281
|
BASE:T({Coalition,Prefixes,Alias})
|
|
@@ -63254,6 +64320,8 @@ self:AddTransition("*","TroopsRTB","*")
|
|
|
63254
64320
|
self:AddTransition("*","CratesDropped","*")
|
|
63255
64321
|
self:AddTransition("*","CratesBuild","*")
|
|
63256
64322
|
self:AddTransition("*","CratesRepaired","*")
|
|
64323
|
+
self:AddTransition("*","CratesBuildStarted","*")
|
|
64324
|
+
self:AddTransition("*","CratesRepairStarted","*")
|
|
63257
64325
|
self:AddTransition("*","Load","*")
|
|
63258
64326
|
self:AddTransition("*","Save","*")
|
|
63259
64327
|
self:AddTransition("*","Stop","Stopped")
|
|
@@ -63349,7 +64417,7 @@ function CTLD:_GetUnitCapabilities(Unit)
|
|
|
63349
64417
|
self:T(self.lid.." _GetUnitCapabilities")
|
|
63350
64418
|
local _unit=Unit
|
|
63351
64419
|
local unittype=_unit:GetTypeName()
|
|
63352
|
-
local capabilities=self.
|
|
64420
|
+
local capabilities=self.UnitTypeCapabilities[unittype]
|
|
63353
64421
|
if not capabilities or capabilities=={}then
|
|
63354
64422
|
capabilities={}
|
|
63355
64423
|
capabilities.troops=false
|
|
@@ -63673,6 +64741,7 @@ local desttimer=TIMER:New(function()NearestGroup:Destroy(false)end,self)
|
|
|
63673
64741
|
desttimer:Start(self.repairtime-1)
|
|
63674
64742
|
local buildtimer=TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,object,true,NearestGroup:GetCoordinate())
|
|
63675
64743
|
buildtimer:Start(self.repairtime)
|
|
64744
|
+
self:__CratesRepairStarted(1,Group,Unit)
|
|
63676
64745
|
else
|
|
63677
64746
|
if not Engineering then
|
|
63678
64747
|
self:_SendMessage("Can't repair this unit with "..build.Name,10,false,Group)
|
|
@@ -63997,6 +65066,34 @@ self:_SendMessage(string.format("No (loadable) crates within %d meters!",finddis
|
|
|
63997
65066
|
end
|
|
63998
65067
|
return self
|
|
63999
65068
|
end
|
|
65069
|
+
function CTLD:_RemoveCratesNearby(_group,_unit)
|
|
65070
|
+
self:T(self.lid.." _RemoveCratesNearby")
|
|
65071
|
+
local finddist=self.CrateDistance or 35
|
|
65072
|
+
local crates,number=self:_FindCratesNearby(_group,_unit,finddist,true)
|
|
65073
|
+
if number>0 then
|
|
65074
|
+
local text=REPORT:New("Removing Crates Found Nearby:")
|
|
65075
|
+
text:Add("------------------------------------------------------------")
|
|
65076
|
+
for _,_entry in pairs(crates)do
|
|
65077
|
+
local entry=_entry
|
|
65078
|
+
local name=entry:GetName()
|
|
65079
|
+
local dropped=entry:WasDropped()
|
|
65080
|
+
if dropped then
|
|
65081
|
+
text:Add(string.format("Crate for %s, %dkg removed",name,entry.PerCrateMass))
|
|
65082
|
+
else
|
|
65083
|
+
text:Add(string.format("Crate for %s, %dkg removed",name,entry.PerCrateMass))
|
|
65084
|
+
end
|
|
65085
|
+
entry:GetPositionable():Destroy(false)
|
|
65086
|
+
end
|
|
65087
|
+
if text:GetCount()==1 then
|
|
65088
|
+
text:Add(" N O N E")
|
|
65089
|
+
end
|
|
65090
|
+
text:Add("------------------------------------------------------------")
|
|
65091
|
+
self:_SendMessage(text:Text(),30,true,_group)
|
|
65092
|
+
else
|
|
65093
|
+
self:_SendMessage(string.format("No (loadable) crates within %d meters!",finddist),10,false,_group)
|
|
65094
|
+
end
|
|
65095
|
+
return self
|
|
65096
|
+
end
|
|
64000
65097
|
function CTLD:_GetDistance(_point1,_point2)
|
|
64001
65098
|
self:T(self.lid.." _GetDistance")
|
|
64002
65099
|
if _point1 and _point2 then
|
|
@@ -64335,6 +65432,26 @@ else
|
|
|
64335
65432
|
return false
|
|
64336
65433
|
end
|
|
64337
65434
|
end
|
|
65435
|
+
function CTLD:_GetUnitPositions(Coordinate,Radius,Heading,Template)
|
|
65436
|
+
local Positions={}
|
|
65437
|
+
local template=_DATABASE:GetGroupTemplate(Template)
|
|
65438
|
+
UTILS.PrintTableToLog(template)
|
|
65439
|
+
local numbertroops=#template.units
|
|
65440
|
+
local newcenter=Coordinate:Translate(Radius,((Heading+270)%360))
|
|
65441
|
+
for i=1,360,math.floor(360/numbertroops)do
|
|
65442
|
+
local phead=((Heading+270+i)%360)
|
|
65443
|
+
local post=newcenter:Translate(Radius,phead)
|
|
65444
|
+
local pos1=post:GetVec2()
|
|
65445
|
+
local p1t={
|
|
65446
|
+
x=pos1.x,
|
|
65447
|
+
y=pos1.y,
|
|
65448
|
+
heading=phead,
|
|
65449
|
+
}
|
|
65450
|
+
table.insert(Positions,p1t)
|
|
65451
|
+
end
|
|
65452
|
+
UTILS.PrintTableToLog(Positions)
|
|
65453
|
+
return Positions
|
|
65454
|
+
end
|
|
64338
65455
|
function CTLD:_UnloadTroops(Group,Unit)
|
|
64339
65456
|
self:T(self.lid.." _UnloadTroops")
|
|
64340
65457
|
local droppingatbase=false
|
|
@@ -64375,14 +65492,25 @@ factor=cargo:GetCratesNeeded()or 1
|
|
|
64375
65492
|
zoneradius=Unit:GetVelocityMPS()or 100
|
|
64376
65493
|
end
|
|
64377
65494
|
local zone=ZONE_GROUP:New(string.format("Unload zone-%s",unitname),Group,zoneradius*factor)
|
|
64378
|
-
local randomcoord=zone:GetRandomCoordinate(10,30*factor)
|
|
65495
|
+
local randomcoord=zone:GetRandomCoordinate(10,30*factor)
|
|
65496
|
+
local heading=Group:GetHeading()or 0
|
|
65497
|
+
if hoverunload or grounded then
|
|
65498
|
+
randomcoord=Group:GetCoordinate()
|
|
65499
|
+
local Angle=(heading+270)%360
|
|
65500
|
+
local offset=hoverunload and 1.5 or 5
|
|
65501
|
+
randomcoord:Translate(offset,Angle,nil,true)
|
|
65502
|
+
end
|
|
65503
|
+
local tempcount=0
|
|
64379
65504
|
for _,_template in pairs(temptable)do
|
|
64380
65505
|
self.TroopCounter=self.TroopCounter+1
|
|
65506
|
+
tempcount=tempcount+1
|
|
64381
65507
|
local alias=string.format("%s-%d",_template,math.random(1,100000))
|
|
65508
|
+
local rad=2.5+tempcount
|
|
65509
|
+
local Positions=self:_GetUnitPositions(randomcoord,rad,heading,_template)
|
|
64382
65510
|
self.DroppedTroops[self.TroopCounter]=SPAWN:NewWithAlias(_template,alias)
|
|
64383
|
-
:InitRandomizeUnits(true,20,2)
|
|
64384
65511
|
:InitDelayOff()
|
|
64385
|
-
:
|
|
65512
|
+
:InitSetUnitAbsolutePositions(Positions)
|
|
65513
|
+
:SpawnFromVec2(randomcoord:GetVec2())
|
|
64386
65514
|
self:__TroopsDeployed(1,Group,Unit,self.DroppedTroops[self.TroopCounter],type)
|
|
64387
65515
|
end
|
|
64388
65516
|
cargo:SetWasDropped(true)
|
|
@@ -64581,6 +65709,7 @@ if self.buildtime and self.buildtime>0 then
|
|
|
64581
65709
|
local buildtimer=TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate())
|
|
64582
65710
|
buildtimer:Start(self.buildtime)
|
|
64583
65711
|
self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group)
|
|
65712
|
+
self:__CratesBuildStarted(1,Group,Unit)
|
|
64584
65713
|
else
|
|
64585
65714
|
self:_BuildObjectFromCrates(Group,Unit,build)
|
|
64586
65715
|
end
|
|
@@ -64825,8 +65954,14 @@ local capabilities=self:_GetUnitCapabilities(_unit)
|
|
|
64825
65954
|
local cantroops=capabilities.troops
|
|
64826
65955
|
local cancrates=capabilities.crates
|
|
64827
65956
|
local topmenu=MENU_GROUP:New(_group,"CTLD",nil)
|
|
64828
|
-
local toptroops=
|
|
64829
|
-
local topcrates=
|
|
65957
|
+
local toptroops=nil
|
|
65958
|
+
local topcrates=nil
|
|
65959
|
+
if cantroops then
|
|
65960
|
+
toptroops=MENU_GROUP:New(_group,"Manage Troops",topmenu)
|
|
65961
|
+
end
|
|
65962
|
+
if cancrates then
|
|
65963
|
+
topcrates=MENU_GROUP:New(_group,"Manage Crates",topmenu)
|
|
65964
|
+
end
|
|
64830
65965
|
local listmenu=MENU_GROUP_COMMAND:New(_group,"List boarded cargo",topmenu,self._ListCargo,self,_group,_unit)
|
|
64831
65966
|
local invtry=MENU_GROUP_COMMAND:New(_group,"Inventory",topmenu,self._ListInventory,self,_group,_unit)
|
|
64832
65967
|
local rbcns=MENU_GROUP_COMMAND:New(_group,"List active zone beacons",topmenu,self._ListRadioBeacons,self,_group,_unit)
|
|
@@ -64868,6 +66003,7 @@ if cancrates then
|
|
|
64868
66003
|
local loadmenu=MENU_GROUP_COMMAND:New(_group,"Load crates",topcrates,self._LoadCratesNearby,self,_group,_unit)
|
|
64869
66004
|
local cratesmenu=MENU_GROUP:New(_group,"Get Crates",topcrates)
|
|
64870
66005
|
local packmenu=MENU_GROUP_COMMAND:New(_group,"Pack crates",topcrates,self._PackCratesNearby,self,_group,_unit)
|
|
66006
|
+
local removecratesmenu=MENU_GROUP:New(_group,"Remove crates",topcrates)
|
|
64871
66007
|
if self.usesubcats then
|
|
64872
66008
|
local subcatmenus={}
|
|
64873
66009
|
for _name,_entry in pairs(self.subcats)do
|
|
@@ -64902,6 +66038,7 @@ menus[menucount]=MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrat
|
|
|
64902
66038
|
end
|
|
64903
66039
|
end
|
|
64904
66040
|
listmenu=MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates,self._ListCratesNearby,self,_group,_unit)
|
|
66041
|
+
removecrates=MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu,self._RemoveCratesNearby,self,_group,_unit)
|
|
64905
66042
|
local unloadmenu=MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates,self._UnloadCrates,self,_group,_unit)
|
|
64906
66043
|
if not self.nobuildmenu then
|
|
64907
66044
|
local buildmenu=MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates,self._BuildCrates,self,_group,_unit)
|
|
@@ -65402,7 +66539,7 @@ self:_SendMessage(string.format("Negative, need to be closer than %dnm to a zone
|
|
|
65402
66539
|
end
|
|
65403
66540
|
return self
|
|
65404
66541
|
end
|
|
65405
|
-
function CTLD:
|
|
66542
|
+
function CTLD:SetUnitCapabilities(Unittype,Cancrates,Cantroops,Cratelimit,Trooplimit,Length,Maxcargoweight)
|
|
65406
66543
|
self:T(self.lid.." UnitCapabilities")
|
|
65407
66544
|
local unittype=nil
|
|
65408
66545
|
local unit=nil
|
|
@@ -65416,7 +66553,7 @@ return self
|
|
|
65416
66553
|
end
|
|
65417
66554
|
local length=20
|
|
65418
66555
|
local maxcargo=500
|
|
65419
|
-
local existingcaps=self.
|
|
66556
|
+
local existingcaps=self.UnitTypeCapabilities[unittype]
|
|
65420
66557
|
if existingcaps then
|
|
65421
66558
|
length=existingcaps.length or 20
|
|
65422
66559
|
maxcargo=existingcaps.cargoweightlimit or 500
|
|
@@ -65429,7 +66566,12 @@ capabilities.cratelimit=Cratelimit or 0
|
|
|
65429
66566
|
capabilities.trooplimit=Trooplimit or 0
|
|
65430
66567
|
capabilities.length=Length or length
|
|
65431
66568
|
capabilities.cargoweightlimit=Maxcargoweight or maxcargo
|
|
65432
|
-
self.
|
|
66569
|
+
self.UnitTypeCapabilities[unittype]=capabilities
|
|
66570
|
+
return self
|
|
66571
|
+
end
|
|
66572
|
+
function CTLD:UnitCapabilities(Unittype,Cancrates,Cantroops,Cratelimit,Trooplimit,Length,Maxcargoweight)
|
|
66573
|
+
self:I(self.lid.."This function been replaced with `SetUnitCapabilities()` - pls use the new one going forward!")
|
|
66574
|
+
self:SetUnitCapabilities(Unittype,Cancrates,Cantroops,Cratelimit,Trooplimit,Length,Maxcargoweight)
|
|
65433
66575
|
return self
|
|
65434
66576
|
end
|
|
65435
66577
|
function CTLD:IsCorrectHover(Unit)
|
|
@@ -77804,8 +78946,9 @@ AltBackend=nil,
|
|
|
77804
78946
|
ConfigFileName="Moose_MSRS.lua",
|
|
77805
78947
|
ConfigFilePath="Config\\",
|
|
77806
78948
|
ConfigLoaded=false,
|
|
78949
|
+
ttsprovider="Microsoft",
|
|
77807
78950
|
}
|
|
77808
|
-
MSRS.version="0.1.
|
|
78951
|
+
MSRS.version="0.1.3"
|
|
77809
78952
|
MSRS.Voices={
|
|
77810
78953
|
Microsoft={
|
|
77811
78954
|
["Hedda"]="Microsoft Hedda Desktop",
|
|
@@ -77926,8 +79069,7 @@ Backend.Vars.Volume=Volume
|
|
|
77926
79069
|
Backend.Functions=Backend.Functions or{}
|
|
77927
79070
|
return self:_NewAltBackend(Backend)
|
|
77928
79071
|
end
|
|
77929
|
-
|
|
77930
|
-
if(not success)and(not self.ConfigLoaded)then
|
|
79072
|
+
if not self.ConfigLoaded then
|
|
77931
79073
|
self:SetPath(PathToSRS)
|
|
77932
79074
|
self:SetPort()
|
|
77933
79075
|
self:SetFrequencies(Frequency)
|
|
@@ -77966,7 +79108,7 @@ while(self.path:sub(-1)=="/"or self.path:sub(-1)==[[\]])and n<=nmax do
|
|
|
77966
79108
|
self.path=self.path:sub(1,#self.path-1)
|
|
77967
79109
|
n=n+1
|
|
77968
79110
|
end
|
|
77969
|
-
self:
|
|
79111
|
+
self:T(string.format("SRS path=%s",self:GetPath()))
|
|
77970
79112
|
end
|
|
77971
79113
|
return self
|
|
77972
79114
|
end
|
|
@@ -78072,6 +79214,7 @@ self.APIKey=PathToCredentials
|
|
|
78072
79214
|
self.provider="gcloud"
|
|
78073
79215
|
self.GRPCOptions.DefaultProvider="gcloud"
|
|
78074
79216
|
self.GRPCOptions.gcloud.key=PathToCredentials
|
|
79217
|
+
self.ttsprovider="Google"
|
|
78075
79218
|
end
|
|
78076
79219
|
return self
|
|
78077
79220
|
end
|
|
@@ -78084,6 +79227,14 @@ self.GRPCOptions.gcloud.key=APIKey
|
|
|
78084
79227
|
end
|
|
78085
79228
|
return self
|
|
78086
79229
|
end
|
|
79230
|
+
function MSRS:SetTTSProviderGoogle()
|
|
79231
|
+
self.ttsprovider="Google"
|
|
79232
|
+
return self
|
|
79233
|
+
end
|
|
79234
|
+
function MSRS:SetTTSProviderMicrosoft()
|
|
79235
|
+
self.ttsprovider="Microsoft"
|
|
79236
|
+
return self
|
|
79237
|
+
end
|
|
78087
79238
|
function MSRS:Help()
|
|
78088
79239
|
local path=self:GetPath()or STTS.DIRECTORY
|
|
78089
79240
|
local exe=STTS.EXECUTABLE or"DCS-SR-ExternalAudio.exe"
|
|
@@ -78269,16 +79420,22 @@ if coordinate then
|
|
|
78269
79420
|
local lat,lon,alt=self:_GetLatLongAlt(coordinate)
|
|
78270
79421
|
command=command..string.format(" -L %.4f -O %.4f -A %d",lat,lon,alt)
|
|
78271
79422
|
end
|
|
78272
|
-
if self.google then
|
|
79423
|
+
if self.google and self.ttsprovider=="Google"then
|
|
78273
79424
|
command=command..string.format(' --ssml -G "%s"',self.google)
|
|
78274
79425
|
end
|
|
78275
79426
|
self:T("MSRS command="..command)
|
|
78276
79427
|
return command
|
|
78277
79428
|
end
|
|
78278
|
-
function MSRS:LoadConfigFile(Path,Filename
|
|
79429
|
+
function MSRS:LoadConfigFile(Path,Filename)
|
|
79430
|
+
if lfs==nil then
|
|
79431
|
+
env.info("*****Note - lfs and os need to be desanitized for MSRS to work!")
|
|
79432
|
+
return false
|
|
79433
|
+
end
|
|
78279
79434
|
local path=Path or lfs.writedir()..MSRS.ConfigFilePath
|
|
78280
79435
|
local file=Filename or MSRS.ConfigFileName or"Moose_MSRS.lua"
|
|
78281
|
-
|
|
79436
|
+
local pathandfile=path..file
|
|
79437
|
+
local filexsists=UTILS.FileExists(pathandfile)
|
|
79438
|
+
if filexsists and not MSRS.ConfigLoaded then
|
|
78282
79439
|
assert(loadfile(path..file))()
|
|
78283
79440
|
if MSRS_Config then
|
|
78284
79441
|
if self then
|
|
@@ -78293,8 +79450,11 @@ end
|
|
|
78293
79450
|
self.culture=MSRS_Config.Culture or"en-GB"
|
|
78294
79451
|
self.gender=MSRS_Config.Gender or"male"
|
|
78295
79452
|
self.google=MSRS_Config.Google
|
|
79453
|
+
if MSRS_Config.Provider then
|
|
79454
|
+
self.ttsprovider=MSRS_Config.Provider
|
|
79455
|
+
end
|
|
78296
79456
|
self.Label=MSRS_Config.Label or"MSRS"
|
|
78297
|
-
self.voice=MSRS_Config.Voice
|
|
79457
|
+
self.voice=MSRS_Config.Voice
|
|
78298
79458
|
if MSRS_Config.GRPC then
|
|
78299
79459
|
self.provider=MSRS_Config.GRPC.DefaultProvider
|
|
78300
79460
|
if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider]then
|
|
@@ -78317,8 +79477,11 @@ end
|
|
|
78317
79477
|
MSRS.culture=MSRS_Config.Culture or"en-GB"
|
|
78318
79478
|
MSRS.gender=MSRS_Config.Gender or"male"
|
|
78319
79479
|
MSRS.google=MSRS_Config.Google
|
|
79480
|
+
if MSRS_Config.Provider then
|
|
79481
|
+
MSRS.ttsprovider=MSRS_Config.Provider
|
|
79482
|
+
end
|
|
78320
79483
|
MSRS.Label=MSRS_Config.Label or"MSRS"
|
|
78321
|
-
MSRS.voice=MSRS_Config.Voice
|
|
79484
|
+
MSRS.voice=MSRS_Config.Voice
|
|
78322
79485
|
if MSRS_Config.GRPC then
|
|
78323
79486
|
MSRS.provider=MSRS_Config.GRPC.DefaultProvider
|
|
78324
79487
|
if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider]then
|
|
@@ -78331,9 +79494,10 @@ end
|
|
|
78331
79494
|
MSRS.ConfigLoaded=true
|
|
78332
79495
|
end
|
|
78333
79496
|
end
|
|
78334
|
-
env.info("MSRS -
|
|
78335
|
-
|
|
78336
|
-
|
|
79497
|
+
env.info("MSRS - Successfully loaded default configuration from disk!",false)
|
|
79498
|
+
end
|
|
79499
|
+
if not filexsists then
|
|
79500
|
+
env.info("MSRS - Cannot find default configuration file!",false)
|
|
78337
79501
|
return false
|
|
78338
79502
|
end
|
|
78339
79503
|
return true
|
|
@@ -78502,7 +79666,7 @@ self.lid=string.format("MSRSQUEUE %s | ",self.alias)
|
|
|
78502
79666
|
return self
|
|
78503
79667
|
end
|
|
78504
79668
|
function MSRSQUEUE:Clear()
|
|
78505
|
-
self:I(self.lid.."
|
|
79669
|
+
self:I(self.lid.."Clearing MSRSQUEUE")
|
|
78506
79670
|
self.queue={}
|
|
78507
79671
|
return self
|
|
78508
79672
|
end
|
|
@@ -78559,7 +79723,7 @@ end
|
|
|
78559
79723
|
transmission.gender=gender
|
|
78560
79724
|
transmission.culture=culture
|
|
78561
79725
|
transmission.voice=voice
|
|
78562
|
-
transmission.
|
|
79726
|
+
transmission.volume=volume
|
|
78563
79727
|
transmission.label=label
|
|
78564
79728
|
transmission.coordinate=coordinate
|
|
78565
79729
|
self:AddTransmission(transmission)
|
|
@@ -78666,6 +79830,7 @@ end
|
|
|
78666
79830
|
self:_CheckRadioQueue(dt)
|
|
78667
79831
|
end
|
|
78668
79832
|
end
|
|
79833
|
+
MSRS.LoadConfigFile()
|
|
78669
79834
|
COMMANDCENTER={
|
|
78670
79835
|
ClassName="COMMANDCENTER",
|
|
78671
79836
|
CommandCenterName="",
|