From 03eeb23ab3c72f6f92a7b8057822d1273a62d2b2 Mon Sep 17 00:00:00 2001 From: BotoX Date: Wed, 25 Sep 2019 20:26:08 +0200 Subject: [PATCH] Implement per-client randomized menus with MenuShufflePerClient native. Add MenuSetClientMapping native. --- core/MenuStyle_Base.cpp | 88 +++++++++++++++++++++++++++++++++-------- core/MenuStyle_Base.h | 12 +++--- 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/core/MenuStyle_Base.cpp b/core/MenuStyle_Base.cpp index b35142fc..07e6d435 100644 --- a/core/MenuStyle_Base.cpp +++ b/core/MenuStyle_Base.cpp @@ -8,7 +8,7 @@ * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License, version 3.0, as published by the * Free Software Foundation. - * + * * This program 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 @@ -99,7 +99,7 @@ void BaseMenuStyle::_CancelClientMenu(int client, MenuCancelReason reason, bool /* Fire callbacks */ mh->OnMenuCancel(menu, client, reason); - + /* Only fire end if there's a valid menu */ if (menu) { @@ -214,7 +214,7 @@ void BaseMenuStyle::ProcessWatchList() } #if defined MENU_DEBUG - logger->LogMessage("BaseMenuStyle::ProcessWatchList(%d,%d,%d,%d,%d,%p)", + logger->LogMessage("BaseMenuStyle::ProcessWatchList(%d,%d,%d,%d,%d,%p)", m_WatchList.m_Size, m_WatchList.m_FirstLink, m_WatchList.m_FreeNodes, @@ -302,7 +302,7 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press) ItemSelection type = states.slots[key_press].type; /* Check if we should play a sound about the type */ - if (g_Menus.MenuSoundsEnabled() && + if (g_Menus.MenuSoundsEnabled() && (!menu || (menu->GetMenuOptionFlags() & MENUFLAG_NO_SOUND) != MENUFLAG_NO_SOUND)) { CellRecipientFilter filter; @@ -323,21 +323,21 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press) if (pCollideable) { const Vector & pos = pCollideable->GetCollisionOrigin(); - enginesound->EmitSound(filter, - client, - CHAN_AUTO, + enginesound->EmitSound(filter, + client, + CHAN_AUTO, #if SOURCE_ENGINE >= SE_PORTAL2 sound->c_str(), - -1, + -1, #endif sound->c_str(), - VOL_NORM, - ATTN_NORM, + VOL_NORM, + ATTN_NORM, #if SOURCE_ENGINE >= SE_PORTAL2 - 0, + 0, #endif - 0, - PITCH_NORM, + 0, + PITCH_NORM, #if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS \ || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_PVKII 0, @@ -604,9 +604,9 @@ bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order) return true; } -CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) : -m_pStyle(pStyle), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false), -m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false), +CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) : +m_pStyle(pStyle), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false), +m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false), m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT) { } @@ -754,6 +754,62 @@ unsigned int CBaseMenu::GetRealItemIndex(int client, unsigned int position) return position; } +void CBaseMenu::ShufflePerClient(int start, int stop) +{ + // limit map len to 255 items since it's using uint8 + int length = MIN(GetItemCount(), 255); + if (stop >= 0) + length = MIN(length, stop); + + for (int i = 1; i < SM_MAXPLAYERS + 1; i++) + { + // populate per-client map ... + m_RandomMaps[i].resize(length); + for (int j = 0; j < length; j++) + m_RandomMaps[i][j] = j; + + // ... and random shuffle it + for (int j = length - 1; j > start; j--) + { + int x = rand() % (j - start + 1) + start; + uint8_t tmp = m_RandomMaps[i][x]; + m_RandomMaps[i][x] = m_RandomMaps[i][j]; + m_RandomMaps[i][j] = tmp; + } + } +} + +void CBaseMenu::SetClientMapping(int client, int *array, int length) +{ + length = MIN(length, 255); + m_RandomMaps[client].resize(length); + for (int i = 0; i < length; i++) + { + m_RandomMaps[client][i] = array[i]; + } +} + +bool CBaseMenu::IsPerClientShuffled() +{ + for (int i = 1; i < SM_MAXPLAYERS + 1; i++) + { + if(m_RandomMaps[i].length() > 0) + return true; + } + return false; +} + +unsigned int CBaseMenu::GetRealItemIndex(int client, unsigned int position) +{ + if (client > 0 && position < m_RandomMaps[client].length()) + { + position = m_RandomMaps[client][position]; + return m_items[position].index; + } + + return position; +} + unsigned int CBaseMenu::GetItemCount() { return m_items.size(); diff --git a/core/MenuStyle_Base.h b/core/MenuStyle_Base.h index 43ae0e63..16f32c1e 100644 --- a/core/MenuStyle_Base.h +++ b/core/MenuStyle_Base.h @@ -8,7 +8,7 @@ * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License, version 3.0, as published by the * Free Software Foundation. - * + * * This program 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 @@ -98,7 +98,7 @@ public: class CBaseMenu; -class BaseMenuStyle : +class BaseMenuStyle : public IMenuStyle, public IClientListener { @@ -113,11 +113,11 @@ public: //IClientListener public: //what derived must implement virtual CBaseMenuPlayer *GetMenuPlayer(int client) =0; virtual void SendDisplay(int client, IMenuPanel *display) =0; -public: //what derived may implement - virtual bool DoClientMenu(int client, - CBaseMenu *menu, +public: //what derived may implement + virtual bool DoClientMenu(int client, + CBaseMenu *menu, unsigned int first_item, - IMenuHandler *mh, + IMenuHandler *mh, unsigned int time); virtual bool DoClientMenu(int client, IMenuPanel *menu, IMenuHandler *mh, unsigned int time); virtual void AddClientToWatch(int client);