Exemplo n.º 1
0
/**
 * @brief Deals damage and causes wounds.
 * @param[in,out] target Pointer to the actor we want to damage.
 * @param[in] damage The value of the damage.
 * @param[in] impact Impact location @c nullptr for splash damage.
 */
void G_DamageActor (Edict* target, const int damage, const vec3_t impact)
{
	assert(target->chr.teamDef);

	G_TakeDamage(target, damage);
	if (damage > 0 && target->HP > 0) {
		const teamDef_t* const teamDef = target->chr.teamDef;
		if (impact) {
			/* Direct hit */
			const byte impactDirection = G_GetImpactDirection(target, impact);
			const float impactHeight = impact[2] / (target->absBox.mins[2] + target->absBox.maxs[2]);
			const int bodyPart = teamDef->bodyTemplate->getHitBodyPart(impactDirection, impactHeight);
			target->chr.wounds.woundLevel[bodyPart] += damage;
		} else {
			/* No direct hit (splash damage) */
			for (int bodyPart = 0; bodyPart < teamDef->bodyTemplate->numBodyParts(); ++bodyPart)
				target->chr.wounds.woundLevel[bodyPart] += teamDef->bodyTemplate->getArea(bodyPart) * damage;
		}
#if 0
		if (!CHRSH_IsTeamDefRobot(target->chr.teamDef))
			/* Knockback -- currently disabled, not planned in the specs, also there's no way to tell stunned and dead actors apart */
			target->STUN = std::min(255.0f, target->STUN + std::max(0.0f, damage * crand() * 0.25f));
#endif
		G_SendWoundStats(target);
	}
}
Exemplo n.º 2
0
/**
 * @brief Write player stats to network buffer
 * @sa G_SendStats
 */
void G_SendPlayerStats (const Player& player)
{
	Edict* ent = nullptr;

	while ((ent = G_EdictsGetNextActor(ent)))
		if (ent->team == player.getTeam()) {
			G_EventActorStats(*ent, G_PlayerToPM(player));
			G_SendWoundStats(ent);
		}
}
Exemplo n.º 3
0
/**
 * @brief Heals a target and treats wounds.
 * @param[in,out] target Pointer to the actor who we want to treat.
 * @param[in] fd Pointer to the firedef used to heal the target.
 * @param[in] heal The value of the damage to heal.
 * @param[in] healerTeam The index of the team of the healer.
 */
void G_TreatActor (Actor* target, const fireDef_t* const fd, const int heal, const int healerTeam)
{
	assert(target->chr.teamDef);

	/* Treat wounds */
	if (fd->dmgweight == gi.csi->damNormal) {
		int mostWounded = 0;
		woundInfo_t* wounds = &target->chr.wounds;

		/* Find the worst not treated wound */
		for (int bodyPart = 0; bodyPart < target->chr.teamDef->bodyTemplate->numBodyParts(); ++bodyPart)
			if (wounds->woundLevel[bodyPart] > wounds->woundLevel[mostWounded])
				mostWounded = bodyPart;

		if (wounds->woundLevel[mostWounded] > 0) {
			const int woundsHealed = std::min(static_cast<int>(abs(heal) / target->chr.teamDef->bodyTemplate->bleedingFactor(mostWounded)),
					wounds->woundLevel[mostWounded]);
			G_TakeDamage(target, heal);
			wounds->woundLevel[mostWounded] -= woundsHealed;
			wounds->treatmentLevel[mostWounded] += woundsHealed;

			/* Update stats here to get info on how many HP the target received. */
			if (target->chr.scoreMission)
				target->chr.scoreMission->heal += abs(heal);
		}
	}

	/* Treat stunned actors */
	if (fd->dmgweight == gi.csi->damStunElectro && target->isStunned()) {
		if (CHRSH_IsTeamDefAlien(target->chr.teamDef) && target->getTeam() != healerTeam)
			/** @todo According to specs it should only be possible to use the medikit to keep an alien sedated when
			 * 'live alien' is researched, is it possible to find if a tech is researched here? */
			target->setStun(std::min(255, target->getStun() - heal));
		else
			target->setStun(std::max(0, target->getStun() + heal));
		G_ActorCheckRevitalise(target);
	}

	/* Increase morale */
	if (fd->dmgweight == gi.csi->damShock)
		target->setMorale(std::min(GET_MORALE(target->chr.score.skills[ABILITY_MIND]), target->morale - heal));

	G_SendWoundStats(target);
}