Example #1
0
/**
 * @sa G_MoraleStopPanic
 * @sa G_MoraleRage
 * @sa G_MoraleStopRage
 * @sa G_MoraleBehaviour
 */
static void G_MoralePanic (edict_t * ent, qboolean sanity)
{
	G_ClientPrintf(G_PLAYER_FROM_ENT(ent), PRINT_HUD, _("%s panics!\n"), ent->chr.name);

	/* drop items in hands */
	if (!sanity && ent->chr.teamDef->weapons) {
		if (RIGHT(ent))
			G_ActorInvMove(ent, INVDEF(gi.csi->idRight), RIGHT(ent),
					INVDEF(gi.csi->idFloor), NONE, NONE, qtrue);
		if (LEFT(ent))
			G_ActorInvMove(ent, INVDEF(gi.csi->idLeft), LEFT(ent),
					INVDEF(gi.csi->idFloor), NONE, NONE, qtrue);
	}

	/* get up */
	G_RemoveCrouched(ent);
	G_ActorSetMaxs(ent);

	/* send panic */
	G_SetPanic(ent);
	G_EventSendState(G_VisToPM(ent->visflags), ent);

	/* center view */
	G_EventCenterView(ent);

	/* move around a bit, try to avoid opponents */
	AI_ActorThink(G_PLAYER_FROM_ENT(ent), ent);

	/* kill TUs */
	G_ActorSetTU(ent, 0);
}
Example #2
0
/**
 * @sa G_MoraleStopPanic
 * @sa G_MoraleRage
 * @sa G_MoraleStopRage
 * @sa G_MoraleBehaviour
 */
static void G_MoralePanic (Edict* ent)
{
	G_ClientPrintf(ent->getPlayer(), PRINT_HUD, _("%s panics!"), ent->chr.name);
	G_PrintStats("%s panics (entnum %i).", ent->chr.name, ent->getIdNum());
	/* drop items in hands */
	if (G_IsInsane(ent) && ent->chr.teamDef->weapons) {
		if (ent->getRightHandItem())
			G_ActorInvMove(ent, INVDEF(CID_RIGHT), ent->getRightHandItem(),
					INVDEF(CID_FLOOR), NONE, NONE, true);
		if (ent->getLeftHandItem())
			G_ActorInvMove(ent, INVDEF(CID_LEFT), ent->getLeftHandItem(),
					INVDEF(CID_FLOOR), NONE, NONE, true);
		G_ClientStateChange(ent->getPlayer(), ent, ~STATE_REACTION, false);
	}

	/* get up */
	G_RemoveCrouched(ent);
	G_ActorSetMaxs(ent);

	/* send panic */
	G_SetPanic(ent);
	G_EventSendState(G_VisToPM(ent->visflags), *ent);

	/* center view */
	G_EventCenterView(*ent);

	/* move around a bit, try to avoid opponents */
	AI_ActorThink(ent->getPlayer(), ent);

	/* kill TUs */
	G_ActorSetTU(ent, 0);
}
Example #3
0
/**
 * @brief Announce the actor die event for the clients that are seeing the actor
 * @param[in] ent The actor that is dying
 */
void G_EventActorDie (const edict_t* ent)
{
	G_EventAdd(G_VisToPM(ent->visflags), EV_ACTOR_DIE, ent->number);
	gi.WriteShort(ent->state);
	gi.WriteByte(ent->pnum);
	G_EventEnd();
}
Example #4
0
/**
 * @brief Stops the rage state of an actor
 * @note This is only called when cvar mor_panic is not zero
 * @sa G_MoralePanic
 * @sa G_MoraleRage
 * @sa G_MoraleStopPanic
 * @sa G_MoraleBehaviour
 */
static void G_MoraleStopRage (edict_t * ent)
{
	if (ent->morale / mor_panic->value > m_rage_stop->value * frand()) {
		G_RemoveInsane(ent);
		G_EventSendState(G_VisToPM(ent->visflags), ent);
	} else
		G_MoralePanic(ent, qtrue); /* regains sanity */
}
Example #5
0
/**
 * @brief Start the shooting event
 * @param ent The entity that starts the shooting
 * @param visMask the vis mask of the teams to determine the clients from this event is send to
 * @param shootType The type of the shoot
 * @param at The grid position to target to
 */
