/* AMX Mod X * Natural Selection 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. */ /* This is the basic data stored for players */ #ifndef CPLAYER_H #define CPLAYER_H #include #include "GameManager.h" class CPlayer { private: edict_t *m_pEdict; entvars_t *m_pev; int m_iIndex; int m_iIsBot; int m_iIsConnected; int m_iOldTeam; int m_iOldImpulse; int m_iOldDeadFlag; int m_iSpeedChange; REAL m_fMaxSpeed; int m_iClass; int m_iHasCustomModel; int m_iHasCustomSkin; int m_iHasCustomBody; char m_szModel[128]; int m_iSkin; int m_iBody; int m_iHasFOV; REAL m_fFOV; int m_iInitialized; public: CPlayer() { memset(this,0x0,sizeof(*this)); } inline void SetEdict(edict_t *Ent) { m_pEdict=Ent; m_pev=&(Ent->v); m_iIndex=ENTINDEX_NEW(Ent); }; inline edict_t *GetEdict(void) { return m_pEdict; }; inline entvars_t *GetPev(void) { return m_pev; }; inline int IsBot(void) { return m_iIsBot; }; inline void SetBot(int onoff) { m_iIsBot=onoff; }; inline int IsConnected(void) { return m_iIsConnected; }; inline BOOL HasPrivateData(void) { if (m_pEdict && m_pEdict->pvPrivateData != NULL) { return TRUE; } return FALSE; }; inline int IsInitialized() { return m_iInitialized; }; inline void Initialize() { if (!IsConnected()) { // This usually means it's a bot... // So just emulate connections Connect(); SetBot(1); } m_iInitialized=1; }; inline void PreThink() { if (!IsInitialized()) { Initialize(); } if (m_iOldTeam != m_pev->team) { GameMan.ExecuteClientChangeTeam(index(),m_pev->team,m_iOldTeam); } if (m_iOldDeadFlag && m_pev->deadflag == 0) { GameMan.ExecuteClientSpawn(index()); } int tClass = GetClass(); if (tClass != m_iClass) { ChangeClass(tClass); } m_iOldImpulse=m_pev->impulse; m_iOldDeadFlag=m_pev->deadflag; m_iOldTeam=m_pev->team; }; inline void PreThink_Post() { // Trying to incorperate this into PostThink_Post led to really *weird* results (i don't think it was propagated to the client properly). // Change the users speed here m_fMaxSpeed=m_pev->maxspeed; m_pev->maxspeed+=m_iSpeedChange; }; /** * This is only hooked if at least 1 * player has custom skins/models/bodies */ inline void PostThink_Post() { if (m_iHasCustomModel) { SET_MODEL(m_pEdict,m_szModel); } if (m_iHasCustomSkin) { m_pev->skin=m_iSkin; } if (m_iHasCustomBody) { m_pev->body=m_iBody; } }; void ChangeClass(int newclass) { GameMan.ExecuteClientChangeClass(index(), newclass, m_iClass); m_iClass=newclass; } void Connect() { m_iIsConnected=1; m_iIsBot=0; Reset(); } void Disconnect(int scanhooks=0) { // If this client had any hooks upon disconnect // then rescan the hooks to see if we can stop // intercepting any of them. if (scanhooks!=0) { if (this->NeedPreThink_Post()) { GameMan.HookPreThink_Post(); } if (this->NeedPostThink_Post()) { GameMan.HookPostThink_Post(); } if (this->NeedUpdateClientData()) { GameMan.HookUpdateClientData(); } } m_iIsConnected=0; m_iIsBot=0; Reset(); } void FullReset() { memset(this,0x0,sizeof(*this)); }; void Reset() { m_iHasCustomModel=0; m_iHasCustomSkin=0; m_iHasCustomBody=0; m_iOldTeam=0; m_iOldDeadFlag=0; m_iSpeedChange=0; m_iClass=0; }; int GetClass() { if (m_pev->deadflag) { return CLASS_DEAD; } if (!m_pev->team) { return CLASS_NOTEAM; } switch (m_pev->iuser3) { case 1: // Light armor marine.. if (m_pev->iuser4 & MASK_HEAVYARMOR) { return CLASS_HEAVY; } if (m_pev->iuser4 & MASK_JETPACK) { return CLASS_JETPACK; } return CLASS_MARINE; case 2: return CLASS_COMMANDER; case 3: return CLASS_SKULK; case 4: return CLASS_GORGE; case 5: return CLASS_LERK; case 6: return CLASS_FADE; case 7: return CLASS_ONOS; case 8: return CLASS_GESTATE; } return CLASS_UNKNOWN; }; inline int &index() { return m_iIndex; }; inline int &GetSpeedChange(void) { return m_iSpeedChange; }; inline int GetMaxSpeed(void) { return (int)m_fMaxSpeed; }; inline void SetSpeedChange(cell &SpeedChange) { m_iSpeedChange=SpeedChange; }; inline void SetModel(char *Model) { if (strcmp(Model,"")!=0) { PRECACHE_MODEL(Model); strncpy(m_szModel,Model,sizeof(m_szModel)-1); m_iHasCustomModel=1; } else { m_iHasCustomModel=0; } }; inline void SetSkin(cell &skin) { if (skin<0) { m_iHasCustomSkin=0; return; } m_iHasCustomSkin=1; m_iSkin=skin; }; inline void SetBody(cell &body) { if (body<0) { m_iHasCustomBody=0; return; } m_iHasCustomBody=1; m_iBody=body; }; /** * Called during pfnUpdateClientData() * Sets the player's FOV continuously */ inline void UpdateFOV(void) { if (m_iHasFOV) { GetPev()->fov=m_fFOV; } }; /** * Called from the native directly. * Changes members, and gets the SetFOV * message id if needed. */ inline int SetFOV(REAL &Amount) { GameMan.UpdateSetFOV(); if (Amount == 0.0) { m_iHasFOV=0; m_fFOV=0.0; MESSAGE_BEGIN(MSG_ONE,GameMan.GetSetFOV(),NULL,GetEdict()); WRITE_BYTE(0); MESSAGE_END(); return 1; } if (Amount > 0) { m_iHasFOV=1; m_fFOV=Amount; MESSAGE_BEGIN(MSG_ONE,GameMan.GetSetFOV(),NULL,GetEdict()); WRITE_BYTE((int)Amount); MESSAGE_END(); return 1; } return 0; }; /** * Returns 1 if this entity needs PreThink_Post hooked * (eg: this entity has custom max speeds) */ inline int NeedPreThink_Post(void) { return m_iSpeedChange != 0; }; /** * Returns 1 if this entity needs PostThink_Post * eg: This entity has a custom model/skin/body */ inline int NeedPostThink_Post(void) { return (m_iHasCustomModel != 0 || m_iHasCustomSkin != 0 || m_iHasCustomBody != 0); }; /** * Returns 1 if this entity needs UpdateClientData * eg: This entity has a custom FOV set */ inline int NeedUpdateClientData(void) { return m_iHasFOV != 0; }; }; #endif