mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Fixed respawn bug in AI_BALANCER + Scheduler bug
AI_BALANCER respawns back the AI. Bug was in the FSM. In a transition, when states are the same, the events SHOULD execute. Added spawn delay interval option API SetSpawnInterval(). Bug that prevented AI_BALANCER to start if multiple AI_BALANCERs is also fixed. Fixed bug in scheduler dispatcher. Multiple schedules for the same scheduler work now too!
This commit is contained in:
parent
243f33764a
commit
1f90c0c766
@ -74,30 +74,35 @@
|
||||
--- AI_BALANCER class
|
||||
-- @type AI_BALANCER
|
||||
-- @field Core.Set#SET_CLIENT SetClient
|
||||
-- @field Functional.Spawn#SPAWN SpawnAI
|
||||
-- @field Wrapper.Group#GROUP Test
|
||||
-- @extends Core.Fsm#FSM_SET
|
||||
AI_BALANCER = {
|
||||
ClassName = "AI_BALANCER",
|
||||
PatrolZones = {},
|
||||
AIGroups = {},
|
||||
Earliest = 5, -- Earliest a new AI can be spawned is in 5 seconds.
|
||||
Latest = 60, -- Latest a new AI can be spawned is in 60 seconds.
|
||||
}
|
||||
|
||||
|
||||
|
||||
--- Creates a new AI_BALANCER object
|
||||
-- @param #AI_BALANCER self
|
||||
-- @param Core.Set#SET_CLIENT SetClient A SET\_CLIENT object that will contain the CLIENT objects to be monitored if they are alive or not (joined by a player).
|
||||
-- @param Functional.Spawn#SPAWN SpawnAI The default Spawn object to spawn new AI Groups when needed.
|
||||
-- @return #AI_BALANCER
|
||||
-- @usage
|
||||
-- -- Define a new AI_BALANCER Object.
|
||||
function AI_BALANCER:New( SetClient, SpawnAI )
|
||||
|
||||
-- Inherits from BASE
|
||||
self = BASE:Inherit( self, FSM_SET:New( SET_GROUP:New() ) ) -- Core.Fsm#FSM_SET
|
||||
local self = BASE:Inherit( self, FSM_SET:New( SET_GROUP:New() ) ) -- AI.AI_Balancer#AI_BALANCER
|
||||
|
||||
self:SetStartState( "None" )
|
||||
self:AddTransition( "*", "Start", "Monitoring" )
|
||||
self:AddTransition( "*", "Monitor", "Monitoring" )
|
||||
self:AddTransition( "*", "Spawn", "Spawning" )
|
||||
self:AddTransition( "Spawning", "Spawned", "Spawned" )
|
||||
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
||||
self:AddTransition( "*", "Destroy", "Destroying" )
|
||||
self:AddTransition( "*", "Return", "Returning" )
|
||||
self:AddTransition( "*", "End", "End" )
|
||||
@ -105,6 +110,9 @@ function AI_BALANCER:New( SetClient, SpawnAI )
|
||||
|
||||
self.SetClient = SetClient
|
||||
self.SpawnAI = SpawnAI
|
||||
|
||||
self.SpawnQueue = {}
|
||||
|
||||
self.ToNearestAirbase = false
|
||||
self.ToHomeAirbase = false
|
||||
|
||||
@ -113,6 +121,20 @@ function AI_BALANCER:New( SetClient, SpawnAI )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets the earliest to the latest interval in seconds how long AI_BALANCER will wait to spawn a new AI.
|
||||
-- Provide 2 identical seconds if the interval should be a fixed amount of seconds.
|
||||
-- @param #AI_BALANCER self
|
||||
-- @param #number Earliest The earliest a new AI can be spawned in seconds.
|
||||
-- @param #number Latest The latest a new AI can be spawned in seconds.
|
||||
-- @return self
|
||||
function AI_BALANCER:InitSpawnInterval( Earliest, Latest )
|
||||
|
||||
self.Earliest = Earliest
|
||||
self.Latest = Latest
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}.
|
||||
-- @param #AI_BALANCER self
|
||||
-- @param Dcs.DCSTypes#Distance ReturnTresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnTresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}.
|
||||
@ -140,15 +162,34 @@ end
|
||||
function AI_BALANCER:onenterSpawning( SetGroup, From, Event, To, ClientName )
|
||||
|
||||
-- OK, Spawn a new group from the default SpawnAI object provided.
|
||||
local AIGroup = self.SpawnAI:Spawn()
|
||||
local AIGroup = self.SpawnAI:Spawn() -- Wrapper.Group#GROUP
|
||||
AIGroup:E( "Spawning new AIGroup" )
|
||||
--TODO: need to rework UnitName thing ...
|
||||
|
||||
SetGroup:Add( ClientName, AIGroup )
|
||||
self.SpawnQueue[ClientName] = nil
|
||||
|
||||
|
||||
-- --- @param Wrapper.Group#GROUP AIGroup
|
||||
-- -- @param Core.Event#EVENTDATA EventData
|
||||
-- local function Respawn( AIGroup, EventData )
|
||||
-- if EventData.IniUnit then
|
||||
-- local CheckGroup = EventData.IniUnit:GetGroup()
|
||||
-- if CheckGroup:GetName() == AIGroup:GetName() then
|
||||
-- if CheckGroup:GetUnits() == nil then
|
||||
-- AIGroup:Respawn( AIGroup:GetTemplate() )
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
--
|
||||
-- AIGroup:EventOnDead( Respawn )
|
||||
-- AIGroup:EventOnEjection( Respawn )
|
||||
|
||||
-- Fire the Spawned event. The first parameter is the AIGroup just Spawned.
|
||||
-- Mission designers can catch this event to bind further actions to the AIGroup.
|
||||
self:Spawned( AIGroup )
|
||||
self:Spawned( AIGroup )
|
||||
end
|
||||
|
||||
--- @param #AI_BALANCER self
|
||||
@ -159,6 +200,14 @@ function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, AIGroup )
|
||||
AIGroup:Destroy()
|
||||
end
|
||||
|
||||
--- @param #AI_BALANCER self
|
||||
-- @param Core.Set#SET_GROUP SetGroup
|
||||
-- @param Wrapper.Group#GROUP AIGroup
|
||||
function AI_BALANCER:onenterDestroyed( SetGroup, From, Event, To, AIGroup )
|
||||
|
||||
AIGroup:Destroy()
|
||||
end
|
||||
|
||||
--- @param #AI_BALANCER self
|
||||
-- @param Core.Set#SET_GROUP SetGroup
|
||||
-- @param Wrapper.Group#GROUP AIGroup
|
||||
@ -240,9 +289,13 @@ function AI_BALANCER:onenterMonitoring( SetGroup )
|
||||
end
|
||||
else
|
||||
if not AIGroup or not AIGroup:IsAlive() == true then
|
||||
self:E("client not alive")
|
||||
self:Spawn( Client.UnitName )
|
||||
self:E("text after spawn")
|
||||
self:E( "Client " .. Client.UnitName .. " not alive." )
|
||||
if not self.SpawnQueue[Client.UnitName] then
|
||||
-- Spawn a new AI taking into account the spawn interval Earliest, Latest
|
||||
self:__Spawn( math.random( self.Earliest, self.Latest ), Client.UnitName )
|
||||
self.SpawnQueue[Client.UnitName] = true
|
||||
self:E( "New AI Spawned for Client " .. Client.UnitName )
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
|
||||
@ -582,10 +582,10 @@ do -- FSM
|
||||
|
||||
if execute then
|
||||
-- only execute the call if the From state is not equal to the To state! Otherwise this function should never execute!
|
||||
if from ~= to then
|
||||
--if from ~= to then
|
||||
self:_call_handler("onenter" .. to, params)
|
||||
self:_call_handler("OnEnter" .. to, params)
|
||||
end
|
||||
--end
|
||||
|
||||
self:_call_handler("onafter" .. EventName, params)
|
||||
self:_call_handler("OnAfter" .. EventName, params)
|
||||
|
||||
@ -75,7 +75,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
||||
end
|
||||
|
||||
self.Schedule = self.Schedule or setmetatable( {}, { __mode = "k" } )
|
||||
self.Schedule[Scheduler] = {}
|
||||
self.Schedule[Scheduler] = self.Schedule[Scheduler] or {}
|
||||
self.Schedule[Scheduler][self.CallID] = {}
|
||||
self.Schedule[Scheduler][self.CallID].Function = ScheduleFunction
|
||||
self.Schedule[Scheduler][self.CallID].Arguments = ScheduleArguments
|
||||
|
||||
@ -207,6 +207,7 @@ SPAWN = {
|
||||
SpawnAliasPrefix = nil,
|
||||
}
|
||||
|
||||
|
||||
--- @type SPAWN.SpawnZoneTable
|
||||
-- @list <Core.Zone#ZONE_BASE> SpawnZone
|
||||
|
||||
|
||||
@ -883,4 +883,3 @@ function GROUP:CalculateThreatLevelA2G()
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
@ -34,7 +34,6 @@ OBJECT = {
|
||||
ObjectName = "",
|
||||
}
|
||||
|
||||
|
||||
--- A DCSObject
|
||||
-- @type DCSObject
|
||||
-- @field id_ The ID of the controllable in DCS
|
||||
@ -43,10 +42,11 @@ OBJECT = {
|
||||
-- @param #OBJECT self
|
||||
-- @param Dcs.DCSWrapper.Object#Object ObjectName The Object name
|
||||
-- @return #OBJECT self
|
||||
function OBJECT:New( ObjectName )
|
||||
function OBJECT:New( ObjectName, Test )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:F2( ObjectName )
|
||||
self.ObjectName = ObjectName
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
-- Name: Respawn Test when Destroyed
|
||||
-- Author: FlightControl
|
||||
-- Date Created: 7 January 2017
|
||||
--
|
||||
-- # Situation:
|
||||
--
|
||||
-- For the red coalition, 2 client slots are foreseen.
|
||||
-- For those players that have not joined the mission, red AI is spawned.
|
||||
-- The red AI should start patrolling an area.
|
||||
--
|
||||
-- The blue side has SAMs nearby.
|
||||
-- Once the red AI takes off, the red AI is attacked by the blue SAMs.
|
||||
-- Red AI should be killed and once that happens, a Respawn of the group should happen!
|
||||
-- The Respawn happens through the InitCleanUp() API of SPAWN.
|
||||
--
|
||||
-- # Test cases:
|
||||
--
|
||||
-- 1. If no player is logging into the red slots, 2 red AI planes should be alive.
|
||||
-- 2. If a player joins one red slot, one red AI plane should return to the nearest home base.
|
||||
-- 3. If two players join the red slots, no AI plane should be spawned, and all airborne AI planes should return to the nearest home base.
|
||||
-- 4. Monitor that once a red AI is destroyed, that it ReSpawns...
|
||||
--
|
||||
|
||||
-- Define the SET of CLIENTs from the red coalition. This SET is filled during startup.
|
||||
local RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ):FilterStart()
|
||||
|
||||
-- Define the SPAWN object for the red AI plane template.
|
||||
-- We use InitCleanUp to check every 20 seconds, if there are no planes blocked at the airbase, waithing for take-off.
|
||||
-- If a blocked plane exists, this red plane will be ReSpawned.
|
||||
local RU_PlanesSpawn = SPAWN:New( "AI RU" ):InitCleanUp( 20 )
|
||||
|
||||
-- Start the AI_BALANCER, using the SET of red CLIENTs, and the SPAWN object as a parameter.
|
||||
local RU_AI_Balancer = AI_BALANCER:New( RU_PlanesClientSet, RU_PlanesSpawn )
|
||||
|
||||
function RU_AI_Balancer:OnAfterSpawned( SetGroup, From, Event, To, AIGroup )
|
||||
|
||||
local PatrolZoneGroup = GROUP:FindByName( "PatrolZone" )
|
||||
local PatrolZone = ZONE_POLYGON:New( "PatrolZone", PatrolZoneGroup )
|
||||
|
||||
|
||||
local Patrol = AI_PATROLZONE:New( PatrolZone, 3000, 6000, 400, 600 )
|
||||
Patrol:ManageFuel( 0.2, 60 )
|
||||
Patrol:SetControllable( AIGroup )
|
||||
Patrol:__Start( 5 )
|
||||
|
||||
end
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user