DayZ 1.30
DayZ Explorer by KGB
 
Загрузка...
Поиск...
Не найдено
ZombieBase.c
См. документацию.
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 protected ref DustEffectCeilingHandlerLocal m_CeilingDustHandler;
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, 5);
55 RegisterNetSyncVariableInt("m_OrientationSynced", 0, 359);
56 RegisterNetSyncVariableFloat("m_MovementSpeed", -1, 3);
57 RegisterNetSyncVariableBool("m_IsCrawling");
58
61
63 if ( !g_Game.IsHeadlessOrDedicatedServer() )
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
475 case DayZInfectedConstants.MINDSTATE_COWER:
476 if ( moveCommand && !moveCommand.IsTurning() )
477 moveCommand.SetIdleState(0);
478 break;
479 }
480
483 SetSynchDirty();
484 }
485 return false;
486 }
487
488 //-------------------------------------------------------------
492
493 protected void HandleSoundEvents()
494 {
497 {
498 return;
499 }
500
502 if ( !IsAlive() )
503 {
506 return;
507 }
508
509 switch ( m_MindState )
510 {
511 case DayZInfectedConstants.MINDSTATE_CALM:
512 m_InfectedSoundEventHandler.PlayRequest(EInfectedSoundEventID.MINDSTATE_CALM_MOVE);
513 break;
514 case DayZInfectedConstants.MINDSTATE_ALERTED:
515 m_InfectedSoundEventHandler.PlayRequest(EInfectedSoundEventID.MINDSTATE_ALERTED_MOVE);
516 break;
517 case DayZInfectedConstants.MINDSTATE_DISTURBED:
518 m_InfectedSoundEventHandler.PlayRequest(EInfectedSoundEventID.MINDSTATE_DISTURBED_IDLE);
519 break
520 case DayZInfectedConstants.MINDSTATE_CHASE:
521 m_InfectedSoundEventHandler.PlayRequest(EInfectedSoundEventID.MINDSTATE_CHASE_MOVE);
522 break;
523 default:
525 break;
526 }
527
528 DebugSound("[Infected @ " + this + "][MindState]" + typename.EnumToString(DayZInfectedConstants, m_MindState));
529 DebugSound("[Infected @ " + this + "][SoundEventID]" + typename.EnumToString(EInfectedSoundEventID, m_InfectedSoundEventHandler.GetCurrentStateEventID()));
530 }
531
532 AbstractWave ProcessVoiceFX(string pSoundSetName)
533 {
534 SoundParams soundParams;
535 SoundObjectBuilder soundObjectBuilder;
536 SoundObject soundObject;
537 if (!g_Game.IsHeadlessOrDedicatedServer())
538 {
539 soundParams = new SoundParams( pSoundSetName );
540 if ( !soundParams.IsValid() )
541 {
542 //SoundError("Invalid sound set.");
543 return null;
544 }
545
546 soundObjectBuilder = new SoundObjectBuilder( soundParams );
547 soundObject = soundObjectBuilder.BuildSoundObject();
548 AttenuateSoundIfNecessary(soundObject);
549
550 return PlaySound(soundObject, soundObjectBuilder);
551 }
552
553 return null;
554 }
555
556 override void OnSoundVoiceEvent(int event_id, string event_user_string)
557 {
558 //super.OnSoundVoiceEvent(event_id, event_user_string);
559 AnimSoundVoiceEvent voice_event = GetCreatureAIType().GetSoundVoiceEvent(event_id);
560 if (voice_event != null)
561 {
563 if (m_InfectedSoundEventHandler) // && m_InfectedSoundEventHandler.IsPlaying())
564 {
566 DebugSound("[Infected @ " + this + "][SoundEvent] InfectedSoundEventHandler - stop all");
567 }
568
570 if (m_LastSoundVoiceAW != null)
571 {
572 DebugSound("[Infected @ " + this + "][AnimVoiceEvent] Stopping LastAW");
573 m_LastSoundVoiceAW.Stop();
574 }
575
578
580 }
581 }
582
583 protected void ProcessSoundVoiceEvent(AnimSoundVoiceEvent sound_event, out AbstractWave aw)
584 {
585 if (!g_Game.IsHeadlessOrDedicatedServer())
586 {
587 SoundObjectBuilder objectBuilder = sound_event.GetSoundBuilder();
588 if (NULL != objectBuilder)
589 {
590 objectBuilder.AddEnvSoundVariables(GetPosition());
591 SoundObject soundObject = objectBuilder.BuildSoundObject();
592 AttenuateSoundIfNecessary(soundObject);
593 aw = PlaySound(soundObject, objectBuilder);
594 }
595 }
596
597 if (g_Game.IsServer())
598 {
599 if (sound_event.m_NoiseParams != NULL)
600 GetGame().GetNoiseSystem().AddNoise(this, sound_event.m_NoiseParams);
601 }
602 }
603
604 //-------------------------------------------------------------
608
612
613 bool FightLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
614 {
615 if (pCurrentCommandID == DayZInfectedConstants.COMMANDID_MOVE)
616 {
617 // we attack only in chase & fight state
618 int mindState = pInputController.GetMindState();
619 if (mindState == DayZInfectedConstants.MINDSTATE_CHASE)
620 {
621 return ChaseAttackLogic(pCurrentCommandID, pInputController, pDt);
622 }
623 else if (mindState == DayZInfectedConstants.MINDSTATE_FIGHT)
624 {
625 return FightAttackLogic(pCurrentCommandID, pInputController, pDt);
626 }
627 }
628 else if (pCurrentCommandID == DayZInfectedConstants.COMMANDID_ATTACK)
629 {
630 DayZInfectedCommandAttack attackCommand = GetCommand_Attack();
631 if (attackCommand && attackCommand.WasHit())
632 {
633 if (m_ActualTarget != null)
634 {
635 if (m_ActualTarget.GetMeleeTargetType() == EMeleeTargetType.NONALIGNABLE)
636 return false;
637
638 bool playerInBlockStance = false;
639 vector targetPos = m_ActualTarget.GetPosition();
640 vector hitPosWS = targetPos;
641 vector zombiePos = GetPosition();
642
643 PlayerBase playerTarget = PlayerBase.Cast(m_ActualTarget);
644 if (playerTarget)
645 {
646 playerInBlockStance = playerTarget.GetMeleeFightLogic() && playerTarget.GetMeleeFightLogic().IsInBlock();
647 }
648
649 if (vector.DistanceSq(targetPos, zombiePos) <= m_ActualAttackType.m_Distance * m_ActualAttackType.m_Distance)
650 {
652 if (playerInBlockStance && (Math.RAD2DEG * Math.AbsFloat(Math3D.AngleFromPosition(targetPos, MiscGameplayFunctions.GetHeadingVector(playerTarget), zombiePos))) <= GameConstants.AI_MAX_BLOCKABLE_ANGLE)
653 {
655 if (m_ActualAttackType.m_IsHeavy == 1)
656 {
657 hitPosWS = m_ActualTarget.ModelToWorld(m_ActualTarget.GetDefaultHitPosition());
658 DamageSystem.CloseCombatDamageName(this, m_ActualTarget, m_ActualTarget.GetHitComponentForAI(), "MeleeZombie", hitPosWS);
659 }
660 else
661 {
663 hitPosWS = m_ActualTarget.ModelToWorld(m_ActualTarget.GetDefaultHitPosition());
664 DamageSystem.CloseCombatDamageName(this, m_ActualTarget, m_ActualTarget.GetHitComponentForAI(), "Dummy_Light", hitPosWS);
665 }
666 }
667 else
668 {
669 hitPosWS = m_ActualTarget.ModelToWorld(m_ActualTarget.GetDefaultHitPosition());
670 DamageSystem.CloseCombatDamageName(this, m_ActualTarget, m_ActualTarget.GetHitComponentForAI(), m_ActualAttackType.m_AmmoType, hitPosWS);
671 }
672 }
673 }
674 }
675
676 return true;
677 }
678
679 return false;
680 }
681
682 bool ChaseAttackLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
683 {
684 // always update target - it can be destroyed
685 m_ActualTarget = pInputController.GetTargetEntity();
686
689 if ( pb && pb.GetCommand_Vehicle() )
690 {
691 return false;
692 }
693
694 if ( m_ActualTarget == NULL )
695 return false;
696
697 vector targetPos = m_ActualTarget.GetPosition();
698 if ( !CanAttackToPosition(targetPos) )
699 return false;
700
701 float targetDist = vector.Distance(targetPos, this.GetPosition());
702 int pitch = GetAttackPitch(m_ActualTarget);
703
704 m_ActualAttackType = GetDayZInfectedType().ChooseAttack(DayZInfectedAttackGroupType.CHASE, targetDist, pitch);
706 {
707 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);
709 if (m_ActualTarget != target)
710 {
711 m_AllTargetObjects.Clear();
712 return false;
713 }
714
715 StartCommand_Attack(m_ActualTarget, m_ActualAttackType.m_Type, m_ActualAttackType.m_Subtype);
717 return true;
718 }
719
720 return false;
721 }
722
723 bool FightAttackLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
724 {
725 // always update target - it can be destroyed
726 m_ActualTarget = pInputController.GetTargetEntity();
727
730 if (pb && pb.GetCommand_Vehicle())
731 return false;
732
733 if (m_AttackCooldownTime > 0)
734 {
736 return false;
737 }
738
739 if (m_ActualTarget == null)
740 return false;
741
742 vector targetPos = m_ActualTarget.GetPosition();
743 float targetDist = vector.Distance(targetPos, this.GetPosition());
744 int pitch = GetAttackPitch(m_ActualTarget);
745
746 if (!CanAttackToPosition(targetPos))
747 return false;
748
749 m_ActualAttackType = GetDayZInfectedType().ChooseAttack(DayZInfectedAttackGroupType.FIGHT, targetDist, pitch);
751 {
752 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);
755 {
756 m_AllTargetObjects.Clear();
757 return false;
758 }
759
760 StartCommand_Attack(m_ActualTarget, m_ActualAttackType.m_Type, m_ActualAttackType.m_Subtype);
762 return true;
763 }
764
765 return false;
766 }
767
769 {
770 const float CENTER_EPS = 0.3;
771 const float TORSO_TO_HEAD_OFFSET = 0.55; // for non-player fallback
772
773 // Approximate infected head height
774 float myHeadY = GetPosition()[1] + 1.8;
775
776 float targetY;
777 PlayerBase playerTarget = PlayerBase.Cast(target);
778 if (playerTarget)
779 {
780 // Stance-aware head pos
781 targetY = MiscGameplayFunctions.GetPlayerHeadPosition(playerTarget)[1];
782 }
783 else
784 {
785 // Non-player: use torso default hit pos, lift toward head
786 vector def = target.GetDefaultHitPosition();
787 if (def != vector.Zero)
788 targetY = target.ModelToWorld(def)[1] + TORSO_TO_HEAD_OFFSET;
789 else
790 targetY = target.GetPosition()[1] + 1.0; // last resort
791 }
792
793 float diff = Math.AbsFloat(targetY - myHeadY);
794 if (diff < CENTER_EPS)
795 return 0;
796
797 if(myHeadY > targetY)
798 return -1;
799 else
800 return 1;
801 }
802
803
804 //-------------------------------------------------------------
808
810
811 bool HandleCrawlTransition(int pCurrentCommandID)
812 {
813 if ( m_CrawlTransition != -1 )
814 {
815 StartCommand_Crawl(m_CrawlTransition);
816
818 m_IsCrawling = true;
819 SetSynchDirty();
820 return true;
821 }
822
823 return pCurrentCommandID == DayZInfectedConstants.COMMANDID_CRAWL;
824 }
825
826 bool EvaluateCrawlTransitionAnimation(EntityAI pSource, string pComponent, string pAmmoType, out int pAnimType)
827 {
828 pAnimType = -1;
829 if ( pComponent == "LeftLeg" && GetHealth(pComponent, "Health") == 0 )
830 pAnimType = 0;
831 else if ( pComponent == "RightLeg" && GetHealth(pComponent, "Health") == 0 )
832 pAnimType = 2;
833
834 if ( pAnimType != -1 )
835 {
836 vector targetDirection = GetDirection();
837 vector toSourceDirection = (pSource.GetPosition() - GetPosition());
838
839 targetDirection[1] = 0;
840 toSourceDirection[1] = 0;
841
842 targetDirection.Normalize();
843 toSourceDirection.Normalize();
844
845 float cosFi = vector.Dot(targetDirection, toSourceDirection);
846 if ( cosFi >= 0 ) // front
847 pAnimType++;
848 }
849
850 return pAnimType != -1;
851 }
852
853 //-------------------------------------------------------------
857
859
860 bool m_DamageHitHeavy = false;
862 float m_ShockDamage = 0;
863
864 const float HIT_INTERVAL_MIN = 0.3; // Minimum time in seconds before a COMMANDID_HIT to COMMANDID_HIT transition is allowed
866
867 bool HandleDamageHit(int pCurrentCommandID)
868 {
869 if ( pCurrentCommandID == DayZInfectedConstants.COMMANDID_HIT )
870 {
871 // Throttle hit command up to a fixed rate
873 {
875 m_DamageHitToProcess = false;
876 m_ShockDamage = 0;
877 return false;
878 }
879 }
880
882 {
883 int randNum = Math.RandomIntInclusive(0, 100);
884 float stunChange = SHOCK_TO_STUN_MULTIPLIER * m_ShockDamage;
885
886 if ( m_DamageHitHeavy || randNum <= stunChange || ( m_MindState == DayZInfectedConstants.MINDSTATE_CALM || m_MindState == DayZInfectedConstants.MINDSTATE_DISTURBED ) )
887 {
890 }
891
892 m_DamageHitToProcess = false;
893 m_ShockDamage = 0;
894 m_HeavyHitOverride = false;
895 return true;
896 }
897
898 return false;
899 }
900
902 bool EvaluateDamageHitAnimation(EntityAI pSource, string pComponent, string pAmmoType, out bool pHeavyHit, out int pAnimType, out float pAnimHitDir)
903 {
904 int invertHitDir = 0; //Used to flip the heavy hit animation direction
905
907 pHeavyHit = ((g_Game.ConfigGetInt("cfgAmmo " + pAmmoType + " hitAnimation") > 0) || m_HeavyHitOverride);
908 invertHitDir = g_Game.ConfigGetInt("cfgAmmo " + pAmmoType + " invertHitDir");
909
911 pAnimType = 0; // belly
912
913 if ( !pHeavyHit )
914 {
915 if ( pComponent == "Torso" ) // body
916 pAnimType = 1;
917 else if ( pComponent == "Head" ) // head
918 pAnimType = 2;
919 }
920
922 //pAnimHitDir = ComputeHitDirectionAngle(pSource);
923 pAnimHitDir = ComputeHitDirectionAngleEx(pSource, invertHitDir);
925 //m_ShockDamage = g_Game.ConfigGetFloat( "CfgAmmo " + pAmmoType + " DamageApplied " + "Shock " + "damage");
926 return true;
927 }
928
930 {
931 vector targetDirection = GetDirection();
932 vector toSourceDirection = (pSource.GetPosition() - GetPosition());
933
934 targetDirection[1] = 0;
935 toSourceDirection[1] = 0;
936
937 targetDirection.Normalize();
938 toSourceDirection.Normalize();
939
940 float cosFi = vector.Dot(targetDirection, toSourceDirection);
941 vector cross = targetDirection * toSourceDirection;
942
943 float dirAngle = Math.Acos(cosFi) * Math.RAD2DEG;
944 if ( cross[1] < 0 )
945 dirAngle = -dirAngle;
946
947 return dirAngle;
948 }
949
950 float ComputeHitDirectionAngleEx(EntityAI pSource, int invertHitDir = 0)
951 {
952 vector targetDirection = GetDirection();
953 vector toSourceDirection = (pSource.GetPosition() - GetPosition());
954
955 targetDirection[1] = 0;
956 toSourceDirection[1] = 0;
957
958 targetDirection.Normalize();
959 toSourceDirection.Normalize();
960
961 float cosFi = vector.Dot(targetDirection, toSourceDirection);
962 vector cross = targetDirection * toSourceDirection;
963
964 float dirAngle = Math.Acos(cosFi) * Math.RAD2DEG;
965
966 // We will invert direction of the hit
967 if ( invertHitDir > 0 )
968 dirAngle -= 180;
969
970 if ( cross[1] < 0 )
971 dirAngle = -dirAngle;
972
973 return dirAngle;
974 }
975
976 //-------------------------------------------------------------
980
981 override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
982 {
983 super.EEHitBy(damageResult, damageType, source, component, dmgZone, ammo, modelPos, speedCoef);
984
985 m_TransportHitRegistered = false;
986
987 if ( !IsAlive() )
988 {
989 ZombieHitData data = new ZombieHitData;
990 data.m_Component = component;
991 data.m_DamageZone = dmgZone;
992 data.m_AmmoType = ammo;
994 }
995 else
996 {
997 int crawlTransitionType = -1;
998 if ( EvaluateCrawlTransitionAnimation(source, dmgZone, ammo, crawlTransitionType) )
999 {
1000 m_CrawlTransition = crawlTransitionType;
1001 return;
1002 }
1003
1005 {
1006 if ( dmgZone )
1007 m_ShockDamage = damageResult.GetDamage( dmgZone, "Shock" );
1008 m_DamageHitToProcess = true;
1009 return;
1010 }
1011 }
1012 }
1013
1014 override void EEHitByRemote(int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos)
1015 {
1016 super.EEHitByRemote(damageType, source, component, dmgZone, ammo, modelPos);
1017 }
1018
1020 protected void DebugSound(string s)
1021 {
1022 //Print(s);
1023 }
1024
1025 //-------------------------------------------------------------
1029
1030 override protected void EOnContact(IEntity other, Contact extra)
1031 {
1032 if ( !IsAlive() )
1033 return;
1034
1035 Transport transport = Transport.Cast(other);
1036 if ( transport )
1037 {
1038 if ( g_Game.IsServer() )
1039 {
1040 RegisterTransportHit(transport);
1041 }
1042 }
1043 }
1044
1045 override bool CanReceiveAttachment(EntityAI attachment, int slotId)
1046 {
1047 if ( !IsAlive() )
1048 {
1049 return false;
1050 }
1051 return super.CanReceiveAttachment(attachment, slotId);
1052 }
1053
1055 {
1056 return GetBonePositionWS( GetBoneIndexByName( "spine3" ) );
1057 }
1058
1060 override bool IsBeingBackstabbed()
1061 {
1062 return m_FinisherInProgress;
1063 }
1064
1065 override void SetBeingBackstabbed(int backstabType)
1066 {
1067 // disable AI simulation
1068 GetAIAgent().SetKeepInIdle(true);
1069
1070 // select death animation
1071 switch (backstabType)
1072 {
1073 case EMeleeHitType.FINISHER_LIVERSTAB:
1074 m_DeathType = DayZInfectedDeathAnims.ANIM_DEATH_BACKSTAB;
1075 break;
1076
1077 case EMeleeHitType.FINISHER_NECKSTAB:
1078 m_DeathType = DayZInfectedDeathAnims.ANIM_DEATH_NECKSTAB;
1079 break;
1080
1081 default:
1082 m_DeathType = DayZInfectedDeathAnims.ANIM_DEATH_DEFAULT;
1083 }
1084
1085 // set flag - death command will be executed
1086 m_FinisherInProgress = true;
1087 }
1088
1091 {
1092 return m_IsCrawling;
1093 }
1094
1095 // called from command death when stealth attack wan't successful
1097 {
1098 // enable AI simulation again
1099 GetAIAgent().SetKeepInIdle(false);
1100
1101 // reset flag
1102 m_FinisherInProgress = false;
1103 }
1104
1105 override void AddArrow(Object arrow, int componentIndex, vector closeBonePosWS, vector closeBoneRotWS)
1106 {
1108 GetActionComponentNameList(componentIndex, CachedObjectsArrays.ARRAY_STRING, "fire");
1109
1110 int pivot = -1;
1111
1112
1113 for (int i = 0; i < CachedObjectsArrays.ARRAY_STRING.Count() && pivot == -1; i++)
1114 {
1116 }
1117
1118 vector parentTransMat[4];
1119 vector arrowTransMat[4];
1120
1121 if (pivot == -1)
1122 {
1123 GetTransformWS(parentTransMat);
1124 }
1125 else
1126 {
1127 vector rotMatrix[3];
1128 Math3D.YawPitchRollMatrix(closeBoneRotWS * Math.RAD2DEG,rotMatrix);
1129
1130 parentTransMat[0] = rotMatrix[0];
1131 parentTransMat[1] = rotMatrix[1];
1132 parentTransMat[2] = rotMatrix[2];
1133 parentTransMat[3] = closeBonePosWS;
1134 }
1135
1136 arrow.GetTransform(arrowTransMat);
1137 Math3D.MatrixInvMultiply4(parentTransMat, arrowTransMat, arrowTransMat);
1138 // orthogonalize matrix - parent might be skewed
1139 Math3D.MatrixOrthogonalize4(arrowTransMat);
1140 arrow.SetTransform(arrowTransMat);
1141
1142 AddChild(arrow, pivot);
1143 }
1144
1145 override bool IsManagingArrows()
1146 {
1147 return true;
1148 }
1149
1151 {
1152 return m_ArrowManager;
1153 }
1154
1155 override void OnStepEvent(int event_id, string event_user_string)
1156 {
1157 super.OnStepEvent(event_id, event_user_string);
1158
1159 SurfaceInfo surfaceInfo;
1160 if (event_id % 2 == 0)
1161 {
1162 surfaceInfo = g_Game.GetSurfaceInfoUnderObjectByBone(this, SurfaceAnimationBone.LeftBackLimb);
1163 }
1164 else if (event_id % 2 == 1)
1165 {
1166 surfaceInfo = g_Game.GetSurfaceInfoUnderObjectByBone(this, SurfaceAnimationBone.RightBackLimb);
1167 }
1168
1169 //string surface;
1170 if(surfaceInfo)
1171 {
1173
1175 {
1176 int stepParticleID = surfaceInfo.GetStepParticleId();
1177 if (stepParticleID > 0)
1178 {
1179 orientation = GetOrientation() * (-1);
1180 ParticleManager.GetInstance().PlayInWorldEx(stepParticleID, null, GetPosition(), orientation);
1181 }
1182 }
1183
1184 HandleCeilingDustStepEffect(surfaceInfo);
1185 }
1186 }
1187
1188 protected void HandleCeilingDustStepEffect(SurfaceInfo surfaceInfo)
1189 {
1190 //non-player entity, only local
1191 if (!GetGame().IsDedicatedServer())
1192 {
1194 m_CeilingDustHandler = new DustEffectCeilingHandlerLocal(this);
1195
1196 m_CeilingDustHandler.OnStepUpdate(surfaceInfo);
1197 }
1198 }
1199}
1200
1202class ZombieHitData
1203{
1207}
RepairTentActionReciveData m_DamageZone
void HandleCeilingDustStepEffect(SurfaceInfo surfaceInfo)
Определения AnimalBase.c:99
vector GetOrientation()
Определения AreaDamageManager.c:306
CodeLockComponent m_Component
Определения CodeLockVisualManager.c:14
AnimBootsType
Определения DayZAnimEvents.c:98
bool ModCommandHandlerInside(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
Определения 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)
Определения DayZAnimal.c:175
bool ModCommandHandlerAfter(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
Определения DayZAnimal.c:185
DayZGame g_Game
Определения DayZGame.c:4074
override Widget Init()
Определения DayZGame.c:127
DayZInfectedConstants
Определения DayZInfected.c:2
DayZInfectedAttackGroupType
Определения DayZInfectedType.c:14
EMeleeHitType
Определения DayZPlayerImplementMeleeCombat.c:2
void DayZPlayerUtils()
cannot be instantiated
Определения DayZPlayerUtils.c:465
vector orientation
Определения DustKickupEffects.c:21
EMeleeTargetType
Определения EMeleeTargetType.c:2
void PlaySound()
Определения HungerSoundHandler.c:39
string m_AmmoType
Определения ImpactEffects.c:18
void InfectedSoundEventHandler(ZombieBase pInfected)
Определения InfectedSoundEventHandler.c:21
EInfectedSoundEventID
Определения InfectedSoundEventHandler.c:2
class BoxCollidingParams component
ComponentInfo for BoxCollidingResult.
void ParticleManager(ParticleManagerSettings settings)
Constructor (ctor)
Определения ParticleManager.c:88
PluginManager GetPluginManager()
Returns registred plugin by class type, better is to use global funtion GetPlugin(typename plugin_typ...
Определения PluginManager.c:284
Определения AnimalBase.c:113
static ref TStringArray ARRAY_STRING
Определения UtilityClasses.c:49
Определения Contact.c:10
proto native float GetMovementSpeed()
void CommandHandler(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
Определения ZombieBase.c:198
int m_StanceVariation
server / singleplayer properties
Определения ZombieBase.c:10
int GetMindStateSynced()
Определения ZombieBase.c:182
void HandleCeilingDustStepEffect(SurfaceInfo surfaceInfo)
Определения ZombieBase.c:1188
float m_KnuckleOutTimer
Определения ZombieBase.c:15
bool m_IsCrawling
Определения ZombieBase.c:34
override void OnSoundVoiceEvent(int event_id, string event_user_string)
Определения ZombieBase.c:556
override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
Определения ZombieBase.c:981
bool m_FinisherInProgress
Определения ZombieBase.c:36
ref ArrowManagerBase m_ArrowManager
Определения ZombieBase.c:38
bool FightLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
Определения ZombieBase.c:613
const float TARGET_CONE_ANGLE_CHASE
Определения ZombieBase.c:3
const float HIT_INTERVAL_MIN
Определения ZombieBase.c:864
int m_MindState
Определения ZombieBase.c:17
ref InfectedSoundEventHandler m_InfectedSoundEventHandler
Определения ZombieBase.c:27
void CommandHandlerDebug(float pDt, int pCurrentCommandID, bool pCurrentCommandFinished)
Определения ZombieBase.c:283
override bool IsManagingArrows()
Определения ZombieBase.c:1145
bool HandleVault(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
Определения ZombieBase.c:413
override array< string > GetSuitableFinisherHitComponents()
returns suitable hit components for finisher attacks; DEPRECATED
Определения ZombieBase.c:177
override bool CanReceiveAttachment(EntityAI attachment, int slotId)
Определения ZombieBase.c:1045
int m_CrawlTransition
Определения ZombieBase.c:809
void ProcessSoundVoiceEvent(AnimSoundVoiceEvent sound_event, out AbstractWave aw)
Определения ZombieBase.c:583
int GetOrientationSynced()
returns rounded zombie yaw for sync purposes
Определения ZombieBase.c:188
float m_DeltaTime
Определения ZombieBase.c:24
bool m_DamageHitHeavy
Определения ZombieBase.c:860
int m_DamageHitType
Определения ZombieBase.c:861
bool IsCrawling()
returns true if crawling; 'DayZInfectedCommandCrawl' is only for the transition, after that it remain...
Определения ZombieBase.c:1090
override bool IsSelfAdjustingTemperature()
Определения ZombieBase.c:149
const float SHOCK_TO_STUN_MULTIPLIER
Определения ZombieBase.c:7
void ZombieBase()
Определения ZombieBase.c:43
int m_OrientationLocal
Определения ZombieBase.c:18
float m_MovementSpeed
Определения ZombieBase.c:21
override bool IsDanger()
Определения ZombieBase.c:108
float m_LastMovementSpeed
Определения ZombieBase.c:12
override void EOnInit(IEntity other, int extra)
Определения ZombieBase.c:92
override void AddArrow(Object arrow, int componentIndex, vector closeBonePosWS, vector closeBoneRotWS)
Определения ZombieBase.c:1105
void OnRecoverFromDeath()
Определения ZombieBase.c:1096
override void EEHitByRemote(int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos)
Определения ZombieBase.c:1014
ref array< Object > m_AllTargetObjects
Определения ZombieBase.c:29
DayZInfectedAttackType m_ActualAttackType
Определения ZombieBase.c:611
EntityAI m_ActualTarget
Определения ZombieBase.c:609
AbstractWave ProcessVoiceFX(string pSoundSetName)
Определения ZombieBase.c:532
const float ORIENTATION_SYNC_THRESHOLD
Определения ZombieBase.c:5
int m_ActiveVaultType
Определения ZombieBase.c:399
void HandleOrientation(float pDt, int pCurrentCommandID)
Определения ZombieBase.c:314
override bool CanBeSkinned()
Определения ZombieBase.c:134
override void OnStepEvent(int event_id, string event_user_string)
Определения ZombieBase.c:1155
override bool IsZombie()
Определения ZombieBase.c:103
bool HandleDamageHit(int pCurrentCommandID)
Определения ZombieBase.c:867
void HandleSoundEvents()
Определения ZombieBase.c:493
bool EvaluateCrawlTransitionAnimation(EntityAI pSource, string pComponent, string pAmmoType, out int pAnimType)
Определения ZombieBase.c:826
vector SetDefaultHitPosition(string pSelection)
Определения ZombieBase.c:171
float m_HitElapsedTime
Определения ZombieBase.c:865
AbstractWave m_LastSoundVoiceAW
Определения ZombieBase.c:26
override AnimBootsType GetBootsType()
Определения ZombieBase.c:129
bool FightAttackLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
Определения ZombieBase.c:723
bool HandleCrawlTransition(int pCurrentCommandID)
Определения ZombieBase.c:811
float m_DamageHitDirection
Определения ZombieBase.c:346
void Init()
Определения ZombieBase.c:48
void HandleMove(int pCurrentCommandID)
Определения ZombieBase.c:297
void DebugSound(string s)
sound debug messages
Определения ZombieBase.c:1020
float m_AttackCooldownTime
Определения ZombieBase.c:610
vector m_DefaultHitPosition
Определения ZombieBase.c:23
ref DustEffectCeilingHandlerLocal m_CeilingDustHandler
Определения ZombieBase.c:39
override bool IsHealthVisible()
Определения ZombieBase.c:139
bool EvaluateDeathAnimationEx(EntityAI pSource, ZombieHitData data, out int pAnimType, out float pAnimHitDir)
Определения ZombieBase.c:363
override bool IsRefresherSignalingViable()
Определения ZombieBase.c:144
float m_ShockDamage
Определения ZombieBase.c:862
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
Определения ZombieBase.c:902
override string GetDefaultHitComponent()
returns default hit component (fallback)
Определения ZombieBase.c:161
override bool IsBeingBackstabbed()
returns true if backstab is in progress; used for suspending of AI targeting and other useful things ...
Определения ZombieBase.c:1060
void EOnContact(IEntity other, Contact extra)
Определения ZombieBase.c:1030
override vector GetCenter()
Определения ZombieBase.c:1054
bool m_DamageHitToProcess
Определения ZombieBase.c:858
bool HandleDeath(int pCurrentCommandID)
Определения ZombieBase.c:349
ref array< typename > m_TargetableObjects
Определения ZombieBase.c:30
override void OnVariablesSynchronized()
synced variable(s) handler
Определения ZombieBase.c:80
bool m_KnuckleLand
Определения ZombieBase.c:14
int m_OrientationSynced
Определения ZombieBase.c:19
override string GetHitComponentForAI()
returns hit component for attacking AI
Определения ZombieBase.c:155
int GetAttackPitch(EntityAI target)
Определения ZombieBase.c:768
float ComputeHitDirectionAngleEx(EntityAI pSource, int invertHitDir=0)
Определения ZombieBase.c:950
int m_LastMindState
Определения ZombieBase.c:11
override void SetBeingBackstabbed(int backstabType)
Определения ZombieBase.c:1065
override bool IsZombieMilitary()
Определения ZombieBase.c:113
const float TARGET_CONE_ANGLE_FIGHT
Определения ZombieBase.c:4
bool IsMale()
Определения ZombieBase.c:118
int m_DeathType
Определения ZombieBase.c:347
override bool CanBeBackstabbed()
Определения ZombieBase.c:123
int GetVaultType(float height)
Определения ZombieBase.c:401
override vector GetDefaultHitPosition()
Определения ZombieBase.c:166
float m_OrientationTimer
Определения ZombieBase.c:20
bool EvaluateDeathAnimation(EntityAI pSource, string pComponent, string pAmmoType, out int pAnimType, out float pAnimHitDir)
Определения ZombieBase.c:370
bool HandleMindStateChange(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
Определения ZombieBase.c:450
float ComputeHitDirectionAngle(EntityAI pSource)
Определения ZombieBase.c:929
override ArrowManagerBase GetArrowManager()
Определения ZombieBase.c:1150
bool ChaseAttackLogic(int pCurrentCommandID, DayZInfectedInputController pInputController, float pDt)
Определения ZombieBase.c:682
Определения ZombieBase.c:2
proto native float GetVaultHeight()
Same as 'DayZCreatureAIInputController::GetJumpHeight'.
proto native int GetMindState()
proto native bool IsVault()
Same as 'DayZCreatureAIInputController::IsJump'.
proto native EntityAI GetTargetEntity()
Определения EnEntity.c:165
Определения EnMath3D.c:28
Определения EnMath.c:7
Определения ObjectTyped.c:2
Определения PlayerBaseClient.c:2
Определения Sound.c:112
proto int GetStepParticleId()
Определения SurfaceInfo.c:9
proto native float GetDamage(string zoneName, string healthType)
Определения DamageSystem.c:2
Native class for boats - handles physics simulation.
Определения Boat.c:29
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
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.
Определения EnConvert.c:305
static const vector Zero
Определения EnConvert.c:123
proto float Normalize()
Normalizes vector. Returns length.
static proto native float Distance(vector v1, vector v2)
Returns the distance between tips of two 3D vectors.
Определения EnConvert.c:119
string GetDefaultHitPositionComponent()
Определения dayzplayer.c:502
DayZGame GetGame()
Определения gameplay.c:636
const float AI_MAX_BLOCKABLE_ANGLE
Определения 3_Game/DayZ/constants.c:1127
const float AI_ATTACKSPEED
Определения 3_Game/DayZ/constants.c:1126
const int AI_SPRINT_STEP_MIN_ID
Определения 3_Game/DayZ/constants.c:1130
const int AI_SPRINT_STEP_MAX_ID
Определения 3_Game/DayZ/constants.c:1131
EntityEvent
Entity events for event-mask, or throwing event from code.
Определения 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 YawPitchRollMatrix(vector ang, out vector mat[3])
Creates rotation matrix from angles.
static proto void MatrixInvMultiply4(vector mat0[4], vector mat1[4], out vector res[4])
Invert-transforms matrix.
static proto void MatrixOrthogonalize4(vector mat[4])
Orthogonalizes matrix.
static proto float NormalizeAngle(float ang)
Normalizes the angle (0...360)
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 AbsInt(int i)
Returns absolute value.
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 proto float Sin(float angle)
Returns sinus 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 const float RAD2DEG
Определения EnMath.c:16
static const float DEG2RAD
Определения EnMath.c:17
static proto float AbsFloat(float f)
Returns absolute value.
static int RandomIntInclusive(int min, int max)
Returns a random int number between and min [inclusive] and max [inclusive].
Определения EnMath.c:54
proto void dBodyApplyImpulse(notnull IEntity body, vector impulse)
Applies impuls on a rigidbody (origin)
class AbstractSoundScene SoundObjectBuilder(SoundParams soundParams)
vector GetPosition()
Get the world position of the Effect.
Определения Effect.c:473
void AbstractWave()
Определения Sound.c:167
class SoundObject SoundParams(string name)
proto native void AddChild(Widget child, bool immedUpdate=true)