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); } }
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); } }
/** * @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]); } } }