mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Merge pull request #183 from vmarkovtsev/issue/1989
Fix 1989 cavaliers -> champions in stables
This commit is contained in:
@@ -23,13 +23,13 @@
|
|||||||
|
|
||||||
bool CRewardLimiter::heroAllowed(const CGHeroInstance * hero) const
|
bool CRewardLimiter::heroAllowed(const CGHeroInstance * hero) const
|
||||||
{
|
{
|
||||||
if (dayOfWeek != 0)
|
if(dayOfWeek != 0)
|
||||||
{
|
{
|
||||||
if (IObjectInterface::cb->getDate(Date::DAY_OF_WEEK) != dayOfWeek)
|
if (IObjectInterface::cb->getDate(Date::DAY_OF_WEEK) != dayOfWeek)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto & reqStack : creatures)
|
for(auto & reqStack : creatures)
|
||||||
{
|
{
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
for (auto slot : hero->Slots())
|
for (auto slot : hero->Slots())
|
||||||
@@ -42,25 +42,25 @@ bool CRewardLimiter::heroAllowed(const CGHeroInstance * hero) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IObjectInterface::cb->getPlayer(hero->tempOwner)->resources.canAfford(resources))
|
if(!IObjectInterface::cb->getPlayer(hero->tempOwner)->resources.canAfford(resources))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (minLevel > hero->level)
|
if(minLevel > hero->level)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (size_t i=0; i<primary.size(); i++)
|
for(size_t i=0; i<primary.size(); i++)
|
||||||
{
|
{
|
||||||
if (primary[i] > hero->getPrimSkillLevel(PrimarySkill::PrimarySkill(i)))
|
if (primary[i] > hero->getPrimSkillLevel(PrimarySkill::PrimarySkill(i)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto & skill : secondary)
|
for(auto & skill : secondary)
|
||||||
{
|
{
|
||||||
if (skill.second > hero->getSecSkillLevel(skill.first))
|
if (skill.second > hero->getSecSkillLevel(skill.first))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto & art : artifacts)
|
for(auto & art : artifacts)
|
||||||
{
|
{
|
||||||
if (!hero->hasArt(art))
|
if (!hero->hasArt(art))
|
||||||
return false;
|
return false;
|
||||||
@@ -73,11 +73,11 @@ std::vector<ui32> CRewardableObject::getAvailableRewards(const CGHeroInstance *
|
|||||||
{
|
{
|
||||||
std::vector<ui32> ret;
|
std::vector<ui32> ret;
|
||||||
|
|
||||||
for (size_t i=0; i<info.size(); i++)
|
for(size_t i=0; i<info.size(); i++)
|
||||||
{
|
{
|
||||||
const CVisitInfo & visit = info[i];
|
const CVisitInfo & visit = info[i];
|
||||||
|
|
||||||
if ((visit.limiter.numOfGrants == 0 || visit.numOfGrants < visit.limiter.numOfGrants) // reward has unlimited uses or some are still available
|
if((visit.limiter.numOfGrants == 0 || visit.numOfGrants < visit.limiter.numOfGrants) // reward has unlimited uses or some are still available
|
||||||
&& visit.limiter.heroAllowed(hero))
|
&& visit.limiter.heroAllowed(hero))
|
||||||
{
|
{
|
||||||
logGlobal->debugStream() << "Reward " << i << " is allowed";
|
logGlobal->debugStream() << "Reward " << i << " is allowed";
|
||||||
@@ -87,19 +87,25 @@ std::vector<ui32> CRewardableObject::getAvailableRewards(const CGHeroInstance *
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CVisitInfo CRewardableObject::getVisitInfo(int index, const CGHeroInstance *) const
|
||||||
|
{
|
||||||
|
return info[index];
|
||||||
|
}
|
||||||
|
|
||||||
void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
|
void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
|
||||||
{
|
{
|
||||||
auto grantRewardWithMessage = [&](int index) -> void
|
auto grantRewardWithMessage = [&](int index) -> void
|
||||||
{
|
{
|
||||||
logGlobal->debugStream() << "Granting reward " << index << ". Message says: " << info[index].message.toString();
|
auto vi = getVisitInfo(index, h);
|
||||||
|
logGlobal->debugStream() << "Granting reward " << index << ". Message says: " << vi.message.toString();
|
||||||
// show message only if it is not empty
|
// show message only if it is not empty
|
||||||
if (!info[index].message.toString().empty())
|
if (!vi.message.toString().empty())
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = h->tempOwner;
|
iw.player = h->tempOwner;
|
||||||
iw.soundID = soundID;
|
iw.soundID = soundID;
|
||||||
iw.text = info[index].message;
|
iw.text = vi.message;
|
||||||
info[index].reward.loadComponents(iw.components, h);
|
vi.reward.loadComponents(iw.components, h);
|
||||||
cb->showInfoDialog(&iw);
|
cb->showInfoDialog(&iw);
|
||||||
}
|
}
|
||||||
// grant reward afterwards. Note that it may remove object
|
// grant reward afterwards. Note that it may remove object
|
||||||
@@ -112,11 +118,11 @@ void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
|
|||||||
sd.soundID = soundID;
|
sd.soundID = soundID;
|
||||||
sd.text = onSelect;
|
sd.text = onSelect;
|
||||||
for (auto index : rewards)
|
for (auto index : rewards)
|
||||||
sd.components.push_back(info[index].reward.getDisplayedComponent(h));
|
sd.components.push_back(getVisitInfo(index, h).reward.getDisplayedComponent(h));
|
||||||
cb->showBlockingDialog(&sd);
|
cb->showBlockingDialog(&sd);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!wasVisited(h))
|
if(!wasVisited(h))
|
||||||
{
|
{
|
||||||
auto rewards = getAvailableRewards(h);
|
auto rewards = getAvailableRewards(h);
|
||||||
logGlobal->debugStream() << "Visiting object with " << rewards.size() << " possible rewards";
|
logGlobal->debugStream() << "Visiting object with " << rewards.size() << " possible rewards";
|
||||||
@@ -175,15 +181,15 @@ void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
|
|||||||
|
|
||||||
void CRewardableObject::heroLevelUpDone(const CGHeroInstance *hero) const
|
void CRewardableObject::heroLevelUpDone(const CGHeroInstance *hero) const
|
||||||
{
|
{
|
||||||
grantRewardAfterLevelup(info[selectedReward], hero);
|
grantRewardAfterLevelup(getVisitInfo(selectedReward, hero), hero);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRewardableObject::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
|
void CRewardableObject::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
|
||||||
{
|
{
|
||||||
if (answer == 0)
|
if(answer == 0)
|
||||||
return; // player refused
|
return; // player refused
|
||||||
|
|
||||||
if (answer > 0 && answer-1 < info.size())
|
if(answer > 0 && answer-1 < info.size())
|
||||||
{
|
{
|
||||||
auto list = getAvailableRewards(hero);
|
auto list = getAvailableRewards(hero);
|
||||||
grantReward(list[answer - 1], hero);
|
grantReward(list[answer - 1], hero);
|
||||||
@@ -205,7 +211,7 @@ void CRewardableObject::grantReward(ui32 rewardID, const CGHeroInstance * hero)
|
|||||||
cb->sendAndApply(&cov);
|
cb->sendAndApply(&cov);
|
||||||
cb->setObjProperty(id, ObjProperty::REWARD_SELECT, rewardID);
|
cb->setObjProperty(id, ObjProperty::REWARD_SELECT, rewardID);
|
||||||
|
|
||||||
grantRewardBeforeLevelup(info[rewardID], hero);
|
grantRewardBeforeLevelup(getVisitInfo(rewardID, hero), hero);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRewardableObject::grantRewardBeforeLevelup(const CVisitInfo & info, const CGHeroInstance * hero) const
|
void CRewardableObject::grantRewardBeforeLevelup(const CVisitInfo & info, const CGHeroInstance * hero) const
|
||||||
@@ -218,7 +224,7 @@ void CRewardableObject::grantRewardBeforeLevelup(const CVisitInfo & info, const
|
|||||||
|
|
||||||
cb->giveResources(hero->tempOwner, info.reward.resources);
|
cb->giveResources(hero->tempOwner, info.reward.resources);
|
||||||
|
|
||||||
for (auto & entry : info.reward.secondary)
|
for(auto & entry : info.reward.secondary)
|
||||||
{
|
{
|
||||||
int current = hero->getSecSkillLevel(entry.first);
|
int current = hero->getSecSkillLevel(entry.first);
|
||||||
if( (current != 0 && current < entry.second) ||
|
if( (current != 0 && current < entry.second) ||
|
||||||
@@ -235,11 +241,11 @@ void CRewardableObject::grantRewardBeforeLevelup(const CVisitInfo & info, const
|
|||||||
si64 expToGive = 0;
|
si64 expToGive = 0;
|
||||||
expToGive += VLC->heroh->reqExp(hero->level+info.reward.gainedLevels) - VLC->heroh->reqExp(hero->level);
|
expToGive += VLC->heroh->reqExp(hero->level+info.reward.gainedLevels) - VLC->heroh->reqExp(hero->level);
|
||||||
expToGive += hero->calculateXp(info.reward.gainedExp);
|
expToGive += hero->calculateXp(info.reward.gainedExp);
|
||||||
if (expToGive)
|
if(expToGive)
|
||||||
cb->changePrimSkill(hero, PrimarySkill::EXPERIENCE, expToGive);
|
cb->changePrimSkill(hero, PrimarySkill::EXPERIENCE, expToGive);
|
||||||
|
|
||||||
// hero is not blocked by levelup dialog - grant remainer immediately
|
// hero is not blocked by levelup dialog - grant remainer immediately
|
||||||
if (!cb->isVisitCoveredByAnotherQuery(this, hero))
|
if(!cb->isVisitCoveredByAnotherQuery(this, hero))
|
||||||
{
|
{
|
||||||
grantRewardAfterLevelup(info, hero);
|
grantRewardAfterLevelup(info, hero);
|
||||||
}
|
}
|
||||||
@@ -247,7 +253,7 @@ void CRewardableObject::grantRewardBeforeLevelup(const CVisitInfo & info, const
|
|||||||
|
|
||||||
void CRewardableObject::grantRewardAfterLevelup(const CVisitInfo & info, const CGHeroInstance * hero) const
|
void CRewardableObject::grantRewardAfterLevelup(const CVisitInfo & info, const CGHeroInstance * hero) const
|
||||||
{
|
{
|
||||||
if (info.reward.manaDiff || info.reward.manaPercentage >= 0)
|
if(info.reward.manaDiff || info.reward.manaPercentage >= 0)
|
||||||
{
|
{
|
||||||
si32 mana = hero->mana;
|
si32 mana = hero->mana;
|
||||||
if (info.reward.manaPercentage >= 0)
|
if (info.reward.manaPercentage >= 0)
|
||||||
@@ -269,7 +275,7 @@ void CRewardableObject::grantRewardAfterLevelup(const CVisitInfo & info, const C
|
|||||||
cb->setMovePoints(&smp);
|
cb->setMovePoints(&smp);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const Bonus & bonus : info.reward.bonuses)
|
for(const Bonus & bonus : info.reward.bonuses)
|
||||||
{
|
{
|
||||||
assert(bonus.source == Bonus::OBJECT);
|
assert(bonus.source == Bonus::OBJECT);
|
||||||
assert(bonus.sid == ID);
|
assert(bonus.sid == ID);
|
||||||
@@ -280,16 +286,16 @@ void CRewardableObject::grantRewardAfterLevelup(const CVisitInfo & info, const C
|
|||||||
cb->giveHeroBonus(&gb);
|
cb->giveHeroBonus(&gb);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ArtifactID art : info.reward.artifacts)
|
for(ArtifactID art : info.reward.artifacts)
|
||||||
cb->giveHeroNewArtifact(hero, VLC->arth->artifacts[art],ArtifactPosition::FIRST_AVAILABLE);
|
cb->giveHeroNewArtifact(hero, VLC->arth->artifacts[art],ArtifactPosition::FIRST_AVAILABLE);
|
||||||
|
|
||||||
if (!info.reward.spells.empty())
|
if(!info.reward.spells.empty())
|
||||||
{
|
{
|
||||||
std::set<SpellID> spellsToGive(info.reward.spells.begin(), info.reward.spells.end());
|
std::set<SpellID> spellsToGive(info.reward.spells.begin(), info.reward.spells.end());
|
||||||
cb->changeSpells(hero, true, spellsToGive);
|
cb->changeSpells(hero, true, spellsToGive);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info.reward.creatures.empty())
|
if(!info.reward.creatures.empty())
|
||||||
{
|
{
|
||||||
CCreatureSet creatures;
|
CCreatureSet creatures;
|
||||||
for (auto & crea : info.reward.creatures)
|
for (auto & crea : info.reward.creatures)
|
||||||
@@ -300,11 +306,11 @@ void CRewardableObject::grantRewardAfterLevelup(const CVisitInfo & info, const C
|
|||||||
|
|
||||||
onRewardGiven(hero);
|
onRewardGiven(hero);
|
||||||
|
|
||||||
if (info.reward.removeObject)
|
if(info.reward.removeObject)
|
||||||
cb->removeObject(this);
|
cb->removeObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRewardableObject::wasVisited (PlayerColor player) const
|
bool CRewardableObject::wasVisited(PlayerColor player) const
|
||||||
{
|
{
|
||||||
switch (visitMode)
|
switch (visitMode)
|
||||||
{
|
{
|
||||||
@@ -326,7 +332,7 @@ bool CRewardableObject::wasVisited (PlayerColor player) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRewardableObject::wasVisited (const CGHeroInstance * h) const
|
bool CRewardableObject::wasVisited(const CGHeroInstance * h) const
|
||||||
{
|
{
|
||||||
switch (visitMode)
|
switch (visitMode)
|
||||||
{
|
{
|
||||||
@@ -733,30 +739,76 @@ void CGBonusingObject::initObj()
|
|||||||
break;
|
break;
|
||||||
case Obj::STABLES:
|
case Obj::STABLES:
|
||||||
configureMessage(info[0], 137, 136, soundBase::STORE);
|
configureMessage(info[0], 137, 136, soundBase::STORE);
|
||||||
|
|
||||||
configureBonusDuration(info[0], Bonus::ONE_WEEK, Bonus::LAND_MOVEMENT, 400, 0);
|
configureBonusDuration(info[0], Bonus::ONE_WEEK, Bonus::LAND_MOVEMENT, 400, 0);
|
||||||
info[0].reward.movePoints = 400;
|
info[0].reward.movePoints = 400;
|
||||||
//TODO: upgrade champions to cavaliers
|
|
||||||
/*
|
|
||||||
bool someUpgradeDone = false;
|
|
||||||
|
|
||||||
for (auto i = h->Slots().begin(); i != h->Slots().end(); ++i)
|
|
||||||
{
|
|
||||||
if(i->second->type->idNumber == CreatureID::CAVALIER)
|
|
||||||
{
|
|
||||||
cb->changeStackType(StackLocation(h, i->first), VLC->creh->creatures[CreatureID::CHAMPION]);
|
|
||||||
someUpgradeDone = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (someUpgradeDone)
|
|
||||||
{
|
|
||||||
grantMessage.addTxt(MetaString::ADVOB_TXT, 138);
|
|
||||||
iw.components.push_back(Component(Component::CREATURE,11,0,1));
|
|
||||||
}*/
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CVisitInfo CGBonusingObject::getVisitInfo(int index, const CGHeroInstance *h) const
|
||||||
|
{
|
||||||
|
if(ID == Obj::STABLES)
|
||||||
|
{
|
||||||
|
assert(index == 0);
|
||||||
|
for(auto& slot : h->Slots())
|
||||||
|
{
|
||||||
|
if(slot.second->type->idNumber == CreatureID::CAVALIER)
|
||||||
|
{
|
||||||
|
CVisitInfo vi(info[0]);
|
||||||
|
vi.message.clear();
|
||||||
|
vi.message.addTxt(MetaString::ADVOB_TXT, 138);
|
||||||
|
vi.reward.extraComponents.push_back(Component(
|
||||||
|
Component::CREATURE, CreatureID::CHAMPION, 0, 1));
|
||||||
|
return std::move(vi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return info[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGBonusingObject::onHeroVisit(const CGHeroInstance *h) const
|
||||||
|
{
|
||||||
|
CRewardableObject::onHeroVisit(h);
|
||||||
|
if(ID == Obj::STABLES)
|
||||||
|
{
|
||||||
|
//regardless of whether this hero visited stables or not, cavaliers must be upgraded
|
||||||
|
for(auto& slot : h->Slots())
|
||||||
|
{
|
||||||
|
if(slot.second->type->idNumber == CreatureID::CAVALIER)
|
||||||
|
{
|
||||||
|
cb->changeStackType(StackLocation(h, slot.first),
|
||||||
|
VLC->creh->creatures[CreatureID::CHAMPION]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGBonusingObject::wasVisited(const CGHeroInstance * h) const
|
||||||
|
{
|
||||||
|
if(ID == Obj::STABLES)
|
||||||
|
{
|
||||||
|
for(auto& slot : h->Slots())
|
||||||
|
{
|
||||||
|
if(slot.second->type->idNumber == CreatureID::CAVALIER)
|
||||||
|
{
|
||||||
|
// always display the reward message if the hero got cavaliers
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CRewardableObject::wasVisited(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGBonusingObject::grantReward(ui32 rewardID, const CGHeroInstance * hero) const
|
||||||
|
{
|
||||||
|
if(ID == Obj::STABLES && CRewardableObject::wasVisited(hero))
|
||||||
|
{
|
||||||
|
// reward message has been displayed - do not give the actual bonus
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CRewardableObject::grantReward(rewardID, hero);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
CGOnceVisitable::CGOnceVisitable()
|
CGOnceVisitable::CGOnceVisitable()
|
||||||
|
@@ -164,6 +164,7 @@ class DLL_LINKAGE CRewardableObject : public CArmedInstance
|
|||||||
|
|
||||||
/// grants reward to hero
|
/// grants reward to hero
|
||||||
void grantRewardBeforeLevelup(const CVisitInfo & reward, const CGHeroInstance * hero) const;
|
void grantRewardBeforeLevelup(const CVisitInfo & reward, const CGHeroInstance * hero) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// controls selection of reward granted to player
|
/// controls selection of reward granted to player
|
||||||
enum ESelectMode
|
enum ESelectMode
|
||||||
@@ -185,9 +186,11 @@ protected:
|
|||||||
/// filters list of visit info and returns rewards that can be granted to current hero
|
/// filters list of visit info and returns rewards that can be granted to current hero
|
||||||
virtual std::vector<ui32> getAvailableRewards(const CGHeroInstance * hero) const;
|
virtual std::vector<ui32> getAvailableRewards(const CGHeroInstance * hero) const;
|
||||||
|
|
||||||
void grantReward(ui32 rewardID, const CGHeroInstance * hero) const;
|
virtual void grantReward(ui32 rewardID, const CGHeroInstance * hero) const;
|
||||||
|
|
||||||
/// Rewars that can be granted by an object
|
virtual CVisitInfo getVisitInfo(int index, const CGHeroInstance *h) const;
|
||||||
|
|
||||||
|
/// Rewards that can be granted by an object
|
||||||
std::vector<CVisitInfo> info;
|
std::vector<CVisitInfo> info;
|
||||||
|
|
||||||
/// MetaString's that contain text for messages for specific situations
|
/// MetaString's that contain text for messages for specific situations
|
||||||
@@ -216,8 +219,8 @@ public:
|
|||||||
std::string getHoverText(const CGHeroInstance * hero) const override;
|
std::string getHoverText(const CGHeroInstance * hero) const override;
|
||||||
|
|
||||||
/// Visitability checks. Note that hero check includes check for hero owner (returns true if object was visited by player)
|
/// Visitability checks. Note that hero check includes check for hero owner (returns true if object was visited by player)
|
||||||
bool wasVisited (PlayerColor player) const override;
|
bool wasVisited(PlayerColor player) const override;
|
||||||
bool wasVisited (const CGHeroInstance * h) const override;
|
bool wasVisited(const CGHeroInstance * h) const override;
|
||||||
|
|
||||||
/// gives reward to player or ask for choice in case of multiple rewards
|
/// gives reward to player or ask for choice in case of multiple rewards
|
||||||
void onHeroVisit(const CGHeroInstance *h) const override;
|
void onHeroVisit(const CGHeroInstance *h) const override;
|
||||||
@@ -263,11 +266,20 @@ public:
|
|||||||
|
|
||||||
class DLL_LINKAGE CGBonusingObject : public CRewardableObject //objects giving bonuses to luck/morale/movement
|
class DLL_LINKAGE CGBonusingObject : public CRewardableObject //objects giving bonuses to luck/morale/movement
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
CVisitInfo getVisitInfo(int index, const CGHeroInstance *h) const override;
|
||||||
|
|
||||||
|
void grantReward(ui32 rewardID, const CGHeroInstance * hero) const override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void initObj() override;
|
void initObj() override;
|
||||||
|
|
||||||
CGBonusingObject();
|
CGBonusingObject();
|
||||||
|
|
||||||
|
void onHeroVisit(const CGHeroInstance *h) const override;
|
||||||
|
|
||||||
|
bool wasVisited(const CGHeroInstance * h) const override;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & static_cast<CRewardableObject&>(*this);
|
h & static_cast<CRewardableObject&>(*this);
|
||||||
|
Reference in New Issue
Block a user