void G_EventStartShoot (const edict_t* ent, vismask_t visMask, shoot_types_t shootType, const pos3_t at)
{
	G_EventAdd(G_VisToPM(visMask), EV_ACTOR_START_SHOOT, ent->number);
	gi.WriteByte(shootType);
	gi.WriteGPos(ent->pos);
	gi.WriteGPos(at);
	G_EventEnd();
}
Example #6
0
/**
 * @brief Announce the actor die event for the clients that are seeing the actor
 * @param[in] ent The actor that is dying
 */
void G_EventActorDie (const Edict& ent, bool attacker)
{
	G_EventAdd(G_VisToPM(ent.visflags), EV_ACTOR_DIE, ent.number);
	gi.WriteShort(ent.state);
	gi.WriteByte(ent.pnum);
	gi.WriteByte(attacker);
	G_EventEnd();
}
Example #7
0
/**
 * @brief Start the shooting event
 * @param ent The entity that starts the shooting
 * @param teamMask the vis mask of the teams to determine the clients from this event is send to
 * @param shootType The type of the shoot
 * @param at The grid position to target to
 */
void G_EventStartShoot (const Edict& ent, teammask_t teamMask, shoot_types_t shootType, const pos3_t at)
{
	G_EventAdd(G_VisToPM(teamMask), EV_ACTOR_START_SHOOT, ent.number);
	gi.WriteByte(shootType);
	gi.WriteGPos(ent.pos);
	gi.WriteGPos(at);
	G_EventEnd();
}
Example #8
0
/**
 * @brief Applies morale behaviour on actors
 * @note only called when mor_panic is not zero
 * @sa G_MoralePanic
 * @sa G_MoraleRage
 * @sa G_MoraleStopRage
 * @sa G_MoraleStopPanic
 */
void G_MoraleBehaviour (int team)
{
	edict_t *ent = NULL;
	int newMorale;

	while ((ent = G_EdictsGetNextInUse(ent))) {
		/* this only applies to ET_ACTOR but not to ET_ACTOR2x2 */
		if (ent->type == ET_ACTOR && ent->team == team && !G_IsDead(ent)) {
			/* civilians have a 1:1 chance to randomly run away in multiplayer */
			if (sv_maxclients->integer >= 2 && level.activeTeam == TEAM_CIVILIAN && 0.5 > frand())
				G_MoralePanic(ent, qfalse);
			/* multiplayer needs enabled sv_enablemorale */
			/* singleplayer has this in every case */
			if (G_IsMoraleEnabled()) {
				/* if panic, determine what kind of panic happens: */
				if (ent->morale <= mor_panic->value && !G_IsPaniced(ent) && !G_IsRaged(ent)) {
					qboolean sanity;
					if ((float) ent->morale / mor_panic->value > (m_sanity->value * frand()))
						sanity = qtrue;
					else
						sanity = qfalse;
					if ((float) ent->morale / mor_panic->value > (m_rage->value * frand()))
						G_MoralePanic(ent, sanity);
					else
						G_MoraleRage(ent, sanity);
					/* if shaken, well .. be shaken; */
				} else if (ent->morale <= mor_shaken->value && !G_IsPaniced(ent)
						&& !G_IsRaged(ent)) {
					/* shaken is later reset along with reaction fire */
					G_SetShaken(ent);
					G_SetState(ent, STATE_REACTION);
					G_EventSendState(G_VisToPM(ent->visflags), ent);
					G_ClientPrintf(G_PLAYER_FROM_ENT(ent), PRINT_HUD, _("%s is currently shaken.\n"),
							ent->chr.name);
				} else {
					if (G_IsPaniced(ent))
						G_MoraleStopPanic(ent);
					else if (G_IsRaged(ent))
						G_MoraleStopRage(ent);
				}
			}

			G_ActorSetMaxs(ent);

			/* morale-regeneration, capped at max: */
			newMorale = ent->morale + MORALE_RANDOM(mor_regeneration->value);
			if (newMorale > GET_MORALE(ent->chr.score.skills[ABILITY_MIND]))
				ent->morale = GET_MORALE(ent->chr.score.skills[ABILITY_MIND]);
			else
				ent->morale = newMorale;

			/* send phys data and state: */
			G_SendStats(ent);
			gi.EndEvents();
		}
	}
}
Example #9
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);
	}
}
Example #10
0
/**
 * @brief Stops the rage state of an actor
 * @note This is only called when cvar mor_panic is not zero
 * @sa G_MoralePanic
 * @sa G_MoraleRage
 * @sa G_MoraleStopPanic
 * @sa G_MoraleBehaviour
 */
