Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_VotingManagerComponent.c
Go to the documentation of this file.
3typedef ScriptInvokerBase<ScriptInvoker_VotingManagerStartMethod> ScriptInvoker_VotingManagerStart;
4
7typedef ScriptInvokerBase<ScriptInvoker_VotingManagerEndMethod> ScriptInvoker_VotingManagerEnd;
8
11typedef ScriptInvokerBase<ScriptInvoker_VotingManagerPlayerMethod> ScriptInvoker_VotingManagerPlayer;
12
15typedef ScriptInvokerBase<ScriptInvoker_VotingManagerVoteCountChangedMethod> ScriptInvoker_VotingManagerVoteCountChanged;
16
17[ComponentEditorProps(category: "GameScripted/Voting", description: "")]
21
23{
24 [Attribute(desc: "Voting Templates, please use configs and the VotingManagerComponent prefab for default gamemode voting templates")]
25 protected ref array<ref SCR_VotingBase> m_aVotingTemplates;
26
27 [Attribute("1")]
28 protected float m_fUpdateStep;
29
30 protected int m_iHostPlayerID = -1;
31 protected float m_fUpdateLength;
32 protected ref array<ref SCR_VotingBase> m_aVotingInstances = {};
33 protected ref set<SCR_VotingBase> m_aAbstainedVotingInstances = new set<SCR_VotingBase>(); //~ Player locally abstained from voting
34 protected ref array<ref Tuple2<int, int>> m_LocalVoteRecords = {};
35
44
45 static const LocalizedString VOTE_TIMEOUT_FORMAT = "#AR-Voting_TimeOut";
46
48 //--- Public, static, anywhere
49
50 //------------------------------------------------------------------------------------------------
53 static SCR_VotingManagerComponent GetInstance()
54 {
55 if (GetGame().GetGameMode())
57 else
58 return null;
59 }
60
62 //--- Public, server
63
64 //------------------------------------------------------------------------------------------------
71 void Vote(int playerID, EVotingType type, int value)
72 {
73 //--- Prevent voting fraud, non-existent players cannot vote!
74 if (!GetGame().GetPlayerManager().IsPlayerConnected(playerID))
75 {
76 Print(string.Format("Non-existent player %1 is attempting to vote in %2 for %3", playerID, typename.EnumToString(EVotingType, type), value), LogLevel.WARNING);
77 return;
78 }
79
80 //--- Find the voting, or create it if it doesn't exist yet
81 SCR_VotingBase voting = FindVoting(type, value);
82 if (!voting)
83 {
84 if (!StartVoting(type, playerID, value))
85 return;
86
87 voting = FindVoting(type, value);
88 }
89
90 //--- Voting for the same value, ignore
91 if (voting.GetPlayerVote(playerID) == value)
92 return;
93
94 //--- Set the vote
95 voting.SetVote(playerID, value);
96
97 //~ If vote was successfully added send RPC to update vote count for players
98 if (voting.AddPlayerVotedServer(playerID))
100
101 m_OnVote.Invoke(type, value, playerID);
102
103 //--- Check if the vote completed the voting
104 EVotingOutcome outcome = EVotingOutcome.EVALUATE;
105 if (voting.Evaluate(outcome))
106 EndVoting(voting, outcome);
107 }
108
109 //------------------------------------------------------------------------------------------------
115 void RemoveVote(int playerID, EVotingType type, int value)
116 {
117 SCR_VotingBase voting = FindVoting(type, value);
118 if (!voting)
119 return;
120
121 //--- Cancel the vote when no votes are left (i.e., last player canceled theirs) or when player who is target of the vote cancels their vote
122 if (voting.RemoveVote(playerID) || (voting.IsValuePlayerID() && playerID == value))
123 EndVoting(voting, EVotingOutcome.FORCE_FAIL);
124
125 //~ If vote was successfully removed send RPC to update vote count for players
126 if (voting.RemovePlayerVotedServer(playerID))
128 }
129
130 //------------------------------------------------------------------------------------------------
131 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
132 protected void RPC_PlayerVoteCountChanged(EVotingType type, int value, int voteCount)
133 {
134 SCR_VotingBase voting = FindVoting(type, value);
135 if (voting)
136 {
137 voting.SetCurrentVoteCount(voteCount);
138 m_PlayerVoteCountChanged.Invoke(type, value, voteCount);
139 }
140 }
141
142 //------------------------------------------------------------------------------------------------
148 bool StartVoting(EVotingType type, int startingPlayerID, int value = SCR_VotingBase.DEFAULT_VALUE)
149 {
150 if (FindVoting(type, value))
151 return false;
152
153 StartVotingBroadcast(type, value, startingPlayerID);
154 Rpc(StartVotingBroadcast, type, value, startingPlayerID);
155
156 //-- Find the voting; cannot use returned value, StartVotingBroadcast is replicated and such functions cannot return anything
157 SCR_VotingBase voting = FindVoting(type, value);
158 return voting != null;
159 }
160
161 //------------------------------------------------------------------------------------------------
168 {
169 SCR_VotingBase voting = FindVoting(type, value);
170 if (voting)
171 EndVoting(voting, outcome);
172 }
173
174 //------------------------------------------------------------------------------------------------
181 {
182 SCR_VotingBase voting = FindVoting(type, value);
183 if (voting)
184 return voting.GetPlayerVote(playerID);
185 else
187 }
188
189 //------------------------------------------------------------------------------------------------
197 bool GetVoteCounts(EVotingType type, int value, out int currentVotes, out int votesRequired)
198 {
199 SCR_VotingBase voting = FindVoting(type, value);
200 if (!voting)
201 return false;
202
203 currentVotes = voting.GetCurrentVoteCount();
204 votesRequired = voting.GetVoteCountRequired();
205
206 return votesRequired > 0;
207 }
208
209 //------------------------------------------------------------------------------------------------
215 {
216 SCR_VotingBase voting = FindVoting(type, value);
217 if (!voting)
218 return 0;
219
220 return voting.GetAuthorId();
221 }
222
223 //------------------------------------------------------------------------------------------------
230
231 //------------------------------------------------------------------------------------------------
238
239 //------------------------------------------------------------------------------------------------
246
247 //------------------------------------------------------------------------------------------------
254
255 //------------------------------------------------------------------------------------------------
262
263 //------------------------------------------------------------------------------------------------
270
271 //------------------------------------------------------------------------------------------------
278
279 //------------------------------------------------------------------------------------------------
286
288 //--- Public, anywhere
289
290 //------------------------------------------------------------------------------------------------
300
301 //------------------------------------------------------------------------------------------------
307 {
308 SCR_VotingBase vote = FindVoting(type, value);
309 bool isOngoing = vote != null;
310 if (!vote)
311 vote = FindTemplate(type);
312
313 return vote && (vote.IsAvailable(value, isOngoing) || DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_VOTING_ENABLE_ALL));
314 }
315
316 //------------------------------------------------------------------------------------------------
322 {
323 return FindVoting(type, value) != null;
324 }
325
326 //------------------------------------------------------------------------------------------------
333 {
334 SCR_VotingBase voting = FindVoting(type, playerID);
335 if (voting)
336 return voting.IsValuePlayerID();
337 else
339 }
340
341 //------------------------------------------------------------------------------------------------
346 {
347 SCR_VotingBase vote = FindVoting(type, value);
348 if (!vote || m_aAbstainedVotingInstances.Contains(vote))
349 return;
350
351 m_aAbstainedVotingInstances.Insert(vote);
352
353 //~ Script invoker
354 m_OnAbstainVoteLocal.Invoke(type, value);
355 }
356
357 //------------------------------------------------------------------------------------------------
363 {
364 if (IsLocalVote(type, value))
365 return false;
366
367 SCR_VotingBase vote = FindVoting(type, value);
368 if (vote && m_aAbstainedVotingInstances.Contains(vote))
369 return true;
370
371 return false;
372 }
373
374 //------------------------------------------------------------------------------------------------
379 {
380 SCR_VotingBase vote = FindVoting(type, value);
381 if (vote)
382 return vote.GetRemainingDuration();
383
384 return -1;
385 }
386
387 //------------------------------------------------------------------------------------------------
396 int GetVotingsAboutPlayer(int playerID, out notnull array<EVotingType> outVotingTypes, bool onlyTemplates = false, bool onlyAvailable = false)
397 {
398 array<ref SCR_VotingBase> votings;
399 if (onlyTemplates)
400 votings = m_aVotingTemplates;
401 else
402 votings = m_aVotingInstances;
403
404 outVotingTypes.Clear();
405 foreach (SCR_VotingBase voting: votings)
406 {
407 //if (template.IsAvailable(playerID, IsVoting(template.GetType(), playerID)) || DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_VOTING_ENABLE_ALL))
408 bool isMatchingValue = onlyTemplates || voting.GetValue() == playerID;
409 bool isAvailable = !onlyAvailable || voting.IsAvailable(playerID, IsVoting(voting.GetType(), playerID)) || (onlyTemplates && DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_VOTING_ENABLE_ALL));
410 if (voting.IsValuePlayerID() && isMatchingValue && isAvailable)
411 outVotingTypes.Insert(voting.GetType());
412 }
413 return outVotingTypes.Count();
414 }
415
416 //------------------------------------------------------------------------------------------------
424 int GetAllVotingsAboutPlayer(bool aboutPlayer, out notnull array<EVotingType> outVotingTypes, bool onlyTemplates = false, bool onlyAvailable = false)
425 {
426 array<ref SCR_VotingBase> votings;
427 if (onlyTemplates)
428 votings = m_aVotingTemplates;
429 else
430 votings = m_aVotingInstances;
431
432 outVotingTypes.Clear();
433 foreach (SCR_VotingBase voting: votings)
434 {
435 if (aboutPlayer == voting.IsValuePlayerID() && (!onlyAvailable || voting.IsAvailable(voting.GetValue(), true)))
436 outVotingTypes.Insert(voting.GetType());
437 }
438 return outVotingTypes.Count();
439 }
440
441 //------------------------------------------------------------------------------------------------
449 int GetAllVotingsWithValue(out notnull array<EVotingType> outVotingTypes, array<EVotingType> outValues, bool onlyTemplates = false, bool onlyAvailable = false)
450 {
451 array<ref SCR_VotingBase> votings;
452 if (onlyTemplates)
453 votings = m_aVotingTemplates;
454 else
455 votings = m_aVotingInstances;
456
457 outVotingTypes.Clear();
458 foreach (SCR_VotingBase voting: votings)
459 {
460 if (voting.GetValue() != SCR_VotingBase.DEFAULT_VALUE && (!onlyAvailable || voting.IsAvailable(voting.GetValue(), true)))
461 {
462 outVotingTypes.Insert(voting.GetType());
463 outValues.Insert(voting.GetValue());
464 }
465 }
466 return outVotingTypes.Count();
467 }
468
469 //------------------------------------------------------------------------------------------------
476 int GetAllVotingValues(EVotingType type, out notnull array<int> outValues, bool onlyTemplates = false, bool onlyAvailable = false)
477 {
478 array<ref SCR_VotingBase> votings;
479 if (onlyTemplates)
480 votings = m_aVotingTemplates;
481 else
482 votings = m_aVotingInstances;
483
484 outValues.Clear();
485 foreach (SCR_VotingBase voting: votings)
486 {
487 if (voting.GetType() == type && (!onlyAvailable || voting.IsAvailable(voting.GetValue(), true)))
488 outValues.Insert(voting.GetValue());
489 }
490 return outValues.Count();
491 }
492
493 //------------------------------------------------------------------------------------------------
497 {
498 SCR_VotingBase template = FindTemplate(type);
499 if (!template)
500 return 0;
501
502 if (template.HasInitiatedVotingLocallyOnce())
503 {
504 Print("Trying to get Join Server vote delay but the local player has already voted for the vote type + (" + typename.EnumToString(EVotingType, type) + ") once so this will always returns 0", LogLevel.WARNING);
505 return 0;
506 }
507
508 if (!template.HasCooldown())
509 return 0;
510
511 //~ Get time stamp. -1 means it is not set
512 float joinTimeStamp = template.GetLocalCooldownTimeStamp();
513 if (joinTimeStamp < 0)
514 return 0;
515
516 return Math.Max((template.GetJoinServerVoteCooldown() + joinTimeStamp) - GetTimeStamp(), 0);
517 }
518
519 //------------------------------------------------------------------------------------------------
523 {
524 SCR_VotingBase template = FindTemplate(type);
525 if (!template || !template.HasCooldown())
526 return 0;
527
528 float lastTimeStamp = template.GetLocalCooldownTimeStamp();
529 if (lastTimeStamp <= 0)
530 return 0;
531
532 return Math.Max((template.GetVoteCooldownTime() + lastTimeStamp) - GetTimeStamp(), 0);
533 }
534
535 //------------------------------------------------------------------------------------------------
539 {
540 SCR_VotingBase template = FindTemplate(type);
541 if (!template)
542 return 0;
543
544 //~ Has voted once so take the cooldown
545 if (template.HasInitiatedVotingLocallyOnce())
547 //~ Hasn't voted yet so take the delay
548 else
550 }
551
552 //------------------------------------------------------------------------------------------------
553 //~ Get the current local timestamp
554 protected float GetTimeStamp()
555 {
556 ChimeraWorld world = GetGame().GetWorld();
557 if (!world)
558 return System.GetTickCount() * 0.001;
559
560 return world.GetLocalTimestamp().DiffMilliseconds(null) * 0.001;
561 }
562
563 //------------------------------------------------------------------------------------------------
568 {
569 SCR_VotingBase template = FindTemplate(type);
570 if (template)
571 return template.GetInfo();
572 else
573 return null;
574 }
575
576 //------------------------------------------------------------------------------------------------
581 string GetValueName(EVotingType type, int value)
582 {
583 SCR_VotingBase template = FindTemplate(type);
584 if (template)
585 return template.GetValueName(value);
586 else
587 return value.ToString();
588 }
589
590 //------------------------------------------------------------------------------------------------
595 {
596 array<EVotingType> validActiveVotingTypes = {};
597 array<int> votingValues = {};
598
599 GetAllVotingsWithValue(validActiveVotingTypes, votingValues, false, true);
600
601 //~ If the vote is already active it does not count as player starting vote
602 for (int i = 0, count = validActiveVotingTypes.Count(); i < count; i++)
603 {
604 if (validActiveVotingTypes[i] == type && votingValues[i] == value)
605 return;
606 }
607
608 //~ Check if the vote has any cooldowns.
609 SCR_VotingBase template = FindTemplate(type);
610 if (!template || !template.HasCooldown())
611 return;
612
613 //~ It has cooldowns so set the last time stamp and set voted once
614 template.SetLocalCooldownTimeStamp(GetTimeStamp());
615 template.SetHasInitiatedVotingLocallyOnce();
616 }
617
618 //------------------------------------------------------------------------------------------------
624 void VoteLocal(EVotingType type, int value)
625 {
626 SCR_VotingBase voting = FindVoting(type, value);
627 if (voting)
628 {
629 voting.SetVoteLocal(value);
630 m_OnVoteLocal.Invoke(type, value);
631
632 //~ Vote Cast Notification
633 SCR_VotingBase template = FindTemplate(type);
634 if (template && template.CanSendNotification(value))
635 {
636 SCR_VotingUIInfo uiInfo = template.GetInfo();
637
638 if (uiInfo && uiInfo.GetLocalVoteCastNotification() != ENotification.UNKNOWN)
639 SCR_NotificationsComponent.SendLocal(uiInfo.GetLocalVoteCastNotification(), value);
640 }
641 }
642 else
643 {
644 //--- Voting doesn't exist yet - cache it, it will be restored by StartVotingBroadcast
645 m_LocalVoteRecords.Insert(new Tuple2<int, int>(type, value));
646 }
647 }
648
649 //------------------------------------------------------------------------------------------------
656 {
657 SCR_VotingBase voting = FindVoting(type, value);
658 if (voting)
659 {
660 m_aAbstainedVotingInstances.Insert(voting);
661
662 voting.RemoveVoteLocal();
663 m_OnRemoveVoteLocal.Invoke(type, value);
664
665 //~ Vote Abstained Notification
666 SCR_VotingBase template = FindTemplate(type);
667 if (template && template.CanSendNotification(value))
668 {
669 SCR_VotingUIInfo uiInfo = template.GetInfo();
670
671 if (uiInfo && uiInfo.GetLocalVoteAbstainedNotification() != ENotification.UNKNOWN)
672 SCR_NotificationsComponent.SendLocal(uiInfo.GetLocalVoteAbstainedNotification(), value);
673 }
674 }
675 }
676
677 //------------------------------------------------------------------------------------------------
684 {
685 SCR_VotingBase voting = FindVoting(type, value);
686 if (voting)
687 return voting.GetLocalVote();
688 else
690 }
691
692 //------------------------------------------------------------------------------------------------
702
703 //------------------------------------------------------------------------------------------------
708 {
709 SCR_VotingBase voting = FindVoting(type, value);
710 if (!voting)
711 return false;
712
714 }
715
716 //------------------------------------------------------------------------------------------------
718 {
719 SCR_VotingBase voting = FindVoting(type, value);
720 if (!voting)
721 return false;
722
724 }
725
726 //------------------------------------------------------------------------------------------------
728 void Log()
729 {
730 Print("---------------------------------------------");
731 PrintFormat("Ongoing votings: %1", m_aVotingInstances.Count());
732 foreach (SCR_VotingBase voting: m_aVotingInstances)
733 {
734 voting.Log();
735 }
736 Print("---------------------------------------------");
737 }
738
740 //--- Protected, server
741
742 //------------------------------------------------------------------------------------------------
743 protected void EndVoting(notnull SCR_VotingBase voting, EVotingOutcome outcome = EVotingOutcome.EVALUATE)
744 {
745 EVotingType type = voting.GetType();
746 int value = voting.GetValue();
747 int winner = SCR_VotingBase.DEFAULT_VALUE;
748 bool resultSuccessful = false;
749
750 switch (outcome)
751 {
752 case EVotingOutcome.EVALUATE:
753 winner = voting.GetWinner();
754 break;
755 case EVotingOutcome.FORCE_WIN:
756 winner = value;
757 break;
758 }
759
760 voting.OnVotingEnd(value, winner);
761
762 EndVotingBroadcast(type, value, winner);
763 Rpc(EndVotingBroadcast, type, value, winner);
764
765 if (winner != SCR_VotingBase.DEFAULT_VALUE)
766 resultSuccessful = true;
767
768 // As we are only tracking positive votes, we are gonna filter this to only get results in GROUP LEADER where there's a winner to prevent some errors
769 // This should be a temporal bad fix just to not spoil analytics, but original issue in voting group leader should be fixed
770 if (type == EVotingType.GROUP_LEADER && winner == -1)
771 return;
772
773 string authorIdentityID = SCR_PlayerIdentityUtils.GetPlayerIdentityId(voting.GetAuthorId());
774 string winnerIdentityID = SCR_PlayerIdentityUtils.GetPlayerIdentityId(winner);
775 //SCR_AnalyticsApplication.GetInstance().VoteToKickResult(type, authorIdentityID, winnerIdentityID, resultSuccessful);
776 }
777
778 //------------------------------------------------------------------------------------------------
780 {
781 for (int i, count = m_aVotingInstances.Count(); i < count; i++)
782 {
783 if (m_aVotingInstances[i].IsMatching(type, value))
784 return m_aVotingInstances[i];
785 }
786 return null;
787 }
788
789 //------------------------------------------------------------------------------------------------
791 {
792 for (int i, count = m_aVotingTemplates.Count(); i < count; i++)
793 {
794 if (m_aVotingTemplates[i].GetType() == type)
795 return m_aVotingTemplates[i];
796 }
797 return null;
798 }
799
801 //--- Protected, anywhere
802
803 //------------------------------------------------------------------------------------------------
810 protected SCR_VotingBase CreateVotingInstance(EVotingType type, int startingPlayerID, int value, float remainingDuration = -1, int currentVoteCount = -1)
811 {
812 if (FindVoting(type, value))
813 return null;
814
815 //--- Find voting template
816 SCR_VotingBase template = FindTemplate(type);
817 if (!template)
818 {
819 Debug.Error2("SCR_VotingManagerComponent", string.Format("Cannot initiate voting of type %1, it does not have a template!", typename.EnumToString(EVotingType, type)));
820 return null;
821 }
822
823 //--- Voting about player who is not connected, ignore
824 if (Replication.IsServer() && template.IsValuePlayerID() && value != SCR_VotingBase.DEFAULT_VALUE && !GetGame().GetPlayerManager().IsPlayerConnected(value))
825 {
826 Print(string.Format("Cannot create voting %1 about %2, player with given ID does not exist!", typename.EnumToString(EVotingType, type), value), LogLevel.WARNING);
827 return null;
828 }
829
830 //--- Start new voting
831 SCR_VotingBase voting = SCR_VotingBase.Cast(template.Type().Spawn());
832 voting.InitFromTemplate(template, startingPlayerID, value, remainingDuration);
833
834 if (currentVoteCount > 0)
835 voting.SetCurrentVoteCount(currentVoteCount);
836
837 m_aVotingInstances.Insert(voting);
838
839 m_OnVotingStart.Invoke(type, value);
840 Print(string.Format("Voting %1 started with value %2.", typename.EnumToString(EVotingType, type), voting.GetValueName(value)), LogLevel.VERBOSE);
841
842 //~ Vote start Notification
843 if (template.CanSendNotification(value))
844 {
845 if (template.GetInfo() && template.GetInfo().GetVotingStartNotification() != ENotification.UNKNOWN)
846 {
847 SCR_NotificationsComponent.SendLocal(template.GetInfo().GetVotingStartNotification(), value, startingPlayerID);
848 }
849 }
850
851 //--- First voting, start updating countdown
852 if (m_aVotingInstances.Count() == 1)
853 SetEventMask(GetOwner(), EntityEvent.FRAME);
854
855 return voting;
856 }
857
858 //------------------------------------------------------------------------------------------------
859 protected void DeleteVotingInstance(EVotingType type, int value, int winner)
860 {
861 SCR_VotingBase voting = FindVoting(type, value);
862 if (!voting)
863 return;
864
865 if (m_aAbstainedVotingInstances.Contains(voting))
866 m_aAbstainedVotingInstances.RemoveItem(voting);
867
868 m_aVotingInstances.RemoveItem(voting);
869
870 m_OnVotingEnd.Invoke(type, value, winner);
871 Print(string.Format("Voting %1 ended, the winner is %2.", typename.EnumToString(EVotingType, type), voting.GetValueName(winner)), LogLevel.VERBOSE);
872
873 SCR_VotingBase template = FindTemplate(type);
874
875 //~ Vote End Notification
876 if (template && template.CanSendNotification(value))
877 {
878 SCR_VotingUIInfo uiInfo = template.GetInfo();
879 if (uiInfo)
880 {
881 //~ Vote succeeded notification
883 SCR_NotificationsComponent.SendLocal(uiInfo.GetVotingSucceedNotification(), value);
884 //~ Vote failed notification
885 else if (winner == SCR_VotingBase.DEFAULT_VALUE && uiInfo.GetVotingFailNotification() != ENotification.UNKNOWN)
886 SCR_NotificationsComponent.SendLocal(uiInfo.GetVotingFailNotification(), value);
887 else if (winner == SCR_VotingBase.ALTERNATIVE_VALUE && uiInfo.GetVotingAlternativeNotification() != ENotification.UNKNOWN)
888 SCR_NotificationsComponent.SendLocal(uiInfo.GetVotingAlternativeNotification(), value);
889 }
890 }
891
892 if (m_aVotingInstances.IsEmpty())
893 ClearEventMask(GetOwner(), EntityEvent.FRAME);
894 }
895
896 //------------------------------------------------------------------------------------------------
897 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
898 protected void StartVotingBroadcast(EVotingType type, int value, int startingPlayerID)
899 {
900 SCR_VotingBase voting = CreateVotingInstance(type, startingPlayerID, value);
901
902 //--- Restore local vote from cache
903 foreach (int index, Tuple2<int, int> record: m_LocalVoteRecords)
904 {
905 if (type == record.param1 && value == record.param2)
906 {
907 if (voting)
908 VoteLocal(record.param1, record.param2);
909
911 break;
912 }
913 }
914 }
915
916 //------------------------------------------------------------------------------------------------
917 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
918 protected void EndVotingBroadcast(EVotingType type, int value, int winner)
919 {
920 DeleteVotingInstance(type, value, winner);
921 }
922
924 //--- Overrides
925
926 //------------------------------------------------------------------------------------------------
927 override void OnPlayerConnected(int playerId)
928 {
929 //--- Force instant refresh in EOnFrame
931 }
932
933 //------------------------------------------------------------------------------------------------
934 override void OnPlayerRegistered(int playerId)
935 {
936 if (SCR_PlayerController.GetLocalPlayerId() != playerId)
937 return;
938
939 float timeStamp = GetTimeStamp();
940
941 //~ How long the game has been running
942 float gameRunTime;
944 if (gameMode)
945 gameRunTime = gameMode.GetElapsedTime();
946 else
947 gameRunTime = float.MAX;
948
949 //~ Add player joined timestamps to any voting that has a delay when player joined
950 foreach (SCR_VotingBase template : m_aVotingTemplates)
951 {
952 if (!template)
953 continue;
954
955 //~ If the vote has a join server delay and the server runtime is greater or equal to the Ignore JoinDelay time. Then set a cooldown for the vote
956 if (template.GetJoinServerVoteCooldown() > 0 && gameRunTime >= template.GetServerRuntimeIgnoreJoinServerCooldown())
957 {
958 template.SetLocalCooldownTimeStamp(timeStamp);
959 continue;
960 }
961 }
962 }
963
964 //------------------------------------------------------------------------------------------------
965 override void OnPlayerDisconnected(int playerId, KickCauseCode cause, int timeout)
966 {
967 SCR_VotingBase vote;
968 for (int i = m_aVotingInstances.Count() - 1; i >= 0; i--)
969 {
970 vote = m_aVotingInstances[i];
971 if (!vote)
972 continue;
973
974 vote.RemoveVote(playerId);
975
976 if (vote.ShouldCancelWhenSubjectLeavesTheServer() && vote.RemoveValue(playerId))
977 EndVoting(vote);
978 }
979
980 //--- Force instant refresh in EOnFrame
982 }
983
984 //------------------------------------------------------------------------------------------------
985 override bool RplSave(ScriptBitWriter writer)
986 {
987 int votingTypeMin, votingTypeMax;
988 SCR_Enum.GetRange(EVotingType, votingTypeMin, votingTypeMax);
989
990 writer.WriteInt(GetHostPlayerID());
991
992 int count = m_aVotingInstances.Count();
993 writer.WriteInt(count);
994
995 for (int i; i < count; i++)
996 {
997 writer.WriteIntRange(m_aVotingInstances[i].GetType(), votingTypeMin, votingTypeMax);
998 writer.WriteInt(m_aVotingInstances[i].GetValue());
999 writer.WriteFloat(m_aVotingInstances[i].GetRemainingDuration());
1000 writer.WriteInt(m_aVotingInstances[i].GetCurrentVoteCount());
1001 writer.WriteInt(m_aVotingInstances[i].GetAuthorId());
1002 }
1003
1004 return true;
1005 }
1006
1007 //------------------------------------------------------------------------------------------------
1008 override bool RplLoad(ScriptBitReader reader)
1009 {
1010 int votingTypeMin, votingTypeMax;
1011 SCR_Enum.GetRange(EVotingType, votingTypeMin, votingTypeMax);
1012
1013 reader.ReadInt(m_iHostPlayerID);
1014
1015 int count;
1016 reader.ReadInt(count);
1017
1019 int value, currentVoteCount, authorId;
1020 float remainingDuration;
1021 for (int i; i < count; i++)
1022 {
1023 reader.ReadIntRange(type, votingTypeMin, votingTypeMax);
1024 reader.ReadInt(value);
1025 reader.ReadFloat(remainingDuration);
1026 reader.ReadInt(currentVoteCount);
1027 reader.ReadInt(authorId);
1028 CreateVotingInstance(type, authorId, value, remainingDuration, currentVoteCount);
1029 }
1030
1031 return true;
1032 }
1033
1034 //------------------------------------------------------------------------------------------------
1035 override protected void EOnFrame(IEntity owner, float timeSlice)
1036 {
1037 m_fUpdateLength += timeSlice;
1039 {
1040 if (Replication.IsServer())
1041 {
1042 //--- Server, manager all votings
1043 if (GetGame().GetPlayerManager().GetPlayerCount() > 0)
1044 {
1045 SCR_VotingBase vote;
1046 //--- Update countdowns (only if some players are present; otherwise votings are paused)
1047 for (int i = m_aVotingInstances.Count() - 1; i >= 0; i--)
1048 {
1049 vote = m_aVotingInstances[i];
1050 if (!vote)
1051 continue;
1052
1053 vote.Update(m_fUpdateLength);
1054
1055 //--- End voting when time expired
1056 EVotingOutcome outcome = EVotingOutcome.EVALUATE;
1057 if (vote.Evaluate(outcome))
1058 EndVoting(vote, outcome);
1059 }
1060 }
1061 }
1062 else
1063 {
1064 SCR_VotingBase vote;
1065 //--- Client, merely update countdowns
1066 for (int i = m_aVotingInstances.Count() - 1; i >= 0; i--)
1067 {
1068 vote = m_aVotingInstances[i];
1069 if (vote)
1070 vote.Update(m_fUpdateLength);
1071 }
1072 }
1073
1074 m_fUpdateLength = 0; //--- Must be after the code above, as it's passed inside Update() as a parameter
1075 }
1076 }
1077
1078 //------------------------------------------------------------------------------------------------
1079 // constructor
1084 {
1085 DiagMenu.RegisterMenu(SCR_DebugMenuID.DEBUGUI_VOTING, "Voting", "Game");
1086 DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_VOTING_ENABLE_ALL, "", "Enable All Vote Types", "Voting");
1087 }
1088}
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition DebugMenuID.c:4
ENotification
EVotingOutcome
EVotingType
Definition EVotingType.c:2
ArmaReforgerScripted GetGame()
Definition game.c:1398
override bool RplLoad(ScriptBitReader reader)
enum EAIGroupCombatMode ComponentEditorProps(category:"GameScripted/AI", description:"Component for utility AI system for groups")
SCR_BaseGameMode GetGameMode()
void SCR_BaseGameModeComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
override bool RplSave(ScriptBitWriter writer)
override EGadgetType GetType()
EDamageType type
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
override SCR_UIInfo GetInfo()
int GetPlayerCount()
override void EOnFrame(IEntity owner, float timeSlice)
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
void RemoveVote(EVotingType type, int value=SCR_VotingBase.DEFAULT_VALUE)
void Vote(EVotingType type, int value)
override int GetValue()
override void Log()
override bool IsMatching(EVotingType type, int value=DEFAULT_VALUE)
override int GetPlayerVote(int playerID)
override bool CanSendNotification(int value)
ScriptInvokerBase< ScriptInvoker_VotingManagerStartMethod > ScriptInvoker_VotingManagerStart
ScriptInvokerBase< ScriptInvoker_VotingManagerPlayerMethod > ScriptInvoker_VotingManagerPlayer
ScriptInvoker_VotingManagerPlayer GetOnRemoveVote()
ref ScriptInvoker_VotingManagerStart m_OnVotingStart
void SCR_VotingManagerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
ref ScriptInvoker_VotingManagerStart m_OnAbstainVoteLocal
SCR_VotingBase FindTemplate(EVotingType type)
void PreVoteLocal(EVotingType type, int value)
func ScriptInvoker_VotingManagerPlayerMethod
ref ScriptInvoker_VotingManagerStart m_OnVoteLocal
void RPC_PlayerVoteCountChanged(EVotingType type, int value, int voteCount)
float m_fUpdateStep
ref array< ref Tuple2< int, int > > m_LocalVoteRecords
void AbstainVoteLocally(EVotingType type, int value=SCR_VotingBase.DEFAULT_VALUE)
int GetHostPlayerID()
int GetVoteAuthorId(EVotingType type, int value)
ref ScriptInvoker_VotingManagerPlayer m_OnVote
func ScriptInvoker_VotingManagerVoteCountChangedMethod
bool GetVoteAlwaysDisplayVoteInitiatorVotingTimer(EVotingType type, int value=SCR_VotingBase.DEFAULT_VALUE)
int GetAllVotingsWithValue(out notnull array< EVotingType > outVotingTypes, array< EVotingType > outValues, bool onlyTemplates=false, bool onlyAvailable=false)
void RemoveVoteLocal(EVotingType type, int value)
int GetAllVotingsAboutPlayer(bool aboutPlayer, out notnull array< EVotingType > outVotingTypes, bool onlyTemplates=false, bool onlyAvailable=false)
int GetLocalVote(EVotingType type, int value=SCR_VotingBase.DEFAULT_VALUE)
bool GetVoteAlwaysDisplayVoteSubjectVotingTimer(EVotingType type, int value=SCR_VotingBase.DEFAULT_VALUE)
ref ScriptInvoker_VotingManagerVoteCountChanged m_PlayerVoteCountChanged
ref ScriptInvoker_VotingManagerStart m_OnRemoveVoteLocal
ScriptInvokerBase< ScriptInvoker_VotingManagerVoteCountChangedMethod > ScriptInvoker_VotingManagerVoteCountChanged
bool StartVoting(EVotingType type, int startingPlayerID, int value=SCR_VotingBase.DEFAULT_VALUE)
ScriptInvoker_VotingManagerStart GetOnRemoveVoteLocal()
void StartVotingBroadcast(EVotingType type, int value, int startingPlayerID)
bool IsVotingAboutPlayer(int playerID, EVotingType type)
bool IsLocalVote(EVotingType type, int value=SCR_VotingBase.DEFAULT_VALUE)
SCR_VotingBase FindVoting(EVotingType type, int value)
ScriptInvoker_VotingManagerStart GetOnVotingStart()
int GetVotingsAboutPlayer(int playerID, out notnull array< EVotingType > outVotingTypes, bool onlyTemplates=false, bool onlyAvailable=false)
void EndVoting(EVotingType type, int value=SCR_VotingBase.DEFAULT_VALUE, EVotingOutcome outcome=EVotingOutcome.EVALUATE)
bool GetVoteCounts(EVotingType type, int value, out int currentVotes, out int votesRequired)
bool IsVoting(EVotingType type, int value=SCR_VotingBase.DEFAULT_VALUE)
int GetCurrentVoteCooldownTime(EVotingType type)
ref array< ref SCR_VotingBase > m_aVotingInstances
ref ScriptInvoker_VotingManagerPlayer m_OnRemoveVote
SCR_VotingBase CreateVotingInstance(EVotingType type, int startingPlayerID, int value, float remainingDuration=-1, int currentVoteCount=-1)
ScriptInvoker_VotingManagerStart GetOnAbstainVoteLocal()
ScriptInvokerBase< ScriptInvoker_VotingManagerEndMethod > ScriptInvoker_VotingManagerEnd
func ScriptInvoker_VotingManagerEndMethod
int GetCurrentJoinServerVoteCooldown(EVotingType type)
void EndVotingBroadcast(EVotingType type, int value, int winner)
bool IsVotingAvailable(EVotingType type, int value=SCR_VotingBase.DEFAULT_VALUE)
float GetTimeStamp()
int GetCurrentVoteCooldownForLocalPlayer(EVotingType type)
float m_fUpdateLength
void DeleteVotingInstance(EVotingType type, int value, int winner)
void VoteLocal(EVotingType type, int value)
ScriptInvoker_VotingManagerPlayer GetOnVote()
SCR_VotingUIInfo GetVotingInfo(EVotingType type)
func ScriptInvoker_VotingManagerStartMethod
bool HasAbstainedLocally(EVotingType type, int value=SCR_VotingBase.DEFAULT_VALUE)
ScriptInvoker_VotingManagerVoteCountChanged GetOnVoteCountChanged()
string GetValueName(EVotingType type, int value)
ref ScriptInvoker_VotingManagerEnd m_OnVotingEnd
ref set< SCR_VotingBase > m_aAbstainedVotingInstances
float GetRemainingDurationOfVote(EVotingType type, int value=SCR_VotingBase.DEFAULT_VALUE)
ScriptInvoker_VotingManagerStart GetOnVoteLocal()
int GetAllVotingValues(EVotingType type, out notnull array< int > outValues, bool onlyTemplates=false, bool onlyAvailable=false)
ScriptInvoker_VotingManagerEnd GetOnVotingEnd()
int Type
Definition Debug.c:13
Diagnostic and developer menu system.
Definition DiagMenu.c:18
Definition Math.c:13
Main replication API.
Definition Replication.c:14
static int GetLocalPlayerId()
Returns either a valid ID of local player or 0.
bool Evaluate(out EVotingOutcome outcome)
bool AddPlayerVotedServer(int playerID)
void InitFromTemplate(SCR_VotingBase template, int startingPlayerID, int value, float remainingDuration)
void SetVoteLocal(int value)
bool RemovePlayerVotedServer(int playerID)
float GetRemainingDuration()
static const int DEFAULT_VALUE
bool RemoveVote(int playerID)
void Update(float timeSlice)
int GetPlayerVote(int playerID)
void SetVote(int playerID, int value=DEFAULT_VALUE)
bool GetAlwaysDisplayVoteSubjectVotingTimer()
void SetCurrentVoteCount(int currentVoteCount)
bool IsAvailable(int value, bool isOngoing)
string GetValueName(int value)
bool GetAlwaysDisplayVoteInitiatorVotingTimer()
bool RemoveValue(int value)
bool ShouldCancelWhenSubjectLeavesTheServer()
static const int ALTERNATIVE_VALUE
Value of the vote, that is used when vote ends in an alternative solution.
ENotification GetVotingSucceedNotification()
ENotification GetLocalVoteCastNotification()
ENotification GetVotingAlternativeNotification()
ENotification GetLocalVoteAbstainedNotification()
ENotification GetVotingFailNotification()
AISpawnerGroupClass AIGroupClass Spawn()
Spawns a new group entity, sets its transformation and then calls OnSpawn.
IEntity GetOwner()
Owner entity of the fuel tank.
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)
SCR_FieldOfViewSettings Attribute
EntityEvent
Various entity events.
Definition EntityEvent.c:14
override void OnPlayerRegistered(int playerId)
override void OnPlayerDisconnected(int playerId, KickCauseCode cause, int timeout)
void OnPlayerConnected(int playerId)
void RplRpc(RplChannel channel, RplRcver rcver, RplCondition condition=RplCondition.None, string customConditionName="")
Definition EnNetwork.c:95
RplRcver
Definition RplRcver.c:59
RplChannel
Communication channel. Reliable is guaranteed to be delivered. Unreliable not.
Definition RplChannel.c:14