/** * @brief Resolve the reaction fire for an entity, this checks that the entity can fire and then takes the shot * @param[in] ent The entity to resolve reaction fire for * @return true if the entity fired (or would have fired if mock), false otherwise */ static qboolean G_ReactionFireTryToShoot (edict_t *ent) { qboolean tookShot; /* check whether this ent has a reaction fire queued */ assert(ent->reactionTarget); /* ent can't take a reaction shot if it's not possible - and check that * the target is still alive */ if (!G_ReactionFireIsPossible(ent, ent->reactionTarget)) { ent->reactionTarget = NULL; return qfalse; } /* take the shot */ tookShot = G_ReactionFireShoot(G_PLAYER_FROM_ENT(ent), ent, ent->reactionTarget->pos, ST_RIGHT_REACTION, ent->chr.RFmode.fmIdx); if (tookShot) { /* clear any shakenness */ G_RemoveShaken(ent); /* check whether further reaction fire is possible */ if (G_ReactionFireIsPossible(ent, ent->reactionTarget)){ /* see how quickly ent can fire (if it can fire at all) */ const int tus = G_ReactionFireGetTUsForItem(ent, ent->reactionTarget, RIGHT(ent)); if (tus >= 0) { /* An enemy getting reaction shot gets more time before * reaction fire is repeated. */ ent->reactionTUs = max(0, ent->reactionTarget->TU - tus); } } } return tookShot; }
/** * @brief Check whether 'target' has just triggered any new reaction fire * @param[in] target The entity triggering fire * @sa G_CanReactionFire * @sa G_GetFiringTUs */ static void G_ReactionFireSearchTarget (const edict_t *target) { edict_t *ent = NULL; /* check all possible shooters */ while ((ent = G_EdictsGetNextLivingActor(ent))) { int tus; /* not if ent has reaction target already */ if (ent->reactionTarget) continue; /* check whether reaction fire is possible */ if (!G_ReactionFireIsPossible(ent, target)) continue; /* see how quickly ent can fire (if it can fire at all) */ tus = G_ReactionFireGetTUsForItem(ent, target, RIGHT(ent)); if (tus < 0) continue; /* queue a reaction fire to take place */ ent->reactionTarget = target; /* An enemy entering the line of fire of a soldier on reaction * fire should have the opportunity to spend time equal to the * sum of these values. */ ent->reactionTUs = max(0, target->TU - (tus / 4.0)); ent->reactionNoDraw = qfalse; } }
/** * @brief Check whether 'target' has just triggered any new reaction fire * @param[in] target The entity triggering fire */ static void G_ReactionFireTargetsUpdateAll (const edict_t *target) { edict_t *shooter = NULL; /* check all possible shooters */ while ((shooter = G_EdictsGetNextLivingActor(shooter))) { /* check whether reaction fire is possible (friend/foe, LoS */ if (G_ReactionFireIsPossible(shooter, target)) { const int TUs = G_ReactionFireGetTUsForItem(shooter, target, RIGHT(shooter)); if (TUs < 0) continue; /* no suitable weapon */ G_ReactionFireTargetsAdd(shooter, target, TUs); } else { G_ReactionFireTargetsRemove(shooter, target); } } }
/** * @brief Resolve the reaction fire for an entity, this checks that the entity can fire and then takes the shot * @param[in] shooter The entity to resolve reaction fire for * @param[in] target The victim of the reaction fire * @return true if the entity fired (or would have fired if mock), false otherwise */ static bool G_ReactionFireTryToShoot (Edict *shooter, const Edict *target) { /* check for valid target */ assert(target); /* shooter can't take a reaction shot if it's not possible - and check that * the target is still alive */ if (!G_ReactionFireIsPossible(shooter, target)) { rft.remove(shooter, target); return false; } /* take the shot */ const bool tookShot = G_ReactionFireShoot(shooter, target->pos, ST_RIGHT_REACTION, shooter->chr.RFmode.getFmIdx()); if (tookShot) { /* clear any shakenness */ G_RemoveShaken(shooter); } return tookShot; }
/** * @brief Resolve the reaction fire for an entity, this checks that the entity can fire and then takes the shot * @param[in] shooter The entity to resolve reaction fire for * @param[in] target The victim of the reaction fire * @return true if the entity fired (or would have fired if mock), false otherwise */ static bool G_ReactionFireTryToShoot (edict_t *shooter, const edict_t *target) { bool tookShot; /* check for valid target */ assert(target); /* shooter can't take a reaction shot if it's not possible - and check that * the target is still alive */ if (!G_ReactionFireIsPossible(shooter, target)) { G_ReactionFireTargetsRemove(shooter, target); return false; } /* take the shot */ tookShot = G_ReactionFireShoot(G_PLAYER_FROM_ENT(shooter), shooter, target->pos, ST_RIGHT_REACTION, shooter->chr.RFmode.fmIdx); if (tookShot) { /* clear any shakenness */ G_RemoveShaken(shooter); } return tookShot; }