1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

Little more work on artifacts.

This commit is contained in:
Michał W. Urbańczyk 2010-12-29 21:04:22 +00:00
parent 8104a43809
commit c9189119b9
17 changed files with 425 additions and 314 deletions

View File

@ -69,6 +69,7 @@ CHeroSwitcher::CHeroSwitcher(int serial)
CHeroWindow::CHeroWindow(const CGHeroInstance *hero)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
artifs = NULL;
garr = NULL;
curHero = NULL;
player = hero->tempOwner;
@ -162,6 +163,7 @@ void CHeroWindow::setHero(const CGHeroInstance *hero)
}
if(hero == curHero)
{
tlog3 << "Spurious call to CHeroWindow::setHero\n";
return;
}
@ -180,13 +182,15 @@ void CHeroWindow::setHero(const CGHeroInstance *hero)
{
delete garr;
OBJ_CONSTRUCTION_CAPTURING_ALL;
garr = new CGarrisonInt(80, 493, 8, Point(), background->bg, Point(16,486), curHero);
garr = new CGarrisonInt(15, 485, 8, Point(), background->bg, Point(15,485), curHero);
artifs = new CArtifactsOfHero(Point(-65, -8), true);
artifs->setHero(hero);
}
AdventureMapButton * split = NULL;
{
BLOCK_CAPTURING;
split = new AdventureMapButton(CGI->generaltexth->allTexts[256], CGI->generaltexth->heroscrn[32], boost::bind(&CGarrisonInt::splitClick,garr), pos.x+604, pos.y+527, "hsbtns9.def", false, NULL, false); //deleted by garrison destructor
split = new AdventureMapButton(CGI->generaltexth->allTexts[256], CGI->generaltexth->heroscrn[32], boost::bind(&CGarrisonInt::splitClick,garr), 604, 527, "hsbtns9.def", false, NULL, false); //deleted by garrison destructor
}
boost::algorithm::replace_first(split->hoverTexts[0],"%s",CGI->generaltexth->allTexts[43]);
garr->addSplitBtn(split);
@ -326,14 +330,14 @@ void CHeroWindow::showAll(SDL_Surface * to)
//hero list blitting
for(int pos=0, g=0; g<LOCPLINT->wanderingHeroes.size(); ++g)
for(int slotPos=0, g=0; g<LOCPLINT->wanderingHeroes.size(); ++g)
{
const CGHeroInstance * cur = LOCPLINT->wanderingHeroes[g];
if (cur->inTownGarrison)
// Only display heroes that are not in garrison
continue;
blitAtLoc(graphics->portraitSmall[cur->portrait], 611, 87+pos*54, to);
blitAtLoc(graphics->portraitSmall[cur->portrait], 611, 87+slotPos*54, to);
//printing yellow border
if(cur->name == curHero->name)
{
@ -341,13 +345,11 @@ void CHeroWindow::showAll(SDL_Surface * to)
{
for(int h=0; h<graphics->portraitSmall[cur->portrait]->h; ++h)
if(f==0 || h==0 || f==graphics->portraitSmall[cur->portrait]->w-1 || h==graphics->portraitSmall[cur->portrait]->h-1)
{
CSDL_Ext::SDL_PutPixelWithoutRefresh(to, 611+f, 87+pos*54+h, 240, 220, 120);
}
CSDL_Ext::SDL_PutPixelWithoutRefresh(to, pos.x + 611+f, pos.y + 87+slotPos*54+h, 240, 220, 120);
}
}
pos ++;
slotPos ++;
}
//secondary skills

View File

