15 Mar 2010

This commit is contained in:
g-cont 2010-03-15 00:00:00 +03:00 committed by Alibek Omarov
parent 2e88e96834
commit 6d88c3904b
69 changed files with 2558 additions and 2109 deletions

View File

@ -229,11 +229,19 @@ SOURCE=.\global\r_particle.cpp
# End Source File
# Begin Source File
SOURCE=.\global\r_tempents.cpp
# End Source File
# Begin Source File
SOURCE=.\global\r_weather.cpp
# End Source File
# Begin Source File
SOURCE=.\global\tempents.cpp
SOURCE=.\global\studio.cpp
# End Source File
# Begin Source File
SOURCE=.\global\sv_tent.cpp
# End Source File
# Begin Source File

View File

@ -9,6 +9,7 @@
#include "studio_ref.h"
#include "hud.h"
#include "r_particle.h"
#include "r_tempents.h"
#include "r_beams.h"
#include "ev_hldm.h"
#include "pm_shared.h"
@ -40,7 +41,7 @@ static HUD_FUNCTIONS gFunctionTable =
HUD_Shutdown,
HUD_RenderCallback,
HUD_CreateEntities,
HUD_UpdateEntity,
HUD_AddVisibleEntity,
HUD_StudioEvent,
HUD_StudioFxTransform,
V_CalcRefdef,
@ -84,6 +85,9 @@ int HUD_VidInit( void )
if( g_pViewRenderBeams )
g_pViewRenderBeams->ClearBeams();
if ( g_pTempEnts )
g_pTempEnts->Clear();
ResetRain ();
gHUD.VidInit();
@ -91,6 +95,30 @@ int HUD_VidInit( void )
return 1;
}
void HUD_ShutdownEffects( void )
{
if ( g_pParticleSystems )
{
// init partsystem
delete g_pParticleSystems;
g_pParticleSystems = NULL;
}
if ( g_pViewRenderBeams )
{
// init render beams
delete g_pViewRenderBeams;
g_pViewRenderBeams = NULL;
}
if ( g_pTempEnts )
{
// init client tempents
delete g_pTempEnts;
g_pTempEnts = NULL;
}
}
void HUD_Init( void )
{
g_engfuncs.pfnAddCommand ("noclip", NULL, "enable or disable no clipping mode" );
@ -105,22 +133,11 @@ void HUD_Init( void )
g_engfuncs.pfnAddCommand ("fov", NULL, "set client field of view" );
g_engfuncs.pfnAddCommand ("fly", NULL, "fly mode (flight)" );
if ( g_pParticleSystems )
{
// init partsystem
delete g_pParticleSystems;
g_pParticleSystems = NULL;
}
if ( g_pViewRenderBeams )
{
// init render beams
delete g_pViewRenderBeams;
g_pViewRenderBeams = NULL;
}
HUD_ShutdownEffects ();
g_pParticleSystems = new ParticleSystemManager();
g_pViewRenderBeams = new CViewRenderBeams();
g_pTempEnts = new CTempEnts();
InitRain(); // init weather system
@ -159,7 +176,7 @@ int HUD_Redraw( float flTime, int state )
return 1;
}
void HUD_UpdateEntityVars( edict_t *ent, skyportal_t *sky, const entity_state_t *state, const entity_state_t *prev )
void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const entity_state_t *prev )
{
int i;
float m_fLerp;
@ -280,12 +297,16 @@ void HUD_UpdateEntityVars( edict_t *ent, skyportal_t *sky, const entity_state_t
ent->v.oldorigin = state->oldorigin;
break;
case ED_SKYPORTAL:
// setup sky portal
sky->vieworg = ent->v.origin;
sky->viewanglesOffset.x = sky->viewanglesOffset.z = 0.0f;
sky->viewanglesOffset.y = gHUD.m_flTime * ent->v.angles[1];
sky->fov = ent->v.fov;
sky->scale = (ent->v.scale ? 1.0f / ent->v.scale : 0); // critical stuff
{
skyportal_t *sky = &gpViewParams->skyportal;
// setup sky portal
sky->vieworg = ent->v.origin;
sky->viewanglesOffset.x = sky->viewanglesOffset.z = 0.0f;
sky->viewanglesOffset.y = gHUD.m_flTime * ent->v.angles[1];
sky->scale = (ent->v.scale ? 1.0f / ent->v.scale : 0.0f ); // critical stuff
sky->fov = ent->v.fov;
}
break;
case ED_BEAM:
ent->v.oldorigin = state->oldorigin; // beam endpoint
@ -318,6 +339,64 @@ void HUD_UpdateEntityVars( edict_t *ent, skyportal_t *sky, const entity_state_t
ent->v.pContainingEntity = ent;
}
int HUD_AddVisibleEntity( edict_t *pEnt, int ed_type )
{
float oldScale, oldRenderAmt;
float shellScale = 1.0f;
int result;
if( pEnt->v.renderfx == kRenderFxGlowShell )
{
oldRenderAmt = pEnt->v.renderamt;
oldScale = pEnt->v.scale;
pEnt->v.renderamt = 255; // clear amount
}
result = CL_AddEntity( pEnt, ed_type, -1 );
if( pEnt->v.renderfx == kRenderFxGlowShell )
{
shellScale = (oldRenderAmt * 0.0015f); // shellOffset
pEnt->v.scale = oldScale + shellScale; // sets new scale
pEnt->v.renderamt = 128;
// render glowshell
result |= CL_AddEntity( pEnt, ed_type, g_pTempEnts->hSprGlowShell );
// restore parms
pEnt->v.scale = oldScale;
pEnt->v.renderamt = oldRenderAmt;
}
// add in muzzleflash effect
if( ed_type == ED_VIEWMODEL && pEnt->v.effects & EF_MUZZLEFLASH )
{
pEnt->v.effects &= ~EF_MUZZLEFLASH;
g_pTempEnts->WeaponFlash( pEnt, 1 );
}
// add light effect
if( pEnt->v.effects & EF_LIGHT )
{
g_pTempEnts->AllocDLight( pEnt->v.origin, 200, 0.01f, 0 );
g_pTempEnts->RocketFlare( pEnt->v.origin );
}
return result;
}
void HUD_CreateEntities( void )
{
EV_UpdateBeams (); // egon use this
EV_UpdateLaserSpot (); // predictable laserspot
// add in any game specific objects here
g_pViewRenderBeams->UpdateTempEntBeams( );
g_pTempEnts->Update();
}
void HUD_UpdateOnRemove( edict_t *pEdict )
{
// move TE_BEAMTRAIL, kill other beams
@ -326,10 +405,9 @@ void HUD_UpdateOnRemove( edict_t *pEdict )
void HUD_Reset( void )
{
gHUD.VidInit();
HUD_VidInit ();
}
void HUD_StartFrame( void )
{
// clear list of server beams after each frame
@ -347,6 +425,8 @@ void HUD_Shutdown( void )
{
gHUD.m_Sound.Close();
HUD_ShutdownEffects ();
IN_Shutdown ();
// perform shutdown operations

View File

@ -128,6 +128,9 @@ inline void CL_PlaySound( int iSound, float flVolume, Vector &pos, float pitch =
#define GetLerpFrac (*g_engfuncs.pfnGetLerpFrac)
#define GetViewModel (*g_engfuncs.pfnGetViewModel)
#define GetModelPtr (*g_engfuncs.pfnGetModelPtr)
#define CL_GetPaletteColor (*g_engfuncs.pEfxAPI->R_GetPaletteColor)
#define CL_AddTempEntity (*g_engfuncs.pEfxAPI->R_AddTempEntity)
#define CL_AddEntity (*g_engfuncs.pEfxAPI->R_AddEntity)
#define GET_ATTACHMENT (*g_engfuncs.pfnGetAttachment)
#define POINT_CONTENTS (*g_engfuncs.pfnPointContents)
#define TRACE_LINE (*g_engfuncs.pfnTraceLine)

View File

@ -6,7 +6,7 @@
#include "extdll.h"
#include "utils.h"
#include "ev_hldm.h"
#include "effects_api.h"
#include "r_tempents.h"
extern "C"
{
@ -56,7 +56,7 @@ void EV_HookEvents( void )
//=================
void EV_CreateTracer( float *start, float *end )
{
g_engfuncs.pEfxAPI->R_TracerEffect( start, end );
g_pTempEnts->TracerEffect( start, end );
}
@ -120,7 +120,7 @@ void EV_EjectBrass( float *origin, float *velocity, float rotation, int model, i
{
Vector endpos = Vector( 0.0f, rotation, 0.0f );
g_engfuncs.pEfxAPI->R_TempModel( origin, velocity, endpos, RANDOM_LONG( 30, 50 ), model, soundtype );
g_pTempEnts->TempModel( origin, velocity, endpos, RANDOM_LONG( 30, 50 ), model, soundtype );
}

View File

@ -6,6 +6,7 @@
#include "extdll.h"
#include "utils.h"
#include "r_beams.h"
#include "r_tempents.h"
#include "effects_api.h"
#include "pm_materials.h"
#include "pm_movevars.h"
@ -186,106 +187,6 @@ float EV_HLDM_PlayTextureSound( int idx, TraceResult *ptr, float *vecSrc, float
return fvolbar;
}
//======================
// MIRROR UTILS
//======================
Vector EV_GetMirrorOrigin( int mirror_index, Vector pos )
{
Vector result = pos;
if( mirror_index < 0 || mirror_index >= gHUD.numMirrors )
return g_vecZero;
switch( gHUD.Mirrors[mirror_index].type )
{
case 0:
result[0] = gHUD.Mirrors[mirror_index].origin[0] * 2 - pos[0];
break;
case 1:
result[1] = gHUD.Mirrors[mirror_index].origin[1] * 2 - pos[1];
break;
default:
case 2:
result[2] = gHUD.Mirrors[mirror_index].origin[2] * 2 - pos[2];
break;
}
return result;
}
Vector EV_GetMirrorAngles( int mirror_index, Vector angles )
{
Vector result = angles;
if( mirror_index < 0 || mirror_index >= gHUD.numMirrors )
return g_vecZero;
switch( gHUD.Mirrors[mirror_index].type )
{
case 0:
result.x = -result.x;
break;
case 1:
result.y = -result.y;
break;
default:
case 2:
result.z = -result.z;
break;
}
return result;
}
Vector EV_MirrorVector( Vector angles )
{
Vector result = angles;
if( gHUD.numMirrors )
{
for( int imc = 0; imc < gHUD.numMirrors; imc++ )
{
if( !gHUD.Mirrors[imc].enabled )
continue;
result = EV_GetMirrorAngles( imc, angles );
}
}
return result;
}
Vector EV_MirrorPos( Vector endpos )
{
Vector mirpos;
mirpos.Init();
if( gHUD.numMirrors )
{
for( int imc = 0; imc < gHUD.numMirrors; imc++ )
{
if( !gHUD.Mirrors[imc].enabled )
continue;
Vector delta;
float dist;
delta = gHUD.Mirrors[imc].origin - endpos;
dist = delta.Length();
if( gHUD.Mirrors[imc].radius < dist )
continue;
mirpos = EV_GetMirrorOrigin( imc, endpos );
}
}
return mirpos;
}
//======================
// END MIRROR UTILS
//======================
//======================
// START DECALS
//======================
@ -302,7 +203,7 @@ void EV_HLDM_FindHullIntersection( int idx, Vector vecSrc, TraceResult pTrace, f
vecHullEnd = vecSrc + ((vecHullEnd - vecSrc ) * 2);
UTIL_TraceLine( vecSrc, vecHullEnd, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &tmpTrace );
UTIL_TraceLine( vecSrc, vecHullEnd, dont_ignore_monsters, GetEntityByIndex( idx ), &tmpTrace );
if ( tmpTrace.flFraction < 1.0 )
{
@ -320,7 +221,7 @@ void EV_HLDM_FindHullIntersection( int idx, Vector vecSrc, TraceResult pTrace, f
vecEnd.y = vecHullEnd.y + minmaxs[j][1];
vecEnd.z = vecHullEnd.z + minmaxs[k][2];
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &tmpTrace );
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx ), &tmpTrace );
if ( tmpTrace.flFraction < 1.0 )
{
@ -368,10 +269,7 @@ void EV_HLDM_CrowbarDecalTrace( TraceResult *pTrace, char *decalName )
if( decalName && decalName[0] && pEnt && ( pEnt->v.solid == SOLID_BSP || pEnt->v.movetype == MOVETYPE_PUSHSTEP ) )
{
HSPRITE decal_tex = g_engfuncs.pEfxAPI->CL_DecalIndexFromName( decalName );
CL_PlaceDecal( pTrace->vecEndPos, pEnt, decal_tex );
Vector mirpos = EV_MirrorPos( pTrace->vecEndPos );
if( mirpos != g_vecZero ) CL_PlaceDecal( mirpos, pEnt, decal_tex );
g_pTempEnts->PlaceDecal( pTrace->vecEndPos, pEnt, decal_tex );
}
}
@ -410,15 +308,8 @@ void EV_HLDM_GunshotDecalTrace( TraceResult *pTrace, char *decalName )
{
HSPRITE decal_tex = g_engfuncs.pEfxAPI->CL_DecalIndexFromName( decalName );
CL_PlaceDecal( pTrace->vecEndPos, pEnt, decal_tex );
g_pTempEnts->PlaceDecal( pTrace->vecEndPos, pEnt, decal_tex );
CL_BulletParticles( pTrace->vecEndPos, Vector( 0, 0, -1 ));
Vector mirpos = EV_MirrorPos( pTrace->vecEndPos );
if( mirpos != g_vecZero )
{
CL_PlaceDecal( mirpos, pEnt, decal_tex );
CL_BulletParticles( mirpos, Vector( 0, 0, -1 ));
}
}
}
@ -557,7 +448,7 @@ void EV_HLDM_FireBullets( int idx, Vector forward, Vector right, Vector up, int
vecEnd = vecSrc + flDistance * vecDir;
}
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &tr );
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx ), &tr );
tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.vecEndPos, forward, right, iBulletType, iTracerFreq, tracerCount );
@ -661,11 +552,11 @@ void EV_FireCrowbar( event_args_t *args )
vecEnd = vecSrc + forward * 32;
// make trace
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &tr );
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx ), &tr );
if ( tr.flFraction >= 1.0 )
{
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &tr );
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx ), &tr );
if ( tr.flFraction < 1.0 )
{
@ -806,8 +697,14 @@ void EV_FireGlock1( event_args_t *args )
EV_MuzzleFlash();
if( args->bparam2 ) HUD_MuzzleFlash( view, 2, "17" ); // silence mode
else HUD_MuzzleFlash( view, 1, "11" ); // normal flash
if( args->bparam2 )
{
g_pTempEnts->MuzzleFlash( view, 2, 17 ); // silence mode
}
else
{
g_pTempEnts->MuzzleFlash( view, 1, 11 ); // normal flash
}
V_PunchAxis( 0, -2.0 );
}
@ -1074,6 +971,14 @@ void EV_SpinGauss( event_args_t *args )
int iSoundState = args->bparam1 ? SND_CHANGE_PITCH : 0;
g_engfuncs.pEventAPI->EV_PlaySound( GetEntityByIndex( args->entindex ), args->origin, CHAN_WEAPON, "ambience/pulsemachine.wav", 1.0, ATTN_NORM, iSoundState, pitch );
if( EV_IsLocal( args->entindex ))
{
edict_t *view = GetViewModel();
// change framerate from 1.0 to 2.5
view->v.framerate = (float)pitch / PITCH_NORM;
}
}
/*
@ -1096,23 +1001,21 @@ void EV_FireGauss( event_args_t *args )
Vector origin = args->origin;
Vector angles = args->angles;
Vector velocity = args->velocity;
Vector mangles;
int m_fPrimaryFire = args->bparam1;
int m_iWeaponVolume = GAUSS_PRIMARY_FIRE_VOLUME;
Vector vecSrc, vecDest;
Vector vecMirrorSrc, vecMirrorDest; //env_mirror use this
edict_t *pentIgnore;
TraceResult tr, mtr, beam_tr;
TraceResult tr, beam_tr;
float flMaxFrac = 1.0;
int nTotal = 0;
int fHasPunched = 0;
int fFirstBeam = 1;
int nMaxHits = 10;
edict_t *pEntity, *pMEntity;
edict_t *pEntity;
int m_iBeam, m_iGlow, m_iBalls;
Vector up, right, forward;
Vector forward;
idx = args->entindex;
@ -1130,13 +1033,7 @@ void EV_FireGauss( event_args_t *args )
AngleVectors( angles, forward, NULL, NULL );
mangles = EV_MirrorVector( angles );
AngleVectors( mangles, right, NULL, NULL );
vecMirrorSrc = EV_MirrorPos( vecSrc );
vecDest = vecSrc + forward * 8192;
vecMirrorDest = vecMirrorSrc + right * 8192;
if ( EV_IsLocal( idx ) )
{
@ -1150,8 +1047,7 @@ void EV_FireGauss( event_args_t *args )
{
nMaxHits--;
UTIL_TraceLine( vecSrc, vecDest, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &tr );
UTIL_TraceLine( vecMirrorSrc, vecMirrorDest, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &mtr );
UTIL_TraceLine( vecSrc, vecDest, dont_ignore_monsters, GetEntityByIndex( idx ), &tr );
if ( tr.fAllSolid )
break;
@ -1168,14 +1064,6 @@ void EV_FireGauss( event_args_t *args )
g_pViewRenderBeams->CreateBeamEntPoint( idx | 0x1000, tr.vecEndPos, m_iBeam, 0.1,
m_fPrimaryFire ? 1.0 : 2.5,0.0,m_fPrimaryFire ? 128.0 : flDamage, 0, 0, 0,
m_fPrimaryFire ? 255 : 255, m_fPrimaryFire ? 128 : 255, m_fPrimaryFire ? 0 : 255 );
if( vecMirrorDest != g_vecZero && vecMirrorSrc != g_vecZero )
{
g_pViewRenderBeams->CreateBeamPoints( vecMirrorSrc, mtr.vecEndPos, m_iBeam,
0.1f, m_fPrimaryFire ? 1.0 : 2.5, 0.0, m_fPrimaryFire ? 128.0 : flDamage,
0, 0, 0, m_fPrimaryFire ? 255 : 255, m_fPrimaryFire ? 128 : 255,
m_fPrimaryFire ? 0 : 255 );
}
}
else
{
@ -1185,7 +1073,6 @@ void EV_FireGauss( event_args_t *args )
}
pEntity = tr.pHit;
pMEntity = mtr.pHit;
if ( pEntity == NULL )
break;
@ -1213,14 +1100,12 @@ void EV_FireGauss( event_args_t *args )
vecSrc = tr.vecEndPos + forward * 8.0f;
vecDest = vecSrc + forward * 8192.0f;
g_engfuncs.pEfxAPI->R_TempSprite( tr.vecEndPos, NULL, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage * n / 255.0, flDamage * n * 0.5 * 0.1, FTENT_FADEOUT );
if( vecMirrorDest != g_vecZero && vecMirrorSrc != g_vecZero )
g_engfuncs.pEfxAPI->R_TempSprite( mtr.vecEndPos, NULL, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage * n / 255.0, flDamage * n * 0.5 * 0.1, FTENT_FADEOUT );
g_pTempEnts->TempSprite( tr.vecEndPos, g_vecZero, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage * n / 255.0, flDamage * n * 0.5 * 0.1, FTENT_FADEOUT );
Vector fwd;
fwd = tr.vecEndPos + tr.vecPlaneNormal;
g_engfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.vecEndPos, fwd, m_iBalls, 3, 0.1, RANDOM_FLOAT( 10, 20 ) / 100.0, 100, 255, 100 );
g_pTempEnts->Sprite_Trail( TE_SPRITETRAIL, tr.vecEndPos, fwd, m_iBalls, 3, 0.1, RANDOM_FLOAT( 10, 20 ) / 100.0, 100, 255, 100 );
// lose energy
if ( n == 0 )
@ -1236,9 +1121,7 @@ void EV_FireGauss( event_args_t *args )
// tunnel
EV_HLDM_DecalGunshot( &tr, BULLET_12MM );
g_engfuncs.pEfxAPI->R_TempSprite( tr.vecEndPos, NULL, 1.0, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT );
if( vecMirrorDest != g_vecZero && vecMirrorSrc != g_vecZero )
g_engfuncs.pEfxAPI->R_TempSprite( mtr.vecEndPos, NULL, 1.0, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT );
g_pTempEnts->TempSprite( tr.vecEndPos, g_vecZero, 1.0, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT );
// limit it to one hole punch
if( fHasPunched ) break;
@ -1251,7 +1134,7 @@ void EV_FireGauss( event_args_t *args )
start = tr.vecEndPos + forward * 8.0f;
UTIL_TraceLine( start, vecDest, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &beam_tr );
UTIL_TraceLine( start, vecDest, dont_ignore_monsters, GetEntityByIndex( idx ), &beam_tr );
if ( !beam_tr.fAllSolid )
{
@ -1260,7 +1143,7 @@ void EV_FireGauss( event_args_t *args )
// trace backwards to find exit point
UTIL_TraceLine( beam_tr.vecEndPos, tr.vecEndPos, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &beam_tr );
UTIL_TraceLine( beam_tr.vecEndPos, tr.vecEndPos, dont_ignore_monsters, GetEntityByIndex( idx ), &beam_tr );
delta = beam_tr.vecEndPos - tr.vecEndPos;
@ -1274,17 +1157,17 @@ void EV_FireGauss( event_args_t *args )
// absorption balls
{
Vector fwd = tr.vecEndPos - forward;
g_engfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.vecEndPos, fwd, m_iBalls, 3, 0.1, RANDOM_FLOAT( 10, 20 ) / 100.0, 100, 255, 100 );
g_pTempEnts->Sprite_Trail( TE_SPRITETRAIL, tr.vecEndPos, fwd, m_iBalls, 3, 0.1, RANDOM_FLOAT( 10, 20 ) / 100.0, 100, 255, 100 );
}
EV_HLDM_DecalGunshot( &beam_tr, BULLET_12MM );
g_engfuncs.pEfxAPI->R_TempSprite( beam_tr.vecEndPos, NULL, 0.1, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT );
g_pTempEnts->TempSprite( beam_tr.vecEndPos, g_vecZero, 0.1, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT );
// balls
{
Vector fwd = beam_tr.vecEndPos - forward;
g_engfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, beam_tr.vecEndPos, fwd, m_iBalls, (int)(flDamage * 0.3), 0.1, RANDOM_FLOAT( 10, 20 ) / 100.0, 200, 255, 40 );
g_pTempEnts->Sprite_Trail( TE_SPRITETRAIL, beam_tr.vecEndPos, fwd, m_iBalls, (int)(flDamage * 0.3), 0.1, RANDOM_FLOAT( 10, 20 ) / 100.0, 200, 255, 40 );
}
vecSrc = beam_tr.vecEndPos + forward;
@ -1301,19 +1184,14 @@ void EV_FireGauss( event_args_t *args )
{
// slug doesn't punch through ever with primary
// fire, so leave a little glowy bit and make some balls
g_engfuncs.pEfxAPI->R_TempSprite( tr.vecEndPos, NULL, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, 200.0 / 255.0, 0.3, FTENT_FADEOUT );
if( vecMirrorDest != g_vecZero && vecMirrorSrc != g_vecZero )
g_engfuncs.pEfxAPI->R_TempSprite( mtr.vecEndPos, NULL, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, 200.0 / 255.0, 0.3, FTENT_FADEOUT );
g_pTempEnts->TempSprite( tr.vecEndPos, g_vecZero, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, 200.0 / 255.0, 0.3, FTENT_FADEOUT );
// balls
{
Vector fwd;
int num_balls = RANDOM_FLOAT( 10, 20 );
fwd = tr.vecEndPos + tr.vecPlaneNormal;
g_engfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.vecEndPos, fwd, m_iBalls, 8, 0.6, num_balls / 100.0, 100, 255, 200 );
fwd = mtr.vecEndPos + mtr.vecPlaneNormal;
if( vecMirrorDest != g_vecZero && vecMirrorSrc != g_vecZero )
g_engfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, mtr.vecEndPos, fwd, m_iBalls, 8, 0.6, num_balls / 100.0, 100, 255, 200 );
g_pTempEnts->Sprite_Trail( TE_SPRITETRAIL, tr.vecEndPos, fwd, m_iBalls, 8, 0.6, num_balls / 100.0, 100, 255, 200 );
}
}
@ -1337,6 +1215,8 @@ void EV_FireGauss( event_args_t *args )
enum EGON_FIRESTATE { FIRE_OFF = 0, FIRE_CHARGE };
enum EGON_FIREMODE { FIRE_NARROW = 0, FIRE_WIDE };
#define EGON_PULSE_INTERVAL 0.1
#define EGON_DISCHARGE_INTERVAL 0.1
#define EGON_PRIMARY_VOLUME 450
#define EGON_BEAM_SPRITE "sprites/xbeam1.spr"
#define EGON_FLARE_SPRITE "sprites/XSpark1.spr"
@ -1344,19 +1224,10 @@ enum EGON_FIREMODE { FIRE_NARROW = 0, FIRE_WIDE };
#define EGON_SOUND_RUN "weapons/egon_run3.wav"
#define EGON_SOUND_STARTUP "weapons/egon_windup2.wav"
#define ARRAYSIZE( p ) (sizeof( p ) / sizeof( p[0] ))
Beam_t *m_pBeam = NULL;
Beam_t *m_pNoise = NULL;
Beam_t *pBeam;
Beam_t *pBeam2;
Beam_t *pMirBeam;
Beam_t *pMirBeam2;
TEMPENTITY *EndFlare;
TEMPENTITY *EndMirFlare;
// UNDONE : mirror beams don't update, end sprite don't drawing
bool b_mir = 0;
TEMPENTITY *m_pEndFlare = NULL;
void EV_EgonFire( event_args_t *args )
{
@ -1387,11 +1258,10 @@ void EV_EgonFire( event_args_t *args )
// Only play the weapon anims if I shot it.
// if ( EV_IsLocal( idx ) ) g_engfuncs.pEventAPI->EV_WeaponAnim ( EGON_FIRECYCLE, args->iparam1, 1.0f );
if ( iStartup == 1 && EV_IsLocal( idx ) && !pBeam && !pBeam2 && cl_lw->integer )
if ( iStartup == 1 && EV_IsLocal( idx ) && !m_pBeam && !m_pNoise && cl_lw->integer )
{
Vector vecSrc, vecEnd, origin, angles, forward, right, mangles;
Vector vecMirrorSrc, vecMirrorDest; // env_mirror use this
TraceResult tr, mtr;
Vector vecSrc, vecEnd, origin, angles, forward;
TraceResult tr;
edict_t *pl = GetEntityByIndex( idx );
@ -1399,18 +1269,11 @@ void EV_EgonFire( event_args_t *args )
{
angles = gHUD.m_vecAngles;
AngleVectors( angles, forward, NULL, NULL );
EV_GetGunPosition( args, vecSrc, pl->v.origin );
mangles = EV_MirrorVector( angles );
AngleVectors( mangles, right, NULL, NULL );
vecMirrorSrc = EV_MirrorPos( vecSrc );
EV_GetGunPosition( args, vecSrc, pl->v.origin );
vecEnd = vecSrc + forward * 2048;
vecMirrorDest = vecMirrorSrc + right * 2048;
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &tr );
// mirror trace
UTIL_TraceLine( vecMirrorSrc, vecMirrorDest, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &mtr );
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx ), &tr );
int iBeamModelIndex = g_engfuncs.pEventAPI->EV_FindModelIndex( EGON_BEAM_SPRITE );
@ -1420,32 +1283,66 @@ void EV_EgonFire( event_args_t *args )
if ( iFireMode == FIRE_WIDE )
{
pBeam = g_pViewRenderBeams->CreateBeamEntPoint( idx | 0x1000, tr.vecEndPos, iBeamModelIndex, 99999, 3.5, 0.2, 0.7, 55, 0, 0, r, g, b );
if ( pBeam ) pBeam->flags |= FBEAM_SINENOISE;
pBeam2 = g_pViewRenderBeams->CreateBeamEntPoint( idx | 0x1000, tr.vecEndPos, iBeamModelIndex, 99999, 5.0, 0.08, 0.7, 25, 0, 0, r, g, b );
if( vecMirrorDest != g_vecZero && vecMirrorSrc != g_vecZero && b_mir )
{
pMirBeam = g_pViewRenderBeams->CreateBeamPoints( vecMirrorSrc, mtr.vecEndPos, iBeamModelIndex, 99999, 3.5, 0.2, 0.7, 55, 0, 0, r, g, b );
if ( pMirBeam ) pBeam->flags |= FBEAM_SINENOISE;
pMirBeam2 = g_pViewRenderBeams->CreateBeamPoints( vecMirrorSrc, mtr.vecEndPos, iBeamModelIndex, 99999, 5.0, 0.08, 0.7, 25, 0, 0, r, g, b );
}
m_pBeam = g_pViewRenderBeams->CreateBeamEntPoint(
idx | 0x1000, // end entity & attachment
tr.vecEndPos, // start pos (sic!)
iBeamModelIndex, // beamSprite
99999, // life
4.0, // width
2.0, // amplitude (noise)
100, // brightness
55, // scrollSpeed
0, // startframe
0, // framerate
r, g, b ); // color
if ( m_pBeam ) m_pBeam->SetFlags( FBEAM_SINENOISE );
m_pNoise = g_pViewRenderBeams->CreateBeamEntPoint(
idx | 0x1000, // end entity & attachment
tr.vecEndPos, // start pos (sic!)
iBeamModelIndex, // beamSprite
99999, // life
5.5, // width
0.08, // amplitude (noise)
100, // brightness
2.5, // scrollSpeed
0, // startframe
0, // framerate
50, 50, 255 ); // color
}
else
{
pBeam = g_pViewRenderBeams->CreateBeamEntPoint( idx | 0x1000, tr.vecEndPos, iBeamModelIndex, 99999, 1.5, 0.1, 0.7, 55, 0, 0, r, g, b );
if ( pBeam ) pBeam->flags |= FBEAM_SINENOISE;
pBeam2 = g_pViewRenderBeams->CreateBeamEntPoint( idx | 0x1000, tr.vecEndPos, iBeamModelIndex, 99999, 5.0, 0.08, 0.7, 25, 0, 0, r, g, b );
if( vecMirrorDest != g_vecZero && vecMirrorSrc != g_vecZero && b_mir )
{
pMirBeam = g_pViewRenderBeams->CreateBeamPoints( vecMirrorSrc, mtr.vecEndPos, iBeamModelIndex, 99999, 1.5, 0.1, 0.7, 55, 0, 0, r, g, b );
if ( pMirBeam ) pBeam->flags |= FBEAM_SINENOISE;
pMirBeam2 = g_pViewRenderBeams->CreateBeamPoints( vecMirrorSrc, mtr.vecEndPos, iBeamModelIndex, 99999, 5.0, 0.08, 0.7, 25, 0, 0, r, g, b );
}
m_pBeam = g_pViewRenderBeams->CreateBeamEntPoint(
idx | 0x1000, // end entity & attachment
tr.vecEndPos, // start pos (sic!)
iBeamModelIndex, // beamSprite
99999, // life
1.5, // width
0.5, // amplitude (noise)
100, // brightness
5.5, // scrollSpeed
0, // startframe
0, // framerate
r, g, b ); // color
if ( m_pBeam ) m_pBeam->SetFlags( FBEAM_SINENOISE );
m_pNoise = g_pViewRenderBeams->CreateBeamEntPoint(
idx | 0x1000, // end entity & attachment
tr.vecEndPos, // start pos (sic!)
iBeamModelIndex, // beamSprite
99999, // life
5.5, // width
0.2, // amplitude (noise)
100, // brightness
2.5, // scrollSpeed
0, // startframe
0, // framerate
80, 120, 255 ); // color
}
EndFlare = g_engfuncs.pEfxAPI->R_TempSprite( tr.vecEndPos, NULL, 1.0, m_iFlare, kRenderGlow, kRenderFxNoDissipation, 255, 9999, FTENT_SPRANIMATE );
if( vecMirrorDest != g_vecZero && vecMirrorSrc != g_vecZero && b_mir )
EndMirFlare = g_engfuncs.pEfxAPI->R_TempSprite( mtr.vecEndPos, NULL, 1.0, m_iFlare, kRenderGlow, kRenderFxNoDissipation, 255, 9999, FTENT_SPRANIMATE );
m_pEndFlare = g_pTempEnts->TempSprite( tr.vecEndPos, g_vecZero, 1.0, m_iFlare, kRenderGlow, kRenderFxNoDissipation, 1.0, 9999, FTENT_SPRCYCLE );
}
}
}
@ -1459,52 +1356,52 @@ void EV_EgonStop( event_args_t *args )
g_engfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, EGON_SOUND_RUN );
if ( args->iparam1 )
if ( args->bparam2 )
g_engfuncs.pEventAPI->EV_PlaySound( GetEntityByIndex( idx ), origin, CHAN_WEAPON, EGON_SOUND_OFF, 0.98, ATTN_NORM, 0, 100 );
if ( EV_IsLocal( idx ) )
{
if ( pBeam )
int iFireMode = args->iparam2;
if ( m_pBeam )
{
pBeam->die = 0.0f;
pBeam = NULL;
m_pBeam->die = 0.0f;
m_pBeam = NULL;
}
if ( pBeam2 )
if ( m_pNoise )
{
pBeam2->die = 0.0f;
pBeam2 = NULL;
m_pNoise->die = 0.0f;
m_pNoise = NULL;
}
if ( pMirBeam )
if ( m_pEndFlare )
{
pMirBeam->die = 0.0f;
pMirBeam = NULL;
if ( iFireMode == FIRE_WIDE )
{
// m_pSprite->Expand( 10, 500 );
m_pEndFlare->flags = FTENT_SCALE|FTENT_FADEOUT;
m_pEndFlare->fadeSpeed = 3.0f;
}
else
{
// UTIL_Remove( m_pSprite );
m_pEndFlare->die = 0.0f;
}
m_pEndFlare = NULL;
}
if ( pMirBeam2 )
{
pMirBeam2->die = 0.0f;
pMirBeam2 = NULL;
}
if( EndFlare )
{
EndFlare->die = 0.0f;
EndFlare = NULL;
}
if( EndMirFlare )
{
EndMirFlare->die = 0.0f;
EndMirFlare = NULL;
}
g_engfuncs.pEventAPI->EV_WeaponAnim( EGON_FIRESTOP, args->iparam2, 1.0f );
g_engfuncs.pEventAPI->EV_WeaponAnim( EGON_FIRESTOP, args->iparam1, 1.0f );
}
}
void EV_UpdateBeams ( void )
{
if ( !pBeam && !pBeam2 ) return;
if ( !m_pBeam && !m_pNoise ) return;
Vector forward, vecSrc, vecEnd, origin, angles, right, mangles;
Vector vecMirrorSrc, vecMirrorDest; //env_mirror use this
TraceResult tr, mtr;
Vector forward, vecSrc, vecEnd, origin, angles;
TraceResult tr;
float timedist;
edict_t *pthisplayer = GetLocalPlayer();
int idx = pthisplayer->serialnumber;
@ -1518,51 +1415,52 @@ void EV_UpdateBeams ( void )
vecSrc = origin;
vecEnd = vecSrc + forward * 2048;
mangles = EV_MirrorVector( angles );
AngleVectors( mangles, right, NULL, NULL );
vecMirrorSrc = EV_MirrorPos( vecSrc );
vecMirrorDest = vecMirrorSrc + right * 2048;
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &tr );
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, GetEntityByIndex( idx ), &tr );
// mirror trace
UTIL_TraceLine( vecMirrorSrc, vecMirrorDest, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &mtr );
// HACKHACK: extract firemode from beamWidth
int iFireMode = ( m_pBeam->width == 4.0 ) ? FIRE_WIDE : FIRE_NARROW;
if ( pBeam )
// calc timedelta for beam effects
switch( iFireMode )
{
pBeam->attachment[1] = tr.vecEndPos;
pBeam->die = gpGlobals->time + 0.1f; // We keep it alive just a little bit forward in the future, just in case.
case FIRE_NARROW:
if ( m_pBeam->m_flDmgTime < gpGlobals->time )
{
m_pBeam->m_flDmgTime = gpGlobals->time + EGON_PULSE_INTERVAL;
}
timedist = ( m_pBeam->m_flDmgTime - gpGlobals->time ) / EGON_DISCHARGE_INTERVAL;
break;
case FIRE_WIDE:
if ( m_pBeam->m_flDmgTime < gpGlobals->time )
{
m_pBeam->m_flDmgTime = gpGlobals->time + EGON_PULSE_INTERVAL;
}
timedist = ( m_pBeam->m_flDmgTime - gpGlobals->time ) / EGON_DISCHARGE_INTERVAL;
break;
}
if ( pBeam2 )
{
pBeam2->attachment[1] = tr.vecEndPos;
pBeam2->die = gpGlobals->time + 0.1f; // We keep it alive just a little bit forward in the future, just in case.
}
// clamp and inverse
timedist = bound( 0.0f, timedist, 1.0f );
timedist = 1.0f - timedist;
if ( pMirBeam )
{
pMirBeam->attachment[1] = mtr.vecEndPos;
pMirBeam->die = gpGlobals->time + 0.1f; // We keep it alive just a little bit forward in the future, just in case.
}
m_pBeam->SetEndPos( tr.vecEndPos );
m_pBeam->SetBrightness( 255 - ( timedist * 180 ));
m_pBeam->SetWidth( 40 - ( timedist * 20 ));
m_pBeam->die = gpGlobals->time + 0.1f; // We keep it alive just a little bit forward in the future, just in case.
if ( pMirBeam2 )
{
pMirBeam2->attachment[1] = mtr.vecEndPos;
pMirBeam2->die = gpGlobals->time + 0.1f; // We keep it alive just a little bit forward in the future, just in case.
}
if ( iFireMode == FIRE_WIDE )
m_pBeam->SetColor( 30 + (25 * timedist), 30 + (30 * timedist), 64 + 80 * fabs( sin( gpGlobals->time * 10 )));
else
m_pBeam->SetColor( 60 + (25 * timedist), 120 + (30 * timedist), 64 + 80 * fabs( sin( gpGlobals->time * 10 )));
if( EndFlare )
{
EndFlare->tentOffset = tr.vecEndPos;
EndFlare->die = gpGlobals->time + 0.1f;
}
m_pNoise->SetEndPos( tr.vecEndPos );
m_pNoise->die = gpGlobals->time + 0.1f; // We keep it alive just a little bit forward in the future, just in case.
if( EndMirFlare )
if( m_pEndFlare )
{
EndMirFlare->tentOffset = mtr.vecEndPos;
EndMirFlare->die = gpGlobals->time + 0.1f;
m_pEndFlare->origin = tr.vecEndPos;
m_pEndFlare->die = gpGlobals->time + 0.1f;
}
}
//======================
@ -1574,15 +1472,13 @@ void EV_UpdateBeams ( void )
//======================
void EV_Decals( event_args_t *args )
{
int idx;
TraceResult tr;
TraceResult *pTrace = &tr;
edict_t *pe;
idx = args->entindex;
// simulate trace result
memset( &tr, 0, sizeof( tr ));
pTrace->vecEndPos = args->origin;
pTrace->pHit = GetEntityByIndex( args->iparam1 );
pe = pTrace->pHit;
if( args->iparam2 == 0 )
{
@ -1649,14 +1545,79 @@ void EV_Decals( event_args_t *args )
if( args->iparam2 == 6 )
{
// monsters shoot
if ( pe && pe->v.solid == SOLID_BSP )
EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ));
if ( pTrace->pHit && pTrace->pHit->v.solid == SOLID_BSP )
EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pTrace->pHit ));
}
}
//======================
// DECALS END
//======================
//======================
// LASERSPOT START
//======================
TEMPENTITY *m_pLaserSpot = NULL;
void EV_UpdateLaserSpot( void )
{
edict_t *m_pPlayer = GetLocalPlayer();
edict_t *m_pWeapon = GetViewModel();
if( !m_pPlayer ) return;
if( m_pPlayer->v.effects & EF_LASERSPOT && !m_pLaserSpot && cl_lw->integer )
{
// create laserspot
int m_iSpotModel = g_engfuncs.pEventAPI->EV_FindModelIndex( "sprites/laserdot.spr" );
m_pLaserSpot = g_pTempEnts->TempSprite( g_vecZero, g_vecZero, 1.0, m_iSpotModel, kRenderGlow, kRenderFxNoDissipation, 1.0, 9999, FTENT_SPRCYCLE );
if( !m_pLaserSpot ) return;
m_pLaserSpot->renderColor = Vector( 200, 12, 12 );
// ALERT( at_console, "CLaserSpot::Create()\n" );
}
else if( !( m_pPlayer->v.effects & EF_LASERSPOT ) && m_pLaserSpot )
{
// destroy laserspot
// ALERT( at_console, "CLaserSpot::Killed()\n" );
m_pLaserSpot->die = 0.0f;
m_pLaserSpot = NULL;
return;
}
else if( !m_pLaserSpot )
{
// inactive
return;
}
ASSERT( m_pLaserSpot != NULL );
Vector forward, vecSrc, vecEnd, origin, angles;
TraceResult tr;
#if 1
GetViewAngles( angles ); // viewmodel doesn't have attachment
origin = m_pWeapon->v.origin;
#else
// TEST: give viewmodel first attachment
GET_ATTACHMENT( m_pWeapon, 1, origin, angles );
#endif
AngleVectors( angles, forward, NULL, NULL );
vecSrc = origin;
vecEnd = vecSrc + forward * 8192;
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, m_pPlayer, &tr );
// update laserspot endpos
m_pLaserSpot->origin = tr.vecEndPos;
m_pLaserSpot->die = gpGlobals->time + 0.1f;
}
//======================
// LASERSPOT END
//======================
//======================
// EFX END
//======================
@ -1682,7 +1643,7 @@ void EV_SnarkFire( event_args_t *args )
vecSrc = vecSrc - ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN );
// store off the old count
UTIL_TraceLine( vecSrc + forward * 20, vecSrc + forward * 64, dont_ignore_monsters, GetEntityByIndex( idx - 1 ), &tr );
UTIL_TraceLine( vecSrc + forward * 20, vecSrc + forward * 64, dont_ignore_monsters, GetEntityByIndex( idx ), &tr );
// find space to drop the thing.
if ( tr.fAllSolid == 0 && tr.fStartSolid == 0 && tr.flFraction > 0.25f )
@ -1697,7 +1658,7 @@ void EV_SnarkFire( event_args_t *args )
//======================
void EV_FireNull( event_args_t *args )
{
ALERT( at_console, "Fire Null!\n" );
ALERT( at_console, "Called null event!\n" );
}
//======================
// NULL END

View File

@ -126,6 +126,7 @@ void EV_HLDM_GunshotDecalTrace( TraceResult *pTrace, char *decalName );
void EV_HLDM_DecalGunshot( TraceResult *pTrace, int iBulletType );
int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount );
void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, float flSpreadX, float flSpreadY );
void EV_UpdateLaserSpot( void );
int EV_IsLocal( int idx );
int EV_IsPlayer( int idx );

View File

@ -674,7 +674,7 @@ void IN_Init( void )
cl_pitchspeed = CVAR_REGISTER( "cl_pitchspeed", "150", 0, "client pitch speed" );
cl_anglespeedkey = CVAR_REGISTER( "cl_anglespeedkey", "1.5", 0, "client anglespeed" );
cl_run = CVAR_REGISTER( "cl_run", "0", FCVAR_ARCHIVE, "keep client for always run mode" );
cl_lw = CVAR_REGISTER( "cl_lw", "1", FCVAR_ARCHIVE, "enable client weapon predicting" );
cl_lw = CVAR_REGISTER( "cl_lw", "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
cl_movespeedkey = CVAR_REGISTER ( "cl_movespeedkey", "2", 0, "global scale factor between run and walk" );
cl_pitchup = CVAR_REGISTER ( "cl_pitchup", "70", 0, "how many pitch up" );

View File

@ -8,6 +8,7 @@
#include "triangle_api.h"
#include "effects_api.h"
#include "ref_params.h"
#include "ev_hldm.h"
#include "hud.h"
#include "r_beams.h"
@ -138,7 +139,6 @@ inline void CBeamSegDraw::SpecifySeg( const Vector &vNormal )
}
void CBeamSegDraw::NextSeg( CBeamSeg *pSeg )
{
if ( m_nSegsDrawn > 0 )
@ -198,6 +198,44 @@ void Beam_t::Reset( void )
m_bCalculatedNoise = false;
}
void Beam_t::SetFlags( int iFlags )
{
if( iFlags & FBEAM_SINENOISE )
m_bCalculatedNoise = false;
flags |= iFlags;
}
void Beam_t::SetStartPos( const Vector pos )
{
attachment[0] = pos;
}
void Beam_t::SetEndPos( const Vector pos )
{
attachment[1] = pos;
}
void Beam_t::SetWidth( float flWidth )
{
width = endWidth = (flWidth * 0.1f);
}
void Beam_t::SetNoise( float flAmplitude )
{
amplitude = (flAmplitude * 0.1f);
}
void Beam_t::SetColor( float cR, float cG, float cB )
{
r = cR;
g = cG;
b = cB;
}
void Beam_t::SetBrightness( float flBrightness )
{
brightness = flBrightness;
}
const Vector& Beam_t::GetRenderOrigin( void )
{
@ -659,7 +697,7 @@ Beam_t *CViewRenderBeams::CreateBeamEntPoint( int nStartEntity, const Vector *pS
}
else
{
beamInfo.m_pStartEnt = GetEntityByIndex( BEAMENT_ENTITY( nStartEntity ) );
beamInfo.m_pStartEnt = LinkWithViewModel( GetEntityByIndex( BEAMENT_ENTITY( nStartEntity ) ) );
beamInfo.m_nStartAttachment = BEAMENT_ATTACHMENT( nStartEntity );
// don't start beams out of the PVS
@ -674,7 +712,7 @@ Beam_t *CViewRenderBeams::CreateBeamEntPoint( int nStartEntity, const Vector *pS
}
else
{
beamInfo.m_pEndEnt = GetEntityByIndex( BEAMENT_ENTITY( nEndEntity ) );
beamInfo.m_pEndEnt = LinkWithViewModel( GetEntityByIndex( BEAMENT_ENTITY( nEndEntity ) ) );
beamInfo.m_nEndAttachment = BEAMENT_ATTACHMENT( nEndEntity );
// Don't start beams out of the PVS
@ -740,7 +778,7 @@ Beam_t *CViewRenderBeams::CreateBeamEntPoint( BeamInfo_t &beamInfo )
return NULL;
pBeam->type = TE_BEAMPOINTS;
pBeam->flags = 0;
pBeam->flags = FBEAM_SINENOISE;
if ( beamInfo.m_pStartEnt )
{
@ -1684,6 +1722,22 @@ void CViewRenderBeams::AddServerBeam( edict_t *pEnvBeam )
}
}
//-----------------------------------------------------------------------------
// change client edict to viewmodel for local client in firstperson
//-----------------------------------------------------------------------------
edict_t *CViewRenderBeams::LinkWithViewModel( edict_t *pEnt )
{
if ( !pEnt || pEnt->free )
return NULL;
if ( EV_IsLocal( pEnt->serialnumber ) && ( gpViewParams->flags & RDF_THIRDPERSON ) == 0 )
{
return GetViewModel(); // change client edict to viewmodel edict
}
return pEnt; // unchanged
}
void CViewRenderBeams::UpdateBeams( int fTrans )
{
for( int i = 0; i < m_nNumServerBeams; i++ )
@ -1737,7 +1791,7 @@ void CViewRenderBeams::DrawBeam( edict_t *pbeam )
beamInfo.m_flWidth = pbeam->v.scale * 0.1f;
beamInfo.m_flEndWidth = beamInfo.m_flWidth;
beamInfo.m_flFadeLength = 0.0f; // will be set on first call UpdateBeam
beamInfo.m_flAmplitude = pbeam->v.body * 0.1f;
beamInfo.m_flAmplitude = (float)(pbeam->v.body * 0.1f);
beamInfo.m_flBrightness = pbeam->v.renderamt;
beamInfo.m_flSpeed = pbeam->v.animtime * 0.1f;
@ -1757,27 +1811,27 @@ void CViewRenderBeams::DrawBeam( edict_t *pbeam )
case BEAM_ENTS:
beam.type = TE_BEAMPOINTS;
beam.flags = FBEAM_STARTENTITY|FBEAM_ENDENTITY;
beam.entity[0] = pbeam->v.owner;
beam.entity[0] = LinkWithViewModel( pbeam->v.aiment );
beam.attachmentIndex[0] = pbeam->v.colormap & 0xFF;
beam.entity[1] = pbeam->v.aiment;
beam.entity[1] = LinkWithViewModel( pbeam->v.owner );
beam.attachmentIndex[1] = ((pbeam->v.colormap & 0xFF00)>>8);
beam.numAttachments = (pbeam->v.owner) ? ((pbeam->v.aiment) ? 2 : 1) : 0;
break;
case BEAM_LASER:
beam.type = TE_BEAMLASER;
beam.flags = FBEAM_STARTENTITY|FBEAM_ENDENTITY;
beam.entity[0] = pbeam->v.owner;
beam.entity[0] = LinkWithViewModel( pbeam->v.aiment );
beam.attachmentIndex[0] = pbeam->v.colormap & 0xFF;
beam.entity[1] = pbeam->v.aiment;
beam.entity[1] = LinkWithViewModel( pbeam->v.owner );
beam.attachmentIndex[1] = ((pbeam->v.colormap & 0xFF00)>>8);
beam.numAttachments = (pbeam->v.owner) ? ((pbeam->v.aiment) ? 2 : 1) : 0;
break;
case BEAM_ENTPOINT:
beam.type = TE_BEAMPOINTS;
beam.flags = 0;
beam.entity[0] = pbeam->v.owner;
beam.entity[0] = LinkWithViewModel( pbeam->v.aiment );
beam.attachmentIndex[0] = pbeam->v.colormap & 0xFF;
beam.entity[1] = pbeam->v.aiment;
beam.entity[1] = LinkWithViewModel( pbeam->v.owner );
beam.attachmentIndex[1] = ((pbeam->v.colormap & 0xFF00)>>8);
beam.numAttachments = 0;
beam.flags = 0;
@ -1869,7 +1923,7 @@ void DrawSegs( int noise_divisions, float *prgNoise, int modelIndex, float frame
segments = 16;
div = 1.0 / (segments - 1);
}
scale *= 100;
scale *= 10;
length = segments * (1.0f / 10);
}
else
@ -2134,6 +2188,7 @@ void DrawCylinder( int noise_divisions, float *prgNoise, int modelIndex, float f
scale = scale * length;
g_engfuncs.pTriAPI->Enable( TRI_SHADER );
g_engfuncs.pTriAPI->CullFace( TRI_NONE );
g_engfuncs.pTriAPI->RenderMode( (kRenderMode_t)rendermode );
g_engfuncs.pTriAPI->Bind( m_hSprite, 0 ); // GetSpriteTexture already set frame
@ -2168,6 +2223,7 @@ void DrawCylinder( int noise_divisions, float *prgNoise, int modelIndex, float f
g_engfuncs.pTriAPI->End();
g_engfuncs.pTriAPI->Disable( TRI_SHADER );
g_engfuncs.pTriAPI->CullFace( TRI_FRONT );
}
//-----------------------------------------------------------------------------

View File

@ -92,6 +92,15 @@ public:
const Vector& GetRenderOrigin( void );
// like CBeam
void SetFlags( int iFlags );
void SetStartPos( const Vector pos );
void SetEndPos( const Vector pos );
void SetWidth( float flWidth );
void SetNoise( float flAmplitude );
void SetColor( float r, float g, float b );
void SetBrightness( float flBrightness );
// bounding box...
Vector m_Mins;
Vector m_Maxs;
@ -153,6 +162,8 @@ public:
// for FBEAM_ONLYNOISEONCE
bool m_bCalculatedNoise;
float m_flDmgTime; // this is egon stuff
};
// ---------------------------------------------------------------- //
@ -257,6 +268,7 @@ public:
void UpdateBeams( int fTrans ); // main drawing func
private:
edict_t *LinkWithViewModel( edict_t *pEnt );
bool AttemptToDie( Beam_t *pBeam );
void FreeDeadTrails( BeamTrail_t **trail );
void UpdateBeam( Beam_t *pbeam, float frametime );

1142
client/global/r_tempents.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
//=======================================================================
// Copyright XashXT Group 2010 ©
// r_tempents.h - tempentities management
//=======================================================================
#ifndef R_TEMPENTS_H
#define R_TEMPENTS_H
//-----------------------------------------------------------------------------
// Purpose: implementation for temp entities
//-----------------------------------------------------------------------------
#include "tempents.h"
#include "effects_api.h"
#define MAX_TEMP_ENTITIES 500
#define TENT_WIND_ACCEL 50
#define MAX_MUZZLEFLASH 4
#define SHARD_VOLUME 12.0 // on shard ever n^3 units
class CTempEnts
{
public:
CTempEnts( void );
virtual ~CTempEnts( void );
void Update( void );
void Clear( void );
void TE_Prepare( TEMPENTITY *pTemp, model_t modelIndex );
int TE_Active( TEMPENTITY *pTemp );
int TE_Update( TEMPENTITY *pTemp ); // return false for instantly die
void BloodSprite( const Vector &org, int colorIndex, int modelIndex, int modelIndex2, float size );
void RicochetSprite( const Vector &pos, int modelIndex, float duration, float scale );
void MuzzleFlash( edict_t *pEnt, int iAttachment, int type );
void TempModel( const Vector &pos, const Vector &dir, const Vector &ang, float life, int modelIndex, int soundtype );
void BreakModel( const Vector &pos, const Vector &size, const Vector &dir, float random, float life, int count, int modelIndex, char flags );
void Bubbles( const Vector &mins, const Vector &maxs, float height, int modelIndex, int count, float speed );
void BubbleTrail( const Vector &start, const Vector &end, float height, int modelIndex, int count, float speed );
void Sprite_Explode( TEMPENTITY *pTemp, float scale, int flags );
void FizzEffect( edict_t *pent, int modelIndex, int density );
TEMPENTITY *DefaultSprite( const Vector &pos, int spriteIndex, float framerate );
void Sprite_Smoke( TEMPENTITY *pTemp, float scale );
TEMPENTITY *TempSprite( const Vector &pos, const Vector &dir, float scale, int modelIndex, int rendermode, int renderfx, float a, float life, int flags );
void AttachTentToPlayer( int client, int modelIndex, float zoffset, float life );
void KillAttachedTents( int client );
void Sprite_Spray( const Vector &pos, const Vector &dir, int modelIndex, int count, int speed, int iRand );
void Sprite_Trail( int type, const Vector &vecStart, const Vector &vecEnd, int modelIndex, int nCount, float flLife, float flSize, float flAmplitude, int nRenderamt, float flSpeed );
void RocketFlare( const Vector& pos );
void PlaySound( TEMPENTITY *pTemp, float damp );
void TracerEffect( const Vector &start, const Vector &end );
void WeaponFlash( edict_t *pEnt, int iAttachment );
void PlaceDecal( Vector pos, Vector dir, float scale, HSPRITE hDecal );
void PlaceDecal( Vector pos, edict_t *pEntity, HSPRITE hDecal );
void AllocDLight( Vector pos, float r, float g, float b, float radius, float time, int flags );
void AllocDLight( Vector pos, float radius, float time, int flags );
void RocketTrail( Vector start, Vector end, int type );
// Data
private:
int m_iTempEntFrame; // used for keyed dlights only
// Global temp entity pool
TEMPENTITY m_TempEnts[MAX_TEMP_ENTITIES];
// Free and active temp entity lists
TEMPENTITY *m_pFreeTempEnts;
TEMPENTITY *m_pActiveTempEnts;
// muzzle flash sprites
model_t m_iMuzzleFlash[MAX_MUZZLEFLASH];
void TempEntFree( TEMPENTITY *pTemp, TEMPENTITY *pPrev );
bool FreeLowPriorityTempEnt( void );
public:
TEMPENTITY *TempEntAllocNoModel( const Vector& org );
TEMPENTITY *TempEntAlloc( const Vector& org, model_t model );
TEMPENTITY *TempEntAllocHigh( const Vector& org, model_t model );
TEMPENTITY *TempEntAllocCustom( const Vector& org, int modelIndex, int high, ENTCALLBACK pfnCallback );
// misc utility shaders
HSPRITE hSprGlowShell; // glowshell shader
};
extern CTempEnts *g_pTempEnts;
#endif//R_TEMPENTS_H

156
client/global/studio.cpp Normal file
View File

@ -0,0 +1,156 @@
//=======================================================================
// Copyright XashXT Group 2010 ©
// studio.cpp - client side studio callbacks
//=======================================================================
#include "extdll.h"
#include "utils.h"
#include "studio_event.h"
#include "effects_api.h"
#include "pm_movevars.h"
#include "r_tempents.h"
#include "ev_hldm.h"
#include "r_beams.h"
#include "hud.h"
//======================
// DRAW BEAM EVENT
//======================
void EV_DrawBeam ( void )
{
// special effect for displacer
edict_t *view = GetViewModel();
float life = 1.05; // animtime
int m_iBeam = g_engfuncs.pEventAPI->EV_FindModelIndex( "sprites/plasma.spr" );
int idx = GetLocalPlayer()->serialnumber; // link with client
g_pViewRenderBeams->CreateBeamEnts( idx | 0x1000, idx | 0x2000, m_iBeam, life, 0.8, 0.5, 127, 0.6, 0, 10, 20, 100, 0 );
g_pViewRenderBeams->CreateBeamEnts( idx | 0x1000, idx | 0x3000, m_iBeam, life, 0.8, 0.5, 127, 0.6, 0, 10, 20, 100, 0 );
g_pViewRenderBeams->CreateBeamEnts( idx | 0x1000, idx | 0x4000, m_iBeam, life, 0.8, 0.5, 127, 0.6, 0, 10, 20, 100, 0 );
}
//======================
// Eject Shell
//======================
void EV_EjectShell( const dstudioevent_t *event, edict_t *entity )
{
vec3_t view_ofs, ShellOrigin, ShellVelocity, forward, right, up;
vec3_t origin = entity->v.origin;
vec3_t angles = entity->v.angles;
vec3_t velocity = entity->v.velocity;
float fR, fU;
int shell = g_engfuncs.pEventAPI->EV_FindModelIndex( event->options );
origin.z = origin.z - entity->v.view_ofs[2];
for( int j = 0; j < 3; j++ )
{
if( angles[j] < -180 )
angles[j] += 360;
else if( angles[j] > 180 )
angles[j] -= 360;
}
angles.x = -angles.x;
AngleVectors( angles, forward, right, up );
fR = RANDOM_FLOAT( 50, 70 );
fU = RANDOM_FLOAT( 100, 150 );
for ( int i = 0; i < 3; i++ )
{
ShellVelocity[i] = velocity[i] + right[i] * fR + up[i] * fU + forward[i] * 25;
ShellOrigin[i] = origin[i] + view_ofs[i] + up[i] * -12 + forward[i] * 20 + right[i] * 4;
}
EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
}
void HUD_StudioEvent( const dstudioevent_t *event, edict_t *entity )
{
float pitch;
Vector pos;
switch( event->event )
{
case 5001:
// MullzeFlash at attachment 1
g_pTempEnts->MuzzleFlash( entity, 1, atoi( event->options ));
break;
case 5011:
// MullzeFlash at attachment 2
g_pTempEnts->MuzzleFlash( entity, 2, atoi( event->options ));
break;
case 5021:
// MullzeFlash at attachment 3
g_pTempEnts->MuzzleFlash( entity, 3, atoi( event->options ));
break;
case 5031:
// MullzeFlash at attachment 4
g_pTempEnts->MuzzleFlash( entity, 4, atoi( event->options ));
break;
case 5002:
// SparkEffect at attachment 1
break;
case 5004:
// Client side sound
GET_ATTACHMENT( entity, 1, pos, NULL );
CL_PlaySound( event->options, 1.0f, pos );
break;
case 5005:
// Client side sound with random pitch
pitch = 85 + RANDOM_LONG( 0, 0x1F );
GET_ATTACHMENT( entity, 1, pos, NULL );
CL_PlaySound( event->options, RANDOM_FLOAT( 0.7f, 0.9f ), pos, pitch );
break;
case 5050:
// Special event for displacer
EV_DrawBeam ();
break;
case 5060:
EV_EjectShell( event, entity );
break;
default:
ALERT( at_console, "Unhandled client-side attachment %i ( %s )\n", event->event, event->options );
break;
}
}
void HUD_StudioFxTransform( edict_t *ent, float transform[4][4] )
{
switch( ent->v.renderfx )
{
case kRenderFxDistort:
case kRenderFxHologram:
if(!RANDOM_LONG( 0, 49 ))
{
int axis = RANDOM_LONG( 0, 1 );
float scale = RANDOM_FLOAT( 1, 1.484 );
if( axis == 1 ) axis = 2; // choose between x & z
transform[axis][0] *= scale;
transform[axis][1] *= scale;
transform[axis][2] *= scale;
}
else if(!RANDOM_LONG( 0, 49 ))
{
float offset;
int axis = RANDOM_LONG( 0, 1 );
if( axis == 1 ) axis = 2; // choose between x & z
offset = RANDOM_FLOAT( -10, 10 );
transform[RANDOM_LONG( 0, 2 )][3] += offset;
}
break;
case kRenderFxExplode:
float scale;
scale = 1.0f + (gHUD.m_flTime - ent->v.animtime) * 10.0;
if( scale > 2 ) scale = 2; // don't blow up more than 200%
transform[0][1] *= scale;
transform[1][1] *= scale;
transform[2][1] *= scale;
break;
}
}

View File

@ -8,387 +8,12 @@
#include "studio_event.h"
#include "effects_api.h"
#include "pm_movevars.h"
#include "tempents.h"
#include "r_tempents.h"
#include "ev_hldm.h"
#include "r_beams.h"
#include "hud.h"
#define MAX_CHANNELS 4 // hl1 and hl2 supported 4 channels for messges
#define TENT_WIND_ACCEL 50
model_t g_muzzleFlash[4]; // custom muzzleflashes
void HUD_MuzzleFlash( edict_t *m_pEnt, int iAttachment, const char *event )
{
int type, index;
type = atoi( event );
index = bound( 0, type % 10, 3 );
g_engfuncs.pEfxAPI->R_MuzzleFlash( g_muzzleFlash[index], m_pEnt->serialnumber, iAttachment, type );
}
void HUD_CreateEntities( void )
{
EV_UpdateBeams (); // egon use this
// add in any game specific objects here
g_pViewRenderBeams->UpdateTempEntBeams( );
}
int HUD_UpdateEntity( TEMPENTITY *pTemp, int framenumber )
{
// before first frame when movevars not initialized
if( !gpMovevars )
{
ALERT( at_error, "TempEntUpdate: no movevars!!!\n" );
return true;
}
float gravity, gravitySlow, fastFreq;
float frametime = gpGlobals->frametime;
fastFreq = gpGlobals->time * 5.5;
gravity = -frametime * gpMovevars->gravity;
gravitySlow = gravity * 0.5;
// save oldorigin
pTemp->oldorigin = pTemp->origin;
if( pTemp->flags & FTENT_SPARKSHOWER )
{
// adjust speed if it's time
// scale is next think time
if( gpGlobals->time > pTemp->m_flSpriteScale )
{
// show Sparks
// FIXME: implement
// g_engfuncs.pEfxAPI->R_SparkEffect( pTemp->origin, 8, -200, 200 );
// reduce life
pTemp->m_flFrameRate -= 0.1f;
if( pTemp->m_flFrameRate <= 0.0f )
{
pTemp->die = gpGlobals->time;
}
else
{
// so it will die no matter what
pTemp->die = gpGlobals->time + 0.5f;
// next think
pTemp->m_flSpriteScale = gpGlobals->time + 0.1f;
}
}
}
else if( pTemp->flags & FTENT_PLYRATTACHMENT )
{
edict_t *pClient = GetEntityByIndex( pTemp->clientIndex );
if( pClient )
{
pTemp->origin = pClient->v.origin + pTemp->tentOffset;
}
}
else if( pTemp->flags & FTENT_SINEWAVE )
{
pTemp->x += pTemp->m_vecVelocity.x * frametime;
pTemp->y += pTemp->m_vecVelocity.y * frametime;
pTemp->origin.x = pTemp->x + sin( pTemp->m_vecVelocity.z + gpGlobals->time ) * ( 10 * pTemp->m_flSpriteScale );
pTemp->origin.y = pTemp->y + sin( pTemp->m_vecVelocity.z + fastFreq + 0.7f ) * ( 8 * pTemp->m_flSpriteScale);
pTemp->origin.z = pTemp->origin.z + pTemp->m_vecVelocity[2] * frametime;
}
else if( pTemp->flags & FTENT_SPIRAL )
{
float s, c;
s = sin( pTemp->m_vecVelocity.z + fastFreq );
c = cos( pTemp->m_vecVelocity.z + fastFreq );
pTemp->origin.x = pTemp->origin.x + pTemp->m_vecVelocity.x * frametime + 8 * sin( gpGlobals->time * 20 );
pTemp->origin.y = pTemp->origin.y + pTemp->m_vecVelocity.y * frametime + 4 * sin( gpGlobals->time * 30 );
pTemp->origin.z = pTemp->origin.z + pTemp->m_vecVelocity.z * frametime;
}
else
{
// just add linear velocity
pTemp->origin = pTemp->origin + pTemp->m_vecVelocity * frametime;
}
if( pTemp->flags & FTENT_SPRANIMATE )
{
pTemp->m_flFrame += frametime * pTemp->m_flFrameRate;
if( pTemp->m_flFrame >= pTemp->m_flFrameMax )
{
pTemp->m_flFrame = pTemp->m_flFrame - (int)(pTemp->m_flFrame);
if(!( pTemp->flags & FTENT_SPRANIMATELOOP ))
{
// this animating sprite isn't set to loop, so destroy it.
pTemp->die = 0.0f;
return false;
}
}
}
else if( pTemp->flags & FTENT_SPRCYCLE )
{
pTemp->m_flFrame += frametime * 10;
if( pTemp->m_flFrame >= pTemp->m_flFrameMax )
{
pTemp->m_flFrame = pTemp->m_flFrame - (int)(pTemp->m_flFrame);
}
}
if( pTemp->flags & FTENT_SCALE )
{
pTemp->m_flSpriteScale += pTemp->m_flFrameRate += 20.0 * (frametime / pTemp->m_flFrameRate);
}
if( pTemp->flags & FTENT_ROTATE )
{
// just add angular velocity
pTemp->angles += pTemp->m_vecAvelocity * frametime;
}
if( pTemp->flags & ( FTENT_COLLIDEALL|FTENT_COLLIDEWORLD ))
{
Vector traceNormal;
float traceFraction = 1.0f;
traceNormal.Init();
if( pTemp->flags & FTENT_COLLIDEALL )
{
TraceResult tr;
TRACE_LINE( pTemp->oldorigin, pTemp->origin, false, NULL, &tr );
// Make sure it didn't bump into itself... (?!?)
if(( tr.flFraction != 1.0f ) && ( tr.pHit == GetEntityByIndex( 0 ) || tr.pHit != GetEntityByIndex( pTemp->clientIndex )))
{
traceFraction = tr.flFraction;
traceNormal = tr.vecPlaneNormal;
if( pTemp->hitcallback )
(*pTemp->hitcallback)( pTemp, &tr );
}
}
else if( pTemp->flags & FTENT_COLLIDEWORLD )
{
TraceResult tr;
TRACE_LINE( pTemp->oldorigin, pTemp->origin, true, NULL, &tr );
if( tr.flFraction != 1.0f )
{
traceFraction = tr.flFraction;
traceNormal = tr.vecPlaneNormal;
if ( pTemp->flags & FTENT_SPARKSHOWER )
{
// chop spark speeds a bit more
pTemp->m_vecVelocity *= 0.6f;
if( pTemp->m_vecVelocity.Length() < 10.0f )
pTemp->m_flFrameRate = 0.0f;
}
if( pTemp->hitcallback )
(*pTemp->hitcallback)( pTemp, &tr );
}
}
if( traceFraction != 1.0f ) // Decent collision now, and damping works
{
float proj, damp;
// Place at contact point
pTemp->origin = pTemp->oldorigin + (traceFraction * frametime) * pTemp->m_vecVelocity;
// Damp velocity
damp = pTemp->bounceFactor;
if( pTemp->flags & ( FTENT_GRAVITY|FTENT_SLOWGRAVITY ))
{
damp *= 0.5f;
if( traceNormal[2] > 0.9f ) // Hit floor?
{
if( pTemp->m_vecVelocity[2] <= 0 && pTemp->m_vecVelocity[2] >= gravity * 3 )
{
pTemp->flags &= ~(FTENT_SLOWGRAVITY|FTENT_ROTATE|FTENT_GRAVITY);
pTemp->flags &= ~(FTENT_COLLIDEWORLD|FTENT_SMOKETRAIL);
pTemp->angles.x = pTemp->angles.z = 0;
damp = 0; // stop
}
}
}
if( pTemp->hitSound )
{
// FIXME: implement
// g_engfuncs.pEfxAPI->CL_PlaySound( pTemp, damp );
}
if( pTemp->flags & FTENT_COLLIDEKILL )
{
// die on impact
pTemp->flags &= ~FTENT_FADEOUT;
pTemp->die = gpGlobals->time;
}
else
{
// reflect velocity
if( damp != 0 )
{
proj = DotProduct( pTemp->m_vecVelocity, traceNormal );
pTemp->m_vecVelocity += (-proj * 2) * traceNormal;
// reflect rotation (fake)
pTemp->angles.y = -pTemp->angles.y;
}
if( damp != 1.0f )
{
pTemp->m_vecVelocity *= damp;
pTemp->angles *= 0.9f;
}
}
}
}
if(( pTemp->flags & FTENT_FLICKER ) && framenumber == pTemp->m_nFlickerFrame )
{
float rgb[3] = { 1.0f, 0.47f, 0.0f };
g_engfuncs.pEfxAPI->CL_AllocDLight( pTemp->origin, rgb, 60, gpGlobals->time + 0.01f, 0, 0 );
}
if( pTemp->flags & FTENT_SMOKETRAIL )
{
// FIXME: implement
// g_engfuncs.pEfxAPI->R_RocketTrail( pTemp->oldorigin, pTemp->entity.origin, 1 );
}
if( pTemp->flags & FTENT_GRAVITY )
pTemp->m_vecVelocity.z += gravity;
else if( pTemp->flags & FTENT_SLOWGRAVITY )
pTemp->m_vecVelocity.z += gravitySlow;
if( pTemp->flags & FTENT_CLIENTCUSTOM )
{
if( pTemp->callback )
(*pTemp->callback)( pTemp );
}
if( pTemp->flags & FTENT_WINDBLOWN )
{
Vector vecWind = gHUD.m_vecWindVelocity;
for( int i = 0 ; i < 2 ; i++ )
{
if( pTemp->m_vecVelocity[i] < vecWind[i] )
{
pTemp->m_vecVelocity[i] += ( frametime * TENT_WIND_ACCEL );
// clamp
if( pTemp->m_vecVelocity[i] > vecWind[i] )
pTemp->m_vecVelocity[i] = vecWind[i];
}
else if( pTemp->m_vecVelocity[i] > vecWind[i] )
{
pTemp->m_vecVelocity[i] -= ( frametime * TENT_WIND_ACCEL );
// clamp
if( pTemp->m_vecVelocity[i] < vecWind[i] )
pTemp->m_vecVelocity[i] = vecWind[i];
}
}
}
return true;
}
void HUD_StudioEvent( const dstudioevent_t *event, edict_t *entity )
{
float pitch;
Vector pos;
switch( event->event )
{
case 5001:
// MullzeFlash at attachment 1
HUD_MuzzleFlash( entity, 1, event->options );
break;
case 5011:
// MullzeFlash at attachment 2
HUD_MuzzleFlash( entity, 2, event->options );
break;
case 5021:
// MullzeFlash at attachment 3
HUD_MuzzleFlash( entity, 3, event->options );
break;
case 5031:
// MullzeFlash at attachment 4
HUD_MuzzleFlash( entity, 4, event->options );
break;
case 5002:
// SparkEffect at attachment 1
break;
case 5004:
// Client side sound
GET_ATTACHMENT( entity, 1, pos, NULL );
CL_PlaySound( event->options, 1.0f, pos );
break;
case 5005:
// Client side sound with random pitch
pitch = 85 + RANDOM_LONG( 0, 0x1F );
GET_ATTACHMENT( entity, 1, pos, NULL );
CL_PlaySound( event->options, RANDOM_FLOAT( 0.7f, 0.9f ), pos, pitch );
break;
case 5050:
// Special event for displacer
break;
case 5060:
// eject shellEV_EjectShell( event, entity );
break;
default:
break;
}
}
void HUD_StudioFxTransform( edict_t *ent, float transform[4][4] )
{
switch( ent->v.renderfx )
{
case kRenderFxDistort:
case kRenderFxHologram:
if(!RANDOM_LONG( 0, 49 ))
{
int axis = RANDOM_LONG( 0, 1 );
float scale = RANDOM_FLOAT( 1, 1.484 );
if( axis == 1 ) axis = 2; // choose between x & z
transform[axis][0] *= scale;
transform[axis][1] *= scale;
transform[axis][2] *= scale;
}
else if(!RANDOM_LONG( 0, 49 ))
{
float offset;
int axis = RANDOM_LONG( 0, 1 );
if( axis == 1 ) axis = 2; // choose between x & z
offset = RANDOM_FLOAT( -10, 10 );
transform[RANDOM_LONG( 0, 2 )][3] += offset;
}
break;
case kRenderFxExplode:
float scale;
scale = 1.0f + (gHUD.m_flTime - ent->v.animtime) * 10.0;
if( scale > 2 ) scale = 2; // don't blow up more than 200%
transform[0][1] *= scale;
transform[1][1] *= scale;
transform[2][1] *= scale;
break;
}
}
/*
=================
@ -739,42 +364,6 @@ void CL_TeleportParticles( const Vector org )
}
}
void CL_PlaceDecal( Vector pos, Vector dir, float scale, HSPRITE hDecal )
{
float rgba[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
int flags = DECAL_FADEALPHA;
g_engfuncs.pEfxAPI->R_SetDecal( pos, dir, rgba, RANDOM_LONG( 0, 360 ), scale, hDecal, flags );
}
void CL_PlaceDecal( Vector pos, edict_t *pEntity, HSPRITE hDecal )
{
float rgba[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
int flags = DECAL_FADEALPHA;
float scale = 5.0f; // FIXME
Vector dir;
g_engfuncs.pEfxAPI->CL_FindExplosionPlane( pos, scale, dir );
g_engfuncs.pEfxAPI->R_SetDecal( pos, dir, rgba, RANDOM_LONG( 0, 360 ), scale, hDecal, flags );
}
void CL_AllocDLight( Vector pos, float r, float g, float b, float radius, float time, int flags )
{
float rgb[3];
rgb[0] = r / 255.0f;
rgb[1] = r / 255.0f;
rgb[2] = r / 255.0f;
if( radius <= 0 ) return;
g_engfuncs.pEfxAPI->CL_AllocDLight( pos, rgb, radius, time, flags, 0 );
}
void CL_AllocDLight( Vector pos, float radius, float time, int flags )
{
CL_AllocDLight( pos, 255, 255, 255, radius, time, flags );
}
void HUD_AddClientMessage( void )
{
static client_textmessage_t gTextMsg[MAX_CHANNELS], *msg;
@ -930,7 +519,32 @@ void TE_ParseBeamEntPoint( void )
/*
---------------
TE_ParseBeamEntPoint
TE_ParseGunShot
Particle effect plus ricochet sound
---------------
*/
void TE_ParseGunShot( void )
{
char soundpath[32];
Vector pos;
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
CL_BulletParticles( pos, Vector( 0, 0, -1 ));
if( RANDOM_LONG( 0, 32 ) <= 8 ) // 25% chanse
{
sprintf( soundpath, "weapons/ric%i.wav", RANDOM_LONG( 1, 5 ));
CL_PlaySound( soundpath, RANDOM_FLOAT( 0.7f, 0.9f ), pos, RANDOM_FLOAT( 95.0f, 105.0f ));
}
}
/*
---------------
TE_ParseExplosion
Creates additive sprite, 2 dynamic lights, flickering particles, explosion sound, move vertically 8 pps
---------------
@ -957,23 +571,21 @@ void TE_ParseExplosion( void )
if( scale != 0.0f )
{
// create explosion sprite
pTemp = g_engfuncs.pEfxAPI->R_DefaultSprite( pos2, spriteIndex, frameRate );
g_engfuncs.pEfxAPI->R_Sprite_Explode( pTemp, scale, flags );
ALERT( at_console, "Explosion scale: %g\n", scale );
pTemp = g_pTempEnts->DefaultSprite( pos2, spriteIndex, frameRate );
g_pTempEnts->Sprite_Explode( pTemp, scale, flags );
if( !( flags & TE_EXPLFLAG_NODLIGHTS ))
{
CL_AllocDLight( pos2, 250, 250, 150, 200, 0.01f, 0 ); // big flash
CL_AllocDLight( pos2, 255, 190, 40, 150, 1.0f, DLIGHT_FADE );// red glow
g_pTempEnts->AllocDLight( pos2, 250, 250, 150, 200, 0.01f, 0 ); // big flash
g_pTempEnts->AllocDLight( pos2, 255, 190, 40, 150, 1.0f, DLIGHT_FADE );// red glow
}
}
if(!( flags & TE_EXPLFLAG_NOPARTICLES ))
CL_ExplosionParticles( pos );
if( RANDOM_LONG( 0, 1 ))
CL_PlaceDecal( pos, dir, scale, g_engfuncs.pEfxAPI->CL_DecalIndexFromName( "{scorch1" ));
else CL_PlaceDecal( pos, dir, scale, g_engfuncs.pEfxAPI->CL_DecalIndexFromName( "{scorch2" ));
g_pTempEnts->PlaceDecal( pos, dir, scale, g_engfuncs.pEfxAPI->CL_DecalIndexFromName( "{scorch1" ));
else g_pTempEnts->PlaceDecal( pos, dir, scale, g_engfuncs.pEfxAPI->CL_DecalIndexFromName( "{scorch2" ));
if( !( flags & TE_EXPLFLAG_NOSOUND ))
{
@ -981,13 +593,306 @@ void TE_ParseExplosion( void )
}
}
void HUD_ParseTempEntity( void )
/*
---------------
TE_ParseSmoke
Creates alphablend sprite, move vertically 30 pps
---------------
*/
void TE_ParseSmoke( void )
{
TEMPENTITY *pTemp;
float scale, framerate;
int modelIndex;
Vector pos;
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
modelIndex = READ_SHORT();
scale = (float)(READ_BYTE() * 0.1f);
framerate = (float)READ_BYTE();
// Half-Life style smoke
// create smoke sprite
pTemp = g_pTempEnts->DefaultSprite( pos, modelIndex, framerate );
g_pTempEnts->Sprite_Smoke( pTemp, scale );
}
/*
---------------
TE_ParseTracer
Creates tracer effect from point to point
---------------
*/
void TE_ParseTracer( void )
{
Vector start, end;
start.x = READ_COORD(); // tracer start
start.y = READ_COORD();
start.z = READ_COORD();
end.x = READ_COORD(); // tracer end
end.y = READ_COORD();
end.z = READ_COORD();
EV_CreateTracer( start, end );
}
/*
---------------
TE_ParseLighting
version of TE_BEAMPOINTS with simplified parameters
---------------
*/
void TE_ParseLighting( void )
{
Vector start, end;
float life, width, noise;
int modelIndex;
start.x = READ_COORD();
start.y = READ_COORD();
start.z = READ_COORD();
end.x = READ_COORD();
end.y = READ_COORD();
end.z = READ_COORD();
life = (float)(READ_BYTE() * 0.1f);
width = (float)(READ_BYTE() * 0.1f);
noise = (float)(READ_BYTE() * 0.1f);
modelIndex = READ_SHORT();
g_pViewRenderBeams->CreateBeamPoints( start, end, modelIndex, life, width, noise, 255, 1.0f, 0, 0, 255, 255, 255 );
}
/*
---------------
TE_ParseBeamEnts
Creates a beam between origins of two entities
---------------
*/
void TE_ParseBeamEnts( void )
{
int modelIndex, startEntity, endEntity, startFrame;
float life, width, noise, framerate, brightness, speed;
Vector vecColor;
startEntity = READ_SHORT();
endEntity = READ_SHORT();
modelIndex = READ_SHORT();
startFrame = READ_BYTE();
framerate = (float)(READ_BYTE() * 0.1f);
life = (float)(READ_BYTE() * 0.1f);
width = (float)(READ_BYTE() * 0.1f);
noise = (float)(READ_BYTE() * 0.1f);
// renderinfo
vecColor.x = (float)READ_BYTE();
vecColor.y = (float)READ_BYTE();
vecColor.z = (float)READ_BYTE();
brightness = (float)READ_BYTE();
speed = (float)(READ_BYTE() * 0.1f);
g_pViewRenderBeams->CreateBeamEnts( startEntity, endEntity, modelIndex, life, width, noise, brightness,
speed, startFrame, framerate, vecColor.x, vecColor.y, vecColor.z );
}
/*
---------------
TE_ParseSparks
Creates a 8 random tracers with gravity, ricochet sprite
---------------
*/
void TE_ParseSparks( void )
{
Vector pos, dir;
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
g_engfuncs.pEfxAPI->CL_FindExplosionPlane( pos, 1.0f, dir );
CL_SparkParticles( pos, dir );
}
/*
---------------
TE_ParseTeleport
Creates a Quake1 teleport splash
---------------
*/
void TE_ParseTeleport( void )
{
Vector pos;
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
CL_TeleportParticles( pos );
}
/*
---------------
TE_ParseBSPDecal
Creates a decal from the .BSP file
---------------
*/
void TE_ParseBSPDecal( void )
{
Vector pos;
int decalIndex, entityIndex, modelIndex;
edict_t *pEntity;
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
decalIndex = READ_SHORT();
entityIndex = READ_SHORT();
if( entityIndex != 0 )
{
modelIndex = READ_SHORT();
}
pEntity = GetEntityByIndex( entityIndex );
g_pTempEnts->PlaceDecal( pos, pEntity, g_engfuncs.pEfxAPI->CL_DecalIndex( decalIndex ));
}
/*
---------------
TE_ParseSpriteTrail
Creates a line of moving glow sprites with gravity, fadeout, and collisions
---------------
*/
void TE_ParseSpriteTrail( void )
{
Vector start, end;
float life, scale, vel, random;
int spriteIndex, count;
start.x = READ_COORD();
start.y = READ_COORD();
start.z = READ_COORD();
end.x = READ_COORD();
end.y = READ_COORD();
end.z = READ_COORD();
spriteIndex = READ_SHORT();
count = READ_BYTE();
life = (float)(READ_BYTE() * 0.1f);
scale = (float)(READ_BYTE() * 0.1f);
vel = (float)READ_BYTE();
random = (float)READ_BYTE();
g_pTempEnts->Sprite_Trail( TE_SPRITETRAIL, start, end, spriteIndex, count, life, scale, random, 255, vel );
}
/*
---------------
TE_ParseSprite
Creates a additive sprite, plays 1 cycle
---------------
*/
void TE_ParseSprite( void )
{
Vector pos;
TEMPENTITY *pTemp;
float scale, brightness;
int spriteIndex;
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
spriteIndex = READ_SHORT();
scale = (float)(READ_BYTE() * 0.1f);
brightness = (float)READ_BYTE();
pTemp = g_pTempEnts->DefaultSprite( pos, spriteIndex, 0 );
if( pTemp )
{
pTemp->m_flSpriteScale = scale;
pTemp->startAlpha = brightness;
pTemp->renderAmt = brightness;
}
}
/*
---------------
TE_ParseBeamRing
Generic function to parse various beam rings
---------------
*/
void TE_ParseBeamRing( int type )
{
Vector start, end, vecColor;
float life, framerate, width, noise, speed, brightness;
int spriteIndex, startFrame;
start.x = READ_COORD();
start.y = READ_COORD();
start.z = READ_COORD();
end.x = READ_COORD();
end.y = READ_COORD();
end.z = READ_COORD();
spriteIndex = READ_SHORT();
startFrame = READ_BYTE();
framerate = (float)(READ_BYTE() * 0.1f);
life = (float)(READ_BYTE() * 0.1f);
width = (float)(READ_BYTE());
noise = (float)(READ_BYTE() * 0.1f);
// renderinfo
vecColor.x = (float)READ_BYTE();
vecColor.y = (float)READ_BYTE();
vecColor.z = (float)READ_BYTE();
brightness = (float)READ_BYTE();
speed = (float)(READ_BYTE() * 0.1f);
g_pViewRenderBeams->CreateBeamCirclePoints( type, start, end, spriteIndex, life, width, width, 0.0f,
noise, brightness, speed, startFrame, framerate, vecColor.x, vecColor.y, vecColor.z );
}
/*
---------------
TE_ParseKillBeam
Kill all beams attached to entity
---------------
*/
void TE_ParseKillBeam( void )
{
edict_t *pEntity = GetEntityByIndex( READ_SHORT() );
g_pViewRenderBeams->KillDeadBeams( pEntity );
}
void HUD_ParseTempEntity( void )
{
char soundpath[32];
Vector pos, pos2, dir, size, color;
float time, random, framerate, radius, scale, decay;
int flags, modelIndex, soundType, count, iColor;
float time, random, radius, scale, decay;
int flags, modelIndex, modelIndex2, soundType, count, iColor;
switch( READ_BYTE() )
{
@ -998,23 +903,74 @@ void HUD_ParseTempEntity( void )
TE_ParseBeamEntPoint();
break;
case TE_GUNSHOT:
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
CL_BulletParticles( pos, Vector( 0, 0, -1 ));
if( RANDOM_LONG( 0, 32 ) <= 8 ) // 25% chanse
{
sprintf( soundpath, "weapons/ric%i.wav", RANDOM_LONG( 1, 5 ));
CL_PlaySound( soundpath, RANDOM_FLOAT( 0.7f, 0.9f ), pos, RANDOM_FLOAT( 95.0f, 105.0f ));
}
TE_ParseGunShot();
break;
case TE_EXPLOSION:
TE_ParseExplosion();
break;
case TE_TAREXPLOSION:
// FIXME: implement
break;
case TE_SMOKE:
TE_ParseSmoke();
break;
case TE_TRACER:
TE_ParseTracer();
break;
case TE_LIGHTNING:
TE_ParseLighting();
break;
case TE_BEAMENTS:
TE_ParseBeamEnts();
break;
case TE_SPARKS:
TE_ParseSparks();
break;
case TE_LAVASPLASH:
// FIXME: implement
break;
case TE_TELEPORT:
TE_ParseTeleport();
break;
case TE_EXPLOSION2:
// FIXME: implement
break;
case TE_BSPDECAL:
TE_ParseBSPDecal();
break;
case TE_IMPLOSION:
// FIXME: implement
break;
case TE_SPRITETRAIL:
TE_ParseSpriteTrail();
break;
case TE_BEAM: break; // obsolete
case TE_SPRITE:
TE_ParseSprite();
break;
case TE_BEAMSPRITE:
// FIXME: implement
break;
case TE_BEAMTORUS:
TE_ParseBeamRing( TE_BEAMTORUS );
break;
case TE_BEAMDISK:
TE_ParseBeamRing( TE_BEAMDISK );
break;
case TE_BEAMCYLINDER:
TE_ParseBeamRing( TE_BEAMCYLINDER );
break;
case TE_BEAMFOLLOW:
TE_ParseBeamFollow();
break;
case TE_GLOWSPRITE:
// FIXME: implement
break;
case TE_BEAMRING:
break;
case TE_KILLBEAM:
TE_ParseKillBeam();
break;
case TE_GUNSHOTDECAL:
pos.x = READ_COORD();
pos.y = READ_COORD();
@ -1022,7 +978,7 @@ void HUD_ParseTempEntity( void )
dir = READ_DIR();
READ_SHORT(); // FIXME: skip entindex
CL_BulletParticles( pos, dir );
CL_PlaceDecal( pos, dir, 2, g_engfuncs.pEfxAPI->CL_DecalIndex( READ_BYTE() ));
g_pTempEnts->PlaceDecal( pos, dir, 2, g_engfuncs.pEfxAPI->CL_DecalIndex( READ_BYTE() ));
if( RANDOM_LONG( 0, 32 ) <= 8 ) // 25% chanse
{
@ -1035,16 +991,9 @@ void HUD_ParseTempEntity( void )
pos.y = READ_COORD();
pos.z = READ_COORD();
g_engfuncs.pEfxAPI->CL_FindExplosionPlane( pos, 10, dir );
CL_PlaceDecal( pos, dir, 2, g_engfuncs.pEfxAPI->CL_DecalIndex( READ_BYTE() ));
g_pTempEnts->PlaceDecal( pos, dir, 2, g_engfuncs.pEfxAPI->CL_DecalIndex( READ_BYTE() ));
READ_SHORT(); // FIXME: skip entindex
break;
case TE_SPARKS:
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
g_engfuncs.pEfxAPI->CL_FindExplosionPlane( pos, 1.0f, dir );
CL_SparkParticles( pos, dir );
break;
case TE_ARMOR_RICOCHET:
pos.x = READ_COORD();
pos.y = READ_COORD();
@ -1052,44 +1001,6 @@ void HUD_ParseTempEntity( void )
radius = READ_BYTE() / 10.0f;
CL_RicochetSparks( pos, radius );
break;
case TE_SMOKE:
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
modelIndex = READ_SHORT();
scale = READ_BYTE();
framerate = READ_BYTE();
#if 1
// Half-Life style smoke
// create smoke sprite
pTemp = g_engfuncs.pEfxAPI->CL_TempEntAlloc( pos, modelIndex );
g_engfuncs.pEfxAPI->R_Sprite_Smoke( pTemp, ( scale * 0.1f ));
if( pTemp )
{
pTemp->die = gpGlobals->time + 5.0f; // should be enough for too long sequence
pTemp->m_flFrameRate = framerate;
pTemp->flags |= FTENT_SPRANIMATE;
}
#else
// quake2 evolved style smoke
CL_SmokeParticles( pos, scale );
#endif
break;
case TE_TELEPORT:
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
CL_TeleportParticles( pos );
break;
case TE_SPRITE:
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
modelIndex = READ_SHORT();
scale = (float)(READ_BYTE() * 0.1f);
decay = READ_BYTE(); // brightness
g_engfuncs.pEfxAPI->R_TempSprite( pos, NULL, scale, modelIndex, 0, 0, decay, 0.02f, 0 );
break;
case TE_ELIGHT:
READ_SHORT(); // skip attachment
// FIXME: need to match with dlight message
@ -1105,15 +1016,6 @@ void HUD_ParseTempEntity( void )
decay = (float)READ_BYTE() * 0.1f;
g_engfuncs.pEfxAPI->CL_AllocDLight( pos, color, radius, time, 0, 0 );
break;
case TE_TRACER:
pos.x = READ_COORD(); // tracer start
pos.y = READ_COORD();
pos.z = READ_COORD();
pos2.x = READ_COORD(); // tracer end
pos2.y = READ_COORD();
pos2.z = READ_COORD();
EV_CreateTracer( pos, pos2 );
break;
case TE_MODEL:
pos.x = READ_COORD(); // tracer start
pos.y = READ_COORD();
@ -1125,17 +1027,17 @@ void HUD_ParseTempEntity( void )
modelIndex = READ_SHORT();
soundType = READ_BYTE();
decay = (float)(READ_BYTE() * 0.1f);
g_engfuncs.pEfxAPI->R_TempModel( pos, dir, pos2, decay, modelIndex, soundType );
g_pTempEnts->TempModel( pos, dir, pos2, decay, modelIndex, soundType );
break;
case TE_BLOODSPRITE:
pos.x = READ_COORD(); // sprite pos
pos.y = READ_COORD();
pos.z = READ_COORD();
modelIndex = READ_SHORT();
READ_SHORT(); // FIXME: skup droplet blood sprite
modelIndex2 =READ_SHORT();
iColor = READ_BYTE();
scale = READ_BYTE(); // scale
g_engfuncs.pEfxAPI->R_BloodSprite( pos, iColor, modelIndex, scale );
g_pTempEnts->BloodSprite( pos, iColor, modelIndex, modelIndex2, scale );
break;
case TE_BREAKMODEL:
pos.x = READ_COORD(); // breakmodel center
@ -1152,7 +1054,7 @@ void HUD_ParseTempEntity( void )
count = READ_BYTE(); // # of shards ( 0 - autodetect by size )
decay = (float)(READ_BYTE() * 0.1f);
flags = READ_BYTE(); // material flags
g_engfuncs.pEfxAPI->R_BreakModel( pos, size, dir, random, decay, count, modelIndex, flags );
g_pTempEnts->BreakModel( pos, size, dir, random, decay, count, modelIndex, flags );
break;
case TE_TEXTMESSAGE:
HUD_AddClientMessage();

View File

@ -17,12 +17,7 @@ void HUD_DrawTransparentTriangles( void )
{
R_DrawWeather();
for( int i = 0; i < 3; i++ )
{
// NOTE: for some reasons in Xash3D
// we needs for three iterations of PartSystem
g_pParticleSystems->UpdateSystems();
}
g_pParticleSystems->UpdateSystems();
}
void HUD_RenderCallback( int fTrans )

View File

@ -33,7 +33,7 @@ extern movevars_t *gpMovevars;
extern int HUD_VidInit( void );
extern void HUD_Init( void );
extern int HUD_Redraw( float flTime, int state );
extern void HUD_UpdateEntityVars( edict_t *out, skyportal_t *sky, const entity_state_t *s, const entity_state_t *p );
extern void HUD_UpdateEntityVars( edict_t *out, const entity_state_t *s, const entity_state_t *p );
extern void HUD_UpdateOnRemove( edict_t *pEdict );
extern void HUD_Reset( void );
extern void HUD_StartFrame( void );
@ -41,7 +41,7 @@ extern void HUD_Frame( double time );
extern void HUD_Shutdown( void );
extern void HUD_RenderCallback( int fTrans );
extern void HUD_CreateEntities( void );
extern int HUD_UpdateEntity( TEMPENTITY *pTemp, int framenumber );
extern int HUD_AddVisibleEntity( edict_t *pEnt, int ed_type );
extern void HUD_StudioEvent( const dstudioevent_t *event, edict_t *entity );
extern void HUD_StudioFxTransform( edict_t *ent, float transform[4][4] );
extern void HUD_ParseTempEntity( void );
@ -207,13 +207,9 @@ extern void DrawProgressBar( void );
extern edict_t *spot;
extern float v_idlescale;
extern int g_weaponselect;
extern model_t g_muzzleFlash[4];
extern int g_iAlive; // indicates alive local client or not
// tempents.c
extern void HUD_MuzzleFlash( edict_t *m_pEnt, int iAttachment, const char *event );
extern void CL_PlaceDecal( Vector pos, Vector dir, float scale, HSPRITE hDecal );
extern void CL_PlaceDecal( Vector pos, edict_t *pEntity, HSPRITE hDecal );
extern void CL_BulletParticles( const Vector org, const Vector dir );
// input.cpp

View File

@ -141,12 +141,6 @@ void CHud :: VidInit( void )
m_hBubble = TEX_Load( "textures/particles/bubble" );
m_hSparks = TEX_Load( "textures/particles/spark" );
m_hSmoke = TEX_Load( "textures/particles/smoke" );
// load custom muzzleflashes
g_muzzleFlash[0] = g_engfuncs.pEventAPI->EV_FindModelIndex( "sprites/muzzleflash1.spr" );
g_muzzleFlash[1] = g_engfuncs.pEventAPI->EV_FindModelIndex( "sprites/muzzleflash2.spr" );
g_muzzleFlash[2] = g_engfuncs.pEventAPI->EV_FindModelIndex( "sprites/muzzleflash3.spr" );
g_muzzleFlash[3] = g_engfuncs.pEventAPI->EV_FindModelIndex( "sprites/muzzleflash.spr" );
m_Sound.VidInit();
m_Ammo.VidInit();

View File

@ -565,14 +565,6 @@ private:
#define SKY_OFF 0
#define SKY_ON 1
typedef struct cl_mirror_s
{
vec3_t origin;
int enabled;
float radius;
int type;
} cl_mirror_t;
class CHud
{
private:
@ -607,8 +599,6 @@ public:
int viewEntityIndex;
int m_iHUDColor;
int viewFlags;
cl_mirror_t Mirrors[32]; // limit - 32 mirrors!
int numMirrors;
private:
// the memory for these arrays are allocated in the first call to CHud::VidInit()
// when the hud.txt and associated sprites are loaded. freed in ~CHud()

View File

@ -148,9 +148,6 @@ int CHud :: MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf )
m_flStartDist = 0;
m_flEndDist = 0;
// clear mirrors
numMirrors = 0;
return 1;
}

View File

@ -236,7 +236,7 @@ typedef struct
int (*pfnVidInit)( void );
void (*pfnInit)( void );
int (*pfnRedraw)( float flTime, int state );
void (*pfnUpdateEntityVars)( edict_t *out, skyportal_t *sky, const struct entity_state_s *in1, const struct entity_state_s *in2 );
void (*pfnUpdateEntityVars)( edict_t *out, const struct entity_state_s *in1, const struct entity_state_s *in2 );
void (*pfnOnFreeEntPrivateData)( edict_t *pEnt ); // this is called on entity removed
void (*pfnReset)( void );
void (*pfnStartFrame)( void );
@ -244,7 +244,7 @@ typedef struct
void (*pfnShutdown)( void );
void (*pfnDrawTriangles)( int fTrans );
void (*pfnCreateEntities)( void );
int (*pfnUpdateEntity)( TEMPENTITY *pTemp, int framenumber );
int (*pfnAddVisibleEntity)( edict_t *pEnt, int ed_type );
void (*pfnStudioEvent)( const dstudioevent_t *event, edict_t *entity );
void (*pfnStudioFxTransform)( edict_t *pEdict, float transform[4][4] );
void (*pfnCalcRefdef)( ref_params_t *parms );

View File

@ -30,7 +30,7 @@
#define FTENT_SPRANIMATELOOP (1<<16) // animating sprite doesn't die when last frame is displayed
#define FTENT_SCALE (1<<17) // an experiment
#define FTENT_SPARKSHOWER (1<<18)
#define FTENT_NOMODEL (1<<19) // doesn't have a model, never draw (it just triggers other things)
#define FTENT_NOMODEL (1<<19) // sets by engine, never draw (it just triggers other things)
#define FTENT_CLIENTCUSTOM (1<<20) // Must specify callback. Callback function is responsible
// for killing tempent and updating fields
// ( unless other flags specify how to do things )
@ -56,7 +56,7 @@ struct tempent_s
short clientIndex; // if attached, this is the index of the client to stick to
// if COLLIDEALL, this is the index of the client to ignore
// TENTS with FTENT_PLYRATTACHMENT MUST set the clientindex!
void *pvEngineData; // private data that alloced, freed and used by engine only
void *pvEngineData; // private data that alloced and used by engine, freed in client.dll
HITCALLBACK hitcallback;
ENTCALLBACK callback;
@ -102,29 +102,17 @@ typedef struct efxapi_s
size_t api_size; // must match with sizeof( efxapi_t );
int (*R_AllocParticle)( cparticle_t *src, HSPRITE shader, int flags );
void (*R_BloodSprite)( float *org, int colorIndex, int modelIndex, float size );
void (*R_BreakModel)( float *pos, float *size, float *dir, float random, float life, int count, int modelIndex, char flags );
void (*R_MuzzleFlash)( int modelIndex, int entityIndex, int iAttachment, int type );
void (*R_Sprite_Explode)( TEMPENTITY *pTemp, float scale, int flags );
void (*R_Sprite_Smoke)( TEMPENTITY *pTemp, float scale );
void (*R_Sprite_Spray)( float *pos, float *dir, int modelIndex, int count, int speed, int iRand );
void (*R_Sprite_Trail)( int type, float *start, float *end, int modelIndex, int count, float life, float size, float amplitude, int renderamt, float speed );
void (*R_TracerEffect)( float *start, float *end );
TEMPENTITY *(*R_TempModel)( float *pos, float *dir, float *ang, float life, int modelIndex, int soundtype );
TEMPENTITY *(*R_DefaultSprite)( float *pos, int spriteIndex, float framerate );
TEMPENTITY *(*R_TempSprite)( float *pos, float *dir, float scale, int modelIndex, int rendermode, int renderfx, float a, float life, int flags );
void (*R_GetPaletteColor)( int colorIndex, float *outColor );
int (*CL_DecalIndex)( int id );
int (*CL_DecalIndexFromName)( const char *szDecalName );
void (*R_SetDecal)( float *org, float *dir, float *rgba, float rot, float rad, HSPRITE hSpr, int flags );
void (*CL_AllocDLight)( const float *org, float *rgb, float rad, float time, int flags, int key );
TEMPENTITY *(*CL_TempEntAlloc)( float *org, int modelIndex );
TEMPENTITY *(*CL_TempEntAllocNoModel)( float *org );
TEMPENTITY *(*CL_TempEntAllocHigh)( float *org, int modelIndex );
TEMPENTITY *(*CL_TentEntAllocCustom)( float *org, int modelIndex, int high, ENTCALLBACK pfnCallback );
void (*CL_FindExplosionPlane)( const float *origin, float radius, float *result );
void (*R_LightForPoint)( const float *rgflOrigin, float *lightValue );
int (*CL_IsBoxVisible)( const float *mins, const float *maxs );
int (*R_CullBox)( const float *mins, const float *maxs );
int (*R_AddEntity)( edict_t *pEnt, int ed_type, HSPRITE customShader );
int (*R_AddTempEntity)( TEMPENTITY *pTemp, HSPRITE customShader );
} efxapi_t;
#endif//EFFECTS_API_H

View File

@ -366,7 +366,7 @@ typedef struct
char (*pfnPM_FindTextureType)( const char *name );
int (*pfnSetupVisibility)( edict_t *pViewEntity, edict_t *pClient, int portal, float *rgflViewOrg );
void (*pfnPhysicsEntity)( edict_t *pEntity ); // was pfnUpdateClientData
int (*pfnAddToFullPack)( edict_t *pHost, edict_t *pClient, edict_t *pEdict, int hostflags, int hostarea, byte *pSet );
int (*pfnAddToFullPack)( edict_t *pView, edict_t *pHost, edict_t *pEdict, int hostflags, int hostarea, byte *pSet );
void (*pfnEndFrame)( void ); // was pfnCreateBaseline
int (*pfnShouldCollide)( edict_t *pTouch, edict_t *pOther ); // was pfnCreateBaseline
void (*pfnUpdateEntityState)( struct entity_state_s *to, edict_t *from, int baseline ); // was pfnRegisterEncoders

View File

@ -94,10 +94,10 @@ class Vector // same data-layout as engine's vec3_t,
{ // which is a vec_t[3]
public:
// Construction/destruction
inline Vector(void) { }
inline Vector(float X, float Y, float Z) { x = X; y = Y; z = Z; }
inline Vector(const Vector& v) { x = v.x; y = v.y; z = v.z; }
inline Vector(float rgfl[3]) { x = rgfl[0]; y = rgfl[1]; z = rgfl[2]; }
inline Vector( void ) { }
inline Vector(float X, float Y, float Z) { x = X; y = Y; z = Z; }
inline Vector(const Vector& v) { x = v.x; y = v.y; z = v.z; }
inline Vector(float *rgfl) { x = rgfl[0]; y = rgfl[1]; z = rgfl[2]; }
// Initialization
void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f){ x = ix; y = iy; z = iz; }

View File

@ -62,7 +62,6 @@ void CL_RunLightStyles( void )
}
}
void CL_SetLightstyle( int i )
{
char *s;
@ -70,7 +69,9 @@ void CL_SetLightstyle( int i )
s = cl.configstrings[i+CS_LIGHTSTYLES];
j = com.strlen( s );
if( j >= MAX_STRING ) Host_Error("CL_SetLightStyle: lightstyle %s is too long\n", s );
if( j >= MAX_STRING )
Host_Error("CL_SetLightStyle: lightstyle %s is too long\n", s );
cl_lightstyle[i].length = j;
@ -83,7 +84,7 @@ void CL_SetLightstyle( int i )
CL_AddLightStyles
================
*/
void CL_AddLightStyles (void)
void CL_AddLightStyles( void )
{
int i;
clightstyle_t *ls;
@ -218,25 +219,6 @@ void pfnAddDLight( const float *org, const float *rgb, float radius, float time,
dl->fade = (flags & DLIGHT_FADE) ? true : false;
}
void CL_LocalMuzzleFlash( void )
{
vec3_t pos;
cdlight_t *dl;
CL_GetAttachment( VIEWENT_INDEX, 1, pos, NULL );
if( VectorCompare( pos, clgame.viewent.v.origin ))
return; // missing attachment
dl = CL_AllocDlight( cl.playernum + 1 );
VectorCopy( pos, dl->origin );
dl->radius = 100;
dl->start = cl.time;
dl->end = dl->start + 50;
dl->color[0] = 1.0f;
dl->color[1] = 0.75f;
dl->color[2] = 0.25f;
}
/*
===============
CL_RunDLights
@ -288,9 +270,9 @@ DECALS MANAGEMENT
==============================================================
*/
#define MAX_DRAWDECALS 256
#define MAX_DECAL_VERTS 128
#define MAX_DECAL_FRAGMENTS 64
#define MAX_DRAWDECALS 1024
#define MAX_DECAL_VERTS 32 // per one decal
#define MAX_DECAL_FRAGMENTS 16
typedef struct cdecal_s
{
@ -698,7 +680,7 @@ static cparticle_t *CL_AllocParticle( void )
if( cl_particlelod->integer > 1 )
{
if(!(Com_RandomLong( 0, 1 ) % cl_particlelod->integer))
if(!( Com_RandomLong( 0, 1 ) % cl_particlelod->integer ))
return NULL;
}
@ -1094,36 +1076,6 @@ void CL_ParticleEffect( const vec3_t org, const vec3_t dir, int color, int count
}
}
void CL_CreateTracer( float *start, float *end )
{
vec3_t vec;
cparticle_t src;
int pal = 238; // nice color for tracers
if( !start || !end ) return;
VectorSubtract( end, start, vec );
VectorNormalize( vec );
VectorClear( src.velocity );
src.color[0] = cl_particlePalette[pal][0];
src.color[1] = cl_particlePalette[pal][1];
src.color[2] = cl_particlePalette[pal][2];
VectorClear( src.colorVelocity );
VectorClear( src.accel );
src.alpha = 1.0f;
src.alphaVelocity = -12.0; // lifetime
src.radius = 1.2f;
src.radiusVelocity = 0;
src.length = 12;
src.lengthVelocity = 0;
src.rotation = 0;
VectorCopy( start, src.origin );
src.velocity[0] = 6000.0f * vec[0];
src.velocity[1] = 6000.0f * vec[1];
src.velocity[2] = 6000.0f * vec[2];
pfnAddParticle( &src, cls.particle, PARTICLE_STRETCH );
}
/*
===============
pfnAddParticle
@ -1143,7 +1095,8 @@ bool pfnAddParticle( cparticle_t *src, HSPRITE shader, int flags )
return false;
}
p->shader = shader;
if( shader ) p->shader = shader;
else p->shader = cls.particle;
p->time = cl.time;
p->flags = flags;
@ -1369,7 +1322,7 @@ void CL_TestEntities( void )
ent.v.controller[0] = ent.v.controller[1] = 90.0f;
ent.v.controller[2] = ent.v.controller[3] = 180.0f;
ent.v.modelindex = pl->v.modelindex;
re->AddRefEntity( &ent, ED_NORMAL );
re->AddRefEntity( &ent, ED_NORMAL, -1 );
}
}
@ -1404,7 +1357,7 @@ void CL_TestLights( void )
VectorSet( mins, -4, -4, -4 );
VectorSet( maxs, 4, 4, 4 );
trace = CL_Move( cl.refdef.vieworg, mins, maxs, end, MOVE_NORMAL, ed );
trace = CL_Move( cl.refdef.vieworg, mins, maxs, end, MOVE_NORMAL|0x200, ed );
VectorSet( dl.color, 1.0f, 1.0f, 1.0f );
dl.texture = flashlight_shader;
dl.intensity = 96;
@ -1446,7 +1399,6 @@ CL_ClearEffects
*/
void CL_ClearEffects( void )
{
CL_ClearTempEnts ();
CL_ClearParticles ();
CL_ClearDlights ();
CL_ClearLightStyles ();

View File

@ -18,7 +18,7 @@ void CL_UpdateEntityFields( edict_t *ent )
// these fields user can overwrite if need
ent->v.model = MAKE_STRING( cl.configstrings[CS_MODELS+ent->pvClientData->current.modelindex] );
clgame.dllFuncs.pfnUpdateEntityVars( ent, &cl.refdef.skyportal, &ent->pvClientData->current, &ent->pvClientData->prev );
clgame.dllFuncs.pfnUpdateEntityVars( ent, &ent->pvClientData->current, &ent->pvClientData->prev );
if( ent->pvClientData->current.ed_flags & ESF_LINKEDICT )
{
@ -314,7 +314,7 @@ void CL_AddPacketEntities( frame_t *frame )
ed_type = ent->pvClientData->current.ed_type;
CL_UpdateEntityFields( ent );
if( re->AddRefEntity( ent, ed_type ))
if( clgame.dllFuncs.pfnAddVisibleEntity( ent, ed_type ))
{
if( ed_type == ED_PORTAL && !VectorCompare( ent->v.origin, ent->v.oldorigin ))
cl.render_flags |= RDF_PORTALINVIEW;
@ -346,7 +346,6 @@ void CL_AddEntities( void )
clgame.dllFuncs.pfnCreateEntities();
CL_FireEvents(); // so tempents can be created immediately
CL_AddTempEnts();
CL_AddParticles();
CL_AddDLights();
CL_AddLightStyles();

View File

@ -104,7 +104,7 @@ bool CL_GetAttachment( int entityIndex, int number, vec3_t origin, vec3_t angles
if( !ed || ed->free || !ed->pvClientData )
return false;
number = bound( 0, number, MAXSTUDIOATTACHMENTS - 1 );
number = bound( 1, number, MAXSTUDIOATTACHMENTS );
if( origin ) VectorAdd( ed->v.origin, ed->pvClientData->origin[number-1], origin );
if( angles ) VectorCopy( ed->pvClientData->angles[number-1], angles );
@ -1961,7 +1961,7 @@ 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 );
S_StartSound( vec3_origin, ent, channel, S_RegisterSound( sample ), 0, 0, PITCH_NORM, SND_STOP );
}
/*
@ -2418,29 +2418,17 @@ static efxapi_t gEfxApi =
{
sizeof( efxapi_t ),
pfnAddParticle,
CL_BloodSprite,
CL_BreakModel,
CL_MuzzleFlash,
CL_SpriteExplode,
CL_SpriteSmoke,
CL_SpriteSpray,
CL_Sprite_Trail,
CL_CreateTracer,
CL_TempModel,
CL_DefaultSprite,
CL_TempSprite,
CL_GetPaletteColor,
pfnDecalIndex,
pfnDecalIndexFromName,
pfnAddDecal,
pfnAddDLight,
CL_TempEntAlloc,
CL_TempEntAllocNoModel,
CL_TempEntAllocHigh,
CL_TentEntAllocCustom,
pfnFindExplosionPlane,
pfnLightForPoint,
CM_BoxVisible,
pfnCullBox,
CL_AddEntity,
CL_AddTempEntity,
};
static event_api_t gEventApi =
@ -2557,13 +2545,13 @@ static cl_enginefuncs_t gEngfuncs =
void CL_UnloadProgs( void )
{
// initialize game
clgame.dllFuncs.pfnShutdown();
CL_FreeEdicts();
CL_FreeEdict( &clgame.viewent );
CL_FreeEdict( &clgame.playermodel );
// deinitialize game
clgame.dllFuncs.pfnShutdown();
StringTable_Delete( clgame.hStringTable );
Com_FreeLibrary( clgame.hInstance );
Mem_FreePool( &cls.mempool );

View File

@ -34,6 +34,7 @@ cvar_t *model;
cvar_t *topcolor;
cvar_t *bottomcolor;
cvar_t *rate;
cvar_t *cl_lw;
client_t cl;
client_static_t cls;
@ -1045,6 +1046,7 @@ void CL_InitLocal( void )
rate = Cvar_Get( "rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE, "player network rate" ); // FIXME
userinfo = Cvar_Get( "@userinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
cl_showfps = Cvar_Get( "cl_showfps", "1", CVAR_ARCHIVE, "show client fps" );
cl_lw = Cvar_Get( "cl_lw", "1", CVAR_ARCHIVE|CVAR_USERINFO, "enable client weapon predicting" );
// register our commands
Cmd_AddCommand ("cmd", CL_ForwardToServer_f, "send a console commandline to the server" );

View File

@ -9,6 +9,20 @@
#include "const.h"
#include "pm_defs.h"
bool CL_IsPredicted( void )
{
edict_t *player = CL_GetLocalPlayer();
if( !player )
return false;
if( player->pvClientData->current.ed_flags & ESF_NO_PREDICTION )
return false;
if( !cl_predict->integer )
return false;
return true;
}
/*
=================
CL_CreateCmd
@ -444,12 +458,10 @@ void CL_CheckPredictionError( void )
edict_t *player;
float flen;
if( !cl_predict->integer ) return;
if( !CL_IsPredicted( )) return;
player = CL_GetLocalPlayer();
if( !player ) return;
if( player->pvClientData->current.ed_flags & ESF_NO_PREDICTION )
return;
// calculate the last usercmd_t we sent that the server has processed
frame = cls.netchan.incoming_acknowledged;
@ -508,11 +520,17 @@ void CL_PredictMovement( void )
// unpredicted pure angled values converted into axis
AngleVectors( cl.refdef.cl_viewangles, cl.refdef.forward, cl.refdef.right, cl.refdef.up );
if( !cl_predict->integer || player->pvClientData->current.ed_flags & ESF_NO_PREDICTION )
if( !CL_IsPredicted( ))
{
// just set angles
cmd = cl.refdef.cmd; // use current command
// run commands even if client predicting is disabled - client expected it
CL_PreRunCmd( player, cmd );
VectorCopy( cl.refdef.cl_viewangles, cl.predicted_angles );
VectorCopy( player->v.view_ofs, cl.predicted_viewofs );
CL_PostRunCmd( player, cmd );
return;
}

View File

@ -17,765 +17,40 @@ TEMPENTS MANAGEMENT
==============================================================
*/
#define SHARD_VOLUME 12.0 // on shard ever n^3 units
#define MAX_TEMPENTS 1024
TEMPENTITY *cl_active_tents, *cl_free_tents;
static TEMPENTITY cl_tents_list[MAX_TEMPENTS];
/*
=================
CL_FreeTempEntity
=================
*/
static void CL_FreeTempEnt( TEMPENTITY *pTemp, TEMPENTITY *pPrev )
int CL_AddEntity( edict_t *pEnt, int ed_type, shader_t customShader )
{
// remove from the active list.
if( pPrev )
{
pPrev->next = pTemp->next;
}
else
{
cl_active_tents = pTemp->next;
}
if( !re || !pEnt )
return false;
// cleanup its data.
if( pTemp->pvEngineData )
Mem_Free( pTemp->pvEngineData );
Mem_Set( pTemp, 0, sizeof( TEMPENTITY ));
// add to the free list.
pTemp->next = cl_free_tents;
cl_free_tents = pTemp;
// let the render reject entity without model
return re->AddRefEntity( pEnt, ed_type, customShader );
}
// free the first low priority tempent it finds.
static bool CL_FreeLowPriorityTempEnt( void )
int CL_AddTempEntity( TEMPENTITY *pTemp, shader_t customShader )
{
TEMPENTITY *pActive = cl_active_tents;
TEMPENTITY *pPrev = NULL;
if( !re || !pTemp )
return false;
while( pActive )
if( !pTemp->pvEngineData )
{
if( pActive->priority == TENTPRIORITY_LOW )
if( pTemp->modelindex && !( pTemp->flags & FTENT_NOMODEL ))
{
CL_FreeTempEnt( pActive, pPrev );
return true;
}
pPrev = pActive;
pActive = pActive->next;
}
return false;
}
// check model
modtype_t type = CM_GetModelType( pTemp->modelindex );
static void CL_PrepareTempEnt( TEMPENTITY *pTemp, int modelIndex )
{
int frameCount;
// Use these to set per-frame and termination conditions / actions
pTemp->flags = FTENT_NONE;
pTemp->die = clgame.globals->time + 0.75f;
if( modelIndex != 0 ) // allocate prevframe only for tents with valid model
pTemp->pvEngineData = Mem_Alloc( cls.mempool, sizeof( studioframe_t ));
else pTemp->flags |= FTENT_NOMODEL;
Mod_GetFrames( modelIndex, &frameCount );
pTemp->modelindex = modelIndex;
pTemp->renderMode = kRenderNormal;
pTemp->renderFX = kRenderFxNone;
VectorSet( pTemp->renderColor, 255, 255, 255 );
pTemp->m_flFrameMax = max( 0, frameCount - 1 );
pTemp->renderAmt = 255;
pTemp->body = 0;
pTemp->skin = 0;
pTemp->fadeSpeed = 0.5f;
pTemp->hitSound = 0;
pTemp->clientIndex = NULLENT_INDEX;
pTemp->bounceFactor = 1;
pTemp->m_flSpriteScale = 1.0f;
}
/*
=================
CL_AllocTempEntity
=================
*/
TEMPENTITY *CL_TempEntAlloc( float *org, int modelIndex )
{
TEMPENTITY *pTemp;
if( !cl_free_tents )
{
MsgDev( D_WARN, "Overflow %d temporary ents!\n", MAX_TEMPENTS );
return NULL;
}
pTemp = cl_free_tents;
cl_free_tents = pTemp->next;
Com_Assert( pTemp->pvEngineData );
CL_PrepareTempEnt( pTemp, modelIndex );
pTemp->priority = TENTPRIORITY_LOW;
if( org ) VectorCopy( org, pTemp->origin );
pTemp->next = cl_active_tents;
cl_active_tents = pTemp;
return pTemp;
}
TEMPENTITY *CL_TempEntAllocNoModel( float *org )
{
return CL_TempEntAlloc( org, 0 );
}
TEMPENTITY *CL_TempEntAllocHigh( float *org, int modelIndex )
{
TEMPENTITY *pTemp;
if( !cl_free_tents )
{
// no temporary ents free, so find the first active low-priority temp ent
// and overwrite it.
CL_FreeLowPriorityTempEnt();
}
if( !cl_free_tents )
{
// didn't find anything? The tent list is either full of high-priority tents
// or all tents in the list are still due to live for > 10 seconds.
MsgDev( D_ERROR, "Couldn't alloc a high priority TENT!\n" );
return NULL;
}
// Move out of the free list and into the active list.
pTemp = cl_free_tents;
cl_free_tents = pTemp->next;
Com_Assert( pTemp->pvEngineData );
CL_PrepareTempEnt( pTemp, modelIndex );
pTemp->priority = TENTPRIORITY_HIGH;
if( org ) VectorCopy( org, pTemp->origin );
pTemp->next = cl_active_tents;
cl_active_tents = pTemp;
return pTemp;
}
TEMPENTITY *CL_TentEntAllocCustom( float *org, int modelIndex, int high, ENTCALLBACK pfnCallback )
{
TEMPENTITY *pTemp;
if( high ) pTemp = CL_TempEntAllocHigh( org, modelIndex );
else CL_TempEntAlloc( org, modelIndex );
if( pTemp && pfnCallback )
{
pTemp->callback = pfnCallback;
pTemp->flags |= FTENT_CLIENTCUSTOM;
}
return pTemp;
}
/*
===============
CL_ClearTempEnts
===============
*/
void CL_ClearTempEnts( void )
{
int i;
cl_active_tents = NULL;
cl_free_tents = cl_tents_list;
for( i = 0; i < MAX_TEMPENTS; i++ )
{
cl_tents_list[i].next = &cl_tents_list[i+1];
if( cl_tents_list[i].pvEngineData )
Mem_Free( cl_tents_list[i].pvEngineData );
cl_tents_list[i].pvEngineData = NULL;
}
cl_tents_list[MAX_TEMPENTS-1].next = NULL;
}
/*
===============
CL_IsActiveTempEnt
===============
*/
bool CL_IsActiveTempEnt( TEMPENTITY *pTemp )
{
bool active = true;
float life;
if( !pTemp ) return false;
life = pTemp->die - clgame.globals->time;
if( life < 0.0f )
{
if( pTemp->flags & FTENT_FADEOUT )
{
int alpha;
if( pTemp->renderMode == kRenderNormal )
pTemp->renderMode = kRenderTransTexture;
alpha = pTemp->startAlpha * ( 1.0f + life * pTemp->fadeSpeed );
if( alpha <= 0 )
if( type == mod_studio || type == mod_sprite )
{
active = false;
alpha = 0;
}
pTemp->renderAmt = alpha;
}
else
{
active = false;
}
}
// never die tempents only die when their die is cleared
if( pTemp->flags & FTENT_NEVERDIE )
{
active = (pTemp->die != 0.0f);
}
return active;
}
bool CL_UpdateTempEnt( TEMPENTITY *pTemp, int framenumber )
{
if( !pTemp ) return false;
return clgame.dllFuncs.pfnUpdateEntity( pTemp, framenumber );
}
/*
===============
CL_AddTempEnts
===============
*/
void CL_AddTempEnts( void )
{
static int gTempEntFrame = 0;
TEMPENTITY *current, *pnext, *pprev;
// nothing to simulate ?
if( !cl_active_tents )
return;
// !!!BUGBUG -- This needs to be time based
// g-cont. it's used only for flickering dlights, what difference ?
gTempEntFrame = (gTempEntFrame + 1) & 31;
current = cl_active_tents;
// !!! Don't simulate while paused.... This is sort of a hack, revisit.
if( cls.key_dest != key_game )
{
while( current )
{
re->AddTmpEntity( current, ED_TEMPENTITY );
current = current->next;
}
}
else
{
pprev = NULL;
while( current )
{
bool fTempEntFreed = false;
pnext = current->next;
// Kill it
if( !CL_IsActiveTempEnt( current ) || !CL_UpdateTempEnt( current, gTempEntFrame ))
{
CL_FreeTempEnt( current, pprev );
fTempEntFreed = true;
// alloc engine data to holds lerping values for studiomdls and sprites
pTemp->pvEngineData = Mem_Alloc( cls.mempool, sizeof( studioframe_t ));
}
else
{
// renderer rejected entity for some reasons...
if( !re->AddTmpEntity( current, ED_TEMPENTITY ))
{
if(!( current->flags & FTENT_PERSIST ))
{
// If we can't draw it this frame, just dump it.
current->die = clgame.globals->time;
// don't fade out, just die
current->flags &= ~FTENT_FADEOUT;
CL_FreeTempEnt( current, pprev );
fTempEntFreed = true;
}
}
pTemp->flags |= FTENT_NOMODEL;
pTemp->modelindex = 0;
}
if( !fTempEntFreed )
pprev = current;
current = pnext;
}
}
}
// let the render reject entity without model
return re->AddTmpEntity( pTemp, ED_TEMPENTITY, customShader );
}
void CL_BloodSprite( float *org, int colorIndex, int modelIndex, float size )
{
TEMPENTITY *pTemp;
if( CM_GetModelType( modelIndex ) == mod_bad )
return;
// Large, single blood sprite is a high-priority tent
if( pTemp = CL_TempEntAllocHigh( org, modelIndex ))
{
int frameCount;
Mod_GetFrames( modelIndex, &frameCount );
pTemp->renderMode = kRenderTransTexture;
pTemp->renderFX = kRenderFxClampMinScale;
pTemp->m_flSpriteScale = Com_RandomFloat(( size / 25.0f), ( size / 35.0f ));
pTemp->flags = FTENT_SPRANIMATE;
CL_GetPaletteColor( colorIndex, pTemp->renderColor );
pTemp->m_flFrameRate = frameCount * 4; // Finish in 0.250 seconds
// play the whole thing once
pTemp->die = clgame.globals->time + (frameCount / pTemp->m_flFrameRate);
pTemp->angles[2] = Com_RandomLong( 0, 360 );
pTemp->bounceFactor = 0;
}
}
void CL_BreakModel( float *pos, float *size, float *dir, float random, float life, int count, int modelIndex, char flags )
{
int i, frameCount;
TEMPENTITY *pTemp;
char type;
if( !modelIndex ) return;
type = flags & BREAK_TYPEMASK;
if( CM_GetModelType( modelIndex ) == mod_bad )
return;
Mod_GetFrames( modelIndex, &frameCount );
if( count == 0 )
{
// assume surface (not volume)
count = (size[0] * size[1] + size[1] * size[2] + size[2] * size[0]) / (3 * SHARD_VOLUME * SHARD_VOLUME);
}
// limit to 100 pieces
if( count > 100 ) count = 100;
for( i = 0; i < count; i++ )
{
vec3_t vecSpot;
// fill up the box with stuff
vecSpot[0] = pos[0] + Com_RandomFloat( -0.5f, 0.5f ) * size[0];
vecSpot[1] = pos[1] + Com_RandomFloat( -0.5f, 0.5f ) * size[1];
vecSpot[2] = pos[2] + Com_RandomFloat( -0.5f, 0.5f ) * size[2];
pTemp = CL_TempEntAlloc( vecSpot, modelIndex );
if( !pTemp ) return;
// keep track of break_type, so we know how to play sound on collision
pTemp->hitSound = type;
if( CM_GetModelType( modelIndex ) == mod_sprite )
pTemp->m_flFrame = Com_RandomLong( 0, frameCount - 1 );
else if( CM_GetModelType( modelIndex ) == mod_studio )
pTemp->body = Com_RandomLong( 0, frameCount - 1 );
pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_SLOWGRAVITY;
if( Com_RandomLong( 0, 255 ) < 200 )
{
pTemp->flags |= FTENT_ROTATE;
pTemp->m_vecAvelocity[0] = Com_RandomFloat( -256, 255 );
pTemp->m_vecAvelocity[1] = Com_RandomFloat( -256, 255 );
pTemp->m_vecAvelocity[2] = Com_RandomFloat( -256, 255 );
}
if(( Com_RandomLong( 0, 255 ) < 100 ) && ( flags & BREAK_SMOKE ))
pTemp->flags |= FTENT_SMOKETRAIL;
if(( type == BREAK_GLASS ) || ( flags & BREAK_TRANS ))
{
pTemp->renderMode = kRenderTransTexture;
pTemp->renderAmt = pTemp->startAlpha = 128;
}
else
{
pTemp->renderMode = kRenderNormal;
pTemp->renderAmt = 255; // set this for fadeout
}
pTemp->m_vecVelocity[0] = dir[0] + Com_RandomFloat( -random, random );
pTemp->m_vecVelocity[1] = dir[1] + Com_RandomFloat( -random, random );
pTemp->m_vecVelocity[2] = dir[2] + Com_RandomFloat( 0, random );
pTemp->die = clgame.globals->time + life + Com_RandomFloat( 0, 1 ); // Add an extra 0-1 secs of life
}
}
/*
===============
CL_TempModel
===============
*/
TEMPENTITY *CL_TempModel( float *pos, float *dir, float *ang, float life, int modelIndex, int type )
{
// alloc a new tempent
TEMPENTITY *pTemp = CL_TempEntAlloc( pos, modelIndex );
if( !pTemp ) return NULL;
// keep track of shell type
switch( type )
{
case 1: pTemp->hitSound = TE_BOUNCE_SHELL; break;
case 2: pTemp->hitSound = TE_BOUNCE_SHOTSHELL; break;
}
if( pos ) VectorCopy( pos, pTemp->origin );
if( dir ) VectorCopy( dir, pTemp->m_vecVelocity );
if( ang ) VectorCopy( ang, pTemp->angles );
pTemp->body = 0;
pTemp->flags = (FTENT_COLLIDEWORLD|FTENT_FADEOUT|FTENT_GRAVITY|FTENT_ROTATE);
pTemp->m_vecAvelocity[0] = Com_RandomFloat( -255, 255 );
pTemp->m_vecAvelocity[1] = Com_RandomFloat( -255, 255 );
pTemp->m_vecAvelocity[2] = Com_RandomFloat( -255, 255 );
pTemp->renderMode = kRenderNormal;
pTemp->startAlpha = 255;
pTemp->die = clgame.globals->time + life;
return pTemp;
}
/*
===============
CL_DefaultSprite
===============
*/
TEMPENTITY *CL_DefaultSprite( float *pos, int spriteIndex, float framerate )
{
TEMPENTITY *pTemp;
int frameCount;
if( !spriteIndex || CM_GetModelType( spriteIndex ) != mod_sprite )
{
MsgDev( D_ERROR, "No Sprite %d!\n", spriteIndex );
return NULL;
}
Mod_GetFrames( spriteIndex, &frameCount );
pTemp = CL_TempEntAlloc( pos, spriteIndex );
if( !pTemp ) return NULL;
pTemp->m_flFrameMax = frameCount - 1;
pTemp->m_flSpriteScale = 1.0f;
pTemp->flags |= FTENT_SPRANIMATE;
if( framerate == 0 ) framerate = 10;
pTemp->m_flFrameRate = framerate;
pTemp->die = clgame.globals->time + (float)frameCount / framerate;
pTemp->m_flFrame = 0;
return pTemp;
}
/*
===============
CL_TempSprite
===============
*/
TEMPENTITY *CL_TempSprite( float *pos, float *dir, float scale, int modelIndex, int rendermode, int renderfx, float a, float life, int flags )
{
TEMPENTITY *pTemp;
int frameCount;
if( !modelIndex )
return NULL;
if( CM_GetModelType( modelIndex ) == mod_bad )
{
MsgDev( D_ERROR, "No model %d!\n", modelIndex );
return NULL;
}
Mod_GetFrames( modelIndex, &frameCount );
pTemp = CL_TempEntAlloc( pos, modelIndex );
if( !pTemp ) return NULL;
pTemp->m_flFrameMax = frameCount - 1;
pTemp->m_flFrameRate = 10;
pTemp->renderMode = rendermode;
pTemp->renderFX = renderfx;
pTemp->m_flSpriteScale = scale;
pTemp->startAlpha = a * 255;
pTemp->renderAmt = a * 255;
pTemp->flags |= flags;
if( pos ) VectorCopy( pos, pTemp->origin );
if( dir ) VectorCopy( dir, pTemp->m_vecVelocity );
if( life ) pTemp->die = clgame.globals->time + life;
else pTemp->die = clgame.globals->time + (frameCount * 0.1f) + 1.0f;
pTemp->m_flFrame = 0;
return pTemp;
}
/*
===============
CL_MuzzleFlash
NOTE: this temp entity live once one frame
so we wan't add it to tent list
===============
*/
void CL_MuzzleFlash( int modelIndex, int entityIndex, int iAttachment, int type )
{
vec3_t pos;
TEMPENTITY *pTemp;
int frameCount;
float scale;
int index;
if( CM_GetModelType( modelIndex ) == mod_bad )
{
MsgDev( D_ERROR, "Invalid muzzleflash %d!\n", modelIndex );
return;
}
Mod_GetFrames( modelIndex, &frameCount );
if( !CL_GetAttachment( entityIndex, iAttachment, pos, NULL ))
{
MsgDev( D_ERROR, "Invalid muzzleflash entity %d!\n", entityIndex );
return;
}
// must set position for right culling on render
pTemp = CL_TempEntAlloc( pos, modelIndex );
if( !pTemp ) return;
index = type % 10;
scale = (type / 10) * 0.1f;
if( scale == 0.0f ) scale = 0.5f;
pTemp->renderMode = kRenderTransAdd;
pTemp->renderAmt = 255;
pTemp->renderFX = 0;
pTemp->die = clgame.globals->time + 0.01; // die at next frame
pTemp->m_flFrame = Com_RandomLong( 0, frameCount - 1 );
pTemp->m_flFrameMax = frameCount - 1;
pTemp->clientIndex = entityIndex;
pTemp->m_iAttachment = iAttachment;
if( index == 0 )
{
// Rifle flash
pTemp->m_flSpriteScale = scale * Com_RandomFloat( 0.5f, 0.6f );
pTemp->angles[2] = 90 * Com_RandomLong( 0, 3 );
}
else
{
pTemp->m_flSpriteScale = scale;
pTemp->angles[2] = Com_RandomLong( 0, 359 );
}
// render now (guranteed that muzzleflash will be draw)
re->AddTmpEntity( pTemp, ED_TEMPENTITY );
}
/*
===============
CL_SpriteExplode
just a preset for exploding sprite
===============
*/
void CL_SpriteExplode( TEMPENTITY *pTemp, float scale, int flags )
{
if( !pTemp ) return;
// NOTE: Xash3D doesn't needs this stuff, because sprites
// have right rendermodes already at loading point
// but i'm leave it for backward compatibility
if( flags & TE_EXPLFLAG_NOADDITIVE )
{
// solid sprite
pTemp->renderMode = kRenderNormal;
pTemp->renderAmt = 255;
}
else if( flags & TE_EXPLFLAG_DRAWALPHA )
{
// alpha sprite
pTemp->renderMode = kRenderTransAlpha;
pTemp->renderAmt = 180;
}
else
{
// additive sprite
pTemp->renderMode = kRenderTransAdd;
pTemp->renderAmt = 120;
}
if( flags & TE_EXPLFLAG_ROTATE )
{
pTemp->angles[2] = Com_RandomLong( 0, 360 );
}
pTemp->renderFX = kRenderFxNone;
pTemp->m_vecVelocity[2] = 8;
pTemp->origin[2] += 10;
pTemp->m_flSpriteScale = scale;
}
/*
===============
CL_SpriteExplode
just a preset for smoke sprite
===============
*/
void CL_SpriteSmoke( TEMPENTITY *pTemp, float scale )
{
int iColor;
if( !pTemp ) return;
iColor = Com_RandomLong( 20, 35 );
pTemp->renderMode = kRenderTransAlpha;
pTemp->renderFX = kRenderFxNone;
pTemp->m_vecVelocity[2] = 30;
VectorSet( pTemp->renderColor, iColor, iColor, iColor );
pTemp->origin[2] += 20;
pTemp->m_flSpriteScale = scale;
pTemp->flags = FTENT_WINDBLOWN;
}
/*
===============
CL_SpriteSpray
just a preset for smoke sprite
===============
*/
void CL_SpriteSpray( float *pos, float *dir, int modelIndex, int count, int speed, int iRand )
{
TEMPENTITY *pTemp;
float noise;
float znoise;
int i, frameCount;
noise = (float)iRand / 100;
// more vertical displacement
znoise = noise * 1.5f;
if( znoise > 1 ) znoise = 1;
if( CM_GetModelType( modelIndex ) == mod_bad )
{
MsgDev( D_ERROR, "No model %d!\n", modelIndex );
return;
}
Mod_GetFrames( modelIndex, &frameCount );
for( i = 0; i < count; i++ )
{
vec3_t velocity;
float scale;
pTemp = CL_TempEntAlloc( pos, modelIndex );
if( !pTemp ) return;
pTemp->renderMode = kRenderTransAlpha;
pTemp->renderFX = kRenderFxNoDissipation;
pTemp->m_flSpriteScale = 0.5f;
pTemp->flags |= FTENT_FADEOUT|FTENT_SLOWGRAVITY;
pTemp->fadeSpeed = 2.0f;
// make the spittle fly the direction indicated, but mix in some noise.
velocity[0] = dir[0] + Com_RandomFloat( -noise, noise );
velocity[1] = dir[1] + Com_RandomFloat( -noise, noise );
velocity[2] = dir[2] + Com_RandomFloat( 0, znoise );
scale = Com_RandomFloat(( speed * 0.8f ), ( speed * 1.2f ));
VectorScale( velocity, scale, pTemp->m_vecVelocity );
pTemp->die = clgame.globals->time + 0.35f;
pTemp->m_flFrame = Com_RandomLong( 0, frameCount - 1 );
}
}
void CL_Sprite_Trail( int type, float *vecStart, float *vecEnd, int modelIndex, int nCount, float flLife, float flSize, float flAmplitude, int nRenderamt, float flSpeed )
{
TEMPENTITY *pTemp;
vec3_t vecDelta, vecDir;
int i, flFrameCount;
if( CM_GetModelType( modelIndex ) == mod_bad )
{
MsgDev( D_ERROR, "No model %d!\n", modelIndex );
return;
}
Mod_GetFrames( modelIndex, &flFrameCount );
VectorSubtract( vecEnd, vecStart, vecDelta );
VectorCopy( vecDelta, vecDir );
VectorNormalize( vecDir );
flAmplitude /= 256.0;
for ( i = 0; i < nCount; i++ )
{
vec3_t vecPos, vecVel;
// Be careful of divide by 0 when using 'count' here...
if ( i == 0 )
{
VectorMA( vecStart, 0, vecDelta, vecPos );
}
else
{
VectorMA( vecStart, i / (nCount - 1.0), vecDelta, vecPos );
}
pTemp = CL_TempEntAlloc( vecPos, modelIndex );
if( !pTemp ) return;
pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_SPRCYCLE | FTENT_FADEOUT | FTENT_SLOWGRAVITY;
VectorScale( vecDir, flSpeed, vecVel );
vecVel[0] += Com_RandomLong( -127, 128 ) * flAmplitude;
vecVel[1] += Com_RandomLong( -127, 128 ) * flAmplitude;
vecVel[2] += Com_RandomLong( -127, 128 ) * flAmplitude;
VectorCopy( vecVel, pTemp->m_vecVelocity );
VectorCopy( vecPos, pTemp->origin );
pTemp->m_flSpriteScale = flSize;
pTemp->renderMode = kRenderGlow;
pTemp->renderFX = kRenderFxNoDissipation;
pTemp->renderAmt = pTemp->startAlpha = nRenderamt;
pTemp->m_flFrame = Com_RandomLong( 0, flFrameCount - 1 );
pTemp->m_flFrameMax = flFrameCount - 1;
pTemp->die = clgame.globals->time + flLife + Com_RandomFloat( 0, 4 );
}
}

View File

@ -48,14 +48,14 @@ void V_SetupRefDef( void )
cl.refdef.time = cl.time * 0.001f;
cl.refdef.frametime = cls.frametime;
cl.refdef.demoplayback = cls.demoplayback;
cl.refdef.smoothing = cl_predict->integer ? false : true;
cl.refdef.smoothing = CL_IsPredicted() ? false : true;
cl.refdef.waterlevel = clent->v.waterlevel;
cl.refdef.flags = cl.render_flags;
cl.refdef.viewsize = 120; // FIXME if you can
cl.refdef.nextView = 0;
// calculate the origin
if( cl_predict->integer && !cl.refdef.demoplayback )
if( CL_IsPredicted( ) && !cl.refdef.demoplayback )
{
// use predicted values
uint i, delta;
@ -93,14 +93,7 @@ void V_AddViewModel( void )
if( cl.refdef.nextView ) return; // add viewmodel only at firstperson pass
if( !cl.frame.valid || cl.refdef.paused ) return;
re->AddRefEntity( &clgame.viewent, ED_VIEWMODEL );
// add in muzzleflash effect
if( clgame.viewent.v.effects & EF_MUZZLEFLASH )
{
clgame.viewent.v.effects &= ~EF_MUZZLEFLASH;
CL_LocalMuzzleFlash();
}
clgame.dllFuncs.pfnAddVisibleEntity( &clgame.viewent, ED_VIEWMODEL );
}
/*

View File

@ -541,6 +541,7 @@ float V_CalcFov( float fov_x, float width, float height );
void CL_InitClientMove( void );
void CL_PredictMove( void );
void CL_CheckPredictionError( void );
bool CL_IsPredicted( void );
//
// cl_phys.c
@ -564,7 +565,6 @@ void CL_ClearEffects( void );
void CL_TestLights( void );
void CL_TestEntities( void );
void CL_LocalMuzzleFlash( void );
void CL_CreateTracer( float *start, float *end );
void CL_GetPaletteColor( int colorIndex, vec3_t outColor );
void CL_FindExplosionPlane( const vec3_t origin, float radius, vec3_t result );
void pfnLightForPoint( const vec3_t point, vec3_t ambientLight );
@ -586,22 +586,8 @@ void CL_PredictMovement (void);
//
// cl_tent.c
//
void CL_AddTempEnts( void );
void CL_ClearTempEnts( void );
struct tempent_s *CL_TempEntAlloc( float *org, int modelIndex );
struct tempent_s *CL_TempEntAllocNoModel( float *org );
struct tempent_s *CL_TempEntAllocHigh( float *org, int modelIndex );
struct tempent_s *CL_TentEntAllocCustom( float *org, int modelIndex, int high, ENTCALLBACK pfnCallback );
struct tempent_s *CL_TempModel( float *pos, float *dir, float *ang, float life, int modelIndex, int soundtype );
struct tempent_s *CL_DefaultSprite( float *pos, int spriteIndex, float framerate );
struct tempent_s *CL_TempSprite( float *pos, float *dir, float scale, int modelIndex, int rendermode, int renderfx, float a, float life, int flags );
void CL_BreakModel( float *pos, float *size, float *dir, float random, float life, int count, int modelIndex, char flags );
void CL_MuzzleFlash( int modelIndex, int entityIndex, int iAttachment, int type );
void CL_SpriteExplode( struct tempent_s *pTemp, float scale, int flags );
void CL_SpriteSmoke( struct tempent_s *pTemp, float scale );
void CL_SpriteSpray( float *pos, float *dir, int modelIndex, int count, int speed, int iRand );
void CL_BloodSprite( float *org, int colorIndex, int modelIndex, float size );
void CL_Sprite_Trail( int type, float *vecStart, float *vecEnd, int modelIndex, int nCount, float flLife, float flSize, float flAmplitude, int nRenderamt, float flSpeed );
int CL_AddEntity( edict_t *pEnt, int ed_type, shader_t customShader );
int CL_AddTempEntity( struct tempent_s *pTemp, shader_t customShader );
//
// cl_con.c

View File

@ -16,6 +16,9 @@
#define MAX_ENT_CLUSTERS 16
#define RATE_MESSAGES 10
// hostflags
#define SVF_SKIPLOCALHOST BIT( 0 )
#define NUM_FOR_EDICT(e) ((int)((edict_t *)(e) - svgame.edicts))
#define EDICT_NUM( num ) SV_EDICT_NUM( num, __FILE__, __LINE__ )
#define STRING( offset ) SV_GetString( offset )

View File

@ -184,6 +184,7 @@ static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_
edict_t *ent;
vec3_t origin;
byte *pset;
sv_client_t *cl;
int leafnum, fullvis = false;
int e, clientcluster, clientarea;
bool force = false;
@ -193,6 +194,19 @@ static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_
// specfically check for it
if( !sv.state ) return;
if( pClient && !portal )
{
// portals can't change hostflags
sv.hostflags = 0;
cl = SV_ClientFromEdict( pClient, true );
Com_Assert( cl == NULL );
// setup hostflags
if( com.atoi( Info_ValueForKey( cl->userinfo, "cl_lw" )) == 1 )
sv.hostflags |= SVF_SKIPLOCALHOST;
}
e = svgame.dllFuncs.pfnSetupVisibility( pViewEnt, pClient, portal, origin );
if( e == 0 ) return; // invalid viewent ?
if( e == -1 ) fullvis = true;
@ -250,7 +264,7 @@ static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_
// if its a portal entity, add everything visible from its camera position
if( !portal && (ent->pvServerData->s.ed_type == ED_PORTAL || ent->pvServerData->s.ed_type == ED_SKYPORTAL))
SV_AddEntitiesToPacket( ent, NULL, frame, ents, true );
SV_AddEntitiesToPacket( ent, pClient, frame, ents, true );
}
}

View File

@ -3160,6 +3160,12 @@ static void pfnPlaybackEvent( int flags, const edict_t *pInvoker, word eventinde
VectorCopy( pInvoker->v.viewangles, args->angles );
else VectorCopy( pInvoker->v.angles, args->angles );
}
else if( SV_ClientFromEdict( pInvoker, true ) && VectorCompare( pInvoker->v.angles, args->angles ))
{
// NOTE: if user specified pPlayer->pev->angles
// silently replace it with viewangles, client expected this
VectorCopy( pInvoker->v.viewangles, args->angles );
}
VectorCopy( pInvoker->v.velocity, args->velocity );
args->ducking = (pInvoker->v.flags & FL_DUCKING) ? true : false;
}
@ -3349,7 +3355,7 @@ int pfnCanSkipPlayer( const edict_t *player )
return false;
}
if( NET_IsLocalAddress( cl->netchan.remote_address ))
if( com.atoi( Info_ValueForKey( cl->userinfo, "cl_lw" )) == 1 )
return true;
return false;
}

View File

@ -254,7 +254,7 @@ static void UI_PlayerSetup_Ownerdraw( void *self )
uiPlayerSetup.refdef.frametime = cls.frametime;
// draw the player model
re->AddRefEntity( &uiPlayerSetup.ent, ED_NORMAL );
re->AddRefEntity( &uiPlayerSetup.ent, ED_NORMAL, -1 );
re->RenderFrame( &uiPlayerSetup.refdef );
}

View File

@ -20,7 +20,7 @@
#define MAX_CLASSNAMES 512 // maxcount of various edicts classnames
#define MAX_SOUNDS 1024 // max unique loaded sounds
#define MAX_MODELS 4096 // total count of brush & studio various models per one map
#define MAX_PARTICLES 32768 // per one frame
#define MAX_PARTICLES 4096 // total particle count per one frame
#define MAX_EDICTS 32768 // absolute limit that never be reached, (do not edit!)
/*

View File

@ -144,8 +144,8 @@ typedef struct render_exp_s
void (*FreeShader)( const char *shadername );
// prepare frame to rendering
bool (*AddRefEntity)( edict_t *pRefEntity, int ed_type );
bool (*AddTmpEntity)( struct tempent_s *TempEnt, int ed_type ); // ED_BEAM, ED_TEMPENTITY etc
bool (*AddRefEntity)( edict_t *pRefEntity, int ed_type, shader_t customShader );
bool (*AddTmpEntity)( struct tempent_s *TempEnt, int ed_type, shader_t customShader );
bool (*AddDynLight)( const void *dlight );
bool (*AddPolygon)( const poly_t *poly );
bool (*AddLightStyle)( int stylenum, vec3_t color );

View File

@ -30,8 +30,8 @@ public:
inline void SetFlags( int flags ) { pev->renderfx |= flags; }
inline void SetStartPos( const Vector& pos ) { pev->origin = pos; }
inline void SetEndPos( const Vector& pos ) { pev->oldorigin = pos; }
void SetStartEntity( edict_t *pEnt );
void SetEndEntity( edict_t *pEnt );
inline void SetStartEntity( edict_t *pEnt ) { pev->aiment = pEnt; }
inline void SetEndEntity( edict_t *pEnt ) { pev->owner = pEnt; }
inline void SetStartAttachment( int attachment ) { pev->colormap = (pev->colormap & 0xFF00)>>8 | attachment; }
inline void SetEndAttachment( int attachment ) { pev->colormap = (pev->colormap & 0xFF) | (attachment<<8); }

View File

@ -225,7 +225,7 @@ public:
};
#endif
void UpdateOnRemove( void );
virtual void UpdateOnRemove( void );
// common member functions
void EXPORT Remove( void );

View File

@ -2018,16 +2018,6 @@ void CBeam::Spawn( void )
pev->solid = SOLID_NOT;
}
void CBeam::SetStartEntity( edict_t *pEnt )
{
pev->owner = pEnt;
}
void CBeam::SetEndEntity( edict_t *pEnt )
{
pev->aiment = pEnt;
}
const Vector &CBeam::GetStartPos( void )
{
int type = GetType();

View File

@ -36,9 +36,10 @@ public:
void Suspend( float flSuspendTime );
void Update( CBasePlayer *m_pPlayer );
void EXPORT Revive( void );
void UpdateOnRemove( void );
void Killed( void ){ UTIL_Remove( this ); }
static CLaserSpot *CreateSpot( void );
static CLaserSpot *CreateSpot( entvars_t *pevOwner = NULL );
};
#endif //BASEINFO_H

View File

@ -196,12 +196,19 @@ LINK_ENTITY_TO_CLASS( floorent, CFloorEnt );
//====================================================================
// Laser pointer target
//====================================================================
CLaserSpot *CLaserSpot::CreateSpot( void )
CLaserSpot *CLaserSpot::CreateSpot( entvars_t *pevOwner )
{
CLaserSpot *pSpot = GetClassPtr( (CLaserSpot *)NULL );
pSpot->pev->classname = MAKE_STRING( "misc_laserdot" );
pSpot->Spawn();
pSpot->pev->classname = MAKE_STRING( "misc_laserdot" );
if( pevOwner )
{
// predictable laserspot (cl_lw must be set to 1)
pSpot->pev->flags |= FL_SKIPLOCALHOST;
pSpot->pev->owner = ENT( pevOwner );
pevOwner->effects |= EF_LASERSPOT;
}
return pSpot;
}
@ -219,11 +226,12 @@ void CLaserSpot::Spawn( void )
// laser dot settings
pev->movetype = MOVETYPE_NONE;
pev->solid = SOLID_NOT;
pev->scale = 1.0;
pev->rendermode = kRenderGlow;
pev->renderfx = kRenderFxNoDissipation;
pev->renderamt = 255;
pev->rendercolor = Vector( 200, 12, 12 );
UTIL_SetModel( ENT( pev ), "sprites/laserdot.spr" );
UTIL_SetOrigin( this, pev->origin );
}
@ -231,6 +239,9 @@ void CLaserSpot::Spawn( void )
void CLaserSpot::Suspend( float flSuspendTime )
{
pev->effects |= EF_NODRAW;
if( !FNullEnt( pev->owner ))
pev->owner->v.effects &= ~EF_LASERSPOT;
// -1 means suspend indefinitely
if( flSuspendTime == -1 ) SetThink( NULL );
@ -243,10 +254,22 @@ void CLaserSpot::Suspend( float flSuspendTime )
void CLaserSpot::Revive( void )
{
if( !FNullEnt( pev->owner ))
pev->owner->v.effects |= EF_LASERSPOT;
pev->effects &= ~EF_NODRAW;
SetThink( NULL );
}
void CLaserSpot::UpdateOnRemove( void )
{
// tell the owner about laserspot
if( !FNullEnt( pev->owner ))
pev->owner->v.effects &= ~EF_LASERSPOT;
CBaseEntity :: UpdateOnRemove ();
}
void CLaserSpot::Update( CBasePlayer *m_pPlayer )
{
TraceResult tr;

View File

@ -407,13 +407,13 @@ void CRpgRocket :: IgniteThink( void )
void CRpgRocket :: CreateTrail( void )
{
if(b_setup) return;
if( b_setup ) return;
// make rocket sound after save\load
EMIT_SOUND( ENT(pev), CHAN_VOICE, "weapons/rpg/rocket1.wav", 1, 0.5 );
// restore rocket trail
SFX_Trail(entindex(), m_iTrail);
SFX_Trail( entindex(), m_iTrail );
b_setup = TRUE;
}

View File

@ -1757,7 +1757,7 @@ void CBasePlayerWeapon::ItemPostFrame( void )
}
if( m_iSpot && !m_pSpot ) // enable laser dot
{
m_pSpot = CLaserSpot::CreateSpot();
m_pSpot = CLaserSpot::CreateSpot( m_pPlayer->pev );
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/spot_on.wav", 1, ATTN_NORM );
m_iSkin = 1; // enable screen
}

View File

@ -1474,7 +1474,7 @@ player is 1 if the ent/e is a player and 0 otherwise
pSet is either the PAS or PVS that we previous set up. We can use it to ask the engine to filter the entity against the PAS or PVS.
we could also use the pas/ pvs that we set in SetupVisibility, if we wanted to. Caching the value is valid in that case, but still only for the current frame
*/
int AddToFullPack( edict_t *pHost, edict_t *pClient, edict_t *pEdict, int hostflags, int hostarea, byte *pSet )
int AddToFullPack( edict_t *pView, edict_t *pHost, edict_t *pEdict, int hostflags, int hostarea, byte *pSet )
{
if( FNullEnt( pEdict )) return 0; // never adding invalid entities
@ -1482,13 +1482,17 @@ int AddToFullPack( edict_t *pHost, edict_t *pClient, edict_t *pEdict, int hostfl
if( pEdict->v.flags & FL_DORMANT )
return 0;
if( FNullEnt( pView )) pView = pHost; // pfnCustomView not set
CBaseEntity *pViewEntity = (CBaseEntity *)CBaseEntity::Instance( pView );
BOOL bIsPortalPass = FALSE;
if( FNullEnt( pHost )) pHost = pClient; // pfnCustomView not set
if( FNullEnt( pClient )) bIsPortalPass = TRUE; // portal pass detected
if( pViewEntity && pViewEntity->m_iClassType == ED_PORTAL )
bIsPortalPass = TRUE; // view from portal camera
// don't send spectators to other players
if( !bIsPortalPass && (( pEdict->v.flags & FL_SPECTATOR ) && ( pEdict != pHost )))
if(( pEdict->v.flags & FL_SPECTATOR ) && ( pEdict != pHost ))
{
return 0;
}
@ -1533,7 +1537,7 @@ int AddToFullPack( edict_t *pHost, edict_t *pClient, edict_t *pEdict, int hostfl
else entorigin = pEntity->pev->origin;
// precalc delta distance for sounds
delta = pHost->v.origin - entorigin;
delta = pView->v.origin - entorigin;
}
// check visibility

View File

@ -42,7 +42,7 @@ extern void SpectatorDisconnect ( edict_t *pEntity );
extern void SpectatorThink ( edict_t *pEntity );
extern int SetupVisibility( edict_t *pViewEntity, edict_t *pClient, int portal, float *rgflViewOrg );
extern int AddToFullPack( edict_t *pHost, edict_t *pClient, edict_t *pEdict, int hostflags, int hostarea, byte *pSet );
extern int AddToFullPack( edict_t *pView, edict_t *pHost, edict_t *pEdict, int hostflags, int hostarea, byte *pSet );
extern void CmdStart( const edict_t *player, const usercmd_t *cmd, unsigned int random_seed );
extern void CmdEnd ( const edict_t *player );

View File

@ -512,10 +512,13 @@ static void S_IssuePlaySounds( void )
while( 1 )
{
ps = s_pendingPlaySounds.next;
if(ps == &s_pendingPlaySounds)
break; // no more pending playSounds
if( ps->beginTime > Sys_DoubleTime())
if( ps == &s_pendingPlaySounds )
break; // no more pending playSounds
if( ps->beginTime > Sys_DoubleTime( ))
break; // No more pending playSounds this frame
// pick a channel and start the sound effect
ch = S_PickChannel( ps->entnum, ps->entchannel );
if( !ch )
@ -585,7 +588,7 @@ void S_StartSound( const vec3_t pos, int entnum, int channel, sound_t handle, fl
ps->sfx = sfx;
ps->entnum = entnum;
ps->entchannel = channel;
ps->use_loop = (flags & SND_STOP_LOOPING) ? false : true;
ps->use_loop = (flags & (SND_STOP_LOOPING|SND_STOP)) ? false : true;
if( pos )
{
@ -768,7 +771,7 @@ void S_Update( ref_params_t *fd )
continue;
}
}
else if( ch->loopstart >= 0 )
else if( ch->loopstart >= 0 && ch->volume > 0.0f )
{
if( S_ChannelState( ch ) == AL_STOPPED )
{

View File

@ -352,7 +352,7 @@ public:
};
#endif
void UpdateOnRemove( void );
virtual void UpdateOnRemove( void );
// common member functions
void EXPORT SUB_Remove( void );

View File

@ -1306,7 +1306,7 @@ player is 1 if the ent/e is a player and 0 otherwise
pSet is either the PAS or PVS that we previous set up. We can use it to ask the engine to filter the entity against the PAS or PVS.
we could also use the pas/ pvs that we set in SetupVisibility, if we wanted to. Caching the value is valid in that case, but still only for the current frame
*/
int AddToFullPack( edict_t *pHost, edict_t *pClient, edict_t *pEdict, int hostflags, int hostarea, byte *pSet )
int AddToFullPack( edict_t *pView, edict_t *pHost, edict_t *pEdict, int hostflags, int hostarea, byte *pSet )
{
if( FNullEnt( pEdict )) return 0; // never adding invalid entities
@ -1314,13 +1314,17 @@ int AddToFullPack( edict_t *pHost, edict_t *pClient, edict_t *pEdict, int hostfl
if( pEdict->v.flags & FL_DORMANT )
return 0;
if( FNullEnt( pView )) pView = pHost; // pfnCustomView not set
CBaseEntity *pViewEntity = (CBaseEntity *)CBaseEntity::Instance( pView );
BOOL bIsPortalPass = FALSE;
if( FNullEnt( pHost )) pHost = pClient; // pfnCustomView not set
if( FNullEnt( pClient )) bIsPortalPass = TRUE; // portal pass detected
if( pViewEntity && pViewEntity->m_iClassType == ED_PORTAL )
bIsPortalPass = TRUE; // view from portal camera
// don't send spectators to other players
if( !bIsPortalPass && (( pEdict->v.flags & FL_SPECTATOR ) && ( pEdict != pHost )))
if(( pEdict->v.flags & FL_SPECTATOR ) && ( pEdict != pHost ))
{
return 0;
}
@ -1365,7 +1369,7 @@ int AddToFullPack( edict_t *pHost, edict_t *pClient, edict_t *pEdict, int hostfl
else entorigin = pEntity->pev->origin;
// precalc delta distance for sounds
delta = pHost->v.origin - entorigin;
delta = pView->v.origin - entorigin;
}
// check visibility
@ -1385,6 +1389,7 @@ int AddToFullPack( edict_t *pHost, edict_t *pClient, edict_t *pEdict, int hostfl
// don't send entity to local client if the client says it's predicting the entity itself.
if( pEntity->pev->flags & FL_SKIPLOCALHOST )
{
if( bIsPortalPass ) return 0;
if(( hostflags & 1 ) && ( pEntity->pev->owner == pHost ))
return 0;
}

View File

@ -46,7 +46,7 @@ extern void SpectatorThink ( edict_t *pEntity );
extern void Sys_Error( const char *error_string );
extern int SetupVisibility( edict_t *pViewEntity, edict_t *pClient, int portal, float *rgflViewOrg );
extern int AddToFullPack( edict_t *pHost, edict_t *pClient, edict_t *pEdict, int hostflags, int hostarea, byte *pSet );
extern int AddToFullPack( edict_t *pView, edict_t *pHost, edict_t *pEdict, int hostflags, int hostarea, byte *pSet );
extern void CmdStart( const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed );
extern void CmdEnd ( const edict_t *player );

View File

@ -204,17 +204,6 @@ void CBeam::Spawn( void )
Precache( );
}
void CBeam::SetStartEntity( edict_t *pEnt )
{
pev->owner = pEnt;
}
void CBeam::SetEndEntity( edict_t *pEnt )
{
pev->aiment = pEnt;
}
// These don't take attachments into account
const Vector &CBeam::GetStartPos( void )
{
@ -250,7 +239,7 @@ CBeam *CBeam::BeamCreate( const char *pSpriteName, int width )
{
// Create a new entity with CBeam private data
CBeam *pBeam = GetClassPtr( (CBeam *)NULL );
pBeam->pev->classname = MAKE_STRING("beam");
pBeam->pev->classname = MAKE_STRING( "beam" );
pBeam->BeamInit( pSpriteName, width );
@ -4143,21 +4132,6 @@ void CEnvDecal::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE use
if ( entityIndex )
WRITE_SHORT( (int)VARS(trace.pHit)->modelindex );
MESSAGE_END();
Vector mirpos = UTIL_MirrorPos(trace.vecEndPos);
if(mirpos != Vector(0,0,0))
{
MESSAGE_BEGIN( MSG_BROADCAST, gmsgTempEntity);
WRITE_BYTE( TE_BSPDECAL );
WRITE_COORD( mirpos.x );
WRITE_COORD( mirpos.y );
WRITE_COORD( mirpos.z );
WRITE_SHORT( iTexture );
WRITE_SHORT( entityIndex );
if ( entityIndex )
WRITE_SHORT( (int)VARS(trace.pHit)->modelindex );
MESSAGE_END();
}
}
void CEnvDecal::Spawn( void )
@ -4657,7 +4631,7 @@ void CParticle::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE use
}
//=========================================================
// G-Cont - env_mirror, mirroring models and decals
// G-Cont - env_mirror (engine feature)
//=========================================================
class CEnvMirror : public CBaseEntity
@ -4665,78 +4639,36 @@ class CEnvMirror : public CBaseEntity
public:
void Spawn( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void KeyValue( KeyValueData* pkvd);
virtual int ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
void Think( void );
STATE GetState( void ) { return pev->impulse ? STATE_ON:STATE_OFF; }
STATE GetState( void ) { return (pev->effects & EF_NODRAW) ? STATE_OFF : STATE_ON; }
};
void CEnvMirror :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "radius"))
{
pev->waterlevel = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else CBaseEntity::KeyValue( pkvd );
}
LINK_ENTITY_TO_CLASS( env_mirror, CEnvMirror );
void CEnvMirror :: Spawn( void )
{
if (!m_pMoveWith) pev->flags |= FL_WORLDBRUSH;
pev->angles = g_vecZero;
pev->movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything
pev->solid = SOLID_BSP;
pev->impulse = TRUE;//enable mirror
Precache();
SET_MODEL( ENT(pev), STRING(pev->model) );
pev->body = pev->rendermode;//save current rendermode
//Smart field system Š
if (!pev->waterlevel) pev->waterlevel = 330;
if (!pev->frags)
{
if (pev->size.y > pev->size.x && pev->size.z > pev->size.x) pev->frags = 0;
if (pev->size.x > pev->size.y && pev->size.z > pev->size.y) pev->frags = 1;
if (pev->size.y > pev->size.z && pev->size.x > pev->size.z) pev->frags = 2;
}
}
void CEnvMirror :: Think( void )
{
MESSAGE_BEGIN(MSG_BROADCAST, gmsgSetMirror, VecBModelOrigin(pev));
WRITE_COORD(VecBModelOrigin(pev).x); //mirror origin
WRITE_COORD(VecBModelOrigin(pev).y);
WRITE_COORD(VecBModelOrigin(pev).z);
WRITE_SHORT(pev->waterlevel); //radius
WRITE_BYTE(pev->frags); //type
WRITE_BYTE(pev->impulse); //state
MESSAGE_END();
// setup mirror
SetObjectClass( ED_PORTAL );
pev->modelindex = 1; // world
pev->oldorigin = pev->origin;
}
void CEnvMirror :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if (useType == USE_TOGGLE)
if ( useType == USE_TOGGLE )
{
if(pev->impulse) useType = USE_OFF;
if( GetState() == STATE_ON )
useType = USE_OFF;
else useType = USE_ON;
}
if(useType == USE_ON)
if ( useType == USE_ON )
{
pev->impulse = TRUE;
pev->rendermode = pev->body;
pev->effects &= ~EF_NODRAW;
}
else if(useType == USE_OFF)
else if ( useType == USE_OFF )
{
pev->impulse = FALSE;
pev->rendermode = kRenderNormal;
pev->effects |= EF_NODRAW;
}
Think();
}
//=========================================================
// G-Cont - env_rain, use triAPI

View File

@ -128,8 +128,8 @@ public:
inline void SetFlags( int flags ) { pev->renderfx |= flags; }
inline void SetStartPos( const Vector& pos ) { pev->origin = pos; }
inline void SetEndPos( const Vector& pos ) { pev->oldorigin = pos; }
void SetStartEntity( edict_t *pEnt );
void SetEndEntity( edict_t *pEnt );
inline void SetStartEntity( edict_t *pEnt ) { pev->aiment = pEnt; }
inline void SetEndEntity( edict_t *pEnt ) { pev->owner = pEnt; }
inline void SetStartAttachment( int attachment ) { pev->colormap = (pev->colormap & 0xFF00)>>8 | attachment; }
inline void SetEndAttachment( int attachment ) { pev->colormap = (pev->colormap & 0xFF) | (attachment<<8); }

View File

@ -78,8 +78,6 @@ public:
BOOL HasAmmo( void );
void UseAmmo( int count );
int flags (void) { return ENGINE_CANSKIP( m_pPlayer->edict()) ? NULL : FEV_NOTHOST; };
enum EGON_FIRESTATE { FIRE_OFF = 0, FIRE_CHARGE };
enum EGON_FIREMODE { FIRE_NARROW = 0, FIRE_WIDE};
@ -215,7 +213,7 @@ void CEgon::PrimaryAttack( void )
m_flAmmoUseTime = UTIL_WeaponTimeBase();// start using ammo ASAP.
PLAYBACK_EVENT_FULL( flags(), m_pPlayer->edict(), m_usEgonFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, pev->body, m_fireMode, 1, m_fireState );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usEgonFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, pev->body, m_fireMode, 1, m_fireState );
SendWeaponAnim( EGON_FIRECYCLE );
m_shakeTime = 0;
@ -235,16 +233,15 @@ void CEgon::PrimaryAttack( void )
if ( m_shootTime != 0 && UTIL_WeaponTimeBase() > m_shootTime )
{
PLAYBACK_EVENT_FULL( flags(), m_pPlayer->edict(), m_usEgonFire, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, pev->body, m_fireMode, 0, m_fireState );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usEgonFire, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, pev->body, m_fireMode, 0, m_fireState );
SendWeaponAnim( EGON_FIRECYCLE );
m_shootTime = 0;
}
if(!AnimRestore)
if( !AnimRestore )
{
PLAYBACK_EVENT_FULL( flags(), m_pPlayer->edict(), m_usEgonFire, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, pev->body, m_fireMode, 0, m_fireState );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usEgonFire, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, pev->body, m_fireMode, 0, m_fireState );
SendWeaponAnim( EGON_FIRECYCLE );
m_shootTime = 0;
m_fireMode = (EGON_FIREMODE)m_iBody;
AnimRestore = TRUE;
}
if ( !HasAmmo() )
@ -263,7 +260,7 @@ void CEgon::SecondaryAttack( void )
{
UpdateScreen();
if ( m_fireState != FIRE_OFF ) EndAttack();
if(m_iBody == 0)
if( m_iBody == 0 )
{
SendWeaponAnim( EGON_ALTFIREON );
m_fireMode = FIRE_NARROW;
@ -395,9 +392,16 @@ void CEgon::Fire( const Vector &vecOrigSrc, const Vector &vecDir )
break;
}
if ( timedist < 0 ) timedist = 0;
else if ( timedist > 1 ) timedist = 1;
timedist = 1-timedist;
if ( timedist < 0 )
{
timedist = 0;
}
else if ( timedist > 1 )
{
timedist = 1;
}
timedist = 1 - timedist;
UpdateEffect( tmpSrc, tr.vecEndPos, timedist );
UpdateScreen();
@ -409,13 +413,13 @@ void CEgon::UpdateEffect( const Vector &startPoint, const Vector &endPoint, floa
if ( !m_pBeam ) CreateEffect();
m_pBeam->SetStartPos( endPoint );
m_pBeam->SetBrightness( 255 - (timeBlend*180) );
m_pBeam->SetWidth( 40 - (timeBlend*20) );
m_pBeam->SetBrightness( 255 - ( timeBlend * 180 ));
m_pBeam->SetWidth( 40 - ( timeBlend * 20 ));
if ( m_fireMode == FIRE_WIDE )
m_pBeam->SetColor( 30 + (25*timeBlend), 30 + (30*timeBlend), 64 + 80*fabs(sin(UTIL_WeaponTimeBase()*10)) );
m_pBeam->SetColor( 30 + (25 * timeBlend), 30 + (30 * timeBlend), 64 + 80 * fabs( sin( UTIL_WeaponTimeBase() * 10 )));
else
m_pBeam->SetColor( 60 + (25*timeBlend), 120 + (30*timeBlend), 64 + 80*fabs(sin(UTIL_WeaponTimeBase()*10)) );
m_pBeam->SetColor( 60 + (25 * timeBlend), 120 + (30 * timeBlend), 64 + 80 * fabs( sin( UTIL_WeaponTimeBase() * 10 )));
UTIL_SetOrigin( m_pSprite, endPoint );
m_pSprite->pev->frame += 8 * gpGlobals->frametime;
@ -494,7 +498,7 @@ void CEgon::DestroyEffect( void )
void CEgon::EndAttack( void )
{
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE, m_pPlayer->edict(), m_usEgonStop, 0, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, 0.0, 0.0, m_fireState, pev->body, 0, 0 );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usEgonStop, 0, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, 0.0, 0.0, pev->body, m_fireMode, 0, m_fireState );
m_fireState = FIRE_OFF;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0;

View File

@ -190,7 +190,7 @@ void CEnvExplosion::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE
// draw fireball
if ( !( pev->spawnflags & SF_ENVEXPLOSION_NOFIREBALL ) )
{
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
MESSAGE_BEGIN( MSG_PAS, gmsgTempEntity, pev->origin );
WRITE_BYTE( TE_EXPLOSION);
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );

View File

@ -216,8 +216,14 @@ void CGauss::SecondaryAttack()
{
m_iChargeLevel++;
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
if ( IsMultiplayer() ) m_flTimeUpdate = UTIL_WeaponTimeBase() + 0.05;
else m_flTimeUpdate = UTIL_WeaponTimeBase() + 0.15;
if ( IsMultiplayer() )
{
m_flTimeUpdate = UTIL_WeaponTimeBase() + 0.05;
}
else
{
m_flTimeUpdate = UTIL_WeaponTimeBase() + 0.15;
}
int pitch = 95 + 10 * m_iChargeLevel;
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usGaussSpin, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, pitch, 0, ( m_iSoundState == SND_CHANGE_PITCH ) ? 1 : 0, 0 );
}
@ -229,8 +235,8 @@ void CGauss::SecondaryAttack()
}
if(!AnimRestore)
{
if(m_fInAttack == 1) SendWeaponAnim( GAUSS_SPINUP );
if(m_fInAttack >= 2) SendWeaponAnim( GAUSS_SPIN );
if( m_fInAttack == 1 ) SendWeaponAnim( GAUSS_SPINUP );
if( m_fInAttack >= 2 ) SendWeaponAnim( GAUSS_SPIN );
AnimRestore = TRUE;
}

View File

@ -124,7 +124,7 @@ void CGrenade::Explode( TraceResult *pTrace, int bitsDamageType )
void CGrenade::Smoke( void )
{
if (UTIL_PointContents ( pev->origin ) == CONTENTS_WATER)
if ( UTIL_PointContents ( pev->origin ) == CONTENTS_WATER )
{
UTIL_Bubbles( pev->origin - Vector( 64, 64, 64 ), pev->origin + Vector( 64, 64, 64 ), 100 );
}
@ -139,20 +139,6 @@ void CGrenade::Smoke( void )
WRITE_BYTE( (pev->dmg - 50) * 0.80 ); // scale * 10
WRITE_BYTE( 12 ); // framerate
MESSAGE_END();
Vector mirpos = UTIL_MirrorPos(pev->origin);
if(mirpos != Vector(0,0,0))
{
MESSAGE_BEGIN( MSG_PVS, gmsgTempEntity, pev->origin );
WRITE_BYTE( TE_SMOKE );
WRITE_COORD( mirpos.x );
WRITE_COORD( mirpos.y );
WRITE_COORD( mirpos.z );
WRITE_SHORT( g_sModelIndexSmoke );
WRITE_BYTE( (pev->dmg - 50) * 0.80 ); // scale * 10
WRITE_BYTE( 12 ); // framerate
MESSAGE_END();
}
}
UTIL_Remove( this );
}

View File

@ -230,7 +230,6 @@ int gmsgCamData; // for trigger_viewset
int gmsgRainData = 0;
int gmsgSetBody = 0;//change body for view weapon model
int gmsgSetSkin = 0;//change skin for view weapon model
int gmsgSetMirror = 0;//set mirror
int gmsgTempEntity = 0;
int gmsgWeaponAnim = 0;
int gmsgIntermission = 0;
@ -297,7 +296,6 @@ void LinkUserMessages( void )
gmsgRainData = REG_USER_MSG("RainData", 28 );
gmsgSetBody = REG_USER_MSG("SetBody", 1);
gmsgSetSkin = REG_USER_MSG("SetSkin", 1);
gmsgSetMirror = REG_USER_MSG("SetMirror", 10);
}
LINK_ENTITY_TO_CLASS( player, CBasePlayer );
@ -4093,49 +4091,6 @@ void CBasePlayer :: UpdateClientData( void )
FireTargets( "game_playerjoin", this, this, USE_TOGGLE, 0 );
}
}
//Xash3D no more haves "skyMessage"
#if 0
CBaseEntity *pSky = UTIL_FindEntityByClassname( NULL, "env_sky" );
if(!FNullEnt(pSky))
{
MESSAGE_BEGIN(MSG_ONE, gmsgSetSky, NULL, pev );
WRITE_BYTE( 1 ); // mode
WRITE_COORD(pSky->pev->origin.x); // view position
WRITE_COORD(pSky->pev->origin.y);
WRITE_COORD(pSky->pev->origin.z);
MESSAGE_END();
//g-cont. found all skyents
edict_t *pent = UTIL_EntitiesInPVS( pSky->edict() );
while ( !FNullEnt( pent ) )
{
//Msg("%s is Sky Entity\n", STRING(pent->v.classname ));
SetBits(pent->v.flags, FL_IMMUNE_WATER );//hack
pent = pent->v.chain;
}
}
#endif
//update all mirrors
edict_t *pFind;
int numMirrors = 0;
pFind = FIND_ENTITY_BY_CLASSNAME( NULL, "env_mirror" );
while ( !FNullEnt( pFind ) )
{
CBaseEntity *pMirror = CBaseEntity::Instance( pFind );
if(numMirrors > 32) break;
if ( pMirror )
{
pMirror->Think();
pMirror->SetNextThink(0.01);
numMirrors++;
}
pFind = FIND_ENTITY_BY_CLASSNAME( pFind, "env_mirror" );
}
FireTargets( "game_playerspawn", this, this, USE_TOGGLE, 0 );
InitStatusBar();

