Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_VotingBase.c
Go to the documentation of this file.
6 {
7  [Attribute("0", UIWidgets.ComboBox, "Type of the vote.", enums: ParamEnumArray.FromEnum(EVotingType))]
8  protected EVotingType m_Type;
9 
10  [Attribute(desc: "When enabled, values are considered player IDs (e.g., a vote to KICK player).")]
11  protected bool m_bIsValuePlayerID;
12 
13  [Attribute("120", desc: "The voting will end after this duration (in seconds) and outcome will be evaluated.")]
14  protected float m_fDuration;
15 
16  [Attribute("0.5", UIWidgets.Slider, "When percentual number of votes for single value is *larger* than this threshold, the voting will instantly end.\ne.g., in a session with 8 players and threshold 0.5, 5 votes are needed to win.", params: "0 1 0.01")]
17  protected float m_fThreshold;
18 
19  [Attribute("0.5", UIWidgets.Slider, "Winner can be declared only if this percentage of players participated in the vote.\nEvaluated together with 'Min Votes', at least one has to pass.", params: "0 1 0.01")]
20  protected float m_iMinParticipation;
21 
22  [Attribute("3", desc: "Winner can be declare only if at least this amount of players participated in the vote.\nEvaluated together with 'Min Participation', at least one has to pass.")]
23  protected int m_iMinVotes;
24 
25  [Attribute(desc: "Visual representation of the voting.")]
26  protected ref SCR_VotingUIInfo m_Info;
27 
28  static const int DEFAULT_VALUE = -1;
29 
30  protected int m_iLocalValue = DEFAULT_VALUE;
31 
32  //~ How many players have voted in favour
33  protected int m_iCurrentVoteCount;
34 
35  //~ Keep track of who voted (server only)
36  protected ref array<int> m_aPlayersVoted_Server = {};
37 
38  //------------------------------------------------------------------------------------------------
42  bool AddPlayerVotedServer(int playerID)
43  {
44  if (m_aPlayersVoted_Server.Contains(playerID))
45  return false;
46 
47  m_aPlayersVoted_Server.Insert(playerID);
48  SetCurrentVoteCount(m_aPlayersVoted_Server.Count());
49 
50  //~ Vote debug
51  Print("Player '" + playerID + "' approved vote | Vote Type: '" + typename.EnumToString(EVotingType, m_Type) + "' | Vote value: '" + m_iLocalValue + "' | Count (" + GetCurrentVoteCount() + "/" + GetVoteCountRequired() + ")");
52 
53  return true;
54  }
55 
56  //------------------------------------------------------------------------------------------------
60  bool RemovePlayerVotedServer(int playerID)
61  {
62  if (!m_aPlayersVoted_Server.Contains(playerID))
63  return false;
64 
65  m_aPlayersVoted_Server.RemoveItem(playerID);
66  SetCurrentVoteCount(m_aPlayersVoted_Server.Count());
67 
68  //~ Vote debug
69  Print("Player '" + playerID + "' removed vote | Vote Type: '" + typename.EnumToString(EVotingType, m_Type) + "' | Vote value: '" + m_iLocalValue + "' | Count (" + GetCurrentVoteCount() + "/" + GetVoteCountRequired() + ")");
70 
71  return true;
72  }
73 
74  //------------------------------------------------------------------------------------------------
77  void SetCurrentVoteCount(int currentVoteCount)
78  {
79  m_iCurrentVoteCount = currentVoteCount;
80  }
81 
82  //------------------------------------------------------------------------------------------------
84  int GetCurrentVoteCount()
85  {
86  return m_iCurrentVoteCount;
87  }
88 
89  //------------------------------------------------------------------------------------------------
90  //--- Public, server
91 
92  //------------------------------------------------------------------------------------------------
96  void SetVote(int playerID, int value = DEFAULT_VALUE);
97 
98  //------------------------------------------------------------------------------------------------
102  bool RemoveVote(int playerID);
103 
104  //------------------------------------------------------------------------------------------------
109  bool RemoveValue(int value);
110 
111  //------------------------------------------------------------------------------------------------
115  bool CanSendNotification(int value)
116  {
117  return true;
118  }
119 
120  //------------------------------------------------------------------------------------------------
124  bool Evaluate(out EVotingOutcome outcome)
125  {
126  return m_fDuration <= 0;
127  }
128 
129  //------------------------------------------------------------------------------------------------
132  int GetWinner()
133  {
134  return DEFAULT_VALUE;
135  }
136 
137  //------------------------------------------------------------------------------------------------
142  void OnVotingEnd(int value = DEFAULT_VALUE, int winner = DEFAULT_VALUE);
143 
144  //------------------------------------------------------------------------------------------------
147  int GetPlayerVote(int playerID)
148  {
149  return DEFAULT_VALUE;
150  }
151 
153  //--- Public, anywhere
154  //------------------------------------------------------------------------------------------------
159  bool IsAvailable(int value, bool isOngoing)
160  {
161  return true;
162  }
163 
164  //------------------------------------------------------------------------------------------------
169  bool IsMatching(EVotingType type, int value = DEFAULT_VALUE);
170 
171  //------------------------------------------------------------------------------------------------
173  void Log();
174 
175  //------------------------------------------------------------------------------------------------
179  string GetValueName(int value)
180  {
181  if (m_bIsValuePlayerID && value > 0)
182  return GetGame().GetPlayerManager().GetPlayerName(value);
183  else
184  return value.ToString();
185  }
186 
187  //------------------------------------------------------------------------------------------------
190  EVotingType GetType()
191  {
192  return m_Type;
193  }
194 
195  //------------------------------------------------------------------------------------------------
199  EVotingType GetValue()
200  {
201  return DEFAULT_VALUE;
202  }
203 
204  //------------------------------------------------------------------------------------------------
207  SCR_VotingUIInfo GetInfo()
208  {
209  return m_Info;
210  }
211  //------------------------------------------------------------------------------------------------
213  float GetRemainingDuration()
214  {
215  return m_fDuration;
216  }
217 
218  //------------------------------------------------------------------------------------------------
221  bool IsValuePlayerID()
222  {
223  return m_bIsValuePlayerID;
224  }
225 
226  //------------------------------------------------------------------------------------------------
230  void SetVoteLocal(int value)
231  {
232  m_iLocalValue = value;
233  }
234 
235  //------------------------------------------------------------------------------------------------
238  void RemoveVoteLocal()
239  {
240  m_iLocalValue = DEFAULT_VALUE;
241  }
242 
243  //------------------------------------------------------------------------------------------------
247  int GetLocalVote()
248  {
249  return m_iLocalValue;
250  }
251 
252  //------------------------------------------------------------------------------------------------
255  void Update(float timeSlice)
256  {
257  m_fDuration = Math.Max(m_fDuration - timeSlice, 0);
258  }
259 
260  //------------------------------------------------------------------------------------------------
265  void InitFromTemplate(SCR_VotingBase template, int value, float remainingDuration)
266  {
267  m_Type = template.m_Type;
268  m_fThreshold = template.m_fThreshold;
269  m_bIsValuePlayerID = template.m_bIsValuePlayerID;
270  m_iMinParticipation = Math.Min(template.m_iMinParticipation, template.m_fThreshold); //--- Min participation cannot be stricter than threshold
271  m_iMinVotes = template.m_iMinVotes;
272 
273  if (remainingDuration == -1)
274  m_fDuration = template.m_fDuration;
275  else
276  m_fDuration = remainingDuration;
277  }
278 
279  //------------------------------------------------------------------------------------------------
282  int GetPlayerCount()
283  {
284  return Math.Max(GetGame().GetPlayerManager().GetPlayerCount(), 1);
285  }
286 
287  //------------------------------------------------------------------------------------------------
290  int GetVoteCountRequired()
291  {
292  float playersRequired = GetPlayerCount() * m_fThreshold;
293  int playersRequiredInt = Math.Ceil(playersRequired);
294 
295  //~ Vote succeeds when vote count is GREATER than threshold. If players requered is == to playersRequired ceil than it means that there is 1 more player needed for the vote to succeed as otherwise the vote is equal
296  if (playersRequired == playersRequiredInt)
297  playersRequiredInt++;
298 
299  if (playersRequiredInt < m_iMinVotes)
300  return m_iMinVotes;
301 
302  return playersRequiredInt;
303  }
304 
305  //------------------------------------------------------------------------------------------------
306  protected bool EvaluateParticipation(int voteCount)
307  {
308  return
309  /*
310  Absolute player limit
311  With m_iMinVotes = 3, at least 3 players have to cast a vote.
312  If there are fewer than 3 players, total amount of players will be used instead (which means the vote has to be unanimous)
313  Examples:
314  Players Votes needed
315  1 1
316  2 2
317  3 3
318  4 3
319  5 3
320  ... ...
321  */
322  voteCount >= Math.Min(m_iMinVotes, GetPlayerCount())
323  /*
324  Relative player limit
325  With m_iMinParticipation = 0.5 (50%), at least half of players need to cast a vote.
326  Examples:
327  Players Votes needed
328  1 1
329  2 1
330  3 2
331  4 2
332  5 3
333  ... ...
334  */
335  && (float)(voteCount / GetPlayerCount()) >= m_iMinParticipation;
336  }
337 };
338 
346 {
347  protected ref set<int> m_aPlayerIDs = new set<int>();
348  protected int m_iValue;
349 
350  //------------------------------------------------------------------------------------------------
351  protected float GetRatio()
352  {
353  return (m_aPlayerIDs.Count() / GetPlayerCount());
354  }
355 
356  //------------------------------------------------------------------------------------------------
357  override void SetVote(int playerID, int value = DEFAULT_VALUE)
358  {
359  m_aPlayerIDs.Insert(playerID);
360  }
361 
362  //------------------------------------------------------------------------------------------------
363  override bool RemoveVote(int playerID)
364  {
365  int index = m_aPlayerIDs.Find(playerID);
366  if (index >= 0)
367  {
368  m_aPlayerIDs.Remove(index);
369  return m_aPlayerIDs.IsEmpty();
370  }
371  else
372  {
373  return false;
374  }
375  }
376 
377  //------------------------------------------------------------------------------------------------
378  override bool RemoveValue(int value)
379  {
380  return m_bIsValuePlayerID && m_iValue == value;
381  }
382 
383  //------------------------------------------------------------------------------------------------
384  override bool IsMatching(EVotingType type, int value = DEFAULT_VALUE)
385  {
386  return m_Type == type && m_iValue == value;
387  }
388 
389  //------------------------------------------------------------------------------------------------
390  override bool Evaluate(out EVotingOutcome outcome)
391  {
392  return super.Evaluate(outcome) || (GetRatio() > m_fThreshold && EvaluateParticipation(m_aPlayerIDs.Count()));
393  }
394 
395  //------------------------------------------------------------------------------------------------
396  override int GetWinner()
397  {
398  if (GetRatio() > m_fThreshold && EvaluateParticipation(m_aPlayerIDs.Count()))
399  return m_iValue; //--- Passed the threshold and minimum participation
400  else
401  return DEFAULT_VALUE; //--- Expired, didn't pass
402  }
403 
404  //------------------------------------------------------------------------------------------------
405  override int GetPlayerVote(int playerID)
406  {
407  if (m_aPlayerIDs.Contains(playerID))
408  return m_iValue;
409  else
410  return DEFAULT_VALUE;
411  }
412 
413  //------------------------------------------------------------------------------------------------
414  override int GetValue()
415  {
416  return m_iValue;
417  }
418 
419  //------------------------------------------------------------------------------------------------
420  override void Log()
421  {
422  PrintFormat("%1 (m_Type = %2, m_iValue = %3, m_iLocalValue = %3)", Type(), typename.EnumToString(EVotingType, m_Type), GetValueName(m_iValue), GetValueName(m_iLocalValue));
423  foreach (int playerID: m_aPlayerIDs)
424  {
425  PrintFormat(" '%1'", GetGame().GetPlayerManager().GetPlayerName(playerID));
426  }
427  }
428 
429  //------------------------------------------------------------------------------------------------
430  override void InitFromTemplate(SCR_VotingBase template, int value, float remainingDuration)
431  {
432  m_iValue = value;
433  super.InitFromTemplate(template, value, remainingDuration);
434  }
435 }
436 
442 class SCR_VotingElection : SCR_VotingBase
443 {
444  protected ref map<int, int> m_Votes = new map<int, int>(); // <playerID, value>
445  protected int m_iHighestValue = DEFAULT_VALUE;
446  protected int m_iHighestCount;
447 
448  //------------------------------------------------------------------------------------------------
449  protected void UpdateHighestValue()
450  {
451  map<int, int> tally = new map<int, int>(); // <value, count>
452  m_iHighestCount = 0;
453  set<int> winners = new set<int>();
454  foreach (int playerID, int value: m_Votes)
455  {
456  int count;
457  if (tally.Find(value, count))
458  count++;
459  else
460  count = 1;
461 
462  tally.Set(value, count);
463 
464  if (count > m_iHighestCount)
465  {
466  m_iHighestCount = count;
467  winners.Clear();
468  winners.Insert(value);
469  }
470  else if (count == m_iHighestCount)
471  {
472  winners.Insert(value);
473  }
474  }
475 
476  if (winners.IsEmpty())
477  m_iHighestValue = DEFAULT_VALUE;
478  else
479  //--- In case of multiple leaders, pick one by random
480  m_iHighestValue = winners[Math.RandomInt(0, winners.Count())];
481  }
482 
483  //------------------------------------------------------------------------------------------------
484  override void SetVote(int playerID, int value = DEFAULT_VALUE)
485  {
486  m_Votes.Set(playerID, value);
487  UpdateHighestValue();
488  }
489 
490  //------------------------------------------------------------------------------------------------
491  override bool RemoveVote(int playerID)
492  {
493  m_Votes.Remove(playerID);
494  UpdateHighestValue();
495  return m_Votes.IsEmpty();
496  }
497 
498  //------------------------------------------------------------------------------------------------
499  override bool RemoveValue(int value)
500  {
501  for (int i = m_Votes.Count() - 1; i >= 0; i--)
502  {
503  if (m_Votes.GetElement(i) == value)
504  m_Votes.RemoveElement(i);
505  }
506  UpdateHighestValue();
507  return false;
508  }
509 
510  //------------------------------------------------------------------------------------------------
511  override bool IsMatching(EVotingType type, int value = DEFAULT_VALUE)
512  {
513  return m_Type == type;
514  }
515 
516  //------------------------------------------------------------------------------------------------
517  override bool Evaluate(out EVotingOutcome outcome)
518  {
519  float ratio = (m_iHighestCount / GetPlayerCount());
520  return super.Evaluate(outcome) || (ratio > m_fThreshold && EvaluateParticipation(m_Votes.Count()));
521  }
522 
523  //------------------------------------------------------------------------------------------------
524  override int GetWinner()
525  {
526  if (EvaluateParticipation(m_Votes.Count()))
527  return m_iHighestValue;
528  else
529  return DEFAULT_VALUE; //--- Expired, didn't pass
530  }
531 
532  //------------------------------------------------------------------------------------------------
533  override int GetPlayerVote(int playerID)
534  {
535  int value;
536  if (m_Votes.Find(playerID, value))
537  return value;
538  else
539  return DEFAULT_VALUE;
540  }
541 
542  //------------------------------------------------------------------------------------------------
543  override void Log()
544  {
545  PrintFormat("%1 (m_Type = %2, m_iLocalValue = %3)", Type(), typename.EnumToString(EVotingType, m_Type), GetValueName(m_iLocalValue));
546  PrintFormat(" Leading value: %1 with %2 votes", m_iHighestValue, m_iHighestCount);
547  string valueName;
548  foreach (int playerID, int value: m_Votes)
549  {
550  PrintFormat(" %1 votes for %2", GetGame().GetPlayerManager().GetPlayerName(playerID), GetValueName(value));
551  }
552  }
553 }
m_aPlayerIDs
protected ref set< int > m_aPlayerIDs
Definition: SCR_VotingBase.c:2
SCR_VotingBase
Definition: SCR_VotingBase.c:5
GetWinner
override int GetWinner()
Definition: SCR_VotingBase.c:51
m_fDuration
float m_fDuration
Definition: SendGoalMessage.c:437
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
m_iValue
protected int m_iValue
Definition: SCR_VotingBase.c:3
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
RemoveVote
override bool RemoveVote(int playerID)
Definition: SCR_VotingBase.c:18
RemoveValue
override bool RemoveValue(int value)
Definition: SCR_VotingBase.c:33
Attribute
typedef Attribute
Post-process effect of scripted camera.
m_Info
protected ref SCR_HintUIInfo m_Info
Definition: SCR_BaseHintCondition.c:3
Evaluate
override bool Evaluate(out EVotingOutcome outcome)
Definition: SCR_VotingBase.c:45
SCR_VotingReferendum
Definition: SCR_VotingBase.c:345
IsMatching
override bool IsMatching(EVotingType type, int value=DEFAULT_VALUE)
Definition: SCR_VotingBase.c:39
SetVote
override void SetVote(int playerID, int value=DEFAULT_VALUE)
Definition: SCR_VotingBase.c:12
m_Type
protected EEditableEntityType m_Type
Definition: SCR_EntitiesToolbarEditorUIComponent.c:3
index
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Definition: SCR_DestructionSynchronizationComponent.c:17
EVotingType
EVotingType
Definition: EVotingType.c:1
SCR_VotingUIInfo
Definition: SCR_VotingUIInfo.c:2
GetPlayerVote
override int GetPlayerVote(int playerID)
Definition: SCR_VotingBase.c:60
type
EDamageType type
Definition: SCR_DestructibleTreeV2.c:32
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
BaseContainerProps
SCR_VotingReferendum SCR_VotingBase BaseContainerProps()
SCR_BaseContainerCustomTitleEnum
SCR_VotingReferendum SCR_VotingBase SCR_BaseContainerCustomTitleEnum(EVotingType, "m_Type")
Definition: SCR_VotingBase.c:441
GetPlayerCount
int GetPlayerCount()
Definition: SCR_Faction.c:365
EVotingOutcome
EVotingOutcome
Definition: EVotingOutcome.c:1
Log
override void Log()
Definition: SCR_VotingBase.c:75
GetValueName
string GetValueName(EVotingType type, int value)
Definition: SCR_VotingManagerComponent.c:490