static void G_MoraleStopRage (Edict *ent)
{
	if (ent->morale / mor_panic->value > m_rage_stop->value * frand()) {
		G_RemoveInsane(ent);
		G_EventSendState(G_VisToPM(ent->visflags), *ent);
		G_PrintStats("%s is no longer insane (entnum %i).", ent->chr.name, ent->number);
	} else {
		G_MoralePanic(ent, true); /* regains sanity */
	}
}
Example #11
0
/**
 * @brief Stops the panic state of an actor
 * @note This is only called when cvar mor_panic is not zero
 * @sa G_MoralePanic
 * @sa G_MoraleRage
 * @sa G_MoraleStopRage
 * @sa G_MoraleBehaviour
 */
static void G_MoraleStopPanic (Edict *ent)
{
	if (ent->morale / mor_panic->value > m_panic_stop->value * frand()) {
		G_RemovePanic(ent);
		G_PrintStats("%s is no longer panicked (entnum %i).", ent->chr.name, ent->number);
		G_EventSendState(G_VisToPM(ent->visflags), *ent);
	} else {
		G_MoralePanic(ent, true);
	}
}
Example #12
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);
	}
}
Example #13
0
static void Think_SmokeAndFire (edict_t *self)
{
	if (self->time + self->count <= level.actualRound) {
		bool checkVis = self->type == ET_SMOKE;
		G_EventEdictPerish(G_VisToPM(self->particleLink->visflags), self->particleLink);
		G_FreeEdict(self->particleLink);
		G_FreeEdict(self);
		if (checkVis)
			G_CheckVis(NULL);
	}
}
Example #14
0
/**
 * @brief Applies morale behaviour on actors
 * @note only called when mor_panic is not zero
 * @sa G_MoralePanic
 * @sa G_MoraleRage
 * @sa G_MoraleStopRage
 * @sa G_MoraleStopPanic
 */
void G_MoraleBehaviour (int team)
{
	bool enabled = G_IsMoraleEnabled(team);
	if (!enabled)
		return;

	Edict* ent = nullptr;
	while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, team)) != nullptr) {
		/* this only applies to ET_ACTOR but not to ET_ACTOR2x2 */
		if (ent->type != ET_ACTOR || CHRSH_IsTeamDefRobot(ent->chr.teamDef))
			continue;

		/* if panic, determine what kind of panic happens: */
		if (!G_IsPanicked(ent) && !G_IsRaged(ent)) {
			if (ent->morale <= mor_panic->integer) {
				const float ratio = (float) ent->morale / mor_panic->value;
				const bool sanity = ratio > (m_sanity->value * frand());
				if (!sanity)
					G_SetInsane(ent);
				if (ratio > (m_rage->value * frand()))
					G_MoralePanic(ent);
				else
					G_MoraleRage(ent);
				/* if shaken, well .. be shaken; */
			} else if (ent->morale <= mor_shaken->integer) {
				/* shaken is later reset along with reaction fire */
				G_SetShaken(ent);
				G_ClientStateChange(ent->getPlayer(), ent, STATE_REACTION, false);
				G_EventSendState(G_VisToPM(ent->visflags), *ent);
				G_ClientPrintf(ent->getPlayer(), PRINT_HUD, _("%s is currently shaken."),
						ent->chr.name);
				G_PrintStats("%s is shaken (entnum %i).", ent->chr.name, ent->getIdNum());
			}
		} else {
			if (G_IsPanicked(ent))
				G_MoraleStopPanic(ent);
			else if (G_IsRaged(ent))
				G_MoraleStopRage(ent);
		}

		G_ActorSetMaxs(ent);

		/* morale-regeneration, capped at max: */
		int newMorale = ent->morale + MORALE_RANDOM(mor_regeneration->value);
		const int maxMorale = GET_MORALE(ent->chr.score.skills[ABILITY_MIND]);
		if (newMorale > maxMorale)
			ent->morale = maxMorale;
		else
			ent->morale = newMorale;

		/* send phys data and state: */
		G_SendStats(*ent);
	}
}
Example #15
0
/**
 * @param[in] teamMask the vis mask to determine the clients from this event is send to
 * @param[in] fd The firedefinition to use
 * @param[in] dt Delta time
 * @param[in] flags bitmask of the following values: @c SF_BODY, @c SF_IMPACT, @c SF_BOUNCING and @c SF_BOUNCED
 * @param[in] position The current position
 * @param[in] velocity The velocity of the throw
 */
