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

Merge pull request #235 from vcmi/issue/2545

Fixes: http://bugs.vcmi.eu/view.php?id=2545, http://bugs.vcmi.eu/view.php?id=2520
This commit is contained in:
Alexander Shishkin 2016-10-11 22:39:02 +03:00 committed by GitHub
commit bdbbc22c66
5 changed files with 64 additions and 22 deletions

View File

@ -251,18 +251,26 @@ void CBank::doVisit(const CGHeroInstance * hero) const
cb->showInfoDialog(&iw);
}
loot.clear();
iw.components.clear();
iw.text.clear();
if (!bc->spells.empty())
{
std::set<SpellID> spells;
bool noWisdom = false;
for (SpellID spell : bc->spells)
for(const SpellID & spellId : bc->spells)
{
iw.text.addTxt (MetaString::SPELL_NAME, spell);
if (VLC->spellh->objects[spell]->level <= hero->getSecSkillLevel(SecondarySkill::WISDOM) + 2)
const CSpell * spell = spellId.toSpell();
iw.text.addTxt (MetaString::SPELL_NAME, spellId);
if(spell->level <= hero->getSecSkillLevel(SecondarySkill::WISDOM) + 2)
{
spells.insert(spell);
iw.components.push_back(Component (Component::SPELL, spell, 0, 0));
if(hero->canLearnSpell(spell))
{
spells.insert(spellId);
iw.components.push_back(Component (Component::SPELL, spellId, 0, 0));
}
}
else
noWisdom = true;
@ -272,10 +280,14 @@ void CBank::doVisit(const CGHeroInstance * hero) const
iw.text.addTxt (MetaString::ADVOB_TXT, 109); //no spellbook
else if (noWisdom)
iw.text.addTxt (MetaString::ADVOB_TXT, 108); //no expert Wisdom
if (spells.empty())
if(!iw.components.empty() || !iw.text.toString().empty())
cb->showInfoDialog(&iw);
if(!spells.empty())
cb->changeSpells (hero, true, spells);
}
loot.clear();
iw.components.clear();
iw.text.clear();

View File

@ -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.

View File

@ -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.

View File

@ -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;
}

View File

@ -1702,16 +1702,12 @@ void CGSignBottle::serializeJsonOptions(JsonSerializeFormat& handler)
void CGScholar::onHeroVisit( const CGHeroInstance * h ) const
{
EBonusType type = bonusType;
int bid = bonusID;
//check if the bonus if applicable, if not - give primary skill (always possible)
int ssl = h->getSecSkillLevel(SecondarySkill(bid)); //current sec skill level, used if bonusType == 1
if((type == SECONDARY_SKILL
&& ((ssl == 3) || (!ssl && !h->canLearnSkill()))) ////hero already has expert level in the skill or (don't know skill and doesn't have free slot)
|| (type == SPELL && (!h->getArt(ArtifactPosition::SPELLBOOK) || vstd::contains(h->spells, (ui32) bid)
|| ( SpellID(bid).toSpell()->level > h->getSecSkillLevel(SecondarySkill::WISDOM) + 2)
))) //hero doesn't have a spellbook or already knows the spell or doesn't have Wisdom
if((type == SECONDARY_SKILL && ((ssl == 3) || (!ssl && !h->canLearnSkill()))) ////hero already has expert level in the skill or (don't know skill and doesn't have free slot)
|| (type == SPELL && !h->canLearnSpell(SpellID(bid).toSpell())))
{
type = PRIM_SKILL;
bid = CRandomGenerator::getDefault().nextInt(GameConstants::PRIMARY_SKILLS - 1);