/** * @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 Actor* target, const int fdTime) { bool repeat = true; /* Check to see whether this triggers any reaction fire */ G_ReactionFireNotifyClientStartShot(target); rf.updateAllTargets(target); rf.notifyClientOnShot(target, fdTime); /* 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) { Actor* shooter = nullptr; repeat = false; /* check all ents to see who wins and who loses a draw */ while ((shooter = G_EdictsGetNextLivingActor(shooter))) { const int entTUs = G_ReactionFireGetTUsForItem(shooter, target); /* indicates an RF weapon is there */ if (entTUs <= 1) continue; if (!rft.hasExpired(shooter, target, fdTime)) continue; if (!rf.tryToShoot(shooter, target)) { G_ReactionFireNotifyClientRFAborted(shooter, target, MAX_ROUTE); continue; } repeat = true; rft.advance(shooter, fdTime); } } }
/** * @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 *target, const int fdTime) { 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) { Edict *shooter = nullptr; repeat = false; /* check all ents to see who wins and who loses a draw */ while ((shooter = G_EdictsGetNextLivingActor(shooter))) { const int entTUs = G_ReactionFireGetTUsForItem(shooter, target); if (entTUs > 1) { /* indicates an RF weapon is there */ if (rft.hasExpired(shooter, target, fdTime)) { if (G_ReactionFireTryToShoot(shooter, target)) { repeat = true; rft.advance(shooter, fdTime); } } } } } }
/** * @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 *target) { Edict *shooter = nullptr; bool fired = false; /* check all possible shooters */ while ((shooter = G_EdictsGetNextLivingActor(shooter))) { const int tus = G_ReactionFireGetTUsForItem(shooter, target); if (tus > 1) { /* indicates an RF weapon is there */ if (rft.hasExpired(shooter, target, 0)) { if (G_ReactionFireTryToShoot(shooter, target)) { rft.advance(shooter, 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 * @param[in] step The number of the step in the move we are checking reactions for * @returns whether any entity fired (or would fire) upon target * @sa G_ReactionFireOnMovement * @sa G_ReactionFirePostShot */ bool ReactionFire::checkExecution (const Edict* target, int step) { Actor* shooter = nullptr; bool fired = false; /* check all possible shooters */ while ((shooter = G_EdictsGetNextLivingActor(shooter))) { const int tus = G_ReactionFireGetTUsForItem(shooter, target); /* indicates an RF weapon is there */ if (tus <= 1) continue; if (!rft.hasExpired(shooter, target, 0)) continue; if (!rf.tryToShoot(shooter, target)) { G_ReactionFireNotifyClientRFAborted(shooter, target, step); continue; } rft.advance(shooter, tus); fired |= true; } return fired; }