void G_EventThrow (teammask_t teamMask, const fireDef_t* fd, float dt, byte flags, const vec3_t position, const vec3_t velocity)
{
	G_EventAdd(G_VisToPM(teamMask), EV_ACTOR_THROW, -1);
	gi.WriteShort(dt * 1000);
	gi.WriteShort(fd->obj->idx);
	gi.WriteByte(fd->weapFdsIdx);
	gi.WriteByte(fd->fdIdx);
	gi.WriteByte(flags);
	gi.WritePos(position);
	gi.WritePos(velocity);
	G_EventEnd();
}
Example #16
0
void G_EventActorFall (const Edict& ent)
{
	G_EventAdd(G_VisToPM(ent.visflags), EV_ACTOR_MOVE, ent.number);
	gi.WriteByte(1);
	gi.WriteByte(ent.pos[0]);
	gi.WriteByte(ent.pos[1]);
	gi.WriteByte(ent.pos[2]);
	gi.WriteByte(makeDV(DIRECTION_FALL, ent.pos[2]));
	gi.WriteShort(GRAVITY);
	gi.WriteShort(0);
	G_EventEnd();
}
Example #17
0
static void Think_SmokeAndFire (Edict* self)
{
	const int endRound = self->time + self->count;
	const int spawnIndex = (self->team + level.teamOfs) % MAX_TEAMS;
	const int currentIndex = (level.activeTeam + level.teamOfs) % MAX_TEAMS;
	if (endRound < level.actualRound || (endRound == level.actualRound && spawnIndex <= currentIndex)) {
		const bool checkVis = self->type == ET_SMOKE;
		G_EventEdictPerish(G_VisToPM(self->particleLink->visflags), *self->particleLink);
		G_FreeEdict(self->particleLink);
		G_FreeEdict(self);
		if (checkVis)
			G_CheckVis(nullptr);
	}
}
Example #18
0
/**
 * @brief Change the amount of available ammo for the given entity
 * @param ent The entity to change the amount of ammo for
 * @param ammo The ammo to change
 * @param amount The new amount of the left ammo
 * @param shootType The shooting type to determine which container to use
 */
void G_EventInventoryAmmo (const Edict& ent, const objDef_t* ammo, int amount, shoot_types_t shootType)
{
	G_EventAdd(G_VisToPM(ent.visflags), EV_INV_AMMO, ent.number);
	gi.WriteByte(amount);
	gi.WriteByte(ammo->idx);
	if (IS_SHOT_RIGHT(shootType))
		gi.WriteByte(CID_RIGHT);
	else
		gi.WriteByte(CID_LEFT);
	/* x and y value */
	gi.WriteByte(0);
	gi.WriteByte(0);
	G_EventEnd();
}
Example #19
0
/**
 * @sa G_MoralePanic
 * @sa G_MoraleStopPanic
 * @sa G_MoraleStopRage
 * @sa G_MoraleBehaviour
 */
static void G_MoraleRage (edict_t * ent, qboolean sanity)
{
	if (sanity)
		G_SetRage(ent);
	else
		G_SetInsane(ent);
	G_EventSendState(G_VisToPM(ent->visflags), ent);

	if (sanity)
		gi.BroadcastPrintf(PRINT_HUD, _("%s is on a rampage.\n"), ent->chr.name);
	else
		gi.BroadcastPrintf(PRINT_HUD, _("%s is consumed by mad rage!\n"), ent->chr.name);
	AI_ActorThink(G_PLAYER_FROM_ENT(ent), ent);
}
Example #20
0
/**
 * @brief Change the amount of available ammo for the given entity
 * @param ent The entity to change the amount of ammo for
 * @param ammo The ammo to change
 * @param amount The new amount of the left ammo
 * @param shootType The shooting type to determine which container to use
 */
