diff --git a/StartInfo.h b/StartInfo.h index 8b2d39a1f..0639e2c67 100644 --- a/StartInfo.h +++ b/StartInfo.h @@ -52,11 +52,12 @@ struct PlayerSettings struct StartInfo { - ui8 mode; //0 - new game; 1 - load game + ui8 mode; //0 - new game; 1 - load game; 2 - campaign ui8 difficulty; //0=easy; 4=impossible std::vector playerInfos; //serial indexed ui8 turnTime; //in minutes, 0=unlimited std::string mapname; + ui8 whichMapInCampaign; //used only for mode 2 PlayerSettings & getIthPlayersSettings(int no) { for(unsigned int i=0; icastleInt->hBuild==this) && !(indeterminate(down)) && (CSDL_Ext::SDL_GetPixel(area,GH.current->motion.x-pos.x,GH.current->motion.y-pos.y) != 0)) //na polu + if( area && (LOCPLINT->castleInt->hBuild==this) && !(indeterminate(down)) && + !CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) //inside building image { if(previousState && !down) LOCPLINT->castleInt->buildingClicked(str->ID); @@ -150,7 +151,7 @@ void CBuildingRect::clickRight(tribool down, bool previousState) { if((!area) || (!((bool)down)) || (this!=LOCPLINT->castleInt->hBuild)) return; - if((CSDL_Ext::SDL_GetPixel(area,GH.current->motion.x-pos.x,GH.current->motion.y-pos.y) != 0)) //na polu + if( !CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) //inside building image { CBuilding *bld = CGI->buildh->buildings[str->townID][str->ID]; assert(bld); diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 9bb56c35d..e2496c1f3 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -110,7 +110,7 @@ CMapInfo::~CMapInfo() void CMapInfo::campaignInit() { - campaignHeader = new CCampaignHeader( CCampaignHandler::getHeader(filename) ); + campaignHeader = new CCampaignHeader( CCampaignHandler::getHeader(filename, lodCmpgn) ); } CMenuScreen::CMenuScreen( EState which ) @@ -158,10 +158,6 @@ CMenuScreen::CMenuScreen( EState which ) buttons[3] = new AdventureMapButton("", "", bind(&CGPreGame::openSel, CGP, campaignList), 550, 358, "ZSSCUS.DEF", SDLK_t); buttons[4] = new AdventureMapButton("", "", bind(&CMenuScreen::moveTo, this, CGP->scrs[newGame]), 582, 464, "ZSSEXIT.DEF", SDLK_ESCAPE); - ////just for testing - CCampaignHandler * ch = new CCampaignHandler(); - ch->getCampaignHeaders(); - //ch->getCampaign("./Maps/ALEXIS.h3c"); } break; } @@ -387,7 +383,7 @@ void CSelectionScreen::changeSelection( const CMapInfo *to ) curOpts->difficulty = to->seldiff; if(type != CMenuScreen::campaignList) { - updateStartInfo(to); + updateStartInfo(to, sInfo, to->mapHeader); } card->changeSelection(to); if(type != CMenuScreen::campaignList) @@ -415,7 +411,7 @@ void setPlayer(PlayerSettings &pset, unsigned player) } } -void CSelectionScreen::updateStartInfo( const CMapInfo * to ) +void CSelectionScreen::updateStartInfo( const CMapInfo * to, StartInfo & sInfo, const CMapHeader * mapHeader ) { sInfo.playerInfos.clear(); if(!to) @@ -429,7 +425,7 @@ void CSelectionScreen::updateStartInfo( const CMapInfo * to ) int serialC=0; for (int i = 0; i < PLAYER_LIMIT; i++) { - const PlayerInfo &pinfo = to->mapHeader->players[i]; + const PlayerInfo &pinfo = mapHeader->players[i]; //neither computer nor human can play - no player if (!(pinfo.canComputerPlay || pinfo.canComputerPlay)) @@ -452,7 +448,7 @@ void CSelectionScreen::updateStartInfo( const CMapInfo * to ) } } - if ((pinfo.generateHeroAtMainTown || to->mapHeader->version==CMapHeader::RoE) && pinfo.hasMainTown //we will generate hero in front of main town + if ((pinfo.generateHeroAtMainTown || mapHeader->version==CMapHeader::RoE) && pinfo.hasMainTown //we will generate hero in front of main town || pinfo.p8) //random hero pset.hero = -1; else @@ -470,7 +466,7 @@ void CSelectionScreen::updateStartInfo( const CMapInfo * to ) void CSelectionScreen::startCampaign() { - CCampaign * ourCampaign = CCampaignHandler::getCampaign(curMap->filename); + CCampaign * ourCampaign = CCampaignHandler::getCampaign(curMap->filename, curMap->lodCmpgn); GH.pushInt( new CBonusSelection(ourCampaign, 0) ); } @@ -619,6 +615,7 @@ void SelectionTab::parseCampaigns( std::vector & files ) { allItems[i].date = std::asctime(std::localtime(&files[i].date)); allItems[i].filename = files[i].name; + allItems[i].lodCmpgn = files[i].inLod; allItems[i].campaignInit(); } } @@ -652,6 +649,7 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function toParse; + std::vector cpm; switch(tabType) { case CMenuScreen::newGame: @@ -677,6 +675,22 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::functionmapPieces[whichMap].c_str(), _it); - //campaign name if (ourCampaign->header.name.length()) printAtLoc(ourCampaign->header.name, 481, 28, FONT_BIG, tytulowy, background); @@ -2088,28 +2098,8 @@ CBonusSelection::CBonusSelection( const CCampaign * _ourCampaign, int _whichMap printAtLoc("Unnamed", 481, 28, FONT_BIG, tytulowy, background); //map size icon - CDefHandler *sizes = CDefHandler::giveDef("SCNRMPSZ.DEF"); - int temp; - switch (ourHeader.width) - { - case 36: - temp=0; - break; - case 72: - temp=1; - break; - case 108: - temp=2; - break; - case 144: - temp=3; - break; - default: - temp=4; - break; - } - blitAtLoc(sizes->ourImages[temp].bitmap, 735, 26, background); - delete sizes; + sizes = CDefHandler::giveDef("SCNRMPSZ.DEF"); + //campaign description printAtLoc(CGI->generaltexth->allTexts[38], 481, 63, FONT_SMALL, tytulowy, background); @@ -2119,27 +2109,31 @@ CBonusSelection::CBonusSelection( const CCampaign * _ourCampaign, int _whichMap printAtLoc((*desc)[i], 481, 86 + i*16, FONT_SMALL, zwykly, background); delete desc; - //map name - std::string mapDesc = ourHeader.description, mapName = ourHeader.name; - - if (mapName.length()) - printAtLoc(mapName, 481, 219, FONT_BIG, tytulowy, background); - else - printAtLoc("Unnamed", 481, 219, FONT_BIG, tytulowy, background); - - //map description - printAtLoc(CGI->generaltexth->allTexts[496], 481, 253, FONT_SMALL, tytulowy, background); - - desc = CMessage::breakText(mapDesc, 45); - for (int i=0; isize(); i++) - printAtLoc((*desc)[i], 481, 281 + i*16, FONT_SMALL, zwykly, background); - delete desc; + //set left part of window + for (int g=0; gscenarios.size(); ++g) + { + if(ourCampaign->conquerable(g)) + { + regions.push_back(new CRegion(this, true, true, g)); + regions[regions.size()-1]->rclickText = ourCampaign->scenarios[g].regionText; + if (highlightedRegion == NULL) + { + highlightedRegion = regions.back(); + selectMap(g); + } + } + else if (ourCampaign->scenarios[g].conquered) //display as striped + { + regions.push_back(new CRegion(this, false, false, g)); + regions[regions.size()-1]->rclickText = ourCampaign->scenarios[g].regionText; + } + } //allies / enemies printAtLoc(CGI->generaltexth->allTexts[390] + ":", 486, 407, FONT_SMALL, zwykly, background); //Allies printAtLoc(CGI->generaltexth->allTexts[391] + ":", 619, 407, FONT_SMALL, zwykly, background); //Enemies int fx=64, ex=244, myT; - myT = ourHeader.players[playerColor].team; + myT = ourHeader->players[playerColor].team; /*for (std::vector::const_iterator i = curOpts->playerInfos.begin(); i != curOpts->playerInfos.end(); i++) { int *myx = ((i->color == playerColor || ourHeader.players[i->color].team == myT) ? &fx : &ex); @@ -2154,29 +2148,14 @@ CBonusSelection::CBonusSelection( const CCampaign * _ourCampaign, int _whichMap //difficulty printAtLoc("Difficulty", 691, 431, FONT_MEDIUM, zwykly, background); //Difficulty - - //set left part of window - for (int g=0; gscenarios.size(); ++g) - { - if(ourCampaign->conquerable(g)) - { - regions.push_back(new CRegion(this, true, true, g)); - if (highlightedRegion == NULL) - { - highlightedRegion = regions.back(); - } - } - else if (ourCampaign->scenarios[g].conquered) //display as striped - { - regions.push_back(new CRegion(this, false, false, g)); - } - } } CBonusSelection::~CBonusSelection() { SDL_FreeSurface(background); + delete sizes; + delete ourHeader; } void CBonusSelection::goBack() @@ -2222,10 +2201,76 @@ void CBonusSelection::loadPositionsOfGraphics() } +void CBonusSelection::selectMap( int whichOne ) +{ + sInfo.difficulty = ourCampaign->scenarios[whichOne].difficulty; + sInfo.mapname = ourCampaign->header.name; + sInfo.mode = 2; + + //get header + int i = 0; + delete ourHeader; + ourHeader = new CMapHeader(); + ourHeader->initFromMemory((const unsigned char*)ourCampaign->mapPieces[whichOne].c_str(), i); + const_cast(curMap)->playerAmnt = ourHeader->players.size(); + + CSelectionScreen::updateStartInfo(curMap, *curOpts, ourHeader); + sInfo.turnTime = 0; + sInfo.whichMapInCampaign = whichOne; +} + +void CBonusSelection::show( SDL_Surface * to ) +{ + blitAt(background, pos.x, pos.y, to); + + //map name + std::string mapDesc = ourHeader->description, + mapName = ourHeader->name; + + if (mapName.length()) + printAtLoc(mapName, 481, 219, FONT_BIG, tytulowy, to); + else + printAtLoc("Unnamed", 481, 219, FONT_BIG, tytulowy, to); + + //map description + printAtLoc(CGI->generaltexth->allTexts[496], 481, 253, FONT_SMALL, tytulowy, to); + + std::vector *desc = CMessage::breakText(mapDesc, 45); + for (int i=0; isize(); i++) + printAtLoc((*desc)[i], 481, 281 + i*16, FONT_SMALL, zwykly, to); + delete desc; + + //map size icon + int temp; + switch (ourHeader->width) + { + case 36: + temp=0; + break; + case 72: + temp=1; + break; + case 108: + temp=2; + break; + case 144: + temp=3; + break; + default: + temp=4; + break; + } + blitAtLoc(sizes->ourImages[temp].bitmap, 735, 26, to); + + CIntObject::show(to); +} + CBonusSelection::CRegion::CRegion( CBonusSelection * _owner, bool _accessible, bool _selectable, int _myNumber ) : owner(_owner), accessible(_accessible), selectable(_selectable), myNumber(_myNumber) { OBJ_CONSTRUCTION; + used = LCLICK | RCLICK; + static const std::string colors[2][8] = { {"R", "B", "N", "G", "O", "V", "T", "P"}, {"Re", "Bl", "Br", "Gr", "Or", "Vi", "Te", "Pi"}}; @@ -2245,6 +2290,8 @@ CBonusSelection::CRegion::CRegion( CBonusSelection * _owner, bool _accessible, b { graphics[g] = BitmapHandler::loadBitmap(prefix + infix[g] + suffix + ".BMP"); } + pos.w = graphics[0]->w; + pos.h = graphics[0]->h; } @@ -2259,15 +2306,23 @@ CBonusSelection::CRegion::~CRegion() void CBonusSelection::CRegion::clickLeft( tribool down, bool previousState ) { //select if selectable & clicked inside our graphic - if(!down && selectable) + if( !down && selectable && !CSDL_Ext::isTransparent(graphics[0], GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) { - //owner->highlightedRegion = this; + owner->selectMap(myNumber); + owner->highlightedRegion = this; } } void CBonusSelection::CRegion::clickRight( tribool down, bool previousState ) { //show r-click text + if( down && !CSDL_Ext::isTransparent(graphics[0], GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) && + rclickText.size() ) + { + CSimpleWindow * temp = CMessage::genWindow(rclickText, 0, true); + CRClickPopupInt *rcpi = new CRClickPopupInt(temp, true); + GH.pushInt(rcpi); + } } void CBonusSelection::CRegion::show( SDL_Surface * to ) diff --git a/client/CPreGame.h b/client/CPreGame.h index 13dff0281..ef71377f0 100644 --- a/client/CPreGame.h +++ b/client/CPreGame.h @@ -31,6 +31,7 @@ public: CCampaignHeader * campaignHeader; //may be NULL if scenario ui8 seldiff; //selected difficulty (only in saved games) std::string filename; + bool lodCmpgn; //tells if this campaign is located in Lod file std::string date; int playerAmnt, humenPlayers; CMapInfo(bool map = true); @@ -73,12 +74,13 @@ struct FileInfo { std::string name; // file name with full path and extension std::time_t date; + bool inLod; //tells if this file is located in Lod }; class InfoCard : public CIntObject { -public: CPicture *bg; +public: CMenuScreen::EState type; CHighlightableButtonsGroup *difficulty; @@ -139,6 +141,7 @@ public: class OptionsTab : public CIntObject { + CPicture *bg; public: enum SelType {TOWN, HERO, BONUS}; struct SelectedBox : public CIntObject //img with current town/hero/bonus @@ -170,7 +173,6 @@ public: void showAll(SDL_Surface * to); }; CMenuScreen::EState type; - CPicture *bg; CSlider *turnDuration; std::set usedHeroes; @@ -195,13 +197,13 @@ public: class CSelectionScreen : public CIntObject { -public: CPicture *bg; //general bg image - AdventureMapButton *start, *back; InfoCard *card; - SelectionTab *sel; OptionsTab *opt; +public: + AdventureMapButton *start, *back; + SelectionTab *sel; CMenuScreen::EState type; //new/save/load#Game const CMapInfo *current; StartInfo sInfo; @@ -211,7 +213,7 @@ public: ~CSelectionScreen(); void toggleTab(CIntObject *tab); void changeSelection(const CMapInfo *to); - void updateStartInfo(const CMapInfo * to); + static void updateStartInfo( const CMapInfo * to, StartInfo & sInfo, const CMapHeader * mapHeader ); void startCampaign(); void startGame(); void difficultyChange(int to); @@ -282,6 +284,7 @@ class CBonusSelection : public CIntObject bool selectable; //true if region should be selectable int myNumber; //number of region public: + std::string rclickText; CRegion(CBonusSelection * _owner, bool _accessible, bool _selectable, int _myNumber); ~CRegion(); @@ -295,12 +298,18 @@ class CBonusSelection : public CIntObject void loadPositionsOfGraphics(); const CCampaign * ourCampaign; + CMapHeader *ourHeader; + CDefHandler *sizes; //icons of map sizes int whichMap; public: + StartInfo sInfo; + void selectMap(int whichOne); + CBonusSelection(const CCampaign * _ourCampaign, int _whichMap); ~CBonusSelection(); void showAll(SDL_Surface * to); + void show(SDL_Surface * to); void goBack(); void startMap(); diff --git a/client/SDL_Extensions.cpp b/client/SDL_Extensions.cpp index 9efadbad1..0992755a8 100644 --- a/client/SDL_Extensions.cpp +++ b/client/SDL_Extensions.cpp @@ -1046,4 +1046,16 @@ std::string CSDL_Ext::processStr(std::string str, std::vector & tor return str; } +bool CSDL_Ext::isTransparent( SDL_Surface * srf, int x, int y ) +{ + if(srf->format->BytesPerPixel == 1) + { + return ((ui8*)srf->pixels)[x + srf->pitch * y] == 0; + } + else + { + assert(!"isTransparent called with non-8bpp surface!"); + } +} + SDL_Surface * CSDL_Ext::std32bppSurface = NULL; diff --git a/config/settings.txt b/config/settings.txt index 4fe05086e..29de4becd 100644 --- a/config/settings.txt +++ b/config/settings.txt @@ -3,7 +3,7 @@ clientSettings { port=3030; - resolution=800x600; // format: WxH + resolution=1024x768; // format: WxH bpp=24; // bytes per pixels: 24 or 32 fullscreen=0; //0 - windowed mode, 1 - fullscreen server=127.0.0.1; //use 127.0.0.1 for localhost diff --git a/hch/CCampaignHandler.cpp b/hch/CCampaignHandler.cpp index 4f6b3307d..08be282dc 100644 --- a/hch/CCampaignHandler.cpp +++ b/hch/CCampaignHandler.cpp @@ -21,54 +21,82 @@ namespace fs = boost::filesystem; */ -std::vector CCampaignHandler::getCampaignHeaders() +std::vector CCampaignHandler::getCampaignHeaders(GetMode mode) { std::vector ret; std::string dirname = DATA_DIR "/Maps"; - std::string ext = ".h3c"; + std::string ext = ".H3C"; if(!boost::filesystem::exists(dirname)) { tlog1 << "Cannot find " << dirname << " directory!\n"; } - fs::path tie(dirname); - fs::directory_iterator end_iter; - for ( fs::directory_iterator file (tie); file!=end_iter; ++file ) + if (mode == Custom || mode == ALL) //add custom campaigns { - if(fs::is_regular_file(file->status()) - && boost::ends_with(file->path().filename(), ext)) + fs::path tie(dirname); + fs::directory_iterator end_iter; + for ( fs::directory_iterator file (tie); file!=end_iter; ++file ) { - ret.push_back( getHeader( file->path().string() ) ); + if(fs::is_regular_file(file->status()) + && boost::ends_with(file->path().filename(), ext)) + { + ret.push_back( getHeader( file->path().string(), false ) ); + } } } + if (mode == ALL) //add all lod campaigns + { + for(int g=0; gentries.size(); ++g) + { + std::string rn = bitmaph->entries[g].nameStr; + if( boost::ends_with(bitmaph->entries[g].nameStr, ext) ) + { + ret.push_back( getHeader(bitmaph->entries[g].nameStr, true) ); + } + } + + } + return ret; } -CCampaignHeader CCampaignHandler::getHeader( const std::string & name ) +CCampaignHeader CCampaignHandler::getHeader( const std::string & name, bool fromLod ) { int realSize; unsigned char * cmpgn = CLodHandler::getUnpackedFile(name, &realSize); int it = 0;//iterator for reading CCampaignHeader ret = readHeaderFromMemory(cmpgn, it); + ret.filename = name; + ret.loadFromLod = false; delete [] cmpgn; return ret; } -CCampaign * CCampaignHandler::getCampaign( const std::string & name ) +CCampaign * CCampaignHandler::getCampaign( const std::string & name, bool fromLod ) { CCampaign * ret = new CCampaign(); int realSize; - unsigned char * cmpgn = CLodHandler::getUnpackedFile(name, &realSize); + unsigned char * cmpgn; + if (fromLod) + { + cmpgn = bitmaph->giveFile(name, &realSize); + } + else + { + cmpgn = CLodHandler::getUnpackedFile(name, &realSize); + } int it = 0; //iterator for reading ret->header = readHeaderFromMemory(cmpgn, it); + ret->header.filename = name; + ret->header.loadFromLod = fromLod; int howManyScenarios = VLC->generaltexth->campaignRegionNames[ret->header.mapVersion].size(); for(int g=0; g void serialize(Handler &h, const int formatVersion) { - h & version & mapVersion & name & description & difficultyChoosenByPlayer & music; + h & version & mapVersion & name & description & difficultyChoosenByPlayer & music & filename & loadFromLod; } }; @@ -121,10 +124,11 @@ class DLL_EXPORT CCampaignHandler static std::vector locateH3mStarts(const unsigned char * buffer, int start, int size); static bool startsAt( const unsigned char * buffer, int size, int pos ); //a simple heuristic that checks if a h3m starts at given pos public: - static std::vector getCampaignHeaders(); - static CCampaignHeader getHeader( const std::string & name ); //name - name of appropriate file + enum GetMode {RoE, AB, SoD, WoG, Custom, ALL}; + static std::vector getCampaignHeaders(GetMode mode); + static CCampaignHeader getHeader( const std::string & name, bool fromLod ); //name - name of appropriate file - static CCampaign * getCampaign(const std::string & name); //name - name of appropriate file + static CCampaign * getCampaign(const std::string & name, bool fromLod); //name - name of appropriate file };