Esempio n. 1
0
/**
 * @param[in] team The team looking at the edict (or not)
 * @param[in] check The edict to check the visibility for
 * @param[in] visFlags The flags for the vis check
 * @param[in] playerMask The mask for the players to send the appear/perish events to. If this is @c 0 the events
 * are not sent - we only update the visflags of the edict
 * @param[in] ent The edict that was responsible for letting the check edict appear and is looking
 */
static int G_DoTestVis (const int team, Edict* check, const vischeckflags_t visFlags, playermask_t playerMask, const Edict* ent)
{
	int status = 0;
	const int vis = G_TestVis(team, check, visFlags);

	/* visibility has changed ... */
	if (vis & VS_CHANGE) {
		/* swap the vis mask for the given team */
		const bool appear = (vis & VS_YES) == VS_YES;
		if (playerMask == 0) {
			G_VisFlagsSwap(*check, G_TeamToVisMask(team));
		} else {
			G_AppearPerishEvent(playerMask, appear, *check, ent);
		}

		/* ... to visible */
		if (vis & VS_YES) {
			status |= VIS_APPEAR;
			if (G_VisShouldStop(check))
				status |= VIS_STOP;
		} else {
			status |= VIS_PERISH;
		}
	} else if (vis == 0 && (visFlags & VT_NEW)) {
		if (G_IsActor(check)) {
			G_EventActorAdd(playerMask, *check);
		}
	}
	return status;
}
Esempio n. 2
0
static void Reset_RescueTrigger (Edict* self, Edict* activator)
{
	if (G_IsActor(activator)) {
		Actor* actor = makeActor(activator);
		if (self->isSameTeamAs(actor))
			actor->setInRescueZone(false);
	}
}
Esempio n. 3
0
int G_VisCheckDist (const Edict* const ent)
{
	if (G_IsActiveCamera(ent))
		return MAX_SPOT_DIST_CAMERA;

	if (G_IsActor(ent))
		return MAX_SPOT_DIST * G_ActorGetInjuryPenalty(ent, MODIFIER_SIGHT);

	return MAX_SPOT_DIST;
}
Esempio n. 4
0
static bool G_CameraUse (Edict* self, Edict* activator)
{
	if (!activator || !G_IsActor(activator)) {
		return false;
	}

	self->toggleActive();

	return false;
}
Esempio n. 5
0
/**
 * @brief Make everything visible to anyone who can't already see it
 */
void G_VisMakeEverythingVisible (void)
{
	edict_t *ent = NULL;
	while ((ent = G_EdictsGetNextInUse(ent))) {
		const int playerMask = G_VisToPM(ent->visflags);
		G_AppearPerishEvent(~playerMask, true, ent, NULL);
		if (G_IsActor(ent))
			G_SendInventory(~G_TeamToPM(ent->team), ent);
	}
}
Esempio n. 6
0
/**
 * @brief Make everything visible to anyone who can't already see it
 */
void G_VisMakeEverythingVisible (void)
{
	Edict* ent = nullptr;
	while ((ent = G_EdictsGetNextInUse(ent))) {
		const int playerMask = G_VisToPM(ent->visflags);
		G_AppearPerishEvent(~playerMask, true, *ent, nullptr);
		if (G_IsActor(ent))
			G_SendInventory(~G_TeamToPM(ent->getTeam()), *ent);
	}
}
Esempio n. 7
0
/**
 * @brief Convert an Edict pointer into an Actor pointer
 */
Actor* makeActor (Edict* ent)
{
	if (G_IsActor(ent)) {
		/* should be a dynamic_cast one fine day */
		Actor* actor = static_cast<Actor*>(ent);
		if (actor)
			return actor;
	}
	Sys_Error("Unexpected non-Actor Edict found.");
	return nullptr;
}
Esempio n. 8
0
/**
 * @brief Iterate through the actor entities (even the dead! - but skips the invisible)
 * @param lastEnt The entity found in the previous iteration; if nullptr, we start at the beginning
 */
Edict* G_EdictsGetNextActor (Edict* lastEnt)
{
	Edict* ent = lastEnt;

	assert(lastEnt < &g_edicts[globals.num_edicts]);

	while ((ent = G_EdictsGetNextInUse(ent))) {
		if (G_IsActor(ent))
			break;
	}
	return ent;
}
Esempio n. 9
0
/**
 * @brief If an actor was standing on the breakable that is going to get destroyed, we have to let him fall to the ground
 * @param self The breakable edict
 * @param activator The touching edict
 * @note This touch function is only executed if the func_breakable edict has a HP level of 0 (e.g. it is already destroyed)
 * @return false because this is no client action
 */
