Compare commits

...

76 Commits

Author SHA1 Message Date
BotoX
078e754a82 fix AMTL for dhooks2 2019-09-21 22:15:03 +02:00
BotoX
a776c14cf8 fix rare crash bug in SDKTools GetGameRulesProxyEnt 2019-09-21 21:39:35 +02:00
BotoX
bd296a27f8 Add OnEntitySpawned to SDKHooks. 2019-09-21 21:38:56 +02:00
BotoX
2e9619ff67 Implement per-client randomized menus with MenuShufflePerClient native.
Add MenuSetClientMapping native.

fix remaining issues
2019-09-21 21:20:53 +02:00
BotoX
67a0d18ce7 Changes on sm_*say 2019-09-21 21:16:43 +02:00
BotoX
c5428a8726 Fix HookEntityOutput/HookSingleEntityOutput bugs in sdktools. 2019-09-21 21:15:57 +02:00
BotoX
8db2132856 cstrike: Fix wrong timeleft calculation (#1072)
* Fix wrong timeleft calculation

* reorder function calls
2019-09-21 21:15:44 +02:00
BotoX
2e28df3dc6 Add GetClientIClient native. 2019-09-21 21:14:14 +02:00
Obuss
b362abf4b2 Logging changes to various base plugins. 2019-09-21 21:13:15 +02:00
BotoX
da1cd9eb11 Extend function calling API for natives and allow catching exceptions.
Change sourcepawn url.
2019-09-21 21:12:29 +02:00
BotoX
82628cfc5a Avoid losing console messages.
Buffers up to 16k bytes of SVC_Print if buffer would overflow, then sends chunks every frame.
Sends up to 2048 bytes per frame and does not split messages.
2019-09-21 20:38:53 +02:00
BotoX
690b3c5a28 Fix @spec not targeting clients in unassigned team. 2019-09-21 20:30:04 +02:00
BotoX
865fa37ed9 Added hack to make plugins open a menu with all possible targets on ReplyToTargetError COMMAND_TARGET_AMBIGUOUS.
Explanation:
There are two clients in the server, one named gene, the other one "Ene ~special characters~".
An admin issues "sm_slay Ene" and gets following error message: More than one client matched the given pattern.
What this hack will do is: Use GetCmdArg(0, ...); to get the command name "sm_slay".
Use GetCmdArgString(...); to get the arguments supplied to the command.
Use GetLastProcessTargetString(...); (which was implemented in this commit) to retrieve the arguments that were passed to the last ProcessTargetString call.
It will then pass this data to the DynamicTargeting plugin through its AmbiguousMenu native.
The plugin will open up a menu on the client and list all targets which match the pattern that was supplied to ProcessTargetString.
If the client selects a menu entry, FakeClientCommand will be used to re-execute the command with the correct target.
2019-09-21 20:29:53 +02:00
BotoX
6fae1811d9 Added client id to MultiTargetFilter forward. 2019-09-21 20:29:27 +02:00
BotoX
7b476e4532 Add more macros to CDetour. 2019-09-21 20:20:37 +02:00
BotoX
ba7fedca6e Remove -Werror, does not compile on GCC due to warning in source SDK. 2019-09-21 20:20:21 +02:00
Asher Baker
b2b29cb33f Fix build with latest hl2sdk-csgo 2019-09-02 21:45:47 +01:00
Bruno Ronning
c5efe48aa3 Update CS:GO "Reload" offset. (#1011)
(cherry picked from commit d7990596f9)
2019-05-14 19:01:14 -04:00
PerfectLaugh
c2d4643204 Remove unneeded paramter in CS_DropWeapon (#988)
Updated in 4/30/2019 csgo update
2019-05-01 15:11:22 -07:00
Nick Hastings
328fbf3f19 Update Linux CSWeaponDropBB signature. 2019-05-01 15:07:06 -07:00
Michael Flaherty
b5119201ff Revert "Update CS:GO CSWeaponDrop Signature (#985)"
This reverts commit fe2a488f30.
2019-05-01 15:05:11 -07:00
Anthony
fe2a488f30 Update CS:GO CSWeaponDrop Signature (#985) 2019-04-30 23:49:00 -07:00
Nicholas Hastings
2bfc349952
Trigger build for hl2sdk-csgo update. 2019-03-28 20:00:32 -04:00
Asher Baker
eb6a39ecde
Get GeoIP data from SM site for now 2019-01-19 12:27:23 +00:00
Michael Flaherty
266532f18c
Prevent FrameIterator OOB Errors (#949) 2019-01-13 13:37:41 -08:00
Nick Hastings
95027e0ae8 Fix BfRead.BytesLeft not being able to be optional. (fixes #945). 2019-01-01 15:37:01 -05:00
Nicholas Hastings
b5a0332181
Fix Mac build. 2018-12-30 19:56:19 -05:00
Asher Baker
ff935b4707
Backport #764 (#942)
Backport #764 to 1.9-dev, to fix build on updated versions of VS 2017.
2018-12-29 15:43:59 +00:00
Deathreus
793c603826 Bump non-critical versioning to 1.9 (#938) 2018-12-27 20:27:47 -05:00
David Anderson
03b270cf18 Don't double-format in ReplyToCommand. 2018-12-12 23:30:55 -08:00
Ruben Gonzalez
3c1c6f6c79
Add new CSGO weapon id's/itemdefs. (#929) 2018-12-12 11:39:30 -08:00
Nick Hastings
81766d31f7 Typo fix for CS:GO POSIX Extinguish gamedata. 2018-12-08 09:10:28 -05:00
Nick Hastings
cb886d4524 Update CS:GO contribution score offset. 2018-12-07 07:26:20 -05:00
Nick Hastings
31836d2667 Hmm... 2018-12-06 20:50:47 -05:00
Nick Hastings
5dcd01801c Add new GiveNamedItem param for CS:GO. 2018-12-06 20:50:40 -05:00
Nick Hastings
5215abe5c5 Update CS:GO SDKTools and SDKHooks offsets. 2018-12-06 20:50:14 -05:00
Ruben Gonzalez
d34d232682 Update csgo gamedata part 1 2018-12-06 20:44:47 -05:00
Dr!fter
a084b3295e Update CS:GO SetClanTag. 2018-11-07 18:14:52 -05:00
Asher Baker
48f7e6bcd5
Update game.empires.txt 2018-10-14 13:07:10 +01:00
Asher Baker
74195870e2 Add a note about FormatTime platform dependence (#908)
This has been another constant source of confusion since the C99 ones were added to the strftime documentation we link.

It'd be nice to have a consistent implementation inside SM in the future.
2018-10-11 11:07:58 +01:00
Asher Baker
e27e75b197 Handle NULLs in SDKCall string return (Fixes #874) (#906)
`SDKCall` has existing semantics that a `-1` retval indicates null, so use that and writes an empty string to the buffer.

Consumers can tell the difference between `""` and `NULL` by checking if the return value is `0` or `-1`.
2018-10-11 00:19:08 +01:00
Ruben Gonzalez
0cdc3616f2 Update CS:GO gamedata. (#904) 2018-10-09 20:21:11 -04:00
Nick Hastings
92e9ca7153 Merge branch '1.9-dev' of https://github.com/alliedmodders/sourcemod into 1.9-dev 2018-10-05 07:12:14 -04:00
Michael Flaherty
ff727d537a [NMRiH] Gamedata update (Fixes #898) (#899) 2018-10-05 07:11:55 -04:00
Michael Flaherty
8803219dd5
Fix regression in vstk size (#894)
* Fix regression in vstk size

* Fix macro comment mistake

* More macro comment removals
2018-10-04 11:14:56 -07:00
Michael Flaherty
ada56b06bb
Fix CS_TerminateRound calls & detour (#893) 2018-10-04 11:14:41 -07:00
Ruben Gonzalez
14eaa097cb Add new weapons to CSWeaponID enum. (#869) 2018-09-12 10:34:50 -04:00
Michael Flaherty
98be188cbe Fix SetClanTag CS:GO Windows Signature (#868) 2018-08-15 18:06:49 -07:00
Asher Baker
3a61446626
Update blacklist.plugins.txt 2018-08-12 22:33:19 +01:00
Michael Flaherty
dd456dcb19 Individualize NameHashSet Hashing & Revisit #709 (#740) (1.9-dev) (#866)
This is a clone of #740, but without the amtl ke::AString lowercase which was implemented in a new version of amtl that 1.9-dev isn't pinned to. Updating this pin and moving fixes is beyond what should go in 1.9, and this fixes a annoying and user-impactful bug with reload/unloading plugins on windows.

Currently in 1.9, once a plugin is loaded into the pluginsys, they must be used with lowercase characters *only*, since pr #709 ignorantly modified their names. 

```
// test.smx exists in /plugins/
sm plugins load TEST.smx // successful
sm plugins unload TEST.smx // TEST.smx not found, it's actually test.smx
```

This pr fixes that error by converting *all* lookups, not just loads.
2018-08-11 13:37:05 +01:00
Nick Hastings
c6303d1ec3 Trigger build against hl2sdk-tf2 update. 2018-08-02 17:30:20 -04:00
Michael Flaherty
ece57df986 Revert "Individualize NameHashSet Hashing & Revisit #709 (#740)"
This reverts commit 3803fbfe20.
2018-07-27 20:36:16 -07:00
Michael Flaherty
3803fbfe20 Individualize NameHashSet Hashing & Revisit #709 (#740)
* Make mac/win lookups lowercase'd

* Revert #709 & 81042cc

* Adjust HashPolicy implementation across sourcemod

Basically, in order to implement our own (actual) hash policy in
`PluginSys.h`, we needed to remove the blanket implementation of `hash`
that was used before. Now, each policy must implement `hash` along with
`matches` in order to be used with `NameHashSet`. While this does force
us to change every implementation of policies across the entirety of
sourcemod, it allows core to use flexible implementations of `hash`.

* Remove logic duplication

* Improve lowercase checks
2018-07-27 18:59:50 -07:00
Dr!fter
50b5bb1970 Fix CS:GO weaponPrice offset. 2018-07-13 07:47:28 -04:00
Nick Hastings
047e0280ca Enable radio menus for IOSoccer. 2018-07-10 20:19:54 -04:00
Mr. Silence
afc493394d Updated some offsets and all signatures for ZPS. (#839)
Signed-off-by: Mr.Silence <Silenci0@users.noreply.github.com>
2018-07-10 20:16:05 -04:00
Joël Troch
54a32e979f [ZPS] Update gamedata and engine migration (#782)
* Migrate ZPS from EP2 to SDK 2013 engine

* Update ZPS gamedata (for version 3.0.7-Hotfix3)
2018-07-10 20:15:41 -04:00
Nick Hastings
07f8043bce Update SDKTools sound functionality for hl2sdk-csgo changes. 2018-07-07 09:07:38 -04:00
Nick Hastings
0a7a01e617 Trigger build for hl2sdk-csgo update. 2018-07-06 21:06:44 -04:00
Ruben Gonzalez
a68b21369c Update SetClanTag signature 2018-07-06 19:22:03 -04:00
Nick Hastings
9a53fc4425 Update SDKTools gamedata for IOSoccer (fixes #833). 2018-06-22 16:31:42 -04:00
Nick Hastings
ab68d046c8 Fix oops with SetConVarBounds. 2018-06-03 12:37:32 -04:00
Dr!fter
cdb9851da6 Fix/Update regex extension and docs (#775, #767) 2018-05-28 15:05:37 -04:00
Nick Hastings
93e9a29353 Merge branch '1.9-dev' of https://github.com/alliedmodders/sourcemod into 1.9-dev 2018-05-20 19:50:58 -04:00
Nick Hastings
fba6997c67 Missed converting a GetFlags instance. 2018-05-20 19:50:52 -04:00
Nick Hastings
880f8869a6 Out with the old ConVar accessibility hacks, in with the new.
Cherry-picked from 467d5705.
2018-05-20 19:50:33 -04:00
Nicholas Hastings
e71497eaa6
Update pushbuild.txt 2018-05-11 08:54:45 -04:00
Nick Hastings
256b33f75a Update BM:S gamedata. 2018-05-06 12:18:02 -04:00
Nick Hastings
c316d8fccd Fix wrong matchmaking_ds bin path being used in some instances. 2018-05-06 10:31:25 -04:00
Nick Hastings
bc09b06166 Update Insurgency FireOutput gamedata. 2018-05-05 11:52:08 -04:00
Nick Hastings
208299f703 Update ConVar hacks for BMS.
This is also to trigger an MM:S build for hl2sdk changes in multiple branches.
2018-05-05 11:52:02 -04:00
Spirrwell
523befc238 Update Function Offsets For PVKII (#808)
* Update Function Offsets For PVKII

-Updates offsets
-Removes "Reload" as no corresponding function actually exists

* Offset Fixes

-Re-add "Reload" as it's defined for CBaseCombatWeapon
-Fix Linux\Mac offsets for GroundEntChanged
2018-05-05 11:51:51 -04:00
Asher Baker
2098a36d4b
Update blacklist.plugins.txt 2018-02-15 22:37:13 +00:00
Nicholas Hastings
083ab81035 Add RemoveEntity native. (bug 5714) (#745) 2018-01-07 13:56:30 -05:00
Ruben Gonzalez
847261b6c9 Merge pull request #744 from alliedmodders/show-required-exts
Address issue #737
2017-12-31 11:17:44 -05:00
Scott Ehlert
309e6ae959 Update CS:GO TerminateRound signature for Linux. 2017-12-19 23:28:19 -06:00
124 changed files with 3468 additions and 4421 deletions

2
.gitmodules vendored
View File

@ -3,4 +3,4 @@
url = https://github.com/alliedmodders/amtl
[submodule "sourcepawn"]
path = sourcepawn
url = https://github.com/alliedmodders/sourcepawn
url = https://github.com/BotoX/sourcepawn.git

View File

@ -200,7 +200,7 @@ class SMConfig(object):
'-pipe',
'-fno-strict-aliasing',
'-Wall',
'-Werror',
# '-Werror',
'-Wno-unused',
'-Wno-switch',
'-Wno-array-bounds',

View File

@ -60,6 +60,9 @@ for sdk_name in SM.sdks:
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
]
if compiler.like('msvc'):
compiler.defines += ['_XKEYCHECK_H']
if builder.target.platform == 'linux':
compiler.postlink += ['-lpthread', '-lrt']
@ -74,10 +77,8 @@ for sdk_name in SM.sdks:
vs_year = ''
if msvc_ver == 1800:
vs_year = '2013'
elif msvc_ver == 1900:
elif 1900 <= msvc_ver < 2000:
vs_year = '2015'
elif msvc_ver == 1910:
vs_year = '2017'
else:
raise Exception('Cannot find libprotobuf for MSVC version "' + str(compiler.version) + '"')

View File

@ -43,6 +43,7 @@
#include <compat_wrappers.h>
#include "concmd_cleaner.h"
#include "PlayerManager.h"
#include <sm_stringhashmap.h>
using namespace SourceHook;
@ -67,6 +68,10 @@ struct ConVarInfo
{
return strcmp(name, info->pVar->GetName()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
/**

View File

@ -412,8 +412,11 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
for (iter = convars->begin(); iter != convars->end(); iter++)
{
const ConVar *cvar = (*iter);
if ((cvar->GetFlags() & FCVAR_DONTRECORD) == FCVAR_DONTRECORD)
#if SOURCE_ENGINE >= SE_ORANGEBOX
if (cvar->IsFlagSet(FCVAR_DONTRECORD))
#else
if (cvar->IsBitSet(FCVAR_DONTRECORD))
#endif
{
continue;
}

View File

@ -77,6 +77,10 @@ struct EventHook
{
return strcmp(name, hook->name.chars()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
enum EventHookMode

View File

@ -50,26 +50,8 @@
typedef ICommandLine *(*FakeGetCommandLine)();
#if defined _WIN32
#define TIER0_NAME "tier0.dll"
#define VSTDLIB_NAME "vstdlib.dll"
#elif defined __APPLE__
#define TIER0_NAME "libtier0.dylib"
#define VSTDLIB_NAME "libvstdlib.dylib"
#elif defined __linux__
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN \
|| SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_INSURGENCY || SOURCE_ENGINE == SE_DOI
#define TIER0_NAME "libtier0_srv.so"
#define VSTDLIB_NAME "libvstdlib_srv.so"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
#define TIER0_NAME "libtier0.so"
#define VSTDLIB_NAME "libvstdlib.so"
#else
#define TIER0_NAME "tier0_i486.so"
#define VSTDLIB_NAME "vstdlib_i486.so"
#endif
#endif
#define TIER0_NAME SOURCE_BIN_PREFIX "tier0" SOURCE_BIN_SUFFIX SOURCE_BIN_EXT
#define VSTDLIB_NAME SOURCE_BIN_PREFIX "vstdlib" SOURCE_BIN_SUFFIX SOURCE_BIN_EXT
CHalfLife2 g_HL2;
ConVar *sv_lan = NULL;

View File

@ -60,6 +60,30 @@ using namespace SourceMod;
#define HUD_PRINTTALK 3
#define HUD_PRINTCENTER 4
#if defined _WIN32
#define SOURCE_BIN_PREFIX ""
#define SOURCE_BIN_SUFFIX ""
#define SOURCE_BIN_EXT ".dll"
#elif defined __APPLE__
#define SOURCE_BIN_PREFIX ""
#define SOURCE_BIN_SUFFIX ""
#define SOURCE_BIN_EXT ".dylib"
#elif defined __linux__
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN \
|| SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_INSURGENCY || SOURCE_ENGINE == SE_DOI
#define SOURCE_BIN_PREFIX "lib"
#define SOURCE_BIN_SUFFIX "_srv"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
#define SOURCE_BIN_PREFIX "lib"
#define SOURCE_BIN_SUFFIX ""
#else
#define SOURCE_BIN_PREFIX ""
#define SOURCE_BIN_SUFFIX "_i486"
#endif
#define SOURCE_BIN_EXT ".so"
#endif
struct DataTableInfo
{
struct SendPropPolicy
@ -68,13 +92,21 @@ struct DataTableInfo
{
return strcmp(name, info.prop->GetName()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
static inline bool matches(const char *name, const DataTableInfo *info)
{
return strcmp(name, info->sc->GetName()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
DataTableInfo(ServerClass *sc)
: sc(sc)
{
@ -90,6 +122,10 @@ struct DataMapCachePolicy
{
return strcmp(name, info.prop->fieldName) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
typedef NameHashSet<sm_datatable_info_t, DataMapCachePolicy> DataMapCache;

View File

@ -308,7 +308,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
{
ItemDrawInfo &dr = drawItems[foundItems].draw;
/* Is the item valid? */
if (menu->GetItemInfo(i, &dr) != NULL)
if (menu->GetItemInfo(i, &dr, client) != NULL)
{
/* Ask the user to change the style, if necessary */
mh->OnMenuDrawItem(menu, client, i, dr.style);
@ -398,7 +398,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
}
while (++lastItem < totalItems)
{
if (menu->GetItemInfo(lastItem, &dr) != NULL)
if (menu->GetItemInfo(lastItem, &dr, client) != NULL)
{
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
if (IsSlotItem(panel, dr.style))
@ -420,7 +420,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
lastItem--;
while (lastItem != 0)
{
if (menu->GetItemInfo(lastItem, &dr) != NULL)
if (menu->GetItemInfo(lastItem, &dr, client) != NULL)
{
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
if (IsSlotItem(panel, dr.style))

View File

@ -633,7 +633,7 @@ bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
return false;
}
CItem item;
CItem item(m_items.length());
item.info = info;
if (draw.display)
@ -655,7 +655,7 @@ bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDr
if (position >= m_items.length())
return false;
CItem item;
CItem item(position);
item.info = info;
if (draw.display)
item.display = new ke::AString(draw.display);
@ -679,11 +679,16 @@ void CBaseMenu::RemoveAllItems()
m_items.clear();
}
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */, int client/* =0 */)
{
if (position >= m_items.length())
return NULL;
if (client > 0 && position < m_RandomMaps[client].length())
{
position = m_RandomMaps[client][position];
}
if (draw)
{
draw->display = m_items[position].display->chars();
@ -693,6 +698,62 @@ const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =
return m_items[position].info.chars();
}
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.length();

View File

@ -43,8 +43,9 @@ using namespace SourceMod;
class CItem
{
public:
CItem()
CItem(unsigned int index)
{
this->index = index;
style = 0;
access = 0;
}
@ -52,11 +53,13 @@ public:
: info(ke::Move(other.info)),
display(ke::Move(other.display))
{
index = other.index;
style = other.style;
access = other.access;
}
CItem & operator =(CItem &&other)
{
index = other.index;
info = ke::Move(other.info);
display = ke::Move(other.display);
style = other.style;
@ -65,6 +68,7 @@ public:
}
public:
unsigned int index;
ke::AString info;
ke::AutoPtr<ke::AString> display;
unsigned int style;
@ -137,7 +141,7 @@ public:
virtual bool InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw);
virtual bool RemoveItem(unsigned int position);
virtual void RemoveAllItems();
virtual const char *GetItemInfo(unsigned int position, ItemDrawInfo *draw=NULL);
virtual const char *GetItemInfo(unsigned int position, ItemDrawInfo *draw=NULL, int client=0);
virtual unsigned int GetItemCount();
virtual bool SetPagination(unsigned int itemsPerPage);
virtual unsigned int GetPagination();
@ -151,6 +155,10 @@ public:
virtual unsigned int GetMenuOptionFlags();
virtual void SetMenuOptionFlags(unsigned int flags);
virtual IMenuHandler *GetHandler();
virtual void ShufflePerClient(int start, int stop);
virtual void SetClientMapping(int client, int *array, int length);
virtual bool IsPerClientShuffled();
virtual unsigned int GetRealItemIndex(int client, unsigned int position);
unsigned int GetBaseMemUsage();
private:
void InternalDelete();
@ -167,6 +175,7 @@ protected:
Handle_t m_hHandle;
IMenuHandler *m_pHandler;
unsigned int m_nFlags;
ke::Vector<uint8_t> m_RandomMaps[SM_MAXPLAYERS+1];
};
#endif //_INCLUDE_MENUSTYLE_BASE_H

View File

@ -514,15 +514,16 @@ void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int ite
/* Check by our item count, NOT the vote array size */
if (item < m_Items)
{
m_ClientVotes[client] = item;
m_Votes[item]++;
unsigned int index = menu->GetRealItemIndex(client, item);
m_ClientVotes[client] = index;
m_Votes[index]++;
m_NumVotes++;
if (sm_vote_chat.GetBool() || sm_vote_console.GetBool() || sm_vote_client_console.GetBool())
{
static char buffer[1024];
ItemDrawInfo dr;
menu->GetItemInfo(item, &dr);
menu->GetItemInfo(item, &dr, client);
if (sm_vote_console.GetBool())
{

View File

@ -30,6 +30,7 @@
*/
#include "PlayerManager.h"
#include "sourcemod.h"
#include "IAdminSystem.h"
#include "ConCmdManager.h"
#include "MenuStyle_Valve.h"
@ -92,6 +93,12 @@ SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &)
#else
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#endif
SH_DECL_HOOK2_void(IVEngineServer, ClientPrintf, SH_NOATTRIB, 0, edict_t *, const char *);
static void PrintfBuffer_FrameAction(void *data)
{
g_Players.OnPrintfFrameAction(reinterpret_cast<unsigned int>(data));
}
ConCommand *maxplayersCmd = NULL;
@ -172,6 +179,7 @@ void PlayerManager::OnSourceModAllInitialized()
#elif SOURCE_ENGINE > SE_EYE // 2013/orangebox, but not original orangebox.
SH_ADD_HOOK(IServerGameDLL, SetServerHibernation, gamedll, SH_MEMBER(this, &PlayerManager::OnServerHibernationUpdate), true);
#endif
SH_ADD_HOOK(IVEngineServer, ClientPrintf, engine, SH_MEMBER(this, &PlayerManager::OnClientPrintf), false);
sharesys->AddInterface(NULL, this);
@ -225,6 +233,7 @@ void PlayerManager::OnSourceModShutdown()
#elif SOURCE_ENGINE > SE_EYE // 2013/orangebox, but not original orangebox.
SH_REMOVE_HOOK(IServerGameDLL, SetServerHibernation, gamedll, SH_MEMBER(this, &PlayerManager::OnServerHibernationUpdate), true);
#endif
SH_REMOVE_HOOK(IVEngineServer, ClientPrintf, engine, SH_MEMBER(this, &PlayerManager::OnClientPrintf), false);
/* Release forwards */
forwardsys->ReleaseForward(m_clconnect);
@ -846,6 +855,88 @@ void PlayerManager::OnClientDisconnect_Post(edict_t *pEntity)
}
}
void PlayerManager::OnClientPrintf(edict_t *pEdict, const char *szMsg)
{
int client = IndexOfEdict(pEdict);
CPlayer &player = m_Players[client];
if (!player.IsConnected())
RETURN_META(MRES_IGNORED);
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(client));
if (pNetChan == NULL)
RETURN_META(MRES_IGNORED);
size_t nMsgLen = strlen(szMsg);
#if SOURCE_ENGINE == SE_EPISODEONE
static const int nNumBitsWritten = 0;
#else
int nNumBitsWritten = pNetChan->GetNumBitsWritten(false); // SVC_Print uses unreliable netchan
#endif
// if the msg is bigger than allowed then just let it fail
if (nMsgLen + 1 >= SVC_Print_BufferSize) // +1 for NETMSG_TYPE_BITS
RETURN_META(MRES_IGNORED);
// enqueue msgs if we'd overflow the SVC_Print buffer (+7 as ceil)
if (!player.m_PrintfBuffer.empty() || (nNumBitsWritten + NETMSG_TYPE_BITS + 7) / 8 + nMsgLen >= SVC_Print_BufferSize)
{
// Don't send any more messages for this player until the buffer is empty.
// Queue up a gameframe hook to empty the buffer (if we haven't already)
if (player.m_PrintfBuffer.empty())
g_SourceMod.AddFrameAction(PrintfBuffer_FrameAction, (void *)(uintptr_t)player.GetSerial());
player.m_PrintfBuffer.append(szMsg);
RETURN_META(MRES_SUPERCEDE);
}
RETURN_META(MRES_IGNORED);
}
void PlayerManager::OnPrintfFrameAction(unsigned int serial)
{
int client = GetClientFromSerial(serial);
CPlayer &player = m_Players[client];
if (!player.IsConnected())
{
player.ClearNetchannelQueue();
return;
}
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(client));
if (pNetChan == NULL)
{
player.ClearNetchannelQueue();
return;
}
while (!player.m_PrintfBuffer.empty())
{
#if SOURCE_ENGINE == SE_EPISODEONE
static const int nNumBitsWritten = 0;
#else
int nNumBitsWritten = pNetChan->GetNumBitsWritten(false); // SVC_Print uses unreliable netchan
#endif
ke::AString &string = player.m_PrintfBuffer.front();
// stop if we'd overflow the SVC_Print buffer (+7 as ceil)
if ((nNumBitsWritten + NETMSG_TYPE_BITS + 7) / 8 + string.length() >= SVC_Print_BufferSize)
break;
SH_CALL(engine, &IVEngineServer::ClientPrintf)(player.m_pEdict, string.chars());
player.m_PrintfBuffer.popFront();
}
if (!player.m_PrintfBuffer.empty())
{
// continue processing it on the next gameframe as buffer is not empty
g_SourceMod.AddFrameAction(PrintfBuffer_FrameAction, (void *)(uintptr_t)player.GetSerial());
}
}
void ClientConsolePrint(edict_t *e, const char *fmt, ...)
{
char buffer[512];
@ -2145,6 +2236,13 @@ void CPlayer::Disconnect()
#if SOURCE_ENGINE == SE_CSGO
m_LanguageCookie = InvalidQueryCvarCookie;
#endif
ClearNetchannelQueue();
}
void CPlayer::ClearNetchannelQueue(void)
{
while (!m_PrintfBuffer.empty())
m_PrintfBuffer.popFront();
}
void CPlayer::SetName(const char *name)

View File

@ -43,6 +43,7 @@
#include <sh_list.h>
#include <sh_vector.h>
#include <am-string.h>
#include <am-deque.h>
#include "ConVarManager.h"
#include <steam/steamclientpublic.h>
@ -123,6 +124,7 @@ private:
bool IsAuthStringValidated();
bool SetEngineString();
bool SetCSteamID();
void ClearNetchannelQueue(void);
private:
bool m_IsConnected = false;
bool m_IsInGame = false;
@ -152,6 +154,7 @@ private:
#if SOURCE_ENGINE == SE_CSGO
QueryCvarCookie_t m_LanguageCookie = InvalidQueryCvarCookie;
#endif
ke::Deque<ke::AString> m_PrintfBuffer;
};
class PlayerManager :
@ -190,6 +193,8 @@ public:
void OnClientSettingsChanged(edict_t *pEntity);
//void OnClientSettingsChanged_Pre(edict_t *pEntity);
void OnServerHibernationUpdate(bool bHibernating);
void OnClientPrintf(edict_t *pEdict, const char *szMsg);
void OnPrintfFrameAction(unsigned int serial);
public: //IPlayerManager
void AddClientListener(IClientListener *listener);
void RemoveClientListener(IClientListener *listener);
@ -267,6 +272,9 @@ private:
int m_SourceTVUserId;
int m_ReplayUserId;
bool m_bInCCKVHook;
private:
static const int NETMSG_TYPE_BITS = 5; // SVC_Print overhead for netmsg type
static const int SVC_Print_BufferSize = 2048 - 1; // -1 for terminating \0
};
#if SOURCE_ENGINE >= SE_ORANGEBOX

View File

@ -36,7 +36,11 @@
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
#if SOURCE_ENGINE == SE_CSGO
SH_DECL_HOOK2_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *, bool);
#else
SH_DECL_HOOK1_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
#endif
#else
SH_DECL_HOOK1_void(ICvar, RegisterConCommandBase, SH_NOATTRIB, 0, ConCommandBase *);
#endif
@ -78,7 +82,11 @@ public:
#endif
}
#if SOURCE_ENGINE == SE_CSGO
void LinkConCommandBase(ConCommandBase *pBase, bool unknown)
#else
void LinkConCommandBase(ConCommandBase *pBase)
#endif
{
IConCommandLinkListener *listener = IConCommandLinkListener::head;
while (listener)

View File

@ -1,551 +0,0 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: 2006-08-13 06:34:30 -0500 (Sun, 13 Aug 2006) $
//
//-----------------------------------------------------------------------------
// $NoKeywords: $
//=============================================================================//
#ifndef CONVAR_H
#define CONVAR_H
#if _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#ifdef _WIN32
#define FORCEINLINE_CVAR FORCEINLINE
#elif _LINUX
#define FORCEINLINE_CVAR __inline__ FORCEINLINE
#else
#error "implement me"
#endif
// The default, no flags at all
#define FCVAR_NONE 0
// Command to ConVars and ConCommands
// ConVar Systems
#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc.
#define FCVAR_LAUNCHER (1<<1) // defined by launcher
#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL
#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL
#define FCVAR_MATERIAL_SYSTEM (1<<4) // Defined by the material system.
#define FCVAR_DATACACHE (1<<19) // Defined by the datacache system.
#define FCVAR_STUDIORENDER (1<<15) // Defined by the studiorender system.
#define FCVAR_FILESYSTEM (1<<21) // Defined by the file system.
#define FCVAR_PLUGIN (1<<18) // Defined by a 3rd party plugin.
#define FCVAR_TOOLSYSTEM (1<<20) // Defined by an IToolSystem library
#define FCVAR_SOUNDSYSTEM (1<<23) // Defined by the soundsystem library
#define FCVAR_INPUTSYSTEM (1<<25) // Defined by the inputsystem dll
#define FCVAR_NETWORKSYSTEM (1<<26) // Defined by the network system
// NOTE!! if you add a cvar system, add it here too!!!!
// the engine lacks a cvar flag, but needs it for xbox
// an engine cvar is thus a cvar not marked with any other system
#define FCVAR_NON_ENGINE ((FCVAR_LAUNCHER|FCVAR_GAMEDLL|FCVAR_CLIENTDLL|FCVAR_MATERIAL_SYSTEM|FCVAR_DATACACHE|FCVAR_STUDIORENDER|FCVAR_FILESYSTEM|FCVAR_PLUGIN|FCVAR_TOOLSYSTEM|FCVAR_SOUNDSYSTEM|FCVAR_INPUTSYSTEM|FCVAR_NETWORKSYSTEM))
// ConVar only
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc
#define FCVAR_NOTIFY (1<<8) // notifies players when changed
#define FCVAR_USERINFO (1<<9) // changes the client's info string
#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar
// It's a ConVar that's shared between the client and the server.
// At signon, the values of all such ConVars are sent from the server to the client (skipped for local
// client, of course )
// If a change is requested it must come from the console (i.e., no remote client changes)
// If a value is changed while a server is active, it's replicated to all connected clients
#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time
#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file
#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles
#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server
#define FCVAR_ARCHIVE_XBOX (1<<24) // cvar written to config.cfg on the Xbox
// #define FCVAR_AVAILABLE (1<<27)
// #define FCVAR_AVAILABLE (1<<28)
// #define FCVAR_AVAILABLE (1<<29)
// #define FCVAR_AVAILABLE (1<<30)
// #define FCVAR_AVAILABLE (1<<31)
class ConVar;
class ConCommand;
class ConCommandBase;
// Any executable that wants to use ConVars need to implement one of
// these to hook up access to console variables.
class IConCommandBaseAccessor
{
public:
// Flags is a combination of FCVAR flags in cvar.h.
// hOut is filled in with a handle to the variable.
virtual bool RegisterConCommandBase( ConCommandBase *pVar )=0;
};
// You don't have to instantiate one of these, just call its
// OneTimeInit function when your executable is initializing.
class ConCommandBaseMgr
{
public:
// Call this ONCE when the executable starts up.
static void OneTimeInit( IConCommandBaseAccessor *pAccessor );
#ifdef _XBOX
static bool Fixup( ConCommandBase* pConCommandBase );
#ifndef _RETAIL
static void PublishCommands( bool bForce );
#endif
#endif
};
// Called when a ConVar changes value
typedef void ( *FnChangeCallback )( ConVar *var, char const *pOldString );
// Called when a ConCommand needs to execute
typedef void ( *FnCommandCallback )( void );
#define COMMAND_COMPLETION_MAXITEMS 64
#define COMMAND_COMPLETION_ITEM_LENGTH 64
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
typedef int ( *FnCommandCompletionCallback )( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
//-----------------------------------------------------------------------------
// Purpose: The base console invoked command/cvar interface
//-----------------------------------------------------------------------------
class ConCommandBase
{
friend class ConCommandBaseMgr;
friend class CCvar;
friend class ConVar;
friend class ConCommand;
public:
ConCommandBase( void );
ConCommandBase( char const *pName, char const *pHelpString = 0,
int flags = 0 );
virtual ~ConCommandBase( void );
virtual bool IsCommand( void ) const;
// Check flag
virtual bool IsBitSet( int flag ) const;
// Set flag
virtual void AddFlags( int flags );
// Return name of cvar
virtual char const *GetName( void ) const;
// Return help text for cvar
virtual char const *GetHelpText( void ) const;
// Deal with next pointer
const ConCommandBase *GetNext( void ) const;
void SetNext( ConCommandBase *next );
virtual bool IsRegistered( void ) const;
// Global methods
static ConCommandBase const *GetCommands( void );
static void AddToList( ConCommandBase *var );
static void RemoveFlaggedCommands( int flag );
static void RevertFlaggedCvars( int flag );
static ConCommandBase const *FindCommand( char const *name );
protected:
virtual void Create( char const *pName, char const *pHelpString = 0,
int flags = 0 );
// Used internally by OneTimeInit to initialize.
virtual void Init();
// Internal copy routine ( uses new operator from correct module )
char *CopyString( char const *from );
// Next ConVar in chain
ConCommandBase *m_pNext;
private:
// Has the cvar been added to the global list?
bool m_bRegistered;
// Static data
char const *m_pszName;
char const *m_pszHelpString;
// ConVar flags
int m_nFlags;
protected:
// ConVars add themselves to this list for the executable. Then ConVarMgr::Init() runs through
// all the console variables and registers them.
static ConCommandBase *s_pConCommandBases;
// ConVars in this executable use this 'global' to access values.
static IConCommandBaseAccessor *s_pAccessor;
public: // Hackalicous
inline int GetFlags() const
{
return m_nFlags;
}
inline void SetFlags(int flags)
{
m_nFlags = flags;
}
};
//-----------------------------------------------------------------------------
// Purpose: The console invoked command
//-----------------------------------------------------------------------------
class ConCommand : public ConCommandBase
{
friend class ConCommandBaseMgr;
friend class CCvar;
#ifdef _STATIC_LINKED
friend class G_ConCommand;
friend class C_ConCommand;
friend class M_ConCommand;
friend class S_ConCommand;
friend class D_ConCommand;
#endif
public:
typedef ConCommandBase BaseClass;
ConCommand( void );
ConCommand( char const *pName, FnCommandCallback callback,
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
virtual ~ConCommand( void );
virtual bool IsCommand( void ) const;
virtual int AutoCompleteSuggest( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
virtual bool CanAutoComplete( void );
// Invoke the function
virtual void Dispatch( void );
private:
virtual void Create( char const *pName, FnCommandCallback callback,
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
// Call this function when executing the command
FnCommandCallback m_fnCommandCallback;
FnCommandCompletionCallback m_fnCompletionCallback;
bool m_bHasCompletionCallback;
public: // Hackalicous
inline FnCommandCallback GetCallback() const
{
return m_fnCommandCallback;
}
};
//-----------------------------------------------------------------------------
// Purpose: A console variable
//-----------------------------------------------------------------------------
class ConVar : public ConCommandBase
{
friend class ConCommandBaseMgr;
friend class CCvar;
friend class CDefaultCvar;
#ifdef _STATIC_LINKED
friend class G_ConVar;
friend class C_ConVar;
friend class M_ConVar;
friend class S_ConVar;
friend class D_ConVar;
#endif
public:
typedef ConCommandBase BaseClass;
ConVar( char const *pName, char const *pDefaultValue, int flags = 0);
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString );
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString, FnChangeCallback callback );
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
FnChangeCallback callback );
virtual ~ConVar( void );
virtual bool IsBitSet( int flag ) const;
virtual char const* GetHelpText( void ) const;
virtual bool IsRegistered( void ) const;
virtual char const *GetName( void ) const;
virtual void AddFlags( int flags );
virtual bool IsCommand( void ) const;
// Install a change callback (there shouldn't already be one....)
void InstallChangeCallback( FnChangeCallback callback );
// Retrieve value
FORCEINLINE_CVAR float GetFloat( void ) const;
FORCEINLINE_CVAR int GetInt( void ) const;
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
FORCEINLINE_CVAR char const *GetString( void ) const;
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
// from alloc/free across dll/exe boundaries.
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
virtual void SetValue( char const *value );
virtual void SetValue( float value );
virtual void SetValue( int value );
// Reset to default value
void Revert( void );
// True if it has a min/max setting
bool GetMin( float& minVal ) const;
bool GetMax( float& maxVal ) const;
char const *GetDefault( void ) const;
static void RevertAll( void );
private:
// Called by CCvar when the value of a var is changing.
virtual void InternalSetValue(char const *value);
// For CVARs marked FCVAR_NEVER_AS_STRING
virtual void InternalSetFloatValue( float fNewValue );
virtual void InternalSetIntValue( int nValue );
virtual bool ClampValue( float& value );
virtual void ChangeStringValue( char const *tempVal );
virtual void Create( char const *pName, char const *pDefaultValue, int flags = 0,
char const *pHelpString = 0, bool bMin = false, float fMin = 0.0,
bool bMax = false, float fMax = false, FnChangeCallback callback = 0 );
// Used internally by OneTimeInit to initialize.
virtual void Init();
private:
// This either points to "this" or it points to the original declaration of a ConVar.
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
ConVar *m_pParent;
// Static data
char const *m_pszDefaultValue;
// Value
// Dynamically allocated
char *m_pszString;
int m_StringLength;
// Values
float m_fValue;
int m_nValue;
// Min/Max values
bool m_bHasMin;
float m_fMinVal;
bool m_bHasMax;
float m_fMaxVal;
// Call this function when ConVar changes
FnChangeCallback m_fnChangeCallback;
public: // Hackalicous
inline FnChangeCallback GetCallback() const
{
return m_fnChangeCallback;
}
inline void SetMin(bool set, float min=0.0)
{
m_bHasMin = set;
m_fMinVal = min;
}
inline void SetMax(bool set, float max=0.0)
{
m_bHasMax = set;
m_fMaxVal = max;
}
};
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
// Output : float
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
{
return m_pParent->m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
// Output : int
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
{
return m_pParent->m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
// Output : char const *
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR char const *ConVar::GetString( void ) const
{
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
{
return "FCVAR_NEVER_AS_STRING";
}
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
}
#ifdef _STATIC_LINKED
// identifies subsystem via piggybacking constructors with flags
class G_ConCommand : public ConCommand
{
public:
G_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_GAMEDLL, completionFunc) {}
};
class C_ConCommand : public ConCommand
{
public:
C_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_CLIENTDLL, completionFunc) {}
};
class M_ConCommand : public ConCommand
{
public:
M_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_MATERIAL_SYSTEM, completionFunc) {}
};
class S_ConCommand : public ConCommand
{
public:
S_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_STUDIORENDER, completionFunc) {}
};
class D_ConCommand : public ConCommand
{
public:
D_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_DATACACHE, completionFunc) {}
};
typedef void ( *G_FnChangeCallback )( G_ConVar *var, char const *pOldString );
typedef void ( *C_FnChangeCallback )( C_ConVar *var, char const *pOldString );
typedef void ( *M_FnChangeCallback )( M_ConVar *var, char const *pOldString );
typedef void ( *S_FnChangeCallback )( S_ConVar *var, char const *pOldString );
typedef void ( *D_FnChangeCallback )( D_ConVar *var, char const *pOldString );
class G_ConVar : public ConVar
{
public:
G_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL) {}
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString ) {}
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax) {}
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, (FnChangeCallback)callback ) {}
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
};
class C_ConVar : public ConVar
{
public:
C_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL) {}
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString ) {}
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax) {}
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, (FnChangeCallback)callback ) {}
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
};
class M_ConVar : public ConVar
{
public:
M_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM) {}
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString ) {}
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax) {}
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, (FnChangeCallback)callback ) {}
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
};
class S_ConVar : public ConVar
{
public:
S_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER) {}
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString ) {}
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax) {}
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, (FnChangeCallback)callback ) {}
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, S_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
};
class D_ConVar : public ConVar
{
public:
D_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE) {}
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString ) {}
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax) {}
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, (FnChangeCallback)callback ) {}
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, D_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
};
// redirect these declarations to their specific subsystem
#ifdef GAME_DLL
#define ConCommand G_ConCommand
#define ConVar G_ConVar
#endif
#ifdef CLIENT_DLL
#define ConCommand C_ConCommand
#define ConVar C_ConVar
#endif
#ifdef MATERIALSYSTEM_DLL
#define ConCommand M_ConCommand
#define ConVar M_ConVar
#endif
#ifdef STUDIORENDER_DLL
#define ConCommand S_ConCommand
#define ConVar S_ConVar
#endif
#ifdef DATACACHE_DLL
#define ConCommand D_ConCommand
#define ConVar D_ConVar
#endif
#endif // _STATIC_LINKED
//-----------------------------------------------------------------------------
// Purpose: Utility to quicky generate a simple console command
//-----------------------------------------------------------------------------
#define CON_COMMAND( name, description ) \
static void name(); \
static ConCommand name##_command( #name, name, description ); \
static void name()
//-----------------------------------------------------------------------------
// Purpose: Utility to quicky generate a simple console command
//-----------------------------------------------------------------------------
#define CON_COMMAND_F( name, description, flags ) \
static void name(); \
static ConCommand name##_command( #name, name, description, flags ); \
static void name()
#endif // CONVAR_H

