diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 729fc5b52..068363de4 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -976,7 +976,7 @@ bool CGHeroInstance::canCastThisSpell(const CSpell * spell) const { const bool isAllowed = IObjectInterface::cb->isAllowed(0, spell->id); - const bool inSpellBook = vstd::contains(spells, spell->id) && nullptr != getArt(ArtifactPosition::SPELLBOOK); + const bool inSpellBook = vstd::contains(spells, spell->id) && hasSpellbook(); const bool specificBonus = hasBonusOfType(Bonus::SPELL, spell->id); bool schoolBonus = false; @@ -1013,6 +1013,38 @@ bool CGHeroInstance::canCastThisSpell(const CSpell * spell) const } } +bool CGHeroInstance::canLearnSpell(const CSpell * spell) const +{ + if(!hasSpellbook()) + return false; + + if(spell->level > getSecSkillLevel(SecondarySkill::WISDOM) + 2) //not enough wisdom + return false; + + if(vstd::contains(spells, spell->id))//already known + return false; + + if(spell->isSpecialSpell()) + { + logGlobal->warn("Hero %s try to learn special spell %s", nodeName(), spell->name); + return false;//special spells can not be learned + } + + if(spell->isCreatureAbility()) + { + logGlobal->warn("Hero %s try to learn creature spell %s", nodeName(), spell->name); + return false;//creature abilities can not be learned + } + + if(IObjectInterface::cb->isAllowed(0, spell->id)) + { + logGlobal->warn("Hero %s try to learn banned spell %s", nodeName(), spell->name); + return false;//banned spells should not be learned + } + + return true; +} + /** * Calculates what creatures and how many to be raised from a battle. * @param battleResult The results of the battle. diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index dce645af4..6cf2552a9 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -157,6 +157,8 @@ public: 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 + bool canLearnSpell(const CSpell * spell) const; + // ----- primary and secondary skill, experience, level handling ----- /// Returns true if hero has lower level than should upon his experience. diff --git a/lib/mapObjects/CGPandoraBox.cpp b/lib/mapObjects/CGPandoraBox.cpp index b10e818e3..ab5b2e1b9 100644 --- a/lib/mapObjects/CGPandoraBox.cpp +++ b/lib/mapObjects/CGPandoraBox.cpp @@ -65,7 +65,7 @@ void CGPandoraBox::giveContentsUpToExp(const CGHeroInstance *h) const break; } } - + std::vector> unpossessedAbilities; //ability + ability level int abilitiesRequiringSlot = 0; @@ -90,17 +90,17 @@ void CGPandoraBox::giveContentsUpToExp(const CGHeroInstance *h) const //getText(iw,afterBattle,175,h); //wtf? iw.text.addTxt(MetaString::ADVOB_TXT, 175); //%s learns something iw.text.addReplacement(h->name); - + if(expVal) iw.components.push_back(Component(Component::EXPERIENCE,0,expVal,0)); - + for(int i=0; ishowInfoDialog(&iw); //give sec skills @@ -138,9 +138,8 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const //TODO: reuse this code for Scholar skill if(spells.size()) { - std::set spellsToGive; + std::set spellsToGive; - std::vector > * sp = &VLC->spellh->objects; auto i = spells.cbegin(); while (i != spells.cend()) { @@ -150,12 +149,13 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const for (; i != spells.cend(); i++) { - if ((*sp)[*i]->level <= h->getSecSkillLevel(SecondarySkill::WISDOM) + 2) //enough wisdom + const CSpell * sp = (*i).toSpell(); + if(h->canLearnSpell(sp)) { iw.components.push_back(Component(Component::SPELL, *i, 0, 0)); spellsToGive.insert(*i); } - if (spellsToGive.size() == 8) //display up to 8 spells at once + if(spellsToGive.size() == 8) //display up to 8 spells at once { break; }