Merge branch 'master' into FF/MasterDevel

This commit is contained in:
Frank
2023-12-21 22:22:10 +01:00
12 changed files with 438 additions and 99 deletions

View File

@@ -449,10 +449,10 @@ do -- Zones and Pathlines
-- Loop over layers. -- Loop over layers.
for layerID, layerData in pairs(env.mission.drawings.layers or {}) do for layerID, layerData in pairs(env.mission.drawings.layers or {}) do
-- Loop over objects in layers. -- Loop over objects in layers.
for objectID, objectData in pairs(layerData.objects or {}) do for objectID, objectData in pairs(layerData.objects or {}) do
-- Check for polygon which has at least 4 points (we would need 3 but the origin seems to be there twice) -- Check for polygon which has at least 4 points (we would need 3 but the origin seems to be there twice)
if objectData.polygonMode and (objectData.polygonMode=="free") and objectData.points and #objectData.points>=4 then if objectData.polygonMode and (objectData.polygonMode=="free") and objectData.points and #objectData.points>=4 then
@@ -488,10 +488,32 @@ do -- Zones and Pathlines
-- Create new polygon zone. -- Create new polygon zone.
local Zone=ZONE_POLYGON:NewFromPointsArray(ZoneName, points) local Zone=ZONE_POLYGON:NewFromPointsArray(ZoneName, points)
--Zone.DrawID = objectID
-- Set color. -- Set color.
Zone:SetColor({1, 0, 0}, 0.15) Zone:SetColor({1, 0, 0}, 0.15)
Zone:SetFillColor({1, 0, 0}, 0.15)
if objectData.colorString then
-- eg colorString = 0xff0000ff
local color = string.gsub(objectData.colorString,"^0x","")
local r = tonumber(string.sub(color,1,2),16)/255
local g = tonumber(string.sub(color,3,4),16)/255
local b = tonumber(string.sub(color,5,6),16)/255
local a = tonumber(string.sub(color,7,8),16)/255
Zone:SetColor({r, g, b}, a)
end
if objectData.fillColorString then
-- eg fillColorString = 0xff00004b
local color = string.gsub(objectData.colorString,"^0x","")
local r = tonumber(string.sub(color,1,2),16)/255
local g = tonumber(string.sub(color,3,4),16)/255
local b = tonumber(string.sub(color,5,6),16)/255
local a = tonumber(string.sub(color,7,8),16)/255
Zone:SetFillColor({r, g, b}, a)
end
-- Store in DB. -- Store in DB.
self.ZONENAMES[ZoneName] = ZoneName self.ZONENAMES[ZoneName] = ZoneName
@@ -532,7 +554,26 @@ do -- Zones and Pathlines
-- Set color. -- Set color.
Zone:SetColor({1, 0, 0}, 0.15) Zone:SetColor({1, 0, 0}, 0.15)
if objectData.colorString then
-- eg colorString = 0xff0000ff
local color = string.gsub(objectData.colorString,"^0x","")
local r = tonumber(string.sub(color,1,2),16)/255
local g = tonumber(string.sub(color,3,4),16)/255
local b = tonumber(string.sub(color,5,6),16)/255
local a = tonumber(string.sub(color,7,8),16)/255
Zone:SetColor({r, g, b}, a)
end
if objectData.fillColorString then
-- eg fillColorString = 0xff00004b
local color = string.gsub(objectData.colorString,"^0x","")
local r = tonumber(string.sub(color,1,2),16)/255
local g = tonumber(string.sub(color,3,4),16)/255
local b = tonumber(string.sub(color,5,6),16)/255
local a = tonumber(string.sub(color,7,8),16)/255
Zone:SetFillColor({r, g, b}, a)
end
-- Store in DB. -- Store in DB.
self.ZONENAMES[ZoneName] = ZoneName self.ZONENAMES[ZoneName] = ZoneName
@@ -756,7 +797,7 @@ end -- cargo
--- Finds a CLIENT based on the ClientName. --- Finds a CLIENT based on the ClientName.
-- @param #DATABASE self -- @param #DATABASE self
-- @param #string ClientName -- @param #string ClientName - Note this is the UNIT name of the client!
-- @return Wrapper.Client#CLIENT The found CLIENT. -- @return Wrapper.Client#CLIENT The found CLIENT.
function DATABASE:FindClient( ClientName ) function DATABASE:FindClient( ClientName )

View File

