From 3474fdaf056211e883d6ff76913b516ae6b9d757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Sat, 10 Jan 2009 22:08:18 +0000 Subject: [PATCH] * save/load partially working * Arena and Witch Hut support * improved support for Resources * minor fixes and changes --- CCastleInterface.cpp | 6 +- CGameInfo.cpp | 20 +++ CGameInfo.h | 3 + CGameState.cpp | 6 + CGameState.h | 13 +- CHeroWindow.cpp | 36 ++--- CMT.cpp | 106 +++++++-------- CPlayerInterface.cpp | 6 +- CPreGame.cpp | 197 +++++++++++++++++++-------- CPreGame.h | 7 +- ChangeLog | 8 +- StartInfo.h | 4 +- client/Client.cpp | 261 +++++++++++++++++++++++++++--------- client/Client.h | 7 + client/Graphics.cpp | 19 +-- client/Graphics.h | 3 +- hch/CAbilityHandler.cpp | 26 ---- hch/CAbilityHandler.h | 3 - hch/CBuildingHandler.cpp | 13 +- hch/CBuildingHandler.h | 1 + hch/CCreatureHandler.cpp | 4 + hch/CCreatureHandler.h | 1 + hch/CDefObjInfoHandler.cpp | 8 ++ hch/CDefObjInfoHandler.h | 3 +- hch/CGeneralTextHandler.cpp | 195 +++++++++++++++------------ hch/CGeneralTextHandler.h | 109 ++++++++------- hch/CHeroHandler.cpp | 11 +- hch/CHeroHandler.h | 5 +- hch/CObjectHandler.cpp | 117 ++++++++++++++-- hch/CObjectHandler.h | 17 ++- lib/Connection.cpp | 16 +-- lib/Connection.h | 7 +- lib/IGameCallback.h | 1 + lib/Interprocess.h | 17 +++ lib/VCMI_Lib.cpp | 109 +++++++++------ lib/VCMI_Lib.h | 15 ++- map.cpp | 39 +++++- map.h | 28 ++-- mapHandler.cpp | 53 +++++--- mapHandler.h | 3 + server/CGameHandler.cpp | 56 +++++--- server/CGameHandler.h | 9 +- server/CVCMIServer.cpp | 72 +++++++++- server/CVCMIServer.h | 1 + 44 files changed, 1103 insertions(+), 538 deletions(-) diff --git a/CCastleInterface.cpp b/CCastleInterface.cpp index d5f153907..ee77629e3 100644 --- a/CCastleInterface.cpp +++ b/CCastleInterface.cpp @@ -1089,7 +1089,7 @@ void CHallInterface::close() delete this; LOCPLINT->castleInt->activate(); } -void CHallInterface::show(SDL_Surface * to) //TODO use me +void CHallInterface::show(SDL_Surface * to) { blitAt(bg,pos); resdatabar.show(); @@ -1460,7 +1460,7 @@ void CFortScreen::RecArea::clickLeft (tribool down) if(!down && pressedL) { LOCPLINT->curint->deactivate(); - //CRecrutationWindow *rw = LOCPLINT->castleInt->showRecruitmentWindow(bid); //TODO use me + CRecrutationWindow *rw = LOCPLINT->castleInt->showRecruitmentWindow(bid); //do not touch me } ClickableL::clickLeft(down); } @@ -1530,7 +1530,7 @@ void CMageGuildScreen::close() LOCPLINT->castleInt->subInt = NULL; LOCPLINT->castleInt->activate(); } -void CMageGuildScreen::show(SDL_Surface * to) //TODO use me +void CMageGuildScreen::show(SDL_Surface * to) { blitAt(bg,pos); resdatabar.show(); diff --git a/CGameInfo.cpp b/CGameInfo.cpp index e677d0c4e..9decefab0 100644 --- a/CGameInfo.cpp +++ b/CGameInfo.cpp @@ -1,4 +1,24 @@ #include "stdafx.h" #include "CGameInfo.h" +#include "lib/VCMI_Lib.h" CGameInfo * CGI; + +CGameInfo::CGameInfo() +{ + mh = NULL; + state = NULL; +} + +void CGameInfo::setFromLib() +{ + generaltexth = VLC->generaltexth; + arth = VLC->arth; + creh = VLC->creh; + townh = VLC->townh; + heroh = VLC->heroh; + objh = VLC->objh; + spellh = VLC->spellh; + dobjinfo = VLC->dobjinfo; + buildh = VLC->buildh; +} \ No newline at end of file diff --git a/CGameInfo.h b/CGameInfo.h index bb3d69da3..c6eefc3ad 100644 --- a/CGameInfo.h +++ b/CGameInfo.h @@ -61,6 +61,9 @@ public: CPathfinder * pathf; CCursorHandler * curh; CScreenHandler * screenh; + + CGameInfo(); + void setFromLib(); }; diff --git a/CGameState.cpp b/CGameState.cpp index d337f693a..6673369e5 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -1122,10 +1122,16 @@ int CGameState::getDate(int mode) const CGameState::CGameState() { mx = new boost::shared_mutex(); + map = NULL; + curB = NULL; + scenarioOps = NULL; } CGameState::~CGameState() { delete mx; + delete map; + delete curB; + delete scenarioOps; } void CGameState::init(StartInfo * si, Mapa * map, int Seed) { diff --git a/CGameState.h b/CGameState.h index 235ffe4f4..19b5d5dc9 100644 --- a/CGameState.h +++ b/CGameState.h @@ -59,7 +59,6 @@ public: template void serialize(Handler &h, const int version) { h & color & serial & currentSelection & fogOfWarMap & resources; - //TODO: vectors of heroes/towns } }; @@ -187,8 +186,6 @@ private: boost::shared_mutex *mx; - CGameState(); - ~CGameState(); void init(StartInfo * si, Mapa * map, int Seed); void loadTownDInfos(); void applyNL(IPack * pack); @@ -210,6 +207,8 @@ private: float getMarketEfficiency(int player, int mode=0); std::set tilesToReveal(int3 pos, int radious, int player) const; //if player==-1 => adds all tiles in radious public: + CGameState(); + ~CGameState(); int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month template void serialize(Handler &h, const int version) { @@ -217,6 +216,14 @@ public: if(!h.saving) { loadTownDInfos(); + + //recreating towns/heroes vectors in players entries + for(int i=0; itowns.size(); i++) + if(map->towns[i]->tempOwner < PLAYER_LIMIT) + players[map->towns[i]->tempOwner].towns.push_back(map->towns[i]); + for(int i=0; iheroes.size(); i++) + if(map->heroes[i]->tempOwner < PLAYER_LIMIT) + players[map->heroes[i]->tempOwner].heroes.push_back(map->heroes[i]); } } diff --git a/CHeroWindow.cpp b/CHeroWindow.cpp index 926680f1f..f94674c5b 100644 --- a/CHeroWindow.cpp +++ b/CHeroWindow.cpp @@ -237,10 +237,10 @@ void CHeroWindow::setHero(const CGHeroInstance *Hero) { secSkillAreas[g]->type = hero->secSkills[g].first; secSkillAreas[g]->bonus = hero->secSkills[g].second; - std::string hlp = CGI->abilh->abilities[ hero->secSkills[g].first ]->infoTexts[hero->secSkills[g].second-1]; + std::string hlp = CGI->generaltexth->skillInfoTexts[ hero->secSkills[g].first ][hero->secSkills[g].second-1]; secSkillAreas[g]->text = hlp.substr(1, hlp.size()-2); - sprintf(bufor, CGI->generaltexth->heroscrn[21].c_str(), CGI->abilh->levels[hero->secSkills[g].second-1].c_str(), CGI->abilh->abilities[hero->secSkills[g].first]->name.c_str()); + sprintf(bufor, CGI->generaltexth->heroscrn[21].c_str(), CGI->generaltexth->levels[hero->secSkills[g].second-1].c_str(), CGI->generaltexth->skillName[hero->secSkills[g].first].c_str()); secSkillAreas[g]->hoverText = std::string(bufor); } @@ -615,50 +615,50 @@ void CHeroWindow::redrawCurBack() if(curHero->secSkills.size()>=1) { blitAt(CGI->abilh->abils44->ourImages[curHero->secSkills[0].first*3+3+curHero->secSkills[0].second-1].bitmap, 18, 276, curBack); - CSDL_Ext::printAt(CGI->abilh->levels[curHero->secSkills[0].second-1], 69, 279, GEOR13, zwykly, curBack); - CSDL_Ext::printAt(CGI->abilh->abilities[curHero->secSkills[0].first]->name, 69, 299, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->levels[curHero->secSkills[0].second-1], 69, 279, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->skillName[curHero->secSkills[0].first], 69, 299, GEOR13, zwykly, curBack); } if(curHero->secSkills.size()>=2) { blitAt(CGI->abilh->abils44->ourImages[curHero->secSkills[1].first*3+3+curHero->secSkills[1].second-1].bitmap, 161, 276, curBack); - CSDL_Ext::printAt(CGI->abilh->levels[curHero->secSkills[1].second-1], 213, 279, GEOR13, zwykly, curBack); - CSDL_Ext::printAt(CGI->abilh->abilities[curHero->secSkills[1].first]->name, 213, 299, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->levels[curHero->secSkills[1].second-1], 213, 279, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->skillName[curHero->secSkills[1].first], 213, 299, GEOR13, zwykly, curBack); } if(curHero->secSkills.size()>=3) { blitAt(CGI->abilh->abils44->ourImages[curHero->secSkills[2].first*3+3+curHero->secSkills[2].second-1].bitmap, 18, 324, curBack); - CSDL_Ext::printAt(CGI->abilh->levels[curHero->secSkills[2].second-1], 69, 327, GEOR13, zwykly, curBack); - CSDL_Ext::printAt(CGI->abilh->abilities[curHero->secSkills[2].first]->name, 69, 347, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->levels[curHero->secSkills[2].second-1], 69, 327, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->skillName[curHero->secSkills[2].first], 69, 347, GEOR13, zwykly, curBack); } if(curHero->secSkills.size()>=4) { blitAt(CGI->abilh->abils44->ourImages[curHero->secSkills[3].first*3+3+curHero->secSkills[3].second-1].bitmap, 161, 324, curBack); - CSDL_Ext::printAt(CGI->abilh->levels[curHero->secSkills[3].second-1], 213, 327, GEOR13, zwykly, curBack); - CSDL_Ext::printAt(CGI->abilh->abilities[curHero->secSkills[3].first]->name, 213, 347, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->levels[curHero->secSkills[3].second-1], 213, 327, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->skillName[curHero->secSkills[3].first], 213, 347, GEOR13, zwykly, curBack); } if(curHero->secSkills.size()>=5) { blitAt(CGI->abilh->abils44->ourImages[curHero->secSkills[4].first*3+3+curHero->secSkills[4].second-1].bitmap, 18, 372, curBack); - CSDL_Ext::printAt(CGI->abilh->levels[curHero->secSkills[4].second-1], 69, 375, GEOR13, zwykly, curBack); - CSDL_Ext::printAt(CGI->abilh->abilities[curHero->secSkills[4].first]->name, 69, 395, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->levels[curHero->secSkills[4].second-1], 69, 375, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->skillName[curHero->secSkills[4].first], 69, 395, GEOR13, zwykly, curBack); } if(curHero->secSkills.size()>=6) { blitAt(CGI->abilh->abils44->ourImages[curHero->secSkills[5].first*3+3+curHero->secSkills[5].second-1].bitmap, 161, 372, curBack); - CSDL_Ext::printAt(CGI->abilh->levels[curHero->secSkills[5].second-1], 213, 375, GEOR13, zwykly, curBack); - CSDL_Ext::printAt(CGI->abilh->abilities[curHero->secSkills[5].first]->name, 213, 395, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->levels[curHero->secSkills[5].second-1], 213, 375, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->skillName[curHero->secSkills[5].first], 213, 395, GEOR13, zwykly, curBack); } if(curHero->secSkills.size()>=7) { blitAt(CGI->abilh->abils44->ourImages[curHero->secSkills[6].first*3+3+curHero->secSkills[6].second-1].bitmap, 18, 420, curBack); - CSDL_Ext::printAt(CGI->abilh->levels[curHero->secSkills[6].second-1], 69, 423, GEOR13, zwykly, curBack); - CSDL_Ext::printAt(CGI->abilh->abilities[curHero->secSkills[6].first]->name, 69, 443, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->levels[curHero->secSkills[6].second-1], 69, 423, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->skillName[curHero->secSkills[6].first], 69, 443, GEOR13, zwykly, curBack); } if(curHero->secSkills.size()>=8) { blitAt(CGI->abilh->abils44->ourImages[curHero->secSkills[7].first*3+3+curHero->secSkills[7].second-1].bitmap, 161, 420, curBack); - CSDL_Ext::printAt(CGI->abilh->levels[curHero->secSkills[7].second-1], 213, 423, GEOR13, zwykly, curBack); - CSDL_Ext::printAt(CGI->abilh->abilities[curHero->secSkills[7].first]->name, 213, 443, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->levels[curHero->secSkills[7].second-1], 213, 423, GEOR13, zwykly, curBack); + CSDL_Ext::printAt(CGI->generaltexth->skillName[curHero->secSkills[7].first], 213, 443, GEOR13, zwykly, curBack); } //printing special ability diff --git a/CMT.cpp b/CMT.cpp index 1e30d06c9..cbc498215 100644 --- a/CMT.cpp +++ b/CMT.cpp @@ -8,8 +8,6 @@ #include #include #include "boost/filesystem/operations.hpp" -#include -#include #include #include #include @@ -43,7 +41,6 @@ #include "client/Client.h" #include "client/CConfigHandler.h" #include "lib/Connection.h" -#include "lib/Interprocess.h" #include "lib/VCMI_Lib.h" #include @@ -54,7 +51,6 @@ extern SDL_Surface * CSDL_Ext::std32bppSurface; std::queue events; boost::mutex eventsM; TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16; -namespace intpr = boost::interprocess; void processCommand(const std::string &message, CClient *&client); #ifndef __GNUC__ int _tmain(int argc, _TCHAR* argv[]) @@ -115,15 +111,7 @@ int main(int argc, char** argv) cgi->bitmaph->init("Data" PATHSEPARATOR "H3bitmap.lod","Data"); tlog0<<"Loading .lod files: "<bitmaph,::console,logfile); - CGI->generaltexth = VLC->generaltexth; - CGI->arth = VLC->arth; - CGI->creh = VLC->creh; - CGI->townh = VLC->townh; - CGI->heroh = VLC->heroh; - CGI->objh = VLC->objh; - CGI->spellh = VLC->spellh; - CGI->dobjinfo = VLC->dobjinfo; - CGI->buildh = VLC->buildh; + CGI->setFromLib(); tlog0<<"Initializing VCMI_Lib: "<curh = new CCursorHandler; @@ -134,15 +122,13 @@ int main(int argc, char** argv) abilh->loadAbilities(); cgi->abilh = abilh; tlog0<<"\tAbility handler: "<pathf = new CPathfinder(); + tlog0<<"\tPathfinder: "<loadHeroAnim(); tlog0<<"\tMain graphics: "< animacje; - for(std::vector::iterator i = cgi->heroh->heroClasses.begin();i!=cgi->heroh->heroClasses.end();i++) - animacje.push_back(&((*i)->*(&CHeroClass::moveAnim))); - graphics->loadHeroAnim(animacje); - tlog0<<"\tHero animations: "<mush = mush; StartInfo *options = new StartInfo(cpg->runLoop()); - tmh.getDif(); - ////////////////////////SERVER STARTING///////////////////////////////////////////////// - char portc[10]; SDL_itoa(conf.cc.port,portc,10); - intpr::shared_memory_object smo(intpr::open_or_create,"vcmi_memory",intpr::read_write); - smo.truncate(sizeof(ServerReady)); - intpr::mapped_region mr(smo,intpr::read_write); - ServerReady *sr = new(mr.get_address())ServerReady(); - std::string comm = std::string(SERVER_NAME) + " " + portc + " > server_log.txt"; - boost::thread servthr(boost::bind(system,comm.c_str())); //runs server executable; //TODO: will it work on non-windows platforms? - tlog0<<"Preparing shared memory and starting server: "<pathf = new CPathfinder(); - tlog0<<"\tPathfinder: "<mode == 0) //new game { - intpr::scoped_lock slock(sr->mutex); - while(!sr->ready) + tmh.getDif(); + char portc[10]; + SDL_itoa(conf.cc.port,portc,10); + CClient::runServer(portc); + tlog0<<"Preparing shared memory and starting server: "<cond.wait(slock); + try + { + tlog0 << "Establishing connection...\n"; + c = new CConnection(conf.cc.server,portc,NAME); + } + catch(...) + { + tlog1 << "\nCannot establish connection! Retrying within 2 seconds" <mapname; + boost::algorithm::erase_last(fname,".vlgm1"); + cl.load(fname); + client = &cl; + boost::thread t(boost::bind(&CClient::run,&cl)); } - THC tlog0<<"\tConnecting to the server: "<> fname; client->save(fname); } + else if(cn=="load") + { + std::string fname; + readed >> fname; + client->load(fname); + } else if(message=="get txt") { boost::filesystem::create_directory("Extracted_txts"); @@ -305,4 +295,4 @@ void processCommand(const std::string &message, CClient *&client) { *client->serv << ui16(513) << message; } -} +} \ No newline at end of file diff --git a/CPlayerInterface.cpp b/CPlayerInterface.cpp index e28250592..d0f093ed0 100644 --- a/CPlayerInterface.cpp +++ b/CPlayerInterface.cpp @@ -646,9 +646,9 @@ void SComponent::init(Etype Type, int Subtype, int Val) oss << ((Val>0)?("+"):("-")) << Val << " " << CGI->generaltexth->primarySkillNames[Subtype]; subtitle = oss.str(); break; - case secskill44: - subtitle += CGI->abilh->levels[Val-1] + " " + CGI->abilh->abilities[Subtype]->name; - description = CGI->abilh->abilities[Subtype]->infoTexts[Val-1]; + case secskill44: case secskill: + subtitle += CGI->generaltexth->levels[Val-1] + " " + CGI->generaltexth->skillName[Subtype]; + description = CGI->generaltexth->skillInfoTexts[Subtype][Val-1]; break; case resource: description = CGI->generaltexth->allTexts[242]; diff --git a/CPreGame.cpp b/CPreGame.cpp index 9013a8702..e71af037f 100644 --- a/CPreGame.cpp +++ b/CPreGame.cpp @@ -20,6 +20,7 @@ #include #include #include +#include "lib/Connection.h" extern SDL_Surface * screen; extern SDL_Color tytulowy, tlo, zwykly ; @@ -811,12 +812,10 @@ void Options::hide() MapSel::~MapSel() { SDL_FreeSurface(bg); - for (size_t i=0; i < scenImgs.size(); ++i) { + for (size_t i=0; i < scenImgs.size(); ++i) + { SDL_FreeSurface(scenImgs[i]); - } - for (size_t i=0; i < scenList.size(); ++i) { - delete scenList[i]; - } + } delete sFlags; } int MapSel::countWL() @@ -838,9 +837,9 @@ void MapSel::printMaps(int from, int to, int at, bool abs) if (true)// { int help=-1; - for (size_t i=0; i < ourMaps.size(); ++i) + for (size_t i=0; i < curVector().size(); ++i) { - if (sizeFilter && ((ourMaps[i].width) != sizeFilter)) { + if (sizeFilter && ((curVector()[i].width) != sizeFilter)) { continue; } else { @@ -857,7 +856,7 @@ void MapSel::printMaps(int from, int to, int at, bool abs) SDL_Color nasz; for (int i=at;i ourMaps.size()-1) + if ((i-at+from) > curVector().size()-1) { SDL_Surface * scenin = CSDL_Ext::newSurface(351,25); SDL_BlitSurface(bg,&genRect(25,351,22,(i-at)*25+115),scenin,NULL); @@ -867,12 +866,12 @@ void MapSel::printMaps(int from, int to, int at, bool abs) SDL_FreeSurface(scenin); continue; } - if (sizeFilter && ((ourMaps[(i-at)+from].width) != sizeFilter)) + if (sizeFilter && ((curVector()[(i-at)+from].width) != sizeFilter)) { to++; at++; from++; - if (((i-at)+from)>ourMaps.size()-1) break; + if (((i-at)+from)>curVector().size()-1) break; else continue; } if ((i-at+from) == selected) @@ -881,10 +880,10 @@ void MapSel::printMaps(int from, int to, int at, bool abs) //SDL_Rect pier = genRect(25,351,24,126+(i*25)); SDL_BlitSurface(bg,&genRect(25,351,22,(i-at)*25+115),scenin,NULL); int temp=-1; - std::ostringstream ostr(std::ostringstream::out); ostr << ourMaps[(i-at)+from].playerAmnt << "/" << ourMaps[(i-at)+from].humenPlayers; + std::ostringstream ostr(std::ostringstream::out); ostr << curVector()[(i-at)+from].playerAmnt << "/" << curVector()[(i-at)+from].humenPlayers; CSDL_Ext::printAt(ostr.str(),6,4,GEOR13,nasz,scenin, 2); std::string temp2; - switch (ourMaps[(i-at)+from].width) + switch (curVector()[(i-at)+from].width) { case 36: temp2="S"; @@ -903,7 +902,7 @@ void MapSel::printMaps(int from, int to, int at, bool abs) break; } CSDL_Ext::printAtMiddle(temp2,50,13,GEOR13,nasz,scenin, 2); - switch (ourMaps[(i-at)+from].version) + switch (curVector()[(i-at)+from].version) { case RoE: temp=0; @@ -918,21 +917,32 @@ void MapSel::printMaps(int from, int to, int at, bool abs) temp=3; break; } - blitAt(Dtypes->ourImages[temp].bitmap,67,2,scenin); - if (!(ourMaps[(i-at)+from].name.length())) - ourMaps[(i-at)+from].name = "Unnamed"; - CSDL_Ext::printAtMiddle(ourMaps[(i-at)+from].name,192,13,GEOR13,nasz,scenin, 2); - if (ourMaps[(i-at)+from].victoryCondition.condition == winStandard) + if (temp >= 0) + blitAt(Dtypes->ourImages[temp].bitmap,67,2,scenin); + else + tlog2 << "Warning: " << curVector()[(i-at)+from].filename << " has wrong version!\n"; + + if(CPG->fromnewgame) + { + if (!(curVector()[(i-at)+from].name.length())) + curVector()[(i-at)+from].name = "Unnamed"; + CSDL_Ext::printAtMiddle(curVector()[(i-at)+from].name,192,13,GEOR13,nasz,scenin, 2); + } + else + { + CSDL_Ext::printAtMiddle(curVector()[(i-at)+from].filename,192,13,GEOR13,nasz,scenin, 2); + } + if (curVector()[(i-at)+from].victoryCondition.condition == winStandard) temp=11; else - temp=ourMaps[(i-at)+from].victoryCondition.condition; + temp=curVector()[(i-at)+from].victoryCondition.condition; blitAt(Dvic->ourImages[temp].bitmap,285,2,scenin); - if (ourMaps[(i-at)+from].lossCondition.typeOfLossCon == lossStandard) + if (curVector()[(i-at)+from].lossCondition.typeOfLossCon == lossStandard) temp=3; else - temp=ourMaps[(i-at)+from].lossCondition.typeOfLossCon; + temp=curVector()[(i-at)+from].lossCondition.typeOfLossCon; blitAt(Dloss->ourImages[temp].bitmap,318,2,scenin); @@ -944,9 +954,9 @@ void MapSel::printMaps(int from, int to, int at, bool abs) int MapSel::whichWL(int nr) { int help=-1; - for (int i=0;i &pliczkiTemp, int &index) } } +void MapSel::processGames( std::vector &pliczkiTemp, int &index ) +{ + ourGames.resize(pliczkiTemp.size()); + + for(int i=0; i> sign >> static_cast(ourGames[i]); + ourGames[i].filename = pliczkiTemp[i]; + ourGames[i].countPlayers(); + } +} void MapSel::init() { //get map files names @@ -1146,16 +1169,29 @@ void MapSel::init() std::sort(ourMaps.begin(),ourMaps.end(),mapSorter(_name)); slid = new Slider(375,92,480,ourMaps.size(),18,true); slid->fun = boost::bind(&CPreGame::printMapsFrom,CPG,_1); + + group.join_all(); + pliczkiTemp.clear(); + tie = fs::path( (fs::initial_path())/"/Games" ); + for ( fs::directory_iterator dir (tie); dir!=end_iter; ++dir ) + { + if (fs::is_regular_file(dir->status())); + { + if (boost::ends_with(dir->path().filename(),".vlgm1")) + pliczkiTemp.push_back("Games/"+(dir->path().leaf())); + } + } + processGames(pliczkiTemp,mapInd); } void MapSel::moveByOne(bool up) { int help=selected; if (up) selected--; else selected ++; - for (int i=selected;i=0;) + for (int i=selected;i=0;) { help=i; - if (!(sizeFilter && ((ourMaps[i].width) != sizeFilter))) + if (!(sizeFilter && ((curVector()[i].width) != sizeFilter))) break; if (up) { @@ -1172,9 +1208,11 @@ void MapSel::moveByOne(bool up) } void MapSel::select(int which, bool updateMapsList, bool forceSettingsUpdate) { + if(which < 0) + return; bool dontSaveSettings = ((selected!=which) || (CPG->ret.playerInfos.size()==0) || forceSettingsUpdate); selected = which; - CPG->ret.mapname = ourMaps[selected].filename; + CPG->ret.mapname = curVector()[selected].filename; if(updateMapsList) printMaps(slid->whereAreWe,18,0,true); int serialC=0; @@ -1184,7 +1222,9 @@ void MapSel::select(int which, bool updateMapsList, bool forceSettingsUpdate) bool wasntpl = true; for (int i=0;igeneraltexth->allTexts[434]; //Player pset.human = true; @@ -1211,7 +1251,7 @@ void MapSel::select(int which, bool updateMapsList, bool forceSettingsUpdate) for (int j=0;j=0) pset.castle=-1; @@ -1220,16 +1260,20 @@ void MapSel::select(int which, bool updateMapsList, bool forceSettingsUpdate) } } pset.heroPortrait=-1; - if (!((ourMaps[which].players[i].generateHeroAtMainTown && ourMaps[which].players[i].hasMainTown) || ourMaps[which].players[i].p8)) + if (! + ((curVector()[which].players[i].generateHeroAtMainTown + && curVector()[which].players[i].hasMainTown) + || curVector()[which].players[i].p8) + ) pset.hero=-2; else pset.hero=-1; - if(ourMaps[which].players[i].mainHeroName.length()) + if(curVector()[which].players[i].mainHeroName.length()) { - pset.heroName = ourMaps[which].players[i].mainHeroName; - if((pset.heroPortrait = ourMaps[which].players[i].mainHeroPortrait)==255) - pset.heroPortrait = ourMaps[which].players[i].p9; + pset.heroName = curVector()[which].players[i].mainHeroName; + if((pset.heroPortrait = curVector()[which].players[i].mainHeroPortrait)==255) + pset.heroPortrait = curVector()[which].players[i].p9; } pset.handicap=0; CPG->ret.playerInfos.push_back(pset); @@ -1245,9 +1289,12 @@ void MapSel::printSelectedInfo() { SDL_BlitSurface(CPG->ourScenSel->scenInf,&genRect(399,337,17,23),screen,&genRect(399,337,413,29)); SDL_BlitSurface(CPG->ourScenSel->scenInf,&genRect(50,91,18,447),screen,&genRect(50,91,414,453)); - SDL_BlitSurface(CPG->ourScenSel->bScens.imgs->ourImages[0].bitmap,NULL,screen,&CPG->ourScenSel->bScens.pos); - SDL_BlitSurface(CPG->ourScenSel->bOptions.imgs->ourImages[0].bitmap,NULL,screen,&CPG->ourScenSel->bOptions.pos); - SDL_BlitSurface(CPG->ourScenSel->bRandom.imgs->ourImages[0].bitmap,NULL,screen,&CPG->ourScenSel->bRandom.pos); + if(CPG->fromnewgame) + { + SDL_BlitSurface(CPG->ourScenSel->bScens.imgs->ourImages[0].bitmap,NULL,screen,&CPG->ourScenSel->bScens.pos); + SDL_BlitSurface(CPG->ourScenSel->bOptions.imgs->ourImages[0].bitmap,NULL,screen,&CPG->ourScenSel->bOptions.pos); + SDL_BlitSurface(CPG->ourScenSel->bRandom.imgs->ourImages[0].bitmap,NULL,screen,&CPG->ourScenSel->bRandom.pos); + } //blit texts CSDL_Ext::printAt(CGI->generaltexth->zelp[21].second,420,25,GEOR13); CSDL_Ext::printAt(CGI->generaltexth->allTexts[496],420,135,GEOR13); @@ -1256,30 +1303,32 @@ void MapSel::printSelectedInfo() CSDL_Ext::printAt(CGI->generaltexth->allTexts[390],420,406,GEOR13,zwykly); CSDL_Ext::printAt(CGI->generaltexth->allTexts[391],585,406,GEOR13,zwykly); - int temp = ourMaps[selected].victoryCondition.condition+1; + CMapInfo &selMap = selectedMap(); + + int temp = selMap.victoryCondition.condition+1; if (temp>20) temp=0; std::string sss = CGI->generaltexth->victoryConditions[temp]; - if (temp && ourMaps[selected].victoryCondition.allowNormalVictory) sss+= "/" + CGI->generaltexth->victoryConditions[0]; + if (temp && selMap.victoryCondition.allowNormalVictory) sss+= "/" + CGI->generaltexth->victoryConditions[0]; CSDL_Ext::printAt(sss,452,310,GEOR13,zwykly); - temp = ourMaps[selected].lossCondition.typeOfLossCon+1; + temp = selMap.lossCondition.typeOfLossCon+1; if (temp>20) temp=0; sss = CGI->generaltexth->lossCondtions[temp]; CSDL_Ext::printAt(sss,452,370,GEOR13,zwykly); //blit descrption - std::vector desc = *CMessage::breakText(ourMaps[selected].description,50); + std::vector desc = *CMessage::breakText(selMap.description,50); for (int i=0;i= ourMaps.size())) return; - if (ourMaps[selected].name.length()) - CSDL_Ext::printAt(ourMaps[selected].name,420,41,GEORXX); + if (selMap.name.length()) + CSDL_Ext::printAt(selMap.name,420,41,GEORXX); else CSDL_Ext::printAt("Unnamed",420,41,GEORXX); std::string diff; - switch (ourMaps[selected].difficulty) + switch (selMap.difficulty) { case 0: diff=gdiff(CGI->generaltexth->zelp[24].second); @@ -1298,7 +1347,7 @@ void MapSel::printSelectedInfo() break; } temp=-1; - switch (ourMaps[selected].width) + switch (selMap.width) { case 36: temp=0; @@ -1317,10 +1366,10 @@ void MapSel::printSelectedInfo() break; } blitAt(Dsizes->ourImages[temp].bitmap,714,28); - temp = ourMaps[selected].victoryCondition.condition; + temp = selMap.victoryCondition.condition; if (temp>12) temp=11; blitAt(Dvic->ourImages[temp].bitmap,420,308); //v - temp=ourMaps[selected].lossCondition.typeOfLossCon; + temp=selMap.lossCondition.typeOfLossCon; if (temp>12) temp=3; blitAt(Dloss->ourImages[temp].bitmap,420,366); //l @@ -1331,15 +1380,16 @@ void MapSel::printSelectedInfo() } void MapSel::printFlags() { + CMapInfo &selMap = selectedMap(); int hy=405, fx=460, ex=640, myT; - if (ourMaps[selected].howManyTeams) - myT = ourMaps[selected].players[CPG->playerColor].team; + if (selMap.howManyTeams) + myT = selMap.players[CPG->playerColor].team; else myT = -1; for (int i=0;iret.playerInfos.size();i++) { if (myT>=0) { - if(ourMaps[selected].players[CPG->ret.playerInfos[i].color].team==myT) + if(selMap.players[CPG->ret.playerInfos[i].color].team==myT) { blitAtWR(sFlags->ourImages[CPG->ret.playerInfos[i].color].bitmap,fx,hy); fx+=sFlags->ourImages[CPG->ret.playerInfos[i].color].bitmap->w; @@ -1376,6 +1426,23 @@ std::string MapSel::gdiff(std::string ss) } return ret; } + +CMapInfo & MapSel::selectedMap() +{ + if(CPG->fromnewgame) + return ourMaps[selected]; + else + return ourGames[selected]; +} + +std::vector & MapSel::curVector() +{ + + if (CPG->fromnewgame) + return ourMaps; + else + return ourGames; +} void CPreGame::printRating() { SDL_BlitSurface(CPG->ourScenSel->scenInf,&genRect(47,83,271,449),screen,&genRect(47,83,666,455)); @@ -1460,6 +1527,7 @@ void CPreGame::initScenSel() void CPreGame::showScenSel() { state=ScenarioList; + ourScenSel->mapsel.slid->positionsAmnt = ourScenSel->mapsel.curVector().size(); SDL_BlitSurface(ourScenSel->background,NULL,screen,NULL); SDL_BlitSurface(ourScenSel->scenInf,NULL,screen,&genRect(ourScenSel->scenInf->h,ourScenSel->scenInf->w,396,6)); CSDL_Ext::printAt(CGI->generaltexth->allTexts[494],427,438,GEOR13);//"Map Diff:" @@ -1482,14 +1550,19 @@ void CPreGame::showScenSel() //add buttons info if(first) { - btns.push_back(&ourScenSel->bEasy); - btns.push_back(&ourScenSel->bNormal); - btns.push_back(&ourScenSel->bHard); - btns.push_back(&ourScenSel->bExpert); - btns.push_back(&ourScenSel->bImpossible); - btns.push_back(&ourScenSel->bScens); - btns.push_back(&ourScenSel->bRandom); - btns.push_back(&ourScenSel->bOptions); + if(fromnewgame) + { + btns.push_back(&ourScenSel->bEasy); + btns.push_back(&ourScenSel->bNormal); + btns.push_back(&ourScenSel->bHard); + btns.push_back(&ourScenSel->bExpert); + btns.push_back(&ourScenSel->bImpossible); + btns.push_back(&ourScenSel->bScens); + btns.push_back(&ourScenSel->bRandom); + btns.push_back(&ourScenSel->bOptions); + } + else + ourScenSel->mapsel.show(); btns.push_back(&ourScenSel->bBegin); btns.push_back(&ourScenSel->bBack); @@ -1583,12 +1656,18 @@ void CPreGame::initNewMenu() } void CPreGame::showNewMenu() { + if(state == ScenarioList && !fromnewgame) + { + showLoadMenu(); + return; + } if (currentTab/*==&ourScenSel->mapsel*/) currentTab->hide(); btns.clear(); interested.clear(); handleOther=NULL; state = newGame; + fromnewgame = true; SDL_BlitSurface(ourNewMenu->background,NULL,screen,NULL); SDL_BlitSurface(ourNewMenu->newGame->ourImages[0].bitmap,NULL,screen,&ourNewMenu->lNewGame); SDL_BlitSurface(ourNewMenu->loadGame->ourImages[0].bitmap,NULL,screen,&ourNewMenu->lLoadGame); @@ -2120,6 +2199,7 @@ StartInfo CPreGame::runLoop() CGI->curh->draw2(); SDL_Delay(20); //give time for other apps } + ret.mode = !fromnewgame; return ret; } std::string CPreGame::buttonText(int which) @@ -2233,6 +2313,7 @@ void CPreGame::showLoadMenu() interested.clear(); handleOther=NULL; state = loadGame; + fromnewgame = false; SDL_BlitSurface(ourLoadMenu->background,NULL,screen,NULL); SDL_BlitSurface(ourLoadMenu->newGame->ourImages[0].bitmap,NULL,screen,&ourLoadMenu->lNewGame); SDL_BlitSurface(ourLoadMenu->loadGame->ourImages[0].bitmap,NULL,screen,&ourLoadMenu->lLoadGame); diff --git a/CPreGame.h b/CPreGame.h index 718f717ee..d182c48df 100644 --- a/CPreGame.h +++ b/CPreGame.h @@ -187,7 +187,6 @@ public: CDefHandler * Dtypes, * Dvic; CDefHandler *Dsizes, * Dloss, * sFlags; - std::vector scenList; std::vector scenImgs; //int current; std::vector ourMaps; @@ -208,6 +207,9 @@ public: void printSelectedInfo(); void printFlags(); void processMaps(std::vector &pliczkiTemp, int &index); + void processGames(std::vector &pliczkiTemp, int &index); + CMapInfo &selectedMap(); + std::vector &curVector(); MapSel(); ~MapSel(); }; @@ -241,6 +243,7 @@ public: StartInfo ret; bool run; bool first; //hasn't we showed the scensel + bool fromnewgame; std::vector interested; CMusicHandler * mush; std::vector btns; @@ -259,7 +262,7 @@ public: ttt fNewGame, fLoadGame, fHighScores, fCredits, fQuit; int highlighted;//0=none; 1=new game; 2=load game; 3=high score; 4=credits; 5=quit } * ourMainMenu, * ourNewMenu, * ourLoadMenu; - ScenSel * ourScenSel; + ScenSel *ourScenSel; Options * ourOptions; std::string map; //selected map CPreGame(); //c-tor diff --git a/ChangeLog b/ChangeLog index 5caa21fdd..288911cbf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -0.64 -> 0.next (???) [as for r672] +0.64 -> 0.next (???) [as for r679] GENERAL: * move some settings to the config/settings.txt file * partial support for new screen resolutions @@ -7,6 +7,7 @@ GENERAL: * support for non-standard screen resolutions ADVENTURE INTERFACE: +* smooth map scrolling on hero movement * added water animation * speed of scrolling map and hero movement can be adjusted in the System Options Window @@ -44,6 +45,11 @@ BATTLES AI PLAYER: * Genius AI (first VCMI AI) will control computer creatures during the combat. +OBJECTS: +* Guardians property for resources is handled +* support for Witch Hut +* support for Arena + And a lot of minor fixes 0.63 -> 0.64 (Nov 01 2008) diff --git a/StartInfo.h b/StartInfo.h index 82c5e49e4..50f7954ff 100644 --- a/StartInfo.h +++ b/StartInfo.h @@ -18,7 +18,7 @@ struct StartInfo ui8 serial; ui8 handicap;//0-no, 1-mild, 2-severe std::string name; - bool human; + ui8 human; template void serialize(Handler &h, const int version) { h & castle; @@ -33,6 +33,7 @@ struct StartInfo h & human; } }; + ui8 mode; //0 - new game; 1 - load game si32 difficulty; //0=easy; 4=impossible std::vector playerInfos; ui8 turnTime; //in minutes, 0=unlimited @@ -48,6 +49,7 @@ struct StartInfo } template void serialize(Handler &h, const int version) { + h & mode; h & difficulty; h & playerInfos; h & turnTime; diff --git a/client/Client.cpp b/client/Client.cpp index b3904b618..bb0340dc0 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -5,9 +5,15 @@ #include "../CPlayerInterface.h" #include "../StartInfo.h" #include "../hch/CArtHandler.h" +#include "../hch/CDefObjInfoHandler.h" #include "../hch/CGeneralTextHandler.h" +#include "../hch/CHeroHandler.h" +#include "../hch/CTownHandler.h" #include "../hch/CObjectHandler.h" +#include "../hch/CBuildingHandler.h" +#include "../hch/CSpellHandler.h" #include "../lib/Connection.h" +#include "../lib/Interprocess.h" #include "../lib/NetPacks.h" #include "../lib/VCMI_Lib.h" #include "../map.h" @@ -20,75 +26,19 @@ #include #include CSharedCond > mess(new std::set); +extern std::string NAME; +namespace intpr = boost::interprocess; +SharedMem sm; CClient::CClient(void) { + serv = NULL; + gs = NULL; + cb = NULL; } CClient::CClient(CConnection *con, StartInfo *si) - :serv(con) -{ - timeHandler tmh; - IObjectInterface::cb = this; - CGI->state = new CGameState(); - tlog0 <<"\tGamestate: "<> pom8; - if(pom8) throw "Server cannot open the map!"; - c << ui8(si->playerInfos.size()+1); //number of players + neutral - for(size_t i=0;iplayerInfos.size();i++) { - c << ui8(si->playerInfos[i].color); //players - } - c << ui8(255); // neutrals - - - ui32 seed, sum; - std::string mapname; - c >> mapname >> sum >> seed; - tlog0 <<"\tSending/Getting info to/from the server: "<checksum << std::endl; - - if(mapa->checksum != sum) - { - tlog1 << "Wrong map checksum!!!" << std::endl; - throw std::string("Wrong checksum"); - } - tlog0 << "\tUsing random seed: "<state; - gs->scenarioOps = si; - gs->init(si,mapa,seed); - - CGI->mh = new CMapHandler(); - tlog0 <<"Initializing GameState (together): "<mh->map = mapa; - tlog0 <<"Creating mapHandler: "<mh->init(); - tlog0 <<"Initializing mapHandler (together): "<state->scenarioOps->playerInfos.size();++i) //initializing interfaces for players - { - ui8 color = gs->scenarioOps->playerInfos[i].color; - CCallback *cb = new CCallback(gs,color,this); - if(!gs->scenarioOps->playerInfos[i].human) { - playerint[color] = static_cast(CAIHandler::getNewAI(cb,conf.cc.defaultAI)); - } - else { - playerint[color] = new CPlayerInterface(color,i); - } - gs->currentPlayer = color; - playerint[color]->init(cb); - } - playerint[255] = CAIHandler::getNewAI(cb,conf.cc.defaultAI); - playerint[255]->init(new CCallback(gs,255,this)); - +{ + newGame(con,si); } CClient::~CClient(void) { @@ -634,10 +584,13 @@ void CClient::run() void CClient::close() { + if(!serv) + return; + tlog3 << "Connection has been requested to be closed.\n"; boost::unique_lock(*serv->wmx); *serv << ui16(99); - tlog3 << "Sended closing signal to the server\n"; + tlog3 << "Sent closing signal to the server\n"; serv->close(); tlog3 << "Our socket has been closed.\n"; } @@ -647,6 +600,96 @@ void CClient::save(const std::string & fname) *serv << ui16(98) << fname; } +void CClient::load( const std::string & fname ) +{ + tlog0 <<"\n\nLoading procedure started!\n\n"; + + timeHandler tmh; + close(); //kill server + tlog0 <<"Sent kill signal to the server: "<clear(); //delete old handlers + delete CGI->mh; + delete CGI->state; + //TODO: del callbacks + + for(std::map::iterator i = playerint.begin(); i!=playerint.end(); i++) + { + delete i->second; //delete player interfaces + } + tlog0 <<"Deleting old data: "<mh = new CMapHandler(); + + CLoadFile lf(fname + ".vlgm1"); + lf >> sig >> dum; + tlog0 <<"Reading save signature: "<> *VLC; + CGI->setFromLib(); + tlog0 <<"Reading handlers: "<> gs; + tlog0 <<"Reading gamestate: "<state = gs; + CGI->mh->map = gs->map; + CGI->mh->init(); + tlog0 <<"Initing maphandler: "<> pom8; + if(pom8) + throw "Server cannot open the savegame!"; + else + tlog0 << "Server opened savegame properly.\n"; + + *serv << ui8(gs->scenarioOps->playerInfos.size()+1); //number of players + neutral + for(size_t i=0;iscenarioOps->playerInfos.size();i++) + { + *serv << ui8(gs->scenarioOps->playerInfos[i].color); //players + } + *serv << ui8(255); // neutrals + tlog0 <<"Sent info to server: "<scenarioOps->playerInfos.size();++i) //initializing interfaces for players + { + ui8 color = gs->scenarioOps->playerInfos[i].color; + CCallback *cb = new CCallback(gs,color,this); + if(!gs->scenarioOps->playerInfos[i].human) { + playerint[color] = static_cast(CAIHandler::getNewAI(cb,conf.cc.defaultAI)); + } + else { + playerint[color] = new CPlayerInterface(color,i); + } + gs->currentPlayer = color; + playerint[color]->init(cb); + tlog0 <<"Setting up interface for player "<< (int)color <<": "<init(new CCallback(gs,255,this)); + tlog0 <<"Setting up interface for neutral \"player\"" << tmh.getDif() << std::endl; + + +} + int CClient::getCurrentPlayer() { return gs->currentPlayer; @@ -655,4 +698,92 @@ int CClient::getCurrentPlayer() int CClient::getSelectedHero() { return IGameCallback::getSelectedHero(getCurrentPlayer())->id; +} + +void CClient::newGame( CConnection *con, StartInfo *si ) +{ + timeHandler tmh; + IObjectInterface::cb = this; + CGI->state = new CGameState(); + tlog0 <<"\tGamestate: "<> pom8; + if(pom8) + throw "Server cannot open the map!"; + else + tlog0 << "Server opened map properly.\n"; + c << ui8(si->playerInfos.size()+1); //number of players + neutral + for(size_t i=0;iplayerInfos.size();i++) + { + c << ui8(si->playerInfos[i].color); //players + } + c << ui8(255); // neutrals + + + ui32 seed, sum; + std::string mapname; + c >> mapname >> sum >> seed; + tlog0 <<"\tSending/Getting info to/from the server: "<checksum << std::endl; + + if(mapa->checksum != sum) + { + tlog1 << "Wrong map checksum!!!" << std::endl; + throw std::string("Wrong checksum"); + } + tlog0 << "\tUsing random seed: "<state; + gs->scenarioOps = si; + gs->init(si,mapa,seed); + + CGI->mh = new CMapHandler(); + tlog0 <<"Initializing GameState (together): "<mh->map = mapa; + tlog0 <<"Creating mapHandler: "<mh->init(); + tlog0 <<"Initializing mapHandler (together): "<state->scenarioOps->playerInfos.size();++i) //initializing interfaces for players + { + ui8 color = gs->scenarioOps->playerInfos[i].color; + CCallback *cb = new CCallback(gs,color,this); + if(!gs->scenarioOps->playerInfos[i].human) { + playerint[color] = static_cast(CAIHandler::getNewAI(cb,conf.cc.defaultAI)); + } + else { + playerint[color] = new CPlayerInterface(color,i); + } + gs->currentPlayer = color; + playerint[color]->init(cb); + } + playerint[255] = CAIHandler::getNewAI(cb,conf.cc.defaultAI); + playerint[255]->init(new CCallback(gs,255,this)); +} + +void CClient::runServer(const char * portc) +{ + static std::string comm = std::string(SERVER_NAME) + " " + portc + " > server_log.txt"; //needs to be static, if not - will be probably destroyed before new thread reads it + boost::thread servthr(boost::bind(system,comm.c_str())); //runs server executable; //TODO: will it work on non-windows platforms? +} + +void CClient::waitForServer() +{ + { + intpr::scoped_lock slock(sm.sr->mutex); + while(!sm.sr->ready) + { + sm.sr->cond.wait(slock); + } + } + intpr::shared_memory_object::remove("vcmi_memory"); } \ No newline at end of file diff --git a/client/Client.h b/client/Client.h index 4cd183e84..f82a4bcdd 100644 --- a/client/Client.h +++ b/client/Client.h @@ -51,7 +51,9 @@ public: ~CClient(void); void close(); + void newGame(CConnection *con, StartInfo *si); //con - connection to server void save(const std::string & fname); + void load(const std::string & fname); void process(int what); void run(); ////////////////////////////////////////////////////////////////////////// @@ -67,6 +69,7 @@ public: void setHoverName(int objid, MetaString * name){}; void setObjProperty(int objid, int prop, int val){}; void changePrimSkill(int ID, int which, int val, bool abs=false){}; + void changeSecSkill(int ID, int which, int val, bool abs=false){}; void showInfoDialog(InfoWindow *iw){}; void showYesNoDialog(YesNoDialog *iw, const CFunctionList &callback){}; void showSelectionDialog(SelectionDialog *iw, const CFunctionList &callback){}; //returns question id @@ -82,6 +85,10 @@ public: ////////////////////////////////////////////////////////////////////////// friend class CCallback; //handling players actions friend void processCommand(const std::string &message, CClient *&client); //handling console + + + static void runServer(const char * portc); + static void waitForServer(); }; #endif // __CLIENT_H__ diff --git a/client/Graphics.cpp b/client/Graphics.cpp index 81cd1ae22..1f8a171de 100644 --- a/client/Graphics.cpp +++ b/client/Graphics.cpp @@ -275,31 +275,32 @@ void Graphics::loadHeroPortraits() } of.close(); } -void Graphics::loadHeroAnim(std::vector & anims) +void Graphics::loadHeroAnim() { + heroAnims.resize(F_NUMBER * 2); std::vector > rotations; //first - group number to be rotated1, second - group number after rotation1 rotations += std::make_pair(6,10), std::make_pair(7,11), std::make_pair(8,12), std::make_pair(1,13), std::make_pair(2,14), std::make_pair(3,15); - for(size_t i=0; iourImages[o].groupNumber==rotations[p].first) + if(heroAnims[i]->ourImages[o].groupNumber==rotations[p].first) { for(int e=0; e<8; ++e) { Cimage nci; - nci.bitmap = CSDL_Ext::rotate01((*anims[i])->ourImages[o+e].bitmap); + nci.bitmap = CSDL_Ext::rotate01(heroAnims[i]->ourImages[o+e].bitmap); nci.groupNumber = rotations[p].second; nci.imName = std::string(); - (*anims[i])->ourImages.push_back(nci); + heroAnims[i]->ourImages.push_back(nci); if(pom>2) //we need only one frame for groups 13/14/15 break; } @@ -313,11 +314,11 @@ void Graphics::loadHeroAnim(std::vector & anims) } } } - for(size_t ff=0; ff<(*anims[i])->ourImages.size(); ++ff) + for(size_t ff=0; ffourImages.size(); ++ff) { - CSDL_Ext::alphaTransform((*anims[i])->ourImages[ff].bitmap); + CSDL_Ext::alphaTransform(heroAnims[i]->ourImages[ff].bitmap); } - (*anims[i])->alphaTransformed = true; + heroAnims[i]->alphaTransformed = true; } } diff --git a/client/Graphics.h b/client/Graphics.h index 4f08eb23f..28ee1f13b 100644 --- a/client/Graphics.h +++ b/client/Graphics.h @@ -36,6 +36,7 @@ public: CDefHandler * un44; //many things CDefHandler * smallIcons, *resources32; //resources 32x32 CDefHandler * flags; + std::vector heroAnims; // [class id: 0 - 17] //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing //creatures std::map smallImgs; //creature ID -> small 32x32 img of creature; //ID=-2 is for blank (black) img; -1 for the border std::map bigImgs; //creature ID -> big 58x64 img of creature; //ID=-2 is for blank (black) img; -1 for the border @@ -53,7 +54,7 @@ public: void loadPaletteAndColors(); void loadHeroFlags(); void loadHeroFlags(std::pair Graphics::*, std::vector > &pr, bool mode); - void loadHeroAnim(std::vector & anims); + void loadHeroAnim(); void loadHeroPortraits(); SDL_Surface * drawHeroInfoWin(const CGHeroInstance * curh); SDL_Surface * drawPrimarySkill(const CGHeroInstance *curh, SDL_Surface *ret, int from=0, int to=PRIMARY_SKILLS); diff --git a/hch/CAbilityHandler.cpp b/hch/CAbilityHandler.cpp index 85c79c7c8..6d78c4cb5 100644 --- a/hch/CAbilityHandler.cpp +++ b/hch/CAbilityHandler.cpp @@ -7,34 +7,8 @@ void CAbilityHandler::loadAbilities() { - std::string buf = CGI->bitmaph->getTextFile("SSTRAITS.TXT"); - int it=0; - std::string dump; - for(int i=0; i<2; ++i) - { - loadToIt(dump,buf,it,3); - } - for (int i=0; iinfoTexts.resize(3); - loadToIt(nab->name,buf,it,4); - loadToIt(nab->infoTexts[0],buf,it,4); - loadToIt(nab->infoTexts[1],buf,it,4); - loadToIt(nab->infoTexts[2],buf,it,3); - nab->idNumber = abilities.size(); - abilities.push_back(nab); - } abils32 = CDefHandler::giveDef("SECSK32.DEF"); abils44 = CDefHandler::giveDef("SECSKILL.DEF"); abils82 = CDefHandler::giveDef("SECSK82.DEF"); - buf = CGI->bitmaph->getTextFile("SKILLLEV.TXT"); - it=0; - for(int i=0; i<6; ++i) - { - std::string buffo; - loadToIt(buffo,buf,it,3); - levels.push_back(buffo); - } } \ No newline at end of file diff --git a/hch/CAbilityHandler.h b/hch/CAbilityHandler.h index feb0ce61c..74a08080a 100644 --- a/hch/CAbilityHandler.h +++ b/hch/CAbilityHandler.h @@ -9,8 +9,6 @@ class CDefHandler; class CAbility { public: - std::string name; - std::vector infoTexts; //0 - basic; 2 - advanced int idNumber; bool isAllowed; //true if we can use this hero's ability (map information) }; @@ -20,7 +18,6 @@ class CAbilityHandler public: std::vector abilities; CDefHandler * abils32, * abils44, * abils82; - std::vector levels; void loadAbilities(); }; diff --git a/hch/CBuildingHandler.cpp b/hch/CBuildingHandler.cpp index 0a1308734..d047eddfc 100644 --- a/hch/CBuildingHandler.cpp +++ b/hch/CBuildingHandler.cpp @@ -14,11 +14,8 @@ unsigned int readNr(std::string &in, int &it) if(in[last]=='\t' || in[last]=='\n' || in[last]==' ' || in[last]=='\r' || in[last]=='\n') break; if(last==in.size()) -#ifndef __GNUC__ - throw new std::exception("Cannot read number..."); -#else - throw new std::exception(); -#endif + throw std::string("Cannot read number..."); + std::stringstream ss(in.substr(it,last-it)); it+=(1+last-it); ss >> last; @@ -131,6 +128,12 @@ void CBuildingHandler::loadBuildings() } +CBuildingHandler::~CBuildingHandler() +{ + for(std::map >::iterator i=buildings.begin(); i!=buildings.end(); i++) + for(std::map::iterator j=i->second.begin(); j!=i->second.end(); j++) + delete j->second; +} const std::string & CBuilding::Name() { if(name.length()) diff --git a/hch/CBuildingHandler.h b/hch/CBuildingHandler.h index 24513abe1..48cfe8b89 100644 --- a/hch/CBuildingHandler.h +++ b/hch/CBuildingHandler.h @@ -28,6 +28,7 @@ public: std::map > > > > hall; //map >[5]> - external vector is the vector of buildings in the row, internal is the list of buildings for the specific slot void loadBuildings(); //main loader + ~CBuildingHandler(); template void serialize(Handler &h, const int version) { diff --git a/hch/CCreatureHandler.cpp b/hch/CCreatureHandler.cpp index dc8e02d4c..30fac87ad 100644 --- a/hch/CCreatureHandler.cpp +++ b/hch/CCreatureHandler.cpp @@ -629,3 +629,7 @@ void CCreatureHandler::loadUnitAnimInfo(CCreature & unit, std::string & src, int } i+=2; } + +CCreatureHandler::~CCreatureHandler() +{ +} \ No newline at end of file diff --git a/hch/CCreatureHandler.h b/hch/CCreatureHandler.h index 4ed4fa354..2f5bffee4 100644 --- a/hch/CCreatureHandler.h +++ b/hch/CCreatureHandler.h @@ -67,6 +67,7 @@ public: void loadAnimationInfo(); void loadUnitAnimInfo(CCreature & unit, std::string & src, int & i); CCreatureHandler(); + ~CCreatureHandler(); template void serialize(Handler &h, const int version) { diff --git a/hch/CDefObjInfoHandler.cpp b/hch/CDefObjInfoHandler.cpp index 6ac3c0cae..c7a12882c 100644 --- a/hch/CDefObjInfoHandler.cpp +++ b/hch/CDefObjInfoHandler.cpp @@ -18,6 +18,7 @@ bool CGDefInfo::isVisitable() } CGDefInfo::CGDefInfo() { + handler = NULL; serial = -1; visitDir = (8|16|32|64|128); //4,5,6,7,8 - any not-from-up direction } @@ -76,4 +77,11 @@ void CDefObjInfoHandler::load() if(nobj->id==98) castles[nobj->subid]=nobj; } +} + +CDefObjInfoHandler::~CDefObjInfoHandler() +{ + for(std::map >::iterator i=gobjs.begin(); i!=gobjs.end(); i++) + for(std::map::iterator j=i->second.begin(); j!=i->second.end(); j++) + delete j->second; } \ No newline at end of file diff --git a/hch/CDefObjInfoHandler.h b/hch/CDefObjInfoHandler.h index 7ff1cbab0..07ab2f5f8 100644 --- a/hch/CDefObjInfoHandler.h +++ b/hch/CDefObjInfoHandler.h @@ -41,8 +41,9 @@ class DLL_EXPORT CDefObjInfoHandler public: std::map > gobjs; std::map castles; - void load(); + void load(); + ~CDefObjInfoHandler(); template void serialize(Handler &h, const int version) { diff --git a/hch/CGeneralTextHandler.cpp b/hch/CGeneralTextHandler.cpp index cb5d940ef..fb7dcc4b7 100644 --- a/hch/CGeneralTextHandler.cpp +++ b/hch/CGeneralTextHandler.cpp @@ -16,88 +16,6 @@ std::string readTo(std::string &in, int &it, char end) return in.substr(pom,last-pom); } void CGeneralTextHandler::load() -{ - std::string buf = bitmaph->getTextFile("GENRLTXT.TXT"), tmp; - int andame = buf.size(); - int i=0; //buf iterator - for(i; igetTextFile("ARRAYTXT.TXT"); - - int itr=0; - while(itrgetTextFile("PRISKILL.TXT"); - for(int hh=0; hh<4; ++hh) - { - loadToIt(tmp, strin, itr, 3); - primarySkillNames.push_back(tmp); - } - - itr = 0; - std::string strin2 = bitmaph->getTextFile("JKTEXT.TXT"); - for(int hh=0; hh<45; ++hh) - { - loadToIt(tmp, strin2, itr, 3); - jktexts.push_back(tmp); - } - - itr = 0; - std::string strin3 = bitmaph->getTextFile("HEROSCRN.TXT"); - for(int hh=0; hh<33; ++hh) - { - loadToIt(tmp, strin3, itr, 3); - heroscrn.push_back(tmp); - } - - strin3 = bitmaph->getTextFile("ARTEVENT.TXT"); - for(itr = 0; itrgetTextFile("ZELP.TXT"); int itr=0, eol=-1, eolnext=-1, pom; @@ -335,7 +253,7 @@ void CGeneralTextHandler::loadTexts() loadToIt(temp,buf,it,3); restypes.push_back(temp); } - + tlog5 << "\t\tReading ZCRGN1 \n"; buf = bitmaph->getTextFile("ZCRGN1.TXT"); it=0; @@ -344,4 +262,115 @@ void CGeneralTextHandler::loadTexts() loadToIt(temp,buf,it,3); creGens.push_back(temp); } + + buf = bitmaph->getTextFile("GENRLTXT.TXT"); + std::string tmp; + andame = buf.size(); + i=0; //buf iterator + for(i; igetTextFile("ARRAYTXT.TXT"); + + itr=0; + while(itrgetTextFile("PRISKILL.TXT"); + for(int hh=0; hh<4; ++hh) + { + loadToIt(tmp, strin, itr, 3); + primarySkillNames.push_back(tmp); + } + + itr = 0; + std::string strin2 = bitmaph->getTextFile("JKTEXT.TXT"); + for(int hh=0; hh<45; ++hh) + { + loadToIt(tmp, strin2, itr, 3); + jktexts.push_back(tmp); + } + + itr = 0; + std::string strin3 = bitmaph->getTextFile("HEROSCRN.TXT"); + for(int hh=0; hh<33; ++hh) + { + loadToIt(tmp, strin3, itr, 3); + heroscrn.push_back(tmp); + } + + strin3 = bitmaph->getTextFile("ARTEVENT.TXT"); + for(itr = 0; itrgetTextFile("SSTRAITS.TXT"); + it=0; + + for(int i=0; i<2; ++i) + loadToIt(dump,buf,it,3); + + skillName.resize(SKILL_QUANTITY); + skillInfoTexts.resize(SKILL_QUANTITY); + for (int i=0; igetTextFile("SKILLLEV.TXT"); + it=0; + for(int i=0; i<6; ++i) + { + std::string buffo; + loadToIt(buffo,buf,it,3); + levels.push_back(buffo); + } +} + + +std::string CGeneralTextHandler::getTitle(std::string text) +{ + std::string ret; + int i=0; + while ((text[i++]!='{')); + while ((text[i]!='}') && (i -#include -DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode); -std::string readTo(std::string &in, int &it, char end); -class DLL_EXPORT CGeneralTextHandler //Handles general texts -{ -public: - class HeroTexts - { - public: - std::string bonusName, shortBonus, longBonus; //for special abilities - std::string biography; //biography, of course - }; - - std::vector hTxts; - std::vector allTexts; - - std::vector arraytxt; - std::vector primarySkillNames; - std::vector jktexts; - std::vector heroscrn; - - //artifacts - std::vector artifEvents; - std::vector artifNames; - std::vector artifDescriptions; - - //towns - std::vector tcommands, hcommands; //texts for town screen and town hall screen - std::vector > townNames; //[type id] => vec of names of instances - std::vector townTypes; //castle, rampart, tower, etc - std::map > > buildings; //map[town id][building id] => pair - - std::vector > zelp; - std::string lossCondtions[4]; - std::string victoryConditions[14]; +#ifndef __CGENERALTEXTHANDLER_H__ +#define __CGENERALTEXTHANDLER_H__ +#include "../global.h" +#include +#include +DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode); +std::string readTo(std::string &in, int &it, char end); +class DLL_EXPORT CGeneralTextHandler //Handles general texts +{ +public: + class HeroTexts + { + public: + std::string bonusName, shortBonus, longBonus; //for special abilities + std::string biography; //biography, of course + }; + + std::vector hTxts; + std::vector allTexts; + + std::vector arraytxt; + std::vector primarySkillNames; + std::vector jktexts; + std::vector heroscrn; + + //artifacts + std::vector artifEvents; + std::vector artifNames; + std::vector artifDescriptions; + + //towns + std::vector tcommands, hcommands; //texts for town screen and town hall screen + std::vector > townNames; //[type id] => vec of names of instances + std::vector townTypes; //castle, rampart, tower, etc + std::map > > buildings; //map[town id][building id] => pair + + std::vector > zelp; + std::string lossCondtions[4]; + std::string victoryConditions[14]; //objects std::vector names; //vector of objects; i-th object in vector has subnumber i @@ -44,16 +44,21 @@ public: std::vector advobtxt; std::vector xtrainfo; std::vector restypes; - std::vector > mines; //first - name; second - event description - - - std::string getTitle(std::string text); - std::string getDescr(std::string text); - - void loadTexts(); - void load(); -}; - - - -#endif // __CGENERALTEXTHANDLER_H__ + std::vector > mines; //first - name; second - event description + + //sec skills + std::vector skillName; + std::vector > skillInfoTexts; //[id][level] : level 0 - basic; 2 - advanced + std::vector levels; + + std::string getTitle(std::string text); + std::string getDescr(std::string text); + + void loadTexts(); + void load(); + CGeneralTextHandler(); +}; + + + +#endif // __CGENERALTEXTHANDLER_H__ diff --git a/hch/CHeroHandler.cpp b/hch/CHeroHandler.cpp index dd80b5748..236285c38 100644 --- a/hch/CHeroHandler.cpp +++ b/hch/CHeroHandler.cpp @@ -10,7 +10,6 @@ void loadToIt(std::string &dest, std::string &src, int &iter, int mode); CHeroClass::CHeroClass() { skillLimit = 8; - moveAnim = NULL; } CHeroClass::~CHeroClass() { @@ -35,7 +34,17 @@ int CHeroClass::chooseSecSkill(const std::set & possibles) const //picks se } CHeroHandler::~CHeroHandler() +{ + for (int i = 0; i < heroes.size(); i++) + delete heroes[i]; + + for (int i = 0; i < heroClasses.size(); i++) + delete heroClasses[i]; +} + +CHeroHandler::CHeroHandler() {} + void CHeroHandler::loadHeroes() { VLC->heroh = this; diff --git a/hch/CHeroHandler.h b/hch/CHeroHandler.h index 1c291355b..cbdb47472 100644 --- a/hch/CHeroHandler.h +++ b/hch/CHeroHandler.h @@ -38,7 +38,6 @@ public: std::vector proSec; //probabilities of gaining secondary skills (out of 112), in id order int selectionProbability[9]; //probability of selection in towns std::vector terrCosts; //default costs of going through terrains: dirt, sand, grass, snow, swamp, rough, subterranean, lava, water, rock; -1 means terrain is imapassable - CDefHandler * moveAnim; //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing int chooseSecSkill(const std::set & possibles) const; //picks secondary skill out from given possibilities CHeroClass(); @@ -60,11 +59,13 @@ public: unsigned int level(unsigned int experience); unsigned int reqExp(unsigned int level); + void loadHeroes(); void loadHeroClasses(); void initHeroClasses(); - ~CHeroHandler(); void initTerrainCosts(); + CHeroHandler(); + ~CHeroHandler(); template void serialize(Handler &h, const int version) { diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 81faf0b1b..a99f3a2fa 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -743,7 +743,7 @@ void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const if(visitors.find(h->id)==visitors.end()) { onNAHeroVisit(h->id, false); - if(ID != 102) //not tree + if(ID != 102 && ID!=4) //not tree nor arena cb->setObjProperty(id,4,h->id); //add to the visitors } else @@ -774,6 +774,9 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const int id=0, subid=0, ot=0, val=1; switch(ID) { + case 4: + ot = 0; + break; case 51: subid=0; ot=80; @@ -806,6 +809,16 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const { switch (ID) { + case 4: //arena + { + SelectionDialog sd; + sd.text << std::pair(11,ot); + sd.components.push_back(Component(0,0,2,0)); + sd.components.push_back(Component(0,1,2,0)); + sd.player = cb->getOwner(heroID); + cb->showSelectionDialog(&sd,boost::bind(&CGVisitableOPH::arenaSelected,this,heroID,_1)); + return; + } case 51: case 23: case 61: @@ -835,7 +848,7 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const val = VLC->heroh->reqExp(h->level+val) - VLC->heroh->reqExp(h->level); if(!ttype) { - cb->setObjProperty(id,4,heroID); //add to the visitors + cb->setObjProperty(this->id,4,heroID); //add to the visitors InfoWindow iw; iw.components.push_back(Component(id,subid,1,0)); iw.player = cb->getOwner(heroID); @@ -892,9 +905,12 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const const std::string & CGVisitableOPH::getHoverText() const { - int pom; + int pom = -1; switch(ID) { + case 4: + pom = -1; + break; case 51: pom = 8; break; @@ -914,9 +930,11 @@ const std::string & CGVisitableOPH::getHoverText() const pom = 18; break; default: - throw "Wrong CGVisitableOPH object ID!\n"; + throw std::string("Wrong CGVisitableOPH object ID!\n"); } - hoverName = VLC->generaltexth->names[ID] + " " + VLC->generaltexth->xtrainfo[pom]; + hoverName = VLC->generaltexth->names[ID]; + if(pom >= 0) + hoverName += (" " + VLC->generaltexth->xtrainfo[pom]); const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer()); if(h) { @@ -928,6 +946,12 @@ const std::string & CGVisitableOPH::getHoverText() const return hoverName; } +void CGVisitableOPH::arenaSelected( int heroID, int primSkill ) const +{ + cb->setObjProperty(id,4,heroID); //add to the visitors + cb->changePrimSkill(heroID,primSkill,2); +} + bool CArmedInstance::needsLastStack() const { return false; @@ -1053,19 +1077,38 @@ void CGResource::initObj() void CGResource::onHeroVisit( const CGHeroInstance * h ) const { - //TODO: handle guards (when battles are finished) - if(message.length()) + if(army.slots.size()) { - InfoWindow iw; - iw.player = h->tempOwner; - iw.text << message; - cb->showInfoDialog(&iw); + if(message.size()) + { + YesNoDialog ynd; + ynd.player = h->getOwner(); + ynd.text << message; + cb->showYesNoDialog(&ynd,boost::bind(&CGResource::fightForRes,this,_1,h)); + } + else + { + fightForRes(1,h); + } } + else + { + if(message.length()) + { + InfoWindow iw; + iw.player = h->tempOwner; + iw.text << message; + cb->showInfoDialog(&iw); + } + collectRes(h->getOwner()); + } +} - cb->giveResource(h->tempOwner,subID,amount); - +void CGResource::collectRes( int player ) const +{ + cb->giveResource(player,subID,amount); ShowInInfobox sii; - sii.player = h->tempOwner; + sii.player = player; sii.c = Component(2,subID,amount,0); sii.text << std::pair(11,113); sii.text.replacements.push_back(VLC->generaltexth->restypes[subID]); @@ -1073,6 +1116,20 @@ void CGResource::onHeroVisit( const CGHeroInstance * h ) const cb->removeObject(id); } +void CGResource::fightForRes(ui32 wantToFight, const CGHeroInstance *h) const +{ + if(wantToFight) + return; + + cb->startBattleI(h->id,army,pos,boost::bind(&CGResource::endBattle,this,_1,h)); +} + +void CGResource::endBattle( BattleResult *result, const CGHeroInstance *h ) const +{ + if(result->winner == 0) //attacker won + collectRes(h->getOwner()); +} + void CGVisitableOPW::newTurn() const { if (cb->getDate(1)==1) //first day of week @@ -1330,4 +1387,36 @@ void CGPickable::chosen( int which, int heroID ) const default: throw std::string("Unhandled treasure choice"); } + cb->removeObject(id); +} + +void CGWitchHut::initObj() +{ + ability = allowedAbilities[ran()%allowedAbilities.size()]; +} + +void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const +{ + InfoWindow iw; + iw.player = h->getOwner(); + + if(h->getSecSkillLevel(ability)) //you alredy know this skill + { + iw.text << std::pair(11,172); + iw.text.replacements.push_back(VLC->generaltexth->skillName[ability]); + } + else if(h->secSkills.size() >= SKILL_PER_HERO) //already all skills slots used + { + iw.text << std::pair(11,173); + iw.text.replacements.push_back(VLC->generaltexth->skillName[ability]); + } + else //give sec skill + { + iw.components.push_back(Component(1, ability, 1, 0)); + iw.text << std::pair(11,171); + iw.text.replacements.push_back(VLC->generaltexth->skillName[ability]); + cb->changeSecSkill(h->id,ability,1,true); + } + + cb->showInfoDialog(&iw); } \ No newline at end of file diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index 81d0f08be..570a71546 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -306,6 +306,7 @@ public: void onNAHeroVisit(int heroID, bool alreadyVisited) const; void initObj(); void treeSelected(int heroID, int resType, int resVal, int expVal, ui32 result) const; //handle player's anwer to the Tree of Knowledge dialog + void arenaSelected(int heroID, int primSkill) const; template void serialize(Handler &h, const int version) { @@ -399,10 +400,14 @@ class DLL_EXPORT CGWitchHut : public CGObjectInstance public: std::vector allowedAbilities; + ui32 ability; + + void onHeroVisit(const CGHeroInstance * h) const; + void initObj(); template void serialize(Handler &h, const int version) { h & static_cast(*this); - h & allowedAbilities; + h & allowedAbilities & ability; } }; @@ -457,7 +462,10 @@ public: std::string message; void onHeroVisit(const CGHeroInstance * h) const; + void collectRes(int player) const; void initObj(); + void fightForRes(ui32 wantToFight, const CGHeroInstance *h) const; + void endBattle(BattleResult *result, const CGHeroInstance *h) const; template void serialize(Handler &h, const int version) { @@ -572,8 +580,13 @@ public: class DLL_EXPORT CObjectHandler { public: - std::vector cregens; //type 17. dwelling subid -> creature ID + std::vector cregens; //type 17. dwelling subid -> creature ID void loadObjects(); + + template void serialize(Handler &h, const int version) + { + h & cregens; + } }; diff --git a/lib/Connection.cpp b/lib/Connection.cpp index 0409cb627..ebad9e591 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -32,13 +32,13 @@ void CConnection::init() //we got connection (*this) << std::string("Aiya!\n") << name << myEndianess; //identify ourselves (*this) >> pom >> pom >> contactEndianess; - out << "Established connection with "< > * Socket, - std::string Name, - std::ostream & Out ) - :socket(Socket),io_service(&Socket->io_service()), out(Out), name(Name)//, send(this), rec(this) + std::string Name ) + :socket(Socket),io_service(&Socket->io_service()), name(Name)//, send(this), rec(this) { init(); } -CConnection::CConnection(boost::asio::basic_socket_acceptor > * acceptor, boost::asio::io_service *Io_service, std::string Name, std::ostream & Out) -: out(Out), name(Name)//, send(this), rec(this) +CConnection::CConnection(boost::asio::basic_socket_acceptor > * acceptor, + boost::asio::io_service *Io_service, std::string Name) +: name(Name)//, send(this), rec(this) { boost::system::error_code error = asio::error::host_not_found; socket = new tcp::socket(*io_service); diff --git a/lib/Connection.h b/lib/Connection.h index dccd3ffb7..780634d40 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -401,7 +401,6 @@ public: class DLL_EXPORT CConnection :public CISer, public COSer { - std::ostream &out; CConnection(void); void init(); public: @@ -414,13 +413,13 @@ public: std::string name; //who uses this connection CConnection - (std::string host, std::string port, std::string Name, std::ostream & Out); + (std::string host, std::string port, std::string Name); CConnection (boost::asio::basic_socket_acceptor > * acceptor, - boost::asio::io_service *Io_service, std::string Name, std::ostream & Out); + boost::asio::io_service *Io_service, std::string Name); CConnection (boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service > * Socket, - std::string Name, std::ostream & Out); //use immediately after accepting connection into socket + std::string Name); //use immediately after accepting connection into socket int write(const void * data, unsigned size); int read(void * data, unsigned size); int readLine(void * data, unsigned maxSize); diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index 79f0e96f2..36fb39b18 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -42,6 +42,7 @@ public: virtual void setHoverName(int objid, MetaString * name)=0; virtual void setObjProperty(int objid, int prop, int val)=0; virtual void changePrimSkill(int ID, int which, int val, bool abs=false)=0; + virtual void changeSecSkill(int ID, int which, int val, bool abs=false)=0; virtual void showInfoDialog(InfoWindow *iw)=0; virtual void showYesNoDialog(YesNoDialog *iw, const CFunctionList &callback)=0; virtual void showSelectionDialog(SelectionDialog *iw, const CFunctionList &callback)=0; //returns question id diff --git a/lib/Interprocess.h b/lib/Interprocess.h index 9df28a1dd..7501e1fab 100644 --- a/lib/Interprocess.h +++ b/lib/Interprocess.h @@ -1,5 +1,7 @@ #include #include +#include +#include struct ServerReady { @@ -20,3 +22,18 @@ struct ServerReady cond.notify_all(); } }; + +struct SharedMem +{ + boost::interprocess::shared_memory_object smo; + boost::interprocess::mapped_region mr; + ServerReady *sr; + + SharedMem() + :smo(boost::interprocess::open_or_create,"vcmi_memory",boost::interprocess::read_write), + mr(smo,boost::interprocess::read_write) + { + smo.truncate(sizeof(ServerReady)); + sr = new(mr.get_address())ServerReady(); + }; +}; \ No newline at end of file diff --git a/lib/VCMI_Lib.cpp b/lib/VCMI_Lib.cpp index 4e04a0685..770167eb9 100644 --- a/lib/VCMI_Lib.cpp +++ b/lib/VCMI_Lib.cpp @@ -20,56 +20,15 @@ DLL_EXPORT CLogger<3> tlog3; DLL_EXPORT CLogger<4> tlog4; DLL_EXPORT CLogger<5> tlog5; DLL_EXPORT CConsoleHandler *console = NULL; -DLL_EXPORT std::ostream *logfile = NULL; +DLL_EXPORT std::ostream *logfile = NULL +; DLL_EXPORT void initDLL(CLodHandler *b, CConsoleHandler *Console, std::ostream *Logfile) { console = Console; logfile = Logfile; - timeHandler pomtime; bitmaph=b; VLC = new LibClasses; - - VLC->generaltexth = new CGeneralTextHandler; - VLC->generaltexth->loadTexts(); - VLC->generaltexth->load(); - tlog0<<"\tGeneral text handler: "<loadHeroes(); - VLC->heroh = heroh; - tlog0 <<"\tHero handler: "<loadArtifacts(); - VLC->arth = arth; - tlog0<<"\tArtifact handler: "<loadCreatures(); - VLC->creh = creh; - tlog0<<"\tCreature handler: "<townh = new CTownHandler; - VLC->townh->loadNames(); - tlog0<<"\tTown handler: "<loadObjects(); - VLC->objh = objh; - tlog0<<"\tObject handler: "<dobjinfo = new CDefObjInfoHandler; - VLC->dobjinfo->load(); - tlog0<<"\tDef information handler: "<buildh = new CBuildingHandler; - VLC->buildh->loadBuildings(); - tlog0<<"\tBuilding handler: "<loadSpells(); - VLC->spellh = spellh; - tlog0<<"\tSpell handler: "<init(); } DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode) @@ -186,3 +145,65 @@ DLL_EXPORT void loadToIt(si32 &dest, std::string &src, int &iter, int mode) loadToIt(pom,src,iter,mode); dest = atol(pom.c_str()); } + +void LibClasses::init() +{ + timeHandler pomtime; + generaltexth = new CGeneralTextHandler; + generaltexth->load(); + tlog0<<"\tGeneral text handler: "<loadHeroes(); + tlog0 <<"\tHero handler: "<loadArtifacts(); + tlog0<<"\tArtifact handler: "<loadCreatures(); + tlog0<<"\tCreature handler: "<loadNames(); + tlog0<<"\tTown handler: "<loadObjects(); + tlog0<<"\tObject handler: "<load(); + tlog0<<"\tDef information handler: "<loadBuildings(); + tlog0<<"\tBuilding handler: "<loadSpells(); + tlog0<<"\tSpell handler: "< void serialize(Handler &h, const int version) + { + if(!h.saving) + { + generaltexth = new CGeneralTextHandler; + generaltexth->load(); + } + h & heroh & arth & creh & townh & objh & dobjinfo & buildh & spellh; + } }; extern DLL_EXPORT LibClasses * VLC; diff --git a/map.cpp b/map.cpp index cb3c4baa0..1203343b4 100644 --- a/map.cpp +++ b/map.cpp @@ -244,6 +244,7 @@ void CMapHeader::initFromMemory( unsigned char *bufor, int &i ) } void CMapHeader::loadPlayerInfo( int &pom, unsigned char * bufor, int &i ) { + players.resize(8); for (pom=0;pom<8;pom++) { players[pom].canHumanPlay = bufor[i++]; @@ -467,10 +468,7 @@ void Mapa::initFromBytes(unsigned char * bufor) readEvents(bufor, i); tlog0<<"\tReading events: "<defInfo) @@ -552,12 +550,28 @@ Mapa::Mapa(std::string filename) checksum = result.checksum(); tlog0 << "\tOur map checksum: "<firstVisitText = readString(bufor,i); guard->nextVisitText = readString(bufor,i); guard->completedText = readString(bufor,i); +} + +void CMapInfo::countPlayers() +{ + playerAmnt=humenPlayers=0; + for (int i=0;i players; // info about players - size 8 std::vector teams; // teams[i] = team of player no i ui8 howManyTeams; void initFromMemory(unsigned char *bufor, int &i); @@ -213,6 +213,13 @@ public: void loadPlayerInfo( int &pom, unsigned char * bufor, int &i); CMapHeader(unsigned char *map); //an argument is a reference to string described a map (unpacked) CMapHeader(); + + + template void serialize(Handler &h, const int Version) + { + h & version & name & description & width & height & twoLevel & difficulty & levelLimit & areAnyPLayers; + h & players & teams & lossCondition & victoryCondition & howManyTeams; + } }; class DLL_EXPORT CMapInfo : public CMapHeader @@ -220,15 +227,9 @@ class DLL_EXPORT CMapInfo : public CMapHeader public: std::string filename; int playerAmnt, humenPlayers; - CMapInfo(std::string fname, unsigned char *map):CMapHeader(map),filename(fname) - { - playerAmnt=humenPlayers=0; - for (int i=0;i void serializeObj(Handler &h, const int version, TObject ** obj) @@ -325,10 +327,8 @@ struct DLL_EXPORT Mapa : public CMapHeader } template void serialize(Handler &h, const int formatVersion) { - h & version & name & description & width & height & twoLevel & difficulty & levelLimit & areAnyPLayers & rumors; - - h & players & teams & lossCondition & victoryCondition & howManyTeams & allowedSpell - & allowedAbilities & allowedArtifact & allowedHeroes & events & grailPos; + h & static_cast(*this); + h & rumors & allowedSpell & allowedAbilities & allowedArtifact & allowedHeroes & events & grailPos; //TODO: viccondetails if(h.saving) diff --git a/mapHandler.cpp b/mapHandler.cpp index 3e8d637ee..a297a4dd0 100644 --- a/mapHandler.cpp +++ b/mapHandler.cpp @@ -404,7 +404,16 @@ void processDef (CGDefInfo* def) { if(def->id == 26) return; - def->handler=CDefHandler::giveDef(def->name); + if(def->name.size()) + { + def->handler = CDefHandler::giveDef(def->name); + } + else + { + tlog2 << "No def name for " << def->id << " " << def->subid << std::endl; + def->handler = NULL; + return; + } def->width = def->handler->ourImages[0].bitmap->w/32; def->height = def->handler->ourImages[0].bitmap->h/32; CGDefInfo* pom = CGI->dobjinfo->gobjs[def->id][def->subid]; @@ -518,7 +527,7 @@ SDL_Surface * CMapHandler::terrainRect(int x, int y, int dx, int dy, int level, if(extRect) SDL_SetClipRect(su, extRect); //preventing blitting outside of that rect if (((dx+x)>((map->width+Woff)) || (dy+y)>((map->height+Hoff))) || ((x<-Woff)||(y<-Hoff) ) ) - throw new std::string("terrainRect: out of range"); + throw std::string("terrainRect: out of range"); ////printing terrain for (int bx=0; bxtype==NULL) continue; - std::vector & iv = themp->type->heroClass->moveAnim->ourImages; + std::vector & iv = graphics->heroAnims[themp->type->heroType]->ourImages; size_t gg; for(gg=0; ggtype==NULL) continue; - std::vector & iv = themp->type->heroClass->moveAnim->ourImages; + std::vector & iv = graphics->heroAnims[themp->type->heroType]->ourImages; size_t gg; for(gg=0; gg < iv.size(); ++gg) @@ -785,7 +794,7 @@ SDL_Surface * CMapHandler::terrainRectSmooth(int x, int y, int dx, int dy, int l if(extRect) SDL_SetClipRect(su, extRect); //preventing blitting outside of that rect if (((dx+x)>((map->width+Woff)) || (dy+y)>((map->height+Hoff))) || ((x<-Woff)||(y<-Hoff) ) ) - throw new std::string("terrainRect: out of range"); + throw std::string("terrainRect: out of range"); ////printing terrain for (int bx= (moveX <= 0 ? 0 : -1); bxtype==NULL) continue; - std::vector & iv = themp->type->heroClass->moveAnim->ourImages; + std::vector & iv = graphics->heroAnims[themp->type->heroType]->ourImages; size_t gg; for(gg=0; ggtype==NULL) continue; - std::vector & iv = themp->type->heroClass->moveAnim->ourImages; + std::vector & iv = graphics->heroAnims[themp->type->heroType]->ourImages; size_t gg; for(gg=0; gg < iv.size(); ++gg) @@ -1328,11 +1337,7 @@ std::string CMapHandler::getDefName(int id, int subid) CGDefInfo* temp = CGI->dobjinfo->gobjs[id][subid]; if(temp) return temp->name; -#ifndef __GNUC__ - throw new std::exception("Def not found."); -#else - throw new std::exception(); -#endif + throw std::string("Def not found."); } bool CMapHandler::printObject(const CGObjectInstance *obj) @@ -1415,11 +1420,7 @@ unsigned char CMapHandler::getHeroFrameNum(const unsigned char &dir, const bool case 8: return 11; default: -#ifndef __GNUC__ - throw std::exception("Something very wrong1."); -#else - throw std::exception(); -#endif + throw std::string("Something very wrong1."); } } else //if(isMoving) @@ -1443,11 +1444,7 @@ unsigned char CMapHandler::getHeroFrameNum(const unsigned char &dir, const bool case 8: return 14; default: -#ifndef __GNUC__ - throw std::exception("Something very wrong2."); -#else - throw std::exception(); -#endif + throw std::string("Something very wrong2."); } } } @@ -1549,6 +1546,18 @@ void CMapHandler::updateWater() //shift colors in palettes of water tiles } } +CMapHandler::~CMapHandler() +{ + delete fullHide; + delete partialHide; +} + +CMapHandler::CMapHandler() +{ + fullHide = NULL; + partialHide = NULL; +} + TerrainTile2::TerrainTile2() :terbitmap(0),tileInfo(0) {} diff --git a/mapHandler.h b/mapHandler.h index e664a398d..a686b268c 100644 --- a/mapHandler.h +++ b/mapHandler.h @@ -85,6 +85,9 @@ public: std::vector > > hideBitmap; //specifies number of graphic that should be used to fully hide a tile + CMapHandler(); + ~CMapHandler(); + void loadDefs(); SDL_Surface * getVisBitmap(int x, int y, const std::vector< std::vector< std::vector > > & visibilityMap, int lvl); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 271cd05fb..0aacea0d2 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1,12 +1,13 @@ -#include "../CGameState.h" #include "../StartInfo.h" #include "../hch/CArtHandler.h" #include "../hch/CBuildingHandler.h" #include "../hch/CDefObjInfoHandler.h" +#include "../hch/CGeneralTextHandler.h" #include "../hch/CHeroHandler.h" #include "../hch/CObjectHandler.h" #include "../hch/CSpellHandler.h" #include "../hch/CTownHandler.h" +#include "../CGameState.h" #include "../lib/CondSh.h" #include "../lib/Connection.h" #include "../lib/NetPacks.h" @@ -183,15 +184,16 @@ void callWith(std::vector args, boost::function fun, ui32 which) fun(args[which]); } -void CGameHandler::changeSecSkill(int ID, ui16 which, int val, bool abs) +void CGameHandler::changeSecSkill( int ID, int which, int val, bool abs/*=false*/ ) { - SetSecSkill sps; - sps.id = ID; - sps.which = which; - sps.abs = abs; - sps.val = val; - sendAndApply(&sps); + SetSecSkill sss; + sss.id = ID; + sss.which = which; + sss.val = val; + sss.abs = abs; + sendAndApply(&sss); } + void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs) { SetPrimSkill sps; @@ -413,18 +415,16 @@ void CGameHandler::handleConnection(std::set players, CConnection &c) c >> fname; { - CSaveFile save(fname); - save << gs->map; + CSaveFile save(std::string("Games") + PATHSEPARATOR + fname + ".vlgm1"); + char hlp[8] = "VCMISVG"; + save << hlp << static_cast(*gs->map) << *VLC << gs; } { - CLoadFile load(fname); - load >> mapa; + CSaveFile save(std::string("Games") + PATHSEPARATOR + fname + ".vsgm1"); + save << *this; } - //save << VLC->arth << VLC->buildh << VLC->creh << VLC->dobjinfo << VLC->heroh - // << VLC->spellh << VLC->townh << this; - //save << this; break; } case 99: //end! @@ -1553,6 +1553,9 @@ void CGameHandler::init(StartInfo *si, int Seed) //} //delete lf; + + for(std::map::iterator i = gs->players.begin(); i != gs->players.end(); i++) + states.addPlayer(i->first); } void CGameHandler::newTurn() @@ -1638,13 +1641,15 @@ void CGameHandler::newTurn() if(gs->map->objects[i]) gs->map->objects[i]->newTurn(); } -void CGameHandler::run() +void CGameHandler::run(bool resume) { BOOST_FOREACH(CConnection *cc, conns) {//init conn. ui8 quantity, pom; //ui32 seed; - (*cc) << gs->scenarioOps->mapname << gs->map->checksum << gs->seed; + if(!resume) + (*cc) << gs->scenarioOps->mapname << gs->map->checksum << gs->seed; + (*cc) >> quantity; //how many players will be handled at that client for(int i=0;iobjects[i]->ID,temps)) // (*skrypty)[map->objects[i]->ID][temps]->newObject(map->objects[i]); //} - for(std::map::iterator i = gs->players.begin(); i != gs->players.end(); i++) - states.addPlayer(i->first); while (!end2) { - newTurn(); - for(std::map::iterator i = gs->players.begin(); i != gs->players.end(); i++) + + std::map::iterator i; + if(!resume) + i = gs->players.begin(); + else + i = gs->players.find(gs->currentPlayer); + + for(; i != gs->players.end(); i++) { + if(!resume) + newTurn(); + else + resume = false; + if((i->second.towns.size()==0 && i->second.heroes.size()==0) || i->second.color<0 || i->first>=PLAYER_LIMIT ) continue; //players has not towns/castle - loser states.setFlag(i->first,&PlayerStatus::makingTurn,true); gs->currentPlayer = i->first; diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 031353b81..749c7cc04 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -57,15 +57,11 @@ public: class CGameHandler : public IGameCallback { static ui32 QID; - //std::set cppscripts; //C++ scripts - //std::map > objscr; //non-C++ scripts - CVCMIServer *s; std::map connections; //player color -> connection to clinet with interface of that player PlayerStatuses states; //player color -> player state std::set conns; - void changeSecSkill(int ID, ui16 which, int val, bool abs=false); void giveSpells(const CGTownInstance *t, const CGHeroInstance *h); void moveStack(int stack, int dest); void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function cb); //use hero=NULL for no hero @@ -93,6 +89,7 @@ public: void setHoverName(int objid, MetaString * name); void setObjProperty(int objid, int prop, int val); void changePrimSkill(int ID, int which, int val, bool abs=false); + void changeSecSkill(int ID, int which, int val, bool abs=false); void showInfoDialog(InfoWindow *iw); void showYesNoDialog(YesNoDialog *iw, const CFunctionList &callback); void showSelectionDialog(SelectionDialog *iw, const CFunctionList &callback); //returns question id @@ -111,7 +108,7 @@ public: void handleConnection(std::set players, CConnection &c); template void serialize(Handler &h, const int version) { - h & QID & gs & states; + h & QID & states; } template void applyAndAsk(Query * sel, ui8 player, boost::function &callback) { @@ -157,7 +154,7 @@ public: gs->apply(info); sendToAllClients(info); } - void run(); + void run(bool resume); void newTurn(); friend class CVCMIServer; diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 4f1a7e064..4504006f4 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -3,6 +3,14 @@ #include #include "../global.h" #include "../lib/Connection.h" +#include "../hch/CArtHandler.h" +#include "../hch/CDefObjInfoHandler.h" +#include "../hch/CGeneralTextHandler.h" +#include "../hch/CHeroHandler.h" +#include "../hch/CTownHandler.h" +#include "../hch/CObjectHandler.h" +#include "../hch/CBuildingHandler.h" +#include "../hch/CSpellHandler.h" #include "zlib.h" #ifndef __GNUC__ #include @@ -87,12 +95,12 @@ void CVCMIServer::newGame(CConnection *c) i--; continue; } - cc = new CConnection(s,NAME,std::cout); + cc = new CConnection(s,NAME); } gh.conns.insert(cc); } - gh.run(); + gh.run(false); } void CVCMIServer::start() { @@ -125,7 +133,7 @@ void CVCMIServer::start() return; } tlog0<<"We've accepted someone... " << std::endl; - CConnection *connection = new CConnection(s,NAME,std::cout); + CConnection *connection = new CConnection(s,NAME); tlog0<<"Got connection!" << std::endl; while(!end2) { @@ -144,10 +152,68 @@ void CVCMIServer::start() case 2: newGame(connection); break; + case 3: + loadGame(connection); + break; } } } +void CVCMIServer::loadGame( CConnection *c ) +{ + std::string fname; + CGameHandler gh; + boost::system::error_code error; + ui8 clients; + *c >> clients >> fname; //how many clients should be connected - TODO: support more than one + + { + char sig[8]; + CMapHeader dum; + + CLoadFile lf(fname + ".vlgm1"); + lf >> sig >> dum; + tlog0 <<"Reading save signature"<> *VLC; + tlog0 <<"Reading handlers"<> (gh.gs); + tlog0 <<"Reading gamestate"<> gh; + } + + *c << ui8(0); + + CConnection* cc; //tcp::socket * ss; + for(int i=0; iio_service()); + acceptor->accept(*s,error); + if(error) //retry + { + tlog3<<"Cannot establish connection - retrying..." << std::endl; + i--; + continue; + } + cc = new CConnection(s,NAME); + } + gh.conns.insert(cc); + } + + gh.run(true); +} + #ifndef __GNUC__ int _tmain(int argc, _TCHAR* argv[]) #else diff --git a/server/CVCMIServer.h b/server/CVCMIServer.h index 36069671f..7948e658e 100644 --- a/server/CVCMIServer.h +++ b/server/CVCMIServer.h @@ -29,6 +29,7 @@ public: ~CVCMIServer(); void setUpConnection(CConnection *c, std::string mapname, si32 checksum); void newGame(CConnection *c); + void loadGame(CConnection *c); void start(); }; #endif // __CVCMISERVER_H__