mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-15 01:24:45 +02:00
Version set to 0.83c, to be released as development build.
Code reorganizations in bonus system, allowing defining bonusNode-like classes. Fixed some issues with artifact handling (proper updating of GUI when moving, minor fixes). Restoring battle AI for neutrals after loading game.
This commit is contained in:
22
ChangeLog
22
ChangeLog
@ -1,14 +1,26 @@
|
||||
0.83 -> 0.84 (Mar 01 2011)
|
||||
GENERAL:
|
||||
* Bonus system has been rewritten
|
||||
* Support for new artifacts (spell scrolls, angelic alliance)
|
||||
* Preliminary support for stack experience (no UI yet)
|
||||
* Partial support for running VCMI in duel mode (no adventure map, only one battle)
|
||||
* Partial support for running VCMI in duel mode (no adventure map, only one battle, ATM only AI-AI battles)
|
||||
* New artifacts supported:
|
||||
- Angellic Alliance
|
||||
- Bird of Perception
|
||||
- Emblem of Cognizance
|
||||
- Spell Scroll
|
||||
- Stoic Watchman
|
||||
|
||||
BATTLES:
|
||||
* Support for eagle eye, tactics and artillery secondary skills (together with corresponding artifacts)
|
||||
* Better animations handling
|
||||
* Defensive stance is supported
|
||||
* New, improved AI for neutral player
|
||||
|
||||
HERO:
|
||||
* New secondary skills supported:
|
||||
- Artillery
|
||||
- Eagle Eye
|
||||
- Tactics
|
||||
|
||||
AI PLAYER:
|
||||
* new AI leading neutral creatures in combat, slightly better then previous
|
||||
|
||||
|
||||
0.82 -> 0.83 (Nov 01 2010)
|
||||
|
@ -44,6 +44,28 @@
|
||||
extern SDL_Surface * screen;
|
||||
using namespace boost::assign;
|
||||
|
||||
void CHeroWithMaybePickedArtifact::getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
|
||||
{
|
||||
BonusList heroBonuses, bonusesFromPickedUpArtifact;
|
||||
hero->getAllBonuses(heroBonuses, selector, limit, hero);
|
||||
|
||||
CArtifactsOfHero::SCommonPart *cp = cww->artSets.size() ? cww->artSets.front()->commonInfo : NULL;
|
||||
if(cp && cp->src.art && cp->src.AOH && cp->src.AOH->getHero() == hero)
|
||||
{
|
||||
cp->src.art->getAllBonuses(bonusesFromPickedUpArtifact, selector, limit, hero);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(Bonus *b, bonusesFromPickedUpArtifact)
|
||||
heroBonuses -= b;
|
||||
BOOST_FOREACH(Bonus *b, heroBonuses)
|
||||
out.push_back(b);
|
||||
}
|
||||
|
||||
CHeroWithMaybePickedArtifact::CHeroWithMaybePickedArtifact(CWindowWithArtifacts *Cww, const CGHeroInstance *Hero)
|
||||
: cww(Cww), hero(Hero)
|
||||
{
|
||||
}
|
||||
|
||||
void CHeroSwitcher::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(!down)
|
||||
@ -69,6 +91,7 @@ CHeroSwitcher::CHeroSwitcher(int serial)
|
||||
}
|
||||
|
||||
CHeroWindow::CHeroWindow(const CGHeroInstance *hero)
|
||||
: heroWArt(this, hero)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
garr = NULL;
|
||||
@ -98,8 +121,6 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero)
|
||||
for(int g=0; g<8; ++g)
|
||||
heroListMi.push_back(new CHeroSwitcher(g));
|
||||
|
||||
|
||||
|
||||
flags = CDefHandler::giveDefEss("CREST58.DEF");
|
||||
|
||||
//areas
|
||||
@ -162,15 +183,14 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals
|
||||
assert(hero == curHero);
|
||||
//assert(hero->tempOwner == LOCPLINT->playerID || hero->tempOwner == NEUTRAL_PLAYER); //for now we won't show hero windows for non-our heroes
|
||||
|
||||
specArea->text = CGI->generaltexth->hTxts[hero->subID].longBonus;
|
||||
specArea->text = CGI->generaltexth->hTxts[curHero->subID].longBonus;
|
||||
|
||||
tacticsButton->callback.clear();
|
||||
tacticsButton->callback2.clear();
|
||||
|
||||
dismissButton->hoverTexts[0] = boost::str(boost::format(CGI->generaltexth->heroscrn[16]) % curHero->name % curHero->type->heroClass->name);
|
||||
portraitArea->hoverText = boost::str(boost::format(CGI->generaltexth->allTexts[15]) % curHero->name % curHero->type->heroClass->name);
|
||||
portraitArea->text = hero->getBiography();
|
||||
|
||||
portraitArea->text = curHero->getBiography();
|
||||
|
||||
{
|
||||
AdventureMapButton * split = NULL;
|
||||
@ -189,7 +209,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals
|
||||
if(!artSets.size())
|
||||
{
|
||||
CArtifactsOfHero *arts = new CArtifactsOfHero(Point(-65, -8), true);
|
||||
arts->setHero(hero);
|
||||
arts->setHero(curHero);
|
||||
artSets.push_back(arts);
|
||||
}
|
||||
}
|
||||
@ -198,14 +218,14 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals
|
||||
//primary skills support
|
||||
for(size_t g=0; g<primSkillAreas.size(); ++g)
|
||||
{
|
||||
primSkillAreas[g]->bonusValue = hero->getPrimSkillLevel(g);
|
||||
primSkillAreas[g]->bonusValue = heroWArt.getPrimSkillLevel(g);
|
||||
}
|
||||
|
||||
//secondary skills support
|
||||
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));
|
||||
int skill = curHero->secSkills[g].first,
|
||||
level = curHero->getSecSkillLevel(static_cast<CGHeroInstance::SecondarySkill>(curHero->secSkills[g].first));
|
||||
secSkillAreas[g]->type = skill;
|
||||
secSkillAreas[g]->bonusValue = level;
|
||||
secSkillAreas[g]->text = CGI->generaltexth->skillInfoTexts[skill][level-1];
|
||||
@ -214,43 +234,43 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals
|
||||
|
||||
//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));
|
||||
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(CGI->heroh->reqExp(hero->level+1)));
|
||||
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(hero->exp));
|
||||
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(curHero->level));
|
||||
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(CGI->heroh->reqExp(curHero->level+1)));
|
||||
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(curHero->exp));
|
||||
|
||||
//printing spell points
|
||||
spellPointsArea->text = boost::str(boost::format(CGI->generaltexth->allTexts[205]) % hero->name % hero->mana % hero->manaLimit());
|
||||
spellPointsArea->text = boost::str(boost::format(CGI->generaltexth->allTexts[205]) % curHero->name % curHero->mana % heroWArt.manaLimit());
|
||||
|
||||
//if we have exchange window with this hero open
|
||||
//if we have exchange window with this curHero open
|
||||
bool noDismiss=false;
|
||||
BOOST_FOREACH(IShowActivable *isa, GH.listInt)
|
||||
{
|
||||
if(CExchangeWindow * cew = dynamic_cast<CExchangeWindow*>(isa))
|
||||
for(int g=0; g < ARRAY_COUNT(cew->heroInst); ++g)
|
||||
if(cew->heroInst[g] == hero)
|
||||
if(cew->heroInst[g] == curHero)
|
||||
noDismiss = true;
|
||||
|
||||
if (dynamic_cast<CKingdomInterface*>(isa))
|
||||
noDismiss = true;
|
||||
}
|
||||
dismissButton->block(!!hero->visitedTown || noDismiss);
|
||||
dismissButton->block(!!curHero->visitedTown || noDismiss);
|
||||
|
||||
if(hero->getSecSkillLevel(CGHeroInstance::TACTICS) == 0)
|
||||
if(curHero->getSecSkillLevel(CGHeroInstance::TACTICS) == 0)
|
||||
tacticsButton->block(true);
|
||||
else
|
||||
{
|
||||
tacticsButton->block(false);
|
||||
tacticsButton->callback = vstd::assigno(hero->tacticFormationEnabled,true);
|
||||
tacticsButton->callback2 = vstd::assigno(hero->tacticFormationEnabled,false);
|
||||
tacticsButton->callback = vstd::assigno(curHero->tacticFormationEnabled,true);
|
||||
tacticsButton->callback2 = vstd::assigno(curHero->tacticFormationEnabled,false);
|
||||
}
|
||||
|
||||
//setting formations
|
||||
formations->onChange = 0;
|
||||
formations->select(hero->formation,true);
|
||||
formations->onChange = boost::bind(&CCallback::setFormation, LOCPLINT->cb, hero, _1);
|
||||
formations->select(curHero->formation,true);
|
||||
formations->onChange = boost::bind(&CCallback::setFormation, LOCPLINT->cb, curHero, _1);
|
||||
|
||||
morale->set(hero);
|
||||
luck->set(hero);
|
||||
morale->set(&heroWArt);
|
||||
luck->set(&heroWArt);
|
||||
|
||||
if(redrawNeeded)
|
||||
redraw();
|
||||
@ -271,6 +291,7 @@ void CHeroWindow::dismissCurrent()
|
||||
void CHeroWindow::questlog()
|
||||
{
|
||||
}
|
||||
|
||||
void CHeroWindow::showAll(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
@ -319,7 +340,7 @@ void CHeroWindow::showAll(SDL_Surface * to)
|
||||
for(int m=0; m<4; ++m)
|
||||
{
|
||||
std::ostringstream primarySkill;
|
||||
primarySkill<<curHero->getPrimSkillLevel(m);
|
||||
primarySkill << primSkillAreas[m]->bonusValue;
|
||||
printAtMiddleLoc(primarySkill.str(), 53 + 70 * m, 166, FONT_SMALL, zwykly, to);
|
||||
}
|
||||
|
||||
@ -365,10 +386,10 @@ void CHeroWindow::showAll(SDL_Surface * to)
|
||||
//printing necessery texts
|
||||
printAtLoc(CGI->generaltexth->jktexts[6].substr(1, CGI->generaltexth->jktexts[6].size()-2), 69, 232, FONT_SMALL, tytulowy, to);
|
||||
std::ostringstream expstr;
|
||||
expstr<<curHero->exp;
|
||||
expstr << curHero->exp;
|
||||
printAtLoc(expstr.str(), 68, 252, FONT_SMALL, zwykly, to);
|
||||
printAtLoc(CGI->generaltexth->jktexts[7].substr(1, CGI->generaltexth->jktexts[7].size()-2), 213, 232, FONT_SMALL, tytulowy, to);
|
||||
std::ostringstream manastr;
|
||||
manastr << curHero->mana << '/' << curHero->manaLimit();
|
||||
manastr << curHero->mana << '/' << heroWArt.manaLimit();
|
||||
printAtLoc(manastr.str(), 211, 252, FONT_SMALL, zwykly, to);
|
||||
}
|
@ -37,7 +37,16 @@ public:
|
||||
CHeroSwitcher(int serial);
|
||||
};
|
||||
|
||||
//helper class for calculating values of hero bonuses without bonuses from picked up artifact
|
||||
class CHeroWithMaybePickedArtifact : public IBonusBearer
|
||||
{
|
||||
public:
|
||||
const CGHeroInstance *hero;
|
||||
CWindowWithArtifacts *cww;
|
||||
|
||||
CHeroWithMaybePickedArtifact(CWindowWithArtifacts *Cww, const CGHeroInstance *Hero);
|
||||
void getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const OVERRIDE;
|
||||
};
|
||||
|
||||
class CHeroWindow: public CWindowWithGarrison, public CWindowWithArtifacts
|
||||
{
|
||||
@ -61,6 +70,8 @@ class CHeroWindow: public CWindowWithGarrison, public CWindowWithArtifacts
|
||||
LRClickableAreaWText * specArea;//speciality
|
||||
MoraleLuckBox * morale, * luck;
|
||||
std::vector<LRClickableAreaWTextComp *> secSkillAreas;
|
||||
CHeroWithMaybePickedArtifact heroWArt;
|
||||
|
||||
public:
|
||||
const CGHeroInstance * curHero;
|
||||
AdventureMapButton * quitButton, * dismissButton, * questlogButton; //general
|
||||
|
@ -430,10 +430,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
}
|
||||
else
|
||||
{
|
||||
battleints[255] = CAIHandler::getNewBattleAI(conf.cc.defaultBattleAI);
|
||||
battleints[255]->init(new CBattleCallback(gs, 255, this));
|
||||
// playerint[255]->init(new CCallback(gs,255,this));
|
||||
// battleints[255] = playerint[255];
|
||||
loadNeutralBattleAI();
|
||||
}
|
||||
|
||||
serv->addStdVecItems(const_cast<CGameInfo*>(CGI)->state);
|
||||
@ -493,6 +490,9 @@ void CClient::serialize( Handler &h, const int version )
|
||||
nInt->init(callback);
|
||||
nInt->serialize(h, version);
|
||||
}
|
||||
|
||||
if(!vstd::contains(battleints, NEUTRAL_PLAYER))
|
||||
loadNeutralBattleAI();
|
||||
}
|
||||
}
|
||||
|
||||
@ -588,6 +588,12 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
battleints[254]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
|
||||
}
|
||||
|
||||
void CClient::loadNeutralBattleAI()
|
||||
{
|
||||
battleints[255] = CAIHandler::getNewBattleAI(conf.cc.defaultBattleAI);
|
||||
battleints[255]->init(new CBattleCallback(gs, 255, this));
|
||||
}
|
||||
|
||||
template void CClient::serialize( CISer<CLoadFile> &h, const int version );
|
||||
template void CClient::serialize( COSer<CSaveFile> &h, const int version );
|
||||
|
||||
|
@ -82,6 +82,8 @@ public:
|
||||
|
||||
void init();
|
||||
void newGame(CConnection *con, StartInfo *si); //con - connection to server
|
||||
|
||||
void loadNeutralBattleAI();
|
||||
void endGame(bool closeConnection = true);
|
||||
void stopConnection();
|
||||
void save(const std::string & fname);
|
||||
|
@ -74,6 +74,7 @@ CFocusable * CFocusable::inputWithFocus;
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
|
||||
void CGarrisonSlot::hover (bool on)
|
||||
{
|
||||
////Hoverable::hover(on);
|
||||
@ -4663,7 +4664,6 @@ void CArtPlace::select ()
|
||||
if(slotID >= Arts::BACKPACK_START)
|
||||
ourOwner->scrollBackpack(0); //will update slots
|
||||
|
||||
// Update the hero bonuses.
|
||||
ourOwner->updateParentWindow();
|
||||
ourOwner->safeRedraw();
|
||||
}
|
||||
@ -4695,7 +4695,7 @@ void CArtPlace::deactivate()
|
||||
|
||||
void CArtPlace::showAll(SDL_Surface *to)
|
||||
{
|
||||
if (ourArt && !picked)
|
||||
if (ourArt && !picked && ourArt == ourOwner->curHero->getArt(slotID)) //last condition is needed for disassembling -> artifact may be gone, but we don't know yet TODO: real, nice solution
|
||||
{
|
||||
int graphic = locked ? 145 : ourArt->artType->id;
|
||||
blitAt(graphics->artDefs->ourImages[graphic].bitmap, pos.x, pos.y, to);
|
||||
@ -5161,16 +5161,17 @@ void CArtifactsOfHero::updateParentWindow()
|
||||
if(!updateState)
|
||||
{
|
||||
cew->deactivate();
|
||||
for(int g=0; g<ARRAY_COUNT(cew->heroInst); ++g)
|
||||
{
|
||||
if(cew->heroInst[g] == curHero)
|
||||
{
|
||||
cew->artifs[g]->setHero(curHero);
|
||||
}
|
||||
}
|
||||
// for(int g=0; g<ARRAY_COUNT(cew->heroInst); ++g)
|
||||
// {
|
||||
// if(cew->heroInst[g] == curHero)
|
||||
// {
|
||||
// cew->artifs[g]->setHero(curHero);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
cew->prepareBackground();
|
||||
cew->redraw();
|
||||
cew->activate();
|
||||
}
|
||||
}
|
||||
@ -5199,13 +5200,14 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
|
||||
if(dst.hero == curHero && dst.slot >= Arts::BACKPACK_START)
|
||||
setSlotData(getArtPlace(dst.slot), dst.slot);
|
||||
if(src.hero == curHero || dst.hero == curHero) //we need to update all slots, artifact might be combined and affect more slots
|
||||
updateWornSlots();
|
||||
updateWornSlots(false);
|
||||
|
||||
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();
|
||||
updateParentWindow();
|
||||
}
|
||||
else if(commonInfo->dst == src) //the dest artifact was moved -> we are picking it
|
||||
{
|
||||
@ -5289,12 +5291,18 @@ void CArtifactsOfHero::artifactDisassembled(const ArtifactLocation &al)
|
||||
updateWornSlots();
|
||||
}
|
||||
|
||||
void CArtifactsOfHero::updateWornSlots()
|
||||
void CArtifactsOfHero::updateWornSlots(bool redrawParent /*= true*/)
|
||||
{
|
||||
for(int i = 0; i < Arts::BACKPACK_START; i++)
|
||||
setSlotData(getArtPlace(i), i);
|
||||
|
||||
updateParentWindow();
|
||||
if(redrawParent)
|
||||
updateParentWindow();
|
||||
}
|
||||
|
||||
const CGHeroInstance * CArtifactsOfHero::getHero() const
|
||||
{
|
||||
return curHero;
|
||||
}
|
||||
|
||||
void CExchangeWindow::close()
|
||||
@ -5307,9 +5315,9 @@ void CExchangeWindow::activate()
|
||||
quit->activate();
|
||||
garr->activate();
|
||||
|
||||
artifs[0]->setHero(heroInst[0]);
|
||||
//artifs[0]->setHero(heroInst[0]);
|
||||
artifs[0]->activate();
|
||||
artifs[1]->setHero(heroInst[1]);
|
||||
//artifs[1]->setHero(heroInst[1]);
|
||||
artifs[1]->activate();
|
||||
|
||||
for(int g=0; g<ARRAY_COUNT(secSkillAreas); g++)
|
||||
@ -5446,11 +5454,12 @@ void CExchangeWindow::prepareBackground()
|
||||
//heroes related thing
|
||||
for(int b=0; b<ARRAY_COUNT(heroInst); b++)
|
||||
{
|
||||
CHeroWithMaybePickedArtifact heroWArt = CHeroWithMaybePickedArtifact(this, heroInst[b]);
|
||||
//printing primary skills' amounts
|
||||
for(int m=0; m<4; ++m)
|
||||
{
|
||||
std::ostringstream primarySkill;
|
||||
primarySkill<<heroInst[b]->getPrimSkillLevel(m);
|
||||
primarySkill << heroWArt.getPrimSkillLevel(m);
|
||||
CSDL_Ext::printAtMiddle(primarySkill.str(), 352 + 93 * b, 35 + 36 * m, FONT_SMALL, zwykly, bg);
|
||||
}
|
||||
|
||||
@ -5472,10 +5481,10 @@ void CExchangeWindow::prepareBackground()
|
||||
printAtMiddle( makeNumberShort(heroInst[b]->mana), 155 + 490*b, 71, FONT_SMALL, zwykly, bg );
|
||||
|
||||
//setting morale
|
||||
blitAt(graphics->morale30->ourImages[heroInst[b]->MoraleVal()+3].bitmap, 177 + 490*b, 45, bg);
|
||||
blitAt(graphics->morale30->ourImages[heroWArt.MoraleVal()+3].bitmap, 177 + 490*b, 45, bg);
|
||||
|
||||
//setting luck
|
||||
blitAt(graphics->luck30->ourImages[heroInst[b]->LuckVal()+3].bitmap, 213 + 490*b, 45, bg);
|
||||
blitAt(graphics->luck30->ourImages[heroWArt.LuckVal()+3].bitmap, 213 + 490*b, 45, bg);
|
||||
}
|
||||
|
||||
//printing portraits
|
||||
@ -6453,7 +6462,7 @@ CThievesGuildWindow::~CThievesGuildWindow()
|
||||
// delete resdatabar;
|
||||
}
|
||||
|
||||
void MoraleLuckBox::set(const CBonusSystemNode *node)
|
||||
void MoraleLuckBox::set(const IBonusBearer *node)
|
||||
{
|
||||
const int textId[] = {62, 88}; //eg %s \n\n\n {Current Luck Modifiers:}
|
||||
const int noneTxtId = 108; //Russian version uses same text for neutral morale\luck
|
||||
@ -6461,7 +6470,7 @@ void MoraleLuckBox::set(const CBonusSystemNode *node)
|
||||
const int componentType[] = {SComponent::luck, SComponent::morale};
|
||||
const int hoverTextBase[] = {7, 4};
|
||||
const Bonus::BonusType bonusType[] = {Bonus::LUCK, Bonus::MORALE};
|
||||
int (CBonusSystemNode::*getValue[])() const = {&CBonusSystemNode::LuckVal, &CBonusSystemNode::MoraleVal};
|
||||
int (IBonusBearer::*getValue[])() const = {&IBonusBearer::LuckVal, &IBonusBearer::MoraleVal};
|
||||
|
||||
int mrlt = -9;
|
||||
TModDescr mrl;
|
||||
@ -6484,8 +6493,7 @@ void MoraleLuckBox::set(const CBonusSystemNode *node)
|
||||
text += CGI->generaltexth->arraytxt[noneTxtId];
|
||||
else
|
||||
{
|
||||
if (node->nodeType == CBonusSystemNode::STACK_INSTANCE &&
|
||||
(node->hasBonusOfType (Bonus::UNDEAD) || node->hasBonusOfType(Bonus::BLOCK_MORALE) || node->hasBonusOfType(Bonus::NON_LIVING))) //it's a creature window
|
||||
if (node->hasBonusOfType (Bonus::UNDEAD) || node->hasBonusOfType(Bonus::BLOCK_MORALE) || node->hasBonusOfType(Bonus::NON_LIVING)) //it's a creature window
|
||||
{
|
||||
text += CGI->generaltexth->arraytxt[113]; //unaffected by morale
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ class CStackInstance;
|
||||
class IMarket;
|
||||
class CTextBox;
|
||||
class CArtifactInstance;
|
||||
class IBonusBearer;
|
||||
|
||||
extern SDL_Color tytulowy, tlo, zwykly ;
|
||||
|
||||
@ -878,7 +879,7 @@ class MoraleLuckBox : public LRClickableAreaWTextComp
|
||||
public:
|
||||
bool morale; //true if morale, false if luck
|
||||
|
||||
void set(const CBonusSystemNode *node);
|
||||
void set(const IBonusBearer *node);
|
||||
void showAll(SDL_Surface * to);
|
||||
|
||||
MoraleLuckBox(bool Morale, const Rect &r);
|
||||
@ -972,7 +973,7 @@ public:
|
||||
/// Contains artifacts of hero. Distincts which artifacts are worn or backpacked
|
||||
class CArtifactsOfHero : public CIntObject
|
||||
{
|
||||
const CGHeroInstance * curHero; //local copy of hero on which we operate
|
||||
const CGHeroInstance * curHero;
|
||||
|
||||
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!)
|
||||
@ -1012,6 +1013,7 @@ public:
|
||||
CArtPlace *getArtPlace(int slot);
|
||||
|
||||
void setHero(const CGHeroInstance * hero);
|
||||
const CGHeroInstance *getHero() const;
|
||||
void dispose(); //free resources not needed after closing windows and reset state
|
||||
void scrollBackpack(int dir); //dir==-1 => to left; dir==1 => to right
|
||||
|
||||
@ -1019,7 +1021,7 @@ public:
|
||||
void markPossibleSlots(const CArtifactInstance* art);
|
||||
void unmarkSlots(bool withRedraw = true);
|
||||
void setSlotData (CArtPlace* artPlace, int slotID);
|
||||
void updateWornSlots ();
|
||||
void updateWornSlots (bool redrawParent = true);
|
||||
void eraseSlotData (CArtPlace* artPlace, int slotID);
|
||||
|
||||
CArtifactsOfHero(const Point& position, bool createCommonPart = false); //c-tor
|
||||
|
2
global.h
2
global.h
@ -33,7 +33,7 @@ typedef si32 TBonusSubtype;
|
||||
#define THC
|
||||
#endif
|
||||
|
||||
#define NAME_VER ("VCMI 0.83b")
|
||||
#define NAME_VER ("VCMI 0.83c")
|
||||
extern std::string NAME; //full name
|
||||
extern std::string NAME_AFFIX; //client / server
|
||||
#define CONSOLE_LOGGING_LEVEL 5
|
||||
|
@ -622,30 +622,11 @@ int3 CGHeroInstance::getPosition(bool h3m) const //h3m=true - returns position o
|
||||
}
|
||||
}
|
||||
|
||||
si32 CGHeroInstance::manaLimit() const
|
||||
{
|
||||
return si32(getPrimSkillLevel(3) * (100.0f + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 24)) / 10.0f);
|
||||
}
|
||||
//void CGHeroInstance::setPosition(int3 Pos, bool h3m) //as above, but sets position
|
||||
//{
|
||||
// if (h3m)
|
||||
// pos = Pos;
|
||||
// else
|
||||
// pos = convertPosition(Pos,true);
|
||||
//}
|
||||
|
||||
bool CGHeroInstance::canWalkOnSea() const
|
||||
{
|
||||
return hasBonusOfType(Bonus::FLYING_MOVEMENT) || hasBonusOfType(Bonus::WATER_WALKING);
|
||||
}
|
||||
|
||||
int CGHeroInstance::getPrimSkillLevel(int id) const
|
||||
{
|
||||
int ret = valOfBonuses(Bonus::PRIMARY_SKILL, id);
|
||||
amax(ret, id/2); //minimal value is 0 for attack and defense and 1 for spell power and knowledge
|
||||
return ret;
|
||||
}
|
||||
|
||||
ui8 CGHeroInstance::getSecSkillLevel(SecondarySkill skill) const
|
||||
{
|
||||
for(size_t i=0; i < secSkills.size(); ++i)
|
||||
|
@ -386,16 +386,11 @@ public:
|
||||
unsigned int getTileCost(const TerrainTile &dest, const TerrainTile &from) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
||||
unsigned int getLowestCreatureSpeed() const;
|
||||
int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
|
||||
si32 manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
|
||||
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
|
||||
bool canWalkOnSea() const;
|
||||
int getCurrentLuck(int stack=-1, bool town=false) const;
|
||||
int getSpellCost(const CSpell *sp) const; //do not use during battles -> bonuses from army would be ignored
|
||||
|
||||
TModDescr getCurrentLuckModifiers(int stack=-1, bool town=false) const; //args as above
|
||||
int getCurrentMorale(int stack=-1, bool town=false) const; //if stack - position of creature, if -1 then morale for hero is calculated; town - if bonuses from town (tavern) should be considered
|
||||
TModDescr getCurrentMoraleModifiers(int stack=-1, bool town=false) const; //args as above
|
||||
int getPrimSkillLevel(int id) const; //0-attack, 1-defence, 2-spell power, 3-knowledge
|
||||
ui8 getSecSkillLevel(SecondarySkill skill) const; //0 - no skill
|
||||
void setSecSkillLevel(SecondarySkill which, int val, bool abs);// abs == 0 - changes by value; 1 - sets to value
|
||||
|
||||
|
@ -140,12 +140,12 @@ void DLL_EXPORT BonusList::eliminateDuplicates()
|
||||
unique();
|
||||
}
|
||||
|
||||
int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
|
||||
int IBonusBearer::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
|
||||
{
|
||||
return valOfBonuses(Selector::type(type) && selector);
|
||||
}
|
||||
|
||||
int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) const
|
||||
int IBonusBearer::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) const
|
||||
{
|
||||
CSelector s = Selector::type(type);
|
||||
if(subtype != -1)
|
||||
@ -154,18 +154,18 @@ int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/)
|
||||
return valOfBonuses(s);
|
||||
}
|
||||
|
||||
int CBonusSystemNode::valOfBonuses(const CSelector &selector) const
|
||||
int IBonusBearer::valOfBonuses(const CSelector &selector) const
|
||||
{
|
||||
BonusList hlp;
|
||||
getBonuses(hlp, selector);
|
||||
return hlp.totalValue();
|
||||
}
|
||||
bool CBonusSystemNode::hasBonus(const CSelector &selector) const
|
||||
bool IBonusBearer::hasBonus(const CSelector &selector) const
|
||||
{
|
||||
return getBonuses(selector).size() > 0;
|
||||
}
|
||||
|
||||
bool CBonusSystemNode::hasBonusOfType(Bonus::BonusType type, int subtype /*= -1*/) const
|
||||
bool IBonusBearer::hasBonusOfType(Bonus::BonusType type, int subtype /*= -1*/) const
|
||||
{
|
||||
CSelector s = Selector::type(type);
|
||||
if(subtype != -1)
|
||||
@ -174,6 +174,150 @@ bool CBonusSystemNode::hasBonusOfType(Bonus::BonusType type, int subtype /*= -1*
|
||||
return hasBonus(s);
|
||||
}
|
||||
|
||||
void IBonusBearer::getModifiersWDescr(TModDescr &out, Bonus::BonusType type, int subtype /*= -1 */) const
|
||||
{
|
||||
getModifiersWDescr(out, subtype != -1 ? Selector::typeSybtype(type, subtype) : Selector::type(type));
|
||||
}
|
||||
|
||||
void IBonusBearer::getModifiersWDescr(TModDescr &out, const CSelector &selector) const
|
||||
{
|
||||
getBonuses(selector).getModifiersWDescr(out);
|
||||
}
|
||||
int IBonusBearer::getBonusesCount(int from, int id) const
|
||||
{
|
||||
return getBonusesCount(Selector::source(from, id));
|
||||
}
|
||||
|
||||
int IBonusBearer::getBonusesCount(const CSelector &selector) const
|
||||
{
|
||||
return getBonuses(selector).size();
|
||||
}
|
||||
|
||||
void IBonusBearer::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
|
||||
{
|
||||
getBonuses(out, selector, 0, root);
|
||||
// FOREACH_CONST_PARENT(p)
|
||||
// p->getBonuses(out, selector, root ? root : this);
|
||||
//
|
||||
// bonuses.getBonuses(out, selector);
|
||||
//
|
||||
// if(!root)
|
||||
// out.limit(*this);
|
||||
}
|
||||
|
||||
BonusList IBonusBearer::getBonuses(const CSelector &selector) const
|
||||
{
|
||||
BonusList ret;
|
||||
getBonuses(ret, selector);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void IBonusBearer::getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
|
||||
{
|
||||
getAllBonuses(out, selector, limit, root);
|
||||
out.eliminateDuplicates();
|
||||
//
|
||||
// getBonuses(out, selector); //first get all the bonuses
|
||||
// out.remove_if(std::not1(limit)); //now remove the ones we don't like
|
||||
// out.limit(*this); //apply bonuses' limiters
|
||||
}
|
||||
|
||||
BonusList IBonusBearer::getBonuses(const CSelector &selector, const CSelector &limit) const
|
||||
{
|
||||
BonusList ret;
|
||||
getBonuses(ret, selector, limit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool IBonusBearer::hasBonusFrom(ui8 source, ui32 sourceID) const
|
||||
{
|
||||
return hasBonus(Selector::source(source,sourceID));
|
||||
}
|
||||
|
||||
int IBonusBearer::MoraleVal() const
|
||||
{
|
||||
if(hasBonusOfType(Bonus::NON_LIVING) || hasBonusOfType(Bonus::UNDEAD) ||
|
||||
hasBonusOfType(Bonus::NO_MORALE) || hasBonusOfType(Bonus::SIEGE_WEAPON))
|
||||
return 0;
|
||||
|
||||
int ret = valOfBonuses(Selector::type(Bonus::MORALE));
|
||||
|
||||
if(hasBonusOfType(Bonus::SELF_MORALE)) //eg. minotaur
|
||||
amax(ret, +1);
|
||||
|
||||
return abetw(ret, -3, +3);
|
||||
}
|
||||
|
||||
int IBonusBearer::LuckVal() const
|
||||
{
|
||||
if(hasBonusOfType(Bonus::NO_LUCK))
|
||||
return 0;
|
||||
|
||||
int ret = valOfBonuses(Selector::type(Bonus::LUCK));
|
||||
|
||||
if(hasBonusOfType(Bonus::SELF_LUCK)) //eg. halfling
|
||||
amax(ret, +1);
|
||||
|
||||
return abetw(ret, -3, +3);
|
||||
}
|
||||
|
||||
si32 IBonusBearer::Attack() const
|
||||
{
|
||||
si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK);
|
||||
|
||||
if(int frenzyPower = valOfBonuses(Bonus::IN_FRENZY)) //frenzy for attacker
|
||||
{
|
||||
ret += frenzyPower * Defense(false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
si32 IBonusBearer::Defense(bool withFrenzy /*= true*/) const
|
||||
{
|
||||
si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE);
|
||||
|
||||
if(withFrenzy && hasBonusOfType(Bonus::IN_FRENZY)) //frenzy for defender
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ui16 IBonusBearer::MaxHealth() const
|
||||
{
|
||||
return valOfBonuses(Bonus::STACK_HEALTH);
|
||||
}
|
||||
|
||||
ui32 IBonusBearer::getMinDamage() const
|
||||
{
|
||||
return valOfBonuses(Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 0) || Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 1));
|
||||
}
|
||||
ui32 IBonusBearer::getMaxDamage() const
|
||||
{
|
||||
return valOfBonuses(Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 0) || Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 2));
|
||||
}
|
||||
|
||||
si32 IBonusBearer::manaLimit() const
|
||||
{
|
||||
return si32(getPrimSkillLevel(3) * (100.0f + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 24)) / 10.0f);
|
||||
}
|
||||
|
||||
int IBonusBearer::getPrimSkillLevel(int id) const
|
||||
{
|
||||
int ret = 0;
|
||||
if(id == PrimarySkill::ATTACK)
|
||||
ret = Attack();
|
||||
else if(id == PrimarySkill::DEFENSE)
|
||||
ret = Defense();
|
||||
else
|
||||
ret = valOfBonuses(Bonus::PRIMARY_SKILL, id);
|
||||
|
||||
amax(ret, id/2); //minimal value is 0 for attack and defense and 1 for spell power and knowledge
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bonus * CBonusSystemNode::getBonus(const CSelector &selector)
|
||||
{
|
||||
Bonus *ret = bonuses.getFirst(selector);
|
||||
@ -195,25 +339,6 @@ const Bonus * CBonusSystemNode::getBonus( const CSelector &selector ) const
|
||||
return (const_cast<CBonusSystemNode*>(this))->getBonus(selector);
|
||||
}
|
||||
|
||||
void CBonusSystemNode::getModifiersWDescr(TModDescr &out, Bonus::BonusType type, int subtype /*= -1 */) const
|
||||
{
|
||||
getModifiersWDescr(out, subtype != -1 ? Selector::typeSybtype(type, subtype) : Selector::type(type));
|
||||
}
|
||||
|
||||
void CBonusSystemNode::getModifiersWDescr(TModDescr &out, const CSelector &selector) const
|
||||
{
|
||||
getBonuses(selector).getModifiersWDescr(out);
|
||||
}
|
||||
int CBonusSystemNode::getBonusesCount(int from, int id) const
|
||||
{
|
||||
return getBonusesCount(Selector::source(from, id));
|
||||
}
|
||||
|
||||
int CBonusSystemNode::getBonusesCount(const CSelector &selector) const
|
||||
{
|
||||
return getBonuses(selector).size();
|
||||
}
|
||||
|
||||
void CBonusSystemNode::getParents(TCNodes &out) const /*retreives list of parent nodes (nodes to inherit bonuses from) */
|
||||
{
|
||||
BOOST_FOREACH(const CBonusSystemNode *parent, parents)
|
||||
@ -226,42 +351,6 @@ void CBonusSystemNode::getParents(TNodes &out)
|
||||
out.insert(const_cast<CBonusSystemNode*>(parent));
|
||||
}
|
||||
|
||||
void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
|
||||
{
|
||||
getBonuses(out, selector, 0, root);
|
||||
// FOREACH_CONST_PARENT(p)
|
||||
// p->getBonuses(out, selector, root ? root : this);
|
||||
//
|
||||
// bonuses.getBonuses(out, selector);
|
||||
//
|
||||
// if(!root)
|
||||
// out.limit(*this);
|
||||
}
|
||||
|
||||
BonusList CBonusSystemNode::getBonuses(const CSelector &selector) const
|
||||
{
|
||||
BonusList ret;
|
||||
getBonuses(ret, selector);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
|
||||
{
|
||||
getAllBonuses(out, selector, limit, root);
|
||||
out.eliminateDuplicates();
|
||||
//
|
||||
// getBonuses(out, selector); //first get all the bonuses
|
||||
// out.remove_if(std::not1(limit)); //now remove the ones we don't like
|
||||
// out.limit(*this); //apply bonuses' limiters
|
||||
}
|
||||
|
||||
BonusList CBonusSystemNode::getBonuses(const CSelector &selector, const CSelector &limit) const
|
||||
{
|
||||
BonusList ret;
|
||||
getBonuses(ret, selector, limit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CBonusSystemNode::getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
|
||||
{
|
||||
FOREACH_CONST_PARENT(p)
|
||||
@ -273,76 +362,6 @@ void CBonusSystemNode::getAllBonuses(BonusList &out, const CSelector &selector,
|
||||
out.limit(*this);
|
||||
}
|
||||
|
||||
bool CBonusSystemNode::hasBonusFrom(ui8 source, ui32 sourceID) const
|
||||
{
|
||||
return hasBonus(Selector::source(source,sourceID));
|
||||
}
|
||||
|
||||
int CBonusSystemNode::MoraleVal() const
|
||||
{
|
||||
if(hasBonusOfType(Bonus::NON_LIVING) || hasBonusOfType(Bonus::UNDEAD) ||
|
||||
hasBonusOfType(Bonus::NO_MORALE) || hasBonusOfType(Bonus::SIEGE_WEAPON))
|
||||
return 0;
|
||||
|
||||
int ret = valOfBonuses(Selector::type(Bonus::MORALE));
|
||||
|
||||
if(hasBonusOfType(Bonus::SELF_MORALE)) //eg. minotaur
|
||||
amax(ret, +1);
|
||||
|
||||
return abetw(ret, -3, +3);
|
||||
}
|
||||
|
||||
int CBonusSystemNode::LuckVal() const
|
||||
{
|
||||
if(hasBonusOfType(Bonus::NO_LUCK))
|
||||
return 0;
|
||||
|
||||
int ret = valOfBonuses(Selector::type(Bonus::LUCK));
|
||||
|
||||
if(hasBonusOfType(Bonus::SELF_LUCK)) //eg. halfling
|
||||
amax(ret, +1);
|
||||
|
||||
return abetw(ret, -3, +3);
|
||||
}
|
||||
|
||||
si32 CBonusSystemNode::Attack() const
|
||||
{
|
||||
si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK);
|
||||
|
||||
if(int frenzyPower = valOfBonuses(Bonus::IN_FRENZY)) //frenzy for attacker
|
||||
{
|
||||
ret += frenzyPower * Defense(false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
si32 CBonusSystemNode::Defense(bool withFrenzy /*= true*/) const
|
||||
{
|
||||
si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE);
|
||||
|
||||
if(withFrenzy && hasBonusOfType(Bonus::IN_FRENZY)) //frenzy for defender
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ui16 CBonusSystemNode::MaxHealth() const
|
||||
{
|
||||
return valOfBonuses(Bonus::STACK_HEALTH);
|
||||
}
|
||||
|
||||
ui32 CBonusSystemNode::getMinDamage() const
|
||||
{
|
||||
return valOfBonuses(Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 0) || Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 1));
|
||||
}
|
||||
ui32 CBonusSystemNode::getMaxDamage() const
|
||||
{
|
||||
return valOfBonuses(Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 0) || Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 2));
|
||||
}
|
||||
|
||||
CBonusSystemNode::CBonusSystemNode()
|
||||
{
|
||||
nodeType = UNKNOWN;
|
||||
|
@ -369,7 +369,47 @@ public:
|
||||
{}
|
||||
};
|
||||
|
||||
class DLL_EXPORT CBonusSystemNode
|
||||
class DLL_EXPORT IBonusBearer
|
||||
{
|
||||
public:
|
||||
virtual void getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const = 0;
|
||||
|
||||
//new bonusing node interface
|
||||
// * selector is predicate that tests if HeroBonus matches our criteria
|
||||
// * root is node on which call was made (NULL will be replaced with this)
|
||||
//interface
|
||||
void getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const; //as above but without duplicates
|
||||
void getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root = NULL) const;
|
||||
void getModifiersWDescr(TModDescr &out, const CSelector &selector) const; //out: pairs<modifier value, modifier description>
|
||||
int getBonusesCount(const CSelector &selector) const;
|
||||
int valOfBonuses(const CSelector &selector) const;
|
||||
bool hasBonus(const CSelector &selector) const;
|
||||
BonusList getBonuses(const CSelector &selector, const CSelector &limit) const;
|
||||
BonusList getBonuses(const CSelector &selector) const;
|
||||
|
||||
//legacy interface
|
||||
int valOfBonuses(Bonus::BonusType type, const CSelector &selector) const;
|
||||
int valOfBonuses(Bonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then anyt;
|
||||
bool hasBonusOfType(Bonus::BonusType type, int subtype = -1) const;//determines if hero has a bonus of given type (and optionally subtype)
|
||||
bool hasBonusFrom(ui8 source, ui32 sourceID) const;
|
||||
void getModifiersWDescr( TModDescr &out, Bonus::BonusType type, int subtype = -1 ) const; //out: pairs<modifier value, modifier description>
|
||||
int getBonusesCount(int from, int id) const;
|
||||
|
||||
//various hlp functions for non-trivial values
|
||||
ui32 getMinDamage() const; //used for stacks and creatures only
|
||||
ui32 getMaxDamage() const;
|
||||
int MoraleVal() const; //range [-3, +3]
|
||||
int LuckVal() const; //range [-3, +3]
|
||||
si32 Attack() const; //get attack of stack with all modificators
|
||||
si32 Defense(bool withFrenzy = true) const; //get defense of stack with all modificators
|
||||
ui16 MaxHealth() const; //get max HP of stack with all modifiers
|
||||
|
||||
si32 manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
|
||||
int getPrimSkillLevel(int id) const; //0-attack, 1-defence, 2-spell power, 3-knowledge
|
||||
|
||||
};
|
||||
|
||||
class DLL_EXPORT CBonusSystemNode : public IBonusBearer
|
||||
{
|
||||
public:
|
||||
BonusList bonuses; //wielded bonuses (local or up-propagated here)
|
||||
@ -384,39 +424,11 @@ public:
|
||||
CBonusSystemNode();
|
||||
virtual ~CBonusSystemNode();
|
||||
|
||||
//new bonusing node interface
|
||||
// * selector is predicate that tests if HeroBonus matches our criteria
|
||||
// * root is node on which call was made (NULL will be replaced with this)
|
||||
//interface
|
||||
void getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const;
|
||||
void getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const; //as above but without duplicates
|
||||
void getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root = NULL) const;
|
||||
void getModifiersWDescr(TModDescr &out, const CSelector &selector) const; //out: pairs<modifier value, modifier description>
|
||||
int getBonusesCount(const CSelector &selector) const;
|
||||
int valOfBonuses(const CSelector &selector) const;
|
||||
bool hasBonus(const CSelector &selector) const;
|
||||
BonusList getBonuses(const CSelector &selector, const CSelector &limit) const;
|
||||
BonusList getBonuses(const CSelector &selector) const;
|
||||
|
||||
void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from),
|
||||
|
||||
//legacy interface
|
||||
int valOfBonuses(Bonus::BonusType type, const CSelector &selector) const;
|
||||
int valOfBonuses(Bonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then anyt;
|
||||
bool hasBonusOfType(Bonus::BonusType type, int subtype = -1) const;//determines if hero has a bonus of given type (and optionally subtype)
|
||||
bool hasBonusFrom(ui8 source, ui32 sourceID) const;
|
||||
void getModifiersWDescr( TModDescr &out, Bonus::BonusType type, int subtype = -1 ) const; //out: pairs<modifier value, modifier description>
|
||||
int getBonusesCount(int from, int id) const;
|
||||
ui32 getMinDamage() const; //used for stacks and creatures only
|
||||
ui32 getMaxDamage() const;
|
||||
|
||||
int MoraleVal() const; //range [-3, +3]
|
||||
int LuckVal() const; //range [-3, +3]
|
||||
si32 Attack() const; //get attack of stack with all modificators
|
||||
si32 Defense(bool withFrenzy = true) const; //get defense of stack with all modificators
|
||||
ui16 MaxHealth() const; //get max HP of stack with all modifiers
|
||||
|
||||
|
||||
const Bonus *getBonus(const CSelector &selector) const;
|
||||
|
||||
//non-const interface
|
||||
void getParents(TNodes &out); //retrieves list of parent nodes (nodes to inherit bonuses from)
|
||||
void getRedParents(TNodes &out); //retrieves list of red parent nodes (nodes bonuses propagate from)
|
||||
|
@ -2578,7 +2578,7 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
|
||||
// if (src.slot >= 19 && dst.slot >= 19 && src.slot < dst.slot)
|
||||
// dst.slot--;
|
||||
|
||||
if (src.slot == dst.slot)
|
||||
if (src.slot == dst.slot && src.hero == dst.hero)
|
||||
COMPLAIN_RET("Won't move artifact: Dest same as source!");
|
||||
|
||||
//moving art to backpack is always allowed (we've ruled out exceptions)
|
||||
|
Reference in New Issue
Block a user