ARTY v0.9.93

added new mark parameters
LLDMS coordinate assignment
This commit is contained in:
funkyfranky 2018-06-06 00:51:59 +02:00
parent 927ae59f75
commit a2790f500c
2 changed files with 283 additions and 127 deletions

View File

@ -251,6 +251,28 @@ do -- COORDINATE
return { x = self.x, y = self.z }
end
--- Returns the coordinate from the latitude and longitude given in decimal degrees.
-- @param #COORDINATE self
-- @param #number latitude Latitude in decimal degrees.
-- @param #number longitude Longitude in decimal degrees.
-- @param #number altitude (Optional) Altitude in meters. Default is the land height at the coordinate.
-- @return #COORDINATE
function COORDINATE:NewFromLLDD( latitude, longitude, altitude)
-- Returns a point from latitude and longitude in the vec3 format.
local vec3=coord.LLtoLO(latitude, longitude)
-- Convert vec3 to coordinate object.
local _coord=self:NewFromVec3(vec3)
-- Adjust height
if altitude==nil then
_coord.y=altitude
end
return _coord
end
--- Returns if the 2 coordinates are at the same 2D position.
-- @param #COORDINATE self

View File

@ -531,7 +531,7 @@ ARTY.id="ARTY | "
--- Arty script version.
-- @field #string version
ARTY.version="0.9.92"
ARTY.version="0.9.93"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -1139,9 +1139,7 @@ function ARTY:onafterStart(Controllable, From, Event, To)
if _dbproperties~=nil then
for property,value in pairs(_dbproperties) do
self:T({property=property, value=value})
--if self[property]==nil then
self[property]=value
--end
end
end
@ -1475,14 +1473,13 @@ function ARTY:onEvent(Event)
local batteryname=self.Controllable:GetName()
local batterycoalition=self.Controllable:GetCoalition()
self:T(string.format("Event captured = %s", tostring(batteryname)))
self:T(string.format("Event id = %s", tostring(Event.id)))
self:T(string.format("Event time = %s", tostring(Event.time)))
self:T(string.format("Event idx = %s", tostring(Event.idx)))
self:T(string.format("Event coalition = %s", tostring(Event.coalition)))
self:T(string.format("Event group id = %s", tostring(Event.groupID)))
self:T(string.format("Event text = %s", tostring(Event.text)))
self:E({eventid=Event.id, vec3=Event.pos})
self:T2(string.format("Event captured = %s", tostring(batteryname)))
self:T2(string.format("Event id = %s", tostring(Event.id)))
self:T2(string.format("Event time = %s", tostring(Event.time)))
self:T2(string.format("Event idx = %s", tostring(Event.idx)))
self:T2(string.format("Event coalition = %s", tostring(Event.coalition)))
self:T2(string.format("Event group id = %s", tostring(Event.groupID)))
self:T2(string.format("Event text = %s", tostring(Event.text)))
if Event.initiator~=nil then
local _unitname=Event.initiator:getName()
self:T(string.format("Event ini unit name = %s", tostring(_unitname)))
@ -1589,6 +1586,11 @@ function ARTY:_OnEventMarkChange(Event)
-- Evaluate marker text and extract parameters.
local _assign=self:_Markertext(Event.text)
-- Check if ENGAGE or MOVE or REQUEST keywords were found.
if _assign==nil or not (_assign.engage or _assign.move or _assign.request) then
return
end
-- Check if job is assigned to this ARTY group. Default is for all ARTY groups.
local _assigned=true
@ -1606,11 +1608,6 @@ function ARTY:_OnEventMarkChange(Event)
if not _assigned then
return
end
-- Check if ENGAGE or MOVE or REQUEST keywords were found.
if not (_assign.engage or _assign.move or _assign.request) then
return
end
-- Check if the authorization key is required and if it is valid.
local _validkey=self:_MarkerKeyAuthentification(Event.text)
@ -1620,7 +1617,16 @@ function ARTY:_OnEventMarkChange(Event)
if _assign.requestammo then
self:_MarkRequestAmmo()
end
-- Done!
if _assign.requestmoves then
self:_MarkRequestMoves()
end
if _assign.requesttargets then
self:_MarkRequestTargets()
end
if _assign.requestrearming then
self:Rearm()
end
-- Requests Done ==> End of story!
return
end
@ -1649,6 +1655,11 @@ function ARTY:_OnEventMarkChange(Event)
-- Also I don't know who can see the mark which was created.
_coord:RemoveMark(Event.idx)
-- Coordinate was given in text, e.g. as lat, long.
if _assign.coord then
_coord=_assign.coord
end
-- Anticipate marker ID.
-- WARNING: Make sure, no marks are set until the COORDINATE:MarkToCoalition() is called or the target/move name will be wrong and target cannot be removed by deleting its marker.
local _id=UTILS._MarkID+1
@ -2594,7 +2605,7 @@ end
function ARTY:_Move(group, ToCoord, Speed, OnRoad)
-- Clear all tasks.
group:ClearTasks()
--group:ClearTasks()
group:OptionAlarmStateGreen()
group:OptionROEHoldFire()
@ -2983,122 +2994,147 @@ function ARTY:_Markertext(text)
assignment.readonly=false
assignment.canceltarget=false
assignment.cancelcurrent=false
--assignment.time=nil
--assignment.nshells=nil
--assignment.prio=nil
--assignment.maxengage=nil
--assignment.radius=nil
--assignment.weapontype=nil
--assignment.speed=nil
--assignment.onroad=nil
--assignment.key=nil
if text:lower():find("arty") then
if text:lower():find("engage") then
assignment.engage=true
elseif text:lower():find("move") then
assignment.move=true
elseif text:lower():find("request") then
assignment.request=true
else
self:E(ARTY.id.."ERROR: Neither ENGAGE nor MOVE keyword specified!")
return
end
-- Check for correct keywords.
if text:lower():find("arty engage") or text:lower():find("arty attack") then
assignment.engage=true
elseif text:lower():find("arty move") or text:lower():find("arty relocate") then
assignment.move=true
elseif text:lower():find("arty request") then
assignment.request=true
else
self:E(ARTY.id..'ERROR: Neither "ARTY ENGAGE" nor "ARTY MOVE" nor "ARTY RELOCATE" nor "ARTY REQUEST" keyword specified!')
return nil
end
-- keywords are split by ","
local keywords=self:_split(text, ",")
-- keywords are split by ","
local keywords=self:_split(text, ",")
for _,key in pairs(keywords) do
for _,key in pairs(keywords) do
local s=self:_split(key, " ")
local val=s[2]
-- Battery name, i.e. which ARTY group should fire.
if key:lower():find("battery") then
local v=self:_split(key, '"')
for i=2,#v,2 do
table.insert(assignment.battery, v[i])
self:T2(ARTY.id..string.format("Key Battery=%s.", v[i]))
end
elseif key:lower():find("time") then
local s=self:_split(key, " ")
local val=s[2]
if val:lower():find("now") then
assignment.time=self:_SecondsToClock(timer.getTime0()+2)
else
assignment.time=val
end
self:T2(ARTY.id..string.format("Key Time=%s.", val))
elseif key:lower():find("shot") then
-- Battery name, i.e. which ARTY group should fire.
if key:lower():find("battery") then
assignment.nshells=tonumber(s[2])
self:T(ARTY.id..string.format("Key Shot=%s.", val))
elseif key:lower():find("prio") then
assignment.prio=tonumber(val)
self:T2(string.format("Key Prio=%s.", val))
elseif key:lower():find("maxengage") then
assignment.maxengage=tonumber(val)
self:T2(ARTY.id..string.format("Key Maxengage=%s.", val))
elseif key:lower():find("radius") then
assignment.radius=tonumber(val)
self:T2(ARTY.id..string.format("Key Radius=%s.", val))
elseif key:lower():find("weapon") then
if val:lower():find("cannon") then
assignment.weapontype=ARTY.WeaponType.Cannon
elseif val:lower():find("rocket") then
assignment.weapontype=ARTY.WeaponType.Rockets
elseif val:lower():find("missile") then
assignment.weapontype=ARTY.WeaponType.GuidedMissile
elseif val:lower():find("nuke") then
assignment.weapontype=ARTY.WeaponType.TacticalNukes
else
assignment.weapontype=ARTY.WeaponType.Auto
end
self:T2(ARTY.id..string.format("Key Weapon=%s.", val))
elseif key:lower():find("speed") then
assignment.speed=tonumber(val)
self:T2(ARTY.id..string.format("Key Speed=%s.", val))
elseif key:lower():find("on road") or key:lower():find("onroad") or key:lower():find("use road")then
assignment.onroad=true
self:T2(ARTY.id..string.format("Key Onroad=true."))
elseif key:lower():find("irrevocable") or key:lower():find("readonly") then
assignment.readonly=true
self:T2(ARTY.id..string.format("Key Readonly=true."))
elseif key:lower():find("canceltarget") then
assignment.canceltarget=true
self:T2(ARTY.id..string.format("Key Cancel Target (before move)=true."))
elseif key:lower():find("cancelcurrent") then
assignment.cancelcurrent=true
self:T2(ARTY.id..string.format("Key Cancel Current=true."))
elseif assignment.request and key:lower():find("rearm") then
assignment.requestrearming=true
self:T2(ARTY.id..string.format("Key Request Rearming=true."))
elseif assignment.request and key:lower():find("ammo") then
assignment.requestammo=true
self:T2(ARTY.id..string.format("Key Request Ammo=true."))
elseif assignment.request and key:lower():find("target") then
assignment.requesttargets=true
self:T2(ARTY.id..string.format("Key Request Targets=true."))
elseif assignment.request and (key:lower():find("move") or key:lower():find("relocation")) then
assignment.requestmoves=true
self:T2(ARTY.id..string.format("Key Request Moves=true."))
elseif key:lower():find("lldms") then
local _flat = "%d+:%d+:%d+%s*[N,S]"
local _flon = "%d+:%d+:%d+%s*[W,E]"
local _lat=key:match(_flat)
local _lon=key:match(_flon)
self:T2(ARTY.id..string.format("Key LLDMS: lat=%s, long=%s", _lat,_lon))
if _lat and _lon then
-- Convert DMS string to DD numbers format.
local _latitude, _longitude=self:_LLDMS2DD(_lat, _lon)
self:T2(ARTY.id..string.format("Key LLDMS: lat=%.3f, long=%.3f", _latitude,_longitude))
local v=self:_split(key, '"')
for i=2,#v,2 do
table.insert(assignment.battery, v[i])
self:T2(ARTY.id..string.format("Key Battery=%s.", v[i]))
-- Convert LL to coordinate object.
if _latitude and _longitude then
assignment.coord=COORDINATE:NewFromLLDD(_latitude,_longitude)
end
elseif key:lower():find("time") then
if val:lower():find("now") then
assignment.time=self:_SecondsToClock(timer.getTime0()+5)
else
assignment.time=val
end
self:T2(ARTY.id..string.format("Key Time=%s.", val))
elseif key:lower():find("shot") then
assignment.nshells=tonumber(s[2])
self:T(ARTY.id..string.format("Key Shot=%s.", val))
elseif key:lower():find("prio") then
assignment.prio=tonumber(val)
self:T2(string.format("Key Prio=%s.", val))
elseif key:lower():find("maxengage") then
assignment.maxengage=tonumber(val)
self:T2(ARTY.id..string.format("Key Maxengage=%s.", val))
elseif key:lower():find("radius") then
assignment.radius=tonumber(val)
self:T2(ARTY.id..string.format("Key Radius=%s.", val))
elseif key:lower():find("weapon") then
if val:lower():find("cannon") then
assignment.weapontype=ARTY.WeaponType.Cannon
elseif val:lower():find("rocket") then
assignment.weapontype=ARTY.WeaponType.Rockets
elseif val:lower():find("missile") then
assignment.weapontype=ARTY.WeaponType.GuidedMissile
elseif val:lower():find("nuke") then
assignment.weapontype=ARTY.WeaponType.TacticalNukes
else
assignment.weapontype=ARTY.WeaponType.Auto
end
self:T2(ARTY.id..string.format("Key Weapon=%s.", val))
elseif key:lower():find("speed") then
assignment.speed=tonumber(val)
self:T2(ARTY.id..string.format("Key Speed=%s.", val))
elseif key:lower():find("on road") or key:lower():find("onroad") or key:lower():find("use road")then
assignment.onroad=true
self:T2(ARTY.id..string.format("Key Onroad=true."))
elseif key:lower():find("irrevocable") or key:lower():find("readonly") then
assignment.readonly=true
self:T2(ARTY.id..string.format("Key Readonly=true."))
elseif key:lower():find("canceltarget") then
assignment.canceltarget=true
self:T2(ARTY.id..string.format("Key Cancel Target (before move)=true."))
elseif key:lower():find("cancelcurrent") then
assignment.cancelcurrent=true
self:T2(ARTY.id..string.format("Key Cancel Current=true."))
elseif assignment.request and key:lower():find("ammo") then
assignment.requestammo=true
end
end
else
self:T2(ARTY.id..string.format("This is NO arty command:\n%s", tostring(text)))
end
end
end
return assignment
@ -3110,6 +3146,44 @@ function ARTY:_MarkRequestAmmo()
self:GetAmmo(true)
end
--- Request Moves.
-- @param #ARTY self
function ARTY:_MarkRequestMoves()
local text=string.format("%s, relocations:", self.Controllable:GetName())
if self.currentMove then
text=text..string.format("\n- %s", self:_MoveInfo(self.currentMove))
else
text=text..string.format("\n- no current relocation")
end
if #self.moves>0 then
for _,move in pairs(self.moves) do
text=text..string.format("\n- %s", self:_MoveInfo(move))
end
else
text=text..string.format("\n- no more relocations")
end
MESSAGE:New(text, 20):Clear():ToCoalition(self.Controllable:GetCoalition())
end
--- Request Targets.
-- @param #ARTY self
function ARTY:_MarkRequestTargets()
local text=string.format("%s, targets:", self.Controllable:GetName())
if self.currentTarget then
text=text..string.format("\n- %s", self:_TargetInfo(self.currentTarget))
else
text=text..string.format("\n- no current target")
end
if #self.targets>0 then
for _,target in pairs(self.targets) do
text=text..string.format("\n- %s", self:_TargetInfo(target))
end
else
text=text..string.format("\n- no more targets")
end
MESSAGE:New(text, 20):Clear():ToCoalition(self.Controllable:GetCoalition())
end
--- Create a name for an engagement initiated by placing a marker.
-- @param #ARTY self
-- @param #number markerid ID of the placed marker.
@ -3320,7 +3394,7 @@ function ARTY:_CheckTargetsInRange()
MESSAGE:New(_name.." assigned.", 10):ToCoalitionIf(self.Controllable:GetCoalition(), self.report or self.Debug)
-- Assign relocation move.
self:AssignMoveCoord(_tocoord, nil, nil, self.autorelocateonroad, false, _name, true)
self:AssignMoveCoord(_tocoord, nil, nil, self.autorelocateonroad, false, _name, true)
end
@ -3716,6 +3790,66 @@ function ARTY:_MoveInfo(move)
return string.format("%s: time=%s, speed=%d, onroad=%s, cancel=%s", move.name, _clock, move.speed, tostring(move.onroad), tostring(move.cancel))
end
--- Convert Latitude and Lontigude from DMS to DD.
-- @param #ARTY self
-- @param #string l1 Latitude or longitude as string in the format DD:MM:SS N/S/W/E
-- @param #string l2 Latitude or longitude as string in the format DD:MM:SS N/S/W/E
-- @return #number Latitude in decimal degree format.
-- @return #number Longitude in decimal degree format.
function ARTY:_LLDMS2DD(l1,l2)
self:F2(l1,l2)
-- Make an array of lat and long.
local _latlong={l1,l2}
local _latitude=nil
local _longitude=nil
for _,ll in pairs(_latlong) do
-- Format is expected as "DD:MM:SS" or "D:M:S".
local _format = "%d+:%d+:%d+"
local _ldms=ll:match(_format)
if ldms then
-- Split DMS to degrees, minutes and seconds.
local _dms=self:_split(_ldms, ":")
local _deg=tonumber(_dms[1])
local _min=tonumber(_dms[2])
local _sec=tonumber(_dms[3])
-- Convert DMS to DD.
local function DMS2DD(d,m,s)
return d+m/60+s/3600
end
-- Detect with hemisphere is meant.
if ll:match("N") then
_latitude=DMS2DD(_deg,_min,_sec)
elseif ll:match("S") then
_latitude=-DMS2DD(_deg,_min,_sec)
elseif ll:match("W") then
_longitude=-DMS2DD(_deg,_min,_sec)
elseif ll:match("E") then
_longitude=DMS2DD(_deg,_min,_sec)
end
-- Debug text.
local text=string.format("DMS %02d Deg %02d min %02d sec",_deg,_min,_sec)
self:T2(ARTY.id..text)
end
end
-- Debug text.
local text=string.format("\nLatitude %.3f", _latitude)
text=text..string.format("\nLongitude %.3f", _longitude)
self:T2(ARTY.id..text)
return _latitude,_longitude
end
--- Convert time in seconds to hours, minutes and seconds.
-- @param #ARTY self
-- @param #number seconds Time in seconds.