1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Sacrificing artifacts. [Code is one giant workaround but should work good enough.] Updated changelog.

This commit is contained in:
Michał W. Urbańczyk 2010-07-23 12:02:15 +00:00
parent 215dc95acb
commit 8487653a8e
16 changed files with 433 additions and 102 deletions

View File

@ -1,3 +1,37 @@
0.8 -> 0.81 (Jun 01 2010)
GENERAL:
ADVENTURE MAP:
* Neutral armies growth implemented (%10 weekly)
* Power rating of neutral stack
* Favourable Winds reduce sailing cost
BATTLES:
HERO:
TOWNS:
* Support for new town structures:
- Artifact Merchant
- Castle Gates
- Magic University
- Portal of Summoning
- Skeleton transformer
- Veil of Darkness
OBJECTS:
* Stables will now upgrade Cavaliers to Champions.
New object supported:
- Altar of Sacrifice
- Aurora Borealis
- Black Market
- Cover of Darkness
- Hill Fort
- Sanctuary
- Tavern
- University
- Whirlpool
0.8 -> 0.81 (Jun 01 2010)
GENERAL:
* It's possible to start campaign

View File

@ -203,7 +203,7 @@ void CHeroWindow::show(SDL_Surface *to)
garr->show(to);
ourBar->show(to);
artifs->show(to);
artifs->showAll(to);
}
void CHeroWindow::setHero(const CGHeroInstance *hero)

View File

@ -609,7 +609,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
owner->fexitb();
owner->myInt->battleInt->castThisSpell(spell);
}
else //adventure spell
else if(!sp->combatSpell && !owner->myInt->battleInt) //adventure spell
{
using namespace Spells;
int spell = mySpell;

View File

@ -90,7 +90,7 @@ public:
void heroVisitCastle(int obj, int heroID){};
void stopHeroVisitCastle(int obj, int heroID){};
void giveHeroArtifact(int artid, int hid, int position){}; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
void removeArtifact(int artid, int hid){};
bool removeArtifact(int artid, int hid){return false;};
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL){}; //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false){}; //if any of armies is hero, hero will be used
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false){}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle

View File

