DayZ 1.27
DayZ Explorer by KGB
 
Загрузка...
Поиск...
Не найдено
Weapon_Base.c
См. документацию.
1
5{
6 int m_action;
8 void AbilityRecord (int a, int at) { m_action = a; m_actionType = at; }
9};
10
32
38class Weapon_Base extends Weapon
39{
41 const int SAMF_DEFAULT = WeaponWithAmmoFlags.CHAMBER | WeaponWithAmmoFlags.MAX_CAPACITY_MAG;
43 const int SAMF_RNG = WeaponWithAmmoFlags.CHAMBER_RNG | WeaponWithAmmoFlags.QUANTITY_RNG;
45 const float VALIDATE_DELAY = 5.0;
46
47 protected const float DEFAULT_DAMAGE_ON_SHOT = 0.05;
49 protected ref WeaponFSM m_fsm;
50 protected bool m_isJammed = false;
51 protected bool m_LiftWeapon = false;
52 protected bool m_BayonetAttached;
53 protected bool m_ButtstockAttached;
54 protected bool m_Charged = false;
55 protected bool m_WeaponOpen = false;
56 protected bool m_WasIronSight;
57 protected int m_BurstCount;
60 protected int m_weaponAnimState = -1;
62 protected int m_weaponHideBarrelIdx = -1; //index in simpleHiddenSelections cfg array
63 protected float m_DmgPerShot = 0; //default is set to zero, since C++ solution has been implemented. See 'damageBarrel' and 'barrelArmor' in configs.
64 protected float m_WeaponLength;
66 protected float m_ShoulderDistance;
68 protected int m_LastLiftHit;
72 protected float m_ChanceToJamSync = 0;
76 private float m_coolDownTime = 0;
77
79 {
80 //m_DmgPerShot = ConfigGetFloat("damagePerShot");
81 m_BayonetAttached = false;
82 m_ButtstockAttached = false;
83 m_WasIronSight = true; // initially uses ironsights by default
86 m_BurstCount = 0;
88 if (GetGame().IsClient())
89 {
91 }
92
93 if ( ConfigIsExisting("simpleHiddenSelections") )
94 {
95 TStringArray selectionNames = new TStringArray;
96 ConfigGetTextArray("simpleHiddenSelections",selectionNames);
97 m_weaponHideBarrelIdx = selectionNames.Find("hide_barrel");
98 m_magazineSimpleSelectionIndex = selectionNames.Find("magazine");
99
100 int bulletIndex = selectionNames.Find("bullet");
101 if ( bulletIndex != -1 )
102 {
103 m_bulletSelectionIndex.Insert(bulletIndex);
104
105 for (int i = 2; i < 100; i++)
106 {
107 bulletIndex = selectionNames.Find(string.Format("bullet%1",i));
108 if (bulletIndex != -1)
109 {
110 m_bulletSelectionIndex.Insert(bulletIndex);
111 }
112 else
113 {
114 break;
115 }
116 }
117 }
118 }
119
124 if (GetGame().IsServer())
125 {
127 }
129 }
130
132
133 override void EEInit()
134 {
135 super.EEInit();
136
137 if (GetGame().IsServer())
138 {
140 }
141 }
142
144 {
145 m_fsm.SetInitialState(initState);
146 SetCharged(!initState.IsDischarged());
147 SetWeaponOpen(!initState.IsWeaponOpen());
148 SetGroundAnimFrameIndex(initState.m_animState);
149 }
150
152 {
153 return m_Charged;
154 }
155
156 void SetCharged(bool value)
157 {
158 m_Charged = value;
159 }
160
162 {
163 return m_WeaponOpen;
164 }
165
166 void SetWeaponOpen(bool value)
167 {
168 m_WeaponOpen = value;
169 }
170
171 override protected float GetWeightSpecialized(bool forceRecalc = false)
172 {
173 float baseWeight = GetInventoryAndCargoWeight(forceRecalc);
174 float ammoWeight;
175 float ammoDamage;
176 string bulletTypeName, ammoTypeName;
177
178 int muzzleCount = GetMuzzleCount();
179 #ifdef DEVELOPER
180 if (WeightDebug.m_VerbosityFlags & WeightDebugType.RECALC_FORCED)
181 {
182 WeightDebugData data1 = WeightDebug.GetWeightDebug(this);
183 data1.SetCalcDetails("TWPN: " + m_ConfigWeight+"(item weight) + " + baseWeight +"(contents weight)" );
184 }
185 #endif
186 for (int muzzleIndex = 0; muzzleIndex < muzzleCount; muzzleIndex++)
187 {
188 //chamber weight
189 if (!IsChamberEmpty(muzzleIndex))
190 {
191 ammoTypeName = GetChamberAmmoTypeName(muzzleIndex);
192 ammoWeight += g_Game.ConfigGetFloat(string.Format("CfgMagazines %1 weight", ammoTypeName));
193
194 #ifdef DEVELOPER
195 if (WeightDebug.m_VerbosityFlags & WeightDebugType.RECALC_FORCED)
196 {
197 WeightDebugData data2 = WeightDebug.GetWeightDebug(this);
198 data2.AddCalcDetails( g_Game.ConfigGetFloat("CfgMagazines " + ammoTypeName + " weight").ToString() +"(chamber weight)");
199 }
200 #endif
201 }
202
203 //correctly calculates internal magazine weight based on the ammo type of each bullet
204 if (HasInternalMagazine(muzzleIndex))
205 {
206 #ifdef DEVELOPER
207 float debugInternalMagWeight;
208 #endif
209 int cartridgeCount = GetInternalMagazineCartridgeCount(muzzleIndex);
210 for (int cartridgeIndex = 0; cartridgeIndex < cartridgeCount; cartridgeIndex++)
211 {
212 GetInternalMagazineCartridgeInfo(muzzleIndex, cartridgeIndex, ammoDamage, bulletTypeName);
213 ammoWeight += Ammunition_Base.GetAmmoWeightByBulletType(bulletTypeName);
214 #ifdef DEVELOPER
215 debugInternalMagWeight += g_Game.ConfigGetFloat("CfgMagazines " + ammoTypeName + " weight");
216 #endif
217 }
218 #ifdef DEVELOPER
219
220 if (WeightDebug.m_VerbosityFlags & WeightDebugType.RECALC_FORCED)
221 {
222 WeightDebugData data3 = WeightDebug.GetWeightDebug(this);
223 data3.AddCalcDetails(debugInternalMagWeight.ToString()+ "(internal mag weight)");
224 }
225 #endif
226 }
227
228 }
229 return ammoWeight + baseWeight + GetConfigWeightModified();
230 }
231
233
234 bool CanProcessAction(int action, int actionType)
235 {
236 return false; // @TODO
237 }
238
244 bool HasActionAbility(int action, int actionType)
245 {
246 int count = GetAbilityCount();
247 for (int i = 0; i < count; ++i)
248 {
249 AbilityRecord rec = GetAbility(i);
250 if (rec.m_action == action && rec.m_actionType == actionType)
251 return true;
252 }
253 return false;
254 }
255
258 int GetAbilityCount() { return m_abilities.Count(); }
263 AbilityRecord GetAbility(int index) { return m_abilities.Get(index); }
264
268 bool CanProcessWeaponEvents() { return m_fsm && m_fsm.IsRunning(); }
269
274 WeaponStateBase GetCurrentState() { return m_fsm.GetCurrentState(); }
275
280 {
281 return CanProcessWeaponEvents() && GetCurrentState().IsWaitingForActionFinish();
282 }
283
284 bool IsIdle()
285 {
286 return CanProcessWeaponEvents() && GetCurrentState().IsIdle();
287 }
288
294 {
296
297 // @NOTE: synchronous events not handled by fsm
298 if (e.GetEventID() == WeaponEventID.SET_NEXT_MUZZLE_MODE)
299 {
300 SetNextWeaponMode(GetCurrentMuzzle());
301 return true;
302 }
303
304 if (m_fsm.ProcessEvent(e) == ProcessEventResult.FSM_OK)
305 return true;
306
307 //if (LogManager.IsWeaponLogEnable()) { wpnDebugPrint("FSM refused to process event (no transition): src=" + GetCurrentState().ToString() + " event=" + e.ToString()); }
308 return false;
309 }
310
314 {
316
318 m_fsm.ProcessAbortEvent(e, aa);
319 return aa == ProcessEventResult.FSM_OK;
320 }
321
322 bool CanChamberBullet(int muzzleIndex, Magazine mag)
323 {
324 return CanChamberFromMag(muzzleIndex, mag) && (!IsChamberFull(muzzleIndex) || IsChamberFiredOut(muzzleIndex) || !IsInternalMagazineFull(muzzleIndex));
325 }
326
327 void SetWeaponAnimState(int state)
328 {
329 m_weaponAnimState = state;
330 SetGroundAnimFrameIndex(state);
331 }
333 {
334 if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[wpnfsm] " + Object.GetDebugName(this) + " resetting anim state: " + typename.EnumToString(PistolAnimState, m_weaponAnimState) + " --> " + typename.EnumToString(PistolAnimState, -1));
336 }
338
339 void EEFired(int muzzleType, int mode, string ammoType)
340 {
341 if ( !GetGame().IsDedicatedServer() )
342 {
343 ItemBase suppressor = GetAttachedSuppressor();
344
345 // Muzzle flash & overheating effects
346 ItemBase.PlayFireParticles(this, muzzleType, ammoType, this, suppressor, "CfgWeapons" );
347 IncreaseOverheating(this, ammoType, this, suppressor, "CfgWeapons");
348
349 if (suppressor)
350 {
351 ItemBase.PlayFireParticles(this, muzzleType, ammoType, suppressor, NULL, "CfgVehicles" );
352 suppressor.IncreaseOverheating(this, ammoType, this, suppressor, "CfgVehicles");
353 }
354 }
355
356 //obsolete, replaced by C++ solution!
357/*
358 if (GetGame().IsServer())
359 {
360 AddHealth("","Health",-m_DmgPerShot); //damages weapon
361 if (suppressor)
362 suppressor.AddHealth("","Health",-m_DmgPerShot); //damages suppressor; TODO add suppressor damage coeficient/parameter (?) to suppressors/weapons (?)
363 }
364*/
365 //JamCheck(muzzleType);
366
367 #ifdef DIAG_DEVELOPER
368 MiscGameplayFunctions.UnlimitedAmmoDebugCheck(this);
369 #endif
370 }
371
372 bool JamCheck(int muzzleIndex )
373 {
374 PlayerBase player = PlayerBase.Cast(GetHierarchyRootPlayer());
375 if ( player )
376 {
377 float rnd = player.GetRandomGeneratorSyncManager().GetRandom01(RandomGeneratorSyncUsage.RGSJam);
378 //Print("Random Jam - " + rnd);
379 if (rnd < GetSyncChanceToJam())
380 return true;
381 }
382 return false;
383 }
384
385 void ShowBullet(int muzzleIndex)
386 {
387 if ( m_bulletSelectionIndex.Count() > muzzleIndex )
388 {
389 SetSimpleHiddenSelectionState(m_bulletSelectionIndex[muzzleIndex],1);
390 }
391 else
392 SelectionBulletShow();
393 }
394
395 void HideBullet(int muzzleIndex)
396 {
397 if ( m_bulletSelectionIndex.Count() > muzzleIndex )
398 {
399 SetSimpleHiddenSelectionState(m_bulletSelectionIndex[muzzleIndex],0);
400 }
401 else
402 SelectionBulletHide();
403 }
404
405 bool IsJammed() { return m_isJammed; }
406 bool CanEjectBullet() {return true;}
407 void SetJammed(bool value) { m_isJammed = value; }
410 {
411 int level = GetHealthLevel();
412
413 if (level >= 0 && level < m_ChanceToJam.Count())
414 return m_ChanceToJam[level];
415 else
416 return 0.0;
417 }
418
419 void SyncSelectionState(bool has_bullet, bool has_mag)
420 {
421 if (has_bullet)
422 {
423 string chamberedAmmoTypeName;
424 float chamberedAmmoDmg;
425
426 if ( GetCartridgeInfo(0, chamberedAmmoDmg, chamberedAmmoTypeName) )
427 {
428 EffectBulletShow(0, chamberedAmmoDmg, chamberedAmmoTypeName);
429 }
430 //ShowBullet(0);
431 SelectionBulletShow();
432 }
433 else
434 {
435 //HideBullet(0);
436 SelectionBulletHide();
437 EffectBulletHide(0);
438 }
439
440 if (has_mag)
441 ShowMagazine();
442 else
443 HideMagazine();
444 }
445
446 /*override void EEOnAfterLoad()
447 {
448 super.EEOnAfterLoad();
449
450 string chamberedAmmoTypeName;
451 float chamberedAmmoDmg;
452
453 if ( GetCartridgeInfo(0, chamberedAmmoDmg, chamberedAmmoTypeName) )
454 {
455 EffectBulletShow(0, chamberedAmmoDmg, chamberedAmmoTypeName);
456 }
457
458 }*/
459
461 {
462 int nMuzzles = GetMuzzleCount();
463 for (int i = 0; i < nMuzzles; ++i)
464 {
465 if (IsChamberFull(i))
466 {
467 ShowBullet(i);
468 float damage;
469 string ammoTypeName;
470 GetCartridgeInfo(i, damage, ammoTypeName);
471 EffectBulletShow(i, damage, ammoTypeName);
472 }
473 else
474 {
475 HideBullet(i);
476 EffectBulletHide(i);
477 }
478
479 Magazine mag = GetMagazine(i);
480 if (mag)
481 ShowMagazine();
482 else
483 HideMagazine();
484 }
485 }
486
487 override bool OnStoreLoad(ParamsReadContext ctx, int version)
488 {
489 if ( !super.OnStoreLoad(ctx, version) )
490 return false;
491
492
493 if (version >= 113)
494 {
495 int current_muzzle = 0;
496 if (!ctx.Read(current_muzzle))
497 {
498 Error("Weapon.OnStoreLoad " + this + " cannot read current muzzle!");
499 return false;
500 }
501
502 if (current_muzzle >= GetMuzzleCount() || current_muzzle < 0)
503 Error("Weapon.OnStoreLoad " + this + " trying to set muzzle index " + current_muzzle + " while it only has " + GetMuzzleCount() + " muzzles!");
504 else
505 SetCurrentMuzzle(current_muzzle);
506 }
507
508 if (version >= 105)
509 {
510 int mode_count = 0;
511 if (!ctx.Read(mode_count))
512 {
513 Error("Weapon.OnStoreLoad " + this + " cannot read mode count!");
514 return false;
515 }
516
517 for (int m = 0; m < mode_count; ++m)
518 {
519 int mode = 0;
520 if (!ctx.Read(mode))
521 {
522 Error("Weapon.OnStoreLoad " + this + " cannot read mode[" + m + "]");
523 return false;
524 }
525
526 if (LogManager.IsWeaponLogEnable()) { wpnDebugPrint("[wpnfsm] " + Object.GetDebugName(this) + " OnStoreLoad - loaded muzzle[" + m + "].mode = " + mode); }
527 SetCurrentMode(m, mode);
528 }
529 }
530
531 if ( version >= 106 )
532 {
533 if ( !ctx.Read(m_isJammed) )
534 {
535 Error("Weapon.OnStoreLoad cannot load jamming state");
536 return false;
537 }
538 }
539
540 if (m_fsm)
541 {
542 if (!m_fsm.OnStoreLoad(ctx, version))
543 return false;
544
545 WeaponStableState wss = WeaponStableState.Cast(m_fsm.GetCurrentState());
546 if (wss)
547 {
548 SetGroundAnimFrameIndex(wss.m_animState);
549 }
550
551 }
552 else
553 {
554 int dummy = 0;
555 if (!ctx.Read(dummy))
556 return false;
557 }
558
559 return true;
560 }
561
563 {
564 if (m_fsm && m_fsm.IsRunning())
565 {
566 if (m_fsm.SaveCurrentFSMState(ctx))
567 {
568 if (LogManager.IsWeaponLogEnable()) { wpnDebugPrint("[wpnfsm] " + Object.GetDebugName(this) + " Weapon=" + this + " state saved."); }
569 }
570 else
571 Error("[wpnfsm] " + Object.GetDebugName(this) + " Weapon=" + this + " state NOT saved.");
572 }
573 else
574 Error("[wpnfsm] " + Object.GetDebugName(this) + " Weapon.SaveCurrentFSMState: trying to save weapon without FSM (or uninitialized weapon) this=" + this + " type=" + GetType());
575 }
576
578 {
579 if (m_fsm)
580 {
581 if (m_fsm.LoadCurrentFSMState(ctx, version))
582 {
584 if (state)
585 {
586 SyncSelectionState(state.HasBullet(), state.HasMagazine());
587 state.SyncAnimState();
588 if (LogManager.IsWeaponLogEnable()) { wpnDebugPrint("[wpnfsm] " + Object.GetDebugName(this) + " Weapon=" + this + " stable state loaded and synced."); }
589 return true;
590 }
591 else
592 {
593 if (LogManager.IsWeaponLogEnable()) { wpnDebugPrint("[wpnfsm] " + Object.GetDebugName(this) + " Weapon=" + this + " unstable/error state loaded."); }
594 return false;
595 }
596 }
597 else
598 {
599 Error("[wpnfsm] " + Object.GetDebugName(this) + " Weapon=" + this + " did not load.");
600 return false;
601 }
602 }
603 else
604 {
605 Error("[wpnfsm] " + Object.GetDebugName(this) + " Weapon.LoadCurrentFSMState: trying to load weapon without FSM (or uninitialized weapon) this=" + this + " type=" + GetType());
606 return false;
607 }
608 }
609
610 override void AfterStoreLoad()
611 {
612 if (m_fsm)
613 {
614 int mi = GetCurrentMuzzle();
615 Magazine mag = GetMagazine(mi);
616 bool has_mag = mag != null;
617 bool has_bullet = !IsChamberEmpty(mi);
618 SyncSelectionState(has_bullet, has_mag);
619 }
620 }
621
623 {
624 super.OnStoreSave(ctx);
625
626 // current muzzle added in version 113
627 int current_muzzle = GetCurrentMuzzle();
628 ctx.Write(current_muzzle);
629
630 // fire mode added in version 105
631 int mode_count = GetMuzzleCount();
632 ctx.Write(mode_count);
633 for (int m = 0; m < mode_count; ++m)
634 ctx.Write(GetCurrentMode(m));
635
636 ctx.Write(m_isJammed);
637
638 if (m_fsm)
639 m_fsm.OnStoreSave(ctx);
640 else
641 {
642 int dummy = 0;
643 ctx.Write(dummy);
644 }
645 }
646
651 {
652 if (m_fsm)
653 return m_fsm.GetInternalStateID();
654 return 0;
655 }
656
661 {
662 if (m_fsm)
663 {
664 return m_fsm.GetCurrentStableStateID();
665 }
666 return 0;
667 }
668
674 {
675 if (m_fsm)
676 {
677 int mi = GetCurrentMuzzle();
678 Magazine mag = GetMagazine(mi);
679 bool has_mag = mag != null;
680 bool has_bullet = !IsChamberEmpty(mi);
681 bool has_jam = IsJammed();
682 array<MuzzleState> muzzleStates = GetMuzzleStates();
683 m_fsm.RandomizeFSMStateEx(muzzleStates, has_mag, has_jam);
685 }
686 }
687
690 {
691 array<MuzzleState> muzzleStates = new array<MuzzleState>;
692
693 int nMuzzles = GetMuzzleCount();
694 for (int i = 0; i < nMuzzles; ++i)
695 {
696 MuzzleState state = MuzzleState.U;
697 if (IsChamberFiredOut(i))
698 state = MuzzleState.F;
699 else if (IsChamberFull(i))
700 state = MuzzleState.L;
701 else if (IsChamberEmpty(i))
702 state = MuzzleState.E;
703 else
704 ErrorEx(string.Format("Unable to identify chamber state of muzzle %1", i));
705
706 muzzleStates.Insert(state);
707 }
708
709 return muzzleStates;
710 }
711
718
726 static Weapon_Base CreateWeaponWithAmmo( string weaponType, string magazineType = "", int flags = WeaponWithAmmoFlags.CHAMBER )
727 {
728 Weapon_Base wpn = Weapon_Base.Cast(GetGame().CreateObjectEx( weaponType, vector.Zero, ECE_PLACE_ON_SURFACE ));
729
730 if ( !wpn )
731 {
732 ErrorEx(string.Format("%1 does not exist or is not a weapon.", weaponType));
733 return null;
734 }
735
736 wpn.SpawnAmmo(magazineType, flags);
737 return wpn;
738 }
739
746 bool SpawnAmmo( string magazineType = "", int flags = WeaponWithAmmoFlags.CHAMBER )
747 {
748 // Attempt internal mag
749 if ( HasInternalMagazine(-1) && FillInnerMagazine(magazineType, flags) )
750 return true;
751
752 // Attempt mag attachment
753 if ( GetMagazineTypeCount(0) > 0 && SpawnAttachedMagazine(magazineType, flags) )
754 return true;
755
756 // Attempt chamber
757 if ( FillChamber(magazineType, flags) )
758 return true;
759
760 return false;
761 }
762
769 Magazine SpawnAttachedMagazine( string magazineType = "", int flags = WeaponWithAmmoFlags.CHAMBER )
770 {
771 // Check if the gun has any magazines registered in config
772 if ( GetMagazineTypeCount(0) == 0 )
773 {
774 ErrorEx(string.Format("No 'magazines' config entry for %1.", this));
775 return null;
776 }
777
778 // Randomize when no specific one is given
779 if ( magazineType == "" )
780 {
781 if ( flags & WeaponWithAmmoFlags.MAX_CAPACITY_MAG)
782 magazineType = GetMaxMagazineTypeName(0);
783 else
784 magazineType = GetRandomMagazineTypeName(0);
785 }
786
787 EntityAI magAI = GetInventory().CreateAttachment(magazineType);
788 if (!magAI)
789 {
790 ErrorEx(string.Format("Failed to create and attach %1 to %2", GetDebugName(magAI), this));
791 return null;
792 }
793
794 Magazine mag;
795 if (!CastTo(mag, magAI))
796 {
797 ErrorEx(string.Format("Expected magazine, created: %1", GetDebugName(magAI)));
798 return null;
799 }
800
801 // Decide random quantity when enabled
802 if (flags & WeaponWithAmmoFlags.QUANTITY_RNG)
803 mag.ServerSetAmmoCount(Math.RandomIntInclusive(0, mag.GetAmmoMax()));
804
805 // Fill chamber when flagged
806 bool chamberRng = (flags & WeaponWithAmmoFlags.CHAMBER_RNG);
807 bool chamber = (flags & WeaponWithAmmoFlags.CHAMBER) || chamberRng;
808 if (chamber || chamberRng)
809 {
810 FillChamber(magazineType, flags);
811 }
812
813 // FSM cares about magazine state
815 Synchronize();
816
817 return mag;
818 }
819
827 bool FillInnerMagazine( string ammoType = "", int flags = WeaponWithAmmoFlags.CHAMBER )
828 {
829 // Don't try to fill it when there are none
830 if (!HasInternalMagazine(-1))
831 return false;
832
833 // Make sure the given ammoType is actually useable
834 if (ammoType != "")
835 {
836 if (!AmmoTypesAPI.MagazineTypeToAmmoType(ammoType, ammoType))
837 return false;
838 }
839
840
841 bool didSomething = false;
842 int muzzCount = GetMuzzleCount();
843
844 bool ammoRng = ammoType == "";
845 bool ammoFullRng = ammoRng && (flags & WeaponWithAmmoFlags.AMMO_MAG_RNG);
846
847 // No full RNG flag, so pick one random and use only this one
848 if (ammoRng && !ammoFullRng)
849 ammoType = GetRandomChamberableAmmoTypeName(0);
850
851 // Fill the internal magazine
852 for (int i = 0; i < muzzCount; ++i)
853 {
854 int ammoCount = GetInternalMagazineMaxCartridgeCount(i);
855
856 // Decide random quantity when enabled
857 if ( flags & WeaponWithAmmoFlags.QUANTITY_RNG )
858 ammoCount = Math.RandomIntInclusive(0, ammoCount);
859
860 // Only do the things when there is actually ammo to fill
861 if (ammoCount > 0)
862 {
863 // Push in the cartridges
864 for (int j = 0; j < ammoCount; ++j)
865 {
866 // Full random, decide a new one for every cartridge
867 if ( ammoFullRng )
868 ammoType = GetRandomChamberableAmmoTypeName(i);
869
870 PushCartridgeToInternalMagazine(i, 0, ammoType);
871 didSomething = true;
872 }
873 }
874 }
875
876 // Call the chamber method if asked for
877 bool chamber = (flags & WeaponWithAmmoFlags.CHAMBER) || (flags & WeaponWithAmmoFlags.CHAMBER_RNG);
878 if (chamber && FillChamber(ammoType, flags))
879 {
880 didSomething = true;
881 }
882
883 // Does not need any FSM fixing, FSM does not care about inner magazines
884
885 return didSomething;
886 }
887
895 bool FillChamber( string ammoType = "", int flags = WeaponWithAmmoFlags.CHAMBER )
896 {
897 // Quickly check if there are any chambers we can fill
898 int muzzCount = GetMuzzleCount();
899 bool anyEmpty = false;
900
901 for (int m = 0; m < muzzCount; ++m)
902 {
903 if (IsChamberEmpty(m))
904 {
905 anyEmpty = true;
906 break;
907 }
908 }
909
910 if (!anyEmpty)
911 return false;
912
913 // Make sure the given ammoType is actually useable
914 if (ammoType != "")
915 if (!AmmoTypesAPI.MagazineTypeToAmmoType(ammoType, ammoType))
916 return false;
917
918 // Just so we don't '&' wastefully in a loop
919 bool didSomething = false;
920 bool chamberFullRng = (flags & WeaponWithAmmoFlags.CHAMBER_RNG_SPORADIC);
921 bool chamberRng = (flags & WeaponWithAmmoFlags.CHAMBER_RNG);
922 bool chamber = (flags & WeaponWithAmmoFlags.CHAMBER);
923
924 if (chamber || chamberRng || chamberFullRng)
925 {
926 int amountToChamber = muzzCount;
927
928 // No need to do this for full rng, as that will roll for every muzzle
929 if (chamberRng)
930 amountToChamber = Math.RandomIntInclusive(0, muzzCount);
931
932 bool chamberAmmoRng = (ammoType == "");
933 bool chamberAmmoFullRng = chamberAmmoRng && (flags & WeaponWithAmmoFlags.AMMO_CHAMBER_RNG);
934
935 // No full RNG flag, so pick one random and use only this one
936 if (chamberAmmoRng && !chamberAmmoFullRng)
937 ammoType = GetRandomChamberableAmmoTypeName(0);
938
939 for (int i = 0; i < muzzCount; ++i)
940 {
941 // Skip when there's already something in the chamber
942 if (!IsChamberEmpty(i))
943 continue;
944
945 // Roll the rng when enabled
946 if (chamberFullRng)
947 chamber = Math.RandomIntInclusive(0, 1);
948
949 // We chambering
950 if (chamber)
951 {
952 // Full random, decide a new one for every muzzle
953 if ( chamberAmmoFullRng )
954 ammoType = GetRandomChamberableAmmoTypeName(i);
955
956 // Push it
957 PushCartridgeToChamber(i, 0, ammoType);
958 didSomething = true;
959
960 // Stop chambering when we hit the desired amount
961 --amountToChamber;
962 if (amountToChamber <= 0)
963 break;
964 }
965 }
966 }
967
968 // Only fix the FSM and Synchronize when absolutely needed
969 if (!didSomething)
970 return false;
971
972 // FSM cares about chamber state
974 Synchronize();
975
976 return true;
977 }
978
980
981
982
986 override int GetSlotsCountCorrect()
987 {
988 int ac = GetInventory().AttachmentCount();
989 int sc = GetInventory().GetAttachmentSlotsCount() + GetMuzzleCount();
990 if (ac > sc) sc = ac; // fix of some weapons which has 1 attachments but 0 slots...
991 return sc;
992 };
993
1002
1003 void OnFire(int muzzle_index)
1004 {
1005/*
1006 array<Man> players();
1007 GetGame().GetPlayers(players);
1008
1009 Man root = GetHierarchyRootPlayer();
1010
1011 if (!root)
1012 {
1013 return;
1014 }
1015
1016 vector safePosition = root.GetPosition() + (root.GetDirection() * "0 1 0" * 3.0);
1017
1018 Man other = null;
1019 foreach (auto player : players)
1020 {
1021 if (player != GetHierarchyRootPlayer())
1022 {
1023 player.SetPosition(safePosition);
1024 }
1025 }
1026*/
1027
1028 m_BurstCount++;
1029 }
1030
1031 void OnFireModeChange(int fireMode)
1032 {
1033 if ( !GetGame().IsDedicatedServer() )
1034 {
1035 EffectSound eff;
1036
1037 if ( fireMode == 0 )
1038 eff = SEffectManager.PlaySound("Fire_Mode_Switch_Marked_Click_SoundSet", GetPosition());
1039 else
1040 eff = SEffectManager.PlaySound("Fire_Mode_Switch_Simple_Click_SoundSet", GetPosition());
1041
1042 eff.SetAutodestroy(true);
1043 }
1044
1046 }
1047
1049 {
1051 {
1052 m_DelayedValidationTimer.Run(VALIDATE_DELAY , this, "ValidateAndRepair");
1053 }
1054 else
1055 {
1056 Error("[wpn] Weapon_Base::DelayedValidateAndRepair m_DelayedValidationTimer not initialized.");
1058 }
1059 }
1060
1062 {
1063 if ( m_fsm )
1064 m_fsm.ValidateAndRepair();
1065 }
1066
1067 override void OnInventoryEnter(Man player)
1068 {
1070
1071 if (GetGame().IsServer())
1072 {
1073 // The server knows about all of its attachments
1075 }
1076 else
1077 {
1078 // The client doesn't know it has attachments yet... give it a moment
1080 }
1081
1082 super.OnInventoryEnter(player);
1083 }
1084
1085 override void OnInventoryExit(Man player)
1086 {
1088 super.OnInventoryExit(player);
1089 }
1090
1091 override void EEItemAttached(EntityAI item, string slot_name)
1092 {
1093 super.EEItemAttached(item, slot_name);
1094
1095 GetPropertyModifierObject().UpdateModifiers();
1096 }
1097
1098 override void EEItemDetached(EntityAI item, string slot_name)
1099 {
1100 super.EEItemDetached(item, slot_name);
1101
1102 GetPropertyModifierObject().UpdateModifiers();
1103 }
1104
1105 override void EEItemLocationChanged(notnull InventoryLocation oldLoc, notnull InventoryLocation newLoc)
1106 {
1107 super.EEItemLocationChanged(oldLoc, newLoc);
1108
1109 if (newLoc.GetType() == InventoryLocationType.HANDS)
1110 {
1111 PlayerBase player;
1112 if (newLoc.GetParent() && PlayerBase.CastTo(player, newLoc.GetParent()))
1113 {
1114 HumanCommandMove cm = player.GetCommand_Move();
1115 if (cm)
1116 {
1117 cm.SetMeleeBlock(false);
1118 }
1119 }
1120 }
1121 }
1122
1123 override void OnItemLocationChanged(EntityAI old_owner, EntityAI new_owner)
1124 {
1125 /*
1126 // TODO(kumarjac): Solve this in code instead, OnItemLocationChanged is called too late.
1127 // Maybe extend an option for items to specify what attachments they must
1128 // be synchronized with? Moving to 'DelayedValidateAndRepair' works for now.
1129 int muzzles = GetMuzzleCount();
1130 for (int muzzleIdx = 0; muzzleIdx < muzzles; muzzleIdx++)
1131 {
1132 Magazine mag = GetMagazine(muzzleIdx);
1133 Print(mag);
1134 if (!mag)
1135 continue;
1136
1137 Print(mag.GetInventory());
1138 if (!mag.GetInventory())
1139 continue;
1140
1141 InventoryLocation invLoc = new InventoryLocation();
1142 mag.GetInventory().GetCurrentInventoryLocation(invLoc);
1143
1144 GetGame().AddInventoryJunctureEx(null, this, invLoc, true, 1000);
1145 }
1146 */
1147
1148 super.OnItemLocationChanged(old_owner,new_owner);
1149
1150 // "resets" optics memory on optics
1151 PlayerBase player;
1152 if (PlayerBase.CastTo(player,old_owner))
1153 {
1154 player.SetReturnToOptics(false);
1155
1156 //optics item state reset
1157 ItemOptics optics;
1158 if (Class.CastTo(optics,GetAttachedOptics()))
1159 {
1160 player.SwitchOptics(optics,false);
1161 }
1162 }
1163
1164 if (old_owner != new_owner && PlayerBase.Cast(new_owner))
1165 SetWasIronSight(true); // reset ironsight/optic default
1166
1167 HideWeaponBarrel(false);
1168 }
1169
1170 override bool CanReleaseAttachment(EntityAI attachment)
1171 {
1172 if ( !super.CanReleaseAttachment( attachment ) )
1173 return false;
1174 Magazine mag = Magazine.Cast(attachment);
1175 if (mag)
1176 {
1177 PlayerBase player = PlayerBase.Cast( GetHierarchyRootPlayer() );
1178 if ( player )
1179 {
1180 if ( player.GetItemInHands() == this )
1181 return true;
1182 }
1183 return false;
1184 }
1185
1186 return true;
1187 }
1188
1189 override bool CanRemoveFromHands(EntityAI parent)
1190 {
1191 if (IsIdle())
1192 {
1193 return true;
1194 }
1195 if (LogManager.IsWeaponLogEnable()) { wpnDebugPrint("[wpnfsm] " + Object.GetDebugName(this) + " Weapon=" + this + " not in stable state=" + GetCurrentState().Type()); }
1196 return false; // do not allow removal of weapon while weapon is busy
1197 }
1198
1200 {
1202 if (GetInventory().GetCurrentInventoryLocation(il))
1203 {
1204 EntityAI parent = il.GetParent();
1205 DayZPlayer dayzp = DayZPlayer.Cast(parent);
1206 if (il.GetType() == InventoryLocationType.HANDS && dayzp)
1207 {
1208 bool remote = dayzp.GetInstanceType() == DayZPlayerInstanceType.INSTANCETYPE_REMOTE;
1209 return remote;
1210 }
1211 }
1212 return true;
1213 }
1214
1216 {
1217 DayZPlayer p = DayZPlayer.Cast(GetHierarchyParent());
1218 if (p && p.GetInstanceType() == DayZPlayerInstanceType.INSTANCETYPE_SERVER)
1219 {
1221
1223 e.WriteToContext(ctx);
1224
1226 wpnDebugPrint("[wpnfsm] " + Object.GetDebugName(this) + " send 2 remote: sending e=" + e + " id=" + e.GetEventID() + " p=" + e.m_player + " m=" + e.m_magazine);
1227
1228 p.StoreInputForRemotes(ctx);
1229 }
1230 }
1231
1232
1234 {
1235 return new DefaultRecoil(this);
1236 }
1237
1238 int GetWeaponSpecificCommand(int weaponAction, int subCommand)
1239 {
1240 return subCommand;
1241 }
1242
1243 bool CanFire()
1244 {
1245 if (!IsChamberEmpty(GetCurrentMuzzle()) && !IsChamberFiredOut(GetCurrentMuzzle()) && !IsJammed() && !m_LiftWeapon && !IsDamageDestroyed())
1246 return true;
1247 return false;
1248 }
1249
1251 {
1252 ItemOptics optic = GetAttachedOptics();
1253 if (!optic)
1254 return true;
1255
1256 return optic.HasWeaponIronsightsOverride();
1257 }
1258
1260 bool InitDOFProperties(out array<float> temp_array)
1261 {
1262 if (GetGame().ConfigIsExisting("cfgWeapons " + GetType() + " PPDOFProperties"))
1263 {
1264 GetGame().ConfigGetFloatArray("cfgWeapons " + GetType() + " PPDOFProperties", temp_array);
1265 return true;
1266 }
1267 return false;
1268 }
1269
1270 bool InitReliability(out array<float> reliability_array)
1271 {
1272 if (GetGame().ConfigIsExisting("cfgWeapons " + GetType() + " Reliability ChanceToJam"))
1273 {
1274 GetGame().ConfigGetFloatArray("cfgWeapons " + GetType() + " Reliability ChanceToJam", reliability_array);
1275 return true;
1276 }
1277 return false;
1278 }
1279
1282 {
1283 if (ConfigIsExisting("WeaponLength"))
1284 {
1285 m_WeaponLength = ConfigGetFloat("WeaponLength");
1286 return true;
1287 }
1288 m_WeaponLength = 0.8; //default value if not set in config; should not be zero
1289 return false;
1290 }
1291
1294 {
1295 if (ConfigIsExisting("WeaponLiftCheckVerticalOffset"))
1296 {
1297 m_WeaponLiftCheckVerticalOffset = ConfigGetFloat("WeaponLiftCheckVerticalOffset");
1298 return true;
1299 }
1300 m_WeaponLiftCheckVerticalOffset = 0.0; //no offset by default
1301 return false;
1302 }
1303
1305 protected bool InitShoulderDistance()
1306 {
1307 if (ConfigIsExisting("ShoulderDistance"))
1308 {
1309 m_ShoulderDistance = ConfigGetFloat("ShoulderDistance");
1310 return true;
1311 }
1312
1314 return false;
1315 }
1316
1318 {
1319 return m_DOFProperties;
1320 }
1321
1323 {
1324 return m_WasIronSight;
1325 }
1326
1327 // used to remember last used ironsight/optic state
1328 void SetWasIronSight(bool state)
1329 {
1330 m_WasIronSight = state;
1331 }
1332
1333 // lifting weapon on obstcles
1335 {
1336 int idx;
1337 float distance;
1338 float hit_fraction;
1339 vector start, end;
1340 vector direction;
1341 vector hit_pos, hit_normal;
1342 Object obj;
1343
1344 bool wasLift = m_LiftWeapon;
1345 vector lastLiftPosition = m_LastLiftPosition;
1346
1347 m_LiftWeapon = false;
1348 // not a gun, no weap.raise for now
1349 if ( HasSelection("Usti hlavne") )
1350 return false;
1351
1352 if (!player)
1353 {
1354 Print("Error: No weapon owner, returning");
1355 return false;
1356 }
1357
1358 // weapon not raised
1359 HumanMovementState movementState = new HumanMovementState();
1360 player.GetMovementState(movementState);
1361 if (!movementState.IsRaised())
1362 return false;
1363
1364 // suppress raising of weapon during melee attack preventing state inconsistency
1365 if (movementState.m_CommandTypeId == DayZPlayerConstants.COMMANDID_MELEE || movementState.m_CommandTypeId == DayZPlayerConstants.COMMANDID_MELEE2)
1366 {
1367 return false;
1368 }
1369
1370
1371 // If possible use aiming angles instead as these will work consistently
1372 // and independently of any cameras, etc.
1373 HumanCommandWeapons hcw = player.GetCommandModifier_Weapons();
1374 if (hcw)
1375 {
1376 vector yawPitchRoll = Vector(
1377 hcw.GetBaseAimingAngleLR() + player.GetOrientation()[0],
1379 0.0);
1380
1381 float xAimHandsOffset = hcw.GetAimingHandsOffsetLR();
1382 float yAimHandsOffset = hcw.GetAimingHandsOffsetUD();
1383
1384 yawPitchRoll[0] = yawPitchRoll[0] + xAimHandsOffset;
1385 yawPitchRoll[1] = Math.Clamp( yawPitchRoll[1] + yAimHandsOffset, DayZPlayerCamera1stPerson.CONST_UD_MIN, DayZPlayerCamera1stPerson.CONST_UD_MAX );
1386
1387 direction = yawPitchRoll.AnglesToVector();
1388 }
1389 else // Fallback to previously implemented logic
1390 {
1391 // freelook raycast
1392 if (player.GetInputController().CameraIsFreeLook())
1393 {
1394 if (player.m_DirectionToCursor != vector.Zero)
1395 {
1396 direction = player.m_DirectionToCursor;
1397 }
1398 // if player raises weapon in freelook
1399 else
1400 {
1401 direction = MiscGameplayFunctions.GetHeadingVector(player);
1402 }
1403 }
1404 else
1405 {
1406 direction = GetGame().GetCurrentCameraDirection(); // exception for freelook. Much better this way!
1407 }
1408 }
1409
1410 idx = player.GetBoneIndexByName("Neck"); //RightHandIndex1
1411 if ( idx == -1 )
1412 { start = player.GetPosition()[1] + 1.5; }
1413 else
1414 { start = player.GetBonePositionWS(idx); }
1415
1416
1417 // Updated weapon lift detection code prototype
1418 {
1419 // 0: construct stable trasformation matrix that
1420 // approximately aligns with the weapon transform
1421 // without actually using the weapon as reference
1422 // (as the weapon can be moved unpredictably by anims)
1423 vector resTM[4];
1424 resTM[0] = Vector(direction[0], 0, direction[2]).Normalized();
1425 resTM[0] = vector.RotateAroundZeroDeg(resTM[0], vector.Up, 90);
1426 resTM[2] = direction;
1427 resTM[1] = resTM[2] * resTM[0];
1428 resTM[3] = start;
1429
1430 // Approximate the roll of leaning
1432 player.GetMovementState(hms);
1433 float leanAngle = hms.m_fLeaning * 35;
1434 vector rotTM[3];
1435 Math3D.YawPitchRollMatrix( Vector(xAimHandsOffset , yAimHandsOffset, leanAngle), rotTM );
1436 Math3D.MatrixMultiply3(resTM, rotTM, resTM);
1437
1438 // Draw relative TM diagnostic
1439 #ifdef DIAG_DEVELOPER
1440 if (DiagMenu.GetValue(DiagMenuIDs.WEAPON_LIFT_DEBUG))
1441 {
1442 Shape.CreateArrow(resTM[3], resTM[3] + resTM[0], 0.05, COLOR_RED, ShapeFlags.ONCE);
1443 Shape.CreateArrow(resTM[3], resTM[3] + resTM[1], 0.05, COLOR_GREEN, ShapeFlags.ONCE);
1444 Shape.CreateArrow(resTM[3], resTM[3] + resTM[2], 0.05, COLOR_BLUE, ShapeFlags.ONCE);
1445 }
1446 #endif
1447
1448 // 1: pick from predefined offset relative to
1449 // the previously constructed transform
1450 float udAngle = Math.Asin(direction[1]) * Math.RAD2DEG;
1451
1452 // offsets are [right, up, forward]
1453 // values are based on what felt right after iterating
1454 vector offsets[] =
1455 {
1456 "0.11 0.17 0.0", // offset while aiming down
1457 "0.12 0.05 0.0", // offset while aiming forward
1458 "0.112 0.03 0.0" // offset while aiming up
1459 };
1460 const int lastIndex = 2; // length of offsets - 1
1461
1462 // <0,1> range of aiming
1463 float a = Math.Clamp(Math.InverseLerp(DayZPlayerCamera1stPerson.CONST_UD_MIN, DayZPlayerCamera1stPerson.CONST_UD_MAX, udAngle), 0, 0.9999);
1464 int lo = a * lastIndex;
1465 int hi = Math.Clamp(lo+1, 0, lastIndex);
1466
1467 // remap to current lo-hi range
1468 float t = Math.Clamp(a * lastIndex - lo, 0, 1);
1469 vector offset = vector.Lerp(offsets[lo], offsets[hi], t);
1470
1471 // offsets are [right, up forward]
1472 // additional offsets added to previous offsets per stance
1473 vector stanceOffsets[] =
1474 {
1475 "0 -0.015 0", // erect
1476 "0 0.03 0", // crouch
1477 "0 -0.04 0",// prone
1478 };
1479
1480 // 2. pick from predefined offsets based on stance,
1481 // allows to even further approximate the alignment
1482 int stanceOffsetIndex = hms.m_iStanceIdx;
1483 if (stanceOffsetIndex >= DayZPlayerConstants.STANCEIDX_PRONE)
1484 stanceOffsetIndex -= DayZPlayerConstants.STANCEIDX_RAISED;
1485
1486 stanceOffsetIndex -= DayZPlayerConstants.STANCEIDX_ERECT;
1487 offset += stanceOffsets[stanceOffsetIndex];
1488
1489 // if any additional height offset is defined, apply it
1491 {
1492 offset[1] = offset[1] + m_WeaponLiftCheckVerticalOffset;
1493 }
1494
1495 //
1496 offset = offset.InvMultiply3(rotTM);
1497
1498 // 3. use the offset as the start position.
1499 // it will not be perfect, but it should reflect
1500 // the actual weapon transform more accurately
1501 start = offset.Multiply4(resTM);
1502 }
1503
1504
1506
1507 vector weaponStart = start + (m_ShoulderDistance * direction);
1508 vector weaponEnd = weaponStart + (distance * direction);
1509
1510 // Draw diagnostics: Script -> Weapon -> Weapon Lift
1511 #ifdef DIAG_DEVELOPER
1512 if (DiagMenu.GetValue(DiagMenuIDs.WEAPON_LIFT_DEBUG))
1513 {
1514 vector diagNoAttachEnd = weaponStart + (m_WeaponLength * direction);
1515 int diagPtsShpFlgs = ShapeFlags.ONCE | ShapeFlags.NOOUTLINE;
1516 float diagPtsRadius = 0.025;
1517 Shape.CreateSphere(COLOR_GREEN, diagPtsShpFlgs, weaponStart, diagPtsRadius);
1518 Shape.CreateSphere(COLOR_YELLOW, diagPtsShpFlgs, diagNoAttachEnd, diagPtsRadius);
1519 Shape.CreateSphere(COLOR_BLUE, diagPtsShpFlgs, weaponEnd, diagPtsRadius);
1520 }
1521 #endif
1522
1523 // For the physical cast, extend the distance by x%
1524 // to allow for smoother transition handling in some cases
1525 end = weaponEnd + ((0.1 * distance) * direction);
1526
1527 // Prepare raycast params and perform the cast in fire geo
1528 RaycastRVParams rayParm = new RaycastRVParams(start, end, player, 0.02);
1529 rayParm.flags = CollisionFlags.ALLOBJECTS;
1530 rayParm.type = ObjIntersect.Fire;
1531
1532 #ifdef DIAG_DEVELOPER
1534 #endif
1535 array<ref RaycastRVResult> results = {};
1536 if (!DayZPhysics.RaycastRVProxy(rayParm, results) || results.Count() == 0)
1537 {
1538 hit_pos = vector.Zero;
1539 hit_fraction = 0;
1540 }
1541 else
1542 {
1543 RaycastRVResult res = results[0];
1544
1545 #ifdef DIAG_DEVELOPER // isect diag
1546 if (DiagMenu.GetValue(DiagMenuIDs.WEAPON_LIFT_DEBUG) == 2)
1547 {
1548 DbgUI.Begin("Weapon Lift Diag");
1549 {
1550 if (res.surface)
1551 {
1552 DbgUI.Text("Intersection data:");
1553 DbgUI.Text(" Name: " + res.surface.GetName());
1554 DbgUI.Text(" EntryName: " + res.surface.GetEntryName());
1555 DbgUI.Text(" SurfaceType: " + res.surface.GetSurfaceType());
1556
1557 DbgUI.Text(" IsPassThrough: " + res.surface.IsPassthrough());
1558 DbgUI.Text(" IsSolid: " + res.surface.IsSolid());
1559 }
1560 else
1561 {
1562 DbgUI.Text("Intersection with no surface");
1563 }
1564 }
1565 DbgUI.End();
1566 }
1567 #endif // !isect diag
1568
1570 {
1571 hit_pos = res.pos;
1572 float len0 = (hit_pos - start).Length();
1573 float len1 = (end - start).Length();
1574 if (len0 <= 0 || len1 <= 0)
1575 {
1576 hit_fraction = 1;
1577 }
1578 else
1579 {
1580 hit_fraction = len0 / len1;
1581 }
1582 }
1583 else
1584 {
1585 hit_pos = vector.Zero;
1586 hit_fraction = 0;
1587 }
1588 }
1589 #ifdef DIAG_DEVELOPER
1591 #endif
1592
1593 // Draw diagnostics: Script -> Weapon -> Weapon Lift
1594 #ifdef DIAG_DEVELOPER
1595 if (DiagMenu.GetValue(DiagMenuIDs.WEAPON_LIFT_DEBUG))
1596 {
1597 const vector epsilon = "0 0.0002 0"; // to overcome excessive z-fighting for diag
1598 if (lastLiftPosition!=vector.Zero)
1599 {
1600 Shape.CreateArrow(start-epsilon, lastLiftPosition-epsilon, 0.05, COLOR_YELLOW, ShapeFlags.ONCE);
1601 }
1602
1603 Shape.CreateArrow(start, weaponEnd, 0.05, COLOR_WHITE, ShapeFlags.ONCE | ShapeFlags.NOZBUFFER );
1604
1605 if (hit_fraction != 0)
1606 {
1607 Shape.CreateArrow(start+epsilon, hit_pos+epsilon, 0.05, COLOR_RED, ShapeFlags.ONCE);
1608 }
1609 }
1610 #endif
1611
1612 // Start by assuming that we want to retain state
1613 bool wantsLift = wasLift;
1614
1615 // Sq. distance of weapon movement required to trigger lift (in)
1616 const float inThreshold = 0.002;
1617 // Sq. distance of weapon movement required to trigger lift (out)
1618 const float outThreshold = 0.003;
1619 const float noIsctOutThreshold = 0.01;
1620 // Max num of ticks with no hit for which hysteresis will persist
1621 // value chosen by iteration, should be approx 0.333s
1622 const int maxNumMissedTicks = 10;
1623
1624 // Min angle in degrees change from last lift to stop lifting
1625 // Base threshold of 0.75 degrees + 0.6 degrees per meter of weapon length
1626 float angleThreshold = 0.75 + Math.Clamp( m_WeaponLength * 0.6, 0, 1.5 );
1627
1628 // Update state when a hit is registered
1629 if (hit_fraction != 0)
1630 {
1631 vector v1 = hit_pos - weaponEnd;
1632 vector v2 = hit_pos - end;
1633 float d = vector.Dot(v1, v2);
1634 // But leave some threshold where previous state is kept
1635 // to prevent excessive switches from occuring
1636 if (!wasLift && d > inThreshold)
1637 {
1638 wantsLift = true;
1639 }
1640 else if (wasLift && d < -outThreshold)
1641 {
1642 wantsLift = false;
1643 }
1644
1645 m_LastLiftPosition = hit_pos;
1646 m_LastLiftHit = player.GetSimulationTimeStamp();
1647 }
1648 else
1649 {
1650 // With no hit and no previous lift
1651 if (lastLiftPosition == vector.Zero)
1652 {
1653 wantsLift = false;
1655 }
1656 // See if previous hit wasn't very close to our current position,
1657 // in which case simply don't lift the weapon
1658 else
1659 {
1660 vector v3 = (lastLiftPosition - start).Normalized();
1661 vector v4 = (end-start).Normalized();
1662 float d2 = vector.Dot(v3, v4);
1663 // no isect, angle delta check
1664 if (Math.Acos(d2) > (angleThreshold * Math.DEG2RAD)) // if relative angle is > x degree, stop lifting
1665 {
1666 wantsLift = false;
1668 }
1669 // no isect, distance check
1670 else
1671 {
1672 float d3 = vector.Dot( lastLiftPosition - weaponEnd, (start-end).Normalized() );
1673 if (d3 < -noIsctOutThreshold)
1674 {
1675 wantsLift = false;
1677 }
1678
1679 // fallback in case offending object disappears or moves
1680 int timeSinceHit = player.GetSimulationTimeStamp() - m_LastLiftHit;
1681 if (timeSinceHit > maxNumMissedTicks)
1682 {
1683 wantsLift = false;
1685 }
1686 }
1687 }
1688 }
1689
1690 // lift is desired
1691 if (wantsLift)
1692 {
1693 //Print(distance);
1694 m_LiftWeapon = true;
1695 return true;
1696 }
1697 return false;
1698 }
1699
1702 {
1703 return res.surface.IsSolid();
1704 }
1705
1708 {
1709 ItemBase attachment;
1710 if (HasBayonetAttached())
1711 {
1712 int bayonetIndex = GetBayonetAttachmentIdx();
1713 attachment = ItemBase.Cast(GetInventory().FindAttachment(bayonetIndex));
1714 }
1715 else
1716 {
1717 attachment = GetAttachedSuppressor();
1718 }
1719
1720 if (attachment)
1721 {
1722 return Math.Max(attachment.m_ItemModelLength + attachment.m_ItemAttachOffset, 0);
1723 }
1724 else
1725 {
1726 return 0;
1727 }
1728 }
1729
1730 void SetSyncJammingChance( float jamming_chance )
1731 {
1732 m_ChanceToJamSync = jamming_chance;
1733 }
1734
1745 bool EjectCartridge(int muzzleIndex, out float ammoDamage, out string ammoTypeName)
1746 {
1747 if (IsChamberEjectable(muzzleIndex))
1748 {
1749 if (PopCartridgeFromChamber(muzzleIndex, ammoDamage, ammoTypeName))
1750 return true;
1751 }
1752 else if (GetInternalMagazineCartridgeCount(muzzleIndex) > 0)
1753 {
1754 if (PopCartridgeFromInternalMagazine(muzzleIndex, ammoDamage, ammoTypeName))
1755 return true;
1756 }
1757 return false;
1758 }
1759
1761 {
1762 float damage = 0.0;
1763 string type;
1764
1765 for (int mi = 0; mi < src.GetMuzzleCount(); ++mi)
1766 {
1767 if (!src.IsChamberEmpty(mi))
1768 {
1769 if (src.GetCartridgeInfo(mi, damage, type))
1770 {
1771 PushCartridgeToChamber(mi, damage, type);
1772 }
1773 }
1774
1775 for (int ci = 0; ci < src.GetInternalMagazineCartridgeCount(mi); ++ci)
1776 {
1777 if (src.GetInternalMagazineCartridgeInfo(mi, ci, damage, type))
1778 {
1779 PushCartridgeToInternalMagazine(mi, damage, type);
1780 }
1781 }
1782 }
1783
1784 int dummy_version = int.MAX;
1785 PlayerBase parentPlayer = PlayerBase.Cast(src.GetHierarchyRootPlayer());
1786 if (!parentPlayer)
1787 dummy_version -= 1;
1789 src.OnStoreSave(ctx.GetWriteContext());
1790 OnStoreLoad(ctx.GetReadContext(), dummy_version);
1791 return true;
1792 }
1793
1795 override void SetBayonetAttached(bool pState, int slot_idx = -1)
1796 {
1797 m_BayonetAttached = pState;
1798 m_BayonetAttachmentIdx = slot_idx;
1799 }
1800
1801 override bool HasBayonetAttached()
1802 {
1803 return m_BayonetAttached;
1804 }
1805
1807 {
1809 }
1810
1811 override void SetButtstockAttached(bool pState, int slot_idx = -1)
1812 {
1813 m_ButtstockAttached = pState;
1814 m_ButtstockAttachmentIdx = slot_idx;
1815 }
1816
1817 override bool HasButtstockAttached()
1818 {
1819 return m_ButtstockAttached;
1820 }
1821
1823 {
1825 }
1826
1827 void HideWeaponBarrel(bool state)
1828 {
1829 if ( !GetGame().IsDedicatedServer() )//hidden for client only
1830 {
1831 ItemOptics optics = GetAttachedOptics();
1832 if ( optics && !optics.AllowsDOF() && m_weaponHideBarrelIdx != -1 )
1833 {
1834 SetSimpleHiddenSelectionState(m_weaponHideBarrelIdx,!state);
1835 }
1836 }
1837 }
1838
1840 {
1842 SetSimpleHiddenSelectionState(m_magazineSimpleSelectionIndex,1);
1843 else
1844 SelectionMagazineShow();
1845 }
1846
1848 {
1850 SetSimpleHiddenSelectionState(m_magazineSimpleSelectionIndex,0);
1851 else
1852 SelectionMagazineHide();
1853 }
1854
1855 override EntityAI ProcessMeleeItemDamage(int mode = 0)
1856 {
1857 EntityAI attachment;
1858
1859 switch (mode)
1860 {
1861 case 0:
1862 super.ProcessMeleeItemDamage();
1863 break;
1864
1865 case 1:
1866 attachment = GetInventory().FindAttachment(m_ButtstockAttachmentIdx);
1867 break;
1868
1869 case 2:
1870 attachment = GetInventory().FindAttachment(m_BayonetAttachmentIdx);
1871 break;
1872
1873 default:
1874 super.ProcessMeleeItemDamage();
1875 break;
1876 }
1877
1878 if (attachment)
1879 {
1880 attachment.ProcessMeleeItemDamage();
1881 return attachment;
1882 }
1883
1884 return this;
1885 }
1886
1888 {
1889 return true;
1890 }
1891
1893 {
1894 return m_BurstCount;
1895 }
1896
1898 {
1899 m_BurstCount = 0;
1900 }
1901
1915
1916 override bool CanBeUsedForSuicide()
1917 {
1918 if (!ConfigGetBool("isSuicideWeapon"))
1919 return false;
1920
1921 return super.CanBeUsedForSuicide();
1922 }
1923
1924 //Debug menu Spawn Ground Special
1925 override void OnDebugSpawn()
1926 {
1928 }
1929
1930 bool AddJunctureToAttachedMagazine(PlayerBase player, int timeoutMS)
1931 {
1932 Magazine mag = GetMagazine(GetCurrentMuzzle());
1934 if (mag)
1935 {
1936 return GetGame().AddInventoryJunctureEx(player, mag, il, false, timeoutMS);
1937 }
1938
1939 return true;
1940 }
1941
1943 {
1944 Magazine mag = GetMagazine(GetCurrentMuzzle());
1945 if (mag)
1946 {
1947 GetGame().ClearJuncture(player, mag);
1948 }
1949 }
1950
1951 void SetNextWeaponMode(int muzzleIndex)
1952 {
1953 SetNextMuzzleMode(muzzleIndex);
1954 }
1955
1956 // CoolDown
1957 void SetCoolDown( float coolDownTime )
1958 {
1959 m_coolDownTime = coolDownTime;
1960 }
1961 void UpdateCoolDown( float dt ) { m_coolDownTime -= dt; }
1963 {
1964 return m_coolDownTime > 0;
1965 }
1966};
1967
const int INPUT_UDT_WEAPON_REMOTE_EVENT
Определения _constants.c:12
eBleedingSourceType GetType()
Определения BleedingSource.c:63
void wpnDebugPrint(string s)
Определения Debug.c:9
void AddAction(typename actionName)
Определения AdvancedCommunication.c:220
const int ECE_PLACE_ON_SURFACE
Определения CentralEconomy.c:37
void Synchronize()
Определения CombinationLock.c:151
override bool IsJammed()
Определения Crossbow.c:22
DayZGame g_Game
Определения DayZGame.c:3868
PhxInteractionLayers
Определения DayZPhysics.c:2
DiagMenuIDs
Определения EDiagMenuIDs.c:2
WeaponEventID
identifier for events. mainly for rpc purposes
Определения Events.c:6
ProcessEventResult
Определения FSMBase.c:41
FirearmActionLoadBullet FirearmActionBase FirearmActionLoadBulletQuick()
void fsmDebugSpam(string s)
Определения HFSMBase.c:9
InventoryLocationType
types of Inventory Location
Определения InventoryLocation.c:4
void IncreaseOverheating(ItemBase weapon, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
Определения ItemBase.c:5292
string Type
Определения JsonDataContaminatedArea.c:11
bool OnStoreLoad(ParamsReadContext ctx, int version)
Определения ModifiersManager.c:265
PistolAnimState
Определения Pistol_Base.c:3
RandomGeneratorSyncUsage
Определения RandomGeneratorSyncManager.c:2
@ AMMO_CHAMBER_RNG
Fully randomizes the ammo type instead of picking one random for all chambers (needs to have type as ...
Определения Weapon_Base.c:26
@ CHAMBER
Chambers bullets.
Определения Weapon_Base.c:16
@ CHAMBER_RNG_SPORADIC
Maybe chambers bullets (full random) example: 0 1 0 0 1 1.
Определения Weapon_Base.c:20
@ MAX_CAPACITY_MAG
Instead of randomizing when type is empty, it looks for the one which has the highest capacity.
Определения Weapon_Base.c:28
@ QUANTITY_RNG
Randomizes the quantity of the bullets in the spawned magazine.
Определения Weapon_Base.c:22
@ CHAMBER_RNG
Maybe chambers bullets (sequential rng) example: 1 1 1 0 0 0.
Определения Weapon_Base.c:18
@ AMMO_MAG_RNG
Fully randomizes the ammo type instead of picking one random for the entire mag (needs to have type a...
Определения Weapon_Base.c:24
enum FSMTransition WeaponTransition
MuzzleState
Определения WeaponStableState.c:15
override bool IsIdle()
Определения WeaponStableState.c:91
bool IsChamberFiredOut(int idx)
Определения WeaponStableState.c:153
bool IsChamberFull(int idx)
Определения WeaponStableState.c:154
void AbilityRecord(int a, int at)
corresponds to Human::actionTypes == CHAMBERING_ONEBULLET_CLOSED, MECHANISM_CLOSED....
Определения Weapon_Base.c:8
int m_actionType
corresponds to Human::actions == RELOAD, MECHANISM, ...
Определения Weapon_Base.c:7
int m_action
Определения Weapon_Base.c:6
pair ( action, actionType )
Определения Weapon_Base.c:5
static bool MagazineTypeToAmmoType(string magazineType, out string ammoType)
Helper method.
Определения AmmoTypes.c:14
Определения AmmoTypes.c:2
static float GetAmmoWeightByBulletType(string bulletType)
Определения AmmunitionPiles.c:6
ammo pile base
Определения AmmunitionPiles.c:3
override ScriptCallQueue GetCallQueue(int call_category)
Определения DayZGame.c:1187
proto native bool ClearJuncture(Man player, notnull EntityAI item)
bool AddInventoryJunctureEx(Man player, notnull EntityAI item, InventoryLocation dst, bool test_dst_occupancy, int timeout_ms)
Определения Game.c:741
proto native vector GetCurrentCameraDirection()
proto native void ConfigGetFloatArray(string path, out TFloatArray values)
Get array of floats from config on path.
Super root of all classes in Enforce script.
Определения EnScript.c:11
static proto bool RaycastRVProxy(notnull RaycastRVParams in, out notnull array< ref RaycastRVResult > results, array< Object > excluded=null)
Определения DayZPhysics.c:124
Определения DbgUI.c:60
Определения DefaultRecoil.c:2
Определения EnDebug.c:233
override void SetAutodestroy(bool auto_destroy)
Sets whether Effect automatically cleans up when it stops.
Определения EffectSound.c:603
Wrapper class for managing sound through SEffectManager.
Определения EffectSound.c:5
Определения Building.c:6
represents transition src -— event[guard]/action -—|> dst
proto native void SetMeleeBlock(bool pBlock)
this enables/disables block
Определения human.c:434
proto native float GetAimingHandsOffsetUD()
returns aiming hands up/down (y) offset angle
proto native float GetBaseAimingAngleLR()
returns base aiming angle LR - without sway/offsets/...
proto native float GetAimingHandsOffsetLR()
returns aiming hands left/right (x) offset angle
proto native float GetBaseAimingAngleUD()
returns base aiming angle UD - without sway/offsets/...
Определения human.c:994
int m_iStanceIdx
current command's id
Определения human.c:1141
int m_CommandTypeId
Определения human.c:1140
float m_fLeaning
current movement (0 idle, 1 walk, 2-run, 3-sprint), only if the command has a movement
Определения human.c:1143
bool IsRaised()
Определения human.c:1148
Определения human.c:1139
proto native EntityAI GetParent()
returns parent of current inventory location
proto native int GetType()
returns type of InventoryLocation
InventoryLocation.
Определения InventoryLocation.c:29
Определения InventoryItem.c:731
bool AllowsDOF()
returns 'true' for non-magnifying optics
Определения ItemOptics.c:422
proto native bool HasWeaponIronsightsOverride()
is weapon in optics mode or not
Определения ItemOptics.c:2
static bool IsWeaponLogEnable()
Определения Debug.c:718
Определения Debug.c:594
Определения EnMath3D.c:28
Определения EnMath.c:7
Определения ObjectTyped.c:2
Определения PlayerBaseClient.c:2
Определения DayZPhysics.c:50
SurfaceInfo surface
surface material info handle
Определения DayZPhysics.c:109
vector pos
position of collision (in world coord)
Определения DayZPhysics.c:103
Определения DayZPhysics.c:99
Определения RecoilBase.c:2
static EffectSound PlaySound(string sound_set, vector position, float play_fade_in=0, float stop_fade_out=0, bool loop=false)
Create and play an EffectSound.
Определения EffectManager.c:169
Manager class for managing Effect (EffectParticle, EffectSound)
Определения EffectManager.c:6
proto void Call(func fn, void param1=NULL, void param2=NULL, void param3=NULL, void param4=NULL, void param5=NULL, void param6=NULL, void param7=NULL, void param8=NULL, void param9=NULL)
adds call into the queue with given parameters and arguments (arguments are held in memory until the ...
proto native ParamsReadContext GetReadContext()
proto native ParamsWriteContext GetWriteContext()
proto bool Write(void value_out)
proto bool Read(void value_in)
proto string GetName()
proto bool IsSolid()
proto string GetSurfaceType()
proto bool IsPassthrough()
proto string GetEntryName()
Определения DayZPlayerImplement.c:63
override void InitStateMachine()
Определения Magnum.c:85
override void HideBullet(int muzzleIndex)
Определения Magnum.c:323
override void ShowBullet(int muzzleIndex)
Определения Magnum.c:300
shorthand
Определения BoltActionRifle_Base.c:6
bool m_ButtstockAttached
Определения Weapon_Base.c:53
int m_BurstCount
Определения Weapon_Base.c:57
float m_ChanceToJamSync
Определения Weapon_Base.c:72
override int GetBayonetAttachmentIdx()
Определения Weapon_Base.c:1806
override int GetButtstockAttachmentIdx()
Определения Weapon_Base.c:1822
void HideMagazine()
Определения Weapon_Base.c:1847
ref array< float > GetWeaponDOF()
Определения Weapon_Base.c:1317
int GetBurstCount()
Определения Weapon_Base.c:1892
bool CopyWeaponStateFrom(notnull Weapon_Base src)
Определения Weapon_Base.c:1760
bool IsShowingChamberedBullet()
Определения Weapon_Base.c:1887
Magazine SpawnAttachedMagazine(string magazineType="", int flags=WeaponWithAmmoFlags.CHAMBER)
Try to spawn and attach a magazine.
Определения Weapon_Base.c:769
bool IsWaitingForActionFinish()
returns true if state machine started playing action/actionType and waits for finish
Определения Weapon_Base.c:279
void SetWasIronSight(bool state)
Определения Weapon_Base.c:1328
bool IsRemoteWeapon()
Определения Weapon_Base.c:1199
bool JamCheck(int muzzleIndex)
Определения Weapon_Base.c:372
float m_coolDownTime
Определения Weapon_Base.c:76
void SyncEventToRemote(WeaponEventBase e)
Определения Weapon_Base.c:1215
void DelayedValidateAndRepair()
Определения Weapon_Base.c:1048
override bool HasBayonetAttached()
Определения Weapon_Base.c:1801
void SetInitialState(WeaponStableState initState)
Определения Weapon_Base.c:143
bool IsCharged()
Определения Weapon_Base.c:151
ref array< int > m_bulletSelectionIndex
Определения Weapon_Base.c:69
ref Timer m_DelayedValidationTimer
Определения Weapon_Base.c:75
int m_LastLiftHit
Определения Weapon_Base.c:68
float m_WeaponLiftCheckVerticalOffset
Определения Weapon_Base.c:65
void SyncSelectionState(bool has_bullet, bool has_mag)
Определения Weapon_Base.c:419
float GetEffectiveAttachmentLength()
Returns effective length of attachments that influence total weapon length.
Определения Weapon_Base.c:1707
bool m_isJammed
weapon state machine
Определения Weapon_Base.c:50
void EEFired(int muzzleType, int mode, string ammoType)
Определения Weapon_Base.c:339
void ShowMagazine()
Определения Weapon_Base.c:1839
static Weapon_Base CreateWeaponWithAmmo(string weaponType, string magazineType="", int flags=WeaponWithAmmoFlags.CHAMBER)
Create weapon with ammo.
Определения Weapon_Base.c:726
float m_ShoulderDistance
Определения Weapon_Base.c:66
int GetWeaponSpecificCommand(int weaponAction, int subCommand)
Определения Weapon_Base.c:1238
bool FillInnerMagazine(string ammoType="", int flags=WeaponWithAmmoFlags.CHAMBER)
Try to fill the inner magazine.
Определения Weapon_Base.c:827
int m_weaponHideBarrelIdx
Определения Weapon_Base.c:62
bool InitWeaponLiftCheckVerticalOffset()
gets weapon vertical offset from config for weaponlift raycast
Определения Weapon_Base.c:1293
int m_BayonetAttachmentIdx
Определения Weapon_Base.c:58
bool EjectCartridge(int muzzleIndex, out float ammoDamage, out string ammoTypeName)
unload bullet from chamber or internal magazine
Определения Weapon_Base.c:1745
ref array< float > m_DOFProperties
Определения Weapon_Base.c:70
ref array< ref AbilityRecord > m_abilities
Определения Weapon_Base.c:48
bool IsIdle()
Определения Weapon_Base.c:284
float GetWeightSpecialized(bool forceRecalc=false)
Определения Weapon_Base.c:171
const float VALIDATE_DELAY
Validation on client side delay to have time properly synchronize attachments needed for check.
Определения Weapon_Base.c:45
override int GetSlotsCountCorrect()
Returns number of slots for attachments corrected for weapons.
Определения Weapon_Base.c:986
void HideWeaponBarrel(bool state)
Определения Weapon_Base.c:1827
bool InitShoulderDistance()
gets approximate weapon distance from shoulder from config
Определения Weapon_Base.c:1305
override bool CanReleaseAttachment(EntityAI attachment)
Определения Weapon_Base.c:1170
void ShowBullet(int muzzleIndex)
Определения Weapon_Base.c:385
bool CanProcessAction(int action, int actionType)
Определения Weapon_Base.c:234
void HideBullet(int muzzleIndex)
Определения Weapon_Base.c:395
array< MuzzleState > GetMuzzleStates()
Helper method for RandomizeFSMState.
Определения Weapon_Base.c:689
void SetCharged(bool value)
Определения Weapon_Base.c:156
void ResetBurstCount()
Определения Weapon_Base.c:1897
bool InitDOFProperties(out array< float > temp_array)
Initializes DOF properties for weapon's ironsight/optics cameras.
Определения Weapon_Base.c:1260
override void EEItemLocationChanged(notnull InventoryLocation oldLoc, notnull InventoryLocation newLoc)
Определения Weapon_Base.c:1105
void SetNextWeaponMode(int muzzleIndex)
Определения Weapon_Base.c:1951
bool AddJunctureToAttachedMagazine(PlayerBase player, int timeoutMS)
Определения Weapon_Base.c:1930
vector m_LastLiftPosition
Определения Weapon_Base.c:67
const float DEFAULT_DAMAGE_ON_SHOT
Определения Weapon_Base.c:47
void Weapon_Base()
Определения Weapon_Base.c:78
override void OnInventoryExit(Man player)
Определения Weapon_Base.c:1085
int m_magazineSimpleSelectionIndex
animation state the weapon is in, -1 == uninitialized
Определения Weapon_Base.c:61
ref WeaponFSM m_fsm
weapon abilities
Определения Weapon_Base.c:49
bool GetWasIronSight()
Определения Weapon_Base.c:1322
bool m_BayonetAttached
Определения Weapon_Base.c:52
bool CanFire()
Определения Weapon_Base.c:1243
void RandomizeFSMState()
With the parameters given, selects a random suitable state for the FSM of the weapon @WARNING: Weapon...
Определения Weapon_Base.c:673
bool m_WeaponOpen
Определения Weapon_Base.c:55
float GetSyncChanceToJam()
Определения Weapon_Base.c:408
bool m_Charged
Определения Weapon_Base.c:54
int m_weaponAnimState
Определения Weapon_Base.c:60
void SetSyncJammingChance(float jamming_chance)
Определения Weapon_Base.c:1730
override void OnDebugSpawn()
Определения Weapon_Base.c:1925
bool FillChamber(string ammoType="", int flags=WeaponWithAmmoFlags.CHAMBER)
Try to fill the chamber.
Определения Weapon_Base.c:895
PhxInteractionLayers hit_mask
Определения Weapon_Base.c:74
void SetWeaponAnimState(int state)
Определения Weapon_Base.c:327
bool LiftWeaponRaycastResultCheck(notnull RaycastRVResult res)
Return whether provided material triggers weapon lift (true) or not (false).
Определения Weapon_Base.c:1701
float GetChanceToJam()
Определения Weapon_Base.c:409
bool HasActionAbility(int action, int actionType)
query if weapon supports action and actionType
Определения Weapon_Base.c:244
void SetWeaponOpen(bool value)
Определения Weapon_Base.c:166
void ForceSyncSelectionState()
Определения Weapon_Base.c:460
bool LiftWeaponCheck(PlayerBase player)
Определения Weapon_Base.c:1334
override void AfterStoreLoad()
Определения Weapon_Base.c:610
bool CanEjectBullet()
Определения Weapon_Base.c:406
bool ProcessWeaponAbortEvent(WeaponEventBase e)
Определения Weapon_Base.c:313
override bool CanRemoveFromHands(EntityAI parent)
Определения Weapon_Base.c:1189
override void EEInit()
Определения Weapon_Base.c:133
override void SetButtstockAttached(bool pState, int slot_idx=-1)
Определения Weapon_Base.c:1811
PropertyModifiers GetPropertyModifierObject()
Определения Weapon_Base.c:994
bool ProcessWeaponEvent(WeaponEventBase e)
weapon's fsm handling of events @NOTE: warning: ProcessWeaponEvent can be called only within DayZPlay...
Определения Weapon_Base.c:293
WeaponStateBase GetCurrentState()
returns currently active state
Определения Weapon_Base.c:274
int GetAbilityCount()
Определения Weapon_Base.c:258
ref array< float > m_ChanceToJam
Определения Weapon_Base.c:71
void AssembleGun()
override on weapons with some assembly required
AbilityRecord GetAbility(int index)
Определения Weapon_Base.c:263
override bool CanBeUsedForSuicide()
Определения Weapon_Base.c:1916
void ClearJunctureToAttachedMagazine(PlayerBase player)
Определения Weapon_Base.c:1942
RecoilBase SpawnRecoilObject()
Определения Weapon_Base.c:1233
override void EEItemDetached(EntityAI item, string slot_name)
Определения Weapon_Base.c:1098
int GetCurrentStableStateID()
tries to return identifier of current stable state (or nearest stable state if unstable state is curr...
Определения Weapon_Base.c:660
void InitStateMachine()
Определения Weapon_Base.c:131
ref PropertyModifiers m_PropertyModifierObject
Определения Weapon_Base.c:73
bool IsJammed()
Определения Weapon_Base.c:405
void ValidateAndRepair()
Определения Weapon_Base.c:1061
const int SAMF_DEFAULT
Full highest capacity magazine + chambered round.
Определения Weapon_Base.c:41
void OnFire(int muzzle_index)
Определения Weapon_Base.c:1003
bool m_LiftWeapon
Определения Weapon_Base.c:51
override void OnItemLocationChanged(EntityAI old_owner, EntityAI new_owner)
Определения Weapon_Base.c:1123
int m_ButtstockAttachmentIdx
Определения Weapon_Base.c:59
override void SetActions()
Определения Weapon_Base.c:1902
void ResetWeaponAnimState()
Определения Weapon_Base.c:332
bool LoadCurrentFSMState(ParamsReadContext ctx, int version)
Определения Weapon_Base.c:577
void SetCoolDown(float coolDownTime)
Определения Weapon_Base.c:1957
bool CanEnterIronsights()
Определения Weapon_Base.c:1250
float m_WeaponLength
Определения Weapon_Base.c:64
float m_DmgPerShot
Определения Weapon_Base.c:63
int GetWeaponAnimState()
Определения Weapon_Base.c:337
override EntityAI ProcessMeleeItemDamage(int mode=0)
Определения Weapon_Base.c:1855
override bool OnStoreLoad(ParamsReadContext ctx, int version)
Определения Weapon_Base.c:487
bool IsCoolDown()
Определения Weapon_Base.c:1962
override void OnStoreSave(ParamsWriteContext ctx)
Определения Weapon_Base.c:622
bool CanChamberBullet(int muzzleIndex, Magazine mag)
Определения Weapon_Base.c:322
bool CanProcessWeaponEvents()
Определения Weapon_Base.c:268
void UpdateCoolDown(float dt)
Определения Weapon_Base.c:1961
bool m_WasIronSight
Определения Weapon_Base.c:56
bool SpawnAmmo(string magazineType="", int flags=WeaponWithAmmoFlags.CHAMBER)
General method trying to attch magazine, fill inner magazine and fill chamber.
Определения Weapon_Base.c:746
void SaveCurrentFSMState(ParamsWriteContext ctx)
Определения Weapon_Base.c:562
void OnFireModeChange(int fireMode)
Определения Weapon_Base.c:1031
override bool HasButtstockAttached()
Определения Weapon_Base.c:1817
void SetJammed(bool value)
Определения Weapon_Base.c:407
const int SAMF_RNG
Random bullet quantity + maybe chambered round.
Определения Weapon_Base.c:43
bool InitReliability(out array< float > reliability_array)
Определения Weapon_Base.c:1270
override void EEItemAttached(EntityAI item, string slot_name)
Определения Weapon_Base.c:1091
bool InitWeaponLength()
gets weapon length from config for weaponlift raycast
Определения Weapon_Base.c:1281
override void OnInventoryEnter(Man player)
Определения Weapon_Base.c:1067
bool IsWeaponOpen()
Определения Weapon_Base.c:161
override void SetBayonetAttached(bool pState, int slot_idx=-1)
attachment helpers (firearm melee)
Определения Weapon_Base.c:1795
int GetInternalStateID()
Определения Weapon_Base.c:650
Magazine m_magazine
Определения Events.c:38
void WriteToContext(ParamsWriteContext ctx)
Определения Events.c:54
DayZPlayer m_player
Определения Events.c:37
WeaponEventID GetEventID()
returns id from enum WeaponEventID
Определения Events.c:42
signalize mechanism manipulation
Определения Events.c:35
weapon finite state machine
script counterpart to engine's class Weapon
Определения InventoryItem.c:49
override bool IsDischarged()
Определения Pistol_Base.c:82
override bool HasBullet()
Определения Crossbow.c:31
override bool HasMagazine()
Определения Crossbow.c:32
represents weapon's stable state (i.e. the basic states that the weapon will spend the most time in)
Определения Crossbow.c:27
represent weapon state base
Определения BulletHide.c:2
void AddCalcDetails(string details)
Определения Debug.c:822
void SetCalcDetails(string details)
Определения Debug.c:816
Определения Debug.c:799
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
proto string ToString(bool simple=true)
proto vector Normalized()
return normalized vector (keeps orginal vector untouched)
proto vector Multiply4(vector mat[4])
Transforms position.
static vector RotateAroundZeroDeg(vector vec, vector axis, float angle)
Rotate a vector around 0,0,0 by an angle in degrees.
Определения EnConvert.c:450
static float Dot(vector v1, vector v2)
Returns Dot product of vector v1 and vector v2.
Определения EnConvert.c:271
static const vector Zero
Определения EnConvert.c:110
proto vector InvMultiply3(vector mat[3])
Invert-transforms vector.
static const vector Up
Определения EnConvert.c:107
static proto native vector Lerp(vector v1, vector v2, float t)
Lerp between two vectors.
proto vector AnglesToVector()
Converts spherical coordinates (yaw, pitch, roll in degrees) to unit length vector.
Определения EnConvert.c:106
override string GetDebugName()
Определения dayzplayer.c:1170
DayZPlayerInstanceType
defined in C++
Определения dayzplayer.c:1068
DayZPlayerConstants
defined in C++
Определения dayzplayer.c:602
Serializer ParamsReadContext
Определения gameplay.c:15
proto native CGame GetGame()
Serializer ParamsWriteContext
Определения gameplay.c:16
const int COLOR_BLUE
Определения constants.c:66
const int COLOR_RED
Определения constants.c:64
const int COLOR_GREEN
Определения constants.c:65
const int COLOR_WHITE
Определения constants.c:63
const int COLOR_YELLOW
Определения constants.c:67
void Error(string err)
Messagebox with error message.
Определения EnDebug.c:90
proto void Print(void var)
Prints content of variable to console/log.
enum ShapeType ErrorEx
CollisionFlags
Определения EnDebug.c:141
ShapeFlags
Определения EnDebug.c:126
static proto native void End()
static proto native void Begin(string windowTitle, float x=0, float y=0)
static proto native void Text(string label)
static proto void BeginCleanupScope()
static proto native void EndCleanupScope()
class DiagMenu Shape
don't call destructor directly. Use Destroy() instead
static proto int GetValue(int id)
Get value as int from the given script id.
static proto bool CastTo(out Class to, Class from)
Try to safely down-cast base class to child class.
array< string > TStringArray
Определения EnScript.c:685
proto native vector Vector(float x, float y, float z)
Vector constructor from components.
static proto void YawPitchRollMatrix(vector ang, out vector mat[3])
Creates rotation matrix from angles.
static proto void MatrixMultiply3(vector mat0[3], vector mat1[3], out vector res[3])
Transforms rotation matrix.
static proto float Max(float x, float y)
Returns bigger of two given values.
static proto float Asin(float s)
Returns angle in radians from sinus.
static proto float Acos(float c)
Returns angle in radians from cosinus.
static proto float Clamp(float value, float min, float max)
Clamps 'value' to 'min' if it is lower than 'min', or to 'max' if it is higher than 'max'.
static proto float InverseLerp(float a, float b, float value)
Calculates the linear value that produces the interpolant value within the range [a,...
static const float RAD2DEG
Определения EnMath.c:16
static const float DEG2RAD
Определения EnMath.c:17
static int RandomIntInclusive(int min, int max)
Returns a random int number between and min [inclusive] and max [inclusive].
Определения EnMath.c:54
@ NONE
No flags.
Определения EnProfiler.c:11
class JsonUndergroundAreaTriggerData GetPosition
Определения UndergroundAreaLoader.c:9
const int CALL_CATEGORY_GAMEPLAY
Определения tools.c:10