View File

@ -1,718 +0,0 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $NoKeywords: $
//===========================================================================//
#ifndef CONVAR_H
#define CONVAR_H
#if _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "tier1/iconvar.h"
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
#include "icvar.h"
#ifdef _WIN32
#define FORCEINLINE_CVAR FORCEINLINE
#elif defined _LINUX || defined __APPLE__
#define FORCEINLINE_CVAR inline
#else
#error "implement me"
#endif
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class ConVar;
class CCommand;
class ConCommand;
class ConCommandBase;
struct characterset_t;
//-----------------------------------------------------------------------------
// Any executable that wants to use ConVars need to implement one of
// these to hook up access to console variables.
//-----------------------------------------------------------------------------
class IConCommandBaseAccessor
{
public:
// Flags is a combination of FCVAR flags in cvar.h.
// hOut is filled in with a handle to the variable.
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
};
//-----------------------------------------------------------------------------
// Helper method for console development
//-----------------------------------------------------------------------------
#if defined( _X360 ) && !defined( _RETAIL )
void ConVar_PublishToVXConsole();
#endif
//-----------------------------------------------------------------------------
// Called when a ConCommand needs to execute
//-----------------------------------------------------------------------------
typedef void ( *FnCommandCallbackV1_t )( void );
typedef void ( *FnCommandCallback_t )( const CCommand &command );
#define COMMAND_COMPLETION_MAXITEMS 64
#define COMMAND_COMPLETION_ITEM_LENGTH 64
//-----------------------------------------------------------------------------
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
//-----------------------------------------------------------------------------
typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
//-----------------------------------------------------------------------------
// Interface version
//-----------------------------------------------------------------------------
class ICommandCallback
{
public:
virtual void CommandCallback( const CCommand &command ) = 0;
};
class ICommandCompletionCallback
{
public:
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
};
//-----------------------------------------------------------------------------
// Purpose: The base console invoked command/cvar interface
//-----------------------------------------------------------------------------
class ConCommandBase
{
friend class CCvar;
friend class ConVar;
friend class ConCommand;
friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
friend void ConVar_PublishToVXConsole();
// FIXME: Remove when ConVar changes are done
friend class CDefaultCvar;
public:
ConCommandBase( void );
ConCommandBase( const char *pName, const char *pHelpString = 0,
int flags = 0 );
virtual ~ConCommandBase( void );
virtual bool IsCommand( void ) const;
// Check flag
virtual bool IsFlagSet( int flag ) const;
// Set flag
virtual void AddFlags( int flags );
// Remove flag
virtual void RemoveFlags( int flags );
// Get flags
virtual int GetFlags( void ) const;
// Return name of cvar
virtual const char *GetName( void ) const;
// Return help text for cvar
virtual const char *GetHelpText( void ) const;
// Deal with next pointer
const ConCommandBase *GetNext( void ) const;
ConCommandBase *GetNext( void );
inline void SetNext(ConCommandBase *pBase)
{
m_pNext = pBase;
}
virtual bool IsRegistered( void ) const;
// Returns the DLL identifier
virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
protected:
virtual void Create( const char *pName, const char *pHelpString = 0,
int flags = 0 );
// Used internally by OneTimeInit to initialize/shutdown
virtual void Init();
void Shutdown();
// Internal copy routine ( uses new operator from correct module )
char *CopyString( const char *from );
private:
// Next ConVar in chain
// Prior to register, it points to the next convar in the DLL.
// Once registered, though, m_pNext is reset to point to the next
// convar in the global list
ConCommandBase *m_pNext;
// Has the cvar been added to the global list?
bool m_bRegistered;
// Static data
const char *m_pszName;
const char *m_pszHelpString;
// ConVar flags
int m_nFlags;
protected:
// ConVars add themselves to this list for the executable.
// Then ConVar_Register runs through all the console variables
// and registers them into a global list stored in vstdlib.dll
static ConCommandBase *s_pConCommandBases;
// ConVars in this executable use this 'global' to access values.
static IConCommandBaseAccessor *s_pAccessor;
public:
inline void SetFlags(int flags)
{
m_nFlags = flags;
}
};
//-----------------------------------------------------------------------------
// Command tokenizer
//-----------------------------------------------------------------------------
class CCommand
{
public:
CCommand();
CCommand( int nArgC, const char **ppArgV );
bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
void Reset();
int ArgC() const;
const char **ArgV() const;
const char *ArgS() const; // All args that occur after the 0th arg, in string form
const char *GetCommandString() const; // The entire command in string form, including the 0th arg
const char *operator[]( int nIndex ) const; // Gets at arguments
const char *Arg( int nIndex ) const; // Gets at arguments
// Helper functions to parse arguments to commands.
const char* FindArg( const char *pName ) const;
int FindArgInt( const char *pName, int nDefaultVal ) const;
static int MaxCommandLength();
static characterset_t* DefaultBreakSet();
private:
enum
{
COMMAND_MAX_ARGC = 64,
COMMAND_MAX_LENGTH = 512,
};
int m_nArgc;
int m_nArgv0Size;
char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
const char* m_ppArgv[ COMMAND_MAX_ARGC ];
};
inline int CCommand::MaxCommandLength()
{
return COMMAND_MAX_LENGTH - 1;
}
inline int CCommand::ArgC() const
{
return m_nArgc;
}
inline const char **CCommand::ArgV() const
{
return m_nArgc ? (const char**)m_ppArgv : NULL;
}
inline const char *CCommand::ArgS() const
{
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
}
inline const char *CCommand::GetCommandString() const
{
return m_nArgc ? m_pArgSBuffer : "";
}
inline const char *CCommand::Arg( int nIndex ) const
{
// FIXME: Many command handlers appear to not be particularly careful
// about checking for valid argc range. For now, we're going to
// do the extra check and return an empty string if it's out of range
if ( nIndex < 0 || nIndex >= m_nArgc )
return "";
return m_ppArgv[nIndex];
}
inline const char *CCommand::operator[]( int nIndex ) const
{
return Arg( nIndex );
}
//-----------------------------------------------------------------------------
// Purpose: The console invoked command
//-----------------------------------------------------------------------------
class ConCommand : public ConCommandBase
{
friend class CCvar;
public:
typedef ConCommandBase BaseClass;
ConCommand( const char *pName, FnCommandCallbackV1_t callback,
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
ConCommand( const char *pName, FnCommandCallback_t callback,
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
ConCommand( const char *pName, ICommandCallback *pCallback,
const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
virtual ~ConCommand( void );
virtual bool IsCommand( void ) const;
virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
virtual bool CanAutoComplete( void );
// Invoke the function
virtual void Dispatch( const CCommand &command );
private:
// NOTE: To maintain backward compat, we have to be very careful:
// All public virtual methods must appear in the same order always
// since engine code will be calling into this code, which *does not match*
// in the mod code; it's using slightly different, but compatible versions
// of this class. Also: Be very careful about adding new fields to this class.
// Those fields will not exist in the version of this class that is instanced
// in mod code.
// Call this function when executing the command
union
{
FnCommandCallbackV1_t m_fnCommandCallbackV1;
FnCommandCallback_t m_fnCommandCallback;
ICommandCallback *m_pCommandCallback;
};
union
{
FnCommandCompletionCallback m_fnCompletionCallback;
ICommandCompletionCallback *m_pCommandCompletionCallback;
};
bool m_bHasCompletionCallback : 1;
bool m_bUsingNewCommandCallback : 1;
bool m_bUsingCommandCallbackInterface : 1;
public:
inline FnCommandCallback_t GetCallback() const
{
return m_fnCommandCallback;
}
};
//-----------------------------------------------------------------------------
// Purpose: A console variable
//-----------------------------------------------------------------------------
class ConVar : public ConCommandBase, public IConVar
{
friend class CCvar;
friend class ConVarRef;
public:
typedef ConCommandBase BaseClass;
ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, FnChangeCallback_t callback );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
FnChangeCallback_t callback );
virtual ~ConVar( void );
virtual bool IsCommand( void ) const;
virtual bool IsFlagSet( int flag ) const;
virtual void AddFlags( int flags );
virtual int GetFlags( void ) const;
virtual const char *GetName( void ) const;
virtual const char* GetHelpText( void ) const;
virtual bool IsRegistered( void ) const;
// Install a change callback (there shouldn't already be one....)
void InstallChangeCallback( FnChangeCallback_t callback );
// Retrieve value
FORCEINLINE_CVAR float GetFloat( void ) const;
FORCEINLINE_CVAR int GetInt( void ) const;
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
FORCEINLINE_CVAR char const *GetString( void ) const;
// Used internally by OneTimeInit to initialize.
virtual void Init();
virtual const char *GetBaseName( void ) const;
virtual int GetSplitScreenPlayerSlot ( void ) const;
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
// from alloc/free across dll/exe boundaries.
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
virtual void SetValue( const char *value );
virtual void SetValue( float value );
virtual void SetValue( int value );
#if SOURCE_ENGINE >= SE_NUCLEARDAWN
virtual void SetValue( Color value );
#endif
// Reset to default value
void Revert( void );
// True if it has a min/max setting
bool GetMin( float& minVal ) const;
bool GetMax( float& maxVal ) const;
const char *GetDefault( void ) const;
private:
// Called by CCvar when the value of a var is changing.
virtual void InternalSetValue(const char *value);
// For CVARs marked FCVAR_NEVER_AS_STRING
virtual void InternalSetFloatValue( float fNewValue );
virtual void InternalSetIntValue( int nValue );
#if SOURCE_ENGINE >= SE_LEFT4DEAD2
virtual void InternalSetColorValue( Color value );
#endif
virtual bool ClampValue( float& value );
virtual void ChangeStringValue( const char *tempVal, float flOldValue );
virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0,
const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
private:
// This either points to "this" or it points to the original declaration of a ConVar.
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
ConVar *m_pParent;
// Static data
const char *m_pszDefaultValue;
// Value
// Dynamically allocated
char *m_pszString;
int m_StringLength;
// Values
float m_fValue;
int m_nValue;
// Min/Max values
bool m_bHasMin;
float m_fMinVal;
bool m_bHasMax;
float m_fMaxVal;
// Call this function when ConVar changes
FnChangeCallback_t m_fnChangeCallback;
public:
inline FnChangeCallback_t GetCallback() const
{
return m_fnChangeCallback;
}
inline void SetMin(bool set, float min=0.0)
{
m_bHasMin = set;
m_fMinVal = min;
}
inline void SetMax(bool set, float max=0.0)
{
m_bHasMax = set;
m_fMaxVal = max;
}
};
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
// Output : float
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
{
return m_pParent->m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
// Output : int
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
{
return m_pParent->m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
// Output : const char *
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
{
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
return "FCVAR_NEVER_AS_STRING";
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
}
//-----------------------------------------------------------------------------
// Used to read/write convars that already exist (replaces the FindVar method)
//-----------------------------------------------------------------------------
class ConVarRef
{
public:
ConVarRef( const char *pName );
ConVarRef( const char *pName, bool bIgnoreMissing );
ConVarRef( IConVar *pConVar );
void Init( const char *pName, bool bIgnoreMissing );
bool IsValid() const;
bool IsFlagSet( int nFlags ) const;
IConVar *GetLinkedConVar();
// Get/Set value
float GetFloat( void ) const;
int GetInt( void ) const;
bool GetBool() const { return !!GetInt(); }
const char *GetString( void ) const;
void SetValue( const char *pValue );
void SetValue( float flValue );
void SetValue( int nValue );
void SetValue( bool bValue );
const char *GetName() const;
const char *GetDefault() const;
private:
// High-speed method to read convar data
IConVar *m_pConVar;
ConVar *m_pConVarState;
};
//-----------------------------------------------------------------------------
// Did we find an existing convar of that name?
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
{
return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
}
FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
{
return m_pConVar;
}
FORCEINLINE_CVAR const char *ConVarRef::GetName() const
{
return m_pConVar->GetName();
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
{
return m_pConVarState->m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
{
return m_pConVarState->m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const
{
Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
return m_pConVarState->m_pszString;
}
FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
{
m_pConVar->SetValue( pValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
{
m_pConVar->SetValue( flValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
{
m_pConVar->SetValue( nValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
{
m_pConVar->SetValue( bValue ? 1 : 0 );
}
FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
{
return m_pConVarState->m_pszDefaultValue;
}
//-----------------------------------------------------------------------------
// Called by the framework to register ConCommands with the ICVar
//-----------------------------------------------------------------------------
void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
void ConVar_Unregister( );
//-----------------------------------------------------------------------------
// Utility methods
//-----------------------------------------------------------------------------
void ConVar_PrintFlags( const ConCommandBase *var );
void ConVar_PrintDescription( const ConCommandBase *pVar );
//-----------------------------------------------------------------------------
// Purpose: Utility class to quickly allow ConCommands to call member methods
//-----------------------------------------------------------------------------
#ifdef _MSC_VER
#pragma warning (disable : 4355 )
#endif
template< class T >
class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
{
typedef ConCommand BaseClass;
typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
public:
CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
{
m_pOwner = pOwner;
m_Func = callback;
m_CompletionFunc = completionFunc;
}
~CConCommandMemberAccessor()
{
Shutdown();
}
void SetOwner( T* pOwner )
{
m_pOwner = pOwner;
}
virtual void CommandCallback( const CCommand &command )
{
Assert( m_pOwner && m_Func );
(m_pOwner->*m_Func)( command );
}
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
{
Assert( m_pOwner && m_CompletionFunc );
return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
}
private:
T* m_pOwner;
FnMemberCommandCallback_t m_Func;
FnMemberCommandCompletionCallback_t m_CompletionFunc;
};
#ifdef _MSC_VER
#pragma warning ( default : 4355 )
#endif
//-----------------------------------------------------------------------------
// Purpose: Utility macros to quicky generate a simple console command
//-----------------------------------------------------------------------------
#define CON_COMMAND( name, description ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description ); \
static void name( const CCommand &args )
#define CON_COMMAND_F( name, description, flags ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description, flags ); \
static void name( const CCommand &args )
#define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description, flags, completion ); \
static void name( const CCommand &args )
#define CON_COMMAND_EXTERN( name, _funcname, description ) \
void _funcname( const CCommand &args ); \
static ConCommand name##_command( #name, _funcname, description ); \
void _funcname( const CCommand &args )
#define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
void _funcname( const CCommand &args ); \
static ConCommand name##_command( #name, _funcname, description, flags ); \
void _funcname( const CCommand &args )
#define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
void _funcname( const CCommand &args ); \
friend class CCommandMemberInitializer_##_funcname; \
class CCommandMemberInitializer_##_funcname \
{ \
public: \
CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \
{ \
m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \
} \
private: \
CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \
}; \
\
CCommandMemberInitializer_##_funcname m_##_funcname##_register; \
#endif // CONVAR_H

View File

@ -1,709 +0,0 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $NoKeywords: $
//===========================================================================//
#ifndef CONVAR_H
#define CONVAR_H
#if _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "tier1/iconvar.h"
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
#include "icvar.h"
#ifdef _WIN32
#define FORCEINLINE_CVAR FORCEINLINE
#elif defined _LINUX || defined __APPLE__
#define FORCEINLINE_CVAR inline
#else
#error "implement me"
#endif
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class ConVar;
class CCommand;
class ConCommand;
class ConCommandBase;
struct characterset_t;
//-----------------------------------------------------------------------------
// Any executable that wants to use ConVars need to implement one of
// these to hook up access to console variables.
//-----------------------------------------------------------------------------
class IConCommandBaseAccessor
{
public:
// Flags is a combination of FCVAR flags in cvar.h.
// hOut is filled in with a handle to the variable.
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
};
//-----------------------------------------------------------------------------
// Helper method for console development
//-----------------------------------------------------------------------------
#if defined( _X360 ) && !defined( _RETAIL )
void ConVar_PublishToVXConsole();
#endif
//-----------------------------------------------------------------------------
// Called when a ConCommand needs to execute
//-----------------------------------------------------------------------------
typedef void ( *FnCommandCallbackV1_t )( void );
typedef void ( *FnCommandCallback_t )( const CCommand &command );
#define COMMAND_COMPLETION_MAXITEMS 64
#define COMMAND_COMPLETION_ITEM_LENGTH 64
//-----------------------------------------------------------------------------
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
//-----------------------------------------------------------------------------
typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
//-----------------------------------------------------------------------------
// Interface version
//-----------------------------------------------------------------------------
class ICommandCallback
{
public:
virtual void CommandCallback( const CCommand &command ) = 0;
};
class ICommandCompletionCallback
{
public:
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
};
//-----------------------------------------------------------------------------
// Purpose: The base console invoked command/cvar interface
//-----------------------------------------------------------------------------
class ConCommandBase
{
friend class CCvar;
friend class ConVar;
friend class ConCommand;
friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
friend void ConVar_PublishToVXConsole();
// FIXME: Remove when ConVar changes are done
friend class CDefaultCvar;
public:
ConCommandBase( void );
ConCommandBase( const char *pName, const char *pHelpString = 0,
int flags = 0 );
virtual ~ConCommandBase( void );
virtual bool IsCommand( void ) const;
// Check flag
virtual bool IsFlagSet( int flag ) const;
// Set flag
virtual void AddFlags( int flags );
// Return name of cvar
virtual const char *GetName( void ) const;
// Return help text for cvar
virtual const char *GetHelpText( void ) const;
// Deal with next pointer
const ConCommandBase *GetNext( void ) const;
ConCommandBase *GetNext( void );
void SetNext(ConCommandBase *pBase)
{
m_pNext = pBase;
}
virtual bool IsRegistered( void ) const;
// Returns the DLL identifier
virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
protected:
virtual void Create( const char *pName, const char *pHelpString = 0,
int flags = 0 );
// Used internally by OneTimeInit to initialize/shutdown
virtual void Init();
void Shutdown();
// Internal copy routine ( uses new operator from correct module )
char *CopyString( const char *from );
private:
// Next ConVar in chain
// Prior to register, it points to the next convar in the DLL.
// Once registered, though, m_pNext is reset to point to the next
// convar in the global list
ConCommandBase *m_pNext;
// Has the cvar been added to the global list?
bool m_bRegistered;
// Static data
const char *m_pszName;
const char *m_pszHelpString;
// ConVar flags
int m_nFlags;
protected:
// ConVars add themselves to this list for the executable.
// Then ConVar_Register runs through all the console variables
// and registers them into a global list stored in vstdlib.dll
static ConCommandBase *s_pConCommandBases;
// ConVars in this executable use this 'global' to access values.
static IConCommandBaseAccessor *s_pAccessor;
public: // Hackalicous
inline int GetFlags() const
{
return m_nFlags;
}
inline void SetFlags(int flags)
{
m_nFlags = flags;
}
};
//-----------------------------------------------------------------------------
// Command tokenizer
//-----------------------------------------------------------------------------
class CCommand
{
public:
CCommand();
CCommand( int nArgC, const char **ppArgV );
bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
void Reset();
int ArgC() const;
const char **ArgV() const;
const char *ArgS() const; // All args that occur after the 0th arg, in string form
const char *GetCommandString() const; // The entire command in string form, including the 0th arg
const char *operator[]( int nIndex ) const; // Gets at arguments
const char *Arg( int nIndex ) const; // Gets at arguments
// Helper functions to parse arguments to commands.
const char* FindArg( const char *pName ) const;
int FindArgInt( const char *pName, int nDefaultVal ) const;
static int MaxCommandLength();
static characterset_t* DefaultBreakSet();
private:
enum
{
COMMAND_MAX_ARGC = 64,
COMMAND_MAX_LENGTH = 512,
};
int m_nArgc;
int m_nArgv0Size;
char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
const char* m_ppArgv[ COMMAND_MAX_ARGC ];
};
inline int CCommand::MaxCommandLength()
{
return COMMAND_MAX_LENGTH - 1;
}
inline int CCommand::ArgC() const
{
return m_nArgc;
}
inline const char **CCommand::ArgV() const
{
return m_nArgc ? (const char**)m_ppArgv : NULL;
}
inline const char *CCommand::ArgS() const
{
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
}
inline const char *CCommand::GetCommandString() const
{
return m_nArgc ? m_pArgSBuffer : "";
}
inline const char *CCommand::Arg( int nIndex ) const
{
// FIXME: Many command handlers appear to not be particularly careful
// about checking for valid argc range. For now, we're going to
// do the extra check and return an empty string if it's out of range
if ( nIndex < 0 || nIndex >= m_nArgc )
return "";
return m_ppArgv[nIndex];
}
inline const char *CCommand::operator[]( int nIndex ) const
{
return Arg( nIndex );
}
//-----------------------------------------------------------------------------
// Purpose: The console invoked command
//-----------------------------------------------------------------------------
class ConCommand : public ConCommandBase
{
friend class CCvar;
public:
typedef ConCommandBase BaseClass;
ConCommand( const char *pName, FnCommandCallbackV1_t callback,
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
ConCommand( const char *pName, FnCommandCallback_t callback,
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
ConCommand( const char *pName, ICommandCallback *pCallback,
const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
virtual ~ConCommand( void );
virtual bool IsCommand( void ) const;
virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
virtual bool CanAutoComplete( void );
// Invoke the function
virtual void Dispatch( const CCommand &command );
private:
// NOTE: To maintain backward compat, we have to be very careful:
// All public virtual methods must appear in the same order always
// since engine code will be calling into this code, which *does not match*
// in the mod code; it's using slightly different, but compatible versions
// of this class. Also: Be very careful about adding new fields to this class.
// Those fields will not exist in the version of this class that is instanced
// in mod code.
// Call this function when executing the command
union
{
FnCommandCallbackV1_t m_fnCommandCallbackV1;
FnCommandCallback_t m_fnCommandCallback;
ICommandCallback *m_pCommandCallback;
};
union
{
FnCommandCompletionCallback m_fnCompletionCallback;
ICommandCompletionCallback *m_pCommandCompletionCallback;
};
bool m_bHasCompletionCallback : 1;
bool m_bUsingNewCommandCallback : 1;
bool m_bUsingCommandCallbackInterface : 1;
public: // Hackalicous
inline FnCommandCallback_t GetCallback() const
{
return m_fnCommandCallback;
}
};
//-----------------------------------------------------------------------------
// Purpose: A console variable
//-----------------------------------------------------------------------------
class ConVar : public ConCommandBase, public IConVar
{
friend class CCvar;
friend class ConVarRef;
public:
typedef ConCommandBase BaseClass;
ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, FnChangeCallback_t callback );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
FnChangeCallback_t callback );
virtual ~ConVar( void );
virtual bool IsFlagSet( int flag ) const;
virtual const char* GetHelpText( void ) const;
virtual bool IsRegistered( void ) const;
virtual const char *GetName( void ) const;
virtual void AddFlags( int flags );
virtual bool IsCommand( void ) const;
// Install a change callback (there shouldn't already be one....)
void InstallChangeCallback( FnChangeCallback_t callback );
// Retrieve value
FORCEINLINE_CVAR float GetFloat( void ) const;
FORCEINLINE_CVAR int GetInt( void ) const;
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
FORCEINLINE_CVAR char const *GetString( void ) const;
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
// from alloc/free across dll/exe boundaries.
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
virtual void SetValue( const char *value );
virtual void SetValue( float value );
virtual void SetValue( int value );
// Reset to default value
void Revert( void );
// True if it has a min/max setting
bool GetMin( float& minVal ) const;
bool GetMax( float& maxVal ) const;
const char *GetDefault( void ) const;
private:
// Called by CCvar when the value of a var is changing.
virtual void InternalSetValue(const char *value);
// For CVARs marked FCVAR_NEVER_AS_STRING
virtual void InternalSetFloatValue( float fNewValue );
virtual void InternalSetIntValue( int nValue );
virtual bool ClampValue( float& value );
virtual void ChangeStringValue( const char *tempVal, float flOldValue );
virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0,
const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
// Used internally by OneTimeInit to initialize.
virtual void Init();
private:
// This either points to "this" or it points to the original declaration of a ConVar.
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
ConVar *m_pParent;
// Static data
const char *m_pszDefaultValue;
// Value
// Dynamically allocated
char *m_pszString;
int m_StringLength;
// Values
float m_fValue;
int m_nValue;
// Min/Max values
bool m_bHasMin;
float m_fMinVal;
bool m_bHasMax;
float m_fMaxVal;
// Call this function when ConVar changes
FnChangeCallback_t m_fnChangeCallback;
public: // Hackalicous
inline FnChangeCallback_t GetCallback() const
{
return m_fnChangeCallback;
}
inline void SetMin(bool set, float min=0.0)
{
m_bHasMin = set;
m_fMinVal = min;
}
inline void SetMax(bool set, float max=0.0)
{
m_bHasMax = set;
m_fMaxVal = max;
}
};
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
// Output : float
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
{
return m_pParent->m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
// Output : int
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
{
return m_pParent->m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
// Output : const char *
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
{
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
return "FCVAR_NEVER_AS_STRING";
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
}
//-----------------------------------------------------------------------------
// Used to read/write convars that already exist (replaces the FindVar method)
//-----------------------------------------------------------------------------
class ConVarRef
{
public:
ConVarRef( const char *pName );
ConVarRef( const char *pName, bool bIgnoreMissing );
ConVarRef( IConVar *pConVar );
void Init( const char *pName, bool bIgnoreMissing );
bool IsValid() const;
bool IsFlagSet( int nFlags ) const;
IConVar *GetLinkedConVar();
// Get/Set value
float GetFloat( void ) const;
int GetInt( void ) const;
bool GetBool() const { return !!GetInt(); }
const char *GetString( void ) const;
void SetValue( const char *pValue );
void SetValue( float flValue );
void SetValue( int nValue );
void SetValue( bool bValue );
const char *GetName() const;
const char *GetDefault() const;
private:
// High-speed method to read convar data
IConVar *m_pConVar;
ConVar *m_pConVarState;
};
//-----------------------------------------------------------------------------
// Did we find an existing convar of that name?
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
{
return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
}
FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
{
return m_pConVar;
}
FORCEINLINE_CVAR const char *ConVarRef::GetName() const
{
return m_pConVar->GetName();
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
{
return m_pConVarState->m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
{
return m_pConVarState->m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const
{
Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
return m_pConVarState->m_pszString;
}
FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
{
m_pConVar->SetValue( pValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
{
m_pConVar->SetValue( flValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
{
m_pConVar->SetValue( nValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
{
m_pConVar->SetValue( bValue ? 1 : 0 );
}
FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
{
return m_pConVarState->m_pszDefaultValue;
}
//-----------------------------------------------------------------------------
// Called by the framework to register ConCommands with the ICVar
//-----------------------------------------------------------------------------
void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
void ConVar_Unregister( );
//-----------------------------------------------------------------------------
// Utility methods
//-----------------------------------------------------------------------------
void ConVar_PrintFlags( const ConCommandBase *var );
void ConVar_PrintDescription( const ConCommandBase *pVar );
//-----------------------------------------------------------------------------
// Purpose: Utility class to quickly allow ConCommands to call member methods
//-----------------------------------------------------------------------------
#if defined _MSC_VER
#pragma warning (disable : 4355 )
#endif
template< class T >
class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
{
typedef ConCommand BaseClass;
typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
public:
CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
{
m_pOwner = pOwner;
m_Func = callback;
m_CompletionFunc = completionFunc;
}
~CConCommandMemberAccessor()
{
Shutdown();
}
void SetOwner( T* pOwner )
{
m_pOwner = pOwner;
}
virtual void CommandCallback( const CCommand &command )
{
Assert( m_pOwner && m_Func );
(m_pOwner->*m_Func)( command );
}
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
{
Assert( m_pOwner && m_CompletionFunc );
return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
}
private:
T* m_pOwner;
FnMemberCommandCallback_t m_Func;
FnMemberCommandCompletionCallback_t m_CompletionFunc;
};
#if defined _MSC_VER
#pragma warning ( default : 4355 )
#endif
//-----------------------------------------------------------------------------
// Purpose: Utility macros to quicky generate a simple console command
//-----------------------------------------------------------------------------
#define CON_COMMAND( name, description ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description ); \
static void name( const CCommand &args )
#define CON_COMMAND_F( name, description, flags ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description, flags ); \
static void name( const CCommand &args )
#define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description, flags, completion ); \
static void name( const CCommand &args )
#define CON_COMMAND_EXTERN( name, _funcname, description ) \
void _funcname( const CCommand &args ); \
static ConCommand name##_command( #name, _funcname, description ); \
void _funcname( const CCommand &args )
#define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
void _funcname( const CCommand &args ); \
static ConCommand name##_command( #name, _funcname, description, flags ); \
void _funcname( const CCommand &args )
#define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
void _funcname( const CCommand &args ); \
friend class CCommandMemberInitializer_##_funcname; \
class CCommandMemberInitializer_##_funcname \
{ \
public: \
CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \
{ \
m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \
} \
private: \
CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \
}; \
\
CCommandMemberInitializer_##_funcname m_##_funcname##_register; \
#endif // CONVAR_H

File diff suppressed because it is too large Load Diff

View File

@ -83,10 +83,12 @@ binary.sources += [
'frame_tasks.cpp',
'smn_halflife.cpp',
'FrameIterator.cpp',
'NativeInvoker.cpp',
]
if builder.target.platform == 'windows':
binary.sources += ['thread/WinThreads.cpp']
else:
binary.sources += ['thread/PosixThreads.cpp']
SM.binaries += [builder.Add(binary)]

View File

@ -82,6 +82,10 @@ struct AuthMethod
{
return strcmp(name, method->name.c_str()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
struct UserAuth

View File

@ -948,20 +948,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand
CExtension *pExt;
unsigned int num = 1;
List<CExtension *> required; // List of loaded and required extensions
List<CExtension *> optional; // List of non loaded optional extensions
for (iter = m_Libs.begin(); iter != m_Libs.end(); iter++)
{
pExt = (*iter);
if (pExt->IsLoaded() || pExt->IsRequired())
required.push_back(pExt);
else if (!pExt->IsLoaded() && !pExt->IsRequired())
optional.push_back(pExt);
}
switch (required.size())
switch (m_Libs.size())
{
case 1:
{
@ -975,11 +962,11 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand
}
default:
{
rootmenu->ConsolePrint("[SM] Displaying %d extensions:", required.size());
rootmenu->ConsolePrint("[SM] Displaying %d extensions:", m_Libs.size());
break;
}
}
for (iter = required.begin(); iter != required.end(); iter++,num++)
for (iter = m_Libs.begin(); iter != m_Libs.end(); iter++,num++)
{
pExt = (*iter);
if (pExt->IsLoaded())
@ -998,32 +985,13 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand
rootmenu->ConsolePrint("[%02d] %s (%s): %s", num, name, version, descr);
}
}
else
else if(pExt->IsRequired() || libsys->PathExists(pExt->GetPath()))
{
rootmenu->ConsolePrint("[%02d] <FAILED> file \"%s\": %s", num, pExt->GetFilename(), pExt->m_Error.c_str());
}
}
if (optional.size())
{
num = 1;
switch (optional.size())
else
{
case 1:
{
rootmenu->ConsolePrint("\n[SM] Displaying 1 optional extension not found:");
break;
}
default:
{
rootmenu->ConsolePrint("\n[SM] Displaying %d optional extensions not found:", optional.size());
break;
}
}
for (iter = optional.begin(); iter != optional.end(); iter++,num++)
{
pExt = (*iter);
rootmenu->ConsolePrint("[%02d] \"%s\"", num, pExt->GetFilename());
rootmenu->ConsolePrint("[%02d] <OPTIONAL> file \"%s\": %s", num, pExt->GetFilename(), pExt->m_Error.c_str());
}
}
return;

View File

@ -46,18 +46,13 @@ SafeFrameIterator::SafeFrameIterator(IFrameIterator *it)
bool SafeFrameIterator::Done() const
{
return current == frames.length();
return current >= frames.length();
}
bool SafeFrameIterator::Next()
{
if (!this->Done())
{
current++;
return true;
}
return false;
current++;
return !this->Done();
}
void SafeFrameIterator::Reset()

View File

@ -72,6 +72,10 @@ public: //NameHashSet
{
return strcmp(key, value->m_File) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
private:
char m_File[PLATFORM_MAX_PATH];
char m_CurFile[PLATFORM_MAX_PATH];

View File

@ -110,6 +110,10 @@ struct QHandleType
{
return type->name && type->name->compare(key) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
typedef ke::Lambda<void(const char *)> HandleReporter;

View File

@ -36,6 +36,7 @@
#include <am-string.h>
#include <am-utility.h>
#include <am-refcounting.h>
#include <sm_stringhashmap.h>
#include "common_logic.h"
class CNativeOwner;
@ -93,6 +94,10 @@ struct Native : public ke::Refcounted<Native>
{
return strcmp(name, entry->name()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};

View File

@ -0,0 +1,321 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn 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 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include <stdio.h>
#include <string.h>
#include "NativeInvoker.h"
/********************
* FUNCTION CALLING *
********************/
NativeInvoker::NativeInvoker(IPluginContext *pContext, const ke::RefPtr<Native> &native)
: context_(pContext),
m_curparam(0),
m_errorstate(SP_ERROR_NONE),
native_(native)
{
}
NativeInvoker::~NativeInvoker()
{
Cancel();
}
bool
NativeInvoker::IsRunnable()
{
return true;
}
IPluginContext *
NativeInvoker::GetParentContext()
{
return context_;
}
int NativeInvoker::PushCell(cell_t cell)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
return SetError(SP_ERROR_PARAMS_MAX);
m_info[m_curparam].marked = false;
m_params[m_curparam] = cell;
m_curparam++;
return SP_ERROR_NONE;
}
int
NativeInvoker::PushCellByRef(cell_t *cell, int flags)
{
return PushArray(cell, 1, flags);
}
int
NativeInvoker::PushFloat(float number)
{
cell_t val = sp::FloatCellUnion(number).cell;
return PushCell(val);
}
int
NativeInvoker::PushFloatByRef(float *number, int flags)
{
return PushCellByRef((cell_t *)number, flags);
}
int
NativeInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
ParamInfo *info = &m_info[m_curparam];
info->flags = inarray ? copyback : 0;
info->marked = true;
info->size = cells;
info->str.is_sz = false;
info->orig_addr = inarray;
m_curparam++;
return SP_ERROR_NONE;
}
int
NativeInvoker::PushString(const char *string)
{
return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
}
int
NativeInvoker::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
{
return _PushString(buffer, sz_flags, cp_flags, length);
}
int
NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
return SetError(SP_ERROR_PARAMS_MAX);
ParamInfo *info = &m_info[m_curparam];
info->marked = true;
info->orig_addr = (cell_t *)string;
info->flags = cp_flags;
info->size = len;
info->str.sz_flags = sz_flags;
info->str.is_sz = true;
m_curparam++;
return SP_ERROR_NONE;
}
void
NativeInvoker::Cancel()
{
if (!m_curparam)
return;
m_errorstate = SP_ERROR_NONE;
m_curparam = 0;
}
int
NativeInvoker::Execute(cell_t *result, cell_t buffer, cell_t size)
{
context_->ClearLastNativeError();
// For backward compatibility, we have to clear the exception state.
// Otherwise code like this:
//
// static cell_t native(cx, params) {
// for (auto callback : callbacks) {
// callback->Execute();
// }
// }
//
// Could unintentionally leak a pending exception back to the caller,
// which wouldn't have happened before the Great Exception Refactoring.
SourcePawn::ExceptionHandler eh(context_);
eh.Debug(!size);
if (!Invoke(result)) {
if(size)
context_->StringToLocalUTF8(buffer, size, eh.Message(), NULL);
int Err = context_->GetLastNativeError();
context_->ClearLastNativeError();
return Err;
}
return SP_ERROR_NONE;
}
bool
NativeInvoker::Invoke(cell_t *result)
{
if (!IsRunnable()) {
Cancel();
context_->ReportErrorNumber(SP_ERROR_NOT_RUNNABLE);
return false;
}
if (int err = m_errorstate) {
Cancel();
context_->ReportErrorNumber(err);
return false;
}
//This is for re-entrancy!
cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1];
cell_t *temp_params = &_temp_params[1];
ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
unsigned int numparams = m_curparam;
unsigned int i;
if (numparams)
{
//Save the info locally, then reset it for re-entrant calls.
memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
}
m_curparam = 0;
/* Initialize 0th parameter */
_temp_params[0] = numparams;
/* Browse the parameters and build arrays */
bool ok = true;
for (i=0; i<numparams; i++) {
/* Is this marked as an array? */
if (temp_info[i].marked) {
if (!temp_info[i].str.is_sz) {
/* Allocate a normal/generic array */
int err = context_->HeapAlloc(
temp_info[i].size,
&(temp_info[i].local_addr),
&(temp_info[i].phys_addr));
if (err != SP_ERROR_NONE) {
context_->ReportErrorNumber(err);
ok = false;
break;
}
if (temp_info[i].orig_addr)
{
memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size);
}
} else {
/* Calculate cells required for the string */
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
/* Allocate the buffer */
int err = context_->HeapAlloc(
cells,
&(temp_info[i].local_addr),
&(temp_info[i].phys_addr));
if (err != SP_ERROR_NONE) {
context_->ReportErrorNumber(err);
ok = false;
break;
}
/* Copy original string if necessary */
if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL))
{
/* Cut off UTF-8 properly */
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8) {
context_->StringToLocalUTF8(
temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr,
NULL);
}
/* Copy a binary blob */
else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY)
{
memmove(temp_info[i].phys_addr, temp_info[i].orig_addr, temp_info[i].size);
}
/* Copy ASCII characters */
else
{
context_->StringToLocal(
temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr);
}
}
} /* End array/string calculation */
/* Update the pushed parameter with the byref local address */
temp_params[i] = temp_info[i].local_addr;
} else {
/* Just copy the value normally */
temp_params[i] = m_params[i];
}
}
/* Make the call if we can */
if (ok)
{
*result = native_->func()(context_, _temp_params);
}
/* i should be equal to the last valid parameter + 1 */
bool docopies = ok;
while (i--) {
if (!temp_info[i].marked)
continue;
if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK)) {
if (temp_info[i].orig_addr) {
if (temp_info[i].str.is_sz) {
memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size);
} else {
if (temp_info[i].size == 1) {
*temp_info[i].orig_addr = *(temp_info[i].phys_addr);
} else {
memcpy(temp_info[i].orig_addr,
temp_info[i].phys_addr,
temp_info[i].size * sizeof(cell_t));
}
}
}
}
if (int err = context_->HeapPop(temp_info[i].local_addr))
context_->ReportErrorNumber(err);
}
return context_->GetLastNativeError() == SP_ERROR_NONE;
}
int
NativeInvoker::SetError(int err)
{
m_errorstate = err;
return err;
}
int NativeInvoker::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) { return 0; }
funcid_t NativeInvoker::GetFunctionID() { return 0; }
int NativeInvoker::Execute2(IPluginContext *ctx, cell_t *result) { return 0; }
int NativeInvoker::CallFunction2(IPluginContext *ctx, const cell_t *params, unsigned int num_params, cell_t *result) { return 0; }
IPluginRuntime *NativeInvoker::GetParentRuntime() { return NULL; }

View File

@ -0,0 +1,79 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn 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 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#include <sp_vm_api.h>
#include <amtl/am-autoptr.h>
#include <amtl/am-refcounting.h>
#include "Native.h"
struct ParamInfo
{
int flags; /* Copy-back flags */
bool marked; /* Whether this is marked as being used */
cell_t local_addr; /* Local address to free */
cell_t *phys_addr; /* Physical address of our copy */
cell_t *orig_addr; /* Original address to copy back to */
ucell_t size; /* Size of array in bytes */
struct {
bool is_sz; /* is a string */
int sz_flags; /* has sz flags */
} str;
};
class NativeInvoker : public IPluginFunction
{
public:
NativeInvoker(IPluginContext *pContext, const ke::RefPtr<Native> &native);
virtual ~NativeInvoker();
public:
int PushCell(cell_t cell);
int PushCellByRef(cell_t *cell, int flags);
int PushFloat(float number);
int PushFloatByRef(float *number, int flags);
int PushArray(cell_t *inarray, unsigned int cells, int copyback);
int PushString(const char *string);
int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
int Execute(cell_t *result, cell_t buffer=0, cell_t size=0);
void Cancel();
int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
IPluginContext *GetParentContext();
bool Invoke(cell_t *result);
bool IsRunnable();
funcid_t GetFunctionID();
int Execute2(IPluginContext *ctx, cell_t *result);
int CallFunction2(IPluginContext *ctx,
const cell_t *params,
unsigned int num_params,
cell_t *result);
IPluginRuntime *GetParentRuntime();
const char *DebugName() {
return native_->name();
}
private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
int SetError(int err);
private:
IPluginContext *context_;
cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam;
int m_errorstate;
ke::RefPtr<Native> native_;
};
#endif //_INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_

View File

@ -31,7 +31,6 @@
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include "PluginSys.h"
#include "ShareSys.h"
#include <ILibrarySys.h>
@ -47,7 +46,6 @@
#include "frame_tasks.h"
#include <amtl/am-string.h>
#include <amtl/am-linkedlist.h>
#include <amtl/am-uniqueptr.h>
#include <bridge/include/IVEngineServerBridge.h>
#include <bridge/include/CoreProvider.h>
@ -934,38 +932,16 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
libsys->CloseDirectory(dir);
}
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
char *strdup_tolower(const char *input)
{
char *str = strdup(input);
for (char *c = str; *c; c++)
{
*c = tolower((unsigned char)*c);
}
return str;
}
#endif
LoadRes CPluginManager::LoadPlugin(CPlugin **aResult, const char *path, bool debug, PluginType type)
{
if (m_LoadingLocked)
return LoadRes_NeverLoad;
/* For windows & mac, we convert the path to lower-case in order to avoid duplicate plugin loading */
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
ke::UniquePtr<char> finalPath = ke::UniquePtr<char>(strdup_tolower(path));
#else
ke::UniquePtr<char> finalPath = ke::UniquePtr<char>(strdup(path));
#endif
/**
* Does this plugin already exist?
*/
CPlugin *pPlugin;
if (m_LoadLookup.retrieve(finalPath.get(), &pPlugin))
if (m_LoadLookup.retrieve(path, &pPlugin))
{
/* Check to see if we should try reloading it */
if (pPlugin->GetStatus() == Plugin_BadLoad
@ -978,12 +954,11 @@ LoadRes CPluginManager::LoadPlugin(CPlugin **aResult, const char *path, bool deb
{
if (aResult)
*aResult = pPlugin;
return LoadRes_AlreadyLoaded;
}
}
CPlugin *plugin = CompileAndPrep(finalPath.get());
CPlugin *plugin = CompileAndPrep(path);
// Assign our outparam so we can return early. It must be set.
*aResult = plugin;
@ -2416,4 +2391,4 @@ static OldPluginAPI sOldPluginAPI;
IPluginManager *CPluginManager::GetOldAPI()
{
return &sOldPluginAPI;
}
}

View File

@ -55,6 +55,9 @@
#include <bridge/include/IScriptManager.h>
#include <am-function.h>
#include <ReentrantList.h>
#ifdef PLATFORM_APPLE
#include <cctype>
#endif
class CPlayer;
@ -143,11 +146,6 @@ public:
*/
static CPlugin *Create(const char *file);
static inline bool matches(const char *file, const CPlugin *plugin)
{
return strcmp(plugin->m_filename, file) == 0;
}
public:
// Evicts the plugin from memory and sets an error state.
void EvictWithError(PluginStatus status, const char *error_fmt, ...);
@ -483,7 +481,54 @@ private:
typedef decltype(m_listeners)::iterator ListenerIter;
typedef decltype(m_plugins)::iterator PluginIter;
NameHashSet<CPlugin *> m_LoadLookup;
struct CPluginPolicy
{
static inline uint32_t hash(const detail::CharsAndLength &key)
{
/* For windows & mac, we convert the path to lower-case in order to avoid duplicate plugin loading */
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
const char *original = key.chars();
char *copy = strdup(original);
for (size_t i = 0; copy[i]; ++i)
{
copy[i] = tolower(copy[i]);
}
uint32_t hash = detail::CharsAndLength(copy).hash();
free(copy);
return hash;
#else
return key.hash();
#endif
}
static inline bool matches(const char *file, const CPlugin *plugin)
{
const char *pluginFile = const_cast<CPlugin*>(plugin)->GetFilename();
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
size_t fileLen = strlen(file);
if (fileLen != strlen(pluginFile))
{
return false;
}
for (size_t i = 0; i < fileLen; ++i)
{
if (tolower(file[i]) != tolower(pluginFile[i]))
{
return false;
}
}
return true;
#else
return strcmp(pluginFile, file) == 0;
#endif
}
};
NameHashSet<CPlugin *, CPluginPolicy> m_LoadLookup;
bool m_AllPluginsLoaded;
IdentityToken_t *m_MyIdent;

View File

@ -46,6 +46,10 @@ struct ConsoleEntry
{
return strcmp(name, entry->command.c_str()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
class RootConsoleMenu :

View File

@ -267,8 +267,7 @@ static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params)
size_t len;
{
DetectExceptions eh(pContext);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
len = g_pSM->FormatString(buffer, sizeof(buffer) - 2, pContext, params, 2);
len = g_pSM->FormatString(buffer, sizeof(buffer) - 1, pContext, params, 2);
if (eh.HasException())
return 0;
}

View File

@ -35,6 +35,8 @@
#include <IForwardSys.h>
#include <ISourceMod.h>
#include <amtl/am-autoptr.h>
#include "ShareSys.h"
#include "NativeInvoker.h"
HandleType_t g_GlobalFwdType = 0;
HandleType_t g_PrivateFwdType = 0;
@ -43,6 +45,7 @@ static bool s_CallStarted = false;
static ICallable *s_pCallable = NULL;
static IPluginFunction *s_pFunction = NULL;
static IForward *s_pForward = NULL;
static NativeInvoker *s_pInvoker = NULL;
class ForwardNativeHelpers :
public SMGlobalClass,
@ -102,6 +105,9 @@ inline void ResetCall()
s_pFunction = NULL;
s_pForward = NULL;
s_pCallable = NULL;
if(s_pInvoker)
delete s_pInvoker;
s_pInvoker = NULL;
}
static cell_t sm_GetFunctionByName(IPluginContext *pContext, const cell_t *params)
@ -366,6 +372,27 @@ static cell_t sm_CallStartForward(IPluginContext *pContext, const cell_t *params
return 1;
}
static cell_t sm_CallStartNative(IPluginContext *pContext, const cell_t *params)
{
ResetCall();
char *name;
pContext->LocalToString(params[1], &name);
ke::RefPtr<Native> pNative = g_ShareSys.FindNative(name);
if (!pNative)
return 0;//pContext->ThrowNativeError("Invalid native \"%s\"", name);
s_pInvoker = new NativeInvoker(pContext, pNative);
s_pCallable = static_cast<ICallable *>(s_pInvoker);
s_CallStarted = true;
return 1;
}
static cell_t sm_CallPushCell(IPluginContext *pContext, const cell_t *params)
{
int err;
@ -656,6 +683,39 @@ static cell_t sm_CallFinish(IPluginContext *pContext, const cell_t *params)
IForward *pForward = s_pForward;
ResetCall();
err = pForward->Execute(result, NULL);
} else if (s_pInvoker) {
err = s_pInvoker->Execute(result);
ResetCall();
}
return err;
}
static cell_t sm_CallFinishEx(IPluginContext *pContext, const cell_t *params)
{
int err = SP_ERROR_NOT_RUNNABLE;
cell_t *result;
if (!s_CallStarted)
{
return pContext->ThrowNativeError("Cannot finish call when there is no call in progress");
}
pContext->LocalToPhysAddr(params[1], &result);
// Note: Execute() swallows exceptions, so this is okay.
if (s_pFunction)
{
IPluginFunction *pFunction = s_pFunction;
ResetCall();
err = pFunction->Execute(result, params[2], params[3]);
} else if (s_pForward) {
IForward *pForward = s_pForward;
ResetCall();
err = pForward->Execute(result, NULL);
} else if (s_pInvoker) {
err = s_pInvoker->Execute(result, params[2], params[3]);
ResetCall();
}
return err;
@ -742,6 +802,7 @@ REGISTER_NATIVES(functionNatives)
{"RemoveAllFromForward", sm_RemoveAllFromForward},
{"Call_StartFunction", sm_CallStartFunction},
{"Call_StartForward", sm_CallStartForward},
{"Call_StartNative", sm_CallStartNative},
{"Call_PushCell", sm_CallPushCell},
{"Call_PushCellRef", sm_CallPushCellRef},
{"Call_PushFloat", sm_CallPushFloat},
@ -753,6 +814,7 @@ REGISTER_NATIVES(functionNatives)
{"Call_PushNullVector", sm_CallPushNullVector},
{"Call_PushNullString", sm_CallPushNullString},
{"Call_Finish", sm_CallFinish},
{"Call_FinishEx", sm_CallFinishEx},
{"Call_Cancel", sm_CallCancel},
{"RequestFrame", sm_AddFrameAction},
{NULL, NULL},

View File

@ -58,6 +58,10 @@ struct maplist_info_t
{
return strcmp(value->name, key) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
#define MAPLIST_FLAG_MAPSFOLDER (1<<0) /**< On failure, use all maps in the maps folder. */

View File

@ -816,8 +816,14 @@ static cell_t GetMenuItem(IPluginContext *pContext, const cell_t *params)
ItemDrawInfo dr;
const char *info;
cell_t client = (params[0] >= 8) ? params[8] : 0;
if(!client && menu->IsPerClientShuffled())
{
return pContext->ThrowNativeError("This menu has been per-client random shuffled. "
"You have to call GetMenuItem with a client index!");
}
if ((info=menu->GetItemInfo(params[2], &dr)) == NULL)
if ((info=menu->GetItemInfo(params[2], &dr, client)) == NULL)
{
return 0;
}
@ -832,6 +838,57 @@ static cell_t GetMenuItem(IPluginContext *pContext, const cell_t *params)
return 1;
}
static cell_t MenuShufflePerClient(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = (Handle_t)params[1];
HandleError err;
IBaseMenu *menu;
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
{
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
}
int start = params[2];
int stop = params[3];
if (stop > 0 && !(stop >= start))
{
return pContext->ThrowNativeError("Stop must be -1 or >= start!");
}
menu->ShufflePerClient(start, stop);
return 1;
}
static cell_t MenuSetClientMapping(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = (Handle_t)params[1];
HandleError err;
IBaseMenu *menu;
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
{
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
}
int client = params[2];
if (client < 1 || client > SM_MAXPLAYERS)
{
return pContext->ThrowNativeError("Invalid client index!");
}
cell_t *array;
pContext->LocalToPhysAddr(params[3], &array);
int length = params[4];
menu->SetClientMapping(client, array, length);
return 1;
}
static cell_t SetMenuPagination(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = (Handle_t)params[1];
@ -1645,6 +1702,8 @@ REGISTER_NATIVES(menuNatives)
{"SetPanelKeys", SetPanelKeys},
{"SetVoteResultCallback", SetVoteResultCallback},
{"VoteMenu", VoteMenu},
{"MenuShufflePerClient", MenuShufflePerClient},
{"MenuSetClientMapping", MenuSetClientMapping},
{"SetMenuNoVoteButton", SetMenuNoVoteButton},
// Transitional syntax support.
@ -1673,6 +1732,8 @@ REGISTER_NATIVES(menuNatives)
{"Menu.ToPanel", CreatePanelFromMenu},
{"Menu.Cancel", CancelMenu},
{"Menu.DisplayVote", VoteMenu},
{"Menu.ShufflePerClient", MenuShufflePerClient},
{"Menu.SetClientMapping", MenuSetClientMapping},
{"Menu.Pagination.get", GetMenuPagination},
{"Menu.Pagination.set", SetMenuPagination},
{"Menu.OptionFlags.get", GetMenuOptionFlags},

View File

@ -141,6 +141,7 @@ public: //ICommandTargetProcessor
smtf->fun->PushString(info->pattern);
smtf->fun->PushCell(ahc.getClone());
smtf->fun->PushCell(info->admin);
cell_t result = 0;
if (smtf->fun->Execute(&result) != SP_ERROR_NONE || !result)
return false;
@ -1460,24 +1461,23 @@ static cell_t IsClientInKickQueue(IPluginContext *pContext, const cell_t *params
return pPlayer->IsInKickQueue() ? 1 : 0;
}
cmd_target_info_t g_ProcessTargetString_info;
static cell_t ProcessTargetString(IPluginContext *pContext, const cell_t *params)
{
cmd_target_info_t info;
pContext->LocalToString(params[1], (char **) &info.pattern);
info.admin = params[2];
pContext->LocalToPhysAddr(params[3], &info.targets);
info.max_targets = params[4];
info.flags = params[5];
pContext->LocalToString(params[6], &info.target_name);
info.target_name_maxlength = params[7];
pContext->LocalToString(params[1], (char **) &g_ProcessTargetString_info.pattern);
g_ProcessTargetString_info.admin = params[2];
pContext->LocalToPhysAddr(params[3], &g_ProcessTargetString_info.targets);
g_ProcessTargetString_info.max_targets = params[4];
g_ProcessTargetString_info.flags = params[5];
pContext->LocalToString(params[6], &g_ProcessTargetString_info.target_name);
g_ProcessTargetString_info.target_name_maxlength = params[7];
cell_t *tn_is_ml;
pContext->LocalToPhysAddr(params[8], &tn_is_ml);
playerhelpers->ProcessCommandTarget(&info);
playerhelpers->ProcessCommandTarget(&g_ProcessTargetString_info);
if (info.target_name_style == COMMAND_TARGETNAME_ML)
if (g_ProcessTargetString_info.target_name_style == COMMAND_TARGETNAME_ML)
{
*tn_is_ml = 1;
}
@ -1486,16 +1486,30 @@ static cell_t ProcessTargetString(IPluginContext *pContext, const cell_t *params
*tn_is_ml = 0;
}
if (info.num_targets == 0)
if (g_ProcessTargetString_info.num_targets == 0)
{
return info.reason;
return g_ProcessTargetString_info.reason;
}
else
{
return info.num_targets;
return g_ProcessTargetString_info.num_targets;
}
}
static cell_t GetLastProcessTargetString(IPluginContext *pContext, const cell_t *params)
{
cell_t *admin, *flags;
pContext->StringToLocalUTF8(params[1], params[2], g_ProcessTargetString_info.pattern, NULL);
pContext->LocalToPhysAddr(params[3], &admin);
pContext->LocalToPhysAddr(params[4], &flags);
*admin = g_ProcessTargetString_info.admin;
*flags = g_ProcessTargetString_info.flags;
return 0;
}
static cell_t FormatActivitySource(IPluginContext *pContext, const cell_t *params)
{
int value;
@ -1647,6 +1661,7 @@ REGISTER_NATIVES(playernatives)
{ "NotifyPostAdminCheck", NotifyPostAdminCheck },
{ "IsClientInKickQueue", IsClientInKickQueue },
{ "ProcessTargetString", ProcessTargetString },
{ "GetLastProcessTargetString", GetLastProcessTargetString },
{ "FormatActivitySource", FormatActivitySource },
{ "GetClientSerial", sm_GetClientSerial },
{ "GetClientFromSerial", sm_GetClientFromSerial },

View File

@ -45,35 +45,14 @@
#include "ConCmdManager.h"
#include "IDBDriver.h"
#include "provider.h"
#if SOURCE_ENGINE >= SE_ALIENSWARM
# include "convar_sm_swarm.h"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
# include "convar_sm_l4d.h"
#elif SOURCE_ENGINE >= SE_ORANGEBOX
# include "convar_sm_ob.h"
#else
# include "convar_sm.h"
#endif
#include "sm_convar.h"
#include <amtl/os/am-shared-library.h>
#include <amtl/os/am-path.h>
#include <bridge/include/IVEngineServerBridge.h>
#include <bridge/include/IPlayerInfoBridge.h>
#include <bridge/include/IFileSystemBridge.h>
#if defined _WIN32
# define MATCHMAKINGDS_SUFFIX ""
# define MATCHMAKINGDS_EXT "dll"
#elif defined __APPLE__
# define MATCHMAKINGDS_SUFFIX ""
# define MATCHMAKINGDS_EXT "dylib"
#elif defined __linux__
#if SOURCE_ENGINE < SE_LEFT4DEAD2
# define MATCHMAKINGDS_SUFFIX "_i486"
#else
# define MATCHMAKINGDS_SUFFIX ""
#endif
# define MATCHMAKINGDS_EXT "so"
#endif
#define MATCHMAKINGDS_NAME "matchmaking_ds" SOURCE_BIN_SUFFIX SOURCE_BIN_EXT
sm_logic_t logicore;
@ -653,10 +632,8 @@ void CoreProviderImpl::InitializeBridge()
char path[PLATFORM_MAX_PATH];
ke::path::Format(path, sizeof(path),
"%s/bin/matchmaking_ds%s.%s",
g_SMAPI->GetBaseDir(),
MATCHMAKINGDS_SUFFIX,
MATCHMAKINGDS_EXT);
"%s/bin/" MATCHMAKINGDS_NAME,
g_SMAPI->GetBaseDir());
if (ke::RefPtr<ke::SharedLib> mmlib = ke::SharedLib::Open(path, NULL, 0)) {
this->matchmakingDSFactory =

38
core/sm_convar.h Normal file
View File

@ -0,0 +1,38 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2018 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* 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
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#pragma once
#define protected public
#define private public
#include <tier1/convar.h>
#undef protected
#undef private

View File

@ -141,14 +141,14 @@ public:
if (m_CmdFlags.retrieve(name, &pCmd))
{
TrackConCommandBase(pCmd, this);
*flags = pCmd->GetFlags();
*flags = pCmd->m_nFlags;
return true;
}
else if ((pCmd=FindCommandBase(name)))
{
m_CmdFlags.insert(name, pCmd);
TrackConCommandBase(pCmd, this);
*flags = pCmd->GetFlags();
*flags = pCmd->m_nFlags;
return true;
}
else
@ -161,14 +161,14 @@ public:
ConCommandBase *pCmd;
if (m_CmdFlags.retrieve(name, &pCmd))
{
pCmd->SetFlags(flags);
pCmd->m_nFlags = flags;
TrackConCommandBase(pCmd, this);
return true;
}
else if ((pCmd=FindCommandBase(name)))
{
m_CmdFlags.insert(name, pCmd);
pCmd->SetFlags(flags);
pCmd->m_nFlags = flags;
TrackConCommandBase(pCmd, this);
return true;
}
@ -184,6 +184,10 @@ private:
{
return strcmp(name, base->GetName()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
NameHashSet<ConCommandBase *, ConCommandPolicy> m_CmdFlags;
} s_CommandFlagsHelper;
@ -540,7 +544,7 @@ static cell_t sm_GetConVarFlags(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
}
return pConVar->GetFlags();
return pConVar->m_nFlags;
}
static cell_t sm_SetConVarFlags(IPluginContext *pContext, const cell_t *params)
@ -555,7 +559,7 @@ static cell_t sm_SetConVarFlags(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
}
pConVar->SetFlags(params[2]);
pConVar->m_nFlags = params[2];
return 1;
}
@ -609,10 +613,12 @@ static cell_t sm_SetConVarBounds(IPluginContext *pContext, const cell_t *params)
switch (params[2])
{
case ConVarBound_Upper:
pConVar->SetMax(params[3] ? true : false, sp_ctof(params[4]));
pConVar->m_fMaxVal = sp_ctof(params[4]);
pConVar->m_bHasMax = params[3] ? true : false;
break;
case ConVarBound_Lower:
pConVar->SetMin(params[3] ? true : false, sp_ctof(params[4]));
pConVar->m_fMinVal = sp_ctof(params[4]);
pConVar->m_bHasMin = params[3] ? true : false;
break;
default:
return pContext->ThrowNativeError("Invalid ConVarBounds value %d");
@ -782,6 +788,16 @@ static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
return 1;
}
static cell_t sm_IsCommandCallback(IPluginContext *pContext, const cell_t *params)
{
const ICommandArgs *pCmd = g_HL2.PeekCommandStack();
if (!pCmd)
return 0;
return 1;
}
static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params)
{
const ICommandArgs *pCmd = g_HL2.PeekCommandStack();
@ -1086,7 +1102,7 @@ static cell_t FindFirstConCommand(IPluginContext *pContext, const cell_t *params
pContext->StringToLocalUTF8(params[1], params[2], pConCmd->GetName(), NULL);
*pIsCmd = pConCmd->IsCommand() ? 1 : 0;
*pFlags = pConCmd->GetFlags();
*pFlags = pConCmd->m_nFlags;
if (params[6])
{
@ -1135,7 +1151,7 @@ static cell_t FindNextConCommand(IPluginContext *pContext, const cell_t *params)
pContext->StringToLocalUTF8(params[2], params[3], pConCmd->GetName(), NULL);
*pIsCmd = pConCmd->IsCommand() ? 1 : 0;
*pFlags = pConCmd->GetFlags();
*pFlags = pConCmd->m_nFlags;
if (params[7])
{
@ -1325,6 +1341,7 @@ REGISTER_NATIVES(consoleNatives)
{"GetConVarDefault", GetConVarDefault},
{"RegServerCmd", sm_RegServerCmd},
{"RegConsoleCmd", sm_RegConsoleCmd},
{"IsCommandCallback", sm_IsCommandCallback},
{"GetCmdArgString", sm_GetCmdArgString},
{"GetCmdArgs", sm_GetCmdArgs},
{"GetCmdArg", sm_GetCmdArg},

View File

@ -94,6 +94,7 @@ enum PropFieldType
PropField_Variant, /**< Valid for variants/any. (User must know type) */
};
// From game/server/variant_t.h, same on all supported games.
class variant_t
{
public:
@ -111,6 +112,15 @@ public:
fieldtype_t fieldType;
};
// From game/server/baseentity.h, same on all supported games.
struct inputdata_t
{
CBaseEntity *pActivator; // The entity that initially caused this chain of output events.
CBaseEntity *pCaller; // The entity that fired this particular output.
variant_t value; // The data parameter for this output.
int nOutputID; // The unique ID of the output that was fired.
};
inline bool CanSetPropName(const char *pszPropName)
{
#if SOURCE_ENGINE == SE_CSGO
@ -280,6 +290,47 @@ static cell_t RemoveEdict(IPluginContext *pContext, const cell_t *params)
return 1;
}
static cell_t RemoveEntity(IPluginContext *pContext, const cell_t *params)
{
auto *pEntity = GetEntity(params[1]);
if (!pEntity)
{
return pContext->ThrowNativeError("Entity %d (%d) is not a valid entity", g_HL2.ReferenceToIndex(params[1]), params[1]);
}
// Some games have UTIL_Remove exposed on IServerTools, but for consistence, we'll
// use this method for all. Results in DeathNotice( this ) being called on parent,
// and parent being cleared (both if any parent) before UTIL_Remove is called.
static inputfunc_t fnKillEntity = nullptr;
if (!fnKillEntity)
{
// Get world, as other ents aren't guaranteed to inherit full datadesc (but kill func is same for all)
CBaseEntity *pGetterEnt = g_HL2.ReferenceToEntity(0);
if (pGetterEnt == nullptr)
{
// If we don't have a world entity yet, we'll have to rely on the given entity. Does this even make sense???
pGetterEnt = pEntity;
}
datamap_t *pMap = g_HL2.GetDataMap(pGetterEnt);
sm_datatable_info_t info;
if (!g_HL2.FindDataMapInfo(pMap, "InputKill", &info))
{
return pContext->ThrowNativeError("Failed to find Kill input!");
}
fnKillEntity = info.prop->inputFunc;
}
// Input data is ignored for this. No need to initialize
static inputdata_t data;
(pEntity->*fnKillEntity)(data);
return 1;
}
static cell_t IsValidEdict(IPluginContext *pContext, const cell_t *params)
{
edict_t *pEdict = GetEdict(params[1]);
@ -2640,6 +2691,7 @@ REGISTER_NATIVES(entityNatives)
{"IsEntNetworkable", IsEntNetworkable},
{"IsValidEdict", IsValidEdict},
{"IsValidEntity", IsValidEntity},
{"RemoveEntity", RemoveEntity},
{"RemoveEdict", RemoveEdict},
{"SetEdictFlags", SetEdictFlags},
{"SetEntData", SetEntData},

View File

@ -356,6 +356,27 @@ static cell_t GetAvgPackets(IPluginContext *pContext, const cell_t *params)
return sp_ftoc(value);
}
static cell_t sm_GetClientIClient(IPluginContext *pContext, const cell_t *params)
{
int client = params[1];
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
if (!pPlayer)
{
return pContext->ThrowNativeError("Client index %d is invalid", client);
}
else if (!pPlayer->IsConnected())
{
return pContext->ThrowNativeError("Client %d is not connected", client);
}
else if (pPlayer->IsFakeClient())
{
return pContext->ThrowNativeError("Client %d is a bot", client);
}
return (cell_t)pPlayer->GetIClient();
}
static cell_t RunAdminCacheChecks(IPluginContext *pContext, const cell_t *params)
{
int client = params[1];
@ -392,6 +413,7 @@ REGISTER_NATIVES(playernatives)
{"GetClientAvgChoke", GetAvgChoke},
{"GetClientAvgData", GetAvgData},
{"GetClientAvgPackets", GetAvgPackets},
{"GetClientIClient", sm_GetClientIClient },
{"RunAdminCacheChecks", RunAdminCacheChecks},
{NULL, NULL}
};

View File

@ -32,15 +32,7 @@
#ifndef _INCLUDE_SOURCEMOD_MM_API_H_
#define _INCLUDE_SOURCEMOD_MM_API_H_
#if SOURCE_ENGINE >= SE_ALIENSWARM
#include "convar_sm_swarm.h"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
#include "convar_sm_l4d.h"
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#include "convar_sm_ob.h"
#else
#include "convar_sm.h"
#endif
#include "sm_convar.h"
#include <ISmmPlugin.h>
#include <eiface.h>
#include <igameevents.h>

View File

@ -96,6 +96,10 @@ struct Cookie
{
return strcmp(name, cookie->name) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
class CookieManager : public IClientListener, public IPluginsListener

View File

@ -51,6 +51,7 @@ IGameConfig *g_pGameConf = NULL;
IGameEventManager2 *gameevents = NULL;
bool hooked_everything = false;
int g_msgHintText = -1;
CGlobalVars *gpGlobals;
SMEXT_LINK(&g_CStrike);
@ -107,6 +108,7 @@ bool CStrike::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool
{
GET_V_IFACE_CURRENT(GetEngineFactory, gameevents, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2);
GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
gpGlobals = ismm->GetCGlobals();
return true;
}

View File

@ -166,6 +166,7 @@ private:
extern IBinTools *g_pBinTools;
extern IGameConfig *g_pGameConf;
extern ISDKTools *g_pSDKTools;
extern CGlobalVars *gpGlobals;
extern int g_msgHintText;
extern bool g_pIgnoreTerminateDetour;
extern bool g_pIgnoreCSWeaponDropDetour;

View File

@ -126,7 +126,7 @@ DETOUR_DECL_MEMBER0(DetourWeaponPrice, int)
}
#endif
#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32)
#if SOURCE_ENGINE != SE_CSGO
DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason)
{
if (g_pIgnoreTerminateDetour)
@ -135,20 +135,31 @@ DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason)
DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason);
return;
}
#elif !defined(WIN32)
DETOUR_DECL_MEMBER4(DetourTerminateRound, void, float, delay, int, reason, int, unknown, int, unknown2)
{
if (g_pIgnoreTerminateDetour)
{
g_pIgnoreTerminateDetour = false;
DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason, unknown, unknown2);
return;
}
#else
//Windows CSGO
//char __userpurge TerminateRound(int a1@<ecx>, float a2@<xmm1>, int *a3)
// a1 - this
// a2 - delay
// a3 - reason
DETOUR_DECL_MEMBER1(DetourTerminateRound, void, int, reason)
// a4 - unknown
// a5 - unknown
DETOUR_DECL_MEMBER3(DetourTerminateRound, void, int, reason, int, unknown, int, unknown2)
{
float delay;
if (g_pIgnoreTerminateDetour)
{
g_pIgnoreTerminateDetour = false;
return DETOUR_MEMBER_CALL(DetourTerminateRound)(reason);
return DETOUR_MEMBER_CALL(DetourTerminateRound)(reason, unknown, unknown2);
}
//Save the delay
@ -178,11 +189,16 @@ DETOUR_DECL_MEMBER1(DetourTerminateRound, void, int, reason)
reason++;
#endif
#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32)
#if SOURCE_ENGINE != SE_CSGO
if (result == Pl_Changed)
return DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason);
return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgdelay, orgreason);
#elif !defined(WIN32)
if (result == Pl_Changed)
return DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason, unknown, unknown2);
return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgdelay, orgreason, unknown, unknown2);
#else
if (result == Pl_Changed)
{
@ -190,22 +206,22 @@ DETOUR_DECL_MEMBER1(DetourTerminateRound, void, int, reason)
{
movss xmm1, delay
}
return DETOUR_MEMBER_CALL(DetourTerminateRound)(reason);
return DETOUR_MEMBER_CALL(DetourTerminateRound)(reason, unknown, unknown2);
}
__asm
{
movss xmm1, orgdelay
}
return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgreason);
return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgreason, unknown, unknown2);
#endif
}
DETOUR_DECL_MEMBER3(DetourCSWeaponDrop, void, CBaseEntity *, weapon, bool, bDropShield, bool, bThrowForward)
DETOUR_DECL_MEMBER2(DetourCSWeaponDrop, void, CBaseEntity *, weapon, bool, bThrowForward)
{
if (g_pIgnoreCSWeaponDropDetour)
{
g_pIgnoreCSWeaponDropDetour = false;
DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, bDropShield, bThrowForward);
DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, bThrowForward);
return;
}
@ -220,7 +236,7 @@ DETOUR_DECL_MEMBER3(DetourCSWeaponDrop, void, CBaseEntity *, weapon, bool, bDrop
if (result == Pl_Continue)
{
DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, bDropShield, bThrowForward);
DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, bThrowForward);
}
return;

View File

@ -230,17 +230,14 @@ static cell_t CS_DropWeapon(IPluginContext *pContext, const cell_t *params)
if (!pWrapper)
{
REGISTER_NATIVE_ADDR(WEAPONDROP_GAMEDATA_NAME,
PassInfo pass[3]; \
PassInfo pass[2]; \
pass[0].flags = PASSFLAG_BYVAL; \
pass[0].type = PassType_Basic; \
pass[0].size = sizeof(CBaseEntity *); \
pass[1].flags = PASSFLAG_BYVAL; \
pass[1].type = PassType_Basic; \
pass[1].size = sizeof(bool); \
pass[2].flags = PASSFLAG_BYVAL; \
pass[2].type = PassType_Basic; \
pass[2].size = sizeof(bool); \
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 3))
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 2))
}
CBaseEntity *pEntity;
@ -273,16 +270,13 @@ static cell_t CS_DropWeapon(IPluginContext *pContext, const cell_t *params)
if (params[4] == 1 && g_pCSWeaponDropDetoured)
g_pIgnoreCSWeaponDropDetour = true;
unsigned char vstk[sizeof(CBaseEntity *) * 2 + sizeof(bool) * 2];
unsigned char vstk[sizeof(CBaseEntity *) * 2 + sizeof(bool)];
unsigned char *vptr = vstk;
// <psychonic> first one is always false. second is true to toss, false to just drop
*(CBaseEntity **)vptr = pEntity;
vptr += sizeof(CBaseEntity *);
*(CBaseEntity **)vptr = pWeapon;
vptr += sizeof(CBaseEntity *);
*(bool *)vptr = false;
vptr += sizeof(bool);
*(bool *)vptr = (params[3]) ? true : false;
pWrapper->Execute(vstk, NULL);
@ -314,7 +308,7 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
reason++;
#endif
#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32)
#if SOURCE_ENGINE != SE_CSGO
static ICallWrapper *pWrapper = NULL;
if (!pWrapper)
@ -342,6 +336,45 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
vptr += sizeof(float);
*(int*)vptr = reason;
pWrapper->Execute(vstk, NULL);
#elif !defined(WIN32)
static ICallWrapper *pWrapper = NULL;
if (!pWrapper)
{
REGISTER_NATIVE_ADDR("TerminateRound",
PassInfo pass[4]; \
pass[0].flags = PASSFLAG_BYVAL; \
pass[0].type = PassType_Basic; \
pass[0].size = sizeof(float); \
pass[1].flags = PASSFLAG_BYVAL; \
pass[1].type = PassType_Basic; \
pass[1].size = sizeof(int); \
pass[2].flags = PASSFLAG_BYVAL; \
pass[2].type = PassType_Basic; \
pass[2].size = sizeof(int); \
pass[3].flags = PASSFLAG_BYVAL; \
pass[3].type = PassType_Basic; \
pass[3].size = sizeof(int); \
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 4))
}
if (params[3] == 1 && g_pTerminateRoundDetoured)
g_pIgnoreTerminateDetour = true;
unsigned char vstk[sizeof(void *) + sizeof(float) + (sizeof(int)*3)];
unsigned char *vptr = vstk;
*(void **)vptr = gamerules;
vptr += sizeof(void *);
*(float *)vptr = sp_ctof(params[1]);
vptr += sizeof(float);
*(int*)vptr = reason;
vptr += sizeof(int);
*(int*)vptr = 0;
vptr += sizeof(int);
*(int*)vptr = 0;
pWrapper->Execute(vstk, NULL);
#else
static void *addr = NULL;
@ -358,6 +391,8 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
__asm
{
push 0
push 0
push reason
movss xmm1, delay
mov ecx, gamerules
@ -866,9 +901,9 @@ static cell_t CS_UpdateClientModel(IPluginContext *pContext, const cell_t *param
static cell_t CS_ItemDefIndexToID(IPluginContext *pContext, const cell_t *params)
{
#if SOURCE_ENGINE == SE_CSGO
ItemIndexMap::Result res = g_mapDefIdxToClass.find((uint16_t)params[1]);
if (!res.found())
ItemIndexMap::Result res = g_mapDefIdxToClass.find((uint16_t)params[1]);
if (!res.found())
return pContext->ThrowNativeError("Invalid item definition passed.");
return res->value.m_iWeaponID;
@ -880,9 +915,9 @@ static cell_t CS_ItemDefIndexToID(IPluginContext *pContext, const cell_t *params
static cell_t CS_WeaponIDToItemDefIndex(IPluginContext *pContext, const cell_t *params)
{
#if SOURCE_ENGINE == SE_CSGO
WeaponIDMap::Result res = g_mapWeaponIDToDefIdx.find((SMCSWeapon)params[1]);
if (!res.found())
WeaponIDMap::Result res = g_mapWeaponIDToDefIdx.find((SMCSWeapon)params[1]);
if (!res.found())
return pContext->ThrowNativeError("Invalid weapon id passed.");
return res->value.m_iDefIdx;

View File

@ -58,7 +58,19 @@ void TimeLeftEvents::FireGameEvent(IGameEvent *event)
if (get_new_timeleft_offset || !round_end_found)
{
get_new_timeleft_offset = false;
timersys->NotifyOfGameStart();
float flGameStartTime = gpGlobals->curtime;
uintptr_t gamerules = (uintptr_t)g_pSDKTools->GetGameRules();
if (gamerules)
{
sm_sendprop_info_t info;
if (gamehelpers->FindSendPropInfo("CCSGameRulesProxy", "m_flGameStartTime", &info))
{
flGameStartTime = *(float *)(gamerules + info.actual_offset);
}
}
timersys->NotifyOfGameStart(flGameStartTime - gpGlobals->curtime);
timersys->MapTimeLeftChanged();
}
round_end_found = false;

View File

@ -336,7 +336,7 @@ SMCSWeapon GetWeaponIdFromDefIdx(uint16_t iDefIdx)
SMCSWeapon_AUG, SMCSWeapon_AWP, SMCSWeapon_FAMAS, SMCSWeapon_G3SG1,
SMCSWeapon_NONE, SMCSWeapon_GALILAR, SMCSWeapon_M249, SMCSWeapon_NONE,
SMCSWeapon_M4A1, SMCSWeapon_MAC10, SMCSWeapon_NONE, SMCSWeapon_P90,
SMCSWeapon_NONE, SMCSWeapon_NONE, SMCSWeapon_NONE, SMCSWeapon_NONE,
SMCSWeapon_NONE, SMCSWeapon_NONE, SMCSWeapon_NONE, SMCSWeapon_MP5NAVY,
SMCSWeapon_UMP45, SMCSWeapon_XM1014, SMCSWeapon_BIZON, SMCSWeapon_MAG7,
SMCSWeapon_NEGEV, SMCSWeapon_SAWEDOFF, SMCSWeapon_TEC9, SMCSWeapon_TASER,
SMCSWeapon_HKP2000, SMCSWeapon_MP7, SMCSWeapon_MP9, SMCSWeapon_NOVA,

View File

@ -33,22 +33,23 @@
#include "pcre.h"
#include "CRegEx.h"
#include <sh_string.h>
#include "extension.h"
RegEx::RegEx()
{
mErrorOffset = 0;
mErrorCode = 0;
mError = NULL;
re = NULL;
mFree = true;
subject = NULL;
mSubStrings = 0;
mMatchCount = 0;
}
void RegEx::Clear ()
{
mErrorOffset = 0;
mErrorCode = 0;
mError = NULL;
if (re)
pcre_free(re);
@ -57,7 +58,7 @@ void RegEx::Clear ()
if (subject)
delete [] subject;
subject = NULL;
mSubStrings = 0;
mMatchCount = 0;
}
RegEx::~RegEx()
@ -81,7 +82,7 @@ int RegEx::Compile(const char *pattern, int iFlags)
if (!mFree)
Clear();
re = pcre_compile(pattern, iFlags, &mError, &mErrorOffset, NULL);
re = pcre_compile2(pattern, iFlags, &mErrorCode, &mError, &mErrorOffset, NULL);
if (re == NULL)
{
@ -93,7 +94,7 @@ int RegEx::Compile(const char *pattern, int iFlags)
return 1;
}
int RegEx::Match(const char *str)
int RegEx::Match(const char *str, unsigned int offset)
{
int rc = 0;
@ -106,7 +107,9 @@ int RegEx::Match(const char *str)
subject = new char[strlen(str)+1];
strcpy(subject, str);
rc = pcre_exec(re, NULL, subject, (int)strlen(subject), 0, 0, ovector, 30);
unsigned int len = strlen(subject);
rc = pcre_exec(re, NULL, subject, len, offset, 0, mMatches[0].mVector, MAX_CAPTURES);
if (rc < 0)
{
@ -114,34 +117,80 @@ int RegEx::Match(const char *str)
{
return 0;
} else {
mErrorOffset = rc;
mErrorCode = rc;
return -1;
}
}
mSubStrings = rc;
mMatches[0].mSubStringCount = rc;
mMatchCount = 1;
return 1;
}
int RegEx::MatchAll(const char *str)
{
int rc = 0;
if (mFree || re == NULL)
return -1;
this->ClearMatch();
//save str
subject = new char[strlen(str) + 1];
strcpy(subject, str);
unsigned int offset = 0;
unsigned int len = strlen(subject);
unsigned int matches = 0;
while (matches < MAX_MATCHES && offset < len && (rc = pcre_exec(re, 0, subject, len, offset, 0, mMatches[matches].mVector, MAX_CAPTURES)) >= 0)
{
offset = mMatches[matches].mVector[1];
mMatches[matches].mSubStringCount = rc;
matches++;
}
if (rc < PCRE_ERROR_NOMATCH || (rc == PCRE_ERROR_NOMATCH && matches == 0))
{
if (rc == PCRE_ERROR_NOMATCH)
{
return 0;
}
else {
mErrorCode = rc;
return -1;
}
}
mMatchCount = matches;
return 1;
}
void RegEx::ClearMatch()
{
// Clears match results
mErrorOffset = 0;
mErrorCode = 0;
mError = NULL;
if (subject)
delete [] subject;
subject = NULL;
mSubStrings = 0;
mMatchCount = 0;
}
const char *RegEx::GetSubstring(int s, char buffer[], int max)
bool RegEx::GetSubstring(int s, char buffer[], int max, int match)
{
int i = 0;
if (s >= mSubStrings || s < 0)
return NULL;
char *substr_a = subject + ovector[2*s];
int substr_l = ovector[2*s+1] - ovector[2*s];
if (s >= mMatches[match].mSubStringCount || s < 0)
return false;
char *substr_a = subject + mMatches[match].mVector[2 * s];
int substr_l = mMatches[match].mVector[2 * s + 1] - mMatches[match].mVector[2 * s];
for (i = 0; i<substr_l; i++)
{
@ -152,6 +201,6 @@ const char *RegEx::GetSubstring(int s, char buffer[], int max)
buffer[i] = '\0';
return buffer;
return true;
}

View File

@ -28,10 +28,20 @@
*
* Version: $Id$
*/
#include <am-string.h>
#ifndef _INCLUDE_CREGEX_H
#define _INCLUDE_CREGEX_H
#define MAX_MATCHES 20
#define MAX_CAPTURES MAX_MATCHES*3
struct RegexMatch
{
int mSubStringCount;
int mVector[MAX_CAPTURES];
};
class RegEx
{
public:
@ -41,17 +51,19 @@ public:
void Clear();
int Compile(const char *pattern, int iFlags);
int Match(const char *str);
int Match(const char *str, unsigned int offset);
int MatchAll(const char *str);
void ClearMatch();
const char *GetSubstring(int s, char buffer[], int max);
bool GetSubstring(int s, char buffer[], int max, int match);
public:
int mErrorOffset;
int mErrorCode;
const char *mError;
int mSubStrings;
int mMatchCount;
RegexMatch mMatches[MAX_MATCHES];
private:
pcre *re;
bool mFree;
int ovector[30];
char *subject;
};

View File

@ -33,6 +33,7 @@
#include "extension.h"
#include <sh_string.h>
#include "pcre.h"
#include "posix_map.h"
#include "CRegEx.h"
using namespace SourceHook;
@ -82,10 +83,11 @@ static cell_t CompileRegex(IPluginContext *pCtx, const cell_t *params)
if (x->Compile(regex, params[2]) == 0)
{
cell_t *eOff;
pCtx->LocalToPhysAddr(params[5], &eOff);
cell_t *eError;
pCtx->LocalToPhysAddr(params[5], &eError);
const char *err = x->mError;
*eOff = x->mErrorOffset;
// Convert error code to posix error code but use pcre's error string since it is more detailed.
*eError = pcre_posix_compile_error_map[x->mErrorCode];
pCtx->StringToLocal(params[3], params[4], err ? err:"unknown");
delete x;
return 0;
@ -112,6 +114,13 @@ static cell_t MatchRegex(IPluginContext *pCtx, const cell_t *params)
sec.pOwner = NULL;
sec.pIdentity = myself->GetIdentity();
unsigned int offset = 0;
if (params[0] >= 4)
{
offset = (unsigned int)params[4];
}
RegEx *x;
if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
@ -129,14 +138,17 @@ static cell_t MatchRegex(IPluginContext *pCtx, const cell_t *params)
char *str;
pCtx->LocalToString(params[2], &str);
int e = x->Match(str);
if(offset >= strlen(str))
return pCtx->ThrowNativeError("Invalid string index\n");
int e = x->Match(str, offset);
if (e == -1)
{
/* there was a match error. move on. */
cell_t *res;
pCtx->LocalToPhysAddr(params[3], &res);
*res = x->mErrorOffset;
*res = x->mErrorCode;
/* only clear the match results, since the regex object
may still be referenced later */
x->ClearMatch();
@ -153,7 +165,60 @@ static cell_t MatchRegex(IPluginContext *pCtx, const cell_t *params)
}
else
{
return x->mSubStrings;
return x->mMatches[0].mSubStringCount;
}
}
static cell_t MatchRegexAll(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
HandleSecurity sec;
sec.pOwner = NULL;
sec.pIdentity = myself->GetIdentity();
RegEx *x;
if ((err = g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
{
return pCtx->ThrowNativeError("Invalid regex handle %x (error %d)", hndl, err);
}
if (!x)
{
pCtx->ThrowNativeError("Regex data not found\n");
return 0;
}
char *str;
pCtx->LocalToString(params[2], &str);
int e = x->MatchAll(str);
if (e == -1)
{
/* there was a match error. move on. */
cell_t *res;
pCtx->LocalToPhysAddr(params[3], &res);
*res = x->mErrorCode;
/* only clear the match results, since the regex object
may still be referenced later */
x->ClearMatch();
return -1;
}
else if (e == 0)
{
/* only clear the match results, since the regex object
may still be referenced later */
x->ClearMatch();
return 0;
}
else
{
return x->mMatchCount;
}
}
@ -165,6 +230,8 @@ static cell_t GetRegexSubString(IPluginContext *pCtx, const cell_t *params)
sec.pOwner=NULL;
sec.pIdentity=myself->GetIdentity();
int match = 0;
RegEx *x;
if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
@ -178,17 +245,93 @@ static cell_t GetRegexSubString(IPluginContext *pCtx, const cell_t *params)
return 0;
}
static char buffer[4096];
const char *ret=x->GetSubstring(params[2], buffer, sizeof(buffer));
if(!ret)
if (params[0] >= 5)
{
return 0;
match = params[5];
}
pCtx->StringToLocalUTF8(params[3], params[4], ret, NULL);
if(match >= x->mMatchCount || match < 0)
return pCtx->ThrowNativeError("Invalid match index passed.\n");
return 1;
char *buffer;
pCtx->LocalToString(params[3], &buffer);
return x->GetSubstring(params[2], buffer, params[4], match);
}
static cell_t GetRegexMatchCount(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
HandleSecurity sec;
sec.pOwner = NULL;
sec.pIdentity = myself->GetIdentity();
RegEx *x;
if ((err = g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
{
return pCtx->ThrowNativeError("Invalid regex handle %x (error %d)", hndl, err);
}
if (!x)
{
return pCtx->ThrowNativeError("Regex data not found\n");
}
return x->mMatchCount;
}
static cell_t GetRegexCaptureCount(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
HandleSecurity sec;
sec.pOwner = NULL;
sec.pIdentity = myself->GetIdentity();
RegEx *x;
if ((err = g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
{
return pCtx->ThrowNativeError("Invalid regex handle %x (error %d)", hndl, err);
}
if (!x)
{
return pCtx->ThrowNativeError("Regex data not found\n");
}
if (params[2] >= x->mMatchCount || params[2] < 0)
return pCtx->ThrowNativeError("Invalid match index passed.\n");
return x->mMatches[params[2]].mSubStringCount;
}
static cell_t GetRegexOffset(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
HandleSecurity sec;
sec.pOwner = NULL;
sec.pIdentity = myself->GetIdentity();
RegEx *x;
if ((err = g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
{
return pCtx->ThrowNativeError("Invalid regex handle %x (error %d)", hndl, err);
}
if (!x)
{
return pCtx->ThrowNativeError("Regex data not found\n");
}
if (params[2] >= x->mMatchCount || params[2] < 0)
return pCtx->ThrowNativeError("Invalid match index passed.\n");
return x->mMatches[params[2]].mVector[1];
}
void RegexHandler::OnHandleDestroy(HandleType_t type, void *object)
@ -209,5 +352,9 @@ const sp_nativeinfo_t regex_natives[] =
{"Regex.GetSubString", GetRegexSubString},
{"Regex.Match", MatchRegex},
{"Regex.Regex", CompileRegex},
{"Regex.MatchAll", MatchRegexAll},
{"Regex.MatchCount", GetRegexMatchCount},
{"Regex.CaptureCount", GetRegexCaptureCount},
{"Regex.MatchOffset", GetRegexOffset},
{NULL, NULL},
};

View File

@ -0,0 +1,136 @@
#pragma once
/*
Maps pcre_compile2 error codes to posix error codes.
From pcreposix.c and pcreposix.h
*/
// posix error codes
enum {
REG_ASSERT = 1, /* internal error ? */
REG_BADBR, /* invalid repeat counts in {} */
REG_BADPAT, /* pattern error */
REG_BADRPT, /* ? * + invalid */
REG_EBRACE, /* unbalanced {} */
REG_EBRACK, /* unbalanced [] */
REG_ECOLLATE, /* collation error - not relevant */
REG_ECTYPE, /* bad class */
REG_EESCAPE, /* bad escape sequence */
REG_EMPTY, /* empty expression */
REG_EPAREN, /* unbalanced () */
REG_ERANGE, /* bad range inside [] */
REG_ESIZE, /* expression too big */
REG_ESPACE, /* failed to get memory */
REG_ESUBREG, /* bad back reference */
REG_INVARG, /* bad argument */
// This isnt used below since it is not a compile error. So we remove it as to not conflict.
//REG_NOMATCH /* match failed */
};
// pcre compile error -> posix compile error
const int pcre_posix_compile_error_map[] = {
0, /* no error */
REG_EESCAPE, /* \ at end of pattern */
REG_EESCAPE, /* \c at end of pattern */
REG_EESCAPE, /* unrecognized character follows \ */
REG_BADBR, /* numbers out of order in {} quantifier */
/* 5 */
REG_BADBR, /* number too big in {} quantifier */
REG_EBRACK, /* missing terminating ] for character class */
REG_ECTYPE, /* invalid escape sequence in character class */
REG_ERANGE, /* range out of order in character class */
REG_BADRPT, /* nothing to repeat */
/* 10 */
REG_BADRPT, /* operand of unlimited repeat could match the empty string */
REG_ASSERT, /* internal error: unexpected repeat */
REG_BADPAT, /* unrecognized character after (? */
REG_BADPAT, /* POSIX named classes are supported only within a class */
REG_EPAREN, /* missing ) */
/* 15 */
REG_ESUBREG, /* reference to non-existent subpattern */
REG_INVARG, /* erroffset passed as NULL */
REG_INVARG, /* unknown option bit(s) set */
REG_EPAREN, /* missing ) after comment */
REG_ESIZE, /* parentheses nested too deeply */
/* 20 */
REG_ESIZE, /* regular expression too large */
REG_ESPACE, /* failed to get memory */
REG_EPAREN, /* unmatched parentheses */
REG_ASSERT, /* internal error: code overflow */
REG_BADPAT, /* unrecognized character after (?< */
/* 25 */
REG_BADPAT, /* lookbehind assertion is not fixed length */
REG_BADPAT, /* malformed number or name after (?( */
REG_BADPAT, /* conditional group contains more than two branches */
REG_BADPAT, /* assertion expected after (?( */
REG_BADPAT, /* (?R or (?[+-]digits must be followed by ) */
/* 30 */
REG_ECTYPE, /* unknown POSIX class name */
REG_BADPAT, /* POSIX collating elements are not supported */
REG_INVARG, /* this version of PCRE is not compiled with PCRE_UTF8 support */
REG_BADPAT, /* spare error */
REG_BADPAT, /* character value in \x{} or \o{} is too large */
/* 35 */
REG_BADPAT, /* invalid condition (?(0) */
REG_BADPAT, /* \C not allowed in lookbehind assertion */
REG_EESCAPE, /* PCRE does not support \L, \l, \N, \U, or \u */
REG_BADPAT, /* number after (?C is > 255 */
REG_BADPAT, /* closing ) for (?C expected */
/* 40 */
REG_BADPAT, /* recursive call could loop indefinitely */
REG_BADPAT, /* unrecognized character after (?P */
REG_BADPAT, /* syntax error in subpattern name (missing terminator) */
REG_BADPAT, /* two named subpatterns have the same name */
REG_BADPAT, /* invalid UTF-8 string */
/* 45 */
REG_BADPAT, /* support for \P, \p, and \X has not been compiled */
REG_BADPAT, /* malformed \P or \p sequence */
REG_BADPAT, /* unknown property name after \P or \p */
REG_BADPAT, /* subpattern name is too long (maximum 32 characters) */
REG_BADPAT, /* too many named subpatterns (maximum 10,000) */
/* 50 */
REG_BADPAT, /* repeated subpattern is too long */
REG_BADPAT, /* octal value is greater than \377 (not in UTF-8 mode) */
REG_BADPAT, /* internal error: overran compiling workspace */
REG_BADPAT, /* internal error: previously-checked referenced subpattern not found */
REG_BADPAT, /* DEFINE group contains more than one branch */
/* 55 */
REG_BADPAT, /* repeating a DEFINE group is not allowed */
REG_INVARG, /* inconsistent NEWLINE options */
REG_BADPAT, /* \g is not followed followed by an (optionally braced) non-zero number */
REG_BADPAT, /* a numbered reference must not be zero */
REG_BADPAT, /* an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT) */
/* 60 */
REG_BADPAT, /* (*VERB) not recognized */
REG_BADPAT, /* number is too big */
REG_BADPAT, /* subpattern name expected */
REG_BADPAT, /* digit expected after (?+ */
REG_BADPAT, /* ] is an invalid data character in JavaScript compatibility mode */
/* 65 */
REG_BADPAT, /* different names for subpatterns of the same number are not allowed */
REG_BADPAT, /* (*MARK) must have an argument */
REG_INVARG, /* this version of PCRE is not compiled with PCRE_UCP support */
REG_BADPAT, /* \c must be followed by an ASCII character */
REG_BADPAT, /* \k is not followed by a braced, angle-bracketed, or quoted name */
/* 70 */
REG_BADPAT, /* internal error: unknown opcode in find_fixedlength() */
REG_BADPAT, /* \N is not supported in a class */
REG_BADPAT, /* too many forward references */
REG_BADPAT, /* disallowed UTF-8/16/32 code point (>= 0xd800 && <= 0xdfff) */
REG_BADPAT, /* invalid UTF-16 string (should not occur) */
/* 75 */
REG_BADPAT, /* overlong MARK name */
REG_BADPAT, /* character value in \u.... sequence is too large */
REG_BADPAT, /* invalid UTF-32 string (should not occur) */
REG_BADPAT, /* setting UTF is disabled by the application */
REG_BADPAT, /* non-hex character in \\x{} (closing brace missing?) */
/* 80 */
REG_BADPAT, /* non-octal character in \o{} (closing brace missing?) */
REG_BADPAT, /* missing opening brace after \o */
REG_BADPAT, /* parentheses too deeply nested */
REG_BADPAT, /* invalid range in character class */
REG_BADPAT, /* group name must start with a non-digit */
/* 85 */
REG_BADPAT /* parentheses too deeply nested (stack check) */
};

View File

@ -112,6 +112,7 @@ IServerTools *servertools = NULL;
// global hooks and forwards
IForward *g_pOnEntityCreated = NULL;
IForward *g_pOnEntitySpawned = NULL;
IForward *g_pOnEntityDestroyed = NULL;
#ifdef GAMEDESC_CAN_CHANGE
@ -252,6 +253,7 @@ bool SDKHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
plsys->AddPluginsListener(&g_Interface);
g_pOnEntityCreated = forwards->CreateForward("OnEntityCreated", ET_Ignore, 2, NULL, Param_Cell, Param_String);
g_pOnEntitySpawned = forwards->CreateForward("OnEntitySpawned", ET_Ignore, 2, NULL, Param_Cell, Param_String);
g_pOnEntityDestroyed = forwards->CreateForward("OnEntityDestroyed", ET_Ignore, 1, NULL, Param_Cell);
#ifdef GAMEDESC_CAN_CHANGE
g_pOnGetGameNameDescription = forwards->CreateForward("OnGetGameDescription", ET_Hook, 2, NULL, Param_String);
@ -343,6 +345,7 @@ void SDKHooks::SDK_OnUnload()
#endif
forwards->ReleaseForward(g_pOnEntityCreated);
forwards->ReleaseForward(g_pOnEntitySpawned);
forwards->ReleaseForward(g_pOnEntityDestroyed);
#ifdef GAMEDESC_CAN_CHANGE
forwards->ReleaseForward(g_pOnGetGameNameDescription);
@ -878,6 +881,27 @@ void SDKHooks::OnEntityCreated(CBaseEntity *pEntity)
}
}
void SDKHooks::OnEntitySpawned(CBaseEntity *pEntity)
{
// Call OnEntitySpawned forward
int ref = gamehelpers->EntityToReference(pEntity);
int index = gamehelpers->ReferenceToIndex(ref);
// This can be -1 for player ents before any players have connected
if ((unsigned)index == INVALID_EHANDLE_INDEX || (index > 0 && index <= playerhelpers->GetMaxClients()))
{
return;
}
if (!IsEntityIndexInRange(index))
{
g_pSM->LogError(myself, "SDKHooks::OnEntitySpawned - Got entity index out of range (%d)", index);
return;
}
HandleEntitySpawned(pEntity, index, ref);
}
#ifdef GAMEDESC_CAN_CHANGE
const char *SDKHooks::Hook_GetGameDescription()
{
@ -1790,6 +1814,32 @@ void SDKHooks::HandleEntityCreated(CBaseEntity *pEntity, int index, cell_t ref)
m_EntityCache[index] = ref;
}
void SDKHooks::HandleEntitySpawned(CBaseEntity *pEntity, int index, cell_t ref)
{
if (g_pOnEntitySpawned->GetFunctionCount() || m_EntListeners.size())
{
cell_t bcompatRef = gamehelpers->EntityToBCompatRef(pEntity);
const char *pName = gamehelpers->GetEntityClassname(pEntity);
if (!pName)
pName = "";
// Send OnEntitySpawned to SM listeners
for (SourceHook::List<ISMEntityListener *>::iterator iter = m_EntListeners.begin(); iter != m_EntListeners.end(); iter++)
{
ISMEntityListener *pListener = (*iter);
pListener->OnEntitySpawned(pEntity, pName);
}
// Call OnEntitySpawned forward
if (g_pOnEntitySpawned->GetFunctionCount())
{
g_pOnEntitySpawned->PushCell(bcompatRef);
g_pOnEntitySpawned->PushString(pName);
g_pOnEntitySpawned->Execute(NULL);
}
}
}
void SDKHooks::HandleEntityDeleted(CBaseEntity *pEntity)
{
cell_t bcompatRef = gamehelpers->EntityToBCompatRef(pEntity);

View File

@ -238,6 +238,7 @@ public: // IFeatureProvider
public: // IEntityListener
virtual void OnEntityCreated(CBaseEntity *pEntity);
virtual void OnEntitySpawned(CBaseEntity *pEntity);
virtual void OnEntityDeleted(CBaseEntity *pEntity);
public: // IClientListener
@ -330,6 +331,7 @@ public:
private:
void HandleEntityCreated(CBaseEntity *pEntity, int index, cell_t ref);
void HandleEntitySpawned(CBaseEntity *pEntity, int index, cell_t ref);
void HandleEntityDeleted(CBaseEntity *pEntity);
void Unhook(CBaseEntity *pEntity);
void Unhook(IPluginContext *pContext);

View File

@ -453,7 +453,7 @@ bool SDKTools::ProcessCommandTarget(cmd_target_info_t *info)
IPlayerInfo *plinfo = player->GetPlayerInfo();
if (plinfo == NULL)
continue;
if (plinfo->GetTeamIndex() == 1 &&
if ((plinfo->GetTeamIndex() == 0 || plinfo->GetTeamIndex() == 1) &&
playerhelpers->FilterCommandTarget(pAdmin, player, info->flags) ==
COMMAND_TARGET_VALID)
{

View File

@ -53,6 +53,10 @@ static CBaseEntity *FindEntityByNetClass(int start, const char *classname)
if (network == NULL)
continue;
IHandleEntity *pHandleEnt = network->GetEntityHandle();
if (pHandleEnt == NULL)
continue;
ServerClass *sClass = network->GetServerClass();
const char *name = sClass->GetName();

View File

@ -51,7 +51,6 @@ void EntityOutputManager::Shutdown()
return;
}
EntityOutputs->Destroy();
ClassNames->Destroy();
fireOutputDetour->Destroy();
}
@ -65,7 +64,6 @@ void EntityOutputManager::Init()
return;
}
EntityOutputs = adtfactory->CreateBasicTrie();
ClassNames = adtfactory->CreateBasicTrie();
}
@ -119,45 +117,30 @@ bool EntityOutputManager::FireEventDetour(void *pOutput, CBaseEntity *pActivator
return true;
}
char sOutput[20];
Q_snprintf(sOutput, sizeof(sOutput), "%p", pOutput);
// attempt to directly lookup a hook using the pOutput pointer
OutputNameStruct *pOutputName = NULL;
bool fastLookup = false;
// Fast lookup failed - check the slow way for hooks that haven't fired yet
if ((fastLookup = EntityOutputs->Retrieve(sOutput, (void **)&pOutputName)) == false)
const char *classname = gamehelpers->GetEntityClassname(pCaller);
if (!classname)
{
const char *classname = gamehelpers->GetEntityClassname(pCaller);
if (!classname)
{
return true;
}
return true;
}
const char *outputname = FindOutputName(pOutput, pCaller);
if (!outputname)
{
return true;
}
const char *outputname = FindOutputName(pOutput, pCaller);
if (!outputname)
{
return true;
}
pOutputName = FindOutputPointer(classname, outputname, false);
pOutputName = FindOutputPointer(classname, outputname, false);
if (!pOutputName)
{
return true;
}
if (!pOutputName)
{
return true;
}
if (!pOutputName->hooks.empty())
{
if (!fastLookup)
{
// hook exists on this classname and output - map it into our quick find trie
EntityOutputs->Insert(sOutput, pOutputName);
}
SourceHook::List<omg_hooks *>::iterator _iter;
omg_hooks *hook;

View File

@ -121,8 +121,6 @@ private:
const char *FindOutputName(void *pOutput, CBaseEntity *pCaller);
//Maps CEntityOutput * to a OutputNameStruct
IBasicTrie *EntityOutputs;
// Maps classname to a ClassNameStruct
IBasicTrie *ClassNames;

View File

@ -445,6 +445,11 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
cell_t *addr;
size_t written;
pContext->LocalToPhysAddr(params[retparam+1], &addr);
if (!(*(char **)vc->retbuf))
{
pContext->StringToLocalUTF8(params[retparam], *addr, "", &written);
return -1;
}
pContext->StringToLocalUTF8(params[retparam], *addr, *(char **)vc->retbuf, &written);
return (cell_t)written;
} else if (vc->retinfo->vtype == Valve_Vector

View File

@ -161,13 +161,14 @@ static cell_t GiveNamedItem(IPluginContext *pContext, const cell_t *params)
static ValveCall *pCall = NULL;
if (!pCall)
{
ValvePassInfo pass[5];
ValvePassInfo pass[6];
InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[1], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[2], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[3], Valve_Bool, PassType_Basic, PASSFLAG_BYVAL);
InitPass(pass[4], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("GiveNamedItem", ValveCall_Player, &pass[4], pass, 4, &pCall))
InitPass(pass[5], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
if (!CreateBaseCall("GiveNamedItem", ValveCall_Player, &pass[5], pass, 5, &pCall))
{
return pContext->ThrowNativeError("\"GiveNamedItem\" not supported by this mod");
} else if (!pCall) {
@ -182,6 +183,7 @@ static cell_t GiveNamedItem(IPluginContext *pContext, const cell_t *params)
DECODE_VALVE_PARAM(3, vparams, 1);
*(CEconItemView **)(vptr + 12) = NULL;
*(bool *)(vptr + 16) = false;
*(void **)(vptr + 17) = NULL;
FINISH_CALL_SIMPLE(&pEntity);
return gamehelpers->EntityToBCompatRef(pEntity);

View File

@ -34,7 +34,10 @@
SH_DECL_HOOK8_void(IVEngineServer, EmitAmbientSound, SH_NOATTRIB, 0, int, const Vector &, const char *, float, soundlevel_t, int, int, float);
#if SOURCE_ENGINE >= SE_PORTAL2
#if SOURCE_ENGINE == SE_CSGO
SH_DECL_HOOK18(IEngineSound, EmitSound, SH_NOATTRIB, 0, int, IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int, void *);
SH_DECL_HOOK18(IEngineSound, EmitSound, SH_NOATTRIB, 1, int, IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int, void *);
#elif SOURCE_ENGINE >= SE_PORTAL2
SH_DECL_HOOK17(IEngineSound, EmitSound, SH_NOATTRIB, 0, int, IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int);
SH_DECL_HOOK17(IEngineSound, EmitSound, SH_NOATTRIB, 1, int, IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int);
#elif SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 \
@ -79,13 +82,13 @@ size_t SoundHooks::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter)
void SoundHooks::_IncRefCounter(int type)
{
if (type == NORMAL_SOUND_HOOK)
{
if (m_NormalCount++ == 0)
{
if (m_NormalCount++ == 0)
{
SH_ADD_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound), false);
SH_ADD_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound2), false);
}
SH_ADD_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound), false);
SH_ADD_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound2), false);
}
}
else if (type == AMBIENT_SOUND_HOOK)
{
if (m_AmbientCount++ == 0)
@ -98,13 +101,13 @@ void SoundHooks::_IncRefCounter(int type)
void SoundHooks::_DecRefCounter(int type)
{
if (type == NORMAL_SOUND_HOOK)
{
if (--m_NormalCount == 0)
{
if (--m_NormalCount == 0)
{
SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound), false);
SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound2), false);
}
SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound), false);
SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound2), false);
}
}
else if (type == AMBIENT_SOUND_HOOK)
{
if (--m_AmbientCount == 0)
@ -313,7 +316,12 @@ uint32 GenerateSoundEntryHash(char const *pSoundEntry)
}
#endif
#if SOURCE_ENGINE >= SE_PORTAL2
#if SOURCE_ENGINE == SE_CSGO
int SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample,
float flVolume, soundlevel_t iSoundlevel, int nSeed, int iFlags, int iPitch, const Vector *pOrigin,
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
float soundtime, int speakerentity, void *pUnknown)
#elif SOURCE_ENGINE >= SE_PORTAL2
int SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample,
float flVolume, soundlevel_t iSoundlevel, int nSeed, int iFlags, int iPitch, const Vector *pOrigin,
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
@ -414,7 +422,16 @@ void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChann
CellRecipientFilter crf;
crf.Initialize(players, size);
#if SOURCE_ENGINE >= SE_PORTAL2
#if SOURCE_ENGINE == SE_CSGO
RETURN_META_VALUE_NEWPARAMS(
MRES_IGNORED,
-1,
static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char*, unsigned int, const char*, float, soundlevel_t,
int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int, void *)>(&IEngineSound::EmitSound),
(crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, iSoundlevel, nSeed, iFlags, iPitch, pOrigin,
pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity, nullptr)
);
#elif SOURCE_ENGINE >= SE_PORTAL2
RETURN_META_VALUE_NEWPARAMS(
MRES_IGNORED,
-1,
@ -450,7 +467,12 @@ void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChann
#endif
}
#if SOURCE_ENGINE >= SE_PORTAL2
#if SOURCE_ENGINE == SE_CSGO
int SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample,
float flVolume, float flAttenuation, int nSeed, int iFlags, int iPitch, const Vector *pOrigin,
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
float soundtime, int speakerentity, void *pUnknown)
#elif SOURCE_ENGINE >= SE_PORTAL2
int SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample,
float flVolume, float flAttenuation, int nSeed, int iFlags, int iPitch, const Vector *pOrigin,
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
@ -552,7 +574,16 @@ void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChan
CellRecipientFilter crf;
crf.Initialize(players, size);
#if SOURCE_ENGINE >= SE_PORTAL2
#if SOURCE_ENGINE == SE_CSGO
RETURN_META_VALUE_NEWPARAMS(
MRES_IGNORED,
-1,
static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, float,
int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int, void *)>(&IEngineSound::EmitSound),
(crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)),
nSeed, iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity, pUnknown)
);
#elif SOURCE_ENGINE >= SE_PORTAL2
RETURN_META_VALUE_NEWPARAMS(
MRES_IGNORED,
-1,
@ -689,7 +720,7 @@ static cell_t EmitAmbientSound(IPluginContext *pContext, const cell_t *params)
char *name;
float vol, delay;
int pitch, flags, level;
entity = SoundReferenceToIndex(params[3]);
cell_t *addr;
@ -849,7 +880,55 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params)
player[0] = cl_array[i];
crf.Reset();
crf.Initialize(player, 1);
#if SOURCE_ENGINE >= SE_PORTAL2
#if SOURCE_ENGINE == SE_CSGO
if (g_InSoundHook)
{
SH_CALL(enginesoundPatch,
static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char*, unsigned int, const char*, float,
soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int, void *)>
(&IEngineSound::EmitSound))
(crf,
player[0],
channel,
sample,
-1,
sample,
vol,
(soundlevel_t)level,
0,
flags,
pitch,
pOrigin,
pDir,
pOrigVec,
updatePos,
soundtime,
speakerentity,
nullptr);
}
else
{
engsound->EmitSound(crf,
player[0],
channel,
sample,
-1,
sample,
vol,
(soundlevel_t)level,
0,
flags,
pitch,
pOrigin,
pDir,
pOrigVec,
updatePos,
soundtime,
speakerentity,
nullptr);
}
#elif SOURCE_ENGINE >= SE_PORTAL2
if (g_InSoundHook)
{
SH_CALL(enginesoundPatch,
@ -979,7 +1058,54 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params)
#endif
}
} else {
#if SOURCE_ENGINE >= SE_PORTAL2
#if SOURCE_ENGINE == SE_CSGO
if (g_InSoundHook)
{
SH_CALL(enginesoundPatch,
static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char*, unsigned int, const char*, float,
soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int, void *)>
(&IEngineSound::EmitSound))
(crf,
entity,
channel,
sample,
-1,
sample,
vol,
(soundlevel_t)level,
0,
flags,
pitch,
pOrigin,
pDir,
pOrigVec,
updatePos,
soundtime,
speakerentity,
nullptr);
}
else
{
engsound->EmitSound(crf,
entity,
channel,
sample,
-1,
sample,
vol,
(soundlevel_t)level,
0,
flags,
pitch,
pOrigin,
pDir,
pOrigVec,
updatePos,
soundtime,
speakerentity,
nullptr);
}
#elif SOURCE_ENGINE >= SE_PORTAL2
if (g_InSoundHook)
{
SH_CALL(enginesoundPatch,
@ -1219,11 +1345,19 @@ static cell_t EmitSoundEntry(IPluginContext *pContext, const cell_t *params)
if (g_InSoundHook)
{
#if SOURCE_ENGINE == SE_CSGO
SH_CALL(enginesoundPatch,
static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char*, unsigned int, const char*, float,
soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int, void *)>
(&IEngineSound::EmitSound))(crf, player[0], channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level, seed,
flags, pitch, pOrigin, pDir, pOrigVec, updatePos, soundtime, speakerentity, nullptr);
#else
SH_CALL(enginesoundPatch,
static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char*, unsigned int, const char*, float,
soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
(&IEngineSound::EmitSound))(crf, player[0], channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level, seed,
flags, pitch, pOrigin, pDir, pOrigVec, updatePos, soundtime, speakerentity);
#endif
}
else
{
@ -1235,11 +1369,19 @@ static cell_t EmitSoundEntry(IPluginContext *pContext, const cell_t *params)
else {
if (g_InSoundHook)
{
#if SOURCE_ENGINE == SE_CSGO
SH_CALL(enginesoundPatch,
static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char*, unsigned int, const char*, float,
soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int, void *)>
(&IEngineSound::EmitSound))(crf, entity, channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level,
seed, flags, pitch, pOrigin, pDir, pOrigVec, updatePos, soundtime, speakerentity, nullptr);
#else
SH_CALL(enginesoundPatch,
static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char*, unsigned int, const char*, float,
soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
(&IEngineSound::EmitSound))(crf, entity, channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level,
seed, flags, pitch, pOrigin, pDir, pOrigVec, updatePos, soundtime, speakerentity);
#endif
}
else
{

View File

@ -53,7 +53,16 @@ public:
void OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float delay);
#if SOURCE_ENGINE >= SE_PORTAL2
#if SOURCE_ENGINE == SE_CSGO
int OnEmitSound(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *, unsigned int, const char *pSample, float flVolume,
soundlevel_t iSoundlevel, int nSeed, int iFlags, int iPitch, const Vector *pOrigin,
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
float soundtime, int speakerentity, void *pUnknown);
int OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample,
float flVolume, float flAttenuation, int nSeed, int iFlags, int iPitch, const Vector *pOrigin,
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
float soundtime, int speakerentity, void *pUnknown);
#elif SOURCE_ENGINE >= SE_PORTAL2
int OnEmitSound(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *, unsigned int, const char *pSample, float flVolume,
soundlevel_t iSoundlevel, int nSeed, int iFlags, int iPitch, const Vector *pOrigin,
const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,

View File

@ -77,6 +77,10 @@ struct topmenu_object_t
{
return strcmp(name, topmenu->name) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
struct topmenu_category_t

View File

@ -19,6 +19,8 @@
"plugin_ee0bb0aa0d24491feda4235a92779f71" "http://forums.alliedmods.net/showpost.php?p=2032419&postcount=1" /* Advertising plugin being uploaded to CS:GO servers */
"plugin_28a4f07bb94e25e160e9655f8a614292" "https://forums.alliedmods.net/showthread.php?t=291340" /* [AnoX]A-Nox Core - Version 2.5 */
"plugin_dad1e86497adcbeb383da6bd8229069d" "https://forums.alliedmods.net/showpost.php?p=2511172&postcount=3" /* ZenServer: Ultimate (Zen) - Version 4.50 */
"plugin_c71bb73bc544728fdcd7fc9b0353f8d6" "https://forums.alliedmods.net/showthread.php?t=304847" /* Malicious plugin uploaded to CS:GO servers */
"plugin_f946e12de75a0553d3012c594d5e7317" "https://forums.alliedmods.net/showthread.php?t=304847" /* Malicious plugin uploaded to CS:GO servers */
"plugin_f405db5491a465b1a30859ee7f7c5080" "" /* UCP Server (Endi) - Version 6.9 */
"plugin_6fcb6721fb740b854b0a05bfc9a7984a" "" /* UCP Server (Endi) - Version 7.1 */
"plugin_4d320d6c5aba5d31c644fe2847c0662f" "" /* UCP Server (Endi) - Version 7.2 */
@ -99,6 +101,11 @@
"plugin_465e4abb31f03cf519e8a80a8b4b44be" "" /* [AnoX]NoSucide - Version 1.0 */
"plugin_33a4351dd2b9350d6f2b21dab68f7d9e" "" /* [CS:GO] Komutcu Daire System (Sourceless distro) - Version 1.0 */
"plugin_0f9828ea5fe6900981137f3c6fb9d70b" "" /* token changer (Adi) - Version 1.1.2 */
"plugin_267929e572d647c43e54ab7aa921174d" "" /* Playwire MOTD (Playwire Media) - Version 1.1.0 */
"plugin_f9874d362c5c8142037045a0a2c6249c" "" /* [AnoX]A-Nox Core (A-Nox dev.) - Version 3.1a */
"plugin_eae8ed2c593591814f9e6bfa73000d85" "" /* Unknown VIP plugin with fake myinfo */
"plugin_da0e76b67029c12eb5c1995df4fa4f89" "" /* token changer (Adi) - Version 1.3.9 */
"plugin_514efe1f39061e7365a31fc21d452a79" "" /* Token Auto Updater (Phoenix) - Version 1.4 */
}
}
}

