diff --git a/CCallback.cpp b/CCallback.cpp index 0379519bf..7c8581644 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -936,6 +936,13 @@ int3 CCallback::getGrailPos( float &outKnownRatio ) return gs->map->grailPos; } +void CCallback::dig( const CGObjectInstance *hero ) +{ + DigWithHero dwh; + dwh.id = hero->id; + sendRequest(&dwh); +} + InfoAboutTown::InfoAboutTown() { tType = NULL; diff --git a/CCallback.h b/CCallback.h index cb2e78c57..0a9096d4e 100644 --- a/CCallback.h +++ b/CCallback.h @@ -127,6 +127,7 @@ public: virtual bool getPath2(int3 dest, CGPath &ret)=0; //uses main, client pathfinder info virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src = int3(-1,-1,-1), int movement = -1) =0; virtual void recalculatePaths()=0; //updates main, client pathfinder info (should be called when moving hero is over) + virtual void dig(const CGObjectInstance *hero)=0; //map virtual std::vector < const CGObjectInstance * > getBlockingObjs(int3 pos)const =0; @@ -223,6 +224,7 @@ public: void save(const std::string &fname); void sendMessage(const std::string &mess); void buildBoat(const IShipyard *obj); + void dig(const CGObjectInstance *hero); //get info bool verifyPath(CPath * path, bool blockSea) const; diff --git a/client/CAdvmapInterface.cpp b/client/CAdvmapInterface.cpp index 732703400..b130e6e25 100644 --- a/client/CAdvmapInterface.cpp +++ b/client/CAdvmapInterface.cpp @@ -578,7 +578,9 @@ void CTerrainRect::clickRight(tribool down, bool previousState) const TerrainTile * tile = LOCPLINT->cb->getTileInfo(mp); if (tile) { - CSimpleWindow * temp = CMessage::genWindow(VLC->generaltexth->terrainNames[tile->tertype], LOCPLINT->playerID, true); + std::string hlp; + CGI->mh->getTerrainDescr(mp, hlp, true); + CSimpleWindow * temp = CMessage::genWindow(hlp, LOCPLINT->playerID, true); CRClickPopupInt *rcpi = new CRClickPopupInt(temp,true); GH.pushInt(rcpi); } @@ -706,7 +708,10 @@ void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent) } else { - adventureInt->statusbar.clear(); + std::string hlp; + CGI->mh->getTerrainDescr(pom, hlp, false); + adventureInt->statusbar.print(hlp); + //adventureInt->statusbar.clear(); } const CGPathNode *pnode = LOCPLINT->cb->getPathInfo(pom); diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 7db2690d4..66a7cc5ec 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -2064,8 +2064,8 @@ CHotSeatPlayers::CHotSeatPlayers(const std::string &firstPlayer) txt[0]->setText(firstPlayer); txt[0]->giveFocus(); - ok = new AdventureMapButton(CGI->generaltexth->zelp[560], bind(&CHotSeatPlayers::enterSelectionScreen, this), 95, 338, "MUBCHCK.DEF"); - cancel = new AdventureMapButton(CGI->generaltexth->zelp[561], bind(&CGuiHandler::popIntTotally, ref(GH), this), 205, 338, "MUBCANC.DEF"); + ok = new AdventureMapButton(CGI->generaltexth->zelp[560], bind(&CHotSeatPlayers::enterSelectionScreen, this), 95, 338, "MUBCHCK.DEF", SDLK_RETURN); + cancel = new AdventureMapButton(CGI->generaltexth->zelp[561], bind(&CGuiHandler::popIntTotally, ref(GH), this), 205, 338, "MUBCANC.DEF", SDLK_ESCAPE); bar = new CGStatusBar(new CPicture(Rect(7, 381, 348, 18), 0));//226, 472 } @@ -2313,6 +2313,10 @@ CBonusSelection::CRegion::~CRegion() void CBonusSelection::CRegion::clickLeft( tribool down, bool previousState ) { //select if selectable & clicked inside our graphic + if ( indeterminate(down) ) + { + return; + } if( !down && selectable && !CSDL_Ext::isTransparent(graphics[0], GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) { owner->selectMap(myNumber); diff --git a/hch/CDefObjInfoHandler.cpp b/hch/CDefObjInfoHandler.cpp index 231fe5598..e7c31a95e 100644 --- a/hch/CDefObjInfoHandler.cpp +++ b/hch/CDefObjInfoHandler.cpp @@ -116,6 +116,17 @@ void CDefObjInfoHandler::load() if(nobj->id==TOWNI_TYPE) castles[nobj->subid]=nobj; } + + for (int i = 0; i < 8 ; i++) + { + + static const char *holeDefs[] = {"AVLHOLD0.DEF", "AVLHLDS0.DEF", "AVLHOLG0.DEF", "AVLHLSN0.DEF", + "AVLHOLS0.DEF", "AVLHOLR0.DEF", "AVLHOLX0.DEF", "AVLHOLL0.DEF"}; + + CGDefInfo * tmp = gobjs[124][0]; + gobjs[124][i] = gobjs[124][0]; + gobjs[124][i]->name = holeDefs[i]; + } } CDefObjInfoHandler::~CDefObjInfoHandler() diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 42f5a22db..c7438699d 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1411,6 +1411,18 @@ struct MakeCustomAction : public CPackForServer } }; +struct DigWithHero : public CPackForServer +{ + DigWithHero(){} + si32 id; //digging hero id + + bool applyGh(CGameHandler *gh); + template void serialize(Handler &h, const int version) + { + h & id; + } +}; + /***********************************************************************************************************/ struct SaveGame : public CPackForClient, public CPackForServer diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 91021c208..d8d69aa86 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -574,6 +574,13 @@ DLL_EXPORT void NewObject::applyGs( CGameState *gs ) id = o->id = gs->map->objects.size(); o->hoverName = VLC->generaltexth->names[ID]; + if(ID == 124) // hole + { + const TerrainTile &t = gs->map->getTile(pos); + o->defInfo = VLC->dobjinfo->gobjs[ID][t.tertype]; + assert(o->defInfo); + } + gs->map->objects.push_back(o); gs->map->addBlockVisTiles(o); o->initObj(); diff --git a/lib/map.cpp b/lib/map.cpp index 6c8d7aa72..b46e94b67 100644 --- a/lib/map.cpp +++ b/lib/map.cpp @@ -1264,7 +1264,7 @@ void Mapa::readTerrain( const unsigned char * bufor, int &i) void Mapa::readDefInfo( const unsigned char * bufor, int &i) { int defAmount = readNormalNr(bufor,i); i+=4; - defy.reserve(defAmount); + defy.reserve(defAmount+8); for (int idd = 0 ; idddobjinfo->gobjs[124][i]); + } } void Mapa::readObjects( const unsigned char * bufor, int &i) diff --git a/mapHandler.cpp b/mapHandler.cpp index 60d13bb0f..2639ccd1c 100644 --- a/mapHandler.cpp +++ b/mapHandler.cpp @@ -17,6 +17,7 @@ #include "hch/CDefHandler.h" #include "client/CConfigHandler.h" #include +#include "hch/CGeneralTextHandler.h" /* * mapHandler.cpp, part of VCMI engine @@ -308,7 +309,14 @@ static void processDef (CGDefInfo* def) { if(def->name.size()) { - def->handler = CDefHandler::giveDefEss(def->name); + if(vstd::contains(CGI->mh->loadedDefs, def->name)) + { + def->handler = CGI->mh->loadedDefs[def->name]; + } + else + { + CGI->mh->loadedDefs[def->name] = def->handler = CDefHandler::giveDefEss(def->name); + } } else { @@ -316,9 +324,11 @@ static void processDef (CGDefInfo* def) 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]; if(pom && def->id!=TOWNI_TYPE) { @@ -417,16 +427,20 @@ void CMapHandler::init() - for(size_t h=0; hdefy.size(); ++h) //initializing loaded def handler's info { - CGI->mh->loadedDefs.insert(std::make_pair(map->defy[h]->name, map->defy[h]->handler)); - tlog0<<"\tCollecting loaded def's handlers: "<defInfo->name << ' '; + + } } // Update map window screen @@ -1324,6 +1338,23 @@ CMapHandler::CMapHandler() partialHide = NULL; } +void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terName ) +{ + out.clear(); + TerrainTile2 &t = ttiles[pos.x][pos.y][pos.z]; + for(std::vector < std::pair >::const_iterator i = t.objects.begin(); i != t.objects.end(); i++) + { + if(i->first->ID == 124) + { + out = i->first->hoverName; + return; + } + } + + if(terName) + out = CGI->generaltexth->terrainNames[t.tileInfo->tertype]; +} + TerrainTile2::TerrainTile2() :tileInfo(0),terbitmap(0) {} diff --git a/mapHandler.h b/mapHandler.h index c6afe1f0d..020321351 100644 --- a/mapHandler.h +++ b/mapHandler.h @@ -114,10 +114,10 @@ public: CMapHandler(); //c-tor ~CMapHandler(); //d-tor - void loadDefs(); SDL_Surface * getVisBitmap(int x, int y, const std::vector< std::vector< std::vector > > & visibilityMap, int lvl); std::vector< std::string > getObjDescriptions(int3 pos); //returns desriptions of objects blocking given position + void getTerrainDescr(const int3 &pos, std::string & out, bool terName); //if tername == false => empty string when tile is clear CGObjectInstance * createObject(int id, int subid, int3 pos, int owner=254); //creates a new object with a certain id and subid bool printObject(const CGObjectInstance * obj); //puts appropriate things to ttiles, so obj will be visible on map bool hideObject(const CGObjectInstance * obj); //removes appropriate things from ttiles, so obj will be no longer visible on map (but still will exist) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 8a4115e45..9a310ff33 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3885,4 +3885,23 @@ void CGameHandler::getLossVicMessage( ui8 player, ui8 standard, bool victory, In out.text.addTxt(MetaString::GENERAL_TXT, 660); //All your forces have been defeated, and you are banished from this land! } } +} + +bool CGameHandler::dig( const CGHeroInstance *h ) +{ + for (std::vector::const_iterator i = gs->map->objects.begin(); i != gs->map->objects.end(); i++) //unflag objs + { + if((*i)->ID == 124 && (*i)->pos == h->getPosition(false)) + { + complain("Cannot dig - there is already a hole under the hero!"); + return false; + } + } + + NewObject no; + no.ID = 124; + no.pos = h->getPosition(false); + no.subID = 0; + sendAndApply(&no); + return true; } \ No newline at end of file diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 86d1ec3f0..c5de9e07e 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -179,6 +179,7 @@ public: bool complain(const std::string &problem); //sends message to all clients, prints on the logs and return true void objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h ); void engageIntoBattle( ui8 player ); + bool dig(const CGHeroInstance *h); template void serialize(Handler &h, const int version) { diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index 83c67ca5b..f56785cc1 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -154,6 +154,12 @@ bool MakeCustomAction::applyGh( CGameHandler *gh ) return gh->makeCustomAction(ba); } +bool DigWithHero::applyGh( CGameHandler *gh ) +{ + ERROR_IF_NOT_OWNS(id); + return gh->dig(gh->getHero(id)); +} + bool PlayerMessage::applyGh( CGameHandler *gh ) { if(gh->getPlayerAt(c) != player) ERROR_AND_RETURN;