bool CASWTraceFilterShot::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) { Assert( pHandleEntity ); if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt2 ) ) return false; CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); // don't collide with other projectiles if ( dynamic_cast<CASW_Flamer_Projectile*>( pEntity ) != NULL ) return false; if ( dynamic_cast<CASW_Extinguisher_Projectile*>( pEntity ) != NULL ) return false; if ( pEntity && pEntity->Classify() == CLASS_ASW_MARINE ) { if ( m_bSkipMarines ) return false; CASW_Marine *pMarine = assert_cast<CASW_Marine*>( pEntity ); if ( m_bSkipRollingMarines && pMarine->GetCurrentMeleeAttack() && pMarine->GetCurrentMeleeAttack()->m_nAttackID == CASW_Melee_System::s_nRollAttackID ) return false; if ( m_bSkipMarinesReflectingProjectiles && pMarine->IsReflectingProjectiles() ) return false; } if ( m_bSkipAliens && pEntity && IsAlienClass( pEntity->Classify() ) ) return false; return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); }
//------------------------------------------------------------------------------ // Purpose: Implement impact function //------------------------------------------------------------------------------ void CWeaponCrowbar::Hit( void ) { CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); //Make sound for the AI CSoundEnt::InsertSound( SOUND_BULLET_IMPACT, m_traceHit.endpos, 400, 0.2f, pPlayer ); CBaseEntity *pHitEntity = m_traceHit.m_pEnt; //Apply damage to a hit target if ( pHitEntity != NULL ) { Vector hitDirection; pPlayer->EyeVectors( &hitDirection, NULL, NULL ); VectorNormalize( hitDirection ); ClearMultiDamage(); CTakeDamageInfo info( GetOwner(), GetOwner(), sk_plr_dmg_crowbar.GetFloat(), DMG_CLUB ); CalculateMeleeDamageForce( &info, hitDirection, m_traceHit.endpos ); pHitEntity->DispatchTraceAttack( info, hitDirection, &m_traceHit ); ApplyMultiDamage(); // Now hit all triggers along the ray that... TraceAttackToTriggers( CTakeDamageInfo( GetOwner(), GetOwner(), sk_plr_dmg_crowbar.GetFloat(), DMG_CLUB ), m_traceHit.startpos, m_traceHit.endpos, hitDirection ); //Play an impact sound ImpactSound( pHitEntity->Classify() == CLASS_NONE || pHitEntity->Classify() == CLASS_MACHINE ); } //Apply an impact effect ImpactEffect(); }
//========================================================= // PlayerKilled - someone/something killed this player //========================================================= void CHalfLifeMultiplay :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor ) { DeathNotice( pVictim, pKiller, pInflictor ); pVictim->m_iDeaths += 1; FireTargets( "game_playerdie", pVictim, pVictim, USE_TOGGLE, 0 ); CBasePlayer *peKiller = NULL; CBaseEntity *ktmp = CBaseEntity::Instance( pKiller ); if ( ktmp && (ktmp->Classify() == CLASS_PLAYER) ) peKiller = (CBasePlayer*)ktmp; if ( pVictim->pev == pKiller ) { // Already increment deaths, don't need to lose frags also // killed self //pKiller->frags -= 1; } else if ( ktmp && ktmp->IsPlayer() ) { // if a player dies in a deathmatch game and the killer is a client, award the killer some points pKiller->frags += IPointsForKill( peKiller, pVictim ); FireTargets( "game_playerkill", ktmp, ktmp, USE_TOGGLE, 0 ); } else { // killed by the world pKiller->frags -= 1; } // update the scores // killed scores pVictim->EffectivePlayerClassChanged(); // killers score, if it's a player CBaseEntity *ep = CBaseEntity::Instance( pKiller ); if ( ep && ep->Classify() == CLASS_PLAYER ) { CBasePlayer *PK = (CBasePlayer*)ep; PK->EffectivePlayerClassChanged(); // let the killer paint another decal as soon as he'd like. PK->m_flNextDecalTime = gpGlobals->time; } // Game rules shouldn't know about specific weapons! Removed this because AvH doesn't have satchel charges. //#ifndef HLDEMO_BUILD // if ( pVictim->HasNamedPlayerItem("weapon_satchel") ) // { // DeactivateSatchels( pVictim ); // } //#endif }
//========================================================= // PlayerKilled - someone/something killed this player //========================================================= void CHalfLifeMultiplay :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor ) { DeathNotice( pVictim, pKiller, pInflictor ); pVictim->m_iDeaths += 1; FireTargets( "game_playerdie", pVictim, pVictim, USE_TOGGLE, 0 ); CBasePlayer *peKiller = NULL; CBaseEntity *ktmp = CBaseEntity::Instance( pKiller ); if ( ktmp && (ktmp->Classify() == CLASS_PLAYER) ) peKiller = (CBasePlayer*)ktmp; if ( pVictim->pev == pKiller ) { // killed self pKiller->frags -= 1; } else if ( ktmp && ktmp->IsPlayer() ) { // if a player dies in a deathmatch game and the killer is a client, award the killer some points pKiller->frags += IPointsForKill( peKiller, pVictim ); FireTargets( "game_playerkill", ktmp, ktmp, USE_TOGGLE, 0 ); } else { // killed by the world pVictim->pev->frags -= 1; } // update the scores // killed scores MESSAGE_BEGIN( MSG_ALL, gmsgScoreInfo ); WRITE_BYTE( ENTINDEX(pVictim->edict()) ); WRITE_SHORT( pVictim->pev->frags ); WRITE_SHORT( pVictim->m_iDeaths ); WRITE_SHORT( pVictim->pev->team ); MESSAGE_END(); // killers score, if it's a player CBaseEntity *ep = CBaseEntity::Instance( pKiller ); if ( ep && ep->Classify() == CLASS_PLAYER ) { CBasePlayer *PK = (CBasePlayer*)ep; MESSAGE_BEGIN( MSG_ALL, gmsgScoreInfo ); WRITE_BYTE( ENTINDEX(PK->edict()) ); WRITE_SHORT( PK->pev->frags ); WRITE_SHORT( PK->m_iDeaths ); WRITE_SHORT( PK->pev->team ); MESSAGE_END(); // let the killer paint another decal as soon as he'd like. PK->m_flNextDecalTime = gpGlobals->time; } }
//----------------------------------------------------------------------------- // Purpose: // Input : *pHandleEntity - // contentsMask - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CASW_Trace_Filter_Doors::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) { if ( !StandardFilterRules( pHandleEntity, contentsMask ) ) return false; // Don't test if the game code tells us we should ignore this collision... CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); const CBaseEntity *pEntPass = EntityFromEntityHandle( m_pPassEnt ); // don't hurt ourself if ( pEntPass == pEntity ) return false; if ( !pEntity || pEntity->Classify() != CLASS_ASW_DOOR ) return false; CASW_Door *pDoor = assert_cast<CASW_Door*>( pEntity ); if ( !pDoor ) return false; if ( m_bRequireLockedOrSealed ) { if ( pDoor->GetSealAmount() > 0 || !pDoor->IsAutoOpen() ) { return true; } else { return false; } } return true; }
void CFlame::Fly( void ) { if ( pev->frags <= 0 || UTIL_PointContents(pev->origin) == CONTENT_WATER ) { FX_Trail( pev->origin, entindex(), PROJ_REMOVE ); UTIL_Remove( this ); return; } pev->frags--; entvars_t *pevOwner = VARS(pev->owner); CBaseEntity *pOther = NULL; while ((pOther = UTIL_FindEntityInSphere( pOther, pev->origin, 50 )) != NULL) { if (pOther->edict() != pev->owner && pOther->pev->takedamage && pOther->Classify() != CLASS_MACHINE ) { TraceResult tr; UTIL_TraceLine( pev->origin, pOther->pev->origin, dont_ignore_monsters, ENT(pev), &tr ); CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); ClearMultiDamage( ); pEntity->TraceAttack( pevOwner, pev->dmg/3, pev->velocity, &tr, DMG_IGNITE | DMG_NEVERGIB); ApplyMultiDamage( pev, pevOwner ); } } pev->nextthink = gpGlobals->time + 0.1; }
void CWeaponImmolator::ImmolationDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore ) { CBaseEntity *pEntity = NULL; trace_t tr; Vector vecSpot; Vector vecSrc = vecSrcIn; // iterate on all entities in the vicinity. for ( CEntitySphereQuery sphere( vecSrc, flRadius ); pEntity = sphere.GetCurrentEntity(); sphere.NextEntity() ) { CBaseCombatCharacter *pBCC; pBCC = pEntity->MyCombatCharacterPointer(); if ( pBCC && !pBCC->IsOnFire() ) { // UNDONE: this should check a damage mask, not an ignore if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore ) { continue; } if( pEntity == GetOwner() ) { continue; } pBCC->Ignite( random->RandomFloat( 15, 20 ) ); } } }
void CBlackHole::RadiusDamage( ) { CBaseEntity *pEntity = NULL; TraceResult tr; float flAdjustedDamage; Vector vecSpot; entvars_t *pevOwner = VARS( pev->owner ); Vector vecSrc = pev->origin + Vector(0,0,1); if ( !pevOwner ) pevOwner = pev; CBaseEntity *pPlayer = CBaseEntity::Instance (pevOwner); // iterate on all entities in the vicinity. while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecSrc, (dmg_chrono_radius.value * (mp_wpn_power.value/100)) )) != NULL) { if ( pEntity->pev->movetype != MOVETYPE_PUSH && pEntity->pev->movetype != MOVETYPE_NONE && pEntity->pev->movetype != MOVETYPE_FOLLOW && pEntity->pev->movetype != MOVETYPE_NOCLIP ) { if (pEntity == this) continue; if (CVAR_GET_FLOAT("mp_noselfdamage")==1 && pEntity->pev == pevOwner ) continue; if (CVAR_GET_FLOAT("mp_noteamdamage")==1 && g_pGameRules->PlayerRelationship(pPlayer, pEntity) == GR_TEAMMATE && pEntity->pev != pevOwner) continue; vecSpot = pEntity->BodyTarget( vecSrc ); UTIL_TraceLine ( vecSrc, vecSpot, ignore_monsters, ENT(pev), &tr ); if ( tr.flFraction == 1.0 || tr.pHit == pEntity->edict() ) { flAdjustedDamage = ( vecSrc - tr.vecEndPos ).Length(); if ( flAdjustedDamage < 1 ) flAdjustedDamage = 1; Vector m_vel = ( vecSrc - tr.vecEndPos ).Normalize() * ((500 * (dmg_chrono_radius.value * (mp_wpn_power.value/100)) / flAdjustedDamage) + 150); if (m_vel.Length() > 1000) m_vel = m_vel.Normalize() * 1000; pEntity->pev->velocity = m_vel; if (flAdjustedDamage < 200) { if (!(pEntity->Classify() == CLASS_MACHINE || pEntity->IsBot() || pEntity->IsPlayer() || FClassnameIs(pEntity->pev, "laser_dot") || FClassnameIs(pEntity->pev, "laser_spot"))) { pEntity->Killed ( pevOwner, 0 ); return; } } } } } }
void CASW_Arena::UpdateArena() { // has arena mode just been turned on? if ( !m_bStartedArenaMode ) { for ( int i=0; i< m_ArenaAliens.Count(); i++ ) { UTIL_PrecacheOther( m_ArenaAliens[i]->m_szAlienClass ); } m_bStartedArenaMode = true; m_ArenaRestTimer.Start( 3.0f ); } if ( m_ArenaShuffleWallsTimer.HasStarted() && m_ArenaShuffleWallsTimer.IsElapsed() ) { TeleportPlayersToSpawn(); ShuffleArenaWalls(); m_ArenaShuffleWallsTimer.Invalidate(); m_ArenaRestTimer.Start( 2.5f ); } if ( m_ArenaRestTimer.HasStarted() && m_ArenaRestTimer.IsElapsed() ) { SpawnArenaWave(); m_ArenaRestTimer.Invalidate(); } if ( m_ArenaCheckTimer.HasStarted() && m_ArenaCheckTimer.IsElapsed() ) { // count live aliens CBaseEntity* pEntity = NULL; int iAliens = 0; while ((pEntity = gEntList.NextEnt( pEntity )) != NULL) { if ( pEntity && pEntity->IsNPC() && pEntity->Classify() != CLASS_ASW_MARINE && pEntity->GetHealth() > 0 ) iAliens++; } if ( iAliens <= 0 && !m_ArenaRestTimer.HasStarted() && !m_ArenaShuffleWallsTimer.HasStarted() ) { RefillMarineAmmo(); if ( asw_arena_shuffle_walls.GetInt() > 0 && ( m_iArenaWave % asw_arena_shuffle_walls.GetInt() ) == 0 && ( m_iArenaWave != 0 ) ) { UTIL_CenterPrintAll( UTIL_VarArgs("Wave %d clear!\nThe arena is changing...", m_iArenaWave ) ); m_ArenaShuffleWallsTimer.Start( 5.0f ); } else { UTIL_CenterPrintAll( UTIL_VarArgs("Wave %d clear!", m_iArenaWave ) ); m_ArenaRestTimer.Start( RandomFloat( 8, 12 ) ); } m_ArenaCheckTimer.Invalidate(); } } }
// searches for all our named spawners and adds them to the list void CASW_Spawn_Group::FindSpawners() { for ( int i = 0; i < MAX_SPAWNER_NAMES_PER_GROUP; i++ ) { if ( m_iszSpawnerNames[ i ] == NULL_STRING ) continue; CBaseEntity *pEnt = NULL; while ( ( pEnt = gEntList.FindEntityByName( pEnt, m_iszSpawnerNames[ i ], NULL ) ) != NULL ) { if ( pEnt->Classify() != CLASS_ASW_SPAWNER && pEnt->Classify() != CLASS_ASW_HOLDOUT_SPAWNER ) continue; CASW_Base_Spawner *pSpawner = assert_cast<CASW_Base_Spawner*>( pEnt ); m_hSpawners.AddToTail( pSpawner ); } } }
//========================================================= // PlayerKilled - someone/something killed this player //========================================================= void CHalfLifeMultiplay :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor ) { DeathNotice( pVictim, pKiller, pInflictor ); FireTargets( "game_playerdie", pVictim, pVictim, USE_TOGGLE, 0 ); CBasePlayer *peKiller = NULL; CBaseEntity *ktmp = CBaseEntity::Instance( pKiller ); if ( ktmp && (ktmp->Classify() == CLASS_PLAYER) ) peKiller = (CBasePlayer*)ktmp; CBaseEntity *ep = CBaseEntity::Instance( pKiller ); if ( ep && ep->Classify() == CLASS_PLAYER ) { CBasePlayer *PK = (CBasePlayer*)ep; // let the killer paint another decal as soon as he'd like. PK->m_flNextDecalTime = gpGlobals->time; } }
char UTIL_TextureHit(TraceResult *ptr, Vector vecSrc, Vector vecEnd) { char chTextureType; float rgfl1[3], rgfl2[3]; const char *pTextureName; char szbuffer[64]; CBaseEntity *pEntity; if( ptr->pHit == NULL ) return CHAR_TEX_FLESH; pEntity = CBaseEntity::Instance(ptr->pHit); if (pEntity && pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE) return CHAR_TEX_FLESH; vecSrc.CopyToArray(rgfl1); vecEnd.CopyToArray(rgfl2); if (pEntity) pTextureName = TRACE_TEXTURE(ENT(pEntity->pev), rgfl1, rgfl2); else pTextureName = TRACE_TEXTURE(ENT(0), rgfl1, rgfl2); if (pTextureName) { if (*pTextureName == '-' || *pTextureName == '+') pTextureName += 2; if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ') pTextureName++; strncpy(szbuffer, pTextureName, sizeof(szbuffer)); szbuffer[CBTEXTURENAMEMAX - 1] = 0; chTextureType = PM_FindTextureType(szbuffer); } else chTextureType = 0; return chTextureType; }
void CBasePlayer::UpdateStatusBar() { int newSBarState[ SBAR_END ]; memset( newSBarState, 0, sizeof(newSBarState) ); // Find an ID Target TraceResult tr; UTIL_MakeVectors( pev->v_angle + pev->punchangle ); Vector vecSrc = EyePosition(); Vector vecEnd = vecSrc + (gpGlobals->v_forward * MAX_ID_RANGE); UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, edict(), &tr); if (tr.flFraction != 1.0) { if ( !FNullEnt( tr.pHit ) ) { CBaseEntity *pEntity = CBaseEntity::Instance( tr.pHit ); if ( pEntity->Classify() == CLASS_PLAYER ) { newSBarState[ SBAR_ID_TARGETNAME ] = ENTINDEX( pEntity->edict() ); newSBarState[ SBAR_ID_TARGETTEAM ] = FALSE; m_flStatusBarDisappearDelay = gpGlobals->time + 1.0; } } else if ( m_flStatusBarDisappearDelay > gpGlobals->time ) { // hold the values for a short amount of time after viewing the object newSBarState[ SBAR_ID_TARGETNAME ] = m_izSBarState[ SBAR_ID_TARGETNAME ]; newSBarState[ SBAR_ID_TARGETHEALTH ] = m_izSBarState[ SBAR_ID_TARGETHEALTH ]; newSBarState[ SBAR_ID_TARGETARMOR ] = m_izSBarState[ SBAR_ID_TARGETARMOR ]; newSBarState[ SBAR_ID_TARGETTEAM ] = m_izSBarState[ SBAR_ID_TARGETTEAM ]; } } // Check values and send if they don't match for (int i = 1; i < SBAR_END; i++) { if ( newSBarState[i] != m_izSBarState[i] ) { MESSAGE_BEGIN( MSG_ONE, gmsgStatusValue, NULL, pev ); WRITE_BYTE( i ); WRITE_SHORT( newSBarState[i] ); MESSAGE_END(); m_izSBarState[i] = newSBarState[i]; } } }
//----------------------------------------------------------------------------- // Purpose: Trace filter that only hits anything but NPCs and the player //----------------------------------------------------------------------------- bool CTraceFilterNoNPCsOrPlayer::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) { if ( CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ) ) { CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); if ( !pEntity ) return NULL; #ifndef CLIENT_DLL if ( pEntity->Classify() == CLASS_PLAYER_ALLY ) return false; // CS hostages are CLASS_PLAYER_ALLY but not IsNPC() #endif return (!pEntity->IsNPC() && !pEntity->IsPlayer()); } return false; }
//----------------------------------------------------------------------------- // Purpose: // Input : *pHandleEntity - // contentsMask - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CASW_Trace_Filter_Door_Crush::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) { if ( !StandardFilterRules( pHandleEntity, contentsMask ) ) return false; if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) ) return false; // Don't test if the game code tells us we should ignore this collision... CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); if ( pEntity ) { //Msg("%f CASW_Trace_Filter_Door_Crush::ShouldHitEntity %s\n", gpGlobals->curtime, pEntity->GetClassname()); if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) ) return false; if ( !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) ) return false; if ( pEntity->Classify() == CLASS_ASW_DOOR ) return false; if ( pEntity->m_takedamage == DAMAGE_NO ) return false; // Translate the vehicle into its driver for damage if ( pEntity->GetServerVehicle() != NULL ) { CBaseEntity *pDriver = pEntity->GetServerVehicle()->GetPassenger(); if ( pDriver != NULL ) { pEntity = pDriver; } } Vector attackDir = pEntity->WorldSpaceCenter() - m_dmgInfo->GetAttacker()->WorldSpaceCenter(); VectorNormalize( attackDir ); pEntity->TakeDamage( *m_dmgInfo ); //CalculateMeleeDamageForce( &info, attackDir, info.GetAttacker()->WorldSpaceCenter(), m_flForceScale ); return true; } return false; }
CASW_Spawn_Group* CASW_Holdout_Wave_Entry::GetSpawnGroup() { if ( m_hSpawnGroup.Get() ) { return m_hSpawnGroup.Get(); } CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, m_iszSpawnGroupName ); if ( pEnt && pEnt->Classify() == CLASS_ASW_SPAWN_GROUP ) { m_hSpawnGroup = assert_cast<CASW_Spawn_Group*>( pEnt ); return m_hSpawnGroup.Get(); } Warning( "Holdout wave entry can't find spawngroup %s\n", STRING( m_iszSpawnGroupName ) ); return NULL; }
//----------------------------------------------------------------------------- // Purpose: Trace filter that only hits NPCs and the player //----------------------------------------------------------------------------- bool CTraceFilterOnlyNPCsAndPlayer::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) { if ( CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ) ) { CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); if ( !pEntity ) return false; #ifdef CSTRIKE_DLL #ifndef CLIENT_DLL if ( pEntity->Classify() == CLASS_PLAYER_ALLY ) return true; // CS hostages are CLASS_PLAYER_ALLY but not IsNPC() #endif // !CLIENT_DLL #endif // CSTRIKE_DLL return (pEntity->IsNPC() || pEntity->IsPlayer()); } return false; }
//------------------------------------------------------------------------------ // Purpose: // Input : // Output : //------------------------------------------------------------------------------ void CAI_ASW_MeleeBehavior::HullAttack( float flDistance, float flDamage, float flForce, CUtlSymbol &AttackHitSound, CUtlSymbol &AttackMissSound ) { Vector vecForceDir; CBaseEntity *pHurt = GetOuter()->CheckTraceHullAttack( flDistance, -Vector( 16.0f, 16.0f, 32.0f ), Vector( 16.0f, 16.0f, 32.0f ), flDamage, DMG_SLASH, flForce ); if ( pHurt ) { SetBehaviorParam( m_StatusParm, 1 ); // Play a random attack hit sound if ( AttackHitSound != UTL_INVAL_SYMBOL ) { GetOuter()->EmitSound( GetSymbolText( AttackHitSound ) ); } // change our sequence to one with the hit in it if ( !m_bSecondaryMelee && ( GetActivity() == ACT_MELEE_ATTACK1 ) ) { if ( GetOuter()->HaveSequenceForActivity( (Activity) ACT_MELEE_ATTACK1_HIT ) ) { SetActivity( (Activity) ACT_MELEE_ATTACK1_HIT ); } } else if ( m_bSecondaryMelee && ( GetActivity() == ACT_MELEE_ATTACK2 ) ) { if ( GetOuter()->HaveSequenceForActivity( (Activity) ACT_MELEE_ATTACK2_HIT ) ) { SetActivity( (Activity) ACT_MELEE_ATTACK2_HIT ); } } if ( m_bKnockdown && pHurt->Classify() == CLASS_ASW_MARINE ) { CASW_Marine *pMarine = static_cast<CASW_Marine*>( pHurt ); Vector vecImpulse = ( GetOuter()->BodyDirection2D() * m_flKnockdownSpeed ) + Vector( 0, 0, m_flKnockdownLift ); pMarine->Knockdown( GetOuter(), vecImpulse ); } } else { // Play a miss sound. GetOuter()->EmitSound( GetSymbolText( AttackMissSound ) ); SetBehaviorParam( m_StatusParm, 0 ); } }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- int CNPC_Houndeye::RangeAttack1Conditions ( float flDot, float flDist ) { // I'm not allowed to attack if standing in another hound eye // (note houndeyes allowed to interpenetrate) trace_t tr; AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,0.1), GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); if (tr.startsolid) { CBaseEntity *pEntity = tr.m_pEnt; if (pEntity->Classify() == CLASS_HOUNDEYE) { return( COND_NONE ); } } // If I'm really close to my enemy allow me to attack if // I'm facing regardless of next attack time if (flDist < 100 && flDot >= 0.3) { return COND_CAN_RANGE_ATTACK1; } if ( gpGlobals->curtime < m_flNextAttack ) { return( COND_NONE ); } if (flDist > ( HOUNDEYE_MAX_ATTACK_RADIUS * 0.5 )) { return COND_TOO_FAR_TO_ATTACK; } if (flDot < 0.3) { return COND_NOT_FACING_ATTACK; } return COND_CAN_RANGE_ATTACK1; }
void CGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ) { const int MASK_RADIUS_DAMAGE = MASK_SHOT&(~CONTENTS_HITBOX); CBaseEntity *pEntity = NULL; trace_t tr; float flAdjustedDamage, falloff; Vector vecSpot; Vector vecSrc = vecSrcIn; if ( flRadius ) falloff = info.GetDamage() / flRadius; else falloff = 1.0; int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false; #ifdef HL2_DLL if( bInWater ) { // Only muffle the explosion if deeper than 2 feet in water. if( !(UTIL_PointContents(vecSrc + Vector(0, 0, 24)) & MASK_WATER) ) { bInWater = false; } } #endif // HL2_DLL vecSrc.z += 1;// in case grenade is lying on the ground float flHalfRadiusSqr = Square( flRadius / 2.0f ); // iterate on all entities in the vicinity. for ( CEntitySphereQuery sphere( vecSrc, flRadius ); (pEntity = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) { // This value is used to scale damage when the explosion is blocked by some other object. float flBlockedDamagePercent = 0.0f; if ( pEntity == pEntityIgnore ) continue; if ( pEntity->m_takedamage == DAMAGE_NO ) continue; // UNDONE: this should check a damage mask, not an ignore if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore ) {// houndeyes don't hurt other houndeyes with their attack continue; } // blast's don't tavel into or out of water if (bInWater && pEntity->GetWaterLevel() == 0) continue; if (!bInWater && pEntity->GetWaterLevel() == 3) continue; // Check that the explosion can 'see' this entity. vecSpot = pEntity->BodyTarget( vecSrc, false ); UTIL_TraceLine( vecSrc, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); if( old_radius_damage.GetBool() ) { if ( tr.fraction != 1.0 && tr.m_pEnt != pEntity ) continue; } else { if ( tr.fraction != 1.0 ) { if ( IsExplosionTraceBlocked(&tr) ) { if( ShouldUseRobustRadiusDamage( pEntity ) ) { if( vecSpot.DistToSqr( vecSrc ) > flHalfRadiusSqr ) { // Only use robust model on a target within one-half of the explosion's radius. continue; } Vector vecToTarget = vecSpot - tr.endpos; VectorNormalize( vecToTarget ); // We're going to deflect the blast along the surface that // interrupted a trace from explosion to this target. Vector vecUp, vecDeflect; CrossProduct( vecToTarget, tr.plane.normal, vecUp ); CrossProduct( tr.plane.normal, vecUp, vecDeflect ); VectorNormalize( vecDeflect ); // Trace along the surface that intercepted the blast... UTIL_TraceLine( tr.endpos, tr.endpos + vecDeflect * ROBUST_RADIUS_PROBE_DIST, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); //NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 255, 0, false, 10 ); // ...to see if there's a nearby edge that the explosion would 'spill over' if the blast were fully simulated. UTIL_TraceLine( tr.endpos, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); //NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 0, 0, false, 10 ); if( tr.fraction != 1.0 && tr.DidHitWorld() ) { // Still can't reach the target. continue; } // else fall through } else { continue; } } // UNDONE: Probably shouldn't let children block parents either? Or maybe those guys should set their owner if they want this behavior? // HL2 - Dissolve damage is not reduced by interposing non-world objects if( tr.m_pEnt && tr.m_pEnt != pEntity && tr.m_pEnt->GetOwnerEntity() != pEntity ) { // Some entity was hit by the trace, meaning the explosion does not have clear // line of sight to the entity that it's trying to hurt. If the world is also // blocking, we do no damage. CBaseEntity *pBlockingEntity = tr.m_pEnt; //Msg( "%s may be blocked by %s...", pEntity->GetClassname(), pBlockingEntity->GetClassname() ); UTIL_TraceLine( vecSrc, vecSpot, CONTENTS_SOLID, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); if( tr.fraction != 1.0 ) { continue; } // Now, if the interposing object is physics, block some explosion force based on its mass. if( pBlockingEntity->VPhysicsGetObject() ) { const float MASS_ABSORB_ALL_DAMAGE = 350.0f; float flMass = pBlockingEntity->VPhysicsGetObject()->GetMass(); float scale = flMass / MASS_ABSORB_ALL_DAMAGE; // Absorbed all the damage. if( scale >= 1.0f ) { continue; } ASSERT( scale > 0.0f ); flBlockedDamagePercent = scale; //Msg(" Object (%s) weighing %fkg blocked %f percent of explosion damage\n", pBlockingEntity->GetClassname(), flMass, scale * 100.0f); } else { // Some object that's not the world and not physics. Generically block 25% damage flBlockedDamagePercent = 0.25f; } } } } // decrease damage for an ent that's farther from the bomb. flAdjustedDamage = ( vecSrc - tr.endpos ).Length() * falloff; flAdjustedDamage = info.GetDamage() - flAdjustedDamage; if ( flAdjustedDamage <= 0 ) { continue; } // the explosion can 'see' this entity, so hurt them! if (tr.startsolid) { // if we're stuck inside them, fixup the position and distance tr.endpos = vecSrc; tr.fraction = 0.0; } CTakeDamageInfo adjustedInfo = info; //Msg("%s: Blocked damage: %f percent (in:%f out:%f)\n", pEntity->GetClassname(), flBlockedDamagePercent * 100, flAdjustedDamage, flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) ); adjustedInfo.SetDamage( flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) ); // Now make a consideration for skill level! if( info.GetAttacker() && info.GetAttacker()->IsPlayer() && pEntity->IsNPC() ) { // An explosion set off by the player is harming an NPC. Adjust damage accordingly. adjustedInfo.AdjustPlayerDamageInflictedForSkillLevel(); } Vector dir = vecSpot - vecSrc; VectorNormalize( dir ); // If we don't have a damage force, manufacture one if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin ) { if ( !( adjustedInfo.GetDamageType() & DMG_PREVENT_PHYSICS_FORCE ) ) { CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc ); } } else { // Assume the force passed in is the maximum force. Decay it based on falloff. float flForce = adjustedInfo.GetDamageForce().Length() * falloff; adjustedInfo.SetDamageForce( dir * flForce ); adjustedInfo.SetDamagePosition( vecSrc ); } if ( tr.fraction != 1.0 && pEntity == tr.m_pEnt ) { ClearMultiDamage( ); pEntity->DispatchTraceAttack( adjustedInfo, dir, &tr ); ApplyMultiDamage(); } else { pEntity->TakeDamage( adjustedInfo ); } // Now hit all triggers along the way that respond to damage... pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, tr.endpos, dir ); #if defined( GAME_DLL ) if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() && ToBaseCombatCharacter( tr.m_pEnt ) ) { // This is a total hack!!! bool bIsPrimary = true; CBasePlayer *player = ToBasePlayer( info.GetAttacker() ); CBaseCombatWeapon *pWeapon = player->GetActiveWeapon(); if ( pWeapon && FClassnameIs( pWeapon, "weapon_smg1" ) ) { bIsPrimary = false; } //gamestats->Event_WeaponHit( player, bIsPrimary, (pWeapon != NULL) ? player->GetActiveWeapon()->GetClassname() : "NULL", info ); } #endif } }
//------------------------------------------------------------------------------ // Purpose: general purpose routine to collect conditions used both during active // and non-active states of the behavior. //------------------------------------------------------------------------------ void CAI_ASW_HealOtherBehavior::GatherCommonConditions( ) { BaseClass::GatherCommonConditions(); // ClearCondition( COND_HEAL_OTHER_HAS_TARGET ); SetCondition( COND_HEAL_OTHER_NOT_HAS_TARGET ); ClearCondition( COND_HEAL_OTHER_TARGET_CHANGED ); ClearCondition( COND_HEAL_OTHER_TARGET_IN_RANGE ); ClearCondition( COND_HEAL_OTHER_NOT_TARGET_IN_RANGE ); CBaseEntity *pBestObject = NULL; int nPotentialHealthBenefit = 0; for( int i = 0; i < GetOuter()->GetNumFactions(); i++ ) { if ( GetOuter()->GetFactionRelationshipDisposition( i ) == D_LIKE ) { CUtlVector< EHANDLE > *pEntityList = GetOuter()->GetEntitiesInFaction( i ); for( int j = 0; j < pEntityList->Count(); j++ ) { CBaseEntity *pEntity = pEntityList->Element( j ); if ( pEntity->GetHealth() <= 0 ) continue; Class_T entClass = pEntity->Classify(); if ( entClass == CLASS_ASW_SHAMAN || entClass == CLASS_ASW_BOOMER || entClass == CLASS_ASW_BOOMERMINI || entClass == CLASS_ASW_PARASITE || entClass == CLASS_ASW_BLOB || entClass == CLASS_ASW_BUZZER || entClass == CLASS_ASW_RUNNER ) { continue; } if ( GetOuter() != pEntity ) { Vector vDiff = pEntity->GetAbsOrigin() - GetAbsOrigin(); float flLengthSquared = vDiff.LengthSqr(); if ( flLengthSquared <= m_flHealConsiderationDistanceSquared ) //&& ( !asw_shaman_only_heal_hurt_pEntity->m_iHealth < pEntity->m_iMaxHealth ) { if ( nPotentialHealthBenefit == 0 || ( pEntity->m_iMaxHealth - pEntity->m_iHealth ) > nPotentialHealthBenefit ) { nPotentialHealthBenefit = ( pEntity->m_iMaxHealth - pEntity->m_iHealth ); pBestObject = pEntity; } } } } } } if ( pBestObject ) { if ( m_hHealTargetEnt != NULL && m_hHealTargetEnt != pBestObject ) { SetCondition( COND_HEAL_OTHER_TARGET_CHANGED ); } // SetCondition( COND_HEAL_OTHER_HAS_TARGET ); ClearCondition( COND_HEAL_OTHER_NOT_HAS_TARGET ); m_hHealTargetEnt = pBestObject; if ( m_hHealTargetEnt.Get() ) { Vector vPredictedPos = m_hHealTargetEnt->GetAbsOrigin() + m_hHealTargetEnt->GetAbsVelocity() * asw_shaman_aim_ahead_time.GetFloat(); Vector vDiff = vPredictedPos - GetAbsOrigin(); if ( vDiff.Length() < m_flHealDistance ) { SetCondition( COND_HEAL_OTHER_TARGET_IN_RANGE ); } else { SetCondition( COND_HEAL_OTHER_NOT_TARGET_IN_RANGE ); } } } else { if ( m_hHealTargetEnt != NULL && m_hHealTargetEnt != pBestObject ) { SetCondition( COND_HEAL_OTHER_TARGET_CHANGED ); } m_hHealTargetEnt = NULL; } }
CBaseEntity * CASW_Rocket::FindPotentialTarget( void ) const { float bestdist = 0; CBaseEntity *bestent = NULL; Vector v_forward, v_right, v_up; AngleVectors( GetAbsAngles(), &v_forward, &v_right, &v_up ); // find the aimtarget nearest us int count = AimTarget_ListCount(); if ( count ) { CBaseEntity **pList = (CBaseEntity **)stackalloc( sizeof(CBaseEntity *) * count ); AimTarget_ListCopy( pList, count ); CTraceFilterSkipTwoEntities filter(this, GetOwnerEntity(), COLLISION_GROUP_NONE); for ( int i = 0; i < count; i++ ) { CBaseEntity *pEntity = pList[i]; if (!pEntity || !pEntity->IsAlive() || !pEntity->edict() || !pEntity->IsNPC() ) { //Msg("not alive or not an edict, skipping\n"); continue; } if (!pEntity || !pEntity->IsAlive() || !pEntity->edict() || !pEntity->IsNPC() ) { //Msg("not alive or not an edict, skipping\n"); continue; } // don't autoaim onto marines if (pEntity->Classify() == CLASS_ASW_MARINE || pEntity->Classify() == CLASS_ASW_COLONIST) continue; if ( pEntity->Classify() == CLASS_ASW_PARASITE ) { CASW_Parasite *pParasite = static_cast< CASW_Parasite* >( pEntity ); if ( pParasite->m_bInfesting ) { continue; } } Vector center = pEntity->BodyTarget( GetAbsOrigin() ); Vector center_flat = center; center_flat.z = GetAbsOrigin().z; Vector dir = (center - GetAbsOrigin()); VectorNormalize( dir ); Vector dir_flat = (center_flat - GetAbsOrigin()); VectorNormalize( dir_flat ); // make sure it's in front of the rocket float dot = DotProduct (dir, v_forward ); //if (dot < 0) //{ //continue; //} float dist = (pEntity->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); if (dist > ASW_ROCKET_MAX_HOMING_RANGE) continue; // check another marine isn't between us and the target to reduce FF trace_t tr; UTIL_TraceLine(GetAbsOrigin(), pEntity->WorldSpaceCenter(), MASK_SHOT, &filter, &tr); if (tr.fraction < 1.0f && tr.m_pEnt != pEntity && tr.m_pEnt && tr.m_pEnt->Classify() == CLASS_ASW_MARINE) continue; // does this critter already have enough rockets to kill it? { CASW_DamageAllocationMgr::IndexType_t assignmentIndex = m_RocketAssigner.Find( pEntity ); if ( m_RocketAssigner.IsValid(assignmentIndex) ) { if ( m_RocketAssigner[assignmentIndex].m_flAccumulatedDamage > pEntity->GetHealth() ) { continue; } } } // check another marine isn't between us and the target to reduce FF UTIL_TraceLine(GetAbsOrigin(), pEntity->WorldSpaceCenter(), MASK_SHOT, &filter, &tr); if (tr.fraction < 1.0f && tr.m_pEnt != pEntity && tr.m_pEnt && tr.m_pEnt->Classify() == CLASS_ASW_MARINE) continue; // increase distance if dot isn't towards us dist += (1.0f - dot) * 150; // bias of x units when object is 90 degrees to the side if (bestdist == 0 || dist < bestdist) { bestdist = dist; bestent = pEntity; } } if ( bestent && asw_rocket_debug.GetBool() ) { Vector center = bestent->BodyTarget( GetAbsOrigin() ); Vector center_flat = center; center_flat.z = GetAbsOrigin().z; Vector dir = (center - GetAbsOrigin()); VectorNormalize( dir ); Msg( "Rocket[%d] starting homing in on %s(%d) dir = %f %f %f\n", entindex(), bestent->GetClassname(), bestent->entindex(), VectorExpand( dir ) ); } } return bestent; }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CNPC_Monk::GatherConditions() { BaseClass::GatherConditions(); // Build my zombie danger index! m_iNumZombies = 0; m_iDangerousZombies = 0; AISightIter_t iter; CBaseEntity *pSightEnt; pSightEnt = GetSenses()->GetFirstSeenEntity( &iter ); while( pSightEnt ) { if( pSightEnt->Classify() == CLASS_ZOMBIE && pSightEnt->IsAlive() ) { // Is this zombie coming for me? CAI_BaseNPC *pZombie = dynamic_cast<CAI_BaseNPC*>(pSightEnt); if( pZombie && pZombie->GetEnemy() == this ) { m_iNumZombies++; // if this zombie is close enough to attack, add him to the zombie danger! float flDist; flDist = (pZombie->GetAbsOrigin() - GetAbsOrigin()).Length2DSqr(); if( flDist <= 128.0f * 128.0f ) { m_iDangerousZombies++; } } } pSightEnt = GetSenses()->GetNextSeenEntity( &iter ); } if( m_iDangerousZombies >= 3 || (GetEnemy() && GetHealth() < 25) ) { // I see many zombies, or I'm quite injured. SpeakIfAllowed( TLK_HELP_ME ); } // NOTE!!!!!! This code assumes grigori is using annabelle! ClearCondition(COND_LOW_PRIMARY_AMMO); if ( GetActiveWeapon() ) { if ( GetActiveWeapon()->UsesPrimaryAmmo() ) { if (!GetActiveWeapon()->HasPrimaryAmmo() ) { SetCondition(COND_NO_PRIMARY_AMMO); } else if ( m_NPCState != NPC_STATE_COMBAT && GetActiveWeapon()->UsesClipsForAmmo1() && GetActiveWeapon()->Clip1() < 2 ) { // Don't send a low ammo message unless we're not in combat. SetCondition(COND_LOW_PRIMARY_AMMO); } } } }
// Add the ability to ignore the world trace void CSDKGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, bool bIgnoreWorld ) { CBaseEntity *pEntity = NULL; trace_t tr; float flAdjustedDamage, falloff; Vector vecSpot; Vector vecToTarget; Vector vecEndPos; Vector vecSrc = vecSrcIn; if ( flRadius ) falloff = info.GetDamage() / flRadius; else falloff = 1.0; int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false; vecSrc.z += 1;// in case grenade is lying on the ground // iterate on all entities in the vicinity. for ( CEntitySphereQuery sphere( vecSrc, flRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) { if ( pEntity->m_takedamage != DAMAGE_NO ) { // UNDONE: this should check a damage mask, not an ignore if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore ) {// houndeyes don't hurt other houndeyes with their attack continue; } // blast's don't tavel into or out of water if (bInWater && pEntity->GetWaterLevel() == 0) continue; if (!bInWater && pEntity->GetWaterLevel() == 3) continue; // radius damage can only be blocked by the world vecSpot = pEntity->BodyTarget( vecSrc ); bool bHit = false; if( bIgnoreWorld ) { vecEndPos = vecSpot; bHit = true; } else { UTIL_TraceLine( vecSrc, vecSpot, MASK_SOLID_BRUSHONLY, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); if (tr.startsolid) { // if we're stuck inside them, fixup the position and distance tr.endpos = vecSrc; tr.fraction = 0.0; } vecEndPos = tr.endpos; if( tr.fraction == 1.0 || tr.m_pEnt == pEntity ) { bHit = true; } } if ( bHit ) { // the explosion can 'see' this entity, so hurt them! //vecToTarget = ( vecSrc - vecEndPos ); vecToTarget = ( vecEndPos - vecSrc ); // decrease damage for an ent that's farther from the bomb. flAdjustedDamage = vecToTarget.Length() * falloff; flAdjustedDamage = info.GetDamage() - flAdjustedDamage; if ( flAdjustedDamage > 0 ) { CTakeDamageInfo adjustedInfo = info; adjustedInfo.SetDamage( flAdjustedDamage ); Vector dir = vecToTarget; VectorNormalize( dir ); // If we don't have a damage force, manufacture one if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin ) { CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc, 1.5 /* explosion scale! */ ); } else { // Assume the force passed in is the maximum force. Decay it based on falloff. float flForce = adjustedInfo.GetDamageForce().Length() * falloff; adjustedInfo.SetDamageForce( dir * flForce ); adjustedInfo.SetDamagePosition( vecSrc ); } pEntity->TakeDamage( adjustedInfo ); // Now hit all triggers along the way that respond to damage... pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, vecEndPos, dir ); } } } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponHarpoon::SecondaryAttack( void ) { CBasePlayer *pPlayer = dynamic_cast<CBasePlayer*>( GetOwner() ); if ( !pPlayer ) return; // Slap things in front of me Vector vecForward; Vector vecBox = Vector( FIST_RANGE,FIST_RANGE,FIST_RANGE * 1.5 ) * 0.5; pPlayer->EyeVectors( &vecForward ); Vector vecSrc = pPlayer->Weapon_ShootPosition( ); Vector vecCenter = vecSrc + (FIST_RANGE * 0.5 * vecForward); #if !defined( CLIENT_DLL ) //NDebugOverlay::Box( vecCenter, -Vector(2,2,2), Vector(2,2,2), 255,0,0,20,2.0); //NDebugOverlay::Box( vecCenter, -vecBox, vecBox, 255,255,255,20,2.0); bool bHitMetal = false; bool bHitPlayer = false; CBaseEntity *pList[100]; int count = UTIL_EntitiesInBox( pList, 100, vecSrc - vecBox, vecSrc + vecBox, FL_CLIENT|FL_NPC|FL_OBJECT ); for ( int i = 0; i < count; i++ ) { CBaseEntity *pEntity = pList[i]; if ( !pEntity->m_takedamage ) continue; if ( pEntity->InSameTeam( this ) ) continue; //NDebugOverlay::EntityBounds( pEntity, 0,255,0,20,2.0); if ( pEntity->IsPlayer() ) { bHitPlayer = true; CTakeDamageInfo info( this, pPlayer, weapon_fist_damage.GetFloat(), DMG_CLUB ); CalculateMeleeDamageForce( &info, (pEntity->GetAbsOrigin() - vecCenter), pEntity->GetAbsOrigin() ); pEntity->TakeDamage( info ); } else if ( pEntity->Classify() == CLASS_MILITARY ) { bHitMetal = true; CTakeDamageInfo info( this, pPlayer, weapon_fist_damage_objects.GetFloat(), DMG_CLUB ); CalculateMeleeDamageForce( &info, (pEntity->GetAbsOrigin() - vecCenter), pEntity->GetAbsOrigin() ); pEntity->TakeDamage( info ); } else { bHitMetal = true; CTakeDamageInfo info( this, pPlayer, weapon_fist_damage.GetFloat(), DMG_CLUB ); CalculateMeleeDamageForce( &info, (pEntity->GetAbsOrigin() - vecCenter), pEntity->GetAbsOrigin() ); pEntity->TakeDamage( info ); } } // Play the right sound if ( bHitPlayer ) { EmitSound( "Harpoon.HitFlesh" ); } else if ( bHitMetal ) { EmitSound( "Harpoon.HitMetal" ); } #endif }
void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType ) { CBaseEntity *pEntity = NULL; TraceResult tr; float flAdjustedDamage, falloff; Vector vecSpot; if ( flRadius ) falloff = flDamage / flRadius; else falloff = 1.0; int bInWater = (UTIL_PointContents ( vecSrc ) == CONTENTS_WATER); vecSrc.z += 1;// in case grenade is lying on the ground if ( !pevAttacker ) pevAttacker = pevInflictor; // iterate on all entities in the vicinity. while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecSrc, flRadius )) != NULL) { if ( pEntity->pev->takedamage != DAMAGE_NO ) { // UNDONE: this should check a damage mask, not an ignore if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore ) {// houndeyes don't hurt other houndeyes with their attack continue; } // blast's don't tavel into or out of water if (bInWater && pEntity->pev->waterlevel == 0) continue; if (!bInWater && pEntity->pev->waterlevel == 3) continue; vecSpot = pEntity->BodyTarget( vecSrc ); UTIL_TraceLine ( vecSrc, vecSpot, dont_ignore_monsters, ENT(pevInflictor), &tr ); if ( tr.flFraction == 1.0 || tr.pHit == pEntity->edict() ) {// the explosion can 'see' this entity, so hurt them! if (tr.fStartSolid) { // if we're stuck inside them, fixup the position and distance tr.vecEndPos = vecSrc; tr.flFraction = 0.0; } // decrease damage for an ent that's farther from the bomb. flAdjustedDamage = ( vecSrc - tr.vecEndPos ).Length() * falloff; flAdjustedDamage = flDamage - flAdjustedDamage; if ( flAdjustedDamage < 0 ) { flAdjustedDamage = 0; } // ALERT( at_console, "hit %s\n", STRING( pEntity->pev->classname ) ); if (tr.flFraction != 1.0) { ClearMultiDamage( ); pEntity->TraceAttack( pevInflictor, flAdjustedDamage, (tr.vecEndPos - vecSrc).Normalize( ), &tr, bitsDamageType ); ApplyMultiDamage( pevInflictor, pevAttacker ); } else { pEntity->TakeDamage ( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType ); } } } } }
void CGargantua :: FlameDamage( Vector vecStart, Vector vecEnd, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType ) { CBaseEntity *pEntity = NULL; TraceResult tr; float flAdjustedDamage; Vector vecSpot; Vector vecMid = (vecStart + vecEnd) * 0.5; float searchRadius = (vecStart - vecMid).Length(); Vector vecAim = (vecEnd - vecStart).Normalize( ); // iterate on all entities in the vicinity. while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecMid, searchRadius )) != NULL) { if ( pEntity->pev->takedamage != DAMAGE_NO ) { // UNDONE: this should check a damage mask, not an ignore if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore ) {// houndeyes don't hurt other houndeyes with their attack continue; } vecSpot = pEntity->BodyTarget( vecMid ); float dist = DotProduct( vecAim, vecSpot - vecMid ); if (dist > searchRadius) dist = searchRadius; else if (dist < -searchRadius) dist = searchRadius; Vector vecSrc = vecMid + dist * vecAim; UTIL_TraceLine ( vecSrc, vecSpot, dont_ignore_monsters, ENT(pev), &tr ); if ( tr.flFraction == 1.0 || tr.pHit == pEntity->edict() ) {// the explosion can 'see' this entity, so hurt them! // decrease damage for an ent that's farther from the flame. dist = ( vecSrc - tr.vecEndPos ).Length(); if (dist > 64) { flAdjustedDamage = flDamage - (dist - 64) * 0.4; if (flAdjustedDamage <= 0) continue; } else { flAdjustedDamage = flDamage; } // ALERT( at_console, "hit %s\n", STRING( pEntity->pev->classname ) ); if (tr.flFraction != 1.0) { ClearMultiDamage( ); pEntity->TraceAttack( pevInflictor, flAdjustedDamage, (tr.vecEndPos - vecSrc).Normalize( ), &tr, bitsDamageType ); ApplyMultiDamage( pevInflictor, pevAttacker ); } else { pEntity->TakeDamage ( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType ); } } } } }
int CCrowbar::Swing( int fFirst ) { int fDidHit = FALSE; TraceResult tr; UTIL_MakeVectors (m_pPlayer->pev->v_angle); Vector vecSrc = m_pPlayer->GetGunPosition( ); Vector vecEnd = vecSrc + gpGlobals->v_forward * 32; UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr ); #ifndef CLIENT_DLL if ( tr.flFraction >= 1.0 ) { UTIL_TraceHull( vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT( m_pPlayer->pev ), &tr ); if ( tr.flFraction < 1.0 ) { // Calculate the point of intersection of the line (or hull) and the object we hit // This is and approximation of the "best" intersection CBaseEntity *pHit = CBaseEntity::Instance( tr.pHit ); if ( !pHit || pHit->IsBSPModel() ) FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict() ); vecEnd = tr.vecEndPos; // This is the point on the actual surface (the hull could have hit space) } } #endif PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usCrowbar, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0.0, 0, 0.0 ); if ( tr.flFraction >= 1.0 ) { if (fFirst) { // miss m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5; // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); } } else { switch( ((m_iSwing++) % 2) + 1 ) { case 0: SendWeaponAnim( CROWBAR_ATTACK1HIT ); break; case 1: SendWeaponAnim( CROWBAR_ATTACK2HIT ); break; case 2: SendWeaponAnim( CROWBAR_ATTACK3HIT ); break; } // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); #ifndef CLIENT_DLL // hit fDidHit = TRUE; CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); ClearMultiDamage( ); if ( (m_flNextPrimaryAttack + 1 < UTIL_WeaponTimeBase() ) || g_pGameRules->IsMultiplayer() ) { // first swing does full damage pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgCrowbar, gpGlobals->v_forward, &tr, DMG_CLUB ); } else { // subsequent swings do half pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgCrowbar / 2, gpGlobals->v_forward, &tr, DMG_CLUB ); } ApplyMultiDamage( m_pPlayer->pev, m_pPlayer->pev ); // play thwack, smack, or dong sound float flVol = 1.0; int fHitWorld = TRUE; if (pEntity) { if ( pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE ) { // play thwack or smack sound switch( RANDOM_LONG(0,2) ) { case 0: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM); break; case 1: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod2.wav", 1, ATTN_NORM); break; case 2: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod3.wav", 1, ATTN_NORM); break; } m_pPlayer->m_iWeaponVolume = CROWBAR_BODYHIT_VOLUME; if ( !pEntity->IsAlive() ) return TRUE; else flVol = 0.1; fHitWorld = FALSE; } } // play texture hit sound // UNDONE: Calculate the correct point of intersection when we hit with the hull instead of the line if (fHitWorld) { float fvolbar = TEXTURETYPE_PlaySound(&tr, vecSrc, vecSrc + (vecEnd-vecSrc)*2, BULLET_PLAYER_CROWBAR); if ( g_pGameRules->IsMultiplayer() ) { // override the volume here, cause we don't play texture sounds in multiplayer, // and fvolbar is going to be 0 from the above call. fvolbar = 1; } // also play crowbar strike switch( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit1.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); break; case 1: EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit2.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); break; } // delay the decal a bit m_trHit = tr; } m_pPlayer->m_iWeaponVolume = flVol * CROWBAR_WALLHIT_VOLUME; #endif m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.25; SetThink( &CCrowbar::Smack ); pev->nextthink = UTIL_WeaponTimeBase() + 0.2; } return fDidHit; }
//========================================================= // SonicAttack //========================================================= void CNPC_Houndeye::SonicAttack ( void ) { EmitSound( "NPC_Houndeye.SonicAttack" ); if (m_pEnergyWave) { UTIL_Remove(m_pEnergyWave); } Vector vFacingDir = EyeDirection3D( ); m_pEnergyWave = (CEnergyWave*)Create( "energy_wave", EyePosition(), GetLocalAngles() ); m_flEndEnergyWaveTime = gpGlobals->curtime + 1; //<<TEMP>> magic m_pEnergyWave->SetAbsVelocity( 100*vFacingDir ); CBaseEntity *pEntity = NULL; // iterate on all entities in the vicinity. for ( CEntitySphereQuery sphere( GetAbsOrigin(), HOUNDEYE_MAX_ATTACK_RADIUS ); pEntity = sphere.GetCurrentEntity(); sphere.NextEntity() ) { if (pEntity->Classify() == CLASS_HOUNDEYE) { continue; } if (pEntity->GetFlags() & FL_NOTARGET) { continue; } IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); if ( pEntity->m_takedamage != DAMAGE_NO || pPhysicsObject) { // -------------------------- // Adjust damage by distance // -------------------------- float flDist = (pEntity->WorldSpaceCenter() - GetAbsOrigin()).Length(); float flDamageAdjuster = 1-( flDist / HOUNDEYE_MAX_ATTACK_RADIUS ); // -------------------------- // Adjust damage by direction // -------------------------- Vector forward; AngleVectors( GetAbsAngles(), &forward ); Vector vEntDir = (pEntity->GetAbsOrigin() - GetAbsOrigin()); VectorNormalize(vEntDir); float flDotPr = DotProduct(forward,vEntDir); flDamageAdjuster *= flDotPr; if (flDamageAdjuster < 0) { continue; } // -------------------------- // Adjust damage by visibility // -------------------------- if ( !FVisible( pEntity ) ) { if ( pEntity->IsPlayer() ) { // if this entity is a client, and is not in full view, inflict half damage. We do this so that players still // take the residual damage if they don't totally leave the houndeye's effective radius. We restrict it to clients // so that monsters in other parts of the level don't take the damage and get pissed. flDamageAdjuster *= 0.5; } else if ( !FClassnameIs( pEntity, "func_breakable" ) && !FClassnameIs( pEntity, "func_pushable" ) ) { // do not hurt nonclients through walls, but allow damage to be done to breakables continue; } } // ------------------------------ // Apply the damage // ------------------------------ if (pEntity->m_takedamage != DAMAGE_NO) { CTakeDamageInfo info( this, this, flDamageAdjuster * sk_Houndeye_dmg_blast.GetFloat(), DMG_SONIC | DMG_ALWAYSGIB ); CalculateExplosiveDamageForce( &info, (pEntity->GetAbsOrigin() - GetAbsOrigin()), pEntity->GetAbsOrigin() ); pEntity->TakeDamage( info ); // Throw the player if ( pEntity->IsPlayer() ) { Vector forward; AngleVectors( GetLocalAngles(), &forward ); Vector vecVelocity = pEntity->GetAbsVelocity(); vecVelocity += forward * 250 * flDamageAdjuster; vecVelocity.z = 300 * flDamageAdjuster; pEntity->SetAbsVelocity( vecVelocity ); pEntity->ViewPunch( QAngle(random->RandomInt(-20,20), 0, random->RandomInt(-20,20)) ); } } // ------------------------------ // Apply physics foces // ------------------------------ IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); if (pPhysicsObject) { float flForce = flDamageAdjuster * 8000; pPhysicsObject->ApplyForceCenter( (vEntDir+Vector(0,0,0.2)) * flForce ); pPhysicsObject->ApplyTorqueCenter( vEntDir * flForce ); } } } }
//----------------------------------------------------------------------------- // Purpose: Intercept damage and decide whether or not we want to trigger // Input : &info - //----------------------------------------------------------------------------- int CWeaponStriderBuster::OnTakeDamage( const CTakeDamageInfo &info ) { // If we're attached, any damage from the player makes us trigger CBaseEntity *pInflictor = info.GetInflictor(); CBaseEntity *pAttacker = info.GetAttacker(); bool bInflictorIsPlayer = ( pInflictor != NULL && pInflictor->IsPlayer() ); bool bAttackerIsPlayer = ( pAttacker != NULL && pAttacker->IsPlayer() ); if ( GetParent() && GetParent()->ClassMatches( g_iszVehicle ) ) { return 0; } // Only take damage from a player, for the moment if ( striderbuster_allow_all_damage.GetBool() || ( IsAttachedToStrider() && ( bAttackerIsPlayer || bInflictorIsPlayer ) ) ) { Detonate(); return 0; } if ( pAttacker && ( pAttacker->Classify() == CLASS_COMBINE || pAttacker->Classify() == CLASS_COMBINE_HUNTER ) ) { if ( VPhysicsGetObject() && !VPhysicsGetObject()->IsMoveable() ) { return 0; } } // Hunters are able to destroy strider busters if ( hunter_hate_held_striderbusters.GetBool() || hunter_hate_thrown_striderbusters.GetBool() || hunter_hate_attached_striderbusters.GetBool() ) { if ( ( GetHealth() > 0 ) && ( pInflictor != NULL ) && FClassnameIs( pInflictor, "hunter_flechette" ) ) { // // Flechette impacts don't hurt the striderbuster unless it's attached to a strider, // but the explosions always do. This is so that held or thrown striderbusters fly // awry because of the flechette, but attached striderbusters break instantly to make // the hunters more effective at defending the strider. // if ( IsAttachedToStrider() || !( info.GetDamageType() & DMG_NEVERGIB ) ) { if( striderbuster_die_detach.GetBool() && IsAttachedToStrider() ) { // Make the buster fall off and break. m_takedamage = DAMAGE_NO; CNPC_Strider *pStrider = dynamic_cast<CNPC_Strider *>(GetOwnerEntity()); Assert( pStrider != NULL ); pStrider->StriderBusterDetached( this ); DestroyConstraint(); // Amplify some lateral force. Vector vecForce = info.GetDamageForce(); vecForce.z = 0.0f; VPhysicsGetObject()->ApplyForceCenter( vecForce * 5.0f ); SetContextThink( NULL, gpGlobals->curtime, s_pBusterPingThinkContext ); SetThink( &CWeaponStriderBuster::BusterDetachThink ); SetNextThink( gpGlobals->curtime ); m_iBusterFlags |= STRIDERBUSTER_FLAG_KNOCKED_OFF_STRIDER; return 0; } else { // Destroy the buster in place // Make sure they know it blew up prematurely. EmitSound( "Weapon_StriderBuster.Dud_Detonate" ); DispatchParticleEffect( "striderbuster_break_flechette", GetAbsOrigin(), GetAbsAngles() ); SetHealth( 0 ); Shatter( info.GetAttacker() ); return 0; } } if ( info.GetDamage() < 5 ) { bool bFirst = ( m_CarryAngles.x == 45 && m_CarryAngles.y == 0 && m_CarryAngles.z == 0); float sinTime = sin( gpGlobals->curtime ); bool bSubtractX = ( bFirst ) ? ( sinTime < 0 ) : ( m_CarryAngles.x < 45 ); m_CarryAngles.x += ( 10.0 + 10.0 * fabsf( sinTime ) + random->RandomFloat( -2.5, 2.5 ) + random->RandomFloat( -2.5, 2.5 ) ) * ( ( bSubtractX ) ? -1.0 : 1.0 ); m_CarryAngles.y = 15 * ( sin( gpGlobals->curtime ) + cos( gpGlobals->curtime * 0.5 ) ) * .5 + random->RandomFloat( -15, 15 ); m_CarryAngles.z = 7.5 * ( sin( gpGlobals->curtime ) + sin( gpGlobals->curtime * 2.0 ) ) * .5 + random->RandomFloat( -7.5, 7.5 ); } return 1; } } // Allow crushing damage if ( info.GetDamageType() & DMG_CRUSH ) return BaseClass::OnTakeDamage( info ); return 0; }