예제 #1
0
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);
	}
}
예제 #2
0
파일: g_cmds.cpp 프로젝트: cigo/ufoai
/**
 * @brief Debug function to print a player's inventory
 */
void G_InvList_f (const Player& player)
{
	Edict* ent = nullptr;

	gi.DPrintf("Print inventory for '%s'\n", player.pers.netname);
	while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, player.getTeam()))) {
		gi.DPrintf("actor: '%s'\n", ent->chr.name);

		const Container* cont = nullptr;
		while ((cont = ent->chr.inv.getNextCont(cont, true))) {
			Com_Printf("Container: %i\n", cont->id);
			Item* item = nullptr;
			while ((item = cont->getNextItem(item))) {
				Com_Printf(".. item.def(): %i, item.ammo: %i, item.ammoLeft: %i, x: %i, y: %i\n",
						(item->def() ? item->def()->idx : NONE), (item->ammoDef() ? item->ammoDef()->idx : NONE),
						item->getAmmoLeft(), item->getX(), item->getY());
				if (item->def())
					Com_Printf(".... weapon: %s\n", item->def()->id);
				if (item->ammoDef())
					Com_Printf(".... ammo:   %s (%i)\n", item->ammoDef()->id, item->getAmmoLeft());
			}
		}
		const float invWeight = ent->chr.inv.getWeight();
		const int maxWeight = ent->chr.score.skills[ABILITY_POWER];
		const float penalty = GET_ENCUMBRANCE_PENALTY(invWeight, maxWeight);
		const int normalTU = GET_TU(ent->chr.score.skills[ABILITY_SPEED], 1.0f - WEIGHT_NORMAL_PENALTY);
		const int tus = GET_TU(ent->chr.score.skills[ABILITY_SPEED], penalty);
		const int tuPenalty = tus - normalTU;
		const char* penaltyStr = 1.0f - penalty < WEIGHT_NORMAL_PENALTY ? "'Light weight'" : (1.0f - penalty < WEIGHT_HEAVY_PENALTY ? "'Normal weight'" : "'Encumbered'");
		Com_Printf("Weight: %g/%i, Encumbrance: %s (%.0f%%), TU's: %i (normal: %i, penalty/bonus: %+i)\n", invWeight, maxWeight, penaltyStr, invWeight / maxWeight * 100.0f, tus, normalTU, tuPenalty);
	}
}
예제 #3
0
/**
 * @brief This function does not add statistical values. Because there is no attacker.
 * The same counts for morale states - they are not affected.
 * @note: This is a debug function to let a whole team die
 */
static void G_KillTeam_f (void)
{
    /* default is to kill all teams */
    int teamToKill = -1;
    edict_t *ent = NULL;
    int amount = -1;

    /* with a parameter we will be able to kill a specific team */
    if (gi.Cmd_Argc() >= 2) {
        teamToKill = atoi(gi.Cmd_Argv(1));
        if (gi.Cmd_Argc() == 3)
            amount = atoi(gi.Cmd_Argv(2));
    }

    Com_DPrintf(DEBUG_GAME, "G_KillTeam: kill team %i\n", teamToKill);

    if (teamToKill >= 0) {
        while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, teamToKill))) {
            if (amount == 0)
                break;
            /* die */
            ent->HP = 0;
            G_ActorDieOrStun(ent, NULL);

            if (teamToKill == TEAM_ALIEN)
                level.num_kills[TEAM_PHALANX][TEAM_ALIEN]++;
            else
                level.num_kills[TEAM_ALIEN][teamToKill]++;
            amount--;
        }
    }

    /* check for win conditions */
    G_MatchEndCheck();
}
예제 #4
0
/**
 * @brief Stun all members of a giben team.
 */
static void G_StunTeam_f (void)
{
    /* default is to kill all teams */
    int teamToKill = -1;
    edict_t *ent = NULL;

    /* with a parameter we will be able to kill a specific team */
    if (gi.Cmd_Argc() == 2)
        teamToKill = atoi(gi.Cmd_Argv(1));

    if (teamToKill >= 0) {
        while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, teamToKill))) {
            /* stun */
            G_ActorDieOrStun(ent, NULL);

            if (teamToKill == TEAM_ALIEN)
                level.num_stuns[TEAM_PHALANX][TEAM_ALIEN]++;
            else
                level.num_stuns[TEAM_ALIEN][teamToKill]++;
        }
    }

    /* check for win conditions */
    G_MatchEndCheck();
}
예제 #5
0
/**
 * @brief Debug function to print a player's inventory
 */
