/** * @brief Called when 'target' is about to shoot, this forces a 'draw' to decide who gets the first shot * @param[in] target The entity about to shoot * @param[in] fdTime The TU of the shot * @sa G_ClientShoot */ void G_ReactionFirePreShot (const edict_t *target, const int fdTime) { edict_t *shooter = NULL; bool repeat = true; /* Check to see whether this triggers any reaction fire */ G_ReactionFireTargetsUpdateAll(target); /* if any reaction fire occurs, we have to loop through all entities again to allow * multiple (fast) RF snap shots before a (slow) aimed shot from the target occurs. */ while (repeat) { repeat = false; /* check all ents to see who wins and who loses a draw */ while ((shooter = G_EdictsGetNextLivingActor(shooter))) { int entTUs = G_ReactionFireGetTUsForItem(shooter, target, RIGHT(shooter)); if (entTUs > 1) { /* indicates an RF weapon is there */ if (G_ReactionFireTargetsExpired(shooter, target, fdTime)) { if (G_ReactionFireTryToShoot(shooter, target)) { repeat = true; G_ReactionFireTargetsAdvance(shooter, target, fdTime); } } } } } }
/** * @brief Called at the end of turn, all outstanding reaction fire is resolved * @sa G_ClientEndRound */ void G_ReactionFireEndTurn (void) { edict_t *ent = NULL; /* resolve all outstanding reaction firing if possible */ while ((ent = G_EdictsGetNextLivingActor(ent))) { if (!ent->reactionTarget) continue; G_ReactionFireTryToShoot(ent); } }
/** * @brief Check all entities to see whether target has caused reaction fire to resolve. * @param[in] target The entity that might be resolving reaction fire * @returns whether any entity fired (or would fire) upon target * @sa G_ReactionFireOnMovement * @sa G_ReactionFirePostShot */ static bool G_ReactionFireCheckExecution (const edict_t *target) { edict_t *shooter = NULL; bool fired = false; /* check all possible shooters */ while ((shooter = G_EdictsGetNextLivingActor(shooter))) { const int tus = G_ReactionFireGetTUsForItem(shooter, target, RIGHT(shooter)); if (tus > 1) { /* indicates an RF weapon is there */ if (G_ReactionFireTargetsExpired(shooter, target, 0)) { if (G_ReactionFireTryToShoot(shooter, target)) { G_ReactionFireTargetsAdvance(shooter, target, tus); fired |= true; } } } } return fired; }
/** * @brief Check all entities to see whether target has caused reaction fire to resolve. * @param[in] target The entity that might be resolving reaction fire * @returns whether any entity fired (or would fire) upon target * @sa G_ReactionFireOnMovement * @sa G_ReactionFirePostShot */ static qboolean G_ReactionFireCheckExecution (const edict_t *target) { edict_t *ent = NULL; qboolean fired = qfalse; /* check all possible shooters */ while ((ent = G_EdictsGetNextLivingActor(ent))) { if (ent->reactionTarget) { const int reactionTargetTU = ent->reactionTarget->TU; const int reactionTU = ent->reactionTUs; const qboolean timeout = g_reaction_fair->integer == 0 || reactionTargetTU < reactionTU; /* check whether target has changed (i.e. the player is making a move with a * different entity) or whether target is out of time. */ if (ent->reactionTarget != target || timeout) fired |= G_ReactionFireTryToShoot(ent); } } return fired; }
/** * @brief Called when 'target' is about to shoot, this forces a 'draw' to decide who gets the first shot * @param[in] target The entity about to shoot * @param[in] fdTime The TU of the shoot * @sa G_ClientShoot */ void G_ReactionFirePreShot (const edict_t *target, const int fdTime) { edict_t *ent = NULL; /* Check to see whether this triggers any reaction fire */ G_ReactionFireSearchTarget(target); /* check all ents to see who wins and who loses a draw */ while ((ent = G_EdictsGetNextLivingActor(ent))) { int entTUs; if (!ent->reactionTarget) continue; /* check this ent hasn't already lost the draw */ if (ent->reactionNoDraw) continue; /* can't reaction fire if no TUs to fire */ entTUs = G_ReactionFireGetTUsForItem(ent, target, RIGHT(ent)); if (entTUs < 0) { ent->reactionTarget = NULL; continue; } /* see who won */ if (entTUs >= fdTime) { /* target wins, so delay ent */ /* ent can't lose the TU battle again */ ent->reactionNoDraw = qtrue; } else { /* ent wins so take the shot */ G_ReactionFireTryToShoot(ent); } } }