Dayz Explorer 1.28.160049
Loading...
Searching...
No Matches
weaponmanager.c
Go to the documentation of this file.
2{
3 const float MAX_DROP_MAGAZINE_DISTANCE_SQ = 4;
4
6
7 protected int m_LastAcknowledgmentID;
8
10 protected Magazine m_PendingTargetMagazine;
12 protected int m_PendingWeaponAction;
14
15 protected bool m_canEnd;
16 protected bool m_justStart;
17 protected bool m_InProgress;
18 protected bool m_IsEventSended;
19 protected bool m_WantContinue;
20 protected bool m_InIronSight;
21 protected bool m_InOptic;
22 protected bool m_readyToStart;
24 protected MagazineStorage m_MagazineInHand;
27
28 protected const int FORCE_EJECT_BULLET_TIMEOUT = 2000;
29#ifdef DIAG_DEVELOPER
30 protected int m_BurstOption;
31#endif
32 //Reload
36 protected Magazine m_PreparedMagazine;
37
38 //Jamming
39 protected float m_NewJamChance;
40 protected bool m_WaitToSyncJamChance;
41
42
44
46 {
48 m_player = player;
52 m_WeaponInHand = NULL;
53 m_MagazineInHand = NULL;
54 m_ControlAction = NULL;
57 m_InProgress = false;
58 m_WantContinue = true;
59 m_IsEventSended = false;
60 m_canEnd = false;
61 m_readyToStart = false;
63
64 m_NewJamChance = -1;
66
70 m_PreparedMagazine = null;
71
72#ifdef DEVELOPER
73 m_BurstOption = 0;
74#endif
75 }
76//----------------------------------------------------------------------------
77// Weapon Action conditions
78//----------------------------------------------------------------------------
80 {
81 if( m_player.GetHumanInventory().GetEntityInHands() != wpn )
82 return false;
83
84 if( m_player.IsLiftWeapon() || !m_player.IsRaised() || wpn.IsDamageDestroyed() || m_player.GetDayZPlayerInventory().IsProcessing() || !m_player.IsWeaponRaiseCompleted() || m_player.IsFighting() )
85 return false;
86
87 return !wpn.IsCoolDown();
88 }
89
90
91 bool CanAttachMagazine(Weapon_Base wpn, Magazine mag, bool reservationCheck = true )
92 {
93 if ( !wpn || !mag )
94 return false;
95
96 if ( m_player.GetHumanInventory().GetEntityInHands() != wpn )
97 return false;
98
99 if ( wpn.IsDamageDestroyed())
100 return false;
101
102 //if ( mag.GetHierarchyRootPlayer() && mag.GetHierarchyRootPlayer() != m_player )
103 //return false;
104
105 if( m_player.IsItemsToDelete())
106 return false;
107
108 if ( reservationCheck && (m_player.GetInventory().HasInventoryReservation(wpn, null) || m_player.GetInventory().HasInventoryReservation(mag, null)))
109 return false;
110
111 InventoryLocation invLoc;
112 invLoc = new InventoryLocation();
113
114 mag.GetInventory().GetCurrentInventoryLocation(invLoc);
115 Weapon_Base wnp2;
116
117
118 //magazine is already in weapon
119 if ( Class.CastTo(wnp2, invLoc.GetParent()) )
120 return false;
121
122 int muzzleIndex = wpn.GetCurrentMuzzle();
123
124 if (wpn.CanAttachMagazine(muzzleIndex, mag))
125 return true;
126
127 return false;
128
129 }
130//---------------------------------------------------------------------------
131
132 bool CanSwapMagazine(Weapon_Base wpn, Magazine mag, bool reservationCheck = true)
133 {
134 if ( !wpn || !mag )
135 return false;
136
137 if ( m_player.GetHumanInventory().GetEntityInHands() != wpn )
138 return false;
139
140 if ( mag.IsDamageDestroyed() || wpn.IsDamageDestroyed())
141 return false;
142
143 //if ( mag.GetHierarchyRootPlayer() && mag.GetHierarchyRootPlayer() != m_player )
144 //return false;
145
146 if( m_player.IsItemsToDelete())
147 return false;
148
149 if ( reservationCheck && (m_player.GetInventory().HasInventoryReservation(wpn, null) || m_player.GetInventory().HasInventoryReservation(mag, null)))
150 return false;
151
152
153 InventoryLocation invLoc;
154 invLoc = new InventoryLocation();
155
156 mag.GetInventory().GetCurrentInventoryLocation(invLoc);
157 Weapon_Base wnp2;
158
159 //second magazine is already in weapon
160 if( Class.CastTo(wnp2, invLoc.GetParent()) )
161 return false;
162
163 int muzzleIndex = wpn.GetCurrentMuzzle();
164
165 Magazine mag2;
166 if( !Class.CastTo(mag2, wpn.GetMagazine(muzzleIndex)) )
167 return false;
168
169 if( GameInventory.CanSwapEntitiesEx( mag, mag2 ) )
170 return true;
171
173
174 if( GameInventory.CanForceSwapEntitiesEx( mag, null, mag2, il ) )
175 return true;
176
177 return false;
178 }
179//----------------------------------------------------------------------------
180 bool CanDetachMagazine(Weapon_Base wpn, Magazine mag, bool reservationCheck = true)
181 {
182 if ( !wpn || !mag )
183 return false;
184
185 if ( m_player.GetHumanInventory().GetEntityInHands() != wpn )
186 return false;
187
188 if ( mag.GetHierarchyParent() != wpn )
189 return false;
190
191 if( m_player.IsItemsToDelete())
192 return false;
193
194 if ( reservationCheck && (m_player.GetInventory().HasInventoryReservation(wpn, null) || m_player.GetInventory().HasInventoryReservation(mag, null)))
195 return false;
196
197 return true;
198 }
199//---------------------------------------------------------------------------
200 bool CanLoadBullet(Weapon_Base wpn, Magazine mag, bool reservationCheck = true)
201 {
202 if (!wpn || !mag)
203 return false;
204
205 if (m_player.GetHumanInventory().GetEntityInHands() != wpn)
206 return false;
207
208 if (mag.IsDamageDestroyed() || wpn.IsDamageDestroyed())
209 return false;
210
211 if (wpn.IsJammed())
212 return false;
213
214 if (m_player.IsItemsToDelete())
215 return false;
216
217 if (reservationCheck && (m_player.GetInventory().HasInventoryReservation(wpn, null) || m_player.GetInventory().HasInventoryReservation(mag, null)))
218 return false;
219
220 for (int i = 0; i < wpn.GetMuzzleCount(); i++)
221 {
222 if (wpn.CanChamberBullet(i, mag))
223 {
224 return true;
225 }
226 }
227
228 return false;
229 }
230//---------------------------------------------------------------------------
231 bool CanLoadMultipleBullet(Weapon_Base wpn, Magazine mag, bool reservationCheck = true)
232 {
233 if (!wpn || !mag)
234 return false;
235
236 if (m_player.GetHumanInventory().GetEntityInHands() != wpn)
237 return false;
238
239 if (mag.IsDamageDestroyed() || wpn.IsDamageDestroyed())
240 return false;
241
242 if (wpn.IsJammed())
243 return false;
244
245 if (m_player.IsItemsToDelete())
246 return false;
247
248 if (reservationCheck && (m_player.GetInventory().HasInventoryReservation(wpn, null) || m_player.GetInventory().HasInventoryReservation(mag, null)))
249 return false;
250
251 bool found = false;
252 bool fireout = false;
253 for (int i = 0; i < wpn.GetMuzzleCount(); i++)
254 {
255 if (fireout)
256 return true;
257
258 if (wpn.CanChamberBullet(i, mag) )
259 {
260 if (found)
261 {
262 return true;
263 }
264
265 if (wpn.HasInternalMagazine(i))
266 {
267 if ((wpn.GetInternalMagazineCartridgeCount(i)) < wpn.GetInternalMagazineMaxCartridgeCount(i))
268 {
269 return true;
270 }
271 }
272
273 if (wpn.IsChamberFiredOut(i))
274 {
275 if (i > 0)
276 return true;
277 fireout = true;
278 }
279 found = true;
280 }
281 }
282
283 return false;
284 }
285//---------------------------------------------------------------------------
286 bool CanUnjam(Weapon_Base wpn, bool reservationCheck = true)
287 {
288 if( !wpn )
289 return false;
290
291 if( m_player.GetHumanInventory().GetEntityInHands() != wpn)
292 return false;
293
294 if( wpn.IsDamageDestroyed())
295 return false;
296
297 if( m_player.IsItemsToDelete())
298 return false;
299
300 if ( reservationCheck && m_player.GetInventory().HasInventoryReservation(wpn, null))
301 return false;
302
303
304 if( !wpn.IsJammed(/*wpn.GetCurrentMuzzle()*/) )
305 return false;
306
307 return true;
308 }
309
310 bool CanEjectBullet(Weapon_Base wpn, bool reservationCheck = true)
311 {
312 if( !wpn )
313 return false;
314
315 if( m_player.GetHumanInventory().GetEntityInHands() != wpn)
316 return false;
317
318 if( m_player.IsItemsToDelete())
319 return false;
320
321 if( reservationCheck && m_player.GetInventory().HasInventoryReservation(wpn, null))
322 return false;
323
324 if( !wpn.CanEjectBullet() )
325 return false;
326
327 if( wpn.IsJammed(/*wpn.GetCurrentMuzzle()*/) )
328 return false;
329
330 return true;
331 }
332
337//----------------------------------------------------------------------------
338 bool InventoryReservation( Magazine mag, InventoryLocation invLoc)
339 {
340 Weapon_Base weapon;
341 InventoryLocation ilWeapon = new InventoryLocation();
342 if (Weapon_Base.CastTo(weapon, m_player.GetItemInHands()) )
343 {
344 weapon.GetInventory().GetCurrentInventoryLocation(ilWeapon);
345 if ( m_player.GetInventory().HasInventoryReservation(weapon, ilWeapon) )
346 {
347 return false;
348 }
349 else
350 {
351 m_player.GetInventory().AddInventoryReservationEx(weapon,ilWeapon,GameInventory.c_InventoryReservationTimeoutMS);
352 }
353 }
354
355 if( invLoc )
356 {
357 if ( m_player.GetInventory().HasInventoryReservation(invLoc.GetItem(),invLoc) )
358 {
359 m_player.GetInventory().ClearInventoryReservationEx(weapon, ilWeapon);
360 return false;
361 }
362 else
363 {
364 m_player.GetInventory().AddInventoryReservationEx(invLoc.GetItem(),invLoc,GameInventory.c_InventoryReservationTimeoutMS);
365 }
366 }
367
368 if( mag )
369 {
371 m_TargetInventoryLocation.SetAttachment( m_WeaponInHand, mag, InventorySlots.MAGAZINE);
372
373 if ( m_player.GetInventory().HasInventoryReservation(mag, m_TargetInventoryLocation) )
374 //if ( !m_player.GetInventory().AddInventoryReservationEx( mag, m_TargetInventoryLocation, GameInventory.c_InventoryReservationTimeoutMS) )
375 {
376 m_player.GetInventory().ClearInventoryReservationEx(weapon, ilWeapon);
377 if (invLoc)
378 {
379 m_player.GetInventory().ClearInventoryReservationEx(invLoc.GetItem(), invLoc);
380 }
381 return false;
382 }
383 else
384 {
385 m_player.GetInventory().AddInventoryReservationEx(mag, m_TargetInventoryLocation, GameInventory.c_InventoryReservationTimeoutMS);
386 }
387 }
390
391 return true;
392 }
393
394//----------------------------------------------------------------------------
395// Weapon Actions
396//----------------------------------------------------------------------------
397 bool AttachMagazine( Magazine mag , ActionBase control_action = NULL )
398 {
399 return StartAction(AT_WPN_ATTACH_MAGAZINE, mag, NULL, control_action);
400 }
401
402 bool DetachMagazine( InventoryLocation invLoc, ActionBase control_action = NULL)
403 {
404 return StartAction(AT_WPN_DETACH_MAGAZINE, NULL, invLoc, control_action);
405 }
406
407 bool SwapMagazine( Magazine mag, ActionBase control_action = NULL )
408 {
410 if (PrepareInventoryLocationForMagazineSwap(m_WeaponInHand, mag, il) )
411 {
412 return StartAction(AT_WPN_SWAP_MAGAZINE, mag, il, control_action);
413 }
414 return false;
415 }
416
417 bool SwapMagazineEx( Magazine mag, InventoryLocation invLoc, ActionBase control_action = NULL )
418 {
419 return StartAction(AT_WPN_SWAP_MAGAZINE, mag, invLoc, control_action);
420 }
421
422 bool LoadBullet( Magazine mag, ActionBase control_action = NULL )
423 {
424 return StartAction(AT_WPN_LOAD_BULLET, mag, NULL, control_action);
425 }
426
427 bool LoadMultiBullet( Magazine mag, ActionBase control_action = NULL )
428 {
429 return StartAction(AT_WPN_LOAD_MULTI_BULLETS_START, mag, NULL, control_action);
430 }
431
433 {
434 if(m_InProgress) m_WantContinue = false;
435 }
436
437 bool Unjam( ActionBase control_action = NULL )
438 {
439 return StartAction(AT_WPN_UNJAM, NULL, NULL, control_action);
440 }
441
442 bool EjectBullet( ActionBase control_action = NULL )
443 {
444 return StartAction(AT_WPN_EJECT_BULLET, NULL, NULL, control_action);
445 }
446
448 {
449 int mi = m_WeaponInHand.GetCurrentMuzzle();
450 if( !m_WeaponInHand.IsChamberFiredOut(mi) && !m_WeaponInHand.IsChamberEmpty(mi) )
451 {
452 int actual_time = GetGame().GetTime();
454 {
455 return false;
456 }
457 }
458 return true;
459 }
460
461 bool EjectBulletVerified( ActionBase control_action = NULL )
462 {
463 if ( m_WeaponInHand )
464 {
465 int mi = m_WeaponInHand.GetCurrentMuzzle();
466 if ( !m_WeaponInHand.IsChamberFiredOut(mi) && !m_WeaponInHand.IsChamberEmpty(mi) )
467 {
469 return StartAction(AT_WPN_EJECT_BULLET, NULL, NULL, control_action);
470 }
471 else
472 {
473 return StartAction(AT_WPN_EJECT_BULLET, NULL, NULL, control_action);
474 }
475 }
476 return false;
477 }
478
480 {
481 return StartAction(AT_WPN_SET_NEXT_MUZZLE_MODE, NULL, NULL, NULL);
482 }
483
485 {
486 int mi = wpn.GetCurrentMuzzle();
487 if ( wpn.IsChamberFiredOut(mi) || wpn.IsJammed() || wpn.IsChamberEmpty(mi) )
488 {
489 wpn.ProcessWeaponEvent(new WeaponEventTrigger(m_player));
490 return;
491 }
492
493 if (wpn.JamCheck(0))
494 {
495 wpn.ProcessWeaponEvent(new WeaponEventTriggerToJam(m_player));
496 }
497 else
498 {
499 wpn.ProcessWeaponEvent(new WeaponEventTrigger(m_player));
500 }
501 }
502
503#ifdef DIAG_DEVELOPER
504 int GetBurstOption()
505 {
506 return m_BurstOption;
507 }
508
509 void SetBurstOption(int value)
510 {
511 m_BurstOption = value;
512 }
513#endif
514//-------------------------------------------------------------------------------------
515// Synchronize - initialize from client side
516//-------------------------------------------------------------------------------------
517
518 //Client
519 private void Synchronize( )
520 {
521 if ( GetGame().IsClient() )
522 {
525
526 ctx.Write(INPUT_UDT_WEAPON_ACTION);
527 ctx.Write(m_PendingWeaponAction);
529
530
531 switch (m_PendingWeaponAction)
532 {
534 {
535 ctx.Write(m_PendingTargetMagazine);
536 break;
537 }
539 {
540 ctx.Write(m_PendingTargetMagazine);
541 m_PendingInventoryLocation.WriteToContext(ctx);
542 break;
543 }
545 {
546 m_PendingInventoryLocation.WriteToContext(ctx);
547 break;
548 }
550 {
551 ctx.Write(m_PendingTargetMagazine);
552 break;
553 }
555 {
556 ctx.Write(m_PendingTargetMagazine);
557 break;
558 }
559 case AT_WPN_UNJAM:
560 {
561 break;
562 }
564 {
565 break;
566 }
567 default:
568 break;
569 }
570 ctx.Send();
571 //if( !m_player.GetDayZPlayerInventory().HasLockedHands() )
572 // m_player.GetDayZPlayerInventory().LockHands();
573 }
574 }
575
576
577
578 void OnSyncJuncture(int pJunctureID, ParamsReadContext pCtx)
579 {
580 if (pJunctureID == DayZPlayerSyncJunctures.SJ_WEAPON_SET_JAMMING_CHANCE )
581 {
582 pCtx.Read(m_NewJamChance);
583 }
584 else
585 {
586 int AcknowledgmentID;
587 pCtx.Read(AcknowledgmentID);
588 if ( AcknowledgmentID == m_PendingWeaponActionAcknowledgmentID)
589 {
590 if (pJunctureID == DayZPlayerSyncJunctures.SJ_WEAPON_ACTION_ACK_ACCEPT)
591 {
592 m_readyToStart = true;
593 }
594 else if (pJunctureID == DayZPlayerSyncJunctures.SJ_WEAPON_ACTION_ACK_REJECT)
595 {
596 if(m_PendingWeaponAction >= 0 )
597 {
598 if(!(GetGame().IsServer() && GetGame().IsMultiplayer()))
599 {
600 InventoryLocation ilWeapon = new InventoryLocation();
601 ItemBase weapon = m_player.GetItemInHands();
602 weapon.GetInventory().GetCurrentInventoryLocation(ilWeapon);
603 m_player.GetInventory().ClearInventoryReservationEx(m_player.GetItemInHands(),ilWeapon);
604
606 {
607 m_PendingTargetMagazine.GetInventory().ClearInventoryReservationEx(m_PendingTargetMagazine, m_TargetInventoryLocation );
608 }
609
611 {
612 m_player.GetInventory().ClearInventoryReservationEx( NULL, m_PendingInventoryLocation );
613 }
614 }
619 m_InProgress = false;
620 }
621 }
622 }
623 }
624 }
625
626
627 //Server
628 bool OnInputUserDataProcess(int userDataType, ParamsReadContext ctx)
629 {
630 Weapon_Base wpn;
631 int mi;
633 int slotID;
634 bool accepted = false;
635 if( userDataType == INPUT_UDT_WEAPON_ACTION)
636 {
637 if (!ctx.Read(m_PendingWeaponAction))
638 return false;
639
641 return false;
642
644 {
645 GetGame().ClearJunctureEx(m_player, m_PendingTargetMagazine);
647 }
648 m_InProgress = true;
649 m_IsEventSended = false;
650 Magazine mag = NULL;
651
652 Weapon_Base.CastTo( wpn, m_player.GetItemInHands() );
653 if ( wpn )
654 mi = wpn.GetCurrentMuzzle();
655
656 switch (m_PendingWeaponAction)
657 {
659 {
660 if ( !ctx.Read(mag) )
661 break;
662
663 if ( !mag || !wpn )
664 break;
665
666 slotID = wpn.GetSlotFromMuzzleIndex(mi);
667 il = new InventoryLocation();
668 il.SetAttachment(wpn,mag,slotID);
669 if( GetGame().AddInventoryJunctureEx(m_player, mag, il, false, 10000) )
670 accepted = true;
671
673 break;
674 }
676 {
677 if ( !ctx.Read(mag) )
678 break;
679
680 il = new InventoryLocation();
681 if (!il.ReadFromContext(ctx))
682 break;
683
684 if ( !mag || !wpn )
685 break;
686
687 if ( !wpn.GetMagazine(mi) )
688 break;
689
690 if ( GetGame().AddActionJuncture(m_player,mag,10000) )
691 accepted = true;
694
695 break;
696 }
698 {
699 il = new InventoryLocation();
700 if ( !il.ReadFromContext(ctx) )
701 break;
702
703 if ( !il.IsValid() )
704 break;
705
706 if ( !wpn )
707 break;
708
709 Magazine det_mag = wpn.GetMagazine(mi);
710 mag = Magazine.Cast(il.GetItem());
711 if ( !det_mag || ( mag != det_mag) )
712 break;
713
714 if (GetGame().AddInventoryJunctureEx(m_player, il.GetItem(), il, true, 10000))
715 accepted = true;
718 break;
719 }
721 {
722 ctx.Read(mag);
723
724 if ( !mag )
725 break;
726
727 if( GetGame().AddActionJuncture(m_player,mag,10000) )
728 accepted = true;
730 break;
731 }
733 {
734 ctx.Read(mag);
735
736 if ( !mag )
737 break;
738
739 if( GetGame().AddActionJuncture(m_player,mag,10000) )
740 accepted = true;
742 break;
743 }
744 case AT_WPN_UNJAM:
745 {
746 accepted = true;
747 //Unjam();
748 break;
749 }
751 {
752 accepted = true;
753 break;
754 }
756 {
757 accepted = true;
758 break;
759 }
760 default:
761 Error("unknown actionID=" + m_PendingWeaponAction);
762 break;
763 }
764 DayZPlayerSyncJunctures.SendWeaponActionAcknowledgment(m_player, m_PendingWeaponActionAcknowledgmentID, accepted);
765 }
766
767 return accepted;
768 }
769
770 bool StartAction(int action, Magazine mag, InventoryLocation il, ActionBase control_action = NULL)
771 {
772 //if it is controled by action inventory reservation and synchronization provide action itself
773 if(control_action)
774 {
775 m_ControlAction = ActionBase.Cast(control_action);
776 m_PendingWeaponAction = action;
777 m_InProgress = true;
778 m_IsEventSended = false;
781 StartPendingAction();
782
783 return true;
784 }
785
786
787 if (GetGame().IsMultiplayer() && GetGame().IsServer())
788 return false;
789
790 if ( !ScriptInputUserData.CanStoreInputUserData() )
791 return false;
792 if ( !InventoryReservation(mag, il) )
793 return false;
794
795 m_PendingWeaponAction = action;
796 m_InProgress = true;
797 m_IsEventSended = false;
798
799 if ( !GetGame().IsMultiplayer() )
800 m_readyToStart = true;
801 else
802 Synchronize();
803
804 return true;
805 }
806
807 void StartPendingAction()
808 {
809 m_WeaponInHand = Weapon_Base.Cast(m_player.GetItemInHands());
810 if(!m_WeaponInHand)
811 {
812 OnWeaponActionEnd();
813 return;
814 }
815 switch (m_PendingWeaponAction)
816 {
818 {
819 m_player.GetDayZPlayerInventory().PostWeaponEvent( new WeaponEventAttachMagazine(m_player, m_PendingTargetMagazine) );
820 break;
821 }
823 {
824 m_player.GetDayZPlayerInventory().PostWeaponEvent( new WeaponEventSwapMagazine(m_player, m_PendingTargetMagazine, m_PendingInventoryLocation) );
825 break;
826 }
828 {
829 Magazine mag = Magazine.Cast(m_PendingInventoryLocation.GetItem());
830 m_player.GetDayZPlayerInventory().PostWeaponEvent( new WeaponEventDetachMagazine(m_player, mag, m_PendingInventoryLocation) );
831 break;
832 }
834 {
835 m_WantContinue = false;
836 m_player.GetDayZPlayerInventory().PostWeaponEvent( new WeaponEventLoad1Bullet(m_player, m_PendingTargetMagazine) );
837 break;
838 }
840 {
841 m_player.GetDayZPlayerInventory().PostWeaponEvent( new WeaponEventLoad1Bullet(m_player, m_PendingTargetMagazine) );
842 break;
843 }
845 {
846 m_player.GetDayZPlayerInventory().PostWeaponEvent( new WeaponEventContinuousLoadBulletEnd(m_player) );
847 break;
848 }
849 case AT_WPN_UNJAM:
850 {
851 m_player.GetDayZPlayerInventory().PostWeaponEvent( new WeaponEventUnjam(m_player, NULL) );
852 break;
853 }
855 {
856 m_player.GetDayZPlayerInventory().PostWeaponEvent( new WeaponEventMechanism(m_player, NULL) );
857 break;
858 }
860 {
861 m_player.GetDayZPlayerInventory().PostWeaponEvent( new WeaponEventSetNextMuzzleMode(m_player, NULL) );
862 break;
863 }
864 default:
865 m_InProgress = false;
866 Error("unknown actionID=" + m_PendingWeaponAction);
867 }
868 m_IsEventSended = true;
869 m_canEnd = false;
870 }
871
872 bool IsRunning()
873 {
874 return m_InProgress;
875 }
876
877 void SetRunning( bool value)
878 {
879 m_InProgress = value;
880 }
881
882 void Refresh()
883 {
884 OnWeaponActionEnd();
885 }
886
887 void Update( float deltaT )
888 {
889 if (m_WeaponInHand != m_player.GetItemInHands())
890 {
891 if( m_WeaponInHand )
892 {
893 m_SuitableMagazines.Clear();
894 OnWeaponActionEnd();
895 }
896 m_WeaponInHand = Weapon_Base.Cast(m_player.GetItemInHands());
897 if ( m_WeaponInHand )
898 {
899 m_MagazineInHand = null;
900 //SET new magazine
901 SetSutableMagazines();
902 m_WeaponInHand.SetSyncJammingChance(0);
903 }
905 }
906
907 if (m_WeaponInHand)
908 {
910 {
912
914 {
915 RefreshAnimationState();
916 }
917 }
918
919 if (!GetGame().IsMultiplayer())
920 {
921 m_WeaponInHand.SetSyncJammingChance(m_WeaponInHand.GetChanceToJam());
922 }
923 else
924 {
925 if ( m_NewJamChance >= 0)
926 {
927 m_WeaponInHand.SetSyncJammingChance(m_NewJamChance);
928 m_NewJamChance = -1;
929 m_WaitToSyncJamChance = false;
930 }
931 if (GetGame().IsServer() && !m_WaitToSyncJamChance )
932 {
933 float actual_chance_to_jam;
934 actual_chance_to_jam = m_WeaponInHand.GetChanceToJam();
935 if ( Math.AbsFloat(m_WeaponInHand.GetSyncChanceToJam() - m_WeaponInHand.GetChanceToJam()) > 0.001 )
936 {
937 DayZPlayerSyncJunctures.SendWeaponJamChance(m_player, m_WeaponInHand.GetChanceToJam());
939 }
940 }
941 }
942
944 {
945 StartPendingAction();
946 m_readyToStart = false;
947 return;
948 }
949
951 return;
952
953 if(m_canEnd)
954 {
955 if(m_WeaponInHand.IsIdle())
956 {
957 OnWeaponActionEnd();
958 }
959 else if(m_justStart)
960 {
961 m_InIronSight = m_player.IsInIronsights();
962 m_InOptic = m_player.IsInOptics();
963
965 {
966 //'RequestResetADSSync' can be called here, if ADS reset is desired
967 m_player.ExitSights();
968 }
969
970 m_justStart = false;
971 }
972
973 }
974 else
975 {
976 m_canEnd = true;
977 m_justStart = true;
978 }
979 }
980 else
981 {
982 if ( m_MagazineInHand != m_player.GetItemInHands() )
983 {
984 m_MagazineInHand = MagazineStorage.Cast(m_player.GetItemInHands());
985 if ( m_MagazineInHand )
986 {
987 SetSutableMagazines();
988 }
989 }
990
991
992 }
993 }
994
995 void OnWeaponActionEnd()
996 {
997 if ( !m_InProgress )
998 return;
999
1000 if (!m_ControlAction)
1001 {
1002 if (GetGame().IsServer() && GetGame().IsMultiplayer())
1003 {
1005 {
1006 GetGame().ClearJunctureEx(m_player,m_PendingTargetMagazine);
1007 }
1008 }
1009 else
1010 {
1012 il.SetHands(m_player,m_player.GetItemInHands());
1013 m_player.GetInventory().ClearInventoryReservationEx(m_player.GetItemInHands(),il);
1014
1016 {
1017 m_player.GetInventory().ClearInventoryReservationEx(m_PendingTargetMagazine, m_TargetInventoryLocation );
1018 }
1019
1021 {
1022 m_player.GetInventory().ClearInventoryReservationEx( m_PendingInventoryLocation.GetItem(), m_PendingInventoryLocation );
1023 }
1024 }
1025 }
1026
1027 m_ControlAction = NULL;
1033 //m_WeaponInHand = NULL;
1034 m_InProgress = false;
1035 m_readyToStart = false;
1036 m_WantContinue = true;
1037
1038 }
1039
1040 void DelayedRefreshAnimationState(int delay)
1041 {
1042 if(m_WeaponInHand)
1043 {
1044 if(delay == 0)
1045 {
1046 RefreshAnimationState();
1047 }
1049 }
1050 }
1051
1052 void RefreshAnimationState()
1053 {
1054 if(m_WeaponInHand)
1055 {
1056 WeaponStableState state = WeaponStableState.Cast( m_WeaponInHand.GetCurrentState() );
1057
1058 if (state)
1059 {
1060 HumanCommandWeapons hcw = m_player.GetCommandModifier_Weapons();
1061 if (hcw)
1062 {
1063 hcw.SetInitState(state.m_animState);
1064 }
1065 }
1066 }
1067 }
1068
1069 bool WantContinue()
1070 {
1071 return m_WantContinue;
1072 }
1073
1074 Magazine GetPreparedMagazine()
1075 {
1076 Magazine mag;
1077 for (int i = 0; i < m_SuitableMagazines.Count(); i++)
1078 {
1079 mag = m_SuitableMagazines[i];
1080 if (!mag || mag.IsRuined() || (mag.GetHierarchyParent() && mag.GetHierarchyParent().IsWeapon()) )
1081 {
1082 m_SuitableMagazines.Remove(i);
1083 i--;
1084 continue;
1085 }
1086
1087 if(!mag.GetHierarchyParent() || mag.GetHierarchyParent().GetInventory().AreChildrenAccessible())
1088 {
1089 if (mag.GetAmmoCount() > 0)
1090 return mag;
1091 }
1092 }
1093
1094 return null;
1095 }
1096
1097 Magazine GetNextPreparedMagazine( out int startIdx )
1098 {
1099 int count = m_SuitableMagazines.Count();
1100 Magazine mag;
1101 for (int i = startIdx; i < count; i++)
1102 {
1103 mag = m_SuitableMagazines[i];
1104 if (mag && mag.GetAmmoCount() > 0 && (!mag.GetHierarchyParent() || mag.GetHierarchyParent().GetInventory().AreChildrenAccessible()))
1105 {
1106 startIdx = i;
1107 return m_SuitableMagazines.Get(i);
1108 }
1109 }
1110 return null;
1111 }
1112
1113 void OnMagazineInventoryEnter(Magazine mag)
1114 {
1115 if (mag)
1116 {
1117 Weapon_Base weapon = Weapon_Base.Cast(mag.GetHierarchyParent());
1118
1119 if (weapon)
1120 return;
1121 }
1122
1123 int i;
1124 MagazineStorage sMag = MagazineStorage.Cast(mag);
1125 if(sMag)
1126 {
1127 for(i = 0; i < m_MagazineStorageInInventory.Count(); i++ )
1128 {
1129 MagazineStorage s_mag_i = m_MagazineStorageInInventory[i];
1130 if(!s_mag_i)
1131 {
1132 m_MagazineStorageInInventory.RemoveOrdered(i);
1133 i--;
1134 continue;
1135 }
1136
1137 if(CompareMagazinesSuitability(s_mag_i,sMag)<0)
1138 break;
1139 }
1140 m_MagazineStorageInInventory.InsertAt(sMag,i);
1141
1142 SetSutableMagazines(); //TODO optimalize
1143 return;
1144 }
1145
1146 if(mag)
1147 {
1148
1149 for(i = 0; i < m_MagazinePilesInInventory.Count(); i++ )
1150 {
1151 Magazine mag_i = m_MagazinePilesInInventory[i];
1152 if(!mag_i)
1153 {
1154 m_MagazinePilesInInventory.RemoveOrdered(i);
1155 i--;
1156 continue;
1157 }
1158
1159
1160 if(CompareMagazinesSuitability(mag_i,mag)<0)
1161 {
1162 break;
1163 }
1164 }
1165 m_MagazinePilesInInventory.InsertAt(mag,i);
1166 SetSutableMagazines(); //TODO optimalize
1167 }
1168
1169 }
1170
1171 void OnMagazineInventoryExit(Magazine mag)
1172 {
1173 m_SuitableMagazines.RemoveItem(mag);
1174
1175 MagazineStorage sMag = MagazineStorage.Cast(mag);
1176 if(sMag)
1177 {
1178 m_MagazineStorageInInventory.RemoveItem(sMag);
1179 return;
1180 }
1181
1182 if(mag)
1183 {
1184 m_MagazinePilesInInventory.RemoveItem(mag);
1185 }
1186 }
1187
1188 void OnMagazineAttach(Magazine mag)
1189 {
1190 OnMagazineInventoryExit(mag);
1191 }
1192
1193 void OnMagazineDetach(Magazine mag)
1194 {
1195 OnMagazineInventoryEnter(mag);
1196 }
1197
1198 int CompareMagazinesSuitability( Magazine mag1, Magazine mag2 )
1199 {
1200 return mag1.GetAmmoCount() - mag2.GetAmmoCount();
1201 }
1202
1203 void SortMagazineAfterLoad()
1204 {
1206 array<Magazine> magazines_piles = new array<Magazine>;
1207 int low_mag1, high_mag1;
1208 int low_mag2, high_mag2;
1209 int i, j;
1210
1211 for(i = 0; i < m_MagazineStorageInInventory.Count(); i++ )
1212 {
1213 MagazineStorage mag = m_MagazineStorageInInventory.Get(i);
1214 mag.GetNetworkID(low_mag1,high_mag1);
1215 for( j = 0; j < magazines.Count(); j++)
1216 {
1217 magazines.Get(j).GetNetworkID(low_mag2,high_mag2);
1218 if(low_mag1 > low_mag2)
1219 {
1220 break;
1221 }
1222 else if (low_mag1 == low_mag2)
1223 {
1224 if( high_mag1 > high_mag2 )
1225 {
1226 break;
1227 }
1228 }
1229 }
1230 magazines.InsertAt(mag,j);
1231 }
1232
1234 m_MagazineStorageInInventory.Copy(magazines);
1235
1236 for(i = 0; i < m_MagazinePilesInInventory.Count(); i++ )
1237 {
1238 Magazine pile = m_MagazinePilesInInventory.Get(i);
1239 pile.GetNetworkID(low_mag1,high_mag1);
1240 for( j = 0; j < magazines_piles.Count(); j++)
1241 {
1242 magazines_piles.Get(j).GetNetworkID(low_mag2,high_mag2);
1243 if(low_mag1 > low_mag2)
1244 {
1245 break;
1246 }
1247 else if (low_mag1 == low_mag2)
1248 {
1249 if( high_mag1 > high_mag2 )
1250 {
1251 break;
1252 }
1253 }
1254 }
1255 magazines_piles.InsertAt(pile,j);
1256 }
1257
1259 m_MagazinePilesInInventory.Copy(magazines_piles);
1260
1261 SetSutableMagazines();
1262 }
1263
1264 void SetSutableMagazines()
1265 {
1266 m_SuitableMagazines.Clear();
1267 int i;
1268
1269 if (m_WeaponInHand)
1270 {
1271 int mi = m_WeaponInHand.GetCurrentMuzzle();
1272
1273 for (i = 0; i < m_MagazineStorageInInventory.Count(); i++ )
1274 {
1275 MagazineStorage s_mag = m_MagazineStorageInInventory[i];
1276
1277 if (!s_mag)
1278 {
1279 m_MagazineStorageInInventory.RemoveOrdered(i);
1280 i--;
1281 continue;
1282 }
1283
1284 if ( m_WeaponInHand.TestAttachMagazine(mi, s_mag, false, true))
1285 m_SuitableMagazines.Insert(s_mag);
1286 }
1287
1288 for (i = 0; i < m_MagazinePilesInInventory.Count(); i++ )
1289 {
1290 Magazine mag = m_MagazinePilesInInventory[i];
1291 if (!mag)
1292 {
1293 m_MagazinePilesInInventory.RemoveOrdered(i);
1294 i--;
1295 continue;
1296 }
1297
1298 if (m_WeaponInHand.CanChamberFromMag(mi, mag))
1299 m_SuitableMagazines.Insert(mag);
1300 }
1301//TODO m_MagazineStorageInInventory and m_MagazinePilesInInventory always sort
1302 }
1303 else if (m_MagazineInHand)
1304 {
1305 for (i = 0; i < m_MagazinePilesInInventory.Count(); i++ )
1306 {
1307 Magazine m_mag = m_MagazinePilesInInventory[i];
1308 if (!m_mag)
1309 {
1310 m_MagazinePilesInInventory.RemoveOrdered(i);
1311 i--;
1312 continue;
1313 }
1314 if (m_MagazineInHand.IsCompatiableAmmo( m_mag ))
1315 m_SuitableMagazines.Insert(m_mag);
1316 }
1317 }
1318 else
1319 {
1320 m_PreparedMagazine = null;
1321 }
1322
1323 }
1324
1325 void OnLiftWeapon()
1326 {
1327 if( m_WeaponInHand )
1328 m_WeaponInHand.ResetBurstCount();
1329 }
1330
1331 string GetCurrentModeName()
1332 {
1333 if( m_WeaponInHand )
1334 {
1335 int mi = m_WeaponInHand.GetCurrentMuzzle();
1336 return m_WeaponInHand.GetCurrentModeName(mi);
1337 }
1338 return "";
1339 }
1340
1341 bool PrepareInventoryLocationForMagazineSwap( notnull Weapon_Base wpn, notnull Magazine new_mag, out InventoryLocation new_il )
1342 {
1343 int muzzleIndex = wpn.GetCurrentMuzzle();
1344 Magazine old_mag = Magazine.Cast(wpn.GetMagazine(muzzleIndex));
1346
1347 if (old_mag)
1348 {
1349 bool result = GameInventory.CanSwapEntitiesEx(new_mag, old_mag);
1350 if ( result )
1351 {
1352 new_mag.GetInventory().GetCurrentInventoryLocation(new_il);
1353 new_il.SetItem(old_mag);
1354 }
1355 else
1356 {
1357 result = GameInventory.CanForceSwapEntitiesEx(new_mag, null, old_mag, new_il);
1358 float dir[4];
1359 if ( !result )
1360 {
1361 new_il.SetGroundEx( old_mag, m_player.GetPosition(), dir);
1362 }
1363 }
1364 }
1365 return true;
1366 }
1367}
const int INPUT_UDT_WEAPON_ACTION
Definition _constants.c:7
const int AT_WPN_DETACH_MAGAZINE
Definition _constants.c:12
const int AT_WPN_LOAD_MULTI_BULLETS_END
Definition _constants.c:17
const int AT_WPN_ATTACH_MAGAZINE
Definition _constants.c:10
const int AT_WPN_LOAD_BULLET
Definition _constants.c:13
const int AT_WPN_UNJAM
Definition _constants.c:14
const int AT_WPN_SWAP_MAGAZINE
Definition _constants.c:11
const int AT_WPN_LOAD_MULTI_BULLETS_START
Definition _constants.c:16
const int AT_WPN_EJECT_BULLET
Definition _constants.c:15
const int AT_WPN_SET_NEXT_MUZZLE_MODE
Definition _constants.c:18
proto int GetTime()
returns mission time in milliseconds
Super root of all classes in Enforce script.
Definition enscript.c:11
script counterpart to engine's class Inventory
Definition inventory.c:79
static bool CanSwapEntitiesEx(notnull EntityAI item1, notnull EntityAI item2)
Definition inventory.c:628
const int c_InventoryReservationTimeoutMS
reservations
Definition inventory.c:712
static bool CanForceSwapEntitiesEx(notnull EntityAI item1, InventoryLocation item1_dst, notnull EntityAI item2, out InventoryLocation item2_dst)
Definition inventory.c:664
InventoryLocation.
provides access to slot configuration
Definition enmath.c:7
Serialization general interface. Serializer API works with:
Definition serializer.c:56
bool EjectBulletVerified(ActionBase control_action=NULL)
PlayerBase m_player
bool CanUnjam(Weapon_Base wpn, bool reservationCheck=true)
bool CanEjectBulletVerified()
bool CanLoadBullet(Weapon_Base wpn, Magazine mag, bool reservationCheck=true)
bool CanAttachMagazine(Weapon_Base wpn, Magazine mag, bool reservationCheck=true)
ActionBase m_ControlAction
int m_PendingWeaponActionAcknowledgmentID
ref array< Magazine > m_MagazinePilesInInventory
bool AttachMagazine(Magazine mag, ActionBase control_action=NULL)
int m_ForceEjectBulletTimestamp
bool LoadBullet(Magazine mag, ActionBase control_action=NULL)
bool CanEjectBullet(Weapon_Base wpn, bool reservationCheck=true)
bool LoadMultiBullet(Magazine mag, ActionBase control_action=NULL)
Magazine m_PendingTargetMagazine
bool DetachMagazine(InventoryLocation invLoc, ActionBase control_action=NULL)
void LoadMultiBulletStop()
bool CanLoadMultipleBullet(Weapon_Base wpn, Magazine mag, bool reservationCheck=true)
bool SetNextMuzzleMode()
int m_LastAcknowledgmentID
bool m_WaitToSyncJamChance
ref array< Magazine > m_SuitableMagazines
bool CanSwapMagazine(Weapon_Base wpn, Magazine mag, bool reservationCheck=true)
Weapon_Base m_WeaponInHand
bool SwapMagazine(Magazine mag, ActionBase control_action=NULL)
const int FORCE_EJECT_BULLET_TIMEOUT
ref array< MagazineStorage > m_MagazineStorageInInventory
bool CanFire(Weapon_Base wpn)
bool CanDetachMagazine(Weapon_Base wpn, Magazine mag, bool reservationCheck=true)
void SetEjectBulletTryTimestamp()
Magazine m_PreparedMagazine
bool Unjam(ActionBase control_action=NULL)
void WeaponManager(PlayerBase player)
ref InventoryLocation m_PendingInventoryLocation
bool SwapMagazineEx(Magazine mag, InventoryLocation invLoc, ActionBase control_action=NULL)
void Fire(Weapon_Base wpn)
ref InventoryLocation m_TargetInventoryLocation
bool EjectBullet(ActionBase control_action=NULL)
int m_PendingWeaponAction
MagazineStorage m_MagazineInHand
int m_AnimationRefreshCooldown
bool InventoryReservation(Magazine mag, InventoryLocation invLoc)
represents weapon's stable state (i.e. the basic states that the weapon will spend the most time in)
Definition crossbow.c:27
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
proto native CGame GetGame()
void Error(string err)
Messagebox with error message.
Definition endebug.c:90