void G_InvList_f (const player_t *player)
{
    edict_t *ent = NULL;

    gi.DPrintf("Print inventory for '%s'\n", player->pers.netname);
    while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, player->pers.team))) {
        containerIndex_t container;
        gi.DPrintf("actor: '%s'\n", ent->chr.name);

        for (container = 0; container < gi.csi->numIDs; container++) {
            const invList_t *ic = CONTAINER(ent, container);
            Com_Printf("Container: %i\n", container);
            while (ic) {
                Com_Printf(".. item.item: %i, item.ammo: %i, item.ammoLeft: %i, x: %i, y: %i\n",
                           (ic->item.item ? ic->item.item->idx : NONE), (ic->item.ammo ? ic->item.ammo->idx : NONE),
                           ic->item.ammoLeft, ic->x, ic->y);
                if (ic->item.item)
                    Com_Printf(".... weapon: %s\n", ic->item.item->id);
                if (ic->item.ammo)
                    Com_Printf(".... ammo:   %s (%i)\n", ic->item.ammo->id, ic->item.ammoLeft);
                ic = ic->next;
            }
        }
    }
}
예제 #6
0
/**
 * @brief Test if point is "visible" from team.
 * @param[in] team A team to test.
 * @param[in] point A point to check.
 * @return true if point is "visible"
 */
static bool G_TeamPointVis (int team, const vec3_t point)
{
	Edict *from = nullptr;
	vec3_t eye;

	/* test if point is visible from team */
	while ((from = G_EdictsGetNextLivingActorOfTeam(from, team))) {
		if (G_FrustumVis(from, point)) {
			/* get viewers eye height */
			G_ActorGetEyeVector(from, eye);

			/* line of sight */
			if (!G_TestLine(eye, point)) {
				const float distance = VectorDist(from->origin, point);
				bool blocked = false;
				/* check visibility in the smoke */
				if (distance >= UNIT_SIZE) {
					Edict *e = nullptr;
					while ((e = G_EdictsGetNextInUse(e))) {
						if (G_IsSmoke(e) && RayIntersectAABB(eye, point, e->absmin, e->absmax)) {
								blocked = true;
								break;
						}
					}
				}
				if (!blocked)
					return true;
			}
		}
	}

	/* not visible */
	return false;
}
예제 #7
0
/**
 * @brief Checks whether there are still actors to fight with left. If none
 * are the match end will be triggered.
 * @sa G_MatchEndTrigger
 */
