mirror of
https://github.com/celisej567/BCWSsrc.git
synced 2026-01-03 18:11:08 +03:00
1
This commit is contained in:
283
sp/src/game/server/BasePropDoor.h
Normal file
283
sp/src/game/server/BasePropDoor.h
Normal file
@@ -0,0 +1,283 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: A base class for model-based doors. The exact movement required to
|
||||
// open or close the door is not dictated by this class, only that
|
||||
// the door has open, closed, opening, and closing states.
|
||||
//
|
||||
// Doors must satisfy these requirements:
|
||||
//
|
||||
// - Derived classes must support being opened by NPCs.
|
||||
// - Never autoclose in the face of a player.
|
||||
// - Never close into an NPC.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef BASEPROPDOOR_H
|
||||
#define BASEPROPDOOR_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "props.h"
|
||||
#include "locksounds.h"
|
||||
#include "entityoutput.h"
|
||||
|
||||
extern ConVar g_debug_doors;
|
||||
|
||||
struct opendata_t
|
||||
{
|
||||
Vector vecStandPos; // Where the NPC should stand.
|
||||
Vector vecFaceDir; // What direction the NPC should face.
|
||||
Activity eActivity; // What activity the NPC should play.
|
||||
};
|
||||
|
||||
|
||||
abstract_class CBasePropDoor : public CDynamicProp
|
||||
{
|
||||
public:
|
||||
|
||||
DECLARE_CLASS( CBasePropDoor, CDynamicProp );
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
CBasePropDoor( void );
|
||||
|
||||
void Spawn();
|
||||
void Precache();
|
||||
void Activate();
|
||||
int ObjectCaps();
|
||||
|
||||
void HandleAnimEvent( animevent_t *pEvent );
|
||||
|
||||
// Base class services.
|
||||
// Do not make the functions in this block virtual!!
|
||||
// {
|
||||
inline bool IsDoorOpen();
|
||||
inline bool IsDoorAjar();
|
||||
inline bool IsDoorOpening();
|
||||
inline bool IsDoorClosed();
|
||||
inline bool IsDoorClosing();
|
||||
inline bool IsDoorLocked();
|
||||
inline bool IsDoorBlocked() const;
|
||||
inline bool IsNPCOpening(CAI_BaseNPC *pNPC);
|
||||
inline bool IsPlayerOpening();
|
||||
inline bool IsOpener(CBaseEntity *pEnt);
|
||||
|
||||
bool NPCOpenDoor(CAI_BaseNPC *pNPC);
|
||||
bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace );
|
||||
// }
|
||||
|
||||
// Implement these in your leaf class.
|
||||
// {
|
||||
virtual bool DoorCanClose( bool bAutoClose ) { return true; }
|
||||
virtual bool DoorCanOpen( void ) { return true; }
|
||||
|
||||
virtual void GetNPCOpenData(CAI_BaseNPC *pNPC, opendata_t &opendata) = 0;
|
||||
virtual float GetOpenInterval(void) = 0;
|
||||
// }
|
||||
|
||||
#ifdef MAPBASE
|
||||
virtual bool PassesDoorFilter(CBaseEntity *pEntity) { return true; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
enum DoorState_t
|
||||
{
|
||||
DOOR_STATE_CLOSED = 0,
|
||||
DOOR_STATE_OPENING,
|
||||
DOOR_STATE_OPEN,
|
||||
DOOR_STATE_CLOSING,
|
||||
DOOR_STATE_AJAR,
|
||||
};
|
||||
|
||||
// dvs: FIXME: make these private
|
||||
void DoorClose();
|
||||
|
||||
CBasePropDoor *GetMaster( void ) { return m_hMaster; }
|
||||
bool HasSlaves( void ) { return ( m_hDoorList.Count() > 0 ); }
|
||||
|
||||
inline void SetDoorState( DoorState_t eDoorState );
|
||||
|
||||
float m_flAutoReturnDelay; // How many seconds to wait before automatically closing, -1 never closes automatically.
|
||||
CUtlVector< CHandle< CBasePropDoor > > m_hDoorList; // List of doors linked to us
|
||||
|
||||
inline CBaseEntity *GetActivator();
|
||||
|
||||
private:
|
||||
|
||||
// Implement these in your leaf class.
|
||||
// {
|
||||
// Called when the door becomes fully open.
|
||||
virtual void OnDoorOpened() {}
|
||||
|
||||
// Called when the door becomes fully closed.
|
||||
virtual void OnDoorClosed() {}
|
||||
|
||||
// Called to tell the door to start opening.
|
||||
virtual void BeginOpening(CBaseEntity *pOpenAwayFrom) = 0;
|
||||
|
||||
// Called to tell the door to start closing.
|
||||
virtual void BeginClosing( void ) = 0;
|
||||
|
||||
// Called when blocked to tell the door to stop moving.
|
||||
virtual void DoorStop( void ) = 0;
|
||||
|
||||
// Called when blocked to tell the door to continue moving.
|
||||
virtual void DoorResume( void ) = 0;
|
||||
|
||||
// Called to send the door instantly to its spawn positions.
|
||||
virtual void DoorTeleportToSpawnPosition() = 0;
|
||||
// }
|
||||
|
||||
private:
|
||||
|
||||
// Main entry points for the door base behaviors.
|
||||
// Do not make the functions in this block virtual!!
|
||||
// {
|
||||
bool DoorActivate();
|
||||
void DoorOpen( CBaseEntity *pOpenAwayFrom );
|
||||
void OpenIfUnlocked(CBaseEntity *pActivator, CBaseEntity *pOpenAwayFrom);
|
||||
|
||||
void DoorOpenMoveDone();
|
||||
void DoorCloseMoveDone();
|
||||
void DoorAutoCloseThink();
|
||||
|
||||
void Lock();
|
||||
void Unlock();
|
||||
|
||||
void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
||||
void OnUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
|
||||
inline bool WillAutoReturn() { return m_flAutoReturnDelay != -1; }
|
||||
|
||||
void StartBlocked(CBaseEntity *pOther);
|
||||
void OnStartBlocked( CBaseEntity *pOther );
|
||||
void MasterStartBlocked( CBaseEntity *pOther );
|
||||
|
||||
void Blocked(CBaseEntity *pOther);
|
||||
void EndBlocked(void);
|
||||
void OnEndBlocked( void );
|
||||
|
||||
void UpdateAreaPortals(bool bOpen);
|
||||
|
||||
// Input handlers
|
||||
void InputClose(inputdata_t &inputdata);
|
||||
void InputLock(inputdata_t &inputdata);
|
||||
void InputOpen(inputdata_t &inputdata);
|
||||
void InputOpenAwayFrom(inputdata_t &inputdata);
|
||||
void InputToggle(inputdata_t &inputdata);
|
||||
void InputUnlock(inputdata_t &inputdata);
|
||||
#ifdef MAPBASE
|
||||
void InputAllowPlayerUse(inputdata_t &inputdata);
|
||||
void InputDisallowPlayerUse(inputdata_t &inputdata);
|
||||
#endif
|
||||
|
||||
void SetDoorBlocker( CBaseEntity *pBlocker );
|
||||
|
||||
void SetMaster( CBasePropDoor *pMaster ) { m_hMaster = pMaster; }
|
||||
|
||||
void CalcDoorSounds();
|
||||
// }
|
||||
|
||||
int m_nHardwareType;
|
||||
|
||||
DoorState_t m_eDoorState; // Holds whether the door is open, closed, opening, or closing.
|
||||
|
||||
locksound_t m_ls; // The sounds the door plays when being locked, unlocked, etc.
|
||||
EHANDLE m_hActivator;
|
||||
|
||||
bool m_bLocked; // True if the door is locked.
|
||||
EHANDLE m_hBlocker; // Entity blocking the door currently
|
||||
bool m_bFirstBlocked; // Marker for being the first door (in a group) to be blocked (needed for motion control)
|
||||
|
||||
bool m_bForceClosed; // True if this door must close no matter what.
|
||||
|
||||
string_t m_SoundMoving;
|
||||
string_t m_SoundOpen;
|
||||
string_t m_SoundClose;
|
||||
|
||||
// dvs: FIXME: can we remove m_flSpeed from CBaseEntity?
|
||||
//float m_flSpeed; // Rotation speed when opening or closing in degrees per second.
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
string_t m_SlaveName;
|
||||
|
||||
CHandle< CBasePropDoor > m_hMaster;
|
||||
|
||||
static void RegisterPrivateActivities();
|
||||
|
||||
// Outputs
|
||||
COutputEvent m_OnBlockedClosing; // Triggered when the door becomes blocked while closing.
|
||||
COutputEvent m_OnBlockedOpening; // Triggered when the door becomes blocked while opening.
|
||||
COutputEvent m_OnUnblockedClosing; // Triggered when the door becomes unblocked while closing.
|
||||
COutputEvent m_OnUnblockedOpening; // Triggered when the door becomes unblocked while opening.
|
||||
COutputEvent m_OnFullyClosed; // Triggered when the door reaches the fully closed position.
|
||||
COutputEvent m_OnFullyOpen; // Triggered when the door reaches the fully open position.
|
||||
COutputEvent m_OnClose; // Triggered when the door is told to close.
|
||||
COutputEvent m_OnOpen; // Triggered when the door is told to open.
|
||||
COutputEvent m_OnLockedUse; // Triggered when the user tries to open a locked door.
|
||||
};
|
||||
|
||||
|
||||
void CBasePropDoor::SetDoorState( DoorState_t eDoorState )
|
||||
{
|
||||
m_eDoorState = eDoorState;
|
||||
}
|
||||
|
||||
bool CBasePropDoor::IsDoorOpen()
|
||||
{
|
||||
return m_eDoorState == DOOR_STATE_OPEN;
|
||||
}
|
||||
|
||||
bool CBasePropDoor::IsDoorAjar()
|
||||
{
|
||||
return ( m_eDoorState == DOOR_STATE_AJAR );
|
||||
}
|
||||
|
||||
bool CBasePropDoor::IsDoorOpening()
|
||||
{
|
||||
return m_eDoorState == DOOR_STATE_OPENING;
|
||||
}
|
||||
|
||||
bool CBasePropDoor::IsDoorClosed()
|
||||
{
|
||||
return m_eDoorState == DOOR_STATE_CLOSED;
|
||||
}
|
||||
|
||||
bool CBasePropDoor::IsDoorClosing()
|
||||
{
|
||||
return m_eDoorState == DOOR_STATE_CLOSING;
|
||||
}
|
||||
|
||||
bool CBasePropDoor::IsDoorLocked()
|
||||
{
|
||||
return m_bLocked;
|
||||
}
|
||||
|
||||
CBaseEntity *CBasePropDoor::GetActivator()
|
||||
{
|
||||
return m_hActivator;
|
||||
}
|
||||
|
||||
bool CBasePropDoor::IsDoorBlocked() const
|
||||
{
|
||||
return ( m_hBlocker != NULL );
|
||||
}
|
||||
|
||||
bool CBasePropDoor::IsNPCOpening( CAI_BaseNPC *pNPC )
|
||||
{
|
||||
return ( pNPC == ( CAI_BaseNPC * )GetActivator() );
|
||||
}
|
||||
|
||||
inline bool CBasePropDoor::IsPlayerOpening()
|
||||
{
|
||||
return ( GetActivator() && GetActivator()->IsPlayer() );
|
||||
}
|
||||
|
||||
inline bool CBasePropDoor::IsOpener(CBaseEntity *pEnt)
|
||||
{
|
||||
return ( GetActivator() == pEnt );
|
||||
}
|
||||
|
||||
#endif // BASEPROPDOOR_H
|
||||
267
sp/src/game/server/CRagdollMagnet.cpp
Normal file
267
sp/src/game/server/CRagdollMagnet.cpp
Normal file
@@ -0,0 +1,267 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "game.h"
|
||||
#include "CRagdollMagnet.h"
|
||||
#include "cplane.h"
|
||||
|
||||
ConVar ai_debug_ragdoll_magnets( "ai_debug_ragdoll_magnets", "0");
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
LINK_ENTITY_TO_CLASS( phys_ragdollmagnet, CRagdollMagnet );
|
||||
BEGIN_DATADESC( CRagdollMagnet )
|
||||
DEFINE_KEYFIELD( m_radius, FIELD_FLOAT, "radius" ),
|
||||
DEFINE_KEYFIELD( m_force, FIELD_FLOAT, "force" ),
|
||||
DEFINE_KEYFIELD( m_axis, FIELD_VECTOR, "axis" ),
|
||||
DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_BoneTarget, FIELD_STRING, "BoneTarget" ),
|
||||
#endif
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_OUTPUT( m_OnUsed, "OnUsed" ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRagdollMagnet::InputEnable( inputdata_t &inputdata )
|
||||
{
|
||||
Enable( true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRagdollMagnet::InputDisable( inputdata_t &inputdata )
|
||||
{
|
||||
Enable( false );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Find the ragdoll magnet entity that should pull this entity's ragdoll
|
||||
// Input : *pNPC - the npc that's dying
|
||||
// Output : CRagdollMagnet - the magnet that's best to use.
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// The nearest ragdoll magnet pulls me in IF:
|
||||
// - Present
|
||||
// - I'm within the magnet's RADIUS
|
||||
// - LATER: There is clear line of sight from my center to the magnet
|
||||
// - LATER: I'm not flagged to ignore ragdoll magnets
|
||||
// - LATER: The magnet is not turned OFF
|
||||
//-----------------------------------------------------------------------------
|
||||
CRagdollMagnet *CRagdollMagnet::FindBestMagnet( CBaseEntity *pNPC )
|
||||
{
|
||||
CRagdollMagnet *pMagnet = NULL;
|
||||
CRagdollMagnet *pBestMagnet;
|
||||
|
||||
float flClosestDist;
|
||||
|
||||
// Assume we won't find one.
|
||||
pBestMagnet = NULL;
|
||||
flClosestDist = FLT_MAX;
|
||||
|
||||
do
|
||||
{
|
||||
pMagnet = (CRagdollMagnet *)gEntList.FindEntityByClassname( pMagnet, "phys_ragdollmagnet" );
|
||||
|
||||
if( pMagnet && pMagnet->IsEnabled() )
|
||||
{
|
||||
if( pMagnet->m_target != NULL_STRING )
|
||||
{
|
||||
// if this magnet has a target, only affect that target!
|
||||
if( pNPC->GetEntityName() == pMagnet->m_target )
|
||||
{
|
||||
return pMagnet;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
float flDist;
|
||||
flDist = pMagnet->DistToPoint( pNPC->WorldSpaceCenter() );
|
||||
|
||||
if( flDist < flClosestDist && flDist <= pMagnet->GetRadius() )
|
||||
{
|
||||
// This is the closest magnet that can pull this npc.
|
||||
flClosestDist = flDist;
|
||||
pBestMagnet = pMagnet;
|
||||
}
|
||||
}
|
||||
|
||||
} while( pMagnet );
|
||||
|
||||
return pBestMagnet;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Get the force that we should add to this NPC's ragdoll.
|
||||
// Input : *pNPC -
|
||||
// Output : Vector
|
||||
//
|
||||
// NOTE: This function assumes pNPC is within this magnet's radius.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef MAPBASE
|
||||
Vector CRagdollMagnet::GetForceVector( CBaseEntity *pNPC, int *pBone )
|
||||
#else
|
||||
Vector CRagdollMagnet::GetForceVector( CBaseEntity *pNPC )
|
||||
#endif
|
||||
{
|
||||
Vector vecForceToApply;
|
||||
|
||||
#ifdef MAPBASE
|
||||
Vector vecNPCPos = pNPC->WorldSpaceCenter();
|
||||
|
||||
if (pBone)
|
||||
{
|
||||
CBaseAnimating *pAnimating = pNPC->GetBaseAnimating();
|
||||
Assert( pAnimating != NULL );
|
||||
|
||||
const char *szBoneTarget = BoneTarget();
|
||||
Assert( szBoneTarget != NULL );
|
||||
|
||||
int iBone = pAnimating->LookupBone( szBoneTarget );
|
||||
|
||||
if (iBone != -1)
|
||||
{
|
||||
matrix3x4_t bonetoworld;
|
||||
pAnimating->GetBoneTransform( iBone, bonetoworld );
|
||||
MatrixPosition( bonetoworld, vecNPCPos );
|
||||
*pBone = iBone;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if( IsBarMagnet() )
|
||||
{
|
||||
CPlane axis;
|
||||
Vector vecForceDir;
|
||||
Vector vecClosest;
|
||||
|
||||
#ifdef MAPBASE
|
||||
CalcClosestPointOnLineSegment( vecNPCPos, GetAbsOrigin(), m_axis, vecClosest, NULL );
|
||||
|
||||
vecForceDir = (vecClosest - vecNPCPos );
|
||||
VectorNormalize( vecForceDir );
|
||||
#else
|
||||
CalcClosestPointOnLineSegment( pNPC->WorldSpaceCenter(), GetAbsOrigin(), m_axis, vecClosest, NULL );
|
||||
|
||||
vecForceDir = (vecClosest - pNPC->WorldSpaceCenter() );
|
||||
VectorNormalize( vecForceDir );
|
||||
#endif
|
||||
|
||||
vecForceToApply = vecForceDir * m_force;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector vecForce;
|
||||
|
||||
#ifdef MAPBASE
|
||||
vecForce = GetAbsOrigin() - vecNPCPos;
|
||||
#else
|
||||
vecForce = GetAbsOrigin() - pNPC->WorldSpaceCenter();
|
||||
#endif
|
||||
VectorNormalize( vecForce );
|
||||
|
||||
vecForceToApply = vecForce * m_force;
|
||||
}
|
||||
|
||||
if( ai_debug_ragdoll_magnets.GetBool() )
|
||||
{
|
||||
IPhysicsObject *pPhysObject;
|
||||
|
||||
pPhysObject = pNPC->VPhysicsGetObject();
|
||||
|
||||
if( pPhysObject )
|
||||
{
|
||||
Msg("Ragdoll magnet adding %f inches/sec to %s\n", m_force/pPhysObject->GetMass(), pNPC->GetClassname() );
|
||||
}
|
||||
}
|
||||
|
||||
return vecForceToApply;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: How far away is this point? This is different for point and bar magnets
|
||||
// Input : &vecPoint - the point
|
||||
// Output : float - the dist
|
||||
//-----------------------------------------------------------------------------
|
||||
float CRagdollMagnet::DistToPoint( const Vector &vecPoint )
|
||||
{
|
||||
if( IsBarMagnet() )
|
||||
{
|
||||
// I'm a bar magnet, so the point's distance is really the plane constant.
|
||||
// A bar magnet is a cylinder who's length is AbsOrigin() to m_axis, and whose
|
||||
// diameter is m_radius.
|
||||
|
||||
// first we build two planes. The TOP and BOTTOM planes.
|
||||
// the idea is that vecPoint must be on the right side of both
|
||||
// planes to be affected by this particular magnet.
|
||||
// TOP and BOTTOM planes can be visualized as the 'caps' of the cylinder
|
||||
// that describes the bar magnet, and they point towards each other.
|
||||
// We're making sure vecPoint is between the caps.
|
||||
Vector vecAxis;
|
||||
|
||||
vecAxis = GetAxisVector();
|
||||
VectorNormalize( vecAxis );
|
||||
|
||||
CPlane top, bottom;
|
||||
|
||||
bottom.InitializePlane( -vecAxis, m_axis );
|
||||
top.InitializePlane( vecAxis, GetAbsOrigin() );
|
||||
|
||||
if( top.PointInFront( vecPoint ) && bottom.PointInFront( vecPoint ) )
|
||||
{
|
||||
// This point is between the two caps, so calculate the distance
|
||||
// of vecPoint from the axis of the bar magnet
|
||||
CPlane axis;
|
||||
Vector vecUp;
|
||||
Vector vecRight;
|
||||
|
||||
// Horizontal and Vertical distances.
|
||||
float hDist, vDist;
|
||||
|
||||
// Need to get a vector that's right-hand to m_axis
|
||||
VectorVectors( vecAxis, vecRight, vecUp );
|
||||
|
||||
//CrossProduct( vecAxis, vecUp, vecRight );
|
||||
//VectorNormalize( vecRight );
|
||||
//VectorNormalize( vecUp );
|
||||
|
||||
// Set up the plane to measure horizontal dist.
|
||||
axis.InitializePlane( vecRight, GetAbsOrigin() );
|
||||
hDist = fabs( axis.PointDist( vecPoint ) );
|
||||
|
||||
axis.InitializePlane( vecUp, GetAbsOrigin() );
|
||||
vDist = fabs( axis.PointDist( vecPoint ) );
|
||||
|
||||
return MAX( hDist, vDist );
|
||||
}
|
||||
else
|
||||
{
|
||||
return FLT_MAX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// I'm a point magnet. Just return dist
|
||||
return ( GetAbsOrigin() - vecPoint ).Length();
|
||||
}
|
||||
}
|
||||
58
sp/src/game/server/CRagdollMagnet.h
Normal file
58
sp/src/game/server/CRagdollMagnet.h
Normal file
@@ -0,0 +1,58 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Used to influence the initial force for a dying NPC's ragdoll.
|
||||
// Passive entity. Just represents position in the world, radius, force
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#pragma once
|
||||
|
||||
#ifndef CRAGDOLLMAGNET_H
|
||||
#define CRAGDOLLMAGNET_H
|
||||
|
||||
#define SF_RAGDOLLMAGNET_BAR 0x00000002 // this is a bar magnet.
|
||||
|
||||
class CRagdollMagnet : public CPointEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CRagdollMagnet, CPointEntity );
|
||||
DECLARE_DATADESC();
|
||||
|
||||
#ifdef MAPBASE
|
||||
Vector GetForceVector( CBaseEntity *pNPC, int *pBone = NULL );
|
||||
#else
|
||||
Vector GetForceVector( CBaseEntity *pNPC );
|
||||
#endif
|
||||
float GetRadius( void ) { return m_radius; }
|
||||
Vector GetAxisVector( void ) { return m_axis - GetAbsOrigin(); }
|
||||
float DistToPoint( const Vector &vecPoint );
|
||||
|
||||
bool IsEnabled( void ) { return !m_bDisabled; }
|
||||
|
||||
int IsBarMagnet( void ) { return (m_spawnflags & SF_RAGDOLLMAGNET_BAR); }
|
||||
|
||||
static CRagdollMagnet *FindBestMagnet( CBaseEntity *pNPC );
|
||||
|
||||
void Enable( bool bEnable ) { m_bDisabled = !bEnable; }
|
||||
|
||||
// Inputs
|
||||
void InputEnable( inputdata_t &inputdata );
|
||||
void InputDisable( inputdata_t &inputdata );
|
||||
|
||||
#ifdef MAPBASE
|
||||
const char *BoneTarget() { return STRING(m_BoneTarget); }
|
||||
|
||||
COutputVector m_OnUsed;
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool m_bDisabled;
|
||||
float m_radius;
|
||||
float m_force;
|
||||
Vector m_axis;
|
||||
#ifdef MAPBASE
|
||||
string_t m_BoneTarget;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif //CRAGDOLLMAGNET_H
|
||||
1662
sp/src/game/server/CommentarySystem.cpp
Normal file
1662
sp/src/game/server/CommentarySystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
198
sp/src/game/server/EffectsServer.cpp
Normal file
198
sp/src/game/server/EffectsServer.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Utility code.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "te.h"
|
||||
#include "shake.h"
|
||||
#include "decals.h"
|
||||
#include "IEffects.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud
|
||||
extern short g_sModelIndexBloodDrop; // (in combatweapon.cpp) holds the sprite index for the initial blood
|
||||
extern short g_sModelIndexBloodSpray; // (in combatweapon.cpp) holds the sprite index for splattered blood
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Client-server neutral effects interface
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEffectsServer : public IEffects
|
||||
{
|
||||
public:
|
||||
CEffectsServer();
|
||||
virtual ~CEffectsServer();
|
||||
|
||||
// Members of the IEffect interface
|
||||
virtual void Beam( const Vector &Start, const Vector &End, int nModelIndex,
|
||||
int nHaloIndex, unsigned char frameStart, unsigned char frameRate,
|
||||
float flLife, unsigned char width, unsigned char endWidth, unsigned char fadeLength,
|
||||
unsigned char noise, unsigned char red, unsigned char green,
|
||||
unsigned char blue, unsigned char brightness, unsigned char speed);
|
||||
virtual void Smoke( const Vector &origin, int mModel, float flScale, float flFramerate );
|
||||
virtual void Sparks( const Vector &position, int nMagnitude = 1, int nTrailLength = 1, const Vector *pvecDir = NULL );
|
||||
virtual void Dust( const Vector &pos, const Vector &dir, float size, float speed );
|
||||
virtual void MuzzleFlash( const Vector &origin, const QAngle &angles, float scale, int type );
|
||||
virtual void MetalSparks( const Vector &position, const Vector &direction );
|
||||
virtual void EnergySplash( const Vector &position, const Vector &direction, bool bExplosive = false );
|
||||
virtual void Ricochet( const Vector &position, const Vector &direction );
|
||||
|
||||
// FIXME: Should these methods remain in this interface? Or go in some
|
||||
// other client-server neutral interface?
|
||||
virtual float Time();
|
||||
virtual bool IsServer();
|
||||
virtual void SuppressEffectsSounds( bool bSuppress ) { Assert(0); }
|
||||
|
||||
private:
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returning true means don't even call TE func
|
||||
// Input : filter -
|
||||
// *suppress_host -
|
||||
// Output : static bool
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SuppressTE( CRecipientFilter& filter )
|
||||
{
|
||||
if ( GetSuppressHost() )
|
||||
{
|
||||
if ( !filter.IgnorePredictionCull() )
|
||||
{
|
||||
filter.RemoveRecipient( (CBasePlayer *)GetSuppressHost() );
|
||||
}
|
||||
|
||||
if ( !filter.GetRecipientCount() )
|
||||
{
|
||||
// Suppress it
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// There's at least one recipient
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Client-server neutral effects interface accessor
|
||||
//-----------------------------------------------------------------------------
|
||||
static CEffectsServer s_EffectServer;
|
||||
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CEffectsServer, IEffects, IEFFECTS_INTERFACE_VERSION, s_EffectServer);
|
||||
IEffects *g_pEffects = &s_EffectServer;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CEffectsServer::CEffectsServer()
|
||||
{
|
||||
}
|
||||
|
||||
CEffectsServer::~CEffectsServer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Generates a beam
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEffectsServer::Beam( const Vector &vecStart, const Vector &vecEnd, int nModelIndex,
|
||||
int nHaloIndex, unsigned char frameStart, unsigned char frameRate,
|
||||
float flLife, unsigned char width, unsigned char endWidth, unsigned char fadeLength,
|
||||
unsigned char noise, unsigned char red, unsigned char green,
|
||||
unsigned char blue, unsigned char brightness, unsigned char speed)
|
||||
{
|
||||
CBroadcastRecipientFilter filter;
|
||||
if ( !SuppressTE( filter ) )
|
||||
{
|
||||
te->BeamPoints( filter, 0.0,
|
||||
&vecStart, &vecEnd, nModelIndex, nHaloIndex, frameStart, frameRate, flLife,
|
||||
width, endWidth, fadeLength, noise, red, green, blue, brightness, speed );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Generates various tempent effects
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEffectsServer::Smoke( const Vector &origin, int mModel, float flScale, float flFramerate )
|
||||
{
|
||||
CPVSFilter filter( origin );
|
||||
if ( !SuppressTE( filter ) )
|
||||
{
|
||||
te->Smoke( filter, 0.0, &origin, mModel, flScale * 0.1f, flFramerate );
|
||||
}
|
||||
}
|
||||
|
||||
void CEffectsServer::Sparks( const Vector &position, int nMagnitude, int nTrailLength, const Vector *pvecDir )
|
||||
{
|
||||
CPVSFilter filter( position );
|
||||
if ( !SuppressTE( filter ) )
|
||||
{
|
||||
te->Sparks( filter, 0.0, &position, nMagnitude, nTrailLength, pvecDir );
|
||||
}
|
||||
}
|
||||
|
||||
void CEffectsServer::Dust( const Vector &pos, const Vector &dir, float size, float speed )
|
||||
{
|
||||
CPVSFilter filter( pos );
|
||||
if ( !SuppressTE( filter ) )
|
||||
{
|
||||
te->Dust( filter, 0.0, pos, dir, size, speed );
|
||||
}
|
||||
}
|
||||
|
||||
void CEffectsServer::MuzzleFlash( const Vector &origin, const QAngle &angles, float scale, int type )
|
||||
{
|
||||
CPVSFilter filter( origin );
|
||||
if ( !SuppressTE( filter ) )
|
||||
{
|
||||
te->MuzzleFlash( filter, 0.0f, origin, angles, scale, type );
|
||||
}
|
||||
}
|
||||
|
||||
void CEffectsServer::MetalSparks( const Vector &position, const Vector &direction )
|
||||
{
|
||||
CPVSFilter filter( position );
|
||||
if ( !SuppressTE( filter ) )
|
||||
{
|
||||
te->MetalSparks( filter, 0.0, &position, &direction );
|
||||
}
|
||||
}
|
||||
|
||||
void CEffectsServer::EnergySplash( const Vector &position, const Vector &direction, bool bExplosive )
|
||||
{
|
||||
CPVSFilter filter( position );
|
||||
if ( !SuppressTE( filter ) )
|
||||
{
|
||||
te->EnergySplash( filter, 0.0, &position, &direction, bExplosive );
|
||||
}
|
||||
}
|
||||
|
||||
void CEffectsServer::Ricochet( const Vector &position, const Vector &direction )
|
||||
{
|
||||
CPVSFilter filter( position );
|
||||
if ( !SuppressTE( filter ) )
|
||||
{
|
||||
te->ArmorRicochet( filter, 0.0, &position, &direction );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FIXME: Should these methods remain in this interface? Or go in some
|
||||
// other client-server neutral interface?
|
||||
//-----------------------------------------------------------------------------
|
||||
float CEffectsServer::Time()
|
||||
{
|
||||
return gpGlobals->curtime;
|
||||
}
|
||||
|
||||
bool CEffectsServer::IsServer()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
388
sp/src/game/server/EntityDissolve.cpp
Normal file
388
sp/src/game/server/EntityDissolve.cpp
Normal file
@@ -0,0 +1,388 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Dissolve entity to be attached to target entity. Serves two purposes:
|
||||
//
|
||||
// 1) An entity that can be placed by a level designer and triggered
|
||||
// to ignite a target entity.
|
||||
//
|
||||
// 2) An entity that can be created at runtime to ignite a target entity.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "EntityDissolve.h"
|
||||
#include "baseanimating.h"
|
||||
#include "physics_prop_ragdoll.h"
|
||||
#include "ai_basenpc.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
static const char *s_pElectroThinkContext = "ElectroThinkContext";
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Lifetime
|
||||
//-----------------------------------------------------------------------------
|
||||
#define DISSOLVE_FADE_IN_START_TIME 0.0f
|
||||
#define DISSOLVE_FADE_IN_END_TIME 1.0f
|
||||
#define DISSOLVE_FADE_OUT_MODEL_START_TIME 1.9f
|
||||
#define DISSOLVE_FADE_OUT_MODEL_END_TIME 2.0f
|
||||
#define DISSOLVE_FADE_OUT_START_TIME 2.0f
|
||||
#define DISSOLVE_FADE_OUT_END_TIME 2.0f
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Model
|
||||
//-----------------------------------------------------------------------------
|
||||
#define DISSOLVE_SPRITE_NAME "sprites/blueglow1.vmt"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Save/load
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_DATADESC( CEntityDissolve )
|
||||
|
||||
DEFINE_FIELD( m_flStartTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_flFadeInStart, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flFadeInLength, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flFadeOutModelStart, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flFadeOutModelLength, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flFadeOutStart, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flFadeOutLength, FIELD_FLOAT ),
|
||||
DEFINE_KEYFIELD( m_nDissolveType, FIELD_INTEGER, "dissolvetype" ),
|
||||
DEFINE_FIELD( m_vDissolverOrigin, FIELD_VECTOR ),
|
||||
DEFINE_KEYFIELD( m_nMagnitude, FIELD_INTEGER, "magnitude" ),
|
||||
|
||||
DEFINE_FUNCTION( DissolveThink ),
|
||||
DEFINE_FUNCTION( ElectrocuteThink ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "Dissolve", InputDissolve ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Networking
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_SERVERCLASS_ST( CEntityDissolve, DT_EntityDissolve )
|
||||
SendPropTime( SENDINFO( m_flStartTime ) ),
|
||||
SendPropFloat( SENDINFO( m_flFadeInStart ), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat( SENDINFO( m_flFadeInLength ), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat( SENDINFO( m_flFadeOutModelStart ), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat( SENDINFO( m_flFadeOutModelLength ), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat( SENDINFO( m_flFadeOutStart ), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat( SENDINFO( m_flFadeOutLength ), 0, SPROP_NOSCALE ),
|
||||
SendPropInt( SENDINFO( m_nDissolveType ), ENTITY_DISSOLVE_BITS, SPROP_UNSIGNED ),
|
||||
SendPropVector (SENDINFO(m_vDissolverOrigin), 0, SPROP_NOSCALE ),
|
||||
SendPropInt( SENDINFO( m_nMagnitude ), 8, SPROP_UNSIGNED ),
|
||||
END_SEND_TABLE()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_entity_dissolver, CEntityDissolve );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CEntityDissolve::CEntityDissolve( void )
|
||||
{
|
||||
m_flStartTime = 0.0f;
|
||||
m_nMagnitude = 250;
|
||||
}
|
||||
|
||||
CEntityDissolve::~CEntityDissolve( void )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Precache
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityDissolve::Precache()
|
||||
{
|
||||
if ( NULL_STRING == GetModelName() )
|
||||
{
|
||||
PrecacheModel( DISSOLVE_SPRITE_NAME );
|
||||
}
|
||||
else
|
||||
{
|
||||
PrecacheModel( STRING( GetModelName() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Spawn
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityDissolve::Spawn()
|
||||
{
|
||||
BaseClass::Spawn();
|
||||
Precache();
|
||||
UTIL_SetModel( this, STRING( GetModelName() ) );
|
||||
|
||||
if ( (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) )
|
||||
{
|
||||
if ( dynamic_cast< CRagdollProp* >( GetMoveParent() ) )
|
||||
{
|
||||
SetContextThink( &CEntityDissolve::ElectrocuteThink, gpGlobals->curtime + 0.01f, s_pElectroThinkContext );
|
||||
}
|
||||
}
|
||||
|
||||
// Setup our times
|
||||
m_flFadeInStart = DISSOLVE_FADE_IN_START_TIME;
|
||||
m_flFadeInLength = DISSOLVE_FADE_IN_END_TIME - DISSOLVE_FADE_IN_START_TIME;
|
||||
|
||||
m_flFadeOutModelStart = DISSOLVE_FADE_OUT_MODEL_START_TIME;
|
||||
m_flFadeOutModelLength = DISSOLVE_FADE_OUT_MODEL_END_TIME - DISSOLVE_FADE_OUT_MODEL_START_TIME;
|
||||
|
||||
m_flFadeOutStart = DISSOLVE_FADE_OUT_START_TIME;
|
||||
m_flFadeOutLength = DISSOLVE_FADE_OUT_END_TIME - DISSOLVE_FADE_OUT_START_TIME;
|
||||
|
||||
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
|
||||
{
|
||||
m_flFadeInStart = 0.0f;
|
||||
m_flFadeOutStart = CORE_DISSOLVE_FADE_START;
|
||||
m_flFadeOutModelStart = CORE_DISSOLVE_MODEL_FADE_START;
|
||||
m_flFadeOutModelLength = CORE_DISSOLVE_MODEL_FADE_LENGTH;
|
||||
m_flFadeInLength = CORE_DISSOLVE_FADEIN_LENGTH;
|
||||
}
|
||||
|
||||
m_nRenderMode = kRenderTransColor;
|
||||
SetRenderColor( 255, 255, 255, 255 );
|
||||
m_nRenderFX = kRenderFxNone;
|
||||
|
||||
SetThink( &CEntityDissolve::DissolveThink );
|
||||
if ( gpGlobals->curtime > m_flStartTime )
|
||||
{
|
||||
// Necessary for server-side ragdolls
|
||||
DissolveThink();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime + 0.01f );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityDissolve::InputDissolve( inputdata_t &inputdata )
|
||||
{
|
||||
string_t strTarget = inputdata.value.StringID();
|
||||
|
||||
if (strTarget == NULL_STRING)
|
||||
{
|
||||
strTarget = m_target;
|
||||
}
|
||||
|
||||
CBaseEntity *pTarget = NULL;
|
||||
while ((pTarget = gEntList.FindEntityGeneric(pTarget, STRING(strTarget), this, inputdata.pActivator)) != NULL)
|
||||
{
|
||||
CBaseAnimating *pBaseAnim = pTarget->GetBaseAnimating();
|
||||
if (pBaseAnim)
|
||||
{
|
||||
pBaseAnim->Dissolve( NULL, gpGlobals->curtime, false, m_nDissolveType, GetAbsOrigin(), m_nMagnitude );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Creates a flame and attaches it to a target entity.
|
||||
// Input : pTarget -
|
||||
//-----------------------------------------------------------------------------
|
||||
CEntityDissolve *CEntityDissolve::Create( CBaseEntity *pTarget, const char *pMaterialName,
|
||||
float flStartTime, int nDissolveType, bool *pRagdollCreated )
|
||||
{
|
||||
if ( pRagdollCreated )
|
||||
{
|
||||
*pRagdollCreated = false;
|
||||
}
|
||||
|
||||
if ( !pMaterialName )
|
||||
{
|
||||
pMaterialName = DISSOLVE_SPRITE_NAME;
|
||||
}
|
||||
|
||||
if ( pTarget->IsPlayer() )
|
||||
{
|
||||
// Simply immediately kill the player.
|
||||
CBasePlayer *pPlayer = assert_cast< CBasePlayer* >( pTarget );
|
||||
pPlayer->SetArmorValue( 0 );
|
||||
CTakeDamageInfo info( pPlayer, pPlayer, pPlayer->GetHealth(), DMG_GENERIC | DMG_REMOVENORAGDOLL | DMG_PREVENT_PHYSICS_FORCE );
|
||||
pPlayer->TakeDamage( info );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CEntityDissolve *pDissolve = (CEntityDissolve *) CreateEntityByName( "env_entity_dissolver" );
|
||||
|
||||
if ( pDissolve == NULL )
|
||||
return NULL;
|
||||
|
||||
pDissolve->m_nDissolveType = nDissolveType;
|
||||
if ( (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) )
|
||||
{
|
||||
if ( pTarget->IsNPC() && pTarget->MyNPCPointer()->CanBecomeRagdoll() )
|
||||
{
|
||||
CTakeDamageInfo info;
|
||||
CBaseEntity *pRagdoll = CreateServerRagdoll( pTarget->MyNPCPointer(), 0, info, COLLISION_GROUP_DEBRIS, true );
|
||||
pRagdoll->SetCollisionBounds( pTarget->CollisionProp()->OBBMins(), pTarget->CollisionProp()->OBBMaxs() );
|
||||
|
||||
// Necessary to cause it to do the appropriate death cleanup
|
||||
if ( pTarget->m_lifeState == LIFE_ALIVE )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 );
|
||||
CTakeDamageInfo ragdollInfo( pPlayer, pPlayer, 10000.0, DMG_SHOCK | DMG_REMOVENORAGDOLL | DMG_PREVENT_PHYSICS_FORCE );
|
||||
pTarget->TakeDamage( ragdollInfo );
|
||||
}
|
||||
|
||||
if ( pRagdollCreated )
|
||||
{
|
||||
*pRagdollCreated = true;
|
||||
}
|
||||
|
||||
UTIL_Remove( pTarget );
|
||||
pTarget = pRagdoll;
|
||||
}
|
||||
}
|
||||
|
||||
pDissolve->SetModelName( AllocPooledString(pMaterialName) );
|
||||
pDissolve->AttachToEntity( pTarget );
|
||||
pDissolve->SetStartTime( flStartTime );
|
||||
pDissolve->Spawn();
|
||||
|
||||
// Send to the client even though we don't have a model
|
||||
pDissolve->AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
|
||||
|
||||
// Play any appropriate noises when we start to dissolve
|
||||
if ( (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) )
|
||||
{
|
||||
pTarget->DispatchResponse( "TLK_ELECTROCUTESCREAM" );
|
||||
}
|
||||
else
|
||||
{
|
||||
pTarget->DispatchResponse( "TLK_DISSOLVESCREAM" );
|
||||
}
|
||||
return pDissolve;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// What type of dissolve?
|
||||
//-----------------------------------------------------------------------------
|
||||
CEntityDissolve *CEntityDissolve::Create( CBaseEntity *pTarget, CBaseEntity *pSource )
|
||||
{
|
||||
// Look for other boogies on the ragdoll + kill them
|
||||
for ( CBaseEntity *pChild = pSource->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
|
||||
{
|
||||
CEntityDissolve *pDissolve = dynamic_cast<CEntityDissolve*>(pChild);
|
||||
if ( !pDissolve )
|
||||
continue;
|
||||
|
||||
return Create( pTarget, STRING( pDissolve->GetModelName() ), pDissolve->m_flStartTime, pDissolve->m_nDissolveType );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Attaches the flame to an entity and moves with it
|
||||
// Input : pTarget - target entity to attach to
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityDissolve::AttachToEntity( CBaseEntity *pTarget )
|
||||
{
|
||||
// So our dissolver follows the entity around on the server.
|
||||
SetParent( pTarget );
|
||||
SetLocalOrigin( vec3_origin );
|
||||
SetLocalAngles( vec3_angle );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : lifetime -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityDissolve::SetStartTime( float flStartTime )
|
||||
{
|
||||
m_flStartTime = flStartTime;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Burn targets around us
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityDissolve::DissolveThink( void )
|
||||
{
|
||||
CBaseAnimating *pTarget = ( GetMoveParent() ) ? GetMoveParent()->GetBaseAnimating() : NULL;
|
||||
|
||||
if ( GetModelName() == NULL_STRING && pTarget == NULL )
|
||||
return;
|
||||
|
||||
if ( pTarget == NULL )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
|
||||
// Turn them into debris
|
||||
pTarget->SetCollisionGroup( COLLISION_GROUP_DISSOLVING );
|
||||
|
||||
if ( pTarget && pTarget->GetFlags() & FL_TRANSRAGDOLL )
|
||||
{
|
||||
SetRenderColorA( 0 );
|
||||
}
|
||||
|
||||
float dt = gpGlobals->curtime - m_flStartTime;
|
||||
|
||||
if ( dt < m_flFadeInStart )
|
||||
{
|
||||
SetNextThink( m_flStartTime + m_flFadeInStart );
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're done fading, then kill our target entity and us
|
||||
if ( dt >= m_flFadeOutStart + m_flFadeOutLength )
|
||||
{
|
||||
// Necessary to cause it to do the appropriate death cleanup
|
||||
// Yeah, the player may have nothing to do with it, but
|
||||
// passing NULL to TakeDamage causes bad things to happen
|
||||
CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 );
|
||||
int iNoPhysicsDamage = g_pGameRules->Damage_GetNoPhysicsForce();
|
||||
CTakeDamageInfo info( pPlayer, pPlayer, 10000.0, DMG_GENERIC | DMG_REMOVENORAGDOLL | iNoPhysicsDamage );
|
||||
pTarget->TakeDamage( info );
|
||||
|
||||
if ( pTarget != pPlayer )
|
||||
{
|
||||
UTIL_Remove( pTarget );
|
||||
}
|
||||
|
||||
UTIL_Remove( this );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Burn targets around us
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityDissolve::ElectrocuteThink( void )
|
||||
{
|
||||
CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( GetMoveParent() );
|
||||
if ( !pRagdoll )
|
||||
return;
|
||||
|
||||
ragdoll_t *pRagdollPhys = pRagdoll->GetRagdoll( );
|
||||
for ( int j = 0; j < pRagdollPhys->listCount; ++j )
|
||||
{
|
||||
Vector vecForce;
|
||||
vecForce = RandomVector( -2400.0f, 2400.0f );
|
||||
pRagdollPhys->list[j].pObject->ApplyForceCenter( vecForce );
|
||||
}
|
||||
|
||||
SetContextThink( &CEntityDissolve::ElectrocuteThink, gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ),
|
||||
s_pElectroThinkContext );
|
||||
}
|
||||
63
sp/src/game/server/EntityDissolve.h
Normal file
63
sp/src/game/server/EntityDissolve.h
Normal file
@@ -0,0 +1,63 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef ENTITYDISSOLVE_H
|
||||
#define ENTITYDISSOLVE_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
class CEntityDissolve : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_CLASS( CEntityDissolve, CBaseEntity );
|
||||
|
||||
CEntityDissolve( void );
|
||||
~CEntityDissolve( void );
|
||||
|
||||
static CEntityDissolve *Create( CBaseEntity *pTarget, const char *pMaterialName,
|
||||
float flStartTime, int nDissolveType = 0, bool *pRagdollCreated = NULL );
|
||||
static CEntityDissolve *Create( CBaseEntity *pTarget, CBaseEntity *pSource );
|
||||
|
||||
void Precache();
|
||||
void Spawn();
|
||||
void AttachToEntity( CBaseEntity *pTarget );
|
||||
void SetStartTime( float flStartTime );
|
||||
void SetDissolverOrigin( Vector vOrigin ) { m_vDissolverOrigin = vOrigin; }
|
||||
void SetMagnitude( int iMagnitude ){ m_nMagnitude = iMagnitude; }
|
||||
void SetDissolveType( int iType ) { m_nDissolveType = iType; }
|
||||
|
||||
Vector GetDissolverOrigin( void )
|
||||
{
|
||||
Vector vReturn = m_vDissolverOrigin;
|
||||
return vReturn;
|
||||
}
|
||||
int GetMagnitude( void ) { return m_nMagnitude; }
|
||||
int GetDissolveType( void ) { return m_nDissolveType; }
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
CNetworkVar( float, m_flStartTime );
|
||||
CNetworkVar( float, m_flFadeInStart );
|
||||
CNetworkVar( float, m_flFadeInLength );
|
||||
CNetworkVar( float, m_flFadeOutModelStart );
|
||||
CNetworkVar( float, m_flFadeOutModelLength );
|
||||
CNetworkVar( float, m_flFadeOutStart );
|
||||
CNetworkVar( float, m_flFadeOutLength );
|
||||
|
||||
protected:
|
||||
void InputDissolve( inputdata_t &inputdata );
|
||||
void DissolveThink( void );
|
||||
void ElectrocuteThink( void );
|
||||
|
||||
CNetworkVar( int, m_nDissolveType );
|
||||
CNetworkVector( m_vDissolverOrigin );
|
||||
CNetworkVar( int, m_nMagnitude );
|
||||
};
|
||||
|
||||
#endif // ENTITYDISSOLVE_H
|
||||
335
sp/src/game/server/EntityFlame.cpp
Normal file
335
sp/src/game/server/EntityFlame.cpp
Normal file
@@ -0,0 +1,335 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Flame entity to be attached to target entity. Serves two purposes:
|
||||
//
|
||||
// 1) An entity that can be placed by a level designer and triggered
|
||||
// to ignite a target entity.
|
||||
//
|
||||
// 2) An entity that can be created at runtime to ignite a target entity.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "EntityFlame.h"
|
||||
#include "ai_basenpc.h"
|
||||
#include "fire.h"
|
||||
#include "shareddefs.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
BEGIN_DATADESC( CEntityFlame )
|
||||
|
||||
DEFINE_KEYFIELD( m_flLifetime, FIELD_FLOAT, "lifetime" ),
|
||||
|
||||
DEFINE_FIELD( m_flSize, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_hEntAttached, FIELD_EHANDLE ),
|
||||
DEFINE_FIELD( m_bUseHitboxes, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( m_iNumHitboxFires, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_flHitboxFireScale, FIELD_FLOAT ),
|
||||
// DEFINE_FIELD( m_bPlayingSound, FIELD_BOOLEAN ),
|
||||
|
||||
DEFINE_FUNCTION( FlameThink ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Ignite", InputIgnite ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST( CEntityFlame, DT_EntityFlame )
|
||||
SendPropEHandle( SENDINFO( m_hEntAttached ) ),
|
||||
END_SEND_TABLE()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( entityflame, CEntityFlame );
|
||||
LINK_ENTITY_TO_CLASS( env_entity_igniter, CEntityFlame );
|
||||
PRECACHE_REGISTER(entityflame);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CEntityFlame::CEntityFlame( void )
|
||||
{
|
||||
m_flSize = 0.0f;
|
||||
m_iNumHitboxFires = 10;
|
||||
m_flHitboxFireScale = 1.0f;
|
||||
m_flLifetime = 0.0f;
|
||||
m_bPlayingSound = false;
|
||||
}
|
||||
|
||||
void CEntityFlame::UpdateOnRemove()
|
||||
{
|
||||
// Sometimes the entity I'm burning gets destroyed by other means,
|
||||
// which kills me. Make sure to stop the burning sound.
|
||||
if ( m_bPlayingSound )
|
||||
{
|
||||
EmitSound( "General.StopBurning" );
|
||||
m_bPlayingSound = false;
|
||||
}
|
||||
|
||||
BaseClass::UpdateOnRemove();
|
||||
}
|
||||
|
||||
void CEntityFlame::Precache()
|
||||
{
|
||||
BaseClass::Precache();
|
||||
|
||||
PrecacheScriptSound( "General.StopBurning" );
|
||||
PrecacheScriptSound( "General.BurningFlesh" );
|
||||
PrecacheScriptSound( "General.BurningObject" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityFlame::InputIgnite( inputdata_t &inputdata )
|
||||
{
|
||||
if (m_target != NULL_STRING)
|
||||
{
|
||||
CBaseEntity *pTarget = NULL;
|
||||
while ((pTarget = gEntList.FindEntityGeneric(pTarget, STRING(m_target), this, inputdata.pActivator)) != NULL)
|
||||
{
|
||||
// Combat characters know how to catch themselves on fire.
|
||||
CBaseCombatCharacter *pBCC = pTarget->MyCombatCharacterPointer();
|
||||
if (pBCC)
|
||||
{
|
||||
// DVS TODO: consider promoting Ignite to CBaseEntity and doing everything here
|
||||
pBCC->Ignite(m_flLifetime);
|
||||
}
|
||||
// Everything else, we handle here.
|
||||
else
|
||||
{
|
||||
CEntityFlame *pFlame = CEntityFlame::Create(pTarget);
|
||||
if (pFlame)
|
||||
{
|
||||
pFlame->SetLifetime(m_flLifetime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Creates a flame and attaches it to a target entity.
|
||||
// Input : pTarget -
|
||||
//-----------------------------------------------------------------------------
|
||||
CEntityFlame *CEntityFlame::Create( CBaseEntity *pTarget, bool useHitboxes )
|
||||
{
|
||||
CEntityFlame *pFlame = (CEntityFlame *) CreateEntityByName( "entityflame" );
|
||||
|
||||
if ( pFlame == NULL )
|
||||
return NULL;
|
||||
|
||||
float xSize = pTarget->CollisionProp()->OBBMaxs().x - pTarget->CollisionProp()->OBBMins().x;
|
||||
float ySize = pTarget->CollisionProp()->OBBMaxs().y - pTarget->CollisionProp()->OBBMins().y;
|
||||
|
||||
float size = ( xSize + ySize ) * 0.5f;
|
||||
|
||||
if ( size < 16.0f )
|
||||
{
|
||||
size = 16.0f;
|
||||
}
|
||||
|
||||
UTIL_SetOrigin( pFlame, pTarget->GetAbsOrigin() );
|
||||
|
||||
pFlame->m_flSize = size;
|
||||
pFlame->SetThink( &CEntityFlame::FlameThink );
|
||||
pFlame->SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
|
||||
pFlame->AttachToEntity( pTarget );
|
||||
pFlame->SetLifetime( 2.0f );
|
||||
|
||||
//Send to the client even though we don't have a model
|
||||
pFlame->AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
|
||||
|
||||
pFlame->SetUseHitboxes( useHitboxes );
|
||||
|
||||
return pFlame;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Attaches the flame to an entity and moves with it
|
||||
// Input : pTarget - target entity to attach to
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityFlame::AttachToEntity( CBaseEntity *pTarget )
|
||||
{
|
||||
// For networking to the client.
|
||||
m_hEntAttached = pTarget;
|
||||
|
||||
if( pTarget->IsNPC() )
|
||||
{
|
||||
EmitSound( "General.BurningFlesh" );
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitSound( "General.BurningObject" );
|
||||
}
|
||||
|
||||
m_bPlayingSound = true;
|
||||
|
||||
// So our heat emitter follows the entity around on the server.
|
||||
SetParent( pTarget );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : lifetime -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityFlame::SetLifetime( float lifetime )
|
||||
{
|
||||
m_flLifetime = gpGlobals->curtime + lifetime;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : use -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityFlame::SetUseHitboxes( bool use )
|
||||
{
|
||||
m_bUseHitboxes = use;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : iNumHitBoxFires -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityFlame::SetNumHitboxFires( int iNumHitboxFires )
|
||||
{
|
||||
m_iNumHitboxFires = iNumHitboxFires;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flHitboxFireScale -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityFlame::SetHitboxFireScale( float flHitboxFireScale )
|
||||
{
|
||||
m_flHitboxFireScale = flHitboxFireScale;
|
||||
}
|
||||
|
||||
float CEntityFlame::GetRemainingLife( void )
|
||||
{
|
||||
return m_flLifetime - gpGlobals->curtime;
|
||||
}
|
||||
|
||||
int CEntityFlame::GetNumHitboxFires( void )
|
||||
{
|
||||
return m_iNumHitboxFires;
|
||||
}
|
||||
|
||||
float CEntityFlame::GetHitboxFireScale( void )
|
||||
{
|
||||
return m_flHitboxFireScale;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Burn targets around us
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityFlame::FlameThink( void )
|
||||
{
|
||||
// Assure that this function will be ticked again even if we early-out in the if below.
|
||||
SetNextThink( gpGlobals->curtime + FLAME_DAMAGE_INTERVAL );
|
||||
|
||||
if ( m_hEntAttached )
|
||||
{
|
||||
if ( m_hEntAttached->GetFlags() & FL_TRANSRAGDOLL )
|
||||
{
|
||||
SetRenderColorA( 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
CAI_BaseNPC *pNPC = m_hEntAttached->MyNPCPointer();
|
||||
if ( pNPC && !pNPC->IsAlive() )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
// Notify the NPC that it's no longer burning!
|
||||
pNPC->Extinguish();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_hEntAttached->GetWaterLevel() > 0 )
|
||||
{
|
||||
Vector mins, maxs;
|
||||
|
||||
mins = m_hEntAttached->WorldSpaceCenter();
|
||||
maxs = mins;
|
||||
|
||||
maxs.z = m_hEntAttached->WorldSpaceCenter().z;
|
||||
maxs.x += 32;
|
||||
maxs.y += 32;
|
||||
|
||||
mins.z -= 32;
|
||||
mins.x -= 32;
|
||||
mins.y -= 32;
|
||||
|
||||
UTIL_Bubbles( mins, maxs, 12 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
|
||||
// See if we're done burning, or our attached ent has vanished
|
||||
if ( m_flLifetime < gpGlobals->curtime || m_hEntAttached == NULL )
|
||||
{
|
||||
EmitSound( "General.StopBurning" );
|
||||
m_bPlayingSound = false;
|
||||
SetThink( &CEntityFlame::SUB_Remove );
|
||||
SetNextThink( gpGlobals->curtime + 0.5f );
|
||||
|
||||
// Notify anything we're attached to
|
||||
if ( m_hEntAttached )
|
||||
{
|
||||
CBaseCombatCharacter *pAttachedCC = m_hEntAttached->MyCombatCharacterPointer();
|
||||
|
||||
if( pAttachedCC )
|
||||
{
|
||||
// Notify the NPC that it's no longer burning!
|
||||
pAttachedCC->Extinguish();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_hEntAttached )
|
||||
{
|
||||
// Do radius damage ignoring the entity I'm attached to. This will harm things around me.
|
||||
RadiusDamage( CTakeDamageInfo( this, this, 4.0f, DMG_BURN ), GetAbsOrigin(), m_flSize/2, CLASS_NONE, m_hEntAttached );
|
||||
|
||||
// Directly harm the entity I'm attached to. This is so we can precisely control how much damage the entity
|
||||
// that is on fire takes without worrying about the flame's position relative to the bodytarget (which is the
|
||||
// distance that the radius damage code uses to determine how much damage to inflict)
|
||||
m_hEntAttached->TakeDamage( CTakeDamageInfo( this, this, FLAME_DIRECT_DAMAGE, DMG_BURN | DMG_DIRECT ) );
|
||||
|
||||
if( !m_hEntAttached->IsNPC() && hl2_episodic.GetBool() )
|
||||
{
|
||||
const float ENTITYFLAME_MOVE_AWAY_DIST = 24.0f;
|
||||
// Make a sound near my origin, and up a little higher (in case I'm on the ground, so NPC's still hear it)
|
||||
CSoundEnt::InsertSound( SOUND_MOVE_AWAY, GetAbsOrigin(), ENTITYFLAME_MOVE_AWAY_DIST, 0.1f, this, SOUNDENT_CHANNEL_REPEATED_DANGER );
|
||||
CSoundEnt::InsertSound( SOUND_MOVE_AWAY, GetAbsOrigin() + Vector( 0, 0, 48.0f ), ENTITYFLAME_MOVE_AWAY_DIST, 0.1f, this, SOUNDENT_CHANNEL_REPEATING );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RadiusDamage( CTakeDamageInfo( this, this, FLAME_RADIUS_DAMAGE, DMG_BURN ), GetAbsOrigin(), m_flSize/2, CLASS_NONE, NULL );
|
||||
}
|
||||
|
||||
FireSystem_AddHeatInRadius( GetAbsOrigin(), m_flSize/2, 2.0f );
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : pEnt -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CreateEntityFlame(CBaseEntity *pEnt)
|
||||
{
|
||||
CEntityFlame::Create( pEnt );
|
||||
}
|
||||
66
sp/src/game/server/EntityFlame.h
Normal file
66
sp/src/game/server/EntityFlame.h
Normal file
@@ -0,0 +1,66 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef ENTITYFLAME_H
|
||||
#define ENTITYFLAME_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#define FLAME_DAMAGE_INTERVAL 0.2f // How often to deal damage.
|
||||
#define FLAME_DIRECT_DAMAGE_PER_SEC 5.0f
|
||||
#define FLAME_RADIUS_DAMAGE_PER_SEC 4.0f
|
||||
|
||||
#define FLAME_DIRECT_DAMAGE ( FLAME_DIRECT_DAMAGE_PER_SEC * FLAME_DAMAGE_INTERVAL )
|
||||
#define FLAME_RADIUS_DAMAGE ( FLAME_RADIUS_DAMAGE_PER_SEC * FLAME_DAMAGE_INTERVAL )
|
||||
|
||||
#define FLAME_MAX_LIFETIME_ON_DEAD_NPCS 10.0f
|
||||
|
||||
class CEntityFlame : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_CLASS( CEntityFlame, CBaseEntity );
|
||||
|
||||
CEntityFlame( void );
|
||||
|
||||
static CEntityFlame *Create( CBaseEntity *pTarget, bool useHitboxes = true );
|
||||
|
||||
void AttachToEntity( CBaseEntity *pTarget );
|
||||
void SetLifetime( float lifetime );
|
||||
void SetUseHitboxes( bool use );
|
||||
void SetNumHitboxFires( int iNumHitBoxFires );
|
||||
void SetHitboxFireScale( float flHitboxFireScale );
|
||||
|
||||
float GetRemainingLife( void );
|
||||
int GetNumHitboxFires( void );
|
||||
float GetHitboxFireScale( void );
|
||||
|
||||
virtual void Precache();
|
||||
virtual void UpdateOnRemove();
|
||||
|
||||
void SetSize( float size ) { m_flSize = size; }
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
protected:
|
||||
|
||||
void InputIgnite( inputdata_t &inputdata );
|
||||
|
||||
void FlameThink( void );
|
||||
|
||||
CNetworkHandle( CBaseEntity, m_hEntAttached ); // The entity that we are burning (attached to).
|
||||
|
||||
CNetworkVar( float, m_flSize );
|
||||
CNetworkVar( bool, m_bUseHitboxes );
|
||||
CNetworkVar( int, m_iNumHitboxFires );
|
||||
CNetworkVar( float, m_flHitboxFireScale );
|
||||
|
||||
CNetworkVar( float, m_flLifetime );
|
||||
bool m_bPlayingSound;
|
||||
};
|
||||
|
||||
#endif // ENTITYFLAME_H
|
||||
207
sp/src/game/server/EntityParticleTrail.cpp
Normal file
207
sp/src/game/server/EntityParticleTrail.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Drops particles where the entity was.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "EntityParticleTrail.h"
|
||||
#include "networkstringtable_gamedll.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Used to retire the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
static const char *s_pRetireContext = "RetireContext";
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Save/load
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_DATADESC( CEntityParticleTrail )
|
||||
|
||||
DEFINE_FIELD( m_iMaterialName, FIELD_MATERIALINDEX ),
|
||||
DEFINE_EMBEDDED( m_Info ),
|
||||
DEFINE_FIELD( m_hConstraintEntity, FIELD_EHANDLE ),
|
||||
|
||||
// Think this should be handled by StartTouch/etc.
|
||||
// DEFINE_FIELD( m_nRefCount, FIELD_INTEGER ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Networking
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_SERVERCLASS_ST( CEntityParticleTrail, DT_EntityParticleTrail )
|
||||
SendPropInt(SENDINFO(m_iMaterialName), MAX_MATERIAL_STRING_BITS, SPROP_UNSIGNED ),
|
||||
SendPropDataTable( SENDINFO_DT( m_Info ), &REFERENCE_SEND_TABLE( DT_EntityParticleTrailInfo ) ),
|
||||
SendPropEHandle(SENDINFO(m_hConstraintEntity)),
|
||||
END_SEND_TABLE()
|
||||
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_particle_trail, CEntityParticleTrail );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Creates a flame and attaches it to a target entity.
|
||||
// Input : pTarget -
|
||||
//-----------------------------------------------------------------------------
|
||||
CEntityParticleTrail *CEntityParticleTrail::Create( CBaseEntity *pTarget, const EntityParticleTrailInfo_t &info, CBaseEntity *pConstraintEntity )
|
||||
{
|
||||
int iMaterialName = GetMaterialIndex( STRING(info.m_strMaterialName) );
|
||||
|
||||
// Look for other particle trails on the entity + copy state to the new entity
|
||||
CEntityParticleTrail *pTrail;
|
||||
CBaseEntity *pNext;
|
||||
for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext )
|
||||
{
|
||||
pNext = pChild->NextMovePeer();
|
||||
pTrail = dynamic_cast<CEntityParticleTrail*>(pChild);
|
||||
if ( pTrail && (pTrail->m_iMaterialName == iMaterialName) )
|
||||
{
|
||||
// Prevent destruction if it re-enters the field
|
||||
pTrail->IncrementRefCount();
|
||||
return pTrail;
|
||||
}
|
||||
}
|
||||
|
||||
pTrail = (CEntityParticleTrail *)CreateEntityByName( "env_particle_trail" );
|
||||
if ( pTrail == NULL )
|
||||
return NULL;
|
||||
|
||||
pTrail->m_hConstraintEntity = pConstraintEntity;
|
||||
pTrail->m_iMaterialName = iMaterialName;
|
||||
pTrail->m_Info.CopyFrom(info);
|
||||
pTrail->m_nRefCount = 1;
|
||||
pTrail->AttachToEntity( pTarget );
|
||||
pTrail->Spawn();
|
||||
return pTrail;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Spawn
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityParticleTrail::Spawn()
|
||||
{
|
||||
BaseClass::Spawn();
|
||||
|
||||
/*
|
||||
SetThink( &CEntityParticleTrail::BoogieThink );
|
||||
SetNextThink( gpGlobals->curtime + 0.01f );
|
||||
|
||||
if ( HasSpawnFlags( SF_RAGDOLL_BOOGIE_ELECTRICAL ) )
|
||||
{
|
||||
SetContextThink( ZapThink, gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ), s_pZapContext );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Spawn
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityParticleTrail::UpdateOnRemove()
|
||||
{
|
||||
g_pNotify->ClearEntity( this );
|
||||
|
||||
BaseClass::UpdateOnRemove();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Force our constraint entity to be trasmitted
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityParticleTrail::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways )
|
||||
{
|
||||
// Are we already marked for transmission?
|
||||
if ( pInfo->m_pTransmitEdict->Get( entindex() ) )
|
||||
return;
|
||||
|
||||
BaseClass::SetTransmit( pInfo, bAlways );
|
||||
|
||||
// Force our constraint entity to be sent too.
|
||||
if ( m_hConstraintEntity )
|
||||
{
|
||||
m_hConstraintEntity->SetTransmit( pInfo, bAlways );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Retire
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityParticleTrail::IncrementRefCount()
|
||||
{
|
||||
if ( m_nRefCount == 0 )
|
||||
{
|
||||
SetContextThink( NULL, gpGlobals->curtime, s_pRetireContext );
|
||||
}
|
||||
++m_nRefCount;
|
||||
}
|
||||
|
||||
void CEntityParticleTrail::DecrementRefCount()
|
||||
{
|
||||
--m_nRefCount;
|
||||
Assert( m_nRefCount >= 0 );
|
||||
if ( m_nRefCount == 0 )
|
||||
{
|
||||
FollowEntity( NULL );
|
||||
g_pNotify->ClearEntity( this );
|
||||
SetContextThink( &CEntityParticleTrail::SUB_Remove, gpGlobals->curtime + m_Info.m_flLifetime, s_pRetireContext );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Clean up when the entity goes away.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityParticleTrail::NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms )
|
||||
{
|
||||
BaseClass::NotifySystemEvent( pNotify, eventType, params );
|
||||
Assert( pNotify == GetMoveParent() );
|
||||
if ( eventType == NOTIFY_EVENT_DESTROY )
|
||||
{
|
||||
FollowEntity( NULL );
|
||||
g_pNotify->ClearEntity( this );
|
||||
if ( m_nRefCount != 0 )
|
||||
{
|
||||
m_nRefCount = 0;
|
||||
SetContextThink( &CEntityParticleTrail::SUB_Remove, gpGlobals->curtime + m_Info.m_flLifetime, s_pRetireContext );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Suppression count
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityParticleTrail::Destroy( CBaseEntity *pTarget, const EntityParticleTrailInfo_t &info )
|
||||
{
|
||||
int iMaterialName = GetMaterialIndex( STRING(info.m_strMaterialName) );
|
||||
|
||||
// Look for the particle trail attached to this entity + decrease refcount
|
||||
CBaseEntity *pNext;
|
||||
for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext )
|
||||
{
|
||||
pNext = pChild->NextMovePeer();
|
||||
CEntityParticleTrail *pTrail = dynamic_cast<CEntityParticleTrail*>(pChild);
|
||||
if ( !pTrail || (pTrail->m_iMaterialName != iMaterialName) )
|
||||
continue;
|
||||
|
||||
pTrail->DecrementRefCount();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Attach to an entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityParticleTrail::AttachToEntity( CBaseEntity *pTarget )
|
||||
{
|
||||
FollowEntity( pTarget );
|
||||
g_pNotify->AddEntity( this, pTarget );
|
||||
}
|
||||
52
sp/src/game/server/EntityParticleTrail.h
Normal file
52
sp/src/game/server/EntityParticleTrail.h
Normal file
@@ -0,0 +1,52 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef ENTITYPARTICLETRAIL_H
|
||||
#define ENTITYPARTICLETRAIL_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "baseparticleentity.h"
|
||||
#include "entityparticletrail_shared.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Spawns particles after the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEntityParticleTrail : public CBaseParticleEntity
|
||||
{
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_CLASS( CEntityParticleTrail, CBaseParticleEntity );
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
public:
|
||||
static CEntityParticleTrail *Create( CBaseEntity *pTarget, const EntityParticleTrailInfo_t &info, CBaseEntity *pConstraint );
|
||||
static void Destroy( CBaseEntity *pTarget, const EntityParticleTrailInfo_t &info );
|
||||
|
||||
void Spawn();
|
||||
virtual void UpdateOnRemove();
|
||||
|
||||
// Force our constraint entity to be trasmitted
|
||||
virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways );
|
||||
|
||||
// Clean up when the entity goes away.
|
||||
virtual void NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms );
|
||||
|
||||
private:
|
||||
void AttachToEntity( CBaseEntity *pTarget );
|
||||
void IncrementRefCount();
|
||||
void DecrementRefCount();
|
||||
|
||||
CNetworkVar( int, m_iMaterialName );
|
||||
CNetworkVarEmbedded( EntityParticleTrailInfo_t, m_Info );
|
||||
CNetworkHandle( CBaseEntity, m_hConstraintEntity );
|
||||
|
||||
int m_nRefCount;
|
||||
};
|
||||
|
||||
#endif // ENTITYPARTICLETRAIL_H
|
||||
826
sp/src/game/server/EnvBeam.cpp
Normal file
826
sp/src/game/server/EnvBeam.cpp
Normal file
@@ -0,0 +1,826 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "beam_shared.h"
|
||||
#include "ndebugoverlay.h"
|
||||
#include "filters.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// Keeps us from doing strcmps in the tracefilter.
|
||||
string_t g_iszPhysicsPropClassname;
|
||||
|
||||
enum Touch_t
|
||||
{
|
||||
touch_none = 0,
|
||||
touch_player_only,
|
||||
touch_npc_only,
|
||||
touch_player_or_npc,
|
||||
touch_player_or_npc_or_physicsprop,
|
||||
};
|
||||
|
||||
class CEnvBeam : public CBeam
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CEnvBeam, CBeam );
|
||||
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void Activate( void );
|
||||
|
||||
void StrikeThink( void );
|
||||
void UpdateThink( void );
|
||||
void RandomArea( void );
|
||||
void RandomPoint( const Vector &vecSrc );
|
||||
void Zap( const Vector &vecSrc, const Vector &vecDest );
|
||||
|
||||
void Strike( void );
|
||||
|
||||
bool PassesTouchFilters(CBaseEntity *pOther);
|
||||
|
||||
void InputTurnOn( inputdata_t &inputdata );
|
||||
void InputTurnOff( inputdata_t &inputdata );
|
||||
void InputToggle( inputdata_t &inputdata );
|
||||
void InputStrikeOnce( inputdata_t &inputdata );
|
||||
#ifdef MAPBASE
|
||||
void InputAmplitude( inputdata_t &inputdata );
|
||||
void InputSetStartEntity( inputdata_t &inputdata ) { m_iszStartEntity = inputdata.value.StringID(); BeamUpdateVars(); }
|
||||
void InputSetEndEntity( inputdata_t &inputdata ) { m_iszEndEntity = inputdata.value.StringID(); BeamUpdateVars(); }
|
||||
#endif
|
||||
|
||||
void TurnOn( void );
|
||||
void TurnOff( void );
|
||||
void Toggle( void );
|
||||
|
||||
const char *GetDecalName( void ){ return STRING( m_iszDecal );}
|
||||
|
||||
inline bool ServerSide( void )
|
||||
{
|
||||
if ( m_life == 0 && !HasSpawnFlags(SF_BEAM_RING) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
void BeamUpdateVars( void );
|
||||
|
||||
int m_active;
|
||||
int m_spriteTexture;
|
||||
|
||||
string_t m_iszStartEntity;
|
||||
string_t m_iszEndEntity;
|
||||
float m_life;
|
||||
float m_boltWidth;
|
||||
float m_noiseAmplitude;
|
||||
int m_speed;
|
||||
float m_restrike;
|
||||
string_t m_iszSpriteName;
|
||||
int m_frameStart;
|
||||
|
||||
float m_radius;
|
||||
|
||||
Touch_t m_TouchType;
|
||||
string_t m_iFilterName;
|
||||
EHANDLE m_hFilter;
|
||||
|
||||
string_t m_iszDecal;
|
||||
|
||||
COutputEvent m_OnTouchedByEntity;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_beam, CEnvBeam );
|
||||
|
||||
BEGIN_DATADESC( CEnvBeam )
|
||||
|
||||
DEFINE_FIELD( m_active, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_spriteTexture, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_KEYFIELD( m_iszStartEntity, FIELD_STRING, "LightningStart" ),
|
||||
DEFINE_KEYFIELD( m_iszEndEntity, FIELD_STRING, "LightningEnd" ),
|
||||
DEFINE_KEYFIELD( m_life, FIELD_FLOAT, "life" ),
|
||||
DEFINE_KEYFIELD( m_boltWidth, FIELD_FLOAT, "BoltWidth" ),
|
||||
DEFINE_KEYFIELD( m_noiseAmplitude, FIELD_FLOAT, "NoiseAmplitude" ),
|
||||
DEFINE_KEYFIELD( m_speed, FIELD_INTEGER, "TextureScroll" ),
|
||||
DEFINE_KEYFIELD( m_restrike, FIELD_FLOAT, "StrikeTime" ),
|
||||
DEFINE_KEYFIELD( m_iszSpriteName, FIELD_STRING, "texture" ),
|
||||
DEFINE_KEYFIELD( m_frameStart, FIELD_INTEGER, "framestart" ),
|
||||
DEFINE_KEYFIELD( m_radius, FIELD_FLOAT, "Radius" ),
|
||||
DEFINE_KEYFIELD( m_TouchType, FIELD_INTEGER, "TouchType" ),
|
||||
DEFINE_KEYFIELD( m_iFilterName, FIELD_STRING, "filtername" ),
|
||||
DEFINE_KEYFIELD( m_iszDecal, FIELD_STRING, "decalname" ),
|
||||
|
||||
DEFINE_FIELD( m_hFilter, FIELD_EHANDLE ),
|
||||
|
||||
// Function Pointers
|
||||
DEFINE_FUNCTION( StrikeThink ),
|
||||
DEFINE_FUNCTION( UpdateThink ),
|
||||
|
||||
// Input functions
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StrikeOnce", InputStrikeOnce ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "Amplitude", InputAmplitude ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetStartEntity", InputSetStartEntity ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetEndEntity", InputSetEndEntity ),
|
||||
#endif
|
||||
|
||||
DEFINE_OUTPUT( m_OnTouchedByEntity, "OnTouchedByEntity" ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::Spawn( void )
|
||||
{
|
||||
if ( !m_iszSpriteName )
|
||||
{
|
||||
SetThink( &CEnvBeam::SUB_Remove );
|
||||
return;
|
||||
}
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
m_noiseAmplitude = MIN(MAX_BEAM_NOISEAMPLITUDE, m_noiseAmplitude);
|
||||
|
||||
// Check for tapering
|
||||
if ( HasSpawnFlags( SF_BEAM_TAPEROUT ) )
|
||||
{
|
||||
SetWidth( m_boltWidth );
|
||||
SetEndWidth( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWidth( m_boltWidth );
|
||||
SetEndWidth( GetWidth() ); // Note: EndWidth is not scaled
|
||||
}
|
||||
|
||||
if ( ServerSide() )
|
||||
{
|
||||
SetThink( &CEnvBeam::UpdateThink );
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
SetFireTime( gpGlobals->curtime );
|
||||
|
||||
if ( GetEntityName() != NULL_STRING )
|
||||
{
|
||||
if ( !(m_spawnflags & SF_BEAM_STARTON) )
|
||||
{
|
||||
AddEffects( EF_NODRAW );
|
||||
m_active = 0;
|
||||
SetNextThink( TICK_NEVER_THINK );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_active = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_active = 0;
|
||||
if ( !GetEntityName() || FBitSet(m_spawnflags, SF_BEAM_STARTON) )
|
||||
{
|
||||
SetThink( &CEnvBeam::StrikeThink );
|
||||
SetNextThink( gpGlobals->curtime + 1.0f );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::Precache( void )
|
||||
{
|
||||
if ( !Q_stristr( STRING(m_iszSpriteName), ".vmt" ) )
|
||||
{
|
||||
// HACK/YWB: This was almost always the laserbeam.spr, so alloc'ing the name a second time with the proper extension isn't going to
|
||||
// kill us on memrory.
|
||||
//Warning( "Level Design Error: %s (%i:%s) Sprite name (%s) missing .vmt extension!\n",
|
||||
// STRING( m_iClassname ), entindex(), GetEntityName(), STRING(m_iszSpriteName) );
|
||||
|
||||
char fixedname[ 512 ];
|
||||
Q_strncpy( fixedname, STRING( m_iszSpriteName ), sizeof( fixedname ) );
|
||||
|
||||
Q_SetExtension( fixedname, ".vmt", sizeof( fixedname ) );
|
||||
|
||||
m_iszSpriteName = AllocPooledString( fixedname );
|
||||
}
|
||||
|
||||
g_iszPhysicsPropClassname = AllocPooledString( "prop_physics" );
|
||||
|
||||
m_spriteTexture = PrecacheModel( STRING(m_iszSpriteName) );
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::Activate( void )
|
||||
{
|
||||
// Get a handle to my filter entity if there is one
|
||||
if (m_iFilterName != NULL_STRING)
|
||||
{
|
||||
m_hFilter = dynamic_cast<CBaseFilter *>(gEntList.FindEntityByName( NULL, m_iFilterName ));
|
||||
}
|
||||
|
||||
BaseClass::Activate();
|
||||
|
||||
if ( ServerSide() )
|
||||
BeamUpdateVars();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler to turn the lightning on either continually or for
|
||||
// interval refiring.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::InputTurnOn( inputdata_t &inputdata )
|
||||
{
|
||||
if ( !m_active )
|
||||
{
|
||||
TurnOn();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler to turn the lightning off.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::InputTurnOff( inputdata_t &inputdata )
|
||||
{
|
||||
if ( m_active )
|
||||
{
|
||||
TurnOff();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler to toggle the lightning on/off.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::InputToggle( inputdata_t &inputdata )
|
||||
{
|
||||
if ( m_active )
|
||||
{
|
||||
TurnOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
TurnOn();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler for making the beam strike once. This will not affect
|
||||
// any interval refiring that might be going on. If the lifetime is set
|
||||
// to zero (infinite) it will turn on and stay on.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::InputStrikeOnce( inputdata_t &inputdata )
|
||||
{
|
||||
Strike();
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler for amplitude
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::InputAmplitude( inputdata_t &inputdata )
|
||||
{
|
||||
m_noiseAmplitude = inputdata.value.Float();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Turns the lightning on. If it is set for interval refiring, it will
|
||||
// begin doing so. If it is set to be continually on, it will do so.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::TurnOn( void )
|
||||
{
|
||||
m_active = 1;
|
||||
|
||||
if ( ServerSide() )
|
||||
{
|
||||
RemoveEffects( EF_NODRAW );
|
||||
DoSparks( GetAbsStartPos(), GetAbsEndPos() );
|
||||
|
||||
SetThink( &CEnvBeam::UpdateThink );
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
SetFireTime( gpGlobals->curtime );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetThink( &CEnvBeam::StrikeThink );
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::TurnOff( void )
|
||||
{
|
||||
m_active = 0;
|
||||
|
||||
if ( ServerSide() )
|
||||
{
|
||||
AddEffects( EF_NODRAW );
|
||||
}
|
||||
|
||||
SetNextThink( TICK_NEVER_THINK );
|
||||
SetThink( NULL );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Think function for striking at intervals.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::StrikeThink( void )
|
||||
{
|
||||
if ( m_life != 0 )
|
||||
{
|
||||
if ( m_spawnflags & SF_BEAM_RANDOM )
|
||||
SetNextThink( gpGlobals->curtime + m_life + random->RandomFloat( 0, m_restrike ) );
|
||||
else
|
||||
SetNextThink( gpGlobals->curtime + m_life + m_restrike );
|
||||
}
|
||||
m_active = 1;
|
||||
|
||||
if (!m_iszEndEntity)
|
||||
{
|
||||
if (!m_iszStartEntity)
|
||||
{
|
||||
RandomArea( );
|
||||
}
|
||||
else
|
||||
{
|
||||
CBaseEntity *pStart = RandomTargetname( STRING(m_iszStartEntity) );
|
||||
if (pStart != NULL)
|
||||
{
|
||||
RandomPoint( pStart->GetAbsOrigin() );
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "env_beam: unknown entity \"%s\"\n", STRING(m_iszStartEntity) );
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Strike();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Strikes once for its configured lifetime.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::Strike( void )
|
||||
{
|
||||
CBroadcastRecipientFilter filter;
|
||||
|
||||
CBaseEntity *pStart = RandomTargetname( STRING(m_iszStartEntity) );
|
||||
CBaseEntity *pEnd = RandomTargetname( STRING(m_iszEndEntity) );
|
||||
|
||||
if ( pStart == NULL || pEnd == NULL )
|
||||
return;
|
||||
|
||||
m_speed = clamp( (int) m_speed, 0, (int) MAX_BEAM_SCROLLSPEED );
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool pointStart = IsStaticPointEntity( pStart );
|
||||
bool pointEnd = IsStaticPointEntity( pEnd );
|
||||
#else
|
||||
int pointStart = IsStaticPointEntity( pStart );
|
||||
int pointEnd = IsStaticPointEntity( pEnd );
|
||||
#endif
|
||||
|
||||
if ( pointStart || pointEnd )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if ( m_spawnflags & SF_BEAM_RING )
|
||||
{
|
||||
te->BeamRing( filter, 0.0,
|
||||
pStart->entindex(),
|
||||
pEnd->entindex(),
|
||||
m_spriteTexture,
|
||||
0, // No halo
|
||||
m_frameStart,
|
||||
(int)m_flFrameRate,
|
||||
m_life,
|
||||
m_boltWidth,
|
||||
0, // No spread
|
||||
m_noiseAmplitude,
|
||||
m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a,
|
||||
m_speed );
|
||||
}
|
||||
else
|
||||
{
|
||||
te->BeamEntPoint( filter, 0.0,
|
||||
pStart->entindex(),
|
||||
&pStart->GetAbsOrigin(),
|
||||
pEnd->entindex(),
|
||||
&pEnd->GetAbsOrigin(),
|
||||
m_spriteTexture,
|
||||
0, // No halo
|
||||
m_frameStart,
|
||||
(int)m_flFrameRate,
|
||||
m_life,
|
||||
m_boltWidth,
|
||||
m_boltWidth, // End width
|
||||
0, // No fade
|
||||
m_noiseAmplitude,
|
||||
m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a,
|
||||
m_speed );
|
||||
}
|
||||
#else
|
||||
if ( m_spawnflags & SF_BEAM_RING )
|
||||
{
|
||||
// don't work
|
||||
return;
|
||||
}
|
||||
|
||||
te->BeamEntPoint( filter, 0.0,
|
||||
pointStart ? 0 : pStart->entindex(),
|
||||
pointStart ? &pStart->GetAbsOrigin() : NULL,
|
||||
pointEnd ? 0 : pEnd->entindex(),
|
||||
pointEnd ? &pEnd->GetAbsOrigin() : NULL,
|
||||
m_spriteTexture,
|
||||
0, // No halo
|
||||
m_frameStart,
|
||||
(int)m_flFrameRate,
|
||||
m_life,
|
||||
m_boltWidth,
|
||||
m_boltWidth, // End width
|
||||
0, // No fade
|
||||
m_noiseAmplitude,
|
||||
m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a,
|
||||
m_speed );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_spawnflags & SF_BEAM_RING)
|
||||
{
|
||||
te->BeamRing( filter, 0.0,
|
||||
pStart->entindex(),
|
||||
pEnd->entindex(),
|
||||
m_spriteTexture,
|
||||
0, // No halo
|
||||
m_frameStart,
|
||||
(int)m_flFrameRate,
|
||||
m_life,
|
||||
m_boltWidth,
|
||||
0, // No spread
|
||||
m_noiseAmplitude,
|
||||
m_clrRender->r,
|
||||
m_clrRender->g,
|
||||
m_clrRender->b,
|
||||
m_clrRender->a,
|
||||
m_speed );
|
||||
}
|
||||
else
|
||||
{
|
||||
te->BeamEnts( filter, 0.0,
|
||||
pStart->entindex(),
|
||||
pEnd->entindex(),
|
||||
m_spriteTexture,
|
||||
0, // No halo
|
||||
m_frameStart,
|
||||
(int)m_flFrameRate,
|
||||
m_life,
|
||||
m_boltWidth,
|
||||
m_boltWidth, // End width
|
||||
0, // No fade
|
||||
m_noiseAmplitude,
|
||||
m_clrRender->r,
|
||||
m_clrRender->g,
|
||||
m_clrRender->b,
|
||||
m_clrRender->a,
|
||||
m_speed );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
DoSparks( pStart->GetAbsOrigin(), pEnd->GetAbsOrigin() );
|
||||
if ( m_flDamage > 0 )
|
||||
{
|
||||
trace_t tr;
|
||||
UTIL_TraceLine( pStart->GetAbsOrigin(), pEnd->GetAbsOrigin(), MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr );
|
||||
BeamDamageInstant( &tr, m_flDamage );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class CTraceFilterPlayersNPCs : public ITraceFilter
|
||||
{
|
||||
public:
|
||||
bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
|
||||
{
|
||||
CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity );
|
||||
if ( pEntity )
|
||||
{
|
||||
if ( pEntity->IsPlayer() || pEntity->MyNPCPointer() )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
virtual TraceType_t GetTraceType() const
|
||||
{
|
||||
return TRACE_ENTITIES_ONLY;
|
||||
}
|
||||
};
|
||||
|
||||
class CTraceFilterPlayersNPCsPhysicsProps : public ITraceFilter
|
||||
{
|
||||
public:
|
||||
bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
|
||||
{
|
||||
CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity );
|
||||
if ( pEntity )
|
||||
{
|
||||
if ( pEntity->IsPlayer() || pEntity->MyNPCPointer() || pEntity->m_iClassname == g_iszPhysicsPropClassname )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
virtual TraceType_t GetTraceType() const
|
||||
{
|
||||
return TRACE_ENTITIES_ONLY;
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CEnvBeam::PassesTouchFilters(CBaseEntity *pOther)
|
||||
{
|
||||
bool fPassedSoFar = false;
|
||||
|
||||
// Touched some player or NPC!
|
||||
if( m_TouchType != touch_npc_only )
|
||||
{
|
||||
if( pOther->IsPlayer() )
|
||||
{
|
||||
fPassedSoFar = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( m_TouchType != touch_player_only )
|
||||
{
|
||||
if( pOther->IsNPC() )
|
||||
{
|
||||
fPassedSoFar = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( m_TouchType == touch_player_or_npc_or_physicsprop )
|
||||
{
|
||||
if( pOther->m_iClassname == g_iszPhysicsPropClassname )
|
||||
{
|
||||
fPassedSoFar = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( fPassedSoFar )
|
||||
{
|
||||
CBaseFilter* pFilter = (CBaseFilter*)(m_hFilter.Get());
|
||||
return (!pFilter) ? true : pFilter->PassesFilter( this, pOther );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::UpdateThink( void )
|
||||
{
|
||||
// Apply damage every 1/10th of a second.
|
||||
if ( ( m_flDamage > 0 ) && ( gpGlobals->curtime >= m_flFireTime + 0.1 ) )
|
||||
{
|
||||
trace_t tr;
|
||||
UTIL_TraceLine( GetAbsStartPos(), GetAbsEndPos(), MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr );
|
||||
BeamDamage( &tr );
|
||||
// BeamDamage calls RelinkBeam, so no need to call it again.
|
||||
}
|
||||
else
|
||||
{
|
||||
RelinkBeam();
|
||||
}
|
||||
|
||||
if( m_TouchType != touch_none )
|
||||
{
|
||||
trace_t tr;
|
||||
Ray_t ray;
|
||||
ray.Init( GetAbsStartPos(), GetAbsEndPos() );
|
||||
|
||||
if( m_TouchType == touch_player_or_npc_or_physicsprop )
|
||||
{
|
||||
CTraceFilterPlayersNPCsPhysicsProps traceFilter;
|
||||
enginetrace->TraceRay( ray, MASK_SHOT, &traceFilter, &tr );
|
||||
}
|
||||
else
|
||||
{
|
||||
CTraceFilterPlayersNPCs traceFilter;
|
||||
enginetrace->TraceRay( ray, MASK_SHOT, &traceFilter, &tr );
|
||||
}
|
||||
|
||||
if( tr.fraction != 1.0 && PassesTouchFilters( tr.m_pEnt ) )
|
||||
{
|
||||
m_OnTouchedByEntity.FireOutput( tr.m_pEnt, this, 0 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &vecSrc -
|
||||
// &vecDest -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::Zap( const Vector &vecSrc, const Vector &vecDest )
|
||||
{
|
||||
CBroadcastRecipientFilter filter;
|
||||
|
||||
te->BeamPoints( filter, 0.0,
|
||||
&vecSrc,
|
||||
&vecDest,
|
||||
m_spriteTexture,
|
||||
0, // No halo
|
||||
m_frameStart,
|
||||
(int)m_flFrameRate,
|
||||
m_life,
|
||||
m_boltWidth,
|
||||
m_boltWidth, // End width
|
||||
0, // No fade
|
||||
m_noiseAmplitude,
|
||||
m_clrRender->r,
|
||||
m_clrRender->g,
|
||||
m_clrRender->b,
|
||||
m_clrRender->a,
|
||||
m_speed );
|
||||
|
||||
DoSparks( vecSrc, vecDest );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::RandomArea( void )
|
||||
{
|
||||
int iLoops = 0;
|
||||
|
||||
for (iLoops = 0; iLoops < 10; iLoops++)
|
||||
{
|
||||
Vector vecSrc = GetAbsOrigin();
|
||||
|
||||
Vector vecDir1 = Vector( random->RandomFloat( -1.0, 1.0 ), random->RandomFloat( -1.0, 1.0 ),random->RandomFloat( -1.0, 1.0 ) );
|
||||
VectorNormalize( vecDir1 );
|
||||
trace_t tr1;
|
||||
UTIL_TraceLine( vecSrc, vecSrc + vecDir1 * m_radius, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr1 );
|
||||
|
||||
if (tr1.fraction == 1.0)
|
||||
continue;
|
||||
|
||||
Vector vecDir2;
|
||||
do {
|
||||
vecDir2 = Vector( random->RandomFloat( -1.0, 1.0 ), random->RandomFloat( -1.0, 1.0 ),random->RandomFloat( -1.0, 1.0 ) );
|
||||
} while (DotProduct(vecDir1, vecDir2 ) > 0);
|
||||
VectorNormalize( vecDir2 );
|
||||
trace_t tr2;
|
||||
UTIL_TraceLine( vecSrc, vecSrc + vecDir2 * m_radius, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr2 );
|
||||
|
||||
if (tr2.fraction == 1.0)
|
||||
continue;
|
||||
|
||||
if ((tr1.endpos - tr2.endpos).Length() < m_radius * 0.1)
|
||||
continue;
|
||||
|
||||
UTIL_TraceLine( tr1.endpos, tr2.endpos, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr2 );
|
||||
|
||||
if (tr2.fraction != 1.0)
|
||||
continue;
|
||||
|
||||
Zap( tr1.endpos, tr2.endpos );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : vecSrc -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::RandomPoint( const Vector &vecSrc )
|
||||
{
|
||||
int iLoops = 0;
|
||||
|
||||
for (iLoops = 0; iLoops < 10; iLoops++)
|
||||
{
|
||||
Vector vecDir1 = Vector( random->RandomFloat( -1.0, 1.0 ), random->RandomFloat( -1.0, 1.0 ),random->RandomFloat( -1.0, 1.0 ) );
|
||||
VectorNormalize( vecDir1 );
|
||||
trace_t tr1;
|
||||
UTIL_TraceLine( vecSrc, vecSrc + vecDir1 * m_radius, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr1 );
|
||||
|
||||
if ((tr1.endpos - vecSrc).Length() < m_radius * 0.1)
|
||||
continue;
|
||||
|
||||
if (tr1.fraction == 1.0)
|
||||
continue;
|
||||
|
||||
Zap( vecSrc, tr1.endpos );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvBeam::BeamUpdateVars( void )
|
||||
{
|
||||
CBaseEntity *pStart = gEntList.FindEntityByName( NULL, m_iszStartEntity );
|
||||
CBaseEntity *pEnd = gEntList.FindEntityByName( NULL, m_iszEndEntity );
|
||||
|
||||
if (( pStart == NULL ) || ( pEnd == NULL ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_nNumBeamEnts = 2;
|
||||
|
||||
m_speed = clamp( (int) m_speed, 0, (int) MAX_BEAM_SCROLLSPEED );
|
||||
|
||||
// NOTE: If the end entity is the beam itself (and the start entity
|
||||
// isn't *also* the beam itself, we've got problems. This is a problem
|
||||
// because SetAbsStartPos actually sets the entity's origin.
|
||||
if ( ( pEnd == this ) && ( pStart != this ) )
|
||||
{
|
||||
DevMsg("env_beams cannot have the end entity be the beam itself\n"
|
||||
"unless the start entity is also the beam itself!\n" );
|
||||
Assert(0);
|
||||
}
|
||||
|
||||
SetModelName( m_iszSpriteName );
|
||||
SetTexture( m_spriteTexture );
|
||||
|
||||
SetType( BEAM_ENTPOINT );
|
||||
|
||||
if ( IsStaticPointEntity( pStart ) )
|
||||
{
|
||||
SetAbsStartPos( pStart->GetAbsOrigin() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetStartEntity( pStart );
|
||||
}
|
||||
|
||||
if ( IsStaticPointEntity( pEnd ) )
|
||||
{
|
||||
SetAbsEndPos( pEnd->GetAbsOrigin() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetEndEntity( pEnd );
|
||||
}
|
||||
|
||||
RelinkBeam();
|
||||
|
||||
SetWidth( MIN(MAX_BEAM_WIDTH, m_boltWidth) );
|
||||
SetNoise( MIN(MAX_BEAM_NOISEAMPLITUDE, m_noiseAmplitude) );
|
||||
SetFrame( m_frameStart );
|
||||
SetScrollRate( m_speed );
|
||||
if ( m_spawnflags & SF_BEAM_SHADEIN )
|
||||
{
|
||||
SetBeamFlags( FBEAM_SHADEIN );
|
||||
}
|
||||
else if ( m_spawnflags & SF_BEAM_SHADEOUT )
|
||||
{
|
||||
SetBeamFlags( FBEAM_SHADEOUT );
|
||||
}
|
||||
}
|
||||
214
sp/src/game/server/EnvFade.cpp
Normal file
214
sp/src/game/server/EnvFade.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "shake.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
class CEnvFade : public CLogicalEntity
|
||||
{
|
||||
private:
|
||||
|
||||
float m_Duration;
|
||||
float m_HoldTime;
|
||||
|
||||
COutputEvent m_OnBeginFade;
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
public:
|
||||
DECLARE_CLASS( CEnvFade, CLogicalEntity );
|
||||
|
||||
virtual void Spawn( void );
|
||||
|
||||
inline float Duration( void ) { return m_Duration; }
|
||||
inline float HoldTime( void ) { return m_HoldTime; }
|
||||
|
||||
inline void SetDuration( float duration ) { m_Duration = duration; }
|
||||
inline void SetHoldTime( float hold ) { m_HoldTime = hold; }
|
||||
|
||||
int DrawDebugTextOverlays(void);
|
||||
|
||||
// Inputs
|
||||
void InputFade( inputdata_t &inputdata );
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_fade, CEnvFade );
|
||||
|
||||
BEGIN_DATADESC( CEnvFade )
|
||||
|
||||
DEFINE_KEYFIELD( m_Duration, FIELD_FLOAT, "duration" ),
|
||||
DEFINE_KEYFIELD( m_HoldTime, FIELD_FLOAT, "holdtime" ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Fade", InputFade ),
|
||||
|
||||
DEFINE_OUTPUT( m_OnBeginFade, "OnBeginFade"),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
|
||||
#define SF_FADE_IN 0x0001 // Fade in, not out
|
||||
#define SF_FADE_MODULATE 0x0002 // Modulate, don't blend
|
||||
#define SF_FADE_ONLYONE 0x0004
|
||||
#define SF_FADE_STAYOUT 0x0008
|
||||
#ifdef MAPBASE
|
||||
#define SF_FADE_DONT_PURGE 0x0016
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvFade::Spawn( void )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler that does the screen fade.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvFade::InputFade( inputdata_t &inputdata )
|
||||
{
|
||||
int fadeFlags = 0;
|
||||
|
||||
if ( m_spawnflags & SF_FADE_IN )
|
||||
{
|
||||
fadeFlags |= FFADE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
fadeFlags |= FFADE_OUT;
|
||||
}
|
||||
|
||||
if ( m_spawnflags & SF_FADE_MODULATE )
|
||||
{
|
||||
fadeFlags |= FFADE_MODULATE;
|
||||
}
|
||||
|
||||
if ( m_spawnflags & SF_FADE_STAYOUT )
|
||||
{
|
||||
fadeFlags |= FFADE_STAYOUT;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( !HasSpawnFlags(SF_FADE_DONT_PURGE) )
|
||||
{
|
||||
fadeFlags |= FFADE_PURGE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( m_spawnflags & SF_FADE_ONLYONE )
|
||||
{
|
||||
if ( inputdata.pActivator && inputdata.pActivator->IsNetClient() )
|
||||
{
|
||||
UTIL_ScreenFade( inputdata.pActivator, m_clrRender, Duration(), HoldTime(), fadeFlags );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
UTIL_ScreenFadeAll( m_clrRender, Duration(), HoldTime(), fadeFlags );
|
||||
#else
|
||||
UTIL_ScreenFadeAll( m_clrRender, Duration(), HoldTime(), fadeFlags|FFADE_PURGE );
|
||||
#endif
|
||||
}
|
||||
|
||||
m_OnBeginFade.FireOutput( inputdata.pActivator, this );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Fetches the arguments from the command line for the fadein and fadeout
|
||||
// console commands.
|
||||
// Input : flTime - Returns the fade time in seconds (the time to fade in or out)
|
||||
// clrFade - Returns the color to fade to or from.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void GetFadeParms( const CCommand &args, float &flTime, color32 &clrFade)
|
||||
{
|
||||
flTime = 2.0f;
|
||||
|
||||
if ( args.ArgC() > 1 )
|
||||
{
|
||||
flTime = atof( args[1] );
|
||||
}
|
||||
|
||||
clrFade.r = 0;
|
||||
clrFade.g = 0;
|
||||
clrFade.b = 0;
|
||||
clrFade.a = 255;
|
||||
|
||||
if ( args.ArgC() > 4 )
|
||||
{
|
||||
clrFade.r = atoi( args[2] );
|
||||
clrFade.g = atoi( args[3] );
|
||||
clrFade.b = atoi( args[4] );
|
||||
|
||||
if ( args.ArgC() == 5 )
|
||||
{
|
||||
clrFade.a = atoi( args[5] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Console command to fade out to a given color.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void CC_FadeOut( const CCommand &args )
|
||||
{
|
||||
float flTime;
|
||||
color32 clrFade;
|
||||
GetFadeParms( args, flTime, clrFade );
|
||||
|
||||
CBasePlayer *pPlayer = UTIL_GetCommandClient();
|
||||
UTIL_ScreenFade( pPlayer, clrFade, flTime, 0, FFADE_OUT | FFADE_PURGE | FFADE_STAYOUT );
|
||||
}
|
||||
static ConCommand fadeout("fadeout", CC_FadeOut, "fadeout {time r g b}: Fades the screen to black or to the specified color over the given number of seconds.", FCVAR_CHEAT );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Console command to fade in from a given color.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void CC_FadeIn( const CCommand &args )
|
||||
{
|
||||
float flTime;
|
||||
color32 clrFade;
|
||||
GetFadeParms( args, flTime, clrFade );
|
||||
|
||||
CBasePlayer *pPlayer = UTIL_GetCommandClient();
|
||||
UTIL_ScreenFade( pPlayer, clrFade, flTime, 0, FFADE_IN | FFADE_PURGE );
|
||||
}
|
||||
|
||||
static ConCommand fadein("fadein", CC_FadeIn, "fadein {time r g b}: Fades the screen in from black or from the specified color over the given number of seconds.", FCVAR_CHEAT );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Draw any debug text overlays
|
||||
// Output : Current text offset from the top
|
||||
//-----------------------------------------------------------------------------
|
||||
int CEnvFade::DrawDebugTextOverlays( void )
|
||||
{
|
||||
int text_offset = BaseClass::DrawDebugTextOverlays();
|
||||
|
||||
if (m_debugOverlays & OVERLAY_TEXT_BIT)
|
||||
{
|
||||
char tempstr[512];
|
||||
|
||||
// print duration
|
||||
Q_snprintf(tempstr,sizeof(tempstr)," duration: %f", m_Duration);
|
||||
EntityText(text_offset,tempstr,0);
|
||||
text_offset++;
|
||||
|
||||
// print hold time
|
||||
Q_snprintf(tempstr,sizeof(tempstr)," hold time: %f", m_HoldTime);
|
||||
EntityText(text_offset,tempstr,0);
|
||||
text_offset++;
|
||||
}
|
||||
return text_offset;
|
||||
}
|
||||
157
sp/src/game/server/EnvHudHint.cpp
Normal file
157
sp/src/game/server/EnvHudHint.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "baseentity.h"
|
||||
#include "entityoutput.h"
|
||||
#include "recipientfilter.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define SF_HUDHINT_ALLPLAYERS 0x0001
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEnvHudHint : public CPointEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CEnvHudHint, CPointEntity );
|
||||
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
|
||||
private:
|
||||
inline bool AllPlayers( void ) { return (m_spawnflags & SF_HUDHINT_ALLPLAYERS) != 0; }
|
||||
|
||||
void InputShowHudHint( inputdata_t &inputdata );
|
||||
void InputHideHudHint( inputdata_t &inputdata );
|
||||
#ifdef MAPBASE
|
||||
void InputSetHudHint( inputdata_t &inputdata );
|
||||
#endif
|
||||
string_t m_iszMessage;
|
||||
DECLARE_DATADESC();
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_hudhint, CEnvHudHint );
|
||||
|
||||
BEGIN_DATADESC( CEnvHudHint )
|
||||
|
||||
DEFINE_KEYFIELD( m_iszMessage, FIELD_STRING, "message" ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ShowHudHint", InputShowHudHint ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "HideHudHint", InputHideHudHint ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetHudHint", InputSetHudHint ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvHudHint::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
|
||||
SetSolid( SOLID_NONE );
|
||||
SetMoveType( MOVETYPE_NONE );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvHudHint::Precache( void )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler for showing the message and/or playing the sound.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvHudHint::InputShowHudHint( inputdata_t &inputdata )
|
||||
{
|
||||
if ( AllPlayers() )
|
||||
{
|
||||
CReliableBroadcastRecipientFilter user;
|
||||
UserMessageBegin( user, "KeyHintText" );
|
||||
WRITE_BYTE( 1 ); // one message
|
||||
WRITE_STRING( STRING(m_iszMessage) );
|
||||
MessageEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
CBaseEntity *pPlayer = NULL;
|
||||
if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() )
|
||||
{
|
||||
pPlayer = inputdata.pActivator;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPlayer = UTIL_GetLocalPlayer();
|
||||
}
|
||||
|
||||
if ( !pPlayer || !pPlayer->IsNetClient() )
|
||||
return;
|
||||
|
||||
CSingleUserRecipientFilter user( (CBasePlayer *)pPlayer );
|
||||
user.MakeReliable();
|
||||
UserMessageBegin( user, "KeyHintText" );
|
||||
WRITE_BYTE( 1 ); // one message
|
||||
WRITE_STRING( STRING(m_iszMessage) );
|
||||
MessageEnd();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvHudHint::InputHideHudHint( inputdata_t &inputdata )
|
||||
{
|
||||
if ( AllPlayers() )
|
||||
{
|
||||
CReliableBroadcastRecipientFilter user;
|
||||
UserMessageBegin( user, "KeyHintText" );
|
||||
WRITE_BYTE( 1 ); // one message
|
||||
WRITE_STRING( STRING(NULL_STRING) );
|
||||
MessageEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
CBaseEntity *pPlayer = NULL;
|
||||
|
||||
if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() )
|
||||
{
|
||||
pPlayer = inputdata.pActivator;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPlayer = UTIL_GetLocalPlayer();
|
||||
}
|
||||
|
||||
if ( !pPlayer || !pPlayer->IsNetClient() )
|
||||
return;
|
||||
|
||||
CSingleUserRecipientFilter user( (CBasePlayer *)pPlayer );
|
||||
user.MakeReliable();
|
||||
UserMessageBegin( user, "KeyHintText" );
|
||||
WRITE_BYTE( 1 ); // one message
|
||||
WRITE_STRING( STRING(NULL_STRING) );
|
||||
MessageEnd();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvHudHint::InputSetHudHint( inputdata_t &inputdata )
|
||||
{
|
||||
m_iszMessage = inputdata.value.StringID();
|
||||
}
|
||||
#endif
|
||||
260
sp/src/game/server/EnvLaser.cpp
Normal file
260
sp/src/game/server/EnvLaser.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: A special kind of beam effect that traces from its start position to
|
||||
// its end position and stops if it hits anything.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "EnvLaser.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_laser, CEnvLaser );
|
||||
|
||||
BEGIN_DATADESC( CEnvLaser )
|
||||
|
||||
DEFINE_KEYFIELD( m_iszLaserTarget, FIELD_STRING, "LaserTarget" ),
|
||||
DEFINE_FIELD( m_pSprite, FIELD_CLASSPTR ),
|
||||
DEFINE_KEYFIELD( m_iszSpriteName, FIELD_STRING, "EndSprite" ),
|
||||
DEFINE_FIELD( m_firePosition, FIELD_VECTOR ),
|
||||
DEFINE_KEYFIELD( m_flStartFrame, FIELD_FLOAT, "framestart" ),
|
||||
|
||||
// Function Pointers
|
||||
DEFINE_FUNCTION( StrikeThink ),
|
||||
|
||||
// Input functions
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_OUTPUT( m_OnTouchedByEntity, "OnTouchedByEntity" ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvLaser::Spawn( void )
|
||||
{
|
||||
if ( !GetModelName() )
|
||||
{
|
||||
SetThink( &CEnvLaser::SUB_Remove );
|
||||
return;
|
||||
}
|
||||
|
||||
SetSolid( SOLID_NONE ); // Remove model & collisions
|
||||
SetThink( &CEnvLaser::StrikeThink );
|
||||
|
||||
SetEndWidth( GetWidth() ); // Note: EndWidth is not scaled
|
||||
|
||||
PointsInit( GetLocalOrigin(), GetLocalOrigin() );
|
||||
|
||||
Precache( );
|
||||
|
||||
if ( !m_pSprite && m_iszSpriteName != NULL_STRING )
|
||||
{
|
||||
m_pSprite = CSprite::SpriteCreate( STRING(m_iszSpriteName), GetAbsOrigin(), TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pSprite = NULL;
|
||||
}
|
||||
|
||||
if ( m_pSprite )
|
||||
{
|
||||
m_pSprite->SetParent( GetMoveParent() );
|
||||
m_pSprite->SetTransparency( kRenderGlow, m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a, m_nRenderFX );
|
||||
}
|
||||
|
||||
if ( GetEntityName() != NULL_STRING && !(m_spawnflags & SF_BEAM_STARTON) )
|
||||
{
|
||||
TurnOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
TurnOn();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvLaser::Precache( void )
|
||||
{
|
||||
SetModelIndex( PrecacheModel( STRING( GetModelName() ) ) );
|
||||
if ( m_iszSpriteName != NULL_STRING )
|
||||
PrecacheModel( STRING(m_iszSpriteName) );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CEnvLaser::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if (FStrEq(szKeyName, "width"))
|
||||
{
|
||||
SetWidth( atof(szValue) );
|
||||
}
|
||||
else if (FStrEq(szKeyName, "NoiseAmplitude"))
|
||||
{
|
||||
SetNoise( atoi(szValue) );
|
||||
}
|
||||
else if (FStrEq(szKeyName, "TextureScroll"))
|
||||
{
|
||||
SetScrollRate( atoi(szValue) );
|
||||
}
|
||||
else if (FStrEq(szKeyName, "texture"))
|
||||
{
|
||||
SetModelName( AllocPooledString(szValue) );
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseClass::KeyValue( szKeyName, szValue );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns whether the laser is currently active.
|
||||
//-----------------------------------------------------------------------------
|
||||
int CEnvLaser::IsOn( void )
|
||||
{
|
||||
if ( IsEffectActive( EF_NODRAW ) )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvLaser::InputTurnOn( inputdata_t &inputdata )
|
||||
{
|
||||
if (!IsOn())
|
||||
{
|
||||
TurnOn();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvLaser::InputTurnOff( inputdata_t &inputdata )
|
||||
{
|
||||
if (IsOn())
|
||||
{
|
||||
TurnOff();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvLaser::InputToggle( inputdata_t &inputdata )
|
||||
{
|
||||
if ( IsOn() )
|
||||
{
|
||||
TurnOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
TurnOn();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvLaser::TurnOff( void )
|
||||
{
|
||||
AddEffects( EF_NODRAW );
|
||||
if ( m_pSprite )
|
||||
m_pSprite->TurnOff();
|
||||
|
||||
SetNextThink( TICK_NEVER_THINK );
|
||||
SetThink( NULL );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvLaser::TurnOn( void )
|
||||
{
|
||||
RemoveEffects( EF_NODRAW );
|
||||
if ( m_pSprite )
|
||||
m_pSprite->TurnOn();
|
||||
|
||||
m_flFireTime = gpGlobals->curtime;
|
||||
|
||||
SetThink( &CEnvLaser::StrikeThink );
|
||||
|
||||
//
|
||||
// Call StrikeThink here to update the end position, otherwise we will see
|
||||
// the beam in the wrong place for one frame since we cleared the nodraw flag.
|
||||
//
|
||||
StrikeThink();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvLaser::FireAtPoint( trace_t &tr )
|
||||
{
|
||||
SetAbsEndPos( tr.endpos );
|
||||
if ( m_pSprite )
|
||||
{
|
||||
UTIL_SetOrigin( m_pSprite, tr.endpos );
|
||||
}
|
||||
|
||||
// Apply damage and do sparks every 1/10th of a second.
|
||||
if ( gpGlobals->curtime >= m_flFireTime + 0.1 )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if ( tr.fraction != 1.0 && tr.m_pEnt && !tr.m_pEnt->IsWorld() )
|
||||
{
|
||||
m_OnTouchedByEntity.FireOutput( tr.m_pEnt, this );
|
||||
}
|
||||
#endif
|
||||
BeamDamage( &tr );
|
||||
DoSparks( GetAbsStartPos(), tr.endpos );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvLaser::StrikeThink( void )
|
||||
{
|
||||
CBaseEntity *pEnd = RandomTargetname( STRING( m_iszLaserTarget ) );
|
||||
|
||||
Vector vecFireAt = GetAbsEndPos();
|
||||
if ( pEnd )
|
||||
{
|
||||
vecFireAt = pEnd->GetAbsOrigin();
|
||||
}
|
||||
|
||||
trace_t tr;
|
||||
|
||||
UTIL_TraceLine( GetAbsOrigin(), vecFireAt, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr );
|
||||
FireAtPoint( tr );
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
|
||||
|
||||
58
sp/src/game/server/EnvLaser.h
Normal file
58
sp/src/game/server/EnvLaser.h
Normal file
@@ -0,0 +1,58 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef ENVLASER_H
|
||||
#define ENVLASER_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "baseentity.h"
|
||||
#include "beam_shared.h"
|
||||
#include "entityoutput.h"
|
||||
|
||||
|
||||
class CSprite;
|
||||
|
||||
|
||||
class CEnvLaser : public CBeam
|
||||
{
|
||||
DECLARE_CLASS( CEnvLaser, CBeam );
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
|
||||
void TurnOn( void );
|
||||
void TurnOff( void );
|
||||
int IsOn( void );
|
||||
|
||||
void FireAtPoint( trace_t &point );
|
||||
void StrikeThink( void );
|
||||
|
||||
void InputTurnOn( inputdata_t &inputdata );
|
||||
void InputTurnOff( inputdata_t &inputdata );
|
||||
void InputToggle( inputdata_t &inputdata );
|
||||
#ifdef MAPBASE
|
||||
void InputSetTarget( inputdata_t &inputdata ) { m_iszLaserTarget = inputdata.value.StringID(); }
|
||||
#endif
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
string_t m_iszLaserTarget; // Name of entity or entities to strike at, randomly picked if more than one match.
|
||||
CSprite *m_pSprite;
|
||||
string_t m_iszSpriteName;
|
||||
Vector m_firePosition;
|
||||
|
||||
#ifdef MAPBASE
|
||||
COutputEvent m_OnTouchedByEntity;
|
||||
#endif
|
||||
|
||||
float m_flStartFrame;
|
||||
};
|
||||
|
||||
#endif // ENVLASER_H
|
||||
307
sp/src/game/server/EnvMessage.cpp
Normal file
307
sp/src/game/server/EnvMessage.cpp
Normal file
@@ -0,0 +1,307 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "EnvMessage.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "KeyValues.h"
|
||||
#include "filesystem.h"
|
||||
#include "Color.h"
|
||||
#include "gamestats.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_message, CMessage );
|
||||
|
||||
BEGIN_DATADESC( CMessage )
|
||||
|
||||
DEFINE_KEYFIELD( m_iszMessage, FIELD_STRING, "message" ),
|
||||
DEFINE_KEYFIELD( m_sNoise, FIELD_SOUNDNAME, "messagesound" ),
|
||||
DEFINE_KEYFIELD( m_MessageAttenuation, FIELD_INTEGER, "messageattenuation" ),
|
||||
DEFINE_KEYFIELD( m_MessageVolume, FIELD_FLOAT, "messagevolume" ),
|
||||
|
||||
DEFINE_FIELD( m_Radius, FIELD_FLOAT ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ShowMessage", InputShowMessage ),
|
||||
|
||||
DEFINE_OUTPUT(m_OnShowMessage, "OnShowMessage"),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMessage::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
|
||||
SetSolid( SOLID_NONE );
|
||||
SetMoveType( MOVETYPE_NONE );
|
||||
|
||||
switch( m_MessageAttenuation )
|
||||
{
|
||||
case 1: // Medium radius
|
||||
m_Radius = ATTN_STATIC;
|
||||
break;
|
||||
|
||||
case 2: // Large radius
|
||||
m_Radius = ATTN_NORM;
|
||||
break;
|
||||
|
||||
case 3: //EVERYWHERE
|
||||
m_Radius = ATTN_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
case 0: // Small radius
|
||||
m_Radius = SNDLVL_IDLE;
|
||||
break;
|
||||
}
|
||||
m_MessageAttenuation = 0;
|
||||
|
||||
// Remap volume from [0,10] to [0,1].
|
||||
m_MessageVolume *= 0.1;
|
||||
|
||||
// No volume, use normal
|
||||
if ( m_MessageVolume <= 0 )
|
||||
{
|
||||
m_MessageVolume = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMessage::Precache( void )
|
||||
{
|
||||
if ( m_sNoise != NULL_STRING )
|
||||
{
|
||||
PrecacheScriptSound( STRING(m_sNoise) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler for showing the message and/or playing the sound.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMessage::InputShowMessage( inputdata_t &inputdata )
|
||||
{
|
||||
CBaseEntity *pPlayer = NULL;
|
||||
|
||||
if ( m_spawnflags & SF_MESSAGE_ALL )
|
||||
{
|
||||
UTIL_ShowMessageAll( STRING( m_iszMessage ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() )
|
||||
{
|
||||
pPlayer = inputdata.pActivator;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPlayer = (gpGlobals->maxClients > 1) ? NULL : UTIL_GetLocalPlayer();
|
||||
}
|
||||
|
||||
if ( pPlayer && pPlayer->IsPlayer() )
|
||||
{
|
||||
UTIL_ShowMessage( STRING( m_iszMessage ), ToBasePlayer( pPlayer ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_sNoise != NULL_STRING )
|
||||
{
|
||||
CPASAttenuationFilter filter( this );
|
||||
|
||||
EmitSound_t ep;
|
||||
ep.m_nChannel = CHAN_BODY;
|
||||
ep.m_pSoundName = (char*)STRING(m_sNoise);
|
||||
ep.m_flVolume = m_MessageVolume;
|
||||
ep.m_SoundLevel = ATTN_TO_SNDLVL( m_Radius );
|
||||
|
||||
EmitSound( filter, entindex(), ep );
|
||||
}
|
||||
|
||||
if ( m_spawnflags & SF_MESSAGE_ONCE )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
}
|
||||
|
||||
m_OnShowMessage.FireOutput( inputdata.pActivator, this );
|
||||
}
|
||||
|
||||
|
||||
void CMessage::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
inputdata_t inputdata;
|
||||
|
||||
inputdata.pActivator = NULL;
|
||||
inputdata.pCaller = NULL;
|
||||
|
||||
InputShowMessage( inputdata );
|
||||
}
|
||||
|
||||
|
||||
class CCredits : public CPointEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CMessage, CPointEntity );
|
||||
DECLARE_DATADESC();
|
||||
|
||||
void Spawn( void );
|
||||
void InputRollCredits( inputdata_t &inputdata );
|
||||
void InputRollOutroCredits( inputdata_t &inputdata );
|
||||
void InputShowLogo( inputdata_t &inputdata );
|
||||
void InputSetLogoLength( inputdata_t &inputdata );
|
||||
|
||||
COutputEvent m_OnCreditsDone;
|
||||
|
||||
virtual void OnRestore();
|
||||
private:
|
||||
|
||||
void RollOutroCredits();
|
||||
|
||||
bool m_bRolledOutroCredits;
|
||||
float m_flLogoLength;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Custom credits.txt, defaults to that
|
||||
string_t m_iszCreditsFile;
|
||||
#endif
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_credits, CCredits );
|
||||
|
||||
BEGIN_DATADESC( CCredits )
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "RollCredits", InputRollCredits ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "RollOutroCredits", InputRollOutroCredits ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ShowLogo", InputShowLogo ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetLogoLength", InputSetLogoLength ),
|
||||
DEFINE_OUTPUT( m_OnCreditsDone, "OnCreditsDone"),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_iszCreditsFile, FIELD_STRING, "CreditsFile" ),
|
||||
#endif
|
||||
|
||||
DEFINE_FIELD( m_bRolledOutroCredits, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( m_flLogoLength, FIELD_FLOAT )
|
||||
END_DATADESC()
|
||||
|
||||
void CCredits::Spawn( void )
|
||||
{
|
||||
SetSolid( SOLID_NONE );
|
||||
SetMoveType( MOVETYPE_NONE );
|
||||
}
|
||||
|
||||
static void CreditsDone_f( void )
|
||||
{
|
||||
CCredits *pCredits = (CCredits*)gEntList.FindEntityByClassname( NULL, "env_credits" );
|
||||
|
||||
if ( pCredits )
|
||||
{
|
||||
pCredits->m_OnCreditsDone.FireOutput( pCredits, pCredits );
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand creditsdone("creditsdone", CreditsDone_f );
|
||||
|
||||
extern ConVar sv_unlockedchapters;
|
||||
|
||||
#ifdef MAPBASE
|
||||
extern int Mapbase_GetChapterCount();
|
||||
#endif
|
||||
|
||||
void CCredits::OnRestore()
|
||||
{
|
||||
BaseClass::OnRestore();
|
||||
|
||||
if ( m_bRolledOutroCredits )
|
||||
{
|
||||
// Roll them again so that the client .dll will send the "creditsdone" message and we'll
|
||||
// actually get back to the main menu
|
||||
RollOutroCredits();
|
||||
}
|
||||
}
|
||||
|
||||
void CCredits::RollOutroCredits()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// Don't set this if we're using Mapbase chapters or if sv_unlockedchapters is already greater than 15
|
||||
if (Mapbase_GetChapterCount() <= 0 && sv_unlockedchapters.GetInt() < 15)
|
||||
#endif
|
||||
sv_unlockedchapters.SetValue( "15" );
|
||||
|
||||
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
|
||||
|
||||
CSingleUserRecipientFilter user( pPlayer );
|
||||
user.MakeReliable();
|
||||
|
||||
UserMessageBegin( user, "CreditsMsg" );
|
||||
WRITE_BYTE( 3 );
|
||||
#ifdef MAPBASE
|
||||
WRITE_STRING( STRING(m_iszCreditsFile) );
|
||||
#endif
|
||||
MessageEnd();
|
||||
}
|
||||
|
||||
void CCredits::InputRollOutroCredits( inputdata_t &inputdata )
|
||||
{
|
||||
RollOutroCredits();
|
||||
|
||||
// In case we save restore
|
||||
m_bRolledOutroCredits = true;
|
||||
|
||||
gamestats->Event_Credits();
|
||||
}
|
||||
|
||||
void CCredits::InputShowLogo( inputdata_t &inputdata )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
|
||||
|
||||
CSingleUserRecipientFilter user( pPlayer );
|
||||
user.MakeReliable();
|
||||
|
||||
if ( m_flLogoLength )
|
||||
{
|
||||
UserMessageBegin( user, "LogoTimeMsg" );
|
||||
WRITE_FLOAT( m_flLogoLength );
|
||||
#ifdef MAPBASE
|
||||
WRITE_STRING( STRING(m_iszCreditsFile) );
|
||||
#endif
|
||||
MessageEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
UserMessageBegin( user, "CreditsMsg" );
|
||||
WRITE_BYTE( 1 );
|
||||
#ifdef MAPBASE
|
||||
WRITE_STRING( STRING(m_iszCreditsFile) );
|
||||
#endif
|
||||
MessageEnd();
|
||||
}
|
||||
}
|
||||
|
||||
void CCredits::InputSetLogoLength( inputdata_t &inputdata )
|
||||
{
|
||||
m_flLogoLength = inputdata.value.Float();
|
||||
}
|
||||
|
||||
void CCredits::InputRollCredits( inputdata_t &inputdata )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
|
||||
|
||||
CSingleUserRecipientFilter user( pPlayer );
|
||||
user.MakeReliable();
|
||||
|
||||
UserMessageBegin( user, "CreditsMsg" );
|
||||
WRITE_BYTE( 2 );
|
||||
#ifdef MAPBASE
|
||||
WRITE_STRING( STRING(m_iszCreditsFile) );
|
||||
#endif
|
||||
MessageEnd();
|
||||
}
|
||||
48
sp/src/game/server/EnvMessage.h
Normal file
48
sp/src/game/server/EnvMessage.h
Normal file
@@ -0,0 +1,48 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef ENVMESSAGE_H
|
||||
#define ENVMESSAGE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "baseentity.h"
|
||||
#include "entityoutput.h"
|
||||
|
||||
|
||||
#define SF_MESSAGE_ONCE 0x0001 // Fade in, not out
|
||||
#define SF_MESSAGE_ALL 0x0002 // Send to all clients
|
||||
|
||||
class CMessage : public CPointEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CMessage, CPointEntity );
|
||||
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
|
||||
inline void SetMessage( string_t iszMessage ) { m_iszMessage = iszMessage; }
|
||||
|
||||
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
|
||||
private:
|
||||
|
||||
void InputShowMessage( inputdata_t &inputdata );
|
||||
|
||||
string_t m_iszMessage; // Message to display.
|
||||
float m_MessageVolume;
|
||||
int m_MessageAttenuation;
|
||||
float m_Radius;
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
string_t m_sNoise;
|
||||
COutputEvent m_OnShowMessage;
|
||||
};
|
||||
|
||||
#endif // ENVMESSAGE_H
|
||||
413
sp/src/game/server/EnvShake.cpp
Normal file
413
sp/src/game/server/EnvShake.cpp
Normal file
@@ -0,0 +1,413 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Implements a screen shake effect that can also shake physics objects.
|
||||
//
|
||||
// NOTE: UTIL_ScreenShake() will only shake players who are on the ground
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "shake.h"
|
||||
#include "physics_saverestore.h"
|
||||
#include "rope.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
class CPhysicsShake : public IMotionEvent
|
||||
{
|
||||
DECLARE_SIMPLE_DATADESC();
|
||||
|
||||
public:
|
||||
virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular )
|
||||
{
|
||||
Vector contact;
|
||||
if ( !pObject->GetContactPoint( &contact, NULL ) )
|
||||
return SIM_NOTHING;
|
||||
|
||||
// fudge the force a bit to make it more dramatic
|
||||
pObject->CalculateForceOffset( m_force * (1.0f + pObject->GetMass()*0.4f), contact, &linear, &angular );
|
||||
|
||||
return SIM_LOCAL_FORCE;
|
||||
}
|
||||
|
||||
Vector m_force;
|
||||
};
|
||||
|
||||
BEGIN_SIMPLE_DATADESC( CPhysicsShake )
|
||||
DEFINE_FIELD( m_force, FIELD_VECTOR ),
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
class CEnvShake : public CPointEntity
|
||||
{
|
||||
private:
|
||||
float m_Amplitude;
|
||||
float m_Frequency;
|
||||
float m_Duration;
|
||||
float m_Radius; // radius of 0 means all players
|
||||
float m_stopTime;
|
||||
float m_nextShake;
|
||||
float m_currentAmp;
|
||||
|
||||
Vector m_maxForce;
|
||||
|
||||
IPhysicsMotionController *m_pShakeController;
|
||||
CPhysicsShake m_shakeCallback;
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
public:
|
||||
DECLARE_CLASS( CEnvShake, CPointEntity );
|
||||
|
||||
~CEnvShake( void );
|
||||
virtual void Spawn( void );
|
||||
virtual void OnRestore( void );
|
||||
|
||||
inline float Amplitude( void ) { return m_Amplitude; }
|
||||
inline float Frequency( void ) { return m_Frequency; }
|
||||
inline float Duration( void ) { return m_Duration; }
|
||||
float Radius( bool bPlayers = true );
|
||||
inline void SetAmplitude( float amplitude ) { m_Amplitude = amplitude; }
|
||||
inline void SetFrequency( float frequency ) { m_Frequency = frequency; }
|
||||
inline void SetDuration( float duration ) { m_Duration = duration; }
|
||||
inline void SetRadius( float radius ) { m_Radius = radius; }
|
||||
|
||||
int DrawDebugTextOverlays(void);
|
||||
|
||||
// Input handlers
|
||||
void InputStartShake( inputdata_t &inputdata );
|
||||
void InputStopShake( inputdata_t &inputdata );
|
||||
void InputAmplitude( inputdata_t &inputdata );
|
||||
void InputFrequency( inputdata_t &inputdata );
|
||||
|
||||
// Causes the camera/physics shakes to happen:
|
||||
void ApplyShake( ShakeCommand_t command );
|
||||
void Think( void );
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_shake, CEnvShake );
|
||||
|
||||
BEGIN_DATADESC( CEnvShake )
|
||||
|
||||
DEFINE_KEYFIELD( m_Amplitude, FIELD_FLOAT, "amplitude" ),
|
||||
DEFINE_KEYFIELD( m_Frequency, FIELD_FLOAT, "frequency" ),
|
||||
DEFINE_KEYFIELD( m_Duration, FIELD_FLOAT, "duration" ),
|
||||
DEFINE_KEYFIELD( m_Radius, FIELD_FLOAT, "radius" ),
|
||||
DEFINE_FIELD( m_stopTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_nextShake, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_currentAmp, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_maxForce, FIELD_VECTOR ),
|
||||
DEFINE_PHYSPTR( m_pShakeController ),
|
||||
DEFINE_EMBEDDED( m_shakeCallback ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StartShake", InputStartShake ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StopShake", InputStopShake ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "Amplitude", InputAmplitude ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "Frequency", InputFrequency ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
|
||||
#define SF_SHAKE_EVERYONE 0x0001 // Don't check radius
|
||||
#define SF_SHAKE_INAIR 0x0004 // Shake players in air
|
||||
#define SF_SHAKE_PHYSICS 0x0008 // Shake physically (not just camera)
|
||||
#define SF_SHAKE_ROPES 0x0010 // Shake ropes too.
|
||||
#define SF_SHAKE_NO_VIEW 0x0020 // DON'T shake the view (only ropes and/or physics objects)
|
||||
#define SF_SHAKE_NO_RUMBLE 0x0040 // DON'T Rumble the XBox Controller
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor.
|
||||
//-----------------------------------------------------------------------------
|
||||
CEnvShake::~CEnvShake( void )
|
||||
{
|
||||
if ( m_pShakeController )
|
||||
{
|
||||
physenv->DestroyMotionController( m_pShakeController );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float CEnvShake::Radius(bool bPlayers)
|
||||
{
|
||||
// The radius for players is zero if SF_SHAKE_EVERYONE is set
|
||||
if ( bPlayers && HasSpawnFlags(SF_SHAKE_EVERYONE))
|
||||
return 0;
|
||||
return m_Radius;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets default member values when spawning.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvShake::Spawn( void )
|
||||
{
|
||||
SetSolid( SOLID_NONE );
|
||||
SetMoveType( MOVETYPE_NONE );
|
||||
|
||||
if ( GetSpawnFlags() & SF_SHAKE_EVERYONE )
|
||||
{
|
||||
m_Radius = 0;
|
||||
}
|
||||
|
||||
if ( HasSpawnFlags( SF_SHAKE_NO_VIEW ) && !HasSpawnFlags( SF_SHAKE_PHYSICS ) && !HasSpawnFlags( SF_SHAKE_ROPES ) )
|
||||
{
|
||||
DevWarning( "env_shake %s with \"Don't shake view\" spawnflag set without \"Shake physics\" or \"Shake ropes\" spawnflags set.", GetDebugName() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Restore the motion controller
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvShake::OnRestore( void )
|
||||
{
|
||||
BaseClass::OnRestore();
|
||||
|
||||
if ( m_pShakeController )
|
||||
{
|
||||
m_pShakeController->SetEventHandler( &m_shakeCallback );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvShake::ApplyShake( ShakeCommand_t command )
|
||||
{
|
||||
if ( !HasSpawnFlags( SF_SHAKE_NO_VIEW ) || !HasSpawnFlags( SF_SHAKE_NO_RUMBLE ) )
|
||||
{
|
||||
bool air = (GetSpawnFlags() & SF_SHAKE_INAIR) ? true : false;
|
||||
UTIL_ScreenShake( GetAbsOrigin(), Amplitude(), Frequency(), Duration(), Radius(), command, air );
|
||||
}
|
||||
|
||||
if ( GetSpawnFlags() & SF_SHAKE_ROPES )
|
||||
{
|
||||
CRopeKeyframe::ShakeRopes( GetAbsOrigin(), Radius(false), Frequency() );
|
||||
}
|
||||
|
||||
if ( GetSpawnFlags() & SF_SHAKE_PHYSICS )
|
||||
{
|
||||
if ( !m_pShakeController )
|
||||
{
|
||||
m_pShakeController = physenv->CreateMotionController( &m_shakeCallback );
|
||||
}
|
||||
// do physics shake
|
||||
switch( command )
|
||||
{
|
||||
case SHAKE_START:
|
||||
case SHAKE_START_NORUMBLE:
|
||||
case SHAKE_START_RUMBLEONLY:
|
||||
{
|
||||
m_stopTime = gpGlobals->curtime + Duration();
|
||||
m_nextShake = 0;
|
||||
m_pShakeController->ClearObjects();
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
m_currentAmp = Amplitude();
|
||||
CBaseEntity *list[1024];
|
||||
float radius = Radius(false);
|
||||
|
||||
// probably checked "Shake Everywhere" do a big radius
|
||||
if ( !radius )
|
||||
{
|
||||
radius = 512;
|
||||
}
|
||||
Vector extents = Vector(radius, radius, radius);
|
||||
extents.z = MAX(extents.z, 100);
|
||||
Vector mins = GetAbsOrigin() - extents;
|
||||
Vector maxs = GetAbsOrigin() + extents;
|
||||
int count = UTIL_EntitiesInBox( list, 1024, mins, maxs, 0 );
|
||||
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
//
|
||||
// Only shake physics entities that players can see. This is one frame out of date
|
||||
// so it's possible that we could miss objects if a player changed PVS this frame.
|
||||
//
|
||||
if ( ( list[i]->GetMoveType() == MOVETYPE_VPHYSICS ) )
|
||||
{
|
||||
IPhysicsObject *pPhys = list[i]->VPhysicsGetObject();
|
||||
if ( pPhys && pPhys->IsMoveable() )
|
||||
{
|
||||
m_pShakeController->AttachObject( pPhys, false );
|
||||
pPhys->Wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SHAKE_STOP:
|
||||
m_pShakeController->ClearObjects();
|
||||
break;
|
||||
case SHAKE_AMPLITUDE:
|
||||
m_currentAmp = Amplitude();
|
||||
case SHAKE_FREQUENCY:
|
||||
m_pShakeController->WakeObjects();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler that starts the screen shake.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvShake::InputStartShake( inputdata_t &inputdata )
|
||||
{
|
||||
if ( HasSpawnFlags( SF_SHAKE_NO_RUMBLE ) )
|
||||
{
|
||||
ApplyShake( SHAKE_START_NORUMBLE );
|
||||
}
|
||||
else if ( HasSpawnFlags( SF_SHAKE_NO_VIEW ) )
|
||||
{
|
||||
ApplyShake( SHAKE_START_RUMBLEONLY );
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyShake( SHAKE_START );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler that stops the screen shake.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvShake::InputStopShake( inputdata_t &inputdata )
|
||||
{
|
||||
ApplyShake( SHAKE_STOP );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles changes to the shake amplitude from an external source.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvShake::InputAmplitude( inputdata_t &inputdata )
|
||||
{
|
||||
SetAmplitude( inputdata.value.Float() );
|
||||
ApplyShake( SHAKE_AMPLITUDE );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles changes to the shake frequency from an external source.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvShake::InputFrequency( inputdata_t &inputdata )
|
||||
{
|
||||
SetFrequency( inputdata.value.Float() );
|
||||
ApplyShake( SHAKE_FREQUENCY );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Calculates the physics shake values
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvShake::Think( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( gpGlobals->curtime > m_nextShake )
|
||||
{
|
||||
// Higher frequency means we recalc the extents more often and perturb the display again
|
||||
m_nextShake = gpGlobals->curtime + (1.0f / Frequency());
|
||||
|
||||
// Compute random shake extents (the shake will settle down from this)
|
||||
for (i = 0; i < 2; i++ )
|
||||
{
|
||||
m_maxForce[i] = random->RandomFloat( -1, 1 );
|
||||
}
|
||||
// make the force it point mostly up
|
||||
m_maxForce.z = 4;
|
||||
VectorNormalize( m_maxForce );
|
||||
m_maxForce *= m_currentAmp * 400; // amplitude is the acceleration of a 100kg object
|
||||
}
|
||||
|
||||
float fraction = ( m_stopTime - gpGlobals->curtime ) / Duration();
|
||||
|
||||
if ( fraction < 0 )
|
||||
{
|
||||
m_pShakeController->ClearObjects();
|
||||
return;
|
||||
}
|
||||
|
||||
float freq = 0;
|
||||
// Ramp up frequency over duration
|
||||
if ( fraction )
|
||||
{
|
||||
freq = (Frequency() / fraction);
|
||||
}
|
||||
|
||||
// square fraction to approach zero more quickly
|
||||
fraction *= fraction;
|
||||
|
||||
// Sine wave that slowly settles to zero
|
||||
fraction = fraction * sin( gpGlobals->curtime * freq );
|
||||
|
||||
// Add to view origin
|
||||
for ( i = 0; i < 3; i++ )
|
||||
{
|
||||
// store the force in the controller callback
|
||||
m_shakeCallback.m_force[i] = m_maxForce[i] * fraction;
|
||||
}
|
||||
|
||||
// Drop amplitude a bit, less for higher frequency shakes
|
||||
m_currentAmp -= m_currentAmp * ( gpGlobals->frametime / (Duration() * Frequency()) );
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: Console command to cause a screen shake.
|
||||
//------------------------------------------------------------------------------
|
||||
void CC_Shake( void )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_GetCommandClient();
|
||||
if (pPlayer)
|
||||
{
|
||||
UTIL_ScreenShake( pPlayer->WorldSpaceCenter(), 25.0, 150.0, 1.0, 750, SHAKE_START );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Draw any debug text overlays
|
||||
// Returns current text offset from the top
|
||||
//-----------------------------------------------------------------------------
|
||||
int CEnvShake::DrawDebugTextOverlays( void )
|
||||
{
|
||||
int text_offset = BaseClass::DrawDebugTextOverlays();
|
||||
|
||||
if (m_debugOverlays & OVERLAY_TEXT_BIT)
|
||||
{
|
||||
char tempstr[512];
|
||||
|
||||
// print amplitude
|
||||
Q_snprintf(tempstr,sizeof(tempstr)," magnitude: %f", m_Amplitude);
|
||||
EntityText(text_offset,tempstr,0);
|
||||
text_offset++;
|
||||
|
||||
// print frequency
|
||||
Q_snprintf(tempstr,sizeof(tempstr)," frequency: %f", m_Frequency);
|
||||
EntityText(text_offset,tempstr,0);
|
||||
text_offset++;
|
||||
|
||||
// print duration
|
||||
Q_snprintf(tempstr,sizeof(tempstr)," duration: %f", m_Duration);
|
||||
EntityText(text_offset,tempstr,0);
|
||||
text_offset++;
|
||||
|
||||
// print radius
|
||||
Q_snprintf(tempstr,sizeof(tempstr)," radius: %f", m_Radius);
|
||||
EntityText(text_offset,tempstr,0);
|
||||
text_offset++;
|
||||
|
||||
}
|
||||
return text_offset;
|
||||
}
|
||||
|
||||
static ConCommand shake("shake", CC_Shake, "Shake the screen.", FCVAR_CHEAT );
|
||||
|
||||
|
||||
195
sp/src/game/server/EnvSpark.cpp
Normal file
195
sp/src/game/server/EnvSpark.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: A point entity that periodically emits sparks and "bzzt" sounds.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "IEffects.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "envspark.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Emits sparks from the given location and plays a random spark sound.
|
||||
// Input : pev -
|
||||
// location -
|
||||
//-----------------------------------------------------------------------------
|
||||
void DoSpark( CBaseEntity *ent, const Vector &location, int nMagnitude, int nTrailLength, bool bPlaySound, const Vector &vecDir )
|
||||
{
|
||||
g_pEffects->Sparks( location, nMagnitude, nTrailLength, &vecDir );
|
||||
|
||||
if ( bPlaySound )
|
||||
{
|
||||
ent->EmitSound( "DoSpark" );
|
||||
}
|
||||
}
|
||||
|
||||
const int SF_SPARK_START_ON = 64;
|
||||
const int SF_SPARK_GLOW = 128;
|
||||
const int SF_SPARK_SILENT = 256;
|
||||
const int SF_SPARK_DIRECTIONAL = 512;
|
||||
|
||||
BEGIN_DATADESC( CEnvSpark )
|
||||
|
||||
DEFINE_KEYFIELD( m_flDelay, FIELD_FLOAT, "MaxDelay" ),
|
||||
DEFINE_FIELD( m_nGlowSpriteIndex, FIELD_INTEGER ),
|
||||
DEFINE_KEYFIELD( m_nMagnitude, FIELD_INTEGER, "Magnitude" ),
|
||||
DEFINE_KEYFIELD( m_nTrailLength, FIELD_INTEGER, "TrailLength" ),
|
||||
|
||||
// Function Pointers
|
||||
DEFINE_FUNCTION( SparkThink ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StartSpark", InputStartSpark ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StopSpark", InputStopSpark ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ToggleSpark", InputToggleSpark ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "SparkOnce", InputSparkOnce ),
|
||||
|
||||
DEFINE_OUTPUT( m_OnSpark, "OnSpark" ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_spark, CEnvSpark );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor! Exciting, isn't it?
|
||||
//-----------------------------------------------------------------------------
|
||||
CEnvSpark::CEnvSpark( void )
|
||||
{
|
||||
m_nMagnitude = 1;
|
||||
m_nTrailLength = 1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called when spawning, after keyvalues have been handled.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvSpark::Spawn(void)
|
||||
{
|
||||
SetThink( NULL );
|
||||
SetUse( NULL );
|
||||
|
||||
if ( FBitSet(m_spawnflags, SF_SPARK_START_ON ) )
|
||||
{
|
||||
SetThink( &CEnvSpark::SparkThink ); // start sparking
|
||||
}
|
||||
|
||||
SetNextThink( gpGlobals->curtime + 0.1 + random->RandomFloat( 0, 1.5 ) );
|
||||
|
||||
// Negative delays are not allowed
|
||||
if ( m_flDelay < 0 )
|
||||
{
|
||||
m_flDelay = 0;
|
||||
}
|
||||
|
||||
#ifdef HL1_DLL
|
||||
// Don't allow 0 delays in HL1 Port. Enforce a default
|
||||
if( m_flDelay == 0 )
|
||||
{
|
||||
m_flDelay = 1.0f;
|
||||
}
|
||||
#endif//HL1_DLL
|
||||
|
||||
Precache( );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvSpark::Precache(void)
|
||||
{
|
||||
m_nGlowSpriteIndex = PrecacheModel( "sprites/glow01.vmt" );
|
||||
|
||||
PrecacheScriptSound( "DoSpark" );
|
||||
}
|
||||
|
||||
extern ConVar phys_pushscale;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Emits sparks at random intervals.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvSpark::SparkThink(void)
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime + 0.1 + random->RandomFloat(0, m_flDelay) );
|
||||
|
||||
Vector vecDir = vec3_origin;
|
||||
if ( FBitSet( m_spawnflags, SF_SPARK_DIRECTIONAL ) )
|
||||
{
|
||||
AngleVectors( GetAbsAngles(), &vecDir );
|
||||
}
|
||||
|
||||
DoSpark( this, WorldSpaceCenter(), m_nMagnitude, m_nTrailLength, !( m_spawnflags & SF_SPARK_SILENT ), vecDir );
|
||||
|
||||
m_OnSpark.FireOutput( this, this );
|
||||
|
||||
if (FBitSet(m_spawnflags, SF_SPARK_GLOW))
|
||||
{
|
||||
CPVSFilter filter( GetAbsOrigin() );
|
||||
te->GlowSprite( filter, 0.0, &GetAbsOrigin(), m_nGlowSpriteIndex, 0.2, 1.5, 25 );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler for starting the sparks.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvSpark::InputStartSpark( inputdata_t &inputdata )
|
||||
{
|
||||
StartSpark();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvSpark::StartSpark( void )
|
||||
{
|
||||
SetThink( &CEnvSpark::SparkThink );
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Shoot one spark.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvSpark::InputSparkOnce( inputdata_t &inputdata )
|
||||
{
|
||||
SparkThink();
|
||||
SetNextThink( TICK_NEVER_THINK );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler for starting the sparks.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvSpark::InputStopSpark( inputdata_t &inputdata )
|
||||
{
|
||||
StopSpark();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvSpark::StopSpark( void )
|
||||
{
|
||||
SetThink( NULL );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler for toggling the on/off state of the sparks.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvSpark::InputToggleSpark( inputdata_t &inputdata )
|
||||
{
|
||||
if ( GetNextThink() == TICK_NEVER_THINK )
|
||||
{
|
||||
InputStartSpark( inputdata );
|
||||
}
|
||||
else
|
||||
{
|
||||
InputStopSpark( inputdata );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
257
sp/src/game/server/EventLog.cpp
Normal file
257
sp/src/game/server/EventLog.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "EventLog.h"
|
||||
#include "team.h"
|
||||
#include "KeyValues.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
CEventLog::CEventLog()
|
||||
{
|
||||
}
|
||||
|
||||
CEventLog::~CEventLog()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CEventLog::FireGameEvent( IGameEvent *event )
|
||||
{
|
||||
PrintEvent ( event );
|
||||
}
|
||||
|
||||
bool CEventLog::PrintEvent( IGameEvent *event )
|
||||
{
|
||||
const char * name = event->GetName();
|
||||
|
||||
if ( Q_strncmp(name, "server_", strlen("server_")) == 0 )
|
||||
{
|
||||
return true; // we don't care about server events (engine does)
|
||||
}
|
||||
else if ( Q_strncmp(name, "player_", strlen("player_")) == 0 )
|
||||
{
|
||||
return PrintPlayerEvent( event );
|
||||
}
|
||||
else if ( Q_strncmp(name, "team_", strlen("team_")) == 0 )
|
||||
{
|
||||
return PrintTeamEvent( event );
|
||||
}
|
||||
else if ( Q_strncmp(name, "game_", strlen("game_")) == 0 )
|
||||
{
|
||||
return PrintGameEvent( event );
|
||||
}
|
||||
else
|
||||
{
|
||||
return PrintOtherEvent( event ); // bomb_, round_, et al
|
||||
}
|
||||
}
|
||||
|
||||
bool CEventLog::PrintGameEvent( IGameEvent *event )
|
||||
{
|
||||
// const char * name = event->GetName() + Q_strlen("game_"); // remove prefix
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CEventLog::PrintPlayerEvent( IGameEvent *event )
|
||||
{
|
||||
const char * eventName = event->GetName();
|
||||
const int userid = event->GetInt( "userid" );
|
||||
|
||||
if ( !Q_strncmp( eventName, "player_connect", Q_strlen("player_connect") ) ) // player connect is before the CBasePlayer pointer is setup
|
||||
{
|
||||
const char *name = event->GetString( "name" );
|
||||
const char *address = event->GetString( "address" );
|
||||
const char *networkid = event->GetString("networkid" );
|
||||
UTIL_LogPrintf( "\"%s<%i><%s><>\" connected, address \"%s\"\n", name, userid, networkid, address);
|
||||
return true;
|
||||
}
|
||||
else if ( !Q_strncmp( eventName, "player_disconnect", Q_strlen("player_disconnect") ) )
|
||||
{
|
||||
const char *reason = event->GetString("reason" );
|
||||
const char *name = event->GetString("name" );
|
||||
const char *networkid = event->GetString("networkid" );
|
||||
CTeam *team = NULL;
|
||||
CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
|
||||
|
||||
if ( pPlayer )
|
||||
{
|
||||
team = pPlayer->GetTeam();
|
||||
}
|
||||
|
||||
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" disconnected (reason \"%s\")\n", name, userid, networkid, team ? team->GetName() : "", reason );
|
||||
return true;
|
||||
}
|
||||
|
||||
CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
|
||||
if ( !pPlayer)
|
||||
{
|
||||
DevMsg( "CEventLog::PrintPlayerEvent: Failed to find player (userid: %i, event: %s)\n", userid, eventName );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !Q_strncmp( eventName, "player_team", Q_strlen("player_team") ) )
|
||||
{
|
||||
const bool bDisconnecting = event->GetBool( "disconnect" );
|
||||
|
||||
if ( !bDisconnecting )
|
||||
{
|
||||
const int newTeam = event->GetInt( "team" );
|
||||
const int oldTeam = event->GetInt( "oldteam" );
|
||||
CTeam *team = GetGlobalTeam( newTeam );
|
||||
CTeam *oldteam = GetGlobalTeam( oldTeam );
|
||||
|
||||
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" joined team \"%s\"\n",
|
||||
pPlayer->GetPlayerName(),
|
||||
pPlayer->GetUserID(),
|
||||
pPlayer->GetNetworkIDString(),
|
||||
oldteam->GetName(),
|
||||
team->GetName() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ( !Q_strncmp( eventName, "player_death", Q_strlen("player_death") ) )
|
||||
{
|
||||
const int attackerid = event->GetInt("attacker" );
|
||||
|
||||
#ifdef HL2MP
|
||||
const char *weapon = event->GetString( "weapon" );
|
||||
#endif
|
||||
|
||||
CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid );
|
||||
CTeam *team = pPlayer->GetTeam();
|
||||
CTeam *attackerTeam = NULL;
|
||||
|
||||
if ( pAttacker )
|
||||
{
|
||||
attackerTeam = pAttacker->GetTeam();
|
||||
}
|
||||
if ( pPlayer == pAttacker && pPlayer )
|
||||
{
|
||||
|
||||
#ifdef HL2MP
|
||||
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"%s\"\n",
|
||||
pPlayer->GetPlayerName(),
|
||||
userid,
|
||||
pPlayer->GetNetworkIDString(),
|
||||
team ? team->GetName() : "",
|
||||
weapon
|
||||
);
|
||||
#else
|
||||
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"%s\"\n",
|
||||
pPlayer->GetPlayerName(),
|
||||
userid,
|
||||
pPlayer->GetNetworkIDString(),
|
||||
team ? team->GetName() : "",
|
||||
pAttacker->GetClassname()
|
||||
);
|
||||
#endif
|
||||
}
|
||||
else if ( pAttacker )
|
||||
{
|
||||
CTeam *attackerTeam = pAttacker->GetTeam();
|
||||
|
||||
#ifdef HL2MP
|
||||
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\"\n",
|
||||
pAttacker->GetPlayerName(),
|
||||
attackerid,
|
||||
pAttacker->GetNetworkIDString(),
|
||||
attackerTeam ? attackerTeam->GetName() : "",
|
||||
pPlayer->GetPlayerName(),
|
||||
userid,
|
||||
pPlayer->GetNetworkIDString(),
|
||||
team ? team->GetName() : "",
|
||||
weapon
|
||||
);
|
||||
#else
|
||||
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\"\n",
|
||||
pAttacker->GetPlayerName(),
|
||||
attackerid,
|
||||
pAttacker->GetNetworkIDString(),
|
||||
attackerTeam ? attackerTeam->GetName() : "",
|
||||
pPlayer->GetPlayerName(),
|
||||
userid,
|
||||
pPlayer->GetNetworkIDString(),
|
||||
team ? team->GetName() : ""
|
||||
);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// killed by the world
|
||||
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"world\"\n",
|
||||
pPlayer->GetPlayerName(),
|
||||
userid,
|
||||
pPlayer->GetNetworkIDString(),
|
||||
team ? team->GetName() : ""
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ( !Q_strncmp( eventName, "player_activate", Q_strlen("player_activate") ) )
|
||||
{
|
||||
UTIL_LogPrintf( "\"%s<%i><%s><>\" entered the game\n",
|
||||
pPlayer->GetPlayerName(),
|
||||
userid,
|
||||
pPlayer->GetNetworkIDString()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ( !Q_strncmp( eventName, "player_changename", Q_strlen("player_changename") ) )
|
||||
{
|
||||
const char *newName = event->GetString( "newname" );
|
||||
const char *oldName = event->GetString( "oldname" );
|
||||
CTeam *team = pPlayer->GetTeam();
|
||||
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" changed name to \"%s\"\n",
|
||||
oldName,
|
||||
userid,
|
||||
pPlayer->GetNetworkIDString(),
|
||||
team ? team->GetName() : "",
|
||||
newName
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ignored events
|
||||
//player_hurt
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CEventLog::PrintTeamEvent( IGameEvent *event )
|
||||
{
|
||||
// const char * name = event->GetName() + Q_strlen("team_"); // remove prefix
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CEventLog::PrintOtherEvent( IGameEvent *event )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CEventLog::Init()
|
||||
{
|
||||
ListenForGameEvent( "player_changename" );
|
||||
ListenForGameEvent( "player_activate" );
|
||||
ListenForGameEvent( "player_death" );
|
||||
ListenForGameEvent( "player_team" );
|
||||
ListenForGameEvent( "player_disconnect" );
|
||||
ListenForGameEvent( "player_connect" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEventLog::Shutdown()
|
||||
{
|
||||
StopListeningForAllEvents();
|
||||
}
|
||||
46
sp/src/game/server/EventLog.h
Normal file
46
sp/src/game/server/EventLog.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#if !defined EVENTLOG_H
|
||||
#define EVENTLOG_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "GameEventListener.h"
|
||||
#include <igamesystem.h>
|
||||
|
||||
class CEventLog : public CGameEventListener, public CBaseGameSystem
|
||||
{
|
||||
|
||||
public:
|
||||
CEventLog();
|
||||
virtual ~CEventLog();
|
||||
|
||||
public: // IGameEventListener Interface
|
||||
|
||||
virtual void FireGameEvent( IGameEvent * event );
|
||||
|
||||
public: // CBaseGameSystem overrides
|
||||
|
||||
virtual bool Init();
|
||||
virtual void Shutdown();
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool PrintEvent( IGameEvent * event );
|
||||
virtual bool PrintGameEvent( IGameEvent * event );
|
||||
virtual bool PrintPlayerEvent( IGameEvent * event );
|
||||
virtual bool PrintTeamEvent( IGameEvent * event );
|
||||
virtual bool PrintOtherEvent( IGameEvent * event );
|
||||
};
|
||||
|
||||
extern IGameSystem* GameLogSystem();
|
||||
|
||||
#endif // EVENTLOG_H
|
||||
1099
sp/src/game/server/GameStats.cpp
Normal file
1099
sp/src/game/server/GameStats.cpp
Normal file
File diff suppressed because it is too large
Load Diff
183
sp/src/game/server/GameStats_BasicStatsFunctions.cpp
Normal file
183
sp/src/game/server/GameStats_BasicStatsFunctions.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "gamestats.h"
|
||||
|
||||
void BasicGameStatsRecord_t::Clear()
|
||||
{
|
||||
m_nCount = 0;
|
||||
m_nSeconds = 0;
|
||||
m_nCommentary = 0;
|
||||
m_nHDR = 0;
|
||||
m_nCaptions = 0;
|
||||
m_bSteam = true;
|
||||
m_bCyberCafe = false;
|
||||
Q_memset( m_nSkill, 0, sizeof( m_nSkill ) );
|
||||
m_nDeaths = 0;
|
||||
}
|
||||
|
||||
void BasicGameStatsRecord_t::SaveToBuffer( CUtlBuffer &buf )
|
||||
{
|
||||
buf.PutInt( m_nCount );
|
||||
buf.PutInt( m_nSeconds );
|
||||
buf.PutInt( m_nCommentary );
|
||||
buf.PutInt( m_nHDR );
|
||||
buf.PutInt( m_nCaptions );
|
||||
for ( int i = 0; i < 3; ++i )
|
||||
{
|
||||
buf.PutInt( m_nSkill[ i ] );
|
||||
}
|
||||
|
||||
buf.PutChar( m_bSteam ? 1 : 0 );
|
||||
buf.PutChar( m_bCyberCafe ? 1 : 0 );
|
||||
buf.PutInt( m_nDeaths );
|
||||
}
|
||||
|
||||
bool BasicGameStatsRecord_t::ParseFromBuffer( CUtlBuffer &buf, int iBufferStatsVersion )
|
||||
{
|
||||
bool bret = true;
|
||||
m_nCount = buf.GetInt();
|
||||
|
||||
if ( m_nCount > 100000 || m_nCount < 0 )
|
||||
{
|
||||
bret = false;
|
||||
}
|
||||
|
||||
m_nSeconds = buf.GetInt();
|
||||
// Note, don't put the buf.GetInt() in the macro since it'll get evaluated twice!!!
|
||||
m_nSeconds = MAX( m_nSeconds, 0 );
|
||||
|
||||
m_nCommentary = buf.GetInt();
|
||||
if ( m_nCommentary < 0 || m_nCommentary > 100000 )
|
||||
{
|
||||
bret = false;
|
||||
}
|
||||
|
||||
m_nHDR = buf.GetInt();
|
||||
if ( m_nHDR < 0 || m_nHDR > 100000 )
|
||||
{
|
||||
bret = false;
|
||||
}
|
||||
|
||||
m_nCaptions = buf.GetInt();
|
||||
if ( m_nCaptions < 0 || m_nCaptions > 100000 )
|
||||
{
|
||||
bret = false;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < 3; ++i )
|
||||
{
|
||||
m_nSkill[ i ] = buf.GetInt();
|
||||
if ( m_nSkill[ i ] < 0 || m_nSkill[ i ] > 100000 )
|
||||
{
|
||||
bret = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( iBufferStatsVersion > GAMESTATS_FILE_VERSION_OLD )
|
||||
{
|
||||
m_bSteam = buf.GetChar() ? true : false;
|
||||
}
|
||||
if ( iBufferStatsVersion > GAMESTATS_FILE_VERSION_OLD2 )
|
||||
{
|
||||
m_bCyberCafe = buf.GetChar() ? true : false;
|
||||
}
|
||||
if ( iBufferStatsVersion > GAMESTATS_FILE_VERSION_OLD5 )
|
||||
{
|
||||
m_nDeaths = buf.GetInt();
|
||||
}
|
||||
|
||||
return bret;
|
||||
}
|
||||
|
||||
void BasicGameStats_t::Clear()
|
||||
{
|
||||
m_nSecondsToCompleteGame = 0;
|
||||
m_Summary.Clear();
|
||||
m_MapTotals.Purge();
|
||||
}
|
||||
|
||||
void BasicGameStats_t::SaveToBuffer( CUtlBuffer& buf )
|
||||
{
|
||||
buf.PutInt( m_nSecondsToCompleteGame );
|
||||
|
||||
m_Summary.SaveToBuffer( buf );
|
||||
|
||||
int c = m_MapTotals.Count();
|
||||
buf.PutInt( c );
|
||||
for ( int i = m_MapTotals.First(); i != m_MapTotals.InvalidIndex(); i = m_MapTotals.Next( i ) )
|
||||
{
|
||||
char const *name = m_MapTotals.GetElementName( i );
|
||||
BasicGameStatsRecord_t &rec = m_MapTotals[ i ];
|
||||
|
||||
buf.PutString( name );
|
||||
rec.SaveToBuffer( buf );
|
||||
}
|
||||
|
||||
buf.PutChar( (char)m_nHL2ChaptureUnlocked );
|
||||
buf.PutChar( m_bSteam ? 1 : 0 );
|
||||
buf.PutChar( m_bCyberCafe ? 1 : 0 );
|
||||
buf.PutShort( (short)m_nDXLevel );
|
||||
}
|
||||
|
||||
BasicGameStatsRecord_t *BasicGameStats_t::FindOrAddRecordForMap( char const *mapname )
|
||||
{
|
||||
int idx = m_MapTotals.Find( mapname );
|
||||
if ( idx == m_MapTotals.InvalidIndex() )
|
||||
{
|
||||
idx = m_MapTotals.Insert( mapname );
|
||||
}
|
||||
|
||||
return &m_MapTotals[ idx ];
|
||||
}
|
||||
|
||||
bool BasicGameStats_t::ParseFromBuffer( CUtlBuffer& buf, int iBufferStatsVersion )
|
||||
{
|
||||
bool bret = true;
|
||||
|
||||
m_nSecondsToCompleteGame = buf.GetInt();
|
||||
if ( m_nSecondsToCompleteGame < 0 || m_nSecondsToCompleteGame > 10000000 )
|
||||
{
|
||||
bret = false;
|
||||
}
|
||||
|
||||
m_Summary.ParseFromBuffer( buf, iBufferStatsVersion );
|
||||
int c = buf.GetInt();
|
||||
if ( c > 1024 || c < 0 )
|
||||
{
|
||||
bret = false;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < c; ++i )
|
||||
{
|
||||
char mapname[ 256 ];
|
||||
buf.GetString( mapname, sizeof( mapname ) );
|
||||
|
||||
BasicGameStatsRecord_t *rec = FindOrAddRecordForMap( mapname );
|
||||
bool valid= rec->ParseFromBuffer( buf, iBufferStatsVersion );
|
||||
if ( !valid )
|
||||
{
|
||||
bret = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( iBufferStatsVersion >= GAMESTATS_FILE_VERSION_OLD2 )
|
||||
{
|
||||
m_nHL2ChaptureUnlocked = (int)buf.GetChar();
|
||||
m_bSteam = buf.GetChar() ? true : false;
|
||||
}
|
||||
if ( iBufferStatsVersion > GAMESTATS_FILE_VERSION_OLD2 )
|
||||
{
|
||||
m_bCyberCafe = buf.GetChar() ? true : false;
|
||||
}
|
||||
if ( iBufferStatsVersion > GAMESTATS_FILE_VERSION_OLD3 )
|
||||
{
|
||||
m_nDXLevel = (int)buf.GetShort();
|
||||
}
|
||||
return bret;
|
||||
}
|
||||
|
||||
289
sp/src/game/server/MaterialModifyControl.cpp
Normal file
289
sp/src/game/server/MaterialModifyControl.cpp
Normal file
@@ -0,0 +1,289 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Material modify control entity.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FIXME: This really should inherit from something more lightweight.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#define MATERIAL_MODIFY_STRING_SIZE 255
|
||||
#define MATERIAL_MODIFY_ANIMATION_UNSET -1
|
||||
|
||||
// Must match C_MaterialModifyControl.cpp
|
||||
enum MaterialModifyMode_t
|
||||
{
|
||||
MATERIAL_MODIFY_MODE_NONE = 0,
|
||||
MATERIAL_MODIFY_MODE_SETVAR = 1,
|
||||
MATERIAL_MODIFY_MODE_ANIM_SEQUENCE = 2,
|
||||
MATERIAL_MODIFY_MODE_FLOAT_LERP = 3,
|
||||
};
|
||||
|
||||
ConVar debug_materialmodifycontrol( "debug_materialmodifycontrol", "0" );
|
||||
|
||||
class CMaterialModifyControl : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
|
||||
DECLARE_CLASS( CMaterialModifyControl, CBaseEntity );
|
||||
|
||||
CMaterialModifyControl();
|
||||
|
||||
void Spawn( void );
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
int UpdateTransmitState();
|
||||
int ShouldTransmit( const CCheckTransmitInfo *pInfo );
|
||||
|
||||
void SetMaterialVar( inputdata_t &inputdata );
|
||||
void SetMaterialVarToCurrentTime( inputdata_t &inputdata );
|
||||
void InputStartAnimSequence( inputdata_t &inputdata );
|
||||
void InputStartFloatLerp( inputdata_t &inputdata );
|
||||
|
||||
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
private:
|
||||
CNetworkString( m_szMaterialName, MATERIAL_MODIFY_STRING_SIZE );
|
||||
CNetworkString( m_szMaterialVar, MATERIAL_MODIFY_STRING_SIZE );
|
||||
CNetworkString( m_szMaterialVarValue, MATERIAL_MODIFY_STRING_SIZE );
|
||||
CNetworkVar( int, m_iFrameStart );
|
||||
CNetworkVar( int, m_iFrameEnd );
|
||||
CNetworkVar( bool, m_bWrap );
|
||||
CNetworkVar( float, m_flFramerate );
|
||||
CNetworkVar( bool, m_bNewAnimCommandsSemaphore );
|
||||
CNetworkVar( float, m_flFloatLerpStartValue );
|
||||
CNetworkVar( float, m_flFloatLerpEndValue );
|
||||
CNetworkVar( float, m_flFloatLerpTransitionTime );
|
||||
CNetworkVar( int, m_nModifyMode );
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(material_modify_control, CMaterialModifyControl);
|
||||
|
||||
BEGIN_DATADESC( CMaterialModifyControl )
|
||||
// Variables.
|
||||
DEFINE_AUTO_ARRAY( m_szMaterialName, FIELD_CHARACTER ),
|
||||
DEFINE_AUTO_ARRAY( m_szMaterialVar, FIELD_CHARACTER ),
|
||||
DEFINE_AUTO_ARRAY( m_szMaterialVarValue, FIELD_CHARACTER ),
|
||||
DEFINE_FIELD( m_iFrameStart, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_iFrameEnd, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_bWrap, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( m_flFramerate, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_bNewAnimCommandsSemaphore, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( m_flFloatLerpStartValue, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flFloatLerpEndValue, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flFloatLerpTransitionTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_nModifyMode, FIELD_INTEGER ),
|
||||
// Inputs.
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetMaterialVar", SetMaterialVar ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "SetMaterialVarToCurrentTime", SetMaterialVarToCurrentTime ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "StartAnimSequence", InputStartAnimSequence ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "StartFloatLerp", InputStartFloatLerp ),
|
||||
END_DATADESC()
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST(CMaterialModifyControl, DT_MaterialModifyControl)
|
||||
SendPropString( SENDINFO( m_szMaterialName ) ),
|
||||
SendPropString( SENDINFO( m_szMaterialVar ) ),
|
||||
SendPropString( SENDINFO( m_szMaterialVarValue ) ),
|
||||
SendPropInt( SENDINFO(m_iFrameStart), 8 ),
|
||||
SendPropInt( SENDINFO(m_iFrameEnd), 8 ),
|
||||
SendPropInt( SENDINFO(m_bWrap), 1, SPROP_UNSIGNED ),
|
||||
SendPropFloat( SENDINFO(m_flFramerate), 0, SPROP_NOSCALE ),
|
||||
SendPropInt( SENDINFO(m_bNewAnimCommandsSemaphore), 1, SPROP_UNSIGNED ),
|
||||
SendPropFloat( SENDINFO(m_flFloatLerpStartValue), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat( SENDINFO(m_flFloatLerpEndValue), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat( SENDINFO(m_flFloatLerpTransitionTime), 0, SPROP_NOSCALE ),
|
||||
SendPropInt( SENDINFO(m_nModifyMode), 2, SPROP_UNSIGNED ),
|
||||
END_SEND_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CMaterialModifyControl::CMaterialModifyControl()
|
||||
{
|
||||
m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET;
|
||||
m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET;
|
||||
m_nModifyMode = MATERIAL_MODIFY_MODE_NONE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
//------------------------------------------------------------------------------
|
||||
void CMaterialModifyControl::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
SetSolid( SOLID_NONE );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
//------------------------------------------------------------------------------
|
||||
bool CMaterialModifyControl::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "materialName" ) )
|
||||
{
|
||||
Q_strncpy( m_szMaterialName.GetForModify(), szValue, MATERIAL_MODIFY_STRING_SIZE );
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( FStrEq( szKeyName, "materialVar" ) )
|
||||
{
|
||||
Q_strncpy( m_szMaterialVar.GetForModify(), szValue, MATERIAL_MODIFY_STRING_SIZE );
|
||||
return true;
|
||||
}
|
||||
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Send even though we don't have a model.
|
||||
//------------------------------------------------------------------------------
|
||||
int CMaterialModifyControl::UpdateTransmitState()
|
||||
{
|
||||
// ALWAYS transmit to all clients.
|
||||
return SetTransmitState( FL_EDICT_FULLCHECK );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Send if the parent is being sent:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CMaterialModifyControl::ShouldTransmit( const CCheckTransmitInfo *pInfo )
|
||||
{
|
||||
CBaseEntity *pEnt = GetMoveParent();
|
||||
if ( pEnt )
|
||||
{
|
||||
return pEnt->ShouldTransmit( pInfo );
|
||||
}
|
||||
|
||||
return FL_EDICT_DONTSEND;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMaterialModifyControl::SetMaterialVar( inputdata_t &inputdata )
|
||||
{
|
||||
//if( debug_materialmodifycontrol.GetBool() && Q_stristr( GetDebugName(), "alyx" ) )
|
||||
//{
|
||||
//DevMsg( 1, "CMaterialModifyControl::SetMaterialVar %s %s %s=\"%s\"\n",
|
||||
//GetDebugName(), m_szMaterialName.Get(), m_szMaterialVar.Get(), inputdata.value.String() );
|
||||
//}
|
||||
Q_strncpy( m_szMaterialVarValue.GetForModify(), inputdata.value.String(), MATERIAL_MODIFY_STRING_SIZE );
|
||||
m_nModifyMode = MATERIAL_MODIFY_MODE_SETVAR;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMaterialModifyControl::SetMaterialVarToCurrentTime( inputdata_t &inputdata )
|
||||
{
|
||||
char temp[32];
|
||||
Q_snprintf( temp, 32, "%f", gpGlobals->curtime );
|
||||
Q_strncpy( m_szMaterialVarValue.GetForModify(), temp, MATERIAL_MODIFY_STRING_SIZE );
|
||||
m_nModifyMode = MATERIAL_MODIFY_MODE_SETVAR;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMaterialModifyControl::InputStartAnimSequence( inputdata_t &inputdata )
|
||||
{
|
||||
char parseString[255];
|
||||
Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString));
|
||||
|
||||
// Get the start & end frames
|
||||
char *pszParam = strtok(parseString," ");
|
||||
if ( pszParam && pszParam[0] )
|
||||
{
|
||||
int iFrameStart = atoi(pszParam);
|
||||
|
||||
pszParam = strtok(NULL," ");
|
||||
if ( pszParam && pszParam[0] )
|
||||
{
|
||||
int iFrameEnd = atoi(pszParam);
|
||||
|
||||
pszParam = strtok(NULL," ");
|
||||
if ( pszParam && pszParam[0] )
|
||||
{
|
||||
float flFramerate = atof(pszParam);
|
||||
|
||||
pszParam = strtok(NULL," ");
|
||||
if ( pszParam && pszParam[0] )
|
||||
{
|
||||
bool bWrap = atoi(pszParam) != 0;
|
||||
|
||||
// Got all the parameters. Save 'em and return;
|
||||
m_iFrameStart = iFrameStart;
|
||||
m_iFrameEnd = iFrameEnd;
|
||||
m_flFramerate = flFramerate;
|
||||
m_bWrap = bWrap;
|
||||
m_nModifyMode = MATERIAL_MODIFY_MODE_ANIM_SEQUENCE;
|
||||
m_bNewAnimCommandsSemaphore = !m_bNewAnimCommandsSemaphore;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Warning("%s (%s) received StartAnimSequence input without correct parameters. Syntax: <Frame Start> <Frame End> <Frame Rate> <Loop>\nSetting <Frame End> to -1 uses the last frame of the texture. <Loop> should be 1 or 0.\n", GetClassname(), GetDebugName() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMaterialModifyControl::InputStartFloatLerp( inputdata_t &inputdata )
|
||||
{
|
||||
char parseString[255];
|
||||
Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString));
|
||||
|
||||
// if( debug_materialmodifycontrol.GetBool() )//&& Q_stristr( GetDebugName(), "alyx" ) )
|
||||
// {
|
||||
// DevMsg( 1, "CMaterialModifyControl::InputStartFloatLerp %s %s %s \"%s\"\n",
|
||||
// GetDebugName(), m_szMaterialName.Get(), m_szMaterialVar.Get(), inputdata.value.String() );
|
||||
// }
|
||||
|
||||
// Get the start & end values
|
||||
char *pszParam = strtok(parseString," ");
|
||||
if ( pszParam && pszParam[0] )
|
||||
{
|
||||
float flStartValue = atof(pszParam);
|
||||
|
||||
pszParam = strtok(NULL," ");
|
||||
if ( pszParam && pszParam[0] )
|
||||
{
|
||||
float flEndValue = atof(pszParam);
|
||||
|
||||
pszParam = strtok(NULL," ");
|
||||
if ( pszParam && pszParam[0] )
|
||||
{
|
||||
float flTransitionTime = atof(pszParam);
|
||||
|
||||
pszParam = strtok(NULL," ");
|
||||
if ( pszParam && pszParam[0] )
|
||||
{
|
||||
bool bWrap = atoi(pszParam) != 0;
|
||||
// We don't implement wrap currently.
|
||||
bWrap = bWrap;
|
||||
|
||||
// Got all the parameters. Save 'em and return;
|
||||
m_flFloatLerpStartValue = flStartValue;
|
||||
m_flFloatLerpEndValue = flEndValue;
|
||||
m_flFloatLerpTransitionTime = flTransitionTime;
|
||||
m_nModifyMode = MATERIAL_MODIFY_MODE_FLOAT_LERP;
|
||||
m_bNewAnimCommandsSemaphore = !m_bNewAnimCommandsSemaphore;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Warning("%s (%s) received StartFloatLerp input without correct parameters. Syntax: <Start Value> <End Value> <Transition Time> <Loop>\n<Loop> should be 1 or 0.\n", GetClassname(), GetDebugName() );
|
||||
}
|
||||
529
sp/src/game/server/PointAngularVelocitySensor.cpp
Normal file
529
sp/src/game/server/PointAngularVelocitySensor.cpp
Normal file
@@ -0,0 +1,529 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Used to fire events based on the orientation of a given entity.
|
||||
//
|
||||
// Looks at its target's anglular velocity every frame and fires outputs
|
||||
// as the angular velocity passes a given threshold value.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "entityinput.h"
|
||||
#include "entityoutput.h"
|
||||
#include "eventqueue.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
enum
|
||||
{
|
||||
AVELOCITY_SENSOR_NO_LAST_RESULT = -2
|
||||
};
|
||||
|
||||
ConVar g_debug_angularsensor( "g_debug_angularsensor", "0", FCVAR_CHEAT );
|
||||
|
||||
class CPointAngularVelocitySensor : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS( CPointAngularVelocitySensor, CPointEntity );
|
||||
|
||||
public:
|
||||
|
||||
CPointAngularVelocitySensor();
|
||||
void Activate(void);
|
||||
void Spawn(void);
|
||||
void Think(void);
|
||||
|
||||
private:
|
||||
|
||||
float SampleAngularVelocity(CBaseEntity *pEntity);
|
||||
int CompareToThreshold(CBaseEntity *pEntity, float flThreshold, bool bFireVelocityOutput);
|
||||
void FireCompareOutput(int nCompareResult, CBaseEntity *pActivator);
|
||||
void DrawDebugLines( void );
|
||||
|
||||
// Input handlers
|
||||
void InputTest( inputdata_t &inputdata );
|
||||
void InputTestWithInterval( inputdata_t &inputdata );
|
||||
|
||||
EHANDLE m_hTargetEntity; // Entity whose angles are being monitored.
|
||||
float m_flThreshold; // The threshold angular velocity that we are looking for.
|
||||
int m_nLastCompareResult; // The comparison result from our last measurement, expressed as -1, 0, or 1
|
||||
int m_nLastFireResult; // The last result for which we fire the output.
|
||||
|
||||
float m_flFireTime;
|
||||
float m_flFireInterval;
|
||||
float m_flLastAngVelocity;
|
||||
|
||||
QAngle m_lastOrientation;
|
||||
|
||||
Vector m_vecAxis;
|
||||
bool m_bUseHelper;
|
||||
|
||||
// Outputs
|
||||
COutputFloat m_AngularVelocity;
|
||||
|
||||
// Compare the target's angular velocity to the threshold velocity and fire the appropriate output.
|
||||
// These outputs are filtered by m_flFireInterval to ignore excessive oscillations.
|
||||
COutputEvent m_OnLessThan;
|
||||
COutputEvent m_OnLessThanOrEqualTo;
|
||||
COutputEvent m_OnGreaterThan;
|
||||
COutputEvent m_OnGreaterThanOrEqualTo;
|
||||
COutputEvent m_OnEqualTo;
|
||||
|
||||
DECLARE_DATADESC();
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(point_angularvelocitysensor, CPointAngularVelocitySensor);
|
||||
|
||||
|
||||
BEGIN_DATADESC( CPointAngularVelocitySensor )
|
||||
|
||||
// Fields
|
||||
DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ),
|
||||
DEFINE_KEYFIELD(m_flThreshold, FIELD_FLOAT, "threshold"),
|
||||
DEFINE_FIELD(m_nLastCompareResult, FIELD_INTEGER),
|
||||
DEFINE_FIELD( m_nLastFireResult, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_flFireTime, FIELD_TIME ),
|
||||
DEFINE_KEYFIELD( m_flFireInterval, FIELD_FLOAT, "fireinterval" ),
|
||||
DEFINE_FIELD( m_flLastAngVelocity, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_lastOrientation, FIELD_VECTOR ),
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUTFUNC(FIELD_VOID, "Test", InputTest),
|
||||
DEFINE_INPUTFUNC(FIELD_VOID, "TestWithInterval", InputTestWithInterval),
|
||||
|
||||
// Outputs
|
||||
DEFINE_OUTPUT(m_OnLessThan, "OnLessThan"),
|
||||
DEFINE_OUTPUT(m_OnLessThanOrEqualTo, "OnLessThanOrEqualTo"),
|
||||
DEFINE_OUTPUT(m_OnGreaterThan, "OnGreaterThan"),
|
||||
DEFINE_OUTPUT(m_OnGreaterThanOrEqualTo, "OnGreaterThanOrEqualTo"),
|
||||
DEFINE_OUTPUT(m_OnEqualTo, "OnEqualTo"),
|
||||
DEFINE_OUTPUT(m_AngularVelocity, "AngularVelocity"),
|
||||
|
||||
DEFINE_KEYFIELD( m_vecAxis, FIELD_VECTOR, "axis" ),
|
||||
DEFINE_KEYFIELD( m_bUseHelper, FIELD_BOOLEAN, "usehelper" ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: constructor provides default values
|
||||
//-----------------------------------------------------------------------------
|
||||
CPointAngularVelocitySensor::CPointAngularVelocitySensor()
|
||||
{
|
||||
m_flFireInterval = 0.2f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called when spawning after parsing keyvalues.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointAngularVelocitySensor::Spawn(void)
|
||||
{
|
||||
m_flThreshold = fabs(m_flThreshold);
|
||||
m_nLastFireResult = AVELOCITY_SENSOR_NO_LAST_RESULT;
|
||||
m_nLastCompareResult = AVELOCITY_SENSOR_NO_LAST_RESULT;
|
||||
// m_flFireInterval = 0.2;
|
||||
m_lastOrientation = vec3_angle;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called after all entities in the map have spawned.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointAngularVelocitySensor::Activate(void)
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target );
|
||||
|
||||
if (m_hTargetEntity)
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Draws magic lines...
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointAngularVelocitySensor::DrawDebugLines( void )
|
||||
{
|
||||
if ( m_hTargetEntity )
|
||||
{
|
||||
Vector vForward, vRight, vUp;
|
||||
AngleVectors( m_hTargetEntity->GetAbsAngles(), &vForward, &vRight, &vUp );
|
||||
|
||||
NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vForward * 64, 255, 0, 0, false, 0 );
|
||||
NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vRight * 64, 0, 255, 0, false, 0 );
|
||||
NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vUp * 64, 0, 0, 255, false, 0 );
|
||||
}
|
||||
|
||||
if ( m_bUseHelper == true )
|
||||
{
|
||||
QAngle Angles;
|
||||
Vector vAxisForward, vAxisRight, vAxisUp;
|
||||
|
||||
Vector vLine = m_vecAxis - GetAbsOrigin();
|
||||
|
||||
VectorNormalize( vLine );
|
||||
|
||||
VectorAngles( vLine, Angles );
|
||||
AngleVectors( Angles, &vAxisForward, &vAxisRight, &vAxisUp );
|
||||
|
||||
NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisForward * 64, 255, 0, 0, false, 0 );
|
||||
NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisRight * 64, 0, 255, 0, false, 0 );
|
||||
NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisUp * 64, 0, 0, 255, false, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns the magnitude of the entity's angular velocity.
|
||||
//-----------------------------------------------------------------------------
|
||||
float CPointAngularVelocitySensor::SampleAngularVelocity(CBaseEntity *pEntity)
|
||||
{
|
||||
if (pEntity->GetMoveType() == MOVETYPE_VPHYSICS)
|
||||
{
|
||||
IPhysicsObject *pPhys = pEntity->VPhysicsGetObject();
|
||||
if (pPhys != NULL)
|
||||
{
|
||||
Vector vecVelocity;
|
||||
AngularImpulse vecAngVelocity;
|
||||
pPhys->GetVelocity(&vecVelocity, &vecAngVelocity);
|
||||
|
||||
QAngle angles;
|
||||
pPhys->GetPosition( NULL, &angles );
|
||||
|
||||
float dt = gpGlobals->curtime - GetLastThink();
|
||||
if ( dt == 0 )
|
||||
dt = 0.1;
|
||||
|
||||
// HACKHACK: We don't expect a real 'delta' orientation here, just enough of an error estimate to tell if this thing
|
||||
// is trying to move, but failing.
|
||||
QAngle delta = angles - m_lastOrientation;
|
||||
|
||||
if ( ( delta.Length() / dt ) < ( vecAngVelocity.Length() * 0.01 ) )
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
m_lastOrientation = angles;
|
||||
|
||||
if ( m_bUseHelper == false )
|
||||
{
|
||||
return vecAngVelocity.Length();
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector vLine = m_vecAxis - GetAbsOrigin();
|
||||
VectorNormalize( vLine );
|
||||
|
||||
Vector vecWorldAngVelocity;
|
||||
pPhys->LocalToWorldVector( &vecWorldAngVelocity, vecAngVelocity );
|
||||
float flDot = DotProduct( vecWorldAngVelocity, vLine );
|
||||
|
||||
return flDot;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QAngle vecAngVel = pEntity->GetLocalAngularVelocity();
|
||||
float flMax = MAX(fabs(vecAngVel[PITCH]), fabs(vecAngVel[YAW]));
|
||||
|
||||
return MAX(flMax, fabs(vecAngVel[ROLL]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Compares the given entity's angular velocity to the threshold velocity.
|
||||
// Input : pEntity - Entity whose angular velocity is being measured.
|
||||
// flThreshold -
|
||||
// Output : Returns -1 if less than, 0 if equal to, or 1 if greater than the threshold.
|
||||
//-----------------------------------------------------------------------------
|
||||
int CPointAngularVelocitySensor::CompareToThreshold(CBaseEntity *pEntity, float flThreshold, bool bFireVelocityOutput)
|
||||
{
|
||||
if (pEntity == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
float flAngVelocity = SampleAngularVelocity(pEntity);
|
||||
|
||||
if ( g_debug_angularsensor.GetBool() )
|
||||
{
|
||||
DrawDebugLines();
|
||||
}
|
||||
|
||||
if (bFireVelocityOutput && (flAngVelocity != m_flLastAngVelocity))
|
||||
{
|
||||
m_AngularVelocity.Set(flAngVelocity, pEntity, this);
|
||||
m_flLastAngVelocity = flAngVelocity;
|
||||
}
|
||||
|
||||
if (flAngVelocity > flThreshold)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (flAngVelocity == flThreshold)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Called every frame to sense the angular velocity of the target entity.
|
||||
// Output is filtered by m_flFireInterval to ignore excessive oscillations.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointAngularVelocitySensor::Think(void)
|
||||
{
|
||||
if (m_hTargetEntity != NULL)
|
||||
{
|
||||
//
|
||||
// Check to see if the measure entity's angular velocity has been within
|
||||
// tolerance of the threshold for the given period of time.
|
||||
//
|
||||
int nCompare = CompareToThreshold(m_hTargetEntity, m_flThreshold, true);
|
||||
if (nCompare != m_nLastCompareResult)
|
||||
{
|
||||
// If we've oscillated back to where we last fired the output, don't
|
||||
// fire the same output again.
|
||||
if (nCompare == m_nLastFireResult)
|
||||
{
|
||||
m_flFireTime = 0;
|
||||
}
|
||||
else if (m_nLastCompareResult != AVELOCITY_SENSOR_NO_LAST_RESULT)
|
||||
{
|
||||
//
|
||||
// The value has changed -- reset the timer. We'll fire the output if
|
||||
// it stays at this value until the interval expires.
|
||||
//
|
||||
m_flFireTime = gpGlobals->curtime + m_flFireInterval;
|
||||
}
|
||||
|
||||
m_nLastCompareResult = nCompare;
|
||||
}
|
||||
else if ((m_flFireTime != 0) && (gpGlobals->curtime >= m_flFireTime))
|
||||
{
|
||||
//
|
||||
// The compare result has held steady long enough -- time to
|
||||
// fire the output.
|
||||
//
|
||||
FireCompareOutput(nCompare, this);
|
||||
m_nLastFireResult = nCompare;
|
||||
m_flFireTime = 0;
|
||||
}
|
||||
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Fires the output after the fire interval if the velocity is stable.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointAngularVelocitySensor::InputTestWithInterval( inputdata_t &inputdata )
|
||||
{
|
||||
if (m_hTargetEntity != NULL)
|
||||
{
|
||||
m_flFireTime = gpGlobals->curtime + m_flFireInterval;
|
||||
m_nLastFireResult = AVELOCITY_SENSOR_NO_LAST_RESULT;
|
||||
m_nLastCompareResult = CompareToThreshold(m_hTargetEntity, m_flThreshold, true);
|
||||
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler for forcing an instantaneous test of the condition.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointAngularVelocitySensor::InputTest( inputdata_t &inputdata )
|
||||
{
|
||||
int nCompareResult = CompareToThreshold(m_hTargetEntity, m_flThreshold, false);
|
||||
FireCompareOutput(nCompareResult, inputdata.pActivator);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Fires the appropriate output based on the given comparison result.
|
||||
// Input : nCompareResult -
|
||||
// pActivator -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointAngularVelocitySensor::FireCompareOutput( int nCompareResult, CBaseEntity *pActivator )
|
||||
{
|
||||
if (nCompareResult == -1)
|
||||
{
|
||||
m_OnLessThan.FireOutput(pActivator, this);
|
||||
m_OnLessThanOrEqualTo.FireOutput(pActivator, this);
|
||||
}
|
||||
else if (nCompareResult == 1)
|
||||
{
|
||||
m_OnGreaterThan.FireOutput(pActivator, this);
|
||||
m_OnGreaterThanOrEqualTo.FireOutput(pActivator, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_OnEqualTo.FireOutput(pActivator, this);
|
||||
m_OnLessThanOrEqualTo.FireOutput(pActivator, this);
|
||||
m_OnGreaterThanOrEqualTo.FireOutput(pActivator, this);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
//
|
||||
// Simple velocity sensor
|
||||
//
|
||||
// ============================================================================
|
||||
|
||||
class CPointVelocitySensor : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS( CPointVelocitySensor, CPointEntity );
|
||||
|
||||
public:
|
||||
|
||||
void Spawn();
|
||||
void Activate( void );
|
||||
void Think( void );
|
||||
|
||||
private:
|
||||
|
||||
void SampleVelocity( void );
|
||||
|
||||
EHANDLE m_hTargetEntity; // Entity whose angles are being monitored.
|
||||
Vector m_vecAxis; // Axis along which to measure the speed.
|
||||
bool m_bEnabled; // Whether we're measuring or not
|
||||
|
||||
// Outputs
|
||||
float m_fPrevVelocity; // stores velocity from last frame, so we only write the output if it has changed
|
||||
COutputFloat m_Velocity;
|
||||
|
||||
void InputEnable( inputdata_t &inputdata );
|
||||
void InputDisable( inputdata_t &inputdata );
|
||||
|
||||
DECLARE_DATADESC();
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( point_velocitysensor, CPointVelocitySensor );
|
||||
|
||||
BEGIN_DATADESC( CPointVelocitySensor )
|
||||
|
||||
// Fields
|
||||
DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ),
|
||||
DEFINE_KEYFIELD( m_vecAxis, FIELD_VECTOR, "axis" ),
|
||||
DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ),
|
||||
DEFINE_FIELD( m_fPrevVelocity, FIELD_FLOAT ),
|
||||
|
||||
// Outputs
|
||||
DEFINE_OUTPUT( m_Velocity, "Velocity" ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointVelocitySensor::Spawn()
|
||||
{
|
||||
Vector vLine = m_vecAxis - GetAbsOrigin();
|
||||
VectorNormalize( vLine );
|
||||
m_vecAxis = vLine;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointVelocitySensor::Activate( void )
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target );
|
||||
|
||||
if ( m_bEnabled && m_hTargetEntity )
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointVelocitySensor::InputEnable( inputdata_t &inputdata )
|
||||
{
|
||||
// Don't interrupt us if we're already enabled
|
||||
if ( m_bEnabled )
|
||||
return;
|
||||
|
||||
m_bEnabled = true;
|
||||
|
||||
if ( m_hTargetEntity )
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointVelocitySensor::InputDisable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bEnabled = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called every frame
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointVelocitySensor::Think( void )
|
||||
{
|
||||
if ( m_hTargetEntity != NULL && m_bEnabled )
|
||||
{
|
||||
SampleVelocity();
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns the magnitude of the entity's angular velocity.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointVelocitySensor::SampleVelocity( void )
|
||||
{
|
||||
if ( m_hTargetEntity == NULL )
|
||||
return;
|
||||
|
||||
Vector vecVelocity;
|
||||
|
||||
if ( m_hTargetEntity->GetMoveType() == MOVETYPE_VPHYSICS )
|
||||
{
|
||||
IPhysicsObject *pPhys = m_hTargetEntity->VPhysicsGetObject();
|
||||
if ( pPhys != NULL )
|
||||
{
|
||||
pPhys->GetVelocity( &vecVelocity, NULL );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vecVelocity = m_hTargetEntity->GetAbsVelocity();
|
||||
}
|
||||
|
||||
/*
|
||||
float flSpeed = VectorNormalize( vecVelocity );
|
||||
float flDot = ( m_vecAxis != vec3_origin ) ? DotProduct( vecVelocity, m_vecAxis ) : 1.0f;
|
||||
*/
|
||||
// We want the component of the velocity vector in the direction of the axis, which since the
|
||||
// axis is normalized is simply their dot product (eg V . A = |V|*|A|*cos(theta) )
|
||||
m_fPrevVelocity = ( m_vecAxis != vec3_origin ) ? DotProduct( vecVelocity, m_vecAxis ) : 1.0f;
|
||||
|
||||
// if it's changed since the last frame, poke the output
|
||||
if ( m_fPrevVelocity != m_Velocity.Get() )
|
||||
{
|
||||
m_Velocity.Set( m_fPrevVelocity, NULL, NULL );
|
||||
}
|
||||
}
|
||||
478
sp/src/game/server/RagdollBoogie.cpp
Normal file
478
sp/src/game/server/RagdollBoogie.cpp
Normal file
@@ -0,0 +1,478 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Dissolve entity to be attached to target entity. Serves two purposes:
|
||||
//
|
||||
// 1) An entity that can be placed by a level designer and triggered
|
||||
// to ignite a target entity.
|
||||
//
|
||||
// 2) An entity that can be created at runtime to ignite a target entity.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "RagdollBoogie.h"
|
||||
#include "physics_prop_ragdoll.h"
|
||||
#include "effect_dispatch_data.h"
|
||||
#include "te_effect_dispatch.h"
|
||||
#include "IEffects.h"
|
||||
#ifdef MAPBASE
|
||||
#include "saverestore_utlvector.h"
|
||||
#include "interval.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Make electriciy every so often
|
||||
//-----------------------------------------------------------------------------
|
||||
static const char *s_pZapContext = "ZapContext";
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Save/load
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_DATADESC( CRagdollBoogie )
|
||||
|
||||
DEFINE_FIELD( m_flStartTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_flBoogieLength, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flMagnitude, FIELD_FLOAT ),
|
||||
|
||||
// Think this should be handled by StartTouch/etc.
|
||||
// DEFINE_FIELD( m_nSuppressionCount, FIELD_INTEGER ),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_FIELD( m_vecColor, FIELD_VECTOR ),
|
||||
#endif
|
||||
|
||||
DEFINE_FUNCTION( BoogieThink ),
|
||||
DEFINE_FUNCTION( ZapThink ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_ragdoll_boogie, CRagdollBoogie );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Creates a flame and attaches it to a target entity.
|
||||
// Input : pTarget -
|
||||
//-----------------------------------------------------------------------------
|
||||
CRagdollBoogie *CRagdollBoogie::Create( CBaseEntity *pTarget, float flMagnitude,
|
||||
#ifdef MAPBASE
|
||||
float flStartTime, float flLengthTime, int nSpawnFlags, const Vector *vecColor )
|
||||
#else
|
||||
float flStartTime, float flLengthTime, int nSpawnFlags )
|
||||
#endif
|
||||
{
|
||||
CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( pTarget );
|
||||
if ( !pRagdoll )
|
||||
return NULL;
|
||||
|
||||
CRagdollBoogie *pBoogie = (CRagdollBoogie *)CreateEntityByName( "env_ragdoll_boogie" );
|
||||
if ( pBoogie == NULL )
|
||||
return NULL;
|
||||
|
||||
pBoogie->AddSpawnFlags( nSpawnFlags );
|
||||
pBoogie->AttachToEntity( pTarget );
|
||||
pBoogie->SetBoogieTime( flStartTime, flLengthTime );
|
||||
pBoogie->SetMagnitude( flMagnitude );
|
||||
#ifdef MAPBASE
|
||||
if (vecColor != NULL)
|
||||
pBoogie->SetColor( *vecColor );
|
||||
#endif
|
||||
pBoogie->Spawn();
|
||||
return pBoogie;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Spawn
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRagdollBoogie::Spawn()
|
||||
{
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetThink( &CRagdollBoogie::BoogieThink );
|
||||
SetNextThink( gpGlobals->curtime + 0.01f );
|
||||
|
||||
if ( HasSpawnFlags( SF_RAGDOLL_BOOGIE_ELECTRICAL ) )
|
||||
{
|
||||
SetContextThink( &CRagdollBoogie::ZapThink, gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ), s_pZapContext );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Zap!
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRagdollBoogie::ZapThink()
|
||||
{
|
||||
if ( !GetMoveParent() )
|
||||
return;
|
||||
|
||||
CBaseAnimating *pRagdoll = GetMoveParent()->GetBaseAnimating();
|
||||
if ( !pRagdoll )
|
||||
return;
|
||||
|
||||
// Make electricity on the client
|
||||
CStudioHdr *pStudioHdr = pRagdoll->GetModelPtr( );
|
||||
if (!pStudioHdr)
|
||||
return;
|
||||
|
||||
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pRagdoll->GetHitboxSet() );
|
||||
|
||||
if ( set->numhitboxes == 0 )
|
||||
return;
|
||||
|
||||
if ( m_nSuppressionCount == 0 )
|
||||
{
|
||||
CEffectData data;
|
||||
|
||||
data.m_nEntIndex = GetMoveParent()->entindex();
|
||||
data.m_flMagnitude = 4;
|
||||
data.m_flScale = HasSpawnFlags(SF_RAGDOLL_BOOGIE_ELECTRICAL_NARROW_BEAM) ? 1.0f : 2.0f;
|
||||
#ifdef MAPBASE
|
||||
if (!m_vecColor.IsZero())
|
||||
{
|
||||
data.m_bCustomColors = true;
|
||||
data.m_CustomColors.m_vecColor1 = m_vecColor;
|
||||
}
|
||||
#endif
|
||||
|
||||
DispatchEffect( "TeslaHitboxes", data );
|
||||
}
|
||||
|
||||
#ifdef HL2_EPISODIC
|
||||
EmitSound( "RagdollBoogie.Zap" );
|
||||
#endif
|
||||
|
||||
SetContextThink( &CRagdollBoogie::ZapThink, gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ), s_pZapContext );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Suppression count
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRagdollBoogie::IncrementSuppressionCount( CBaseEntity *pTarget )
|
||||
{
|
||||
// Look for other boogies on the ragdoll + kill them
|
||||
for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
|
||||
{
|
||||
CRagdollBoogie *pBoogie = dynamic_cast<CRagdollBoogie*>(pChild);
|
||||
if ( !pBoogie )
|
||||
continue;
|
||||
|
||||
++pBoogie->m_nSuppressionCount;
|
||||
}
|
||||
}
|
||||
|
||||
void CRagdollBoogie::DecrementSuppressionCount( CBaseEntity *pTarget )
|
||||
{
|
||||
// Look for other boogies on the ragdoll + kill them
|
||||
CBaseEntity *pNext;
|
||||
for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext )
|
||||
{
|
||||
pNext = pChild->NextMovePeer();
|
||||
CRagdollBoogie *pBoogie = dynamic_cast<CRagdollBoogie*>(pChild);
|
||||
if ( !pBoogie )
|
||||
continue;
|
||||
|
||||
if ( --pBoogie->m_nSuppressionCount <= 0 )
|
||||
{
|
||||
pBoogie->m_nSuppressionCount = 0;
|
||||
|
||||
float dt = gpGlobals->curtime - pBoogie->m_flStartTime;
|
||||
if ( dt >= pBoogie->m_flBoogieLength )
|
||||
{
|
||||
PhysCallbackRemove( pBoogie->NetworkProp() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Attach to an entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRagdollBoogie::AttachToEntity( CBaseEntity *pTarget )
|
||||
{
|
||||
m_nSuppressionCount = 0;
|
||||
|
||||
// Look for other boogies on the ragdoll + kill them
|
||||
CBaseEntity *pNext;
|
||||
for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext )
|
||||
{
|
||||
pNext = pChild->NextMovePeer();
|
||||
CRagdollBoogie *pBoogie = dynamic_cast<CRagdollBoogie*>(pChild);
|
||||
if ( !pBoogie )
|
||||
continue;
|
||||
|
||||
m_nSuppressionCount = pBoogie->m_nSuppressionCount;
|
||||
UTIL_Remove( pChild );
|
||||
}
|
||||
|
||||
FollowEntity( pTarget );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : lifetime -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRagdollBoogie::SetBoogieTime( float flStartTime, float flLengthTime )
|
||||
{
|
||||
m_flStartTime = flStartTime;
|
||||
m_flBoogieLength = flLengthTime;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Burn targets around us
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRagdollBoogie::SetMagnitude( float flMagnitude )
|
||||
{
|
||||
m_flMagnitude = flMagnitude;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Burn targets around us
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRagdollBoogie::BoogieThink( void )
|
||||
{
|
||||
CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( GetMoveParent() );
|
||||
if ( !pRagdoll )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
|
||||
float flMagnitude = m_flMagnitude;
|
||||
if ( m_flBoogieLength != 0 )
|
||||
{
|
||||
float dt = gpGlobals->curtime - m_flStartTime;
|
||||
if ( dt >= m_flBoogieLength )
|
||||
{
|
||||
// Don't remove while suppressed... this helps if we try to start another boogie
|
||||
if ( m_nSuppressionCount == 0 )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
}
|
||||
SetThink( NULL );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( dt < 0 )
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ) );
|
||||
return;
|
||||
}
|
||||
|
||||
flMagnitude = SimpleSplineRemapVal( dt, 0.0f, m_flBoogieLength, m_flMagnitude, 0.0f );
|
||||
}
|
||||
|
||||
#ifndef _XBOX
|
||||
if ( m_nSuppressionCount == 0 )
|
||||
{
|
||||
ragdoll_t *pRagdollPhys = pRagdoll->GetRagdoll( );
|
||||
for ( int j = 0; j < pRagdollPhys->listCount; ++j )
|
||||
{
|
||||
float flMass = pRagdollPhys->list[j].pObject->GetMass();
|
||||
float flForce = m_flMagnitude * flMass;
|
||||
|
||||
Vector vecForce;
|
||||
vecForce = RandomVector( -flForce, flForce );
|
||||
pRagdollPhys->list[j].pObject->ApplyForceCenter( vecForce );
|
||||
}
|
||||
}
|
||||
#endif // !_XBOX
|
||||
|
||||
SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ) );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Allows mappers to control ragdoll dancing
|
||||
//-----------------------------------------------------------------------------
|
||||
class CPointRagdollBoogie : public CBaseEntity
|
||||
{
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_CLASS( CPointRagdollBoogie, CBaseEntity );
|
||||
|
||||
public:
|
||||
bool ApplyBoogie(CBaseEntity *pTarget, CBaseEntity *pActivator);
|
||||
|
||||
void InputActivate( inputdata_t &inputdata );
|
||||
void InputDeactivate( inputdata_t &inputdata );
|
||||
void InputBoogieTarget( inputdata_t &inputdata );
|
||||
void InputSetZapColor( inputdata_t &inputdata );
|
||||
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
|
||||
private:
|
||||
float m_flStartTime;
|
||||
interval_t m_BoogieLength;
|
||||
float m_flMagnitude;
|
||||
|
||||
Vector m_vecZapColor;
|
||||
|
||||
// This allows us to change or remove active boogies later.
|
||||
CUtlVector<CHandle<CRagdollBoogie>> m_Boogies;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Save/load
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_DATADESC( CPointRagdollBoogie )
|
||||
|
||||
DEFINE_KEYFIELD( m_flStartTime, FIELD_FLOAT, "StartTime" ),
|
||||
DEFINE_KEYFIELD( m_BoogieLength, FIELD_INTERVAL, "BoogieLength" ),
|
||||
DEFINE_KEYFIELD( m_flMagnitude, FIELD_FLOAT, "Magnitude" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_vecZapColor, FIELD_VECTOR, "ZapColor" ),
|
||||
|
||||
// Think this should be handled by StartTouch/etc.
|
||||
// DEFINE_FIELD( m_nSuppressionCount, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_UTLVECTOR( m_Boogies, FIELD_EHANDLE ),
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "BoogieTarget", InputBoogieTarget ),
|
||||
DEFINE_INPUTFUNC( FIELD_VECTOR, "SetZapColor", InputSetZapColor ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( point_ragdollboogie, CPointRagdollBoogie );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPointRagdollBoogie::ApplyBoogie( CBaseEntity *pTarget, CBaseEntity *pActivator )
|
||||
{
|
||||
if (dynamic_cast<CRagdollProp*>(pTarget))
|
||||
{
|
||||
m_Boogies.AddToTail(CRagdollBoogie::Create(pTarget, m_flMagnitude, gpGlobals->curtime + m_flStartTime, RandomInterval(m_BoogieLength), GetSpawnFlags(), &m_vecZapColor));
|
||||
}
|
||||
else if (pTarget->MyCombatCharacterPointer())
|
||||
{
|
||||
// Basically CBaseCombatCharacter::BecomeRagdollBoogie(), but adjusted to our needs
|
||||
CTakeDamageInfo info(this, pActivator, 1.0f, DMG_GENERIC);
|
||||
|
||||
CBaseEntity *pRagdoll = CreateServerRagdoll(pTarget->MyCombatCharacterPointer(), 0, info, COLLISION_GROUP_INTERACTIVE_DEBRIS, true);
|
||||
|
||||
pRagdoll->SetCollisionBounds(CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs());
|
||||
|
||||
m_Boogies.AddToTail(CRagdollBoogie::Create(pRagdoll, m_flMagnitude, gpGlobals->curtime + m_flStartTime, RandomInterval(m_BoogieLength), GetSpawnFlags(), &m_vecZapColor));
|
||||
|
||||
CTakeDamageInfo ragdollInfo(this, pActivator, 10000.0, DMG_GENERIC | DMG_REMOVENORAGDOLL);
|
||||
ragdollInfo.SetDamagePosition(WorldSpaceCenter());
|
||||
ragdollInfo.SetDamageForce(Vector(0, 0, 1));
|
||||
ragdollInfo.SetForceFriendlyFire(true);
|
||||
pTarget->TakeDamage(ragdollInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointRagdollBoogie::InputActivate( inputdata_t &inputdata )
|
||||
{
|
||||
CBaseEntity *pEnt = gEntList.FindEntityByName(NULL, STRING(m_target), this, inputdata.pActivator, inputdata.pCaller);
|
||||
while (pEnt)
|
||||
{
|
||||
ApplyBoogie(pEnt, inputdata.pActivator);
|
||||
|
||||
pEnt = gEntList.FindEntityByName(pEnt, STRING(m_target), this, inputdata.pActivator, inputdata.pCaller);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointRagdollBoogie::InputDeactivate( inputdata_t &inputdata )
|
||||
{
|
||||
if (m_Boogies.Count() == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < m_Boogies.Count(); i++)
|
||||
{
|
||||
UTIL_Remove(m_Boogies[i]);
|
||||
}
|
||||
|
||||
m_Boogies.Purge();
|
||||
|
||||
//m_Boogies.RemoveAll();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointRagdollBoogie::InputBoogieTarget( inputdata_t &inputdata )
|
||||
{
|
||||
CBaseEntity *pEnt = gEntList.FindEntityByName(NULL, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller);
|
||||
while (pEnt)
|
||||
{
|
||||
if (!ApplyBoogie(pEnt, inputdata.pActivator))
|
||||
{
|
||||
Warning("%s was unable to apply ragdoll boogie to %s, classname %s.\n", GetDebugName(), pEnt->GetDebugName(), pEnt->GetClassname());
|
||||
}
|
||||
|
||||
pEnt = gEntList.FindEntityByName(pEnt, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointRagdollBoogie::InputSetZapColor( inputdata_t &inputdata )
|
||||
{
|
||||
inputdata.value.Vector3D( m_vecZapColor );
|
||||
if (!m_vecZapColor.IsZero())
|
||||
{
|
||||
// Turn into ratios of 255
|
||||
m_vecZapColor /= 255.0f;
|
||||
}
|
||||
|
||||
// Apply to existing boogies
|
||||
for (int i = 0; i < m_Boogies.Count(); i++)
|
||||
{
|
||||
if (m_Boogies[i])
|
||||
{
|
||||
m_Boogies[i]->SetColor( m_vecZapColor );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles key values from the BSP before spawn is called.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPointRagdollBoogie::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "ZapColor" ) )
|
||||
{
|
||||
UTIL_StringToVector(m_vecZapColor.Base(), szValue);
|
||||
if (!m_vecZapColor.IsZero())
|
||||
{
|
||||
// Turn into ratios of 255
|
||||
m_vecZapColor /= 255.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
62
sp/src/game/server/RagdollBoogie.h
Normal file
62
sp/src/game/server/RagdollBoogie.h
Normal file
@@ -0,0 +1,62 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef RAGDOLLBOOGIE_H
|
||||
#define RAGDOLLBOOGIE_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set this spawnflag before calling Spawn to get electrical effects
|
||||
//-----------------------------------------------------------------------------
|
||||
#define SF_RAGDOLL_BOOGIE_ELECTRICAL 0x10000
|
||||
#define SF_RAGDOLL_BOOGIE_ELECTRICAL_NARROW_BEAM 0x20000
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Makes ragdolls DANCE!
|
||||
//-----------------------------------------------------------------------------
|
||||
class CRagdollBoogie : public CBaseEntity
|
||||
{
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_CLASS( CRagdollBoogie, CBaseEntity );
|
||||
|
||||
public:
|
||||
#ifdef MAPBASE
|
||||
static CRagdollBoogie *Create( CBaseEntity *pTarget, float flMagnitude, float flStartTime, float flLengthTime = 0.0f, int nSpawnFlags = 0, const Vector *vecColor = NULL );
|
||||
#else
|
||||
static CRagdollBoogie *Create( CBaseEntity *pTarget, float flMagnitude, float flStartTime, float flLengthTime = 0.0f, int nSpawnFlags = 0 );
|
||||
#endif
|
||||
static void IncrementSuppressionCount( CBaseEntity *pTarget );
|
||||
static void DecrementSuppressionCount( CBaseEntity *pTarget );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void SetColor( const Vector &vecColor ) { m_vecColor = vecColor; }
|
||||
#endif
|
||||
|
||||
void Spawn();
|
||||
|
||||
private:
|
||||
void AttachToEntity( CBaseEntity *pTarget );
|
||||
void SetBoogieTime( float flStartTime, float flLengthTime );
|
||||
void SetMagnitude( float flMagnitude );
|
||||
void BoogieThink( void );
|
||||
void ZapThink();
|
||||
|
||||
float m_flStartTime;
|
||||
float m_flBoogieLength;
|
||||
float m_flMagnitude;
|
||||
int m_nSuppressionCount;
|
||||
|
||||
#ifdef MAPBASE
|
||||
Vector m_vecColor = Vector(1, 1, 1);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // RAGDOLLBOOGIE_H
|
||||
305
sp/src/game/server/ServerNetworkProperty.cpp
Normal file
305
sp/src/game/server/ServerNetworkProperty.cpp
Normal file
@@ -0,0 +1,305 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "ServerNetworkProperty.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "gameinterface.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern CTimedEventMgr g_NetworkPropertyEventMgr;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Save/load
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_DATADESC_NO_BASE( CServerNetworkProperty )
|
||||
// DEFINE_FIELD( m_pOuter, FIELD_CLASSPTR ),
|
||||
// DEFINE_FIELD( m_pPev, FIELD_CLASSPTR ),
|
||||
// DEFINE_FIELD( m_PVSInfo, PVSInfo_t ),
|
||||
// DEFINE_FIELD( m_pServerClass, FIELD_CLASSPTR ),
|
||||
DEFINE_GLOBAL_FIELD( m_hParent, FIELD_EHANDLE ),
|
||||
// DEFINE_FIELD( m_TimerEvent, CEventRegister ),
|
||||
// DEFINE_FIELD( m_bPendingStateChange, FIELD_BOOLEAN ),
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CServerNetworkProperty::CServerNetworkProperty()
|
||||
{
|
||||
Init( NULL );
|
||||
}
|
||||
|
||||
|
||||
CServerNetworkProperty::~CServerNetworkProperty()
|
||||
{
|
||||
/* Free our transmit proxy.
|
||||
if ( m_pTransmitProxy )
|
||||
{
|
||||
m_pTransmitProxy->Release();
|
||||
}*/
|
||||
|
||||
engine->CleanUpEntityClusterList( &m_PVSInfo );
|
||||
|
||||
// remove the attached edict if it exists
|
||||
DetachEdict();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Initialization
|
||||
//-----------------------------------------------------------------------------
|
||||
void CServerNetworkProperty::Init( CBaseEntity *pEntity )
|
||||
{
|
||||
m_pPev = NULL;
|
||||
m_pOuter = pEntity;
|
||||
m_pServerClass = NULL;
|
||||
// m_pTransmitProxy = NULL;
|
||||
m_bPendingStateChange = false;
|
||||
m_PVSInfo.m_nClusterCount = 0;
|
||||
m_TimerEvent.Init( &g_NetworkPropertyEventMgr, this );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Connects, disconnects edicts
|
||||
//-----------------------------------------------------------------------------
|
||||
void CServerNetworkProperty::AttachEdict( edict_t *pRequiredEdict )
|
||||
{
|
||||
Assert ( !m_pPev );
|
||||
|
||||
// see if there is an edict allocated for it, otherwise get one from the engine
|
||||
if ( !pRequiredEdict )
|
||||
{
|
||||
pRequiredEdict = engine->CreateEdict();
|
||||
}
|
||||
|
||||
m_pPev = pRequiredEdict;
|
||||
m_pPev->SetEdict( GetBaseEntity(), true );
|
||||
}
|
||||
|
||||
void CServerNetworkProperty::DetachEdict()
|
||||
{
|
||||
if ( m_pPev )
|
||||
{
|
||||
m_pPev->SetEdict( NULL, false );
|
||||
engine->RemoveEdict( m_pPev );
|
||||
m_pPev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Entity handles
|
||||
//-----------------------------------------------------------------------------
|
||||
IHandleEntity *CServerNetworkProperty::GetEntityHandle( )
|
||||
{
|
||||
return m_pOuter;
|
||||
}
|
||||
|
||||
void CServerNetworkProperty::Release()
|
||||
{
|
||||
delete m_pOuter;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the network parent
|
||||
//-----------------------------------------------------------------------------
|
||||
CServerNetworkProperty* CServerNetworkProperty::GetNetworkParent()
|
||||
{
|
||||
CBaseEntity *pParent = m_hParent.Get();
|
||||
return pParent ? pParent->NetworkProp() : NULL;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Marks for deletion
|
||||
//-----------------------------------------------------------------------------
|
||||
void CServerNetworkProperty::MarkForDeletion()
|
||||
{
|
||||
m_pOuter->AddEFlags( EFL_KILLME );
|
||||
}
|
||||
|
||||
bool CServerNetworkProperty::IsMarkedForDeletion() const
|
||||
{
|
||||
return ( m_pOuter->GetEFlags() & EFL_KILLME ) != 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PVS information
|
||||
//-----------------------------------------------------------------------------
|
||||
void CServerNetworkProperty::RecomputePVSInformation()
|
||||
{
|
||||
if ( m_pPev && ( ( m_pPev->m_fStateFlags & FL_EDICT_DIRTY_PVS_INFORMATION ) != 0 ) )
|
||||
{
|
||||
m_pPev->m_fStateFlags &= ~FL_EDICT_DIRTY_PVS_INFORMATION;
|
||||
engine->BuildEntityClusterList( edict(), &m_PVSInfo );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Serverclass
|
||||
//-----------------------------------------------------------------------------
|
||||
ServerClass* CServerNetworkProperty::GetServerClass()
|
||||
{
|
||||
if ( !m_pServerClass )
|
||||
m_pServerClass = m_pOuter->GetServerClass();
|
||||
return m_pServerClass;
|
||||
}
|
||||
|
||||
const char* CServerNetworkProperty::GetClassName() const
|
||||
{
|
||||
return STRING(m_pOuter->m_iClassname);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Transmit proxies
|
||||
/*-----------------------------------------------------------------------------
|
||||
void CServerNetworkProperty::SetTransmitProxy( CBaseTransmitProxy *pProxy )
|
||||
{
|
||||
if ( m_pTransmitProxy )
|
||||
{
|
||||
m_pTransmitProxy->Release();
|
||||
}
|
||||
|
||||
m_pTransmitProxy = pProxy;
|
||||
|
||||
if ( m_pTransmitProxy )
|
||||
{
|
||||
m_pTransmitProxy->AddRef();
|
||||
}
|
||||
}*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PVS rules
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CServerNetworkProperty::IsInPVS( const edict_t *pRecipient, const void *pvs, int pvssize )
|
||||
{
|
||||
RecomputePVSInformation();
|
||||
|
||||
// ignore if not touching a PV leaf
|
||||
// negative leaf count is a node number
|
||||
// If no pvs, add any entity
|
||||
|
||||
Assert( pvs && ( edict() != pRecipient ) );
|
||||
|
||||
unsigned char *pPVS = ( unsigned char * )pvs;
|
||||
|
||||
if ( m_PVSInfo.m_nClusterCount < 0 ) // too many clusters, use headnode
|
||||
{
|
||||
return ( engine->CheckHeadnodeVisible( m_PVSInfo.m_nHeadNode, pPVS, pvssize ) != 0);
|
||||
}
|
||||
|
||||
for ( int i = m_PVSInfo.m_nClusterCount; --i >= 0; )
|
||||
{
|
||||
if (pPVS[m_PVSInfo.m_pClusters[i] >> 3] & (1 << (m_PVSInfo.m_pClusters[i] & 7) ))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // not visible
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PVS: this function is called a lot, so it avoids function calls
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CServerNetworkProperty::IsInPVS( const CCheckTransmitInfo *pInfo )
|
||||
{
|
||||
// PVS data must be up to date
|
||||
Assert( !m_pPev || ( ( m_pPev->m_fStateFlags & FL_EDICT_DIRTY_PVS_INFORMATION ) == 0 ) );
|
||||
|
||||
int i;
|
||||
|
||||
// Early out if the areas are connected
|
||||
if ( !m_PVSInfo.m_nAreaNum2 )
|
||||
{
|
||||
for ( i=0; i< pInfo->m_AreasNetworked; i++ )
|
||||
{
|
||||
int clientArea = pInfo->m_Areas[i];
|
||||
if ( clientArea == m_PVSInfo.m_nAreaNum || engine->CheckAreasConnected( clientArea, m_PVSInfo.m_nAreaNum ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// doors can legally straddle two areas, so
|
||||
// we may need to check another one
|
||||
for ( i=0; i< pInfo->m_AreasNetworked; i++ )
|
||||
{
|
||||
int clientArea = pInfo->m_Areas[i];
|
||||
if ( clientArea == m_PVSInfo.m_nAreaNum || clientArea == m_PVSInfo.m_nAreaNum2 )
|
||||
break;
|
||||
|
||||
if ( engine->CheckAreasConnected( clientArea, m_PVSInfo.m_nAreaNum ) )
|
||||
break;
|
||||
|
||||
if ( engine->CheckAreasConnected( clientArea, m_PVSInfo.m_nAreaNum2 ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( i == pInfo->m_AreasNetworked )
|
||||
{
|
||||
// areas not connected
|
||||
return false;
|
||||
}
|
||||
|
||||
// ignore if not touching a PV leaf
|
||||
// negative leaf count is a node number
|
||||
// If no pvs, add any entity
|
||||
|
||||
Assert( edict() != pInfo->m_pClientEnt );
|
||||
|
||||
unsigned char *pPVS = ( unsigned char * )pInfo->m_PVS;
|
||||
|
||||
if ( m_PVSInfo.m_nClusterCount < 0 ) // too many clusters, use headnode
|
||||
{
|
||||
return (engine->CheckHeadnodeVisible( m_PVSInfo.m_nHeadNode, pPVS, pInfo->m_nPVSSize ) != 0);
|
||||
}
|
||||
|
||||
for ( i = m_PVSInfo.m_nClusterCount; --i >= 0; )
|
||||
{
|
||||
int nCluster = m_PVSInfo.m_pClusters[i];
|
||||
if ( ((int)(pPVS[nCluster >> 3])) & BitVec_BitInByte( nCluster ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // not visible
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CServerNetworkProperty::SetUpdateInterval( float val )
|
||||
{
|
||||
if ( val == 0 )
|
||||
m_TimerEvent.StopUpdates();
|
||||
else
|
||||
m_TimerEvent.SetUpdateInterval( val );
|
||||
}
|
||||
|
||||
|
||||
void CServerNetworkProperty::FireEvent()
|
||||
{
|
||||
// Our timer went off. If our state has changed in the background, then
|
||||
// trigger a state change in the edict.
|
||||
if ( m_bPendingStateChange )
|
||||
{
|
||||
m_pPev->StateChanged();
|
||||
m_bPendingStateChange = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
258
sp/src/game/server/ServerNetworkProperty.h
Normal file
258
sp/src/game/server/ServerNetworkProperty.h
Normal file
@@ -0,0 +1,258 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef SERVERNETWORKPROPERTY_H
|
||||
#define SERVERNETWORKPROPERTY_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "iservernetworkable.h"
|
||||
#include "server_class.h"
|
||||
#include "edict.h"
|
||||
#include "timedeventmgr.h"
|
||||
|
||||
//
|
||||
// Lightweight base class for networkable data on the server.
|
||||
//
|
||||
class CServerNetworkProperty : public IServerNetworkable, public IEventRegisterCallback
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS_NOBASE( CServerNetworkProperty );
|
||||
DECLARE_DATADESC();
|
||||
|
||||
public:
|
||||
CServerNetworkProperty();
|
||||
virtual ~CServerNetworkProperty();
|
||||
|
||||
public:
|
||||
// IServerNetworkable implementation.
|
||||
virtual IHandleEntity *GetEntityHandle( );
|
||||
virtual edict_t *GetEdict() const;
|
||||
virtual CBaseNetworkable* GetBaseNetworkable();
|
||||
virtual CBaseEntity* GetBaseEntity();
|
||||
virtual ServerClass* GetServerClass();
|
||||
virtual const char* GetClassName() const;
|
||||
virtual void Release();
|
||||
virtual int AreaNum() const;
|
||||
virtual PVSInfo_t* GetPVSInfo();
|
||||
|
||||
public:
|
||||
// Other public methods
|
||||
void Init( CBaseEntity *pEntity );
|
||||
|
||||
void AttachEdict( edict_t *pRequiredEdict = NULL );
|
||||
|
||||
// Methods to get the entindex + edict
|
||||
int entindex() const;
|
||||
edict_t *edict();
|
||||
const edict_t *edict() const;
|
||||
|
||||
// Sets the edict pointer (for swapping edicts)
|
||||
void SetEdict( edict_t *pEdict );
|
||||
|
||||
// All these functions call through to CNetStateMgr.
|
||||
// See CNetStateMgr for details about these functions.
|
||||
void NetworkStateForceUpdate();
|
||||
void NetworkStateChanged();
|
||||
void NetworkStateChanged( unsigned short offset );
|
||||
|
||||
// Marks the PVS information dirty
|
||||
void MarkPVSInformationDirty();
|
||||
|
||||
// Marks for deletion
|
||||
void MarkForDeletion();
|
||||
bool IsMarkedForDeletion() const;
|
||||
|
||||
// Sets the network parent
|
||||
void SetNetworkParent( EHANDLE hParent );
|
||||
CServerNetworkProperty* GetNetworkParent();
|
||||
|
||||
// This is useful for entities that don't change frequently or that the client
|
||||
// doesn't need updates on very often. If you use this mode, the server will only try to
|
||||
// detect state changes every N seconds, so it will save CPU cycles and bandwidth.
|
||||
//
|
||||
// Note: N must be less than AUTOUPDATE_MAX_TIME_LENGTH.
|
||||
//
|
||||
// Set back to zero to disable the feature.
|
||||
//
|
||||
// This feature works on top of manual mode.
|
||||
// - If you turn it on and manual mode is off, it will autodetect changes every N seconds.
|
||||
// - If you turn it on and manual mode is on, then every N seconds it will only say there
|
||||
// is a change if you've called NetworkStateChanged.
|
||||
void SetUpdateInterval( float N );
|
||||
|
||||
// You can use this to override any entity's ShouldTransmit behavior.
|
||||
// void SetTransmitProxy( CBaseTransmitProxy *pProxy );
|
||||
|
||||
// This version does a PVS check which also checks for connected areas
|
||||
bool IsInPVS( const CCheckTransmitInfo *pInfo );
|
||||
|
||||
// This version doesn't do the area check
|
||||
bool IsInPVS( const edict_t *pRecipient, const void *pvs, int pvssize );
|
||||
|
||||
// Called by the timed event manager when it's time to detect a state change.
|
||||
virtual void FireEvent();
|
||||
|
||||
// Recomputes PVS information
|
||||
void RecomputePVSInformation();
|
||||
|
||||
private:
|
||||
// Detaches the edict.. should only be called by CBaseNetworkable's destructor.
|
||||
void DetachEdict();
|
||||
CBaseEntity *GetOuter();
|
||||
|
||||
// Marks the networkable that it will should transmit
|
||||
void SetTransmit( CCheckTransmitInfo *pInfo );
|
||||
|
||||
private:
|
||||
CBaseEntity *m_pOuter;
|
||||
// CBaseTransmitProxy *m_pTransmitProxy;
|
||||
edict_t *m_pPev;
|
||||
PVSInfo_t m_PVSInfo;
|
||||
ServerClass *m_pServerClass;
|
||||
|
||||
// NOTE: This state is 'owned' by the entity. It's only copied here
|
||||
// also to help improve cache performance in networking code.
|
||||
EHANDLE m_hParent;
|
||||
|
||||
// Counters for SetUpdateInterval.
|
||||
CEventRegister m_TimerEvent;
|
||||
bool m_bPendingStateChange : 1;
|
||||
|
||||
// friend class CBaseTransmitProxy;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// inline methods // TODOMO does inline work on virtual functions ?
|
||||
//-----------------------------------------------------------------------------
|
||||
inline CBaseNetworkable* CServerNetworkProperty::GetBaseNetworkable()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline CBaseEntity* CServerNetworkProperty::GetBaseEntity()
|
||||
{
|
||||
return m_pOuter;
|
||||
}
|
||||
|
||||
inline CBaseEntity *CServerNetworkProperty::GetOuter()
|
||||
{
|
||||
return m_pOuter;
|
||||
}
|
||||
|
||||
inline PVSInfo_t *CServerNetworkProperty::GetPVSInfo()
|
||||
{
|
||||
return &m_PVSInfo;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Marks the PVS information dirty
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void CServerNetworkProperty::MarkPVSInformationDirty()
|
||||
{
|
||||
if ( m_pPev )
|
||||
{
|
||||
m_pPev->m_fStateFlags |= FL_EDICT_DIRTY_PVS_INFORMATION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets/gets the network parent
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void CServerNetworkProperty::SetNetworkParent( EHANDLE hParent )
|
||||
{
|
||||
m_hParent = hParent;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Methods related to the net state mgr
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void CServerNetworkProperty::NetworkStateForceUpdate()
|
||||
{
|
||||
if ( m_pPev )
|
||||
m_pPev->StateChanged();
|
||||
}
|
||||
|
||||
inline void CServerNetworkProperty::NetworkStateChanged()
|
||||
{
|
||||
// If we're using the timer, then ignore this call.
|
||||
if ( m_TimerEvent.IsRegistered() )
|
||||
{
|
||||
// If we're waiting for a timer event, then queue the change so it happens
|
||||
// when the timer goes off.
|
||||
m_bPendingStateChange = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_pPev )
|
||||
m_pPev->StateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
inline void CServerNetworkProperty::NetworkStateChanged( unsigned short varOffset )
|
||||
{
|
||||
// If we're using the timer, then ignore this call.
|
||||
if ( m_TimerEvent.IsRegistered() )
|
||||
{
|
||||
// If we're waiting for a timer event, then queue the change so it happens
|
||||
// when the timer goes off.
|
||||
m_bPendingStateChange = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_pPev )
|
||||
m_pPev->StateChanged( varOffset );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Methods to get the entindex + edict
|
||||
//-----------------------------------------------------------------------------
|
||||
inline int CServerNetworkProperty::entindex() const
|
||||
{
|
||||
return ENTINDEX( m_pPev );
|
||||
}
|
||||
|
||||
inline edict_t* CServerNetworkProperty::GetEdict() const
|
||||
{
|
||||
// This one's virtual, that's why we have to two other versions
|
||||
return m_pPev;
|
||||
}
|
||||
|
||||
inline edict_t *CServerNetworkProperty::edict()
|
||||
{
|
||||
return m_pPev;
|
||||
}
|
||||
|
||||
inline const edict_t *CServerNetworkProperty::edict() const
|
||||
{
|
||||
return m_pPev;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the edict pointer (for swapping edicts)
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void CServerNetworkProperty::SetEdict( edict_t *pEdict )
|
||||
{
|
||||
m_pPev = pEdict;
|
||||
}
|
||||
|
||||
|
||||
inline int CServerNetworkProperty::AreaNum() const
|
||||
{
|
||||
const_cast<CServerNetworkProperty*>(this)->RecomputePVSInformation();
|
||||
return m_PVSInfo.m_nAreaNum;
|
||||
}
|
||||
|
||||
|
||||
#endif // SERVERNETWORKPROPERTY_H
|
||||
462
sp/src/game/server/SkyCamera.cpp
Normal file
462
sp/src/game/server/SkyCamera.cpp
Normal file
@@ -0,0 +1,462 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "igamesystem.h"
|
||||
#include "entitylist.h"
|
||||
#include "SkyCamera.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// automatically hooks in the system's callbacks
|
||||
CEntityClassList<CSkyCamera> g_SkyList;
|
||||
template <> CSkyCamera *CEntityClassList<CSkyCamera>::m_pClassList = NULL;
|
||||
#ifdef MAPBASE
|
||||
CHandle<CSkyCamera> g_hActiveSkybox = NULL;
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Retrives the current skycamera
|
||||
//-----------------------------------------------------------------------------
|
||||
CSkyCamera* GetCurrentSkyCamera()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if ( g_hActiveSkybox.Get() == NULL )
|
||||
{
|
||||
g_hActiveSkybox = GetSkyCameraList();
|
||||
}
|
||||
return g_hActiveSkybox.Get();
|
||||
#else
|
||||
return g_SkyList.m_pClassList;
|
||||
#endif
|
||||
}
|
||||
|
||||
CSkyCamera* GetSkyCameraList()
|
||||
{
|
||||
return g_SkyList.m_pClassList;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
LINK_ENTITY_TO_CLASS( sky_camera, CSkyCamera );
|
||||
|
||||
BEGIN_DATADESC( CSkyCamera )
|
||||
|
||||
DEFINE_KEYFIELD( m_skyboxData.scale, FIELD_INTEGER, "scale" ),
|
||||
DEFINE_FIELD( m_skyboxData.origin, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_skyboxData.area, FIELD_INTEGER ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_FIELD( m_skyboxData.angles, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_skyboxData.skycamera, FIELD_EHANDLE ),
|
||||
DEFINE_KEYFIELD( m_skyboxData.skycolor, FIELD_COLOR32, "skycolor" ),
|
||||
DEFINE_KEYFIELD( m_bUseAnglesForSky, FIELD_BOOLEAN, "use_angles_for_sky" ),
|
||||
#endif
|
||||
|
||||
// Quiet down classcheck
|
||||
// DEFINE_FIELD( m_skyboxData, sky3dparams_t ),
|
||||
|
||||
// This is re-set up in the constructor
|
||||
// DEFINE_FIELD( m_pNext, CSkyCamera ),
|
||||
|
||||
// fog data for 3d skybox
|
||||
DEFINE_KEYFIELD( m_bUseAngles, FIELD_BOOLEAN, "use_angles" ),
|
||||
DEFINE_KEYFIELD( m_skyboxData.fog.enable, FIELD_BOOLEAN, "fogenable" ),
|
||||
DEFINE_KEYFIELD( m_skyboxData.fog.blend, FIELD_BOOLEAN, "fogblend" ),
|
||||
DEFINE_KEYFIELD( m_skyboxData.fog.dirPrimary, FIELD_VECTOR, "fogdir" ),
|
||||
DEFINE_KEYFIELD( m_skyboxData.fog.colorPrimary, FIELD_COLOR32, "fogcolor" ),
|
||||
DEFINE_KEYFIELD( m_skyboxData.fog.colorSecondary, FIELD_COLOR32, "fogcolor2" ),
|
||||
DEFINE_KEYFIELD( m_skyboxData.fog.start, FIELD_FLOAT, "fogstart" ),
|
||||
DEFINE_KEYFIELD( m_skyboxData.fog.end, FIELD_FLOAT, "fogend" ),
|
||||
DEFINE_KEYFIELD( m_skyboxData.fog.maxdensity, FIELD_FLOAT, "fogmaxdensity" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_skyboxData.fog.farz, FIELD_FLOAT, "farz" ),
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ForceUpdate", InputForceUpdate ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StartUpdating", InputStartUpdating ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StopUpdating", InputStopUpdating ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ActivateSkybox", InputActivateSkybox ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "DeactivateSkybox", InputDeactivateSkybox ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFogStartDist", InputSetFogStartDist ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFogEndDist", InputSetFogEndDist ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFogMaxDensity", InputSetFogMaxDensity ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOnFog", InputTurnOnFog ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOffFog", InputTurnOffFog ),
|
||||
DEFINE_INPUTFUNC( FIELD_COLOR32, "SetFogColor", InputSetFogColor ),
|
||||
DEFINE_INPUTFUNC( FIELD_COLOR32, "SetFogColorSecondary", InputSetFogColorSecondary ),
|
||||
DEFINE_INPUTFUNC( FIELD_EHANDLE, "CopyFogController", InputCopyFogController ),
|
||||
DEFINE_INPUTFUNC( FIELD_EHANDLE, "CopyFogControllerWithScale", InputCopyFogControllerWithScale ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetFarZ", InputSetFarZ ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_COLOR32, "SetSkyColor", InputSetSkyColor ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetScale", InputSetScale ),
|
||||
|
||||
DEFINE_THINKFUNC( UpdateThink ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// List of maps in HL2 that we must apply our skybox fog fixup hack to
|
||||
//-----------------------------------------------------------------------------
|
||||
static const char *s_pBogusFogMaps[] =
|
||||
{
|
||||
"d1_canals_01",
|
||||
"d1_canals_01a",
|
||||
"d1_canals_02",
|
||||
"d1_canals_03",
|
||||
"d1_canals_09",
|
||||
"d1_canals_10",
|
||||
"d1_canals_11",
|
||||
"d1_canals_12",
|
||||
"d1_canals_13",
|
||||
"d1_eli_01",
|
||||
"d1_trainstation_01",
|
||||
"d1_trainstation_03",
|
||||
"d1_trainstation_04",
|
||||
"d1_trainstation_05",
|
||||
"d1_trainstation_06",
|
||||
"d3_c17_04",
|
||||
"d3_c17_11",
|
||||
"d3_c17_12",
|
||||
"d3_citadel_01",
|
||||
NULL
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CSkyCamera::CSkyCamera()
|
||||
{
|
||||
g_SkyList.Insert( this );
|
||||
m_skyboxData.fog.maxdensity = 1.0f;
|
||||
#ifdef MAPBASE
|
||||
m_skyboxData.skycolor.Init(0, 0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
CSkyCamera::~CSkyCamera()
|
||||
{
|
||||
g_SkyList.Remove( this );
|
||||
}
|
||||
|
||||
void CSkyCamera::Spawn( void )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (HasSpawnFlags(SF_SKY_MASTER))
|
||||
g_hActiveSkybox = this;
|
||||
|
||||
if (HasSpawnFlags(SF_SKY_START_UPDATING))
|
||||
{
|
||||
SetCameraEntityMode();
|
||||
|
||||
SetThink( &CSkyCamera::UpdateThink );
|
||||
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCameraPositionMode();
|
||||
}
|
||||
#else
|
||||
m_skyboxData.origin = GetLocalOrigin();
|
||||
#endif
|
||||
m_skyboxData.area = engine->GetArea( m_skyboxData.origin );
|
||||
|
||||
Precache();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Activate!
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSkyCamera::Activate( )
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
if ( m_bUseAngles )
|
||||
{
|
||||
AngleVectors( GetAbsAngles(), &m_skyboxData.fog.dirPrimary.GetForModify() );
|
||||
m_skyboxData.fog.dirPrimary.GetForModify() *= -1.0f;
|
||||
}
|
||||
|
||||
#ifdef HL2_DLL
|
||||
// NOTE! This is a hack. There was a bug in the skybox fog computation
|
||||
// on the client DLL that caused it to use the average of the primary and
|
||||
// secondary fog color when blending was enabled. The bug is fixed, but to make
|
||||
// the maps look the same as before the bug fix without having to download new maps,
|
||||
// I have to cheat here and slam the primary and secondary colors to be the average of
|
||||
// the primary and secondary colors.
|
||||
if ( m_skyboxData.fog.blend )
|
||||
{
|
||||
for ( int i = 0; s_pBogusFogMaps[i]; ++i )
|
||||
{
|
||||
if ( !Q_stricmp( s_pBogusFogMaps[i], STRING(gpGlobals->mapname) ) )
|
||||
{
|
||||
m_skyboxData.fog.colorPrimary.SetR( ( m_skyboxData.fog.colorPrimary.GetR() + m_skyboxData.fog.colorSecondary.GetR() ) * 0.5f );
|
||||
m_skyboxData.fog.colorPrimary.SetG( ( m_skyboxData.fog.colorPrimary.GetG() + m_skyboxData.fog.colorSecondary.GetG() ) * 0.5f );
|
||||
m_skyboxData.fog.colorPrimary.SetB( ( m_skyboxData.fog.colorPrimary.GetB() + m_skyboxData.fog.colorSecondary.GetB() ) * 0.5f );
|
||||
m_skyboxData.fog.colorPrimary.SetA( ( m_skyboxData.fog.colorPrimary.GetA() + m_skyboxData.fog.colorSecondary.GetA() ) * 0.5f );
|
||||
m_skyboxData.fog.colorSecondary = m_skyboxData.fog.colorPrimary;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CSkyCamera::AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID )
|
||||
{
|
||||
if (!BaseClass::AcceptInput( szInputName, pActivator, pCaller, Value, outputID ))
|
||||
return false;
|
||||
|
||||
if (g_hActiveSkybox == this)
|
||||
{
|
||||
// Most inputs require an update
|
||||
DoUpdate( true );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSkyCamera::SetCameraEntityMode()
|
||||
{
|
||||
m_skyboxData.skycamera = this;
|
||||
|
||||
// Ensure the viewrender knows whether this should be using angles
|
||||
if (m_bUseAnglesForSky)
|
||||
m_skyboxData.angles.SetX( 1 );
|
||||
else
|
||||
m_skyboxData.angles.SetX( 0 );
|
||||
}
|
||||
|
||||
void CSkyCamera::SetCameraPositionMode()
|
||||
{
|
||||
// Must be absolute now that the sky_camera can be parented
|
||||
m_skyboxData.skycamera = NULL;
|
||||
m_skyboxData.origin = GetAbsOrigin();
|
||||
if (m_bUseAnglesForSky)
|
||||
m_skyboxData.angles = GetAbsAngles();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Update sky position mid-game
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CSkyCamera::DoUpdate( bool bUpdateData )
|
||||
{
|
||||
// Now that sky camera updating uses an entity handle directly transmitted to the client,
|
||||
// this thinking is only used to update area and other parameters
|
||||
|
||||
// Getting into another area is unlikely, but if it's not expensive, I guess it's okay.
|
||||
int area = engine->GetArea( GetAbsOrigin() );
|
||||
if (m_skyboxData.area != area)
|
||||
{
|
||||
m_skyboxData.area = area;
|
||||
bUpdateData = true;
|
||||
}
|
||||
|
||||
if ( m_bUseAngles )
|
||||
{
|
||||
Vector fogForward;
|
||||
AngleVectors( GetAbsAngles(), &fogForward );
|
||||
fogForward *= -1.0f;
|
||||
|
||||
if ( m_skyboxData.fog.dirPrimary.Get() != fogForward )
|
||||
{
|
||||
m_skyboxData.fog.dirPrimary = fogForward;
|
||||
bUpdateData = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bUpdateData)
|
||||
{
|
||||
// Updates client data, this completely ignores m_pOldSkyCamera
|
||||
CBasePlayer *pPlayer = NULL;
|
||||
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
||||
{
|
||||
pPlayer = UTIL_PlayerByIndex(i);
|
||||
if (pPlayer)
|
||||
pPlayer->m_Local.m_skybox3d.CopyFrom(m_skyboxData);
|
||||
}
|
||||
}
|
||||
|
||||
// Needed for entity interpolation
|
||||
SetSimulationTime( gpGlobals->curtime );
|
||||
|
||||
return bUpdateData;
|
||||
}
|
||||
|
||||
void CSkyCamera::UpdateThink()
|
||||
{
|
||||
if (DoUpdate())
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime + 0.2f );
|
||||
}
|
||||
}
|
||||
|
||||
void CSkyCamera::InputForceUpdate( inputdata_t &inputdata )
|
||||
{
|
||||
if (m_skyboxData.skycamera == NULL)
|
||||
{
|
||||
m_skyboxData.origin = GetAbsOrigin();
|
||||
if (m_bUseAnglesForSky)
|
||||
m_skyboxData.angles = GetAbsAngles();
|
||||
}
|
||||
|
||||
DoUpdate( true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSkyCamera::InputStartUpdating( inputdata_t &inputdata )
|
||||
{
|
||||
if (GetCurrentSkyCamera() == this)
|
||||
{
|
||||
SetCameraEntityMode();
|
||||
DoUpdate( true );
|
||||
|
||||
SetThink( &CSkyCamera::UpdateThink );
|
||||
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
|
||||
}
|
||||
|
||||
// If we become the current sky camera later, remember that we want to update
|
||||
AddSpawnFlags( SF_SKY_START_UPDATING );
|
||||
|
||||
// Must update transmit state so we show up on the client
|
||||
DispatchUpdateTransmitState();
|
||||
}
|
||||
|
||||
void CSkyCamera::InputStopUpdating( inputdata_t &inputdata )
|
||||
{
|
||||
SetThink( NULL );
|
||||
SetNextThink( TICK_NEVER_THINK );
|
||||
RemoveSpawnFlags( SF_SKY_START_UPDATING );
|
||||
DispatchUpdateTransmitState();
|
||||
|
||||
SetCameraPositionMode();
|
||||
DoUpdate( true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Activate!
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSkyCamera::InputActivateSkybox( inputdata_t &inputdata )
|
||||
{
|
||||
CSkyCamera *pActiveSky = GetCurrentSkyCamera();
|
||||
if (pActiveSky && pActiveSky->GetNextThink() != TICK_NEVER_THINK && pActiveSky != this)
|
||||
{
|
||||
// Deactivate that skybox
|
||||
pActiveSky->SetThink( NULL );
|
||||
pActiveSky->SetNextThink( TICK_NEVER_THINK );
|
||||
}
|
||||
|
||||
g_hActiveSkybox = this;
|
||||
|
||||
if (HasSpawnFlags( SF_SKY_START_UPDATING ))
|
||||
InputStartUpdating( inputdata );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Deactivate!
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSkyCamera::InputDeactivateSkybox( inputdata_t &inputdata )
|
||||
{
|
||||
if (GetCurrentSkyCamera() == this)
|
||||
{
|
||||
g_hActiveSkybox = NULL;
|
||||
|
||||
// ClientData doesn't catch this immediately
|
||||
CBasePlayer *pPlayer = NULL;
|
||||
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
||||
{
|
||||
pPlayer = UTIL_PlayerByIndex( i );
|
||||
if (pPlayer)
|
||||
pPlayer->m_Local.m_skybox3d.area = 255;
|
||||
}
|
||||
}
|
||||
|
||||
SetThink( NULL );
|
||||
SetNextThink( TICK_NEVER_THINK );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: Input handlers for setting fog stuff.
|
||||
//------------------------------------------------------------------------------
|
||||
void CSkyCamera::InputSetFogStartDist( inputdata_t &inputdata ) { m_skyboxData.fog.start = inputdata.value.Float(); }
|
||||
void CSkyCamera::InputSetFogEndDist( inputdata_t &inputdata ) { m_skyboxData.fog.end = inputdata.value.Float(); }
|
||||
void CSkyCamera::InputSetFogMaxDensity( inputdata_t &inputdata ) { m_skyboxData.fog.maxdensity = inputdata.value.Float(); }
|
||||
void CSkyCamera::InputTurnOnFog( inputdata_t &inputdata ) { m_skyboxData.fog.enable = true; }
|
||||
void CSkyCamera::InputTurnOffFog( inputdata_t &inputdata ) { m_skyboxData.fog.enable = false; }
|
||||
void CSkyCamera::InputSetFogColor( inputdata_t &inputdata ) { m_skyboxData.fog.colorPrimary = inputdata.value.Color32(); }
|
||||
void CSkyCamera::InputSetFogColorSecondary( inputdata_t &inputdata ) { m_skyboxData.fog.colorSecondary = inputdata.value.Color32(); }
|
||||
|
||||
void CSkyCamera::InputSetFarZ( inputdata_t &inputdata ) { m_skyboxData.fog.farz = inputdata.value.Int(); }
|
||||
|
||||
void CSkyCamera::InputCopyFogController( inputdata_t &inputdata )
|
||||
{
|
||||
CFogController *pFogController = dynamic_cast<CFogController*>(inputdata.value.Entity().Get());
|
||||
if (!pFogController)
|
||||
return;
|
||||
|
||||
m_skyboxData.fog.dirPrimary = pFogController->m_fog.dirPrimary;
|
||||
m_skyboxData.fog.colorPrimary = pFogController->m_fog.colorPrimary;
|
||||
m_skyboxData.fog.colorSecondary = pFogController->m_fog.colorSecondary;
|
||||
//m_skyboxData.fog.colorPrimaryLerpTo = pFogController->m_fog.colorPrimaryLerpTo;
|
||||
//m_skyboxData.fog.colorSecondaryLerpTo = pFogController->m_fog.colorSecondaryLerpTo;
|
||||
m_skyboxData.fog.start = pFogController->m_fog.start;
|
||||
m_skyboxData.fog.end = pFogController->m_fog.end;
|
||||
m_skyboxData.fog.farz = pFogController->m_fog.farz;
|
||||
m_skyboxData.fog.maxdensity = pFogController->m_fog.maxdensity;
|
||||
|
||||
//m_skyboxData.fog.startLerpTo = pFogController->m_fog.startLerpTo;
|
||||
//m_skyboxData.fog.endLerpTo = pFogController->m_fog.endLerpTo;
|
||||
//m_skyboxData.fog.lerptime = pFogController->m_fog.lerptime;
|
||||
//m_skyboxData.fog.duration = pFogController->m_fog.duration;
|
||||
//m_skyboxData.fog.enable = pFogController->m_fog.enable;
|
||||
m_skyboxData.fog.blend = pFogController->m_fog.blend;
|
||||
}
|
||||
|
||||
void CSkyCamera::InputCopyFogControllerWithScale( inputdata_t &inputdata )
|
||||
{
|
||||
CFogController *pFogController = dynamic_cast<CFogController*>(inputdata.value.Entity().Get());
|
||||
if (!pFogController)
|
||||
return;
|
||||
|
||||
m_skyboxData.fog.dirPrimary = pFogController->m_fog.dirPrimary;
|
||||
m_skyboxData.fog.colorPrimary = pFogController->m_fog.colorPrimary;
|
||||
m_skyboxData.fog.colorSecondary = pFogController->m_fog.colorSecondary;
|
||||
//m_skyboxData.fog.colorPrimaryLerpTo = pFogController->m_fog.colorPrimaryLerpTo;
|
||||
//m_skyboxData.fog.colorSecondaryLerpTo = pFogController->m_fog.colorSecondaryLerpTo;
|
||||
m_skyboxData.fog.start = pFogController->m_fog.start * m_skyboxData.scale;
|
||||
m_skyboxData.fog.end = pFogController->m_fog.end * m_skyboxData.scale;
|
||||
m_skyboxData.fog.farz = pFogController->m_fog.farz != -1 ? (pFogController->m_fog.farz * m_skyboxData.scale) : pFogController->m_fog.farz;
|
||||
m_skyboxData.fog.maxdensity = pFogController->m_fog.maxdensity;
|
||||
|
||||
//m_skyboxData.fog.startLerpTo = pFogController->m_fog.startLerpTo;
|
||||
//m_skyboxData.fog.endLerpTo = pFogController->m_fog.endLerpTo;
|
||||
//m_skyboxData.fog.lerptime = pFogController->m_fog.lerptime;
|
||||
//m_skyboxData.fog.duration = pFogController->m_fog.duration;
|
||||
//m_skyboxData.fog.enable = pFogController->m_fog.enable;
|
||||
m_skyboxData.fog.blend = pFogController->m_fog.blend;
|
||||
}
|
||||
#endif
|
||||
103
sp/src/game/server/SkyCamera.h
Normal file
103
sp/src/game/server/SkyCamera.h
Normal file
@@ -0,0 +1,103 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Resource collection entity
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef SKYCAMERA_H
|
||||
#define SKYCAMERA_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
class CSkyCamera;
|
||||
|
||||
#ifdef MAPBASE
|
||||
#define SF_SKY_MASTER (1 << 0)
|
||||
#define SF_SKY_START_UPDATING (1 << 1)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Sky Camera Class
|
||||
// Now derived directly from CBaseEntity for parenting and angles! (please don't break anything)
|
||||
//
|
||||
//=============================================================================
|
||||
class CSkyCamera : public CBaseEntity
|
||||
#else
|
||||
//=============================================================================
|
||||
//
|
||||
// Sky Camera Class
|
||||
//
|
||||
class CSkyCamera : public CLogicalEntity
|
||||
#endif
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
DECLARE_CLASS( CSkyCamera, CBaseEntity );
|
||||
#else
|
||||
DECLARE_CLASS( CSkyCamera, CLogicalEntity );
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_DATADESC();
|
||||
CSkyCamera();
|
||||
~CSkyCamera();
|
||||
virtual void Spawn( void );
|
||||
virtual void Activate();
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID );
|
||||
|
||||
int UpdateTransmitState() { return HasSpawnFlags( SF_SKY_START_UPDATING ) ? SetTransmitState( FL_EDICT_ALWAYS ) : BaseClass::UpdateTransmitState(); }
|
||||
|
||||
void SetCameraEntityMode();
|
||||
void SetCameraPositionMode();
|
||||
|
||||
bool DoUpdate( bool bUpdateData = false );
|
||||
void UpdateThink();
|
||||
|
||||
void InputForceUpdate( inputdata_t &inputdata );
|
||||
void InputStartUpdating( inputdata_t &inputdata );
|
||||
void InputStopUpdating( inputdata_t &inputdata );
|
||||
|
||||
void InputActivateSkybox( inputdata_t &inputdata );
|
||||
void InputDeactivateSkybox( inputdata_t &inputdata );
|
||||
|
||||
void InputSetFogStartDist( inputdata_t &data );
|
||||
void InputSetFogEndDist( inputdata_t &data );
|
||||
void InputTurnOnFog( inputdata_t &data );
|
||||
void InputTurnOffFog( inputdata_t &data );
|
||||
void InputSetFogColor( inputdata_t &data );
|
||||
void InputSetFogColorSecondary( inputdata_t &data );
|
||||
void InputSetFogMaxDensity( inputdata_t &inputdata );
|
||||
void InputCopyFogController( inputdata_t &inputdata );
|
||||
void InputCopyFogControllerWithScale( inputdata_t &inputdata );
|
||||
|
||||
void InputSetFarZ( inputdata_t &data );
|
||||
|
||||
void InputSetSkyColor( inputdata_t &inputdata ) { m_skyboxData.skycolor = inputdata.value.Color32(); }
|
||||
|
||||
void InputSetScale( inputdata_t &inputdata ) { m_skyboxData.scale = inputdata.value.Int(); }
|
||||
#endif
|
||||
|
||||
public:
|
||||
sky3dparams_t m_skyboxData;
|
||||
bool m_bUseAngles;
|
||||
#ifdef MAPBASE
|
||||
// Uses angles for actual skybox
|
||||
bool m_bUseAnglesForSky;
|
||||
#endif
|
||||
CSkyCamera *m_pNext;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Retrives the current skycamera
|
||||
//-----------------------------------------------------------------------------
|
||||
CSkyCamera* GetCurrentSkyCamera();
|
||||
CSkyCamera* GetSkyCameraList();
|
||||
|
||||
|
||||
#endif // SKYCAMERA_H
|
||||
584
sp/src/game/server/TemplateEntities.cpp
Normal file
584
sp/src/game/server/TemplateEntities.cpp
Normal file
@@ -0,0 +1,584 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Template entities are used by spawners to create copies of entities
|
||||
// that were configured by the level designer. This allows us to spawn
|
||||
// entities with arbitrary sets of key/value data and entity I/O
|
||||
// connections.
|
||||
//
|
||||
// Template entities are marked with a special spawnflag which causes
|
||||
// them not to spawn, but to be saved as a string containing all the
|
||||
// map data (keyvalues and I/O connections) from the BSP. Template
|
||||
// entities are looked up by name by the spawner, which copies the
|
||||
// map data into a local string (that's how the template data is saved
|
||||
// and restored). Once all the entities in the map have been activated,
|
||||
// the template database is freed.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "igamesystem.h"
|
||||
#include "mapentities_shared.h"
|
||||
#include "point_template.h"
|
||||
#include "eventqueue.h"
|
||||
#include "TemplateEntities.h"
|
||||
#include "utldict.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
ConVar template_debug( "template_debug", "0" );
|
||||
|
||||
// This is appended to key's values that will need to be unique in template instances
|
||||
const char *ENTITYIO_FIXUP_STRING = "&0000";
|
||||
|
||||
int MapEntity_GetNumKeysInEntity( const char *pEntData );
|
||||
|
||||
struct TemplateEntityData_t
|
||||
{
|
||||
const char *pszName;
|
||||
char *pszMapData;
|
||||
string_t iszMapData;
|
||||
int iMapDataLength;
|
||||
bool bNeedsEntityIOFixup; // If true, this template has entity I/O in its mapdata that needs fixup before spawning.
|
||||
char *pszFixedMapData; // A single copy of this template that we used to fix up the Entity I/O whenever someone wants a fixed version of this template
|
||||
|
||||
DECLARE_SIMPLE_DATADESC();
|
||||
};
|
||||
|
||||
BEGIN_SIMPLE_DATADESC( TemplateEntityData_t )
|
||||
//DEFINE_FIELD( pszName, FIELD_STRING ), // Saved custom, see below
|
||||
//DEFINE_FIELD( pszMapData, FIELD_STRING ), // Saved custom, see below
|
||||
DEFINE_FIELD( iszMapData, FIELD_STRING ),
|
||||
DEFINE_FIELD( iMapDataLength, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( bNeedsEntityIOFixup, FIELD_BOOLEAN ),
|
||||
|
||||
//DEFINE_FIELD( pszFixedMapData, FIELD_STRING ), // Not saved at all
|
||||
END_DATADESC()
|
||||
|
||||
struct grouptemplate_t
|
||||
{
|
||||
CEntityMapData *pMapDataParser;
|
||||
char pszName[MAPKEY_MAXLENGTH];
|
||||
int iIndex;
|
||||
bool bChangeTargetname;
|
||||
};
|
||||
|
||||
static CUtlVector<TemplateEntityData_t *> g_Templates;
|
||||
|
||||
int g_iCurrentTemplateInstance;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Saves the given entity's keyvalue data for later use by a spawner.
|
||||
// Returns the index into the templates.
|
||||
//-----------------------------------------------------------------------------
|
||||
int Templates_Add(CBaseEntity *pEntity, const char *pszMapData, int nLen)
|
||||
{
|
||||
const char *pszName = STRING(pEntity->GetEntityName());
|
||||
if ((!pszName) || (!strlen(pszName)))
|
||||
{
|
||||
DevWarning(1, "RegisterTemplateEntity: template entity with no name, class %s\n", pEntity->GetClassname());
|
||||
return -1;
|
||||
}
|
||||
|
||||
TemplateEntityData_t *pEntData = (TemplateEntityData_t *)malloc(sizeof(TemplateEntityData_t));
|
||||
pEntData->pszName = strdup( pszName );
|
||||
|
||||
// We may modify the values of the keys in this mapdata chunk later on to fix Entity I/O
|
||||
// connections. For this reason, we need to ensure we have enough memory to do that.
|
||||
int iKeys = MapEntity_GetNumKeysInEntity( pszMapData );
|
||||
int iExtraSpace = (strlen(ENTITYIO_FIXUP_STRING)+1) * iKeys;
|
||||
|
||||
// Extra 1 because the mapdata passed in isn't null terminated
|
||||
pEntData->iMapDataLength = nLen + iExtraSpace + 1;
|
||||
pEntData->pszMapData = (char *)malloc( pEntData->iMapDataLength );
|
||||
memcpy(pEntData->pszMapData, pszMapData, nLen + 1);
|
||||
pEntData->pszMapData[nLen] = '\0';
|
||||
|
||||
// We don't alloc these suckers right now because that gives us no time to
|
||||
// tweak them for Entity I/O purposes.
|
||||
pEntData->iszMapData = NULL_STRING;
|
||||
pEntData->bNeedsEntityIOFixup = false;
|
||||
pEntData->pszFixedMapData = NULL;
|
||||
|
||||
return g_Templates.AddToTail(pEntData);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if the specified index needs to be fixed up to be unique
|
||||
// when the template is spawned.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Templates_IndexRequiresEntityIOFixup( int iIndex )
|
||||
{
|
||||
Assert( iIndex < g_Templates.Count() );
|
||||
return g_Templates[iIndex]->bNeedsEntityIOFixup;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Looks up a template entity by its index in the templates
|
||||
// Used by point_templates because they often have multiple templates with the same name
|
||||
//-----------------------------------------------------------------------------
|
||||
string_t Templates_FindByIndex( int iIndex )
|
||||
{
|
||||
Assert( iIndex < g_Templates.Count() );
|
||||
|
||||
// First time through we alloc the mapdata onto the pool.
|
||||
// It's safe to do it now because this isn't called until post Entity I/O cleanup.
|
||||
if ( g_Templates[iIndex]->iszMapData == NULL_STRING )
|
||||
{
|
||||
g_Templates[iIndex]->iszMapData = AllocPooledString( g_Templates[iIndex]->pszMapData );
|
||||
}
|
||||
|
||||
return g_Templates[iIndex]->iszMapData;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int Templates_GetStringSize( int iIndex )
|
||||
{
|
||||
Assert( iIndex < g_Templates.Count() );
|
||||
return g_Templates[iIndex]->iMapDataLength;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Looks up a template entity by name, returning the map data blob as
|
||||
// a null-terminated string containing key/value pairs.
|
||||
// NOTE: This can't handle multiple templates with the same targetname.
|
||||
//-----------------------------------------------------------------------------
|
||||
string_t Templates_FindByTargetName(const char *pszName)
|
||||
{
|
||||
int nCount = g_Templates.Count();
|
||||
for (int i = 0; i < nCount; i++)
|
||||
{
|
||||
TemplateEntityData_t *pTemplate = g_Templates.Element(i);
|
||||
if ( !stricmp(pTemplate->pszName, pszName) )
|
||||
return Templates_FindByIndex( i );
|
||||
}
|
||||
|
||||
return NULL_STRING;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A new version of name fixup which targets all instances of a name
|
||||
// in a keyvalue, including output parameters.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Templates_NewNameFixup( CUtlVector< grouptemplate_t > &GroupTemplates, int i, int iCount, CEntityMapData *mapData, CUtlDict< int, int > &KeyInstanceCount, char *keyName, char *value )
|
||||
{
|
||||
do
|
||||
{
|
||||
// Ignore targetnames
|
||||
if ( !stricmp( keyName, "targetname" ) )
|
||||
continue;
|
||||
|
||||
// Add to the count for this
|
||||
int idx = KeyInstanceCount.Find( keyName );
|
||||
if ( idx == KeyInstanceCount.InvalidIndex() )
|
||||
{
|
||||
idx = KeyInstanceCount.Insert( keyName, 0 );
|
||||
}
|
||||
KeyInstanceCount[idx]++;
|
||||
|
||||
// Loop through our group templates
|
||||
for ( int iTName = 0; iTName < iCount; iTName++ )
|
||||
{
|
||||
char *pName = GroupTemplates[iTName].pszName;
|
||||
if (strstr( value, pName ) == NULL)
|
||||
continue;
|
||||
|
||||
if ( template_debug.GetInt() )
|
||||
{
|
||||
Msg("Template Connection Found: Key %s (\"%s\") in entity named \"%s\"(%d) matches entity %d's targetname\n", keyName, value, GroupTemplates[i].pszName, i, iTName );
|
||||
}
|
||||
|
||||
char newvalue[MAPKEY_MAXLENGTH];
|
||||
char fixedup[MAPKEY_MAXLENGTH];
|
||||
Q_strncpy( fixedup, pName, MAPKEY_MAXLENGTH );
|
||||
Q_strncat( fixedup, ENTITYIO_FIXUP_STRING, sizeof( fixedup ), COPY_ALL_CHARACTERS );
|
||||
|
||||
// Get the current key instance. (-1 because it's this one we're changing)
|
||||
int nKeyInstance = KeyInstanceCount[idx] - 1;
|
||||
|
||||
// Add our IO value to the targetname
|
||||
V_StrSubst( value, pName, fixedup, newvalue, MAPKEY_MAXLENGTH );
|
||||
|
||||
if ( template_debug.GetInt() )
|
||||
{
|
||||
Msg(" Fixed up value: Key %s with \"%s\" in entity named \"%s\"(%d) has become \"%s\"\n", keyName, value, GroupTemplates[i].pszName, i, newvalue );
|
||||
}
|
||||
|
||||
mapData->SetValue( keyName, newvalue, nKeyInstance );
|
||||
Q_strncpy( value, newvalue, MAPKEY_MAXLENGTH );
|
||||
|
||||
// Remember we changed this targetname
|
||||
GroupTemplates[iTName].bChangeTargetname = true;
|
||||
|
||||
// Set both entity's flags telling them their template needs fixup when it's spawned
|
||||
g_Templates[ GroupTemplates[i].iIndex ]->bNeedsEntityIOFixup = true;
|
||||
g_Templates[ GroupTemplates[iTName].iIndex ]->bNeedsEntityIOFixup = true;
|
||||
}
|
||||
}
|
||||
while ( mapData->GetNextKey(keyName, value) );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A CPointTemplate has asked us to reconnect all the entity I/O links
|
||||
// inside it's templates. Go through the keys and add look for values
|
||||
// that match a name within the group's entity names. Append %d to any
|
||||
// found values, which will later be filled out by a unique identifier
|
||||
// whenever the template is instanced.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Templates_ReconnectIOForGroup( CPointTemplate *pGroup )
|
||||
{
|
||||
int iCount = pGroup->GetNumTemplates();
|
||||
if ( !iCount )
|
||||
return;
|
||||
|
||||
// First assemble a list of the targetnames of all the templates in the group.
|
||||
// We need to store off the original names here, because we're going to change
|
||||
// them as we go along.
|
||||
CUtlVector< grouptemplate_t > GroupTemplates;
|
||||
int i;
|
||||
for ( i = 0; i < iCount; i++ )
|
||||
{
|
||||
grouptemplate_t newGroupTemplate;
|
||||
newGroupTemplate.iIndex = pGroup->GetTemplateIndexForTemplate(i);
|
||||
newGroupTemplate.pMapDataParser = new CEntityMapData( g_Templates[ newGroupTemplate.iIndex ]->pszMapData, g_Templates[ newGroupTemplate.iIndex ]->iMapDataLength );
|
||||
Assert( newGroupTemplate.pMapDataParser );
|
||||
newGroupTemplate.pMapDataParser->ExtractValue( "targetname", newGroupTemplate.pszName );
|
||||
newGroupTemplate.bChangeTargetname = false;
|
||||
|
||||
GroupTemplates.AddToTail( newGroupTemplate );
|
||||
}
|
||||
|
||||
if (pGroup->AllowNameFixup())
|
||||
{
|
||||
char keyName[MAPKEY_MAXLENGTH];
|
||||
char value[MAPKEY_MAXLENGTH];
|
||||
char valueclipped[MAPKEY_MAXLENGTH];
|
||||
|
||||
// Now go through all the entities in the group and parse their mapdata keyvalues.
|
||||
// We're looking for any values that match targetnames of any of the group entities.
|
||||
for ( i = 0; i < iCount; i++ )
|
||||
{
|
||||
// We need to know what instance of each key we're changing.
|
||||
// Store a table of the count of the keys we've run into.
|
||||
CUtlDict< int, int > KeyInstanceCount;
|
||||
CEntityMapData *mapData = GroupTemplates[i].pMapDataParser;
|
||||
|
||||
// Loop through our keys
|
||||
if ( !mapData->GetFirstKey(keyName, value) )
|
||||
continue;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( pGroup->NameFixupExpanded() )
|
||||
{
|
||||
Templates_NewNameFixup( GroupTemplates, i, iCount, mapData, KeyInstanceCount, keyName, value );
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
// Ignore targetnames
|
||||
if ( !stricmp( keyName, "targetname" ) )
|
||||
continue;
|
||||
|
||||
// Add to the count for this
|
||||
int idx = KeyInstanceCount.Find( keyName );
|
||||
if ( idx == KeyInstanceCount.InvalidIndex() )
|
||||
{
|
||||
idx = KeyInstanceCount.Insert( keyName, 0 );
|
||||
}
|
||||
KeyInstanceCount[idx]++;
|
||||
|
||||
// Entity I/O values are stored as "Targetname,<data>", so we need to see if there's a ',' in the string
|
||||
char *sValue = value;
|
||||
// FIXME: This is very brittle. Any key with a , will not be found.
|
||||
char *s = strchr( value, ',' );
|
||||
if ( s )
|
||||
{
|
||||
// Grab just the targetname of the receiver
|
||||
Q_strncpy( valueclipped, value, (s - value+1) );
|
||||
sValue = valueclipped;
|
||||
}
|
||||
|
||||
// Loop through our group templates
|
||||
for ( int iTName = 0; iTName < iCount; iTName++ )
|
||||
{
|
||||
char *pName = GroupTemplates[iTName].pszName;
|
||||
if ( stricmp( pName, sValue ) )
|
||||
continue;
|
||||
|
||||
if ( template_debug.GetInt() )
|
||||
{
|
||||
Msg("Template Connection Found: Key %s (\"%s\") in entity named \"%s\"(%d) matches entity %d's targetname\n", keyName, sValue, GroupTemplates[i].pszName, i, iTName );
|
||||
}
|
||||
|
||||
char newvalue[MAPKEY_MAXLENGTH];
|
||||
|
||||
// Get the current key instance. (-1 because it's this one we're changing)
|
||||
int nKeyInstance = KeyInstanceCount[idx] - 1;
|
||||
|
||||
// Add our IO value to the targetname
|
||||
// We need to append it if this isn't an Entity I/O value, or prepend it to the ',' if it is
|
||||
if ( s )
|
||||
{
|
||||
Q_strncpy( newvalue, valueclipped, MAPKEY_MAXLENGTH );
|
||||
Q_strncat( newvalue, ENTITYIO_FIXUP_STRING, sizeof(newvalue), COPY_ALL_CHARACTERS );
|
||||
Q_strncat( newvalue, s, sizeof(newvalue), COPY_ALL_CHARACTERS );
|
||||
mapData->SetValue( keyName, newvalue, nKeyInstance );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_strncpy( newvalue, sValue, MAPKEY_MAXLENGTH );
|
||||
Q_strncat( newvalue, ENTITYIO_FIXUP_STRING, sizeof(newvalue), COPY_ALL_CHARACTERS );
|
||||
mapData->SetValue( keyName, newvalue, nKeyInstance );
|
||||
}
|
||||
|
||||
// Remember we changed this targetname
|
||||
GroupTemplates[iTName].bChangeTargetname = true;
|
||||
|
||||
// Set both entity's flags telling them their template needs fixup when it's spawned
|
||||
g_Templates[ GroupTemplates[i].iIndex ]->bNeedsEntityIOFixup = true;
|
||||
g_Templates[ GroupTemplates[iTName].iIndex ]->bNeedsEntityIOFixup = true;
|
||||
}
|
||||
}
|
||||
while ( mapData->GetNextKey(keyName, value) );
|
||||
}
|
||||
|
||||
// Now change targetnames for all entities that need them changed
|
||||
for ( i = 0; i < iCount; i++ )
|
||||
{
|
||||
char value[MAPKEY_MAXLENGTH];
|
||||
|
||||
if ( GroupTemplates[i].bChangeTargetname )
|
||||
{
|
||||
CEntityMapData *mapData = GroupTemplates[i].pMapDataParser;
|
||||
mapData->ExtractValue( "targetname", value );
|
||||
Q_strncat( value, ENTITYIO_FIXUP_STRING, sizeof(value), COPY_ALL_CHARACTERS );
|
||||
mapData->SetValue( "targetname", value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete our group parsers
|
||||
for ( i = 0; i < iCount; i++ )
|
||||
{
|
||||
delete GroupTemplates[i].pMapDataParser;
|
||||
}
|
||||
GroupTemplates.Purge();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Someone's about to start instancing a new group of entities.
|
||||
// Generate a unique identifier for this group.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Templates_StartUniqueInstance( void )
|
||||
{
|
||||
g_iCurrentTemplateInstance++;
|
||||
|
||||
// Make sure there's enough room to fit it into the string
|
||||
int iMax = pow(10.0f, (int)((strlen(ENTITYIO_FIXUP_STRING) - 1))); // -1 for the &
|
||||
if ( g_iCurrentTemplateInstance >= iMax )
|
||||
{
|
||||
// We won't hit this.
|
||||
Assert(0);
|
||||
// Hopefully there were still be instance number 0 around.
|
||||
g_iCurrentTemplateInstance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Someone wants to spawn an instance of a template that requires
|
||||
// entity IO fixup. Fill out the pMapData with a copy of the template
|
||||
// with unique key/values where the template requires them.
|
||||
//-----------------------------------------------------------------------------
|
||||
char *Templates_GetEntityIOFixedMapData( int iIndex )
|
||||
{
|
||||
#ifndef MAPBASE // This code also runs when the point_template's script scope is active
|
||||
Assert( Templates_IndexRequiresEntityIOFixup( iIndex ) );
|
||||
#endif
|
||||
|
||||
// First time through?
|
||||
if ( !g_Templates[iIndex]->pszFixedMapData )
|
||||
{
|
||||
g_Templates[iIndex]->pszFixedMapData = new char[g_Templates[iIndex]->iMapDataLength];
|
||||
Q_strncpy( g_Templates[iIndex]->pszFixedMapData, g_Templates[iIndex]->pszMapData, g_Templates[iIndex]->iMapDataLength );
|
||||
}
|
||||
|
||||
int iFixupSize = strlen(ENTITYIO_FIXUP_STRING); // don't include \0 when copying in the fixup
|
||||
char *sOurFixup = new char[iFixupSize+1]; // do alloc room here for the null terminator
|
||||
Q_snprintf( sOurFixup, iFixupSize+1, "%c%.4d", ENTITYIO_FIXUP_STRING[0], g_iCurrentTemplateInstance );
|
||||
|
||||
// Now rip through the map data string and replace any instances of the fixup string with our unique identifier
|
||||
char *c = g_Templates[iIndex]->pszFixedMapData;
|
||||
do
|
||||
{
|
||||
if ( *c == ENTITYIO_FIXUP_STRING[0] )
|
||||
{
|
||||
// Make sure it's our fixup string
|
||||
bool bValid = true;
|
||||
for ( int i = 1; i < iFixupSize; i++ )
|
||||
{
|
||||
// Look for any number, because we've already used this string
|
||||
if ( !(*(c+i) >= '0' && *(c+i) <= '9') )
|
||||
{
|
||||
// Some other string
|
||||
bValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Stomp it with our unique string
|
||||
if ( bValid )
|
||||
{
|
||||
memcpy( c, sOurFixup, iFixupSize );
|
||||
c += iFixupSize;
|
||||
}
|
||||
}
|
||||
c++;
|
||||
} while (*c);
|
||||
|
||||
return g_Templates[iIndex]->pszFixedMapData;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Frees all the template data. Called on level shutdown.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Templates_RemoveAll(void)
|
||||
{
|
||||
int nCount = g_Templates.Count();
|
||||
for (int i = 0; i < nCount; i++)
|
||||
{
|
||||
TemplateEntityData_t *pTemplate = g_Templates.Element(i);
|
||||
|
||||
free((void *)pTemplate->pszName);
|
||||
free(pTemplate->pszMapData);
|
||||
if ( pTemplate->pszFixedMapData )
|
||||
{
|
||||
free(pTemplate->pszFixedMapData);
|
||||
}
|
||||
|
||||
free(pTemplate);
|
||||
}
|
||||
|
||||
g_Templates.RemoveAll();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Hooks in the template manager's callbacks.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CTemplatesHook : public CAutoGameSystem
|
||||
{
|
||||
public:
|
||||
CTemplatesHook( char const *name ) : CAutoGameSystem( name )
|
||||
{
|
||||
}
|
||||
|
||||
virtual void LevelShutdownPostEntity( void )
|
||||
{
|
||||
Templates_RemoveAll();
|
||||
}
|
||||
};
|
||||
|
||||
CTemplatesHook g_TemplateEntityHook( "CTemplatesHook" );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TEMPLATE SAVE / RESTORE
|
||||
//-----------------------------------------------------------------------------
|
||||
static short TEMPLATE_SAVE_RESTORE_VERSION = 1;
|
||||
|
||||
class CTemplate_SaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler
|
||||
{
|
||||
public:
|
||||
const char *GetBlockName()
|
||||
{
|
||||
return "Templates";
|
||||
}
|
||||
|
||||
//---------------------------------
|
||||
|
||||
void Save( ISave *pSave )
|
||||
{
|
||||
pSave->WriteInt( &g_iCurrentTemplateInstance );
|
||||
|
||||
short nCount = g_Templates.Count();
|
||||
pSave->WriteShort( &nCount );
|
||||
for ( int i = 0; i < nCount; i++ )
|
||||
{
|
||||
TemplateEntityData_t *pTemplate = g_Templates[i];
|
||||
pSave->WriteAll( pTemplate );
|
||||
pSave->WriteString( pTemplate->pszName );
|
||||
pSave->WriteString( pTemplate->pszMapData );
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------
|
||||
|
||||
void WriteSaveHeaders( ISave *pSave )
|
||||
{
|
||||
pSave->WriteShort( &TEMPLATE_SAVE_RESTORE_VERSION );
|
||||
}
|
||||
|
||||
//---------------------------------
|
||||
|
||||
void ReadRestoreHeaders( IRestore *pRestore )
|
||||
{
|
||||
// No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so.
|
||||
short version;
|
||||
pRestore->ReadShort( &version );
|
||||
m_fDoLoad = ( version == TEMPLATE_SAVE_RESTORE_VERSION );
|
||||
}
|
||||
|
||||
//---------------------------------
|
||||
|
||||
void Restore( IRestore *pRestore, bool createPlayers )
|
||||
{
|
||||
if ( m_fDoLoad )
|
||||
{
|
||||
Templates_RemoveAll();
|
||||
g_Templates.Purge();
|
||||
g_iCurrentTemplateInstance = pRestore->ReadInt();
|
||||
|
||||
int iTemplates = pRestore->ReadShort();
|
||||
while ( iTemplates-- )
|
||||
{
|
||||
TemplateEntityData_t *pNewTemplate = (TemplateEntityData_t *)malloc(sizeof(TemplateEntityData_t));
|
||||
pRestore->ReadAll( pNewTemplate );
|
||||
|
||||
int sizeData = 0;//pRestore->SkipHeader();
|
||||
char szName[MAPKEY_MAXLENGTH];
|
||||
pRestore->ReadString( szName, MAPKEY_MAXLENGTH, sizeData );
|
||||
pNewTemplate->pszName = strdup( szName );
|
||||
//sizeData = pRestore->SkipHeader();
|
||||
pNewTemplate->pszMapData = (char *)malloc( pNewTemplate->iMapDataLength );
|
||||
pRestore->ReadString( pNewTemplate->pszMapData, pNewTemplate->iMapDataLength, sizeData );
|
||||
|
||||
// Set this to NULL so it'll be created the first time it gets used
|
||||
pNewTemplate->pszFixedMapData = NULL;
|
||||
|
||||
g_Templates.AddToTail( pNewTemplate );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_fDoLoad;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CTemplate_SaveRestoreBlockHandler g_Template_SaveRestoreBlockHandler;
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
ISaveRestoreBlockHandler *GetTemplateSaveRestoreBlockHandler()
|
||||
{
|
||||
return &g_Template_SaveRestoreBlockHandler;
|
||||
}
|
||||
36
sp/src/game/server/TemplateEntities.h
Normal file
36
sp/src/game/server/TemplateEntities.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Template entities are used by spawners to create copies of entities
|
||||
// that were configured by the level designer. This allows us to spawn
|
||||
// entities with arbitrary sets of key/value data and entity I/O
|
||||
// connections.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef TEMPLATEENTITIES_H
|
||||
#define TEMPLATEENTITIES_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "isaverestore.h"
|
||||
|
||||
class CBaseEntity;
|
||||
class CPointTemplate;
|
||||
|
||||
int Templates_Add(CBaseEntity *pEntity, const char *pszMapData, int nLen);
|
||||
string_t Templates_FindByIndex( int iIndex );
|
||||
int Templates_GetStringSize( int iIndex );
|
||||
string_t Templates_FindByTargetName(const char *pszName);
|
||||
void Templates_ReconnectIOForGroup( CPointTemplate *pGroup );
|
||||
|
||||
// Some templates have Entity I/O connecting the entities within the template.
|
||||
// Unique versions of these templates need to be created whenever they're instanced.
|
||||
void Templates_StartUniqueInstance( void );
|
||||
bool Templates_IndexRequiresEntityIOFixup( int iIndex );
|
||||
char *Templates_GetEntityIOFixedMapData( int iIndex );
|
||||
|
||||
// Save / Restore
|
||||
ISaveRestoreBlockHandler *GetTemplateSaveRestoreBlockHandler( void );
|
||||
|
||||
#endif // TEMPLATEENTITIES_H
|
||||
118
sp/src/game/server/WaterLODControl.cpp
Normal file
118
sp/src/game/server/WaterLODControl.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Shadow control entity.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FIXME: This really should inherit from something more lightweight
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Water LOD control entity
|
||||
//------------------------------------------------------------------------------
|
||||
class CWaterLODControl : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CWaterLODControl, CBaseEntity );
|
||||
|
||||
CWaterLODControl();
|
||||
|
||||
void Spawn( void );
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
int UpdateTransmitState();
|
||||
void SetCheapWaterStartDistance( inputdata_t &inputdata );
|
||||
void SetCheapWaterEndDistance( inputdata_t &inputdata );
|
||||
|
||||
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
private:
|
||||
CNetworkVar( float, m_flCheapWaterStartDistance );
|
||||
CNetworkVar( float, m_flCheapWaterEndDistance );
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(water_lod_control, CWaterLODControl);
|
||||
|
||||
BEGIN_DATADESC( CWaterLODControl )
|
||||
|
||||
DEFINE_KEYFIELD( m_flCheapWaterStartDistance, FIELD_FLOAT, "cheapwaterstartdistance" ),
|
||||
DEFINE_KEYFIELD( m_flCheapWaterEndDistance, FIELD_FLOAT, "cheapwaterenddistance" ),
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUT( m_flCheapWaterStartDistance, FIELD_FLOAT, "SetCheapWaterStartDistance" ),
|
||||
DEFINE_INPUT( m_flCheapWaterEndDistance, FIELD_FLOAT, "SetCheapWaterEndDistance" ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST_NOBASE(CWaterLODControl, DT_WaterLODControl)
|
||||
SendPropFloat(SENDINFO(m_flCheapWaterStartDistance), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat(SENDINFO(m_flCheapWaterEndDistance), 0, SPROP_NOSCALE ),
|
||||
END_SEND_TABLE()
|
||||
|
||||
|
||||
CWaterLODControl::CWaterLODControl()
|
||||
{
|
||||
m_flCheapWaterStartDistance = 1000.0f;
|
||||
m_flCheapWaterEndDistance = 2000.0f;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Send even though we don't have a model
|
||||
//------------------------------------------------------------------------------
|
||||
int CWaterLODControl::UpdateTransmitState()
|
||||
{
|
||||
// ALWAYS transmit to all clients.
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
|
||||
bool CWaterLODControl::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "cheapwaterstartdistance" ) )
|
||||
{
|
||||
m_flCheapWaterStartDistance = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( FStrEq( szKeyName, "cheapwaterenddistance" ) )
|
||||
{
|
||||
m_flCheapWaterEndDistance = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
//------------------------------------------------------------------------------
|
||||
void CWaterLODControl::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
SetSolid( SOLID_NONE );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Input values
|
||||
//------------------------------------------------------------------------------
|
||||
void CWaterLODControl::SetCheapWaterStartDistance( inputdata_t &inputdata )
|
||||
{
|
||||
m_flCheapWaterStartDistance = atof( inputdata.value.String() );
|
||||
}
|
||||
|
||||
void CWaterLODControl::SetCheapWaterEndDistance( inputdata_t &inputdata )
|
||||
{
|
||||
m_flCheapWaterEndDistance = atof( inputdata.value.String() );
|
||||
}
|
||||
27
sp/src/game/server/base_gameinterface.cpp
Normal file
27
sp/src/game/server/base_gameinterface.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "gameinterface.h"
|
||||
#include "mapentities.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
void CServerGameClients::GetPlayerLimits( int& minplayers, int& maxplayers, int &defaultMaxPlayers ) const
|
||||
{
|
||||
minplayers = defaultMaxPlayers = 1;
|
||||
maxplayers = MAX_PLAYERS;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------------- //
|
||||
// Mod-specific CServerGameDLL implementation.
|
||||
// -------------------------------------------------------------------------------------------- //
|
||||
|
||||
void CServerGameDLL::LevelInit_ParseAllEntities( const char *pMapEntities )
|
||||
{
|
||||
}
|
||||
60
sp/src/game/server/base_transmit_proxy.cpp
Normal file
60
sp/src/game/server/base_transmit_proxy.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "base_transmit_proxy.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
CBaseTransmitProxy::CBaseTransmitProxy( CBaseEntity *pEnt )
|
||||
{
|
||||
m_hEnt = pEnt;
|
||||
m_refCount = 0;
|
||||
}
|
||||
|
||||
|
||||
CBaseTransmitProxy::~CBaseTransmitProxy()
|
||||
{
|
||||
// Unlink from our parent entity.
|
||||
if ( m_hEnt )
|
||||
{
|
||||
m_refCount = 0xFFFF; // Prevent us from deleting ourselves again.
|
||||
// m_hEnt->NetworkProp()->SetTransmitProxy( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CBaseTransmitProxy::ShouldTransmit( const CCheckTransmitInfo *pInfo, int nPrevShouldTransmitResult )
|
||||
{
|
||||
// Anyone implementing a transmit proxy should override this since that's the point!!
|
||||
Assert( false );
|
||||
return FL_EDICT_DONTSEND;
|
||||
}
|
||||
|
||||
|
||||
void CBaseTransmitProxy::AddRef()
|
||||
{
|
||||
m_refCount++;
|
||||
}
|
||||
|
||||
|
||||
void CBaseTransmitProxy::Release()
|
||||
{
|
||||
if ( m_refCount == 0xFFFF )
|
||||
{
|
||||
// This means we are inside our destructor already, so we don't want to do anything here.
|
||||
}
|
||||
else if ( m_refCount <= 1 )
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
else
|
||||
{
|
||||
--m_refCount;
|
||||
}
|
||||
}
|
||||
|
||||
41
sp/src/game/server/base_transmit_proxy.h
Normal file
41
sp/src/game/server/base_transmit_proxy.h
Normal file
@@ -0,0 +1,41 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef BASE_TRANSMIT_PROXY_H
|
||||
#define BASE_TRANSMIT_PROXY_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "ehandle.h"
|
||||
|
||||
|
||||
class CBaseEntity;
|
||||
|
||||
|
||||
class CBaseTransmitProxy
|
||||
{
|
||||
public:
|
||||
|
||||
CBaseTransmitProxy( CBaseEntity *pEnt );
|
||||
virtual ~CBaseTransmitProxy();
|
||||
|
||||
// Override this to control the ShouldTransmit behavior of whatever entity the proxy is attached to.
|
||||
// bPrevShouldTransmitResult is what the proxy's entity's ShouldTransmit() returned.
|
||||
virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo, int nPrevShouldTransmitResult );
|
||||
|
||||
|
||||
void AddRef();
|
||||
void Release();
|
||||
|
||||
private:
|
||||
EHANDLE m_hEnt;
|
||||
unsigned short m_refCount;
|
||||
};
|
||||
|
||||
|
||||
#endif // BASE_TRANSMIT_PROXY_H
|
||||
Binary file not shown.
713
sp/src/game/server/basecombatcharacter.h
Normal file
713
sp/src/game/server/basecombatcharacter.h
Normal file
@@ -0,0 +1,713 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Base combat character with no AI
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef BASECOMBATCHARACTER_H
|
||||
#define BASECOMBATCHARACTER_H
|
||||
|
||||
#include <limits.h>
|
||||
#include "weapon_proficiency.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef INVASION_DLL
|
||||
#include "tf_shareddefs.h"
|
||||
|
||||
#define POWERUP_THINK_CONTEXT "PowerupThink"
|
||||
#endif
|
||||
|
||||
#include "cbase.h"
|
||||
#include "baseentity.h"
|
||||
#include "baseflex.h"
|
||||
#include "damagemodifier.h"
|
||||
#include "utllinkedlist.h"
|
||||
#include "ai_hull.h"
|
||||
#include "ai_utils.h"
|
||||
#include "physics_impact_damage.h"
|
||||
|
||||
class CNavArea;
|
||||
class CScriptedTarget;
|
||||
typedef CHandle<CBaseCombatWeapon> CBaseCombatWeaponHandle;
|
||||
|
||||
// -------------------------------------
|
||||
// Capability Bits
|
||||
// -------------------------------------
|
||||
|
||||
enum Capability_t
|
||||
{
|
||||
bits_CAP_MOVE_GROUND = 0x00000001, // walk/run
|
||||
bits_CAP_MOVE_JUMP = 0x00000002, // jump/leap
|
||||
bits_CAP_MOVE_FLY = 0x00000004, // can fly, move all around
|
||||
bits_CAP_MOVE_CLIMB = 0x00000008, // climb ladders
|
||||
bits_CAP_MOVE_SWIM = 0x00000010, // navigate in water // UNDONE - not yet implemented
|
||||
bits_CAP_MOVE_CRAWL = 0x00000020, // crawl // UNDONE - not yet implemented
|
||||
bits_CAP_MOVE_SHOOT = 0x00000040, // tries to shoot weapon while moving
|
||||
bits_CAP_SKIP_NAV_GROUND_CHECK = 0x00000080, // optimization - skips ground tests while computing navigation
|
||||
bits_CAP_USE = 0x00000100, // open doors/push buttons/pull levers
|
||||
//bits_CAP_HEAR = 0x00000200, // can hear forced sounds
|
||||
bits_CAP_AUTO_DOORS = 0x00000400, // can trigger auto doors
|
||||
bits_CAP_OPEN_DOORS = 0x00000800, // can open manual doors
|
||||
bits_CAP_TURN_HEAD = 0x00001000, // can turn head, always bone controller 0
|
||||
bits_CAP_WEAPON_RANGE_ATTACK1 = 0x00002000, // can do a weapon range attack 1
|
||||
bits_CAP_WEAPON_RANGE_ATTACK2 = 0x00004000, // can do a weapon range attack 2
|
||||
bits_CAP_WEAPON_MELEE_ATTACK1 = 0x00008000, // can do a weapon melee attack 1
|
||||
bits_CAP_WEAPON_MELEE_ATTACK2 = 0x00010000, // can do a weapon melee attack 2
|
||||
bits_CAP_INNATE_RANGE_ATTACK1 = 0x00020000, // can do a innate range attack 1
|
||||
bits_CAP_INNATE_RANGE_ATTACK2 = 0x00040000, // can do a innate range attack 1
|
||||
bits_CAP_INNATE_MELEE_ATTACK1 = 0x00080000, // can do a innate melee attack 1
|
||||
bits_CAP_INNATE_MELEE_ATTACK2 = 0x00100000, // can do a innate melee attack 1
|
||||
bits_CAP_USE_WEAPONS = 0x00200000, // can use weapons (non-innate attacks)
|
||||
//bits_CAP_STRAFE = 0x00400000, // strafe ( walk/run sideways)
|
||||
bits_CAP_ANIMATEDFACE = 0x00800000, // has animated eyes/face
|
||||
bits_CAP_USE_SHOT_REGULATOR = 0x01000000, // Uses the shot regulator for range attack1
|
||||
bits_CAP_FRIENDLY_DMG_IMMUNE = 0x02000000, // don't take damage from npc's that are D_LI
|
||||
bits_CAP_SQUAD = 0x04000000, // can form squads
|
||||
bits_CAP_DUCK = 0x08000000, // cover and reload ducking
|
||||
bits_CAP_NO_HIT_PLAYER = 0x10000000, // don't hit players
|
||||
bits_CAP_AIM_GUN = 0x20000000, // Use arms to aim gun, not just body
|
||||
bits_CAP_NO_HIT_SQUADMATES = 0x40000000, // none
|
||||
bits_CAP_SIMPLE_RADIUS_DAMAGE = 0x80000000, // Do not use robust radius damage model on this character.
|
||||
};
|
||||
|
||||
#define bits_CAP_DOORS_GROUP (bits_CAP_AUTO_DOORS | bits_CAP_OPEN_DOORS)
|
||||
#define bits_CAP_RANGE_ATTACK_GROUP (bits_CAP_WEAPON_RANGE_ATTACK1 | bits_CAP_WEAPON_RANGE_ATTACK2)
|
||||
#define bits_CAP_MELEE_ATTACK_GROUP (bits_CAP_WEAPON_MELEE_ATTACK1 | bits_CAP_WEAPON_MELEE_ATTACK2)
|
||||
|
||||
|
||||
class CBaseCombatWeapon;
|
||||
|
||||
#define BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE 0.9f
|
||||
|
||||
enum Disposition_t
|
||||
{
|
||||
D_ER, // Undefined - error
|
||||
D_HT, // Hate
|
||||
D_FR, // Fear
|
||||
D_LI, // Like
|
||||
D_NU // Neutral
|
||||
};
|
||||
|
||||
const int DEF_RELATIONSHIP_PRIORITY = INT_MIN;
|
||||
|
||||
struct Relationship_t
|
||||
{
|
||||
EHANDLE entity; // Relationship to a particular entity
|
||||
Class_T classType; // Relationship to a class CLASS_NONE = not class based (Def. in baseentity.h)
|
||||
Disposition_t disposition; // D_HT (Hate), D_FR (Fear), D_LI (Like), D_NT (Neutral)
|
||||
int priority; // Relative importance of this relationship (higher numbers mean more important)
|
||||
|
||||
DECLARE_SIMPLE_DATADESC();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This should contain all of the combat entry points / functionality
|
||||
// that are common between NPCs and players
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBaseCombatCharacter : public CBaseFlex
|
||||
{
|
||||
DECLARE_CLASS( CBaseCombatCharacter, CBaseFlex );
|
||||
|
||||
public:
|
||||
CBaseCombatCharacter(void);
|
||||
~CBaseCombatCharacter(void);
|
||||
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_PREDICTABLE();
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
virtual void Spawn( void );
|
||||
virtual void Precache();
|
||||
|
||||
virtual int Restore( IRestore &restore );
|
||||
|
||||
virtual const impactdamagetable_t &GetPhysicsImpactDamageTable( void );
|
||||
|
||||
int TakeHealth( float flHealth, int bitsDamageType );
|
||||
void CauseDeath( const CTakeDamageInfo &info );
|
||||
|
||||
virtual bool FVisible ( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); // true iff the parameter can be seen by me.
|
||||
virtual bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ) { return BaseClass::FVisible( vecTarget, traceMask, ppBlocker ); }
|
||||
static void ResetVisibilityCache( CBaseCombatCharacter *pBCC = NULL );
|
||||
|
||||
#ifdef MAPBASE
|
||||
virtual bool ShouldUseVisibilityCache( CBaseEntity *pEntity );
|
||||
#endif
|
||||
|
||||
#ifdef PORTAL
|
||||
virtual bool FVisibleThroughPortal( const CProp_Portal *pPortal, CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
|
||||
#endif
|
||||
|
||||
virtual bool FInViewCone( CBaseEntity *pEntity );
|
||||
virtual bool FInViewCone( const Vector &vecSpot );
|
||||
|
||||
#ifdef PORTAL
|
||||
virtual CProp_Portal* FInViewConeThroughPortal( CBaseEntity *pEntity );
|
||||
virtual CProp_Portal* FInViewConeThroughPortal( const Vector &vecSpot );
|
||||
#endif
|
||||
|
||||
virtual bool FInAimCone( CBaseEntity *pEntity );
|
||||
virtual bool FInAimCone( const Vector &vecSpot );
|
||||
|
||||
virtual bool ShouldShootMissTarget( CBaseCombatCharacter *pAttacker );
|
||||
virtual CBaseEntity *FindMissTarget( void );
|
||||
|
||||
#ifndef MAPBASE // This function now exists in CBaseEntity
|
||||
// Do not call HandleInteraction directly, use DispatchInteraction
|
||||
bool DispatchInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt ) { return ( interactionType > 0 ) ? HandleInteraction( interactionType, data, sourceEnt ) : false; }
|
||||
#endif
|
||||
virtual bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt );
|
||||
|
||||
virtual QAngle BodyAngles();
|
||||
virtual Vector BodyDirection2D( void );
|
||||
virtual Vector BodyDirection3D( void );
|
||||
virtual Vector HeadDirection2D( void ) { return BodyDirection2D( ); }; // No head motion so just return body dir
|
||||
virtual Vector HeadDirection3D( void ) { return BodyDirection2D( ); }; // No head motion so just return body dir
|
||||
virtual Vector EyeDirection2D( void ) { return HeadDirection2D( ); }; // No eye motion so just return head dir
|
||||
virtual Vector EyeDirection3D( void ) { return HeadDirection3D( ); }; // No eye motion so just return head dir
|
||||
|
||||
virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways );
|
||||
|
||||
// -----------------------
|
||||
// Fog
|
||||
// -----------------------
|
||||
virtual bool IsHiddenByFog( const Vector &target ) const; ///< return true if given target cant be seen because of fog
|
||||
virtual bool IsHiddenByFog( CBaseEntity *target ) const; ///< return true if given target cant be seen because of fog
|
||||
virtual bool IsHiddenByFog( float range ) const; ///< return true if given distance is too far to see through the fog
|
||||
virtual float GetFogObscuredRatio( const Vector &target ) const;///< return 0-1 ratio where zero is not obscured, and 1 is completely obscured
|
||||
virtual float GetFogObscuredRatio( CBaseEntity *target ) const; ///< return 0-1 ratio where zero is not obscured, and 1 is completely obscured
|
||||
virtual float GetFogObscuredRatio( float range ) const; ///< return 0-1 ratio where zero is not obscured, and 1 is completely obscured
|
||||
|
||||
|
||||
// -----------------------
|
||||
// Vision
|
||||
// -----------------------
|
||||
enum FieldOfViewCheckType { USE_FOV, DISREGARD_FOV };
|
||||
|
||||
// Visible starts with line of sight, and adds all the extra game checks like fog, smoke, camo...
|
||||
bool IsAbleToSee( const CBaseEntity *entity, FieldOfViewCheckType checkFOV );
|
||||
bool IsAbleToSee( CBaseCombatCharacter *pBCC, FieldOfViewCheckType checkFOV );
|
||||
|
||||
virtual bool IsLookingTowards( const CBaseEntity *target, float cosTolerance = BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE ) const; // return true if our view direction is pointing at the given target, within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
|
||||
virtual bool IsLookingTowards( const Vector &target, float cosTolerance = BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE ) const; // return true if our view direction is pointing at the given target, within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
|
||||
|
||||
virtual bool IsInFieldOfView( CBaseEntity *entity ) const; // Calls IsLookingTowards with the current field of view.
|
||||
virtual bool IsInFieldOfView( const Vector &pos ) const;
|
||||
|
||||
enum LineOfSightCheckType
|
||||
{
|
||||
IGNORE_NOTHING,
|
||||
IGNORE_ACTORS
|
||||
};
|
||||
virtual bool IsLineOfSightClear( CBaseEntity *entity, LineOfSightCheckType checkType = IGNORE_NOTHING ) const;// strictly LOS check with no other considerations
|
||||
virtual bool IsLineOfSightClear( const Vector &pos, LineOfSightCheckType checkType = IGNORE_NOTHING, CBaseEntity *entityToIgnore = NULL ) const;
|
||||
|
||||
// -----------------------
|
||||
// Ammo
|
||||
// -----------------------
|
||||
virtual int GiveAmmo( int iCount, int iAmmoIndex, bool bSuppressSound = false );
|
||||
int GiveAmmo( int iCount, const char *szName, bool bSuppressSound = false );
|
||||
virtual void RemoveAmmo( int iCount, int iAmmoIndex );
|
||||
virtual void RemoveAmmo( int iCount, const char *szName );
|
||||
void RemoveAllAmmo( );
|
||||
virtual int GetAmmoCount( int iAmmoIndex ) const;
|
||||
int GetAmmoCount( char *szName ) const;
|
||||
|
||||
virtual Activity NPC_TranslateActivity( Activity baseAct );
|
||||
|
||||
// -----------------------
|
||||
// Weapons
|
||||
// -----------------------
|
||||
CBaseCombatWeapon* Weapon_Create( const char *pWeaponName );
|
||||
virtual Activity Weapon_TranslateActivity( Activity baseAct, bool *pRequired = NULL );
|
||||
void Weapon_SetActivity( Activity newActivity, float duration );
|
||||
virtual void Weapon_FrameUpdate( void );
|
||||
virtual void Weapon_HandleAnimEvent( animevent_t *pEvent );
|
||||
CBaseCombatWeapon* Weapon_OwnsThisType( const char *pszWeapon, int iSubType = 0 ) const; // True if already owns a weapon of this class
|
||||
virtual bool Weapon_CanUse( CBaseCombatWeapon *pWeapon ); // True is allowed to use this class of weapon
|
||||
#ifdef MAPBASE
|
||||
virtual Activity Weapon_BackupActivity( Activity activity, bool weaponTranslationWasRequired = false, CBaseCombatWeapon *pSpecificWeapon = NULL );
|
||||
virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ); // Adds weapon to player
|
||||
virtual void Weapon_EquipHolstered( CBaseCombatWeapon *pWeapon ); // Pretty much only useful for NPCs
|
||||
virtual void Weapon_HandleEquip( CBaseCombatWeapon *pWeapon );
|
||||
#else
|
||||
virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ); // Adds weapon to player
|
||||
#endif
|
||||
virtual bool Weapon_EquipAmmoOnly( CBaseCombatWeapon *pWeapon ); // Adds weapon ammo to player, leaves weapon
|
||||
bool Weapon_Detach( CBaseCombatWeapon *pWeapon ); // Clear any pointers to the weapon.
|
||||
virtual void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget = NULL, const Vector *pVelocity = NULL );
|
||||
virtual bool Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex = 0 ); // Switch to given weapon if has ammo (false if failed)
|
||||
virtual Vector Weapon_ShootPosition( ); // gun position at current position/orientation
|
||||
bool Weapon_IsOnGround( CBaseCombatWeapon *pWeapon );
|
||||
CBaseEntity* Weapon_FindUsable( const Vector &range ); // search for a usable weapon in this range
|
||||
virtual bool Weapon_CanSwitchTo(CBaseCombatWeapon *pWeapon);
|
||||
virtual bool Weapon_SlotOccupied( CBaseCombatWeapon *pWeapon );
|
||||
virtual CBaseCombatWeapon *Weapon_GetSlot( int slot ) const;
|
||||
CBaseCombatWeapon *Weapon_GetWpnForAmmo( int iAmmoIndex );
|
||||
|
||||
|
||||
// For weapon strip
|
||||
void Weapon_DropAll( bool bDisallowWeaponPickup = false );
|
||||
|
||||
virtual bool AddPlayerItem( CBaseCombatWeapon *pItem ) { return false; }
|
||||
virtual bool RemovePlayerItem( CBaseCombatWeapon *pItem ) { return false; }
|
||||
|
||||
virtual bool CanBecomeServerRagdoll( void ) { return true; }
|
||||
|
||||
// -----------------------
|
||||
// Damage
|
||||
// -----------------------
|
||||
// Don't override this for characters, override the per-life-state versions below
|
||||
virtual int OnTakeDamage( const CTakeDamageInfo &info );
|
||||
|
||||
// Override these to control how your character takes damage in different states
|
||||
virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
|
||||
virtual int OnTakeDamage_Dying( const CTakeDamageInfo &info );
|
||||
virtual int OnTakeDamage_Dead( const CTakeDamageInfo &info );
|
||||
|
||||
virtual float GetAliveDuration( void ) const; // return time we have been alive (only valid when alive)
|
||||
|
||||
virtual void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ) {}
|
||||
virtual void NotifyFriendsOfDamage( CBaseEntity *pAttackerEntity ) {}
|
||||
virtual bool HasEverBeenInjured( int team = TEAM_ANY ) const; // return true if we have ever been injured by a member of the given team
|
||||
virtual float GetTimeSinceLastInjury( int team = TEAM_ANY ) const; // return time since we were hurt by a member of the given team
|
||||
|
||||
|
||||
virtual void OnPlayerKilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ) {}
|
||||
|
||||
// utility function to calc damage force
|
||||
Vector CalcDamageForceVector( const CTakeDamageInfo &info );
|
||||
|
||||
virtual int BloodColor();
|
||||
virtual Activity GetDeathActivity( void );
|
||||
|
||||
virtual bool CorpseGib( const CTakeDamageInfo &info );
|
||||
virtual void CorpseFade( void ); // Called instead of GibNPC() when gibs are disabled
|
||||
virtual bool HasHumanGibs( void );
|
||||
virtual bool HasAlienGibs( void );
|
||||
virtual bool ShouldGib( const CTakeDamageInfo &info ) { return false; } // Always ragdoll, unless specified by the leaf class
|
||||
|
||||
float GetDamageAccumulator() { return m_flDamageAccumulator; }
|
||||
int GetDamageCount( void ) { return m_iDamageCount; } // # of times NPC has been damaged. used for tracking 1-shot kills.
|
||||
|
||||
// Character killed (only fired once)
|
||||
virtual void Event_Killed( const CTakeDamageInfo &info );
|
||||
|
||||
// Killed a character
|
||||
void InputKilledNPC( inputdata_t &inputdata );
|
||||
#ifdef MAPBASE
|
||||
|
||||
void InputGiveWeapon( inputdata_t &inputdata );
|
||||
void InputDropWeapon( inputdata_t &inputdata );
|
||||
void InputPickupWeaponInstant( inputdata_t &inputdata );
|
||||
COutputEvent m_OnWeaponEquip;
|
||||
COutputEvent m_OnWeaponDrop;
|
||||
|
||||
virtual void InputHolsterWeapon( inputdata_t &inputdata );
|
||||
virtual void InputHolsterAndDestroyWeapon( inputdata_t &inputdata );
|
||||
virtual void InputUnholsterWeapon( inputdata_t &inputdata );
|
||||
void InputSwitchToWeapon( inputdata_t &inputdata );
|
||||
|
||||
COutputEHANDLE m_OnKilledEnemy;
|
||||
COutputEHANDLE m_OnKilledPlayer;
|
||||
virtual void OnKilledNPC( CBaseCombatCharacter *pKilled );
|
||||
|
||||
virtual CBaseEntity *FindNamedEntity( const char *pszName, IEntityFindFilter *pFilter = NULL );
|
||||
|
||||
COutputFloat m_OnHealthChanged;
|
||||
#else
|
||||
virtual void OnKilledNPC( CBaseCombatCharacter *pKilled ) {};
|
||||
#endif
|
||||
|
||||
// Exactly one of these happens immediately after killed (gibbed may happen later when the corpse gibs)
|
||||
// Character gibbed or faded out (violence controls) (only fired once)
|
||||
// returns true if gibs were spawned
|
||||
virtual bool Event_Gibbed( const CTakeDamageInfo &info );
|
||||
// Character entered the dying state without being gibbed (only fired once)
|
||||
virtual void Event_Dying( const CTakeDamageInfo &info );
|
||||
virtual void Event_Dying();
|
||||
// character died and should become a ragdoll now
|
||||
// return true if converted to a ragdoll, false to use AI death
|
||||
virtual bool BecomeRagdoll( const CTakeDamageInfo &info, const Vector &forceVector );
|
||||
virtual void FixupBurningServerRagdoll( CBaseEntity *pRagdoll );
|
||||
|
||||
virtual bool BecomeRagdollBoogie( CBaseEntity *pKiller, const Vector &forceVector, float duration, int flags );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// A version of BecomeRagdollBoogie() that allows the color to change and returns the entity itself instead.
|
||||
// In order to avoid breaking anything, it doesn't change the original function.
|
||||
virtual CBaseEntity *BecomeRagdollBoogie( CBaseEntity *pKiller, const Vector &forceVector, float duration, int flags, const Vector *vecColor );
|
||||
#endif
|
||||
|
||||
CBaseEntity *FindHealthItem( const Vector &vecPosition, const Vector &range );
|
||||
|
||||
|
||||
virtual CBaseEntity *CheckTraceHullAttack( float flDist, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float forceScale = 1.0f, bool bDamageAnyNPC = false );
|
||||
virtual CBaseEntity *CheckTraceHullAttack( const Vector &vStart, const Vector &vEnd, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float flForceScale = 1.0f, bool bDamageAnyNPC = false );
|
||||
|
||||
virtual CBaseCombatCharacter *MyCombatCharacterPointer( void ) { return this; }
|
||||
|
||||
// VPHYSICS
|
||||
virtual void VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent );
|
||||
virtual void VPhysicsUpdate( IPhysicsObject *pPhysics );
|
||||
float CalculatePhysicsStressDamage( vphysics_objectstress_t *pStressOut, IPhysicsObject *pPhysics );
|
||||
void ApplyStressDamage( IPhysicsObject *pPhysics, bool bRequireLargeObject );
|
||||
|
||||
virtual void PushawayTouch( CBaseEntity *pOther ) {}
|
||||
|
||||
void SetImpactEnergyScale( float fScale ) { m_impactEnergyScale = fScale; }
|
||||
|
||||
virtual void UpdateOnRemove( void );
|
||||
|
||||
virtual Disposition_t IRelationType( CBaseEntity *pTarget );
|
||||
virtual int IRelationPriority( CBaseEntity *pTarget );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void AddRelationship( const char *pszRelationship, CBaseEntity *pActivator );
|
||||
void InputSetRelationship( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
virtual void SetLightingOriginRelative( CBaseEntity *pLightingOrigin );
|
||||
|
||||
protected:
|
||||
Relationship_t *FindEntityRelationship( CBaseEntity *pTarget );
|
||||
|
||||
public:
|
||||
|
||||
// Vehicle queries
|
||||
virtual bool IsInAVehicle( void ) const { return false; }
|
||||
virtual IServerVehicle *GetVehicle( void ) { return NULL; }
|
||||
virtual CBaseEntity *GetVehicleEntity( void ) { return NULL; }
|
||||
virtual bool ExitVehicle( void ) { return false; }
|
||||
|
||||
// Blood color (see BLOOD_COLOR_* macros in baseentity.h)
|
||||
void SetBloodColor( int nBloodColor );
|
||||
#ifdef MAPBASE
|
||||
void InputSetBloodColor( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
// Weapons..
|
||||
CBaseCombatWeapon* GetActiveWeapon() const;
|
||||
int WeaponCount() const;
|
||||
CBaseCombatWeapon* GetWeapon( int i ) const;
|
||||
bool RemoveWeapon( CBaseCombatWeapon *pWeapon );
|
||||
virtual void RemoveAllWeapons();
|
||||
WeaponProficiency_t GetCurrentWeaponProficiency()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// Mapbase adds proficiency override
|
||||
return (m_ProficiencyOverride > WEAPON_PROFICIENCY_INVALID) ? m_ProficiencyOverride : m_CurrentWeaponProficiency;
|
||||
#else
|
||||
return m_CurrentWeaponProficiency;
|
||||
#endif
|
||||
}
|
||||
void SetCurrentWeaponProficiency( WeaponProficiency_t iProficiency ) { m_CurrentWeaponProficiency = iProficiency; }
|
||||
virtual WeaponProficiency_t CalcWeaponProficiency( CBaseCombatWeapon *pWeapon );
|
||||
virtual Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget = NULL );
|
||||
virtual float GetSpreadBias( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget );
|
||||
virtual void DoMuzzleFlash();
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
HSCRIPT GetScriptActiveWeapon();
|
||||
HSCRIPT GetScriptWeaponIndex( int i );
|
||||
HSCRIPT GetScriptWeaponByType( const char *pszWeapon, int iSubType = 0 );
|
||||
void GetScriptAllWeapons( HSCRIPT hTable );
|
||||
int ScriptGetCurrentWeaponProficiency() { return GetCurrentWeaponProficiency(); }
|
||||
|
||||
void ScriptDropWeapon( HSCRIPT hWeapon );
|
||||
void ScriptEquipWeapon( HSCRIPT hWeapon );
|
||||
|
||||
int ScriptGetAmmoCount( int iType ) const;
|
||||
void ScriptSetAmmoCount( int iType, int iCount );
|
||||
|
||||
const Vector& ScriptGetAttackSpread( HSCRIPT hWeapon, HSCRIPT hTarget );
|
||||
float ScriptGetSpreadBias( HSCRIPT hWeapon, HSCRIPT hTarget );
|
||||
|
||||
int ScriptRelationType( HSCRIPT pTarget );
|
||||
int ScriptRelationPriority( HSCRIPT pTarget );
|
||||
void ScriptSetRelationship( HSCRIPT pTarget, int disposition, int priority );
|
||||
|
||||
HSCRIPT GetScriptVehicleEntity();
|
||||
|
||||
bool ScriptInViewCone( const Vector &vecSpot ) { return FInViewCone( vecSpot ); }
|
||||
bool ScriptEntInViewCone( HSCRIPT pEntity ) { return FInViewCone( ToEnt( pEntity ) ); }
|
||||
|
||||
bool ScriptInAimCone( const Vector &vecSpot ) { return FInAimCone( vecSpot ); }
|
||||
bool ScriptEntInAimCone( HSCRIPT pEntity ) { return FInAimCone( ToEnt( pEntity ) ); }
|
||||
|
||||
const Vector& ScriptBodyAngles( void ) { static Vector vec; QAngle qa = BodyAngles(); vec.x = qa.x; vec.y = qa.y; vec.z = qa.z; return vec; }
|
||||
#endif
|
||||
|
||||
// Interactions
|
||||
static void InitInteractionSystem();
|
||||
|
||||
// Relationships
|
||||
static void AllocateDefaultRelationships( );
|
||||
static void SetDefaultRelationship( Class_T nClass, Class_T nClassTarget, Disposition_t nDisposition, int nPriority );
|
||||
#ifdef MAPBASE
|
||||
static Disposition_t GetDefaultRelationshipDisposition( Class_T nClassSource, Class_T nClassTarget );
|
||||
static int GetDefaultRelationshipPriority( Class_T nClassSource, Class_T nClassTarget );
|
||||
int GetDefaultRelationshipPriority( Class_T nClassTarget );
|
||||
#endif
|
||||
Disposition_t GetDefaultRelationshipDisposition( Class_T nClassTarget );
|
||||
virtual void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority );
|
||||
virtual bool RemoveEntityRelationship( CBaseEntity *pEntity );
|
||||
virtual void AddClassRelationship( Class_T nClass, Disposition_t nDisposition, int nPriority );
|
||||
#ifdef MAPBASE
|
||||
virtual bool RemoveClassRelationship( Class_T nClass );
|
||||
#endif
|
||||
|
||||
virtual void ChangeTeam( int iTeamNum );
|
||||
|
||||
// Nav hull type
|
||||
Hull_t GetHullType() const { return m_eHull; }
|
||||
void SetHullType( Hull_t hullType ) { m_eHull = hullType; }
|
||||
|
||||
// FIXME: The following 3 methods are backdoor hack methods
|
||||
|
||||
// This is a sort of hack back-door only used by physgun!
|
||||
void SetAmmoCount( int iCount, int iAmmoIndex );
|
||||
|
||||
// This is a hack to blat out the current active weapon...
|
||||
// Used by weapon_slam + game_ui
|
||||
void SetActiveWeapon( CBaseCombatWeapon *pNewWeapon );
|
||||
void ClearActiveWeapon() { SetActiveWeapon( NULL ); }
|
||||
virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) {}
|
||||
|
||||
// I can't use my current weapon anymore. Switch me to the next best weapon.
|
||||
bool SwitchToNextBestWeapon(CBaseCombatWeapon *pCurrent);
|
||||
|
||||
// This is a hack to copy the relationship strings used by monstermaker
|
||||
void SetRelationshipString( string_t theString ) { m_RelationshipString = theString; }
|
||||
|
||||
float GetNextAttack() const { return m_flNextAttack; }
|
||||
void SetNextAttack( float flWait ) { m_flNextAttack = flWait; }
|
||||
|
||||
bool m_bForceServerRagdoll;
|
||||
|
||||
// Pickup prevention
|
||||
bool IsAllowedToPickupWeapons( void ) { return !m_bPreventWeaponPickup; }
|
||||
void SetPreventWeaponPickup( bool bPrevent ) { m_bPreventWeaponPickup = bPrevent; }
|
||||
bool m_bPreventWeaponPickup;
|
||||
|
||||
virtual CNavArea *GetLastKnownArea( void ) const { return m_lastNavArea; } // return the last nav area the player occupied - NULL if unknown
|
||||
virtual bool IsAreaTraversable( const CNavArea *area ) const; // return true if we can use the given area
|
||||
virtual void ClearLastKnownArea( void );
|
||||
virtual void UpdateLastKnownArea( void ); // invoke this to update our last known nav area (since there is no think method chained to CBaseCombatCharacter)
|
||||
virtual void OnNavAreaChanged( CNavArea *enteredArea, CNavArea *leftArea ) { } // invoked (by UpdateLastKnownArea) when we enter a new nav area (or it is reset to NULL)
|
||||
virtual void OnNavAreaRemoved( CNavArea *removedArea );
|
||||
|
||||
// -----------------------
|
||||
// Notification from INextBots.
|
||||
// -----------------------
|
||||
virtual void OnPursuedBy( INextBot * RESTRICT pPursuer ){} // called every frame while pursued by a bot in DirectChase.
|
||||
|
||||
#ifdef GLOWS_ENABLE
|
||||
// Glows
|
||||
void AddGlowEffect( void );
|
||||
void RemoveGlowEffect( void );
|
||||
bool IsGlowEffectActive( void );
|
||||
#endif // GLOWS_ENABLE
|
||||
|
||||
#ifdef INVASION_DLL
|
||||
public:
|
||||
|
||||
|
||||
// TF2 Powerups
|
||||
virtual bool CanBePoweredUp( void );
|
||||
bool HasPowerup( int iPowerup );
|
||||
virtual bool CanPowerupNow( int iPowerup ); // Return true if I can be powered by this powerup right now
|
||||
virtual bool CanPowerupEver( int iPowerup ); // Return true if I ever accept this powerup type
|
||||
|
||||
void SetPowerup( int iPowerup, bool bState, float flTime = 0, float flAmount = 0, CBaseEntity *pAttacker = NULL, CDamageModifier *pDamageModifier = NULL );
|
||||
virtual bool AttemptToPowerup( int iPowerup, float flTime, float flAmount = 0, CBaseEntity *pAttacker = NULL, CDamageModifier *pDamageModifier = NULL );
|
||||
virtual float PowerupDuration( int iPowerup, float flTime );
|
||||
virtual void PowerupStart( int iPowerup, float flAmount = 0, CBaseEntity *pAttacker = NULL, CDamageModifier *pDamageModifier = NULL );
|
||||
virtual void PowerupEnd( int iPowerup );
|
||||
|
||||
void PowerupThink( void );
|
||||
virtual void PowerupThink( int iPowerup );
|
||||
|
||||
public:
|
||||
|
||||
CNetworkVar( int, m_iPowerups );
|
||||
float m_flPowerupAttemptTimes[ MAX_POWERUPS ];
|
||||
float m_flPowerupEndTimes[ MAX_POWERUPS ];
|
||||
float m_flFractionalBoost; // POWERUP_BOOST health fraction - specific powerup data
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
// returns the last body region that took damage
|
||||
int LastHitGroup() const { return m_LastHitGroup; }
|
||||
#ifndef MAPBASE // For filter_damage_transfer
|
||||
protected:
|
||||
#endif
|
||||
void SetLastHitGroup( int nHitGroup ) { m_LastHitGroup = nHitGroup; }
|
||||
|
||||
public:
|
||||
CNetworkVar( float, m_flNextAttack ); // cannot attack again until this time
|
||||
|
||||
#ifdef GLOWS_ENABLE
|
||||
protected:
|
||||
CNetworkVar( bool, m_bGlowEnabled );
|
||||
#endif // GLOWS_ENABLE
|
||||
|
||||
private:
|
||||
Hull_t m_eHull;
|
||||
|
||||
void UpdateGlowEffect( void );
|
||||
void DestroyGlowEffect( void );
|
||||
|
||||
protected:
|
||||
int m_bloodColor; // color of blood particless
|
||||
|
||||
// -------------------
|
||||
// combat ability data
|
||||
// -------------------
|
||||
float m_flFieldOfView; // cosine of field of view for this character
|
||||
Vector m_HackedGunPos; // HACK until we can query end of gun
|
||||
string_t m_RelationshipString; // Used to load up relationship keyvalues
|
||||
float m_impactEnergyScale;// scale the amount of energy used to calculate damage this ent takes due to physics
|
||||
|
||||
public:
|
||||
static int GetInteractionID(); // Returns the next interaction #
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Mapbase's new method for adding interactions which allows them to be handled with their names, currently for VScript
|
||||
static void AddInteractionWithString( int &interaction, const char *szName );
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Visibility-related stuff
|
||||
bool ComputeLOS( const Vector &vecEyePosition, const Vector &vecTarget ) const;
|
||||
private:
|
||||
// For weapon strip
|
||||
void ThrowDirForWeaponStrip( CBaseCombatWeapon *pWeapon, const Vector &vecForward, Vector *pVecThrowDir );
|
||||
void DropWeaponForWeaponStrip( CBaseCombatWeapon *pWeapon, const Vector &vecForward, const QAngle &vecAngles, float flDiameter );
|
||||
|
||||
friend class CScriptedTarget; // needs to access GetInteractionID()
|
||||
|
||||
static int m_lastInteraction; // Last registered interaction #
|
||||
static Relationship_t** m_DefaultRelationship;
|
||||
|
||||
// attack/damage
|
||||
int m_LastHitGroup; // the last body region that took damage
|
||||
float m_flDamageAccumulator; // so very small amounts of damage do not get lost.
|
||||
int m_iDamageCount; // # of times NPC has been damaged. used for tracking 1-shot kills.
|
||||
|
||||
// Weapon proficiency gets calculated each time an NPC changes his weapon, and then
|
||||
// cached off as the CurrentWeaponProficiency.
|
||||
WeaponProficiency_t m_CurrentWeaponProficiency;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Weapon proficiency can be overridden with this.
|
||||
WeaponProficiency_t m_ProficiencyOverride = WEAPON_PROFICIENCY_INVALID;
|
||||
#endif
|
||||
|
||||
// ---------------
|
||||
// Relationships
|
||||
// ---------------
|
||||
CUtlVector<Relationship_t> m_Relationship; // Array of relationships
|
||||
|
||||
protected:
|
||||
// shared ammo slots
|
||||
CNetworkArrayForDerived( int, m_iAmmo, MAX_AMMO_SLOTS );
|
||||
|
||||
// Usable character items
|
||||
CNetworkArray( CBaseCombatWeaponHandle, m_hMyWeapons, MAX_WEAPONS );
|
||||
|
||||
CNetworkHandle( CBaseCombatWeapon, m_hActiveWeapon );
|
||||
|
||||
friend class CCleanupDefaultRelationShips;
|
||||
|
||||
IntervalTimer m_aliveTimer;
|
||||
|
||||
unsigned int m_hasBeenInjured; // bitfield corresponding to team ID that did the injury
|
||||
|
||||
// we do this because MAX_TEAMS is 32, which is wasteful for most games
|
||||
enum { MAX_DAMAGE_TEAMS = 4 };
|
||||
struct DamageHistory
|
||||
{
|
||||
int team; // which team hurt us (TEAM_INVALID means slot unused)
|
||||
IntervalTimer interval; // how long has it been
|
||||
};
|
||||
DamageHistory m_damageHistory[ MAX_DAMAGE_TEAMS ];
|
||||
|
||||
// last known navigation area of player - NULL if unknown
|
||||
CNavArea *m_lastNavArea;
|
||||
CAI_MoveMonitor m_NavAreaUpdateMonitor;
|
||||
int m_registeredNavTeam; // ugly, but needed to clean up player team counts in nav mesh
|
||||
};
|
||||
|
||||
|
||||
inline float CBaseCombatCharacter::GetAliveDuration( void ) const
|
||||
{
|
||||
return m_aliveTimer.GetElapsedTime();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
inline int CBaseCombatCharacter::WeaponCount() const
|
||||
{
|
||||
return MAX_WEAPONS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : i -
|
||||
//-----------------------------------------------------------------------------
|
||||
inline CBaseCombatWeapon *CBaseCombatCharacter::GetWeapon( int i ) const
|
||||
{
|
||||
Assert( (i >= 0) && (i < MAX_WEAPONS) );
|
||||
return m_hMyWeapons[i].Get();
|
||||
}
|
||||
|
||||
#ifdef INVASION_DLL
|
||||
// Powerup Inlines
|
||||
inline bool CBaseCombatCharacter::CanBePoweredUp( void ) { return true; }
|
||||
inline float CBaseCombatCharacter::PowerupDuration( int iPowerup, float flTime ) { return flTime; }
|
||||
inline void CBaseCombatCharacter::PowerupEnd( int iPowerup ) { return; }
|
||||
inline void CBaseCombatCharacter::PowerupThink( int iPowerup ) { return; }
|
||||
#endif
|
||||
|
||||
EXTERN_SEND_TABLE(DT_BaseCombatCharacter);
|
||||
|
||||
void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CTraceFilterMelee : public CTraceFilterEntitiesOnly
|
||||
{
|
||||
public:
|
||||
// It does have a base, but we'll never network anything below here..
|
||||
DECLARE_CLASS_NOBASE( CTraceFilterMelee );
|
||||
|
||||
CTraceFilterMelee( const IHandleEntity *passentity, int collisionGroup, CTakeDamageInfo *dmgInfo, float flForceScale, bool bDamageAnyNPC )
|
||||
: m_pPassEnt(passentity), m_collisionGroup(collisionGroup), m_dmgInfo(dmgInfo), m_pHit(NULL), m_flForceScale(flForceScale), m_bDamageAnyNPC(bDamageAnyNPC)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask );
|
||||
|
||||
public:
|
||||
const IHandleEntity *m_pPassEnt;
|
||||
int m_collisionGroup;
|
||||
CTakeDamageInfo *m_dmgInfo;
|
||||
CBaseEntity *m_pHit;
|
||||
float m_flForceScale;
|
||||
bool m_bDamageAnyNPC;
|
||||
};
|
||||
|
||||
#endif // BASECOMBATCHARACTER_H
|
||||
747
sp/src/game/server/basecombatweapon.cpp
Normal file
747
sp/src/game/server/basecombatweapon.cpp
Normal file
@@ -0,0 +1,747 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "ai_basenpc.h"
|
||||
#include "animation.h"
|
||||
#include "basecombatweapon.h"
|
||||
#include "player.h" // For gEvilImpulse101 / CBasePlayer
|
||||
#include "gamerules.h" // For g_pGameRules
|
||||
#include <KeyValues.h>
|
||||
#include "ammodef.h"
|
||||
#include "baseviewmodel.h"
|
||||
#include "in_buttons.h"
|
||||
#include "soundent.h"
|
||||
#include "weapon_parse.h"
|
||||
#include "game.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "sendproxy.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "vphysics/constraints.h"
|
||||
#include "npcevent.h"
|
||||
#include "igamesystem.h"
|
||||
#include "collisionutils.h"
|
||||
#include "iservervehicle.h"
|
||||
#include "func_break.h"
|
||||
|
||||
#ifdef HL2MP
|
||||
#include "hl2mp_gamerules.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern int gEvilImpulse101; // In Player.h
|
||||
|
||||
// -----------------------------------------
|
||||
// Sprite Index info
|
||||
// -----------------------------------------
|
||||
short g_sModelIndexLaser; // holds the index for the laser beam
|
||||
const char *g_pModelNameLaser = "sprites/laserbeam.vmt";
|
||||
short g_sModelIndexLaserDot; // holds the index for the laser beam dot
|
||||
short g_sModelIndexFireball; // holds the index for the fireball
|
||||
short g_sModelIndexSmoke; // holds the index for the smoke cloud
|
||||
short g_sModelIndexWExplosion; // holds the index for the underwater explosion
|
||||
short g_sModelIndexBubbles; // holds the index for the bubbles model
|
||||
short g_sModelIndexBloodDrop; // holds the sprite index for the initial blood
|
||||
short g_sModelIndexBloodSpray; // holds the sprite index for splattered blood
|
||||
|
||||
|
||||
ConVar weapon_showproficiency( "weapon_showproficiency", "0" );
|
||||
extern ConVar ai_debug_shoot_positions;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Precache global weapon sounds
|
||||
//-----------------------------------------------------------------------------
|
||||
void W_Precache(void)
|
||||
{
|
||||
PrecacheFileWeaponInfoDatabase( filesystem, g_pGameRules->GetEncryptionKey() );
|
||||
|
||||
|
||||
|
||||
#ifdef HL1_DLL
|
||||
g_sModelIndexWExplosion = CBaseEntity::PrecacheModel ("sprites/WXplo1.vmt");// underwater fireball
|
||||
g_sModelIndexBloodSpray = CBaseEntity::PrecacheModel ("sprites/bloodspray.vmt"); // initial blood
|
||||
g_sModelIndexBloodDrop = CBaseEntity::PrecacheModel ("sprites/blood.vmt"); // splattered blood
|
||||
g_sModelIndexLaserDot = CBaseEntity::PrecacheModel("sprites/laserdot.vmt");
|
||||
#endif // HL1_DLL
|
||||
|
||||
#ifndef TF_DLL
|
||||
g_sModelIndexFireball = CBaseEntity::PrecacheModel ("sprites/zerogxplode.vmt");// fireball
|
||||
|
||||
g_sModelIndexSmoke = CBaseEntity::PrecacheModel ("sprites/steam1.vmt");// smoke
|
||||
g_sModelIndexBubbles = CBaseEntity::PrecacheModel ("sprites/bubble.vmt");//bubbles
|
||||
g_sModelIndexLaser = CBaseEntity::PrecacheModel( (char *)g_pModelNameLaser );
|
||||
|
||||
PrecacheParticleSystem( "blood_impact_red_01" );
|
||||
PrecacheParticleSystem( "blood_impact_green_01" );
|
||||
PrecacheParticleSystem( "blood_impact_yellow_01" );
|
||||
|
||||
CBaseEntity::PrecacheModel ("effects/bubble.vmt");//bubble trails
|
||||
|
||||
CBaseEntity::PrecacheModel("models/weapons/w_bullet.mdl");
|
||||
#endif
|
||||
|
||||
CBaseEntity::PrecacheScriptSound( "BaseCombatWeapon.WeaponDrop" );
|
||||
CBaseEntity::PrecacheScriptSound( "BaseCombatWeapon.WeaponMaterialize" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Transmit weapon data
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseCombatWeapon::UpdateTransmitState( void)
|
||||
{
|
||||
// If the weapon is being carried by a CBaseCombatCharacter, let the combat character do the logic
|
||||
// about whether or not to transmit it.
|
||||
if ( GetOwner() )
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_PVSCHECK );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's just lying around, then use CBaseEntity's visibility test to see if it should be sent.
|
||||
return BaseClass::UpdateTransmitState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBaseCombatWeapon::Operator_FrameUpdate( CBaseCombatCharacter *pOperator )
|
||||
{
|
||||
StudioFrameAdvance( ); // animate
|
||||
|
||||
if ( IsSequenceFinished() )
|
||||
{
|
||||
if ( SequenceLoops() )
|
||||
{
|
||||
// animation does loop, which means we're playing subtle idle. Might need to fidget.
|
||||
int iSequence = SelectWeightedSequence( GetActivity() );
|
||||
if ( iSequence != ACTIVITY_NOT_AVAILABLE )
|
||||
{
|
||||
ResetSequence( iSequence ); // Set to new anim (if it's there)
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
{
|
||||
// animation that just ended doesn't loop! That means we just finished a fidget
|
||||
// and should return to our heaviest weighted idle (the subtle one)
|
||||
SelectHeaviestSequence( GetActivity() );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Animation events are passed back to the weapon's owner/operator
|
||||
DispatchAnimEvents( pOperator );
|
||||
|
||||
// Update and dispatch the viewmodel events
|
||||
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
|
||||
|
||||
if ( pOwner == NULL )
|
||||
return;
|
||||
|
||||
CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex );
|
||||
|
||||
if ( vm != NULL )
|
||||
{
|
||||
vm->StudioFrameAdvance();
|
||||
vm->DispatchAnimEvents( this );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pEvent -
|
||||
// *pOperator -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCombatWeapon::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator )
|
||||
{
|
||||
if ( (pEvent->type & AE_TYPE_NEWEVENTSYSTEM) && (pEvent->type & AE_TYPE_SERVER) )
|
||||
{
|
||||
if ( pEvent->event == AE_NPC_WEAPON_FIRE )
|
||||
{
|
||||
bool bSecondary = (atoi( pEvent->options ) != 0);
|
||||
Operator_ForceNPCFire( pOperator, bSecondary );
|
||||
return;
|
||||
}
|
||||
else if ( pEvent->event == AE_WPN_PLAYWPNSOUND )
|
||||
{
|
||||
int iSnd = GetWeaponSoundFromString(pEvent->options);
|
||||
if ( iSnd != -1 )
|
||||
{
|
||||
WeaponSound( (WeaponSound_t)iSnd );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DevWarning( 2, "Unhandled animation event %d from %s --> %s\n", pEvent->event, pOperator->GetClassname(), GetClassname() );
|
||||
}
|
||||
|
||||
// NOTE: This should never be called when a character is operating the weapon. Animation events should be
|
||||
// routed through the character, and then back into CharacterAnimEvent()
|
||||
void CBaseCombatWeapon::HandleAnimEvent( animevent_t *pEvent )
|
||||
{
|
||||
//If the player is receiving this message, pass it through
|
||||
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
|
||||
|
||||
if ( pOwner != NULL )
|
||||
{
|
||||
Operator_HandleAnimEvent( pEvent, pOwner );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Make the weapon visible and tangible
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseEntity* CBaseCombatWeapon::Respawn( void )
|
||||
{
|
||||
// make a copy of this weapon that is invisible and inaccessible to players (no touch function). The weapon spawn/respawn code
|
||||
// will decide when to make the weapon visible and touchable.
|
||||
CBaseEntity *pNewWeapon = CBaseEntity::Create( GetClassname(), g_pGameRules->VecWeaponRespawnSpot( this ), GetLocalAngles(), GetOwnerEntity() );
|
||||
|
||||
if ( pNewWeapon )
|
||||
{
|
||||
pNewWeapon->AddEffects( EF_NODRAW );// invisible for now
|
||||
pNewWeapon->SetTouch( NULL );// no touch
|
||||
pNewWeapon->SetThink( &CBaseCombatWeapon::AttemptToMaterialize );
|
||||
|
||||
UTIL_DropToFloor( this, MASK_SOLID );
|
||||
|
||||
// not a typo! We want to know when the weapon the player just picked up should respawn! This new entity we created is the replacement,
|
||||
// but when it should respawn is based on conditions belonging to the weapon that was taken.
|
||||
pNewWeapon->SetNextThink( gpGlobals->curtime + g_pGameRules->FlWeaponRespawnTime( this ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning("Respawn failed to create %s!\n", GetClassname() );
|
||||
}
|
||||
|
||||
return pNewWeapon;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Weapons ignore other weapons when LOS tracing
|
||||
//-----------------------------------------------------------------------------
|
||||
class CWeaponLOSFilter : public CTraceFilterSkipTwoEntities
|
||||
{
|
||||
DECLARE_CLASS( CWeaponLOSFilter, CTraceFilterSkipTwoEntities );
|
||||
public:
|
||||
CWeaponLOSFilter( IHandleEntity *pHandleEntity, IHandleEntity *pHandleEntity2, int collisionGroup ) :
|
||||
CTraceFilterSkipTwoEntities( pHandleEntity, pHandleEntity2, collisionGroup ), m_pVehicle( NULL )
|
||||
{
|
||||
// If the tracing entity is in a vehicle, then ignore it
|
||||
if ( pHandleEntity != NULL )
|
||||
{
|
||||
CBaseCombatCharacter *pBCC = ((CBaseEntity *)pHandleEntity)->MyCombatCharacterPointer();
|
||||
if ( pBCC != NULL )
|
||||
{
|
||||
m_pVehicle = pBCC->GetVehicleEntity();
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
|
||||
{
|
||||
CBaseEntity *pEntity = (CBaseEntity *)pServerEntity;
|
||||
|
||||
if ( pEntity->GetCollisionGroup() == COLLISION_GROUP_WEAPON )
|
||||
return false;
|
||||
|
||||
// Don't collide with the tracing entity's vehicle (if it exists)
|
||||
if ( pServerEntity == m_pVehicle )
|
||||
return false;
|
||||
|
||||
if ( pEntity->GetHealth() > 0 )
|
||||
{
|
||||
CBreakable *pBreakable = dynamic_cast<CBreakable *>(pEntity);
|
||||
if ( pBreakable && pBreakable->IsBreakable() && pBreakable->GetMaterialType() == matGlass)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::ShouldHitEntity( pServerEntity, contentsMask );
|
||||
}
|
||||
|
||||
private:
|
||||
CBaseEntity *m_pVehicle;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Check the weapon LOS for an owner at an arbitrary position
|
||||
// If bSetConditions is true, LOS related conditions will also be set
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseCombatWeapon::WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions )
|
||||
{
|
||||
// --------------------
|
||||
// Check for occlusion
|
||||
// --------------------
|
||||
CAI_BaseNPC* npcOwner = m_hOwner.Get()->MyNPCPointer();
|
||||
|
||||
// Find its relative shoot position
|
||||
Vector vecRelativeShootPosition;
|
||||
VectorSubtract( npcOwner->Weapon_ShootPosition(), npcOwner->GetAbsOrigin(), vecRelativeShootPosition );
|
||||
Vector barrelPos = ownerPos + vecRelativeShootPosition;
|
||||
|
||||
// FIXME: If we're in a vehicle, we need some sort of way to handle shooting out of them
|
||||
|
||||
// Use the custom LOS trace filter
|
||||
CWeaponLOSFilter traceFilter( m_hOwner.Get(), npcOwner->GetEnemy(), COLLISION_GROUP_BREAKABLE_GLASS );
|
||||
trace_t tr;
|
||||
UTIL_TraceLine( barrelPos, targetPos, MASK_SHOT, &traceFilter, &tr );
|
||||
|
||||
// See if we completed the trace without interruption
|
||||
if ( tr.fraction == 1.0 )
|
||||
{
|
||||
if ( ai_debug_shoot_positions.GetBool() )
|
||||
{
|
||||
NDebugOverlay::Line( barrelPos, targetPos, 0, 255, 0, false, 1.0 );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CBaseEntity *pHitEnt = tr.m_pEnt;
|
||||
|
||||
CBasePlayer *pEnemyPlayer = ToBasePlayer( npcOwner->GetEnemy() );
|
||||
|
||||
// is player in a vehicle? if so, verify vehicle is target and return if so (so npc shoots at vehicle)
|
||||
if ( pEnemyPlayer && pEnemyPlayer->IsInAVehicle() )
|
||||
{
|
||||
// Ok, player in vehicle, check if vehicle is target we're looking at, fire if it is
|
||||
// Also, check to see if the owner of the entity is the vehicle, in which case it's valid too.
|
||||
// This catches vehicles that use bone followers.
|
||||
CBaseEntity *pVehicle = pEnemyPlayer->GetVehicle()->GetVehicleEnt();
|
||||
if ( pHitEnt == pVehicle || pHitEnt->GetOwnerEntity() == pVehicle )
|
||||
return true;
|
||||
}
|
||||
|
||||
// Hitting our enemy is a success case
|
||||
if ( pHitEnt == npcOwner->GetEnemy() )
|
||||
{
|
||||
if ( ai_debug_shoot_positions.GetBool() )
|
||||
{
|
||||
NDebugOverlay::Line( barrelPos, targetPos, 0, 255, 0, false, 1.0 );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// If a vehicle is blocking the view, grab its driver and use that as the combat character
|
||||
CBaseCombatCharacter *pBCC;
|
||||
IServerVehicle *pVehicle = pHitEnt->GetServerVehicle();
|
||||
if ( pVehicle )
|
||||
{
|
||||
pBCC = pVehicle->GetPassenger( );
|
||||
}
|
||||
else
|
||||
{
|
||||
pBCC = ToBaseCombatCharacter( pHitEnt );
|
||||
}
|
||||
|
||||
if ( pBCC )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if ( npcOwner->IRelationType( pBCC ) <= D_FR )
|
||||
#else
|
||||
if ( npcOwner->IRelationType( pBCC ) == D_HT )
|
||||
#endif
|
||||
return true;
|
||||
|
||||
if ( bSetConditions )
|
||||
{
|
||||
npcOwner->SetCondition( COND_WEAPON_BLOCKED_BY_FRIEND );
|
||||
}
|
||||
}
|
||||
else if ( bSetConditions )
|
||||
{
|
||||
npcOwner->SetCondition( COND_WEAPON_SIGHT_OCCLUDED );
|
||||
npcOwner->SetEnemyOccluder( pHitEnt );
|
||||
|
||||
if( ai_debug_shoot_positions.GetBool() )
|
||||
{
|
||||
NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 0, 0, false, 1.0 );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Base class always returns not bits
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseCombatWeapon::WeaponRangeAttack1Condition( float flDot, float flDist )
|
||||
{
|
||||
if ( UsesPrimaryAmmo() && !HasPrimaryAmmo() )
|
||||
{
|
||||
return COND_NO_PRIMARY_AMMO;
|
||||
}
|
||||
else if ( flDist < m_fMinRange1)
|
||||
{
|
||||
return COND_TOO_CLOSE_TO_ATTACK;
|
||||
}
|
||||
else if (flDist > m_fMaxRange1)
|
||||
{
|
||||
return COND_TOO_FAR_TO_ATTACK;
|
||||
}
|
||||
else if (flDot < 0.5) // UNDONE: Why check this here? Isn't the AI checking this already?
|
||||
{
|
||||
return COND_NOT_FACING_ATTACK;
|
||||
}
|
||||
|
||||
return COND_CAN_RANGE_ATTACK1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Base class always returns not bits
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseCombatWeapon::WeaponRangeAttack2Condition( float flDot, float flDist )
|
||||
{
|
||||
// currently disabled
|
||||
return COND_NONE;
|
||||
|
||||
if ( m_bReloadsSingly )
|
||||
{
|
||||
if (m_iClip2 <=0)
|
||||
{
|
||||
return COND_NO_SECONDARY_AMMO;
|
||||
}
|
||||
else if ( flDist < m_fMinRange2)
|
||||
{
|
||||
return COND_TOO_CLOSE_TO_ATTACK;
|
||||
}
|
||||
else if (flDist > m_fMaxRange2)
|
||||
{
|
||||
return COND_TOO_FAR_TO_ATTACK;
|
||||
}
|
||||
else if (flDot < 0.5)
|
||||
{
|
||||
return COND_NOT_FACING_ATTACK;
|
||||
}
|
||||
return COND_CAN_RANGE_ATTACK2;
|
||||
}
|
||||
|
||||
return COND_NONE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Base class always returns not bits
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseCombatWeapon::WeaponMeleeAttack1Condition( float flDot, float flDist )
|
||||
{
|
||||
return COND_NONE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Base class always returns not bits
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseCombatWeapon::WeaponMeleeAttack2Condition( float flDot, float flDist )
|
||||
{
|
||||
return COND_NONE;
|
||||
}
|
||||
|
||||
//====================================================================================
|
||||
// WEAPON DROPPING / DESTRUCTION
|
||||
//====================================================================================
|
||||
void CBaseCombatWeapon::Delete( void )
|
||||
{
|
||||
SetTouch( NULL );
|
||||
// FIXME: why doesn't this just remove itself now?
|
||||
SetThink(&CBaseCombatWeapon::SUB_Remove);
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
}
|
||||
|
||||
void CBaseCombatWeapon::DestroyItem( void )
|
||||
{
|
||||
CBaseCombatCharacter *pOwner = m_hOwner.Get();
|
||||
|
||||
if ( pOwner )
|
||||
{
|
||||
// if attached to a player, remove.
|
||||
pOwner->RemovePlayerItem( this );
|
||||
}
|
||||
|
||||
Kill( );
|
||||
}
|
||||
|
||||
void CBaseCombatWeapon::Kill( void )
|
||||
{
|
||||
SetTouch( NULL );
|
||||
// FIXME: why doesn't this just remove itself now?
|
||||
// FIXME: how is this different than Delete(), and why do they have the same code in them?
|
||||
SetThink(&CBaseCombatWeapon::SUB_Remove);
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
}
|
||||
|
||||
//====================================================================================
|
||||
// FALL TO GROUND
|
||||
//====================================================================================
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Setup for the fall
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCombatWeapon::FallInit( void )
|
||||
{
|
||||
SetModel( GetWorldModel() );
|
||||
VPhysicsDestroyObject();
|
||||
|
||||
if ( !VPhysicsInitNormal( SOLID_BBOX, GetSolidFlags() | FSOLID_TRIGGER, false ) )
|
||||
{
|
||||
SetMoveType( MOVETYPE_FLYGRAVITY );
|
||||
SetSolid( SOLID_BBOX );
|
||||
AddSolidFlags( FSOLID_TRIGGER );
|
||||
}
|
||||
else
|
||||
{
|
||||
#if !defined( CLIENT_DLL )
|
||||
// Constrained start?
|
||||
if ( HasSpawnFlags( SF_WEAPON_START_CONSTRAINED ) )
|
||||
{
|
||||
//Constrain the weapon in place
|
||||
IPhysicsObject *pReferenceObject, *pAttachedObject;
|
||||
|
||||
pReferenceObject = g_PhysWorldObject;
|
||||
pAttachedObject = VPhysicsGetObject();
|
||||
|
||||
if ( pReferenceObject && pAttachedObject )
|
||||
{
|
||||
constraint_fixedparams_t fixed;
|
||||
fixed.Defaults();
|
||||
fixed.InitWithCurrentObjectState( pReferenceObject, pAttachedObject );
|
||||
|
||||
fixed.constraint.forceLimit = lbs2kg( 10000 );
|
||||
fixed.constraint.torqueLimit = lbs2kg( 10000 );
|
||||
|
||||
m_pConstraint = physenv->CreateFixedConstraint( pReferenceObject, pAttachedObject, NULL, fixed );
|
||||
|
||||
m_pConstraint->SetGameData( (void *) this );
|
||||
}
|
||||
}
|
||||
#endif //CLIENT_DLL
|
||||
}
|
||||
|
||||
SetPickupTouch();
|
||||
|
||||
SetThink( &CBaseCombatWeapon::FallThink );
|
||||
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Items that have just spawned run this think to catch them when
|
||||
// they hit the ground. Once we're sure that the object is grounded,
|
||||
// we change its solid type to trigger and set it in a large box that
|
||||
// helps the player get it.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCombatWeapon::FallThink ( void )
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
|
||||
bool shouldMaterialize = false;
|
||||
IPhysicsObject *pPhysics = VPhysicsGetObject();
|
||||
if ( pPhysics )
|
||||
{
|
||||
shouldMaterialize = pPhysics->IsAsleep();
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldMaterialize = (GetFlags() & FL_ONGROUND) ? true : false;
|
||||
}
|
||||
|
||||
if ( shouldMaterialize )
|
||||
{
|
||||
// clatter if we have an owner (i.e., dropped by someone)
|
||||
// don't clatter if the gun is waiting to respawn (if it's waiting, it is invisible!)
|
||||
if ( GetOwnerEntity() )
|
||||
{
|
||||
EmitSound( "BaseCombatWeapon.WeaponDrop" );
|
||||
}
|
||||
Materialize();
|
||||
}
|
||||
}
|
||||
|
||||
//====================================================================================
|
||||
// WEAPON SPAWNING
|
||||
//====================================================================================
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Make a weapon visible and tangible
|
||||
//-----------------------------------------------------------------------------//
|
||||
void CBaseCombatWeapon::Materialize( void )
|
||||
{
|
||||
if ( IsEffectActive( EF_NODRAW ) )
|
||||
{
|
||||
// changing from invisible state to visible.
|
||||
#ifdef HL2MP
|
||||
EmitSound( "AlyxEmp.Charge" );
|
||||
#else
|
||||
EmitSound( "BaseCombatWeapon.WeaponMaterialize" );
|
||||
#endif
|
||||
|
||||
RemoveEffects( EF_NODRAW );
|
||||
DoMuzzleFlash();
|
||||
}
|
||||
#ifdef HL2MP
|
||||
if ( HasSpawnFlags( SF_NORESPAWN ) == false )
|
||||
{
|
||||
VPhysicsInitNormal( SOLID_BBOX, GetSolidFlags() | FSOLID_TRIGGER, false );
|
||||
SetMoveType( MOVETYPE_VPHYSICS );
|
||||
|
||||
HL2MPRules()->AddLevelDesignerPlacedObject( this );
|
||||
}
|
||||
#else
|
||||
SetSolid( SOLID_BBOX );
|
||||
AddSolidFlags( FSOLID_TRIGGER );
|
||||
#endif
|
||||
|
||||
SetPickupTouch();
|
||||
|
||||
SetThink (NULL);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: See if the game rules will let this weapon respawn
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCombatWeapon::AttemptToMaterialize( void )
|
||||
{
|
||||
float time = g_pGameRules->FlWeaponTryRespawn( this );
|
||||
|
||||
if ( time == 0 )
|
||||
{
|
||||
Materialize();
|
||||
return;
|
||||
}
|
||||
|
||||
SetNextThink( gpGlobals->curtime + time );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Weapon has been picked up, should it respawn?
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCombatWeapon::CheckRespawn( void )
|
||||
{
|
||||
switch ( g_pGameRules->WeaponShouldRespawn( this ) )
|
||||
{
|
||||
case GR_WEAPON_RESPAWN_YES:
|
||||
Respawn();
|
||||
break;
|
||||
case GR_WEAPON_RESPAWN_NO:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
class CWeaponList : public CAutoGameSystem
|
||||
{
|
||||
public:
|
||||
CWeaponList( char const *name ) : CAutoGameSystem( name )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void LevelShutdownPostEntity()
|
||||
{
|
||||
m_list.Purge();
|
||||
}
|
||||
|
||||
void AddWeapon( CBaseCombatWeapon *pWeapon )
|
||||
{
|
||||
m_list.AddToTail( pWeapon );
|
||||
}
|
||||
|
||||
void RemoveWeapon( CBaseCombatWeapon *pWeapon )
|
||||
{
|
||||
m_list.FindAndRemove( pWeapon );
|
||||
}
|
||||
CUtlLinkedList< CBaseCombatWeapon * > m_list;
|
||||
};
|
||||
|
||||
CWeaponList g_WeaponList( "CWeaponList" );
|
||||
|
||||
void OnBaseCombatWeaponCreated( CBaseCombatWeapon *pWeapon )
|
||||
{
|
||||
g_WeaponList.AddWeapon( pWeapon );
|
||||
}
|
||||
|
||||
void OnBaseCombatWeaponDestroyed( CBaseCombatWeapon *pWeapon )
|
||||
{
|
||||
g_WeaponList.RemoveWeapon( pWeapon );
|
||||
}
|
||||
|
||||
int CBaseCombatWeapon::GetAvailableWeaponsInBox( CBaseCombatWeapon **pList, int listMax, const Vector &mins, const Vector &maxs )
|
||||
{
|
||||
// linear search all weapons
|
||||
int count = 0;
|
||||
int index = g_WeaponList.m_list.Head();
|
||||
while ( index != g_WeaponList.m_list.InvalidIndex() )
|
||||
{
|
||||
CBaseCombatWeapon *pWeapon = g_WeaponList.m_list[index];
|
||||
// skip any held weapon
|
||||
if ( !pWeapon->GetOwner() )
|
||||
{
|
||||
// restrict to mins/maxs
|
||||
if ( IsPointInBox( pWeapon->GetAbsOrigin(), mins, maxs ) )
|
||||
{
|
||||
if ( count < listMax )
|
||||
{
|
||||
pList[count] = pWeapon;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
index = g_WeaponList.m_list.Next( index );
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseCombatWeapon::ObjectCaps( void )
|
||||
{
|
||||
int caps = BaseClass::ObjectCaps();
|
||||
if ( !IsFollowingEntity() && !HasSpawnFlags(SF_WEAPON_NO_PLAYER_PICKUP) )
|
||||
{
|
||||
caps |= FCAP_IMPULSE_USE;
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCombatWeapon::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
CBasePlayer *pPlayer = ToBasePlayer( pActivator );
|
||||
|
||||
if ( pPlayer )
|
||||
{
|
||||
m_OnPlayerUse.FireOutput( pActivator, pCaller );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Mark that we're being +USE'd, not bumped
|
||||
AddSpawnFlags(SF_WEAPON_USED);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Bump the weapon to try equipping it before picking it up physically. This is
|
||||
// important in a few spots in the game where the player could potentially +use pickup
|
||||
// and then THROW AWAY a vital weapon, rendering them unable to continue the game.
|
||||
//
|
||||
if ( pPlayer->BumpWeapon( this ) )
|
||||
{
|
||||
OnPickedUp( pPlayer );
|
||||
}
|
||||
else
|
||||
{
|
||||
pPlayer->PickupObject( this );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
RemoveSpawnFlags(SF_WEAPON_USED);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
30
sp/src/game/server/basecombatweapon.h
Normal file
30
sp/src/game/server/basecombatweapon.h
Normal file
@@ -0,0 +1,30 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef COMBATWEAPON_H
|
||||
#define COMBATWEAPON_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "entityoutput.h"
|
||||
#include "basecombatweapon_shared.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Bullet types
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------
|
||||
// Sounds
|
||||
// -----------------------------------------
|
||||
|
||||
struct animevent_t;
|
||||
|
||||
extern void SpawnBlood(Vector vecSpot, const Vector &vecDir, int bloodColor, float flDamage);
|
||||
|
||||
#endif // COMBATWEAPON_H
|
||||
10486
sp/src/game/server/baseentity.cpp
Normal file
10486
sp/src/game/server/baseentity.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3077
sp/src/game/server/baseentity.h
Normal file
3077
sp/src/game/server/baseentity.h
Normal file
File diff suppressed because it is too large
Load Diff
2967
sp/src/game/server/baseflex.cpp
Normal file
2967
sp/src/game/server/baseflex.cpp
Normal file
File diff suppressed because it is too large
Load Diff
324
sp/src/game/server/baseflex.h
Normal file
324
sp/src/game/server/baseflex.h
Normal file
@@ -0,0 +1,324 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef BASEFLEX_H
|
||||
#define BASEFLEX_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "BaseAnimatingOverlay.h"
|
||||
#include "utlvector.h"
|
||||
#include "utlrbtree.h"
|
||||
#include "sceneentity_shared.h"
|
||||
|
||||
struct flexsettinghdr_t;
|
||||
struct flexsetting_t;
|
||||
class AI_Response;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A .vfe referenced by a scene during .vcd playback
|
||||
//-----------------------------------------------------------------------------
|
||||
class CFlexSceneFile
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MAX_FLEX_FILENAME = 128,
|
||||
};
|
||||
|
||||
char filename[ MAX_FLEX_FILENAME ];
|
||||
void *buffer;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Animated characters who have vertex flex capability (e.g., facial expressions)
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBaseFlex : public CBaseAnimatingOverlay
|
||||
{
|
||||
DECLARE_CLASS( CBaseFlex, CBaseAnimatingOverlay );
|
||||
public:
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_PREDICTABLE();
|
||||
// script description
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
|
||||
// Construction
|
||||
CBaseFlex( void );
|
||||
~CBaseFlex( void );
|
||||
|
||||
virtual void SetModel( const char *szModelName );
|
||||
|
||||
void Blink( );
|
||||
|
||||
virtual void SetViewtarget( const Vector &viewtarget );
|
||||
const Vector &GetViewtarget( void ) const;
|
||||
|
||||
void SetFlexWeight( char *szName, float value );
|
||||
void SetFlexWeight( LocalFlexController_t index, float value );
|
||||
float GetFlexWeight( char *szName );
|
||||
float GetFlexWeight( LocalFlexController_t index );
|
||||
|
||||
// Look up flex controller index by global name
|
||||
LocalFlexController_t FindFlexController( const char *szName );
|
||||
void EnsureTranslations( const flexsettinghdr_t *pSettinghdr );
|
||||
|
||||
// Keep track of what scenes are being played
|
||||
void StartChoreoScene( CChoreoScene *scene );
|
||||
void RemoveChoreoScene( CChoreoScene *scene, bool canceled = false );
|
||||
|
||||
// Start the specifics of an scene event
|
||||
#ifdef MAPBASE
|
||||
virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget, CSceneEntity *pSceneEnt = NULL );
|
||||
#else
|
||||
virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget );
|
||||
#endif
|
||||
|
||||
// Manipulation of events for the object
|
||||
// Should be called by think function to process all scene events
|
||||
// The default implementation resets m_flexWeight array and calls
|
||||
// AddSceneEvents
|
||||
virtual void ProcessSceneEvents( void );
|
||||
|
||||
// Assumes m_flexWeight array has been set up, this adds the actual currently playing
|
||||
// expressions to the flex weights and adds other scene events as needed
|
||||
virtual bool ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
|
||||
|
||||
// Remove all playing events
|
||||
void ClearSceneEvents( CChoreoScene *scene, bool canceled );
|
||||
|
||||
// Stop specifics of event
|
||||
virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
|
||||
|
||||
// Add the event to the queue for this actor
|
||||
#ifdef MAPBASE
|
||||
void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget = NULL, CSceneEntity *pSceneEnt = NULL );
|
||||
#else
|
||||
void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget = NULL );
|
||||
#endif
|
||||
|
||||
// Remove the event from the queue for this actor
|
||||
void RemoveSceneEvent( CChoreoScene *scene, CChoreoEvent *event, bool fastKill );
|
||||
|
||||
// Checks to see if the event should be considered "completed"
|
||||
bool CheckSceneEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event );
|
||||
|
||||
// Checks to see if a event should be considered "completed"
|
||||
virtual bool CheckSceneEventCompletion( CSceneEventInfo *info, float currenttime, CChoreoScene *scene, CChoreoEvent *event );
|
||||
|
||||
// Finds the layer priority of the current scene
|
||||
int GetScenePriority( CChoreoScene *scene );
|
||||
|
||||
// Returns true if the actor is not currently in a scene OR if the actor
|
||||
// is in a scene, but a PERMIT_RESPONSES event is active and the permit time
|
||||
// period has enough time remaining to handle the response in full.
|
||||
bool PermitResponse( float response_length );
|
||||
|
||||
// Set response end time (0 to clear response blocking)
|
||||
void SetPermitResponse( float endtime );
|
||||
|
||||
void SentenceStop( void ) { EmitSound( "AI_BaseNPC.SentenceStop" ); }
|
||||
|
||||
virtual float PlayScene( const char *pszScene, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
|
||||
#ifdef MAPBASE
|
||||
virtual float PlayAutoGeneratedSoundScene( const char *soundname, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
|
||||
#else
|
||||
virtual float PlayAutoGeneratedSoundScene( const char *soundname );
|
||||
#endif
|
||||
|
||||
// Returns the script instance of the scene entity associated with our oldest ("top level") scene event
|
||||
virtual HSCRIPT ScriptGetOldestScene( void );
|
||||
virtual HSCRIPT ScriptGetSceneByIndex( int index );
|
||||
|
||||
virtual int GetSpecialDSP( void ) { return 0; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
virtual bool GetGameTextSpeechParams( hudtextparms_t ¶ms );
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// For handling .vfe files
|
||||
// Search list, or add if not in list
|
||||
const void *FindSceneFile( const char *filename );
|
||||
|
||||
// Find setting by name
|
||||
const flexsetting_t *FindNamedSetting( const flexsettinghdr_t *pSettinghdr, const char *expr );
|
||||
|
||||
// Called at the lowest level to actually apply an expression
|
||||
void AddFlexSetting( const char *expr, float scale, const flexsettinghdr_t *pSettinghdr, bool newexpression );
|
||||
|
||||
// Called at the lowest level to actually apply a flex animation
|
||||
void AddFlexAnimation( CSceneEventInfo *info );
|
||||
|
||||
bool HasSceneEvents() const;
|
||||
bool IsRunningSceneMoveToEvent();
|
||||
|
||||
LocalFlexController_t FlexControllerLocalToGlobal( const flexsettinghdr_t *pSettinghdr, int key );
|
||||
|
||||
private:
|
||||
// Starting various expression types
|
||||
|
||||
bool RequestStartSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget );
|
||||
bool RequestStartGestureSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget );
|
||||
|
||||
bool HandleStartSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor );
|
||||
bool HandleStartGestureSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor );
|
||||
bool StartFacingSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget );
|
||||
bool StartMoveToSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget );
|
||||
|
||||
// Processing various expression types
|
||||
bool ProcessFlexAnimationSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
|
||||
bool ProcessFlexSettingSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
|
||||
bool ProcessSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
|
||||
bool ProcessGestureSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
|
||||
bool ProcessFacingSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
|
||||
bool ProcessMoveToSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
|
||||
bool ProcessLookAtSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
|
||||
|
||||
// Set playing the scene sequence
|
||||
public:
|
||||
bool EnterSceneSequence( CChoreoScene *scene, CChoreoEvent *event, bool bRestart = false );
|
||||
private:
|
||||
bool ExitSceneSequence( void );
|
||||
|
||||
private:
|
||||
CNetworkArray( float, m_flexWeight, MAXSTUDIOFLEXCTRL ); // indexed by model local flexcontroller
|
||||
|
||||
// Vector from actor to eye target
|
||||
CNetworkVector( m_viewtarget );
|
||||
|
||||
// Blink state
|
||||
CNetworkVar( int, m_blinktoggle );
|
||||
|
||||
// Array of active SceneEvents, in order oldest to newest
|
||||
CUtlVector < CSceneEventInfo > m_SceneEvents;
|
||||
|
||||
// Mapping for each loaded scene file used by this actor
|
||||
struct FS_LocalToGlobal_t
|
||||
{
|
||||
explicit FS_LocalToGlobal_t() :
|
||||
m_Key( 0 ),
|
||||
m_nCount( 0 ),
|
||||
m_Mapping( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
explicit FS_LocalToGlobal_t( const flexsettinghdr_t *key ) :
|
||||
m_Key( key ),
|
||||
m_nCount( 0 ),
|
||||
m_Mapping( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
void SetCount( int count )
|
||||
{
|
||||
Assert( !m_Mapping );
|
||||
Assert( count > 0 );
|
||||
m_nCount = count;
|
||||
m_Mapping = new LocalFlexController_t[ m_nCount ];
|
||||
Q_memset( m_Mapping, 0, m_nCount * sizeof( int ) );
|
||||
}
|
||||
|
||||
FS_LocalToGlobal_t( const FS_LocalToGlobal_t& src )
|
||||
{
|
||||
m_Key = src.m_Key;
|
||||
delete m_Mapping;
|
||||
m_Mapping = new LocalFlexController_t[ src.m_nCount ];
|
||||
Q_memcpy( m_Mapping, src.m_Mapping, src.m_nCount * sizeof( int ) );
|
||||
|
||||
m_nCount = src.m_nCount;
|
||||
}
|
||||
|
||||
~FS_LocalToGlobal_t()
|
||||
{
|
||||
delete m_Mapping;
|
||||
m_nCount = 0;
|
||||
m_Mapping = 0;
|
||||
}
|
||||
|
||||
const flexsettinghdr_t *m_Key;
|
||||
int m_nCount;
|
||||
LocalFlexController_t *m_Mapping;
|
||||
};
|
||||
|
||||
static bool FlexSettingLessFunc( const FS_LocalToGlobal_t& lhs, const FS_LocalToGlobal_t& rhs );
|
||||
|
||||
CUtlRBTree< FS_LocalToGlobal_t, unsigned short > m_LocalToGlobal;
|
||||
|
||||
// The NPC is in a scene, but another .vcd (such as a short wave to say in response to the player doing something )
|
||||
// can be layered on top of this actor (assuming duration matches, etc.
|
||||
float m_flAllowResponsesEndTime;
|
||||
|
||||
// List of actively playing scenes
|
||||
CUtlVector < CChoreoScene * > m_ActiveChoreoScenes;
|
||||
bool m_bUpdateLayerPriorities;
|
||||
|
||||
public:
|
||||
bool IsSuppressedFlexAnimation( CSceneEventInfo *info );
|
||||
|
||||
private:
|
||||
// last time a foreground flex animation was played
|
||||
float m_flLastFlexAnimationTime;
|
||||
|
||||
|
||||
public:
|
||||
void DoBodyLean( void );
|
||||
|
||||
virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
|
||||
|
||||
|
||||
#ifdef HL2_DLL
|
||||
Vector m_vecPrevOrigin;
|
||||
Vector m_vecPrevVelocity;
|
||||
CNetworkVector( m_vecLean );
|
||||
CNetworkVector( m_vecShift );
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// For toggling blinking
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void CBaseFlex::Blink()
|
||||
{
|
||||
m_blinktoggle = !m_blinktoggle;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Do we have active expressions?
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool CBaseFlex::HasSceneEvents() const
|
||||
{
|
||||
return m_SceneEvents.Count() != 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Other inlines
|
||||
//-----------------------------------------------------------------------------
|
||||
inline const Vector &CBaseFlex::GetViewtarget( ) const
|
||||
{
|
||||
return m_viewtarget.Get(); // bah
|
||||
}
|
||||
|
||||
inline void CBaseFlex::SetFlexWeight( char *szName, float value )
|
||||
{
|
||||
SetFlexWeight( FindFlexController( szName ), value );
|
||||
}
|
||||
|
||||
inline float CBaseFlex::GetFlexWeight( char *szName )
|
||||
{
|
||||
return GetFlexWeight( FindFlexController( szName ) );
|
||||
}
|
||||
|
||||
|
||||
EXTERN_SEND_TABLE(DT_BaseFlex);
|
||||
|
||||
|
||||
#endif // BASEFLEX_H
|
||||
131
sp/src/game/server/basegrenade_concussion.cpp
Normal file
131
sp/src/game/server/basegrenade_concussion.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "baseentity.h"
|
||||
#include "basegrenade_shared.h"
|
||||
#include "soundent.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
class CBaseGrenadeConcussion : public CBaseGrenade
|
||||
{
|
||||
DECLARE_DATADESC();
|
||||
|
||||
public:
|
||||
DECLARE_CLASS( CBaseGrenadeConcussion, CBaseGrenade );
|
||||
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void FallThink(void);
|
||||
void ExplodeConcussion( CBaseEntity *pOther );
|
||||
|
||||
protected:
|
||||
static int m_nTrailSprite;
|
||||
};
|
||||
|
||||
int CBaseGrenadeConcussion::m_nTrailSprite = 0;
|
||||
|
||||
LINK_ENTITY_TO_CLASS( npc_concussiongrenade, CBaseGrenadeConcussion );
|
||||
|
||||
BEGIN_DATADESC( CBaseGrenadeConcussion )
|
||||
|
||||
DEFINE_THINKFUNC( FallThink ),
|
||||
DEFINE_ENTITYFUNC( ExplodeConcussion ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
void CBaseGrenadeConcussion::FallThink(void)
|
||||
{
|
||||
if (!IsInWorld())
|
||||
{
|
||||
Remove( );
|
||||
return;
|
||||
}
|
||||
CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, GetAbsVelocity().Length( ), 0.2 );
|
||||
|
||||
SetNextThink( gpGlobals->curtime + random->RandomFloat(0.05, 0.1) );
|
||||
|
||||
if (GetWaterLevel() != 0)
|
||||
{
|
||||
SetAbsVelocity( GetAbsVelocity() * 0.5 );
|
||||
}
|
||||
|
||||
Vector pos = GetAbsOrigin() + Vector(random->RandomFloat(-4, 4), random->RandomFloat(-4, 4), random->RandomFloat(-4, 4));
|
||||
|
||||
CPVSFilter filter( GetAbsOrigin() );
|
||||
|
||||
te->Sprite( filter, 0.0,
|
||||
&pos,
|
||||
m_nTrailSprite,
|
||||
random->RandomFloat(0.5, 0.8),
|
||||
200 );
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Contact grenade, explode when it touches something
|
||||
//
|
||||
void CBaseGrenadeConcussion::ExplodeConcussion( CBaseEntity *pOther )
|
||||
{
|
||||
trace_t tr;
|
||||
Vector vecSpot;// trace starts here!
|
||||
|
||||
Vector velDir = GetAbsVelocity();
|
||||
VectorNormalize( velDir );
|
||||
vecSpot = GetAbsOrigin() - velDir * 32;
|
||||
UTIL_TraceLine( vecSpot, vecSpot + velDir * 64, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
Explode( &tr, DMG_BLAST );
|
||||
}
|
||||
|
||||
|
||||
void CBaseGrenadeConcussion::Spawn( void )
|
||||
{
|
||||
// point sized, solid, bouncing
|
||||
SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
|
||||
SetSolid( SOLID_BBOX );
|
||||
SetCollisionGroup( COLLISION_GROUP_PROJECTILE );
|
||||
SetModel( "models/weapons/w_grenade.mdl" ); // BUG: wrong model
|
||||
|
||||
UTIL_SetSize(this, vec3_origin, vec3_origin);
|
||||
|
||||
// contact grenades arc lower
|
||||
SetGravity( UTIL_ScaleForGravity( 400 ) ); // use a lower gravity for grenades to make them easier to see
|
||||
QAngle angles;
|
||||
VectorAngles(GetAbsVelocity(), angles );
|
||||
SetLocalAngles( angles );
|
||||
|
||||
m_nRenderFX = kRenderFxGlowShell;
|
||||
SetRenderColor( 200, 200, 20, 255 );
|
||||
|
||||
// make NPCs afaid of it while in the air
|
||||
SetThink( &CBaseGrenadeConcussion::FallThink );
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
|
||||
// Tumble in air
|
||||
QAngle vecAngVel( random->RandomFloat ( -100, -500 ), 0, 0 );
|
||||
SetLocalAngularVelocity( vecAngVel );
|
||||
|
||||
// Explode on contact
|
||||
SetTouch( &CBaseGrenadeConcussion::ExplodeConcussion );
|
||||
|
||||
m_flDamage = 80;
|
||||
|
||||
// Allow player to blow this puppy up in the air
|
||||
m_takedamage = DAMAGE_YES;
|
||||
}
|
||||
|
||||
|
||||
void CBaseGrenadeConcussion::Precache( void )
|
||||
{
|
||||
BaseClass::Precache( );
|
||||
|
||||
PrecacheModel("models/weapons/w_grenade.mdl");
|
||||
m_nTrailSprite = PrecacheModel("sprites/twinkle01.vmt");
|
||||
}
|
||||
71
sp/src/game/server/basegrenade_contact.cpp
Normal file
71
sp/src/game/server/basegrenade_contact.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "basegrenade_shared.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern ConVar sk_plr_dmg_grenade;
|
||||
|
||||
// ==========================================================================================
|
||||
|
||||
class CBaseGrenadeContact : public CBaseGrenade
|
||||
{
|
||||
DECLARE_CLASS( CBaseGrenadeContact, CBaseGrenade );
|
||||
public:
|
||||
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
};
|
||||
LINK_ENTITY_TO_CLASS( npc_contactgrenade, CBaseGrenadeContact );
|
||||
|
||||
|
||||
void CBaseGrenadeContact::Spawn( void )
|
||||
{
|
||||
// point sized, solid, bouncing
|
||||
SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
|
||||
SetSolid( SOLID_BBOX );
|
||||
SetCollisionGroup( COLLISION_GROUP_PROJECTILE );
|
||||
SetModel( "models/weapons/w_grenade.mdl" ); // BUG: wrong model
|
||||
|
||||
UTIL_SetSize(this, vec3_origin, vec3_origin);
|
||||
|
||||
// contact grenades arc lower
|
||||
SetGravity( UTIL_ScaleForGravity( 400 ) ); // use a lower gravity for grenades to make them easier to see
|
||||
|
||||
QAngle angles;
|
||||
VectorAngles(GetAbsVelocity(), angles);
|
||||
SetLocalAngles( angles );
|
||||
|
||||
// make NPCs afaid of it while in the air
|
||||
SetThink( &CBaseGrenadeContact::DangerSoundThink );
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
|
||||
// Tumble in air
|
||||
QAngle vecAngVelocity( random->RandomFloat ( -100, -500 ), 0, 0 );
|
||||
SetLocalAngularVelocity( vecAngVelocity );
|
||||
|
||||
// Explode on contact
|
||||
SetTouch( &CBaseGrenadeContact::ExplodeTouch );
|
||||
|
||||
m_flDamage = sk_plr_dmg_grenade.GetFloat();
|
||||
|
||||
// Allow player to blow this puppy up in the air
|
||||
m_takedamage = DAMAGE_YES;
|
||||
|
||||
m_iszBounceSound = NULL_STRING;
|
||||
}
|
||||
|
||||
|
||||
void CBaseGrenadeContact::Precache( void )
|
||||
{
|
||||
BaseClass::Precache( );
|
||||
|
||||
PrecacheModel("models/weapons/w_grenade.mdl");
|
||||
}
|
||||
73
sp/src/game/server/basegrenade_timed.cpp
Normal file
73
sp/src/game/server/basegrenade_timed.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "basegrenade_shared.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
class CBaseGrenadeTimed : public CBaseGrenade
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CBaseGrenadeTimed, CBaseGrenade );
|
||||
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
};
|
||||
LINK_ENTITY_TO_CLASS( npc_handgrenade, CBaseGrenadeTimed );
|
||||
|
||||
|
||||
void CBaseGrenadeTimed::Spawn( void )
|
||||
{
|
||||
SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
|
||||
SetSolid( SOLID_BBOX );
|
||||
SetCollisionGroup( COLLISION_GROUP_PROJECTILE );
|
||||
SetModel( "models/Weapons/w_grenade.mdl" );
|
||||
|
||||
UTIL_SetSize(this, Vector( -4, -4, -4), Vector(4, 4, 4));
|
||||
|
||||
QAngle angles;
|
||||
Vector vel = GetAbsVelocity();
|
||||
|
||||
VectorAngles( vel, angles );
|
||||
SetLocalAngles( angles );
|
||||
|
||||
SetTouch( &CBaseGrenadeTimed::BounceTouch ); // Bounce if touched
|
||||
|
||||
// Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate
|
||||
// will insert a DANGER sound into the world sound list and delay detonation for one second so that
|
||||
// the grenade explodes after the exact amount of time specified in the call to ShootTimed().
|
||||
|
||||
SetThink( &CBaseGrenadeTimed::TumbleThink );
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
|
||||
// if the delay is < 0.1 seconds, don't fly anywhere
|
||||
if ((m_flDetonateTime - gpGlobals->curtime) < 0.1)
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
SetAbsVelocity( vec3_origin );
|
||||
}
|
||||
|
||||
// Tumble through the air
|
||||
// pGrenade->m_vecAngVelocity.x = -400;
|
||||
SetGravity(1.0); // Don't change or throw calculations will be off!
|
||||
SetFriction(0.8);
|
||||
|
||||
m_flDamage = 100; // ????
|
||||
|
||||
m_takedamage = DAMAGE_NO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CBaseGrenadeTimed::Precache( void )
|
||||
{
|
||||
BaseClass::Precache( );
|
||||
|
||||
PrecacheModel("models/weapons/w_grenade.mdl");
|
||||
}
|
||||
349
sp/src/game/server/basemultiplayerplayer.cpp
Normal file
349
sp/src/game/server/basemultiplayerplayer.cpp
Normal file
@@ -0,0 +1,349 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "mp_shareddefs.h"
|
||||
#include "basemultiplayerplayer.h"
|
||||
|
||||
// Minimum interval between rate-limited commands that players can run.
|
||||
#define COMMAND_MAX_RATE 0.3
|
||||
|
||||
CBaseMultiplayerPlayer::CBaseMultiplayerPlayer()
|
||||
{
|
||||
m_iCurrentConcept = MP_CONCEPT_NONE;
|
||||
m_flLastForcedChangeTeamTime = -1;
|
||||
m_iBalanceScore = 0;
|
||||
m_flConnectionTime = gpGlobals->curtime;
|
||||
|
||||
// per life achievement counters
|
||||
m_pAchievementKV = new KeyValues( "achievement_counts" );
|
||||
|
||||
m_flAreaCaptureScoreAccumulator = 0.0f;
|
||||
}
|
||||
|
||||
CBaseMultiplayerPlayer::~CBaseMultiplayerPlayer()
|
||||
{
|
||||
m_pAchievementKV->deleteThis();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CAI_Expresser *CBaseMultiplayerPlayer::CreateExpresser( void )
|
||||
{
|
||||
m_pExpresser = new CMultiplayer_Expresser(this);
|
||||
if ( !m_pExpresser)
|
||||
return NULL;
|
||||
|
||||
m_pExpresser->Connect(this);
|
||||
return m_pExpresser;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseMultiplayerPlayer::PostConstructor( const char *szClassname )
|
||||
{
|
||||
BaseClass::PostConstructor( szClassname );
|
||||
CreateExpresser();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseMultiplayerPlayer::ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet )
|
||||
{
|
||||
BaseClass::ModifyOrAppendCriteria( criteriaSet );
|
||||
|
||||
ModifyOrAppendPlayerCriteria( criteriaSet );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseMultiplayerPlayer::SpeakIfAllowed( AIConcept_t concept, const char *modifiers, char *pszOutResponseChosen, size_t bufsize, IRecipientFilter *filter )
|
||||
{
|
||||
if ( !IsAlive() )
|
||||
return false;
|
||||
|
||||
//if ( IsAllowedToSpeak( concept, bRespondingToPlayer ) )
|
||||
return Speak( concept, modifiers, pszOutResponseChosen, bufsize, filter );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
IResponseSystem *CBaseMultiplayerPlayer::GetResponseSystem()
|
||||
{
|
||||
return BaseClass::GetResponseSystem();
|
||||
// NOTE: This is where you would hook your custom responses.
|
||||
// return <*>GameRules()->m_ResponseRules[iIndex].m_ResponseSystems[m_iCurrentConcept];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Doesn't actually speak the concept. Just finds a response in the system. You then have to play it yourself.
|
||||
//-----------------------------------------------------------------------------
|
||||
AI_Response *CBaseMultiplayerPlayer::SpeakConcept( int iConcept )
|
||||
{
|
||||
m_iCurrentConcept = iConcept;
|
||||
return SpeakFindResponse( g_pszMPConcepts[iConcept] );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseMultiplayerPlayer::SpeakConceptIfAllowed( int iConcept, const char *modifiers, char *pszOutResponseChosen, size_t bufsize, IRecipientFilter *filter )
|
||||
{
|
||||
// Save the current concept.
|
||||
m_iCurrentConcept = iConcept;
|
||||
return SpeakIfAllowed( g_pszMPConcepts[iConcept], modifiers, pszOutResponseChosen, bufsize, filter );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseMultiplayerPlayer::CanHearAndReadChatFrom( CBasePlayer *pPlayer )
|
||||
{
|
||||
// can always hear the console unless we're ignoring all chat
|
||||
if ( !pPlayer )
|
||||
return m_iIgnoreGlobalChat != CHAT_IGNORE_ALL;
|
||||
|
||||
// check if we're ignoring all chat
|
||||
if ( m_iIgnoreGlobalChat == CHAT_IGNORE_ALL )
|
||||
return false;
|
||||
|
||||
// check if we're ignoring all but teammates
|
||||
if ( m_iIgnoreGlobalChat == CHAT_IGNORE_TEAM && g_pGameRules->PlayerRelationship( this, pPlayer ) != GR_TEAMMATE )
|
||||
return false;
|
||||
|
||||
// can't hear dead players if we're alive
|
||||
if ( pPlayer->m_lifeState != LIFE_ALIVE && m_lifeState == LIFE_ALIVE )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseMultiplayerPlayer::ShouldRunRateLimitedCommand( const CCommand &args )
|
||||
{
|
||||
return ShouldRunRateLimitedCommand( args[0] );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseMultiplayerPlayer::ShouldRunRateLimitedCommand( const char *pszCommand )
|
||||
{
|
||||
const char *pcmd = pszCommand;
|
||||
|
||||
int i = m_RateLimitLastCommandTimes.Find( pcmd );
|
||||
if ( i == m_RateLimitLastCommandTimes.InvalidIndex() )
|
||||
{
|
||||
m_RateLimitLastCommandTimes.Insert( pcmd, gpGlobals->curtime );
|
||||
return true;
|
||||
}
|
||||
else if ( (gpGlobals->curtime - m_RateLimitLastCommandTimes[i]) < COMMAND_MAX_RATE )
|
||||
{
|
||||
// Too fast.
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RateLimitLastCommandTimes[i] = gpGlobals->curtime;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseMultiplayerPlayer::ClientCommand( const CCommand &args )
|
||||
{
|
||||
const char *pcmd = args[0];
|
||||
|
||||
if ( FStrEq( pcmd, "ignoremsg" ) )
|
||||
{
|
||||
if ( ShouldRunRateLimitedCommand( args ) )
|
||||
{
|
||||
m_iIgnoreGlobalChat = (m_iIgnoreGlobalChat + 1) % 3;
|
||||
switch( m_iIgnoreGlobalChat )
|
||||
{
|
||||
case CHAT_IGNORE_NONE:
|
||||
ClientPrint( this, HUD_PRINTTALK, "#Accept_All_Messages" );
|
||||
break;
|
||||
case CHAT_IGNORE_ALL:
|
||||
ClientPrint( this, HUD_PRINTTALK, "#Ignore_Broadcast_Messages" );
|
||||
break;
|
||||
case CHAT_IGNORE_TEAM:
|
||||
ClientPrint( this, HUD_PRINTTALK, "#Ignore_Broadcast_Team_Messages" );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return BaseClass::ClientCommand( args );
|
||||
}
|
||||
|
||||
bool CBaseMultiplayerPlayer::ShouldShowVoiceSubtitleToEnemy( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// calculate a score for this player. higher is more likely to be switched
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseMultiplayerPlayer::CalculateTeamBalanceScore( void )
|
||||
{
|
||||
// base score is 0 - ( seconds on server )
|
||||
float flTimeConnected = gpGlobals->curtime - m_flConnectionTime;
|
||||
int iScore = 0 - (int)flTimeConnected;
|
||||
|
||||
// if we were switched recently, score us way down
|
||||
float flLastSwitchedTime = GetLastForcedChangeTeamTime();
|
||||
if ( flLastSwitchedTime > 0 && ( gpGlobals->curtime - flLastSwitchedTime ) < 300 )
|
||||
{
|
||||
iScore -= 10000;
|
||||
}
|
||||
return iScore;
|
||||
}
|
||||
|
||||
void CBaseMultiplayerPlayer::Spawn( void )
|
||||
{
|
||||
ResetPerLifeCounters();
|
||||
|
||||
StopScoringEscortPoints();
|
||||
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
void CBaseMultiplayerPlayer::AwardAchievement( int iAchievement, int iCount )
|
||||
{
|
||||
Assert( iAchievement >= 0 && iAchievement < 0xFFFF ); // must fit in short
|
||||
|
||||
CSingleUserRecipientFilter filter( this );
|
||||
|
||||
UserMessageBegin( filter, "AchievementEvent" );
|
||||
WRITE_SHORT( iAchievement );
|
||||
WRITE_SHORT( iCount );
|
||||
MessageEnd();
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
#include "utlbuffer.h"
|
||||
|
||||
void DumpAchievementCounters( const CCommand &args )
|
||||
{
|
||||
int iPlayerIndex = 1;
|
||||
|
||||
if ( args.ArgC() >= 2 )
|
||||
{
|
||||
iPlayerIndex = atoi( args[1] );
|
||||
}
|
||||
|
||||
CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( iPlayerIndex ) );
|
||||
if ( pPlayer && pPlayer->GetPerLifeCounterKeys() )
|
||||
{
|
||||
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
|
||||
pPlayer->GetPerLifeCounterKeys()->RecursiveSaveToFile( buf, 0 );
|
||||
|
||||
char szBuf[1024];
|
||||
|
||||
// probably not the best way to print out a CUtlBuffer
|
||||
int pos = 0;
|
||||
while ( buf.PeekStringLength() )
|
||||
{
|
||||
szBuf[pos] = buf.GetChar();
|
||||
pos++;
|
||||
}
|
||||
szBuf[pos] = '\0';
|
||||
|
||||
Msg( "%s\n", szBuf );
|
||||
}
|
||||
}
|
||||
ConCommand dump_achievement_counters( "dump_achievement_counters", DumpAchievementCounters, "Spew the per-life achievement counters for multiplayer players", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY );
|
||||
|
||||
#endif // _DEBUG
|
||||
|
||||
int CBaseMultiplayerPlayer::GetPerLifeCounterKV( const char *name )
|
||||
{
|
||||
return m_pAchievementKV->GetInt( name, 0 );
|
||||
}
|
||||
|
||||
void CBaseMultiplayerPlayer::SetPerLifeCounterKV( const char *name, int value )
|
||||
{
|
||||
m_pAchievementKV->SetInt( name, value );
|
||||
}
|
||||
|
||||
void CBaseMultiplayerPlayer::ResetPerLifeCounters( void )
|
||||
{
|
||||
m_pAchievementKV->Clear();
|
||||
}
|
||||
|
||||
|
||||
ConVar tf_escort_score_rate( "tf_escort_score_rate", "1", FCVAR_CHEAT, "Score for escorting the train, in points per second" );
|
||||
|
||||
#define ESCORT_SCORE_CONTEXT "AreaScoreContext"
|
||||
#define ESCORT_SCORE_INTERVAL 0.1
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: think to accumulate and award points for escorting the train
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseMultiplayerPlayer::EscortScoringThink( void )
|
||||
{
|
||||
m_flAreaCaptureScoreAccumulator += ESCORT_SCORE_INTERVAL;
|
||||
|
||||
if ( m_flCapPointScoreRate > 0 )
|
||||
{
|
||||
float flTimeForOnePoint = 1.0f / m_flCapPointScoreRate;
|
||||
|
||||
int iPoints = 0;
|
||||
|
||||
while ( m_flAreaCaptureScoreAccumulator >= flTimeForOnePoint )
|
||||
{
|
||||
m_flAreaCaptureScoreAccumulator -= flTimeForOnePoint;
|
||||
iPoints++;
|
||||
}
|
||||
|
||||
if ( iPoints > 0 )
|
||||
{
|
||||
IGameEvent *event = gameeventmanager->CreateEvent( "player_escort_score" );
|
||||
if ( event )
|
||||
{
|
||||
event->SetInt( "player", entindex() );
|
||||
event->SetInt( "points", iPoints );
|
||||
gameeventmanager->FireEvent( event, true /* only to server */ );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetContextThink( &CBaseMultiplayerPlayer::EscortScoringThink, gpGlobals->curtime + ESCORT_SCORE_INTERVAL, ESCORT_SCORE_CONTEXT );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: We're escorting the train, start giving points
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseMultiplayerPlayer::StartScoringEscortPoints( float flRate )
|
||||
{
|
||||
Assert( flRate > 0.0f );
|
||||
m_flCapPointScoreRate = flRate;
|
||||
SetContextThink( &CBaseMultiplayerPlayer::EscortScoringThink, gpGlobals->curtime + ESCORT_SCORE_INTERVAL, ESCORT_SCORE_CONTEXT );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Stopped escorting the train
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseMultiplayerPlayer::StopScoringEscortPoints( void )
|
||||
{
|
||||
SetContextThink( NULL, 0, ESCORT_SCORE_CONTEXT );
|
||||
}
|
||||
|
||||
127
sp/src/game/server/basemultiplayerplayer.h
Normal file
127
sp/src/game/server/basemultiplayerplayer.h
Normal file
@@ -0,0 +1,127 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef BASEMULTIPLAYERPLAYER_H
|
||||
#define BASEMULTIPLAYERPLAYER_H
|
||||
#pragma once
|
||||
|
||||
#include "player.h"
|
||||
#include "ai_speech.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBaseMultiplayerPlayer : public CAI_ExpresserHost<CBasePlayer>
|
||||
{
|
||||
|
||||
DECLARE_CLASS( CBaseMultiplayerPlayer, CAI_ExpresserHost<CBasePlayer> );
|
||||
|
||||
public:
|
||||
|
||||
CBaseMultiplayerPlayer();
|
||||
~CBaseMultiplayerPlayer();
|
||||
|
||||
virtual void Spawn( void );
|
||||
|
||||
virtual void PostConstructor( const char *szClassname );
|
||||
virtual void ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
|
||||
|
||||
virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL );
|
||||
virtual IResponseSystem *GetResponseSystem();
|
||||
AI_Response *SpeakConcept( int iConcept );
|
||||
virtual bool SpeakConceptIfAllowed( int iConcept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL );
|
||||
|
||||
virtual bool CanHearAndReadChatFrom( CBasePlayer *pPlayer );
|
||||
virtual bool CanSpeak( void ) { return true; }
|
||||
virtual bool CanBeAutobalanced() { return true; }
|
||||
|
||||
virtual void Precache( void )
|
||||
{
|
||||
PrecacheParticleSystem( "achieved" );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
virtual bool ClientCommand( const CCommand &args );
|
||||
|
||||
virtual bool CanSpeakVoiceCommand( void ) { return true; }
|
||||
virtual bool ShouldShowVoiceSubtitleToEnemy( void );
|
||||
virtual void NoteSpokeVoiceCommand( const char *pszScenePlayed ) {}
|
||||
|
||||
virtual void OnAchievementEarned( int iAchievement ) {}
|
||||
|
||||
enum
|
||||
{
|
||||
CHAT_IGNORE_NONE = 0,
|
||||
CHAT_IGNORE_ALL,
|
||||
CHAT_IGNORE_TEAM,
|
||||
};
|
||||
|
||||
int m_iIgnoreGlobalChat;
|
||||
|
||||
//---------------------------------
|
||||
// Speech support
|
||||
virtual CAI_Expresser *GetExpresser() { return m_pExpresser; }
|
||||
virtual CMultiplayer_Expresser *GetMultiplayerExpresser() { return m_pExpresser; }
|
||||
|
||||
void SetLastForcedChangeTeamTimeToNow( void ) { m_flLastForcedChangeTeamTime = gpGlobals->curtime; }
|
||||
float GetLastForcedChangeTeamTime( void ) { return m_flLastForcedChangeTeamTime; }
|
||||
|
||||
void SetTeamBalanceScore( int iScore ) { m_iBalanceScore = iScore; }
|
||||
int GetTeamBalanceScore( void ) { return m_iBalanceScore; }
|
||||
|
||||
virtual int CalculateTeamBalanceScore( void );
|
||||
|
||||
void AwardAchievement( int iAchievement, int iCount = 1 );
|
||||
int GetPerLifeCounterKV( const char *name );
|
||||
void SetPerLifeCounterKV( const char *name, int value );
|
||||
void ResetPerLifeCounters( void );
|
||||
|
||||
KeyValues *GetPerLifeCounterKeys( void ) { return m_pAchievementKV; }
|
||||
|
||||
void EscortScoringThink( void );
|
||||
void StartScoringEscortPoints( float flRate );
|
||||
void StopScoringEscortPoints( void );
|
||||
float m_flAreaCaptureScoreAccumulator;
|
||||
float m_flCapPointScoreRate;
|
||||
|
||||
float GetConnectionTime( void ) { return m_flConnectionTime; }
|
||||
|
||||
// Command rate limiting.
|
||||
bool ShouldRunRateLimitedCommand( const CCommand &args );
|
||||
bool ShouldRunRateLimitedCommand( const char *pszCommand );
|
||||
|
||||
protected:
|
||||
virtual CAI_Expresser *CreateExpresser( void );
|
||||
|
||||
int m_iCurrentConcept;
|
||||
private:
|
||||
//---------------------------------
|
||||
CMultiplayer_Expresser *m_pExpresser;
|
||||
|
||||
float m_flConnectionTime;
|
||||
float m_flLastForcedChangeTeamTime;
|
||||
|
||||
int m_iBalanceScore; // a score used to determine which players are switched to balance the teams
|
||||
|
||||
KeyValues *m_pAchievementKV;
|
||||
|
||||
// This lets us rate limit the commands the players can execute so they don't overflow things like reliable buffers.
|
||||
CUtlDict<float,int> m_RateLimitLastCommandTimes;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inline methods
|
||||
//-----------------------------------------------------------------------------
|
||||
inline CBaseMultiplayerPlayer *ToBaseMultiplayerPlayer( CBaseEntity *pEntity )
|
||||
{
|
||||
if ( !pEntity || !pEntity->IsPlayer() )
|
||||
return NULL;
|
||||
#if _DEBUG
|
||||
return dynamic_cast<CBaseMultiplayerPlayer *>( pEntity );
|
||||
#else
|
||||
return static_cast<CBaseMultiplayerPlayer *>( pEntity );
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // BASEMULTIPLAYERPLAYER_H
|
||||
126
sp/src/game/server/basetempentity.cpp
Normal file
126
sp/src/game/server/basetempentity.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $Log: $
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "basetempentity.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST_NOBASE(CBaseTempEntity, DT_BaseTempEntity)
|
||||
END_SEND_TABLE()
|
||||
|
||||
|
||||
|
||||
|
||||
// Global list of temp entity event classes
|
||||
CBaseTempEntity *CBaseTempEntity::s_pTempEntities = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns head of list
|
||||
// Output : CBaseTempEntity * -- head of list
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseTempEntity *CBaseTempEntity::GetList( void )
|
||||
{
|
||||
return s_pTempEntities;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Creates temp entity, sets name, adds to global list
|
||||
// Input : *name -
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseTempEntity::CBaseTempEntity( const char *name )
|
||||
{
|
||||
m_pszName = name;
|
||||
Assert( m_pszName );
|
||||
|
||||
// Add to list
|
||||
m_pNext = s_pTempEntities;
|
||||
s_pTempEntities = this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseTempEntity::~CBaseTempEntity( void )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Get the name of this temp entity
|
||||
// Output : const char *
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CBaseTempEntity::GetName( void )
|
||||
{
|
||||
return m_pszName ? m_pszName : "Unnamed";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Get next temp ent in chain
|
||||
// Output : CBaseTempEntity *
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseTempEntity *CBaseTempEntity::GetNext( void )
|
||||
{
|
||||
return m_pNext;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseTempEntity::Precache( void )
|
||||
{
|
||||
// Nothing...
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Default test implementation. Should only be called by derived classes
|
||||
// Input : *current_origin -
|
||||
// *current_angles -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseTempEntity::Test( const Vector& current_origin, const QAngle& current_angles )
|
||||
{
|
||||
Vector origin, forward;
|
||||
|
||||
Msg( "%s\n", m_pszName );
|
||||
AngleVectors( current_angles, &forward );
|
||||
|
||||
VectorMA( current_origin, 20, forward, origin );
|
||||
|
||||
CBroadcastRecipientFilter filter;
|
||||
|
||||
Create( filter, 0.0 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called at startup to allow temp entities to precache any models/sounds that they need
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseTempEntity::PrecacheTempEnts( void )
|
||||
{
|
||||
CBaseTempEntity *te = GetList();
|
||||
while ( te )
|
||||
{
|
||||
te->Precache();
|
||||
te = te->GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBaseTempEntity::Create( IRecipientFilter& filter, float delay )
|
||||
{
|
||||
// temp entities can't be reliable or part of the signon message, use real entities instead
|
||||
Assert( !filter.IsReliable() && !filter.IsInitMessage() );
|
||||
Assert( delay >= -1 && delay <= 1); // 1 second max delay
|
||||
|
||||
engine->PlaybackTempEntity( filter, delay,
|
||||
(void *)this, GetServerClass()->m_pTable, GetServerClass()->m_ClassID );
|
||||
}
|
||||
65
sp/src/game/server/basetempentity.h
Normal file
65
sp/src/game/server/basetempentity.h
Normal file
@@ -0,0 +1,65 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $Log: $
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#if !defined( BASETEMPENTITY_H )
|
||||
#define BASETEMPENTITY_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "edict.h"
|
||||
|
||||
// This is the base class for TEMP ENTITIES that use the
|
||||
// event system to propagate
|
||||
class CBaseTempEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS_NOBASE( CBaseTempEntity );
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
CBaseTempEntity( const char *name );
|
||||
virtual ~CBaseTempEntity( void );
|
||||
|
||||
const char *GetName( void );
|
||||
|
||||
// Force all derived classes to implement a test
|
||||
virtual void Test( const Vector& current_origin, const QAngle& current_angles );
|
||||
|
||||
virtual void Create( IRecipientFilter& filter, float delay = 0.0 );
|
||||
|
||||
virtual void Precache( void );
|
||||
|
||||
CBaseTempEntity *GetNext( void );
|
||||
|
||||
// Get list of tempentities
|
||||
static CBaseTempEntity *GetList( void );
|
||||
|
||||
// Called at startup to allow temp entities to precache any models/sounds that they need
|
||||
static void PrecacheTempEnts( void );
|
||||
|
||||
void NetworkStateChanged() {} // TE's are sent out right away so we don't track whether state changes or not,
|
||||
// but we want to allow CNetworkVars.
|
||||
void NetworkStateChanged( void *pVar ) {}
|
||||
|
||||
private:
|
||||
// Descriptive name, for when running tests
|
||||
const char *m_pszName;
|
||||
|
||||
// Next in chain
|
||||
CBaseTempEntity *m_pNext;
|
||||
|
||||
// ConVars add themselves to this list for the executable. Then ConVarMgr::Init() runs through
|
||||
// all the console variables and registers them.
|
||||
static CBaseTempEntity *s_pTempEntities;
|
||||
};
|
||||
|
||||
#endif // BASETEMPENTITY_H
|
||||
69
sp/src/game/server/basetoggle.h
Normal file
69
sp/src/game/server/basetoggle.h
Normal file
@@ -0,0 +1,69 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: For the slow removing of the CBaseToggle entity
|
||||
// only old entities that need it for backwards-compatibility should
|
||||
// include this file
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef BASETOGGLE_H
|
||||
#define BASETOGGLE_H
|
||||
#pragma once
|
||||
|
||||
#include "baseentity.h"
|
||||
|
||||
|
||||
class CBaseToggle : public CBaseEntity
|
||||
{
|
||||
DECLARE_CLASS( CBaseToggle, CBaseEntity );
|
||||
public:
|
||||
CBaseToggle();
|
||||
|
||||
virtual bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
virtual bool KeyValue( const char *szKeyName, Vector vec ) { return BaseClass::KeyValue( szKeyName, vec ); };
|
||||
virtual bool KeyValue( const char *szKeyName, float flValue ) { return BaseClass::KeyValue( szKeyName, flValue ); };
|
||||
|
||||
TOGGLE_STATE m_toggle_state;
|
||||
float m_flMoveDistance;// how far a door should slide or rotate
|
||||
float m_flWait;
|
||||
float m_flLip;
|
||||
|
||||
Vector m_vecPosition1;
|
||||
Vector m_vecPosition2;
|
||||
|
||||
QAngle m_vecMoveAng;
|
||||
QAngle m_vecAngle1;
|
||||
QAngle m_vecAngle2;
|
||||
|
||||
float m_flHeight;
|
||||
EHANDLE m_hActivator;
|
||||
Vector m_vecFinalDest;
|
||||
QAngle m_vecFinalAngle;
|
||||
|
||||
int m_movementType;
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
virtual float GetDelay( void ) { return m_flWait; }
|
||||
|
||||
// common member functions
|
||||
void LinearMove( const Vector &vecDest, float flSpeed );
|
||||
void LinearMoveDone( void );
|
||||
void AngularMove( const QAngle &vecDestAngle, float flSpeed );
|
||||
void AngularMoveDone( void );
|
||||
bool IsLockedByMaster( void );
|
||||
virtual void MoveDone( void );
|
||||
|
||||
static float AxisValue( int flags, const QAngle &angles );
|
||||
void AxisDir( void );
|
||||
static float AxisDelta( int flags, const QAngle &angle1, const QAngle &angle2 );
|
||||
|
||||
string_t m_sMaster; // If this button has a master switch, this is the targetname.
|
||||
// A master switch must be of the multisource type. If all
|
||||
// of the switches in the multisource have been triggered, then
|
||||
// the button will be allowed to operate. Otherwise, it will be
|
||||
// deactivated.
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // BASETOGGLE_H
|
||||
116
sp/src/game/server/baseviewmodel.cpp
Normal file
116
sp/src/game/server/baseviewmodel.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "animation.h"
|
||||
#include "baseviewmodel.h"
|
||||
#include "player.h"
|
||||
#include <KeyValues.h>
|
||||
#include "studio.h"
|
||||
#include "vguiscreen.h"
|
||||
#include "saverestore_utlvector.h"
|
||||
#include "hltvdirector.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
void SendProxy_AnimTime( const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID );
|
||||
void SendProxy_SequenceChanged( const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Save Data for Base Weapon object
|
||||
//-----------------------------------------------------------------------------//
|
||||
BEGIN_DATADESC( CBaseViewModel )
|
||||
|
||||
DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ),
|
||||
|
||||
// Client only
|
||||
// DEFINE_FIELD( m_LagAnglesHistory, CInterpolatedVar < QAngle > ),
|
||||
// DEFINE_FIELD( m_vLagAngles, FIELD_VECTOR ),
|
||||
|
||||
DEFINE_FIELD( m_nViewModelIndex, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_flTimeWeaponIdle, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_nAnimationParity, FIELD_INTEGER ),
|
||||
|
||||
// Client only
|
||||
// DEFINE_FIELD( m_nOldAnimationParity, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_FIELD( m_vecLastFacing, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_hWeapon, FIELD_EHANDLE ),
|
||||
DEFINE_UTLVECTOR( m_hScreens, FIELD_EHANDLE ),
|
||||
|
||||
// Read from weapons file
|
||||
// DEFINE_FIELD( m_sVMName, FIELD_STRING ),
|
||||
// DEFINE_FIELD( m_sAnimationPrefix, FIELD_STRING ),
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// Don't save these, init to 0 and regenerate
|
||||
// DEFINE_FIELD( m_Activity, FIELD_INTEGER ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
int CBaseViewModel::UpdateTransmitState()
|
||||
{
|
||||
if ( IsEffectActive( EF_NODRAW ) )
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_DONTSEND );
|
||||
}
|
||||
|
||||
return SetTransmitState( FL_EDICT_FULLCHECK );
|
||||
}
|
||||
|
||||
int CBaseViewModel::ShouldTransmit( const CCheckTransmitInfo *pInfo )
|
||||
{
|
||||
// check if receipient owns this weapon viewmodel
|
||||
CBasePlayer *pOwner = ToBasePlayer( m_hOwner );
|
||||
|
||||
if ( pOwner && pOwner->edict() == pInfo->m_pClientEnt )
|
||||
{
|
||||
return FL_EDICT_ALWAYS;
|
||||
}
|
||||
|
||||
// check if recipient spectates the own of this viewmodel
|
||||
CBaseEntity *pRecipientEntity = CBaseEntity::Instance( pInfo->m_pClientEnt );
|
||||
|
||||
if ( pRecipientEntity->IsPlayer() )
|
||||
{
|
||||
CBasePlayer *pPlayer = static_cast<CBasePlayer*>( pRecipientEntity );
|
||||
#ifndef _XBOX
|
||||
if ( pPlayer->IsHLTV() || pPlayer->IsReplay() )
|
||||
{
|
||||
// if this is the HLTV client, transmit all viewmodels in our PVS
|
||||
return FL_EDICT_PVSCHECK;
|
||||
}
|
||||
#endif
|
||||
if ( (pPlayer->GetObserverMode() == OBS_MODE_IN_EYE) && (pPlayer->GetObserverTarget() == pOwner) )
|
||||
{
|
||||
return FL_EDICT_ALWAYS;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't send to anyone else except the local player or his spectators
|
||||
return FL_EDICT_DONTSEND;
|
||||
}
|
||||
|
||||
void CBaseViewModel::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways )
|
||||
{
|
||||
// Are we already marked for transmission?
|
||||
if ( pInfo->m_pTransmitEdict->Get( entindex() ) )
|
||||
return;
|
||||
|
||||
BaseClass::SetTransmit( pInfo, bAlways );
|
||||
|
||||
// Force our screens to be sent too.
|
||||
for ( int i=0; i < m_hScreens.Count(); i++ )
|
||||
{
|
||||
CVGuiScreen *pScreen = m_hScreens[i].Get();
|
||||
if ( pScreen )
|
||||
pScreen->SetTransmit( pInfo, bAlways );
|
||||
}
|
||||
}
|
||||
17
sp/src/game/server/baseviewmodel.h
Normal file
17
sp/src/game/server/baseviewmodel.h
Normal file
@@ -0,0 +1,17 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Server side view model object
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#if !defined( BASEVIEWMODEL_H )
|
||||
#define BASEVIEWMODEL_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "baseviewmodel_shared.h"
|
||||
|
||||
#endif // BASEVIEWMODEL_H
|
||||
27
sp/src/game/server/bitstring.cpp
Normal file
27
sp/src/game/server/bitstring.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Arbitrary length bit string
|
||||
// ** NOTE: This class does NOT override the bitwise operators
|
||||
// as doing so would require overriding the operators
|
||||
// to allocate memory for the returned bitstring. This method
|
||||
// would be prone to memory leaks as the calling party
|
||||
// would have to remember to delete the memory. Funtions
|
||||
// are used instead to require the calling party to allocate
|
||||
// and destroy their own memory
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "bitstring.h"
|
||||
#include "utlbuffer.h"
|
||||
#include "tier0/dbg.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
28
sp/src/game/server/bitstring.h
Normal file
28
sp/src/game/server/bitstring.h
Normal file
@@ -0,0 +1,28 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Arbitrary length bit string
|
||||
// ** NOTE: This class does NOT override the bitwise operators
|
||||
// as doing so would require overriding the operators
|
||||
// to allocate memory for the returned bitstring. This method
|
||||
// would be prone to memory leaks as the calling party
|
||||
// would have to remember to delete the memory. Funtions
|
||||
// are used instead to require the calling party to allocate
|
||||
// and destroy their own memory
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $Log: $
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef BITSTRING_H
|
||||
#define BITSTRING_H
|
||||
#pragma once
|
||||
|
||||
#include "bitvec.h"
|
||||
|
||||
|
||||
#endif // BITSTRING_H
|
||||
1522
sp/src/game/server/bmodels.cpp
Normal file
1522
sp/src/game/server/bmodels.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1594
sp/src/game/server/buttons.cpp
Normal file
1594
sp/src/game/server/buttons.cpp
Normal file
File diff suppressed because it is too large
Load Diff
172
sp/src/game/server/buttons.h
Normal file
172
sp/src/game/server/buttons.h
Normal file
@@ -0,0 +1,172 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef BUTTONS_H
|
||||
#define BUTTONS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
class CBaseButton : public CBaseToggle
|
||||
{
|
||||
public:
|
||||
|
||||
DECLARE_CLASS( CBaseButton, CBaseToggle );
|
||||
|
||||
void Spawn( void );
|
||||
virtual void Precache( void );
|
||||
bool CreateVPhysics();
|
||||
void RotSpawn( void );
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
int DrawDebugTextOverlays();
|
||||
|
||||
protected:
|
||||
|
||||
void ButtonActivate( );
|
||||
void SparkSoundCache( void );
|
||||
|
||||
void ButtonTouch( ::CBaseEntity *pOther );
|
||||
void ButtonSpark ( void );
|
||||
void TriggerAndWait( void );
|
||||
void ButtonReturn( void );
|
||||
void ButtonBackHome( void );
|
||||
void ButtonUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
|
||||
bool OnUseLocked( CBaseEntity *pActivator );
|
||||
|
||||
virtual void Lock();
|
||||
virtual void Unlock();
|
||||
|
||||
// Input handlers
|
||||
void InputLock( inputdata_t &inputdata );
|
||||
void InputUnlock( inputdata_t &inputdata );
|
||||
void InputPress( inputdata_t &inputdata );
|
||||
void InputPressIn( inputdata_t &inputdata );
|
||||
void InputPressOut( inputdata_t &inputdata );
|
||||
|
||||
virtual int OnTakeDamage( const CTakeDamageInfo &info );
|
||||
|
||||
enum BUTTON_CODE { BUTTON_NOTHING, BUTTON_ACTIVATE, BUTTON_RETURN, BUTTON_PRESS };
|
||||
|
||||
BUTTON_CODE ButtonResponseToTouch( void );
|
||||
void Press( CBaseEntity *pActivator, BUTTON_CODE eCode );
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
virtual int ObjectCaps(void);
|
||||
|
||||
Vector m_vecMoveDir;
|
||||
|
||||
bool m_fStayPushed; // button stays pushed in until touched again?
|
||||
bool m_fRotating; // a rotating button? default is a sliding button.
|
||||
|
||||
locksound_t m_ls; // door lock sounds
|
||||
|
||||
byte m_bLockedSound; // ordinals from entity selection
|
||||
byte m_bLockedSentence;
|
||||
byte m_bUnlockedSound;
|
||||
byte m_bUnlockedSentence;
|
||||
bool m_bLocked;
|
||||
int m_sounds;
|
||||
float m_flUseLockedTime; // Controls how often we fire the OnUseLocked output.
|
||||
|
||||
bool m_bSolidBsp;
|
||||
|
||||
string_t m_sNoise; // The actual WAV file name of the sound.
|
||||
|
||||
COutputEvent m_OnDamaged;
|
||||
COutputEvent m_OnPressed;
|
||||
COutputEvent m_OnUseLocked;
|
||||
COutputEvent m_OnIn;
|
||||
COutputEvent m_OnOut;
|
||||
|
||||
int m_nState;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Rotating button (aka "lever")
|
||||
//
|
||||
class CRotButton : public CBaseButton
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CRotButton, CBaseButton );
|
||||
|
||||
void Spawn( void );
|
||||
bool CreateVPhysics( void );
|
||||
|
||||
};
|
||||
|
||||
|
||||
class CMomentaryRotButton : public CRotButton
|
||||
{
|
||||
DECLARE_CLASS( CMomentaryRotButton, CRotButton );
|
||||
|
||||
public:
|
||||
void Spawn ( void );
|
||||
bool CreateVPhysics( void );
|
||||
virtual int ObjectCaps( void );
|
||||
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
void UseMoveDone( void );
|
||||
void ReturnMoveDone( void );
|
||||
void OutputMovementComplete(void);
|
||||
void SetPositionMoveDone(void);
|
||||
void UpdateSelf( float value, bool bPlaySound );
|
||||
|
||||
void PlaySound( void );
|
||||
void UpdateTarget( float value, CBaseEntity *pActivator );
|
||||
|
||||
int DrawDebugTextOverlays(void);
|
||||
|
||||
static CMomentaryRotButton *Instance( edict_t *pent ) { return (CMomentaryRotButton *)GetContainingEntity(pent); }
|
||||
|
||||
float GetPos(const QAngle &vecAngles);
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
virtual void Lock();
|
||||
virtual void Unlock();
|
||||
|
||||
// Input handlers
|
||||
void InputSetPosition( inputdata_t &inputdata );
|
||||
void InputSetPositionImmediately( inputdata_t &inputdata );
|
||||
void InputDisableUpdateTarget( inputdata_t &inputdata );
|
||||
void InputEnableUpdateTarget( inputdata_t &inputdata );
|
||||
|
||||
void InputEnable( inputdata_t &inputdata );
|
||||
void InputDisable( inputdata_t &inputdata );
|
||||
|
||||
virtual void Enable( void );
|
||||
virtual void Disable( void );
|
||||
|
||||
bool m_bDisabled;
|
||||
|
||||
COutputFloat m_Position;
|
||||
COutputEvent m_OnUnpressed;
|
||||
COutputEvent m_OnFullyOpen;
|
||||
COutputEvent m_OnFullyClosed;
|
||||
COutputEvent m_OnReachedPosition;
|
||||
|
||||
int m_lastUsed;
|
||||
QAngle m_start;
|
||||
QAngle m_end;
|
||||
float m_IdealYaw;
|
||||
string_t m_sNoise;
|
||||
|
||||
bool m_bUpdateTarget; // Used when jiggling so that we don't jiggle the target (door, etc)
|
||||
|
||||
int m_direction;
|
||||
float m_returnSpeed;
|
||||
float m_flStartPosition;
|
||||
|
||||
protected:
|
||||
|
||||
void UpdateThink( void );
|
||||
};
|
||||
|
||||
|
||||
#endif // BUTTONS_H
|
||||
2199
sp/src/game/server/cbase.cpp
Normal file
2199
sp/src/game/server/cbase.cpp
Normal file
File diff suppressed because it is too large
Load Diff
157
sp/src/game/server/cbase.h
Normal file
157
sp/src/game/server/cbase.h
Normal file
@@ -0,0 +1,157 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef CBASE_H
|
||||
#define CBASE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
// Silence certain warnings
|
||||
#pragma warning(disable : 4244) // int or float down-conversion
|
||||
#pragma warning(disable : 4305) // int or float data truncation
|
||||
#pragma warning(disable : 4201) // nameless struct/union
|
||||
#pragma warning(disable : 4511) // copy constructor could not be generated
|
||||
#pragma warning(disable : 4675) // resolved overload was found by argument dependent lookup
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG 1
|
||||
#endif
|
||||
|
||||
// Misc C-runtime library headers
|
||||
#include <math.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// tier 0
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "basetypes.h"
|
||||
|
||||
// tier 1
|
||||
#include "tier1/strtools.h"
|
||||
#include "utlvector.h"
|
||||
#include "mathlib/vmatrix.h"
|
||||
|
||||
// tier 2
|
||||
#include "string_t.h"
|
||||
|
||||
// tier 3
|
||||
#include "vphysics_interface.h"
|
||||
|
||||
// Shared engine/DLL constants
|
||||
#include "const.h"
|
||||
#include "edict.h"
|
||||
|
||||
// Shared header describing protocol between engine and DLLs
|
||||
#include "eiface.h"
|
||||
#include "iserverentity.h"
|
||||
|
||||
#include "dt_send.h"
|
||||
|
||||
// Shared header between the client DLL and the game DLLs
|
||||
#include "shareddefs.h"
|
||||
#include "ehandle.h"
|
||||
|
||||
// app
|
||||
#if defined(_X360)
|
||||
#define DISABLE_DEBUG_HISTORY 1
|
||||
#endif
|
||||
|
||||
|
||||
#include "datamap.h"
|
||||
#include "util.h"
|
||||
#include "predictable_entity.h"
|
||||
#include "predictableid.h"
|
||||
#include "variant_t.h"
|
||||
#include "takedamageinfo.h"
|
||||
#include "utllinkedlist.h"
|
||||
#include "touchlink.h"
|
||||
#include "groundlink.h"
|
||||
#include "base_transmit_proxy.h"
|
||||
#include "soundflags.h"
|
||||
#include "networkvar.h"
|
||||
#include "baseentity_shared.h"
|
||||
#include "basetoggle.h"
|
||||
#include "igameevents.h"
|
||||
#ifdef MAPBASE
|
||||
#include "tier1/mapbase_con_groups.h"
|
||||
#endif
|
||||
|
||||
// saverestore.h declarations
|
||||
class ISave;
|
||||
class IRestore;
|
||||
|
||||
// maximum number of targets a single multi_manager entity may be assigned.
|
||||
#define MAX_MULTI_TARGETS 16
|
||||
|
||||
// NPCEvent.h declarations
|
||||
struct animevent_t;
|
||||
|
||||
struct studiohdr_t;
|
||||
class CStudioHdr;
|
||||
|
||||
extern void FireTargets( const char *targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
|
||||
// people gib if their health is <= this at the time of death
|
||||
#define GIB_HEALTH_VALUE -30
|
||||
|
||||
#define MAX_OLD_ENEMIES 4 // how many old enemies to remember
|
||||
|
||||
// used by suit voice to indicate damage sustained and repaired type to player
|
||||
|
||||
enum
|
||||
{
|
||||
itbd_Paralyze = 0,
|
||||
itbd_NerveGas,
|
||||
itbd_PoisonRecover,
|
||||
itbd_Radiation,
|
||||
itbd_DrownRecover,
|
||||
itbd_Acid,
|
||||
itbd_SlowBurn,
|
||||
itbd_SlowFreeze,
|
||||
|
||||
// Must be last!
|
||||
CDMG_TIMEBASED
|
||||
};
|
||||
|
||||
// when calling KILLED(), a value that governs gib behavior is expected to be
|
||||
// one of these three values
|
||||
#define GIB_NORMAL 0// gib if entity was overkilled
|
||||
#define GIB_NEVER 1// never gib, no matter how much death damage is done ( freezing, etc )
|
||||
#define GIB_ALWAYS 2// always gib
|
||||
|
||||
class CAI_BaseNPC;
|
||||
class CAI_ScriptedSequence;
|
||||
class CSound;
|
||||
|
||||
#ifdef _XBOX
|
||||
//#define FUNCTANK_AUTOUSE We haven't made the decision to use this yet (sjb)
|
||||
#else
|
||||
#undef FUNCTANK_AUTOUSE
|
||||
#endif//_XBOX
|
||||
|
||||
// This is a precompiled header. Include a bunch of common stuff.
|
||||
// This is kind of ugly in that it adds a bunch of dependency where it isn't needed.
|
||||
// But on balance, the compile time is much lower (even incrementally) once the precompiled
|
||||
// headers contain these headers.
|
||||
#include "precache_register.h"
|
||||
#include "baseanimating.h"
|
||||
#include "basecombatweapon.h"
|
||||
#include "basecombatcharacter.h"
|
||||
#include "gamerules.h"
|
||||
#include "entitylist.h"
|
||||
#include "basetempentity.h"
|
||||
#include "player.h"
|
||||
#include "te.h"
|
||||
#include "physics.h"
|
||||
#include "ndebugoverlay.h"
|
||||
#include "recipientfilter.h"
|
||||
|
||||
#endif // CBASE_H
|
||||
1575
sp/src/game/server/client.cpp
Normal file
1575
sp/src/game/server/client.cpp
Normal file
File diff suppressed because it is too large
Load Diff
32
sp/src/game/server/client.h
Normal file
32
sp/src/game/server/client.h
Normal file
@@ -0,0 +1,32 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#ifndef CLIENT_H
|
||||
#define CLIENT_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
class CCommand;
|
||||
class CUserCmd;
|
||||
class CBasePlayer;
|
||||
|
||||
|
||||
void ClientActive( edict_t *pEdict, bool bLoadGame );
|
||||
void ClientPutInServer( edict_t *pEdict, const char *playername );
|
||||
void ClientCommand( CBasePlayer *pSender, const CCommand &args );
|
||||
void ClientPrecache( void );
|
||||
// Game specific precaches
|
||||
void ClientGamePrecache( void );
|
||||
const char *GetGameDescription( void );
|
||||
void Host_Say( edict_t *pEdict, bool teamonly );
|
||||
|
||||
|
||||
|
||||
#endif // CLIENT_H
|
||||
314
sp/src/game/server/colorcorrection.cpp
Normal file
314
sp/src/game/server/colorcorrection.cpp
Normal file
@@ -0,0 +1,314 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Color correction entity.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define COLOR_CORRECTION_ENT_THINK_RATE TICK_INTERVAL
|
||||
|
||||
static const char *s_pFadeInContextThink = "ColorCorrectionFadeInThink";
|
||||
static const char *s_pFadeOutContextThink = "ColorCorrectionFadeOutThink";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FIXME: This really should inherit from something more lightweight
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Shadow control entity
|
||||
//------------------------------------------------------------------------------
|
||||
class CColorCorrection : public CBaseEntity
|
||||
{
|
||||
DECLARE_CLASS( CColorCorrection, CBaseEntity );
|
||||
public:
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
CColorCorrection();
|
||||
|
||||
void Spawn( void );
|
||||
int UpdateTransmitState();
|
||||
void Activate( void );
|
||||
|
||||
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
|
||||
// Inputs
|
||||
void InputEnable( inputdata_t &inputdata );
|
||||
void InputDisable( inputdata_t &inputdata );
|
||||
void InputSetFadeInDuration ( inputdata_t &inputdata );
|
||||
void InputSetFadeOutDuration ( inputdata_t &inputdata );
|
||||
|
||||
private:
|
||||
void FadeIn ( void );
|
||||
void FadeOut ( void );
|
||||
|
||||
void FadeInThink( void ); // Fades lookup weight from Cur->MaxWeight
|
||||
void FadeOutThink( void ); // Fades lookup weight from CurWeight->0.0
|
||||
|
||||
|
||||
|
||||
float m_flFadeInDuration; // Duration for a full 0->MaxWeight transition
|
||||
float m_flFadeOutDuration; // Duration for a full Max->0 transition
|
||||
float m_flStartFadeInWeight;
|
||||
float m_flStartFadeOutWeight;
|
||||
float m_flTimeStartFadeIn;
|
||||
float m_flTimeStartFadeOut;
|
||||
|
||||
float m_flMaxWeight;
|
||||
|
||||
bool m_bStartDisabled;
|
||||
CNetworkVar( bool, m_bEnabled );
|
||||
|
||||
CNetworkVar( float, m_MinFalloff );
|
||||
CNetworkVar( float, m_MaxFalloff );
|
||||
CNetworkVar( float, m_flCurWeight );
|
||||
CNetworkString( m_netlookupFilename, MAX_PATH );
|
||||
|
||||
string_t m_lookupFilename;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(color_correction, CColorCorrection);
|
||||
|
||||
BEGIN_DATADESC( CColorCorrection )
|
||||
|
||||
DEFINE_THINKFUNC( FadeInThink ),
|
||||
DEFINE_THINKFUNC( FadeOutThink ),
|
||||
|
||||
DEFINE_FIELD( m_flCurWeight, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flTimeStartFadeIn, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flTimeStartFadeOut, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flStartFadeInWeight, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flStartFadeOutWeight, FIELD_FLOAT ),
|
||||
|
||||
DEFINE_KEYFIELD( m_MinFalloff, FIELD_FLOAT, "minfalloff" ),
|
||||
DEFINE_KEYFIELD( m_MaxFalloff, FIELD_FLOAT, "maxfalloff" ),
|
||||
DEFINE_KEYFIELD( m_flMaxWeight, FIELD_FLOAT, "maxweight" ),
|
||||
DEFINE_KEYFIELD( m_flFadeInDuration, FIELD_FLOAT, "fadeInDuration" ),
|
||||
DEFINE_KEYFIELD( m_flFadeOutDuration, FIELD_FLOAT, "fadeOutDuration" ),
|
||||
DEFINE_KEYFIELD( m_lookupFilename, FIELD_STRING, "filename" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ),
|
||||
DEFINE_KEYFIELD( m_bStartDisabled, FIELD_BOOLEAN, "StartDisabled" ),
|
||||
// DEFINE_ARRAY( m_netlookupFilename, FIELD_CHARACTER, MAX_PATH ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFadeInDuration", InputSetFadeInDuration ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFadeOutDuration", InputSetFadeOutDuration ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID );
|
||||
IMPLEMENT_SERVERCLASS_ST_NOBASE(CColorCorrection, DT_ColorCorrection)
|
||||
SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_NOSCALE, 0.0f, HIGH_DEFAULT, SendProxy_Origin ),
|
||||
SendPropFloat( SENDINFO(m_MinFalloff) ),
|
||||
SendPropFloat( SENDINFO(m_MaxFalloff) ),
|
||||
SendPropFloat( SENDINFO(m_flCurWeight) ),
|
||||
SendPropString( SENDINFO(m_netlookupFilename) ),
|
||||
SendPropBool( SENDINFO(m_bEnabled) ),
|
||||
END_SEND_TABLE()
|
||||
|
||||
|
||||
CColorCorrection::CColorCorrection() : BaseClass()
|
||||
{
|
||||
m_bEnabled = true;
|
||||
m_MinFalloff = 0.0f;
|
||||
m_MaxFalloff = 1000.0f;
|
||||
m_flMaxWeight = 1.0f;
|
||||
m_flCurWeight.Set( 0.0f );
|
||||
m_flFadeInDuration = 0.0f;
|
||||
m_flFadeOutDuration = 0.0f;
|
||||
m_flStartFadeInWeight = 0.0f;
|
||||
m_flStartFadeOutWeight = 0.0f;
|
||||
m_flTimeStartFadeIn = 0.0f;
|
||||
m_flTimeStartFadeOut = 0.0f;
|
||||
m_netlookupFilename.GetForModify()[0] = 0;
|
||||
m_lookupFilename = NULL_STRING;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Send even though we don't have a model
|
||||
//------------------------------------------------------------------------------
|
||||
int CColorCorrection::UpdateTransmitState()
|
||||
{
|
||||
// ALWAYS transmit to all clients.
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
//------------------------------------------------------------------------------
|
||||
void CColorCorrection::Spawn( void )
|
||||
{
|
||||
AddEFlags( EFL_FORCE_CHECK_TRANSMIT | EFL_DIRTY_ABSTRANSFORM );
|
||||
Precache();
|
||||
SetSolid( SOLID_NONE );
|
||||
|
||||
// To fade in/out the weight.
|
||||
SetContextThink( &CColorCorrection::FadeInThink, TICK_NEVER_THINK, s_pFadeInContextThink );
|
||||
SetContextThink( &CColorCorrection::FadeOutThink, TICK_NEVER_THINK, s_pFadeOutContextThink );
|
||||
|
||||
if( m_bStartDisabled )
|
||||
{
|
||||
m_bEnabled = false;
|
||||
m_flCurWeight.Set ( 0.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bEnabled = true;
|
||||
m_flCurWeight.Set ( 1.0f );
|
||||
}
|
||||
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
void CColorCorrection::Activate( void )
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
Q_strncpy( m_netlookupFilename.GetForModify(), STRING( m_lookupFilename ), MAX_PATH );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets up internal vars needed for fade in lerping
|
||||
//-----------------------------------------------------------------------------
|
||||
void CColorCorrection::FadeIn ( void )
|
||||
{
|
||||
m_bEnabled = true;
|
||||
m_flTimeStartFadeIn = gpGlobals->curtime;
|
||||
m_flStartFadeInWeight = m_flCurWeight;
|
||||
SetNextThink ( gpGlobals->curtime + COLOR_CORRECTION_ENT_THINK_RATE, s_pFadeInContextThink );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets up internal vars needed for fade out lerping
|
||||
//-----------------------------------------------------------------------------
|
||||
void CColorCorrection::FadeOut ( void )
|
||||
{
|
||||
m_bEnabled = false;
|
||||
m_flTimeStartFadeOut = gpGlobals->curtime;
|
||||
m_flStartFadeOutWeight = m_flCurWeight;
|
||||
SetNextThink ( gpGlobals->curtime + COLOR_CORRECTION_ENT_THINK_RATE, s_pFadeOutContextThink );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Fades lookup weight from CurWeight->MaxWeight
|
||||
//-----------------------------------------------------------------------------
|
||||
void CColorCorrection::FadeInThink( void )
|
||||
{
|
||||
// Check for conditions where we shouldnt fade in
|
||||
if ( m_flFadeInDuration <= 0 || // not set to fade in
|
||||
m_flCurWeight >= m_flMaxWeight || // already past max weight
|
||||
!m_bEnabled || // fade in/out mutex
|
||||
m_flMaxWeight == 0.0f || // min==max
|
||||
m_flStartFadeInWeight >= m_flMaxWeight ) // already at max weight
|
||||
{
|
||||
SetNextThink ( TICK_NEVER_THINK, s_pFadeInContextThink );
|
||||
return;
|
||||
}
|
||||
|
||||
// If we started fading in without fully fading out, use a truncated duration
|
||||
float flTimeToFade = m_flFadeInDuration;
|
||||
if ( m_flStartFadeInWeight > 0.0f )
|
||||
{
|
||||
float flWeightRatio = m_flStartFadeInWeight / m_flMaxWeight;
|
||||
flWeightRatio = clamp ( flWeightRatio, 0.0f, 0.99f );
|
||||
flTimeToFade = m_flFadeInDuration * (1.0 - flWeightRatio);
|
||||
}
|
||||
|
||||
Assert ( flTimeToFade > 0.0f );
|
||||
float flFadeRatio = (gpGlobals->curtime - m_flTimeStartFadeIn) / flTimeToFade;
|
||||
flFadeRatio = clamp ( flFadeRatio, 0.0f, 1.0f );
|
||||
m_flStartFadeInWeight = clamp ( m_flStartFadeInWeight, 0.0f, 1.0f );
|
||||
|
||||
m_flCurWeight = Lerp( flFadeRatio, m_flStartFadeInWeight, m_flMaxWeight );
|
||||
|
||||
SetNextThink( gpGlobals->curtime + COLOR_CORRECTION_ENT_THINK_RATE, s_pFadeInContextThink );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Fades lookup weight from CurWeight->0.0
|
||||
//-----------------------------------------------------------------------------
|
||||
void CColorCorrection::FadeOutThink( void )
|
||||
{
|
||||
// Check for conditions where we shouldn't fade out
|
||||
if ( m_flFadeOutDuration <= 0 || // not set to fade out
|
||||
m_flCurWeight <= 0.0f || // already faded out
|
||||
m_bEnabled || // fade in/out mutex
|
||||
m_flMaxWeight == 0.0f || // min==max
|
||||
m_flStartFadeOutWeight <= 0.0f )// already at min weight
|
||||
{
|
||||
SetNextThink ( TICK_NEVER_THINK, s_pFadeOutContextThink );
|
||||
return;
|
||||
}
|
||||
|
||||
// If we started fading out without fully fading in, use a truncated duration
|
||||
float flTimeToFade = m_flFadeOutDuration;
|
||||
if ( m_flStartFadeOutWeight < m_flMaxWeight )
|
||||
{
|
||||
float flWeightRatio = m_flStartFadeOutWeight / m_flMaxWeight;
|
||||
flWeightRatio = clamp ( flWeightRatio, 0.01f, 1.0f );
|
||||
flTimeToFade = m_flFadeOutDuration * flWeightRatio;
|
||||
}
|
||||
|
||||
Assert ( flTimeToFade > 0.0f );
|
||||
float flFadeRatio = (gpGlobals->curtime - m_flTimeStartFadeOut) / flTimeToFade;
|
||||
flFadeRatio = clamp ( flFadeRatio, 0.0f, 1.0f );
|
||||
m_flStartFadeOutWeight = clamp ( m_flStartFadeOutWeight, 0.0f, 1.0f );
|
||||
|
||||
m_flCurWeight = Lerp( 1.0f - flFadeRatio, 0.0f, m_flStartFadeOutWeight );
|
||||
|
||||
SetNextThink( gpGlobals->curtime + COLOR_CORRECTION_ENT_THINK_RATE, s_pFadeOutContextThink );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Input handlers
|
||||
//------------------------------------------------------------------------------
|
||||
void CColorCorrection::InputEnable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bEnabled = true;
|
||||
|
||||
if ( m_flFadeInDuration > 0.0f )
|
||||
{
|
||||
FadeIn();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flCurWeight = m_flMaxWeight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CColorCorrection::InputDisable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bEnabled = false;
|
||||
|
||||
if ( m_flFadeOutDuration > 0.0f )
|
||||
{
|
||||
FadeOut();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flCurWeight = 0.0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CColorCorrection::InputSetFadeInDuration( inputdata_t& inputdata )
|
||||
{
|
||||
m_flFadeInDuration = inputdata.value.Float();
|
||||
}
|
||||
|
||||
void CColorCorrection::InputSetFadeOutDuration( inputdata_t& inputdata )
|
||||
{
|
||||
m_flFadeOutDuration = inputdata.value.Float();
|
||||
}
|
||||
236
sp/src/game/server/colorcorrectionvolume.cpp
Normal file
236
sp/src/game/server/colorcorrectionvolume.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Color correction entity.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "cbase.h"
|
||||
#include "triggers.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FIXME: This really should inherit from something more lightweight
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Shadow control entity
|
||||
//------------------------------------------------------------------------------
|
||||
class CColorCorrectionVolume : public CBaseTrigger
|
||||
{
|
||||
DECLARE_CLASS( CColorCorrectionVolume, CBaseTrigger );
|
||||
public:
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
CColorCorrectionVolume();
|
||||
|
||||
void Spawn( void );
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
int UpdateTransmitState();
|
||||
|
||||
void ThinkFunc();
|
||||
|
||||
virtual bool PassesTriggerFilters(CBaseEntity *pOther);
|
||||
virtual void StartTouch( CBaseEntity *pEntity );
|
||||
virtual void EndTouch( CBaseEntity *pEntity );
|
||||
|
||||
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
|
||||
// Inputs
|
||||
void InputEnable( inputdata_t &inputdata );
|
||||
void InputDisable( inputdata_t &inputdata );
|
||||
|
||||
private:
|
||||
|
||||
bool m_bEnabled;
|
||||
bool m_bStartDisabled;
|
||||
|
||||
CNetworkVar( float, m_Weight );
|
||||
CNetworkVar( float, m_MaxWeight );
|
||||
CNetworkString( m_lookupFilename, MAX_PATH );
|
||||
|
||||
float m_LastEnterWeight;
|
||||
float m_LastEnterTime;
|
||||
|
||||
float m_LastExitWeight;
|
||||
float m_LastExitTime;
|
||||
|
||||
float m_FadeDuration;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(color_correction_volume, CColorCorrectionVolume);
|
||||
|
||||
BEGIN_DATADESC( CColorCorrectionVolume )
|
||||
|
||||
DEFINE_THINKFUNC( ThinkFunc ),
|
||||
|
||||
DEFINE_KEYFIELD( m_FadeDuration, FIELD_FLOAT, "fadeDuration" ),
|
||||
DEFINE_KEYFIELD( m_MaxWeight, FIELD_FLOAT, "maxweight" ),
|
||||
DEFINE_AUTO_ARRAY_KEYFIELD( m_lookupFilename, FIELD_CHARACTER, "filename" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ),
|
||||
DEFINE_KEYFIELD( m_bStartDisabled, FIELD_BOOLEAN, "StartDisabled" ),
|
||||
|
||||
DEFINE_FIELD( m_Weight, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_LastEnterWeight, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_LastEnterTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_LastExitWeight, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_LastExitTime, FIELD_FLOAT ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST_NOBASE(CColorCorrectionVolume, DT_ColorCorrectionVolume)
|
||||
SendPropFloat( SENDINFO(m_Weight) ),
|
||||
SendPropString( SENDINFO(m_lookupFilename) ),
|
||||
END_SEND_TABLE()
|
||||
|
||||
|
||||
CColorCorrectionVolume::CColorCorrectionVolume() : BaseClass()
|
||||
{
|
||||
m_bEnabled = true;
|
||||
m_MaxWeight = 1.0f;
|
||||
m_lookupFilename.GetForModify()[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Send even though we don't have a model
|
||||
//------------------------------------------------------------------------------
|
||||
int CColorCorrectionVolume::UpdateTransmitState()
|
||||
{
|
||||
// ALWAYS transmit to all clients.
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
|
||||
bool CColorCorrectionVolume::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "filename" ) )
|
||||
{
|
||||
Q_strncpy( m_lookupFilename.GetForModify(), szValue, MAX_PATH );
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ( FStrEq( szKeyName, "maxweight" ) )
|
||||
{
|
||||
float max_weight;
|
||||
sscanf( szValue, "%f", &max_weight );
|
||||
m_MaxWeight = max_weight;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
//------------------------------------------------------------------------------
|
||||
void CColorCorrectionVolume::Spawn( void )
|
||||
{
|
||||
BaseClass::Spawn();
|
||||
|
||||
AddEFlags( EFL_FORCE_CHECK_TRANSMIT | EFL_DIRTY_ABSTRANSFORM );
|
||||
Precache();
|
||||
|
||||
SetSolid( SOLID_BSP );
|
||||
SetSolidFlags( FSOLID_TRIGGER | FSOLID_NOT_SOLID );
|
||||
SetModel( STRING( GetModelName() ) );
|
||||
|
||||
SetThink( &CColorCorrectionVolume::ThinkFunc );
|
||||
SetNextThink( gpGlobals->curtime + 0.01f );
|
||||
|
||||
if( m_bStartDisabled )
|
||||
{
|
||||
m_bEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CColorCorrectionVolume::PassesTriggerFilters( CBaseEntity *pEntity )
|
||||
{
|
||||
if( pEntity == UTIL_GetLocalPlayer() )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CColorCorrectionVolume::StartTouch( CBaseEntity *pEntity )
|
||||
{
|
||||
m_LastEnterTime = gpGlobals->curtime;
|
||||
m_LastEnterWeight = m_Weight;
|
||||
}
|
||||
|
||||
void CColorCorrectionVolume::EndTouch( CBaseEntity *pEntity )
|
||||
{
|
||||
m_LastExitTime = gpGlobals->curtime;
|
||||
m_LastExitWeight = m_Weight;
|
||||
}
|
||||
|
||||
void CColorCorrectionVolume::ThinkFunc( )
|
||||
{
|
||||
if( !m_bEnabled )
|
||||
{
|
||||
m_Weight.Set( 0.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_LastEnterTime > m_LastExitTime )
|
||||
{
|
||||
// we most recently entered the volume
|
||||
|
||||
if( m_Weight < 1.0f )
|
||||
{
|
||||
float dt = gpGlobals->curtime - m_LastEnterTime;
|
||||
float weight = m_LastEnterWeight + dt / ((1.0f-m_LastEnterWeight)*m_FadeDuration);
|
||||
if( weight>1.0f )
|
||||
weight = 1.0f;
|
||||
|
||||
m_Weight = weight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we most recently exitted the volume
|
||||
|
||||
if( m_Weight > 0.0f )
|
||||
{
|
||||
float dt = gpGlobals->curtime - m_LastExitTime;
|
||||
float weight = (1.0f-m_LastExitWeight) + dt / (m_LastExitWeight*m_FadeDuration);
|
||||
if( weight>1.0f )
|
||||
weight = 1.0f;
|
||||
|
||||
m_Weight = 1.0f - weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetNextThink( gpGlobals->curtime + 0.01f );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Input handlers
|
||||
//------------------------------------------------------------------------------
|
||||
void CColorCorrectionVolume::InputEnable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bEnabled = true;
|
||||
}
|
||||
|
||||
void CColorCorrectionVolume::InputDisable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bEnabled = false;
|
||||
}
|
||||
146
sp/src/game/server/controlentities.cpp
Normal file
146
sp/src/game/server/controlentities.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: contains entities who have no physical representation in the game, and who
|
||||
// must be triggered by other entities to cause their effects.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "player.h"
|
||||
#include "tier1/strtools.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: when fired, it changes which track the CD is playing
|
||||
//-----------------------------------------------------------------------------
|
||||
class CTargetCDAudioRep : public CPointEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CTargetCDAudioRep, CPointEntity );
|
||||
|
||||
void InputChangeCDTrack( inputdata_t &inputdata );
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
private:
|
||||
int m_iTrack; // CD track to change to when fired
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( target_cdaudio, CTargetCDAudioRep );
|
||||
|
||||
BEGIN_DATADESC( CTargetCDAudioRep )
|
||||
|
||||
DEFINE_KEYFIELD( m_iTrack, FIELD_INTEGER, "track" ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ChangeCDTrack", InputChangeCDTrack ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Changes the current playing CD track
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTargetCDAudioRep::InputChangeCDTrack( inputdata_t &inputdata )
|
||||
{
|
||||
int iTrack = m_iTrack;
|
||||
|
||||
|
||||
edict_t *pClient = NULL;
|
||||
if ( gpGlobals->maxClients == 1 )
|
||||
{
|
||||
pClient = engine->PEntityOfEntIndex( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// In multiplayer, send it back to the activator
|
||||
CBasePlayer *player = dynamic_cast< CBasePlayer * >( inputdata.pActivator );
|
||||
if ( player )
|
||||
{
|
||||
pClient = player->edict();
|
||||
}
|
||||
}
|
||||
|
||||
// Can't play if the client is not connected!
|
||||
if ( !pClient )
|
||||
return;
|
||||
|
||||
if ( iTrack < -1 || iTrack > 30 )
|
||||
{
|
||||
Warning( "TargetCDAudio - Track %d out of range\n", iTrack );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( iTrack == -1 )
|
||||
{
|
||||
engine->ClientCommand( pClient, "cd pause\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
engine->ClientCommand ( pClient, "cd play %3d\n", iTrack );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: changes the gravity of the player who activates this entity
|
||||
//-----------------------------------------------------------------------------
|
||||
class CTargetChangeGravity : public CPointEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CTargetChangeGravity, CPointEntity );
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
void InputChangeGrav( inputdata_t &inputdata );
|
||||
void InputResetGrav( inputdata_t &inputdata );
|
||||
|
||||
int m_iGravity;
|
||||
|
||||
int m_iOldGrav;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( target_changegravity, CTargetChangeGravity );
|
||||
|
||||
BEGIN_DATADESC( CTargetChangeGravity )
|
||||
|
||||
DEFINE_KEYFIELD( m_iGravity, FIELD_INTEGER, "gravity" ),
|
||||
DEFINE_FIELD( m_iOldGrav, FIELD_INTEGER ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ChangeGrav", InputChangeGrav ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ResetGrav", InputResetGrav ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler for changing the activator's gravity.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTargetChangeGravity::InputChangeGrav( inputdata_t &inputdata )
|
||||
{
|
||||
CBasePlayer *pl = ToBasePlayer( inputdata.pActivator );
|
||||
if ( !pl )
|
||||
return;
|
||||
|
||||
// Save the gravity to restore it in InputResetGrav
|
||||
if ( m_iOldGrav )
|
||||
m_iOldGrav = pl->GetGravity();
|
||||
|
||||
pl->SetGravity(m_iGravity);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler for resetting the activator's gravity.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTargetChangeGravity::InputResetGrav( inputdata_t &inputdata )
|
||||
{
|
||||
CBasePlayer *pl = ToBasePlayer( inputdata.pActivator );
|
||||
if ( !pl )
|
||||
return;
|
||||
|
||||
pl->SetGravity(m_iOldGrav);
|
||||
}
|
||||
|
||||
|
||||
71
sp/src/game/server/cplane.cpp
Normal file
71
sp/src/game/server/cplane.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "game.h"
|
||||
#include "cplane.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//=========================================================
|
||||
// Plane
|
||||
//=========================================================
|
||||
CPlane::CPlane ( void )
|
||||
{
|
||||
m_fInitialized = FALSE;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// InitializePlane - Takes a normal for the plane and a
|
||||
// point on the plane and
|
||||
//=========================================================
|
||||
void CPlane::InitializePlane ( const Vector &vecNormal, const Vector &vecPoint )
|
||||
{
|
||||
m_vecNormal = vecNormal;
|
||||
m_flDist = DotProduct ( m_vecNormal, vecPoint );
|
||||
m_fInitialized = TRUE;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// PointInFront - determines whether the given vector is
|
||||
// in front of the plane.
|
||||
//=========================================================
|
||||
bool CPlane::PointInFront ( const Vector &vecPoint )
|
||||
{
|
||||
float flFace;
|
||||
|
||||
if ( !m_fInitialized )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
flFace = DotProduct ( m_vecNormal, vecPoint ) - m_flDist;
|
||||
|
||||
if ( flFace >= 0 )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
float CPlane::PointDist ( const Vector &vecPoint )
|
||||
{
|
||||
float flDist;
|
||||
|
||||
if ( !m_fInitialized )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
flDist = DotProduct ( m_vecNormal, vecPoint ) - m_flDist;
|
||||
|
||||
return flDist;
|
||||
}
|
||||
44
sp/src/game/server/cplane.h
Normal file
44
sp/src/game/server/cplane.h
Normal file
@@ -0,0 +1,44 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#pragma once
|
||||
|
||||
#ifndef CPLANE_H
|
||||
#define CPLANE_H
|
||||
|
||||
//=========================================================
|
||||
// Plane
|
||||
//=========================================================
|
||||
class CPlane
|
||||
{
|
||||
public:
|
||||
CPlane ( void );
|
||||
|
||||
//=========================================================
|
||||
// InitializePlane - Takes a normal for the plane and a
|
||||
// point on the plane and
|
||||
//=========================================================
|
||||
void InitializePlane ( const Vector &vecNormal, const Vector &vecPoint );
|
||||
|
||||
//=========================================================
|
||||
// PointInFront - determines whether the given vector is
|
||||
// in front of the plane.
|
||||
//=========================================================
|
||||
bool PointInFront ( const Vector &vecPoint );
|
||||
|
||||
//=========================================================
|
||||
// How far off the plane is this point?
|
||||
//=========================================================
|
||||
float PointDist( const Vector &vecPoint );
|
||||
|
||||
private:
|
||||
Vector m_vecNormal;
|
||||
float m_flDist;
|
||||
bool m_fInitialized;
|
||||
};
|
||||
|
||||
#endif //CPLANE_H
|
||||
9
sp/src/game/server/csm.vpc
Normal file
9
sp/src/game/server/csm.vpc
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
$Project
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "env_cascade_light.cpp"
|
||||
}
|
||||
}
|
||||
85
sp/src/game/server/damagemodifier.cpp
Normal file
85
sp/src/game/server/damagemodifier.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "damagemodifier.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CDamageModifier::CDamageModifier()
|
||||
{
|
||||
m_flModifier = 1;
|
||||
m_bDoneToMe = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDamageModifier::AddModifierToEntity( CBaseEntity *pEntity )
|
||||
{
|
||||
RemoveModifier();
|
||||
|
||||
pEntity->m_DamageModifiers.AddToTail( this );
|
||||
m_hEnt = pEntity;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDamageModifier::RemoveModifier()
|
||||
{
|
||||
if ( m_hEnt.Get() )
|
||||
{
|
||||
m_hEnt->m_DamageModifiers.FindAndRemove( this );
|
||||
m_hEnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDamageModifier::SetModifier( float flScale )
|
||||
{
|
||||
m_flModifier = flScale;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CDamageModifier::GetModifier() const
|
||||
{
|
||||
return m_flModifier;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseEntity* CDamageModifier::GetCharacter() const
|
||||
{
|
||||
return m_hEnt.Get();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDamageModifier::SetDoneToMe( bool bDoneToMe )
|
||||
{
|
||||
m_bDoneToMe = bDoneToMe;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CDamageModifier::IsDamageDoneToMe() const
|
||||
{
|
||||
return m_bDoneToMe;
|
||||
}
|
||||
|
||||
46
sp/src/game/server/damagemodifier.h
Normal file
46
sp/src/game/server/damagemodifier.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef DAMAGEMODIFIER_H
|
||||
#define DAMAGEMODIFIER_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
class CBaseEntity;
|
||||
|
||||
|
||||
#include "ehandle.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Class handling generic damage modification to & from a player
|
||||
//-----------------------------------------------------------------------------
|
||||
class CDamageModifier
|
||||
{
|
||||
public:
|
||||
CDamageModifier();
|
||||
|
||||
void AddModifierToEntity( CBaseEntity *pChar );
|
||||
void RemoveModifier();
|
||||
|
||||
void SetModifier( float flDamageScale );
|
||||
float GetModifier() const;
|
||||
|
||||
void SetDoneToMe( bool bDoneToMe );
|
||||
bool IsDamageDoneToMe() const;
|
||||
|
||||
CBaseEntity *GetCharacter() const;
|
||||
|
||||
private:
|
||||
float m_flModifier;
|
||||
CHandle<CBaseEntity> m_hEnt;
|
||||
bool m_bDoneToMe; // True = modifies damage done to the entity, false = damage done by the entity
|
||||
};
|
||||
|
||||
|
||||
#endif // DAMAGEMODIFIER_H
|
||||
66
sp/src/game/server/data_collector.cpp
Normal file
66
sp/src/game/server/data_collector.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// data_collector.cpp
|
||||
// Data collection system
|
||||
// Author: Michael S. Booth, June 2004
|
||||
|
||||
#include "cbase.h"
|
||||
#include "data_collector.h"
|
||||
|
||||
static CDataCollector *collector = NULL;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void StartDataCollection( void )
|
||||
{
|
||||
if (collector)
|
||||
{
|
||||
// already collecting
|
||||
return;
|
||||
}
|
||||
|
||||
collector = new CDataCollector;
|
||||
Msg( "Data colletion started.\n" );
|
||||
}
|
||||
ConCommand data_collection_start( "data_collection_start", StartDataCollection, "Start collecting game event data." );
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void StopDataCollection( void )
|
||||
{
|
||||
if (collector)
|
||||
{
|
||||
delete collector;
|
||||
collector = NULL;
|
||||
|
||||
Msg( "Data collection stopped.\n" );
|
||||
}
|
||||
}
|
||||
ConCommand data_collection_stop( "data_collection_stop", StopDataCollection, "Stop collecting game event data." );
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
CDataCollector::CDataCollector( void )
|
||||
{
|
||||
// register for all events
|
||||
gameeventmanager->AddListener( this, true );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
CDataCollector::~CDataCollector()
|
||||
{
|
||||
gameeventmanager->RemoveListener( this );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* This is invoked for each event that occurs in the game
|
||||
*/
|
||||
void CDataCollector::FireGameEvent( KeyValues *event )
|
||||
{
|
||||
DevMsg( "Collected event '%s'\n", event->GetName() );
|
||||
}
|
||||
37
sp/src/game/server/data_collector.h
Normal file
37
sp/src/game/server/data_collector.h
Normal file
@@ -0,0 +1,37 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// data_collector.h
|
||||
// Data collection system
|
||||
// Author: Michael S. Booth, June 2004
|
||||
|
||||
#ifndef _DATA_COLLECTOR_H_
|
||||
#define _DATA_COLLECTOR_H_
|
||||
|
||||
#include <igameevents.h>
|
||||
#include <KeyValues.h>
|
||||
|
||||
/**
|
||||
* This class is used to monitor the event stream and
|
||||
* store interesting events to disk for later analysis.
|
||||
*/
|
||||
class CDataCollector : public IGameEventListener
|
||||
{
|
||||
public:
|
||||
CDataCollector( void );
|
||||
~CDataCollector();
|
||||
|
||||
// IGameEventListener
|
||||
virtual void FireGameEvent( KeyValues *event );
|
||||
};
|
||||
|
||||
|
||||
extern void StartDataCollection( void );
|
||||
extern void StopDataCollection( void );
|
||||
|
||||
|
||||
#endif // _DATA_COLLECTOR_H_
|
||||
1433
sp/src/game/server/doors.cpp
Normal file
1433
sp/src/game/server/doors.cpp
Normal file
File diff suppressed because it is too large
Load Diff
162
sp/src/game/server/doors.h
Normal file
162
sp/src/game/server/doors.h
Normal file
@@ -0,0 +1,162 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef DOORS_H
|
||||
#define DOORS_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "locksounds.h"
|
||||
#include "entityoutput.h"
|
||||
|
||||
//Since I'm here, might as well explain how these work. Base.fgd is the file that connects
|
||||
//flags to entities. It is full of lines with this number, a label, and a default value.
|
||||
//Voila, dynamicly generated checkboxes on the Flags tab of Entity Properties.
|
||||
|
||||
// doors
|
||||
#define SF_DOOR_ROTATE_YAW 0 // yaw by default
|
||||
#define SF_DOOR_START_OPEN_OBSOLETE 1
|
||||
#define SF_DOOR_ROTATE_BACKWARDS 2
|
||||
#define SF_DOOR_NONSOLID_TO_PLAYER 4
|
||||
#define SF_DOOR_PASSABLE 8
|
||||
#define SF_DOOR_ONEWAY 16
|
||||
#define SF_DOOR_NO_AUTO_RETURN 32
|
||||
#define SF_DOOR_ROTATE_ROLL 64
|
||||
#define SF_DOOR_ROTATE_PITCH 128
|
||||
#define SF_DOOR_PUSE 256 // door can be opened by player's use button.
|
||||
#define SF_DOOR_NONPCS 512 // NPC can't open
|
||||
#define SF_DOOR_PTOUCH 1024 // player touch opens
|
||||
#define SF_DOOR_LOCKED 2048 // Door is initially locked
|
||||
#define SF_DOOR_SILENT 4096 // Door plays no audible sound, and does not alert NPCs when opened
|
||||
#define SF_DOOR_USE_CLOSES 8192 // Door can be +used to close before its autoreturn delay has expired.
|
||||
#define SF_DOOR_SILENT_TO_NPCS 16384 // Does not alert NPC's when opened.
|
||||
#define SF_DOOR_IGNORE_USE 32768 // Completely ignores player +use commands.
|
||||
#define SF_DOOR_NEW_USE_RULES 65536 // For func_door entities, behave more like prop_door_rotating with respect to +USE (changelist 242482)
|
||||
|
||||
|
||||
enum FuncDoorSpawnPos_t
|
||||
{
|
||||
FUNC_DOOR_SPAWN_CLOSED = 0,
|
||||
FUNC_DOOR_SPAWN_OPEN,
|
||||
};
|
||||
|
||||
|
||||
class CBaseDoor : public CBaseToggle
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CBaseDoor, CBaseToggle );
|
||||
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
bool CreateVPhysics();
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
|
||||
virtual void StartBlocked( CBaseEntity *pOther );
|
||||
virtual void Blocked( CBaseEntity *pOther );
|
||||
virtual void EndBlocked( void );
|
||||
|
||||
void Activate( void );
|
||||
|
||||
virtual int ObjectCaps( void )
|
||||
{
|
||||
int flags = BaseClass::ObjectCaps();
|
||||
if ( HasSpawnFlags( SF_DOOR_PUSE ) )
|
||||
return flags | FCAP_IMPULSE_USE | FCAP_USE_IN_RADIUS;
|
||||
|
||||
return flags;
|
||||
};
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
// This is ONLY used by the node graph to test movement through a door
|
||||
void InputSetToggleState( inputdata_t &inputdata );
|
||||
virtual void SetToggleState( int state );
|
||||
|
||||
virtual bool IsRotatingDoor() { return false; }
|
||||
virtual bool ShouldSavePhysics();
|
||||
// used to selectivly override defaults
|
||||
void DoorTouch( CBaseEntity *pOther );
|
||||
|
||||
// local functions
|
||||
int DoorActivate( );
|
||||
void DoorGoUp( void );
|
||||
void DoorGoDown( void );
|
||||
void DoorHitTop( void );
|
||||
void DoorHitBottom( void );
|
||||
void UpdateAreaPortals( bool isOpen );
|
||||
void Unlock( void );
|
||||
void Lock( void );
|
||||
int GetDoorMovementGroup( CBaseDoor *pDoorList[], int listMax );
|
||||
|
||||
// Input handlers
|
||||
void InputClose( inputdata_t &inputdata );
|
||||
void InputLock( inputdata_t &inputdata );
|
||||
void InputOpen( inputdata_t &inputdata );
|
||||
void InputToggle( inputdata_t &inputdata );
|
||||
void InputUnlock( inputdata_t &inputdata );
|
||||
void InputSetSpeed( inputdata_t &inputdata );
|
||||
|
||||
Vector m_vecMoveDir; // The direction of motion for linear moving doors.
|
||||
|
||||
locksound_t m_ls; // door lock sounds
|
||||
|
||||
byte m_bLockedSentence;
|
||||
byte m_bUnlockedSentence;
|
||||
|
||||
bool m_bForceClosed; // If set, always close, even if we're blocked.
|
||||
bool m_bDoorGroup;
|
||||
bool m_bLocked; // Whether the door is locked
|
||||
bool m_bIgnoreDebris;
|
||||
bool m_bIgnoreNonPlayerEntsOnBlock; // Non-player entities should never block. This variable needs more letters.
|
||||
|
||||
FuncDoorSpawnPos_t m_eSpawnPosition;
|
||||
|
||||
float m_flBlockDamage; // Damage inflicted when blocked.
|
||||
string_t m_NoiseMoving; //Start/Looping sound
|
||||
string_t m_NoiseArrived; //End sound
|
||||
string_t m_NoiseMovingClosed; //Start/Looping sound
|
||||
string_t m_NoiseArrivedClosed; //End sound
|
||||
string_t m_ChainTarget; ///< Entity name to pass Touch and Use events to
|
||||
|
||||
CNetworkVar( float, m_flWaveHeight );
|
||||
|
||||
// Outputs
|
||||
COutputEvent m_OnBlockedClosing; // Triggered when the door becomes blocked while closing.
|
||||
COutputEvent m_OnBlockedOpening; // Triggered when the door becomes blocked while opening.
|
||||
COutputEvent m_OnUnblockedClosing; // Triggered when the door becomes unblocked while closing.
|
||||
COutputEvent m_OnUnblockedOpening; // Triggered when the door becomes unblocked while opening.
|
||||
COutputEvent m_OnFullyClosed; // Triggered when the door reaches the fully closed position.
|
||||
COutputEvent m_OnFullyOpen; // Triggered when the door reaches the fully open position.
|
||||
COutputEvent m_OnClose; // Triggered when the door is told to close.
|
||||
COutputEvent m_OnOpen; // Triggered when the door is told to open.
|
||||
COutputEvent m_OnLockedUse; // Triggered when the user tries to open a locked door.
|
||||
|
||||
void StartMovingSound( void );
|
||||
virtual void StopMovingSound( void );
|
||||
void MovingSoundThink( void );
|
||||
#ifdef HL1_DLL
|
||||
bool PassesBlockTouchFilter(CBaseEntity *pOther);
|
||||
string_t m_iBlockFilterName;
|
||||
EHANDLE m_hBlockFilter;
|
||||
#endif
|
||||
|
||||
bool ShouldLoopMoveSound( void ) { return m_bLoopMoveSound; }
|
||||
bool m_bLoopMoveSound; // Move sound loops until stopped
|
||||
|
||||
private:
|
||||
void ChainUse( void ); ///< Chains +use on through to m_ChainTarget
|
||||
void ChainTouch( CBaseEntity *pOther ); ///< Chains touch on through to m_ChainTarget
|
||||
void SetChaining( bool chaining ) { m_isChaining = chaining; } ///< Latch to prevent recursion
|
||||
bool m_isChaining;
|
||||
|
||||
void CloseAreaPortalsThink( void ); ///< Delays turning off area portals when closing doors to prevent visual artifacts
|
||||
};
|
||||
|
||||
#endif // DOORS_H
|
||||
203
sp/src/game/server/dynamiclight.cpp
Normal file
203
sp/src/game/server/dynamiclight.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Dynamic light.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "dlight.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
#define NUM_DL_EXPONENT_BITS 8
|
||||
#define MIN_DL_EXPONENT_VALUE -((1 << (NUM_DL_EXPONENT_BITS-1)) - 1)
|
||||
#define MAX_DL_EXPONENT_VALUE ((1 << (NUM_DL_EXPONENT_BITS-1)) - 1)
|
||||
|
||||
|
||||
class CDynamicLight : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CDynamicLight, CBaseEntity );
|
||||
|
||||
void Spawn( void );
|
||||
void DynamicLightThink( void );
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
// Turn on and off the light
|
||||
void InputTurnOn( inputdata_t &inputdata );
|
||||
void InputTurnOff( inputdata_t &inputdata );
|
||||
void InputToggle( inputdata_t &inputdata );
|
||||
|
||||
public:
|
||||
unsigned char m_ActualFlags;
|
||||
CNetworkVar( unsigned char, m_Flags );
|
||||
CNetworkVar( unsigned char, m_LightStyle );
|
||||
bool m_On;
|
||||
CNetworkVar( float, m_Radius );
|
||||
CNetworkVar( int, m_Exponent );
|
||||
CNetworkVar( float, m_InnerAngle );
|
||||
CNetworkVar( float, m_OuterAngle );
|
||||
CNetworkVar( float, m_SpotRadius );
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(light_dynamic, CDynamicLight);
|
||||
|
||||
BEGIN_DATADESC( CDynamicLight )
|
||||
|
||||
DEFINE_FIELD( m_ActualFlags, FIELD_CHARACTER ),
|
||||
DEFINE_FIELD( m_Flags, FIELD_CHARACTER ),
|
||||
DEFINE_FIELD( m_On, FIELD_BOOLEAN ),
|
||||
|
||||
DEFINE_THINKFUNC( DynamicLightThink ),
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUT( m_Radius, FIELD_FLOAT, "distance" ),
|
||||
DEFINE_INPUT( m_Exponent, FIELD_INTEGER, "brightness" ),
|
||||
DEFINE_INPUT( m_InnerAngle, FIELD_FLOAT, "_inner_cone" ),
|
||||
DEFINE_INPUT( m_OuterAngle, FIELD_FLOAT, "_cone" ),
|
||||
DEFINE_INPUT( m_SpotRadius, FIELD_FLOAT, "spotlight_radius" ),
|
||||
DEFINE_INPUT( m_LightStyle, FIELD_CHARACTER,"style" ),
|
||||
|
||||
// Input functions
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST(CDynamicLight, DT_DynamicLight)
|
||||
SendPropInt( SENDINFO(m_Flags), 4, SPROP_UNSIGNED ),
|
||||
SendPropInt( SENDINFO(m_LightStyle), 4, SPROP_UNSIGNED ),
|
||||
SendPropFloat( SENDINFO(m_Radius), 0, SPROP_NOSCALE),
|
||||
SendPropInt( SENDINFO(m_Exponent), NUM_DL_EXPONENT_BITS),
|
||||
SendPropFloat( SENDINFO(m_InnerAngle), 8, 0, 0.0, 360.0f ),
|
||||
SendPropFloat( SENDINFO(m_OuterAngle), 8, 0, 0.0, 360.0f ),
|
||||
SendPropFloat( SENDINFO(m_SpotRadius), 0, SPROP_NOSCALE),
|
||||
END_SEND_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CDynamicLight::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "_light" ) )
|
||||
{
|
||||
color32 tmp;
|
||||
UTIL_StringToColor32( &tmp, szValue );
|
||||
SetRenderColor( tmp.r, tmp.g, tmp.b );
|
||||
}
|
||||
else if ( FStrEq( szKeyName, "pitch" ) )
|
||||
{
|
||||
float angle = atof(szValue);
|
||||
if ( angle )
|
||||
{
|
||||
QAngle angles = GetAbsAngles();
|
||||
angles[PITCH] = -angle;
|
||||
SetAbsAngles( angles );
|
||||
}
|
||||
}
|
||||
else if ( FStrEq( szKeyName, "spawnflags" ) )
|
||||
{
|
||||
m_ActualFlags = m_Flags = atoi(szValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Turn on and off the light
|
||||
//------------------------------------------------------------------------------
|
||||
void CDynamicLight::InputTurnOn( inputdata_t &inputdata )
|
||||
{
|
||||
m_Flags = m_ActualFlags;
|
||||
m_On = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDynamicLight::InputTurnOff( inputdata_t &inputdata )
|
||||
{
|
||||
// This basically shuts it off
|
||||
m_Flags = DLIGHT_NO_MODEL_ILLUMINATION | DLIGHT_NO_WORLD_ILLUMINATION;
|
||||
m_On = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDynamicLight::InputToggle( inputdata_t &inputdata )
|
||||
{
|
||||
if (m_On)
|
||||
{
|
||||
InputTurnOff( inputdata );
|
||||
}
|
||||
else
|
||||
{
|
||||
InputTurnOn( inputdata );
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
//------------------------------------------------------------------------------
|
||||
void CDynamicLight::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
SetSolid( SOLID_NONE );
|
||||
m_On = true;
|
||||
UTIL_SetSize( this, vec3_origin, vec3_origin );
|
||||
AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
|
||||
|
||||
// If we have a target, think so we can orient towards it
|
||||
if ( m_target != NULL_STRING )
|
||||
{
|
||||
SetThink( &CDynamicLight::DynamicLightThink );
|
||||
SetNextThink( gpGlobals->curtime + 0.1 );
|
||||
}
|
||||
|
||||
int clampedExponent = clamp( (int) m_Exponent, MIN_DL_EXPONENT_VALUE, MAX_DL_EXPONENT_VALUE );
|
||||
if ( m_Exponent != clampedExponent )
|
||||
{
|
||||
Warning( "light_dynamic at [%d %d %d] has invalid exponent value (%d must be between %d and %d).\n",
|
||||
(int)GetAbsOrigin().x, (int)GetAbsOrigin().x, (int)GetAbsOrigin().x,
|
||||
m_Exponent.Get(),
|
||||
MIN_DL_EXPONENT_VALUE,
|
||||
MAX_DL_EXPONENT_VALUE );
|
||||
|
||||
m_Exponent = clampedExponent;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDynamicLight::DynamicLightThink( void )
|
||||
{
|
||||
if ( m_target == NULL_STRING )
|
||||
return;
|
||||
|
||||
CBaseEntity *pEntity = GetNextTarget();
|
||||
if ( pEntity )
|
||||
{
|
||||
Vector vecToTarget = (pEntity->GetAbsOrigin() - GetAbsOrigin());
|
||||
QAngle vecAngles;
|
||||
VectorAngles( vecToTarget, vecAngles );
|
||||
SetAbsAngles( vecAngles );
|
||||
}
|
||||
|
||||
SetNextThink( gpGlobals->curtime + 0.1 );
|
||||
}
|
||||
2628
sp/src/game/server/effects.cpp
Normal file
2628
sp/src/game/server/effects.cpp
Normal file
File diff suppressed because it is too large
Load Diff
68
sp/src/game/server/effects.h
Normal file
68
sp/src/game/server/effects.h
Normal file
@@ -0,0 +1,68 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef EFFECTS_H
|
||||
#define EFFECTS_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
class CBaseEntity;
|
||||
class Vector;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The rotor wash shooter. It emits gibs when pushed by a rotor wash
|
||||
//-----------------------------------------------------------------------------
|
||||
abstract_class IRotorWashShooter
|
||||
{
|
||||
public:
|
||||
virtual CBaseEntity *DoWashPush( float flWashStartTime, const Vector &vecForce ) = 0;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets at the interface if the entity supports it
|
||||
//-----------------------------------------------------------------------------
|
||||
IRotorWashShooter *GetRotorWashShooter( CBaseEntity *pEntity );
|
||||
|
||||
class CEnvQuadraticBeam : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS( CEnvQuadraticBeam, CPointEntity );
|
||||
|
||||
public:
|
||||
void Spawn();
|
||||
void SetSpline( const Vector &control, const Vector &target )
|
||||
{
|
||||
m_targetPosition = target;
|
||||
m_controlPosition = control;
|
||||
}
|
||||
void SetScrollRate( float rate )
|
||||
{
|
||||
m_scrollRate = rate;
|
||||
}
|
||||
|
||||
void SetWidth( float width )
|
||||
{
|
||||
m_flWidth = width;
|
||||
}
|
||||
|
||||
private:
|
||||
CNetworkVector( m_targetPosition );
|
||||
CNetworkVector( m_controlPosition );
|
||||
CNetworkVar( float, m_scrollRate );
|
||||
CNetworkVar( float, m_flWidth );
|
||||
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_SERVERCLASS();
|
||||
};
|
||||
CEnvQuadraticBeam *CreateQuadraticBeam( const char *pSpriteName, const Vector &start, const Vector &control, const Vector &end, float width, CBaseEntity *pOwner );
|
||||
|
||||
|
||||
#endif // EFFECTS_H
|
||||
147
sp/src/game/server/enginecallback.h
Normal file
147
sp/src/game/server/enginecallback.h
Normal file
@@ -0,0 +1,147 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//===========================================================================//
|
||||
#ifndef ENGINECALLBACK_H
|
||||
#define ENGINECALLBACK_H
|
||||
|
||||
#define EIFACEV21
|
||||
|
||||
#ifndef EIFACE_H
|
||||
#include "eiface.h"
|
||||
#endif
|
||||
#ifdef EIFACEV21
|
||||
#include "eifacev21.h"
|
||||
#endif
|
||||
|
||||
#ifdef EIFACEV21
|
||||
class IVEngineServerV21; // this class from eifacev21.h
|
||||
#endif
|
||||
class IFileSystem; // include filesystem.h
|
||||
class IEngineSound; // include engine/IEngineSound.h
|
||||
class IVEngineServer;
|
||||
class IVoiceServer;
|
||||
class IStaticPropMgrServer;
|
||||
class ISpatialPartition;
|
||||
class IVModelInfo;
|
||||
class IEngineTrace;
|
||||
class IGameEventManager2;
|
||||
class IVDebugOverlay;
|
||||
class IDataCache;
|
||||
class IMDLCache;
|
||||
class IServerEngineTools;
|
||||
class IXboxSystem;
|
||||
class IScriptManager;
|
||||
class CSteamAPIContext;
|
||||
class CSteamGameServerAPIContext;
|
||||
|
||||
#ifdef EIFACEV21
|
||||
extern IVEngineServerV21 *engineV21; // i hate this
|
||||
#endif
|
||||
extern IVEngineServer *engine;
|
||||
extern IVoiceServer *g_pVoiceServer;
|
||||
extern IFileSystem *filesystem;
|
||||
extern IStaticPropMgrServer *staticpropmgr;
|
||||
extern ISpatialPartition *partition;
|
||||
extern IEngineSound *enginesound;
|
||||
extern IVModelInfo *modelinfo;
|
||||
extern IEngineTrace *enginetrace;
|
||||
extern IGameEventManager2 *gameeventmanager;
|
||||
extern IVDebugOverlay *debugoverlay;
|
||||
extern IDataCache *datacache;
|
||||
extern IMDLCache *mdlcache;
|
||||
extern IServerEngineTools *serverenginetools;
|
||||
extern IXboxSystem *xboxsystem; // 360 only
|
||||
extern IScriptManager *scriptmanager;
|
||||
extern CSteamAPIContext *steamapicontext; // available on game clients
|
||||
extern CSteamGameServerAPIContext *steamgameserverapicontext; //available on game servers
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Precaches a material
|
||||
//-----------------------------------------------------------------------------
|
||||
void PrecacheMaterial( const char *pMaterialName );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Converts a previously precached material into an index
|
||||
//-----------------------------------------------------------------------------
|
||||
int GetMaterialIndex( const char *pMaterialName );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Converts a previously precached material index into a string
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *GetMaterialNameFromIndex( int nMaterialIndex );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Precache-related methods for particle systems
|
||||
//-----------------------------------------------------------------------------
|
||||
void PrecacheParticleSystem( const char *pParticleSystemName );
|
||||
int GetParticleSystemIndex( const char *pParticleSystemName );
|
||||
const char *GetParticleSystemNameFromIndex( int nIndex );
|
||||
|
||||
|
||||
class IRecipientFilter;
|
||||
void EntityMessageBegin( CBaseEntity * entity, bool reliable = false );
|
||||
void UserMessageBegin( IRecipientFilter& filter, const char *messagename );
|
||||
void MessageEnd( void );
|
||||
|
||||
// bytewise
|
||||
void MessageWriteByte( int iValue);
|
||||
void MessageWriteChar( int iValue);
|
||||
void MessageWriteShort( int iValue);
|
||||
void MessageWriteWord( int iValue );
|
||||
void MessageWriteLong( int iValue);
|
||||
void MessageWriteFloat( float flValue);
|
||||
void MessageWriteAngle( float flValue);
|
||||
void MessageWriteCoord( float flValue);
|
||||
void MessageWriteVec3Coord( const Vector& rgflValue);
|
||||
void MessageWriteVec3Normal( const Vector& rgflValue);
|
||||
void MessageWriteAngles( const QAngle& rgflValue);
|
||||
void MessageWriteString( const char *sz );
|
||||
void MessageWriteEntity( int iValue);
|
||||
void MessageWriteEHandle( CBaseEntity *pEntity ); //encoded as a long
|
||||
|
||||
|
||||
// bitwise
|
||||
void MessageWriteBool( bool bValue );
|
||||
void MessageWriteUBitLong( unsigned int data, int numbits );
|
||||
void MessageWriteSBitLong( int data, int numbits );
|
||||
void MessageWriteBits( const void *pIn, int nBits );
|
||||
|
||||
#ifndef NO_STEAM
|
||||
|
||||
/// Returns Steam ID, given player index. Returns an invalid SteamID upon
|
||||
/// failure
|
||||
extern CSteamID GetSteamIDForPlayerIndex( int iPlayerIndex );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Bytewise
|
||||
#define WRITE_BYTE (MessageWriteByte)
|
||||
#define WRITE_CHAR (MessageWriteChar)
|
||||
#define WRITE_SHORT (MessageWriteShort)
|
||||
#define WRITE_WORD (MessageWriteWord)
|
||||
#define WRITE_LONG (MessageWriteLong)
|
||||
#define WRITE_FLOAT (MessageWriteFloat)
|
||||
#define WRITE_ANGLE (MessageWriteAngle)
|
||||
#define WRITE_COORD (MessageWriteCoord)
|
||||
#define WRITE_VEC3COORD (MessageWriteVec3Coord)
|
||||
#define WRITE_VEC3NORMAL (MessageWriteVec3Normal)
|
||||
#define WRITE_ANGLES (MessageWriteAngles)
|
||||
#define WRITE_STRING (MessageWriteString)
|
||||
#define WRITE_ENTITY (MessageWriteEntity)
|
||||
#define WRITE_EHANDLE (MessageWriteEHandle)
|
||||
|
||||
// Bitwise
|
||||
#define WRITE_BOOL (MessageWriteBool)
|
||||
#define WRITE_UBITLONG (MessageWriteUBitLong)
|
||||
#define WRITE_SBITLONG (MessageWriteSBitLong)
|
||||
#define WRITE_BITS (MessageWriteBits)
|
||||
|
||||
#endif //ENGINECALLBACK_H
|
||||
458
sp/src/game/server/entity_tools_server.cpp
Normal file
458
sp/src/game/server/entity_tools_server.cpp
Normal file
@@ -0,0 +1,458 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
#include "cbase.h"
|
||||
#include "const.h"
|
||||
#include "toolframework/itoolentity.h"
|
||||
#include "entitylist.h"
|
||||
#include "toolframework/itoolsystem.h"
|
||||
#include "KeyValues.h"
|
||||
#include "icliententity.h"
|
||||
#include "iserverentity.h"
|
||||
#include "sceneentity.h"
|
||||
#include "particles/particles.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Interface from engine to tools for manipulating entities
|
||||
//-----------------------------------------------------------------------------
|
||||
class CServerTools : public IServerTools
|
||||
{
|
||||
public:
|
||||
// Inherited from IServerTools
|
||||
virtual IServerEntity *GetIServerEntity( IClientEntity *pClientEntity );
|
||||
virtual bool GetPlayerPosition( Vector &org, QAngle &ang, IClientEntity *pClientPlayer = NULL );
|
||||
virtual bool SnapPlayerToPosition( const Vector &org, const QAngle &ang, IClientEntity *pClientPlayer = NULL );
|
||||
virtual int GetPlayerFOV( IClientEntity *pClientPlayer = NULL );
|
||||
virtual bool SetPlayerFOV( int fov, IClientEntity *pClientPlayer = NULL );
|
||||
virtual bool IsInNoClipMode( IClientEntity *pClientPlayer = NULL );
|
||||
virtual CBaseEntity *FirstEntity( void );
|
||||
virtual CBaseEntity *NextEntity( CBaseEntity *pEntity );
|
||||
virtual CBaseEntity *FindEntityByHammerID( int iHammerID );
|
||||
virtual bool GetKeyValue( CBaseEntity *pEntity, const char *szField, char *szValue, int iMaxLen );
|
||||
virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, const char *szValue );
|
||||
virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, float flValue );
|
||||
virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, const Vector &vecValue );
|
||||
virtual CBaseEntity *CreateEntityByName( const char *szClassName );
|
||||
virtual void DispatchSpawn( CBaseEntity *pEntity );
|
||||
virtual void ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen );
|
||||
virtual void AddOriginToPVS( const Vector &org );
|
||||
virtual void MoveEngineViewTo( const Vector &vPos, const QAngle &vAngles );
|
||||
virtual bool DestroyEntityByHammerId( int iHammerID );
|
||||
virtual CBaseEntity *GetBaseEntityByEntIndex( int iEntIndex );
|
||||
virtual void RemoveEntity( CBaseEntity *pEntity );
|
||||
virtual void RemoveEntityImmediate( CBaseEntity *pEntity );
|
||||
virtual IEntityFactoryDictionary *GetEntityFactoryDictionary( void );
|
||||
virtual void SetMoveType( CBaseEntity *pEntity, int val );
|
||||
virtual void SetMoveType( CBaseEntity *pEntity, int val, int moveCollide );
|
||||
virtual void ResetSequence( CBaseAnimating *pEntity, int nSequence );
|
||||
virtual void ResetSequenceInfo( CBaseAnimating *pEntity );
|
||||
virtual void ClearMultiDamage( void );
|
||||
virtual void ApplyMultiDamage( void );
|
||||
virtual void AddMultiDamage( const CTakeDamageInfo &pTakeDamageInfo, CBaseEntity *pEntity );
|
||||
virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore );
|
||||
virtual ITempEntsSystem *GetTempEntsSystem( void );
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Singleton
|
||||
//-----------------------------------------------------------------------------
|
||||
static CServerTools g_ServerTools;
|
||||
|
||||
// VSERVERTOOLS_INTERFACE_VERSION_1 is compatible with the latest since we're only adding things to the end, so expose that as well.
|
||||
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerTools, IServerTools001, VSERVERTOOLS_INTERFACE_VERSION_1, g_ServerTools );
|
||||
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerTools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION, g_ServerTools );
|
||||
|
||||
// When bumping the version to this interface, check that our assumption is still valid and expose the older version in the same way
|
||||
COMPILE_TIME_ASSERT( VSERVERTOOLS_INTERFACE_VERSION_INT == 2 );
|
||||
|
||||
|
||||
IServerEntity *CServerTools::GetIServerEntity( IClientEntity *pClientEntity )
|
||||
{
|
||||
if ( pClientEntity == NULL )
|
||||
return NULL;
|
||||
|
||||
CBaseHandle ehandle = pClientEntity->GetRefEHandle();
|
||||
if ( ehandle.GetEntryIndex() >= MAX_EDICTS )
|
||||
return NULL; // the first MAX_EDICTS entities are networked, the rest are client or server only
|
||||
|
||||
#if 0
|
||||
// this fails, since the server entities have extra bits in their serial numbers,
|
||||
// since 20 bits are reserved for serial numbers, except for networked entities, which are restricted to 10
|
||||
|
||||
// Brian believes that everything should just restrict itself to 10 to make things simpler,
|
||||
// so if/when he changes NUM_SERIAL_NUM_BITS to 10, we can switch back to this simpler code
|
||||
|
||||
IServerNetworkable *pNet = gEntList.GetServerNetworkable( ehandle );
|
||||
if ( pNet == NULL )
|
||||
return NULL;
|
||||
|
||||
CBaseEntity *pServerEnt = pNet->GetBaseEntity();
|
||||
return pServerEnt;
|
||||
#else
|
||||
IHandleEntity *pEnt = gEntList.LookupEntityByNetworkIndex( ehandle.GetEntryIndex() );
|
||||
if ( pEnt == NULL )
|
||||
return NULL;
|
||||
|
||||
CBaseHandle h = gEntList.GetNetworkableHandle( ehandle.GetEntryIndex() );
|
||||
const int mask = ( 1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS ) - 1;
|
||||
if ( !h.IsValid() || ( ( h.GetSerialNumber() & mask ) != ( ehandle.GetSerialNumber() & mask ) ) )
|
||||
return NULL;
|
||||
|
||||
IServerUnknown *pUnk = static_cast< IServerUnknown* >( pEnt );
|
||||
return pUnk->GetBaseEntity();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CServerTools::GetPlayerPosition( Vector &org, QAngle &ang, IClientEntity *pClientPlayer )
|
||||
{
|
||||
IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
|
||||
CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
|
||||
if ( pPlayer == NULL )
|
||||
return false;
|
||||
|
||||
org = pPlayer->EyePosition();
|
||||
ang = pPlayer->EyeAngles();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CServerTools::SnapPlayerToPosition( const Vector &org, const QAngle &ang, IClientEntity *pClientPlayer )
|
||||
{
|
||||
IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
|
||||
CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
|
||||
if ( pPlayer == NULL )
|
||||
return false;
|
||||
|
||||
pPlayer->SetAbsOrigin( org - pPlayer->GetViewOffset() );
|
||||
pPlayer->SnapEyeAngles( ang );
|
||||
|
||||
// Disengage from hierarchy
|
||||
pPlayer->SetParent( NULL );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CServerTools::GetPlayerFOV( IClientEntity *pClientPlayer )
|
||||
{
|
||||
IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
|
||||
CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
|
||||
if ( pPlayer == NULL )
|
||||
return 0;
|
||||
|
||||
return pPlayer->GetFOV();
|
||||
}
|
||||
|
||||
bool CServerTools::SetPlayerFOV( int fov, IClientEntity *pClientPlayer )
|
||||
{
|
||||
IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
|
||||
CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
|
||||
if ( pPlayer == NULL )
|
||||
return false;
|
||||
|
||||
pPlayer->SetDefaultFOV( fov );
|
||||
CBaseEntity *pFOVOwner = pPlayer->GetFOVOwner();
|
||||
return pPlayer->SetFOV( pFOVOwner ? pFOVOwner : pPlayer, fov );
|
||||
}
|
||||
|
||||
bool CServerTools::IsInNoClipMode( IClientEntity *pClientPlayer )
|
||||
{
|
||||
IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
|
||||
CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
|
||||
if ( pPlayer == NULL )
|
||||
return true;
|
||||
|
||||
return pPlayer->GetMoveType() == MOVETYPE_NOCLIP;
|
||||
}
|
||||
|
||||
CBaseEntity *CServerTools::FirstEntity( void )
|
||||
{
|
||||
return gEntList.FirstEnt();
|
||||
}
|
||||
|
||||
CBaseEntity *CServerTools::NextEntity( CBaseEntity *pEntity )
|
||||
{
|
||||
CBaseEntity *pEnt;
|
||||
|
||||
if ( pEntity == NULL )
|
||||
{
|
||||
pEnt = gEntList.FirstEnt();
|
||||
}
|
||||
else
|
||||
{
|
||||
pEnt = gEntList.NextEnt( (CBaseEntity *)pEntity );
|
||||
}
|
||||
return pEnt;
|
||||
}
|
||||
|
||||
CBaseEntity *CServerTools::FindEntityByHammerID( int iHammerID )
|
||||
{
|
||||
CBaseEntity *pEntity = gEntList.FirstEnt();
|
||||
|
||||
while (pEntity)
|
||||
{
|
||||
if (pEntity->m_iHammerID == iHammerID)
|
||||
return pEntity;
|
||||
pEntity = gEntList.NextEnt( pEntity );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CServerTools::GetKeyValue( CBaseEntity *pEntity, const char *szField, char *szValue, int iMaxLen )
|
||||
{
|
||||
return pEntity->GetKeyValue( szField, szValue, iMaxLen );
|
||||
}
|
||||
|
||||
bool CServerTools::SetKeyValue( CBaseEntity *pEntity, const char *szField, const char *szValue )
|
||||
{
|
||||
return pEntity->KeyValue( szField, szValue );
|
||||
}
|
||||
|
||||
bool CServerTools::SetKeyValue( CBaseEntity *pEntity, const char *szField, float flValue )
|
||||
{
|
||||
return pEntity->KeyValue( szField, flValue );
|
||||
}
|
||||
|
||||
bool CServerTools::SetKeyValue( CBaseEntity *pEntity, const char *szField, const Vector &vecValue )
|
||||
{
|
||||
return pEntity->KeyValue( szField, vecValue );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// entity spawning
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseEntity *CServerTools::CreateEntityByName( const char *szClassName )
|
||||
{
|
||||
return ::CreateEntityByName( szClassName );
|
||||
}
|
||||
|
||||
void CServerTools::DispatchSpawn( CBaseEntity *pEntity )
|
||||
{
|
||||
::DispatchSpawn( pEntity );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Reload particle definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
void CServerTools::ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen )
|
||||
{
|
||||
// FIXME: Use file name to determine if we care about this data
|
||||
CUtlBuffer buf( pBufData, nLen, CUtlBuffer::READ_ONLY );
|
||||
g_pParticleSystemMgr->ReadParticleConfigFile( buf, true );
|
||||
}
|
||||
|
||||
void CServerTools::AddOriginToPVS( const Vector &org )
|
||||
{
|
||||
engine->AddOriginToPVS( org );
|
||||
}
|
||||
|
||||
void CServerTools::MoveEngineViewTo( const Vector &vPos, const QAngle &vAngles )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_GetListenServerHost();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
extern void EnableNoClip( CBasePlayer *pPlayer );
|
||||
EnableNoClip( pPlayer );
|
||||
|
||||
Vector zOffset = pPlayer->EyePosition() - pPlayer->GetAbsOrigin();
|
||||
|
||||
pPlayer->SetAbsOrigin( vPos - zOffset );
|
||||
pPlayer->SnapEyeAngles( vAngles );
|
||||
}
|
||||
|
||||
bool CServerTools::DestroyEntityByHammerId( int iHammerID )
|
||||
{
|
||||
CBaseEntity *pEntity = (CBaseEntity*)FindEntityByHammerID( iHammerID );
|
||||
if ( !pEntity )
|
||||
return false;
|
||||
|
||||
UTIL_Remove( pEntity );
|
||||
return true;
|
||||
}
|
||||
|
||||
void CServerTools::RemoveEntity( CBaseEntity *pEntity )
|
||||
{
|
||||
UTIL_Remove( pEntity );
|
||||
}
|
||||
|
||||
void CServerTools::RemoveEntityImmediate( CBaseEntity *pEntity )
|
||||
{
|
||||
UTIL_RemoveImmediate( pEntity );
|
||||
}
|
||||
|
||||
CBaseEntity *CServerTools::GetBaseEntityByEntIndex( int iEntIndex )
|
||||
{
|
||||
edict_t *pEdict = INDEXENT( iEntIndex );
|
||||
if ( pEdict )
|
||||
return CBaseEntity::Instance( pEdict );
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IEntityFactoryDictionary *CServerTools::GetEntityFactoryDictionary( void )
|
||||
{
|
||||
return ::EntityFactoryDictionary();
|
||||
}
|
||||
|
||||
|
||||
void CServerTools::SetMoveType( CBaseEntity *pEntity, int val )
|
||||
{
|
||||
pEntity->SetMoveType( (MoveType_t)val );
|
||||
}
|
||||
|
||||
void CServerTools::SetMoveType( CBaseEntity *pEntity, int val, int moveCollide )
|
||||
{
|
||||
pEntity->SetMoveType( (MoveType_t)val, (MoveCollide_t)moveCollide );
|
||||
}
|
||||
|
||||
void CServerTools::ResetSequence( CBaseAnimating *pEntity, int nSequence )
|
||||
{
|
||||
pEntity->ResetSequence( nSequence );
|
||||
}
|
||||
|
||||
void CServerTools::ResetSequenceInfo( CBaseAnimating *pEntity )
|
||||
{
|
||||
pEntity->ResetSequenceInfo();
|
||||
}
|
||||
|
||||
|
||||
void CServerTools::ClearMultiDamage( void )
|
||||
{
|
||||
::ClearMultiDamage();
|
||||
}
|
||||
|
||||
void CServerTools::ApplyMultiDamage( void )
|
||||
{
|
||||
::ApplyMultiDamage();
|
||||
}
|
||||
|
||||
void CServerTools::AddMultiDamage( const CTakeDamageInfo &pTakeDamageInfo, CBaseEntity *pEntity )
|
||||
{
|
||||
::AddMultiDamage( pTakeDamageInfo, pEntity );
|
||||
}
|
||||
|
||||
void CServerTools::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore )
|
||||
{
|
||||
::RadiusDamage( info, vecSrc, flRadius, iClassIgnore, pEntityIgnore );
|
||||
}
|
||||
|
||||
|
||||
ITempEntsSystem *CServerTools::GetTempEntsSystem( void )
|
||||
{
|
||||
return (ITempEntsSystem *)te;
|
||||
}
|
||||
|
||||
|
||||
// Interface from engine to tools for manipulating entities
|
||||
class CServerChoreoTools : public IServerChoreoTools
|
||||
{
|
||||
public:
|
||||
// Iterates through ALL entities (separate list for client vs. server)
|
||||
virtual EntitySearchResult NextChoreoEntity( EntitySearchResult currentEnt )
|
||||
{
|
||||
CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( currentEnt );
|
||||
ent = gEntList.FindEntityByClassname( ent, "logic_choreographed_scene" );
|
||||
return reinterpret_cast< EntitySearchResult >( ent );
|
||||
}
|
||||
|
||||
virtual const char *GetSceneFile( EntitySearchResult sr )
|
||||
{
|
||||
CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( sr );
|
||||
if ( !sr )
|
||||
return "";
|
||||
|
||||
if ( Q_stricmp( ent->GetClassname(), "logic_choreographed_scene" ) )
|
||||
return "";
|
||||
|
||||
return GetSceneFilename( ent );
|
||||
}
|
||||
|
||||
// For interactive editing
|
||||
virtual int GetEntIndex( EntitySearchResult sr )
|
||||
{
|
||||
CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( sr );
|
||||
if ( !ent )
|
||||
return -1;
|
||||
|
||||
return ent->entindex();
|
||||
}
|
||||
|
||||
virtual void ReloadSceneFromDisk( int entindex )
|
||||
{
|
||||
CBaseEntity *ent = CBaseEntity::Instance( entindex );
|
||||
if ( !ent )
|
||||
return;
|
||||
|
||||
::ReloadSceneFromDisk( ent );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static CServerChoreoTools g_ServerChoreoTools;
|
||||
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerChoreoTools, IServerChoreoTools, VSERVERCHOREOTOOLS_INTERFACE_VERSION, g_ServerChoreoTools );
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Applies keyvalues to the entity by hammer ID.
|
||||
//------------------------------------------------------------------------------
|
||||
void CC_Ent_Keyvalue( const CCommand &args )
|
||||
{
|
||||
// Must have an odd number of arguments.
|
||||
if ( ( args.ArgC() < 4 ) || ( args.ArgC() & 1 ) )
|
||||
{
|
||||
Msg( "Format: ent_keyvalue <entity id> \"key1\" \"value1\" \"key2\" \"value2\" ... \"keyN\" \"valueN\"\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
|
||||
CBaseEntity *pEnt;
|
||||
if ( FStrEq( args[1], "" ) || FStrEq( args[1], "!picker" ) )
|
||||
{
|
||||
if (!pPlayer)
|
||||
return;
|
||||
|
||||
extern CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer );
|
||||
pEnt = FindPickerEntity( pPlayer );
|
||||
|
||||
if ( !pEnt )
|
||||
{
|
||||
ClientPrint( pPlayer, HUD_PRINTCONSOLE, "No entity in front of player.\n" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ( FStrEq( args[1], "!self" ) || FStrEq( args[1], "!caller" ) || FStrEq( args[1], "!activator" ) )
|
||||
{
|
||||
if (!pPlayer)
|
||||
return;
|
||||
|
||||
pEnt = pPlayer;
|
||||
}
|
||||
else
|
||||
{
|
||||
int nID = atoi( args[1] );
|
||||
|
||||
pEnt = g_ServerTools.FindEntityByHammerID( nID );
|
||||
if ( !pEnt )
|
||||
{
|
||||
Msg( "Entity ID %d not found.\n", nID );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int nArg = 2;
|
||||
while ( nArg < args.ArgC() )
|
||||
{
|
||||
const char *pszKey = args[ nArg ];
|
||||
const char *pszValue = args[ nArg + 1 ];
|
||||
nArg += 2;
|
||||
|
||||
g_ServerTools.SetKeyValue( pEnt, pszKey, pszValue );
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand ent_keyvalue("ent_keyvalue", CC_Ent_Keyvalue, "Applies the comma delimited key=value pairs to the entity with the given Hammer ID.\n\tFormat: ent_keyvalue <entity id> <key1> <value1> <key2> <value2> ... <keyN> <valueN>\n", FCVAR_CHEAT);
|
||||
33
sp/src/game/server/entityapi.h
Normal file
33
sp/src/game/server/entityapi.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#ifndef ENTITYAPI_H
|
||||
#define ENTITYAPI_H
|
||||
|
||||
|
||||
class SendTable;
|
||||
|
||||
extern void LoadMapEntities( const char *pMapEntities );
|
||||
extern void DispatchObjectCollisionBox( edict_t *pent );
|
||||
extern float DispatchObjectPhysicsVelocity( edict_t *pent, float moveTime );
|
||||
extern ServerClass* DispatchGetObjectServerClass(edict_t *pent);
|
||||
extern ServerClass* GetAllServerClasses();
|
||||
extern void SaveWriteFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount );
|
||||
extern void SaveReadFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount );
|
||||
extern void SaveGlobalState( CSaveRestoreData *pSaveData );
|
||||
extern void RestoreGlobalState( CSaveRestoreData *pSaveData );
|
||||
extern void ResetGlobalState( void );
|
||||
extern CSaveRestoreData *SaveInit( int size );
|
||||
extern int CreateEntityTransitionList( CSaveRestoreData *pSaveData, int levelMask );
|
||||
extern void ClearEntities( void );
|
||||
extern void FreeContainingEntity( edict_t *ed );
|
||||
|
||||
class ISaveRestoreBlockHandler;
|
||||
ISaveRestoreBlockHandler *GetEntitySaveRestoreBlockHandler();
|
||||
|
||||
|
||||
#endif // ENTITYAPI_H
|
||||
76
sp/src/game/server/entityblocker.cpp
Normal file
76
sp/src/game/server/entityblocker.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "entityblocker.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
LINK_ENTITY_TO_CLASS( entity_blocker, CEntityBlocker );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &origin -
|
||||
// &mins -
|
||||
// &maxs -
|
||||
// NULL -
|
||||
// Output : CEntityBlocker
|
||||
//-----------------------------------------------------------------------------
|
||||
CEntityBlocker *CEntityBlocker::Create( const Vector &origin, const Vector &mins, const Vector &maxs, CBaseEntity *pOwner, bool bBlockPhysics )
|
||||
{
|
||||
CEntityBlocker *pBlocker = (CEntityBlocker *) CBaseEntity::Create( "entity_blocker", origin, vec3_angle, pOwner );
|
||||
|
||||
if ( pBlocker != NULL )
|
||||
{
|
||||
pBlocker->SetSize( mins, maxs );
|
||||
if ( bBlockPhysics )
|
||||
{
|
||||
pBlocker->VPhysicsInitStatic();
|
||||
}
|
||||
}
|
||||
|
||||
return pBlocker;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEntityBlocker::Spawn( void )
|
||||
{
|
||||
SetSolid( SOLID_BBOX );
|
||||
AddSolidFlags( FSOLID_CUSTOMRAYTEST );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Entity blockers don't block tracelines so they don't screw up weapon fire, etc
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CEntityBlocker::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CC_Test_Entity_Blocker( void )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_GetCommandClient();
|
||||
Vector vecForward;
|
||||
pPlayer->GetVectors( &vecForward, NULL, NULL );
|
||||
|
||||
trace_t tr;
|
||||
Vector vecOrigin = pPlayer->GetAbsOrigin() + (vecForward * 256);
|
||||
UTIL_TraceHull( vecOrigin + Vector(0,0,256), vecOrigin - Vector(0,0,256), VEC_HULL_MIN_SCALED( pPlayer ), VEC_HULL_MAX_SCALED( pPlayer ), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr );
|
||||
if ( !tr.allsolid && !tr.startsolid )
|
||||
{
|
||||
CEntityBlocker::Create( tr.endpos, VEC_HULL_MIN_SCALED( pPlayer ), VEC_HULL_MAX_SCALED( pPlayer ), NULL, true );
|
||||
NDebugOverlay::Box( tr.endpos, VEC_HULL_MIN_SCALED( pPlayer ), VEC_HULL_MAX_SCALED( pPlayer ), 0, 255, 0, 64, 1000.0 );
|
||||
}
|
||||
}
|
||||
static ConCommand test_entity_blocker("test_entity_blocker", CC_Test_Entity_Blocker, "Test command that drops an entity blocker out in front of the player.", FCVAR_CHEAT );
|
||||
28
sp/src/game/server/entityblocker.h
Normal file
28
sp/src/game/server/entityblocker.h
Normal file
@@ -0,0 +1,28 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef ENTITYBLOCKER_H
|
||||
#define ENTITYBLOCKER_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//==================================================================================================================
|
||||
// Entity Blocker
|
||||
//==================================================================================================================
|
||||
class CEntityBlocker : public CBaseEntity
|
||||
{
|
||||
DECLARE_CLASS( CEntityBlocker, CBaseEntity );
|
||||
|
||||
public:
|
||||
|
||||
static CEntityBlocker *Create( const Vector &origin, const Vector &mins, const Vector &maxs, CBaseEntity *pOwner = NULL, bool bBlockPhysics = false );
|
||||
|
||||
void Spawn( void );
|
||||
bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace );
|
||||
};
|
||||
|
||||
#endif // ENTITYBLOCKER_H
|
||||
50
sp/src/game/server/entityinput.h
Normal file
50
sp/src/game/server/entityinput.h
Normal file
@@ -0,0 +1,50 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef INPUTVAR_H
|
||||
#define INPUTVAR_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "baseentity.h"
|
||||
#include "entitylist.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Used to request a value, or a set of values, from a set of entities.
|
||||
// used when a multi-input variable needs to refresh it's inputs
|
||||
//-----------------------------------------------------------------------------
|
||||
class CMultiInputVar
|
||||
{
|
||||
public:
|
||||
CMultiInputVar() : m_InputList(NULL) {}
|
||||
~CMultiInputVar();
|
||||
|
||||
struct inputitem_t
|
||||
{
|
||||
variant_t value; // local copy of variable (maybe make this a variant?)
|
||||
int outputID; // the ID number of the output that sent this
|
||||
inputitem_t *next;
|
||||
|
||||
// allocate and free from MPool memory
|
||||
static void *operator new( size_t stAllocBlock );
|
||||
static void *operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine );
|
||||
static void operator delete( void *pMem );
|
||||
static void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine ) { operator delete(pMem); }
|
||||
};
|
||||
|
||||
inputitem_t *m_InputList; // list of data
|
||||
int m_bUpdatedThisFrame;
|
||||
|
||||
void AddValue( variant_t newVal, int outputID );
|
||||
|
||||
DECLARE_SIMPLE_DATADESC();
|
||||
};
|
||||
|
||||
#endif // INPUTVAR_H
|
||||
1716
sp/src/game/server/entitylist.cpp
Normal file
1716
sp/src/game/server/entitylist.cpp
Normal file
File diff suppressed because it is too large
Load Diff
382
sp/src/game/server/entitylist.h
Normal file
382
sp/src/game/server/entitylist.h
Normal file
@@ -0,0 +1,382 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef ENTITYLIST_H
|
||||
#define ENTITYLIST_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "baseentity.h"
|
||||
|
||||
class IEntityListener;
|
||||
|
||||
abstract_class CBaseEntityClassList
|
||||
{
|
||||
public:
|
||||
CBaseEntityClassList();
|
||||
~CBaseEntityClassList();
|
||||
virtual void LevelShutdownPostEntity() = 0;
|
||||
|
||||
CBaseEntityClassList *m_pNextClassList;
|
||||
};
|
||||
|
||||
template< class T >
|
||||
class CEntityClassList : public CBaseEntityClassList
|
||||
{
|
||||
public:
|
||||
virtual void LevelShutdownPostEntity() { m_pClassList = NULL; }
|
||||
|
||||
void Insert( T *pEntity )
|
||||
{
|
||||
pEntity->m_pNext = m_pClassList;
|
||||
m_pClassList = pEntity;
|
||||
}
|
||||
|
||||
void Remove( T *pEntity )
|
||||
{
|
||||
T **pPrev = &m_pClassList;
|
||||
T *pCur = *pPrev;
|
||||
while ( pCur )
|
||||
{
|
||||
if ( pCur == pEntity )
|
||||
{
|
||||
*pPrev = pCur->m_pNext;
|
||||
return;
|
||||
}
|
||||
pPrev = &pCur->m_pNext;
|
||||
pCur = *pPrev;
|
||||
}
|
||||
}
|
||||
|
||||
static T *m_pClassList;
|
||||
};
|
||||
|
||||
// Derive a class from this if you want to filter entity list searches
|
||||
abstract_class IEntityFindFilter
|
||||
{
|
||||
public:
|
||||
virtual bool ShouldFindEntity( CBaseEntity *pEntity ) = 0;
|
||||
virtual CBaseEntity *GetFilterResult( void ) = 0;
|
||||
};
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Returns false every time. Created for some sick hack involving FindEntityProcedural looking at FindNamedEntity.
|
||||
class CNullEntityFilter : public IEntityFindFilter
|
||||
{
|
||||
public:
|
||||
virtual bool ShouldFindEntity( CBaseEntity *pEntity ) { return false; }
|
||||
virtual CBaseEntity *GetFilterResult( void ) { return NULL; }
|
||||
};
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: a global list of all the entities in the game. All iteration through
|
||||
// entities is done through this object.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CGlobalEntityList : public CBaseEntityList
|
||||
{
|
||||
public:
|
||||
private:
|
||||
int m_iHighestEnt; // the topmost used array index
|
||||
int m_iNumEnts;
|
||||
int m_iNumEdicts;
|
||||
|
||||
bool m_bClearingEntities;
|
||||
CUtlVector<IEntityListener *> m_entityListeners;
|
||||
|
||||
public:
|
||||
IServerNetworkable* GetServerNetworkable( CBaseHandle hEnt ) const;
|
||||
CBaseNetworkable* GetBaseNetworkable( CBaseHandle hEnt ) const;
|
||||
CBaseEntity* GetBaseEntity( CBaseHandle hEnt ) const;
|
||||
edict_t* GetEdict( CBaseHandle hEnt ) const;
|
||||
|
||||
int NumberOfEntities( void );
|
||||
int NumberOfEdicts( void );
|
||||
|
||||
// mark an entity as deleted
|
||||
void AddToDeleteList( IServerNetworkable *ent );
|
||||
// call this before and after each frame to delete all of the marked entities.
|
||||
void CleanupDeleteList( void );
|
||||
int ResetDeleteList( void );
|
||||
|
||||
// frees all entities in the game
|
||||
void Clear( void );
|
||||
|
||||
// Returns true while in the Clear() call.
|
||||
bool IsClearingEntities() {return m_bClearingEntities;}
|
||||
|
||||
// add a class that gets notified of entity events
|
||||
void AddListenerEntity( IEntityListener *pListener );
|
||||
void RemoveListenerEntity( IEntityListener *pListener );
|
||||
|
||||
void ReportEntityFlagsChanged( CBaseEntity *pEntity, unsigned int flagsOld, unsigned int flagsNow );
|
||||
|
||||
// entity is about to be removed, notify the listeners
|
||||
void NotifyCreateEntity( CBaseEntity *pEnt );
|
||||
void NotifySpawn( CBaseEntity *pEnt );
|
||||
void NotifyRemoveEntity( CBaseHandle hEnt );
|
||||
// iteration functions
|
||||
|
||||
// returns the next entity after pCurrentEnt; if pCurrentEnt is NULL, return the first entity
|
||||
CBaseEntity *NextEnt( CBaseEntity *pCurrentEnt );
|
||||
CBaseEntity *FirstEnt() { return NextEnt(NULL); }
|
||||
|
||||
// returns the next entity of the specified class, using RTTI
|
||||
template< class T >
|
||||
T *NextEntByClass( T *start )
|
||||
{
|
||||
for ( CBaseEntity *x = NextEnt( start ); x; x = NextEnt( x ) )
|
||||
{
|
||||
start = dynamic_cast<T*>( x );
|
||||
if ( start )
|
||||
return start;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// search functions
|
||||
bool IsEntityPtr( void *pTest );
|
||||
#ifdef MAPBASE
|
||||
CBaseEntity *FindEntityByClassname( CBaseEntity *pStartEntity, const char *szName, IEntityFindFilter *pFilter = NULL );
|
||||
#else
|
||||
CBaseEntity *FindEntityByClassname( CBaseEntity *pStartEntity, const char *szName );
|
||||
#endif
|
||||
CBaseEntity *FindEntityByName( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL, IEntityFindFilter *pFilter = NULL );
|
||||
CBaseEntity *FindEntityByName( CBaseEntity *pStartEntity, string_t iszName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL, IEntityFindFilter *pFilter = NULL )
|
||||
{
|
||||
return FindEntityByName( pStartEntity, STRING(iszName), pSearchingEntity, pActivator, pCaller, pFilter );
|
||||
}
|
||||
CBaseEntity *FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius );
|
||||
CBaseEntity *FindEntityByTarget( CBaseEntity *pStartEntity, const char *szName );
|
||||
CBaseEntity *FindEntityByModel( CBaseEntity *pStartEntity, const char *szModelName );
|
||||
|
||||
CBaseEntity *FindEntityByNameNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
||||
CBaseEntity *FindEntityByNameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
||||
CBaseEntity *FindEntityByClassnameNearest( const char *szName, const Vector &vecSrc, float flRadius );
|
||||
CBaseEntity *FindEntityByClassnameWithin( CBaseEntity *pStartEntity , const char *szName, const Vector &vecSrc, float flRadius );
|
||||
CBaseEntity *FindEntityByClassnameWithin( CBaseEntity *pStartEntity , const char *szName, const Vector &vecMins, const Vector &vecMaxs );
|
||||
|
||||
#ifdef MAPBASE
|
||||
CBaseEntity *FindEntityGeneric( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL, IEntityFindFilter *pFilter = NULL );
|
||||
#else
|
||||
CBaseEntity *FindEntityGeneric( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
||||
#endif
|
||||
CBaseEntity *FindEntityGenericWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
||||
CBaseEntity *FindEntityGenericNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
||||
|
||||
CBaseEntity *FindEntityNearestFacing( const Vector &origin, const Vector &facing, float threshold);
|
||||
CBaseEntity *FindEntityClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, char *classname);
|
||||
CBaseEntity *FindEntityByNetname( CBaseEntity *pStartEntity, const char *szModelName );
|
||||
|
||||
CBaseEntity *FindEntityProcedural( const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
||||
|
||||
CGlobalEntityList();
|
||||
|
||||
// CBaseEntityList overrides.
|
||||
protected:
|
||||
|
||||
virtual void OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle );
|
||||
virtual void OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle );
|
||||
|
||||
};
|
||||
|
||||
extern CGlobalEntityList gEntList;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inlines.
|
||||
//-----------------------------------------------------------------------------
|
||||
inline edict_t* CGlobalEntityList::GetEdict( CBaseHandle hEnt ) const
|
||||
{
|
||||
IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt ));
|
||||
if ( pUnk )
|
||||
return pUnk->GetNetworkable()->GetEdict();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline CBaseNetworkable* CGlobalEntityList::GetBaseNetworkable( CBaseHandle hEnt ) const
|
||||
{
|
||||
IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt ));
|
||||
if ( pUnk )
|
||||
return pUnk->GetNetworkable()->GetBaseNetworkable();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline IServerNetworkable* CGlobalEntityList::GetServerNetworkable( CBaseHandle hEnt ) const
|
||||
{
|
||||
IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt ));
|
||||
if ( pUnk )
|
||||
return pUnk->GetNetworkable();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline CBaseEntity* CGlobalEntityList::GetBaseEntity( CBaseHandle hEnt ) const
|
||||
{
|
||||
IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt ));
|
||||
if ( pUnk )
|
||||
return pUnk->GetBaseEntity();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Common finds
|
||||
#if 0
|
||||
|
||||
template <class ENT_TYPE>
|
||||
inline bool FindEntityByName( const char *pszName, ENT_TYPE **ppResult)
|
||||
{
|
||||
CBaseEntity *pBaseEntity = gEntList.FindEntityByName( NULL, pszName );
|
||||
|
||||
if ( pBaseEntity )
|
||||
*ppResult = dynamic_cast<ENT_TYPE *>( pBaseEntity );
|
||||
else
|
||||
*ppResult = NULL;
|
||||
|
||||
return ( *ppResult != NULL );
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool FindEntityByName<CBaseEntity>( const char *pszName, CBaseEntity **ppResult)
|
||||
{
|
||||
*ppResult = gEntList.FindEntityByName( NULL, pszName );
|
||||
return ( *ppResult != NULL );
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool FindEntityByName<CAI_BaseNPC>( const char *pszName, CAI_BaseNPC **ppResult)
|
||||
{
|
||||
CBaseEntity *pBaseEntity = gEntList.FindEntityByName( NULL, pszName );
|
||||
|
||||
if ( pBaseEntity )
|
||||
*ppResult = pBaseEntity->MyNPCPointer();
|
||||
else
|
||||
*ppResult = NULL;
|
||||
|
||||
return ( *ppResult != NULL );
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Simple object for storing a list of objects
|
||||
//-----------------------------------------------------------------------------
|
||||
struct entitem_t
|
||||
{
|
||||
EHANDLE hEnt;
|
||||
struct entitem_t *pNext;
|
||||
|
||||
// uses pool memory
|
||||
static void* operator new( size_t stAllocateBlock );
|
||||
static void *operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine );
|
||||
static void operator delete( void *pMem );
|
||||
static void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine ) { operator delete( pMem ); }
|
||||
};
|
||||
|
||||
class CEntityList
|
||||
{
|
||||
public:
|
||||
CEntityList();
|
||||
~CEntityList();
|
||||
|
||||
int m_iNumItems;
|
||||
entitem_t *m_pItemList; // null terminated singly-linked list
|
||||
|
||||
void AddEntity( CBaseEntity * );
|
||||
void DeleteEntity( CBaseEntity * );
|
||||
};
|
||||
|
||||
enum notify_system_event_t
|
||||
{
|
||||
NOTIFY_EVENT_TELEPORT = 0,
|
||||
NOTIFY_EVENT_DESTROY,
|
||||
};
|
||||
|
||||
struct notify_teleport_params_t
|
||||
{
|
||||
Vector prevOrigin;
|
||||
QAngle prevAngles;
|
||||
bool physicsRotate;
|
||||
};
|
||||
|
||||
struct notify_destroy_params_t
|
||||
{
|
||||
};
|
||||
|
||||
struct notify_system_event_params_t
|
||||
{
|
||||
union
|
||||
{
|
||||
const notify_teleport_params_t *pTeleport;
|
||||
const notify_destroy_params_t *pDestroy;
|
||||
};
|
||||
notify_system_event_params_t( const notify_teleport_params_t *pInTeleport ) { pTeleport = pInTeleport; }
|
||||
notify_system_event_params_t( const notify_destroy_params_t *pInDestroy ) { pDestroy = pInDestroy; }
|
||||
};
|
||||
|
||||
|
||||
abstract_class INotify
|
||||
{
|
||||
public:
|
||||
// Add notification for an entity
|
||||
virtual void AddEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ) = 0;
|
||||
|
||||
// Remove notification for an entity
|
||||
virtual void RemoveEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ) = 0;
|
||||
|
||||
// Call the named input in each entity who is watching pEvent's status
|
||||
virtual void ReportNamedEvent( CBaseEntity *pEntity, const char *pEventName ) = 0;
|
||||
|
||||
// System events don't make sense as inputs, so are handled through a generic notify function
|
||||
virtual void ReportSystemEvent( CBaseEntity *pEntity, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ) = 0;
|
||||
|
||||
inline void ReportDestroyEvent( CBaseEntity *pEntity )
|
||||
{
|
||||
notify_destroy_params_t destroy;
|
||||
ReportSystemEvent( pEntity, NOTIFY_EVENT_DESTROY, notify_system_event_params_t(&destroy) );
|
||||
}
|
||||
|
||||
inline void ReportTeleportEvent( CBaseEntity *pEntity, const Vector &prevOrigin, const QAngle &prevAngles, bool physicsRotate )
|
||||
{
|
||||
notify_teleport_params_t teleport;
|
||||
teleport.prevOrigin = prevOrigin;
|
||||
teleport.prevAngles = prevAngles;
|
||||
teleport.physicsRotate = physicsRotate;
|
||||
ReportSystemEvent( pEntity, NOTIFY_EVENT_TELEPORT, notify_system_event_params_t(&teleport) );
|
||||
}
|
||||
|
||||
// Remove this entity from the notify list
|
||||
virtual void ClearEntity( CBaseEntity *pNotify ) = 0;
|
||||
};
|
||||
|
||||
// Implement this class and register with gEntList to receive entity create/delete notification
|
||||
class IEntityListener
|
||||
{
|
||||
public:
|
||||
virtual void OnEntityCreated( CBaseEntity *pEntity ) {};
|
||||
virtual void OnEntitySpawned( CBaseEntity *pEntity ) {};
|
||||
virtual void OnEntityDeleted( CBaseEntity *pEntity ) {};
|
||||
};
|
||||
|
||||
// singleton
|
||||
extern INotify *g_pNotify;
|
||||
|
||||
void EntityTouch_Add( CBaseEntity *pEntity );
|
||||
int AimTarget_ListCount();
|
||||
int AimTarget_ListCopy( CBaseEntity *pList[], int listMax );
|
||||
void AimTarget_ForceRepopulateList();
|
||||
|
||||
void SimThink_EntityChanged( CBaseEntity *pEntity );
|
||||
int SimThink_ListCount();
|
||||
int SimThink_ListCopy( CBaseEntity *pList[], int listMax );
|
||||
|
||||
#endif // ENTITYLIST_H
|
||||
225
sp/src/game/server/entityoutput.h
Normal file
225
sp/src/game/server/entityoutput.h
Normal file
@@ -0,0 +1,225 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Declares basic entity communications classes, for input/output of data
|
||||
// between entities
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef ENTITYOUTPUT_H
|
||||
#define ENTITYOUTPUT_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "baseentity.h"
|
||||
|
||||
|
||||
#define EVENT_FIRE_ALWAYS -1
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A COutputEvent consists of an array of these CEventActions.
|
||||
// Each CEventAction holds the information to fire a single input in
|
||||
// a target entity, after a specific delay.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEventAction
|
||||
{
|
||||
public:
|
||||
CEventAction( const char *ActionData = NULL );
|
||||
|
||||
string_t m_iTarget; // name of the entity(s) to cause the action in
|
||||
string_t m_iTargetInput; // the name of the action to fire
|
||||
string_t m_iParameter; // parameter to send, 0 if none
|
||||
float m_flDelay; // the number of seconds to wait before firing the action
|
||||
int m_nTimesToFire; // The number of times to fire this event, or EVENT_FIRE_ALWAYS.
|
||||
|
||||
int m_iIDStamp; // unique identifier stamp
|
||||
|
||||
static int s_iNextIDStamp;
|
||||
|
||||
CEventAction *m_pNext;
|
||||
|
||||
// allocates memory from engine.MPool/g_EntityListPool
|
||||
static void *operator new( size_t stAllocateBlock );
|
||||
static void *operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine );
|
||||
static void operator delete( void *pMem );
|
||||
static void operator delete( void *pMem , int nBlockUse, const char *pFileName, int nLine ) { operator delete(pMem); }
|
||||
|
||||
DECLARE_SIMPLE_DATADESC();
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Stores a list of connections to other entities, for data/commands to be
|
||||
// communicated along.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBaseEntityOutput
|
||||
{
|
||||
public:
|
||||
~CBaseEntityOutput();
|
||||
|
||||
void ParseEventAction( const char *EventData );
|
||||
void AddEventAction( CEventAction *pEventAction );
|
||||
void RemoveEventAction( CEventAction *pEventAction );
|
||||
|
||||
int Save( ISave &save );
|
||||
int Restore( IRestore &restore, int elementCount );
|
||||
|
||||
int NumberOfElements( void );
|
||||
|
||||
float GetMaxDelay( void );
|
||||
|
||||
fieldtype_t ValueFieldType() { return m_Value.FieldType(); }
|
||||
|
||||
void FireOutput( variant_t Value, CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay = 0 );
|
||||
|
||||
/// Delete every single action in the action list.
|
||||
void DeleteAllElements( void ) ;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Needed for ReplaceOutput, hopefully not bad
|
||||
CEventAction *GetActionList() { return m_ActionList; }
|
||||
void SetActionList(CEventAction *newlist) { m_ActionList = newlist; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
variant_t m_Value;
|
||||
CEventAction *m_ActionList;
|
||||
DECLARE_SIMPLE_DATADESC();
|
||||
|
||||
CBaseEntityOutput() {} // this class cannot be created, only it's children
|
||||
|
||||
private:
|
||||
CBaseEntityOutput( CBaseEntityOutput& ); // protect from accidental copying
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: wraps variant_t data handling in convenient, compiler type-checked template
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class Type, fieldtype_t fieldType >
|
||||
class CEntityOutputTemplate : public CBaseEntityOutput
|
||||
{
|
||||
public:
|
||||
//
|
||||
// Sets an initial value without firing the output.
|
||||
//
|
||||
void Init( Type value )
|
||||
{
|
||||
m_Value.Set( fieldType, &value );
|
||||
}
|
||||
|
||||
//
|
||||
// Sets a value and fires the output.
|
||||
//
|
||||
void Set( Type value, CBaseEntity *pActivator, CBaseEntity *pCaller )
|
||||
{
|
||||
m_Value.Set( fieldType, &value );
|
||||
FireOutput( m_Value, pActivator, pCaller );
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the current value.
|
||||
//
|
||||
Type Get( void )
|
||||
{
|
||||
return *((Type*)&m_Value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Template specializations for type Vector, so we can implement Get, Set, and Init differently.
|
||||
//
|
||||
template<>
|
||||
class CEntityOutputTemplate<class Vector, FIELD_VECTOR> : public CBaseEntityOutput
|
||||
{
|
||||
public:
|
||||
void Init( const Vector &value )
|
||||
{
|
||||
m_Value.SetVector3D( value );
|
||||
}
|
||||
|
||||
void Set( const Vector &value, CBaseEntity *pActivator, CBaseEntity *pCaller )
|
||||
{
|
||||
m_Value.SetVector3D( value );
|
||||
FireOutput( m_Value, pActivator, pCaller );
|
||||
}
|
||||
|
||||
void Get( Vector &vec )
|
||||
{
|
||||
m_Value.Vector3D(vec);
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Shortcut to using QAngles in Vector outputs, makes it look cleaner and allows easy modification
|
||||
void Init( const QAngle &value )
|
||||
{
|
||||
// reinterpret_cast<const Vector&>(value)
|
||||
m_Value.SetAngle3D( value );
|
||||
}
|
||||
|
||||
// Shortcut to using QAngles in Vector outputs, makes it look cleaner and allows easy modification
|
||||
void Set( const QAngle &value, CBaseEntity *pActivator, CBaseEntity *pCaller )
|
||||
{
|
||||
// reinterpret_cast<const Vector&>(value)
|
||||
m_Value.SetAngle3D( value );
|
||||
FireOutput( m_Value, pActivator, pCaller );
|
||||
}
|
||||
|
||||
// Shortcut to using QAngles in Vector outputs, makes it look cleaner and allows easy modification
|
||||
void Get( QAngle &ang )
|
||||
{
|
||||
m_Value.Angle3D(ang);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
class CEntityOutputTemplate<class Vector, FIELD_POSITION_VECTOR> : public CBaseEntityOutput
|
||||
{
|
||||
public:
|
||||
void Init( const Vector &value )
|
||||
{
|
||||
m_Value.SetPositionVector3D( value );
|
||||
}
|
||||
|
||||
void Set( const Vector &value, CBaseEntity *pActivator, CBaseEntity *pCaller )
|
||||
{
|
||||
m_Value.SetPositionVector3D( value );
|
||||
FireOutput( m_Value, pActivator, pCaller );
|
||||
}
|
||||
|
||||
void Get( Vector &vec )
|
||||
{
|
||||
m_Value.Vector3D(vec);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: parameterless entity event
|
||||
//-----------------------------------------------------------------------------
|
||||
class COutputEvent : public CBaseEntityOutput
|
||||
{
|
||||
public:
|
||||
// void Firing, no parameter
|
||||
void FireOutput( CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay = 0 );
|
||||
};
|
||||
|
||||
|
||||
// useful typedefs for allowed output data types
|
||||
typedef CEntityOutputTemplate<variant_t,FIELD_INPUT> COutputVariant;
|
||||
typedef CEntityOutputTemplate<int,FIELD_INTEGER> COutputInt;
|
||||
typedef CEntityOutputTemplate<float,FIELD_FLOAT> COutputFloat;
|
||||
typedef CEntityOutputTemplate<string_t,FIELD_STRING> COutputString;
|
||||
typedef CEntityOutputTemplate<EHANDLE,FIELD_EHANDLE> COutputEHANDLE;
|
||||
typedef CEntityOutputTemplate<Vector,FIELD_VECTOR> COutputVector;
|
||||
typedef CEntityOutputTemplate<Vector,FIELD_POSITION_VECTOR> COutputPositionVector;
|
||||
typedef CEntityOutputTemplate<color32,FIELD_COLOR32> COutputColor32;
|
||||
|
||||
#endif // ENTITYOUTPUT_H
|
||||
505
sp/src/game/server/env_cascade_light.cpp
Normal file
505
sp/src/game/server/env_cascade_light.cpp
Normal file
@@ -0,0 +1,505 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Entity to control screen overlays on a player
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "shareddefs.h"
|
||||
#include "lights.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define ENV_CASCADE_STARTON (1<<0)
|
||||
|
||||
static ConVar defdist("csm_default_distance", "1000", FCVAR_DEVELOPMENTONLY, "Default Z distance. Used for some fov calculations. Please dont change");
|
||||
static ConVar curdist("csm_current_distance","14000", 0, "Current Z distance. You can change it.");
|
||||
static ConVar defFOV("csm_default_fov","15", FCVAR_DEVELOPMENTONLY, "Default FOV. Used for some fov calculations. Please dont change");
|
||||
static ConVar curFOV("csm_current_fov","15", 0, "Current FOV. You can change it");
|
||||
static ConVar csm_second_fov("csm_second_fov", "26", FCVAR_NONE ,"FOV of the second csm.");
|
||||
|
||||
class CLightOrigin : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS(CLightOrigin, CPointEntity);
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
void Spawn();
|
||||
|
||||
CLightOrigin();
|
||||
|
||||
bool angFEnv = false;
|
||||
|
||||
void InitialThink(void);
|
||||
|
||||
private:
|
||||
|
||||
CNetworkVector(LightEnvVector);
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(csmorigin, CLightOrigin);
|
||||
|
||||
BEGIN_DATADESC(CLightOrigin)
|
||||
DEFINE_FIELD(LightEnvVector, FIELD_VECTOR),
|
||||
DEFINE_THINKFUNC(InitialThink)
|
||||
END_DATADESC()
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST(CLightOrigin, DT_LightOrigin)
|
||||
SendPropVector(SENDINFO(LightEnvVector))
|
||||
END_SEND_TABLE()
|
||||
|
||||
CLightOrigin::CLightOrigin()
|
||||
{
|
||||
}
|
||||
|
||||
void CLightOrigin::Spawn()
|
||||
{
|
||||
if (angFEnv)
|
||||
{
|
||||
CBaseEntity* pEntity = NULL;
|
||||
pEntity = gEntList.FindEntityByClassname(pEntity, "light_environment");
|
||||
if (pEntity)
|
||||
{
|
||||
CEnvLight* pEnv = dynamic_cast<CEnvLight*>(pEntity);
|
||||
|
||||
QAngle bb = pEnv->GetAbsAngles();
|
||||
bb.x = bb.x;
|
||||
SetAbsAngles(bb);
|
||||
|
||||
ConColorMsg(Color(0,230,0), "light_environment Founded!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
//Msg("What the fuck? Map dont have light_environment with targetname!");
|
||||
ConColorMsg(Color(230, 0, 0), "What the fuck? Map dont have light_environment with targetname!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CLightOrigin::InitialThink()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: second csm
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class CEnvCascadeLightSecond : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS(CEnvCascadeLightSecond, CPointEntity);
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
CEnvCascadeLightSecond();
|
||||
bool KeyValue(const char* szKeyName, const char* szValue);
|
||||
|
||||
// Always transmit to clients
|
||||
virtual int UpdateTransmitState();
|
||||
virtual void Activate(void);
|
||||
|
||||
void InitialThink(void);
|
||||
|
||||
CNetworkHandle(CBaseEntity, m_hTargetEntity);
|
||||
CNetworkVector(m_LinearFloatLightColor);
|
||||
|
||||
private:
|
||||
CNetworkVar(bool, m_bState);
|
||||
CNetworkVar(float, m_flLightFOV);
|
||||
CNetworkVar(bool, m_bEnableShadows);
|
||||
CNetworkVar(bool, m_bLightOnlyTarget);
|
||||
CNetworkVar(bool, m_bLightWorld);
|
||||
CNetworkVar(bool, m_bCameraSpace);
|
||||
CNetworkVar(float, m_flAmbient);
|
||||
CNetworkString(m_SpotlightTextureName, MAX_PATH);
|
||||
CNetworkVar(int, m_nSpotlightTextureFrame);
|
||||
CNetworkVar(float, m_flNearZ);
|
||||
CNetworkVar(float, m_flFarZ);
|
||||
CNetworkVar(int, m_nShadowQuality);
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(second_csm, CEnvCascadeLightSecond);
|
||||
|
||||
BEGIN_DATADESC(CEnvCascadeLightSecond)
|
||||
DEFINE_FIELD(m_hTargetEntity, FIELD_EHANDLE),
|
||||
DEFINE_FIELD(m_bState, FIELD_BOOLEAN),
|
||||
DEFINE_KEYFIELD(m_flLightFOV, FIELD_FLOAT, "lightfov"),
|
||||
DEFINE_KEYFIELD(m_bEnableShadows, FIELD_BOOLEAN, "enableshadows"),
|
||||
DEFINE_KEYFIELD(m_bLightOnlyTarget, FIELD_BOOLEAN, "lightonlytarget"),
|
||||
DEFINE_KEYFIELD(m_bLightWorld, FIELD_BOOLEAN, "lightworld"),
|
||||
DEFINE_KEYFIELD(m_bCameraSpace, FIELD_BOOLEAN, "cameraspace"),
|
||||
DEFINE_KEYFIELD(m_flAmbient, FIELD_FLOAT, "ambient"),
|
||||
DEFINE_AUTO_ARRAY_KEYFIELD(m_SpotlightTextureName, FIELD_CHARACTER, "texturename"),
|
||||
DEFINE_KEYFIELD(m_nSpotlightTextureFrame, FIELD_INTEGER, "textureframe"),
|
||||
DEFINE_KEYFIELD(m_flNearZ, FIELD_FLOAT, "nearz"),
|
||||
DEFINE_KEYFIELD(m_flFarZ, FIELD_FLOAT, "farz"),
|
||||
DEFINE_KEYFIELD(m_nShadowQuality, FIELD_INTEGER, "shadowquality"),
|
||||
DEFINE_FIELD(m_LinearFloatLightColor, FIELD_VECTOR),
|
||||
DEFINE_THINKFUNC(InitialThink),
|
||||
END_DATADESC()
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST(CEnvCascadeLightSecond, DT_EnvCascadeLightSecond)
|
||||
SendPropEHandle(SENDINFO(m_hTargetEntity)),
|
||||
SendPropBool(SENDINFO(m_bState)),
|
||||
SendPropFloat(SENDINFO(m_flLightFOV)),
|
||||
SendPropBool(SENDINFO(m_bEnableShadows)),
|
||||
SendPropBool(SENDINFO(m_bLightOnlyTarget)),
|
||||
SendPropBool(SENDINFO(m_bLightWorld)),
|
||||
SendPropBool(SENDINFO(m_bCameraSpace)),
|
||||
SendPropVector(SENDINFO(m_LinearFloatLightColor)),
|
||||
SendPropFloat(SENDINFO(m_flAmbient)),
|
||||
SendPropString(SENDINFO(m_SpotlightTextureName)),
|
||||
SendPropInt(SENDINFO(m_nSpotlightTextureFrame)),
|
||||
SendPropFloat(SENDINFO(m_flNearZ), 16, SPROP_ROUNDDOWN, 0.0f, 500.0f),
|
||||
SendPropFloat(SENDINFO(m_flFarZ), 18, SPROP_ROUNDDOWN, 0.0f, 1500.0f),
|
||||
SendPropInt(SENDINFO(m_nShadowQuality), 1, SPROP_UNSIGNED) // Just one bit for now
|
||||
END_SEND_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CEnvCascadeLightSecond::CEnvCascadeLightSecond(void)
|
||||
{
|
||||
m_bState = true;
|
||||
m_flLightFOV = 45.0f;
|
||||
m_bEnableShadows = true;
|
||||
m_bLightOnlyTarget = false;
|
||||
m_bLightWorld = true;
|
||||
m_bCameraSpace = false;
|
||||
|
||||
Q_strcpy(m_SpotlightTextureName.GetForModify(), "tools\\fakecsm\\mask_ring");
|
||||
m_nSpotlightTextureFrame = 0;
|
||||
m_LinearFloatLightColor.Init(1.0f, 1.0f, 1.0f);
|
||||
m_flAmbient = 0.0f;
|
||||
m_flNearZ = 8000.0f;
|
||||
m_flFarZ = 16000.0f;
|
||||
m_nShadowQuality = 0;
|
||||
}
|
||||
|
||||
void UTIL_ColorStringToLinearFloatColorCSMFakeSecond(Vector& color, const char* pString)
|
||||
{
|
||||
float tmp[4];
|
||||
UTIL_StringToFloatArray(tmp, 4, pString);
|
||||
if (tmp[3] <= 0.0f)
|
||||
{
|
||||
tmp[3] = 255.0f;
|
||||
}
|
||||
tmp[3] *= (1.0f / 255.0f);
|
||||
color.x = GammaToLinear(tmp[0] * (1.0f / 255.0f)) * tmp[3];
|
||||
color.y = GammaToLinear(tmp[1] * (1.0f / 255.0f)) * tmp[3];
|
||||
color.z = GammaToLinear(tmp[2] * (1.0f / 255.0f)) * tmp[3];
|
||||
}
|
||||
|
||||
bool CEnvCascadeLightSecond::KeyValue(const char* szKeyName, const char* szValue)
|
||||
{
|
||||
if (FStrEq(szKeyName, "lightcolor"))
|
||||
{
|
||||
Vector tmp;
|
||||
UTIL_ColorStringToLinearFloatColorCSMFakeSecond(tmp, szValue);
|
||||
m_LinearFloatLightColor = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::KeyValue(szKeyName, szValue);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEnvCascadeLightSecond::Activate(void)
|
||||
{
|
||||
if (GetSpawnFlags() & ENV_CASCADE_STARTON)
|
||||
{
|
||||
m_bState = true;
|
||||
}
|
||||
|
||||
SetThink(&CEnvCascadeLightSecond::InitialThink);
|
||||
SetNextThink(gpGlobals->curtime + 0.1f);
|
||||
|
||||
BaseClass::Activate();
|
||||
}
|
||||
|
||||
void CEnvCascadeLightSecond::InitialThink(void)
|
||||
{
|
||||
float bibigon = defdist.GetFloat() / curdist.GetFloat();
|
||||
m_flLightFOV = csm_second_fov.GetFloat() * bibigon;
|
||||
m_hTargetEntity = gEntList.FindEntityByName(NULL, m_target);
|
||||
}
|
||||
|
||||
int CEnvCascadeLightSecond::UpdateTransmitState()
|
||||
{
|
||||
return SetTransmitState(FL_EDICT_ALWAYS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: main csm code
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEnvCascadeLight : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS(CEnvCascadeLight, CPointEntity);
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
CEnvCascadeLight();
|
||||
bool KeyValue(const char* szKeyName, const char* szValue);
|
||||
|
||||
// Always transmit to clients
|
||||
virtual int UpdateTransmitState();
|
||||
virtual void Activate(void);
|
||||
void Spawn();
|
||||
void Preparation();
|
||||
|
||||
void InputTurnOn(inputdata_t& inputdata);
|
||||
void InputTurnOff(inputdata_t& inputdata);
|
||||
void InputSetEnableShadows(inputdata_t& inputdata);
|
||||
void InputSetLightColor( inputdata_t &inputdata );
|
||||
void InputSetSpotlightTexture(inputdata_t& inputdata);
|
||||
void InputSetAmbient(inputdata_t& inputdata);
|
||||
|
||||
void InitialThink(void);
|
||||
|
||||
CNetworkHandle(CBaseEntity, m_hTargetEntity);
|
||||
|
||||
private:
|
||||
CLightOrigin* pEnv;
|
||||
CNetworkVar(bool, m_bState);
|
||||
CNetworkVar(float, m_flLightFOV);
|
||||
CNetworkVar(bool, EnableAngleFromEnv);
|
||||
CNetworkVar(bool, m_bEnableShadows);
|
||||
CNetworkVar(bool, m_bLightOnlyTarget);
|
||||
CNetworkVar(bool, m_bLightWorld);
|
||||
CNetworkVar(bool, m_bCameraSpace);
|
||||
CNetworkVector(m_LinearFloatLightColor);
|
||||
CNetworkVar(float, m_flAmbient);
|
||||
CNetworkString(m_SpotlightTextureName, MAX_PATH);
|
||||
CNetworkVar(int, m_nSpotlightTextureFrame);
|
||||
CNetworkVar(float, m_flNearZ);
|
||||
CNetworkVar(float, m_flFarZ);
|
||||
CNetworkVar(int, m_nShadowQuality);
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(env_cascade_light, CEnvCascadeLight);
|
||||
|
||||
BEGIN_DATADESC(CEnvCascadeLight)
|
||||
DEFINE_FIELD(m_hTargetEntity, FIELD_EHANDLE),
|
||||
DEFINE_FIELD(m_bState, FIELD_BOOLEAN),
|
||||
DEFINE_KEYFIELD(m_bEnableShadows, FIELD_BOOLEAN, "enableshadows"),
|
||||
DEFINE_KEYFIELD(m_bLightOnlyTarget, FIELD_BOOLEAN, "lightonlytarget"),
|
||||
DEFINE_KEYFIELD(m_bLightWorld, FIELD_BOOLEAN, "lightworld"),
|
||||
DEFINE_KEYFIELD(m_bCameraSpace, FIELD_BOOLEAN, "cameraspace"),
|
||||
DEFINE_KEYFIELD(m_flAmbient, FIELD_FLOAT, "ambient"),
|
||||
DEFINE_AUTO_ARRAY_KEYFIELD(m_SpotlightTextureName, FIELD_CHARACTER, "texturename"),
|
||||
DEFINE_KEYFIELD(m_nSpotlightTextureFrame, FIELD_INTEGER, "textureframe"),
|
||||
DEFINE_KEYFIELD(m_flNearZ, FIELD_FLOAT, "nearz"),
|
||||
DEFINE_KEYFIELD(m_flFarZ, FIELD_FLOAT, "farz"),
|
||||
DEFINE_KEYFIELD(m_nShadowQuality, FIELD_INTEGER, "shadowquality"),
|
||||
DEFINE_FIELD(m_LinearFloatLightColor, FIELD_VECTOR),
|
||||
DEFINE_KEYFIELD(EnableAngleFromEnv, FIELD_BOOLEAN, "uselightenvangles"),
|
||||
|
||||
DEFINE_INPUTFUNC(FIELD_VOID, "TurnOn", InputTurnOn),
|
||||
DEFINE_INPUTFUNC(FIELD_VOID, "TurnOff", InputTurnOff),
|
||||
DEFINE_INPUTFUNC(FIELD_BOOLEAN, "EnableShadows", InputSetEnableShadows),
|
||||
// this is broken . . need to be able to set color and intensity like light_dynamic
|
||||
// DEFINE_INPUTFUNC( FIELD_COLOR32, "LightColor", InputSetLightColor ),
|
||||
DEFINE_INPUTFUNC(FIELD_FLOAT, "Ambient", InputSetAmbient),
|
||||
DEFINE_INPUTFUNC(FIELD_STRING, "SpotlightTexture", InputSetSpotlightTexture),
|
||||
DEFINE_THINKFUNC(InitialThink),
|
||||
END_DATADESC()
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST(CEnvCascadeLight, DT_EnvCascadeLight)
|
||||
SendPropEHandle(SENDINFO(m_hTargetEntity)),
|
||||
SendPropBool(SENDINFO(m_bState)),
|
||||
SendPropFloat(SENDINFO(m_flLightFOV)),
|
||||
SendPropBool(SENDINFO(m_bEnableShadows)),
|
||||
SendPropBool(SENDINFO(m_bLightOnlyTarget)),
|
||||
SendPropBool(SENDINFO(m_bLightWorld)),
|
||||
SendPropBool(SENDINFO(m_bCameraSpace)),
|
||||
SendPropVector(SENDINFO(m_LinearFloatLightColor)),
|
||||
SendPropFloat(SENDINFO(m_flAmbient)),
|
||||
SendPropString(SENDINFO(m_SpotlightTextureName)),
|
||||
SendPropInt(SENDINFO(m_nSpotlightTextureFrame)),
|
||||
SendPropFloat(SENDINFO(m_flNearZ), 16, SPROP_ROUNDDOWN, 0.0f, 500.0f),
|
||||
SendPropFloat(SENDINFO(m_flFarZ), 18, SPROP_ROUNDDOWN, 0.0f, 1500.0f),
|
||||
SendPropInt(SENDINFO(m_nShadowQuality), 1, SPROP_UNSIGNED) // Just one bit for now
|
||||
END_SEND_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CEnvCascadeLight::CEnvCascadeLight(void)
|
||||
{
|
||||
m_bState = true;
|
||||
m_flLightFOV = 45.0f;
|
||||
m_bEnableShadows = true;
|
||||
m_bLightOnlyTarget = false;
|
||||
m_bLightWorld = true;
|
||||
m_bCameraSpace = false;
|
||||
EnableAngleFromEnv = false;
|
||||
|
||||
Q_strcpy(m_SpotlightTextureName.GetForModify(), "tools\\fakecsm\\mask_center");
|
||||
m_nSpotlightTextureFrame = 0;
|
||||
m_LinearFloatLightColor.Init(1.0f, 1.0f, 1.0f);
|
||||
m_flAmbient = 0.0f;
|
||||
m_flNearZ = 8000.0f;
|
||||
m_flFarZ = 16000.0f;
|
||||
m_nShadowQuality = 0;
|
||||
}
|
||||
ConVar csm_second_intensity("csm_second_intensity", "2");
|
||||
void CEnvCascadeLight::Preparation()
|
||||
{
|
||||
CreateEntityByName("csmorigin");
|
||||
CreateEntityByName("second_csm");
|
||||
defFOV.SetValue(m_flLightFOV);
|
||||
CBaseEntity* CSMOrigin = NULL;
|
||||
CBaseEntity* CSMSecond = NULL;
|
||||
|
||||
CSMOrigin = gEntList.FindEntityByClassname(CSMOrigin, "csmorigin");
|
||||
//if origin is exist
|
||||
if (CSMOrigin)
|
||||
{
|
||||
|
||||
pEnv = dynamic_cast<CLightOrigin*>(CSMOrigin);
|
||||
|
||||
|
||||
CSMSecond = gEntList.FindEntityByClassname(CSMSecond, "second_csm");
|
||||
//if second csm is exist
|
||||
if (CSMSecond)
|
||||
{
|
||||
CEnvCascadeLightSecond* SecondCSM = dynamic_cast<CEnvCascadeLightSecond*>(CSMSecond);
|
||||
SecondCSM->SetAbsAngles(GetAbsAngles());
|
||||
SecondCSM->SetAbsOrigin(GetAbsOrigin());
|
||||
SecondCSM->SetParent(GetBaseEntity());
|
||||
SecondCSM->m_LinearFloatLightColor = m_LinearFloatLightColor * csm_second_intensity.GetFloat();
|
||||
|
||||
|
||||
DispatchSpawn(SecondCSM);
|
||||
}
|
||||
|
||||
SetParent(pEnv, 1);
|
||||
SetAbsOrigin(Vector(pEnv->GetAbsOrigin().x, pEnv->GetAbsOrigin().y, pEnv->GetAbsOrigin().z + curdist.GetInt()));
|
||||
|
||||
if (EnableAngleFromEnv)
|
||||
{
|
||||
pEnv->angFEnv = true;
|
||||
SetLocalAngles(QAngle(90, 0, 0));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
pEnv->SetAbsAngles(QAngle((GetLocalAngles().x - 90), GetLocalAngles().y, -GetLocalAngles().z));
|
||||
|
||||
Msg("pEnv local angle = %f %f %f \n", pEnv->GetLocalAngles().x, pEnv->GetLocalAngles().y, pEnv->GetLocalAngles().z);
|
||||
|
||||
SetLocalAngles(QAngle(90, 0, 0));
|
||||
DevMsg("CSM using light_environment \n");
|
||||
}
|
||||
//DispatchSpawn(CSMSecond);
|
||||
DispatchSpawn(CSMOrigin);
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg("Main csm entity can't find \"csmorigin\" entity!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CEnvCascadeLight::Spawn()
|
||||
{
|
||||
Preparation();
|
||||
}
|
||||
|
||||
void UTIL_ColorStringToLinearFloatColorCSMFake(Vector& color, const char* pString)
|
||||
{
|
||||
float tmp[4];
|
||||
UTIL_StringToFloatArray(tmp, 4, pString);
|
||||
if (tmp[3] <= 0.0f)
|
||||
{
|
||||
tmp[3] = 255.0f;
|
||||
}
|
||||
tmp[3] *= (1.0f / 255.0f);
|
||||
color.x = GammaToLinear(tmp[0] * (1.0f / 255.0f)) * tmp[3];
|
||||
color.y = GammaToLinear(tmp[1] * (1.0f / 255.0f)) * tmp[3];
|
||||
color.z = GammaToLinear(tmp[2] * (1.0f / 255.0f)) * tmp[3];
|
||||
}
|
||||
|
||||
bool CEnvCascadeLight::KeyValue(const char* szKeyName, const char* szValue)
|
||||
{
|
||||
if (FStrEq(szKeyName, "lightcolor"))
|
||||
{
|
||||
Vector tmp;
|
||||
UTIL_ColorStringToLinearFloatColorCSMFake(tmp, szValue);
|
||||
m_LinearFloatLightColor = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::KeyValue(szKeyName, szValue);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEnvCascadeLight::InputTurnOn(inputdata_t& inputdata)
|
||||
{
|
||||
m_bState = true;
|
||||
}
|
||||
|
||||
void CEnvCascadeLight::InputTurnOff(inputdata_t& inputdata)
|
||||
{
|
||||
m_bState = false;
|
||||
}
|
||||
|
||||
|
||||
void CEnvCascadeLight::InputSetEnableShadows(inputdata_t& inputdata)
|
||||
{
|
||||
m_bEnableShadows = inputdata.value.Bool();
|
||||
}
|
||||
|
||||
//void CEnvProjectedTexture::InputSetLightColor( inputdata_t &inputdata )
|
||||
//{
|
||||
//m_cLightColor = inputdata.value.Color32();
|
||||
//}
|
||||
|
||||
void CEnvCascadeLight::InputSetAmbient(inputdata_t& inputdata)
|
||||
{
|
||||
m_flAmbient = inputdata.value.Float();
|
||||
}
|
||||
|
||||
void CEnvCascadeLight::InputSetSpotlightTexture(inputdata_t& inputdata)
|
||||
{
|
||||
Q_strcpy(m_SpotlightTextureName.GetForModify(), inputdata.value.String());
|
||||
}
|
||||
|
||||
void CEnvCascadeLight::Activate(void)
|
||||
{
|
||||
if (GetSpawnFlags() & ENV_CASCADE_STARTON)
|
||||
{
|
||||
m_bState = true;
|
||||
}
|
||||
|
||||
SetThink(&CEnvCascadeLight::InitialThink);
|
||||
SetNextThink(gpGlobals->curtime + 0.1f);
|
||||
|
||||
BaseClass::Activate();
|
||||
}
|
||||
|
||||
void CEnvCascadeLight::InitialThink(void)
|
||||
{
|
||||
m_hTargetEntity = gEntList.FindEntityByName(NULL, m_target);
|
||||
|
||||
float bibigon = defdist.GetFloat() / curdist.GetFloat();
|
||||
curFOV.SetValue(defFOV.GetFloat() * bibigon);
|
||||
m_flLightFOV = curFOV.GetFloat();
|
||||
//if(pEnv != NULL)
|
||||
//SetAbsOrigin(Vector(pEnv->GetAbsOrigin().x, pEnv->GetAbsOrigin().y, pEnv->GetAbsOrigin().z + curdist.GetInt()));
|
||||
}
|
||||
|
||||
int CEnvCascadeLight::UpdateTransmitState()
|
||||
{
|
||||
return SetTransmitState(FL_EDICT_ALWAYS);
|
||||
}
|
||||
367
sp/src/game/server/env_debughistory.cpp
Normal file
367
sp/src/game/server/env_debughistory.cpp
Normal file
@@ -0,0 +1,367 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
#include "cbase.h"
|
||||
#include "isaverestore.h"
|
||||
#include "env_debughistory.h"
|
||||
#include "tier0/vprof.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// Number of characters worth of debug to use per history category
|
||||
#define DEBUG_HISTORY_VERSION 6
|
||||
#define DEBUG_HISTORY_FIRST_VERSIONED 5
|
||||
#define MAX_DEBUG_HISTORY_LINE_LENGTH 256
|
||||
#define MAX_DEBUG_HISTORY_LENGTH (1000 * MAX_DEBUG_HISTORY_LINE_LENGTH)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Stores debug history in savegame files for debugging reference
|
||||
//-----------------------------------------------------------------------------
|
||||
class CDebugHistory : public CBaseEntity
|
||||
{
|
||||
DECLARE_CLASS( CDebugHistory, CBaseEntity );
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
|
||||
void Spawn();
|
||||
void AddDebugHistoryLine( int iCategory, const char *szLine );
|
||||
void ClearHistories( void );
|
||||
void DumpDebugHistory( int iCategory );
|
||||
|
||||
int Save( ISave &save );
|
||||
int Restore( IRestore &restore );
|
||||
|
||||
private:
|
||||
char m_DebugLines[MAX_HISTORY_CATEGORIES][MAX_DEBUG_HISTORY_LENGTH];
|
||||
char *m_DebugLineEnd[MAX_HISTORY_CATEGORIES];
|
||||
};
|
||||
|
||||
BEGIN_DATADESC( CDebugHistory )
|
||||
//DEFINE_FIELD( m_DebugLines, FIELD_CHARACTER ), // Not saved because we write it out manually
|
||||
//DEFINE_FIELD( m_DebugLineEnd, FIELD_CHARACTER ),
|
||||
END_DATADESC()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_debughistory, CDebugHistory );
|
||||
|
||||
// The handle to the debug history singleton. Created on first access via GetDebugHistory.
|
||||
static CHandle< CDebugHistory > s_DebugHistory;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Spawn
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::Spawn()
|
||||
{
|
||||
BaseClass::Spawn();
|
||||
|
||||
#ifdef DISABLE_DEBUG_HISTORY
|
||||
UTIL_Remove( this );
|
||||
#else
|
||||
if ( g_pGameRules && g_pGameRules->IsMultiplayer() )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "DEBUG HISTORY IS ENABLED. Disable before release (in env_debughistory.h).\n" );
|
||||
}
|
||||
#endif
|
||||
|
||||
ClearHistories();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::AddDebugHistoryLine( int iCategory, const char *szLine )
|
||||
{
|
||||
if ( iCategory < 0 || iCategory >= MAX_HISTORY_CATEGORIES )
|
||||
{
|
||||
Warning("Attempted to add a debughistory line to category %d. Valid categories are %d to %d.\n", iCategory, 0, (MAX_HISTORY_CATEGORIES-1) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't do debug history before the singleton is properly set up.
|
||||
if ( !m_DebugLineEnd[iCategory] )
|
||||
return;
|
||||
|
||||
const char *pszRemaining = szLine;
|
||||
int iCharsToWrite = strlen( pszRemaining ) + 1; // Add 1 so that we copy the null terminator
|
||||
|
||||
// Clip the line if it's too long. Wasteful doing it this way, but keeps code below nice & simple.
|
||||
char szTmpBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH];
|
||||
if ( iCharsToWrite > MAX_DEBUG_HISTORY_LINE_LENGTH)
|
||||
{
|
||||
memcpy( szTmpBuffer, szLine, sizeof(szTmpBuffer) );
|
||||
szTmpBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH-1] = '\0';
|
||||
pszRemaining = szTmpBuffer;
|
||||
iCharsToWrite = MAX_DEBUG_HISTORY_LINE_LENGTH;
|
||||
}
|
||||
|
||||
while ( iCharsToWrite )
|
||||
{
|
||||
int iCharsLeftBeforeLoop = sizeof(m_DebugLines[iCategory]) - (m_DebugLineEnd[iCategory] - m_DebugLines[iCategory]);
|
||||
|
||||
// Write into the buffer
|
||||
int iWrote = MIN( iCharsToWrite, iCharsLeftBeforeLoop );
|
||||
memcpy( m_DebugLineEnd[iCategory], pszRemaining, iWrote );
|
||||
m_DebugLineEnd[iCategory] += iWrote;
|
||||
pszRemaining += iWrote;
|
||||
|
||||
// Did we loop?
|
||||
if ( iWrote == iCharsLeftBeforeLoop )
|
||||
{
|
||||
m_DebugLineEnd[iCategory] = m_DebugLines[iCategory];
|
||||
}
|
||||
|
||||
iCharsToWrite -= iWrote;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::DumpDebugHistory( int iCategory )
|
||||
{
|
||||
if ( iCategory < 0 || iCategory >= MAX_HISTORY_CATEGORIES )
|
||||
{
|
||||
Warning("Attempted to dump a history for category %d. Valid categories are %d to %d.\n", iCategory, 0, (MAX_HISTORY_CATEGORIES-1) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the start of the oldest whole debug line.
|
||||
const char *pszLine = m_DebugLineEnd[iCategory] + 1;
|
||||
if ( (pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) )
|
||||
{
|
||||
pszLine = m_DebugLines[iCategory];
|
||||
}
|
||||
|
||||
// Are we at the start of a line? If there's a null terminator before us, then we're good to go.
|
||||
while ( (!( pszLine == m_DebugLines[iCategory] && *(m_DebugLines[iCategory]+sizeof(m_DebugLines[iCategory])-1) == '\0' ) &&
|
||||
!( pszLine != m_DebugLines[iCategory] && *(pszLine-1) == '\0' ))
|
||||
|| *pszLine == '\0' )
|
||||
{
|
||||
pszLine++;
|
||||
|
||||
// Have we looped?
|
||||
if ( (pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) )
|
||||
{
|
||||
pszLine = m_DebugLines[iCategory];
|
||||
}
|
||||
|
||||
if ( pszLine == m_DebugLineEnd[iCategory] )
|
||||
{
|
||||
// We looped through the entire history, and found nothing.
|
||||
Msg( "Debug History of Category %d is EMPTY\n", iCategory );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Now print everything up till the end
|
||||
char szMsgBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH];
|
||||
char *pszMsg = szMsgBuffer;
|
||||
Msg( "Starting Debug History Dump of Category %d\n", iCategory );
|
||||
while ( pszLine != m_DebugLineEnd[iCategory] )
|
||||
{
|
||||
*pszMsg = *pszLine;
|
||||
if ( *pszLine == '\0' )
|
||||
{
|
||||
if ( szMsgBuffer[0] != '\0' )
|
||||
{
|
||||
// Found a full line, so print it
|
||||
Msg( "%s", szMsgBuffer );
|
||||
}
|
||||
|
||||
// Clear the buffer
|
||||
pszMsg = szMsgBuffer;
|
||||
*pszMsg = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
pszMsg++;
|
||||
}
|
||||
|
||||
pszLine++;
|
||||
|
||||
// Have we looped?
|
||||
if ( (pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) )
|
||||
{
|
||||
pszLine = m_DebugLines[iCategory];
|
||||
}
|
||||
}
|
||||
Msg("Ended Debug History Dump of Category %d\n", iCategory );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::ClearHistories( void )
|
||||
{
|
||||
for ( int i = 0; i < MAX_HISTORY_CATEGORIES; i++ )
|
||||
{
|
||||
memset( m_DebugLines[i], 0, sizeof(m_DebugLines[i]) );
|
||||
m_DebugLineEnd[i] = m_DebugLines[i];
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CDebugHistory::Save( ISave &save )
|
||||
{
|
||||
int iVersion = DEBUG_HISTORY_VERSION;
|
||||
save.WriteInt( &iVersion );
|
||||
int iMaxCategorys = MAX_HISTORY_CATEGORIES;
|
||||
save.WriteInt( &iMaxCategorys );
|
||||
for ( int iCategory = 0; iCategory < MAX_HISTORY_CATEGORIES; iCategory++ )
|
||||
{
|
||||
int iEnd = m_DebugLineEnd[iCategory] - m_DebugLines[iCategory];
|
||||
save.WriteInt( &iEnd );
|
||||
save.WriteData( m_DebugLines[iCategory], MAX_DEBUG_HISTORY_LENGTH );
|
||||
}
|
||||
|
||||
return BaseClass::Save(save);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CDebugHistory::Restore( IRestore &restore )
|
||||
{
|
||||
ClearHistories();
|
||||
|
||||
int iVersion = restore.ReadInt();
|
||||
|
||||
if ( iVersion >= DEBUG_HISTORY_FIRST_VERSIONED )
|
||||
{
|
||||
int iMaxCategorys = restore.ReadInt();
|
||||
for ( int iCategory = 0; iCategory < MIN(iMaxCategorys,MAX_HISTORY_CATEGORIES); iCategory++ )
|
||||
{
|
||||
int iEnd = restore.ReadInt();
|
||||
m_DebugLineEnd[iCategory] = m_DebugLines[iCategory] + iEnd;
|
||||
restore.ReadData( m_DebugLines[iCategory], sizeof(m_DebugLines[iCategory]), 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int iMaxCategorys = iVersion;
|
||||
for ( int iCategory = 0; iCategory < MIN(iMaxCategorys,MAX_HISTORY_CATEGORIES); iCategory++ )
|
||||
{
|
||||
int iEnd = restore.ReadInt();
|
||||
m_DebugLineEnd[iCategory] = m_DebugLines[iCategory] + iEnd;
|
||||
restore.ReadData( m_DebugLines[iCategory], sizeof(m_DebugLines[iCategory]), 0 );
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::Restore(restore);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Singleton debug history. Created by first usage.
|
||||
//-----------------------------------------------------------------------------
|
||||
CDebugHistory *GetDebugHistory()
|
||||
{
|
||||
#ifdef DISABLE_DEBUG_HISTORY
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if ( g_pGameRules && g_pGameRules->IsMultiplayer() )
|
||||
return NULL;
|
||||
|
||||
if ( s_DebugHistory == NULL )
|
||||
{
|
||||
CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, "env_debughistory" );
|
||||
if ( pEnt )
|
||||
{
|
||||
s_DebugHistory = dynamic_cast<CDebugHistory*>(pEnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_DebugHistory = ( CDebugHistory * )CreateEntityByName( "env_debughistory" );
|
||||
if ( s_DebugHistory )
|
||||
{
|
||||
s_DebugHistory->Spawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert( s_DebugHistory );
|
||||
return s_DebugHistory;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void AddDebugHistoryLine( int iCategory, const char *pszLine )
|
||||
{
|
||||
#ifdef DISABLE_DEBUG_HISTORY
|
||||
return;
|
||||
#else
|
||||
if ( g_pGameRules && g_pGameRules->IsMultiplayer() )
|
||||
return;
|
||||
|
||||
if ( !GetDebugHistory() )
|
||||
{
|
||||
Warning("Failed to find or create an env_debughistory.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
GetDebugHistory()->AddDebugHistoryLine( iCategory, pszLine );
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CC_DebugHistory_AddLine( const CCommand &args )
|
||||
{
|
||||
if ( !UTIL_IsCommandIssuedByServerAdmin() )
|
||||
return;
|
||||
|
||||
if ( args.ArgC() < 3 )
|
||||
{
|
||||
Warning("Incorrect parameters. Format: <category id> <line>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int iCategory = atoi(args[ 1 ]);
|
||||
const char *pszLine = args[ 2 ];
|
||||
AddDebugHistoryLine( iCategory, pszLine );
|
||||
}
|
||||
static ConCommand dbghist_addline( "dbghist_addline", CC_DebugHistory_AddLine, "Add a line to the debug history. Format: <category id> <line>", FCVAR_NONE );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CC_DebugHistory_Dump( const CCommand &args )
|
||||
{
|
||||
if ( !UTIL_IsCommandIssuedByServerAdmin() )
|
||||
return;
|
||||
|
||||
if ( args.ArgC() < 2 )
|
||||
{
|
||||
Warning("Incorrect parameters. Format: <category id>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( GetDebugHistory() )
|
||||
{
|
||||
int iCategory = atoi(args[ 1 ]);
|
||||
GetDebugHistory()->DumpDebugHistory( iCategory );
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand dbghist_dump("dbghist_dump", CC_DebugHistory_Dump,
|
||||
"Dump the debug history to the console. Format: <category id>\n"
|
||||
" Categories:\n"
|
||||
" 0: Entity I/O\n"
|
||||
" 1: AI Decisions\n"
|
||||
" 2: Scene Print\n"
|
||||
" 3: Alyx Blind\n"
|
||||
" 4: Log of damage done to player",
|
||||
FCVAR_NONE );
|
||||
|
||||
35
sp/src/game/server/env_debughistory.h
Normal file
35
sp/src/game/server/env_debughistory.h
Normal file
@@ -0,0 +1,35 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef ENV_DEBUGHISTORY_H
|
||||
#define ENV_DEBUGHISTORY_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
enum debughistorycategories_t
|
||||
{
|
||||
HISTORY_ENTITY_IO,
|
||||
HISTORY_AI_DECISIONS,
|
||||
HISTORY_SCENE_PRINT,
|
||||
HISTORY_ALYX_BLIND, // TEMP: until we find and fix this bug
|
||||
HISTORY_PLAYER_DAMAGE, // record all damage done to the player
|
||||
|
||||
// Add new categories here
|
||||
|
||||
MAX_HISTORY_CATEGORIES,
|
||||
};
|
||||
|
||||
#define DISABLE_DEBUG_HISTORY
|
||||
|
||||
#if defined(DISABLE_DEBUG_HISTORY)
|
||||
#define ADD_DEBUG_HISTORY( category, line ) ((void)0)
|
||||
#else
|
||||
#define ADD_DEBUG_HISTORY( category, line ) AddDebugHistoryLine( category, line )
|
||||
void AddDebugHistoryLine( int iCategory, const char *pszLine );
|
||||
#endif
|
||||
|
||||
#endif // ENV_DEBUGHISTORY_H
|
||||
186
sp/src/game/server/env_dof_controller.cpp
Normal file
186
sp/src/game/server/env_dof_controller.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
//====== Copyright <20> 1996-2004, Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose: Depth of field controller entity
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "baseentity.h"
|
||||
#include "entityoutput.h"
|
||||
#include "env_dof_controller.h"
|
||||
#include "ai_utils.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_dof_controller, CEnvDOFController );
|
||||
|
||||
BEGIN_DATADESC( CEnvDOFController )
|
||||
|
||||
DEFINE_KEYFIELD( m_bDOFEnabled, FIELD_BOOLEAN, "enabled" ),
|
||||
DEFINE_KEYFIELD( m_flNearBlurDepth, FIELD_FLOAT, "near_blur" ),
|
||||
DEFINE_KEYFIELD( m_flNearFocusDepth, FIELD_FLOAT, "near_focus" ),
|
||||
DEFINE_KEYFIELD( m_flFarFocusDepth, FIELD_FLOAT, "far_focus" ),
|
||||
DEFINE_KEYFIELD( m_flFarBlurDepth, FIELD_FLOAT, "far_blur" ),
|
||||
DEFINE_KEYFIELD( m_flNearBlurRadius, FIELD_FLOAT, "near_radius" ),
|
||||
DEFINE_KEYFIELD( m_flFarBlurRadius, FIELD_FLOAT, "far_radius" ),
|
||||
DEFINE_KEYFIELD( m_strFocusTargetName, FIELD_STRING, "focus_target" ),
|
||||
DEFINE_KEYFIELD( m_flFocusTargetRange, FIELD_FLOAT, "focus_range" ),
|
||||
|
||||
DEFINE_FIELD( m_hFocusTarget, FIELD_EHANDLE ),
|
||||
|
||||
DEFINE_THINKFUNC( UpdateParamBlend ),
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetNearBlurDepth", InputSetNearBlurDepth ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetNearFocusDepth", InputSetNearFocusDepth ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFarFocusDepth", InputSetFarFocusDepth ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFarBlurDepth", InputSetFarBlurDepth ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetNearBlurRadius", InputSetNearBlurRadius ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFarBlurRadius", InputSetFarBlurRadius ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetFocusTarget", InputSetFocusTarget ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFocusTargetRange", InputSetFocusTargetRange ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST( CEnvDOFController, DT_EnvDOFController )
|
||||
SendPropInt( SENDINFO(m_bDOFEnabled), 1, SPROP_UNSIGNED ),
|
||||
SendPropFloat( SENDINFO(m_flNearBlurDepth), 0, SPROP_NOSCALE),
|
||||
SendPropFloat( SENDINFO(m_flNearFocusDepth), 0, SPROP_NOSCALE),
|
||||
SendPropFloat( SENDINFO(m_flFarFocusDepth), 0, SPROP_NOSCALE),
|
||||
SendPropFloat( SENDINFO(m_flFarBlurDepth), 0, SPROP_NOSCALE),
|
||||
SendPropFloat( SENDINFO(m_flNearBlurRadius), 0, SPROP_NOSCALE),
|
||||
SendPropFloat( SENDINFO(m_flFarBlurRadius), 0, SPROP_NOSCALE),
|
||||
END_SEND_TABLE()
|
||||
|
||||
void CEnvDOFController::Spawn()
|
||||
{
|
||||
SetSolid( SOLID_NONE );
|
||||
SetMoveType( MOVETYPE_NONE );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Find our target entity and hold on to it
|
||||
m_hFocusTarget = gEntList.FindEntityByName( NULL, m_strFocusTargetName, this );
|
||||
|
||||
// Update if we have a focal target
|
||||
if ( m_hFocusTarget )
|
||||
{
|
||||
SetThink( &CEnvDOFController::UpdateParamBlend );
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CEnvDOFController::Activate()
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
#ifndef MAPBASE // Mapbase moves this to Spawn() to avoid issues with save/restore and entities set via the SetFocusTarget input
|
||||
// Find our target entity and hold on to it
|
||||
m_hFocusTarget = gEntList.FindEntityByName( NULL, m_strFocusTargetName );
|
||||
|
||||
// Update if we have a focal target
|
||||
if ( m_hFocusTarget )
|
||||
{
|
||||
SetThink( &CEnvDOFController::UpdateParamBlend );
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int CEnvDOFController::UpdateTransmitState()
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
void CEnvDOFController::InputSetNearBlurDepth( inputdata_t &inputdata )
|
||||
{
|
||||
m_flNearBlurDepth = inputdata.value.Float();
|
||||
}
|
||||
|
||||
void CEnvDOFController::InputSetNearFocusDepth( inputdata_t &inputdata )
|
||||
{
|
||||
m_flNearFocusDepth = inputdata.value.Float();
|
||||
}
|
||||
|
||||
void CEnvDOFController::InputSetFarFocusDepth( inputdata_t &inputdata )
|
||||
{
|
||||
m_flFarFocusDepth = inputdata.value.Float();
|
||||
}
|
||||
|
||||
void CEnvDOFController::InputSetFarBlurDepth( inputdata_t &inputdata )
|
||||
{
|
||||
m_flFarBlurDepth = inputdata.value.Float();
|
||||
}
|
||||
|
||||
void CEnvDOFController::InputSetNearBlurRadius( inputdata_t &inputdata )
|
||||
{
|
||||
m_flNearBlurRadius = inputdata.value.Float();
|
||||
m_bDOFEnabled = ( m_flNearBlurRadius > 0.0f ) || ( m_flFarBlurRadius > 0.0f );
|
||||
}
|
||||
|
||||
void CEnvDOFController::InputSetFarBlurRadius( inputdata_t &inputdata )
|
||||
{
|
||||
m_flFarBlurRadius = inputdata.value.Float();
|
||||
m_bDOFEnabled = ( m_flNearBlurRadius > 0.0f ) || ( m_flFarBlurRadius > 0.0f );
|
||||
}
|
||||
|
||||
void CEnvDOFController::SetControllerState( DOFControlSettings_t setting )
|
||||
{
|
||||
m_flNearBlurDepth = setting.flNearBlurDepth;
|
||||
m_flNearBlurRadius = setting.flNearBlurRadius;
|
||||
m_flNearFocusDepth = setting.flNearFocusDistance;
|
||||
|
||||
m_flFarBlurDepth = setting.flFarBlurDepth;
|
||||
m_flFarBlurRadius = setting.flFarBlurRadius;
|
||||
m_flFarFocusDepth = setting.flFarFocusDistance;
|
||||
|
||||
m_bDOFEnabled = ( m_flNearBlurRadius > 0.0f ) || ( m_flFarBlurRadius > 0.0f );
|
||||
}
|
||||
|
||||
#define BLUR_DEPTH 500.0f
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Blend the parameters to the specified value
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvDOFController::UpdateParamBlend()
|
||||
{
|
||||
// Update our focal target if we have one
|
||||
if ( m_hFocusTarget )
|
||||
{
|
||||
CBasePlayer *pPlayer = AI_GetSinglePlayer();
|
||||
float flDistToFocus = ( m_hFocusTarget->GetAbsOrigin() - pPlayer->GetAbsOrigin() ).Length();
|
||||
m_flFarFocusDepth.GetForModify() = flDistToFocus + m_flFocusTargetRange;
|
||||
m_flFarBlurDepth.GetForModify() = m_flFarFocusDepth + BLUR_DEPTH;
|
||||
|
||||
SetThink( &CEnvDOFController::UpdateParamBlend );
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Set the "focus" target entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvDOFController::InputSetFocusTarget( inputdata_t &inputdata )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
m_hFocusTarget = gEntList.FindEntityByName( NULL, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller );
|
||||
#else
|
||||
m_hFocusTarget = gEntList.FindEntityByName( NULL, inputdata.value.String() );
|
||||
#endif
|
||||
|
||||
// Update if we have a focal target
|
||||
if ( m_hFocusTarget )
|
||||
{
|
||||
SetThink( &CEnvDOFController::UpdateParamBlend );
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Set the range behind the focus entity that we'll blur (in units)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvDOFController::InputSetFocusTargetRange( inputdata_t &inputdata )
|
||||
{
|
||||
m_flFocusTargetRange = inputdata.value.Float();
|
||||
}
|
||||
56
sp/src/game/server/env_dof_controller.h
Normal file
56
sp/src/game/server/env_dof_controller.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
struct DOFControlSettings_t
|
||||
{
|
||||
// Near plane
|
||||
float flNearBlurDepth;
|
||||
float flNearBlurRadius;
|
||||
float flNearFocusDistance;
|
||||
// Far plane
|
||||
float flFarBlurDepth;
|
||||
float flFarBlurRadius;
|
||||
float flFarFocusDistance;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Entity that controls depth of field postprocessing
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEnvDOFController : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS( CEnvDOFController, CPointEntity );
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
virtual void Spawn();
|
||||
virtual void Activate();
|
||||
virtual int UpdateTransmitState();
|
||||
void SetControllerState( DOFControlSettings_t setting );
|
||||
|
||||
void UpdateParamBlend();
|
||||
|
||||
// Inputs
|
||||
void InputSetNearBlurDepth( inputdata_t &inputdata );
|
||||
void InputSetNearFocusDepth( inputdata_t &inputdata );
|
||||
void InputSetFarFocusDepth( inputdata_t &inputdata );
|
||||
void InputSetFarBlurDepth( inputdata_t &inputdata );
|
||||
void InputSetNearBlurRadius( inputdata_t &inputdata );
|
||||
void InputSetFarBlurRadius( inputdata_t &inputdata );
|
||||
|
||||
void InputSetFocusTarget( inputdata_t &inputdata );
|
||||
void InputSetFocusTargetRange( inputdata_t &inputdata );
|
||||
|
||||
private:
|
||||
float m_flFocusTargetRange;
|
||||
|
||||
string_t m_strFocusTargetName; // Name of the entity to focus on
|
||||
EHANDLE m_hFocusTarget;
|
||||
|
||||
CNetworkVar( bool, m_bDOFEnabled );
|
||||
CNetworkVar( float, m_flNearBlurDepth );
|
||||
CNetworkVar( float, m_flNearFocusDepth );
|
||||
CNetworkVar( float, m_flFarFocusDepth );
|
||||
CNetworkVar( float, m_flFarBlurDepth );
|
||||
CNetworkVar( float, m_flNearBlurRadius );
|
||||
CNetworkVar( float, m_flFarBlurRadius );
|
||||
};
|
||||
542
sp/src/game/server/env_effectsscript.cpp
Normal file
542
sp/src/game/server/env_effectsscript.cpp
Normal file
@@ -0,0 +1,542 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "baseanimating.h"
|
||||
#include "Sprite.h"
|
||||
#include "SpriteTrail.h"
|
||||
#include <ctype.h>
|
||||
#include "animation.h"
|
||||
#include "eventlist.h"
|
||||
#include "npcevent.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
enum EffectType
|
||||
{
|
||||
EFFECT_TYPE_TRAIL = 1,
|
||||
EFFECT_TYPE_SPRITE
|
||||
};
|
||||
|
||||
|
||||
bool g_bUnget = false;
|
||||
unsigned char *buffer;
|
||||
char name[ 256 ];
|
||||
const char *currenttoken;
|
||||
int tokencount;
|
||||
char token[ 1204 ];
|
||||
|
||||
class CEffectScriptElement
|
||||
{
|
||||
public:
|
||||
|
||||
CEffectScriptElement();
|
||||
|
||||
char m_szEffectName[128];
|
||||
CHandle<CSpriteTrail> m_pTrail;
|
||||
CHandle<CSprite> m_pSprite;
|
||||
int m_iType;
|
||||
int m_iRenderType;
|
||||
|
||||
int m_iR;
|
||||
int m_iG;
|
||||
int m_iB;
|
||||
int m_iA;
|
||||
|
||||
char m_szAttachment[128];
|
||||
char m_szMaterial[128];
|
||||
|
||||
float m_flScale;
|
||||
float m_flFadeTime;
|
||||
float m_flTextureRes;
|
||||
|
||||
bool m_bStopFollowOnKill;
|
||||
|
||||
bool IsActive( void ) { return m_bActive; }
|
||||
void Activate( void ) { m_bActive = true; }
|
||||
void Deactivate( void ) { m_bActive = false; }
|
||||
private:
|
||||
|
||||
bool m_bActive;
|
||||
};
|
||||
|
||||
CEffectScriptElement::CEffectScriptElement()
|
||||
{
|
||||
m_pTrail = NULL;
|
||||
m_pSprite = NULL;
|
||||
m_iType = 0;
|
||||
|
||||
Deactivate();
|
||||
m_iRenderType = kRenderTransAdd;
|
||||
|
||||
m_iR = 255;
|
||||
m_iG = 0;
|
||||
m_iB = 0;
|
||||
m_iA = 255;
|
||||
|
||||
m_flScale = 1.0f;
|
||||
m_flFadeTime = 1.0f;
|
||||
m_flTextureRes = -1.0f;
|
||||
m_bStopFollowOnKill = false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// An entity which emits other entities at points
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEnvEffectsScript : public CBaseAnimating
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CEnvEffectsScript, CBaseAnimating );
|
||||
DECLARE_DATADESC();
|
||||
|
||||
virtual void Precache();
|
||||
virtual void Spawn();
|
||||
virtual int UpdateTransmitState();
|
||||
|
||||
void InputSetSequence( inputdata_t &inputdata );
|
||||
void ParseScriptFile( void );
|
||||
void LoadFromBuffer( const char *scriptfile, const char *buffer );
|
||||
|
||||
virtual void Think( void );
|
||||
|
||||
void ParseNewEffect( void );
|
||||
|
||||
const char *GetScriptFile( void )
|
||||
{
|
||||
return STRING( m_iszScriptName );
|
||||
}
|
||||
|
||||
void HandleAnimEvent ( animevent_t *pEvent );
|
||||
void TrailEffectEvent( CEffectScriptElement *pEffect );
|
||||
void SpriteEffectEvent( CEffectScriptElement *pEffect );
|
||||
|
||||
CEffectScriptElement *GetScriptElementByName( const char *pName );
|
||||
|
||||
private:
|
||||
|
||||
string_t m_iszScriptName;
|
||||
|
||||
CUtlVector< CEffectScriptElement > m_ScriptElements;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool IsRootCommand( void )
|
||||
{
|
||||
if ( !Q_stricmp( token, "effect" ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool ParseToken( void )
|
||||
{
|
||||
if ( g_bUnget )
|
||||
{
|
||||
g_bUnget = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
currenttoken = engine->ParseFile( currenttoken, token, sizeof( token ) );
|
||||
tokencount++;
|
||||
return currenttoken != NULL ? true : false;
|
||||
}
|
||||
|
||||
inline void Unget()
|
||||
{
|
||||
g_bUnget = true;
|
||||
}
|
||||
|
||||
inline bool TokenWaiting( void )
|
||||
{
|
||||
|
||||
const char *p = currenttoken;
|
||||
while ( *p && *p!='\n')
|
||||
{
|
||||
// Special handler for // comment blocks
|
||||
if ( *p == '/' && *(p+1) == '/' )
|
||||
return false;
|
||||
|
||||
if ( !V_isspace( *p ) || V_isalnum( *p ) )
|
||||
return true;
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Save/load
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_DATADESC( CEnvEffectsScript )
|
||||
// Inputs
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetSequence", InputSetSequence ),
|
||||
DEFINE_KEYFIELD( m_iszScriptName, FIELD_STRING, "scriptfile" ),
|
||||
// DEFINE_FIELD( m_ScriptElements, CUtlVector < CEffectScriptElement > ),
|
||||
|
||||
DEFINE_FUNCTION( Think ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_effectscript, CEnvEffectsScript );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Should we transmit it to the client?
|
||||
//-----------------------------------------------------------------------------
|
||||
int CEnvEffectsScript::UpdateTransmitState()
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Precache
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEffectsScript::Precache()
|
||||
{
|
||||
BaseClass::Precache();
|
||||
PrecacheModel( STRING( GetModelName() ) );
|
||||
|
||||
if ( m_iszScriptName != NULL_STRING )
|
||||
ParseScriptFile();
|
||||
else
|
||||
Warning( "CEnvEffectsScript with no script!\n" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Spawn
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEffectsScript::Spawn()
|
||||
{
|
||||
Precache();
|
||||
BaseClass::Spawn();
|
||||
|
||||
// We need a model for its animation sequences even though we don't render it
|
||||
SetModel( STRING( GetModelName() ) );
|
||||
|
||||
AddEffects( EF_NODRAW );
|
||||
|
||||
SetThink( &CEnvEffectsScript::Think );
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
}
|
||||
|
||||
void CEnvEffectsScript::Think( void )
|
||||
{
|
||||
StudioFrameAdvance();
|
||||
DispatchAnimEvents( this );
|
||||
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
}
|
||||
|
||||
void CEnvEffectsScript::TrailEffectEvent( CEffectScriptElement *pEffect )
|
||||
{
|
||||
if ( pEffect->IsActive() == false )
|
||||
{
|
||||
//Only one type of this effect active at a time.
|
||||
if ( pEffect->m_pTrail == NULL )
|
||||
{
|
||||
pEffect->m_pTrail = CSpriteTrail::SpriteTrailCreate( pEffect->m_szMaterial, GetAbsOrigin(), true );
|
||||
pEffect->m_pTrail->FollowEntity( this );
|
||||
pEffect->m_pTrail->SetTransparency( pEffect->m_iRenderType, pEffect->m_iR, pEffect->m_iG, pEffect->m_iB, pEffect->m_iA, kRenderFxNone );
|
||||
pEffect->m_pTrail->SetStartWidth( pEffect->m_flScale );
|
||||
if ( pEffect->m_flTextureRes < 0.0f )
|
||||
{
|
||||
pEffect->m_pTrail->SetTextureResolution( 1.0f / ( 16.0f * pEffect->m_flScale ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
pEffect->m_pTrail->SetTextureResolution( pEffect->m_flTextureRes );
|
||||
}
|
||||
pEffect->m_pTrail->SetLifeTime( pEffect->m_flFadeTime );
|
||||
pEffect->m_pTrail->TurnOn();
|
||||
pEffect->m_pTrail->SetAttachment( this, LookupAttachment( pEffect->m_szAttachment ) );
|
||||
|
||||
pEffect->Activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEnvEffectsScript::SpriteEffectEvent( CEffectScriptElement *pEffect )
|
||||
{
|
||||
if ( pEffect->IsActive() == false )
|
||||
{
|
||||
//Only one type of this effect active at a time.
|
||||
if ( pEffect->m_pSprite == NULL )
|
||||
{
|
||||
pEffect->m_pSprite = CSprite::SpriteCreate( pEffect->m_szMaterial, GetAbsOrigin(), true );
|
||||
pEffect->m_pSprite->FollowEntity( this );
|
||||
pEffect->m_pSprite->SetTransparency( pEffect->m_iRenderType, pEffect->m_iR, pEffect->m_iG, pEffect->m_iB, pEffect->m_iA, kRenderFxNone );
|
||||
pEffect->m_pSprite->SetScale( pEffect->m_flScale );
|
||||
pEffect->m_pSprite->TurnOn();
|
||||
pEffect->m_pSprite->SetAttachment( this, LookupAttachment( pEffect->m_szAttachment ) );
|
||||
|
||||
pEffect->Activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEnvEffectsScript::HandleAnimEvent ( animevent_t *pEvent )
|
||||
{
|
||||
if ( pEvent->event == AE_START_SCRIPTED_EFFECT )
|
||||
{
|
||||
CEffectScriptElement *pCurrent = GetScriptElementByName( pEvent->options );
|
||||
|
||||
if ( pCurrent )
|
||||
{
|
||||
if ( pCurrent->m_iType == EFFECT_TYPE_TRAIL )
|
||||
TrailEffectEvent( pCurrent );
|
||||
else if ( pCurrent->m_iType == EFFECT_TYPE_SPRITE )
|
||||
SpriteEffectEvent( pCurrent );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( pEvent->event == AE_STOP_SCRIPTED_EFFECT )
|
||||
{
|
||||
CEffectScriptElement *pCurrent = GetScriptElementByName( pEvent->options );
|
||||
|
||||
if ( pCurrent && pCurrent->IsActive() )
|
||||
{
|
||||
pCurrent->Deactivate();
|
||||
|
||||
if ( pCurrent->m_iType == EFFECT_TYPE_TRAIL )
|
||||
{
|
||||
if ( pCurrent->m_bStopFollowOnKill == true )
|
||||
{
|
||||
Vector vOrigin;
|
||||
GetAttachment( pCurrent->m_pTrail->m_nAttachment, vOrigin );
|
||||
|
||||
pCurrent->m_pTrail->StopFollowingEntity();
|
||||
|
||||
pCurrent->m_pTrail->m_hAttachedToEntity = NULL;
|
||||
pCurrent->m_pTrail->m_nAttachment = 0;
|
||||
|
||||
pCurrent->m_pTrail->SetAbsOrigin( vOrigin);
|
||||
}
|
||||
|
||||
pCurrent->m_pTrail->FadeAndDie( pCurrent->m_flFadeTime );
|
||||
pCurrent->m_pTrail = NULL;
|
||||
}
|
||||
|
||||
else if ( pCurrent->m_iType == EFFECT_TYPE_SPRITE )
|
||||
{
|
||||
if ( pCurrent->m_bStopFollowOnKill == true )
|
||||
{
|
||||
Vector vOrigin;
|
||||
GetAttachment( pCurrent->m_pSprite->m_nAttachment, vOrigin );
|
||||
|
||||
pCurrent->m_pSprite->StopFollowingEntity();
|
||||
|
||||
pCurrent->m_pSprite->m_hAttachedToEntity = NULL;
|
||||
pCurrent->m_pSprite->m_nAttachment = 0;
|
||||
|
||||
pCurrent->m_pSprite->SetAbsOrigin( vOrigin);
|
||||
}
|
||||
|
||||
pCurrent->m_pSprite->FadeAndDie( pCurrent->m_flFadeTime );
|
||||
pCurrent->m_pSprite = NULL;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BaseClass::HandleAnimEvent( pEvent );
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input that sets the sequence of the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEffectsScript::InputSetSequence( inputdata_t &inputdata )
|
||||
{
|
||||
if ( inputdata.value.StringID() != NULL_STRING )
|
||||
{
|
||||
int nSequence = LookupSequence( STRING( inputdata.value.StringID() ) );
|
||||
if ( nSequence != ACT_INVALID )
|
||||
{
|
||||
SetSequence( nSequence );
|
||||
ResetSequenceInfo();
|
||||
SetCycle( 0.0f );
|
||||
m_flPlaybackRate = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEnvEffectsScript::ParseScriptFile( void )
|
||||
{
|
||||
int length = 0;
|
||||
m_ScriptElements.RemoveAll();
|
||||
const char *pScriptName = GetScriptFile();
|
||||
|
||||
//Reset everything.
|
||||
g_bUnget = false;
|
||||
currenttoken = NULL;
|
||||
tokencount = 0;
|
||||
memset( token, 0, 1204 );
|
||||
memset( name, 0, 256 );
|
||||
|
||||
|
||||
unsigned char *buffer = (unsigned char *)UTIL_LoadFileForMe( pScriptName, &length );
|
||||
if ( length <= 0 || !buffer )
|
||||
{
|
||||
DevMsg( 1, "CEnvEffectsScript: failed to load %s\n", pScriptName );
|
||||
return;
|
||||
}
|
||||
|
||||
currenttoken = (const char *)buffer;
|
||||
LoadFromBuffer( pScriptName, (const char *)buffer );
|
||||
|
||||
UTIL_FreeFile( buffer );
|
||||
}
|
||||
|
||||
void CEnvEffectsScript::LoadFromBuffer( const char *scriptfile, const char *buffer )
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
ParseToken();
|
||||
|
||||
if ( !token[0] )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( token, "effect" ) )
|
||||
{
|
||||
ParseNewEffect();
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "CEnvEffectsScript: Unknown entry type '%s'\n", token );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEnvEffectsScript::ParseNewEffect( void )
|
||||
{
|
||||
//Add a new effect to the list.
|
||||
CEffectScriptElement NewElement;
|
||||
|
||||
// Effect Group Name
|
||||
ParseToken();
|
||||
Q_strncpy( NewElement.m_szEffectName, token, sizeof( NewElement.m_szEffectName ) );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
ParseToken();
|
||||
|
||||
// Oops, part of next definition
|
||||
if( IsRootCommand() )
|
||||
{
|
||||
Unget();
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( token, "{" ) )
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
ParseToken();
|
||||
if ( !Q_stricmp( token, "}" ) )
|
||||
break;
|
||||
|
||||
if ( !Q_stricmp( token, "type" ) )
|
||||
{
|
||||
ParseToken();
|
||||
|
||||
if ( !Q_stricmp( token, "trail" ) )
|
||||
NewElement.m_iType = EFFECT_TYPE_TRAIL;
|
||||
else if ( !Q_stricmp( token, "sprite" ) )
|
||||
NewElement.m_iType = EFFECT_TYPE_SPRITE;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( token, "material" ) )
|
||||
{
|
||||
ParseToken();
|
||||
Q_strncpy( NewElement.m_szMaterial, token, sizeof( NewElement.m_szMaterial ) );
|
||||
PrecacheModel( NewElement.m_szMaterial );
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( token, "attachment" ) )
|
||||
{
|
||||
ParseToken();
|
||||
Q_strncpy( NewElement.m_szAttachment, token, sizeof( NewElement.m_szAttachment ) );
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( token, "color" ) )
|
||||
{
|
||||
ParseToken();
|
||||
sscanf( token, "%i %i %i %i", &NewElement.m_iR, &NewElement.m_iG, &NewElement.m_iB, &NewElement.m_iA );
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( token, "scale" ) )
|
||||
{
|
||||
ParseToken();
|
||||
|
||||
NewElement.m_flScale = atof( token );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( token, "texturescale" ) )
|
||||
{
|
||||
ParseToken();
|
||||
|
||||
float flTextureScale = atof( token );
|
||||
NewElement.m_flTextureRes = (flTextureScale > 0.0f) ? 1.0f / flTextureScale : 0.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( token, "fadetime" ) )
|
||||
{
|
||||
ParseToken();
|
||||
|
||||
NewElement.m_flFadeTime = atof( token );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( token, "stopfollowonkill" ) )
|
||||
{
|
||||
ParseToken();
|
||||
|
||||
NewElement.m_bStopFollowOnKill = !!atoi( token );
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_ScriptElements.AddToTail( NewElement );
|
||||
}
|
||||
|
||||
CEffectScriptElement *CEnvEffectsScript::GetScriptElementByName( const char *pName )
|
||||
{
|
||||
for ( int i = 0; i < m_ScriptElements.Count(); i++ )
|
||||
{
|
||||
CEffectScriptElement *pCurrent = &m_ScriptElements.Element( i );
|
||||
|
||||
if ( pCurrent && !Q_stricmp( pCurrent->m_szEffectName, pName ) )
|
||||
{
|
||||
return pCurrent;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
475
sp/src/game/server/env_entity_maker.cpp
Normal file
475
sp/src/game/server/env_entity_maker.cpp
Normal file
@@ -0,0 +1,475 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "entityoutput.h"
|
||||
#include "TemplateEntities.h"
|
||||
#include "point_template.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define SF_ENTMAKER_AUTOSPAWN 0x0001
|
||||
#define SF_ENTMAKER_WAITFORDESTRUCTION 0x0002
|
||||
#define SF_ENTMAKER_IGNOREFACING 0x0004
|
||||
#define SF_ENTMAKER_CHECK_FOR_SPACE 0x0008
|
||||
#define SF_ENTMAKER_CHECK_PLAYER_LOOKING 0x0010
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: An entity that mapmakers can use to ensure there's a required entity never runs out.
|
||||
// i.e. physics cannisters that need to be used.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEnvEntityMaker : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS( CEnvEntityMaker, CPointEntity );
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
|
||||
virtual void Spawn( void );
|
||||
virtual void Activate( void );
|
||||
|
||||
void SpawnEntity( Vector vecAlternateOrigin = vec3_invalid, QAngle vecAlternateAngles = vec3_angle );
|
||||
void CheckSpawnThink( void );
|
||||
void InputForceSpawn( inputdata_t &inputdata );
|
||||
void InputForceSpawnAtEntityOrigin( inputdata_t &inputdata );
|
||||
#ifdef MAPBASE
|
||||
void InputForceSpawnAtEntityCenter( inputdata_t &inputdata );
|
||||
void InputForceSpawnAtPosition( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
void SpawnEntityFromScript();
|
||||
void SpawnEntityAtEntityOriginFromScript(HSCRIPT hEntity);
|
||||
void SpawnEntityAtNamedEntityOriginFromScript(const char* pszName);
|
||||
void SpawnEntityAtLocationFromScript(const Vector& vecAlternateOrigin, const Vector& vecAlternateAngles);
|
||||
private:
|
||||
|
||||
CPointTemplate *FindTemplate();
|
||||
|
||||
bool HasRoomToSpawn();
|
||||
bool IsPlayerLooking();
|
||||
|
||||
Vector m_vecEntityMins;
|
||||
Vector m_vecEntityMaxs;
|
||||
EHANDLE m_hCurrentInstance;
|
||||
EHANDLE m_hCurrentBlocker; // Last entity that blocked us spawning something
|
||||
Vector m_vecBlockerOrigin;
|
||||
|
||||
// Movement after spawn
|
||||
QAngle m_angPostSpawnDirection;
|
||||
float m_flPostSpawnDirectionVariance;
|
||||
float m_flPostSpawnSpeed;
|
||||
bool m_bPostSpawnUseAngles;
|
||||
|
||||
string_t m_iszTemplate;
|
||||
|
||||
COutputEvent m_pOutputOnSpawned;
|
||||
COutputEvent m_pOutputOnFailedSpawn;
|
||||
#ifdef MAPBASE
|
||||
COutputEHANDLE m_pOutputOutEntity;
|
||||
#endif
|
||||
};
|
||||
|
||||
BEGIN_DATADESC( CEnvEntityMaker )
|
||||
// DEFINE_FIELD( m_vecEntityMins, FIELD_VECTOR ),
|
||||
// DEFINE_FIELD( m_vecEntityMaxs, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_hCurrentInstance, FIELD_EHANDLE ),
|
||||
DEFINE_FIELD( m_hCurrentBlocker, FIELD_EHANDLE ),
|
||||
DEFINE_FIELD( m_vecBlockerOrigin, FIELD_VECTOR ),
|
||||
DEFINE_KEYFIELD( m_iszTemplate, FIELD_STRING, "EntityTemplate" ),
|
||||
DEFINE_KEYFIELD( m_angPostSpawnDirection, FIELD_VECTOR, "PostSpawnDirection" ),
|
||||
DEFINE_KEYFIELD( m_flPostSpawnDirectionVariance, FIELD_FLOAT, "PostSpawnDirectionVariance" ),
|
||||
DEFINE_KEYFIELD( m_flPostSpawnSpeed, FIELD_FLOAT, "PostSpawnSpeed" ),
|
||||
DEFINE_KEYFIELD( m_bPostSpawnUseAngles, FIELD_BOOLEAN, "PostSpawnInheritAngles" ),
|
||||
|
||||
// Outputs
|
||||
DEFINE_OUTPUT( m_pOutputOnSpawned, "OnEntitySpawned" ),
|
||||
DEFINE_OUTPUT( m_pOutputOnFailedSpawn, "OnEntityFailedSpawn" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_OUTPUT( m_pOutputOutEntity, "OutSpawnedEntity" ),
|
||||
#endif
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ForceSpawn", InputForceSpawn ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "ForceSpawnAtEntityOrigin", InputForceSpawnAtEntityOrigin ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "ForceSpawnAtEntityCenter", InputForceSpawnAtEntityCenter ),
|
||||
DEFINE_INPUTFUNC( FIELD_VECTOR, "ForceSpawnAtPosition", InputForceSpawnAtPosition ),
|
||||
#endif
|
||||
|
||||
// Functions
|
||||
DEFINE_THINKFUNC( CheckSpawnThink ),
|
||||
END_DATADESC()
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC( CEnvEntityMaker, CBaseEntity, "env_entity_maker" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( SpawnEntityFromScript, "SpawnEntity", "Create an entity at the location of the maker" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( SpawnEntityAtEntityOriginFromScript, "SpawnEntityAtEntityOrigin", "Create an entity at the location of a specified entity instance" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( SpawnEntityAtNamedEntityOriginFromScript, "SpawnEntityAtNamedEntityOrigin", "Create an entity at the location of a named entity" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( SpawnEntityAtLocationFromScript, "SpawnEntityAtLocation", "Create an entity at a specified location and orientaton, orientation is Euler angle in degrees (pitch, yaw, roll)" )
|
||||
END_SCRIPTDESC()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_entity_maker, CEnvEntityMaker );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::Spawn( void )
|
||||
{
|
||||
m_vecEntityMins = vec3_origin;
|
||||
m_vecEntityMaxs = vec3_origin;
|
||||
m_hCurrentInstance = NULL;
|
||||
m_hCurrentBlocker = NULL;
|
||||
m_vecBlockerOrigin = vec3_origin;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::Activate( void )
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
// check for valid template
|
||||
if ( m_iszTemplate == NULL_STRING )
|
||||
{
|
||||
Warning( "env_entity_maker %s has no template entity!\n", GetEntityName().ToCStr() );
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
|
||||
// Spawn an instance
|
||||
if ( m_spawnflags & SF_ENTMAKER_AUTOSPAWN )
|
||||
{
|
||||
SpawnEntity();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CPointTemplate *CEnvEntityMaker::FindTemplate()
|
||||
{
|
||||
// Find our point_template
|
||||
CPointTemplate *pTemplate = dynamic_cast<CPointTemplate *>(gEntList.FindEntityByName( NULL, STRING(m_iszTemplate) ));
|
||||
if ( !pTemplate )
|
||||
{
|
||||
Warning( "env_entity_maker %s failed to find template %s.\n", GetEntityName().ToCStr(), STRING(m_iszTemplate) );
|
||||
}
|
||||
|
||||
return pTemplate;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawn an instance of the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::SpawnEntity( Vector vecAlternateOrigin, QAngle vecAlternateAngles )
|
||||
{
|
||||
CPointTemplate *pTemplate = FindTemplate();
|
||||
if (!pTemplate)
|
||||
return;
|
||||
|
||||
// Spawn our template
|
||||
Vector vecSpawnOrigin = GetAbsOrigin();
|
||||
QAngle vecSpawnAngles = GetAbsAngles();
|
||||
|
||||
if( vecAlternateOrigin != vec3_invalid )
|
||||
{
|
||||
// We have a valid alternate origin and angles. Use those instead
|
||||
// of spawning the items at my own origin and angles.
|
||||
vecSpawnOrigin = vecAlternateOrigin;
|
||||
vecSpawnAngles = vecAlternateAngles;
|
||||
}
|
||||
|
||||
CUtlVector<CBaseEntity*> hNewEntities;
|
||||
if ( !pTemplate->CreateInstance( vecSpawnOrigin, vecSpawnAngles, &hNewEntities ) )
|
||||
return;
|
||||
|
||||
//Adrian: oops we couldn't spawn the entity (or entities) for some reason!
|
||||
if ( hNewEntities.Count() == 0 )
|
||||
return;
|
||||
|
||||
m_hCurrentInstance = hNewEntities[0];
|
||||
|
||||
// Assume it'll block us
|
||||
m_hCurrentBlocker = m_hCurrentInstance;
|
||||
m_vecBlockerOrigin = m_hCurrentBlocker->GetAbsOrigin();
|
||||
|
||||
// Store off the mins & maxs the first time we spawn
|
||||
if ( m_vecEntityMins == vec3_origin )
|
||||
{
|
||||
m_hCurrentInstance->CollisionProp()->WorldSpaceAABB( &m_vecEntityMins, &m_vecEntityMaxs );
|
||||
m_vecEntityMins -= m_hCurrentInstance->GetAbsOrigin();
|
||||
m_vecEntityMaxs -= m_hCurrentInstance->GetAbsOrigin();
|
||||
}
|
||||
|
||||
// Fire our output
|
||||
m_pOutputOnSpawned.FireOutput( this, this );
|
||||
|
||||
// Start thinking
|
||||
if ( m_spawnflags & SF_ENTMAKER_AUTOSPAWN )
|
||||
{
|
||||
SetThink( &CEnvEntityMaker::CheckSpawnThink );
|
||||
SetNextThink( gpGlobals->curtime + 0.5f );
|
||||
}
|
||||
|
||||
// If we have a specified post spawn speed, apply it to all spawned entities
|
||||
if ( m_flPostSpawnSpeed )
|
||||
{
|
||||
for ( int i = 0; i < hNewEntities.Count(); i++ )
|
||||
{
|
||||
CBaseEntity *pEntity = hNewEntities[i];
|
||||
|
||||
#ifdef MAPBASE
|
||||
m_pOutputOutEntity.Set(pEntity, pEntity, this);
|
||||
#endif
|
||||
|
||||
if ( pEntity->GetMoveType() == MOVETYPE_NONE )
|
||||
continue;
|
||||
|
||||
// Calculate a velocity for this entity
|
||||
Vector vForward,vRight,vUp;
|
||||
QAngle angSpawnDir( m_angPostSpawnDirection );
|
||||
if ( m_bPostSpawnUseAngles )
|
||||
{
|
||||
if ( GetParent() )
|
||||
{
|
||||
angSpawnDir += GetParent()->GetAbsAngles();
|
||||
}
|
||||
else
|
||||
{
|
||||
angSpawnDir += GetAbsAngles();
|
||||
}
|
||||
}
|
||||
AngleVectors( angSpawnDir, &vForward, &vRight, &vUp );
|
||||
Vector vecShootDir = vForward;
|
||||
vecShootDir += vRight * random->RandomFloat(-1, 1) * m_flPostSpawnDirectionVariance;
|
||||
vecShootDir += vForward * random->RandomFloat(-1, 1) * m_flPostSpawnDirectionVariance;
|
||||
vecShootDir += vUp * random->RandomFloat(-1, 1) * m_flPostSpawnDirectionVariance;
|
||||
VectorNormalize( vecShootDir );
|
||||
vecShootDir *= m_flPostSpawnSpeed;
|
||||
|
||||
// Apply it to the entity
|
||||
IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject();
|
||||
if ( pPhysicsObject )
|
||||
{
|
||||
pPhysicsObject->AddVelocity(&vecShootDir, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
pEntity->SetAbsVelocity( vecShootDir );
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < hNewEntities.Count(); i++ )
|
||||
{
|
||||
m_pOutputOutEntity.Set(hNewEntities[i], hNewEntities[i], this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pTemplate->CreationComplete( hNewEntities );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawn an instance of the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::SpawnEntityFromScript()
|
||||
{
|
||||
SpawnEntity();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawn an instance of the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::SpawnEntityAtEntityOriginFromScript( HSCRIPT hEntity )
|
||||
{
|
||||
CBaseEntity *pTargetEntity = ToEnt( hEntity );
|
||||
if ( pTargetEntity )
|
||||
{
|
||||
SpawnEntity( pTargetEntity->GetAbsOrigin(), pTargetEntity->GetAbsAngles() );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawn an instance of the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::SpawnEntityAtNamedEntityOriginFromScript( const char *pszName )
|
||||
{
|
||||
CBaseEntity *pTargetEntity = gEntList.FindEntityByName( NULL, pszName, this, NULL, NULL );
|
||||
|
||||
if( pTargetEntity )
|
||||
{
|
||||
SpawnEntity( pTargetEntity->GetAbsOrigin(), pTargetEntity->GetAbsAngles() );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawn an instance of the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::SpawnEntityAtLocationFromScript( const Vector &vecAlternateOrigin, const Vector &vecAlternateAngles )
|
||||
{
|
||||
SpawnEntity( vecAlternateOrigin, *((QAngle *)&vecAlternateAngles) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns whether or not the template entities can fit if spawned.
|
||||
// Input : pBlocker - Returns blocker unless NULL.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CEnvEntityMaker::HasRoomToSpawn()
|
||||
{
|
||||
// Do we have a blocker from last time?
|
||||
if ( m_hCurrentBlocker )
|
||||
{
|
||||
// If it hasn't moved, abort immediately
|
||||
if ( m_vecBlockerOrigin == m_hCurrentBlocker->GetAbsOrigin() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if there's enough room to spawn
|
||||
trace_t tr;
|
||||
UTIL_TraceHull( GetAbsOrigin(), GetAbsOrigin(), m_vecEntityMins, m_vecEntityMaxs, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
|
||||
if ( tr.m_pEnt || tr.startsolid )
|
||||
{
|
||||
// Store off our blocker to check later
|
||||
m_hCurrentBlocker = tr.m_pEnt;
|
||||
if ( m_hCurrentBlocker )
|
||||
{
|
||||
m_vecBlockerOrigin = m_hCurrentBlocker->GetAbsOrigin();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if the player is looking towards us.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CEnvEntityMaker::IsPlayerLooking()
|
||||
{
|
||||
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
|
||||
if ( pPlayer )
|
||||
{
|
||||
// Only spawn if the player's looking away from me
|
||||
Vector vLookDir = pPlayer->EyeDirection3D();
|
||||
Vector vTargetDir = GetAbsOrigin() - pPlayer->EyePosition();
|
||||
VectorNormalize( vTargetDir );
|
||||
|
||||
float fDotPr = DotProduct( vLookDir,vTargetDir );
|
||||
if ( fDotPr > 0 )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Check to see if we should spawn another instance
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::CheckSpawnThink( void )
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime + 0.5f );
|
||||
|
||||
// Do we have an instance?
|
||||
if ( m_hCurrentInstance )
|
||||
{
|
||||
// If Wait-For-Destruction is set, abort immediately
|
||||
if ( m_spawnflags & SF_ENTMAKER_WAITFORDESTRUCTION )
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to see if there's enough room to spawn
|
||||
if ( !HasRoomToSpawn() )
|
||||
return;
|
||||
|
||||
// We're clear, now check to see if the player's looking
|
||||
if ( !( HasSpawnFlags( SF_ENTMAKER_IGNOREFACING ) ) && IsPlayerLooking() )
|
||||
return;
|
||||
|
||||
// Clear, no player watching, so spawn!
|
||||
SpawnEntity();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawns the entities, checking for space if flagged to do so.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::InputForceSpawn( inputdata_t &inputdata )
|
||||
{
|
||||
CPointTemplate *pTemplate = FindTemplate();
|
||||
if (!pTemplate)
|
||||
return;
|
||||
|
||||
if ( HasSpawnFlags( SF_ENTMAKER_CHECK_FOR_SPACE ) && !HasRoomToSpawn() )
|
||||
{
|
||||
m_pOutputOnFailedSpawn.FireOutput( this, this );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( HasSpawnFlags( SF_ENTMAKER_CHECK_PLAYER_LOOKING ) && IsPlayerLooking() )
|
||||
{
|
||||
m_pOutputOnFailedSpawn.FireOutput( this, this );
|
||||
return;
|
||||
}
|
||||
|
||||
SpawnEntity();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::InputForceSpawnAtEntityOrigin( inputdata_t &inputdata )
|
||||
{
|
||||
CBaseEntity *pTargetEntity = gEntList.FindEntityByName( NULL, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller );
|
||||
|
||||
if( pTargetEntity )
|
||||
{
|
||||
SpawnEntity( pTargetEntity->GetAbsOrigin(), pTargetEntity->GetAbsAngles() );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::InputForceSpawnAtEntityCenter( inputdata_t &inputdata )
|
||||
{
|
||||
CBaseEntity *pTargetEntity = gEntList.FindEntityByName( NULL, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller );
|
||||
|
||||
if( pTargetEntity )
|
||||
{
|
||||
SpawnEntity( pTargetEntity->WorldSpaceCenter(), pTargetEntity->GetAbsAngles() );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::InputForceSpawnAtPosition(inputdata_t &inputdata)
|
||||
{
|
||||
Vector vecPos;
|
||||
inputdata.value.Vector3D(vecPos);
|
||||
if (vecPos != vec3_origin && vecPos.IsValid())
|
||||
{
|
||||
SpawnEntity(vecPos, GetLocalAngles());
|
||||
}
|
||||
}
|
||||
#endif // MAPBASE
|
||||
|
||||
336
sp/src/game/server/env_global_light.cpp
Normal file
336
sp/src/game/server/env_global_light.cpp
Normal file
@@ -0,0 +1,336 @@
|
||||
//========= Copyright 1996-2010, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: global dynamic light. Ported from Insolence's port of Alien Swarm's env_global_light.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FIXME: This really should inherit from something more lightweight
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Sunlight shadow control entity
|
||||
//------------------------------------------------------------------------------
|
||||
class CGlobalLight : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CGlobalLight, CBaseEntity );
|
||||
|
||||
CGlobalLight();
|
||||
|
||||
void Spawn( void );
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
virtual bool GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen );
|
||||
int UpdateTransmitState();
|
||||
|
||||
// Inputs
|
||||
void InputSetAngles( inputdata_t &inputdata );
|
||||
void InputEnable( inputdata_t &inputdata );
|
||||
void InputDisable( inputdata_t &inputdata );
|
||||
void InputSetTexture( inputdata_t &inputdata );
|
||||
void InputSetEnableShadows( inputdata_t &inputdata );
|
||||
void InputSetLightColor( inputdata_t &inputdata );
|
||||
#ifdef MAPBASE
|
||||
void InputSetBrightness( inputdata_t &inputdata );
|
||||
void InputSetColorTransitionTime( inputdata_t &inputdata );
|
||||
void InputSetXOffset( inputdata_t &inputdata ) { m_flEastOffset = inputdata.value.Float(); }
|
||||
void InputSetYOffset( inputdata_t &inputdata ) { m_flForwardOffset = inputdata.value.Float(); }
|
||||
void InputSetOrthoSize( inputdata_t &inputdata ) { m_flOrthoSize = inputdata.value.Float(); }
|
||||
void InputSetDistance( inputdata_t &inputdata ) { m_flSunDistance = inputdata.value.Float(); }
|
||||
void InputSetFOV( inputdata_t &inputdata ) { m_flFOV = inputdata.value.Float(); }
|
||||
void InputSetNearZDistance( inputdata_t &inputdata ) { m_flNearZ = inputdata.value.Float(); }
|
||||
void InputSetNorthOffset( inputdata_t &inputdata ) { m_flNorthOffset = inputdata.value.Float(); }
|
||||
#endif
|
||||
|
||||
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
private:
|
||||
CNetworkVector( m_shadowDirection );
|
||||
|
||||
CNetworkVar( bool, m_bEnabled );
|
||||
|
||||
CNetworkString( m_TextureName, MAX_PATH );
|
||||
#ifdef MAPBASE
|
||||
CNetworkVar( int, m_nSpotlightTextureFrame );
|
||||
#endif
|
||||
CNetworkColor32( m_LightColor );
|
||||
#ifdef MAPBASE
|
||||
CNetworkVar( float, m_flBrightnessScale );
|
||||
#endif
|
||||
CNetworkVar( float, m_flColorTransitionTime );
|
||||
CNetworkVar( float, m_flSunDistance );
|
||||
CNetworkVar( float, m_flFOV );
|
||||
CNetworkVar( float, m_flNearZ );
|
||||
CNetworkVar( float, m_flNorthOffset );
|
||||
#ifdef MAPBASE
|
||||
CNetworkVar( float, m_flEastOffset ); // xoffset
|
||||
CNetworkVar( float, m_flForwardOffset ); // yoffset
|
||||
CNetworkVar( float, m_flOrthoSize );
|
||||
#endif
|
||||
CNetworkVar( bool, m_bEnableShadows );
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(env_global_light, CGlobalLight);
|
||||
|
||||
BEGIN_DATADESC( CGlobalLight )
|
||||
|
||||
DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ),
|
||||
DEFINE_AUTO_ARRAY_KEYFIELD( m_TextureName, FIELD_CHARACTER, "texturename" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_nSpotlightTextureFrame, FIELD_INTEGER, "textureframe" ),
|
||||
#endif
|
||||
DEFINE_KEYFIELD( m_flSunDistance, FIELD_FLOAT, "distance" ),
|
||||
DEFINE_KEYFIELD( m_flFOV, FIELD_FLOAT, "fov" ),
|
||||
DEFINE_KEYFIELD( m_flNearZ, FIELD_FLOAT, "nearz" ),
|
||||
DEFINE_KEYFIELD( m_flNorthOffset, FIELD_FLOAT, "northoffset" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_flEastOffset, FIELD_FLOAT, "eastoffset" ),
|
||||
DEFINE_KEYFIELD( m_flForwardOffset, FIELD_FLOAT, "forwardoffset" ),
|
||||
DEFINE_KEYFIELD( m_flOrthoSize, FIELD_FLOAT, "orthosize" ),
|
||||
#endif
|
||||
DEFINE_KEYFIELD( m_bEnableShadows, FIELD_BOOLEAN, "enableshadows" ),
|
||||
DEFINE_FIELD( m_LightColor, FIELD_COLOR32 ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_flBrightnessScale, FIELD_FLOAT, "brightnessscale" ),
|
||||
#endif
|
||||
DEFINE_KEYFIELD( m_flColorTransitionTime, FIELD_FLOAT, "colortransitiontime" ),
|
||||
|
||||
DEFINE_FIELD( m_shadowDirection, FIELD_VECTOR ),
|
||||
|
||||
// Inputs
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetXOffset", InputSetXOffset ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetYOffset", InputSetYOffset ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetOrthoSize", InputSetOrthoSize ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetDistance", InputSetDistance ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFOV", InputSetFOV ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetNearZDistance", InputSetNearZDistance ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetNorthOffset", InputSetNorthOffset ),
|
||||
#else
|
||||
DEFINE_INPUT( m_flSunDistance, FIELD_FLOAT, "SetDistance" ),
|
||||
DEFINE_INPUT( m_flFOV, FIELD_FLOAT, "SetFOV" ),
|
||||
DEFINE_INPUT( m_flNearZ, FIELD_FLOAT, "SetNearZDistance" ),
|
||||
DEFINE_INPUT( m_flNorthOffset, FIELD_FLOAT, "SetNorthOffset" ),
|
||||
#endif
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_COLOR32, "LightColor", InputSetLightColor ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetAngles", InputSetAngles ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetTexture", InputSetTexture ),
|
||||
DEFINE_INPUTFUNC( FIELD_BOOLEAN, "EnableShadows", InputSetEnableShadows ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetBrightness", InputSetBrightness ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetColorTransitionTime", InputSetColorTransitionTime ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST_NOBASE(CGlobalLight, DT_GlobalLight)
|
||||
SendPropVector(SENDINFO(m_shadowDirection), -1, SPROP_NOSCALE ),
|
||||
SendPropBool(SENDINFO(m_bEnabled) ),
|
||||
SendPropString(SENDINFO(m_TextureName)),
|
||||
#ifdef MAPBASE
|
||||
SendPropInt(SENDINFO(m_nSpotlightTextureFrame)),
|
||||
#endif
|
||||
/*SendPropInt(SENDINFO (m_LightColor ), 32, SPROP_UNSIGNED, SendProxy_Color32ToInt32 ),*/
|
||||
SendPropInt(SENDINFO (m_LightColor ), 32, SPROP_UNSIGNED, SendProxy_Color32ToInt ),
|
||||
#ifdef MAPBASE
|
||||
SendPropFloat( SENDINFO( m_flBrightnessScale ) ),
|
||||
#endif
|
||||
SendPropFloat( SENDINFO( m_flColorTransitionTime ) ),
|
||||
SendPropFloat(SENDINFO(m_flSunDistance), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat(SENDINFO(m_flFOV), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat(SENDINFO(m_flNearZ), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat(SENDINFO(m_flNorthOffset), 0, SPROP_NOSCALE ),
|
||||
#ifdef MAPBASE
|
||||
SendPropFloat(SENDINFO(m_flEastOffset), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat(SENDINFO(m_flForwardOffset), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat(SENDINFO(m_flOrthoSize), 0, SPROP_NOSCALE ),
|
||||
#endif
|
||||
SendPropBool( SENDINFO( m_bEnableShadows ) ),
|
||||
END_SEND_TABLE()
|
||||
|
||||
|
||||
CGlobalLight::CGlobalLight()
|
||||
{
|
||||
#if defined( _X360 )
|
||||
Q_strcpy( m_TextureName.GetForModify(), "effects/flashlight_border" );
|
||||
#else
|
||||
Q_strcpy( m_TextureName.GetForModify(), "effects/flashlight001" );
|
||||
#endif
|
||||
#ifdef MAPBASE
|
||||
m_LightColor.Init( 255, 255, 255, 255 );
|
||||
#else
|
||||
m_LightColor.Init( 255, 255, 255, 1 );
|
||||
#endif
|
||||
m_flColorTransitionTime = 0.5f;
|
||||
m_flSunDistance = 10000.0f;
|
||||
m_flFOV = 5.0f;
|
||||
m_bEnableShadows = false;
|
||||
#ifdef MAPBASE
|
||||
m_nSpotlightTextureFrame = 0;
|
||||
m_flBrightnessScale = 1.0f;
|
||||
m_flOrthoSize = 1000.0f;
|
||||
#endif
|
||||
m_bEnabled = true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Send even though we don't have a model
|
||||
//------------------------------------------------------------------------------
|
||||
int CGlobalLight::UpdateTransmitState()
|
||||
{
|
||||
// ALWAYS transmit to all clients.
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
|
||||
bool CGlobalLight::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if ( FStrEq( szKeyName, "lightcolor" ) || FStrEq( szKeyName, "color" ) )
|
||||
#else
|
||||
if ( FStrEq( szKeyName, "color" ) )
|
||||
#endif
|
||||
{
|
||||
float tmp[4];
|
||||
UTIL_StringToFloatArray( tmp, 4, szValue );
|
||||
|
||||
m_LightColor.SetR( tmp[0] );
|
||||
m_LightColor.SetG( tmp[1] );
|
||||
m_LightColor.SetB( tmp[2] );
|
||||
m_LightColor.SetA( tmp[3] );
|
||||
}
|
||||
else if ( FStrEq( szKeyName, "angles" ) )
|
||||
{
|
||||
QAngle angles;
|
||||
UTIL_StringToVector( angles.Base(), szValue );
|
||||
if (angles == vec3_angle)
|
||||
{
|
||||
angles.Init( 80, 30, 0 );
|
||||
}
|
||||
Vector vForward;
|
||||
AngleVectors( angles, &vForward );
|
||||
m_shadowDirection = vForward;
|
||||
return true;
|
||||
}
|
||||
else if ( FStrEq( szKeyName, "texturename" ) )
|
||||
{
|
||||
#if defined( _X360 )
|
||||
if ( Q_strcmp( szValue, "effects/flashlight001" ) == 0 )
|
||||
{
|
||||
// Use this as the default for Xbox
|
||||
Q_strcpy( m_TextureName.GetForModify(), "effects/flashlight_border" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_strcpy( m_TextureName.GetForModify(), szValue );
|
||||
}
|
||||
#else
|
||||
Q_strcpy( m_TextureName.GetForModify(), szValue );
|
||||
#endif
|
||||
}
|
||||
else if ( FStrEq( szKeyName, "StartDisabled" ) )
|
||||
{
|
||||
m_bEnabled.Set( atoi( szValue ) <= 0 );
|
||||
}
|
||||
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
}
|
||||
|
||||
bool CGlobalLight::GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "color" ) )
|
||||
{
|
||||
Q_snprintf( szValue, iMaxLen, "%d %d %d %d", m_LightColor.GetR(), m_LightColor.GetG(), m_LightColor.GetB(), m_LightColor.GetA() );
|
||||
return true;
|
||||
}
|
||||
else if ( FStrEq( szKeyName, "texturename" ) )
|
||||
{
|
||||
Q_snprintf( szValue, iMaxLen, "%s", m_TextureName.Get() );
|
||||
return true;
|
||||
}
|
||||
else if ( FStrEq( szKeyName, "StartDisabled" ) )
|
||||
{
|
||||
Q_snprintf( szValue, iMaxLen, "%d", !m_bEnabled.Get() );
|
||||
return true;
|
||||
}
|
||||
return BaseClass::GetKeyValue( szKeyName, szValue, iMaxLen );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
//------------------------------------------------------------------------------
|
||||
void CGlobalLight::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
SetSolid( SOLID_NONE );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Input values
|
||||
//------------------------------------------------------------------------------
|
||||
void CGlobalLight::InputSetAngles( inputdata_t &inputdata )
|
||||
{
|
||||
const char *pAngles = inputdata.value.String();
|
||||
|
||||
QAngle angles;
|
||||
UTIL_StringToVector( angles.Base(), pAngles );
|
||||
|
||||
Vector vTemp;
|
||||
AngleVectors( angles, &vTemp );
|
||||
m_shadowDirection = vTemp;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Input handlers
|
||||
//------------------------------------------------------------------------------
|
||||
void CGlobalLight::InputEnable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bEnabled = true;
|
||||
}
|
||||
|
||||
void CGlobalLight::InputDisable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bEnabled = false;
|
||||
}
|
||||
|
||||
void CGlobalLight::InputSetTexture( inputdata_t &inputdata )
|
||||
{
|
||||
Q_strcpy( m_TextureName.GetForModify(), inputdata.value.String() );
|
||||
}
|
||||
|
||||
void CGlobalLight::InputSetEnableShadows( inputdata_t &inputdata )
|
||||
{
|
||||
m_bEnableShadows = inputdata.value.Bool();
|
||||
}
|
||||
|
||||
void CGlobalLight::InputSetLightColor( inputdata_t &inputdata )
|
||||
{
|
||||
m_LightColor = inputdata.value.Color32();
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CGlobalLight::InputSetBrightness( inputdata_t &inputdata )
|
||||
{
|
||||
m_flBrightnessScale = inputdata.value.Float();
|
||||
}
|
||||
|
||||
void CGlobalLight::InputSetColorTransitionTime( inputdata_t &inputdata )
|
||||
{
|
||||
m_flColorTransitionTime = inputdata.value.Float();
|
||||
}
|
||||
#endif
|
||||
229
sp/src/game/server/env_instructor_hint.cpp
Normal file
229
sp/src/game/server/env_instructor_hint.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: An entity for creating instructor hints entirely with map logic
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "baseentity.h"
|
||||
#include "world.h"
|
||||
|
||||
#ifdef INFESTED_DLL
|
||||
#include "asw_marine.h"
|
||||
#include "asw_player.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEnvInstructorHint : public CPointEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CEnvInstructorHint, CPointEntity );
|
||||
DECLARE_DATADESC();
|
||||
|
||||
private:
|
||||
void InputShowHint( inputdata_t &inputdata );
|
||||
void InputEndHint( inputdata_t &inputdata );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void InputSetCaption( inputdata_t &inputdata ) { m_iszCaption = inputdata.value.StringID(); }
|
||||
#endif
|
||||
|
||||
string_t m_iszReplace_Key;
|
||||
string_t m_iszHintTargetEntity;
|
||||
int m_iTimeout;
|
||||
string_t m_iszIcon_Onscreen;
|
||||
string_t m_iszIcon_Offscreen;
|
||||
string_t m_iszCaption;
|
||||
string_t m_iszActivatorCaption;
|
||||
color32 m_Color;
|
||||
float m_fIconOffset;
|
||||
float m_fRange;
|
||||
uint8 m_iPulseOption;
|
||||
uint8 m_iAlphaOption;
|
||||
uint8 m_iShakeOption;
|
||||
bool m_bStatic;
|
||||
bool m_bNoOffscreen;
|
||||
bool m_bForceCaption;
|
||||
string_t m_iszBinding;
|
||||
bool m_bAllowNoDrawTarget;
|
||||
bool m_bLocalPlayerOnly;
|
||||
#ifdef MAPBASE
|
||||
string_t m_iszStartSound;
|
||||
int m_iHintTargetPos;
|
||||
#endif
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_instructor_hint, CEnvInstructorHint );
|
||||
|
||||
BEGIN_DATADESC( CEnvInstructorHint )
|
||||
|
||||
DEFINE_KEYFIELD( m_iszReplace_Key, FIELD_STRING, "hint_replace_key" ),
|
||||
DEFINE_KEYFIELD( m_iszHintTargetEntity, FIELD_STRING, "hint_target" ),
|
||||
DEFINE_KEYFIELD( m_iTimeout, FIELD_INTEGER, "hint_timeout" ),
|
||||
DEFINE_KEYFIELD( m_iszIcon_Onscreen, FIELD_STRING, "hint_icon_onscreen" ),
|
||||
DEFINE_KEYFIELD( m_iszIcon_Offscreen, FIELD_STRING, "hint_icon_offscreen" ),
|
||||
DEFINE_KEYFIELD( m_iszCaption, FIELD_STRING, "hint_caption" ),
|
||||
DEFINE_KEYFIELD( m_iszActivatorCaption, FIELD_STRING, "hint_activator_caption" ),
|
||||
DEFINE_KEYFIELD( m_Color, FIELD_COLOR32, "hint_color" ),
|
||||
DEFINE_KEYFIELD( m_fIconOffset, FIELD_FLOAT, "hint_icon_offset" ),
|
||||
DEFINE_KEYFIELD( m_fRange, FIELD_FLOAT, "hint_range" ),
|
||||
DEFINE_KEYFIELD( m_iPulseOption, FIELD_CHARACTER, "hint_pulseoption" ),
|
||||
DEFINE_KEYFIELD( m_iAlphaOption, FIELD_CHARACTER, "hint_alphaoption" ),
|
||||
DEFINE_KEYFIELD( m_iShakeOption, FIELD_CHARACTER, "hint_shakeoption" ),
|
||||
DEFINE_KEYFIELD( m_bStatic, FIELD_BOOLEAN, "hint_static" ),
|
||||
DEFINE_KEYFIELD( m_bNoOffscreen, FIELD_BOOLEAN, "hint_nooffscreen" ),
|
||||
DEFINE_KEYFIELD( m_bForceCaption, FIELD_BOOLEAN, "hint_forcecaption" ),
|
||||
DEFINE_KEYFIELD( m_iszBinding, FIELD_STRING, "hint_binding" ),
|
||||
DEFINE_KEYFIELD( m_bAllowNoDrawTarget, FIELD_BOOLEAN, "hint_allow_nodraw_target" ),
|
||||
DEFINE_KEYFIELD( m_bLocalPlayerOnly, FIELD_BOOLEAN, "hint_local_player_only" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_iszStartSound, FIELD_STRING, "hint_start_sound" ),
|
||||
DEFINE_KEYFIELD( m_iHintTargetPos, FIELD_INTEGER, "hint_target_pos" ),
|
||||
#endif
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "ShowHint", InputShowHint ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "EndHint", InputEndHint ),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetCaption", InputSetCaption ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
#define LOCATOR_ICON_FX_PULSE_SLOW 0x00000001
|
||||
#define LOCATOR_ICON_FX_ALPHA_SLOW 0x00000008
|
||||
#define LOCATOR_ICON_FX_SHAKE_NARROW 0x00000040
|
||||
#define LOCATOR_ICON_FX_STATIC 0x00000100 // This icon draws at a fixed location on the HUD.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handler for showing the message and/or playing the sound.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvInstructorHint::InputShowHint( inputdata_t &inputdata )
|
||||
{
|
||||
IGameEvent * event = gameeventmanager->CreateEvent( "instructor_server_hint_create", false );
|
||||
if ( event )
|
||||
{
|
||||
CBaseEntity *pTargetEntity = gEntList.FindEntityByName( NULL, m_iszHintTargetEntity );
|
||||
if( pTargetEntity == NULL && !m_bStatic )
|
||||
pTargetEntity = inputdata.pActivator;
|
||||
|
||||
if( pTargetEntity == NULL )
|
||||
pTargetEntity = GetWorldEntity();
|
||||
|
||||
char szColorString[128];
|
||||
Q_snprintf( szColorString, sizeof( szColorString ), "%.3d,%.3d,%.3d", m_Color.r, m_Color.g, m_Color.b );
|
||||
|
||||
int iFlags = 0;
|
||||
|
||||
iFlags |= (m_iPulseOption == 0) ? 0 : (LOCATOR_ICON_FX_PULSE_SLOW << (m_iPulseOption - 1));
|
||||
iFlags |= (m_iAlphaOption == 0) ? 0 : (LOCATOR_ICON_FX_ALPHA_SLOW << (m_iAlphaOption - 1));
|
||||
iFlags |= (m_iShakeOption == 0) ? 0 : (LOCATOR_ICON_FX_SHAKE_NARROW << (m_iShakeOption - 1));
|
||||
iFlags |= m_bStatic ? LOCATOR_ICON_FX_STATIC : 0;
|
||||
|
||||
CBasePlayer *pActivator = NULL;
|
||||
bool bFilterByActivator = m_bLocalPlayerOnly;
|
||||
|
||||
#ifdef INFESTED_DLL
|
||||
CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>( inputdata.pActivator );
|
||||
if ( pMarine )
|
||||
{
|
||||
pActivator = pMarine->GetCommander();
|
||||
}
|
||||
#else
|
||||
if ( inputdata.value.StringID() != NULL_STRING )
|
||||
{
|
||||
CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, inputdata.value.String() );
|
||||
pActivator = dynamic_cast<CBasePlayer*>( pTarget );
|
||||
if ( pActivator )
|
||||
{
|
||||
bFilterByActivator = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( GameRules()->IsMultiplayer() == false )
|
||||
{
|
||||
pActivator = UTIL_GetLocalPlayer();
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "Failed to play server side instructor hint: no player specified for hint\n" );
|
||||
Assert( 0 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *pActivatorCaption = m_iszActivatorCaption.ToCStr();
|
||||
if ( !pActivatorCaption || pActivatorCaption[ 0 ] == '\0' )
|
||||
{
|
||||
pActivatorCaption = m_iszCaption.ToCStr();
|
||||
}
|
||||
|
||||
event->SetString( "hint_name", GetEntityName().ToCStr() );
|
||||
event->SetString( "hint_replace_key", m_iszReplace_Key.ToCStr() );
|
||||
event->SetInt( "hint_target", pTargetEntity->entindex() );
|
||||
event->SetInt( "hint_activator_userid", ( pActivator ? pActivator->GetUserID() : 0 ) );
|
||||
event->SetInt( "hint_timeout", m_iTimeout );
|
||||
event->SetString( "hint_icon_onscreen", m_iszIcon_Onscreen.ToCStr() );
|
||||
event->SetString( "hint_icon_offscreen", m_iszIcon_Offscreen.ToCStr() );
|
||||
event->SetString( "hint_caption", m_iszCaption.ToCStr() );
|
||||
event->SetString( "hint_activator_caption", pActivatorCaption );
|
||||
event->SetString( "hint_color", szColorString );
|
||||
event->SetFloat( "hint_icon_offset", m_fIconOffset );
|
||||
event->SetFloat( "hint_range", m_fRange );
|
||||
event->SetInt( "hint_flags", iFlags );
|
||||
event->SetString( "hint_binding", m_iszBinding.ToCStr() );
|
||||
event->SetBool( "hint_allow_nodraw_target", m_bAllowNoDrawTarget );
|
||||
event->SetBool( "hint_nooffscreen", m_bNoOffscreen );
|
||||
event->SetBool( "hint_forcecaption", m_bForceCaption );
|
||||
event->SetBool( "hint_local_player_only", bFilterByActivator );
|
||||
#ifdef MAPBASE
|
||||
event->SetString( "hint_start_sound", m_iszStartSound.ToCStr() );
|
||||
event->SetInt( "hint_target_pos", m_iHintTargetPos );
|
||||
#endif
|
||||
|
||||
gameeventmanager->FireEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvInstructorHint::InputEndHint( inputdata_t &inputdata )
|
||||
{
|
||||
IGameEvent * event = gameeventmanager->CreateEvent( "instructor_server_hint_stop", false );
|
||||
if ( event )
|
||||
{
|
||||
event->SetString( "hint_name", GetEntityName().ToCStr() );
|
||||
|
||||
gameeventmanager->FireEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A generic target entity that gets replicated to the client for instructor hint targetting
|
||||
//-----------------------------------------------------------------------------
|
||||
class CInfoInstructorHintTarget : public CPointEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CInfoInstructorHintTarget, CPointEntity );
|
||||
|
||||
virtual int UpdateTransmitState( void ) // set transmit filter to transmit always
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
DECLARE_DATADESC();
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( info_target_instructor_hint, CInfoInstructorHintTarget );
|
||||
|
||||
BEGIN_DATADESC( CInfoInstructorHintTarget )
|
||||
|
||||
END_DATADESC()
|
||||
193
sp/src/game/server/env_particlescript.cpp
Normal file
193
sp/src/game/server/env_particlescript.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "baseanimating.h"
|
||||
#include "SkyCamera.h"
|
||||
#include "studio.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// HACK HACK: Must match cl_dll/cl_animevent.h!!!!
|
||||
#define CL_EVENT_SPRITEGROUP_CREATE 6002
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// An entity which emits other entities at points
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEnvParticleScript : public CBaseAnimating
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CEnvParticleScript, CBaseAnimating );
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
CEnvParticleScript();
|
||||
|
||||
virtual void Precache();
|
||||
virtual void Spawn();
|
||||
virtual void Activate();
|
||||
virtual int UpdateTransmitState();
|
||||
|
||||
void InputSetSequence( inputdata_t &inputdata );
|
||||
|
||||
private:
|
||||
|
||||
void PrecacheAnimationEventMaterials();
|
||||
|
||||
CNetworkVar( float, m_flSequenceScale );
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Save/load
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_DATADESC( CEnvParticleScript )
|
||||
|
||||
DEFINE_FIELD( m_flSequenceScale, FIELD_FLOAT ),
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetSequence", InputSetSequence ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_particlescript, CEnvParticleScript );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Datatable
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_SERVERCLASS_ST( CEnvParticleScript, DT_EnvParticleScript )
|
||||
SendPropFloat(SENDINFO(m_flSequenceScale), 0, SPROP_NOSCALE),
|
||||
END_SEND_TABLE()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CEnvParticleScript::CEnvParticleScript()
|
||||
{
|
||||
UseClientSideAnimation();
|
||||
}
|
||||
|
||||
|
||||
void CEnvParticleScript::PrecacheAnimationEventMaterials()
|
||||
{
|
||||
CStudioHdr *hdr = GetModelPtr();
|
||||
if ( hdr )
|
||||
{
|
||||
int numseq = hdr->GetNumSeq();
|
||||
for ( int i = 0; i < numseq; ++i )
|
||||
{
|
||||
mstudioseqdesc_t& seqdesc = hdr->pSeqdesc( i );
|
||||
int ecount = seqdesc.numevents;
|
||||
for ( int j = 0 ; j < ecount; ++j )
|
||||
{
|
||||
const mstudioevent_t* event = seqdesc.pEvent( j );
|
||||
if ( event->event == CL_EVENT_SPRITEGROUP_CREATE )
|
||||
{
|
||||
char pAttachmentName[256];
|
||||
char pSpriteName[256];
|
||||
int nArgs = sscanf( event->pszOptions(), "%255s %255s", pAttachmentName, pSpriteName );
|
||||
if ( nArgs == 2 )
|
||||
{
|
||||
PrecacheMaterial( pSpriteName );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Precache
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvParticleScript::Precache()
|
||||
{
|
||||
BaseClass::Precache();
|
||||
PrecacheModel( STRING( GetModelName() ) );
|
||||
|
||||
// We need a model for its animation sequences even though we don't render it
|
||||
SetModel( STRING( GetModelName() ) );
|
||||
|
||||
PrecacheAnimationEventMaterials();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Spawn
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvParticleScript::Spawn()
|
||||
{
|
||||
Precache();
|
||||
BaseClass::Spawn();
|
||||
AddEffects( EF_NOSHADOW );
|
||||
// We need a model for its animation sequences even though we don't render it
|
||||
SetModel( STRING( GetModelName() ) );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Activate
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvParticleScript::Activate()
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
DetectInSkybox();
|
||||
CSkyCamera *pCamera = GetEntitySkybox();
|
||||
if ( pCamera )
|
||||
{
|
||||
float flSkyboxScale = pCamera->m_skyboxData.scale;
|
||||
if ( flSkyboxScale == 0.0f )
|
||||
{
|
||||
flSkyboxScale = 1.0f;
|
||||
}
|
||||
|
||||
m_flSequenceScale = flSkyboxScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flSequenceScale = 1.0f;
|
||||
}
|
||||
|
||||
m_flPlaybackRate = 1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Should we transmit it to the client?
|
||||
//-----------------------------------------------------------------------------
|
||||
int CEnvParticleScript::UpdateTransmitState()
|
||||
{
|
||||
if ( IsEffectActive( EF_NODRAW ) )
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_DONTSEND );
|
||||
}
|
||||
|
||||
if ( IsEFlagSet( EFL_IN_SKYBOX ) )
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
return SetTransmitState( FL_EDICT_PVSCHECK );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input that sets the sequence of the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvParticleScript::InputSetSequence( inputdata_t &inputdata )
|
||||
{
|
||||
if ( inputdata.value.StringID() != NULL_STRING )
|
||||
{
|
||||
int nSequence = LookupSequence( STRING( inputdata.value.StringID() ) );
|
||||
if ( nSequence != ACT_INVALID )
|
||||
{
|
||||
SetSequence( nSequence );
|
||||
}
|
||||
}
|
||||
}
|
||||
135
sp/src/game/server/env_player_surface_trigger.cpp
Normal file
135
sp/src/game/server/env_player_surface_trigger.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "decals.h"
|
||||
#include "env_player_surface_trigger.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_player_surface_trigger, CEnvPlayerSurfaceTrigger );
|
||||
|
||||
BEGIN_DATADESC( CEnvPlayerSurfaceTrigger )
|
||||
DEFINE_KEYFIELD( m_iTargetGameMaterial, FIELD_INTEGER, "gamematerial" ),
|
||||
DEFINE_FIELD( m_iCurrentGameMaterial, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ),
|
||||
|
||||
DEFINE_THINKFUNC( UpdateMaterialThink ),
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
|
||||
// Outputs
|
||||
DEFINE_OUTPUT(m_OnSurfaceChangedToTarget, "OnSurfaceChangedToTarget"),
|
||||
DEFINE_OUTPUT(m_OnSurfaceChangedFromTarget, "OnSurfaceChangedFromTarget"),
|
||||
END_DATADESC()
|
||||
|
||||
// Global list of surface triggers
|
||||
CUtlVector< CHandle<CEnvPlayerSurfaceTrigger> > g_PlayerSurfaceTriggers;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CEnvPlayerSurfaceTrigger::~CEnvPlayerSurfaceTrigger( void )
|
||||
{
|
||||
g_PlayerSurfaceTriggers.FindAndRemove( this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvPlayerSurfaceTrigger::Spawn( void )
|
||||
{
|
||||
SetSolid( SOLID_NONE );
|
||||
SetMoveType( MOVETYPE_NONE );
|
||||
|
||||
m_iCurrentGameMaterial = 0;
|
||||
m_bDisabled = false;
|
||||
|
||||
g_PlayerSurfaceTriggers.AddToTail( this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvPlayerSurfaceTrigger::OnRestore( void )
|
||||
{
|
||||
BaseClass::OnRestore();
|
||||
|
||||
g_PlayerSurfaceTriggers.AddToTail( this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvPlayerSurfaceTrigger::SetPlayerSurface( CBasePlayer *pPlayer, char gameMaterial )
|
||||
{
|
||||
// Ignore players in the air (stops bunny hoppers escaping triggers)
|
||||
if ( gameMaterial == 0 )
|
||||
return;
|
||||
|
||||
// Loop through the surface triggers and tell them all about the change
|
||||
int iCount = g_PlayerSurfaceTriggers.Count();
|
||||
for ( int i = 0; i < iCount; i++ )
|
||||
{
|
||||
g_PlayerSurfaceTriggers[i]->PlayerSurfaceChanged( pPlayer, gameMaterial );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvPlayerSurfaceTrigger::PlayerSurfaceChanged( CBasePlayer *pPlayer, char gameMaterial )
|
||||
{
|
||||
if ( m_bDisabled )
|
||||
return;
|
||||
|
||||
// Fire the output if we've changed, but only if it involves the target material
|
||||
if ( gameMaterial != (char)m_iCurrentGameMaterial &&
|
||||
( gameMaterial == m_iTargetGameMaterial || m_iCurrentGameMaterial == m_iTargetGameMaterial ) )
|
||||
{
|
||||
DevMsg( 2, "Player changed material to %d (was %d)\n", gameMaterial, m_iCurrentGameMaterial );
|
||||
|
||||
m_iCurrentGameMaterial = (int)gameMaterial;
|
||||
|
||||
SetThink( &CEnvPlayerSurfaceTrigger::UpdateMaterialThink );
|
||||
SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Think function to fire outputs. Done this way so that sv_alternate ticks
|
||||
// doesn't allow multiple surface changes in the same tick to fire outputs.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvPlayerSurfaceTrigger::UpdateMaterialThink( void )
|
||||
{
|
||||
if ( m_iCurrentGameMaterial == m_iTargetGameMaterial )
|
||||
{
|
||||
m_OnSurfaceChangedToTarget.FireOutput( NULL, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_OnSurfaceChangedFromTarget.FireOutput( NULL, this );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvPlayerSurfaceTrigger::InputDisable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bDisabled = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvPlayerSurfaceTrigger::InputEnable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bDisabled = false;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user