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)); } }
TEST_F(GameTest, CountSpawnpoints) { const char* filterId = TEST_GetStringProperty("mapdef-id"); const mapDef_t* md; Cvar_Set("rm_drop", "+craft_drop_herakles"); /* use a known seed to reproduce an error */ unsigned int seed; if (TEST_ExistsProperty("mapdef-seed")) { seed = TEST_GetLongProperty("mapdef-seed"); } else { seed = (unsigned int) time(nullptr); } srand(seed); MapDef_Foreach(md) { if (md->mapTheme[0] == '.') continue; if (filterId && !Q_streq(filterId, md->id)) continue; if (md->aircraft) /* if the mapdef has a list of dropships, let's assume they bring their own spawnpoints */ continue; Com_Printf("testCountSpawnpoints: Mapdef %s (seed %u)\n", md->id, seed); const char* asmName = (const char*)LIST_GetByIdx(md->params, 0); SV_Map(true, md->mapTheme, asmName, false); const int spawnPoints = static_cast<int>(level.num_spawnpoints[TEAM_PHALANX]); Com_Printf("Map: %s Mapdef %s Spawnpoints: %i\n", md->mapTheme, md->id, spawnPoints); ASSERT_TRUE(level.num_spawnpoints[TEAM_PHALANX] >= 12) << "Map " << md->mapTheme << " only " << spawnPoints << " spawnpoints"; } }
/* * ============== SV_Loadgame_f * * ============== */ void SV_Loadgame_f(void) { char name[MAX_OSPATH]; FILE *f; char *dir; if (Cmd_Argc() != 2) { Com_Printf("USAGE: loadgame <directory>\n"); return; } Com_Printf("Loading game...\n"); dir = Cmd_Argv(1); if (strstr(dir, "..") || strstr(dir, "/") || strstr(dir, "\\")) { Com_Printf("Bad savedir.\n"); } /* make sure the server.ssv file exists */ Com_sprintf(name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir(), Cmd_Argv(1)); f = fopen(name, "rb"); if (!f) { Com_Printf("No such savegame: %s\n", name); return; } fclose(f); SV_CopySaveGame(Cmd_Argv(1), "current"); SV_ReadServerFile(); /* go to the map */ sv.state = ss_dead; /* don't save current level when changing */ SV_Map(false, svs.mapcmd, true); }
/* ============== SV_Loadgame_f ============== */ static void SV_Loadgame_f (void) { char name[MAX_OSPATH]; char *dir; if (Cmd_Argc() != 2) { Com_Printf ("USAGE: loadgame <directory>\n"); return; } dir = Cmd_Argv(1); if (strstr(dir, "..") || strchr(dir, '/') || strchr(dir, '\\')) { Com_Printf ("Bad savedir.\n"); return; } // make sure the server.ssv file exists Com_sprintf (name, sizeof(name), "save/%s/server.ssv", Cmd_Argv(1)); if (FS_LoadFileEx( name, NULL, FS_TYPE_REAL|FS_PATH_GAME ) == -1 ) { Com_Printf ("No such savegame: %s\n", name); return; } Com_Printf ("Loading game...\n"); SV_CopySaveGame(Cmd_Argv(1), "current"); SV_ReadServerFile (); // go to the map sv.state = ss_dead; // don't save current level when changing SV_Map (false, svs.mapcmd, true); }
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); }
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); }
/* ================== SV_GameMap_f Saves the state of the map just being exited and goes to a new map. If the initial character of the map string is '*', the next map is in a new unit, so the current savegame directory is cleared of map files. Example: *inter.cin+jail Clears the archived maps, plays the inter.cin cinematic, then goes to map jail.bsp. ================== */ void SV_GameMap_f (void) { char *map; int i; client_t *cl; qboolean *savedInuse; if (Cmd_Argc() != 2) { Com_Printf ("USAGE: gamemap <map>\n"); return; } Com_DPrintf("SV_GameMap(%s)\n", Cmd_Argv(1)); FS_CreatePath (va("%s/save/current/", FS_Gamedir())); // check for clearing the current savegame map = Cmd_Argv(1); if (map[0] == '*') { // wipe all the *.sav files SV_WipeSavegame ("current"); } else { // save the map just exited if (sv.state == ss_game) { // clear all the client inuse flags before saving so that // when the level is re-entered, the clients will spawn // at spawn points instead of occupying body shells savedInuse = malloc(maxclients->value * sizeof(qboolean)); for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++) { savedInuse[i] = cl->edict->inuse; cl->edict->inuse = false; } SV_WriteLevelFile (); // we must restore these for clients to transfer over correctly for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++) cl->edict->inuse = savedInuse[i]; free (savedInuse); } } // start up the next map SV_Map (false, Cmd_Argv(1), false ); // archive server state strncpy (svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd)-1); // copy off the level to the autosave slot if (!dedicated->value) { SV_WriteServerFile (true); SV_CopySaveGame ("current", "save0"); } }
/* ================== SV_DemoMap_f Puts the server in demo mode on a specific map/cinematic ================== */ void SV_DemoMap_f (void) { // Knightmare- force off DM, CTF mode Cvar_SetValue( "ttctf", 0); Cvar_SetValue( "ctf", 0); Cvar_SetValue( "deathmatch", 0); SV_Map (true, Cmd_Argv(1), false ); }
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); } }
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 */ }
/* * Puts the server in demo mode on a specific map/cinematic */ void SV_DemoMap_f(void) { if (Cmd_Argc() != 2) { Com_Printf("USAGE: demomap <demoname.dm2>\n"); return; } SV_Map(true, Cmd_Argv(1), false); }
/** * @brief This test cycles through the list of map definitions found in the maps.ufo script * and tries to load (and build in case of RMA) each map. */ static void testMapDefsSingleplayer (void) { int i; CU_ASSERT_TRUE(cls.numMDs > 0); for (i = 0; i < cls.numMDs; i++) { const mapDef_t* md = &cls.mds[i]; if (md->map[0] == '.') continue; SV_Map(qtrue, md->map, md->param); CU_PASS(md->map); } }
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)); } }
/* ============== SV_Loadgame_f ============== */ void SV_Loadgame_f (void) { char name[MAX_OSPATH]; FILE *f; char *dir; if (Cmd_Argc() != 2) { Com_Printf ("USAGE: loadgame <directory>\n"); return; } Com_Printf ("Loading game...\n"); dir = Cmd_Argv(1); if (strstr (dir, "..") || strstr (dir, "/") || strstr (dir, "\\") ) { Com_Printf ("Bad savedir.\n"); } // make sure the server.ssv file exists Com_sprintf (name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir(), Cmd_Argv(1)); f = fopen (name, "rb"); if (!f) { Com_Printf ("No such savegame: %s\n", name); return; } fclose (f); // Knightmare- set saveshot name if ( !dedicated->value && (!strcmp(Cmd_Argv(1), "quick") || !strcmp(Cmd_Argv(1), "quik")) ) { Com_sprintf(sv_loadshotname, sizeof(sv_loadshotname), "save/%s/shot.png", Cmd_Argv(1)); R_FreePic (sv_loadshotname); Com_sprintf(sv_loadshotname, sizeof(sv_loadshotname), "/save/%s/shot.png", Cmd_Argv(1)); load_saveshot = R_DrawFindPic(sv_loadshotname); } SV_CopySaveGame (Cmd_Argv(1), "current"); SV_ReadServerFile (); // go to the map sv.state = ss_dead; // don't save current level when changing SV_Map (false, svs.mapcmd, true); }
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)); } }
static void testMapDefsMultiplayer (void) { int i; CU_ASSERT_TRUE(cls.numMDs > 0); masterserver_url = Cvar_Get("noname", "", 0, NULL); http_timeout = Cvar_Get("noname", "", 0, NULL); http_proxy = Cvar_Get("noname", "", 0, NULL); Cvar_Set("sv_maxclients", "2"); for (i = 0; i < cls.numMDs; i++) { const mapDef_t* md = &cls.mds[i]; if (md->multiplayer) { SV_Map(qtrue, md->map, md->param); CU_PASS(md->map); } } }
/* ================== SV_DemoMap_f Puts the server in demo mode on a specific map/cinematic ================== */ static void SV_DemoMap_f (void) { char demoName[MAX_QPATH]; if (Cmd_Argc() != 2) { Com_Printf ("USAGE: demomap <demoname>\n"); return; } if(strlen(Cmd_Argv(1)) >= sizeof(demoName)-1) { Com_Printf("Demomap: Demo name is too long\n"); return; } Q_strncpyz(demoName, Cmd_Argv(1), sizeof(demoName)); COM_DefaultExtension(demoName, sizeof(demoName), ".dm2"); SV_Map (true, demoName, false ); }
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)); } }
/* ================== SV_GameMap_f Saves the state of the map just being exited and goes to a new map. If the initial character of the map string is '*', the next map is in a new unit, so the current savegame directory is cleared of map files. Example: *inter.cin+jail Clears the archived maps, plays the inter.cin cinematic, then goes to map jail.bsp. ================== */ static void SV_GameMap_f (void) { char *map, expanded[MAX_QPATH], tMap[MAX_QPATH]; int i; client_t *cl; //qboolean *savedInuse; if (Cmd_Argc() != 2) { Com_Printf ("USAGE: gamemap <map>\n"); return; } Q_strncpyz(tMap, Cmd_Argv(1), sizeof(tMap)); map = tMap; Com_DPrintf("SV_GameMap(%s)\n", map); FS_CreatePath (va("%s/save/current/", FS_Gamedir())); // check for clearing the current savegame if (map[0] == '*') { // wipe all the *.sav files SV_WipeSavegame("current"); } else { // save the map just exited if (!strchr(map, '.') && !strchr(map, '$')) { Com_sprintf (expanded, sizeof(expanded), "maps/%s.bsp", map); if (FS_LoadFile (expanded, NULL) == -1) { Com_Printf ("Can't find %s\n", expanded); return; } } if (sv.state == ss_game) { qboolean savedInuse[MAX_CLIENTS]; // clear all the client inuse flags before saving so that // when the level is re-entered, the clients will spawn // at spawn points instead of occupying body shells //savedInuse = malloc(maxclients->integer * sizeof(qboolean)); for (i=0,cl=svs.clients ; i<maxclients->integer; i++,cl++) { savedInuse[i] = cl->edict->inuse; cl->edict->inuse = false; } SV_WriteLevelFile (); // we must restore these for clients to transfer over correctly for (i=0,cl=svs.clients ; i<maxclients->integer; i++,cl++) cl->edict->inuse = savedInuse[i]; //free (savedInuse); } } // start up the next map SV_Map (false, map, false ); // archive server state Q_strncpyz (svs.mapcmd, map, sizeof(svs.mapcmd)); // copy off the level to the autosave slot if (!dedicated->integer && !Cvar_VariableIntValue("deathmatch")) { SV_WriteServerFile(true); SV_CopySaveGame("current", "save0"); } }
void GameTest::testCountSpawnpointsForMapInSingleplayerMode(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo) { if (verbose) { std::cout << "[ ] adding test parameter: gamemode singleplayer" << std::endl; Com_Printf("CountSpawnpoints - adding test parameter: gamemode singleplayer\n"); } /* Set initial values. */ /* load singleplayer map */ Cvar_Set("sv_maxclients", "1"); /* It seems, because of reaction-fire limitations we cannot spawn more than 128 actors total. */ Cvar_Set("sv_maxsoldiersperteam", "12"); Cvar_Set("ai_singleplayeraliens", "64"); Cvar_Set("ai_numcivilians", "16"); Com_Printf("CountSpawnpoints - loading map: mode singleplayer mapdef %s map %s assembly %s dropship %s ufo %s\n", md->id, md->mapTheme, asmName, aircraft, ufo); long time = Sys_Milliseconds(); try { SV_Map(true, md->mapTheme, asmName, true); } catch (comDrop_t&) { ADD_FAILURE() << "Error: Failed to load assembly " << asmName << " from mapdef " << md->id << ", map " << md->mapTheme << " aircraft: " << aircraft << ", ufo: " << ufo << " => singleplayer mode."; Com_Printf("CountSpawnpoints - error: Failed to load map.\n"); SV_ShutdownGameProgs(); return; } time = Sys_Milliseconds() - time; Com_Printf("CountSpawnpoints - result: %li ms\n", time); mapCount++; /* This is the max number of aliens the UFO can bring to the battlefield. */ const int numteamUFO = testCountSpawnpointsGetNumteamValueForUFO(ufo); /* The number of human spawnpoints required on the map depends on the 'numteam' value of the used dropship, if any. */ const int minHumans = testCountSpawnpointsGetNumteamValueForAircraft(aircraft); /* The number of spawnpoints for 2x2 units required on the map depends on the number of UGVs the aircraft can transport. */ const int minHuman2x2 = testCountSpawnpointsGetNum2x2ValueForAircraft(aircraft); /* How many aliens do we need to have on the map, at least? The mapdef defines the map to support up to 'maxaliens' aliens, so the map should have at least this number of spawnpoints available. However, this number must not be higher than the 'numteam' value of the used UFO, if any. */ const int minAliens = std::min(md->maxAliens, numteamUFO); /* Count the spawnpoints available on the map. */ const int spawnCivs = static_cast<int>(level.num_spawnpoints[TEAM_CIVILIAN]); const int spawnHumans = static_cast<int>(level.num_spawnpoints[TEAM_PHALANX]); const int spawnAliens = static_cast<int>(level.num_spawnpoints[TEAM_ALIEN]); const int spawnHuman2x2 = static_cast<int>(level.num_2x2spawnpoints[TEAM_PHALANX]); /* Make gtest report back in case there are not enough human spawnpoints. */ EXPECT_GE(spawnHumans, minHumans) << "Error: Assembly " << asmName << " in mapdef " << md->id << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft << " ufo: " << ufo << "): Only " << spawnHumans << " human spawnpoints but " << minHumans << " expected."; /* Make gtest report back in case there are not enough alien spawnpoints. */ EXPECT_GE(spawnAliens, minAliens) << "Error: Assembly " << asmName << " in mapdef " << md->id << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft << " ufo: " << ufo << "): Only " << spawnAliens << " alien spawnpoints but " << minAliens << " expected."; /* Make gtest report back in case there are not enough human 2x2 spawnpoints. */ EXPECT_GE(spawnHuman2x2, minHuman2x2) << "Error: Assembly " << asmName << " in mapdef " << md->id << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft << " ufo: " << ufo << "): Only " << spawnHuman2x2 << " human 2x2 spawnpoints but " << minHuman2x2 << " expected."; /* Make gtest report back if the number of aliens allowed on the map is smaller than the crew number of the used UFO, if any. */ if (ufo) EXPECT_GE(md->maxAliens, numteamUFO) << "Error: Assembly " << asmName << " in mapdef " << md->id << " from map " << md->mapTheme << " in singleplayer mode (aircraft: " << aircraft << " ufo: " << ufo << "): The number of aliens allowed on the map is smaller than expected."; /* Print report to log. */ Com_Printf("CountSpawnpoints - map: mode singleplayer\n"); Com_Printf("CountSpawnpoints - map: mapdef %s\n", md->id); Com_Printf("CountSpawnpoints - map: map %s\n", md->mapTheme); Com_Printf("CountSpawnpoints - map: assembly %s\n", asmName); Com_Printf("CountSpawnpoints - map: aircraft %s \n", aircraft); Com_Printf("CountSpawnpoints - map: ufo %s\n", ufo); Com_Printf("CountSpawnpoints - count spawnpoints: civilian %i\n", spawnCivs); Com_Printf("CountSpawnpoints - count spawnpoints: singleplayer needs/found %i/%i\n", minHumans, spawnHumans); Com_Printf("CountSpawnpoints - count spawnpoints: singleplayer_2x2 needs/found %i/%i\n", minHuman2x2, spawnHuman2x2); Com_Printf("CountSpawnpoints - count spawnpoints: alien needs/found %i/%i\n", minAliens, spawnAliens); if (spawnHumans < minHumans) Com_Printf("CountSpawnpoints - error: missing spawnpoints - singleplayer needs/found %i/%i\n", minHumans, spawnHumans); if (spawnHuman2x2 < minHuman2x2) Com_Printf("CountSpawnpoints - error: missing spawnpoints - singleplayer_2x2 needs/found %i/%i\n", minHuman2x2, spawnHuman2x2); if (spawnAliens < minAliens) Com_Printf("CountSpawnpoints - error: missing spawnpoints - alien needs/found %i/%i\n", minAliens, spawnAliens); if (ufo) { if (md->maxAliens < numteamUFO) { Com_Printf("CountSpawnpoints - error: mapdef parameter - maxaliens needs/found %i/%i\n", numteamUFO, md->maxAliens); } } SV_ShutdownGameProgs(); }
void GameTest::testCountSpawnpointsForMapInMultiplayerMode(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo) { if (verbose) { std::cout << "[ ] adding test parameter: gamemode multiplayer" << std::endl; Com_Printf("CountSpawnpoints - adding test parameter: gamemode multiplayer\n"); } if (LIST_IsEmpty(md->gameTypes)) { ADD_FAILURE() << "Error: Multiplayer enabled, but no gametypes defined in mapdef " << md->id; Com_Printf("CountSpawnpoints - error: Multiplayer enabled, but no gametypes defined in mapdef.\n"); return; } if (md->teams < 1) { ADD_FAILURE() << "Error: Multiplayer enabled, but number of teams is " << md->teams; Com_Printf("CountSpawnpoints - error: Multiplayer enabled, but number of teams is %i.\n", md->teams); return; } /* Set initial values. */ /* Load map in multiplayer mode. */ Cvar_Set("sv_maxclients", DOUBLEQUOTE(MAX_CLIENTS)); /* It seems, because of reaction-fire limitations we cannot spawn more than 128 actors total. */ Cvar_Set("sv_maxsoldiersperteam", "12"); Cvar_Set("ai_multiplayeraliens", "64"); Cvar_Set("ai_numcivilians", "16"); Com_Printf("CountSpawnpoints - loading map: mode multiplayer mapdef %s map %s assembly %s dropship %s ufo %s\n", md->id, md->mapTheme, asmName, aircraft, ufo); long time = Sys_Milliseconds(); try { SV_Map(true, md->mapTheme, asmName, true); } catch (comDrop_t&) { ADD_FAILURE() << "Error: Failed to load assembly " << asmName << " from mapdef " << md->id << ", map " << md->mapTheme << " aircraft: " << aircraft << ", ufo: " << ufo << " => multiplayer mode."; Com_Printf("CountSpawnpoints - error: Multiplayer enabled, but no gametypes defined in mapdef.\n"); Com_Printf("CountSpawnpoints - error: Failed to load map.\n"); SV_ShutdownGameProgs(); return; } time = Sys_Milliseconds() - time; Com_Printf("CountSpawnpoints - result: %li ms\n", time); SV_ShutdownGameProgs(); mapCount++; /* Print report to log. */ Com_Printf("CountSpawnpoints - map: mode multiplayer\n"); Com_Printf("CountSpawnpoints - map: mapdef %s\n", md->id); Com_Printf("CountSpawnpoints - map: map %s\n", md->mapTheme); Com_Printf("CountSpawnpoints - map: assembly %s\n", asmName); Com_Printf("CountSpawnpoints - map: aircraft %s \n", aircraft); Com_Printf("CountSpawnpoints - map: ufo %s\n", ufo); /* Check if one of the gametypes available in the mapdef defines a coop mode, in which case we will need aliens on the map. */ int coop = 0; /* The number of alien spawnpoints required on the map. In PvP gamemodes this is zero, while in coop games we check for the number given as 'maxaliens' in the mapdef. */ int minAliens = 0; /* The number of player spawnpoints required for each team is determined by the value of sv_maxsoldiersperteam given in the gametype def. */ int minMP = 0; /* Count spawnpoints for TEAM_CIVILIAN. */ const int spawnCivs = static_cast<int>(level.num_spawnpoints[TEAM_CIVILIAN]); Com_Printf("CountSpawnpoints - count spawnpoints: civilian %i\n", spawnCivs); /* Find the highest numbers for alien and player spawnpoints needed in the map. */ LIST_Foreach(md->gameTypes, const char, gameType) { for (int i = 0; i < csi.numGTs; i++) { const gametype_t* gt = &csi.gts[i]; if (!Q_streq(gt->id, gameType)) continue; const cvarlist_t* list = gt->cvars; for (int j = 0; j < gt->num_cvars; j++, list++) { if (Q_streq(list->name, "ai_multiplayeraliens")) { coop = std::max(coop, atoi(list->value)); } else if (Q_streq(list->name, "sv_maxsoldiersperteam")) { minMP = std::max(minMP, atoi(list->value)); } } } } /* If the mapdef does not define a coop mode, we do not need aliens. */ if (coop) minAliens = std::min(md->maxAliens, testCountSpawnpointsGetNumteamValueForUFO(ufo)); const int startTeam = TEAM_CIVILIAN + 1; /* For every single mp team defined in the mapdef - check if there are enough spawnpoints available. */ for (int currTeamNum = startTeam; currTeamNum < startTeam + md->teams; ++currTeamNum) { if (currTeamNum > TEAM_MAX_HUMAN) { ADD_FAILURE() << "Error: Mapdef " << md->id << " has too many teams set."; Com_Printf("CountSpawnpoints - error: Too many teams set.\n"); break; } const int spawnTeam = static_cast<int>(level.num_spawnpoints[currTeamNum]); /* Make gtest report back in case there are not enough spawnpoints available for the team. */ EXPECT_GE(spawnTeam, minMP) << "Error: Assembly " << asmName << " from mapdef " << md->id << ", map " << md->mapTheme << "(aircraft: " << aircraft << ", ufo: " << ufo << ") in multiplayer mode: Only " << spawnTeam << " spawnpoints for team " << currTeamNum << " but " << minMP << " expected."; /* Log the result. */ Com_Printf("CountSpawnpoints - count spawnpoints: player team/needs/found %i/%i/%i\n", currTeamNum, minMP, spawnTeam); if (spawnTeam < minMP) Com_Printf("CountSpawnpoints - error: missing spawnpoints - player team/needs/found %i/%i/%i\n", currTeamNum, minMP, spawnTeam); } if (minAliens) { const int spawnAliens = static_cast<int>(level.num_spawnpoints[TEAM_ALIEN]); /* Make gtest report back in case there are not enough alien spawnpoints available. */ EXPECT_GE(spawnAliens, minAliens) << "Assembly " << asmName << " from mapdef " << md->id << ", map " << md->mapTheme << "(aircraft: " << aircraft << ", ufo: " << ufo << ") in multiplayer mode defines at least one coop game mode," << " but does not have enough alien spawn positions for that. We expect at least " << minAliens << " spawn positions for aliens, the map provides " << spawnAliens << "."; /* Log the result. */ Com_Printf("CountSpawnpoints - count spawnpoints: alien needs/found %i/%i\n", minAliens, spawnAliens); if (spawnAliens < minAliens) Com_Printf("CountSpawnpoints - error: missing spawnpoints - alien needs/found %i/%i\n", minAliens, spawnAliens); } SV_ShutdownGameProgs(); }
/** * @brief This test cycles through the list of map definitions found in the maps.ufo script * and tries to find surfaces to stand on with no sound assigned to them. * * This test takes too long to be run every time testall is run. So it's set up almost like a game: * After 5 maps (the first of them is fully checked) with missing sounds, the test stops. * If we manage to 'clean' one of those 5 maps, the next map will show up in the next run. */ TEST_F(FootStepTest, DISABLED_MapDefsFootSteps) { const char* filterId = TEST_GetStringProperty("mapdef-id"); const mapDef_t* md; int mapCount = 0; // the number of maps read int badMapCount = 0; const int skipCount = 20; // to skip the first n mapDefs const int badMapCountMax = 25; // # of maps with missing sounds before this test stops const int mapCountMax = 150; // should of cause be higher than skip + bad const int texCountMax = 30; char texNames[texCountMax][MAX_QPATH]; bool done = false; OBJZERO(texNames); ASSERT_TRUE(csi.numMDs > 0); MapDef_Foreach(md) { if (md->mapTheme[0] == '.') continue; if (filterId && !Q_streq(filterId, md->id)) continue; mapCount++; if (mapCount <= skipCount) continue; /* use a known seed to reproduce an error */ unsigned int seed; if (TEST_ExistsProperty("mapdef-seed")) { seed = TEST_GetLongProperty("mapdef-seed"); } else { seed = (unsigned int) time(nullptr); } srand(seed); int count = 0; Com_Printf("testMapDefsFootSteps: Mapdef %s (seed %u)\n", md->id, seed); const char* asmName = (const char*)LIST_GetByIdx(md->params, 0); SV_Map(true, md->mapTheme, asmName); /* now that we have loaded the map, check all cells for walkable places */ GridBox mBox(sv->mapData.mapBox); // test ALL the cells #if !FOOTSTEPS_FULL if (mapCount >= skipCount + 4) { // after the first 4 maps, reduce the testing area const pos3_t center = {148, 128, 0}; mBox.set(center, center); // the box on the map we're testing mBox.expandXY(10); // just test a few cells around the center of the map mBox.maxs[2] = 2; // and 3 levels high } #endif mBox.clipToMaxBoundaries(); for (int x = mBox.getMinX(); x <= mBox.getMaxX() && !done; x++) { for (int y = mBox.getMinY(); y <= mBox.getMaxY() && !done; y++) { for (int z = mBox.getMinZ(); z <= mBox.getMaxZ(); z++) { const int floor = sv->mapData.routing.getFloor(1, x, y, z); if (floor < 0) // if we have a floor in that cell continue; const AABB noBox(vec3_origin, vec3_origin); // we're doing a point-trace const pos3_t cellPos = {(pos_t)x, (pos_t)y, (pos_t)z}; // the cell in question vec3_t from, to; PosToVec(cellPos, from); // the center of the cell VectorCopy(from, to); // also base for the endpoint of the trace from[2] -= UNIT_HEIGHT / 2; // bottom of the cell from[2] += (floor + 2) * QUANT; // add the height of the floor plus 2 QUANTS to[2] -= 2 * UNIT_HEIGHT; // we should really hit the ground with this const trace_t trace = SV_Trace(Line(from, to), noBox, nullptr, MASK_SOLID); if (!trace.surface) continue; const char* snd = SV_GetFootstepSound(trace.surface->name); if (snd) continue; for (int i = 0; i < texCountMax; ++i) { if (!texNames[i][0]) { // found a free slot ? Q_strncpyz(texNames[i], trace.surface->name, sizeof(texNames[i])); count++; break; } if (Q_streq(trace.surface->name, texNames[i])) // already there ? break; } if (count > texCountMax) { done = true; break; // the z-loop } } } } if (!texNames[0][0]) { Com_Printf("In map %s, asm %s: Nothing detected\n", md->mapTheme, asmName); } else { ++badMapCount; for (int i = 0; i < texCountMax; ++i) { if (texNames[i][0]) { Com_Printf("In map %s, asm %s: No sound for: %s\n", md->mapTheme, asmName, texNames[i]); } } } OBJZERO(texNames); SV_ShutdownGameProgs(); if (done || mapCount >= mapCountMax || badMapCount >= badMapCountMax) break; } }
/* ================== SV_GameMap_f Saves the state of the map just being exited and goes to a new map. If the initial character of the map string is '*', the next map is in a new unit, so the current savegame directory is cleared of map files. Example: *inter.cin+jail Clears the archived maps, plays the inter.cin cinematic, then goes to map jail.bsp. ================== */ void SV_GameMap_f (void) { char *map; int32_t i, l; client_t *cl; qboolean *savedInuse; if (Cmd_Argc() != 2) { Com_Printf ("USAGE: gamemap <map>\n"); return; } Com_DPrintf("SV_GameMap(%s)\n", Cmd_Argv(1)); FS_CreatePath (va("%s/save/current/", FS_Gamedir())); // check for clearing the current savegame map = Cmd_Argv(1); if (map[0] == '*') { // wipe all the *.sav files SV_WipeSavegame ("current"); } else { // save the map just exited if (sv.state == ss_game) { // clear all the client inuse flags before saving so that // when the level is re-entered, the clients will spawn // at spawn points instead of occupying body shells savedInuse = (qboolean*)Z_TagMalloc(maxclients->value * sizeof(qboolean), TAG_SERVER); for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++) { savedInuse[i] = cl->edict->inuse; cl->edict->inuse = false; } SV_WriteLevelFile (); // we must restore these for clients to transfer over correctly for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++) cl->edict->inuse = savedInuse[i]; Z_Free (savedInuse); } } // start up the next map SV_Map (false, Cmd_Argv(1), false ); // archive server state strncpy (svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd)-1); // copy off the level to the autosave slot // Knightmare- don't do this in deathmatch or for cinematics l = strlen(map); //l = strcspn(map, "+"); if (!dedicated->value && !Cvar_VariableValue("deathmatch") && Q_strcasecmp (map+l-4, ".cin") && Q_strcasecmp (map+l-4, ".roq") && Q_strcasecmp (map+l-4, ".pcx")) { SV_WriteServerFile (true); SV_CopySaveGame ("current", "vrsave00"); } }
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)); } }
/** * @sa Qcommon_Frame */ void SV_Frame (int now, void* data) { Com_ReadFromPipe(); /* change the gametype even if no server is running (e.g. the first time) */ if (sv_dedicated->integer && sv_gametype->modified) { Com_SetGameType(); sv_gametype->modified = false; } if (sv_dedicated->integer) { const char* s; do { s = Sys_ConsoleInput(); if (s) Cbuf_AddText("%s\n", s); } while (s); } /* if server is not active, do nothing */ if (!svs.initialized) { #ifdef DEDICATED_ONLY Com_Printf("Starting next map from the mapcycle\n"); SV_NextMapcycle(); #endif return; } svs.realtime = now; /* if time is about to hit the 32nd bit, kick all clients * and clear sv.time, rather * than checking for negative time wraparound everywhere. * 2giga-milliseconds = 23 days, so it won't be too often */ if (svs.realtime > 0x70000000) { SV_Map(true, sv->name, sv->assembly); return; } /* keep the random time dependent */ rand(); SV_CheckSpawnSoldiers(); SV_CheckStartMatch(); SV_CheckTimeouts(); if (!sv_threads->integer) SV_RunGameFrame(); else /* signal the game frame thread to wake up */ SDL_CondSignal(svs.gameFrameCond); SV_LogHandleOutput(); /* next map in the cycle */ if (sv->endgame && sv_maxclients->integer > 1) SV_NextMapcycle(); /* send a heartbeat to the master if needed */ Master_Heartbeat(); SV_PingPlayers(); /* server is empty - so shutdown */ if (svs.abandon && svs.killserver) SV_Shutdown("Server disconnected.", false); }
static void testMoveEntities (void) { pos3_t pos; vec3_t vec; pathing_t* path = Mem_AllocType(pathing_t); forbiddenList_t forbiddenList; const byte crouchingState = 0; const int maxTUs = MAX_ROUTE_TUS; forbiddenList.reset(); SV_Map(true, mapName, nullptr); /* starting point */ VectorSet(vec, 240, -144, 32); VecToPos(vec, pos); G_CompleteRecalcRouting(); { Edict* ent = nullptr; while ((ent = G_EdictsGetNextInUse(ent))) { /* Dead 2x2 unit will stop walking, too. */ if (ent->type == ET_SOLID) { int j; for (j = 0; j < ent->forbiddenListSize; j++) { forbiddenList.add(ent->forbiddenListPos[j], (byte*) &ent->fieldSize); } } } } { int lengthStored; pos3_t to; Grid_CalcPathing(sv->mapData.routing, ACTOR_SIZE_NORMAL, path, pos, maxTUs, &forbiddenList); Grid_MoveStore(path); /* walk onto the func_breakable */ { VectorSet(vec, 112, -144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 4 * TU_MOVE_STRAIGHT); } /* walk over the func_breakable */ { VectorSet(vec, 80, -144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 5 * TU_MOVE_STRAIGHT); } /* walk over the func_breakable */ { VectorSet(vec, 16, -144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 7 * TU_MOVE_STRAIGHT); } } /* starting point */ VectorSet(vec, 144, 144, 32); VecToPos(vec, pos); { int lengthStored; pos3_t to; Grid_CalcPathing(sv->mapData.routing, ACTOR_SIZE_NORMAL, path, pos, maxTUs, &forbiddenList); Grid_MoveStore(path); /* walk through the opened door */ { VectorSet(vec, 112, 144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, TU_MOVE_STRAIGHT); } /* walk around the opened door */ { VectorSet(vec, 144, 208, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, true); CU_ASSERT_EQUAL(lengthStored, 2 * TU_MOVE_STRAIGHT + TU_MOVE_DIAGONAL); } } SV_ShutdownGameProgs(); }
/* * ================== SV_DemoMap_f * * Puts the server in demo mode on a specific map/cinematic ================== */ void SV_DemoMap_f(void) { SV_Map(true, Cmd_Argv(1), false); }
/* * SV_Map_f * * User command to change the map * map: restart game, and start map * devmap: restart game, enable cheats, and start map * gamemap: just start the map */ static void SV_Map_f( void ) { char *map; char mapname[MAX_CONFIGSTRING_CHARS]; qboolean found = qfalse; if( Cmd_Argc() < 2 ) { Com_Printf( "Usage: %s <map>\n", Cmd_Argv( 0 ) ); return; } // if map "<map>" is used Cmd_Args() will return the "" as well. if( Cmd_Argc() == 2 ) map = Cmd_Argv( 1 ); else map = Cmd_Args(); Com_DPrintf( "SV_GameMap(%s)\n", map ); // applies to fullnames and filenames (whereas + strlen( "maps/" ) wouldnt) if( strlen( map ) >= MAX_CONFIGSTRING_CHARS ) { Com_Printf( "Map name too long.\n" ); return; } Q_strncpyz( mapname, map, sizeof( mapname ) ); if( ML_ValidateFilename( mapname ) ) { COM_StripExtension( mapname ); if( ML_FilenameExists( mapname ) ) { found = qtrue; } else { ML_Update(); if( ML_FilenameExists( mapname ) ) found = qtrue; } } if( !found ) { if( ML_ValidateFullname( map ) ) { Q_strncpyz( mapname, ML_GetFilename( map ), sizeof( mapname ) ); if( *mapname ) found = qtrue; } if( !found ) { Com_Printf( "Couldn't find map: %s\n", map ); return; } } if( FS_GetNotifications() & FS_NOTIFT_NEWPAKS ) { FS_RemoveNotifications( FS_NOTIFT_NEWPAKS ); sv.state = ss_dead; // don't save current level when changing } else if( !Q_stricmp( Cmd_Argv( 0 ), "map" ) || !Q_stricmp( Cmd_Argv( 0 ), "devmap" ) ) { sv.state = ss_dead; // don't save current level when changing } // start up the next map SV_Map( mapname, !Q_stricmp( Cmd_Argv( 0 ), "devmap" ) ); // archive server state Q_strncpyz( svs.mapcmd, mapname, sizeof( svs.mapcmd ) ); }
static void testMoveEntities (void) { routing_t *routing; pos3_t pos; vec3_t vec; pathing_t *path = Mem_AllocType(pathing_t); pos_t *forbiddenList[MAX_FORBIDDENLIST]; int forbiddenListLength = 0; const byte crouchingState = 0; const int distance = MAX_ROUTE; SV_Map(qtrue, mapName, NULL); /* starting point */ VectorSet(vec, 240, -144, 32); VecToPos(vec, pos); routing = &sv->mapData.map[ACTOR_SIZE_NORMAL - 1]; G_CompleteRecalcRouting(); { edict_t *ent = NULL; while ((ent = G_EdictsGetNextInUse(ent))) { /* Dead 2x2 unit will stop walking, too. */ if (ent->type == ET_SOLID) { int j; for (j = 0; j < ent->forbiddenListSize; j++) { forbiddenList[forbiddenListLength++] = ent->forbiddenListPos[j]; forbiddenList[forbiddenListLength++] = (byte*) &ent->fieldSize; } } } } { int lengthStored; pos3_t to; Grid_MoveCalc(routing, ACTOR_SIZE_NORMAL, path, pos, crouchingState, distance, forbiddenList, forbiddenListLength); Grid_MoveStore(path); /* walk onto the func_breakable */ { VectorSet(vec, 112, -144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, qtrue); CU_ASSERT_EQUAL(lengthStored, 4 * TU_MOVE_STRAIGHT); } /* walk over the func_breakable */ { VectorSet(vec, 80, -144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, qtrue); CU_ASSERT_EQUAL(lengthStored, 5 * TU_MOVE_STRAIGHT); } /* walk over the func_breakable */ { VectorSet(vec, 16, -144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, qtrue); CU_ASSERT_EQUAL(lengthStored, 7 * TU_MOVE_STRAIGHT); } } /* starting point */ VectorSet(vec, 144, 144, 32); VecToPos(vec, pos); { int lengthStored; pos3_t to; Grid_MoveCalc(routing, ACTOR_SIZE_NORMAL, path, pos, crouchingState, distance, forbiddenList, forbiddenListLength); Grid_MoveStore(path); /* walk through the opened door */ { VectorSet(vec, 112, 144, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, qtrue); CU_ASSERT_EQUAL(lengthStored, TU_MOVE_STRAIGHT); } /* walk around the opened door */ { VectorSet(vec, 144, 208, 32); VecToPos(vec, to); lengthStored = Grid_MoveLength(path, to, crouchingState, qtrue); CU_ASSERT_EQUAL(lengthStored, 2 * TU_MOVE_STRAIGHT + TU_MOVE_DIAGONAL); } } SV_ShutdownGameProgs(); }