@ -773,7 +773,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
for (int i=0; i<artifacts.size(); i++)
{
artifacts[i]->type = hero->getArtAtPos(i)->id;
artifacts[i]->type = hero->getArtTypeId(i);
if (artifacts[i]->type<0 || artifacts[i]->type == 145 )
artifacts[i]->hoverText = CGI->generaltexth->heroscrn[11];
else
@ -785,7 +785,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
for (int i=0; i<backpack.size(); i++)
{
backpack[i]->type = hero->getArtAtPos(19+i)->id;
backpack[i]->type = hero->getArtTypeId(19+i);
if (backpack[i]->type<0)
backpack[i]->hoverText ="";
else
@ -836,7 +836,7 @@ void CKingdomInterface::CHeroItem::scrollArts(int move)
backpackPos = ( backpackPos + move + hero->artifacts.size()) % hero->artifacts.size();
for (int i=0; i<backpack.size(); i++)
{
backpack[i]->type = hero->getArtAtPos(19+(backpackPos + i)%hero->artifacts.size())->id;
backpack[i]->type = hero->getArtTypeId(19+(backpackPos + i)%hero->artifacts.size());
if (backpack[i]->type<0)
backpack[i]->hoverText ="";
else
@ -901,7 +901,7 @@ void CKingdomInterface::CHeroItem::showAll(SDL_Surface * to)
case 0://equipped arts
for (int i = iter ; i<iter+9;i++)
{
int artID = hero->getArtAtPos(i)->id;
int artID = hero->getArtTypeId(i);
if (artID>=0)
blitAt(graphics->artDefs->ourImages[artID].bitmap,pos.x+268+48*(i%9),pos.y+66,to);
}

View File

@ -2607,7 +2607,7 @@ void CTradeWindow::CTradeableItem::showAll(SDL_Surface * to)
if(downSelection)
posToSubCenter.y += 8;
break;
case ARTIFACT:
case ARTIFACT_TYPE:
posToSubCenter = Point(19, 58);
break;
}
@ -2628,17 +2628,17 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
if(type == ARTIFACT_PLACEHOLDER)
{
CAltarWindow *aw = static_cast<CAltarWindow *>(mw);
const CArtifact *movedArt = aw->arts->commonInfo->srcArtifact;
const CArtifactInstance *movedArt = aw->arts->commonInfo->srcArtifact;
if(movedArt)
{
aw->moveFromSlotToAltar(aw->arts->commonInfo->srcSlotID, this, movedArt->id);
}
else if(id >= 0)
else if(const CArtifactInstance *art = getArtInstance())
{
movedArt = CGI->arth->artifacts[id];
movedArt = art;
aw->arts->commonInfo->srcAOH = aw->arts;
aw->arts->commonInfo->srcArtifact = movedArt;
aw->arts->commonInfo->srcSlotID = 19 + vstd::findPos(aw->hero->artifacts, const_cast<CArtifact*>(movedArt));
aw->arts->commonInfo->srcSlotID = aw->hero->CArtifactSet::getArtPos(art);// vstd::findPos(aw->hero->artifacts, const_cast<CArtifact*>(movedArt));
aw->arts->commonInfo->destAOH = aw->arts;
CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[movedArt->id].bitmap);
@ -2679,7 +2679,7 @@ SDL_Surface * CTradeWindow::CTradeableItem::getSurface()
return graphics->resources32->ourImages[id].bitmap;
case PLAYER:
return graphics->flags->ourImages[id].bitmap;
case ARTIFACT:
case ARTIFACT_TYPE:
case ARTIFACT_PLACEHOLDER:
return id >= 0 ? graphics->artDefs->ourImages[id].bitmap : NULL;
case CREATURE:
@ -2737,7 +2737,7 @@ void CTradeWindow::CTradeableItem::clickRight(tribool down, bool previousState)
case CREATURE_PLACEHOLDER:
//GH.statusbar->print(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->creatures[id]->namePl));
break;
case ARTIFACT:
case ARTIFACT_TYPE:
case ARTIFACT_PLACEHOLDER:
if(id >= 0)
adventureInt->handleRightClick(CGI->arth->artifacts[id]->Description(), down);
@ -2759,13 +2759,40 @@ std::string CTradeWindow::CTradeableItem::getName(int number /*= -1*/) const
return CGI->creh->creatures[id]->nameSing;
else
return CGI->creh->creatures[id]->namePl;
case ARTIFACT:
case ARTIFACT_TYPE:
return CGI->arth->artifacts[id]->Name();
}
assert(0);
return "";
}
const CArtifactInstance * CTradeWindow::CTradeableItem::getArtInstance() const
{
switch(type)
{
case ARTIFACT_PLACEHOLDER:
case ARTIFACT_INSTANCE:
return (const CArtifactInstance *)hlp;
default:
return NULL;
}
}
const CArtifact * CTradeWindow::CTradeableItem::getArt() const
{
return NULL;
}
void CTradeWindow::CTradeableItem::setArtInstance(const CArtifactInstance *art) const
{
}
void CTradeWindow::CTradeableItem::setArt(const CArtifact *artT) const
{
}
CTradeWindow::CTradeWindow(const IMarket *Market, const CGHeroInstance *Hero, EMarketMode Mode)
: market(Market), hero(Hero), arts(NULL), hLeft(NULL), hRight(NULL), readyToTrade(false)
{
@ -2792,14 +2819,14 @@ void CTradeWindow::initTypes()
break;
case RESOURCE_ARTIFACT:
itemsType[1] = RESOURCE;
itemsType[0] = ARTIFACT;
itemsType[0] = ARTIFACT_TYPE;
break;
case CREATURE_EXP:
itemsType[1] = CREATURE;
itemsType[0] = CREATURE_PLACEHOLDER;
break;
case ARTIFACT_EXP:
itemsType[1] = ARTIFACT;
itemsType[1] = ARTIFACT_TYPE;
itemsType[0] = ARTIFACT_PLACEHOLDER;
break;
}
@ -2869,7 +2896,7 @@ std::vector<int> *CTradeWindow::getItemsIds(bool Left)
ids->push_back(i);
break;
case ARTIFACT:
case ARTIFACT_TYPE:
ids = new std::vector<int>(market->availableItemsIds(mode));
break;
}
@ -3318,7 +3345,7 @@ std::string CMarketplaceWindow::selectionSubtitle(bool Left) const
{
case RESOURCE:
return boost::lexical_cast<std::string>( slider->value * r2 );
case ARTIFACT:
case ARTIFACT_TYPE:
return (deal->blocked ? "0" : "1");
case PLAYER:
return (hRight ? CGI->generaltexth->capColors[hRight->id] : "");
@ -3346,7 +3373,7 @@ Point CMarketplaceWindow::selectionOffset(bool Left) const
{
case RESOURCE:
return Point(410, 446);
case ARTIFACT:
case ARTIFACT_TYPE:
return Point(425, 447);
case PLAYER:
return Point(417, 451);
@ -3392,7 +3419,7 @@ void CMarketplaceWindow::getBaseForPositions(EType type, int &dx, int &dy, int &
dy = 98;
assert(!Right);
break;
case ARTIFACT://45,123
case ARTIFACT_TYPE://45,123
x = 340-289;
y = 180;
w = 44;
@ -4494,7 +4521,7 @@ CRClickPopupInt::~CRClickPopupInt()
CCS->curh->show();
}
CArtPlace::CArtPlace(const CArtifact* Art)
CArtPlace::CArtPlace(const CArtifactInstance* Art)
: marked(false), ourArt(Art)
{
}
@ -4514,7 +4541,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
// If clicked on spellbook, open it only if no artifact is held at the moment.
if(ourArt && !down && previousState && !ourOwner->commonInfo->srcAOH)
{
if(ourArt->id == 0)
if(ourArt->artType->id == 0)
{
CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), ourOwner->curHero, LOCPLINT, LOCPLINT->battleInt);
GH.pushInt(spellWindow);
@ -4523,7 +4550,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
if (!down && previousState)
{
if(ourArt && ourArt->id == 0)
if(ourArt && ourArt->id == 0) //spellbook
return; //this is handled separately
if(!ourOwner->commonInfo->srcAOH) //nothing has been clicked
@ -4544,7 +4571,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
{
if (slotID >= 19) // Backpack destination.
{
const CArtifact * cur = ourOwner->commonInfo->srcArtifact;
const CArtifact * const cur = ourOwner->commonInfo->srcArtifact->artType;
switch(cur->id)
{
@ -4552,30 +4579,20 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
//should not happen, catapult cannot be selected
assert(cur->id != 3);
break;
case 4: case 5: case 6:
{
std::string text = CGI->generaltexth->allTexts[153];
boost::algorithm::replace_first(text, "%s", cur->Name());
LOCPLINT->showInfoDialog(text);
}
case 4: case 5: case 6: //war machines cannot go to backpack
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[153]) % cur->Name()));
break;
default:
ourOwner->commonInfo->destAOH = ourOwner;
ourOwner->commonInfo->destSlotID = slotID;
ourOwner->commonInfo->destArtifact = NULL;
// Correction for backpack position when src lies before dest.
ourOwner->commonInfo->destSlotID +=
(ourOwner->commonInfo->srcAOH == ourOwner
&& ourOwner->commonInfo->srcSlotID >= 19
&& ourOwner->commonInfo->srcSlotID <= slotID);
LOCPLINT->cb->swapArtifacts(
ourOwner->commonInfo->srcAOH->curHero,
ourOwner->commonInfo->srcSlotID,
ourOwner->curHero,
ourOwner->commonInfo->destSlotID);
setMeAsDest();
//
// // Correction for backpack position when src lies before dest.
// int correction = (ourOwner->commonInfo->srcAOH == ourOwner
// && ourOwner->commonInfo->srcSlotID >= 19
// && ourOwner->commonInfo->srcSlotID <= slotID);
// ourOwner->commonInfo->destSlotID += correction;
ourOwner->realizeCurrentTransaction();
break;
}
}
@ -4583,26 +4600,20 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
else if (this->fitsHere(ourOwner->commonInfo->srcArtifact) &&
(!ourArt || ourOwner->curHero->tempOwner == LOCPLINT->playerID))
{
ourOwner->commonInfo->destAOH = ourOwner;
ourOwner->commonInfo->destSlotID = slotID;
ourOwner->commonInfo->destArtifact = ourArt;
setMeAsDest();
// Special case when the dest artifact can't be fit into the src slot.
CGI->arth->unequipArtifact(ourOwner->curHero->artifWorn, slotID);
//CGI->arth->unequipArtifact(ourOwner->curHero->artifWorn, slotID);
const CArtifactsOfHero* srcAOH = ourOwner->commonInfo->srcAOH;
ui16 srcSlotID = ourOwner->commonInfo->srcSlotID;
if (ourArt && srcSlotID < 19 && !ourArt->fitsAt(srcAOH->curHero->artifWorn, srcSlotID))
if (ourArt && srcSlotID < 19 && !ourArt->canBePutAt(ArtifactLocation(srcAOH->curHero, srcSlotID)))
{
// Put dest artifact into owner's backpack.
ourOwner->commonInfo->srcAOH = ourOwner;
ourOwner->commonInfo->srcSlotID = ourOwner->curHero->artifacts.size() + 19;
}
LOCPLINT->cb->swapArtifacts(
srcAOH->curHero,
srcSlotID,
ourOwner->curHero,
slotID);
ourOwner->realizeCurrentTransaction();
}
}
}
@ -4614,39 +4625,36 @@ void CArtPlace::clickRight(tribool down, bool previousState)
{
if (slotID < 19)
{
selectedNo = false;
if(ourOwner->allowedAssembling)
{
std::vector<const CArtifact *> assemblyPossibilities = ourArt->assemblyPossibilities(ourOwner->curHero);
// If the artifact can be assembled, display dialog.
if (ourArt->constituentOf != NULL)
BOOST_FOREACH(const CArtifact *combination, assemblyPossibilities)
{
BOOST_FOREACH(ui32 combination, *ourArt->constituentOf)
LOCPLINT->showArtifactAssemblyDialog(
ourArt->artType->id,
combination->id,
true,
boost::bind(&CCallback::assembleArtifacts, LOCPLINT->cb, ourOwner->curHero, slotID, true, combination->id),
0);
if(assemblyPossibilities.size())
{
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;
}
tlog3 << "More than one possibility of assembling... taking only first\n";
break;
}
}
// Otherwise if the artifact can be diasassembled, display dialog.
if (ourArt->constituents != NULL)
if(ourArt->canBeDisassembled())
{
LOCPLINT->showArtifactAssemblyDialog(
ourArt->id,
ourArt->artType->id,
0,
false,
boost::bind(&CCallback::assembleArtifacts, LOCPLINT->cb, ourOwner->curHero, slotID, false, 0),
boost::bind(&CArtPlace::userSelectedNo, this));
if (!selectedNo)
return;
0);
}
}
}
@ -4656,14 +4664,6 @@ void CArtPlace::clickRight(tribool down, bool previousState)
}
}
/**
* Helper function to catch when a user selects no in an artifact assembly dialog.
*/
void CArtPlace::userSelectedNo ()
{
selectedNo = true;
}
/**
* Selects artifact slot so that the containing artifact looks like it's picked up.
*/
@ -4681,10 +4681,10 @@ void CArtPlace::select ()
ourOwner->commonInfo->srcAOH = ourOwner;
// Temporarily remove artifact from hero.
if (slotID < 19)
CGI->arth->unequipArtifact(ourOwner->curHero->artifWorn, slotID);
else
ourOwner->curHero->artifacts.erase(ourOwner->curHero->artifacts.begin() + (slotID - 19));
// if (slotID < 19)
// CGI->arth->unequipArtifact(ourOwner->curHero->artifWorn, slotID);
// else
// ourOwner->curHero->artifacts.erase(ourOwner->curHero->artifacts.begin() + (slotID - 19));
ourOwner->markPossibleSlots(ourArt);
//ourOwner->curHero->recreateArtBonuses();
@ -4719,7 +4719,7 @@ void CArtPlace::deactivate()
void CArtPlace::showAll(SDL_Surface *to)
{
if (ourArt)
blitAt(graphics->artDefs->ourImages[ourArt->id].bitmap, pos.x, pos.y, to);
blitAt(graphics->artDefs->ourImages[ourArt->artType->id].bitmap, pos.x, pos.y, to);
if(marked && active)
{
@ -4739,7 +4739,7 @@ void CArtPlace::showAll(SDL_Surface *to)
}
}
bool CArtPlace::fitsHere(const CArtifact * art) const
bool CArtPlace::fitsHere(const CArtifactInstance * art) const
{
// You can place 'no artifact' anywhere.
if(!art)
@ -4749,7 +4749,7 @@ bool CArtPlace::fitsHere(const CArtifact * art) const
if (slotID >= 19)
return !CGI->arth->isBigArtifact(art->id);
return art->fitsAt(ourOwner->curHero->artifWorn, slotID);
return art->canBePutAt(ArtifactLocation(ourOwner->curHero, slotID));
}
CArtPlace::~CArtPlace()
@ -4762,6 +4762,17 @@ bool CArtPlace::locked() const
return ourArt && ourArt->id == 145;
}
void CArtPlace::setMeAsDest(bool backpackAsVoid /*= true*/)
{
ourOwner->commonInfo->destAOH = ourOwner;
ourOwner->commonInfo->destSlotID = slotID;
if(slotID >= 19)
ourOwner->commonInfo->destArtifact = NULL;
else
ourOwner->commonInfo->destArtifact = ourArt;
}
void HoverableArea::hover (bool on)
{
if (on)
@ -4900,7 +4911,7 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
if(curHero != hero)
{
//delete curHero;
//hero = curHero = new CGHeroInstance(*hero);
curHero = hero; //was: creating a copy
}
// Compensate backpack pos if an artifact was insertad before it.
@ -4915,11 +4926,11 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
// A swap was made, make the replaced artifact the current selected.
if (commonInfo->destSlotID < 19 && commonInfo->destArtifact)
{
// Temporarily remove artifact from hero.
if (commonInfo->srcSlotID < 19)
CGI->arth->unequipArtifact(curHero->artifWorn, commonInfo->srcSlotID);
else
curHero->artifacts.erase(curHero->artifacts.begin() + (commonInfo->srcSlotID - 19));
// // Temporarily remove artifact from hero.
// if (commonInfo->srcSlotID < 19)
// CGI->arth->unequipArtifact(curHero->artifWorn, commonInfo->srcSlotID);
// else
// curHero->artifacts.erase(curHero->artifacts.begin() + (commonInfo->srcSlotID - 19));
updateParentWindow(); //TODO: evil! but does the thing
@ -4950,7 +4961,8 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
if(hero != curHero)
{
// delete curHero;
// curHero = new CGHeroInstance(*hero);
// curHero = new CGHeroInstance(*hero);
curHero = hero; //was: creating a copy
}
if (curHero->artifacts.size() > 0)
@ -4974,18 +4986,18 @@ void CArtifactsOfHero::dispose()
void CArtifactsOfHero::scrollBackpack(int dir)
{
backpackPos += dir;
if (curHero->artifacts.size() > 0)
if (curHero->artifactsInBackpack.size() > 0)
{
if (backpackPos < 0) // No guarantee of modulus behavior with negative operands.
{
do
{
backpackPos += curHero->artifacts.size();
backpackPos += curHero->artifactsInBackpack.size();
} while (backpackPos < 0);
}
else
{
backpackPos %= curHero->artifacts.size();
backpackPos %= curHero->artifactsInBackpack.size();
}
}
@ -4994,22 +5006,22 @@ void CArtifactsOfHero::scrollBackpack(int dir)
//set new data
size_t s = 0;
for( ; s < curHero->artifacts.size(); ++s)
for( ; s < curHero->artifactsInBackpack.size(); ++s)
{
if (s < curHero->artifacts.size())
if (s < curHero->artifactsInBackpack.size())
{
int slotID = 19 + (s + backpackPos)%curHero->artifacts.size();
const CArtifact *art = curHero->getArt(slotID);
int slotID = 19 + (s + backpackPos)%curHero->artifactsInBackpack.size();
const CArtifactInstance *art = curHero->getArt(slotID);
assert(art);
if(!vstd::contains(toOmmit, art->id))
if(!vstd::contains(toOmmit, art->artType->id))
{
if(s - ommited < 5)
setSlotData(backpack[s-ommited], slotID);
}
else
{
toOmmit -= art->id;
toOmmit -= art->artType->id;
ommited ++;
continue;
}
@ -5019,8 +5031,8 @@ void CArtifactsOfHero::scrollBackpack(int dir)
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());
leftArtRoll->block(curHero->artifactsInBackpack.size() - ommited <= backpack.size());
rightArtRoll->block(curHero->artifactsInBackpack.size() - ommited <= backpack.size());
safeRedraw();
@ -5031,7 +5043,7 @@ void CArtifactsOfHero::scrollBackpack(int dir)
*
* @param art Artifact checked against.
*/
void CArtifactsOfHero::markPossibleSlots (const CArtifact* art)
void CArtifactsOfHero::markPossibleSlots(const CArtifactInstance* art)
{
for (std::set<CArtifactsOfHero *>::iterator it = commonInfo->participants.begin();
it != commonInfo->participants.end();
@ -5075,15 +5087,15 @@ void CArtifactsOfHero::unmarkSlots(bool withRedraw /*= true*/)
void CArtifactsOfHero::setSlotData (CArtPlace* artPlace, int slotID)
{
artPlace->slotID = slotID;
artPlace->ourArt = curHero->getArt(slotID);
artPlace->ourArt = curHero->CArtifactSet::getArt(slotID);
if (artPlace->ourArt)
{
artPlace->text = artPlace->ourArt->Description();
artPlace->text = artPlace->ourArt->artType->Description();
if (artPlace->locked()) // Locks should appear as empty.
artPlace->hoverText = CGI->generaltexth->allTexts[507];
else
artPlace->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % artPlace->ourArt->Name().c_str());
artPlace->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % artPlace->ourArt->artType->Name());
}
else
{
@ -5204,6 +5216,14 @@ void CArtifactsOfHero::safeRedraw()
redraw();
}
void CArtifactsOfHero::realizeCurrentTransaction()
{
assert(commonInfo->srcAOH);
assert(commonInfo->destAOH);
LOCPLINT->cb->swapArtifacts(commonInfo->srcAOH->curHero, commonInfo->srcSlotID,
commonInfo->destAOH->curHero, commonInfo->destSlotID);
}
void CExchangeWindow::close()
{
GH.popIntTotally(this);

View File

@ -68,6 +68,7 @@ class CGGarrison;
class CStackInstance;
class IMarket;
class CTextBox;
class CArtifactInstance;
extern SDL_Color tytulowy, tlo, zwykly ;
@ -582,7 +583,7 @@ class CTradeWindow : public CIntObject //base for markets and altar of sacrifice
public:
enum EType
{
RESOURCE, PLAYER, ARTIFACT, CREATURE, CREATURE_PLACEHOLDER,ARTIFACT_PLACEHOLDER
RESOURCE, PLAYER, ARTIFACT_TYPE, CREATURE, CREATURE_PLACEHOLDER, ARTIFACT_PLACEHOLDER, ARTIFACT_INSTANCE
};
class CTradeableItem : public CIntObject
{
@ -593,6 +594,13 @@ public:
bool left;
std::string subtitle; //empty if default
void *hlp; //holds ptr to artifact instance id type artifact
const CArtifactInstance *getArtInstance() const;
const CArtifact *getArt() const;
void setArtInstance(const CArtifactInstance *art) const;
void setArt(const CArtifact *artT) const;
CFunctionList<void()> callback;
bool downSelection;
@ -905,10 +913,10 @@ public:
int slotID; //0 head 1 shoulders 2 neck 3 right hand 4 left hand 5 torso 6 right ring 7 left ring 8 feet 9 misc. slot 1 10 misc. slot 2 11 misc. slot 3 12 misc. slot 4 13 ballista (war machine 1) 14 ammo cart (war machine 2) 15 first aid tent (war machine 3) 16 catapult 17 spell book 18 misc. slot 5 19+ backpack slots
bool marked;
bool selectedNo;
CArtifactsOfHero * ourOwner;
const CArtifact * ourArt;
CArtPlace(const CArtifact * Art); //c-tor
const CArtifactInstance * ourArt;
CArtPlace(const CArtifactInstance * Art); //c-tor
void clickLeft(tribool down, bool previousState);
void clickRight(tribool down, bool previousState);
void select ();
@ -916,16 +924,18 @@ public:
void activate();
void deactivate();
void showAll(SDL_Surface * to);
bool fitsHere (const CArtifact * art) const; //returns true if given artifact can be placed here
bool fitsHere (const CArtifactInstance * art) const; //returns true if given artifact can be placed here
bool locked () const;
void userSelectedNo ();
void setMeAsDest(bool backpackAsVoid = true);
~CArtPlace(); //d-tor
};
class CArtifactsOfHero : public CIntObject
{
CGHeroInstance * curHero; //local copy of hero on which we operate
const CGHeroInstance * curHero; //local copy of hero on which we operate
std::vector<CArtPlace *> artWorn; // 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
std::vector<CArtPlace *> backpack; //hero's visible backpack (only 5 elements!)
@ -935,12 +945,12 @@ public:
struct SCommonPart
{
std::set<CArtifactsOfHero *> participants; // Needed to mark slots.
const CArtifact * srcArtifact; // Held artifact.
const CArtifactInstance * srcArtifact; // Held artifact.
const CArtifactsOfHero * srcAOH; // Following two needed to uniquely identify the source.
int srcSlotID; //
const CArtifactsOfHero * destAOH; // For swapping. (i.e. changing what is held)
int destSlotID; // Needed to determine what kind of action was last taken in setHero
const CArtifact * destArtifact; // For swapping.
const CArtifactInstance * destArtifact; // For swapping.
void reset();
} * commonInfo; //when we have more than one CArtifactsOfHero in one window with exchange possibility, we use this (eg. in exchange window); to be provided externally
@ -951,12 +961,14 @@ public:
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 realizeCurrentTransaction(); //calls callback with parameters stored in commonInfo
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 markPossibleSlots(const CArtifactInstance* art);
void unmarkSlots(bool withRedraw = true);
void setSlotData (CArtPlace* artPlace, int slotID);
void eraseSlotData (CArtPlace* artPlace, int slotID);

View File

@ -151,6 +151,7 @@ namespace Arts
AFTER_LAST
};
const ui16 BACKPACK_START = 19;
const int LOCK_ID = 145;
}
enum EAlignment

View File

@ -922,13 +922,23 @@ int CArtifactInstance::firstBackpackSlot(const CGHeroInstance *h) const
return -1;
}
bool CArtifactInstance::canBePutAt(const ArtifactLocation &al) const
bool CArtifactInstance::canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved /*= false*/) const
{
if(al.slot >= Arts::BACKPACK_START)
{
if(artType->isBig())
return false;
//TODO backpack limit
return true;
}
if(!vstd::contains(artType->possibleSlots, al.slot))
return false;
//simple artifact -> test if slot is free [combined artifacts have this function overridden]
return al.hero->isPositionFree(al.slot);
if(!assumeDestRemoved) //test if slot is free
return al.hero->isPositionFree(al.slot);
return true;
}
void CArtifactInstance::putAt(CGHeroInstance *h, ui16 slot)
@ -960,4 +970,37 @@ void CArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot)
}
//TODO delete me?
}
bool CArtifactInstance::canBeDisassembled() const
{
return false;
}
std::vector<const CArtifact *> CArtifactInstance::assemblyPossibilities(const CGHeroInstance *h) const
{
std::vector<const CArtifact *> ret;
if(!artType->constituentOf)
return ret;
BOOST_FOREACH(ui32 combination, *artType->constituentOf)
{
if (artType->canBeAssembledTo(h->artifWorn, combination))
{
ret.push_back(VLC->arth->artifacts[combination]);
}
}
return ret;
}
bool CCombinedArtifactInstance::canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved /*= false*/) const
{
return CArtifactInstance::canBePutAt(al, assumeDestRemoved);
//TODO look for place for constituents
}
bool CCombinedArtifactInstance::canBeDisassembled() const
{
return true;
}