View File

@ -342,7 +342,6 @@ extern int gmsgHudText;
extern int gmsgParticle; // LRC
extern int gmsgSetBody;
extern int gmsgSetSkin;
extern int gmsgSetMirror;
extern int gmsgShake;
extern int gmsgFade;
extern int gmsgWeaponAnim;

View File

@ -52,7 +52,6 @@ public:
BOOL ShouldWeaponIdle( void ) { return TRUE; };
CLaserSpot *m_pSpot;
CLaserSpot *m_pMirSpot;
};
class CRpgRocket : public CGrenade
@ -408,7 +407,6 @@ void CRpg::Reload( void )
if ( m_iClip == 0 )
{
if ( m_pSpot && m_iOverloadLevel ) m_pSpot->Suspend( 2.1 );
if ( m_pMirSpot && m_iOverloadLevel ) m_pMirSpot->Suspend( 2.1 );
m_iBody = 0;//show rocket
DefaultReload( RPG_MAX_CLIP, RPG_RELOAD, 2.1 );
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT ( 10, 15 );
@ -417,11 +415,11 @@ void CRpg::Reload( void )
void CRpg::UpdateSpot( void )
{
if (m_iOverloadLevel)
if ( m_iOverloadLevel )
{
if (!m_pSpot)
{
m_pSpot = CLaserSpot::CreateSpot();
m_pSpot = CLaserSpot::CreateSpot( m_pPlayer->pev );
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/spot_on.wav", 1, ATTN_NORM);
}
@ -433,23 +431,16 @@ void CRpg::UpdateSpot( void )
UTIL_TraceLine ( vecSrc, vecSrc + vecAiming * 8192, dont_ignore_monsters, ignore_glass, ENT(m_pPlayer->pev), &tr );
float flLength = (tr.vecEndPos - vecSrc).Length();
//disable scale feature
//m_pSpot->pev->scale = flLength / 650;
int m_iSpotBright = (1 / log(flLength / 0.3))*1700;
if (m_iSpotBright > 255 ) m_iSpotBright = 255;
// disable scale feature
// m_pSpot->pev->scale = flLength / 650;
m_iSpotBright = m_iSpotBright + RANDOM_LONG (1, flLength / 200);
int m_iSpotBright = ( 1 / log( flLength / 0.3 )) * 1700;
if ( m_iSpotBright > 255 ) m_iSpotBright = 255;
m_iSpotBright = m_iSpotBright + RANDOM_LONG ( 1, flLength / 200 );
m_pSpot->pev->renderamt = m_iSpotBright;
UTIL_SetOrigin( m_pSpot, tr.vecEndPos + tr.vecPlaneNormal * 0.1);
Vector mirpos = UTIL_MirrorPos(tr.vecEndPos + tr.vecPlaneNormal * 0.1);
if(mirpos != Vector(0,0,0))
{
if(!m_pMirSpot)m_pMirSpot = CLaserSpot::CreateSpot();
UTIL_SetOrigin( m_pMirSpot, mirpos);
m_pMirSpot->pev->renderamt = m_iSpotBright;
}
UTIL_SetOrigin( m_pSpot, tr.vecEndPos + tr.vecPlaneNormal * 0.1 );
}
UpdateScreen();// update rocket screen
@ -483,11 +474,6 @@ void CRpg::ShutdownScreen ( void )
m_pSpot = NULL;
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/spot_off.wav", 1, ATTN_NORM);
}
if(m_pMirSpot)
{
m_pMirSpot->Killed( NULL, GIB_NEVER );
m_pMirSpot = NULL;
}
}
void CRpg::WeaponIdle( void )

