From c48cdf25e0920fd8bd5b73bd42f8b13f22bfff20 Mon Sep 17 00:00:00 2001 From: g-cont Date: Fri, 19 Mar 2010 00:00:00 +0300 Subject: [PATCH] 19 Mar 2010 --- client/global/cl_tent.cpp | 6 +- client/global/dll_int.cpp | 7 + client/global/ev_hldm.cpp | 2 +- client/global/r_tempents.cpp | 2 +- client/global/view.cpp | 2 +- server/ents/basefunc.cpp | 5 + server/global/client.cpp | 7 + server/global/utils.cpp | 6 +- spirit/animation.cpp | 7 - spirit/basemonster.h | 5 +- spirit/bmodels.cpp | 41 +--- spirit/effects.cpp | 98 ++------- spirit/ggrenade.cpp | 2 +- spirit/handgrenade.cpp | 1 + spirit/locus.cpp | 176 ++-------------- spirit/locus.h | 3 +- spirit/monsters.cpp | 43 +++- spirit/monsters.h | 376 +++++++++++++++++------------------ spirit/player.cpp | 44 +++- spirit/player.h | 19 +- spirit/scripted.cpp | 233 +++++++++++++++------- spirit/scripted.h | 30 ++- spirit/sound.cpp | 2 +- spirit/tentacle.cpp | 3 +- spirit/util.cpp | 40 ++++ spirit/util.h | 5 + spirit/world.cpp | 6 +- todo.log | 2 +- vid_gl/r_backend.h | 6 + vid_gl/r_draw.c | 13 +- vid_gl/r_main.c | 3 - vid_gl/r_mesh.c | 26 +++ vid_gl/r_opengl.h | 9 + vid_gl/r_register.c | 3 + vid_gl/r_shader.c | 26 ++- 35 files changed, 659 insertions(+), 600 deletions(-) diff --git a/client/global/cl_tent.cpp b/client/global/cl_tent.cpp index 16342661..c41febef 100644 --- a/client/global/cl_tent.cpp +++ b/client/global/cl_tent.cpp @@ -165,7 +165,7 @@ void TE_ParseExplosion( void ) char szDecal[32]; sprintf( szDecal, "{scorch%i", RANDOM_LONG( 1, 3 )); - g_pTempEnts->PlaceDecal( pos2, scale * 24, szDecal ); + g_pTempEnts->PlaceDecal( pos2, 48.0f, szDecal ); if( !( flags & TE_EXPLFLAG_NOSOUND )) { @@ -406,7 +406,7 @@ void TE_ParseBSPDecal( void ) } pEntity = GetEntityByIndex( entityIndex ); - g_pTempEnts->PlaceDecal( pos, 5.0f, decalIndex ); + g_pTempEnts->PlaceDecal( pos, 2.0f, decalIndex ); } /* @@ -768,7 +768,7 @@ void TE_ParseDecal( int type ) if( type == TE_DECALHIGH || type == TE_WORLDDECALHIGH ) decalIndex += 256; - g_pTempEnts->PlaceDecal( pos, 5.0f, decalIndex ); + g_pTempEnts->PlaceDecal( pos, 2.0f, decalIndex ); } /* diff --git a/client/global/dll_int.cpp b/client/global/dll_int.cpp index 77338a26..be897c50 100644 --- a/client/global/dll_int.cpp +++ b/client/global/dll_int.cpp @@ -197,6 +197,13 @@ void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const enti m_fLerp = 1.0f; else m_fLerp = GetLerpFrac(); + if( state->flags & FL_PROJECTILE && state->ed_flags & ( ESF_NO_PREDICTION|ESF_NODELTA )) + { + // cut rocket trail, dont pass it from teleport + // FIXME: don't work + g_pViewRenderBeams->KillDeadBeams( ent ); + } + // copy state to progs ent->v.modelindex = state->modelindex; ent->v.weaponmodel = state->weaponmodel; diff --git a/client/global/ev_hldm.cpp b/client/global/ev_hldm.cpp index cb32e2fc..0b3c8ca8 100644 --- a/client/global/ev_hldm.cpp +++ b/client/global/ev_hldm.cpp @@ -269,7 +269,7 @@ void EV_HLDM_CrowbarDecalTrace( TraceResult *pTrace, char *decalName ) // only decal brush models such as the world etc. if( decalName && decalName[0] && pEnt && ( pEnt->v.solid == SOLID_BSP || pEnt->v.movetype == MOVETYPE_PUSHSTEP ) ) { - g_pTempEnts->PlaceDecal( pTrace->vecEndPos, 5.0f, decalName ); + g_pTempEnts->PlaceDecal( pTrace->vecEndPos, 2.0f, decalName ); } } diff --git a/client/global/r_tempents.cpp b/client/global/r_tempents.cpp index 79e9c0a4..fae55023 100644 --- a/client/global/r_tempents.cpp +++ b/client/global/r_tempents.cpp @@ -1063,7 +1063,7 @@ void CTempEnts::MuzzleFlash( edict_t *pEnt, int iAttachment, int type ) pTemp->renderMode = kRenderTransAdd; pTemp->renderAmt = 255; pTemp->renderFX = 0; - pTemp->die = gpGlobals->time + 0.01; // die at next frame + pTemp->die = gpGlobals->time + 0.015; // die at next frame pTemp->m_flFrame = RANDOM_LONG( 0, frameCount - 1 ); pTemp->m_flFrameMax = frameCount - 1; pTemp->clientIndex = pEnt->serialnumber; diff --git a/client/global/view.cpp b/client/global/view.cpp index 22c44d35..7615fa1f 100644 --- a/client/global/view.cpp +++ b/client/global/view.cpp @@ -306,7 +306,7 @@ void V_PreRender( ref_params_t *pparams ) //========================== void V_CalcGlobalFog( ref_params_t *pparams ) { - int bOn = (pparams->waterlevel < 2) && (gHUD.m_flStartDist > 0) && (gHUD.m_flEndDist > 0); + int bOn = (pparams->waterlevel < 2) && (gHUD.m_flStartDist > 0) && (gHUD.m_flEndDist > 0 && gHUD.m_flStartDist); g_engfuncs.pTriAPI->Fog( gHUD.m_vecFogColor, gHUD.m_flStartDist, gHUD.m_flEndDist, bOn ); } diff --git a/server/ents/basefunc.cpp b/server/ents/basefunc.cpp index b108eda8..f67aaa64 100644 --- a/server/ents/basefunc.cpp +++ b/server/ents/basefunc.cpp @@ -718,6 +718,11 @@ void CFuncTeleport :: Touch( CBaseEntity *pOther ) { Vector vecOriginOffs = pTarget->pev->origin - pLandmark->pev->origin; + if( pOther->pev->flags & FL_PROJECTILE ) + { + pOther->pev->angles = UTIL_VecToAngles( pOther->pev->velocity ); + } + // do we need to rotate the entity? if ( pLandmark->pev->angles != pTarget->pev->angles ) { diff --git a/server/global/client.cpp b/server/global/client.cpp index b1adb0d9..5fcb3b81 100644 --- a/server/global/client.cpp +++ b/server/global/client.cpp @@ -1518,6 +1518,13 @@ int AddToFullPack( edict_t *pView, edict_t *pHost, edict_t *pEdict, int hostflag default: return 0; // skipped } + if( bIsPortalPass && (pEdict->v.flags & FL_PROJECTILE) && pEdict->v.teleport_time ) + { + // HACKHACK - add grenades, rockets and other things that passed teleport into portal PVS + // as potentially visible. This is only for single frame. + return 1; + } + if( !ENGINE_CHECK_AREA( pEdict, hostarea )) { // blocked by a door diff --git a/server/global/utils.cpp b/server/global/utils.cpp index e5b95bb8..2171d8ef 100644 --- a/server/global/utils.cpp +++ b/server/global/utils.cpp @@ -2317,10 +2317,10 @@ void UTIL_SetFogAll( Vector color, int iFadeTime, int iStartDist, int iEndDist ) { // loop through all players - if(IsMultiplayer()) + if( IsMultiplayer( )) { - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - UTIL_SetFog( color, iFadeTime, iStartDist, iEndDist, i ); + for ( int i = 0; i < gpGlobals->maxClients; i++ ) + UTIL_SetFog( color, iFadeTime, iStartDist, iEndDist, i+1 ); } else UTIL_SetFog( color, iFadeTime, iStartDist, iEndDist ); } diff --git a/spirit/animation.cpp b/spirit/animation.cpp index b589ca44..245395b3 100644 --- a/spirit/animation.cpp +++ b/spirit/animation.cpp @@ -16,13 +16,6 @@ #include #include - -#pragma warning( disable : 4244 ) - -// hack into header files that we can ship -typedef int qboolean; -typedef unsigned char byte; -//#include "../utils/common/mathlib.h" #include "extdll.h" #include "const.h" #include "studio_ref.h" diff --git a/spirit/basemonster.h b/spirit/basemonster.h index ee0c644a..babab73c 100644 --- a/spirit/basemonster.h +++ b/spirit/basemonster.h @@ -193,8 +193,9 @@ public: virtual Schedule_t *GetScheduleOfType( int Type ); virtual Schedule_t *GetSchedule( void ); virtual void ScheduleChange( void ) {} - virtual int CanPlaySequence( void ) { return ((m_pCine == NULL) && (m_MonsterState == MONSTERSTATE_NONE || m_MonsterState == MONSTERSTATE_IDLE || m_IdealMonsterState == MONSTERSTATE_IDLE)); } - virtual int CanPlaySequence( BOOL fDisregardState, int interruptLevel ); +// virtual int CanPlaySequence( void ) { return ((m_pCine == NULL) && (m_MonsterState == MONSTERSTATE_NONE || m_MonsterState == MONSTERSTATE_IDLE || m_IdealMonsterState == MONSTERSTATE_IDLE)); } + virtual int CanPlaySequence( int interruptFlags ); +// virtual int CanPlaySequence( BOOL fDisregardState, int interruptLevel ); virtual int CanPlaySentence( BOOL fDisregardState ) { return IsAlive(); } virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ); virtual void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ); diff --git a/spirit/bmodels.cpp b/spirit/bmodels.cpp index 7c5ded45..c97909ed 100644 --- a/spirit/bmodels.cpp +++ b/spirit/bmodels.cpp @@ -52,13 +52,10 @@ Vector VecBModelOrigin( entvars_t* pevBModel ) /*QUAKED func_wall (0 .5 .8) ? This is just a solid wall if not inhibited */ -#define SF_FUNCWALL_ROTATE 1 - class CFuncWall : public CBaseEntity { public: void Spawn( void ); - //void PostSpawn(void); //AJH void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); virtual STATE GetState( void ) { return pev->frame?STATE_ON:STATE_OFF; }; @@ -73,26 +70,14 @@ LINK_ENTITY_TO_CLASS( func_wall, CFuncWall ); void CFuncWall :: Spawn( void ) { - - // If it can't move/go away, it's really part of the world - if (!m_pMoveWith) //LRC - pev->flags |= FL_WORLDBRUSH; - - pev->angles = g_vecZero; - -/* if (pev->spawnflags & SF_FUNCWALL_ROTATE){ //AJH - Now we can rotate complex stuff on spawn - Doesn't work!!! - ALERT(at_debug,"DEBUG: Rotate flag set, rotating brush in 0.1seconds\n"); - pev->flags &= !FL_WORLDBRUSH; - SetThink(&CFuncWall::PostSpawn); - SetNextThink(0.1); - - } -*/ + pev->angles = g_vecZero; pev->movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything pev->solid = SOLID_BSP; SET_MODEL( ENT(pev), STRING(pev->model) ); - + // If it can't move/go away, it's really part of the world + if (!m_pMoveWith) //LRC + pev->flags |= FL_WORLDBRUSH; //LRC if (m_iStyle >= 32) LIGHT_STYLE(m_iStyle, "a"); @@ -100,17 +85,6 @@ void CFuncWall :: Spawn( void ) } -/* -void CFuncWall :: PostSpawn (){ //AJH - Bug, this doesn't work, I have no idea why. - ALERT(at_debug,"DEBUG: Rotating from %f %f %f ", pev->angles.x,pev->angles.y,pev->angles.z); - //UTIL_AssignAngles(this,pev->vuser1); - pev->angles = pev->vuser1; - ALERT(at_debug,"to %f %f %f\n",pev->angles.x,pev->angles.y,pev->angles.z); - ALERT(at_debug,"String vuser1 = %s\n",pev->vuser1); - DontThink(); -} -*/ - void CFuncWall :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { if ( ShouldToggle( useType, (int)(pev->frame)) ) @@ -558,11 +532,6 @@ void CFuncRotating :: Spawn( ) UTIL_SetOrigin(this, pev->origin); SET_MODEL( ENT(pev), STRING(pev->model) ); - if(pev->origin == g_vecZero)//G-Cont. Set custom orirgin. Don't right work :( - { - UTIL_SetOrigin(this, VecBModelOrigin(pev)); - ALERT(at_console, "DEBUG: Using custom origin: Rotate object coordinates is %f %f %f \n", pev->origin.x, pev->origin.y, pev->origin.z); - } SetUse(&CFuncRotating :: RotatingUse ); // did level designer forget to assign speed? if (pev->speed <= 0) @@ -681,7 +650,7 @@ void CFuncRotating :: HurtTouch ( CBaseEntity *pOther ) // pev->dmg = pev->avelocity.Length() / 10; if (m_hActivator) - pOther->TakeDamage( pev, m_hActivator->pev, pev->dmg, DMG_CRUSH ); //AJH Attribute damage to he who switched me. + pOther->TakeDamage( pev, m_hActivator->pev, pev->dmg, DMG_CRUSH ); else pOther->TakeDamage( pev, pev, pev->dmg, DMG_CRUSH ); diff --git a/spirit/effects.cpp b/spirit/effects.cpp index 282a33f4..6325a3bd 100644 --- a/spirit/effects.cpp +++ b/spirit/effects.cpp @@ -1302,14 +1302,13 @@ void CLaser::TurnOn( void ) void CLaser::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { int active = (GetState() == STATE_ON); + if ( !ShouldToggle( useType, active ) ) return; if ( active ) TurnOff(); - else { - m_hActivator = pActivator; //AJH Storage variable to allow *locus start/end positions + else TurnOn(); - } } @@ -1335,9 +1334,6 @@ void CLaser::FireAtPoint( Vector startpos, TraceResult &tr ) BeamDamage( &tr ); DoSparks( startpos, tr.vecEndPos ); SetEndPos( tr.vecEndPos ); - if ( m_pStartSprite ) - UTIL_SetOrigin( m_pStartSprite, tr.vecEndPos ); - BeamDamage( &tr ); DoSparks( GetStartPos(), tr.vecEndPos ); } @@ -1347,18 +1343,18 @@ void CLaser::StrikeThink( void ) Vector startpos = pev->origin; if (m_iszStartPosition) { - startpos = CalcLocus_Position(this, m_hActivator, STRING(m_iszStartPosition)); //AJH allow *locus start/end positions + startpos = CalcLocus_Position(this, NULL, STRING(m_iszStartPosition)); } if (m_iTowardsMode) { - m_firePosition = startpos + CalcLocus_Velocity(this, m_hActivator, STRING(pev->message)); //AJH allow *locus start/end positions + m_firePosition = startpos + CalcLocus_Velocity(this, NULL, STRING(pev->message)); } else { CBaseEntity *pEnd = RandomTargetname( STRING(pev->message) ); - if ( pEnd ) m_firePosition = CalcLocus_Position(this,pEnd,STRING(pev->message)); + if ( pEnd ) m_firePosition = pEnd->pev->origin; } TraceResult tr; @@ -2617,14 +2613,7 @@ void CBlood::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useTyp UTIL_TraceLine( start, start + forward * BloodAmount() * 2, ignore_monsters, NULL, &tr ); if ( tr.flFraction != 1.0 ) - { - int blood; - if(Color() == BLOOD_COLOR_RED)blood = 1; - else if(Color() == BLOOD_COLOR_YELLOW)blood = 2; - CBaseEntity *pHit = CBaseEntity::Instance( tr.pHit ); - PLAYBACK_EVENT_FULL( FEV_RELIABLE|FEV_GLOBAL, edict(), m_usDecals, 0.0, (float *)&tr.vecEndPos, (float *)&g_vecZero, 0.0, 0.0, pHit->entindex(), blood, 0, 0 ); - //UTIL_BloodDecalTrace( &tr, Color() ); - } + UTIL_BloodDecalTrace( &tr, Color() ); } } @@ -3343,7 +3332,6 @@ void CEnvFootsteps::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE #define EXTENT_ARCING 2 #define EXTENT_OBSTRUCTED_REVERSE 3 #define EXTENT_ARCING_REVERSE 4 -#define EXTENT_ARCING_THROUGH 5 //AJH class CEnvRain : public CBaseEntity { @@ -3505,8 +3493,8 @@ void CEnvRain::Spawn( void ) if (m_pitch) pev->angles.x = m_pitch; -// else if (pev->angles.x == 0) // don't allow horizontal rain. //AJH -Why not? -// pev->angles.x = 90; + else if (pev->angles.x == 0) // don't allow horizontal rain. + pev->angles.x = 90; if (m_burstSize == 0) // in case the level designer forgot to set it. m_burstSize = 2; @@ -3587,10 +3575,6 @@ void CEnvRain::Think( void ) if (tr.flFraction == 1.0) bDraw = FALSE; vecDest = tr.vecEndPos; break; - case EXTENT_ARCING_THROUGH: //AJH - Arcs full length of brush only when blocked - UTIL_TraceLine( vecDest, vecSrc, dont_ignore_monsters, NULL, &tr); - if (tr.flFraction == 1.0) bDraw = FALSE; - break; case EXTENT_ARCING_REVERSE: UTIL_TraceLine( vecDest, vecSrc, ignore_monsters, NULL, &tr); if (tr.flFraction == 1.0) bDraw = FALSE; @@ -4289,6 +4273,7 @@ void CItemSoda::CanTouch ( CBaseEntity *pOther ) //========================================================= // LRC - env_fog, extended a bit from the DMC version +// g-cont - fix save\load issues, add multiplayer support //========================================================= #define SF_FOG_ACTIVE 1 #define SF_FOG_FADING 0x8000 @@ -4297,14 +4282,10 @@ class CEnvFog : public CBaseEntity { public: void Spawn( void ); - void Precache( void ); - void EXPORT ResumeThink( void ); - void EXPORT Resume2Think( void ); void EXPORT TurnOn( void ); void EXPORT TurnOff( void ); void EXPORT FadeInDone( void ); void EXPORT FadeOutDone( void ); - void SendData( Vector col, int fFadeTime, int StartDist, int iEndDist); void KeyValue( KeyValueData *pkvd ); virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); @@ -4395,22 +4376,10 @@ void CEnvFog :: Spawn ( void ) UTIL_DesiredThink( this ); } -// Precache is now used only to continue after a game has loaded. -// Precache(); - // things get messed up if we try to draw fog with a startdist // or an enddist of 0, so we don't allow it. if (m_iStartDist == 0) m_iStartDist = 1; - if (m_iEndDist == 0) m_iEndDist = 1; -} - -void CEnvFog :: Precache ( void ) -{ - if (pev->spawnflags & SF_FOG_ACTIVE) - { - SetThink(&CEnvFog :: ResumeThink ); - SetNextThink( 0.1 ); - } + if (m_iEndDist == 0) m_iEndDist = 1000; } extern int gmsgSetFog; @@ -4421,17 +4390,17 @@ void CEnvFog :: TurnOn ( void ) pev->spawnflags |= SF_FOG_ACTIVE; + UTIL_SetFogAll( pev->rendercolor, m_iFadeIn, m_iStartDist, m_iEndDist ); + if( m_iFadeIn ) { pev->spawnflags |= SF_FOG_FADING; - SendData( pev->rendercolor, m_iFadeIn, m_iStartDist, m_iEndDist); SetNextThink( m_iFadeIn ); SetThink(&CEnvFog :: FadeInDone ); } else { pev->spawnflags &= ~SF_FOG_FADING; - SendData( pev->rendercolor, 0, m_iStartDist, m_iEndDist); if (m_fHoldTime) { SetNextThink( m_fHoldTime ); @@ -4446,36 +4415,24 @@ void CEnvFog :: TurnOff ( void ) pev->spawnflags &= ~SF_FOG_ACTIVE; + UTIL_SetFogAll( pev->rendercolor, -m_iFadeOut, m_iStartDist, m_iEndDist ); + if( m_iFadeOut ) { pev->spawnflags |= SF_FOG_FADING; - SendData( pev->rendercolor, -m_iFadeOut, m_iStartDist, m_iEndDist); SetNextThink( m_iFadeOut ); SetThink(&CEnvFog :: FadeOutDone ); } else { pev->spawnflags &= ~SF_FOG_FADING; - SendData( g_vecZero, 0, 0, 0 ); DontThink(); } } -//yes, this intermediate think function is necessary. -// the engine seems to ignore the nextthink time when starting up. -// So this function gets called immediately after the precache finishes, -// regardless of what nextthink time is specified. -void CEnvFog :: ResumeThink ( void ) -{ -// ALERT(at_console, "Fog resume %f\n", gpGlobals->time); - SetThink(&CEnvFog ::FadeInDone); - SetNextThink(0.1); -} - void CEnvFog :: FadeInDone ( void ) { pev->spawnflags &= ~SF_FOG_FADING; - SendData( pev->rendercolor, 0, m_iStartDist, m_iEndDist); if (m_fHoldTime) { @@ -4487,7 +4444,6 @@ void CEnvFog :: FadeInDone ( void ) void CEnvFog :: FadeOutDone ( void ) { pev->spawnflags &= ~SF_FOG_FADING; - SendData( g_vecZero, 0, 0, 0); } void CEnvFog :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) @@ -4501,32 +4457,6 @@ void CEnvFog :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE use TurnOn(); } } - -void CEnvFog :: SendData ( Vector col, int iFadeTime, int iStartDist, int iEndDist ) -{ -// ALERT(at_console, "Fog send (%d %d %d), %d - %d\n", col.x, col.y, col.z, iStartDist, iEndDist); - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = (CBasePlayer*)UTIL_PlayerByIndex( i ); - if ( pPlayer ) - { - MESSAGE_BEGIN( MSG_ONE, gmsgSetFog, NULL, pPlayer->pev ); - WRITE_BYTE ( col.x ); - WRITE_BYTE ( col.y ); - WRITE_BYTE ( col.z ); - WRITE_SHORT ( iFadeTime ); - WRITE_SHORT ( iStartDist ); - WRITE_SHORT ( iEndDist ); - MESSAGE_END(); - -// pPlayer->m_iFogStartDist = iStartDist; -// pPlayer->m_iFogEndDist = iEndDist; -// pPlayer->m_vecFogColor = col; -// pPlayer->m_bClientFogRefresh = FALSE; - } - } -} - LINK_ENTITY_TO_CLASS( env_fog, CEnvFog ); //========================================================= diff --git a/spirit/ggrenade.cpp b/spirit/ggrenade.cpp index 35535a7d..224c7436 100644 --- a/spirit/ggrenade.cpp +++ b/spirit/ggrenade.cpp @@ -412,7 +412,7 @@ CGrenade * CGrenade:: ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector v pGrenade->pev->gravity = 0.5; pGrenade->pev->friction = 0.8; - SET_MODEL(ENT(pGrenade->pev), "models/w_grenade.mdl"); + SET_MODEL(ENT(pGrenade->pev), "models/hgrenade.mdl"); pGrenade->pev->dmg = 100; return pGrenade; diff --git a/spirit/handgrenade.cpp b/spirit/handgrenade.cpp index d61369b3..2c720913 100644 --- a/spirit/handgrenade.cpp +++ b/spirit/handgrenade.cpp @@ -68,6 +68,7 @@ void CHandGrenade::Precache( void ) PRECACHE_MODEL("models/w_grenade.mdl"); PRECACHE_MODEL("models/v_grenade.mdl"); PRECACHE_MODEL("models/p_grenade.mdl"); + PRECACHE_MODEL("models/hgrenade.mdl"); // physic model. Xash3D requires it } int CHandGrenade::GetItemInfo(ItemInfo *p) diff --git a/spirit/locus.cpp b/spirit/locus.cpp index b2f3014c..70340939 100644 --- a/spirit/locus.cpp +++ b/spirit/locus.cpp @@ -52,7 +52,7 @@ Vector CalcLocus_Velocity( CBaseEntity *pEntity, CBaseEntity *pLocus, const char return g_vecZero; } -float CalcLocus_Ratio( CBaseEntity *pLocus, const char *szText ,int mode) //AJH added 'mode' = ratio to return +float CalcLocus_Ratio( CBaseEntity *pLocus, const char *szText ) { if ((*szText >= '0' && *szText <= '9') || *szText == '-') { // assume it's a float @@ -60,19 +60,12 @@ float CalcLocus_Ratio( CBaseEntity *pLocus, const char *szText ,int mode) //AJH } CBaseEntity *pCalc = UTIL_FindEntityByTargetname(NULL, szText, pLocus); - - if (pCalc != NULL){ - //ALERT(at_debug,"Entity \"%s\" found, calling CalcRatio, mode %i.\n",szText,mode); - return pCalc->CalcRatio( pLocus ); - }else{ - ALERT(at_aiconsole, "Bad or missing calc_ratio entity \"%s\", mode %i\n", szText,mode); // MJB/AJH - might need to be supressed; this error is often returned when there is no error - return 0; // we need some signal for "fail". NaN, maybe? - } -} -float CalcLocus_Ratio( CBaseEntity *pLocus, const char *szText) //AJH calls new CalcLocusRatio -{ - return CalcLocus_Ratio(pLocus,szText,0); + if (pCalc != NULL) + return pCalc->CalcRatio( pLocus ); + + ALERT(at_error, "Bad or missing calc_ratio entity \"%s\"\n", szText); + return 0; // we need some signal for "fail". NaN, maybe? } //============================================= @@ -417,15 +410,15 @@ Vector CCalcPosition::CalcPosition( CBaseEntity *pLocus ) class CCalcRatio : public CPointEntity { public: - float CalcRatio( CBaseEntity *pLocus, int mode ); + float CalcRatio( CBaseEntity *pLocus ); }; LINK_ENTITY_TO_CLASS( calc_ratio, CCalcRatio ); - float CCalcRatio::CalcRatio( CBaseEntity *pLocus, int mode) //AJH 'mode' (ratio to return is overridden) +float CCalcRatio::CalcRatio( CBaseEntity *pLocus ) { - //ALERT(at_debug,"Calc_ratio 'ratio_to_return' is %i\n",pev->skin); - float fBasis = CalcLocus_Ratio( pLocus, STRING(pev->target),pev->skin); //AJH pev->skin is 'ratio to return' + float fBasis = CalcLocus_Ratio( pLocus, STRING(pev->target)); + switch (pev->impulse) { case 1: fBasis = 1-fBasis; break; //reversed @@ -433,8 +426,8 @@ LINK_ENTITY_TO_CLASS( calc_ratio, CCalcRatio ); case 3: fBasis = 1/fBasis; break; //reciprocal } - fBasis += CalcLocus_Ratio( pLocus, STRING(pev->netname),pev->body); //AJH pev->body is 'ratio to return' - fBasis = fBasis * CalcLocus_Ratio( pLocus, STRING(pev->message),pev->button);//AJH pev->iuser3 is 'ratio to return' + fBasis += CalcLocus_Ratio( pLocus, STRING(pev->netname)); + fBasis = fBasis * CalcLocus_Ratio( pLocus, STRING(pev->message)); if (!FStringNull(pev->noise)) { @@ -488,98 +481,10 @@ LINK_ENTITY_TO_CLASS( calc_ratio, CCalcRatio ); else return fBasis; } - - -/*// calc_angletransform by MJB. -#define SF_ANGLETRANS_DEBUG 1 // MJB - debug info -class CCalcAngleTransform : public CPointEntity { - public: - Vector CalcVelocity( CBaseEntity *pLocus ); -}; - -LINK_ENTITY_TO_CLASS( calc_angletransform, CCalcAngleTransform ); - -Vector CCalcAngleTransform::CalcVelocity( CBaseEntity *pLocus ) { - - Vector vecBasis1 = CalcLocus_Velocity( this, pLocus, STRING(pev->netname)); // netname: input 1 velocity - if (pev->modelindex != 0) { // modelindex: is 0 - Y Z X - vecBasis1 = UTIL_VecToAngles( vecBasis1 ); // is 1 - [LV] - if(pev->spawnflags & SF_ANGLETRANS_DEBUG) - ALERT(at_debug,"VecToAngles(vecBasis1)\n"); // WOOT! Gotcha lil' bastard! You'll never deceive me again. - } - - float basis1; - switch(pev->skin) { // skin: input 1 axis - case 0:basis1=vecBasis1.x;break; - case 1:basis1=vecBasis1.y;break; - case 2:basis1=vecBasis1.z;break; - default:ALERT(at_debug,"Invalid input-1 axis\n");break; - } - - Vector vecBasis2 = CalcLocus_Velocity( this, pLocus, STRING(pev->message)); // message: input 2 velocity - if (pev->button != 0) { // button: is 0 - Y Z X - vecBasis2 = UTIL_VecToAngles( vecBasis2 ); // is 1 - [LV] - if(pev->spawnflags & SF_ANGLETRANS_DEBUG) - ALERT(at_debug,"VecToAngles(vecBasis2)\n"); // WOOT! And the same to you! - } - - float basis2; - switch(pev->body) { // body: input 2 axis - case 0:basis2=vecBasis2.x;break; - case 1:basis2=vecBasis2.y;break; - case 2:basis2=vecBasis2.z;break; - default:ALERT(at_debug,"Invalid input-2 axis\n");break; - } - - float pi = 3.14159; - float transformation; - switch(pev->effects) { // effects: choose calculation - case 0:transformation=basis1;break; // output = basis1 - case 1:transformation=basis1+basis2;break; // add - case 2:transformation=basis1-basis2;break; // subtract - case 3:transformation=basis1*basis2;break; // multiply - case 4:transformation=basis1/basis2;break; // divide - case 5:transformation=basis1*sin(basis2*pi/180);break; // basis1 * sin(basis2) - case 6:transformation=basis1*cos(basis2*pi/180);break; // basis1 * cos(basis2) - case 7:transformation=basis1*tan(basis2*pi/180);break; // basis1 * tan(basis2) - case 8:transformation=basis1*(transformation=sin(basis2*pi/180))*transformation;break; // basis1 * sinē(basis2) - case 9:transformation=basis1*(transformation=cos(basis2*pi/180))*transformation;break; // basis1 * cosē(basis2) - case 10:transformation=basis1*(transformation=tan(basis2*pi/180))*transformation;break; // basis1 * tanē(basis2) - default:ALERT(at_debug,"Invalid transformation\n");break; - } - - Vector vecOutput = Vector(0, 0, 0); // This is 'mister empty vector' to make sure that whatever targets this only inherits the desired axis. - switch(pev->impulse) { // impulse: choose output axis - case 0:vecOutput = Vector(transformation, 0, 0);break; - case 1:vecOutput = Vector(0, transformation, 0);break; - case 2:vecOutput = Vector(0, 0, transformation);break; - default:{ALERT(at_debug,"Invalid output axis\n");break;} - } - - if(pev->spawnflags & SF_ANGLETRANS_DEBUG) - ALERT(at_debug,"Input-1 = %f, Input-2 = %f, Transformation = %f, Result = %f %f %f\n", basis1,basis2,transformation,vecOutput.x,vecOutput.y,vecOutput.z); - // OK - our work here is done. Now spit it out (makevectors vecoutput??)!! - UTIL_MakeVectors( vecOutput ); - return (gpGlobals->v_forward); - -// MJB There are two problems with this entity, which is why its commented out: -// Problem 1) Whenever it is used, all world surfaces are duplicated and the whole (duplicated) map's corner is positioned where you put the entity(s) -// Problem 2) When targeting this with a motion_manager, the 'roll' value appears to be completely ignored - no idea if the problem lies in the motion_manager or in here. - - -}*/ - - //======================================================= #define SF_CALCVELOCITY_NORMALIZE 1 -#define SF_CALCVELOCITY_SWAPZ 2 // MJB this should more correctly be called 'invertZ', but never mind. -#define SF_CALCVELOCITY_SWAPXY 4 // MJB axis swapping (pitch and yaw) -#define SF_CALCVELOCITY_SWAPYZ 8 // MJB axis swapping (yaw and roll) -#define SF_CALCVELOCITY_SWAPXZ 16 // MJB axis swapping (pitch and roll) -#define SF_CALCVELOCITY_DEBUGSWAP 32 // So what the hell is the swapping DOING? - - +#define SF_CALCVELOCITY_SWAPZ 2 class CCalcSubVelocity : public CPointEntity { Vector Convert( CBaseEntity *pLocus, Vector vecVel ); @@ -601,7 +506,7 @@ Vector CCalcSubVelocity::CalcVelocity( CBaseEntity *pLocus ) { case 1: //angles return ConvertAngles( pLocus, pLocus->pev->angles ); - case 2: //viewangles + case 2: //v_angle return ConvertAngles( pLocus, pLocus->pev->viewangles ); case 5: // this could cause problems. @@ -645,7 +550,6 @@ Vector CCalcSubVelocity::ConvertAngles( CBaseEntity *pLocus, Vector vecAngles ) } - //======================================================= class CCalcVelocityPath : public CPointEntity { @@ -737,57 +641,13 @@ Vector CCalcVelocityPolar::CalcVelocity( CBaseEntity *pLocus ) Vector vecBasis = CalcLocus_Velocity( this, pLocus, STRING(pev->netname) ); Vector vecAngles = UTIL_VecToAngles( vecBasis ) + pev->angles; Vector vecOffset = CalcLocus_Velocity( this, pLocus, STRING(pev->message) ); + float fFactor = CalcLocus_Ratio( pLocus, STRING(pev->noise) ); if (!(pev->spawnflags & SF_CALCVELOCITY_NORMALIZE)) fFactor = fFactor * vecBasis.Length(); - - /*float tempswap; - - // MJB I've tried adding this code so I can swap the vector components, - // but for some reason it just isn't working. I have no idea why. - // Perhaps YOU know why and could fix it? - - if(pev->spawnflags & SF_CALCVELOCITY_SWAPXY) { // MJB axis swapping - X and Y - tempswap = vecAngles.y; - vecAngles.y = vecAngles.x; - vecAngles.x = tempswap; - if(pev->spawnflags & SF_CALCVELOCITY_DEBUGSWAP) - ALERT(at_debug,"Swapping Pitch = %f, Yaw = %f, Temporary = %f\n", vecAngles.x,vecAngles.y,tempswap); - } - - if(pev->spawnflags & SF_CALCVELOCITY_SWAPYZ) { // MJB axis swapping - Y and Z - tempswap = vecAngles.z; - vecAngles.z = vecAngles.y; - vecAngles.y = tempswap; - if(pev->spawnflags & SF_CALCVELOCITY_DEBUGSWAP) - ALERT(at_debug,"Swapping Yaw = %f, Roll = %f, Temporary = %f\n", vecAngles.y,vecAngles.z,tempswap); - } - - if(pev->spawnflags & SF_CALCVELOCITY_SWAPXZ) { // MJB axis swapping - X and Z - tempswap = vecAngles.z; - vecAngles.z = vecAngles.x; - vecAngles.x = tempswap; - if(pev->spawnflags & SF_CALCVELOCITY_DEBUGSWAP) - ALERT(at_debug,"Swapping Pitch = %f, Roll = %f, Temporary = %f\n", vecAngles.x,vecAngles.z,tempswap); - } - - // MJB I've tried adding this code so I can swap the vector components, - // but for some reason it just isn't working. I have no idea why. - // Perhaps YOU know why and could fix it? - - */ - + UTIL_MakeVectors( vecAngles ); - - /* MJB - a vain attempt at debugging the nonbehaving code. - if(pev->spawnflags & SF_CALCVELOCITY_SWAPXY) // MJB axis swapping - X and Y - ALERT(at_debug,"** Swapping Pitch = %f, Yaw = %f, Temporary = %f\n", vecAngles.x,vecAngles.y,tempswap); - if(pev->spawnflags & SF_CALCVELOCITY_SWAPYZ) // MJB axis swapping - Y and Z - ALERT(at_debug,"** Swapping Yaw = %f, Roll = %f, Temporary = %f\n", vecAngles.y,vecAngles.z,tempswap); - if(pev->spawnflags & SF_CALCVELOCITY_SWAPXZ) // MJB axis swapping - X and Z - ALERT(at_debug,"** Swapping Pitch = %f, Roll = %f, Temporary = %f\n", vecAngles.x,vecAngles.z,tempswap); */ - return (gpGlobals->v_forward * fFactor) + vecOffset; } @@ -798,7 +658,7 @@ class CMark : public CPointEntity { public: Vector CalcVelocity(CBaseEntity *pLocus) { return pev->movedir; } - float CalcRatio(CBaseEntity *pLocus, int mode ) { return pev->frags; }//AJH added 'mode' = ratio to return + float CalcRatio(CBaseEntity *pLocus) { return pev->frags; } void Think( void ) { SUB_Remove(); } }; @@ -808,7 +668,7 @@ public: void Spawn( void ); void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); Vector CalcVelocity(CBaseEntity *pLocus) { return pev->movedir; } - float CalcRatio(CBaseEntity *pLocus, int mode ) { return pev->frags; }//AJH added 'mode' = ratio to return + float CalcRatio(CBaseEntity *pLocus) { return pev->frags; } void KeyValue( KeyValueData *pkvd ); virtual int Save( CSave &save ); diff --git a/spirit/locus.h b/spirit/locus.h index bc789cf2..a0df46f0 100644 --- a/spirit/locus.h +++ b/spirit/locus.h @@ -1,4 +1,3 @@ Vector CalcLocus_Position ( CBaseEntity *pEntity, CBaseEntity *pLocus, const char *szText ); Vector CalcLocus_Velocity ( CBaseEntity *pEntity, CBaseEntity *pLocus, const char *szText ); -float CalcLocus_Ratio ( CBaseEntity *pLocus, const char *szText); -float CalcLocus_Ratio ( CBaseEntity *pLocus, const char *szText,int mode ); //AJH added 'mode' = ratio to return \ No newline at end of file +float CalcLocus_Ratio ( CBaseEntity *pLocus, const char *szText); \ No newline at end of file diff --git a/spirit/monsters.cpp b/spirit/monsters.cpp index 6c214828..2816f7cb 100644 --- a/spirit/monsters.cpp +++ b/spirit/monsters.cpp @@ -1250,7 +1250,6 @@ void CBaseMonster :: SetActivity ( Activity NewActivity ) else { // Not available try to get default anim - // ZAEBALO!!!!! ALERT ( at_aiconsole, "%s has no sequence for act:%d\n", STRING(pev->classname), NewActivity ); pev->sequence = 0; // Set to the reset anim (if it's there) } @@ -3130,15 +3129,32 @@ BOOL CBaseMonster :: FCheckAITrigger ( void ) //LRC - to help debug when sequences won't play... #define DEBUG_CANTPLAY -int CBaseMonster :: CanPlaySequence( BOOL fDisregardState, int interruptLevel ) +int CBaseMonster :: CanPlaySequence( int interruptFlags ) { - if ( m_pCine || !IsAlive() || m_MonsterState == MONSTERSTATE_PRONE ) + if ( m_pCine ) { + if ( interruptFlags & SS_INTERRUPT_SCRIPTS ) + { + return true; + } + else + { +#ifdef DEBUG_CANTPLAY + ALERT(at_debug, "CANTPLAY: Already playing %s \"%s\"!\n", STRING(m_pCine->pev->classname), STRING(m_pCine->pev->targetname)); +#endif + return false; + } + } + else if ( !IsAlive() || m_MonsterState == MONSTERSTATE_PRONE ) + { +#ifdef DEBUG_CANTPLAY + ALERT(at_debug, "CANTPLAY: Dead/Barnacled!\n"); +#endif // monster is already running a scripted sequence or dead! return FALSE; } - if ( fDisregardState ) + if ( interruptFlags & SS_INTERRUPT_ANYSTATE ) { // ok to go, no matter what the monster state. (scripted AI) return TRUE; @@ -3150,10 +3166,13 @@ int CBaseMonster :: CanPlaySequence( BOOL fDisregardState, int interruptLevel ) return TRUE; } - if ( m_MonsterState == MONSTERSTATE_ALERT && interruptLevel >= SS_INTERRUPT_BY_NAME ) + if ( m_MonsterState == MONSTERSTATE_ALERT && interruptFlags & SS_INTERRUPT_ALERT ) return TRUE; // unknown situation +#ifdef DEBUG_CANTPLAY + ALERT(at_debug, "CANTPLAY: non-interruptable state.\n"); +#endif return FALSE; } @@ -3222,14 +3241,16 @@ BOOL CBaseMonster :: FindLateralCover ( const Vector &vecThreat, const Vector &v Vector CBaseMonster :: ShootAtEnemy( const Vector &shootOrigin ) { - CBaseEntity *pEnemy = m_hEnemy; - - if ( pEnemy ) + if (m_pCine != NULL && m_hTargetEnt != NULL && (m_pCine->m_fTurnType == 1)) { - return ( (pEnemy->BodyTarget( shootOrigin ) - pEnemy->pev->origin) + m_vecEnemyLKP - shootOrigin ).Normalize(); + Vector vecDest = ( m_hTargetEnt->pev->absmin + m_hTargetEnt->pev->absmax ) / 2; + return ( vecDest - shootOrigin ).Normalize(); } - else - return gpGlobals->v_forward; + else if ( m_hEnemy ) + { + return ( (m_hEnemy->BodyTarget( shootOrigin ) - m_hEnemy->pev->origin) + m_vecEnemyLKP - shootOrigin ).Normalize(); + } + else return gpGlobals->v_forward; } diff --git a/spirit/monsters.h b/spirit/monsters.h index dc44fbab..a672e368 100644 --- a/spirit/monsters.h +++ b/spirit/monsters.h @@ -1,189 +1,187 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* This source code contains proprietary and confidential information of -* Valve LLC and its suppliers. Access to this code is restricted to -* persons who have executed a written SDK license with Valve. Any access, -* use or distribution of this code by or to any unlicensed person is illegal. -* -****/ -#ifndef MONSTERS_H -#include "skill.h" -#define MONSTERS_H - -/* - -===== monsters.h ======================================================== - - Header file for monster-related utility code - -*/ - -// CHECKLOCALMOVE result types -#define LOCALMOVE_INVALID 0 // move is not possible -#define LOCALMOVE_INVALID_DONT_TRIANGULATE 1 // move is not possible, don't try to triangulate -#define LOCALMOVE_VALID 2 // move is possible - -// Hit Group standards -#define HITGROUP_GENERIC 0 -#define HITGROUP_HEAD 1 -#define HITGROUP_CHEST 2 -#define HITGROUP_STOMACH 3 -#define HITGROUP_LEFTARM 4 -#define HITGROUP_RIGHTARM 5 -#define HITGROUP_LEFTLEG 6 -#define HITGROUP_RIGHTLEG 7 - - -// Monster Spawnflags -#define SF_MONSTER_WAIT_TILL_SEEN 1// spawnflag that makes monsters wait until player can see them before attacking. -#define SF_MONSTER_GAG 2 // no idle noises from this monster -#define SF_MONSTER_HITMONSTERCLIP 4 -// 8 -#define SF_MONSTER_PRISONER 16 // monster won't attack anyone, no one will attacke him. -// 32 -// 64 -#define SF_MONSTER_NO_YELLOW_BLOBS 128 //LRC- if the monster is stuck, don't give errors or show yellow blobs. -//LRC- wasn't implemented. #define SF_MONSTER_WAIT_FOR_SCRIPT 128 //spawnflag that makes monsters wait to check for attacking until the script is done or they've been attacked -#define SF_MONSTER_PREDISASTER 256 //this is a predisaster scientist or barney. Influences how they speak. -#define SF_MONSTER_FADECORPSE 512 // Fade out corpse after death -#define SF_MONSTER_NO_WPN_DROP 1024 //LRC- never drop your weapon (player can't pick it up.) -//LRC - this clashes with 'not in deathmatch'. Replaced with m_iPlayerReact. -//#define SF_MONSTER_INVERT_PLAYERREACT 2048 //LRC- if this monster would usually attack the player, don't attack unless provoked. If you would usually NOT attack the player, attack him. -#define SF_MONSTER_FALL_TO_GROUND 0x80000000 - -// specialty spawnflags -#define SF_MONSTER_TURRET_AUTOACTIVATE 32 -#define SF_MONSTER_TURRET_STARTINACTIVE 64 -#define SF_MONSTER_WAIT_UNTIL_PROVOKED 64 // don't attack the player unless provoked - - - -// MoveToOrigin stuff -#define MOVE_START_TURN_DIST 64 // when this far away from moveGoal, start turning to face next goal -#define MOVE_STUCK_DIST 32 // if a monster can't step this far, it is stuck. - - -// MoveToOrigin stuff -#define MOVE_NORMAL 0// normal move in the direction monster is facing -#define MOVE_STRAFE 1// moves in direction specified, no matter which way monster is facing - -// spawn flags 256 and above are already taken by the engine -extern void UTIL_MoveToOrigin( edict_t* pent, const Vector &vecGoal, float flDist, int iMoveType ); - -Vector VecCheckToss ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flGravityAdj = 1.0 ); -Vector VecCheckThrow ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj = 1.0 ); -extern DLL_GLOBAL Vector g_vecAttackDir; -extern DLL_GLOBAL CONSTANT float g_flMeleeRange; -extern DLL_GLOBAL CONSTANT float g_flMediumRange; -extern DLL_GLOBAL CONSTANT float g_flLongRange; -extern void EjectBrass (const Vector &vecOrigin, const Vector &vecVelocity, float rotation, int model, int soundtype ); -extern void ExplodeModel( const Vector &vecOrigin, float speed, int model, int count ); - -BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget ); -BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget, Vector &vecTargetOrigin, float flSize = 0.0 ); - -// monster to monster relationship types -#define R_AL -2 // (ALLY) pals. Good alternative to R_NO when applicable. -#define R_FR -1// (FEAR)will run -#define R_NO 0// (NO RELATIONSHIP) disregard -#define R_DL 1// (DISLIKE) will attack -#define R_HT 2// (HATE)will attack this character instead of any visible DISLIKEd characters -#define R_NM 3// (NEMESIS) A monster Will ALWAYS attack its nemsis, no matter what - - -// these bits represent the monster's memory -#define MEMORY_CLEAR 0 -#define bits_MEMORY_PROVOKED ( 1 << 0 )// right now only used for houndeyes. -#define bits_MEMORY_INCOVER ( 1 << 1 )// monster knows it is in a covered position. -#define bits_MEMORY_SUSPICIOUS ( 1 << 2 )// Ally is suspicious of the player, and will move to provoked more easily -#define bits_MEMORY_PATH_FINISHED ( 1 << 3 )// Finished monster path (just used by big momma for now) -#define bits_MEMORY_ON_PATH ( 1 << 4 )// Moving on a path -#define bits_MEMORY_MOVE_FAILED ( 1 << 5 )// Movement has already failed -#define bits_MEMORY_FLINCHED ( 1 << 6 )// Has already flinched -#define bits_MEMORY_KILLED ( 1 << 7 )// HACKHACK -- remember that I've already called my Killed() -#define bits_MEMORY_CUSTOM4 ( 1 << 28 ) // Monster-specific memory -#define bits_MEMORY_CUSTOM3 ( 1 << 29 ) // Monster-specific memory -#define bits_MEMORY_CUSTOM2 ( 1 << 30 ) // Monster-specific memory -#define bits_MEMORY_CUSTOM1 ( 1 << 31 ) // Monster-specific memory - -// trigger conditions for scripted AI -// these MUST match the CHOICES interface in halflife.fgd for the base monster -enum -{ - AITRIGGER_NONE = 0, - AITRIGGER_SEEPLAYER_ANGRY_AT_PLAYER, - AITRIGGER_TAKEDAMAGE, - AITRIGGER_HALFHEALTH, - AITRIGGER_DEATH, - AITRIGGER_SQUADMEMBERDIE, - AITRIGGER_SQUADLEADERDIE, - AITRIGGER_HEARWORLD, - AITRIGGER_HEARPLAYER, - AITRIGGER_HEARCOMBAT, - AITRIGGER_SEEPLAYER_UNCONDITIONAL, - AITRIGGER_SEEPLAYER_NOT_IN_COMBAT, -}; -/* - 0 : "No Trigger" - 1 : "See Player" - 2 : "Take Damage" - 3 : "50% Health Remaining" - 4 : "Death" - 5 : "Squad Member Dead" - 6 : "Squad Leader Dead" - 7 : "Hear World" - 8 : "Hear Player" - 9 : "Hear Combat" -*/ - -// -// A gib is a chunk of a body, or a piece of wood/metal/rocks/etc. -// -class CGib : public CBaseEntity -{ -public: - void Spawn( const char *szGibModel ); - void EXPORT BounceGibTouch ( CBaseEntity *pOther ); - void EXPORT StickyGibTouch ( CBaseEntity *pOther ); - void EXPORT WaitTillLand( void ); - void LimitVelocity( void ); - - virtual int ObjectCaps( void ) { return (CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DONT_SAVE; } - static void SpawnHeadGib( entvars_t *pevVictim ); - static void SpawnHeadGib( entvars_t *pevVictim, const char *szGibModel ); - static void SpawnRandomGibs( entvars_t *pevVictim, int cGibs, int human ); - static void SpawnRandomGibs( entvars_t *pevVictim, int cGibs, int notfirst, const char *szGibModel ); //LRC - static void SpawnStickyGibs( entvars_t *pevVictim, Vector vecOrigin, int cGibs ); - - int m_bloodColor; - int m_cBloodDecals; - int m_material; - float m_lifeTime; -}; - - -#define CUSTOM_SCHEDULES\ - virtual Schedule_t *ScheduleFromName( const char *pName );\ - static Schedule_t *m_scheduleList[]; - -#define DEFINE_CUSTOM_SCHEDULES(derivedClass)\ - Schedule_t *derivedClass::m_scheduleList[] = - -#define IMPLEMENT_CUSTOM_SCHEDULES(derivedClass, baseClass)\ - Schedule_t *derivedClass::ScheduleFromName( const char *pName )\ - {\ - Schedule_t *pSchedule = ScheduleInList( pName, m_scheduleList, ARRAYSIZE(m_scheduleList) );\ - if ( !pSchedule )\ - return baseClass::ScheduleFromName(pName);\ - return pSchedule;\ - } - - - -#endif //MONSTERS_H +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* This source code contains proprietary and confidential information of +* Valve LLC and its suppliers. Access to this code is restricted to +* persons who have executed a written SDK license with Valve. Any access, +* use or distribution of this code by or to any unlicensed person is illegal. +* +****/ +#ifndef MONSTERS_H +#include "skill.h" +#define MONSTERS_H + +/* + +===== monsters.h ======================================================== + + Header file for monster-related utility code + +*/ + +// CHECKLOCALMOVE result types +#define LOCALMOVE_INVALID 0 // move is not possible +#define LOCALMOVE_INVALID_DONT_TRIANGULATE 1 // move is not possible, don't try to triangulate +#define LOCALMOVE_VALID 2 // move is possible + +// Hit Group standards +#define HITGROUP_GENERIC 0 +#define HITGROUP_HEAD 1 +#define HITGROUP_CHEST 2 +#define HITGROUP_STOMACH 3 +#define HITGROUP_LEFTARM 4 +#define HITGROUP_RIGHTARM 5 +#define HITGROUP_LEFTLEG 6 +#define HITGROUP_RIGHTLEG 7 + + +// Monster Spawnflags +#define SF_MONSTER_WAIT_TILL_SEEN 1// spawnflag that makes monsters wait until player can see them before attacking. +#define SF_MONSTER_GAG 2 // no idle noises from this monster +#define SF_MONSTER_HITMONSTERCLIP 4 +// 8 +#define SF_MONSTER_PRISONER 16 // monster won't attack anyone, no one will attacke him. +// 32 +// 64 +#define SF_MONSTER_NO_YELLOW_BLOBS 128 //LRC- if the monster is stuck, don't give errors or show yellow blobs. +//LRC- wasn't implemented. #define SF_MONSTER_WAIT_FOR_SCRIPT 128 //spawnflag that makes monsters wait to check for attacking until the script is done or they've been attacked +#define SF_MONSTER_PREDISASTER 256 //this is a predisaster scientist or barney. Influences how they speak. +#define SF_MONSTER_FADECORPSE 512 // Fade out corpse after death +#define SF_MONSTER_NO_WPN_DROP 1024 //LRC- never drop your weapon (player can't pick it up.) +//LRC - this clashes with 'not in deathmatch'. Replaced with m_iPlayerReact. +//#define SF_MONSTER_INVERT_PLAYERREACT 2048 //LRC- if this monster would usually attack the player, don't attack unless provoked. If you would usually NOT attack the player, attack him. +#define SF_MONSTER_FALL_TO_GROUND 0x80000000 + +// specialty spawnflags +#define SF_MONSTER_TURRET_AUTOACTIVATE 32 +#define SF_MONSTER_TURRET_STARTINACTIVE 64 +#define SF_MONSTER_WAIT_UNTIL_PROVOKED 64 // don't attack the player unless provoked + +// MoveToOrigin stuff +#define MOVE_START_TURN_DIST 64 // when this far away from moveGoal, start turning to face next goal +#define MOVE_STUCK_DIST 32 // if a monster can't step this far, it is stuck. + + +// MoveToOrigin stuff +#define MOVE_NORMAL 0// normal move in the direction monster is facing +#define MOVE_STRAFE 1// moves in direction specified, no matter which way monster is facing + +// spawn flags 256 and above are already taken by the engine +extern void UTIL_MoveToOrigin( edict_t* pent, const Vector &vecGoal, float flDist, int iMoveType ); + +Vector VecCheckToss ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flGravityAdj = 1.0 ); +Vector VecCheckThrow ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj = 1.0 ); +extern DLL_GLOBAL Vector g_vecAttackDir; +extern DLL_GLOBAL CONSTANT float g_flMeleeRange; +extern DLL_GLOBAL CONSTANT float g_flMediumRange; +extern DLL_GLOBAL CONSTANT float g_flLongRange; +extern void EjectBrass (const Vector &vecOrigin, const Vector &vecVelocity, float rotation, int model, int soundtype ); +extern void ExplodeModel( const Vector &vecOrigin, float speed, int model, int count ); + +BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget ); +BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget, Vector &vecTargetOrigin, float flSize = 0.0 ); + +// monster to monster relationship types +#define R_AL -2 // (ALLY) pals. Good alternative to R_NO when applicable. +#define R_FR -1// (FEAR)will run +#define R_NO 0// (NO RELATIONSHIP) disregard +#define R_DL 1// (DISLIKE) will attack +#define R_HT 2// (HATE)will attack this character instead of any visible DISLIKEd characters +#define R_NM 3// (NEMESIS) A monster Will ALWAYS attack its nemsis, no matter what + + +// these bits represent the monster's memory +#define MEMORY_CLEAR 0 +#define bits_MEMORY_PROVOKED ( 1 << 0 )// right now only used for houndeyes. +#define bits_MEMORY_INCOVER ( 1 << 1 )// monster knows it is in a covered position. +#define bits_MEMORY_SUSPICIOUS ( 1 << 2 )// Ally is suspicious of the player, and will move to provoked more easily +#define bits_MEMORY_PATH_FINISHED ( 1 << 3 )// Finished monster path (just used by big momma for now) +#define bits_MEMORY_ON_PATH ( 1 << 4 )// Moving on a path +#define bits_MEMORY_MOVE_FAILED ( 1 << 5 )// Movement has already failed +#define bits_MEMORY_FLINCHED ( 1 << 6 )// Has already flinched +#define bits_MEMORY_KILLED ( 1 << 7 )// HACKHACK -- remember that I've already called my Killed() +#define bits_MEMORY_CUSTOM4 ( 1 << 28 ) // Monster-specific memory +#define bits_MEMORY_CUSTOM3 ( 1 << 29 ) // Monster-specific memory +#define bits_MEMORY_CUSTOM2 ( 1 << 30 ) // Monster-specific memory +#define bits_MEMORY_CUSTOM1 ( 1 << 31 ) // Monster-specific memory + +// trigger conditions for scripted AI +// these MUST match the CHOICES interface in halflife.fgd for the base monster +enum +{ + AITRIGGER_NONE = 0, + AITRIGGER_SEEPLAYER_ANGRY_AT_PLAYER, + AITRIGGER_TAKEDAMAGE, + AITRIGGER_HALFHEALTH, + AITRIGGER_DEATH, + AITRIGGER_SQUADMEMBERDIE, + AITRIGGER_SQUADLEADERDIE, + AITRIGGER_HEARWORLD, + AITRIGGER_HEARPLAYER, + AITRIGGER_HEARCOMBAT, + AITRIGGER_SEEPLAYER_UNCONDITIONAL, + AITRIGGER_SEEPLAYER_NOT_IN_COMBAT, +}; +/* + 0 : "No Trigger" + 1 : "See Player" + 2 : "Take Damage" + 3 : "50% Health Remaining" + 4 : "Death" + 5 : "Squad Member Dead" + 6 : "Squad Leader Dead" + 7 : "Hear World" + 8 : "Hear Player" + 9 : "Hear Combat" +*/ + +// +// A gib is a chunk of a body, or a piece of wood/metal/rocks/etc. +// +class CGib : public CBaseEntity +{ +public: + void Spawn( const char *szGibModel ); + void EXPORT BounceGibTouch ( CBaseEntity *pOther ); + void EXPORT StickyGibTouch ( CBaseEntity *pOther ); + void EXPORT WaitTillLand( void ); + void LimitVelocity( void ); + + virtual int ObjectCaps( void ) { return (CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DONT_SAVE; } + static void SpawnHeadGib( entvars_t *pevVictim ); + static void SpawnHeadGib( entvars_t *pevVictim, const char *szGibModel ); + static void SpawnRandomGibs( entvars_t *pevVictim, int cGibs, int human ); + static void SpawnRandomGibs( entvars_t *pevVictim, int cGibs, int notfirst, const char *szGibModel ); //LRC + static void SpawnStickyGibs( entvars_t *pevVictim, Vector vecOrigin, int cGibs ); + + int m_bloodColor; + int m_cBloodDecals; + int m_material; + float m_lifeTime; +}; + + +#define CUSTOM_SCHEDULES\ + virtual Schedule_t *ScheduleFromName( const char *pName );\ + static Schedule_t *m_scheduleList[]; + +#define DEFINE_CUSTOM_SCHEDULES(derivedClass)\ + Schedule_t *derivedClass::m_scheduleList[] = + +#define IMPLEMENT_CUSTOM_SCHEDULES(derivedClass, baseClass)\ + Schedule_t *derivedClass::ScheduleFromName( const char *pName )\ + {\ + Schedule_t *pSchedule = ScheduleInList( pName, m_scheduleList, ARRAYSIZE(m_scheduleList) );\ + if ( !pSchedule )\ + return baseClass::ScheduleFromName(pName);\ + return pSchedule;\ + } + + + +#endif //MONSTERS_H diff --git a/spirit/player.cpp b/spirit/player.cpp index 14013169..b2fc9e7c 100644 --- a/spirit/player.cpp +++ b/spirit/player.cpp @@ -130,7 +130,13 @@ TYPEDESCRIPTION CBasePlayer::m_playerSaveData[] = DEFINE_FIELD( CBasePlayer, viewEntity, FIELD_STRING), DEFINE_FIELD( CBasePlayer, viewFlags, FIELD_INTEGER), DEFINE_FIELD( CBasePlayer, viewNeedsUpdate, FIELD_INTEGER), - + DEFINE_FIELD( CBasePlayer, m_iFogStartDist, FIELD_INTEGER), + DEFINE_FIELD( CBasePlayer, m_iFogEndDist, FIELD_INTEGER ), + DEFINE_FIELD( CBasePlayer, m_iFogFinalEndDist, FIELD_INTEGER ), + DEFINE_FIELD( CBasePlayer, m_FogColor, FIELD_VECTOR ), + DEFINE_FIELD( CBasePlayer, m_FogFadeTime, FIELD_INTEGER), + DEFINE_FIELD( CBasePlayer, m_flStartTime, FIELD_TIME ), + DEFINE_FIELD( CBasePlayer, Rain_dripsPerSecond, FIELD_INTEGER ), DEFINE_FIELD( CBasePlayer, Rain_windX, FIELD_FLOAT ), DEFINE_FIELD( CBasePlayer, Rain_windY, FIELD_FLOAT ), @@ -262,7 +268,7 @@ void LinkUserMessages( void ) gmsgShowGameTitle = REG_USER_MSG("GameTitle", 0 ); gmsgTempEntity = REG_USER_MSG( "TempEntity", -1); - gmsgSetFog = REG_USER_MSG("SetFog", 9 ); //LRC + gmsgSetFog = REG_USER_MSG("SetFog", 7 ); //LRC gmsgKeyedDLight = REG_USER_MSG("KeyedDLight", -1 ); //LRC gmsgSetSky = REG_USER_MSG( "SetSky", 7 ); //LRC gmsgHUDColor = REG_USER_MSG( "HUDColor", 4 ); //LRC @@ -3071,6 +3077,7 @@ void CBasePlayer :: Precache( void ) // Make sure any necessary user messages have been registered LinkUserMessages(); viewNeedsUpdate = 1; + fogNeedsUpdate = 1; m_iUpdateTime = 5; // won't update for 1/2 a second @@ -3507,6 +3514,7 @@ void CBasePlayer :: ForceClientDllUpdate( void ) m_flFlashLightTime = 1; // Force to update flashlight Rain_needsUpdate = 1; viewNeedsUpdate = 1; + fogNeedsUpdate = 1; // Now force all the necessary messages // to be sent. @@ -4153,6 +4161,38 @@ void CBasePlayer :: UpdateClientData( void ) gDisplayTitle = 0; } + if(m_FogFadeTime != 0) + { + float flDegree = (gpGlobals->time - m_flStartTime) / m_FogFadeTime; + m_iFogEndDist -= (FOG_HARDWARE_LIMIT - m_iFogFinalEndDist) * (flDegree / m_iFogFinalEndDist); + + // cap it + if (m_iFogEndDist > FOG_HARDWARE_LIMIT ) + { + m_iFogEndDist = FOG_HARDWARE_LIMIT; + m_FogFadeTime = 0; + } + if (m_iFogEndDist < m_iFogFinalEndDist) + { + m_iFogEndDist = m_iFogFinalEndDist; + m_FogFadeTime = 0; + } + fogNeedsUpdate = TRUE; + } + + if(fogNeedsUpdate != 0) + { + //update fog + MESSAGE_BEGIN( MSG_ONE, gmsgSetFog, NULL, pev ); + WRITE_BYTE ( m_FogColor.x ); + WRITE_BYTE ( m_FogColor.y ); + WRITE_BYTE ( m_FogColor.z ); + WRITE_SHORT ( m_iFogStartDist ); + WRITE_SHORT ( m_iFogEndDist ); + MESSAGE_END(); + fogNeedsUpdate = 0; + } + if (pev->health != m_iClientHealth) { int iHealth = max( pev->health, 0 ); // make sure that no negative health values are sent diff --git a/spirit/player.h b/spirit/player.h index 04d0f1f8..b3e18bea 100644 --- a/spirit/player.h +++ b/spirit/player.h @@ -313,11 +313,22 @@ public: float m_flStatusBarDisappearDelay; char m_SbarString0[ SBAR_STRING_SIZE ]; char m_SbarString1[ SBAR_STRING_SIZE ]; + // for trigger_viewset - int viewEntity; // string - int viewFlags; // 1-active, 2-draw hud - int viewNeedsUpdate; // precache sets to 1, UpdateClientData() sets to 0 - float m_flNextChatTime; + int viewEntity; // string + int viewFlags; // 1-active, 2-draw hud + int viewNeedsUpdate; // precache sets to 1, UpdateClientData() sets to 0 + float m_flNextChatTime; + + // fog variables + int m_iFogStartDist; + int m_iFogEndDist; + int m_iFogFinalEndDist; + int m_FogFadeTime; + Vector m_FogColor; + int fogNeedsUpdate; + float m_flStartTime; + int Rain_dripsPerSecond; float Rain_windX, Rain_windY; float Rain_randX, Rain_randY; diff --git a/spirit/scripted.cpp b/spirit/scripted.cpp index f82d83d2..c98d1642 100644 --- a/spirit/scripted.cpp +++ b/spirit/scripted.cpp @@ -94,26 +94,47 @@ void CCineMonster :: KeyValue( KeyValueData *pkvd ) m_fMoveTo = atoi( pkvd->szValue ); pkvd->fHandled = TRUE; } + else if (FStrEq(pkvd->szKeyName, "m_fTurnType")) + { + m_fTurnType = atoi( pkvd->szValue ); + pkvd->fHandled = TRUE; + } else if (FStrEq(pkvd->szKeyName, "m_fAction")) { m_fAction = atoi( pkvd->szValue ); pkvd->fHandled = TRUE; - } - else if (FStrEq(pkvd->szKeyName, "m_flRepeat")) - { - m_flRepeat = atof( pkvd->szValue ); - pkvd->fHandled = TRUE; } +// LRC else if (FStrEq(pkvd->szKeyName, "m_flRepeat")) +// { +// m_flRepeat = atof( pkvd->szValue ); +// pkvd->fHandled = TRUE; +// } else if (FStrEq(pkvd->szKeyName, "m_flRadius")) { m_flRadius = atof( pkvd->szValue ); pkvd->fHandled = TRUE; } + else if (FStrEq(pkvd->szKeyName, "m_iRepeats")) + { + m_iRepeats = atoi( pkvd->szValue ); + m_iRepeatsLeft = m_iRepeats; + pkvd->fHandled = TRUE; + } + else if (FStrEq(pkvd->szKeyName, "m_fRepeatFrame")) + { + m_fRepeatFrame = atof( pkvd->szValue ); + pkvd->fHandled = TRUE; + } else if (FStrEq(pkvd->szKeyName, "m_iFinishSchedule")) { m_iFinishSchedule = atoi( pkvd->szValue ); pkvd->fHandled = TRUE; } + else if (FStrEq(pkvd->szKeyName, "m_iPriority")) + { + m_iPriority = atoi( pkvd->szValue ); + pkvd->fHandled = TRUE; + } else { CBaseMonster::KeyValue( pkvd ); @@ -127,11 +148,12 @@ TYPEDESCRIPTION CCineMonster::m_SaveData[] = DEFINE_FIELD( CCineMonster, m_iszPlay, FIELD_STRING ), DEFINE_FIELD( CCineMonster, m_iszEntity, FIELD_STRING ), DEFINE_FIELD( CCineMonster, m_iszAttack, FIELD_STRING ), //LRC - DEFINE_FIELD( CCineMonster, m_iszMoveTarget, FIELD_STRING ), //LRC + DEFINE_FIELD( CCineMonster, m_iszMoveTarget, FIELD_STRING ), //LRC DEFINE_FIELD( CCineMonster, m_iszFireOnBegin, FIELD_STRING ), DEFINE_FIELD( CCineMonster, m_fMoveTo, FIELD_INTEGER ), + DEFINE_FIELD( CCineMonster, m_fTurnType, FIELD_INTEGER ), DEFINE_FIELD( CCineMonster, m_fAction, FIELD_INTEGER ), - DEFINE_FIELD( CCineMonster, m_flRepeat, FIELD_FLOAT ), +//LRC- this is unused DEFINE_FIELD( CCineMonster, m_flRepeat, FIELD_FLOAT ), DEFINE_FIELD( CCineMonster, m_flRadius, FIELD_FLOAT ), DEFINE_FIELD( CCineMonster, m_iDelay, FIELD_INTEGER ), @@ -142,24 +164,26 @@ TYPEDESCRIPTION CCineMonster::m_SaveData[] = DEFINE_FIELD( CCineMonster, m_saved_effects, FIELD_INTEGER ), DEFINE_FIELD( CCineMonster, m_iFinishSchedule, FIELD_INTEGER ), DEFINE_FIELD( CCineMonster, m_interruptable, FIELD_BOOLEAN ), -};IMPLEMENT_SAVERESTORE( CCineMonster, CBaseMonster ); + //LRC + DEFINE_FIELD( CCineMonster, m_iRepeats, FIELD_INTEGER ), + DEFINE_FIELD( CCineMonster, m_iRepeatsLeft, FIELD_INTEGER ), + DEFINE_FIELD( CCineMonster, m_fRepeatFrame, FIELD_FLOAT ), + DEFINE_FIELD( CCineMonster, m_iPriority, FIELD_INTEGER ), +}; + + +IMPLEMENT_SAVERESTORE( CCineMonster, CBaseMonster ); LINK_ENTITY_TO_CLASS( scripted_sequence, CCineMonster ); LINK_ENTITY_TO_CLASS( scripted_action, CCineMonster ); -LINK_ENTITY_TO_CLASS( aiscripted_sequence, CCineMonster ); + +LINK_ENTITY_TO_CLASS( aiscripted_sequence, CCineMonster ); //LRC - aiscripted sequences don't need to be seperate //========================================================= // FCanOverrideState - returns FALSE, scripted sequences // cannot possess entities regardless of state. //========================================================= -BOOL CCineMonster :: FCanOverrideState( void ) -{ - if ( FClassnameIs(pev, "aiscripted_sequence") || pev->spawnflags & SF_SCRIPT_OVERRIDESTATE ) - return TRUE; - return FALSE; -} - void CCineMonster :: Spawn( void ) { // pev->solid = SOLID_TRIGGER; @@ -168,18 +192,26 @@ void CCineMonster :: Spawn( void ) m_iState = STATE_OFF; //LRC - // if no targetname, start now - if ( FStringNull(pev->targetname) || !FStringNull( m_iszIdle ) ) + if ( FStringNull(m_iszIdle) && FStringNull(pev->targetname) ) // if no targetname, start now { - SetThink( CineThink ); + SetThink(&CCineMonster :: CineThink ); + SetNextThink( 1.0 ); + } + else if ( m_iszIdle ) + { + SetThink(&CCineMonster :: InitIdleThink ); SetNextThink( 1.0 ); - // Wait to be used? - if ( pev->targetname ) - m_startTime = gpGlobals->time + 1E6; } if ( pev->spawnflags & SF_SCRIPT_NOINTERRUPT ) m_interruptable = FALSE; - else m_interruptable = TRUE; + else + m_interruptable = TRUE; + + //LRC - the only difference between AI and normal sequences + if ( FClassnameIs(pev, "aiscripted_sequence") || pev->spawnflags & SF_SCRIPT_OVERRIDESTATE ) + { + m_iPriority |= SS_INTERRUPT_ANYSTATE; + } } // @@ -196,18 +228,21 @@ void CCineMonster :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYP if ( pTarget ) { +// ALERT(at_console, "Sequence \"%s\" triggered, already has a target.\n", STRING(pev->targetname)); // am I already playing the script? if ( pTarget->m_scriptState == SCRIPT_PLAYING ) return; - m_startTime = gpGlobals->time + 0.05; + m_startTime = gpGlobals->time + 0.05; //why the delay? -- LRC } else { - // if not, try finding them +// ALERT(at_console, "Sequence \"%s\" triggered, can't find target; searching\n", STRING(pev->targetname)); m_hActivator = pActivator; - SetThink( CineThink ); - pev->nextthink = gpGlobals->time; + // if not, try finding them + SetThink(&CCineMonster :: CineThink ); +// SetNextThink( 0 ); + CineThink(); //LRC } } @@ -276,7 +311,7 @@ void CCineMonster :: Pain( void ) // ********** Cinematic Think ********** // -// find a viable entity +//LRC: now redefined... find a viable entity with the given name, and return it (or NULL if not found). CBaseMonster* CCineMonster :: FindEntity( const char* sName, CBaseEntity *pActivator ) { CBaseEntity *pEntity; @@ -290,7 +325,7 @@ CBaseMonster* CCineMonster :: FindEntity( const char* sName, CBaseEntity *pActiv if ( FBitSet( pEntity->pev->flags, FL_MONSTER )) { pMonster = pEntity->MyMonsterPointer( ); - if ( pMonster && pMonster->CanPlaySequence( FCanOverrideState(), SS_INTERRUPT_BY_NAME ) ) + if ( pMonster && pMonster->CanPlaySequence( m_iPriority | SS_INTERRUPT_ALERT ) ) { return pMonster; } @@ -311,7 +346,7 @@ CBaseMonster* CCineMonster :: FindEntity( const char* sName, CBaseEntity *pActiv if ( FBitSet( pEntity->pev->flags, FL_MONSTER )) { pMonster = pEntity->MyMonsterPointer( ); - if ( pMonster && pMonster->CanPlaySequence( FCanOverrideState(), SS_INTERRUPT_IDLE ) ) + if ( pMonster && pMonster->CanPlaySequence( m_iPriority ) ) { return pMonster; } @@ -327,11 +362,17 @@ void CCineMonster :: PossessEntity( void ) { CBaseEntity *pEntity = m_hTargetEnt; CBaseMonster *pTarget = NULL; - if ( pEntity ) pTarget = pEntity->MyMonsterPointer(); + if ( pEntity ) + pTarget = pEntity->MyMonsterPointer(); + +// ALERT( at_console, "Possess: pEntity %s, pTarget %s\n", STRING(pEntity->pev->targetname), STRING(pTarget->pev->targetname)); if ( pTarget ) { - if (pTarget->m_pCine) pTarget->m_pCine->CancelScript(); + if (pTarget->m_pCine) + { + pTarget->m_pCine->CancelScript(); + } pTarget->m_pCine = this; if (m_iszAttack) @@ -341,12 +382,20 @@ void CCineMonster :: PossessEntity( void ) if ( pTarget->m_hTargetEnt == NULL ) { // nothing. Anything with that classname? while ((pTarget->m_hTargetEnt = UTIL_FindEntityInSphere( pTarget->m_hTargetEnt, pev->origin, m_flRadius )) != NULL) + { if (FClassnameIs( pTarget->m_hTargetEnt->pev, STRING(m_iszAttack))) break; + } } if (pTarget->m_hTargetEnt == NULL) + { // nothing. Oh well. + ALERT(at_debug,"%s %s has a missing \"turn target\": %s\n",STRING(pev->classname),STRING(pev->targetname),STRING(m_iszAttack)); pTarget->m_hTargetEnt = this; + } + } + else + { + pTarget->m_hTargetEnt = this; } - else pTarget->m_hTargetEnt = this; if (m_iszMoveTarget) { @@ -358,60 +407,59 @@ void CCineMonster :: PossessEntity( void ) pTarget->m_pGoalEnt = this; } } - else pTarget->m_pGoalEnt = this; + else + { + pTarget->m_pGoalEnt = this; + } +// if (IsAction()) +// pTarget->PushEnemy(this,pev->origin); m_saved_movetype = pTarget->pev->movetype; m_saved_solid = pTarget->pev->solid; m_saved_effects = pTarget->pev->effects; pTarget->pev->effects |= pev->effects; +// ALERT(at_console, "script. IsAction = %d",IsAction()); + + m_iState = STATE_ON; // LRC: assume we'll set it to 'on', unless proven otherwise... switch (m_fMoveTo) { - case 0: - pTarget->m_scriptState = SCRIPT_WAIT; - break; - case 1: - pTarget->m_scriptState = SCRIPT_WALK_TO_MARK; - DelayStart( 1 ); - break; - case 2: - pTarget->m_scriptState = SCRIPT_RUN_TO_MARK; - DelayStart( 1 ); - break; - - case 4: - UTIL_SetOrigin( pTarget, pev->origin ); - pTarget->pev->ideal_yaw = pev->angles.y; - pTarget->pev->avelocity = Vector( 0, 0, 0 ); - pTarget->pev->velocity = Vector( 0, 0, 0 ); - pTarget->pev->effects |= EF_NOINTERP; - pTarget->pev->angles.y = pev->angles.y; - pTarget->m_scriptState = SCRIPT_WAIT; - m_startTime = gpGlobals->time + 1E6; - //pTarget->pev->flags &= ~FL_ONGROUND; + DelayStart( 1 ); + m_iState = STATE_TURN_ON; + // fall through... + case 0: + case 4: + case 5: + case 6: + pTarget->m_scriptState = SCRIPT_WAIT; break; } // ALERT( at_aiconsole, "\"%s\" found and used (INT: %s)\n", STRING( pTarget->pev->targetname ), FBitSet(pev->spawnflags, SF_SCRIPT_NOINTERRUPT)?"No":"Yes" ); pTarget->m_IdealMonsterState = MONSTERSTATE_SCRIPT; - if (m_iszIdle) - { - StartSequence( pTarget, m_iszIdle, FALSE ); - if (FStrEq( STRING(m_iszIdle), STRING(m_iszPlay))) - { - pTarget->pev->framerate = 0; - } - } +// if (m_iszIdle) +// { +// ALERT(at_console, "Possess: Play idle sequence\n"); +// StartSequence( pTarget, m_iszIdle, FALSE ); +// if (FStrEq( STRING(m_iszIdle), STRING(m_iszPlay))) +// { +// pTarget->pev->framerate = 0; +// } +// } +// ALERT(at_console, "Finished PossessEntity, ms %d, ims %d\n", pTarget->m_MonsterState, pTarget->m_IdealMonsterState); } + } -void CCineMonster :: CineThink( void ) +// at the beginning of the level, set up the idle animation. --LRC +void CCineMonster :: InitIdleThink( void ) { - if ((m_hTargetEnt = FindEntity(STRING(m_iszEntity),m_hActivator)) != NULL) + if ((m_hTargetEnt = FindEntity(STRING(m_iszEntity), NULL)) != NULL) { PossessEntity( ); + m_startTime = gpGlobals->time + 1E6; ALERT( at_aiconsole, "script \"%s\" using monster \"%s\"\n", STRING( pev->targetname ), STRING( m_iszEntity ) ); } else @@ -422,10 +470,30 @@ void CCineMonster :: CineThink( void ) } } +void CCineMonster :: CineThink( void ) +{ +// ALERT(at_console, "Sequence think, activator %s\n", STRING(m_hActivator->pev->targetname)); + if ((m_hTargetEnt = FindEntity(STRING(m_iszEntity),m_hActivator)) != NULL) + { +// ALERT(at_console, "Sequence found %s \"%s\"\n", STRING(m_hTargetEnt->pev->classname), STRING(m_hTargetEnt->pev->targetname)); + PossessEntity( ); + ALERT( at_aiconsole, "script \"%s\" using monster \"%s\"\n", STRING( pev->targetname ), STRING( m_iszEntity ) ); + } + else + { +// ALERT(at_console, "Sequence found nothing called %s\n", STRING(m_iszEntity)); + CancelScript( ); + ALERT( at_aiconsole, "script \"%s\" can't find monster \"%s\"\n", STRING( pev->targetname ), STRING( m_iszEntity ) ); + SetNextThink( 1.0 ); + } +} + // lookup a sequence name and setup the target monster to play it BOOL CCineMonster :: StartSequence( CBaseMonster *pTarget, int iszSeq, BOOL completeOnEmpty ) { +// ALERT( at_console, "StartSequence %s \"%s\"\n", STRING(pev->classname), STRING(pev->targetname)); + if ( !iszSeq && completeOnEmpty ) { SequenceDone( pTarget ); @@ -447,7 +515,7 @@ BOOL CCineMonster :: StartSequence( CBaseMonster *pTarget, int iszSeq, BOOL comp else s = "Yes"; - ALERT( at_console, "%s (%s): started \"%s\":INT:%s\n", STRING( pTarget->pev->targetname ), STRING( pTarget->pev->classname ), STRING( iszSeq), s ); + ALERT( at_debug, "%s (%s): started \"%s\":INT:%s\n", STRING( pTarget->pev->targetname ), STRING( pTarget->pev->classname ), STRING( iszSeq), s ); #endif pTarget->pev->frame = 0; @@ -464,8 +532,10 @@ BOOL CCineMonster :: StartSequence( CBaseMonster *pTarget, int iszSeq, BOOL comp //========================================================= void CCineMonster :: SequenceDone ( CBaseMonster *pMonster ) { - //ALERT( at_aiconsole, "Sequence %s finished\n", STRING( m_pCine->m_iszPlay ) ); + m_iRepeatsLeft = m_iRepeats; //LRC - reset the repeater count m_iState = STATE_OFF; // we've finished. +// ALERT( at_console, "Sequence %s finished\n", STRING(pev->targetname));//STRING( m_pCine->m_iszPlay ) ); + if ( !( pev->spawnflags & SF_SCRIPT_REPEATABLE ) ) { SetThink(&CCineMonster :: SUB_Remove ); @@ -495,7 +565,9 @@ void CCineMonster :: SequenceDone ( CBaseMonster *pMonster ) //========================================================= void CCineMonster :: FixScriptMonsterSchedule( CBaseMonster *pMonster ) { - if ( pMonster->m_IdealMonsterState != MONSTERSTATE_DEAD ) pMonster->m_IdealMonsterState = MONSTERSTATE_IDLE; + if ( pMonster->m_IdealMonsterState != MONSTERSTATE_DEAD ) + pMonster->m_IdealMonsterState = MONSTERSTATE_IDLE; +// pMonster->ClearSchedule(); switch ( m_iFinishSchedule ) { @@ -557,6 +629,9 @@ int CCineMonster::IgnoreConditions( void ) { if ( CanInterrupt() ) return 0; + + // Big fat BUG: This is an IgnoreConditions function - we need to return the conditions + // that _shouldn't_ be able to break the script, instead of the conditions that _should_!! return SCRIPT_BREAK_CONDITIONS; } @@ -612,7 +687,7 @@ void CCineMonster :: CancelScript( void ) } -// find all the cinematic entities with my targetname and tell them to wait before starting +// find all the cinematic entities with my targetname and tell them whether to wait before starting void CCineMonster :: DelayStart( int state ) { CBaseEntity *pCine = UTIL_FindEntityByTargetname(NULL, STRING(pev->targetname)); @@ -622,9 +697,14 @@ void CCineMonster :: DelayStart( int state ) if (FClassnameIs( pCine->pev, "scripted_sequence" ) || FClassnameIs( pCine->pev, "scripted_action" )) { CCineMonster *pTarget = GetClassPtr((CCineMonster *)(pCine->pev)); - if (state) pTarget->m_iDelay++; + if (state) + { +// ALERT(at_console, "Delaying start\n"); + pTarget->m_iDelay++; + } else { +// ALERT(at_console, "Undelaying start\n"); pTarget->m_iDelay--; if (pTarget->m_iDelay <= 0) { @@ -696,9 +776,11 @@ BOOL CBaseMonster :: CineCleanup( ) { // okay, reset me to what it thought I was before m_pCine->m_hTargetEnt = NULL; + pev->movetype = m_pCine->m_saved_movetype; - pev->solid = m_pCine->m_saved_solid; - pev->effects = m_pCine->m_saved_effects; + +// LRC - why mess around with this? Solidity isn't changed by sequences! +// pev->solid = m_pCine->m_saved_solid; if (m_pCine->pev->spawnflags & SF_SCRIPT_STAYDEAD) pev->deadflag = DEAD_DYING; @@ -805,6 +887,11 @@ BOOL CBaseMonster :: CineCleanup( ) FCheckAITrigger(); pev->deadflag = DEAD_NO; } + + + // SetAnimation( m_MonsterState ); + //LRC- removed, was never implemented. ClearBits(pev->spawnflags, SF_MONSTER_WAIT_FOR_SCRIPT ); + return TRUE; } diff --git a/spirit/scripted.h b/spirit/scripted.h index f7ec4970..1cefc563 100644 --- a/spirit/scripted.h +++ b/spirit/scripted.h @@ -32,12 +32,11 @@ #define SCRIPT_BREAK_CONDITIONS (bits_COND_LIGHT_DAMAGE|bits_COND_HEAVY_DAMAGE) -enum SS_INTERRUPT -{ - SS_INTERRUPT_IDLE = 0, - SS_INTERRUPT_BY_NAME, - SS_INTERRUPT_AI, -}; +//LRC - rearranged into flags +#define SS_INTERRUPT_IDLE 0x0 +#define SS_INTERRUPT_ALERT 0x1 +#define SS_INTERRUPT_ANYSTATE 0x2 +#define SS_INTERRUPT_SCRIPTS 0x4 // when a monster finishes an AI scripted sequence, we can choose // a schedule to place them in. These defines are the aliases to @@ -80,15 +79,18 @@ public: // (Do a precise attack if we'll be turning to face the target, but we haven't just walked to the target.) BOOL PreciseAttack( void ) { - if (m_fMoveTo == 0) { ALERT(at_console,"preciseattack fails check 2\n"); return FALSE; } - if (m_fMoveTo != 5 && m_iszAttack == 0) { ALERT(at_console,"preciseattack fails check 3\n"); return FALSE; } - return TRUE; + // if (m_fTurnType != 1) { ALERT(at_console,"preciseattack fails check 1\n"); return FALSE; } + // if (m_fMoveTo == 0) { ALERT(at_console,"preciseattack fails check 2\n"); return FALSE; } + // if (m_fMoveTo != 5 && m_iszAttack == 0) { ALERT(at_console,"preciseattack fails check 3\n"); return FALSE; } + // ALERT(at_console,"preciseattack passes!\n"); + // return TRUE; + return m_fTurnType == 1 && ( m_fMoveTo == 5 || (m_fMoveTo != 0 && !FStrEq(STRING(m_iszAttack), STRING(m_iszMoveTarget)) )); + }; void ReleaseEntity( CBaseMonster *pEntity ); void CancelScript( void ); virtual BOOL StartSequence( CBaseMonster *pTarget, int iszSeq, BOOL completeOnEmpty ); - BOOL CCineMonster :: FCanOverrideState( void ); void SequenceDone ( CBaseMonster *pMonster ); virtual void FixScriptMonsterSchedule( CBaseMonster *pMonster ); BOOL CanInterrupt( void ); @@ -102,10 +104,15 @@ public: int m_iszMoveTarget; // entity to move to int m_iszFireOnBegin; // entity to fire when the sequence _starts_. int m_fMoveTo; + int m_fTurnType; int m_fAction; int m_iFinishSchedule; float m_flRadius; // range to search - float m_flRepeat; // repeat rate +//LRC- this does nothing!! float m_flRepeat; // repeat rate + int m_iRepeats; //LRC - number of times to repeat the animation + int m_iRepeatsLeft; //LRC + float m_fRepeatFrame; //LRC + int m_iPriority; //LRC int m_iDelay; float m_startTime; @@ -113,6 +120,7 @@ public: int m_saved_movetype; int m_saved_solid; int m_saved_effects; +// Vector m_vecOrigOrigin; BOOL m_interruptable; }; diff --git a/spirit/sound.cpp b/spirit/sound.cpp index 7c81f696..3871ef0f 100644 --- a/spirit/sound.cpp +++ b/spirit/sound.cpp @@ -722,7 +722,7 @@ void CAmbientGeneric :: ToggleUse ( CBaseEntity *pActivator, CBaseEntity *pCalle InitModulationParms(); // AJH / MJB - [LR] volume field: - if (pev->noise) m_dpv.vol = CalcLocus_Ratio(this, STRING(pev->noise), 0); + if (pev->noise) m_dpv.vol = CalcLocus_Ratio(this, STRING(pev->noise)); if (m_pPlayFrom) { diff --git a/spirit/tentacle.cpp b/spirit/tentacle.cpp index 593d6d23..04b9f269 100644 --- a/spirit/tentacle.cpp +++ b/spirit/tentacle.cpp @@ -71,7 +71,8 @@ public: void Killed( entvars_t *pevAttacker, int iGib ); MONSTERSTATE GetIdealState ( void ) { return MONSTERSTATE_IDLE; }; - int CanPlaySequence( BOOL fDisregardState ) { return TRUE; }; +// int CanPlaySequence( BOOL fDisregardState ) { return TRUE; }; + int CanPlaySequence( int interruptFlags ) { return TRUE; }; int Classify( void ); diff --git a/spirit/util.cpp b/spirit/util.cpp index 9702373d..94a33709 100644 --- a/spirit/util.cpp +++ b/spirit/util.cpp @@ -1499,6 +1499,46 @@ void UTIL_ShowMessageAll( const char *pString ) } } +void UTIL_SetFogAll( Vector color, int iFadeTime, int iStartDist, int iEndDist ) +{ + // loop through all players + if( IsMultiplayer( )) + { + for ( int i = 0; i < gpGlobals->maxClients; i++ ) + UTIL_SetFog( color, iFadeTime, iStartDist, iEndDist, i+1 ); + } + else UTIL_SetFog( color, iFadeTime, iStartDist, iEndDist ); +} + +void UTIL_SetFog( Vector color, int iFadeTime, int iStartDist, int iEndDist, int playernum ) +{ + CBasePlayer *pPlayer = (CBasePlayer*)UTIL_PlayerByIndex( playernum ); + + if ( pPlayer ) + { + if( pPlayer->m_FogFadeTime != 0 ) return;//fading in progress !!!TODO: make smooth re-fading + if( IsMultiplayer( )) iFadeTime = 0; // disable fading in multiplayer + + if( iFadeTime > 0 ) + { + pPlayer->m_iFogEndDist = FOG_HARDWARE_LIMIT; + pPlayer->m_iFogFinalEndDist = iEndDist; + } + else if( iFadeTime < 0 ) + { + pPlayer->m_iFogEndDist = iEndDist; + pPlayer->m_iFogFinalEndDist = iEndDist; + } + else pPlayer->m_iFogEndDist = iEndDist; + + pPlayer->m_iFogStartDist = iStartDist; + pPlayer->m_FogColor = color; + pPlayer->m_FogFadeTime = iFadeTime; + pPlayer->m_flStartTime = gpGlobals->time; + pPlayer->fogNeedsUpdate = TRUE; + } +} + // Overloaded to add IGNORE_GLASS void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, edict_t *pentIgnore, TraceResult *ptr ) { diff --git a/spirit/util.h b/spirit/util.h index 0c2ee902..6de750f2 100644 --- a/spirit/util.h +++ b/spirit/util.h @@ -27,6 +27,8 @@ #include "enginecallback.h" #include "event_api.h" +#define FOG_HARDWARE_LIMIT 8192 + //g-cont. safe precaching models & sounds int PRECACHE_MODEL( char* s ); // classic precache int PRECACHE_MODEL( string_t s ); // pev->model as argument @@ -331,6 +333,9 @@ extern void UTIL_ShowMessage ( const char *pString, CBaseEntity *pPlayer ); extern void UTIL_ShowMessageAll ( const char *pString ); extern void UTIL_ScreenFadeAll ( const Vector &color, float fadeTime, float holdTime, int alpha, int flags ); extern void UTIL_ScreenFade ( CBaseEntity *pEntity, const Vector &color, float fadeTime, float fadeHold, int alpha, int flags ); +extern void UTIL_SetFog ( Vector color, int iFadeTime, int iStartDist, int iEndDist, int playernum = 1 ); +extern void UTIL_SetFogAll ( Vector color, int iFadeTime, int iStartDist, int iEndDist ); + extern void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, edict_t *pentIgnore, TraceResult *ptr); extern void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, edict_t *pentIgnore, TraceResult *ptr); diff --git a/spirit/world.cpp b/spirit/world.cpp index 3e8c32cb..7bc1587d 100644 --- a/spirit/world.cpp +++ b/spirit/world.cpp @@ -534,9 +534,9 @@ void CWorld :: Precache( void ) ALERT ( at_debug, "**COULD NOT CREATE SOUNDENT**\n" ); } - if( pev->message != 0 ) + if( pev->target != 0 ) { - SET_SKYBOX( STRING( pev->message )); + SET_SKYBOX( STRING( pev->target )); } else { @@ -677,7 +677,7 @@ void CWorld :: KeyValue( KeyValueData *pkvd ) if( FStrEq( pkvd->szKeyName, "skyname" )) { // Sent over net now. - pev->message = ALLOC_STRING( pkvd->szValue ); + pev->target = ALLOC_STRING( pkvd->szValue ); pkvd->fHandled = TRUE; } else if ( FStrEq(pkvd->szKeyName, "sounds") ) diff --git a/todo.log b/todo.log index b821633b..3a432524 100644 --- a/todo.log +++ b/todo.log @@ -28,4 +28,4 @@ Xash 0.71 Beta 05.05.10 4. complete lights.shader 5. revision server physic 6. revision monster moving -7. implement env_laser \ No newline at end of file +7. reborn Xash 0.4 Source Code \ No newline at end of file diff --git a/vid_gl/r_backend.h b/vid_gl/r_backend.h index 24998c1a..858c447e 100644 --- a/vid_gl/r_backend.h +++ b/vid_gl/r_backend.h @@ -436,6 +436,12 @@ typedef struct int drawMode; rgba_t color; + // linear fog stuff + vec4_t fogColor; + float fogStartDist; + float fogEndDist; + bool fogEnabled; + int features; int numVertex; int numColor; diff --git a/vid_gl/r_draw.c b/vid_gl/r_draw.c index 7ddf19c1..11ca6556 100644 --- a/vid_gl/r_draw.c +++ b/vid_gl/r_draw.c @@ -307,7 +307,18 @@ static void Tri_CheckOverflow( int numIndices, int numVertices ) void Tri_Fog( float flFogColor[3], float flStart, float flEnd, int bOn ) { - // FIXME: implement + // ignore fog calls from TriApi callbacks + // to avoid strange artefacts and other issues + if( triState.fActive ) return; + + // change fog params + triState.fogColor[0] = bound( 0.0f, flFogColor[0], 1.0f ); + triState.fogColor[1] = bound( 0.0f, flFogColor[1], 1.0f ); + triState.fogColor[2] = bound( 0.0f, flFogColor[2], 1.0f ); + triState.fogColor[3] = 1.0f; + triState.fogStartDist = min( flStart, flEnd ); + triState.fogEndDist = max( flStart, flEnd ); + triState.fogEnabled = bOn; } void Tri_CullFace( int mode ) diff --git a/vid_gl/r_main.c b/vid_gl/r_main.c index 53effe9e..32224579 100644 --- a/vid_gl/r_main.c +++ b/vid_gl/r_main.c @@ -812,7 +812,6 @@ void R_Set2DMode( bool enable ) } } - /* ============ R_PolyBlend @@ -1740,8 +1739,6 @@ void R_BeginFrame( bool clearScene ) } } - pglDrawBuffer( GL_BACK ); - if( r_colorbits->modified ) { r_colorbits->modified = false; diff --git a/vid_gl/r_mesh.c b/vid_gl/r_mesh.c index e3af5517..ce9502e6 100644 --- a/vid_gl/r_mesh.c +++ b/vid_gl/r_mesh.c @@ -632,6 +632,24 @@ void R_DrawPortals( void ) } } +/* +=============== +R_RenderFog +=============== +*/ +void R_RenderFog( void ) +{ + if( !triState.fogEnabled ) return; + + pglEnable( GL_FOG ); +// pglFogf( GL_FOG_DENSITY, 0.0025 ); + pglFogi( GL_FOG_MODE, GL_LINEAR ); + pglFogfv( GL_FOG_COLOR, triState.fogColor ); + pglFogf( GL_FOG_START, triState.fogStartDist ); + pglFogf( GL_FOG_END, triState.fogEndDist ); + pglHint( GL_FOG_HINT, GL_NICEST ); +} + /* ================ R_DrawMeshes @@ -642,6 +660,8 @@ void R_DrawMeshes( void ) int i; meshbuffer_t *meshbuf; + R_RenderFog(); + RI.previousentity = NULL; if( RI.meshlist->num_opaque_meshes ) { @@ -652,6 +672,9 @@ void R_DrawMeshes( void ) } Tri_RenderCallback( false ); + // don't fogging translucent surfaces + if( triState.fogEnabled ) pglDisable( GL_FOG ); + if( RI.meshlist->num_translucent_meshes ) { meshbuf = RI.meshlist->meshbuffer_translucent; @@ -662,6 +685,9 @@ void R_DrawMeshes( void ) Tri_RenderCallback( true ); R_LoadIdentity(); + + // clearing fog after each frame + triState.fogEnabled = false; } /* diff --git a/vid_gl/r_opengl.h b/vid_gl/r_opengl.h index 6df85e9f..58b55b96 100644 --- a/vid_gl/r_opengl.h +++ b/vid_gl/r_opengl.h @@ -272,6 +272,15 @@ typedef uint GLhandleARB; #define GL_INCR 0x1E02 #define GL_DECR 0x1E03 +// fog stuff +#define GL_FOG 0x0B60 +#define GL_FOG_INDEX 0x0B61 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_COLOR 0x0B66 + #define GL_POLYGON_OFFSET_FACTOR 0x8038 #define GL_POLYGON_OFFSET_UNITS 0x2A00 #define GL_POLYGON_OFFSET_POINT 0x2A01 diff --git a/vid_gl/r_register.c b/vid_gl/r_register.c index 326ca961..dc94e453 100644 --- a/vid_gl/r_register.c +++ b/vid_gl/r_register.c @@ -261,6 +261,9 @@ static dllfunc_t opengl_110funcs[] = {"glClipPlane", (void **) &pglClipPlane}, {"glGetClipPlane", (void **) &pglGetClipPlane}, {"glShadeModel", (void **) &pglShadeModel}, + {"glFogfv", (void **) &pglFogfv}, + {"glFogf", (void **) &pglFogf}, + {"glFogi", (void **) &pglFogi}, {NULL, NULL} }; diff --git a/vid_gl/r_shader.c b/vid_gl/r_shader.c index fdd35472..61c11d47 100644 --- a/vid_gl/r_shader.c +++ b/vid_gl/r_shader.c @@ -79,6 +79,30 @@ static bool r_shaderHasDlightPass; #define Shader_Malloc( size ) Mem_Alloc( r_shaderpool, size ) #define Shader_Free( data ) Mem_Free( data ) +const char *R_SkyPath( void ) +{ + // reinstall loadformats by magic keyword :) + if( !com.stricmp( GI->texmode, "Xash3D" ) || !com.stricmp( GI->texmode, "Xash" )) + return "env"; + else if( !com.stricmp( GI->texmode, "stalker" ) || !com.stricmp( GI->texmode, "S.T.A.L.K.E.R" )) + return "textures/sky"; + else if( !com.stricmp( GI->texmode, "Doom1" ) || !com.stricmp( GI->texmode, "Doom2" )) + return "gfx/env"; + else if( !com.stricmp( GI->texmode, "Quake1" )) + return "gfx/env"; + else if( !com.stricmp( GI->texmode, "Quake2" )) + return "env"; + else if( !com.stricmp( GI->texmode, "Quake3" )) + return "env"; + else if( !com.stricmp( GI->texmode, "Quake4" ) || !com.stricmp( GI->texmode, "Doom3" )) + return "env"; + else if( !com.stricmp( GI->texmode, "hl1" ) || !com.stricmp( GI->texmode, "Half-Life" )) + return "gfx/env"; + else if( !com.stricmp( GI->texmode, "hl2" ) || !com.stricmp( GI->texmode, "Half-Life 2" )) + return "materials/skybox"; + return "png"; +} + /* ======================================================================= @@ -4076,7 +4100,7 @@ ref_shader_t *R_SetupSky( const char *name ) { if( !Shader_CheckSkybox( loadname )) { - com.strncpy( loadname, va( "env/%s", name ), sizeof( loadname )); + com.strncpy( loadname, va( "%s/%s", R_SkyPath(), name ), sizeof( loadname )); if( Shader_CheckSkybox( loadname )) shader_valid = true; else shader_valid = true;