View File

@ -99,7 +99,6 @@
"engine" "csgo"
"engine" "sdk2013"
"engine" "contagion"
"engine" "bms"
}
"Offsets"
@ -113,6 +112,24 @@
}
}
"#default"
{
"#supported"
{
"engine" "bms"
}
"Offsets"
{
"GetDataDescMap"
{
"windows" "12"
"linux" "13"
"mac" "13"
}
}
}
/* The Ship is completely different */
"ship"
{
@ -162,6 +179,7 @@
"game" "kz"
"game" "doi"
"game" "bms"
"game" "iosoccer"
}
"Keys"
@ -211,6 +229,7 @@
"game" "kz"
"game" "doi"
"game" "bms"
"game" "iosoccer"
}
"Keys"

View File

@ -17,7 +17,6 @@
"#supported"
{
"game" "ageofchivalry"
"game" "zps"
"game" "bg2"
"game" "pvkii"
"game" "gesource"

View File

@ -19,6 +19,7 @@
{
"game" "synergy"
"game" "empires"
"game" "zps"
}
"Offsets"

View File

@ -6,148 +6,148 @@
{
"Blocked"
{
"windows" "105"
"linux" "106"
"mac" "106"
"windows" "106"
"linux" "107"
"mac" "107"
}
"EndTouch"
{
"windows" "103"
"linux" "104"
"mac" "104"
"windows" "104"
"linux" "105"
"mac" "105"
}
"FireBullets"
{
"windows" "117"
"linux" "118"
"mac" "118"
"windows" "118"
"linux" "119"
"mac" "119"
}
"GetMaxHealth"
{
"windows" "121"
"linux" "122"
"mac" "122"
"windows" "122"
"linux" "123"
"mac" "123"
}
"GroundEntChanged"
{
"windows" "175"
"linux" "177"
"mac" "177"
"windows" "177"
"linux" "179"
"mac" "179"
}
"OnTakeDamage"
{
"windows" "67"
"linux" "68"
"mac" "68"
"windows" "68"
"linux" "69"
"mac" "69"
}
"OnTakeDamage_Alive"
{
"windows" "295"
"linux" "296"
"mac" "296"
"windows" "298"
"linux" "299"
"mac" "299"
}
"PreThink"
{
"windows" "368"
"linux" "369"
"mac" "369"
"windows" "371"
"linux" "372"
"mac" "372"
}
"PostThink"
{
"windows" "369"
"linux" "370"
"mac" "370"
"windows" "372"
"linux" "373"
"mac" "373"
}
"Reload"
{
"windows" "306"
"linux" "312"
"mac" "312"
"windows" "310"
"linux" "316"
"mac" "316"
}
"SetTransmit"
{
"windows" "22"
"linux" "23"
"mac" "23"
"windows" "23"
"linux" "24"
"mac" "24"
}
"ShouldCollide"
{
"windows" "17"
"linux" "18"
"mac" "18"
"windows" "18"
"linux" "19"
"mac" "19"
}
"Spawn"
{
"windows" "24"
"linux" "25"
"mac" "25"
"windows" "25"
"linux" "26"
"mac" "26"
}
"StartTouch"
{
"windows" "101"
"linux" "102"
"mac" "102"
}
"Think"
{
"windows" "51"
"linux" "52"
"mac" "52"
}
"Touch"
{
"windows" "102"
"linux" "103"
"mac" "103"
}
"Think"
{
"windows" "52"
"linux" "53"
"mac" "53"
}
"Touch"
{
"windows" "103"
"linux" "104"
"mac" "104"
}
"TraceAttack"
{
"windows" "65"
"linux" "66"
"mac" "66"
"windows" "66"
"linux" "67"
"mac" "67"
}
"Use"
{
"windows" "100"
"linux" "101"
"mac" "101"
"windows" "101"
"linux" "102"
"mac" "102"
}
"VPhysicsUpdate"
{
"windows" "154"
"linux" "155"
"mac" "155"
"windows" "156"
"linux" "157"
"mac" "157"
}
"Weapon_CanSwitchTo"
{
"windows" "287"
"linux" "288"
"mac" "288"
"windows" "290"
"linux" "291"
"mac" "291"
}
"Weapon_CanUse"
{
"windows" "281"
"linux" "282"
"mac" "282"
}
"Weapon_Drop"
{
"windows" "284"
"linux" "285"
"mac" "285"
}
"Weapon_Equip"
"Weapon_Drop"
{
"windows" "282"
"linux" "283"
"mac" "283"
"windows" "287"
"linux" "288"
"mac" "288"
}
"Weapon_Switch"
"Weapon_Equip"
{
"windows" "285"
"linux" "286"
"mac" "286"
}
"Weapon_Switch"
{
"windows" "288"
"linux" "289"
"mac" "289"
}
}
}

