int CBaseEntity::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) { Vector vecTemp; if(!pev->takedamage) return 0; // UNDONE: some entity types may be immune or resistant to some bitsDamageType // 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 = pevAttacker->origin - (VecBModelOrigin(pev)); } else // an actual missile was involved. { vecTemp = pevInflictor->origin - (VecBModelOrigin(pev)); } // this global is still used for glass and other non-monster killables, along with decals. g_vecAttackDir = vecTemp.Normalize(); // save damage based on the target's armor level // figure momentum add (don't let hurt brushes or other triggers move player) if((!FNullEnt(pevInflictor)) && (pev->movetype == MOVETYPE_WALK || pev->movetype == MOVETYPE_STEP) && (pevAttacker->solid != SOLID_TRIGGER)) { Vector vecDir = pev->origin - (pevInflictor->absmin + pevInflictor->absmax) * 0.5; vecDir = vecDir.Normalize(); float flForce = flDamage * ((32 * 32 * 72.0) / (pev->size.x * pev->size.y * pev->size.z)) * 5; if(flForce > 1000.0) flForce = 1000.0; pev->velocity = pev->velocity + vecDir * flForce; } // do the damage pev->health -= flDamage; if(pev->health <= 0) { Killed(pevAttacker, GIB_NORMAL); return 0; } return 1; }
void CBubbling::FizzThink( void ) { MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, VecBModelOrigin(pev) ); WRITE_BYTE( TE_FIZZ ); WRITE_SHORT( (short)ENTINDEX( edict() ) ); WRITE_SHORT( (short)m_bubbleModel ); WRITE_BYTE( m_density ); MESSAGE_END(); if ( m_frequency > 19 ) pev->nextthink = gpGlobals->time + 0.5; else pev->nextthink = gpGlobals->time + 2.5 - (0.1 * m_frequency); }
// // Touch - will hurt others based on how fast the brush is spinning // void CFuncRotating :: HurtTouch ( CBaseEntity *pOther ) { entvars_t *pevOther = pOther->pev; // we can't hurt this thing, so we're not concerned with it if ( !pevOther->takedamage ) return; // calculate damage based on rotation speed pev->dmg = pev->avelocity.Length() / 10; pOther->TakeDamage( pev, pev, pev->dmg, DMG_CRUSH); pevOther->velocity = (pevOther->origin - VecBModelOrigin(pev) ).Normalize() * pev->dmg; }
void CPendulum :: Touch ( CBaseEntity *pOther ) { entvars_t *pevOther = pOther->pev; if ( pev->dmg <= 0 ) return; // we can't hurt this thing, so we're not concerned with it if ( !pevOther->takedamage ) return; // calculate damage based on rotation speed float damage = pev->dmg * pev->speed * 0.01; if ( damage < 0 ) damage = -damage; pOther->TakeDamage( pev, pev, damage, DMG_CRUSH ); pevOther->velocity = (pevOther->origin - VecBModelOrigin(pev) ).Normalize() * damage; }
void CBreakable::Die( void ) { Vector vecSpot;// shard origin Vector vecVelocity;// shard velocity CBaseEntity *pEntity = NULL; char cFlag = 0; int pitch; float fvol; pitch = 95 + RANDOM_LONG(0,29); if (pitch > 97 && pitch < 103) pitch = 100; // The more negative pev->health, the louder // the sound should be. fvol = RANDOM_FLOAT(0.85, 1.0) + (abs(pev->health) / 100.0); if (fvol > 1.0) fvol = 1.0; switch (m_Material) { case matGlass: switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustglass1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustglass2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_GLASS; break; case matWood: switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustcrate1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustcrate2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_WOOD; break; case matComputer: case matMetal: switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustmetal1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustmetal2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_METAL; break; case matFlesh: switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustflesh1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustflesh2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_FLESH; break; case matRocks: case matCinderBlock: switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustconcrete1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustconcrete2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_CONCRETE; break; case matCeilingTile: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustceiling.wav", fvol, ATTN_NORM, 0, pitch); break; } if (m_Explosion == expDirected) vecVelocity = g_vecAttackDir * 200; else { vecVelocity.x = 0; vecVelocity.y = 0; vecVelocity.z = 0; } vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5; MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpot ); WRITE_BYTE( TE_BREAKMODEL); // position WRITE_COORD( vecSpot.x ); WRITE_COORD( vecSpot.y ); WRITE_COORD( vecSpot.z ); // size WRITE_COORD( pev->size.x); WRITE_COORD( pev->size.y); WRITE_COORD( pev->size.z); // velocity WRITE_COORD( vecVelocity.x ); WRITE_COORD( vecVelocity.y ); WRITE_COORD( vecVelocity.z ); // randomization WRITE_BYTE( 10 ); // Model WRITE_SHORT( m_idShard ); //model id# // # of shards WRITE_BYTE( 0 ); // let client decide // duration WRITE_BYTE( 25 );// 2.5 seconds // flags WRITE_BYTE( cFlag ); MESSAGE_END(); float size = pev->size.x; if ( size < pev->size.y ) size = pev->size.y; if ( size < pev->size.z ) size = pev->size.z; // !!! HACK This should work! // Build a box above the entity that looks like an 8 pixel high sheet Vector mins = pev->absmin; Vector maxs = pev->absmax; mins.z = pev->absmax.z; maxs.z += 8; // BUGBUG -- can only find 256 entities on a breakable -- should be enough CBaseEntity *pList[256]; int count = UTIL_EntitiesInBox( pList, 256, mins, maxs, FL_ONGROUND ); if ( count ) { for ( int i = 0; i < count; i++ ) { ClearBits( pList[i]->pev->flags, FL_ONGROUND ); pList[i]->pev->groundentity = NULL; } } // Don't fire something that could fire myself pev->targetname = 0; pev->solid = SOLID_NOT; // Fire targets on break SUB_UseTargets( NULL, USE_TOGGLE, 0 ); SetThink( &CBreakable::SUB_Remove ); pev->nextthink = pev->ltime + 0.1; if ( m_iszSpawnObject ) CBaseEntity::Create( (char *)STRING(m_iszSpawnObject), VecBModelOrigin(pev), pev->angles, edict() ); if ( Explodable() ) { ExplosionCreate( Center(), pev->angles, edict(), ExplosionMagnitude(), TRUE ); } }
//----------------------------------------------------------------------------- // Purpose: Player has taken some damage. This is now using the Quake functionality. //----------------------------------------------------------------------------- int CBasePlayer::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) { if ( (pev->takedamage == DAMAGE_NO) || (IsAlive() == FALSE) ) return 0; //We are wearing the suit and we want to be hurt by lava or slime if ( m_iQuakeItems & IT_SUIT ) { if ( bitsDamageType & DMG_BURN || bitsDamageType & DMG_ACID ) return 0; } CBaseEntity *pAttacker = CBaseEntity::Instance(pevAttacker); // keep track of amount of damage last sustained m_lastDamageAmount = flDamage; // check for quad damage powerup on the attacker if (pAttacker->IsPlayer()) { if ( ((CBasePlayer*)pAttacker)->m_flSuperDamageFinished > gpGlobals->time ) { if (gpGlobals->deathmatch == 4) flDamage *= 8; else flDamage *= 4; } } // team play damage avoidance if ( g_pGameRules->PlayerRelationship( this, pAttacker ) == GR_TEAMMATE ) { // Teamplay 3 you can still hurt yourself if ( CVAR_GET_FLOAT( "mp_teamplay" ) == 3 && pAttacker != this ) return 0; // Teamplay 1 can't hurt any teammates, including yourself if ( CVAR_GET_FLOAT( "mp_teamplay" ) == 1 ) return 0; // Teamplay 2 you can still hurt teammates } // save damage based on the target's armor level float flSave = ceil(pev->armortype * flDamage); if (flSave >= pev->armorvalue) { flSave = pev->armorvalue; pev->armortype = 0; // lost all armor m_iQuakeItems &= ~(IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3); } pev->armorvalue -= flSave; float flTake = ceil(flDamage - flSave); // add to the damage total for clients, which will be sent as a single message at the end of the frame pev->dmg_take = pev->dmg_take + flTake; pev->dmg_inflictor = ENT(pevInflictor); Vector vecTemp; if ( pevAttacker == pevInflictor ) { vecTemp = pevAttacker->origin - ( VecBModelOrigin(pev) ); } else // an actual missile was involved. { vecTemp = pevInflictor->origin - ( VecBModelOrigin(pev) ); } // this global is still used for glass and other non-monster killables, along with decals. g_vecAttackDir = vecTemp.Normalize(); // figure momentum add if ( (pevInflictor) && (pev->movetype == MOVETYPE_WALK) && !( FBitSet (bitsDamageType, DMG_BURN) ) && !( FBitSet (bitsDamageType, DMG_ACID) ) ) { Vector vecPush = (pev->origin - (pevInflictor->absmin + pevInflictor->absmax) * 0.5).Normalize(); // Set kickback for smaller weapons // Read: only if it's not yourself doing the damage if ( (flDamage < 60) && pAttacker->IsPlayer() && (pAttacker != this) ) pev->velocity = pev->velocity + vecPush * flDamage * 11; else { // Otherwise, these rules apply to rockets and grenades // for blast velocity if ( pAttacker == this ) { if ( m_iQuakeWeapon != IT_LIGHTNING ) pev->velocity = pev->velocity + vecPush * flDamage * 8; } else pev->velocity = pev->velocity + vecPush * flDamage * 8; } // Rocket Jump modifiers int iRocketJumpModifier = (int)CVAR_GET_FLOAT("rj"); if ( (iRocketJumpModifier > 1) && (pAttacker == this) && m_iQuakeWeapon == ( IT_ROCKET_LAUNCHER | IT_GRENADE_LAUNCHER ) ) pev->velocity = pev->velocity + vecPush * flDamage * iRocketJumpModifier; } // check for godmode or invincibility if (pev->flags & FL_GODMODE) return 0; if (m_flInvincibleFinished > gpGlobals->time) { if (m_fInvincSound < gpGlobals->time) { EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM); m_fInvincSound = gpGlobals->time + 2; } return 0; } // do the damage pev->health -= (int)flTake; // tell director about it MESSAGE_BEGIN( MSG_SPEC, SVC_DIRECTOR ); WRITE_BYTE ( 9 ); // command length in bytes WRITE_BYTE ( DRC_CMD_EVENT ); // take damage event WRITE_SHORT( ENTINDEX(this->edict()) ); // index number of primary entity WRITE_SHORT( ENTINDEX(ENT(pevInflictor)) ); // index number of secondary entity WRITE_LONG( 5 ); // eventflags (priority and flags) MESSAGE_END(); // react to the damage m_bitsDamageType |= bitsDamageType; // Save this so we can report it to the client m_bitsHUDDamage = -1; // make sure the damage bits get resent if ( pev->health <= 0 ) { g_pevLastInflictor = pevInflictor; Killed( pevAttacker, GIB_NORMAL ); g_pevLastInflictor = NULL; return 0; } // play pain sound Pain( pAttacker ); return flTake; }
void CBreakable::Die() { Vector vecSpot; // shard origin Vector vecVelocity; // shard velocity CBaseEntity *pEntity = NULL; char cFlag = 0; int pitch; float fvol; pev->takedamage = DAMAGE_NO; pev->deadflag = DEAD_DEAD; pev->effects = EF_NODRAW; pitch = 95 + RANDOM_LONG(0, 29); if (pitch > 97 && pitch < 103) pitch = 100; // The more negative pev->health, the louder // the sound should be. fvol = RANDOM_FLOAT(0.85, 1.0) + (abs((int)pev->health) / 100.0f); if (fvol > 1.0f) fvol = 1.0f; switch (m_Material) { case matGlass: switch (RANDOM_LONG(0, 1)) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustglass1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustglass2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_GLASS; if (TheBots != NULL) { TheBots->OnEvent(EVENT_BREAK_GLASS, this); } break; case matWood: switch (RANDOM_LONG(0, 1)) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustcrate1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustcrate2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_WOOD; if (TheBots != NULL) { TheBots->OnEvent(EVENT_BREAK_WOOD, this); } break; case matMetal: case matComputer: switch (RANDOM_LONG(0, 1)) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustmetal1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustmetal2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_METAL; if (TheBots != NULL) { TheBots->OnEvent(EVENT_BREAK_METAL, this); } break; case matFlesh: switch (RANDOM_LONG(0, 1)) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustflesh1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustflesh2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_FLESH; if (TheBots != NULL) { TheBots->OnEvent(EVENT_BREAK_FLESH, this); } break; case matCinderBlock: case matRocks: switch (RANDOM_LONG(0, 1)) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustconcrete1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustconcrete2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_CONCRETE; if (TheBots != NULL) { TheBots->OnEvent(EVENT_BREAK_CONCRETE, this); } break; case matCeilingTile: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustceiling.wav", fvol, ATTN_NORM, 0, pitch); break; default: break; } if (m_Explosion == expDirected) { vecVelocity = g_vecAttackDir * 200.0f; } else { vecVelocity.x = 0; vecVelocity.y = 0; vecVelocity.z = 0; } vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5; MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecSpot); WRITE_BYTE(TE_BREAKMODEL); WRITE_COORD(vecSpot.x); // position WRITE_COORD(vecSpot.y); WRITE_COORD(vecSpot.z); WRITE_COORD(pev->size.x); // size WRITE_COORD(pev->size.y); WRITE_COORD(pev->size.z); WRITE_COORD(vecVelocity.x); // velocity WRITE_COORD(vecVelocity.y); WRITE_COORD(vecVelocity.z); WRITE_BYTE(10); // randomization WRITE_SHORT(m_idShard); // model id# WRITE_BYTE(0); // # of shards, let client decide WRITE_BYTE(25); // duration, 2.5 seconds WRITE_BYTE(cFlag); // flags MESSAGE_END(); float size = pev->size.x; if (size < pev->size.y) size = pev->size.y; if (size < pev->size.z) size = pev->size.z; Vector mins = pev->absmin; Vector maxs = pev->absmax; mins.z = pev->absmax.z; maxs.z += 8; CBaseEntity *pList[256]; int count = UTIL_EntitiesInBox(pList, ARRAYSIZE(pList), mins, maxs, FL_ONGROUND); if (count) { for (int i = 0; i < count; ++i) { pList[i]->pev->flags &= ~FL_ONGROUND; pList[i]->pev->groundentity = NULL; } } pev->solid = SOLID_NOT; SUB_UseTargets(NULL, USE_TOGGLE, 0); SetThink(NULL); pev->nextthink = pev->ltime + 0.1f; if (m_iszSpawnObject) { CBaseEntity::Create((char *)STRING(m_iszSpawnObject), VecBModelOrigin(pev), pev->angles, edict()); } if (Explodable()) { ExplosionCreate(Center(), pev->angles, edict(), ExplosionMagnitude(), TRUE); } }