//----------------------------------------------------------------------------- // Copyright(c), HL Rally: Source, 2004, All rights reserved. // The contents of this file may only be used / distributed in accordance // with the conditions listed in the supplied license, or with written // permission of the respective authors listed. //----------------------------------------------------------------------------- // Includes #include "cbase.h" #include "EntityInfoCheckpoint.h" #include "CheckpointManagerABC.h" int CEntityInfoCheckpoint::ms_iTotalCheckpoints = 0; LINK_ENTITY_TO_CLASS(info_rally_checkpoint, CEntityInfoCheckpoint); // Data descriptor BEGIN_DATADESC(CEntityInfoCheckpoint) DEFINE_KEYFIELD(m_iTouchOrder, FIELD_INTEGER, "touchorder"), DEFINE_KEYFIELD(m_iTimeExtension, FIELD_INTEGER, "timeextension"), DEFINE_KEYFIELD(m_iTimeExtensionReverse, FIELD_INTEGER, "timeextensionreverse"), DEFINE_FUNCTION(StartTouch), END_DATADESC() /** * Returns the player index of a player * * @todo Remove this - Valve must have made some way of doing this easilly */ inline int getPlayerIndex(CPlayerRally *pl) { for(int i = 0; i <= MAX_PLAYERS; i++ ) { if(pl == (CPlayerRally *)UTIL_PlayerByIndex(i)) return i; } return -1; } /** * Constructor */ CEntityInfoCheckpoint::CEntityInfoCheckpoint() { m_iTimeExtension = 10; Reset(); } /** * Destructor */ CEntityInfoCheckpoint::~CEntityInfoCheckpoint() { } /** * Resets the entitys touch information */ void CEntityInfoCheckpoint::Reset() { memset(m_vecTouchInfo, 0, sizeof(m_vecTouchInfo)); } /** * Precache resources */ void CEntityInfoCheckpoint::Precache() { PrecacheScriptSound("HLRally.CheckpointCorrect"); PrecacheScriptSound("HLRally.CheckpointWrong"); } /** * Spawns the entity */ void CEntityInfoCheckpoint::Spawn() { Precache(); SetMoveType(MOVETYPE_NONE); SetModel(STRING(GetModelName())); // set size and link into world AddEffects(EF_NODRAW); SetSolid(SOLID_BSP); AddSolidFlags(FSOLID_NOT_SOLID); AddSolidFlags(FSOLID_TRIGGER); // Increment total number of checkpoints ms_iTotalCheckpoints++; BaseClass::Spawn(); } /** * As a player passes through the checkpoint, StartTouch is invoked * once when the player starts to touch the checkpoint entity. */ void CEntityInfoCheckpoint::StartTouch(CBaseEntity *pOther) { if(!pOther->IsPlayer()) return; CPlayerRally *pPlayer = (CPlayerRally *)pOther; int iPlayerIdx = getPlayerIndex(pPlayer); DevMsg("Touched checkpoint %i\n", m_iTouchOrder); // If the player has already touched this checkpoint if(m_vecTouchInfo[0][iPlayerIdx].m_bTouchedThisLap) { CEntityInfoCheckpoint *pNextEnt = CCheckpointManagerABC::GetInstance()->GetCheckpointAfterTouchOrder(m_iTouchOrder); if(pNextEnt && pNextEnt->m_vecTouchInfo[0][iPlayerIdx].m_bTouchedThisLap) CCheckpointManagerABC::GetInstance()->CheckpointTouchWrong(this, pPlayer); return; } CEntityInfoCheckpoint *pBefore = CCheckpointManagerABC::GetInstance()->GetCheckpointBeforeTouchOrder(m_iTouchOrder); // If the player hasn't touched the previous checkpoint if(pBefore && !pBefore->m_vecTouchInfo[0][iPlayerIdx].m_bTouchedThisLap) { CCheckpointManagerABC::GetInstance()->CheckpointTouchWrong(this, pPlayer); return; } // Was the correct checkpoint CCheckpointManagerABC::GetInstance()->CheckpointTouchCorrect(this, pPlayer); bool bIsFirstTouch = true; bool bIsLastTouch = true; for(int i = 1; i <= gpGlobals->maxClients; i++) { if(UTIL_PlayerByIndex(i)) { if(m_vecTouchInfo[0][iPlayerIdx].m_bTouchedThisLap) bIsFirstTouch = false; if(iPlayerIdx != i && !m_vecTouchInfo[0][iPlayerIdx].m_bTouchedThisLap) bIsLastTouch = false; } } if(bIsFirstTouch) CCheckpointManagerABC::GetInstance()->CheckpointTouchFirstPlayerThrough(this, pPlayer); if(bIsLastTouch) CCheckpointManagerABC::GetInstance()->CheckpointTouchLastPlayerThrough(this, pPlayer); // Player with index iPlayerIdx has touched in lap xxx m_vecTouchInfo[0][iPlayerIdx].m_bTouchedThisLap = true; if(this == CCheckpointManagerABC::GetInstance()->GetCheckpointLast()) CCheckpointManagerABC::GetInstance()->CheckpointPlayerFinishesLap(pPlayer); } /** * Returns the current numbered index of the checkpoint */ int CEntityInfoCheckpoint::GetTouchOrder() { return m_iTouchOrder; } /** * Returns the number of seconds that the player's time is extended when the * checkpoint is passed */ int CEntityInfoCheckpoint::GetTimeExtension() { return m_iTimeExtension; } /** * Returns the number of seconds that the player's time is extended when the * checkpoint is passed, if playing in reverse mode */ int CEntityInfoCheckpoint::GetTimeExtensionReverse() { return m_iTimeExtensionReverse; }