mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Trading Post handling.
This commit is contained in:
parent
71b73bad53
commit
1002bd2b4f
@ -732,25 +732,6 @@ std::vector < const CGObjectInstance * > CCallback::getVisitableObjs( int3 pos )
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CCallback::getMarketOffer( int t1, int t2, int &give, int &rec, int mode/*=0*/ ) const
|
||||
{
|
||||
if(mode) return; //TODO - support
|
||||
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
|
||||
//if(gs->resVals[t1] >= gs->resVals[t2])
|
||||
float r = gs->resVals[t1], //price of given resource
|
||||
g = gs->resVals[t2] / gs->getMarketEfficiency(player,mode); //price of wanted resource
|
||||
if(r>g) //if given resource is more expensive than wanted
|
||||
{
|
||||
rec = ceil(r / g);
|
||||
give = 1;
|
||||
}
|
||||
else //if wanted resource is more expensive
|
||||
{
|
||||
give = ceil(g / r);
|
||||
rec = 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector < const CGObjectInstance * > CCallback::getFlaggableObjects(int3 pos) const
|
||||
{
|
||||
if(!isVisible(pos))
|
||||
@ -772,11 +753,15 @@ int3 CCallback::getMapSize() const
|
||||
return CGI->mh->sizes;
|
||||
}
|
||||
|
||||
void CCallback::trade( int mode, int id1, int id2, int val1 )
|
||||
void CCallback::trade(const CGObjectInstance *market, int mode, int id1, int id2, int val1, const CGHeroInstance *hero/* = NULL*/)
|
||||
{
|
||||
int p1, p2;
|
||||
getMarketOffer(id1,id2,p1,p2,mode);
|
||||
TradeOnMarketplace pack(player,mode,id1,id2,val1);
|
||||
TradeOnMarketplace pack;
|
||||
pack.market = market;
|
||||
pack.hero = hero;
|
||||
pack.mode = mode;
|
||||
pack.r1 = id1;
|
||||
pack.r2 = id2;
|
||||
pack.val = val1;
|
||||
sendRequest(&pack);
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ public:
|
||||
virtual bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1)=0; //if newID==-1 then best possible upgrade will be made
|
||||
virtual void swapGarrisonHero(const CGTownInstance *town)=0;
|
||||
|
||||
virtual void trade(int mode, int id1, int id2, int val1)=0; //mode==0: sell val1 units of id1 resource for id2 resiurce
|
||||
virtual void trade(const CGObjectInstance *market, int mode, int id1, int id2, int val1, const CGHeroInstance *hero = NULL)=0; //mode==0: sell val1 units of id1 resource for id2 resiurce
|
||||
|
||||
virtual void selectionMade(int selection, int asker) =0;
|
||||
virtual int swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)=0;//swaps creatures between two posiibly different garrisons // TODO: AI-unsafe code - fix it!
|
||||
@ -146,7 +146,6 @@ public:
|
||||
virtual std::vector<const CGHeroInstance *> getAvailableHeroes(const CGTownInstance * town) const =0; //heroes that can be recruited
|
||||
virtual int canBuildStructure(const CGTownInstance *t, int ID) =0;//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
|
||||
virtual std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID) =0;
|
||||
virtual void getMarketOffer(int t1, int t2, int &give, int &rec, int mode=0)const =0; //t1 - type of given resource, t2 - type of received resource; give is the amount of resource t1 that can be traded for amount rec of resource t2 (one of them is 1)
|
||||
virtual bool getTownInfo(const CGObjectInstance *town, InfoAboutTown &dest) const = 0;
|
||||
|
||||
virtual UpgradeInfo getUpgradeInfo(const CArmedInstance *obj, int stackPos)const =0;
|
||||
@ -226,7 +225,7 @@ public:
|
||||
void endTurn();
|
||||
void swapGarrisonHero(const CGTownInstance *town);
|
||||
void buyArtifact(const CGHeroInstance *hero, int aid);
|
||||
void trade(int mode, int id1, int id2, int val1);
|
||||
void trade(const CGObjectInstance *market, int mode, int id1, int id2, int val1, const CGHeroInstance *hero = NULL);
|
||||
void setFormation(const CGHeroInstance * hero, bool tight);
|
||||
void setSelection(const CArmedInstance * obj);
|
||||
void recruitHero(const CGTownInstance *town, const CGHeroInstance *hero);
|
||||
@ -265,7 +264,6 @@ public:
|
||||
|
||||
std::vector < const CGObjectInstance * > getBlockingObjs(int3 pos) const;
|
||||
std::vector < const CGObjectInstance * > getVisitableObjs(int3 pos) const;
|
||||
void getMarketOffer(int t1, int t2, int &give, int &rec, int mode=0) const; //t1 - type of given resource, t2 - type of received resource; give is the amount of resource t1 that can be traded for amount rec of resource t2 (one of them is 1)
|
||||
std::vector < const CGObjectInstance * > getFlaggableObjects(int3 pos) const;
|
||||
int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map
|
||||
std::vector<const CGHeroInstance *> getAvailableHeroes(const CGTownInstance * town) const; //heroes that can be recruited
|
||||
|
@ -31,6 +31,7 @@ class CGDwelling;
|
||||
class CCreatureSet;
|
||||
class CArmedInstance;
|
||||
class IShipyard;
|
||||
class IMarket;
|
||||
struct BattleResult;
|
||||
struct BattleAttack;
|
||||
struct BattleStackAttacked;
|
||||
@ -81,6 +82,7 @@ public:
|
||||
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const int soundID, bool selection, bool cancel) = 0; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
|
||||
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd) = 0; //all stacks operations between these objects become allowed, interface has to call onEnd when done
|
||||
virtual void showPuzzleMap(){};
|
||||
virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor){};
|
||||
virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID){}; //called when a hero casts a spell
|
||||
virtual void tileHidden(const std::set<int3> &pos){};
|
||||
virtual void tileRevealed(const std::set<int3> &pos){};
|
||||
|
@ -2,6 +2,7 @@
|
||||
GENERAL:
|
||||
* It's possible to start campaign
|
||||
* Support for build grail victory condition
|
||||
* New artifacts supported: Angel's Wings and Boots of levitation
|
||||
|
||||
ADVENTURE MAP:
|
||||
* Creatures now guard surrounding tiles
|
||||
@ -9,6 +10,8 @@ ADVENTURE MAP:
|
||||
- Summon Boat
|
||||
- Scuttle Boat
|
||||
- Dimension Door
|
||||
- Fly
|
||||
- Water walk
|
||||
|
||||
BATTLES:
|
||||
* A number of new creature abilities supported
|
||||
@ -33,6 +36,7 @@ TOWNS:
|
||||
|
||||
OBJECTS:
|
||||
New object supported:
|
||||
- Trading Post
|
||||
- War Machine Factory
|
||||
|
||||
0.75 -> 0.8 (Mar 01 2010)
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "CPreGame.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
#include "../hch/CSpellHandler.h"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable : 4355)
|
||||
@ -1521,15 +1522,19 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
|
||||
//act on key down if marketplace windows is not already opened
|
||||
if(key.state != SDL_PRESSED || GH.topInt()->type & BLOCK_ADV_HOTKEYS) return;
|
||||
|
||||
//check if we have aby marketplace
|
||||
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo();
|
||||
size_t i = 0;
|
||||
for(; i<towns.size(); i++)
|
||||
if(vstd::contains(towns[i]->builtBuildings, 14))
|
||||
//check if we have any marketplace
|
||||
const CGTownInstance *townWithMarket = NULL;
|
||||
BOOST_FOREACH(const CGTownInstance *t, LOCPLINT->cb->getTownsInfo())
|
||||
{
|
||||
if(vstd::contains(t->builtBuildings, 14))
|
||||
{
|
||||
townWithMarket = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i != towns.size()) //if any town has marketplace, open window
|
||||
GH.pushInt(new CMarketplaceWindow);
|
||||
if(townWithMarket) //if any town has marketplace, open window
|
||||
GH.pushInt(new CMarketplaceWindow(townWithMarket));
|
||||
else //if not - complain
|
||||
LOCPLINT->showInfoDialog("No available marketplace!", std::vector<SComponent*>(), soundBase::sound_todo);
|
||||
return;
|
||||
|
@ -635,7 +635,7 @@ void CCastleInterface::buildingClicked(int building)
|
||||
break;
|
||||
case 14: //marketplace
|
||||
{
|
||||
CMarketplaceWindow *cmw = new CMarketplaceWindow();
|
||||
CMarketplaceWindow *cmw = new CMarketplaceWindow(town);
|
||||
GH.pushInt(cmw);
|
||||
break;
|
||||
}
|
||||
|
@ -1973,4 +1973,10 @@ void CPlayerInterface::stopMovement()
|
||||
{
|
||||
if(stillMoveHero.get() == DURING_MOVE)//if we are in the middle of hero movement
|
||||
stillMoveHero.setn(STOP_MOVE); //after showing dialog movement will be stopped
|
||||
}
|
||||
|
||||
void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor)
|
||||
{
|
||||
CMarketplaceWindow *cmw = new CMarketplaceWindow(market, market->availableModes().front());
|
||||
GH.pushInt(cmw);
|
||||
}
|
@ -161,6 +161,7 @@ public:
|
||||
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd);
|
||||
void showArtifactAssemblyDialog(ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList<void()> onYes, CFunctionList<void()> onNo);
|
||||
void showPuzzleMap();
|
||||
void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor);
|
||||
void advmapSpellCast(const CGHeroInstance * caster, int spellID); //called when a hero casts a spell
|
||||
void tileHidden(const std::set<int3> &pos); //called when given tiles become hidden under fog of war
|
||||
void tileRevealed(const std::set<int3> &pos); //called when fog of war disappears from given tiles
|
||||
|
@ -2655,7 +2655,8 @@ static void initItems( std::vector<CMarketplaceWindow::CTradeableItem*> &i, std:
|
||||
i[j]->pos = p[j] + i[j]->pos;
|
||||
}
|
||||
}
|
||||
CMarketplaceWindow::CMarketplaceWindow(int Mode)
|
||||
CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, EMarketMode Mode)
|
||||
:market(Market)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
type = BLOCK_ADV_HOTKEYS;
|
||||
@ -2808,7 +2809,7 @@ void CMarketplaceWindow::setMax()
|
||||
|
||||
void CMarketplaceWindow::makeDeal()
|
||||
{
|
||||
LOCPLINT->cb->trade(mode,hLeft->id,hRight->id,slider->value*r1);
|
||||
LOCPLINT->cb->trade(market->o, mode, hLeft->id, hRight->id, slider->value*r1);
|
||||
slider->moveTo(0);
|
||||
hLeft = NULL;
|
||||
selectionChanged(true);
|
||||
@ -2824,7 +2825,7 @@ void CMarketplaceWindow::selectionChanged(bool side)
|
||||
{
|
||||
if(mode == RESOURCE_RESOURCE)
|
||||
{
|
||||
LOCPLINT->cb->getMarketOffer(hLeft->id,hRight->id,r1,r2,0);
|
||||
market->getOffer(hLeft->id, hRight->id, r1, r2, mode);
|
||||
slider->setAmount(LOCPLINT->cb->getResourceAmount(hLeft->id) / r1);
|
||||
}
|
||||
else if(mode == RESOURCE_PLAYER)
|
||||
@ -2850,8 +2851,9 @@ void CMarketplaceWindow::selectionChanged(bool side)
|
||||
int h1, h2;
|
||||
for(int i=0;i<right.size();i++)
|
||||
{
|
||||
market->getOffer(hLeft->id, i, h1, h2, RESOURCE_RESOURCE);
|
||||
|
||||
std::ostringstream oss;
|
||||
LOCPLINT->cb->getMarketOffer(hLeft->id,i,h1,h2,0);
|
||||
oss << h2;
|
||||
if(h1!=1)
|
||||
oss << "/" << h1;
|
||||
@ -2880,10 +2882,11 @@ void CMarketplaceWindow::getPositionsFor(std::vector<Rect> &poss, bool Right, ET
|
||||
}
|
||||
}
|
||||
|
||||
void CMarketplaceWindow::setMode(int Mode)
|
||||
void CMarketplaceWindow::setMode(EMarketMode Mode)
|
||||
{
|
||||
CMarketplaceWindow *nwindow = new CMarketplaceWindow(market, Mode);
|
||||
GH.popIntTotally(this);
|
||||
GH.pushInt(new CMarketplaceWindow(Mode));
|
||||
GH.pushInt(nwindow);
|
||||
}
|
||||
|
||||
CSystemOptionsWindow::CSystemOptionsWindow(const SDL_Rect &pos, CPlayerInterface * owner)
|
||||
|
@ -65,6 +65,7 @@ class CResDataBar;
|
||||
struct SPuzzleInfo;
|
||||
class CGGarrison;
|
||||
class CStackInstance;
|
||||
class IMarket;
|
||||
|
||||
extern SDL_Color tytulowy, tlo, zwykly ;
|
||||
|
||||
@ -536,14 +537,15 @@ public:
|
||||
CTradeableItem(int Type, int ID, bool Left);
|
||||
};
|
||||
|
||||
const IMarket *market;
|
||||
CPicture *bg; //background
|
||||
std::vector<CTradeableItem*> left, right;
|
||||
std::vector<std::string> rSubs; //offer caption
|
||||
CTradeableItem *hLeft, *hRight; //highlighted items (NULL if no highlight)
|
||||
|
||||
EType ltype, rtype;
|
||||
int mode,//0 - res<->res; 1 - res<->plauer; 2 - buy artifact; 3 - sell artifact
|
||||
r1, r2; //suggested amounts of traded resources
|
||||
EMarketMode mode;//0 - res<->res; 1 - res<->plauer; 2 - buy artifact; 3 - sell artifact
|
||||
int r1, r2; //suggested amounts of traded resources
|
||||
AdventureMapButton *ok, *max, *deal;
|
||||
CSlider *slider; //for choosing amount to be exchanged
|
||||
|
||||
@ -552,9 +554,9 @@ public:
|
||||
void sliderMoved(int to);
|
||||
void makeDeal();
|
||||
void selectionChanged(bool side); //true == left
|
||||
CMarketplaceWindow(int Mode = RESOURCE_RESOURCE); //c-tor
|
||||
CMarketplaceWindow(const IMarket *Market, EMarketMode Mode = RESOURCE_RESOURCE); //c-tor
|
||||
~CMarketplaceWindow(); //d-tor
|
||||
void setMode(int Mode); //mode setter
|
||||
void setMode(EMarketMode Mode); //mode setter
|
||||
|
||||
void getPositionsFor(std::vector<Rect> &poss, bool Right, EType type) const;
|
||||
};
|
||||
|
@ -720,6 +720,15 @@ void OpenWindow::applyCl(CClient *cl)
|
||||
GH.pushInt( new CThievesGuildWindow(obj) );
|
||||
}
|
||||
break;
|
||||
case MARKET_WINDOW:
|
||||
{
|
||||
//displays Thieves' Guild window (when hero enters Den of Thieves)
|
||||
const CGObjectInstance *obj = cl->getObj(id1);
|
||||
const CGHeroInstance *hero = cl->getHero(id2);
|
||||
const IMarket *market = IMarket::castFrom(obj);
|
||||
INTERFACE_CALL_IF_PRESENT(cl->getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, showMarketWindow, market, hero);
|
||||
}
|
||||
break;
|
||||
case PUZZLE_MAP:
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(id1, showPuzzleMap);
|
||||
|
3
global.h
3
global.h
@ -107,7 +107,8 @@ const int SPELL_LEVELS = 5;
|
||||
|
||||
enum EMarketMode
|
||||
{
|
||||
RESOURCE_RESOURCE, RESOURCE_PLAYER, CREATURE_RESOURCE, ARTIFACT_RESOURCE
|
||||
RESOURCE_RESOURCE, RESOURCE_PLAYER, CREATURE_RESOURCE, ARTIFACT_RESOURCE, RESOURCE_ARTIFACT, ARTIFACT_EXP, CREATURE_EXP,
|
||||
MARTKET_AFTER_LAST_PLACEHOLDER
|
||||
};
|
||||
|
||||
//uncomment to make it work
|
||||
|
@ -144,8 +144,24 @@ void CObjectHandler::loadObjects()
|
||||
cregens[dw]=cr;
|
||||
}
|
||||
tlog5 << "\t\tDone loading objects!\n";
|
||||
|
||||
ifs.close();
|
||||
ifs.clear();
|
||||
|
||||
int k = -1;
|
||||
ifs.open(DATA_DIR "/config/resources.txt");
|
||||
ifs >> k;
|
||||
int pom;
|
||||
for(int i=0;i<k;i++)
|
||||
{
|
||||
ifs >> pom;
|
||||
resVals.push_back(pom);
|
||||
}
|
||||
tlog5 << "\t\tDone loading resource prices!\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::ifstream istr;
|
||||
istr.open(DATA_DIR "/config/bankconfig.txt", std::ios_base::binary);
|
||||
if(!istr.is_open())
|
||||
@ -1567,7 +1583,7 @@ bool CGTownInstance::hasCapitol() const
|
||||
return (builtBuildings.find(13))!=builtBuildings.end();
|
||||
}
|
||||
CGTownInstance::CGTownInstance()
|
||||
:IShipyard(this)
|
||||
:IShipyard(this), IMarket(this)
|
||||
{
|
||||
builded=-1;
|
||||
destroyed=-1;
|
||||
@ -1802,6 +1818,39 @@ void CGTownInstance::getBonuses(BonusList &out, const CSelector &selector, const
|
||||
}
|
||||
}
|
||||
|
||||
int CGTownInstance::getMarketEfficiency() const
|
||||
{
|
||||
if(!vstd::contains(builtBuildings, 14))
|
||||
return 0;
|
||||
|
||||
const PlayerState *p = cb->getPlayerState(tempOwner);
|
||||
assert(p);
|
||||
|
||||
int marketCount = 0;
|
||||
BOOST_FOREACH(const CGTownInstance *t, p->towns)
|
||||
if(vstd::contains(t->builtBuildings, 14))
|
||||
marketCount++;
|
||||
|
||||
return marketCount;
|
||||
}
|
||||
|
||||
bool CGTownInstance::allowsTrade(EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case RESOURCE_RESOURCE:
|
||||
case RESOURCE_PLAYER:
|
||||
return vstd::contains(builtBuildings, 14); // marketplace
|
||||
case ARTIFACT_RESOURCE:
|
||||
return (subID == 2 || subID == 5 || subID == 8) && vstd::contains(builtBuildings, 17);//artifact merchants
|
||||
case CREATURE_RESOURCE:
|
||||
return subID == 6 && vstd::contains(builtBuildings, 21); //Freelancer's guild
|
||||
default:
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
if(visitors.find(h->id)==visitors.end())
|
||||
@ -5859,4 +5908,153 @@ void CArmedInstance::getBonuses(BonusList &out, const CSelector &selector, const
|
||||
out.push_back(Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, -1, id, VLC->generaltexth->arraytxt[116]));//Undead in group -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case RESOURCE_RESOURCE:
|
||||
{
|
||||
float effectiveness = std::min(((float)getMarketEfficiency()+1.0f) / 20.0f, 0.5f);
|
||||
|
||||
float r = VLC->objh->resVals[id1], //value of given resource
|
||||
g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
|
||||
|
||||
if(r>g) //if given resource is more expensive than wanted
|
||||
{
|
||||
val2 = ceil(r / g);
|
||||
val1 = 1;
|
||||
}
|
||||
else //if wanted resource is more expensive
|
||||
{
|
||||
val1 = (g / r) + 0.5f;
|
||||
val2 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IMarket::allowsTrade(EMarketMode mode) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int IMarket::availableUnits(EMarketMode mode, int marketItemSerial) const
|
||||
{
|
||||
if(mode == RESOURCE_RESOURCE || ARTIFACT_RESOURCE || CREATURE_RESOURCE)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<int> IMarket::availableItemsIds(EMarketMode mode) const
|
||||
{
|
||||
std::vector<int> ret;
|
||||
if(mode == RESOURCE_RESOURCE || ARTIFACT_RESOURCE || CREATURE_RESOURCE)
|
||||
for (int i = 0; i < 7; i++)
|
||||
ret.push_back(i);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const IMarket * IMarket::castFrom(const CGObjectInstance *obj)
|
||||
{
|
||||
switch(obj->ID)
|
||||
{
|
||||
case TOWNI_TYPE:
|
||||
return static_cast<const CGTownInstance*>(obj);
|
||||
case 99: //Trading Post
|
||||
case 221: //Trading Post (snow)
|
||||
return static_cast<const CGMarket*>(obj);
|
||||
default:
|
||||
tlog1 << "Cannot cast to IMarket object with ID " << obj->ID << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
IMarket::IMarket(const CGObjectInstance *O)
|
||||
:o(O)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::vector<EMarketMode> IMarket::availableModes() const
|
||||
{
|
||||
std::vector<EMarketMode> ret;
|
||||
for (int i = 0; i < MARTKET_AFTER_LAST_PLACEHOLDER; i++)
|
||||
if(allowsTrade((EMarketMode)i))
|
||||
ret.push_back((EMarketMode)i);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CGMarket::onHeroVisit(const CGHeroInstance * h) const
|
||||
{
|
||||
OpenWindow ow;
|
||||
ow.id1 = id;
|
||||
ow.id2 = h->id;
|
||||
ow.window = OpenWindow::MARKET_WINDOW;
|
||||
cb->sendAndApply(&ow);
|
||||
}
|
||||
|
||||
void CGMarket::initObj()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CGMarket::newTurn() const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int CGMarket::getMarketEfficiency() const
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
bool CGMarket::allowsTrade(EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case RESOURCE_RESOURCE:
|
||||
case RESOURCE_PLAYER:
|
||||
switch(ID)
|
||||
{
|
||||
case 99: //Trading Post
|
||||
case 221: //Trading Post (snow)
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CGMarket::availableUnits(EMarketMode mode, int marketItemSerial) const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<int> CGMarket::availableItemsIds(EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case RESOURCE_RESOURCE:
|
||||
case RESOURCE_PLAYER:
|
||||
return IMarket::availableItemsIds(mode);
|
||||
default:
|
||||
return std::vector<int>();
|
||||
}
|
||||
}
|
||||
|
||||
CGMarket::CGMarket()
|
||||
:IMarket(this)
|
||||
{
|
||||
}
|
@ -141,18 +141,22 @@ public:
|
||||
static IShipyard *castFrom(CGObjectInstance *obj);
|
||||
};
|
||||
|
||||
/*class DLL_EXPORT IMarket
|
||||
{
|
||||
public:
|
||||
const CGObjectInstance *o;
|
||||
|
||||
IMarket(const CGObjectInstance *O);
|
||||
virtual bool allowsMode(EMarketMode mode);
|
||||
virtual float getEfficiency(EMarketMode mode);
|
||||
|
||||
static const IMarket *castFrom(const CGObjectInstance *obj);
|
||||
static IMarket castFrom(CGObjectInstance *obj);
|
||||
};*/
|
||||
class DLL_EXPORT IMarket
|
||||
{
|
||||
virtual int getMarketEfficiency() const =0;
|
||||
public:
|
||||
const CGObjectInstance *o;
|
||||
|
||||
IMarket(const CGObjectInstance *O);
|
||||
virtual bool allowsTrade(EMarketMode mode) const;
|
||||
virtual int availableUnits(EMarketMode mode, int marketItemSerial) const; //-1 if unlimited
|
||||
virtual std::vector<int> availableItemsIds(EMarketMode mode) const;
|
||||
|
||||
bool getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const; //val1 - how many units of id1 player has to give to receive val2 units
|
||||
std::vector<EMarketMode> availableModes() const;
|
||||
|
||||
static const IMarket *castFrom(const CGObjectInstance *obj);
|
||||
};
|
||||
|
||||
class DLL_EXPORT CGObjectInstance : public IObjectInterface
|
||||
{
|
||||
@ -446,6 +450,7 @@ public:
|
||||
h & visitors;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_EXPORT CTownBonus : public CGTownBuilding
|
||||
{
|
||||
///used for one-time bonusing structures
|
||||
@ -463,7 +468,8 @@ public:
|
||||
h & visitors;
|
||||
}
|
||||
};
|
||||
class DLL_EXPORT CGTownInstance : public CGDwelling, public IShipyard
|
||||
|
||||
class DLL_EXPORT CGTownInstance : public CGDwelling, public IShipyard, public IMarket
|
||||
{
|
||||
public:
|
||||
CTown * town;
|
||||
@ -505,6 +511,8 @@ public:
|
||||
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<int3> &offsets) const; //offsets to obj pos when we boat can be placed
|
||||
int getMarketEfficiency() const; //=market count
|
||||
bool allowsTrade(EMarketMode mode) const;
|
||||
void setPropertyDer(ui8 what, ui32 val);
|
||||
void newTurn() const;
|
||||
|
||||
@ -1121,7 +1129,7 @@ public:
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CPlayersVisited&>(*this);;
|
||||
h & static_cast<CPlayersVisited&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1134,11 +1142,30 @@ public:
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);;
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
}
|
||||
void giveBonusTo( ui8 player ) const;
|
||||
};
|
||||
|
||||
class DLL_EXPORT CGMarket : public CGObjectInstance, public IMarket
|
||||
{
|
||||
public:
|
||||
CGMarket();
|
||||
void onHeroVisit(const CGHeroInstance * h) const; //open trading window
|
||||
void initObj();
|
||||
void newTurn() const; //reset artifacts for black market every month
|
||||
|
||||
int getMarketEfficiency() const;
|
||||
bool allowsTrade(EMarketMode mode) const;
|
||||
int availableUnits(EMarketMode mode, int marketItemSerial) const; //-1 if unlimited
|
||||
std::vector<int> availableItemsIds(EMarketMode mode) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
struct BankConfig
|
||||
{
|
||||
BankConfig() {level = chance = upgradeChance = combatValue = value = rewardDifficulty = easiest = 0; };
|
||||
@ -1166,12 +1193,13 @@ public:
|
||||
std::vector<si32> cregens; //type 17. dwelling subid -> creature ID
|
||||
std::map <ui32, std::vector <BankConfig*> > banksInfo; //[index][preset]
|
||||
std::map <ui32, std::string> creBanksNames; //[crebank index] -> name of this creature bank
|
||||
std::vector<ui32> resVals; //default values of resources in gold
|
||||
|
||||
void loadObjects();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & cregens & banksInfo & creBanksNames;
|
||||
h & cregens & banksInfo & creBanksNames & resVals;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1347,14 +1347,6 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
(*i).second.resources[x] = startres[x];
|
||||
}
|
||||
|
||||
tis.open(DATA_DIR "/config/resources.txt");
|
||||
tis >> k;
|
||||
int pom;
|
||||
for(int i=0;i<k;i++)
|
||||
{
|
||||
tis >> pom;
|
||||
resVals.push_back(pom);
|
||||
}
|
||||
|
||||
/*************************HEROES************************************************/
|
||||
std::set<int> hids;
|
||||
@ -1735,18 +1727,6 @@ UpgradeInfo CGameState::getUpgradeInfo(const CArmedInstance *obj, int stackPos)
|
||||
return ret;
|
||||
}
|
||||
|
||||
float CGameState::getMarketEfficiency( int player, int mode/*=0*/ )
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lock(*mx);
|
||||
if(mode) return -1; //todo - support other modes
|
||||
int mcount = 0;
|
||||
for(unsigned int i=0;i<getPlayer(player)->towns.size();i++)
|
||||
if(vstd::contains(getPlayer(player)->towns[i]->builtBuildings,14))
|
||||
mcount++;
|
||||
float ret = std::min(((float)mcount+1.0f)/20.0f,0.5f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CGameState::loadTownDInfos()
|
||||
{
|
||||
for(int i=0;i<F_NUMBER;i++)
|
||||
|
@ -378,7 +378,6 @@ public:
|
||||
Mapa * map;
|
||||
std::map<ui8, PlayerState> players; //ID <-> player state
|
||||
std::map<int, CGDefInfo*> villages, forts, capitols; //def-info for town graphics
|
||||
std::vector<ui32> resVals; //default values of resources in gold
|
||||
CBonusSystemNode globalEffects;
|
||||
|
||||
struct DLL_EXPORT HeroesPool
|
||||
@ -417,7 +416,7 @@ public:
|
||||
si8 battleMaxSpellLevel(); //calculates maximum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, SPELL_LEVELS is returned
|
||||
bool battleCanShoot(int ID, int dest); //determines if stack with given ID shoot at the selected destination
|
||||
UpgradeInfo getUpgradeInfo(const CArmedInstance *obj, int stackPos);
|
||||
float getMarketEfficiency(int player, int mode=0);
|
||||
//float getMarketEfficiency(int player, int mode=0);
|
||||
std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID);
|
||||
int canBuildStructure(const CGTownInstance *t, int ID);// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
|
||||
bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if src tile is visitable from dst tile
|
||||
@ -441,7 +440,7 @@ public:
|
||||
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 <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & scenarioOps & seed & currentPlayer & day & map & players & resVals & hpool & globalEffects & campaign;
|
||||
h & scenarioOps & seed & currentPlayer & day & map & players & hpool & globalEffects & campaign;
|
||||
if(!h.saving)
|
||||
{
|
||||
loadTownDInfos();
|
||||
|
@ -615,7 +615,7 @@ struct OpenWindow : public CPackForClient //517
|
||||
OpenWindow(){type = 517;};
|
||||
void applyCl(CClient *cl);
|
||||
|
||||
enum EWindow {EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL, SHIPYARD_WINDOW, THIEVES_GUILD, PUZZLE_MAP};
|
||||
enum EWindow {EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL, SHIPYARD_WINDOW, THIEVES_GUILD, PUZZLE_MAP, MARKET_WINDOW};
|
||||
ui8 window;
|
||||
ui32 id1, id2;
|
||||
|
||||
@ -673,7 +673,7 @@ struct NewTurn : public CPackForClient //101
|
||||
|
||||
struct Component : public CPack //2002 helper for object scrips informations
|
||||
{
|
||||
enum {PRIM_SKILL, SEC_SKILL, RESOURCE, CREATURE, ARTIFACT, EXPERIENCE, SPELL, MORALE=8, LUCK, BUILDING, HERO, FLAG};
|
||||
enum EComponentType {PRIM_SKILL, SEC_SKILL, RESOURCE, CREATURE, ARTIFACT, EXPERIENCE, SPELL, MORALE=8, LUCK, BUILDING, HERO, FLAG};
|
||||
ui16 id, subtype; //id uses ^^^ enums, when id==EXPPERIENCE subtype==0 means exp points and subtype==1 levels)
|
||||
si32 val; // + give; - take
|
||||
si16 when; // 0 - now; +x - within x days; -x - per x days
|
||||
@ -1361,18 +1361,17 @@ struct BuyArtifact : public CPackForServer
|
||||
struct TradeOnMarketplace : public CPackForServer
|
||||
{
|
||||
TradeOnMarketplace(){};
|
||||
TradeOnMarketplace(ui8 Player, ui8 Mode, /*si32 ID, */ui32 R1, ui32 R2, ui32 Val)
|
||||
:player(Player),mode(Mode),/*id(ID),*/r1(R1),r2(R2),val(Val){};
|
||||
ui8 player;
|
||||
|
||||
const CGObjectInstance *market;
|
||||
const CGHeroInstance *hero; //needed when trading artifacts / creatures
|
||||
ui8 mode;//0 - res<->res;
|
||||
//si32 id; //object id
|
||||
ui32 r1, r2; //mode 0: r1 - sold resource, r2 - bought res
|
||||
ui32 val; //units of sold resource
|
||||
|
||||
bool applyGh(CGameHandler *gh);
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & player & mode & /*id & */r1 & r2 & val;
|
||||
h & market & hero & mode & r1 & r2 & val;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -62,6 +62,7 @@ void registerTypes1(Serializer &s)
|
||||
s.template registerType<CGDenOfthieves>();
|
||||
s.template registerType<CGObelisk>();
|
||||
s.template registerType<CGLighthouse>();
|
||||
s.template registerType<CGMarket>();
|
||||
}
|
||||
|
||||
template<typename Serializer> DLL_EXPORT
|
||||
|
10
lib/map.cpp
10
lib/map.cpp
@ -1935,6 +1935,16 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
|
||||
nobj->tempOwner = readNormalNr(bufor,i); i+=4;
|
||||
break;
|
||||
}
|
||||
case 2: //Altar of Sacrifice
|
||||
case 7: //Black Market
|
||||
case 99: //Trading Post
|
||||
case 213: //Freelancer's Guild
|
||||
case 221: //Trading Post (snow)
|
||||
{
|
||||
nobj = new CGMarket();
|
||||
break;
|
||||
}
|
||||
|
||||
default: //any other object
|
||||
{
|
||||
nobj = new CGObjectInstance();
|
||||
|
@ -2968,24 +2968,38 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CGameHandler::tradeResources( ui32 val, ui8 player, ui32 id1, ui32 id2 )
|
||||
|
||||
bool CGameHandler::tradeResources(const IMarket *market, ui32 val, ui8 player, ui32 id1, ui32 id2)
|
||||
{
|
||||
val = std::min(si32(val),gs->getPlayer(player)->resources[id1]);
|
||||
double yield = (double)gs->resVals[id1] * val * gs->getMarketEfficiency(player);
|
||||
yield /= gs->resVals[id2];
|
||||
int r1 = gs->getPlayer(player)->resources[id1],
|
||||
r2 = gs->getPlayer(player)->resources[id2];
|
||||
|
||||
amin(val, r1); //can't trade more resources than have
|
||||
|
||||
int b1, b2; //base quantities for trade
|
||||
market->getOffer(id1, id2, b1, b2, RESOURCE_RESOURCE);
|
||||
int units = val / b1; //how many base quantities we trade
|
||||
|
||||
if(val%b1) //all offered units of resource should be used, if not -> somewhere in calculations must be an error
|
||||
{
|
||||
//TODO: complain?
|
||||
assert(0);
|
||||
}
|
||||
|
||||
SetResource sr;
|
||||
sr.player = player;
|
||||
sr.resid = id1;
|
||||
sr.val = gs->getPlayer(player)->resources[id1] - val;
|
||||
sr.val = r1 - b1 * units;
|
||||
sendAndApply(&sr);
|
||||
|
||||
sr.resid = id2;
|
||||
sr.val = gs->getPlayer(player)->resources[id2] + (int)yield;
|
||||
sr.val = r2 + b2 * units;
|
||||
sendAndApply(&sr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CGameHandler::sendResources(ui32 val, ui8 player, ui32 r1, ui32 r2)
|
||||
{
|
||||
const PlayerState *p2 = gs->getPlayer(r2, false);
|
||||
|
@ -36,6 +36,8 @@ struct SetResource;
|
||||
struct SetResources;
|
||||
struct NewStructures;
|
||||
class CGHeroInstance;
|
||||
class IMarket;
|
||||
|
||||
extern std::map<ui32, CFunctionList<void(ui32)> > callbacks; //question id => callback functions - for selection dialogs
|
||||
extern boost::mutex gsm;
|
||||
|
||||
@ -163,7 +165,7 @@ public:
|
||||
bool hireHero( ui32 tid, ui8 hid );
|
||||
bool buildBoat( ui32 objid );
|
||||
bool setFormation( si32 hid, ui8 formation );
|
||||
bool tradeResources( ui32 val, ui8 player, ui32 id1, ui32 id2 );
|
||||
bool tradeResources(const IMarket *market, ui32 val, ui8 player, ui32 id1, ui32 id2);
|
||||
bool sendResources(ui32 val, ui8 player, ui32 r1, ui32 r2);
|
||||
bool assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assemble, ui32 assembleTo);
|
||||
bool buyArtifact( ui32 hid, si32 aid );
|
||||
|
@ -1,5 +1,8 @@
|
||||
#include "../lib/NetPacks.h"
|
||||
#include "CGameHandler.h"
|
||||
#include "../hch/CObjectHandler.h"
|
||||
#include "../lib/IGameCallback.h"
|
||||
#include "../lib/map.h"
|
||||
|
||||
|
||||
#define PLAYER_OWNS(id) (gh->getPlayerAt(c)==gh->getOwner(id))
|
||||
@ -7,6 +10,7 @@
|
||||
tlog1<<"Player is not allowed to perform this action!\n"; \
|
||||
return false;}
|
||||
#define ERROR_IF_NOT_OWNS(id) if(!PLAYER_OWNS(id)) ERROR_AND_RETURN
|
||||
#define COMPLAIN_AND_RETURN(txt) { gh->complain(txt); ERROR_AND_RETURN }
|
||||
|
||||
/*
|
||||
* NetPacksServer.cpp, part of VCMI engine
|
||||
@ -111,11 +115,30 @@ bool BuyArtifact::applyGh( CGameHandler *gh )
|
||||
|
||||
bool TradeOnMarketplace::applyGh( CGameHandler *gh )
|
||||
{
|
||||
if(gh->getPlayerAt(c) != player) ERROR_AND_RETURN;
|
||||
//market must be owned or visited
|
||||
const IMarket *m = IMarket::castFrom(market);
|
||||
|
||||
if(!m)
|
||||
COMPLAIN_AND_RETURN("market is not-a-market! :/");
|
||||
|
||||
ui8 player = market->tempOwner;
|
||||
|
||||
if(player >= PLAYER_LIMIT)
|
||||
player = gh->getTile(market->visitablePos())->visitableObjects.back()->tempOwner;
|
||||
|
||||
if(player >= PLAYER_LIMIT)
|
||||
COMPLAIN_AND_RETURN("No player can use this market!");
|
||||
|
||||
if(hero && (player != hero->tempOwner || hero->visitablePos() != market->visitablePos()))
|
||||
COMPLAIN_AND_RETURN("This hero can't use this marketplace!");
|
||||
|
||||
if(gh->getPlayerAt(c) != player)
|
||||
ERROR_AND_RETURN;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case RESOURCE_RESOURCE:
|
||||
return gh->tradeResources(val,player,r1,r2);
|
||||
return gh->tradeResources(m, val, player, r1, r2);
|
||||
case RESOURCE_PLAYER:
|
||||
return gh->sendResources(val, player, r1, r2);
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user