From: Rudolf Polzer Date: Mon, 25 Jul 2011 18:21:32 +0000 (+0200) Subject: Rewrite of vote code. X-Git-Tag: xonotic-v0.5.0~148^2~41 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=85d7b75eec365a4da388894e6ef783d81e5ec688;p=xonotic%2Fxonotic-data.pk3dir.git Rewrite of vote code. Fixes: #542 "Voting panel does not disappear" Fixes: client disconnects when voting is used while client downloads a map --- diff --git a/qcsrc/client/Main.qc b/qcsrc/client/Main.qc index 95a01ab0e..0b0faa310 100644 --- a/qcsrc/client/Main.qc +++ b/qcsrc/client/Main.qc @@ -847,13 +847,26 @@ void Ent_Nagger() { float nags, i, j, b, f; - nags = ReadByte(); + nags = ReadByte(); // NAGS NAGS NAGS NAGS NAGS NAGS NADZ NAGS NAGS NAGS if(!(nags & 4)) { if(vote_called_vote) strunzone(vote_called_vote); vote_called_vote = string_null; + vote_active = 0; + } + else + { + vote_active = 1; + } + + if(nags & 64) + { + vote_yescount = ReadByte(); + vote_nocount = ReadByte(); + vote_needed = ReadByte(); + vote_highlighted = ReadChar(); } if(nags & 128) @@ -1300,22 +1313,6 @@ void Net_ReadPingPLReport() playerslots[e].ping_movementloss = ml / 255.0; } -void Net_VoteDialog(float highlight) { - if(highlight) { - vote_highlighted = ReadByte(); - return; - } - - vote_yescount = ReadByte(); - vote_nocount = ReadByte(); - vote_needed = ReadByte(); - vote_active = 1; -} - -void Net_VoteDialogReset() { - vote_active = 0; -} - void Net_Notify() { float type; type = ReadByte(); @@ -1385,14 +1382,6 @@ float CSQC_Parse_TempEntity() Net_TeamNagger(); bHandled = true; break; - case TE_CSQC_VOTE: - Net_VoteDialog(ReadByte()); - bHandled = true; - break; - case TE_CSQC_VOTERESET: - Net_VoteDialogReset(); - bHandled = true; - break; case TE_CSQC_LIGHTNINGARC: Net_ReadLightningarc(); bHandled = true; diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc index 6b1171956..260b2c5c5 100644 --- a/qcsrc/client/hud.qc +++ b/qcsrc/client/hud.qc @@ -3117,7 +3117,7 @@ void HUD_VoteWindow(void) pos = panel_pos; mySize = panel_size; - a = vote_alpha * bound(autocvar_hud_panel_vote_alreadyvoted_alpha, 1 - vote_highlighted, 1); + a = vote_alpha * (vote_highlighted ? autocvar_hud_panel_vote_alreadyvoted_alpha : 1); HUD_Panel_DrawBg(a); a = panel_fg_alpha * a; @@ -3168,7 +3168,7 @@ void HUD_VoteWindow(void) drawsetcliparea(pos_x, pos_y, mySize_x * 0.5, mySize_y); drawpic_skin(pos + eY * (5/8) * mySize_y, "voteprogress_voted", eX * mySize_x + eY * (3/8) * mySize_y, '1 1 1', a, DRAWFLAG_NORMAL); } - else if(vote_highlighted == 2) { + else if(vote_highlighted == -1) { drawsetcliparea(pos_x + 0.5 * mySize_x, pos_y, mySize_x * 0.5, mySize_y); drawpic_skin(pos + eY * (5/8) * mySize_y, "voteprogress_voted", eX * mySize_x + eY * (3/8) * mySize_y, '1 1 1', a, DRAWFLAG_NORMAL); } @@ -3187,10 +3187,6 @@ void HUD_VoteWindow(void) } drawresetcliparea(); - - if(!vote_active) { - vote_highlighted = 0; - } } // Mod icons panel (#10) diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index e253ee5c7..939f6f970 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -55,8 +55,6 @@ const float TE_CSQC_NEXGUNBEAMPARTICLE = 104; const float TE_CSQC_LIGHTNINGARC = 105; const float TE_CSQC_TEAMNAGGER = 106; const float TE_CSQC_PINGPLREPORT = 107; -const float TE_CSQC_VOTE = 108; -const float TE_CSQC_VOTERESET = 109; const float TE_CSQC_ANNOUNCE = 110; const float TE_CSQC_TARGET_MUSIC = 111; const float TE_CSQC_NOTIFY = 112; diff --git a/qcsrc/server/clientcommands.qc b/qcsrc/server/clientcommands.qc index ac08cc916..c1d3162a5 100644 --- a/qcsrc/server/clientcommands.qc +++ b/qcsrc/server/clientcommands.qc @@ -1,11 +1,22 @@ entity nagger; float readycount; + float Nagger_SendEntity(entity to, float sendflags) { float nags, i, f, b; entity e; WriteByte(MSG_ENTITY, ENT_CLIENT_NAGGER); + // bits: + // 1 = ready + // 2 = player needs to ready up + // 4 = vote + // 8 = player needs to vote + // 16 = warmup + // sendflags: + // 64 = vote counts + // 128 = vote string + nags = 0; if(readycount) { @@ -22,19 +33,28 @@ float Nagger_SendEntity(entity to, float sendflags) if(inWarmupStage) nags |= 16; + if(sendflags & 64) + nags |= 64; + if(sendflags & 128) nags |= 128; if(!(nags & 4)) // no vote called? send no string - nags &~= 128; + nags &~= (64 | 128); WriteByte(MSG_ENTITY, nags); - if(nags & 128) + if(nags & 64) { - WriteString(MSG_ENTITY, votecalledvote_display); + WriteByte(MSG_ENTITY, vote_yescount); + WriteByte(MSG_ENTITY, vote_nocount); + WriteByte(MSG_ENTITY, vote_needed_absolute); + WriteChar(MSG_ENTITY, to.vote_vote); } + if(nags & 128) + WriteString(MSG_ENTITY, votecalledvote_display); + if(nags & 1) { for(i = 1; i <= maxclients; i += 8) @@ -60,7 +80,7 @@ void Nagger_VoteChanged() void Nagger_VoteCountChanged() { if(nagger) - nagger.SendFlags |= 1; + nagger.SendFlags |= 64; } void Nagger_ReadyCounted() { diff --git a/qcsrc/server/vote.qc b/qcsrc/server/vote.qc index bad3eafe4..1690cf437 100644 --- a/qcsrc/server/vote.qc +++ b/qcsrc/server/vote.qc @@ -116,18 +116,6 @@ float RemapVote(string vote, string cmd, entity e) return TRUE; } -void VoteDialog_UpdateHighlight(float selected) { - WriteByte(MSG_ONE, SVC_TEMPENTITY); - WriteByte(MSG_ONE, TE_CSQC_VOTE); - WriteByte(MSG_ONE, 1); - WriteByte(MSG_ONE, selected); -} - -void VoteDialog_Reset() { - WriteByte(MSG_ALL, SVC_TEMPENTITY); - WriteByte(MSG_ALL, TE_CSQC_VOTERESET); -} - float GameCommand_Vote(string s, entity e) { local float playercount; float argc; @@ -180,10 +168,9 @@ float GameCommand_Vote(string s, entity e) { bprint("\{1}^2* ^3", VoteNetname(votecaller), "^2 calls a vote for ", votecalledvote_display, "\n"); if(autocvar_sv_eventlog) GameLogEcho(strcat(":vote:vcall:", ftos(votecaller.playerid), ":", votecalledvote_display)); - VoteCount(); // needed if you are the only one Nagger_VoteChanged(); + VoteCount(); // needed if you are the only one msg_entity = e; - VoteDialog_UpdateHighlight(1); local entity player; FOR_EACH_REALCLIENT(player) @@ -203,13 +190,10 @@ float GameCommand_Vote(string s, entity e) { if(!votecalled) { print_to(e, "^1No vote called."); } else if(e == votecaller) { // the votecaller can stop a vote - VoteDialog_Reset(); VoteStop(e); } else if(!e) { // server admin / console can too - VoteDialog_Reset(); VoteStop(e); } else if(e.vote_master) { // masters can too - VoteDialog_Reset(); VoteStop(e); } else { print_to(e, "^1You are not allowed to stop that Vote."); @@ -232,8 +216,8 @@ float GameCommand_Vote(string s, entity e) { bprint("\{1}^2* ^3", VoteNetname(votecaller), "^2 calls a vote to become ^3master^2.\n"); if(autocvar_sv_eventlog) GameLogEcho(strcat(":vote:vcall:", ftos(votecaller.playerid), ":", votecalledvote_display)); - VoteCount(); // needed if you are the only one Nagger_VoteChanged(); + VoteCount(); // needed if you are the only one } } else { print_to(e, "^1Vote to become master is NOT allowed."); @@ -284,7 +268,6 @@ float GameCommand_Vote(string s, entity e) { } else if(e.vote_vote == 0 || autocvar_sv_vote_change) { msg_entity = e; - VoteDialog_UpdateHighlight(1); print_to(e, "^1You accepted the vote."); e.vote_vote = 1; centerprint_expire(e, CENTERPRIO_VOTE); @@ -302,7 +285,6 @@ float GameCommand_Vote(string s, entity e) { } else if(e.vote_vote == 0 || autocvar_sv_vote_change) { msg_entity = e; - VoteDialog_UpdateHighlight(2); print_to(e, "^1You rejected the vote."); e.vote_vote = -1; centerprint_expire(e, CENTERPRIO_VOTE); @@ -320,7 +302,6 @@ float GameCommand_Vote(string s, entity e) { } else if(e.vote_vote == 0 || autocvar_sv_vote_change) { msg_entity = e; - VoteDialog_UpdateHighlight(3); print_to(e, "^1You abstained from your vote."); e.vote_vote = -2; centerprint_expire(e, CENTERPRIO_VOTE); @@ -525,54 +506,42 @@ void VoteStop(entity stopper) { VoteReset(); } -void VoteSpam(float yescount, float nocount, float abstaincount, float notvoters, float mincount, string result) +void VoteSpam(float notvoters, float mincount, string result) { string s; if(mincount >= 0) { - s = strcat("\{1}^2* vote results: ^1", ftos(yescount), "^2:^1"); - s = strcat(s, ftos(nocount), "^2 (^1"); + s = strcat("\{1}^2* vote results: ^1", ftos(vote_yescount), "^2:^1"); + s = strcat(s, ftos(vote_nocount), "^2 (^1"); s = strcat(s, ftos(mincount), "^2 needed), ^1"); - s = strcat(s, ftos(abstaincount), "^2 didn't care, ^1"); + s = strcat(s, ftos(vote_abstaincount), "^2 didn't care, ^1"); s = strcat(s, ftos(notvoters), "^2 didn't vote\n"); } else { - s = strcat("\{1}^2* vote results: ^1", ftos(yescount), "^2:^1"); - s = strcat(s, ftos(nocount), "^2, ^1"); - s = strcat(s, ftos(abstaincount), "^2 didn't care, ^1"); + s = strcat("\{1}^2* vote results: ^1", ftos(vote_yescount), "^2:^1"); + s = strcat(s, ftos(vote_nocount), "^2, ^1"); + s = strcat(s, ftos(vote_abstaincount), "^2 didn't care, ^1"); s = strcat(s, ftos(notvoters), "^2 didn't have to vote\n"); } bprint(s); if(autocvar_sv_eventlog) { - s = strcat(":vote:v", result, ":", ftos(yescount)); - s = strcat(s, ":", ftos(nocount)); - s = strcat(s, ":", ftos(abstaincount)); + s = strcat(":vote:v", result, ":", ftos(vote_yescount)); + s = strcat(s, ":", ftos(vote_nocount)); + s = strcat(s, ":", ftos(vote_abstaincount)); s = strcat(s, ":", ftos(notvoters)); s = strcat(s, ":", ftos(mincount)); GameLogEcho(s); } } -void VoteDialog_Update(float msg, float vyes, float vno, float needed) { - WriteByte(msg, SVC_TEMPENTITY); - WriteByte(msg, TE_CSQC_VOTE); - WriteByte(msg, 0); - WriteByte(msg, vyes); - WriteByte(msg, vno); - WriteByte(msg, needed); -} - void VoteCount() { local float playercount; playercount = 0; - local float yescount; - yescount = 0; - local float nocount; - nocount = 0; - local float abstaincount; - abstaincount = 0; + vote_yescount = 0; + vote_nocount = 0; + vote_abstaincount = 0; local entity player; //same for real players local float realplayercount; @@ -581,14 +550,16 @@ void VoteCount() { local float realplayerabstaincount; realplayercount = realplayernocount = realplayerabstaincount = realplayeryescount = 0; + Nagger_VoteCountChanged(); + FOR_EACH_REALCLIENT(player) { if(player.vote_vote == -1) { - ++nocount; + ++vote_nocount; } else if(player.vote_vote == 1) { - ++yescount; + ++vote_yescount; } else if(player.vote_vote == -2) { - ++abstaincount; + ++vote_abstaincount; } ++playercount; //do the same for real players @@ -607,18 +578,25 @@ void VoteCount() { //in tournament mode, if we have at least one player then don't make the vote dependent on spectators (so specs don't have to press F1) if(autocvar_sv_vote_nospectators) if(realplayercount > 0) { - yescount = realplayeryescount; - nocount = realplayernocount; - abstaincount = realplayerabstaincount; + vote_yescount = realplayeryescount; + vote_nocount = realplayernocount; + vote_abstaincount = realplayerabstaincount; playercount = realplayercount; } float votefactor, simplevotefactor; votefactor = bound(0.5, autocvar_sv_vote_majority_factor, 0.999); simplevotefactor = autocvar_sv_vote_simple_majority_factor; - float needed; - needed = floor((playercount - abstaincount) * max(votefactor, simplevotefactor)) + 1; - VoteDialog_Update(MSG_ALL, yescount, nocount, needed); + + // FIXME this number is a guess + vote_needed_absolute = floor((playercount - vote_abstaincount) * votefactor) + 1; + if(simplevotefactor) + { + simplevotefactor = bound(votefactor, simplevotefactor, 0.999); + vote_needed_simple = floor((vote_yescount + vote_nocount) * simplevotefactor) + 1; + } + else + vote_needed_simple = 0; if(votecalledmaster && playercount == 1) { @@ -634,31 +612,28 @@ void VoteCount() { } VoteReset(); } else { - if(yescount > (playercount - abstaincount) * votefactor) + if(vote_yescount >= vote_needed_absolute) { - VoteSpam(yescount, nocount, abstaincount, playercount - yescount - nocount - abstaincount, -1, "yes"); + VoteSpam(playercount - vote_yescount - vote_nocount - vote_abstaincount, -1, "yes"); VoteAccept(); - VoteDialog_Reset(); } - else if(nocount >= (playercount - abstaincount) * (1 - votefactor)) // that means, yescount cannot reach minyes any more + else if(vote_nocount > playercount - vote_abstaincount - vote_needed_absolute) // that means, vote_yescount cannot reach vote_needed_absolute any more { - VoteSpam(yescount, nocount, abstaincount, playercount - yescount - nocount - abstaincount, -1, "no"); + VoteSpam(playercount - vote_yescount - vote_nocount - vote_abstaincount, -1, "no"); VoteReject(); - VoteDialog_Reset(); } else if(time > votefinished) { if(simplevotefactor) { string result; - simplevotefactor = bound(votefactor, simplevotefactor, 0.999); - if(yescount > (yescount + nocount) * simplevotefactor) + if(vote_yescount >= vote_needed_simple) result = "yes"; - else if(yescount + nocount > 0) + else if(vote_yescount + vote_nocount > 0) result = "no"; else result = "timeout"; - VoteSpam(yescount, nocount, abstaincount, playercount - yescount - nocount - abstaincount, floor(min((playercount - abstaincount) * votefactor, (yescount + nocount) * simplevotefactor)) + 1, result); + VoteSpam(playercount - vote_yescount - vote_nocount - vote_abstaincount, min(vote_needed_absolute, vote_needed_simple), result); if(result == "yes") VoteAccept(); else if(result == "no") @@ -668,10 +643,9 @@ void VoteCount() { } else { - VoteSpam(yescount, nocount, abstaincount, playercount - yescount - nocount - abstaincount, floor((playercount - abstaincount) * votefactor) + 1, "timeout"); + VoteSpam(playercount - vote_yescount - vote_nocount - vote_abstaincount, vote_needed_absolute, "timeout"); VoteTimeout(); } - VoteDialog_Reset(); } } } diff --git a/qcsrc/server/vote.qh b/qcsrc/server/vote.qh index 7d937a93c..75eda9849 100644 --- a/qcsrc/server/vote.qh +++ b/qcsrc/server/vote.qh @@ -7,6 +7,11 @@ float votefinished; .float vote_master; .float vote_next; .float vote_vote; +float vote_yescount; +float vote_nocount; +float vote_abstaincount; +float vote_needed_absolute; +float vote_needed_simple; float VoteCheckNasty(string cmd); entity GetKickVoteVictim(string vote, string cmd, entity caller); @@ -22,5 +27,5 @@ void VoteAccept(); void VoteReject(); void VoteTimeout(); void VoteStop(entity stopper); -void VoteSpam(float yescount, float nocount, float abstaincount, float notvoters, float mincount, string result); +void VoteSpam(float notvoters, float mincount, string result); void VoteCount();