1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Partially functional artifact screen.

[TBD compound artifacts, backpack arranging, "live" modifying values, many details]
This commit is contained in:
Michał W. Urbańczyk 2011-01-06 20:00:19 +00:00
parent ebb9c84da9
commit 401b364ad7
16 changed files with 388 additions and 225 deletions

View File

@ -52,6 +52,7 @@ class CSaveFile;
typedef si32 TQuantity;
template <typename Serializer> class CISer;
template <typename Serializer> class COSer;
struct ArtifactLocation;
class CBattleGameInterface
{
@ -100,7 +101,9 @@ public:
//virtual void garrisonChanged(const CGObjectInstance * obj){};
//artifacts operations
virtual void heroArtifactSetChanged(const CGHeroInstance*hero){};
virtual void artifactPut(const ArtifactLocation &al){};
virtual void artifactRemoved(const ArtifactLocation &al){};
virtual void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst){};
virtual void heroCreated(const CGHeroInstance*){};
virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)=0; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id

View File

@ -1189,7 +1189,6 @@ townList(ADVOPT.tlistSize,ADVOPT.tlistX,ADVOPT.tlistY,ADVOPT.tlistAU,ADVOPT.tlis
//townList.init();
//townList.genList();
heroWindow = NULL;
for (int g=0; g<ADVOPT.gemG.size(); ++g)
{
@ -1203,7 +1202,6 @@ townList(ADVOPT.tlistSize,ADVOPT.tlistX,ADVOPT.tlistY,ADVOPT.tlistAU,ADVOPT.tlis
CAdvMapInt::~CAdvMapInt()
{
SDL_FreeSurface(bg);
delete heroWindow;
for(int i=0; i<gems.size(); i++)
delete gems[i];

View File

@ -177,8 +177,6 @@ public:
const CSpell *spellBeingCasted; //NULL if none
CHeroWindow * heroWindow;
const CArmedInstance *selection; //currently selected town/hero
//functions bound to buttons

View File

@ -47,10 +47,9 @@ void CHeroSwitcher::clickLeft(tribool down, bool previousState)
{
if(!down)
{
getOwner()->deactivate();
const CGHeroInstance * buf = LOCPLINT->getWHero(id);
getOwner()->setHero(buf);
getOwner()->activate();
GH.popIntTotally(getOwner());
GH.pushInt(new CHeroWindow(buf));
}
}
@ -61,7 +60,7 @@ CHeroWindow * CHeroSwitcher::getOwner()
CHeroSwitcher::CHeroSwitcher(int serial)
{
pos = Rect(677, 95 + serial * 54, 48, 32) + pos;
pos = Rect(612, 87 + serial * 54, 48, 32) + pos;
id = serial;
used = LCLICK;
}
@ -69,9 +68,8 @@ CHeroSwitcher::CHeroSwitcher(int serial)
CHeroWindow::CHeroWindow(const CGHeroInstance *hero)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
artifs = NULL;
garr = NULL;
curHero = NULL;
curHero = hero;
player = hero->tempOwner;
background = new CPicture("HeroScr4.BMP");
@ -118,12 +116,11 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero)
specArea = new LRClickableAreaWText(Rect(18, 180, 136, 42), CGI->generaltexth->heroscrn[27]);
expArea = new LRClickableAreaWText(Rect(18, 228, 136, 42), CGI->generaltexth->heroscrn[9]);
morale = new MoraleLuckBox(true, Rect(175,179,53,45));
luck = new MoraleLuckBox(false, Rect(233,179,53,45));
spellPointsArea = new LRClickableAreaWText(Rect(162,228, 136, 42), CGI->generaltexth->heroscrn[22]);
for(int i=0; i<SKILL_PER_HERO; ++i)
for(int i = 0; i < std::min(hero->secSkills.size(), 8u); ++i)
{
Rect r = Rect(i%2 == 0 ? 18 : 162, 276 + 48 * (i/2), 136, 42);
secSkillAreas.push_back(new LRClickableAreaWTextComp(r, SComponent::secskill));
@ -141,7 +138,7 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero)
new CPicture(graphics->pskillsm->ourImages[4].bitmap, 20, 230, false);
new CPicture(graphics->pskillsm->ourImages[3].bitmap, 162, 230, false);
setHero(hero);
update(hero);
}
CHeroWindow::~CHeroWindow()
@ -154,21 +151,16 @@ CHeroWindow::~CHeroWindow()
//artifs->dispose();
}
void CHeroWindow::setHero(const CGHeroInstance *hero)
void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= false*/)
{
if(!hero) //something strange... no hero? it shouldn't happen
{
tlog1 << "Set NULL hero? no way...\n";
return;
}
if(hero == curHero)
{
tlog3 << "Spurious call to CHeroWindow::setHero\n";
return;
}
assert(hero == curHero);
assert(hero->tempOwner == LOCPLINT->playerID); //for now we won't show hero windows for non-our heroes
curHero = hero;
specArea->text = CGI->generaltexth->hTxts[hero->subID].longBonus;
@ -179,21 +171,29 @@ void CHeroWindow::setHero(const CGHeroInstance *hero)
portraitArea->hoverText = boost::str(boost::format(CGI->generaltexth->allTexts[15]) % curHero->name % curHero->type->heroClass->name);
portraitArea->text = hero->getBiography();
{
delete garr;
OBJ_CONSTRUCTION_CAPTURING_ALL;
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), 604, 527, "hsbtns9.def", false, NULL, false); //deleted by garrison destructor
}
boost::algorithm::replace_first(split->hoverTexts[0],"%s",CGI->generaltexth->allTexts[43]);
}
//delete garr;
OBJ_CONSTRUCTION_CAPTURING_ALL;
if(!garr)
{
garr = new CGarrisonInt(15, 485, 8, Point(), background->bg, Point(15,485), curHero);
garr->addSplitBtn(split);
}
if(!artSets.size())
{
CArtifactsOfHero *arts = new CArtifactsOfHero(Point(-65, -8), true);
arts->setHero(hero);
artSets.push_back(arts);
}
}
//primary skills support
for(size_t g=0; g<primSkillAreas.size(); ++g)
@ -202,7 +202,7 @@ void CHeroWindow::setHero(const CGHeroInstance *hero)
}
//secondary skills support
for(size_t g=0; g<std::min(secSkillAreas.size(),hero->secSkills.size()); ++g)
for(size_t g=0; g< secSkillAreas.size(); ++g)
{
int skill = hero->secSkills[g].first,
level = hero->getSecSkillLevel(static_cast<CGHeroInstance::SecondarySkill>(hero->secSkills[g].first));
@ -212,7 +212,6 @@ void CHeroWindow::setHero(const CGHeroInstance *hero)
secSkillAreas[g]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[21]) % CGI->generaltexth->levels[level-1] % CGI->generaltexth->skillName[skill]);
}
//printing experience - original format does not support ui64
expArea->text = CGI->generaltexth->allTexts[2];
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(hero->level));
@ -252,11 +251,13 @@ void CHeroWindow::setHero(const CGHeroInstance *hero)
morale->set(hero);
luck->set(hero);
if(redrawNeeded)
redraw();
}
void CHeroWindow::quit()
{
adventureInt->heroWindow = NULL;
GH.popIntTotally(this);
}
@ -322,10 +323,6 @@ void CHeroWindow::showAll(SDL_Surface * to)
printAtMiddleLoc(primarySkill.str(), 53 + 70 * m, 166, FONT_SMALL, zwykly, to);
}
//morale and luck printing
blitAtLoc(graphics->luck42->ourImages[curHero->LuckVal()+3].bitmap, 239, 182, to);
blitAtLoc(graphics->morale42->ourImages[curHero->MoraleVal()+3].bitmap, 181, 182, to);
blitAtLoc(flags->ourImages[player].bitmap, 606, 8, to);
//hero list blitting