void G_MatchEndCheck (void)
{
	int activeTeams;
	int i, last;

	if (level.intermissionTime > 0.0) /* already decided */
		return;

	if (!level.numplayers) {
		G_MatchEndTrigger(0, 0);
		return;
	}

	/** @todo count from 0 to get the civilians for objectives */
	for (i = 1, activeTeams = 0, last = 0; i < MAX_TEAMS; i++) {
		edict_t *ent = NULL;
		/* search for living but not stunned actors - there must at least be one actor
		 * that is still able to attack or defend himself */
		while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, i)) != NULL) {
			if (!G_IsStunned(ent)) {
				last = i;
				activeTeams++;
				break;
			}
		}
	}

	/** @todo < 2 does not work when we count civilians */
	/* prepare for sending results */
	if (activeTeams < 2) {
		const int timeGap = (level.activeTeam == TEAM_ALIEN ? 10.0 : 3.0);
		G_MatchEndTrigger(activeTeams == 1 ? last : 0, timeGap);
	}
}
예제 #8
0
TEST_F(GameTest, InventoryTempContainerLinks)
{
	const char* mapName = "test_game";
	ASSERT_NE(-1, FS_CheckFile("maps/%s.bsp", mapName)) << "Map resource '" << mapName << ".bsp' for test is missing.";
	SV_Map(true, mapName, nullptr);
	level.activeTeam = TEAM_ALIEN;

	/* first alien that should die and drop its inventory */
	Actor* actor = G_EdictsGetNextLivingActorOfTeam(nullptr, TEAM_ALIEN);
	int nr = 0;
	const Container* cont = nullptr;
	while ((cont = actor->chr.inv.getNextCont(cont, true))) {
		if (cont->id == CID_ARMOUR || cont->id == CID_FLOOR)
			continue;
		nr += cont->countItems();
	}
	ASSERT_TRUE(nr > 0) << "Could not find any items in the inventory of the actor";

	ASSERT_TRUE(nullptr == actor->getFloor());
	G_InventoryToFloor(actor);
	ASSERT_TRUE(nullptr != actor->getFloor());
	ASSERT_EQ(G_GetFloorItemFromPos(actor->pos)->getFloor(), actor->getFloor());

	nr = 0;
	cont = nullptr;
	while ((cont = actor->chr.inv.getNextCont(cont, true))) {
		if (cont->id == CID_ARMOUR || cont->id == CID_FLOOR)
			continue;
		nr += cont->countItems();
	}
	ASSERT_EQ(0, nr);
}
예제 #9
0
static void testVisFlags (void)
{
	const char *mapName = "test_game";
	if (FS_CheckFile("maps/%s.bsp", mapName) != -1) {
		edict_t *ent;
		int num;

		/* the other tests didn't call the server shutdown function to clean up */
		OBJZERO(*sv);
		SV_Map(true, mapName, NULL);

		num = 0;
		ent = NULL;
		while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, TEAM_ALIEN))) {
			const teammask_t teamMask = G_TeamToVisMask(ent->team);
			const bool visible = ent->visflags & teamMask;
			char *visFlagsBuf = Mem_StrDup(Com_UnsignedIntToBinary(ent->visflags));
			char *teamMaskBuf = Mem_StrDup(Com_UnsignedIntToBinary(teamMask));
			CU_ASSERT_EQUAL(ent->team, TEAM_ALIEN);
			UFO_CU_ASSERT_TRUE_MSG(visible, va("visflags: %s, teamMask: %s", visFlagsBuf, teamMaskBuf));
			Mem_Free(visFlagsBuf);
			Mem_Free(teamMaskBuf);
			num++;
		}

		SV_ShutdownGameProgs();
		CU_ASSERT_TRUE(num > 0);
	} else {
		UFO_CU_FAIL_MSG(va("Map resource '%s.bsp' for test is missing.", mapName));
	}
}
예제 #10
0
/**
 * @brief Guess! Reset all "shaken" states on end of turn?
 * @note Normally called on end of turn.
 * @sa G_ClientStateChange
 * @param[in] team Index of team to loop through.
 */
void G_ReactionFireReset (int team)
{
	Edict *ent = nullptr;

	while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, team))) {
		G_RemoveShaken(ent);
	}
}
예제 #11
0
파일: g_round.cpp 프로젝트: drone-pl/ufoai
static void G_RoundTouchTriggers (int team)
{
	Actor* actor = nullptr;

	while ((actor = G_EdictsGetNextLivingActorOfTeam(actor, team))) {
		G_TouchTriggers(actor);
	}
}
예제 #12
0
/**
 * @brief Guess! Reset all "shaken" states on end of turn?
 * @note Normally called on end of turn.
 * @sa G_ClientStateChange
 * @param[in] team Index of team to loop through.
 */
void G_ReactionFireReset (int team)
{
	Actor* actor = nullptr;

	while ((actor = G_EdictsGetNextLivingActorOfTeam(actor, team))) {
		actor->removeShaken();
	}
}
예제 #13
0
/**
 * @brief Network function to update the time units (TUs) for each team-member.
 * @param[in] team The index of the team to update the values for.
 * @sa G_SendStats
 */
void G_GiveTimeUnits (int team)
{
	edict_t *ent = NULL;

	while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, team))) {
		G_ActorGiveTimeUnits(ent);
		G_SendStats(ent);
	}
}
예제 #14
0
파일: g_round.cpp 프로젝트: cigo/ufoai
/**
 * @brief Uudates the weight carried for each team member.
 * @param[in] team The index of the team to update the values for.
 */