View File

@ -1,142 +1,142 @@
"Games"
{
"#default"
{
"Offsets"
{
"Blocked"
{
"windows" "109"
"linux" "110"
"mac" "110"
}
"EndTouch"
{
"windows" "107"
"linux" "108"
"mac" "108"
}
"FireBullets"
{
"windows" "120"
"linux" "121"
"mac" "121"
}
"OnTakeDamage"
{
"windows" "66"
"linux" "67"
"mac" "67"
}
"OnTakeDamage_Alive"
{
"windows" "290"
"linux" "291"
"mac" "291"
}
"PreThink"
{
"windows" "352"
"linux" "353"
"mac" "353"
}
"PostThink"
{
"windows" "353"
"linux" "354"
"mac" "354"
}
"SetTransmit"
{
"windows" "20"
"linux" "21"
"mac" "21"
}
"ShouldCollide"
{
"windows" "16"
"linux" "17"
"mac" "17"
}
"Spawn"
{
"windows" "22"
"linux" "23"
"mac" "23"
}
"StartTouch"
{
"windows" "105"
"linux" "106"
"mac" "106"
}
"Think"
{
"windows" "48"
"linux" "49"
"mac" "49"
}
"Touch"
{
"windows" "106"
"linux" "107"
"mac" "107"
}
"TraceAttack"
{
"windows" "64"
"linux" "65"
"mac" "65"
}
"VPhysicsUpdate"
{
"windows" "166"
"linux" "167"
"mac" "167"
}
"Weapon_CanSwitchTo"
{
"windows" "284"
"linux" "285"
"mac" "285"
}
"Weapon_CanUse"
{
"windows" "278"
"linux" "279"
"mac" "279"
}
"Weapon_Drop"
{
"windows" "281"
"linux" "282"
"mac" "282"
}
"Weapon_Equip"
{
"windows" "279"
"linux" "280"
"mac" "280"
}
"Weapon_Switch"
{
"windows" "282"
"linux" "283"
"mac" "283"
}
}
}
"#default"
{
"Offsets"
{
"EntityListeners"
{
"windows" "131108"
"linux" "131108"
"mac" "131108"
}
}
}
}
"Games"
{
"#default"
{
"Offsets"
{
"Blocked"
{
"windows" "110"
"linux" "111"
"mac" "111"
}
"EndTouch"
{
"windows" "108"
"linux" "109"
"mac" "109"
}
"FireBullets"
{
"windows" "121"
"linux" "122"
"mac" "122"
}
"OnTakeDamage"
{
"windows" "67"
"linux" "68"
"mac" "68"
}
"OnTakeDamage_Alive"
{
"windows" "291"
"linux" "292"
"mac" "292"
}
"PreThink"
{
"windows" "353"
"linux" "354"
"mac" "354"
}
"PostThink"
{
"windows" "354"
"linux" "355"
"mac" "355"
}
"SetTransmit"
{
"windows" "21"
"linux" "22"
"mac" "22"
}
"ShouldCollide"
{
"windows" "17"
"linux" "18"
"mac" "18"
}
"Spawn"
{
"windows" "23"
"linux" "24"
"mac" "24"
}
"StartTouch"
{
"windows" "106"
"linux" "107"
"mac" "107"
}
"Think"
{
"windows" "49"
"linux" "50"
"mac" "50"
}
"Touch"
{
"windows" "107"
"linux" "108"
"mac" "108"
}
"TraceAttack"
{
"windows" "65"
"linux" "66"
"mac" "66"
}
"VPhysicsUpdate"
{
"windows" "167"
"linux" "168"
"mac" "168"
}
"Weapon_CanSwitchTo"
{
"windows" "285"
"linux" "286"
"mac" "286"
}
"Weapon_CanUse"
{
"windows" "279"
"linux" "280"
"mac" "280"
}
"Weapon_Drop"
{
"windows" "282"
"linux" "283"
"mac" "283"
}
"Weapon_Equip"
{
"windows" "280"
"linux" "281"
"mac" "281"
}
"Weapon_Switch"
{
"windows" "283"
"linux" "284"
"mac" "284"
}
}
}
"#default"
{
"Offsets"
{
"EntityListeners"
{
"windows" "131108"
"linux" "131108"
"mac" "131108"
}
}
}
}

