Example #1
0
/**
 * @brief Called after 'target' has fired, this might trigger more reaction fire or resolve outstanding reaction fire (because target is out of time)
 * @param[in] target The entity that has just fired
 * @sa G_ClientShoot
 */
void G_ReactionFirePostShot (Actor* target)
{
	/* Check to see whether this resolves any reaction fire */
	rf.notifyClientOnShot(target, 0);
	rf.checkExecution(target, MAX_ROUTE);
	G_ReactionFireNotifyClientEndShot(target);
}
Example #2
0
/**
 * @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);
		}
	}
}
Example #3
0
/**
 * @brief Get the weapon firing TUs of the item in the hand of the shooter.
 * @return -1 if no firedef was found for the item or the reaction fire mode is not activated.
 * @param[in] shooter The reaction firing actor
 * @param[in] target The target to check reaction fire for (e.g. check whether the weapon that was marked for
 * using in reaction fire situations can handle the distance between the shooter and the target)
 */
static int G_ReactionFireGetTUsForItem (const Actor* shooter, const Edict* target)
{
	const fireDef_t* fd = rf.getFireDef(shooter);
	if (!fd)
		return -1;

	const int tus = G_ActorGetModifiedTimeForFiredef(shooter, fd, true);

	if (tus <= shooter->TU && rf.isInWeaponRange(shooter, target, fd)) {
		return tus;
	}

	return -1;
}
Example #4
0
/**
 * @brief Called when 'target' moves, possibly triggering or resolving reaction fire
 * @param[in] target The target entity
 * @param[in] step The number of the step in the move we are checking reactions for
 * @return true If any shots were (or would be) taken
 * @sa G_ClientMove
 */
bool G_ReactionFireOnMovement (Actor* target, int step)
{
#if DEBUG_RF
	G_ReactionFirePrintSituation(target);
#endif
	rf.notifyClientOnStep(target, step);

	/* Check to see whether this resolves any reaction fire */
	const bool fired = rf.checkExecution(target, step);

	/* Check to see whether this triggers any reaction fire */
	rf.updateAllTargets(target);

	return fired;
}
Example #5
0
/**
 * @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 using reaction fire
 * @param[in] target The victim of the reaction fire
 * @return true if the entity fired, false otherwise
 */
bool ReactionFire::tryToShoot (Actor* 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 (!isPossible(shooter, target)) {
		rft.remove(shooter, target);
		return false;
	}

	/* take the shot */
	const actorHands_t hand = shooter->chr.RFmode.getHand();
	const shoot_types_t type = (hand == ACTOR_HAND_RIGHT ? ST_RIGHT_REACTION
			: (hand == ACTOR_HAND_LEFT ? ST_LEFT_REACTION : ST_NUM_SHOOT_TYPES));
	const bool tookShot = rf.shoot(shooter, target->pos, type, shooter->chr.RFmode.getFmIdx());

	if (tookShot) {
		/* clear any shakenness */
		shooter->removeShaken();
	}

	return tookShot;
}
Example #6
0
/**
 * @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;
}
Example #7
0
/**
 * @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 using reaction fire
 * @param[in] target The victim of the reaction fire
 * @return true if the entity fired, false otherwise
 */
bool ReactionFire::tryToShoot (Actor* 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 (!isPossible(shooter, target)) {
		rft.remove(shooter, target);
		return false;
	}

	/* take the shot */
	const bool tookShot = rf.shoot(shooter, target->pos, ST_RIGHT_REACTION, shooter->chr.RFmode.getFmIdx());

	if (tookShot) {
		/* clear any shakenness */
		shooter->removeShaken();
	}

	return tookShot;
}
Example #8
0
/**
 * @brief Removes the given target from the reaction fire lists
 * @param[in] target The target to remove from the lists
 */
void G_ReactionFireOnDead (const Actor* target)
{
	assert(G_IsDead(target));
	rf.updateAllTargets(target);
	rf.resetTargets(target);
}