static void G_UpdateCarriedWeight (int team)
{
	Edict* ent = nullptr;

	while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, team))) {
		if (ent->chr.scoreMission) {
			ent->chr.scoreMission->carriedWeight += ent->chr.inv.getWeight();
		}
	}
}
예제 #15
0
파일: g_round.cpp 프로젝트: drone-pl/ufoai
/**
 * @brief Updates the weight carried for each team member.
 * @param[in] team The index of the team to update the values for.
 */
static void G_UpdateCarriedWeight (int team)
{
	Actor* actor = nullptr;

	while ((actor = G_EdictsGetNextLivingActorOfTeam(actor, team))) {
		if (actor->chr.scoreMission) {
			actor->chr.scoreMission->carriedWeight += actor->chr.inv.getWeight();
		}
	}
}
예제 #16
0
파일: g_morale.cpp 프로젝트: cigo/ufoai
/**
 * @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);
	}
}
예제 #17
0
/**
 * @brief Guess! Reset all "shaken" states on end of turn?
 * @note Normally called on end of turn.
 * @sa G_ClientStateChange
 * @param[in] team Index of team to loop through.
 */
void G_ReactionFireReset (int team)
{
	edict_t *ent = NULL;

	while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, team))) {
		/** @todo why do we send the state here and why do we change the "shaken"
		 * state? - see G_MoraleBehaviour */
		G_RemoveShaken(ent);

		G_EventActorStateChange(G_TeamToPM(ent->team), ent);
	}
}
예제 #18
0
파일: g_round.cpp 프로젝트: cigo/ufoai
/**
 * @brief Regenerate the "STUN" value of each (partly) stunned team member.
 * @note The values are @b not sent via network. This is done in
 * @c G_GiveTimeUnits. It @b has to be called afterwards.
 * @param[in] team The index of the team to update the values for.
 * @sa G_GiveTimeUnits
 * @todo Make this depend on the character-attributes.
 */
static void G_UpdateStunState (int team)
{
	Edict* ent = nullptr;
	const int regen = 1;

	while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, team))) {
		if (ent->STUN > 0) {
			if (regen > ent->STUN)
				ent->STUN = 0;
			else
				ent->STUN -= regen;

			G_ActorCheckRevitalise(ent);
		}
	}
}
예제 #19
0
static void SVCmd_AddItem_f (void)
{
	const int team = TEAM_DEFAULT;
	Actor* actor = G_EdictsGetNextLivingActorOfTeam(nullptr, team);

	if (gi.Cmd_Argc() < 3) {
		gi.DPrintf("Usage: %s <item-id>\n", gi.Cmd_Argv(1));
		return;
	}

	if (!actor) {
		gi.DPrintf("Could not add item, no living members of team %i left\n", team);
		return;
	}

	G_AddItemToFloor(actor->pos, gi.Cmd_Argv(2));
}
예제 #20
0
파일: g_round.cpp 프로젝트: drone-pl/ufoai
/**
 * @brief Regenerate the "STUN" value of each (partly) stunned team member.
 * @note The values are @b not sent via network. This is done in
 * @c G_GiveTimeUnits. It @b has to be called afterwards.
 * @param[in] team The index of the team to update the values for.
 * @sa G_GiveTimeUnits
 * @todo Make this depend on the character-attributes.
 */
static void G_UpdateStunState (int team)
{
	const int regen = 1;

	Actor* actor = nullptr;
	while ((actor = G_EdictsGetNextLivingActorOfTeam(actor, team))) {
		const int stun = actor->getStun();
		if (stun > 0) {
			if (regen > stun)
				actor->setStun(0);
			else
				actor->addStun(-regen);

			G_ActorCheckRevitalise(actor);
		}
	}
}
예제 #21
0
static void testInventoryTempContainerLinks (void)
{
	const char *mapName = "test_game";
	if (FS_CheckFile("maps/%s.bsp", mapName) != -1) {
		edict_t *ent;
		int nr;
		containerIndex_t container;
		const invList_t *ic;

		/* 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 */
		ent = G_EdictsGetNextLivingActorOfTeam(NULL, TEAM_ALIEN);
		nr = 0;
		for (container = 0; container < CID_MAX; container++) {
			if (container == CID_ARMOUR || container == CID_FLOOR)
				continue;
			for (ic = ent->getContainer(container); ic; ic = ic->getNext())
				nr++;
		}
		CU_ASSERT_TRUE(nr > 0);

		CU_ASSERT_PTR_NULL(ent->getFloor());
		G_InventoryToFloor(ent);
		CU_ASSERT_PTR_NOT_NULL(ent->getFloor());
		CU_ASSERT_PTR_EQUAL(G_GetFloorItemFromPos(ent->pos)->getFloor(), ent->getFloor());

		nr = 0;
		for (container = 0; container < CID_MAX; container++) {
			if (container == CID_ARMOUR || container == CID_FLOOR)
				continue;
			for (ic = ent->getContainer(container); ic; ic = ic->getNext())
				nr++;
		}
		CU_ASSERT_EQUAL(nr, 0);

		SV_ShutdownGameProgs();
	} else {
		UFO_CU_FAIL_MSG(va("Map resource '%s.bsp' for test is missing.", mapName));
	}
}
예제 #22
0
파일: g_health.cpp 프로젝트: yason/ufoai
/**
 * @brief Deal damage to each wounded team member.
 * @param[in] team The index of the team to deal damage to.
 */