void G_EventInventoryAmmo (const edict_t* ent, const objDef_t* ammo, int amount, shoot_types_t shootType)
{
	G_EventAdd(G_VisToPM(ent->visflags), EV_INV_AMMO, ent->number);
	gi.WriteByte(amount);
	gi.WriteByte(ammo->idx);
	if (IS_SHOT_RIGHT(shootType))
		gi.WriteByte(gi.csi->idRight);
	else
		gi.WriteByte(gi.csi->idLeft);
	/* x and y value */
	gi.WriteByte(0);
	gi.WriteByte(0);
	G_EventEnd();
}
Example #21
0
/**
 * @sa G_MoralePanic
 * @sa G_MoraleStopPanic
 * @sa G_MoraleStopRage
 * @sa G_MoraleBehaviour
 */
static void G_MoraleRage (Edict* ent)
{
	G_SetRage(ent);
	if (!G_IsInsane(ent)) {
		gi.BroadcastPrintf(PRINT_HUD, _("%s is on a rampage!"), ent->chr.name);
		G_PrintStats("%s is on a rampage (entnum %i).", ent->chr.name, ent->getIdNum());
	} else {
		gi.BroadcastPrintf(PRINT_HUD, _("%s is consumed by mad rage!"), ent->chr.name);
		G_PrintStats("%s is consumed by mad rage (entnum %i).", ent->chr.name, ent->getIdNum());
	}
	G_EventSendState(G_VisToPM(ent->visflags), *ent);
	G_ClientStateChange(ent->getPlayer(), ent, ~STATE_REACTION, false);

	AI_ActorThink(ent->getPlayer(), ent);
}
Example #22
0
/**
 * @sa G_MoralePanic
 * @sa G_MoraleStopPanic
 * @sa G_MoraleStopRage
 * @sa G_MoraleBehaviour
 */
static void G_MoraleRage (edict_t *ent, bool sanity)
{
	if (sanity) {
		G_SetRage(ent);
		gi.BroadcastPrintf(PRINT_HUD, _("%s is on a rampage!"), ent->chr.name);
		G_PrintStats("%s is on a rampage (entnum %i).", ent->chr.name, ent->number);
	} else {
		G_SetInsane(ent);
		gi.BroadcastPrintf(PRINT_HUD, _("%s is consumed by mad rage!"), ent->chr.name);
		G_PrintStats("%s is consumed by mad rage (entnum %i).", ent->chr.name, ent->number);
	}
	G_EventSendState(G_VisToPM(ent->visflags), ent);

	AI_ActorThink(G_PLAYER_FROM_ENT(ent), ent);
}
Example #23
0
/**
 * @brief Writes a step of the move event to the net
 * @param[in] ent Edict to move
 * @param[in] stepAmount Pointer to the amount of steps in this move-event
 * @param[in] dvec The direction vector for the step to be added
 * @param[in] contentFlags The material we are walking over
 */
