diff --git a/CGameInterface.h b/CGameInterface.h index 44d482c2f..927870370 100644 --- a/CGameInterface.h +++ b/CGameInterface.h @@ -27,6 +27,7 @@ struct TryMoveHero; class CGHeroInstance; class CGTownInstance; class CGObjectInstance; +class CGBlackMarket; class CGDwelling; class CCreatureSet; class CArmedInstance; @@ -87,6 +88,7 @@ public: virtual void tileHidden(const std::set &pos){}; virtual void tileRevealed(const std::set &pos){}; virtual void newObject(const CGObjectInstance * obj){}; //eg. ship built in shipyard + virtual void availableArtifactsChanged(const CGBlackMarket *bm = NULL){}; //bm may be NULL, then artifacts are changed in the global pool (used by merchants in towns) virtual void yourTurn(){}; virtual void centerView (int3 pos, int focusTime){}; virtual void availableCreaturesChanged(const CGDwelling *town){}; diff --git a/client/AdventureMapButton.cpp b/client/AdventureMapButton.cpp index 8c902e20f..06211e755 100644 --- a/client/AdventureMapButton.cpp +++ b/client/AdventureMapButton.cpp @@ -513,7 +513,9 @@ void CSlider::moveTo(int to) else slider->pos.y = pos.y+16; } - moved(to); + + if(moved) + moved(to); } void CSlider::clickLeft(tribool down, bool previousState) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index bb0bacc31..995afa6a9 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -1989,4 +1989,10 @@ void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInsta { CMarketplaceWindow *cmw = new CMarketplaceWindow(market, visitor, market->availableModes().front()); GH.pushInt(cmw); +} + +void CPlayerInterface::availableArtifactsChanged(const CGBlackMarket *bm /*= NULL*/) +{ + if(CMarketplaceWindow *cmw = dynamic_cast(GH.topInt())) + cmw->artifactsChanged(false); } \ No newline at end of file diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 0a4734a3d..5b96513eb 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -167,6 +167,7 @@ public: void tileHidden(const std::set &pos); //called when given tiles become hidden under fog of war void tileRevealed(const std::set &pos); //called when fog of war disappears from given tiles void newObject(const CGObjectInstance * obj); + void availableArtifactsChanged(const CGBlackMarket *bm = NULL); //bm may be NULL, then artifacts are changed in the global pool (used by merchants in towns) void yourTurn(); void availableCreaturesChanged(const CGDwelling *town); void heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain);//if gain hero received bonus, else he lost it diff --git a/client/GUIBase.cpp b/client/GUIBase.cpp index 021bb5b5a..307c63941 100644 --- a/client/GUIBase.cpp +++ b/client/GUIBase.cpp @@ -597,11 +597,21 @@ void CIntObject::printAtMiddleLoc( const std::string & text, int x, int y, EFont CSDL_Ext::printAtMiddle(text, pos.x + x, pos.y + y, font, kolor, dst, refresh); } +void CIntObject::printAtMiddleLoc(const std::string & text, const Point &p, EFonts font, SDL_Color kolor, SDL_Surface * dst, bool refresh /*= false*/) +{ + printAtMiddleLoc(text, p.x, p.y, font, kolor, dst, refresh); +} + void CIntObject::blitAtLoc( SDL_Surface * src, int x, int y, SDL_Surface * dst ) { blitAt(src, pos.x + x, pos.y + y, dst); } +void CIntObject::blitAtLoc(SDL_Surface * src, const Point &p, SDL_Surface * dst) +{ + blitAtLoc(src, p.x, p.y, dst); +} + void CIntObject::printAtMiddleWBLoc( const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor, SDL_Surface * dst, bool refrsh /*= false*/ ) { CSDL_Ext::printAtMiddleWB(text, pos.x + x, pos.y + y, font, charpr, kolor, dst, refrsh); diff --git a/client/GUIBase.h b/client/GUIBase.h index cb130b247..996784414 100644 --- a/client/GUIBase.h +++ b/client/GUIBase.h @@ -382,8 +382,10 @@ public: void printAtLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst, bool refresh = false); void printToLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst, bool refresh = false); void printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst, bool refresh = false); + void printAtMiddleLoc(const std::string & text, const Point &p, EFonts font, SDL_Color kolor, SDL_Surface * dst, bool refresh = false); void printAtMiddleWBLoc(const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor, SDL_Surface * dst, bool refrsh = false); void blitAtLoc(SDL_Surface * src, int x, int y, SDL_Surface * dst); + void blitAtLoc(SDL_Surface * src, const Point &p, SDL_Surface * dst); bool isItInLoc(const SDL_Rect &rect, int x, int y); bool isItInLoc(const SDL_Rect &rect, const Point &p); const Rect & center(const Rect &r); //sets pos so that r will be in the center of screen, returns new position diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index e1c37d84b..101acd8ae 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -2794,6 +2794,7 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan :market(Market), hero(Hero), hLeft(NULL), hRight(NULL), readyToTrade(false) { OBJ_CONSTRUCTION_CAPTURING_ALL; + type = BLOCK_ADV_HOTKEYS; mode = Mode; @@ -2802,6 +2803,7 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan std::string bgName; std::vector *rIds = NULL, *lIds = NULL; + bool sliderNeeded = true; switch(Mode) { @@ -2835,6 +2837,14 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan lIds->push_back(-1); } break; + + case RESOURCE_ARTIFACT: + bgName = "TPMRKABS.bmp"; + ltype = RESOURCE; + rtype = ARTIFACT; + sliderNeeded = false; + + rIds = new std::vector(market->availableItemsIds(mode)); } bg = new CPicture(bgName); @@ -2865,20 +2875,34 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan delNull(rIds); delNull(lIds); - //slider and buttons must be created after bg - slider = new CSlider(231,490,137,boost::bind(&CMarketplaceWindow::sliderMoved,this,_1),0,0); - ok = new AdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally,&GH,this),516,520,"IOK6432.DEF",SDLK_RETURN); ok->assignedKeys.insert(SDLK_ESCAPE); deal = new AdventureMapButton("","",boost::bind(&CMarketplaceWindow::makeDeal,this),307,520,"TPMRKB.DEF"); - max = new AdventureMapButton("","",boost::bind(&CMarketplaceWindow::setMax,this),229,520,"IRCBTNS.DEF"); + deal->block(true); + + + //slider and buttons must be created after bg + if(sliderNeeded) + { + slider = new CSlider(231,490,137,0,0,0); + slider->moved = boost::bind(&CMarketplaceWindow::sliderMoved,this,_1); + max = new AdventureMapButton("","",boost::bind(&CMarketplaceWindow::setMax,this),229,520,"IRCBTNS.DEF"); + max->block(true); + } + else + { + slider = NULL; + max = NULL; + deal->pos.x -= 38; + } //left side switch(Mode) { case RESOURCE_RESOURCE: case RESOURCE_PLAYER: + case RESOURCE_ARTIFACT: printAtMiddle(CGI->generaltexth->allTexts[270],154,148,FONT_SMALL,zwykly,*bg); //kingdom res. break; case CREATURE_RESOURCE: @@ -2891,6 +2915,7 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan { case RESOURCE_RESOURCE: case CREATURE_RESOURCE: + case RESOURCE_ARTIFACT: printAtMiddle(CGI->generaltexth->allTexts[168],445,148,FONT_SMALL,zwykly,*bg); //available for trade break; case RESOURCE_PLAYER: @@ -2906,8 +2931,6 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan new AdventureMapButton("","",boost::bind(&CMarketplaceWindow::setMode,this, CREATURE_RESOURCE), 516, 450,"TPMRKBU4.DEF"); - max->block(true); - deal->block(true); } CMarketplaceWindow::~CMarketplaceWindow() @@ -2944,7 +2967,13 @@ void CMarketplaceWindow::showAll(SDL_Surface * to) if(readyToTrade) { blitAt(hLeft->getSurface(),pos.x+141,pos.y+457,to); - printAtMiddle(boost::lexical_cast( slider->value * r1 ),pos.x+156,pos.y+505,FONT_SMALL,zwykly,to); + int val = -1; + if(slider) + val = slider->value * r1; + else + val = (deal->blocked) ? 0 : r1; + + printAtMiddle(boost::lexical_cast(val),pos.x+156,pos.y+505,FONT_SMALL,zwykly,to); } break; @@ -2960,6 +2989,11 @@ void CMarketplaceWindow::showAll(SDL_Surface * to) break; } + Point rightSubOffset; + Point selectionPos; + Point selectionSubOffset; + std::string selectionSub; + //right side switch(rtype) { @@ -2974,24 +3008,40 @@ void CMarketplaceWindow::showAll(SDL_Surface * to) printAtMiddle(CGI->generaltexth->allTexts[164],right[i]->pos.x+36,right[i]->pos.y+57,FONT_SMALL,zwykly,to); } } - if(readyToTrade) - { - blitAt(hRight->getSurface(),pos.x+429,pos.y+457,to); - printAtMiddle(boost::lexical_cast( slider->value * r2 ),pos.x+443,pos.y+505,FONT_SMALL,zwykly,to); - } + selectionPos = Point(429, 457); + selectionSubOffset = Point(14, 47); + selectionSub = boost::lexical_cast( slider->value * r2 ); + break; + + case ARTIFACT: + if(hLeft) //print prices + for(int i=0; iid != hLeft->id || mode != RESOURCE_RESOURCE) + printAtMiddle(rSubs[i], right[i]->pos.x+18, right[i]->pos.y+57, FONT_SMALL, zwykly, to); + + selectionPos = Point(425, 447); + selectionSubOffset = Point(18, 57); + selectionSub = (deal->blocked) ? "0" : "1"; break; case PLAYER: BOOST_FOREACH(CTradeableItem *i, right) printAtMiddle(CGI->generaltexth->capColors[i->id], i->pos.x + 31, i->pos.y + 76, FONT_SMALL, zwykly, to); - if(readyToTrade) - { - blitAt(hRight->getSurface(),pos.x+417,pos.y+451,to); - printAtMiddle(CGI->generaltexth->capColors[hRight->id], pos.x+417 + 31, pos.y+451 + 76, FONT_SMALL, zwykly, to); - } + selectionPos = Point(417, 451); + selectionSubOffset = rightSubOffset = Point(31, 76); + selectionSub = hRight ? CGI->generaltexth->capColors[hRight->id] : ""; break; } + + + if(readyToTrade) + { + assert(hRight); + blitAtLoc(hRight->getSurface(), selectionPos, to); + printAtMiddleLoc(selectionSub, selectionPos + selectionSubOffset, FONT_SMALL, zwykly, to); + } + } void CMarketplaceWindow::setMax() @@ -3001,7 +3051,13 @@ void CMarketplaceWindow::setMax() void CMarketplaceWindow::makeDeal() { - if(!slider->value) + int sliderValue = 0; + if(slider) + sliderValue = slider->value; + else + sliderValue = !deal->blocked; //should always be 1 + + if(!sliderValue) return; int leftIdToSend = -1; @@ -3010,8 +3066,16 @@ void CMarketplaceWindow::makeDeal() else leftIdToSend = hLeft->id; - LOCPLINT->cb->trade(market->o, mode, leftIdToSend, hRight->id, slider->value*r1, hero); - slider->moveTo(0); + if(mode != RESOURCE_ARTIFACT) + { + LOCPLINT->cb->trade(market->o, mode, leftIdToSend, hRight->id, slider->value*r1, hero); + slider->moveTo(0); + } + else + { + LOCPLINT->cb->trade(market->o, mode, leftIdToSend, hRight->id, r2, hero); + } + hLeft = NULL; hRight = NULL; selectionChanged(true); @@ -3038,18 +3102,29 @@ void CMarketplaceWindow::selectionChanged(bool side) else assert(0); - slider->setAmount(newAmount / r1); - slider->moveTo(0); - max->block(false); - deal->block(false); + if(slider) + { + slider->setAmount(newAmount / r1); + slider->moveTo(0); + max->block(false); + deal->block(false); + } + else + { + deal->block(LOCPLINT->cb->getResourceAmount(hLeft->id) < r1); + } } else { - max->block(true); + if(slider) + { + max->block(true); + slider->setAmount(0); + slider->moveTo(0); + } deal->block(true); - slider->setAmount(0); - slider->moveTo(0); } + if(side && hLeft) //left selection changed, recalculate offers { rSubs.clear(); @@ -3057,7 +3132,10 @@ void CMarketplaceWindow::selectionChanged(bool side) int h1, h2; for(int i=0;igetOffer(hLeft->id, i, h1, h2, mode); + if(rtype != ARTIFACT) + market->getOffer(hLeft->id, i, h1, h2, mode); + else + market->getOffer(hLeft->id, right[i]->id, h1, h2, mode); std::ostringstream oss; oss << h2; @@ -3101,6 +3179,14 @@ void CMarketplaceWindow::getPositionsFor(std::vector &poss, bool Right, ET dx = 83; dy = 98; assert(!Right); + + case ARTIFACT://45,123 + x = 342-288; + y = 181; + w = 44; + h = 44; + dx = 83; + dy = 79; } @@ -3144,6 +3230,27 @@ void CMarketplaceWindow::garrisonChanged() } } +void CMarketplaceWindow::artifactsChanged(bool left) +{ + assert(!left); + if(mode != RESOURCE_ARTIFACT) + return; + + std::vector available = market->availableItemsIds(mode); + std::set toRemove; + BOOST_FOREACH(CTradeableItem *t, right) + if(!vstd::contains(available, t->id)) + toRemove.insert(t); + + BOOST_FOREACH(CTradeableItem *t, toRemove) + { + if(active) + t->deactivate(); + right -= t; + delChild(t); + } +} + CSystemOptionsWindow::CSystemOptionsWindow(const SDL_Rect &pos, CPlayerInterface * owner) { this->pos = pos; diff --git a/client/GUIClasses.h b/client/GUIClasses.h index f832c0eba..1b343eb80 100644 --- a/client/GUIClasses.h +++ b/client/GUIClasses.h @@ -596,6 +596,7 @@ public: void getPositionsFor(std::vector &poss, bool Right, EType type) const; void garrisonChanged(); //removes creatures with count 0 from the list (apparently whole stack has been sold) + void artifactsChanged(bool left); }; class CSystemOptionsWindow : public CIntObject diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 091fb66d3..3625d81d5 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -760,6 +760,21 @@ void NewObject::applyCl(CClient *cl) } } +void SetAvailableArtifacts::applyCl(CClient *cl) +{ + if(id < 0) //artifact merchants globally + { + for(std::map::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++) + i->second->availableArtifactsChanged(NULL); + } + else + { + const CGBlackMarket *bm = dynamic_cast(cl->getObj(id)); + assert(bm); + INTERFACE_CALL_IF_PRESENT(cl->getTile(bm->visitablePos())->visitableObjects.back()->tempOwner, availableArtifactsChanged, bm); + } +} + void TradeComponents::applyCl(CClient *cl) {///Shop handler switch (CGI->mh->map->objects[objectid]->ID) diff --git a/global.h b/global.h index b863c5aec..4b2e2087e 100644 --- a/global.h +++ b/global.h @@ -109,7 +109,7 @@ const int WEEKLY_GROWTH = 10; //percent enum EMarketMode { - RESOURCE_RESOURCE, RESOURCE_PLAYER, CREATURE_RESOURCE, ARTIFACT_RESOURCE, RESOURCE_ARTIFACT, ARTIFACT_EXP, CREATURE_EXP, + RESOURCE_RESOURCE, RESOURCE_PLAYER, CREATURE_RESOURCE, RESOURCE_ARTIFACT, ARTIFACT_RESOURCE, ARTIFACT_EXP, CREATURE_EXP, MARTKET_AFTER_LAST_PLACEHOLDER }; diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 48be84309..6913fd128 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -1945,6 +1945,22 @@ bool CGTownInstance::allowsTrade(EMarketMode mode) const } } +std::vector CGTownInstance::availableItemsIds(EMarketMode mode) const +{ + if(mode == RESOURCE_ARTIFACT) + { + std::vector ret; + BOOST_FOREACH(const CArtifact *a, merchantArtifacts) + if(a) + ret.push_back(a->id); + else + ret.push_back(-1); + return ret; + } + else + return IMarket::availableItemsIds(mode); +} + void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const { if(visitors.find(h->id)==visitors.end()) @@ -6107,6 +6123,21 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) val1 = 1; val2 = 1; break; + case RESOURCE_ARTIFACT: + { + float effectiveness = std::min(((float)getMarketEfficiency()+3.0f) / 20.0f, 0.6f); + float r = VLC->objh->resVals[id1], //value of offered resource + g = VLC->arth->artifacts[id2]->price / effectiveness; //value of bought artifact in gold + + if(id1 != 6) //non-gold prices are doubled + r /= 2; + + assert(g >= r); //should we allow artifacts cheaper than unit of resource? + val1 = (g / r) + 0.5f; + val2 = 1; + } + break; + default: assert(0); return false; @@ -6211,6 +6242,9 @@ bool CGMarket::allowsTrade(EMarketMode mode) const } case CREATURE_RESOURCE: return ID == 213; //Freelancer's Guild + case ARTIFACT_RESOURCE: + case RESOURCE_ARTIFACT: + return ID == 7; //Black Market } return false; } @@ -6258,12 +6292,13 @@ std::vector CGBlackMarket::availableItemsIds(EMarketMode mode) const } } -void CGBlackMarket::initObj() -{ - -} - void CGBlackMarket::newTurn() const { + if(cb->getDate(2) != 1) + return; + SetAvailableArtifacts saa; + saa.id = id; + cb->pickAllowedArtsSet(saa.arts); + cb->sendAndApply(&saa); } \ No newline at end of file diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index d1d4b8821..c041c28fd 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -513,6 +513,7 @@ public: void getOutOffsets(std::vector &offsets) const; //offsets to obj pos when we boat can be placed int getMarketEfficiency() const; //=market count bool allowsTrade(EMarketMode mode) const; + std::vector availableItemsIds(EMarketMode mode) const; void setPropertyDer(ui8 what, ui32 val); void newTurn() const; @@ -1166,13 +1167,13 @@ class DLL_EXPORT CGBlackMarket : public CGMarket public: std::vector artifacts; //available artifacts - void initObj(); void newTurn() const; //reset artifacts for black market every month std::vector availableItemsIds(EMarketMode mode) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); + h & artifacts; } }; diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index 0af3c5cc6..e1b5f9c09 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -196,6 +196,18 @@ void IGameCallback::getAllowedArts(std::vector &out, std::vector &out) +{ + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 3 ; j++) + { + out.push_back(VLC->arth->artifacts[getRandomArt(CArtifact::ART_TREASURE << i)]); + } + } + out.push_back(VLC->arth->artifacts[getRandomArt(CArtifact::ART_MAJOR)]); +} + void IGameCallback::getAllowed(std::vector &out, int flags) { if(flags & CArtifact::ART_TREASURE) @@ -269,4 +281,4 @@ inline TerrainTile * IGameCallback::getTile( int3 pos ) const PlayerState * IGameCallback::getPlayerState( int color ) { return gs->getPlayer(color, false); -} \ No newline at end of file +} diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index 7236b2623..198c49dd2 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -61,6 +61,7 @@ public: virtual bool isAllowed(int type, int id); //type: 0 - spell; 1- artifact virtual ui16 getRandomArt (int flags); virtual void getAllowedArts(std::vector &out, std::vector CArtHandler::*arts, int flag); + virtual void pickAllowedArtsSet(std::vector &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant virtual void getAllowed(std::vector &out, int flags); //flags: bitfield uses EartClass virtual void getAllowedSpells(std::vector &out, ui16 level); virtual int3 getMapSize(); //returns size of the map diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 8bb83462a..e38eb064c 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -647,7 +647,7 @@ struct NewObject : public CPackForClient //518 struct SetAvailableArtifacts : public CPackForClient //519 { SetAvailableArtifacts(){type = 519;}; - //void applyCl(CClient *cl); + void applyCl(CClient *cl); DLL_EXPORT void applyGs(CGameState *gs); si32 id; //two variants: id < 0: set artifact pool for Artifact Merchants in towns; id >= 0: set pool for adv. map Black Market (id is the id of Black Market instance then) diff --git a/lib/RegisterTypes.cpp b/lib/RegisterTypes.cpp index 6835fb6f7..7ef713749 100644 --- a/lib/RegisterTypes.cpp +++ b/lib/RegisterTypes.cpp @@ -63,6 +63,7 @@ void registerTypes1(Serializer &s) s.template registerType(); s.template registerType(); s.template registerType(); + s.template registerType(); } template DLL_EXPORT @@ -124,6 +125,7 @@ void registerTypes2(Serializer &s) s.template registerType(); s.template registerType(); s.template registerType(); + s.template registerType(); s.template registerType(); s.template registerType(); diff --git a/lib/map.cpp b/lib/map.cpp index 9249aa2ce..afc14d870 100644 --- a/lib/map.cpp +++ b/lib/map.cpp @@ -1949,7 +1949,6 @@ void Mapa::readObjects( const unsigned char * bufor, int &i) break; } //case 2: //Altar of Sacrifice - //case 7: //Black Market case 99: //Trading Post case 213: //Freelancer's Guild case 221: //Trading Post (snow) @@ -1957,6 +1956,11 @@ void Mapa::readObjects( const unsigned char * bufor, int &i) nobj = new CGMarket(); break; } + case 7: //Black Market + { + nobj = new CGBlackMarket(); + break; + } default: //any other object { diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index b1609ed55..1f81d29ab 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1042,6 +1042,14 @@ void CGameHandler::newTurn() //unhiding what shouldn't be hidden? //that's handled in netpacks client } + if(getDate(2) == 1) + { + SetAvailableArtifacts saa; + saa.id = -1; + pickAllowedArtsSet(saa.arts); + sendAndApply(&saa); + } + sendAndApply(&n); tlog5 << "Info about turn " << n.day << "has been sent!" << std::endl; handleTimeEvents(); @@ -3032,6 +3040,56 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid ) return false; } +bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, int rid, int aid) +{ + if(!vstd::contains(m->availableItemsIds(RESOURCE_ARTIFACT), aid)) + COMPLAIN_RET("That artifact is unavailable!"); + + int b1, b2; + m->getOffer(rid, aid, b1, b2, RESOURCE_ARTIFACT); + + if(getResource(h->tempOwner, rid) < b1) + COMPLAIN_RET("You can't afford to buy this artifact!"); + + SetResource sr; + sr.player = h->tempOwner; + sr.resid = rid; + sr.val = getResource(h->tempOwner, rid) - b1; + sendAndApply(&sr); + + + SetAvailableArtifacts saa; + if(m->o->ID == TOWNI_TYPE) + { + saa.id = -1; + saa.arts = CGTownInstance::merchantArtifacts; + } + else if(const CGBlackMarket *bm = dynamic_cast(m->o)) //black market + { + saa.id = bm->id; + saa.arts = bm->artifacts; + } + else + COMPLAIN_RET("Wrong marktet..."); + + bool found = false; + BOOST_FOREACH(const CArtifact *&art, saa.arts) + { + if(art && art->id == aid) + { + art = NULL; + found = true; + break; + } + } + + if(!found) + COMPLAIN_RET("Cannot find selected artifact on the list"); + + sendAndApply(&saa); + + giveHeroArtifact(aid, h->id, -2); +} bool CGameHandler::tradeResources(const IMarket *market, ui32 val, ui8 player, ui32 id1, ui32 id2) { diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 6010b9506..15195cec1 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -172,7 +172,8 @@ public: bool sendResources(ui32 val, ui8 player, ui32 r1, ui32 r2); bool sellCreatures(ui32 count, const IMarket *market, const CGHeroInstance * hero, ui32 slot, ui32 resourceID); bool assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assemble, ui32 assembleTo); - bool buyArtifact( ui32 hid, si32 aid ); + bool buyArtifact( ui32 hid, si32 aid ); //for blacksmith and mage guild only -> buying for gold in common buildings + bool buyArtifact( const IMarket *m, const CGHeroInstance *h, int rid, int aid); //for artifact merchant and black market -> buying for any resource in special building / advobject bool swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot); bool garrisonSwap(si32 tid); bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID ); diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index f4229f3bd..af802e6e2 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -145,9 +145,12 @@ bool TradeOnMarketplace::applyGh( CGameHandler *gh ) if(!hero) COMPLAIN_AND_RETURN("Only hero can sell creatures!"); return gh->sellCreatures(val, m, hero, r1, r2); + case RESOURCE_ARTIFACT: + if(!hero) + COMPLAIN_AND_RETURN("Only hero can buy artifacts!"); + return gh->buyArtifact(m, hero, r1, r2); default: - gh->complain("Unknown exchange mode!"); - ERROR_AND_RETURN; + COMPLAIN_AND_RETURN("Unknown exchange mode!"); } }