View File

@ -67,7 +67,7 @@
"StartTouch"
{
"windows" "100"
"linux" "101
"linux" "101"
}
"Think"
{
@ -121,4 +121,4 @@
}
}
}
}
}

View File

@ -6,148 +6,148 @@
"Offsets"
{
"Blocked"
{
"windows" "105"
"linux" "106"
"mac" "106"
}
"EndTouch"
{
"windows" "103"
"linux" "104"
"mac" "104"
}
"EndTouch"
{
"windows" "101"
"linux" "102"
"mac" "102"
}
"FireBullets"
{
"windows" "113"
"linux" "114"
"mac" "114"
"windows" "115"
"linux" "116"
"mac" "116"
}
"GetMaxHealth"
{
"windows" "118"
"linux" "119"
"mac" "119"
"windows" "120"
"linux" "121"
"mac" "121"
}
"GroundEntChanged"
{
"windows" "178"
"linux" "180"
"mac" "180"
"windows" "180"
"linux" "182"
"mac" "182"
}
"OnTakeDamage"
{
"windows" "63"
"linux" "64"
"mac" "64"
"windows" "65"
"linux" "66"
"mac" "66"
}
"OnTakeDamage_Alive"
{
"windows" "277"
"linux" "278"
"mac" "278"
}
"PreThink"
{
"windows" "338"
"linux" "339"
"mac" "339"
}
"PostThink"
{
"windows" "339"
"linux" "340"
"mac" "340"
}
"Reload"
{
"windows" "275"
"linux" "276"
"mac" "276"
}
"PreThink"
{
"windows" "336"
"linux" "337"
"mac" "337"
}
"PostThink"
{
"windows" "337"
"linux" "338"
"mac" "338"
}
"Reload"
{
"windows" "273"
"linux" "274"
"mac" "274"
}
"SetTransmit"
{
"windows" "21"
"linux" "22"
"mac" "22"
}
"ShouldCollide"
{
"windows" "16"
"linux" "17"
"mac" "17"
}
"Spawn"
{
"windows" "23"
"linux" "24"
"mac" "24"
}
"ShouldCollide"
{
"windows" "18"
"linux" "19"
"mac" "19"
}
"Spawn"
{
"windows" "25"
"linux" "26"
"mac" "26"
}
"StartTouch"
{
"windows" "99"
"linux" "100"
"mac" "100"
"windows" "101"
"linux" "102"
"mac" "102"
}
"Think"
{
"windows" "48"
"linux" "49"
"mac" "49"
"windows" "50"
"linux" "51"
"mac" "51"
}
"Touch"
{
"windows" "102"
"linux" "103"
"mac" "103"
}
"TraceAttack"
{
"windows" "63"
"linux" "64"
"mac" "64"
}
"Use"
{
"windows" "100"
"linux" "101"
"mac" "101"
}
"TraceAttack"
{
"windows" "61"
"linux" "62"
"mac" "62"
}
"Use"
{
"windows" "98"
"linux" "99"
"mac" "99"
}
"VPhysicsUpdate"
{
"windows" "158"
"linux" "159"
"mac" "159"
"windows" "160"
"linux" "161"
"mac" "161"
}
"Weapon_CanSwitchTo"
{
"windows" "269"
"linux" "270"
"mac" "270"
"windows" "271"
"linux" "272"
"mac" "272"
}
"Weapon_CanUse"
{
"windows" "263"
"linux" "264"
"mac" "264"
"windows" "265"
"linux" "266"
"mac" "266"
}
"Weapon_Drop"
{
"windows" "268"
"linux" "269"
"mac" "269"
}
"Weapon_Equip"
{
"windows" "266"
"linux" "267"
"mac" "267"
}
"Weapon_Equip"
{
"windows" "264"
"linux" "265"
"mac" "265"
}
"Weapon_Switch"
{
"windows" "267"
"linux" "268"
"mac" "268"
"windows" "269"
"linux" "270"
"mac" "270"
}
}
}

