09 Dec 2009
This commit is contained in:
parent
fea3c34e68
commit
e2027e6330
|
@ -225,6 +225,10 @@ SOURCE=.\global\r_particle.cpp
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\global\r_weather.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\global\tempents.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -289,6 +293,10 @@ SOURCE=.\global\r_particle.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\global\r_weather.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\global\utils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "r_particle.h"
|
||||
#include "ev_hldm.h"
|
||||
#include "pm_shared.h"
|
||||
#include "r_weather.h"
|
||||
|
||||
cl_enginefuncs_t g_engfuncs;
|
||||
cl_globalvars_t *gpGlobals;
|
||||
|
@ -71,6 +72,8 @@ int HUD_VidInit( void )
|
|||
if( g_pParticleSystems )
|
||||
g_pParticleSystems->ClearSystems();
|
||||
|
||||
ResetRain ();
|
||||
|
||||
gHUD.VidInit();
|
||||
|
||||
return 1;
|
||||
|
@ -96,7 +99,9 @@ void HUD_Init( void )
|
|||
delete g_pParticleSystems;
|
||||
g_pParticleSystems = NULL;
|
||||
}
|
||||
|
||||
g_pParticleSystems = new ParticleSystemManager();
|
||||
InitRain(); // init weather system
|
||||
|
||||
gHUD.Init();
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ inline void CL_PlaySound( int iSound, float flVolume, Vector &pos, float pitch =
|
|||
#define RANDOM_FLOAT (*g_engfuncs.pEventAPI->EV_RandomFloat)
|
||||
#define LOAD_FILE (*g_engfuncs.pfnLoadFile)
|
||||
#define FILE_EXISTS (*g_engfuncs.pfnFileExists)
|
||||
#define FREE_FILE FREE
|
||||
#define FREE_FILE (*g_engfuncs.pfnFreeFile)
|
||||
#define DELETE_FILE (*g_engfuncs.pfnRemoveFile)
|
||||
#define LOAD_LIBRARY (*g_engfuncs.pfnLoadLibrary)
|
||||
#define GET_PROC_ADDRESS (*g_engfuncs.pfnGetProcAddress)
|
||||
|
|
|
@ -118,7 +118,7 @@ void ParticleSystemManager::UpdateSystems( void )
|
|||
ParticleSystem* pLast = NULL;
|
||||
ParticleSystem*pLastSorted = NULL;
|
||||
|
||||
// SortSystems();
|
||||
SortSystems();
|
||||
|
||||
pSystem = m_pFirstSystem;
|
||||
while( pSystem )
|
||||
|
|
|
@ -0,0 +1,698 @@
|
|||
//=======================================================================
|
||||
// Copyright (C) Shambler Team 2005
|
||||
// rain.cpp - TriAPI weather effects
|
||||
// based on original code from BUzer
|
||||
//=======================================================================
|
||||
|
||||
#include "extdll.h"
|
||||
#include "utils.h"
|
||||
#include "effects_api.h"
|
||||
#include "triangle_api.h"
|
||||
#include "hud.h"
|
||||
#include "r_weather.h"
|
||||
|
||||
void WaterLandingEffect( cl_drip *drip );
|
||||
void ParseRainFile( void );
|
||||
|
||||
cl_drip FirstChainDrip;
|
||||
cl_rainfx FirstChainFX;
|
||||
|
||||
double rain_curtime; // current time
|
||||
double rain_oldtime; // last time we have updated drips
|
||||
double rain_timedelta; // difference between old time and current time
|
||||
double rain_nextspawntime; // when the next drip should be spawned
|
||||
cvar_t *cl_debugrain;
|
||||
int dripcounter = 0;
|
||||
int fxcounter = 0;
|
||||
HSPRITE hsprWaterRing;
|
||||
HSPRITE hsprDripTexture;
|
||||
|
||||
/*
|
||||
=================================
|
||||
ProcessRain
|
||||
|
||||
Must think every frame.
|
||||
=================================
|
||||
*/
|
||||
void ProcessRain( void )
|
||||
{
|
||||
rain_oldtime = rain_curtime; // save old time
|
||||
rain_curtime = GetClientTime();
|
||||
rain_timedelta = rain_curtime - rain_oldtime;
|
||||
|
||||
// first frame
|
||||
if ( rain_oldtime == 0 )
|
||||
{
|
||||
// fix first frame bug with nextspawntime
|
||||
rain_nextspawntime = GetClientTime();
|
||||
ParseRainFile();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( gHUD.Rain.dripsPerSecond == 0 && FirstChainDrip.p_Next == NULL )
|
||||
{
|
||||
// keep nextspawntime correct
|
||||
rain_nextspawntime = rain_curtime;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( v_paused ) return; // not in pause
|
||||
|
||||
double timeBetweenDrips = 1 / (double)gHUD.Rain.dripsPerSecond;
|
||||
|
||||
cl_drip* curDrip = FirstChainDrip.p_Next;
|
||||
cl_drip* nextDrip = NULL;
|
||||
|
||||
edict_t *player = GetLocalPlayer();
|
||||
|
||||
if( !player ) return; // not in game
|
||||
|
||||
// save debug info
|
||||
float debug_lifetime = 0;
|
||||
int debug_howmany = 0;
|
||||
int debug_attempted = 0;
|
||||
int debug_dropped = 0;
|
||||
|
||||
while ( curDrip != NULL ) // go through list
|
||||
{
|
||||
nextDrip = curDrip->p_Next; // save pointer to next drip
|
||||
|
||||
if ( gHUD.Rain.weatherMode == 0 )
|
||||
curDrip->origin.z -= rain_timedelta * DRIPSPEED; // rain
|
||||
else curDrip->origin.z -= rain_timedelta * SNOWSPEED; // snow
|
||||
|
||||
curDrip->origin.x += rain_timedelta * curDrip->xDelta;
|
||||
curDrip->origin.y += rain_timedelta * curDrip->yDelta;
|
||||
|
||||
// remove drip if its origin lower than minHeight
|
||||
if ( curDrip->origin.z < curDrip->minHeight )
|
||||
{
|
||||
if ( curDrip->landInWater/* && gHUD.Rain.weatherMode == 0*/ )
|
||||
WaterLandingEffect( curDrip ); // create water rings
|
||||
|
||||
if ( cl_debugrain->value )
|
||||
{
|
||||
debug_lifetime += (rain_curtime - curDrip->birthTime);
|
||||
debug_howmany++;
|
||||
}
|
||||
|
||||
curDrip->p_Prev->p_Next = curDrip->p_Next; // link chain
|
||||
if ( nextDrip != NULL )
|
||||
nextDrip->p_Prev = curDrip->p_Prev;
|
||||
delete curDrip;
|
||||
|
||||
dripcounter--;
|
||||
}
|
||||
|
||||
curDrip = nextDrip; // restore pointer, so we can continue moving through chain
|
||||
}
|
||||
|
||||
int maxDelta; // maximum height randomize distance
|
||||
float falltime;
|
||||
if ( gHUD.Rain.weatherMode == 0 )
|
||||
{
|
||||
maxDelta = DRIPSPEED * rain_timedelta; // for rain
|
||||
falltime = (gHUD.Rain.globalHeight + 4096) / DRIPSPEED;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxDelta = SNOWSPEED * rain_timedelta; // for snow
|
||||
falltime = (gHUD.Rain.globalHeight + 4096) / SNOWSPEED;
|
||||
}
|
||||
|
||||
while ( rain_nextspawntime < rain_curtime )
|
||||
{
|
||||
rain_nextspawntime += timeBetweenDrips;
|
||||
if ( cl_debugrain->value ) debug_attempted++;
|
||||
|
||||
if ( dripcounter < MAXDRIPS ) // check for overflow
|
||||
{
|
||||
float deathHeight;
|
||||
Vector vecStart, vecEnd;
|
||||
|
||||
vecStart[0] = RANDOM_FLOAT( player->v.origin.x - gHUD.Rain.distFromPlayer, player->v.origin.x + gHUD.Rain.distFromPlayer );
|
||||
vecStart[1] = RANDOM_FLOAT( player->v.origin.y - gHUD.Rain.distFromPlayer, player->v.origin.y + gHUD.Rain.distFromPlayer );
|
||||
vecStart[2] = gHUD.Rain.globalHeight;
|
||||
|
||||
float xDelta = gHUD.Rain.windX + RANDOM_FLOAT( gHUD.Rain.randX * -1, gHUD.Rain.randX );
|
||||
float yDelta = gHUD.Rain.windY + RANDOM_FLOAT( gHUD.Rain.randY * -1, gHUD.Rain.randY );
|
||||
|
||||
// find a point at bottom of map
|
||||
vecEnd[0] = falltime * xDelta;
|
||||
vecEnd[1] = falltime * yDelta;
|
||||
vecEnd[2] = -4096;
|
||||
|
||||
TraceResult tr;
|
||||
TRACE_HULL( vecStart, vecStart + vecEnd, true, 1, player, &tr );
|
||||
|
||||
if ( tr.fStartSolid || tr.fAllSolid )
|
||||
{
|
||||
if ( cl_debugrain->value > 1 )
|
||||
debug_dropped++;
|
||||
continue; // drip cannot be placed
|
||||
}
|
||||
|
||||
// falling to water?
|
||||
int contents = POINT_CONTENTS( tr.vecEndPos );
|
||||
|
||||
if ( contents == CONTENTS_WATER )
|
||||
{
|
||||
// NOTE: in Xash3D PM_WaterEntity always return a valid water volume or NULL
|
||||
// so not needs to run additional checks here
|
||||
edict_t *pWater = g_engfuncs.pfnWaterEntity( tr.vecEndPos );
|
||||
if ( pWater )
|
||||
{
|
||||
deathHeight = pWater->v.maxs[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
// hit the world
|
||||
deathHeight = tr.vecEndPos[2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
deathHeight = tr.vecEndPos[2];
|
||||
}
|
||||
|
||||
// just in case..
|
||||
if ( deathHeight > vecStart[2] )
|
||||
{
|
||||
ALERT( at_error, "rain: can't create drip in water\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
cl_drip *newClDrip = new cl_drip;
|
||||
if ( !newClDrip )
|
||||
{
|
||||
gHUD.Rain.dripsPerSecond = 0; // disable rain
|
||||
ALERT( at_error, "rain: failed to allocate object!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
vecStart[2] -= RANDOM_FLOAT( 0, maxDelta ); // randomize a bit
|
||||
|
||||
newClDrip->alpha = RANDOM_FLOAT( 0.12, 0.2 );
|
||||
newClDrip->origin = vecStart;
|
||||
|
||||
newClDrip->xDelta = xDelta;
|
||||
newClDrip->yDelta = yDelta;
|
||||
|
||||
newClDrip->birthTime = rain_curtime; // store time when it was spawned
|
||||
newClDrip->minHeight = deathHeight;
|
||||
|
||||
if ( contents == CONTENTS_WATER )
|
||||
newClDrip->landInWater = 1;
|
||||
else newClDrip->landInWater = 0;
|
||||
|
||||
// add to first place in chain
|
||||
newClDrip->p_Next = FirstChainDrip.p_Next;
|
||||
newClDrip->p_Prev = &FirstChainDrip;
|
||||
if ( newClDrip->p_Next != NULL )
|
||||
newClDrip->p_Next->p_Prev = newClDrip;
|
||||
FirstChainDrip.p_Next = newClDrip;
|
||||
|
||||
dripcounter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( cl_debugrain->value )
|
||||
ALERT( at_error, "rain: drip limit overflow! %i > %i\n", dripcounter, MAXDRIPS );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( cl_debugrain->value ) // print debug info
|
||||
{
|
||||
ALERT( at_console, "Rain info: Drips exist: %i\n", dripcounter );
|
||||
ALERT( at_console, "Rain info: FX's exist: %i\n", fxcounter );
|
||||
ALERT( at_console, "Rain info: Attempted/Dropped: %i, %i\n", debug_attempted, debug_dropped );
|
||||
if ( debug_howmany )
|
||||
{
|
||||
float ave = debug_lifetime / (float)debug_howmany;
|
||||
ALERT( at_console, "Rain info: Average drip life time: %f\n", ave);
|
||||
}
|
||||
else ALERT( at_console, "Rain info: Average drip life time: --\n" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
=================================
|
||||
WaterLandingEffect
|
||||
=================================
|
||||
*/
|
||||
void WaterLandingEffect( cl_drip *drip )
|
||||
{
|
||||
if ( fxcounter >= MAXFX )
|
||||
{
|
||||
ALERT( at_console, "Rain error: FX limit overflow!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
cl_rainfx *newFX = new cl_rainfx;
|
||||
if ( !newFX )
|
||||
{
|
||||
ALERT( at_console, "Rain error: failed to allocate FX object!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
newFX->alpha = RANDOM_FLOAT( 0.6, 0.9 );
|
||||
newFX->origin = drip->origin;
|
||||
newFX->origin[2] = drip->minHeight; // correct position
|
||||
|
||||
newFX->birthTime = GetClientTime();
|
||||
newFX->life = RANDOM_FLOAT( 0.7f, 1.0f );
|
||||
|
||||
// add to first place in chain
|
||||
newFX->p_Next = FirstChainFX.p_Next;
|
||||
newFX->p_Prev = &FirstChainFX;
|
||||
if ( newFX->p_Next != NULL )
|
||||
newFX->p_Next->p_Prev = newFX;
|
||||
FirstChainFX.p_Next = newFX;
|
||||
|
||||
fxcounter++;
|
||||
}
|
||||
|
||||
/*
|
||||
=================================
|
||||
ProcessFXObjects
|
||||
|
||||
Remove all fx objects with out time to live
|
||||
Call every frame before ProcessRain
|
||||
=================================
|
||||
*/
|
||||
void ProcessFXObjects( void )
|
||||
{
|
||||
float curtime = GetClientTime();
|
||||
|
||||
cl_rainfx* curFX = FirstChainFX.p_Next;
|
||||
cl_rainfx* nextFX = NULL;
|
||||
|
||||
while ( curFX != NULL ) // go through FX objects list
|
||||
{
|
||||
nextFX = curFX->p_Next; // save pointer to next
|
||||
|
||||
// delete current?
|
||||
if (( curFX->birthTime + curFX->life ) < curtime )
|
||||
{
|
||||
curFX->p_Prev->p_Next = curFX->p_Next; // link chain
|
||||
if ( nextFX != NULL )
|
||||
nextFX->p_Prev = curFX->p_Prev;
|
||||
delete curFX;
|
||||
fxcounter--;
|
||||
}
|
||||
curFX = nextFX; // restore pointer
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================================
|
||||
ResetRain
|
||||
clear memory, delete all objects
|
||||
=================================
|
||||
*/
|
||||
void ResetRain( void )
|
||||
{
|
||||
// delete all drips
|
||||
cl_drip* delDrip = FirstChainDrip.p_Next;
|
||||
FirstChainDrip.p_Next = NULL;
|
||||
|
||||
while ( delDrip != NULL )
|
||||
{
|
||||
cl_drip* nextDrip = delDrip->p_Next; // save pointer to next drip in chain
|
||||
delete delDrip;
|
||||
delDrip = nextDrip; // restore pointer
|
||||
dripcounter--;
|
||||
}
|
||||
|
||||
// delete all FX objects
|
||||
cl_rainfx* delFX = FirstChainFX.p_Next;
|
||||
FirstChainFX.p_Next = NULL;
|
||||
|
||||
while ( delFX != NULL )
|
||||
{
|
||||
cl_rainfx* nextFX = delFX->p_Next;
|
||||
delete delFX;
|
||||
delFX = nextFX;
|
||||
fxcounter--;
|
||||
}
|
||||
|
||||
InitRain();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
=================================
|
||||
InitRain
|
||||
initialze system
|
||||
=================================
|
||||
*/
|
||||
void InitRain( void )
|
||||
{
|
||||
cl_debugrain = CVAR_REGISTER( "cl_debugrain", "0", 0, "display rain debug info (trace missing, drops etc)" );
|
||||
|
||||
gHUD.Rain.dripsPerSecond = 0;
|
||||
gHUD.Rain.distFromPlayer = 0;
|
||||
gHUD.Rain.windX = 0;
|
||||
gHUD.Rain.windY = 0;
|
||||
gHUD.Rain.randX = 0;
|
||||
gHUD.Rain.randY = 0;
|
||||
gHUD.Rain.weatherMode = 0;
|
||||
gHUD.Rain.globalHeight = 0;
|
||||
|
||||
FirstChainDrip.birthTime = 0;
|
||||
FirstChainDrip.minHeight = 0;
|
||||
FirstChainDrip.origin[0]=0;
|
||||
FirstChainDrip.origin[1]=0;
|
||||
FirstChainDrip.origin[2]=0;
|
||||
FirstChainDrip.alpha = 0;
|
||||
FirstChainDrip.xDelta = 0;
|
||||
FirstChainDrip.yDelta = 0;
|
||||
FirstChainDrip.landInWater = 0;
|
||||
FirstChainDrip.p_Next = NULL;
|
||||
FirstChainDrip.p_Prev = NULL;
|
||||
|
||||
FirstChainFX.alpha = 0;
|
||||
FirstChainFX.birthTime = 0;
|
||||
FirstChainFX.life = 0;
|
||||
FirstChainFX.origin[0] = 0;
|
||||
FirstChainFX.origin[1] = 0;
|
||||
FirstChainFX.origin[2] = 0;
|
||||
FirstChainFX.p_Next = NULL;
|
||||
FirstChainFX.p_Prev = NULL;
|
||||
|
||||
rain_oldtime = 0;
|
||||
rain_curtime = 0;
|
||||
rain_nextspawntime = 0;
|
||||
|
||||
// engine will be free unused shaders after each change map
|
||||
// so reload it again
|
||||
hsprWaterRing = 0;
|
||||
hsprDripTexture = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
===========================
|
||||
ParseRainFile
|
||||
|
||||
List of settings:
|
||||
drips - max raindrips\snowflakes
|
||||
distance - radius of rain\snow
|
||||
windx - wind shift X
|
||||
windy - wind shift Y
|
||||
randx - random shift X
|
||||
randy - random shift Y
|
||||
mode - rain = 0\snow =1
|
||||
height - max height to create raindrips\snowflakes
|
||||
===========================
|
||||
*/
|
||||
void ParseRainFile( void )
|
||||
{
|
||||
if ( gHUD.Rain.distFromPlayer != 0 || gHUD.Rain.dripsPerSecond != 0 || gHUD.Rain.globalHeight != 0 )
|
||||
return;
|
||||
|
||||
char mapname[256], filepath[256];
|
||||
const char *token = NULL;
|
||||
const char *pfile;
|
||||
char *afile;
|
||||
|
||||
strcpy( mapname, STRING( gpGlobals->mapname ));
|
||||
if ( strlen( mapname ) == 0 )
|
||||
{
|
||||
ALERT( at_error, "rain: unable to read map name\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Xash3D always set bare mapname without path and extension
|
||||
// mapname[strlen(mapname)-4] = 0;
|
||||
|
||||
sprintf( filepath, "scripts/weather/%s.txt", mapname );
|
||||
|
||||
afile = (char *)LOAD_FILE( filepath, NULL );
|
||||
pfile = afile;
|
||||
|
||||
if ( !pfile )
|
||||
{
|
||||
if (cl_debugrain->value > 1 )
|
||||
ALERT( at_error, "rain: couldn't open rain settings file %s\n", mapname );
|
||||
return;
|
||||
}
|
||||
|
||||
while ( true )
|
||||
{
|
||||
token = COM_ParseToken( &pfile );
|
||||
if( !token ) break;
|
||||
|
||||
if ( !stricmp( token, "drips" )) // dripsPerSecond
|
||||
{
|
||||
token = COM_ParseToken( &pfile );
|
||||
gHUD.Rain.dripsPerSecond = atoi( token );
|
||||
}
|
||||
else if ( !stricmp( token, "distance" )) // distFromPlayer
|
||||
{
|
||||
token = COM_ParseToken( &pfile );
|
||||
gHUD.Rain.distFromPlayer = atof( token );
|
||||
}
|
||||
else if ( !stricmp( token, "windx" )) // windX
|
||||
{
|
||||
token = COM_ParseToken( &pfile );
|
||||
gHUD.Rain.windX = atof( token );
|
||||
}
|
||||
else if ( !stricmp( token, "windy" )) // windY
|
||||
{
|
||||
token = COM_ParseToken( &pfile );
|
||||
gHUD.Rain.windY = atof( token );
|
||||
}
|
||||
else if ( !stricmp( token, "randx" )) // randX
|
||||
{
|
||||
token = COM_ParseToken( &pfile );
|
||||
gHUD.Rain.randX = atof( token );
|
||||
}
|
||||
else if ( !stricmp( token, "randy" )) // randY
|
||||
{
|
||||
token = COM_ParseToken( &pfile );
|
||||
gHUD.Rain.randY = atof( token );
|
||||
}
|
||||
else if ( !stricmp( token, "mode" )) // weatherMode
|
||||
{
|
||||
token = COM_ParseToken( &pfile );
|
||||
gHUD.Rain.weatherMode = atoi( token );
|
||||
}
|
||||
else if ( !stricmp( token, "height" )) // globalHeight
|
||||
{
|
||||
token = COM_ParseToken( &pfile );
|
||||
gHUD.Rain.globalHeight = atof( token );
|
||||
}
|
||||
else ALERT( at_error, "rain: unknown token %s in file %s\n", token, mapname );
|
||||
}
|
||||
FREE_FILE( afile );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
|
||||
void SetPoint( float x, float y, float z, float (*matrix)[4] )
|
||||
{
|
||||
Vector point = Vector( x, y, z ), result;
|
||||
|
||||
result.x = DotProduct( point, matrix[0] ) + matrix[0][3];
|
||||
result.y = DotProduct( point, matrix[1] ) + matrix[1][3];
|
||||
result.z = DotProduct( point, matrix[2] ) + matrix[2][3];
|
||||
|
||||
g_engfuncs.pTriAPI->Vertex3f( result[0], result[1], result[2] );
|
||||
}
|
||||
|
||||
/*
|
||||
=================================
|
||||
DrawRain
|
||||
|
||||
draw raindrips and snowflakes
|
||||
=================================
|
||||
*/
|
||||
void DrawRain( void )
|
||||
{
|
||||
if ( FirstChainDrip.p_Next == NULL )
|
||||
return; // no drips to draw
|
||||
|
||||
if( hsprDripTexture == 0 )
|
||||
{
|
||||
if ( gHUD.Rain.weatherMode == 0 )
|
||||
{
|
||||
// load rain sprite
|
||||
hsprDripTexture = g_engfuncs.pTriAPI->LoadShader( "sprites/raindrop.spr", false );
|
||||
}
|
||||
else
|
||||
{
|
||||
// load snow sprite
|
||||
hsprDripTexture = g_engfuncs.pTriAPI->LoadShader( "sprites/snowflake.spr", false );
|
||||
}
|
||||
}
|
||||
if( hsprDripTexture <= 0 ) return;
|
||||
|
||||
float visibleHeight = gHUD.Rain.globalHeight - SNOWFADEDIST;
|
||||
|
||||
// usual triapi stuff
|
||||
g_engfuncs.pTriAPI->Enable( TRI_SHADER );
|
||||
g_engfuncs.pTriAPI->Bind( hsprDripTexture, 0 );
|
||||
g_engfuncs.pTriAPI->RenderMode( kRenderTransAdd );
|
||||
g_engfuncs.pTriAPI->CullFace( TRI_NONE );
|
||||
|
||||
// go through drips list
|
||||
cl_drip *Drip = FirstChainDrip.p_Next;
|
||||
edict_t *player = GetLocalPlayer();
|
||||
if( !player ) return; // not in game yet
|
||||
|
||||
if ( gHUD.Rain.weatherMode == 0 ) // draw rain
|
||||
{
|
||||
while ( Drip != NULL )
|
||||
{
|
||||
cl_drip* nextdDrip = Drip->p_Next;
|
||||
|
||||
Vector2D toPlayer;
|
||||
toPlayer.x = player->v.origin[0] - Drip->origin[0];
|
||||
toPlayer.y = player->v.origin[1] - Drip->origin[1];
|
||||
toPlayer = toPlayer.Normalize();
|
||||
|
||||
toPlayer.x *= DRIP_SPRITE_HALFWIDTH;
|
||||
toPlayer.y *= DRIP_SPRITE_HALFWIDTH;
|
||||
|
||||
float shiftX = (Drip->xDelta / DRIPSPEED) * DRIP_SPRITE_HALFHEIGHT;
|
||||
float shiftY = (Drip->yDelta / DRIPSPEED) * DRIP_SPRITE_HALFHEIGHT;
|
||||
|
||||
g_engfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, Drip->alpha );
|
||||
g_engfuncs.pTriAPI->Begin( TRI_TRIANGLES );
|
||||
|
||||
g_engfuncs.pTriAPI->TexCoord2f( 0, 0 );
|
||||
g_engfuncs.pTriAPI->Vertex3f( Drip->origin[0]-toPlayer.y - shiftX, Drip->origin[1]+toPlayer.x - shiftY,Drip->origin[2] + DRIP_SPRITE_HALFHEIGHT );
|
||||
|
||||
g_engfuncs.pTriAPI->TexCoord2f( 0.5, 1 );
|
||||
g_engfuncs.pTriAPI->Vertex3f( Drip->origin[0] + shiftX, Drip->origin[1] + shiftY, Drip->origin[2]-DRIP_SPRITE_HALFHEIGHT );
|
||||
|
||||
g_engfuncs.pTriAPI->TexCoord2f( 1, 0 );
|
||||
g_engfuncs.pTriAPI->Vertex3f( Drip->origin[0]+toPlayer.y - shiftX, Drip->origin[1]-toPlayer.x - shiftY, Drip->origin[2]+DRIP_SPRITE_HALFHEIGHT);
|
||||
|
||||
g_engfuncs.pTriAPI->End();
|
||||
Drip = nextdDrip;
|
||||
}
|
||||
}
|
||||
|
||||
else // draw snow
|
||||
{
|
||||
Vector normal;
|
||||
|
||||
GetViewAngles( (float *)normal );
|
||||
|
||||
float matrix[3][4];
|
||||
AngleMatrix( normal, matrix ); // calc view matrix
|
||||
|
||||
while ( Drip != NULL )
|
||||
{
|
||||
cl_drip* nextdDrip = Drip->p_Next;
|
||||
|
||||
matrix[0][3] = Drip->origin[0]; // write origin to matrix
|
||||
matrix[1][3] = Drip->origin[1];
|
||||
matrix[2][3] = Drip->origin[2];
|
||||
|
||||
// apply start fading effect
|
||||
float alpha = (Drip->origin[2] <= visibleHeight) ? Drip->alpha : ((gHUD.Rain.globalHeight - Drip->origin[2]) / (float)SNOWFADEDIST) * Drip->alpha;
|
||||
|
||||
g_engfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, alpha );
|
||||
g_engfuncs.pTriAPI->Begin( TRI_QUADS );
|
||||
|
||||
g_engfuncs.pTriAPI->TexCoord2f( 0, 0 );
|
||||
SetPoint( 0, SNOW_SPRITE_HALFSIZE, SNOW_SPRITE_HALFSIZE, matrix );
|
||||
|
||||
g_engfuncs.pTriAPI->TexCoord2f( 0, 1 );
|
||||
SetPoint( 0, SNOW_SPRITE_HALFSIZE, -SNOW_SPRITE_HALFSIZE, matrix );
|
||||
|
||||
g_engfuncs.pTriAPI->TexCoord2f( 1, 1 );
|
||||
SetPoint( 0, -SNOW_SPRITE_HALFSIZE, -SNOW_SPRITE_HALFSIZE, matrix );
|
||||
|
||||
g_engfuncs.pTriAPI->TexCoord2f( 1, 0 );
|
||||
SetPoint( 0, -SNOW_SPRITE_HALFSIZE, SNOW_SPRITE_HALFSIZE, matrix );
|
||||
|
||||
g_engfuncs.pTriAPI->End();
|
||||
Drip = nextdDrip;
|
||||
}
|
||||
}
|
||||
g_engfuncs.pTriAPI->Disable( TRI_SHADER );
|
||||
}
|
||||
|
||||
/*
|
||||
=================================
|
||||
DrawFXObjects
|
||||
=================================
|
||||
*/
|
||||
void DrawFXObjects( void )
|
||||
{
|
||||
if ( FirstChainFX.p_Next == NULL )
|
||||
return; // no objects to draw
|
||||
|
||||
float curtime = GetClientTime();
|
||||
|
||||
// usual triapi stuff
|
||||
if( hsprWaterRing == 0 ) // in case what we don't want search it if not found
|
||||
{
|
||||
// load water ring sprite
|
||||
hsprWaterRing = g_engfuncs.pTriAPI->LoadShader( "sprites/waterring.spr", false );
|
||||
}
|
||||
|
||||
if( hsprWaterRing <= 0 ) return; // don't waste time
|
||||
|
||||
g_engfuncs.pTriAPI->Enable( TRI_SHADER );
|
||||
g_engfuncs.pTriAPI->Bind( hsprWaterRing, 0 );
|
||||
g_engfuncs.pTriAPI->RenderMode( kRenderTransAdd );
|
||||
g_engfuncs.pTriAPI->CullFace( TRI_NONE );
|
||||
|
||||
// go through objects list
|
||||
cl_rainfx* curFX = FirstChainFX.p_Next;
|
||||
while ( curFX != NULL )
|
||||
{
|
||||
cl_rainfx* nextFX = curFX->p_Next;
|
||||
|
||||
// fadeout
|
||||
float alpha = ((curFX->birthTime + curFX->life - curtime) / curFX->life) * curFX->alpha;
|
||||
float size = (curtime - curFX->birthTime) * MAXRINGHALFSIZE;
|
||||
float color[3];
|
||||
|
||||
// UNDONE: calc lighting right
|
||||
g_engfuncs.pEfxAPI->R_LightForPoint( (const float *)curFX->origin, color );
|
||||
// ALERT( at_console, "color %g %g %g\n", color[0], color[1], color[2] );
|
||||
|
||||
g_engfuncs.pTriAPI->Color4f( 0.4 + color[0], 0.4 + color[1], 0.4 + color[2], alpha );
|
||||
g_engfuncs.pTriAPI->Begin( TRI_QUADS );
|
||||
|
||||
g_engfuncs.pTriAPI->TexCoord2f( 0, 0 );
|
||||
g_engfuncs.pTriAPI->Vertex3f( curFX->origin[0] - size, curFX->origin[1] - size, curFX->origin[2] );
|
||||
|
||||
g_engfuncs.pTriAPI->TexCoord2f( 0, 1 );
|
||||
g_engfuncs.pTriAPI->Vertex3f( curFX->origin[0] - size, curFX->origin[1] + size, curFX->origin[2] );
|
||||
|
||||
g_engfuncs.pTriAPI->TexCoord2f( 1, 1 );
|
||||
g_engfuncs.pTriAPI->Vertex3f( curFX->origin[0] + size, curFX->origin[1] + size, curFX->origin[2] );
|
||||
|
||||
g_engfuncs.pTriAPI->TexCoord2f( 1, 0 );
|
||||
g_engfuncs.pTriAPI->Vertex3f( curFX->origin[0] + size, curFX->origin[1] - size, curFX->origin[2] );
|
||||
|
||||
g_engfuncs.pTriAPI->End();
|
||||
curFX = nextFX;
|
||||
}
|
||||
g_engfuncs.pTriAPI->Disable( TRI_SHADER );
|
||||
}
|
||||
|
||||
/*
|
||||
=================================
|
||||
DrawAll
|
||||
=================================
|
||||
*/
|
||||
|
||||
void R_DrawWeather( void )
|
||||
{
|
||||
ProcessFXObjects();
|
||||
ProcessRain();
|
||||
DrawRain();
|
||||
DrawFXObjects();
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2004, Shambler Team. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Shambler Team. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Shambler Team.
|
||||
*
|
||||
****/
|
||||
/*
|
||||
====== rain.h ========================================================
|
||||
*/
|
||||
#ifndef __RAIN_H__
|
||||
#define __RAIN_H__
|
||||
|
||||
#define DRIPSPEED 900 // speed of raindrips (pixel per secs)
|
||||
#define SNOWSPEED 200 // speed of snowflakes
|
||||
#define SNOWFADEDIST 80
|
||||
|
||||
#define MAXDRIPS 3000 // max raindrops
|
||||
#define MAXFX 3000 // max effects
|
||||
|
||||
#define DRIP_SPRITE_HALFHEIGHT 46
|
||||
#define DRIP_SPRITE_HALFWIDTH 8
|
||||
#define SNOW_SPRITE_HALFSIZE 3
|
||||
|
||||
// radius water rings
|
||||
#define MAXRINGHALFSIZE 25
|
||||
|
||||
typedef struct cl_drip
|
||||
{
|
||||
float birthTime;
|
||||
float minHeight; // minimal height to kill raindrop
|
||||
vec3_t origin;
|
||||
float alpha;
|
||||
|
||||
float xDelta; // side speed
|
||||
float yDelta;
|
||||
int landInWater;
|
||||
|
||||
cl_drip* p_Next; // next drip in chain
|
||||
cl_drip* p_Prev; // previous drip in chain
|
||||
} cl_drip_t;
|
||||
|
||||
typedef struct cl_rainfx
|
||||
{
|
||||
float birthTime;
|
||||
float life;
|
||||
vec3_t origin;
|
||||
float alpha;
|
||||
|
||||
cl_rainfx* p_Next; // next fx in chain
|
||||
cl_rainfx* p_Prev; // previous fx in chain
|
||||
} cl_rainfx_t;
|
||||
|
||||
void R_DrawWeather( void );
|
||||
void ResetRain( void );
|
||||
void InitRain( void );
|
||||
|
||||
#endif
|
|
@ -6,6 +6,7 @@
|
|||
#include "extdll.h"
|
||||
#include "utils.h"
|
||||
#include "r_particle.h"
|
||||
#include "r_weather.h"
|
||||
|
||||
void HUD_DrawTriangles( void )
|
||||
{
|
||||
|
@ -13,6 +14,7 @@ void HUD_DrawTriangles( void )
|
|||
|
||||
void HUD_DrawTransparentTriangles( void )
|
||||
{
|
||||
R_DrawWeather();
|
||||
g_pParticleSystems->UpdateSystems();
|
||||
}
|
||||
|
||||
|
|
|
@ -357,6 +357,36 @@ void DrawProgressBar( void )
|
|||
DrawImageBar( CVAR_GET_FLOAT( "scr_download" ), "m_download", (ScreenWidth - 128)>>1, ScreenHeight - 60 );
|
||||
}
|
||||
|
||||
void AngleMatrix( const vec3_t angles, float (*matrix)[4] )
|
||||
{
|
||||
float angle;
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
angle = angles[YAW] * (M_PI*2 / 360);
|
||||
sy = sin( angle );
|
||||
cy = cos( angle );
|
||||
angle = angles[PITCH] * (M_PI*2 / 360);
|
||||
sp = sin( angle );
|
||||
cp = cos( angle );
|
||||
angle = angles[ROLL] * (M_PI*2 / 360);
|
||||
sr = sin( angle );
|
||||
cr = cos( angle );
|
||||
|
||||
// matrix = (YAW * PITCH) * ROLL
|
||||
matrix[0][0] = cp*cy;
|
||||
matrix[1][0] = cp*sy;
|
||||
matrix[2][0] = -sp;
|
||||
matrix[0][1] = sr*sp*cy+cr*-sy;
|
||||
matrix[1][1] = sr*sp*sy+cr*cy;
|
||||
matrix[2][1] = sr*cp;
|
||||
matrix[0][2] = (cr*sp*cy+-sr*-sy);
|
||||
matrix[1][2] = (cr*sp*sy+-sr*cy);
|
||||
matrix[2][2] = cr*cp;
|
||||
matrix[0][3] = 0.0;
|
||||
matrix[1][3] = 0.0;
|
||||
matrix[2][3] = 0.0;
|
||||
}
|
||||
|
||||
//
|
||||
// hl2 fade - this supports multiple fading
|
||||
// FIXME: make Class CHudFade instead of C-style code?
|
||||
|
|
|
@ -166,6 +166,9 @@ extern void DrawGenericBar( float percent, int w, int h );
|
|||
extern void DrawGenericBar( float percent, int x, int y, int w, int h );
|
||||
extern void Draw_VidInit( void );
|
||||
|
||||
// mathlib
|
||||
extern void AngleMatrix( const vec3_t angles, float (*matrix)[4] );
|
||||
|
||||
// from cl_view.c
|
||||
extern void DrawProgressBar( void );
|
||||
extern edict_t *spot;
|
||||
|
|
|
@ -318,10 +318,6 @@ typedef enum
|
|||
#define CL_ACTIVE 2 // draw normal hud
|
||||
#define CL_PAUSED 3 // pause when active
|
||||
|
||||
// client key destination
|
||||
#define KEY_GAME 1
|
||||
#define KEY_HUDMENU 2
|
||||
|
||||
// built-in particle-system flags
|
||||
#define PARTICLE_GRAVITY 40 // default particle gravity
|
||||
|
||||
|
@ -347,21 +343,8 @@ typedef enum
|
|||
#define RDF_NOFOVADJUSTMENT (1<<4) // do not adjust fov for widescreen
|
||||
#define RDF_THIRDPERSON (1<<5) // enable chase cam instead firstperson
|
||||
|
||||
// engine built-in default shader
|
||||
#define MAP_DEFAULT_SHADER "*black"
|
||||
|
||||
// client modelindexes
|
||||
#define NULLENT_INDEX -1 // engine always return NULL, only for internal use
|
||||
#define VIEWENT_INDEX -2 // can get viewmodel for local client
|
||||
|
||||
// basic console charwidths
|
||||
#define TINYCHAR_WIDTH (SMALLCHAR_WIDTH)
|
||||
#define TINYCHAR_HEIGHT (SMALLCHAR_HEIGHT/2)
|
||||
#define SMALLCHAR_WIDTH 8
|
||||
#define SMALLCHAR_HEIGHT 16
|
||||
#define BIGCHAR_WIDTH 16
|
||||
#define BIGCHAR_HEIGHT 24
|
||||
#define GIANTCHAR_WIDTH 32
|
||||
#define GIANTCHAR_HEIGHT 48
|
||||
|
||||
#endif//CONST_H
|
|
@ -52,6 +52,7 @@ typedef struct efxapi_s
|
|||
void (*CL_FindExplosionPlane)( const float *origin, float radius, float *result );
|
||||
int (*CL_DecalIndexFromName)( const char *szDecalName );
|
||||
int (*CL_DecalIndex)( int id );
|
||||
void (*R_LightForPoint)( const float *rgflOrigin, float *lightValue );
|
||||
} efxapi_t;
|
||||
|
||||
#endif//EFFECTS_API_H
|
|
@ -1117,6 +1117,12 @@ bool pfnAddParticle( cparticle_t *src, HSPRITE shader, int flags )
|
|||
return true;
|
||||
}
|
||||
|
||||
void pfnLightForPoint( const vec3_t point, vec3_t ambientLight )
|
||||
{
|
||||
if( re ) re->LightForPoint( point, ambientLight );
|
||||
else VectorClear( ambientLight );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_ResetEvent
|
||||
|
|
|
@ -890,8 +890,6 @@ void CL_InitWorld( void )
|
|||
ent->v.movetype = MOVETYPE_PUSH;
|
||||
clgame.globals->numEntities = 1;
|
||||
|
||||
clgame.globals->mapname = MAKE_STRING( cl.configstrings[CS_NAME] );
|
||||
|
||||
clgame.globals->coop = Cvar_VariableInteger( "coop" );
|
||||
clgame.globals->teamplay = Cvar_VariableInteger( "teamplay" );
|
||||
clgame.globals->deathmatch = Cvar_VariableInteger( "deathmatch" );
|
||||
|
@ -1961,6 +1959,87 @@ static void pfnKillEvents( int entnum, const char *eventname )
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnPlaySound
|
||||
|
||||
=============
|
||||
*/
|
||||
void pfnPlaySound( edict_t *ent, float *org, int chan, const char *samp, float vol, float attn, int flags, int pitch )
|
||||
{
|
||||
int entindex = 0;
|
||||
|
||||
if( CL_IsValidEdict( ent )) entindex = ent->serialnumber;
|
||||
S_StartSound( org, entindex, chan, S_RegisterSound( samp ), vol, attn, pitch, flags );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnStopSound
|
||||
|
||||
=============
|
||||
*/
|
||||
void pfnStopSound( int ent, int channel, const char *sample )
|
||||
{
|
||||
S_StartSound( vec3_origin, ent, channel, S_RegisterSound( sample ), 1.0f, ATTN_NORM, PITCH_NORM, SND_STOP );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnFindModelIndex
|
||||
|
||||
=============
|
||||
*/
|
||||
int pfnFindModelIndex( const char *model )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !model || !*model ) return 0;
|
||||
for( i = 1; i < MAX_MODELS; i++ )
|
||||
{
|
||||
if( !com.strcmp( model, cl.configstrings[CS_MODELS+i] ))
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnIsLocal
|
||||
|
||||
=============
|
||||
*/
|
||||
int pfnIsLocal( int playernum )
|
||||
{
|
||||
if( playernum == cl.playernum )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnLocalPlayerViewheight
|
||||
|
||||
=============
|
||||
*/
|
||||
void pfnLocalPlayerViewheight( float *view_ofs )
|
||||
{
|
||||
// predicted or smoothed
|
||||
if( view_ofs ) VectorCopy( cl.predicted_viewofs, view_ofs );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnStopAllSounds
|
||||
|
||||
=============
|
||||
*/
|
||||
void pfnStopAllSounds( edict_t *ent, int entchannel )
|
||||
{
|
||||
// FIXME: this not valid code
|
||||
S_StopAllSounds ();
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
VGui_GetPanel
|
||||
|
@ -2314,6 +2393,7 @@ static efxapi_t gEfxApi =
|
|||
pfnFindExplosionPlane,
|
||||
pfnDecalIndexFromName,
|
||||
pfnDecalIndex,
|
||||
pfnLightForPoint,
|
||||
};
|
||||
|
||||
static event_api_t gEventApi =
|
||||
|
@ -2326,6 +2406,12 @@ static event_api_t gEventApi =
|
|||
pfnRandomLong,
|
||||
pfnHookEvent,
|
||||
pfnKillEvents,
|
||||
pfnPlaySound,
|
||||
pfnStopSound,
|
||||
pfnFindModelIndex,
|
||||
pfnIsLocal,
|
||||
pfnLocalPlayerViewheight,
|
||||
pfnStopAllSounds
|
||||
};
|
||||
|
||||
// engine callbacks
|
||||
|
|
|
@ -700,7 +700,9 @@ void CL_PrepVideo( void )
|
|||
|
||||
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
|
||||
MsgDev( D_LOAD, "CL_PrepVideo: %s\n", cl.configstrings[CS_NAME] );
|
||||
|
||||
// let the render dll load the map
|
||||
clgame.globals->mapname = MAKE_STRING( cl.configstrings[CS_NAME] );
|
||||
com.strncpy( mapname, cl.configstrings[CS_MODELS+1], MAX_STRING );
|
||||
CM_BeginRegistration( mapname, true, &map_checksum );
|
||||
re->BeginRegistration( mapname, CM_VisData()); // load map
|
||||
|
|
|
@ -552,6 +552,7 @@ void CL_ClearEffects( void );
|
|||
void CL_TestLights( void );
|
||||
void CL_TestEntities( void );
|
||||
void CL_FindExplosionPlane( const vec3_t origin, float radius, vec3_t result );
|
||||
void pfnLightForPoint( const vec3_t point, vec3_t ambientLight );
|
||||
bool pfnAddParticle( cparticle_t *src, HSPRITE shader, int flags );
|
||||
void pfnAddDecal( float *org, float *dir, float *rgba, float rot, float rad, HSPRITE hSpr, int flags );
|
||||
void pfnAddDLight( const float *org, const float *rgb, float radius, float time, int flags, int key );
|
||||
|
|
|
@ -30,6 +30,16 @@
|
|||
|
||||
==============================================================
|
||||
*/
|
||||
// basic console charwidths
|
||||
#define TINYCHAR_WIDTH (SMALLCHAR_WIDTH)
|
||||
#define TINYCHAR_HEIGHT (SMALLCHAR_HEIGHT/2)
|
||||
#define SMALLCHAR_WIDTH 8
|
||||
#define SMALLCHAR_HEIGHT 16
|
||||
#define BIGCHAR_WIDTH 16
|
||||
#define BIGCHAR_HEIGHT 24
|
||||
#define GIANTCHAR_WIDTH 32
|
||||
#define GIANTCHAR_HEIGHT 48
|
||||
|
||||
#define SCREEN_WIDTH 640
|
||||
#define SCREEN_HEIGHT 480
|
||||
extern cvar_t *scr_width;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define bound(min, num, max) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min))
|
||||
#define MAX_STRING_TABLES 8 // seperately stringsystems
|
||||
#define MAX_MODS 128 // environment games that engine can keep visible
|
||||
#define MAP_DEFAULT_SHADER "*black" // engine built-in default shader
|
||||
#ifndef __cplusplus
|
||||
#define bool BOOL // sizeof( int )
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
};
|
||||
LINK_ENTITY_TO_CLASS( func_wall, CFuncWall );
|
||||
LINK_ENTITY_TO_CLASS( func_static, CFuncWall );
|
||||
LINK_ENTITY_TO_CLASS( func_bossgate, CFuncWall );
|
||||
LINK_ENTITY_TO_CLASS( func_wall_toggle, CFuncWall );
|
||||
LINK_ENTITY_TO_CLASS( func_illusionary, CFuncWall );
|
||||
|
||||
|
@ -42,11 +43,19 @@ void CFuncWall :: Spawn( void )
|
|||
{
|
||||
CBaseBrush::Spawn();
|
||||
|
||||
if(FClassnameIs(pev, "func_illusionary" ))
|
||||
if( FClassnameIs( pev, "func_illusionary" ))
|
||||
{
|
||||
pev->solid = SOLID_NOT;
|
||||
pev->movetype = MOVETYPE_NONE;
|
||||
}
|
||||
else if( FClassnameIs( pev, "func_bossgate" ))
|
||||
{
|
||||
if(( gpGlobals->serverflags & 15 ) == 15 )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
return; // all episodes completed
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pev->solid = SOLID_BSP;
|
||||
|
|
|
@ -64,15 +64,10 @@ void CBaseParticle::Spawn( void )
|
|||
{
|
||||
Precache();
|
||||
|
||||
pev->origin.z += 72;
|
||||
|
||||
UTIL_SetModel( edict(), "sprites/null.spr" );
|
||||
UTIL_SetOrigin( this, pev->origin );
|
||||
pev->solid = SOLID_NOT;
|
||||
|
||||
// TESTONLY: don't forget to remove
|
||||
pev->angles = Vector( 0, 90, 0 );
|
||||
|
||||
if( pev->spawnflags & SF_START_ON || FStringNull( pev->targetname ))
|
||||
m_iState = STATE_ON;
|
||||
else m_iState = STATE_OFF;
|
||||
|
|
6
todo.log
6
todo.log
|
@ -155,14 +155,14 @@ Beta 13.12.09
|
|||
129. fixup sound orientation OK
|
||||
130. don't show console on changelevel OK
|
||||
131. fixup teleports and trigger push's OK
|
||||
132. implement _detail.txt lists for hl
|
||||
132. implement _detail.txt lists for hl OK
|
||||
133. new sound\render system version replacement OK
|
||||
134. dx sound engine complete OK
|
||||
135. implement dsp OK
|
||||
136. re-vision uimenu
|
||||
137. complete rewriting physic.dll OK
|
||||
138. implement hashtable for loaded sounds OK
|
||||
139. finalize triangle API
|
||||
139. finalize triangle API OK
|
||||
140. net_msg is buggly!!!! OK
|
||||
141. implement client predicting OK
|
||||
142. finalize CL_Move and CL_LinkEdict OK
|
||||
|
@ -188,7 +188,7 @@ Beta 13.12.09
|
|||
162. rewrote auto-classify OK
|
||||
163. rewrote sv_phys.c OK
|
||||
164. remove vprogs.dll OK
|
||||
165. finalize EventAPI
|
||||
165. finalize EventAPI OK
|
||||
166. move cl_input.c into client.dll OK
|
||||
167. fix all founded errors
|
||||
168. release at 13/12/2009
|
||||
|
|
|
@ -1670,7 +1670,7 @@ void R_ModifyColor( const ref_stage_t *pass )
|
|||
}
|
||||
break;
|
||||
case RGBGEN_LIGHTING_AMBIENT_ONLY:
|
||||
if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) )
|
||||
if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ))
|
||||
{
|
||||
vec4_t ambient;
|
||||
|
||||
|
|
|
@ -643,6 +643,7 @@ void R_DrawMeshes( void )
|
|||
int i;
|
||||
meshbuffer_t *meshbuf;
|
||||
|
||||
Tri_RenderCallback( false );
|
||||
RI.previousentity = NULL;
|
||||
if( RI.meshlist->num_opaque_meshes )
|
||||
{
|
||||
|
@ -652,8 +653,8 @@ void R_DrawMeshes( void )
|
|||
R_BatchMeshBuffer( meshbuf, NULL );
|
||||
}
|
||||
|
||||
Tri_RenderCallback( false );
|
||||
|
||||
Tri_RenderCallback( true );
|
||||
if( RI.meshlist->num_translucent_meshes )
|
||||
{
|
||||
meshbuf = RI.meshlist->meshbuffer_translucent;
|
||||
|
@ -662,8 +663,6 @@ void R_DrawMeshes( void )
|
|||
R_BatchMeshBuffer( meshbuf, NULL );
|
||||
}
|
||||
|
||||
Tri_RenderCallback( true );
|
||||
|
||||
R_LoadIdentity();
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ bool PlaneEqual( plane_t *p, vec3_t normal, vec_t dist )
|
|||
|
||||
/*
|
||||
=================
|
||||
PlaneTypeForNormal
|
||||
MapPlaneTypeForNormal
|
||||
=================
|
||||
*/
|
||||
int MapPlaneTypeForNormal( const vec3_t normal )
|
||||
|
@ -125,7 +125,7 @@ int CreateNewFloatPlane( vec3_t normal, vec_t dist )
|
|||
p = &mapplanes[nummapplanes];
|
||||
VectorCopy( normal, p->normal );
|
||||
p->dist = dist;
|
||||
p->type = (p+1)->type = PlaneTypeForNormal( p->normal );
|
||||
p->type = (p+1)->type = MapPlaneTypeForNormal( p->normal );
|
||||
|
||||
VectorSubtract( vec3_origin, normal, (p+1)->normal );
|
||||
(p+1)->dist = -dist;
|
||||
|
|
|
@ -53,6 +53,7 @@ byte* bsp_base;
|
|||
bool bsp_halflife = false;
|
||||
dmiptexname_t *mipnames = NULL;
|
||||
int mip_count = 0;
|
||||
file_t *detail_txt;
|
||||
|
||||
bool MipExist( const char *name )
|
||||
{
|
||||
|
@ -67,10 +68,77 @@ bool MipExist( const char *name )
|
|||
return FS_FileExists( name );
|
||||
}
|
||||
|
||||
static const char *DetailTextureForName( const char *name )
|
||||
{
|
||||
if( !name || !*name ) return NULL;
|
||||
if( !com.strnicmp( name, "sky", 3 ))
|
||||
return NULL; // never details for sky
|
||||
|
||||
// never apply details for liquids
|
||||
if( !com.strnicmp( name + 1, "!lava", 5 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name + 1, "!slime", 6 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name, "!cur_90", 7 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name, "!cur_0", 6 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name, "!cur_270", 8 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name, "!cur_180", 8 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name, "!cur_up", 7 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name, "!cur_dwn", 8 ))
|
||||
return NULL;
|
||||
if( name[0] == '!' )
|
||||
return NULL;
|
||||
|
||||
// never apply details to the special textures
|
||||
if( !com.strnicmp( name, "origin", 6 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name, "clip", 4 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name, "hint", 4 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name, "skip", 4 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name, "translucent", 11 ))
|
||||
return NULL;
|
||||
if( !com.strnicmp( name, "3dsky", 5 ))
|
||||
return NULL;
|
||||
if( name[0] == '@' )
|
||||
return NULL;
|
||||
|
||||
// last check ...
|
||||
if( !com.strnicmp( name, "null", 4 ))
|
||||
return NULL;
|
||||
|
||||
// at this point we can apply detail textures to the current
|
||||
if( com.stristr( name, "brick" )) return "dt_brick";
|
||||
if( com.stristr( name, "carpet" )) return "dt_carpet1";
|
||||
if( com.stristr( name, "crete" )) return "dt_conc";
|
||||
if( com.stristr( name, "generic" )) return va( "dt_fabric%i", Com_RandomLong( 1, 2 ));
|
||||
if( com.stristr( name, "grass" )) return "dt_grass1";
|
||||
if( com.stristr( name, "ground" ) || com.stristr( name, "gnd" ))
|
||||
return va( "dt_ground%i", Com_RandomLong( 1, 5 ));
|
||||
if( com.stristr( name, "metal" ) || com.stristr( name, "metl" ))
|
||||
return va( "dt_metal%i", Com_RandomLong( 1, 2 ));
|
||||
if( com.stristr( name, "rock" )) return "dt_rock1";
|
||||
if( com.stristr( name, "snow" )) return va( "dt_snow%i", Com_RandomLong( 1, 2 ));
|
||||
if( com.stristr( name, "stone" )) return va( "dt_stone%i", Com_RandomLong( 1, 4 ));
|
||||
if( com.stristr( name, "steel" )) return "dt_steel1";
|
||||
if( com.stristr( name, "wood" )) return va( "dt_wood%i", Com_RandomLong( 1, 3 ));
|
||||
|
||||
// apply default detail texture
|
||||
return "dt_brick";
|
||||
}
|
||||
|
||||
void Conv_BspTextures( const char *name, dlump_t *l, const char *ext )
|
||||
{
|
||||
dmiptexlump_t *m;
|
||||
string genericname;
|
||||
const char *det_name;
|
||||
mip_t *mip;
|
||||
int i, k;
|
||||
int *dofs, size;
|
||||
|
@ -83,6 +151,8 @@ void Conv_BspTextures( const char *name, dlump_t *l, const char *ext )
|
|||
m->nummiptex = LittleLong( m->nummiptex );
|
||||
dofs = m->dataofs;
|
||||
|
||||
detail_txt = FS_Open( va( "%s/%s_detail.txt", gs_gamedir, name ), "wb" );
|
||||
|
||||
mipnames = Mem_Realloc( basepool, mipnames, m->nummiptex * sizeof( dmiptexname_t ));
|
||||
mip_count = 0;
|
||||
|
||||
|
@ -94,9 +164,15 @@ void Conv_BspTextures( const char *name, dlump_t *l, const char *ext )
|
|||
|
||||
// needs to simulate directly loading
|
||||
mip = (mip_t *)((byte *)m + dofs[i]);
|
||||
if( !LittleLong( mip->offsets[0] )) continue; // not in bsp
|
||||
|
||||
// build detailtexture string
|
||||
det_name = DetailTextureForName( mip->name ); // lookup both registers
|
||||
com.strnlwr( mip->name, mip->name, sizeof( mip->name )); // name
|
||||
|
||||
// detailtexture detected
|
||||
if( det_name ) FS_Printf( detail_txt, "%s detail/%s 10.0 10.0\n", mip->name, det_name );
|
||||
if( !LittleLong( mip->offsets[0] )) continue; // not in bsp, skipped
|
||||
|
||||
// check for '*' symbol issues
|
||||
k = com.strlen( com.strrchr( mip->name, '*' ));
|
||||
if( k ) mip->name[com.strlen(mip->name)-k] = '!'; // quake1 issues
|
||||
|
@ -124,6 +200,7 @@ void Conv_BspTextures( const char *name, dlump_t *l, const char *ext )
|
|||
ConvMIP( va("%s/%s", name, mip->name ), buffer, size, ext ); // convert it
|
||||
}
|
||||
mip_count = 0; // freed and invaliadte
|
||||
FS_Close( detail_txt );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Reference in New Issue