Files
HL2Overcharged/game/server/lights.cpp
2025-05-21 21:20:08 +03:00

428 lines
12 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: spawn and think functions for editor-placed lights
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "lights.h"
#include "world.h"
#ifdef DEFERRED
#include "deferred/deferred_shared_common.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
LINK_ENTITY_TO_CLASS(light, CLight);
BEGIN_DATADESC(CLight)
DEFINE_FIELD(m_iCurrentFade, FIELD_CHARACTER),
DEFINE_FIELD(m_iTargetFade, FIELD_CHARACTER),
DEFINE_KEYFIELD(m_iStyle, FIELD_INTEGER, "style"),
DEFINE_KEYFIELD(m_iDefaultStyle, FIELD_INTEGER, "defaultstyle"),
DEFINE_KEYFIELD(m_iszPattern, FIELD_STRING, "pattern"),
// Fuctions
DEFINE_FUNCTION(FadeThink),
// Inputs
DEFINE_INPUTFUNC(FIELD_STRING, "SetPattern", InputSetPattern),
DEFINE_INPUTFUNC(FIELD_STRING, "FadeToPattern", InputFadeToPattern),
DEFINE_INPUTFUNC(FIELD_VOID, "Toggle", InputToggle),
DEFINE_INPUTFUNC(FIELD_VOID, "TurnOn", InputTurnOn),
DEFINE_INPUTFUNC(FIELD_VOID, "TurnOff", InputTurnOff),
END_DATADESC()
//
// Cache user-entity-field values until spawn is called.
//
bool CLight::KeyValue(const char *szKeyName, const char *szValue)
{
if (FStrEq(szKeyName, "pitch"))
{
QAngle angles = GetAbsAngles();
angles.x = atof(szValue);
SetAbsAngles(angles);
}
else
{
return BaseClass::KeyValue(szKeyName, szValue);
}
return true;
}
// Light entity
// If targeted, it will toggle between on or off.
void CLight::Spawn(void)
{
if (!GetEntityName())
{ // inert light
UTIL_Remove(this);
return;
}
if (m_iStyle >= 32)
{
if (m_iszPattern == NULL_STRING && m_iDefaultStyle > 0)
{
m_iszPattern = MAKE_STRING(GetDefaultLightstyleString(m_iDefaultStyle));
}
if (FBitSet(m_spawnflags, SF_LIGHT_START_OFF))
engine->LightStyle(m_iStyle, "a");
else if (m_iszPattern != NULL_STRING)
engine->LightStyle(m_iStyle, (char *)STRING(m_iszPattern));
else
engine->LightStyle(m_iStyle, "m");
}
}
void CLight::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
{
if (m_iStyle >= 32)
{
if (!ShouldToggle(useType, !FBitSet(m_spawnflags, SF_LIGHT_START_OFF)))
return;
Toggle();
}
}
//-----------------------------------------------------------------------------
// Purpose: Turn the light on
//-----------------------------------------------------------------------------
void CLight::TurnOn(void)
{
if (m_iszPattern != NULL_STRING)
{
engine->LightStyle(m_iStyle, (char *)STRING(m_iszPattern));
}
else
{
engine->LightStyle(m_iStyle, "m");
}
CLEARBITS(m_spawnflags, SF_LIGHT_START_OFF);
}
//-----------------------------------------------------------------------------
// Purpose: Turn the light off
//-----------------------------------------------------------------------------
void CLight::TurnOff(void)
{
engine->LightStyle(m_iStyle, "a");
SETBITS(m_spawnflags, SF_LIGHT_START_OFF);
}
//-----------------------------------------------------------------------------
// Purpose: Toggle the light on/off
//-----------------------------------------------------------------------------
void CLight::Toggle(void)
{
//Toggle it
if (FBitSet(m_spawnflags, SF_LIGHT_START_OFF))
{
TurnOn();
}
else
{
TurnOff();
}
}
//-----------------------------------------------------------------------------
// Purpose: Handle the "turnon" input handler
// Input : &inputdata -
//-----------------------------------------------------------------------------
void CLight::InputTurnOn(inputdata_t &inputdata)
{
TurnOn();
}
//-----------------------------------------------------------------------------
// Purpose: Handle the "turnoff" input handler
// Input : &inputdata -
//-----------------------------------------------------------------------------
void CLight::InputTurnOff(inputdata_t &inputdata)
{
TurnOff();
}
//-----------------------------------------------------------------------------
// Purpose: Handle the "toggle" input handler
// Input : &inputdata -
//-----------------------------------------------------------------------------
void CLight::InputToggle(inputdata_t &inputdata)
{
Toggle();
}
//-----------------------------------------------------------------------------
// Purpose: Input handler for setting a light pattern
//-----------------------------------------------------------------------------
void CLight::InputSetPattern(inputdata_t &inputdata)
{
m_iszPattern = inputdata.value.StringID();
engine->LightStyle(m_iStyle, (char *)STRING(m_iszPattern));
// Light is on if pattern is set
CLEARBITS(m_spawnflags, SF_LIGHT_START_OFF);
}
//-----------------------------------------------------------------------------
// Purpose: Input handler for fading from first value in old pattern to
// first value in new pattern
//-----------------------------------------------------------------------------
void CLight::InputFadeToPattern(inputdata_t &inputdata)
{
m_iCurrentFade = (STRING(m_iszPattern))[0];
m_iTargetFade = inputdata.value.String()[0];
m_iszPattern = inputdata.value.StringID();
SetThink(&CLight::FadeThink);
SetNextThink(gpGlobals->curtime);
// Light is on if pattern is set
CLEARBITS(m_spawnflags, SF_LIGHT_START_OFF);
}
//------------------------------------------------------------------------------
// Purpose : Fade light to new starting pattern value then stop thinking
//------------------------------------------------------------------------------
void CLight::FadeThink(void)
{
if (m_iCurrentFade < m_iTargetFade)
{
m_iCurrentFade++;
}
else if (m_iCurrentFade > m_iTargetFade)
{
m_iCurrentFade--;
}
// If we're done fading instantiate our light pattern and stop thinking
if (m_iCurrentFade == m_iTargetFade)
{
engine->LightStyle(m_iStyle, (char *)STRING(m_iszPattern));
SetNextThink(TICK_NEVER_THINK);
}
// Otherwise instantiate our current fade value and keep thinking
else
{
char sCurString[2];
sCurString[0] = m_iCurrentFade;
sCurString[1] = 0;
engine->LightStyle(m_iStyle, sCurString);
// UNDONE: Consider making this settable war to control fade speed
SetNextThink(gpGlobals->curtime + 0.1f);
}
}
//
// shut up spawn functions for new spotlights
//
LINK_ENTITY_TO_CLASS(light_spot, CLight);
LINK_ENTITY_TO_CLASS(light_glspot, CLight);
LINK_ENTITY_TO_CLASS(light_environment_old, CEnvLight);
#ifndef DEFERRED
BEGIN_DATADESC(CEnvLight)
DEFINE_FIELD(m_angSunAngles, FIELD_VECTOR),
DEFINE_FIELD(m_vecLight, FIELD_VECTOR),
DEFINE_FIELD(m_vecAmbient, FIELD_VECTOR),
DEFINE_KEYFIELD(m_bCascadedShadowMappingEnabled, FIELD_BOOLEAN, "CSM_Enable"),
DEFINE_FIELD(csmEnableLightColor, FIELD_BOOLEAN),
DEFINE_KEYFIELD(csmEnableAmbientLightColor, FIELD_BOOLEAN, "CSM_Dark"),
DEFINE_FIELD(csmLightColor, FIELD_COLOR32),
DEFINE_FIELD(csmAmbientColor, FIELD_COLOR32),
DEFINE_KEYFIELD(cmsFov, FIELD_INTEGER, "CSM_FOV"),
END_DATADESC()
IMPLEMENT_SERVERCLASS_ST_NOBASE(CEnvLight, DT_CEnvLight)
SendPropQAngles(SENDINFO(m_angSunAngles)),
SendPropVector(SENDINFO(m_vecLight)),
SendPropVector(SENDINFO(m_vecAmbient)),
SendPropBool(SENDINFO(m_bCascadedShadowMappingEnabled)),
SendPropBool(SENDINFO(csmEnableLightColor)),
SendPropBool(SENDINFO(csmEnableAmbientLightColor)),
SendPropInt(SENDINFO_STRUCTELEM(csmLightColor), 32, SPROP_UNSIGNED),
SendPropInt(SENDINFO_STRUCTELEM(csmAmbientColor), 32, SPROP_UNSIGNED),
SendPropInt(SENDINFO(cmsFov), 1, SPROP_UNSIGNED),
END_SEND_TABLE()
CEnvLight::CEnvLight() : m_bHasHDRLightSet(false), m_bHasHDRAmbientSet(false)
{
//csmEnableLightColor = false;
//m_bCascadedShadowMappingEnabled = cvar->FindVar("r_post_draw_csm_enabled")->GetBool();
//csmEnableAmbientLightColor = false;
cmsFov = 90;
csmLightColor.SetR(0);
csmLightColor.SetG(0);
csmLightColor.SetB(0);
csmLightColor.SetA(0);
csmAmbientColor.SetR(0);
csmAmbientColor.SetG(0);
csmAmbientColor.SetB(0);
csmAmbientColor.SetA(0);
}
static Vector ConvertLightmapGammaToLinear(int *iColor4)
{
Vector vecColor;
for (int i = 0; i < 3; ++i)
{
vecColor[i] = powf(iColor4[i] / 315.0f, 2.32f); // We make ambient a bit darker than baked ambient
}
vecColor *= iColor4[3] / 325.0f, 2.32f; // We make ambient a bit darker than baked ambient
return vecColor;
}
bool CEnvLight::KeyValue(const char *szKeyName, const char *szValue)
{
if (FStrEq(szKeyName, "pitch"))
{
m_angSunAngles.SetX(-atof(szValue));
}
else if (FStrEq(szKeyName, "angles"))
{
Vector vecParsed;
UTIL_StringToVector(vecParsed.Base(), szValue);
m_angSunAngles.SetY(vecParsed.y);
}
else if (FStrEq(szKeyName, "_light") || FStrEq(szKeyName, "_lightHDR"))
{
int iParsed[4];
UTIL_StringToIntArray(iParsed, 4, szValue);
if (iParsed[0] <= 0 || iParsed[1] <= 0 || iParsed[2] <= 0)
return true;
if (FStrEq(szKeyName, "_lightHDR"))
{
// HDR overrides LDR
m_bHasHDRLightSet = true;
}
else if (m_bHasHDRLightSet)
{
// If this is LDR and we got HDR already, bail out.
return true;
}
m_vecLight = ConvertLightmapGammaToLinear(iParsed);
DevMsg("Parsed light_environment light: %i %i %i %i\n",
iParsed[0], iParsed[1], iParsed[2], iParsed[3]);
}
else if (FStrEq(szKeyName, "_ambient") || FStrEq(szKeyName, "_ambientHDR"))
{
int iParsed[4];
UTIL_StringToIntArray(iParsed, 4, szValue);
if (iParsed[0] <= 0 || iParsed[1] <= 0 || iParsed[2] <= 0)
return true;
if (FStrEq(szKeyName, "_ambientHDR"))
{
// HDR overrides LDR
m_bHasHDRLightSet = true;
}
else if (m_bHasHDRLightSet)
{
// If this is LDR and we got HDR already, bail out.
return true;
}
m_vecAmbient = ConvertLightmapGammaToLinear(iParsed);
DevMsg("Parsed light_environment ambient: %i %i %i %i\n",
iParsed[0], iParsed[1], iParsed[2], iParsed[3]);
}
else
{
return BaseClass::KeyValue(szKeyName, szValue);
}
return true;
}
void CEnvLight::Spawn()
{
SetName(MAKE_STRING("light_environment"));
BaseClass::Spawn();
m_bCascadedShadowMappingEnabled = HasSpawnFlags(0x01);
}
#else
bool CEnvLight::KeyValue(const char *szKeyName, const char *szValue)
{
if (FStrEq(szKeyName, "_light"))
{
// nothing
UTIL_StringToFloatArray(m_vecLight, 4, szValue);
}
else
{
if (FStrEq(szKeyName, "pitch"))
{
m_fLightPitch = atof(szValue);
}
else if (FStrEq(szKeyName, "_ambient"))
{
UTIL_StringToFloatArray(m_vecAmbientLight, 4, szValue);
}
return BaseClass::KeyValue(szKeyName, szValue);
}
return true;
}
ConVar deferred_autoenvlight_ambient_intensity_low("deferred_autoenvlight_ambient_intensity_low", "0.35");
ConVar deferred_autoenvlight_ambient_intensity_high("deferred_autoenvlight_ambient_intensity_high", "0.85");
ConVar deferred_autoenvlight_diffuse_intensity("deferred_autoenvlight_diffuse_intensity", "15");
void CEnvLight::Activate(void)
{
BaseClass::Activate();
if (GetGlobalLight() == NULL)
{
CBaseEntity *pGlobalLight = CreateEntityByName("light_environment");
if (pGlobalLight)
{
float ds = deferred_autoenvlight_diffuse_intensity.GetFloat();
float asl = deferred_autoenvlight_ambient_intensity_low.GetFloat();
float ash = deferred_autoenvlight_ambient_intensity_high.GetFloat();
const QAngle &vecAngles = GetAbsAngles();
pGlobalLight->KeyValue("origin", UTIL_VarArgs("%f %f %f", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z));
pGlobalLight->KeyValue("diffuse", UTIL_VarArgs("%f %f %f %f", m_vecLight[0], m_vecLight[1], m_vecLight[2], m_vecLight[3] * ds));
pGlobalLight->KeyValue("ambient_high", UTIL_VarArgs("%f %f %f %f", m_vecAmbientLight[0], m_vecAmbientLight[1], m_vecAmbientLight[2], m_vecAmbientLight[3] * ash));
pGlobalLight->KeyValue("ambient_low", UTIL_VarArgs("%f %f %f %f", m_vecAmbientLight[0], m_vecAmbientLight[1], m_vecAmbientLight[2], m_vecAmbientLight[3] * asl));
pGlobalLight->KeyValue("spawnflags", "3");
pGlobalLight->KeyValue("angles", UTIL_VarArgs("%f %f %f", -m_fLightPitch, vecAngles.y, vecAngles.z));
DispatchSpawn(pGlobalLight);
//pGlobalLight->Activate(); // Should not be activated here: the global light is created before the level activates all entities.
}
}
UTIL_Remove(this);
}
#endif