7 [
Attribute(
"0", UIWidgets.ComboBox,
"Type of the vote.", enums: ParamEnumArray.FromEnum(
EVotingType))]
10 [
Attribute(
desc:
"When enabled, values are considered player IDs (e.g., a vote to KICK player).")]
11 protected bool m_bIsValuePlayerID;
13 [
Attribute(
"120",
desc:
"The voting will end after this duration (in seconds) and outcome will be evaluated.")]
14 protected float m_fDuration;
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;
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;
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;
28 static const int DEFAULT_VALUE = -1;
30 protected int m_iLocalValue = DEFAULT_VALUE;
33 protected int m_iCurrentVoteCount;
36 protected ref array<int> m_aPlayersVoted_Server = {};
42 bool AddPlayerVotedServer(
int playerID)
44 if (m_aPlayersVoted_Server.Contains(playerID))
47 m_aPlayersVoted_Server.Insert(playerID);
48 SetCurrentVoteCount(m_aPlayersVoted_Server.Count());
51 Print(
"Player '" + playerID +
"' approved vote | Vote Type: '" +
typename.EnumToString(
EVotingType, m_Type) +
"' | Vote value: '" + m_iLocalValue +
"' | Count (" + GetCurrentVoteCount() +
"/" + GetVoteCountRequired() +
")");
60 bool RemovePlayerVotedServer(
int playerID)
62 if (!m_aPlayersVoted_Server.Contains(playerID))
65 m_aPlayersVoted_Server.RemoveItem(playerID);
66 SetCurrentVoteCount(m_aPlayersVoted_Server.Count());
69 Print(
"Player '" + playerID +
"' removed vote | Vote Type: '" +
typename.EnumToString(
EVotingType, m_Type) +
"' | Vote value: '" + m_iLocalValue +
"' | Count (" + GetCurrentVoteCount() +
"/" + GetVoteCountRequired() +
")");
77 void SetCurrentVoteCount(
int currentVoteCount)
79 m_iCurrentVoteCount = currentVoteCount;
84 int GetCurrentVoteCount()
86 return m_iCurrentVoteCount;
96 void SetVote(
int playerID,
int value = DEFAULT_VALUE);
102 bool RemoveVote(
int playerID);
109 bool RemoveValue(
int value);
115 bool CanSendNotification(
int value)
134 return DEFAULT_VALUE;
142 void OnVotingEnd(
int value = DEFAULT_VALUE,
int winner = DEFAULT_VALUE);
147 int GetPlayerVote(
int playerID)
149 return DEFAULT_VALUE;
159 bool IsAvailable(
int value,
bool isOngoing)
179 string GetValueName(
int value)
181 if (m_bIsValuePlayerID && value > 0)
182 return GetGame().GetPlayerManager().GetPlayerName(value);
184 return value.ToString();
201 return DEFAULT_VALUE;
213 float GetRemainingDuration()
221 bool IsValuePlayerID()
223 return m_bIsValuePlayerID;
230 void SetVoteLocal(
int value)
232 m_iLocalValue = value;
238 void RemoveVoteLocal()
240 m_iLocalValue = DEFAULT_VALUE;
249 return m_iLocalValue;
255 void Update(
float timeSlice)
257 m_fDuration = Math.Max(m_fDuration - timeSlice, 0);
265 void InitFromTemplate(
SCR_VotingBase template,
int value,
float remainingDuration)
268 m_fThreshold =
template.m_fThreshold;
269 m_bIsValuePlayerID =
template.m_bIsValuePlayerID;
270 m_iMinParticipation = Math.Min(
template.m_iMinParticipation,
template.m_fThreshold);
271 m_iMinVotes =
template.m_iMinVotes;
273 if (remainingDuration == -1)
284 return Math.Max(
GetGame().GetPlayerManager().GetPlayerCount(), 1);
290 int GetVoteCountRequired()
292 float playersRequired = GetPlayerCount() * m_fThreshold;
293 int playersRequiredInt = Math.Ceil(playersRequired);
296 if (playersRequired == playersRequiredInt)
297 playersRequiredInt++;
299 if (playersRequiredInt < m_iMinVotes)
302 return playersRequiredInt;
306 protected bool EvaluateParticipation(
int voteCount)
322 voteCount >= Math.Min(m_iMinVotes, GetPlayerCount())
335 && (float)(voteCount / GetPlayerCount()) >= m_iMinParticipation;
347 protected ref set<int> m_aPlayerIDs =
new set<int>();
348 protected int m_iValue;
351 protected float GetRatio()
357 override void SetVote(
int playerID,
int value = DEFAULT_VALUE)
363 override bool RemoveVote(
int playerID)
378 override bool RemoveValue(
int value)
380 return m_bIsValuePlayerID &&
m_iValue == value;
392 return super.Evaluate(outcome) || (GetRatio() > m_fThreshold && EvaluateParticipation(
m_aPlayerIDs.Count()));
396 override int GetWinner()
398 if (GetRatio() > m_fThreshold && EvaluateParticipation(
m_aPlayerIDs.Count()))
401 return DEFAULT_VALUE;
405 override int GetPlayerVote(
int playerID)
410 return DEFAULT_VALUE;
414 override int GetValue()
425 PrintFormat(
" '%1'",
GetGame().GetPlayerManager().GetPlayerName(playerID));
430 override void InitFromTemplate(
SCR_VotingBase template,
int value,
float remainingDuration)
433 super.InitFromTemplate(
template, value, remainingDuration);
444 protected ref map<int, int> m_Votes =
new map<int, int>();
445 protected int m_iHighestValue = DEFAULT_VALUE;
446 protected int m_iHighestCount;
449 protected void UpdateHighestValue()
451 map<int, int> tally =
new map<int, int>();
453 set<int> winners =
new set<int>();
454 foreach (
int playerID,
int value: m_Votes)
457 if (tally.Find(value, count))
462 tally.Set(value, count);
464 if (count > m_iHighestCount)
466 m_iHighestCount = count;
468 winners.Insert(value);
470 else if (count == m_iHighestCount)
472 winners.Insert(value);
476 if (winners.IsEmpty())
477 m_iHighestValue = DEFAULT_VALUE;
480 m_iHighestValue = winners[Math.RandomInt(0, winners.Count())];
484 override void SetVote(
int playerID,
int value = DEFAULT_VALUE)
486 m_Votes.Set(playerID, value);
487 UpdateHighestValue();
493 m_Votes.Remove(playerID);
494 UpdateHighestValue();
495 return m_Votes.IsEmpty();
501 for (
int i = m_Votes.Count() - 1; i >= 0; i--)
503 if (m_Votes.GetElement(i) == value)
504 m_Votes.RemoveElement(i);
506 UpdateHighestValue();
520 return super.Evaluate(outcome) || (ratio > m_fThreshold && EvaluateParticipation(m_Votes.Count()));
526 if (EvaluateParticipation(m_Votes.Count()))
527 return m_iHighestValue;
529 return DEFAULT_VALUE;
536 if (m_Votes.Find(playerID, value))
539 return DEFAULT_VALUE;
546 PrintFormat(
" Leading value: %1 with %2 votes", m_iHighestValue, m_iHighestCount);
548 foreach (
int playerID,
int value: m_Votes)
550 PrintFormat(
" %1 votes for %2",
GetGame().GetPlayerManager().GetPlayerName(playerID),
GetValueName(value));