View File

@ -75,7 +75,11 @@ public:
int firstAvailableSlot(const CGHeroInstance *h) const;
int firstBackpackSlot(const CGHeroInstance *h) const;
bool canBePutAt(const ArtifactLocation &al) const;
virtual bool canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved = false) const;
virtual bool canBeDisassembled() const;
std::vector<const CArtifact *> assemblyPossibilities(const CGHeroInstance *h) const;
void putAt(CGHeroInstance *h, ui16 slot);
void removeFrom(CGHeroInstance *h, ui16 slot);
@ -92,7 +96,8 @@ public:
class DLL_EXPORT CCombinedArtifactInstance : public CArtifactInstance
{
public:
bool canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved = false) const OVERRIDE;
bool canBeDisassembled() const OVERRIDE;
};
class DLL_EXPORT IModableArt : public CArtifact //artifact which can have different properties, such as scroll or banner

View File

@ -144,6 +144,11 @@ bool CCreature::valid() const
return this == VLC->creh->creatures[idNumber];
}
std::string CCreature::nodeName() const
{
return "Type of creature " + namePl;
}
int readNumber(int & befi, int & i, int andame, std::string & buf) //helper function for void CCreatureHandler::loadCreatures() and loadUnitAnimInfo()
{
befi=i;

View File

@ -64,6 +64,7 @@ public:
bool valid() const;
void addBonus(int val, int type, int subtype = -1);
std::string nodeName() const OVERRIDE;
//void getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const;
template<typename RanGen>

View File

@ -663,7 +663,7 @@ int CGHeroInstance::getPrimSkillLevel(int id) const
ui8 CGHeroInstance::getSecSkillLevel(SecondarySkill skill) const
{
for(size_t i=0; i < secSkills.size(); ++i)
if(secSkills[i].first==ID)
if(secSkills[i].first == skill)
return secSkills[i].second;
return 0;
}
@ -729,25 +729,6 @@ int CGHeroInstance::maxMovePoints(bool onLand) const
return int(base + base*modifier) + bonus;
}
const CArtifact* CGHeroInstance::getArtAtPos(ui16 pos) const
{
if(pos<19)
if(vstd::contains(artifWorn,pos))
return artifWorn.find(pos)->second;
else
return NULL;
else
if(pos-19 < artifacts.size())
return artifacts[pos-19];
else
return NULL;
}
const CArtifact * CGHeroInstance::getArt(int pos) const
{
return getArtAtPos(pos);
}
// int CGHeroInstance::getSpellSecLevel(int spell) const
// {
// int bestslvl = 0;
@ -1418,14 +1399,6 @@ si32 CGHeroInstance::manaRegain() const
return 1 + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 8) + valOfBonuses(Bonus::MANA_REGENERATION); //1 + Mysticism level
}
si32 CGHeroInstance::getArtPos(int aid) const
{
for(std::map<ui16, const CArtifact*>::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++)
if(i->second->id == aid)
return i->first;
return -1;
}
/**
* Places an artifact in hero's backpack. If it's a big artifact equips it
* or discards it if it cannot be equipped.
@ -1451,18 +1424,6 @@ void CGHeroInstance::giveArtifact (ui32 aid) //use only for fixed artifacts
}
}
bool CGHeroInstance::hasArt( ui32 aid ) const
{
for(std::vector<const CArtifact*>::const_iterator i = artifacts.begin(); i != artifacts.end(); i++)
if((*i)->id == aid)
return true;
for(std::map<ui16, const CArtifact*>::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++)
if(i->second->id == aid)
return true;
return false;
}
int CGHeroInstance::getBoatType() const
{
int alignment = type->heroType / 6;
@ -4389,7 +4350,7 @@ void CGSeerHut::finishQuest(const CGHeroInstance * h, ui32 accept) const
case CQuest::MISSION_ART:
for (std::vector<ui16>::const_iterator it = m5arts.begin(); it != m5arts.end(); ++it)
{
cb->removeArtifact(VLC->arth->artifacts[*it], h->id);
cb->removeArtifact(ArtifactLocation(h, h->getArtPos(*it, false)));
}
break;
case CQuest::MISSION_ARMY:
@ -6938,6 +6899,17 @@ const CArtifactInstance* CArtifactSet::getArt(ui16 pos) const
return NULL;
}
// if(pos<19)
// if(vstd::contains(artifWorn,pos))
// return artifWorn.find(pos)->second;
// else
// return NULL;
// else
// if(pos-19 < artifacts.size())
// return artifacts[pos-19];
// else
// return NULL;
si32 CArtifactSet::getArtPos(int aid, bool onlyWorn /*= true*/) const
{
for(std::map<ui16, ArtSlotInfo>::const_iterator i = artifactsWorn.begin(); i != artifactsWorn.end(); i++)
@ -6954,7 +6926,20 @@ si32 CArtifactSet::getArtPos(int aid, bool onlyWorn /*= true*/) const
return -1;
}
bool CArtifactSet::hasArt(ui32 aid, bool onlyWorn /*= true*/) const
si32 CArtifactSet::getArtPos(const CArtifactInstance *art) const
{
for(std::map<ui16, ArtSlotInfo>::const_iterator i = artifactsWorn.begin(); i != artifactsWorn.end(); i++)
if(i->second.artifact == art)
return i->first;
for(int i = 0; i < artifactsInBackpack.size(); i++)
if(artifactsInBackpack[i].artifact == art)
return Arts::BACKPACK_START + i;
return -1;
}
bool CArtifactSet::hasArt(ui32 aid, bool onlyWorn /*= false*/) const
{
return getArtPos(aid, onlyWorn) != -1;
}
@ -6981,4 +6966,20 @@ bool CArtifactSet::isPositionFree(ui16 pos) const
return !s->artifact && !s->locked;
return true; //no slot means not used
}
si32 CArtifactSet::getArtTypeId(ui16 pos) const
{
const CArtifactInstance * const a = getArt(pos);
if(!a)
{
tlog2 << (dynamic_cast<const CGHeroInstance*>(this))->name << " has no artifact at " << pos << " (getArtTypeId)\n";
return -1;
}
return a->artType->id;
}
CArtifactSet::~CArtifactSet()
{
}

