struct Agent { [ unsavable = "true" ] persistent var link : DeviceLink; [ unsavable = "true" ] persistent var reprimands : array< ReprimandData >; [ unsavable = "true" ] persistent var supportingAgents : array< PersistentID >; [ unsavable = "true" ] persistent var areas : array< DeviceLink >; [ unsavable = "true" ] persistent var incomingFilter : EFilterType; [ unsavable = "true" ] persistent var cachedDelayDuration : Float; public static function Construct( link : DeviceLink, const areas : ref< array< SecurityAreaControllerPS > > ) : Agent { var agent : Agent; var i : Int32; if( !( DeviceLink.IsValid( link ) ) || ( areas.Size() == 0 ) ) { return agent; } agent.link = link; Agent.SetIncomingFilter( agent, areas ); if( DeviceLink.GetLinkClassName( link ) == 'PuppetDeviceLinkPS' ) { agent.cachedDelayDuration = RandRangeF( 0.1, 1.0 ); } for( i = 0; i < areas.Size(); i += 1 ) { agent.areas.PushBack( DeviceLink.Construct( areas[ i ] ) ); } return agent; } public static function AddArea( self : ref< Agent >, area : SecurityAreaControllerPS ) { Agent.SetIncomingFilter( self, area ); self.areas.PushBack( DeviceLink.Construct( area ) ); } public static function RemoveArea( self : ref< Agent >, const remainingAreas : ref< array< SecurityAreaControllerPS > > ) { var i : Int32; Agent.SetIncomingFilter( self, remainingAreas ); self.areas.Clear(); for( i = 0; i < remainingAreas.Size(); i += 1 ) { self.areas.PushBack( DeviceLink.Construct( remainingAreas[ i ] ) ); } } public static function SetIncomingFilter( self : ref< Agent >, const areas : ref< array< SecurityAreaControllerPS > > ) { var i : Int32; self.incomingFilter = EFilterType.ALLOW_ALL; for( i = 0; i < areas.Size(); i += 1 ) { Agent.SetIncomingFilter( self, areas[ i ] ); } } public static function SetIncomingFilter( self : ref< Agent >, area : SecurityAreaControllerPS ) { if( ( ( Int32 )( self.incomingFilter ) ) < ( ( Int32 )( area.GetIncomingFilter() ) ) ) { self.incomingFilter = area.GetIncomingFilter(); } } public static function IsValid( self : Agent ) : Bool { if( DeviceLink.IsValid( self.link ) && ( self.areas.Size() != 0 ) ) { return true; } return false; } public static function GetAreas( const self : ref< Agent >, areas : ref< array< DeviceLink > > ) { var i : Int32; for( i = 0; i < self.areas.Size(); i += 1 ) { areas.PushBack( self.areas[ i ] ); } } public static function IsEligible( const self : ref< Agent >, state : ESecuritySystemState, const breachedAreas : ref< array< SecurityAreaControllerPS > >, inputsOutgoingFilter : EFilterType, out breachOrigin : EBreachOrigin ) : Bool { var i, k : Int32; breachOrigin = EBreachOrigin.EXTERNAL; for( i = 0; i < breachedAreas.Size(); i += 1 ) { for( k = 0; k < self.areas.Size(); k += 1 ) { if( breachedAreas[ i ] == self.areas[ k ] ) { breachOrigin = EBreachOrigin.LOCAL; return true; } } } if( inputsOutgoingFilter == EFilterType.ALLOW_ALL ) { if( self.incomingFilter == EFilterType.ALLOW_ALL ) { return true; } if( self.incomingFilter == EFilterType.ALLOW_COMBAT_ONLY && state == ESecuritySystemState.COMBAT ) { return true; } return false; } if( inputsOutgoingFilter == EFilterType.ALLOW_COMBAT_ONLY ) { if( self.incomingFilter == EFilterType.ALLOW_ALL ) { return true; } if( self.incomingFilter == EFilterType.ALLOW_COMBAT_ONLY && state == ESecuritySystemState.COMBAT ) { return true; } return false; } return false; } public static function IsEligibleToShareData( const self : ref< Agent >, state : ESecuritySystemState, const breachedAreas : ref< array< SecurityAreaControllerPS > >, inputsOutgoingFilter : EFilterType ) : Bool { var i, k : Int32; if( inputsOutgoingFilter == EFilterType.ALLOW_ALL ) { if( self.incomingFilter == EFilterType.ALLOW_ALL ) { return true; } if( self.incomingFilter == EFilterType.ALLOW_COMBAT_ONLY && state == ESecuritySystemState.COMBAT ) { return true; } } if( inputsOutgoingFilter == EFilterType.ALLOW_COMBAT_ONLY ) { if( self.incomingFilter == EFilterType.ALLOW_ALL ) { return true; } if( self.incomingFilter == EFilterType.ALLOW_COMBAT_ONLY && state == ESecuritySystemState.COMBAT ) { return true; } } for( i = 0; i < breachedAreas.Size(); i += 1 ) { for( k = 0; k < self.areas.Size(); k += 1 ) { if( breachedAreas[ i ] == self.areas[ k ] ) { return true; } } } return false; } public static function AddSupport( self : ref< Agent >, id : PersistentID, shouldAdd : Bool ) : Bool { var i : Int32; if( shouldAdd ) { for( i = 0; i < self.supportingAgents.Size(); i += 1 ) { if( self.supportingAgents[ i ] == id ) { return false; } } self.supportingAgents.PushBack( id ); if( self.supportingAgents.Size() == 1 ) { return true; } return false; } else { for( i = 0; i < self.supportingAgents.Size(); i += 1 ) { if( self.supportingAgents[ i ] == id ) { self.supportingAgents.EraseFast( i ); if( self.supportingAgents.Size() == 0 ) { return true; } return false; } } return false; } } public static function HasSupport( const self : ref< Agent > ) : Bool { return self.supportingAgents.Size() > 0; } public static function ClearSupport( self : ref< Agent > ) { self.supportingAgents.Clear(); } public static function IsPerformingReprimand( const self : ref< Agent > ) : Bool { var i : Int32; for( i = 0; i < self.reprimands.Size(); i += 1 ) { if( self.reprimands[ i ].isActive ) { return true; } } return false; } public static function IsPerformingReprimandAgainst( const self : ref< Agent >, target : EntityID ) : Bool { var i : Int32; for( i = 0; i < self.reprimands.Size(); i += 1 ) { if( ( self.reprimands[ i ].receiver == target ) && self.reprimands[ i ].isActive ) { return true; } } return false; } public static function GetReprimandReceiver( const self : ref< Agent > ) : EntityID { var i : Int32; for( i = 0; i < self.reprimands.Size(); i += 1 ) { if( self.reprimands[ i ].isActive ) { return self.reprimands[ i ].receiver; } } return EMPTY_ENTITY_ID(); } public static function GetReprimandsCount( const self : ref< Agent >, target : EntityID ) : Int32 { var i : Int32; for( i = 0; i < self.reprimands.Size(); i += 1 ) { if( self.reprimands[ i ].receiver == target ) { return self.reprimands[ i ].count; } } return 0; } public static function ReleaseFromReprimand( self : ref< Agent >, target : EntityID ) { var i : Int32; for( i = 0; i < self.reprimands.Size(); i += 1 ) { if( self.reprimands[ i ].receiver == target ) { self.reprimands[ i ].isActive = false; } } } public static function ForceRelaseReprimands( self : ref< Agent > ) { var i : Int32; for( i = 0; i < self.reprimands.Size(); i += 1 ) { self.reprimands[ i ].isActive = false; } } public static function StoreReprimand( self : ref< Agent >, reprimandData : ReprimandData ) { var i : Int32; for( i = 0; i < self.reprimands.Size(); i += 1 ) { if( ( self.reprimands[ i ].receiver == reprimandData.receiver ) && ( self.reprimands[ i ].reprimandID != reprimandData.reprimandID ) ) { self.reprimands[ i ].count += 1; self.reprimands[ i ].reprimandID = reprimandData.reprimandID; self.reprimands[ i ].isActive = true; return; } } reprimandData.count = 1; self.reprimands.PushBack( reprimandData ); return; } public static function WipeReprimand( self : ref< Agent >, target : EntityID ) { var i : Int32; for( i = 0; i < self.reprimands.Size(); i += 1 ) { if( self.reprimands[ i ].receiver == target ) { self.reprimands.EraseFast( i ); return; } } } public static function WipeReprimand( self : ref< Agent >, attGroup : CName, attSystem : AttitudeSystem ) { var i : Int32; for( i = self.reprimands.Size() - 1; i >= 0; i -= 1 ) { if( attSystem.GetAttitudeRelation( attGroup, self.reprimands[ i ].receiverAttitudeGroup ) == EAIAttitude.AIA_Friendly ) { self.reprimands.Erase( i ); } } } }