void GrafxMakeRandomBackground( GraphicsDevice *device, CampaignOptions *co, struct MissionOptions *mo, Map *map) { HSV tint; CampaignSettingInit(&co->Setting); ActorsInit(); ObjsInit(); MobObjsInit(); SetupQuickPlayCampaign(&co->Setting, &gConfig.QuickPlay); co->seed = rand(); tint.h = rand() * 360.0 / RAND_MAX; tint.s = rand() * 1.0 / RAND_MAX; tint.v = 0.5; DrawBuffer buffer; DrawBufferInit(&buffer, Vec2iNew(X_TILES, Y_TILES), device); co->MissionIndex = 0; GrafxMakeBackground( device, &buffer, co, mo, map, tint, 0, 1, Vec2iCenterOfTile(Vec2iScaleDiv(map->Size, 2)), NULL); DrawBufferTerminate(&buffer); ActorsTerminate(); ObjsTerminate(); MobObjsTerminate(); RemoveAllWatches(); MissionOptionsTerminate(mo); CampaignSettingTerminate(&co->Setting); co->seed = gConfig.Game.RandomSeed; }
void GrafxMakeRandomBackground( GraphicsDevice *device, CampaignOptions *co, struct MissionOptions *mo, Map *map) { CampaignSettingInit(&co->Setting); SetupQuickPlayCampaign(&co->Setting); const HSV tint = { rand() * 360.0 / RAND_MAX, rand() * 1.0 / RAND_MAX, 0.5 }; DrawBuffer buffer; DrawBufferInit(&buffer, svec2i(X_TILES, Y_TILES), device); co->MissionIndex = 0; GrafxMakeBackground( device, &buffer, co, mo, map, tint, false, svec2_zero(), NULL); DrawBufferTerminate(&buffer); MissionOptionsTerminate(mo); CampaignSettingTerminate(&co->Setting); }
static void Setup(int buildTables) { Mission *m = CampaignGetCurrentMission(&gCampaign); if (!m) { return; } MissionCopy(&lastMission, ¤tMission); MissionCopy(¤tMission, m); MissionOptionsTerminate(&gMission); CampaignAndMissionSetup(buildTables, &gCampaign, &gMission); MakeBackground(&gGraphicsDevice, buildTables); sCursorTile = TileNone(); Autosave(); sJustLoaded = true; sHasUnbakedChanges = false; }
int main(int argc, char *argv[]) { int wait = 0; int controllerFlag = SDL_INIT_GAMECONTROLLER; credits_displayer_t creditsDisplayer; memset(&creditsDisplayer, 0, sizeof creditsDisplayer); custom_campaigns_t campaigns; memset(&campaigns, 0, sizeof campaigns); int forceResolution = 0; int err = 0; const char *loadCampaign = NULL; ENetAddress connectAddr; memset(&connectAddr, 0, sizeof connectAddr); srand((unsigned int)time(NULL)); LogInit(); PrintTitle(); if (getenv("DEBUG") != NULL) { debug = true; char *dbg; if ((dbg = getenv("DEBUG_LEVEL")) != NULL) { debug_level = CLAMP(atoi(dbg), D_NORMAL, D_MAX); } } SetupConfigDir(); gConfig = ConfigLoad(GetConfigFilePath(CONFIG_FILE)); LoadCredits(&creditsDisplayer, colorPurple, colorDarker); AutosaveInit(&gAutosave); AutosaveLoad(&gAutosave, GetConfigFilePath(AUTOSAVE_FILE)); if (enet_initialize() != 0) { LOG(LM_MAIN, LL_ERROR, "An error occurred while initializing ENet."); err = EXIT_FAILURE; goto bail; } NetClientInit(&gNetClient); // Print command line char buf[CDOGS_PATH_MAX]; buf[0] = '\0'; for (int i = 0; i < argc; i++) { strcat(buf, " "); // HACK: for OS X, blank out the -psn_XXXX argument so that it doesn't // break arg parsing #ifdef __APPLE__ if (strncmp(argv[i], "-psn", strlen("-psn")) == 0) { argv[i] = ""; } #endif strcat(buf, argv[i]); } LOG(LM_MAIN, LL_INFO, "Command line (%d args):%s", argc, buf); { struct option longopts[] = { {"fullscreen", no_argument, NULL, 'f'}, {"scale", required_argument, NULL, 's'}, {"screen", required_argument, NULL, 'c'}, {"forcemode", no_argument, NULL, 'o'}, {"nosound", no_argument, NULL, 'n'}, {"nojoystick", no_argument, NULL, 'j'}, {"wait", no_argument, NULL, 'w'}, {"shakemult", required_argument, NULL, 'm'}, {"connect", required_argument, NULL, 'x'}, {"debug", required_argument, NULL, 'd'}, {"log", required_argument, NULL, 1000}, {"help", no_argument, NULL, 'h'}, {0, 0, NULL, 0} }; int opt = 0; int idx = 0; while ((opt = getopt_long(argc, argv, "fs:c:onjwm:xd\0h", longopts, &idx)) != -1) { switch (opt) { case 'f': ConfigGet(&gConfig, "Graphics.Fullscreen")->u.Bool.Value = true; break; case 's': ConfigSetInt(&gConfig, "Graphics.ScaleFactor", atoi(optarg)); break; case 'c': sscanf(optarg, "%dx%d", &ConfigGet(&gConfig, "Graphics.ResolutionWidth")->u.Int.Value, &ConfigGet(&gConfig, "Graphics.ResolutionHeight")->u.Int.Value); LOG(LM_MAIN, LL_DEBUG, "Video mode %dx%d set...", ConfigGetInt(&gConfig, "Graphics.ResolutionWidth"), ConfigGetInt(&gConfig, "Graphics.ResolutionHeight")); break; case 'o': forceResolution = 1; break; case 'n': LOG(LM_MAIN, LL_INFO, "Sound to 0 volume"); ConfigGet(&gConfig, "Sound.SoundVolume")->u.Int.Value = 0; ConfigGet(&gConfig, "Sound.MusicVolume")->u.Int.Value = 0; break; case 'j': debug(D_NORMAL, "nojoystick\n"); controllerFlag = 0; break; case 'w': wait = 1; break; case 'm': { ConfigGet(&gConfig, "Graphics.ShakeMultiplier")->u.Int.Value = MAX(atoi(optarg), 0); printf("Shake multiplier: %d\n", ConfigGetInt(&gConfig, "Graphics.ShakeMultiplier")); } break; case 'h': PrintHelp(); goto bail; case 'd': // Set debug level debug = true; debug_level = CLAMP(atoi(optarg), D_NORMAL, D_MAX); break; case 1000: { char *comma = strchr(optarg, ','); if (comma) { // Set logging level for a single module // The module and level are comma separated *comma = '\0'; const LogLevel ll = StrLogLevel(comma + 1); LogModuleSetLevel(StrLogModule(optarg), ll); printf("Logging %s at %s\n", optarg, LogLevelName(ll)); } else { // Set logging level for all modules const LogLevel ll = StrLogLevel(optarg); for (int i = 0; i < (int)LM_COUNT; i++) { LogModuleSetLevel((LogModule)i, ll); } printf("Logging everything at %s\n", LogLevelName(ll)); } } break; case 'x': if (enet_address_set_host(&connectAddr, optarg) != 0) { printf("Error: unknown host %s\n", optarg); } break; default: PrintHelp(); // Ignore unknown arguments break; } } if (optind < argc) { // non-option ARGV-elements for (; optind < argc; optind++) { // Load campaign loadCampaign = argv[optind]; } } } debug(D_NORMAL, "Initialising SDL...\n"); const int sdlFlags = SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_HAPTIC; if (SDL_Init(sdlFlags | controllerFlag) != 0) { LOG(LM_MAIN, LL_ERROR, "Could not initialise SDL: %s", SDL_GetError()); err = EXIT_FAILURE; goto bail; } if (SDLJBN_Init() != 0) { LOG(LM_MAIN, LL_ERROR, "Could not initialise SDLJBN: %s", SDLJBN_GetError()); err = EXIT_FAILURE; goto bail; } SDL_EventState(SDL_DROPFILE, SDL_DISABLE); GetDataFilePath(buf, ""); LOG(LM_MAIN, LL_INFO, "data dir(%s)", buf); LOG(LM_MAIN, LL_INFO, "config dir(%s)", GetConfigFilePath("")); SoundInitialize(&gSoundDevice, "sounds"); if (!gSoundDevice.isInitialised) { LOG(LM_MAIN, LL_ERROR, "Sound initialization failed!"); } LoadHighScores(); debug(D_NORMAL, "Loading song lists...\n"); LoadSongs(); MusicPlayMenu(&gSoundDevice); EventInit(&gEventHandlers, NULL, NULL, true); NetServerInit(&gNetServer); if (wait) { printf("Press the enter key to continue...\n"); getchar(); } if (!PicManagerTryInit( &gPicManager, "graphics/cdogs.px", "graphics/cdogs2.px")) { LOG(LM_MAIN, LL_ERROR, "Failed to initialize graphics"); err = EXIT_FAILURE; goto bail; } memcpy(origPalette, gPicManager.palette, sizeof(origPalette)); GraphicsInit(&gGraphicsDevice, &gConfig); GraphicsInitialize(&gGraphicsDevice, forceResolution); if (!gGraphicsDevice.IsInitialized) { LOG(LM_MAIN, LL_WARN, "Cannot initialise video; trying default config"); ConfigResetDefault(ConfigGet(&gConfig, "Graphics")); GraphicsInit(&gGraphicsDevice, &gConfig); GraphicsInitialize(&gGraphicsDevice, forceResolution); } if (!gGraphicsDevice.IsInitialized) { LOG(LM_MAIN, LL_ERROR, "Video didn't init!"); err = EXIT_FAILURE; goto bail; } FontLoadFromJSON(&gFont, "graphics/font.png", "graphics/font.json"); PicManagerLoadDir(&gPicManager, "graphics"); ParticleClassesInit(&gParticleClasses, "data/particles.json"); AmmoInitialize(&gAmmo, "data/ammo.json"); BulletAndWeaponInitialize( &gBulletClasses, &gGunDescriptions, "data/bullets.json", "data/guns.json"); CharacterClassesInitialize(&gCharacterClasses, "data/character_classes.json"); LoadPlayerTemplates( &gPlayerTemplates, &gCharacterClasses, PLAYER_TEMPLATE_FILE); PickupClassesInit( &gPickupClasses, "data/pickups.json", &gAmmo, &gGunDescriptions); MapObjectsInit(&gMapObjects, "data/map_objects.json"); CollisionSystemInit(&gCollisionSystem); CampaignInit(&gCampaign); LoadAllCampaigns(&campaigns); PlayerDataInit(&gPlayerDatas); GrafxMakeRandomBackground( &gGraphicsDevice, &gCampaign, &gMission, &gMap); debug(D_NORMAL, ">> Entering main loop\n"); // Attempt to pre-load campaign if requested if (loadCampaign != NULL) { LOG(LM_MAIN, LL_INFO, "Loading campaign %s...", loadCampaign); gCampaign.Entry.Mode = strstr(loadCampaign, "/" CDOGS_DOGFIGHT_DIR "/") != NULL ? GAME_MODE_DOGFIGHT : GAME_MODE_NORMAL; CampaignEntry entry; if (!CampaignEntryTryLoad(&entry, loadCampaign, GAME_MODE_NORMAL) || !CampaignLoad(&gCampaign, &entry)) { LOG(LM_MAIN, LL_ERROR, "Failed to load campaign %s", loadCampaign); } } else if (connectAddr.host != 0) { if (NetClientTryScanAndConnect(&gNetClient, connectAddr.host)) { ScreenWaitForCampaignDef(); } else { printf("Failed to connect\n"); } } LOG(LM_MAIN, LL_INFO, "Starting game"); MainLoop(&creditsDisplayer, &campaigns); bail: debug(D_NORMAL, ">> Shutting down...\n"); MapTerminate(&gMap); PlayerDataTerminate(&gPlayerDatas); MapObjectsTerminate(&gMapObjects); PickupClassesTerminate(&gPickupClasses); ParticleClassesTerminate(&gParticleClasses); AmmoTerminate(&gAmmo); WeaponTerminate(&gGunDescriptions); BulletTerminate(&gBulletClasses); CharacterClassesTerminate(&gCharacterClasses); MissionOptionsTerminate(&gMission); NetClientTerminate(&gNetClient); atexit(enet_deinitialize); EventTerminate(&gEventHandlers); GraphicsTerminate(&gGraphicsDevice); PicManagerTerminate(&gPicManager); FontTerminate(&gFont); AutosaveSave(&gAutosave, GetConfigFilePath(AUTOSAVE_FILE)); AutosaveTerminate(&gAutosave); ConfigSave(&gConfig, GetConfigFilePath(CONFIG_FILE)); SavePlayerTemplates(&gPlayerTemplates, PLAYER_TEMPLATE_FILE); CArrayTerminate(&gPlayerTemplates); FreeSongs(&gMenuSongs); FreeSongs(&gGameSongs); SaveHighScores(); UnloadCredits(&creditsDisplayer); UnloadAllCampaigns(&campaigns); CampaignTerminate(&gCampaign); SoundTerminate(&gSoundDevice, true); ConfigDestroy(&gConfig); SDLJBN_Quit(); SDL_Quit(); return err; }
static void Campaign(GraphicsDevice *graphics, CampaignOptions *co) { if (IsPasswordAllowed(co->Entry.Mode)) { MissionSave m; AutosaveLoadMission( &gAutosave, &m, co->Entry.Path, co->Entry.BuiltinIndex); co->MissionIndex = EnterPassword(graphics, &m); } else { co->MissionIndex = 0; } bool run = false; bool gameOver = true; do { CampaignAndMissionSetup(1, co, &gMission); if (IsGameOptionsNeeded(gCampaign.Entry.Mode)) { debug(D_NORMAL, ">> Game options\n"); if (!GameOptions(gCampaign.Entry.Mode)) { run = false; goto bail; } gCampaign.OptionsSet = true; } // Mission briefing if (IsMissionBriefingNeeded(co->Entry.Mode)) { if (!ScreenMissionBriefing(&gMission)) { run = false; goto bail; } } // Equip guns if (!PlayerEquip()) { run = false; goto bail; } // Initialise before waiting for game start; // server will send us messages GameEventsInit(&gGameEvents); if (gCampaign.IsClient) { if (!ScreenWaitForGameStart()) { run = false; goto bail; } } MapLoad(&gMap, &gMission, co); // Seed random if PVP mode (otherwise players will always spawn in same // position) if (IsPVP(co->Entry.Mode)) { srand((unsigned int)time(NULL)); } if (!gCampaign.IsClient) { MapLoadDynamic(&gMap, &gMission, &co->Setting.characters); // Note: place players first, // as bad guys are placed away from players StartPlayers(ModeMaxHealth(co->Entry.Mode), co->MissionIndex); AddAndPlacePlayers(); if (!IsPVP(co->Entry.Mode)) { InitializeBadGuys(); CreateEnemies(); } } MusicPlayGame( &gSoundDevice, gCampaign.Entry.Path, gMission.missionData->Song); run = RunGame(&gMission, &gMap); // Don't quit if all players died, that's normal for PVP modes if (IsPVP(co->Entry.Mode) && GetNumPlayers(true, false, false) == 0) { run = true; } GameEventsTerminate(&gGameEvents); const int survivingPlayers = GetNumPlayers(true, false, false); // In co-op (non-PVP) modes, at least one player must survive if (!IsPVP(co->Entry.Mode)) { gameOver = survivingPlayers == 0 || co->MissionIndex == (int)gCampaign.Setting.Missions.size - 1; } int maxScore = 0; for (int i = 0; i < (int)gPlayerDatas.size; i++) { PlayerData *p = CArrayGet(&gPlayerDatas, i); p->survived = IsPlayerAlive(p); if (IsPlayerAlive(p)) { TActor *player = CArrayGet(&gActors, p->Id); p->hp = player->health; p->RoundsWon++; maxScore = MAX(maxScore, p->RoundsWon); } } if (IsPVP(co->Entry.Mode)) { gameOver = maxScore == ModeMaxRoundsWon(co->Entry.Mode); CASSERT(maxScore <= ModeMaxRoundsWon(co->Entry.Mode), "score exceeds max rounds won"); } MissionEnd(); MusicPlayMenu(&gSoundDevice); if (run) { switch (co->Entry.Mode) { case GAME_MODE_DOGFIGHT: ScreenDogfightScores(); break; case GAME_MODE_DEATHMATCH: ScreenDeathmatchFinalScores(); break; default: ScreenMissionSummary(&gCampaign, &gMission); // Note: must use cached value because players get cleaned up // in CleanupMission() if (gameOver && survivingPlayers > 0) { ScreenVictory(&gCampaign); } break; } } // Check if any scores exceeded high scores, if we're not a PVP mode if (!IsPVP(co->Entry.Mode)) { bool allTime = false; bool todays = false; for (int i = 0; i < (int)gPlayerDatas.size; i++) { PlayerData *p = CArrayGet(&gPlayerDatas, i); if (((run && !p->survived) || gameOver) && p->IsLocal) { EnterHighScore(p); allTime |= p->allTime >= 0; todays |= p->today >= 0; } if (!p->survived) { p->totalScore = 0; p->missions = 0; } else { p->missions++; } p->lastMission = co->MissionIndex; } if (allTime) { DisplayAllTimeHighScores(graphics); } if (todays) { DisplayTodaysHighScores(graphics); } } if (!HasRounds(co->Entry.Mode)) { co->MissionIndex++; } bail: // Need to terminate the mission later as it is used in calculating scores MissionOptionsTerminate(&gMission); } while (run && !gameOver); // Final screen if (run) { switch (co->Entry.Mode) { case GAME_MODE_DOGFIGHT: ScreenDogfightFinalScores(); break; default: // no end screen break; } } }
static void Campaign(GraphicsDevice *graphics, CampaignOptions *co) { if (co->IsClient) { // If connecting to a server, we've already received the mission index // Do nothing } else if (IsPasswordAllowed(co->Entry.Mode)) { MissionSave m; AutosaveLoadMission(&gAutosave, &m, co->Entry.Path); co->MissionIndex = EnterPassword(graphics, &m); } else { co->MissionIndex = 0; } bool run = false; bool gameOver = true; do { // Unready all the players for (int i = 0; i < (int)gPlayerDatas.size; i++) { PlayerData *p = CArrayGet(&gPlayerDatas, i); p->Ready = false; } CampaignAndMissionSetup(1, co, &gMission); if (IsGameOptionsNeeded(co->Entry.Mode)) { debug(D_NORMAL, ">> Game options\n"); if (!GameOptions(co->Entry.Mode)) { run = false; goto bail; } co->OptionsSet = true; // If enabled, start net server if (!co->IsClient && ConfigGetBool(&gConfig, "StartServer")) { NetServerOpen(&gNetServer); } } // Mission briefing if (IsMissionBriefingNeeded(co->Entry.Mode)) { if (!ScreenMissionBriefing(&gMission)) { run = false; goto bail; } } // Equip guns if (!PlayerEquip()) { run = false; goto bail; } if (co->IsClient) { if (!ScreenWaitForGameStart()) { run = false; goto bail; } } run = RunGame(co, &gMission, &gMap); // Don't quit if all players died, that's normal for PVP modes if (IsPVP(co->Entry.Mode) && GetNumPlayers(PLAYER_ALIVE_OR_DYING, false, false) == 0) { run = true; } const int survivingPlayers = GetNumPlayers(PLAYER_ALIVE, false, false); // In co-op (non-PVP) modes, at least one player must survive if (!IsPVP(co->Entry.Mode)) { gameOver = survivingPlayers == 0 || co->MissionIndex == (int)gCampaign.Setting.Missions.size - 1; } int maxScore = 0; for (int i = 0; i < (int)gPlayerDatas.size; i++) { PlayerData *p = CArrayGet(&gPlayerDatas, i); p->survived = IsPlayerAlive(p); if (IsPlayerAlive(p)) { TActor *player = ActorGetByUID(p->ActorUID); p->hp = player->health; p->RoundsWon++; maxScore = MAX(maxScore, p->RoundsWon); } } if (IsPVP(co->Entry.Mode)) { gameOver = maxScore == ModeMaxRoundsWon(co->Entry.Mode); CASSERT(maxScore <= ModeMaxRoundsWon(co->Entry.Mode), "score exceeds max rounds won"); } MissionEnd(); MusicPlayMenu(&gSoundDevice); if (run) { switch (co->Entry.Mode) { case GAME_MODE_DOGFIGHT: ScreenDogfightScores(); break; case GAME_MODE_DEATHMATCH: ScreenDeathmatchFinalScores(); break; default: ScreenMissionSummary(&gCampaign, &gMission); // Note: must use cached value because players get cleaned up // in CleanupMission() if (gameOver && survivingPlayers > 0) { ScreenVictory(&gCampaign); } break; } } // Check if any scores exceeded high scores, if we're not a PVP mode if (!IsPVP(co->Entry.Mode)) { bool allTime = false; bool todays = false; for (int i = 0; i < (int)gPlayerDatas.size; i++) { PlayerData *p = CArrayGet(&gPlayerDatas, i); if (((run && !p->survived) || gameOver) && p->IsLocal) { EnterHighScore(p); allTime |= p->allTime >= 0; todays |= p->today >= 0; } if (!p->survived) { p->totalScore = 0; p->missions = 0; } else { p->missions++; } p->lastMission = co->MissionIndex; } if (allTime) { DisplayAllTimeHighScores(graphics); } if (todays) { DisplayTodaysHighScores(graphics); } } if (!HasRounds(co->Entry.Mode)) { co->MissionIndex++; } bail: // Need to terminate the mission later as it is used in calculating scores MissionOptionsTerminate(&gMission); } while (run && !gameOver); // Final screen if (run) { switch (co->Entry.Mode) { case GAME_MODE_DOGFIGHT: ScreenDogfightFinalScores(); break; default: // no end screen break; } } NetServerClose(&gNetServer); }