DayZ Scripts
v1.21.156300 · Jun 20, 2023
 
Loading...
Searching...
No Matches
ZombieBase.c
Go to the documentation of this file.
2{
3 const float TARGET_CONE_ANGLE_CHASE = 20;
4 const float TARGET_CONE_ANGLE_FIGHT = 30;
5 const float ORIENTATION_SYNC_THRESHOLD = 30; //threshold for local heading/orientation sync
6
7 const float SHOCK_TO_STUN_MULTIPLIER = 2.82;
8
10 protected int m_StanceVariation = 0;
11 protected int m_LastMindState = -1;
12 protected float m_LastMovementSpeed = -1;
13
14 protected bool m_KnuckleLand = false;
15 protected float m_KnuckleOutTimer = 0;
16
17 protected int m_MindState = -1;
18 protected int m_OrientationLocal = -1; //local 'companion' value for sync checking
19 protected int m_OrientationSynced = -1;
20 protected float m_OrientationTimer;
21 protected float m_MovementSpeed = -1;
22
24
27
30
31 //static ref map<int,ref array<string>> m_FinisherSelectionMap; //! which selections in the FireGeometry trigger which finisher on hit (when applicable)
32
33 protected bool m_IsCrawling; //'DayZInfectedCommandCrawl' is transition to crawl only, 'DayZInfectedCommandMove' used after that, hence this VARIABLE_WET
34
35 protected bool m_FinisherInProgress = false; //is this object being backstabbed?
36
38
39
40
41 //-------------------------------------------------------------
43 {
44 Init();
45 }
46
47 void Init()
48 {
49 SetEventMask(EntityEvent.INIT);
50
51 m_IsCrawling = false;
52
53 RegisterNetSyncVariableInt("m_MindState", -1, 4);
54 RegisterNetSyncVariableInt("m_OrientationSynced", 0, 359);
55 RegisterNetSyncVariableFloat("m_MovementSpeed", -1, 3);
56 RegisterNetSyncVariableBool("m_IsCrawling");
57
59 m_DefaultHitPosition = SetDefaultHitPosition(GetDayZInfectedType().GetDefaultHitPositionComponent());
60
62 if ( !GetGame().IsDedicatedServer() )
63 {
64 m_LastSoundVoiceAW = null;
65 m_InfectedSoundEventHandler = new InfectedSoundEventHandler(this);
66 }
67
72
73 m_OrientationTimer = 0;
74
76 }
77
80 {
81 DebugSound("[Infected @ " + this + "][OnVariablesSynchronized]");
82 HandleSoundEvents();
83
84 if ( m_OrientationLocal != m_OrientationSynced )
85 {
86 m_OrientationLocal = m_OrientationSynced;
87 }
88 }
89
90 //-------------------------------------------------------------
91 override void EOnInit(IEntity other, int extra)
92 {
93 if ( !GetGame().IsMultiplayer() || GetGame().IsServer() )
94 {
95 m_StanceVariation = Math.RandomInt(0, 4);
96
98 moveCommand.SetStanceVariation(m_StanceVariation);
99 }
100 }
101
102 override bool IsZombie()
103 {
104 return true;
105 }
106
107 override bool IsDanger()
108 {
109 return true;
110 }
111
112 override bool IsZombieMilitary()
113 {
114 return false;
115 }
116
117 bool IsMale()
118 {
119 return true;
120 }
121
122 override bool CanBeBackstabbed()
123 {
124 return true;
125 }
126
127 //-------------------------------------------------------------
129 {
130 return AnimBootsType.Boots;
131 }
132
133 override bool CanBeSkinned()
134 {
135 return false;
136 }
137 //-------------------------------------------------------------
138 override bool IsHealthVisible()
139 {
140 return false;
141 }
142 //-------------------------------------------------------------
144 {
145 return false;
146 }
147
149 override string GetHitComponentForAI()
150 {
151 return GetDayZInfectedType().GetHitComponentForAI();
152 }
153
155 override string GetDefaultHitComponent()
156 {
157 return GetDayZInfectedType().GetDefaultHitComponent();
158 }
159
161 {
162 return m_DefaultHitPosition;
163 }
164
165 protected vector SetDefaultHitPosition(string pSelection)
166 {
167 return GetSelectionPositionMS(pSelection);
168 }
169
172 {
173 return GetDayZInfectedType().GetSuitableFinisherHitComponents();
174 }
175
177 {
178 return m_MindState;
179 }
180
183 {
184 return m_OrientationSynced;
185 }
186
187 //-------------------------------------------------------------
191
192 void CommandHandler(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
193 {
195 if ( ModCommandHandlerBefore(pDt, pCurrentCommandID, pCurrentCommandFinished) )
196 {
197 return;
198 }
199
201 if ( pCurrentCommandID != DayZInfectedConstants.COMMANDID_DEATH )
202 {
203 if ( HandleDeath(pCurrentCommandID) )
204 return;
205 }
206 else if (!pCurrentCommandFinished)
207 {
208 return;
209 }
210
211
213 HandleMove(pCurrentCommandID);
214 HandleOrientation(pDt,pCurrentCommandID);
215
217 if (pCurrentCommandFinished)
218 {
221 moveCommand.SetStanceVariation(m_StanceVariation);
222
223 return;
224 }
225
227 if ( ModCommandHandlerInside(pDt, pCurrentCommandID, pCurrentCommandFinished) )
228 {
229 return;
230 }
231
233 if ( HandleCrawlTransition(pCurrentCommandID) )
234 {
235 return;
236 }
237
239 if ( HandleDamageHit(pCurrentCommandID) )
240 {
241 return;
242 }
243
245 if ( inputController )
246 {
247 if ( HandleVault(pCurrentCommandID, inputController, pDt) )
248 {
249 return;
250 }
251
252 if ( HandleMindStateChange(pCurrentCommandID, inputController, pDt) )
253 {
254 return;
255 }
256
257 if ( FightLogic(pCurrentCommandID, inputController, pDt) )
258 {
259 return;
260 }
261 }
262
264 if ( ModCommandHandlerAfter(pDt, pCurrentCommandID, pCurrentCommandFinished) )
265 {
266 return;
267 }
268 }
269
270 //-------------------------------------------------------------
274 // these functions are for modded overide in script command mods
275
276 bool ModCommandHandlerBefore(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
277 {
278 return false;
279 }
280
281 bool ModCommandHandlerInside(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
282 {
283 return false;
284 }
285
286 bool ModCommandHandlerAfter(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
287 {
288 return false;
289 }
290
291 //-------------------------------------------------------------
295
296 void CommandHandlerDebug(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
297 {
298 if ( GetPluginManager() )
299 {
300 PluginDayZInfectedDebug infectedDebug = PluginDayZInfectedDebug.Cast(GetPluginManager().GetPluginByType(PluginDayZInfectedDebug));
301 if ( infectedDebug )
302 infectedDebug.CommandHandler(this);
303 }
304 }
305 //-------------------------------------------------------------
309
310 void HandleMove(int pCurrentCommandID)
311 {
313 m_MovementSpeed = ic.GetMovementSpeed();
314 if (Math.AbsFloat(m_LastMovementSpeed - m_MovementSpeed) >= 0.9 && m_LastMovementSpeed != m_MovementSpeed)
315 {
316 SetSynchDirty();
317 }
318
319 m_LastMovementSpeed = m_MovementSpeed;
320 }
321
322 //-------------------------------------------------------------
326
327 void HandleOrientation(float pDt, int pCurrentCommandID)
328 {
329 m_OrientationTimer += pDt;
330
331 int yaw = Math.Round(GetOrientation()[0]);
332 yaw = Math.NormalizeAngle(yaw);
333
334 //atan2(sin(x-y), cos(x-y))
335 float angleSourceRad = m_OrientationSynced * Math.DEG2RAD;
336 float angleTargetRad = yaw * Math.DEG2RAD;
337
338 float angleDiffRad = Math.Atan2(Math.Sin(angleTargetRad - angleSourceRad), Math.Cos(angleSourceRad - angleTargetRad));
339 angleDiffRad *= Math.RAD2DEG;
340 angleDiffRad = Math.Round(angleDiffRad);
341
342 if (m_OrientationTimer >= 2.0 || m_OrientationSynced == -1 || Math.AbsInt(angleDiffRad) > ORIENTATION_SYNC_THRESHOLD)
343 {
344 m_OrientationTimer = 0.0;
345
346 if (m_OrientationSynced == -1 || Math.AbsInt(angleDiffRad) > 5)
347 {
348 //Print("DbgSyncOrientation | HandleMove | original: " + m_OrientationSynced + " | target: " + yaw + " | diff: " + angleDiffRad);
349 m_OrientationSynced = yaw;
350 SetSynchDirty();
351 }
352 }
353 }
354
355 //-------------------------------------------------------------
359
360 float m_DamageHitDirection = 0;
361 int m_DeathType = 0;
362
363 bool HandleDeath(int pCurrentCommandID)
364 {
365 if ( !IsAlive() || m_FinisherInProgress )
366 {
367 StartCommand_Death(m_DeathType, m_DamageHitDirection);
368 m_MovementSpeed = -1;
369 m_MindState = -1;
370 SetSynchDirty();
371 return true;
372 }
373
374 return false;
375 }
376
377 bool EvaluateDeathAnimationEx(EntityAI pSource, ZombieHitData data, out int pAnimType, out float pAnimHitDir)
378 {
379 bool ret = EvaluateDeathAnimation(pSource,data.m_DamageZone,data.m_AmmoType,pAnimType,pAnimHitDir);
380
381 return ret;
382 }
383
384 bool EvaluateDeathAnimation(EntityAI pSource, string pComponent, string pAmmoType, out int pAnimType, out float pAnimHitDir)
385 {
387 bool doPhxImpulse = GetGame().ConfigGetInt("cfgAmmo " + pAmmoType + " doPhxImpulse") > 0;
388
390 pAnimType = doPhxImpulse;
391
393 pAnimHitDir = ComputeHitDirectionAngle(pSource);
394
396 if ( doPhxImpulse )
397 {
398 vector impulse = 80 * m_TransportHitVelocity;
399 impulse[1] = 80 * 1.5;
400 //Print("Impulse: " + impulse.ToString());
401
402 dBodyApplyImpulse(this, impulse);
403 }
404
405 return true;
406 }
407
408 //-------------------------------------------------------------
412
413 int m_ActiveVaultType = -1;
414
415 int GetVaultType(float height)
416 {
417 if ( height <= 0.6 )
418 return 0;
419 else if ( height <= 1.1 )
420 return 1;
421 else if ( height <= 1.6 )
422 return 2;
423 else
424 return 3;
425 }
426
427 bool HandleVault(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
428 {
429 if ( pCurrentCommandID == DayZInfectedConstants.COMMANDID_VAULT )
430 {
431 DayZInfectedCommandVault vaultCmd = GetCommand_Vault();
432 if ( vaultCmd && vaultCmd.WasLand() )
433 {
434 m_KnuckleOutTimer = 0;
435 m_KnuckleLand = true;
436 }
437 if ( m_KnuckleLand )
438 {
439 m_KnuckleOutTimer += pDt;
440 if ( m_KnuckleOutTimer > 2.0 )
441 StartCommand_Vault(-1);
442 }
443
444 return true;
445 }
446
447 if ( pInputController.IsVault() )
448 {
449 float vaultHeight = pInputController.GetVaultHeight();
450 int vaultType = GetVaultType(vaultHeight);
451 m_KnuckleLand = false;
452 StartCommand_Vault(vaultType);
453 return true;
454 }
455
456 return false;
457 }
458
459 //-------------------------------------------------------------
463
464 bool HandleMindStateChange(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
465 {
467
468 m_MindState = pInputController.GetMindState();
469 if ( m_LastMindState != m_MindState )
470 {
471 switch ( m_MindState )
472 {
473 case DayZInfectedConstants.MINDSTATE_CALM:
474 if ( moveCommand && !moveCommand.IsTurning() )
475 moveCommand.SetIdleState(0);
476 break;
477
478 case DayZInfectedConstants.MINDSTATE_DISTURBED:
479 if ( moveCommand && !moveCommand.IsTurning() )
480 moveCommand.SetIdleState(1);
481 break;
482
483 case DayZInfectedConstants.MINDSTATE_CHASE:
484 if ( moveCommand && !moveCommand.IsTurning() && (m_LastMindState < DayZInfectedConstants.MINDSTATE_CHASE) )
485 moveCommand.SetIdleState(2);
486 break;
487 }
488
489 m_LastMindState = m_MindState;
490 m_AttackCooldownTime = 0.0;
491 SetSynchDirty();
492 }
493 return false;
494 }
495
496 //-------------------------------------------------------------
500
501 protected void HandleSoundEvents()
502 {
504 if ( !m_InfectedSoundEventHandler )
505 {
506 return;
507 }
508
510 if ( !IsAlive() )
511 {
513 m_InfectedSoundEventHandler.Stop();
514 return;
515 }
516
517 switch ( m_MindState )
518 {
519 case DayZInfectedConstants.MINDSTATE_CALM:
520 m_InfectedSoundEventHandler.PlayRequest(EInfectedSoundEventID.MINDSTATE_CALM_MOVE);
521 break;
522 case DayZInfectedConstants.MINDSTATE_ALERTED:
523 m_InfectedSoundEventHandler.PlayRequest(EInfectedSoundEventID.MINDSTATE_ALERTED_MOVE);
524 break;
525 case DayZInfectedConstants.MINDSTATE_DISTURBED:
526 m_InfectedSoundEventHandler.PlayRequest(EInfectedSoundEventID.MINDSTATE_DISTURBED_IDLE);
527 break
528 case DayZInfectedConstants.MINDSTATE_CHASE:
529 m_InfectedSoundEventHandler.PlayRequest(EInfectedSoundEventID.MINDSTATE_CHASE_MOVE);
530 break;
531 default:
532 m_InfectedSoundEventHandler.Stop();
533 break;
534 }
535
536 DebugSound("[Infected @ " + this + "][MindState]" + typename.EnumToString(DayZInfectedConstants, m_MindState));
537 DebugSound("[Infected @ " + this + "][SoundEventID]" + typename.EnumToString(EInfectedSoundEventID, m_InfectedSoundEventHandler.GetCurrentStateEventID()));
538 }
539
540 AbstractWave ProcessVoiceFX(string pSoundSetName)
541 {
542 SoundParams soundParams;
543 SoundObjectBuilder soundObjectBuilder;
544 SoundObject soundObject;
545 if (!GetGame().IsDedicatedServer())
546 {
547 soundParams = new SoundParams( pSoundSetName );
548 if ( !soundParams.IsValid() )
549 {
550 //SoundError("Invalid sound set.");
551 return null;
552 }
553
554 soundObjectBuilder = new SoundObjectBuilder( soundParams );
555 soundObject = soundObjectBuilder.BuildSoundObject();
556 AttenuateSoundIfNecessary(soundObject);
557
558 return PlaySound(soundObject, soundObjectBuilder);
559 }
560
561 return null;
562 }
563
564 override void OnSoundVoiceEvent(int event_id, string event_user_string)
565 {
566 //super.OnSoundVoiceEvent(event_id, event_user_string);
567 AnimSoundVoiceEvent voice_event = GetCreatureAIType().GetSoundVoiceEvent(event_id);
568 if (voice_event != null)
569 {
571 if (m_InfectedSoundEventHandler) // && m_InfectedSoundEventHandler.IsPlaying())
572 {
573 m_InfectedSoundEventHandler.Stop();
574 DebugSound("[Infected @ " + this + "][SoundEvent] InfectedSoundEventHandler - stop all");
575 }
576
578 if (m_LastSoundVoiceAW != null)
579 {
580 DebugSound("[Infected @ " + this + "][AnimVoiceEvent] Stopping LastAW");
581 m_LastSoundVoiceAW.Stop();
582 }
583
585 ProcessSoundVoiceEvent(voice_event, m_LastSoundVoiceAW);
586
587 HandleSoundEvents();
588 }
589 }
590
591 protected void ProcessSoundVoiceEvent(AnimSoundVoiceEvent sound_event, out AbstractWave aw)
592 {
593 if (!GetGame().IsDedicatedServer())
594 {
595 SoundObjectBuilder objectBuilder = sound_event.GetSoundBuilder();
596 if (NULL != objectBuilder)
597 {
598 objectBuilder.UpdateEnvSoundControllers(GetPosition());
599 SoundObject soundObject = objectBuilder.BuildSoundObject();
600 AttenuateSoundIfNecessary(soundObject);
601 aw = PlaySound(soundObject, objectBuilder);
602 }
603 }
604
605 if (GetGame().IsServer())
606 {
607 if (sound_event.m_NoiseParams != NULL)
608 GetGame().GetNoiseSystem().AddNoise(this, sound_event.m_NoiseParams);
609 }
610 }
611
612 //-------------------------------------------------------------
616
617 EntityAI m_ActualTarget = null;
618 float m_AttackCooldownTime = 0;
619 DayZInfectedAttackType m_ActualAttackType = null;
620
621 bool FightLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
622 {
623 if (pCurrentCommandID == DayZInfectedConstants.COMMANDID_MOVE)
624 {
625 // we attack only in chase & fight state
626 int mindState = pInputController.GetMindState();
627 if (mindState == DayZInfectedConstants.MINDSTATE_CHASE)
628 {
629 return ChaseAttackLogic(pCurrentCommandID, pInputController, pDt);
630 }
631 else if (mindState == DayZInfectedConstants.MINDSTATE_FIGHT)
632 {
633 return FightAttackLogic(pCurrentCommandID, pInputController, pDt);
634 }
635 }
636 else if (pCurrentCommandID == DayZInfectedConstants.COMMANDID_ATTACK)
637 {
638 DayZInfectedCommandAttack attackCommand = GetCommand_Attack();
639 if (attackCommand && attackCommand.WasHit())
640 {
641 if (m_ActualTarget != null)
642 {
643 if (m_ActualTarget.GetMeleeTargetType() == EMeleeTargetType.NONALIGNABLE)
644 return false;
645
646 bool playerInBlockStance = false;
647 vector targetPos = m_ActualTarget.GetPosition();
648 vector hitPosWS = targetPos;
649 vector zombiePos = GetPosition();
650
651 PlayerBase playerTarget = PlayerBase.Cast(m_ActualTarget);
652 if (playerTarget)
653 {
654 playerInBlockStance = playerTarget.GetMeleeFightLogic() && playerTarget.GetMeleeFightLogic().IsInBlock();
655 }
656
657 if (vector.DistanceSq(targetPos, zombiePos) <= m_ActualAttackType.m_Distance * m_ActualAttackType.m_Distance)
658 {
660 if (playerInBlockStance && (Math.RAD2DEG * Math.AbsFloat(Math3D.AngleFromPosition(targetPos, MiscGameplayFunctions.GetHeadingVector(playerTarget), zombiePos))) <= GameConstants.AI_MAX_BLOCKABLE_ANGLE)
661 {
663 if (m_ActualAttackType.m_IsHeavy == 1)
664 {
665 hitPosWS = m_ActualTarget.ModelToWorld(m_ActualTarget.GetDefaultHitPosition());
666 DamageSystem.CloseCombatDamageName(this, m_ActualTarget, m_ActualTarget.GetHitComponentForAI(), "MeleeZombie", hitPosWS);
667 }
668 else
669 {
671 hitPosWS = m_ActualTarget.ModelToWorld(m_ActualTarget.GetDefaultHitPosition());
672 DamageSystem.CloseCombatDamageName(this, m_ActualTarget, m_ActualTarget.GetHitComponentForAI(), "Dummy_Light", hitPosWS);
673 }
674 }
675 else
676 {
677 hitPosWS = m_ActualTarget.ModelToWorld(m_ActualTarget.GetDefaultHitPosition());
678 DamageSystem.CloseCombatDamageName(this, m_ActualTarget, m_ActualTarget.GetHitComponentForAI(), m_ActualAttackType.m_AmmoType, hitPosWS);
679 }
680 }
681 }
682 }
683
684 return true;
685 }
686
687 return false;
688 }
689
690 bool ChaseAttackLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
691 {
692 // always update target - it can be destroyed
693 m_ActualTarget = pInputController.GetTargetEntity();
694
696 PlayerBase pb = PlayerBase.Cast(m_ActualTarget);
697 if ( pb && pb.GetCommand_Vehicle() )
698 {
699 return false;
700 }
701
702 if ( m_ActualTarget == NULL )
703 return false;
704
705 vector targetPos = m_ActualTarget.GetPosition();
706 if ( !CanAttackToPosition(targetPos) )
707 return false;
708
709 float targetDist = vector.Distance(targetPos, this.GetPosition());
710 int pitch = GetAttackPitch(m_ActualTarget);
711
712 m_ActualAttackType = GetDayZInfectedType().ChooseAttack(DayZInfectedAttackGroupType.CHASE, targetDist, pitch);
713 if (m_ActualAttackType)
714 {
715 Object target = DayZPlayerUtils.GetMeleeTarget(this.GetPosition(), this.GetDirection(), TARGET_CONE_ANGLE_CHASE, m_ActualAttackType.m_Distance, -1.0, 2.0, this, m_TargetableObjects, m_AllTargetObjects);
717 if (m_ActualTarget != target)
718 {
719 m_AllTargetObjects.Clear();
720 return false;
721 }
722
723 StartCommand_Attack(m_ActualTarget, m_ActualAttackType.m_Type, m_ActualAttackType.m_Subtype);
724 m_AttackCooldownTime = m_ActualAttackType.m_Cooldown;
725 return true;
726 }
727
728 return false;
729 }
730
731 bool FightAttackLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
732 {
733 // always update target - it can be destroyed
734 m_ActualTarget = pInputController.GetTargetEntity();
735
737 PlayerBase pb = PlayerBase.Cast(m_ActualTarget);
738 if (pb && pb.GetCommand_Vehicle())
739 return false;
740
741 if (m_AttackCooldownTime > 0)
742 {
743 m_AttackCooldownTime -= pDt * GameConstants.AI_ATTACKSPEED;
744 return false;
745 }
746
747 if (m_ActualTarget == null)
748 return false;
749
750 vector targetPos = m_ActualTarget.GetPosition();
751 float targetDist = vector.Distance(targetPos, this.GetPosition());
752 int pitch = GetAttackPitch(m_ActualTarget);
753
754 if (!CanAttackToPosition(targetPos))
755 return false;
756
757 m_ActualAttackType = GetDayZInfectedType().ChooseAttack(DayZInfectedAttackGroupType.FIGHT, targetDist, pitch);
758 if (m_ActualAttackType)
759 {
760 Object target = DayZPlayerUtils.GetMeleeTarget(this.GetPosition(), this.GetDirection(), TARGET_CONE_ANGLE_FIGHT, m_ActualAttackType.m_Distance, -1.0, 2.0, this, m_TargetableObjects, m_AllTargetObjects);
762 if (m_AllTargetObjects.Count() > 0 && m_AllTargetObjects[0] != m_ActualTarget)
763 {
764 m_AllTargetObjects.Clear();
765 return false;
766 }
767
768 StartCommand_Attack(m_ActualTarget, m_ActualAttackType.m_Type, m_ActualAttackType.m_Subtype);
769 m_AttackCooldownTime = m_ActualAttackType.m_Cooldown;
770 return true;
771 }
772
773 return false;
774 }
775
777 {
778 vector attackRefPos;
779
780 attackRefPos = target.GetDefaultHitPosition();
782 if ( attackRefPos != vector.Zero )
783 {
784 attackRefPos = target.ModelToWorld(attackRefPos);
785 }
786 else
787 {
788 attackRefPos = target.GetPosition();
789 }
790
791 // Now we have only erect stance, we need to get head position later too
792 float headPosY = GetPosition()[1];
793 headPosY += 1.8;
794
795 float diff = Math.AbsFloat(attackRefPos[1] - headPosY);
796
797 if ( diff < 0.3 )
798 return 0;
799
800 if ( headPosY > attackRefPos[1] )
801 return -1;
802 else
803 return 1;
804 }
805
806 //-------------------------------------------------------------
810
811 int m_CrawlTransition = -1;
812
813 bool HandleCrawlTransition(int pCurrentCommandID)
814 {
815 if ( m_CrawlTransition != -1 )
816 {
817 StartCommand_Crawl(m_CrawlTransition);
818
819 m_CrawlTransition = -1;
820 m_IsCrawling = true;
821 SetSynchDirty();
822 return true;
823 }
824
825 return pCurrentCommandID == DayZInfectedConstants.COMMANDID_CRAWL;
826 }
827
828 bool EvaluateCrawlTransitionAnimation(EntityAI pSource, string pComponent, string pAmmoType, out int pAnimType)
829 {
830 pAnimType = -1;
831 if ( pComponent == "LeftLeg" && GetHealth(pComponent, "Health") == 0 )
832 pAnimType = 0;
833 else if ( pComponent == "RightLeg" && GetHealth(pComponent, "Health") == 0 )
834 pAnimType = 2;
835
836 if ( pAnimType != -1 )
837 {
838 vector targetDirection = GetDirection();
839 vector toSourceDirection = (pSource.GetPosition() - GetPosition());
840
841 targetDirection[1] = 0;
842 toSourceDirection[1] = 0;
843
844 targetDirection.Normalize();
845 toSourceDirection.Normalize();
846
847 float cosFi = vector.Dot(targetDirection, toSourceDirection);
848 if ( cosFi >= 0 ) // front
849 pAnimType++;
850 }
851
852 return pAnimType != -1;
853 }
854
855 //-------------------------------------------------------------
859
860 bool m_DamageHitToProcess = false;
861
862 bool m_DamageHitHeavy = false;
863 int m_DamageHitType = 0;
864 float m_ShockDamage = 0;
865
866 bool HandleDamageHit(int pCurrentCommandID)
867 {
868 if ( pCurrentCommandID == DayZInfectedConstants.COMMANDID_HIT )
869 {
870 m_DamageHitToProcess = false;
871 m_ShockDamage = 0;
872 return true;
873 }
874
875 if ( m_DamageHitToProcess )
876 {
877 int randNum = Math.RandomIntInclusive(0, 100);
878 float stunChange = SHOCK_TO_STUN_MULTIPLIER * m_ShockDamage;
879
880 if ( m_DamageHitHeavy || randNum <= stunChange || ( m_MindState == DayZInfectedConstants.MINDSTATE_CALM || m_MindState == DayZInfectedConstants.MINDSTATE_DISTURBED ) )
881 StartCommand_Hit(m_DamageHitHeavy, m_DamageHitType, m_DamageHitDirection);
882
883 m_DamageHitToProcess = false;
884 m_ShockDamage = 0;
885 m_HeavyHitOverride = false;
886 return true;
887 }
888
889 return false;
890 }
891
893 bool EvaluateDamageHitAnimation(EntityAI pSource, string pComponent, string pAmmoType, out bool pHeavyHit, out int pAnimType, out float pAnimHitDir)
894 {
895 int invertHitDir = 0; //Used to flip the heavy hit animation direction
896
898 pHeavyHit = ((GetGame().ConfigGetInt("cfgAmmo " + pAmmoType + " hitAnimation") > 0) || m_HeavyHitOverride);
899 invertHitDir = GetGame().ConfigGetInt("cfgAmmo " + pAmmoType + " invertHitDir");
900
902 pAnimType = 0; // belly
903
904 if ( !pHeavyHit )
905 {
906 if ( pComponent == "Torso" ) // body
907 pAnimType = 1;
908 else if ( pComponent == "Head" ) // head
909 pAnimType = 2;
910 }
911
913 //pAnimHitDir = ComputeHitDirectionAngle(pSource);
914 pAnimHitDir = ComputeHitDirectionAngleEx(pSource, invertHitDir);
916 //m_ShockDamage = GetGame().ConfigGetFloat( "CfgAmmo " + pAmmoType + " DamageApplied " + "Shock " + "damage");
917 return true;
918 }
919
921 {
922 vector targetDirection = GetDirection();
923 vector toSourceDirection = (pSource.GetPosition() - GetPosition());
924
925 targetDirection[1] = 0;
926 toSourceDirection[1] = 0;
927
928 targetDirection.Normalize();
929 toSourceDirection.Normalize();
930
931 float cosFi = vector.Dot(targetDirection, toSourceDirection);
932 vector cross = targetDirection * toSourceDirection;
933
934 float dirAngle = Math.Acos(cosFi) * Math.RAD2DEG;
935 if ( cross[1] < 0 )
936 dirAngle = -dirAngle;
937
938 return dirAngle;
939 }
940
941 float ComputeHitDirectionAngleEx(EntityAI pSource, int invertHitDir = 0)
942 {
943 vector targetDirection = GetDirection();
944 vector toSourceDirection = (pSource.GetPosition() - GetPosition());
945
946 targetDirection[1] = 0;
947 toSourceDirection[1] = 0;
948
949 targetDirection.Normalize();
950 toSourceDirection.Normalize();
951
952 float cosFi = vector.Dot(targetDirection, toSourceDirection);
953 vector cross = targetDirection * toSourceDirection;
954
955 float dirAngle = Math.Acos(cosFi) * Math.RAD2DEG;
956
957 // We will invert direction of the hit
958 if ( invertHitDir > 0 )
959 dirAngle -= 180;
960
961 if ( cross[1] < 0 )
962 dirAngle = -dirAngle;
963
964 return dirAngle;
965 }
966
967 //-------------------------------------------------------------
971
972 override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
973 {
974 super.EEHitBy(damageResult, damageType, source, component, dmgZone, ammo, modelPos, speedCoef);
975
976 m_TransportHitRegistered = false;
977
978 if ( !IsAlive() )
979 {
980 ZombieHitData data = new ZombieHitData;
981 data.m_Component = component;
982 data.m_DamageZone = dmgZone;
983 data.m_AmmoType = ammo;
984 EvaluateDeathAnimationEx(source, data, m_DeathType, m_DamageHitDirection);
985 }
986 else
987 {
988 int crawlTransitionType = -1;
989 if ( EvaluateCrawlTransitionAnimation(source, dmgZone, ammo, crawlTransitionType) )
990 {
991 m_CrawlTransition = crawlTransitionType;
992 return;
993 }
994
995 if ( EvaluateDamageHitAnimation(source, dmgZone, ammo, m_DamageHitHeavy, m_DamageHitType, m_DamageHitDirection) )
996 {
997 if ( dmgZone )
998 m_ShockDamage = damageResult.GetDamage( dmgZone, "Shock" );
999 m_DamageHitToProcess = true;
1000 return;
1001 }
1002 }
1003 }
1004
1005 override void EEHitByRemote(int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos)
1006 {
1007 super.EEHitByRemote(damageType, source, component, dmgZone, ammo, modelPos);
1008 }
1009
1011 protected void DebugSound(string s)
1012 {
1013 //Print(s);
1014 }
1015
1016 //-------------------------------------------------------------
1020
1021 override protected void EOnContact(IEntity other, Contact extra)
1022 {
1023 if ( !IsAlive() )
1024 return;
1025
1026 Transport transport = Transport.Cast(other);
1027 if ( transport )
1028 {
1029 if ( GetGame().IsServer() )
1030 {
1031 RegisterTransportHit(transport);
1032 }
1033 }
1034 }
1035
1036 override bool CanReceiveAttachment(EntityAI attachment, int slotId)
1037 {
1038 if ( !IsAlive() )
1039 {
1040 return false;
1041 }
1042 return super.CanReceiveAttachment(attachment, slotId);
1043 }
1044
1046 {
1047 return GetBonePositionWS( GetBoneIndexByName( "spine3" ) );
1048 }
1049
1051 override bool IsBeingBackstabbed()
1052 {
1053 return m_FinisherInProgress;
1054 }
1055
1056 override void SetBeingBackstabbed(int backstabType)
1057 {
1058 // disable AI simulation
1059 GetAIAgent().SetKeepInIdle(true);
1060
1061 // select death animation
1062 switch (backstabType)
1063 {
1064 case EMeleeHitType.FINISHER_LIVERSTAB:
1065 m_DeathType = DayZInfectedDeathAnims.ANIM_DEATH_BACKSTAB;
1066 break;
1067
1068 case EMeleeHitType.FINISHER_NECKSTAB:
1069 m_DeathType = DayZInfectedDeathAnims.ANIM_DEATH_NECKSTAB;
1070 break;
1071
1072 default:
1073 m_DeathType = DayZInfectedDeathAnims.ANIM_DEATH_DEFAULT;
1074 }
1075
1076 // set flag - death command will be executed
1077 m_FinisherInProgress = true;
1078
1079 //Print("DbgZombies | DumbZombie on: " + GetGame().GetTime());
1080 }
1081
1084 {
1085 return m_IsCrawling;
1086 }
1087
1088 // called from command death when stealth attack wan't successful
1090 {
1091 // enable AI simulation again
1092 GetAIAgent().SetKeepInIdle(false);
1093
1094 // reset flag
1095 m_FinisherInProgress = false;
1096
1097 //Print("DbgZombies | DumbZombie off: " + GetGame().GetTime());
1098 }
1099
1100 override void AddArrow(Object arrow, int componentIndex, vector closeBonePosWS, vector closeBoneRotWS)
1101 {
1103 GetActionComponentNameList(componentIndex, CachedObjectsArrays.ARRAY_STRING, "fire");
1104
1105 int pivot = -1;
1106
1107
1108 for (int i = 0; i < CachedObjectsArrays.ARRAY_STRING.Count() && pivot == -1; i++)
1109 {
1111 }
1112
1113 vector parentTransMat[4];
1114 vector arrowTransMat[4];
1115
1116 if (pivot == -1)
1117 {
1118 GetTransformWS(parentTransMat);
1119 }
1120 else
1121 {
1122 vector rotMatrix[3];
1123 Math3D.YawPitchRollMatrix(closeBoneRotWS * Math.RAD2DEG,rotMatrix);
1124
1125 parentTransMat[0] = rotMatrix[0];
1126 parentTransMat[1] = rotMatrix[1];
1127 parentTransMat[2] = rotMatrix[2];
1128 parentTransMat[3] = closeBonePosWS;
1129 }
1130
1131 arrow.GetTransform(arrowTransMat);
1132 Math3D.MatrixInvMultiply4(parentTransMat, arrowTransMat, arrowTransMat);
1133 // orthogonalize matrix - parent might be skewed
1134 Math3D.MatrixOrthogonalize4(arrowTransMat);
1135 arrow.SetTransform(arrowTransMat);
1136
1137 AddChild(arrow, pivot);
1138 }
1139
1140 override bool IsManagingArrows()
1141 {
1142 return true;
1143 }
1144
1146 {
1147 return m_ArrowManager;
1148 }
1149}
1150
1152class ZombieHitData
1153{
1157}
RepairCarChassisActionReciveData m_DamageZone
protected ref ArrowManagerBase m_ArrowManager
Definition AnimalBase.c:24
vector GetOrientation()
AnimBootsType
proto native int GetBoneIndexByName(string pBoneName)
returns bone index for a name (-1 if pBoneName doesn't exist)
override Widget Init()
Definition DayZGame.c:122
DayZInfectedConstants
Definition DayZInfected.c:2
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
EMeleeTargetType
void PlaySound()
string m_AmmoType
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 void Stop()
proto native int ConfigGetInt(string path)
Get int value from config on path.
proto native NoiseSystem GetNoiseSystem()
static ref TStringArray ARRAY_STRING
proto native float GetMovementSpeed()
protected void DebugSound(string s)
sound debug messages
int GetVaultType(float height)
Definition ZombieBase.c:415
override array< string > GetSuitableFinisherHitComponents()
returns suitable hit components for finisher attacks; DEPRECATED
Definition ZombieBase.c:171
void Init()
Definition ZombieBase.c:47
bool EvaluateCrawlTransitionAnimation(EntityAI pSource, string pComponent, string pAmmoType, out int pAnimType)
Definition ZombieBase.c:828
protected ref ArrowManagerBase m_ArrowManager
Definition ZombieBase.c:37
bool FightAttackLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
Definition ZombieBase.c:731
bool ModCommandHandlerInside(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
Definition ZombieBase.c:281
override string GetHitComponentForAI()
returns hit component for attacking AI
Definition ZombieBase.c:149
bool HandleDeath(int pCurrentCommandID)
Definition ZombieBase.c:363
protected void HandleSoundEvents()
Definition ZombieBase.c:501
bool HandleVault(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
Definition ZombieBase.c:427
int GetAttackPitch(EntityAI target)
Definition ZombieBase.c:776
protected vector SetDefaultHitPosition(string pSelection)
Definition ZombieBase.c:165
bool IsMale()
Definition ZombieBase.c:117
bool ChaseAttackLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
Definition ZombieBase.c:690
override ArrowManagerBase GetArrowManager()
void CommandHandler(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
Definition ZombieBase.c:192
override bool IsZombie()
Definition ZombieBase.c:102
override string GetDefaultHitComponent()
returns default hit component (fallback)
Definition ZombieBase.c:155
bool HandleDamageHit(int pCurrentCommandID)
Definition ZombieBase.c:866
override bool CanBeBackstabbed()
Definition ZombieBase.c:122
float ComputeHitDirectionAngleEx(EntityAI pSource, int invertHitDir=0)
Definition ZombieBase.c:941
void HandleMove(int pCurrentCommandID)
Definition ZombieBase.c:310
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
Definition ZombieBase.c:893
bool EvaluateDeathAnimationEx(EntityAI pSource, ZombieHitData data, out int pAnimType, out float pAnimHitDir)
Definition ZombieBase.c:377
override vector GetDefaultHitPosition()
Definition ZombieBase.c:160
bool EvaluateDeathAnimation(EntityAI pSource, string pComponent, string pAmmoType, out int pAnimType, out float pAnimHitDir)
Definition ZombieBase.c:384
override void OnSoundVoiceEvent(int event_id, string event_user_string)
Definition ZombieBase.c:564
float ComputeHitDirectionAngle(EntityAI pSource)
Definition ZombieBase.c:920
override void SetBeingBackstabbed(int backstabType)
override bool IsHealthVisible()
Definition ZombieBase.c:138
protected vector m_DefaultHitPosition
Definition ZombieBase.c:23
protected ref array< Object > m_AllTargetObjects
Definition ZombieBase.c:28
override void AddArrow(Object arrow, int componentIndex, vector closeBonePosWS, vector closeBoneRotWS)
int GetOrientationSynced()
returns rounded zombie yaw for sync purposes
Definition ZombieBase.c:182
void OnRecoverFromDeath()
int GetMindStateSynced()
Definition ZombieBase.c:176
protected ref array< typename > m_TargetableObjects
Definition ZombieBase.c:29
override void EEHitByRemote(int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos)
override bool IsDanger()
Definition ZombieBase.c:107
bool FightLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
Definition ZombieBase.c:621
protected AbstractWave m_LastSoundVoiceAW
Definition ZombieBase.c:25
override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
Definition ZombieBase.c:972
void HandleOrientation(float pDt, int pCurrentCommandID)
Definition ZombieBase.c:327
override bool IsRefresherSignalingViable()
Definition ZombieBase.c:143
override void EOnInit(IEntity other, int extra)
Definition ZombieBase.c:91
bool IsCrawling()
returns true if crawling; 'DayZInfectedCommandCrawl' is only for the transition, after that it remain...
protected float m_OrientationTimer
Definition ZombieBase.c:20
override bool IsBeingBackstabbed()
returns true if backstab is in progress; used for suspending of AI targeting and other useful things ...
override bool CanBeSkinned()
Definition ZombieBase.c:133
override vector GetCenter()
AbstractWave ProcessVoiceFX(string pSoundSetName)
Definition ZombieBase.c:540
protected void ProcessSoundVoiceEvent(AnimSoundVoiceEvent sound_event, out AbstractWave aw)
Definition ZombieBase.c:591
override void OnVariablesSynchronized()
synced variable(s) handler
Definition ZombieBase.c:79
bool HandleCrawlTransition(int pCurrentCommandID)
Definition ZombieBase.c:813
bool ModCommandHandlerBefore(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
Definition ZombieBase.c:276
bool HandleMindStateChange(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
Definition ZombieBase.c:464
override protected void EOnContact(IEntity other, Contact extra)
override AnimBootsType GetBootsType()
Definition ZombieBase.c:128
override bool IsManagingArrows()
bool ModCommandHandlerAfter(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
Definition ZombieBase.c:286
override bool CanReceiveAttachment(EntityAI attachment, int slotId)
protected bool m_IsCrawling
Definition ZombieBase.c:33
override bool IsZombieMilitary()
Definition ZombieBase.c:112
protected ref InfectedSoundEventHandler m_InfectedSoundEventHandler
Definition ZombieBase.c:26
void ZombieBase()
Definition ZombieBase.c:42
void CommandHandlerDebug(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
Definition ZombieBase.c:296
proto native bool IsVault()
Same as 'DayZCreatureAIInputController::IsJump'.
proto native float GetVaultHeight()
Same as 'DayZCreatureAIInputController::GetJumpHeight'.
proto native EntityAI GetTargetEntity()
proto native int GetMindState()
override int GetMeleeTargetType()
Definition Building.c:46
Definition EnMath.c:7
proto void AddNoise(EntityAI source_entity, NoiseParams noise_params, float external_strenght_multiplier=1.0)
proto native void UpdateEnvSoundControllers(vector position)
SoundObject BuildSoundObject()
Definition Sound.c:49
proto native bool IsValid()
proto native float GetDamage(string zoneName, string healthType)
Base native class for all motorized wheeled vehicles.
Definition Car.c:80
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 const vector Zero
Definition EnConvert.c:110
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.
Definition EnConvert.c:271
string GetDefaultHitPositionComponent()
Definition dayzplayer.c:502
proto native CGame GetGame()
const float AI_ATTACKSPEED
Definition constants.c:891
const float AI_MAX_BLOCKABLE_ANGLE
Definition constants.c:892
EntityEvent
Entity events for event-mask, or throwing event from code.
Definition EnEntity.c:45
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].
Definition EnMath.c:53
static proto float AbsFloat(float f)
Returns absolute value.
static proto float NormalizeAngle(float ang)
Normalizes the angle (0...360)
static const float RAD2DEG
Definition EnMath.c:16
static const float DEG2RAD
Definition EnMath.c:17
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 void AddChild(Widget child, bool immedUpdate=true)
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