@ -2745,6 +2745,7 @@ void CTradeWindow::CTradeableItem::showAll(SDL_Surface * to)
case PLAYER:
posToSubCenter = Point(31, 76);
break;
case ARTIFACT_PLACEHOLDER:
case ARTIFACT:
posToSubCenter = Point(18, 57);
break;
@ -2760,12 +2761,37 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
{
CTradeWindow *mw = static_cast<CTradeWindow *>(parent);
assert(mw);
if(type == ARTIFACT_PLACEHOLDER)
{
}
if(down)
{
if(type == ARTIFACT_PLACEHOLDER)
{
CAltarWindow *aw = static_cast<CAltarWindow *>(mw);
const CArtifact *movedArt = aw->arts->commonInfo->srcArtifact;
if(movedArt)
{
aw->moveFromSlotToAltar(aw->arts->commonInfo->srcSlotID, this, movedArt->id);
}
else if(id >= 0)
{
movedArt = CGI->arth->artifacts[id];
aw->arts->commonInfo->srcAOH = aw->arts;
aw->arts->commonInfo->srcArtifact = movedArt;
aw->arts->commonInfo->srcSlotID = 19 + vstd::findPos(aw->hero->artifacts, movedArt->id);
aw->arts->commonInfo->destAOH = aw->arts;
CGI->curh->dragAndDropCursor(graphics->artDefs->ourImages[movedArt->id].bitmap);
id = -1;
subtitle = "";
aw->arts->artifactsOnAltar.erase(movedArt->id);
aw->deal->block(!aw->arts->artifactsOnAltar.size());
aw->arts->markPossibleSlots(movedArt);
}
aw->calcTotalExp();
return;
}
if(left)
{
if(mw->hLeft != this)
@ -2793,7 +2819,8 @@ SDL_Surface * CTradeWindow::CTradeableItem::getSurface()
case PLAYER:
return graphics->flags->ourImages[id].bitmap;
case ARTIFACT:
return graphics->artDefs->ourImages[id].bitmap;
case ARTIFACT_PLACEHOLDER:
return id >= 0 ? graphics->artDefs->ourImages[id].bitmap : NULL;
case CREATURE:
return graphics->bigImgs[id];
default:
@ -2841,12 +2868,20 @@ void CTradeWindow::CTradeableItem::hover(bool on)
void CTradeWindow::CTradeableItem::clickRight(tribool down, bool previousState)
{
switch(type)
if(down)
{
case CREATURE:
case CREATURE_PLACEHOLDER:
//GH.statusbar->print(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->creatures[id]->namePl));
break;
switch(type)
{
case CREATURE:
case CREATURE_PLACEHOLDER:
//GH.statusbar->print(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->creatures[id]->namePl));
break;
case ARTIFACT:
case ARTIFACT_PLACEHOLDER:
if(id >= 0)
adventureInt->handleRightClick(CGI->arth->artifacts[id]->Description(), down);
break;
}
}
}
@ -2908,7 +2943,7 @@ void CTradeWindow::initItems(bool Left)
for(int j=0; j<amount; j++)
{
int id = (ids && ids->size()>j) ? (*ids)[j] : j;
if(id < 0)
if(id < 0 && mode != ARTIFACT_EXP) //when sacrificing artifacts we need to prepare empty slots
continue;
CTradeableItem *hlp = new CTradeableItem(itemsType[Left], id, Left, j);
@ -2923,6 +2958,9 @@ std::vector<int> *CTradeWindow::getItemsIds(bool Left)
{
std::vector<int> *ids = NULL;
if(mode == ARTIFACT_EXP)
return new std::vector<int>(22, -1);
if(Left)
{
switch(itemsType[1])
@ -2974,8 +3012,8 @@ void CTradeWindow::getPositionsFor(std::vector<Rect> &poss, bool Left, EType typ
for (int j = 0; j < 5 ; j++)
poss += Rect(x + dx*j, y + dy*i, w, h);
poss += Rect(x + dx*2.5, y + dy*5, w, h);
poss += Rect(x + dx*2.5, y + dy*5, w, h);
poss += Rect(x + dx*1.5, y + dy*4, w, h);
poss += Rect(x + dx*2.5, y + dy*4, w, h);
}
else
{
@ -3085,19 +3123,23 @@ void CTradeWindow::getEmptySlots(std::set<CTradeableItem *> &toRemove)
void CTradeWindow::setMode(EMarketMode Mode)
{
const IMarket *m = market;
const CGHeroInstance *h = hero;
CTradeWindow *nwindow = NULL;
GH.popIntTotally(this);
switch(Mode)
{
case CREATURE_EXP:
case ARTIFACT_EXP:
nwindow = new CAltarWindow(market, hero, Mode);
nwindow = new CAltarWindow(m, h, Mode);
break;
default:
nwindow = new CMarketplaceWindow(market, hero, Mode);
nwindow = new CMarketplaceWindow(m, h, Mode);
break;
}
GH.popIntTotally(this);
GH.pushInt(nwindow);
}
@ -3490,15 +3532,19 @@ CAltarWindow::CAltarWindow(const IMarket *Market, const CGHeroInstance *Hero /*=
sacrificeBackpack = new AdventureMapButton(CGI->generaltexth->zelp[570],boost::bind(&CAltarWindow::SacrificeBackpack,this),147,520,"ALTEMBK.DEF");
sacrificeBackpack->block(!hero->artifacts.size());
BLOCK_CAPTURING;
slider = NULL;
max = NULL;
arts = new CArtifactsOfHero(Point(-267,-10));
arts->commonInfo = new CArtifactsOfHero::SCommonPart;
arts->commonInfo->participants.insert(arts);
arts->setHero(Hero);
arts->recActions = 255;
addChild(arts);
{
BLOCK_CAPTURING;
arts = new CArtifactsOfHero(Point(-267,-10));
arts->commonInfo = new CArtifactsOfHero::SCommonPart;
arts->commonInfo->participants.insert(arts);
arts->setHero(Hero);
arts->recActions = 255;
arts->allowedAssembling = false;
addChild(arts);
}
initItems(false);
}
@ -3512,9 +3558,9 @@ CAltarWindow::CAltarWindow(const IMarket *Market, const CGHeroInstance *Hero /*=
deal = new AdventureMapButton(CGI->generaltexth->zelp[585],boost::bind(&CAltarWindow::makeDeal,this),269,520,"ALTSACR.DEF");
if(/*Hero->getAlignment() != EVIL && */Mode == CREATURE_EXP)
if(Hero->getAlignment() != EVIL && Mode == CREATURE_EXP)
new AdventureMapButton(CGI->generaltexth->zelp[580], boost::bind(&CTradeWindow::setMode,this, ARTIFACT_EXP), 516, 421, "ALTART.DEF");
if(/*Hero->getAlignment() != GOOD && */Mode == ARTIFACT_EXP)
if(Hero->getAlignment() != GOOD && Mode == ARTIFACT_EXP)
new AdventureMapButton(CGI->generaltexth->zelp[572], boost::bind(&CTradeWindow::setMode,this, CREATURE_EXP), 516, 421, "ALTSACC.DEF");
expPerUnit.resize(ARMY_SIZE, 0);
@ -3555,23 +3601,44 @@ void CAltarWindow::sliderMoved(int to)
void CAltarWindow::makeDeal()
{
blockTrade();
slider->value = 0;
std::vector<int> toSacrifice = sacrificedUnits;
for (int i = 0; i < toSacrifice.size(); i++)
if(mode == CREATURE_EXP)
{
if(toSacrifice[i])
LOCPLINT->cb->trade(market->o, mode, i, 0, toSacrifice[i], hero);
blockTrade();
slider->value = 0;
std::vector<int> toSacrifice = sacrificedUnits;
for (int i = 0; i < toSacrifice.size(); i++)
{
if(toSacrifice[i])
LOCPLINT->cb->trade(market->o, mode, i, 0, toSacrifice[i], hero);
}
BOOST_FOREACH(int& val, sacrificedUnits)
val = 0;
BOOST_FOREACH(CTradeableItem *t, items[0])
{
t->type = CREATURE_PLACEHOLDER;
t->subtitle = "";
}
}
BOOST_FOREACH(int& val, sacrificedUnits)
val = 0;
BOOST_FOREACH(CTradeableItem *t, items[0])
else
{
t->type = CREATURE_PLACEHOLDER;
t->subtitle = "";
BOOST_FOREACH(int artID, arts->artifactsOnAltar) //sacrifice each artifact on the list
{
LOCPLINT->cb->trade(market->o, mode, artID, -1, 1, hero);
}
arts->artifactsOnAltar.clear();
BOOST_FOREACH(CTradeableItem *t, items[0])
{
t->id = -1;
t->subtitle = "";
}
arts->commonInfo->reset();
arts->scrollBackpack(0);
deal->block(true);
}
calcTotalExp();
@ -3579,14 +3646,33 @@ void CAltarWindow::makeDeal()
void CAltarWindow::SacrificeAll()
{
BOOST_FOREACH(CTradeableItem *t, items[1])
sacrificedUnits[t->serial] = hero->getAmount(t->serial);
if(mode == CREATURE_EXP)
{
bool movedAnything = false;
BOOST_FOREACH(CTradeableItem *t, items[1])
sacrificedUnits[t->serial] = hero->getAmount(t->serial);
sacrificedUnits[items[1].front()->serial]--;
sacrificedUnits[items[1].front()->serial]--;
BOOST_FOREACH(CTradeableItem *t, items[0])
updateRight(t);
BOOST_FOREACH(CTradeableItem *t, items[0])
{
updateRight(t);
if(t->type == CREATURE)
movedAnything = true;
}
deal->block(!movedAnything);
calcTotalExp();
}
else
{
for(std::map<ui16,ui32>::const_iterator i = hero->artifWorn.begin(); i != hero->artifWorn.end(); i++)
{
moveFromSlotToAltar(i->first, NULL, i->second);
}
SacrificeBackpack();
}
redraw();
}
@ -3599,7 +3685,13 @@ void CAltarWindow::selectionChanged(bool side)
CTradeableItem *&theOther = side ? hRight : hLeft;
theOther = *std::find_if(items[!side].begin(), items[!side].end(), boost::bind(&CTradeableItem::serial, _1) == selected->serial);
slider->setAmount(hero->getAmount(hLeft->serial));
int stackCount = 0;
for (int i = 0; i < ARMY_SIZE; i++)
if(hero->getAmount(i) > sacrificedUnits[i])
stackCount++;
slider->setAmount(hero->getAmount(hLeft->serial) - (stackCount == 1));
slider->block(!slider->amount);
slider->value = sacrificedUnits[hLeft->serial];
max->block(!slider->amount);
@ -3672,16 +3764,28 @@ void CAltarWindow::getExpValues()
void CAltarWindow::calcTotalExp()
{
int val = 0;
for (int i = 0; i < sacrificedUnits.size(); i++)
if(mode == CREATURE_EXP)
{
val += expPerUnit[i] * sacrificedUnits[i];
for (int i = 0; i < sacrificedUnits.size(); i++)
{
val += expPerUnit[i] * sacrificedUnits[i];
}
}
else
{
for(std::multiset<int>::const_iterator i = arts->artifactsOnAltar.begin(); i != arts->artifactsOnAltar.end(); i++)
{
int dmp, valOfArt;
market->getOffer(*i, 0, dmp, valOfArt, mode);
val += valOfArt * arts->artifactsOnAltar.count(*i);
}
}
expOnAltar->setTxt(boost::lexical_cast<std::string>(val));
}
void CAltarWindow::setExpToLevel()
{
expToLevel->setTxt(boost::lexical_cast<std::string>(CGI->heroh->reqExp(hero->level+1) - hero->exp));
expToLevel->setTxt(boost::lexical_cast<std::string>(CGI->heroh->reqExp(CGI->heroh->level(hero->exp)+1) - hero->exp));
}
void CAltarWindow::blockTrade()
@ -3703,9 +3807,86 @@ void CAltarWindow::updateRight(CTradeableItem *toUpdate)
toUpdate->subtitle = val ? boost::str(boost::format(CGI->generaltexth->allTexts[122]) % boost::lexical_cast<std::string>(val * expPerUnit[toUpdate->serial])) : ""; //%s exp
}
int CAltarWindow::firstFreeSlot()
{
int ret = -1;
while(items[0][++ret]->id >= 0 && ret + 1 < items[0].size());
return ret < items[0].size() ? ret : -1;
}
void CAltarWindow::SacrificeBackpack()
{
std::multiset<int> toOmmit = arts->artifactsOnAltar;
for (int i = 0; i < hero->artifacts.size(); i++)
{
if(vstd::contains(toOmmit, hero->artifacts[i]))
{
toOmmit -= hero->artifacts[i];
continue;
}
putOnAltar(NULL, hero->artifacts[i]);
}
arts->scrollBackpack(0);
calcTotalExp();
}
void CAltarWindow::artifactPicked()
{
redraw();
}
void CAltarWindow::showAll(SDL_Surface * to)
{
CTradeWindow::showAll(to);
if(mode == ARTIFACT_EXP && arts && arts->commonInfo->srcArtifact)
{
blitAtLoc(graphics->artDefs->ourImages[arts->commonInfo->srcArtifact->id].bitmap, 281, 442, to);
int dmp, val;
market->getOffer(arts->commonInfo->srcArtifact->id, 0, dmp, val, ARTIFACT_EXP);
printAtMiddleLoc(boost::lexical_cast<std::string>(val), 304, 498, FONT_SMALL, zwykly, to);
}
}
bool CAltarWindow::putOnAltar(CTradeableItem* altarSlot, int artID)
{
if(artID != 1 && artID < 7) //special art
return false;
if(!altarSlot)
{
int slotIndex = firstFreeSlot();
if(slotIndex < 0)
{
tlog2 << "No free slots on altar!\n";
return false;
}
altarSlot = items[0][slotIndex];
}
int dmp, val;
market->getOffer(artID, 0, dmp, val, ARTIFACT_EXP);
arts->artifactsOnAltar.insert(artID);
altarSlot->id = artID;
altarSlot->subtitle = boost::lexical_cast<std::string>(val);
deal->block(false);
return true;
}
void CAltarWindow::moveFromSlotToAltar(int slotID, CTradeableItem* altarSlot, int artID)
{
if(arts->commonInfo->srcArtifact)
{
arts->commonInfo->destSlotID = 65500;
arts->commonInfo->destAOH = arts;
}
if(putOnAltar(altarSlot, artID))
LOCPLINT->cb->swapArtifacts(hero, slotID, hero, 65500);
}
CSystemOptionsWindow::CSystemOptionsWindow(const SDL_Rect &pos, CPlayerInterface * owner)
@ -4465,34 +4646,39 @@ void CArtPlace::clickRight(tribool down, bool previousState)
if (slotID < 19)
{
selectedNo = false;
// If the artifact can be assembled, display dialog.
if (ourArt->constituentOf != NULL) {
BOOST_FOREACH(ui32 combination, *ourArt->constituentOf) {
if (ourArt->canBeAssembledTo(ourOwner->curHero->artifWorn, combination)) {
LOCPLINT->showArtifactAssemblyDialog(
ourArt->id,
combination,
true,
boost::bind(&CCallback::assembleArtifacts, LOCPLINT->cb, ourOwner->curHero, slotID, true, combination),
boost::bind(&CArtPlace::userSelectedNo, this));
if (!selectedNo)
return;
if(ourOwner->allowedAssembling)
{
// If the artifact can be assembled, display dialog.
if (ourArt->constituentOf != NULL)
{
BOOST_FOREACH(ui32 combination, *ourArt->constituentOf)
{
if (ourArt->canBeAssembledTo(ourOwner->curHero->artifWorn, combination))
{
LOCPLINT->showArtifactAssemblyDialog(
ourArt->id,
combination,
true,
boost::bind(&CCallback::assembleArtifacts, LOCPLINT->cb, ourOwner->curHero, slotID, true, combination),
boost::bind(&CArtPlace::userSelectedNo, this));
if (!selectedNo)
return;
}
}
}
}
// Otherwise if the artifact can be diasassembled, display dialog.
if (ourArt->constituents != NULL)
{
LOCPLINT->showArtifactAssemblyDialog(
ourArt->id,
0,
false,
boost::bind(&CCallback::assembleArtifacts, LOCPLINT->cb, ourOwner->curHero, slotID, false, 0),
boost::bind(&CArtPlace::userSelectedNo, this));
if (!selectedNo)
return;
// Otherwise if the artifact can be diasassembled, display dialog.
if (ourArt->constituents != NULL)
{
LOCPLINT->showArtifactAssemblyDialog(
ourArt->id,
0,
false,
boost::bind(&CCallback::assembleArtifacts, LOCPLINT->cb, ourOwner->curHero, slotID, false, 0),
boost::bind(&CArtPlace::userSelectedNo, this));
if (!selectedNo)
return;
}
}
}
@ -4533,13 +4719,15 @@ void CArtPlace::select ()
ourOwner->markPossibleSlots(ourArt);
//ourOwner->curHero->recreateArtBonuses();
// Update the hero bonuses.
ourOwner->updateParentWindow();
if (slotID >= 19)
ourOwner->scrollBackpack(backpackCorrection);
else
ourOwner->eraseSlotData(this, slotID);
// Update the hero bonuses.
ourOwner->updateParentWindow();
ourOwner->safeRedraw();
}
/**
@ -4559,7 +4747,7 @@ void CArtPlace::deactivate()
}
}
void CArtPlace::show(SDL_Surface *to)
void CArtPlace::showAll(SDL_Surface *to)
{
if (ourArt)
blitAt(graphics->artDefs->ourImages[ourArt->id].bitmap, pos.x, pos.y, to);
@ -4703,6 +4891,7 @@ void CArtifactsOfHero::SCommonPart::reset()
destAOH = srcAOH = NULL;
destArtifact = srcArtifact = NULL;
destSlotID = srcSlotID = -1;
CGI->curh->dragAndDropCursor(NULL);
}
void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
@ -4751,7 +4940,6 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
{
// Reset all parameters.
commonInfo->reset();
CGI->curh->dragAndDropCursor(NULL);
unmarkSlots();
}
}
@ -4776,10 +4964,6 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
for (int g = 0; g < 19 ; g++)
setSlotData(artWorn[g], g);
scrollBackpack(0);
//blocking scrolling if there is not enough artifacts to scroll
leftArtRoll->block(curHero->artifacts.size() <= backpack.size());
rightArtRoll->block(curHero->artifacts.size() <= backpack.size());
}
void CArtifactsOfHero::dispose()
@ -4792,23 +4976,54 @@ void CArtifactsOfHero::scrollBackpack(int dir)
backpackPos += dir;
if (curHero->artifacts.size() > 0)
{
if (backpackPos < 0) { // No guarantee of modulus behavior with negative operands.
do {
if (backpackPos < 0) // No guarantee of modulus behavior with negative operands.
{
do
{
backpackPos += curHero->artifacts.size();
} while (backpackPos < 0);
} else {
}
else
{
backpackPos %= curHero->artifacts.size();
}
}
std::multiset<int> toOmmit = artifactsOnAltar;
int ommited = 0;
//set new data
for (size_t s = 0; s < backpack.size(); ++s)
size_t s = 0;
for( ; s < curHero->artifacts.size(); ++s)
{
if (s < curHero->artifacts.size())
setSlotData(backpack[s], 19 + (s + backpackPos)%curHero->artifacts.size());
else
eraseSlotData(backpack[s], 19 + s);
{
int slotID = 19 + (s + backpackPos)%curHero->artifacts.size();
const CArtifact *art = curHero->getArt(slotID);
assert(art);
if(!vstd::contains(toOmmit, art->id))
{
if(s - ommited < 5)
setSlotData(backpack[s-ommited], slotID);
}
else
{
toOmmit -= art->id;
ommited ++;
continue;
}
}
}
for( ; s - ommited < 5; s++)
eraseSlotData(backpack[s-ommited], 19 + s);
//blocking scrolling if there is not enough artifacts to scroll
leftArtRoll->block(curHero->artifacts.size() - ommited <= backpack.size());
rightArtRoll->block(curHero->artifacts.size() - ommited <= backpack.size());
safeRedraw();
}
/**
@ -4830,6 +5045,8 @@ void CArtifactsOfHero::markPossibleSlots (const CArtifact* art)
(*it)->artWorn[i]->marked = false;
}
}
safeRedraw();
}
/**
@ -4846,6 +5063,8 @@ void CArtifactsOfHero::unmarkSlots ()
(*it)->artWorn[i]->marked = false;
}
}
safeRedraw();
}
/**
@ -4882,7 +5101,7 @@ void CArtifactsOfHero::eraseSlotData (CArtPlace* artPlace, int slotID)
}
CArtifactsOfHero::CArtifactsOfHero(const Point &position) :
backpackPos(0), updateState(false), commonInfo(NULL), curHero(NULL)
backpackPos(0), updateState(false), commonInfo(NULL), curHero(NULL), allowedAssembling(true)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
pos += position;
@ -4970,6 +5189,14 @@ void CArtifactsOfHero::updateParentWindow()
}
}
void CArtifactsOfHero::safeRedraw()
{
if(parent)
parent->redraw();
else
redraw();
}
void CExchangeWindow::close()
{
GH.popIntTotally(this);
@ -5071,8 +5298,8 @@ void CExchangeWindow::show(SDL_Surface * to)
if(screen->w != 800 || screen->h !=600)
CMessage::drawBorder(LOCPLINT->playerID,to,828,628,pos.x-14,pos.y-15);
artifs[0]->show(to);
artifs[1]->show(to);
artifs[0]->showAll(to);
artifs[1]->showAll(to);
ourBar->show(to);

View File

@ -687,7 +687,11 @@ public:
void selectionChanged(bool side); //true == left
void SacrificeAll();
void SacrificeBackpack();
void putOnAltar(int backpackIndex);
bool putOnAltar(CTradeableItem* altarSlot, int artID);
void makeDeal();
void showAll(SDL_Surface * to);
void blockTrade();
void sliderMoved(int to);
@ -701,6 +705,10 @@ public:
void calcTotalExp();
void setExpToLevel();
void updateRight(CTradeableItem *toUpdate);
void artifactPicked();
int firstFreeSlot();
void moveFromSlotToAltar(int slotID, CTradeableItem* altarSlot, int artID);
};
class CSystemOptionsWindow : public CIntObject
@ -900,7 +908,7 @@ public:
void deselect ();
void activate();
void deactivate();
void show(SDL_Surface * to);
void showAll(SDL_Surface * to);
bool fitsHere (const CArtifact * art); //returns true if given artifact can be placed here
bool locked () const;
void userSelectedNo ();
@ -937,10 +945,14 @@ public:
bool updateState; // Whether the commonInfo should be updated on setHero or not.
AdventureMapButton * leftArtRoll, * rightArtRoll;
bool allowedAssembling;
std::multiset<int> artifactsOnAltar; //artifacts id that are technically present in backpack but in GUI are moved to the altar - they'll be ommited in backpack slots
void setHero(const CGHeroInstance * hero);
void dispose(); //free resources not needed after closing windows and reset state
void scrollBackpack(int dir); //dir==-1 => to left; dir==1 => to right
void safeRedraw();
void markPossibleSlots (const CArtifact* art);
void unmarkSlots ();
void setSlotData (CArtPlace* artPlace, int slotID);

View File

@ -143,6 +143,27 @@ CArtifact::~CArtifact()
{
}
int CArtifact::getArtClassSerial() const
{
if(id == 1)
return 4;
switch(aClass)
{
case ART_TREASURE:
return 0;
case ART_MINOR:
return 1;
case ART_MAJOR:
return 2;
case ART_RELIC:
return 3;
case ART_SPECIAL:
return 5;
}
return -1;
}
CArtHandler::CArtHandler()
{
VLC->arth = this;

View File

@ -30,6 +30,7 @@ public:
bool canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 artifactID) const;
void addBonusesTo (BonusList *otherBonuses) const;
void removeBonusesFrom (BonusList *otherBonuses) const;
int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other
ui32 price;
std::vector<ui16> possibleSlots; //ids of slots where artifact can be placed

View File

@ -6507,7 +6507,21 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode)
val2 = (VLC->creh->creatures[id1]->AIValue / 40) * 5;
}
break;
case ARTIFACT_EXP:
{
val1 = 1;
int givenClass = VLC->arth->artifacts[id1]->getArtClassSerial();
if(givenClass < 0 || givenClass > 3)
{
val2 = 0;
return false;
}
static const int expPerClass[] = {1000, 1500, 3000, 6000};
val2 = expPerClass[givenClass];
}
break;
default:
assert(0);
return false;

View File

@ -469,7 +469,7 @@ bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, SDL_Surface
void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, bool update )
{
if(current)
if(!current)
return;
bool w = false;

View File

@ -2635,7 +2635,7 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange( const CStack* attacker, con
if(defendingHero)
{
multBonus *= (std::max(0, 100-attackerHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 23))) / 100.0f;
multBonus *= (std::max(0, 100-defendingHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 23))) / 100.0f;
}
//handling hate effect

View File

@ -91,7 +91,7 @@ public:
virtual void heroVisitCastle(int obj, int heroID)=0;
virtual void stopHeroVisitCastle(int obj, int heroID)=0;
virtual void giveHeroArtifact(int artid, int hid, int position)=0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
virtual void removeArtifact(int artid, int hid) = 0;
virtual bool removeArtifact(int artid, int hid) = 0;
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL)=0; //use hero=NULL for no hero
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle

View File

@ -1409,7 +1409,7 @@ struct TradeOnMarketplace : public CPackForServer
const CGObjectInstance *market;
const CGHeroInstance *hero; //needed when trading artifacts / creatures
ui8 mode;//enum EMarketMode
ui32 r1, r2; //mode 0: r1 - sold resource, r2 - bought res
ui32 r1, r2; //mode 0: r1 - sold resource, r2 - bought res (exception: when sacrificing art r1 is art id [todo: make r2 preferred slot?]
ui32 val; //units of sold resource
bool applyGh(CGameHandler *gh);

View File

@ -2095,7 +2095,7 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
sendAndApply(&sha);
}
void CGameHandler::removeArtifact(int artid, int hid)
bool CGameHandler::removeArtifact(int artid, int hid)
{
const CGHeroInstance* h = getHero(hid);
@ -2109,7 +2109,8 @@ void CGameHandler::removeArtifact(int artid, int hid)
sha.artifacts.erase(it);
else //worn
{
for (std::map<ui16,ui32>::iterator itr = sha.artifWorn.begin(); itr != sha.artifWorn.end(); ++itr)
std::map<ui16,ui32>::iterator itr;
for (itr = sha.artifWorn.begin(); itr != sha.artifWorn.end(); ++itr)
{
if (itr->second == artid)
{
@ -2117,8 +2118,15 @@ void CGameHandler::removeArtifact(int artid, int hid)
break;
}
}
if(itr == sha.artifWorn.end())
{
tlog2 << "Cannot find artifact to remove!\n";
return false;
}
}
sendAndApply(&sha);
return true;
}
void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town) //use hero=NULL for no hero
@ -4930,5 +4938,16 @@ bool CGameHandler::sacrificeCreatures(const IMarket *market, const CGHeroInstanc
exp *= count;
changePrimSkill (hero->id, 4, exp);
return true;
}
bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, ui32 artID)
{
if(!removeArtifact(artID, hero->id))
COMPLAIN_RET("Cannot find artifact to sacrifice!");
int dmp, expToGive;
m->getOffer(artID, 0, dmp, expToGive, ARTIFACT_EXP);
changePrimSkill(hero->id, 4, expToGive);
return true;
}

View File

@ -139,7 +139,7 @@ public:
void stopHeroVisitCastle(int obj, int heroID);
void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack
void moveArtifact(int hid, int oldPosition, int destPos);
void removeArtifact(int artid, int hid);
bool removeArtifact(int artid, int hid);
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL); //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false); //if any of armies is hero, hero will be used
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false); //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
@ -216,6 +216,7 @@ public:
void run(bool resume, const StartInfo *si = NULL);
void newTurn();
void handleAfterAttackCasting( const BattleAttack & bat );
bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, ui32 artID);
friend class CVCMIServer;
friend class CScriptCallback;
};

View File

@ -162,6 +162,8 @@ bool TradeOnMarketplace::applyGh( CGameHandler *gh )
return gh->buySecSkill(m, hero, r2);
case CREATURE_EXP:
return gh->sacrificeCreatures(m, hero, r1, val);
case ARTIFACT_EXP:
return gh->sacrificeArtifact(m, hero, r1);
default:
COMPLAIN_AND_RETURN("Unknown exchange mode!");
}