コード例 #1
0
ファイル: g_morale.cpp プロジェクト: cigo/ufoai
/**
 * @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);
}
コード例 #2
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);
}
コード例 #3
0
ファイル: g_mission.cpp プロジェクト: MyWifeRules/ufoai-1
/**
 * @brief Mission trigger
 * @todo use level.nextmap to spawn another map when every living actor has touched the mission trigger
 * @todo use level.actualRound to determine the 'King of the Hill' time
 * @note Don't set a client action here - otherwise the movement event might
 * be corrupted
 */
bool G_MissionTouch (edict_t *self, edict_t *activator)
{
	if (!self->owner)
		return false;

	switch (self->owner->team) {
	case TEAM_ALIEN:
		if (G_IsAlien(activator)) {
			if (!self->count) {
				self->count = level.actualRound;
				gi.BroadcastPrintf(PRINT_HUD, _("Aliens entered target zone!"));
			}
			return true;
		} else {
			/* reset king of the hill counter */
			self->count = 0;
		}
	/* general case that also works for multiplayer teams */
	default:
		if (activator->team == self->owner->team) {
			if (!self->owner->count) {
				self->owner->count = level.actualRound;
				if (self->owner->item) {
					/* search the item in the activator's inventory */
					containerIndex_t container;

					for (container = 0; container < gi.csi->numIDs; container++) {
						const invDef_t *invDef = INVDEF(container);
						invList_t *ic;
						/* ignore items linked from any temp container the actor
						 * must have this in his hands */
						if (invDef->temp)
							continue;
						for (ic = CONTAINER(activator, container); ic; ic = ic->next) {
							const objDef_t *od = ic->item.t;
							/* check whether we found the searched item in the
							 * actor's inventory */
							if (Q_streq(od->id, self->owner->item)) {
								/* drop the weapon - even if out of TUs */
								G_ActorInvMove(activator, invDef, ic, INVDEF(gi.csi->idFloor),
									NONE, NONE, false);
								gi.BroadcastPrintf(PRINT_HUD, _("Item was placed."));
								self->owner->count = level.actualRound;
								return true;
							}
						}
					}
				} else {
					gi.BroadcastPrintf(PRINT_HUD, _("Target zone is occupied!"));
				}
			}
			return true;
		} else {
			/* reset king of the hill counter */
			self->count = 0;
		}
	}
	return false;
}
コード例 #4
0
ファイル: test_game.cpp プロジェクト: Ed-von-Schleck/ufoai
TEST_F(GameTest, InventoryForDiedAlien)
{
	const char* mapName = "test_game";
	ASSERT_NE(-1, FS_CheckFile("maps/%s.bsp", mapName)) << "Map resource '" << mapName << ".bsp' for test is missing.";
	Actor* diedEnt;
	Actor* actor;
	Edict* floorItems;
	Item* invlist;
	int count;
	SV_Map(true, mapName, nullptr);
	level.activeTeam = TEAM_ALIEN;

	/* first alien that should die and drop its inventory */
	diedEnt = G_EdictsGetNextLivingActorOfTeam(nullptr, TEAM_ALIEN);
	ASSERT_TRUE(nullptr != diedEnt);
	diedEnt->HP = 0;
	ASSERT_TRUE(G_ActorDieOrStun(diedEnt, nullptr));
	ASSERT_TRUE(diedEnt->isDead());

	/* now try to collect the inventory with a second alien */
	actor = G_EdictsGetNextLivingActorOfTeam(nullptr, TEAM_ALIEN);
	ASSERT_TRUE(nullptr != actor);

	/* move to the location of the first died alien to drop the inventory into the same floor container */
	Player& player = actor->getPlayer();
	ASSERT_TRUE(G_IsAIPlayer(&player));
	G_ClientMove(player, 0, actor, diedEnt->pos);
	ASSERT_TRUE(VectorCompare(actor->pos, diedEnt->pos));

	floorItems = G_GetFloorItems(actor);
	ASSERT_TRUE(nullptr != floorItems);
	ASSERT_EQ(floorItems->getFloor(), actor->getFloor());

	/* drop everything to floor to make sure we have space in the backpack */
	G_InventoryToFloor(actor);
	ASSERT_EQ(0, GAMETEST_GetItemCount(actor, CID_BACKPACK));

	invlist = actor->getContainer(CID_BACKPACK);
	ASSERT_TRUE(nullptr == invlist);
	count = GAMETEST_GetItemCount(actor, CID_FLOOR);
	if (count > 0) {
		Item* entryToMove = actor->getFloor();
		int tx, ty;
		actor->chr.inv.findSpace(INVDEF(CID_BACKPACK), entryToMove, &tx, &ty, entryToMove);
		if (tx == NONE)
			return;
		Com_Printf("trying to move item %s from floor into backpack to pos %i:%i\n", entryToMove->def()->name, tx, ty);
		ASSERT_TRUE(G_ActorInvMove(actor, INVDEF(CID_FLOOR), entryToMove, INVDEF(CID_BACKPACK), tx, ty, false));
		ASSERT_EQ(count - 1, GAMETEST_GetItemCount(actor, CID_FLOOR)) << "item " << entryToMove->def()->name << " could not get moved successfully from floor into backpack";
		Com_Printf("item %s was removed from floor\n", entryToMove->def()->name);
		ASSERT_EQ(1, GAMETEST_GetItemCount(actor, CID_BACKPACK)) << "item " << entryToMove->def()->name << " could not get moved successfully from floor into backpack";
		Com_Printf("item %s was moved successfully into the backpack\n", entryToMove->def()->name);
		invlist = actor->getContainer(CID_BACKPACK);
		ASSERT_TRUE(nullptr != invlist);
	}
}
コード例 #5
0
ファイル: g_mission.cpp プロジェクト: drone-pl/ufoai
/**
 * @brief Mission trigger
 * @todo use level.nextmap to spawn another map when every living actor has touched the mission trigger
 * @todo use level.actualRound to determine the 'King of the Hill' time
 * @note Don't set a client action here - otherwise the movement event might
 * be corrupted
 */
