diff --git a/core/smn_admin.cpp b/core/smn_admin.cpp index 67f1addc..4f6e3ed6 100644 --- a/core/smn_admin.cpp +++ b/core/smn_admin.cpp @@ -418,6 +418,11 @@ static cell_t FlagBitsToArray(IPluginContext *pContext, const cell_t *params) } } +static cell_t CanAdminTarget(IPluginContext *pContext, const cell_t *params) +{ + return g_Admins.CanAdminTarget(params[1], params[2]) ? 1 : 0; +} + REGISTER_NATIVES(adminNatives) { {"DumpAdminCache", DumpAdminCache}, @@ -454,6 +459,7 @@ REGISTER_NATIVES(adminNatives) {"FlagBitArrayToBits", FlagBitArrayToBits}, {"FlagArrayToBits", FlagArrayToBits}, {"FlagBitsToArray", FlagBitsToArray}, + {"CanAdminTarget", CanAdminTarget}, /* -------------------------------------------------- */ {NULL, NULL}, }; diff --git a/core/smn_player.cpp b/core/smn_player.cpp index c480bee4..c520c01e 100644 --- a/core/smn_player.cpp +++ b/core/smn_player.cpp @@ -345,6 +345,30 @@ static cell_t GetClientUserId(IPluginContext *pContext, const cell_t *params) return engine->GetPlayerUserId(pPlayer->GetEdict()); } +static cell_t CanUserTarget(IPluginContext *pContext, const cell_t *params) +{ + int client = params[1]; + int target = params[2]; + + CPlayer *pPlayer = g_Players.GetPlayerByIndex(client); + if (!pPlayer) + { + return pContext->ThrowNativeError("Player %d is not a valid client", client); + } else if (!pPlayer->IsConnected()) { + return pContext->ThrowNativeError("Player %d is not connected", client); + } + + CPlayer *pTarget = g_Players.GetPlayerByIndex(target); + if (!pTarget) + { + return pContext->ThrowNativeError("Player %d is not a valid client", target); + } else if (!pTarget->IsConnected()) { + return pContext->ThrowNativeError("Player %d is not connected", target); + } + + return g_Admins.CanAdminTarget(pPlayer->GetAdminId(), pTarget->GetAdminId()) ? 1 : 0; +} + REGISTER_NATIVES(playernatives) { {"GetMaxClients", sm_GetMaxClients}, @@ -364,6 +388,7 @@ REGISTER_NATIVES(playernatives) {"SetUserFlagBits", SetUserFlagBits}, {"GetUserFlagBits", GetUserFlagBits}, {"GetClientUserId", GetClientUserId}, + {"CanUserTarget", CanUserTarget}, {NULL, NULL} }; diff --git a/plugins/include/admin.inc b/plugins/include/admin.inc index d803edf3..6c929eb0 100644 --- a/plugins/include/admin.inc +++ b/plugins/include/admin.inc @@ -462,12 +462,33 @@ native FlagArrayToBits(const AdminFlag:array[], numFlags) =0; */ native FlagBitsToArray(bits, AdminFlag:array[], maxSize) =0; +/** + * Tests whether one admin can target another. + * + * @param admin Admin doing the targetting (may be INVALID_ADMIN_ID). + * @param target Target admin (may be INVALID_ADMIN_ID). + * @return True if targetable, false if immune. + */ +native CanAdminTarget(AdminId:admin, AdminId:target); +/** + * Converts a flag to its single bit. + * + * @param flag Flag to convert. + * @return Bit representation of the flag. + */ stock FlagToBit(AdminFlag:flag) { return (1<<_:flag); } +/** + * Converts a bit to an AdminFlag. + * + * @param bit Bit to convert. + * @param flag Stores the converted flag by reference. + * @return True on success, false otherwise. + */ stock bool:BitToFlag(bit, &AdminFlag:flag) { new AdminFlag:array[1]; diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index cab69d2c..8080c4e4 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -328,6 +328,17 @@ native SetUserFlagBits(client, flags); */ native GetUserFlagBits(client); +/** + * Returns whether a user can target another user. + * This is a helper function for CanAdminTarget. + * + * @param client Player's index. + * @param target Target player's index. + * @return True if target is targettable by the player, false otherwise. + * @error Invalid or unconnected player indexers. + */ +native bool:CanUserTarget(client, target); + /** * Logs a generic message to the HL2 logs. *