bool CCreatureSet::canBeMergedWith(const CCreatureSet &cs, bool allowMergingStacks) const { if(!allowMergingStacks) { int freeSlots = stacksCount() - GameConstants::ARMY_SIZE; std::set<const CCreature*> cresToAdd; for(TSlots::const_iterator i = cs.stacks.begin(); i != cs.stacks.end(); i++) { SlotID dest = getSlotFor(i->second->type); if(!dest.validSlot() || hasStackAtSlot(dest)) cresToAdd.insert(i->second->type); } return cresToAdd.size() <= freeSlots; } else { CCreatureSet cres; //get types of creatures that need their own slot for(TSlots::const_iterator i = cs.stacks.begin(); i != cs.stacks.end(); i++) cres.addToSlot(i->first, i->second->type->idNumber, 1, true); SlotID j; for(TSlots::const_iterator i = stacks.begin(); i != stacks.end(); i++) { if ((j = cres.getSlotFor(i->second->type)).validSlot()) cres.addToSlot(j, i->second->type->idNumber, 1, true); //merge if possible else return false; //no place found } return true; //all stacks found their slots } }
void CRewardableObject::grantRewardAfterLevelup(const CVisitInfo & info, const CGHeroInstance * hero) const { if(info.reward.manaDiff || info.reward.manaPercentage >= 0) { si32 mana = hero->mana; if (info.reward.manaPercentage >= 0) mana = hero->manaLimit() * info.reward.manaPercentage / 100; cb->setManaPoints(hero->id, mana + info.reward.manaDiff); } if(info.reward.movePoints || info.reward.movePercentage >= 0) { SetMovePoints smp; smp.hid = hero->id; smp.val = hero->movement; if (info.reward.movePercentage >= 0) // percent from max smp.val = hero->maxMovePoints(hero->boat != nullptr) * info.reward.movePercentage / 100; smp.val = std::max<si32>(0, smp.val + info.reward.movePoints); cb->setMovePoints(&smp); } for(const Bonus & bonus : info.reward.bonuses) { assert(bonus.source == Bonus::OBJECT); assert(bonus.sid == ID); GiveBonus gb; gb.who = GiveBonus::HERO; gb.bonus = bonus; gb.id = hero->id.getNum(); cb->giveHeroBonus(&gb); } for(ArtifactID art : info.reward.artifacts) cb->giveHeroNewArtifact(hero, VLC->arth->artifacts[art],ArtifactPosition::FIRST_AVAILABLE); if(!info.reward.spells.empty()) { std::set<SpellID> spellsToGive(info.reward.spells.begin(), info.reward.spells.end()); cb->changeSpells(hero, true, spellsToGive); } if(!info.reward.creatures.empty()) { CCreatureSet creatures; for (auto & crea : info.reward.creatures) creatures.addToSlot(creatures.getFreeSlot(), new CStackInstance(crea.type, crea.count)); cb->giveCreatures(this, hero, creatures, false); } onRewardGiven(hero); if(info.reward.removeObject) cb->removeObject(this); }
void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward { switch (rewardType) { case EXPERIENCE: { TExpType expVal = h->calculateXp(rVal); cb->changePrimSkill(h, PrimarySkill::EXPERIENCE, expVal, false); break; } case MANA_POINTS: { cb->setManaPoints(h->id, h->mana+rVal); break; } case MORALE_BONUS: case LUCK_BONUS: { Bonus hb(Bonus::ONE_WEEK, (rewardType == 3 ? Bonus::MORALE : Bonus::LUCK), Bonus::OBJECT, rVal, h->id.getNum(), "", -1); GiveBonus gb; gb.id = h->id.getNum(); gb.bonus = hb; cb->giveHeroBonus(&gb); } break; case RESOURCES: cb->giveResource(h->getOwner(), static_cast<Res::ERes>(rID), rVal); break; case PRIMARY_SKILL: cb->changePrimSkill(h, static_cast<PrimarySkill::PrimarySkill>(rID), rVal, false); break; case SECONDARY_SKILL: cb->changeSecSkill(h, SecondarySkill(rID), rVal, false); break; case ARTIFACT: cb->giveHeroNewArtifact(h, VLC->arth->artifacts[rID],ArtifactPosition::FIRST_AVAILABLE); break; case SPELL: { std::set<SpellID> spell; spell.insert (SpellID(rID)); cb->changeSpells(h, true, spell); } break; case CREATURE: { CCreatureSet creatures; creatures.setCreature(SlotID(0), CreatureID(rID), rVal); cb->giveCreatures(this, h, creatures, false); } break; default: break; } }