bool G_MissionTouch (Edict* self, Edict* activator)
{
	if (!self->owner())
		return false;

	switch (self->owner()->getTeam()) {
	case TEAM_ALIEN:
		if (G_IsAlien(activator)) {
			if (!self->count) {
				self->count = level.actualRound;
				gi.BroadcastPrintf(PRINT_HUD, _("Aliens entered target zone!"));
			}
			return true;
		} else {
			/* reset king of the hill counter */
			self->count = 0;
		}
	/* general case that also works for multiplayer teams */
	default:
		if (!activator->isSameTeamAs(self->owner())) {
			/* reset king of the hill counter */
			self->count = 0;
			return false;
		}
		if (self->owner()->count)
			return false;

		self->owner()->count = level.actualRound;
		if (!self->owner()->item) {
			gi.BroadcastPrintf(PRINT_HUD, _("Target zone is occupied!"));
			return true;
		}

		/* search the item in the activator's inventory */
		/* ignore items linked from any temp container the actor must have this in his hands */
		const Container* cont = nullptr;
		while ((cont = activator->chr.inv.getNextCont(cont))) {
			Item* item = nullptr;
			while ((item = cont->getNextItem(item))) {
				const objDef_t* od = item->def();
				/* check whether we found the searched item in the actor's inventory */
				if (!Q_streq(od->id, self->owner()->item))
					continue;

				/* drop the weapon - even if out of TUs */
				G_ActorInvMove(makeActor(activator), cont->def(), item, INVDEF(CID_FLOOR), NONE, NONE, false);
				gi.BroadcastPrintf(PRINT_HUD, _("Item was placed."));
				self->owner()->count = level.actualRound;
				return true;
			}
		}
		break;
	}
	return true;
}
コード例 #6
0
ファイル: g_actor.cpp プロジェクト: Maximaximum/ufoai
/**
 * @brief Reload weapon with actor.
 * @param[in] ent Pointer to an actor reloading weapon.
 * @param[in] invDef Reloading weapon in right or left hand.
 * @sa AI_ActorThink
 */
