Ejemplo n.º 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 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);
					}
				}
			}
		}
	}
}
Ejemplo n.º 2
0
/**
 * @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);
	}
}
Ejemplo n.º 3
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);
		}
	}
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 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 */
			rft.add(shooter, target, TUs);
		} else {
			rft.remove(shooter, target);
		}
	}
}
Ejemplo n.º 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);
		}
	}
}
Ejemplo n.º 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 *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;
}
Ejemplo n.º 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;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
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 to resolve reaction fire for
 * @param[in] target The victim of the reaction fire
 * @return true if the entity fired (or would have fired if mock), false otherwise
 */
static bool G_ReactionFireTryToShoot (edict_t *shooter, const edict_t *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 (!G_ReactionFireIsPossible(shooter, target)) {
		rft.remove(shooter, target);
		return false;
	}

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

	if (tookShot) {
		/* clear any shakenness */
		G_RemoveShaken(shooter);
	}

	return tookShot;
}
Ejemplo n.º 11
0
static void G_ReactionFireNotifyClientStartShot (const Edict* target)
{
	rft.notifyClientMove(target, MAX_ROUTE, true);
}
Ejemplo n.º 12
0
/**
 * @brief free function to destroy the table of reaction fire targets for the given edict.
 * @param[in] shooter The reaction firing actor
 */
void G_ReactionFireTargetsDestroy (const Edict* shooter)
{
	rft.destroy(shooter);
}
Ejemplo n.º 13
0
void ReactionFire::notifyClientOnStep (const Edict* target, int step)
{
	rft.notifyClientOnStep(target, step);
}
Ejemplo n.º 14
0
void ReactionFire::notifyClientOnShot (const Edict* target, int tusTarget)
{
	rft.notifyClientOnShot(target, tusTarget);
}
Ejemplo n.º 15
0
/**
 * @brief Called at the end of turn, all outstanding reaction fire is resolved
 * @sa G_ClientEndRound
 */
void G_ReactionFireOnEndTurn (void)
{
	/* we explicitly do nothing at end of turn, just reset the table */
	rft.reset();
}
Ejemplo n.º 16
0
/**
 * @brief free function to initialize the reaction fire table for all entities.
 */
void G_ReactionFireTargetsInit (void)
{
	rft.init();
}
Ejemplo n.º 17
0
void G_ReactionFireNotifyClientRFAborted (const Actor* shooter, const Edict* target, int step)
{
	rft.notifyClientRFAborted(shooter, target, step);
}
Ejemplo n.º 18
0
void G_ReactionFireNotifyClientEndMove (const Actor* target)
{
	rft.notifyClientMove(target, target->moveinfo.steps - 1, false);
}
Ejemplo n.º 19
0
void G_ReactionFireNotifyClientStartMove (const Actor* target)
{
	/* note that this is sent _before_ the actual move event, so we can't use the step number */
	rft.notifyClientMove(target, MAX_ROUTE, true);
}
Ejemplo n.º 20
0
static void G_ReactionFireNotifyClientEndShot (const Edict* target)
{
	rft.notifyClientMove(target, MAX_ROUTE, false);
}
Ejemplo n.º 21
0
/**
 * @brief free function to create a table of reaction fire targets for the given edict.
 * @param[in] shooter The reaction firing actor
 */
void G_ReactionFireTargetsCreate (const Edict* shooter)
{
	rft.create(shooter);
}
Ejemplo n.º 22
0
void ReactionFire::resetTargets (const Edict* shooter)
{
	rft.resetTargetList(shooter);
}