1 // _________ __ __
2 // / _____// |_____________ _/ |______ ____ __ __ ______
3 // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
4 // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
5 // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
6 // \/ \/ \//_____/ \/
7 // ______________________ ______________________
8 // T H E W A R B E G I N S
9 // Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name stratagus.cpp - The main file. */
12 //
13 // (c) Copyright 1998-2015 by Lutz Sammer, Francois Beerten,
14 // Jimmy Salmon, Pali Rohár and cybermind
15 //
16 // This program is free software; you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation; only version 2 of the License.
19 //
20 // This program is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 // GNU General Public License for more details.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with this program; if not, write to the Free Software
27 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 // 02111-1307, USA.
29 //
30
31 //@{
32
33 /**
34 ** @mainpage
35 **
36 ** @section Introduction Introduction
37 **
38 ** Welcome to the source code documentation of the Stratagus engine.
39 ** Extract the source documentation with doxygen (http://www.doxygen.org) tool.
40 **
41 ** Any help to improve this documention is welcome. If you didn't
42 ** understand something or you found an error or a wrong spelling
43 ** or wrong grammar please write an email (including a patch :).
44 **
45 ** @section Information Information
46 **
47 ** Visit the https://github.com/Andrettin/Wyrmgus web page for the latest news and
48 ** <A HREF="../index.html">Stratagus Info</A> for other documentation.
49 **
50 ** @section Modules Modules
51 **
52 ** This are the main modules of the Stratagus engine.
53 **
54 ** @subsection Map Map
55 **
56 ** Handles the map. A map is made from tiles.
57 **
58 ** @see map.h @see map.cpp @see tileset.h @see tileset.cpp
59 **
60 ** @subsection Unit Unit
61 **
62 ** Handles units. Units are ships, flyers, buildings, creatures,
63 ** machines.
64 **
65 ** @see unit.h @see unit.cpp @see unittype.h @see unittype.cpp
66 **
67 ** @subsection Missile Missile
68 **
69 ** Handles missiles. Missiles are all other sprites on map
70 ** which are no unit.
71 **
72 ** @see missile.h @see missile.cpp
73 **
74 ** @subsection Player Player
75 **
76 ** Handles players, all units are owned by a player. A player
77 ** could be controlled by a human or a computer.
78 **
79 ** @see player.h @see player.cpp @see ::CPlayer
80 **
81 ** @subsection Sound Sound
82 **
83 ** Handles the high and low level of the sound. There are the
84 ** background music support, voices and sound effects.
85 ** Following low level backends are supported: OSS and SDL.
86 **
87 ** @todo adpcm file format support for sound effects
88 ** @todo better separation of low and high level, assembler mixing
89 ** support.
90 ** @todo Streaming support of ogg/mp3 files.
91 **
92 ** @see sound.h @see sound.cpp
93 ** @see script_sound.cpp @see sound_id.cpp @see sound_server.cpp
94 ** @see unitsound.cpp
95 ** @see sdl_audio.cpp
96 ** @see ogg.cpp @see wav.cpp
97 **
98 ** @subsection Video Video
99 **
100 ** Handles the high and low level of the graphics.
101 ** This also contains the sprite and linedrawing routines.
102 **
103 ** See page @ref VideoModule for more information upon supported
104 ** features and video platforms.
105 **
106 ** @see video.h @see video.cpp
107 **
108 ** @subsection Network Network
109 **
110 ** Handles the high and low level of the network protocol.
111 ** The network protocol is needed for multiplayer games.
112 **
113 ** See page @ref NetworkModule for more information upon supported
114 ** features and API.
115 **
116 ** @see network.h @see network.cpp
117 **
118 ** @subsection Pathfinder Pathfinder
119 **
120 ** @see pathfinder.h @see pathfinder.cpp
121 **
122 ** @subsection AI AI
123 **
124 ** There are currently two AI's. The old one is very hardcoded,
125 ** but does things like placing buildings better than the new.
126 ** The old AI shouldn't be used. The new is very flexible, but
127 ** very basic. It includes none optimations.
128 **
129 ** See page @ref AiModule for more information upon supported
130 ** features and API.
131 **
132 ** @see ai_local.h
133 ** @see ai.h @see ai.cpp
134 **
135 ** @subsection CCL CCL
136 **
137 ** CCL is Craft Configuration Language, which is used to
138 ** configure and customize Stratagus.
139 **
140 ** @see script.h @see script.cpp
141 **
142 ** @subsection Icon Icon
143 **
144 ** @see icons.h @see icons.cpp
145 **
146 ** @subsection Editor Editor
147 **
148 ** This is the integrated editor, it shouldn't be a perfect
149 ** editor. It is used to test new features of the engine.
150 **
151 ** See page @ref EditorModule for more information upon supported
152 ** features and API.
153 **
154 ** @see editor.h @see editor.cpp
155 */
156
157 /*----------------------------------------------------------------------------
158 -- Includes
159 ----------------------------------------------------------------------------*/
160
161 #include <ctype.h>
162
163 #ifdef USE_BEOS
164 #include <fcntl.h>
165 #include <sys/types.h>
166 #include <sys/stat.h>
167
168 extern void beos_init(int argc, char **argv);
169
170 #endif
171
172 #ifdef MAC_BUNDLE
173 #define Button ButtonOSX
174 #include <Carbon/Carbon.h>
175 #undef Button
176 #endif
177
178 #include "SDL.h"
179
180 #include "stratagus.h"
181
182 #include "ai.h"
183 //Wyrmgus start
184 #include "character.h"
185 //Wyrmgus end
186 #include "editor.h"
187 #include "game.h"
188 #include "guichan.h"
189 #include "iocompat.h"
190 #include "iolib.h"
191 #include "map/map.h"
192 #include "netconnect.h"
193 #include "network.h"
194 #include "parameters.h"
195 #include "player.h"
196 #include "replay.h"
197 #include "results.h"
198 #include "settings.h"
199 #include "sound_server.h"
200 #include "time/calendar.h"
201 #include "time/timeline.h"
202 #include "title.h"
203 #include "translate.h"
204 #include "ui/interface.h"
205 #include "ui/ui.h"
206 #include "unit/unit_manager.h"
207 #include "version.h"
208 #include "video.h"
209 #include "widgets.h"
210 #include "util.h"
211
212 #include "missile.h" //for FreeBurningBuildingFrames
213
214 #ifdef USE_STACKTRACE
215 #include <stdexcept>
216 #include <stacktrace/call_stack.hpp>
217 #include <stacktrace/stack_exception.hpp>
218 #endif
219
220 #include <stdlib.h>
221 #include <stdio.h>
222
223 #ifdef USE_WIN32
224 #include <windows.h>
225 #include <dbghelp.h>
226 #endif
227
228 #ifdef USE_PHYSFS
229 #include <physfs.h>
230 #endif
231
232 #if defined(USE_WIN32) && ! defined(NO_STDIO_REDIRECT)
233 #include "windows.h"
234 #define REDIRECT_OUTPUT
235 #endif
236
237 #if defined(USE_WIN32) && ! defined(REDIRECT_OUTPUT)
238 #include "SetupConsole_win32.h"
239 #endif
240
241 #ifdef __MORPHOS__
242 unsigned long __stack = 1000000;
243 __attribute__ ((section(".text"))) UBYTE VString[] = "$VER: Wyrmsun " VERSION "\r\n";
244 #endif
245
246 /*----------------------------------------------------------------------------
247 -- Variables
248 ----------------------------------------------------------------------------*/
249
250 std::string StratagusLibPath; /// Path for data directory
251
252 /// Name, Version, Copyright
253 const char NameLine[] = NAME " v" VERSION ", " COPYRIGHT;
254
255 std::string CliMapName; /// Filename of the map given on the command line
256 std::string MenuRace;
257
258 bool EnableDebugPrint; /// if enabled, print the debug messages
259 bool EnableAssert; /// if enabled, halt on assertion failures
260 bool EnableUnitDebug; /// if enabled, a unit info dump will be created
261
262 /*============================================================================
263 == MAIN
264 ============================================================================*/
265
266 /**
267 ** Pre menu setup.
268 */
PreMenuSetup()269 void PreMenuSetup()
270 {
271 //
272 // Initial menus require some gfx.
273 //
274 SetDefaultTextColors(FontWhite, FontYellow);
275
276 LoadFonts();
277
278 InitVideoCursors();
279
280 LoadCursors();
281
282 InitSettings();
283
284 InitUserInterface();
285 UI.Load();
286 }
287
288 /**
289 ** Run the guichan main menus loop.
290 **
291 ** @return 0 for success, else exit.
292 */
MenuLoop()293 static int MenuLoop()
294 {
295 int status;
296
297 initGuichan();
298 InterfaceState = IfaceStateMenu;
299 // Clear screen
300 Video.ClearScreen();
301 Invalidate();
302
303 ButtonUnderCursor = -1;
304 OldButtonUnderCursor = -1;
305 CursorState = CursorStatePoint;
306 GameCursor = UI.Point.Cursor;
307
308 // FIXME delete this when switching to full guichan GUI
309 const std::string filename = LibraryFileName("scripts/guichan.lua");
310 status = LuaLoadFile(filename);
311
312 // We clean up later in Exit
313 return status;
314 }
315
316 //----------------------------------------------------------------------------
317
318 /**
319 ** Print headerline, copyright, ...
320 */
PrintHeader()321 static void PrintHeader()
322 {
323 std::string CompileOptions =
324 #ifdef DEBUG
325 "DEBUG "
326 #endif
327 #ifdef USE_ZLIB
328 "ZLIB "
329 #endif
330 #ifdef USE_BZ2LIB
331 "BZ2LIB "
332 #endif
333 #ifdef USE_VORBIS
334 "VORBIS "
335 #endif
336 #ifdef USE_THEORA
337 "THEORA "
338 #endif
339 #ifdef USE_FLUIDSYNTH
340 "FLUIDSYNTH "
341 #endif
342 #ifdef USE_MIKMOD
343 "MIKMOD "
344 #endif
345 #ifdef USE_MNG
346 "MNG "
347 #endif
348 #ifdef USE_OPENGL
349 "OPENGL "
350 #endif
351 #ifdef USE_GLES
352 "GLES "
353 #endif
354 #ifdef USE_WIN32
355 "WIN32 "
356 #endif
357 #ifdef USE_LINUX
358 "LINUX "
359 #endif
360 #ifdef USE_BSD
361 "BSD "
362 #endif
363 #ifdef __MORPHOS__
364 "MORPHOS "
365 #endif
366 #ifdef USE_BEOS
367 "BEOS "
368 #endif
369 #ifdef USE_MAC
370 "MAC "
371 #endif
372 #ifdef USE_X11
373 "X11 "
374 #endif
375 #ifdef USE_TOUCHSCREEN
376 "TOUCHSCREEN "
377 #endif
378 "";
379
380 fprintf(stdout,
381 "%s\n written by Lutz Sammer, Fabrice Rossi, Vladi Shabanski, Patrice Fortier,\n"
382 " Jon Gabrielson, Andreas Arens, Nehal Mistry, Jimmy Salmon, Pali Rohar,\n"
383 " cybermind, Andrettin and others.\n"
384 "\t" HOMEPAGE "\n"
385 "Compile options %s",
386 NameLine, CompileOptions.c_str());
387 }
388
PrintLicense()389 void PrintLicense()
390 {
391 printf("\n"
392 "\n"
393 "Stratagus may be copied only under the terms of the GNU General Public License\n"
394 "which may be found in the Stratagus source kit.\n"
395 "\n"
396 "DISCLAIMER:\n"
397 "This software is provided as-is. The author(s) can not be held liable for any\n"
398 "damage that might arise from the use of this software.\n"
399 "Use it at your own risk.\n"
400 "\n");
401 }
402
403
404 /**
405 ** Exit the game.
406 **
407 ** @param err Error code to pass to shell.
408 */
Exit(int err)409 void Exit(int err)
410 {
411 if (GameRunning) {
412 StopGame(GameExit);
413 return;
414 }
415
416 StopMusic();
417 QuitSound();
418 NetworkQuitGame();
419
420 ExitNetwork1();
421 CleanModules();
422 FreeBurningBuildingFrames();
423 FreeSounds();
424 FreeGraphics();
425 FreePlayerColors();
426 FreeButtonStyles();
427 FreeAllContainers();
428 freeGuichan();
429 DebugPrint("Frames %lu, Slow frames %d = %ld%%\n" _C_
430 FrameCounter _C_ SlowFrameCounter _C_
431 (SlowFrameCounter * 100) / (FrameCounter ? FrameCounter : 1));
432 lua_settop(Lua, 0);
433 lua_close(Lua);
434 DeInitVideo();
435 #ifdef USE_PHYSFS
436 if (PHYSFS_isInit()) {
437 PHYSFS_deinit();
438 }
439 #endif
440
441 fprintf(stdout, "%s", _("Thanks for playing " NAME ".\n"));
442 exit(err);
443 }
444
445 /**
446 ** Do a fatal exit.
447 ** Called on out of memory or crash.
448 **
449 ** @param err Error code to pass to shell.
450 */
ExitFatal(int err)451 void ExitFatal(int err)
452 {
453 #ifdef USE_STACKTRACE
454 throw stacktrace::stack_runtime_error((const char*)err);
455 #endif
456 exit(err);
457 }
458
459 /**
460 ** Display the usage.
461 */
Usage()462 static void Usage()
463 {
464 PrintHeader();
465 printf(
466 "\n\nUsage: %s [OPTIONS] [map.smp|map.smp.gz]\n"
467 "\t-a\t\tEnables asserts check in engine code (for debugging)\n"
468 "\t-c file.lua\tConfiguration start file (default stratagus.lua)\n"
469 "\t-d datapath\tPath to stratagus data (default current directory)\n"
470 "\t-D depth\tVideo mode depth = pixel per point\n"
471 "\t-e\t\tStart editor (instead of game)\n"
472 "\t-E file.lua\tEditor configuration start file (default editor.lua)\n"
473 "\t-F\t\tFull screen video mode\n"
474 "\t-G \"options\"\tGame options (passed to game scripts)\n"
475 "\t-h\t\tHelp shows this page\n"
476 "\t-i\t\tEnables unit info dumping into log (for debugging)\n"
477 "\t-I addr\t\tNetwork address to use\n"
478 "\t-l\t\tDisable command log\n"
479 "\t-N name\t\tName of the player\n"
480 #if defined(USE_OPENGL) || defined(USE_GLES)
481 "\t-o\t\tDo not use OpenGL or OpenGL ES 1.1\n"
482 "\t-O\t\tUse OpenGL or OpenGL ES 1.1\n"
483 #endif
484 "\t-p\t\tEnables debug messages printing in console\n"
485 "\t-P port\t\tNetwork port to use\n"
486 "\t-s sleep\tNumber of frames for the AI to sleep before it starts\n"
487 "\t-S speed\tSync speed (100 = 30 frames/s)\n"
488 "\t-u userpath\tPath where stratagus saves preferences, log and savegame\n"
489 "\t-v mode\t\tVideo mode resolution in format <xres>x<yres>\n"
490 "\t-W\t\tWindowed video mode\n"
491 #if defined(USE_OPENGL) || defined(USE_GLES)
492 "\t-x idx\t\tControls fullscreen scaling if your graphics card supports shaders.\n"\
493 "\t \t\tPass 1 for nearest-neigubour, 2 for EPX/AdvMame, 3 for HQx, 4 for SAL, 5 for SuperEagle\n"\
494 "\t \t\tYou can also use Ctrl+Alt+/ to cycle between these scaling algorithms at runtime.\n"
495 "\t \t\tPass -1 to force old-school nearest neighbour scaling without shaders\n"\
496 "\t-Z\t\tUse OpenGL to scale the screen to the viewport (retro-style). Implies -O.\n"
497 #endif
498 "map is relative to StratagusLibPath=datapath, use ./map for relative to cwd\n",
499 Parameters::Instance.applicationName.c_str());
500 }
501
502 #ifdef REDIRECT_OUTPUT
503
504 static std::string stdoutFile;
505 static std::string stderrFile;
506
CleanupOutput()507 static void CleanupOutput()
508 {
509 fclose(stdout);
510 fclose(stderr);
511
512 struct stat st;
513 if (stat(stdoutFile.c_str(), &st) == 0 && st.st_size == 0) {
514 unlink(stdoutFile.c_str());
515 }
516 if (stat(stderrFile.c_str(), &st) == 0 && st.st_size == 0) {
517 unlink(stderrFile.c_str());
518 }
519 }
520
RedirectOutput()521 static void RedirectOutput()
522 {
523 std::string path = Parameters::Instance.GetUserDirectory();
524
525 makedir(path.c_str(), 0777);
526
527 stdoutFile = path + "\\stdout.txt";
528 stderrFile = path + "\\stderr.txt";
529
530 if (!freopen(stdoutFile.c_str(), "w", stdout)) {
531 printf("freopen stdout failed");
532 }
533 if (!freopen(stderrFile.c_str(), "w", stderr)) {
534 printf("freopen stderr failed");
535 }
536 atexit(CleanupOutput);
537 }
538 #endif
539
ParseCommandLine(int argc,char ** argv,Parameters & parameters)540 void ParseCommandLine(int argc, char **argv, Parameters ¶meters)
541 {
542 for (;;) {
543 switch (getopt(argc, argv, "ac:d:D:eE:FG:hiI:lN:oOP:ps:S:u:v:Wx:Z?-")) {
544 case 'a':
545 EnableAssert = true;
546 continue;
547 case 'c':
548 parameters.luaStartFilename = optarg;
549 if (strlen(optarg) > 4 &&
550 !(strstr(optarg, ".lua") == optarg + strlen(optarg) - 4)) {
551 parameters.luaStartFilename += ".lua";
552 }
553 continue;
554 case 'd': {
555 StratagusLibPath = optarg;
556 size_t index;
557 while ((index = StratagusLibPath.find('\\')) != std::string::npos) {
558 StratagusLibPath[index] = '/';
559 }
560 continue;
561 }
562 case 'D':
563 Video.Depth = atoi(optarg);
564 continue;
565 case 'e':
566 Editor.Running = EditorCommandLine;
567 continue;
568 case 'E':
569 parameters.luaEditorStartFilename = optarg;
570 continue;
571 case 'F':
572 VideoForceFullScreen = 1;
573 Video.FullScreen = 1;
574 continue;
575 case 'G':
576 parameters.luaScriptArguments = optarg;
577 continue;
578 case 'i':
579 EnableUnitDebug = true;
580 continue;
581 case 'I':
582 CNetworkParameter::Instance.localHost = optarg;
583 continue;
584 case 'l':
585 CommandLogDisabled = true;
586 continue;
587 case 'N':
588 parameters.LocalPlayerName = optarg;
589 continue;
590 #if defined(USE_OPENGL) || defined(USE_GLES)
591 case 'o':
592 ForceUseOpenGL = 1;
593 UseOpenGL = 0;
594 if (ZoomNoResize) {
595 fprintf(stderr, "Error: -Z only works with OpenGL enabled\n");
596 Usage();
597 ExitFatal(-1);
598 }
599 continue;
600 case 'O':
601 ForceUseOpenGL = 1;
602 UseOpenGL = 1;
603 continue;
604 #endif
605 case 'P':
606 CNetworkParameter::Instance.localPort = atoi(optarg);
607 continue;
608 case 'p':
609 EnableDebugPrint = true;
610 continue;
611 case 's':
612 AiSleepCycles = atoi(optarg);
613 continue;
614 case 'S':
615 VideoSyncSpeed = atoi(optarg);
616 continue;
617 case 'u':
618 Parameters::Instance.SetUserDirectory(optarg);
619 continue;
620 case 'v': {
621 char *sep = strchr(optarg, 'x');
622 if (!sep || !*(sep + 1)) {
623 fprintf(stderr, "%s: incorrect format of video mode resolution -- '%s'\n", argv[0], optarg);
624 Usage();
625 ExitFatal(-1);
626 }
627 Video.Height = atoi(sep + 1);
628 *sep = 0;
629 Video.Width = atoi(optarg);
630 if (!Video.Height || !Video.Width) {
631 fprintf(stderr, "%s: incorrect format of video mode resolution -- '%sx%s'\n", argv[0], optarg, sep + 1);
632 Usage();
633 ExitFatal(-1);
634 }
635 #if defined(USE_OPENGL) || defined(USE_GLES)
636 if (ZoomNoResize) {
637 Video.ViewportHeight = Video.Height;
638 Video.ViewportWidth = Video.Width;
639 Video.Height = 0;
640 Video.Width = 0;
641 }
642 #endif
643 continue;
644 }
645 case 'W':
646 VideoForceFullScreen = 1;
647 Video.FullScreen = 0;
648 continue;
649 #if defined(USE_OPENGL) || defined(USE_GLES)
650 case 'x':
651 ShaderIndex = atoi(optarg) % MAX_SHADERS;
652 if (atoi(optarg) == -1) {
653 GLShaderPipelineSupported = false;
654 //Wyrmgus start
655 } else {
656 GLShaderPipelineSupported = true;
657 //Wyrmgus end
658 }
659 continue;
660 case 'Z':
661 ForceUseOpenGL = 1;
662 UseOpenGL = 1;
663 ZoomNoResize = 1;
664 Video.ViewportHeight = Video.Height;
665 Video.ViewportWidth = Video.Width;
666 Video.Height = 0;
667 Video.Width = 0;
668 continue;
669 #endif
670 case -1:
671 break;
672 case '?':
673 case 'h':
674 default:
675 Usage();
676 ExitFatal(-1);
677 }
678 break;
679 }
680
681 if (argc - optind > 1) {
682 fprintf(stderr, "too many map files. if you meant to pass game arguments, these go after '--'\n");
683 Usage();
684 ExitFatal(-1);
685 }
686
687 if (argc - optind) {
688 size_t index;
689 CliMapName = argv[optind];
690 while ((index = CliMapName.find('\\')) != std::string::npos) {
691 CliMapName[index] = '/';
692 }
693 }
694 }
695
696 #ifdef USE_WIN32
CreateDumpFile(EXCEPTION_POINTERS * ExceptionInfo)697 static LONG WINAPI CreateDumpFile(EXCEPTION_POINTERS *ExceptionInfo)
698 {
699 HANDLE hFile = CreateFile("crash.dmp", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
700 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
701 MINIDUMP_EXCEPTION_INFORMATION mei;
702 mei.ThreadId = GetCurrentThreadId();
703 mei.ClientPointers = TRUE;
704 mei.ExceptionPointers = ExceptionInfo;
705 MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mei, NULL, NULL);
706 fprintf(stderr, "" NAME " crashed!\n");
707 fprintf(stderr, "A mini dump file \"crash.dmp\" has been created in the Stratagus folder.\n");
708 fprintf(stderr, "Please send this call stack to our bug tracker: " HOMEPAGE "/issues\n");
709 fprintf(stderr, "and tell us what caused this bug to occur.\n");
710 return EXCEPTION_EXECUTE_HANDLER;
711 }
712 #endif
713
714 /**
715 ** The main program: initialise, parse options and arguments.
716 **
717 ** @param argc Number of arguments.
718 ** @param argv Vector of arguments.
719 */
stratagusMain(int argc,char ** argv)720 int stratagusMain(int argc, char **argv)
721 {
722 #ifdef USE_BEOS
723 // Parse arguments for BeOS
724 beos_init(argc, argv);
725 #endif
726 #ifdef USE_WIN32
727 SetUnhandledExceptionFilter(CreateDumpFile);
728 #endif
729 #if defined(USE_WIN32) && ! defined(REDIRECT_OUTPUT)
730 SetupConsole();
731 #endif
732 // Setup some defaults.
733 #ifndef MAC_BUNDLE
734 StratagusLibPath = ".";
735 #else
736 freopen("/tmp/stdout.txt", "w", stdout);
737 freopen("/tmp/stderr.txt", "w", stderr);
738 // Look for the specified data set inside the application bundle
739 // This should be a subdir of the Resources directory
740 CFURLRef pluginRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
741 CFSTR(MAC_BUNDLE_DATADIR), nullptr, nullptr);
742 CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef, kCFURLPOSIXPathStyle);
743 const char *pathPtr = CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding());
744 Assert(pathPtr);
745 StratagusLibPath = pathPtr;
746 #endif
747
748 #ifdef USE_PHYSFS
749 if (PHYSFS_init(argv[0])) {
750 PHYSFS_mount(PHYSFS_DATAFILE, "/", 0);
751 }
752 #endif
753
754 #ifdef USE_STACKTRACE
755 try {
756 #endif
757 Parameters ¶meters = Parameters::Instance;
758 parameters.SetDefaultValues();
759 parameters.SetLocalPlayerNameFromEnv();
760
761 #ifdef REDIRECT_OUTPUT
762 RedirectOutput();
763 #endif
764
765 if (argc > 0) {
766 parameters.applicationName = argv[0];
767 }
768
769 // FIXME: Parse options before or after scripts?
770 ParseCommandLine(argc, argv, parameters);
771 // Init the random number generator.
772 InitSyncRand();
773
774 makedir(parameters.GetUserDirectory().c_str(), 0777);
775
776 // Init Lua and register lua functions!
777 InitLua();
778 LuaRegisterModules();
779
780 // Initialise AI module
781 InitAiModule();
782
783 LoadCcl(parameters.luaStartFilename, parameters.luaScriptArguments);
784
785 PrintHeader();
786 PrintLicense();
787
788 // Setup video display
789 InitVideo();
790
791 // Setup sound card
792 if (!InitSound()) {
793 InitMusic();
794 }
795
796 #ifndef DEBUG // For debug it's better not to have:
797 srand(time(nullptr)); // Random counter = random each start
798 #endif
799
800 // Show title screens.
801 SetDefaultTextColors(FontYellow, FontWhite);
802 LoadFonts();
803 SetClipping(0, 0, Video.Width - 1, Video.Height - 1);
804 Video.ClearScreen();
805 ShowTitleScreens();
806
807 // Init player data
808 ThisPlayer = nullptr;
809 //Don't clear the Players structure as it would erase the allowed units.
810 // memset(Players, 0, sizeof(Players));
811 NumPlayers = 0;
812
813 UnitManager.Init(); // Units memory management
814 PreMenuSetup(); // Load everything needed for menus
815
816 MenuLoop();
817
818 Exit(0);
819 #ifdef USE_STACKTRACE
820 } catch (const std::exception &e) {
821 fprintf(stderr, "" NAME " crashed!\n");
822 fprintf(stderr, "Please send this call stack to our bug tracker: " HOMEPAGE "/issues\n");
823 fprintf(stderr, "and tell us what caused this bug to occur.\n");
824 fprintf(stderr, " === exception state traceback === \n");
825 fprintf(stderr, "%s", e.what());
826 exit(1);
827 }
828 #endif
829 return 0;
830 }
831
832 //Wyrmgus start
GetReverseDirection(int direction)833 int GetReverseDirection(int direction)
834 {
835 if (direction == North) {
836 return South;
837 } else if (direction == Northeast) {
838 return Southwest;
839 } else if (direction == East) {
840 return West;
841 } else if (direction == Southeast) {
842 return Northwest;
843 } else if (direction == South) {
844 return North;
845 } else if (direction == Southwest) {
846 return Northeast;
847 } else if (direction == West) {
848 return East;
849 } else if (direction == Northwest) {
850 return Southeast;
851 }
852 return -1;
853 }
854
GetDirectionNameById(int direction)855 std::string GetDirectionNameById(int direction)
856 {
857 if (direction == North) {
858 return "north";
859 } else if (direction == Northeast) {
860 return "northeast";
861 } else if (direction == East) {
862 return "east";
863 } else if (direction == Southeast) {
864 return "southeast";
865 } else if (direction == South) {
866 return "south";
867 } else if (direction == Southwest) {
868 return "southwest";
869 } else if (direction == West) {
870 return "west";
871 } else if (direction == Northwest) {
872 return "northwest";
873 }
874 return "";
875 }
876
GetDirectionIdByName(const std::string & direction)877 int GetDirectionIdByName(const std::string &direction)
878 {
879 if (direction == "north") {
880 return North;
881 } else if (direction == "northeast") {
882 return Northeast;
883 } else if (direction == "east") {
884 return East;
885 } else if (direction == "southeast") {
886 return Southeast;
887 } else if (direction == "south") {
888 return South;
889 } else if (direction == "southwest") {
890 return Southwest;
891 } else if (direction == "west") {
892 return West;
893 } else if (direction == "northwest") {
894 return Northwest;
895 } else {
896 return -1;
897 }
898 }
899
GetDirectionFromOffset(int x,int y)900 int GetDirectionFromOffset(int x, int y)
901 {
902 if (x < 0 && y == 0) {
903 return West;
904 } else if (x > 0 && y == 0) {
905 return East;
906 } else if (y < 0 && x == 0) {
907 return North;
908 } else if (y > 0 && x == 0) {
909 return South;
910 } else if (x < 0 && y < 0) {
911 return Northwest;
912 } else if (x > 0 && y < 0) {
913 return Northeast;
914 } else if (x < 0 && y > 0) {
915 return Southwest;
916 } else if (x > 0 && y > 0) {
917 return Southeast;
918 }
919
920 return -1;
921 }
922
GetDirectionOffset(int direction)923 Vec2i GetDirectionOffset(int direction)
924 {
925 Vec2i offset(0, 0);
926
927 if (direction == North || direction == Northwest || direction == Northeast) {
928 offset.y = -1;
929 } else if (direction == South || direction == Southwest || direction == Southeast) {
930 offset.y = 1;
931 }
932 if (direction == West || direction == Northwest || direction == Southwest) {
933 offset.x = -1;
934 } else if (direction == East || direction == Northeast || direction == Southeast) {
935 offset.x = 1;
936 }
937
938 return offset;
939 }
940 //Wyrmgus end
941
942 //@}
943