This commit is contained in:
Frank 2020-07-24 01:34:38 +02:00
parent 2328f9a36b
commit 04923b65b2
5 changed files with 114 additions and 57 deletions

View File

@ -79,8 +79,6 @@ function ASTAR:New()
self.lid="ASTAR | "
self.Debug=true
return self
end
@ -136,6 +134,19 @@ function ASTAR:AddNode(Node)
return self
end
--- Add a node to the table of grid nodes specifying its coordinate.
-- @param #ASTAR self
-- @param Core.Point#COORDINATE Coordinate The coordinate where the node is created.
-- @return #ASTAR self
function ASTAR:AddNodeFromCoordinate(Coordinate)
local node=self:GetNodeFromCoordinate(Coordinate)
self:AddNode(node)
return self
end
--- Check if the coordinate of a node has is at a valid surface type.
-- @param #ASTAR self
-- @param #ASTAR.Node Node The node to be added.
@ -163,17 +174,6 @@ function ASTAR:CheckValidSurfaceType(Node, SurfaceTypes)
end
--- Set valid neighbours to require line of sight between two nodes.
-- @param #ASTAR self
-- @param #number CorridorWidth Width of LoS corridor in meters.
-- @return #ASTAR self
function ASTAR:SetValidNeighbourLoS(CorridorWidth)
self:SetValidNeighbourFunction(ASTAR.LoS, CorridorWidth)
return self
end
--- Add a function to determine if a neighbour of a node is valid.
-- @param #ASTAR self
-- @param #function NeighbourFunction Function that needs to return *true* for a neighbour to be valid.
@ -191,6 +191,32 @@ function ASTAR:SetValidNeighbourFunction(NeighbourFunction, ...)
return self
end
--- Set valid neighbours to require line of sight between two nodes.
-- @param #ASTAR self
-- @param #number CorridorWidth Width of LoS corridor in meters.
-- @return #ASTAR self
function ASTAR:SetValidNeighbourLoS(CorridorWidth)
self:SetValidNeighbourFunction(ASTAR.LoS, CorridorWidth)
return self
end
--- Set valid neighbours to be in a certain distance.
-- @param #ASTAR self
-- @param #number MaxDistance Max distance between nodes in meters. Default is 2000 m.
-- @return #ASTAR self
function ASTAR:SetValidNeighbourDistance(MaxDistance)
self:SetValidNeighbourFunction(ASTAR.DistMax, MaxDistance)
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Grid functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -329,6 +355,20 @@ function ASTAR.LoS(nodeA, nodeB, corridor)
return los
end
--- Function to check if two nodes have line of sight (LoS).
-- @param #ASTAR.Node nodeA First node.
-- @param #ASTAR.Node nodeB Other node.
-- @param #number distmax Max distance in meters. Default is 2000 m.
-- @return #boolean If true, distance between the two nodes is below threshold.
function ASTAR.DistMax(nodeA, nodeB, distmax)
distmax=distmax or 2000
local dist=nodeA.coordinate:Get2DDistance(nodeB.coordinate)
return dist<=distmax
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Misc functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -338,6 +378,7 @@ end
-- @param #ASTAR self
-- @param Core.Point#COORDINATE Coordinate.
-- @return #ASTAR.Node Cloest node to the coordinate.
-- @return #number Distance to closest node in meters.
function ASTAR:FindClosestNode(Coordinate)
local distMin=math.huge
@ -355,16 +396,22 @@ function ASTAR:FindClosestNode(Coordinate)
end
return closeNode
return closeNode, distMin
end
--- Add a node.
--- Find the start node.
-- @param #ASTAR self
-- @param #ASTAR.Node Node The node to be added to the nodes table.
-- @return #ASTAR self
function ASTAR:FindStartNode()
self.startNode=self:FindClosestNode(self.startCoord)
local node, dist=self:FindClosestNode(self.startCoord)
self.startNode=node
if dist>1000 then
self:AddNode(node)
end
return self
end
@ -375,7 +422,13 @@ end
-- @return #ASTAR self
function ASTAR:FindEndNode()
self.endNode=self:FindClosestNode(self.endCoord)
local node, dist=self:FindClosestNode(self.endCoord)
self.endNode=node
if dist>1000 then
self:AddNode(node)
end
return self
end
@ -432,9 +485,6 @@ function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
table.remove(path, 1)
end
-- Set end time.
local T9=timer.getAbsTime()
-- Debug message.
local text=string.format("Found path with %d nodes", #path)
self:I(self.lid..text)
@ -473,7 +523,7 @@ function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
-- Debug message.
local text=string.format("WARNING: Could NOT find valid path!")
self:I(self.lid..text)
self:E(self.lid..text)
MESSAGE:New(text, 60, "ASTAR"):ToAllIf(self.Debug)
return nil -- no valid path

View File

@ -75,6 +75,7 @@ __Moose.Include( 'Scripts/Moose/Ops/Auftrag.lua' )
__Moose.Include( 'Scripts/Moose/Ops/OpsGroup.lua' )
__Moose.Include( 'Scripts/Moose/Ops/FlightGroup.lua' )
__Moose.Include( 'Scripts/Moose/Ops/NavyGroup.lua' )
__Moose.Include( 'Scripts/Moose/Ops/ArmyGroup.lua' )
__Moose.Include( 'Scripts/Moose/Ops/Squadron.lua' )
__Moose.Include( 'Scripts/Moose/Ops/AirWing.lua' )
__Moose.Include( 'Scripts/Moose/Ops/Intelligence.lua' )

View File

@ -70,6 +70,7 @@ function ARMYGROUP:New(GroupName)
-- Add FSM transitions.
-- From State --> Event --> To State
self:AddTransition("*", "FullStop", "Holding") -- Hold position.
self:AddTransition("*", "Cruise", "Cruising") -- Hold position.
self:AddTransition("*", "Detour", "OnDetour") -- Make a detour to a coordinate and resume route afterwards.
self:AddTransition("OnDetour", "DetourReached", "Cruising") -- Group reached the detour coordinate.
@ -342,11 +343,6 @@ function ARMYGROUP:onafterSpawned(From, Event, To)
end
-- Get orientation.
self.Corientlast=self.group:GetUnit(1):GetOrientationX()
self.depth=self.group:GetHeight()
-- Update route.
self:Cruise()
@ -534,8 +530,6 @@ function ARMYGROUP:onafterCruise(From, Event, To, Speed)
end
--- On after "Dead" event.
-- @param #ARMYGROUP self
-- @param #string From From state.
@ -624,7 +618,7 @@ function ARMYGROUP:OnEventBirth(EventData)
end
--- Flightgroup event function handling the crash of a unit.
--- Event function handling the crash of a unit.
-- @param #ARMYGROUP self
-- @param Core.Event#EVENTDATA EventData Event data.
function ARMYGROUP:OnEventDead(EventData)
@ -649,7 +643,7 @@ function ARMYGROUP:OnEventDead(EventData)
end
--- Flightgroup event function handling the crash of a unit.
--- Event function handling the crash of a unit.
-- @param #ARMYGROUP self
-- @param Core.Event#EVENTDATA EventData Event data.
function ARMYGROUP:OnEventRemoveUnit(EventData)
@ -755,9 +749,7 @@ function ARMYGROUP:_InitGroup()
self.position=self:GetCoordinate()
-- Radio parameters from template.
self.radioOn=true -- Radio is always on for ships.
self.radioFreq=tonumber(self.template.units[1].frequency)/1000000
self.radioModu=tonumber(self.template.units[1].modulation)/1000000
self.radioOn=false -- Radio is always OFF for ground.
-- If not set by the use explicitly yet, we take the template values as defaults.
if not self.radioFreqDefault then
@ -810,7 +802,7 @@ function ARMYGROUP:_InitGroup()
--text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
text=text..string.format("Elements = %d\n", #self.elements)
text=text..string.format("Waypoints = %d\n", #self.waypoints)
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radioFreq, UTILS.GetModulationName(self.radioModu), tostring(self.radioOn))
--text=text..string.format("Radio = %.1f MHz %s %s\n", self.radioFreq, UTILS.GetModulationName(self.radioModu), tostring(self.radioOn))
--text=text..string.format("Ammo = %d (G=%d/R=%d/B=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Bombs, self.ammo.Missiles)
text=text..string.format("FSM state = %s\n", self:GetState())
text=text..string.format("Is alive = %s\n", tostring(self.group:IsAlive()))

View File

@ -1817,13 +1817,15 @@ function AUFTRAG:onafterStatus(From, Event, To)
self:E(self.lid..string.format("ERROR: FSM state %s != %s mission status!", fsmstate, self.status))
end
-- Data on assigned groups.
local text="Group data:"
for groupname,_groupdata in pairs(self.groupdata) do
local groupdata=_groupdata --#AUFTRAG.GroupData
text=text..string.format("\n- %s: status mission=%s opsgroup=%s", groupname, groupdata.status, groupdata.opsgroup and groupdata.opsgroup:GetState() or "N/A")
end
self:I(self.lid..text)
self:T(self.lid..text)
-- Ready to evaluate mission outcome?
local ready2evaluate=self.Tover and Tnow-self.Tover>=self.dTevaluate or false
-- Check if mission is OVER (done or cancelled) and enough time passed to evaluate the result.
@ -2014,7 +2016,7 @@ end
-- @param Ops.OpsGroup#OPSGROUP opsgroup The flight group.
-- @param Ops.OpsGroup#OPSGROUP.Task task Waypoint task.
function AUFTRAG:SetGroupWaypointTask(opsgroup, task)
self:I(self.lid..string.format("Setting waypoint task %s", task and task.description or "WTF"))
self:T2(self.lid..string.format("Setting waypoint task %s", task and task.description or "WTF"))
local groupdata=self:GetGroupData(opsgroup)
if groupdata then
groupdata.waypointtask=task
@ -2037,7 +2039,7 @@ end
-- @param Ops.OpsGroup#OPSGROUP opsgroup The flight group.
-- @param #number waypointindex Waypoint index.
function AUFTRAG:SetGroupWaypointIndex(opsgroup, waypointindex)
self:I(self.lid..string.format("Setting waypoint index %d", waypointindex))
self:T2(self.lid..string.format("Setting waypoint index %d", waypointindex))
local groupdata=self:GetGroupData(opsgroup)
if groupdata then
groupdata.waypointindex=waypointindex
@ -2127,7 +2129,7 @@ end
function AUFTRAG:onafterQueued(From, Event, To, Airwing)
self.status=AUFTRAG.Status.QUEUED
self.airwing=Airwing
self:I(self.lid..string.format("New mission status=%s at airwing %s", self.status, tostring(Airwing.alias)))
self:T(self.lid..string.format("New mission status=%s at airwing %s", self.status, tostring(Airwing.alias)))
end
@ -2138,7 +2140,7 @@ end
-- @param #string To To state.
function AUFTRAG:onafterRequested(From, Event, To)
self.status=AUFTRAG.Status.REQUESTED
self:I(self.lid..string.format("New mission status=%s", self.status))
self:T(self.lid..string.format("New mission status=%s", self.status))
end
--- On after "Assign" event.
@ -2148,7 +2150,7 @@ end
-- @param #string To To state.
function AUFTRAG:onafterAssign(From, Event, To)
self.status=AUFTRAG.Status.ASSIGNED
self:I(self.lid..string.format("New mission status=%s", self.status))
self:T(self.lid..string.format("New mission status=%s", self.status))
end
--- On after "Schedule" event. Mission is added to the mission queue of a FLIGHTGROUP.
@ -2159,7 +2161,7 @@ end
-- @param Ops.OpsGroup#OPSGROUP FlightGroup
function AUFTRAG:onafterScheduled(From, Event, To, FlightGroup)
self.status=AUFTRAG.Status.SCHEDULED
self:I(self.lid..string.format("New mission status=%s", self.status))
self:T(self.lid..string.format("New mission status=%s", self.status))
end
--- On after "Start" event.
@ -2169,7 +2171,7 @@ end
-- @param #string To To state.
function AUFTRAG:onafterStarted(From, Event, To)
self.status=AUFTRAG.Status.STARTED
self:I(self.lid..string.format("New mission status=%s", self.status))
self:T(self.lid..string.format("New mission status=%s", self.status))
end
--- On after "Execute" event.
@ -2179,7 +2181,7 @@ end
-- @param #string To To state.
function AUFTRAG:onafterExecuting(From, Event, To)
self.status=AUFTRAG.Status.EXECUTING
self:I(self.lid..string.format("New mission status=%s", self.status))
self:T(self.lid..string.format("New mission status=%s", self.status))
end
--- On after "Done" event.
@ -2189,7 +2191,7 @@ end
-- @param #string To To state.
function AUFTRAG:onafterDone(From, Event, To)
self.status=AUFTRAG.Status.DONE
self:I(self.lid..string.format("New mission status=%s", self.status))
self:T(self.lid..string.format("New mission status=%s", self.status))
-- Set time stamp.
self.Tover=timer.getAbsTime()
@ -2259,7 +2261,7 @@ end
function AUFTRAG:onafterSuccess(From, Event, To)
self.status=AUFTRAG.Status.SUCCESS
self:I(self.lid..string.format("New mission status=%s", self.status))
self:T(self.lid..string.format("New mission status=%s", self.status))
-- Stop mission.
self:Stop()
@ -2287,20 +2289,20 @@ function AUFTRAG:onafterCancel(From, Event, To)
if self.wingcommander then
self:I(self.lid..string.format("Wingcommander will cancel the mission. Will wait for mission DONE before evaluation!"))
self:T(self.lid..string.format("Wingcommander will cancel the mission. Will wait for mission DONE before evaluation!"))
self.wingcommander:CancelMission(self)
elseif self.airwing then
self:I(self.lid..string.format("Airwing %s will cancel the mission. Will wait for mission DONE before evaluation!", self.airwing.alias))
self:T(self.lid..string.format("Airwing %s will cancel the mission. Will wait for mission DONE before evaluation!", self.airwing.alias))
-- Airwing will cancel all flight missions and remove queued request from warehouse queue.
self.airwing:MissionCancel(self)
else
self:I(self.lid..string.format("No airwing or wingcommander. Attached flights will cancel the mission on their own. Will wait for mission DONE before evaluation!"))
self:T(self.lid..string.format("No airwing or wingcommander. Attached flights will cancel the mission on their own. Will wait for mission DONE before evaluation!"))
for _,_groupdata in pairs(self.groupdata) do
local groupdata=_groupdata --#AUFTRAG.GroupData
@ -2311,7 +2313,7 @@ function AUFTRAG:onafterCancel(From, Event, To)
-- Special mission states.
if self.status==AUFTRAG.Status.PLANNED then
self:I(self.lid..string.format("Cancelled mission was in planned stage. Call it done!"))
self:T(self.lid..string.format("Cancelled mission was in planned stage. Call it done!"))
self:Done()
end
@ -2325,7 +2327,7 @@ end
function AUFTRAG:onafterFailed(From, Event, To)
self.status=AUFTRAG.Status.FAILED
self:I(self.lid..string.format("New mission status=%s", self.status))
self:T(self.lid..string.format("New mission status=%s", self.status))
if self.missionRepeated>=self.missionRepeatMax then
@ -2353,7 +2355,7 @@ function AUFTRAG:onafterRepeat(From, Event, To)
-- Set mission status to PLANNED.
self.status=AUFTRAG.Status.PLANNED
self:I(self.lid..string.format("New mission status=%s (on Repeat)", self.status))
self:T(self.lid..string.format("New mission status=%s (on Repeat)", self.status))
-- Increase repeat counter.
self.missionRepeated=self.missionRepeated+1
@ -2452,7 +2454,7 @@ function AUFTRAG:DelAsset(Asset)
local asset=_asset --Ops.AirWing#AIRWING.SquadronAsset
if asset.uid==Asset.uid then
self:I(self.lid..string.format("Removing asset \"%s\" from mission", tostring(asset.spawngroupname)))
self:T(self.lid..string.format("Removing asset \"%s\" from mission", tostring(asset.spawngroupname)))
table.remove(self.assets, i)
return self
end
@ -3289,7 +3291,7 @@ function AUFTRAG:_TargetFromObject(Object)
self.Ntargets=Ninitial
-- Debug info.
self:I(self.lid..string.format("Mission Target %s Type=%s, Ntargets=%d, Lifepoints=%d", target.Name, target.Type, Ninitial, Lifepoints))
self:T(self.lid..string.format("Mission Target %s Type=%s, Ntargets=%d, Lifepoints=%d", target.Name, target.Type, Ninitial, Lifepoints))
return target
end

View File

@ -374,7 +374,7 @@ function CHIEF:onafterStatus(From, Event, To)
-- Clean up missions where the contact was lost.
for _,_contact in pairs(self.ContactsLost) do
local contact=_contact --#CHIEF.Contact
local contact=_contact --#INTEL.Contact
if contact.mission and contact.mission:IsNotOver() then
@ -539,7 +539,6 @@ end
-- @param #string Event Event.
-- @param #string To To state.
-- @param #string Defcon New defence condition.
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
function CHIEF:onbeforeDefcon(From, Event, To, Defcon)
local gotit=false
@ -569,7 +568,6 @@ end
-- @param #string Event Event.
-- @param #string To To state.
-- @param #string Defcon New defence condition.
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
function CHIEF:onafterDefcon(From, Event, To, Defcon)
self:I(self.lid..string.format("Changing Defcon from %s --> %s", self.Defcon, Defcon))
@ -577,6 +575,20 @@ function CHIEF:onafterDefcon(From, Event, To, Defcon)
self.Defcon=Defcon
end
--- On after "DeclareWar" event.
-- @param #CHIEF self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #CHIEF Chief The Chief we declared war on.
function CHIEF:onafterDeclareWar(From, Event, To, Chief)
if Chief then
self:AddWarOnChief(Chief)
end
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Resources
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------