View File

@ -38,7 +38,7 @@ public:
class CHeroWindow: public CWindowWithGarrison
class CHeroWindow: public CWindowWithGarrison, public CWindowWithArtifacts
{
enum ELabel {};
std::map<ELabel, CLabel*> labels;
@ -52,8 +52,6 @@ class CHeroWindow: public CWindowWithGarrison
//AdventureMapButton * gar4button; //splitting
std::vector<CHeroSwitcher *> heroListMi; //new better list of heroes
CArtifactsOfHero * artifs;
//clickable areas
LRClickableAreaWText * portraitArea;
std::vector<LRClickableAreaWTextComp *> primSkillAreas;
@ -71,7 +69,8 @@ public:
int player;
CHeroWindow(const CGHeroInstance *hero); //c-tor
~CHeroWindow(); //d-tor
void setHero(const CGHeroInstance * hero); //sets main displayed hero
void update(const CGHeroInstance * hero, bool redrawNeeded = false); //sets main displayed hero
void showAll(SDL_Surface * to); //shows and activates adv. map interface
// void redrawCurBack(); //redraws curBAck from scratch
void quit(); //stops displaying hero window and disposes

View File

@ -46,6 +46,7 @@
#include <sstream>
#include <boost/filesystem.hpp>
#include "../StartInfo.h"
#include <boost/foreach.hpp>
#ifdef min
#undef min
@ -508,7 +509,7 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
{
if((*i)->type & IShowActivable::WITH_GARRISON)
{
CGarrisonHolder *cgh = static_cast<CGarrisonHolder*>(*i);
CGarrisonHolder *cgh = dynamic_cast<CGarrisonHolder*>(*i);
cgh->updateGarrisons();
}
else if(CTradeWindow *cmw = dynamic_cast<CTradeWindow*>(*i))
@ -954,11 +955,9 @@ void CPlayerInterface::tileHidden(const std::set<int3> &pos)
void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
adventureInt->heroWindow = new CHeroWindow(hero);
adventureInt->heroWindow->setHero(hero);
GH.pushInt(adventureInt->heroWindow);
GH.pushInt(new CHeroWindow(hero));
}
/*
void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
@ -997,7 +996,7 @@ void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
}
updateInfo(hero);
}
}*/
void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town )
{
@ -2121,21 +2120,25 @@ void CPlayerInterface::sendCustomEvent( int code )
void CPlayerInterface::stackChagedCount(const StackLocation &location, const TQuantity &change, bool isAbsolute)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
garrisonChanged(location.army);
}
void CPlayerInterface::stackChangedType(const StackLocation &location, const CCreature &newType)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
garrisonChanged(location.army);
}
void CPlayerInterface::stacksErased(const StackLocation &location)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
garrisonChanged(location.army);
}
void CPlayerInterface::stacksSwapped(const StackLocation &loc1, const StackLocation &loc2)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
garrisonChanged(loc1.army);
if(loc2.army != loc1.army)
garrisonChanged(loc2.army);
@ -2143,16 +2146,37 @@ void CPlayerInterface::stacksSwapped(const StackLocation &loc1, const StackLocat
void CPlayerInterface::newStackInserted(const StackLocation &location, const CStackInstance &stack)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
garrisonChanged(location.army);
}
void CPlayerInterface::stacksRebalanced(const StackLocation &src, const StackLocation &dst, TQuantity count)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
garrisonChanged(src.army);
if(dst.army != src.army)
garrisonChanged(dst.army);
}
void CPlayerInterface::artifactPut(const ArtifactLocation &al)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
}
void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
}
void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
BOOST_FOREACH(IShowActivable *isa, GH.listInt)
if(isa->type & IShowActivable::WITH_ARTIFACTS)
BOOST_FOREACH(CArtifactsOfHero *aoh, (dynamic_cast<CWindowWithArtifacts*>(isa))->artSets)
aoh->artifactMoved(src, dst);
}
CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting()
{
spellbookLastPageBattle = spellbokLastPageAdvmap = 0;

View File

@ -166,7 +166,11 @@ public:
void stacksSwapped(const StackLocation &loc1, const StackLocation &loc2) OVERRIDE;
void newStackInserted(const StackLocation &location, const CStackInstance &stack) OVERRIDE; //new stack inserted at given (previously empty position)
void stacksRebalanced(const StackLocation &src, const StackLocation &dst, TQuantity count) OVERRIDE; //moves creatures from src stack to dst slot, may be used for merging/splittint/moving stacks
void heroArtifactSetChanged(const CGHeroInstance* hero) OVERRIDE;
void artifactPut(const ArtifactLocation &al);
void artifactRemoved(const ArtifactLocation &al);
void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst);
void heroCreated(const CGHeroInstance* hero) OVERRIDE;
void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback) OVERRIDE;
void heroInGarrisonChange(const CGTownInstance *town) OVERRIDE;

