static void UI_MapInfoGetNext (int step) { const mapDef_t *md; int ref = cls.currentSelectedMap; while (qtrue) { cls.currentSelectedMap += step; if (cls.currentSelectedMap < 0) cls.currentSelectedMap = cls.numMDs - 1; cls.currentSelectedMap %= cls.numMDs; md = Com_GetMapDefByIDX(cls.currentSelectedMap); /* avoid infinit loop */ if (ref == cls.currentSelectedMap) break; /* special purpose maps are not startable without the specific context */ if (md->map[0] == '.') continue; if (md->map[0] != '+' && FS_CheckFile("maps/%s.bsp", md->map) != -1) break; if (md->map[0] == '+' && FS_CheckFile("maps/%s.ump", md->map + 1) != -1) break; } }
bool R_ModelExists (const char *name) { if (Com_GetExtension(name) == NULL) { int i; for (i = 0; mod_extensions[i] != NULL; i++) { if (FS_CheckFile("models/%s.%s", name, mod_extensions[i]) != -1) { return true; } } return false; } return FS_CheckFile("models/%s", name) != -1; }
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); }
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)); } }
/** * @brief Console command to load a savegame * @sa SAV_GameLoad */ static void SAV_GameLoad_f (void) { const char *error = NULL; /* get argument */ if (Cmd_Argc() < 2) { Com_Printf("Usage: %s <filename>\n", Cmd_Argv(0)); return; } /* Check if savegame exists */ if (FS_CheckFile("save/%s.%s", Cmd_Argv(1), SAVEGAME_EXTENSION) <= 0) { Com_Printf("savegame file '%s' doesn't exist or an empty file\n", Cmd_Argv(1)); return; } Com_DPrintf(DEBUG_CLIENT, "load file '%s'\n", Cmd_Argv(1)); /* load and go to map */ if (!SAV_GameLoad(Cmd_Argv(1), &error)) { Cbuf_Execute(); /* wipe outstanding campaign commands */ cgi->UI_Popup(_("Error"), "%s\n%s", _("Error loading game."), error ? error : ""); Cmd_ExecuteString("game_exit"); } }
TEST_F(GameTest, DoorTrigger) { const char* mapName = "test_game"; ASSERT_NE(-1, FS_CheckFile("maps/%s.bsp", mapName)) << "Map resource '" << mapName << ".bsp' for test is missing."; Edict* e = nullptr; int cnt = 0; int doors = 0; SV_Map(true, mapName, nullptr); while ((e = G_EdictsGetNextInUse(e))) { cnt++; if (e->type != ET_DOOR) continue; if (Q_streq(e->targetname, "left-0")) { ASSERT_TRUE(e->doorState) << "this one is triggered by an actor standing inside of a trigger_touch"; } else if (Q_streq(e->targetname, "right-0")) { ASSERT_FALSE(e->doorState) << "this one has a trigger_touch, too - but nobody is touching that trigger yet"; } else { ASSERT_TRUE(false) << "both of the used doors have a targetname set"; } doors++; } ASSERT_TRUE(cnt > 0); ASSERT_TRUE(doors == 2); }
/** * @brief Loads in a model for the given name * @param[in] filename Filename relative to base dir and with extension (models/model.md2) * @param[inout] mod Structure to initialize * @return True if the loading was succeed. True or false structure mod was edited. */ static bool R_LoadModel (model_t *mod, const char *filename) { byte *buf; int modfilelen; char animname[MAX_QPATH]; if (filename[0] == '\0') Com_Error(ERR_FATAL, "R_ModForName: NULL name"); /* load the file */ modfilelen = FS_LoadFile(filename, &buf); if (!buf) return false; OBJZERO(*mod); Q_strncpyz(mod->name, filename, sizeof(mod->name)); /* call the appropriate loader */ switch (LittleLong(*(unsigned *) buf)) { case IDALIASHEADER: /* MD2 header */ R_ModLoadAliasMD2Model(mod, buf, modfilelen, true); break; case DPMHEADER: R_ModLoadAliasDPMModel(mod, buf, modfilelen); break; case IDMD3HEADER: /* MD3 header */ R_ModLoadAliasMD3Model(mod, buf, modfilelen); break; case IDBSPHEADER: Com_Error(ERR_FATAL, "R_ModForName: don't load BSPs with this function"); break; default: { const char* ext = Com_GetExtension(filename); if (ext != NULL && !Q_strcasecmp(ext, "obj")) R_LoadObjModel(mod, buf, modfilelen); else Com_Error(ERR_FATAL, "R_ModForName: unknown fileid for %s", mod->name); } } /* load the animations */ Com_StripExtension(mod->name, animname, sizeof(animname)); Com_DefaultExtension(animname, sizeof(animname), ".anm"); /* try to load the animation file */ if (FS_CheckFile("%s", animname) != -1) { R_ModLoadAnims(&mod->alias, animname); } FS_FreeFile(buf); return true; }
static void testMapLoading (void) { if (FS_CheckFile("maps/%s.bsp", mapName) != -1) { CM_LoadMap(mapName, qtrue, "", &mapData, &mapTiles); CM_LoadMap(mapName, qtrue, "", &mapData, &mapTiles); } else { UFO_CU_FAIL_MSG(va("Map resource '%s.bsp' for test is missing.", mapName)); } }
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); } }
/** * @brief Prints the map info for the server creation dialogue * @todo Skip special map that start with a '.' (e.g. .baseattack) */ static void UI_MapInfo (int step) { const char *mapname; const mapDef_t *md; const cgame_export_t *list = GAME_GetCurrentType(); if (!list) return; if (!cls.numMDs) return; UI_MapInfoGetNext(step); md = list->MapInfo(step); if (!md) return; mapname = md->map; /* skip random map char */ Cvar_Set("mn_svmapid", md->id); if (mapname[0] == '+') { Cvar_Set("mn_svmapname", va("%s %s", md->map, md->param ? md->param : "")); mapname++; } else { Cvar_Set("mn_svmapname", md->map); } if (FS_CheckFile("pics/maps/shots/%s.jpg", mapname) != -1) Cvar_Set("mn_mappic", va("maps/shots/%s", mapname)); else Cvar_Set("mn_mappic", "maps/shots/default"); if (FS_CheckFile("pics/maps/shots/%s_2.jpg", mapname) != -1) Cvar_Set("mn_mappic2", va("maps/shots/%s_2", mapname)); else Cvar_Set("mn_mappic2", "maps/shots/default"); if (FS_CheckFile("pics/maps/shots/%s_3.jpg", mapname) != -1) Cvar_Set("mn_mappic3", va("maps/shots/%s_3", mapname)); else Cvar_Set("mn_mappic3", "maps/shots/default"); }
static void testMapLoading (void) { if (FS_CheckFile("maps/%s.bsp", mapName) != -1) { char entityString[MAX_TOKEN_CHARS]; CM_LoadMap(mapName, true, "", entityString, &mapData, &mapTiles); CM_LoadMap(mapName, true, "", entityString, &mapData, &mapTiles); } else { UFO_CU_FAIL_MSG(va("Map resource '%s.bsp' for test is missing.", mapName)); } }
TEST_F(GameTest, Shooting) { 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); /** @todo equip the soldier */ /** @todo set the input variables -- gi.ReadFormat(format, &pos, &i, &firemode, &from); */ /** @todo do the shot -- G_ClientShoot(player, ent, pos, i, firemode, &mock, true, from); */ /** @todo implement the test here - e.g. extend shot_mock_t */ }
/** * @brief Open a cinematic file and store status to a structure * @sa CIN_CloseCinematic */ void CIN_OpenCinematic (cinematic_t* cin, const char* fileName) { char name[MAX_OSPATH]; int status = 1; Com_StripExtension(fileName, name, sizeof(name)); /* If already playing a cinematic, stop it */ CIN_CloseCinematic(cin); if (FS_CheckFile("%s.roq", name) >= 0) status = CIN_ROQ_OpenCinematic(cin, va("%s.roq", name)); else if (FS_CheckFile("%s.ogm", name) >= 0) status = CIN_OGM_OpenCinematic(cin, va("%s.ogm", name)); if (status != 0) { Com_Printf("Could not load cinematic '%s'\n", name); cin->status = CIN_STATUS_INVALID; } }
static void UI_RequestMapList_f (void) { const char *callbackCmd; int i; if (Cmd_Argc() != 2) { Com_Printf("Usage: %s <callback>\n", Cmd_Argv(0)); return; } if (!cls.numMDs) return; callbackCmd = Cmd_Argv(1); Cbuf_AddText(va("%s begin;", callbackCmd)); for (i = 0; i < cls.numMDs; i++) { const mapDef_t *md = Com_GetMapDefByIDX(i); const char *preview; /* special purpose maps are not startable without the specific context */ if (md->map[0] == '.') continue; /* do we have the map file? */ if (md->map[0] != '+' && FS_CheckFile("maps/%s.bsp", md->map) == -1) continue; if (md->map[0] == '+' && FS_CheckFile("maps/%s.ump", md->map + 1) == -1) continue; preview = md->map; if (preview[0] == '+') preview++; if (FS_CheckFile("pics/maps/shots/%s.jpg", preview) == -1) preview = "default"; Cbuf_AddText(va("%s add \"%s\" \"%s\";", callbackCmd, md->id, preview)); } Cbuf_AddText(va("%s end;", callbackCmd)); }
static bool UI_CheckRadarImage (const char* imageName, const int level) { char const* const* ext = imageExtensions; while (*ext) { if (FS_CheckFile("pics/radars/%s_%i.%s", imageName, level, *ext) > 0) return true; ext++; } /* none found */ return false; }
/** * @brief Registers a new TTF font * @note The TTF font path is translated via gettext to be able to use different * fonts for every translation * @param[in] font Font to register */ static void UI_RegisterFont (const uiFont_t* font) { const char* path = _(font->path); if (!path) Com_Error(ERR_FATAL, "...font without path (font %s)", font->name); if (FS_CheckFile("%s", path) == -1) Com_Error(ERR_FATAL, "...font file %s does not exist (font %s)", path, font->name); R_FontRegister(font->name, font->size, path, font->style); }
static qboolean TEST_CheckModel (const char *path) { const char *extensions[] = {"md2", "md3", "dpm", "obj", NULL}; int i = 0; if (Q_strnull(path)) return qtrue; while (extensions[i]) { if (FS_CheckFile("models/%s.%s", path, extensions[i]) != -1) return qtrue; i++; } return qfalse; }
/** * @brief Some sound strings may end on a '+' to indicate to use a random sound * which can be identified by replacing the '+' by a number * @param[in,out] sound The sound string that we might need to convert * @param[in] size The size of the @c sound buffer * @return Pointer to the @c sound buffer */ const char* CL_ConvertSoundFromEvent (char* sound, size_t size) { const size_t length = strlen(sound) - 1; if (sound[length] != '+') return sound; for (int i = 1; i <= 99; i++) { if (!FS_CheckFile("sounds/%s%02i", sound, i) == -1) continue; sound[length] = '\0'; Q_strcat(sound, size, "%02i", rand() % i + 1); return sound; } return ""; }
static void testShooting (void) { const char *mapName = "test_game"; if (FS_CheckFile("maps/%s.bsp", mapName) != -1) { /* the other tests didn't call the server shutdown function to clean up */ OBJZERO(*sv); SV_Map(true, mapName, NULL); /** @todo equip the soldier */ /** @todo set the input variables -- gi.ReadFormat(format, &pos, &i, &firemode, &from); */ /** @todo do the shot -- G_ClientShoot(player, ent, pos, i, firemode, &mock, true, from); */ /** @todo implement the test here - e.g. extend shot_mock_t */ SV_ShutdownGameProgs(); } else { UFO_CU_FAIL_MSG(va("Map resource '%s.bsp' for test is missing.", mapName)); } }
static qboolean TEST_CheckImage (const char *path) { const char *extensions[] = {"png", "tga", "jpg", NULL}; int i = 0; if (Q_strnull(path)) return qtrue; while (extensions[i]) { if (FS_CheckFile("pics/%s.%s", path, extensions[i]) != -1) return qtrue; i++; } return qfalse; }
static qboolean TEST_CheckSound (const char *path) { const char *extensions[] = {"wav", "ogg", NULL}; int i = 0; if (Q_strnull(path)) return qtrue; while (extensions[i]) { if (FS_CheckFile("sound/%s.%s", path, extensions[i]) != -1) return qtrue; i++; } return qfalse; }
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)); } }
/** * @brief Some sound strings may end on a '+' to indicate to use a random sound * which can be identified by replacing the '+' by a number * @param[in,out] sound The sound string that we might need to convert * @param[in] size The size of the @c sound buffer * @return Pointer to the @c sound buffer */ const char* CL_ConvertSoundFromEvent (char* sound, size_t size) { /* Plain file name? Just return it unchanged */ const size_t length = strlen(sound) - 1; if (sound[length] != '+') return sound; /* Otherwise we are going to replace the '+' with a random number */ sound[length] = '\0'; /* First we need check how many files we can choose from (if any) */ int i; for (i = 0; i < 99; i++) if (FS_CheckFile("sounds/%s%02i", sound, i + 1) == -1) break; /* Knowing that we can now choose a random one */ if (i > 0) { Q_strcat(sound, size, "%02i", rand() % i + 1); return sound; } return ""; }
/** * @brief Play a sound on the client side * @param[in] self Pointer to the event structure that is currently executed * @param[in] msg holds the network data * @sa EV_SOUND * @note if the last character of the sound file string that was sent by the * server is a '+', we will select a random sound file by replacing the '+' * character with a number between 01..99 */ void CL_SoundEvent (const eventRegister_t *self, struct dbuffer *msg) { char sound[MAX_QPATH]; vec3_t origin; int number; le_t *le; size_t length; /* read data */ NET_ReadFormat(msg, self->formatString, &number, &origin, &sound, sizeof(sound)); le = LE_Get(number); if (le) { if (LE_IsLivingActor(le) && le->team != cls.team) { /** @todo render */ } else if (LE_IsDoor(le) || LE_IsBreakable(le)) { /** @todo render */ } } length = strlen(sound) - 1; if (sound[length] == '+') { int i; sound[length] = '\0'; for (i = 1; i <= 99; i++) { if (FS_CheckFile("sounds/%s%02i", sound, i) == -1) break; } Com_sprintf(sound + length, sizeof(sound) - length, "%02i", rand() % i + 1); } Com_DPrintf(DEBUG_SOUND, "Play network sample %s at (%f:%f:%f)\n", sound, origin[0], origin[1], origin[2]); S_LoadAndPlaySample(sound, origin, SOUND_ATTN_NORM, SND_VOLUME_DEFAULT); }
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"; }
static void testDoorTrigger (void) { const char *mapName = "test_game"; if (FS_CheckFile("maps/%s.bsp", mapName) != -1) { edict_t *e = NULL; int cnt = 0; int doors = 0; /* the other tests didn't call the server shutdown function to clean up */ OBJZERO(*sv); SV_Map(true, mapName, NULL); while ((e = G_EdictsGetNextInUse(e))) { cnt++; if (e->type == ET_DOOR) { if (Q_streq(e->targetname, "left-0")) { /* this one is triggered by an actor standing inside of a trigger_touch */ CU_ASSERT_TRUE(e->doorState); } else if (Q_streq(e->targetname, "right-0")) { /* this one has a trigger_touch, too - but nobody is touching that trigger yet */ CU_ASSERT_FALSE(e->doorState); } else { /* both of the used doors have a targetname set */ CU_ASSERT(false); } doors++; } } SV_ShutdownGameProgs(); CU_ASSERT_TRUE(cnt > 0); CU_ASSERT_TRUE(doors == 2); } else { UFO_CU_FAIL_MSG(va("Map resource '%s.bsp' for test is missing.", mapName)); } }
static void testMove (void) { vec3_t vec; pos3_t pos; pos_t gridPos; if (FS_CheckFile("maps/%s.bsp", mapName) != -1) { char entityString[MAX_TOKEN_CHARS]; CM_LoadMap(mapName, true, "", entityString, &mapData, &mapTiles); CM_LoadMap(mapName, true, "", entityString, &mapData, &mapTiles); } else { UFO_CU_FAIL_MSG_FATAL(va("Map resource '%s.bsp' for test is missing.", mapName)); } VectorSet(vec, 16, 16, 48); VecToPos(vec, pos); CU_ASSERT_EQUAL(pos[0], 128); CU_ASSERT_EQUAL(pos[1], 128); CU_ASSERT_EQUAL(pos[2], 0); VectorSet(vec, 80, 16, 80); VecToPos(vec, pos); CU_ASSERT_EQUAL(pos[0], 130); CU_ASSERT_EQUAL(pos[1], 128); CU_ASSERT_EQUAL(pos[2], 1); gridPos = Grid_Fall(mapData.routing, ACTOR_SIZE_NORMAL, pos); CU_ASSERT_EQUAL(gridPos, 1); { const byte crouchingState = 0; const int maxTUs = MAX_ROUTE_TUS; int lengthStored; pos3_t to; pathing_t* path = Mem_AllocType(pathing_t); VectorSet(vec, 80, 80, 32); VecToPos(vec, pos); Grid_CalcPathing(mapData.routing, ACTOR_SIZE_NORMAL, path, pos, maxTUs, nullptr); Grid_MoveStore(path); /* move downwards */ { int lengthUnstored; VectorSet(vec, 80, 48, 32); VecToPos(vec, to); lengthUnstored = Grid_MoveLength(path, to, crouchingState, false); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthUnstored, lengthStored); CU_ASSERT_EQUAL(lengthStored, TU_MOVE_STRAIGHT); } /* try to move three steps upwards - there is a brush*/ { VectorSet(vec, 80, 176, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, ROUTING_NOT_REACHABLE); } /* try move into the nodraw */ { VectorSet(vec, 48, 16, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, ROUTING_NOT_REACHABLE); } /* move into the lightclip */ { VectorSet(vec, 48, 48, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, TU_MOVE_DIAGONAL); } /* move into the passable */ { VectorSet(vec, 144, 48, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, TU_MOVE_DIAGONAL + TU_MOVE_STRAIGHT); } /* go to the other side - diagonal, followed by six straight moves */ { VectorSet(vec, -16, 48, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 6 * TU_MOVE_STRAIGHT + TU_MOVE_DIAGONAL); } /* try to walk out of the map */ { VectorSet(vec, 48, 272, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, ROUTING_NOT_REACHABLE); } /* walk to the map border */ { VectorSet(vec, 48, 240, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 4 * TU_MOVE_STRAIGHT + TU_MOVE_DIAGONAL); } /* walk a level upwards */ { VectorSet(vec, 240, 80, 96); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 5 * TU_MOVE_STRAIGHT); } /* move to the door (not a func_door) */ { VectorSet(vec, 176, -80, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 4 * TU_MOVE_STRAIGHT + 2 * TU_MOVE_DIAGONAL); } /* move into the trigger_touch */ { VectorSet(vec, -48, -80, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 5 * TU_MOVE_STRAIGHT + 3 * TU_MOVE_DIAGONAL); } /* try to walk into the actorclip */ { VectorSet(vec, -48, -48, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, ROUTING_NOT_REACHABLE); } } }
/** * Take a screenshot of the frame buffer * @param[in] x * @param[in] y * @param[in] width * @param[in] height * @param[in] filename Force to use a filename. Else NULL to autogen a filename * @param[in] ext Force to use an image format (tga/png/jpg). Else NULL to use value of r_screenshot_format */ void R_ScreenShot (int x, int y, int width, int height, const char *filename, const char *ext) { char checkName[MAX_OSPATH]; int type, shotNum, quality = 100; qFILE f; int rowPack; glGetIntegerv(GL_PACK_ALIGNMENT, &rowPack); glPixelStorei(GL_PACK_ALIGNMENT, 1); /* Find out what format to save in */ if (ext == NULL) ext = r_screenshot_format->string; if (!Q_strcasecmp(ext, "png")) type = SSHOTTYPE_PNG; else if (!Q_strcasecmp(ext, "jpg")) type = SSHOTTYPE_JPG; else type = SSHOTTYPE_TGA_COMP; /* Set necessary values */ switch (type) { case SSHOTTYPE_TGA_COMP: Com_Printf("Taking TGA screenshot...\n"); ext = "tga"; break; case SSHOTTYPE_PNG: Com_Printf("Taking PNG screenshot...\n"); ext = "png"; break; case SSHOTTYPE_JPG: if (Cmd_Argc() == 3) quality = atoi(Cmd_Argv(2)); else quality = r_screenshot_jpeg_quality->integer; if (quality > 100 || quality <= 0) quality = 100; Com_Printf("Taking JPG screenshot (at %i%% quality)...\n", quality); ext = "jpg"; break; } /* Find a file name to save it to */ if (filename) { Com_sprintf(checkName, sizeof(checkName), "scrnshot/%s.%s", filename, ext); } else { for (shotNum = 0; shotNum < 1000; shotNum++) { Com_sprintf(checkName, sizeof(checkName), "scrnshot/ufo%i%i.%s", shotNum / 10, shotNum % 10, ext); if (FS_CheckFile("%s", checkName) == -1) break; } if (shotNum == 1000) { Com_Printf("R_ScreenShot_f: screenshot limit (of 1000) exceeded!\n"); return; } } /* Open it */ FS_OpenFile(checkName, &f, FILE_WRITE); if (!f.f) { Com_Printf("R_ScreenShot_f: Couldn't create file: %s\n", checkName); return; } /* Allocate room for a copy of the framebuffer */ byte* const buffer = Mem_PoolAllocTypeN(byte, width * height * 3, vid_imagePool); if (!buffer) { Com_Printf("R_ScreenShot_f: Could not allocate %i bytes for screenshot!\n", width * height * 3); FS_CloseFile(&f); return; } /* Read the framebuffer into our storage */ glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); R_CheckError(); /* Write */ switch (type) { case SSHOTTYPE_TGA_COMP: R_WriteCompressedTGA(&f, buffer, width, height); break; case SSHOTTYPE_PNG: R_WritePNG(&f, buffer, width, height); break; case SSHOTTYPE_JPG: R_WriteJPG(&f, buffer, width, height, quality); break; } /* Finish */ FS_CloseFile(&f); Mem_Free(buffer); Com_Printf("Wrote %s to %s\n", checkName, FS_Gamedir()); glPixelStorei(GL_PACK_ALIGNMENT, rowPack); }
/** * @brief Validate a path supplied by a filelist. * @param[in,out] path Pointer to file (path) to download (high bits will be stripped). * @sa CL_QueueHTTPDownload * @sa CL_ParseFileList */ static void CL_CheckAndQueueDownload (char *path) { size_t length; const char *ext; bool pak; bool gameLocal; StripHighBits(path); length = strlen(path); if (length >= MAX_QPATH) return; ext = Com_GetExtension(path); if (ext == NULL) return; if (Q_streq(ext, "pk3")) { Com_Printf("NOTICE: Filelist is requesting a .pk3 file (%s)\n", path); pak = true; } else pak = false; if (!pak && !Q_streq(ext, "bsp") && !Q_streq(ext, "wav") && !Q_streq(ext, "md2") && !Q_streq(ext, "ogg") && !Q_streq(ext, "md3") && !Q_streq(ext, "png") && !Q_streq(ext, "jpg") && !Q_streq(ext, "obj") && !Q_streq(ext, "mat") && !Q_streq(ext, "ump")) { Com_Printf("WARNING: Illegal file type '%s' in filelist.\n", path); return; } if (path[0] == '@') { if (pak) { Com_Printf("WARNING: @ prefix used on a pk3 file (%s) in filelist.\n", path); return; } gameLocal = true; path++; length--; } else gameLocal = false; if (strstr(path, "..") || !isvalidchar(path[0]) || !isvalidchar(path[length - 1]) || strstr(path, "//") || strchr(path, '\\') || (!pak && !strchr(path, '/')) || (pak && strchr(path, '/'))) { Com_Printf("WARNING: Illegal path '%s' in filelist.\n", path); return; } /* by definition pk3s are game-local */ if (gameLocal || pak) { bool exists; /* search the user homedir to find the pk3 file */ if (pak) { char gamePath[MAX_OSPATH]; FILE *f; Com_sprintf(gamePath, sizeof(gamePath), "%s/%s", FS_Gamedir(), path); f = fopen(gamePath, "rb"); if (!f) exists = false; else { exists = true; fclose(f); } } else exists = FS_CheckFile("%s", path); if (!exists) { if (CL_QueueHTTPDownload(path)) { /* pk3s get bumped to the top and HTTP switches to single downloading. * this prevents someone on 28k dialup trying to do both the main .pk3 * and referenced configstrings data at once. */ if (pak) { dlqueue_t** anchor = &cls.downloadQueue; while ((*anchor)->next) anchor = &(*anchor)->next; /* Remove the last element from the end of the list ... */ dlqueue_t* const d = *anchor; *anchor = 0; /* ... and prepend it to the list. */ d->next = cls.downloadQueue; cls.downloadQueue = d; } } } } else CL_CheckOrDownloadFile(path); }
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)); } }