/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_CRYCOMMON_IAGENT_H #define CRYINCLUDE_CRYCOMMON_IAGENT_H #pragma once #include "Cry_Math.h" #include "AgentParams.h" #include "CrySizer.h" #include // <> required for Interfuscator #include // <> required for Interfuscator #include "SerializeFwd.h" #include #include // <> required for Interfuscator #include "IAIMannequin.h" #include #if defined(LINUX) || defined(APPLE) # include "platform.h" #endif #ifdef max #undef max #endif struct IAIActorProxy; struct IAIObject; struct IAIRateOfDeathHandler; struct IEntity; struct IGoalPipe; struct IGoalPipeListener; struct IPhysicalEntity; struct IWeapon; struct IAIGroupProxy; class CPipeUser; struct GoalParams; // Defines for AIObject types. #define AIOBJECT_NONE 200 #define AIOBJECT_DUMMY 0 #define AIOBJECT_ACTOR 5 #define AIOBJECT_VEHICLE 6 #define AIOBJECT_TARGET 9 #define AIOBJECT_AWARE 10 #define AIOBJECT_ATTRIBUTE 11 #define AIOBJECT_WAYPOINT 12 #define AIOBJECT_HIDEPOINT 13 #define AIOBJECT_SNDSUPRESSOR 14 #define AIOBJECT_NAV_SEED 15 #define AIOBJECT_HELICOPTER 40 #define AIOBJECT_HELICOPTERCRYSIS2 41 #define AIOBJECT_GUNFIRE 42 #define AIOBJECT_INFECTED 45 #define AIOBJECT_ALIENTICK 46 #define AIOBJECT_CAR 50 #define AIOBJECT_BOAT 60 #define AIOBJECT_AIRPLANE 70 #define AIOBJECT_2D_FLY 80 #define AIOBJECT_MOUNTEDWEAPON 90 #define AIOBJECT_GLOBALALERTNESS 94 #define AIOBJECT_LEADER 95 #define AIOBJECT_ORDER 96 #define AIOBJECT_PLAYER 100 #define AIOBJECT_GRENADE 150 #define AIOBJECT_RPG 151 #define AI_USE_HIDESPOTS (1 << 14) // Signal ids #define AISIGNAL_INCLUDE_DISABLED 0 #define AISIGNAL_DEFAULT 1 #define AISIGNAL_PROCESS_NEXT_UPDATE 3 #define AISIGNAL_NOTIFY_ONLY 9 #define AISIGNAL_ALLOW_DUPLICATES 10 #define AISIGNAL_RECEIVED_PREV_UPDATE 30 // Internal AI system use only, like AISIGNAL_DEFAULT but used for logging/recording. // A signal sent in the previous update and processed in the current (AISIGNAL_PROCESS_NEXT_UPDATE). #define AISIGNAL_INITIALIZATION -100 // Anchors #define AIANCHOR_FIRST 200 #define AIANCHOR_COMBAT_HIDESPOT 320 #define AIANCHOR_COMBAT_HIDESPOT_SECONDARY 330 #define AIANCHOR_COMBAT_TERRITORY 342 #define AIANCHOR_MNM_SHAPE 343 #define AIANCHOR_REINFORCEMENT_SPOT 400 #define AIANCHOR_NOGRENADE_SPOT 405 #define AIANCHOR_ADVANTAGE_POINT 329 // Summary: // Event types. #define AIEVENT_ONVISUALSTIMULUS 2 #define AIEVENT_ONSOUNDEVENT 4 #define AIEVENT_AGENTDIED 5 #define AIEVENT_SLEEP 6 #define AIEVENT_WAKEUP 7 #define AIEVENT_ENABLE 8 #define AIEVENT_DISABLE 9 #define AIEVENT_PATHFINDON 11 #define AIEVENT_PATHFINDOFF 12 #define AIEVENT_CLEAR 15 //#define AIEVENT_MOVEMENT_CONTROL 16 // Based on parameters lets object know if he is allowed to move. // #define AIEVENT_DROPBEACON 17 #define AIEVENT_USE 19 #define AIEVENT_CLEARACTIVEGOALS 22 #define AIEVENT_DRIVER_IN 23 // To enable/disable AIVehicles. #define AIEVENT_DRIVER_OUT 24 // To enable/disable AIVehicles. #define AIEVENT_FORCEDNAVIGATION 25 #define AIEVENT_ADJUSTPATH 26 #define AIEVENT_LOWHEALTH 27 #define AIEVENT_ONBULLETRAIN 28 #define AIEVENT_PLAYER_STUNT_SPRINT 101 #define AIEVENT_PLAYER_STUNT_JUMP 102 #define AIEVENT_PLAYER_STUNT_PUNCH 103 #define AIEVENT_PLAYER_STUNT_THROW 104 #define AIEVENT_PLAYER_STUNT_THROW_NPC 105 #define AIEVENT_PLAYER_THROW 106 #define AIEVENT_PLAYER_STUNT_CLOAK 107 #define AIEVENT_PLAYER_STUNT_UNCLOAK 108 #define AIEVENT_PLAYER_STUNT_ARMORED 109 #define AIEVENT_PLAYER_STAMP_MELEE 110 // Summary: // System Events types. #define AISYSEVENT_DISABLEMODIFIER 1 #define AIREADIBILITY_INTERESTING 5 #define AIREADIBILITY_SEEN 10 #define AIREADIBILITY_LOST 20 #define AIREADIBILITY_NORMAL 30 #define AIREADIBILITY_NOPRIORITY 1 #define AIGOALPIPE_LOOP 0 #define AIGOALPIPE_RUN_ONCE 1 // Todo: Not working yet - see PipeUser.cpp #define AIGOALPIPE_NOTDUPLICATE 2 #define AIGOALPIPE_HIGHPRIORITY 4 // It will be not removed when a goal pipe is selected. #define AIGOALPIPE_SAMEPRIORITY 8 // Sets the priority to be the same as active goal pipe. #define AIGOALPIPE_DONT_RESET_AG 16 // Don't reset the AG Input (by default AG Action input is reset to idle). #define AIGOALPIPE_KEEP_LAST_SUBPIPE 32 // Keeps the last inserted subpipe. #define AIGOALPIPE_KEEP_ON_TOP 64 // Keeps the inserted subpipe on the top for its duration, FIFO. enum ESignalFilter { SIGNALFILTER_SENDER, SIGNALFILTER_LASTOP, SIGNALFILTER_GROUPONLY, SIGNALFILTER_FACTIONONLY, SIGNALFILTER_ANYONEINCOMM, SIGNALFILTER_TARGET, SIGNALFILTER_SUPERGROUP, SIGNALFILTER_SUPERFACTION, SIGNALFILTER_SUPERTARGET, SIGNALFILTER_NEARESTGROUP, SIGNALFILTER_NEARESTSPECIES, SIGNALFILTER_NEARESTINCOMM, SIGNALFILTER_HALFOFGROUP, SIGNALFILTER_LEADER, SIGNALFILTER_GROUPONLY_EXCEPT, SIGNALFILTER_ANYONEINCOMM_EXCEPT, SIGNALFILTER_LEADERENTITY, SIGNALFILTER_NEARESTINCOMM_FACTION, SIGNALFILTER_NEARESTINCOMM_LOOKING, SIGNALFILTER_FORMATION, SIGNALFILTER_FORMATION_EXCEPT, SIGNALFILTER_READABILITY = 100, SIGNALFILTER_READABILITYAT, // Readability anticipation. SIGNALFILTER_READABILITYRESPONSE, // Readability response. }; static const float AISPEED_ZERO = 0.0f; static const float AISPEED_SLOW = 0.21f; static const float AISPEED_WALK = 0.4f; static const float AISPEED_RUN = 1.0f; static const float AISPEED_SPRINT = 1.4f; #define AI_JUMP_CHECK_COLLISION (1 << 0) #define AI_JUMP_ON_GROUND (1 << 1) #define AI_JUMP_RELATIVE (1 << 2) #define AI_JUMP_MOVING_TARGET (1 << 3) // Description: // The coverage half-angle of a hidespot anchor. The total coverage angle is twice this angle. #define HIDESPOT_COVERAGE_ANGLE_COS 0.5f // cos(60 degrees) enum EStance { STANCE_NULL = -1, STANCE_STAND = 0, STANCE_CROUCH, STANCE_PRONE, STANCE_RELAXED, STANCE_STEALTH, STANCE_LOW_COVER, STANCE_ALERTED, STANCE_HIGH_COVER, STANCE_SWIM, STANCE_ZEROG, // This value must be last STANCE_LAST }; inline const char* GetStanceName(int stance) { switch (stance) { case STANCE_NULL: return "Null"; case STANCE_STAND: return "Stand"; case STANCE_CROUCH: return "Crouch"; case STANCE_PRONE: return "Prone"; case STANCE_RELAXED: return "Relaxed"; case STANCE_STEALTH: return "Stealth"; case STANCE_ALERTED: return "Alerted"; case STANCE_LOW_COVER: return "LowCover"; case STANCE_HIGH_COVER: return "HighCover"; case STANCE_SWIM: return "Swim"; case STANCE_ZEROG: return "Zero-G"; default: return ""; } }; // Description: // Look style essentially define the transition style when look target is set. // Hard style is fast (surprised, startled), while soft is slow, relaxed. // NOLOWER variations only turn upper body, do not change actual body direction. enum ELookStyle { LOOKSTYLE_DEFAULT = 0, LOOKSTYLE_HARD, LOOKSTYLE_HARD_NOLOWER, LOOKSTYLE_SOFT, LOOKSTYLE_SOFT_NOLOWER, LOOKSTYLE_COUNT }; enum EFireMode { FIREMODE_OFF = 0, // Do not fire. FIREMODE_BURST = 1, // Fire in bursts - living targets only. FIREMODE_CONTINUOUS = 2, // Fire continuously - living targets only. FIREMODE_FORCED = 3, // Fire continuously - allow any target. FIREMODE_AIM = 4, // Aim target only - allow any target. FIREMODE_SECONDARY = 5, // Fire secondary weapon (grenades,....). FIREMODE_SECONDARY_SMOKE = 6, // Fire smoke grenade. FIREMODE_MELEE = 7, // Melee. FIREMODE_KILL = 8, // No missing, shoot directly at the target, no matter what aggression/attackRange/accuracy is. FIREMODE_BURST_WHILE_MOVING = 9, // [mikko] to be renamed. FIREMODE_PANIC_SPREAD = 10, FIREMODE_BURST_DRAWFIRE = 11, FIREMODE_MELEE_FORCED = 12, // Melee, without distance restrictions. FIREMODE_BURST_SNIPE = 13, FIREMODE_AIM_SWEEP = 14, FIREMODE_BURST_ONCE = 15, // Fire a single burst, then go to FIREMODE_OFF. FIREMODE_VEHICLE, FIREMODE_SERIALIZATION_HELPER_LAST, FIREMODE_SERIALIZATION_HELPER_FIRST = 0 }; enum EAIGoalFlags { // Todo: names are not coherent, but they can used together; rename all of them? AILASTOPRES_USE = 0x01, // AILASTOPRES_LOOKAT = 0x02, AI_LOOK_FORWARD = 0x04, AI_MOVE_BACKWARD = 0x08, // Default direction. AI_MOVE_RIGHT = 0x10, AI_MOVE_LEFT = 0x20, AI_MOVE_FORWARD = 0x40, AI_MOVE_BACKRIGHT = 0x80, AI_MOVE_BACKLEFT = 0x100, AI_MOVE_TOWARDS_GROUP = 0x200, // Towards the other group members. AI_REQUEST_PARTIAL_PATH = 0x400, AI_BACKOFF_FROM_TARGET = 0x800, AI_BREAK_ON_LIVE_TARGET = 0x1000, AI_RANDOM_ORDER = 0x2000, AI_CONSTANT_SPEED = 0x2000, // Used in stick goal (not using AI_RANDOM_ORDER) . AI_USE_TIME = 0x4000, // When param can be interpreted as time or distance, use time. AI_STOP_ON_ANIMATION_START = 0x8000, AI_USE_TARGET_MOVEMENT = 0x10000, // When requesting a direction (AI_MOVE_LEFT/RIGHT etc), make it relative to target movement direction. AI_ADJUST_SPEED = 0x20000, // Used in stick goal forces to adjust the speed based on the target. AI_CHECK_SLOPE_DISTANCE = 0x40000, // Used in backoff goal, checks the actual distance on slopes rather than horizontal. }; // Description: // Unit properties for group behavior (see CLeader/CLeaderAction). // These bit flags can be combined based on the unit capabilities. enum EUnitProperties { UPR_COMBAT_GROUND = 1, // The unit can take part in ground actions. UPR_COMBAT_FLIGHT = 2, // The unit can take part in flight actions. UPR_COMBAT_MARINE = 4, // The unit can take part in marine actions. UPR_COMBAT_RECON = 8, // The unit can take part in recon actions. UPR_ALL = -1, }; enum EAIUseAction { AIUSEOP_NONE, AIUSEOP_PLANTBOMB, AIUSEOP_VEHICLE, AIUSEOP_RPG }; enum ELeaderAction { LA_NONE, LA_HIDE, LA_HOLD, LA_ATTACK, LA_SEARCH, LA_FOLLOW, LA_USE, LA_USE_VEHICLE, LA_LAST, // Make sure this one is always the last! }; enum EAIAlertStatus { AIALERTSTATUS_SAFE, AIALERTSTATUS_UNSAFE, AIALERTSTATUS_READY, AIALERTSTATUS_ACTION }; enum EAITargetThreat { AITHREAT_NONE, AITHREAT_SUSPECT, AITHREAT_INTERESTING, AITHREAT_THREATENING, AITHREAT_AGGRESSIVE, AITHREAT_LAST // For serialization. }; enum EAITargetType { // Atomic types. AITARGET_NONE, // No target. AITARGET_SOUND, // Primary sensory from sound event. AITARGET_MEMORY, // Primary sensory from vis event, not visible. AITARGET_VISUAL, // Primary sensory from vis event, visible. // Backwards compatibility for scriptbind. AITARGET_ENEMY, AITARGET_FRIENDLY, AITARGET_BEACON, AITARGET_GRENADE, AITARGET_RPG, // For serialization. AITARGET_LAST }; enum EAITargetContextType { // Atomic types. AITARGET_CONTEXT_UNKNOWN, // No specific subtype. AITARGET_CONTEXT_GUNFIRE, // Gunfire subtype. // For serialization. AITARGET_CONTEXT_LAST }; enum EAITargetZone { AIZONE_IGNORE = 0, // Ignoring target zones AIZONE_KILL, AIZONE_COMBAT_NEAR, AIZONE_COMBAT_FAR, AIZONE_WARN, AIZONE_OUT, AIZONE_LAST }; enum EAIWeaponAccessories { AIWEPA_NONE = 0, AIWEPA_LASER = 0x0001, AIWEPA_COMBAT_LIGHT = 0x0002, AIWEPA_PATROL_LIGHT = 0x0004, }; // Note: // In practice, rather than modifying/setting all these values explicitly when // making a pathfind request, I suggest you set up bunch of constant sets // of properties, and use them. struct AgentPathfindingProperties { AgentPathfindingProperties( IAISystem::tNavCapMask _navCapMask, float _triangularResistanceFactor, float _waypointResistanceFactor, float _flightResistanceFactor, float _volumeResistanceFactor, float _roadResistanceFactor, float _waterResistanceFactor, float _maxWaterDepth, float _minWaterDepth, float _exposureFactor, float _dangerCost, float _zScale, uint32 _customNavCapsMask = 0, float _radius = 0.3f, float _height = 2.0f, float _maxSlope = 0.0f, int _id = -1, bool _avoidObstacles = true) : navCapMask(_navCapMask) , triangularResistanceFactor(_triangularResistanceFactor) , waypointResistanceFactor(_waypointResistanceFactor) , flightResistanceFactor(_flightResistanceFactor) , volumeResistanceFactor(_volumeResistanceFactor) , roadResistanceFactor(_roadResistanceFactor) , waterResistanceFactor(_waterResistanceFactor) , maxWaterDepth(_maxWaterDepth) , minWaterDepth(_minWaterDepth) , exposureFactor(_exposureFactor) , dangerCost(_dangerCost) , zScale(_zScale) , customNavCapsMask(_customNavCapsMask) , radius(_radius) , height(_height) , maxSlope(_maxSlope) , id(_id) , avoidObstacles(_avoidObstacles) { if (maxWaterDepth < minWaterDepth) { maxWaterDepth = minWaterDepth; } } AgentPathfindingProperties() { SetToDefaults(); } void SetToDefaults() { navCapMask = IAISystem::NAVMASK_ALL; triangularResistanceFactor = 0.0f; waypointResistanceFactor = 0.0f; flightResistanceFactor = 0.0f; volumeResistanceFactor = 0.0f; roadResistanceFactor = 0.0f; waterResistanceFactor = 0.0f; maxWaterDepth = 10000.0f; minWaterDepth = -10000.0f; exposureFactor = 0.0f; dangerCost = 0.0f; // Cost (in meters) per dead body in the destination node! zScale = 1.0f; customNavCapsMask = 0; radius = 0.3f; height = 2.0f; maxSlope = 0.0f; id = -1; avoidObstacles = true; } // Description: // Kind of nodes this agent can traverse. // Expected to normally be set just once when the agent is created. IAISystem::tNavCapMask navCapMask; // Description: // Basic extra costs associated with traversing each node type. // Everything below here could be reasonably set/modified each time // a pathfind request is made. float triangularResistanceFactor; float waypointResistanceFactor; float flightResistanceFactor; float volumeResistanceFactor; float roadResistanceFactor; // Summary: // Additional cost modifiers. float waterResistanceFactor; // Summary: // Only travel if water depth is between min and max values. float maxWaterDepth; float minWaterDepth; float exposureFactor; float dangerCost; // Summary: // Quantity the z component should be scaled by when calculating distances. float zScale; uint32 customNavCapsMask; float radius; float height; float maxSlope; // NOTE Aug 17, 2009: unique id of this instance among others. If there // were an array of these structs this could have been an index into that array. int id; bool avoidObstacles; }; struct AgentMovementSpeeds { enum EAgentMovementUrgency { AMU_SLOW, AMU_WALK, AMU_RUN, AMU_SPRINT, AMU_NUM_VALUES }; enum EAgentMovementStance { AMS_RELAXED, AMS_COMBAT, AMS_STEALTH, AMS_ALERTED, AMS_LOW_COVER, AMS_HIGH_COVER, AMS_CROUCH, AMS_PRONE, AMS_SWIM, AMS_NUM_VALUES }; struct SSpeedRange { float def, min, max; }; AgentMovementSpeeds() { memset(this, 0, sizeof(*this)); } void SetBasicSpeeds(float slow, float walk, float run, float sprint, float maneuver) { for (int s = 0; s < AMS_NUM_VALUES; ++s) { speedRanges[s][AMU_SLOW].def = slow; speedRanges[s][AMU_SLOW].min = maneuver; speedRanges[s][AMU_SLOW].max = slow; speedRanges[s][AMU_WALK].def = walk; speedRanges[s][AMU_WALK].min = maneuver; speedRanges[s][AMU_WALK].max = walk; speedRanges[s][AMU_RUN].def = run; speedRanges[s][AMU_RUN].min = maneuver; speedRanges[s][AMU_RUN].max = run; speedRanges[s][AMU_SPRINT].def = sprint; speedRanges[s][AMU_SPRINT].min = maneuver; speedRanges[s][AMU_SPRINT].max = sprint; } } void SetRanges(int stance, int urgency, float sdef, float smin, float smax) { assert(stance >= 0 && stance < AMS_NUM_VALUES); assert(urgency >= 0 && urgency < AMU_NUM_VALUES); speedRanges[stance][urgency].def = sdef; speedRanges[stance][urgency].min = smin; speedRanges[stance][urgency].max = smax; } void CopyRanges(int stance, int toUrgency, int fromUrgency) { assert(stance >= 0 && stance < AMS_NUM_VALUES); assert(toUrgency >= 0 && toUrgency < AMU_NUM_VALUES); assert(fromUrgency >= 0 && fromUrgency < AMU_NUM_VALUES); speedRanges[stance][toUrgency] = speedRanges[stance][fromUrgency]; } const SSpeedRange& GetRange(int stance, int urgency) const { assert(stance >= 0 && stance < AMS_NUM_VALUES); assert(urgency >= 0 && urgency < AMU_NUM_VALUES); return speedRanges[stance][urgency]; } // (MATT) Non-const version needed for serialisation {2009/04/23} SSpeedRange& GetRange(int stance, int urgency) { assert(stance >= 0 && stance < AMS_NUM_VALUES); assert(urgency >= 0 && urgency < AMU_NUM_VALUES); return speedRanges[stance][urgency]; } private: SSpeedRange speedRanges[AMS_NUM_VALUES][AMU_NUM_VALUES]; }; enum EAgentAvoidanceAbilities { eAvoidance_NONE = 0, eAvoidance_Vehicles = 0x01, // Agent can avoid vehicles eAvoidance_Actors = 0x02, // Agent can avoid puppets - DEPRECATED eAvoidance_Players = 0x04, // Agent can avoid players - DEPRECATED eAvoidance_StaticObstacle = 0x10, // Agent can avoid static physical objects (non-pushable) eAvoidance_PushableObstacle = 0x20, // Agent can avoid pushable objects eAvoidance_DamageRegion = 0x100, // Agent can avoid damage regions eAvoidance_ALL = 0xFFFF, eAvoidance_DEFAULT = eAvoidance_ALL, // Avoid all by default }; // Description: // Structure containing all the relevant information describing the way agent moves (can strafe,speeds,inertia,...). struct AgentMovementAbility { bool b3DMove; bool bUsePathfinder; bool usePredictiveFollowing; bool allowEntityClampingByAnimation; float maxAccel; float maxDecel; float minTurnRadius; float maxTurnRadius; float avoidanceRadius; float pathLookAhead; // How far to look ahead when path following. float pathRadius; // How wide the path should be treated. float pathSpeedLookAheadPerSpeed; // How far to look ahead to do speed control (mult this by the speed); -ve means use pathLookAhead. float cornerSlowDown; // Slow down at corners: 0 to 1. float slopeSlowDown; // Slow down on slopes uphill (0 to 1). float optimalFlightHeight; float minFlightHeight; float maxFlightHeight; float maneuverTrh; // Cosine of forward^desired angle, after which to start maneuvering float velDecay; // How fast velocity decays with cos(fwdDir^pathDir) . float pathFindPrediction; // Time in seconds how much the path finder will predict the start of the path. // Description: // Enables/disables the path getting regenerated during tracing (needed for crowd control and dynamic // updates to graph) - regeneration interval (in seconds) - 0 disables. float pathRegenIntervalDuringTrace; // Description: // Enables/disables teleporting when path following. bool teleportEnabled; // Description: // Sets to true if the movement speed should be lowered in low light conditions. bool lightAffectsSpeed; // Description: // Adjusts the movement speed based on the angel between body dir and move dir. // Enables/disables the algorithm to attempt to handle the agent getting stuck during tracing. bool resolveStickingInTrace; float directionalScaleRefSpeedMin; float directionalScaleRefSpeedMax; // Description: // Adjusts how the agent pathfollows around dynamic obstacles, both pushable and non-pushable uint32 avoidanceAbilities; bool pushableObstacleWeakAvoidance; float pushableObstacleAvoidanceRadius; // Description: // Defines the mass range of obstacles that can be pushed by this agent // If mass < min, agent will not avoid it // If mass > max, agent will always avoid it // If mass is in-between, agent will avoid it with an avoidanceRadius adjusted by the ratio between float pushableObstacleMassMin; float pushableObstacleMassMax; // True if the agent should participate in collision avoidance; false if not. // Note: if disabled, other agents don't avoid it either! bool collisionAvoidanceParticipation; // When moving, this increment value will be progressively added // to the agents avoidance radius (the rate is defined with the // CollisionAvoidanceRadiusIncrementIncreaseRate/DecreaseRate // console variables). // This is meant to make the agent keep a bit more distance between // him and other agents/obstacles. /Mario float collisionAvoidanceRadiusIncrement; AgentMovementSpeeds movementSpeeds; AgentPathfindingProperties pathfindingProperties; AgentMovementAbility() : b3DMove(false) , bUsePathfinder(true) , usePredictiveFollowing(false) , allowEntityClampingByAnimation(false) , maxAccel(std::numeric_limits::max()) , maxDecel(std::numeric_limits::max()) , minTurnRadius(0) , maxTurnRadius(0) , avoidanceRadius(0) , pathLookAhead(3.0f) , pathRadius(1.0f) , pathSpeedLookAheadPerSpeed(-1) , cornerSlowDown(0.0f) , slopeSlowDown(1.f) , optimalFlightHeight(0) , minFlightHeight(0) , maxFlightHeight(0) , maneuverTrh(0.f) , velDecay(0.0f) , pathFindPrediction(0) , resolveStickingInTrace(true) , pathRegenIntervalDuringTrace(0.0f) , teleportEnabled(false) , lightAffectsSpeed(false) , directionalScaleRefSpeedMin(-1.0f) , directionalScaleRefSpeedMax(-1.0f) , avoidanceAbilities(eAvoidance_DEFAULT) , pushableObstacleWeakAvoidance(false) , pushableObstacleAvoidanceRadius(0.35f) , pushableObstacleMassMin(0.0f) , pushableObstacleMassMax(0.0f) , collisionAvoidanceRadiusIncrement(0.0f) , collisionAvoidanceParticipation(true) {} }; struct AIObjectParams { AgentParameters m_sParamStruct; AgentMovementAbility m_moveAbility; uint16 type; IAIObject* association; const char* name; EntityId entityID; AIObjectParams() : type(0) , association(0) , name(0) , entityID(0) { } AIObjectParams(uint16 _type, const AgentParameters& sParamStruct, const AgentMovementAbility& moveAbility) : m_sParamStruct(sParamStruct) , m_moveAbility(moveAbility) , type(_type) , association(0) , name(0) , entityID(0) { } AIObjectParams(uint16 _type, IAIObject* _association = 0, EntityId _entityID = 0) : type(_type) , association(_association) , name(0) , entityID(_entityID) { } }; struct AIWeaponDescriptor { string firecmdHandler; float fSpeed; // Relevant for projectiles only. float fDamageRadius; // Explosion radius for rockets/grenades. float fChargeTime; float fRangeMax; float fRangeMin; bool bSignalOnShoot; int burstBulletCountMin; // The burst bullet count is scaled between min and max based on several factors (distance, visibility). int burstBulletCountMax; // Each burst is followed by a pause. float burstPauseTimeMin; // The burst pause is scale between min and max. float burstPauseTimeMax; float singleFireTriggerTime; // Interval between single shot shots. Scale randomly between 70-125%. Set to -1 for continuous fire. float spreadRadius; // Miss spread radius in meters. float coverFireTime; // How long the shooting should continue after the target is not visible anymore. float drawTime; // How long the AI will shoot around the target before aiming it precisely float sweepWidth; // How wide is the sweep left/right around the target direction during float sweepFrequency; // How fast the sweep left/right around the target direction during float pressureMultiplier; float lobCriticalDistance; float preferredHeight; // Preferred height used to throw the bullet if using a slow_projectile prediction float closeDistance; // What to consider close distance during the slow_projectile prediction float preferredHeightForCloseDistance; // Preferred height used to throw the bullet if using a slow_projectile prediction for close distance float maxAcceptableDistanceFromTarget; // Maximum distance allowed to evaluate the landing of the projectile. If less than 0 it's not taken into account. float minimumDistanceFromFriends; // Minimum distance to agents of a friendly faction. For now it is only used in the lob fire command by overriding the default value. Vec3 projectileGravity; // What's the gravity of the fired projectile - Used only for predicting grenade landing string smartObjectClass; AIWeaponDescriptor(const string& fcHandler = "instant", float chargeTime = -1.0f, float speed = -1.0f, float damageRadius = -1.0f) : firecmdHandler(fcHandler) , fSpeed(speed) , fDamageRadius(damageRadius) , fChargeTime(chargeTime) , fRangeMax(1000.f) , fRangeMin(1.f) , bSignalOnShoot(false) , burstBulletCountMin(1) , burstBulletCountMax(10) , burstPauseTimeMin(0.8f) , burstPauseTimeMax(3.5f) , singleFireTriggerTime(-1.0f) , spreadRadius(1.0f) , coverFireTime(2.0f) , drawTime(3.0f) , sweepWidth(2.5f) , sweepFrequency(3.0f) , pressureMultiplier(1.0f) , lobCriticalDistance(5.0f) , preferredHeight(5.0f) , closeDistance(0.0f) , preferredHeightForCloseDistance(5.0) , maxAcceptableDistanceFromTarget(-1.0f) , minimumDistanceFromFriends(-1.0f) , projectileGravity(0.0f, 0.0f, -9.8f) { } void GetMemoryUsage(ICrySizer* pSizer) const { pSizer->AddObject(smartObjectClass); pSizer->AddObject(firecmdHandler); } }; // The description of the various hazardous areas // related to the weapon. struct HazardWeaponDescriptor { // The maximum look ahead distance for constructing the waring area (>= 0.0f) (in meters). float maxHazardDistance; // The radius of the hazard warning area (>= 0.0f) (in meters). float hazardRadius; // How far to nudge the start of the warn area in the forwards direction from // the pivot position (in case the gun sticks out quite a bit for example) // (in meters). Negative values will nudge backwards. float startPosNudgeOffset; // How much we allow the hazard area approximation to deviate from the actual position of // its source (>= 0.0f) (in meters). float maxHazardApproxPosDeviation; // How much we allow the hazard area approximation deviate from the actual movement // direction of its source (>= 0.0f) (in degrees). float maxHazardApproxAngleDeviationDeg; HazardWeaponDescriptor() : maxHazardDistance(40.0f) , hazardRadius(4.0f) , startPosNudgeOffset(0.0f) , maxHazardApproxPosDeviation(5.0f) , maxHazardApproxAngleDeviationDeg(10.0f) { } void GetMemoryUsage(ICrySizer* pSizer) const { } }; // Memory fire control enum EMemoryFireType { eMFT_Disabled = 0, // Never allowed to fire at memory eMFT_UseCoverFireTime, // Can fire at memory using the weapon's cover fire time eMFT_Always, // Always allowed to fire at memory eMFT_COUNT, }; // Summary: // Current fire state of the AI based on its current fire command handler enum EAIFireState { eAIFS_Off = 0, eAIFS_On, eAIFS_Blocking, // Fire command handler is doing extra work and is not ready to fire yet eAIFS_COUNT, }; // Summary: // Projectile information to be used for firing weapon. struct SFireCommandProjectileInfo { EntityId trackingId; float fSpeedScale; SFireCommandProjectileInfo() : trackingId(0) , fSpeedScale(1.0f) {} void Reset() { trackingId = 0; fSpeedScale = 1.0f; } }; // Summary: // Interface to the fire command handler. struct IFireCommandHandler { // virtual ~IFireCommandHandler(){} // Summary: // Gets the name identifier of the handler. virtual const char* GetName() = 0; // Description: // Reset is called each time. virtual void Reset() = 0; // Description: // Update is called on each AI update when the target is valid. virtual EAIFireState Update(IAIObject* pTarget, bool canFire, EFireMode fireMode, const AIWeaponDescriptor& descriptor, Vec3& outShootTargetPos) = 0; // Description: // Checks if it's ok to shoot with this weapon in fireVector - to see if no friends are hit, no ostacles nearby hit, etc. virtual bool ValidateFireDirection(const Vec3& fireVector, bool mustHit) = 0; // Description: // Deletes the handler. virtual void Release() = 0; // Description: // Draws debug information. virtual void DebugDraw() = 0; // Description: // Returns true if default effect should be used for special firemode. virtual bool UseDefaultEffectFor(EFireMode fireMode) const = 0; // Description: // Called whenever weapon is reloaded. // Summary: // Reloads a weapon. virtual void OnReload() = 0; // Description: // Called whenever shot is done (if weapon descriptor defines EnableWeaponListener). // Summary: // Shot event function. virtual void OnShoot() = 0; // Description: // Returns how many shots were done. virtual int GetShotCount() const = 0; // Description: // Used by fire command handler to fill in information about projectiles to be fired by the AI virtual void GetProjectileInfo(SFireCommandProjectileInfo& info) const {}; virtual bool GetOverrideAimingPosition(Vec3& overrideAimingPosition) const { return false; } // Description: // If this firemode has a pause timer i.e. burst pause, this should return the current value of that timer // or if the fire mode has a slow fire rate i.e. rocket launcher it should return the fire timer - 0 otherwise virtual float GetTimeToNextShot() const = 0; virtual void GetMemoryUsage(ICrySizer* pSizer) const{} // }; // Description: // Memento used in CanTargetPointBeReached etc. class CTargetPointRequest { public: CTargetPointRequest() {} CTargetPointRequest(const Vec3& _targetPoint, bool _continueMovingAtEnd = true) : targetPoint(_targetPoint) , pathID(-1) , continueMovingAtEnd(_continueMovingAtEnd) , splitPoint(ZERO) {} ETriState GetResult() const { return result; } const Vec3& GetPosition() const { return targetPoint; } void SetResult(ETriState res) { result = res; } private: // Data is internal to AI (CNavPath)! friend class CNavPath; Vec3 targetPoint; Vec3 splitPoint; int itIndex; int itBeforeIndex; // Summary: // Used to identify the path this was valid for. int pathID; bool continueMovingAtEnd; ETriState result; }; struct SAIEVENT { bool bFuzzySight; bool bSetObserver; int nDeltaHealth; float fThreat; int nType; int nFlags; Vec3 vPosition; Vec3 vStimPos; Vec3 vForcedNavigation; EntityId sourceId; EntityId targetId; SAIEVENT() : bFuzzySight(false) , bSetObserver(false) , nDeltaHealth(0) , fThreat(0.f) , nType(0) , nFlags(0) , vPosition(ZERO) , vStimPos(ZERO) , vForcedNavigation(ZERO) , sourceId(0) , targetId(0) {} }; enum EObjectResetType { AIOBJRESET_INIT, AIOBJRESET_SHUTDOWN, }; enum EGoalPipeEvent { ePN_Deselected, // Sent if replaced by selecting other pipe. ePN_Finished, // Sent if reached end of pipe. ePN_Inserted, // Sent if pipe is inserted with InsertPipe(). ePN_Suspended, // Sent if other pipe was inserted. ePN_Resumed, // Sent if resumed after finishing inserted pipes. ePN_Removed, // Sent if inserted pipe was removed with RemovePipe(). ePN_Exiting, // Sent if a non-looped pipe is completed ePN_AnimStarted, // Sent when exact positioning animation is started. ePN_RefPointMoved, // Sent to the last inserted goal pipe when the ref. point is moved. }; // Todo: Figure out better way to handle this, the structure is almost 1:1 to the SActorTargetParams. typedef uint32 TAnimationGraphQueryID; struct SAIActorTargetRequest { SAIActorTargetRequest() : id(0) , approachLocation(ZERO) , approachDirection(ZERO) , animLocation(ZERO) , animDirection(ZERO) , vehicleSeat(0) , speed(0) , directionTolerance(0) , startArcAngle(0) , startWidth(0) , loopDuration(-1) , signalAnimation(true) , projectEndPoint(true) , lowerPrecision(false) , useAssetAlignment(false) , stance(STANCE_NULL) , pQueryStart(0) , pQueryEnd(0) { } void Reset() { id = 0; approachLocation.zero(); approachDirection.zero(); animLocation.zero(); animDirection.zero(); vehicleSeat = 0; speed = 0; directionTolerance = 0; startArcAngle = 0; startWidth = 0; loopDuration = -1; signalAnimation = true; projectEndPoint = true; lowerPrecision = false; useAssetAlignment = false; stance = STANCE_NULL; pQueryStart = 0; pQueryEnd = 0; vehicleName = ""; animation = ""; } void Serialize(TSerialize ser); int id; // id=0 means invalid Vec3 approachLocation; Vec3 approachDirection; Vec3 animLocation; Vec3 animDirection; string vehicleName; int vehicleSeat; float speed; float directionTolerance; float startArcAngle; float startWidth; float loopDuration; // (-1 = forever) bool signalAnimation; bool projectEndPoint; bool lowerPrecision; // Lower precision should be true when passing through a navSO. bool useAssetAlignment; string animation; EStance stance; TAnimationGraphQueryID* pQueryStart; TAnimationGraphQueryID* pQueryEnd; }; enum CoverHeight { LowCover, HighCover }; enum EBodyOrientationMode { FullyTowardsMovementDirection, FullyTowardsAimOrLook, HalfwayTowardsAimOrLook }; struct IPipeUser { typedef AZStd::shared_ptr LookTargetPtr; // virtual ~IPipeUser() {} virtual bool SelectPipe(int id, const char* name, IAIObject* pArgument = 0, int goalPipeId = 0, bool resetAlways = false, const GoalParams* node = 0) = 0; virtual IGoalPipe* InsertSubPipe(int id, const char* name, IAIObject* pArgument = 0, int goalPipeId = 0, const GoalParams* node = 0) = 0; virtual bool CancelSubPipe(int goalPipeId) = 0; virtual bool RemoveSubPipe(int goalPipeId, bool keepInserted = false) = 0; virtual bool IsUsingPipe(const char* name) const = 0; virtual bool IsUsingPipe(int goalPipeId) const = 0; virtual void Pause(bool pause) = 0; virtual bool IsPaused() const = 0; virtual IAIObject* GetAttentionTargetAssociation() const = 0; virtual IAIObject* GetLastOpResult() = 0; virtual void ResetCurrentPipe(bool bAlways) {; } virtual IAIObject* GetSpecialAIObject(const char* objName, float range = 0.0f) = 0; virtual void MakeIgnorant(bool ignorant) = 0; #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM virtual bool SetCharacter(const char* character, const char* behaviour = NULL) = 0; #endif virtual void SetInCover(bool inCover) = 0; virtual bool IsInCover() const = 0; virtual bool IsCoverCompromised() const = 0; virtual void SetCoverCompromised() = 0; virtual bool IsTakingCover(float distanceThreshold) const = 0; virtual bool IsMovingToCover() const = 0; virtual CoverHeight CalculateEffectiveCoverHeight() const = 0; virtual void ClearDevalued() = 0; virtual void RegisterGoalPipeListener(IGoalPipeListener* pListener, int goalPipeId, const char* debugClassName) = 0; virtual void UnRegisterGoalPipeListener(IGoalPipeListener* pListener, int goalPipeId) = 0; virtual int GetGoalPipeId() const = 0; virtual IGoalPipe* GetCurrentGoalPipe() = 0; virtual void SetAllowedStrafeDistances(float start, float end, bool whileMoving) = 0; virtual void SetExtraPriority(float priority) = 0; virtual float GetExtraPriority(void) = 0; virtual IAIObject* GetRefPoint() = 0; virtual void SetRefPointPos(const Vec3& pos) = 0; virtual void SetRefPointPos(const Vec3& pos, const Vec3& dir) = 0; virtual void SetRefShapeName(const char* shapeName) = 0; virtual const char* GetRefShapeName() const = 0; virtual void SetActorTargetRequest(const SAIActorTargetRequest& req) = 0; virtual void ClearActorTargetRequest() = 0; virtual EntityId GetLastUsedSmartObjectId() const = 0; virtual bool IsUsingNavSO() const = 0; virtual void ClearPath(const char* dbgString) = 0; virtual void SetFireMode(EFireMode mode) = 0; virtual EFireMode GetFireMode() const = 0; // Summary: // Adds the current hideobject position to ignore list (will be ignored for specified time). virtual void IgnoreCurrentHideObject(float timeOut = 10.0f) = 0; // Summary: // Returns most probable target position or the target if it is visible. virtual Vec3 GetProbableTargetPosition() = 0; virtual void AllowLowerBodyToTurn(bool bAllowLowerBodyToTurn) = 0; virtual bool IsAllowingBodyTurn() = 0; virtual LookTargetPtr CreateLookTarget() = 0; // }; struct IGoalPipeListener { virtual void OnGoalPipeEvent(IPipeUser* pPipeUser, EGoalPipeEvent event, int goalPipeId, bool& unregisterListenerAfterEvent) = 0; private: friend class CPipeUser; typedef DynArray< std::pair< IPipeUser*, int > > VectorRegisteredPipes; VectorRegisteredPipes _vector_registered_pipes; protected: virtual ~IGoalPipeListener() { assert(_vector_registered_pipes.empty()); while (_vector_registered_pipes.empty() == false) { _vector_registered_pipes.back().first->UnRegisterGoalPipeListener(this, _vector_registered_pipes.back().second); } } }; struct ISmartObjectManager { typedef IStatObj* IStatObjPtr; // virtual ~ISmartObjectManager(){} virtual void RemoveSmartObject(IEntity* pEntity) = 0; virtual const char* GetSmartObjectStateName(int id) const = 0; virtual void RegisterSmartObjectState(const char* sStateName) = 0; virtual void AddSmartObjectState(IEntity* pEntity, const char* sState) = 0; virtual void RemoveSmartObjectState(IEntity* pEntity, const char* sState) = 0; virtual bool CheckSmartObjectStates(const IEntity* pEntity, const char* patternStates) const = 0; virtual void SetSmartObjectState(IEntity* pEntity, const char* sStateName) = 0; virtual void ModifySmartObjectStates(IEntity* pEntity, const char* listStates) = 0; virtual void DrawSOClassTemplate(IEntity* pEntity) = 0;//TODO make const virtual bool ValidateSOClassTemplate(IEntity* pEntity) = 0;//TODO make const // Call with ppStatObjects == NULL to get numAllocStatObjects. // Call with allocated ppStatObjects array with numAllocStatObjects, returns found #. virtual uint32 GetSOClassTemplateIStatObj(IEntity* pEntity, IStatObjPtr* ppStatObjects, uint32& numAllocStatObjects) = 0;//TODO make this const at some point if possible virtual void ReloadSmartObjectRules() = 0; virtual int SmartObjectEvent(const char* sEventName, IEntity*& pUser, IEntity*& pObject, const Vec3* pExtraPoint = NULL, bool bHighPriority = false) = 0; virtual SmartObjectHelper* GetSmartObjectHelper(const char* className, const char* helperName) const = 0; // }; struct IAIAction; struct IAIActionManager : public IGoalPipeListener { // // returns an existing AI Action from the library or NULL if not found virtual IAIAction* GetAIAction(const char* sName) = 0; // returns an existing AI Action by its index in the library or NULL index is out of range virtual IAIAction* GetAIAction(size_t index) = 0; virtual void ReloadActions() = 0; // aborts specific AI Action (specified by goalPipeId) or all AI Actions (goalPipeId == 0) in which pEntity is a user virtual void AbortAIAction(IEntity* pEntity, int goalPipeId = 0) = 0; // finishes specific AI Action (specified by goalPipeId) for the pEntity as a user virtual void FinishAIAction(IEntity* pEntity, int goalPipeId) = 0; // }; struct IPuppet { // virtual ~IPuppet() {} virtual void UpTargetPriority(const IAIObject* pTarget, float fPriorityIncrement) = 0; virtual void UpdateBeacon() = 0; virtual bool IsAlarmed() const = 0; virtual float GetPerceptionAlarmLevel() const = 0; virtual IAIObject* MakeMeLeader() = 0; // Summary: // Gets the owner of a dummy AI Object virtual IAIObject* GetEventOwner(IAIObject* pObject) const = 0; // Summary: // Where to shoot if need to miss now (target is another AI) - select some point around target . virtual Vec3 ChooseMissPoint_Deprecated(const Vec3& targetPos) const = 0; // Return Value: // true and sends signal "OnFriendInWay" if there is a friendly agent in the line of fire. // Description: // Checks if there are friends in the line of fire. // If the cheapTest flag is set, only cone test is performed, otherwise raycasting. virtual bool CheckFriendsInLineOfFire(const Vec3& fireDirection, bool cheapTest) = 0; // Description: // Gets the distance of an AI object to this, along this path. // Note: // Must be called with bInit=true first time and then false // other time to avoid considering path regeneration after. virtual float GetDistanceAlongPath(const Vec3& pos, bool bInit) = 0; virtual void EnableFire(bool enable) = 0; virtual bool IsFireEnabled() const = 0; virtual void EnableCoverFire(bool enable) = 0; virtual bool IsCoverFireEnabled() const = 0; virtual bool GetPosAlongPath(float dist, bool extrapolateBeyond, Vec3& retPos) const = 0; virtual IFireCommandHandler* GetFirecommandHandler() const = 0; // Description: // Changes flag so this puppet can be shoot or not. virtual void SetCanBeShot(bool bCanBeShot) {; } virtual bool GetCanBeShot() const { return true; } // Set how this puppet treats firing at its memory target virtual void SetMemoryFireType(EMemoryFireType eType) {; } virtual EMemoryFireType GetMemoryFireType() const { return eMFT_UseCoverFireTime; } virtual bool CanMemoryFire() const { return true; } // Helper to get the puppet's perceived position of an agent // Returns TRUE if puppet has a perceived location for this target virtual bool GetPerceivedTargetPos(IAIObject* pTarget, Vec3& vPos) const = 0; // ROD Handler virtual void SetRODHandler(IAIRateOfDeathHandler* pHandler) = 0; virtual void ClearRODHandler() = 0; // }; struct IAISignalExtraData { // virtual ~IAISignalExtraData(){} virtual void Serialize(TSerialize ser) = 0; virtual const char* GetObjectName() const = 0; virtual void SetObjectName(const char* objectName) = 0; // To/from script table virtual void ToScriptTable(SmartScriptTable& table) const = 0; virtual void FromScriptTable(const SmartScriptTable& table) = 0; // IAISignalExtraData() : string1(NULL) , string2(NULL) {} Vec3 point; Vec3 point2; ScriptHandle nID; float fValue; int iValue; int iValue2; const char* string1; const char* string2; }; // Put new signal here! struct AISIGNAL { int nSignal; uint32 m_nCrcText; EntityId senderID; IAISignalExtraData* pEData; static const int SIGNAL_NAME_LENGTH = 50; char strText[SIGNAL_NAME_LENGTH]; AISIGNAL() : nSignal(0) , m_nCrcText(0) , senderID(0) , pEData(NULL) { strText[0] = 0; } void Serialize(TSerialize ser); inline bool Compare(uint32 crc) const { return m_nCrcText == crc; } }; struct PATHPOINT { Vec3 vPos; Vec3 vDir; PATHPOINT( const Vec3& _vPos = Vec3_Zero, const Vec3& _vDir = Vec3_Zero) : vPos(_vPos) , vDir(_vDir) {} }; typedef DynArray PATHPOINTVECTOR; // Summary: // Current phase of actor target animation enum EActorTargetPhase { eATP_None, eATP_Waiting, eATP_Starting, eATP_Started, eATP_Playing, eATP_StartedAndFinished, eATP_Finished, eATP_Error, }; enum EAITargetStuntReaction { AITSR_NONE, AITSR_SEE_STUNT_ACTION, AITSR_SEE_CLOAKED, AITSR_LAST }; // Summary: // Current phase of actor target animation. enum ERequestedGrenadeType { eRGT_INVALID = -1, eRGT_ANY, eRGT_SMOKE_GRENADE, eRGT_FLASHBANG_GRENADE, eRGT_FRAG_GRENADE, eRGT_EMP_GRENADE, eRGT_GRUNT_GRENADE, eRGT_COUNT, }; struct SAIPredictedCharacterState { SAIPredictedCharacterState() : predictionTime(0.f) , position(ZERO) , velocity(ZERO) {} void Set(const Vec3& pos, const Vec3& vel, float predT) { position = pos; velocity = vel; predictionTime = predT; } void Serialize(TSerialize ser); Vec3 position; Vec3 velocity; float predictionTime; // Time of prediction relative to when it was made. }; struct SAIPredictedCharacterStates { SAIPredictedCharacterStates() : nStates(0){} void Serialize(TSerialize ser); enum { maxStates = 32 }; SAIPredictedCharacterState states[maxStates]; int nStates; }; enum ECoverBodyDirection { eCoverBodyDirection_Unspecified, eCoverBodyDirection_Left, eCoverBodyDirection_Right, }; enum ECoverAction { eCoverAction_Unspecified, eCoverAction_Set, eCoverAction_Clear, }; enum ECoverLocationRequest { eCoverLocationRequest_Unspecified, eCoverLocationRequest_Set, eCoverLocationRequest_Clear, }; struct SAICoverRequest { SAICoverRequest() : coverBodyDirection(eCoverBodyDirection_Unspecified) , coverAction(eCoverAction_Unspecified) , coverActionName(NULL) , coverLocation(IDENTITY) , coverLocationRequest(eCoverLocationRequest_Unspecified) {} // coverNormal points OUT of the cover surface void SetCoverBodyDirection(const Vec3& coverNormal, const Vec3& targetDirection) { const Vec2 coverNormal2D(coverNormal); const Vec2 targetDirection2D(targetDirection); const float cross = coverNormal2D.Cross(targetDirection2D); //assert( coverBodyDirection == eCoverBodyDirection_Unspecified ); // Cannot be guaranteed yet coverBodyDirection = (cross < 0.0f) ? eCoverBodyDirection_Left : eCoverBodyDirection_Right; } // coverNormal points OUT of the cover surface void SetCoverBodyDirectionWithThreshold(const Vec3& coverNormal, const Vec3& targetDirection, const float thresholdAngleRadians) { const Vec2 coverNormal2D(coverNormal); const Vec2 targetDirection2D = Vec2(targetDirection).GetNormalizedSafe(Vec2(0, 1)); const float dot = (-coverNormal2D).Dot(targetDirection2D); //assert( coverBodyDirection == eCoverBodyDirection_Unspecified ); // Cannot be guaranteed yet const float threshold = cos(thresholdAngleRadians); if (dot <= threshold) { const float cross = coverNormal2D.Cross(targetDirection2D); coverBodyDirection = (cross < 0.0f) ? eCoverBodyDirection_Left : eCoverBodyDirection_Right; } } void SetCoverAction(const char* const name, const float postureLean) { coverActionName = name; coverAction = (coverActionName && coverActionName[0]) ? eCoverAction_Set : eCoverAction_Clear; //assert( coverBodyDirection == eCoverBodyDirection_Unspecified ); // Cannot be guaranteed yet if (postureLean < 0) { coverBodyDirection = eCoverBodyDirection_Left; } else if (0 < postureLean) { coverBodyDirection = eCoverBodyDirection_Right; } } void ClearCoverAction() { coverActionName = NULL; coverAction = eCoverAction_Clear; } void SetCoverLocation(const Vec3& position, const Vec3& forwardDirection) { CRY_ASSERT(position.IsValid()); CRY_ASSERT(forwardDirection.IsValid()); CRY_ASSERT(forwardDirection.IsUnit()); coverLocation = QuatT(position, Quat::CreateRotationVDir(forwardDirection)); coverLocationRequest = eCoverLocationRequest_Set; } void ClearCoverLocation() { coverLocationRequest = eCoverLocationRequest_Clear; } ECoverBodyDirection coverBodyDirection; ECoverAction coverAction; const char* coverActionName; QuatT coverLocation; ECoverLocationRequest coverLocationRequest; }; struct SOBJECTSTATE { enum EFireControllerIndex { eFireControllerIndex_None = 0, eFireControllerIndex_First = 1, eFireControllerIndex_Second = 2, eFireControllerIndex_Third = 3, eFireControllerIndex_Fourth = 4, eFireControllerIndex_All = 17185, // This value right shifted (4*n) times put in & with 0xf should give you the index of the n+1 fire controller index }; // Actor's movement\looking\firing related. bool jump; bool aimObstructed; bool aimTargetIsValid; // bool forceWeaponAlertness; EAIFireState fire; EAIFireState fireSecondary; EAIFireState fireMelee; ERequestedGrenadeType requestedGrenadeType; int weaponAccessories; // Weapon accessories to enable. int bodystate; float lean; float peekOver; Vec3 vShootTargetPos; // The requested position to shoot at. This value must be passed directly to weapon system, // the AI system has decided already if the shot should miss or hit. Notes: can be (0,0,0) if not begin requested! Vec3 vAimTargetPos; // The requested position to aim at. This value is slightly different from the vShootTarget, and is // used for visual representation to where to shoot at. Notes: can be (0,0,0) if not begin requested! Vec3 vLookTargetPos; // The requested position to look at. Notes: can be (0,0,0) if not begin requested! Vec3 vLobLaunchPosition; Vec3 vLobLaunchVelocity; SFireCommandProjectileInfo projectileInfo; ELookStyle eLookStyle; bool bAllowLowerBodyToTurn; // FR: Temporary flag to avoid the body turn while doing specific operation. // It should be removed when there could be a proper procedural clip in Mannequin to lock the turn, aiming, etc. Vec3 vMoveDir; Vec3 vForcedNavigation; Vec3 vBodyTargetDir; Vec3 vDesiredBodyDirectionAtTarget; float fForcedNavigationSpeed; unsigned int movementContext; // flags that give context to movement, which can be used by animation selection system // Hint to animation system what will happen in the future. [not used in Crysis2] SAIPredictedCharacterStates predictedCharacterStates; // Precision movement support: A replacement for the old velocity based movement system above. // NOTE: If the move target and inflection point are equal (and non-zero) they mark the end of the path. Vec3 vMoveTarget; // If non-zero, contains the absolute position the agent should (and can) move towards. Vec3 vInflectionPoint; // If non-zero, contains the estimated future move target once the agent reaches the current move target. // Description: // AISPEED_ZERO, AISPEED_SLOW, AISPEED_WALK, AISPEED_RUN, AISPEED_SPRINT. This affects animation and thus speed only indirectly, // due to it affecting the available max/min speeds. // See also: // AISPEED_ZERO, AISPEED_SLOW, AISPEED_WALK, AISPEED_RUN, AISPEED_SPRINT float fMovementUrgency; float fDesiredSpeed; //< in m/s float fTargetSpeed; //< in m/s bool allowStrafing; // Whether strafing is allowed or not. bool allowEntityClampingByAnimation; float fDistanceToPathEnd; Vec3 vDirOffPath; // displacement vector between the physical position and the current path. EActorTargetPhase curActorTargetPhase; // Return value. Vec3 curActorTargetFinishPos; // Return value. SAIActorTargetRequest actorTargetReq; bool bCloseContact; bool bReevaluate; bool bTargetEnabled; bool bTargetIsGroupTarget; bool continuousMotion; EAITargetType eTargetType; EAITargetContextType eTargetContextType; EAITargetThreat eTargetThreat; tAIObjectID eTargetID; EAITargetType ePeakTargetType; EAITargetThreat ePeakTargetThreat; tAIObjectID ePeakTargetID; EAITargetType ePreviousPeakTargetType; EAITargetThreat ePreviousPeakTargetThreat; tAIObjectID ePreviousPeakTargetID; Vec3 vTargetPos; float fDistanceFromTarget; EAITargetStuntReaction eTargetStuntReaction; int nTargetType; DynArray vSignals; int secondaryIndex; CAIMannequinCommandList<32> mannequinRequest; SAICoverRequest coverRequest; EBodyOrientationMode bodyOrientationMode; SOBJECTSTATE() : forceWeaponAlertness(false) , eLookStyle(LOOKSTYLE_DEFAULT) , bAllowLowerBodyToTurn(true) , continuousMotion(false) , vLobLaunchPosition(ZERO) , vLobLaunchVelocity(ZERO) , bodyOrientationMode(HalfwayTowardsAimOrLook) { FullReset(true); } void Reset(bool clearMoveDir = true) { bCloseContact = false; bTargetIsGroupTarget = false; eTargetThreat = AITHREAT_NONE; eTargetType = AITARGET_NONE; eTargetID = 0; vTargetPos.zero(); eTargetContextType = AITARGET_CONTEXT_UNKNOWN; eTargetStuntReaction = AITSR_NONE; if (clearMoveDir) { if (!continuousMotion) { vMoveDir.zero(); } } vForcedNavigation.zero(); fForcedNavigationSpeed = 0.0f; projectileInfo.Reset(); predictedCharacterStates.nStates = 0; bTargetEnabled = false; } void FullReset(bool clearMoveDir = false) { Reset(clearMoveDir); //Only reset peaks on a full reset ePeakTargetThreat = AITHREAT_NONE; ePeakTargetType = AITARGET_NONE; ePeakTargetID = 0; ePreviousPeakTargetType = AITARGET_NONE; ePreviousPeakTargetThreat = AITHREAT_NONE; ePreviousPeakTargetID = 0; vLookTargetPos.zero(); vBodyTargetDir.zero(); vShootTargetPos.zero(); vAimTargetPos.zero(); vLobLaunchPosition.zero(); vLobLaunchVelocity.zero(); fDistanceToPathEnd = -1.0f; movementContext = 0; bAllowLowerBodyToTurn = true; vMoveDir.zero(); vMoveTarget.zero(); vInflectionPoint.zero(); vDesiredBodyDirectionAtTarget.zero(); vDirOffPath.zero(); jump = false; fire = eAIFS_Off; fireSecondary = eAIFS_Off; fireMelee = eAIFS_Off; requestedGrenadeType = eRGT_ANY; aimObstructed = false; aimTargetIsValid = false; weaponAccessories = AIWEPA_NONE; allowStrafing = false; bodystate = 0; fDistanceFromTarget = FLT_MAX; actorTargetReq.Reset(); curActorTargetPhase = eATP_None; curActorTargetFinishPos.zero(); allowEntityClampingByAnimation = false; nTargetType = 0; fMovementUrgency = AISPEED_WALK; fDesiredSpeed = 1.0f; fTargetSpeed = 1.0f; lean = 0.0f; peekOver = 0.0f; ClearSignals(); secondaryIndex = 0; continuousMotion = false; coverRequest = SAICoverRequest(); mannequinRequest.ClearCommands(); bodyOrientationMode = HalfwayTowardsAimOrLook; } void ClearSignals() { for (size_t idx = 0, count = vSignals.size(); idx != count; ++idx) { if (vSignals[idx].pEData) { gEnv->pAISystem->FreeSignalExtraData(vSignals[idx].pEData); } } vSignals.clear(); } bool operator == (SOBJECTSTATE& other) { if (fire == other.fire) { if (bodystate == other.bodystate) { return true; } } return false; } void Serialize(TSerialize ser); }; struct SAIBodyInfo { Vec3 vEyePos; Vec3 vEyeDir; // Direction of head (where I'm looking at). Vec3 vEyeDirAnim; // Direction of head from animation . Vec3 vEntityDir; Vec3 vAnimBodyDir; Vec3 vMoveDir; // Direction of entity movement. Vec3 vUpDir; // Direction of entity (my up). Vec3 vFireDir; // Firing direction. Vec3 vFirePos; // Firing position. float maxSpeed; // Maximum speed i can move at. float normalSpeed; // The "normal" (walking) speed. float minSpeed; // Minimum speed i need to move anywhere (otherwise I'll consider myself stopped). EStance stance; AABB stanceSize; // Approximate local bounds of the stance, relative to the entity position. AABB colliderSize; // Approximate local bounds of the stance, relative to the entity position. bool isAiming; bool isFiring; bool isMoving; float lean; // The amount the character is leaning. float peekOver; // The amount the character is peaking-over. float slopeAngle; //If valid animated eye direction present, use that for better precision const Vec3& GetEyeDir() const { return vEyeDirAnim.IsZero() ? vEyeDir : vEyeDirAnim; } //If valid animated body direction present, use that for better precision const Vec3& GetBodyDir() const { return vAnimBodyDir.IsZero() ? vEntityDir : vAnimBodyDir; } EntityId linkedVehicleEntityId; SAIBodyInfo() : vEyePos(ZERO) , vEyeDir(ZERO) , vEyeDirAnim(ZERO) , vEntityDir(ZERO) , vAnimBodyDir(ZERO) , vMoveDir(ZERO) , vUpDir(ZERO) , vFireDir(ZERO) , vFirePos(ZERO) , maxSpeed(0) , normalSpeed(0) , minSpeed(0) , stance(STANCE_NULL) , isAiming(false) , isFiring(false) , isMoving(false) , linkedVehicleEntityId(0) , lean(0.0f) , slopeAngle(0.0f) , stanceSize(Vec3_Zero, Vec3_Zero) , colliderSize(Vec3_Zero, Vec3_Zero) { } IEntity* GetLinkedVehicleEntity() const { assert(gEnv && gEnv->pEntitySystem); return linkedVehicleEntityId ? gEnv->pEntitySystem->GetEntity(linkedVehicleEntityId) : NULL; } }; struct SAIWeaponInfo { SAIWeaponInfo() : lastShotTime((int64)0) , ammoCount(0) , clipSize(0) , outOfAmmo(false) , shotIsDone(false) , canMelee(false) , hasLightAccessory(false) , hasLaserAccessory(false) , isReloading(false) , isFiring(false) { } CTimeValue lastShotTime; int ammoCount; int clipSize; bool canMelee : 1; bool outOfAmmo : 1; bool lowAmmo : 1; bool shotIsDone : 1; bool hasLightAccessory : 1; bool hasLaserAccessory : 1; bool isReloading : 1; bool isFiring : 1; }; enum EAIAGInput { AIAG_SIGNAL, AIAG_ACTION, }; struct SAIBodyInfoQuery { SAIBodyInfoQuery(const Vec3& pos, const Vec3& trg, EStance _stance, float _lean = 0.0f, float _peekOver = 0.0f, bool _defaultPose = false) : stance(_stance) , lean(_lean) , peekOver(_peekOver) , defaultPose(_defaultPose) , position(pos) , target(trg) { } SAIBodyInfoQuery(EStance _stance, float _lean = 0.0f, float _peekOver = 0.0f, bool _defaultPose = false) : stance(_stance) , lean(_lean) , peekOver(_peekOver) , defaultPose(_defaultPose) , position(ZERO) , target(ZERO) { } SAIBodyInfoQuery() : stance(STANCE_NULL) , lean(0.0f) , peekOver(0.0f) , defaultPose(true) , position(ZERO) , target(ZERO) { } EStance stance; float lean; float peekOver; bool defaultPose; Vec3 position; Vec3 target; }; struct SCommunicationSound { SCommunicationSound() : playSoundControlId(INVALID_AUDIO_CONTROL_ID) , stopSoundControlId(INVALID_AUDIO_CONTROL_ID) { } SCommunicationSound(const Audio::TAudioControlID _playSoundControlId, const Audio::TAudioControlID _stopSoundControlId) : playSoundControlId(_playSoundControlId) , stopSoundControlId(_stopSoundControlId) { } Audio::TAudioControlID playSoundControlId; Audio::TAudioControlID stopSoundControlId; }; struct IAICommunicationHandler { enum ECommunicationHandlerEvent { SoundStarted = 0, SoundFinished, SoundCancelled, SoundFailed, VoiceStarted, VoiceFinished, VoiceCancelled, VoiceFailed, ActionStarted, ActionCancelled, ActionFailed, SignalStarted, SignalFinished, SignalCancelled, SignalFailed, }; enum EAnimationMethod { AnimationMethodSignal = 0, AnimationMethodAction, }; struct IEventListener { // virtual ~IEventListener(){} virtual void OnCommunicationHandlerEvent(ECommunicationHandlerEvent type, CommPlayID playID, EntityId actorID) = 0; // }; // virtual ~IAICommunicationHandler(){} virtual SCommunicationSound PlaySound(CommPlayID playID, const char* name, IEventListener* listener = 0) = 0; virtual void StopSound(const SCommunicationSound& soundToStop) = 0; virtual SCommunicationSound PlayVoice(CommPlayID playID, const char* name, ELipSyncMethod lipSyncMethod, IEventListener* listener = 0) = 0; virtual void StopVoice(const SCommunicationSound& soundToStop) = 0; virtual void SendDialogueRequest(CommPlayID playID, const char* name, IEventListener* listener = 0) = 0; virtual void PlayAnimation(CommPlayID playID, const char* name, EAnimationMethod method, IEventListener* listener = 0) = 0; virtual void StopAnimation(CommPlayID playID, const char* name, EAnimationMethod method) = 0; virtual bool IsInAGState(const char* name) = 0; virtual void ResetAnimationState() = 0; virtual bool IsPlayingAnimation() const = 0; virtual bool IsPlayingSound() const = 0; virtual void OnSoundTriggerFinishedToPlay(const Audio::TAudioControlID nTriggerID) = 0; // }; enum EWaypointNodeType { WNT_UNSET, WNT_WAYPOINT, WNT_HIDE, WNT_ENTRYEXIT, WNT_EXITONLY, WNT_HIDESECONDARY }; enum EWaypointLinkType { WLT_AUTO_PASS = 320, WLT_AUTO_IMPASS = -320, WLT_EDITOR_PASS = 321, WLT_EDITOR_IMPASS = -321, WLT_UNKNOWN_TYPE = 0 }; #endif // CRYINCLUDE_CRYCOMMON_IAGENT_H