void CBreakable::Spawn( void ) { Precache( ); if ( FBitSet( pev->spawnflags, SF_BREAK_TRIGGER_ONLY ) ) pev->takedamage = DAMAGE_NO; else pev->takedamage = DAMAGE_YES; pev->solid = SOLID_BSP; pev->movetype = MOVETYPE_PUSH; m_angle = pev->angles.y; pev->angles.y = 0; SET_MODEL(ENT(pev), STRING(pev->model) );//set size and link into world. SetTouch( &CBreakable::BreakTouch ); if ( FBitSet( pev->spawnflags, SF_BREAK_TRIGGER_ONLY ) ) // Only break on trigger SetTouch( NULL ); // Flag unbreakable glass as "worldbrush" so it will block ALL tracelines if ( !IsBreakable() && pev->rendermode != kRenderNormal ) pev->flags |= FL_WORLDBRUSH; }
void CBreakable::Restart() { pev->solid = SOLID_BSP; pev->movetype = MOVETYPE_PUSH; pev->deadflag = DEAD_NO; if (pev->spawnflags & SF_BREAK_TRIGGER_ONLY) pev->takedamage = DAMAGE_NO; else pev->takedamage = DAMAGE_YES; pev->health = m_flHealth; pev->effects &= ~EF_NODRAW; m_angle = pev->angles.y; pev->angles.y = 0; SET_MODEL(ENT(pev), STRING(pev->model)); SetTouch(&CBreakable::BreakTouch); if (pev->spawnflags & SF_BREAK_TRIGGER_ONLY) { SetTouch(NULL); } if (!IsBreakable() && pev->rendermode != kRenderNormal) { pev->flags |= FL_WORLDBRUSH; } }
void CBreakable::Spawn( void ) { Precache( ); if ( FBitSet( pev->spawnflags, SF_BREAK_TRIGGER_ONLY ) ) pev->takedamage = DAMAGE_NO; else pev->takedamage = DAMAGE_YES; pev->solid = SOLID_BSP; pev->movetype = MOVETYPE_PUSH; m_angle = pev->angles.y; pev->angles.y = 0; // HACK: matGlass can receive decals, we need the client to know about this // so use class to store the material flag if ( m_Material == matGlass ) { pev->playerclass = 1; } SET_MODEL(ENT(pev), STRING(pev->model) );//set size and link into world. SetTouch( &CBreakable::BreakTouch ); if ( FBitSet( pev->spawnflags, SF_BREAK_TRIGGER_ONLY ) ) // Only break on trigger SetTouch( NULL ); // Flag unbreakable glass as "worldbrush" so it will block ALL tracelines if ( !IsBreakable() && pev->rendermode != kRenderNormal ) pev->flags |= FL_WORLDBRUSH; }
//----------------------------------------------------------------------------- // Purpose: Breaks the breakable if it can be broken. // Input : pBreaker - The entity that caused us to break, either via an input, // by shooting us, or by touching us. //----------------------------------------------------------------------------- void CBreakable::Break( CBaseEntity *pBreaker ) { if ( IsBreakable() ) { m_hBreaker = pBreaker; Die(); } }
void CBreakable::BreakTouch(CBaseEntity *pOther) { float flDamage; entvars_t *pevToucher = pOther->pev; // only players can break these right now if (!pOther->IsPlayer() || !IsBreakable()) { if (pev->rendermode == kRenderNormal || !FClassnameIs(pOther->pev, "grenade")) return; pev->angles.y = m_angle; UTIL_MakeVectors(pev->angles); g_vecAttackDir = gpGlobals->v_forward; pev->takedamage = DAMAGE_NO; pev->deadflag = DEAD_DEAD; pev->effects = EF_NODRAW; Die(); } // can be broken when run into if (pev->spawnflags & SF_BREAK_TOUCH) { flDamage = pevToucher->velocity.Length() * 0.01f; if (flDamage >= pev->health) { SetTouch(NULL); TakeDamage(pevToucher, pevToucher, flDamage, DMG_CRUSH); // do a little damage to player if we broke glass or computer pOther->TakeDamage(pev, pev, flDamage / 4, DMG_SLASH); } } // can be broken when stood upon if ((pev->spawnflags & SF_BREAK_PRESSURE) && pevToucher->absmin.z >= pev->maxs.z - 2) { // play creaking sound here. DamageSound(); SetThink(&CBreakable::Die); SetTouch(NULL); // BUGBUG: why doesn't zero delay work? if (m_flDelay == 0.0f) { m_flDelay = 0.1f; } pev->nextthink = pev->ltime + m_flDelay; } }
//========================================================= // Special takedamage for func_breakable. Allows us to make // exceptions that are breakable-specific // bitsDamageType indicates the type of damage sustained ie: DMG_CRUSH //========================================================= int CBreakable :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType ) { Vector vecTemp; // if Attacker == Inflictor, the attack was a melee or other instant-hit attack. // (that is, no actual entity projectile was involved in the attack so use the shooter's origin). if ( pevAttacker == pevInflictor ) { vecTemp = pevInflictor->origin - ( pev->absmin + ( pev->size * 0.5 ) ); // if a client hit the breakable with a crowbar, and breakable is crowbar-sensitive, break it now. if ( FBitSet ( pevAttacker->flags, FL_CLIENT ) && FBitSet ( pev->spawnflags, SF_BREAK_CROWBAR ) && (bitsDamageType & DMG_CLUB)) flDamage = pev->health; } else // an actual missile was involved. { vecTemp = pevInflictor->origin - ( pev->absmin + ( pev->size * 0.5 ) ); } if (!IsBreakable()) return 0; // Breakables take double damage from the crowbar if ( bitsDamageType & DMG_CLUB ) flDamage *= 2; // Boxes / glass / etc. don't take much poison damage, just the impact of the dart - consider that 10% if ( bitsDamageType & DMG_POISON ) flDamage *= 0.1; // this global is still used for glass and other non-monster killables, along with decals. g_vecAttackDir = vecTemp.Normalize(); // do the damage pev->health -= flDamage; if (pev->health <= 0) { // LRC - Die() does everything necessary // if (!m_iRespawnTime) // { // Killed( pevAttacker, GIB_NORMAL ); // } Die(); return 0; } // Make a shard noise each time func breakable is hit. // Don't play shard noise if cbreakable actually died. DamageSound(); return 1; }
//----------------------------------------------------------------------------- // Purpose: Breaks the breakable if it can be broken. // Input : pBreaker - The entity that caused us to break, either via an input, // by shooting us, or by touching us. //----------------------------------------------------------------------------- void CBreakable::Break( CBaseEntity *pBreaker ) { if ( IsBreakable() ) { QAngle angles = GetLocalAngles(); angles.y = m_angle; SetLocalAngles( angles ); m_hBreaker = pBreaker; Die(); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBreakable::Spawn( void ) { // Initialize damage modifiers. Must be done before baseclass spawn. m_flDmgModBullet = func_breakdmg_bullet.GetFloat(); m_flDmgModClub = func_breakdmg_club.GetFloat(); m_flDmgModExplosive = func_breakdmg_explosive.GetFloat(); ParsePropData(); Precache( ); if ( !m_iHealth || FBitSet( m_spawnflags, SF_BREAK_TRIGGER_ONLY ) ) { // This allows people to shoot at the glass (since it's penetrable) if ( m_Material == matGlass ) { m_iHealth = 1; } m_takedamage = DAMAGE_NO; } else { m_takedamage = DAMAGE_YES; } m_iMaxHealth = ( m_iHealth > 0 ) ? m_iHealth : 1; SetSolid( SOLID_BSP ); SetMoveType( MOVETYPE_PUSH ); // this is a hack to shoot the gibs in a specific yaw/direction m_angle = GetLocalAngles().y; SetLocalAngles( vec3_angle ); SetModel( STRING( GetModelName() ) );//set size and link into world. SetTouch( &CBreakable::BreakTouch ); if ( FBitSet( m_spawnflags, SF_BREAK_TRIGGER_ONLY ) ) // Only break on trigger { SetTouch( NULL ); } // Flag unbreakable glass as "worldbrush" so it will block ALL tracelines if ( !IsBreakable() && m_nRenderMode != kRenderNormal ) AddFlag( FL_WORLDBRUSH ); if ( m_impactEnergyScale == 0 ) { m_impactEnergyScale = 1.0; } CreateVPhysics(); }
// Break when triggered void CBreakable::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { if ( IsBreakable() ) { pev->angles.y = m_angle; UTIL_MakeVectors(pev->angles); g_vecAttackDir = gpGlobals->v_forward; Die(); } }
void CBreakable::Spawn( void ) { Precache( ); if ( FBitSet( pev->spawnflags, SF_BREAK_TRIGGER_ONLY ) ) pev->takedamage = DAMAGE_NO; else pev->takedamage = DAMAGE_YES; if (m_iClass) //LRC - might these additions cause problems? { pev->flags |= FL_MONSTER; pev->view_ofs = (pev->maxs + pev->mins) / 2; } if (m_iszWhenHit) //LRC - locus trigger { m_pHitProxy = GetClassPtr( (CPointEntity*)NULL ); } pev->solid = SOLID_BSP; pev->movetype = MOVETYPE_PUSH; m_angle = pev->angles.y; pev->angles.y = 0; m_iInitialHealth = pev->health; m_iInitialRenderAmt = pev->renderamt; m_iInitialRenderMode = pev->rendermode; // HACK: matGlass can receive decals, we need the client to know about this // so use class to store the material flag if ( m_Material == matGlass ) { pev->playerclass = 1; } SET_MODEL(ENT(pev), STRING(pev->model) );//set size and link into world. SetTouch(&CBreakable:: BreakTouch ); SetUse(&CBreakable:: BreakUse ); if ( FBitSet( pev->spawnflags, SF_BREAK_TRIGGER_ONLY ) ) // Only break on trigger SetTouch( NULL ); // Flag unbreakable glass as "worldbrush" so it will block ALL tracelines if ( !IsBreakable() && pev->rendermode != kRenderNormal ) pev->flags |= FL_WORLDBRUSH; if (m_iStyle >= 32) LIGHT_STYLE(m_iStyle, "z"); else if (m_iStyle <= -32) LIGHT_STYLE(-m_iStyle, "a"); }
// Break when triggered void CBreakable::BreakUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { // for a respawnable entity, ON means someone wants it to respawn- but this one's solid already. if (m_iRespawnTime && useType == USE_ON) return; if ( IsBreakable() ) { pev->angles.y = m_angle; UTIL_MakeVectors(pev->angles); g_vecAttackDir = gpGlobals->v_forward; Die(); } }
void CBreakable::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) { if (IsBreakable()) { pev->angles.y = m_angle; UTIL_MakeVectors(pev->angles); g_vecAttackDir = gpGlobals->v_forward; pev->takedamage = DAMAGE_NO; pev->deadflag = DEAD_DEAD; pev->effects = EF_NODRAW; Die(); } }
//----------------------------------------------------------------------------- // Purpose: Allows us to make damage exceptions that are breakable-specific. //----------------------------------------------------------------------------- int CBreakable::OnTakeDamage( const CTakeDamageInfo &info ) { Vector vecTemp; CTakeDamageInfo subInfo = info; // If attacker can't do at least the min required damage to us, don't take any damage from them if ( m_takedamage == DAMAGE_NO || info.GetDamage() < m_iMinHealthDmg ) return 0; // Check our damage filter if ( !PassesDamageFilter(subInfo) ) { m_bTookPhysicsDamage = false; return 1; } vecTemp = subInfo.GetInflictor()->GetAbsOrigin() - WorldSpaceCenter(); if (!IsBreakable()) return 0; float flPropDamage = GetBreakableDamage( subInfo, assert_cast<IBreakableWithPropData*>(this) ); subInfo.SetDamage( flPropDamage ); int iPrevHealth = m_iHealth; BaseClass::OnTakeDamage( subInfo ); // HACK: slam health back to what it was so UpdateHealth can do its thing int iNewHealth = m_iHealth; m_iHealth = iPrevHealth; if ( !UpdateHealth( iNewHealth, info.GetAttacker() ) ) return 1; // Make a shard noise each time func breakable is hit, if it's capable of taking damage if ( m_takedamage == DAMAGE_YES ) { // Don't play shard noise if being burned. // Don't play shard noise if cbreakable actually died. if ( ( subInfo.GetDamageType() & DMG_BURN ) == false ) { DamageSound(); } } return 1; }
void CBreakable::BreakTouch( CBaseEntity *pOther ) { float flDamage; // only players can break these right now if ( !pOther->IsPlayer() || !IsBreakable() ) { return; } // can I be broken when run into? if ( HasSpawnFlags( SF_BREAK_TOUCH ) ) { flDamage = pOther->GetSmoothedVelocity().Length() * 0.01; if (flDamage >= m_iHealth) { m_takedamage = DAMAGE_YES; SetTouch( NULL ); OnTakeDamage( CTakeDamageInfo( pOther, pOther, flDamage, DMG_CRUSH ) ); // do a little damage to player if we broke glass or computer CTakeDamageInfo info( pOther, pOther, flDamage/4, DMG_SLASH ); CalculateMeleeDamageForce( &info, (pOther->GetAbsOrigin() - GetAbsOrigin()), GetAbsOrigin() ); pOther->TakeDamage( info ); } } // can I be broken when stood upon? if ( HasSpawnFlags( SF_BREAK_PRESSURE ) && pOther->GetGroundEntity() == this ) { // play creaking sound here. DamageSound(); m_hBreaker = pOther; SetThink ( &CBreakable::Die ); SetTouch( NULL ); // Add optional delay SetNextThink( gpGlobals->curtime + m_flPressureDelay ); } }
void CBreakable::BreakTouch( CBaseEntity *pOther ) { float flDamage; entvars_t* pevToucher = pOther->pev; // only players can break these right now if ( !pOther->IsPlayer() || !IsBreakable() ) { return; } if ( FBitSet ( pev->spawnflags, SF_BREAK_TOUCH ) ) {// can be broken when run into flDamage = pevToucher->velocity.Length() * 0.01; if (flDamage >= pev->health) { SetTouch( NULL ); TakeDamage(pevToucher, pevToucher, flDamage, DMG_CRUSH); // do a little damage to player if we broke glass or computer pOther->TakeDamage( pev, pev, flDamage/4, DMG_SLASH ); } } if ( FBitSet ( pev->spawnflags, SF_BREAK_PRESSURE ) && pevToucher->absmin.z >= pev->maxs.z - 2 ) {// can be broken when stood upon // play creaking sound here. DamageSound(); SetThink ( &CBreakable::Die ); SetTouch( NULL ); if ( m_flDelay == 0 ) {// !!!BUGBUG - why doesn't zero delay work? m_flDelay = 0.1; } pev->nextthink = pev->ltime + m_flDelay; } }
int CBreakable::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) { Vector vecTemp; // if Attacker == Inflictor, the attack was a melee or other instant-hit attack. // (that is, no actual entity projectile was involved in the attack so use the shooter's origin). if (pevAttacker == pevInflictor) { vecTemp = pevInflictor->origin - (pev->absmin + (pev->size * 0.5f)); // if a client hit the breakable with a crowbar, and breakable is crowbar-sensitive, break it now. if ((pevAttacker->flags & FL_CLIENT) && (pev->spawnflags & SF_BREAK_CROWBAR) && (bitsDamageType & DMG_CLUB)) { flDamage = pev->health; } } else { // an actual missile was involved. vecTemp = pevInflictor->origin - (pev->absmin + (pev->size * 0.5f)); } if (!IsBreakable()) return 0; // Breakables take double damage from the crowbar if (bitsDamageType & DMG_CLUB) { flDamage *= 2.0f; } // Boxes / glass / etc. don't take much poison damage, just the impact of the dart - consider that 10% if (bitsDamageType & DMG_POISON) { flDamage *= 0.1f; } // this global is still used for glass and other non-monster killables, along with decals. g_vecAttackDir = vecTemp.Normalize(); // do the damage pev->health -= flDamage; if (pev->health <= 0) { pev->takedamage = DAMAGE_NO; pev->deadflag = DEAD_DEAD; pev->effects = EF_NODRAW; Die(); if (m_flDelay == 0.0f) { m_flDelay = 0.1f; } pev->nextthink = pev->ltime + m_flDelay; return 0; } // Make a shard noise each time func breakable is hit. // Don't play shard noise if cbreakable actually died. DamageSound(); return 1; }