Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_GadgetManagerComponent.c
Go to the documentation of this file.
3 {
4  SCR_GadgetManagerComponent m_GadgetManager;
6 
7  bool m_bIsControlledInit = false; // init flag for controlled entity invokers
8  bool m_bIsDefaultInit = false; // init flag for default invokers
9  bool m_bIsControlledEnt = false; // controlled entity flag
10 
11  //------------------------------------------------------------------------------------------------
13  bool IsInit()
14  {
17 
18  return m_bIsDefaultInit;
19  }
20 
21  //------------------------------------------------------------------------------------------------
25  void InitInvokers(IEntity character, SCR_CharacterControllerComponent controller)
26  {
27  if (m_bIsDefaultInit)
28  return;
29 
30  m_Controller = controller;
31  SCR_InventoryStorageManagerComponent invManager = SCR_InventoryStorageManagerComponent.Cast(character.FindComponent(SCR_InventoryStorageManagerComponent));
32  if (invManager)
33  {
34  m_Controller.m_OnGadgetStateChangedInvoker.Insert(m_GadgetManager.OnGadgetStateChanged);
35  m_Controller.m_OnControlledByPlayer.Insert(m_GadgetManager.OnControlledByPlayer);
36  invManager.m_OnItemAddedInvoker.Insert(m_GadgetManager.OnItemAdded);
37  invManager.m_OnItemRemovedInvoker.Insert(m_GadgetManager.OnItemRemoved);
38 
39  m_bIsDefaultInit = true;
40  }
41  }
42 
43  //------------------------------------------------------------------------------------------------
47  void InitControlledInvokers(IEntity character, SCR_CharacterControllerComponent controller)
48  {
49  if (m_bIsControlledInit)
50  return;
51 
52  m_Controller = controller;
53  m_Controller.GetOnPlayerDeathWithParam().Insert(m_GadgetManager.OnPlayerDeath);
54  m_Controller.m_OnGadgetFocusStateChangedInvoker.Insert(m_GadgetManager.OnGadgetFocusStateChanged);
55 
56  SCR_EditorManagerEntity editorManager = SCR_EditorManagerEntity.GetInstance();
57  if (editorManager)
58  editorManager.GetOnOpened().Insert(m_GadgetManager.OnEditorOpened);
59 
60  m_bIsControlledEnt = true;
61  m_bIsControlledInit = true;
62  }
63 
64  //------------------------------------------------------------------------------------------------
67  void CleanupInvokers(GenericEntity character)
68  {
69  if (m_Controller)
70  {
71  m_Controller.m_OnGadgetStateChangedInvoker.Remove(m_GadgetManager.OnGadgetStateChanged);
72  m_Controller.m_OnControlledByPlayer.Remove(m_GadgetManager.OnControlledByPlayer);
73  }
74 
75  SCR_InventoryStorageManagerComponent invManager = SCR_InventoryStorageManagerComponent.Cast(character.FindComponent(SCR_InventoryStorageManagerComponent));
76  if (invManager)
77  {
78  invManager.m_OnItemAddedInvoker.Remove(m_GadgetManager.OnItemAdded);
79  invManager.m_OnItemRemovedInvoker.Remove(m_GadgetManager.OnItemRemoved);
80  }
81 
82  m_bIsDefaultInit = false;
83  }
84 
85  //------------------------------------------------------------------------------------------------
88  void CleanupLocalInvokers(GenericEntity character)
89  {
90  if (m_Controller)
91  {
92  m_Controller.GetOnPlayerDeathWithParam().Remove(m_GadgetManager.OnPlayerDeath);
93  m_Controller.m_OnGadgetFocusStateChangedInvoker.Remove(m_GadgetManager.OnGadgetFocusStateChanged);
94  }
95 
96  SCR_EditorManagerEntity editorManager = SCR_EditorManagerEntity.GetInstance();
97  if (editorManager)
98  editorManager.GetOnOpened().Remove(m_GadgetManager.OnEditorOpened);
99 
100  m_bIsControlledInit = false;
101  m_bIsControlledEnt = false;
102  }
103 
104  //------------------------------------------------------------------------------------------------
107  void Clear(GenericEntity entity)
108  {
109  if (!entity)
110  return;
111 
112  CleanupLocalInvokers(entity);
113  CleanupInvokers(entity);
114  }
115 
116  //------------------------------------------------------------------------------------------------
117  // constructor
119  void SCR_GadgetInvokersInitState(notnull SCR_GadgetManagerComponent gadgetManager)
120  {
121  m_GadgetManager = gadgetManager;
122  }
123 }
124 
125 [EntityEditorProps(category: "GameScripted/Gadgets", description: "Gadget manager", color: "0 0 255 255")]
126 class SCR_GadgetManagerComponentClass : ScriptGameComponentClass
127 {
128  //------------------------------------------------------------------------------------------------
129  static override bool DependsOn(string className)
130  {
131  if (className == "SCR_CharacterInventoryStorageComponent") // enforce load order here to be able to access storage
132  return true;
133 
134  return false;
135  }
136 }
137 
138 class SCR_GadgetManagerComponent : ScriptGameComponent
139 {
140  int m_iRadiosFlags = EGadgetType.RADIO | EGadgetType.RADIO_BACKPACK;
141 
142  ref ScriptInvoker<SCR_GadgetComponent> m_OnGadgetAdded = new ScriptInvoker(); // called when gadget is added to inventory
143  ref ScriptInvoker<SCR_GadgetComponent> m_OnGadgetRemoved = new ScriptInvoker(); // called when gadget is removed from inventory
144  protected static ref ScriptInvoker<IEntity, SCR_GadgetManagerComponent> s_OnGadgetInitDone = new ScriptInvoker(); // invoked after gadget init is done on a newly spawned character
145 
146  protected bool m_bIsGadgetADS; // is gadget currently in raised state
147  protected IEntity m_HeldGadget;
148  protected SCR_GadgetComponent m_HeldGadgetComponent;
149  protected SCR_GadgetComponent m_HiddenGadgetComponent;
150  protected InputManager m_InputManager;
151  protected SCR_InventoryStorageManagerComponent m_InventoryStorageMgr;
153  protected SCR_VONController m_VONController;
154  protected ref SCR_GadgetInvokersInitState m_pInvokersState = new SCR_GadgetInvokersInitState(this);
155 
156  protected ref array<ref array <SCR_GadgetComponent>> m_aInventoryGadgetTypes = {}; // array of gadget types > array of gadget components
157  protected ref map<EGadgetType, int> m_aGadgetArrayMap = new map<EGadgetType, int>; // map of gadget types -> gadget type array ID
158 
159  //TODO
160  protected SCR_GadgetComponent m_LastHeldGadgetComponent; // hack to make thingy work, unhack me
161 
162  //------------------------------------------------------------------------------------------------
163  // GET/SET METHODS
164  //------------------------------------------------------------------------------------------------
165 
166  //------------------------------------------------------------------------------------------------
168  static ScriptInvoker GetOnGadgetInitDoneInvoker()
169  {
170  return s_OnGadgetInitDone;
171  }
172 
173  //------------------------------------------------------------------------------------------------
176  static SCR_GadgetManagerComponent GetGadgetManager(IEntity entity)
177  {
178  GenericEntity player = GenericEntity.Cast(entity);
179  if (!player)
180  return null;
181 
182  SCR_GadgetManagerComponent gadgetManager = SCR_GadgetManagerComponent.Cast( player.FindComponent(SCR_GadgetManagerComponent) );
183 
184  return gadgetManager;
185  }
186 
187  //------------------------------------------------------------------------------------------------
190  IEntity GetHeldGadget()
191  {
192  if (m_HeldGadget)
193  return m_HeldGadget;
194  else if (m_HiddenGadgetComponent)
195  return m_HiddenGadgetComponent.GetOwner();
196  else
197  return null;
198  }
199 
200  //------------------------------------------------------------------------------------------------
203  bool GetIsGadgetADS()
204  {
205  return m_bIsGadgetADS;
206  }
207 
208  //------------------------------------------------------------------------------------------------
211  SCR_GadgetComponent GetHeldGadgetComponent()
212  {
213  if (m_HeldGadgetComponent)
214  return m_HeldGadgetComponent;
215 
216  return m_HiddenGadgetComponent;
217  }
218 
219  //------------------------------------------------------------------------------------------------
225  void SetGadgetMode(IEntity gadget, EGadgetMode targetMode, bool doFocus = false)
226  {
227  if (!gadget)
228  return;
229 
230  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast( gadget.FindComponent(SCR_GadgetComponent) );
231  if (!gadgetComp)
232  return;
233 
234  if ( targetMode == EGadgetMode.IN_HAND && !gadgetComp.CanBeHeld() )
235  return;
236 
237  // switch mode rules
238  if (!CanChangeGadgetMode(gadget, gadgetComp, targetMode))
239  return;
240 
241  if ( targetMode == EGadgetMode.IN_HAND || gadgetComp.GetMode() == EGadgetMode.IN_HAND || gadgetComp == m_HiddenGadgetComponent ) // If going TO or FROM mode1 -> anims need to happen first. Mode is synched from finish events instead of here
242  {
243  if (!m_Controller)
244  return;
245 
246  if (targetMode == EGadgetMode.IN_HAND) // Gadget to hand
247  {
248  if (m_Controller.GetWeaponADSInput())
249  m_Controller.SetWeaponADSInput(false);
250 
251  if (gadgetComp.CanBeRaised())
252  m_Controller.TakeGadgetInLeftHand(gadget, gadgetComp.GetAnimVariable(), doFocus);
253  else
254  m_Controller.TakeGadgetInLeftHand(gadget, gadgetComp.GetAnimVariable());
255  }
256  else // Gadget from hand
257  {
258  if (targetMode == EGadgetMode.ON_GROUND) // if moving from hand to storage, SetGadgetMode will call hand->ground ground->slot , so we cannot wait for anim to finish to switch mode
259  m_Controller.RemoveGadgetFromHand(true);
260  else
261  m_Controller.RemoveGadgetFromHand(gadgetComp == m_HiddenGadgetComponent);
262 
263  if (gadgetComp.GetType() == EGadgetType.MAP) // TODO hotfix against incorrect toggle set when spamming input, will be solved when map has unfocused & focused mode
264  return;
265 
266  if (gadgetComp.m_bFocused) // close focus state
267  gadgetComp.ToggleFocused(false);
268  }
269  }
270  else // If switching between NONE and MODE0
271  gadgetComp.OnModeChanged(targetMode, GetOwner());
272  }
273 
274  //------------------------------------------------------------------------------------------------
278  static void SetGadgetModeStashed(SCR_GadgetComponent gadgetComp, EGadgetMode targetMode)
279  {
280  if (targetMode != EGadgetMode.ON_GROUND && targetMode != EGadgetMode.IN_STORAGE)
281  return;
282 
283  gadgetComp.OnModeChanged(targetMode, null);
284  }
285 
286  //------------------------------------------------------------------------------------------------
288  void RemoveHeldGadget()
289  {
290  if (m_HeldGadget)
291  SetGadgetMode(m_HeldGadget, EGadgetMode.IN_SLOT); // whether the gadget is actually slotted or put to storage is handled in OnGadgetStateChanged
292  else if (m_HiddenGadgetComponent)
293  SetGadgetMode(m_HiddenGadgetComponent.GetOwner(), EGadgetMode.IN_SLOT);
294  }
295 
296  //------------------------------------------------------------------------------------------------
298  protected void OnActivateHeldGadget()
299  {
300  if (m_HeldGadgetComponent)
301  m_HeldGadgetComponent.ActivateAction();
302  else if (m_HiddenGadgetComponent)
303  m_HiddenGadgetComponent.ActivateAction();
304  }
305 
306  //------------------------------------------------------------------------------------------------
309  void ToggleHeldGadget(bool state)
310  {
311  if (m_HeldGadgetComponent)
312  m_HeldGadgetComponent.ToggleActive(state);
313  else if (m_HiddenGadgetComponent)
314  m_HiddenGadgetComponent.ToggleActive(state);
315  }
316 
317  //------------------------------------------------------------------------------------------------
321  array<SCR_GadgetComponent> GetGadgetsByType(EGadgetType type)
322  {
323  int gadgetArrayID = m_aGadgetArrayMap.Get(type);
324  if (gadgetArrayID != -1)
325  {
326  array<SCR_GadgetComponent> arr = {};
327  arr.Copy(m_aInventoryGadgetTypes[gadgetArrayID]);
328 
329  return arr;
330  }
331 
332  return null;
333  }
334 
335  //------------------------------------------------------------------------------------------------
339  IEntity GetGadgetByType(EGadgetType type)
340  {
341  array<SCR_GadgetComponent> gadgets = GetGadgetsByType(type);
342  if (!gadgets || gadgets.IsEmpty())
343  return null;
344 
345  foreach (SCR_GadgetComponent comp : gadgets)
346  {
347  if (comp)
348  return comp.GetOwner();
349  else
350  Print(GetOwner().ToString() + " SCR_GadgetManager::GetGadgetsByType returned null entry in an array of " + typename.EnumToString(EGadgetType, type) + " gadgets", LogLevel.ERROR); // this should not happen
351  }
352 
353  return null;
354  }
355 
356  //------------------------------------------------------------------------------------------------
360  IEntity GetQuickslotGadgetByType(EGadgetType type)
361  {
362  SCR_CharacterInventoryStorageComponent charStorage = SCR_CharacterInventoryStorageComponent.Cast( GetOwner().FindComponent(SCR_CharacterInventoryStorageComponent) );
363  array<IEntity> quickslotEntities = charStorage.GetQuickSlotItems();
364 
365  foreach (IEntity entity : quickslotEntities )
366  {
367  if (!entity) // empty slots will be null
368  continue;
369 
370  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast( entity.FindComponent(SCR_GadgetComponent) );
371  if (gadgetComp)
372  {
373  if (gadgetComp.GetType() == type)
374  return entity;
375  }
376  }
377 
378  return null;
379  }
380 
381  //------------------------------------------------------------------------------------------------
385  bool IsGadgetOwned(SCR_GadgetComponent gadgetComp)
386  {
387  int gadgetArrayID = m_aGadgetArrayMap.Get(gadgetComp.GetType());
388  if (gadgetArrayID != 1)
389  {
390  return m_aInventoryGadgetTypes[gadgetArrayID].Contains(gadgetComp);
391  }
392 
393  return false;
394  }
395 
396  //------------------------------------------------------------------------------------------------
397  // MANAGER METHODS
398  //------------------------------------------------------------------------------------------------
399 
400  //------------------------------------------------------------------------------------------------
405  protected bool CanChangeGadgetMode(IEntity gadget, SCR_GadgetComponent gadgetComp, EGadgetMode targetMode)
406  {
407  if ( targetMode == EGadgetMode.IN_HAND || gadgetComp.GetMode() == EGadgetMode.IN_HAND ) // If going TO or FROM mode1 -> anims need to happen first. Mode is synched from finish events instead of here
408  {
409  CompartmentAccessComponent compAccess = CompartmentAccessComponent.Cast(GetOwner().FindComponent(CompartmentAccessComponent)); // if in vehicle
410  if (compAccess && compAccess.IsInCompartment())
411  {
412  InventoryItemComponent invItemComponent = InventoryItemComponent.Cast(gadget.FindComponent(InventoryItemComponent));
413  if (!invItemComponent)
414  return false;
415 
416  CharacterModifierAttributes charModifData = CharacterModifierAttributes.Cast(invItemComponent.FindAttribute(CharacterModifierAttributes));
417  if (!charModifData)
418  return false;
419 
420  if (targetMode == EGadgetMode.IN_HAND && !charModifData.CanBeEquippedInVehicle())
421  return false;
422  }
423  }
424 
425  return true;
426  }
427 
428  //------------------------------------------------------------------------------------------------
431  protected void UpdateHeldGadget(IEntity gadget)
432  {
433  // no need ot update
434  if (gadget && gadget == m_HeldGadget)
435  return;
436 
437  m_bIsGadgetADS = false;
438 
439  // clear
440  if (!gadget)
441  {
442  if (m_HeldGadgetComponent && m_HeldGadgetComponent.m_bFocused)
443  OnGadgetFocusStateChanged(m_HeldGadget, false);
444 
445  m_HeldGadget = null;
446  m_LastHeldGadgetComponent = m_HeldGadgetComponent;
447  m_HeldGadgetComponent = null;
448 
449  CharacterInputContext inputCtx = m_Controller.GetInputContext();
450  IEntity hiddenGadget = inputCtx.GetWantedLefHandGadgetEntity();
451  if (hiddenGadget)
452  {
453  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast( hiddenGadget.FindComponent(SCR_GadgetComponent) );
454  if (!gadgetComp)
455  return;
456 
457  m_HiddenGadgetComponent = gadgetComp;
458 
459  ConnectToGadgetsManagerSystem();
460  }
461  else
462  {
463  m_HiddenGadgetComponent = null;
464  }
465  }
466  else
467  {
468  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast( gadget.FindComponent(SCR_GadgetComponent) );
469  if (!gadgetComp)
470  return;
471 
472  m_HeldGadget = gadget;
473  m_HeldGadgetComponent = gadgetComp;
474  m_HiddenGadgetComponent = null;
475  ConnectToGadgetsManagerSystem();
476  }
477  }
478 
479  //------------------------------------------------------------------------------------------------
483  void HandleInput(IEntity gadget, float inputVal)
484  {
485  EGadgetMode targetMode = EGadgetMode.IN_HAND;
486  bool doFocus = inputVal != 1; // input modifier from config
487 
488  if (m_HeldGadget == gadget) // already holding this gadget
489  targetMode = EGadgetMode.IN_STORAGE;
490 
491  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast( gadget.FindComponent(SCR_GadgetComponent) );
492  if (!gadgetComp)
493  return;
494 
495  if (inputVal != 1 && gadgetComp.CanBeToggled())
496  gadgetComp.ToggleActive(!gadgetComp.IsToggledOn());
497  else
498  SetGadgetMode(gadget, targetMode, doFocus);
499  }
500 
501  //------------------------------------------------------------------------------------------------
503  protected void ClearToggleState()
504  {
505  m_bIsGadgetADS = false;
506  if (m_HeldGadgetComponent)
507  {
508  m_HeldGadgetComponent.ToggleFocused(false);
509  m_Controller.SetGadgetRaisedModeWanted(false);
510  }
511  }
512 
513  //------------------------------------------------------------------------------------------------
514  // EVENTS
515  //------------------------------------------------------------------------------------------------
516 
517  //------------------------------------------------------------------------------------------------
521  void OnItemAdded(IEntity item, BaseInventoryStorageComponent storageOwner)
522  {
523  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast(item.FindComponent(SCR_GadgetComponent));
524  if (!gadgetComp)
525  return;
526 
527  EGadgetType type = gadgetComp.GetType();
528 
529  int gadgetArrayID = m_aGadgetArrayMap.Get(type);
530  if (gadgetArrayID == -1)
531  return;
532 
533  m_aInventoryGadgetTypes[gadgetArrayID].Insert(gadgetComp);
534 
535  // Check whether the gadget is in equipment slot (OnAddedToSlot will happen before this)
536  EquipmentStorageComponent equipmentComp = EquipmentStorageComponent.Cast(storageOwner);
537  if (equipmentComp)
538  {
539  InventoryStorageSlot storageSlot = equipmentComp.FindItemSlot(item);
540  if (storageSlot)
541  SetGadgetMode(item, EGadgetMode.IN_SLOT);
542  }
543  else if (type == EGadgetType.RADIO_BACKPACK) // special case for backpack radios, always in (character) slot
544  SetGadgetMode(item, EGadgetMode.IN_SLOT);
545  else
546  SetGadgetMode(item, EGadgetMode.IN_STORAGE);
547 
548  m_OnGadgetAdded.Invoke(gadgetComp);
549 
550  if (m_VONController && (type & m_iRadiosFlags)) // add entries to VONController
551  {
552  BaseRadioComponent radioComp = BaseRadioComponent.Cast(gadgetComp.GetOwner().FindComponent(BaseRadioComponent));
553  if (!radioComp)
554  return;
555 
556  // Put all transceivers (AKA) channels in the VoN menu
557  int count = radioComp.TransceiversCount();
558  for (int i = 0; i < count; i++)
559  {
560  SCR_VONEntryRadio radioEntry = new SCR_VONEntryRadio();
561  radioEntry.SetRadioEntry(radioComp.GetTransceiver(i), i + 1, gadgetComp);
562  m_VONController.AddEntry(radioEntry);
563  }
564  }
565  }
566 
567  //------------------------------------------------------------------------------------------------
571  void OnItemRemoved(IEntity item, BaseInventoryStorageComponent storageOwner)
572  {
573  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast(item.FindComponent(SCR_GadgetComponent));
574  if (!gadgetComp)
575  return;
576 
577  InventoryItemComponent invComp = InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent));
578  if (!invComp)
579  return;
580 
581  EGadgetType type = gadgetComp.GetType();
582 
583  int gadgetArrayID = m_aGadgetArrayMap.Get(gadgetComp.GetType());
584  if (gadgetArrayID == -1)
585  return;
586 
587  int gadgetPos = m_aInventoryGadgetTypes[gadgetArrayID].Find(gadgetComp);
588  if (gadgetPos != -1)
589  m_aInventoryGadgetTypes[gadgetArrayID].Remove(gadgetPos);
590 
591  m_OnGadgetRemoved.Invoke(gadgetComp);
592 
593  if (m_VONController && (type == EGadgetType.RADIO || type == EGadgetType.RADIO_BACKPACK)) // remove entries from VONController
594  {
595  array<ref SCR_VONEntry> entries = {};
596  m_VONController.GetVONEntries(entries);
597 
598  for (int i = entries.Count() - 1; i >= 0; --i)
599  {
600  SCR_VONEntryRadio entry = SCR_VONEntryRadio.Cast(entries[i]);
601  if (entry && entry.GetGadget() == gadgetComp)
602  m_VONController.RemoveEntry(entries[i]); // multiple entries per gadget possible
603  }
604  }
605  }
606 
607  //------------------------------------------------------------------------------------------------
612  void OnPlayerDeath(SCR_CharacterControllerComponent charController, IEntity instigatorEntity, notnull Instigator instigator)
613  {
614  if (!charController || charController != m_Controller)
615  return;
616 
617  ClearToggleState();
618  m_pInvokersState.Clear(GetOwner());
619  UnregisterVONEntries();
620  UnregisterInputs();
621  DisconnectFromGadgetsManagerSystem();
622  }
623 
624  //------------------------------------------------------------------------------------------------
628  void OnControlledByPlayer(IEntity owner, bool controlled)
629  {
630  if (System.IsConsoleApp()) // hotfix for this being called on DS when other players control their characters
631  return;
632 
633  if (controlled && owner != SCR_PlayerController.GetLocalControlledEntity()) // same as hotfix above but for hosted server, if we get controlled=true for entity which isnt ours, discard
634  controlled = false;
635 
636  if (!controlled)
637  {
638  m_pInvokersState.CleanupLocalInvokers(GetOwner());
639  UnregisterInputs();
640  UnregisterVONEntries();
641  DisconnectFromGadgetsManagerSystem();
642  }
643  else if (owner)
644  {
645  m_pInvokersState.InitControlledInvokers(owner, m_Controller);
646  RegisterInputs();
647  RegisterVONEntries();
648  ConnectToGadgetsManagerSystem();
649  }
650  }
651 
652  //------------------------------------------------------------------------------------------------
657  void OnGadgetStateChanged(IEntity gadget, bool isInHand, bool isOnGround)
658  {
659  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast(gadget.FindComponent(SCR_GadgetComponent));
660  if (!gadgetComp)
661  return;
662 
663  if (isInHand)
664  {
665  UpdateHeldGadget(gadget);
666  gadgetComp.OnModeChanged(EGadgetMode.IN_HAND, GetOwner());
667  }
668  else
669  {
670  UpdateHeldGadget(null);
671 
672  if (isOnGround) // this means it has been moved directly to ground from hand
673  {
674  gadgetComp.OnModeChanged(EGadgetMode.ON_GROUND, GetOwner());
675  return;
676  }
677 
678  // Check whether this gadget is slotted in a parent's equipment storage in order to set correct mode
679  IEntity parent = gadget.GetParent();
680  if (parent)
681  {
682  InventoryItemComponent item = InventoryItemComponent.Cast(gadget.FindComponent(InventoryItemComponent));
683  if (item)
684  {
685  EquipmentStorageSlot storageSlot = EquipmentStorageSlot.Cast(item.GetParentSlot());
686  if (storageSlot && storageSlot.GetOwner() == parent)
687  {
688  gadgetComp.OnModeChanged(EGadgetMode.IN_SLOT, GetOwner());
689  return;
690  }
691  }
692  }
693 
694  gadgetComp.OnModeChanged(EGadgetMode.IN_STORAGE, GetOwner());
695  }
696  }
697 
698  //------------------------------------------------------------------------------------------------
702  void OnGadgetFocusStateChanged(IEntity gadget, bool isFocused)
703  {
704  SCR_GadgetComponent gadgetComponent;
705  if (gadget)
706  {
707  gadgetComponent = m_HeldGadgetComponent;
708  }
709  else
710  {
711  // when gadget is switched, this gets called after gadget state change with null TODO preferably this shouldnt happen :(
712  gadgetComponent = m_LastHeldGadgetComponent;
713  isFocused = false;
714  }
715 
716  m_bIsGadgetADS = isFocused;
717 
718  // TODO hotfix against incorrect toggle set when spamming input, will be solved when map has unfocused & focused mode
719  if (!gadgetComponent
720  || ( !isFocused && gadgetComponent.GetType() == EGadgetType.MAP && gadgetComponent.GetMode() == EGadgetMode.IN_HAND ) )
721  return;
722 
723  gadgetComponent.ToggleFocused(isFocused);
724  }
725 
726  //------------------------------------------------------------------------------------------------
728  void OnEditorOpened()
729  {
730  ClearToggleState();
731  }
732 
733  //------------------------------------------------------------------------------------------------
734  // INPUTS & INIT
735  //------------------------------------------------------------------------------------------------
736 
737  //------------------------------------------------------------------------------------------------
741  protected void OnGadgetInput(float value, EActionTrigger reason)
742  {
743  EGadgetType input = GetGadgetInputAction();
744  if (input == 0)
745  return;
746 
747  // Search quickslots first, then inventory
748  IEntity gadget = GetQuickslotGadgetByType(input);
749  if (!gadget)
750  gadget = GetGadgetByType(input);
751 
752  if (!gadget)
753  return;
754 
755  HandleInput(gadget, value);
756  }
757 
758  //------------------------------------------------------------------------------------------------
762  protected void ActionFlashlightToggle(float value, EActionTrigger reason)
763  {
764  // Search quickslots first, then inventory
765  IEntity flashlight = GetQuickslotGadgetByType(EGadgetType.FLASHLIGHT);
766  if (!flashlight)
767  flashlight = GetGadgetByType(EGadgetType.FLASHLIGHT);
768 
769  if (!flashlight)
770  return;
771 
772  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast(flashlight.FindComponent(SCR_GadgetComponent));
773  if (gadgetComp)
774  gadgetComp.ActivateAction();
775  }
776 
777  //------------------------------------------------------------------------------------------------
779  protected void OnPauseMenu()
780  {
781  if (SCR_MapGadgetComponent.Cast(m_HeldGadgetComponent))
782  SetGadgetMode( m_HeldGadget, EGadgetMode.IN_STORAGE ); // TODO update state transition
783  }
784 
785  //------------------------------------------------------------------------------------------------
787  protected void OnGadgetADS()
788  {
789  SetGadgetADS(!m_bIsGadgetADS);
790  }
791 
792  //------------------------------------------------------------------------------------------------
796  protected void OnGadgetADSHold(float value, EActionTrigger reason)
797  {
798  SetGadgetADS(reason == EActionTrigger.DOWN);
799  }
800 
801  //------------------------------------------------------------------------------------------------
804  void SetGadgetADS(bool gadgetADS)
805  {
806  if (!m_Controller)
807  return;
808 
809  if (m_HeldGadgetComponent && m_HeldGadgetComponent.CanBeRaised())
810  {
811  m_Controller.SetGadgetRaisedModeWanted(gadgetADS);
812  }
813  else if (m_HiddenGadgetComponent && m_HiddenGadgetComponent.CanBeRaised())
814  {
815  if (gadgetADS)
816  m_Controller.RecoverHiddenGadget(false, false);
817 
818  m_Controller.SetGadgetRaisedModeWanted(gadgetADS);
819  }
820  }
821 
822  //------------------------------------------------------------------------------------------------
825  protected void RegisterInitialGadgets(IEntity character)
826  {
827  array<IEntity> foundItems = {};
828  array<typename> componentsQuery = {SCR_GadgetComponent};
829 
830  m_InventoryStorageMgr = SCR_InventoryStorageManagerComponent.Cast( character.FindComponent(SCR_InventoryStorageManagerComponent) );
831  if (m_InventoryStorageMgr)
832  m_InventoryStorageMgr.FindItemsWithComponents(foundItems, componentsQuery, EStoragePurpose.PURPOSE_ANY);
833 
834  int count = foundItems.Count();
835  for (int i = 0; i < count; i++)
836  {
837  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast( foundItems[i].FindComponent(SCR_GadgetComponent) );
838  int gadgetArrayID = m_aGadgetArrayMap.Get(gadgetComp.GetType());
839  if (gadgetArrayID == -1)
840  continue;
841 
842  m_aInventoryGadgetTypes[gadgetArrayID].Insert(gadgetComp);
843 
844  if (gadgetComp.GetMode() != EGadgetMode.ON_GROUND) // initial gadget for client can/will already have set mode members by replication, set the entire mode process properly here
845  {
846  SetGadgetMode(foundItems[i], gadgetComp.GetMode());
847  continue;
848  }
849 
850  // initial gadgets for host will likely be added to storage before manager starts catching OnAdded events and will default to ground
851  InventoryItemComponent invItemComp = InventoryItemComponent.Cast( foundItems[i].FindComponent(InventoryItemComponent) );
852  if (invItemComp)
853  {
854  EquipmentStorageSlot storageSlot = EquipmentStorageSlot.Cast(invItemComp.GetParentSlot()); // Check whether the gadget is in equipment slot (OnAddedToSlot will happen before this)
855  if (storageSlot || gadgetComp.GetType() == EGadgetType.RADIO_BACKPACK) // backpack slot is not EquipmentStorageSlot but we consider it as such
856  {
857  SetGadgetMode(foundItems[i], EGadgetMode.IN_SLOT);
858  continue;
859  }
860  }
861 
862  SetGadgetMode(foundItems[i], EGadgetMode.IN_STORAGE);
863  }
864 
865  s_OnGadgetInitDone.Invoke(character, this);
866  }
867 
868  //------------------------------------------------------------------------------------------------
870  protected void RegisterVONEntries()
871  {
872  if (!GetGame().GetPlayerController())
873  return;
874 
875  m_VONController = SCR_VONController.Cast(GetGame().GetPlayerController().FindComponent(SCR_VONController));
876  if (!m_VONController)
877  return;
878 
879  array<SCR_GadgetComponent> radiosArray = {};
880  radiosArray.Copy(GetGadgetsByType(EGadgetType.RADIO)); // squad radios
881  radiosArray.InsertAll(GetGadgetsByType(EGadgetType.RADIO_BACKPACK)); // backpack radio
882 
883  foreach (SCR_GadgetComponent radio : radiosArray)
884  {
885  BaseRadioComponent radioComp = BaseRadioComponent.Cast(radio.GetOwner().FindComponent(BaseRadioComponent));
886  int count = radioComp.TransceiversCount();
887  for (int i = 0 ; i < count; ++i) // Get all individual transceivers (AKA channels) from the radio
888  {
889  SCR_VONEntryRadio radioEntry = new SCR_VONEntryRadio();
890  radioEntry.SetRadioEntry(radioComp.GetTransceiver(i), i + 1, radio);
891 
892  m_VONController.AddEntry(radioEntry);
893  }
894  }
895  }
896 
897  //------------------------------------------------------------------------------------------------
898  protected void UnregisterVONEntries()
899  {
900  if (!m_VONController)
901  return;
902 
903  array<SCR_GadgetComponent> radiosArray = {};
904  radiosArray.Copy(GetGadgetsByType(EGadgetType.RADIO)); // squad radios
905  radiosArray.InsertAll(GetGadgetsByType(EGadgetType.RADIO_BACKPACK)); // backpack radio
906 
907  array<ref SCR_VONEntry> entries = {};
908  m_VONController.GetVONEntries(entries);
909 
910  foreach (SCR_GadgetComponent radio : radiosArray)
911  {
912  for (int i = entries.Count() - 1; i >= 0; --i)
913  {
914  SCR_VONEntryRadio entry = SCR_VONEntryRadio.Cast(entries[i]);
915  if (entry && entry.GetGadget() == radio)
916  m_VONController.RemoveEntry(entries[i]); // multiple entries per gadget possible
917  }
918  }
919  }
920 
921  //------------------------------------------------------------------------------------------------
923  protected void RegisterInputs()
924  {
925  m_InputManager = GetGame().GetInputManager();
926  if (!m_InputManager)
927  return;
928 
929  // Gadgets
930  m_InputManager.AddActionListener("GadgetMap", EActionTrigger.DOWN, OnGadgetInput);
931  m_InputManager.AddActionListener("MapEscape", EActionTrigger.DOWN, OnPauseMenu);
932  m_InputManager.AddActionListener("GadgetCompass", EActionTrigger.DOWN, OnGadgetInput);
933  m_InputManager.AddActionListener("GadgetBinoculars", EActionTrigger.DOWN, OnGadgetInput);
934  m_InputManager.AddActionListener("GadgetFlashlight", EActionTrigger.DOWN, OnGadgetInput);
935  m_InputManager.AddActionListener("GadgetFlashlightToggle", EActionTrigger.DOWN, ActionFlashlightToggle);
936  m_InputManager.AddActionListener("GadgetWatch", EActionTrigger.DOWN, OnGadgetInput);
937  m_InputManager.AddActionListener("GadgetADS", EActionTrigger.DOWN, OnGadgetADS);
938  m_InputManager.AddActionListener("GadgetADSHold", EActionTrigger.DOWN, OnGadgetADSHold);
939  m_InputManager.AddActionListener("GadgetADSHold", EActionTrigger.UP, OnGadgetADSHold);
940  m_InputManager.AddActionListener("GadgetCancel", EActionTrigger.DOWN, RemoveHeldGadget);
941  m_InputManager.AddActionListener("GadgetActivate", EActionTrigger.DOWN, OnActivateHeldGadget);
942  }
943 
944  //------------------------------------------------------------------------------------------------
946  protected void UnregisterInputs()
947  {
948  m_InputManager = GetGame().GetInputManager();
949  if (!m_InputManager)
950  return;
951 
952  m_InputManager.RemoveActionListener("GadgetMap", EActionTrigger.DOWN, OnGadgetInput);
953  m_InputManager.RemoveActionListener("MapEscape", EActionTrigger.DOWN, OnPauseMenu);
954  m_InputManager.RemoveActionListener("GadgetCompass", EActionTrigger.DOWN, OnGadgetInput);
955  m_InputManager.RemoveActionListener("GadgetBinoculars", EActionTrigger.DOWN, OnGadgetInput);
956  m_InputManager.RemoveActionListener("GadgetFlashlight", EActionTrigger.DOWN, OnGadgetInput);
957  m_InputManager.RemoveActionListener("GadgetFlashlightToggle", EActionTrigger.DOWN, ActionFlashlightToggle);
958  m_InputManager.RemoveActionListener("GadgetWatch", EActionTrigger.DOWN, OnGadgetInput);
959  m_InputManager.RemoveActionListener("GadgetADS", EActionTrigger.DOWN, OnGadgetADS);
960  m_InputManager.RemoveActionListener("GadgetADSHold", EActionTrigger.DOWN, OnGadgetADSHold);
961  m_InputManager.RemoveActionListener("GadgetADSHold", EActionTrigger.UP, OnGadgetADSHold);
962  m_InputManager.RemoveActionListener("GadgetCancel", EActionTrigger.DOWN, RemoveHeldGadget);
963  m_InputManager.RemoveActionListener("GadgetActivate", EActionTrigger.DOWN, OnActivateHeldGadget);
964  }
965 
966  //------------------------------------------------------------------------------------------------
969  protected EGadgetType GetGadgetInputAction()
970  {
971  if ( m_InputManager.GetActionTriggered("GadgetMap") )
972  return EGadgetType.MAP;
973 
974  if ( m_InputManager.GetActionTriggered("GadgetCompass") )
975  return EGadgetType.COMPASS;
976 
977  if ( m_InputManager.GetActionTriggered("GadgetBinoculars") )
978  return EGadgetType.BINOCULARS;
979 
980  if ( m_InputManager.GetActionTriggered("GadgetFlashlight") )
981  return EGadgetType.FLASHLIGHT;
982 
983  if ( m_InputManager.GetActionTriggered("GadgetWatch") )
984  return EGadgetType.WRISTWATCH;
985 
986  return 0;
987  }
988 
989  //------------------------------------------------------------------------------------------------
992  protected void InitComponent(IEntity owner)
993  {
995  if (!controller)
996  return;
997 
998  m_Controller = controller;
999 
1000  m_pInvokersState.InitInvokers(owner, m_Controller); // default (all entities with gadget manager) invokers
1001 
1002  if (SCR_PlayerController.GetLocalControlledEntity() == owner)
1003  m_pInvokersState.InitControlledInvokers(owner, m_Controller); // local (controlled entity) invokers, ignore owned non controlled characters
1004 
1005  // Owner specific behavior
1006  if (m_pInvokersState.IsInit())
1007  {
1008  RegisterInitialGadgets(owner);
1009 
1010  if (m_pInvokersState.m_bIsControlledEnt)
1011  {
1012  RegisterInputs();
1013  RegisterVONEntries();
1014  }
1015  else
1016  DisconnectFromGadgetsManagerSystem(); // if not controlled entity, clear frame
1017  }
1018  }
1019 
1020  //------------------------------------------------------------------------------------------------
1021  // RPC
1022  //------------------------------------------------------------------------------------------------
1023 
1024  //------------------------------------------------------------------------------------------------
1028  void AskToggleGadget(SCR_GadgetComponent gadgetComp, bool state)
1029  {
1030  RplId id = Replication.FindId(gadgetComp);
1031 
1032  if ( id && id.IsValid() )
1033  Rpc(RPC_AskToggleGadget, id, state);
1034  }
1035 
1036  //------------------------------------------------------------------------------------------------
1040  [RplRpc(RplChannel.Reliable, RplRcver.Server)]
1041  protected void RPC_AskToggleGadget(RplId id, bool state)
1042  {
1043  // TODO sanity check
1044 
1045  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast(Replication.FindItem(id));
1046  if (!gadgetComp)
1047  return;
1048 
1049  gadgetComp.OnToggleActive(state);
1050  Rpc(RPC_DoToggleGadget, id, state);
1051  }
1052 
1053  //------------------------------------------------------------------------------------------------
1057  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast, RplCondition.NoOwner)]
1058  protected void RPC_DoToggleGadget(RplId id, bool state)
1059  {
1060  // TODO sanity check
1061 
1062  SCR_GadgetComponent gadgetComp = SCR_GadgetComponent.Cast(Replication.FindItem(id));
1063  if (!gadgetComp)
1064  return;
1065 
1066  gadgetComp.OnToggleActive(state);
1067  }
1068 
1069  //------------------------------------------------------------------------------------------------
1070  protected void ConnectToGadgetsManagerSystem()
1071  {
1072  World world = GetOwner().GetWorld();
1073  GadgetManagersSystem gadgetManagersSystem = GadgetManagersSystem.Cast(world.FindSystem(GadgetManagersSystem));
1074  if (!gadgetManagersSystem)
1075  return;
1076 
1077  gadgetManagersSystem.Register(this);
1078  }
1079 
1080  //------------------------------------------------------------------------------------------------
1081  protected void DisconnectFromGadgetsManagerSystem()
1082  {
1083  World world = GetOwner().GetWorld();
1084  GadgetManagersSystem gadgetManagersSystem = GadgetManagersSystem.Cast(world.FindSystem(GadgetManagersSystem));
1085  if (!gadgetManagersSystem)
1086  return;
1087 
1088  gadgetManagersSystem.Unregister(this);
1089  }
1090 
1091  //------------------------------------------------------------------------------------------------
1092  override void OnDelete(IEntity owner)
1093  {
1094  DisconnectFromGadgetsManagerSystem();
1095 
1096  super.OnDelete(owner);
1097  }
1098 
1099  #ifndef DISABLE_GADGETS
1100  //------------------------------------------------------------------------------------------------
1103  void Update(float timeSlice)
1104  {
1105  if (!m_pInvokersState.IsInit())
1106  InitComponent(GetOwner());
1107 
1108  // context
1109  if (!m_InputManager || !(m_HeldGadgetComponent || m_HiddenGadgetComponent))
1110  {
1111  DisconnectFromGadgetsManagerSystem();
1112  return;
1113  }
1114 
1115  SCR_GadgetComponent gadgetComp;
1116  if (m_HeldGadgetComponent)
1117  gadgetComp = m_HeldGadgetComponent;
1118  else
1119  gadgetComp = m_HiddenGadgetComponent;
1120 
1121  m_InputManager.ActivateContext("GadgetContext");
1122 
1123  if (gadgetComp.CanBeToggled())
1124  m_InputManager.ActivateContext("GadgetContextToggleable");
1125 
1126  if (gadgetComp.IsUsingADSControls())
1127  {
1128  // Cancel gadget ADS while actively driving vehicle
1129  SCR_ChimeraCharacter character = SCR_ChimeraCharacter.Cast(GetOwner());
1130  if (character && character.IsDriving(1))
1131  {
1132  if (m_bIsGadgetADS)
1133  SetGadgetADS(false);
1134  }
1135  else
1136  {
1137  m_InputManager.ActivateContext("GadgetContextRaisable");
1138  }
1139  }
1140 
1141  if (gadgetComp.GetType() == EGadgetType.MAP)
1142  m_InputManager.ActivateContext("GadgetMapContext");
1143  }
1144 
1145  //------------------------------------------------------------------------------------------------
1146  override void OnPostInit(IEntity owner)
1147  {
1148  if ( g_Game.InPlayMode() )
1149  ConnectToGadgetsManagerSystem();
1150 
1151  // init arrays
1152  typename gadgetTypes = EGadgetType;
1153  int count = gadgetTypes.GetVariableCount();
1154  array <SCR_GadgetComponent> gadgets;
1155  for ( int i = 0; i < count; i++ )
1156  {
1157  gadgets = {};
1158  m_aInventoryGadgetTypes.Insert(gadgets);
1159  m_aGadgetArrayMap.Insert( Math.Pow(2, i), i); // EGadgetType flag + array ID
1160  }
1161  }
1162  #endif
1163 }
SCR_PlayerController
Definition: SCR_PlayerController.c:31
m_InputManager
protected InputManager m_InputManager
Definition: SCR_BaseManualCameraComponent.c:15
CharacterInputContext
Definition: CharacterInputContext.c:12
m_Controller
protected CompartmentControllerComponent m_Controller
Definition: SCR_VehicleDamageManagerComponent.c:197
m_bIsControlledInit
bool m_bIsControlledInit
Definition: SCR_GadgetManagerComponent.c:5
InventoryStorageSlot
Definition: InventoryStorageSlot.c:12
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
ScriptGameComponentClass
Definition: ScriptGameComponent.c:12
SCR_GadgetManagerComponent
Definition: SCR_GadgetManagerComponent.c:138
EquipmentStorageSlot
Definition: EquipmentStorageSlot.c:7
SCR_VONEntryRadio
VONEntry class for radio entries.
Definition: SCR_VONEntryRadio.c:3
RplRpc
SCR_AchievementsHandlerClass ScriptComponentClass RplRpc(RplChannel.Reliable, RplRcver.Owner)] void UnlockOnClient(AchievementId achievement)
Definition: SCR_AchievementsHandler.c:11
GenericEntity
SCR_GenericBoxEntityClass GenericEntity
func
func
Definition: SCR_AIThreatSystem.c:5
m_VONController
protected SCR_VONController m_VONController
Definition: SCR_VonDisplay.c:101
SCR_CharacterControllerComponent
Definition: SCR_CharacterControllerComponent.c:35
GetPlayerController
proto external PlayerController GetPlayerController()
Definition: SCR_PlayerDeployMenuHandlerComponent.c:307
Instigator
Definition: Instigator.c:6
CharacterModifierAttributes
Definition: CharacterModifierAttributes.c:12
m_GadgetManager
SCR_GadgetManagerComponent m_GadgetManager
Definition: SCR_GadgetManagerComponent.c:2
m_bIsControlledEnt
bool m_bIsControlledEnt
Definition: SCR_GadgetManagerComponent.c:7
GetOwner
IEntity GetOwner()
Owner entity of the fuel tank.
Definition: SCR_FuelNode.c:128
GadgetManagersSystem
Definition: GadgetManagersSystem.c:1
SCR_GadgetInvokersInitState
Controls invoker resgistration for gadget manager.
Definition: SCR_GadgetManagerComponent.c:2
InventoryItemComponent
Definition: InventoryItemComponent.c:12
EntityEditorProps
class SCR_GadgetInvokersInitState EntityEditorProps(category:"GameScripted/Gadgets", description:"Gadget manager", color:"0 0 255 255")
Definition: SCR_GadgetManagerComponent.c:125
m_bIsDefaultInit
bool m_bIsDefaultInit
Definition: SCR_GadgetManagerComponent.c:6
EStoragePurpose
EStoragePurpose
Definition: EStoragePurpose.c:12
type
EDamageType type
Definition: SCR_DestructibleTreeV2.c:32
IsValid
override bool IsValid(IEntity actionOwner, IEntity actionUser, SCR_BaseUseSupportStationAction action, vector actionPosition, out ESupportStationReasonInvalid reasonInvalid, out int supplyCost)
Definition: SCR_BaseDamageHealSupportStationComponent.c:98
SCR_GadgetInvokersInitState
void SCR_GadgetInvokersInitState(notnull SCR_GadgetManagerComponent gadgetManager)
Definition: SCR_GadgetManagerComponent.c:117
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180
SCR_EditorManagerEntity
Definition: SCR_EditorManagerEntity.c:26