View File

@ -1024,3 +1024,8 @@ Rect Rect::around(const Rect &r, int width /*= 1*/) /*creates rect around anothe
{
return Rect(r.x - width, r.y - width, r.w + width * 2, r.h + width * 2);
}
Rect Rect::centerIn(const Rect &r)
{
return Rect(r.x + (r.w - w) / 2, r.y + (r.h - h) / 2, w, h);
}

View File

@ -149,6 +149,7 @@ struct Rect : public SDL_Rect
h = surf->h;
}
Rect centerIn(const Rect &r);
static Rect createCentered(int w, int h);
static Rect around(const Rect &r, int width = 1); //creates rect around another
@ -300,7 +301,7 @@ public:
class IShowActivable : public IShowable, public IActivable
{
public:
enum {WITH_GARRISON = 1, BLOCK_ADV_HOTKEYS = 2};
enum {WITH_GARRISON = 1, BLOCK_ADV_HOTKEYS = 2, WITH_ARTIFACTS = 4};
int type; //bin flags using etype
IShowActivable();
virtual ~IShowActivable(){}; //d-tor
@ -435,7 +436,7 @@ public:
virtual void keyPressed(const SDL_KeyboardEvent & key); //call-in
};
class CGarrisonHolder : public CIntObject// to unify updating garrisons via PlayerInterface
class CGarrisonHolder : public virtual CIntObject// to unify updating garrisons via PlayerInterface
{
public:
CGarrisonHolder();

View File

@ -326,7 +326,7 @@ CGarrisonSlot::~CGarrisonSlot()
if(active)
deactivate();
}
void CGarrisonSlot::show(SDL_Surface * to)
void CGarrisonSlot::showAll(SDL_Surface * to)
{
std::map<int,SDL_Surface*> &imgs = (owner->smallIcons ? graphics->smallImgs : graphics->bigImgs);
if(creature)
@ -2200,10 +2200,10 @@ void CCreInfoWindow::init(const CCreature *cre, const CBonusSystemNode *stackNod
printLine(6, CGI->generaltexth->zelp[441].first, cre->valOfBonuses(Bonus::STACKS_SPEED), stackNode->valOfBonuses(Bonus::STACKS_SPEED));
//setting morale
morale = new MoraleLuckBox(true, genRect(42, 42, pos.x + 24, pos.y + 189));
morale = new MoraleLuckBox(true, genRect(42, 42, 24, 189));
morale->set(stackNode);
//setting luck
luck = new MoraleLuckBox(false, genRect(42, 42, pos.x + 77, pos.y + 189));
luck = new MoraleLuckBox(false, genRect(42, 42, 77, 189));
luck->set(stackNode);
//luck and morale
@ -2628,20 +2628,20 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
if(type == ARTIFACT_PLACEHOLDER)
{
CAltarWindow *aw = static_cast<CAltarWindow *>(mw);
const CArtifactInstance *movedArt = aw->arts->commonInfo->srcArtifact;
const CArtifactInstance *movedArt = aw->arts->commonInfo->src.art;
if(movedArt)
{
aw->moveFromSlotToAltar(aw->arts->commonInfo->srcSlotID, this, movedArt->id);
aw->moveFromSlotToAltar(aw->arts->commonInfo->src.slotID, this, movedArt->id);
}
else if(const CArtifactInstance *art = getArtInstance())
{
movedArt = art;
aw->arts->commonInfo->srcAOH = aw->arts;
aw->arts->commonInfo->srcArtifact = movedArt;
aw->arts->commonInfo->srcSlotID = aw->hero->CArtifactSet::getArtPos(art);// vstd::findPos(aw->hero->artifacts, const_cast<CArtifact*>(movedArt));
aw->arts->commonInfo->src.AOH = aw->arts;
aw->arts->commonInfo->src.art = movedArt;
aw->arts->commonInfo->src.slotID = 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);
aw->arts->commonInfo->dst.AOH = aw->arts;
CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[movedArt->artType->id].bitmap);
id = -1;
subtitle = "";
@ -3825,12 +3825,12 @@ void CAltarWindow::artifactPicked()
void CAltarWindow::showAll(SDL_Surface * to)
{
CTradeWindow::showAll(to);
if(mode == ARTIFACT_EXP && arts && arts->commonInfo->srcArtifact)
if(mode == ARTIFACT_EXP && arts && arts->commonInfo->src.art)
{
blitAtLoc(graphics->artDefs->ourImages[arts->commonInfo->srcArtifact->id].bitmap, 281, 442, to);
blitAtLoc(graphics->artDefs->ourImages[arts->commonInfo->src.art->artType->id].bitmap, 281, 442, to);
int dmp, val;
market->getOffer(arts->commonInfo->srcArtifact->id, 0, dmp, val, ARTIFACT_EXP);
market->getOffer(arts->commonInfo->src.art->artType->id, 0, dmp, val, ARTIFACT_EXP);
printAtMiddleLoc(boost::lexical_cast<std::string>(val), 304, 498, FONT_SMALL, zwykly, to);
}
}
@ -3864,10 +3864,10 @@ bool CAltarWindow::putOnAltar(CTradeableItem* altarSlot, int artID)
void CAltarWindow::moveFromSlotToAltar(int slotID, CTradeableItem* altarSlot, int artID)
{
if(arts->commonInfo->srcArtifact)
if(arts->commonInfo->src.art)
{
arts->commonInfo->destSlotID = 65500;
arts->commonInfo->destAOH = arts;
arts->commonInfo->dst.slotID = 65500;
arts->commonInfo->dst.AOH = arts;
}
if(putOnAltar(altarSlot, artID))
@ -4159,8 +4159,7 @@ void CTavernWindow::HeroPortrait::clickRight(tribool down, bool previousState)
{
if(down && h)
{
adventureInt->heroWindow->setHero(h);
GH.pushInt(new CRClickPopupInt(adventureInt->heroWindow,false));
GH.pushInt(new CRClickPopupInt(new CHeroWindow(h), true));
}
}
@ -4539,7 +4538,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
//LRClickableAreaWTextComp::clickLeft(down);
// If clicked on spellbook, open it only if no artifact is held at the moment.
if(ourArt && !down && previousState && !ourOwner->commonInfo->srcAOH)
if(ourArt && !down && previousState && !ourOwner->commonInfo->src.AOH)
{
if(ourArt->artType->id == 0)
{
@ -4553,7 +4552,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
if(ourArt && ourArt->id == 0) //spellbook
return; //this is handled separately
if(!ourOwner->commonInfo->srcAOH) //nothing has been clicked
if(!ourOwner->commonInfo->src.AOH) //nothing has been clicked
{
if(ourArt //to prevent selecting empty slots (bugfix to what GrayFace reported)
&& ourOwner->curHero->tempOwner == LOCPLINT->playerID)//can't take art from another player
@ -4567,11 +4566,15 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
select();
}
}
else if(ourArt == ourOwner->commonInfo->src.art) //restore previously picked artifact
{
deselect();
}
else //perform artifact substitution
{
if (slotID >= 19) // Backpack destination.
{
const CArtifact * const cur = ourOwner->commonInfo->srcArtifact->artType;
const CArtifact * const cur = ourOwner->commonInfo->src.art->artType;
switch(cur->id)
{
@ -4584,6 +4587,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
break;
default:
setMeAsDest();
amin(ourOwner->commonInfo->dst.slotID, ourOwner->curHero->artifactsInBackpack.size() + Arts::BACKPACK_START);
//
// // Correction for backpack position when src lies before dest.
// int correction = (ourOwner->commonInfo->srcAOH == ourOwner
@ -4597,21 +4601,21 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
}
}
//check if swap is possible
else if (this->fitsHere(ourOwner->commonInfo->srcArtifact) &&
else if (fitsHere(ourOwner->commonInfo->src.art) &&
(!ourArt || ourOwner->curHero->tempOwner == LOCPLINT->playerID))
{
setMeAsDest();
// Special case when the dest artifact can't be fit into the src slot.
//CGI->arth->unequipArtifact(ourOwner->curHero->artifWorn, slotID);
const CArtifactsOfHero* srcAOH = ourOwner->commonInfo->srcAOH;
ui16 srcSlotID = ourOwner->commonInfo->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;
}
//
// // Special case when the dest artifact can't be fit into the src slot.
// //CGI->arth->unequipArtifact(ourOwner->curHero->artifWorn, slotID);
// const CArtifactsOfHero* srcAOH = ourOwner->commonInfo->src.AOH;
// ui16 srcSlotID = ourOwner->commonInfo->src.slotID;
// if (ourArt && srcSlotID < 19 && !ourArt->canBePutAt(ArtifactLocation(srcAOH->curHero, srcSlotID)))
// {
// // Put dest artifact into owner's backpack.
// ourOwner->commonInfo->src.AOH = ourOwner;
// ourOwner->commonInfo->src.slotID = ourOwner->curHero->artifacts.size() + 19;
// }
ourOwner->realizeCurrentTransaction();
}
@ -4674,24 +4678,16 @@ void CArtPlace::select ()
int backpackCorrection = -(slotID - 19 < ourOwner->backpackPos);
CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[ourArt->id].bitmap);
CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[ourArt->artType->id].bitmap);
ourOwner->commonInfo->srcArtifact = ourArt;
ourOwner->commonInfo->srcSlotID = slotID;
ourOwner->commonInfo->srcAOH = ourOwner;
ourOwner->commonInfo->src.setTo(this, false);
// 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));
ourOwner->markPossibleSlots(ourArt);
//ourOwner->curHero->recreateArtBonuses();
if (slotID >= 19)
ourOwner->scrollBackpack(backpackCorrection);
else
//
// if (slotID >= 19)
// ourOwner->scrollBackpack(backpackCorrection);
// else
ourOwner->eraseSlotData(this, slotID);
// Update the hero bonuses.
@ -4706,6 +4702,11 @@ void CArtPlace::deselect ()
{
CCS->curh->dragAndDropCursor(NULL);
ourOwner->unmarkSlots();
ourOwner->commonInfo->src.clear();
ourOwner->updateParentWindow();
ourOwner->safeRedraw();
}
void CArtPlace::deactivate()
@ -4749,7 +4750,7 @@ bool CArtPlace::fitsHere(const CArtifactInstance * art) const
if (slotID >= 19)
return !CGI->arth->isBigArtifact(art->id);
return art->canBePutAt(ArtifactLocation(ourOwner->curHero, slotID));
return art->canBePutAt(ArtifactLocation(ourOwner->curHero, slotID), true);
}
CArtPlace::~CArtPlace()
@ -4764,13 +4765,7 @@ bool CArtPlace::locked() const
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;
ourOwner->commonInfo->dst.setTo(this, backpackAsVoid);
}
void HoverableArea::hover (bool on)
@ -4897,74 +4892,72 @@ LRClickableAreaOpenTown::LRClickableAreaOpenTown()
void CArtifactsOfHero::SCommonPart::reset()
{
destAOH = srcAOH = NULL;
destArtifact = srcArtifact = NULL;
destSlotID = srcSlotID = -1;
src.clear();
dst.clear();
CCS->curh->dragAndDropCursor(NULL);
}
void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
{
// An update is made, rather than initialization.
if (curHero && curHero->id == hero->id)
{
if(curHero != hero)
{
//delete curHero;
curHero = hero; //was: creating a copy
}
// Compensate backpack pos if an artifact was insertad before it.
if (commonInfo->destSlotID >= 19 && commonInfo->destAOH == this
&& commonInfo->destSlotID - 19 < backpackPos)
{
backpackPos++;
}
if (updateState && commonInfo->srcAOH == this)
{
// 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);
// // An update is made, rather than initialization.
// if (curHero && curHero->id == hero->id)
// {
// if(curHero != hero)
// {
// //delete curHero;
// curHero = hero; //was: creating a copy
// }
//
// // Compensate backpack pos if an artifact was insertad before it.
// if (commonInfo->dst.slotID >= 19 && commonInfo->destAOH == this
// && commonInfo->dst.slotID - 19 < backpackPos)
// {
// backpackPos++;
// }
//
// if (updateState && commonInfo->srcAOH == this)
// {
// // A swap was made, make the replaced artifact the current selected.
// if (commonInfo->dst.slotID < 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));
//
// updateParentWindow(); //TODO: evil! but does the thing
//
// // Source <- Dest
// commonInfo->srcArtifact = commonInfo->destArtifact;
//
// // Reset destination parameters.
// commonInfo->dst.clear();
//
// CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[commonInfo->srcArtifact->id].bitmap);
// markPossibleSlots(commonInfo->srcArtifact);
// }
// else if (commonInfo->destAOH != NULL)
// {
// // Reset all parameters.
// commonInfo->reset();
// unmarkSlots();
// }
// }
// }
// else
// curHero->artifacts.erase(curHero->artifacts.begin() + (commonInfo->srcSlotID - 19));
updateParentWindow(); //TODO: evil! but does the thing
// Source <- Dest
commonInfo->srcArtifact = commonInfo->destArtifact;
// Reset destination parameters.
commonInfo->destAOH = NULL;
commonInfo->destArtifact = NULL;
commonInfo->destSlotID = -1;
CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[commonInfo->srcArtifact->id].bitmap);
markPossibleSlots(commonInfo->srcArtifact);
}
else if (commonInfo->destAOH != NULL)
{
// Reset all parameters.
commonInfo->reset();
unmarkSlots();
}
}
}
else
{
commonInfo->reset();
}
if(hero != curHero)
{
// delete curHero;
// curHero = new CGHeroInstance(*hero);
curHero = hero; //was: creating a copy
}
// {
// commonInfo->reset();
// }
//
// if(hero != curHero)
// {
// // delete curHero;
// // curHero = new CGHeroInstance(*hero);
// curHero = hero; //was: creating a copy
// }
curHero = hero;
if (curHero->artifacts.size() > 0)
backpackPos %= curHero->artifacts.size();
else
@ -5045,18 +5038,9 @@ void CArtifactsOfHero::scrollBackpack(int dir)
*/
void CArtifactsOfHero::markPossibleSlots(const CArtifactInstance* art)
{
for (std::set<CArtifactsOfHero *>::iterator it = commonInfo->participants.begin();
it != commonInfo->participants.end();
++it)
{
for (int i = 0; i < (*it)->artWorn.size(); i++)
{
if ((*it)->artWorn[i]->fitsHere(art))
(*it)->artWorn[i]->marked = true;
else
(*it)->artWorn[i]->marked = false;
}
}
BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants)
BOOST_FOREACH(CArtPlace *place, aoh->artWorn)
place->marked = art->canBePutAt(ArtifactLocation(aoh->curHero, place->slotID), true);
safeRedraw();
}
@ -5066,16 +5050,9 @@ void CArtifactsOfHero::markPossibleSlots(const CArtifactInstance* art)
*/
void CArtifactsOfHero::unmarkSlots(bool withRedraw /*= true*/)
{
if(!commonInfo) return;
for (std::set<CArtifactsOfHero *>::iterator it = commonInfo->participants.begin();
it != commonInfo->participants.end();
++it)
{
for (int i = 0; i < (*it)->artWorn.size(); i++)
{
(*it)->artWorn[i]->marked = false;
}
}
BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants)
BOOST_FOREACH(CArtPlace *place, aoh->artWorn)
place->marked = false;
if(withRedraw)
safeRedraw();
@ -5175,11 +5152,7 @@ void CArtifactsOfHero::updateParentWindow()
if(updateState)
chw->curHero = curHero;
else
{
chw->deactivate();
chw->setHero(curHero);
chw->activate();
}
chw->update(curHero, true);
}
else if(CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(GH.topInt()))
{
@ -5218,10 +5191,78 @@ void CArtifactsOfHero::safeRedraw()
void CArtifactsOfHero::realizeCurrentTransaction()
{
assert(commonInfo->srcAOH);
assert(commonInfo->destAOH);
LOCPLINT->cb->swapArtifacts(commonInfo->srcAOH->curHero, commonInfo->srcSlotID,
commonInfo->destAOH->curHero, commonInfo->destSlotID);
assert(commonInfo->src.AOH);
assert(commonInfo->dst.AOH);
LOCPLINT->cb->swapArtifacts(commonInfo->src.AOH->curHero, commonInfo->src.slotID,
commonInfo->dst.AOH->curHero, commonInfo->dst.slotID);
}
void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
{
BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants) //update affected slots
{
if(src.hero == aoh->curHero)
setSlotData(aoh->getArtPlace(src.slot), src.slot);
if(dst.hero == aoh->curHero)
setSlotData(aoh->getArtPlace(dst.slot), dst.slot);
}
updateParentWindow();
if(commonInfo->src == src) //artifact was taken from us
{
assert(commonInfo->dst == dst || dst.slot == dst.hero->artifactsInBackpack.size() + Arts::BACKPACK_START);
commonInfo->reset();
unmarkSlots();
}
else if(commonInfo->dst == src) //the dest artifact was moved -> we are picking it
{
assert(dst.slot >= Arts::BACKPACK_START);
commonInfo->reset();
CArtPlace *ap = NULL;
BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants)
{
if(aoh->curHero == dst.hero)
{
commonInfo->src.AOH = aoh;
if(ap = aoh->getArtPlace(dst.slot))
break;
}
}
if(ap)
{
ap->select();
}
else
{
commonInfo->src.art = src.getArt();
commonInfo->src.slotID = src.slot;
assert(commonInfo->src.AOH);
CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[src.getArt()->artType->id].bitmap);
markPossibleSlots(dst.getArt());
}
}
else
{
tlog1 << "Unexpected artifact movement...\n";
}
}
CArtPlace * CArtifactsOfHero::getArtPlace(int slot)
{
if(slot < Arts::BACKPACK_START)
{
return artWorn[slot];
}
else
{
BOOST_FOREACH(CArtPlace *ap, backpack)
if(ap->slotID == slot)
return ap;
}
return NULL;
}
void CExchangeWindow::close()
@ -6461,7 +6502,9 @@ void MoraleLuckBox::set(const CBonusSystemNode *node)
void MoraleLuckBox::showAll(SDL_Surface * to)
{
CDefEssential *def = morale ? graphics->morale42 : graphics->luck42;
blitAt(def->ourImages[bonusValue].bitmap, pos, to);
SDL_Surface *img = def->ourImages[bonusValue + 3].bitmap;
blitAt(img, Rect(img).centerIn(pos), to); //put img in the center of our pos
}
MoraleLuckBox::MoraleLuckBox(bool Morale, const Rect &r)
@ -6811,3 +6854,45 @@ void CFocusable::moveFocus()
}
}
}
CWindowWithArtifacts::CWindowWithArtifacts()
{
type |= WITH_ARTIFACTS;
}
CWindowWithArtifacts::~CWindowWithArtifacts()
{
}
void CArtifactsOfHero::SCommonPart::Artpos::clear()
{
slotID = -1;
AOH = NULL;
art = NULL;
}
CArtifactsOfHero::SCommonPart::Artpos::Artpos()
{
clear();
}
void CArtifactsOfHero::SCommonPart::Artpos::setTo(const CArtPlace *place, bool dontTakeBackpack)
{
slotID = place->slotID;
AOH = place->ourOwner;
if(slotID >= 19 && dontTakeBackpack)
art = NULL;
else
art = place->ourArt;
}
bool CArtifactsOfHero::SCommonPart::Artpos::operator==(const ArtifactLocation &al) const
{
if(!AOH)
return false;
bool ret = al.hero == AOH->curHero && al.slot == slotID;
//assert(al.getArt() == art);
return ret;
}

