mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-03 00:46:55 +02:00
Various fixes and improvements around kill hero and kill monster quests. A few minor unrelated fixes.
This commit is contained in:
@ -1116,6 +1116,7 @@ void CGHeroInstance::initObj()
|
||||
UpdateSpeciality();
|
||||
|
||||
mana = manaLimit(); //after all bonuses are taken into account, make sure this line is the last one
|
||||
type->name = name;
|
||||
}
|
||||
void CGHeroInstance::UpdateSpeciality()
|
||||
{
|
||||
@ -3871,12 +3872,10 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
|
||||
{
|
||||
case MISSION_NONE:
|
||||
return true;
|
||||
break;
|
||||
case MISSION_LEVEL:
|
||||
if (m13489val <= h->level)
|
||||
return true;
|
||||
return false;
|
||||
break;
|
||||
case MISSION_PRIMARY_STAT:
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
@ -3884,17 +3883,11 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case MISSION_KILL_HERO:
|
||||
if (h->cb->gameState()->map->heroesToBeat[m13489val]->tempOwner < PLAYER_LIMIT)
|
||||
return false; //if the pointer is not NULL
|
||||
return true;
|
||||
break;
|
||||
case MISSION_KILL_CREATURE:
|
||||
if (h->cb->gameState()->map->monsters[m13489val]->pos == int3(-1,-1,-1))
|
||||
if (!h->cb->getObjByQuestIdentifier(m13489val))
|
||||
return true;
|
||||
return false;
|
||||
break;
|
||||
case MISSION_ART:
|
||||
for (int i = 0; i < m5arts.size(); ++i)
|
||||
{
|
||||
@ -3903,7 +3896,6 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
|
||||
return false; //if the artifact was not found
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case MISSION_ARMY:
|
||||
{
|
||||
std::vector<CStackBasicDescriptor>::const_iterator cre;
|
||||
@ -3921,7 +3913,6 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
|
||||
}
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case MISSION_RESOURCES:
|
||||
for (int i = 0; i < 7; ++i) //including Mithril ?
|
||||
{ //Quest has no direct access to callback
|
||||
@ -3929,17 +3920,14 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case MISSION_HERO:
|
||||
if (m13489val == h->type->ID)
|
||||
return true;
|
||||
return false;
|
||||
break;
|
||||
case MISSION_PLAYER:
|
||||
if (m13489val == h->getOwner())
|
||||
return true;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -3958,6 +3946,17 @@ void CGSeerHut::initObj()
|
||||
nextVisitText = VLC->generaltexth->quests[missionType-1][1][textOption];
|
||||
completedText = VLC->generaltexth->quests[missionType-1][2][textOption];
|
||||
}
|
||||
|
||||
if(missionType == MISSION_KILL_CREATURE)
|
||||
{
|
||||
stackToKill = getCreatureToKill(false)->getStack(0);
|
||||
stackDirection = checkDirection();
|
||||
}
|
||||
else if(missionType == MISSION_KILL_HERO)
|
||||
{
|
||||
heroName = getHeroToKill(false)->name;
|
||||
heroPortrait = getHeroToKill(false)->portrait;
|
||||
}
|
||||
}
|
||||
else
|
||||
firstVisitText = VLC->generaltexth->seerEmpty[textOption];
|
||||
@ -3989,30 +3988,25 @@ const std::string & CGSeerHut::getHoverText() const
|
||||
ms.addReplacement(m13489val);
|
||||
break;
|
||||
case MISSION_PRIMARY_STAT:
|
||||
{
|
||||
MetaString loot;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (m2stats[i])
|
||||
MetaString loot;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m2stats[i]);
|
||||
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
|
||||
}
|
||||
if (m2stats[i])
|
||||
{
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m2stats[i]);
|
||||
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
|
||||
}
|
||||
}
|
||||
ms.addReplacement(loot.buildList());
|
||||
}
|
||||
ms.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_KILL_HERO:
|
||||
ms.addReplacement(cb->gameState()->map->heroesToBeat[m13489val]->name);
|
||||
break;
|
||||
case MISSION_HERO:
|
||||
ms.addReplacement(VLC->heroh->heroes[m13489val]->name);
|
||||
ms.addReplacement(heroName);
|
||||
break;
|
||||
case MISSION_KILL_CREATURE:
|
||||
{
|
||||
ms.addReplacement(cb->gameState()->map->monsters[m13489val]->getStack(0));
|
||||
}
|
||||
ms.addReplacement(stackToKill);
|
||||
break;
|
||||
case MISSION_ART:
|
||||
{
|
||||
@ -4051,6 +4045,9 @@ const std::string & CGSeerHut::getHoverText() const
|
||||
ms.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_HERO:
|
||||
ms.addReplacement(VLC->heroh->heroes[m13489val]->name);
|
||||
break;
|
||||
case MISSION_PLAYER:
|
||||
ms.addReplacement(VLC->generaltexth->colors[m13489val]);
|
||||
break;
|
||||
@ -4096,7 +4093,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
switch (missionType)
|
||||
{
|
||||
case MISSION_LEVEL:
|
||||
iw.components.push_back (Component (Component::EXPERIENCE, 1, m13489val, 0));
|
||||
iw.components.push_back(Component (Component::EXPERIENCE, 1, m13489val, 0));
|
||||
if (!isCustom)
|
||||
iw.text.addReplacement(m13489val);
|
||||
break;
|
||||
@ -4107,7 +4104,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
if (m2stats[i])
|
||||
{
|
||||
iw.components.push_back (Component (Component::PRIM_SKILL, i, m2stats[i], 0));
|
||||
iw.components.push_back(Component (Component::PRIM_SKILL, i, m2stats[i], 0));
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m2stats[i]);
|
||||
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
|
||||
@ -4118,28 +4115,20 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
}
|
||||
break;
|
||||
case MISSION_KILL_HERO:
|
||||
iw.components.push_back (Component (Component::HERO,
|
||||
cb->gameState()->map->heroesToBeat[m13489val]->type->ID, 0, 0));
|
||||
iw.components.push_back(Component(Component::HERO, heroPortrait, 0, 0));
|
||||
if (!isCustom)
|
||||
iw.text.addReplacement(cb->gameState()->map->heroesToBeat[m13489val]->name);
|
||||
addReplacements(iw.text, firstVisitText);
|
||||
break;
|
||||
case MISSION_HERO:
|
||||
iw.components.push_back (Component (Component::HERO, m13489val, 0, 0));
|
||||
iw.components.push_back(Component (Component::HERO, m13489val, 0, 0));
|
||||
if (!isCustom)
|
||||
iw.text.addReplacement(VLC->heroh->heroes[m13489val]->name);
|
||||
break;
|
||||
case MISSION_KILL_CREATURE:
|
||||
{
|
||||
CStackInstance stack = cb->gameState()->map->monsters[m13489val]->getStack(0);
|
||||
iw.components.push_back (Component(stack));
|
||||
iw.components.push_back(Component(stackToKill));
|
||||
if (!isCustom)
|
||||
{
|
||||
iw.text.addReplacement(stack);
|
||||
if (std::count(firstVisitText.begin(), firstVisitText.end(), '%') == 2) //say where is placed monster
|
||||
{
|
||||
iw.text.addReplacement(VLC->generaltexth->arraytxt[147+checkDirection()]);
|
||||
}
|
||||
}
|
||||
addReplacements(iw.text, firstVisitText);
|
||||
}
|
||||
break;
|
||||
case MISSION_ART:
|
||||
@ -4147,12 +4136,12 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
MetaString loot;
|
||||
for (std::vector<ui16>::const_iterator it = m5arts.begin(); it != m5arts.end(); ++it)
|
||||
{
|
||||
iw.components.push_back (Component (Component::ARTIFACT, *it, 0, 0));
|
||||
iw.components.push_back(Component (Component::ARTIFACT, *it, 0, 0));
|
||||
loot << "%s";
|
||||
loot.addReplacement(MetaString::ART_NAMES, *it);
|
||||
}
|
||||
if (!isCustom)
|
||||
iw.text.addReplacement (loot.buildList());
|
||||
iw.text.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_ARMY:
|
||||
@ -4165,7 +4154,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
loot.addReplacement(*it);
|
||||
}
|
||||
if (!isCustom)
|
||||
iw.text.addReplacement (loot.buildList());
|
||||
iw.text.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_RESOURCES:
|
||||
@ -4175,20 +4164,20 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
if (m7resources[i])
|
||||
{
|
||||
iw.components.push_back (Component (Component::RESOURCE, i, m7resources[i], 0));
|
||||
iw.components.push_back(Component (Component::RESOURCE, i, m7resources[i], 0));
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m7resources[i]);
|
||||
loot.addReplacement(MetaString::RES_NAMES, i);
|
||||
}
|
||||
}
|
||||
if (!isCustom)
|
||||
iw.text.addReplacement (loot.buildList());
|
||||
iw.text.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_PLAYER:
|
||||
iw.components.push_back (Component (Component::FLAG, m13489val, 0, 0));
|
||||
iw.components.push_back(Component (Component::FLAG, m13489val, 0, 0));
|
||||
if (!isCustom)
|
||||
iw.text.addReplacement (VLC->generaltexth->colors[m13489val]);
|
||||
iw.text.addReplacement(VLC->generaltexth->colors[m13489val]);
|
||||
break;
|
||||
}
|
||||
cb->setObjProperty (id,10,1);
|
||||
@ -4197,6 +4186,8 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
else if (!checkQuest(h))
|
||||
{
|
||||
iw.text << nextVisitText;
|
||||
if(!isCustom)
|
||||
addReplacements(iw.text, nextVisitText);
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
if (checkQuest(h)) // propose completion, also on first visit
|
||||
@ -4269,23 +4260,14 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
}
|
||||
break;
|
||||
case MISSION_KILL_HERO:
|
||||
case MISSION_KILL_CREATURE:
|
||||
if (!isCustom)
|
||||
bd.text.addReplacement(cb->gameState()->map->heroesToBeat[m13489val]->name);
|
||||
addReplacements(bd.text, completedText);
|
||||
break;
|
||||
case MISSION_HERO:
|
||||
if (!isCustom)
|
||||
bd.text.addReplacement(VLC->heroh->heroes[m13489val]->name);
|
||||
break;
|
||||
case MISSION_KILL_CREATURE:
|
||||
{
|
||||
{
|
||||
bd.text.addReplacement(cb->gameState()->map->monsters[m13489val]->getArmy()[0]);
|
||||
if (std::count(firstVisitText.begin(), firstVisitText.end(), '%') == 2) //say where is placed monster
|
||||
{
|
||||
bd.text.addReplacement(VLC->generaltexth->arraytxt[147+checkDirection()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
case MISSION_PLAYER:
|
||||
if (!isCustom)
|
||||
bd.text.addReplacement(VLC->generaltexth->colors[m13489val]);
|
||||
@ -4294,25 +4276,25 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
|
||||
switch (rewardType)
|
||||
{
|
||||
case 1: bd.components.push_back (Component (Component::EXPERIENCE, 0, rVal*(100+h->getSecSkillLevel(CGHeroInstance::LEARNING)*5)/100.0f, 0));
|
||||
case 1: bd.components.push_back(Component (Component::EXPERIENCE, 0, rVal*(100+h->getSecSkillLevel(CGHeroInstance::LEARNING)*5)/100.0f, 0));
|
||||
break;
|
||||
case 2: bd.components.push_back (Component (Component::PRIM_SKILL, 5, rVal, 0));
|
||||
case 2: bd.components.push_back(Component (Component::PRIM_SKILL, 5, rVal, 0));
|
||||
break;
|
||||
case 3: bd.components.push_back (Component (Component::MORALE, 0, rVal, 0));
|
||||
case 3: bd.components.push_back(Component (Component::MORALE, 0, rVal, 0));
|
||||
break;
|
||||
case 4: bd.components.push_back (Component (Component::LUCK, 0, rVal, 0));
|
||||
case 4: bd.components.push_back(Component (Component::LUCK, 0, rVal, 0));
|
||||
break;
|
||||
case 5: bd.components.push_back (Component (Component::RESOURCE, rID, rVal, 0));
|
||||
case 5: bd.components.push_back(Component (Component::RESOURCE, rID, rVal, 0));
|
||||
break;
|
||||
case 6: bd.components.push_back (Component (Component::PRIM_SKILL, rID, rVal, 0));
|
||||
case 6: bd.components.push_back(Component (Component::PRIM_SKILL, rID, rVal, 0));
|
||||
break;
|
||||
case 7: bd.components.push_back (Component (Component::SEC_SKILL, rID, rVal, 0));
|
||||
case 7: bd.components.push_back(Component (Component::SEC_SKILL, rID, rVal, 0));
|
||||
break;
|
||||
case 8: bd.components.push_back (Component (Component::ARTIFACT, rID, 0, 0));
|
||||
case 8: bd.components.push_back(Component (Component::ARTIFACT, rID, 0, 0));
|
||||
break;
|
||||
case 9: bd.components.push_back (Component (Component::SPELL, rID, 0, 0));
|
||||
case 9: bd.components.push_back(Component (Component::SPELL, rID, 0, 0));
|
||||
break;
|
||||
case 10: bd.components.push_back (Component (Component::CREATURE, rID, rVal, 0));
|
||||
case 10: bd.components.push_back(Component (Component::CREATURE, rID, rVal, 0));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4330,7 +4312,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
}
|
||||
int CGSeerHut::checkDirection() const
|
||||
{
|
||||
int3 cord = cb->gameState()->map->monsters[m13489val]->pos;
|
||||
int3 cord = getCreatureToKill()->pos;
|
||||
if ((double)cord.x/(double)cb->getMapSize().x < 0.34) //north
|
||||
{
|
||||
if ((double)cord.y/(double)cb->getMapSize().y < 0.34) //northwest
|
||||
@ -4443,6 +4425,41 @@ void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward
|
||||
}
|
||||
}
|
||||
|
||||
const CGHeroInstance * CGSeerHut::getHeroToKill(bool allowNull) const
|
||||
{
|
||||
const CGObjectInstance *o = cb->getObjByQuestIdentifier(m13489val);
|
||||
if(allowNull && !o)
|
||||
return NULL;
|
||||
assert(o && o->ID == HEROI_TYPE);
|
||||
return static_cast<const CGHeroInstance*>(o);
|
||||
}
|
||||
|
||||
const CGCreature * CGSeerHut::getCreatureToKill(bool allowNull) const
|
||||
{
|
||||
const CGObjectInstance *o = cb->getObjByQuestIdentifier(m13489val);
|
||||
if(allowNull && !o)
|
||||
return NULL;
|
||||
assert(o && o->ID == 54);
|
||||
return static_cast<const CGCreature*>(o);
|
||||
}
|
||||
|
||||
void CGSeerHut::addReplacements(MetaString &out, const std::string &base) const
|
||||
{
|
||||
switch(missionType)
|
||||
{
|
||||
case MISSION_KILL_CREATURE:
|
||||
out.addReplacement(stackToKill);
|
||||
if (std::count(base.begin(), base.end(), '%') == 2) //say where is placed monster
|
||||
{
|
||||
out.addReplacement(VLC->generaltexth->arraytxt[147+stackDirection]);
|
||||
}
|
||||
break;
|
||||
case MISSION_KILL_HERO:
|
||||
out.addReplacement(heroName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CGQuestGuard::initObj()
|
||||
{
|
||||
blockVisit = true;
|
||||
|
Reference in New Issue
Block a user