static void G_WriteStep (edict_t* ent, byte** stepAmount, const int dvec, const int contentFlags)
{
    /* write move header if not yet done */
    if (gi.GetEvent() != EV_ACTOR_MOVE) {
        gi.AddEvent(G_VisToPM(ent->visflags), EV_ACTOR_MOVE);
        gi.WriteShort(ent->number);
        /* stepAmount is a pointer to a location in the netchannel
         * the value of this pointer depends on how far the actor walks
         * and this might be influenced at a later stage inside this
         * loop. That's why we can modify the value of this byte
         * if e.g. a VIS_STOP occurred and no more steps should be made.
         * But keep in mind, that no other events might be between
         * this event and its successful end - otherwise the
         * stepAmount pointer would no longer be valid and you would
         * modify data in the new event. */
        *stepAmount = gi.WriteDummyByte(0);
        /* Add three more dummy bytes.  These will be the final actor position. */
        gi.WriteDummyByte(0); /* x */
        gi.WriteDummyByte(0); /* y */
        gi.WriteDummyByte(0); /* z */
    } else if (!*stepAmount) {
        gi.DPrintf("Event %i activate and no stepAmount pointer set\n", gi.GetEvent());
        return;
    }

    /* the moveinfo stuff is used inside the G_PhysicsStep think function */
    if (ent->moveinfo.steps >= MAX_DVTAB) {
        ent->moveinfo.steps = 0;
        ent->moveinfo.currentStep = 0;
    }
    ent->moveinfo.contentFlags[ent->moveinfo.steps] = contentFlags;
    ent->moveinfo.visflags[ent->moveinfo.steps] = ent->visflags;
    ent->moveinfo.steps++;

    /* store steps in netchannel */
    byte *pStep = *stepAmount;
    (*pStep)++;
    /* store the position too */
    *(pStep + 1) = ent->pos[0];
    *(pStep + 2) = ent->pos[1];
    *(pStep + 3) = ent->pos[2];

    /* write move header and always one step after another - because the next step
     * might already be the last one due to some stop event */
    gi.WriteShort(dvec);
    gi.WriteShort(ent->speed);
    gi.WriteShort(contentFlags);
}
Example #24
0
/**
 * @brief After an actor changed his state, he might get visible for other
 * players. Check the vis here and send the state change to the clients that
 * are seeing him already.
 * @param ent The actor edict
 */
static void G_ClientStateChangeUpdate (edict_t *ent)
{
	/* Send the state change. */
	G_EventSendState(G_VisToPM(ent->visflags), ent);

	/* Check if the player appears/perishes, seen from other teams. */
	G_CheckVis(ent);

	/* Calc new vis for this player. */
	G_CheckVisTeamAll(ent->team, 0, ent);

	/* Send the new TUs. */
	G_SendStats(ent);

	/* End the event. */
	G_EventEnd();
}
Example #25
0
/**
 * @brief Removes one particular item from a given container
 * @param itemID The id of the item to remove
 * @param ent The edict that holds the inventory to remove the item from
 * @param container The container in the inventory of the edict to remove the searched item from.
 * @return @c true if the removal was successful, @c false otherwise.
 */
bool G_InventoryRemoveItemByID (const char *itemID, edict_t *ent, containerIndex_t container)
{
	invList_t *ic = CONTAINER(ent, container);
	while (ic) {
		const objDef_t *item = ic->item.item;
		if (item != NULL && Q_streq(item->id, itemID)) {
			/* remove the virtual item to update the inventory lists */
			if (!game.i.RemoveFromInventory(&game.i, &ent->chr.i, INVDEF(container), ic))
				gi.Error("Could not remove item '%s' from inventory %i",
						ic->item.item->id, container);
			G_EventInventoryDelete(ent, G_VisToPM(ent->visflags), INVDEF(container), ic->x, ic->y);
			return true;
		}
		ic = ic->next;
	}

	return false;
}
Example #26
0
/**
 * @brief Updates the reaction fire settings in case something was moved into a hand or from a hand
 * that would make the current settings invalid
 * @param[in,out] actor The actor edict to check the settings for
 * @param[in] fmIdx The fire mode index that should be used for reaction fire
 * @param[in] hand The hand that should be used for reaction fire
 * @param[in] od The object/weapon for the reaction fire
 */
void G_ReactionFireSettingsUpdate (Actor* actor, fireDefIndex_t fmIdx, actorHands_t hand, const objDef_t* od)
{
	actor->chr.RFmode.set(hand, fmIdx, od);	/* FiremodeSettings */

	if (!G_ActorHasWorkingFireModeSet(actor)) {
		/* Disable reaction fire if no valid firemode was found. */
		G_ClientStateChange(actor->getPlayer(), actor, ~STATE_REACTION, false);
		G_EventReactionFireChange(*actor);
		G_EventSendState(G_VisToPM(actor->visflags), *actor);
		return;
	}

	G_EventReactionFireChange(*actor);

	/* If reaction fire is active, update the reserved TUs */
	if (actor->isReaction()) {
		G_ReactionFireSettingsReserveTUs(actor);
	}
}
Example #27
0
/**
 * @brief Do the shooting
 * @param ent The entity that is doing the shooting
 * @param visMask the vis mask to determine the clients from this event is send to
 * @param fd The firedefinition to use for the shoot
 * @param firstShoot Is this the first shoot
 * @param shootType The type of the shoot
 * @param flags Define some flags in a bitmask: @c SF_BODY, @c SF_IMPACT, @c SF_BOUNCING and @c SF_BOUNCING
 * @param trace The trace what was used to determine whether this shot has hit something
 * @param from The position the entity shoots from
 * @param impact The impact world vector for the shot
 */
