09 Dec 2009
This commit is contained in:
parent
fea3c34e68
commit
e2027e6330
|
@ -225,6 +225,10 @@ SOURCE=.\global\r_particle.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\global\r_weather.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\global\tempents.cpp
|
SOURCE=.\global\tempents.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
@ -289,6 +293,10 @@ SOURCE=.\global\r_particle.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\global\r_weather.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\global\utils.h
|
SOURCE=.\global\utils.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "r_particle.h"
|
#include "r_particle.h"
|
||||||
#include "ev_hldm.h"
|
#include "ev_hldm.h"
|
||||||
#include "pm_shared.h"
|
#include "pm_shared.h"
|
||||||
|
#include "r_weather.h"
|
||||||
|
|
||||||
cl_enginefuncs_t g_engfuncs;
|
cl_enginefuncs_t g_engfuncs;
|
||||||
cl_globalvars_t *gpGlobals;
|
cl_globalvars_t *gpGlobals;
|
||||||
|
@ -71,6 +72,8 @@ int HUD_VidInit( void )
|
||||||
if( g_pParticleSystems )
|
if( g_pParticleSystems )
|
||||||
g_pParticleSystems->ClearSystems();
|
g_pParticleSystems->ClearSystems();
|
||||||
|
|
||||||
|
ResetRain ();
|
||||||
|
|
||||||
gHUD.VidInit();
|
gHUD.VidInit();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -96,7 +99,9 @@ void HUD_Init( void )
|
||||||
delete g_pParticleSystems;
|
delete g_pParticleSystems;
|
||||||
g_pParticleSystems = NULL;
|
g_pParticleSystems = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pParticleSystems = new ParticleSystemManager();
|
g_pParticleSystems = new ParticleSystemManager();
|
||||||
|
InitRain(); // init weather system
|
||||||
|
|
||||||
gHUD.Init();
|
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 RANDOM_FLOAT (*g_engfuncs.pEventAPI->EV_RandomFloat)
|
||||||
#define LOAD_FILE (*g_engfuncs.pfnLoadFile)
|
#define LOAD_FILE (*g_engfuncs.pfnLoadFile)
|
||||||
#define FILE_EXISTS (*g_engfuncs.pfnFileExists)
|
#define FILE_EXISTS (*g_engfuncs.pfnFileExists)
|
||||||
#define FREE_FILE FREE
|
#define FREE_FILE (*g_engfuncs.pfnFreeFile)
|
||||||
#define DELETE_FILE (*g_engfuncs.pfnRemoveFile)
|
#define DELETE_FILE (*g_engfuncs.pfnRemoveFile)
|
||||||
#define LOAD_LIBRARY (*g_engfuncs.pfnLoadLibrary)
|
#define LOAD_LIBRARY (*g_engfuncs.pfnLoadLibrary)
|
||||||
#define GET_PROC_ADDRESS (*g_engfuncs.pfnGetProcAddress)
|
#define GET_PROC_ADDRESS (*g_engfuncs.pfnGetProcAddress)
|
||||||
|
|
|
@ -118,7 +118,7 @@ void ParticleSystemManager::UpdateSystems( void )
|
||||||
ParticleSystem* pLast = NULL;
|
ParticleSystem* pLast = NULL;
|
||||||
ParticleSystem*pLastSorted = NULL;
|
ParticleSystem*pLastSorted = NULL;
|
||||||
|
|
||||||
// SortSystems();
|
SortSystems();
|
||||||
|
|
||||||
pSystem = m_pFirstSystem;
|
pSystem = m_pFirstSystem;
|
||||||
while( pSystem )
|
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 "extdll.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "r_particle.h"
|
#include "r_particle.h"
|
||||||
|
#include "r_weather.h"
|
||||||
|
|
||||||
void HUD_DrawTriangles( void )
|
void HUD_DrawTriangles( void )
|
||||||
{
|
{
|
||||||
|
@ -13,6 +14,7 @@ void HUD_DrawTriangles( void )
|
||||||
|
|
||||||
void HUD_DrawTransparentTriangles( void )
|
void HUD_DrawTransparentTriangles( void )
|
||||||
{
|
{
|
||||||
|
R_DrawWeather();
|
||||||
g_pParticleSystems->UpdateSystems();
|
g_pParticleSystems->UpdateSystems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -357,6 +357,36 @@ void DrawProgressBar( void )
|
||||||
DrawImageBar( CVAR_GET_FLOAT( "scr_download" ), "m_download", (ScreenWidth - 128)>>1, ScreenHeight - 60 );
|
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
|
// hl2 fade - this supports multiple fading
|
||||||
// FIXME: make Class CHudFade instead of C-style code?
|
// 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 DrawGenericBar( float percent, int x, int y, int w, int h );
|
||||||
extern void Draw_VidInit( void );
|
extern void Draw_VidInit( void );
|
||||||
|
|
||||||
|
// mathlib
|
||||||
|
extern void AngleMatrix( const vec3_t angles, float (*matrix)[4] );
|
||||||
|
|
||||||
// from cl_view.c
|
// from cl_view.c
|
||||||
extern void DrawProgressBar( void );
|
extern void DrawProgressBar( void );
|
||||||
extern edict_t *spot;
|
extern edict_t *spot;
|
||||||
|
|
|
@ -318,10 +318,6 @@ typedef enum
|
||||||
#define CL_ACTIVE 2 // draw normal hud
|
#define CL_ACTIVE 2 // draw normal hud
|
||||||
#define CL_PAUSED 3 // pause when active
|
#define CL_PAUSED 3 // pause when active
|
||||||
|
|
||||||
// client key destination
|
|
||||||
#define KEY_GAME 1
|
|
||||||
#define KEY_HUDMENU 2
|
|
||||||
|
|
||||||
// built-in particle-system flags
|
// built-in particle-system flags
|
||||||
#define PARTICLE_GRAVITY 40 // default particle gravity
|
#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_NOFOVADJUSTMENT (1<<4) // do not adjust fov for widescreen
|
||||||
#define RDF_THIRDPERSON (1<<5) // enable chase cam instead firstperson
|
#define RDF_THIRDPERSON (1<<5) // enable chase cam instead firstperson
|
||||||
|
|
||||||
// engine built-in default shader
|
|
||||||
#define MAP_DEFAULT_SHADER "*black"
|
|
||||||
|
|
||||||
// client modelindexes
|
// client modelindexes
|
||||||
#define NULLENT_INDEX -1 // engine always return NULL, only for internal use
|
#define NULLENT_INDEX -1 // engine always return NULL, only for internal use
|
||||||
#define VIEWENT_INDEX -2 // can get viewmodel for local client
|
#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
|
#endif//CONST_H
|
|
@ -52,6 +52,7 @@ typedef struct efxapi_s
|
||||||
void (*CL_FindExplosionPlane)( const float *origin, float radius, float *result );
|
void (*CL_FindExplosionPlane)( const float *origin, float radius, float *result );
|
||||||
int (*CL_DecalIndexFromName)( const char *szDecalName );
|
int (*CL_DecalIndexFromName)( const char *szDecalName );
|
||||||
int (*CL_DecalIndex)( int id );
|
int (*CL_DecalIndex)( int id );
|
||||||
|
void (*R_LightForPoint)( const float *rgflOrigin, float *lightValue );
|
||||||
} efxapi_t;
|
} efxapi_t;
|
||||||
|
|
||||||
#endif//EFFECTS_API_H
|
#endif//EFFECTS_API_H
|
|
@ -1117,6 +1117,12 @@ bool pfnAddParticle( cparticle_t *src, HSPRITE shader, int flags )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pfnLightForPoint( const vec3_t point, vec3_t ambientLight )
|
||||||
|
{
|
||||||
|
if( re ) re->LightForPoint( point, ambientLight );
|
||||||
|
else VectorClear( ambientLight );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
CL_ResetEvent
|
CL_ResetEvent
|
||||||
|
|
|
@ -890,8 +890,6 @@ void CL_InitWorld( void )
|
||||||
ent->v.movetype = MOVETYPE_PUSH;
|
ent->v.movetype = MOVETYPE_PUSH;
|
||||||
clgame.globals->numEntities = 1;
|
clgame.globals->numEntities = 1;
|
||||||
|
|
||||||
clgame.globals->mapname = MAKE_STRING( cl.configstrings[CS_NAME] );
|
|
||||||
|
|
||||||
clgame.globals->coop = Cvar_VariableInteger( "coop" );
|
clgame.globals->coop = Cvar_VariableInteger( "coop" );
|
||||||
clgame.globals->teamplay = Cvar_VariableInteger( "teamplay" );
|
clgame.globals->teamplay = Cvar_VariableInteger( "teamplay" );
|
||||||
clgame.globals->deathmatch = Cvar_VariableInteger( "deathmatch" );
|
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
|
VGui_GetPanel
|
||||||
|
@ -2314,6 +2393,7 @@ static efxapi_t gEfxApi =
|
||||||
pfnFindExplosionPlane,
|
pfnFindExplosionPlane,
|
||||||
pfnDecalIndexFromName,
|
pfnDecalIndexFromName,
|
||||||
pfnDecalIndex,
|
pfnDecalIndex,
|
||||||
|
pfnLightForPoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
static event_api_t gEventApi =
|
static event_api_t gEventApi =
|
||||||
|
@ -2326,6 +2406,12 @@ static event_api_t gEventApi =
|
||||||
pfnRandomLong,
|
pfnRandomLong,
|
||||||
pfnHookEvent,
|
pfnHookEvent,
|
||||||
pfnKillEvents,
|
pfnKillEvents,
|
||||||
|
pfnPlaySound,
|
||||||
|
pfnStopSound,
|
||||||
|
pfnFindModelIndex,
|
||||||
|
pfnIsLocal,
|
||||||
|
pfnLocalPlayerViewheight,
|
||||||
|
pfnStopAllSounds
|
||||||
};
|
};
|
||||||
|
|
||||||
// engine callbacks
|
// engine callbacks
|
||||||
|
|
|
@ -700,7 +700,9 @@ void CL_PrepVideo( void )
|
||||||
|
|
||||||
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
|
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
|
||||||
MsgDev( D_LOAD, "CL_PrepVideo: %s\n", cl.configstrings[CS_NAME] );
|
MsgDev( D_LOAD, "CL_PrepVideo: %s\n", cl.configstrings[CS_NAME] );
|
||||||
|
|
||||||
// let the render dll load the map
|
// 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 );
|
com.strncpy( mapname, cl.configstrings[CS_MODELS+1], MAX_STRING );
|
||||||
CM_BeginRegistration( mapname, true, &map_checksum );
|
CM_BeginRegistration( mapname, true, &map_checksum );
|
||||||
re->BeginRegistration( mapname, CM_VisData()); // load map
|
re->BeginRegistration( mapname, CM_VisData()); // load map
|
||||||
|
|
|
@ -552,6 +552,7 @@ void CL_ClearEffects( void );
|
||||||
void CL_TestLights( void );
|
void CL_TestLights( void );
|
||||||
void CL_TestEntities( void );
|
void CL_TestEntities( void );
|
||||||
void CL_FindExplosionPlane( const vec3_t origin, float radius, vec3_t result );
|
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 );
|
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 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 );
|
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_WIDTH 640
|
||||||
#define SCREEN_HEIGHT 480
|
#define SCREEN_HEIGHT 480
|
||||||
extern cvar_t *scr_width;
|
extern cvar_t *scr_width;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#define bound(min, num, max) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min))
|
#define bound(min, num, max) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min))
|
||||||
#define MAX_STRING_TABLES 8 // seperately stringsystems
|
#define MAX_STRING_TABLES 8 // seperately stringsystems
|
||||||
#define MAX_MODS 128 // environment games that engine can keep visible
|
#define MAX_MODS 128 // environment games that engine can keep visible
|
||||||
|
#define MAP_DEFAULT_SHADER "*black" // engine built-in default shader
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
#define bool BOOL // sizeof( int )
|
#define bool BOOL // sizeof( int )
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
};
|
};
|
||||||
LINK_ENTITY_TO_CLASS( func_wall, CFuncWall );
|
LINK_ENTITY_TO_CLASS( func_wall, CFuncWall );
|
||||||
LINK_ENTITY_TO_CLASS( func_static, 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_wall_toggle, CFuncWall );
|
||||||
LINK_ENTITY_TO_CLASS( func_illusionary, CFuncWall );
|
LINK_ENTITY_TO_CLASS( func_illusionary, CFuncWall );
|
||||||
|
|
||||||
|
@ -42,11 +43,19 @@ void CFuncWall :: Spawn( void )
|
||||||
{
|
{
|
||||||
CBaseBrush::Spawn();
|
CBaseBrush::Spawn();
|
||||||
|
|
||||||
if(FClassnameIs(pev, "func_illusionary" ))
|
if( FClassnameIs( pev, "func_illusionary" ))
|
||||||
{
|
{
|
||||||
pev->solid = SOLID_NOT;
|
pev->solid = SOLID_NOT;
|
||||||
pev->movetype = MOVETYPE_NONE;
|
pev->movetype = MOVETYPE_NONE;
|
||||||
}
|
}
|
||||||
|
else if( FClassnameIs( pev, "func_bossgate" ))
|
||||||
|
{
|
||||||
|
if(( gpGlobals->serverflags & 15 ) == 15 )
|
||||||
|
{
|
||||||
|
UTIL_Remove( this );
|
||||||
|
return; // all episodes completed
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pev->solid = SOLID_BSP;
|
pev->solid = SOLID_BSP;
|
||||||
|
|
|
@ -64,15 +64,10 @@ void CBaseParticle::Spawn( void )
|
||||||
{
|
{
|
||||||
Precache();
|
Precache();
|
||||||
|
|
||||||
pev->origin.z += 72;
|
|
||||||
|
|
||||||
UTIL_SetModel( edict(), "sprites/null.spr" );
|
UTIL_SetModel( edict(), "sprites/null.spr" );
|
||||||
UTIL_SetOrigin( this, pev->origin );
|
UTIL_SetOrigin( this, pev->origin );
|
||||||
pev->solid = SOLID_NOT;
|
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 ))
|
if( pev->spawnflags & SF_START_ON || FStringNull( pev->targetname ))
|
||||||
m_iState = STATE_ON;
|
m_iState = STATE_ON;
|
||||||
else m_iState = STATE_OFF;
|
else m_iState = STATE_OFF;
|
||||||
|
|
6
todo.log
6
todo.log
|
@ -155,14 +155,14 @@ Beta 13.12.09
|
||||||
129. fixup sound orientation OK
|
129. fixup sound orientation OK
|
||||||
130. don't show console on changelevel OK
|
130. don't show console on changelevel OK
|
||||||
131. fixup teleports and trigger push's 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
|
133. new sound\render system version replacement OK
|
||||||
134. dx sound engine complete OK
|
134. dx sound engine complete OK
|
||||||
135. implement dsp OK
|
135. implement dsp OK
|
||||||
136. re-vision uimenu
|
136. re-vision uimenu
|
||||||
137. complete rewriting physic.dll OK
|
137. complete rewriting physic.dll OK
|
||||||
138. implement hashtable for loaded sounds OK
|
138. implement hashtable for loaded sounds OK
|
||||||
139. finalize triangle API
|
139. finalize triangle API OK
|
||||||
140. net_msg is buggly!!!! OK
|
140. net_msg is buggly!!!! OK
|
||||||
141. implement client predicting OK
|
141. implement client predicting OK
|
||||||
142. finalize CL_Move and CL_LinkEdict OK
|
142. finalize CL_Move and CL_LinkEdict OK
|
||||||
|
@ -188,7 +188,7 @@ Beta 13.12.09
|
||||||
162. rewrote auto-classify OK
|
162. rewrote auto-classify OK
|
||||||
163. rewrote sv_phys.c OK
|
163. rewrote sv_phys.c OK
|
||||||
164. remove vprogs.dll OK
|
164. remove vprogs.dll OK
|
||||||
165. finalize EventAPI
|
165. finalize EventAPI OK
|
||||||
166. move cl_input.c into client.dll OK
|
166. move cl_input.c into client.dll OK
|
||||||
167. fix all founded errors
|
167. fix all founded errors
|
||||||
168. release at 13/12/2009
|
168. release at 13/12/2009
|
||||||
|
|
|
@ -1670,7 +1670,7 @@ void R_ModifyColor( const ref_stage_t *pass )
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RGBGEN_LIGHTING_AMBIENT_ONLY:
|
case RGBGEN_LIGHTING_AMBIENT_ONLY:
|
||||||
if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) )
|
if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ))
|
||||||
{
|
{
|
||||||
vec4_t ambient;
|
vec4_t ambient;
|
||||||
|
|
||||||
|
|
|
@ -643,6 +643,7 @@ void R_DrawMeshes( void )
|
||||||
int i;
|
int i;
|
||||||
meshbuffer_t *meshbuf;
|
meshbuffer_t *meshbuf;
|
||||||
|
|
||||||
|
Tri_RenderCallback( false );
|
||||||
RI.previousentity = NULL;
|
RI.previousentity = NULL;
|
||||||
if( RI.meshlist->num_opaque_meshes )
|
if( RI.meshlist->num_opaque_meshes )
|
||||||
{
|
{
|
||||||
|
@ -652,8 +653,8 @@ void R_DrawMeshes( void )
|
||||||
R_BatchMeshBuffer( meshbuf, NULL );
|
R_BatchMeshBuffer( meshbuf, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
Tri_RenderCallback( false );
|
|
||||||
|
|
||||||
|
Tri_RenderCallback( true );
|
||||||
if( RI.meshlist->num_translucent_meshes )
|
if( RI.meshlist->num_translucent_meshes )
|
||||||
{
|
{
|
||||||
meshbuf = RI.meshlist->meshbuffer_translucent;
|
meshbuf = RI.meshlist->meshbuffer_translucent;
|
||||||
|
@ -662,8 +663,6 @@ void R_DrawMeshes( void )
|
||||||
R_BatchMeshBuffer( meshbuf, NULL );
|
R_BatchMeshBuffer( meshbuf, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
Tri_RenderCallback( true );
|
|
||||||
|
|
||||||
R_LoadIdentity();
|
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 )
|
int MapPlaneTypeForNormal( const vec3_t normal )
|
||||||
|
@ -125,7 +125,7 @@ int CreateNewFloatPlane( vec3_t normal, vec_t dist )
|
||||||
p = &mapplanes[nummapplanes];
|
p = &mapplanes[nummapplanes];
|
||||||
VectorCopy( normal, p->normal );
|
VectorCopy( normal, p->normal );
|
||||||
p->dist = dist;
|
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 );
|
VectorSubtract( vec3_origin, normal, (p+1)->normal );
|
||||||
(p+1)->dist = -dist;
|
(p+1)->dist = -dist;
|
||||||
|
|
|
@ -53,6 +53,7 @@ byte* bsp_base;
|
||||||
bool bsp_halflife = false;
|
bool bsp_halflife = false;
|
||||||
dmiptexname_t *mipnames = NULL;
|
dmiptexname_t *mipnames = NULL;
|
||||||
int mip_count = 0;
|
int mip_count = 0;
|
||||||
|
file_t *detail_txt;
|
||||||
|
|
||||||
bool MipExist( const char *name )
|
bool MipExist( const char *name )
|
||||||
{
|
{
|
||||||
|
@ -67,10 +68,77 @@ bool MipExist( const char *name )
|
||||||
return FS_FileExists( 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 )
|
void Conv_BspTextures( const char *name, dlump_t *l, const char *ext )
|
||||||
{
|
{
|
||||||
dmiptexlump_t *m;
|
dmiptexlump_t *m;
|
||||||
string genericname;
|
string genericname;
|
||||||
|
const char *det_name;
|
||||||
mip_t *mip;
|
mip_t *mip;
|
||||||
int i, k;
|
int i, k;
|
||||||
int *dofs, size;
|
int *dofs, size;
|
||||||
|
@ -83,6 +151,8 @@ void Conv_BspTextures( const char *name, dlump_t *l, const char *ext )
|
||||||
m->nummiptex = LittleLong( m->nummiptex );
|
m->nummiptex = LittleLong( m->nummiptex );
|
||||||
dofs = m->dataofs;
|
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 ));
|
mipnames = Mem_Realloc( basepool, mipnames, m->nummiptex * sizeof( dmiptexname_t ));
|
||||||
mip_count = 0;
|
mip_count = 0;
|
||||||
|
|
||||||
|
@ -94,9 +164,15 @@ void Conv_BspTextures( const char *name, dlump_t *l, const char *ext )
|
||||||
|
|
||||||
// needs to simulate directly loading
|
// needs to simulate directly loading
|
||||||
mip = (mip_t *)((byte *)m + dofs[i]);
|
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
|
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
|
// check for '*' symbol issues
|
||||||
k = com.strlen( com.strrchr( mip->name, '*' ));
|
k = com.strlen( com.strrchr( mip->name, '*' ));
|
||||||
if( k ) mip->name[com.strlen(mip->name)-k] = '!'; // quake1 issues
|
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
|
ConvMIP( va("%s/%s", name, mip->name ), buffer, size, ext ); // convert it
|
||||||
}
|
}
|
||||||
mip_count = 0; // freed and invaliadte
|
mip_count = 0; // freed and invaliadte
|
||||||
|
FS_Close( detail_txt );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Reference in New Issue