View File

@ -263,17 +263,6 @@ void CTripmineGrenade :: MakeBeam( void )
m_pBeam->SetColor( 0, 214, 198 );
m_pBeam->SetScrollRate( 255 );
m_pBeam->SetBrightness( 50 );
mirpos = UTIL_MirrorPos(vecTmpEnd + gpGlobals->v_up * 1.4);
mirend = UTIL_MirrorPos(pev->origin + gpGlobals->v_up * 1.4);
if(mirpos != mirend)
{
m_pMirBeam = CBeam::BeamCreate( g_pModelNameLaser, 5 );
m_pMirBeam->PointsInit( mirpos, mirend );
m_pMirBeam->SetColor( 0, 214, 198 );
m_pMirBeam->SetScrollRate( 255 );
m_pMirBeam->SetBrightness( 50 );
}
}

View File

@ -3280,97 +3280,4 @@ int HaveCamerasInPVS( edict_t* edict )
}
}
return 0;
}
Vector UTIL_GetMirrorOrigin(CBaseEntity *pMirror, Vector pos)
{
Vector result = pos;
switch ((int)pMirror->pev->frags)
{
case 0:
result[0] = pMirror->pev->origin[0]*2 - pos[0];
break;
case 1:
result[1] = pMirror->pev->origin[1]*2 - pos[1];
break;
case 2:
default:
result[2] = pMirror->pev->origin[2]*2 - pos[2];
break;
}
return result;
}
Vector UTIL_GetMirrorAngles (CBaseEntity *pMirror, Vector angles )
{
Vector result = angles;
switch ((int)pMirror->pev->frags)
{
case 0:
result[0] = -result[0];
break;
case 1:
result[1] = -result[1];
break;
case 2:
default:
result[2] = -result[2];
break;
}
return result;
}
Vector UTIL_MirrorVector( Vector angles )
{
Vector result = angles;
edict_t *pFind;
int numMirrors = 0;
pFind = FIND_ENTITY_BY_CLASSNAME( NULL, "env_mirror" );
while ( !FNullEnt( pFind ) )
{
CBaseEntity *pMirror = CBaseEntity::Instance( pFind );
if(numMirrors > 32) break;
if ( pMirror )
{
numMirrors++;
if(!pMirror->pev->impulse) continue;
result = UTIL_GetMirrorAngles(pMirror, angles);
}
pFind = FIND_ENTITY_BY_CLASSNAME( pFind, "env_mirror" );
}
return result;
}
Vector UTIL_MirrorPos ( Vector endpos )
{
Vector mirpos(0, 0, 0);
edict_t *pFind;
int numMirrors = 0;
pFind = FIND_ENTITY_BY_CLASSNAME( NULL, "env_mirror" );
while ( !FNullEnt( pFind ) )
{
CBaseEntity *pMirror = CBaseEntity::Instance( pFind );
if(numMirrors > 32) break;
if ( pMirror )
{
numMirrors++;
if(!pMirror->pev->impulse) continue;
Vector delta;
float dist;
delta = pMirror->Center() - endpos;
dist = delta.Length();
if(pMirror->pev->waterlevel < dist) continue;
mirpos = UTIL_GetMirrorOrigin(pMirror, endpos);
}
pFind = FIND_ENTITY_BY_CLASSNAME( pFind, "env_mirror" );
}
return mirpos;
}

View File

@ -633,7 +633,5 @@ CBaseEntity* UTIL_FollowReference( CBaseEntity* pStartEntity, const char* szName
// for trigger_viewset
int HaveCamerasInPVS( edict_t* edict );
BOOL IsMultiplayer ( void );
Vector UTIL_MirrorVector( Vector angles );
Vector UTIL_MirrorPos ( Vector endpos );
#endif //UTIL_H

View File

@ -88,22 +88,29 @@ LINK_ENTITY_TO_CLASS( laser_spot, CLaserSpot );
//=========================================================
//=========================================================
CLaserSpot *CLaserSpot::CreateSpot( void )
CLaserSpot *CLaserSpot::CreateSpot( entvars_t *pevOwner )
{
CLaserSpot *pSpot = GetClassPtr( (CLaserSpot *)NULL );
pSpot->Spawn();
pSpot->pev->classname = MAKE_STRING("laser_spot");
if( pevOwner )
{
// predictable laserspot (cl_lw must be set to 1)
pSpot->pev->flags |= FL_SKIPLOCALHOST;
pSpot->pev->owner = ENT( pevOwner );
pevOwner->effects |= EF_LASERSPOT;
}
return pSpot;
}
//=========================================================
//=========================================================
CLaserSpot *CLaserSpot::CreateSpot( const char* spritename )
CLaserSpot *CLaserSpot::CreateSpot( const char* spritename, entvars_t *pevOwner )
{
CLaserSpot *pSpot = CreateSpot();
SET_MODEL(ENT(pSpot->pev), spritename);
CLaserSpot *pSpot = CreateSpot( pevOwner );
SET_MODEL( ENT( pSpot->pev ), spritename );
return pSpot;
}
@ -130,9 +137,12 @@ void CLaserSpot::Spawn( void )
void CLaserSpot::Suspend( float flSuspendTime )
{
pev->effects |= EF_NODRAW;
if( !FNullEnt( pev->owner ))
pev->owner->v.effects &= ~EF_LASERSPOT;
//LRC: -1 means suspend indefinitely
if (flSuspendTime == -1)
// LRC: -1 means suspend indefinitely
if ( flSuspendTime == -1 )
{
SetThink( NULL );
}
@ -148,10 +158,22 @@ void CLaserSpot::Suspend( float flSuspendTime )
//=========================================================
void CLaserSpot::Revive( void )
{
if( !FNullEnt( pev->owner ))
pev->owner->v.effects |= EF_LASERSPOT;
pev->effects &= ~EF_NODRAW;
SetThink( NULL );
}
void CLaserSpot::UpdateOnRemove( void )
{
// tell the owner about laserspot
if( !FNullEnt( pev->owner ))
pev->owner->v.effects &= ~EF_LASERSPOT;
CBaseEntity :: UpdateOnRemove ();
}
void CLaserSpot::Precache( void )
{
PRECACHE_MODEL("sprites/laserdot.spr");
@ -487,6 +509,7 @@ void W_Precache(void)
// used by explosions
PRECACHE_MODEL ("models/grenade.mdl");
PRECACHE_MODEL ("sprites/explode1.spr");
PRECACHE_MODEL ("sprites/animglow01.spr");
PRECACHE_SOUND ("weapons/debris1.wav");// explosion aftermaths
PRECACHE_SOUND ("weapons/debris2.wav");// explosion aftermaths

View File

@ -32,9 +32,10 @@ class CLaserSpot : public CBaseEntity
public:
void Suspend( float flSuspendTime );
void EXPORT Revive( void );
void UpdateOnRemove( void );
static CLaserSpot *CreateSpot( void );
static CLaserSpot *CreateSpot( const char* spritename );
static CLaserSpot *CreateSpot( entvars_t *pevOwner = NULL );
static CLaserSpot *CreateSpot( const char* spritename, entvars_t *pevOwner = NULL );
};
// Contact Grenade / Timed grenade / Satchel Charge

View File

@ -32,11 +32,11 @@ Beta 13.02.10
7. fix loaders for ATI1N and ATI2N OK
8. fix sky changelevel bug
9. rewrote UI_Field code OK
10.autocomplete and command history for system console OK
11.create mutex for dedicated server OK
12.revision of Xash Environment System OK
13.implement temp-ents OK
14.implement realtime wind
10. autocomplete and command history for system console OK
11. create mutex for dedicated server OK
12. revision of Xash Environment System OK
13. implement temp-ents OK
14. implement realtime wind
15. fixup muzzleflashes OK
16. fix CL_GetEntityByIndex: invalid entindex OK
17. implement beams OK
@ -45,11 +45,12 @@ Beta 13.02.10
20. rails2d.shader OK
20. merge abaddon.shader
21. implement all TE_* messages
22. final revision of ClientAPI
23. fix Egon and Gauss firing
22. final revision of ClientAPI OK
23. fix Egon and Gauss firing OK
24. revision server physic
25. revision monster moving
26. get rid of fakemirror stuff in spirit
26. get rid of fakemirror stuff in spirit OK
27. rewrite engine particle system

View File

@ -249,7 +249,7 @@ typedef struct ref_entity_s
vec3_t lightingOrigin;
// RT_SPRITE stuff
struct ref_shader_s *spriteshader; // client drawing stuff
struct ref_shader_s *customShader; // client drawing stuff
float radius; // used as RT_SPRITE's radius
// outilne stuff

View File

@ -529,7 +529,7 @@ bool R_PushSprite( const meshbuffer_t *mb, int type, float right, float left, fl
}
break;
case SPR_FWD_PARALLEL: // normal sprite
default: if( e->spriteshader )
default: if( e->customShader )
angle = e->angles[PITCH];
else angle = e->angles[ROLL]; // for support rotating muzzleflashes
RotatePointAroundVector( v_right, RI.vpn, RI.vright, angle );
@ -719,7 +719,8 @@ static void R_AddSpriteModelToList( ref_entity_t *e )
if( R_SpriteOccluded( e )) return;
frame = R_GetSpriteFrame( e->model, e->prev->curframe, e->angles[YAW] );
shader = &r_shaders[frame->shader];
if( e->customShader ) shader = e->customShader;
else shader = &r_shaders[frame->shader];
if( RI.refdef.flags & (RDF_PORTALINVIEW|RDF_SKYPORTALINVIEW) || ( RI.params & RP_SKYPORTALVIEW ))
{
@ -750,7 +751,7 @@ static void R_AddSpritePolyToList( ref_entity_t *e )
return;
}
mb = R_AddMeshToList( MB_SPRITE, R_FogForSphere( e->origin, e->radius ), e->spriteshader, -1 );
mb = R_AddMeshToList( MB_SPRITE, R_FogForSphere( e->origin, e->radius ), e->customShader, -1 );
if( mb ) mb->shaderkey |= ( bound( 1, 0x4000 - (unsigned int)dist, 0x4000 - 1 ) << 12 );
}
@ -1382,7 +1383,7 @@ static void R_CullEntities( void )
}
break;
case RT_SPRITE:
culled = ( e->radius <= 0 ) || ( e->spriteshader == NULL );
culled = ( e->radius <= 0 ) || ( e->customShader == NULL );
break;
case RT_NONE:
default: break;
@ -1997,8 +1998,15 @@ int R_ComputeFxBlend( ref_entity_t *e )
offset = ((int)e->index ) * 363.0f; // Use ent index to de-sync these fx
if( m_pEntity ) renderAmt = m_pEntity->v.renderamt;
else renderAmt = e->renderamt;
if( e->ent_type == ED_TEMPENTITY )
{
renderAmt = e->renderamt;
}
else if( m_pEntity )
{
renderAmt = m_pEntity->v.renderamt;
}
else renderAmt = 255;
switch( e->renderfx )
{
@ -2463,9 +2471,10 @@ bool R_AddPortalEntity( edict_t *pRefEntity, ref_entity_t *refent )
return true;
}
bool R_AddEntityToScene( edict_t *pRefEntity, int ed_type )
bool R_AddEntityToScene( edict_t *pRefEntity, int ed_type, shader_t customShader )
{
ref_entity_t *refent;
ref_shader_t *shader;
bool result = false;
if( !pRefEntity || pRefEntity->v.modelindex <= 0 || pRefEntity->v.modelindex >= MAX_MODELS )
@ -2517,6 +2526,13 @@ bool R_AddEntityToScene( edict_t *pRefEntity, int ed_type )
refent->parent = NULL;
refent->prev = NULL;
// setup custom shader
if( customShader >= 0 && customShader < MAX_SHADERS && (shader = &r_shaders[customShader]))
refent->customShader = shader;
else refent->customShader = NULL;
refent->rtype = RT_MODEL;
// setup rtype
switch( ed_type )
{
@ -2550,15 +2566,16 @@ bool R_AddEntityToScene( edict_t *pRefEntity, int ed_type )
FollowEntity.v.movetype = MOVETYPE_FOLLOW;
FollowEntity.v.weaponmodel = 0;
if( R_AddEntityToScene( &FollowEntity, ED_NORMAL ))
if( R_AddEntityToScene( &FollowEntity, ED_NORMAL, customShader ))
r_entities[r_numEntities-1].parent = refent; // set parent
}
return result;
}
bool R_AddTeEntToScene( TEMPENTITY *pTempEntity, int ed_type )
bool R_AddTeEntToScene( TEMPENTITY *pTempEntity, int ed_type, shader_t customShader )
{
ref_entity_t *refent;
ref_shader_t *shader;
vec3_t center;
if( !pTempEntity || pTempEntity->modelindex <= 0 || pTempEntity->modelindex >= MAX_MODELS )
@ -2639,6 +2656,11 @@ bool R_AddTeEntToScene( TEMPENTITY *pTempEntity, int ed_type )
return false;
}
// setup custom shader
if( customShader >= 0 && customShader < MAX_SHADERS && (shader = &r_shaders[customShader]))
refent->customShader = shader;
else refent->customShader = NULL;
refent->rtype = RT_MODEL;
refent->prev->frame = refent->prev->curframe; // save oldframe

