123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- /* Copyright (c) 2002-2012 Croteam Ltd.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as published by
- the Free Software Foundation
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
- #include "StdH.h"
- #include "LevelInfo.h"
- #include <io.h>
- CListHead _lhAutoDemos;
- CListHead _lhAllLevels;
- CListHead _lhFilteredLevels;
- extern INDEX sam_bShowAllLevels;
- CLevelInfo::CLevelInfo(void)
- {
- li_fnLevel = CTString("Levels\\Default.wld");
- li_strName = TRANS("<invalid level>");
- li_ulSpawnFlags = 0x0;
- }
- CLevelInfo::CLevelInfo(const CLevelInfo &li)
- {
- li_fnLevel = li.li_fnLevel;
- li_strName = li.li_strName;
- li_ulSpawnFlags = li.li_ulSpawnFlags;
- }
- void CLevelInfo::operator=(const CLevelInfo &li)
- {
- li_fnLevel = li.li_fnLevel;
- li_strName = li.li_strName;
- li_ulSpawnFlags = li.li_ulSpawnFlags;
- }
- // get level info for given filename
- BOOL GetLevelInfo(CLevelInfo &li, const CTFileName &fnm)
- {
- // try to
- try {
- // open the world file
- CTFileStream strm;
- strm.Open_t(fnm);
- // skip initial chunk ids
- strm.ExpectID_t("BUIV"); // 'build version'
- INDEX iDummy;
- strm>>iDummy; // the version number
- strm.ExpectID_t("WRLD"); // 'world'
- strm.ExpectID_t("WLIF"); // 'world info'
- if (strm.PeekID_t()==CChunkID("DTRS")) {
- strm.ExpectID_t("DTRS"); // 'world info'
- }
- // read the name
- strm>>li.li_strName;
- // read the flags
- strm>>li.li_ulSpawnFlags;
- // translate name
- li.li_strName = TranslateConst(li.li_strName, 0);
- // if dummy name
- if (li.li_strName=="") {
- // use filename
- li.li_strName = fnm.FileName();
- }
- // remember filename
- li.li_fnLevel = fnm;
- // succeed
- return TRUE;
- // if failed
- } catch (char *strError) {
- (void) strError;
- //CPrintF("Invalid world file '%s': %s\n", (const char*) fnm, strError);
- // set dummy info
- li = CLevelInfo();
- // fail
- return FALSE;
- }
- }
- int qsort_CompareLevels(const void *elem1, const void *elem2 )
- {
- const CLevelInfo &li1 = **(CLevelInfo **)elem1;
- const CLevelInfo &li2 = **(CLevelInfo **)elem2;
- return strcmp(li1.li_fnLevel, li2.li_fnLevel);
- }
- // init level-info subsystem
- void LoadLevelsList(void)
- {
- CPrintF(TRANS("Reading levels directory...\n"));
- // list the levels directory with subdirs
- CDynamicStackArray<CTFileName> afnmDir;
- MakeDirList(afnmDir, CTString("Levels\\"), "*.wld", DLI_RECURSIVE|DLI_SEARCHCD);
- // for each file in the directory
- for (INDEX i=0; i<afnmDir.Count(); i++) {
- CTFileName fnm = afnmDir[i];
- CPrintF(TRANS(" file '%s' : "), (const char *)fnm);
- // try to load its info, and if valid
- CLevelInfo li;
- if (GetLevelInfo(li, fnm)) {
- CPrintF(TRANS("'%s' spawn=0x%08x\n"), li.li_strName, li.li_ulSpawnFlags);
- // create new info for that file
- CLevelInfo *pliNew = new CLevelInfo;
- *pliNew = li;
- // add it to list of all levels
- _lhAllLevels.AddTail(pliNew->li_lnNode);
- } else {
- CPrintF(TRANS("invalid level\n"));
- }
- }
- // sort the list
- _lhAllLevels.Sort(qsort_CompareLevels, offsetof(CLevelInfo, li_lnNode));
- }
- // cleanup level-info subsystem
- void ClearLevelsList(void)
- {
- // delete list of levels
- FORDELETELIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
- delete &itli.Current();
- }
- }
- // find all levels that match given flags
- void FilterLevels(ULONG ulSpawnFlags)
- {
- // delete list of filtered levels
- {FORDELETELIST(CLevelInfo, li_lnNode, _lhFilteredLevels, itli) {
- delete &itli.Current();
- }}
- // for each level in main list
- FOREACHINLIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
- CLevelInfo &li = *itli;
- // initially, the level is not visible in list
- BOOL bVisible = FALSE;
- // if all levels are shown, it is visible
- if (sam_bShowAllLevels) {
- bVisible = TRUE;
- // if it satisfies the spawn flags
- } else if (li.li_ulSpawnFlags&ulSpawnFlags) {
- // if spawn flags include single player
- if (ulSpawnFlags&SPF_SINGLEPLAYER) {
- // visibile only if visited already
- bVisible = FileExists(li.li_fnLevel.NoExt()+".vis");
- // if not single player
- } else {
- // it is visibile
- bVisible = TRUE;
- }
- }
- // if visible
- if (bVisible) {
- // make a copy
- CLevelInfo *pliNew = new CLevelInfo;
- *pliNew = li;
- // add it to the list of filtered levels
- _lhFilteredLevels.AddTail(pliNew->li_lnNode);
- }
- }
- }
- // if level doesn't support given flags, find one that does
- void ValidateLevelForFlags(CTString &fnm, ULONG ulSpawnFlags)
- {
- // for each level in main list
- {FOREACHINLIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
- CLevelInfo &li = *itli;
- // if found
- if (li.li_fnLevel == fnm) {
- // if it satisfies the flags
- if (li.li_ulSpawnFlags&ulSpawnFlags) {
- // all ok
- return;
- }
- }
- }}
-
- // for each level in main list
- {FOREACHINLIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
- CLevelInfo &li = *itli;
- // if it satisfies the flags
- if (li.li_ulSpawnFlags&ulSpawnFlags) {
- // use that one
- fnm = li.li_fnLevel;
- return;
- }
- }}
- // if nothing found, use default invalid level
- fnm = CLevelInfo().li_fnLevel;
- }
- // get level info for its filename
- CLevelInfo FindLevelByFileName(const CTFileName &fnm)
- {
- // for each level in main list
- FOREACHINLIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
- CLevelInfo &li = *itli;
- // if found
- if (li.li_fnLevel == fnm) {
- // return it
- return li;
- }
- }
- // if none found, return dummy
- return CLevelInfo();
- }
- int qsort_CompareDemos(const void *elem1, const void *elem2 )
- {
- const CLevelInfo &li1 = **(CLevelInfo **)elem1;
- const CLevelInfo &li2 = **(CLevelInfo **)elem2;
- return strcmp(li1.li_fnLevel, li2.li_fnLevel);
- }
- // init list of autoplay demos
- void LoadDemosList(void)
- {
- CPrintF(TRANS("Reading demos directory...\n"));
- // list the levels directory with subdirs
- CDynamicStackArray<CTFileName> afnmDir;
- MakeDirList(afnmDir, CTString("Demos\\"), "Demos\\Auto-*.dem", DLI_RECURSIVE);
- // for each file in the directory
- for (INDEX i=0; i<afnmDir.Count(); i++) {
- CTFileName fnm = afnmDir[i];
- // create new info for that file
- CLevelInfo *pli = new CLevelInfo;
- pli->li_fnLevel = fnm;
- CPrintF(" %s\n", (const char *)pli->li_fnLevel);
- // add it to list
- _lhAutoDemos.AddTail(pli->li_lnNode);
- }
- // sort the list
- _lhAutoDemos.Sort(qsort_CompareDemos, offsetof(CLevelInfo, li_lnNode));
- // add the intro to the start
- extern CTString sam_strIntroLevel;
- if (sam_strIntroLevel!="") {
- CLevelInfo *pli = new CLevelInfo;
- pli->li_fnLevel = sam_strIntroLevel;
- CPrintF(" %s\n", (const char *)pli->li_fnLevel);
- _lhAutoDemos.AddHead(pli->li_lnNode);
- }
- }
- // clear list of autoplay demos
- void ClearDemosList(void)
- {
- // delete list of levels
- FORDELETELIST(CLevelInfo, li_lnNode, _lhAllLevels, itli) {
- delete &itli.Current();
- }
- }
|