Example #1
0
//-----------------------------------------------------------------------------
// 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;
}
Example #2
0
/*
============
idActor::Damage

this		entity that is being damaged
inflictor	entity that is causing the damage
attacker	entity that caused the inflictor to damage targ
	example: this=monster, inflictor=rocket, attacker=player

dir			direction of the attack for knockback in global space
point		point at which the damage is being inflicted, used for headshots
damage		amount of damage being inflicted

inflictor, attacker, dir, and point can be NULL for environmental effects

Bleeding wounds and surface overlays are applied in the collision code that
calls Damage()
============
*/
void idActor::Damage( idEntity *inflictor, idEntity *attacker, const noVec3 &dir, const char *damageDefName, const float damageScale, const int location ) {
	if ( !fl.takedamage ) {
		return;
	}

	if ( !inflictor ) {
		inflictor = gameLocal.world;
	}
	if ( !attacker ) {
		attacker = gameLocal.world;
	}
#if 0
#ifdef _D3XP
	SetTimeState ts( timeGroup );

	// Helltime boss is immune to all projectiles except the helltime killer
	if ( finalBoss && idStr::Icmp(inflictor->GetEntityDefName(), "projectile_helltime_killer") ) {
		return;
	}

	// Maledict is immume to the falling asteroids
	if ( !idStr::Icmp( GetEntityDefName(), "monster_boss_d3xp_maledict" ) && 
		(!idStr::Icmp( damageDefName, "damage_maledict_asteroid" ) || !idStr::Icmp( damageDefName, "damage_maledict_asteroid_splash" ) ) ) {
			return;
	}
#else
	if ( finalBoss && !inflictor->IsType( idSoulCubeMissile::Type ) ) {
		return;
	}
#endif
#endif
	const idDict *damageDef = gameLocal.FindEntityDefDict( damageDefName );
	if ( !damageDef ) {
		gameLocal.Error( "Unknown damageDef '%s'", damageDefName );
	}

	int	damage = damageDef->GetInt( "damage" ) * damageScale;
	damage = GetDamageForLocation( damage, location );

	// inform the attacker that they hit someone
	attacker->DamageFeedback( this, inflictor, damage );
	if ( damage > 0 ) {
		health -= damage;

#ifdef _D3XP
		//Check the health against any damage cap that is currently set
		if(damageCap >= 0 && health < damageCap) {
			health = damageCap;
		}
#endif

		if ( health <= 0 ) {
			if ( health < -999 ) {
				health = -999;
			}
			Killed( inflictor, attacker, damage, dir, location );
			if ( ( health < -20 ) && spawnArgs.GetBool( "gib" ) && damageDef->GetBool( "gib" ) ) {
			Gib( dir, damageDefName );
			}
		} else {
			Pain( inflictor, attacker, damage, dir, location );
		}
	} else {
		// don't accumulate knockback
		if ( af.IsLoaded() ) {
			// clear impacts
			af.Rest();

			// physics is turned off by calling af.Rest()
			BecomeActive( TH_PHYSICS );
		}
	}

}