View File

@ -25,6 +25,7 @@
*
*/
struct ArtifactLocation;
class CStackBasicDescriptor;
class CBonusSystemNode;
class CArtifact;
@ -214,7 +215,7 @@ public:
void clickLeft(tribool down, bool previousState);
void activate();
void deactivate();
void show(SDL_Surface * to);
void showAll(SDL_Surface * to);
CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg=0, const CStackInstance * Creature=NULL);
~CGarrisonSlot(); //d-tor
};
@ -907,6 +908,15 @@ public:
void show(SDL_Surface * to);
};
class CWindowWithArtifacts : public virtual CIntObject
{
public:
std::vector<CArtifactsOfHero *> artSets;
CWindowWithArtifacts();
~CWindowWithArtifacts();
};
class CArtPlace: public LRClickableAreaWTextComp
{
public:
@ -932,7 +942,6 @@ public:
~CArtPlace(); //d-tor
};
class CArtifactsOfHero : public CIntObject
{
const CGHeroInstance * curHero; //local copy of hero on which we operate
@ -944,13 +953,19 @@ class CArtifactsOfHero : public CIntObject
public:
struct SCommonPart
{
struct Artpos
{
int slotID;
const CArtifactsOfHero * AOH;
const CArtifactInstance *art;
Artpos();
void clear();
void setTo(const CArtPlace *place, bool dontTakeBackpack);
bool operator==(const ArtifactLocation &al) const;
} src, dst;
std::set<CArtifactsOfHero *> participants; // Needed to mark slots.
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 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
@ -962,6 +977,8 @@ public:
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 artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst);
CArtPlace *getArtPlace(int slot);
void setHero(const CGHeroInstance * hero);
void dispose(); //free resources not needed after closing windows and reset state

View File

@ -169,15 +169,19 @@ void RebalanceStacks::applyCl( CClient *cl )
void PutArtifact::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(al.hero->tempOwner, artifactPut, al);
}
void EraseArtifact::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(al.hero->tempOwner, artifactRemoved, al);
}
void MoveArtifact::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
if(src.hero->tempOwner != dst.hero->tempOwner)
INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
}
void GiveBonus::applyCl( CClient *cl )
@ -394,13 +398,15 @@ void SetHeroesInTown::applyCl( CClient *cl )
void SetHeroArtifacts::applyCl( CClient *cl )
{
CGHeroInstance *h = GS(cl)->getHero(hid);
CGameInterface *player = (vstd::contains(cl->playerint,h->tempOwner) ? cl->playerint[h->tempOwner] : NULL);
if(!player)
return;
tlog1 << "SetHeroArtifacts :(\n";
//
// CGHeroInstance *h = GS(cl)->getHero(hid);
// CGameInterface *player = (vstd::contains(cl->playerint,h->tempOwner) ? cl->playerint[h->tempOwner] : NULL);
// if(!player)
// return;
//h->recreateArtBonuses();
player->heroArtifactSetChanged(h);
//player->heroArtifactSetChanged(h);
// BOOST_FOREACH(Bonus bonus, gained)
// {

View File

@ -958,6 +958,7 @@ void CArtifactInstance::putAt(CGHeroInstance *h, ui16 slot)
asi.artifact = this;
asi.locked = false;
if(slot < Arts::BACKPACK_START)
h->attachTo(this);
}

