diff --git a/client/CAdvmapInterface.cpp b/client/CAdvmapInterface.cpp index 41f641be2..d43dfdd52 100644 --- a/client/CAdvmapInterface.cpp +++ b/client/CAdvmapInterface.cpp @@ -521,14 +521,18 @@ void CTerrainRect::clickLeft(tribool down, bool previousState) { for(size_t i=0; i < bobjs.size(); ++i) { - if(bobjs[i]->ID == TOWNI_TYPE && bobjs[i]->tempOwner == LOCPLINT->playerID) //town - switch selection to it + const CGObjectInstance *o = bobjs[i]; + const CGPathNode *pn = LOCPLINT->cb->getPathInfo(mp); + if( ((o->ID == HEROI_TYPE && pn->turns == 255) //inaccessible hero + || o->ID == TOWNI_TYPE) //or town + && o->tempOwner == LOCPLINT->playerID) //but must belong to us { - LOCPLINT->adventureInt->select(static_cast(bobjs[i])); + LOCPLINT->adventureInt->select(static_cast(o)); return; } - else if(bobjs[i]->ID == HEROI_TYPE //it's a hero - && bobjs[i]->tempOwner == LOCPLINT->playerID //our hero (is this condition needed?) - && currentHero == (bobjs[i]) ) //and selected one + else if(o->ID == HEROI_TYPE //it's a hero + && o->tempOwner == LOCPLINT->playerID //our hero (is this condition needed?) + && currentHero == (o) ) //and selected one { LOCPLINT->openHeroWindow(currentHero); return; @@ -715,7 +719,7 @@ void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent) { if(LOCPLINT->adventureInt->selection->ID == TOWNI_TYPE) { - if(obj) + if(obj && obj->tempOwner == LOCPLINT->playerID) { if(obj->ID == TOWNI_TYPE) { diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 114377503..24041d78f 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -142,6 +142,8 @@ void CPlayerInterface::init(ICallback * CB) void CPlayerInterface::yourTurn() { boost::unique_lock un(*pim); + boost::unique_lock lock(eventsM); //block handling events until interface is ready + LOCPLINT = this; makingTurn = true; @@ -1069,7 +1071,7 @@ void CPlayerInterface::showShipyardDialog(const IShipyard *obj) int state = obj->state(); std::vector cost; obj->getBoatCost(cost); - CShipyardWindow *csw = new CShipyardWindow(cost, state, boost::bind(&CCallback::buildBoat, cb, obj)); + CShipyardWindow *csw = new CShipyardWindow(cost, state, obj->getBoatType(), boost::bind(&CCallback::buildBoat, cb, obj)); GH.pushInt(csw); } @@ -1119,7 +1121,11 @@ bool CPlayerInterface::ctrlPressed() const void CPlayerInterface::update() { - pim->lock(); + while(!terminate_cond.get() && !pim->try_lock()) //try acquiring long until it succeeds or we are told to terminate + boost::this_thread::sleep(boost::posix_time::milliseconds(15)); + + if(terminate_cond.get()) + return; //if there are any waiting dialogs, show them if(dialogs.size() && !showingDialog->get()) diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 3136580cc..7b5d6140d 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -110,7 +110,7 @@ CMenuScreen::CMenuScreen( EState which ) ////just for testing CCampaignHandler * ch = new CCampaignHandler(); ch->getCampaignHeaders(); - ch->getCampaign("./Maps/ALEXIS.h3c"); + //ch->getCampaign("./Maps/ALEXIS.h3c"); } break; } diff --git a/client/Client.cpp b/client/Client.cpp index fb433ccbd..d73135f63 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -171,6 +171,8 @@ void CClient::stop() // Game is ending // Tell the network thread to reach a stable state terminate = true; + GH.curInt = NULL; + LOCPLINT->terminate_cond.setn(true); LOCPLINT->pim->lock(); endGame(); } @@ -189,7 +191,6 @@ void CClient::save(const std::string & fname) void CClient::endGame() { tlog0 << "\n\nEnding current game!" << std::endl; - GH.curInt = NULL; if(GH.topInt()) GH.topInt()->deactivate(); GH.listInt.clear(); diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 432f20761..dcf687870 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -4652,7 +4652,7 @@ void CShipyardWindow::deactivate() void CShipyardWindow::show( SDL_Surface * to ) { blitAt(bg,pos,to); - CSDL_Ext::blit8bppAlphaTo24bpp(graphics->boatAnims[1]->ourImages[21 + frame++/8%8].bitmap, NULL, to, &genRect(64, 96, pos.x+110, pos.y+85)); + CSDL_Ext::blit8bppAlphaTo24bpp(graphics->boatAnims[boat]->ourImages[21 + frame++/8%8].bitmap, NULL, to, &genRect(64, 96, pos.x+110, pos.y+85)); build->show(to); quit->show(to); } @@ -4663,8 +4663,9 @@ CShipyardWindow::~CShipyardWindow() delete quit; } -CShipyardWindow::CShipyardWindow(const std::vector &cost, int state, const boost::function &onBuy) +CShipyardWindow::CShipyardWindow(const std::vector &cost, int state, int boatType, const boost::function &onBuy) { + boat = boatType; frame = 0; SDL_Surface * bgtemp; //loaded as 8bpp surface bgtemp = BitmapHandler::loadBitmap("TPSHIP.bmp"); diff --git a/client/GUIClasses.h b/client/GUIClasses.h index 5e6811a7b..f25de2226 100644 --- a/client/GUIClasses.h +++ b/client/GUIClasses.h @@ -802,11 +802,12 @@ public: AdventureMapButton *build, *quit; unsigned char frame; //frame of the boat animation + int boat; //which boat graphic should be used void activate(); void deactivate(); void show(SDL_Surface * to); - CShipyardWindow(const std::vector &cost, int state, const boost::function &onBuy); + CShipyardWindow(const std::vector &cost, int state, int boatType, const boost::function &onBuy); ~CShipyardWindow(); }; diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index a49c05438..00c533fe2 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -1442,7 +1442,7 @@ int CGTownInstance::getSightRadious() const //returns sight distance { if (subID == 2) //tower { - if ((builtBuildings.find(17)) != builtBuildings.end()) //skyship + if ((builtBuildings.find(26)) != builtBuildings.end()) //skyship return -1; //entire map else if ((builtBuildings.find(21)) != builtBuildings.end()) //lookout tower return 20; @@ -1732,6 +1732,11 @@ int3 CGTownInstance::getSightCenter() const return pos - int3(2,0,0); } +ui8 CGTownInstance::getPassableness() const +{ + return army ? 1< &offsets ) const { offsets += int3(-1,2,0), int3(-3,2,0); @@ -1771,9 +1776,15 @@ void CGTownInstance::removeCapitols (ui8 owner, bool me) const } } -ui8 CGTownInstance::getPassableness() const +int CGTownInstance::getBoatType() const { - return army ? 1<creh->creatures[town->basicCreatures.front()]; + if (c->isGood()) + return 1; + else if (c->isEvil()) + return 0; + else //neutral + return 2; } void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const @@ -5363,6 +5374,12 @@ const IShipyard * IShipyard::castFrom( const CGObjectInstance *obj ) return castFrom(const_cast(obj)); } +int IShipyard::getBoatType() const +{ + //We make good ships by default + return 1; +} + CGShipyard::CGShipyard() :IShipyard(this) { diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index 68cd48171..599bfe8ba 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -121,7 +121,8 @@ public: const CGObjectInstance *o; IShipyard(const CGObjectInstance *O); - void getBoatCost(std::vector &cost) const; + virtual void getBoatCost(std::vector &cost) const; + virtual int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral virtual void getOutOffsets(std::vector &offsets) const =0; //offsets to obj pos when we boat can be placed //virtual bool validLocation() const; //returns true if there is a water tile near where boat can be placed int3 bestLocation() const; //returns location when the boat should be placed @@ -484,6 +485,7 @@ public: ui8 getPassableness() const; //bitmap - if the bit is set the corresponding player can pass through the visitable tiles of object, even if it's blockvis; if not set - default properties from definfo are used int3 getSightCenter() const; //"center" tile from which the sight distance is calculated int getSightRadious() const; //returns sight distance + int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral void getOutOffsets(std::vector &offsets) const; //offsets to obj pos when we boat can be placed void setPropertyDer(ui8 what, ui32 val); void newTurn() const; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index d4911fcb3..39fcab578 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3616,16 +3616,7 @@ bool CGameHandler::buildBoat( ui32 objid ) //create boat NewObject no; no.ID = 8; - if (obj->o->ID == TOWNI_TYPE) - { //check what kind of creatures are avaliable in town - if (VLC->creh->creatures[(static_cast(obj))->creatures[0].second[0]].isGood()) - boatType = 1; - else if (VLC->creh->creatures[(static_cast(obj))->creatures[0].second[0]].isEvil()) - boatType = 0; - else //neutral - boatType = 2; - } - no.subID = boatType; + no.subID = obj->getBoatType(); no.pos = tile + int3(1,0,0); sendAndApply(&no);