/* AMX Mod X * Sven Co-op Module * * by the AMX Mod X Development Team * * This file is part of AMX Mod X. * * * 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 2 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, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, the author gives permission to * link the code of this program with the Half-Life Game Engine ("HL * Engine") and Modified Game Libraries ("MODs") developed by Valve, * L.L.C ("Valve"). You must obey the GNU General Public License in all * respects for all of the code used other than the HL Engine and MODs * from Valve. If you modify this file, you may extend this exception * to your version of the file, but you are not obligated to do so. If * you do not wish to do so, delete this exception statement from your * version. */ #include #include #include "amxxmodule.h" #include "CString.h" #include "Trie.h" // right now there is no Linux Sven Co-op, but for the future... #if defined __linux__ #define EXTRAOFFSET_MONSTER 0 #define EXTRAOFFSET_WEAPON 0 #define EXTRAOFFSET_WBOX 0 #define EXTRAOFFSET_PLAYER 0 #else #define EXTRAOFFSET_MONSTER 0 #define EXTRAOFFSET_WEAPON 0 #define EXTRAOFFSET_WBOX 0 #define EXTRAOFFSET_PLAYER 0 #endif // defined __linux__ // 32-bit #if !defined __amd64__ #define OFFSET_LAST_HEALTH 834 // arbitrary, our own storage // monster offsets #define OFFSET_MONSTER_FRAGS 9 + EXTRAOFFSET_MONSTER #define OFFSET_MONSTER_ALLY 10 + EXTRAOFFSET_MONSTER // player offsets (non-ammo) #define OFFSET_PLAYER_DEATHS 8624 + EXTRAOFFSET_PLAYER // weapon offsets #define OFFSET_WEAPON_TYPE 8224 + EXTRAOFFSET_WEAPON #define OFFSET_WEAPON_CLIP 8233 + EXTRAOFFSET_WBOX #define OFFSET_WBOX_AMMO 8255 + EXTRAOFFSET_WBOX // ammo offsets #define OFFSET_357_AMMO 8563 + EXTRAOFFSET_PLAYER #define OFFSET_9MM_AMMO 8557 + EXTRAOFFSET_PLAYER #define OFFSET_CROSSBOW_AMMO 8566 + EXTRAOFFSET_PLAYER #define OFFSET_SHOTGUN_AMMO 8558 + EXTRAOFFSET_PLAYER #define OFFSET_RPG_AMMO 8565 + EXTRAOFFSET_PLAYER #define OFFSET_ENERGY_AMMO 8564 + EXTRAOFFSET_PLAYER #define OFFSET_HORNETGUN_AMMO 8571 + EXTRAOFFSET_PLAYER #define OFFSET_HANDGRENADE_AMMO 8569 + EXTRAOFFSET_PLAYER #define OFFSET_TRIPMINE_AMMO 8567 + EXTRAOFFSET_PLAYER #define OFFSET_SATCHEL_AMMO 8568 + EXTRAOFFSET_PLAYER #define OFFSET_SNARK_AMMO 8570 + EXTRAOFFSET_PLAYER #define OFFSET_MEDKIT_AMMO 8559 + EXTRAOFFSET_PLAYER #define OFFSET_MINIGUN_AMMO 8560 + EXTRAOFFSET_PLAYER #define OFFSET_SNIPERRIFLE_AMMO 8561 + EXTRAOFFSET_PLAYER #define OFFSET_ARGRENADE_AMMO 8562 + EXTRAOFFSET_PLAYER // 64-bit (no amd64 Sven Co-op, but thinking ahead) #else #define OFFSET_OLD_HEALTH 834 // monster offsets #define OFFSET_MONSTER_FRAGS 9 + EXTRAOFFSET_MONSTER #define OFFSET_MONSTER_ALLY 10 + EXTRAOFFSET_MONSTER // player offsets (non-ammo) #define OFFSET_PLAYER_DEATHS 8624 + EXTRAOFFSET_PLAYER // weapon offsets #define OFFSET_WEAPON_TYPE 8224 + EXTRAOFFSET_WEAPON #define OFFSET_WEAPON_CLIP 8233 + EXTRAOFFSET_WBOX #define OFFSET_WBOX_AMMO 8255 + EXTRAOFFSET_WBOX // ammo offsets #define OFFSET_357_AMMO 8563 + EXTRAOFFSET_PLAYER #define OFFSET_9MM_AMMO 8557 + EXTRAOFFSET_PLAYER #define OFFSET_CROSSBOW_AMMO 8566 + EXTRAOFFSET_PLAYER #define OFFSET_SHOTGUN_AMMO 8558 + EXTRAOFFSET_PLAYER #define OFFSET_RPG_AMMO 8565 + EXTRAOFFSET_PLAYER #define OFFSET_ENERGY_AMMO 8564 + EXTRAOFFSET_PLAYER #define OFFSET_HORNETGUN_AMMO 8571 + EXTRAOFFSET_PLAYER #define OFFSET_HANDGRENADE_AMMO 8569 + EXTRAOFFSET_PLAYER #define OFFSET_TRIPMINE_AMMO 8567 + EXTRAOFFSET_PLAYER #define OFFSET_SATCHEL_AMMO 8568 + EXTRAOFFSET_PLAYER #define OFFSET_SNARK_AMMO 8570 + EXTRAOFFSET_PLAYER #define OFFSET_MEDKIT_AMMO 8559 + EXTRAOFFSET_PLAYER #define OFFSET_MINIGUN_AMMO 8560 + EXTRAOFFSET_PLAYER #define OFFSET_SNIPERRIFLE_AMMO 8561 + EXTRAOFFSET_PLAYER #define OFFSET_ARGRENADE_AMMO 8562 + EXTRAOFFSET_PLAYER #endif // weapon ids enum { SCW_CROWBAR = 1, SCW_9MMHANDGUN = 2, SCW_357 = 3, SCW_9MMAR = 4, SCW_CROSSBOW = 6, SCW_SHOTGUN = 7, SCW_RPG = 8, SCW_GAUSS = 9, SCW_EGON = 10, SCW_HORNETGUN = 11, SCW_HANDGRENADE = 12, SCW_TRIPMINE = 13, SCW_SATCHEL = 14, SCW_SNARK = 15, SCW_UZIAKIMBO = 16, SCW_UZI = 17, SCW_MEDKIT = 18, SCW_CROWBAR_ELECTRIC = 19, SCW_PIPEWRENCH = 20, SCW_MINIGUN = 21, SCW_GRAPPLE = 22, SCW_SNIPERRIFLE = 23, SCW_ARGRENADE = 24 }; // // externs // extern AMX_NATIVE_INFO svencoop_Exports[]; extern int gmsgScoreInfo; extern KeyValueData g_kvd; extern Trie g_allyNameTrie, g_enemyNameTrie; // // inline functions // inline bool UTIL_IsPlayer(edict_t *pPlayer) { if(strcmp(STRING(pPlayer->v.classname), "player") == 0) return true; return false; } inline bool UTIL_IsMonster(edict_t *pMonster) { if(strncmp(STRING(pMonster->v.classname), "monster_", 8) == 0) return true; return false; } // // entity checking defines // #define CHECK_ENTITY(x) \ if (x <= 0 || x > gpGlobals->maxEntities) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Entity out of range (%d)", x); \ return 0; \ } else { \ if (x <= gpGlobals->maxClients) { \ if (!MF_IsPlayerIngame(x)) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Invalid player %d (not in-game)", x); \ return 0; \ } \ } else { \ if (x != 0 && FNullEnt(INDEXENT(x))) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Invalid entity %d", x); \ return 0; \ } \ } \ } #define CHECK_PLAYER(x) \ if (x < 1 || x > gpGlobals->maxClients) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Player out of range (%d)", x); \ return 0; \ } else { \ if (!MF_IsPlayerIngame(x) || FNullEnt(MF_GetPlayerEdict(x))) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Invalid player %d", x); \ return 0; \ } \ } #define CHECK_NONPLAYER(x) \ if (x < 1 || x <= gpGlobals->maxClients || x > gpGlobals->maxEntities) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Non-player entity %d out of range", x); \ return 0; \ } else { \ if (FNullEnt(INDEXENT(x))) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Invalid non-player entity %d", x); \ return 0; \ } \ } #define CHECK_MONSTER(x) \ if (x < 1 || x <= gpGlobals->maxClients || x > gpGlobals->maxEntities) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Monster entity %d out of range", x); \ return 0; \ } else { \ if (FNullEnt(INDEXENT(x))) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Invalid monster entity %d", x); \ return 0; \ } else { \ if(strncmp(STRING(GETEDICT(x)->v.classname),"monster_",8) != 0) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Entity %d (\"%s\") is not a monster_* entity", x, STRING(GETEDICT(x)->v.classname)); \ return 0; \ } \ } \ } #define GETEDICT(n) \ ((n >= 1 && n <= gpGlobals->maxClients) ? MF_GetPlayerEdict(n) : INDEXENT(n))