void G_BleedWounds (const int team)
{
	Actor* actor = nullptr;

	while ((actor = G_EdictsGetNextLivingActorOfTeam(actor, team))) {
		if (CHRSH_IsTeamDefRobot(actor->chr.teamDef))
			continue;
		const teamDef_t* const teamDef = actor->chr.teamDef;
		const woundInfo_t& wounds = actor->chr.wounds;
		int damage = 0;
		for (int bodyPart = 0; bodyPart < teamDef->bodyTemplate->numBodyParts(); ++bodyPart)
			if (wounds.woundLevel[bodyPart] > actor->chr.maxHP * teamDef->bodyTemplate->woundThreshold(bodyPart))
				damage += wounds.woundLevel[bodyPart] * teamDef->bodyTemplate->bleedingFactor(bodyPart);
		if (damage > 0) {
			G_PrintStats("%s is bleeding (damage: %i)", actor->chr.name, damage);
			G_TakeDamage(actor, damage);
			G_CheckDeathOrKnockout(actor, nullptr, nullptr, damage);
		}
	}
	/* Maybe the last team member bled to death */
	G_MatchEndCheck();
}
예제 #23
0
/**
 * @brief Test if point is "visible" from team.
 * @param[in] team A team to test.
 * @param[in] point A point to check.
 * @return true if point is "visible"
 */
static bool G_TeamPointVis (int team, const vec3_t point)
{
	edict_t *from = NULL;
	vec3_t eye;

	/* test if point is visible from team */
	while ((from = G_EdictsGetNextLivingActorOfTeam(from, team))) {
		if (G_FrustumVis(from, point)) {
			/* get viewers eye height */
			VectorCopy(from->origin, eye);
			if (G_IsCrouched(from))
				eye[2] += EYE_CROUCH;
			else
				eye[2] += EYE_STAND;

			/* line of sight */
			if (!G_TestLine(eye, point))
				return true;
		}
	}

	/* not visible */
	return false;
}
예제 #24
0
TEST_F(GameTest, VisFlags)
{
	const char* mapName = "test_game";
	ASSERT_NE(-1, FS_CheckFile("maps/%s.bsp", mapName)) << "Map resource '" << mapName << ".bsp' for test is missing.";
	int num;

	SV_Map(true, mapName, nullptr);

	num = 0;
	Actor* actor = nullptr;
	while ((actor = G_EdictsGetNextLivingActorOfTeam(actor, TEAM_ALIEN))) {
		const teammask_t teamMask = G_TeamToVisMask(actor->getTeam());
		const bool visible = actor->visflags & teamMask;
		char* visFlagsBuf = Mem_StrDup(Com_UnsignedIntToBinary(actor->visflags));
		char* teamMaskBuf = Mem_StrDup(Com_UnsignedIntToBinary(teamMask));
		ASSERT_EQ(actor->getTeam(), TEAM_ALIEN);
		ASSERT_TRUE(visible) << "visflags: " << visFlagsBuf << ", teamMask: " << teamMaskBuf;
		Mem_Free(visFlagsBuf);
		Mem_Free(teamMaskBuf);
		num++;
	}

	ASSERT_TRUE(num > 0) << "No alien actors found";
}
예제 #25
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));
	}
}