2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2024-05-16 19:00:44 +00:00
Copyright ( C ) 2021 Justin Marshall
Copyright ( C ) 2021 - 2024 Robert Beckebans
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-12-22 15:18:19 +00:00
# include "precompiled.h"
2012-11-26 18:58:24 +00:00
# pragma hdrstop
# include "Game_local.h"
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idLight
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
const idEventDef EV_Light_SetShader ( " setShader " , " s " ) ;
const idEventDef EV_Light_GetLightParm ( " getLightParm " , " d " , ' f ' ) ;
const idEventDef EV_Light_SetLightParm ( " setLightParm " , " df " ) ;
const idEventDef EV_Light_SetLightParms ( " setLightParms " , " ffff " ) ;
const idEventDef EV_Light_SetRadiusXYZ ( " setRadiusXYZ " , " fff " ) ;
const idEventDef EV_Light_SetRadius ( " setRadius " , " f " ) ;
const idEventDef EV_Light_On ( " On " , NULL ) ;
const idEventDef EV_Light_Off ( " Off " , NULL ) ;
const idEventDef EV_Light_FadeOut ( " fadeOutLight " , " f " ) ;
const idEventDef EV_Light_FadeIn ( " fadeInLight " , " f " ) ;
2024-05-16 19:00:44 +00:00
const idEventDef EV_Light_UpdateModelTarget ( " <updateModelTarget> " , NULL ) ; // RB
2012-11-26 18:58:24 +00:00
CLASS_DECLARATION ( idEntity , idLight )
2012-11-28 15:47:07 +00:00
EVENT ( EV_Light_SetShader , idLight : : Event_SetShader )
EVENT ( EV_Light_GetLightParm , idLight : : Event_GetLightParm )
EVENT ( EV_Light_SetLightParm , idLight : : Event_SetLightParm )
EVENT ( EV_Light_SetLightParms , idLight : : Event_SetLightParms )
EVENT ( EV_Light_SetRadiusXYZ , idLight : : Event_SetRadiusXYZ )
EVENT ( EV_Light_SetRadius , idLight : : Event_SetRadius )
EVENT ( EV_Hide , idLight : : Event_Hide )
EVENT ( EV_Show , idLight : : Event_Show )
EVENT ( EV_Light_On , idLight : : Event_On )
EVENT ( EV_Light_Off , idLight : : Event_Off )
EVENT ( EV_Activate , idLight : : Event_ToggleOnOff )
EVENT ( EV_PostSpawn , idLight : : Event_SetSoundHandles )
EVENT ( EV_Light_FadeOut , idLight : : Event_FadeOut )
EVENT ( EV_Light_FadeIn , idLight : : Event_FadeIn )
2024-05-16 19:00:44 +00:00
EVENT ( EV_Light_FadeIn , idLight : : Event_FadeIn )
EVENT ( EV_Light_UpdateModelTarget , idLight : : Event_UpdateModelTarget )
2012-11-26 18:58:24 +00:00
END_CLASS
/*
= = = = = = = = = = = = = = = =
idGameEdit : : ParseSpawnArgsToRenderLight
parse the light parameters
this is the canonical renderLight parm parsing ,
which should be used by dmap and the editor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameEdit : : ParseSpawnArgsToRenderLight ( const idDict * args , renderLight_t * renderLight )
{
2012-11-26 18:58:24 +00:00
bool gotTarget , gotUp , gotRight ;
2012-11-28 15:47:07 +00:00
const char * texture ;
2012-11-26 18:58:24 +00:00
idVec3 color ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
memset ( renderLight , 0 , sizeof ( * renderLight ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! args - > GetVector ( " light_origin " , " " , renderLight - > origin ) )
{
2012-11-26 18:58:24 +00:00
args - > GetVector ( " origin " , " " , renderLight - > origin ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
gotTarget = args - > GetVector ( " light_target " , " " , renderLight - > target ) ;
gotUp = args - > GetVector ( " light_up " , " " , renderLight - > up ) ;
gotRight = args - > GetVector ( " light_right " , " " , renderLight - > right ) ;
args - > GetVector ( " light_start " , " 0 0 0 " , renderLight - > start ) ;
2012-11-28 15:47:07 +00:00
if ( ! args - > GetVector ( " light_end " , " " , renderLight - > end ) )
{
2012-11-26 18:58:24 +00:00
renderLight - > end = renderLight - > target ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// we should have all of the target/right/up or none of them
2012-11-28 15:47:07 +00:00
if ( ( gotTarget | | gotUp | | gotRight ) ! = ( gotTarget & & gotUp & & gotRight ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Printf ( " Light at (%f,%f,%f) has bad target info \n " ,
2012-11-28 15:47:07 +00:00
renderLight - > origin [ 0 ] , renderLight - > origin [ 1 ] , renderLight - > origin [ 2 ] ) ;
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! gotTarget )
{
2012-11-26 18:58:24 +00:00
renderLight - > pointLight = true ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// allow an optional relative center of light and shadow offset
args - > GetVector ( " light_center " , " 0 0 0 " , renderLight - > lightCenter ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// create a point light
2012-11-28 15:47:07 +00:00
if ( ! args - > GetVector ( " light_radius " , " 300 300 300 " , renderLight - > lightRadius ) )
{
2012-11-26 18:58:24 +00:00
float radius ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
args - > GetFloat ( " light " , " 300 " , radius ) ;
renderLight - > lightRadius [ 0 ] = renderLight - > lightRadius [ 1 ] = renderLight - > lightRadius [ 2 ] = radius ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// get the rotation matrix in either full form, or single angle form
idAngles angles ;
idMat3 mat ;
2012-11-28 15:47:07 +00:00
if ( ! args - > GetMatrix ( " light_rotation " , " 1 0 0 0 1 0 0 0 1 " , mat ) )
{
if ( ! args - > GetMatrix ( " rotation " , " 1 0 0 0 1 0 0 0 1 " , mat ) )
{
2023-12-04 19:15:34 +00:00
// RB: light_angles is specific for lights that have been modified by the editLights command
// these lights have a static model and are not proper grouped using func_group
if ( args - > GetAngles ( " light_angles " , " 0 0 0 " , angles ) )
{
angles [ 0 ] = idMath : : AngleNormalize360 ( angles [ 0 ] ) ;
angles [ 1 ] = idMath : : AngleNormalize360 ( angles [ 1 ] ) ;
angles [ 2 ] = idMath : : AngleNormalize360 ( angles [ 2 ] ) ;
mat = angles . ToMat3 ( ) ;
}
2021-05-09 19:25:25 +00:00
// RB: TrenchBroom interop
// support "angles" like in Quake 3
2023-12-04 19:15:34 +00:00
else if ( args - > GetAngles ( " angles " , " 0 0 0 " , angles ) )
2021-05-09 19:25:25 +00:00
{
angles [ 0 ] = idMath : : AngleNormalize360 ( angles [ 0 ] ) ;
angles [ 1 ] = idMath : : AngleNormalize360 ( angles [ 1 ] ) ;
angles [ 2 ] = idMath : : AngleNormalize360 ( angles [ 2 ] ) ;
mat = angles . ToMat3 ( ) ;
}
else
{
args - > GetFloat ( " angle " , " 0 " , angles [ 1 ] ) ;
angles [ 0 ] = 0 ;
angles [ 1 ] = idMath : : AngleNormalize360 ( angles [ 1 ] ) ;
angles [ 2 ] = 0 ;
mat = angles . ToMat3 ( ) ;
}
2012-11-26 18:58:24 +00:00
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// fix degenerate identity matrices
mat [ 0 ] . FixDegenerateNormal ( ) ;
mat [ 1 ] . FixDegenerateNormal ( ) ;
mat [ 2 ] . FixDegenerateNormal ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
renderLight - > axis = mat ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// check for other attributes
args - > GetVector ( " _color " , " 1 1 1 " , color ) ;
renderLight - > shaderParms [ SHADERPARM_RED ] = color [ 0 ] ;
renderLight - > shaderParms [ SHADERPARM_GREEN ] = color [ 1 ] ;
renderLight - > shaderParms [ SHADERPARM_BLUE ] = color [ 2 ] ;
args - > GetFloat ( " shaderParm3 " , " 1 " , renderLight - > shaderParms [ SHADERPARM_TIMESCALE ] ) ;
2012-11-28 15:47:07 +00:00
if ( ! args - > GetFloat ( " shaderParm4 " , " 0 " , renderLight - > shaderParms [ SHADERPARM_TIMEOFFSET ] ) )
{
2012-11-26 18:58:24 +00:00
// offset the start time of the shader to sync it to the game time
renderLight - > shaderParms [ SHADERPARM_TIMEOFFSET ] = - MS2SEC ( gameLocal . time ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
args - > GetFloat ( " shaderParm5 " , " 0 " , renderLight - > shaderParms [ 5 ] ) ;
args - > GetFloat ( " shaderParm6 " , " 0 " , renderLight - > shaderParms [ 6 ] ) ;
args - > GetFloat ( " shaderParm7 " , " 0 " , renderLight - > shaderParms [ SHADERPARM_MODE ] ) ;
args - > GetBool ( " noshadows " , " 0 " , renderLight - > noShadows ) ;
args - > GetBool ( " nospecular " , " 0 " , renderLight - > noSpecular ) ;
args - > GetBool ( " parallel " , " 0 " , renderLight - > parallel ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
args - > GetString ( " texture " , " lights/squarelight1 " , & texture ) ;
2021-02-20 15:24:45 +00:00
2012-11-26 18:58:24 +00:00
// allow this to be NULL
renderLight - > shader = declManager - > FindMaterial ( texture , false ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : UpdateChangeableSpawnArgs
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : UpdateChangeableSpawnArgs ( const idDict * source )
{
2021-02-20 15:24:45 +00:00
// jmarshall
lightStyleFrameTime = spawnArgs . GetInt ( " ls_frametime " , " 100 " ) ;
lightStyle = spawnArgs . GetInt ( " style " , - 1 ) ;
lightStyleState . Reset ( ) ;
// jmarshall end
2012-11-26 18:58:24 +00:00
idEntity : : UpdateChangeableSpawnArgs ( source ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( source )
{
2012-11-26 18:58:24 +00:00
source - > Print ( ) ;
}
FreeSoundEmitter ( true ) ;
gameEdit - > ParseSpawnArgsToRefSound ( source ? source : & spawnArgs , & refSound ) ;
2012-11-28 15:47:07 +00:00
if ( refSound . shader & & ! refSound . waitfortrigger )
{
2012-11-26 18:58:24 +00:00
StartSoundShader ( refSound . shader , SND_CHANNEL_ANY , 0 , false , NULL ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
gameEdit - > ParseSpawnArgsToRenderLight ( source ? source : & spawnArgs , & renderLight ) ;
2019-11-11 19:27:44 +00:00
2023-03-07 17:26:43 +00:00
// RB: allow the ingame light editor to move the light
GetPhysics ( ) - > SetOrigin ( renderLight . origin ) ;
GetPhysics ( ) - > SetAxis ( renderLight . axis ) ;
2024-05-16 19:00:44 +00:00
// link func_static modelTarget
modelTarget = NULL ;
const char * target = source - > GetString ( " modelTarget " ) ;
if ( target ! = NULL & & target [ 0 ] ! = ' \0 ' )
{
PostEventMS ( & EV_Light_UpdateModelTarget , 0 ) ;
}
2023-03-07 17:26:43 +00:00
// RB end
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : idLight
= = = = = = = = = = = = = = = =
*/
idLight : : idLight ( ) :
previousBaseColor ( vec3_zero ) ,
2012-11-28 15:47:07 +00:00
nextBaseColor ( vec3_zero )
{
2012-11-26 18:58:24 +00:00
memset ( & renderLight , 0 , sizeof ( renderLight ) ) ;
localLightOrigin = vec3_zero ;
localLightAxis = mat3_identity ;
lightDefHandle = - 1 ;
levels = 0 ;
currentLevel = 0 ;
baseColor = vec3_zero ;
breakOnTrigger = false ;
count = 0 ;
triggercount = 0 ;
lightParent = NULL ;
fadeFrom . Set ( 1 , 1 , 1 , 1 ) ;
fadeTo . Set ( 1 , 1 , 1 , 1 ) ;
fadeStart = 0 ;
fadeEnd = 0 ;
soundWasPlaying = false ;
2021-03-01 07:10:52 +00:00
// RB begin
lightStyle = - 1 ;
lightStyleFrameTime = 100 ;
lightStyleBase . Set ( 300 , 300 , 300 ) ;
lightStyleState . Reset ( ) ;
// RB end
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idLight : : ~ idLight
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idLight : : ~ idLight ( )
{
if ( lightDefHandle ! = - 1 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > FreeLightDef ( lightDefHandle ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idLight : : Save
archives object for save game file
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Save ( idSaveGame * savefile ) const
{
2012-11-26 18:58:24 +00:00
savefile - > WriteRenderLight ( renderLight ) ;
2019-11-11 19:27:44 +00:00
2024-05-13 21:11:02 +00:00
// RB keep it for savegame compatibility but we have no support for dmap generated shadow models
savefile - > WriteBool ( false ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteVec3 ( localLightOrigin ) ;
savefile - > WriteMat3 ( localLightAxis ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteString ( brokenModel ) ;
savefile - > WriteInt ( levels ) ;
savefile - > WriteInt ( currentLevel ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteVec3 ( baseColor ) ;
savefile - > WriteBool ( breakOnTrigger ) ;
savefile - > WriteInt ( count ) ;
savefile - > WriteInt ( triggercount ) ;
savefile - > WriteObject ( lightParent ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteVec4 ( fadeFrom ) ;
savefile - > WriteVec4 ( fadeTo ) ;
savefile - > WriteInt ( fadeStart ) ;
savefile - > WriteInt ( fadeEnd ) ;
savefile - > WriteBool ( soundWasPlaying ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Restore
unarchives object from save game file
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Restore ( idRestoreGame * savefile )
{
2012-11-26 18:58:24 +00:00
bool hadPrelightModel ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadRenderLight ( renderLight ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( hadPrelightModel ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadVec3 ( localLightOrigin ) ;
savefile - > ReadMat3 ( localLightAxis ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadString ( brokenModel ) ;
savefile - > ReadInt ( levels ) ;
savefile - > ReadInt ( currentLevel ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadVec3 ( baseColor ) ;
savefile - > ReadBool ( breakOnTrigger ) ;
savefile - > ReadInt ( count ) ;
savefile - > ReadInt ( triggercount ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( lightParent ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadVec4 ( fadeFrom ) ;
savefile - > ReadVec4 ( fadeTo ) ;
savefile - > ReadInt ( fadeStart ) ;
savefile - > ReadInt ( fadeEnd ) ;
savefile - > ReadBool ( soundWasPlaying ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
lightDefHandle = - 1 ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
SetLightLevel ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Spawn
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Spawn ( )
{
2012-11-26 18:58:24 +00:00
bool start_off ;
bool needBroken ;
2012-11-28 15:47:07 +00:00
const char * demonic_shader ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// do the parsing the same way dmap and the editor do
gameEdit - > ParseSpawnArgsToRenderLight ( & spawnArgs , & renderLight ) ;
2021-02-20 15:24:45 +00:00
// jmarshall: Store the original light radius for the light style.
lightStyleBase = renderLight . lightRadius ;
// jmarshall end
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// we need the origin and axis relative to the physics origin/axis
localLightOrigin = ( renderLight . origin - GetPhysics ( ) - > GetOrigin ( ) ) * GetPhysics ( ) - > GetAxis ( ) . Transpose ( ) ;
localLightAxis = renderLight . axis * GetPhysics ( ) - > GetAxis ( ) . Transpose ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// set the base color from the shader parms
baseColor . Set ( renderLight . shaderParms [ SHADERPARM_RED ] , renderLight . shaderParms [ SHADERPARM_GREEN ] , renderLight . shaderParms [ SHADERPARM_BLUE ] ) ;
2012-11-28 15:47:07 +00:00
previousBaseColor . Set ( renderLight . shaderParms [ SHADERPARM_RED ] , renderLight . shaderParms [ SHADERPARM_GREEN ] , renderLight . shaderParms [ SHADERPARM_BLUE ] ) ;
nextBaseColor . Set ( renderLight . shaderParms [ SHADERPARM_RED ] , renderLight . shaderParms [ SHADERPARM_GREEN ] , renderLight . shaderParms [ SHADERPARM_BLUE ] ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// set the number of light levels
spawnArgs . GetInt ( " levels " , " 1 " , levels ) ;
currentLevel = levels ;
2012-11-28 15:47:07 +00:00
if ( levels < = 0 )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Invalid light level set on entity #%d(%s) " , entityNumber , name . c_str ( ) ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// make sure the demonic shader is cached
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " mat_demonic " , NULL , & demonic_shader ) )
{
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_MATERIAL , demonic_shader ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// game specific functionality, not mirrored in
// editor or dmap light parsing
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// also put the light texture on the model, so light flares
// can get the current intensity of the light
renderEntity . referenceShader = renderLight . shader ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
lightDefHandle = - 1 ; // no static version yet
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
spawnArgs . GetBool ( " start_off " , " 0 " , start_off ) ;
2012-11-28 15:47:07 +00:00
if ( start_off )
{
2012-11-26 18:58:24 +00:00
Off ( ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// Midnight CTF
if ( gameLocal . mpGame . IsGametypeFlagBased ( ) & & gameLocal . serverInfo . GetBool ( " si_midnight " ) & & ! spawnArgs . GetBool ( " midnight_override " ) )
{
Off ( ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
health = spawnArgs . GetInt ( " health " , " 0 " ) ;
spawnArgs . GetString ( " broken " , " " , brokenModel ) ;
spawnArgs . GetBool ( " break " , " 0 " , breakOnTrigger ) ;
spawnArgs . GetInt ( " count " , " 1 " , count ) ;
2019-11-11 19:27:44 +00:00
2021-02-20 15:24:45 +00:00
// jmarshall
lightStyleFrameTime = spawnArgs . GetInt ( " ls_frametime " , " 100 " ) ;
lightStyle = spawnArgs . GetInt ( " style " , - 1 ) ;
int numStyles = spawnArgs . GetInt ( " num_styles " , " 0 " ) ;
if ( numStyles > 0 )
{
for ( int i = 0 ; i < numStyles ; i + + )
{
idStr style = spawnArgs . GetString ( va ( " light_style%d " , i ) ) ;
light_styles . Append ( style ) ;
}
}
else
{
// RB: it's not defined in entityDef light so use predefined Quake 1 table
for ( int i = 0 ; i < 12 ; i + + )
{
idStr style = spawnArgs . GetString ( va ( " light_style%d " , i ) , predef_lightstyles [ i ] ) ;
light_styles . Append ( style ) ;
}
}
// jmarshall end
2012-11-26 18:58:24 +00:00
triggercount = 0 ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
fadeFrom . Set ( 1 , 1 , 1 , 1 ) ;
fadeTo . Set ( 1 , 1 , 1 , 1 ) ;
fadeStart = 0 ;
fadeEnd = 0 ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// if we have a health make light breakable
2012-11-28 15:47:07 +00:00
if ( health )
{
2012-11-26 18:58:24 +00:00
idStr model = spawnArgs . GetString ( " model " ) ; // get the visual model
2012-11-28 15:47:07 +00:00
if ( ! model . Length ( ) )
{
2024-05-16 19:00:44 +00:00
model = spawnArgs . GetString ( " modelTarget " ) ;
if ( ! model . Length ( ) )
{
gameLocal . Error ( " Breakable light without a model set on entity #%d(%s) " , entityNumber , name . c_str ( ) ) ;
}
2012-11-26 18:58:24 +00:00
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
fl . takedamage = true ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// see if we need to create a broken model name
needBroken = true ;
2012-11-28 15:47:07 +00:00
if ( model . Length ( ) & & ! brokenModel . Length ( ) )
{
2012-11-26 18:58:24 +00:00
int pos ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
needBroken = false ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
pos = model . Find ( " . " ) ;
2012-11-28 15:47:07 +00:00
if ( pos < 0 )
{
2012-11-26 18:58:24 +00:00
pos = model . Length ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( pos > 0 )
{
2012-11-26 18:58:24 +00:00
model . Left ( pos , brokenModel ) ;
}
brokenModel + = " _broken " ;
2012-11-28 15:47:07 +00:00
if ( pos > 0 )
{
2012-11-26 18:58:24 +00:00
brokenModel + = & model [ pos ] ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// make sure the model gets cached
2012-11-28 15:47:07 +00:00
if ( ! renderModelManager - > CheckModel ( brokenModel ) )
{
if ( needBroken )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Model '%s' not found for entity %d(%s) " , brokenModel . c_str ( ) , entityNumber , name . c_str ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
brokenModel = " " ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > SetContents ( spawnArgs . GetBool ( " nonsolid " ) ? 0 : CONTENTS_SOLID ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// make sure the collision model gets cached
idClipModel : : CheckModel ( brokenModel ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
PostEventMS ( & EV_PostSpawn , 0 ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : SetLightLevel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : SetLightLevel ( )
{
2012-11-26 18:58:24 +00:00
idVec3 color ;
float intensity ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
intensity = ( float ) currentLevel / ( float ) levels ;
color = baseColor * intensity ;
renderLight . shaderParms [ SHADERPARM_RED ] = color [ 0 ] ;
renderLight . shaderParms [ SHADERPARM_GREEN ] = color [ 1 ] ;
renderLight . shaderParms [ SHADERPARM_BLUE ] = color [ 2 ] ;
2024-05-16 19:00:44 +00:00
if ( modelTarget )
{
renderEntity_t * rent = modelTarget - > GetRenderEntity ( ) ;
rent - > shaderParms [ SHADERPARM_RED ] = color [ 0 ] ;
rent - > shaderParms [ SHADERPARM_GREEN ] = color [ 1 ] ;
rent - > shaderParms [ SHADERPARM_BLUE ] = color [ 2 ] ;
}
else
{
renderEntity . shaderParms [ SHADERPARM_RED ] = color [ 0 ] ;
renderEntity . shaderParms [ SHADERPARM_GREEN ] = color [ 1 ] ;
renderEntity . shaderParms [ SHADERPARM_BLUE ] = color [ 2 ] ;
}
2012-11-26 18:58:24 +00:00
PresentLightDefChange ( ) ;
PresentModelDefChange ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : GetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : GetColor ( idVec3 & out ) const
{
2012-11-26 18:58:24 +00:00
out [ 0 ] = renderLight . shaderParms [ SHADERPARM_RED ] ;
out [ 1 ] = renderLight . shaderParms [ SHADERPARM_GREEN ] ;
out [ 2 ] = renderLight . shaderParms [ SHADERPARM_BLUE ] ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : GetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : GetColor ( idVec4 & out ) const
{
2012-11-26 18:58:24 +00:00
out [ 0 ] = renderLight . shaderParms [ SHADERPARM_RED ] ;
out [ 1 ] = renderLight . shaderParms [ SHADERPARM_GREEN ] ;
out [ 2 ] = renderLight . shaderParms [ SHADERPARM_BLUE ] ;
out [ 3 ] = renderLight . shaderParms [ SHADERPARM_ALPHA ] ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : SetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : SetColor ( float red , float green , float blue )
{
2012-11-26 18:58:24 +00:00
baseColor . Set ( red , green , blue ) ;
SetLightLevel ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : SetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : SetColor ( const idVec4 & color )
{
2012-11-26 18:58:24 +00:00
baseColor = color . ToVec3 ( ) ;
renderLight . shaderParms [ SHADERPARM_ALPHA ] = color [ 3 ] ;
renderEntity . shaderParms [ SHADERPARM_ALPHA ] = color [ 3 ] ;
SetLightLevel ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : SetColor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : SetColor ( const idVec3 & color )
{
2012-11-26 18:58:24 +00:00
baseColor = color ;
SetLightLevel ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : SetShader
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : SetShader ( const char * shadername )
{
2012-11-26 18:58:24 +00:00
// allow this to be NULL
renderLight . shader = declManager - > FindMaterial ( shadername , false ) ;
PresentLightDefChange ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : SetLightParm
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : SetLightParm ( int parmnum , float value )
{
if ( ( parmnum < 0 ) | | ( parmnum > = MAX_ENTITY_SHADER_PARMS ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " shader parm index (%d) out of range " , parmnum ) ;
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
renderLight . shaderParms [ parmnum ] = value ;
PresentLightDefChange ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : SetLightParms
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : SetLightParms ( float parm0 , float parm1 , float parm2 , float parm3 )
{
2012-11-26 18:58:24 +00:00
renderLight . shaderParms [ SHADERPARM_RED ] = parm0 ;
renderLight . shaderParms [ SHADERPARM_GREEN ] = parm1 ;
renderLight . shaderParms [ SHADERPARM_BLUE ] = parm2 ;
renderLight . shaderParms [ SHADERPARM_ALPHA ] = parm3 ;
2024-05-16 19:00:44 +00:00
if ( modelTarget )
{
renderEntity_t * rent = modelTarget - > GetRenderEntity ( ) ;
rent - > shaderParms [ SHADERPARM_RED ] = parm0 ;
rent - > shaderParms [ SHADERPARM_GREEN ] = parm1 ;
rent - > shaderParms [ SHADERPARM_BLUE ] = parm2 ;
rent - > shaderParms [ SHADERPARM_ALPHA ] = parm3 ;
}
else
{
renderEntity . shaderParms [ SHADERPARM_RED ] = parm0 ;
renderEntity . shaderParms [ SHADERPARM_GREEN ] = parm1 ;
renderEntity . shaderParms [ SHADERPARM_BLUE ] = parm2 ;
renderEntity . shaderParms [ SHADERPARM_ALPHA ] = parm3 ;
}
2012-11-26 18:58:24 +00:00
PresentLightDefChange ( ) ;
PresentModelDefChange ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : SetRadiusXYZ
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : SetRadiusXYZ ( float x , float y , float z )
{
2012-11-26 18:58:24 +00:00
renderLight . lightRadius [ 0 ] = x ;
renderLight . lightRadius [ 1 ] = y ;
renderLight . lightRadius [ 2 ] = z ;
PresentLightDefChange ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : SetRadius
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : SetRadius ( float radius )
{
2012-11-26 18:58:24 +00:00
renderLight . lightRadius [ 0 ] = renderLight . lightRadius [ 1 ] = renderLight . lightRadius [ 2 ] = radius ;
PresentLightDefChange ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : On
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : On ( )
{
2012-11-26 18:58:24 +00:00
currentLevel = levels ;
2024-05-16 19:00:44 +00:00
2012-11-26 18:58:24 +00:00
// offset the start time of the shader to sync it to the game time
renderLight . shaderParms [ SHADERPARM_TIMEOFFSET ] = - MS2SEC ( gameLocal . time ) ;
2012-11-28 15:47:07 +00:00
if ( ( soundWasPlaying | | refSound . waitfortrigger ) & & refSound . shader )
{
2012-11-26 18:58:24 +00:00
StartSoundShader ( refSound . shader , SND_CHANNEL_ANY , 0 , false , NULL ) ;
soundWasPlaying = false ;
}
SetLightLevel ( ) ;
BecomeActive ( TH_UPDATEVISUALS ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Off
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Off ( )
{
2012-11-26 18:58:24 +00:00
currentLevel = 0 ;
2024-05-16 19:00:44 +00:00
2012-11-26 18:58:24 +00:00
// kill any sound it was making
2012-11-28 15:47:07 +00:00
if ( refSound . referenceSound & & refSound . referenceSound - > CurrentlyPlaying ( ) )
{
2012-11-26 18:58:24 +00:00
StopSound ( SND_CHANNEL_ANY , false ) ;
soundWasPlaying = true ;
}
SetLightLevel ( ) ;
BecomeActive ( TH_UPDATEVISUALS ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Fade
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Fade ( const idVec4 & to , float fadeTime )
{
2012-11-26 18:58:24 +00:00
GetColor ( fadeFrom ) ;
fadeTo = to ;
fadeStart = gameLocal . time ;
fadeEnd = gameLocal . time + SEC2MS ( fadeTime ) ;
BecomeActive ( TH_THINK ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : FadeOut
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : FadeOut ( float time )
{
2012-11-26 18:58:24 +00:00
Fade ( colorBlack , time ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : FadeIn
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : FadeIn ( float time )
{
2012-11-26 18:58:24 +00:00
idVec3 color ;
idVec4 color4 ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
currentLevel = levels ;
spawnArgs . GetVector ( " _color " , " 1 1 1 " , color ) ;
color4 . Set ( color . x , color . y , color . z , 1.0f ) ;
Fade ( color4 , time ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Killed
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Killed ( idEntity * inflictor , idEntity * attacker , int damage , const idVec3 & dir , int location )
{
2012-11-26 18:58:24 +00:00
BecomeBroken ( attacker ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : BecomeBroken
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : BecomeBroken ( idEntity * activator )
{
const char * damageDefName ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
fl . takedamage = false ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( brokenModel . Length ( ) )
{
2012-11-26 18:58:24 +00:00
SetModel ( brokenModel ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! spawnArgs . GetBool ( " nonsolid " ) )
{
GetPhysics ( ) - > SetClipModel ( new ( TAG_PHYSICS_CLIP_ENTITY ) idClipModel ( brokenModel . c_str ( ) ) , 1.0f ) ;
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > SetContents ( CONTENTS_SOLID ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( spawnArgs . GetBool ( " hideModelOnBreak " ) )
{
2012-11-26 18:58:24 +00:00
SetModel ( " " ) ;
GetPhysics ( ) - > SetContents ( 0 ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( common - > IsServer ( ) )
{
2012-11-26 18:58:24 +00:00
ServerSendEvent ( EVENT_BECOMEBROKEN , NULL , true ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " def_damage " , " " , & damageDefName ) )
{
2012-11-26 18:58:24 +00:00
idVec3 origin = renderEntity . origin + renderEntity . bounds . GetCenter ( ) * renderEntity . axis ;
gameLocal . RadiusDamage ( origin , activator , activator , this , this , damageDefName ) ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
ActivateTargets ( activator ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// offset the start time of the shader to sync it to the game time
renderEntity . shaderParms [ SHADERPARM_TIMEOFFSET ] = - MS2SEC ( gameLocal . time ) ;
renderLight . shaderParms [ SHADERPARM_TIMEOFFSET ] = - MS2SEC ( gameLocal . time ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// set the state parm
renderEntity . shaderParms [ SHADERPARM_MODE ] = 1 ;
renderLight . shaderParms [ SHADERPARM_MODE ] = 1 ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// if the light has a sound, either start the alternate (broken) sound, or stop the sound
2012-11-28 15:47:07 +00:00
const char * parm = spawnArgs . GetString ( " snd_broken " ) ;
2012-12-11 22:48:55 +00:00
if ( refSound . shader | | ( parm ! = NULL & & * parm ! = ' \0 ' ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
StopSound ( SND_CHANNEL_ANY , false ) ;
2012-11-28 15:47:07 +00:00
const idSoundShader * alternate = refSound . shader ? refSound . shader - > GetAltSound ( ) : declManager - > FindSound ( parm ) ;
if ( alternate )
{
2012-11-26 18:58:24 +00:00
// start it with no diversity, so the leadin break sound plays
refSound . referenceSound - > StartSound ( alternate , SND_CHANNEL_ANY , 0.0 , 0 ) ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
parm = spawnArgs . GetString ( " mtr_broken " ) ;
2012-12-11 22:48:55 +00:00
if ( parm ! = NULL & & * parm ! = ' \0 ' )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
SetShader ( parm ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : PresentLightDefChange
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : PresentLightDefChange ( )
{
2012-11-26 18:58:24 +00:00
// let the renderer apply it to the world
2012-11-28 15:47:07 +00:00
if ( ( lightDefHandle ! = - 1 ) )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > UpdateLightDef ( lightDefHandle , & renderLight ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
lightDefHandle = gameRenderWorld - > AddLightDef ( & renderLight ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idLight : : PresentModelDefChange
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : PresentModelDefChange ( )
{
2024-05-16 19:00:44 +00:00
if ( modelTarget )
{
modelTarget - > BecomeActive ( TH_UPDATEVISUALS ) ;
modelTarget - > Present ( ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! renderEntity . hModel | | IsHidden ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// add to refresh list
2012-11-28 15:47:07 +00:00
if ( modelDefHandle = = - 1 )
{
2012-11-26 18:58:24 +00:00
modelDefHandle = gameRenderWorld - > AddEntityDef ( & renderEntity ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > UpdateEntityDef ( modelDefHandle , & renderEntity ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idLight : : Present
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Present ( )
{
2012-11-26 18:58:24 +00:00
// don't present to the renderer if the entity hasn't changed
2012-11-28 15:47:07 +00:00
if ( ! ( thinkFlags & TH_UPDATEVISUALS ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// add the model
idEntity : : Present ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// current transformation
renderLight . axis = localLightAxis * GetPhysics ( ) - > GetAxis ( ) ;
renderLight . origin = GetPhysics ( ) - > GetOrigin ( ) + GetPhysics ( ) - > GetAxis ( ) * localLightOrigin ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// reference the sound for shader synced effects
2012-11-28 15:47:07 +00:00
if ( lightParent )
{
2012-11-26 18:58:24 +00:00
renderLight . referenceSound = lightParent - > GetSoundEmitter ( ) ;
2024-05-16 19:00:44 +00:00
if ( modelTarget )
{
renderEntity_t * rent = modelTarget - > GetRenderEntity ( ) ;
rent - > referenceSound = lightParent - > GetSoundEmitter ( ) ;
}
else
{
renderEntity . referenceSound = lightParent - > GetSoundEmitter ( ) ;
}
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
renderLight . referenceSound = refSound . referenceSound ;
2024-05-16 19:00:44 +00:00
if ( modelTarget )
{
renderEntity_t * rent = modelTarget - > GetRenderEntity ( ) ;
rent - > referenceSound = refSound . referenceSound ;
}
else
{
renderEntity . referenceSound = refSound . referenceSound ;
}
2012-11-26 18:58:24 +00:00
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// update the renderLight and renderEntity to render the light and flare
PresentLightDefChange ( ) ;
PresentModelDefChange ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Think
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Think ( )
{
2012-11-26 18:58:24 +00:00
idVec4 color ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( thinkFlags & TH_THINK )
{
if ( fadeEnd > 0 )
{
if ( gameLocal . time < fadeEnd )
{
2012-11-26 18:58:24 +00:00
color . Lerp ( fadeFrom , fadeTo , ( float ) ( gameLocal . time - fadeStart ) / ( float ) ( fadeEnd - fadeStart ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
color = fadeTo ;
fadeEnd = 0 ;
BecomeInactive ( TH_THINK ) ;
}
SetColor ( color ) ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
RunPhysics ( ) ;
Present ( ) ;
}
2021-02-20 15:24:45 +00:00
/*
= = = = = = = = = = = = = = = =
idLight : : SharedThink
= = = = = = = = = = = = = = = =
*/
// jmarshall
void idLight : : SharedThink ( )
{
float lightval ;
int stringlength ;
float offset ;
int offsetwhole ;
int otime ;
int lastch , nextch ;
if ( lightStyle = = - 1 )
{
return ;
}
if ( lightStyle > light_styles . Num ( ) )
{
//gameLocal.Error( "Light style out of range\n" );
return ;
}
idStr dl_stylestring = light_styles [ lightStyle ] ;
otime = gameLocal . time - lightStyleState . dl_time ;
stringlength = dl_stylestring . Length ( ) ;
// it's been a long time since you were updated, lets assume a reset
if ( otime > 2 * lightStyleFrameTime )
{
otime = 0 ;
lightStyleState . dl_frame = lightStyleState . dl_oldframe = 0 ;
lightStyleState . dl_backlerp = 0 ;
}
lightStyleState . dl_time = gameLocal . time ;
offset = ( ( float ) otime ) / lightStyleFrameTime ;
offsetwhole = ( int ) offset ;
lightStyleState . dl_backlerp + = offset ;
if ( lightStyleState . dl_backlerp > 1 ) // we're moving on to the next frame
{
lightStyleState . dl_oldframe = lightStyleState . dl_oldframe + ( int ) lightStyleState . dl_backlerp ;
lightStyleState . dl_frame = lightStyleState . dl_oldframe + 1 ;
if ( lightStyleState . dl_oldframe > = stringlength )
{
lightStyleState . dl_oldframe = ( lightStyleState . dl_oldframe ) % stringlength ;
//if (cent->dl_oldframe < 3 && cent->dl_sound) { // < 3 so if an alarm comes back into the pvs it will only start a sound if it's going to be closely synced with the light, otherwise wait till the next cycle
// engine->S_StartSound(NULL, cent->currentState.number, CHAN_AUTO, cgs.gameSounds[cent->dl_sound]);
//}
}
if ( lightStyleState . dl_frame > = stringlength )
{
lightStyleState . dl_frame = ( lightStyleState . dl_frame ) % stringlength ;
}
lightStyleState . dl_backlerp = lightStyleState . dl_backlerp - ( int ) lightStyleState . dl_backlerp ;
}
lastch = dl_stylestring [ lightStyleState . dl_oldframe ] - ' a ' ;
nextch = dl_stylestring [ lightStyleState . dl_frame ] - ' a ' ;
lightval = ( lastch * ( 1.0 - lightStyleState . dl_backlerp ) ) + ( nextch * lightStyleState . dl_backlerp ) ;
// ydnar: dlight values go from 0-1.5ish
#if 0
lightval = ( lightval * ( 1000.0f / 24.0f ) ) - 200.0f ; // they want 'm' as the "middle" value as 300
lightval = max ( 0.0f , lightval ) ;
lightval = min ( 1000.0f , lightval ) ;
# else
lightval * = 0.071429f ;
lightval = Max ( 0.0f , lightval ) ;
lightval = Min ( 20.0f , lightval ) ;
# endif
renderLight . lightRadius . x = lightval * lightStyleBase . x ;
renderLight . lightRadius . y = lightval * lightStyleBase . y ;
renderLight . lightRadius . z = lightval * lightStyleBase . z ;
if ( ! common - > IsClient ( ) )
{
BecomeActive ( TH_THINK ) ;
}
PresentLightDefChange ( ) ;
}
// jmarshall end
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = =
idLight : : ClientThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : ClientThink ( const int curTime , const float fraction , const bool predict )
{
2012-11-26 18:58:24 +00:00
InterpolatePhysics ( fraction ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( baseColor ! = nextBaseColor )
{
2012-11-26 18:58:24 +00:00
baseColor = Lerp ( previousBaseColor , nextBaseColor , fraction ) ;
SetColor ( baseColor ) ;
BecomeActive ( TH_UPDATEVISUALS ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : GetPhysicsToSoundTransform
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idLight : : GetPhysicsToSoundTransform ( idVec3 & origin , idMat3 & axis )
{
2012-11-26 18:58:24 +00:00
origin = localLightOrigin + renderLight . lightCenter ;
axis = localLightAxis * GetPhysics ( ) - > GetAxis ( ) ;
return true ;
}
2023-12-04 19:15:34 +00:00
// RB
idVec3 idLight : : GetEditOrigin ( ) const
{
return ( GetPhysics ( ) - > GetOrigin ( ) + GetPhysics ( ) - > GetAxis ( ) * localLightOrigin ) ;
}
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = =
idLight : : FreeLightDef
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : FreeLightDef ( )
{
if ( lightDefHandle ! = - 1 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > FreeLightDef ( lightDefHandle ) ;
lightDefHandle = - 1 ;
}
}
/*
= = = = = = = = = = = = = = = =
idLight : : SaveState
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : SaveState ( idDict * args )
{
2012-11-26 18:58:24 +00:00
int i , c = spawnArgs . GetNumKeyVals ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < c ; i + + )
{
const idKeyValue * pv = spawnArgs . GetKeyVal ( i ) ;
if ( pv - > GetKey ( ) . Find ( " editor_ " , false ) > = 0 | | pv - > GetKey ( ) . Find ( " parse_ " , false ) > = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
args - > Set ( pv - > GetKey ( ) , pv - > GetValue ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = =
idLight : : ShowEditingDialog
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : ShowEditingDialog ( )
{
2016-02-07 16:19:07 +00:00
if ( g_editEntityMode . GetInteger ( ) = = 1 )
{
common - > InitTool ( EDITOR_LIGHT , & spawnArgs , this ) ;
}
else
{
common - > InitTool ( EDITOR_SOUND , & spawnArgs , this ) ;
}
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_SetShader
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_SetShader ( const char * shadername )
{
2012-11-26 18:58:24 +00:00
SetShader ( shadername ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_GetLightParm
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_GetLightParm ( int parmnum )
{
if ( ( parmnum < 0 ) | | ( parmnum > = MAX_ENTITY_SHADER_PARMS ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " shader parm index (%d) out of range " , parmnum ) ;
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idThread : : ReturnFloat ( renderLight . shaderParms [ parmnum ] ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_SetLightParm
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_SetLightParm ( int parmnum , float value )
{
2012-11-26 18:58:24 +00:00
SetLightParm ( parmnum , value ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_SetLightParms
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_SetLightParms ( float parm0 , float parm1 , float parm2 , float parm3 )
{
2012-11-26 18:58:24 +00:00
SetLightParms ( parm0 , parm1 , parm2 , parm3 ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_SetRadiusXYZ
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_SetRadiusXYZ ( float x , float y , float z )
{
2012-11-26 18:58:24 +00:00
SetRadiusXYZ ( x , y , z ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_SetRadius
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_SetRadius ( float radius )
{
2012-11-26 18:58:24 +00:00
SetRadius ( radius ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_Hide
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_Hide ( )
{
2024-05-16 19:00:44 +00:00
if ( modelTarget )
{
modelTarget - > Hide ( ) ;
}
else
{
Hide ( ) ;
}
2012-11-26 18:58:24 +00:00
PresentModelDefChange ( ) ;
Off ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_Show
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_Show ( )
{
2024-05-16 19:00:44 +00:00
if ( modelTarget )
{
modelTarget - > Show ( ) ;
}
else
{
Show ( ) ;
}
2012-11-26 18:58:24 +00:00
PresentModelDefChange ( ) ;
On ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_On
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_On ( )
{
2012-11-26 18:58:24 +00:00
On ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_Off
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_Off ( )
{
2012-11-26 18:58:24 +00:00
Off ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_ToggleOnOff
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_ToggleOnOff ( idEntity * activator )
{
2012-11-26 18:58:24 +00:00
triggercount + + ;
2012-11-28 15:47:07 +00:00
if ( triggercount < count )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// reset trigger count
triggercount = 0 ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( breakOnTrigger )
{
2012-11-26 18:58:24 +00:00
BecomeBroken ( activator ) ;
breakOnTrigger = false ;
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! currentLevel )
{
2012-11-26 18:58:24 +00:00
On ( ) ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
currentLevel - - ;
2012-11-28 15:47:07 +00:00
if ( ! currentLevel )
{
2012-11-26 18:58:24 +00:00
Off ( ) ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
SetLightLevel ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_SetSoundHandles
set the same sound def handle on all targeted lights
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_SetSoundHandles ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
idEntity * targetEnt ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! refSound . referenceSound )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < targets . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
targetEnt = targets [ i ] . GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( targetEnt ! = NULL & & targetEnt - > IsType ( idLight : : Type ) )
{
idLight * light = static_cast < idLight * > ( targetEnt ) ;
2012-11-26 18:58:24 +00:00
light - > lightParent = this ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// explicitly delete any sounds on the entity
light - > FreeSoundEmitter ( true ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// manually set the refSound to this light's refSound
light - > renderEntity . referenceSound = renderEntity . referenceSound ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// update the renderEntity to the renderer
light - > UpdateVisuals ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_FadeOut
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_FadeOut ( float time )
{
2012-11-26 18:58:24 +00:00
FadeOut ( time ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : Event_FadeIn
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : Event_FadeIn ( float time )
{
2012-11-26 18:58:24 +00:00
FadeIn ( time ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : ClientPredictionThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : ClientPredictionThink ( )
{
2012-11-26 18:58:24 +00:00
Think ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : WriteToSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : WriteToSnapshot ( idBitMsg & msg ) const
{
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > WriteToSnapshot ( msg ) ;
WriteBindToSnapshot ( msg ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
msg . WriteByte ( currentLevel ) ;
msg . WriteLong ( PackColor ( baseColor ) ) ;
// msg.WriteBits( lightParent.GetEntityNum(), GENTITYNUM_BITS );
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
/* // only helps prediction
msg . WriteLong ( PackColor ( fadeFrom ) ) ;
msg . WriteLong ( PackColor ( fadeTo ) ) ;
msg . WriteLong ( fadeStart ) ;
msg . WriteLong ( fadeEnd ) ;
*/
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: send renderLight.shader
msg . WriteFloat ( renderLight . lightRadius [ 0 ] , 5 , 10 ) ;
msg . WriteFloat ( renderLight . lightRadius [ 1 ] , 5 , 10 ) ;
msg . WriteFloat ( renderLight . lightRadius [ 2 ] , 5 , 10 ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
msg . WriteLong ( PackColor ( idVec4 ( renderLight . shaderParms [ SHADERPARM_RED ] ,
renderLight . shaderParms [ SHADERPARM_GREEN ] ,
renderLight . shaderParms [ SHADERPARM_BLUE ] ,
renderLight . shaderParms [ SHADERPARM_ALPHA ] ) ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
msg . WriteFloat ( renderLight . shaderParms [ SHADERPARM_TIMESCALE ] , 5 , 10 ) ;
msg . WriteLong ( renderLight . shaderParms [ SHADERPARM_TIMEOFFSET ] ) ;
//msg.WriteByte( renderLight.shaderParms[SHADERPARM_DIVERSITY] );
msg . WriteShort ( renderLight . shaderParms [ SHADERPARM_MODE ] ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
WriteColorToSnapshot ( msg ) ;
}
/*
= = = = = = = = = = = = = = = =
idLight : : ReadFromSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idLight : : ReadFromSnapshot ( const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
idVec4 shaderColor ;
int oldCurrentLevel = currentLevel ;
idVec3 oldBaseColor = baseColor ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
previousBaseColor = nextBaseColor ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
GetPhysics ( ) - > ReadFromSnapshot ( msg ) ;
ReadBindFromSnapshot ( msg ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
currentLevel = msg . ReadByte ( ) ;
2012-11-28 15:47:07 +00:00
if ( currentLevel ! = oldCurrentLevel )
{
2012-11-26 18:58:24 +00:00
// need to call On/Off for flickering lights to start/stop the sound
// while doing it this way rather than through events, the flickering is out of sync between clients
// but at least there is no question about saving the event and having them happening globally in the world
2012-11-28 15:47:07 +00:00
if ( currentLevel )
{
2012-11-26 18:58:24 +00:00
On ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
Off ( ) ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
UnpackColor ( msg . ReadLong ( ) , nextBaseColor ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// lightParentEntityNum = msg.ReadBits( GENTITYNUM_BITS );
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
/* // only helps prediction
UnpackColor ( msg . ReadLong ( ) , fadeFrom ) ;
UnpackColor ( msg . ReadLong ( ) , fadeTo ) ;
fadeStart = msg . ReadLong ( ) ;
fadeEnd = msg . ReadLong ( ) ;
*/
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: read renderLight.shader
renderLight . lightRadius [ 0 ] = msg . ReadFloat ( 5 , 10 ) ;
renderLight . lightRadius [ 1 ] = msg . ReadFloat ( 5 , 10 ) ;
renderLight . lightRadius [ 2 ] = msg . ReadFloat ( 5 , 10 ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
UnpackColor ( msg . ReadLong ( ) , shaderColor ) ;
renderLight . shaderParms [ SHADERPARM_RED ] = shaderColor [ 0 ] ;
renderLight . shaderParms [ SHADERPARM_GREEN ] = shaderColor [ 1 ] ;
renderLight . shaderParms [ SHADERPARM_BLUE ] = shaderColor [ 2 ] ;
renderLight . shaderParms [ SHADERPARM_ALPHA ] = shaderColor [ 3 ] ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
renderLight . shaderParms [ SHADERPARM_TIMESCALE ] = msg . ReadFloat ( 5 , 10 ) ;
renderLight . shaderParms [ SHADERPARM_TIMEOFFSET ] = msg . ReadLong ( ) ;
//renderLight.shaderParms[SHADERPARM_DIVERSITY] = msg.ReadFloat();
renderLight . shaderParms [ SHADERPARM_MODE ] = msg . ReadShort ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
ReadColorFromSnapshot ( msg ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( msg . HasChanged ( ) )
{
if ( ( currentLevel ! = oldCurrentLevel ) | | ( previousBaseColor ! = nextBaseColor ) )
{
2012-11-26 18:58:24 +00:00
SetLightLevel ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
PresentLightDefChange ( ) ;
PresentModelDefChange ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idLight : : ClientReceiveEvent
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idLight : : ClientReceiveEvent ( int event , int time , const idBitMsg & msg )
{
switch ( event )
{
case EVENT_BECOMEBROKEN :
{
2012-11-26 18:58:24 +00:00
BecomeBroken ( NULL ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
return idEntity : : ClientReceiveEvent ( event , time , msg ) ;
}
}
}
2024-05-16 19:00:44 +00:00
/*
= = = = = = = = = = = = = = = =
RB idLight : : Event_UpdateModelTarget
connects this light to its original and separate brush / patch model
= = = = = = = = = = = = = = = =
*/
void idLight : : Event_UpdateModelTarget ( )
{
const char * target = spawnArgs . GetString ( " modelTarget " ) ;
idEntity * ent = gameLocal . FindEntity ( target ) ;
if ( ent - > IsType ( idStaticEntity : : Type ) )
{
modelTarget = static_cast < idStaticEntity * > ( ent ) ;
//ent->UpdateVisuals();
}
}