@@ -2020,7 +2020,7 @@ _ZONE_TRIANGLE = {
Coords={}, Coords={},
CenterVec2={x=0, y=0}, CenterVec2={x=0, y=0},
SurfaceArea=0, SurfaceArea=0,
DrawIDs={} DrawID={}
} }
--- ---
-- @param #_ZONE_TRIANGLE self -- @param #_ZONE_TRIANGLE self
@@ -2100,15 +2100,35 @@ function _ZONE_TRIANGLE:Draw(Coalition, Color, Alpha, FillColor, FillAlpha, Line
for i=1, #self.Coords do for i=1, #self.Coords do
local c1 = self.Coords[i] local c1 = self.Coords[i]
local c2 = self.Coords[i % #self.Coords + 1] local c2 = self.Coords[i % #self.Coords + 1]
table.add(self.DrawIDs, c1:LineToAll(c2, Coalition, Color, Alpha, LineType, ReadOnly)) local id = c1:LineToAll(c2, Coalition, Color, Alpha, LineType, ReadOnly)
self.DrawID[#self.DrawID+1] = id
end end
return self.DrawIDs local newID = self.Coords[1]:MarkupToAllFreeForm({self.Coords[2],self.Coords[3]},Coalition,Color,Alpha,FillColor,FillAlpha,LineType,ReadOnly)
self.DrawID[#self.DrawID+1] = newID
return self.DrawID
end
--- Draw the triangle
-- @param #_ZONE_TRIANGLE self
-- @return #table of draw IDs
function _ZONE_TRIANGLE:Fill(Coalition, FillColor, FillAlpha, ReadOnly)
Coalition=Coalition or -1
FillColor = FillColor
FillAlpha = FillAlpha
local newID = self.Coords[1]:MarkupToAllFreeForm({self.Coords[2],self.Coords[3]},Coalition,nil,nil,FillColor,FillAlpha,0,nil)
self.DrawID[#self.DrawID+1] = newID
return self.DrawID
end end
--- ---
-- @type ZONE_POLYGON_BASE -- @type ZONE_POLYGON_BASE
-- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCS#Vec2}. -- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCS#Vec2}.
-- @field #number SurfaceArea
-- @field #table DrawID
-- @field #table FillTriangles
-- @field #table _Triangles
-- @field #table Borderlines
-- @extends #ZONE_BASE -- @extends #ZONE_BASE
@@ -2133,9 +2153,11 @@ end
-- @field #ZONE_POLYGON_BASE -- @field #ZONE_POLYGON_BASE
ZONE_POLYGON_BASE = { ZONE_POLYGON_BASE = {
ClassName="ZONE_POLYGON_BASE", ClassName="ZONE_POLYGON_BASE",
_Triangles={}, -- _ZONE_TRIANGLES _Triangles={}, -- #table of #_ZONE_TRIANGLE
SurfaceArea=0, SurfaceArea=0,
DrawID={} -- making a table out of the MarkID so its easier to draw an n-sided polygon, see ZONE_POLYGON_BASE:Draw() DrawID={}, -- making a table out of the MarkID so its easier to draw an n-sided polygon, see ZONE_POLYGON_BASE:Draw()
FillTriangles = {},
Borderlines = {},
} }
--- A 2D points array. --- A 2D points array.
@@ -2172,7 +2194,7 @@ function ZONE_POLYGON_BASE:New( ZoneName, PointsArray )
self._Triangles = self:_Triangulate() self._Triangles = self:_Triangulate()
-- set the polygon's surface area -- set the polygon's surface area
self.SurfaceArea = self:_CalculateSurfaceArea() self.SurfaceArea = self:_CalculateSurfaceArea()
end end
return self return self
@@ -2470,18 +2492,18 @@ end
-- @param #table FillColor RGB color table {r, g, b}, e.g. {1,0,0} for red. Default is same as `Color` value. -- doesn't seem to work -- @param #table FillColor RGB color table {r, g, b}, e.g. {1,0,0} for red. Default is same as `Color` value. -- doesn't seem to work
-- @param #number FillAlpha Transparency [0,1]. Default 0.15. -- doesn't seem to work -- @param #number FillAlpha Transparency [0,1]. Default 0.15. -- doesn't seem to work
-- @param #number LineType Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 1=Solid. -- @param #number LineType Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 1=Solid.
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false. -- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.s
-- @return #ZONE_POLYGON_BASE self -- @return #ZONE_POLYGON_BASE self
function ZONE_POLYGON_BASE:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly, IncludeTriangles) function ZONE_POLYGON_BASE:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly, IncludeTriangles)
local coords = self:GetVerticiesCoordinates() local coords = self:GetVerticiesCoordinates()
local coord=coords[1] --Core.Point#COORDINATE local coord=coords[1] --Core.Point#COORDINATE
table.remove(coords, 1) table.remove(coords, 1)
coord:MarkupToAllFreeForm(coords, Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly, "Drew Polygon") coord:MarkupToAllFreeForm(coords, Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly, "Drew Polygon")
if true then if true then
return return
end end
@@ -2533,8 +2555,94 @@ function ZONE_POLYGON_BASE:DrawZone(Coalition, Color, Alpha, FillColor, FillAlph
table.add(self.DrawID, c1:LineToAll(c2, Coalition, Color, Alpha, LineType, ReadOnly)) table.add(self.DrawID, c1:LineToAll(c2, Coalition, Color, Alpha, LineType, ReadOnly))
end end
end end
if self._.Polygon and #self._.Polygon >= 3 then
Coalition = Coalition or self:GetDrawCoalition()
-- Set draw coalition.
self:SetDrawCoalition(Coalition)
Color = Color or self:GetColorRGB()
Alpha = Alpha or self:GetColorAlpha()
FillColor = FillColor or self:GetFillColorRGB()
FillAlpha = FillAlpha or self:GetFillColorAlpha()
if FillColor then
self:ReFill(FillColor,FillAlpha)
end end
return self
if Color then
self:ReDrawBorderline(Color,Alpha,LineType)
end
end
return self
end
--- Change/Re-fill a Polygon Zone
-- @param #ZONE_POLYGON_BASE self
-- @param #table Color RGB color table {r, g, b}, e.g. {1,0,0} for red.
-- @param #number Alpha Transparency [0,1]. Default 1.
-- @return #ZONE_POLYGON_BASE self
function ZONE_POLYGON_BASE:ReFill(Color,Alpha)
local color = Color or self:GetFillColorRGB() or {1,0,0}
local alpha = Alpha or self:GetFillColorAlpha() or 1
local coalition = self:GetDrawCoalition() or -1
-- undraw if already filled
if #self.FillTriangles > 0 then
for _, triangle in pairs(self._Triangles) do
triangle:UndrawZone()
end
-- remove mark IDs
for _,_value in pairs(self.FillTriangles) do
table.remove_by_value(self.DrawID, _value)
end
self.FillTriangles = nil
self.FillTriangles = {}
end
-- refill
for _, triangle in pairs(self._Triangles) do
local draw_ids = triangle:Fill(coalition,color,alpha,nil)
self.FillTriangles = draw_ids
table.combine(self.DrawID, draw_ids)
end
return self
end
--- Change/Re-draw the border of a Polygon Zone
-- @param #ZONE_POLYGON_BASE self
-- @param #table Color RGB color table {r, g, b}, e.g. {1,0,0} for red.
-- @param #number Alpha Transparency [0,1]. Default 1.
-- @param #number LineType Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 1=Solid.
-- @return #ZONE_POLYGON_BASE
function ZONE_POLYGON_BASE:ReDrawBorderline(Color, Alpha, LineType)
local color = Color or self:GetFillColorRGB() or {1,0,0}
local alpha = Alpha or self:GetFillColorAlpha() or 1
local coalition = self:GetDrawCoalition() or -1
local linetype = LineType or 1
-- undraw if already drawn
if #self.Borderlines > 0 then
for _, MarkID in pairs(self.Borderlines) do
trigger.action.removeMark(MarkID)
end
-- remove mark IDs
for _,_value in pairs(self.Borderlines) do
table.remove_by_value(self.DrawID, _value)
end
self.Borderlines = nil
self.Borderlines = {}
end
-- Redraw border
local coords = self:GetVerticiesCoordinates()
for i = 1, #coords do
local c1 = coords[i]
local c2 = coords[i % #coords + 1]
local newID = c1:LineToAll(c2, coalition, color, alpha, linetype, nil)
self.DrawID[#self.DrawID+1]=newID
self.Borderlines[#self.Borderlines+1] = newID
end
return self
end end
--- Get the surface area of this polygon --- Get the surface area of this polygon
@@ -2870,6 +2978,7 @@ function ZONE_POLYGON_BASE:Boundary(Coalition, Color, Radius, Alpha, Segments, C
Alpha = Alpha or 1 Alpha = Alpha or 1
Segments = Segments or 10 Segments = Segments or 10
Closed = Closed or false Closed = Closed or false
local Limit
local i = 1 local i = 1
local j = #self._.Polygon local j = #self._.Polygon
if (Closed) then if (Closed) then
@@ -3068,18 +3177,18 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
self.ScanData.Scenery = {} self.ScanData.Scenery = {}
self.ScanData.SceneryTable = {} self.ScanData.SceneryTable = {}
self.ScanData.Units = {} self.ScanData.Units = {}
local vectors = self:GetBoundingSquare() local vectors = self:GetBoundingSquare()
local minVec3 = {x=vectors.x1, y=0, z=vectors.y1} local minVec3 = {x=vectors.x1, y=0, z=vectors.y1}
local maxVec3 = {x=vectors.x2, y=0, z=vectors.y2} local maxVec3 = {x=vectors.x2, y=0, z=vectors.y2}
local minmarkcoord = COORDINATE:NewFromVec3(minVec3) local minmarkcoord = COORDINATE:NewFromVec3(minVec3)
local maxmarkcoord = COORDINATE:NewFromVec3(maxVec3) local maxmarkcoord = COORDINATE:NewFromVec3(maxVec3)
local ZoneRadius = minmarkcoord:Get2DDistance(maxmarkcoord)/2 local ZoneRadius = minmarkcoord:Get2DDistance(maxmarkcoord)/2
-- self:I("Scan Radius:" ..ZoneRadius) -- self:I("Scan Radius:" ..ZoneRadius)
local CenterVec3 = self:GetCoordinate():GetVec3() local CenterVec3 = self:GetCoordinate():GetVec3()
--[[ this a bit shaky in functionality it seems --[[ this a bit shaky in functionality it seems
local VolumeBox = { local VolumeBox = {
id = world.VolumeType.BOX, id = world.VolumeType.BOX,
@@ -3089,7 +3198,7 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
} }
} }
--]] --]]
local SphereSearch = { local SphereSearch = {
id = world.VolumeType.SPHERE, id = world.VolumeType.SPHERE,
params = { params = {
@@ -3097,13 +3206,13 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
radius = ZoneRadius, radius = ZoneRadius,
} }
} }
local function EvaluateZone( ZoneObject ) local function EvaluateZone( ZoneObject )
if ZoneObject then if ZoneObject then
local ObjectCategory = Object.getCategory(ZoneObject) local ObjectCategory = Object.getCategory(ZoneObject)
if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then
local CoalitionDCSUnit = ZoneObject:getCoalition() local CoalitionDCSUnit = ZoneObject:getCoalition()
@@ -3137,7 +3246,7 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
self:F2( { Name = ZoneObject:getName(), Coalition = CoalitionDCSUnit } ) self:F2( { Name = ZoneObject:getName(), Coalition = CoalitionDCSUnit } )
end end
end end
-- trying with box search -- trying with box search
if ObjectCategory == Object.Category.SCENERY and self:IsVec3InZone(ZoneObject:getPoint()) then if ObjectCategory == Object.Category.SCENERY and self:IsVec3InZone(ZoneObject:getPoint()) then
local SceneryType = ZoneObject:getTypeName() local SceneryType = ZoneObject:getTypeName()
@@ -3156,7 +3265,7 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
-- Search objects. -- Search objects.
local inzoneunits = SET_UNIT:New():FilterZones({self}):FilterOnce() local inzoneunits = SET_UNIT:New():FilterZones({self}):FilterOnce()
local inzonestatics = SET_STATIC:New():FilterZones({self}):FilterOnce() local inzonestatics = SET_STATIC:New():FilterZones({self}):FilterOnce()
inzoneunits:ForEach( inzoneunits:ForEach(
function(unit) function(unit)
local Unit = unit --Wrapper.Unit#UNIT local Unit = unit --Wrapper.Unit#UNIT
@@ -3164,7 +3273,7 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
EvaluateZone(DCS) EvaluateZone(DCS)
end end
) )
inzonestatics:ForEach( inzonestatics:ForEach(
function(static) function(static)
local Static = static --Wrapper.Static#STATIC local Static = static --Wrapper.Static#STATIC
@@ -3172,19 +3281,19 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
EvaluateZone(DCS) EvaluateZone(DCS)
end end
) )
local searchscenery = false local searchscenery = false
for _,_type in pairs(ObjectCategories) do for _,_type in pairs(ObjectCategories) do
if _type == Object.Category.SCENERY then if _type == Object.Category.SCENERY then
searchscenery = true searchscenery = true
end end
end end
if searchscenery then if searchscenery then
-- Search objects. -- Search objects.
world.searchObjects({Object.Category.SCENERY}, SphereSearch, EvaluateZone ) world.searchObjects({Object.Category.SCENERY}, SphereSearch, EvaluateZone )
end end
end end
--- Count the number of different coalitions inside the zone. --- Count the number of different coalitions inside the zone.
@@ -3400,7 +3509,7 @@ end
end end
do -- ZONE_ELASTIC do -- ZONE_ELASTIC
--- ---
-- @type ZONE_ELASTIC -- @type ZONE_ELASTIC
-- @field #table points Points in 2D. -- @field #table points Points in 2D.
@@ -3427,14 +3536,14 @@ do -- ZONE_ELASTIC
function ZONE_ELASTIC:New(ZoneName, Points) function ZONE_ELASTIC:New(ZoneName, Points)
local self=BASE:Inherit(self, ZONE_POLYGON_BASE:New(ZoneName, Points)) --#ZONE_ELASTIC local self=BASE:Inherit(self, ZONE_POLYGON_BASE:New(ZoneName, Points)) --#ZONE_ELASTIC
-- Zone objects are added to the _DATABASE and SET_ZONE objects. -- Zone objects are added to the _DATABASE and SET_ZONE objects.
_EVENTDISPATCHER:CreateEventNewZone( self ) _EVENTDISPATCHER:CreateEventNewZone( self )
if Points then if Points then
self.points=Points self.points=Points
end end
return self return self
end end
@@ -3443,10 +3552,10 @@ do -- ZONE_ELASTIC
-- @param DCS#Vec2 Vec2 Point in 2D (with x and y coordinates). -- @param DCS#Vec2 Vec2 Point in 2D (with x and y coordinates).
-- @return #ZONE_ELASTIC self -- @return #ZONE_ELASTIC self
function ZONE_ELASTIC:AddVertex2D(Vec2) function ZONE_ELASTIC:AddVertex2D(Vec2)
-- Add vec2 to points. -- Add vec2 to points.
table.insert(self.points, Vec2) table.insert(self.points, Vec2)
return self return self
end end
@@ -3456,10 +3565,10 @@ do -- ZONE_ELASTIC
-- @param DCS#Vec3 Vec3 Point in 3D (with x, y and z coordinates). Only the x and z coordinates are used. -- @param DCS#Vec3 Vec3 Point in 3D (with x, y and z coordinates). Only the x and z coordinates are used.
-- @return #ZONE_ELASTIC self -- @return #ZONE_ELASTIC self
function ZONE_ELASTIC:AddVertex3D(Vec3) function ZONE_ELASTIC:AddVertex3D(Vec3)
-- Add vec2 from vec3 to points. -- Add vec2 from vec3 to points.
table.insert(self.points, {x=Vec3.x, y=Vec3.z}) table.insert(self.points, {x=Vec3.x, y=Vec3.z})
return self return self
end end
@@ -3469,10 +3578,10 @@ do -- ZONE_ELASTIC
-- @param Core.Set#SET_GROUP GroupSet Set of groups. -- @param Core.Set#SET_GROUP GroupSet Set of groups.
-- @return #ZONE_ELASTIC self -- @return #ZONE_ELASTIC self
function ZONE_ELASTIC:AddSetGroup(GroupSet) function ZONE_ELASTIC:AddSetGroup(GroupSet)
-- Add set to table. -- Add set to table.
table.insert(self.setGroups, GroupSet) table.insert(self.setGroups, GroupSet)
return self return self
end end
@@ -3484,13 +3593,13 @@ do -- ZONE_ELASTIC
-- @param #boolean Draw Draw the zone. Default `nil`. -- @param #boolean Draw Draw the zone. Default `nil`.
-- @return #ZONE_ELASTIC self -- @return #ZONE_ELASTIC self
function ZONE_ELASTIC:Update(Delay, Draw) function ZONE_ELASTIC:Update(Delay, Draw)
-- Debug info. -- Debug info.
self:T(string.format("Updating ZONE_ELASTIC %s", tostring(self.ZoneName))) self:T(string.format("Updating ZONE_ELASTIC %s", tostring(self.ZoneName)))
-- Copy all points. -- Copy all points.
local points=UTILS.DeepCopy(self.points or {}) local points=UTILS.DeepCopy(self.points or {})
if self.setGroups then if self.setGroups then
for _,_setGroup in pairs(self.setGroups) do for _,_setGroup in pairs(self.setGroups) do
local setGroup=_setGroup --Core.Set#SET_GROUP local setGroup=_setGroup --Core.Set#SET_GROUP
@@ -3505,7 +3614,7 @@ do -- ZONE_ELASTIC
-- Update polygon verticies from points. -- Update polygon verticies from points.
self._.Polygon=self:_ConvexHull(points) self._.Polygon=self:_ConvexHull(points)
if Draw~=false then if Draw~=false then
if self.DrawID or Draw==true then if self.DrawID or Draw==true then
self:UndrawZone() self:UndrawZone()
@@ -3515,7 +3624,7 @@ do -- ZONE_ELASTIC
return self return self
end end
--- Start the updating scheduler. --- Start the updating scheduler.
-- @param #ZONE_ELASTIC self -- @param #ZONE_ELASTIC self
-- @param #number Tstart Time in seconds before the updating starts. -- @param #number Tstart Time in seconds before the updating starts.
@@ -3524,9 +3633,9 @@ do -- ZONE_ELASTIC
-- @param #boolean Draw Draw the zone. Default `nil`. -- @param #boolean Draw Draw the zone. Default `nil`.
-- @return #ZONE_ELASTIC self -- @return #ZONE_ELASTIC self
function ZONE_ELASTIC:StartUpdate(Tstart, dT, Tstop, Draw) function ZONE_ELASTIC:StartUpdate(Tstart, dT, Tstop, Draw)
self.updateID=self:ScheduleRepeat(Tstart, dT, 0, Tstop, ZONE_ELASTIC.Update, self, 0, Draw) self.updateID=self:ScheduleRepeat(Tstart, dT, 0, Tstop, ZONE_ELASTIC.Update, self, 0, Draw)
return self return self
end end
@@ -3535,46 +3644,46 @@ do -- ZONE_ELASTIC
-- @param #number Delay Delay in seconds before the scheduler will be stopped. Default 0. -- @param #number Delay Delay in seconds before the scheduler will be stopped. Default 0.
-- @return #ZONE_ELASTIC self -- @return #ZONE_ELASTIC self
function ZONE_ELASTIC:StopUpdate(Delay) function ZONE_ELASTIC:StopUpdate(Delay)
if Delay and Delay>0 then if Delay and Delay>0 then
self:ScheduleOnce(Delay, ZONE_ELASTIC.StopUpdate, self) self:ScheduleOnce(Delay, ZONE_ELASTIC.StopUpdate, self)
else else
if self.updateID then if self.updateID then
self:ScheduleStop(self.updateID) self:ScheduleStop(self.updateID)
self.updateID=nil self.updateID=nil
end end
end end
return self return self
end end
--- Create a convec hull. --- Create a convec hull.
-- @param #ZONE_ELASTIC self -- @param #ZONE_ELASTIC self
-- @param #table pl Points -- @param #table pl Points
-- @return #table Points -- @return #table Points
function ZONE_ELASTIC:_ConvexHull(pl) function ZONE_ELASTIC:_ConvexHull(pl)
if #pl == 0 then if #pl == 0 then
return {} return {}
end end
table.sort(pl, function(left,right) table.sort(pl, function(left,right)
return left.x < right.x return left.x < right.x
end) end)
local h = {} local h = {}
-- Function: ccw > 0 if three points make a counter-clockwise turn, clockwise if ccw < 0, and collinear if ccw = 0. -- Function: ccw > 0 if three points make a counter-clockwise turn, clockwise if ccw < 0, and collinear if ccw = 0.
local function ccw(a,b,c) local function ccw(a,b,c)
return (b.x - a.x) * (c.y - a.y) > (b.y - a.y) * (c.x - a.x) return (b.x - a.x) * (c.y - a.y) > (b.y - a.y) * (c.x - a.x)
end end
-- lower hull -- lower hull
for i,pt in pairs(pl) do for i,pt in pairs(pl) do
while #h >= 2 and not ccw(h[#h-1], h[#h], pt) do while #h >= 2 and not ccw(h[#h-1], h[#h], pt) do
@@ -3582,7 +3691,7 @@ do -- ZONE_ELASTIC
end end
table.insert(h,pt) table.insert(h,pt)
end end
-- upper hull -- upper hull
local t = #h + 1 local t = #h + 1
for i=#pl, 1, -1 do for i=#pl, 1, -1 do
@@ -3592,12 +3701,12 @@ do -- ZONE_ELASTIC
end end
table.insert(h, pt) table.insert(h, pt)
end end
table.remove(h, #h) table.remove(h, #h)
return h return h
end end
end end
@@ -3634,7 +3743,7 @@ ZONE_OVAL = {
function ZONE_OVAL:New(name, vec2, major_axis, minor_axis, angle) function ZONE_OVAL:New(name, vec2, major_axis, minor_axis, angle)
self = BASE:Inherit(self, ZONE_BASE:New()) self = BASE:Inherit(self, ZONE_BASE:New())
self.ZoneName = name self.ZoneName = name
self.CenterVec2 = vec2 self.CenterVec2 = vec2
self.MajorAxis = major_axis self.MajorAxis = major_axis
@@ -3672,7 +3781,7 @@ function ZONE_OVAL:NewFromDrawing(DrawingName)
return self return self
end end
--- Gets the major axis of the oval. --- Gets the major axis of the oval.
-- @param #ZONE_OVAL self -- @param #ZONE_OVAL self
-- @return #number The major axis of the oval -- @return #number The major axis of the oval
function ZONE_OVAL:GetMajorAxis() function ZONE_OVAL:GetMajorAxis()
@@ -3868,7 +3977,7 @@ do -- ZONE_AIRBASE
self._.ZoneAirbase = Airbase self._.ZoneAirbase = Airbase
self._.ZoneVec2Cache = self._.ZoneAirbase:GetVec2() self._.ZoneVec2Cache = self._.ZoneAirbase:GetVec2()
if Airbase:IsShip() then if Airbase:IsShip() then
self.isShip=true self.isShip=true
self.isHelipad=false self.isHelipad=false
@@ -3876,11 +3985,11 @@ do -- ZONE_AIRBASE
elseif Airbase:IsHelipad() then elseif Airbase:IsHelipad() then
self.isShip=false self.isShip=false
self.isHelipad=true self.isHelipad=true
self.isAirdrome=false self.isAirdrome=false
elseif Airbase:IsAirdrome() then elseif Airbase:IsAirdrome() then
self.isShip=false self.isShip=false
self.isHelipad=false self.isHelipad=false
self.isAirdrome=true self.isAirdrome=true
end end
-- Zone objects are added to the _DATABASE and SET_ZONE objects. -- Zone objects are added to the _DATABASE and SET_ZONE objects.

View File

@@ -1064,9 +1064,9 @@ function UTILS.BeaufortScale(speed)
return bn,bd return bn,bd
end end
--- Split string at seperators. C.f. [split-string-in-lua](http://stackoverflow.com/questions/1426954/split-string-in-lua). --- Split string at separators. C.f. [split-string-in-lua](http://stackoverflow.com/questions/1426954/split-string-in-lua).
-- @param #string str Sting to split. -- @param #string str Sting to split.
-- @param #string sep Speparator for split. -- @param #string sep Separator for split.
-- @return #table Split text. -- @return #table Split text.
function UTILS.Split(str, sep) function UTILS.Split(str, sep)
local result = {} local result = {}
@@ -2146,17 +2146,17 @@ function UTILS.IsLoadingDoorOpen( unit_name )
return true return true
end end
if string.find(type_name, "Bell-47") then -- bell aint got no doors so always ready to load injured soldiers if type_name == "Bell-47" then -- bell aint got no doors so always ready to load injured soldiers
BASE:T(unit_name .. " door is open") BASE:T(unit_name .. " door is open")
return true return true
end end
if string.find(type_name, "UH-60L") and (unit:getDrawArgumentValue(401) == 1 or unit:getDrawArgumentValue(402) == 1) then if type_name == "UH-60L" and (unit:getDrawArgumentValue(401) == 1 or unit:getDrawArgumentValue(402) == 1) then
BASE:T(unit_name .. " cargo door is open") BASE:T(unit_name .. " cargo door is open")
return true return true
end end
if string.find(type_name, "UH-60L" ) and (unit:getDrawArgumentValue(38) == 1 or unit:getDrawArgumentValue(400) == 1 ) then if type_name == "UH-60L" and (unit:getDrawArgumentValue(38) > 0 or unit:getDrawArgumentValue(400) == 1 ) then
BASE:T(unit_name .. " front door(s) are open") BASE:T(unit_name .. " front door(s) are open")
return true return true
end end

View File

@@ -3772,54 +3772,66 @@ function CONTROLLABLE:OptionProhibitAfterburner( Prohibit )
return self return self
end end
--- Defines the usage of Electronic Counter Measures by airborne forces. Disables the ability for AI to use their ECM. --- [Air] Defines the usage of Electronic Counter Measures by airborne forces.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param #number ECMvalue Can be - 0=Never on, 1=if locked by radar, 2=if detected by radar, 3=always on, defaults to 1
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:OptionECM_Never() function CONTROLLABLE:OptionECM( ECMvalue )
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
if self:IsAir() then local DCSControllable = self:GetDCSObject()
self:SetOption( AI.Option.Air.id.ECM_USING, 0 ) if DCSControllable then
local Controller = self:_GetController()
if self:IsAir() then
Controller:setOption( AI.Option.Air.id.ECM_USING, ECMvalue or 1 )
end
end end
return self return self
end end
--- Defines the usage of Electronic Counter Measures by airborne forces. If the AI is actively being locked by an enemy radar they will enable their ECM jammer. --- [Air] Defines the usage of Electronic Counter Measures by airborne forces. Disables the ability for AI to use their ECM.
-- @param #CONTROLLABLE self
-- @return #CONTROLLABLE self
function CONTROLLABLE:OptionECM_Never()
self:F2( { self.ControllableName } )
self:OptionECM(0)
return self
end
--- [Air] Defines the usage of Electronic Counter Measures by airborne forces. If the AI is actively being locked by an enemy radar they will enable their ECM jammer.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:OptionECM_OnlyLockByRadar() function CONTROLLABLE:OptionECM_OnlyLockByRadar()
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
if self:IsAir() then self:OptionECM(1)
self:SetOption( AI.Option.Air.id.ECM_USING, 1 )
end
return self return self
end end
--- Defines the usage of Electronic Counter Measures by airborne forces. If the AI is being detected by a radar they will enable their ECM. --- [Air] Defines the usage of Electronic Counter Measures by airborne forces. If the AI is being detected by a radar they will enable their ECM.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:OptionECM_DetectedLockByRadar() function CONTROLLABLE:OptionECM_DetectedLockByRadar()
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
if self:IsAir() then self:OptionECM(2)
self:SetOption( AI.Option.Air.id.ECM_USING, 2 )
end
return self return self
end end
--- Defines the usage of Electronic Counter Measures by airborne forces. AI will leave their ECM on all the time. --- [Air] Defines the usage of Electronic Counter Measures by airborne forces. AI will leave their ECM on all the time.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:OptionECM_AlwaysOn() function CONTROLLABLE:OptionECM_AlwaysOn()
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
if self:IsAir() then self:OptionECM(3)
self:SetOption( AI.Option.Air.id.ECM_USING, 3 )
end
return self return self
end end

View File

@@ -0,0 +1,77 @@
---
parent: Beginner
nav_order: 06
---
# How to ask for help
{: .no_toc }
1. Table of contents
{:toc}
After you have tried to solve the problem on your own, you can also get help
from the community.
{: .highlight }
> But it is important to follow certain rules! Read them below.
## Communities
There are two ways to communicate with the community.
The fastest way is to use Discord:
- <https://discord.gg/gj68fm969S>{:target="_blank"}
But if you don't like Discord, you are able to post in the DCS forum.
Check out the MOOSE thread here:
- <https://forums.eagle.ru/showthread.php?t=138043>
## How to post requests
MOOSE is a community project and support is community based.
Please remember when posting a question:
- Before posting anything follow the [troubleshooting steps].
- **Read your logs**.
A post should contain the following:
1. A describtion what you expected to happen and what actually happened.
- Do not use vague words this stuff is hard to help with! Be specific.
2. Describe what happens instead.
- The less detail you offer, the less chance you can be helped.
- Dont say it doesnt work. Or is it broken. Say what it actually does.
3. Post your code in Discord as formatted code:
- Wrap a single line of code in backticks \` like this:
![discord-single-line-code.png](../images/beginner/discord-single-line-code.png)
- Multiple lines of code should be posted like this:
![discord-multi-line-code.png](../images/beginner/discord-multi-line-code.png)
- Post your log lines with the error or warning messages. Format them like this:
![discord-fomat-logs.png](../images/beginner/discord-fomat-logs.png)
- Some complex problems need the mission (.miz file) also.
- But post your mission only when requested.
- Try to simplify your mission if it is complex!
There are people in the Discord and in the forum, who spend their free time to
help you. <br />
It is your responsibility to make their "work" as easy as possible.
Welcome to MOOSE and good luck!
## Next step
Last but not least some [tipps and tricks].
[troubleshooting steps]: problems.md
[tipps and tricks]: tipps-and-tricks.md

View File

@@ -9,5 +9,50 @@ nav_order: 04
1. Table of contents 1. Table of contents
{:toc} {:toc}
{: .warning } The best way to get compftable with a Moose class is to try the demo missions of
> THIS DOCUMENT IS STILL WORK IN PROGRESS! the class you want to learn. The Moose team created a lot of demo missions for
most of the classes.
## Download demo missions
Go to the repository [MOOSE_MISSIONS]{:target="_blank"}, search the folder of
the class, download the mission (`.miz`) and rum them.
## Read the mission script
In the same folder a `.lua` file with the same name is placed which is the
included mission script. You can watch these mission scripts easily online at
GitHub to understand what is happening in the mission.
## Read documentation
Next step is to read the [documentation]{:target="_blank"} of the class to
understand the code of the demo mission.
{: .note }
> The documentation is quite long and might be confusing for beginners.
> Start by looking at the description at the top of the documentation of a
> class. It often contains examples and explanations. <br /><br />
> Then search for the function names and look at the description of the
> functions and its parameters.
## Make small changes to the script
Download the `.lua` file, change the parameters to suit your needs in
[Notepad++]{:target="_blank"}, add it to the mission and rerun the mission.
Observe what happens and adapt the code.
If you want to use more functions combine them all up.
{: .note }
> But it is wise to do this in small steps. So it is easier to find errors.
## Next step
If the mission shows not the expected behaviour take a look at section
[problems].
[MOOSE_MISSIONS]: https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop
[documentation]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/index.html
[Notepad++]: https://notepad-plus-plus.org/downloads/
[problems]: problems.md

View File

@@ -144,9 +144,16 @@ have create everything on your own.
- Change the text a little bit, like `Hello Dude! ...` and save the file. - Change the text a little bit, like `Hello Dude! ...` and save the file.
- Run the mission again. - Run the mission again.
- The text will not be changed in the mission. Why? - The text will not be changed in the mission. Why?
The mission editor copies the script into the mission file when you add it.
Ever change on the script file on your hard disk is not recognized by mission editor. {: .important }
You have to add the file after each change again. The mission editor copies the script into the mission file when you add it.
Every change on the script file on your hard disk is not recognized by mission
editor. **You have to add the file after each change again!**
There is also another method available to dynamically load mission scripts.
But this method has some brawbacks and will be explained in the advanced section.
Now we add the mission script again:
- On the left side of the `TRIGGERS` dialog click on `Load Mission Script`. - On the left side of the `TRIGGERS` dialog click on `Load Mission Script`.
- On the right side under `ACTIONS` you need to add the script again: - On the right side under `ACTIONS` you need to add the script again:

46
docs/beginner/problems.md Normal file
View File

@@ -0,0 +1,46 @@
---
parent: Beginner
nav_order: 05
---
# Problems
{: .no_toc }
1. Table of contents
{:toc}
## Something went wrong
If the mission shows not the expected behaviour do the following steps:
1. Double check if you added the changed mission script to the mission again!
1. Check if the triggers are configured as requested in the last sections.
## Read the logs
The DCS log is a super important and useful log for the entire of DCS World.
All scripting and other errors are recorded here. It is the one stop shop for
things that occurred in your mission. It will tell you if there was a mistake.
1. Open the file `dcs.log` in the `Logs` subfolder in your DCS
[Saved Games folder].
1. Search for the following line: `*** MOOSE INCLUDE END ***`
- If it is included in the log, Moose was loaded.
- If the line is not in the log check the triggers again!
1. Search for lines with `SCRIPTING` and `WARNING` or `ERROR` and read them.
- This might help to find your error.
{: .note }
> You will find a lot of warning and error lines in the log which are not
> related to `SCRIPTING`. They are related to stuff from Eagle Dynamics or
> Third Parties and you have to ignore them. EA does the same. ;o)
## Next step
If you don't find the error and/or don't understand the messages in the log file
you can [ask for help].
[Saved Games folder]: tipps-and-tricks.md#find-the-saved-games-folder
[ask for help]: ask-for-help.md

View File

@@ -33,7 +33,9 @@ This folder can be found in your userprofile as subfolder of `Saved Games`.
The easiest way to find it, is to open search and paste the text below into it The easiest way to find it, is to open search and paste the text below into it
and press Enter: and press Enter:
```%userprofile%\Saved Games``` ```
%userprofile%\Saved Games
```
{: .note } {: .note }
> The text will work even if your Windows is installed with another language, > The text will work even if your Windows is installed with another language,

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB