13 Apr 2010

This commit is contained in:
g-cont 2010-04-13 00:00:00 +04:00 committed by Alibek Omarov
parent 406f0d5f9a
commit d8e6ac9a99
55 changed files with 633 additions and 230 deletions

View File

@ -244,7 +244,7 @@ public:
};
#endif
void UpdateOnRemove( void );
virtual void UpdateOnRemove( void );
// common member functions
void EXPORT SUB_Remove( void );
@ -253,8 +253,8 @@ public:
void EXPORT SUB_FadeOut ( void );
void EXPORT SUB_CallUseToggle( void ) { this->Use( this, this, USE_TOGGLE, 0 ); }
int ShouldToggle( USE_TYPE useType, BOOL currentState );
void FireBullets( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq = 4, int iDamage = 0, entvars_t *pevAttacker = NULL );
void FireBullets( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq = 4, int iDamage = 0, entvars_t *pevAttacker = NULL );
Vector FireBulletsPlayer( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq = 4, int iDamage = 0, entvars_t *pevAttacker = NULL, int shared_rand = 0 );
virtual CBaseEntity *Respawn( void ) { return NULL; }
void SUB_UseTargets( CBaseEntity *pActivator, USE_TYPE useType, float value );

View File

@ -979,11 +979,6 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
}
if( to->ed_type == ED_CLIENT )
{
if( pNet->pev->fixangle )
{
to->ed_flags |= ESF_NO_PREDICTION;
}
if( pNet->pev->teleport_time )
{
to->ed_flags |= ESF_NO_PREDICTION;

View File

@ -1513,6 +1513,96 @@ void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting
ApplyMultiDamage(pev, pevAttacker);
}
/*
================
FireBullets
Go to the trouble of combining multiple pellets into a single damage call.
This version is used by Players, uses the random seed generator to sync client and server side shots.
================
*/
Vector CBaseEntity::FireBulletsPlayer( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int shared_rand )
{
static int tracerCount;
TraceResult tr;
Vector vecRight = gpGlobals->v_right;
Vector vecUp = gpGlobals->v_up;
float x, y, z;
if ( pevAttacker == NULL )
pevAttacker = pev; // the default attacker is ourselves
ClearMultiDamage();
gMultiDamage.type = DMG_BULLET | DMG_NEVERGIB;
for ( ULONG iShot = 1; iShot <= cShots; iShot++ )
{
//Use player's random seed.
// get circular gaussian spread
x = UTIL_SharedRandomFloat( shared_rand + iShot, -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 1 + iShot ) , -0.5, 0.5 );
y = UTIL_SharedRandomFloat( shared_rand + ( 2 + iShot ), -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 3 + iShot ), -0.5, 0.5 );
z = x * x + y * y;
Vector vecDir = vecDirShooting +
x * vecSpread.x * vecRight +
y * vecSpread.y * vecUp;
Vector vecEnd;
vecEnd = vecSrc + vecDir * flDistance;
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev)/*pentIgnore*/, &tr);
// do damage, paint decals
if (tr.flFraction != 1.0)
{
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
if ( iDamage )
{
pEntity->TraceAttack(pevAttacker, iDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) );
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
DecalGunshot( &tr, iBulletType );
}
else switch(iBulletType)
{
default:
case BULLET_PLAYER_9MM:
pEntity->TraceAttack(pevAttacker, gSkillData.plrDmg9MM, vecDir, &tr, DMG_BULLET);
break;
case BULLET_PLAYER_MP5:
pEntity->TraceAttack(pevAttacker, gSkillData.plrDmgMP5, vecDir, &tr, DMG_BULLET);
break;
case BULLET_PLAYER_BUCKSHOT:
// make distance based!
pEntity->TraceAttack(pevAttacker, gSkillData.plrDmgBuckshot, vecDir, &tr, DMG_BULLET);
break;
case BULLET_PLAYER_357:
pEntity->TraceAttack(pevAttacker, gSkillData.plrDmg357, vecDir, &tr, DMG_BULLET);
break;
case BULLET_NONE: // FIX
pEntity->TraceAttack(pevAttacker, 50, vecDir, &tr, DMG_CLUB);
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
// only decal glass
if ( !FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != 0)
{
UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0,2) );
}
break;
}
}
// make bullet trails
UTIL_BubbleTrail( vecSrc, tr.vecEndPos, (flDistance * tr.flFraction) / 64.0 );
}
ApplyMultiDamage(pev, pevAttacker);
return Vector( x * vecSpread.x, y * vecSpread.y, 0.0 );
}
void CBaseEntity :: TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType )
{

View File

@ -1946,6 +1946,7 @@ void CFade::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType
if ( !(pev->spawnflags & SF_FADE_IN) )
fadeFlags |= FFADE_OUT;
else fadeFlags |= FFADE_IN;
if ( pev->spawnflags & SF_FADE_MODULATE )
fadeFlags |= FFADE_MODULATE;

View File

@ -136,8 +136,8 @@ void CGauss::Precache( void )
m_iBalls = PRECACHE_MODEL( "sprites/hotglow.spr" );
m_iBeam = PRECACHE_MODEL( "sprites/smoke.spr" );
m_usGaussFire = PRECACHE_EVENT( 1, "events/gauss.sc" );
m_usGaussSpin = PRECACHE_EVENT( 1, "events/gaussspin.sc" );
m_usGaussFire = PRECACHE_EVENT( 1, "evGauss" );
m_usGaussSpin = PRECACHE_EVENT( 1, "evGaussSpin" );
}
int CGauss::AddToPlayer( CBasePlayer *pPlayer )
@ -415,7 +415,7 @@ void CGauss::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage )
// This reliable event is used to stop the spinning sound
// It's delayed by a fraction of second to make sure it is delayed by 1 frame on the client
// It's sent reliably anyway, which could lead to other delays
PLAYBACK_EVENT_FULL( FEV_RELIABLE, m_pPlayer->edict(), m_usGaussFire, 0.01, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 1 );
PLAYBACK_EVENT_FULL( FEV_RELIABLE, m_pPlayer->edict(), m_usGaussFire, 0.01, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, 0.0, 0.0, pev->body, 0, 0, 1 );
/*
ALERT( at_console, "%f %f %f\n%f %f %f\n",

View File

@ -106,7 +106,7 @@ void CMP5::Precache( void )
PRECACHE_SOUND ("weapons/357_cock1.wav");
m_usMP5 = PRECACHE_EVENT( 1, "events/mp5.sc" );
m_usMP5 = PRECACHE_EVENT( 1, "evMP5" );
}
int CMP5::GetItemInfo(ItemInfo *p)
@ -161,8 +161,6 @@ void CMP5::PrimaryAttack()
return;
}
PLAYBACK_EVENT( 0, m_pPlayer->edict(), m_usMP5 );
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
@ -173,18 +171,21 @@ void CMP5::PrimaryAttack()
Vector vecSrc = m_pPlayer->GetGunPosition( );
Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
Vector vecDir;
if ( g_pGameRules->IsDeathmatch() )
{
// optimized multiplayer. Widened to make it easier to hit a moving player
m_pPlayer->FireBullets( 1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, 8192, BULLET_PLAYER_MP5, 2 );
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_MP5, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
}
else
{
// single player spread
m_pPlayer->FireBullets( 1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_MP5, 2 );
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, 8192, BULLET_PLAYER_MP5, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
}
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usMP5, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, MP5_FIRE1, 0, 0 );
if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
// HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);

View File

@ -1545,7 +1545,7 @@ void CFuncTrackTrain :: Precache( void )
PRECACHE_SOUND("plats/ttrain_brake1.wav");
PRECACHE_SOUND("plats/ttrain_start1.wav");
m_usAdjustPitch = PRECACHE_EVENT( 1, "events/train.sc" );
m_usAdjustPitch = PRECACHE_EVENT( 1, "evTrain" );
}
// This class defines the volume of space that the player must stand in to control the train

View File

@ -184,7 +184,6 @@ int gmsgHideWeapon = 0;
int gmsgSetCurWeap = 0;
int gmsgSayText = 0;
int gmsgTextMsg = 0;
int gmsgSetFOV = 0;
int gmsgShowMenu = 0;
int gmsgGeigerRange = 0;
int gmsgTempEntity = 0;
@ -215,7 +214,7 @@ void LinkUserMessages( void )
gmsgWeaponList = REG_USER_MSG("WeaponList", -1);
gmsgResetHUD = REG_USER_MSG("ResetHUD", 1); // called every respawn
gmsgInitHUD = REG_USER_MSG("InitHUD", 0 ); // called every time a new player joins the server
gmsgShowGameTitle = REG_USER_MSG("GameTitle", 1);
gmsgShowGameTitle = REG_USER_MSG("GameTitle", 0);
gmsgDeathMsg = REG_USER_MSG( "DeathMsg", -1 );
gmsgScoreInfo = REG_USER_MSG( "ScoreInfo", 5 );
gmsgTeamInfo = REG_USER_MSG( "TeamInfo", -1 ); // sets the name of a player's team
@ -226,7 +225,6 @@ void LinkUserMessages( void )
gmsgWeapPickup = REG_USER_MSG( "WeapPickup", 1 );
gmsgItemPickup = REG_USER_MSG( "ItemPickup", -1 );
gmsgHideWeapon = REG_USER_MSG( "HideWeapon", 1 );
gmsgSetFOV = REG_USER_MSG( "SetFOV", 1 );
gmsgShowMenu = REG_USER_MSG( "ShowMenu", -1 );
gmsgShake = REG_USER_MSG("ScreenShake", sizeof(ScreenShake));
gmsgFade = REG_USER_MSG("ScreenFade", sizeof(ScreenFade));
@ -899,11 +897,6 @@ void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib )
// reset FOV
pev->fov = 90.0f;
MESSAGE_BEGIN( MSG_ONE, gmsgSetFOV, NULL, pev );
WRITE_BYTE(0);
MESSAGE_END();
// UNDONE: Put this in, but add FFADE_PERMANENT and make fade time 8.8 instead of 4.12
// UTIL_ScreenFade( edict(), Vector(128,0,0), 6, 15, 255, FFADE_OUT | FFADE_MODULATE );
@ -4058,7 +4051,6 @@ void CBasePlayer :: UpdateClientData( void )
if (gDisplayTitle)
{
MESSAGE_BEGIN( MSG_ONE, gmsgShowGameTitle, NULL, pev );
WRITE_BYTE( 0 );
MESSAGE_END();
gDisplayTitle = 0;
}

View File

@ -113,7 +113,7 @@ void CPython::Precache( void )
PRECACHE_SOUND ("weapons/357_shot1.wav");
PRECACHE_SOUND ("weapons/357_shot2.wav");
m_usFirePython = PRECACHE_EVENT( 1, "events/python.sc" );
m_usFirePython = PRECACHE_EVENT( 1, "evPython" );
}
BOOL CPython::Deploy( )
@ -205,7 +205,11 @@ void CPython::PrimaryAttack()
Vector vecSrc = m_pPlayer->GetGunPosition( );
Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
m_pPlayer->FireBullets( 1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, 8192, BULLET_PLAYER_357, 0 );
Vector vecDir;
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, 8192, BULLET_PLAYER_357, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usFirePython, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, PYTHON_FIRE1, 0, 0 );
if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
// HEV suit - indicate out of ammo condition

View File

@ -48,8 +48,8 @@ class CLaserSpot : public CBaseEntity
public:
void Suspend( float flSuspendTime );
void EXPORT Revive( void );
static CLaserSpot *CreateSpot( void );
void UpdateOnRemove( void );
static CLaserSpot *CreateSpot( entvars_t *pevOwner = NULL );
};
LINK_ENTITY_TO_CLASS( laser_spot, CLaserSpot );
@ -95,13 +95,21 @@ IMPLEMENT_SAVERESTORE( CRpg, CBasePlayerWeapon );
//=========================================================
//=========================================================
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;
}
@ -114,6 +122,7 @@ void CLaserSpot::Spawn( void )
pev->solid = SOLID_NOT;
pev->rendermode = kRenderGlow;
pev->rendercolor = Vector( 200, 12, 12 );
pev->renderfx = kRenderFxNoDissipation;
pev->renderamt = 255;
@ -142,6 +151,15 @@ void CLaserSpot::Revive( void )
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");
@ -183,6 +201,7 @@ CRpgRocket *CRpgRocket::CreateRpgRocket( Vector vecOrigin, Vector vecAngles, CBa
{
CRpgRocket *pRocket = GetClassPtr( (CRpgRocket *)NULL );
pRocket->SetObjectClass( ED_NORMAL );
UTIL_SetOrigin( pRocket->pev, vecOrigin );
pRocket->pev->angles = vecAngles;
pRocket->Spawn();
@ -564,6 +583,7 @@ void CRpg::PrimaryAttack()
else
{
PlayEmptySound( );
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.7;//no longer indicate fps :)
}
UpdateSpot( );
}
@ -631,7 +651,7 @@ void CRpg::UpdateSpot( void )
{
if (!m_pSpot)
{
m_pSpot = CLaserSpot::CreateSpot();
m_pSpot = CLaserSpot::CreateSpot( m_pPlayer->pev );
}
UTIL_MakeVectors( m_pPlayer->pev->viewangles );

View File

@ -114,8 +114,8 @@ void CShotgun::Precache( void )
PRECACHE_SOUND ("weapons/357_cock1.wav"); // gun empty sound
PRECACHE_SOUND ("weapons/scock1.wav"); // cock gun
m_usSingleFire = PRECACHE_EVENT( 1, "events/shotgun1.sc" );
m_usDoubleFire = PRECACHE_EVENT( 1, "events/shotgun2.sc" );
m_usSingleFire = PRECACHE_EVENT( 1, "evShotgun1" );
m_usDoubleFire = PRECACHE_EVENT( 1, "evShotgun2" );
}
int CShotgun::AddToPlayer( CBasePlayer *pPlayer )
@ -174,8 +174,6 @@ void CShotgun::PrimaryAttack()
return;
}
PLAYBACK_EVENT( 0, m_pPlayer->edict(), m_usSingleFire );
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
@ -187,17 +185,21 @@ void CShotgun::PrimaryAttack()
Vector vecSrc = m_pPlayer->GetGunPosition( );
Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
Vector vecDir;
if ( g_pGameRules->IsDeathmatch() )
{
// altered deathmatch spread
m_pPlayer->FireBullets( 4, vecSrc, vecAiming, VECTOR_CONE_DM_SHOTGUN, 2048, BULLET_PLAYER_BUCKSHOT, 0 );
vecDir = m_pPlayer->FireBulletsPlayer( 4, vecSrc, vecAiming, VECTOR_CONE_DM_SHOTGUN, 2048, BULLET_PLAYER_BUCKSHOT, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
}
else
{
// regular old, untouched spread.
m_pPlayer->FireBullets( 6, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_BUCKSHOT, 0 );
vecDir = m_pPlayer->FireBulletsPlayer( 6, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_BUCKSHOT, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
}
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usSingleFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, SHOTGUN_FIRE, 0, 0 );
if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
// HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
@ -232,8 +234,6 @@ void CShotgun::SecondaryAttack( void )
return;
}
PLAYBACK_EVENT( 0, m_pPlayer->edict(), m_usDoubleFire );
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
@ -244,18 +244,22 @@ void CShotgun::SecondaryAttack( void )
Vector vecSrc = m_pPlayer->GetGunPosition( );
Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
Vector vecDir;
if ( g_pGameRules->IsDeathmatch() )
{
// tuned for deathmatch
m_pPlayer->FireBullets( 8, vecSrc, vecAiming, VECTOR_CONE_DM_DOUBLESHOTGUN, 2048, BULLET_PLAYER_BUCKSHOT, 0 );
vecDir = m_pPlayer->FireBulletsPlayer( 8, vecSrc, vecAiming, VECTOR_CONE_DM_DOUBLESHOTGUN, 2048, BULLET_PLAYER_BUCKSHOT, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
}
else
{
// untouched default single player
m_pPlayer->FireBullets( 12, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_BUCKSHOT, 0 );
vecDir = m_pPlayer->FireBulletsPlayer( 12, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_BUCKSHOT, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
}
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usDoubleFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, SHOTGUN_FIRE2, 0, 0 );
if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
// HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);

View File

@ -402,6 +402,14 @@ void W_Precache(void)
g_sModelIndexLaser = PRECACHE_MODEL( (char *)g_pModelNameLaser );
g_sModelIndexLaserDot = PRECACHE_MODEL("sprites/laserdot.spr");
// custom muzzleflashes
PRECACHE_MODEL ("sprites/muzzleflash1.spr");
PRECACHE_MODEL ("sprites/muzzleflash2.spr");
PRECACHE_MODEL ("sprites/muzzleflash3.spr");
PRECACHE_MODEL ("sprites/muzzleflash.spr");
// ricochet
PRECACHE_MODEL ("sprites/richo1.spr");
// used by explosions
PRECACHE_MODEL ("models/grenade.mdl");

View File

@ -153,7 +153,7 @@ void CDecal :: TriggerDecal ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE
WRITE_SHORT( (int)pev->skin );
entityIndex = (short)ENTINDEX(trace.pHit);
WRITE_SHORT( entityIndex );
if ( entityIndex )
if ( entityIndex != NULLENT_INDEX )
WRITE_SHORT( (int)VARS(trace.pHit)->modelindex );
MESSAGE_END();
@ -661,11 +661,15 @@ void CWorld :: Precache( void )
else
CVAR_SET_FLOAT( "v_dark", 0.0 );
pev->spawnflags &= ~SF_WORLD_DARK; // don't apply fade after save\restore
if ( pev->spawnflags & SF_WORLD_TITLE )
gDisplayTitle = TRUE; // display the game title if this key is set
else
gDisplayTitle = FALSE;
pev->spawnflags &= ~SF_WORLD_TITLE; // don't show logo after save\restore
if ( pev->spawnflags & SF_WORLD_FORCETEAM )
{
CVAR_SET_FLOAT( "mp_defaultteam", 1 );

View File

@ -163,15 +163,6 @@ void HUD_Init( void )
int HUD_Redraw( float flTime, int state )
{
static int oldstate;
if( oldstate == CL_ACTIVE && state == CL_LOADING )
{
// HACKHACK: fire only once to prevent multiply GL_BLEND each frame
DrawImageBar( 100, "m_loading" ); // HACKHACK
}
oldstate = state;
switch( state )
{
case CL_LOADING:
@ -184,6 +175,9 @@ int HUD_Redraw( float flTime, int state )
gHUD.Redraw( flTime );
DrawPause();
break;
case CL_CHANGELEVEL:
DrawImageBar( 100, "m_loading" );
break;
}
return 1;
}
@ -291,9 +285,15 @@ void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const enti
{
edict_t *viewent = GetViewModel();
// if viewmodel has changed update sequence here
if( viewent->v.modelindex != state->viewmodel )
{
// ALERT( at_console, "Viewmodel changed\n" );
SendWeaponAnim( viewent->v.sequence, viewent->v.body, viewent->v.framerate );
}
// setup player viewmodel (only for local player!)
viewent->v.modelindex = state->viewmodel;
gHUD.m_flFOV = ent->v.fov; // keep client fov an actual
gHUD.m_flFOV = ent->v.fov; // keep client fov an actual
}
break;
case ED_PORTAL:

View File

@ -746,7 +746,7 @@ void EV_FireMP5( event_args_t *args )
Vector origin = args->origin;
Vector angles = args->angles;
Vector velocity = args->velocity;
int body;
int body, animbase;
Vector ShellVelocity;
Vector ShellOrigin;
@ -757,6 +757,7 @@ void EV_FireMP5( event_args_t *args )
idx = args->entindex;
body = args->iparam1;
animbase = args->iparam2; // because spirit and bshift dlls has different enums
AngleVectors( angles, forward, right, up );
@ -766,7 +767,7 @@ void EV_FireMP5( event_args_t *args )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
g_engfuncs.pEventAPI->EV_WeaponAnim( MP5_FIRE1 + RANDOM_LONG( 0, 2 ), body, 1.0f );
g_engfuncs.pEventAPI->EV_WeaponAnim( animbase + RANDOM_LONG( 0, 2 ), body, 1.0f );
V_PunchAxis( 0, RANDOM_FLOAT( -2, 2 ) );
}
@ -825,7 +826,7 @@ void EV_FireShotGunDouble( event_args_t *args )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
g_engfuncs.pEventAPI->EV_WeaponAnim( SHOTGUN_FIRE2, args->iparam1, 1.0f );
g_engfuncs.pEventAPI->EV_WeaponAnim( args->iparam2, args->iparam1, 1.0f );
V_PunchAxis( 0, -10.0 );
}
@ -876,7 +877,7 @@ void EV_FireShotGunSingle( event_args_t *args )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
g_engfuncs.pEventAPI->EV_WeaponAnim( SHOTGUN_FIRE, args->iparam1, 1.0f );
g_engfuncs.pEventAPI->EV_WeaponAnim( args->iparam2, args->iparam1, 1.0f );
V_PunchAxis( 0, -5.0 );
}
@ -929,7 +930,7 @@ void EV_FirePython( event_args_t *args )
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
g_engfuncs.pEventAPI->EV_WeaponAnim( PYTHON_FIRE1, args->iparam1, 1.0f );
g_engfuncs.pEventAPI->EV_WeaponAnim( args->iparam2, args->iparam1, 1.0f );
V_PunchAxis( 0, -10.0 );
}

View File

@ -1099,10 +1099,15 @@ void V_CalcScreenBlend( ref_params_t *pparams )
pparams->blend[1] = 0.0f;
pparams->blend[2] = 0.0f;
pparams->blend[3] = 1.0f;
v_dark->integer++; // HACKHACK
if( !pparams->paused && IN_GAME( ))
{
// HACKHACK
v_dark->integer++;
}
// make first 10 frames black then reset
if( v_dark->integer < 10 ) return;
if( v_dark->integer < 100 ) return;
CVAR_SET_FLOAT( "v_dark", 0.0f );
}

View File

@ -668,7 +668,7 @@ public:
int _cdecl MsgFunc_TempEntity( const char *pszName, int iSize, void *pbuf );
// user commansds
void _cdecl UserCmd_LoadingPlaque( void );
void _cdecl UserCmd_ChangeLevel( void );
// Screen information
SCREENINFO m_scrinfo;

View File

@ -44,7 +44,7 @@ DECLARE_HUDMESSAGE( TempEntity );
DECLARE_HUDMESSAGE( ServerName );
DECLARE_HUDMESSAGE( ScreenShake );
DECLARE_HUDMESSAGE( Intermission );
DECLARE_HUDCOMMAND( LoadingPlaque );
DECLARE_HUDCOMMAND( ChangeLevel );
int CHud :: InitMessages( void )
{
@ -72,7 +72,7 @@ int CHud :: InitMessages( void )
HOOK_MESSAGE( ScreenFade );
HOOK_MESSAGE( ScreenShake );
HOOK_COMMAND( "plaque", LoadingPlaque );
HOOK_COMMAND( "hud_changelevel", ChangeLevel ); // send by engine
viewEntityIndex = 0; // trigger_viewset stuff
viewFlags = 0;
@ -103,7 +103,7 @@ int CHud :: InitMessages( void )
return 1;
}
void CHud :: UserCmd_LoadingPlaque( void )
void CHud :: UserCmd_ChangeLevel( void )
{
m_iDrawPlaque = 0; // disable plaque rendering
}

View File

@ -368,6 +368,7 @@ typedef enum
#define CL_LOADING 1 // draw loading progress-bar
#define CL_ACTIVE 2 // draw normal hud
#define CL_PAUSED 3 // pause when active
#define CL_CHANGELEVEL 4 // draw 'loading' during changelevel
// built-in dlight flags
#define DLIGHT_FADE (1<<0) // fade dlight at end of lifetime

View File

@ -522,7 +522,7 @@ void CL_PlayDemo_f( void )
CL_Disconnect();
Host_ShutdownServer();
com.snprintf( filename, MAX_STRING, "demos/%s.dem", Cmd_Argv( 1 ));
com.snprintf( filename, MAX_STRING, "$demos/%s.dem", Cmd_Argv( 1 ));
if(!FS_FileExists( filename ))
{
MsgDev( D_ERROR, "couldn't open %s\n", filename );

View File

@ -518,7 +518,7 @@ void CL_Reconnect_f( void )
// disable plaque draw on change map
cls.drawplaque = false;
Cmd_ExecuteString( "plaque\n" );
Cmd_ExecuteString( "hud_changelevel\n" );
if( cls.demoplayback ) return;
@ -1075,6 +1075,48 @@ void CL_InitLocal( void )
}
//============================================================================
/*
==================
CL_ApplyAddAngle
==================
*/
void CL_ApplyAddAngle( void )
{
float frametime = (cl.serverframetime * 0.001f);
float amove = 0.0f;
int i;
for( i = 0; i < CMD_MASK; i++ )
{
add_angle_t *add = &cl.addangle[i];
float f, remainder = fabs( add->yawdelta - add->accum );
float amount_to_add;
if( remainder <= 0.0001f )
continue; // this angle expired
// apply some of the delta
f = frametime;
f = bound( 0.0f, f, 1.0f );
amount_to_add = f * add->yawdelta;
if( add->yawdelta > 0.0f )
{
amount_to_add = min( amount_to_add, remainder );
}
else
{
amount_to_add = max( amount_to_add, -remainder );
}
add->accum += amount_to_add;
amove += amount_to_add;
}
cl.refdef.cl_viewangles[1] += amove;
}
/*
==================
@ -1120,6 +1162,9 @@ void CL_Frame( int time )
// predict all unacknowledged movements
CL_PredictMovement();
// apply accumulated angles
CL_ApplyAddAngle();
Host_CheckChanges();
// allow sound and video DLL change
@ -1130,7 +1175,7 @@ void CL_Frame( int time )
}
// update the screen
SCR_UpdateScreen();
SCR_UpdateScreen ();
// update audio
S_Update( &cl.refdef );

View File

@ -30,6 +30,7 @@ char *svc_strings[256] =
"svc_frame",
"svc_sound",
"svc_setangle",
"svc_addangle",
"svc_setview",
"svc_print",
"svc_centerprint",
@ -627,8 +628,48 @@ void CL_ParseSetAngle( sizebuf_t *msg )
cl.refdef.cl_viewangles[0] = MSG_ReadAngle32( msg );
cl.refdef.cl_viewangles[1] = MSG_ReadAngle32( msg );
cl.refdef.cl_viewangles[2] = MSG_ReadAngle32( msg );
if( cl.refdef.cl_viewangles[0] > 180 ) cl.refdef.cl_viewangles[0] -= 360;
if( cl.refdef.cl_viewangles[1] > 180 ) cl.refdef.cl_viewangles[1] -= 360;
if( cl.refdef.cl_viewangles[2] > 180 ) cl.refdef.cl_viewangles[2] -= 360;
}
/*
================
CL_ParseAddAngle
add the view angle yaw
================
*/
void CL_ParseAddAngle( sizebuf_t *msg )
{
float ang_total;
float ang_final;
float apply_now;
add_angle_t *a;
ang_total = MSG_ReadAngle32( msg );
ang_final = MSG_ReadAngle32( msg );
if( ang_total > 180.0f )
{
ang_total -= 360.0f;
}
if( ang_final > 180.0f )
{
ang_final -= 360.0f;
}
// apply this angle after prediction
a = &cl.addangle[(cl.frame.serverframe) & CMD_MASK];
a->yawdelta = ang_final;
a->accum = 0.0f;
apply_now = ang_total - ang_final;
cl.refdef.cl_viewangles[1] += apply_now;
}
/*
================
CL_ParseCrosshairAngle
@ -741,7 +782,7 @@ void CL_ParseServerMessage( sizebuf_t *msg )
break;
case svc_changing:
cls.drawplaque = false;
Cmd_ExecuteString( "plaque\n" );
Cmd_ExecuteString( "hud_changelevel\n" );
case svc_reconnect:
if( cls.drawplaque )
Msg( "Server disconnected, reconnecting\n" );
@ -776,6 +817,9 @@ void CL_ParseServerMessage( sizebuf_t *msg )
case svc_setangle:
CL_ParseSetAngle( msg );
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_setview:
cl.refdef.viewentity = MSG_ReadWord( msg );
break;

View File

@ -149,7 +149,8 @@ V_PreRender
*/
bool V_PreRender( void )
{
bool clearScene = true;
bool clearScene = true;
static bool oldState;
// too early
if( !re ) return false;
@ -163,6 +164,15 @@ bool V_PreRender( void )
clearScene = false;
re->BeginFrame( clearScene );
if( oldState && !cls.drawplaque )
{
// fire once
CL_DrawHUD( CL_CHANGELEVEL );
re->EndFrame();
}
oldState = cls.drawplaque;
return cls.drawplaque;
}

View File

@ -20,6 +20,13 @@
#define STRING( offset ) CL_GetString( offset )
#define MAKE_STRING(str) CL_AllocString( str )
// add angles
typedef struct
{
float yawdelta;
float accum;
} add_angle_t;
// console stuff
typedef struct
{
@ -91,6 +98,9 @@ typedef struct
// predicting stuff
vec3_t predicted_origins[CMD_BACKUP];// for debug comparing against server
add_angle_t addangle[CMD_BACKUP]; // accumulate angles from server
float old_addangle;
float cur_addangle;
float predicted_step; // for stair up smoothing
uint predicted_step_time;
@ -315,7 +325,7 @@ typedef struct
bool demorecording;
bool demoplayback;
bool demowaiting; // don't record until a non-delta message is received
bool drawplaque; // draw plaque when level is loading
int drawplaque; // draw plaque when level is loading
string demoname; // for demo looping
file_t *demofile;

View File

@ -162,8 +162,8 @@ bool Cmd_GetFontList( const char *s, char *completedname, int length )
string matchbuf;
int i, numfonts;
t = FS_Search(va("gfx/fonts/%s*.*", s ), true);
if(!t) return false;
t = FS_Search( va( "gfx/fonts/%s*.*", s ), true);
if( !t ) return false;
FS_FileBase( t->filenames[0], matchbuf );
if( completedname && length ) com.strncpy( completedname, matchbuf, length );
@ -207,7 +207,7 @@ bool Cmd_GetDemoList( const char *s, char *completedname, int length )
string matchbuf;
int i, numdems;
t = FS_Search( va( "demos/%s*.dem", s ), true);
t = FS_Search( va( "$demos/%s*.dem", s ), true );
if( !t ) return false;
FS_FileBase( t->filenames[0], matchbuf );
@ -251,8 +251,8 @@ bool Cmd_GetMovieList( const char *s, char *completedname, int length )
string matchbuf;
int i, nummovies;
t = FS_Search(va("media/%s*.roq", s ), true);
if(!t) return false;
t = FS_Search( va( "media/%s*.roq", s ), true );
if( !t ) return false;
FS_FileBase(t->filenames[0], matchbuf );
if(completedname && length) com.strncpy( completedname, matchbuf, length );
@ -296,8 +296,8 @@ bool Cmd_GetMusicList( const char *s, char *completedname, int length )
string matchbuf;
int i, numtracks;
t = FS_Search(va("media/%s*.ogg", s ), true);
if(!t) return false;
t = FS_Search( va( "media/%s*.ogg", s ), true );
if( !t ) return false;
FS_FileBase(t->filenames[0], matchbuf );
if(completedname && length) com.strncpy( completedname, matchbuf, length );
@ -341,7 +341,7 @@ bool Cmd_GetSavesList( const char *s, char *completedname, int length )
string matchbuf;
int i, numsaves;
t = FS_Search( va( "save/%s*.sav", s ), true );
t = FS_Search( va( "$save/%s*.sav", s ), true );
if( !t ) return false;
FS_FileBase( t->filenames[0], matchbuf );
@ -472,7 +472,7 @@ bool Cmd_GetItemsList( const char *s, char *completedname, int length )
string matchbuf;
int i, numitems;
t = FS_Search( va("scripts/items/%s*.txt", s ), true );
t = FS_Search( va( "scripts/items/%s*.txt", s ), true );
if( !t ) return false;
FS_FileBase( t->filenames[0], matchbuf );

View File

@ -66,6 +66,7 @@ enum svc_ops_e
svc_frame, // server frame
svc_sound, // <see code>
svc_setangle, // [short short short] set the view angle to this absolute value
svc_addangle, // [short short] add angles when client turn on mover
svc_setview, // [short] entity number
svc_print, // [byte] id [string] null terminated string
svc_centerprint, // [string] to put in center of the screen

View File

@ -21,6 +21,7 @@ extern int SV_UPDATE_BACKUP;
// hostflags
#define SVF_SKIPLOCALHOST BIT( 0 )
#define SVF_PLAYERSONLY BIT( 1 )
// mapvalid flags
#define MAP_IS_EXIST BIT( 0 )
@ -119,6 +120,9 @@ typedef struct sv_client_s
int surpressCount; // number of messages rate supressed
float anglechangetotal; // add angles to client position
float anglechangefinal; // add angles to client position
edict_t *edict; // EDICT_NUM(clientnum+1)
edict_t *pViewEntity; // svc_setview member
char name[32]; // extracted from userinfo, color string allowed
@ -283,7 +287,6 @@ extern cvar_t *sv_reconnect_limit;
extern cvar_t *rcon_password;
extern cvar_t *hostname;
extern cvar_t *sv_stepheight;
extern cvar_t *sv_playersonly;
extern cvar_t *sv_rollangle;
extern cvar_t *sv_rollspeed;
extern cvar_t *sv_maxspeed;
@ -306,14 +309,15 @@ int SV_DecalIndex( const char *name );
int SV_EventIndex( const char *name );
int SV_GenericIndex( const char *name );
int SV_UserMessageIndex( const char *name );
int SV_CalcPacketLoss( sv_client_t *cl );
void SV_ExecuteUserCommand (char *s);
void SV_InitOperatorCommands( void );
void SV_KillOperatorCommands( void );
void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo );
void Master_Heartbeat (void);
void Master_Packet (void);
void SV_PrepWorldFrame( void );
void SV_CalcFrametime( void );
void Master_Heartbeat( void );
void Master_Packet( void );
//
// sv_init.c

View File

@ -675,16 +675,17 @@ void SV_PutClientInServer( edict_t *ent )
}
else
{
// needs to setup angles on restore
if( ent->v.fixangle )
// NOTE: we needs to setup angles on restore here
if( ent->v.fixangle == 1 )
{
MSG_WriteByte( &sv.multicast, svc_setangle );
MSG_WriteAngle32( &sv.multicast, ent->v.angles[0] );
MSG_WriteAngle32( &sv.multicast, ent->v.angles[1] );
MSG_WriteAngle32( &sv.multicast, 0 );
MSG_DirectSend( MSG_ONE, vec3_origin, client->edict );
ent->v.fixangle = false;
ent->v.fixangle = 0;
}
ent->pvServerData->s.ed_flags |= (ESF_NODELTA|ESF_NO_PREDICTION);
}
client->pViewEntity = NULL; // reset pViewEntity

View File

@ -609,7 +609,7 @@ void SV_ConSay_f( void )
SV_Heartbeat_f
==================
*/
void SV_Heartbeat_f (void)
void SV_Heartbeat_f( void )
{
svs.last_heartbeat = MAX_HEARTBEAT;
}
@ -664,6 +664,18 @@ void SV_KillServer_f( void )
NET_Config ( false ); // close network sockets
}
/*
===============
SV_PlayersOnly_f
disable plhysics but players
===============
*/
void SV_PlayersOnly_f( void )
{
sv.hostflags = sv.hostflags ^ SVF_PLAYERSONLY;
}
/*
==================
SV_InitOperatorCommands
@ -700,6 +712,7 @@ void SV_InitOperatorCommands( void )
Cmd_AddCommand( "killsave", SV_DeleteSave_f, "delete a saved game file and saveshot" );
Cmd_AddCommand( "autosave", SV_AutoSave_f, "save the game to 'autosave' file" );
Cmd_AddCommand( "killserver", SV_KillServer_f, "shutdown current server" );
Cmd_AddCommand( "playersonly", SV_PlayersOnly_f, "freezes time, except for players" );
}
void SV_KillOperatorCommands( void )
@ -710,6 +723,7 @@ void SV_KillOperatorCommands( void )
Cmd_RemoveCommand( "status" );
Cmd_RemoveCommand( "serverinfo" );
Cmd_RemoveCommand( "clientinfo" );
Cmd_RemoveCommand( "playersonly" );
Cmd_RemoveCommand( "map" );
Cmd_RemoveCommand( "movie" );

View File

@ -51,18 +51,29 @@ void SV_UpdateEntityState( const edict_t *ent, bool baseline )
if( !ent->pvServerData->s.classname )
ent->pvServerData->s.classname = SV_ClassIndex( STRING( ent->v.classname ));
if( client )
if( client && !sv.paused )
{
SV_SetIdealPitch( client );
if( ent->v.fixangle )
switch( ent->v.fixangle )
{
case 1:
MSG_WriteByte( &sv.multicast, svc_setangle );
MSG_WriteAngle32( &sv.multicast, ent->v.angles[0] );
MSG_WriteAngle32( &sv.multicast, ent->v.angles[1] );
MSG_WriteAngle32( &sv.multicast, 0 );
MSG_DirectSend( MSG_ONE, vec3_origin, client->edict );
ent->pvServerData->s.ed_flags |= ESF_NO_PREDICTION;
break;
case 2:
MSG_WriteByte( &sv.multicast, svc_addangle );
MSG_WriteAngle32( &sv.multicast, client->anglechangetotal );
MSG_WriteAngle32( &sv.multicast, client->anglechangefinal );
MSG_DirectSend( MSG_ONE, vec3_origin, client->edict );
client->anglechangetotal = client->anglechangefinal = 0;
break;
}
client->edict->v.fixangle = 0; // reset fixangle
if( client->modelindex )
{
@ -73,10 +84,6 @@ void SV_UpdateEntityState( const edict_t *ent, bool baseline )
svgame.dllFuncs.pfnUpdateEntityState( &ent->pvServerData->s, (edict_t *)ent, baseline );
if( client )
{
client->edict->v.fixangle = false;
}
// always keep an actual
ent->pvServerData->s.number = ent->serialnumber;
}
@ -197,7 +204,7 @@ static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_
if( pClient && !portal )
{
// portals can't change hostflags
sv.hostflags = 0;
sv.hostflags &= ~SVF_SKIPLOCALHOST;
cl = SV_ClientFromEdict( pClient, true );
Com_Assert( cl == NULL );

View File

@ -111,7 +111,7 @@ void SV_ConfigString( int index, const char *val )
}
}
static bool SV_EntitiesIn( int mode, const vec3_t v1, const vec3_t v2 )
static bool SV_OriginIn( int mode, const vec3_t v1, const vec3_t v2 )
{
int leafnum, cluster;
int area1, area2;
@ -122,7 +122,7 @@ static bool SV_EntitiesIn( int mode, const vec3_t v1, const vec3_t v2 )
area1 = CM_LeafArea( leafnum );
if( mode == DVIS_PHS ) mask = CM_ClusterPHS( cluster );
else if( mode == DVIS_PVS ) mask = CM_ClusterPVS( cluster );
else Host_Error( "SV_EntitiesIn ?\n" );
else Host_Error( "SV_OriginIn ?\n" );
leafnum = CM_PointLeafnum( v2 );
cluster = CM_LeafCluster( leafnum );
@ -135,6 +135,32 @@ static bool SV_EntitiesIn( int mode, const vec3_t v1, const vec3_t v2 )
return true;
}
static bool SV_BBoxIn( int mode, const vec3_t org1, const vec3_t absmin, const vec3_t absmax )
{
int leafnum, cluster;
int area1, area2;
byte *mask;
vec3_t org2;
leafnum = CM_PointLeafnum( org1 );
cluster = CM_LeafCluster( leafnum );
area1 = CM_LeafArea( leafnum );
if( mode == DVIS_PHS ) mask = CM_ClusterPHS( cluster );
else if( mode == DVIS_PVS ) mask = CM_ClusterPVS( cluster );
else Host_Error( "SV_BBoxIn ?\n" );
VectorAverage( absmin, absmax, org2 );
leafnum = CM_PointLeafnum( org2 );
cluster = CM_LeafCluster( leafnum );
area2 = CM_LeafArea( leafnum );
if( pe && mask && !pe->BoxVisible( absmin, absmax, mask ))
return false;
else if( !CM_AreasConnected( area1, area2 ))
return false;
return true;
}
void SV_WriteEntityPatch( const char *filename )
{
file_t *f;
@ -1065,7 +1091,7 @@ edict_t* pfnFindClientInPVS( edict_t *pEdict )
org = cl->pViewEntity->v.origin;
else org = pClient->v.origin;
if( SV_EntitiesIn( DVIS_PVS, pEdict->v.origin, org ))
if( SV_OriginIn( DVIS_PVS, pEdict->v.origin, org ))
return pClient;
}
return NULL;
@ -1099,7 +1125,7 @@ edict_t* pfnFindClientInPHS( edict_t *pEdict )
org = cl->pViewEntity->v.origin;
else org = pClient->v.origin;
if( SV_EntitiesIn( DVIS_PHS, pEdict->v.origin, org ))
if( SV_OriginIn( DVIS_PHS, pEdict->v.origin, org ))
return pClient;
}
return NULL;
@ -1111,28 +1137,25 @@ pfnEntitiesInPVS
=================
*/
edict_t* pfnEntitiesInPVS( edict_t *pplayer )
edict_t *pfnEntitiesInPVS( edict_t *pplayer )
{
edict_t *pEdict, *chain;
vec3_t checkPos;
int i;
int i, result;
chain = NULL;
if( !SV_IsValidEdict( pplayer ))
return NULL;
if( !pplayer || pplayer->free )
return chain;
for( i = svgame.globals->maxClients + 1; i < svgame.globals->numEntities; i++ )
for( chain = NULL, i = svgame.globals->maxClients + 1; i < svgame.globals->numEntities; i++ )
{
pEdict = EDICT_NUM( i );
if( !SV_IsValidEdict( pEdict )) continue;
if( CM_GetModelType( pEdict->v.modelindex ) == mod_brush )
VectorAverage( pEdict->v.mins, pEdict->v.maxs, checkPos );
else VectorCopy( pEdict->v.origin, checkPos );
result = SV_BBoxIn( DVIS_PVS, pplayer->v.origin, pEdict->v.absmin, pEdict->v.absmax );
else result = SV_OriginIn( DVIS_PVS, pplayer->v.origin, pEdict->v.origin );
if( SV_EntitiesIn( DVIS_PVS, checkPos, pplayer->v.origin ))
if( result )
{
pEdict->v.chain = chain;
chain = pEdict;
@ -1147,28 +1170,25 @@ pfnEntitiesInPHS
=================
*/
edict_t* pfnEntitiesInPHS( edict_t *pplayer )
edict_t *pfnEntitiesInPHS( edict_t *pplayer )
{
edict_t *pEdict, *chain;
vec3_t checkPos;
int i;
int i, result;
chain = NULL;
if( !SV_IsValidEdict( pplayer ))
return NULL;
if( !pplayer || pplayer->free )
return chain;
for( i = svgame.globals->maxClients + 1; i < svgame.globals->numEntities; i++ )
for( chain = NULL, i = svgame.globals->maxClients + 1; i < svgame.globals->numEntities; i++ )
{
pEdict = EDICT_NUM( i );
if( !SV_IsValidEdict( pEdict )) continue;
if( CM_GetModelType( pEdict->v.modelindex ) == mod_brush )
VectorAverage( pEdict->v.mins, pEdict->v.maxs, checkPos );
else VectorCopy( pEdict->v.origin, checkPos );
result = SV_BBoxIn( DVIS_PHS, pplayer->v.origin, pEdict->v.absmin, pEdict->v.absmax );
else result = SV_OriginIn( DVIS_PHS, pplayer->v.origin, pEdict->v.origin );
if( SV_EntitiesIn( DVIS_PHS, checkPos, pplayer->v.origin ))
if( result )
{
pEdict->v.chain = chain;
chain = pEdict;
@ -1281,6 +1301,9 @@ int pfnDropToFloor( edict_t* e )
vec3_t end;
trace_t trace;
if( sv.loadgame )
return 0;
if( !SV_IsValidEdict( e ))
{
MsgDev( D_ERROR, "SV_DropToFloor: invalid entity %s\n", SV_ClassName( e ));

View File

@ -175,16 +175,11 @@ void SV_ActivateServer( void )
// Activate the DLL server code
svgame.dllFuncs.pfnServerActivate( svgame.edicts, svgame.globals->numEntities, svgame.globals->maxClients );
// all precaches are complete
sv.state = ss_active;
Host_SetServerState( sv.state );
// create a baseline for more efficient communications
SV_CreateBaseline();
if( !sv.loadgame )
sv.frametime = 0;
if( sv.loadgame ) SV_CalcFrametime ();
// run two frames to allow everything to settle
SV_Physics();
@ -211,8 +206,12 @@ void SV_ActivateServer( void )
Cvar_FullSet( "mapname", sv.name, CVAR_SERVERINFO|CVAR_INIT );
CM_EndRegistration (); // free unused models
sv.state = ss_active;
sv.cphys_prepped = true;
physinfo->modified = true;
Host_SetServerState( sv.state );
}
/*

View File

@ -25,7 +25,6 @@ cvar_t *sv_maxvelocity;
cvar_t *sv_gravity;
cvar_t *sv_stepheight;
cvar_t *sv_noreload; // don't reload level state when reentering
cvar_t *sv_playersonly;
cvar_t *sv_rollangle;
cvar_t *sv_rollspeed;
cvar_t *sv_wallbounce;
@ -219,6 +218,24 @@ void SV_UpdateServerInfo( void )
serverinfo->modified = false;
}
/*
=================
SV_CalcFrametime
=================
*/
void SV_CalcFrametime( void )
{
if( sv_fps->modified )
{
if( sv_fps->value < 10 ) Cvar_Set( "sv_fps", "10" ); // too slow, also, netcode uses a byte
else if( sv_fps->value > 90 ) Cvar_Set( "sv_fps", "90" ); // abusive
sv_fps->modified = false;
}
// calc sv.frametime
sv.frametime = ( 1000 / sv_fps->integer );
}
/*
=================
SV_ReadPackets
@ -296,16 +313,6 @@ void SV_CheckTimeouts( void )
float zombiepoint;
int i, numclients = 0;
if( sv_fps->modified )
{
if( sv_fps->value < 10 ) Cvar_Set( "sv_fps", "10" ); // too slow, also, netcode uses a byte
else if( sv_fps->value > 90 ) Cvar_Set( "sv_fps", "90" ); // abusive
sv_fps->modified = false;
}
// calc sv.frametime
sv.frametime = ( 1000 / sv_fps->integer );
droppoint = svs.realtime - (timeout->value * 1000);
zombiepoint = svs.realtime - (zombietime->value * 1000);
@ -431,6 +438,9 @@ void SV_Frame( int time )
// keep the random time dependent
rand ();
// calc sv.frametime
SV_CalcFrametime ();
// check timeouts
SV_CheckTimeouts ();
@ -473,11 +483,11 @@ void SV_Frame( int time )
// send messages back to the clients that had packets read this frame
SV_SendClientMessages ();
// send a heartbeat to the master if needed
Master_Heartbeat ();
// clear edict flags for next frame
SV_PrepWorldFrame ();
// send a heartbeat to the master if needed
Master_Heartbeat ();
}
//============================================================================
@ -589,7 +599,6 @@ void SV_Init( void )
sv_fps = Cvar_Get( "sv_fps", "72.1", CVAR_ARCHIVE, "running server physics at" );
sv_stepheight = Cvar_Get( "sv_stepheight", "18", CVAR_ARCHIVE|CVAR_PHYSICINFO, "how high you can step up" );
sv_playersonly = Cvar_Get( "playersonly", "0", 0, "freezes time, except for players" );
sv_newunit = Cvar_Get( "sv_newunit", "0", 0, "sets to 1 while new unit is loading" );
hostname = Cvar_Get( "sv_hostname", "unnamed", CVAR_SERVERINFO | CVAR_ARCHIVE, "host name" );
timeout = Cvar_Get( "timeout", "125", 0, "connection timeout" );

View File

@ -171,6 +171,21 @@ Returns false if the entity removed itself.
*/
bool SV_RunThink( edict_t *ent )
{
#if 1
float thinktime;
thinktime = ent->v.nextthink;
if( thinktime <= 0.0f || thinktime > ( sv.time * 0.001f ) + ( sv.frametime * 0.001f ))
return true;
if( thinktime < svgame.globals->time )
thinktime = ( sv.time * 0.001f ); // don't let things stay in the past.
// it is possible to start that way
// by a trigger with a local time.
ent->v.nextthink = 0;
svgame.globals->time = thinktime;
svgame.dllFuncs.pfnThink( ent );
#else
int i;
float newtime;
@ -196,6 +211,7 @@ bool SV_RunThink( edict_t *ent )
if( ent->v.nextthink <= svgame.globals->time || ent->v.nextthink > newtime || !sv_synchthink->integer )
break;
}
#endif
return !ent->free;
}
@ -1167,6 +1183,22 @@ bool SV_PushAngles( edict_t *pusher, vec3_t move, vec3_t amove )
VectorAdd( check->v.origin, move, check->v.origin );
VectorAdd( check->v.angles, amove, check->v.angles);
if( check->v.flags & FL_CLIENT )
{
sv_client_t *cl;
if(( cl = SV_ClientFromEdict( check, true )) != NULL )
{
// Because we can run multiple ticks per server frame,
// accumulate a total offset here instead of straight
// setting it. The engine will reset anglechange to 0
// when the message is actually sent to the client
cl->anglechangetotal += amove[1];
cl->anglechangefinal = amove[1];
check->v.fixangle = 2;
}
}
// figure movement due to the pusher's amove
VectorSubtract( check->v.origin, pusher->v.origin, org );
org2[0] = DotProduct( org, forward );
@ -1182,7 +1214,7 @@ bool SV_PushAngles( edict_t *pusher, vec3_t move, vec3_t amove )
check->v.groundentity = 0;
block = SV_TestEntityPosition( check, vec3_origin );
if (!block)
if( !block )
{
// pushed ok
SV_LinkEdict( check, false );
@ -1209,7 +1241,6 @@ bool SV_PushAngles( edict_t *pusher, vec3_t move, vec3_t amove )
continue;
}
MsgDev( D_INFO, "Pusher hit %s\n", SV_ClassName( check ));
svgame.globals->time = (sv.time * 0.001f);
svgame.dllFuncs.pfnBlocked( pusher, check );
@ -1272,19 +1303,19 @@ void SV_Physics_Pusher( edict_t *ent )
float thinktime;
float oldltime;
float movetime;
vec3_t oldorg, move;
vec3_t oldorg, lmove;
vec3_t oldang, amove;
float l;
oldltime = ent->v.ltime;
thinktime = ent->v.nextthink;
if( thinktime < ent->v.ltime + svgame.globals->frametime )
if( thinktime < ent->v.ltime + ( sv.frametime * 0.001f ))
{
movetime = thinktime - ent->v.ltime;
if( movetime < 0 ) movetime = 0;
if( movetime < 0.0f ) movetime = 0.0f;
}
else movetime = svgame.globals->frametime;
else movetime = sv.frametime * 0.001f;
if( movetime )
{
@ -1301,15 +1332,15 @@ void SV_Physics_Pusher( edict_t *ent )
svgame.dllFuncs.pfnThink( ent );
if( ent->free ) return;
VectorSubtract( ent->v.origin, oldorg, move );
VectorSubtract( ent->v.origin, oldorg, lmove );
VectorSubtract( ent->v.angles, oldang, amove);
l = VectorLength( move ) + VectorLength( amove );
if( l > 1.0f / 64 )
l = VectorLength( lmove ) + VectorLength( amove );
if( l > ( 1.0f / 64 ))
{
Msg( "**** snap: %f\n", l );
VectorCopy( oldorg, ent->v.origin );
SV_PushAngles( ent, move, amove );
VectorCopy( oldang, ent->v.angles );
SV_PushAngles( ent, lmove, amove );
}
}
@ -1318,9 +1349,8 @@ void SV_Physics_Pusher( edict_t *ent )
ent->v.nextthink = 0;
svgame.globals->time = (sv.time * 0.001f);
svgame.dllFuncs.pfnThink( ent );
if( ent->free ) return;
}
SV_LinkEdict( ent, false );
}
/*
@ -2098,9 +2128,8 @@ void SV_Physics( void )
// let the progs know that a new frame has started
svgame.globals->time = sv.time * 0.001f;
svgame.globals->frametime = sv.frametime * 0.001f;
svgame.dllFuncs.pfnStartFrame();
// Msg( "SV_Physics: %g, frametime %g\n", svgame.globals->time, svgame.globals->frametime );
svgame.dllFuncs.pfnStartFrame();
SV_CheckAllEnts ();
@ -2114,7 +2143,7 @@ void SV_Physics( void )
}
// treat each object in turn
if( !sv_playersonly->integer )
if( !( sv.hostflags & SVF_PLAYERSONLY ))
{
for( i = svgame.globals->maxClients + 1; i < svgame.globals->numEntities; i++ )
{
@ -2135,5 +2164,5 @@ void SV_Physics( void )
svgame.dllFuncs.pfnEndFrame();
if( !sv_playersonly->integer ) sv.time += sv.frametime;
if( !( sv.hostflags & SVF_PLAYERSONLY )) sv.time += sv.frametime;
}

View File

@ -340,25 +340,46 @@ void LandmarkOrigin( SAVERESTOREDATA *pSaveData, vec3_t output, const char *pLan
VectorClear( output );
}
// UNDONE: This could be a better test - can we run the absbox through the bsp and see
// if it contains any solid space? or would that eliminate some entities we want to keep?
int EntityInSolid( edict_t *ent )
{
edict_t *pParent = ent->v.aiment;
edict_t *hit, *touch[MAX_EDICTS];
int i, contents, numtouch;
vec3_t point;
// HACKHACK -- If you're attached to a client, always go through
// if you're attached to a client, always go through
if( SV_IsValidEdict( pParent ))
{
if( pParent->v.flags & FL_CLIENT )
return 0;
}
VectorAverage( ent->v.absmin, ent->v.absmax, point );
#if 1
return (SV_PointContents( point ) == CONTENTS_SOLID);
#else
return SV_TestEntityPosition( ent, vec3_origin );
#endif
// run first test - stuck in the world
contents = CM_PointContents( point, 0 );
// solid or deathfog area
if( contents & ( BASECONT_SOLID|BASECONT_NODROP ))
return 1;
// run second test - stuck in the bspbrush
numtouch = SV_AreaEdicts( ent->v.absmin, ent->v.absmax, touch, MAX_EDICTS, AREA_SOLID );
for( i = 0; i < numtouch; i++ )
{
hit = touch[i];
if( hit == ent ) continue;
if( hit->v.solid != SOLID_BSP )
continue;
contents = CM_TransformedPointContents( point, World_HullForEntity( hit ), hit->v.origin, hit->v.angles );
// stuck in bspbrsuh
if( contents & ( BASECONT_SOLID|BASECONT_NODROP ))
return 1;
}
return 0;
}
void SV_ClearSaveDir( void )
@ -367,7 +388,7 @@ void SV_ClearSaveDir( void )
int i;
// just delete all HL? files
t = FS_Search( "save/*.HL?", true );
t = FS_Search( "$save/*.HL?", true );
if( !t ) return; // already empty
for( i = 0; i < t->numfilenames; i++ )
@ -634,8 +655,8 @@ SAVERESTOREDATA *SV_LoadSaveData( const char *level )
char *pszTokenList;
int i, id, size, version;
com.snprintf( name, sizeof( name ), "save/%s.HL1", level );
MsgDev( D_INFO, "Loading game from %s...\n", name );
com.snprintf( name, sizeof( name ), "$save/%s.HL1", level );
MsgDev( D_INFO, "Loading game from %s...\n", name + 1 );
pFile = FS_Open( name, "rb" );
if( !pFile )
@ -806,7 +827,7 @@ void SV_EntityPatchRead( SAVERESTOREDATA *pSaveData, const char *level )
file_t *pFile;
int i, size, entityId;
com.snprintf( name, sizeof( name ), "save/%s.HL3", level );
com.snprintf( name, sizeof( name ), "$save/%s.HL3", level );
pFile = FS_Open( name, "rb" );
if( !pFile ) return;
@ -1317,7 +1338,7 @@ int SV_SaveGameSlot( const char *pSaveName, const char *pSaveComment )
pSaveData = SV_SaveInit( 0 );
com.strncpy( hlPath, "save/*.HL?", sizeof( hlPath ));
com.strncpy( hlPath, "$save/*.HL?", sizeof( hlPath ));
gameHeader.mapCount = SV_MapCount( hlPath );
com.strncpy( gameHeader.mapName, sv.name, sizeof( gameHeader.mapName ));
com.strncpy( gameHeader.comment, pSaveComment, sizeof( gameHeader.comment ));
@ -1457,9 +1478,9 @@ bool SV_LoadGame( const char *pName )
if( !pName || !pName[0] )
return false;
com.snprintf( name, sizeof( name ), "save/%s.sav", pName );
com.snprintf( name, sizeof( name ), "$save/%s.sav", pName );
MsgDev( D_INFO, "Loading game from %s...\n", name );
MsgDev( D_INFO, "Loading game from %s...\n", name + 1 );
SV_ClearSaveDir();
if( !svs.initialized ) SV_InitGame ();
@ -1569,7 +1590,7 @@ used for reload game after player death
*/
const char *SV_GetLatestSave( void )
{
search_t *f = FS_Search( "save/*.sav", true );
search_t *f = FS_Search( "$save/*.sav", true );
int i, found = 0;
long newest = 0, ft;
string savename;

View File

@ -131,7 +131,7 @@ static void UI_LoadGame_GetGameList( void )
search_t *t;
int i;
t = FS_Search( "save/*.sav", true );
t = FS_Search( "$save/*.sav", true );
for( i = 0; t && i < t->numfilenames; i++ )
{

View File

@ -131,7 +131,7 @@ static void UI_PlayDemo_GetDemoList( void )
search_t *t;
int i;
t = FS_Search( "demos/*.dem", true );
t = FS_Search( "$demos/*.dem", true );
for( i = 0; t && i < t->numfilenames; i++ )
{

View File

@ -131,7 +131,7 @@ static void UI_RecDemo_GetDemoList( void )
search_t *t;
int i = 0, j;
t = FS_Search( "demos/*.dem", true );
t = FS_Search( "$demos/*.dem", true );
if( cls.state == ca_active && !cls.demorecording && !cls.demoplayback )
{

View File

@ -131,7 +131,7 @@ static void UI_SaveGame_GetGameList( void )
search_t *t;
int i = 0, j;
t = FS_Search( "save/*.sav", true );
t = FS_Search( "$save/*.sav", true );
if( cls.state == ca_active )
{

View File

@ -116,7 +116,7 @@ searchpath_t fs_directpath; // static direct path
static void FS_InitMemory( void );
const char *FS_FileExtension( const char *in );
static searchpath_t *FS_FindFile (const char *name, int *index, bool quiet );
static searchpath_t *FS_FindFile( const char *name, int *index, bool quiet, bool gamedironly );
static dlumpinfo_t *W_FindLump( wfile_t *wad, const char *name, const char matchtype );
static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack, fs_offset_t offset, fs_offset_t packsize, fs_offset_t realsize, int flags);
static byte *W_LoadFile( const char *path, fs_offset_t *filesizeptr );
@ -877,7 +877,7 @@ If keep_plain_dirs is set, the pack will be added AFTER the first sequence of
plain directories.
================
*/
static bool FS_AddPack_Fullpath( const char *pakfile, bool *already_loaded, bool keep_plain_dirs )
static bool FS_AddPack_Fullpath( const char *pakfile, bool *already_loaded, bool keep_plain_dirs, int flags )
{
searchpath_t *search;
pack_t *pak = NULL;
@ -924,6 +924,7 @@ static bool FS_AddPack_Fullpath( const char *pakfile, bool *already_loaded, bool
search = (searchpath_t *)Mem_Alloc( fs_mempool, sizeof( searchpath_t ));
search->pack = pak;
search->next = fs_searchpaths;
search->flags |= flags;
fs_searchpaths = search;
}
else // otherwise we want to append directly after insertion_point.
@ -931,6 +932,7 @@ static bool FS_AddPack_Fullpath( const char *pakfile, bool *already_loaded, bool
search = (searchpath_t *)Mem_Alloc( fs_mempool, sizeof( searchpath_t ));
search->pack = pak;
search->next = insertion_point->next;
search->flags |= flags;
insertion_point->next = search;
}
}
@ -939,6 +941,7 @@ static bool FS_AddPack_Fullpath( const char *pakfile, bool *already_loaded, bool
search = (searchpath_t *)Mem_Alloc( fs_mempool, sizeof( searchpath_t ));
search->pack = pak;
search->next = fs_searchpaths;
search->flags |= flags;
fs_searchpaths = search;
}
return true;
@ -1025,7 +1028,6 @@ static bool FS_AddWad_Fullpath( const char *wadfile, bool *already_loaded, bool
}
}
/*
================
FS_AddPack
@ -1049,14 +1051,14 @@ bool FS_AddPack( const char *pakfile, bool *already_loaded, bool keep_plain_dirs
if( already_loaded ) *already_loaded = false;
// then find the real name...
search = FS_FindFile( pakfile, &index, true );
search = FS_FindFile( pakfile, &index, true, false );
if( !search || search->pack )
{
MsgDev( D_WARN, "FS_AddPack: could not find pak \"%s\"\n", pakfile );
return false;
}
com.sprintf( fullpath, "%s%s", search->filename, pakfile );
return FS_AddPack_Fullpath( fullpath, already_loaded, keep_plain_dirs );
return FS_AddPack_Fullpath( fullpath, already_loaded, keep_plain_dirs, 0 );
}
/*
@ -1088,7 +1090,7 @@ void FS_AddGameDirectory( const char *dir, int flags )
if( !com.stricmp( FS_FileExtension( list.strings[i] ), "pak" ))
{
com.sprintf( pakfile, "%s%s", dir, list.strings[i] );
FS_AddPack_Fullpath( pakfile, NULL, false );
FS_AddPack_Fullpath( pakfile, NULL, false, flags );
}
}
@ -1098,7 +1100,7 @@ void FS_AddGameDirectory( const char *dir, int flags )
if( !com.stricmp( FS_FileExtension( list.strings[i]), "pk2" ))
{
com.sprintf( pakfile, "%s%s", dir, list.strings[i] );
FS_AddPack_Fullpath( pakfile, NULL, false );
FS_AddPack_Fullpath( pakfile, NULL, false, flags );
}
}
@ -1108,7 +1110,7 @@ void FS_AddGameDirectory( const char *dir, int flags )
if( !com.stricmp( FS_FileExtension( list.strings[i] ), "pk3" ))
{
com.sprintf( pakfile, "%s%s", dir, list.strings[i] );
FS_AddPack_Fullpath( pakfile, NULL, false );
FS_AddPack_Fullpath( pakfile, NULL, false, flags );
}
}
@ -1300,7 +1302,7 @@ void FS_Rescan( void )
FS_ClearSearchPath();
FS_AddGameHierarchy( SI.GameInfo->basedir, 0 );
FS_AddGameHierarchy( SI.GameInfo->gamedir, 0 );
FS_AddGameHierarchy( SI.GameInfo->gamedir, FS_GAMEDIR_PATH );
}
void FS_Rescan_f( void )
@ -2032,7 +2034,7 @@ Return the searchpath where the file was found (or NULL)
and the file index in the package if relevant
====================
*/
static searchpath_t *FS_FindFile( const char *name, int* index, bool quiet )
static searchpath_t *FS_FindFile( const char *name, int* index, bool quiet, bool gamedironly )
{
searchpath_t *search;
char *pEnvPath;
@ -2041,6 +2043,9 @@ static searchpath_t *FS_FindFile( const char *name, int* index, bool quiet )
// search through the path, one element at a time
for( search = fs_searchpaths; search; search = search->next )
{
if( gamedironly & !( search->flags & FS_GAMEDIR_PATH ))
continue;
// is the element a pak file?
if( search->pack )
{
@ -2145,10 +2150,17 @@ Look for a file in the search paths and open it in read-only mode
*/
file_t *FS_OpenReadFile( const char *filename, const char *mode, bool quiet )
{
searchpath_t *search;
int pack_ind;
searchpath_t *search;
bool gamedironly = false;
int pack_ind;
search = FS_FindFile( filename, &pack_ind, quiet );
if( filename[0] == '$' )
{
filename++;
gamedironly = true;
}
search = FS_FindFile( filename, &pack_ind, quiet, gamedironly );
// not found?
if( search == NULL )
@ -2798,7 +2810,15 @@ Look for a file in the packages and in the filesystem
*/
bool FS_FileExists( const char *filename )
{
if( FS_FindFile( filename, NULL, true ))
bool gamedironly = false;
if( filename[0] == '$' )
{
filename++;
gamedironly = true;
}
if( FS_FindFile( filename, NULL, true, gamedironly ))
return true;
return false;
}
@ -2829,7 +2849,7 @@ dll_user_t *FS_FindLibrary( const char *dllname, bool directpath )
else com.strncpy( dllpath, dllname, sizeof( dllpath ));
FS_DefaultExtension( dllpath, ".dll" ); // trying to apply if forget
search = FS_FindFile( dllpath, &index, true );
search = FS_FindFile( dllpath, &index, true, false );
if( !search )
{
fs_ext_path = false;
@ -2837,7 +2857,7 @@ dll_user_t *FS_FindLibrary( const char *dllname, bool directpath )
// trying check also 'bin' folder for indirect paths
com.strncpy( dllpath, dllname, sizeof( dllpath ));
search = FS_FindFile( dllpath, &index, true );
search = FS_FindFile( dllpath, &index, true, false );
if( !search ) return NULL; // unable to find
}
@ -2901,7 +2921,7 @@ fs_offset_t FS_FileTime( const char *filename )
searchpath_t *search;
int pack_ind;
search = FS_FindFile( filename, &pack_ind, true );
search = FS_FindFile( filename, &pack_ind, true, false );
if( !search ) return -1; // doesn't exist
if( search->pack ) // grab pack filetime
@ -2976,6 +2996,7 @@ static search_t *_FS_Search( const char *pattern, int caseinsensitive, int quiet
searchpath_t *searchpath;
pack_t *pak;
wfile_t *wad;
bool gamedironly = false;
int i, basepathlength, numfiles, numchars;
int resultlistindex, dirlistindex;
const char *slash, *backslash, *colon, *separator;
@ -2992,8 +3013,14 @@ static search_t *_FS_Search( const char *pattern, int caseinsensitive, int quiet
return NULL;
}
stringlistinit(&resultlist);
stringlistinit(&dirlist);
if( pattern[0] == '$' )
{
gamedironly = true;
pattern++; // ignore this symbol
}
stringlistinit( &resultlist );
stringlistinit( &dirlist );
slash = com.strrchr( pattern, '/' );
backslash = com.strrchr( pattern, '\\' );
colon = com.strrchr( pattern, ':' );
@ -3007,6 +3034,9 @@ static search_t *_FS_Search( const char *pattern, int caseinsensitive, int quiet
// search through the path, one element at a time
for( searchpath = fs_searchpaths; searchpath; searchpath = searchpath->next )
{
if( gamedironly && !( searchpath->flags & FS_GAMEDIR_PATH ))
continue;
// is the element a pak file?
if( searchpath->pack )
{
@ -4209,7 +4239,7 @@ static byte *W_LoadFile( const char *path, fs_offset_t *lumpsizeptr )
searchpath_t *search;
int index;
search = FS_FindFile( path, &index, true );
search = FS_FindFile( path, &index, true, false );
if( search && search->wad )
return W_ReadLump( search->wad, &search->wad->lumps[index], lumpsizeptr );
return NULL;

View File

@ -411,6 +411,7 @@ typedef struct rgbdata_s
// filesystem flags
#define FS_STATIC_PATH 1 // FS_ClearSearchPath will be ignore this path
#define FS_NOWRITE_PATH 2 // default behavior - last added gamedir set as writedir. This flag disables it
#define FS_GAMEDIR_PATH 4 // just a marker for gamedir path
/*
==============================================================================

View File

@ -64,7 +64,9 @@ typedef struct
{
float animtime; // curstate.animtime
int sequence; // curstate.sequence
int gaitsequence; // curstate.gaitsequence
float frame; // curstate.frame
float gaitframe; // client->frame + yaw
vec3_t origin; // curstate.origin
vec3_t angles; // curstate.angles
byte blending[16]; // curstate.blending
@ -75,11 +77,14 @@ typedef struct
{
float animtime; // latched.prevanimtime
float sequencetime; // latechd.prevsequencetime
float gaitsequencetime; // latehed.prevgaitsequencetime
byte seqblending[16]; // blending between sequence when it's changed
vec3_t origin; // latched.prevorigin
vec3_t angles; // latched.prevangles
int sequence; // latched.prevsequence
int gaitsequence; // latched.gaitsequence
float frame; // latched.prevframe
float gaitframe; // latched.gaitprevframe
byte controller[16]; // latched.prevcontroller
byte blending[16]; // latched.prevblending
} latchedvars_t;
@ -92,7 +97,6 @@ typedef struct
// CLIENT SPECIFIC
vec3_t gaitorigin; // client oldorigin used to calc velocity
float gaitframe; // client->frame + yaw
float gaityaw; // local value
// EVENT SPECIFIC

View File

@ -293,14 +293,12 @@ void CBaseEntity :: ResetParent( void )
void CBaseEntity :: SetupPhysics( void )
{
// rebuild all parents
if( pFlags & PF_LINKCHILD ) LinkChild( this );
if ( pFlags & PF_LINKCHILD ) LinkChild( this );
if ( gpGlobals->changelevel )
{
ALERT( at_console, "rebuild Phys()\n" );
m_physinit = FALSE; // rebuild parents on next level
}
if( m_physinit ) return;
if ( m_physinit ) return;
SetParent(); //set all parents
m_physinit = true;

View File

@ -1169,11 +1169,6 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
}
if( to->ed_type == ED_CLIENT )
{
if( pNet->pev->fixangle )
{
to->ed_flags |= ESF_NO_PREDICTION;
}
if( pNet->pev->teleport_time )
{
to->ed_flags |= ESF_NO_PREDICTION;

View File

@ -1137,11 +1137,6 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
}
if( to->ed_type == ED_CLIENT )
{
if( pNet->pev->fixangle )
{
to->ed_flags |= ESF_NO_PREDICTION;
}
if( pNet->pev->teleport_time )
{
to->ed_flags |= ESF_NO_PREDICTION;

View File

@ -2790,6 +2790,7 @@ void CFade::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType
if ( !(pev->spawnflags & SF_FADE_IN) )
fadeFlags |= FFADE_OUT;
else fadeFlags |= FFADE_IN;
if ( pev->spawnflags & SF_FADE_MODULATE )
fadeFlags |= FFADE_MODULATE;

View File

@ -320,7 +320,7 @@ void CGauss::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage )
// It's delayed by a fraction of second to make sure it is delayed by 1 frame on the client
// It's sent reliably anyway, which could lead to other delays
PLAYBACK_EVENT_FULL( NULL | FEV_RELIABLE, m_pPlayer->edict(), m_usGaussFire, 0.01, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, 0.0, 0.0, pev->body, 0, 0, 1 );
PLAYBACK_EVENT_FULL( FEV_RELIABLE, m_pPlayer->edict(), m_usGaussFire, 0.01, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, 0.0, 0.0, pev->body, 0, 0, 1 );
// ALERT( at_console, "%f %f %f\n%f %f %f\n", vecSrc.x, vecSrc.y, vecSrc.z, vecDest.x, vecDest.y, vecDest.z );
// ALERT( at_console, "%f %f\n", tr.flFraction, flMaxFrac );

View File

@ -133,7 +133,7 @@ void CMP5::PrimaryAttack()
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, 8192, BULLET_PLAYER_MP5, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
else vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, 8192, BULLET_PLAYER_MP5, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usMP5, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, 0, 0, 0 );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usMP5, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, MP5_FIRE1, 0, 0 );
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1;

View File

@ -4148,7 +4148,6 @@ void CBasePlayer :: UpdateClientData( void )
if (gDisplayTitle)
{
MESSAGE_BEGIN( MSG_ONE, gmsgShowGameTitle, NULL, pev );
WRITE_BYTE( 0 );
MESSAGE_END();
gDisplayTitle = 0;
}

View File

@ -157,7 +157,7 @@ void CPython::PrimaryAttack()
Vector vecDir;
vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, 8192, BULLET_PLAYER_357, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usFirePython, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, 0, 0, 0 );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usFirePython, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, PYTHON_FIRE1, 0, 0 );
m_flNextPrimaryAttack = gpGlobals->time + 1.0;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT ( 10, 15 );

View File

@ -145,7 +145,7 @@ void CShotgun::PrimaryAttack()
vecDir = m_pPlayer->FireBulletsPlayer( 4, vecSrc, vecAiming, VECTOR_CONE_DM_SHOTGUN, 2048, BULLET_PLAYER_BUCKSHOT, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
else vecDir = m_pPlayer->FireBulletsPlayer( 6, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_BUCKSHOT, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usSingleFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, 0, 0, 0 );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usSingleFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, SHOTGUN_FIRE, 0, 0 );
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
@ -206,7 +206,7 @@ void CShotgun::SecondaryAttack( void )
else vecDir = m_pPlayer->FireBulletsPlayer( 12, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_BUCKSHOT, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usDoubleFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, 0, 0, 0 );
PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usDoubleFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, pev->body, SHOTGUN_FIRE2, 0, 0 );
if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
// HEV suit - indicate out of ammo condition

View File

@ -653,11 +653,15 @@ void CWorld :: Precache( void )
else
CVAR_SET_FLOAT( "v_dark", 0.0 );
pev->spawnflags &= ~SF_WORLD_DARK; // don't apply fade after save\restore
if ( pev->spawnflags & SF_WORLD_TITLE )
gDisplayTitle = TRUE; // display the game title if this key is set
else
gDisplayTitle = FALSE;
pev->spawnflags &= ~SF_WORLD_TITLE; // don't show logo after save\restore
if ( pev->spawnflags & SF_WORLD_FORCETEAM )
{
CVAR_SET_FLOAT( "mp_defaultteam", 1 );

View File

@ -25,10 +25,11 @@ Xash 0.71 Beta 05.05.10
1. revision of all resources
2. fix sky changelevel bug
3. complete lights.shader
4. revision server physic
4. implement original half-life dll OK
5. revision monster moving OK
6. fix save\restore global state OK
7. rewrite WalkMove OK
8. tune UPDATE_BACKUP value for singleplayer OK
9. fix monsters interpolation OK
10.
10.revision MOVETYPE_PUSH physic
11.rewrite EntitiesInPVS check

View File

@ -494,13 +494,13 @@ void GL_InitCommands( void )
r_norefresh = Cvar_Get( "r_norefresh", "0", 0, "disable rendering (use with caution)" );
r_fullbright = Cvar_Get( "r_fullbright", "0", CVAR_CHEAT|CVAR_LATCH_VIDEO, "disable lightmaps, get fullbright" );
r_lightmap = Cvar_Get( "r_lightmap", "0", CVAR_CHEAT, "lightmap debugging tool" );
r_drawentities = Cvar_Get( "r_drawentities", "1", CVAR_CHEAT, "render entities" );
r_drawentities = Cvar_Get( "r_drawentities", "1", CVAR_CHEAT|CVAR_ARCHIVE, "render entities" );
r_drawworld = Cvar_Get( "r_drawworld", "1", CVAR_CHEAT, "render world" );
r_novis = Cvar_Get( "r_novis", "0", 0, "ignore vis information (perfomance test)" );
r_nocull = Cvar_Get( "r_nocull", "0", 0, "ignore frustrum culling (perfomance test)" );
r_speeds = Cvar_Get( "r_speeds", "0", CVAR_ARCHIVE, "shows r_speeds" );
r_drawelements = Cvar_Get( "r_drawelements", "1", 0, "use gldrawElements or glDrawRangeElements" );
gl_wireframe = Cvar_Get( "gl_wireframe", "0", CVAR_CHEAT|CVAR_ARCHIVE, "show mesh triangles" );
gl_wireframe = Cvar_Get( "gl_wireframe", "0", CVAR_CHEAT, "show mesh triangles" );
r_lockpvs = Cvar_Get( "r_lockpvs", "0", CVAR_CHEAT, "lockpvs area at current point (pvs test)" );
gl_clear = Cvar_Get( "gl_clear", "0", CVAR_ARCHIVE, "clearing screen after each frame" );
r_mode = Cvar_Get( "r_mode", VID_DEFAULTMODE, CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "display resolution mode" );

View File

@ -139,7 +139,8 @@ void R_StudioUpdateVars( edict_t *in, ref_entity_t *out )
{
int i;
out->lerp->latched.sequencetime = 0.0f; // no lerping between sequences
out->lerp->latched.sequencetime = 0.0f; // no lerping between sequences
out->lerp->latched.gaitsequencetime = 0.0f; // no lerping between gaitsequences
out->lerp->latched.sequence = out->lerp->curstate.sequence = in->v.sequence; // keep an actual
out->lerp->latched.animtime = out->lerp->curstate.animtime = in->v.animtime;
@ -182,6 +183,13 @@ void R_StudioUpdateVarsInterpolant( edict_t *in, ref_entity_t *out )
}
out->lerp->curstate.sequence = in->v.sequence; // keep an actual
if( in->v.gaitsequence != out->lerp->curstate.gaitsequence && out->lerp->latched.sequencetime == 0.0f )
{
out->lerp->latched.gaitsequencetime = out->lerp->curstate.animtime + 0.01f;
out->lerp->latched.gaitsequence = out->lerp->curstate.gaitsequence; // save old gaitsequence
}
out->lerp->curstate.gaitsequence = in->v.gaitsequence; // keep an actual
if( in->v.animtime != out->lerp->curstate.animtime )
{
// client got new packet, shuffle animtimes
@ -286,6 +294,7 @@ void R_StudioAllocTentExtradata( TEMPENTITY *in, ref_entity_t *e )
Com_Assert( studio->lerp == NULL );
e->lerp->latched.sequencetime = 0.0f; // no lerping between sequences
e->lerp->latched.gaitsequencetime = 0.0f; // no lerping between gaitsequences
e->lerp->latched.sequence = e->lerp->curstate.sequence = in->m_iSequence; // keep an actual
e->lerp->latched.animtime = e->lerp->curstate.animtime = in->m_flFrameMax; // HACKHACK: used m_flFrameMax as animtime
@ -1435,7 +1444,7 @@ void R_StudioSetupBones( ref_entity_t *e )
pseqdesc = (dstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + e->gaitsequence;
panim = R_StudioGetAnim( e->model, pseqdesc );
R_StudioCalcRotations( pos2, q2, pseqdesc, panim, pstudio->lerp->gaitframe );
R_StudioCalcRotations( pos2, q2, pseqdesc, panim, pstudio->lerp->curstate.gaitframe );
for( i = 0; i < m_pStudioHeader->numbones; i++ )
{
@ -1446,6 +1455,29 @@ void R_StudioSetupBones( ref_entity_t *e )
Mem_Copy( q[i], q2[i], sizeof( q[i] ));
}
}
if( m_fDoInterp && pstudio->lerp->latched.gaitsequencetime && ( pstudio->lerp->latched.gaitsequencetime + 0.2 > RI.refdef.time) && ( pstudio->lerp->latched.gaitsequence < m_pStudioHeader->numseq ))
{
// blend from last sequence
static float pos1b[MAXSTUDIOBONES][3];
static vec4_t q1b[MAXSTUDIOBONES];
float s;
pseqdesc = (dstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pstudio->lerp->latched.gaitsequence;
panim = R_StudioGetAnim( e->model, pseqdesc );
// clip prevframe
R_StudioCalcRotations( pos1b, q1b, pseqdesc, panim, pstudio->lerp->latched.gaitframe );
s = 1.0f - ( RI.refdef.time - pstudio->lerp->latched.gaitsequencetime ) / 0.2f;
R_StudioSlerpBones( q, pos, q1b, pos1b, s );
}
else
{
// store prevframe otherwise
//Msg( "prevgaitframe = %4.2f\n", pstudio->lerp->curstate.gaitframe );
pstudio->lerp->latched.gaitframe = pstudio->lerp->curstate.gaitframe;
}
for( i = 0; i < m_pStudioHeader->numbones; i++ )
{
@ -2159,16 +2191,16 @@ void R_StudioProcessGait( ref_entity_t *e, edict_t *pplayer, studiovars_t *pstud
// calc gait frame
if( pseqdesc->linearmovement[0] > 0 )
{
pstudio->lerp->gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes;
pstudio->lerp->curstate.gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes;
}
else
{
pstudio->lerp->gaitframe += pseqdesc->fps * dt;
pstudio->lerp->curstate.gaitframe += pseqdesc->fps * dt;
}
// do modulo
pstudio->lerp->gaitframe = pstudio->lerp->gaitframe - (int)(pstudio->lerp->gaitframe / pseqdesc->numframes) * pseqdesc->numframes;
if( pstudio->lerp->gaitframe < 0 ) pstudio->lerp->gaitframe += pseqdesc->numframes;
pstudio->lerp->curstate.gaitframe = pstudio->lerp->curstate.gaitframe - (int)(pstudio->lerp->curstate.gaitframe / pseqdesc->numframes) * pseqdesc->numframes;
if( pstudio->lerp->curstate.gaitframe < 0 ) pstudio->lerp->curstate.gaitframe += pseqdesc->numframes;
}
static bool R_StudioSetupModel( ref_entity_t *e, ref_model_t *mod )