void G_ActorReload (Edict* ent, const invDef_t* invDef)
{
	const objDef_t* weapon;

	if (ent->getContainer(invDef->id)) {
		weapon = ent->getContainer(invDef->id)->def();
	} else if (invDef->isLeftDef() && ent->getRightHandItem()->isHeldTwoHanded()) {
		/* Check for two-handed weapon */
		invDef = INVDEF(CID_RIGHT);
		weapon = ent->getRightHandItem()->def();
	} else
		return;

	assert(weapon);

	/* LordHavoc: Check if item is researched when in singleplayer? I don't think this is really a
	 * cheat issue as in singleplayer there is no way to inject fake client commands in the virtual
	 * network buffer, and in multiplayer everything is researched */

	/* search for clips and select the one that is available easily */
	/* also try the temp containers */
	const invDef_t* bestContainer = nullptr;
	Item* ammoItem = nullptr;
	int tu = 100;
	const Container* cont = nullptr;
	while ((cont = ent->chr.inv.getNextCont(cont, true))) {
		if (cont->def()->out >= tu)
			continue;
		/* Once we've found at least one clip, there's no point
		 * searching other containers if it would take longer
		 * to retrieve the ammo from them than the one
		 * we've already found. */
		Item* item = nullptr;
		while ((item = cont->getNextItem(item))) {
			if (item->def()->isLoadableInWeapon(weapon)) {
				ammoItem = item;
				bestContainer = INVDEF(cont->id);
				tu = bestContainer->out;
				break;
			}
		}
	}

	/* send request */
	if (bestContainer)
		G_ActorInvMove(ent, bestContainer, ammoItem, invDef, 0, 0, true);
}
コード例 #7
0
/**
 * @brief Retrieve or collect weapon from any linked container for the actor
 * @note This function will also collect items from floor containers when the actor
 * is standing on a given point.
 * @sa AI_ActorThink
 */
void G_ClientGetWeaponFromInventory (edict_t *ent)
{
	invList_t *ic;
	invList_t *icFinal;
	const invDef_t *invDef;
	int tu;
	containerIndex_t container;
	const invDef_t *bestContainer;

	/* e.g. bloodspiders are not allowed to carry or collect weapons */
	if (!ent->chr.teamDef->weapons)
		return;

	/* search for weapons and select the one that is available easily */
	tu = 100;
	invDef = INVDEF(gi.csi->idRight);
	bestContainer = NULL;
	icFinal = NULL;

	/* also try the temp containers */
	for (container = 0; container < gi.csi->numIDs; container++) {
		if (INVDEF(container)->out < tu) {
			/* Once we've found at least one clip, there's no point
			 * searching other containers if it would take longer
			 * to retrieve the ammo from them than the one
			 * we've already found. */
			for (ic = CONTAINER(ent, container); ic; ic = ic->next) {
				assert(ic->item.item);
				if (ic->item.item->weapon && (ic->item.ammoLeft > 0 || !ic->item.item->reload)) {
					icFinal = ic;
					bestContainer = INVDEF(container);
					tu = bestContainer->out;
					break;
				}
			}
		}
	}

	/* send request */
	if (bestContainer)
		G_ActorInvMove(ent, bestContainer, icFinal, invDef, 0, 0, true);
}
コード例 #8
0
/**
 * @brief The client sent us a message that he did something. We now execute the related function(s) and notify him if necessary.
 * @param[in] player The player to execute the action for (the actor belongs to this player)
 * @note a client action will also send the server side edict number to determine the actor
 */
