mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-27 07:15:37 +03:00
240 lines
7.6 KiB
C
240 lines
7.6 KiB
C
|
/* 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 <extdll.h>
|
||
|
#include <meta_api.h>
|
||
|
#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<char,String> 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))
|
||
|
|