//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: Order handling // // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include "orders.h" #include "tf_player.h" #include "tf_func_resource.h" #include "tf_team.h" #include "tf_obj_resourcepump.h" IMPLEMENT_SERVERCLASS_ST(COrder, DT_Order) SendPropInt( SENDINFO(m_iOrderType), 4, SPROP_UNSIGNED ), SendPropInt( SENDINFO(m_iTargetEntIndex), 16, SPROP_UNSIGNED ), END_SEND_TABLE() LINK_ENTITY_TO_CLASS( tf_order, COrder ); COrder::COrder() { m_iOrderType = 0; m_iTargetEntIndex = 0; m_hTarget = NULL; m_flDistanceToRemove = 0; m_hOwningPlayer = NULL; m_flDieTime = 0; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void COrder::UpdateOnRemove( void ) { DetachFromPlayer(); // Chain at end to mimic destructor unwind order BaseClass::UpdateOnRemove(); } //----------------------------------------------------------------------------- // Purpose: Transmit weapon data //----------------------------------------------------------------------------- int COrder::ShouldTransmit( const CCheckTransmitInfo *pInfo ) { CBaseEntity* pRecipientEntity = CBaseEntity::Instance( pInfo->m_pClientEnt ); // If this is a personal order, only send to it's owner if ( GetOwner() ) { if ( GetOwner() == pRecipientEntity ) return FL_EDICT_ALWAYS; return FL_EDICT_DONTSEND; } // Otherwise, only send to players on our team if ( InSameTeam( pRecipientEntity ) ) return FL_EDICT_ALWAYS; return FL_EDICT_DONTSEND; } void COrder::DetachFromPlayer() { // Detach from our owner. if ( m_hOwningPlayer ) { m_hOwningPlayer->SetOrder( NULL ); m_hOwningPlayer = NULL; if ( GetTeam() ) { ((CTFTeam*)GetTeam())->RemoveOrder( this ); } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int COrder::GetType( void ) { return m_iOrderType; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CBaseEntity *COrder::GetTargetEntity( void ) { return m_hTarget; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void COrder::SetType( int iOrderType ) { m_iOrderType = iOrderType; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void COrder::SetTarget( CBaseEntity *pTarget ) { m_hTarget = pTarget; if ( m_hTarget ) { m_iTargetEntIndex = m_hTarget->entindex(); } else { m_iTargetEntIndex = 0; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void COrder::SetDistance( float flDistance ) { m_flDistanceToRemove = flDistance; } void COrder::SetLifetime( float flLifetime ) { m_flDieTime = gpGlobals->curtime + flLifetime; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Purpose: for updates on the order. Return true if the order should be removed. //----------------------------------------------------------------------------- bool COrder::Update( void ) { // Orders with no targets & no owners don't go away on their own if ( !GetOwner() ) return false; // Has it timed out? if( gpGlobals->curtime > m_flDieTime ) return true; // Check to make sure we're still within the correct distance if ( m_flDistanceToRemove ) { CBaseEntity *pTarget = GetTargetEntity(); if ( pTarget ) { // Have the player and the target moved away from each other? if ( (m_hOwningPlayer->GetAbsOrigin() - pTarget->GetAbsOrigin()).Length() > (m_flDistanceToRemove * 1.25) ) return true; } } return false; } //----------------------------------------------------------------------------- // Purpose: An event for this order's target has arrived. Return true if this order should be removed. //----------------------------------------------------------------------------- bool COrder::UpdateOnEvent( COrderEvent_Base *pEvent ) { // Default behavior is to get rid of the order if the object we're referencing // gets destroyed. if ( pEvent->GetType() == ORDER_EVENT_OBJECT_DESTROYED ) { COrderEvent_ObjectDestroyed *pObjDestroyed = (COrderEvent_ObjectDestroyed*)pEvent; if ( pObjDestroyed->m_pObject == GetTargetEntity() ) return true; } return false; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CBaseTFPlayer *COrder::GetOwner( void ) { return m_hOwningPlayer; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void COrder::SetOwner( CBaseTFPlayer *pPlayer ) { // Null out our m_hOwningPlayer so we don't recurse infinitely. CHandle hPlayer = m_hOwningPlayer; m_hOwningPlayer = 0; if ( hPlayer.Get() && (hPlayer != pPlayer) ) { Assert( hPlayer->GetOrder() == this ); hPlayer->SetOrder( NULL ); } m_hOwningPlayer = pPlayer; }