View File

@ -1,105 +1,105 @@
"Games"
{
/* Zombic Panic Source 2.0 */
/* Zombic Panic Source 3.0.7 (Hotfix-3) */
"zps"
{
"Offsets"
{
"EndTouch"
{
"windows" "96"
"linux" "97"
"windows" "113"
"linux" "114"
}
"FireBullets"
{
"windows" "108"
"linux" "109"
"windows" "125"
"linux" "126"
}
"OnTakeDamage"
{
"windows" "61"
"linux" "62"
"windows" "74"
"linux" "75"
}
"PreThink"
{
"windows" "295"
"linux" "296"
"windows" "351"
"linux" "352"
}
"PostThink"
{
"windows" "296"
"linux" "297"
"windows" "352"
"linux" "353"
}
"SetTransmit"
{
"windows" "19"
"linux" "20"
"windows" "26"
"linux" "27"
}
"ShouldCollide"
{
"windows" "15"
"linux" "16"
"windows" "22"
"linux" "23"
}
"Spawn"
{
"windows" "21"
"linux" "22"
"windows" "28"
"linux" "29"
}
"StartTouch"
{
"windows" "94"
"linux" "95"
"windows" "111"
"linux" "112"
}
"Think"
{
"windows" "46"
"linux" "47"
"windows" "57"
"linux" "58"
}
"Touch"
{
"windows" "95"
"linux" "96"
"windows" "112"
"linux" "113"
}
"TraceAttack"
{
"windows" "59"
"linux" "60"
"windows" "70"
"linux" "71"
}
"Use"
{
"windows" "93"
"linux" "94"
"windows" "110"
"linux" "111"
}
"VPhysicsUpdate"
{
"windows" "149"
"linux" "150"
"windows" "170"
"linux" "171"
}
"Weapon_CanSwitchTo"
{
"windows" "240"
"linux" "241"
"windows" "281"
"linux" "282"
}
"Weapon_CanUse"
{
"windows" "234"
"linux" "235"
"windows" "274"
"linux" "275"
}
"Weapon_Drop"
{
"windows" "237"
"linux" "238"
"windows" "277"
"linux" "278"
}
"Weapon_Equip"
{
"windows" "235"
"linux" "236"
"windows" "275"
"linux" "276"
}
"Weapon_Switch"
{
"windows" "278"
"linux" "279"
}
//"Weapon_Switch"
//{
// "windows" "234"
// "linux" "235"
//}
}
}
}

View File

