Exemple #1
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);
		}
	}
}
Exemple #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 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);
					}
				}
			}
		}
	}
}
Exemple #3
0
/**
 * @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;
}
Exemple #4
0
/**
 * @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;
	}
}
Exemple #5
0
/**
 * @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);
		}
	}
}
Exemple #6
0
/**
 * @brief Check whether 'target' has just triggered any new reaction fire
 * @param[in] target The entity triggering fire
 */
void ReactionFire::updateAllTargets (const Edict* target)
{
	Actor* shooter = nullptr;

	/* check all possible shooters */
	while ((shooter = G_EdictsGetNextLivingActor(shooter))) {
		/* check whether reaction fire is possible (friend/foe, LoS) */
		if (isPossible(shooter, target)) {
			const int TUs = G_ReactionFireGetTUsForItem(shooter, target);
			if (TUs < 0)
				continue;	/* no suitable weapon */
			rft.add(shooter, target, TUs);
		} else {
			rft.remove(shooter, target);
		}
	}
}
Exemple #7
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
 * @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;
}
Exemple #8
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;
}
Exemple #9
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 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);
		}
	}
}