/** * @brief Build the forbidden list for the pathfinding (server side). * @param[in] team The team number if the list should be calculated from the eyes of that team. Use 0 to ignore team. * @param[in] movingActor The moving actor to build the forbidden list for. If this is an AI actor, everything other actor will be * included in the forbidden list - even the invisible ones. This is needed to ensure that they are not walking into each other * (civilians <=> aliens, aliens <=> civilians) * @sa G_MoveCalc * @sa Grid_CheckForbidden * @sa CL_BuildForbiddenList <- shares quite some code * @note This is used for pathfinding. * It is a list of where the selected unit can not move to because others are standing there already. */ static void G_BuildForbiddenList (int team, const edict_t *movingActor) { edict_t *ent = NULL; int visMask; forbiddenListLength = 0; /* team visibility */ if (team) visMask = G_TeamToVisMask(team); else visMask = TEAM_ALL; while ((ent = G_EdictsGetNextInUse(ent))) { /* Dead 2x2 unit will stop walking, too. */ if (G_IsBlockingMovementActor(ent) && (G_IsAI(movingActor) || (ent->visflags & visMask))) { forbiddenList[forbiddenListLength++] = ent->pos; forbiddenList[forbiddenListLength++] = (byte*) &ent->fieldSize; } else if (ent->type == ET_SOLID) { int j; for (j = 0; j < ent->forbiddenListSize; j++) { forbiddenList[forbiddenListLength++] = ent->forbiddenListPos[j]; forbiddenList[forbiddenListLength++] = (byte*) &ent->fieldSize; } } } if (forbiddenListLength > MAX_FORBIDDENLIST) gi.Error("G_BuildForbiddenList: list too long\n"); }
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)); } }
static int G_DoTestVis (const int team, edict_t * check, bool perish, int playerMask, const edict_t *ent) { int status = 0; const int visFlags = perish ? VT_PERISH : 0; const int vis = G_TestVis(team, check, visFlags); /* visibility has changed ... */ if (vis & VIS_CHANGE) { /* swap the vis mask for the given team */ const bool appear = (vis & VIS_YES) == VIS_YES; if (playerMask == 0) { G_VisFlagsSwap(check, G_TeamToVisMask(team)); } else { G_AppearPerishEvent(playerMask, appear, check, ent); } /* ... to visible */ if (vis & VIS_YES) { status |= VIS_APPEAR; if (G_VisShouldStop(check)) status |= VIS_STOP; } else status |= VIS_PERISH; } return status; }
/** * @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; }
/** * @brief Converts player mask to vis mask * @param[in] playerMask The player bit mask (contains the player numbers) that * is converted to a vis mask * @return Returns a vis mask for all the teams of the connected players that * are marked in the given @c playerMask. */ teammask_t G_PMToVis (playermask_t playerMask) { player_t *p; teammask_t teamMask = 0; /* don't handle the ai players, here */ p = NULL; while ((p = G_PlayerGetNextActiveHuman(p))) { if (playerMask & G_PlayerToPM(p)) teamMask |= G_TeamToVisMask(p->pers.team); } return teamMask; }
/** * @brief Converts vis mask to player mask * @param[in] vis_mask The visibility bit mask (contains the team numbers) that * is converted to a player mask * @return Returns a playermask for all the teams of the connected players that * are marked in the given @c vis_mask. */ unsigned int G_VisToPM (vismask_t vis_mask) { player_t *p; unsigned int playerMask; playerMask = 0; /* don't handle the ai players, here */ p = NULL; while ((p = G_PlayerGetNextActiveHuman(p))) { if (vis_mask & G_TeamToVisMask(p->pers.team)) playerMask |= G_PlayerToPM(p); } return playerMask; }
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"; }