View File

@ -1190,6 +1190,21 @@ void CGHeroInstance::UpdateSpeciality()
}
void CGHeroInstance::updateSkill(int which, int val)
{
if(which == LEADERSHIP || which == LUCK)
{
bool luck = which == LUCK;
Bonus::BonusType type[] = {Bonus::MORALE, Bonus::LUCK};
Bonus *b = getBonus(Selector::type(type[luck]) && Selector::sourceType(Bonus::SECONDARY_SKILL));
if(!b)
{
b = new Bonus(Bonus::PERMANENT, type[luck], Bonus::SECONDARY_SKILL, +val, which, which, Bonus::BASE_NUMBER);
addNewBonus(b);
}
else
b->val = +val;
}
int skillVal = 0;
switch (which)
{

View File

@ -712,7 +712,10 @@ DLL_EXPORT void EraseArtifact::applyGs( CGameState *gs )
DLL_EXPORT void MoveArtifact::applyGs( CGameState *gs )
{
assert(!dst.getArt());
CArtifactInstance *a = src.getArt();
a->removeFrom(src.hero, src.slot);
a->putAt(dst.hero, dst.slot);
}
DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs )

View File

@ -2486,8 +2486,8 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
// Check if src/dest slots are appropriate for the artifacts exchanged.
// Moving to the backpack is always allowed.
if ((!srcArtifact || destSlot < Arts::BACKPACK_START)
&& srcArtifact && !srcArtifact->canBePutAt(dst))
COMPLAIN_RET("Cannot swap artifacts!");
&& srcArtifact && !srcArtifact->canBePutAt(dst, true))
COMPLAIN_RET("Cannot move artifact!");
if ((srcArtifact && srcArtifact->artType->id == Arts::ID_LOCK) || (destArtifact && destArtifact->artType->id == Arts::ID_LOCK))
COMPLAIN_RET("Cannot move artifact locks.");
@ -2497,6 +2497,16 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
if (srcSlot == Arts::MACH4 || destSlot == Arts::MACH4)
COMPLAIN_RET("Cannot move catapult!");
if(dst.slot >= Arts::BACKPACK_START)
amin(dst.slot, Arts::BACKPACK_START + dst.hero->artifactsInBackpack.size());
// Correction for destination from removing source artifact in backpack.
if (src.slot >= 19 && dst.slot >= 19 && src.slot < dst.slot)
dst.slot--;
if (src.slot == dst.slot)
COMPLAIN_RET("Won't move artifact: Dest same as source!");
//moving art to backpack is always allowed (we've ruled out exceptions)
if(destSlot >= Arts::BACKPACK_START)
{
@ -2506,7 +2516,7 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
{
if(destArtifact) //old artifact must be removed first
{
moveArtifact(dst, ArtifactLocation(destHero, destHero->artifactsInBackpack.size()-1));
moveArtifact(dst, ArtifactLocation(destHero, destHero->artifactsInBackpack.size() + Arts::BACKPACK_START));
}
moveArtifact(src, dst);
}
@ -2526,9 +2536,6 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
// // 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));
// }