mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
* Freelancer's Guild support (both town structure and adventure map object)
* fixed crashes on r-click on hero in tavern and adv map * fixed descync issue * allow free movement FROM guarded tile
This commit is contained in:
parent
6541e89f90
commit
8bda10b695
@ -38,12 +38,14 @@ TOWNS:
|
||||
* Support for new town structures:
|
||||
- Lighthouse
|
||||
- Colossus
|
||||
- Freelancer's Guild
|
||||
- Guardian Spirit
|
||||
- Necromancy Amplifier
|
||||
- Soul Prison
|
||||
|
||||
OBJECTS:
|
||||
New object supported:
|
||||
- Freelancer's Guild
|
||||
- Trading Post
|
||||
- War Machine Factory
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <boost/format.hpp>
|
||||
using namespace boost::assign;
|
||||
using namespace CSDL_Ext;
|
||||
|
||||
@ -557,6 +558,8 @@ void CCastleInterface::buildingClicked(int building)
|
||||
building = town->town->hordeLvl[1] + 30;
|
||||
}
|
||||
|
||||
const CBuilding *b = CGI->buildh->buildings[town->subID][building];
|
||||
|
||||
if(building >= 30)
|
||||
{
|
||||
showRecruitmentWindow(building);
|
||||
@ -635,7 +638,7 @@ void CCastleInterface::buildingClicked(int building)
|
||||
break;
|
||||
case 14: //marketplace
|
||||
{
|
||||
CMarketplaceWindow *cmw = new CMarketplaceWindow(town);
|
||||
CMarketplaceWindow *cmw = new CMarketplaceWindow(town, town->visitingHero);
|
||||
GH.pushInt(cmw);
|
||||
break;
|
||||
}
|
||||
@ -648,13 +651,13 @@ void CCastleInterface::buildingClicked(int building)
|
||||
{
|
||||
switch(town->subID)
|
||||
{
|
||||
/*Rampart*/ case 1://Mystic Pond
|
||||
/*Rampart*/ case 1://Mystic Pond
|
||||
enterFountain(building);
|
||||
break;
|
||||
/*Tower*/ case 2://Artifact Merchant
|
||||
/*Dungeon*/ case 5://Artifact Merchant
|
||||
/*Conflux*/ case 8://Artifact Merchant
|
||||
tlog4<<"Artifact Merchant not handled\n";
|
||||
/*Tower*/ case 2://Artifact Merchant
|
||||
/*Dungeon*/ case 5://Artifact Merchant
|
||||
/*Conflux*/ case 8://Artifact Merchant
|
||||
GH.pushInt(new CMarketplaceWindow(town, town->visitingHero, RESOURCE_ARTIFACT));
|
||||
break;
|
||||
default:
|
||||
defaultBuildingClicked(building);
|
||||
@ -671,13 +674,16 @@ void CCastleInterface::buildingClicked(int building)
|
||||
{
|
||||
switch(town->subID)
|
||||
{
|
||||
/*Rampart*/ case 1: //Fountain of Fortune
|
||||
/*Rampart*/ case 1: //Fountain of Fortune
|
||||
enterFountain(building);
|
||||
break;
|
||||
/*Stronghold*/ case 6: //Freelancer's Guild
|
||||
tlog4<<"Freelancer's Guild not handled\n";
|
||||
/*Stronghold*/case 6: //Freelancer's Guild
|
||||
if(town->visitingHero)
|
||||
GH.pushInt(new CMarketplaceWindow(town, town->visitingHero, CREATURE_RESOURCE));
|
||||
else
|
||||
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->Name())); //Only visiting heroes may use the %s.
|
||||
break;
|
||||
/*Conflux*/ case 8: //Magic University
|
||||
/*Conflux*/ case 8: //Magic University
|
||||
tlog4<<"Magic University not handled\n";
|
||||
break;
|
||||
default:
|
||||
|
@ -478,11 +478,15 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
|
||||
wwg->garr->recreateSlots();
|
||||
wasGarrison = true;
|
||||
}
|
||||
else
|
||||
else if(CKingdomInterface *cki = dynamic_cast<CKingdomInterface*>(*i))
|
||||
{//a cheat for Kingdom Overview window (it has CWindowWithGarrison-childrens which are not present in ListInt)
|
||||
CKingdomInterface *cki = dynamic_cast<CKingdomInterface*>(*i);//need to create "Garrison Holder" class thingy
|
||||
if (cki)
|
||||
cki->updateAllGarrisons();
|
||||
//need to create "Garrison Holder" class thingy
|
||||
cki->updateAllGarrisons();
|
||||
}
|
||||
else if(CMarketplaceWindow *cmw = dynamic_cast<CMarketplaceWindow*>(*i))
|
||||
{
|
||||
if(obj == cmw->hero)
|
||||
cmw->garrisonChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1977,6 +1981,6 @@ void CPlayerInterface::stopMovement()
|
||||
|
||||
void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor)
|
||||
{
|
||||
CMarketplaceWindow *cmw = new CMarketplaceWindow(market, market->availableModes().front());
|
||||
CMarketplaceWindow *cmw = new CMarketplaceWindow(market, visitor, market->availableModes().front());
|
||||
GH.pushInt(cmw);
|
||||
}
|
@ -2581,8 +2581,9 @@ CCustomImgComponent::~CCustomImgComponent()
|
||||
SDL_FreeSurface(bmp);
|
||||
}
|
||||
|
||||
CMarketplaceWindow::CTradeableItem::CTradeableItem( int Type, int ID, bool Left)
|
||||
CMarketplaceWindow::CTradeableItem::CTradeableItem( EType Type, int ID, bool Left, int Serial)
|
||||
{
|
||||
serial = Serial;
|
||||
left = Left;
|
||||
type = Type;
|
||||
id = ID;
|
||||
@ -2639,24 +2640,29 @@ SDL_Surface * CMarketplaceWindow::CTradeableItem::getSurface()
|
||||
return graphics->flags->ourImages[id].bitmap;
|
||||
case ARTIFACT:
|
||||
return graphics->artDefs->ourImages[id].bitmap;
|
||||
case CREATURE:
|
||||
return graphics->bigImgs[id];
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
static void initItems( std::vector<CMarketplaceWindow::CTradeableItem*> &i, std::vector<Rect> &p, int type, int amount, bool left, std::vector<int> *ids/*=NULL*/ )
|
||||
static void initItems( std::vector<CMarketplaceWindow::CTradeableItem*> &i, std::vector<Rect> &p, CMarketplaceWindow::EType type, int amount, bool left, std::vector<int> *ids/*=NULL*/ )
|
||||
{
|
||||
if(ids)
|
||||
amin(amount, ids->size());
|
||||
|
||||
i.resize(amount);
|
||||
for(int j=0;j<amount;j++)
|
||||
{
|
||||
i[j] = new CMarketplaceWindow::CTradeableItem(type,(ids && ids->size()>j) ? (*ids)[j] : j, left);
|
||||
i[j]->pos = p[j] + i[j]->pos;
|
||||
int id = (ids && ids->size()>j) ? (*ids)[j] : j;
|
||||
if(id < 0)
|
||||
continue;
|
||||
|
||||
i.push_back(new CMarketplaceWindow::CTradeableItem(type, id, left, j));
|
||||
i.back()->pos = p[j] + i.back()->pos;
|
||||
}
|
||||
}
|
||||
CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, EMarketMode Mode)
|
||||
:market(Market)
|
||||
CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstance *Hero, EMarketMode Mode)
|
||||
:market(Market), hero(Hero), hLeft(NULL), hRight(NULL), readyToTrade(false)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
type = BLOCK_ADV_HOTKEYS;
|
||||
@ -2675,6 +2681,7 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, EMarketMode Mode)
|
||||
ltype = RESOURCE;
|
||||
rtype = RESOURCE;
|
||||
break;
|
||||
|
||||
case RESOURCE_PLAYER:
|
||||
bgName = "TPMRKPTS.bmp";
|
||||
ltype = RESOURCE;
|
||||
@ -2685,13 +2692,40 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, EMarketMode Mode)
|
||||
if(i != LOCPLINT->playerID && LOCPLINT->cb->getPlayerStatus(i) == PlayerState::INGAME)
|
||||
rIds->push_back(i);
|
||||
break;
|
||||
|
||||
case CREATURE_RESOURCE:
|
||||
bgName = "TPMRKCRS.bmp";
|
||||
ltype = CREATURE;
|
||||
rtype = RESOURCE;
|
||||
lIds = new std::vector<int>;
|
||||
for(int i = 0; i < 7; i++)
|
||||
{
|
||||
if(const CCreature *c = hero->getCreature(i))
|
||||
lIds->push_back(c->idNumber);
|
||||
else
|
||||
lIds->push_back(-1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
bg = new CPicture(bgName);
|
||||
bg->colorizeAndConvert(LOCPLINT->playerID);
|
||||
|
||||
printAtMiddle(CGI->generaltexth->allTexts[158],300,27,FONT_BIG,tytulowy,*bg); //title
|
||||
printAtMiddle(CGI->generaltexth->allTexts[270],154,148,FONT_SMALL,zwykly,*bg); //kingdom res.
|
||||
if(market->o->ID == 99 || market->o->ID == 221)
|
||||
{
|
||||
printAtMiddle(CGI->generaltexth->allTexts[159],300,27,FONT_BIG,tytulowy,*bg); //title
|
||||
}
|
||||
else if(mode == CREATURE_RESOURCE)
|
||||
{
|
||||
if(market->o->ID == TOWNI_TYPE)
|
||||
printAtMiddle(CGI->buildh->buildings[6][21]->Name(), 300, 27, FONT_BIG, tytulowy, *bg); //title
|
||||
else
|
||||
printAtMiddle(market->o->getHoverText(), 300, 27, FONT_BIG, tytulowy, *bg); //title
|
||||
}
|
||||
else
|
||||
{
|
||||
printAtMiddle(CGI->generaltexth->allTexts[158],300,27,FONT_BIG,tytulowy,*bg); //trading post
|
||||
}
|
||||
|
||||
std::vector<Rect> lpos, rpos;
|
||||
getPositionsFor(lpos, false, ltype);
|
||||
@ -2705,28 +2739,44 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, EMarketMode Mode)
|
||||
//slider and buttons must be created after bg
|
||||
slider = new CSlider(231,490,137,boost::bind(&CMarketplaceWindow::sliderMoved,this,_1),0,0);
|
||||
|
||||
hLeft = hRight = NULL;
|
||||
|
||||
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");
|
||||
|
||||
//left side
|
||||
switch(Mode)
|
||||
{
|
||||
case RESOURCE_RESOURCE:
|
||||
{
|
||||
new AdventureMapButton("","",boost::bind(&CMarketplaceWindow::setMode,this, RESOURCE_PLAYER), 18, 520,"TPMRKBU1.DEF");
|
||||
printAtMiddle(CGI->generaltexth->allTexts[168],445,147,FONT_SMALL,zwykly,*bg); //available for trade
|
||||
}
|
||||
break;
|
||||
case RESOURCE_PLAYER:
|
||||
{
|
||||
new AdventureMapButton("","",boost::bind(&CMarketplaceWindow::setMode,this, RESOURCE_RESOURCE), 516, 450,"TPMRKBU5.DEF");
|
||||
printAtMiddle(CGI->generaltexth->allTexts[169],445,55,FONT_SMALL,zwykly,*bg); //players
|
||||
}
|
||||
printAtMiddle(CGI->generaltexth->allTexts[270],154,148,FONT_SMALL,zwykly,*bg); //kingdom res.
|
||||
break;
|
||||
case CREATURE_RESOURCE:
|
||||
printAtMiddle(boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->name), 152, 102, FONT_SMALL, zwykly, *bg); //%s's Creatures
|
||||
break;
|
||||
}
|
||||
|
||||
//right side
|
||||
switch(Mode)
|
||||
{
|
||||
case RESOURCE_RESOURCE:
|
||||
case CREATURE_RESOURCE:
|
||||
printAtMiddle(CGI->generaltexth->allTexts[168],445,148,FONT_SMALL,zwykly,*bg); //available for trade
|
||||
break;
|
||||
case RESOURCE_PLAYER:
|
||||
printAtMiddle(CGI->generaltexth->allTexts[169],445,55,FONT_SMALL,zwykly,*bg); //players
|
||||
break;
|
||||
}
|
||||
|
||||
if(printButtonFor(RESOURCE_PLAYER))
|
||||
new AdventureMapButton("","",boost::bind(&CMarketplaceWindow::setMode,this, RESOURCE_PLAYER), 18, 520,"TPMRKBU1.DEF");
|
||||
if(printButtonFor(RESOURCE_RESOURCE))
|
||||
new AdventureMapButton("","",boost::bind(&CMarketplaceWindow::setMode,this, RESOURCE_RESOURCE), 516, 450,"TPMRKBU5.DEF");
|
||||
if(printButtonFor(CREATURE_RESOURCE))
|
||||
new AdventureMapButton("","",boost::bind(&CMarketplaceWindow::setMode,this, CREATURE_RESOURCE), 516, 450,"TPMRKBU4.DEF");
|
||||
|
||||
|
||||
max->block(true);
|
||||
deal->block(true);
|
||||
}
|
||||
@ -2745,9 +2795,9 @@ CMarketplaceWindow::~CMarketplaceWindow()
|
||||
bg = NULL;
|
||||
}
|
||||
|
||||
void CMarketplaceWindow::show(SDL_Surface * to)
|
||||
void CMarketplaceWindow::showAll(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::show(to);
|
||||
CIntObject::showAll(to);
|
||||
|
||||
|
||||
if(hRight)
|
||||
@ -2756,49 +2806,62 @@ void CMarketplaceWindow::show(SDL_Surface * to)
|
||||
CSDL_Ext::drawBorder(to,hLeft->pos.x-1,hLeft->pos.y-1,hLeft->pos.w+2,hLeft->pos.h+2,int3(255,231,148));
|
||||
|
||||
//left side
|
||||
if(mode == RESOURCE_RESOURCE || mode == RESOURCE_PLAYER)
|
||||
switch(ltype)
|
||||
{
|
||||
case RESOURCE:
|
||||
for(int i=0;i<left.size();i++)
|
||||
printAtMiddle(boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(i)),
|
||||
left[i]->pos.x+36,left[i]->pos.y+57,FONT_SMALL,zwykly,to);
|
||||
printAtMiddle(boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(i)), left[i]->pos.x+36,left[i]->pos.y+57,FONT_SMALL,zwykly,to);
|
||||
|
||||
|
||||
if(hLeft && hRight && (hLeft->id != hRight->id || mode != RESOURCE_RESOURCE))
|
||||
if(readyToTrade)
|
||||
{
|
||||
blitAt(hLeft->getSurface(),pos.x+141,pos.y+457,to);
|
||||
printAtMiddle(boost::lexical_cast<std::string>( slider->value * r1 ),pos.x+156,pos.y+505,FONT_SMALL,zwykly,to);
|
||||
}
|
||||
break;
|
||||
|
||||
case CREATURE:
|
||||
BOOST_FOREACH(CTradeableItem *t, left)
|
||||
printAtMiddle(boost::lexical_cast<std::string>(hero->getAmount(t->serial)), t->pos.x+29, t->pos.y+76, FONT_SMALL, zwykly, to);
|
||||
|
||||
if(readyToTrade)
|
||||
{
|
||||
blitAt(hLeft->getSurface(),pos.x+128,pos.y+450,to);
|
||||
printAtMiddle(boost::lexical_cast<std::string>( slider->value * r1 ),pos.x+160,pos.y+527,FONT_SMALL,zwykly,to);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(mode == RESOURCE_RESOURCE)
|
||||
//right side
|
||||
switch(rtype)
|
||||
{
|
||||
case RESOURCE:
|
||||
if(hLeft) //print prices
|
||||
{
|
||||
for(int i=0; i<right.size();i++)
|
||||
{
|
||||
if(right[i]->id != hLeft->id)
|
||||
if(right[i]->id != hLeft->id || mode != RESOURCE_RESOURCE)
|
||||
printAtMiddle(rSubs[i],right[i]->pos.x+36,right[i]->pos.y+57,FONT_SMALL,zwykly,to);
|
||||
else
|
||||
printAtMiddle(CGI->generaltexth->allTexts[164],right[i]->pos.x+36,right[i]->pos.y+57,FONT_SMALL,zwykly,to);
|
||||
}
|
||||
}
|
||||
if(hLeft && hRight && (hLeft->id != hRight->id))
|
||||
if(readyToTrade)
|
||||
{
|
||||
blitAt(hRight->getSurface(),pos.x+429,pos.y+457,to);
|
||||
printAtMiddle(boost::lexical_cast<std::string>( slider->value * r2 ),pos.x+443,pos.y+505,FONT_SMALL,zwykly,to);
|
||||
}
|
||||
}
|
||||
else if(mode == RESOURCE_PLAYER)
|
||||
{
|
||||
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(hLeft && hRight)
|
||||
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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2809,30 +2872,44 @@ void CMarketplaceWindow::setMax()
|
||||
|
||||
void CMarketplaceWindow::makeDeal()
|
||||
{
|
||||
LOCPLINT->cb->trade(market->o, mode, hLeft->id, hRight->id, slider->value*r1);
|
||||
if(!slider->value)
|
||||
return;
|
||||
|
||||
int leftIdToSend = -1;
|
||||
if(mode == CREATURE_RESOURCE)
|
||||
leftIdToSend = hLeft->serial;
|
||||
else
|
||||
leftIdToSend = hLeft->id;
|
||||
|
||||
LOCPLINT->cb->trade(market->o, mode, leftIdToSend, hRight->id, slider->value*r1, hero);
|
||||
slider->moveTo(0);
|
||||
hLeft = NULL;
|
||||
hRight = NULL;
|
||||
selectionChanged(true);
|
||||
}
|
||||
|
||||
void CMarketplaceWindow::sliderMoved( int to )
|
||||
{
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CMarketplaceWindow::selectionChanged(bool side)
|
||||
{
|
||||
if(hLeft && hRight && (hLeft->id!= hRight->id || mode != RESOURCE_RESOURCE))
|
||||
readyToTrade = (hLeft && hRight && (hLeft->id!= hRight->id || mode != RESOURCE_RESOURCE));
|
||||
|
||||
if(readyToTrade)
|
||||
{
|
||||
if(mode == RESOURCE_RESOURCE)
|
||||
{
|
||||
market->getOffer(hLeft->id, hRight->id, r1, r2, mode);
|
||||
slider->setAmount(LOCPLINT->cb->getResourceAmount(hLeft->id) / r1);
|
||||
}
|
||||
else if(mode == RESOURCE_PLAYER)
|
||||
{
|
||||
r1 = 1;
|
||||
slider->setAmount(LOCPLINT->cb->getResourceAmount(hLeft->id));
|
||||
}
|
||||
int newAmount = -1;
|
||||
market->getOffer(hLeft->id, hRight->id, r1, r2, mode);
|
||||
|
||||
if(ltype == RESOURCE)
|
||||
newAmount = LOCPLINT->cb->getResourceAmount(hLeft->id);
|
||||
else if(ltype == CREATURE)
|
||||
newAmount = hero->getAmount(hLeft->serial) - (hero->Slots().size() == 1 && hero->needsLastStack());
|
||||
else
|
||||
assert(0);
|
||||
|
||||
slider->setAmount(newAmount / r1);
|
||||
slider->moveTo(0);
|
||||
max->block(false);
|
||||
deal->block(false);
|
||||
@ -2851,7 +2928,7 @@ 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);
|
||||
market->getOffer(hLeft->id, i, h1, h2, mode);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << h2;
|
||||
@ -2860,35 +2937,84 @@ void CMarketplaceWindow::selectionChanged(bool side)
|
||||
rSubs[i] = oss.str();
|
||||
}
|
||||
}
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CMarketplaceWindow::getPositionsFor(std::vector<Rect> &poss, bool Right, EType type) const
|
||||
{
|
||||
if(type == RESOURCE)
|
||||
{
|
||||
poss += genRect(66,74,39 ,180), genRect(66,74,122,180), genRect(66,74,204,180),
|
||||
genRect(66,74,39,259), genRect(66,74,122,259), genRect(66,74,204,259),
|
||||
genRect(66,74,122,338);
|
||||
if(Right)
|
||||
BOOST_FOREACH(Rect &r, poss)
|
||||
r.x += 288;
|
||||
}
|
||||
else if(type == PLAYER)
|
||||
int h, w, x, y, dx, dy;
|
||||
int leftToRightOffset = 288;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case RESOURCE:
|
||||
dx = 82;
|
||||
dy = 79;
|
||||
x = 39;
|
||||
y = 180;
|
||||
h = 66;
|
||||
w = 74;
|
||||
break;
|
||||
case PLAYER:
|
||||
dx = 83;
|
||||
dy = 118;
|
||||
h = 64;
|
||||
w = 58;
|
||||
x = 44;
|
||||
y = 83;
|
||||
assert(Right);
|
||||
poss += genRect(64, 58, 333, 84), genRect(64, 58, 333 + 83, 84), genRect(64, 58, 333 + 2 * 83, 84),
|
||||
genRect(64, 58, 333, 84 + 118), genRect(64, 58, 333 + 83, 84 + 118), genRect(64, 58, 333 + 2 * 83, 84 + 118),
|
||||
genRect(64, 58, 333 + 83, 84 + 2*118);
|
||||
break;
|
||||
case CREATURE://45,123
|
||||
x = 45;
|
||||
y = 123;
|
||||
w = 58;
|
||||
h = 64;
|
||||
dx = 83;
|
||||
dy = 98;
|
||||
assert(!Right);
|
||||
}
|
||||
|
||||
|
||||
poss += genRect(h, w, x, y), genRect(h, w, x + dx, y), genRect(h, w, x + 2*dx, y),
|
||||
genRect(h, w, x, y + dy), genRect(h, w, x + dx, y + dy), genRect(h, w, x + 2*dx, y + dy),
|
||||
genRect(h, w, x + dx, y + 2*dy);
|
||||
|
||||
if(Right)
|
||||
BOOST_FOREACH(Rect &r, poss)
|
||||
r.x += leftToRightOffset;
|
||||
}
|
||||
|
||||
void CMarketplaceWindow::setMode(EMarketMode Mode)
|
||||
{
|
||||
CMarketplaceWindow *nwindow = new CMarketplaceWindow(market, Mode);
|
||||
CMarketplaceWindow *nwindow = new CMarketplaceWindow(market, hero, Mode);
|
||||
GH.popIntTotally(this);
|
||||
GH.pushInt(nwindow);
|
||||
}
|
||||
|
||||
bool CMarketplaceWindow::printButtonFor(EMarketMode M) const
|
||||
{
|
||||
return market->allowsTrade(M) && M != mode && (hero || mode != CREATURE_RESOURCE);
|
||||
}
|
||||
|
||||
void CMarketplaceWindow::garrisonChanged()
|
||||
{
|
||||
if(mode != CREATURE_RESOURCE)
|
||||
return;
|
||||
|
||||
std::set<CTradeableItem *> toRemove;
|
||||
BOOST_FOREACH(CTradeableItem *t, left)
|
||||
if(!hero->getAmount(t->serial))
|
||||
toRemove.insert(t);
|
||||
|
||||
BOOST_FOREACH(CTradeableItem *t, toRemove)
|
||||
{
|
||||
if(active)
|
||||
t->deactivate();
|
||||
left -= t;
|
||||
delChild(t);
|
||||
}
|
||||
}
|
||||
|
||||
CSystemOptionsWindow::CSystemOptionsWindow(const SDL_Rect &pos, CPlayerInterface * owner)
|
||||
{
|
||||
this->pos = pos;
|
||||
|
@ -518,26 +518,29 @@ public:
|
||||
|
||||
class CMarketplaceWindow : public CIntObject
|
||||
{
|
||||
bool printButtonFor(EMarketMode M) const;
|
||||
public:
|
||||
enum EType
|
||||
{
|
||||
RESOURCE, PLAYER, ARTIFACT
|
||||
RESOURCE, PLAYER, ARTIFACT, CREATURE
|
||||
};
|
||||
class CTradeableItem : public CIntObject
|
||||
{
|
||||
public:
|
||||
int type; //0 - res, 1 - artif big, 2 - artif small, 3 - player flag
|
||||
int id;
|
||||
EType type;
|
||||
int id;
|
||||
int serial;
|
||||
bool left;
|
||||
CFunctionList<void()> callback;
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
SDL_Surface *getSurface();
|
||||
CTradeableItem(int Type, int ID, bool Left);
|
||||
CTradeableItem(EType Type, int ID, bool Left, int Serial);
|
||||
};
|
||||
|
||||
const IMarket *market;
|
||||
const CGHeroInstance *hero;
|
||||
CPicture *bg; //background
|
||||
std::vector<CTradeableItem*> left, right;
|
||||
std::vector<std::string> rSubs; //offer caption
|
||||
@ -548,17 +551,20 @@ public:
|
||||
int r1, r2; //suggested amounts of traded resources
|
||||
AdventureMapButton *ok, *max, *deal;
|
||||
CSlider *slider; //for choosing amount to be exchanged
|
||||
bool readyToTrade;
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void setMax();
|
||||
void sliderMoved(int to);
|
||||
void makeDeal();
|
||||
void selectionChanged(bool side); //true == left
|
||||
CMarketplaceWindow(const IMarket *Market, EMarketMode Mode = RESOURCE_RESOURCE); //c-tor
|
||||
CMarketplaceWindow(const IMarket *Market, const CGHeroInstance *Hero = NULL, EMarketMode Mode = RESOURCE_RESOURCE); //c-tor
|
||||
~CMarketplaceWindow(); //d-tor
|
||||
void setMode(EMarketMode Mode); //mode setter
|
||||
|
||||
void getPositionsFor(std::vector<Rect> &poss, bool Right, EType type) const;
|
||||
|
||||
void garrisonChanged(); //removes creatures with count 0 from the list (apparently whole stack has been sold)
|
||||
};
|
||||
|
||||
class CSystemOptionsWindow : public CIntObject
|
||||
|
@ -61,7 +61,7 @@ SDL_Surface * Graphics::drawHeroInfoWin(const InfoAboutHero &curh)
|
||||
}
|
||||
else
|
||||
{
|
||||
printAtMiddle(VLC->generaltexth->arraytxt[174 + 3*i->second.count],slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
|
||||
printAtMiddle(VLC->generaltexth->arraytxt[174 + 3*(i->second.count-1)],slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ void IObjectInterface::preInit()
|
||||
void CPlayersVisited::setPropertyDer( ui8 what, ui32 val )
|
||||
{
|
||||
if(what == 10)
|
||||
players.insert(val);
|
||||
players.insert((ui8)val);
|
||||
}
|
||||
|
||||
bool CPlayersVisited::hasVisited( ui8 player ) const
|
||||
@ -1162,6 +1162,7 @@ void CGHeroInstance::pushPrimSkill(int which, int val)
|
||||
|
||||
void CGHeroInstance::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
|
||||
{
|
||||
#define FOREACH_OWNER_TOWN(town) if(const PlayerState *p = cb->getPlayerState(tempOwner)) BOOST_FOREACH(const CGTownInstance *town, p->towns)
|
||||
CArmedInstance::getBonuses(out, selector, root);
|
||||
|
||||
//TODO eliminate by moving secondary skills effects to bonus system
|
||||
@ -1172,7 +1173,7 @@ void CGHeroInstance::getBonuses(BonusList &out, const CSelector &selector, const
|
||||
out.push_back(Bonus(Bonus::PERMANENT, Bonus::LUCK, Bonus::SECONDARY_SKILL, luckSkill, 9, VLC->generaltexth->arraytxt[73+luckSkill]));
|
||||
|
||||
//guardian spirit
|
||||
BOOST_FOREACH(const CGTownInstance *t, cb->getPlayerState(tempOwner)->towns)
|
||||
FOREACH_OWNER_TOWN(t)
|
||||
if(t->subID ==1 && vstd::contains(t->builtBuildings,26)) //rampart with grail
|
||||
out.push_back(Bonus(Bonus::PERMANENT, Bonus::LUCK, Bonus::TOWN_STRUCTURE, +2, 26, VLC->generaltexth->buildings[1][26].first + " +2"));
|
||||
}
|
||||
@ -1180,7 +1181,7 @@ void CGHeroInstance::getBonuses(BonusList &out, const CSelector &selector, const
|
||||
if(Selector::matchesType(selector, Bonus::SEA_MOVEMENT))
|
||||
{
|
||||
//lighthouses
|
||||
BOOST_FOREACH(const CGTownInstance *t, cb->getPlayerState(tempOwner)->towns)
|
||||
FOREACH_OWNER_TOWN(t)
|
||||
if(t->subID == 0 && vstd::contains(t->builtBuildings,17)) //castle
|
||||
out.push_back(Bonus(Bonus::PERMANENT, Bonus::SEA_MOVEMENT, Bonus::TOWN_STRUCTURE, +500, 17, VLC->generaltexth->buildings[0][17].first + " +500"));
|
||||
}
|
||||
@ -1192,14 +1193,14 @@ void CGHeroInstance::getBonuses(BonusList &out, const CSelector &selector, const
|
||||
out.push_back(Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::SECONDARY_SKILL, moraleSkill, 6, VLC->generaltexth->arraytxt[104+moraleSkill]));
|
||||
|
||||
//colossus
|
||||
BOOST_FOREACH(const CGTownInstance *t, cb->getPlayerState(tempOwner)->towns)
|
||||
FOREACH_OWNER_TOWN(t)
|
||||
if(t->subID == 0 && vstd::contains(t->builtBuildings,26)) //castle
|
||||
out.push_back(Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::TOWN_STRUCTURE, +2, 26, VLC->generaltexth->buildings[0][26].first + " +2"));
|
||||
}
|
||||
|
||||
if(Selector::matchesTypeSubtype(selector, Bonus::SECONDARY_SKILL_PREMY, 12)) //necromancy
|
||||
{
|
||||
BOOST_FOREACH(const CGTownInstance *t, cb->getPlayerState(tempOwner)->towns)
|
||||
FOREACH_OWNER_TOWN(t)
|
||||
{
|
||||
if(t->subID == 4) //necropolis
|
||||
{
|
||||
@ -5932,7 +5933,30 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode)
|
||||
val2 = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CREATURE_RESOURCE:
|
||||
{
|
||||
const float effectivenessArray[] = {0, 0.3, 0.45, 0.50, 0.65, 0.7, 0.85, 0.9, 1};
|
||||
float effectiveness = effectivenessArray[std::min(getMarketEfficiency(), 8)];
|
||||
|
||||
float r = VLC->creh->creatures[id1]->cost[6], //value of given creature in gold
|
||||
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;
|
||||
case RESOURCE_PLAYER:
|
||||
val1 = 1;
|
||||
val2 = 1;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@ -5949,19 +5973,29 @@ bool IMarket::allowsTrade(EMarketMode mode) const
|
||||
|
||||
int IMarket::availableUnits(EMarketMode mode, int marketItemSerial) const
|
||||
{
|
||||
if(mode == RESOURCE_RESOURCE || ARTIFACT_RESOURCE || CREATURE_RESOURCE)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
switch(mode)
|
||||
{
|
||||
case RESOURCE_RESOURCE:
|
||||
case ARTIFACT_RESOURCE:
|
||||
case CREATURE_RESOURCE:
|
||||
return -1;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> IMarket::availableItemsIds(EMarketMode mode) const
|
||||
{
|
||||
std::vector<int> ret;
|
||||
if(mode == RESOURCE_RESOURCE || ARTIFACT_RESOURCE || CREATURE_RESOURCE)
|
||||
switch(mode)
|
||||
{
|
||||
case RESOURCE_RESOURCE:
|
||||
case ARTIFACT_RESOURCE:
|
||||
case CREATURE_RESOURCE:
|
||||
for (int i = 0; i < 7; i++)
|
||||
ret.push_back(i);
|
||||
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -5971,8 +6005,10 @@ const IMarket * IMarket::castFrom(const CGObjectInstance *obj)
|
||||
{
|
||||
case TOWNI_TYPE:
|
||||
return static_cast<const CGTownInstance*>(obj);
|
||||
case 7: //Black Market
|
||||
case 99: //Trading Post
|
||||
case 221: //Trading Post (snow)
|
||||
case 213: //Freelancer's Guild
|
||||
return static_cast<const CGMarket*>(obj);
|
||||
default:
|
||||
tlog1 << "Cannot cast to IMarket object with ID " << obj->ID << std::endl;
|
||||
@ -6034,7 +6070,10 @@ bool CGMarket::allowsTrade(EMarketMode mode) const
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case CREATURE_RESOURCE:
|
||||
return ID == 213; //Freelancer's Guild
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int CGMarket::availableUnits(EMarketMode mode, int marketItemSerial) const
|
||||
|
@ -192,6 +192,7 @@ void CCreatureSet::setFormation(bool tight)
|
||||
void CCreatureSet::setStackCount(TSlot slot, TQuantity count)
|
||||
{
|
||||
assert(vstd::contains(slots, slot));
|
||||
assert(count > 0);
|
||||
slots[slot].count = count;
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ public:
|
||||
virtual bool needsLastStack() const; //true if last stack cannot be taken
|
||||
int getArmyStrength() const; //sum of AI values of creatures
|
||||
ui64 getPower (TSlot slot) const; //value of specific stack
|
||||
std::string getRoughAmount (TSlot slot) const; //rought size of specific stack
|
||||
std::string getRoughAmount (TSlot slot) const; //rough size of specific stack
|
||||
|
||||
bool contains(const CStackInstance *stack) const;
|
||||
|
||||
|
@ -1752,7 +1752,7 @@ void CGameState::getNeighbours( const TerrainTile &srct, int3 tile, std::vector<
|
||||
const TerrainTile &hlpt = map->getTile(hlp);
|
||||
|
||||
//we cannot visit things from blocked tiles
|
||||
if(srct.blocked && hlpt.visitable)
|
||||
if(srct.blocked && hlpt.visitable && srct.blockingObjects.front()->ID != HEROI_TYPE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -2216,6 +2216,8 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int
|
||||
CGPathNode *cp = mq.front();
|
||||
mq.pop();
|
||||
|
||||
const int3 guardPosition = guardingCreaturePosition(cp->coord);
|
||||
const bool guardedPosition = (guardPosition != int3(-1, -1, -1) && cp->coord != src);
|
||||
const TerrainTile &ct = map->getTile(cp->coord);
|
||||
int movement = cp->moveRemains, turn = cp->turns;
|
||||
if(!movement)
|
||||
@ -2252,7 +2254,6 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int
|
||||
remains = moveAtNextTile - cost;
|
||||
}
|
||||
|
||||
const bool guardedPosition = guardingCreaturePosition(cp->coord) != int3(-1, -1, -1);
|
||||
const bool neighborIsGuard = guardingCreaturePosition(cp->coord) == dp.coord;
|
||||
|
||||
if((dp.turns==0xff //we haven't been here before
|
||||
@ -2267,10 +2268,10 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int
|
||||
dp.theNodeBefore = cp;
|
||||
|
||||
const bool guardedNeighbor = guardingCreaturePosition(dp.coord) != int3(-1, -1, -1);
|
||||
const bool positionIsGuard = guardingCreaturePosition(cp->coord) == cp->coord;
|
||||
//const bool positionIsGuard = guardingCreaturePosition(cp->coord) == cp->coord; //can this be true? hero never passes from monster tile...
|
||||
|
||||
if (dp.accessible == CGPathNode::ACCESSIBLE || dp.accessible == CGPathNode::FLYABLE
|
||||
|| (guardedNeighbor && !positionIsGuard)) // Can step into a hostile tile once.
|
||||
|| (guardedNeighbor && !guardedPosition)) // Can step into a hostile tile once.
|
||||
{
|
||||
mq.push(&dp);
|
||||
}
|
||||
@ -3851,7 +3852,7 @@ void InfoAboutHero::initFromHero( const CGHeroInstance *h, bool detailed )
|
||||
//hide info about hero stacks counts using descriptives names ids
|
||||
for(TSlots::const_iterator i = army.Slots().begin(); i != army.Slots().end(); ++i)
|
||||
{
|
||||
army.setStackCount(i->first, i->second.getQuantityID());
|
||||
army.setStackCount(i->first, i->second.getQuantityID()+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1064,7 +1064,7 @@ void CGameHandler::newTurn()
|
||||
}
|
||||
}
|
||||
}
|
||||
void CGameHandler::run(bool resume)
|
||||
void CGameHandler::run(bool resume, const StartInfo *si /*= NULL*/)
|
||||
{
|
||||
using namespace boost::posix_time;
|
||||
BOOST_FOREACH(CConnection *cc, conns)
|
||||
@ -1072,7 +1072,7 @@ void CGameHandler::run(bool resume)
|
||||
ui8 quantity, pom;
|
||||
//ui32 seed;
|
||||
if(!resume)
|
||||
(*cc) << gs->scenarioOps << gs->map->checksum << gs->seed;
|
||||
(*cc) << si << gs->map->checksum << gs->seed; // gs->scenarioOps
|
||||
|
||||
(*cc) >> quantity; //how many players will be handled at that client
|
||||
for(int i=0;i<quantity;i++)
|
||||
@ -3028,6 +3028,46 @@ bool CGameHandler::tradeResources(const IMarket *market, ui32 val, ui8 player, u
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameHandler::sellCreatures(ui32 count, const IMarket *market, const CGHeroInstance * hero, ui32 slot, ui32 resourceID)
|
||||
{
|
||||
if(!vstd::contains(hero->Slots(), slot))
|
||||
COMPLAIN_RET("Hero doesn't have any creature in that slot!");
|
||||
|
||||
const CStackInstance &s = hero->getStack(slot);
|
||||
|
||||
if(s.count < count //can't sell more creatures than have
|
||||
|| hero->Slots().size() == 1 && hero->needsLastStack() && s.count == count) //can't sell last stack
|
||||
{
|
||||
COMPLAIN_RET("Not enough creatures in army!");
|
||||
}
|
||||
|
||||
int b1, b2; //base quantities for trade
|
||||
market->getOffer(s.type->idNumber, resourceID, b1, b2, CREATURE_RESOURCE);
|
||||
int units = count / b1; //how many base quantities we trade
|
||||
|
||||
if(count%b1) //all offered units of resource should be used, if not -> somewhere in calculations must be an error
|
||||
{
|
||||
//TODO: complain?
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
SetGarrisons sg;
|
||||
sg.garrs[hero->id] = hero->getArmy();
|
||||
if(s.count > count)
|
||||
sg.garrs[hero->id].setStackCount(slot, s.count - count);
|
||||
else
|
||||
sg.garrs[hero->id].eraseStack(slot);
|
||||
sendAndApply(&sg);
|
||||
|
||||
SetResource sr;
|
||||
sr.player = hero->tempOwner;
|
||||
sr.resid = resourceID;
|
||||
sr.val = getResource(hero->tempOwner, resourceID) + b2 * units;
|
||||
sendAndApply(&sr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameHandler::sendResources(ui32 val, ui8 player, ui32 r1, ui32 r2)
|
||||
{
|
||||
|
@ -167,6 +167,7 @@ public:
|
||||
bool setFormation( si32 hid, ui8 formation );
|
||||
bool tradeResources(const IMarket *market, ui32 val, ui8 player, ui32 id1, ui32 id2);
|
||||
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 swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot);
|
||||
@ -203,7 +204,7 @@ public:
|
||||
void sendAndApply(SetResources * info);
|
||||
void sendAndApply(NewStructures * info);
|
||||
|
||||
void run(bool resume);
|
||||
void run(bool resume, const StartInfo *si = NULL);
|
||||
void newTurn();
|
||||
void handleAfterAttackCasting( const BattleAttack & bat );
|
||||
friend class CVCMIServer;
|
||||
|
@ -92,6 +92,7 @@ void CVCMIServer::newGame(CConnection *c)
|
||||
*c << ui8(0); //OK!
|
||||
}
|
||||
|
||||
StartInfo startInfoCpy = *si;
|
||||
gh.init(si,rand());
|
||||
c->setGS(gh.gs);
|
||||
|
||||
@ -118,7 +119,7 @@ void CVCMIServer::newGame(CConnection *c)
|
||||
gh.conns.insert(cc);
|
||||
}
|
||||
|
||||
gh.run(false);
|
||||
gh.run(false, &startInfoCpy);
|
||||
}
|
||||
void CVCMIServer::start()
|
||||
{
|
||||
|
@ -141,6 +141,10 @@ bool TradeOnMarketplace::applyGh( CGameHandler *gh )
|
||||
return gh->tradeResources(m, val, player, r1, r2);
|
||||
case RESOURCE_PLAYER:
|
||||
return gh->sendResources(val, player, r1, r2);
|
||||
case CREATURE_RESOURCE:
|
||||
if(!hero)
|
||||
COMPLAIN_AND_RETURN("Only hero can sell creatures!");
|
||||
return gh->sellCreatures(val, m, hero, r1, r2);
|
||||
default:
|
||||
gh->complain("Unknown exchange mode!");
|
||||
ERROR_AND_RETURN;
|
||||
|
Loading…
Reference in New Issue
Block a user