00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032
00033
00034
00035
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039
00040 #include "stratagus.h"
00041 #include "map.h"
00042 #include "minimap.h"
00043 #include "player.h"
00044 #include "unit.h"
00045 #include "unittype.h"
00046 #include "upgrade.h"
00047 #include "pathfinder.h"
00048 #include "ui.h"
00049 #include "font.h"
00050 #include "sound.h"
00051 #include "sound_server.h"
00052 #include "interface.h"
00053 #include "cursor.h"
00054 #include "spells.h"
00055 #include "construct.h"
00056 #include "actions.h"
00057 #include "network.h"
00058 #include "netconnect.h"
00059 #include "missile.h"
00060 #include "settings.h"
00061 #include "results.h"
00062 #include "trigger.h"
00063 #include "replay.h"
00064 #include "iolib.h"
00065 #include "iocompat.h"
00066
00067 #include "script.h"
00068
00069
00070
00071
00072
00073 Settings GameSettings;
00074 static int LcmPreventRecurse;
00075 GameResults GameResult;
00076
00077
00078
00079
00080
00081
00082
00083
00084
00092 static void LoadStratagusMap(const std::string &smpname, const std::string &mapname, CMap *map)
00093 {
00094 char mapfull[PATH_MAX];
00095 CFile file;
00096
00097
00098 strcpy_s(mapfull, sizeof(mapfull), smpname.c_str());
00099 char *p = strrchr(mapfull, '/');
00100 if (!p) {
00101 p = mapfull;
00102 } else {
00103 ++p;
00104 }
00105 strcpy_s(p, sizeof(mapfull) - (p - mapfull), mapname.c_str());
00106
00107 if (file.open(mapfull, CL_OPEN_READ) == -1) {
00108
00109 strcpy_s(mapfull, sizeof(mapfull), StratagusLibPath.c_str());
00110 strcat_s(mapfull, sizeof(mapfull), "/");
00111 strcat_s(mapfull, sizeof(mapfull), smpname.c_str());
00112 char *p = strrchr(mapfull, '/');
00113 if (!p) {
00114 p = mapfull;
00115 } else {
00116 ++p;
00117 }
00118 strcpy_s(p, sizeof(mapfull) - (p - mapfull), mapname.c_str());
00119 if (file.open(mapfull, CL_OPEN_READ) == -1) {
00120
00121 strcpy_s(mapfull, sizeof(mapfull), StratagusLibPath.c_str());
00122 strcat_s(mapfull, sizeof(mapfull), "/");
00123 strcat_s(mapfull, sizeof(mapfull), mapname.c_str());
00124 if (file.open(mapfull, CL_OPEN_READ) == -1) {
00125
00126 strcpy_s(mapfull, sizeof(mapfull), mapname.c_str());
00127 } else {
00128 file.close();
00129 }
00130 } else {
00131 file.close();
00132 }
00133 } else {
00134 file.close();
00135 }
00136
00137 if (LcmPreventRecurse) {
00138 fprintf(stderr, "recursive use of load map!\n");
00139 ExitFatal(-1);
00140 }
00141 InitPlayers();
00142 LcmPreventRecurse = 1;
00143 if (LuaLoadFile(mapfull) == -1) {
00144 fprintf(stderr, "Can't load lua file: %s\n", mapfull);
00145 ExitFatal(-1);
00146 }
00147 LcmPreventRecurse = 0;
00148
00149 #if 0
00150
00151 if (!ThisPlayer) {
00152 fprintf(stderr, "%s: invalid map\n", mapname.c_str());
00153 ExitFatal(-1);
00154 }
00155 #endif
00156 if (!Map.Info.MapWidth || !Map.Info.MapHeight) {
00157 fprintf(stderr, "%s: invalid map\n", mapname.c_str());
00158 ExitFatal(-1);
00159 }
00160 Map.Info.Filename = mapname;
00161 }
00162
00163
00164
00165 static int WriteMapPresentation(const std::string &mapname, CMap *map)
00166 {
00167 FileWriter *f = NULL;
00168 int i;
00169 int topplayer;
00170 int numplayers;
00171 const char *type[] = {"", "", "neutral", "nobody",
00172 "computer", "person", "rescue-passive", "rescue-active"};
00173
00174 numplayers = 0;
00175 topplayer = PlayerMax - 2;
00176
00177 try {
00178 f = CreateFileWriter(mapname);
00179 f->printf("-- Stratagus Map Presentation\n");
00180 f->printf("-- File generated by the stratagus builtin editor.\n");
00181
00182 f->printf("-- File licensed under the GNU GPL version 2.\n\n");
00183
00184 f->printf("DefinePlayerTypes(");
00185 while (topplayer > 0 && map->Info.PlayerType[topplayer] == PlayerNobody) {
00186 --topplayer;
00187 }
00188 for (i = 0; i <= topplayer; ++i) {
00189 f->printf("%s\"%s\"", (i ? ", " : ""), type[map->Info.PlayerType[i]]);
00190 if (map->Info.PlayerType[i] == PlayerPerson) {
00191 ++numplayers;
00192 }
00193 }
00194 f->printf(")\n");
00195
00196 f->printf("PresentMap(\"%s\", %d, %d, %d, %d)\n",
00197 map->Info.Description.c_str(), numplayers, map->Info.MapWidth, map->Info.MapHeight,
00198 map->Info.MapUID + 1);
00199
00200 f->printf("DefineMapSetup(GetCurrentLuaPath()..\"/setup.sms\")\n");
00201 } catch (const FileException &) {
00202 fprintf(stderr, "ERROR: cannot write the map presentation\n");
00203 delete f;
00204 return -1;
00205 }
00206 delete f;
00207
00208 return 1;
00209 }
00210
00211
00218 int WriteMapSetup(const char *mapSetup, CMap *map)
00219 {
00220 FileWriter *f = NULL;
00221 int i;
00222
00223 try {
00224 f = CreateFileWriter(mapSetup);
00225
00226 f->printf("-- Stratagus Map Setup\n");
00227 f->printf("-- File generated by the stratagus builtin editor.\n");
00228
00229 f->printf("-- File licensed under the GNU GPL version 2.\n\n");
00230
00231 f->printf("-- player configuration\n");
00232 for (i = 0; i < PlayerMax - 1; ++i) {
00233 f->printf("Players[%d]:SetStartView(%d, %d)\n", i, Players[i].StartX, Players[i].StartY);
00234 f->printf("Players[%d].EnergyStored = %d\n", i, Players[i].GetEnergyStored());
00235 f->printf("Players[%d].MagmaStored = %d\n", i, Players[i].GetMagmaStored());
00236 f->printf("Players[%d].AiName = \"%s\"\n", i, Players[i].AiName.c_str());
00237 }
00238 f->printf("\n");
00239
00240 f->printf("-- patches\n");
00241 f->printf("%s", Map.PatchManager.savePatches(true).c_str());
00242 f->printf("\n");
00243
00244 f->printf("-- place units\n");
00245 for (i = 0; i < NumUnits; ++i) {
00246 f->printf("CreateUnit(\"%s\", ", Units[i]->Type->Ident.c_str());
00247 if (Units[i]->Player->Index == PlayerMax - 1) {
00248 f->printf("PlayerNumNeutral");
00249 } else {
00250 f->printf("%d", Units[i]->Player->Index);
00251 }
00252 f->printf(", {%d, %d})\n", Units[i]->X, Units[i]->Y);
00253 }
00254 f->printf("\n\n");
00255 } catch (const FileException &) {
00256 fprintf(stderr,"Can't save map setup: `%s' \n", mapSetup);
00257 delete f;
00258 return -1;
00259 }
00260 delete f;
00261
00262 return 1;
00263 }
00264
00265
00266
00273 int SaveStratagusMap(const std::string &mapName, CMap *map)
00274 {
00275 std::string mapPresentation;
00276 std::string mapSetup;
00277
00278 if (!map->Info.MapWidth || !map->Info.MapHeight) {
00279 fprintf(stderr, "%s: invalid Bos Wars map\n", mapName.c_str());
00280 ExitFatal(-1);
00281 }
00282
00283 if (mapName.find(".map") == std::string::npos) {
00284 fprintf(stderr, "%s: invalid Bos Wars map filename\n", mapName.c_str());
00285 }
00286
00287 makedir(mapName.c_str(), 0777);
00288 mapPresentation = mapName + std::string("/presentation.smp");
00289 mapSetup = mapName + std::string("/setup.sms");
00290 if (WriteMapPresentation(mapPresentation, map) == -1) {
00291 return -1;
00292 }
00293
00294 return WriteMapSetup(mapSetup.c_str(), map);
00295 }
00296
00297
00304 static void LoadMap(const std::string &filename, CMap *map)
00305 {
00306 const char *tmp;
00307 const char *name = filename.c_str();
00308
00309 tmp = strrchr(name, '.');
00310 if (tmp) {
00311 if (!strcmp(tmp, ".gz")) {
00312 while (tmp - 1 > name && *--tmp != '.') {
00313 }
00314 }
00315 if (!strcmp(tmp, ".smp") || !strcmp(tmp, ".smp.gz")) {
00316 if (map->Info.Filename.empty()) {
00317
00318 LoadStratagusMapInfo(filename);
00319 }
00320 Assert(!map->Info.Filename.empty());
00321 map->Create();
00322 LoadStratagusMap(filename, map->Info.Filename.c_str(), map);
00323 return;
00324 }
00325 }
00326
00327 fprintf(stderr, "Unrecognized map format\n");
00328 ExitFatal(-1);
00329 }
00330
00336 void SetGamePaused(bool paused)
00337 {
00338 GamePaused = paused;
00339 }
00340
00346 bool GetGamePaused()
00347 {
00348 return GamePaused;
00349 }
00350
00356 void SetGameSpeed(int speed)
00357 {
00358 if (GameCycle == 0 || FastForwardCycle < GameCycle) {
00359 VideoSyncSpeed = speed * 100 / CYCLES_PER_SECOND;
00360 SetVideoSync();
00361 }
00362 }
00363
00369 int GetGameSpeed()
00370 {
00371 return CYCLES_PER_SECOND * VideoSyncSpeed / 100;
00372 }
00373
00374
00375
00376
00377
00381 static void GameTypeFreeForAll(void)
00382 {
00383 int i;
00384 int j;
00385
00386 for (i = 0; i < PlayerMax - 1; ++i) {
00387 for (j = 0; j < PlayerMax - 1; ++j) {
00388 if (i != j) {
00389 CommandDiplomacy(i, DiplomacyEnemy, j);
00390 }
00391 }
00392 }
00393 }
00394
00398 static void GameTypeTopVsBottom(void)
00399 {
00400 int i;
00401 int j;
00402 int top;
00403 int middle;
00404
00405 middle = Map.Info.MapHeight / 2;
00406 for (i = 0; i < PlayerMax - 1; ++i) {
00407 top = Players[i].StartY <= middle;
00408 for (j = 0; j < PlayerMax - 1; ++j) {
00409 if (i != j) {
00410 if ((top && Players[j].StartY <= middle) ||
00411 (!top && Players[j].StartY > middle)) {
00412 CommandDiplomacy(i, DiplomacyAllied, j);
00413 Players[i].SharedVision |= (1 << j);
00414 } else {
00415 CommandDiplomacy(i, DiplomacyEnemy, j);
00416 }
00417 }
00418 }
00419 }
00420 }
00421
00425 static void GameTypeLeftVsRight(void)
00426 {
00427 int i;
00428 int j;
00429 int left;
00430 int middle;
00431
00432 middle = Map.Info.MapWidth / 2;
00433 for (i = 0; i < PlayerMax - 1; ++i) {
00434 left = Players[i].StartX <= middle;
00435 for (j = 0; j < PlayerMax - 1; ++j) {
00436 if (i != j) {
00437 if ((left && Players[j].StartX <= middle) ||
00438 (!left && Players[j].StartX > middle)) {
00439 CommandDiplomacy(i, DiplomacyAllied, j);
00440 Players[i].SharedVision |= (1 << j);
00441 } else {
00442 CommandDiplomacy(i, DiplomacyEnemy, j);
00443 }
00444 }
00445 }
00446 }
00447 }
00448
00452 static void GameTypeManVsMachine(void)
00453 {
00454 int i;
00455 int j;
00456
00457 for (i = 0; i < PlayerMax - 1; ++i) {
00458 if (Players[i].Type != PlayerPerson && Players[i].Type != PlayerComputer) {
00459 continue;
00460 }
00461 for (j = 0; j < PlayerMax - 1; ++j) {
00462 if (i != j) {
00463 if (Players[i].Type == Players[j].Type) {
00464 CommandDiplomacy(i, DiplomacyAllied, j);
00465 Players[i].SharedVision |= (1 << j);
00466 } else {
00467 CommandDiplomacy(i, DiplomacyEnemy, j);
00468 }
00469 }
00470 }
00471 }
00472 }
00473
00477 static void GameTypeManTeamVsMachine(void)
00478 {
00479 int i;
00480 int j;
00481
00482 for (i = 0; i < PlayerMax - 1; ++i) {
00483 if (Players[i].Type != PlayerPerson && Players[i].Type != PlayerComputer) {
00484 continue;
00485 }
00486 for (j = 0; j < PlayerMax - 1; ++j) {
00487 if (i != j) {
00488 if (Players[i].Type == Players[j].Type) {
00489 CommandDiplomacy(i, DiplomacyAllied, j);
00490 Players[i].SharedVision |= (1 << j);
00491 } else {
00492 CommandDiplomacy(i, DiplomacyEnemy, j);
00493 }
00494 }
00495 }
00496 if (Players[i].Type == PlayerPerson) {
00497 Players[i].Team = 2;
00498 } else {
00499 Players[i].Team = 1;
00500 }
00501 }
00502 }
00503
00504
00505
00506
00507
00518 void CreateGame(const std::string &filename, CMap *map)
00519 {
00520 int i;
00521
00522 if (SaveGameLoading) {
00523 SaveGameLoading = false;
00524
00525 CommandLog(NULL, NoUnitP, FlushCommands, -1, -1, NoUnitP, NULL, -1);
00526 return;
00527 }
00528
00529 InitVisionTable();
00530 InitPlayers();
00531
00532 if (Map.Info.Filename.empty() && !filename.empty()) {
00533 char path[PATH_MAX];
00534
00535 LibraryFileName(filename.c_str(), path, sizeof(path));
00536 if (strcasestr(filename.c_str(), ".smp")) {
00537 LuaLoadFile(path);
00538 }
00539 }
00540
00541 for (i = 0; i < PlayerMax; ++i) {
00542 int playertype = Map.Info.PlayerType[i];
00543
00544 if (GameSettings.Presets[i].Type != SettingsPresetMapDefault) {
00545 playertype = GameSettings.Presets[i].Type;
00546 }
00547 CreatePlayer(playertype);
00548 }
00549
00550 if (!filename.empty()) {
00551 if (CurrentMapPath != filename) {
00552 strcpy_s(CurrentMapPath, sizeof(CurrentMapPath), filename.c_str());
00553 }
00554
00555
00556
00557
00558 InitUnitTypes(1);
00559 LoadMap(filename, map);
00560 }
00561
00562 GameCycle = 0;
00563 FastForwardCycle = 0;
00564 SyncHash = 0;
00565 InitSyncRand();
00566
00567 if (IsNetworkGame()) {
00568 DebugPrint("Client setup: Calling InitNetwork2\n");
00569 InitNetwork2();
00570 } else {
00571 if (!LocalPlayerName.empty() && LocalPlayerName != "Anonymous") {
00572 ThisPlayer->SetName(LocalPlayerName);
00573 }
00574 }
00575
00576 CallbackMusicOn();
00577
00578 #if 0
00579 GamePaused = true;
00580 #endif
00581
00582 if (FlagRevealMap) {
00583 Map.Reveal();
00584 }
00585
00586
00587
00588
00589 if (GameSettings.GameType != SettingsGameTypeMapDefault) {
00590 switch (GameSettings.GameType) {
00591 case SettingsGameTypeMelee:
00592 break;
00593 case SettingsGameTypeFreeForAll:
00594 GameTypeFreeForAll();
00595 break;
00596 case SettingsGameTypeTopVsBottom:
00597 GameTypeTopVsBottom();
00598 break;
00599 case SettingsGameTypeLeftVsRight:
00600 GameTypeLeftVsRight();
00601 break;
00602 case SettingsGameTypeManVsMachine:
00603 GameTypeManVsMachine();
00604 break;
00605 case SettingsGameTypeManTeamVsMachine:
00606 GameTypeManTeamVsMachine();
00607 }
00608 }
00609
00610
00611
00612
00613 SetPlayersPalette();
00614 InitIcons();
00615 LoadIcons();
00616
00617 LoadCursors();
00618 UnitUnderCursor = NoUnitP;
00619
00620 InitMissileTypes();
00621 LoadMissileSprites();
00622 InitConstructions();
00623 LoadConstructions();
00624 LoadUnitTypes();
00625 LoadDecorations();
00626
00627 InitSelections();
00628
00629 InitUserInterface();
00630 UI.Load();
00631
00632 Map.Init();
00633 UI.Minimap.Create();
00634
00635
00636
00637
00638 LoadUnitSounds();
00639 MapUnitSounds();
00640 if (SoundEnabled()) {
00641 InitSoundClient();
00642 }
00643
00644
00645
00646
00647 InitSpells();
00648
00649
00650
00651
00652 InitGroups();
00653
00654
00655
00656
00657 DebugPlayers();
00658 PlayersInitAi();
00659
00660
00661
00662
00663 InitButtons();
00664
00665
00666
00667
00668 InitTriggers();
00669
00670 SetDefaultTextColors(UI.NormalFontColor, UI.ReverseFontColor);
00671
00672 #if 0
00673 if (!UI.SelectedViewport) {
00674 UI.SelectedViewport = UI.Viewports;
00675 }
00676 #endif
00677 UI.SelectedViewport->Center(
00678 ThisPlayer->StartX, ThisPlayer->StartY, TileSizeX / 2, TileSizeY / 2);
00679
00680
00681
00682
00683
00684 InitPathfinder();
00685
00686
00687
00688
00689 for (i = 0; i < NumUnits; ++i) {
00690
00691
00692 if (Units[i]->RescuedFrom) {
00693 Units[i]->Colors = &Units[i]->RescuedFrom->UnitColors;
00694 } else {
00695 Units[i]->Colors = &Units[i]->Player->UnitColors;
00696 }
00697 }
00698
00699 GameResult = GameNoResult;
00700
00701 CommandLog(NULL, NoUnitP, FlushCommands, -1, -1, NoUnitP, NULL, -1);
00702 Video.ClearScreen();
00703 }
00704
00710 void InitSettings(void)
00711 {
00712 for (int i = 0; i < PlayerMax; ++i) {
00713 GameSettings.Presets[i].Team = SettingsPresetMapDefault;
00714 GameSettings.Presets[i].Type = SettingsPresetMapDefault;
00715 }
00716 GameSettings.Resources = SettingsPresetMapDefault;
00717 GameSettings.NumUnits = SettingsPresetMapDefault;
00718 GameSettings.Opponents = SettingsPresetMapDefault;
00719 GameSettings.Difficulty = SettingsPresetMapDefault;
00720 GameSettings.GameType = SettingsPresetMapDefault;
00721 GameSettings.MapRichness = SettingsPresetMapDefault;
00722 GameSettings.NetGameType = SettingsSinglePlayerGame;
00723 }
00724