void G_EventShoot (const edict_t* ent, vismask_t visMask, const fireDef_t* fd, bool firstShoot, shoot_types_t shootType, int flags, const trace_t* trace, const vec3_t from, const vec3_t impact)
{
	const edict_t *targetEdict = trace->ent;

	G_EventAdd(G_VisToPM(visMask), EV_ACTOR_SHOOT, ent->number);
	if (targetEdict && G_IsBreakable(targetEdict))
		gi.WriteShort(targetEdict->number);
	else
		gi.WriteShort(SKIP_LOCAL_ENTITY);
	gi.WriteByte(firstShoot ? 1 : 0);
	gi.WriteShort(fd->obj->idx);
	gi.WriteByte(fd->weapFdsIdx);
	gi.WriteByte(fd->fdIdx);
	gi.WriteByte(shootType);
	gi.WriteByte(flags);
	gi.WriteByte(trace->contentFlags);
	gi.WritePos(from);
	gi.WritePos(impact);
	gi.WriteDir(trace->plane.normal);
	G_EventEnd();
}
Example #28
0
/**
 * @brief Do the shooting
 * @param ent The entity that is doing the shooting
 * @param teamMask the vis mask to determine the clients from this event is send to
 * @param fd The firedefinition to use for the shoot
 * @param firstShoot Is this the first shoot
 * @param shootType The type of the shoot
 * @param flags Define some flags in a bitmask: @c SF_BODY, @c SF_IMPACT, @c SF_BOUNCING and @c SF_BOUNCING
 * @param trace The trace what was used to determine whether this shot has hit something
 * @param from The position the entity shoots from
 * @param impact The impact world vector for the shot
 */
void G_EventShoot (const Edict& ent, teammask_t teamMask, const fireDef_t* fd, bool firstShoot, shoot_types_t shootType, int flags, const trace_t* trace, const vec3_t from, const vec3_t impact)
{
	const Edict* targetEdict = G_EdictsGetByNum(trace->entNum);	/* the ent possibly hit by the trace */

	G_EventAdd(G_VisToPM(teamMask), EV_ACTOR_SHOOT, ent.number);
	if (targetEdict && G_IsBreakable(targetEdict))
		gi.WriteShort(targetEdict->number);
	else
		gi.WriteShort(SKIP_LOCAL_ENTITY);
	gi.WriteByte(firstShoot ? 1 : 0);
	gi.WriteShort(fd->obj->idx);
	gi.WriteByte(fd->weapFdsIdx);
	gi.WriteByte(fd->fdIdx);
	gi.WriteByte(shootType);
	gi.WriteByte(flags);
	gi.WriteByte(trace->contentFlags);
	gi.WritePos(from);
	gi.WritePos(impact);
	gi.WriteDir(trace->plane.normal);
	G_EventEnd();
}
Example #29
0
/**
 * @brief Writes a step of the move event to the net
 * @param[in] ent Edict to move
 * @param[in] stepAmount Pointer to the amount of steps in this move-event
 * @param[in] dvec The direction vector for the step to be added
 * @param[in] contentFlags The material we are walking over
 */