View File

@ -267,8 +267,12 @@ public:
const ArtSlotInfo *getSlot(ui16 pos) const;
const CArtifactInstance* getArt(ui16 pos) const; //NULL - no artifact
si32 getArtPos(int aid, bool onlyWorn = true) const; //looks for equipped artifact with given ID and returns its slot ID or -1 if none(if more than one such artifact lower ID is returned)
bool hasArt(ui32 aid, bool onlyWorn = true) const; //checks if hero possess artifact of given id (either in backack or worn)
si32 getArtPos(const CArtifactInstance *art) const;
bool hasArt(ui32 aid, bool onlyWorn = false) const; //checks if hero possess artifact of given id (either in backack or worn)
bool isPositionFree(ui16 pos) const;
si32 getArtTypeId(ui16 pos) const;
virtual ~CArtifactSet();
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -384,10 +388,10 @@ public:
int maxMovePoints(bool onLand) const;
const CArtifact* getArtAtPos(ui16 pos) const; //NULL - no artifact
const CArtifact * getArt(int pos) const;
si32 getArtPos(int aid) const; //looks for equipped artifact with given ID and returns its slot ID or -1 if none(if more than one such artifact lower ID is returned)
bool hasArt(ui32 aid) const; //checks if hero possess artifact of given id (either in backack or worn)
// const CArtifact* getArtAtPos(ui16 pos) const; //NULL - no artifact
// const CArtifact * getArt(int pos) const;
// si32 getArtPos(int aid) const; //looks for equipped artifact with given ID and returns its slot ID or -1 if none(if more than one such artifact lower ID is returned)
// bool hasArt(ui32 aid) const; //checks if hero possess artifact of given id (either in backack or worn)
//int getSpellSecLevel(int spell) const; //returns level of secondary ability (fire, water, earth, air magic) known to this hero and applicable to given spell; -1 if error
static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest

View File

@ -112,7 +112,7 @@ public:
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 giveNewArtifact(int hid, int position)=0;
virtual bool removeArtifact(const CArtifact* art, int hid) = 0;
//virtual bool removeArtifact(const CArtifact* art, 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

@ -604,8 +604,17 @@ DLL_EXPORT const CStackInstance * StackLocation::getStack()
DLL_EXPORT const CArtifactInstance *ArtifactLocation::getArt() const
{
const ArtSlotInfo *s = getSlot();
if(s && !s->locked && s->artifact)
return s->artifact;
if(s && s->artifact)
{
if(!s->locked)
return s->artifact;
else
{
tlog3 << "ArtifactLocation::getArt: That location is locked!\n";
return NULL;
}
}
return NULL;
}
DLL_EXPORT CArtifactInstance *ArtifactLocation::getArt()

View File

@ -207,7 +207,7 @@ void LibClasses::init()
spellh->loadSpells();
tlog0<<"\tSpell handler: "<<pomtime.getDif()<<std::endl;
IS_AI_ENABLED = true;
IS_AI_ENABLED = false;
}
void LibClasses::clear()

View File

@ -1610,43 +1610,46 @@ void CGameHandler::stopHeroVisitCastle(int obj, int heroID)
sendAndApply(&vc);
}
bool CGameHandler::removeArtifact(const CArtifact* art, int hid)
{
const CGHeroInstance* h = getHero(hid);
SetHeroArtifacts sha;
sha.hid = hid;
sha.artifacts = h->artifacts;
sha.artifWorn = h->artifWorn;
std::vector<const CArtifact*>::iterator it;
if ((it = std::find(sha.artifacts.begin(), sha.artifacts.end(), art)) != sha.artifacts.end()) //it is in backpack
sha.artifacts.erase(it);
else //worn
{
std::map<ui16, const CArtifact*>::iterator itr;
for (itr = sha.artifWorn.begin(); itr != sha.artifWorn.end(); ++itr)
{
if (itr->second == art)
{
VLC->arth->unequipArtifact(sha.artifWorn, itr->first);
break;
}
}
if(itr == sha.artifWorn.end())
{
tlog2 << "Cannot find artifact to remove!\n";
return false;
}
}
sendAndApply(&sha);
return true;
}
// bool CGameHandler::removeArtifact(const CArtifact* art, int hid)
// {
// const CGHeroInstance* h = getHero(hid);
//
// SetHeroArtifacts sha;
// sha.hid = hid;
// sha.artifacts = h->artifacts;
// sha.artifWorn = h->artifWorn;
//
// std::vector<const CArtifact*>::iterator it;
// if ((it = std::find(sha.artifacts.begin(), sha.artifacts.end(), art)) != sha.artifacts.end()) //it is in backpack
// sha.artifacts.erase(it);
// else //worn
// {
// std::map<ui16, const CArtifact*>::iterator itr;
// for (itr = sha.artifWorn.begin(); itr != sha.artifWorn.end(); ++itr)
// {
// if (itr->second == art)
// {
// VLC->arth->unequipArtifact(sha.artifWorn, itr->first);
// break;
// }
// }
//
// if(itr == sha.artifWorn.end())
// {
// tlog2 << "Cannot find artifact to remove!\n";
// return false;
// }
// }
// sendAndApply(&sha);
// return true;
// }
void CGameHandler::removeArtifact(const ArtifactLocation &al)
{
assert(al.getArt());
EraseArtifact ea;
ea.al = al;
sendAndApply(&ea);
}
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
{
@ -1656,10 +1659,10 @@ void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstanc
if(army2->tempOwner < PLAYER_LIMIT)
states.setFlag(army2->tempOwner,&PlayerStatus::engagedIntoBattle,true);
const CArmedInstance *armies[2];
static const CArmedInstance *armies[2];
armies[0] = army1;
armies[1] = army2;
const CGHeroInstance*heroes[2];
static const CGHeroInstance*heroes[2];
heroes[0] = hero1;
heroes[1] = hero2;
@ -2098,7 +2101,8 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
return false;
}
removeArtifact(VLC->arth->artifacts[2], t->visitingHero->id);
//remove grail
removeArtifact(ArtifactLocation(t->visitingHero, t->visitingHero->getArtPos(2, false)));
}
NewStructures ns;
@ -2450,103 +2454,97 @@ bool CGameHandler::garrisonSwap( si32 tid )
}
// With the amount of changes done to the function, it's more like transferArtifacts.
bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot)
// Function moves artifact from src to dst. If dst is not a backpack and is already occupied, old dst art goes to backpack and is replaced.
bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot)
{
CGHeroInstance *srcHero = gs->getHero(srcHeroID);
CGHeroInstance *destHero = gs->getHero(destHeroID);
ArtifactLocation src(srcHero, srcSlot), dst(destHero, destSlot);
// Make sure exchange is even possible between the two heroes.
if (distance(srcHero->pos,destHero->pos) > 1.5 )
return false;
if(!isAllowedExchange(srcHeroID, destHeroID))
COMPLAIN_RET("That heroes cannot make any exchange!");
const CArtifact *srcArtifact = srcHero->getArt(srcSlot);
const CArtifact *destArtifact = destHero->getArt(destSlot);
const CArtifactInstance *srcArtifact = src.getArt();
const CArtifactInstance *destArtifact = dst.getArt();
if (srcArtifact == NULL)
{
complain("No artifact to swap!");
return false;
}
COMPLAIN_RET("No artifact to move!");
if (destArtifact && srcHero->tempOwner != destHero->tempOwner)
{
complain("Can't take artifact from hero of another player!");
return false;
}
COMPLAIN_RET("Can't touch artifact on hero of another player!");
SetHeroArtifacts sha;
sha.hid = srcHeroID;
sha.artifacts = srcHero->artifacts;
sha.artifWorn = srcHero->artifWorn;
// Combinational artifacts needs to be removed first so they don't get denied movement because of their own locks.
if (srcHeroID == destHeroID && srcSlot < 19 && destSlot < 19)
{
sha.setArtAtPos(srcSlot, NULL);
if (!vstd::contains(sha.artifWorn, destSlot))
destArtifact = NULL;
}
// // Combinational artifacts needs to be removed first so they don't get denied movement because of their own locks.
// if (srcHeroID == destHeroID && srcSlot < 19 && destSlot < 19)
// {
// sha.setArtAtPos(srcSlot, NULL);
// if (!vstd::contains(sha.artifWorn, destSlot))
// destArtifact = NULL;
// }
// Check if src/dest slots are appropriate for the artifacts exchanged.
// Moving to the backpack is always allowed.
if ((!srcArtifact || destSlot < 19)
&& (srcArtifact && !srcArtifact->fitsAt(srcHeroID == destHeroID ? sha.artifWorn : destHero->artifWorn, destSlot)))
if ((!srcArtifact || destSlot < Arts::BACKPACK_START)
&& srcArtifact && !srcArtifact->canBePutAt(dst))
COMPLAIN_RET("Cannot swap artifacts!");
if ((srcArtifact && srcArtifact->artType->id == Arts::LOCK_ID) || (destArtifact && destArtifact->artType->id == Arts::LOCK_ID))
COMPLAIN_RET("Cannot move artifact locks.");
if (destSlot >= Arts::BACKPACK_START && srcArtifact->artType->isBig())
COMPLAIN_RET("Cannot put big artifacts in backpack!");
if (srcSlot == Arts::MACH4 || destSlot == Arts::MACH4)
COMPLAIN_RET("Cannot move catapult!");
//moving art to backpack is always allowed (we've ruled out exceptions)
if(destSlot >= Arts::BACKPACK_START)
{
complain("Cannot swap artifacts!");
return false;
moveArtifact(src, dst);
}
else //moving art to another slot
{
if(destArtifact) //old artifact must be removed first
{
moveArtifact(dst, ArtifactLocation(destHero, destHero->artifactsInBackpack.size()-1));
}
moveArtifact(src, dst);
}
if ((srcArtifact && srcArtifact->id == 145) || (destArtifact && destArtifact->id == 145))
{
complain("Cannot move artifact locks.");
return false;
}
if (destSlot >= 19 && srcArtifact->isBig())
{
complain("Cannot put big artifacts in backpack!");
return false;
}
if (srcSlot == 16 || destSlot == 16)
{
complain("Cannot move catapult!");
return false;
}
// If dest does not fit in src, put it in dest's backpack instead.
if (srcHeroID == destHeroID) // To avoid stumbling on own locks, remove artifact first.
sha.setArtAtPos(destSlot, NULL);
const bool destFits = !destArtifact || srcSlot >= 19 || destSlot >= 19 || destArtifact->fitsAt(sha.artifWorn, srcSlot);
if (srcHeroID == destHeroID && destArtifact)
sha.setArtAtPos(destSlot, destArtifact);
sha.setArtAtPos(srcSlot, NULL);
if (destSlot < 19 && (destArtifact || srcSlot < 19) && destFits)
sha.setArtAtPos(srcSlot, destArtifact ? destArtifact : NULL);
// Internal hero artifact arrangement.
if(srcHero == destHero)
{
// Correction for destination from removing source artifact in backpack.
if (srcSlot >= 19 && destSlot >= 19 && srcSlot < destSlot)
destSlot--;
sha.setArtAtPos(destSlot, srcHero->getArtAtPos(srcSlot));
}
if (srcHeroID != destHeroID)
{
// Exchange between two different heroes.
SetHeroArtifacts sha2;
sha2.hid = destHeroID;
sha2.artifacts = destHero->artifacts;
sha2.artifWorn = destHero->artifWorn;
sha2.setArtAtPos(destSlot, srcArtifact ? srcArtifact : NULL);
if (!destFits)
sha2.setArtAtPos(sha2.artifacts.size() + 19, destHero->getArtAtPos(destSlot));
sendAndApply(&sha2);
}
sendAndApply(&sha);
//
// // If dest does not fit in src, put it in dest's backpack instead.
// if (srcHeroID == destHeroID) // To avoid stumbling on own locks, remove artifact first.
// sha.setArtAtPos(destSlot, NULL);
// const bool destFits = !destArtifact || srcSlot >= 19 || destSlot >= 19 || destArtifact->fitsAt(sha.artifWorn, srcSlot);
// if (srcHeroID == destHeroID && destArtifact)
// sha.setArtAtPos(destSlot, destArtifact);
//
// sha.setArtAtPos(srcSlot, NULL);
// if (destSlot < 19 && (destArtifact || srcSlot < 19) && destFits)
// sha.setArtAtPos(srcSlot, destArtifact ? destArtifact : NULL);
//
// // Internal hero artifact arrangement.
// if(srcHero == destHero)
// {
// // Correction for destination from removing source artifact in backpack.
// if (srcSlot >= 19 && destSlot >= 19 && srcSlot < destSlot)
// destSlot--;
//
// sha.setArtAtPos(destSlot, srcHero->getArtAtPos(srcSlot));
// }
// if (srcHeroID != destHeroID)
// {
// // Exchange between two different heroes.
// SetHeroArtifacts sha2;
// sha2.hid = destHeroID;
// sha2.artifacts = destHero->artifacts;
// sha2.artifWorn = destHero->artifWorn;
// sha2.setArtAtPos(destSlot, srcArtifact ? srcArtifact : NULL);
// if (!destFits)
// sha2.setArtAtPos(sha2.artifacts.size() + 19, destHero->getArtAtPos(destSlot));
// sendAndApply(&sha2);
// }
// sendAndApply(&sha);
return true;
}
@ -2566,8 +2564,8 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem
}
CGHeroInstance *hero = gs->getHero(heroID);
const CArtifact *destArtifact = hero->getArt(artifactSlot);
const CArtifactInstance *destArtifact = hero->getArt(artifactSlot);
/*
SetHeroArtifacts sha;
sha.hid = heroID;
sha.artifacts = hero->artifacts;
@ -2678,7 +2676,8 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem
sendAndApply(&sha);
return true;
return true;*/
return false;
}
bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
@ -2711,7 +2710,7 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
return false;
}
giveResource(hero->getOwner(),6,-price);
giveResource(hero->getOwner(),Res::GOLD,-price);
giveHeroNewArtifact(hero, VLC->arth->artifacts[aid], 9+aid);
return true;
}
@ -4562,13 +4561,19 @@ bool CGameHandler::sacrificeCreatures(const IMarket *market, const CGHeroInstanc
return true;
}
bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, const CArtifact* art)
bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, int slot)
{
if(!removeArtifact(art, hero->id))
ArtifactLocation al(hero, slot);
const CArtifactInstance *a = al.getArt();
if(!a)
COMPLAIN_RET("Cannot find artifact to sacrifice!");
int dmp, expToGive;
m->getOffer(art->id, 0, dmp, expToGive, ARTIFACT_EXP);
m->getOffer(hero->getArtTypeId(slot), 0, dmp, expToGive, ARTIFACT_EXP);
removeArtifact(al);
changePrimSkill(hero->id, 4, expToGive);
return true;
}
@ -4977,7 +4982,10 @@ void CGameHandler::putArtifact(const ArtifactLocation &al, const CArtifactInstan
void CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2)
{
MoveArtifact ma;
ma.src = al1;
ma.dst = al2;
sendAndApply(&ma);
}
void CGameHandler::giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, int pos)
@ -4987,7 +4995,7 @@ void CGameHandler::giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact
NewArtifact na;
na.art = a;
sendAndApply(&na);
sendAndApply(&na); // -> updates a!!!
giveHeroArtifact(h, a, pos);
}