View File

@ -1019,6 +1019,7 @@ static bool R_DrawPortalSurface( void )
if( ent->rtype == RT_PORTALSURFACE )
{
if( ent->flags & EF_NODRAW ) continue; // disabled
d = PlaneDiff( ent->origin, original_plane );
if( ( d >= -64 ) && ( d <= 64 ) )
{

View File

@ -597,14 +597,17 @@ bool R_DrawSpriteModel( const meshbuffer_t *mb )
if( ilerp != 0 )
{
e->renderamt = renderamt * ilerp; // merge prevframe alpha
rb->shaderkey = r_shaders[oldframe->shader].sortkey;
if( e->customShader ) rb->shaderkey = e->customShader->sortkey;
else rb->shaderkey = r_shaders[oldframe->shader].sortkey;
if( R_PushSprite( rb, psprite->type, oldframe->left, oldframe->right, oldframe->down, oldframe->up ))
R_RenderMeshBuffer( rb );
}
if( lerp != 0 )
{
e->renderamt = renderamt * lerp; // merge frame alpha
rb->shaderkey = r_shaders[frame->shader].sortkey;
if( e->customShader ) rb->shaderkey = e->customShader->sortkey;
else rb->shaderkey = r_shaders[frame->shader].sortkey;
if( R_PushSprite( rb, psprite->type, frame->left, frame->right, frame->down, frame->up ))
R_RenderMeshBuffer( rb );
}

View File

@ -1548,7 +1548,7 @@ static void R_StudioCalcAttachments( ref_entity_t *e )
matrix4x4 out;
dstudioattachment_t *pAtt;
vec3_t axis[3];
vec3_t localOrg, localAng;
vec3_t localOrg, localAng, bonepos;
if( m_pStudioHeader->numattachments <= 0 )
{
@ -1572,10 +1572,12 @@ static void R_StudioCalcAttachments( ref_entity_t *e )
// compute pos and angles
Matrix4x4_VectorTransform( out, pAtt[i].org, localOrg );
Matrix4x4_VectorTransform( out, pAtt[i].vectors[0], axis[0] );
Matrix4x4_VectorTransform( out, pAtt[i].vectors[1], axis[1] );
Matrix4x4_VectorTransform( out, pAtt[i].vectors[2], axis[2] );
Matrix3x3_ToAngles( axis, localAng, true ); // FIXME: dll's uses FLU ?
Matrix4x4_OriginFromMatrix( out, bonepos );
VectorSubtract( localOrg, bonepos, axis[0] ); // make forward
VectorNormalizeFast( axis[0] );
VectorVectors( axis[0], axis[1], axis[2] ); // make right and up
Matrix3x3_ToAngles( axis, localAng, false ); // FIXME: dll's uses FLU ?
ri.SetAttachment( e->index, i, localOrg, localAng );
}
}
@ -1740,9 +1742,10 @@ void R_StudioDrawMesh( const meshbuffer_t *mb, short *ptricmds, float s, float t
r_backacc.numVerts++;
}
}
if( features & MF_SVECTORS )
R_BuildTangentVectors( r_backacc.numVerts, inVertsArray, inNormalsArray, inCoordsArray, r_backacc.numElems / 3, inElemsArray, inSVectorsArray );
R_StudioSetUpTransform( RI.currententity, true );
r_features = features;
R_RenderMeshBuffer( mb );
@ -2457,7 +2460,8 @@ bool R_CullStudioModel( ref_entity_t *e )
dstudiomesh_t *pmesh;
pmesh = (dstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex) + j;
shader = &r_shaders[ptexture[pskinref[pmesh->skinref]].shader];
if( e->customShader ) shader = e->customShader;
else shader = &r_shaders[ptexture[pskinref[pmesh->skinref]].shader];
if( shader && ( shader->sort <= SORT_ALPHATEST ))
{
@ -2549,7 +2553,10 @@ void R_AddStudioModelToList( ref_entity_t *e )
dstudiomesh_t *pmesh;
pmesh = (dstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex) + j;
shader = &r_shaders[ptexture[pskinref[pmesh->skinref]].shader];
if( e->customShader ) shader = e->customShader;
else shader = &r_shaders[ptexture[pskinref[pmesh->skinref]].shader];
if( shader ) R_AddModelMeshToList( modhandle, fog, shader, ((j<<8)|i));
}
}