dvander@530: /** ds@653: * vim: set ts=4 : ds@1330: * ============================================================================= dvander@1231: * SourceMod ds@3099: * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. ds@1330: * ============================================================================= dvander@530: * ds@1330: * This program is free software; you can redistribute it and/or modify it under ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the ds@1330: * Free Software Foundation. dvander@1231: * ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ds@1330: * details. dvander@1231: * ds@1330: * You should have received a copy of the GNU General Public License along with ds@1330: * this program. If not, see . dvander@1231: * ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants ds@1330: * this exception to all derivative works. AlliedModders LLC defines further ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), ds@1330: * or . dvander@530: * dvander@530: * Version: $Id$ dvander@530: */ dvander@530: dvander@530: #include "sm_globals.h" dvander@532: #include "sourcemod.h" dvander@530: #include "sourcemm_api.h" ds@873: #include "HandleSys.h" dvander@591: #include "PlayerManager.h" ds@873: #include "HalfLife2.h" ds@874: dvander@530: static cell_t SetRandomSeed(IPluginContext *pContext, const cell_t *params) dvander@530: { dvander@530: engrandom->SetSeed(params[1]); dvander@530: dvander@530: return 1; dvander@530: } dvander@530: dvander@530: static cell_t GetRandomFloat(IPluginContext *pContext, const cell_t *params) dvander@530: { dvander@530: float fMin = sp_ctof(params[1]); dvander@530: float fMax = sp_ctof(params[2]); dvander@530: dvander@530: float fRandom = engrandom->RandomFloat(fMin, fMax); dvander@530: dvander@530: return sp_ftoc(fRandom); dvander@530: } dvander@530: dvander@530: static cell_t GetRandomInt(IPluginContext *pContext, const cell_t *params) dvander@530: { dvander@530: return engrandom->RandomInt(params[1], params[2]); dvander@530: } dvander@530: dvander@532: static cell_t IsMapValid(IPluginContext *pContext, const cell_t *params) dvander@532: { dvander@532: char *map; dvander@532: pContext->LocalToString(params[1], &map); dvander@532: dvander@532: return engine->IsMapValid(map); dvander@532: } dvander@532: dvander@532: static cell_t IsDedicatedServer(IPluginContext *pContext, const cell_t *params) dvander@532: { dvander@532: return engine->IsDedicatedServer(); dvander@532: } dvander@532: dvander@532: static cell_t GetEngineTime(IPluginContext *pContext, const cell_t *params) dvander@532: { ds@3099: #if SOURCE_ENGINE >= SE_LEFT4DEAD2 pred@2850: float fTime = Plat_FloatTime(); fyrenmoo@2851: #else fyrenmoo@2851: float fTime = engine->Time(); fyrenmoo@2851: #endif pred@2850: dvander@532: return sp_ftoc(fTime); dvander@532: } dvander@532: dvander@532: static cell_t GetGameTime(IPluginContext *pContext, const cell_t *params) dvander@532: { dvander@532: return sp_ftoc(gpGlobals->curtime); dvander@532: } dvander@532: aangione@3540: static cell_t GetGameTickCount(IPluginContext *pContext, const cell_t *params) aangione@3540: { aangione@3540: return gpGlobals->tickcount; aangione@3540: } aangione@3540: dvander@532: static cell_t CreateFakeClient(IPluginContext *pContext, const cell_t *params) dvander@532: { skamonkey@3401: if (!g_SourceMod.IsMapRunning()) skamonkey@3401: { skamonkey@3401: return pContext->ThrowNativeError("Cannot create fakeclient when no map is active"); skamonkey@3401: } skamonkey@3401: dvander@532: char *netname; dvander@532: dvander@532: pContext->LocalToString(params[1], &netname); dvander@532: dvander@532: edict_t *pEdict = engine->CreateFakeClient(netname); dvander@532: dvander@532: /* :TODO: does the engine fire forwards for us and whatnot? no idea... */ dvander@532: dvander@532: if (!pEdict) dvander@532: { dvander@532: return 0; dvander@532: } dvander@532: ds@2400: return IndexOfEdict(pEdict); dvander@532: } dvander@532: dvander@532: static cell_t SetFakeClientConVar(IPluginContext *pContext, const cell_t *params) dvander@532: { dvander@532: CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]); dvander@532: dvander@532: if (!pPlayer) dvander@532: { ds@994: return pContext->ThrowNativeError("Client index %d is invalid", params[1]); dvander@532: } dvander@532: dvander@532: if (!pPlayer->IsConnected()) dvander@532: { ds@994: return pContext->ThrowNativeError("Client %d is not connected", params[1]); dvander@532: } dvander@532: dvander@532: if (!pPlayer->IsFakeClient()) dvander@532: { ds@994: return pContext->ThrowNativeError("Client %d is not a fake client", params[1]); dvander@532: } dvander@532: dvander@532: char *cvar, *value; dvander@532: dvander@532: pContext->LocalToString(params[2], &cvar); dvander@532: pContext->LocalToString(params[3], &value); dvander@532: dvander@532: engine->SetFakeClientConVarValue(pPlayer->GetEdict(), cvar, value); dvander@532: dvander@532: return 1; dvander@532: } dvander@532: dvander@532: static cell_t GetGameDescription(IPluginContext *pContext, const cell_t *params) dvander@532: { dvander@532: const char *description; dvander@532: dvander@532: if (params[3]) dvander@532: { dvander@532: description = gamedll->GetGameDescription(); dvander@532: } else { dvander@532: description = SERVER_CALL(GetGameDescription)(); dvander@532: } dvander@532: dvander@532: size_t numBytes; dvander@532: dvander@532: pContext->StringToLocalUTF8(params[1], params[2], description, &numBytes); dvander@532: dvander@532: return numBytes; dvander@532: } dvander@532: ds@721: static cell_t GetGameFolderName(IPluginContext *pContext, const cell_t *params) ds@721: { ds@729: const char *name = g_SourceMod.GetGameFolderName(); ds@721: size_t numBytes; ds@721: ds@721: pContext->StringToLocalUTF8(params[1], params[2], name, &numBytes); ds@721: ds@721: return numBytes; ds@721: } ds@721: dvander@1604: /* Useless comment to bump the build */ dvander@532: static cell_t GetCurrentMap(IPluginContext *pContext, const cell_t *params) dvander@532: { dvander@532: size_t bytes; dvander@532: pContext->StringToLocalUTF8(params[1], params[2], STRING(gpGlobals->mapname), &bytes); dvander@532: return bytes; dvander@532: } dvander@532: faluco@656: static cell_t PrecacheModel(IPluginContext *pContext, const cell_t *params) faluco@656: { faluco@656: char *model; faluco@656: pContext->LocalToString(params[1], &model); faluco@656: faluco@656: return engine->PrecacheModel(model, params[2] ? true : false); faluco@656: } faluco@656: faluco@656: static cell_t PrecacheSentenceFile(IPluginContext *pContext, const cell_t *params) faluco@656: { faluco@656: char *sentencefile; faluco@656: pContext->LocalToString(params[1], &sentencefile); faluco@656: faluco@656: return engine->PrecacheSentenceFile(sentencefile, params[2] ? true : false); faluco@656: } faluco@656: faluco@656: static cell_t PrecacheDecal(IPluginContext *pContext, const cell_t *params) faluco@656: { faluco@656: char *decal; faluco@656: pContext->LocalToString(params[1], &decal); faluco@656: faluco@656: return engine->PrecacheDecal(decal, params[2] ? true : false); faluco@656: } faluco@656: faluco@656: static cell_t PrecacheGeneric(IPluginContext *pContext, const cell_t *params) faluco@656: { faluco@656: char *generic; faluco@656: pContext->LocalToString(params[1], &generic); faluco@656: faluco@656: return engine->PrecacheGeneric(generic, params[2] ? true : false); faluco@656: } faluco@656: faluco@656: static cell_t IsModelPrecached(IPluginContext *pContext, const cell_t *params) faluco@656: { faluco@656: char *model; faluco@656: pContext->LocalToString(params[1], &model); faluco@656: faluco@656: return engine->IsModelPrecached(model) ? 1 : 0; faluco@656: } faluco@656: faluco@656: static cell_t IsDecalPrecached(IPluginContext *pContext, const cell_t *params) faluco@656: { faluco@656: char *decal; faluco@656: pContext->LocalToString(params[1], &decal); faluco@656: faluco@656: return engine->IsDecalPrecached(decal) ? 1 : 0; faluco@656: } faluco@656: faluco@656: static cell_t IsGenericPrecached(IPluginContext *pContext, const cell_t *params) faluco@656: { faluco@656: char *generic; faluco@656: pContext->LocalToString(params[1], &generic); faluco@656: faluco@656: return engine->IsGenericPrecached(generic) ? 1 : 0; faluco@656: } faluco@656: faluco@656: static cell_t PrecacheSound(IPluginContext *pContext, const cell_t *params) faluco@656: { faluco@656: char *sample; faluco@656: pContext->LocalToString(params[1], &sample); faluco@656: faluco@656: return enginesound->PrecacheSound(sample, params[2] ? true : false) ? 1 : 0; faluco@656: } faluco@656: faluco@656: static cell_t IsSoundPrecached(IPluginContext *pContext, const cell_t *params) faluco@656: { faluco@656: char *sample; faluco@656: pContext->LocalToString(params[1], &sample); faluco@656: faluco@656: return enginesound->IsSoundPrecached(sample) ? 1 : 0; faluco@656: } faluco@656: faluco@682: static cell_t smn_CreateDialog(IPluginContext *pContext, const cell_t *params) faluco@682: { faluco@682: KeyValues *pKV; faluco@682: HandleError herr; faluco@682: Handle_t hndl = static_cast(params[2]); faluco@682: CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]); faluco@682: faluco@682: if (!pPlayer) faluco@682: { ds@994: return pContext->ThrowNativeError("Client index %d is invalid", params[1]); faluco@682: } faluco@682: ds@891: if (!pPlayer->IsInGame()) faluco@682: { ds@891: return pContext->ThrowNativeError("Client %d is not in game", params[1]); faluco@682: } faluco@682: faluco@682: pKV = g_SourceMod.ReadKeyValuesHandle(hndl, &herr, true); faluco@682: if (herr != HandleError_None) faluco@682: { faluco@682: return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr); faluco@682: } faluco@682: dvander@1581: serverpluginhelpers->CreateMessage(pPlayer->GetEdict(), dvander@1581: static_cast(params[3]), dvander@1581: pKV, dvander@1581: vsp_interface); faluco@682: faluco@682: return 1; faluco@682: } faluco@682: ds@873: static cell_t PrintToChat(IPluginContext *pContext, const cell_t *params) ds@873: { ds@873: int client = params[1]; ds@873: CPlayer *pPlayer = g_Players.GetPlayerByIndex(client); ds@873: ds@873: if (!pPlayer) ds@873: { ds@994: return pContext->ThrowNativeError("Client index %d is invalid", client); ds@873: } ds@873: ds@891: if (!pPlayer->IsInGame()) ds@873: { ds@892: return pContext->ThrowNativeError("Client %d is not in game", client); ds@873: } ds@873: dvander@1011: g_SourceMod.SetGlobalTarget(client); dvander@1011: ds@899: char buffer[192]; ds@873: g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); ds@873: dvander@1017: /* Check for an error before printing to the client */ dvander@2175: if (pContext->GetLastNativeError() != SP_ERROR_NONE) dvander@1017: { dvander@1017: return 0; dvander@1017: } dvander@1017: dvander@1132: if (!g_HL2.TextMsg(client, HUD_PRINTTALK, buffer)) dvander@1132: { dvander@1132: return pContext->ThrowNativeError("Could not send a usermessage"); dvander@1132: } ds@873: ds@873: return 1; ds@873: } ds@873: ds@873: static cell_t PrintCenterText(IPluginContext *pContext, const cell_t *params) ds@873: { ds@873: int client = params[1]; ds@873: CPlayer *pPlayer = g_Players.GetPlayerByIndex(client); ds@873: ds@873: if (!pPlayer) ds@873: { ds@994: return pContext->ThrowNativeError("Client index %d is invalid", client); ds@873: } ds@873: ds@891: if (!pPlayer->IsInGame()) ds@873: { ds@892: return pContext->ThrowNativeError("Client %d is not in game", client); ds@873: } ds@873: dvander@1011: g_SourceMod.SetGlobalTarget(client); dvander@1011: ds@899: char buffer[192]; ds@873: g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); ds@873: dvander@1017: /* Check for an error before printing to the client */ dvander@2175: if (pContext->GetLastNativeError() != SP_ERROR_NONE) dvander@1017: { dvander@1017: return 0; dvander@1017: } dvander@1017: dvander@1132: if (!g_HL2.TextMsg(client, HUD_PRINTCENTER, buffer)) dvander@1132: { dvander@1132: return pContext->ThrowNativeError("Could not send a usermessage"); dvander@1132: } ds@873: ds@873: return 1; ds@873: } ds@873: faluco@1218: static cell_t PrintHintText(IPluginContext *pContext, const cell_t *params) faluco@1218: { faluco@1218: int client = params[1]; faluco@1218: CPlayer *pPlayer = g_Players.GetPlayerByIndex(client); faluco@1218: faluco@1218: if (!pPlayer) faluco@1218: { faluco@1218: return pContext->ThrowNativeError("Client index %d is invalid", client); faluco@1218: } faluco@1218: faluco@1218: if (!pPlayer->IsInGame()) faluco@1218: { faluco@1218: return pContext->ThrowNativeError("Client %d is not in game", client); faluco@1218: } faluco@1218: faluco@1218: g_SourceMod.SetGlobalTarget(client); faluco@1218: faluco@1218: char buffer[192]; faluco@1218: g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); faluco@1218: faluco@1218: /* Check for an error before printing to the client */ dvander@2175: if (pContext->GetLastNativeError() != SP_ERROR_NONE) faluco@1218: { faluco@1218: return 0; faluco@1218: } faluco@1218: teame06@1264: if (!g_HL2.HintTextMsg(client, buffer)) faluco@1218: { faluco@1218: return pContext->ThrowNativeError("Could not send a usermessage"); faluco@1218: } faluco@1218: faluco@1218: return 1; faluco@1218: } faluco@1218: faluco@1218: static cell_t ShowVGUIPanel(IPluginContext *pContext, const cell_t *params) faluco@1218: { faluco@1218: HandleError herr; faluco@1218: char *name; faluco@1218: KeyValues *pKV = NULL; faluco@1218: int client = params[1]; faluco@1218: Handle_t hndl = static_cast(params[3]); faluco@1218: CPlayer *pPlayer = g_Players.GetPlayerByIndex(client); faluco@1218: faluco@1218: if (!pPlayer) faluco@1218: { faluco@1218: return pContext->ThrowNativeError("Client index %d is invalid", client); faluco@1218: } faluco@1218: faluco@1218: if (!pPlayer->IsInGame()) faluco@1218: { faluco@1218: return pContext->ThrowNativeError("Client %d is not in game", client); faluco@1218: } faluco@1218: faluco@1218: if (hndl != BAD_HANDLE) faluco@1218: { faluco@1218: pKV = g_SourceMod.ReadKeyValuesHandle(hndl, &herr, true); faluco@1218: if (herr != HandleError_None) faluco@1218: { faluco@1218: return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr); faluco@1218: } faluco@1218: } faluco@1218: faluco@1218: pContext->LocalToString(params[2], &name); faluco@1218: faluco@1218: if (!g_HL2.ShowVGUIMenu(client, name, pKV, (params[4]) ? true : false)) faluco@1218: { faluco@1218: return pContext->ThrowNativeError("Could not send a usermessage"); faluco@1218: } faluco@1218: faluco@1218: return 1; faluco@1218: } faluco@1218: dvander@1621: static cell_t smn_IsPlayerAlive(IPluginContext *pContext, const cell_t *params) dvander@1621: { dvander@1621: CPlayer *player = g_Players.GetPlayerByIndex(params[1]); dvander@1621: if (player == NULL) dvander@1621: { dvander@1621: return pContext->ThrowNativeError("Invalid client index %d", params[1]); dvander@1621: } dvander@1621: else if (!player->IsInGame()) dvander@1621: { dvander@1621: return pContext->ThrowNativeError("Client %d is not in game", params[1]); dvander@1621: } dvander@1621: dvander@1621: unsigned int state = player->GetLifeState(); dvander@1621: dvander@1621: if (state == PLAYER_LIFE_UNKNOWN) dvander@1621: { dvander@1621: return pContext->ThrowNativeError("\"IsPlayerAlive\" not supported by this mod"); dvander@1621: } dvander@1621: else if (state == PLAYER_LIFE_ALIVE) dvander@1621: { dvander@1621: return 1; dvander@1621: } dvander@1621: else dvander@1621: { dvander@1621: return 0; dvander@1621: } dvander@1621: } dvander@1621: dvander@1837: static cell_t GuessSDKVersion(IPluginContext *pContext, const cell_t *params) dvander@1837: { dvander@2846: #if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 dvander@1837: int version = g_SMAPI->GetSourceEngineBuild(); dvander@1837: dvander@2846: switch (version) dvander@1837: { dvander@2846: case SOURCE_ENGINE_ORIGINAL: dvander@2846: return 10; dvander@2846: case SOURCE_ENGINE_EPISODEONE: dvander@1837: return 20; dvander@2846: fyrenmoo@2857: # if defined METAMOD_PLAPI_VERSION dvander@2846: /* Newer games. */ dvander@2846: case SOURCE_ENGINE_DARKMESSIAH: dvander@2846: return 15; dvander@2846: case SOURCE_ENGINE_ORANGEBOX: dvander@1837: return 30; skamonkey@3180: case SOURCE_ENGINE_BLOODYGOODTIME: skamonkey@3180: return 32; skamonkey@3373: case SOURCE_ENGINE_EYE: skamonkey@3427: return 33; skamonkey@3613: case SOURCE_ENGINE_CSS: skamonkey@3613: return 34; fyrenmoo@2889: case SOURCE_ENGINE_ORANGEBOXVALVE: fyrenmoo@2889: return 35; dvander@2846: case SOURCE_ENGINE_LEFT4DEAD: fyrenmoo@2731: return 40; fyrenmoo@2851: case SOURCE_ENGINE_LEFT4DEAD2: fyrenmoo@2851: return 50; ds@3099: case SOURCE_ENGINE_ALIENSWARM: ds@3099: return 60; skamonkey@3515: case SOURCE_ENGINE_PORTAL2: skamonkey@3515: return 70; skamonkey@3515: case SOURCE_ENGINE_CSGO: skamonkey@3515: return 80; dvander@2846: # endif fyrenmoo@2731: } dvander@1837: #else dvander@1837: if (g_HL2.IsOriginalEngine()) dvander@1837: { dvander@1837: return 10; dvander@1837: } dvander@1837: else dvander@1837: { dvander@1837: return 20; dvander@1837: } dvander@1837: #endif dvander@1837: dvander@1837: return 0; dvander@1837: } dvander@1837: pred@2746: static cell_t IndexToReference(IPluginContext *pContext, const cell_t *params) pred@2746: { pred@2746: if (params[1] >= NUM_ENT_ENTRIES || params[1] < 0) pred@2746: { pred@2746: return pContext->ThrowNativeError("Invalid entity index %i", params[1]); pred@2746: } pred@2746: pred@2746: return g_HL2.IndexToReference(params[1]); pred@2746: } pred@2746: pred@2746: static cell_t ReferenceToIndex(IPluginContext *pContext, const cell_t *params) pred@2746: { pred@2746: return g_HL2.ReferenceToIndex(params[1]); pred@2746: } pred@2746: pred@2746: static cell_t ReferenceToBCompatRef(IPluginContext *pContext, const cell_t *params) pred@2746: { pred@2746: return g_HL2.ReferenceToBCompatRef(params[1]); pred@2746: } pred@2746: dvander@530: REGISTER_NATIVES(halflifeNatives) dvander@530: { dvander@532: {"CreateFakeClient", CreateFakeClient}, dvander@532: {"GetCurrentMap", GetCurrentMap}, dvander@532: {"GetEngineTime", GetEngineTime}, dvander@532: {"GetGameDescription", GetGameDescription}, ds@721: {"GetGameFolderName", GetGameFolderName}, dvander@532: {"GetGameTime", GetGameTime}, aangione@3540: {"GetGameTickCount", GetGameTickCount}, dvander@530: {"GetRandomFloat", GetRandomFloat}, dvander@530: {"GetRandomInt", GetRandomInt}, dvander@532: {"IsDedicatedServer", IsDedicatedServer}, dvander@532: {"IsMapValid", IsMapValid}, dvander@532: {"SetFakeClientConVar", SetFakeClientConVar}, dvander@532: {"SetRandomSeed", SetRandomSeed}, faluco@656: {"PrecacheModel", PrecacheModel}, faluco@656: {"PrecacheSentenceFile", PrecacheSentenceFile}, faluco@656: {"PrecacheDecal", PrecacheDecal}, faluco@656: {"PrecacheGeneric", PrecacheGeneric}, faluco@656: {"IsModelPrecached", IsModelPrecached}, faluco@656: {"IsDecalPrecached", IsDecalPrecached}, faluco@656: {"IsGenericPrecached", IsGenericPrecached}, faluco@656: {"PrecacheSound", PrecacheSound}, faluco@656: {"IsSoundPrecached", IsSoundPrecached}, faluco@682: {"CreateDialog", smn_CreateDialog}, ds@873: {"PrintToChat", PrintToChat}, ds@873: {"PrintCenterText", PrintCenterText}, faluco@1218: {"PrintHintText", PrintHintText}, faluco@1218: {"ShowVGUIPanel", ShowVGUIPanel}, dvander@1621: {"IsPlayerAlive", smn_IsPlayerAlive}, dvander@1837: {"GuessSDKVersion", GuessSDKVersion}, pred@2746: {"EntIndexToEntRef", IndexToReference}, pred@2746: {"EntRefToEntIndex", ReferenceToIndex}, pred@2746: {"MakeCompatEntRef", ReferenceToBCompatRef}, dvander@530: {NULL, NULL}, dvander@530: };