int G_ClientAction (player_t * player)
{
	player_action_t action;
	int num;
	pos3_t pos;
	int i;
	fireDefIndex_t firemode;
	int from, fx, fy, to, tx, ty;
	actorHands_t hand;
	int fmIdx, objIdx;
	int resCrouch, resShot;
	edict_t *ent;
	const char *format;

	/* read the header */
	action = (player_action_t)gi.ReadByte();
	num = gi.ReadShort();

	ent = G_EdictsGetByNum(num);
	if (ent == NULL)
		return action;

	format = pa_format[action];

	switch (action) {
	case PA_NULL:
		/* do nothing on a null action */
		break;

	case PA_TURN:
		gi.ReadFormat(format, &i);
		G_ClientTurn(player, ent, (dvec_t) i);
		break;

	case PA_MOVE:
		gi.ReadFormat(format, &pos);
		G_ClientMove(player, player->pers.team, ent, pos);
		break;

	case PA_STATE:
		gi.ReadFormat(format, &i);
		G_ClientStateChange(player, ent, i, true);
		break;

	case PA_SHOOT:
		gi.ReadFormat(format, &pos, &i, &firemode, &from);
		G_ClientShoot(player, ent, pos, i, firemode, NULL, true, from);
		break;

	case PA_INVMOVE:
		gi.ReadFormat(format, &from, &fx, &fy, &to, &tx, &ty);

		if (from < 0 || from >= gi.csi->numIDs || to < 0 || to >= gi.csi->numIDs) {
			gi.DPrintf("G_ClientAction: PA_INVMOVE Container index out of range. (from: %i, to: %i)\n", from, to);
		} else {
			const invDef_t *fromPtr = INVDEF(from);
			const invDef_t *toPtr = INVDEF(to);
			invList_t *fromItem = INVSH_SearchInInventory(&ent->chr.i, fromPtr, fx, fy);
			if (fromItem)
				G_ActorInvMove(ent, fromPtr, fromItem, toPtr, tx, ty, true);
		}
		break;

	case PA_USE:
		if (ent->clientAction) {
			edict_t *actionEnt;

			/* read the door the client wants to open */
			gi.ReadFormat(format, &i);

			/* get the door edict */
			actionEnt = G_EdictsGetByNum(i);

			/* maybe the door is no longer 'alive' because it was destroyed */
			if (actionEnt && ent->clientAction == actionEnt) {
				if (G_IsDoor(actionEnt)) {
					G_ActorUseDoor(ent, actionEnt);
				}
			}
		}
		break;

	case PA_REACT_SELECT:
		gi.ReadFormat(format, &hand, &fmIdx, &objIdx);
		G_ReactionFireSettingsUpdate(ent, fmIdx, hand, INVSH_GetItemByIDX(objIdx));
		break;

	case PA_RESERVE_STATE:
		gi.ReadFormat(format, &resShot, &resCrouch);

		G_ActorReserveTUs(ent, ent->chr.reservedTus.reaction, resShot, resCrouch);
		break;

	default:
		gi.Error("G_ClientAction: Unknown action!\n");
	}
	return action;
}
コード例 #9
0
ファイル: g_mission.cpp プロジェクト: chagara/ufoai
/**
 * @brief Mission trigger
 * @todo use level.nextmap to spawn another map when every living actor has touched the mission trigger
 * @note Don't set a client action here - otherwise the movement event might
 * be corrupted
 */
