Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_CampaignFeedbackComponent.c
Go to the documentation of this file.
2{
3}
4
5class SCR_CampaignFeedbackComponent : ScriptComponent
6{
7 [Attribute("{3EE26F4747B6E99D}Configs/Hints/Conflict/ConflictHints.conf", params: "conf class=SCR_CampaignHintStorage")]
8 protected ResourceName m_sHintsConfig;
9
10 [Attribute(defvalue: "3000", desc: "Delay before the vehicle inventory hint appears (ms)")]
11 protected int m_iVehicleHintDelay;
12
14
16
17 protected SCR_CampaignMilitaryBaseComponent m_BaseWithPlayer;
18
19 protected AudioHandle m_PlayedRadio = AudioHandle.Invalid;
20
21 protected vector m_vFirstSpawnPosition;
22
23 protected SCR_MapCampaignUI m_MapCampaignUI;
24
25 protected ref TimeContainer m_SpawnTime;
26
27 protected ref SCR_CampaignHintStorage m_HintsConfig;
28
29 protected SCR_EPopUpState m_EPopUpState;
30
31 protected ref array<int> m_aShownHints = {};
32 protected ref array<int> m_aHintQueue = {};
33
34 protected bool m_bIsPlayerInRadioRange = true;
36 protected bool m_bWasMapOpened;
37 protected bool m_bIsConscious;
38 protected bool m_bWasNight;
40 protected bool m_bIsPlayerCapturing;
41
43
46
47 static const float ICON_FLASH_DURATION = 20;
48 static const float ICON_FLASH_PERIOD = 0.5;
49
50 protected static const int AFTER_RESPAWN_HINT_DELAY_MS = 16500;
51 protected static const int DELAY_BETWEEN_HINTS_MS = 1000;
52 protected static const int FEATURE_HINT_DELAY = 120000;
53 protected static const int NIGHT_HINT_DELAY_MS = 10000;
54 protected static const int COHESION_HINT_DELAY_MS = 20000;
55
56 static const string POPUP_HELP_CONTEST = "#AR-Campaign_Popup_HelpContest";
57 static const string POPUP_SEIZING_CONTESTED = "#AR-Campaign_SeizingContested-UC";
58 static const string POPUP_HELP_CAPTURE = "#AR-Campaign_Popup_HelpCapture";
59 static const string POPUP_SEIZING_FRIENDLY = "#AR-Campaign_SeizingFriendly-UC";
60 static const string POPUP_STOP_CAPTURE = "#AR-Campaign_Popup_StopCapture";
61 static const string POPUP_SEIZING_ENEMY = "#AR-Campaign_SeizingEnemy-UC";
62
63 //------------------------------------------------------------------------------------------------
65 static SCR_CampaignFeedbackComponent GetInstance()
66 {
67 PlayerController pc = GetGame().GetPlayerController();
68
69 if (!pc)
70 return null;
71
72 return SCR_CampaignFeedbackComponent.Cast(pc.FindComponent(SCR_CampaignFeedbackComponent));
73 }
74
75 //------------------------------------------------------------------------------------------------
80 {
82 if (show)
83 {
84 if (m_vFirstSpawnPosition != vector.Zero)
85 return; // Entity change while already spawned at some position, do not update.
86
88 }
89 else
90 {
91 SetMapOpened(false);
92
93 if (m_MapCampaignUI)
94 m_MapCampaignUI.RemoveSpawnPositionHint();
95
97 }
98
99 m_vFirstSpawnPosition = position;
100 }
101
102 //------------------------------------------------------------------------------------------------
105 {
106 m_MapCampaignUI = mapUi;
107 }
108
109 //------------------------------------------------------------------------------------------------
111 {
112 ChimeraWorld world = m_PlayerController.GetWorld();
113 TimeAndWeatherManagerEntity manager = world.GetTimeAndWeatherManager();
114
115 if (manager)
116 m_SpawnTime = manager.GetTime();
117 else
118 Print("Time And Weather manager not found", LogLevel.WARNING);
119 }
120
121 //------------------------------------------------------------------------------------------------
124 {
125 return m_SpawnTime;
126 }
127
128 //------------------------------------------------------------------------------------------------
132 {
134 }
135
136 //------------------------------------------------------------------------------------------------
139 {
140 return m_vFirstSpawnPosition;
141 }
142
143 //------------------------------------------------------------------------------------------------
146 {
147 return m_bWasMapOpened;
148 }
149
150 //------------------------------------------------------------------------------------------------
153 void SetMapOpened(bool wasOpened)
154 {
155 m_bWasMapOpened = wasOpened;
156 }
157
158 //------------------------------------------------------------------------------------------------
161 {
162 return m_BaseWithPlayer;
163 }
164
165 //------------------------------------------------------------------------------------------------
167 {
168 SCR_CampaignFactionManager fManager = SCR_CampaignFactionManager.Cast(GetGame().GetFactionManager());
169
170 if (!fManager)
171 return;
172
174
175 if (!player)
176 return;
177
178 SCR_CampaignFaction faction = SCR_CampaignFaction.Cast(SCR_FactionManager.SGetLocalPlayerFaction());
179
180 if (!faction)
181 return;
182
183 bool isInRangeNow = m_Campaign.GetBaseManager().IsEntityInFactionRadioSignal(player, faction);
184
185 if (isInRangeNow != m_bIsPlayerInRadioRange)
186 {
187 m_bIsPlayerInRadioRange = isInRangeNow;
188
189 if (isInRangeNow)
190 {
191 SCR_PopUpNotification.GetInstance().PopupMsg("#AR-Campaign_RadioRangeEntered-UC", duration: 3);
192 SCR_UISoundEntity.SoundEvent(SCR_SoundEvent.SOUND_RADIO_SIGNAL_GAIN);
193 }
194 else
195 {
196 SCR_PopUpNotification.GetInstance().PopupMsg("#AR-Campaign_RadioRangeLeft-UC", duration: 3);
197 SCR_UISoundEntity.SoundEvent(SCR_SoundEvent.SOUND_RADIO_SIGNAL_LOST);
198 }
199 }
200 }
201
202 //------------------------------------------------------------------------------------------------
203 protected void RegisterTasksShown()
204 {
206 GetGame().GetInputManager().RemoveActionListener("TasksOpen", EActionTrigger.DOWN, RegisterTasksShown);
207 }
208
209 //------------------------------------------------------------------------------------------------
211 void SetIsPlayerInRadioRange(bool status)
212 {
214 }
215
216 //------------------------------------------------------------------------------------------------
217 protected void GroupLeaderHint()
218 {
219 SCR_GroupsManagerComponent groupsManager = SCR_GroupsManagerComponent.GetInstance();
220
221 if (!groupsManager)
222 return;
223
224 SCR_AIGroup group = groupsManager.GetPlayerGroup(m_PlayerController.GetPlayerId());
225
226 if (!group)
227 return;
228
229 IEntity leader = GetGame().GetPlayerManager().GetPlayerControlledEntity(group.GetLeaderID());
230
231 if (leader != m_PlayerController.GetControlledEntity())
232 return;
233
234 GetGame().GetCallqueue().Remove(GroupLeaderHint);
235 ShowHint(EHint.GAMEPLAY_GROUPS);
236 }
237
238 //------------------------------------------------------------------------------------------------
239 protected void LoneDriverHint()
240 {
241 SCR_ChimeraCharacter player = SCR_ChimeraCharacter.Cast(GetGame().GetPlayerController().GetControlledEntity());
242
243 if (!player)
244 return;
245
246 if (!player.IsInVehicle())
247 return;
248
249 Vehicle vehicle = Vehicle.Cast(SCR_EntityHelper.GetMainParent(player));
250
251 if (!vehicle)
252 return;
253
254 SCR_EditableVehicleComponent comp = SCR_EditableVehicleComponent.Cast(vehicle.FindComponent(SCR_EditableVehicleComponent));
255
256 if (!comp)
257 return;
258
259 array<CompartmentAccessComponent> compartments = {};
260
261 if (comp.GetCrew(compartments, false) > 1)
262 return;
263
264 GetGame().GetCallqueue().Remove(LoneDriverHint);
265
266 ShowHint(EHint.CONFLICT_DRIVER);
267 }
268
269 //------------------------------------------------------------------------------------------------
270 protected void TransportRequestHint()
271 {
272 if (m_BaseWithPlayer)
273 return;
274
275 SCR_ChimeraCharacter player = SCR_ChimeraCharacter.Cast(m_PlayerController.GetControlledEntity());
276
277 if (!player || player.IsInVehicle())
278 return;
279
281
282 if (!baseManager)
283 return;
284
285 array<SCR_MilitaryBaseComponent> bases = {};
286 baseManager.GetBases(bases);
287 int minDistanceSq = 500 * 500;
288 vector playerPos = player.GetOrigin();
290
291 // Show this hint only if player is far enough from any base
292 foreach (SCR_MilitaryBaseComponent base : bases)
293 {
294 campaignBase = SCR_CampaignMilitaryBaseComponent.Cast(base);
295
296 if (!campaignBase)
297 continue;
298
299 if (vector.DistanceSqXZ(playerPos, campaignBase.GetOwner().GetOrigin()) < minDistanceSq)
300 return;
301 }
302
303 minDistanceSq = 300 * 300;
304 array<int> playerIds = {};
305 int localPlayerId = m_PlayerController.GetPlayerId();
306 GetGame().GetPlayerManager().GetPlayers(playerIds);
307
308 // Show this hint only if player is far enough from any other living player
309 foreach (int playerId : playerIds)
310 {
311 if (playerId == localPlayerId)
312 continue;
313
314 SCR_ChimeraCharacter otherPlayer = SCR_ChimeraCharacter.Cast(GetGame().GetPlayerManager().GetPlayerControlledEntity(playerId));
315
316 if (!otherPlayer)
317 continue;
318
319 CharacterControllerComponent charControl = otherPlayer.GetCharacterController();
320
321 if (!charControl || charControl.IsDead())
322 continue;
323
324 if (vector.DistanceSqXZ(playerPos, otherPlayer.GetOrigin()) < minDistanceSq)
325 return;
326 }
327
328 GetGame().GetCallqueue().Remove(TransportRequestHint);
329 ShowHint(EHint.CONFLICT_TRANSPORT_REQUEST, showMultipleTimes: true);
330 }
331
332 //------------------------------------------------------------------------------------------------
336 {
337 SCR_CampaignFaction playerFaction = SCR_CampaignFaction.Cast(SCR_FactionManager.SGetLocalPlayerFaction());
338
339 if (!playerFaction || base.GetFaction() != playerFaction)
340 return;
341
342 if (base.GetHQRadioCoverage(playerFaction) != SCR_ERadioCoverageStatus.RECEIVE)
343 return;
344
345 ShowHint(EHint.CONFLICT_NO_CONNECTION);
346 }
347
348 //------------------------------------------------------------------------------------------------
351 {
352 // ---- FUNCTIONAL: Always register radial menu & hover listeners ----
353 SCR_MapRadialUI mapContextualMenu = SCR_MapRadialUI.GetInstance();
354 if (mapContextualMenu)
355 {
356 SCR_RadialMenu radialMenu = mapContextualMenu.GetRadialController().GetRadialMenu();
357 if (radialMenu)
358 {
359 // Available now — hook directly
360 radialMenu.GetOnEntryPerformed().Insert(OnEntryPerformed);
361 radialMenu.GetOnOpen().Insert(OnRadialMenuOpen);
362 }
363 else
364 {
365 // Not ready yet — wait for init (deferred)
366 mapContextualMenu.GetOnMenuInitInvoker().Insert(OnRadialMenuAvailable);
367 }
368 }
369
371 if (mapEntity)
372 {
374 if (mapCampaignUI)
375 mapCampaignUI.GetOnBaseHovered().Insert(OnBaseHovered);
376 }
377
378 // ---- HINTS: Guard only the hint logic, may early exit ----
379 if (GetGame().GetWorld().GetWorldTime() < FEATURE_HINT_DELAY)
380 return;
381
382 if (!config)
383 return;
384
385 if(config.MapEntityMode == EMapEntityMode.SPAWNSCREEN)
386 return;
387
388 switch (config.MapEntityMode)
389 {
390 case EMapEntityMode.COMBAT_SUPPORT_STATION:
391 ShowHint(EHint.CONFLICT_COMMANDER_HQ_RADIO);
392 break;
393
394 case EMapEntityMode.OPERATIONS_STATION:
395 ShowHint(EHint.CONFLICT_COMMANDER_HQ_OPERATIONS);
396 break;
397
398 case EMapEntityMode.LOGISTICS_STATION:
399 ShowHint(EHint.CONFLICT_COMMANDER_HQ_LOGISTICS);
400 break;
401
402 default:
403 ShowHint(EHint.CONFLICT_GROUP_ICONS);
404 break;
405 }
406
407 SCR_GroupsManagerComponent groupManager = SCR_GroupsManagerComponent.GetInstance();
408 if (!groupManager)
409 return;
410
411 SCR_AIGroup playerGroup = groupManager.GetPlayerGroup(SCR_PlayerController.GetLocalPlayerId());
412 if (!playerGroup)
413 return;
414
415 SCR_Faction playerFaction = SCR_Faction.Cast(playerGroup.GetFaction());
416 if (!playerFaction)
417 return;
418
420 ShowHint(EHint.CONFLICT_SQUAD_LEADER_COMMUNICATION);
421 }
422
423 //------------------------------------------------------------------------------------------------
424 protected void OnRadialMenuAvailable()
425 {
427 if (!mapMenu)
428 return;
429
431 // adding radial menu-related invokers deferred, remove in OnMapClose
432 SCR_RadialMenu radialMenu = mapMenu.GetRadialController().GetRadialMenu();
433 if (radialMenu)
434 {
435 radialMenu.GetOnEntryPerformed().Insert(OnEntryPerformed);
436 radialMenu.GetOnOpen().Insert(OnRadialMenuOpen);
437 }
438 }
439
440 //------------------------------------------------------------------------------------------------
442 {
443 if (!entry)
444 return;
445
446 SCR_FactionCommanderPlayerComponent commander = SCR_FactionCommanderPlayerComponent.Cast(m_PlayerController.FindComponent(SCR_FactionCommanderPlayerComponent));
447 if (!commander)
448 return;
449
450 SCR_FactionCommanderMenuEntry configForEntry = commander.GetConfigForEntry(entry);
451 if (!configForEntry)
452 return;
453
454 if (configForEntry.GetShowHint())
455 ShowHint(configForEntry.GetHintId());
456 }
457
458 //------------------------------------------------------------------------------------------------
460 {
462 if (mapMenu)
463 {
465
466 SCR_RadialMenu radialMenu = mapMenu.GetRadialController().GetRadialMenu();
467 if (radialMenu)
468 {
469 radialMenu.GetOnEntryPerformed().Remove(OnEntryPerformed);
470 radialMenu.GetOnOpen().Remove(OnRadialMenuOpen);
471 }
472 }
473
475 if (mapEntity)
476 {
478 if (mapCampaignUI)
479 mapCampaignUI.GetOnBaseHovered().Remove(OnBaseHovered)
480 }
481 }
482
483 //------------------------------------------------------------------------------------------------
485 {
486 if (base && base.GetType() == SCR_ECampaignBaseType.SOURCE_BASE)
487 ShowHint(EHint.CONFLICT_SOURCE_BASE);
488 }
489
490 //------------------------------------------------------------------------------------------------
491 protected void OnCommanderVolunteer(int playerId)
492 {
493 ShowHint(EHint.CONFLICT_COMMANDER_VOTING);
495 }
496
497 //------------------------------------------------------------------------------------------------
498 protected void OnFactionCommanderChanged(SCR_Faction faction, int commanderPlayerId)
499 {
500 if (SCR_PlayerController.GetLocalPlayerId() != commanderPlayerId)
501 return;
502
503 ShowHint(EHint.CONFLICT_COMMANDER_ROLE);
504 if (SCR_FactionCommanderHandlerComponent.GetInstance())
505 SCR_FactionCommanderHandlerComponent.GetInstance().GetOnFactionCommanderChanged().Remove(OnFactionCommanderChanged);
506 }
507
508 //------------------------------------------------------------------------------------------------
509 protected void OnBaseClickedShowSupplyLimit(bool selected)
510 {
511 if (!selected)
512 return;
513
514 ShowHint(EHint.CONFLICT_COMMANDER_HQ_LOGISTICS_SUPPLY);
516 }
517
518 //------------------------------------------------------------------------------------------------
520 {
521 return m_EPopUpState;
522 }
523
524 //------------------------------------------------------------------------------------------------
526 {
528 SCR_PopupMessage currentMsg = popup.GetCurrentMsg();
529
530 // if is there any popup with higher priority, the seize popup will not appear.
531 if (currentMsg && currentMsg.m_iPriority > SCR_ECampaignSeizingMessagePrio.SEIZING_ENEMY)
532 return;
533
534 // Determine what kind of pop up should show
535 m_EPopUpState = GetPopUpState();
536
537 // Execute the logic to display the pop up
538 HandlePopUpState(m_EPopUpState, popup, currentMsg);
539 }
540
541 //------------------------------------------------------------------------------------------------
543 {
544 // Player has to be alive and inside a base
545 if (!m_BaseWithPlayer || !IsLocalPlayerAlive())
546 return SCR_EPopUpState.NONE;
547
548 SCR_EBaseCaptureState capturestate = m_BaseWithPlayer.GetCaptureState();
549
550 if (capturestate == SCR_EBaseCaptureState.NONE)
551 return SCR_EPopUpState.NONE;
552
554
555 if (capturestate == SCR_EBaseCaptureState.CONTESTED)
556 {
557 SCR_CampaignSeizingComponent seizingComp = SCR_CampaignSeizingComponent.Cast(m_BaseWithPlayer.GetOwner().FindComponent(SCR_CampaignSeizingComponent));
558 if (!seizingComp)
559 return SCR_EPopUpState.NONE;
560
561 if (seizingComp.GetContestingFactionsCount() > 1 || !m_bIsPlayerCapturing)
562 return SCR_EPopUpState.CONTESTED;
563
564 return SCR_EPopUpState.NONE;
565 }
566
567 if (capturestate == SCR_EBaseCaptureState.CAPTURING)
568 {
569 // If relay tower is being reconfigured, calculate the capture duration
570 if (m_BaseWithPlayer.GetType() == SCR_ECampaignBaseType.RELAY)
572
573 // If capture timers are invalid, hide seizing popup
575 return SCR_EPopUpState.NONE;
576
577 SCR_CampaignFaction capturingFaction = SCR_CampaignFaction.Cast(m_BaseWithPlayer.GetCapturingFaction());
578
579 //Determine who the base is being captured by
580 bool isPlayerFaction = capturingFaction == SCR_FactionManager.SGetLocalPlayerFaction();
581
582 if (isPlayerFaction)
583 {
585 return SCR_EPopUpState.NONE;
586
587 return SCR_EPopUpState.FRIENDLY_CAPTURE;
588 }
589
590 return SCR_EPopUpState.ENEMY_CAPTURE;
591 }
592
593 return SCR_EPopUpState.NONE;
594 }
595
596 //------------------------------------------------------------------------------------------------
597 protected void HandlePopUpState(SCR_EPopUpState state, notnull SCR_PopUpNotification popup, SCR_PopupMessage currentMsg)
598 {
599 string subTitle;
600
601 switch (state)
602 {
603 case SCR_EPopUpState.NONE:
604 {
605 if (currentMsg && (currentMsg.m_iPriority == SCR_ECampaignSeizingMessagePrio.SEIZING_YOU || currentMsg.m_iPriority == SCR_ECampaignSeizingMessagePrio.SEIZING_ENEMY || currentMsg.m_iPriority == SCR_ECampaignSeizingMessagePrio.CONTESTING))
606 popup.HideCurrentMsg();
607
608 break;
609 }
610
611 case SCR_EPopUpState.CONTESTED:
612 {
613 if (currentMsg && (currentMsg.m_iPriority == SCR_ECampaignSeizingMessagePrio.SEIZING_ENEMY || currentMsg.m_iPriority == SCR_ECampaignSeizingMessagePrio.SEIZING_YOU))
614 popup.HideCurrentMsg();
615
617 subTitle = POPUP_HELP_CONTEST;
618
619 SetPopup(popup, currentMsg, POPUP_SEIZING_CONTESTED, subTitle, SCR_ECampaignSeizingMessagePrio.CONTESTING);
620
621 break;
622 }
623
624 case SCR_EPopUpState.FRIENDLY_CAPTURE:
625 {
626 if (currentMsg && (currentMsg.m_iPriority == SCR_ECampaignSeizingMessagePrio.SEIZING_ENEMY || currentMsg.m_iPriority == SCR_ECampaignSeizingMessagePrio.CONTESTING))
627 popup.HideCurrentMsg();
628
630 subTitle = POPUP_HELP_CAPTURE;
631
632 SetPopup(popup, currentMsg, POPUP_SEIZING_FRIENDLY, subTitle, SCR_ECampaignSeizingMessagePrio.SEIZING_YOU, m_bIsPlayerCapturing);
633
634 break;
635 }
636
637 case SCR_EPopUpState.ENEMY_CAPTURE:
638 {
639 if (currentMsg && (currentMsg.m_iPriority == SCR_ECampaignSeizingMessagePrio.SEIZING_YOU || currentMsg.m_iPriority == SCR_ECampaignSeizingMessagePrio.CONTESTING))
640 popup.HideCurrentMsg();
641
643 subTitle = POPUP_STOP_CAPTURE;
644
645 SetPopup(popup, currentMsg, POPUP_SEIZING_ENEMY, subTitle, SCR_ECampaignSeizingMessagePrio.SEIZING_ENEMY, m_bIsPlayerCapturing);
646
647 break;
648 }
649 }
650 }
651
652 //------------------------------------------------------------------------------------------------
653 protected void SetPopup(SCR_PopUpNotification popup, SCR_PopupMessage currentMsg, string title, string subtitle, int priority, bool useProgressBar = false)
654 {
655 bool needsUpdate = !currentMsg || currentMsg.m_iPriority != priority || currentMsg.m_sText != title || currentMsg.m_sSubtitle != subtitle;
656
657 if (!needsUpdate)
658 return;
659
660 if (useProgressBar)
661 popup.PopupMsg(title, -1, prio: priority, progressStart: m_fBaseWithPlayerCaptureStart, progressEnd: m_fBaseWithPlayerCaptureEnd, category: SCR_EPopupMsgFilter.TUTORIAL);
662 else
663 popup.PopupMsg(title, -1, subtitle, prio: priority, category: SCR_EPopupMsgFilter.TUTORIAL);
664 }
665
666 //------------------------------------------------------------------------------------------------
667 protected bool IsPlayerCapturing()
668 {
669 SCR_CampaignSeizingComponent seizingComp = SCR_CampaignSeizingComponent.Cast(m_BaseWithPlayer.GetOwner().FindComponent(SCR_CampaignSeizingComponent));
670 if (!seizingComp)
671 return false;
672
674 if (!player)
675 return false;
676
677 CharacterControllerComponent charController = player.GetCharacterController();
678
679 if (!charController || charController.GetLifeState() == ECharacterLifeState.DEAD)
680 return false;
681
682 vector playerPos = player.GetOrigin();
683
684 // Triggers calculate entity presence by bounding boxes
685 // We need to calculate the player's bbox radius to match the distance to the trigger
686 vector boundsMin, boundsMax;
687 player.GetWorldBounds(boundsMin, boundsMax);
688 float distanceDiff = vector.DistanceXZ(boundsMin, boundsMax) * 0.5;
689
690 if (!player.IsInVehicle() || SCR_TerrainHelper.GetHeightAboveTerrain(playerPos) <= seizingComp.GetMaximumAltitude())
691 return vector.DistanceXZ(playerPos, m_BaseWithPlayer.GetOwner().GetOrigin()) <= (seizingComp.GetRadius() + distanceDiff);
692 else
693 return false;
694 }
695
696 //------------------------------------------------------------------------------------------------
699 {
701 GetGame().GetCallqueue().CallLater(ProcessHintQueue, SCR_GameModeCampaign.UI_UPDATE_DELAY); // Delay so we show the hint after the deploy menu has closed
702
703 SCR_GroupsManagerComponent groupManager = SCR_GroupsManagerComponent.GetInstance();
704 if (!groupManager)
705 return;
706
707 SCR_AIGroup playerGroup = groupManager.GetPlayerGroup(SCR_PlayerController.GetLocalPlayerId());
708 if (!playerGroup)
709 return;
710
712 {
713 switch (playerGroup.GetGroupRole())
714 {
715 case SCR_EGroupRole.RECON:
716 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_SQUAD_LEADER_RECON, false, false);
717 break;
718
719 case SCR_EGroupRole.TRANSPORT:
720 case SCR_EGroupRole.HELI_TRANSPORT:
721 case SCR_EGroupRole.ENGINEER:
722 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_SQUAD_LEADER_SUPPLIES, false, false);
723 break;
724
725 case SCR_EGroupRole.ASSAULT:
726 case SCR_EGroupRole.MECHANIZED:
727 case SCR_EGroupRole.MACHINEGUN:
728 case SCR_EGroupRole.ANTITANK:
729 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_SQUAD_LEADER_BASIC, false, false);
730 break;
731 case SCR_EGroupRole.MEDIC:
732 case SCR_EGroupRole.MORTAR:
733 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_SQUAD_LEADER_SUPPORT, false, false);
734 break;
735 }
736 }
737 else
738 {
739 switch (playerGroup.GetGroupRole())
740 {
741 case SCR_EGroupRole.ASSAULT:
742 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_GROUPS_ASSAULT, false, false);
743 break;
744
745 case SCR_EGroupRole.MECHANIZED:
746 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_GROUPS_MECHANIZED, false, false);
747 break;
748
749 case SCR_EGroupRole.TRANSPORT:
750 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_GROUPS_TRANSPORT, false, false);
751 break;
752
753 case SCR_EGroupRole.HELI_TRANSPORT:
754 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_GROUPS_HELI_TRANSPORT, false, false);
755 break;
756
757 case SCR_EGroupRole.RECON:
758 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_GROUPS_RECON, false, false);
759 break;
760
761 case SCR_EGroupRole.MACHINEGUN:
762 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_GROUPS_MACHINEGUN, false, false);
763 break;
764
765 case SCR_EGroupRole.ANTITANK:
766 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_GROUPS_ANTITANK, false, false);
767 break;
768
769 case SCR_EGroupRole.ENGINEER:
770 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_GROUPS_ENGINEER, false, false);
771 break;
772
773 case SCR_EGroupRole.MEDIC:
774 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_GROUPS_MEDIC, false, false);
775 break;
776
777 case SCR_EGroupRole.MORTAR:
778 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_GROUPS_MORTAR, false, false);
779 break;
780 }
781 }
782
783 if (!m_aShownHints.Contains(EHint.CONFLICT_SERVICE_DEPOTS))
784 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_SERVICE_DEPOTS, false, false);
785 else if (!m_aShownHints.Contains(EHint.CONFLICT_RALLY_POINTS))
786 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_RALLY_POINTS, false, false);
787 else if (!m_aShownHints.Contains(EHint.CONFLICT_RESPAWN))
788 GetGame().GetCallqueue().CallLater(ShowHint, AFTER_RESPAWN_HINT_DELAY_MS, false, EHint.CONFLICT_RESPAWN, false, false);
789 }
790
791 //------------------------------------------------------------------------------------------------
793 {
794 ShowHint(EHint.CONFLICT_FOB_BUILDING);
795 SCR_EstablishBaseTaskEntity.GetOnPlayerEnteredEstablishingArea().Remove(OnCheckEstablishmentArea);
796 }
797
798 //------------------------------------------------------------------------------------------------
799 protected void OnTaskAssigneeAdded(SCR_Task task, SCR_TaskExecutor executor, int requesterID)
800 {
801 SCR_GroupsManagerComponent groupManager = SCR_GroupsManagerComponent.GetInstance();
802 if (!groupManager)
803 return;
804
805 SCR_TaskExecutorGroup groupExec = SCR_TaskExecutorGroup.Cast(executor);
806 if (groupExec)
807 {
808 SCR_AIGroup assignedGroup = groupManager.FindGroup(groupExec.GetGroupID());
809 if (!assignedGroup)
810 return;
811
812 array<int> playerIds = {};
813 playerIds = assignedGroup.GetPlayerIDs();
814 if (!playerIds.Contains(SCR_PlayerController.GetLocalPlayerId()))
815 return;
816 }
817 else
818 {
819 SCR_TaskExecutorPlayer playerExec = SCR_TaskExecutorPlayer.Cast(executor);
820 if (!playerExec)
821 return;
822
824 return;
825 }
826
827 SCR_AIGroup playerGroup = groupManager.GetPlayerGroup(SCR_PlayerController.GetLocalPlayerId());
828 if (!playerGroup)
829 return;
830
831 if (SCR_EstablishBaseTaskEntity.Cast(task))
832 {
833 if (playerGroup == SCR_EGroupRole.ENGINEER)
834 ShowHint(EHint.CONFLICT_OBJECTIVES_ESTABLISH_BASE);
835 else
836 ShowHint(EHint.CONFLICT_FOB_OBJECTIVE);
837
838 return;
839 }
840
841 if (SCR_PickupRequestedTaskEntity.Cast(task))
842 {
843 ShowHint(EHint.CONFLICT_PICKUP_ASSIGNED);
844 return;
845 }
846
847 if (SCR_ReinforceRequestedTaskEntity.Cast(task))
848 {
849 ShowHint(EHint.CONFLICT_REINFORCE_ASSIGNMENT);
850 return;
851 }
852
853 if (SCR_RearmRequestedTaskEntity.Cast(task))
854 {
855 ShowHint(EHint.CONFLICT_REARM_ASSIGNMENT);
856 return;
857 }
858
859 if (SCR_RepairRequestedTaskEntity.Cast(task))
860 {
861 ShowHint(EHint.CONFLICT_REPAIR_ASSIGNMENT);
862 return;
863 }
864
865 if (SCR_FireSupportRequestedTaskEntity.Cast(task))
866 {
867 ShowHint(EHint.CONFLICT_FIRE_SUPPORT_ASSIGNMENT);
868 return;
869 }
870
871 if (SCR_ResupplyCampaignMilitaryBaseTaskEntity.Cast(task))
872 {
873 ShowHint(EHint.CONFLICT_OBJECTIVES_RESSUPLY);
874 return;
875 }
876
877 if (SCR_AttackTaskEntity.Cast(task))
878 {
879 ShowHint(EHint.CONFLICT_OBJECTIVES_ATTACK);
880 return;
881 }
882
883 if (SCR_SeizeCampaignMilitaryBaseTaskEntity.Cast(task))
884 {
885 ShowHint(EHint.CONFLICT_OBJECTIVES_SEIZE);
886 return;
887 }
888
889 if (SCR_HoldCampaignMilitaryBaseTaskEntity.Cast(task))
890 {
891 ShowHint(EHint.CONFLICT_OBJECTIVES_HOLD);
892 return;
893 }
894
895 if (SCR_ReconTaskEntity.Cast(task))
896 {
897 ShowHint(EHint.CONFLICT_OBJECTIVES_RECON);
898 return;
899 }
900
901 if (SCR_DismantleCampaignMilitaryBaseTaskEntity.Cast(task))
902 {
903 ShowHint(EHint.CONFLICT_OBJECTIVES_DISMANTLE);
904 return;
905 }
906
907 if (SCR_ClearTaskEntity.Cast(task))
908 {
909 ShowHint(EHint.CONFLICT_OBJECTIVES_CLEAR);
910 return;
911 }
912
913 // TODO: once implement the hints for objectives rally, regroup request, restock request
914 }
915
916 //------------------------------------------------------------------------------------------------
921 void ShowHint(EHint hintID, bool showImmediately = false, bool showMultipleTimes = false)
922 {
923 if (m_Campaign.IsTutorial())
924 return;
925
926 if (RplSession.Mode() == RplMode.Dedicated)
927 return;
928
929 SCR_HintUIInfo info = m_HintsConfig.GetHintByEnum(hintID);
930
931 if (!info)
932 return;
933
934 if (!showMultipleTimes && (m_aShownHints.Contains(hintID) || m_aHintQueue.Contains(hintID)))
935 return;
936
937 float currentTime = GetGame().GetWorld().GetWorldTime();
938
939 if (currentTime < m_fNextAllowedHintTimestamp && !showImmediately)
940 {
941 m_aHintQueue.Insert(hintID);
942 }
943 else
944 {
945 if (!SCR_HintManagerComponent.ShowHint(info))
946 {
948 return;
949 }
950
951 m_aShownHints.Insert(hintID);
952
953 // Show the next hint in queue after this hint's duration expires
954 float durationMs = 1000 * info.GetDuration();
955 m_fNextAllowedHintTimestamp = currentTime + durationMs;
956 GetGame().GetCallqueue().Remove(ProcessHintQueue);
957 GetGame().GetCallqueue().CallLater(ProcessHintQueue, durationMs + DELAY_BETWEEN_HINTS_MS);
958 }
959 }
960
961 //------------------------------------------------------------------------------------------------
962 protected void ProcessHintQueue()
963 {
964 if (m_aHintQueue.IsEmpty())
965 return;
966
967 int hintId = m_aHintQueue[0];
968 m_aHintQueue.RemoveOrdered(0);
969
970 ShowHint(hintId, showMultipleTimes: true);
971 }
972
973 //------------------------------------------------------------------------------------------------
976 {
977 GetGame().GetCallqueue().Remove(ProcessHintQueue);
978 }
979
980 //------------------------------------------------------------------------------------------------
983 void OnConsciousnessChanged(bool conscious)
984 {
985 m_bIsConscious = conscious;
986 }
987
988 //------------------------------------------------------------------------------------------------
991 {
992 return m_bIsConscious;
993 }
994
995 //------------------------------------------------------------------------------------------------
996 protected bool IsLocalPlayerAlive()
997 {
999 if (player)
1000 {
1001 CharacterControllerComponent charController = player.GetCharacterController();
1002 if (charController && charController.GetLifeState() == ECharacterLifeState.DEAD)
1003 return false;
1004 }
1005
1006 return true;
1007 }
1008
1009 //------------------------------------------------------------------------------------------------
1014 void OnPlayerKilled(notnull SCR_InstigatorContextData instigatorContextData)
1015 {
1016 if (instigatorContextData.GetVictimEntity() != SCR_PlayerController.GetLocalControlledEntity())
1017 return;
1018
1019 if (m_BaseWithPlayer)
1020 OnBaseLeft(m_BaseWithPlayer);
1021
1023 GetGame().GetCallqueue().Remove(ShowHint);
1024 }
1025
1026 //------------------------------------------------------------------------------------------------
1029 void OnBaseFactionChanged(notnull SCR_MilitaryBaseComponent base, Faction faction)
1030 {
1031 if (faction != SCR_FactionManager.SGetLocalPlayerFaction())
1032 return;
1033
1035
1036 if (!campaignBase)
1037 return;
1038
1039 if (campaignBase.GetType() == SCR_ECampaignBaseType.BASE && GetGame().GetWorld().GetWorldTime() > FEATURE_HINT_DELAY)
1040 {
1042 array<SCR_MilitaryBaseComponent> bases = {};
1043 baseManager.GetBases(bases);
1044 int friendlyBases;
1045
1046 foreach (SCR_MilitaryBaseComponent currentBase : bases)
1047 {
1048 if (currentBase.GetOwner() != faction)
1049 continue;
1050
1051 friendlyBases++;
1052
1053 if (friendlyBases == 3)
1054 {
1055 ShowHint(EHint.CONFLICT_SUPPLIES);
1056 break;
1057 }
1058 }
1059 }
1060 }
1061
1062 //------------------------------------------------------------------------------------------------
1065 {
1066 if (m_BaseWithPlayer)
1067 OnBaseLeft(m_BaseWithPlayer);
1068
1069 m_BaseWithPlayer = base;
1070
1071 SCR_CampaignSeizingComponent seizingComponent = SCR_CampaignSeizingComponent.Cast(m_BaseWithPlayer.GetOwner().FindComponent(SCR_CampaignSeizingComponent));
1072
1073 if (seizingComponent)
1074 {
1075 OnSeizingTimerChange(seizingComponent.GetSeizingStartTimestamp(), seizingComponent.GetSeizingEndTimestamp());
1076 seizingComponent.GetOnTimerChange().Remove(OnSeizingTimerChange);
1077 seizingComponent.GetOnTimerChange().Insert(OnSeizingTimerChange);
1078 }
1079 else
1080 {
1081 OnSeizingTimerChange(null, null);
1082 }
1083
1084 SCR_CampaignFaction playerFaction = SCR_CampaignFaction.Cast(SCR_FactionManager.SGetLocalPlayerFaction());
1085
1086 if (m_BaseWithPlayer.GetFaction() != playerFaction)
1087 {
1088 // Entering an enemy base
1089 if (playerFaction && m_BaseWithPlayer.IsHQRadioTrafficPossible(playerFaction))
1090 {
1091 SCR_TaskExecutor executor = SCR_TaskExecutor.FromPlayerID(m_PlayerController.GetPlayerId());
1092
1093 if (executor)
1094 {
1095 array<SCR_Task> availableTasks = {};
1096 SCR_TaskSystem.GetInstance().GetTasksVisibleFor(availableTasks, executor);
1097 SCR_SeizeCampaignMilitaryBaseTaskEntity campaignTask;
1098
1099 foreach (SCR_Task task : availableTasks)
1100 {
1101 campaignTask = SCR_SeizeCampaignMilitaryBaseTaskEntity.Cast(task);
1102
1103 if (!campaignTask || campaignTask.GetMilitaryBase() != m_BaseWithPlayer || campaignTask.IsTaskAssignedTo(executor))
1104 continue;
1105
1106 // Entering an enemy base within radio signal reach while not having its seize task assigned
1107 ShowHint(EHint.CONFLICT_VOLUNTEERING);
1108 break;
1109 }
1110 }
1111
1112 // Entering an enemy base within radio signal reach
1113 if (m_BaseWithPlayer.GetType() == SCR_ECampaignBaseType.RELAY)
1114 ShowHint(EHint.CONFLICT_TOWER_SEIZING);
1115 else
1116 ShowHint(EHint.CONFLICT_BASE_SEIZING);
1117 }
1118 }
1119 else
1120 {
1121 // Entering a friendly base
1123
1124 if (player && player.IsInVehicle())
1125 {
1126 // Entering a friendly base in a vehicle
1127 if (m_BaseWithPlayer.GetType() == SCR_ECampaignBaseType.BASE && !m_BaseWithPlayer.IsHQ())
1128 ShowHint(EHint.CONFLICT_SUPPLY_RUNS);
1129 }
1130
1131 // Entering a friendly base with an armory
1132 if (GetGame().GetWorld().GetWorldTime() > SCR_GameModeCampaign.BACKEND_DELAY && m_BaseWithPlayer.GetServiceDelegateByType(SCR_EServicePointType.ARMORY))
1133 {
1134 ShowHint(EHint.CONFLICT_LOADOUTS);
1135 ShowHint(EHint.GAMEPLAY_RADIO_RESPAWN);
1136 }
1137
1138 // Entering a friendly base covered by enemy radio signal
1139 bool covered;
1140
1141 if (SCR_FactionManager.SGetLocalPlayerFaction() == m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.BLUFOR))
1142 covered = base.IsHQRadioTrafficPossible(m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.OPFOR));
1143 else
1144 covered = base.IsHQRadioTrafficPossible(m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.BLUFOR));
1145
1146 if (covered)
1147 ShowHint(EHint.CONFLICT_DEFENDING_BASES);
1148 }
1149 }
1150
1151 //------------------------------------------------------------------------------------------------
1154 {
1155 SCR_CampaignSeizingComponent seizingComponent = SCR_CampaignSeizingComponent.Cast(base.GetOwner().FindComponent(SCR_CampaignSeizingComponent));
1156
1157 if (seizingComponent)
1158 seizingComponent.GetOnTimerChange().Remove(OnSeizingTimerChange);
1159
1160 if (m_BaseWithPlayer == base)
1161 m_BaseWithPlayer = null;
1162 }
1163
1164 //------------------------------------------------------------------------------------------------
1166 {
1167 Faction winner = GetGame().GetFactionManager().GetFactionByIndex(m_Campaign.GetWinningFactionId());
1168
1169 if (!winner || winner == SCR_FactionManager.SGetLocalPlayerFaction())
1170 return;
1171
1172 m_Campaign.GetOnMatchSituationChanged().Remove(OnMatchSituationChanged);
1173 ShowHint(EHint.CONFLICT_LOSING);
1174 }
1175
1176 //------------------------------------------------------------------------------------------------
1185
1186 //------------------------------------------------------------------------------------------------
1191 void MobileAssemblyFeedback(SCR_EMobileAssemblyStatus msgID, int playerID, int factionID)
1192 {
1193 SCR_CampaignFactionManager fManager = SCR_CampaignFactionManager.Cast(GetGame().GetFactionManager());
1194
1195 if (!fManager)
1196 return;
1197
1198 Faction localPlayerFaction = SCR_FactionManager.SGetLocalPlayerFaction();
1199
1200 if (fManager.GetFactionIndex(localPlayerFaction) != factionID)
1201 return;
1202
1203 const int duration = 6; // TODO: check for good const usage
1204 LocalizedString text;
1205 LocalizedString text2;
1206 string playerName = SCR_PlayerNamesFilterCache.GetInstance().GetPlayerDisplayName(playerID);
1207
1209
1210 if (mapEntity && mapEntity.IsOpen())
1211 m_MapCampaignUI.InitMobileAssembly(localPlayerFaction.GetFactionKey(), msgID == SCR_EMobileAssemblyStatus.DEPLOYED);
1212
1213 switch (msgID)
1214 {
1215 case SCR_EMobileAssemblyStatus.DEPLOYED:
1216 {
1217 text = "#AR-Campaign_MobileAssemblyDeployed-UC";
1218 text2 = "#AR-Campaign_MobileAssemblyPlayerName";
1219 break;
1220 }
1221
1222 case SCR_EMobileAssemblyStatus.DISMANTLED:
1223 {
1224 text = "#AR-Campaign_MobileAssemblyDismantled-UC";
1225 text2 = "#AR-Campaign_MobileAssemblyPlayerName";
1226 Faction reconfigurerFaction = SCR_FactionManager.SGetPlayerFaction(playerID);
1227
1228 if (reconfigurerFaction && localPlayerFaction != reconfigurerFaction)
1229 playerName = reconfigurerFaction.GetFactionName();
1230
1231 break;
1232 }
1233
1234 case SCR_EMobileAssemblyStatus.DESTROYED:
1235 {
1236 text = "#AR-Campaign_MobileAssemblyDestroyed-UC";
1237 break;
1238 }
1239 }
1240
1241 if (text != string.Empty)
1242 {
1243 if (text2 != string.Empty && playerName != string.Empty)
1244 SCR_PopUpNotification.GetInstance().PopupMsg(text, duration, text2: text2, text2param1: playerName, prio: SCR_ECampaignPopupPriority.MHQ);
1245 else
1246 SCR_PopUpNotification.GetInstance().PopupMsg(text, duration);
1247 }
1248 }
1249
1250 //------------------------------------------------------------------------------------------------
1266 void PlayRadioMsg(SCR_ERadioMsg msg, int factionId, int baseCallsign, int callerCallsignCompany, int callerCallsignPlatoon, int callerCallsignSquad, int callerCallsignCharacter, int calledCallsignCompany, int calledCallsignPlatoon, int calledCallsignSquad, int calledCallsignCharacter, int param, float seed, float quality)
1267 {
1268 if (m_Campaign.IsTutorial())
1269 return;
1270
1272
1273 if (!pc)
1274 return;
1275
1276 IEntity player = pc.GetMainEntity();
1277
1278 if (!player)
1279 return;
1280
1281 SCR_HQRadioSoundEntity radioSoundEntity = SCR_HQRadioSoundEntity.GetInstance();
1282 if (!radioSoundEntity)
1283 return;
1284
1285 SimpleSoundComponent soundComp = radioSoundEntity.GetSimpleSoundComponent();
1286 if (!soundComp)
1287 return;
1288
1289 int signalBase = soundComp.GetSignalIndex("Base");
1290 int signalCompanyCaller = soundComp.GetSignalIndex("CompanyCaller");
1291 int signalCompanyCalled = soundComp.GetSignalIndex("CompanyCalled");
1292 int signalPlatoonCaller = soundComp.GetSignalIndex("PlatoonCaller");
1293 int signalPlatoonCalled = soundComp.GetSignalIndex("PlatoonCalled");
1294 int signalSquadCaller = soundComp.GetSignalIndex("SquadCaller");
1295 int signalSquadCalled = soundComp.GetSignalIndex("SquadCalled");
1296 int signalSoldierCaller = soundComp.GetSignalIndex("SoldierCaller");
1297 int signalSoldierCalled = soundComp.GetSignalIndex("SoldierCalled");
1298 int signalSeed = soundComp.GetSignalIndex("Seed");
1299 int signalQuality = soundComp.GetSignalIndex("TransmissionQuality");
1300
1301 SCR_CampaignFactionManager fManager = SCR_CampaignFactionManager.Cast(GetGame().GetFactionManager());
1302 SCR_CampaignFaction faction = SCR_CampaignFaction.Cast(fManager.GetFactionByIndex(factionId));
1303 SCR_CampaignMilitaryBaseComponent base = m_Campaign.GetBaseManager().FindBaseByCallsign(baseCallsign);
1304
1305 if (base)
1306 {
1307 SCR_MilitaryBaseCallsign callsignInfo;
1308
1309 if (faction == m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.BLUFOR))
1310 callsignInfo = faction.GetBaseCallsignByIndex(base.GetCallsign());
1311 else
1312 callsignInfo = faction.GetBaseCallsignByIndex(base.GetCallsign(), m_Campaign.GetCallsignOffset());
1313
1314 if (callsignInfo)
1315 soundComp.SetSignalValue(signalBase, callsignInfo.GetSignalIndex());
1316 }
1317
1318 if (callerCallsignCompany != SCR_CampaignMilitaryBaseComponent.INVALID_PLAYER_INDEX)
1319 {
1320 soundComp.SetSignalValue(signalCompanyCaller, callerCallsignCompany);
1321 soundComp.SetSignalValue(signalPlatoonCaller, callerCallsignPlatoon);
1322 soundComp.SetSignalValue(signalSquadCaller, callerCallsignSquad);
1323 soundComp.SetSignalValue(signalSoldierCaller, callerCallsignCharacter);
1324 }
1325
1326 if (calledCallsignCompany != SCR_CampaignMilitaryBaseComponent.INVALID_PLAYER_INDEX)
1327 {
1328 soundComp.SetSignalValue(signalCompanyCalled, calledCallsignCompany);
1329 soundComp.SetSignalValue(signalPlatoonCalled, calledCallsignPlatoon);
1330 soundComp.SetSignalValue(signalSquadCalled, calledCallsignSquad);
1331 soundComp.SetSignalValue(signalSoldierCalled, calledCallsignCharacter);
1332 }
1333
1334 soundComp.SetSignalValue(signalSeed, seed);
1335 soundComp.SetSignalValue(signalQuality, quality);
1336
1337 string msgName;
1338 LocalizedString text;
1339 LocalizedString text2;
1340 string param1;
1341 string text2param1;
1342 string text2param2;
1345 string sound;
1346 bool mustSetFactionKey = true;
1347 bool mustSetFactionIdentityVoice = false;
1348
1349 switch (msg)
1350 {
1351 case SCR_ERadioMsg.SEIZED_MAIN:
1352 {
1353 msgName = SCR_SoundEvent.SOUND_HQ_MOB;
1354 break;
1355 }
1356
1357 case SCR_ERadioMsg.SEIZED_MAJOR:
1358 {
1359 msgName = SCR_SoundEvent.SOUND_HQ_FOB;
1360 break;
1361 }
1362
1363 case SCR_ERadioMsg.SEIZED_SMALL:
1364 {
1365 msgName = SCR_SoundEvent.SOUND_HQ_COP;
1366 break;
1367 }
1368
1369 case SCR_ERadioMsg.DEMOTION_RENEGADE:
1370 {
1371 mustSetFactionKey = false;
1372 mustSetFactionIdentityVoice = true;
1373 msgName = SCR_SoundEvent.SOUND_HQC_M_RENEGADE_COMMANDER;
1374 text = "#AR-Campaign_Demotion-UC";
1375 text2 = "#AR-Rank_Renegade";
1376 break;
1377 }
1378
1379 case SCR_ERadioMsg.DEMOTION:
1380 {
1381 mustSetFactionKey = false;
1382 mustSetFactionIdentityVoice = true;
1383 msgName = SCR_SoundEvent.SOUND_HQC_M_DEMOTE_COMMANDER;
1384 text = "#AR-Campaign_Demotion-UC";
1385 SCR_CampaignFaction campaignFaction = SCR_CampaignFaction.Cast(SCR_FactionManager.SGetLocalPlayerFaction());
1386
1387 if (campaignFaction)
1388 text2 = campaignFaction.GetRanks().GetRankNameUpperCase(param);
1389
1390 break;
1391 }
1392
1393 case SCR_ERadioMsg.PROMOTION_PRIVATE:
1394 {
1395 mustSetFactionKey = false;
1396 mustSetFactionIdentityVoice = true;
1397 msgName = SCR_SoundEvent.SOUND_HQC_M_PPRIVATE_COMMANDER;
1398 text = "#AR-Campaign_Promotion-UC";
1399 text2 = "#AR-Rank_WestPrivate";
1400 break;
1401 }
1402
1403 case SCR_ERadioMsg.PROMOTION_CORPORAL:
1404 {
1405 mustSetFactionKey = false;
1406 mustSetFactionIdentityVoice = true;
1407 msgName = SCR_SoundEvent.SOUND_HQC_M_PCORPORAL_COMMANDER;
1408 text = "#AR-Campaign_Promotion-UC";
1409 text2 = "#AR-Rank_WestCorporal";
1410 break;
1411 }
1412
1413 case SCR_ERadioMsg.PROMOTION_SERGEANT:
1414 {
1415 mustSetFactionKey = false;
1416 mustSetFactionIdentityVoice = true;
1417 msgName = SCR_SoundEvent.SOUND_HQC_M_PSERGEANT_COMMANDER;
1418 text = "#AR-Campaign_Promotion-UC";
1419 text2 = "#AR-Rank_WestSergeant";
1420 break;
1421 }
1422
1423 case SCR_ERadioMsg.PROMOTION_LIEUTENANT:
1424 {
1425 mustSetFactionKey = false;
1426 mustSetFactionIdentityVoice = true;
1427 msgName = SCR_SoundEvent.SOUND_HQC_M_PLIEUTENANT_COMMANDER;
1428 text = "#AR-Campaign_Promotion-UC";
1429 text2 = "#AR-Rank_WestLieutenant";
1430 break;
1431 }
1432
1433 case SCR_ERadioMsg.PROMOTION_CAPTAIN:
1434 {
1435 mustSetFactionKey = false;
1436 mustSetFactionIdentityVoice = true;
1437 msgName = SCR_SoundEvent.SOUND_HQC_M_PCAPTAIN_COMMANDER;
1438 text = "#AR-Campaign_Promotion-UC";
1439 text2 = "#AR-Rank_WestCaptain";
1440 break;
1441 }
1442
1443 case SCR_ERadioMsg.PROMOTION_MAJOR:
1444 {
1445 mustSetFactionKey = false;
1446 mustSetFactionIdentityVoice = true;
1447 msgName = SCR_SoundEvent.SOUND_HQC_M_PMAJOR_COMMANDER;
1448 text = "#AR-Campaign_Promotion-UC";
1449 text2 = "#AR-Rank_WestMajor";
1450 break;
1451 }
1452
1453 case SCR_ERadioMsg.VICTORY:
1454 {
1455 SCR_CampaignFaction f = SCR_CampaignFaction.Cast(fManager.GetFactionByIndex(param));
1456
1457 if (!f || f != SCR_FactionManager.SGetLocalPlayerFaction())
1458 return;
1459
1460 msgName = SCR_SoundEvent.SOUND_HQC_M_VICTORY_COMMANDER;
1461 mustSetFactionKey = false;
1462 mustSetFactionIdentityVoice = true;
1463 break;
1464 }
1465
1466 case SCR_ERadioMsg.WINNING:
1467 {
1468 msgName = SCR_SoundEvent.SOUND_HQC_M_WINNING_COMMANDER;
1469 mustSetFactionKey = false;
1470 mustSetFactionIdentityVoice = true;
1471 break;
1472 }
1473
1474 case SCR_ERadioMsg.LOSING:
1475 {
1476 msgName = SCR_SoundEvent.SOUND_HQC_M_LOSING_COMMANDER;
1477 mustSetFactionKey = false;
1478 mustSetFactionIdentityVoice = true;
1479 break;
1480 }
1481
1482 case SCR_ERadioMsg.DEFEAT:
1483 {
1484 SCR_CampaignFaction f = SCR_CampaignFaction.Cast(fManager.GetFactionByIndex(param));
1485
1486 if (!f || f == SCR_FactionManager.SGetLocalPlayerFaction())
1487 return;
1488
1489 msgName = SCR_SoundEvent.SOUND_HQC_M_DEFEAT_COMMANDER;
1490 mustSetFactionKey = false;
1491 mustSetFactionIdentityVoice = true;
1492 break;
1493 }
1494
1495 case SCR_ERadioMsg.RELAY:
1496 {
1497 msgName = SCR_SoundEvent.SOUND_SL_RRD;
1498 break;
1499 }
1500
1501 case SCR_ERadioMsg.REQUEST_EVAC:
1502 {
1503 msgName = SCR_SoundEvent.SOUND_SL_ERT;
1504 break;
1505 }
1506
1507 case SCR_ERadioMsg.REQUEST_FUEL:
1508 {
1509 msgName = SCR_SoundEvent.SOUND_SL_RRT;
1510 break;
1511 }
1512
1513 case SCR_ERadioMsg.SUPPLIES:
1514 {
1515 msgName = SCR_SoundEvent.SOUND_SL_SDD;
1516 break;
1517 }
1518
1519 case SCR_ERadioMsg.REQUEST_REINFORCEMENTS:
1520 {
1521 msgName = SCR_SoundEvent.SOUND_SL_REI;
1522 break;
1523 }
1524
1525 case SCR_ERadioMsg.REQUEST_TRANSPORT:
1526 {
1527 msgName = SCR_SoundEvent.SOUND_SL_TRT;
1528 break;
1529 }
1530
1531 case SCR_ERadioMsg.CONFIRM:
1532 {
1533 msgName = SCR_SoundEvent.SOUND_SL_CSR;
1534 break;
1535 }
1536
1537 case SCR_ERadioMsg.TASK_ASSIGN_SEIZE:
1538 {
1539 msgName = SCR_SoundEvent.SOUND_SL_SRT;
1540 break;
1541 }
1542
1543 case SCR_ERadioMsg.TASK_UNASSIGN_REFUEL:
1544 {
1545 msgName = SCR_SoundEvent.SOUND_HQ_RRU;
1546 break;
1547 }
1548
1549 case SCR_ERadioMsg.TASK_UNASSIGN_TRANSPORT:
1550 {
1551 msgName = SCR_SoundEvent.SOUND_HQ_TRU;
1552 break;
1553 }
1554
1555 case SCR_ERadioMsg.TASK_UNASSIGN_EVAC:
1556 {
1557 msgName = SCR_SoundEvent.SOUND_HQ_ETU;
1558 break;
1559 }
1560
1561 case SCR_ERadioMsg.TASK_CANCEL_REQUEST:
1562 {
1563 msgName = SCR_SoundEvent.SOUND_HQ_RCR;
1564 break;
1565 }
1566
1567 case SCR_ERadioMsg.TASK_ASSIST:
1568 {
1569 msgName = SCR_SoundEvent.SOUND_SL_CHR;
1570 break;
1571 }
1572
1573 case SCR_ERadioMsg.BASE_LOST:
1574 {
1575 msgName = SCR_SoundEvent.SOUND_HQ_BAL;
1576 break;
1577 }
1578
1579 case SCR_ERadioMsg.RELAY_LOST:
1580 {
1581 msgName = SCR_SoundEvent.SOUND_HQ_RRL;
1582 break;
1583 }
1584
1585 case SCR_ERadioMsg.BASE_UNDER_ATTACK:
1586 {
1587 if (!base)
1588 return;
1589
1590 if (base.GetType() == SCR_ECampaignBaseType.BASE)
1591 {
1592 msgName = SCR_SoundEvent.SOUND_HQC_M_BASEUNDERATTACK_COMMANDER;
1593 mustSetFactionKey = false;
1594 mustSetFactionIdentityVoice = true;
1595 }
1596
1597 text = "#AR-Campaign_BaseUnderAttack-UC";
1598
1599 if (base.GetType() == SCR_ECampaignBaseType.RELAY)
1600 text2 = "%1";
1601 else
1602 text2 = "%1 (%2)";
1603
1604 text2param1 = base.GetBaseName();
1605 text2param2 = base.GetCallsignDisplayName();
1606
1607 if (m_BaseWithPlayer == base)
1608 sound = SCR_SoundEvent.SOUND_SIREN;
1609
1610 prio = SCR_ECampaignPopupPriority.BASE_UNDER_ATTACK;
1611 duration = 11;
1612 break;
1613 }
1614
1615 case SCR_ERadioMsg.BUILT_ARMORY:
1616 {
1617 msgName = SCR_SoundEvent.SOUND_HQ_BAA;
1618 break;
1619 }
1620
1621 case SCR_ERadioMsg.BUILT_FUEL:
1622 {
1623 msgName = SCR_SoundEvent.SOUND_HQ_BFA;
1624 break;
1625 }
1626
1627 case SCR_ERadioMsg.BUILT_REPAIR:
1628 {
1629 msgName = SCR_SoundEvent.SOUND_HQ_BRA;
1630 break;
1631 }
1632
1633 case SCR_ERadioMsg.BUILT_SUPPLY:
1634 {
1635 msgName = SCR_SoundEvent.SOUND_HQ_SCB;
1636 break;
1637 }
1638
1639 case SCR_ERadioMsg.BUILT_VEHICLES_LIGHT:
1640 {
1641 msgName = SCR_SoundEvent.SOUND_HQ_LCB;
1642 break;
1643 }
1644
1645 case SCR_ERadioMsg.BUILT_VEHICLES_HEAVY:
1646 {
1647 msgName = SCR_SoundEvent.SOUND_HQ_VCB;
1648 break;
1649 }
1650
1651 case SCR_ERadioMsg.BUILT_BARRACKS:
1652 {
1653 msgName = SCR_SoundEvent.SOUND_HQ_BCB;
1654 break;
1655 }
1656
1657 case SCR_ERadioMsg.BUILT_ANTENNA:
1658 {
1659 msgName = SCR_SoundEvent.SOUND_HQ_ACB;
1660 break;
1661 }
1662
1663 case SCR_ERadioMsg.BUILT_FIELD_HOSPITAL:
1664 {
1665 msgName = SCR_SoundEvent.SOUND_HQ_HCB;
1666 break;
1667 }
1668
1669 case SCR_ERadioMsg.BUILT_HELIPAD:
1670 {
1671 msgName = SCR_SoundEvent.SOUND_HQ_BHA;
1672 break;
1673 }
1674
1675 case SCR_ERadioMsg.DESTROYED_ARMORY:
1676 {
1677 if (!base)
1678 return;
1679
1680 msgName = SCR_SoundEvent.SOUND_HQ_BAD;
1681 text = "#AR-Campaign_Building_Destroyed-UC";
1682 text2 = base.GetBaseName();
1683 param1 = "#AR-Campaign_Building_Armory-UC";
1684 duration = 5;
1685 break;
1686 }
1687
1688 case SCR_ERadioMsg.DESTROYED_FUEL:
1689 {
1690 if (!base)
1691 return;
1692
1693 msgName = SCR_SoundEvent.SOUND_HQ_BFD;
1694 text = "#AR-Campaign_Building_Destroyed-UC";
1695 text2 = base.GetBaseName();
1696 param1 = "#AR-Campaign_Building_FuelDepot-UC";
1697 duration = 5;
1698 break;
1699 }
1700
1701 case SCR_ERadioMsg.DESTROYED_REPAIR:
1702 {
1703 if (!base)
1704 return;
1705
1706 msgName = SCR_SoundEvent.SOUND_HQ_BRD;
1707 text = "#AR-Campaign_Building_Destroyed-UC";
1708 text2 = base.GetBaseName();
1709 param1 = "#AR-Campaign_Building_RepairDepot-UC";
1710 duration = 5;
1711 break;
1712 }
1713
1714 case SCR_ERadioMsg.REPAIRED_ARMORY:
1715 {
1716 if (!base)
1717 return;
1718
1719 msgName = SCR_SoundEvent.SOUND_HQ_BAR;
1720 text = "#AR-Campaign_Building_Available-UC";
1721 text2 = base.GetBaseName();
1722 param1 = "#AR-Campaign_Building_Armory-UC";
1723 duration = 5;
1724 break;
1725 }
1726
1727 case SCR_ERadioMsg.REPAIRED_FUEL:
1728 {
1729 if (!base)
1730 return;
1731
1732 msgName = SCR_SoundEvent.SOUND_HQ_BFR;
1733 text = "#AR-Campaign_Building_Available-UC";
1734 text2 = base.GetBaseName();
1735 param1 = "#AR-Campaign_Building_FuelDepot-UC";
1736 duration = 5;
1737 break;
1738 }
1739
1740 case SCR_ERadioMsg.REPAIRED_REPAIR:
1741 {
1742 if (!base)
1743 return;
1744
1745 msgName = SCR_SoundEvent.SOUND_HQ_BRR;
1746 text = "#AR-Campaign_Building_Available-UC";
1747 text2 = base.GetBaseName();
1748 param1 = "#AR-Campaign_Building_RepairDepot-UC";
1749 duration = 5;
1750 break;
1751 }
1752
1753 case SCR_ERadioMsg.COMMANDER_ARRIVAL:
1754 {
1755 msgName = SCR_SoundEvent.SOUND_HQC_ARRIVAL_HQCBATTALION;
1756 mustSetFactionKey = false;
1757 mustSetFactionIdentityVoice = true;
1758 break;
1759 }
1760
1761 case SCR_ERadioMsg.COMMANDER_RESIGNATION:
1762 {
1763 msgName = SCR_SoundEvent.SOUND_HQC_RESIGNATION_HQCBATTALION;
1764 mustSetFactionKey = false;
1765 mustSetFactionIdentityVoice = true;
1766 break;
1767 }
1768
1769 case SCR_ERadioMsg.COMMANDER_DISRUPTION:
1770 {
1771 msgName = SCR_SoundEvent.SOUND_HQC_DISRUPTION_HQCBATTALION;
1772 mustSetFactionKey = false;
1773 mustSetFactionIdentityVoice = true;
1774 break;
1775 }
1776 }
1777
1778 bool isFriendly = faction == fManager.GetPlayerFaction(pc.GetPlayerId());
1779
1780 if (!msgName.IsEmpty())
1781 {
1782 if (mustSetFactionKey)
1783 msgName = msgName + "_" + faction.GetFactionKey();
1784
1785 if (mustSetFactionIdentityVoice)
1786 {
1787 int signalIdentityVoice = soundComp.GetSignalIndex("IdentityVoice");
1788 soundComp.SetSignalValue(signalIdentityVoice, faction.GetIndentityVoiceSignal());
1789 }
1790
1791 BaseContainer settings = GetGame().GetGameUserSettings().GetModule("SCR_AudioSettings");
1792 bool announcerEnabled = true; //enabled so everything is in the default state if we dont find settings
1793 if (settings)
1794 {
1795 settings.Get("m_bHQAnnouncer", announcerEnabled);
1796 }
1797
1798 if (announcerEnabled)
1799 radioSoundEntity.PlayRadioSound(msgName);
1800 }
1801
1802 if (isFriendly && (!text.IsEmpty() || !text2.IsEmpty()))
1803 SCR_PopUpNotification.GetInstance().PopupMsg(text, duration, text2: text2, prio: prio, param1: param1, sound: sound, text2param1: text2param1, text2param2: text2param2);
1804 }
1805
1806 //------------------------------------------------------------------------------------------------
1807 protected void OnXPChanged(int totalXP, SCR_EXPRewards rewardID, int XP, bool volunteer, bool profileUsed, int skillLevel)
1808 {
1809 if (rewardID == SCR_EXPRewards.ENEMY_KILL || rewardID == SCR_EXPRewards.ENEMY_KILL_VEH)
1810 {
1811 GetGame().GetCallqueue().CallLater(ShowHint, 30000 + Math.RandomIntInclusive(0, 30000), false, EHint.CONFLICT_ELIMINATING_ENEMIES, false, false);
1812 }
1813
1814 if (XP > 0)
1815 {
1816 if (rewardID != SCR_EXPRewards.ENEMY_KILL && rewardID != SCR_EXPRewards.ENEMY_KILL_VEH)
1817 ShowHint(EHint.CONFLICT_PROMOTIONS);
1818
1819 if (rewardID == SCR_EXPRewards.VETERANCY)
1820 ShowHint(EHint.CONFLICT_VETERANCY);
1821 }
1822
1823 PrintFormat("Local player XP change: %1, event: %2, current XP: %3", XP, SCR_Enum.GetEnumName(SCR_EXPRewards, rewardID), totalXP, level: LogLevel.VERBOSE);
1824 }
1825
1826 //------------------------------------------------------------------------------------------------
1827 protected void OnPlayerJoinedGroup(SCR_AIGroup group, int playerID)
1828 {
1829 if (playerID != SCR_PlayerController.GetLocalPlayerId())
1830 return;
1831
1832 switch (group.GetGroupRole())
1833 {
1834 case SCR_EGroupRole.MORTAR:
1835 case SCR_EGroupRole.ANTITANK:
1836 case SCR_EGroupRole.MACHINEGUN:
1837 case SCR_EGroupRole.ENGINEER:
1838 case SCR_EGroupRole.MEDIC:
1839 case SCR_EGroupRole.RECON:
1840 ShowHint(EHint.CONFLICT_GROUPS_SUPPORT);
1841 break;
1842
1843 case SCR_EGroupRole.TRANSPORT:
1844 case SCR_EGroupRole.MECHANIZED:
1845 ShowHint(EHint.CONFLICT_GROUPS_LOGISTIC);
1846 break;
1847
1848 default:
1849 return;
1850 }
1851 }
1852
1853 //------------------------------------------------------------------------------------------------
1854 protected void OnGroupMenuShow()
1855 {
1856 ShowHint(EHint.CONFLICT_GROUPS_INTRO);
1857
1859 }
1860
1861 //------------------------------------------------------------------------------------------------
1863 {
1864 if (!task)
1865 return;
1866
1867 if (task.IsInherited(SCR_PickupRequestedTaskEntity) ||
1868 task.IsInherited(SCR_ReinforceRequestedTaskEntity) ||
1869 task.IsInherited(SCR_RearmRequestedTaskEntity) ||
1870 task.IsInherited(SCR_RepairRequestedTaskEntity) ||
1871 task.IsInherited(SCR_FireSupportRequestedTaskEntity) ||
1872 task.IsInherited(SCR_HoldCampaignMilitaryBaseTaskEntity) ||
1873 task.IsInherited(SCR_ResupplyCampaignMilitaryBaseTaskEntity))
1874 {
1875 ShowHint(EHint.CONFLICT_SUPPORT_REQUESTS_BASICS);
1876 return;
1877 }
1878
1879 if (task.IsInherited(SCR_AttackTaskEntity) ||
1880 task.IsInherited(SCR_SeizeCampaignMilitaryBaseTaskEntity) ||
1881 task.IsInherited(SCR_HoldCampaignMilitaryBaseTaskEntity) ||
1882 task.IsInherited(SCR_ReconTaskEntity) ||
1883 task.IsInherited(SCR_DismantleCampaignMilitaryBaseTaskEntity))
1884 {
1885 SCR_GroupsManagerComponent groupManager = SCR_GroupsManagerComponent.GetInstance();
1886 if (!groupManager)
1887 return;
1888
1889 SCR_AIGroup playerGroup = groupManager.GetPlayerGroup(SCR_PlayerController.GetLocalPlayerId());
1890 if (!playerGroup)
1891 return;
1892
1893 SCR_Faction playerFaction = SCR_Faction.Cast(playerGroup.GetFaction());
1894 if (!playerFaction)
1895 return;
1896
1898 ShowHint(EHint.CONFLICT_OBJECTIVES_SQUAD_LEADER);
1899 else
1900 ShowHint(EHint.CONFLICT_OBJECTIVES_BASICS);
1901
1902 return;
1903 }
1904 }
1905
1906 //------------------------------------------------------------------------------------------------
1910 protected void OnVehicleEnter(ChimeraCharacter playerCharacter, IEntity compartmentEntit)
1911 {
1912 if (playerCharacter != SCR_PlayerController.GetLocalControlledEntity())
1913 return;
1914
1915 SCR_GroupsManagerComponent groupManager = SCR_GroupsManagerComponent.GetInstance();
1916 if (!groupManager)
1917 return;
1918
1919 SCR_AIGroup playerGroup = groupManager.GetPlayerGroup(SCR_PlayerController.GetLocalPlayerId());
1920 if (!playerGroup)
1921 return;
1922
1923 if (SCR_PlayerController.GetLocalPlayerId() == playerGroup.GetLeaderID())
1924 {
1925 switch (playerGroup.GetGroupRole())
1926 {
1927 case SCR_EGroupRole.TRANSPORT:
1928 case SCR_EGroupRole.HELI_TRANSPORT:
1929 case SCR_EGroupRole.ENGINEER:
1930 ShowHint(EHint.CONFLICT_SQUAD_LEADER_LOGISTIC_FOB);
1931 break;
1932 }
1933 }
1934 else
1935 {
1936 GetGame().GetCallqueue().CallLater(ShowHint, m_iVehicleHintDelay, false, EHint.GAMEPLAY_VEHICLE_INVENTORY, false, false);
1937 }
1938 }
1939
1940 //------------------------------------------------------------------------------------------------
1943 {
1944 GetGame().GetCallqueue().CallLater(RegisterVehicleEnter, 100, true);
1945 }
1946
1947 //------------------------------------------------------------------------------------------------
1948 protected void RegisterVehicleEnter()
1949 {
1951 if (!player)
1952 return;
1953
1955 if (!accessComp)
1956 {
1957 GetGame().GetCallqueue().Remove(RegisterVehicleEnter);
1958 return;
1959 }
1960
1961 accessComp.GetOnPlayerCompartmentEnter().Insert(OnVehicleEnter);
1962 GetGame().GetCallqueue().Remove(RegisterVehicleEnter);
1963 }
1964
1965 //------------------------------------------------------------------------------------------------
1966 protected void UnregisterVehicleEnter()
1967 {
1969 if (!player)
1970 return;
1971
1973 if (!accessComp)
1974 return;
1975
1976 accessComp.GetOnPlayerCompartmentEnter().Remove(OnVehicleEnter);
1977 }
1978
1979 //------------------------------------------------------------------------------------------------
1981 {
1982 if (newState != SCR_ETaskState.COMPLETED)
1983 return;
1984
1985 array<int> assigneeIDs = task.GetTaskAssigneePlayerIDs();
1986 int myPlayerId = SCR_PlayerController.GetLocalPlayerId();
1987 if (assigneeIDs.Contains(myPlayerId))
1988 {
1989 ShowHint(EHint.CONFLICT_OBJECTIVES_ADVANCED);
1990 }
1991 }
1992
1993 //------------------------------------------------------------------------------------------------
1994 protected void OnRadialMenuOpen()
1995 {
1996 SCR_GroupsManagerComponent groupManager = SCR_GroupsManagerComponent.GetInstance();
1997 if (!groupManager)
1998 return;
1999
2000 SCR_AIGroup playerGroup = groupManager.GetPlayerGroup(SCR_PlayerController.GetLocalPlayerId());
2001 if (!playerGroup)
2002 return;
2003
2004 if (SCR_PlayerController.GetLocalPlayerId() == playerGroup.GetLeaderID())
2005 {
2006 ShowHint(EHint.CONFLICT_SUPPORT_REQUESTS_SQUAD_LEADER);
2007 }
2008 }
2009
2010 //------------------------------------------------------------------------------------------------
2011 protected void OnJournalOpened(bool newVisibility)
2012 {
2013 SCR_GroupsManagerComponent groupManager = SCR_GroupsManagerComponent.GetInstance();
2014 if (!groupManager)
2015 return;
2016
2017 SCR_AIGroup playerGroup = groupManager.GetPlayerGroup(SCR_PlayerController.GetLocalPlayerId());
2018 if (!playerGroup)
2019 return;
2020
2021 if (SCR_PlayerController.GetLocalPlayerId() == playerGroup.GetLeaderID())
2022 {
2023 ShowHint(EHint.CONFLICT_SQUAD_LEADER_ADVANCED);
2024 }
2025
2026 ShowHint(EHint.CONFLICT_TASK_RELEVANCE);
2027 }
2028
2029 //------------------------------------------------------------------------------------------------
2030 protected void NightHint()
2031 {
2032 ChimeraWorld world = GetGame().GetWorld();
2033 if (!world)
2034 return;
2035
2036 TimeAndWeatherManagerEntity timeManager = world.GetTimeAndWeatherManager();
2037 if (!timeManager)
2038 return;
2039
2040 float now = timeManager.GetTimeOfTheDay();
2041
2042 if (timeManager.IsNightHour(now) && !m_bWasNight)
2043 ShowHint(EHint.CONFLICT_NIGHT_PLAY);
2044
2045 m_bWasNight = timeManager.IsNightHour(now);
2046
2047 SCR_HintManagerComponent hintManager = SCR_HintManagerComponent.GetInstance();
2048 if (hintManager && hintManager.WasShown(EHint.CONFLICT_NIGHT_PLAY))
2049 GetGame().GetCallqueue().Remove(NightHint);
2050 }
2051
2052 //------------------------------------------------------------------------------------------------
2053 protected void OnArsenalOpen()
2054 {
2055 ShowHint(EHint.CONFLICT_MSAR);
2056 }
2057
2058 //------------------------------------------------------------------------------------------------
2060 {
2061 if (!slot)
2062 return;
2063
2064 if (slot.IsInherited(SCR_InventorySlotWeaponSlotsUI))
2065 // CallLater (with delay) is part of the intended design: it prevents showing the hint too aggressively
2066 GetGame().GetCallqueue().CallLater(ShowHint, 3000, false, EHint.GAMEPLAY_WEAPON_INSPECTION, false, false);
2067 }
2068
2069 //------------------------------------------------------------------------------------------------
2071 {
2073 if (menu)
2074 {
2075 menu.GetOnItemHover().Insert(OnItemSlotHover);
2076 GetGame().GetCallqueue().Remove(TryRegisterInventoryHover);
2077 }
2078 else
2079 {
2080 GetGame().GetCallqueue().CallLater(TryRegisterInventoryHover, 500, false);
2081 }
2082 }
2083
2084 //------------------------------------------------------------------------------------------------
2085 protected void CheckSquadCohesionHint()
2086 {
2087 SCR_GroupsManagerComponent groupsManager = SCR_GroupsManagerComponent.GetInstance();
2088 SCR_AIGroup group = groupsManager.GetPlayerGroup(m_PlayerController.GetPlayerId());
2089 if (!group)
2090 return;
2091
2092 if (group.GetLeaderID() != m_PlayerController.GetPlayerId())
2093 return;
2094
2095 SCR_AIGroupCohesionComponent cohesionComp = SCR_AIGroupCohesionComponent.Cast(group.FindComponent(SCR_AIGroupCohesionComponent));
2096 if (!cohesionComp)
2097 return;
2098
2099 array<int> playersInCohesion = {};
2100 cohesionComp.GetPlayersInCohesion(playersInCohesion);
2101
2102 int total = group.GetPlayerCount();
2103 if (total < 2)
2104 return;
2105
2106 float ratio = playersInCohesion.Count() / total;
2107 if (ratio >= 0.6)
2108 {
2110 {
2111 ShowHint(EHint.CONFLICT_SQUAD_LEADER_COHESION);
2113 }
2114 }
2115 else
2116 {
2118 }
2119
2120 SCR_HintManagerComponent hintManager = SCR_HintManagerComponent.GetInstance();
2121 if (hintManager && hintManager.WasShown(EHint.CONFLICT_SQUAD_LEADER_COHESION))
2122 {
2123 GetGame().GetCallqueue().Remove(CheckSquadCohesionHint);
2124 return;
2125 }
2126 }
2127
2128 //------------------------------------------------------------------------------------------------
2129 protected void ProcessEvents(bool activate)
2130 {
2131 if (RplSession.Mode() == RplMode.Dedicated)
2132 return;
2133
2134 GetGame().GetCallqueue().Remove(CheckPlayerInsideRadioRange);
2135 GetGame().GetCallqueue().Remove(RefreshCurrentPopupMessage);
2136 GetGame().GetCallqueue().Remove(GroupLeaderHint);
2137 GetGame().GetCallqueue().Remove(LoneDriverHint);
2138 GetGame().GetCallqueue().Remove(NightHint);
2139 GetGame().GetCallqueue().Remove(CheckSquadCohesionHint);
2140
2141 if (activate)
2142 {
2143 GetGame().GetCallqueue().CallLater(CheckPlayerInsideRadioRange, 3000, true);
2144 GetGame().GetCallqueue().CallLater(RefreshCurrentPopupMessage, 500, true);
2145 GetGame().GetCallqueue().CallLater(GroupLeaderHint, FEATURE_HINT_DELAY, true);
2146 GetGame().GetCallqueue().CallLater(LoneDriverHint, FEATURE_HINT_DELAY, true);
2147 GetGame().GetCallqueue().CallLater(NightHint, NIGHT_HINT_DELAY_MS, true);
2148 GetGame().GetCallqueue().CallLater(CheckSquadCohesionHint, COHESION_HINT_DELAY_MS, true);
2149
2150 GetGame().GetInputManager().AddActionListener("TasksOpen", EActionTrigger.DOWN, RegisterTasksShown);
2152 if (taskUIManager)
2153 taskUIManager.GetOnTaskHUDVisible().Insert(ShowVolunteerHint);
2154
2156
2157 if (m_Campaign)
2158 {
2159 m_Campaign.GetOnPlayerKilled().Insert(OnPlayerKilled);
2160 m_Campaign.GetBaseManager().GetOnLocalPlayerEnteredBase().Insert(OnBaseEntered);
2161 m_Campaign.GetBaseManager().GetOnLocalPlayerLeftBase().Insert(OnBaseLeft);
2162 m_Campaign.GetBaseManager().GetOnSignalChanged().Insert(BaseOutOfRangeHint);
2163 m_Campaign.GetOnMatchSituationChanged().Insert(OnMatchSituationChanged);
2164 }
2165
2167
2168 if (comp)
2169 comp.GetOnXPChanged().Insert(OnXPChanged);
2170
2172
2173 if (inventoryComp)
2175
2179 if (SCR_FactionCommanderHandlerComponent.GetInstance())
2180 SCR_FactionCommanderHandlerComponent.GetInstance().GetOnFactionCommanderChanged().Insert(OnFactionCommanderChanged);
2181
2183 SCR_EstablishBaseTaskEntity.GetOnPlayerEnteredEstablishingArea().Insert(OnCheckEstablishmentArea);
2184 SCR_Task.GetOnTaskAssigneeAdded().Insert(OnTaskAssigneeAdded);
2188 if (m_TaskManager)
2189 m_TaskManager.GetOnTaskSelected().Insert(OnTaskSelected);
2190
2192
2193 SCR_Task.GetOnTaskStateChanged().Insert(OnTaskStateChanged);
2195 if (taskManager)
2196 taskManager.GetOnTaskHUDVisible().Insert(OnJournalOpened);
2197
2200 }
2201 else
2202 {
2203 GetGame().GetInputManager().RemoveActionListener("TasksOpen", EActionTrigger.DOWN, RegisterTasksShown);
2205 if (taskUIManager)
2206 taskUIManager.GetOnTaskHUDVisible().Remove(ShowVolunteerHint);
2207
2209
2210 if (baseManager)
2211 baseManager.GetOnBaseFactionChanged().Remove(OnBaseFactionChanged);
2212
2213 if (m_Campaign)
2214 {
2215 m_Campaign.GetOnPlayerKilled().Remove(OnPlayerKilled);
2216 m_Campaign.GetOnMatchSituationChanged().Remove(OnMatchSituationChanged);
2217
2218 SCR_CampaignMilitaryBaseManager campaignBaseManager = m_Campaign.GetBaseManager();
2219
2220 if (campaignBaseManager)
2221 {
2222 campaignBaseManager.GetOnLocalPlayerEnteredBase().Remove(OnBaseEntered);
2223 campaignBaseManager.GetOnLocalPlayerLeftBase().Remove(OnBaseLeft);
2224 campaignBaseManager.GetOnSignalChanged().Remove(BaseOutOfRangeHint);
2225 }
2226 }
2227
2229 {
2231
2232 if (comp)
2233 comp.GetOnXPChanged().Remove(OnXPChanged);
2234
2236
2237 if (inventoryComp)
2239 }
2240
2244 if (SCR_FactionCommanderHandlerComponent.GetInstance())
2245 SCR_FactionCommanderHandlerComponent.GetInstance().GetOnFactionCommanderChanged().Remove(OnFactionCommanderChanged);
2246
2248 SCR_EstablishBaseTaskEntity.GetOnPlayerEnteredEstablishingArea().Remove(OnCheckEstablishmentArea);
2249 SCR_Task.GetOnTaskAssigneeAdded().Remove(OnTaskAssigneeAdded);
2253 if (m_TaskManager)
2254 m_TaskManager.GetOnTaskSelected().Remove(OnTaskSelected);
2255
2257
2258 SCR_Task.GetOnTaskStateChanged().Remove(OnTaskStateChanged);
2260 if (taskManager)
2261 taskManager.GetOnTaskHUDVisible().Remove(OnJournalOpened);
2262
2265 if (menu)
2266 menu.GetOnItemHover().Remove(OnItemSlotHover);
2267 }
2268 }
2269
2270 //------------------------------------------------------------------------------------------------
2273 void OnOwnershipChanged(bool changing, bool becameOwner)
2274 {
2275 if (changing)
2276 return;
2277
2278 ProcessEvents(becameOwner);
2279 }
2280
2281 //------------------------------------------------------------------------------------------------
2282 protected void ShowVolunteerHint(bool newVisibility)
2283 {
2284 if (GetGame().GetWorld().GetWorldTime() < FEATURE_HINT_DELAY)
2285 return;
2286
2288 if (taskUIManager)
2289 taskUIManager.GetOnTaskHUDVisible().Remove(ShowVolunteerHint);
2290
2291 ShowHint(EHint.CONFLICT_VOLUNTEERING);
2292 ShowHint(EHint.CONFLICT_PRIMARY_OBJECTIVES);
2293 }
2294
2295 protected void OnHintHide(SCR_HintUIInfo info, bool isSilent)
2296 {
2297 m_fNextAllowedHintTimestamp = GetGame().GetWorld().GetWorldTime();
2298 }
2299
2300 //------------------------------------------------------------------------------------------------
2307 void OnPlayerSuppliesInteraction(EResourcePlayerInteractionType interactionType, PlayerController playerController, SCR_ResourceComponent resourceComponentFrom, SCR_ResourceComponent resourceComponentTo, EResourceType resourceType, float resourceValue)
2308 {
2309 if (interactionType != EResourcePlayerInteractionType.VEHICLE_UNLOAD)
2310 return;
2311
2313
2314 if (comp)
2316
2317 ShowHint(EHint.CONFLICT_BUILDING);
2318 }
2319
2320 //------------------------------------------------------------------------------------------------
2321 override void EOnInit(IEntity owner)
2322 {
2323 if (!m_PlayerController)
2324 return;
2325
2326 m_Campaign = SCR_GameModeCampaign.GetInstance();
2327
2328 m_PlayerController.GetOnOwnershipChangedInvoker().Insert(OnOwnershipChanged);
2329
2330 RplComponent rpl = RplComponent.Cast(m_PlayerController.FindComponent(RplComponent));
2331
2332 if (rpl && rpl.IsOwner())
2333 ProcessEvents(true);
2334 }
2335
2336 //------------------------------------------------------------------------------------------------
2337 override void OnPostInit(IEntity owner)
2338 {
2339 super.OnPostInit(owner);
2340
2341 if (!GetGame().InPlayMode())
2342 return;
2343
2344 SetEventMask(owner, EntityEvent.INIT);
2345
2347
2348 if (RplSession.Mode() == RplMode.Dedicated)
2349 return;
2350
2351 //Parse & register hints list
2352 Resource container = BaseContainerTools.LoadContainer(m_sHintsConfig);
2353 m_HintsConfig = SCR_CampaignHintStorage.Cast(BaseContainerTools.CreateInstanceFromContainer(container.GetResource().ToBaseContainer()));
2354
2355 SCR_HintManagerComponent.GetInstance().GetOnHintHide().Insert(OnHintHide);
2356 }
2357
2358 //------------------------------------------------------------------------------------------------
2359 // destructor
2361 {
2362 SCR_HintManagerComponent hintManager = SCR_HintManagerComponent.GetInstance();
2363 if (hintManager)
2364 {
2365 hintManager.GetOnHintHide().Remove(OnHintHide);
2366 }
2367
2368 ProcessEvents(false);
2369 }
2370}
2371
2387
2388enum SCR_ECampaignSeizingMessagePrio
2389{
2393 SEIZING_ENEMY = 999
2394}
EHint
Definition EHint.c:11
ArmaReforgerScripted GetGame()
Definition game.c:1398
RplMode
Mode of replication.
Definition RplMode.c:9
SCR_GameModeCampaign m_Campaign
void OnMapClose(MapConfiguration config)
void SetMapOpened(bool wasOpened)
void OnBaseFactionChanged(notnull SCR_MilitaryBaseComponent base, Faction faction)
void UnregisterVehicleEnter()
void BaseOutOfRangeHint(SCR_CampaignMilitaryBaseComponent base)
void OnJournalOpened(bool newVisibility)
void ShowHint(EHint hintID, bool showImmediately=false, bool showMultipleTimes=false)
void OnHintHide(SCR_HintUIInfo info, bool isSilent)
void OnPlayerJoinedGroup(SCR_AIGroup group, int playerID)
WorldTimestamp m_fBaseWithPlayerCaptureStart
void RegisterTasksShown()
void RegisterVehicleListener()
Registers a callback for vehicle enter events for the local player.
void OnMapOpen(MapConfiguration config)
void TryRegisterInventoryHover()
bool m_bIsPlayerInRadioRange
void OnXPChanged(int totalXP, SCR_EXPRewards rewardID, int XP, bool volunteer, bool profileUsed, int skillLevel)
void CheckPlayerInsideRadioRange()
bool IsPlayerCapturing()
void OnVehicleEnter(ChimeraCharacter playerCharacter, IEntity compartmentEntit)
void CheckSquadCohesionHint()
void OnEntryPerformed(SCR_SelectionMenuEntry entry)
void SetMapCampaignUI(SCR_MapCampaignUI mapUi)
vector GetPlayerSpawnPos()
Returns players position after spawning.
void OnRadialMenuAvailable()
float m_fNextAllowedHintTimestamp
TimeContainer GetSpawnTime()
ref array< int > m_aHintQueue
void HandlePopUpState(SCR_EPopUpState state, notnull SCR_PopUpNotification popup, SCR_PopupMessage currentMsg)
void OnBaseClickedShowSupplyLimit(bool selected)
void MobileAssemblyFeedback(SCR_EMobileAssemblyStatus msgID, int playerID, int factionID)
WorldTimestamp m_fBaseWithPlayerCaptureEnd
void OnTaskStateChanged(SCR_Task task, SCR_ETaskState newState)
void OnBaseHovered(SCR_CampaignMilitaryBaseComponent base)
void ShowVolunteerHint(bool newVisibility)
bool CanShowPlayerSpawn()
void ~SCR_CampaignFeedbackComponent()
void PlayRadioMsg(SCR_ERadioMsg msg, int factionId, int baseCallsign, int callerCallsignCompany, int callerCallsignPlatoon, int callerCallsignSquad, int callerCallsignCharacter, int calledCallsignCompany, int calledCallsignPlatoon, int calledCallsignSquad, int calledCallsignCharacter, int param, float seed, float quality)
void OnItemSlotHover(SCR_InventorySlotUI slot)
enum SCR_ECampaignPopupPriority CONTESTING
void OnCommanderVolunteer(int playerId)
bool m_bCanShowSpawnPosition
void SetPopup(SCR_PopUpNotification popup, SCR_PopupMessage currentMsg, string title, string subtitle, int priority, bool useProgressBar=false)
void OnTaskAssigneeAdded(SCR_Task task, SCR_TaskExecutor executor, int requesterID)
void OnRespawn()
Hints are displayed with a delay after respawn so player has time to find their bearings.
void ProcessEvents(bool activate)
SCR_EPopUpState GetPopUpState()
void TransportRequestHint()
void RegisterVehicleEnter()
bool IsLocalPlayerAlive()
SCR_ECampaignPopupPriority
Popup message priorities sorted from lowest to highest.
void RefreshCurrentPopupMessage()
void OnMatchSituationChanged()
bool m_bCohesionHintWasShown
void OnBaseEntered(notnull SCR_CampaignMilitaryBaseComponent base)
SCR_CampaignMilitaryBaseComponent GetBaseWithPlayer()
void ProcessHintQueue()
SCR_EPopUpState GetCurrentPopUpState()
void OnSeizingTimerChange(WorldTimestamp start, WorldTimestamp end)
void OnPlayerKilled(notnull SCR_InstigatorContextData instigatorContextData)
void OnBaseLeft(notnull SCR_CampaignMilitaryBaseComponent base)
void SetIsPlayerInRadioRange(bool status)
enum SCR_ECampaignPopupPriority SEIZING_YOU
void OnTaskSelected(SCR_Task task)
void OnPlayerSuppliesInteraction(EResourcePlayerInteractionType interactionType, PlayerController playerController, SCR_ResourceComponent resourceComponentFrom, SCR_ResourceComponent resourceComponentTo, EResourceType resourceType, float resourceValue)
void OnFactionCommanderChanged(SCR_Faction faction, int commanderPlayerId)
void UpdatePlayerSpawnHint(bool show, vector position=vector.Zero)
void OnCheckEstablishmentArea()
bool m_bIsPlayerCapturing
vector position
SCR_EGroupRole
Group roles.
SCR_EPopUpState
State of a popup message so we can easily determine what to display.
void SCR_FactionManager(IEntitySource src, IEntity parent)
SCR_FastTravelComponentClass m_PlayerController
void SCR_GameModeCampaign(IEntitySource src, IEntity parent)
void SCR_GroupsManagerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
AudioHandle m_PlayedRadio
EMapEntityMode
Mode of the map.
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
void SCR_Task(IEntitySource src, IEntity parent)
Definition SCR_Task.c:1938
SCR_ETaskState
Definition SCR_Task.c:3
SCR_TaskManagerUIComponent m_TaskManager
void TimeContainer(int hours=0, int minutes=0, int seconds=0)
proto external int SetEventMask(notnull IEntity owner, int mask)
Definition Math.c:13
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
int GetPlayerCount(bool checkMasterAndSlaves=false)
SCR_EGroupRole GetGroupRole()
array< int > GetPlayerIDs()
static ScriptInvoker GetOnPlayerAdded()
int GetLeaderID()
Faction GetFaction()
static ScriptInvokerBool GetOnBaseSelected()
SCR_ECampaignBaseType GetType()
Returns type of this base.
bool IsHQRadioTrafficPossible(notnull SCR_CampaignFaction faction, SCR_ERadioCoverageStatus direction=SCR_ERadioCoverageStatus.RECEIVE)
OnLocalPlayerLeftBaseInvoker GetOnLocalPlayerLeftBase()
OnSignalChangedInvoker GetOnSignalChanged()
Triggered when a base's radio coverage changes.
OnLocalPlayerEnteredBaseInvoker GetOnLocalPlayerEnteredBase()
OnPlayerEnterCompartment GetOnPlayerCompartmentEnter(bool createNew=true)
static IEntity GetMainParent(IEntity entity, bool self=false)
int GetCommanderId()
static ScriptInvoker GetOnGroupMenuShown()
static ScriptInvokerInventorySlotHover GetOnItemHover()
static SCR_InventoryMenuUI GetInventoryMenu()
static ScriptInvokerVoid GetOnArsenalEnter()
BaseHoveredInvoker GetOnBaseHovered()
void InitMobileAssembly(string factionKey, bool deployed)
void RemoveSpawnPositionHint()
Called to hide Spawn Position hint if player is killed (or his entity disappear for some reason).
static ScriptInvokerBase< MapConfigurationInvoker > GetOnMapClose()
Get on map close invoker.
SCR_MapUIBaseComponent GetMapUIComponent(typename componentType)
bool IsOpen()
Check if the map is opened.
static ScriptInvokerBase< MapConfigurationInvoker > GetOnMapOpen()
Get on map open invoker.
static SCR_MapEntity GetMapInstance()
Get map entity instance.
2D map radial menu UI
ScriptInvokerVoid GetOnMenuInitInvoker()
static SCR_MapRadialUI GetInstance()
SCR_RadialMenuController GetRadialController()
int GetBases(notnull out array< SCR_MilitaryBaseComponent > bases)
OnBaseFactionChangedInvoker GetOnBaseFactionChanged()
static SCR_MilitaryBaseSystem GetInstance()
static int GetLocalPlayerId()
Returns either a valid ID of local player or 0.
static IEntity GetLocalControlledEntity()
Takes care of dynamic and static onscreen popups.
void ChangeProgressBarFinish(WorldTimestamp progressEnd)
void PopupMsg(string text, float duration=DEFAULT_DURATION, string text2="", int prio=-1, string param1="", string param2="", string param3="", string param4="", string text2param1="", string text2param2="", string text2param3="", string text2param4="", string sound="", SCR_EPopupMsgFilter category=SCR_EPopupMsgFilter.ALL, WorldTimestamp progressStart=null, WorldTimestamp progressEnd=null)
static const float DEFAULT_DURATION
static SCR_PopUpNotification GetInstance()
SCR_PopupMessage GetCurrentMsg()
ScriptInvokerSelectionMenuEntry GetOnEntryPerformed()
static SCR_TaskManagerUIComponent GetInstance()
static float GetHeightAboveTerrain(vector pos, BaseWorld world=null, bool noUnderwater=false, TraceParam trace=null)
void EOnInit(IEntity owner)
proto external int GetSignalIndex(string name)
proto external void SetSignalValue(int signal, float value)
enum EPhysicsLayerPresets Vehicle
Definition gameLib.c:24
SCR_EditableEntityComponent GetControlledEntity()
ECharacterLifeState
void OnConsciousnessChanged(bool conscious)
Will be called when the consciousness of the character changes.
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
proto void PrintFormat(string fmt, void param1=NULL, void param2=NULL, void param3=NULL, void param4=NULL, void param5=NULL, void param6=NULL, void param7=NULL, void param8=NULL, void param9=NULL, LogLevel level=LogLevel.NORMAL)
@ NONE
When Shape is created and not initialized yet.
Definition ShapeType.c:15
@ DEFAULT
Use currently set main RT format (based on game options).
SCR_FieldOfViewSettings Attribute
EntityEvent
Various entity events.
Definition EntityEvent.c:14
proto external PlayerController GetPlayerController()
EActionTrigger
void OnOwnershipChanged(bool changing, bool becameOwner)
Tuple param1