Team Fortress 2 Source Code as on 22/4/2020
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.

391 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // An entity that allows level designer control over the fog parameters.
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "fogcontroller.h"
  8. #include "entityinput.h"
  9. #include "entityoutput.h"
  10. #include "eventqueue.h"
  11. #include "player.h"
  12. #include "world.h"
  13. #include "ndebugoverlay.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. CFogSystem s_FogSystem( "FogSystem" );
  17. //-----------------------------------------------------------------------------
  18. // Purpose:
  19. //-----------------------------------------------------------------------------
  20. CFogSystem *FogSystem( void )
  21. {
  22. return &s_FogSystem;
  23. }
  24. LINK_ENTITY_TO_CLASS( env_fog_controller, CFogController );
  25. BEGIN_DATADESC( CFogController )
  26. DEFINE_INPUTFUNC( FIELD_FLOAT, "SetStartDist", InputSetStartDist ),
  27. DEFINE_INPUTFUNC( FIELD_FLOAT, "SetEndDist", InputSetEndDist ),
  28. DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMaxDensity", InputSetMaxDensity ),
  29. DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ),
  30. DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
  31. DEFINE_INPUTFUNC( FIELD_COLOR32, "SetColor", InputSetColor ),
  32. DEFINE_INPUTFUNC( FIELD_COLOR32, "SetColorSecondary", InputSetColorSecondary ),
  33. DEFINE_INPUTFUNC( FIELD_INTEGER, "SetFarZ", InputSetFarZ ),
  34. DEFINE_INPUTFUNC( FIELD_STRING, "SetAngles", InputSetAngles ),
  35. DEFINE_INPUTFUNC( FIELD_COLOR32, "SetColorLerpTo", InputSetColorLerpTo ),
  36. DEFINE_INPUTFUNC( FIELD_COLOR32, "SetColorSecondaryLerpTo", InputSetColorSecondaryLerpTo ),
  37. DEFINE_INPUTFUNC( FIELD_FLOAT, "SetStartDistLerpTo", InputSetStartDistLerpTo ),
  38. DEFINE_INPUTFUNC( FIELD_FLOAT, "SetEndDistLerpTo", InputSetEndDistLerpTo ),
  39. DEFINE_INPUTFUNC( FIELD_VOID, "StartFogTransition", InputStartFogTransition ),
  40. // Quiet classcheck
  41. //DEFINE_EMBEDDED( m_fog ),
  42. DEFINE_KEYFIELD( m_bUseAngles, FIELD_BOOLEAN, "use_angles" ),
  43. DEFINE_KEYFIELD( m_fog.colorPrimary, FIELD_COLOR32, "fogcolor" ),
  44. DEFINE_KEYFIELD( m_fog.colorSecondary, FIELD_COLOR32, "fogcolor2" ),
  45. DEFINE_KEYFIELD( m_fog.dirPrimary, FIELD_VECTOR, "fogdir" ),
  46. DEFINE_KEYFIELD( m_fog.enable, FIELD_BOOLEAN, "fogenable" ),
  47. DEFINE_KEYFIELD( m_fog.blend, FIELD_BOOLEAN, "fogblend" ),
  48. DEFINE_KEYFIELD( m_fog.start, FIELD_FLOAT, "fogstart" ),
  49. DEFINE_KEYFIELD( m_fog.end, FIELD_FLOAT, "fogend" ),
  50. DEFINE_KEYFIELD( m_fog.maxdensity, FIELD_FLOAT, "fogmaxdensity" ),
  51. DEFINE_KEYFIELD( m_fog.farz, FIELD_FLOAT, "farz" ),
  52. DEFINE_KEYFIELD( m_fog.duration, FIELD_FLOAT, "foglerptime" ),
  53. DEFINE_THINKFUNC( SetLerpValues ),
  54. DEFINE_FIELD( m_iChangedVariables, FIELD_INTEGER ),
  55. DEFINE_FIELD( m_fog.lerptime, FIELD_TIME ),
  56. DEFINE_FIELD( m_fog.colorPrimaryLerpTo, FIELD_COLOR32 ),
  57. DEFINE_FIELD( m_fog.colorSecondaryLerpTo, FIELD_COLOR32 ),
  58. DEFINE_FIELD( m_fog.startLerpTo, FIELD_FLOAT ),
  59. DEFINE_FIELD( m_fog.endLerpTo, FIELD_FLOAT ),
  60. END_DATADESC()
  61. IMPLEMENT_SERVERCLASS_ST_NOBASE( CFogController, DT_FogController )
  62. // fog data
  63. SendPropInt( SENDINFO_STRUCTELEM( m_fog.enable ), 1, SPROP_UNSIGNED ),
  64. SendPropInt( SENDINFO_STRUCTELEM( m_fog.blend ), 1, SPROP_UNSIGNED ),
  65. SendPropVector( SENDINFO_STRUCTELEM(m_fog.dirPrimary), -1, SPROP_COORD),
  66. SendPropInt( SENDINFO_STRUCTELEM( m_fog.colorPrimary ), 32, SPROP_UNSIGNED ),
  67. SendPropInt( SENDINFO_STRUCTELEM( m_fog.colorSecondary ), 32, SPROP_UNSIGNED ),
  68. SendPropFloat( SENDINFO_STRUCTELEM( m_fog.start ), 0, SPROP_NOSCALE ),
  69. SendPropFloat( SENDINFO_STRUCTELEM( m_fog.end ), 0, SPROP_NOSCALE ),
  70. SendPropFloat( SENDINFO_STRUCTELEM( m_fog.maxdensity ), 0, SPROP_NOSCALE ),
  71. SendPropFloat( SENDINFO_STRUCTELEM( m_fog.farz ), 0, SPROP_NOSCALE ),
  72. SendPropInt( SENDINFO_STRUCTELEM( m_fog.colorPrimaryLerpTo ), 32, SPROP_UNSIGNED ),
  73. SendPropInt( SENDINFO_STRUCTELEM( m_fog.colorSecondaryLerpTo ), 32, SPROP_UNSIGNED ),
  74. SendPropFloat( SENDINFO_STRUCTELEM( m_fog.startLerpTo ), 0, SPROP_NOSCALE ),
  75. SendPropFloat( SENDINFO_STRUCTELEM( m_fog.endLerpTo ), 0, SPROP_NOSCALE ),
  76. SendPropFloat( SENDINFO_STRUCTELEM( m_fog.lerptime ), 0, SPROP_NOSCALE ),
  77. SendPropFloat( SENDINFO_STRUCTELEM( m_fog.duration ), 0, SPROP_NOSCALE ),
  78. END_SEND_TABLE()
  79. CFogController::CFogController()
  80. {
  81. // Make sure that old maps without fog fields don't get wacked out fog values.
  82. m_fog.enable = false;
  83. m_fog.maxdensity = 1.0f;
  84. }
  85. CFogController::~CFogController()
  86. {
  87. }
  88. void CFogController::Spawn( void )
  89. {
  90. BaseClass::Spawn();
  91. m_fog.colorPrimaryLerpTo = m_fog.colorPrimary;
  92. m_fog.colorSecondaryLerpTo = m_fog.colorSecondary;
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Activate!
  96. //-----------------------------------------------------------------------------
  97. void CFogController::Activate( )
  98. {
  99. BaseClass::Activate();
  100. if ( m_bUseAngles )
  101. {
  102. AngleVectors( GetAbsAngles(), &m_fog.dirPrimary.GetForModify() );
  103. m_fog.dirPrimary.GetForModify() *= -1.0f;
  104. }
  105. }
  106. //-----------------------------------------------------------------------------
  107. // Purpose:
  108. //-----------------------------------------------------------------------------
  109. int CFogController::UpdateTransmitState()
  110. {
  111. return SetTransmitState( FL_EDICT_ALWAYS );
  112. }
  113. //------------------------------------------------------------------------------
  114. // Purpose: Input handler for setting the fog start distance.
  115. //------------------------------------------------------------------------------
  116. void CFogController::InputSetStartDist(inputdata_t &inputdata)
  117. {
  118. // Get the world entity.
  119. m_fog.start = inputdata.value.Float();
  120. }
  121. //------------------------------------------------------------------------------
  122. // Purpose: Input handler for setting the fog end distance.
  123. //------------------------------------------------------------------------------
  124. void CFogController::InputSetEndDist(inputdata_t &inputdata)
  125. {
  126. // Get the world entity.
  127. m_fog.end = inputdata.value.Float();
  128. }
  129. //------------------------------------------------------------------------------
  130. // Input handler for setting the maximum density of the fog. This lets us bring
  131. // the start distance in without the scene fogging too much.
  132. //------------------------------------------------------------------------------
  133. void CFogController::InputSetMaxDensity( inputdata_t &inputdata )
  134. {
  135. m_fog.maxdensity = inputdata.value.Float();
  136. }
  137. //------------------------------------------------------------------------------
  138. // Purpose: Input handler for turning on the fog.
  139. //------------------------------------------------------------------------------
  140. void CFogController::InputTurnOn(inputdata_t &inputdata)
  141. {
  142. // Get the world entity.
  143. m_fog.enable = true;
  144. }
  145. //------------------------------------------------------------------------------
  146. // Purpose: Input handler for turning off the fog.
  147. //------------------------------------------------------------------------------
  148. void CFogController::InputTurnOff(inputdata_t &inputdata)
  149. {
  150. // Get the world entity.
  151. m_fog.enable = false;
  152. }
  153. //------------------------------------------------------------------------------
  154. // Purpose: Input handler for setting the primary fog color.
  155. //------------------------------------------------------------------------------
  156. void CFogController::InputSetColor(inputdata_t &inputdata)
  157. {
  158. // Get the world entity.
  159. m_fog.colorPrimary = inputdata.value.Color32();
  160. }
  161. //------------------------------------------------------------------------------
  162. // Purpose: Input handler for setting the secondary fog color.
  163. //------------------------------------------------------------------------------
  164. void CFogController::InputSetColorSecondary(inputdata_t &inputdata)
  165. {
  166. // Get the world entity.
  167. m_fog.colorSecondary = inputdata.value.Color32();
  168. }
  169. void CFogController::InputSetFarZ(inputdata_t &inputdata)
  170. {
  171. m_fog.farz = inputdata.value.Int();
  172. }
  173. //------------------------------------------------------------------------------
  174. // Purpose: Sets the angles to use for the secondary fog direction.
  175. //------------------------------------------------------------------------------
  176. void CFogController::InputSetAngles( inputdata_t &inputdata )
  177. {
  178. const char *pAngles = inputdata.value.String();
  179. QAngle angles;
  180. UTIL_StringToVector( angles.Base(), pAngles );
  181. Vector vTemp;
  182. AngleVectors( angles, &vTemp );
  183. SetAbsAngles( angles );
  184. AngleVectors( GetAbsAngles(), &m_fog.dirPrimary.GetForModify() );
  185. m_fog.dirPrimary.GetForModify() *= -1.0f;
  186. }
  187. //-----------------------------------------------------------------------------
  188. // Purpose: Draw any debug text overlays
  189. // Output : Current text offset from the top
  190. //-----------------------------------------------------------------------------
  191. int CFogController::DrawDebugTextOverlays(void)
  192. {
  193. int text_offset = BaseClass::DrawDebugTextOverlays();
  194. if (m_debugOverlays & OVERLAY_TEXT_BIT)
  195. {
  196. char tempstr[512];
  197. Q_snprintf(tempstr,sizeof(tempstr),"State: %s",(m_fog.enable)?"On":"Off");
  198. EntityText(text_offset,tempstr,0);
  199. text_offset++;
  200. Q_snprintf(tempstr,sizeof(tempstr),"Start: %3.0f",m_fog.start.Get());
  201. EntityText(text_offset,tempstr,0);
  202. text_offset++;
  203. Q_snprintf(tempstr,sizeof(tempstr),"End : %3.0f",m_fog.end.Get());
  204. EntityText(text_offset,tempstr,0);
  205. text_offset++;
  206. color32 color = m_fog.colorPrimary;
  207. Q_snprintf(tempstr,sizeof(tempstr),"1) Red : %i",color.r);
  208. EntityText(text_offset,tempstr,0);
  209. text_offset++;
  210. Q_snprintf(tempstr,sizeof(tempstr),"1) Green: %i",color.g);
  211. EntityText(text_offset,tempstr,0);
  212. text_offset++;
  213. Q_snprintf(tempstr,sizeof(tempstr),"1) Blue : %i",color.b);
  214. EntityText(text_offset,tempstr,0);
  215. text_offset++;
  216. color = m_fog.colorSecondary;
  217. Q_snprintf(tempstr,sizeof(tempstr),"2) Red : %i",color.r);
  218. EntityText(text_offset,tempstr,0);
  219. text_offset++;
  220. Q_snprintf(tempstr,sizeof(tempstr),"2) Green: %i",color.g);
  221. EntityText(text_offset,tempstr,0);
  222. text_offset++;
  223. Q_snprintf(tempstr,sizeof(tempstr),"2) Blue : %i",color.b);
  224. EntityText(text_offset,tempstr,0);
  225. text_offset++;
  226. }
  227. return text_offset;
  228. }
  229. #define FOG_CONTROLLER_COLORPRIMARY_LERP 1
  230. #define FOG_CONTROLLER_COLORSECONDARY_LERP 2
  231. #define FOG_CONTROLLER_START_LERP 4
  232. #define FOG_CONTROLLER_END_LERP 8
  233. void CFogController::InputSetColorLerpTo(inputdata_t &data)
  234. {
  235. m_iChangedVariables |= FOG_CONTROLLER_COLORPRIMARY_LERP;
  236. m_fog.colorPrimaryLerpTo = data.value.Color32();
  237. }
  238. void CFogController::InputSetColorSecondaryLerpTo(inputdata_t &data)
  239. {
  240. m_iChangedVariables |= FOG_CONTROLLER_COLORSECONDARY_LERP;
  241. m_fog.colorSecondaryLerpTo = data.value.Color32();
  242. }
  243. void CFogController::InputSetStartDistLerpTo(inputdata_t &data)
  244. {
  245. m_iChangedVariables |= FOG_CONTROLLER_START_LERP;
  246. m_fog.startLerpTo = data.value.Float();
  247. }
  248. void CFogController::InputSetEndDistLerpTo(inputdata_t &data)
  249. {
  250. m_iChangedVariables |= FOG_CONTROLLER_END_LERP;
  251. m_fog.endLerpTo = data.value.Float();
  252. }
  253. void CFogController::InputStartFogTransition(inputdata_t &data)
  254. {
  255. SetThink( &CFogController::SetLerpValues );
  256. m_fog.lerptime = gpGlobals->curtime + m_fog.duration + 0.1;
  257. SetNextThink( gpGlobals->curtime + m_fog.duration );
  258. }
  259. void CFogController::SetLerpValues( void )
  260. {
  261. if ( m_iChangedVariables & FOG_CONTROLLER_COLORPRIMARY_LERP )
  262. {
  263. m_fog.colorPrimary = m_fog.colorPrimaryLerpTo;
  264. }
  265. if ( m_iChangedVariables & FOG_CONTROLLER_COLORSECONDARY_LERP )
  266. {
  267. m_fog.colorSecondary = m_fog.colorSecondaryLerpTo;
  268. }
  269. if ( m_iChangedVariables & FOG_CONTROLLER_START_LERP )
  270. {
  271. m_fog.start = m_fog.startLerpTo;
  272. }
  273. if ( m_iChangedVariables & FOG_CONTROLLER_END_LERP )
  274. {
  275. m_fog.end = m_fog.endLerpTo;
  276. }
  277. m_iChangedVariables = 0;
  278. m_fog.lerptime = gpGlobals->curtime;
  279. }
  280. //-----------------------------------------------------------------------------
  281. // Purpose: Clear out the fog controller.
  282. //-----------------------------------------------------------------------------
  283. void CFogSystem::LevelInitPreEntity( void )
  284. {
  285. m_pMasterController = NULL;
  286. }
  287. //-----------------------------------------------------------------------------
  288. // Purpose: On level load find the master fog controller. If no controller is
  289. // set as Master, use the first fog controller found.
  290. //-----------------------------------------------------------------------------
  291. void CFogSystem::LevelInitPostEntity( void )
  292. {
  293. CFogController *pFogController = NULL;
  294. do
  295. {
  296. pFogController = static_cast<CFogController*>( gEntList.FindEntityByClassname( pFogController, "env_fog_controller" ) );
  297. if ( pFogController )
  298. {
  299. if ( m_pMasterController == NULL )
  300. {
  301. m_pMasterController = pFogController;
  302. }
  303. else
  304. {
  305. if ( pFogController->IsMaster() )
  306. {
  307. m_pMasterController = pFogController;
  308. }
  309. }
  310. }
  311. } while ( pFogController );
  312. // HACK: Singleplayer games don't get a call to CBasePlayer::Spawn on level transitions.
  313. // CBasePlayer::Activate is called before this is called so that's too soon to set up the fog controller.
  314. // We don't have a hook similar to Activate that happens after LevelInitPostEntity
  315. // is called, or we could just do this in the player itself.
  316. if ( gpGlobals->maxClients == 1 )
  317. {
  318. CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
  319. if ( pPlayer && ( pPlayer->m_Local.m_PlayerFog.m_hCtrl.Get() == NULL ) )
  320. {
  321. pPlayer->InitFogController();
  322. }
  323. }
  324. }