|
BANNED
|

05-25-2009
, 11:23
vote patch
|
#1
|
Hi! im sorry if this is not right topic, i'd like to share patch i made for sourcemod-1.2, it works on current 1.3.0-dev
it is not plugin or extension - its patch for core, apply like this patch -p0 < vote.patch for *nix, dont know for windows
what it do:
main feature is when player is alive and vote starts - its dont show for alive players, only for dead. to get vote menu - alive players must type "vote" in chat or any other word - its configured in sm_vote_menu_show_trigger
sounds: startvote, endvote (from mani_admin_plugin, archive included)
core.conf:
Code:
/**
* Specifies the sound that gets played when vote menu started.
*/
"VoteStartSound" "admin_plugin/actions/startyourvoting.mp3"
/**
* Specifies the sound that gets played when vote menu ended.
*/
"VoteEndSound" "admin_plugin/actions/endofvote.mp3"
shows players choices during vote: sm_vote_print_votes (1-on, 0-off)
voting progress in hint box: sm_vote_show_voted_items (How many vote options the hint box should show. 0 - to disable it)
this from what i start write this patch: when plaer alive it pending vote for him, to prevent player to accidentaly choche items: sm_vote_menu_show_trigger (Chat trigger to show pended vote menu. "" - to disable pending for alive players)
im testing it right now, any suggestions from you would be nice)
PS: sorry for my english, im russian
here is text of patch:
Code:
diff -Nurw --strip-trailing-cr sourcemod-central/configs/core.cfg sourcemod-central/configs/core.cfg
--- sourcemod-central/configs/core.cfg 2009-05-13 03:28:04.000000000 +0300
+++ sourcemod-central/configs/core.cfg 2009-05-16 02:44:06.000000000 +0300
@@ -107,4 +107,14 @@
* Currently this will log details about the gamedata updating process.
*/
"DebugSpew" "no"
+
+ /**
+ * Specifies the sound that gets played when vote menu started.
+ */
+ "VoteStartSound" "admin_plugin/actions/startyourvoting.mp3"
+
+ /**
+ * Specifies the sound that gets played when vote menu ended.
+ */
+ "VoteEndSound" "admin_plugin/actions/endofvote.mp3"
}
diff -Nurw --strip-trailing-cr sourcemod-central/core/MenuVoting.cpp sourcemod-central/core/MenuVoting.cpp
--- sourcemod-central/core/MenuVoting.cpp 2009-05-13 03:28:04.000000000 +0300
+++ sourcemod-central/core/MenuVoting.cpp 2009-05-16 02:33:42.000000000 +0300
@@ -31,12 +31,41 @@
#include <string.h>
#include <stdlib.h>
+#include "Logger.h"
#include "MenuVoting.h"
+#include "MenuManager.h"
#include "PlayerManager.h"
#include "sourcemm_api.h"
+#include "HalfLife2.h"
+#include "ConCmdManager.h"
+#include "Translator.h"
+#include "sm_stringutil.h"
+#include "CellRecipientFilter.h"
+
+/* :HACKHACK: We can't SH_DECL here because ConCmdManager.cpp does.
+ * While the OB build only runs on MM:S 1.6.0+ (SH 5+), the older one.
+ * can technically be compiled against any MM:S version after 1.4.2.
+ */
+#if SOURCE_ENGINE >= SE_ORANGEBOX
+extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
+extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
+#else
+extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
+#if SH_IMPL_VERSION >= 5
+extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate0<void>);
+#elif SH_IMPL_VERSION == 4
+extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
+#elif SH_IMPL_VERSION == 3
+extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
+#endif //SH_IMPL_VERSION
+#endif //SE_ORANGEBOX
float g_next_vote = 0.0f;
+ConVar sm_vote_menu_show_trigger("sm_vote_menu_show_trigger", "vote", 0, "Chat trigger to show pended vote menu. \"\" - to disable pending for alive players");
+ConVar sm_vote_print_votes("sm_vote_print_votes", "1", 0, "Should the option that a player vote on get printed");
+ConVar sm_vote_show_voted_items("sm_vote_show_voted_items", "3", 0, "How many vote options the hint box should show. 0 - to disable it", true, 0.0, true, 5.0);
+
#if SOURCE_ENGINE >= SE_ORANGEBOX
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
#else
@@ -91,14 +120,62 @@
g_Players.AddClientListener(this);
}
+void VoteMenuHandler::OnSourceModAllInitialized_Post(){
+ g_pCorePhrases->AddPhraseFile("common.phrases");
+}
+
+void VoteMenuHandler::OnSourceModGameInitialized(){
+ m_pSayCmd = FindCommand("say");
+ m_pSayTeamCmd = FindCommand("say_team");
+
+ if(m_pSayCmd){
+ SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &VoteMenuHandler::OnSayCommand_Pre, false);
+ }
+
+ if(m_pSayTeamCmd){
+ SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &VoteMenuHandler::OnSayCommand_Pre, false);
+ }
+}
+
void VoteMenuHandler::OnSourceModShutdown()
{
g_Players.RemoveClientListener(this);
+
+ if(m_pSayTeamCmd){
+ SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &VoteMenuHandler::OnSayCommand_Pre, false);
+ }
+
+ if(m_pSayCmd){
+ SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &VoteMenuHandler::OnSayCommand_Pre, false);
+ }
+}
+
+ConfigResult VoteMenuHandler::OnSourceModConfigChanged(const char *key,
+ const char *value,
+ ConfigSource source,
+ char *error,
+ size_t maxlength){
+ if(!strcmp(key, "VoteStartSound")){
+ m_VoteStartSound.assign(value);
+ return ConfigResult_Accept;
+
+ }else if(!strcmp(key, "VoteEndSound")){
+ m_VoteEndSound.assign(value);
+ return ConfigResult_Accept;
+ }
+
+ return ConfigResult_Ignore;
}
void VoteMenuHandler::OnSourceModLevelChange(const char *mapName)
{
g_next_vote = 0.0f;
+
+ if(m_VoteStartSound.size() > 0)
+ enginesound->PrecacheSound(m_VoteStartSound.c_str(), true);
+
+ if(m_VoteEndSound.size() > 0)
+ enginesound->PrecacheSound(m_VoteEndSound.c_str(), true);
}
unsigned int VoteMenuHandler::GetMenuAPIVersion2()
@@ -113,11 +190,11 @@
return;
}
- /* Wipe out their vote if they had one. We have to make sure the the the
+ /* Wipe out their vote if they had one. We have to make sure that the
* newly connected client is not allowed to vote.
*/
int item;
- if ((item = m_ClientVotes[client]) >= -1)
+ if ((item = m_ClientVotes[client]) >= -1 || item == -3)
{
if (item >= 0)
{
@@ -166,17 +243,53 @@
m_fStartTime = gpGlobals->curtime;
m_nMenuTime = max_time;
+ cell_t cl[1];
+ CPlayer *pPlayer;
+ CellRecipientFilter crf;
+ bool vote_start_sound = m_bVoteMenuSound && m_VoteStartSound.size() > 0;
+
for (unsigned int i=0; i<num_clients; i++)
{
if (clients[i] < 1 || clients[i] > 256)
{
continue;
}
+
+ pPlayer = g_Players.GetPlayerByIndex(clients[i]);
+ if(pPlayer && pPlayer->IsInGame() && !pPlayer->IsFakeClient()){
+
+ //play a sound about the vote start
+ if(vote_start_sound){
+ cl[0] = clients[i];
+ crf.Reset();
+ crf.Initialize(cl, 1);
+ enginesound->EmitSound(crf, cl[0], CHAN_AUTO, m_VoteStartSound.c_str(), VOL_NORM, ATTN_NORM);
+ }
+
+ //mark client as vote menu pending
+ if(m_sVoteMenuShowTrigger[0] && pPlayer->GetLifeState() == PLAYER_LIFE_ALIVE){
+ m_ClientVotes[clients[i]] = -3;
+ m_ClientsPending++;
+
+ char text[128];
+ if(!CoreTranslate(text, sizeof(text), "[SM] %T", 3, NULL, "vote menu show trigger", &clients[i], m_sVoteMenuShowTrigger))
+ UTIL_Format(text, sizeof(text), "[SM] Type %s to show vote menu", m_sVoteMenuShowTrigger);
+
+ g_HL2.TextMsg(clients[i], HUD_PRINTTALK, text);
+
+ continue;
+ }
+ }
+
menu->Display(clients[i], max_time, this);
}
StartVoting();
+ m_pVoteShowTimer = g_Timers.CreateTimer(this, 0.95, this, TIMER_FLAG_REPEAT);
+ if(m_pVoteShowTimer)
+ g_Timers.FireTimerOnce(m_pVoteShowTimer, false);
+
return true;
}
@@ -189,13 +302,13 @@
return false;
}
- return (m_ClientVotes[client] > -2);
+ return (m_ClientVotes[client] > -2 || m_ClientVotes[client] == -3);
}
bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
{
if (!IsClientInVotePool(client)
- || m_ClientVotes[client] == -1)
+ || m_ClientVotes[client] == -1 || m_ClientVotes[client] == -3)
{
return false;
}
@@ -275,6 +388,11 @@
m_VoteFlags = flags;
m_pHandler = handler;
+ m_sVoteMenuShowTrigger = const_cast<char *>(sm_vote_menu_show_trigger.GetString());
+ m_bVoteMenuSound = g_Menus.MenuSoundsEnabled() && (menu->GetMenuOptionFlags() & MENUFLAG_NO_SOUND) != MENUFLAG_NO_SOUND;
+ m_bVotePrintVotes = sm_vote_print_votes.GetBool();
+ m_VoteShowVotedItems = sm_vote_show_voted_items.GetInt();
+
m_pHandler->OnMenuStart(m_pCurMenu);
return true;
@@ -294,7 +412,7 @@
/* By now we know how many clients were set.
* If there are none, we should end IMMEDIATELY.
*/
- if (m_Clients == 0)
+ if (m_Clients == 0 && m_ClientsPending == 0)
{
EndVoting();
}
@@ -306,7 +424,7 @@
m_Clients--;
- if (m_bStarted && m_Clients == 0)
+ if (m_bStarted && m_Clients == 0 && m_ClientsPending == 0)
{
EndVoting();
}
@@ -320,6 +438,24 @@
void VoteMenuHandler::EndVoting()
{
+ //play a sound about the vote end
+ if(m_bVoteMenuSound && m_VoteEndSound.size() > 0){
+ int maxClients = g_Players.GetMaxClients();
+ CellRecipientFilter crf;
+ CPlayer *pPlayer;
+ cell_t cl[1];
+
+ for(int i = 1; i <= maxClients; i++){
+ pPlayer = g_Players.GetPlayerByIndex(i);
+ if(pPlayer && pPlayer->IsInGame() && !pPlayer->IsFakeClient()){
+ cl[0] = i;
+ crf.Reset();
+ crf.Initialize(cl, 1);
+ enginesound->EmitSound(crf, cl[0], CHAN_AUTO, m_VoteEndSound.c_str(), VOL_NORM, ATTN_NORM);
+ }
+ }
+ }
+
/* Set when the next delay ends. We ignore cancellation because a menu
* was, at one point, displayed, which is all that counts. However, we
* do re-calculate the time just in case the menu had no time limit.
@@ -380,10 +516,10 @@
/* Build the client list */
for (int i=1; i<=gpGlobals->maxClients; i++)
{
- if (m_ClientVotes[i] >= -1)
+ if (m_ClientVotes[i] >= -1 || m_ClientVotes[i] == -3)
{
client_vote[vote.num_clients].client = i;
- client_vote[vote.num_clients].item = m_ClientVotes[i];
+ client_vote[vote.num_clients].item = m_ClientVotes[i] == -3 ? -1 : m_ClientVotes[i];
vote.num_clients++;
}
}
@@ -424,6 +560,9 @@
void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
{
+ if(m_ClientVotes[client] == -3)
+ m_ClientsPending--;
+
m_ClientVotes[client] = -1;
m_pHandler->OnMenuDisplay(menu, client, display);
}
@@ -446,9 +585,33 @@
m_ClientVotes[client] = item;
m_Votes[item]++;
m_NumVotes++;
+
+ //show
+ if(m_bVotePrintVotes){
+ CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
+ const char *pl_name = pPlayer ? pPlayer->GetName() : NULL;
+ int maxClients = g_Players.GetMaxClients();
+
+ for(int i = 1; i <= maxClients; i++){
+ pPlayer = g_Players.GetPlayerByIndex(i);
+ if(pPlayer && pPlayer->IsInGame() && !pPlayer->IsFakeClient()){
+ char text[512];
+ ItemDrawInfo dr;
+ if(m_pCurMenu->GetItemInfo(item, &dr)){
+ if(!CoreTranslate(text, sizeof(text), "[SM] %T", 4, NULL, "Vote Select", &i, pl_name, dr.display))
+ UTIL_Format(text, sizeof(text), "[SM] %s has chosen %s.", pl_name, dr.display);
+
+ g_HL2.TextMsg(i, HUD_PRINTTALK, text);
+ }
+ }
+ }
+ }
}
m_pHandler->OnMenuSelect(menu, client, item);
+
+ if(m_VoteShowVotedItems && m_pVoteShowTimer)
+ g_Timers.FireTimerOnce(m_pVoteShowTimer, false);
}
void VoteMenuHandler::OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page)
@@ -462,12 +625,18 @@
void VoteMenuHandler::InternalReset()
{
m_Clients = 0;
+ m_ClientsPending = 0;
m_Items = 0;
m_bStarted = false;
m_pCurMenu = NULL;
m_NumVotes = 0;
m_bCancelled = false;
m_pHandler = NULL;
+ m_sVoteMenuShowTrigger = NULL;
+ m_bVoteMenuSound = false;
+ m_pVoteShowTimer = NULL;
+ m_VoteShowVotedItems = 0;
+ m_bVotePrintVotes = false;
}
void VoteMenuHandler::CancelVoting()
@@ -489,3 +658,100 @@
{
return m_bCancelled;
}
+
+ResultType VoteMenuHandler::OnTimer(ITimer *pTimer, void *pData){
+ if(!m_bStarted || m_fStartTime+m_nMenuTime < gpGlobals->curtime+1)
+ return static_cast<ResultType>(Pl_Stop);
+
+ if(!m_VoteShowVotedItems)
+ return static_cast<ResultType>(Pl_Continue);
+
+ //count
+ menu_vote_result_t::menu_item_vote_t item_vote[256];
+ unsigned int num_items = 0, num_votes = 0, num_clients = 0;
+
+ for(unsigned int i=0; i < m_Items; i++)
+ if(m_Votes[i] > 0){
+ item_vote[num_items].count = m_Votes[i];
+ item_vote[num_items].item = i;
+ num_votes+= m_Votes[i];
+ num_items++;
+ }
+
+ qsort(item_vote, num_items, sizeof(menu_vote_result_t::menu_item_vote_t), SortVoteItems);
+
+ for(int i=1; i <= gpGlobals->maxClients; i++)
+ if(m_ClientVotes[i] >= -1 || m_ClientVotes[i] == -3)
+ num_clients++;
+
+ //format
+ char text[512];
+ ItemDrawInfo dr;
+ int cnt = num_items > m_VoteShowVotedItems ? m_VoteShowVotedItems : num_items;
+
+ text[0] = 0;
+ for(int i=0,j=0; i < cnt && item_vote[i].count; i++)
+ if(m_pCurMenu->GetItemInfo(item_vote[i].item, &dr))
+ j+= UTIL_Format(&text[j], sizeof(text)-j, "\n%d. %s - %d", i+1, dr.display, item_vote[i].count);
+
+ //show
+ int maxClients = g_Players.GetMaxClients();
+ for(int i = 1; i <= maxClients; i++){
+
+ CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
+ if(pPlayer && pPlayer->IsInGame() && !pPlayer->IsFakeClient()){
+
+ char hintboxText[512];
+ int time_left = m_nMenuTime - (unsigned int)(gpGlobals->curtime - m_fStartTime);
+
+ UTIL_Format(hintboxText, sizeof(hintboxText), "%s (%d/%d) - %d s%s", m_pCurMenu->GetDefaultTitle(), num_votes, num_clients, time_left > 0 ? time_left : 0, text);
+
+ g_HL2.HintTextMsg(i, hintboxText);
+ }
+ }
+
+ return static_cast<ResultType>(Pl_Continue);
+}
+
+void VoteMenuHandler::OnTimerEnd(ITimer *pTimer, void *pData){
+ m_pVoteShowTimer = NULL;
+
+ m_ClientsPending = 0;
+
+ if(m_bStarted && !m_Clients)
+ EndVoting();
+}
+
+#if SOURCE_ENGINE >= SE_ORANGEBOX
+void VoteMenuHandler::OnSayCommand_Pre(const CCommand &command){
+#else
+void VoteMenuHandler::OnSayCommand_Pre(){
+ CCommand command;
+#endif
+
+ if(!m_pCurMenu || !m_sVoteMenuShowTrigger || !m_sVoteMenuShowTrigger[0] || !m_ClientsPending)
+ return;
+
+ int client = g_ConCmds.GetCommandClient();
+ if(client < 1 || client > 256 || m_ClientVotes[client] != -3)
+ return;
+
+ const char *arg1 = command.Arg(1);
+ if(!arg1 || strcasecmp(arg1, m_sVoteMenuShowTrigger))
+ return;
+
+ unsigned int time_limit;
+ if(m_nMenuTime == MENU_TIME_FOREVER){
+ time_limit = m_nMenuTime;
+
+ }else{
+ time_limit = (int)((float)m_nMenuTime - (gpGlobals->curtime - m_fStartTime));
+ if(time_limit == MENU_TIME_FOREVER)
+ time_limit = 1;
+ }
+
+ m_pCurMenu->Display(client, time_limit, this);
+
+ if(m_VoteShowVotedItems && m_pVoteShowTimer)
+ g_Timers.FireTimerOnce(m_pVoteShowTimer, false);
+}
diff -Nurw --strip-trailing-cr sourcemod-central/core/MenuVoting.h sourcemod-central/core/MenuVoting.h
--- sourcemod-central/core/MenuVoting.h 2009-05-13 03:28:04.000000000 +0300
+++ sourcemod-central/core/MenuVoting.h 2009-05-15 23:08:57.000000000 +0300
@@ -36,6 +36,7 @@
#include <IPlayerHelpers.h>
#include <sh_vector.h>
#include "sm_globals.h"
+#include "TimerSys.h"
using namespace SourceHook;
using namespace SourceMod;
@@ -43,11 +44,22 @@
class VoteMenuHandler :
public IMenuHandler,
public SMGlobalClass,
- public IClientListener
+ public IClientListener,
+ public ITimedEvent
{
+public: //ITimedEvent
+ ResultType OnTimer(ITimer *pTimer, void *pData);
+ void OnTimerEnd(ITimer *pTimer, void *pData);
public: //SMGlobalClass
void OnSourceModAllInitialized();
+ void OnSourceModAllInitialized_Post();
+ void OnSourceModGameInitialized();
void OnSourceModShutdown();
+ ConfigResult OnSourceModConfigChanged(const char *key,
+ const char *value,
+ ConfigSource source,
+ char *error,
+ size_t maxlength);
void OnSourceModLevelChange(const char *mapName);
public: //IClientListener
void OnClientDisconnected(int client);
@@ -75,6 +87,12 @@
bool IsClientInVotePool(int client);
bool GetClientVoteChoice(int client, unsigned int *pItem);
bool RedrawToClient(int client);
+private: //ConCommand
+#if SOURCE_ENGINE >= SE_ORANGEBOX
+ void OnSayCommand_Pre(const CCommand &command);
+#else
+ void OnSayCommand_Pre();
+#endif
private:
void Reset(IMenuHandler *mh);
void DecrementPlayerCount();
@@ -86,8 +104,18 @@
unsigned int flags);
void StartVoting();
private:
+ String m_VoteStartSound;
+ String m_VoteEndSound;
+ char *m_sVoteMenuShowTrigger;
+ bool m_bVoteMenuSound;
+ ConCommand *m_pSayCmd;
+ ConCommand *m_pSayTeamCmd;
+ ITimer *m_pVoteShowTimer;
+ bool m_bVotePrintVotes;
+ unsigned int m_VoteShowVotedItems;
IMenuHandler *m_pHandler;
unsigned int m_Clients;
+ unsigned int m_ClientsPending;
unsigned int m_Items;
CVector<unsigned int> m_Votes;
IBaseMenu *m_pCurMenu;
diff -Nurw --strip-trailing-cr sourcemod-central/translations/core.phrases.txt sourcemod-central/translations/core.phrases.txt
--- sourcemod-central/translations/core.phrases.txt 2009-05-13 03:28:04.000000000 +0300
+++ sourcemod-central/translations/core.phrases.txt 2009-05-16 02:41:48.000000000 +0300
@@ -56,4 +56,11 @@
"#format" "{1:s}"
"en" "{1}"
}
+
+ "vote menu show trigger"
+ {
+ "#format" "{1:s}"
+ "en" "Type {1} to show vote menu"
+ "ru" "Напишите {1} для меню голосований"
+ }
}
TO Administrator: please move this topic to AlliedModders Forum Index > SourceMod > Extensions, Snippets, Tutorials
Last edited by grif_ssa; 05-25-2009 at 11:45.
|
|