abstract class TweakAIActionRecord { public static function GetFriendlyName( record : TweakDBID, const nodeName : ref< String > ) : String { var actionName : String; if( IsFinal() ) { actionName = "NoStringDebugInFinal =("; } else if( GetDebugActionNameFromRecord( record, actionName ) ) { return ( ( ( "Archetype" + nodeName ) + ": ''" ) + actionName ) + "'' "; } return ( ( nodeName + ": ''" ) + actionName ) + "'' "; } public static function GetDebugActionNameFromRecord( record : TweakDBID, debugStringName : ref< String > ) : Bool { var actionName : TweakDBID; if( AIScriptUtils.GetActionNameFromRecord( record, actionName ) ) { debugStringName = TDBID.ToStringDEBUG( actionName ); return true; } debugStringName = TDBID.ToStringDEBUG( record ); return false; } public static function GetHeldItemType( const context : ScriptExecutionContext, out heldItemType : gamedataItemType ) : Bool { var item : weak< ItemObject >; var ts : TransactionSystem; var owner : gamePuppet; owner = ScriptExecutionContext.GetOwner( context ); ts = GameInstance.GetTransactionSystem( owner.GetGame() ); if( !( ts ) ) { return false; } item = ts.GetItemInSlot( owner, T"AttachmentSlots.WeaponRight" ); if( !( item ) ) { item = ts.GetItemInSlot( owner, T"AttachmentSlots.WeaponLeft" ); } if( !( item ) ) { return false; } heldItemType = item.GetItemData().GetItemType(); return true; } public static function IsArchetypeAction( record : TweakDBID ) : Bool { return AIScriptUtils.IsArchetypeAction( record ); } public static function GetActionRecord( const context : ScriptExecutionContext, actionID : TweakDBID, actionDebugName : ref< String >, out actionRecord : weak< AIAction_Record > ) : Bool { var record : AIRecord_Record; if( !( ScriptExecutionContext.GetOverriddenNode( context, actionID, record, true ) ) ) { return false; } if( record ) { actionID = record.GetID(); } if( !( IsFinal() ) ) { actionDebugName = TDBID.ToStringDEBUG( actionID ); } actionRecord = ( ( AIAction_Record )( record ) ); return actionRecord != NULL; } public static function GetSelectorRecord( const context : ScriptExecutionContext, selectorID : TweakDBID, selectorDebugName : ref< String >, out selectorRecord : weak< AIActionSelector_Record > ) : Bool { var record : AIRecord_Record; if( !( ScriptExecutionContext.GetOverriddenNode( context, selectorID, record, true ) ) ) { return false; } selectorID = record.GetID(); if( !( IsFinal() ) ) { selectorDebugName = TDBID.ToStringDEBUG( selectorID ); } selectorRecord = ( ( AIActionSelector_Record )( record ) ); return selectorRecord != NULL; } public static function GetSequenceRecord( const context : ScriptExecutionContext, sequenceID : TweakDBID, sequenceDebugName : ref< String >, out sequenceRecord : weak< AIActionSequence_Record > ) : Bool { var record : AIRecord_Record; if( !( ScriptExecutionContext.GetOverriddenNode( context, sequenceID, record, true ) ) ) { return false; } sequenceID = record.GetID(); if( !( IsFinal() ) ) { sequenceDebugName = TDBID.ToStringDEBUG( sequenceID ); } sequenceRecord = ( ( AIActionSequence_Record )( record ) ); return sequenceRecord != NULL; } public static function GetSmartCompositeRecord( const context : ScriptExecutionContext, smartCompositeID : TweakDBID, smartCompositeDebugName : ref< String >, out smartCompositeRecord : weak< AIActionSmartComposite_Record > ) : Bool { var record : AIRecord_Record; if( !( ScriptExecutionContext.GetOverriddenNode( context, smartCompositeID, record, true ) ) ) { return false; } smartCompositeID = record.GetID(); if( !( IsFinal() ) ) { smartCompositeDebugName = TDBID.ToStringDEBUG( smartCompositeID ); } smartCompositeRecord = ( ( AIActionSmartComposite_Record )( record ) ); return smartCompositeRecord != NULL; } public static function GetActionRecordFromSelector( const context : ScriptExecutionContext, selectorRecord : weak< AIActionSelector_Record >, actionDebugName : ref< String >, out actionRecord : weak< AIAction_Record >, out nodeIterator : Int32, out shouldCallAgain : Bool ) : Bool { var count : Int32; var limitCount : Uint32; var alternativesLimitEnabled : Bool; var alternativesLimit : Uint32; var player : PlayerPuppet; var playerInCombat : Bool; var blackBoard : IBlackboard; limitCount = 0; if( !( selectorRecord ) ) { return false; } player = GetPlayer( ScriptExecutionContext.GetOwner( context ).GetGame() ); if( player ) { playerInCombat = player.IsInCombat(); } alternativesLimitEnabled = ScriptExecutionContext.GetTweakActionSystem( context ).IsTweakCompositeAlternativesLimitEnabled( context, playerInCombat ); alternativesLimit = ScriptExecutionContext.GetTweakActionSystem( context ).GetTweakCompositeAlternativesLimit( context ); count = selectorRecord.GetActionsCount(); if( nodeIterator >= count ) { nodeIterator = 0; } while( nodeIterator < count ) { if( ( !( selectorRecord.DisableActionsLimit() ) && alternativesLimitEnabled ) && ( limitCount >= alternativesLimit ) ) { shouldCallAgain = true; return false; } actionRecord = selectorRecord.GetActionsItem( nodeIterator ); if( !( actionRecord ) ) { nodeIterator += 1; limitCount += ( ( Uint32 )( 1 ) ); continue; } if( !( TweakAIActionRecord.GetActionRecord( context, actionRecord.GetID(), actionDebugName, actionRecord ) ) ) { return false; } if( ( ( AISubActionRandomize_Record )( actionRecord.AnimData().AnimVariationSubAction() ) ) ) { blackBoard = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).GetAIControllerComponent().GetActionBlackboard(); if( ( ( TweakDBID )( blackBoard.GetVariant( GetAllBlackboardDefs().AIAction.ownerLastAnimVariationAction ) ) ) != actionRecord.GetID() ) { blackBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerLastAnimVariationAction, TDBID.None() ); blackBoard.SetBool( GetAllBlackboardDefs().AIAction.ownerCurrentAnimVariationSet, false ); } if( AICondition.ActivationCheck( context, actionRecord ) ) { blackBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerLastAnimVariationAction, actionRecord.GetID() ); return true; } } else if( AICondition.ActivationCheck( context, actionRecord ) ) { return true; } nodeIterator += 1; limitCount += ( ( Uint32 )( 1 ) ); } actionRecord = selectorRecord.DefaultAction(); if( actionRecord ) { nodeIterator = -1; if( !( TweakAIActionRecord.GetActionRecord( context, actionRecord.GetID(), actionDebugName, actionRecord ) ) ) { return false; } return true; } return false; } public static function IsThisLastActionInSelector( selectorRecord : weak< AIActionSelector_Record >, const nodeIterator : Int32 ) : Bool { var count : Int32; if( !( selectorRecord ) ) { return false; } if( nodeIterator < 0 ) { return true; } count = selectorRecord.GetActionsCount(); return nodeIterator >= ( count - 1 ); } public static function GetActionRecordFromSequence( const context : ScriptExecutionContext, sequenceRecord : weak< AIActionSequence_Record >, actionDebugName : ref< String >, out actionRecord : weak< AIAction_Record >, out sequenceIterator : Int32, out shouldCallAgain : Bool ) : Bool { var count : Int32; var limitCount : Uint32; var alternativesLimitEnabled : Bool; var alternativesLimit : Uint32; var player : PlayerPuppet; var playerInCombat : Bool; var blackBoard : IBlackboard; limitCount = 0; if( !( sequenceRecord ) ) { return false; } player = GetPlayer( ScriptExecutionContext.GetOwner( context ).GetGame() ); if( player ) { playerInCombat = player.IsInCombat(); } alternativesLimitEnabled = ScriptExecutionContext.GetTweakActionSystem( context ).IsTweakCompositeAlternativesLimitEnabled( context, playerInCombat ); alternativesLimit = ScriptExecutionContext.GetTweakActionSystem( context ).GetTweakCompositeAlternativesLimit( context ); count = sequenceRecord.GetActionsCount(); if( sequenceIterator >= count ) { sequenceIterator = 0; } while( sequenceIterator < count ) { if( ( !( sequenceRecord.DisableActionsLimit() ) && alternativesLimitEnabled ) && ( limitCount >= alternativesLimit ) ) { shouldCallAgain = true; return false; } actionRecord = sequenceRecord.GetActionsItem( sequenceIterator ); if( !( actionRecord ) ) { sequenceIterator += 1; limitCount += ( ( Uint32 )( 1 ) ); continue; } if( !( TweakAIActionRecord.GetActionRecord( context, actionRecord.GetID(), actionDebugName, actionRecord ) ) ) { return false; } if( ( ( AISubActionRandomize_Record )( actionRecord.AnimData().AnimVariationSubAction() ) ) ) { blackBoard = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).GetAIControllerComponent().GetActionBlackboard(); if( ( ( TweakDBID )( blackBoard.GetVariant( GetAllBlackboardDefs().AIAction.ownerLastAnimVariationAction ) ) ) != actionRecord.GetID() ) { blackBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerLastAnimVariationAction, TDBID.None() ); blackBoard.SetBool( GetAllBlackboardDefs().AIAction.ownerCurrentAnimVariationSet, false ); } if( AICondition.ActivationCheck( context, actionRecord ) ) { blackBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerLastAnimVariationAction, actionRecord.GetID() ); return true; } } else if( AICondition.ActivationCheck( context, actionRecord ) ) { return true; } sequenceIterator += 1; limitCount += ( ( Uint32 )( 1 ) ); } actionRecord = NULL; return false; } public static function IsThisLastActionInSequence( sequenceRecord : weak< AIActionSequence_Record >, const sequenceIterator : Int32 ) : Bool { var count : Int32; if( !( sequenceRecord ) ) { return false; } count = sequenceRecord.GetActionsCount(); return sequenceIterator >= ( count - 1 ); } public static function IsThisLastActionInSmartComposite( smartCompositeRecord : weak< AIActionSmartComposite_Record >, const iterator : Int32 ) : Bool { var count : Int32; if( !( smartCompositeRecord ) ) { return false; } count = smartCompositeRecord.GetNodesCount(); return iterator >= ( count - 1 ); } public static function IsSmartCompositeASequence( smartCompositeRecord : weak< AIActionSmartComposite_Record > ) : Bool { var type : gamedataAISmartCompositeType; type = gamedataAISmartCompositeType.Invalid; type = smartCompositeRecord.Type().Type(); if( type == gamedataAISmartCompositeType.Sequence ) { return true; } if( type == gamedataAISmartCompositeType.SequenceWithMemory ) { return true; } if( type == gamedataAISmartCompositeType.SequenceWithSmartMemory ) { return true; } return false; } public static function IsSmartCompositeASelector( smartCompositeRecord : weak< AIActionSmartComposite_Record > ) : Bool { var type : gamedataAISmartCompositeType; type = gamedataAISmartCompositeType.Invalid; type = smartCompositeRecord.Type().Type(); if( type == gamedataAISmartCompositeType.Selector ) { return true; } if( type == gamedataAISmartCompositeType.SelectorWithMemory ) { return true; } if( type == gamedataAISmartCompositeType.SelectorWithSmartMemory ) { return true; } return false; } } class TweakAIAction extends TweakAIActionAbstract { [ customEditor = "TweakDBGroupInheritance;AIAction" ] editable var m_record : TweakDBID; public override function GetDescription( context : ScriptExecutionContext ) : String { var result : String; result = super.GetDescription( context ); if( result == "" ) { return TDBID.ToStringDEBUG( m_record ); } return result; } private override function GetActionRecord( const context : ScriptExecutionContext, actionDebugName : ref< String >, out actionRecord : weak< AIAction_Record >, out shouldCallAgain : Bool ) : Bool { return TweakAIActionRecord.GetActionRecord( context, m_record, actionDebugName, actionRecord ); } private override function Debug_GetBaseActionId() : TweakDBID { return m_record; } public export function GetFriendlyName() : String { if( TweakDBInterface.GetAIActionRecord( m_record ) ) { return TweakAIActionRecord.GetFriendlyName( m_record, "Action" ); } else { return TweakAIActionRecord.GetFriendlyName( m_record, " [INVALID] Action" ); } } } class TweakAIActionCondition extends TweakAIActionConditionAbstract { [ customEditor = "TweakDBGroupInheritance;AIAction" ] editable var m_record : TweakDBID; public override function GetDescription( context : ScriptExecutionContext ) : String { var result : String; result = super.GetDescription( context ); if( result == "" ) { return TDBID.ToStringDEBUG( m_record ); } return result; } private override function GetActionRecord( const context : ScriptExecutionContext, actionDebugName : ref< String >, out actionRecord : weak< AIAction_Record > ) : Bool { return TweakAIActionRecord.GetActionRecord( context, m_record, actionDebugName, actionRecord ); } public function GetFriendlyName() : String { if( TweakDBInterface.GetAIActionRecord( m_record ) ) { return TweakAIActionRecord.GetFriendlyName( m_record, "Condition" ); } else { return TweakAIActionRecord.GetFriendlyName( m_record, " [INVALID] Condition" ); } } } class TweakAIActionSelector extends TweakAIActionAbstract { [ customEditor = "TweakDBGroupInheritance;AIActionSelector" ] editable var m_selector : TweakDBID; var m_selectorRecord : weak< AIActionSelector_Record >; var m_nodeIterator : Int32; private override function GetActionRecord( const context : ScriptExecutionContext, actionDebugName : ref< String >, out actionRecord : weak< AIAction_Record >, out shouldCallAgain : Bool ) : Bool { var selectorRecord : weak< AIActionSelector_Record >; if( !( TweakAIActionRecord.GetSelectorRecord( context, m_selector, actionDebugName, selectorRecord ) ) ) { return false; } if( selectorRecord != m_selectorRecord ) { m_nodeIterator = 0; m_selectorRecord = selectorRecord; } return TweakAIActionRecord.GetActionRecordFromSelector( context, m_selectorRecord, actionDebugName, actionRecord, m_nodeIterator, shouldCallAgain ); } private override function Debug_GetBaseActionId() : TweakDBID { var selectorRecord : AIActionSelector_Record; var actionRecord : AIAction_Record; selectorRecord = m_selectorRecord; if( !( selectorRecord ) ) { return T""; } if( m_nodeIterator < 0 ) { actionRecord = selectorRecord.DefaultAction(); } else if( m_nodeIterator < selectorRecord.GetActionsCount() ) { actionRecord = selectorRecord.GetActionsItem( m_nodeIterator ); } else { actionRecord = NULL; } if( !( actionRecord ) ) { return T""; } return actionRecord.GetID(); } private override function Debug_GetCompositeId() : TweakDBID { return m_selector; } public export function GetFriendlyName() : String { if( TweakDBInterface.GetAIActionSelectorRecord( m_selector ) ) { return TweakAIActionRecord.GetFriendlyName( m_selector, "Selector" ); } else { return TweakAIActionRecord.GetFriendlyName( m_selector, " [INVALID] Selector" ); } } private export override function Update( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome { var result : AIbehaviorUpdateOutcome; if( !( RetryGetActionRecord( context ) ) ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } switch( super.Update( context ) ) { case AIbehaviorUpdateOutcome.FAILURE: { result = RunNextAction( context ); if( result == AIbehaviorUpdateOutcome.SUCCESS ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } return result; } case AIbehaviorUpdateOutcome.SUCCESS: { return AIbehaviorUpdateOutcome.SUCCESS; } default: break; } return AIbehaviorUpdateOutcome.IN_PROGRESS; } private export override function Deactivate( context : ScriptExecutionContext ) { super.Deactivate( context ); m_nodeIterator = 0; } private final function RunNextAction( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome { if( TweakAIActionRecord.IsThisLastActionInSelector( m_selectorRecord, m_nodeIterator ) ) { return AIbehaviorUpdateOutcome.FAILURE; } m_nodeIterator += 1; super.Deactivate( context ); super.Activate( context ); if( VerifyActionRecord() ) { return super.Update( context ); } return AIbehaviorUpdateOutcome.IN_PROGRESS; } } class TweakAIActionSequence extends TweakAIActionAbstract { [ customEditor = "TweakDBGroupInheritance;AIActionSequence" ] editable var m_sequence : TweakDBID; private var m_sequenceRecord : weak< AIActionSequence_Record >; private var m_sequenceIterator : Int32; private override function GetActionRecord( const context : ScriptExecutionContext, actionDebugName : ref< String >, out actionRecord : weak< AIAction_Record >, out shouldCallAgain : Bool ) : Bool { var sequenceRecord : weak< AIActionSequence_Record >; if( !( TweakAIActionRecord.GetSequenceRecord( context, m_sequence, actionDebugName, sequenceRecord ) ) ) { ResetSequence(); return false; } if( sequenceRecord != m_sequenceRecord ) { ResetSequence(); m_sequenceRecord = sequenceRecord; } return TweakAIActionRecord.GetActionRecordFromSequence( context, m_sequenceRecord, actionDebugName, actionRecord, m_sequenceIterator, shouldCallAgain ); } private override function Debug_GetBaseActionId() : TweakDBID { return m_sequence; } private override function Debug_GetCompositeId() : TweakDBID { return m_sequence; } public export function GetFriendlyName() : String { if( TweakDBInterface.GetAIActionSequenceRecord( m_sequence ) ) { return TweakAIActionRecord.GetFriendlyName( m_sequence, "Sequence" ); } else { return TweakAIActionRecord.GetFriendlyName( m_sequence, " [INVALID] Sequence" ); } } private export override function Update( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome { var result : AIbehaviorUpdateOutcome; if( !( RetryGetActionRecord( context ) ) ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } switch( super.Update( context ) ) { case AIbehaviorUpdateOutcome.FAILURE: ResetSequence(); return AIbehaviorUpdateOutcome.FAILURE; case AIbehaviorUpdateOutcome.SUCCESS: result = RunNextAction( context ); if( result == AIbehaviorUpdateOutcome.FAILURE ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } return result; default: break; } return AIbehaviorUpdateOutcome.IN_PROGRESS; } private export override function Deactivate( context : ScriptExecutionContext ) { super.Deactivate( context ); if( !( m_sequenceRecord ) || !( m_sequenceRecord.HasMemory() ) ) { ResetSequence(); } } private final function ResetSequence() { m_sequenceIterator = 0; } private final function RunNextAction( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome { if( TweakAIActionRecord.IsThisLastActionInSequence( m_sequenceRecord, m_sequenceIterator ) ) { ResetSequence(); return AIbehaviorUpdateOutcome.SUCCESS; } m_sequenceIterator += 1; super.Deactivate( context ); super.Activate( context ); if( VerifyActionRecord() ) { return super.Update( context ); } return AIbehaviorUpdateOutcome.IN_PROGRESS; } } enum ETweakAINodeType { Action = 0, Selector = 1, Sequence = 2, } class TweakAIActionSmartComposite extends TweakAIActionAbstract { [ customEditor = "TweakDBGroupInheritance;AIActionSmartComposite" ] editable var m_smartComposite : TweakDBID; private var m_smartCompositeRecord : weak< AIActionSmartComposite_Record >; private var m_interruptionRequested : Bool; private var m_conditionSuccessfulCheckTimeStamp : Float; private var m_conditionCheckTimeStamp : Float; private var m_iteration : Uint32; private var m_nodeIterator : Int32; private var m_currentNodeIterator : Int32; private var m_currentNodeType : ETweakAINodeType; private var m_currentNode : weak< AINode_Record >; private final function ResetComposite() { ResetNodeIterator(); m_interruptionRequested = false; m_gracefullyInterrupted = false; m_iteration = 0; m_conditionSuccessfulCheckTimeStamp = 0.0; m_currentNode = NULL; } public virtual function GetSmartCompositeRecord( const context : ScriptExecutionContext, smartCompositeID : TweakDBID, smartCompositeStringName : ref< String >, out smartCompositeRecord : weak< AIActionSmartComposite_Record > ) : Bool { return TweakAIActionRecord.GetSmartCompositeRecord( context, smartCompositeID, smartCompositeStringName, smartCompositeRecord ); } private override function GetActionRecord( const context : ScriptExecutionContext, actionDebugName : ref< String >, out actionRecord : weak< AIAction_Record >, out shouldCallAgain : Bool ) : Bool { var nodeCount : Int32; var selectorRecord : weak< AIActionSelector_Record >; var sequenceRecord : weak< AIActionSequence_Record >; var smartCompositeRecord : weak< AIActionSmartComposite_Record >; var debugName : String; var limitCounter : Uint32; var tempBool : Bool; var alternativesLimitEnabled : Bool; var alternativesLimit : Uint32; var owner : gamePuppet; var player : PlayerPuppet; var playerInCombat : Bool; var blackBoard : IBlackboard; limitCounter = 0; tempBool = false; if( !( GetSmartCompositeRecord( context, m_smartComposite, actionDebugName, smartCompositeRecord ) ) ) { return false; } else { RandomizeGracefulInterruptionConditionCheckInterval( smartCompositeRecord ); } owner = ScriptExecutionContext.GetOwner( context ); player = GetPlayer( ScriptExecutionContext.GetOwner( context ).GetGame() ); if( player ) { playerInCombat = player.IsInCombat(); } alternativesLimitEnabled = ScriptExecutionContext.GetTweakActionSystem( context ).IsTweakCompositeAlternativesLimitEnabled( context, playerInCombat ); alternativesLimit = ScriptExecutionContext.GetTweakActionSystem( context ).GetTweakCompositeAlternativesLimit( context ); if( smartCompositeRecord != m_smartCompositeRecord ) { m_smartCompositeRecord = smartCompositeRecord; ResetComposite(); } nodeCount = m_smartCompositeRecord.GetNodesCount(); if( nodeCount == 0 ) { return false; } while( m_nodeIterator < nodeCount ) { if( ( !( smartCompositeRecord.DisableActionsLimit() ) && alternativesLimitEnabled ) && ( limitCounter >= alternativesLimit ) ) { shouldCallAgain = true; return false; } m_currentNode = m_smartCompositeRecord.GetNodesItem( m_nodeIterator ); actionRecord = ( ( AIAction_Record )( m_currentNode ) ); if( actionRecord ) { if( !( TweakAIActionRecord.GetActionRecord( context, actionRecord.GetID(), actionDebugName, actionRecord ) ) ) { return false; } m_currentNodeType = ETweakAINodeType.Action; if( ( ( AISubActionRandomize_Record )( actionRecord.AnimData().AnimVariationSubAction() ) ) ) { blackBoard = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).GetAIControllerComponent().GetActionBlackboard(); if( ( ( TweakDBID )( blackBoard.GetVariant( GetAllBlackboardDefs().AIAction.ownerLastAnimVariationAction ) ) ) != actionRecord.GetID() ) { blackBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerLastAnimVariationAction, TDBID.None() ); blackBoard.SetBool( GetAllBlackboardDefs().AIAction.ownerCurrentAnimVariationSet, false ); } if( AICondition.ActivationCheck( context, actionRecord ) ) { blackBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerLastAnimVariationAction, actionRecord.GetID() ); return true; } } else if( AICondition.ActivationCheck( context, actionRecord ) ) { return true; } else { IncrementNodeIterator(); limitCounter += ( ( Uint32 )( 1 ) ); continue; } return false; } if( !( IsFinal() ) ) { debugName = TDBID.ToStringDEBUG( m_smartCompositeRecord.GetID() ); if( AIActionHelper.ActionDebugHelper( "", owner, debugName ) ) { } } selectorRecord = ( ( AIActionSelector_Record )( m_currentNode ) ); if( selectorRecord ) { if( !( TweakAIActionRecord.GetSelectorRecord( context, selectorRecord.GetID(), actionDebugName, selectorRecord ) ) ) { return false; } if( !( IsFinal() ) ) { debugName = TDBID.ToStringDEBUG( selectorRecord.GetID() ); if( AIActionHelper.ActionDebugHelper( "", owner, debugName ) ) { } } if( !( selectorRecord.ActivationCondition() ) || AICondition.CheckActionCondition( context, selectorRecord.ActivationCondition() ) ) { m_currentNodeType = ETweakAINodeType.Selector; tempBool = TweakAIActionRecord.GetActionRecordFromSelector( context, selectorRecord, actionDebugName, actionRecord, m_currentNodeIterator, shouldCallAgain ); if( shouldCallAgain ) { return false; } if( !( tempBool ) ) { if( TweakAIActionRecord.IsSmartCompositeASelector( m_smartCompositeRecord ) ) { IncrementNodeIterator(); limitCounter += ( ( Uint32 )( 1 ) ); continue; } return false; } } else { if( m_smartCompositeRecord.FailOnNodeActivationConditionFailure() || selectorRecord.FailOnNodeActivationConditionFailure() ) { return false; } IncrementNodeIterator(); limitCounter += ( ( Uint32 )( 1 ) ); continue; } } sequenceRecord = ( ( AIActionSequence_Record )( m_currentNode ) ); if( sequenceRecord ) { if( !( TweakAIActionRecord.GetSequenceRecord( context, sequenceRecord.GetID(), actionDebugName, sequenceRecord ) ) ) { return false; } if( !( IsFinal() ) ) { debugName = TDBID.ToStringDEBUG( sequenceRecord.GetID() ); if( AIActionHelper.ActionDebugHelper( "", owner, debugName ) ) { } if( AIActionHelper.ActionDebugHelper( owner, debugName ) ) { } } if( m_currentNodeType == ETweakAINodeType.Sequence && ( m_currentNodeIterator > 0 ) ) { tempBool = TweakAIActionRecord.GetActionRecordFromSequence( context, sequenceRecord, actionDebugName, actionRecord, m_currentNodeIterator, shouldCallAgain ); if( shouldCallAgain ) { return false; } if( !( tempBool ) ) { if( TweakAIActionRecord.IsSmartCompositeASequence( m_smartCompositeRecord ) ) { IncrementNodeIterator(); limitCounter += ( ( Uint32 )( 1 ) ); continue; } return false; } } else if( !( sequenceRecord.ActivationCondition() ) || AICondition.CheckActionCondition( context, sequenceRecord.ActivationCondition() ) ) { m_currentNodeType = ETweakAINodeType.Sequence; tempBool = TweakAIActionRecord.GetActionRecordFromSequence( context, sequenceRecord, actionDebugName, actionRecord, m_currentNodeIterator, shouldCallAgain ); if( shouldCallAgain ) { return false; } if( !( tempBool ) ) { if( TweakAIActionRecord.IsSmartCompositeASelector( m_smartCompositeRecord ) ) { IncrementNodeIterator(); limitCounter += ( ( Uint32 )( 1 ) ); continue; } return false; } } else { if( m_smartCompositeRecord.FailOnNodeActivationConditionFailure() || sequenceRecord.FailOnNodeActivationConditionFailure() ) { return false; } IncrementNodeIterator(); limitCounter += ( ( Uint32 )( 1 ) ); continue; } } return actionRecord != NULL; } return false; } private override function Debug_GetBaseActionId() : TweakDBID { return m_smartComposite; } private override function Debug_GetCompositeId() : TweakDBID { return m_smartComposite; } private final function RandomizeGracefulInterruptionConditionCheckInterval( smartCompositeRecord : weak< AIActionSmartComposite_Record > ) { var randomCheckIntervalMods : array< Float >; m_gracefulInterruptionCheckRandomizedInterval = 0.0; m_hasGracefulInterruptionConditions = false; if( smartCompositeRecord.GetGracefulInterruptionConditionCount() > 0 ) { m_hasGracefulInterruptionConditions = true; } if( m_hasGracefulInterruptionConditions && ( smartCompositeRecord.GracefulInterruptionConditionCheckInterval() > 0.0 ) ) { randomCheckIntervalMods.Resize( 3 ); randomCheckIntervalMods[ 0 ] = 0.0; randomCheckIntervalMods[ 1 ] = 0.0334; randomCheckIntervalMods[ 2 ] = 0.0667; m_gracefulInterruptionCheckRandomizedInterval = smartCompositeRecord.GracefulInterruptionConditionCheckInterval(); m_gracefulInterruptionCheckRandomizedInterval += randomCheckIntervalMods[ RandRange( 0, 3 ) ]; } } public export virtual function GetFriendlyName() : String { if( TweakDBInterface.GetAIActionSmartCompositeRecord( m_smartComposite ) ) { return TweakAIActionRecord.GetFriendlyName( m_smartComposite, "SmartComposite" ); } else { return TweakAIActionRecord.GetFriendlyName( m_smartComposite, " [INVALID] SmartComposite" ); } } protected function CheckGracefulInterruptionConditions( const context : ScriptExecutionContext ) : Bool { var i : Int32; var count : Int32; count = m_smartCompositeRecord.GetGracefulInterruptionConditionCount(); for( i = 0; i < count; i += 1 ) { if( AICondition.CheckActionCondition( context, m_smartCompositeRecord.GetGracefulInterruptionConditionItem( i ) ) ) { return true; } } return false; } [ profile = "" ] private export override function Update( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome { if( !( RetryGetActionRecord( context ) ) ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } if( !( m_smartCompositeRecord ) ) { return AIbehaviorUpdateOutcome.FAILURE; } if( !( m_interruptionRequested ) ) { if( ( m_hasGracefulInterruptionConditions && ( m_gracefulInterruptionCheckRandomizedInterval <= 0.0 ) ) || ( ( m_gracefulInterruptionCheckRandomizedInterval > 0.0 ) && ( EngineTime.ToFloat( ScriptExecutionContext.GetAITime( context ) ) >= ( m_conditionCheckTimeStamp + m_gracefulInterruptionCheckRandomizedInterval ) ) ) ) { if( CheckGracefulInterruptionConditions( context ) ) { if( ( m_smartCompositeRecord.ConditionSuccessDuration() > 0.0 ) && ( m_conditionSuccessfulCheckTimeStamp < 0.0 ) ) { m_conditionSuccessfulCheckTimeStamp = EngineTime.ToFloat( ScriptExecutionContext.GetAITime( context ) ); } if( ( m_smartCompositeRecord.ConditionSuccessDuration() <= 0.0 ) || ( ( m_smartCompositeRecord.ConditionSuccessDuration() > 0.0 ) && ( EngineTime.ToFloat( ScriptExecutionContext.GetAITime( context ) ) >= ( m_conditionSuccessfulCheckTimeStamp + m_smartCompositeRecord.ConditionSuccessDuration() ) ) ) ) { m_interruptionRequested = super.RequestGracefulInterruption( context ); if( m_interruptionRequested ) { m_gracefullyInterrupted = true; } } } else { m_conditionSuccessfulCheckTimeStamp = -1.0; } m_conditionCheckTimeStamp = EngineTime.ToFloat( ScriptExecutionContext.GetAITime( context ) ); } } switch( super.Update( context ) ) { case AIbehaviorUpdateOutcome.FAILURE: { if( m_currentNodeType == ETweakAINodeType.Selector ) { if( RunCurrentNodeNextAction( context ) ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } } if( TweakAIActionRecord.IsSmartCompositeASelector( m_smartCompositeRecord ) && RunNextNode( context ) ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } ResetNodeIterator(); return AIbehaviorUpdateOutcome.FAILURE; } case AIbehaviorUpdateOutcome.SUCCESS: { if( m_interruptionRequested ) { return AIbehaviorUpdateOutcome.SUCCESS; } if( m_currentNodeType == ETweakAINodeType.Sequence && RunCurrentNodeNextAction( context ) ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } if( TweakAIActionRecord.IsSmartCompositeASequence( m_smartCompositeRecord ) && RunNextNode( context ) ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } return RepeatComposite( context ); } default: break; } return AIbehaviorUpdateOutcome.IN_PROGRESS; } private export override function Deactivate( context : ScriptExecutionContext ) { m_interruptionRequested = false; m_iteration = 0; m_currentNodeIterator = 0; if( !( m_smartCompositeRecord ) || !( m_smartCompositeRecord.Type().HasMemory() ) ) { ResetNodeIterator(); } else if( m_smartCompositeRecord.Type().IncrementIteratorOnDeactivation() ) { if( TweakAIActionRecord.IsThisLastActionInSmartComposite( m_smartCompositeRecord, m_nodeIterator ) ) { ResetNodeIterator(); } else { IncrementNodeIterator(); } } super.Deactivate( context ); m_gracefullyInterrupted = false; } private final function RepeatComposite( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome { m_iteration += ( ( Uint32 )( 1 ) ); if( ( m_smartCompositeRecord.Repeat() < 0 ) || ( m_iteration == ( ( Uint32 )( m_smartCompositeRecord.Repeat() ) ) ) ) { return AIbehaviorUpdateOutcome.SUCCESS; } super.Deactivate( context ); ResetNodeIterator(); super.Activate( context ); if( VerifyActionRecord() ) { switch( super.Update( context ) ) { case AIbehaviorUpdateOutcome.FAILURE: { if( m_currentNodeType == ETweakAINodeType.Selector ) { if( RunCurrentNodeNextAction( context ) ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } } if( TweakAIActionRecord.IsSmartCompositeASelector( m_smartCompositeRecord ) && RunNextNode( context ) ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } ResetNodeIterator(); return AIbehaviorUpdateOutcome.FAILURE; } case AIbehaviorUpdateOutcome.SUCCESS: { if( m_interruptionRequested ) { return AIbehaviorUpdateOutcome.SUCCESS; } if( m_currentNodeType == ETweakAINodeType.Sequence && RunCurrentNodeNextAction( context ) ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } if( TweakAIActionRecord.IsSmartCompositeASequence( m_smartCompositeRecord ) && RunNextNode( context ) ) { return AIbehaviorUpdateOutcome.IN_PROGRESS; } return AIbehaviorUpdateOutcome.IN_PROGRESS; } default: break; } return AIbehaviorUpdateOutcome.IN_PROGRESS; } return AIbehaviorUpdateOutcome.FAILURE; } private final function RunNextNode( context : ScriptExecutionContext ) : Bool { if( TweakAIActionRecord.IsThisLastActionInSmartComposite( m_smartCompositeRecord, m_nodeIterator ) ) { return false; } super.Deactivate( context ); IncrementNodeIterator(); super.Activate( context ); if( VerifyActionRecord() ) { super.Update( context ); } return true; } private final function RunCurrentNodeNextAction( context : ScriptExecutionContext ) : Bool { if( m_currentNodeType == ETweakAINodeType.Sequence && TweakAIActionRecord.IsThisLastActionInSequence( ( ( AIActionSequence_Record )( m_currentNode ) ), m_currentNodeIterator ) ) { return false; } if( m_currentNodeType == ETweakAINodeType.Selector && TweakAIActionRecord.IsThisLastActionInSelector( ( ( AIActionSelector_Record )( m_currentNode ) ), m_currentNodeIterator ) ) { return false; } m_currentNodeIterator += 1; super.Deactivate( context ); m_gracefullyInterrupted = false; super.Activate( context ); if( VerifyActionRecord() ) { super.Update( context ); } return true; } private final function ResetNodeIterator() { if( m_smartCompositeRecord && m_smartCompositeRecord.Type().RandomizeIteratorOnReset() ) { m_nodeIterator = RandRange( 0, m_smartCompositeRecord.GetNodesCount() ); m_currentNodeIterator = m_nodeIterator; } else { m_nodeIterator = 0; m_currentNodeIterator = 0; } } private final function IncrementNodeIterator() { m_nodeIterator += 1; m_currentNodeIterator = 0; m_gracefullyInterrupted = false; } } class IdleActionsCondition extends AIbehaviorconditionScript { private override final function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes { var characterRecord : weak< Character_Record >; characterRecord = TweakDBInterface.GetCharacterRecord( ScriptExecutionContext.GetOwner( context ).GetRecordID() ); if( !( characterRecord ) ) { return false; } if( !( characterRecord.IdleActions() ) ) { return false; } return true; } public constexpr function GetFriendlyName() : String { return "IdleActionsCondition"; } } class IdleActions extends TweakAIActionSmartComposite { public override function GetSmartCompositeRecord( const context : ScriptExecutionContext, smartCompositeID : TweakDBID, smartCompositeDebugName : ref< String >, out smartCompositeRecord : weak< AIActionSmartComposite_Record > ) : Bool { var characterRecord : weak< Character_Record >; characterRecord = TweakDBInterface.GetCharacterRecord( ScriptExecutionContext.GetOwner( context ).GetRecordID() ); if( !( characterRecord ) ) { return false; } smartCompositeRecord = characterRecord.IdleActions(); smartCompositeDebugName = "IdleActions"; return ( ( smartCompositeRecord ) ? ( true ) : ( false ) ); } public override function GetFriendlyName() : String { return "IdleActions"; } } class PatrolAction extends TweakAIActionSmartComposite { public override function GetSmartCompositeRecord( const context : ScriptExecutionContext, smartCompositeID : TweakDBID, smartCompositeDebugName : ref< String >, out smartCompositeRecord : weak< AIActionSmartComposite_Record > ) : Bool { var record : AIRecord_Record; var patrolActionID : TweakDBID; patrolActionID = ( ( TweakDBID )( GetPuppet( context ).GetAIControllerComponent().GetAIPatrolBlackboard().GetVariant( GetAllBlackboardDefs().AIPatrol.patrolAction ) ) ); if( !( TDBID.IsValid( patrolActionID ) ) ) { return false; } if( !( ScriptExecutionContext.GetOverriddenNode( context, patrolActionID, record, true ) ) ) { return false; } smartCompositeID = record.GetID(); if( !( IsFinal() ) ) { smartCompositeDebugName = TDBID.ToStringDEBUG( smartCompositeID ); } smartCompositeRecord = ( ( AIActionSmartComposite_Record )( record ) ); return smartCompositeRecord != NULL; } public export override function GetFriendlyName() : String { return "PatrolAction"; } } class PatrolSpotAction extends TweakAIActionSmartComposite { editable inlined var m_patrolAction : AIArgumentMapping; public override function GetSmartCompositeRecord( const context : ScriptExecutionContext, smartCompositeID : TweakDBID, smartCompositeDebugName : ref< String >, out smartCompositeRecord : weak< AIActionSmartComposite_Record > ) : Bool { var patrolActionName : CName; var patrolCompositeID : TweakDBID; var patrolCompositeRecord : weak< AIActionSmartComposite_Record >; patrolActionName = ( ( CName )( ScriptExecutionContext.GetMappingValue( context, m_patrolAction ) ) ); patrolCompositeID = TDBID.Create( ( ( String )( patrolActionName ) ) ); if( !( TDBID.IsValid( patrolCompositeID ) ) ) { return false; } patrolCompositeRecord = TweakDBInterface.GetAIActionSmartCompositeRecord( patrolCompositeID ); if( !( patrolCompositeRecord ) ) { return false; } smartCompositeRecord = patrolCompositeRecord; smartCompositeDebugName = "PatrolSpotAction"; return ( ( smartCompositeRecord ) ? ( true ) : ( false ) ); } public export override function GetFriendlyName() : String { return "PatrolSpotAction"; } }