Dayz Explorer 1.28.160049
Loading...
Searching...
No Matches
staminahandler.c
Go to the documentation of this file.
10
11
19{
20 protected float m_ActivationThreshold;
21 protected float m_DrainThreshold
22 protected bool m_State;
23
24 void StaminaConsumer(float threshold, float threshold2, bool state)
25 {
26 m_ActivationThreshold = threshold; //can be activated if above this threshold
27 m_DrainThreshold = threshold2; //can continually drain until it reaches this threshold
28 m_State = state;
29 }
30
31 bool GetState() { return m_State; }
32 void SetState(bool state) { m_State = state; }
33
35 void SetActivationThreshold(float threshold) { m_ActivationThreshold = threshold; }
36
37 float GetDrainThreshold() { return m_DrainThreshold; }
38 void SetDrainThreshold(float threshold) { m_DrainThreshold = threshold; }
39}
40
42{
44
49
50 void RegisterConsumer(EStaminaConsumers consumer, float threshold, float depletion_threshold = -1)
51 {
52 if (depletion_threshold == -1)
53 {
54 depletion_threshold = threshold;
55 }
56
57 if ( !m_StaminaConsumers.Contains(consumer) )
58 {
60 StaminaConsumer sc = new StaminaConsumer(threshold, depletion_threshold, true);
61 m_StaminaConsumers.Set(consumer, sc);
62 }
63 }
64
65 bool HasEnoughStaminaFor(EStaminaConsumers consumer, float curStamina, bool isDepleted, float cap)
66 {
68 if (m_StaminaConsumers && m_StaminaConsumers.Find(consumer, sc))
69 {
70 if (consumer != EStaminaConsumers.SPRINT)
71 {
72 if (isDepleted || (curStamina < sc.GetDrainThreshold()))
73 {
74 sc.SetState(false);
75 return false;
76 }
77 }
78 else
79 {
80 if (!isDepleted)
81 {
82 if (sc.GetState())
83 {
84 sc.SetState(true);
85 return true;
86 }
87 }
88 else
89 {
90 sc.SetState(false);
91 return false;
92 }
93 }
94
95 if (curStamina > sc.GetDrainThreshold() || curStamina == cap) //Sometimes player can't go up to drain threshold
96 {
97 sc.SetState(true);
98 return true;
99 }
100 }
101
102 return false;
103 }
104
105 bool HasEnoughStaminaToStart(EStaminaConsumers consumer, float curStamina, bool isDepleted, float cap)
106 {
108 if (m_StaminaConsumers && m_StaminaConsumers.Find(consumer, sc))
109 {
110 if ((isDepleted || (curStamina < sc.GetActivationThreshold() && curStamina < cap)))
111 {
112 sc.SetState(false);
113 return false;
114 }
115 else
116 {
117 sc.SetState(true);
118 return true;
119 }
120 }
121
122 return false;
123 }
124}
125
126
135class StaminaModifier
136{
137 bool m_InUse = false;
140
141 void StaminaModifier(int type, float min, float max, float cooldown, float startTime = 0, float duration = 0)
142 {
143 m_Type = type;
144 m_MinValue = min;
145 m_MaxValue = max;
146 m_Cooldown = cooldown;
147 m_StartTimeAdjustment = startTime;
148 m_Duration = duration;
149 m_Tick = 1;
150 }
151
152 int GetType() { return m_Type; }
153
154 float GetMinValue() { return m_MinValue; }
155 void SetMinValue(float val) { m_MinValue = val; }
156
157 float GetMaxValue() { return m_MaxValue; }
158 void SetMaxValue(float val) { m_MaxValue = val; }
159
160 float GetCooldown() { return m_Cooldown; }
161 void SetCooldown(float val) { m_Cooldown = val; }
162
163 float GetStartTime() { return m_StartTime; } //Actual game time (progressive modifiers only)
164 void SetStartTime(float val) { m_StartTime = val; }
165
166 float GetStartTimeAdjustment() {return m_StartTimeAdjustment;} //adjustment to current time (progressive modifiers only)
167
168 float GetDuration() { return m_Duration; }
170
171 bool IsInUse() { return m_InUse; }
172 void SetInUse(bool val) { m_InUse = val; }
173
174 float GetRunTime() { return m_ProgressTime; }
175 void AddRunTime(float val) { m_ProgressTime += val; }
176 void SetRunTimeTick(float val) { m_Tick = val; }
178}
179
180class StaminaModifierExponential : StaminaModifier
181{
182 protected ref SMDataExponential m_SMDataEx;
183
184 float GetBaseValue() { return m_SMDataEx.m_BaseValue; }
185 float GetExponent() { return m_SMDataEx.m_Exponent; }
186 float GetMultiplier() { return m_SMDataEx.m_Multiplier; }
187 override float GetCooldown() { return m_SMDataEx.m_Cooldown; }
188 override float GetStartTimeAdjustment() { return m_SMDataEx.m_StartTimeAdjustment; }
189 override float GetDuration() { return m_SMDataEx.m_Duration; }
190 override float GetDurationAdjusted() { return m_SMDataEx.m_Duration / m_Tick; }
191
192 void SetData(SMDataExponential data) { m_SMDataEx = data; }
193}
194
196{
197 const int FIXED = 0;
198 const int RANDOMIZED = 1;
199 const int LINEAR = 2; //Useful ONLY for regular, over-time stamina drain
200 const int EXPONENTIAL = 3; //Useful ONLY for regular, over-time stamina drain
201
203
208
210 void RegisterFixed(EStaminaModifiers modifier, float value, float cooldown = GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION)
211 {
212 if ( !m_StaminaModifiers.Contains(modifier) )
213 {
215 StaminaModifier sm = new StaminaModifier(FIXED, -1, value, cooldown);
216 m_StaminaModifiers.Set(modifier, sm);
217 }
218 }
219
221 void RegisterRandomized(EStaminaModifiers modifier, float minValue, float maxValue, float cooldown = GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION)
222 {
223 if ( !m_StaminaModifiers.Contains(modifier) )
224 {
226 StaminaModifier sm = new StaminaModifier(RANDOMIZED, minValue, maxValue, cooldown);
227 m_StaminaModifiers.Set(modifier, sm);
228 }
229 }
230
232 void RegisterLinear(EStaminaModifiers modifier, float startValue, float endValue, float startTime, float duration, float cooldown = GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION)
233 {
234 StaminaModifier sm = new StaminaModifier(LINEAR, startValue, endValue, cooldown, startTime, duration);
235 m_StaminaModifiers.Set(modifier, sm);
236 }
237
239 void RegisterExponential(EStaminaModifiers modifier, float startValue, float exponent, float startTime, float duration, float cooldown = GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION)
240 {
241 StaminaModifier sm = new StaminaModifier(EXPONENTIAL, startValue, exponent, cooldown, startTime, duration);
242 m_StaminaModifiers.Set(modifier, sm);
243 }
244
246 void RegisterExponentialEx(EStaminaModifiers modifier, SMDataExponential data)
247 {
248 StaminaModifierExponential smex = new StaminaModifierExponential(EXPONENTIAL, data.m_BaseValue, data.m_Exponent, data.m_Cooldown, data.m_StartTimeAdjustment, data.m_Duration);
249 smex.SetData(data);
250 m_StaminaModifiers.Set(modifier, smex);
251 }
252
253 StaminaModifier GetModifierData(EStaminaModifiers modifier)
254 {
255 return m_StaminaModifiers.Get(modifier);
256 }
257}
258
259
261{
262 protected float m_PlayerLoad;
263 protected float m_StaminaDelta;
264 protected float m_Stamina;
265 protected float m_StaminaSynced; //guaranteed to be identical on server and client
266 protected float m_StaminaCap;
267 protected float m_StaminaDepletion;
268 protected float m_StaminaDepletionMultiplier; //controls depletion rate
269 protected float m_StaminaRecoveryMultiplier; //controls recovery rate
270 protected float m_Time;
272 protected ref HumanMovementState m_State;
275
276 protected bool m_Debug;
277 protected bool m_StaminaDepleted;
278
281 ref set<EStaminaMultiplierTypes> m_ActiveDepletionModifiers;
282
284 ref set<EStaminaMultiplierTypes> m_ActiveRecoveryModifiers;
285
286 protected bool m_IsInCooldown;
287
290
291 #ifdef DIAG_DEVELOPER
292 protected bool m_StaminaDisabled;
293 #endif
294
296 {
297 if (GetGame().IsServer() || !GetGame().IsMultiplayer())
298 m_StaminaParams = new Param3<float,float,bool>(0, 0, false);
299
300 m_State = new HumanMovementState();
301 m_Player = player;
302 m_Stamina = CfgGameplayHandler.GetStaminaMax();
303 m_StaminaSynced = CfgGameplayHandler.GetStaminaMax();
304 m_StaminaCap = CfgGameplayHandler.GetStaminaMax();
308 m_Time = 0;
309 m_StaminaDepleted = false;
310 m_IsInCooldown = false;
311 m_HumanMoveSettings = m_Player.GetDayZPlayerType().CommandMoveSettingsW();
312
315
317
318 //----------------- depletion --------------------
320 m_ActiveDepletionModifiers = new set<EStaminaMultiplierTypes>;
321
322 //----------------- recovery --------------------
324 m_ActiveRecoveryModifiers = new set<EStaminaMultiplierTypes>;
325
326 Init();
327 }
328
329
330 void Init()
331 {
332 //----------------- depletion --------------------
333 m_RegisteredDepletionModifiers.Insert(EStaminaMultiplierTypes.MASK, MaskMdfr.STAMINA_DEPLETION_MODIFIER);
334 m_RegisteredDepletionModifiers.Insert(EStaminaMultiplierTypes.FATIGUE, FatigueMdfr.STAMINA_DEPLETION_MULTIPLIER);
335 m_RegisteredDepletionModifiers.Insert(EStaminaMultiplierTypes.EPINEPHRINE, EpinephrineMdfr.STAMINA_DEPLETION_MULTIPLIER);
336 m_RegisteredDepletionModifiers.Insert(EStaminaMultiplierTypes.VOMIT_EXHAUSTION, VomitSymptom.STAMINA_DEPLETION_MULTIPLIER);
337 m_RegisteredDepletionModifiers.Insert(EStaminaMultiplierTypes.DISEASE_PNEUMONIA, PneumoniaMdfr.STAMINA_DEPLETION_MULTIPLIER);
338
339 //----------------- recovery --------------------
340 m_RegisteredRecoveryModifiers.Insert(EStaminaMultiplierTypes.MASK, MaskMdfr.STAMINA_RECOVERY_MODIFIER);
341 m_RegisteredRecoveryModifiers.Insert(EStaminaMultiplierTypes.FATIGUE, FatigueMdfr.STAMINA_RECOVERY_MULTIPLIER);
342 m_RegisteredRecoveryModifiers.Insert(EStaminaMultiplierTypes.DROWNING, DrowningMdfr.STAMINA_RECOVERY_MULTIPLIER);
343 m_RegisteredRecoveryModifiers.Insert(EStaminaMultiplierTypes.VOMIT_EXHAUSTION, VomitSymptom.STAMINA_RECOVERY_MULTIPLIER);
344 m_RegisteredRecoveryModifiers.Insert(EStaminaMultiplierTypes.DISEASE_PNEUMONIA, PneumoniaMdfr.STAMINA_RECOVERY_MULTIPLIER);
345
346 }
347
349 {
350 if (m_RegisteredDepletionModifiers.Contains(type))
351 {
352 m_ActiveDepletionModifiers.Insert(type);
354 }
355 else
356 {
357 Error("attempting to activate unregistered depletion modifier");
358 }
359 }
360
362 {
363 int index = m_ActiveDepletionModifiers.Find(type);
364 if (index != -1)
365 {
366 m_ActiveDepletionModifiers.Remove(index);
368 }
369 }
370
372 {
373 float value = 1;
374
375 foreach (int multiplier: m_ActiveDepletionModifiers)
376 {
377 value *= m_RegisteredDepletionModifiers.Get(multiplier);
378 }
379
380 if (value != m_StaminaDepletionMultiplier)
382 }
383
385 {
386 if (m_RegisteredRecoveryModifiers.Contains(type))
387 {
388 m_ActiveRecoveryModifiers.Insert(type);
390 }
391 else
392 {
393 Error("attempting to activate unregistered recovery modifier");
394 }
395 }
396
397
399 {
400 int index = m_ActiveRecoveryModifiers.Find(type);
401 if (index != -1)
402 {
403 m_ActiveRecoveryModifiers.Remove(index);
405 }
406 }
407
409 {
410 float value = 1;
411
412 foreach (int multiplier: m_ActiveRecoveryModifiers)
413 {
414 value *= m_RegisteredRecoveryModifiers.Get(multiplier);
415 }
416
417 if (value != m_StaminaRecoveryMultiplier)
418 {
420 }
421 }
422
423 void Update(float deltaT, int pCurrentCommandID)
424 {
425 #ifdef DIAG_DEVELOPER
426 if (m_StaminaDisabled)
427 return;
428 #endif
429
430 if (m_Player)
431 {
432 bool isServerOrSingleplayer = GetGame().IsServer() || !GetGame().IsMultiplayer();
433 // Calculates actual max stamina based on player's load
434 if (isServerOrSingleplayer)
435 {
437 m_PlayerLoad = m_Player.GetWeightEx();
438
440 if (m_PlayerLoad >= CfgGameplayHandler.GetStaminaWeightLimitThreshold())
441 {
442 m_StaminaCap = Math.Max((CfgGameplayHandler.GetStaminaMax() - (((m_PlayerLoad - CfgGameplayHandler.GetStaminaWeightLimitThreshold())/GameConstants.STAMINA_KG_TO_GRAMS) * CfgGameplayHandler.GetStaminaKgToStaminaPercentPenalty())),CfgGameplayHandler.GetStaminaMinCap());
443 }
444 else
445 {
446 m_StaminaCap = CfgGameplayHandler.GetStaminaMax();
447 }
448 }
449
450 // Calculates stamina gain/loss based on movement and load
451 m_Player.GetMovementState(m_State);
452
453 switch (m_State.m_CommandTypeId)
454 {
455 case DayZPlayerConstants.COMMANDID_MOVE:
457 break;
458 case DayZPlayerConstants.COMMANDID_LADDER:
460 break;
461 case DayZPlayerConstants.COMMANDID_SWIM:
463 break;
464 case DayZPlayerConstants.COMMANDID_FALL:
465 case DayZPlayerConstants.COMMANDID_MELEE2:
466 case DayZPlayerConstants.COMMANDID_CLIMB:
467 break;
468 default:
469 if (!m_IsInCooldown)
470 {
471 m_StaminaDelta = GameConstants.STAMINA_GAIN_IDLE_PER_SEC;
472 }
473 break;
474 }
475
476 //Sets current stamina & stores + syncs data with client
477 float temp = m_StaminaDelta * deltaT;
478 if (temp < 0)
479 {
481 }
482 else
483 {
485 }
486
487 m_Stamina = Math.Max(0, Math.Min((m_Stamina + temp), m_StaminaCap));
489
490 if (isServerOrSingleplayer)
491 {
492 m_Player.GetStatStamina().Set(m_Stamina);
493 m_Time += deltaT;
494
495 if (m_Time >= GameConstants.STAMINA_SYNC_RATE)
496 {
497 m_Time = 0;
499 }
500 }
501
502 #ifndef SERVER
504 #endif
505
508
509 m_StaminaDelta = 0;
510 m_StaminaDepletion = 0; // resets depletion modifier
511
512 }
513 }
514
516 void OnRPC(float stamina, float stamina_cap, bool cooldown)
517 {
518 }
519
521 void OnSyncJuncture(int pJunctureID, ParamsReadContext pCtx)
522 {
523 switch ( pJunctureID )
524 {
525 case DayZPlayerSyncJunctures.SJ_STAMINA:
526 float stamina;
527 float stamina_cap;
528 bool cooldown;
529
530 if (!pCtx.Read(stamina) || !pCtx.Read(stamina_cap) || !pCtx.Read(cooldown))
531 {
532 return;
533 }
534
535 m_Stamina = stamina; //?
536 m_StaminaSynced = stamina;
537
538 if (m_Player.GetInstanceType() != DayZPlayerInstanceType.INSTANCETYPE_CLIENT)
539 {
540 return;
541 }
542
543 if ( stamina_cap != m_StaminaCap )
544 {
545 m_StaminaCap = stamina_cap;
546 }
547
548 m_IsInCooldown = cooldown;
549 m_Player.SetStamina(m_Stamina, m_StaminaCap);
550 break;
551
552 case DayZPlayerSyncJunctures.SJ_STAMINA_MISC:
554 break;
555 }
556 }
557
558 protected void StaminaProcessor_Move(HumanMovementState pHumanMovementState)
559 {
560 switch (pHumanMovementState.m_iMovement)
561 {
562 case DayZPlayerConstants.MOVEMENTIDX_SPRINT: //sprint
563 if (pHumanMovementState.m_iStanceIdx == DayZPlayerConstants.STANCEIDX_ERECT)
564 {
565 m_StaminaDelta = -GameConstants.STAMINA_DRAIN_STANDING_SPRINT_PER_SEC * CfgGameplayHandler.GetSprintStaminaModifierErc();
566 SetCooldown(GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION);
567 break;
568 }
569 else if ( pHumanMovementState.m_iStanceIdx == DayZPlayerConstants.STANCEIDX_CROUCH)
570 {
571 m_StaminaDelta = -GameConstants.STAMINA_DRAIN_CROUCHED_SPRINT_PER_SEC * CfgGameplayHandler.GetSprintStaminaModifierCro();
572 SetCooldown(GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION);
573 break;
574 }
575
576 m_StaminaDelta = GameConstants.STAMINA_GAIN_JOG_PER_SEC;
577 break;
578
579 case DayZPlayerConstants.MOVEMENTIDX_RUN: //jog
580 if (m_Player.GetCurrentWaterLevel() >= m_HumanMoveSettings.m_fWaterLevelSpeedRectrictionHigh)
581 {
582 m_StaminaDelta = -GameConstants.STAMINA_DRAIN_STANDING_SPRINT_PER_SEC * CfgGameplayHandler.GetSprintStaminaModifierErc();
583 break;
584 }
585
586 if (!m_IsInCooldown)
587 {
588 m_StaminaDelta = (GameConstants.STAMINA_GAIN_JOG_PER_SEC + CalcStaminaGainBonus());
589 }
590 break;
591
592 case DayZPlayerConstants.MOVEMENTIDX_WALK: //walk
593 if (!m_IsInCooldown)
594 {
595 m_StaminaDelta = (GameConstants.STAMINA_GAIN_WALK_PER_SEC + CalcStaminaGainBonus());
596 }
597 break;
598
599 case DayZPlayerConstants.MOVEMENTIDX_IDLE: //idle
600 if (m_Player.IsRolling())
601 {
602 m_StaminaDelta = GameConstants.STAMINA_GAIN_ROLL_PER_SEC;
603 break;
604 }
605
606 if (!m_IsInCooldown)
607 {
608 m_StaminaDelta = (GameConstants.STAMINA_GAIN_IDLE_PER_SEC + CalcStaminaGainBonus());
609 }
610 break;
611
612 default:
613 if (!m_IsInCooldown)
614 {
615 m_StaminaDelta = GameConstants.STAMINA_GAIN_IDLE_PER_SEC;
616 }
617 break;
618 }
619 }
620
621 protected void StaminaProcessor_Ladder(HumanMovementState pHumanMovementState)
622 {
623 switch (pHumanMovementState.m_iMovement)
624 {
625 case 2: //climb up (fast)
626 m_StaminaDelta = -GameConstants.STAMINA_DRAIN_LADDER_FAST_PER_SEC * CfgGameplayHandler.GetSprintLadderStaminaModifier();
627 SetCooldown(GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION);
628 break;
629
630 case 1: //climb up (slow)
631 if (!m_IsInCooldown)
632 {
633 m_StaminaDelta = (GameConstants.STAMINA_GAIN_LADDER_PER_SEC + CalcStaminaGainBonus());
634 }
635 break;
636
637 default:
638 if (!m_IsInCooldown)
639 {
640 m_StaminaDelta = GameConstants.STAMINA_GAIN_IDLE_PER_SEC + CalcStaminaGainBonus();
641 }
642 break;
643 }
644 }
645
646 protected void StaminaProcessor_Swimming(HumanMovementState pHumanMovementState)
647 {
648 switch (pHumanMovementState.m_iMovement)
649 {
650 case 3: //swim fast
651 m_StaminaDelta = -GameConstants.STAMINA_DRAIN_SWIM_FAST_PER_SEC * CfgGameplayHandler.GetSprintSwimmingStaminaModifier();
652 SetCooldown(GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION);
653 break;
654
655
656 case 2: //swim slow
657 if (!m_IsInCooldown)
658 {
659 m_StaminaDelta = (GameConstants.STAMINA_GAIN_SWIM_PER_SEC + CalcStaminaGainBonus());
660 }
661 break;
662
663 default:
664 if (!m_IsInCooldown)
665 {
666 m_StaminaDelta = GameConstants.STAMINA_GAIN_IDLE_PER_SEC + CalcStaminaGainBonus();
667 }
668 break;
669 }
670 }
671
673 protected void SyncStamina(float stamina, float stamina_cap, bool cooldown)
674 {
675 m_Player.GetStatStamina().Set(m_Stamina);
677 pCtx.Write(m_Stamina);
678 pCtx.Write(m_StaminaCap);
679 pCtx.Write(m_IsInCooldown);
680 m_Player.SendSyncJuncture(DayZPlayerSyncJunctures.SJ_STAMINA,pCtx);
681 }
682
685 {
687
689 pCtx.Write(p.param1);
690 pCtx.Write(p.param2);
691 m_Player.SendSyncJuncture(DayZPlayerSyncJunctures.SJ_STAMINA_MISC,pCtx);
692 }
693
696 {
697 float depletionMultiplier;
698 float recoveryMultiplier;
699 if (!pCtx.Read(depletionMultiplier) || !pCtx.Read(recoveryMultiplier))
700 {
701 return;
702 }
703
704 m_StaminaDepletionMultiplier = depletionMultiplier;
705 m_StaminaRecoveryMultiplier = recoveryMultiplier;
706 }
707
709 {
711
713 EStaminaConsumers.HOLD_BREATH,
714 GameConstants.STAMINA_HOLD_BREATH_THRESHOLD_ACTIVATE,
715 GameConstants.STAMINA_HOLD_BREATH_THRESHOLD_DRAIN,
716 );
718 EStaminaConsumers.SPRINT,
719 CfgGameplayHandler.GetStaminaMinCap() + 15,
720 );
723 GameConstants.STAMINA_JUMP_THRESHOLD,
724 );
726 EStaminaConsumers.VAULT,
727 GameConstants.STAMINA_VAULT_THRESHOLD,
728 );
730 EStaminaConsumers.CLIMB,
731 GameConstants.STAMINA_CLIMB_THRESHOLD,
732 );
734 EStaminaConsumers.MELEE_HEAVY,
735 GameConstants.STAMINA_MELEE_HEAVY_THRESHOLD,
736 );
738 EStaminaConsumers.MELEE_EVADE,
739 GameConstants.STAMINA_MELEE_EVADE_THRESHOLD,
740 );
743 GameConstants.STAMINA_ROLL_THRESHOLD,
744 );
747 }
748
750 {
752
754 m_StaminaModifiers.RegisterExponentialEx(
755 EStaminaModifiers.HOLD_BREATH,
756 data,
757 );
758 m_StaminaModifiers.RegisterExponentialEx(
759 EStaminaModifiers.PUSH_CAR,
760 data,
761 );
762 m_StaminaModifiers.RegisterFixed(EStaminaModifiers.DROWN, 10);
763 m_StaminaModifiers.RegisterFixed(
765 GameConstants.STAMINA_DRAIN_JUMP * CfgGameplayHandler.GetObstacleTraversalStaminaModifier(),
766 );
767 m_StaminaModifiers.RegisterFixed(
768 EStaminaModifiers.VAULT,
769 GameConstants.STAMINA_DRAIN_VAULT * CfgGameplayHandler.GetObstacleTraversalStaminaModifier(),
770 );
771 m_StaminaModifiers.RegisterFixed(
772 EStaminaModifiers.CLIMB,
773 GameConstants.STAMINA_DRAIN_CLIMB * CfgGameplayHandler.GetObstacleTraversalStaminaModifier(),
774 );
775 m_StaminaModifiers.RegisterFixed(
776 EStaminaModifiers.MELEE_LIGHT,
777 GameConstants.STAMINA_DRAIN_MELEE_LIGHT * CfgGameplayHandler.GetMeleeStaminaModifier(),
778 );
779 m_StaminaModifiers.RegisterFixed(
780 EStaminaModifiers.MELEE_HEAVY,
781 GameConstants.STAMINA_DRAIN_MELEE_HEAVY * CfgGameplayHandler.GetMeleeStaminaModifier(),
782 );
783 m_StaminaModifiers.RegisterFixed(
784 EStaminaModifiers.OVERALL_DRAIN,
785 CfgGameplayHandler.GetStaminaMax(),
786 5.0,
787 );
788 m_StaminaModifiers.RegisterRandomized(
789 EStaminaModifiers.MELEE_EVADE,
790 3 * CfgGameplayHandler.GetMeleeStaminaModifier(),
791 GameConstants.STAMINA_DRAIN_MELEE_EVADE * CfgGameplayHandler.GetMeleeStaminaModifier(),
792 );
793 m_StaminaModifiers.RegisterFixed(EStaminaModifiers.ROLL, GameConstants.STAMINA_DRAIN_ROLL);
794 }
795
797 protected float CalcStaminaGainBonus()
798 {
799 if (m_StaminaDepletion > 0)
800 return 0;
801
802 if (m_Stamina > 25)
803 return Math.Min((m_Stamina/10),GameConstants.STAMINA_GAIN_BONUS_CAP); // exp version
804 else
805 return GameConstants.STAMINA_GAIN_BONUS_CAP; // linear version
806 }
807
808 protected void ApplyExhaustion()
809 {
811 HumanCommandAdditives ad = m_Player.GetCommandModifier_Additives();
812
813 float exhaustion_value = 1;
814 if (m_StaminaCap != 0)
815 {
816 exhaustion_value = 1 - ((m_Stamina / (m_StaminaCap * 0.01)) * 0.01);
817 }
818
819 exhaustion_value = Math.Min(1, exhaustion_value);
820 if (ad)
821 {
822 // do not apply exhaustion on local client if player is in ADS/Optics (camera shakes)
823 if (m_Player.GetInstanceType() == DayZPlayerInstanceType.INSTANCETYPE_CLIENT && (m_Player.IsInOptics() || m_Player.IsInIronsights()))
824 {
825 ad.SetExhaustion(0, true);
826 }
827 else
828 {
829 ad.SetExhaustion(exhaustion_value, true);
830 }
831 }
832 }
833
835 protected void CheckStaminaState()
836 {
837 if (m_Stamina <= 0)
838 {
839 m_StaminaDepleted = true;
841 if (!m_IsInCooldown)
842 {
843 // set this only once
844 SetCooldown(GameConstants.STAMINA_REGEN_COOLDOWN_EXHAUSTION);
845 }
846 }
847 else
848 {
849 m_StaminaDepleted = false;
850 }
851 }
852
854 protected void SetCooldown(float time, int modifier = -1)
855 {
856 if ( m_StaminaDepleted || m_Stamina <= 0.0 )
857 {
858 ResetCooldown(modifier);
859 return;
860 }
861
862 m_IsInCooldown = true;
863
864 Timer timer;
865 if (m_TimerMap.Find(modifier, timer) && timer.IsRunning())
866 {
867 timer.Stop();
868 }
869 else
870 {
871 timer = new Timer;
872 m_TimerMap.Set(modifier,timer);
873 }
874 timer.Run(time, this, "ResetCooldown", new Param1<int>( modifier ));
875 //Print(m_TimerMap.Count());
876 }
877
878 protected void ResetCooldown(int modifier = -1)
879 {
880 StaminaModifier sm = m_StaminaModifiers.GetModifierData(modifier);
881 if (sm)
882 {
883 //Print(modifier);
884 //Error("Error: No StaminaModifier found! | StaminaHandler | ResetCooldown");
885 sm.SetStartTime(-1);
886 sm.ResetRunTime();
887 sm.SetInUse(false);
888 }
889 m_IsInCooldown = false;
890 }
891
893 {
894
895 }
896
897 // ---------------------------------------------------
902
907
908 void SetStamina(float stamina_value)
909 {
910 m_Stamina = Math.Clamp(stamina_value, 0, CfgGameplayHandler.GetStaminaMax());
912 }
913
915 {
916 return m_Stamina;
917 }
918
920 {
921 return m_Stamina / GetStaminaMax();
922 }
923
925 {
926 return m_StaminaSynced;
927 }
928
930 {
931 return GetSyncedStamina() / GetStaminaMax();
932 }
933
935 {
936 return m_StaminaCap;
937 }
938
940 {
941 return CfgGameplayHandler.GetStaminaMax();
942 }
943
944 //obsolete, use ActivateDepletionModifier/DeactivateDepletionModifier instead
952 //obsolete, use ActivateRecoveryModifier/DeactivateRecoveryModifier instead
960
965
967 {
969 }
970
971 void DepleteStaminaEx(EStaminaModifiers modifier, float dT = -1, float coef = 1.0)
972 {
973 #ifdef DIAG_DEVELOPER
974 if (m_StaminaDisabled)
975 return;
976 #endif
977 float val = 0.0;
978 float current_time = m_Player.GetSimulationTimeStamp();
979 float valueProgress;
980 StaminaModifier sm = m_StaminaModifiers.GetModifierData(modifier);
981
982 // select by modifier type and drain stamina
983 switch (sm.GetType())
984 {
985 case m_StaminaModifiers.FIXED:
986 if (dT == -1)
987 {
988 dT = 1;
989 }
990 m_StaminaDepletion += sm.GetMaxValue() * dT * coef;
991
992 break;
993
994 case m_StaminaModifiers.RANDOMIZED:
995 val = Math.RandomFloat(sm.GetMinValue(), sm.GetMaxValue());
996 m_StaminaDepletion += val * coef;
997
998 break;
999
1000 case m_StaminaModifiers.LINEAR:
1001 if (!sm.IsInUse())
1002 {
1003 sm.SetStartTime(current_time + sm.GetStartTimeAdjustment()/dT);
1004 sm.SetRunTimeTick(dT);
1005 sm.SetInUse(true);
1006 }
1007 valueProgress = Math.Clamp((current_time - sm.GetStartTime())/sm.GetDurationAdjusted(), 0, 1 );
1008 val = Math.Lerp(sm.GetMinValue(), sm.GetMaxValue(), valueProgress);
1009 m_StaminaDepletion += val * coef;
1010
1011 break;
1012
1013 case m_StaminaModifiers.EXPONENTIAL:
1015 if (!Class.CastTo(smex,sm))
1016 {
1017 ErrorEx("StaminaModifierExponential not found for modifier type: " + sm.GetType());
1018 break;
1019 }
1020
1021 if (!smex.IsInUse())
1022 {
1023 smex.SetStartTime(current_time + smex.GetStartTimeAdjustment()/dT);
1024 smex.SetRunTimeTick(dT);
1025 smex.SetInUse(true);
1026 }
1027 valueProgress = Math.Clamp((current_time - smex.GetStartTime())/smex.GetDurationAdjusted(), 0, 1 );
1028 float exp;
1029 if (Math.AbsFloat(smex.GetBaseValue()) < 1)
1030 {
1031 exp = 1 - Math.Lerp(0, smex.GetExponent(), valueProgress);
1032 val = Math.Pow(smex.GetBaseValue(),exp);
1033 }
1034 else
1035 {
1036 exp = Math.Lerp(Math.Min(0, smex.GetExponent()), Math.Max(0, smex.GetExponent()), valueProgress);
1037 val = Math.Pow(smex.GetBaseValue(),exp) + smex.GetBaseValue() - 1;
1038 }
1039
1040 m_StaminaDepletion += val * smex.GetMultiplier() * coef;
1041
1042 break;
1043 }
1044
1046 SetCooldown(sm.GetCooldown(),modifier);
1047
1049 m_StaminaDepletion = Math.Clamp(m_StaminaDepletion, 0, CfgGameplayHandler.GetStaminaMax());
1050 }
1051
1052 #ifdef DIAG_DEVELOPER
1053 void SetStaminaDisabled(bool value)
1054 {
1055 m_StaminaDisabled = value;
1056 }
1057 #endif
1058
1060 //Deprecated code playpen//
1063 void DepleteStamina(EStaminaModifiers modifier, float dT = -1)
1064 {
1065 DepleteStaminaEx(modifier,dT);
1066 }
1067}
eBleedingSourceType m_Type
eBleedingSourceType GetType()
float m_Duration
proto native bool IsMultiplayer()
proto native bool IsServer()
Super root of all classes in Enforce script.
Definition enscript.c:11
Definition mask.c:2
Definition enmath.c:7
Base Param Class with no parameters. Used as general purpose parameter overloaded with Param1 to Para...
Definition param.c:12
Serialization general interface. Serializer API works with:
Definition serializer.c:56
void RegisterConsumer(EStaminaConsumers consumer, float threshold, float depletion_threshold=-1)
ref map< EStaminaConsumers, ref StaminaConsumer > m_StaminaConsumers
bool HasEnoughStaminaToStart(EStaminaConsumers consumer, float curStamina, bool isDepleted, float cap)
bool HasEnoughStaminaFor(EStaminaConsumers consumer, float curStamina, bool isDepleted, float cap)
float m_StaminaDepletionMultiplier
Timer GetCooldownTimer(int modifier)
void StaminaProcessor_Ladder(HumanMovementState pHumanMovementState)
void RegisterStaminaModifiers()
ref HumanMovementState m_State
void StaminaProcessor_Swimming(HumanMovementState pHumanMovementState)
float GetDepletionMultiplier()
void RecalculateRecoveryMultiplier()
void DepleteStamina(EStaminaModifiers modifier, float dT=-1)
Deprecated.
void DepleteStaminaEx(EStaminaModifiers modifier, float dT=-1, float coef=1.0)
void SetDepletionMultiplier(float val)
void SetRecoveryMultiplier(float val)
float m_StaminaRecoveryMultiplier
ref set< EStaminaMultiplierTypes > m_ActiveDepletionModifiers
void SyncAdditionalStaminaInfo(Param par)
Method to sync more info for stamina manager. Template parameter means it is very extendable for furt...
ref StaminaModifiers m_StaminaModifiers
void OnSyncJuncture(int pJunctureID, ParamsReadContext pCtx)
called from PlayerBase - syncs stamina values on server with client AND sets the value to match on se...
void CheckStaminaState()
check if the stamina is completely depleted
ref map< int, ref Timer > m_TimerMap
void DeactivateRecoveryModifier(EStaminaMultiplierTypes type)
void RegisterStaminaConsumers()
bool HasEnoughStaminaFor(EStaminaConsumers consumer)
void StaminaHandler(PlayerBase player)
PlayerBase m_Player
float GetRecoveryMultiplier()
void OnRPC(float stamina, float stamina_cap, bool cooldown)
deprecated use, StaminaHandler uses SyncJunctures now
float GetSyncedStamina()
float CalcStaminaGainBonus()
Calulates stamina regain bonus coef based on current stamina cap and level.
ref set< EStaminaMultiplierTypes > m_ActiveRecoveryModifiers
ref Param3< float, float, bool > m_StaminaParams
void RecalculateDepletionMultiplier()
void StaminaProcessor_Move(HumanMovementState pHumanMovementState)
float GetStaminaNormalized()
float GetSyncedStaminaNormalized()
void DeactivateDepletionModifier(EStaminaMultiplierTypes type)
bool m_StaminaDepleted
DEPRECATED.
bool HasEnoughStaminaToStart(EStaminaConsumers consumer)
void SetCooldown(float time, int modifier=-1)
set cooldown timer between each consume of stamina
void SetStamina(float stamina_value)
void ReadAdditionalStaminaInfo(ParamsReadContext pCtx)
Order of read parameters must match the order of writing above.
ref StaminaConsumers m_StaminaConsumers
void ActivateDepletionModifier(EStaminaMultiplierTypes type)
SHumanCommandMoveSettings m_HumanMoveSettings
void ResetCooldown(int modifier=-1)
void SyncStamina(float stamina, float stamina_cap, bool cooldown)
stamina sync - server part
ref map< EStaminaMultiplierTypes, float > m_RegisteredRecoveryModifiers
void ActivateRecoveryModifier(EStaminaMultiplierTypes type)
ref map< EStaminaMultiplierTypes, float > m_RegisteredDepletionModifiers
void Update(float deltaT, int pCurrentCommandID)
override float GetStartTimeAdjustment()
void SetData(SMDataExponential data)
override float GetDurationAdjusted()
ref SMDataExponential m_SMDataEx
DayZPlayerInstanceType
defined in C++
DayZPlayerConstants
defined in C++
Definition dayzplayer.c:602
EStaminaConsumers
EStaminaModifiers
proto native CGame GetGame()
void Error(string err)
Messagebox with error message.
Definition endebug.c:90
enum ShapeType ErrorEx
float GetRunTime()
Definition tools.c:323
float GetDuration()
Definition tools.c:313
class SHumanGlobalSettings SHumanCommandMoveSettings()
enum EObjectTemperatureState m_State
class PlayerStatBase m_MinValue
T m_MaxValue
void StaminaConsumer(float threshold, float threshold2, bool state)
const int RANDOMIZED
m_ActivationThreshold
EStaminaMultiplierTypes
DROWNING
float GetMinValue()
void SetMaxValue(float val)
const int LINEAR
DISEASE_PNEUMONIA
float m_ProgressTime
void StaminaModifier(int type, float min, float max, float cooldown, float startTime=0, float duration=0)
void RegisterLinear(EStaminaModifiers modifier, float startValue, float endValue, float startTime, float duration, float cooldown=GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION)
register lerped modifier - depletes stamina for startValue, and, after a startTime,...
void SetActivationThreshold(float threshold)
void ResetRunTime()
FATIGUE
float m_Tick
void SetStartTime(float val)
void SetInUse(bool val)
StaminaModifierExponential FIXED
m_InUse
void StaminaConsumers()
void SetDrainThreshold(float threshold)
float m_StartTimeAdjustment
void SetState(bool state)
ref map< EStaminaModifiers, ref StaminaModifier > m_StaminaModifiers
void RegisterExponentialEx(EStaminaModifiers modifier, SMDataExponential data)
register exponential modifier, extended parameters
float GetMaxValue()
float GetStartTimeAdjustment()
bool IsInUse()
float m_Multiplier
float m_StartTime
VOMIT_EXHAUSTION
float GetDrainThreshold()
const int EXPONENTIAL
float GetActivationThreshold()
void SetRunTimeTick(float val)
void StaminaModifiers()
void SetMinValue(float val)
void RegisterExponential(EStaminaModifiers modifier, float startValue, float exponent, float startTime, float duration, float cooldown=GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION)
register exponential modifier - depletes stamina for startValue, and, after a startTime,...
void RegisterFixed(EStaminaModifiers modifier, float value, float cooldown=GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION)
register single value modifier - depletes stamina for that value
EPINEPHRINE
float GetStartTime()
void SetCooldown(float val)
StaminaModifier GetModifierData(EStaminaModifiers modifier)
MASK
float GetCooldown()
float GetDurationAdjusted()
float m_Cooldown
void AddRunTime(float val)
void RegisterRandomized(EStaminaModifiers modifier, float minValue, float maxValue, float cooldown=GameConstants.STAMINA_REGEN_COOLDOWN_DEPLETION)
register randomized modifier - stamina will be depleted by value between min and max value;