//========================== // V_CalcWaterLevel //========================== float V_CalcWaterLevel( struct ref_params_s *pparams ) { float waterOffset = 0.0f; if( pparams->waterlevel >= 2 ) { int waterEntity = WATER_ENTITY( pparams->simorg ); float waterDist = cl_waterdist->value; if( waterEntity >= 0 && waterEntity < pparams->max_entities ) { cl_entity_t *pwater = GET_ENTITY( waterEntity ); if( pwater && ( pwater->model != NULL )) waterDist += ( pwater->curstate.scale * 16.0f ); } Vector point = pparams->vieworg; // eyes are above water, make sure we're above the waves if( pparams->waterlevel == 2 ) { point.z -= waterDist; for( int i = 0; i < waterDist; i++ ) { int contents = POINT_CONTENTS( point ); if( contents > CONTENTS_WATER ) break; point.z += 1; } waterOffset = (point.z + waterDist) - pparams->vieworg[2]; } else { // eyes are under water. Make sure we're far enough under point[2] += waterDist; for( int i = 0; i < waterDist; i++ ) { int contents = POINT_CONTENTS( point ); if( contents <= CONTENTS_WATER ) break; point.z -= 1; } waterOffset = (point.z - waterDist) - pparams->vieworg[2]; } } return waterOffset; }
/** * Probes the world space at v_location and returns whether or not the point * is in mid-air. */ bool IsThinAir(const Vector &v_location) { // do the actual probe int contents = POINT_CONTENTS(v_location); // point belongs to mid-air in either of these cases return (contents == CONTENTS_EMPTY || contents == CONTENT_FOG || contents == CONTENT_FLYFIELD || contents == CONTENT_GRAVITY_FLYFIELD); }
/** * Probes the world space at v_location and returns whether or not the point * belongs to swimmable liquid. */ bool IsLiquid(const Vector &v_location) { // do the actual probe int contents = POINT_CONTENTS(v_location); // point belongs to liquid in either of these cases return (contents == CONTENTS_WATER || contents == CONTENTS_SLIME || contents == CONTENTS_LAVA); }
/** * Probes the world space at v_location and returns whether or not the point * belongs to the reachable world - thin air or swimmable liquid - or the void. * Concrete materials and skyboxes are assimilated to the void because of their * "unreachable" state. */ bool PointBelongsToWorld(const Vector &v_location) { // do the actual probe int contents = POINT_CONTENTS(v_location); // point belongs to reachable world only if it's NOT inside concrete material, // NOT in the sky and NOT inside a ladder entity return !(contents == CONTENTS_SOLID || contents == CONTENTS_SKY || contents == CONTENTS_LADDER); }
static cell AMX_NATIVE_CALL PointContents(AMX *amx, cell *params) { cell *cAddr = MF_GetAmxAddr(amx, params[1]); REAL fX = amx_ctof(cAddr[0]); REAL fY = amx_ctof(cAddr[1]); REAL fZ = amx_ctof(cAddr[2]); Vector vPoint = Vector(fX, fY, fZ); return POINT_CONTENTS(vPoint); }
void CBaseEntity::FireBulletsWater( Vector vecSrc, Vector vecEnd, float ScaleSplash1, float ScaleSplash2 ) { if( !( POINT_CONTENTS( vecEnd ) == CONTENTS_WATER && POINT_CONTENTS( vecSrc ) != CONTENTS_WATER ) ) return; float len = Vector( vecEnd - vecSrc).Length(); Vector vecTemp = ( vecEnd + vecSrc ) / 2; while( len >= 1 ) { if( POINT_CONTENTS( vecTemp ) == CONTENTS_WATER ) vecEnd = vecTemp; else vecSrc = vecTemp; vecTemp = ( vecEnd + vecSrc ) / 2; len = Vector( vecEnd - vecSrc).Length(); } MESSAGE_BEGIN(MSG_ALL, gmsgWaterSplash); WRITE_COORD( vecTemp.x ); WRITE_COORD( vecTemp.y ); WRITE_COORD( vecTemp.z ); WRITE_COORD( ScaleSplash1 ); WRITE_COORD( ScaleSplash2 ); MESSAGE_END(); switch( RANDOM_LONG( 1, 3 ) ) { case 1: UTIL_EmitAmbientSound( ENT(0), vecTemp, "items/water_splash/water_splash1.wav", 1, ATTN_NORM, 0, 100 ); break; case 2: UTIL_EmitAmbientSound( ENT(0), vecTemp, "items/water_splash/water_splash2.wav", 1, ATTN_NORM, 0, 100 ); break; case 3: UTIL_EmitAmbientSound( ENT(0), vecTemp, "items/water_splash/water_splash3.wav", 1, ATTN_NORM, 0, 100 ); break; } }
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++ ) { int newDamage = iDamage; //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), &tr); // do damage, paint decals if (tr.flFraction != 1.0) { CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); newDamage -= vec3_t( tr.vecEndPos - vecSrc ).Length() * 0.01; pEntity->TraceAttack(pevAttacker, newDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) ); FireBulletsWater( vecSrc, tr.vecEndPos, 0.5, 0.3 ); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); if( cShots == 1 ) { float unit = iDamage; while( newDamage > 0 ) { if( POINT_CONTENTS( tr.vecEndPos + vecDir * unit ) == CONTENTS_SOLID ) break; UTIL_TraceLine(tr.vecEndPos + vecDir * unit, vecSrc, dont_ignore_monsters, ENT(pev), &tr); if( tr.fAllSolid ) break; TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); newDamage /= 2; unit /= 2; vecSrc = tr.vecEndPos; UTIL_TraceLine(tr.vecEndPos, vecEnd, dont_ignore_monsters, ENT(pev), &tr); newDamage -= vec3_t( tr.vecEndPos - vecSrc ).Length() * 0.01; pEntity = CBaseEntity::Instance(tr.pHit); pEntity->TraceAttack(pevAttacker, newDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) ); FireBulletsWater( vecSrc, tr.vecEndPos, 0.5, 0.3 ); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); } } } // 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 ParticleSystem::DrawParticle( particle *part, Vector &right, Vector &up ) { float fSize = part->m_fSize; Vector point1, point2, point3, point4; Vector origin = part->origin; // nothing to draw? if ( fSize == 0 ) return; // frustrum visible check if( !ParticleIsVisible( part )) return; float fCosSize = CosLookup( part->m_fAngle ) * fSize; float fSinSize = SinLookup( part->m_fAngle ) * fSize; // calculate the four corners of the sprite point1 = origin + fSinSize * up; point1 = point1 + (-fCosSize) * right; point2 = origin + fCosSize * up; point2 = point2 + fSinSize * right; point3 = origin + (-fSinSize) * up; point3 = point3 + fCosSize * right; point4 = origin + (-fCosSize) * up; point4 = point4 + (-fSinSize) * right; int iContents = 0; g_engfuncs.pTriAPI->Enable( TRI_SHADER ); for ( particle *pDraw = part; pDraw; pDraw = pDraw->m_pOverlay ) { if( pDraw->pType->m_SpriteIndex == 0 ) continue; if ( pDraw->pType->m_iDrawCond ) { if ( iContents == 0 ) iContents = POINT_CONTENTS( origin ); if ( iContents != pDraw->pType->m_iDrawCond ) continue; } int numFrames = GetModelFrames( pDraw->pType->m_SpriteIndex ); // ALERT( at_console, "UpdParticle %d: age %f, life %f, R:%f G:%f, B, %f \n", pDraw->pType->m_hSprite, part->age, part->age_death, pDraw->m_fRed, pDraw->m_fGreen, pDraw->m_fBlue); // if we've reached the end of the sprite's frames, loop back while ( pDraw->frame > numFrames ) pDraw->frame -= numFrames; while ( pDraw->frame < 0 ) pDraw->frame += numFrames; HSPRITE m_hSprite; m_hSprite = g_engfuncs.pTriAPI->GetSpriteTexture( pDraw->pType->m_SpriteIndex, int( pDraw->frame )); g_engfuncs.pTriAPI->RenderMode( pDraw->pType->m_iRenderMode ); g_engfuncs.pTriAPI->Color4f( pDraw->m_fRed, pDraw->m_fGreen, pDraw->m_fBlue, pDraw->m_fAlpha ); g_engfuncs.pTriAPI->Bind( m_hSprite, int( pDraw->frame )); g_engfuncs.pTriAPI->Begin( TRI_QUADS ); g_engfuncs.pTriAPI->TexCoord2f ( 0, 0 ); g_engfuncs.pTriAPI->Vertex3fv( point1 ); g_engfuncs.pTriAPI->TexCoord2f ( 1, 0 ); g_engfuncs.pTriAPI->Vertex3fv ( point2 ); g_engfuncs.pTriAPI->TexCoord2f ( 1, 1 ); g_engfuncs.pTriAPI->Vertex3fv ( point3 ); g_engfuncs.pTriAPI->TexCoord2f ( 0, 1 ); g_engfuncs.pTriAPI->Vertex3fv ( point4 ); g_engfuncs.pTriAPI->End(); } g_engfuncs.pTriAPI->Disable( TRI_SHADER ); }
bool ParticleSystem::UpdateSystem( float frametime ) { // the entity emitting this system edict_t *source = GetEntityByIndex( m_iEntIndex ); if( !source ) return false; // Don't update if the system is outside the player's PVS. enable = (source->v.renderfx == kRenderFxAurora); // check for contents to remove if( POINT_CONTENTS( source->v.origin ) == m_iKillCondition ) { enable = 0; } if( m_pMainParticle == NULL ) { if ( enable ) { ParticleType *pType = m_pMainType; if ( pType ) { m_pMainParticle = pType->CreateParticle( this ); if ( m_pMainParticle ) { m_pMainParticle->m_iEntIndex = m_iEntIndex; m_pMainParticle->age_death = -1; // never die } } } } else if ( !enable ) { m_pMainParticle->age_death = 0; // die now m_pMainParticle = NULL; } particle* pParticle = m_pActiveParticle; particle* pLast = NULL; while( pParticle ) { if ( UpdateParticle( pParticle, frametime )) { pLast = pParticle; pParticle = pParticle->nextpart; } else // deactivate it { if ( pLast ) { pLast->nextpart = pParticle->nextpart; pParticle->nextpart = m_pFreeParticle; m_pFreeParticle = pParticle; pParticle = pLast->nextpart; } else // deactivate the first particle in the list { m_pActiveParticle = pParticle->nextpart; pParticle->nextpart = m_pFreeParticle; m_pFreeParticle = pParticle; pParticle = m_pActiveParticle; } } } return true; }
int UTIL_PointContents( const Vector &vec ) { return POINT_CONTENTS(vec); }
void CParticleSystem :: DrawParticle( CParticle *part, Vector &right, Vector &up ) { float fSize = part->m_fSize; // nothing to draw? if( fSize <= 0 ) return; // frustrum visible check if( !ParticleIsVisible( part )) return; Vector point1, point2, point3, point4; Vector origin = part->origin; float fCosSize = CosLookup( part->m_fAngle ) * fSize; float fSinSize = SinLookup( part->m_fAngle ) * fSize; // calculate the four corners of the sprite point1 = origin + up * fSinSize + right * -fCosSize; point2 = origin + up * fCosSize + right * fSinSize; point3 = origin + up * -fSinSize + right * fCosSize; point4 = origin + up * -fCosSize + right * -fSinSize; int iContents = CONTENTS_NONE; model_t *pModel; for( CParticle *pDraw = part; pDraw; pDraw = pDraw->m_pOverlay ) { if( !pDraw->pType->m_hSprite ) continue; if( pDraw->pType->m_iDrawCond ) { if( pDraw->pType->m_iDrawCond == CONTENT_SPOTLIGHT ) { if( !R_CountPlights( )) continue; // fast reject for( int i = 0; i < MAX_PLIGHTS; i++ ) { plight_t *pl = &cl_plights[i]; if( pl->die < GET_CLIENT_TIME() || !pl->radius ) continue; if( !R_CullSphereExt( pl->frustum, part->origin, part->m_fSize + 1, pl->clipflags )) break; // cone intersected with particle } if( i == MAX_PLIGHTS ) continue; // no intersection } else { if( iContents == CONTENTS_NONE ) iContents = POINT_CONTENTS( origin ); if( iContents != pDraw->pType->m_iDrawCond ) continue; } } pModel = (model_t *)gEngfuncs.GetSpritePointer( pDraw->pType->m_hSprite ); // if we've reached the end of the sprite's frames, loop back while (pDraw->frame > pModel->numframes) pDraw->frame -= pModel->numframes; while (pDraw->frame < 0) pDraw->frame += pModel->numframes; if( !TriSpriteTexture( pModel, (int)pDraw->frame )) continue; gEngfuncs.pTriAPI->RenderMode( pDraw->pType->m_iRenderMode ); if( m_iLightingModel >= 1 ) { color24 lightColor; Vector lightingColor; if( m_iLightingModel == 1 ) R_LightForPoint( part->origin, &lightColor, false, true, fSize + 1 ); else R_LightForPoint( part->origin, &lightColor, false, true, 0.0f ); // FIXME: this code is totally wrong. // We need a fake lightmap here like in sprite implementation lightingColor.x = pDraw->m_fRed * lightColor.r * (1.0f / 255.0f); lightingColor.y = pDraw->m_fGreen * lightColor.g * (1.0f / 255.0f); lightingColor.z = pDraw->m_fBlue * lightColor.b * (1.0f / 255.0f); pglColor4f( lightingColor.x, lightingColor.y, lightingColor.z, pDraw->m_fAlpha ); } else pglColor4f( pDraw->m_fRed, pDraw->m_fGreen, pDraw->m_fBlue, pDraw->m_fAlpha ); pglBegin( GL_QUADS ); pglTexCoord2f( 0.0f, 0.0f ); pglVertex3fv( point1 ); pglTexCoord2f( 1.0f, 0.0f ); pglVertex3fv( point2 ); pglTexCoord2f( 1.0f, 1.0f ); pglVertex3fv( point3 ); pglTexCoord2f( 0.0f, 1.0f ); pglVertex3fv( point4 ); pglEnd(); if( m_iLightingModel >=2 && R_CountPlights( )) { for( int i = 0; i < MAX_PLIGHTS; i++ ) { plight_t *pl = &cl_plights[i]; if( pl->die < GET_CLIENT_TIME() || !pl->radius ) continue; if( R_CullSphereExt( pl->frustum, part->origin, part->m_fSize + 1, pl->clipflags )) continue; R_BeginDrawProjection( pl ); pglBegin( GL_QUADS ); pglVertex3fv( point1 ); pglVertex3fv( point2 ); pglVertex3fv( point3 ); pglVertex3fv( point4 ); pglEnd(); R_EndDrawProjection(); } } } }
AURSTATE CParticleSystem :: UpdateSystem( float frametime ) { if( m_pEntity != NULL ) { // don't update if the system is outside the player's PVS. if( m_pEntity->curstate.messagenum != r_currentMessageNum ) { // but always update rocket particles if( !FBitSet( m_pEntity->curstate.effects, EF_NUKE_ROCKET )) return AURORA_INVISIBLE; } // time-based particle system if( m_fLifeTime != 0.0f ) { enable = (m_fLifeTime >= RI.refdef.time) ? true : false; } else { enable = (m_pEntity->curstate.renderfx == kRenderFxAurora) ? true : false; } // check for contents to remove if( m_iKillCondition == POINT_CONTENTS( m_pEntity->origin )) { m_pEntity = NULL; enable = false; } } else { enable = false; } if( m_pEntity != NULL ) { Vector angles = m_pEntity->angles; // get the system entity matrix if( m_iEntAttachment && m_pEntity->model->type == mod_studio ) entityMatrix.FromVector( R_StudioAttachmentDir( m_pEntity, m_iEntAttachment - 1 )); else entityMatrix = matrix3x3( angles ); } if( m_pMainParticle == NULL ) { if( enable ) { CParticleType *pType = m_pMainType; if( pType ) { m_pMainParticle = pType->CreateParticle( this ); if( m_pMainParticle ) { // first origin initialize if( m_iEntAttachment && m_pEntity->model->type == mod_studio ) m_pMainParticle->origin = R_StudioAttachmentPos( m_pEntity, m_iEntAttachment - 1 ); else m_pMainParticle->origin = m_pEntity->origin; m_pMainParticle->m_pEntity = m_pEntity; m_pMainParticle->age_death = -1.0f; // never die } } } } else if( !enable ) { MarkForDeletion(); } // last particle is died, allow to remove partsystem if( !m_pEntity && !m_pActiveParticle ) return AURORA_REMOVE; CParticle *pParticle = m_pActiveParticle; CParticle *pLast = NULL; while( pParticle ) { if( UpdateParticle( pParticle, frametime )) { pLast = pParticle; pParticle = pParticle->nextpart; } else { // deactivate it if( pLast ) { pLast->nextpart = pParticle->nextpart; pParticle->nextpart = m_pFreeParticle; m_pFreeParticle = pParticle; pParticle = pLast->nextpart; } else { // deactivate the first CParticle in the list m_pActiveParticle = pParticle->nextpart; pParticle->nextpart = m_pFreeParticle; m_pFreeParticle = pParticle; pParticle = m_pActiveParticle; } } } return AURORA_DRAW; }