From e7478e0a055dc65b31c7669f612ba31bf6c52819 Mon Sep 17 00:00:00 2001 From: Richard Helgeby Date: Sun, 14 Nov 2010 15:17:19 +0100 Subject: [PATCH] Imported some API-features from zr-dev. Added API test plugins in testsuite. --- Makefile | 4 +- buildtests.sh | 12 ++ src/include/zombiereloaded.inc | 35 +++++ src/include/zr/infect.zr.inc | 123 ++++++++++++++++ src/include/zr/respawn.zr.inc | 95 ++++++++++++ src/testsuite/zr/infectapitest.sp | 176 ++++++++++++++++++++++ src/testsuite/zr/respawnapitest.sp | 132 +++++++++++++++++ src/zombiereloaded.sp | 5 +- src/zr/api/api.inc | 92 ++++++++++++ src/zr/api/infect.api.inc | 229 +++++++++++++++++++++++++++++ src/zr/api/respawn.api.inc | 149 +++++++++++++++++++ src/zr/infect.inc | 20 +++ src/zr/respawn.inc | 118 ++++++++++++--- src/zr/zombiereloaded.inc | 10 ++ src/zr/zspawn.inc | 4 +- 15 files changed, 1179 insertions(+), 25 deletions(-) create mode 100755 buildtests.sh create mode 100644 src/include/zombiereloaded.inc create mode 100644 src/include/zr/infect.zr.inc create mode 100644 src/include/zr/respawn.zr.inc create mode 100644 src/testsuite/zr/infectapitest.sp create mode 100644 src/testsuite/zr/respawnapitest.sp create mode 100644 src/zr/api/api.inc create mode 100644 src/zr/api/infect.api.inc create mode 100644 src/zr/api/respawn.api.inc diff --git a/Makefile b/Makefile index 95f5cee..f9f6f47 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ SPCOMP=env/linux/bin/spcomp-1.3.4 VERSIONDUMP=./updateversion.sh vpath %.sp $(SOURCEDIR) -vpath %.inc $(SOURCEDIR)/include +vpath %.inc $(SOURCEDIR)/zr vpath %.smx $(BUILDDIR) SOURCEFILES=$(SOURCEDIR)/*.sp @@ -19,7 +19,7 @@ prepare: prepare_newlines prepare_builddir prepare_newlines: @echo "Removing windows newlines" - @find $(SOURCEDIR) -name \*.inc -exec dos2unix -p '{}' \; + @find $(SOURCEDIR)/zr -name \*.inc -exec dos2unix -p '{}' \; @find $(SOURCEDIR) -name \*.sp -exec dos2unix -p '{}' \; prepare_builddir: diff --git a/buildtests.sh b/buildtests.sh new file mode 100755 index 0000000..8fa166d --- /dev/null +++ b/buildtests.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +BUILD_DIR=build +SRC=src/testsuite/zr +SM_INCLUDE=env/include +ZR_INCLUDE=src/include +SPCOMP=env/linux/bin/spcomp-1.3.4 + +mkdir -p $BUILD_DIR + +$SPCOMP -i$SM_INCLUDE -i$ZR_INCLUDE -o$BUILD_DIR/respawnapitest.smx $SRC/respawnapitest.sp +$SPCOMP -i$SM_INCLUDE -i$ZR_INCLUDE -o$BUILD_DIR/infectapitest.smx $SRC/infectapitest.sp diff --git a/src/include/zombiereloaded.inc b/src/include/zombiereloaded.inc new file mode 100644 index 0000000..afbd748 --- /dev/null +++ b/src/include/zombiereloaded.inc @@ -0,0 +1,35 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: zombiereloaded.inc + * Type: Include + * Description: Main API include file. + * Notes: Include this file to include the whole ZR API. + * + * Copyright (C) 2009-2010 Greyscale, Richard Helgeby + * + * This program 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. + * + * 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 . + * + * ============================================================================ + */ + +#if defined _zr_included + #endinput +#endif +#define _zr_included + +#include +#include diff --git a/src/include/zr/infect.zr.inc b/src/include/zr/infect.zr.inc new file mode 100644 index 0000000..e3b9ce3 --- /dev/null +++ b/src/include/zr/infect.zr.inc @@ -0,0 +1,123 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: infect.zr.inc + * Type: Include + * Description: Infect-related natives/forwards. + * + * Copyright (C) 2009-2010 Greyscale, Richard Helgeby + * + * This program 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. + * + * 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 . + * + * ============================================================================ + */ + +/** + * Returns true if the player is a zombie, false if not. + * + * @param client The client index. + * + * @return True if zombie, false if not. + * @error Invalid client index, not connected or not alive. + */ +native bool:ZR_IsClientZombie(client); + +/** + * Returns true if the player is a human, false if not. + * + * @param client The client index. + * + * @return True if human, false if not. + * @error Invalid client index, not connected or not alive. + */ +native bool:ZR_IsClientHuman(client); + +/** + * Infects a player. + * + * Note: If the player already is a zombie, the player will be re-infected. + * + * @param client The client to infect. + * @param attacker (Optional) The attacker who did the infect. + * @param motherInfect (Optional) Infect as a mother zombie. + * @param respawnOverride (Optional) Set to true to override respawn cvar. + * @param respawn (Optional) Value to override with. + * + * @error Invalid client index, not connected or not alive. + */ +native ZR_InfectClient(client, attacker = -1, bool:motherInfect = false, bool:respawnOverride = false, bool:respawn = false); + +/** + * Turns a zombie back into a human. + * + * Note: If the player already is a human, this code will still run as the + * player was a zombie. + * + * @param client The client to make human. + * @param respawn Teleport client back to spawn. + * @param protect Start spawn protection on client. + * + * @error Invalid client index, not connected or not alive. + */ +native ZR_HumanClient(client, bool:respawn = false, bool:protect = false); + +/** + * Called when a player is about to become a zombie. + * Here you can modify any variable or block the infection entirely. + * + * @param client The client index. + * @param attacker The the infecter. (-1 if there is no infecter) + * @param motherInfect If the client is becoming a mother zombie. + * @param respawnOverride True if the respawn cvar is being overridden. + * @param respawn The value that respawn is being overridden with. + * + * @return Plugin_Handled to block infection. Anything else + * (like Plugin_Continue) to allow infection. + */ +forward Action:ZR_OnClientInfect(&client, &attacker, &bool:motherInfect, &bool:respawnOverride, &bool:respawn); + +/** + * Called after a player has become a zombie. + * + * @param client The client that was infected. + * @param attacker The the infecter. (-1 if there is no infecter) + * @param motherInfect If the client is a mother zombie. + * @param respawnOverride True if the respawn cvar was overridden. + * @param respawn The value that respawn was overridden with. + */ +forward ZR_OnClientInfected(client, attacker, bool:motherInfect, bool:respawnOverride, bool:respawn); + +/** + * Called when a player is about to become a human. (Through an admin command). + * Here you can modify any variable or block the action entirely. + * + * @param client The client index. + * @param respawn True if the client was respawned, false if not. + * @param protect True if the client spawn protected, false if not. + * + * @return Plugin_Handled to block infection. Anything else + * (like Plugin_Continue) to allow acion. + */ +forward Action:ZR_OnClientHuman(&client, &bool:respawn, &bool:protect); + +/** + * Called after a player has become a human. (Through an admin command.) + * + * @param client The client index. + * @param respawn Whether the client was respawned. + * @param protect Whether the client has spawn protection. + */ +forward ZR_OnClientHumanPost(client, bool:respawn, bool:protect); diff --git a/src/include/zr/respawn.zr.inc b/src/include/zr/respawn.zr.inc new file mode 100644 index 0000000..f27c1ee --- /dev/null +++ b/src/include/zr/respawn.zr.inc @@ -0,0 +1,95 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: respawn.zr.inc + * Type: Include + * Description: Infect-related natives/forwards. + * + * Copyright (C) 2009-2010 Greyscale, Richard Helgeby + * + * This program 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. + * + * 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 . + * + * ============================================================================ + */ + +/** + * Conditions for respawning players. + */ +enum ZR_RespawnCondition +{ + ZR_Repsawn_Default = -1, /** Let ZR decide according to its settings. */ + ZR_Respawn_Human = 0, /** Respawn as a human. */ + ZR_Respawn_Zombie, /** Respawn as a zombie. */ + ZR_Respawn_ZombieIfSuicide /** Respawn as a zombie if killed by world damage. */ +} + +/** + * Spawns a player into the round. + * + * @param client The client index. + * @param condition Optional. Set respawn condition, defaults to current + * ZR settings. See ZR_RespawnCondition for details. + * @error Invalid client index, not connected or already alive. + */ +native ZR_RespawnClient(client, ZR_RespawnCondition:condition = ZR_Repsawn_Default); + +/** + * Called right before ZR is about to respawn a player. + * Here you can modify any variable or stop the action entirely. + * + * @param client The client index. + * @param condition Respawn condition. See ZR_RespawnCondition for + * details. + * + * @return Plugin_Handled to block respawn. + */ +forward Action:ZR_OnClientRespawn(&client, &ZR_RespawnCondition:condition); + +/** + * Called after ZR respawned a player. + * + * @param client The client index. + * @param condition Current condition of the respawned player. See + * ZR_RespawnCondition for details. + */ +forward ZR_OnClientRespawned(client, ZR_RespawnCondition:condition); + +/** + * Set if a player died by a suicide or world damage. + + * Note: This will change the respawn condition. + * Note: This value is reset to default by ZR when a zombie player dies. + * + * @param client The client index. + * @param suicide True to say the player suicided, false if killed by another + * player. + * + * @error Invalid client index or not connected. + */ +native ZR_SetKilledByWorld(client, bool:suicide); + +/** + * Get whether the player died by a suicide or world damage. + * + * Note: This value is only valid after death event, and before respawn. + * + * @param client The client index. + * + * @return True if the player died by suicide, false if killed by + * another player. + * @error Invalid client index or not connected. + */ +native bool:ZR_GetKilledByWorld(client); diff --git a/src/testsuite/zr/infectapitest.sp b/src/testsuite/zr/infectapitest.sp new file mode 100644 index 0000000..4b7a620 --- /dev/null +++ b/src/testsuite/zr/infectapitest.sp @@ -0,0 +1,176 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: respawnapi.sp + * Type: Test plugin + * Description: Tests the infection API. + * + * Copyright (C) 2009-2010 Greyscale, Richard Helgeby + * + * This program 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. + * + * 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 . + * + * ============================================================================ + */ + +#pragma semicolon 1 +#include +#include + +public Plugin:myinfo = +{ + name = "Zombie:Reloaded Infection API Test", + author = "Greyscale | Richard Helgeby", + description = "Tests the infection API for ZR", + version = "1.0.0", + url = "http://code.google.com/p/zombiereloaded/" +}; + +new Handle:cvarBlockInfect; +new Handle:cvarBlockHuman; + +public OnPluginStart() +{ + LoadTranslations("common.phrases"); + + RegConsoleCmd("zrtest_iszombie", IsZombieCommand, "Returns whether a player is a zombie or not. Usage: zrtest_iszombie "); + RegConsoleCmd("zrtest_ishuman", IsHumanCommand, "Returns whether a player is a human or not. Usage: zrtest_ishuman "); + + RegConsoleCmd("zrtest_infect", InfectClientCommand, "Infects a player. Usage: zrtest_infect "); + RegConsoleCmd("zrtest_human", HumanClientCommand, "Turns a player back into a human. Usage: zrtest_human "); + + cvarBlockInfect = CreateConVar("zrtest_block_infect", "0", "Block infection."); + cvarBlockHuman = CreateConVar("zrtest_block_human", "0", "Block turning players back into humans."); +} + +public Action:IsZombieCommand(client, argc) +{ + new target = -1; + new String:valueString[64]; + + if (argc >= 1) + { + GetCmdArg(1, valueString, sizeof(valueString)); + target = FindTarget(client, valueString); + } + else + { + ReplyToCommand(client, "Returns whether a player is a zombie or not. Usage: zrtest_iszombie "); + return Plugin_Handled; + } + + ReplyToCommand(client, "Client %d is a zombie: %d", client, ZR_IsClientZombie(target)); + + return Plugin_Handled; +} + +public Action:IsHumanCommand(client, argc) +{ + new target = -1; + new String:valueString[64]; + + if (argc >= 1) + { + GetCmdArg(1, valueString, sizeof(valueString)); + target = FindTarget(client, valueString); + } + else + { + ReplyToCommand(client, "Returns whether a player is a human or not. Usage: zrtest_ishuman "); + return Plugin_Handled; + } + + ReplyToCommand(client, "Client %d is a human: %d", client, ZR_IsClientHuman(target)); + + return Plugin_Handled; +} + +public Action:InfectClientCommand(client, argc) +{ + new target = -1; + new String:valueString[64]; + + if (argc >= 1) + { + GetCmdArg(1, valueString, sizeof(valueString)); + target = FindTarget(client, valueString); + } + + if (target < 0) + { + ReplyToCommand(client, "Infects a player. Usage: zrtest_infect "); + return Plugin_Handled; + } + + ZR_InfectClient(target); + + return Plugin_Handled; +} + +public Action:HumanClientCommand(client, argc) +{ + new target = -1; + new String:valueString[64]; + + if (argc >= 1) + { + GetCmdArg(1, valueString, sizeof(valueString)); + target = FindTarget(client, valueString); + } + + if (target < 0) + { + ReplyToCommand(client, "Turns a player back into a human. Usage: zrtest_human "); + return Plugin_Handled; + } + + ZR_HumanClient(target); + + return Plugin_Handled; +} + +public Action:ZR_OnClientInfect(&client, &attacker, &bool:motherInfect, &bool:respawnOverride, &bool:respawn) +{ + if (GetConVarBool(cvarBlockInfect)) + { + PrintToChatAll("Infection blocked on client %d.", client); + return Plugin_Handled; + } + + PrintToChatAll("Client %d is about to be infected. Attacker: %d, Mother zombie: %d, Respawn override: %d, Respawn: %d.", client, attacker, motherInfect, respawnOverride, respawn); + return Plugin_Continue; +} + +public ZR_OnClientInfected(client, attacker, bool:motherInfect, bool:respawnOverride, bool:respawn) +{ + PrintToChatAll("Client %d was infected. Attacker: %d, Mother zombie: %d, Respawn override: %d, Respawn: %d.", client, attacker, motherInfect, respawnOverride, respawn); +} + +public Action:ZR_OnClientHuman(&client, &bool:respawn, &bool:protect) +{ + if (GetConVarBool(cvarBlockHuman)) + { + PrintToChatAll("Turning human blocked on client %d.", client); + return Plugin_Handled; + } + + PrintToChatAll("Client %d is about to become a human. Respawn: %d, Spawn protect: %d", client, respawn, protect); + return Plugin_Continue; +} + +public ZR_OnClientHumanPost(client, bool:respawn, bool:protect) +{ + PrintToChatAll("Client %d turned a human. Respawn: %d, Spawn protect: %d", client, respawn, protect); +} diff --git a/src/testsuite/zr/respawnapitest.sp b/src/testsuite/zr/respawnapitest.sp new file mode 100644 index 0000000..c5192be --- /dev/null +++ b/src/testsuite/zr/respawnapitest.sp @@ -0,0 +1,132 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: respawnapi.sp + * Type: Test plugin + * Description: Tests the respawn API. + * + * Copyright (C) 2009-2010 Greyscale, Richard Helgeby + * + * This program 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. + * + * 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 . + * + * ============================================================================ + */ + +#pragma semicolon 1 +#include +#include + +public Plugin:myinfo = +{ + name = "Zombie:Reloaded Respawn API Test", + author = "Greyscale | Richard Helgeby", + description = "Tests the respawn API for ZR", + version = "1.0.0", + url = "http://code.google.com/p/zombiereloaded/" +}; + +new Handle:cvarBlockRespawn; +new Handle:cvarAllSuicide; + +public OnPluginStart() +{ + LoadTranslations("common.phrases"); + + RegConsoleCmd("zrtest_killed_by_world", KilledByWorldCommand, "Gets or sets the killed by world value. Usage: zrtest_killed_by_world [1|0]"); + RegConsoleCmd("zrtest_respawn", RespawnClientCommand, "Respawn a player. Usage: zrtest_respawn "); + + cvarBlockRespawn = CreateConVar("zrtest_block_respawn", "0", "Block respawning."); + cvarAllSuicide = CreateConVar("zrtest_all_suicide", "0", "Treat all deaths as suicide."); +} + +public Action:KilledByWorldCommand(client, argc) +{ + new target = -1; + new String:valueString[64]; + + if (argc >= 1) + { + GetCmdArg(1, valueString, sizeof(valueString)); + target = FindTarget(client, valueString); + } + + if (target <= 0) + { + ReplyToCommand(client, "Gets or sets the killed by world value. Usage: zrtest_killed_by_world [value]"); + return Plugin_Handled; + } + + if (argc > 1) + { + // Set value. + GetCmdArg(2, valueString, sizeof(valueString)); + ZR_SetKilledByWorld(target, bool:StringToInt(valueString)); + } + else + { + // Print value. + ReplyToCommand(client, "Killed by world: %d", ZR_GetKilledByWorld(target)); + } + + return Plugin_Handled; +} + +public Action:RespawnClientCommand(client, argc) +{ + new target = -1; + new String:valueString[64]; + + if (argc >= 1) + { + GetCmdArg(1, valueString, sizeof(valueString)); + target = FindTarget(client, valueString); + } + + if (target < 0) + { + ReplyToCommand(client, "Respawn a player. Usage: zrtest_respawn "); + return Plugin_Handled; + } + + ZR_RespawnClient(target, ZR_Repsawn_Default); + + return Plugin_Handled; +} + +public Action:ZR_OnClientRespawn(&client, &ZR_RespawnCondition:condition) +{ + if (GetConVarBool(cvarBlockRespawn)) + { + PrintToChatAll("Respawn blocked on client %d.", client); + return Plugin_Handled; + } + + PrintToChatAll("Client %d is about to respawn. Condition: %d", client, condition); + + if (GetConVarBool(cvarAllSuicide)) + { + // Set client suicide. + ZR_SetKilledByWorld(client, true); + PrintToChatAll("Client %d is marked as suicide victim."); + } + + return Plugin_Continue; +} + +public ZR_OnClientRespawned(client, ZR_RespawnCondition:condition) +{ + PrintToChatAll("Client %d respawned.", client); +} diff --git a/src/zombiereloaded.sp b/src/zombiereloaded.sp index b64bd90..bfa1122 100644 --- a/src/zombiereloaded.sp +++ b/src/zombiereloaded.sp @@ -113,6 +113,8 @@ #include "zr/volfeatures/volfeatures" #include "zr/debugtools" +#include "zr/api/api" + /** * Record plugin info. */ @@ -137,7 +139,8 @@ public Plugin:myinfo = */ public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { - // TODO: EXTERNAL API + // Load API. + APIInit(); // Let plugin load. return APLRes_Success; diff --git a/src/zr/api/api.inc b/src/zr/api/api.inc new file mode 100644 index 0000000..4bb4cea --- /dev/null +++ b/src/zr/api/api.inc @@ -0,0 +1,92 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: api.inc + * Type: Core + * Description: Native handlers for the ZR API. + * + * Copyright (C) 2009-2010 Greyscale, Richard Helgeby + * + * This program 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. + * + * 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 . + * + * ============================================================================ + */ + +/** + * Application Programming Interface (API) + * + * To allow other plugins or extensions to interact directly with Zombie:Reloaded we need to implement + * an API. SourceMod allows us to do this by creating global "natives" or "forwards." + * + * Natives are basically functions that can be called from any plugin that includes its definition. + * Forwards are functions that are called on a given event. (Such as OnClientPutInServer) + * ZR's API files are located in sourcemod/scripting/include/zr/category.zr.inc. We chose to create multiple + * files simply for organization. Including zr.inc will automatically include the rest of the files as well. + * + * To better understand how natives and forwards are created, go here: + * http://wiki.alliedmods.net/Creating_Natives_(SourceMod_Scripting) + * http://wiki.alliedmods.net/Function_Calling_API_(SourceMod_Scripting) + */ + +#include "zr/api/infect.api" +#include "zr/api/respawn.api" + +/** + * Initializes all main natives and forwards. + */ +APIInit() +{ + // Forward event to sub-modules. + APIInfectInit(); + APIRespawnInit(); +} + +/** + * Validates a client index and when it fails, an error is thrown. + * + * @param client The client index to validate. + * @param alive Set to true to validate that the client is alive, false to ignore. + * + * @error Throws an error when the client isn't valid. + */ +stock APIValidateClientIndex(client, EligibleCondition:alive = Condition_Either) +{ + // Verify client index. + if (client < 1 || client > MaxClients) + { + ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index. (%d)", client); + } + + // Verify that the client is connected. + if (!IsClientConnected(client)) + { + ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not connected.", client); + } + + // Check if the player must be dead or alive. + new bool:bAlive = bool:alive; + if (alive != Condition_Either) + { + if (bAlive && !IsPlayerAlive(client)) + { + ThrowNativeError(SP_ERROR_NATIVE, "Client %d must be alive.", client); + } + else if (!bAlive && IsPlayerAlive(client)) + { + ThrowNativeError(SP_ERROR_NATIVE, "Client %d must be dead.", client); + } + } +} diff --git a/src/zr/api/infect.api.inc b/src/zr/api/infect.api.inc new file mode 100644 index 0000000..8c86470 --- /dev/null +++ b/src/zr/api/infect.api.inc @@ -0,0 +1,229 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: infect.api.inc + * Type: Core + * Description: Native handlers for the ZR API. (Infect module) + * + * Copyright (C) 2009-2010 Greyscale, Richard Helgeby + * + * This program 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. + * + * 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 . + * + * ============================================================================ + */ + +/** + * @section Global forward handles. + */ +new Handle:g_hAPIFwdOnClientInfect = INVALID_HANDLE; +new Handle:g_hAPIFwdOnClientInfected = INVALID_HANDLE; +new Handle:g_hAPIFwdOnClientHuman = INVALID_HANDLE; +new Handle:g_hAPIFwdOnClientHumanPost = INVALID_HANDLE; +/** + * @endsection + */ + +/** + * Initializes all natives and forwards related to infection. + */ +APIInfectInit() +{ + // Infect module natives/forwards (infect.zr.inc) + + // Natives + CreateNative("ZR_IsClientZombie", APIIsClientZombie); + CreateNative("ZR_IsClientHuman", APIIsClientHuman); + CreateNative("ZR_InfectClient", APIInfectClient); + CreateNative("ZR_HumanClient", APIHumanClient); + + // Forwards + g_hAPIFwdOnClientInfect = CreateGlobalForward("ZR_OnClientInfect", ET_Hook, Param_CellByRef, Param_CellByRef, Param_CellByRef, Param_CellByRef, Param_CellByRef); + g_hAPIFwdOnClientInfected = CreateGlobalForward("ZR_OnClientInfected", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + g_hAPIFwdOnClientHuman = CreateGlobalForward("ZR_OnClientHuman", ET_Hook, Param_CellByRef, Param_CellByRef, Param_CellByRef); + g_hAPIFwdOnClientHumanPost = CreateGlobalForward("ZR_OnClientHumanPost", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); +} + +/** + * Native call function (ZR_IsClientInfected) + * Returns true if the client is a zombie, false if not. + */ +public APIIsClientZombie(Handle:plugin, numParams) +{ + new client = GetNativeCell(1); + + // Validate the client index. + APIValidateClientIndex(client, Condition_True); + + return InfectIsClientInfected(client); +} + +/** + * Native call function (ZR_IsClientHuman) + * Returns true if the client is a human, false if not. + * + * bool:InfectIsClientHuman(client) + */ +public APIIsClientHuman(Handle:plugin, numParams) +{ + new client = GetNativeCell(1); + + // Validate the client index. + APIValidateClientIndex(client, Condition_True); + + return InfectIsClientHuman(client); +} + +/** + * Native call function (ZR_InfectClient) + * Infects a client. + * + * native ZR_InfectClient(client, attacker = -1, bool:motherInfect = false, bool:respawnOverride = false, bool:respawn = false); + */ +public APIInfectClient(Handle:plugin, numParams) +{ + new client = GetNativeCell(1); + new attacker = GetNativeCell(2); + new bool:motherInfect = bool:GetNativeCell(3); + new bool:respawnOverride = bool:GetNativeCell(4); + new bool:respawn = bool:GetNativeCell(5); + + // Validate the client index. + APIValidateClientIndex(client, Condition_True); + + InfectHumanToZombie(client, attacker, motherInfect, respawnOverride, respawn); +} + +/** + * Native call function (ZR_HumanClient) + * Turns a zombie back into a human. + * + * native ZR_HumanClient(client, bool:respawn = false, bool:protect = false); + */ +public APIHumanClient(Handle:plugin, numParams) +{ + new client = GetNativeCell(1); + new bool:respawn = bool:GetNativeCell(2); + new bool:protect = bool:GetNativeCell(2); + + // Validate the client index. + APIValidateClientIndex(client, Condition_True); + + InfectZombieToHuman(client, respawn, protect); +} + +/** + * Called when a client is about to become a zombie. + * + * @param client The client to infect. + * @param attacker The attacker who did the infect. + * @param motherinfect Indicates a mother zombie infect. + * @param respawnoverride Set to true to override respawn cvar. + * @param respawn Value to override with. + * + * InfectHumanToZombie(client, attacker = -1, bool:motherinfect = false, bool:respawnoverride = false, bool:respawn = false) + */ +Action:APIOnClientInfect(&client, &attacker, &bool:motherinfect, &bool:respawnoverride, &bool:respawn) +{ + // Start forward call. + Call_StartForward(g_hAPIFwdOnClientInfect); + + // Push the parameters. + Call_PushCellRef(client); + Call_PushCellRef(attacker); + Call_PushCellRef(motherinfect); + Call_PushCellRef(respawnoverride); + Call_PushCellRef(respawn); + + // Get what they returned. + new Action:result; + Call_Finish(result); + return result; +} + +/** + * Called after a client has become a zombie. + * + * @param client The client to infect. + * @param attacker The attacker who did the infect. + * @param motherinfect Indicates a mother zombie infect. + * @param respawnoverride Set to true to override respawn cvar. + * @param respawn Value to override with. + * + * InfectHumanToZombie(client, attacker = -1, bool:motherinfect = false, bool:respawnoverride = false, bool:respawn = false) + */ +APIOnClientInfected(client, attacker, bool:motherinfect, bool:respawnoverride, bool:respawn) +{ + // Start forward call. + Call_StartForward(g_hAPIFwdOnClientInfected); + + // Push the parameters. + Call_PushCell(client); + Call_PushCell(attacker); + Call_PushCell(motherinfect); + Call_PushCell(respawnoverride); + Call_PushCell(respawn); + + // Finish the call. + Call_Finish(); +} + +/** + * Called when a client is about to become a human. (Through either zr_human or admin menu) + * + * @param client The client index. + * @param respawn True if the client was respawned, false if not. + * @param protect True if the client spawn protected, false if not. + * + * InfectZombieToHuman(client, bool:respawn = false, bool:protect = false) + */ +Action:APIOnClientHuman(&client, &bool:respawn, &bool:protect) +{ + // Start forward call. + Call_StartForward(g_hAPIFwdOnClientHuman); + + // Push the parameters. + Call_PushCellRef(client); + Call_PushCellRef(respawn); + Call_PushCellRef(protect); + + // Get what they returned. + new Action:result; + Call_Finish(result); + return result; +} + +/** + * Called after a client has become a human. (Through either zr_human or admin menu) + * + * @param client The client index. + * @param respawn True if the client was respawned, false if not. + * @param protect True if the client spawn protected, false if not. + * + * InfectZombieToHuman(client, bool:respawn = false, bool:protect = false) + */ +APIOnClientHumanPost(client, bool:respawn, bool:protect) +{ + // Start forward call. + Call_StartForward(g_hAPIFwdOnClientHumanPost); + + // Push the parameters. + Call_PushCell(client); + Call_PushCell(respawn); + Call_PushCell(protect); + + // Finish the call. + Call_Finish(); +} diff --git a/src/zr/api/respawn.api.inc b/src/zr/api/respawn.api.inc new file mode 100644 index 0000000..8bcdeed --- /dev/null +++ b/src/zr/api/respawn.api.inc @@ -0,0 +1,149 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: respawn.api.inc + * Type: Core + * Description: Native handlers for the ZR API. (Respawn module) + * + * Copyright (C) 2009-2010 Greyscale, Richard Helgeby + * + * This program 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. + * + * 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 . + * + * ============================================================================ + */ + +/** + * @section Global forward handles. + */ +new Handle:g_hAPIFwdOnClientRespawn = INVALID_HANDLE; +new Handle:g_hAPIFwdOnClientRespawned = INVALID_HANDLE; +/** + * @endsection + */ + +/** + * Initializes all natives and forwards related to respawn. + */ +APIRespawnInit() +{ + // Respawn module natives/forwards (respawn.zr.inc) + + // Natives + CreateNative("ZR_RespawnClient", APIRespawnClient); + CreateNative("ZR_SetKilledByWorld", APISetKilledByWorld); + CreateNative("ZR_GetKilledByWorld", APIGetKilledByWorld); + + // Forwards + g_hAPIFwdOnClientRespawn = CreateGlobalForward("ZR_OnClientRespawn", ET_Hook, Param_CellByRef, Param_CellByRef); + g_hAPIFwdOnClientRespawned = CreateGlobalForward("ZR_OnClientRespawned", ET_Ignore, Param_Cell, Param_Cell); +} + +/** + * Native call function (ZR_RespawnClient) + * Spawns a player into the round following rules set by cvars. + * + * RespawnSpawnClient(client, bool:zombie = false, bool:zombie_if_suicide = false) + */ +public APIRespawnClient(Handle:plugin, numParams) +{ + new client = GetNativeCell(1); + + // Validate index and that player isn't alive. + APIValidateClientIndex(client, Condition_False); + + // Restore respawn condition. + new RespawnCondition:condition = RespawnCondition:GetNativeCell(2); + new bool:zombie; + new bool:zombieIfSuicide; + RespawnRestoreCondition(condition, zombie, zombieIfSuicide); + + // Respawn the client. + RespawnSpawnClient(client, zombie, zombieIfSuicide); +} + +/** + * Called right before ZR is about to respawn a player. + * + * @param client The client index. + * @param condition Respawn condition. See RespawnCondition for + * details. + */ +Action:APIOnClientRespawn(&client, &RespawnCondition:condition) +{ + // Start forward call. + Call_StartForward(g_hAPIFwdOnClientRespawn); + + // Push the parameters. + Call_PushCellRef(client); + Call_PushCellRef(condition); + + // Get what they returned. + new Action:result; + Call_Finish(result); + return result; +} + +/** + * Called after a player was respawned. + * + * @param client The client index. + * @param condition Current condition of the respawned player. See + * RespawnCondition for details. + */ +Action:APIOnClientRespawned(client, RespawnCondition:condition) +{ + // Start forward call. + Call_StartForward(g_hAPIFwdOnClientRespawned); + + // Push the parameters. + Call_PushCell(client); + Call_PushCell(condition); + + // Finish the call. + Call_Finish(); +} + +/** + * Native call function (ZR_SetKilledByWorld) + * Override if the client died by a suicide. + */ +public APISetKilledByWorld(Handle:plugin, numParams) +{ + new client = GetNativeCell(1); + + // Validate the client index. + APIValidateClientIndex(client, Condition_Either); + + new bool:suicide = bool:GetNativeCell(2); + + // Override the old value. + bKilledByWorld[client] = suicide; +} + +/** + * Native call function (ZR_GetKilledByWorld) + * Read the value of if the client died by a suicide. + */ +public APIGetKilledByWorld(Handle:plugin, numParams) +{ + new client = GetNativeCell(1); + + // Validate the client index. + APIValidateClientIndex(client, Condition_Either); + + // Return the value. + return _:bKilledByWorld[client]; +} diff --git a/src/zr/infect.inc b/src/zr/infect.inc index 06df5e8..ee2732b 100644 --- a/src/zr/infect.inc +++ b/src/zr/infect.inc @@ -563,6 +563,15 @@ public Action:InfectMotherZombie(Handle:timer) */ InfectHumanToZombie(client, attacker = -1, bool:motherinfect = false, bool:respawnoverride = false, bool:respawn = false) { + // Forward pre-event to modules. + new Action:result = APIOnClientInfect(client, attacker, motherinfect, respawnoverride, respawn); + + // Check if infection should be blocked. + if (result == Plugin_Handled) + { + return; + } + // Mark player as zombie. bZombie[client] = true; @@ -650,6 +659,7 @@ InfectHumanToZombie(client, attacker = -1, bool:motherinfect = false, bool:respa SEffectsOnClientInfected(client); ZTeleOnClientInfected(client); ZHPOnClientInfected(client); + APIOnClientInfected(client, attacker, motherinfect, respawnoverride, respawn); } /** @@ -662,6 +672,15 @@ InfectHumanToZombie(client, attacker = -1, bool:motherinfect = false, bool:respa */ InfectZombieToHuman(client, bool:respawn = false, bool:protect = false) { + // Forward pre-event to modules. + new Action:result = APIOnClientHuman(client, respawn, protect); + + // Check if action should be blocked. + if (result == Plugin_Handled) + { + return; + } + // Mark player as human. bZombie[client] = false; @@ -702,6 +721,7 @@ InfectZombieToHuman(client, bool:respawn = false, bool:protect = false) // Forward event to modules. SEffectsOnClientHuman(client); + APIOnClientHumanPost(client, respawn, protect); } /** diff --git a/src/zr/respawn.inc b/src/zr/respawn.inc index 2c67ab2..833be31 100644 --- a/src/zr/respawn.inc +++ b/src/zr/respawn.inc @@ -25,6 +25,17 @@ * ============================================================================ */ +/** + * Conditions for respawning players. + */ +enum RespawnCondition +{ + Repsawn_Default = -1, /** Let ZR decide according to its settings. */ + Respawn_Human = 0, /** Respawn as a human. */ + Respawn_Zombie, /** Respawn as a zombie. */ + Respawn_ZombieIfSuicide /** Respawn as a zombie if killed by world damage. */ +} + /** * Array for storing respawn timer handles per client. */ @@ -133,37 +144,59 @@ RespawnOnRoundEnd() /** * Spawns a player into the round. * - * @param client The client index. + * @param client The client index. + * @param zombie Respawn as zombie. + * @param zombieIfSuicide Respawn as zombie if killed by world damage. + * + * @return True if the player was spawned, false otherwise. */ -RespawnSpawnClient(client, bool:zombie = false) +bool:RespawnSpawnClient(client, bool:zombie = false, bool:zombieIfSuicide = false) { // If client isn't in-game, then stop. if (!IsClientInGame(client)) { - return; + return false; } + // Get respawn condition. + //new bool:zombieIfSuicide = GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE_WORLD]); + new RespawnCondition:condition = RespawnToContition(zombie, zombieIfSuicide); + + // Trigger API forward. + new Action:result = APIOnClientRespawn(client, condition); + + // Check if respawn should be stopped. + if (result == Plugin_Handled) + { + return false; + } + + // Restore respawn condition. + RespawnRestoreCondition(condition, zombie, zombieIfSuicide); + // Spawn player. CS_RespawnPlayer(client); - // Stop here if the first zombie hasn't spawned yet. - if (!g_bZombieSpawned) + // Check if first zombie has spawned. + if (g_bZombieSpawned) { - return; + // Infect if player should spawn as zombie. + if (zombie) + { + InfectHumanToZombie(client); + } + // Infect if player committed suicide by world damage. + else if (zombieIfSuicide && bKilledByWorld[client]) + { + InfectHumanToZombie(client); + bKilledByWorld[client] = false; + } } - // Infect if zombie is true. - if (zombie) - { - InfectHumanToZombie(client); - return; - } + // Forward event to modules. + APIOnClientRespawned(client, condition); - if (GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE_WORLD]) && bKilledByWorld[client]) - { - InfectHumanToZombie(client); - bKilledByWorld[client] = false; - } + return true; } /** @@ -183,7 +216,7 @@ public Action:RespawnTimer(Handle:timer, any:client) return; } - // If player isn't alive, then stop. + // If player already is alive, then stop. if (IsPlayerAlive(client)) { return; @@ -202,5 +235,52 @@ public Action:RespawnTimer(Handle:timer, any:client) new bool:respawn_zombie = GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE]); // Spawn player. - RespawnSpawnClient(client, respawn_zombie); + RespawnSpawnClient(client, respawn_zombie, true); +} + +/** + * Converts separate conditions into a single condition value. + */ +RespawnCondition:RespawnToContition(bool:zombie, bool:zombieIfSuicide) +{ + if (zombieIfSuicide) + { + return Respawn_ZombieIfSuicide; + } + else if (zombie) + { + return Respawn_Zombie; + } + + return Respawn_Human; +} + +/** + * Restores respawn condition to individual variables. If the condition invalid, + * nothing will be changed. + * + * @param condition Condition to restore. + * @param zombie Output. + * @param zombieIfSucidie Output. + */ +RespawnRestoreCondition(RespawnCondition:condition, &bool:zombie, &bool:zombieIfSuicide) +{ + switch (condition) + { + case Respawn_Human: + { + zombie = false; + zombieIfSuicide = false; + } + case Respawn_Zombie: + { + zombie = true; + zombieIfSuicide = false; + } + case Respawn_ZombieIfSuicide: + { + zombie = false; + zombieIfSuicide = true; + } + } } diff --git a/src/zr/zombiereloaded.inc b/src/zr/zombiereloaded.inc index 25f603e..4c16e0b 100644 --- a/src/zr/zombiereloaded.inc +++ b/src/zr/zombiereloaded.inc @@ -39,6 +39,16 @@ * @endsection */ +/** + * Options that a condition must pass to be eligible. + */ +enum EligibleCondition +{ + Condition_False = 0, /** Condition must be false. */ + Condition_True = 1, /** Condition must be true. */ + Condition_Either = -1 /** Condition can be either true or false. */ +} + /** * Global variable set to true when the first zombie(s) is/are spawned. */ diff --git a/src/zr/zspawn.inc b/src/zr/zspawn.inc index c6e9fa0..ed11d21 100644 --- a/src/zr/zspawn.inc +++ b/src/zr/zspawn.inc @@ -263,9 +263,7 @@ bool:ZSpawnClient(client, bool:force = false, bool:zombie = false) } // Tell respawn module to respawn client. - RespawnSpawnClient(client, teamzombie); - - return true; + return RespawnSpawnClient(client, teamzombie, false); } /**