//=======================
// ClientFog
//=======================
extern int gmsgSetFog;
const int SF_FOG_STARTON = 1;
LINK_ENTITY_TO_CLASS( env_fog, CClientFog );
TYPEDESCRIPTION CClientFog::m_SaveData[] =
{
DEFINE_FIELD( CClientFog, m_fActive, FIELD_BOOLEAN ),
DEFINE_FIELD( CClientFog, m_iStartDist, FIELD_INTEGER ),
DEFINE_FIELD( CClientFog, m_iEndDist, FIELD_INTEGER ),
};
IMPLEMENT_SAVERESTORE( CClientFog, CBaseEntity );
CClientFog *CClientFog::FogCreate()
{
CClientFog *pFog = GetClassPtr( ( CClientFog * ) NULL );
pFog->pev->classname = MAKE_STRING( "env_fog" );
pFog->Spawn();
return pFog;
}
void CClientFog::KeyValue( KeyValueData *pkvd )
{
if( FStrEq( pkvd->szKeyName, "startdist" ) )
{
m_iStartDist = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if( FStrEq( pkvd->szKeyName, "enddist" ) )
{
m_iEndDist = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else
CBaseEntity::KeyValue( pkvd );
}
void CClientFog::Spawn()
{
pev->effects |= EF_NODRAW;
if( FStringNull( pev->targetname ) )
pev->spawnflags |= SF_FOG_STARTON;
//Delay fog startup to the next frame
pev->nextthink = gpGlobals->time + 0.01;
SetThink( &CClientFog::FogThink );
}
void CClientFog::FogThink()
{
if( !( pev->spawnflags & SF_FOG_STARTON ) )
{
m_fActive = FALSE;
}
else
{
m_fActive = TRUE;
EnableForAll();
}
SetThink( NULL );
}
void CClientFog::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if( !m_fActive )
{
m_fActive = TRUE;
EnableForAll();
}
else
{
m_fActive = FALSE;
SetFogAll( g_vecZero, 0, 0 );
}
}
void CClientFog::CheckFogForClient( edict_t* pClient )
{
//TODO: currently only one fog entity can exist in a map
//This can be updated to use a fog manager object that keeps track of which fog entity is active to automatically change fog settings
CClientFog* pFog = ( CClientFog* ) UTIL_FindEntityByClassname( NULL, "env_fog" );
if( pFog && pFog->m_fActive == TRUE )
{
pFog->SetFog( pClient, pFog->pev->rendercolor, pFog->m_iStartDist, pFog->m_iEndDist );
}
else
{
SetFog( pClient, g_vecZero, 0, 0 );
}
}
void CClientFog::EnableForAll()
{
SetFogAll( pev->rendercolor, m_iStartDist, m_iEndDist );
}
static void InternalSetFog( edict_t* pClient, const Vector& color, float startDistance, float endDistance )
{
MESSAGE_BEGIN( pClient ? MSG_ONE : MSG_ALL, gmsgSetFog, NULL, pClient );
WRITE_SHORT( color.x );
WRITE_SHORT( color.y );
WRITE_SHORT( color.z );
WRITE_SHORT( startDistance );
WRITE_SHORT( endDistance );
MESSAGE_END();
}
void CClientFog::SetFog( edict_t* pClient, const Vector& color, float startDistance, float endDistance )
{
if( pClient == NULL )
{
ALERT( at_error, "CClientFog::SetFog called with NULL client\n" );
return;
}
InternalSetFog( pClient, color, startDistance, endDistance );
}
void CClientFog::SetFogAll( const Vector& color, float startDistance, float endDistance )
{
InternalSetFog( NULL, color, startDistance, endDistance );
}
//=======================
// ClientFog
//=======================
class CClientFog : public CBaseEntity
{
public:
void Spawn();
void KeyValue( KeyValueData *pkvd );
void EXPORT FogThink();
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
float m_iStartDist;
float m_iEndDist;
BOOL m_fActive;
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
/**
* @brief Checks if there's a fog entity active whose settings needs sending. Otherwise, tells the client to disable fog
*/
static void CheckFogForClient( edict_t* pClient );
private:
void EnableForAll();
/**
* @brief Sets the fog settings for the given client
*/
static void SetFog( edict_t* pClient, const Vector& color, float startDistance, float endDistance );
/**
* @brief Sets the fog settings for all clients
*/
static void SetFogAll( const Vector& color, float startDistance, float endDistance );
public:
static CClientFog *FogCreate();
};
extern DLL_GLOBAL int g_iSkillLevel, gDisplayTitle;
extern DLL_GLOBAL int gLevelLoaded;
int gmsgTeamNames = 0;
int gmsgSetFog = 0;
void LinkUserMessages( void )
, after...gmsgTeamNames = REG_USER_MSG( "TeamNames", -1 );
gmsgSetFog = REG_USER_MSG("SetFog", -1 );
CBasePlayer::PlayerDeathThink
add the following code before the nextthink, before the respawn code:m_fUpdateFog = TRUE;
CBasePlayer::Restore
add the following code at the very end, right before the `return status;`:
//Force the fog to update next frame
m_fUpdateFog = TRUE;
This will ensure that the fog is properly restored after loading a saved game.CBasePlayer :: UpdateClientData
add the following code:
//Update fog after respawn (also sets the fog after connect in multiplayer)
if( m_fUpdateFog )
{
m_fUpdateFog = FALSE;
CClientFog::CheckFogForClient( edict() );
}
//Enable fog after level load (singleplayer only)
if( gLevelLoaded )
{
CClientFog::CheckFogForClient( edict() );
gLevelLoaded = FALSE;
}
BOOL m_fUpdateFog; // True when fog update msg needs to be sent
DLL_GLOBAL int gLevelLoaded;
CWorld :: Precache( void )
add he following line:gLevelLoaded = TRUE;
int __MsgFunc_GameMode(const char *pszName, int iSize, void *pbuf )
{
return gHUD.MsgFunc_GameMode( pszName, iSize, pbuf );
}
add the following code:
int __MsgFunc_SetFog(const char *pszName, int iSize, void *pbuf )
{
return gHUD.MsgFunc_SetFog( pszName, iSize, pbuf );
}
After HOOK_MESSAGE( TeamInfo );
add the following line:HOOK_MESSAGE( SetFog );
int _cdecl MsgFunc_Concuss( const char *pszName, int iSize, void *pbuf );
int _cdecl MsgFunc_SetFog(const char *pszName, int iSize, void *pbuf);
vec3_t FogColor;
float g_iFogColor[3];
float g_iStartDist;
float g_iEndDist;
In CHud::MsgFunc_ResetHUD
we add the following code:
g_iStartDist = 0.0;
g_iEndDist = 0.0;
At the bottom of the file we add the following code:
int CHud :: MsgFunc_SetFog( const char *pszName, int iSize, void *pbuf )
{
BEGIN_READ( pbuf, iSize );
FogColor.x = TransformColor ( READ_SHORT() );
FogColor.y = TransformColor ( READ_SHORT() );
FogColor.z = TransformColor ( READ_SHORT() );
g_iStartDist = READ_SHORT();
g_iEndDist = READ_SHORT();
return 1;
}
inline float TransformColor ( float color )
{
float trns_clr;
if(color >= 0 ) trns_clr = color / 255.0f;
else trns_clr = 1.0;//default value
return trns_clr;
}
#include "winsani_in.h"
#include <windows.h>
#include "winsani_out.h"
#include <gl/gl.h>
Now, after #include "particleman.h"
add the following include:#include "r_studioint.h"
extern float g_iFogColor[4];
extern float g_iStartDist;
extern float g_iEndDist;
extern int g_iWaterLevel;
extern vec3_t FogColor;
extern engine_studio_api_t IEngineStudio;
void BlackFog ( void )
{
static float fColorBlack[3] = {0,0,0};
bool bFog = g_iStartDist > 0 && g_iEndDist > 0;
if (bFog)
gEngfuncs.pTriAPI->Fog ( fColorBlack, g_iStartDist, g_iEndDist, bFog );
else
gEngfuncs.pTriAPI->Fog ( g_iFogColor, g_iStartDist, g_iEndDist, bFog );
}
void RenderFog ( void )
{
float g_iFogColor[4] = { FogColor.x, FogColor.y, FogColor.z, 1.0 };
bool bFog = g_iStartDist > 0 && g_iEndDist > 0;
if ( bFog )
{
if ( IEngineStudio.IsHardware() == 2 )
{
gEngfuncs.pTriAPI->Fog ( g_iFogColor, g_iStartDist, g_iEndDist, bFog );
}
else if ( IEngineStudio.IsHardware() == 1 )
{
glEnable(GL_FOG);
glFogi (GL_FOG_MODE, GL_LINEAR);
glFogfv (GL_FOG_COLOR, g_iFogColor);
glFogf (GL_FOG_DENSITY, 1.0f);
glHint (GL_FOG_HINT, GL_DONT_CARE);
glFogf (GL_FOG_START, g_iStartDist);
glFogf (GL_FOG_END, g_iEndDist);
}
}
}
In void DLLEXPORT HUD_DrawNormalTriangles( void )
add this:RenderFog();
void DLLEXPORT HUD_DrawTransparentTriangles( void )
add this:BlackFog();
opengl32.lib
. Make sure to do this for both debug and release configurations. Now, you should have working fog in your level, but lets not forget the fgd entry, so add this somewhere in your fgd file:
@PointClass size(-16 -16 -16, 16 16 16) base(Targetname) = env_fog : "Client Fog"
[
startdist(string) : "Start Distance" : "1"
enddist(integer) : "End Distance" : 1500
rendercolor(color255) : "Fog Color (R G B)" : "0 0 0"
spawnflags(Flags) =
[
1 : "Start On" : 0
]
]
You must log in to post a comment. You can login or register a new account.
cdll_int.h(38,13): error C2040: 'HSPRITE': 'int' differs in levels of indirection from 'HSPRITE__ *'
Any ideas as to what is causing that?
Probably replacing all instances of vec_3t with Vector and DotProduct with FDotProduct should do the trick
Hold on, it does. I'm blind
That is not true, latest version of HL engine still uses Legacy GL functions but has shader compatibility. The reason why this tutorial doesn't work is that the shaders DON'T know if
glEnable(GL_FOG)
is run, it just is impossible. To make this tutorial work, theoretically you should replaceglEnable(GL_FOG)
with something likeglUniform1i(glGetUniformLocation(SHADERID, "fogEnabled"), (int)true)
but I have ZERO clue on how to find SHADERID atm.There is also an alternative method, you will have to modify the shader code for your mod though; which should be in "Half-Life/platform/gl_shaders/fs_world.frag". Replace
uniform bool fogEnabled
withlayout(location = 0) uniform bool fogEnabled
. Now go back into your code and replace everyglEnable(GL_FOG)
withglUniform1i(0, (int)true)
and obviously replace everyglDisable(GL_FOG)
withglUniform1i(0, (int)false)
.(And yes, I don't know how to reply lol)
Suggested change, in
CBasePlayer::Precache
function, addm_bSendMessages
here: