From 3d29c31deb044104622e1a93d030aaba17eb65dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Sun, 1 Feb 2009 14:11:41 +0000 Subject: [PATCH] * further fight with hanged scroll tab * fixed r-click on FoW crash * fixed crash on opening tavern window after load * fixed recruiting new heroes after load * fixed crash on loading map with spell scrolls * fixed more crashes * displpaying difficulty level of saved game * added support for Library of Enlightenment * added notification when saving is done --- AdventureMapButton.cpp | 4 +++ CAdvmapInterface.cpp | 10 ++++++ CCallback.cpp | 10 +++--- CGameState.cpp | 2 ++ CGameState.h | 31 ++++++++++++++++++ CPreGame.cpp | 37 ++++++++++++++++++---- StartInfo.h | 2 +- client/Client.cpp | 11 ++++++- hch/CObjectHandler.cpp | 70 ++++++++++++++++++++++++++++++----------- hch/CObjectHandler.h | 1 + lib/Connection.h | 4 +-- map.cpp | 4 +++ map.h | 5 ++- server/CGameHandler.cpp | 12 +++++-- server/CGameHandler.h | 1 + server/CVCMIServer.cpp | 3 +- 16 files changed, 169 insertions(+), 38 deletions(-) diff --git a/AdventureMapButton.cpp b/AdventureMapButton.cpp index 7e979cff3..184dda8de 100644 --- a/AdventureMapButton.cpp +++ b/AdventureMapButton.cpp @@ -371,6 +371,10 @@ void CSlider::clickLeft (tribool down) moveTo(rw*amount); return; } + else + { + moving = false; + } if(moving) { MotionInterested::deactivate(); diff --git a/CAdvmapInterface.cpp b/CAdvmapInterface.cpp index 5fa45faa0..1330011e2 100644 --- a/CAdvmapInterface.cpp +++ b/CAdvmapInterface.cpp @@ -454,6 +454,11 @@ void CTerrainRect::clickRight(tribool down) { case 34: { + if(!vstd::contains(graphics->heroWins,obj->subID)) + { + tlog3 << "Warning - no infowin for hero " << obj->subID << std::endl; + break; + } CInfoPopup * ip = new CInfoPopup(graphics->heroWins[obj->subID], LOCPLINT->current->motion.x-graphics->heroWins[obj->subID]->w, LOCPLINT->current->motion.y-graphics->heroWins[obj->subID]->h,false @@ -463,6 +468,11 @@ void CTerrainRect::clickRight(tribool down) } case 98: { + if(!vstd::contains(graphics->townWins,obj->subID)) + { + tlog3 << "Warning - no infowin for town " << obj->subID << std::endl; + break; + } CInfoPopup * ip = new CInfoPopup(graphics->townWins[obj->id], LOCPLINT->current->motion.x-graphics->townWins[obj->id]->w, LOCPLINT->current->motion.y-graphics->townWins[obj->id]->h,false diff --git a/CCallback.cpp b/CCallback.cpp index b7f6364ac..db89265f5 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -574,9 +574,9 @@ void CCallback::buyArtifact(const CGHeroInstance *hero, int aid) std::vector < const CGObjectInstance * > CCallback::getBlockingObjs( int3 pos ) const { std::vector ret; - if(!gs->map->isInTheMap(pos)) - return ret; boost::shared_lock lock(*gs->mx); + if(!gs->map->isInTheMap(pos) || !isVisible(pos)) + return ret; BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].blockingObjects) ret.push_back(obj); return ret; @@ -585,9 +585,9 @@ std::vector < const CGObjectInstance * > CCallback::getBlockingObjs( int3 pos ) std::vector < const CGObjectInstance * > CCallback::getVisitableObjs( int3 pos ) const { std::vector ret; - if(!gs->map->isInTheMap(pos)) - return ret; boost::shared_lock lock(*gs->mx); + if(!gs->map->isInTheMap(pos) || !isVisible(pos)) + return ret; BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].visitableObjects) ret.push_back(obj); return ret; @@ -614,7 +614,7 @@ void CCallback::getMarketOffer( int t1, int t2, int &give, int &rec, int mode/*= std::vector < const CGObjectInstance * > CCallback::getFlaggableObjects(int3 pos) const { - if(!isVisible(pos, LOCPLINT->playerID)) + if(!isVisible(pos)) return std::vector < const CGObjectInstance * >(); std::vector < const CGObjectInstance * > ret; diff --git a/CGameState.cpp b/CGameState.cpp index 4a2179d24..4ae5a2504 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -721,6 +721,8 @@ void CGameState::applyNL(IPack * pack) } else map->objects[h->id] = h; + + h->initHeroDefInfo(); map->heroes.push_back(h); players[h->tempOwner].heroes.push_back(h); map->addBlockVisTiles(h); diff --git a/CGameState.h b/CGameState.h index 5de46dcf8..2bbcde71f 100644 --- a/CGameState.h +++ b/CGameState.h @@ -60,6 +60,27 @@ public: template void serialize(Handler &h, const int version) { h & color & serial & currentSelection & fogOfWarMap & resources; + + ui32 size; + if(h.saving) //write subids of available heroes + { + size = availableHeroes.size(); + h & size; + for(size_t i=0; i < size; i++) + h & availableHeroes[i]->subID; + } + else + { + ui32 hid; + h & size; + for(size_t i=0; i < size; i++) + { + //fill availableHeroes with dummy hero instances, holding subids + h & hid; + availableHeroes.push_back(new CGHeroInstance); + availableHeroes[availableHeroes.size()-1]->subID = hid; + } + } } }; @@ -225,6 +246,16 @@ public: 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]); + //recreating available heroes + for(std::map::iterator i=players.begin(); i!=players.end(); i++) + { + for(size_t j=0; j < i->second.availableHeroes.size(); j++) + { + ui32 hlp = i->second.availableHeroes[j]->subID; + delete i->second.availableHeroes[j]; + i->second.availableHeroes[j] = hpool.heroesPool[hlp]; + } + } } } diff --git a/CPreGame.cpp b/CPreGame.cpp index dc76adf2a..59f4b2957 100644 --- a/CPreGame.cpp +++ b/CPreGame.cpp @@ -1074,12 +1074,18 @@ void MapSel::processMaps(std::vector &pliczkiTemp, int &index) void MapSel::processGames( std::vector &pliczkiTemp, int &index ) { ourGames.resize(pliczkiTemp.size()); + ui32 hlp; for(int i=0; i> sign >> static_cast(ourGames[i]); + lf >> sign >> hlp >> static_cast(ourGames[i]) >> ourGames[i].seldiff; + if(hlp != version) + { + tlog3 << "\t" << ourGames[i].filename << " seems to be too " << ((hlp>version) ? "new" : "old") << " and will be ommited.\n"; + continue; + } ourGames[i].filename = pliczkiTemp[i]; ourGames[i].countPlayers(); } @@ -1308,6 +1314,8 @@ MapSel::MapSel():selected(0),sizeFilter(0) } void MapSel::printSelectedInfo() { + CMapInfo &selMap = selectedMap(); + 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)); if(CPG->fromnewgame) @@ -1316,6 +1324,19 @@ void MapSel::printSelectedInfo() 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); } + else + { + CPG->ourScenSel->bEasy.state = 2 + (selMap.seldiff==0); + CPG->ourScenSel->bNormal.state = 2 + (selMap.seldiff==1); + CPG->ourScenSel->bHard.state = 2 + (selMap.seldiff==2); + CPG->ourScenSel->bExpert.state = 2 + (selMap.seldiff==3); + CPG->ourScenSel->bImpossible.state = 2 + (selMap.seldiff==4); + CPG->ourScenSel->bEasy.show(); + CPG->ourScenSel->bNormal.show(); + CPG->ourScenSel->bHard.show(); + CPG->ourScenSel->bExpert.show(); + CPG->ourScenSel->bImpossible.show(); + } //blit texts CSDL_Ext::printAt(CGI->generaltexth->zelp[21].second,420,25,GEOR13); CSDL_Ext::printAt(CGI->generaltexth->allTexts[496],420,135,GEOR13); @@ -1324,8 +1345,6 @@ 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); - CMapInfo &selMap = selectedMap(); - int temp = selMap.victoryCondition.condition+1; if (temp>20) temp=0; std::string sss = CGI->generaltexth->victoryConditions[temp]; @@ -2165,13 +2184,15 @@ StartInfo CPreGame::runLoop() { highlightButton(1,2); current->highlighted=1; - (this->*(current->fNewGame))(); + if(current->fNewGame) + (this->*(current->fNewGame))(); } else if (isItIn(¤t->lLoadGame,sEvent.motion.x,sEvent.motion.y)) { highlightButton(2,2); current->highlighted=2; - (this->*(current->fLoadGame))(); + if(current->fLoadGame) + (this->*(current->fLoadGame))(); } else if (isItIn(¤t->lHighScores,sEvent.motion.x,sEvent.motion.y)) { @@ -2187,7 +2208,8 @@ StartInfo CPreGame::runLoop() { highlightButton(5,2); current->highlighted=5; - (this->*(current->fQuit))(); + if(current->fQuit) + (this->*(current->fQuit))(); } } else if ((sEvent.type==SDL_MOUSEBUTTONDOWN) && (sEvent.button.button == SDL_BUTTON_RIGHT)) @@ -2376,16 +2398,19 @@ void CPreGame::initLoadMenu() ourLoadMenu->lLoadGame.w=ourLoadMenu->loadGame->ourImages[0].bitmap->w; ourLoadMenu->lLoadGame.x=568; ourLoadMenu->lLoadGame.y=120; + ourLoadMenu->fLoadGame = NULL; //campaign ourLoadMenu->lHighScores.h=ourLoadMenu->highScores->ourImages[0].bitmap->h; ourLoadMenu->lHighScores.w=ourLoadMenu->highScores->ourImages[0].bitmap->w; ourLoadMenu->lHighScores.x=541; ourLoadMenu->lHighScores.y=233; + ourLoadMenu->fHighScores = NULL; //tutorial ourLoadMenu->lCredits.h=ourLoadMenu->credits->ourImages[0].bitmap->h; ourLoadMenu->lCredits.w=ourLoadMenu->credits->ourImages[0].bitmap->w; ourLoadMenu->lCredits.x=545; ourLoadMenu->lCredits.y=358; + ourLoadMenu->fCredits = NULL; //back ourLoadMenu->lQuit.h=ourLoadMenu->quit->ourImages[0].bitmap->h; ourLoadMenu->lQuit.w=ourLoadMenu->quit->ourImages[0].bitmap->w; diff --git a/StartInfo.h b/StartInfo.h index 50f7954ff..035f94566 100644 --- a/StartInfo.h +++ b/StartInfo.h @@ -34,7 +34,7 @@ struct StartInfo } }; ui8 mode; //0 - new game; 1 - load game - si32 difficulty; //0=easy; 4=impossible + ui8 difficulty; //0=easy; 4=impossible std::vector playerInfos; ui8 turnTime; //in minutes, 0=unlimited std::string mapname; diff --git a/client/Client.cpp b/client/Client.cpp index 697d04f06..4a60eb82f 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -31,6 +31,7 @@ namespace intpr = boost::interprocess; void CClient::init() { + IObjectInterface::cb = this; serv = NULL; gs = NULL; cb = NULL; @@ -58,6 +59,13 @@ void CClient::process(int what) static BattleAction curbaction; switch (what) { + case 95: //system message + { + std::string m; + *serv >> m; + tlog4 << "System message from server: " << m << std::endl; + break; + } case 100: //one of our interfaces has turn { ui8 player; @@ -635,12 +643,13 @@ void CClient::load( const std::string & fname ) tlog0 <<"Restarting server: "<mh = new CMapHandler(); CLoadFile lf(fname + ".vlgm1"); - lf >> sig >> dum; + lf >> sig >> ver >> dum >> *sig; tlog0 <<"Reading save signature: "<> *VLC; diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 143060f5a..b65864d33 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -475,25 +475,9 @@ void CGHeroInstance::initHero(int SUBID) void CGHeroInstance::initHero() { - if(!defInfo) - { - defInfo = new CGDefInfo(); - defInfo->id = 34; - defInfo->subid = subID; - defInfo->printPriority = 0; - defInfo->visitDir = 0xff; - } + initHeroDefInfo(); if(!type) type = VLC->heroh->heroes[subID]; - for(int i=0;i<6;i++) - { - defInfo->blockMap[i]=255; - defInfo->visitMap[i]=0; - } - defInfo->handler=NULL; - defInfo->blockMap[5] = 253; - defInfo->visitMap[5] = 2; - artifWorn[16] = 3; if(type->heroType % 2 == 1) //it's a magical hero { @@ -559,6 +543,25 @@ void CGHeroInstance::initHero() boost::algorithm::replace_first(hoverName,"%s", type->heroClass->name); } +void CGHeroInstance::initHeroDefInfo() +{ + if(!defInfo) + { + defInfo = new CGDefInfo(); + defInfo->id = 34; + defInfo->subid = subID; + defInfo->printPriority = 0; + defInfo->visitDir = 0xff; + } + for(int i=0;i<6;i++) + { + defInfo->blockMap[i]=255; + defInfo->visitMap[i]=0; + } + defInfo->handler=NULL; + defInfo->blockMap[5] = 253; + defInfo->visitMap[5] = 2; +} CGHeroInstance::~CGHeroInstance() { } @@ -597,6 +600,7 @@ void CGHeroInstance::initObj() { blockVisit = true; } + int CGTownInstance::getSightDistance() const //returns sight distance { return 10; @@ -743,7 +747,7 @@ void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const if(visitors.find(h->id)==visitors.end()) { onNAHeroVisit(h->id, false); - if(ID != 102 && ID!=4) //not tree nor arena + if(ID != 102 && ID!=4 && ID!=41) //not tree nor arena nor library of enlightenment cb->setObjProperty(id,4,h->id); //add to the visitors } else @@ -804,6 +808,9 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const ot = 146; val = 1; break; + case 41: + ot = 66; + break; } if (!alreadyVisited) { @@ -891,6 +898,30 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const } break; } + case 41: + { + const CGHeroInstance *h = cb->getHero(heroID); + if(h->level < 10 - 2*h->getSecSkillLevel(4)) //not enough level + { + InfoWindow iw; + iw.player = cb->getOwner(heroID); + iw.text << std::pair(11,68); + cb->showInfoDialog(&iw); + } + else + { + cb->setObjProperty(this->id,4,heroID); //add to the visitors + cb->changePrimSkill(heroID,0,2); + cb->changePrimSkill(heroID,1,2); + cb->changePrimSkill(heroID,2,2); + cb->changePrimSkill(heroID,3,2); + InfoWindow iw; + iw.player = cb->getOwner(heroID); + iw.text << std::pair(11,66); + cb->showInfoDialog(&iw); + } + break; + } } } else @@ -929,6 +960,8 @@ const std::string & CGVisitableOPH::getHoverText() const case 102: pom = 18; break; + case 41: + break; default: throw std::string("Wrong CGVisitableOPH object ID!\n"); } @@ -1276,6 +1309,7 @@ void CGArtifact::initObj() void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const { cb->giveHeroArtifact(subID,h->id,-2); + cb->removeObject(id); InfoWindow iw; iw.player = h->tempOwner; iw.components.push_back(Component(4,subID,0,0)); diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index ef767c145..ad975db82 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -221,6 +221,7 @@ public: void initHero(); void initHero(int SUBID); + void initHeroDefInfo(); CGHeroInstance(); virtual ~CGHeroInstance(); diff --git a/lib/Connection.h b/lib/Connection.h index 21ebdddea..6197697e6 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -17,7 +17,7 @@ #include #include -const int version = 63; +const ui32 version = 63; class CConnection; namespace mpl = boost::mpl; @@ -189,7 +189,7 @@ public: } template - COSer & operator&(T & t) + COSer & operator&(const T & t) { return * this->This() << t; } diff --git a/map.cpp b/map.cpp index fd73a7f07..e99a59243 100644 --- a/map.cpp +++ b/map.cpp @@ -1418,6 +1418,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i) case 32: // Garden of Revelation case 100: //Learning Stone case 102: //Tree of Knowledge + case 41: //Library of Enlightenment { nobj = new CGVisitableOPH(); break; @@ -1584,6 +1585,9 @@ void Mapa::readObjects( unsigned char * bufor, int &i) { art->army = readCreatureSet(bufor,i,7,(version>RoE)); } + } + if(areSettings || defInfo->id==93) + { art->spell = readNormalNr(bufor,i); i+=4; } diff --git a/map.h b/map.h index 36eb73ac7..b2840d727 100644 --- a/map.h +++ b/map.h @@ -229,6 +229,7 @@ public: class DLL_EXPORT CMapInfo : public CMapHeader { public: + ui8 seldiff; //selected difficulty (only in saved games) std::string filename; std::string date; int playerAmnt, humenPlayers; @@ -366,10 +367,12 @@ struct DLL_EXPORT Mapa : public CMapHeader if(h.saving) //create vector with all defs used on map { for(int i=0; idefInfo->serial = -1; //set serial to serial -1 - indicates that def is not present in defs vector + if(objects[i]) + objects[i]->defInfo->serial = -1; //set serial to serial -1 - indicates that def is not present in defs vector for(int i=0; idefInfo; if(cur->serial < 0) { diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 3c1c86272..1edb3698c 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -413,18 +413,19 @@ void CGameHandler::handleConnection(std::set players, CConnection &c) std::string fname; Mapa * mapa; c >> fname; - { + sendMessageTo(c,"Serializing game info..."); CSaveFile save(std::string("Games") + PATHSEPARATOR + fname + ".vlgm1"); char hlp[8] = "VCMISVG"; - save << hlp << static_cast(*gs->map) << *VLC << gs; + save << hlp << version << static_cast(*gs->map) << gs->scenarioOps->difficulty << *VLC << gs; } { + sendMessageTo(c,"Serializing server info..."); CSaveFile save(std::string("Games") + PATHSEPARATOR + fname + ".vsgm1"); save << *this; } - + sendMessageTo(c,"Game has been succesfully saved!"); break; } case 99: //end! @@ -2342,4 +2343,9 @@ void CGameHandler::setObjProperty( int objid, int prop, int val ) sob.what = prop; sob.val = val; sendAndApply(&sob); +} + +void CGameHandler::sendMessageTo( CConnection &c, std::string message ) +{ + c << ui16(95) << message; } \ No newline at end of file diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 749c7cc04..41a999c02 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -62,6 +62,7 @@ class CGameHandler : public IGameCallback PlayerStatuses states; //player color -> player state std::set conns; + void sendMessageTo(CConnection &c, std::string message); 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 diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index e959a76df..e49913b2d 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -169,11 +169,12 @@ void CVCMIServer::loadGame( CConnection *c ) *c >> clients >> fname; //how many clients should be connected - TODO: support more than one { + ui32 ver; char sig[8]; CMapHeader dum; CLoadFile lf(fname + ".vlgm1"); - lf >> sig >> dum; + lf >> sig >> ver >> dum >> *sig; tlog0 <<"Reading save signature"<> *VLC;