@ -219,93 +219,94 @@
{
"GiveNamedItem"
{
"windows" "450"
"linux" "451"
"mac" "451"
"windows" "456"
"linux" "457"
"mac" "457"
}
"RemovePlayerItem"
{
"windows" "293"
"linux" "294"
"mac" "294"
"windows" "296"
"linux" "297"
"mac" "297"
}
"Weapon_GetSlot"
{
"windows" "289"
"linux" "290"
"mac" "290"
"windows" "292"
"linux" "293"
"mac" "293"
}
"Ignite"
{
"windows" "223"
"linux" "224"
"mac" "224"
}
"Extinguish"
{
"windows" "226"
"linux" "227"
"mac" "227"
}
"Extinguish"
{
"windows" "229"
"linux" "230"
"linux64" "230"
"mac64" "230"
}
"Teleport"
{
"windows" "113"
"linux" "114"
"mac" "114"
"windows" "114"
"linux" "115"
"mac" "115"
}
"CommitSuicide"
{
"windows" "500"
"linux" "500"
"mac" "500"
"windows" "506"
"linux" "506"
"mac" "506"
}
"GetVelocity"
{
"windows" "138"
"linux" "139"
"mac" "139"
"windows" "140"
"linux" "141"
"mac" "141"
}
"EyeAngles"
{
"windows" "129"
"linux" "130"
"mac" "130"
"windows" "131"
"linux" "132"
"mac" "132"
}
"AcceptInput"
{
"windows" "40"
"linux" "41"
"mac" "41"
"windows" "41"
"linux" "42"
"mac" "42"
}
"SetEntityModel"
{
"windows" "26"
"linux" "27"
"mac" "27"
"windows" "27"
"linux" "28"
"mac" "28"
}
"WeaponEquip"
{
"windows" "282"
"linux" "283"
"mac" "283"
"windows" "285"
"linux" "286"
"mac" "286"
}
"Activate"
{
"windows" "37"
"linux" "38"
"mac" "38"
"windows" "38"
"linux" "39"
"mac" "39"
}
"PlayerRunCmd"
{
"windows" "470"
"linux" "471"
"mac" "471"
"windows" "476"
"linux" "477"
"mac" "477"
}
"GiveAmmo"
{
"windows" "275"
"linux" "276"
"mac" "276"
"windows" "278"
"linux" "279"
"mac" "279"
}
}
}

View File

@ -91,7 +91,6 @@
"#supported"
{
"game" "ageofchivalry"
"game" "zps"
"game" "bg2"
"game" "gesource"
"game" "RnLBeta"

View File

@ -153,7 +153,7 @@
"FireOutput"
{
"library" "server"
"windows" "\x55\x8B\xEC\x83\xEC\x20\x53\x8B\xC1"
"windows" "\x55\x8B\xEC\x81\xEC\x20\x01\x00\x00\x53\x8B\xC1"
"linux" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
"mac" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
}

View File

@ -1,200 +1,200 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your SourceMod install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after SM's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(SourceMod)
*/
"Games"
{
/* General Temp Entities */
"#default"
{
"Offsets"
{
"GetTEName"
{
"windows" "4"
"linux" "4"
"mac" "4"
}
"GetTENext"
{
"windows" "8"
"linux" "8"
"mac" "8"
}
"TE_GetServerClass"
{
"windows" "0"
"linux" "0"
"mac" "0"
}
}
}
/* CBaseEntityOutput::FireOutput */
"#default"
{
"Signatures"
{
"FireOutput"
{
"library" "server"
"windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x53\x8B\x5D\x20\x8B\xC1\x8B\x4D\x1C\x56\x57\x8B"
"linux" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
"mac" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
}
}
}
/* SetUserInfo data */
"#default"
{
"Offsets"
{
/**
* CBaseClient::SetUserCVar(char const*,char const*);
* Linux offset straight from VTable dump.
* Windows offset is crazy. Found the windows SetName function using string "(%d)%-0.*s"
* Cross referenced back to the vtable and counted manually (SetUserCvar is 1 higher, offsets start from 1)
*/
"SetUserCvar"
{
"windows" "18"
"linux" "58"
"mac" "58"
}
/**
* CBaseClient::SetName(char const*);
* Linux offset straight from VTable dump.
* Has string "(%d)%-0.*s"
*/
"SetClientName"
{
"windows" "17"
"linux" "57"
"mac" "57"
}
/**
* Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made.
* Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end.
* Linux: mov byte ptr [esi+98h], 0
* Win: mov byte ptr [esi+0A4h], 0
*/
"InfoChanged"
{
"windows" "140"
"linux" "140"
"mac" "140"
}
}
}
"#default"
{
"Offsets"
{
"GiveNamedItem"
{
"windows" "421"
"linux" "422"
"mac" "422"
}
"RemovePlayerItem"
{
"windows" "288"
"linux" "289"
"mac" "289"
}
"Weapon_GetSlot"
{
"windows" "286"
"linux" "287"
"mac" "287"
}
"Ignite"
{
"windows" "225"
"linux" "226"
"mac" "226"
}
"Extinguish"
{
"windows" "229"
"linux" "230"
"mac" "230"
}
"Teleport"
{
"windows" "116"
"linux" "117"
"mac" "117"
}
"CommitSuicide"
{
"windows" "461"
"linux" "461"
"mac" "461"
}
"GetVelocity"
{
"windows" "149"
"linux" "150"
"mac" "150"
}
"EyeAngles"
{
"windows" "139"
"linux" "140"
"mac" "140"
}
"SetEntityModel"
{
"windows" "24"
"linux" "25"
"mac" "25"
}
"AcceptInput"
{
"windows" "37"
"linux" "38"
"mac" "38"
}
"WeaponEquip"
{
"windows" "279"
"linux" "280"
"mac" "280"
}
"Activate"
{
"windows" "34"
"linux" "35"
"mac" "35"
}
"PlayerRunCmd"
{
"windows" "440"
"linux" "441"
"mac" "441"
}
"GiveAmmo"
{
"windows" "270"
"linux" "271"
"mac" "271"
}
}
"Keys"
{
"GameRulesProxy" "CBM_MP_GameRulesProxy"
"GameRulesDataTable" "blackmesa_mp_gamerules_data"
}
}
}
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your SourceMod install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after SM's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(SourceMod)
*/
"Games"
{
/* General Temp Entities */
"#default"
{
"Offsets"
{
"GetTEName"
{
"windows" "4"
"linux" "4"
"mac" "4"
}
"GetTENext"
{
"windows" "8"
"linux" "8"
"mac" "8"
}
"TE_GetServerClass"
{
"windows" "0"
"linux" "0"
"mac" "0"
}
}
}
/* CBaseEntityOutput::FireOutput */
"#default"
{
"Signatures"
{
"FireOutput"
{
"library" "server"
"windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x53\x8B\x5D\x20\x8B\xC1\x8B\x4D\x1C\x56\x57\x8B"
"linux" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
"mac" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
}
}
}
/* SetUserInfo data */
"#default"
{
"Offsets"
{
/**
* CBaseClient::SetUserCVar(char const*,char const*);
* Linux offset straight from VTable dump.
* Windows offset is crazy. Found the windows SetName function using string "(%d)%-0.*s"
* Cross referenced back to the vtable and counted manually (SetUserCvar is 1 higher, offsets start from 1)
*/
"SetUserCvar"
{
"windows" "18"
"linux" "58"
"mac" "58"
}
/**
* CBaseClient::SetName(char const*);
* Linux offset straight from VTable dump.
* Has string "(%d)%-0.*s"
*/
"SetClientName"
{
"windows" "17"
"linux" "57"
"mac" "57"
}
/**
* Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made.
* Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end.
* Linux: mov byte ptr [esi+98h], 0
* Win: mov byte ptr [esi+0A4h], 0
*/
"InfoChanged"
{
"windows" "140"
"linux" "140"
"mac" "140"
}
}
}
"#default"
{
"Offsets"
{
"GiveNamedItem"
{
"windows" "423"
"linux" "424"
"mac" "424"
}
"RemovePlayerItem"
{
"windows" "289"
"linux" "290"
"mac" "290"
}
"Weapon_GetSlot"
{
"windows" "287"
"linux" "288"
"mac" "288"
}
"Ignite"
{
"windows" "226"
"linux" "227"
"mac" "227"
}
"Extinguish"
{
"windows" "230"
"linux" "231"
"mac" "231"
}
"Teleport"
{
"windows" "117"
"linux" "118"
"mac" "118"
}
"CommitSuicide"
{
"windows" "463"
"linux" "463"
"mac" "463"
}
"GetVelocity"
{
"windows" "150"
"linux" "151"
"mac" "151"
}
"EyeAngles"
{
"windows" "140"
"linux" "141"
"mac" "141"
}
"SetEntityModel"
{
"windows" "25"
"linux" "26"
"mac" "26"
}
"AcceptInput"
{
"windows" "38"
"linux" "39"
"mac" "39"
}
"WeaponEquip"
{
"windows" "280"
"linux" "281"
"mac" "281"
}
"Activate"
{
"windows" "35"
"linux" "36"
"mac" "36"
}
"PlayerRunCmd"
{
"windows" "442"
"linux" "443"
"mac" "443"
}
"GiveAmmo"
{
"windows" "271"
"linux" "272"
"mac" "272"
}
}
"Keys"
{
"GameRulesProxy" "CBM_MP_GameRulesProxy"
"GameRulesDataTable" "blackmesa_mp_gamerules_data"
}
}
}

View File

@ -1,113 +1,98 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your SourceMod install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after SM's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(SourceMod)
*/
"Games"
{
/* IOS:Source */
"ios"
{
"Offsets"
{
/* CBasePlayer */
"GiveNamedItem"
{
"windows" "328"
"linux" "329"
}
"RemovePlayerItem"
{
"windows" "226"
"linux" "227"
}
"Weapon_GetSlot"
{
"windows" "224"
"linux" "225"
}
"Ignite"
{
"windows" "188"
"linux" "189"
}
"Extinguish"
{
"windows" "189"
"linux" "190"
}
"Teleport"
{
"windows" "98"
"linux" "99"
}
"CommitSuicide"
{
"windows" "356"
"linux" "357"
}
"GetVelocity"
{
"windows" "126"
"linux" "127"
}
"EyeAngles"
{
"windows" "118"
"linux" "119"
}
"DispatchKeyValue"
{
"windows" "31"
"linux" "30"
}
"DispatchKeyValueFloat"
{
"windows" "30"
"linux" "31"
}
"DispatchKeyValueVector"
{
"windows" "29"
"linux" "32"
}
"AcceptInput"
{
"windows" "35"
"linux" "36"
}
"SetEntityModel"
{
"windows" "25"
"linux" "26"
}
"WeaponEquip"
{
"windows" "217"
"linux" "218"
}
"Activate"
{
"windows" "32"
"linux" "33"
}
"PlayerRunCmd"
{
"windows" "346"
"linux" "347"
}
}
"Keys"
{
"GameRulesProxy" "CSDKGameRulesProxy"
"GameRulesDataTable" "sdk_gamerules_data"
}
}
}
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your SourceMod install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after SM's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(SourceMod)
*/
"Games"
{
/* IOSoccer */
"iosoccer"
{
"Offsets"
{
/* CBasePlayer */
"GiveNamedItem"
{
"windows" "336"
"linux" "337"
}
"RemovePlayerItem"
{
"windows" "241"
"linux" "242"
}
"Weapon_GetSlot"
{
"windows" "239"
"linux" "240"
}
"Ignite"
{
"windows" "196"
"linux" "197"
}
"Extinguish"
{
"windows" "200"
"linux" "201"
}
"Teleport"
{
"windows" "103"
"linux" "104"
}
"CommitSuicide"
{
"windows" "378"
"linux" "378"
}
"GetVelocity"
{
"windows" "133"
"linux" "134"
}
"EyeAngles"
{
"windows" "125"
"linux" "126"
}
"AcceptInput"
{
"windows" "34"
"linux" "35"
}
"SetEntityModel"
{
"windows" "23"
"linux" "24"
}
"WeaponEquip"
{
"windows" "232"
"linux" "233"
}
"Activate"
{
"windows" "31"
"linux" "32"
}
"PlayerRunCmd"
{
"windows" "356"
"linux" "357"
}
}
"Keys"
{
"GameRulesProxy" "CSDKGameRulesProxy"
"GameRulesDataTable" "sdk_gamerules_data"
}
}
}

View File

@ -55,7 +55,7 @@
"FireOutput"
{
"library" "server"
"windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x53\x8B\x5D\x20\x8B\xC1\x8B\x4D\x1C\x56\x57\x8B"
"windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x2A\x2A\xD9\x2A\x2A\x53\x8B\xD9\xC7\x45\x2A\x2A\x2A\x2A\x2A\x8B\x4D\x1C\x56\x57\x8B"
"linux" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
"mac" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
}

View File

@ -37,93 +37,93 @@
/* CBasePlayer */
"GiveNamedItem"
{
"windows" "404"
"linux" "405"
"mac" "405"
"windows" "406"
"linux" "407"
"mac" "407"
}
"RemovePlayerItem"
{
"windows" "275"
"linux" "276"
"mac" "276"
}
"Weapon_GetSlot"
{
"windows" "273"
"linux" "274"
"mac" "274"
}
"Weapon_GetSlot"
{
"windows" "271"
"linux" "272"
"mac" "272"
}
"Ignite"
{
"windows" "212"
"linux" "213"
"mac" "213"
"windows" "214"
"linux" "215"
"mac" "215"
}
"Extinguish"
{
"windows" "216"
"linux" "217"
"mac" "217"
"windows" "218"
"linux" "219"
"mac" "219"
}
"Teleport"
{
"windows" "109"
"linux" "110"
"mac" "110"
"windows" "111"
"linux" "112"
"mac" "112"
}
"CommitSuicide"
{
"windows" "443"
"linux" "443"
"mac" "443"
"windows" "444"
"linux" "445"
"mac" "445"
}
"GetVelocity"
{
"windows" "141"
"linux" "142"
"mac" "142"
"windows" "143"
"linux" "144"
"mac" "144"
}
"EyeAngles"
{
"windows" "132"
"linux" "133"
"mac" "133"
"windows" "134"
"linux" "135"
"mac" "135"
}
"AcceptInput"
{
"windows" "37"
"linux" "38"
"mac" "38"
"windows" "39"
"linux" "40"
"mac" "40"
}
"SetEntityModel"
{
"windows" "25"
"linux" "26"
"mac" "26"
"windows" "27"
"linux" "28"
"mac" "28"
}
"WeaponEquip"
{
"windows" "264"
"linux" "265"
"mac" "265"
"windows" "266"
"linux" "267"
"mac" "267"
}
"Activate"
{
"windows" "34"
"linux" "35"
"mac" "35"
"windows" "36"
"linux" "37"
"mac" "37"
}
"PlayerRunCmd"
{
"windows" "422"
"linux" "423"
"mac" "423"
"windows" "424"
"linux" "425"
"mac" "425"
}
"GiveAmmo"
{
"windows" "255"
"linux" "256"
"mac" "256"
"windows" "257"
"linux" "258"
"mac" "258"
}
}

View File

@ -18,73 +18,73 @@
{
"GiveNamedItem"
{
"windows" "358"
"linux" "359"
"windows" "552"
"linux" "553"
}
"RemovePlayerItem"
{
"windows" "247"
"linux" "248"
"windows" "289"
"linux" "290"
}
"Weapon_GetSlot"
{
"windows" "242"
"linux" "243"
"windows" "284"
"linux" "285"
}
"Ignite"
{
"windows" "199"
"linux" "200"
"windows" "223"
"linux" "224"
}
"Extinguish"
{
"windows" "203"
"linux" "204"
"windows" "227"
"linux" "228"
}
"Teleport"
{
"windows" "104"
"linux" "105"
"windows" "121"
"linux" "122"
}
"CommitSuicide"
{
"windows" "405"
"linux" "405"
"windows" "465"
"linux" "465"
}
"GetVelocity"
{
"windows" "133"
"linux" "134"
"windows" "153"
"linux" "154"
}
"EyeAngles"
{
"windows" "125"
"linux" "126"
"windows" "144"
"linux" "145"
}
"AcceptInput"
{
"windows" "35"
"linux" "36"
"windows" "42"
"linux" "43"
}
"SetEntityModel"
{
"windows" "24"
"linux" "25"
"windows" "30"
"linux" "31"
}
"WeaponEquip"
{
"windows" "235"
"linux" "236"
"windows" "275"
"linux" "276"
}
"Activate"
{
"windows" "32"
"linux" "33"
"windows" "39"
"linux" "40"
}
"PlayerRunCmd"
{
"windows" "377"
"linux" "378"
"windows" "443"
"linux" "444"
}
}
"Signatures"
@ -92,13 +92,13 @@
"FindEntityByClassname"
{
"library" "server"
"windows" "\x55\x8B\xEC\x53\x56\x8B\xF1\x8B\x4D\x2A\x57\x85\xC9\x74\x2A\x8B\x01\x8B\x50\x2A\xFF\xD2\x8B\x00\x25\x2A\x2A\x2A\x2A\x40\xC1\xE0\x2A\x8B\x3C\x30\xEB\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x85\xFF\x74\x2A\x8B\x5D\x2A\x8B\x37\x85\xF6\x75\x2A\x68\x2A\x2A\x2A\x2A\xFF\x2A\x2A\x2A\x2A\x2A\x83\xC4\x2A\xEB\x2A\x39"
"windows" "\x55\x8B\xEC\x53\x56\x57\x8B\xF9\x8B\x4D\x2A\x85\xC9\x74\x2A\x8B\x01\xFF\x2A\x2A\x8B\x2A\x81\xE6\x2A\x2A\x2A\x2A\x46\x03\xF6\x8B\x34\x2A\xEB\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x85\xF6\x74\x2A\x8B\x5D\x2A\x8B\x3E\x85\xFF\x75\x2A\x68\x2A\x2A\x2A\x2A\xFF\x2A\x2A\x2A\x2A\x83\xC4\x2A\xEB\x2A\x39"
"linux" "@_ZN17CGlobalEntityList21FindEntityByClassnameEP11CBaseEntityPKc"
}
"FireOutput"
{
"library" "server"
"windows" "\x55\x8B\xEC\x81\x2A\x2A\x2A\x2A\x2A\x53\x56\x8B\x71\x2A\x57"
"windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x2A\x2A\x53\x8B\x5D\x2A\x8B\xC1\x8B\x2A\x2A\x56\x57"
"linux" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
}
}
@ -135,7 +135,7 @@
"CBaseTempEntity"
{
"library" "server"
"windows" "\x55\x8B\xEC\x8B\xC1\x8B\x4D\x2A\xC7\x2A\x2A\x2A\x2A\x2A\x89"
"windows" "\x55\x8B\xEC\x8B\x45\x2A\xC7\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x89"
}
"s_pTempEntities"
{

View File

@ -217,7 +217,7 @@
}
"game.ios.txt"
{
"game" "ios"
"game" "iosoccer"
}
"game.left4dead2.txt"
{

View File

@ -27,12 +27,12 @@
"mac" "4"
}
// In HandleCommand_Buy_Internal
// -*(_DWORD *)(v34 + 204)
// -*(_DWORD *)(v34 + 208) in ida 7 -v34[52]
"WeaponPrice"
{
"windows" "204"
"linux" "204"
"mac" "204"
"windows" "208"
"linux" "208"
"mac" "208"
}
//Offset into CheckRestartRound
"CTTeamScoreOffset"
@ -117,23 +117,17 @@
"windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x83\xEC\x0C\x53\x56\x57\x6A\x01"
"linux" "\x2A\x2A\x2A\x2A\x2A\x2A\x0F\xB6\x55\x14\x89\x75\xF8\x8B\x75\x08"
}
"CSWeaponDrop"//Wildcard first 6 bytes for CS:S DM (kept for backcompat with old SM versions)
{
"library" "server"
"windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x81\xEC\x2A\x2A\x2A\x2A\x53\x8B\x5D\x08\x56\x57\x6A\x00\x68"
"linux" "\x2A\x2A\x2A\x2A\x2A\x2A\x56\x53\x81\xEC\x7C\x02\x00\x00\x8B\x5D\x0C\x8B\x75\x08\x85\xDB\x74\x2A\xC7\x44\x24\x2A\x2A\x2A\x2A\x00"
}
"CSWeaponDropBB" //Revert back to using CSWeaponDrop(weapon, bool, bool)
{
"library" "server"
"windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x83\xE4\xF8\x83\xC4\x04\x55\x8B\x6B\x04\x89\x6C\x24\x04\x8B\xEC\x83\xEC\x34\x56"
"linux" "\x2A\x2A\x2A\x2A\x2A\x2A\x83\xEC\x7C\x8B\x5D\x08\x0F\xB6\x7D\x14"
"linux" "\x2A\x2A\x2A\x2A\x2A\x2A\xEC\x70\x8B\x5D\x08\x0F\xB6\x75\x10"
}
"TerminateRound"
{
"library" "server"
"windows" "\x55\x8B\xEC\x83\xE4\xF8\x83\xEC\x2A\x53\x8B\xD9\xF3\x0F\x2A\x2A\x2A\x2A\x56\x57\x89\x2A\x2A\x2A\x83\xBB"
"linux" "\x55\x89\xE5\x57\x56\x53\x81\xEC\xDC\x00\x00\x00\x8B\x75\x08\x8B\x86"
"linux" "\x55\x89\xE5\x57\x56\x53\x81\xEC\xBC\x00\x00\x00\x8B\x7D\x08\x8B\x9F"
}
//In CS:GO this is actually CCSGameRules::CheckRestartRound(void) but to keep same gamedata as cs:s.
"CheckWinLimit"
@ -145,13 +139,13 @@
"SetClanTag"
{
"library" "server"
"windows" "\x55\x8B\xEC\x8B\x55\x08\x85\xD2\x74\x2A\x8D\x81\x34\x25\x00\x00"
"windows" "\x55\x8B\xEC\x8B\x55\x08\x85\xD2\x74\x2A\x8D\x81\x2A\x2A\x2A\x2A\x56\x8D\x70\x0F\x3B\xC6\x73\x2A\x2B\xD0\x66\x0F\x2A\x2A\x2A\x2A\x8A\x0C\x02"
"linux" "\x55\x89\xE5\x83\xEC\x18\x8B\x45\x0C\x85\xC0\x74\x2A\x89\x44\x24\x04\x8B\x45\x08\xC7\x44\x24\x08\x10\x00\x00\x00"
}
"SetModelFromClass"
{
"library" "server"
"windows" "\x53\x56\x57\x8B\xF9\x8B\x87\x00\x03\x00\x00"
"windows" "\x53\x56\x57\x8B\xF9\x8B\x87\x14\x03\x00\x00"
"linux" "\x55\x89\xE5\x83\xEC\x28\x89\x5D\xF4\x8B\x5D\x08\x89\x75\xF8\x89\x7D\xFC\x89\x1C\x24\xE8\x2A\x2A\x2A\x2A\x83\xF8\x02"
}
//GetCCSWeaponData Found in HandleCommand_Buy_Internal
@ -194,9 +188,9 @@
{
"CScore"
{
"windows" "75"
"linux" "75"
"mac" "75"
"windows" "63"
"linux" "63"
"mac" "63"
}
}
}

View File

@ -24,7 +24,8 @@ files = [
'basecommands.sp',
'mapchooser.sp',
'randomcycle.sp',
'sql-admin-manager.sp'
'sql-admin-manager.sp',
'DynamicTargeting.sp'
]
spcomp_argv = [

266
plugins/DynamicTargeting.sp Normal file
View File

@ -0,0 +1,266 @@
#pragma semicolon 1
#define PLUGIN_VERSION "1.0"
#include <sourcemod>
#include <DynamicTargeting>
#pragma newdecls required
public Plugin myinfo =
{
name = "Dynamic Targeting",
author = "BotoX",
description = "",
version = PLUGIN_VERSION,
url = ""
}
char g_PlayerNames[MAXPLAYERS + 1][MAX_NAME_LENGTH];
Handle g_PlayerData[MAXPLAYERS + 1];
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
CreateNative("AmbiguousMenu", Native_AmbiguousMenu);
RegPluginLibrary("DynamicTargeting");
return APLRes_Success;
}
public void OnClientDisconnect(int client)
{
if(g_PlayerData[client] != INVALID_HANDLE)
{
CloseHandle(g_PlayerData[client]);
g_PlayerData[client] = INVALID_HANDLE;
}
}
int CreateAmbiguousMenu(int client, const char[] sCommand, const char[] sArgString, const char[] sPattern, int FilterFlags)
{
Menu menu = new Menu(MenuHandler_AmbiguousMenu, MenuAction_Select|MenuAction_Cancel|MenuAction_End|MenuAction_DrawItem|MenuAction_DisplayItem);
menu.ExitButton = true;
char sTitle[32 + MAX_TARGET_LENGTH];
FormatEx(sTitle, sizeof(sTitle), "Target \"%s\" is ambiguous.", sPattern);
menu.SetTitle(sTitle);
int Players = 0;
int[] aClients = new int[MaxClients + 1];
for(int i = 1; i <= MaxClients; i++)
{
if(!IsClientConnected(i) || i == client)
continue;
if(FilterFlags & COMMAND_FILTER_NO_BOTS && IsFakeClient(i))
continue;
if(!(FilterFlags & COMMAND_FILTER_CONNECTED) && !IsClientInGame(i))
continue;
if(FilterFlags & COMMAND_FILTER_ALIVE && !IsPlayerAlive(i))
continue;
if(FilterFlags & COMMAND_FILTER_DEAD && IsPlayerAlive(i))
continue;
// insert player names into g_PlayerNames array
GetClientName(i, g_PlayerNames[i], sizeof(g_PlayerNames[]));
if(StrContains(g_PlayerNames[i], sPattern, false) != -1)
aClients[Players++] = i;
}
// sort aClients array by player name
SortCustom1D(aClients, Players, SortByPlayerName);
// insert players sorted
char sUserId[12];
char sDisp[MAX_NAME_LENGTH + 16];
for(int i = 0; i < Players; i++)
{
IntToString(GetClientUserId(aClients[i]), sUserId, sizeof(sUserId));
FormatEx(sDisp, sizeof(sDisp), "%s (%s)", g_PlayerNames[aClients[i]], sUserId);
menu.AddItem(sUserId, sDisp);
}
DataPack pack = new DataPack();
pack.WriteString(sCommand);
pack.WriteString(sArgString);
pack.WriteString(sPattern);
pack.WriteCell(FilterFlags);
if(g_PlayerData[client] != INVALID_HANDLE)
{
CloseHandle(g_PlayerData[client]);
g_PlayerData[client] = INVALID_HANDLE;
}
CancelClientMenu(client);
g_PlayerData[client] = pack;
menu.Display(client, MENU_TIME_FOREVER);
return 0;
}
public int MenuHandler_AmbiguousMenu(Menu menu, MenuAction action, int param1, int param2)
{
switch(action)
{
case MenuAction_End:
{
CloseHandle(menu);
}
case MenuAction_Cancel:
{
if(g_PlayerData[param1] != INVALID_HANDLE)
{
CloseHandle(g_PlayerData[param1]);
g_PlayerData[param1] = INVALID_HANDLE;
}
}
case MenuAction_Select:
{
int Style;
char sItem[32];
char sDisp[MAX_NAME_LENGTH + 16];
menu.GetItem(param2, sItem, sizeof(sItem), Style, sDisp, sizeof(sDisp));
int UserId = StringToInt(sItem);
int client = GetClientOfUserId(UserId);
if(!client)
{
PrintToChat(param1, "\x04[DynamicTargeting]\x01 Player no longer available.");
menu.DisplayAt(param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER);
return 0;
}
DataPack pack = view_as<DataPack>(g_PlayerData[param1]);
pack.Reset();
char sCommand[128];
pack.ReadString(sCommand, sizeof(sCommand));
char sArgString[256];
pack.ReadString(sArgString, sizeof(sArgString));
char sPattern[MAX_TARGET_LENGTH];
pack.ReadString(sPattern, sizeof(sPattern));
int Result = ReCallAmbiguous(param1, client, sCommand, sArgString, sPattern);
return Result;
}
case MenuAction_DrawItem:
{
int Style;
char sItem[32];
menu.GetItem(param2, sItem, sizeof(sItem), Style);
int UserId = StringToInt(sItem);
int client = GetClientOfUserId(UserId);
if(!client) // Player disconnected
return ITEMDRAW_DISABLED;
return Style;
}
case MenuAction_DisplayItem:
{
int Style;
char sItem[32];
char sDisp[MAX_NAME_LENGTH + 16];
menu.GetItem(param2, sItem, sizeof(sItem), Style, sDisp, sizeof(sDisp));
if(!sItem[0])
return 0;
char sBuffer[MAX_NAME_LENGTH + 16];
int UserId = StringToInt(sItem);
int client = GetClientOfUserId(UserId);
if(!client) // Player disconnected
return 0;
GetClientName(client, g_PlayerNames[client], sizeof(g_PlayerNames[]));
FormatEx(sBuffer, sizeof(sBuffer), "%s (%d)", g_PlayerNames[client], UserId);
if(!StrEqual(sDisp, sBuffer))
return RedrawMenuItem(sBuffer);
return 0;
}
}
return 0;
}
int ReCallAmbiguous(int client, int newClient, const char[] sCommand, const char[] sArgString, const char[] sPattern)
{
char sTarget[16];
FormatEx(sTarget, sizeof(sTarget), "#%d", GetClientUserId(newClient));
char sNewArgString[256];
strcopy(sNewArgString, sizeof(sNewArgString), sArgString);
char sPart[256];
int CurrentIndex = 0;
int NextIndex = 0;
while(NextIndex != -1 && CurrentIndex < sizeof(sNewArgString))
{
NextIndex = BreakString(sNewArgString[CurrentIndex], sPart, sizeof(sPart));
if(StrEqual(sPart, sPattern))
{
ReplaceStringEx(sNewArgString[CurrentIndex], sizeof(sNewArgString) - CurrentIndex, sPart, sTarget);
break;
}
CurrentIndex += NextIndex;
}
FakeClientCommandEx(client, "%s %s", sCommand, sNewArgString);
return 0;
}
public int Native_AmbiguousMenu(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
if(client > MaxClients || client <= 0)
{
ThrowNativeError(SP_ERROR_NATIVE, "Client is not valid.");
return -1;
}
if(!IsClientInGame(client))
{
ThrowNativeError(SP_ERROR_NATIVE, "Client is not in-game.");
return -1;
}
if(IsFakeClient(client))
{
ThrowNativeError(SP_ERROR_NATIVE, "Client is fake-client.");
return -1;
}
char sCommand[128];
GetNativeString(2, sCommand, sizeof(sCommand));
char sArgString[256];
GetNativeString(3, sArgString, sizeof(sArgString));
char sPattern[MAX_TARGET_LENGTH];
GetNativeString(4, sPattern, sizeof(sPattern));
int FilterFlags = GetNativeCell(5);
return CreateAmbiguousMenu(client, sCommand, sArgString, sPattern, FilterFlags);
}
public int SortByPlayerName(int elem1, int elem2, const int[] array, Handle hndl)
{
return strcmp(g_PlayerNames[elem1], g_PlayerNames[elem2], false);
}

