home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / game / Light.cpp < prev    next >
C/C++ Source or Header  |  2005-11-14  |  39KB  |  1,515 lines

  1.  
  2. #include "../idlib/precompiled.h"
  3. #pragma hdrstop
  4.  
  5. #include "Game_local.h"
  6.  
  7. /*
  8. ===============================================================================
  9.  
  10.   idLight
  11.  
  12. ===============================================================================
  13. */
  14.  
  15. const idEventDef EV_Light_SetShader( "setShader", "s" );
  16. const idEventDef EV_Light_GetLightParm( "getLightParm", "d", 'f' );
  17. const idEventDef EV_Light_SetLightParm( "setLightParm", "df" );
  18. const idEventDef EV_Light_SetLightParms( "setLightParms", "ffff" );
  19. const idEventDef EV_Light_SetRadiusXYZ( "setRadiusXYZ", "fff" );
  20. const idEventDef EV_Light_SetRadius( "setRadius", "f" );
  21. const idEventDef EV_Light_On( "On", NULL );
  22. const idEventDef EV_Light_Off( "Off", NULL );
  23. const idEventDef EV_Light_FadeOut( "fadeOutLight", "f" );
  24. const idEventDef EV_Light_FadeIn( "fadeInLight", "f" );
  25.  
  26. // RAVEN BEGIN
  27. // bdube: added
  28. const idEventDef EV_Light_SetLightGUI ( "setLightGUI", "s" );
  29. // jscott: added for modview
  30. const idEventDef EV_Light_SetCurrentLightLevel( "setCurrentLightLevel", "d" );
  31. const idEventDef EV_Light_SetMaxLightLevel( "setMaxLightLevel", "d" );
  32. // kfuller: 8/11/03
  33. const idEventDef EV_Light_IsOn( "isOn", NULL, 'f' );
  34. const idEventDef EV_Light_Break( "break", "ef" );
  35. // kfuller: lights that blink to life
  36. const idEventDef EV_Light_DoneBlinking( "doneBlinking", NULL );
  37. // kfuller: lights that blink off
  38. const idEventDef EV_Light_DoneBlinkingOff( "doneBlinkingOff", NULL );
  39. // abahr:
  40. const idEventDef EV_Light_Timer( "<lightTimer>" );
  41. // RAVEN END
  42.  
  43. CLASS_DECLARATION( idEntity, idLight )
  44.     EVENT( EV_Light_SetShader,        idLight::Event_SetShader )
  45.     EVENT( EV_Light_GetLightParm,    idLight::Event_GetLightParm )
  46.     EVENT( EV_Light_SetLightParm,    idLight::Event_SetLightParm )
  47.     EVENT( EV_Light_SetLightParms,    idLight::Event_SetLightParms )
  48.     EVENT( EV_Light_SetRadiusXYZ,    idLight::Event_SetRadiusXYZ )
  49.     EVENT( EV_Light_SetRadius,        idLight::Event_SetRadius )
  50.     EVENT( EV_Hide,                    idLight::Event_Hide )
  51.     EVENT( EV_Show,                    idLight::Event_Show )
  52.     EVENT( EV_Light_On,                idLight::Event_On )
  53.     EVENT( EV_Light_Off,            idLight::Event_Off )
  54.     EVENT( EV_Activate,                idLight::Event_ToggleOnOff )
  55.     EVENT( EV_PostSpawn,            idLight::Event_SetSoundHandles )
  56.     EVENT( EV_Light_FadeOut,        idLight::Event_FadeOut )
  57.     EVENT( EV_Light_FadeIn,            idLight::Event_FadeIn )
  58.  
  59. // RAVEN BEGIN
  60. // bdube: added
  61.     EVENT( EV_Light_SetLightGUI,                idLight::Event_SetLightGUI )
  62.     EVENT( EV_Light_SetCurrentLightLevel,        idLight::Event_SetCurrentLightLevel )
  63.     EVENT( EV_Light_SetMaxLightLevel,            idLight::Event_SetMaxLightLevel )
  64. // kfuller: 8/11/03
  65.     EVENT( EV_Light_IsOn,            idLight::Event_IsOn )
  66.     EVENT( EV_Light_Break,            idLight::Event_Break )
  67. // kfuller: lights that blink to life
  68.     EVENT( EV_Light_DoneBlinking,    idLight::Event_DoneBlinking )
  69. // kfuller: lights that blink off
  70.     EVENT( EV_Light_DoneBlinkingOff,    idLight::Event_DoneBlinkingOff )
  71.     EVENT( EV_Earthquake,                idLight::Event_EarthQuake )
  72. // abahr:
  73.     EVENT( EV_Light_Timer,                idLight::Event_Timer )
  74. // RAVEN END
  75. END_CLASS
  76.  
  77.  
  78. /*
  79. ================
  80. idGameEdit::ParseSpawnArgsToRenderLight
  81.  
  82. parse the light parameters
  83. this is the canonical renderLight parm parsing,
  84. which should be used by dmap and the editor
  85. ================
  86. */
  87. bool idGameEdit::ParseSpawnArgsToRenderLight( const idDict *args, renderLight_t *renderLight ) {
  88.     bool        gotTarget, gotUp, gotRight;
  89.     const char    *texture;
  90.     idVec3        color;
  91.     bool        rv = true;
  92.  
  93.     memset( renderLight, 0, sizeof( *renderLight ) );
  94.  
  95.     if (!args->GetVector("light_origin", "", renderLight->origin)) {
  96.         args->GetVector( "origin", "", renderLight->origin );
  97.     }
  98.  
  99.     gotTarget = args->GetVector( "light_target", "", renderLight->target );
  100.     gotUp = args->GetVector( "light_up", "", renderLight->up );
  101.     gotRight = args->GetVector( "light_right", "", renderLight->right );
  102.     args->GetVector( "light_start", "0 0 0", renderLight->start );
  103.     if ( !args->GetVector( "light_end", "", renderLight->end ) ) {
  104.         renderLight->end = renderLight->target;
  105.     }
  106.  
  107.     // we should have all of the target/right/up or none of them
  108.     if ( ( gotTarget || gotUp || gotRight ) != ( gotTarget && gotUp && gotRight ) ) {
  109.         gameLocal.Warning( "Light at (%f,%f,%f) has bad target info\n",
  110.             renderLight->origin[0], renderLight->origin[1], renderLight->origin[2] );
  111.  
  112.         return false;
  113.     }
  114.  
  115.     if ( !gotTarget ) {
  116.         renderLight->pointLight = true;
  117.  
  118.         // allow an optional relative center of light and shadow offset
  119.         args->GetVector( "light_center", "0 0 0", renderLight->lightCenter );
  120.  
  121. // RAVEN BEGIN
  122. // bdube: default light radius changed to 320
  123.         // create a point light
  124.         if (!args->GetVector( "light_radius", "320 320 320", renderLight->lightRadius ) ) {
  125.             float radius;
  126.  
  127.             args->GetFloat( "light", "320", radius );
  128. // RAVEN END
  129.             renderLight->lightRadius[0] = renderLight->lightRadius[1] = renderLight->lightRadius[2] = radius;
  130.         }
  131.  
  132.         if ( renderLight->lightRadius[0] == 0 ||
  133.              renderLight->lightRadius[1] == 0 ||
  134.              renderLight->lightRadius[2] == 0 ) {
  135.             gameLocal.Warning( "PointLight at ( %d, %d, %d ) has at least one radius component of 0!",
  136.                 ( int )renderLight->origin[0], ( int )renderLight->origin[1], ( int )renderLight->origin[2] );
  137.             rv = false;
  138.         }
  139.     }
  140.  
  141.     // get the rotation matrix in either full form, or single angle form
  142.     idAngles angles;
  143.     idMat3 mat;
  144.     if ( !args->GetMatrix( "light_rotation", "1 0 0 0 1 0 0 0 1", mat ) ) {
  145.         if ( !args->GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", mat ) ) {
  146.                args->GetFloat( "angle", "0", angles[ 1 ] );
  147.                angles[ 0 ] = 0;
  148.             angles[ 1 ] = idMath::AngleNormalize360( angles[ 1 ] );
  149.                angles[ 2 ] = 0;
  150.             mat = angles.ToMat3();
  151.         }
  152.     }
  153.  
  154.     // fix degenerate identity matrices
  155.     mat[0].FixDegenerateNormal();
  156.     mat[1].FixDegenerateNormal();
  157.     mat[2].FixDegenerateNormal();
  158.  
  159.     renderLight->axis = mat;
  160.  
  161.     // check for other attributes
  162.     args->GetVector( "_color", "1 1 1", color );
  163.     renderLight->shaderParms[ SHADERPARM_RED ]        = color[0];
  164.     renderLight->shaderParms[ SHADERPARM_GREEN ]    = color[1];
  165.     renderLight->shaderParms[ SHADERPARM_BLUE ]        = color[2];
  166.     args->GetFloat( "shaderParm3", "1", renderLight->shaderParms[ SHADERPARM_TIMESCALE ] );
  167.     if ( !args->GetFloat( "shaderParm4", "0", renderLight->shaderParms[ SHADERPARM_TIMEOFFSET ] ) ) {
  168.         // offset the start time of the shader to sync it to the game time
  169.         renderLight->shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
  170.     }
  171.  
  172.     args->GetFloat( "shaderParm5", "0", renderLight->shaderParms[5] );
  173.     args->GetFloat( "shaderParm6", "0", renderLight->shaderParms[6] );
  174.     args->GetFloat( "shaderParm7", "0", renderLight->shaderParms[ SHADERPARM_MODE ] );
  175.     args->GetBool( "noshadows", "0", renderLight->noShadows );
  176.  
  177. // RAVEN BEGIN
  178. // dluetscher: added a min light detail level setting that describes when this light is visible
  179.     args->GetFloat( "detailLevel", "10", renderLight->detailLevel );
  180. // RAVEN END
  181.  
  182. // RAVEN BEGIN
  183. // ddynerman: dynamic shadows
  184.     args->GetBool( "noDynamicShadows", "0", renderLight->noDynamicShadows );
  185. // RAVEN END
  186.     args->GetBool( "nospecular", "0", renderLight->noSpecular );
  187.     args->GetBool( "parallel", "0", renderLight->parallel );
  188.  
  189.     args->GetString( "texture", "lights/squarelight1", &texture );
  190.     // allow this to be NULL
  191.     renderLight->shader = declManager->FindMaterial( texture, false );
  192.  
  193.     return rv;
  194. }
  195.  
  196. /*
  197. ================
  198. idLight::UpdateChangeableSpawnArgs
  199. ================
  200. */
  201. void idLight::UpdateChangeableSpawnArgs( const idDict *source ) {
  202.  
  203.     idEntity::UpdateChangeableSpawnArgs( source );
  204.  
  205.     if ( source ) {
  206.         source->Print();
  207.     }
  208.     FreeSoundEmitter( true );
  209.     gameEdit->ParseSpawnArgsToRefSound( source ? source : &spawnArgs, &refSound );
  210.     if ( refSound.shader && !refSound.waitfortrigger ) {
  211.         StartSoundShader( refSound.shader, SND_CHANNEL_ANY, 0, false, NULL );
  212.     }
  213.  
  214.     gameEdit->ParseSpawnArgsToRenderLight( source ? source : &spawnArgs, &renderLight );
  215.  
  216.     UpdateVisuals();
  217. }
  218.  
  219. /*
  220. ================
  221. idLight::idLight
  222. ================
  223. */
  224. idLight::idLight() {
  225.     memset( &renderLight, 0, sizeof( renderLight ) );
  226. // RAVEN BEGIN
  227. // dluetscher: added a default detail level to each render light
  228.     renderLight.detailLevel = DEFAULT_LIGHT_DETAIL_LEVEL;
  229. // RAVEN END
  230.     localLightOrigin    = vec3_zero;
  231.     localLightAxis        = mat3_identity;
  232.     lightDefHandle        = -1;
  233.     levels                = 0;
  234.     currentLevel        = 0;
  235.     baseColor            = vec3_zero;
  236.     breakOnTrigger        = false;
  237.     count                = 0;
  238.     triggercount        = 0;
  239.     lightParent            = NULL;
  240.     fadeFrom.Set( 1, 1, 1, 1 );
  241.     fadeTo.Set( 1, 1, 1, 1 );
  242.     fadeStart            = 0;
  243.     fadeEnd                = 0;
  244.     soundWasPlaying        = false;
  245.     
  246. // RAVEN BEGIN
  247. // bdube: light gui
  248.     lightGUI            = NULL;
  249.     random                = 0.0f;
  250.     wait                = 0.0f;
  251. // RAVEN END    
  252. }
  253.  
  254. /*
  255. ================
  256. idLight::~idLight
  257. ================
  258. */
  259. idLight::~idLight() {
  260.     if ( lightDefHandle != -1 ) {
  261.         gameRenderWorld->FreeLightDef( lightDefHandle );
  262.     }
  263. }
  264.  
  265. /*
  266. ================
  267. idLight::Save
  268.  
  269. archives object for save game file
  270. ================
  271. */
  272. void idLight::Save( idSaveGame *savefile ) const {
  273.     savefile->WriteRenderLight( renderLight );
  274.     
  275.     savefile->WriteBool( renderLight.prelightModel != NULL );
  276.  
  277.     savefile->WriteVec3( localLightOrigin );
  278.     savefile->WriteMat3( localLightAxis );
  279.     //qhandle_t        lightDefHandle;    // cnicholson: This wasn't here from id, so I didnt add it either. 
  280.  
  281.     savefile->WriteString( brokenModel );
  282.     savefile->WriteInt( levels );
  283.     savefile->WriteInt( currentLevel );
  284.  
  285.     savefile->WriteVec3( baseColor );
  286.     savefile->WriteBool( breakOnTrigger );
  287.     savefile->WriteInt( count );
  288.     savefile->WriteInt( triggercount );
  289.     savefile->WriteObject( lightParent );
  290.  
  291.     savefile->WriteVec4( fadeFrom );
  292.     savefile->WriteVec4( fadeTo );
  293.     savefile->WriteInt( fadeStart );
  294.     savefile->WriteInt( fadeEnd );
  295.  
  296.     lightGUI.Save( savefile );            // cnicholson: added unsaved var
  297.  
  298.     savefile->WriteBool( soundWasPlaying );
  299. }
  300.  
  301. /*
  302. ================
  303. idLight::Restore
  304.  
  305. unarchives object from save game file
  306. ================
  307. */
  308. void idLight::Restore( idRestoreGame *savefile ) {
  309. // RAVEN BEGIN
  310. // jscott: constants can be read from the spawnargs
  311.     wait = spawnArgs.GetFloat( "wait" );
  312.     random = spawnArgs.GetFloat( "random" );
  313. // RAVEN END
  314.  
  315.     bool hadPrelightModel;
  316.  
  317. // RAVEN BEGIN
  318. // mwhitlock: Xenon texture streaming
  319. #if defined(_XENON)
  320.     declManager->SetLightMaterialList(&renderLight.allMaterials);
  321. #endif
  322. // RAVEN END
  323.  
  324.     savefile->ReadRenderLight( renderLight );
  325.  
  326. // RAVEN BEGIN
  327. // mwhitlock: Xenon texture streaming
  328. #if defined(_XENON)
  329.     declManager->SetLightMaterialList(0);
  330. #endif
  331. // RAVEN END
  332.  
  333.     savefile->ReadBool( hadPrelightModel );
  334.     renderLight.prelightModel = renderModelManager->CheckModel( va( "_prelight_%s", name.c_str() ) );
  335.     if ( ( renderLight.prelightModel == NULL ) && hadPrelightModel ) {
  336.         assert( 0 );
  337.         if ( developer.GetBool() ) {
  338.             // we really want to know if this happens
  339.             gameLocal.Error( "idLight::Restore: prelightModel '_prelight_%s' not found", name.c_str() );
  340.         } else {
  341.             // but let it slide after release
  342.             gameLocal.Warning( "idLight::Restore: prelightModel '_prelight_%s' not found", name.c_str() );
  343.         }
  344.     }
  345.  
  346.     savefile->ReadVec3( localLightOrigin );
  347.     savefile->ReadMat3( localLightAxis );
  348.  
  349.     savefile->ReadString( brokenModel );
  350.     savefile->ReadInt( levels );
  351.     savefile->ReadInt( currentLevel );
  352.  
  353.     savefile->ReadVec3( baseColor );
  354.     savefile->ReadBool( breakOnTrigger );
  355.     savefile->ReadInt( count );
  356.     savefile->ReadInt( triggercount );
  357.     savefile->ReadObject( reinterpret_cast<idClass *&>( lightParent ) );
  358.  
  359.     savefile->ReadVec4( fadeFrom );
  360.     savefile->ReadVec4( fadeTo );
  361.     savefile->ReadInt( fadeStart );
  362.     savefile->ReadInt( fadeEnd );
  363. // RAVEN BEGIN
  364. // bdube: light gui
  365.     lightGUI.Restore ( savefile );
  366. // RAVEN END    
  367.  
  368.     savefile->ReadBool( soundWasPlaying );
  369.     
  370.     lightDefHandle = -1;
  371.  
  372.     SetLightLevel();
  373. }
  374.  
  375. /*
  376. ================
  377. idLight::Spawn
  378. ================
  379. */
  380. void idLight::Spawn( void ) {
  381.     bool start_off;
  382.     bool needBroken;
  383.     const char *demonic_shader;
  384.  
  385. // RAVEN BEGIN
  386. // mwhitlock: Xenon texture streaming
  387. #if defined(_XENON)
  388.     declManager->SetLightMaterialList(&renderLight.allMaterials);
  389. #endif
  390. // RAVEN END
  391.  
  392.     // do the parsing the same way dmap and the editor do
  393.     if ( !gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &renderLight ) ) {
  394.         gameLocal.Warning( "Removing invalid light named: %s", GetName() );
  395.         PostEventMS( &EV_Remove, 0 );
  396.         return;
  397.     }
  398.  
  399.     // we need the origin and axis relative to the physics origin/axis
  400.     localLightOrigin = ( renderLight.origin - GetPhysics()->GetOrigin() ) * GetPhysics()->GetAxis().Transpose();
  401.     localLightAxis = renderLight.axis * GetPhysics()->GetAxis().Transpose();
  402.  
  403.     // set the base color from the shader parms
  404.     baseColor.Set( renderLight.shaderParms[ SHADERPARM_RED ], renderLight.shaderParms[ SHADERPARM_GREEN ], renderLight.shaderParms[ SHADERPARM_BLUE ] );
  405.  
  406.     // set the number of light levels
  407.     spawnArgs.GetInt( "levels", "1", levels );
  408.     currentLevel = levels;
  409.     if ( levels <= 0 ) {
  410.         gameLocal.Error( "Invalid light level set on entity #%d(%s)", entityNumber, name.c_str() );
  411.     }
  412.  
  413.     // make sure the demonic shader is cached
  414.     if ( spawnArgs.GetString( "mat_demonic", NULL, &demonic_shader ) ) {
  415.         declManager->FindType( DECL_MATERIAL, demonic_shader );
  416.     }
  417.  
  418.     // game specific functionality, not mirrored in
  419.     // editor or dmap light parsing
  420.  
  421.     // also put the light texture on the model, so light flares
  422.     // can get the current intensity of the light
  423.     renderEntity.referenceShader = renderLight.shader;
  424.  
  425.     lightDefHandle = -1;        // no static version yet
  426.  
  427.     // see if an optimized shadow volume exists
  428.     // the renderer will ignore this value after a light has been moved,
  429.     // but there may still be a chance to get it wrong if the game moves
  430.     // a light before the first present, and doesn't clear the prelight
  431.     renderLight.prelightModel = 0;
  432.     if ( name[ 0 ] ) {
  433.         // this will return 0 if not found
  434.         renderLight.prelightModel = renderModelManager->CheckModel( va( "_prelight_%s", name.c_str() ) );
  435.     }
  436.  
  437.     spawnArgs.GetBool( "start_off", "0", start_off );
  438.     if ( start_off ) {
  439.         Off();
  440.     }
  441.  
  442.     health = spawnArgs.GetInt( "health", "0" );
  443.     spawnArgs.GetString( "broken", "", brokenModel );
  444.     spawnArgs.GetBool( "break", "0", breakOnTrigger );
  445.     spawnArgs.GetInt( "count", "1", count );
  446.  
  447.     triggercount = 0;
  448.  
  449.     fadeFrom.Set( 1, 1, 1, 1 );
  450.     fadeTo.Set( 1, 1, 1, 1 );
  451.     fadeStart            = 0;
  452.     fadeEnd                = 0;
  453.  
  454.     // if we have a health make light breakable
  455.     if ( health ) {
  456.         idStr model = spawnArgs.GetString( "model" );        // get the visual model
  457.         if ( !model.Length() ) {
  458.             gameLocal.Error( "Breakable light without a model set on entity #%d(%s)", entityNumber, name.c_str() );
  459.         }
  460.  
  461.         fl.takedamage    = true;
  462.  
  463.         // see if we need to create a broken model name
  464.         needBroken = true;
  465.         if ( model.Length() && !brokenModel.Length() ) {
  466.             int    pos;
  467.  
  468.             needBroken = false;
  469.         
  470.             pos = model.Find( "." );
  471.             if ( pos < 0 ) {
  472.                 pos = model.Length();
  473.             }
  474.             if ( pos > 0 ) {
  475.                 model.Left( pos, brokenModel );
  476.             }
  477.             brokenModel += "_broken";
  478.             if ( pos > 0 ) {
  479.                 brokenModel += &model[ pos ];
  480.             }
  481.         }
  482.     
  483.         // make sure the model gets cached
  484.         if ( !renderModelManager->CheckModel( brokenModel ) ) {
  485.             if ( needBroken ) {
  486.                 gameLocal.Error( "Model '%s' not found for entity %d(%s)", brokenModel.c_str(), entityNumber, name.c_str() );
  487.             } else {
  488.                 brokenModel = "";
  489.             }
  490.         }
  491.  
  492.         GetPhysics()->SetContents( spawnArgs.GetBool( "nonsolid" ) ? 0 : CONTENTS_SOLID );
  493.     }
  494.  
  495.     PostEventMS( &EV_PostSpawn, 0 );
  496.     
  497. // RAVEN BEGIN
  498. // bdube: light guis    
  499.     const char* lightGUI;
  500.     if ( spawnArgs.GetString ( "light_gui", "", &lightGUI ) ) {    
  501.         PostEventMS( &EV_Light_SetLightGUI, 0, lightGUI );
  502.     }
  503.  
  504. // abahr:
  505.     wait = spawnArgs.GetFloat( "wait" );
  506.     random = spawnArgs.GetFloat( "random" );
  507. // AReis: Minor light optimization stuff.
  508.     spawnArgs.GetBool( "globalLight", "0", renderLight.globalLight );
  509. // RAVEN END
  510.  
  511.     UpdateVisuals();
  512.  
  513. // RAVEN BEGIN
  514. // ddynerman: ambient lights added clientside
  515.      if( renderLight.shader && renderLight.shader->IsAmbientLight() ) {
  516.          if ( !gameLocal.ambientLights.Find( static_cast<idEntity*>(this) ) ) {
  517.              gameLocal.ambientLights.Append( static_cast<idEntity*>(this) );
  518.          }
  519.          fl.networkSync = false; // don't transmit ambient lights
  520.      }
  521. // RAVEN END
  522.  
  523. // RAVEN BEGIN
  524. // mwhitlock: Xenon texture streaming
  525. #if defined(_XENON)
  526.     declManager->SetLightMaterialList(0);
  527. #endif
  528. // RAVEN END
  529. }
  530.  
  531. /*
  532. ================
  533. idLight::SetLightLevel
  534. ================
  535. */
  536. void idLight::SetLightLevel( void ) {
  537.     idVec3    color;
  538.     float    intensity;
  539.  
  540.     intensity = ( float )currentLevel / ( float )levels;
  541.     color = baseColor * intensity;
  542.     renderLight.shaderParms[ SHADERPARM_RED ]    = color[ 0 ];
  543.     renderLight.shaderParms[ SHADERPARM_GREEN ]    = color[ 1 ];
  544.     renderLight.shaderParms[ SHADERPARM_BLUE ]    = color[ 2 ];
  545.     renderEntity.shaderParms[ SHADERPARM_RED ]    = color[ 0 ];
  546.     renderEntity.shaderParms[ SHADERPARM_GREEN ]= color[ 1 ];
  547.     renderEntity.shaderParms[ SHADERPARM_BLUE ]    = color[ 2 ];
  548.     PresentLightDefChange();
  549.     PresentModelDefChange();
  550. }
  551.  
  552. /*
  553. ================
  554. idLight::GetColor
  555. ================
  556. */
  557. void idLight::GetColor( idVec3 &out ) const {
  558.     out[ 0 ] = renderLight.shaderParms[ SHADERPARM_RED ];
  559.     out[ 1 ] = renderLight.shaderParms[ SHADERPARM_GREEN ];
  560.     out[ 2 ] = renderLight.shaderParms[ SHADERPARM_BLUE ];
  561. }
  562.  
  563. /*
  564. ================
  565. idLight::GetColor
  566. ================
  567. */
  568. void idLight::GetColor( idVec4 &out ) const {
  569.     out[ 0 ] = renderLight.shaderParms[ SHADERPARM_RED ];
  570.     out[ 1 ] = renderLight.shaderParms[ SHADERPARM_GREEN ];
  571.     out[ 2 ] = renderLight.shaderParms[ SHADERPARM_BLUE ];
  572.     out[ 3 ] = renderLight.shaderParms[ SHADERPARM_ALPHA ];
  573. }
  574.  
  575. /*
  576. ================
  577. idLight::SetColor
  578. ================
  579. */
  580. void idLight::SetColor( float red, float green, float blue ) {
  581.     baseColor.Set( red, green, blue );
  582.     SetLightLevel();
  583. }
  584.  
  585. /*
  586. ================
  587. idLight::SetColor
  588. ================
  589. */
  590. void idLight::SetColor( const idVec4 &color ) {
  591.     baseColor = color.ToVec3();
  592.     renderLight.shaderParms[ SHADERPARM_ALPHA ]        = color[ 3 ];
  593.     renderEntity.shaderParms[ SHADERPARM_ALPHA ]    = color[ 3 ];
  594.     SetLightLevel();
  595. }
  596.  
  597. /*
  598. ================
  599. idLight::SetShader
  600. ================
  601. */
  602. void idLight::SetShader( const char *shadername ) {
  603.     // allow this to be NULL
  604.     renderLight.shader = declManager->FindMaterial( shadername, false );
  605.     PresentLightDefChange();
  606. }
  607.  
  608. /*
  609. ================
  610. idLight::SetLightParm
  611. ================
  612. */
  613. void idLight::SetLightParm( int parmnum, float value ) {
  614.     if ( ( parmnum < 0 ) || ( parmnum >= MAX_ENTITY_SHADER_PARMS ) ) {
  615.         gameLocal.Error( "shader parm index (%d) out of range", parmnum );
  616.     }
  617.  
  618.     renderLight.shaderParms[ parmnum ] = value;
  619.     PresentLightDefChange();
  620. }
  621.  
  622. /*
  623. ================
  624. idLight::SetLightParms
  625. ================
  626. */
  627. void idLight::SetLightParms( float parm0, float parm1, float parm2, float parm3 ) {
  628.     renderLight.shaderParms[ SHADERPARM_RED ]        = parm0;
  629.     renderLight.shaderParms[ SHADERPARM_GREEN ]        = parm1;
  630.     renderLight.shaderParms[ SHADERPARM_BLUE ]        = parm2;
  631.     renderLight.shaderParms[ SHADERPARM_ALPHA ]        = parm3;
  632.     renderEntity.shaderParms[ SHADERPARM_RED ]        = parm0;
  633.     renderEntity.shaderParms[ SHADERPARM_GREEN ]    = parm1;
  634.     renderEntity.shaderParms[ SHADERPARM_BLUE ]        = parm2;
  635.     renderEntity.shaderParms[ SHADERPARM_ALPHA ]    = parm3;
  636.     baseColor.Set( parm0, parm1, parm2 );
  637.     PresentLightDefChange();
  638.     PresentModelDefChange();
  639. }
  640.  
  641. /*
  642. ================
  643. idLight::SetRadiusXYZ
  644. ================
  645. */
  646. void idLight::SetRadiusXYZ( float x, float y, float z ) {
  647.     renderLight.lightRadius[0] = x;
  648.     renderLight.lightRadius[1] = y;
  649.     renderLight.lightRadius[2] = z;
  650.     PresentLightDefChange();
  651. }
  652.  
  653. /*
  654. ================
  655. idLight::SetRadius
  656. ================
  657. */
  658. void idLight::SetRadius( float radius ) {
  659.     renderLight.lightRadius[0] = renderLight.lightRadius[1] = renderLight.lightRadius[2] = radius;
  660.     PresentLightDefChange();
  661. }
  662.  
  663. /*
  664. ================
  665. idLight::On
  666. ================
  667. */
  668. void idLight::On( void ) {
  669.     currentLevel = levels;
  670.     // offset the start time of the shader to sync it to the game time
  671.     renderLight.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
  672.  
  673. // RAVEN BEGIN
  674.     idStr    blinkOnSound;
  675.     if (spawnArgs.GetString("snd_blinkOn", "", blinkOnSound))
  676.     {
  677.         refSound.shader = declManager->FindSound(blinkOnSound);
  678.         int howLongInMS = StartSoundShader( refSound.shader, SND_CHANNEL_ANY, 0, false, NULL );
  679.         PostEventMS(&EV_Light_DoneBlinking, howLongInMS);
  680.         soundWasPlaying = false;
  681.         idStr    blinkOnTexture;
  682.         if (spawnArgs.GetString( "mtr_blinkOn", "", blinkOnTexture ))
  683.         {
  684.             renderLight.shader = declManager->FindMaterial( blinkOnTexture, false );
  685.             UpdateVisuals();
  686.             Present();
  687.         }
  688.     }
  689.     else
  690. // RAVEN END
  691.  
  692.     if ( ( soundWasPlaying || refSound.waitfortrigger ) && refSound.shader ) {
  693.         StartSoundShader( refSound.shader, SND_CHANNEL_ANY, 0, false, NULL );
  694.         soundWasPlaying = false;
  695.     }
  696.     SetLightLevel();
  697.     BecomeActive( TH_UPDATEVISUALS );
  698. }
  699.  
  700. /*
  701. ================
  702. idLight::Off
  703. ================
  704. */
  705. void idLight::Off( void ) {
  706. // RAVEN BEGIN
  707. // kfuller: lights can flicker off
  708.     idStr    blinkOffSound;
  709.     if (spawnArgs.GetString("snd_blinkOff", "", blinkOffSound))
  710.     {
  711.         refSound.shader = declManager->FindSound(blinkOffSound);
  712.         int howLongInMS = StartSoundShader( refSound.shader, SND_CHANNEL_ANY, 0, false, NULL );//*1000;
  713.         PostEventMS(&EV_Light_DoneBlinkingOff, howLongInMS);
  714.         soundWasPlaying = false;
  715.         idStr    blinkOffTexture;
  716.         if (spawnArgs.GetString( "mtr_blinkOff", "", blinkOffTexture ))
  717.         {
  718.             renderLight.shader = declManager->FindMaterial( blinkOffTexture, false );
  719.             UpdateVisuals();
  720.             Present();
  721.         }
  722.     }
  723.     else
  724.     {
  725.         currentLevel = 0;
  726.         // kill any sound it was making
  727.         idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  728.         if ( emitter && emitter->CurrentlyPlaying() ) {
  729.             StopSound( SND_CHANNEL_ANY, false );
  730.             soundWasPlaying = true;
  731.         }
  732.     }
  733. // RAVEN END
  734.     SetLightLevel();
  735.     BecomeActive( TH_UPDATEVISUALS );
  736. }
  737.  
  738. /*
  739. ================
  740. idLight::Fade
  741. ================
  742. */
  743. void idLight::Fade( const idVec4 &to, float fadeTime ) {
  744.     GetColor( fadeFrom );
  745.     fadeTo = to;
  746.     fadeStart = gameLocal.time;
  747.     fadeEnd = gameLocal.time + SEC2MS( fadeTime );
  748.     BecomeActive( TH_THINK );
  749. }
  750.  
  751. /*
  752. ================
  753. idLight::FadeOut
  754. ================
  755. */
  756. void idLight::FadeOut( float time ) {
  757.     Fade( colorBlack, time );
  758. }
  759.  
  760. /*
  761. ================
  762. idLight::FadeIn
  763. ================
  764. */
  765. void idLight::FadeIn( float time ) {
  766.     idVec3 color;
  767.     idVec4 color4;
  768.  
  769.     currentLevel = levels;
  770.     spawnArgs.GetVector( "_color", "1 1 1", color );
  771.     color4.Set( color.x, color.y, color.z, 1.0f );
  772.     Fade( color4, time );
  773. }
  774.  
  775. /*
  776. ================
  777. idLight::Killed
  778. ================
  779. */
  780. void idLight::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
  781.     BecomeBroken( attacker );
  782. }
  783.  
  784. /*
  785. ================
  786. idLight::BecomeBroken
  787. ================
  788. */
  789. void idLight::BecomeBroken( idEntity *activator ) {
  790.     const char *damageDefName;
  791.  
  792.     fl.takedamage = false;
  793.  
  794.     if ( brokenModel.Length() ) {
  795.         SetModel( brokenModel );
  796.  
  797.         if ( !spawnArgs.GetBool( "nonsolid" ) ) {
  798. // RAVEN BEGIN
  799. // mwhitlock: Dynamic memory consolidation
  800.             RV_PUSH_HEAP_MEM(this);
  801. // RAVEN END
  802.             GetPhysics()->SetClipModel( new idClipModel( brokenModel.c_str() ), 1.0f );
  803. // RAVEN BEGIN
  804. // mwhitlock: Dynamic memory consolidation
  805.             RV_POP_HEAP();
  806. // RAVEN END
  807.             GetPhysics()->SetContents( CONTENTS_SOLID );
  808.         }
  809.     } else if ( spawnArgs.GetBool( "hideModelOnBreak" ) ) {
  810.         SetModel( "" );
  811.         GetPhysics()->SetContents( 0 );
  812.     }
  813.  
  814.     if ( gameLocal.isServer ) {
  815.  
  816.         ServerSendInstanceEvent( EVENT_BECOMEBROKEN, NULL, true, -1 );
  817.  
  818.         if ( spawnArgs.GetString( "def_damage", "", &damageDefName ) ) {
  819.             idVec3 origin = renderEntity.origin + renderEntity.bounds.GetCenter() * renderEntity.axis;
  820.             gameLocal.RadiusDamage( origin, activator, activator, this, this, damageDefName );
  821.         }
  822.  
  823.     }
  824.  
  825.     ActivateTargets( activator );
  826.  
  827.     // offset the start time of the shader to sync it to the game time
  828.     renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
  829.     renderLight.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
  830.  
  831.     // set the state parm
  832.     renderEntity.shaderParms[ SHADERPARM_MODE ] = 1;
  833.     renderLight.shaderParms[ SHADERPARM_MODE ] = 1;
  834.  
  835.     // if the light has a sound, either start the alternate (broken) sound, or stop the sound
  836.     const char *parm = spawnArgs.GetString( "snd_broken" );
  837.     if ( refSound.shader || ( parm && *parm ) ) {
  838.         StopSound( SND_CHANNEL_ANY, false );
  839.         const idSoundShader *alternate = refSound.shader ? refSound.shader->GetAltSound() : declManager->FindSound( parm );
  840.         if ( alternate ) {
  841.             // start it with no diversity, so the leadin break sound plays
  842.             idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  843.             if( emitter ) {
  844.                 emitter->UpdateEmitter( refSound.origin, refSound.velocity, refSound.listenerId, &refSound.parms );
  845.                 emitter->StartSound( alternate, SND_CHANNEL_ANY, 0.0, 0 );
  846.             }
  847.         }
  848.     }
  849.  
  850.     parm = spawnArgs.GetString( "mtr_broken" );
  851.     if ( parm && *parm ) {
  852.         SetShader( parm );
  853.     }
  854.  
  855.     UpdateVisuals();
  856. }
  857.  
  858. /*
  859. ================
  860. idLight::PresentLightDefChange
  861. ================
  862. */
  863. void idLight::PresentLightDefChange( void ) {
  864.     // let the renderer apply it to the world
  865.     if ( ( lightDefHandle != -1 ) ) {
  866.         gameRenderWorld->UpdateLightDef( lightDefHandle, &renderLight );
  867.     } else {
  868.         lightDefHandle = gameRenderWorld->AddLightDef( &renderLight );
  869.     }
  870. }
  871.  
  872. /*
  873. ================
  874. idLight::PresentModelDefChange
  875. ================
  876. */
  877. void idLight::PresentModelDefChange( void ) {
  878.  
  879.     if ( !renderEntity.hModel || IsHidden() ) {
  880.         return;
  881.     }
  882.  
  883.     // add to refresh list
  884.     if ( modelDefHandle == -1 ) {
  885.         modelDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
  886.     } else {
  887.         gameRenderWorld->UpdateEntityDef( modelDefHandle, &renderEntity );
  888.     }
  889. }
  890.  
  891. /*
  892. ================
  893. idLight::Present
  894. ================
  895. */
  896. void idLight::Present( void ) {
  897. // RAVEN BEGIN
  898. // jnewquist: Tag scope and callees to track allocations using "new".
  899.     MEM_SCOPED_TAG( tag, MA_RENDER );
  900. // RAVEN END
  901.     // don't present to the renderer if the entity hasn't changed
  902.     if ( !( thinkFlags & TH_UPDATEVISUALS ) ) {
  903.         return;
  904.     }
  905.  
  906.     // add the model
  907.     idEntity::Present();
  908.  
  909.     // current transformation
  910.     renderLight.axis    = localLightAxis * GetPhysics()->GetAxis();
  911.     renderLight.origin  = GetPhysics()->GetOrigin() + GetPhysics()->GetAxis() * localLightOrigin;
  912.  
  913.     // reference the sound for shader synced effects
  914.     if ( lightParent ) {
  915. // RAVEN BEGIN
  916.         renderLight.referenceSoundHandle = lightParent->GetSoundEmitter();
  917.         renderEntity.referenceSoundHandle = lightParent->GetSoundEmitter();
  918.     }
  919.     else {
  920.         renderLight.referenceSoundHandle = refSound.referenceSoundHandle;
  921.         renderEntity.referenceSoundHandle = refSound.referenceSoundHandle;
  922. // RAVEN END
  923.     }
  924.  
  925.     // update the renderLight and renderEntity to render the light and flare
  926.     PresentLightDefChange();
  927.     PresentModelDefChange();
  928. }
  929.  
  930. /*
  931. ================
  932. idLight::Think
  933. ================
  934. */
  935. void idLight::Think( void ) {
  936.     idVec4 color;
  937.  
  938.     if ( thinkFlags & TH_THINK ) {
  939.         if ( fadeEnd > 0 ) {
  940.             if ( gameLocal.time < fadeEnd ) {
  941.                 color.Lerp( fadeFrom, fadeTo, ( float )( gameLocal.time - fadeStart ) / ( float )( fadeEnd - fadeStart ) );
  942.             } else {
  943.                 color = fadeTo;
  944.                 fadeEnd = 0;
  945.                 BecomeInactive( TH_THINK );
  946.             }
  947.             SetColor( color );
  948.         }
  949.  
  950. // RAVEN BEGIN
  951. // bdube: gui controlled lights        
  952.         if ( lightGUI ) {
  953.             SetColor ( lightGUI->GetRenderEntity()->gui[0]->GetLightColor ( ) );
  954.         }
  955. // RAVEN END
  956.     }
  957.  
  958.     RunPhysics();
  959.     Present();
  960. }
  961.  
  962. /*
  963. ================
  964. idLight::GetPhysicsToSoundTransform
  965. ================
  966. */
  967. bool idLight::GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ) {
  968.     origin = localLightOrigin + renderLight.lightCenter;
  969.     axis = localLightAxis * GetPhysics()->GetAxis();
  970.     return true;
  971. }
  972.  
  973. /*
  974. ================
  975. idLight::FreeLightDef
  976. ================
  977. */
  978. void idLight::FreeLightDef( void ) {
  979.     if ( lightDefHandle != -1 ) {
  980.         gameRenderWorld->FreeLightDef( lightDefHandle );
  981.         lightDefHandle = -1;
  982.     }
  983. }
  984.  
  985. /*
  986. ================
  987. idLight::SaveState
  988. ================
  989. */
  990. void idLight::SaveState( idDict *args ) {
  991.     int i, c = spawnArgs.GetNumKeyVals();
  992.     for ( i = 0; i < c; i++ ) {
  993.         const idKeyValue *pv = spawnArgs.GetKeyVal(i);
  994.         if ( pv->GetKey().Find( "editor_", false ) >= 0 || pv->GetKey().Find( "parse_", false ) >= 0 ) {
  995.             continue;
  996.         }
  997.         args->Set( pv->GetKey(), pv->GetValue() );
  998.     }
  999. }
  1000.  
  1001. /*
  1002. ===============
  1003. idLight::ShowEditingDialog
  1004. ===============
  1005. */
  1006. void idLight::ShowEditingDialog( void ) {
  1007.     if ( g_editEntityMode.GetInteger() == 1 ) {
  1008.         common->InitTool( EDITOR_LIGHT, &spawnArgs );
  1009.     } else {
  1010.         common->InitTool( EDITOR_SOUND, &spawnArgs );
  1011.     }
  1012. }
  1013.  
  1014. /*
  1015. ================
  1016. idLight::Event_SetShader
  1017. ================
  1018. */
  1019. void idLight::Event_SetShader( const char *shadername ) {
  1020.     SetShader( shadername );
  1021. }
  1022.  
  1023. /*
  1024. ================
  1025. idLight::Event_GetLightParm
  1026. ================
  1027. */
  1028. void idLight::Event_GetLightParm( int parmnum ) {
  1029.     if ( ( parmnum < 0 ) || ( parmnum >= MAX_ENTITY_SHADER_PARMS ) ) {
  1030.         gameLocal.Error( "shader parm index (%d) out of range", parmnum );
  1031.     }
  1032.  
  1033.     idThread::ReturnFloat( renderLight.shaderParms[ parmnum ] );
  1034. }
  1035.  
  1036. /*
  1037. ================
  1038. idLight::Event_SetLightParm
  1039. ================
  1040. */
  1041. void idLight::Event_SetLightParm( int parmnum, float value ) {
  1042.     SetLightParm( parmnum, value );
  1043. }
  1044.  
  1045. /*
  1046. ================
  1047. idLight::Event_SetLightParms
  1048. ================
  1049. */
  1050. void idLight::Event_SetLightParms( float parm0, float parm1, float parm2, float parm3 ) {
  1051.     SetLightParms( parm0, parm1, parm2, parm3 );
  1052. }
  1053.  
  1054. /*
  1055. ================
  1056. idLight::Event_SetRadiusXYZ
  1057. ================
  1058. */
  1059. void idLight::Event_SetRadiusXYZ( float x, float y, float z ) {
  1060.     SetRadiusXYZ( x, y, z );
  1061. }
  1062.  
  1063. /*
  1064. ================
  1065. idLight::Event_SetRadius
  1066. ================
  1067. */
  1068. void idLight::Event_SetRadius( float radius ) {
  1069.     SetRadius( radius );
  1070. }
  1071.  
  1072. /*
  1073. ================
  1074. idLight::Event_Hide
  1075. ================
  1076. */
  1077. void idLight::Event_Hide( void ) {
  1078.     Hide();
  1079.     PresentModelDefChange();
  1080.     Off();
  1081. }
  1082.  
  1083. /*
  1084. ================
  1085. idLight::Event_Show
  1086. ================
  1087. */
  1088. void idLight::Event_Show( void ) {
  1089.     Show();
  1090.     PresentModelDefChange();
  1091.     On();
  1092. }
  1093.  
  1094. /*
  1095. ================
  1096. idLight::Event_On
  1097. ================
  1098. */
  1099. void idLight::Event_On( void ) {
  1100.     On();
  1101. }
  1102.  
  1103. /*
  1104. ================
  1105. idLight::Event_Off
  1106. ================
  1107. */
  1108. void idLight::Event_Off( void ) {
  1109.     Off();
  1110. }
  1111.  
  1112. /*
  1113. ================
  1114. idLight::Event_ToggleOnOff
  1115. ================
  1116. */
  1117. void idLight::Event_ToggleOnOff( idEntity *activator ) {
  1118. // RAVEN BEGIN
  1119. // abahr:
  1120.     if( wait > 0 ) {
  1121.         if( EventIsPosted(&EV_Light_Timer) ) {
  1122.             CancelEvents( &EV_Light_Timer );
  1123.         } else {
  1124.             ProcessEvent( &EV_Light_Timer );
  1125.         }
  1126.     } else {
  1127. // RAVEN END
  1128.     triggercount++;
  1129.     if ( triggercount < count ) {
  1130.         return;
  1131.     }
  1132.  
  1133.     // reset trigger count
  1134.     triggercount = 0;
  1135.  
  1136.     if ( breakOnTrigger ) {
  1137.         BecomeBroken( activator );
  1138.         breakOnTrigger = false;
  1139.         return;
  1140.     }
  1141.  
  1142.     if ( !currentLevel ) {
  1143.         On();
  1144.     }
  1145.     else {
  1146.         currentLevel--;
  1147.         if ( !currentLevel ) {
  1148.             Off();
  1149.         }
  1150.         else {
  1151.             SetLightLevel();
  1152.         }
  1153.     }
  1154. // RAVEN BEGIN
  1155. // abahr:
  1156.     }
  1157. // RAVEN END
  1158. }
  1159.  
  1160. // RAVEN BEGIN
  1161. // abahr:
  1162. /*
  1163. ================
  1164. idSound::Event_Timer
  1165. ================
  1166. */
  1167. void idLight::Event_Timer( void ) {
  1168. // FIXME: think about putting this logic in helper function so we don't have cut and pasted code
  1169.     if ( !currentLevel ) {
  1170.         On();
  1171.     }
  1172.     else {
  1173.         currentLevel--;
  1174.         if ( !currentLevel ) {
  1175.             Off();
  1176.         }
  1177.         else {
  1178.             SetLightLevel();
  1179.         }
  1180.     }
  1181.  
  1182.     PostEventSec( &EV_Light_Timer, wait + gameLocal.random.CRandomFloat() * random );
  1183. }
  1184.  
  1185. /*
  1186. ================
  1187. idLight::Event_SetSoundHandles
  1188.  
  1189.   set the same sound def handle on all targeted lights
  1190. ================
  1191. */
  1192. void idLight::Event_SetSoundHandles( void ) {
  1193.     int i;
  1194.     idEntity *targetEnt;
  1195.  
  1196.     if ( !soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle ) ) {
  1197.         return;
  1198.     }
  1199.  
  1200.     for ( i = 0; i < targets.Num(); i++ ) {
  1201.         targetEnt = targets[ i ].GetEntity();
  1202.         if ( targetEnt && targetEnt->IsType( idLight::Type ) ) {
  1203.             idLight    *light = static_cast<idLight*>(targetEnt);
  1204.             light->lightParent = this;
  1205.  
  1206.             // explicitly delete any sounds on the entity
  1207.             light->FreeSoundEmitter( true );
  1208.  
  1209.             // manually set the refSound to this light's refSound
  1210.             light->renderEntity.referenceSoundHandle = renderEntity.referenceSoundHandle;
  1211.  
  1212.             // update the renderEntity to the renderer
  1213.             light->UpdateVisuals();
  1214.         }
  1215. // RAVEN BEGIN
  1216. // rjohnson: func_static's can now have their color parms affected by lights
  1217.         else if ( targetEnt && targetEnt->IsType( idStaticEntity::GetClassType() ) ) {
  1218.             targetEnt->GetRenderEntity()->referenceShader = renderLight.shader;
  1219.             targetEnt->GetRenderEntity()->referenceSoundHandle = renderEntity.referenceSoundHandle;
  1220.         }
  1221. // RAVEN END
  1222.     }    
  1223. }
  1224.  
  1225. /*
  1226. ================
  1227. idLight::Event_FadeOut
  1228. ================
  1229. */
  1230. void idLight::Event_FadeOut( float time ) {
  1231.     FadeOut( time );
  1232. }
  1233.  
  1234. /*
  1235. ================
  1236. idLight::Event_FadeIn
  1237. ================
  1238. */
  1239. void idLight::Event_FadeIn( float time ) {
  1240.     FadeIn( time );
  1241. }
  1242.  
  1243. /*
  1244. ================
  1245. idLight::ClientPredictionThink
  1246. ================
  1247. */
  1248. void idLight::ClientPredictionThink( void ) {
  1249.     Think();
  1250. }
  1251.  
  1252. /*
  1253. ================
  1254. idLight::WriteToSnapshot
  1255. ================
  1256. */
  1257. void idLight::WriteToSnapshot( idBitMsgDelta &msg ) const {
  1258.  
  1259.     GetPhysics()->WriteToSnapshot( msg );
  1260.     WriteBindToSnapshot( msg );
  1261.  
  1262.     msg.WriteByte( currentLevel );
  1263.     msg.WriteLong( PackColor( baseColor ) );
  1264.     // msg.WriteBits( lightParent.GetEntityNum(), GENTITYNUM_BITS );
  1265.  
  1266. /*    // only helps prediction
  1267.     msg.WriteLong( PackColor( fadeFrom ) );
  1268.     msg.WriteLong( PackColor( fadeTo ) );
  1269.     msg.WriteLong( fadeStart );
  1270.     msg.WriteLong( fadeEnd );
  1271. */
  1272.  
  1273.     // FIXME: send renderLight.shader
  1274.     msg.WriteFloat( renderLight.lightRadius[0], 5, 10 );
  1275.     msg.WriteFloat( renderLight.lightRadius[1], 5, 10 );
  1276.     msg.WriteFloat( renderLight.lightRadius[2], 5, 10 );
  1277.  
  1278.     msg.WriteLong( PackColor( idVec4( renderLight.shaderParms[SHADERPARM_RED],
  1279.                                       renderLight.shaderParms[SHADERPARM_GREEN],
  1280.                                       renderLight.shaderParms[SHADERPARM_BLUE],
  1281.                                       renderLight.shaderParms[SHADERPARM_ALPHA] ) ) );
  1282.  
  1283.     msg.WriteFloat( renderLight.shaderParms[SHADERPARM_TIMESCALE], 5, 10 );
  1284.     msg.WriteLong( renderLight.shaderParms[SHADERPARM_TIMEOFFSET] );
  1285.     //msg.WriteByte( renderLight.shaderParms[SHADERPARM_DIVERSITY] );
  1286.     msg.WriteShort( renderLight.shaderParms[SHADERPARM_MODE] );
  1287.  
  1288.     WriteColorToSnapshot( msg );
  1289. }
  1290.  
  1291. /*
  1292. ================
  1293. idLight::ReadFromSnapshot
  1294. ================
  1295. */
  1296. void idLight::ReadFromSnapshot( const idBitMsgDelta &msg ) {
  1297.     idVec4    shaderColor;
  1298.     int        oldCurrentLevel = currentLevel;
  1299.     idVec3    oldBaseColor = baseColor;
  1300.  
  1301.     GetPhysics()->ReadFromSnapshot( msg );
  1302.     ReadBindFromSnapshot( msg );
  1303.  
  1304.     currentLevel = msg.ReadByte();
  1305.     if ( currentLevel != oldCurrentLevel ) {
  1306.         // need to call On/Off for flickering lights to start/stop the sound
  1307.         // while doing it this way rather than through events, the flickering is out of sync between clients
  1308.         // but at least there is no question about saving the event and having them happening globally in the world
  1309.         if ( currentLevel ) {
  1310.             On();
  1311.         } else {
  1312.             Off();
  1313.         }
  1314.     }
  1315.     UnpackColor( msg.ReadLong(), baseColor );
  1316.     // lightParentEntityNum = msg.ReadBits( GENTITYNUM_BITS );    
  1317.  
  1318. /*    // only helps prediction
  1319.     UnpackColor( msg.ReadLong(), fadeFrom );
  1320.     UnpackColor( msg.ReadLong(), fadeTo );
  1321.     fadeStart = msg.ReadLong();
  1322.     fadeEnd = msg.ReadLong();
  1323. */
  1324.  
  1325.     // FIXME: read renderLight.shader
  1326.     renderLight.lightRadius[0] = msg.ReadFloat( 5, 10 );
  1327.     renderLight.lightRadius[1] = msg.ReadFloat( 5, 10 );
  1328.     renderLight.lightRadius[2] = msg.ReadFloat( 5, 10 );
  1329.  
  1330.     UnpackColor( msg.ReadLong(), shaderColor );
  1331.     renderLight.shaderParms[SHADERPARM_RED] = shaderColor[0];
  1332.     renderLight.shaderParms[SHADERPARM_GREEN] = shaderColor[1];
  1333.     renderLight.shaderParms[SHADERPARM_BLUE] = shaderColor[2];
  1334.     renderLight.shaderParms[SHADERPARM_ALPHA] = shaderColor[3];
  1335.  
  1336.     renderLight.shaderParms[SHADERPARM_TIMESCALE] = msg.ReadFloat( 5, 10 );
  1337.     renderLight.shaderParms[SHADERPARM_TIMEOFFSET] = msg.ReadLong();
  1338.     //renderLight.shaderParms[SHADERPARM_DIVERSITY] = msg.ReadFloat();
  1339.     renderLight.shaderParms[SHADERPARM_MODE] = msg.ReadShort();
  1340.  
  1341.     ReadColorFromSnapshot( msg );
  1342.  
  1343.     if ( msg.HasChanged() ) {
  1344.         if ( ( currentLevel != oldCurrentLevel ) || ( baseColor != oldBaseColor ) ) {
  1345.             SetLightLevel();
  1346.         } else {
  1347.             PresentLightDefChange();
  1348.             PresentModelDefChange();
  1349.         }
  1350.     }
  1351. }
  1352.  
  1353. /*
  1354. ================
  1355. idLight::ClientReceiveEvent
  1356. ================
  1357. */
  1358. bool idLight::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
  1359.  
  1360.     switch( event ) {
  1361.         case EVENT_BECOMEBROKEN: {
  1362.             BecomeBroken( NULL );
  1363.             return true;
  1364.         }
  1365.         default: {
  1366.             return idEntity::ClientReceiveEvent( event, time, msg );
  1367.         }
  1368.     }
  1369. //unreachable
  1370. //    return false;
  1371. }
  1372.  
  1373. // RAVEN BEGIN
  1374. // kfuller: 8/11/03
  1375. void idLight::Event_IsOn()
  1376. {
  1377.     // not entirely sure this is the best way to check for offness
  1378.     if (currentLevel == 0)
  1379.     {
  1380.         idThread::ReturnFloat( false );
  1381.     }
  1382.     else
  1383.     {
  1384.         idThread::ReturnFloat( true );
  1385.     }
  1386. }
  1387.  
  1388. void idLight::Event_Break(idEntity *activator, float turnOff)
  1389. {
  1390.     BecomeBroken(activator);
  1391.     if (turnOff)
  1392.     {
  1393.         Off();
  1394.     }
  1395. }
  1396.  
  1397. void idLight::Event_DoneBlinking()
  1398. {
  1399.     // switch to a new (possibly non-blinking) shader for the light as well as a new looping sound
  1400.     idStr    blinkedOn;
  1401.     if (spawnArgs.GetString( "mtr_doneBlinking", "", blinkedOn ))
  1402.     {
  1403.         renderLight.shader = declManager->FindMaterial( blinkedOn, false );
  1404.         UpdateVisuals();
  1405.         Present();
  1406.     }
  1407.     idStr    doneBlinkingSound;
  1408.     if (spawnArgs.GetBool("doneBlinkingNoSound"))
  1409.     {
  1410.         StopSound( SCHANNEL_ANY, false );
  1411.     }
  1412.     else if (spawnArgs.GetString("snd_doneBlinking", "", doneBlinkingSound))
  1413.     {
  1414.         StopSound( SCHANNEL_ANY, false );
  1415.         if (doneBlinkingSound.Icmp("none"))
  1416.         {
  1417.             refSound.shader = declManager->FindSound(doneBlinkingSound);
  1418.             StartSoundShader( refSound.shader, SND_CHANNEL_ANY, 0, false, NULL );
  1419.             soundWasPlaying = false;
  1420.         }
  1421.     }
  1422. }
  1423.  
  1424. void idLight::Event_DoneBlinkingOff()
  1425. {
  1426.     // switch light and sound off
  1427.     currentLevel = 0;
  1428.     SetLightLevel();
  1429. // RAVEN BEGIN
  1430.     // kill any sound it was making
  1431.     idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  1432.     if ( emitter && emitter->CurrentlyPlaying ( ) ) {
  1433. // RAVEN END
  1434.         StopSound( SCHANNEL_ANY, false );
  1435.         soundWasPlaying = true;
  1436.     }
  1437. }
  1438.  
  1439. // kfuller: want fx entities to be able to respond to earthquakes
  1440. void idLight::Event_EarthQuake(float requiresLOS)
  1441. {
  1442.     // does this entity even care about earthquakes?
  1443.     float    quakeChance = 0;
  1444.  
  1445.     if (!spawnArgs.GetFloat("quakeChance", "0", quakeChance))
  1446.     {
  1447.         return;
  1448.     }
  1449.     if (rvRandom::flrand(0, 1.0f) > quakeChance)
  1450.     {
  1451.         // failed its activation roll
  1452.         return;
  1453.     }
  1454.  
  1455.     if (requiresLOS)
  1456.     {
  1457.         bool inPVS = gameLocal.InPlayerPVS( this );
  1458.  
  1459.         // for lights, a line-of-sight check doesn't make as much sense, so if the quake requires an LOS check
  1460.         //we'll actually perform a PVS check
  1461.         if (!inPVS)
  1462.         {
  1463.             return;
  1464.         }
  1465.     }
  1466.     // do something with this light
  1467.     if (spawnArgs.GetBool("quakeBreak"))
  1468.     {
  1469.         spawnArgs.SetBool("quakeBreak", false);
  1470.         BecomeBroken(gameLocal.entities[ENTITYNUM_WORLD]);
  1471.         return;
  1472.     }
  1473.  
  1474.     float    offTime = spawnArgs.GetFloat("quakeOffTime", "1.0");
  1475.     
  1476.     Off();
  1477.     PostEventMS(&EV_Light_On, offTime*1000.0f);
  1478. }
  1479.  
  1480. /*
  1481. ================
  1482. idLight::Event_SetLightGUI
  1483. ================
  1484. */
  1485. void idLight::Event_SetLightGUI ( const char* gui ) {
  1486.     lightGUI = gameLocal.FindEntity ( gui );
  1487.     if ( lightGUI && lightGUI->GetRenderEntity() && lightGUI->GetRenderEntity()->gui[0] ) {
  1488.         BecomeActive ( TH_THINK );
  1489.     } else {
  1490.         lightGUI = NULL;
  1491.     }
  1492. }
  1493.  
  1494. /*
  1495. ================
  1496. idLight::Event_SetCurrentLightLevel
  1497. ================
  1498. */
  1499. void idLight::Event_SetCurrentLightLevel( int in ) { 
  1500.     currentLevel = in;
  1501.     SetLightLevel ( );
  1502. }
  1503.  
  1504. /*
  1505. ================
  1506. idLight::Event_SetMaxLightLevel
  1507. ================
  1508. */
  1509. void idLight::Event_SetMaxLightLevel ( int in ) { 
  1510.     levels = in; 
  1511.     SetLightLevel ( );
  1512. }
  1513.  
  1514. // RAVEN END
  1515.