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