static void G_WriteStep (edict_t* ent, byte** stepAmount, const int dvec, const int contentFlags)
{
	/* write move header if not yet done */
	if (gi.GetEvent() != EV_ACTOR_MOVE) {
		G_EventAdd(G_VisToPM(ent->visflags), EV_ACTOR_MOVE, ent->number);
	}

	/* the moveinfo stuff is used inside the G_PhysicsStep think function */
	if (ent->moveinfo.steps >= MAX_ROUTE) {
		ent->moveinfo.steps = 0;
		ent->moveinfo.currentStep = 0;
	}
	ent->moveinfo.contentFlags[ent->moveinfo.steps] = contentFlags;
	ent->moveinfo.visflags[ent->moveinfo.steps] = ent->visflags;
	ent->moveinfo.steps++;

	/* write move header and always one step after another - because the next step
	 * might already be the last one due to some stop event */
	gi.WriteShort(dvec);
	gi.WriteShort(ent->speed);
	gi.WriteShort(contentFlags);
}
Example #30
0
/**
 * @note Think functions are only executed when the match is running
 * or in other word, the game has started
 */
void G_MissionThink (Edict* self)
{
	if (!G_MatchIsRunning())
		return;

	/* when every player has joined the match - spawn the mission target
	 * particle (if given) to mark the trigger */
	if (self->particle) {
		self->link = G_SpawnParticle(self->origin, self->spawnflags, self->particle);

		/* This is automatically freed on map shutdown */
		self->particle = nullptr;
	}

	Edict* chain = self->groupMaster;
	if (!chain)
		chain = self;
	while (chain) {
		if (chain->type == ET_MISSION) {
			if (chain->item) {
				const Item* ic;
				G_GetFloorItems(chain);
				ic = chain->getFloor();
				if (!ic) {
					/* reset the counter if there is no item */
					chain->count = 0;
					return;
				}
				for (; ic; ic = ic->getNext()) {
					const objDef_t* od = ic->def();
					assert(od);
					/* not the item we are looking for */
					if (Q_streq(od->id, chain->item))
						break;
				}
				if (!ic) {
					/* reset the counter if it's not the searched item */
					chain->count = 0;
					return;
				}
			}
			if (chain->time) {
				/* Check that the target zone is still occupied (last defender might have died) */
				if (!chain->item && !G_MissionIsTouched(chain)) {
						chain->count = 0;
				}
				const int endTime = level.actualRound - chain->count;
				const int spawnIndex = (chain->getTeam() + level.teamOfs) % MAX_TEAMS;
				const int currentIndex = (level.activeTeam + level.teamOfs) % MAX_TEAMS;
				/* not every edict in the group chain has
				 * been occupied long enough */
				if (!chain->count || endTime < chain->time ||
						(endTime == chain->time && spawnIndex < currentIndex))
					return;
			}
			if (chain->target && !chain->time && !chain->item) {
				if (!G_MissionIsTouched(chain))
					return;
			}
		}
		chain = chain->groupChain;
	}

	const bool endMission = self->target == nullptr;

	/* store team before the edict is released */
	const int team = self->getTeam();
	chain = self->groupMaster;
	if (!chain)
		chain = self;
	while (chain) {
		if (chain->type == ET_MISSION) {
			G_UseEdict(chain, nullptr);
			if (chain->item != nullptr) {
				Edict* item = G_GetEdictFromPos(chain->pos, ET_ITEM);
				if (item != nullptr) {
					if (!G_InventoryRemoveItemByID(chain->item, item, CID_FLOOR)) {
						Com_Printf("Could not remove item '%s' from floor edict %i\n", chain->item, item->getIdNum());
					} else if (!item->getFloor()) {
						G_EventPerish(*item);
						G_FreeEdict(item);
					}
				}
			}
			if (chain->link != nullptr) {
				Edict* particle = G_GetEdictFromPos(chain->pos, ET_PARTICLE);
				if (particle != nullptr) {
					G_AppearPerishEvent(G_VisToPM(particle->visflags), false, *particle, nullptr);
					G_FreeEdict(particle);
				}
				chain->link = nullptr;
			}

			/* Display mission message */
			if (G_ValidMessage(chain)) {
				const char* msg = chain->message;
				if (msg[0] == '_')
					++msg;
				gi.BroadcastPrintf(PRINT_HUD, "%s", msg);
			}
		}

		Edict* ent = chain->groupChain;
		/* free the group chain */
		G_FreeEdict(chain);
		chain = ent;
	}

	if (endMission)
		G_MatchEndTrigger(team, level.activeTeam == TEAM_ALIEN ? 10 : 3);
}