1.1 --- a/core/smn_menus.cpp Fri Jul 11 06:51:21 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,1569 +0,0 @@
1.4 -/**
1.5 - * vim: set ts=4 :
1.6 - * =============================================================================
1.7 - * SourceMod
1.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 - * =============================================================================
1.10 - *
1.11 - * This program is free software; you can redistribute it and/or modify it under
1.12 - * the terms of the GNU General Public License, version 3.0, as published by the
1.13 - * Free Software Foundation.
1.14 - *
1.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 - * details.
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License along with
1.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 - *
1.23 - * As a special exception, AlliedModders LLC gives you permission to link the
1.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 - * by the Valve Corporation. You must obey the GNU General Public License in
1.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 - * this exception to all derivative works. AlliedModders LLC defines further
1.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 - * or <http://www.sourcemod.net/license.php>.
1.31 - *
1.32 - * Version: $Id$
1.33 - */
1.34 -
1.35 -#include "sm_globals.h"
1.36 -#include <sh_stack.h>
1.37 -#include "DebugReporter.h"
1.38 -#include "MenuManager.h"
1.39 -#include "MenuStyle_Valve.h"
1.40 -#include "MenuStyle_Radio.h"
1.41 -#include "HandleSys.h"
1.42 -#include "PluginSys.h"
1.43 -#include "PlayerManager.h"
1.44 -#include "sm_stringutil.h"
1.45 -#include "sourcemm_api.h"
1.46 -#if defined MENU_DEBUG
1.47 -#include "Logger.h"
1.48 -#endif
1.49 -#include "ChatTriggers.h"
1.50 -
1.51 -#if defined CreateMenu
1.52 -#undef CreateMenu
1.53 -#endif
1.54 -
1.55 -/**
1.56 - * And God said, "let there be menus," and behold, there were menus.
1.57 - * God saw the menus and they were good. And the evening and the morning
1.58 - * were the third day.
1.59 - */
1.60 -
1.61 -enum MenuAction
1.62 -{
1.63 - MenuAction_Start = (1<<0), /**< A menu has been started (nothing passed) */
1.64 - MenuAction_Display = (1<<1), /**< A menu is about to be displayed (param1=client, param2=MenuPanel Handle) */
1.65 - MenuAction_Select = (1<<2), /**< An item was selected (param1=client, param2=item) */
1.66 - MenuAction_Cancel = (1<<3), /**< The menu was cancelled (param1=client, param2=item) */
1.67 - MenuAction_End = (1<<4), /**< A menu's display/selection cycle is complete (nothing passed). */
1.68 - MenuAction_VoteEnd = (1<<5), /**< (VOTE ONLY): A vote sequence has ended (param1=chosen item) */
1.69 - MenuAction_VoteStart = (1<<6), /**< (VOTE ONLY): A vote sequence has started */
1.70 - MenuAction_VoteCancel = (1<<7), /**< (VOTE ONLY): A vote sequence has been cancelled (nothing passed) */
1.71 - MenuAction_DrawItem = (1<<8), /**< A style is being drawn; return the new style (param1=client, param2=item) */
1.72 - MenuAction_DisplayItem = (1<<9), /**< the odd duck */
1.73 -};
1.74 -
1.75 -class CPanelHandler : public IMenuHandler
1.76 -{
1.77 - friend class MenuNativeHelpers;
1.78 -public:
1.79 - CPanelHandler()
1.80 - {
1.81 - }
1.82 - void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
1.83 - void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
1.84 -private:
1.85 - IPluginFunction *m_pFunc;
1.86 - IPlugin *m_pPlugin;
1.87 -};
1.88 -
1.89 -class CMenuHandler : public IMenuHandler
1.90 -{
1.91 - friend class MenuNativeHelpers;
1.92 -public:
1.93 - CMenuHandler(IPluginFunction *pBasic, int flags);
1.94 -public:
1.95 - void OnMenuStart(IBaseMenu *menu);
1.96 - void OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display);
1.97 - void OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page);
1.98 - void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
1.99 - void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
1.100 - void OnMenuDestroy(IBaseMenu *menu);
1.101 - void OnMenuVoteStart(IBaseMenu *menu);
1.102 - void OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *results);
1.103 - void OnMenuVoteCancel(IBaseMenu *menu, VoteCancelReason reason);
1.104 - void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
1.105 - unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
1.106 - bool OnSetHandlerOption(const char *option, const void *data);
1.107 -#if 0
1.108 - void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
1.109 - void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display);
1.110 -#endif
1.111 -private:
1.112 - cell_t DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res=0);
1.113 -private:
1.114 - IPluginFunction *m_pBasic;
1.115 - int m_Flags;
1.116 - IPluginFunction *m_pVoteResults;
1.117 - cell_t m_fnVoteResult;
1.118 -};
1.119 -
1.120 -/**
1.121 - * GLOBAL CLASS FOR HELPERS
1.122 - */
1.123 -
1.124 -class MenuNativeHelpers :
1.125 - public SMGlobalClass,
1.126 - public IHandleTypeDispatch,
1.127 - public IPluginsListener
1.128 -{
1.129 -public:
1.130 - virtual void OnSourceModAllInitialized()
1.131 - {
1.132 - m_PanelType = g_HandleSys.CreateType("IMenuPanel", this, 0, NULL, NULL, g_pCoreIdent, NULL);
1.133 - m_TempPanelType = g_HandleSys.CreateType("TempIMenuPanel", this, m_PanelType, NULL, NULL, g_pCoreIdent, NULL);
1.134 - g_PluginSys.AddPluginsListener(this);
1.135 - }
1.136 -
1.137 - virtual void OnSourceModShutdown()
1.138 - {
1.139 - g_HandleSys.RemoveType(m_TempPanelType, g_pCoreIdent);
1.140 - g_HandleSys.RemoveType(m_PanelType, g_pCoreIdent);
1.141 -
1.142 - while (!m_FreePanelHandlers.empty())
1.143 - {
1.144 - delete m_FreePanelHandlers.front();
1.145 - m_FreePanelHandlers.pop();
1.146 - }
1.147 -
1.148 - while (!m_FreeMenuHandlers.empty())
1.149 - {
1.150 - delete m_FreeMenuHandlers.front();
1.151 - m_FreeMenuHandlers.pop();
1.152 - }
1.153 - }
1.154 -
1.155 - virtual void OnHandleDestroy(HandleType_t type, void *object)
1.156 - {
1.157 - if (type == m_TempPanelType)
1.158 - {
1.159 - return;
1.160 - }
1.161 -
1.162 - IMenuPanel *panel = (IMenuPanel *)object;
1.163 - panel->DeleteThis();
1.164 - }
1.165 -
1.166 - virtual bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
1.167 - {
1.168 - *pSize = ((IMenuPanel *)object)->GetApproxMemUsage();
1.169 - return true;
1.170 - }
1.171 -
1.172 - /**
1.173 - * It is extremely important that unloaded plugins don't crash.
1.174 - * Thus, if a plugin unloads, we run through every handler we have.
1.175 - * This means we do almost no runtime work for keeping track of
1.176 - * our panel handlers (we don't have to store a list of the running
1.177 - * ones), but when push comes to shove, we have to scan them all
1.178 - * in case any of them are active.
1.179 - */
1.180 - virtual void OnPluginUnloaded(IPlugin *plugin)
1.181 - {
1.182 - for (size_t i = 0; i < m_PanelHandlers.size(); i++)
1.183 - {
1.184 - if (m_PanelHandlers[i]->m_pPlugin == plugin)
1.185 - {
1.186 - m_PanelHandlers[i]->m_pPlugin = NULL;
1.187 - m_PanelHandlers[i]->m_pFunc = NULL;
1.188 - }
1.189 - }
1.190 - }
1.191 -
1.192 - inline HandleType_t GetPanelType()
1.193 - {
1.194 - return m_PanelType;
1.195 - }
1.196 -
1.197 - inline HandleType_t GetTempPanelType()
1.198 - {
1.199 - return m_TempPanelType;
1.200 - }
1.201 -
1.202 - CPanelHandler *GetPanelHandler(IPluginFunction *pFunction)
1.203 - {
1.204 - CPanelHandler *handler;
1.205 - if (m_FreePanelHandlers.empty())
1.206 - {
1.207 - handler = new CPanelHandler;
1.208 - m_PanelHandlers.push_back(handler);
1.209 - } else {
1.210 - handler = m_FreePanelHandlers.front();
1.211 - m_FreePanelHandlers.pop();
1.212 - }
1.213 - handler->m_pFunc = pFunction;
1.214 - handler->m_pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
1.215 - return handler;
1.216 - }
1.217 -
1.218 - void FreePanelHandler(CPanelHandler *handler)
1.219 - {
1.220 - handler->m_pFunc = NULL;
1.221 - handler->m_pPlugin = NULL;
1.222 - m_FreePanelHandlers.push(handler);
1.223 - }
1.224 -
1.225 - CMenuHandler *GetMenuHandler(IPluginFunction *pFunction, int flags)
1.226 - {
1.227 - CMenuHandler *handler;
1.228 - if (m_FreeMenuHandlers.empty())
1.229 - {
1.230 - handler = new CMenuHandler(pFunction, flags);
1.231 - } else {
1.232 - handler = m_FreeMenuHandlers.front();
1.233 - m_FreeMenuHandlers.pop();
1.234 - handler->m_pBasic = pFunction;
1.235 - handler->m_Flags = flags;
1.236 - handler->m_pVoteResults = NULL;
1.237 - }
1.238 - return handler;
1.239 - }
1.240 -
1.241 - void FreeMenuHandler(CMenuHandler *handler)
1.242 - {
1.243 - m_FreeMenuHandlers.push(handler);
1.244 - }
1.245 -
1.246 -private:
1.247 - HandleType_t m_PanelType;
1.248 - HandleType_t m_TempPanelType;
1.249 - CStack<CPanelHandler *> m_FreePanelHandlers;
1.250 - CStack<CMenuHandler *> m_FreeMenuHandlers;
1.251 - CVector<CPanelHandler *> m_PanelHandlers;
1.252 -} g_MenuHelpers;
1.253 -
1.254 -/**
1.255 - * BASIC PANEL HANDLER WRAPPER
1.256 - */
1.257 -
1.258 -void CPanelHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
1.259 -{
1.260 - if (m_pFunc)
1.261 - {
1.262 - m_pFunc->PushCell(BAD_HANDLE);
1.263 - m_pFunc->PushCell(MenuAction_Cancel);
1.264 - m_pFunc->PushCell(client);
1.265 - m_pFunc->PushCell(reason);
1.266 - m_pFunc->Execute(NULL);
1.267 - }
1.268 - g_MenuHelpers.FreePanelHandler(this);
1.269 -}
1.270 -
1.271 -void CPanelHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
1.272 -{
1.273 - if (m_pFunc)
1.274 - {
1.275 - unsigned int old_reply = g_ChatTriggers.SetReplyTo(SM_REPLY_CHAT);
1.276 - m_pFunc->PushCell(BAD_HANDLE);
1.277 - m_pFunc->PushCell(MenuAction_Select);
1.278 - m_pFunc->PushCell(client);
1.279 - m_pFunc->PushCell(item);
1.280 - m_pFunc->Execute(NULL);
1.281 - g_ChatTriggers.SetReplyTo(old_reply);
1.282 - }
1.283 - g_MenuHelpers.FreePanelHandler(this);
1.284 -}
1.285 -
1.286 -static IMenuPanel *s_pCurPanel = NULL;
1.287 -static unsigned int s_CurPanelReturn = 0;
1.288 -static const ItemDrawInfo *s_CurDrawInfo = NULL;
1.289 -static unsigned int *s_CurSelectPosition = NULL;
1.290 -
1.291 -/**
1.292 - * MENU HANDLER WRAPPER
1.293 - */
1.294 -CMenuHandler::CMenuHandler(IPluginFunction *pBasic, int flags) :
1.295 - m_pBasic(pBasic), m_Flags(flags), m_pVoteResults(NULL)
1.296 -{
1.297 - /* :TODO: We can probably cache the handle ahead of time */
1.298 -}
1.299 -
1.300 -void CMenuHandler::OnMenuStart(IBaseMenu *menu)
1.301 -{
1.302 - if ((m_Flags & (int)MenuAction_Start) == (int)MenuAction_Start)
1.303 - {
1.304 - DoAction(menu, MenuAction_Start, 0, 0);
1.305 - }
1.306 -}
1.307 -
1.308 -void CMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *panel)
1.309 -{
1.310 - if ((m_Flags & (int)MenuAction_Display) == (int)MenuAction_Display)
1.311 - {
1.312 - HandleSecurity sec;
1.313 - sec.pIdentity = g_pCoreIdent;
1.314 - sec.pOwner = m_pBasic->GetParentContext()->GetIdentity();
1.315 -
1.316 - HandleAccess access;
1.317 - g_HandleSys.InitAccessDefaults(NULL, &access);
1.318 - access.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
1.319 -
1.320 - Handle_t hndl = g_HandleSys.CreateHandleEx(g_MenuHelpers.GetTempPanelType(), panel, &sec, &access, NULL);
1.321 -
1.322 - DoAction(menu, MenuAction_Display, client, hndl);
1.323 -
1.324 - g_HandleSys.FreeHandle(hndl, &sec);
1.325 - }
1.326 -}
1.327 -
1.328 -void CMenuHandler::OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page)
1.329 -{
1.330 - /* Save old position first. */
1.331 - unsigned int first_item = item_on_page;
1.332 - unsigned int *old_pos = s_CurSelectPosition;
1.333 -
1.334 - s_CurSelectPosition = &first_item;
1.335 -
1.336 - unsigned int old_reply = g_ChatTriggers.SetReplyTo(SM_REPLY_CHAT);
1.337 - DoAction(menu, MenuAction_Select, client, item);
1.338 - g_ChatTriggers.SetReplyTo(old_reply);
1.339 -
1.340 - s_CurSelectPosition = old_pos;
1.341 -}
1.342 -
1.343 -void CMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
1.344 -{
1.345 - unsigned int old_reply = g_ChatTriggers.SetReplyTo(SM_REPLY_CHAT);
1.346 - DoAction(menu, MenuAction_Cancel, client, (cell_t)reason);
1.347 - g_ChatTriggers.SetReplyTo(old_reply);
1.348 -}
1.349 -
1.350 -void CMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
1.351 -{
1.352 - DoAction(menu, MenuAction_End, reason, 0);
1.353 -}
1.354 -
1.355 -void CMenuHandler::OnMenuDestroy(IBaseMenu *menu)
1.356 -{
1.357 - g_MenuHelpers.FreeMenuHandler(this);
1.358 -}
1.359 -
1.360 -void CMenuHandler::OnMenuVoteStart(IBaseMenu *menu)
1.361 -{
1.362 - DoAction(menu, MenuAction_VoteStart, 0, 0);
1.363 -}
1.364 -
1.365 -void CMenuHandler::OnMenuVoteCancel(IBaseMenu *menu, VoteCancelReason reason)
1.366 -{
1.367 - DoAction(menu, MenuAction_VoteCancel, reason, 0);
1.368 -}
1.369 -
1.370 -void CMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
1.371 -{
1.372 - if ((m_Flags & (int)MenuAction_DrawItem) == (int)MenuAction_DrawItem)
1.373 - {
1.374 - cell_t result = DoAction(menu, MenuAction_DrawItem, client, item, style);
1.375 - style = (unsigned int)result;
1.376 - }
1.377 -}
1.378 -
1.379 -unsigned int CMenuHandler::OnMenuDisplayItem(IBaseMenu *menu,
1.380 - int client,
1.381 - IMenuPanel *panel,
1.382 - unsigned int item,
1.383 - const ItemDrawInfo &dr)
1.384 -{
1.385 - if ((m_Flags & (int)MenuAction_DisplayItem) == (int)MenuAction_DisplayItem)
1.386 - {
1.387 - IMenuPanel *oldpanel = s_pCurPanel;
1.388 - unsigned int oldret = s_CurPanelReturn;
1.389 - const ItemDrawInfo *oldinfo = s_CurDrawInfo;
1.390 - s_pCurPanel = panel;
1.391 - s_CurPanelReturn = 0;
1.392 - s_CurDrawInfo = &dr;
1.393 -
1.394 - cell_t res = DoAction(menu, MenuAction_DisplayItem, client, item, 0);
1.395 -
1.396 - if (!res)
1.397 - {
1.398 - res = s_CurPanelReturn;
1.399 - }
1.400 -
1.401 - s_pCurPanel = oldpanel;
1.402 - s_CurPanelReturn = oldret;
1.403 - s_CurDrawInfo = oldinfo;
1.404 -
1.405 - return res;
1.406 - }
1.407 -
1.408 - return 0;
1.409 -}
1.410 -
1.411 -cell_t CMenuHandler::DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res)
1.412 -{
1.413 -#if defined MENU_DEBUG
1.414 - g_Logger.LogMessage("[SM_MENU] CMenuHandler::DoAction() (menu %p/%08x) (action %d) (param1 %d) (param2 %d)",
1.415 - menu,
1.416 - menu->GetHandle(),
1.417 - action,
1.418 - param1,
1.419 - param2);
1.420 -#endif
1.421 - cell_t res = def_res;
1.422 - m_pBasic->PushCell(menu->GetHandle());
1.423 - m_pBasic->PushCell((cell_t)action);
1.424 - m_pBasic->PushCell(param1);
1.425 - m_pBasic->PushCell(param2);
1.426 - m_pBasic->Execute(&res);
1.427 - return res;
1.428 -}
1.429 -
1.430 -void CMenuHandler::OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *results)
1.431 -{
1.432 - if (!m_pVoteResults)
1.433 - {
1.434 - /* Call MenuAction_VoteEnd instead. See if there are any extra winners. */
1.435 - unsigned int num_items = 1;
1.436 - for (unsigned int i=1; i<results->num_items; i++)
1.437 - {
1.438 - if (results->item_list[i].count != results->item_list[0].count)
1.439 - {
1.440 - break;
1.441 - }
1.442 - num_items++;
1.443 - }
1.444 -
1.445 - /* See if we need to pick a random winner. */
1.446 - unsigned int winning_item;
1.447 - if (num_items > 1)
1.448 - {
1.449 - /* Yes, we do. */
1.450 - srand(time(NULL));
1.451 - winning_item = rand() % num_items;
1.452 - winning_item = results->item_list[winning_item].item;
1.453 - } else {
1.454 - /* No, take the first. */
1.455 - winning_item = results->item_list[0].item;
1.456 - }
1.457 -
1.458 - unsigned int total_votes = results->num_votes;
1.459 - unsigned int winning_votes = results->item_list[0].count;
1.460 -
1.461 - DoAction(menu, MenuAction_VoteEnd, winning_item, (total_votes << 16) | (winning_votes & 0xFFFF));
1.462 - } else {
1.463 - IPluginContext *pContext = m_pVoteResults->GetParentContext();
1.464 - bool no_call = false;
1.465 - int err;
1.466 -
1.467 - /* First array */
1.468 - cell_t client_array_address = -1;
1.469 - cell_t *client_array_base = NULL;
1.470 - cell_t client_array_size = results->num_clients + (results->num_clients * 2);
1.471 - if (client_array_size)
1.472 - {
1.473 - if ((err = pContext->HeapAlloc(client_array_size, &client_array_address, &client_array_base))
1.474 - != SP_ERROR_NONE)
1.475 - {
1.476 - g_DbgReporter.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for client list.", client_array_size * sizeof(cell_t));
1.477 - no_call = true;
1.478 - } else {
1.479 - cell_t target_offs = sizeof(cell_t) * results->num_clients;
1.480 - cell_t *cur_index = client_array_base;
1.481 - cell_t *cur_array;
1.482 - for (unsigned int i=0; i<results->num_clients; i++)
1.483 - {
1.484 - /* Copy the array index */
1.485 - *cur_index = target_offs;
1.486 - /* Get the current array address */
1.487 - cur_array = (cell_t *)((char *)cur_index + target_offs);
1.488 - /* Store information */
1.489 - cur_array[0] = results->client_list[i].client;
1.490 - cur_array[1] = results->client_list[i].item;
1.491 - /* Adjust for the new target by subtracting one indirection
1.492 - * and adding one array.
1.493 - */
1.494 - target_offs += (sizeof(cell_t) * 2) - sizeof(cell_t);
1.495 - cur_index++;
1.496 - }
1.497 - }
1.498 - }
1.499 -
1.500 - /* Second array */
1.501 - cell_t item_array_address = -1;
1.502 - cell_t *item_array_base = NULL;
1.503 - cell_t item_array_size = results->num_items + (results->num_items * 2);
1.504 - if (item_array_size)
1.505 - {
1.506 - if ((err = pContext->HeapAlloc(item_array_size, &item_array_address, &item_array_base))
1.507 - != SP_ERROR_NONE)
1.508 - {
1.509 - g_DbgReporter.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for item list.", item_array_size);
1.510 - no_call = true;
1.511 - } else {
1.512 - cell_t target_offs = sizeof(cell_t) * results->num_items;
1.513 - cell_t *cur_index = item_array_base;
1.514 - cell_t *cur_array;
1.515 - for (unsigned int i=0; i<results->num_items; i++)
1.516 - {
1.517 - /* Copy the array index */
1.518 - *cur_index = target_offs;
1.519 - /* Get the current array address */
1.520 - cur_array = (cell_t *)((char *)cur_index + target_offs);
1.521 - /* Store information */
1.522 - cur_array[0] = results->item_list[i].item;
1.523 - cur_array[1] = results->item_list[i].count;
1.524 - /* Adjust for the new target by subtracting one indirection
1.525 - * and adding one array.
1.526 - */
1.527 - target_offs += (sizeof(cell_t) * 2) - sizeof(cell_t);
1.528 - cur_index++;
1.529 - }
1.530 - }
1.531 - }
1.532 -
1.533 - /* Finally, push everything */
1.534 - if (!no_call)
1.535 - {
1.536 - m_pVoteResults->PushCell(menu->GetHandle());
1.537 - m_pVoteResults->PushCell(results->num_votes);
1.538 - m_pVoteResults->PushCell(results->num_clients);
1.539 - m_pVoteResults->PushCell(client_array_address);
1.540 - m_pVoteResults->PushCell(results->num_items);
1.541 - m_pVoteResults->PushCell(item_array_address);
1.542 - m_pVoteResults->Execute(NULL);
1.543 - }
1.544 -
1.545 - /* Free what we allocated, in reverse order as required */
1.546 - if (item_array_address != -1)
1.547 - {
1.548 - pContext->HeapPop(item_array_address);
1.549 - }
1.550 - if (client_array_address != -1)
1.551 - {
1.552 - pContext->HeapPop(client_array_address);
1.553 - }
1.554 - }
1.555 -}
1.556 -
1.557 -bool CMenuHandler::OnSetHandlerOption(const char *option, const void *data)
1.558 -{
1.559 - if (strcmp(option, "set_vote_results_handler") == 0)
1.560 - {
1.561 - void **array = (void **)data;
1.562 - m_pVoteResults = (IPluginFunction *)array[0];
1.563 - m_fnVoteResult = *(cell_t *)((cell_t *)array[1]);
1.564 - return true;
1.565 - }
1.566 -
1.567 - return false;
1.568 -}
1.569 -
1.570 -/**
1.571 - * INLINE FUNCTIONS FOR NATIVES
1.572 - */
1.573 -
1.574 -inline Handle_t MakePanelHandle(IMenuPanel *panel, IPluginContext *pContext)
1.575 -{
1.576 - return g_HandleSys.CreateHandle(g_MenuHelpers.GetPanelType(), panel, pContext->GetIdentity(), g_pCoreIdent, NULL);
1.577 -}
1.578 -
1.579 -inline HandleError ReadPanelHandle(Handle_t hndl, IMenuPanel **panel)
1.580 -{
1.581 - HandleSecurity sec;
1.582 - sec.pIdentity = g_pCoreIdent;
1.583 - sec.pOwner = NULL;
1.584 - return g_HandleSys.ReadHandle(hndl, g_MenuHelpers.GetPanelType(), &sec, (void **)panel);
1.585 -}
1.586 -
1.587 -inline IMenuStyle *GetStyleFromCell(cell_t cell)
1.588 -{
1.589 - enum MenuStyle
1.590 - {
1.591 - MenuStyle_Default = 0, /**< The "default" menu style for the mod */
1.592 - MenuStyle_Valve = 1, /**< The Valve provided menu style (Used on HL2DM) */
1.593 - MenuStyle_Radio = 2, /**< The simpler menu style commonly used on CS:S */
1.594 - };
1.595 -
1.596 - if (cell == MenuStyle_Valve)
1.597 - {
1.598 - return &g_ValveMenuStyle;
1.599 - } else if (cell == MenuStyle_Radio
1.600 - && g_RadioMenuStyle.IsSupported())
1.601 - {
1.602 - return &g_RadioMenuStyle;
1.603 - }
1.604 -
1.605 - return g_Menus.GetDefaultStyle();
1.606 -}
1.607 -
1.608 -/***********************************
1.609 - **** NATIVE DEFINITIONS ***********
1.610 - ***********************************/
1.611 -
1.612 -static cell_t CreateMenu(IPluginContext *pContext, const cell_t *params)
1.613 -{
1.614 - IMenuStyle *style = g_Menus.GetDefaultStyle();
1.615 - IPluginFunction *pFunction;
1.616 -
1.617 - if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
1.618 - {
1.619 - return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
1.620 - }
1.621 -
1.622 - CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[2]);
1.623 - IBaseMenu *menu = style->CreateMenu(handler, pContext->GetIdentity());
1.624 -
1.625 - Handle_t hndl = menu->GetHandle();
1.626 - if (!hndl)
1.627 - {
1.628 - menu->Destroy();
1.629 - return BAD_HANDLE;
1.630 - }
1.631 -
1.632 - return hndl;
1.633 -}
1.634 -
1.635 -static cell_t DisplayMenu(IPluginContext *pContext, const cell_t *params)
1.636 -{
1.637 - Handle_t hndl = (Handle_t)params[1];
1.638 - HandleError err;
1.639 - IBaseMenu *menu;
1.640 -
1.641 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.642 - {
1.643 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.644 - }
1.645 -
1.646 - return menu->Display(params[2], params[3]) ? 1 : 0;
1.647 -}
1.648 -
1.649 -static cell_t DisplayMenuAtItem(IPluginContext *pContext, const cell_t *params)
1.650 -{
1.651 - Handle_t hndl = (Handle_t)params[1];
1.652 - HandleError err;
1.653 - IBaseMenu *menu;
1.654 -
1.655 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.656 - {
1.657 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.658 - }
1.659 -
1.660 - return menu->DisplayAtItem(params[2], params[4], params[3]) ? 1 : 0;
1.661 -}
1.662 -
1.663 -static cell_t VoteMenu(IPluginContext *pContext, const cell_t *params)
1.664 -{
1.665 - if (g_Menus.IsVoteInProgress())
1.666 - {
1.667 - return pContext->ThrowNativeError("A vote is already in progress");
1.668 - }
1.669 -
1.670 - Handle_t hndl = (Handle_t)params[1];
1.671 - HandleError err;
1.672 - IBaseMenu *menu;
1.673 -
1.674 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.675 - {
1.676 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.677 - }
1.678 -
1.679 - cell_t *addr;
1.680 - pContext->LocalToPhysAddr(params[2], &addr);
1.681 -
1.682 - if (!g_Menus.StartVote(menu, params[3], addr, params[4]))
1.683 - {
1.684 - return 0;
1.685 - }
1.686 -
1.687 - return 1;
1.688 -}
1.689 -
1.690 -static cell_t AddMenuItem(IPluginContext *pContext, const cell_t *params)
1.691 -{
1.692 - Handle_t hndl = (Handle_t)params[1];
1.693 - HandleError err;
1.694 - IBaseMenu *menu;
1.695 -
1.696 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.697 - {
1.698 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.699 - }
1.700 -
1.701 - char *info;
1.702 - ItemDrawInfo dr;
1.703 -
1.704 - pContext->LocalToString(params[2], &info);
1.705 - pContext->LocalToString(params[3], (char **)&dr.display);
1.706 - dr.style = params[4];
1.707 -
1.708 - return menu->AppendItem(info, dr) ? 1 : 0;
1.709 -}
1.710 -
1.711 -static cell_t InsertMenuItem(IPluginContext *pContext, const cell_t *params)
1.712 -{
1.713 - Handle_t hndl = (Handle_t)params[1];
1.714 - HandleError err;
1.715 - IBaseMenu *menu;
1.716 -
1.717 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.718 - {
1.719 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.720 - }
1.721 -
1.722 - char *info;
1.723 - ItemDrawInfo dr;
1.724 -
1.725 - pContext->LocalToString(params[3], &info);
1.726 - pContext->LocalToString(params[4], (char **)&dr.display);
1.727 - dr.style = params[5];
1.728 -
1.729 - return menu->InsertItem(params[2], info, dr) ? 1 : 0;
1.730 -}
1.731 -
1.732 -static cell_t RemoveMenuItem(IPluginContext *pContext, const cell_t *params)
1.733 -{
1.734 - Handle_t hndl = (Handle_t)params[1];
1.735 - HandleError err;
1.736 - IBaseMenu *menu;
1.737 -
1.738 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.739 - {
1.740 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.741 - }
1.742 -
1.743 - return menu->RemoveItem(params[2]) ? 1 : 0;
1.744 -}
1.745 -
1.746 -static cell_t RemoveAllMenuItems(IPluginContext *pContext, const cell_t *params)
1.747 -{
1.748 - Handle_t hndl = (Handle_t)params[1];
1.749 - HandleError err;
1.750 - IBaseMenu *menu;
1.751 -
1.752 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.753 - {
1.754 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.755 - }
1.756 -
1.757 - menu->RemoveAllItems();
1.758 -
1.759 - return 1;
1.760 -}
1.761 -
1.762 -static cell_t GetMenuItem(IPluginContext *pContext, const cell_t *params)
1.763 -{
1.764 - Handle_t hndl = (Handle_t)params[1];
1.765 - HandleError err;
1.766 - IBaseMenu *menu;
1.767 -
1.768 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.769 - {
1.770 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.771 - }
1.772 -
1.773 - ItemDrawInfo dr;
1.774 - const char *info;
1.775 -
1.776 - if ((info=menu->GetItemInfo(params[2], &dr)) == NULL)
1.777 - {
1.778 - return 0;
1.779 - }
1.780 -
1.781 - pContext->StringToLocalUTF8(params[3], params[4], info, NULL);
1.782 - pContext->StringToLocalUTF8(params[6], params[7], dr.display ? dr.display : "", NULL);
1.783 -
1.784 - cell_t *addr;
1.785 - pContext->LocalToPhysAddr(params[5], &addr);
1.786 - *addr = dr.style;
1.787 -
1.788 - return 1;
1.789 -}
1.790 -
1.791 -static cell_t SetMenuPagination(IPluginContext *pContext, const cell_t *params)
1.792 -{
1.793 - Handle_t hndl = (Handle_t)params[1];
1.794 - HandleError err;
1.795 - IBaseMenu *menu;
1.796 -
1.797 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.798 - {
1.799 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.800 - }
1.801 -
1.802 - return menu->SetPagination(params[2]) ? 1 : 0;
1.803 -}
1.804 -
1.805 -static cell_t GetMenuPagination(IPluginContext *pContext, const cell_t *params)
1.806 -{
1.807 - Handle_t hndl = (Handle_t)params[1];
1.808 - HandleError err;
1.809 - IBaseMenu *menu;
1.810 -
1.811 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.812 - {
1.813 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.814 - }
1.815 -
1.816 - return menu->GetPagination();
1.817 -}
1.818 -
1.819 -static cell_t GetMenuItemCount(IPluginContext *pContext, const cell_t *params)
1.820 -{
1.821 - Handle_t hndl = (Handle_t)params[1];
1.822 - HandleError err;
1.823 - IBaseMenu *menu;
1.824 -
1.825 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.826 - {
1.827 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.828 - }
1.829 -
1.830 - return menu->GetItemCount();
1.831 -}
1.832 -
1.833 -static cell_t SetMenuTitle(IPluginContext *pContext, const cell_t *params)
1.834 -{
1.835 - Handle_t hndl = (Handle_t)params[1];
1.836 - HandleError err;
1.837 - IBaseMenu *menu;
1.838 -
1.839 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.840 - {
1.841 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.842 - }
1.843 -
1.844 - g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
1.845 -
1.846 - char buffer[1024];
1.847 - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1.848 -
1.849 - menu->SetDefaultTitle(buffer);
1.850 -
1.851 - return 1;
1.852 -}
1.853 -
1.854 -static cell_t GetMenuTitle(IPluginContext *pContext, const cell_t *params)
1.855 -{
1.856 - Handle_t hndl = (Handle_t)params[1];
1.857 - HandleError err;
1.858 - IBaseMenu *menu;
1.859 -
1.860 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.861 - {
1.862 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.863 - }
1.864 -
1.865 - size_t written;
1.866 - const char *title = menu->GetDefaultTitle();
1.867 - pContext->StringToLocalUTF8(params[2], params[3], title, &written);
1.868 -
1.869 - return (cell_t)written;
1.870 -}
1.871 -
1.872 -
1.873 -static cell_t CreatePanelFromMenu(IPluginContext *pContext, const cell_t *params)
1.874 -{
1.875 - Handle_t hndl = (Handle_t)params[1];
1.876 - HandleError err;
1.877 - IBaseMenu *menu;
1.878 -
1.879 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.880 - {
1.881 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.882 - }
1.883 -
1.884 - IMenuPanel *panel = menu->CreatePanel();
1.885 - hndl = MakePanelHandle(panel, pContext);
1.886 - if (!hndl)
1.887 - {
1.888 - panel->DeleteThis();
1.889 - }
1.890 -
1.891 - return hndl;
1.892 -}
1.893 -
1.894 -static cell_t GetMenuExitButton(IPluginContext *pContext, const cell_t *params)
1.895 -{
1.896 - Handle_t hndl = (Handle_t)params[1];
1.897 - HandleError err;
1.898 - IBaseMenu *menu;
1.899 -
1.900 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.901 - {
1.902 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.903 - }
1.904 -
1.905 - return ((menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT) ? 1 : 0;
1.906 -}
1.907 -
1.908 -static cell_t GetMenuExitBackButton(IPluginContext *pContext, const cell_t *params)
1.909 -{
1.910 - Handle_t hndl = (Handle_t)params[1];
1.911 - HandleError err;
1.912 - IBaseMenu *menu;
1.913 -
1.914 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.915 - {
1.916 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.917 - }
1.918 -
1.919 - return ((menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXITBACK) == MENUFLAG_BUTTON_EXIT) ? 1 : 0;
1.920 -}
1.921 -
1.922 -static cell_t SetMenuExitButton(IPluginContext *pContext, const cell_t *params)
1.923 -{
1.924 - Handle_t hndl = (Handle_t)params[1];
1.925 - HandleError err;
1.926 - IBaseMenu *menu;
1.927 -
1.928 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.929 - {
1.930 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.931 - }
1.932 -
1.933 - unsigned int flags = menu->GetMenuOptionFlags();
1.934 -
1.935 - if (params[2])
1.936 - {
1.937 - flags |= MENUFLAG_BUTTON_EXIT;
1.938 - } else {
1.939 - flags &= ~MENUFLAG_BUTTON_EXIT;
1.940 - }
1.941 -
1.942 - menu->SetMenuOptionFlags(flags);
1.943 - unsigned int new_flags = menu->GetMenuOptionFlags();
1.944 -
1.945 - return (flags == new_flags);
1.946 -}
1.947 -
1.948 -static cell_t SetMenuExitBackButton(IPluginContext *pContext, const cell_t *params)
1.949 -{
1.950 - Handle_t hndl = (Handle_t)params[1];
1.951 - HandleError err;
1.952 - IBaseMenu *menu;
1.953 -
1.954 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.955 - {
1.956 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.957 - }
1.958 -
1.959 - unsigned int flags = menu->GetMenuOptionFlags();
1.960 -
1.961 - if (params[2])
1.962 - {
1.963 - flags |= MENUFLAG_BUTTON_EXITBACK;
1.964 - } else {
1.965 - flags &= ~MENUFLAG_BUTTON_EXITBACK;
1.966 - }
1.967 -
1.968 - menu->SetMenuOptionFlags(flags);
1.969 -
1.970 - return 1;
1.971 -}
1.972 -
1.973 -static cell_t CancelMenu(IPluginContext *pContext, const cell_t *params)
1.974 -{
1.975 - Handle_t hndl = (Handle_t)params[1];
1.976 - HandleError err;
1.977 - IBaseMenu *menu;
1.978 -
1.979 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.980 - {
1.981 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.982 - }
1.983 -
1.984 - g_Menus.CancelMenu(menu);
1.985 -
1.986 - return 1;
1.987 -}
1.988 -
1.989 -static cell_t IsVoteInProgress(IPluginContext *pContext, const cell_t *params)
1.990 -{
1.991 - return g_Menus.IsVoteInProgress() ? 1 : 0;
1.992 -}
1.993 -
1.994 -static cell_t GetMenuStyle(IPluginContext *pContext, const cell_t *params)
1.995 -{
1.996 - Handle_t hndl = (Handle_t)params[1];
1.997 - HandleError err;
1.998 - IBaseMenu *menu;
1.999 -
1.1000 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.1001 - {
1.1002 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1003 - }
1.1004 -
1.1005 - return menu->GetDrawStyle()->GetHandle();
1.1006 -}
1.1007 -
1.1008 -static cell_t GetMenuStyleHandle(IPluginContext *pContext, const cell_t *params)
1.1009 -{
1.1010 - IMenuStyle *style = GetStyleFromCell(params[1]);
1.1011 - if (!style)
1.1012 - {
1.1013 - return BAD_HANDLE;
1.1014 - }
1.1015 -
1.1016 - return style->GetHandle();
1.1017 -}
1.1018 -
1.1019 -static cell_t CreatePanel(IPluginContext *pContext, const cell_t *params)
1.1020 -{
1.1021 - Handle_t hndl = (Handle_t)params[1];
1.1022 - HandleError err;
1.1023 - IMenuStyle *style;
1.1024 -
1.1025 - if (hndl != 0)
1.1026 - {
1.1027 - if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
1.1028 - {
1.1029 - return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
1.1030 - }
1.1031 - } else {
1.1032 - style = g_Menus.GetDefaultStyle();
1.1033 - }
1.1034 -
1.1035 - IMenuPanel *panel = style->CreatePanel();
1.1036 -
1.1037 - hndl = MakePanelHandle(panel, pContext);
1.1038 - if (!hndl)
1.1039 - {
1.1040 - panel->DeleteThis();
1.1041 - return BAD_HANDLE;
1.1042 - }
1.1043 -
1.1044 - return hndl;
1.1045 -}
1.1046 -
1.1047 -static cell_t CreateMenuEx(IPluginContext *pContext, const cell_t *params)
1.1048 -{
1.1049 - Handle_t hndl = (Handle_t)params[1];
1.1050 - HandleError err;
1.1051 - IMenuStyle *style;
1.1052 -
1.1053 - if (hndl != 0)
1.1054 - {
1.1055 - if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
1.1056 - {
1.1057 - return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
1.1058 - }
1.1059 - } else {
1.1060 - style = g_Menus.GetDefaultStyle();
1.1061 - }
1.1062 -
1.1063 - IPluginFunction *pFunction;
1.1064 - if ((pFunction=pContext->GetFunctionById(params[2])) == NULL)
1.1065 - {
1.1066 - return pContext->ThrowNativeError("Function id %x is invalid", params[2]);
1.1067 - }
1.1068 -
1.1069 - CMenuHandler *handler = g_MenuHelpers.GetMenuHandler(pFunction, params[3]);
1.1070 -
1.1071 - IBaseMenu *pMenu = style->CreateMenu(handler, pContext->GetIdentity());
1.1072 - hndl = pMenu->GetHandle();
1.1073 - if (!hndl)
1.1074 - {
1.1075 - pMenu->Destroy();
1.1076 - return BAD_HANDLE;
1.1077 - }
1.1078 -
1.1079 - return hndl;
1.1080 -}
1.1081 -
1.1082 -static cell_t GetClientMenu(IPluginContext *pContext, const cell_t *params)
1.1083 -{
1.1084 - Handle_t hndl = (Handle_t)params[2];
1.1085 - HandleError err;
1.1086 - IMenuStyle *style;
1.1087 -
1.1088 - if (hndl != 0)
1.1089 - {
1.1090 - if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
1.1091 - {
1.1092 - return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
1.1093 - }
1.1094 - } else {
1.1095 - style = g_Menus.GetDefaultStyle();
1.1096 - }
1.1097 -
1.1098 - return style->GetClientMenu(params[1], NULL);
1.1099 -}
1.1100 -
1.1101 -static cell_t CancelClientMenu(IPluginContext *pContext, const cell_t *params)
1.1102 -{
1.1103 - Handle_t hndl = (Handle_t)params[3];
1.1104 - HandleError err;
1.1105 - IMenuStyle *style;
1.1106 -
1.1107 - if (hndl != 0)
1.1108 - {
1.1109 - if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
1.1110 - {
1.1111 - return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
1.1112 - }
1.1113 - } else {
1.1114 - style = g_Menus.GetDefaultStyle();
1.1115 - }
1.1116 -
1.1117 - return style->CancelClientMenu(params[1], params[2] ? true : false) ? 1 : 0;
1.1118 -}
1.1119 -
1.1120 -static cell_t GetMaxPageItems(IPluginContext *pContext, const cell_t *params)
1.1121 -{
1.1122 - Handle_t hndl = (Handle_t)params[1];
1.1123 - HandleError err;
1.1124 - IMenuStyle *style;
1.1125 -
1.1126 - if (hndl != 0)
1.1127 - {
1.1128 - if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
1.1129 - {
1.1130 - return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
1.1131 - }
1.1132 - } else {
1.1133 - style = g_Menus.GetDefaultStyle();
1.1134 - }
1.1135 -
1.1136 - return style->GetMaxPageItems();
1.1137 -}
1.1138 -
1.1139 -static cell_t GetPanelStyle(IPluginContext *pContext, const cell_t *params)
1.1140 -{
1.1141 - Handle_t hndl = (Handle_t)params[1];
1.1142 - HandleError err;
1.1143 - IMenuPanel *panel;
1.1144 -
1.1145 - if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
1.1146 - {
1.1147 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1148 - }
1.1149 -
1.1150 - return panel->GetParentStyle()->GetHandle();
1.1151 -}
1.1152 -
1.1153 -static cell_t SetPanelTitle(IPluginContext *pContext, const cell_t *params)
1.1154 -{
1.1155 - Handle_t hndl = (Handle_t)params[1];
1.1156 - HandleError err;
1.1157 - IMenuPanel *panel;
1.1158 -
1.1159 - if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
1.1160 - {
1.1161 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1162 - }
1.1163 -
1.1164 - char *text;
1.1165 - pContext->LocalToString(params[2], &text);
1.1166 -
1.1167 - panel->DrawTitle(text, params[3] ? true : false);
1.1168 -
1.1169 - return 1;
1.1170 -}
1.1171 -
1.1172 -static cell_t DrawPanelItem(IPluginContext *pContext, const cell_t *params)
1.1173 -{
1.1174 - Handle_t hndl = (Handle_t)params[1];
1.1175 - HandleError err;
1.1176 - IMenuPanel *panel;
1.1177 -
1.1178 - if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
1.1179 - {
1.1180 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1181 - }
1.1182 -
1.1183 - ItemDrawInfo dr;
1.1184 - pContext->LocalToString(params[2], (char **)&dr.display);
1.1185 - dr.style = params[3];
1.1186 -
1.1187 - return panel->DrawItem(dr);
1.1188 -}
1.1189 -
1.1190 -static cell_t DrawPanelText(IPluginContext *pContext, const cell_t *params)
1.1191 -{
1.1192 - Handle_t hndl = (Handle_t)params[1];
1.1193 - HandleError err;
1.1194 - IMenuPanel *panel;
1.1195 -
1.1196 - if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
1.1197 - {
1.1198 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1199 - }
1.1200 -
1.1201 - char *text;
1.1202 - pContext->LocalToString(params[2], &text);
1.1203 -
1.1204 - return panel->DrawRawLine(text) ? 1 : 0;
1.1205 -}
1.1206 -
1.1207 -static cell_t CanPanelDrawFlags(IPluginContext *pContext, const cell_t *params)
1.1208 -{
1.1209 - Handle_t hndl = (Handle_t)params[1];
1.1210 - HandleError err;
1.1211 - IMenuPanel *panel;
1.1212 -
1.1213 - if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
1.1214 - {
1.1215 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1216 - }
1.1217 -
1.1218 - return panel->CanDrawItem(params[2]);
1.1219 -}
1.1220 -
1.1221 -static cell_t SendPanelToClient(IPluginContext *pContext, const cell_t *params)
1.1222 -{
1.1223 - Handle_t hndl = (Handle_t)params[1];
1.1224 - HandleError err;
1.1225 - IMenuPanel *panel;
1.1226 -
1.1227 - if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
1.1228 - {
1.1229 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1230 - }
1.1231 -
1.1232 - IPluginFunction *pFunction;
1.1233 - if ((pFunction=pContext->GetFunctionById(params[3])) == NULL)
1.1234 - {
1.1235 - return pContext->ThrowNativeError("Function id %x is invalid", params[3]);
1.1236 - }
1.1237 -
1.1238 - CPanelHandler *handler = g_MenuHelpers.GetPanelHandler(pFunction);
1.1239 - if (!panel->SendDisplay(params[2], handler, params[4]))
1.1240 - {
1.1241 - g_MenuHelpers.FreePanelHandler(handler);
1.1242 - }
1.1243 -
1.1244 - return 1;
1.1245 -}
1.1246 -
1.1247 -static cell_t SetPanelKeys(IPluginContext *pContext, const cell_t *params)
1.1248 -{
1.1249 - Handle_t hndl = (Handle_t)params[1];
1.1250 - HandleError err;
1.1251 - IMenuPanel *panel;
1.1252 -
1.1253 - if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
1.1254 - {
1.1255 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1256 - }
1.1257 -
1.1258 - return panel->SetSelectableKeys(params[2]);
1.1259 -}
1.1260 -
1.1261 -static cell_t GetPanelCurrentKey(IPluginContext *pContext, const cell_t *params)
1.1262 -{
1.1263 - Handle_t hndl = (Handle_t)params[1];
1.1264 - HandleError err;
1.1265 - IMenuPanel *panel;
1.1266 -
1.1267 - if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
1.1268 - {
1.1269 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1270 - }
1.1271 -
1.1272 - return panel->GetCurrentKey();
1.1273 -}
1.1274 -
1.1275 -static cell_t GetPanelTextRemaining(IPluginContext *pContext, const cell_t *params)
1.1276 -{
1.1277 - Handle_t hndl = (Handle_t)params[1];
1.1278 - HandleError err;
1.1279 - IMenuPanel *panel;
1.1280 -
1.1281 - if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
1.1282 - {
1.1283 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1284 - }
1.1285 -
1.1286 - return panel->GetAmountRemaining();
1.1287 -}
1.1288 -
1.1289 -static cell_t SetPanelCurrentKey(IPluginContext *pContext, const cell_t *params)
1.1290 -{
1.1291 - Handle_t hndl = (Handle_t)params[1];
1.1292 - HandleError err;
1.1293 - IMenuPanel *panel;
1.1294 -
1.1295 - if ((err=ReadPanelHandle(hndl, &panel)) != HandleError_None)
1.1296 - {
1.1297 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1298 - }
1.1299 -
1.1300 - return panel->SetCurrentKey(params[2]) ? 1 : 0;
1.1301 -}
1.1302 -
1.1303 -static cell_t RedrawMenuItem(IPluginContext *pContext, const cell_t *params)
1.1304 -{
1.1305 - if (!s_pCurPanel)
1.1306 - {
1.1307 - return pContext->ThrowNativeError("You can only call this once from a MenuAction_DisplayItem callback");
1.1308 - }
1.1309 -
1.1310 - char *str;
1.1311 - pContext->LocalToString(params[1], &str);
1.1312 -
1.1313 - ItemDrawInfo dr = *s_CurDrawInfo;
1.1314 - dr.display = str;
1.1315 -
1.1316 - if ((s_CurPanelReturn = s_pCurPanel->DrawItem(dr)) != 0)
1.1317 - {
1.1318 - s_pCurPanel = NULL;
1.1319 - }
1.1320 -
1.1321 - return s_CurPanelReturn;
1.1322 -}
1.1323 -
1.1324 -static cell_t GetMenuOptionFlags(IPluginContext *pContext, const cell_t *params)
1.1325 -{
1.1326 - Handle_t hndl = (Handle_t)params[1];
1.1327 - HandleError err;
1.1328 - IBaseMenu *menu;
1.1329 -
1.1330 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.1331 - {
1.1332 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1333 - }
1.1334 -
1.1335 - return menu->GetMenuOptionFlags();
1.1336 -}
1.1337 -
1.1338 -static cell_t SetMenuOptionFlags(IPluginContext *pContext, const cell_t *params)
1.1339 -{
1.1340 - Handle_t hndl = (Handle_t)params[1];
1.1341 - HandleError err;
1.1342 - IBaseMenu *menu;
1.1343 -
1.1344 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.1345 - {
1.1346 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1347 - }
1.1348 -
1.1349 - menu->SetMenuOptionFlags(params[2]);
1.1350 -
1.1351 - return 1;
1.1352 -}
1.1353 -
1.1354 -static cell_t CancelVote(IPluginContext *pContxt, const cell_t *params)
1.1355 -{
1.1356 - if (!g_Menus.IsVoteInProgress())
1.1357 - {
1.1358 - return pContxt->ThrowNativeError("No vote is in progress");
1.1359 - }
1.1360 -
1.1361 - g_Menus.CancelVoting();
1.1362 -
1.1363 - return 1;
1.1364 -}
1.1365 -
1.1366 -static cell_t SetVoteResultCallback(IPluginContext *pContext, const cell_t *params)
1.1367 -{
1.1368 - Handle_t hndl = (Handle_t)params[1];
1.1369 - HandleError err;
1.1370 - IBaseMenu *menu;
1.1371 -
1.1372 - if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
1.1373 - {
1.1374 - return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
1.1375 - }
1.1376 -
1.1377 - IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
1.1378 - if (!pFunction)
1.1379 - {
1.1380 - return pContext->ThrowNativeError("Invalid function %x", params[2]);
1.1381 - }
1.1382 -
1.1383 - void *array[2];
1.1384 - array[0] = pFunction;
1.1385 - array[1] = (void *)¶ms[2];
1.1386 -
1.1387 - IMenuHandler *pHandler = menu->GetHandler();
1.1388 - if (!pHandler->OnSetHandlerOption("set_vote_results_handler", (const void *)array))
1.1389 - {
1.1390 - return pContext->ThrowNativeError("The given menu does not support this option");
1.1391 - }
1.1392 -
1.1393 - return 1;
1.1394 -}
1.1395 -
1.1396 -static cell_t CheckVoteDelay(IPluginContext *pContext, const cell_t *params)
1.1397 -{
1.1398 - return g_Menus.GetRemainingVoteDelay();
1.1399 -}
1.1400 -
1.1401 -static cell_t GetMenuSelectionPosition(IPluginContext *pContext, const cell_t *params)
1.1402 -{
1.1403 - if (!s_CurSelectPosition)
1.1404 - {
1.1405 - return pContext->ThrowNativeError("Can only be called from inside a MenuAction_Select callback");
1.1406 - }
1.1407 -
1.1408 - return *s_CurSelectPosition;
1.1409 -}
1.1410 -
1.1411 -static cell_t IsClientInVotePool(IPluginContext *pContext, const cell_t *params)
1.1412 -{
1.1413 - int client;
1.1414 - IGamePlayer *pPlayer;
1.1415 -
1.1416 - client = params[1];
1.1417 - if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
1.1418 - {
1.1419 - return pContext->ThrowNativeError("Invalid client index %d", client);
1.1420 - }
1.1421 -
1.1422 - if (!g_Menus.IsVoteInProgress())
1.1423 - {
1.1424 - return pContext->ThrowNativeError("No vote is in progress");
1.1425 - }
1.1426 -
1.1427 - return g_Menus.IsClientInVotePool(client) ? 1 : 0;
1.1428 -}
1.1429 -
1.1430 -static cell_t RedrawClientVoteMenu(IPluginContext *pContext, const cell_t *params)
1.1431 -{
1.1432 - int client;
1.1433 - IGamePlayer *pPlayer;
1.1434 -
1.1435 - client = params[1];
1.1436 - if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
1.1437 - {
1.1438 - return pContext->ThrowNativeError("Invalid client index %d", client);
1.1439 - }
1.1440 -
1.1441 - if (!g_Menus.IsVoteInProgress())
1.1442 - {
1.1443 - return pContext->ThrowNativeError("No vote is in progress");
1.1444 - }
1.1445 -
1.1446 - if (!g_Menus.IsClientInVotePool(client))
1.1447 - {
1.1448 - return pContext->ThrowNativeError("Client is not in the voting pool");
1.1449 - }
1.1450 -
1.1451 - return g_Menus.RedrawClientVoteMenu(client) ? 1 : 0;
1.1452 -}
1.1453 -
1.1454 -class EmptyMenuHandler : public IMenuHandler
1.1455 -{
1.1456 -public:
1.1457 -} s_EmptyMenuHandler;
1.1458 -
1.1459 -static cell_t InternalShowMenu(IPluginContext *pContext, const cell_t *params)
1.1460 -{
1.1461 - int client = params[1];
1.1462 - CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1.1463 -
1.1464 - if (pPlayer == NULL)
1.1465 - {
1.1466 - return pContext->ThrowNativeError("Invalid client index %d", client);
1.1467 - }
1.1468 - else if (!pPlayer->IsInGame())
1.1469 - {
1.1470 - return pContext->ThrowNativeError("Client %d is not in game", client);
1.1471 - }
1.1472 -
1.1473 - if (!g_RadioMenuStyle.IsSupported())
1.1474 - {
1.1475 - return pContext->ThrowNativeError("Radio menus are not supported on this mod");
1.1476 - }
1.1477 -
1.1478 - char *str;
1.1479 - pContext->LocalToString(params[2], &str);
1.1480 -
1.1481 - IMenuPanel *pPanel = g_RadioMenuStyle.MakeRadioDisplay(str, params[4]);
1.1482 -
1.1483 - if (pPanel == NULL)
1.1484 - {
1.1485 - return 0;
1.1486 - }
1.1487 -
1.1488 - IMenuHandler *pHandler;
1.1489 - CPanelHandler *pActualHandler = NULL;
1.1490 - if (params[5] != -1)
1.1491 - {
1.1492 - IPluginFunction *pFunction = pContext->GetFunctionById(params[5]);
1.1493 - if (pFunction == NULL)
1.1494 - {
1.1495 - return pContext->ThrowNativeError("Invalid function index %x", params[5]);
1.1496 - }
1.1497 - pActualHandler = g_MenuHelpers.GetPanelHandler(pFunction);
1.1498 - }
1.1499 -
1.1500 - if (pActualHandler == NULL)
1.1501 - {
1.1502 - pHandler = &s_EmptyMenuHandler;
1.1503 - }
1.1504 - else
1.1505 - {
1.1506 - pHandler = pActualHandler;
1.1507 - }
1.1508 -
1.1509 - bool bSuccess = pPanel->SendDisplay(client, pHandler, params[3]);
1.1510 -
1.1511 - pPanel->DeleteThis();
1.1512 -
1.1513 - if (!bSuccess && pActualHandler != NULL)
1.1514 - {
1.1515 - g_MenuHelpers.FreePanelHandler(pActualHandler);
1.1516 - }
1.1517 -
1.1518 - return bSuccess ? 1 : 0;
1.1519 -}
1.1520 -
1.1521 -REGISTER_NATIVES(menuNatives)
1.1522 -{
1.1523 - {"AddMenuItem", AddMenuItem},
1.1524 - {"CanPanelDrawFlags", CanPanelDrawFlags},
1.1525 - {"CancelClientMenu", CancelClientMenu},
1.1526 - {"CancelMenu", CancelMenu},
1.1527 - {"CancelVote", CancelVote},
1.1528 - {"CheckVoteDelay", CheckVoteDelay},
1.1529 - {"CreateMenu", CreateMenu},
1.1530 - {"CreateMenuEx", CreateMenuEx},
1.1531 - {"CreatePanel", CreatePanel},
1.1532 - {"CreatePanelFromMenu", CreatePanelFromMenu},
1.1533 - {"DisplayMenu", DisplayMenu},
1.1534 - {"DisplayMenuAtItem", DisplayMenuAtItem},
1.1535 - {"DrawPanelItem", DrawPanelItem},
1.1536 - {"DrawPanelText", DrawPanelText},
1.1537 - {"GetClientMenu", GetClientMenu},
1.1538 - {"GetMaxPageItems", GetMaxPageItems},
1.1539 - {"GetMenuExitBackButton", GetMenuExitBackButton},
1.1540 - {"GetMenuExitButton", GetMenuExitButton},
1.1541 - {"GetMenuItem", GetMenuItem},
1.1542 - {"GetMenuItemCount", GetMenuItemCount},
1.1543 - {"GetMenuOptionFlags", GetMenuOptionFlags},
1.1544 - {"GetMenuPagination", GetMenuPagination},
1.1545 - {"GetMenuSelectionPosition",GetMenuSelectionPosition},
1.1546 - {"GetMenuStyle", GetMenuStyle},
1.1547 - {"GetMenuStyleHandle", GetMenuStyleHandle},
1.1548 - {"GetMenuTitle", GetMenuTitle},
1.1549 - {"GetPanelTextRemaining", GetPanelTextRemaining},
1.1550 - {"GetPanelCurrentKey", GetPanelCurrentKey},
1.1551 - {"GetPanelStyle", GetPanelStyle},
1.1552 - {"InsertMenuItem", InsertMenuItem},
1.1553 - {"InternalShowMenu", InternalShowMenu},
1.1554 - {"IsClientInVotePool", IsClientInVotePool},
1.1555 - {"IsVoteInProgress", IsVoteInProgress},
1.1556 - {"RedrawClientVoteMenu", RedrawClientVoteMenu},
1.1557 - {"RedrawMenuItem", RedrawMenuItem},
1.1558 - {"RemoveAllMenuItems", RemoveAllMenuItems},
1.1559 - {"RemoveMenuItem", RemoveMenuItem},
1.1560 - {"SendPanelToClient", SendPanelToClient},
1.1561 - {"SetMenuExitBackButton", SetMenuExitBackButton},
1.1562 - {"SetMenuExitButton", SetMenuExitButton},
1.1563 - {"SetMenuOptionFlags", SetMenuOptionFlags},
1.1564 - {"SetMenuPagination", SetMenuPagination},
1.1565 - {"SetMenuTitle", SetMenuTitle},
1.1566 - {"SetPanelCurrentKey", SetPanelCurrentKey},
1.1567 - {"SetPanelTitle", SetPanelTitle},
1.1568 - {"SetPanelKeys", SetPanelKeys},
1.1569 - {"SetVoteResultCallback", SetVoteResultCallback},
1.1570 - {"VoteMenu", VoteMenu},
1.1571 - {NULL, NULL},
1.1572 -};