Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
WeaponSelectionMenu.c
Go to the documentation of this file.
1//#define DISABLE_WEAPON_SWITCHING
2
3// Todo: PerFrame Optimization and Refactor
4class SCR_WeaponSelectionMenu : SCR_InfoDisplay
5{
6 private BaseWeaponManagerComponent m_WeaponManager;
7 private SCR_InventoryStorageManagerComponent m_inventory20ManagerComp
8 private GenericEntity m_Owner;
9 private BaseControllerComponent m_Controller;
10 private InputManager m_InputManager;
11 private BaseInteractionHandlerComponent m_InteractionMenu;
12 private Widget m_wVerticalLayout;
13 private Widget m_wHighlightedWeapon;
14
15 private float m_fLastInteractionTime = 0;
16 private float m_fLastSelectionTime = 0;
17
18 private ref array<WeaponSlotComponent> m_aWeaponSlotsUnsorted = new array<WeaponSlotComponent>;
19 private ref array<WeaponSlotComponent> m_aWeaponSlotsSorted = new array<WeaponSlotComponent>;
20 private ref array<IEntity> m_aWeaponEntities = new array<IEntity>;
21 private ref array<Widget> m_aWeaponWidgets = new array<Widget>;
22
24
25 [Attribute("{80102F7397A6DFDC}UI/layouts/HUD/WeaponSelection/WeaponSelectionCategoryNumber.layout", UIWidgets.ResourceNamePicker, "Layout of category number widget","layout")]
27
28 [Attribute("{F6725A5E6A624F5F}UI/layouts/HUD/WeaponSelection/WeaponSlot.layout", UIWidgets.ResourceNamePicker, "Scoreboard layout","layout")]
30
31 [Attribute("100", UIWidgets.EditBox, "Speed of scrolling between weapons (delay in ms)")]
32 private float m_fSelectionTimeout;
33
34 [Attribute("5000", UIWidgets.EditBox, "Weapon selection auto closing time (in ms)")]
35 private float m_fInteractionTimeout;
36
37 [Attribute("1 1 1 0.10", UIWidgets.ColorPicker, "")]
38 protected ref Color m_ColorSelected;
39
40 [Attribute("0 0 0 1", UIWidgets.ColorPicker, "")]
42
43 [Attribute("0 0 0 0.1", UIWidgets.ColorPicker, "")]
44 protected ref Color m_ColorDefault;
45
46 [Attribute("1 1 1 1", UIWidgets.ColorPicker, "")]
48
49 [Attribute("5", UIWidgets.EditBox, "")]
51
52 [Attribute(SCR_SoundEvent.FOCUS, UIWidgets.EditBox, "")]
54
55 [Attribute("{0054C496786770A6}UI/Textures/Icons/icons_keyboard_32.imageset", UIWidgets.ResourceNamePicker, "")]
57
58 //------------------------------------------------------------------------------------------------
59 void Init(IEntity owner)
60 {
61 m_Owner = GenericEntity.Cast(owner);
62 if (!m_Owner || !m_wRoot)
63 return;
64
65 // Get action menu
66 // Todo: Cache workspace
67 ArmaReforgerScripted game = GetGame();
68 if (game)
69 {
70 PlayerController pc = game.GetPlayerController();
71 if (pc)
72 {
73 m_InteractionMenu = BaseInteractionHandlerComponent.Cast(pc.FindComponent(BaseInteractionHandlerComponent));
74 }
75
76 HUDManagerComponent hudManager = game.GetHUDManager();
77 if (hudManager)
78 {
79 array<SCR_InfoDisplay> displays = hudManager.GetHUDElements();
80 foreach (SCR_InfoDisplay display : displays)
81 {
82 SCR_WeaponSelectionMenu weaponSwitching = SCR_WeaponSelectionMenu.Cast(display);
83 if (weaponSwitching && weaponSwitching != this)
84 {
85 weaponSwitching.Show(false, UIConstants.FADE_RATE_DEFAULT);
86 break;
87 }
88 }
89 }
90 }
91
92 m_InputManager = GetGame().GetInputManager();
93
94 if (Vehicle.Cast(m_Owner))
95 {
96 BaseVehicleNodeComponent nodeComponent = BaseVehicleNodeComponent.Cast(m_Owner.FindComponent(BaseVehicleNodeComponent));
97 if (!nodeComponent)
98 return;
99 m_Controller = BaseControllerComponent.Cast(nodeComponent.FindComponent(BaseControllerComponent));
100 m_WeaponManager = BaseWeaponManagerComponent.Cast(nodeComponent.FindComponent(BaseWeaponManagerComponent));
101
102 }
103 else
104 {
105 m_Controller = BaseControllerComponent.Cast(m_Owner.FindComponent(BaseControllerComponent));
106 m_WeaponManager = BaseWeaponManagerComponent.Cast(m_Owner.FindComponent(BaseWeaponManagerComponent));
107 }
108
109 if (!m_WeaponManager)
110 return;
111
112 array<WeaponSlotComponent> weapons = new array<WeaponSlotComponent>;
113 m_WeaponManager.GetWeaponsSlots(weapons);
114
115 m_aWeaponSlotsUnsorted.Clear();
116 foreach (WeaponSlotComponent slot : weapons)
117 {
118 m_aWeaponSlotsUnsorted.Insert(slot);
119 }
120
121 m_aWeaponSlotsSorted = GetSortedWeaponSlots(m_aWeaponSlotsUnsorted);
122
123 /*
124 foreach (WeaponSlotComponent weapon: m_aWeaponSlotsSorted)
125 {
126 if (weapon && weapon.GetWeaponEntity())
127 {
128 m_Controller.SelectWeapon(weapon);
129 break;
130 }
131 }
132 */
133
134 // Hide menu and scan all widgets in slots
135 m_wRoot.SetOpacity(0);
136 m_wVerticalLayout = m_wRoot.FindAnyWidget("WeaponMenu");
137
138 Widget child = m_wRoot.GetChildren();
139 if (child)
140 {
141 while(child)
142 {
143 Widget newChild = null;
144 if (child)
145 {
146 newChild = child.GetSibling();
147 child = newChild;
148 }
149 }
150 }
151
152 // Init widgets
154 }
155
156 //------------------------------------------------------------------------------------------------
158 {
159 if (!m_inventory20ManagerComp)
160 m_inventory20ManagerComp = SCR_InventoryStorageManagerComponent.Cast(m_Owner.FindComponent(SCR_InventoryStorageManagerComponent));
161 if (!m_inventory20ManagerComp)
162 return;
163
164 CharacterControllerComponent controller = CharacterControllerComponent.Cast(m_Owner.FindComponent(CharacterControllerComponent));
165 if (!controller)
166 return;
167
168 auto bandage = m_inventory20ManagerComp.GetBandageItem();
169 if (bandage)
170 controller.TakeGadgetInLeftHand(bandage, 1);
171 }
172
173 //------------------------------------------------------------------------------------------------
175 {
176 m_aWeaponEntities.Clear();
177 foreach (WeaponSlotComponent weapon: m_aWeaponSlotsUnsorted)
178 {
179 IEntity entity = weapon.GetWeaponEntity();
180 m_aWeaponEntities.Insert(entity);
181 }
182 }
183
184 //------------------------------------------------------------------------------------------------
186 {
187 if (m_aWeaponSlotsUnsorted.Count() != m_aWeaponEntities.Count())
188 return true;
189
190 foreach (int i, WeaponSlotComponent slot : m_aWeaponSlotsUnsorted)
191 {
192 if (slot && slot.GetWeaponEntity() != m_aWeaponEntities.Get(i))
193 return true;
194 }
195
196 return false;
197 }
198
199 //------------------------------------------------------------------------------------------------
201 {
202 if (!m_Controller)
203 return false;
204
205 int i = m_aWeaponWidgets.Find(m_wHighlightedWeapon);
206 if (i < 0 && i < m_aWeaponSlotsSorted.Count())
207 return false;
208
209 WeaponSlotComponent slot = m_aWeaponSlotsSorted.Get(i);
210 if (!slot)
211 return false;
212
213 if (slot != m_WeaponManager.GetCurrent())
214 {
215 OnSelectWeapon(slot);
216 return true;
217 }
218 return false;
219 }
220
221 //------------------------------------------------------------------------------------------------
223 {
224 if (!m_wVerticalLayout)
225 return;
226
227 // Delete all categories
228 Widget child = m_wVerticalLayout.GetChildren();
229 while (child)
230 {
231 Widget nextChild = child.GetSibling();
232 child.RemoveFromHierarchy();
233 child = nextChild;
234 }
235
236 m_aWeaponWidgets.Clear();
237
238 foreach (WeaponSlotComponent slot: m_aWeaponSlotsSorted)
239 {
240 if (!slot || !slot.GetWeaponEntity())
241 {
242 m_aWeaponWidgets.Insert(null);
243 continue;
244 }
245
246 // Create category
247 Widget category = GetGame().GetWorkspace().CreateWidgets("{93F4C116E103AFD4}UI/layouts/HUD/WeaponSelection/WeaponCategory.layout",m_wVerticalLayout);
248 if (!category)
249 continue;
250
251 VerticalLayoutSlot.SetPadding(category, 0,4,0,4);
252
253 // Create weapon prefab
254 int categoryNumber = slot.GetWeaponSlotIndex() + 1;
255
256 Widget w = LoadWeaponPrefab(category, slot, categoryNumber);
257 m_aWeaponWidgets.Insert(w);
258
259 Widget numberRoot = GetGame().GetWorkspace().CreateWidgets(m_sNumberWidgetLayout,category);
260 if (!numberRoot)
261 continue;
262
263 ImageWidget number = ImageWidget.Cast(numberRoot.FindAnyWidget("NumberText"));
264 if (number)
265 number.LoadImageFromSet(0, m_sWeaponNumberImageset, categoryNumber.ToString());
266 }
267 }
268
269 //------------------------------------------------------------------------------------------------
270 array<WeaponSlotComponent> GetSortedWeaponSlots(array<WeaponSlotComponent> weapons)
271 {
272 array<WeaponSlotComponent> sortedWeapons = new array<WeaponSlotComponent>;
273 array<int> slotIndexes = new array<int>;
274
275 foreach (WeaponSlotComponent slot : weapons)
276 {
277 if (slot)
278 {
279 int i = slot.GetWeaponSlotIndex() + 1;
280 if (i < 1)
281 i = 100;
282 slotIndexes.Insert(i);
283 }
284 else
285 {
286 slotIndexes.Insert(100);
287 }
288 }
289
290 int count = weapons.Count();
291 for (int i = 0; i < count; i++)
292 {
293 int lowestScore = 1000;
294 int slotIndex = -1;
295
296 for (int j = 0; j < count; j++)
297 {
298 if (slotIndexes.Get(j) <= lowestScore)
299 {
300 slotIndex = j;
301 lowestScore = slotIndexes.Get(j);
302 }
303 }
304
305 if (slotIndex > -1)
306 {
307 WeaponSlotComponent slot = weapons.Get(slotIndex);
308 sortedWeapons.Insert(slot);
309 slotIndexes.Set(slotIndex,1000);
310 }
311 }
312
313 return sortedWeapons;
314 }
315
316 //------------------------------------------------------------------------------------------------
318 {
319 if (!parent)
320 return null;
321
322 Widget w = GetGame().GetWorkspace().CreateWidgets(m_sWeaponWidgetLayout, parent);
323 if (!w)
324 return null;
325
326 HorizontalLayoutSlot.SetPadding(w,0,0,2,0);
327 SetDefaultColor(w,false);
328
329 UIInfo uiInfo = weapon.GetUIInfo();
330 if (uiInfo)
331 {
332 TextWidget name = TextWidget.Cast(w.FindAnyWidget("Name"));
333 ImageWidget icon = ImageWidget.Cast(w.FindAnyWidget("Icon"));
334
335 if (name)
336 {
337 string text = uiInfo.GetName();
338 text.ToUpper();
339 name.SetText(text);
340 }
341
342 if (icon)
343 {
344 string path = uiInfo.GetIconPath();
345 if (path != string.Empty)
346 {
347 icon.LoadImageTexture(0, path);
348 int x, y;
349 icon.GetImageSize(0,x,y);
350 icon.SetSize((float)x, (float)y);
351 }
352 }
353 }
354 else
355 {
356 // Weapon slot is empty: Hide the widget
357 w.SetVisible(false);
358 }
359 return w;
360 }
361
362 //------------------------------------------------------------------------------------------------
363 void HighlightWeapon(int i)
364 {
365 int count = m_aWeaponWidgets.Count();
366 if (i > -1 && i < count)
367 {
368 Widget w = m_aWeaponWidgets.Get(i);
369 if (w && m_wHighlightedWeapon != w)
370 {
371 SetDefaultColor(m_wHighlightedWeapon);
373 SCR_UISoundEntity.SoundEvent(SCR_SoundEvent.ITEM_SELECTED);
374 m_wHighlightedWeapon = w;
375 }
376 }
377 }
378
379 //------------------------------------------------------------------------------------------------
381 {
383
384 int count = m_aWeaponWidgets.Count();
385 i++;
386 for (i; i < count; i++)
387 {
388 if (m_aWeaponWidgets.Get(i))
389 break;
390
391 if (i == count)
392 return;
393 }
394
396 }
397
398 //------------------------------------------------------------------------------------------------
400 {
402 i--;
403 for (i; i >= 0; i--)
404 {
405 if (m_aWeaponWidgets.Get(i))
406 break;
407
408 if (i == 0)
409 return;
410 }
412 }
413
414 //------------------------------------------------------------------------------------------------
416 {
419 }
420
421 //------------------------------------------------------------------------------------------------
423 {
424 int i = -1;
425 if (!m_wHighlightedWeapon)
426 {
427 if (!m_WeaponManager)
428 return -1;
429
430 WeaponSlotComponent currentSlot = m_WeaponManager.GetCurrentSlot();
431 if (!currentSlot)
432 return -1;
433
434 i = m_aWeaponSlotsSorted.Find(currentSlot);
435 }
436 else
437 {
438 i = m_aWeaponWidgets.Find(m_wHighlightedWeapon);
439 }
440
441 return i;
442 }
443
444 //------------------------------------------------------------------------------------------------
446 {
447 int targetSlot = -1;
448
449 if (m_InputManager.GetActionTriggered("SwitchWeaponCategory1"))
450 targetSlot = 0;
451 else if (m_InputManager.GetActionTriggered("SwitchWeaponCategory2"))
452 targetSlot = 1;
453 else if (m_InputManager.GetActionTriggered("SwitchWeaponCategory3"))
454 targetSlot = 2;
455 else if (m_InputManager.GetActionTriggered("SwitchWeaponCategory4"))
456 targetSlot = 3;
457 else if (m_InputManager.GetActionTriggered("SwitchWeaponCategory5"))
458 targetSlot = 4;
459 else if (m_InputManager.GetActionTriggered("SwitchWeaponCategory6"))
460 targetSlot = 5;
461
462 if (targetSlot < 0 || !m_aWeaponSlotsSorted)
463 return;
464
465 foreach (int i, WeaponSlotComponent slot : m_aWeaponSlotsSorted)
466 {
467 if (!slot)
468 continue;
469
470 if (targetSlot == slot.GetWeaponSlotIndex())
471 {
472 if (!m_Controller || !m_WeaponManager)
473 return;
474
475 IEntity weaponEntity = slot.GetWeaponEntity();
476 WeaponSlotComponent currentlySelectedSlot = WeaponSlotComponent.Cast(m_WeaponManager.GetCurrent());
477
478 // Prevent switching to empty weapon slot or the same weapon is selected
479 if (weaponEntity && currentlySelectedSlot != slot)
480 {
481 OnSelectWeapon(slot);
482 if (IsShown() && i < m_aWeaponWidgets.Count())
483 {
484 Widget w = m_aWeaponWidgets.Get(i);
485 if (w)
486 GetGame().GetWorkspace().SetFocusedWidget(w);
487 }
488 Show(false);
489 }
490 }
491
492 }
493 }
494
495 //------------------------------------------------------------------------------------------------
496 void SetDefaultColor(Widget w, bool animate = true)
497 {
499 }
500
501 //------------------------------------------------------------------------------------------------
502 void SetHighlightColor(Widget w, bool animate = true)
503 {
505 }
506
507 //------------------------------------------------------------------------------------------------
508 void HighlightWidget(Widget w, Color backgroundColor, Color colorChild, bool animate = true)
509 {
510 if (!w)
511 return;
512
513 Widget background = w.FindAnyWidget("Background");
514 if (!background)
515 return;
516
517 SCR_UISoundEntity.SoundEvent(SCR_SoundEvent.ITEM_CONFIRMED);
518
519 if (animate)
520 {
521 AnimateWidget.Color(background, backgroundColor, m_fHighlightAnimationSpeed);
523 }
524 else
525 {
526 background.SetColor(backgroundColor);
527 w.SetColor(colorChild);
528 }
529 }
530
531 //------------------------------------------------------------------------------------------------
532 private void RegisterListeners()
533 {
534 if (!m_InputManager)
535 return;
536
537 m_InputManager.AddActionListener("SwitchWeaponCategory1", EActionTrigger.DOWN, HandleKeyboardWeaponSwitch);
538 m_InputManager.AddActionListener("SwitchWeaponCategory2", EActionTrigger.DOWN, HandleKeyboardWeaponSwitch);
539 m_InputManager.AddActionListener("SwitchWeaponCategory3", EActionTrigger.DOWN, HandleKeyboardWeaponSwitch);
540 m_InputManager.AddActionListener("SwitchWeaponCategory4", EActionTrigger.DOWN, HandleKeyboardWeaponSwitch);
541 m_InputManager.AddActionListener("SwitchWeaponCategory5", EActionTrigger.DOWN, EquipHealingItem);
542 m_InputManager.AddActionListener("SwitchWeaponCategory6", EActionTrigger.DOWN, HandleKeyboardWeaponSwitch);
543 }
544
545 //------------------------------------------------------------------------------------------------
546 override void Show(bool show, float speed = UIConstants.FADE_RATE_DEFAULT, EAnimationCurve curve = EAnimationCurve.LINEAR)
547 {
548 super.Show(show, speed);
549
550 //Added this to update the weapon selection upon showing the menu
551 if (show)
552 {
555 }
556 }
557
558 //------------------------------------------------------------------------------------------------
559 private void OnSelectWeapon(WeaponSlotComponent slot)
560 {
562 Event_OnSelectWeapon.Invoke();
563
564 if (!m_Controller)
565 return;
566
567 CharacterControllerComponent characterController = CharacterControllerComponent.Cast(m_Controller);
568 if (characterController)
569 {
570 characterController.SelectWeapon(slot);
571 return;
572 }
573
574 TurretControllerComponent turretController = TurretControllerComponent.Cast(m_Controller);
575 if (turretController)
576 {
577 IEntity player = SCR_PlayerController.GetLocalControlledEntity();
578 turretController.SelectWeapon(player, slot);
579 }
580 }
581
582 //------------------------------------------------------------------------------------------------
584 static ScriptInvoker GetOnSelectWeaponInvoker()
585 {
587 }
588
589 #define DISABLE_WEAPON_SWITCHING
590 #ifndef DISABLE_WEAPON_SWITCHING
591 //------------------------------------------------------------------------------------------------
592 override event void UpdateValues(IEntity owner, float timeSlice)
593 {
594 // Todo: Rewrite this per frame update at event base system as much as possible. Idealy remove whole per frame call.
595
596 //Checking this only when the selection is shown, as only then it's relevant
597 if (m_bShown && DidWeaponsChange())
598 {
601 }
602
603 float cancel = m_InputManager.GetActionTriggered("CharacterCancelWeaponSwitch");
604 float switching = m_InputManager.GetActionValue("CharacterSwitchWeapon");
605 float radialSwitch = m_InputManager.GetActionValue("CharacterSwitchWeaponRadial");
606
607 // TODO@AS: Input collision workaround, resolve
608 if (Math.AbsFloat(m_InputManager.GetActionValue("CharacterSpeedAnalog")) > 0)
609 switching = 0;
610
611 if (m_InteractionMenu && m_InteractionMenu.IsInteractionAvailable())
612 {
613 Show(false);
614 return;
615 }
616
617 if (switching != 0 || m_bShown)
618 {
619 m_InputManager.ActivateContext("WeaponSelectionContext", 250);
620 if (m_InputManager.GetActionTriggered("WeaponSelection"))
621 {
622 m_fLastSelectionTime = owner.GetWorld().GetWorldTime();
624 Show(false);
625 switching = 0;
626 }
627 }
628
629 if (m_bShown)
630 {
631 if (cancel /*|| m_Player.IsInVehicle()*/)
632 {
633 Show(false);
634 return;
635 }
636
637 float time = owner.GetWorld().GetWorldTime();
638 if (switching == 0 && time > m_fLastInteractionTime + m_fInteractionTimeout)
639 {
640 SCR_UISoundEntity.SoundEvent(SCR_SoundEvent.ITEM_CANCELLED);
641 Show(false, UIConstants.FADE_RATE_SLOW);
642 return;
643 }
644 }
645
646 if (switching != 0)
647 {
648 float time = owner.GetWorld().GetWorldTime();
649 float remainingTime = time - m_fLastSelectionTime + m_fSelectionTimeout;
650
651 m_fLastInteractionTime = time;
652 if (!m_bShown)
653 {
654 Show(true);
656 m_fLastSelectionTime = time;
657 }
658 else if (time > m_fLastSelectionTime + m_fSelectionTimeout)
659 {
660 m_fLastSelectionTime = time;
661 if (switching > 0)
663 else
665 }
666 }
667 }
668
669 //------------------------------------------------------------------------------------------------
670 override event void OnStopDraw(IEntity owner)
671 {
672 m_aWeaponSlotsUnsorted.Clear();
673 m_aWeaponSlotsSorted.Clear();
674
675 HUDManagerComponent hudManager = GetGame().GetHUDManager();
676 if (hudManager)
677 {
678 array<SCR_InfoDisplay> displays = hudManager.GetHUDElements();
679 foreach (SCR_InfoDisplay display : displays)
680 {
681 SCR_WeaponSelectionMenu weaponSwitching = SCR_WeaponSelectionMenu.Cast(display);
682 if (weaponSwitching && weaponSwitching != this)
683 {
684 weaponSwitching.Show(true, UIConstants.FADE_RATE_DEFAULT);
685 break;
686 }
687 }
688 }
689
690 super.OnStopDraw(owner);
691 }
692
693 //------------------------------------------------------------------------------------------------
694 override event void OnStartDraw(IEntity owner)
695 {
696 super.OnStartDraw(owner);
697 Init(owner);
698 RegisterListeners();
699 }
700 #endif
701
702 //------------------------------------------------------------------------------------------------
703 void ~SCR_WeaponSelectionMenu()
704 {
705
706 }
707};
string path
override void Init()
ref DSGameConfig game
Definition DSConfig.c:81
ArmaReforgerScripted GetGame()
Definition game.c:1398
InputManager m_InputManager
Widget m_wRoot
bool IsShown()
bool m_bShown
override event void UpdateValues(IEntity owner, float timeSlice)
override event void OnStartDraw(IEntity owner)
override event void OnStopDraw(IEntity owner)
enum EVehicleType IEntity
EAnimationCurve
static WidgetAnimationColor Color(Widget widget, Color color, float speed)
Definition Color.c:13
proto external BaseWorld GetWorld()
Input management system for user interactions.
Definition Math.c:13
void HighlightWidget(Widget w, Color backgroundColor, Color colorChild, bool animate=true)
void SetDefaultColor(Widget w, bool animate=true)
array< WeaponSlotComponent > GetSortedWeaponSlots(array< WeaponSlotComponent > weapons)
static ref ScriptInvoker Event_OnSelectWeapon
Widget LoadWeaponPrefab(Widget parent, BaseWeaponComponent weapon, int category)
void SetHighlightColor(Widget w, bool animate=true)
UIInfo - allows to define UI elements.
Definition UIInfo.c:14
enum EPhysicsLayerPresets Vehicle
Definition gameLib.c:24
override void Show()
Definition gameLib.c:262
SCR_FieldOfViewSettings Attribute
EActionTrigger
ScriptInvokerBase< func > ScriptInvoker
Definition tools.c:134