Some parts of this article referring to Behavior Selection Trees and old-style behavior scripts are for CRYENGINE 3.4 or earlier. The Behavior Selection Tree and old-style behavior scripts were deprecated in favor of the Modular Behavior Tree in CRYENGINE 3.5 and beyond.
(Here ai_DebugDraw=1, ai_DebugDrawCover=2, and [AI/Physics] is on.)
TPS query:
AI.RegisterTacticalPointQuery({
Name = "Civilian_HideFromEnemy",
{
Generation =
{
cover_from_attentionTarget_around_puppet = 25
},
Conditions =
{
reachable = true,
},
Weights =
{
distance_from_puppet = -1,
},
},
});
TPS query referenced in a goalpipe:
<GoalPipes>
<GoalPipe name="Civilian_HideFromEnemy">
<TacticalPos name="Civilian_HideFromEnemy"/>
</GoalPipe>
</GoalPipes>
Goalpipe selected in a behavior:
local Behavior = CreateAIBehavior("CivilianIdle",
{
Alertness = 0,
OnEnemySeen = function(self, entity, distance)
entity:SelectPipe(0, "Civilian_HideFromEnemy");
end,
OnTPSDestReached = function(self, entity)
entity:SelectPipe(0, "_first_");
end,
})
For more realism, add the following before goalop TacticalPos:
<Speed id="Sprint"/>
New Civilian behavior:
<?xml version="1.0" encoding="utf-8"?>
<SelectionTrees>
<SelectionTree name="Civilian" type="BehaviorSelectionTree">
<Variables>
<Variable name="alerted"/>
</Variables>
<SignalVariables>
<Signal name="OnNoTarget" variable="alerted" value="false"/>
</SignalVariables>
<LeafTranslations>
<Map node="Alerted" target="CivilianAlerted"/>
<Map node="Idle" target="CivilianIdle"/>
</LeafTranslations>
<Priority name="Root">
<Leaf name="Alerted" condition="alerted"/>
<Leaf name="Idle"/>
</Priority>
</SelectionTree>
</SelectionTrees>
Idle behavior:
local Behavior = CreateAIBehavior("CivilianIdle",
{
Alertness = 0,
OnBulletRain = function(self, entity, sender, data)
entity.AI.hostileId = data.id;
AI.AddPersonallyHostile(entity.id, entity.AI.hostileId);
AI.SetBehaviorVariable(entity.id, "alerted", true);
end,
OnTPSDestReached = function(self, entity)
entity:SelectPipe(0, "_first_");
end,
});
Alerted behavior:
local Behavior = CreateAIBehavior("CivilianAlerted", "CivilianIdle",
{
Alertness = 2,
Constructor = function(self, entity)
entity:SelectPipe(0, "Civilian_HideFromEnemy");
end,
Destructor = function(self, entity)
AI.RemovePersonallyHostile(entity.id, entity.AI.hostileId);
end,
});