static bool Touch_Breakable (edict_t *self, edict_t *activator)
{
    /* not yet broken */
    if (self->HP != 0)
        return false;

    /** @todo check that the actor is standing upon the breakable */
    if (G_IsActor(activator))
        G_ActorFall(activator);

    return false;
}
Esempio n. 10
0
/**
 * @brief Rescue trigger
 * @sa SP_trigger_resuce
 */
static bool Touch_RescueTrigger (Edict* self, Edict* activator)
{
	/* these actors should really not be able to trigger this - they don't move anymore */
	assert(!G_IsDead(activator));

	if (G_IsActor(activator)) {
		Actor* actor = makeActor(activator);
		if (self->isSameTeamAs(actor))
			actor->setInRescueZone(true);
	}

	return false;
}
Esempio n. 11
0
/**
 * @brief Iterate through the actor entities (even the dead!)
 * @param lastEnt The entity found in the previous iteration; if nullptr, we start at the beginning
 */
Actor* G_EdictsGetNextActor (Actor* lastEnt)
{
	Edict* ent = lastEnt;

	assert(lastEnt < &g_edicts[globals.num_edicts]);

	while ((ent = G_EdictsGetNextInUse(ent))) {
		if (G_IsActor(ent)) {
			Actor* actor = static_cast<Actor*>(ent);
			if (actor)
				return actor;
			Sys_Error("dynamic_cast to Actor failed.");
		}
	}
	return nullptr;
}
Esempio n. 12
0
static bool Message_Use (edict_t *self, edict_t *activator)
{
	if (!activator || !G_IsActor(activator)) {
		return false;
	} else {
		player_t *player = G_PLAYER_FROM_ENT(activator);
		const char *msg = self->message;
		/* remove gettext marker */
		if (msg[0] == '_')
			msg++;
		G_ClientPrintf(player, PRINT_HUD, "%s", msg);

		if (self->spawnflags & 1)
			G_FreeEdict(self);

		return false;
	}
}
Esempio n. 13
0
static bool Message_Use (Edict* self, Edict* activator)
{
	if (!activator || !G_IsActor(activator)) {
		return false;
	} else {
		Player& player = activator->getPlayer();
		const char* msg = self->message;
		/* remove gettext marker */
		if (msg[0] == '_')
			msg++;
		G_ClientPrintf(player, PRINT_HUD, "%s", msg);

		if (self->spawnflags & 1)
			G_FreeEdict(self);

		return false;
	}
}
Esempio n. 14
0
/**
 * @brief Function to calculate possible damages for mock pseudoaction.
 * @param[in,out] mock Pseudo action - only for calculating mock values - NULL for real action.
 * @param[in] shooter Pointer to attacker for this mock pseudoaction.
 * @param[in] struck Pointer to victim of this mock pseudoaction.
 * @param[in] damage Updates mock value of damage.
 * @note Called only from G_Damage().
 * @sa G_Damage
 */
static void G_UpdateShotMock (shot_mock_t *mock, const edict_t *shooter, const edict_t *struck, int damage)
{
	assert(struck->number != shooter->number || mock->allow_self);

	if (damage > 0) {
		if (!struck->inuse || G_IsDead(struck))
			return;
		else if (!G_IsVisibleForTeam(struck, shooter->team))
			return;
		else if (G_IsCivilian(struck))
			mock->civilian += 1;
		else if (struck->team == shooter->team)
			mock->friendCount += 1;
		else if (G_IsActor(struck))
			mock->enemyCount += 1;
		else
			return;

		mock->damage += damage;
	}
}
Esempio n. 15
0
/**
 * @brief Function to calculate possible damages for mock pseudoaction.
 * @param[in,out] mock Pseudo action - only for calculating mock values - nullptr for real action.
 * @param[in] shooter Pointer to attacker for this mock pseudoaction.
 * @param[in] struck Pointer to victim of this mock pseudoaction.
 * @param[in] damage Updates mock value of damage.
 * @note Called only from G_Damage().
 * @sa G_Damage
 */
