Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
11 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "entityoutput.h"
  8. #include "ndebugoverlay.h"
  9. #include "modelentities.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. extern ConVar ent_debugkeys;
  13. extern ConVar showtriggers;
  14. LINK_ENTITY_TO_CLASS( func_brush, CFuncBrush );
  15. BEGIN_DATADESC( CFuncBrush )
  16. DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputTurnOn ),
  17. DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputTurnOff ),
  18. DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
  19. DEFINE_KEYFIELD( m_iDisabled, FIELD_INTEGER, "StartDisabled" ),
  20. DEFINE_KEYFIELD( m_iSolidity, FIELD_INTEGER, "Solidity" ),
  21. DEFINE_KEYFIELD( m_bSolidBsp, FIELD_BOOLEAN, "solidbsp" ),
  22. DEFINE_KEYFIELD( m_iszExcludedClass, FIELD_STRING, "excludednpc" ),
  23. DEFINE_KEYFIELD( m_bInvertExclusion, FIELD_BOOLEAN, "invert_exclusion" ),
  24. DEFINE_INPUTFUNC( FIELD_STRING, "SetExcluded", InputSetExcluded ),
  25. DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetInvert", InputSetInvert ),
  26. END_DATADESC()
  27. IMPLEMENT_SERVERCLASS_ST(CFuncBrush, DT_FuncBrush)
  28. END_SEND_TABLE()
  29. void CFuncBrush::Spawn( void )
  30. {
  31. SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything
  32. SetSolid( SOLID_VPHYSICS );
  33. AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID );
  34. if ( m_iSolidity == BRUSHSOLID_NEVER )
  35. {
  36. AddSolidFlags( FSOLID_NOT_SOLID );
  37. }
  38. SetModel( STRING( GetModelName() ) );
  39. if ( m_iDisabled )
  40. TurnOff();
  41. // If it can't move/go away, it's really part of the world
  42. if ( !GetEntityName() || !m_iParent )
  43. AddFlag( FL_WORLDBRUSH );
  44. CreateVPhysics();
  45. // Slam the object back to solid - if we really want it to be solid.
  46. if ( m_bSolidBsp )
  47. {
  48. SetSolid( SOLID_BSP );
  49. }
  50. }
  51. void CFuncBrush::Activate( void )
  52. {
  53. BaseClass::Activate();
  54. IPhysicsObject *pPhysObject = VPhysicsGetObject();
  55. if( pPhysObject )
  56. {
  57. pPhysObject->Wake();
  58. }
  59. }
  60. //-----------------------------------------------------------------------------
  61. bool CFuncBrush::CreateVPhysics( void )
  62. {
  63. // NOTE: Don't init this static. It's pretty common for these to be constrained
  64. // and dynamically parented. Initing shadow avoids having to destroy the physics
  65. // object later and lose the constraints.
  66. IPhysicsObject *pPhys = VPhysicsInitShadow(false, false);
  67. if ( pPhys )
  68. {
  69. int contents = modelinfo->GetModelContents( GetModelIndex() );
  70. if ( m_iDisabled || !(contents & (MASK_SOLID|MASK_PLAYERSOLID|MASK_NPCSOLID)) )
  71. {
  72. // leave the physics shadow there in case it has crap constrained to it
  73. // but disable collisions with it
  74. pPhys->EnableCollisions( false );
  75. }
  76. }
  77. return true;
  78. }
  79. //-----------------------------------------------------------------------------
  80. // Purpose:
  81. //-----------------------------------------------------------------------------
  82. int CFuncBrush::DrawDebugTextOverlays( void )
  83. {
  84. int nOffset = BaseClass::DrawDebugTextOverlays();
  85. if (m_debugOverlays & OVERLAY_TEXT_BIT)
  86. {
  87. char tempstr[512];
  88. Q_snprintf( tempstr,sizeof(tempstr), "angles: %g %g %g", (double)GetLocalAngles()[PITCH], (double)GetLocalAngles()[YAW], (double)GetLocalAngles()[ROLL] );
  89. EntityText( nOffset, tempstr, 0 );
  90. nOffset++;
  91. }
  92. return nOffset;
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Purpose: Input handler for toggling the hidden/shown state of the brush.
  96. //-----------------------------------------------------------------------------
  97. void CFuncBrush::InputToggle( inputdata_t &inputdata )
  98. {
  99. if ( IsOn() )
  100. {
  101. TurnOff();
  102. return;
  103. }
  104. TurnOn();
  105. }
  106. //-----------------------------------------------------------------------------
  107. // Purpose: Input handler for hiding the brush.
  108. //-----------------------------------------------------------------------------
  109. void CFuncBrush::InputTurnOff( inputdata_t &inputdata )
  110. {
  111. TurnOff();
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Purpose: Input handler for showing the brush.
  115. //-----------------------------------------------------------------------------
  116. void CFuncBrush::InputTurnOn( inputdata_t &inputdata )
  117. {
  118. TurnOn();
  119. }
  120. //-----------------------------------------------------------------------------
  121. //
  122. //-----------------------------------------------------------------------------
  123. void CFuncBrush::InputSetExcluded( inputdata_t &inputdata )
  124. {
  125. m_iszExcludedClass = inputdata.value.StringID();
  126. }
  127. //-----------------------------------------------------------------------------
  128. //
  129. //-----------------------------------------------------------------------------
  130. void CFuncBrush::InputSetInvert( inputdata_t &inputdata )
  131. {
  132. m_bInvertExclusion = inputdata.value.Bool();
  133. }
  134. //-----------------------------------------------------------------------------
  135. // Purpose: Hides the brush.
  136. //-----------------------------------------------------------------------------
  137. void CFuncBrush::TurnOff( void )
  138. {
  139. if ( !IsOn() )
  140. return;
  141. if ( m_iSolidity != BRUSHSOLID_ALWAYS )
  142. {
  143. AddSolidFlags( FSOLID_NOT_SOLID );
  144. }
  145. AddEffects( EF_NODRAW );
  146. IPhysicsObject *pObject = VPhysicsGetObject();
  147. if( pObject )
  148. {
  149. pObject->Wake();
  150. pObject->EnableCollisions( false );
  151. }
  152. WakeRestingObjects();
  153. m_iDisabled = TRUE;
  154. }
  155. //-----------------------------------------------------------------------------
  156. // Purpose: Shows the brush.
  157. //-----------------------------------------------------------------------------
  158. void CFuncBrush::TurnOn( void )
  159. {
  160. if ( IsOn() )
  161. return;
  162. if ( m_iSolidity != BRUSHSOLID_NEVER )
  163. {
  164. RemoveSolidFlags( FSOLID_NOT_SOLID );
  165. }
  166. RemoveEffects( EF_NODRAW );
  167. IPhysicsObject *pObject = VPhysicsGetObject();
  168. if( pObject )
  169. {
  170. pObject->EnableCollisions( true );
  171. if( pObject->IsAsleep() )
  172. {
  173. pObject->Wake();
  174. }
  175. }
  176. m_iDisabled = FALSE;
  177. }
  178. bool CFuncBrush::IsOn( void )
  179. {
  180. return !IsEffectActive( EF_NODRAW );
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Purpose: Invisible field that activates when touched
  184. // All inputs are passed up to the main entity, unless filtered out
  185. //-----------------------------------------------------------------------------
  186. // DVS TODO: obsolete, remove
  187. class CTriggerBrush : public CBaseEntity
  188. {
  189. //
  190. // Filters controlling what this trigger responds to.
  191. //
  192. enum TriggerFilters_e
  193. {
  194. TRIGGER_IGNOREPLAYERS = 0x01,
  195. TRIGGER_IGNORENPCS = 0x02,
  196. TRIGGER_IGNOREPUSHABLES = 0x04,
  197. TRIGGER_IGNORETOUCH = 0x08,
  198. TRIGGER_IGNOREUSE = 0x10,
  199. TRIGGER_IGNOREALL = 0x20,
  200. };
  201. public:
  202. DECLARE_CLASS( CTriggerBrush, CBaseEntity );
  203. // engine inputs
  204. void Spawn( void );
  205. void StartTouch( CBaseEntity *pOther );
  206. void EndTouch( CBaseEntity *pOther );
  207. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  208. // input filtering (use/touch/blocked)
  209. bool PassesInputFilter( CBaseEntity *pOther, int filter );
  210. // input functions
  211. void InputEnable( inputdata_t &inputdata )
  212. {
  213. RemoveFlag( FL_DONTTOUCH );
  214. }
  215. void InputDisable( inputdata_t &inputdata )
  216. {
  217. // this ensures that all the remaining EndTouch() calls still get passed through
  218. AddFlag( FL_DONTTOUCH );
  219. }
  220. // outputs
  221. COutputEvent m_OnStartTouch;
  222. COutputEvent m_OnEndTouch;
  223. COutputEvent m_OnUse;
  224. // data
  225. int m_iInputFilter;
  226. int m_iDontMessageParent;
  227. DECLARE_DATADESC();
  228. };
  229. LINK_ENTITY_TO_CLASS( trigger_brush, CTriggerBrush );
  230. BEGIN_DATADESC( CTriggerBrush )
  231. DEFINE_KEYFIELD( m_iInputFilter, FIELD_INTEGER, "InputFilter" ),
  232. DEFINE_KEYFIELD( m_iDontMessageParent, FIELD_INTEGER, "DontMessageParent" ),
  233. DEFINE_OUTPUT( m_OnStartTouch, "OnStartTouch" ),
  234. DEFINE_OUTPUT( m_OnEndTouch, "OnEndTouch" ),
  235. DEFINE_OUTPUT( m_OnUse, "OnUse" ),
  236. DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
  237. DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
  238. END_DATADESC()
  239. void CTriggerBrush::Spawn( void )
  240. {
  241. SetSolid( SOLID_BSP );
  242. AddSolidFlags( FSOLID_TRIGGER );
  243. SetMoveType( MOVETYPE_NONE );
  244. SetModel( STRING( GetModelName() ) ); // set size and link into world
  245. if ( !showtriggers.GetInt() )
  246. {
  247. AddEffects( EF_NODRAW );
  248. }
  249. }
  250. //-----------------------------------------------------------------------------
  251. // Purpose: Called when an entity starts touching us.
  252. // Input : pOther - the entity that is now touching us.
  253. //-----------------------------------------------------------------------------
  254. void CTriggerBrush::StartTouch( CBaseEntity *pOther )
  255. {
  256. if ( PassesInputFilter(pOther, m_iInputFilter) && !(m_iInputFilter & TRIGGER_IGNORETOUCH) )
  257. {
  258. m_OnStartTouch.FireOutput( pOther, this );
  259. if ( !m_iDontMessageParent )
  260. BaseClass::StartTouch( pOther );
  261. }
  262. }
  263. //-----------------------------------------------------------------------------
  264. // Purpose: Called when an entity stops touching us.
  265. // Input : pOther - the entity that was touching us.
  266. //-----------------------------------------------------------------------------
  267. void CTriggerBrush::EndTouch( CBaseEntity *pOther )
  268. {
  269. if ( PassesInputFilter(pOther, m_iInputFilter) && !(m_iInputFilter & TRIGGER_IGNORETOUCH) )
  270. {
  271. m_OnEndTouch.FireOutput( pOther, this );
  272. if ( !m_iDontMessageParent )
  273. BaseClass::EndTouch( pOther );
  274. }
  275. }
  276. //-----------------------------------------------------------------------------
  277. // Purpose: Called when we are triggered by another entity or used by the player.
  278. // Input : pActivator -
  279. // pCaller -
  280. // useType -
  281. // value -
  282. //-----------------------------------------------------------------------------
  283. void CTriggerBrush::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  284. {
  285. if ( PassesInputFilter(pActivator, m_iInputFilter) && !(m_iInputFilter & TRIGGER_IGNOREUSE) )
  286. {
  287. m_OnUse.FireOutput( pActivator, this );
  288. if ( !m_iDontMessageParent )
  289. {
  290. BaseClass::Use( pActivator, pCaller, useType, value );
  291. }
  292. }
  293. }
  294. //-----------------------------------------------------------------------------
  295. // Purpose: Checks an entity input, against a filter and the current entity
  296. // Input : *pOther - the entity that is part of the input (touch/untouch/block/use)
  297. // filter - a field of standard filters (TriggerFilters_e)
  298. // Output : Returns true if the input passes, false if it should be ignored
  299. //-----------------------------------------------------------------------------
  300. bool CTriggerBrush::PassesInputFilter( CBaseEntity *pOther, int filter )
  301. {
  302. if ( !filter )
  303. return true;
  304. // check for players
  305. if ( (filter & TRIGGER_IGNOREPLAYERS) && pOther->IsPlayer() )
  306. return false;
  307. // NPCs
  308. if ( (filter & TRIGGER_IGNORENPCS) && pOther->edict() && (pOther->GetFlags() & FL_NPC) )
  309. return false;
  310. // pushables
  311. if ( (filter & TRIGGER_IGNOREPUSHABLES) && FStrEq(STRING(pOther->m_iClassname), "func_pushable") )
  312. return false;
  313. return true;
  314. }