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