View File

@ -168,7 +168,7 @@ public:
void showCompInfo(ShowInInfobox * comp) OVERRIDE;
void heroVisitCastle(int obj, int heroID) OVERRIDE;
void stopHeroVisitCastle(int obj, int heroID) OVERRIDE;
bool removeArtifact(const CArtifact* art, int hid) OVERRIDE;
//bool removeArtifact(const CArtifact* art, int hid) OVERRIDE;
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) OVERRIDE; //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) OVERRIDE; //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) OVERRIDE; //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) OVERRIDE; //for hero<=>neutral army
@ -212,7 +212,7 @@ public:
bool buyArtifact( ui32 hid, si32 aid ); //for blacksmith and mage guild only -> buying for gold in common buildings
bool buyArtifact( const IMarket *m, const CGHeroInstance *h, int rid, int aid); //for artifact merchant and black market -> buying for any resource in special building / advobject
bool buySecSkill( const IMarket *m, const CGHeroInstance *h, int skill);
bool swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot);
bool moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot);
bool garrisonSwap(si32 tid);
bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID );
bool recruitCreatures(si32 objid, ui32 crid, ui32 cram, si32 level);
@ -252,7 +252,7 @@ public:
void run(bool resume);
void newTurn();
void handleAfterAttackCasting( const BattleAttack & bat );
bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, const CArtifact* art);
bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, int slot);
friend class CVCMIServer;
friend class CScriptCallback;
};

View File

@ -112,7 +112,7 @@ bool GarrisonHeroSwap::applyGh( CGameHandler *gh )
bool ExchangeArtifacts::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(hid1);//second hero can be ally
return gh->swapArtifacts(hid1,hid2,slot1,slot2);
return gh->moveArtifact(hid1,hid2,slot1,slot2);
}
bool AssembleArtifacts::applyGh( CGameHandler *gh )
@ -170,7 +170,7 @@ bool TradeOnMarketplace::applyGh( CGameHandler *gh )
case CREATURE_EXP:
return gh->sacrificeCreatures(m, hero, r1, val);
case ARTIFACT_EXP:
return gh->sacrificeArtifact(m, hero, hero->getArtAtPos(r1));
return gh->sacrificeArtifact(m, hero, r1);
default:
COMPLAIN_AND_RETURN("Unknown exchange mode!");
}