View File

@ -34,6 +34,7 @@
#pragma semicolon 1
#include <sourcemod>
#include <basecomm>
#pragma newdecls required
@ -80,6 +81,9 @@ public void OnPluginStart()
public Action OnClientSayCommand(int client, const char[] command, const char[] sArgs)
{
if (client <= 0 || BaseComm_IsClientGagged(client))
return Plugin_Continue;
int startidx;
if (sArgs[startidx] != CHAT_SYMBOL)
return Plugin_Continue;
@ -88,51 +92,20 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
if (strcmp(command, "say", false) == 0)
{
if (sArgs[startidx] != CHAT_SYMBOL) // sm_say alias
{
if (!CheckCommandAccess(client, "sm_say", ADMFLAG_CHAT))
{
return Plugin_Continue;
}
SendChatToAll(client, sArgs[startidx]);
LogAction(client, -1, "\"%L\" triggered sm_say (text %s)", client, sArgs[startidx]);
return Plugin_Stop;
}
startidx++;
if (sArgs[startidx] != CHAT_SYMBOL) // sm_psay alias
{
if (!CheckCommandAccess(client, "sm_psay", ADMFLAG_CHAT))
{
return Plugin_Continue;
}
char arg[64];
int len = BreakString(sArgs[startidx], arg, sizeof(arg));
int target = FindTarget(client, arg, true, false);
if (target == -1 || len == -1)
return Plugin_Stop;
SendPrivateChat(client, target, sArgs[startidx+len]);
return Plugin_Stop;
}
startidx++;
// sm_csay alias
if (!CheckCommandAccess(client, "sm_csay", ADMFLAG_CHAT))
if (!CheckCommandAccess(client, "sm_psay_chat", ADMFLAG_CHAT))
{
return Plugin_Continue;
}
DisplayCenterTextToAll(client, sArgs[startidx]);
LogAction(client, -1, "\"%L\" triggered sm_csay (text %s)", client, sArgs[startidx]);
char arg[64];
int len = BreakString(sArgs[startidx], arg, sizeof(arg));
int target = FindTarget(client, arg, true, false);
if (target == -1 || len == -1)
return Plugin_Stop;
SendPrivateChat(client, target, sArgs[startidx+len]);
return Plugin_Stop;
}

View File

@ -185,52 +185,53 @@ public int MenuHandler_GagTypes(Menu menu, MenuAction action, int param1, int pa
{
case CommType_Mute:
{
PerformMute(param1, g_GagTarget[param1]);
PerformMute(g_GagTarget[param1]);
LogAction(param1, g_GagTarget[param1], "\"%L\" muted \"%L\"", param1, g_GagTarget[param1]);
ShowActivity2(param1, "[SM] ", "%t", "Muted target", "_s", name);
}
case CommType_UnMute:
{
PerformUnMute(param1, g_GagTarget[param1]);
PerformUnMute(g_GagTarget[param1]);
LogAction(param1, g_GagTarget[param1], "\"%L\" unmuted \"%L\"", param1, g_GagTarget[param1]);
ShowActivity2(param1, "[SM] ", "%t", "Unmuted target", "_s", name);
}
case CommType_Gag:
{
PerformGag(param1, g_GagTarget[param1]);
PerformGag(g_GagTarget[param1]);
LogAction(param1, g_GagTarget[param1], "\"%L\" gagged \"%L\"", param1, g_GagTarget[param1]);
ShowActivity2(param1, "[SM] ", "%t", "Gagged target", "_s", name);
}
case CommType_UnGag:
{
PerformUnGag(param1, g_GagTarget[param1]);
PerformUnGag(g_GagTarget[param1]);
LogAction(param1, g_GagTarget[param1], "\"%L\" ungagged \"%L\"", param1, g_GagTarget[param1]);
ShowActivity2(param1, "[SM] ", "%t", "Ungagged target", "_s", name);
}
case CommType_Silence:
{
PerformSilence(param1, g_GagTarget[param1]);
PerformSilence(g_GagTarget[param1]);
LogAction(param1, g_GagTarget[param1], "\"%L\" silenced \"%L\"", param1, g_GagTarget[param1]);
ShowActivity2(param1, "[SM] ", "%t", "Silenced target", "_s", name);
}
case CommType_UnSilence:
{
PerformUnSilence(param1, g_GagTarget[param1]);
PerformUnSilence(g_GagTarget[param1]);
LogAction(param1, g_GagTarget[param1], "\"%L\" unsilenced \"%L\"", param1, g_GagTarget[param1]);
ShowActivity2(param1, "[SM] ", "%t", "Unsilenced target", "_s", name);
}
}
}
}
void PerformMute(int client, int target, bool silent=false)
void PerformMute(int target)
{
g_Muted[target] = true;
SetClientListeningFlags(target, VOICE_MUTED);
FireOnClientMute(target, true);
if (!silent)
{
LogAction(client, target, "\"%L\" muted \"%L\"", client, target);
}
}
void PerformUnMute(int client, int target, bool silent=false)
void PerformUnMute(int target)
{
g_Muted[target] = false;
if (g_Cvar_Deadtalk.IntValue == 1 && !IsPlayerAlive(target))
@ -247,36 +248,21 @@ void PerformUnMute(int client, int target, bool silent=false)
}
FireOnClientMute(target, false);
if (!silent)
{
LogAction(client, target, "\"%L\" unmuted \"%L\"", client, target);
}
}
void PerformGag(int client, int target, bool silent=false)
void PerformGag(int target)
{
g_Gagged[target] = true;
FireOnClientGag(target, true);
if (!silent)
{
LogAction(client, target, "\"%L\" gagged \"%L\"", client, target);
}
}
void PerformUnGag(int client, int target, bool silent=false)
void PerformUnGag(int target)
{
g_Gagged[target] = false;
FireOnClientGag(target, false);
if (!silent)
{
LogAction(client, target, "\"%L\" ungagged \"%L\"", client, target);
}
}
void PerformSilence(int client, int target)
void PerformSilence(int target)
{
if (!g_Gagged[target])
{
@ -290,11 +276,9 @@ void PerformSilence(int client, int target)
SetClientListeningFlags(target, VOICE_MUTED);
FireOnClientMute(target, true);
}
LogAction(client, target, "\"%L\" silenced \"%L\"", client, target);
}
void PerformUnSilence(int client, int target)
void PerformUnSilence(int target)
{
if (g_Gagged[target])
{
@ -320,8 +304,6 @@ void PerformUnSilence(int client, int target)
}
FireOnClientMute(target, false);
}
LogAction(client, target, "\"%L\" unsilenced \"%L\"", client, target);
}
public Action Command_Mute(int client, int args)
@ -357,16 +339,18 @@ public Action Command_Mute(int client, int args)
{
int target = target_list[i];
PerformMute(client, target);
PerformMute(target);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Muted target", target_name);
LogAction(client, -1, "\"%L\" muted \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Muted target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" muted \"%L\"", client, target_list[0]);
}
return Plugin_Handled;
@ -405,16 +389,18 @@ public Action Command_Gag(int client, int args)
{
int target = target_list[i];
PerformGag(client, target);
PerformGag(target);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Gagged target", target_name);
LogAction(client, -1, "\"%L\" gagged \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Gagged target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" gagged \"%L\"", client, target_list[0]);
}
return Plugin_Handled;
@ -453,16 +439,18 @@ public Action Command_Silence(int client, int args)
{
int target = target_list[i];
PerformSilence(client, target);
PerformSilence(target);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Silenced target", target_name);
LogAction(client, -1, "\"%L\" silenced \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Silenced target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" silenced \"%L\"", client, target_list[0]);
}
return Plugin_Handled;
@ -506,9 +494,11 @@ public Action Command_Unmute(int client, int args)
continue;
}
PerformUnMute(client, target);
PerformUnMute(target);
}
LogAction(client, -1, "\"%L\" unmuted \"%s\"", client, target_name);
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Unmuted target", target_name);
@ -554,16 +544,18 @@ public Action Command_Ungag(int client, int args)
{
int target = target_list[i];
PerformUnGag(client, target);
PerformUnGag(target);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Ungagged target", target_name);
LogAction(client, -1, "\"%L\" ungagged \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Ungagged target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" ungagged \"%L\"", client, target_list[0]);
}
return Plugin_Handled;
@ -602,16 +594,18 @@ public Action Command_Unsilence(int client, int args)
{
int target = target_list[i];
PerformUnSilence(client, target);
PerformUnSilence(target);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Unsilenced target", target_name);
LogAction(client, -1, "\"%L\" unsilenced \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Unsilenced target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" unsilenced \"%L\"", client, target_list[0]);
}
return Plugin_Handled;

View File

@ -85,7 +85,7 @@ public int Native_SetClientGag(Handle hPlugin, int numParams)
return false;
}
PerformGag(-1, client, true);
PerformGag(client);
}
else
{
@ -94,7 +94,7 @@ public int Native_SetClientGag(Handle hPlugin, int numParams)
return false;
}
PerformUnGag(-1, client, true);
PerformUnGag(client);
}
return true;
@ -122,7 +122,7 @@ public int Native_SetClientMute(Handle hPlugin, int numParams)
return false;
}
PerformMute(-1, client, true);
PerformMute(client);
}
else
{
@ -131,7 +131,7 @@ public int Native_SetClientMute(Handle hPlugin, int numParams)
return false;
}
PerformUnMute(-1, client, true);
PerformUnMute(client);
}
return true;

View File

@ -31,10 +31,8 @@
* Version: $Id$
*/
void PerformKick(int client, int target, const char[] reason)
void PerformKick(int target, const char[] reason)
{
LogAction(client, target, "\"%L\" kicked \"%L\" (reason \"%s\")", client, target, reason);
if (reason[0] == '\0')
{
KickClient(target, "%t", "Kicked by admin");
@ -110,7 +108,8 @@ public int MenuHandler_Kick(Menu menu, MenuAction action, int param1, int param2
char name[MAX_NAME_LENGTH];
GetClientName(target, name, sizeof(name));
ShowActivity2(param1, "[SM] ", "%t", "Kicked target", "_s", name);
PerformKick(param1, target, "");
PerformKick(target, "");
LogAction(param1, target, "\"%L\" kicked \"%L\"", param1, target);
}
/* Re-draw the menu if they're still valid */
@ -193,13 +192,22 @@ public Action Command_Kick(int client, int args)
}
else
{
PerformKick(client, target_list[i], reason);
PerformKick(target_list[i], reason);
}
}
if (kick_self)
{
PerformKick(client, client, reason);
PerformKick(client, reason);
}
if (tn_is_ml)
{
LogAction(client, -1, "\"%L\" kicked \"%s\" (reason \"%s\")", client, target_name, reason);
}
else
{
LogAction(client, target_list[0], "\"%L\" kicked \"%L\" (reason \"%s\")", client, target_list[0], reason);
}
}
else

View File

@ -59,18 +59,12 @@ void KillAllBeacons()
}
}
void PerformBeacon(int client, int target)
void PerformBeacon(int target)
{
if (g_BeaconSerial[target] == 0)
{
CreateBeacon(target);
LogAction(client, target, "\"%L\" set a beacon on \"%L\"", client, target);
}
else
{
KillBeacon(target);
LogAction(client, target, "\"%L\" removed a beacon on \"%L\"", client, target);
}
}
public Action Timer_Beacon(Handle timer, any value)
@ -187,8 +181,9 @@ public int MenuHandler_Beacon(Menu menu, MenuAction action, int param1, int para
char name[MAX_NAME_LENGTH];
GetClientName(target, name, sizeof(name));
PerformBeacon(param1, target);
PerformBeacon(target);
ShowActivity2(param1, "[SM] ", "%t", "Toggled beacon on target", "_s", name);
LogAction(param1, target, "\"%L\" toggled beacon on \"%L\"", param1, target);
}
/* Re-draw the menu if they're still valid */
@ -230,16 +225,18 @@ public Action Command_Beacon(int client, int args)
for (int i = 0; i < target_count; i++)
{
PerformBeacon(client, target_list[i]);
PerformBeacon(target_list[i]);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Toggled beacon on target", target_name);
LogAction(client, -1, "\"%L\" toggled beacon on \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Toggled beacon on target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" toggled beacon on \"%L\"", client, target_list[0]);
}
return Plugin_Handled;

View File

@ -33,7 +33,7 @@
int g_BlindTarget[MAXPLAYERS+1];
void PerformBlind(int client, int target, int amount)
void PerformBlind(int target, int amount)
{
int targets[2];
targets[0] = target;
@ -75,8 +75,6 @@ void PerformBlind(int client, int target, int amount)
}
EndMessage();
LogAction(client, target, "\"%L\" set blind on \"%L\" (amount \"%d\")", client, target, amount);
}
public void AdminMenu_Blind(TopMenu topmenu,
@ -211,7 +209,8 @@ public int MenuHandler_Amount(Menu menu, MenuAction action, int param1, int para
char name[MAX_NAME_LENGTH];
GetClientName(target, name, sizeof(name));
PerformBlind(param1, target, amount);
PerformBlind(target, amount);
LogAction(param1, target, "\"%L\" set blind on \"%L\", amount %d.", param1, target, amount);
ShowActivity2(param1, "[SM] ", "%t", "Set blind on target", "_s", name, amount);
}
@ -276,16 +275,18 @@ public Action Command_Blind(int client, int args)
for (int i = 0; i < target_count; i++)
{
PerformBlind(client, target_list[i], amount);
PerformBlind(target_list[i], amount);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Set blind on target", target_name);
LogAction(client, -1, "\"%L\" set blind on \"%s\", amount %d.", client, target_name, amount);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Set blind on target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" set blind on \"%L\", amount %d.", client, target_list[0], amount);
}
return Plugin_Handled;

View File

@ -106,7 +106,7 @@ void KillAllDrugs()
}
}
void PerformDrug(int client, int target, int toggle)
void PerformDrug(int target, int toggle)
{
switch (toggle)
{
@ -115,12 +115,10 @@ void PerformDrug(int client, int target, int toggle)
if (g_DrugTimers[target] == null)
{
CreateDrug(target);
LogAction(client, target, "\"%L\" drugged \"%L\"", client, target);
}
else
{
KillDrug(target);
LogAction(client, target, "\"%L\" undrugged \"%L\"", client, target);
}
}
@ -129,7 +127,6 @@ void PerformDrug(int client, int target, int toggle)
if (g_DrugTimers[target] == null)
{
CreateDrug(target);
LogAction(client, target, "\"%L\" drugged \"%L\"", client, target);
}
}
@ -138,7 +135,6 @@ void PerformDrug(int client, int target, int toggle)
if (g_DrugTimers[target] != null)
{
KillDrug(target);
LogAction(client, target, "\"%L\" undrugged \"%L\"", client, target);
}
}
}
@ -268,7 +264,8 @@ public int MenuHandler_Drug(Menu menu, MenuAction action, int param1, int param2
char name[MAX_NAME_LENGTH];
GetClientName(target, name, sizeof(name));
PerformDrug(param1, target, 2);
PerformDrug(target, 2);
LogAction(param1, target, "\"%L\" toggled drugs on \"%L\"", param1, target);
ShowActivity2(param1, "[SM] ", "%t", "Toggled drug on target", "_s", name);
}
@ -326,16 +323,18 @@ public Action Command_Drug(int client, int args)
for (int i = 0; i < target_count; i++)
{
PerformDrug(client, target_list[i], toggle);
PerformDrug(target_list[i], toggle);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Toggled drug on target", target_name);
LogAction(client, -1, "\"%L\" toggled drugs on \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Toggled drug on target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" toggled drugs on \"%L\"", client, target_list[0]);
}
return Plugin_Handled;

View File

@ -64,24 +64,16 @@ void KillAllFireBombs()
}
}
void PerformBurn(int client, int target, float seconds)
{
IgniteEntity(target, seconds);
LogAction(client, target, "\"%L\" ignited \"%L\" (seconds \"%f\")", client, target, seconds);
}
void PerformFireBomb(int client, int target)
{
if (g_FireBombSerial[client] == 0)
{
CreateFireBomb(target);
LogAction(client, target, "\"%L\" set a FireBomb on \"%L\"", client, target);
}
else
{
KillFireBomb(target);
SetEntityRenderColor(client, 255, 255, 255, 255);
LogAction(client, target, "\"%L\" removed a FireBomb on \"%L\"", client, target);
}
}
@ -306,7 +298,8 @@ public int MenuHandler_Burn(Menu menu, MenuAction action, int param1, int param2
{
char name[MAX_NAME_LENGTH];
GetClientName(target, name, sizeof(name));
PerformBurn(param1, target, 20.0);
IgniteEntity(target, 20.0);
LogAction(param1, target, "\"%L\" ignited \"%L\" (seconds \"20\")", param1, target);
ShowActivity2(param1, "[SM] ", "%t", "Set target on fire", "_s", name);
}
@ -353,6 +346,7 @@ public int MenuHandler_FireBomb(Menu menu, MenuAction action, int param1, int pa
GetClientName(target, name, sizeof(name));
PerformFireBomb(param1, target);
LogAction(param1, target, "\"%L\" toggled FireBomb on \"%L\"", param1, target);
ShowActivity2(param1, "[SM] ", "%t", "Toggled FireBomb on target", "_s", name);
}
@ -408,16 +402,18 @@ public Action Command_Burn(int client, int args)
for (int i = 0; i < target_count; i++)
{
PerformBurn(client, target_list[i], seconds);
IgniteEntity(target_list[i], seconds);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Set target on fire", target_name);
LogAction(client, -1, "\"%L\" ignited \"%s\" (seconds \"%f\")", client, target_name, seconds);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Set target on fire", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" ignited \"%L\" (seconds \"%f\")", client, target_list[0], seconds);
}
return Plugin_Handled;
@ -460,10 +456,12 @@ public Action Command_FireBomb(int client, int args)
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Toggled FireBomb on target", target_name);
LogAction(client, -1, "\"%L\" toggled FireBomb on \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Toggled FireBomb on target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" toggled FireBomb on \"%L\"", client, target_list[0]);
}
return Plugin_Handled;
}

View File

@ -33,12 +33,6 @@
int g_GravityTarget[MAXPLAYERS+1];
void PerformGravity(int client, int target, float amount)
{
SetEntityGravity(target, amount);
LogAction(client, target, "\"%L\" set gravity on \"%L\" (amount \"%f\")", client, target, amount);
}
public void AdminMenu_Gravity(TopMenu topmenu,
TopMenuAction action,
TopMenuObject object_id,
@ -169,7 +163,8 @@ public int MenuHandler_GravityAmount(Menu menu, MenuAction action, int param1, i
char name[MAX_NAME_LENGTH];
GetClientName(target, name, sizeof(name));
PerformGravity(param1, target, amount);
SetEntityGravity(target, amount);
LogAction(param1, target, "\"%L\" set gravity on \"%L\" to %f.", param1, target, amount);
ShowActivity2(param1, "[SM] ", "%t", "Set gravity on target", "_s", name, amount);
}
@ -229,16 +224,18 @@ public Action Command_Gravity(int client, int args)
for (int i = 0; i < target_count; i++)
{
PerformGravity(client, target_list[i], amount);
SetEntityGravity(target_list[i], amount);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Set gravity on target", target_name);
LogAction(client, -1, "\"%L\" set gravity on \"%s\" to %f.", client, target_name, amount);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Set gravity on target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" set gravity on \"%L\" to %f.", client, target_list[0], amount);
}
return Plugin_Handled;

View File

@ -125,24 +125,12 @@ void KillAllFreezes()
}
}
void PerformFreeze(int client, int target, int time)
{
FreezeClient(target, time);
LogAction(client, target, "\"%L\" froze \"%L\"", client, target);
}
void PerformFreezeBomb(int client, int target)
void PerformFreezeBomb(int target)
{
if (g_FreezeBombSerial[target] != 0)
{
KillFreezeBomb(target);
LogAction(client, target, "\"%L\" removed a FreezeBomb on \"%L\"", client, target);
}
else
{
CreateFreezeBomb(target);
LogAction(client, target, "\"%L\" set a FreezeBomb on \"%L\"", client, target);
}
}
public Action Timer_Freeze(Handle timer, any value)
@ -421,7 +409,8 @@ public int MenuHandler_Freeze(Menu menu, MenuAction action, int param1, int para
char name[MAX_NAME_LENGTH];
GetClientName(target, name, sizeof(name));
PerformFreeze(param1, target, g_Cvar_FreezeDuration.IntValue);
FreezeClient(target, g_Cvar_FreezeDuration.IntValue);
LogAction(param1, target, "\"%L\" froze \"%L\"", param1, target);
ShowActivity2(param1, "[SM] ", "%t", "Froze target", "_s", name);
}
@ -467,7 +456,8 @@ public int MenuHandler_FreezeBomb(Menu menu, MenuAction action, int param1, int
char name[MAX_NAME_LENGTH];
GetClientName(target, name, sizeof(name));
PerformFreezeBomb(param1, target);
PerformFreezeBomb(target);
LogAction(param1, target, "\"%L\" toggled FreezeBomb on \"%L\"", param1, target);
ShowActivity2(param1, "[SM] ", "%t", "Toggled FreezeBomb on target", "_s", name);
}
@ -523,16 +513,18 @@ public Action Command_Freeze(int client, int args)
for (int i = 0; i < target_count; i++)
{
PerformFreeze(client, target_list[i], seconds);
FreezeClient(target_list[i], seconds);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Froze target", target_name);
LogAction(client, -1, "\"%L\" froze \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Froze target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" froze \"%L\"", client, target_list[0]);
}
return Plugin_Handled;
@ -569,16 +561,18 @@ public Action Command_FreezeBomb(int client, int args)
for (int i = 0; i < target_count; i++)
{
PerformFreezeBomb(client, target_list[i]);
PerformFreezeBomb(target_list[i]);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Toggled FreezeBomb on target", target_name);
LogAction(client, -1, "\"%L\" toggled FreezeBomb on \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Toggled FreezeBomb on target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" toggled FreezeBomb on \"%L\"", client, target_list[0]);
}
return Plugin_Handled;

View File

@ -31,7 +31,7 @@
* Version: $Id$
*/
void PerformNoClip(int client, int target)
void PerformNoClip(int target)
{
MoveType movetype = GetEntityMoveType(target);
@ -43,8 +43,6 @@ void PerformNoClip(int client, int target)
{
SetEntityMoveType(target, MOVETYPE_WALK);
}
LogAction(client, target, "\"%L\" toggled noclip on \"%L\"", client, target);
}
public void AdminMenu_NoClip(TopMenu topmenu,
@ -112,7 +110,8 @@ public int MenuHandler_NoClip(Menu menu, MenuAction action, int param1, int para
char name[MAX_NAME_LENGTH];
GetClientName(target, name, sizeof(name));
PerformNoClip(param1, target);
PerformNoClip(target);
LogAction(param1, target, "\"%L\" toggled noclip on \"%L\"", param1, target);
ShowActivity2(param1, "[SM] ", "%t", "Toggled noclip on target", "_s", name);
}
@ -155,16 +154,18 @@ public Action Command_NoClip(int client, int args)
for (int i = 0; i < target_count; i++)
{
PerformNoClip(client, target_list[i]);
PerformNoClip(target_list[i]);
}
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Toggled noclip on target", target_name);
LogAction(client, -1, "\"%L\" toggled noclip on \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Toggled noclip on target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" toggled noclip on \"%L\"", client, target_list[0]);
}
return Plugin_Handled;

View File

@ -68,13 +68,11 @@ void PerformTimeBomb(int client, int target)
if (g_TimeBombSerial[target] == 0)
{
CreateTimeBomb(target);
LogAction(client, target, "\"%L\" set a TimeBomb on \"%L\"", client, target);
}
else
{
KillTimeBomb(target);
SetEntityRenderColor(client, 255, 255, 255, 255);
LogAction(client, target, "\"%L\" removed a TimeBomb on \"%L\"", client, target);
}
}
@ -279,6 +277,7 @@ public int MenuHandler_TimeBomb(Menu menu, MenuAction action, int param1, int pa
GetClientName(target, name, sizeof(name));
PerformTimeBomb(param1, target);
LogAction(param1, target, "\"%L\" toggled TimeBomb on \"%L\"", param1, target);
ShowActivity2(param1, "[SM] ", "%t", "Toggled TimeBomb on target", "_s", name);
}
@ -327,10 +326,12 @@ public Action Command_TimeBomb(int client, int args)
if (tn_is_ml)
{
ShowActivity2(client, "[SM] ", "%t", "Toggled TimeBomb on target", target_name);
LogAction(client, -1, "\"%L\" toggled TimeBomb on \"%s\"", client, target_name);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Toggled TimeBomb on target", "_s", target_name);
LogAction(client, target_list[0], "\"%L\" toggled TimeBomb on \"%L\"", client, target_list[0]);
}
return Plugin_Handled;

View File

@ -0,0 +1,24 @@
#if defined _DynamicTargeting_Included
#endinput
#endif
#define _DynamicTargeting_Included
native int AmbiguousMenu(int client, char[] sCommand, char[] sArgString, char[] sPattern, int FilterFlags);
public SharedPlugin __pl_DynamicTargeting =
{
name = "DynamicTargeting",
file = "DynamicTargeting.smx",
#if defined REQUIRE_PLUGIN
required = 1,
#else
required = 0,
#endif
};
#if !defined REQUIRE_PLUGIN
public __pl_DynamicTargeting_SetNTVOptional()
{
MarkNativeAsOptional("AmbiguousMenu");
}
#endif

View File

@ -738,6 +738,15 @@ native float GetClientAvgData(int client, NetFlow flow);
*/
native float GetClientAvgPackets(int client, NetFlow flow);
/**
* Returns the client's baseserver IClient pointer.
*
* @param client Player's index.
* @return IClient address.
* @error Invalid client index, client not connected, or fake client.
*/
native Address GetClientIClient(int client);
/**
* Translates an userid index to the real player index.
*

View File

@ -84,6 +84,25 @@ native int ProcessTargetString(const char[] pattern,
int tn_maxlength,
bool &tn_is_ml);
/**
* Retrieves arguments that were passed to the last ProcessTargetString call.
*
* @param pattern Buffer to store the pattern.
* @param p_maxlen Maximum length of the pattern buffer.
* @param admin OUTPUT: Admin performing the action, or 0 if the server.
* @param filter_flags OUTPUT: Filter flags.
* @noreturn
*/
native void GetLastProcessTargetString(char[] pattern,
int p_maxlen,
int &admin,
int &filter_flags);
#undef REQUIRE_PLUGIN
#include <DynamicTargeting>
#define REQUIRE_PLUGIN
/**
* Replies to a client with a given message describing a targetting
* failure reason.
@ -93,7 +112,7 @@ native int ProcessTargetString(const char[] pattern,
* @param client Client index, or 0 for server.
* @param reason COMMAND_TARGET reason.
*/
stock void ReplyToTargetError(int client, int reason)
stock void ReplyToTargetError(int client, int reason, bool dynamic=true)
{
switch (reason)
{
@ -128,6 +147,34 @@ stock void ReplyToTargetError(int client, int reason)
case COMMAND_TARGET_AMBIGUOUS:
{
ReplyToCommand(client, "[SM] %t", "More than one client matched");
if(dynamic &&
GetFeatureStatus(FeatureType_Native, "GetLastProcessTargetString") == FeatureStatus_Available &&
LibraryExists("DynamicTargeting"))
{
if(GetFeatureStatus(FeatureType_Native, "IsCommandCallback") == FeatureStatus_Available &&
!IsCommandCallback())
{
return;
}
char sCommand[128];
GetCmdArg(0, sCommand, sizeof(sCommand));
char sArgString[256];
GetCmdArgString(sArgString, sizeof(sArgString));
char pattern[MAX_TARGET_LENGTH];
int admin;
int filter_flags;
GetLastProcessTargetString(pattern, sizeof(pattern), admin, filter_flags);
if(!admin || !IsClientInGame(admin) || IsFakeClient(admin))
return;
AmbiguousMenu(admin, sCommand, sArgString, pattern, filter_flags);
}
}
}
}
@ -137,9 +184,13 @@ stock void ReplyToTargetError(int client, int reason)
*
* @param pattern Pattern name.
* @param clients Array to fill with unique, valid client indexes.
* @param client Client that triggered this filter.
* @return True if pattern was recognized, false otherwise.
*/
typedef MultiTargetFilter = function bool (const char[] pattern, Handle clients);
typeset MultiTargetFilter {
function bool (const char[] pattern, Handle clients);
function bool (const char[] pattern, Handle clients, int client);
}
/**
* Adds a multi-target filter function for ProcessTargetString().

Some files were not shown because too many files have changed in this diff Show More