3 const float TARGET_CONE_ANGLE_CHASE = 20;
4 const float TARGET_CONE_ANGLE_FIGHT = 30;
5 const float ORIENTATION_SYNC_THRESHOLD = 30;
7 const float SHOCK_TO_STUN_MULTIPLIER = 2.82;
10 protected int m_StanceVariation = 0;
11 protected int m_LastMindState = -1;
12 protected float m_LastMovementSpeed = -1;
14 protected bool m_KnuckleLand =
false;
15 protected float m_KnuckleOutTimer = 0;
17 protected int m_MindState = -1;
18 protected int m_OrientationLocal = -1;
19 protected int m_OrientationSynced = -1;
21 protected float m_MovementSpeed = -1;
35 protected bool m_FinisherInProgress =
false;
53 RegisterNetSyncVariableInt(
"m_MindState", -1, 4);
54 RegisterNetSyncVariableInt(
"m_OrientationSynced", 0, 359);
55 RegisterNetSyncVariableFloat(
"m_MovementSpeed", -1, 3);
56 RegisterNetSyncVariableBool(
"m_IsCrawling");
62 if ( !
GetGame().IsDedicatedServer() )
64 m_LastSoundVoiceAW = null;
73 m_OrientationTimer = 0;
81 DebugSound(
"[Infected @ " +
this +
"][OnVariablesSynchronized]");
84 if ( m_OrientationLocal != m_OrientationSynced )
86 m_OrientationLocal = m_OrientationSynced;
98 moveCommand.SetStanceVariation(m_StanceVariation);
151 return GetDayZInfectedType().GetHitComponentForAI();
157 return GetDayZInfectedType().GetDefaultHitComponent();
162 return m_DefaultHitPosition;
167 return GetSelectionPositionMS(pSelection);
173 return GetDayZInfectedType().GetSuitableFinisherHitComponents();
184 return m_OrientationSynced;
192 void CommandHandler(
float pDt,
int pCurrentCommandID,
bool pCurrentCommandFinished)
195 if ( ModCommandHandlerBefore(pDt, pCurrentCommandID, pCurrentCommandFinished) )
203 if ( HandleDeath(pCurrentCommandID) )
206 else if (!pCurrentCommandFinished)
213 HandleMove(pCurrentCommandID);
214 HandleOrientation(pDt,pCurrentCommandID);
217 if (pCurrentCommandFinished)
221 moveCommand.SetStanceVariation(m_StanceVariation);
227 if ( ModCommandHandlerInside(pDt, pCurrentCommandID, pCurrentCommandFinished) )
233 if ( HandleCrawlTransition(pCurrentCommandID) )
239 if ( HandleDamageHit(pCurrentCommandID) )
245 if ( inputController )
247 if ( HandleVault(pCurrentCommandID, inputController, pDt) )
252 if ( HandleMindStateChange(pCurrentCommandID, inputController, pDt) )
257 if ( FightLogic(pCurrentCommandID, inputController, pDt) )
264 if ( ModCommandHandlerAfter(pDt, pCurrentCommandID, pCurrentCommandFinished) )
300 PluginDayZInfectedDebug infectedDebug = PluginDayZInfectedDebug.Cast(
GetPluginManager().GetPluginByType(PluginDayZInfectedDebug));
302 infectedDebug.CommandHandler(
this);
314 if (
Math.
AbsFloat(m_LastMovementSpeed - m_MovementSpeed) >= 0.9 && m_LastMovementSpeed != m_MovementSpeed)
319 m_LastMovementSpeed = m_MovementSpeed;
329 m_OrientationTimer += pDt;
335 float angleSourceRad = m_OrientationSynced *
Math.
DEG2RAD;
338 float angleDiffRad =
Math.
Atan2(
Math.
Sin(angleTargetRad - angleSourceRad),
Math.
Cos(angleSourceRad - angleTargetRad));
342 if (m_OrientationTimer >= 2.0 || m_OrientationSynced == -1 ||
Math.
AbsInt(angleDiffRad) > ORIENTATION_SYNC_THRESHOLD)
344 m_OrientationTimer = 0.0;
346 if (m_OrientationSynced == -1 ||
Math.
AbsInt(angleDiffRad) > 5)
349 m_OrientationSynced = yaw;
360 float m_DamageHitDirection = 0;
365 if ( !IsAlive() || m_FinisherInProgress )
368 m_MovementSpeed = -1;
379 bool ret = EvaluateDeathAnimation(pSource,data.m_DamageZone,data.m_AmmoType,pAnimType,pAnimHitDir);
390 pAnimType = doPhxImpulse;
393 pAnimHitDir = ComputeHitDirectionAngle(pSource);
398 vector impulse = 80 * m_TransportHitVelocity;
399 impulse[1] = 80 * 1.5;
413 int m_ActiveVaultType = -1;
419 else if ( height <= 1.1 )
421 else if ( height <= 1.6 )
431 DayZInfectedCommandVault vaultCmd = GetCommand_Vault();
432 if ( vaultCmd && vaultCmd.WasLand() )
434 m_KnuckleOutTimer = 0;
435 m_KnuckleLand =
true;
439 m_KnuckleOutTimer += pDt;
440 if ( m_KnuckleOutTimer > 2.0 )
441 StartCommand_Vault(-1);
447 if ( pInputController.
IsVault() )
450 int vaultType = GetVaultType(vaultHeight);
451 m_KnuckleLand =
false;
452 StartCommand_Vault(vaultType);
469 if ( m_LastMindState != m_MindState )
471 switch ( m_MindState )
474 if ( moveCommand && !moveCommand.IsTurning() )
475 moveCommand.SetIdleState(0);
479 if ( moveCommand && !moveCommand.IsTurning() )
480 moveCommand.SetIdleState(1);
484 if ( moveCommand && !moveCommand.IsTurning() && (m_LastMindState <
DayZInfectedConstants.MINDSTATE_CHASE) )
485 moveCommand.SetIdleState(2);
489 m_LastMindState = m_MindState;
490 m_AttackCooldownTime = 0.0;
504 if ( !m_InfectedSoundEventHandler )
513 m_InfectedSoundEventHandler.Stop();
517 switch ( m_MindState )
532 m_InfectedSoundEventHandler.Stop();
536 DebugSound(
"[Infected @ " +
this +
"][MindState]" +
typename.EnumToString(
DayZInfectedConstants, m_MindState));
537 DebugSound(
"[Infected @ " +
this +
"][SoundEventID]" +
typename.EnumToString(
EInfectedSoundEventID, m_InfectedSoundEventHandler.GetCurrentStateEventID()));
545 if (!
GetGame().IsDedicatedServer())
556 AttenuateSoundIfNecessary(soundObject);
558 return PlaySound(soundObject, soundObjectBuilder);
567 AnimSoundVoiceEvent voice_event = GetCreatureAIType().GetSoundVoiceEvent(event_id);
568 if (voice_event != null)
571 if (m_InfectedSoundEventHandler)
573 m_InfectedSoundEventHandler.Stop();
574 DebugSound(
"[Infected @ " +
this +
"][SoundEvent] InfectedSoundEventHandler - stop all");
578 if (m_LastSoundVoiceAW != null)
580 DebugSound(
"[Infected @ " +
this +
"][AnimVoiceEvent] Stopping LastAW");
581 m_LastSoundVoiceAW.
Stop();
585 ProcessSoundVoiceEvent(voice_event, m_LastSoundVoiceAW);
593 if (!
GetGame().IsDedicatedServer())
596 if (NULL != objectBuilder)
600 AttenuateSoundIfNecessary(soundObject);
601 aw =
PlaySound(soundObject, objectBuilder);
607 if (sound_event.m_NoiseParams != NULL)
618 float m_AttackCooldownTime = 0;
629 return ChaseAttackLogic(pCurrentCommandID, pInputController, pDt);
633 return FightAttackLogic(pCurrentCommandID, pInputController, pDt);
638 DayZInfectedCommandAttack attackCommand = GetCommand_Attack();
639 if (attackCommand && attackCommand.WasHit())
641 if (m_ActualTarget != null)
646 bool playerInBlockStance =
false;
647 vector targetPos = m_ActualTarget.GetPosition();
648 vector hitPosWS = targetPos;
654 playerInBlockStance = playerTarget.GetMeleeFightLogic() && playerTarget.GetMeleeFightLogic().IsInBlock();
665 hitPosWS = m_ActualTarget.ModelToWorld(m_ActualTarget.GetDefaultHitPosition());
666 DamageSystem.CloseCombatDamageName(
this, m_ActualTarget, m_ActualTarget.GetHitComponentForAI(),
"MeleeZombie", hitPosWS);
671 hitPosWS = m_ActualTarget.ModelToWorld(m_ActualTarget.GetDefaultHitPosition());
672 DamageSystem.CloseCombatDamageName(
this, m_ActualTarget, m_ActualTarget.GetHitComponentForAI(),
"Dummy_Light", hitPosWS);
677 hitPosWS = m_ActualTarget.ModelToWorld(m_ActualTarget.GetDefaultHitPosition());
678 DamageSystem.CloseCombatDamageName(
this, m_ActualTarget, m_ActualTarget.GetHitComponentForAI(), m_ActualAttackType.
m_AmmoType, hitPosWS);
697 if ( pb && pb.GetCommand_Vehicle() )
702 if ( m_ActualTarget == NULL )
705 vector targetPos = m_ActualTarget.GetPosition();
706 if ( !CanAttackToPosition(targetPos) )
710 int pitch = GetAttackPitch(m_ActualTarget);
713 if (m_ActualAttackType)
717 if (m_ActualTarget != target)
723 StartCommand_Attack(m_ActualTarget, m_ActualAttackType.
m_Type, m_ActualAttackType.
m_Subtype);
724 m_AttackCooldownTime = m_ActualAttackType.
m_Cooldown;
738 if (pb && pb.GetCommand_Vehicle())
741 if (m_AttackCooldownTime > 0)
747 if (m_ActualTarget == null)
750 vector targetPos = m_ActualTarget.GetPosition();
752 int pitch = GetAttackPitch(m_ActualTarget);
754 if (!CanAttackToPosition(targetPos))
758 if (m_ActualAttackType)
768 StartCommand_Attack(m_ActualTarget, m_ActualAttackType.
m_Type, m_ActualAttackType.
m_Subtype);
769 m_AttackCooldownTime = m_ActualAttackType.
m_Cooldown;
780 attackRefPos = target.GetDefaultHitPosition();
784 attackRefPos = target.ModelToWorld(attackRefPos);
788 attackRefPos = target.GetPosition();
800 if ( headPosY > attackRefPos[1] )
811 int m_CrawlTransition = -1;
815 if ( m_CrawlTransition != -1 )
817 StartCommand_Crawl(m_CrawlTransition);
819 m_CrawlTransition = -1;
831 if ( pComponent ==
"LeftLeg" && GetHealth(pComponent,
"Health") == 0 )
833 else if ( pComponent ==
"RightLeg" && GetHealth(pComponent,
"Health") == 0 )
836 if ( pAnimType != -1 )
838 vector targetDirection = GetDirection();
841 targetDirection[1] = 0;
842 toSourceDirection[1] = 0;
847 float cosFi =
vector.
Dot(targetDirection, toSourceDirection);
852 return pAnimType != -1;
860 bool m_DamageHitToProcess =
false;
862 bool m_DamageHitHeavy =
false;
863 int m_DamageHitType = 0;
864 float m_ShockDamage = 0;
870 m_DamageHitToProcess =
false;
875 if ( m_DamageHitToProcess )
878 float stunChange = SHOCK_TO_STUN_MULTIPLIER * m_ShockDamage;
881 StartCommand_Hit(m_DamageHitHeavy, m_DamageHitType, m_DamageHitDirection);
883 m_DamageHitToProcess =
false;
885 m_HeavyHitOverride =
false;
895 int invertHitDir = 0;
898 pHeavyHit = ((
GetGame().
ConfigGetInt(
"cfgAmmo " + pAmmoType +
" hitAnimation") > 0) || m_HeavyHitOverride);
906 if ( pComponent ==
"Torso" )
908 else if ( pComponent ==
"Head" )
914 pAnimHitDir = ComputeHitDirectionAngleEx(pSource, invertHitDir);
922 vector targetDirection = GetDirection();
925 targetDirection[1] = 0;
926 toSourceDirection[1] = 0;
931 float cosFi =
vector.
Dot(targetDirection, toSourceDirection);
932 vector cross = targetDirection * toSourceDirection;
936 dirAngle = -dirAngle;
943 vector targetDirection = GetDirection();
946 targetDirection[1] = 0;
947 toSourceDirection[1] = 0;
952 float cosFi =
vector.
Dot(targetDirection, toSourceDirection);
953 vector cross = targetDirection * toSourceDirection;
958 if ( invertHitDir > 0 )
962 dirAngle = -dirAngle;
974 super.EEHitBy(damageResult, damageType, source,
component, dmgZone, ammo, modelPos, speedCoef);
976 m_TransportHitRegistered =
false;
980 ZombieHitData data =
new ZombieHitData;
982 data.m_DamageZone = dmgZone;
983 data.m_AmmoType = ammo;
984 EvaluateDeathAnimationEx(source, data, m_DeathType, m_DamageHitDirection);
988 int crawlTransitionType = -1;
989 if ( EvaluateCrawlTransitionAnimation(source, dmgZone, ammo, crawlTransitionType) )
991 m_CrawlTransition = crawlTransitionType;
995 if ( EvaluateDamageHitAnimation(source, dmgZone, ammo, m_DamageHitHeavy, m_DamageHitType, m_DamageHitDirection) )
998 m_ShockDamage = damageResult.
GetDamage( dmgZone,
"Shock" );
999 m_DamageHitToProcess =
true;
1007 super.EEHitByRemote(damageType, source,
component, dmgZone, ammo, modelPos);
1031 RegisterTransportHit(transport);
1042 return super.CanReceiveAttachment(attachment, slotId);
1053 return m_FinisherInProgress;
1059 GetAIAgent().SetKeepInIdle(
true);
1062 switch (backstabType)
1065 m_DeathType = DayZInfectedDeathAnims.ANIM_DEATH_BACKSTAB;
1069 m_DeathType = DayZInfectedDeathAnims.ANIM_DEATH_NECKSTAB;
1073 m_DeathType = DayZInfectedDeathAnims.ANIM_DEATH_DEFAULT;
1077 m_FinisherInProgress =
true;
1085 return m_IsCrawling;
1092 GetAIAgent().SetKeepInIdle(
false);
1095 m_FinisherInProgress =
false;
1113 vector parentTransMat[4];
1125 parentTransMat[0] = rotMatrix[0];
1126 parentTransMat[1] = rotMatrix[1];
1127 parentTransMat[2] = rotMatrix[2];
1128 parentTransMat[3] = closeBonePosWS;
1131 arrow.GetTransform(arrowTransMat);
1135 arrow.SetTransform(arrowTransMat);
RepairCarChassisActionReciveData m_DamageZone
protected ref ArrowManagerBase m_ArrowManager
proto native int GetBoneIndexByName(string pBoneName)
returns bone index for a name (-1 if pBoneName doesn't exist)
DayZInfectedAttackGroupType
protected ref array< Object > m_AllTargetObjects
All potential targets found during most recent TargetSelection.
protected ref array< typename > m_TargetableObjects
Typenames of all directly/preferred targetable objects (1st Pass + 2nd Pass)
private void DayZPlayerUtils()
cannot be instantiated
void InfectedSoundEventHandler(ZombieBase pInfected)
class BoxCollidingParams component
ComponentInfo for BoxCollidingResult.
PluginManager GetPluginManager()
Returns registred plugin by class type, better is to use global funtion GetPlugin(typename plugin_typ...
class SoundObjectBuilder SoundObject(SoundParams soundParams)
class JsonUndergroundAreaTriggerData GetPosition
class ZombieBase extends DayZInfected m_Component
an extendable data container
proto native int ConfigGetInt(string path)
Get int value from config on path.
proto native NoiseSystem GetNoiseSystem()
static ref TStringArray ARRAY_STRING
protected void DebugSound(string s)
sound debug messages
int GetVaultType(float height)
override array< string > GetSuitableFinisherHitComponents()
returns suitable hit components for finisher attacks; DEPRECATED
bool EvaluateCrawlTransitionAnimation(EntityAI pSource, string pComponent, string pAmmoType, out int pAnimType)
protected ref ArrowManagerBase m_ArrowManager
bool FightAttackLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
bool ModCommandHandlerInside(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
override string GetHitComponentForAI()
returns hit component for attacking AI
bool HandleDeath(int pCurrentCommandID)
protected void HandleSoundEvents()
bool HandleVault(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
int GetAttackPitch(EntityAI target)
protected vector SetDefaultHitPosition(string pSelection)
bool ChaseAttackLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
override ArrowManagerBase GetArrowManager()
void CommandHandler(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
override string GetDefaultHitComponent()
returns default hit component (fallback)
bool HandleDamageHit(int pCurrentCommandID)
override bool CanBeBackstabbed()
float ComputeHitDirectionAngleEx(EntityAI pSource, int invertHitDir=0)
void HandleMove(int pCurrentCommandID)
bool EvaluateDamageHitAnimation(EntityAI pSource, string pComponent, string pAmmoType, out bool pHeavyHit, out int pAnimType, out float pAnimHitDir)
selects animation type and direction based on damage system data
bool EvaluateDeathAnimationEx(EntityAI pSource, ZombieHitData data, out int pAnimType, out float pAnimHitDir)
override vector GetDefaultHitPosition()
bool EvaluateDeathAnimation(EntityAI pSource, string pComponent, string pAmmoType, out int pAnimType, out float pAnimHitDir)
override void OnSoundVoiceEvent(int event_id, string event_user_string)
float ComputeHitDirectionAngle(EntityAI pSource)
override void SetBeingBackstabbed(int backstabType)
override bool IsHealthVisible()
protected vector m_DefaultHitPosition
protected ref array< Object > m_AllTargetObjects
override void AddArrow(Object arrow, int componentIndex, vector closeBonePosWS, vector closeBoneRotWS)
int GetOrientationSynced()
returns rounded zombie yaw for sync purposes
void OnRecoverFromDeath()
protected ref array< typename > m_TargetableObjects
override void EEHitByRemote(int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos)
bool FightLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
protected AbstractWave m_LastSoundVoiceAW
override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
void HandleOrientation(float pDt, int pCurrentCommandID)
override bool IsRefresherSignalingViable()
override void EOnInit(IEntity other, int extra)
bool IsCrawling()
returns true if crawling; 'DayZInfectedCommandCrawl' is only for the transition, after that it remain...
protected float m_OrientationTimer
override bool IsBeingBackstabbed()
returns true if backstab is in progress; used for suspending of AI targeting and other useful things ...
override bool CanBeSkinned()
override vector GetCenter()
AbstractWave ProcessVoiceFX(string pSoundSetName)
protected void ProcessSoundVoiceEvent(AnimSoundVoiceEvent sound_event, out AbstractWave aw)
override void OnVariablesSynchronized()
synced variable(s) handler
bool HandleCrawlTransition(int pCurrentCommandID)
bool ModCommandHandlerBefore(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
bool HandleMindStateChange(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
override protected void EOnContact(IEntity other, Contact extra)
override AnimBootsType GetBootsType()
override bool IsManagingArrows()
bool ModCommandHandlerAfter(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
override bool CanReceiveAttachment(EntityAI attachment, int slotId)
protected bool m_IsCrawling
override bool IsZombieMilitary()
protected ref InfectedSoundEventHandler m_InfectedSoundEventHandler
void CommandHandlerDebug(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
override int GetMeleeTargetType()
proto void AddNoise(EntityAI source_entity, NoiseParams noise_params, float external_strenght_multiplier=1.0)
proto native void UpdateEnvSoundControllers(vector position)
SoundObject BuildSoundObject()
proto native bool IsValid()
proto native float GetDamage(string zoneName, string healthType)
Base native class for all motorized wheeled vehicles.
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
static proto native float Distance(vector v1, vector v2)
Returns the distance between tips of two 3D vectors.
proto float Normalize()
Normalizes vector. Returns length.
static proto native float DistanceSq(vector v1, vector v2)
Returns the square distance between tips of two 3D vectors.
static float Dot(vector v1, vector v2)
Returns Dot product of vector v1 and vector v2.
string GetDefaultHitPositionComponent()
proto native CGame GetGame()
const float AI_ATTACKSPEED
const float AI_MAX_BLOCKABLE_ANGLE
EntityEvent
Entity events for event-mask, or throwing event from code.
static proto float AngleFromPosition(vector origin, vector originDir, vector target)
Angle that a target is from the direction of an origin.
static proto void MatrixOrthogonalize4(vector mat[4])
Orthogonalizes matrix.
static proto void MatrixInvMultiply4(vector mat0[4], vector mat1[4], out vector res[4])
Invert-transforms matrix.
static proto void YawPitchRollMatrix(vector ang, out vector mat[3])
Creates rotation matrix from angles.
static proto float Acos(float c)
Returns angle in radians from cosinus.
static proto float Cos(float angle)
Returns cosinus of angle in radians.
static proto int RandomInt(int min, int max)
Returns a random int number between and min [inclusive] and max [exclusive].
static proto float Round(float f)
Returns mathematical round of value.
static proto float Atan2(float y, float x)
Returns angle in radians from tangent.
static int RandomIntInclusive(int min, int max)
Returns a random int number between and min [inclusive] and max [inclusive].
static proto float AbsFloat(float f)
Returns absolute value.
static proto float NormalizeAngle(float ang)
Normalizes the angle (0...360)
static const float RAD2DEG
static const float DEG2RAD
static proto float Sin(float angle)
Returns sinus of angle in radians.
static proto int AbsInt(int i)
Returns absolute value.
proto void dBodyApplyImpulse(notnull IEntity body, vector impulse)
Applies impuls on a rigidbody (origin)
proto native HumanCommandMove GetCommand_Move()
proto native HumanCommandMove StartCommand_Move()
returns current command ID
proto native HumanCommandDeathCallback StartCommand_Death(int pType, float pDirection, typename pCallbackClass)
--— Death --—
enum HumanMoveCommandID GetTransformWS(out vector pTm[4])
gets human transform in World Space
proto native HumanInputController GetInputController()
returns human input controller