2023-07-30 14:28:58 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
Copyright (C) 2023 the OpenMoHAA team
|
|
|
|
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
|
|
or (at your option) any later version.
|
|
|
|
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "bg_voteoptions.h"
|
2023-09-12 00:01:07 +02:00
|
|
|
#include "../qcommon/script.h"
|
2023-07-30 14:28:58 +02:00
|
|
|
|
2023-11-03 21:09:18 +01:00
|
|
|
#if defined(GAME_DLL)
|
2023-11-03 21:28:46 +01:00
|
|
|
# define VO_FS_FreeFile gi.FS_FreeFile
|
|
|
|
# define VO_FS_ReadFile(a, b) gi.FS_ReadFile(a, b, true)
|
|
|
|
# define VO_SendRemoteCommand(s) // ?
|
|
|
|
# define VO_ExecuteCommand(s) gi.Cmd_Execute(EXEC_NOW, s)
|
|
|
|
# define VO_Cvar_Set(name, value) gi.cvar_set(name, value)
|
|
|
|
# define VO_Cvar_Get(name, value, flags) gi.Cvar_Get(name, value, flags)
|
|
|
|
# define VO_LV_ConvertString(s) gi.LV_ConvertString(s)
|
2023-11-03 21:09:18 +01:00
|
|
|
#elif defined(CGAME_DLL)
|
2023-11-03 21:28:46 +01:00
|
|
|
# define VO_FS_FreeFile cgi.FS_FreeFile
|
|
|
|
# define VO_FS_ReadFile(a, b) cgi.FS_ReadFile(a, b, qtrue)
|
|
|
|
# define VO_SendRemoteCommand(s) cgi.SendClientCommand(s)
|
|
|
|
# define VO_ExecuteCommand(s) cgi.Cmd_Execute(EXEC_NOW, s)
|
|
|
|
# define VO_Cvar_Set(name, value) cgi.Cvar_Set(name, value)
|
|
|
|
# define VO_Cvar_Get(name, value, flags) cgi.Cvar_Get(name, value, flags)
|
|
|
|
# define VO_LV_ConvertString(s) cgi.LV_ConvertString(s)
|
2023-11-03 21:09:18 +01:00
|
|
|
#else
|
|
|
|
# pragma error("VoteOptions can must be used with fgame or cgame")
|
|
|
|
#endif
|
|
|
|
|
2023-09-12 00:01:07 +02:00
|
|
|
CLASS_DECLARATION(Class, VoteOptions, NULL) {
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
VoteOptionListItem::VoteOptionListItem()
|
|
|
|
: m_pNext(NULL)
|
|
|
|
{}
|
|
|
|
|
|
|
|
SingleVoteOption::SingleVoteOption()
|
|
|
|
: m_optionType(VOTE_NO_CHOICES)
|
|
|
|
, m_pListItem(NULL)
|
|
|
|
, m_pNext(NULL)
|
|
|
|
{}
|
|
|
|
|
|
|
|
SingleVoteOption::~SingleVoteOption()
|
|
|
|
{
|
|
|
|
VoteOptionListItem *item;
|
|
|
|
VoteOptionListItem *next;
|
|
|
|
|
|
|
|
for (item = m_pListItem; item; item = next) {
|
|
|
|
next = item->m_pNext;
|
|
|
|
delete item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VoteOptions::VoteOptions()
|
|
|
|
{
|
|
|
|
m_pHeadOption = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
VoteOptions::~VoteOptions()
|
|
|
|
{
|
|
|
|
ClearOptions();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VoteOptions::ClearOptions()
|
|
|
|
{
|
|
|
|
SingleVoteOption *option;
|
|
|
|
SingleVoteOption *next;
|
|
|
|
|
|
|
|
for (option = m_pHeadOption; option; option = next) {
|
|
|
|
next = option->m_pNext;
|
|
|
|
delete option;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pHeadOption = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VoteOptions::SetupVoteOptions(const char *configFileName)
|
|
|
|
{
|
|
|
|
char *buffer;
|
|
|
|
int compressedLength;
|
2023-09-18 23:34:24 +02:00
|
|
|
long length;
|
2023-09-12 00:01:07 +02:00
|
|
|
|
2023-11-03 21:28:46 +01:00
|
|
|
length = VO_FS_ReadFile(configFileName, (void **)&buffer);
|
2023-09-18 23:34:24 +02:00
|
|
|
if (length == -1 || !length) {
|
2023-09-12 00:01:07 +02:00
|
|
|
Com_Printf("WARNING: Couldn't find voting options file: %s\n", configFileName);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// compress the buffer before setting up
|
|
|
|
compressedLength = COM_Compress(buffer);
|
|
|
|
SetupVoteOptions(configFileName, compressedLength, buffer);
|
2023-11-03 21:09:18 +01:00
|
|
|
VO_FS_FreeFile(buffer);
|
2023-09-12 00:01:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void VoteOptions::SetupVoteOptions(const char *configFileName, int length, const char *buffer)
|
|
|
|
{
|
|
|
|
if (length >= MAX_VOTEOPTIONS_BUFFER_LENGTH) {
|
|
|
|
Com_Error(
|
|
|
|
ERR_DROP,
|
2024-06-07 20:34:13 +02:00
|
|
|
"VoteOptions: Options file '%s' is too big. Max size is %lu bytes\n",
|
2023-09-12 00:01:07 +02:00
|
|
|
configFileName,
|
|
|
|
MAX_VOTEOPTIONS_BUFFER_LENGTH
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_sFileName = configFileName;
|
|
|
|
m_sBuffer = buffer;
|
|
|
|
|
|
|
|
ParseVoteOptions();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VoteOptions::ParseVoteOptions()
|
|
|
|
{
|
|
|
|
SingleVoteOption *option;
|
|
|
|
SingleVoteOption *newOption;
|
|
|
|
VoteOptionListItem *listItem;
|
|
|
|
VoteOptionListItem *newListItem;
|
|
|
|
str token;
|
|
|
|
Script script;
|
|
|
|
|
|
|
|
ClearOptions();
|
|
|
|
script.LoadFile(m_sFileName.c_str(), m_sBuffer.length(), m_sBuffer.c_str());
|
|
|
|
|
|
|
|
option = m_pHeadOption;
|
|
|
|
|
|
|
|
while (script.TokenAvailable(true)) {
|
|
|
|
token = script.GetToken(true);
|
|
|
|
|
|
|
|
if (!str::icmp(token, "{")) {
|
|
|
|
Com_Error(
|
|
|
|
ERR_DROP,
|
|
|
|
"Vote Options %s: Found choices list without option header on line %d.\n",
|
|
|
|
m_sFileName.c_str(),
|
|
|
|
script.GetLineNumber()
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!str::icmp(token, "}")) {
|
|
|
|
Com_Error(
|
|
|
|
ERR_DROP,
|
|
|
|
"Vote Options %s: Illegal end of choices list without list being started on line %d.\n",
|
|
|
|
m_sFileName.c_str(),
|
|
|
|
script.GetLineNumber()
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!token.length()) {
|
|
|
|
Com_Error(
|
|
|
|
ERR_DROP,
|
|
|
|
"Vote Options %s: Empty option name on line %d.\n",
|
|
|
|
m_sFileName.c_str(),
|
|
|
|
script.GetLineNumber()
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
newOption = new SingleVoteOption();
|
|
|
|
|
|
|
|
if (option) {
|
|
|
|
option->m_pNext = newOption;
|
|
|
|
} else {
|
|
|
|
m_pHeadOption = newOption;
|
|
|
|
}
|
|
|
|
option = newOption;
|
|
|
|
|
|
|
|
newOption->m_sOptionName = token;
|
|
|
|
|
|
|
|
if (!script.TokenAvailable(false)) {
|
|
|
|
Com_Error(
|
|
|
|
ERR_DROP,
|
|
|
|
"Vote Options %s: Option without a command specified on line %d.\n",
|
|
|
|
m_sFileName.c_str(),
|
|
|
|
script.GetLineNumber()
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
newOption->m_sCommand = script.GetToken(false);
|
|
|
|
|
|
|
|
if (script.TokenAvailable(false)) {
|
|
|
|
token = script.GetToken(false);
|
|
|
|
|
|
|
|
if (!str::icmp(token, "nochoices")) {
|
|
|
|
newOption->m_optionType = VOTE_NO_CHOICES;
|
|
|
|
} else if (!str::icmp(token, "list")) {
|
|
|
|
newOption->m_optionType = VOTE_OPTION_LIST;
|
|
|
|
} else if (!str::icmp(token, "text")) {
|
|
|
|
newOption->m_optionType = VOTE_OPTION_TEXT;
|
|
|
|
} else if (!str::icmp(token, "integer")) {
|
|
|
|
newOption->m_optionType = VOTE_OPTION_INTEGER;
|
|
|
|
} else if (!str::icmp(token, "float")) {
|
|
|
|
newOption->m_optionType = VOTE_OPTION_FLOAT;
|
|
|
|
} else if (!str::icmp(token, "client")) {
|
|
|
|
newOption->m_optionType = VOTE_OPTION_CLIENT;
|
|
|
|
} else if (!str::icmp(token, "clientnotself")) {
|
|
|
|
newOption->m_optionType = VOTE_OPTION_CLIENT_NOT_SELF;
|
|
|
|
} else {
|
|
|
|
Com_Error(
|
|
|
|
ERR_DROP,
|
|
|
|
"Vote Options %s: Illegal option type '%s' specified on line %d.\n"
|
|
|
|
" Valid types are nochoices, list, text, & number.\n",
|
|
|
|
m_sFileName.c_str(),
|
|
|
|
token.c_str(),
|
|
|
|
script.GetLineNumber()
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newOption->m_optionType == VOTE_OPTION_LIST) {
|
|
|
|
if (!script.TokenAvailable(true) || Q_stricmp(script.GetToken(true), "{")) {
|
|
|
|
Com_Error(
|
|
|
|
ERR_DROP,
|
|
|
|
"Vote Options %s: Missing '{'. No choices list specified for list option on line %d.\n",
|
|
|
|
m_sFileName.c_str(),
|
|
|
|
script.GetLineNumber()
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
listItem = NULL;
|
|
|
|
|
|
|
|
while (script.TokenAvailable(true)) {
|
|
|
|
token = script.GetToken(true);
|
|
|
|
|
|
|
|
if (!str::icmp(token, "}")) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
newListItem = new VoteOptionListItem();
|
|
|
|
|
|
|
|
if (listItem) {
|
|
|
|
listItem->m_pNext = newListItem;
|
|
|
|
} else {
|
|
|
|
newOption->m_pListItem = newListItem;
|
|
|
|
}
|
2024-10-02 14:09:36 +02:00
|
|
|
listItem = newListItem;
|
2023-12-31 00:53:26 +01:00
|
|
|
newListItem->m_sItemName = token;
|
2023-09-12 00:01:07 +02:00
|
|
|
|
|
|
|
if (!script.TokenAvailable(false)) {
|
|
|
|
Com_Error(
|
|
|
|
ERR_DROP,
|
|
|
|
"Vote Options %s: List choice without vote string specified on line %d.\n",
|
|
|
|
m_sFileName.c_str(),
|
|
|
|
script.GetLineNumber()
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
newListItem->m_sCommand = script.GetToken(false);
|
|
|
|
}
|
|
|
|
} else if (script.TokenAvailable(true)) {
|
|
|
|
token = script.GetToken(true);
|
|
|
|
|
|
|
|
if (!str::icmp(token, "{")) {
|
|
|
|
Com_Error(
|
|
|
|
ERR_DROP,
|
|
|
|
"Vote Options %s: Choices list specified for non-list option on line %d.\n",
|
|
|
|
m_sFileName.c_str(),
|
|
|
|
script.GetLineNumber()
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
script.UnGetToken();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *VoteOptions::GetVoteOptionsFile(int *outLen) const
|
|
|
|
{
|
|
|
|
if (outLen) {
|
|
|
|
*outLen = m_sBuffer.length();
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_sBuffer.c_str();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VoteOptions::GetVoteOptionsMain(int index, str *outOptionCommand, voteoptiontype_t *outOptionType) const
|
|
|
|
{
|
|
|
|
SingleVoteOption *option;
|
|
|
|
int optionIndex;
|
|
|
|
|
|
|
|
if (index < 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
optionIndex = 1;
|
|
|
|
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
|
|
|
|
optionIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!option) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*outOptionCommand = option->m_sCommand;
|
|
|
|
*outOptionType = option->m_optionType;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VoteOptions::GetVoteOptionSub(int index, int listIndex, str *outCommand) const
|
|
|
|
{
|
|
|
|
SingleVoteOption *option;
|
|
|
|
VoteOptionListItem *item;
|
|
|
|
int optionIndex;
|
|
|
|
int itemIndex;
|
|
|
|
|
|
|
|
if (index < 1 || listIndex < 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
optionIndex = 1;
|
|
|
|
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
|
|
|
|
optionIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!option) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (option->m_optionType != VOTE_OPTION_LIST) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
itemIndex = 1;
|
|
|
|
for (item = option->m_pListItem; itemIndex < listIndex && option != NULL; item = item->m_pNext) {
|
|
|
|
itemIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!item) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*outCommand = item->m_sCommand;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VoteOptions::GetVoteOptionMainName(int index, str *outVoteName) const
|
|
|
|
{
|
|
|
|
SingleVoteOption *option;
|
|
|
|
int optionIndex;
|
|
|
|
|
|
|
|
if (index < 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
optionIndex = 1;
|
|
|
|
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
|
|
|
|
optionIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!option) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*outVoteName = option->m_sOptionName;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VoteOptions::GetVoteOptionSubName(int index, int listIndex, str *outName) const
|
|
|
|
{
|
|
|
|
SingleVoteOption *option;
|
|
|
|
VoteOptionListItem *item;
|
|
|
|
int optionIndex;
|
|
|
|
int itemIndex;
|
|
|
|
|
|
|
|
if (index < 1 || listIndex < 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
optionIndex = 1;
|
|
|
|
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
|
|
|
|
optionIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!option) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (option->m_optionType != VOTE_OPTION_LIST) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
itemIndex = 1;
|
|
|
|
for (item = option->m_pListItem; itemIndex < listIndex && option != NULL; item = item->m_pNext) {
|
|
|
|
itemIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!item) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*outName = item->m_sItemName;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2023-11-03 21:09:18 +01:00
|
|
|
|
|
|
|
#if defined(CGAME_DLL)
|
|
|
|
|
|
|
|
static str g_sVoteString;
|
|
|
|
static VoteOptions g_voteOptions;
|
|
|
|
|
|
|
|
void CG_VoteOptions_StartReadFromServer(const char *string)
|
|
|
|
{
|
|
|
|
g_sVoteString = string;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CG_VoteOptions_ContinueReadFromServer(const char *string)
|
|
|
|
{
|
|
|
|
if (g_sVoteString.length() >= MAX_VOTEOPTIONS_BUFFER_LENGTH) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_sVoteString += string;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CG_VoteOptions_FinishReadFromServer(const char *string)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (g_sVoteString.length() >= MAX_VOTEOPTIONS_BUFFER_LENGTH) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_sVoteString += va("%s\n", string);
|
|
|
|
if (!str::cmp(g_sVoteString, "\n")) {
|
|
|
|
VO_SendRemoteCommand("wait 250;gvo\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < g_sVoteString.length(); i++) {
|
|
|
|
if (g_sVoteString[i] == 1) {
|
|
|
|
g_sVoteString[i] = '"';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_voteOptions.SetupVoteOptions("ServerVoteOptions", g_sVoteString.length(), g_sVoteString.c_str());
|
|
|
|
g_sVoteString = "";
|
|
|
|
g_voteOptions.SetupMainOptionsList();
|
|
|
|
}
|
|
|
|
|
2023-12-31 00:39:43 +01:00
|
|
|
void CG_PushCallVote_f(void)
|
2023-11-03 21:28:46 +01:00
|
|
|
{
|
|
|
|
g_voteOptions.SetupMainOptionsList();
|
|
|
|
}
|
|
|
|
|
2023-12-31 00:39:43 +01:00
|
|
|
void CG_PushCallVoteSubList_f(void)
|
2023-11-03 21:28:46 +01:00
|
|
|
{
|
|
|
|
g_voteOptions.SetupSubOptionsList(atoi(cgi.Argv(1)));
|
|
|
|
}
|
|
|
|
|
2023-12-31 00:39:43 +01:00
|
|
|
void CG_PushCallVoteSubText_f(void)
|
2023-11-03 21:28:46 +01:00
|
|
|
{
|
|
|
|
str command;
|
|
|
|
str name;
|
|
|
|
voteoptiontype_t type;
|
|
|
|
|
|
|
|
if (!g_voteOptions.GetVoteOptionsMain(atoi(cgi.Argv(1)), &command, &type)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type != voteoptiontype_t::VOTE_OPTION_TEXT) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_voteOptions.GetVoteOptionMainName(atoi(cgi.Argv(1)), &name);
|
|
|
|
VO_ExecuteCommand("forcemenu votesubtext\n");
|
|
|
|
VO_Cvar_Set("ui_votesubtitle", name.c_str());
|
|
|
|
VO_Cvar_Set("ui_votestringentry", "");
|
|
|
|
}
|
|
|
|
|
2023-12-31 00:39:43 +01:00
|
|
|
void CG_PushCallVoteSubInteger_f(void)
|
2023-11-03 21:28:46 +01:00
|
|
|
{
|
|
|
|
str command;
|
|
|
|
str name;
|
|
|
|
voteoptiontype_t type;
|
|
|
|
|
|
|
|
if (!g_voteOptions.GetVoteOptionsMain(atoi(cgi.Argv(1)), &command, &type)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type != voteoptiontype_t::VOTE_OPTION_INTEGER) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_voteOptions.GetVoteOptionMainName(atoi(cgi.Argv(1)), &name);
|
|
|
|
VO_ExecuteCommand("forcemenu votesubinteger\n");
|
|
|
|
VO_Cvar_Set("ui_votesubtitle", name.c_str());
|
|
|
|
VO_Cvar_Set("ui_votestringentry", "");
|
|
|
|
}
|
|
|
|
|
2023-12-31 00:39:43 +01:00
|
|
|
void CG_PushCallVoteSubFloat_f(void)
|
2023-11-03 21:28:46 +01:00
|
|
|
{
|
|
|
|
str command;
|
|
|
|
str name;
|
|
|
|
voteoptiontype_t type;
|
|
|
|
|
|
|
|
if (!g_voteOptions.GetVoteOptionsMain(atoi(cgi.Argv(1)), &command, &type)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type != voteoptiontype_t::VOTE_OPTION_FLOAT) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_voteOptions.GetVoteOptionMainName(atoi(cgi.Argv(1)), &name);
|
|
|
|
VO_ExecuteCommand("forcemenu votesubfloat\n");
|
|
|
|
VO_Cvar_Set("ui_votesubtitle", name.c_str());
|
|
|
|
VO_Cvar_Set("ui_votestringentry", "");
|
|
|
|
}
|
|
|
|
|
2023-12-31 00:39:43 +01:00
|
|
|
void CG_PushCallVoteSubClient_f(void)
|
2023-11-03 21:28:46 +01:00
|
|
|
{
|
|
|
|
str command;
|
|
|
|
str name;
|
|
|
|
int index;
|
|
|
|
int i;
|
|
|
|
voteoptiontype_t type;
|
|
|
|
|
|
|
|
index = atoi(cgi.Argv(1));
|
|
|
|
|
|
|
|
if (!g_voteOptions.GetVoteOptionsMain(index, &command, &type)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type != voteoptiontype_t::VOTE_OPTION_CLIENT && type != voteoptiontype_t::VOTE_OPTION_CLIENT_NOT_SELF) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_voteOptions.GetVoteOptionMainName(index, &name);
|
|
|
|
VO_ExecuteCommand("forcemenu votesubclient\n");
|
|
|
|
VO_Cvar_Set("ui_votesubtitle", name.c_str());
|
|
|
|
VO_ExecuteCommand("globalwidgetcommand voteclientlist deleteallitems\n");
|
|
|
|
|
|
|
|
for (i = 0; i < cgs.maxclients; i++) {
|
|
|
|
if (type == VOTE_OPTION_CLIENT_NOT_SELF && cg.snap && i == cg.snap->ps.clientNum) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strlen(cg.clientinfo[i].name)) {
|
|
|
|
continue;
|
|
|
|
}
|
2024-10-02 14:09:36 +02:00
|
|
|
|
2023-11-03 21:28:46 +01:00
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand voteclientlist additem \"%i: %s\" \"callvote %i %i;popmenu 0\"\n",
|
|
|
|
i,
|
2024-06-07 20:36:55 +02:00
|
|
|
cg.clientinfo[i].name,
|
2023-11-03 21:28:46 +01:00
|
|
|
index,
|
|
|
|
i)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand voteclientlist additem \"%s\" \"popmenu 0\"\n", VO_LV_ConvertString("[Cancel Vote]"))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-12-31 00:39:43 +01:00
|
|
|
void CG_PushVote_f(void)
|
2023-11-03 21:28:46 +01:00
|
|
|
{
|
|
|
|
VO_Cvar_Set("ui_votesubtitle", cgs.voteString);
|
|
|
|
VO_ExecuteCommand("forcemenu votecast\n");
|
|
|
|
}
|
|
|
|
|
2023-12-31 00:39:43 +01:00
|
|
|
void CG_CallEntryVote_f(void)
|
2023-11-03 21:28:46 +01:00
|
|
|
{
|
|
|
|
str command;
|
|
|
|
str name;
|
|
|
|
const char *entry;
|
|
|
|
int index;
|
|
|
|
voteoptiontype_t type;
|
|
|
|
|
|
|
|
index = VO_Cvar_Get("ui_votetype", "0", 0)->integer;
|
|
|
|
|
|
|
|
if (!g_voteOptions.GetVoteOptionsMain(index, &command, &type)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type != voteoptiontype_t::VOTE_OPTION_TEXT && type != voteoptiontype_t::VOTE_OPTION_INTEGER
|
|
|
|
&& type != voteoptiontype_t::VOTE_OPTION_FLOAT) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
entry = VO_Cvar_Get("ui_votestringentry", "", 0)->string;
|
|
|
|
VO_ExecuteCommand(va("callvote %i \"%s\"\n", index, entry));
|
|
|
|
}
|
|
|
|
|
2023-12-31 00:39:43 +01:00
|
|
|
void VoteOptions::SetupMainOptionsList(void)
|
2023-11-03 21:09:18 +01:00
|
|
|
{
|
2023-11-04 18:43:10 +01:00
|
|
|
SingleVoteOption *option;
|
|
|
|
int count;
|
|
|
|
|
2023-11-03 21:28:46 +01:00
|
|
|
VO_ExecuteCommand("forcemenu votemain\n");
|
|
|
|
VO_ExecuteCommand("globalwidgetcommand votelistmain deleteallitems\n");
|
|
|
|
|
2023-11-04 18:43:10 +01:00
|
|
|
if (!IsSetup()) {
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0\"\n",
|
|
|
|
VO_LV_ConvertString("Retrieving voting options from server..."))
|
|
|
|
);
|
|
|
|
VO_SendRemoteCommand("gvo\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
count = 1;
|
|
|
|
|
|
|
|
for (option = m_pHeadOption; option; option = option->m_pNext, count++) {
|
|
|
|
switch (option->m_optionType) {
|
|
|
|
case VOTE_NO_CHOICES:
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand votelistmain additem \"%s\" \"callvote %i;popmenu 0\"\n",
|
|
|
|
option->m_sOptionName.c_str(),
|
|
|
|
count)
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case VOTE_OPTION_LIST:
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;pushcallvotesublist %i\"\n",
|
|
|
|
option->m_sOptionName.c_str(),
|
|
|
|
count)
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case VOTE_OPTION_TEXT:
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype "
|
|
|
|
"%i;pushcallvotesubtext %i\"\n",
|
|
|
|
option->m_sOptionName.c_str(),
|
|
|
|
count,
|
|
|
|
count)
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case VOTE_OPTION_INTEGER:
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype "
|
|
|
|
"%i;pushcallvotesubinteger %i\"\n",
|
|
|
|
option->m_sOptionName.c_str(),
|
|
|
|
count,
|
|
|
|
count)
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case VOTE_OPTION_FLOAT:
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype "
|
|
|
|
"%i;pushcallvotesubfloat %i\"\n",
|
|
|
|
option->m_sOptionName.c_str(),
|
|
|
|
count,
|
|
|
|
count)
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case VOTE_OPTION_CLIENT:
|
|
|
|
case VOTE_OPTION_CLIENT_NOT_SELF:
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype "
|
|
|
|
"%i;pushcallvotesubclient %i\"\n",
|
|
|
|
option->m_sOptionName.c_str(),
|
|
|
|
count,
|
|
|
|
count)
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0\"\n", VO_LV_ConvertString("[Cancel Vote]"))
|
|
|
|
);
|
2023-11-03 21:09:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void VoteOptions::SetupSubOptionsList(int index)
|
|
|
|
{
|
2023-11-04 18:43:10 +01:00
|
|
|
SingleVoteOption *option;
|
|
|
|
VoteOptionListItem *item;
|
|
|
|
int count;
|
|
|
|
int numItems;
|
|
|
|
|
2023-11-03 21:28:46 +01:00
|
|
|
if (index < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-11-04 18:43:10 +01:00
|
|
|
count = 1;
|
|
|
|
for (option = m_pHeadOption; count < index && option; option = option->m_pNext) {
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!option) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (option->m_optionType != VOTE_OPTION_LIST || !option->m_pListItem) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VO_ExecuteCommand("forcemenu votesublist\n");
|
|
|
|
VO_Cvar_Set("ui_votesubtitle", option->m_sOptionName.c_str());
|
|
|
|
VO_ExecuteCommand("globalwidgetcommand votelistsub deleteallitems\n");
|
|
|
|
|
|
|
|
if (IsSetup()) {
|
|
|
|
numItems = 1;
|
|
|
|
|
|
|
|
for (item = option->m_pListItem; item; item = item->m_pNext, numItems++) {
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand votelistsub additem \"%s\" \"callvote %i %i;popmenu 0\"\n",
|
|
|
|
item->m_sItemName.c_str(),
|
|
|
|
index,
|
|
|
|
numItems)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
va("globalwidgetcommand votelistsub additem \"%s\" \"popmenu 0\"\n", VO_LV_ConvertString("[Cancel Vote]"))
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
VO_ExecuteCommand(
|
|
|
|
"globalwidgetcommand votelistsub additem \"Retrieving voting options from server...\" \"popmenu 0\"\n"
|
|
|
|
);
|
|
|
|
VO_SendRemoteCommand("gvo\n");
|
|
|
|
}
|
2023-11-03 21:09:18 +01:00
|
|
|
}
|
|
|
|
#endif
|