LevelInfo.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "StdH.h"
  13. #include "LevelInfo.h"
  14. #include <io.h>
  15. CListHead _lhAutoDemos;
  16. CListHead _lhAllLevels;
  17. CListHead _lhFilteredLevels;
  18. extern INDEX sam_bShowAllLevels;
  19. CLevelInfo::CLevelInfo(void)
  20. {
  21. li_fnLevel = CTString("Levels\\Default.wld");
  22. li_strName = TRANS("<invalid level>");
  23. li_ulSpawnFlags = 0x0;
  24. }
  25. CLevelInfo::CLevelInfo(const CLevelInfo &li)
  26. {
  27. li_fnLevel = li.li_fnLevel;
  28. li_strName = li.li_strName;
  29. li_ulSpawnFlags = li.li_ulSpawnFlags;
  30. }
  31. void CLevelInfo::operator=(const CLevelInfo &li)
  32. {
  33. li_fnLevel = li.li_fnLevel;
  34. li_strName = li.li_strName;
  35. li_ulSpawnFlags = li.li_ulSpawnFlags;
  36. }
  37. // get level info for given filename
  38. BOOL GetLevelInfo(CLevelInfo &li, const CTFileName &fnm)
  39. {
  40. // try to
  41. try {
  42. // open the world file
  43. CTFileStream strm;
  44. strm.Open_t(fnm);
  45. // skip initial chunk ids
  46. strm.ExpectID_t("BUIV"); // 'build version'
  47. INDEX iDummy;
  48. strm>>iDummy; // the version number
  49. strm.ExpectID_t("WRLD"); // 'world'
  50. strm.ExpectID_t("WLIF"); // 'world info'
  51. if (strm.PeekID_t()==CChunkID("DTRS")) {
  52. strm.ExpectID_t("DTRS"); // 'world info'
  53. }
  54. // read the name
  55. strm>>li.li_strName;
  56. // read the flags
  57. strm>>li.li_ulSpawnFlags;
  58. // translate name
  59. li.li_strName = TranslateConst(li.li_strName, 0);
  60. // if dummy name
  61. if (li.li_strName=="") {
  62. // use filename
  63. li.li_strName = fnm.FileName();
  64. }
  65. // remember filename
  66. li.li_fnLevel = fnm;
  67. // succeed
  68. return TRUE;
  69. // if failed
  70. } catch (char *strError) {
  71. (void) strError;
  72. //CPrintF("Invalid world file '%s': %s\n", (const char*) fnm, strError);
  73. // set dummy info
  74. li = CLevelInfo();
  75. // fail
  76. return FALSE;
  77. }
  78. }
  79. int qsort_CompareLevels(const void *elem1, const void *elem2 )
  80. {
  81. const CLevelInfo &li1 = **(CLevelInfo **)elem1;
  82. const CLevelInfo &li2 = **(CLevelInfo **)elem2;
  83. return strcmp(li1.li_fnLevel, li2.li_fnLevel);
  84. }
  85. // init level-info subsystem
  86. void LoadLevelsList(void)
  87. {
  88. CPrintF(TRANS("Reading levels directory...\n"));
  89. // list the levels directory with subdirs
  90. CDynamicStackArray<CTFileName> afnmDir;
  91. MakeDirList(afnmDir, CTString("Levels\\"), "*.wld", DLI_RECURSIVE|DLI_SEARCHCD);
  92. // for each file in the directory
  93. for (INDEX i=0; i<afnmDir.Count(); i++) {
  94. CTFileName fnm = afnmDir[i];
  95. CPrintF(TRANS(" file '%s' : "), (const char *)fnm);
  96. // try to load its info, and if valid
  97. CLevelInfo li;
  98. if (GetLevelInfo(li, fnm)) {
  99. CPrintF(TRANS("'%s' spawn=0x%08x\n"), li.li_strName, li.li_ulSpawnFlags);
  100. // create new info for that file
  101. CLevelInfo *pliNew = new CLevelInfo;
  102. *pliNew = li;
  103. // add it to list of all levels
  104. _lhAllLevels.AddTail(pliNew->li_lnNode);
  105. } else {
  106. CPrintF(TRANS("invalid level\n"));
  107. }
  108. }
  109. // sort the list
  110. _lhAllLevels.Sort(qsort_CompareLevels, offsetof(CLevelInfo, li_lnNode));
  111. }
  112. // cleanup level-info subsystem
  113. void ClearLevelsList(void)
  114. {
  115. // delete list of levels
  116. FORDELETELIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
  117. delete &itli.Current();
  118. }
  119. }
  120. // find all levels that match given flags
  121. void FilterLevels(ULONG ulSpawnFlags)
  122. {
  123. // delete list of filtered levels
  124. {FORDELETELIST(CLevelInfo, li_lnNode, _lhFilteredLevels, itli) {
  125. delete &itli.Current();
  126. }}
  127. // for each level in main list
  128. FOREACHINLIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
  129. CLevelInfo &li = *itli;
  130. // initially, the level is not visible in list
  131. BOOL bVisible = FALSE;
  132. // if all levels are shown, it is visible
  133. if (sam_bShowAllLevels) {
  134. bVisible = TRUE;
  135. // if it satisfies the spawn flags
  136. } else if (li.li_ulSpawnFlags&ulSpawnFlags) {
  137. // if spawn flags include single player
  138. if (ulSpawnFlags&SPF_SINGLEPLAYER) {
  139. // visibile only if visited already
  140. bVisible = FileExists(li.li_fnLevel.NoExt()+".vis");
  141. // if not single player
  142. } else {
  143. // it is visibile
  144. bVisible = TRUE;
  145. }
  146. }
  147. // if visible
  148. if (bVisible) {
  149. // make a copy
  150. CLevelInfo *pliNew = new CLevelInfo;
  151. *pliNew = li;
  152. // add it to the list of filtered levels
  153. _lhFilteredLevels.AddTail(pliNew->li_lnNode);
  154. }
  155. }
  156. }
  157. // if level doesn't support given flags, find one that does
  158. void ValidateLevelForFlags(CTString &fnm, ULONG ulSpawnFlags)
  159. {
  160. // for each level in main list
  161. {FOREACHINLIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
  162. CLevelInfo &li = *itli;
  163. // if found
  164. if (li.li_fnLevel == fnm) {
  165. // if it satisfies the flags
  166. if (li.li_ulSpawnFlags&ulSpawnFlags) {
  167. // all ok
  168. return;
  169. }
  170. }
  171. }}
  172. // for each level in main list
  173. {FOREACHINLIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
  174. CLevelInfo &li = *itli;
  175. // if it satisfies the flags
  176. if (li.li_ulSpawnFlags&ulSpawnFlags) {
  177. // use that one
  178. fnm = li.li_fnLevel;
  179. return;
  180. }
  181. }}
  182. // if nothing found, use default invalid level
  183. fnm = CLevelInfo().li_fnLevel;
  184. }
  185. // get level info for its filename
  186. CLevelInfo FindLevelByFileName(const CTFileName &fnm)
  187. {
  188. // for each level in main list
  189. FOREACHINLIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
  190. CLevelInfo &li = *itli;
  191. // if found
  192. if (li.li_fnLevel == fnm) {
  193. // return it
  194. return li;
  195. }
  196. }
  197. // if none found, return dummy
  198. return CLevelInfo();
  199. }
  200. int qsort_CompareDemos(const void *elem1, const void *elem2 )
  201. {
  202. const CLevelInfo &li1 = **(CLevelInfo **)elem1;
  203. const CLevelInfo &li2 = **(CLevelInfo **)elem2;
  204. return strcmp(li1.li_fnLevel, li2.li_fnLevel);
  205. }
  206. // init list of autoplay demos
  207. void LoadDemosList(void)
  208. {
  209. CPrintF(TRANS("Reading demos directory...\n"));
  210. // list the levels directory with subdirs
  211. CDynamicStackArray<CTFileName> afnmDir;
  212. MakeDirList(afnmDir, CTString("Demos\\"), "Demos\\Auto-*.dem", DLI_RECURSIVE);
  213. // for each file in the directory
  214. for (INDEX i=0; i<afnmDir.Count(); i++) {
  215. CTFileName fnm = afnmDir[i];
  216. // create new info for that file
  217. CLevelInfo *pli = new CLevelInfo;
  218. pli->li_fnLevel = fnm;
  219. CPrintF(" %s\n", (const char *)pli->li_fnLevel);
  220. // add it to list
  221. _lhAutoDemos.AddTail(pli->li_lnNode);
  222. }
  223. // sort the list
  224. _lhAutoDemos.Sort(qsort_CompareDemos, offsetof(CLevelInfo, li_lnNode));
  225. // add the intro to the start
  226. extern CTString sam_strIntroLevel;
  227. if (sam_strIntroLevel!="") {
  228. CLevelInfo *pli = new CLevelInfo;
  229. pli->li_fnLevel = sam_strIntroLevel;
  230. CPrintF(" %s\n", (const char *)pli->li_fnLevel);
  231. _lhAutoDemos.AddHead(pli->li_lnNode);
  232. }
  233. }
  234. // clear list of autoplay demos
  235. void ClearDemosList(void)
  236. {
  237. // delete list of levels
  238. FORDELETELIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
  239. delete &itli.Current();
  240. }
  241. }