Added check to make sure player are alive to perform sm_slap, sm_burn, sm_slay.
3 * ================================================================
5 * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
6 * ================================================================
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License,
10 * version 3.0, as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to
21 * link the code of this program (as well as its derivative works) to
22 * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any
23 * Game MODs that run on software by the Valve Corporation. You must
24 * obey the GNU General Public License in all respects for all other
25 * code used. Additionally, AlliedModders LLC grants this exception
26 * to all derivative works. AlliedModders LLC defines further
27 * exceptions, found in LICENSE.txt (as of this writing, version
28 * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
33 #include "sm_globals.h"
34 #include "PluginSys.h"
35 #include "ForwardSys.h"
36 #include "HandleSys.h"
38 HandleType_t g_GlobalFwdType = 0;
39 HandleType_t g_PrivateFwdType = 0;
41 static bool s_CallStarted = false;
42 static ICallable *s_pCallable = NULL;
43 static IPluginFunction *s_pFunction = NULL;
44 static IForward *s_pForward = NULL;
46 class ForwardNativeHelpers :
48 public IHandleTypeDispatch
51 void OnSourceModAllInitialized()
55 /* Set GlobalFwd handle access security */
56 g_HandleSys.InitAccessDefaults(NULL, &sec);
57 sec.access[HandleAccess_Read] = 0;
58 sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
60 /* Create 'GlobalFwd' handle type */
61 g_GlobalFwdType = g_HandleSys.CreateType("GlobalFwd", this, 0, NULL, &sec, g_pCoreIdent, NULL);
63 /* Private forwards are cloneable */
64 sec.access[HandleAccess_Clone] = 0;
66 /* Create 'PrivateFwd' handle type */
67 g_PrivateFwdType = g_HandleSys.CreateType("PrivateFwd", this, g_GlobalFwdType, NULL, &sec, g_pCoreIdent, NULL);
70 void OnSourceModShutdown()
72 g_HandleSys.RemoveType(g_PrivateFwdType, g_pCoreIdent);
73 g_HandleSys.RemoveType(g_GlobalFwdType, g_pCoreIdent);
76 void OnHandleDestroy(HandleType_t type, void *object)
78 IForward *pForward = static_cast<IForward *>(object);
80 g_Forwards.ReleaseForward(pForward);
82 } g_ForwardNativeHelpers;
85 /* Turn a public index into a function ID */
86 inline funcid_t PublicIndexToFuncId(uint32_t idx)
88 return (idx << 1) | (1 << 0);
91 /* Reset global function/forward call variables */
92 inline void ResetCall()
94 s_CallStarted = false;
100 static cell_t sm_GetFunctionByName(IPluginContext *pContext, const cell_t *params)
102 Handle_t hndl = static_cast<Handle_t>(params[1]);
110 pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
112 pPlugin = g_PluginSys.PluginFromHandle(hndl, &err);
116 return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", hndl, err);
120 pContext->LocalToString(params[2], &name);
122 /* Get public function index */
123 if (pPlugin->GetBaseContext()->FindPublicByName(name, &idx) == SP_ERROR_NOT_FOUND)
125 /* Return INVALID_FUNCTION if not found */
129 /* Return function ID */
130 return PublicIndexToFuncId(idx);
133 static cell_t sm_CreateGlobalForward(IPluginContext *pContext, const cell_t *params)
135 cell_t count = params[0];
137 ParamType forwardParams[SP_MAX_EXEC_PARAMS];
139 if (count - 2 > SP_MAX_EXEC_PARAMS)
141 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAMS_MAX, NULL);
144 pContext->LocalToString(params[1], &name);
147 for (int i = 3; i <= count; i++)
149 pContext->LocalToPhysAddr(params[i], &addr);
150 forwardParams[i - 3] = static_cast<ParamType>(*addr);
153 IForward *pForward = g_Forwards.CreateForward(name, static_cast<ExecType>(params[2]), count - 2, forwardParams);
155 return g_HandleSys.CreateHandle(g_GlobalFwdType, pForward, pContext->GetIdentity(), g_pCoreIdent, NULL);
158 static cell_t sm_CreateForward(IPluginContext *pContext, const cell_t *params)
160 cell_t count = params[0];
161 ParamType forwardParams[SP_MAX_EXEC_PARAMS];
163 if (count - 1 > SP_MAX_EXEC_PARAMS)
165 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAMS_MAX, NULL);
169 for (int i = 2; i <= count; i++)
171 pContext->LocalToPhysAddr(params[i], &addr);
172 forwardParams[i - 2] = static_cast<ParamType>(*addr);
175 IChangeableForward *pForward = g_Forwards.CreateForwardEx(NULL, static_cast<ExecType>(params[1]), count - 1, forwardParams);
177 return g_HandleSys.CreateHandle(g_PrivateFwdType, pForward, pContext->GetIdentity(), g_pCoreIdent, NULL);
180 static cell_t sm_GetForwardFunctionCount(IPluginContext *pContext, const cell_t *params)
182 Handle_t hndl = static_cast<Handle_t>(params[1]);
186 if ((err=g_HandleSys.ReadHandle(hndl, g_GlobalFwdType, NULL, (void **)&pForward))
189 return pContext->ThrowNativeError("Invalid forward handle %x (error %d)", hndl, err);
192 return pForward->GetFunctionCount();
195 static cell_t sm_AddToForward(IPluginContext *pContext, const cell_t *params)
197 Handle_t fwdHandle = static_cast<Handle_t>(params[1]);
198 Handle_t plHandle = static_cast<Handle_t>(params[2]);
200 IChangeableForward *pForward;
203 if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
206 return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
211 pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
213 pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
217 return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err);
221 IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[3]);
225 return pContext->ThrowNativeError("Invalid function id (%X)", params[3]);
228 return pForward->AddFunction(pFunction);
231 static cell_t sm_RemoveFromForward(IPluginContext *pContext, const cell_t *params)
233 Handle_t fwdHandle = static_cast<Handle_t>(params[1]);
234 Handle_t plHandle = static_cast<Handle_t>(params[2]);
236 IChangeableForward *pForward;
239 if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
242 return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
247 pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
249 pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
253 return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err);
257 IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[3]);
261 return pContext->ThrowNativeError("Invalid function id (%X)", params[3]);
264 return pForward->RemoveFunction(pFunction);
267 static cell_t sm_RemoveAllFromForward(IPluginContext *pContext, const cell_t *params)
269 Handle_t fwdHandle = static_cast<Handle_t>(params[1]);
270 Handle_t plHandle = static_cast<Handle_t>(params[2]);
272 IChangeableForward *pForward;
275 if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
278 return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
283 pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
285 pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
289 return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err);
293 return pForward->RemoveFunctionsOfPlugin(pPlugin);
296 static cell_t sm_CallStartFunction(IPluginContext *pContext, const cell_t *params)
304 return pContext->ThrowNativeError("Cannot start a call while one is already in progress");
307 hndl = static_cast<Handle_t>(params[1]);
311 pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
313 pPlugin = g_PluginSys.PluginFromHandle(hndl, &err);
317 return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", hndl, err);
321 s_pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[2]);
325 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
328 s_pCallable = static_cast<ICallable *>(s_pFunction);
330 s_CallStarted = true;
335 static cell_t sm_CallStartForward(IPluginContext *pContext, const cell_t *params)
343 return pContext->ThrowNativeError("Cannot start a call while one is already in progress");
346 hndl = static_cast<Handle_t>(params[1]);
348 if ((err=g_HandleSys.ReadHandle(hndl, g_GlobalFwdType, NULL, (void **)&pForward))
351 return pContext->ThrowNativeError("Invalid forward handle %x (error %d)", hndl, err);
354 s_pForward = pForward;
356 s_pCallable = static_cast<ICallable *>(pForward);
358 s_CallStarted = true;
363 static cell_t sm_CallPushCell(IPluginContext *pContext, const cell_t *params)
369 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
372 err = s_pCallable->PushCell(params[1]);
376 s_pCallable->Cancel();
378 return pContext->ThrowNativeErrorEx(err, NULL);
384 static cell_t sm_CallPushCellRef(IPluginContext *pContext, const cell_t *params)
391 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
394 pContext->LocalToPhysAddr(params[1], &addr);
396 err = s_pCallable->PushCellByRef(addr);
400 s_pCallable->Cancel();
402 return pContext->ThrowNativeErrorEx(err, NULL);
408 static cell_t sm_CallPushFloat(IPluginContext *pContext, const cell_t *params)
414 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
417 err = s_pCallable->PushFloat(sp_ctof(params[1]));
421 s_pCallable->Cancel();
423 return pContext->ThrowNativeErrorEx(err, NULL);
429 static cell_t sm_CallPushFloatRef(IPluginContext *pContext, const cell_t *params)
436 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
439 pContext->LocalToPhysAddr(params[1], &addr);
441 err = s_pCallable->PushFloatByRef(reinterpret_cast<float *>(addr));
445 s_pCallable->Cancel();
447 return pContext->ThrowNativeErrorEx(err, NULL);
453 static cell_t sm_CallPushArray(IPluginContext *pContext, const cell_t *params)
460 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
463 pContext->LocalToPhysAddr(params[1], &addr);
465 err = s_pCallable->PushArray(addr, params[2]);
469 s_pCallable->Cancel();
471 return pContext->ThrowNativeErrorEx(err, NULL);
477 static cell_t sm_CallPushArrayEx(IPluginContext *pContext, const cell_t *params)
484 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
487 pContext->LocalToPhysAddr(params[1], &addr);
489 err = s_pCallable->PushArray(addr, params[2], params[3]);
493 s_pCallable->Cancel();
495 return pContext->ThrowNativeErrorEx(err, NULL);
501 static cell_t sm_CallPushString(IPluginContext *pContext, const cell_t *params)
508 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
511 pContext->LocalToString(params[1], &value);
513 err = s_pCallable->PushString(value);
517 s_pCallable->Cancel();
519 return pContext->ThrowNativeErrorEx(err, NULL);
525 static cell_t sm_CallPushStringEx(IPluginContext *pContext, const cell_t *params)
532 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
535 pContext->LocalToString(params[1], &value);
537 err = s_pCallable->PushStringEx(value, params[2], params[3], params[4]);
541 s_pCallable->Cancel();
543 return pContext->ThrowNativeErrorEx(err, NULL);
549 static cell_t sm_CallFinish(IPluginContext *pContext, const cell_t *params)
551 int err = SP_ERROR_NOT_RUNNABLE;
556 return pContext->ThrowNativeError("Cannot finish call when there is no call in progress");
559 pContext->LocalToPhysAddr(params[1], &result);
563 IPluginFunction *pFunction = s_pFunction;
565 err = pFunction->Execute(result);
566 } else if (s_pForward) {
567 IForward *pForward = s_pForward;
569 err = pForward->Execute(result, NULL);
575 static cell_t sm_CallCancel(IPluginContext *pContext, const cell_t *params)
579 return pContext->ThrowNativeError("Cannot cancel call when there is no call in progress");
582 s_pCallable->Cancel();
588 REGISTER_NATIVES(functionNatives)
590 {"GetFunctionByName", sm_GetFunctionByName},
591 {"CreateGlobalForward", sm_CreateGlobalForward},
592 {"CreateForward", sm_CreateForward},
593 {"GetForwardFunctionCount", sm_GetForwardFunctionCount},
594 {"AddToForward", sm_AddToForward},
595 {"RemoveFromForward", sm_RemoveFromForward},
596 {"RemoveAllFromForward", sm_RemoveAllFromForward},
597 {"Call_StartFunction", sm_CallStartFunction},
598 {"Call_StartForward", sm_CallStartForward},
599 {"Call_PushCell", sm_CallPushCell},
600 {"Call_PushCellRef", sm_CallPushCellRef},
601 {"Call_PushFloat", sm_CallPushFloat},
602 {"Call_PushFloatRef", sm_CallPushFloatRef},
603 {"Call_PushArray", sm_CallPushArray},
604 {"Call_PushArrayEx", sm_CallPushArrayEx},
605 {"Call_PushString", sm_CallPushString},
606 {"Call_PushStringEx", sm_CallPushStringEx},
607 {"Call_Finish", sm_CallFinish},
608 {"Call_Cancel", sm_CallCancel},