Преглед изворни кода

Fixed http://bugs.vcmi.eu/view.php?id=2545

AlexVinS пре 9 година
родитељ
комит
4173a5064c
3 измењених фајлова са 43 додато и 9 уклоњено
  1. 33 1
      lib/mapObjects/CGHeroInstance.cpp
  2. 2 0
      lib/mapObjects/CGHeroInstance.h
  3. 8 8
      lib/mapObjects/CGPandoraBox.cpp

+ 33 - 1
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.

+ 2 - 0
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.

+ 8 - 8
lib/mapObjects/CGPandoraBox.cpp

@@ -65,7 +65,7 @@ void CGPandoraBox::giveContentsUpToExp(const CGHeroInstance *h) const
 			break;
 		}
 	}
-	
+
 	std::vector<std::pair<SecondarySkill, ui8>> 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; i<primskills.size(); i++)
 			if(primskills[i])
 				iw.components.push_back(Component(Component::PRIM_SKILL,i,primskills[i],0));
 
 		for(auto abilityData : unpossessedAbilities)
 			iw.components.push_back(Component(Component::SEC_SKILL, abilityData.first, abilityData.second, 0));
-			
+
 		cb->showInfoDialog(&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<SpellID> spellsToGive;	
+		std::set<SpellID> spellsToGive;
 
-		std::vector<ConstTransitivePtr<CSpell> > * 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;
 				}