/** * @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 Prints some reaction fire data to the console * @param[in] target The target entity */ static void G_ReactionFirePrintSituation (Edict* target) { if (!G_IsAlien(target)) return; Com_Printf("Alien %i at %i/%i/%i TU:%i\n", target->number, target->pos[0], target->pos[1], target->pos[2], target->TU); Actor* shooter = nullptr; /* check all possible shooters */ while ((shooter = G_EdictsGetNextLivingActor(shooter))) { if (G_IsAlien(shooter) || G_IsCivilian(shooter)) continue; char msgHdr[100]; Com_sprintf(msgHdr, sizeof(msgHdr), "S%i: at %i/%i/%i RF: ", shooter->number, shooter->pos[0], shooter->pos[1], shooter->pos[2]); int ttus = rft.getTriggerTUs(shooter, target); if (ttus == -2) Com_Printf("%s not initialized\n", msgHdr); if (ttus == -1) Com_Printf("%s not aiming\n", msgHdr); else if (rft.hasExpired(shooter, target, 0)) Com_Printf("expired\n", msgHdr); else Com_Printf("%s not yet: %i\n", msgHdr, ttus); } }
/** * @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; }