Exemplo n.º 1
0
void G_CheckDeathOrKnockout (Edict* target, Edict* attacker, const fireDef_t* fd, int damage)
{
	/* Sanity check */
	target->HP = std::min(std::max(target->HP, 0), target->chr.maxHP);
	/* Check death/knockout. */
	if (target->HP == 0 || target->HP <= target->STUN) {
		G_SendStats(*target);

		if (G_ActorDieOrStun(target, attacker)) {
			G_PrintActorStats(target, attacker, fd);

			/* apply morale changes */
			if (mor_panic->integer)
				G_Morale(ML_DEATH, target, attacker, damage);

			/* Update number of killed/stunned actors for this attacker. */
			G_UpdateCharacterBodycount(attacker, fd, target);
		}
	} else {
		target->chr.minHP = std::min(target->chr.minHP, target->HP);
		if (damage > 0) {
			if (mor_panic->integer)
				G_Morale(ML_WOUND, target, attacker, damage);
		}
		G_SendStats(*target);
	}
}
Exemplo n.º 2
0
void G_CheckDeathOrKnockout (edict_t *target, edict_t *attacker, const fireDef_t *fd, int damage)
{
	/* Check death/knockout. */
	if (target->HP == 0 || target->HP <= target->STUN) {
		G_SendStats(target);

		if (G_ActorDieOrStun(target, attacker)) {
			G_PrintActorStats(target, attacker, fd);

			/* apply morale changes */
			if (mor_panic->integer)
				G_Morale(ML_DEATH, target, attacker, damage);

			/* Update number of killed/stunned actors for this attacker. */
			G_UpdateCharacterBodycount(attacker, fd, target);
		}
	} else {
		target->chr.minHP = std::min(target->chr.minHP, target->HP);
		if (damage > 0) {
			if (mor_panic->integer)
				G_Morale(ML_WOUND, target, attacker, damage);
		} else { /* medikit, etc. */
			const int hp = GET_HP(target->chr.score.skills[ABILITY_POWER]);
			if (target->HP > hp) {
				target->HP = std::min(std::max(hp, 0), target->chr.maxHP);
			}
		}
		G_SendStats(target);
	}
}
Exemplo n.º 3
0
/**
 * @brief Applies morale changes to actors who find themselves in the general direction of a shot.
 * @param shooter The shooting actor.
 * @param fd The firedef used to shoot.
 * @param from The weapon's muzzle location.
 * @param weapon The weapon used to shoot.
 * @param impact The shoot's impact location.
 */
static void G_ShotMorale (const Actor* shooter, const fireDef_t* fd, const vec3_t from, const Item* weapon, const vec3_t impact)
{
	/* Skip not detectable shoots */
	if (weapon->def()->dmgtype == gi.csi->damLaser || fd->irgoggles)
		return;

	Actor* check = nullptr;
	const float minDist = UNIT_SIZE * 1.5f;
	while ((check = G_EdictsGetNextLivingActor(check))) {
		/* Skip yourself */
		if (check == shooter)
			continue;
		pos3_t target;
		VecToPos(impact, target);
		/* Skip the hit actor -- morale was already handled */
		if (check->isSamePosAs(target))
			continue;
		vec3_t dir1, dir2;
		VectorSubtract(check->origin, from, dir1);
		VectorSubtract(impact, from, dir2);
		const float len1 = VectorLength(dir1);
		const float len2 = VectorLength(dir2);
		const float dot = DotProduct(dir1, dir2);
		if (dot / (len1 * len2) < 0.7f)
			continue;
		/* Skip if shooting next or over an ally */
		if (check->isSameTeamAs(shooter) && VectorDistSqr(check->origin, shooter->origin)
				<= minDist * minDist)
			continue;
		vec3_t vec1;
		if (len1 > len2) {
			VectorSubtract(dir2, dir1, vec1);
		} else {
			VectorScale(dir2, dot / (len2 * len2), vec1);
			VectorSubtract(dir1, vec1, vec1);
		}
		const float morDist = (check->isSamePosAs(target) ? UNIT_SIZE * 0.5f : minDist);
		if (VectorLengthSqr(vec1) <= morDist * morDist) {
			/* @todo Add a visibility check here? */
			G_Morale(ML_SHOOT, check, shooter, fd->damage[0]);
		}
	}
}