bool G_MissionTouch (Edict* self, Edict* activator)
{
	if (!G_IsLivingActor(activator))
		return false;

	Actor* actor = makeActor(activator);
	const char* const actorTeam = G_MissionGetTeamString(actor->getTeam());
	if (!G_IsCivilian(actor) && self->isOpponent(actor)) {
		if (!self->item && self->count) {
			if (self->targetname) {
				gi.BroadcastPrintf(PRINT_HUD, _("%s forces are attacking the %s!"), actorTeam, self->targetname);
			} else {
				const char* const teamName = G_MissionGetTeamString(self->getTeam());
				gi.BroadcastPrintf(PRINT_HUD, _("%s forces are attacking %s target zone!"),
						actorTeam, teamName);
			}

			/* reset king of the hill counter */
			self->count = 0;
		}
		return false;
	}
	if (self->count)
		return false;

	if (self->isSameTeamAs(actor)) {
		self->count = level.actualRound;
		if (!self->item) {
			linkedList_t* touched = self->touchedList;
			while (touched) {
				const Edict* const ent = static_cast<const Edict* const>(touched->data);
				if (!self->isSameTeamAs(ent) && !G_IsDead(ent)) {
					return true;
				}
				touched = touched->next;
			}
			if (self->targetname) {
				gi.BroadcastPrintf(PRINT_HUD, _("%s forces have occupied the %s!"), actorTeam, self->targetname);
			} else {
				gi.BroadcastPrintf(PRINT_HUD, _("%s forces have occupied their target zone!"), actorTeam);
			}
			return true;
		}
	}

	/* search the item in the activator's inventory */
	/* ignore items linked from any temp container the actor must have this in his hands */
	const Container* cont = nullptr;
	while ((cont = actor->chr.inv.getNextCont(cont))) {
		Item* item = nullptr;
		while ((item = cont->getNextItem(item))) {
			const objDef_t* od = item->def();
			/* check whether we found the searched item in the actor's inventory */
			if (!Q_streq(od->id, self->item))
				continue;

			/* drop the weapon - even if out of TUs */
			G_ActorInvMove(actor, cont->def(), item, INVDEF(CID_FLOOR), NONE, NONE, false);
			if (self->targetname) {
				gi.BroadcastPrintf(PRINT_HUD, _("The %s was placed at the %s."), item->def()->name, self->targetname);
			} else {
				gi.BroadcastPrintf(PRINT_HUD, _("The %s was placed."), item->def()->name);
			}
			self->count = level.actualRound;
			return true;
		}
	}

	return false;
}
コード例 #10
0
static void testInventoryWithTwoDiedAliensOnTheSameGridTile (void)
{
	const char *mapName = "test_game";
	if (FS_CheckFile("maps/%s.bsp", mapName) != -1) {
		edict_t *diedEnt;
		edict_t *diedEnt2;
		edict_t *ent;
		edict_t *floorItems;
		invList_t *invlist;
		int count;
		/* the other tests didn't call the server shutdown function to clean up */
		OBJZERO(*sv);
		SV_Map(true, mapName, NULL);
		level.activeTeam = TEAM_ALIEN;

		/* first alien that should die and drop its inventory */
		diedEnt = G_EdictsGetNextLivingActorOfTeam(NULL, TEAM_ALIEN);
		CU_ASSERT_PTR_NOT_NULL_FATAL(diedEnt);
		diedEnt->HP = 0;
		G_ActorDieOrStun(diedEnt, NULL);
		CU_ASSERT_TRUE_FATAL(G_IsDead(diedEnt));

		/* second alien that should die and drop its inventory */
		diedEnt2 = G_EdictsGetNextLivingActorOfTeam(NULL, TEAM_ALIEN);
		CU_ASSERT_PTR_NOT_NULL_FATAL(diedEnt2);

		/* move to the location of the first died alien to drop the inventory into the same floor container */
		Player &player = diedEnt2->getPlayer();
		CU_ASSERT_TRUE_FATAL(G_IsAIPlayer(&player));
		G_ClientMove(player, 0, diedEnt2, diedEnt->pos);
		CU_ASSERT_TRUE_FATAL(VectorCompare(diedEnt2->pos, diedEnt->pos));

		diedEnt2->HP = 0;
		G_ActorDieOrStun(diedEnt2, NULL);
		CU_ASSERT_TRUE_FATAL(G_IsDead(diedEnt2));

		/* now try to collect the inventory with a third alien */
		ent = G_EdictsGetNextLivingActorOfTeam(NULL, TEAM_ALIEN);
		CU_ASSERT_PTR_NOT_NULL_FATAL(ent);

		player = ent->getPlayer();
		CU_ASSERT_TRUE_FATAL(G_IsAIPlayer(&player));

		G_ClientMove(player, 0, ent, diedEnt->pos);
		CU_ASSERT_TRUE_FATAL(VectorCompare(ent->pos, diedEnt->pos));

		floorItems = G_GetFloorItems(ent);
		CU_ASSERT_PTR_NOT_NULL_FATAL(floorItems);
		CU_ASSERT_PTR_EQUAL(floorItems->getFloor(), ent->getFloor());

		/* drop everything to floor to make sure we have space in the backpack */
		G_InventoryToFloor(ent);
		CU_ASSERT_EQUAL(GAMETEST_GetItemCount(ent, CID_BACKPACK), 0);

		invlist = ent->getContainer(CID_BACKPACK);
		CU_ASSERT_PTR_NULL_FATAL(invlist);

		count = GAMETEST_GetItemCount(ent, CID_FLOOR);
		if (count > 0) {
			invList_t *entryToMove = ent->getFloor();
			int tx, ty;
			ent->chr.inv.findSpace(INVDEF(CID_BACKPACK), entryToMove, &tx, &ty, entryToMove);
			if (tx != NONE) {
				Com_Printf("trying to move item %s from floor into backpack to pos %i:%i\n", entryToMove->def()->name, tx, ty);
				CU_ASSERT_TRUE(G_ActorInvMove(ent, INVDEF(CID_FLOOR), entryToMove, INVDEF(CID_BACKPACK), tx, ty, false));
				UFO_CU_ASSERT_EQUAL_INT_MSG_FATAL(GAMETEST_GetItemCount(ent, CID_FLOOR), count - 1, va("item %s could not get moved successfully from floor into backpack", entryToMove->def()->name));
				Com_Printf("item %s was removed from floor\n", entryToMove->def()->name);
				UFO_CU_ASSERT_EQUAL_INT_MSG_FATAL(GAMETEST_GetItemCount(ent, CID_BACKPACK), 1, va("item %s could not get moved successfully from floor into backpack", entryToMove->def()->name));
				Com_Printf("item %s was moved successfully into the backpack\n", entryToMove->def()->name);
				invlist = ent->getContainer(CID_BACKPACK);
				CU_ASSERT_PTR_NOT_NULL_FATAL(invlist);
			}
		}

		SV_ShutdownGameProgs();
	} else {
		UFO_CU_FAIL_MSG(va("Map resource '%s.bsp' for test is missing.", mapName));
	}
}