static void G_UpdateShotMock (shot_mock_t* mock, const Edict* shooter, const Edict* struck, int damage)
{
	assert(!struck->isSameAs(shooter) || mock->allow_self);

	if (damage <= 0)
		return;

	if (!struck->inuse || G_IsDead(struck))
		return;

	if (!G_IsAI(shooter) && !G_IsVisibleForTeam(struck, shooter->getTeam()))
		return;

	if (G_IsCivilian(struck))
		mock->civilian += 1;
	else if (struck->isSameTeamAs(shooter))
		mock->friendCount += 1;
	else if (G_IsActor(struck))
		mock->enemyCount += 1;
	else
		return;

	mock->damage += damage;
}
Esempio n. 16
0
/**
 * @brief Applies the given damage value to an edict that is either an actor or has
 * the @c FL_DESTROYABLE flag set.
 * @param ent The edict to apply the damage to.
 * @param damage The damage value.
 * @note This function assures, that the health points of the edict are never
 * getting negative.
 * @sa G_Damage
 */
void G_TakeDamage (edict_t *ent, int damage)
{
    if (G_IsBreakable(ent) || G_IsActor(ent))
        ent->HP = max(ent->HP - damage, 0);
}
Esempio n. 17
0
/**
 * @brief Deals splash damage to a target and its surroundings.
 * @param[in] ent The shooting actor
 * @param[in] fd The fire definition that defines what type of damage is dealt and how big the splash radius is.
 * @param[in] impact The impact vector where the grenade is exploding
 * @param[in,out] mock pseudo shooting - only for calculating mock values - NULL for real shots
 * @param[in] tr The trace where the grenade hits something (or not)
 */
static void G_SplashDamage (edict_t *ent, const fireDef_t *fd, vec3_t impact, shot_mock_t *mock, const trace_t* tr)
{
	edict_t *check = NULL;
	vec3_t center;
	float dist;
	int damage;

	const bool shock = (fd->obj->dmgtype == gi.csi->damShock);

	assert(fd->splrad > 0.0);

	while ((check = G_EdictsGetNextInUse(check))) {
		/* If we use a blinding weapon we skip the target if it's looking
		 * away from the impact location. */
		if (shock && !G_FrustumVis(check, impact))
			continue;

		if (G_IsBrushModel(check) && G_IsBreakable(check))
			VectorCenterFromMinsMaxs(check->absmin, check->absmax, center);
		else if (G_IsLivingActor(check) || G_IsBreakable(check))
			VectorCopy(check->origin, center);
		else
			continue;

		/* check for distance */
		dist = VectorDist(impact, center);
		dist = dist > UNIT_SIZE / 2 ? dist - UNIT_SIZE / 2 : 0;
		if (dist > fd->splrad)
			continue;

		if (fd->irgoggles) {
			if (G_IsActor(check)) {
				/* check whether this actor (check) is in the field of view of the 'shooter' (ent) */
				if (G_FrustumVis(ent, check->origin)) {
					if (!mock) {
						const unsigned int playerMask = G_TeamToPM(ent->team) ^ G_VisToPM(check->visflags);
						G_AppearPerishEvent(playerMask, true, check, ent);
						G_VisFlagsAdd(check, G_PMToVis(playerMask));
					}
				}
			}
			continue;
		}

		/* check for walls */
		if (G_IsLivingActor(check) && !G_ActorVis(impact, ent, check, false))
			continue;

		/* do damage */
		if (shock)
			damage = 0;
		else
			damage = fd->spldmg[0] * (1.0 - dist / fd->splrad);

		if (mock)
			mock->allow_self = true;
		G_Damage(check, fd, damage, ent, mock, NULL);
		if (mock)
			mock->allow_self = false;
	}

	/** @todo splash might also hit other surfaces and the trace doesn't handle that */
	if (tr && G_FireAffectedSurface(tr->surface, fd)) {
		/* move a little away from the impact vector */
		VectorMA(impact, 1, tr->plane.normal, impact);
		G_SpawnParticle(impact, tr->contentFlags >> 8, "burning");
	}
Esempio n. 18
0
/**
 * @brief Checks whether the given edict is a living actor
 * @param[in] ent The edict to perform the check for
 * @sa LE_IsLivingActor
 */
bool G_IsLivingActor (const Edict* ent)
{
	return G_IsActor(ent) && (G_IsStunned(ent) || !G_IsDead(ent));
}