mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Fix 2139 captured spell scroll descriptions
This commit is contained in:
parent
b19e082f37
commit
afa95312ba
@ -386,31 +386,19 @@ void CArtPlace::setArtifact(const CArtifactInstance *art)
|
||||
image->disable();
|
||||
text = std::string();
|
||||
hoverText = CGI->generaltexth->allTexts[507];
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
image->enable();
|
||||
image->setFrame(locked ? ArtifactID::ART_LOCK : art->artType->iconIndex);
|
||||
|
||||
std::string artDesc = ourArt->artType->Description();
|
||||
if (vstd::contains (artDesc, '{'))
|
||||
text = artDesc;
|
||||
else
|
||||
text = '{' + ourArt->artType->Name() + "}\n\n" + artDesc; //workaround for new artifacts with single name, turns it to H3-style
|
||||
text = art->getEffectiveDescription(ourOwner->curHero);
|
||||
|
||||
if(art->artType->id == ArtifactID::SPELL_SCROLL)
|
||||
{
|
||||
// we expect scroll description to be like this: This scroll contains the [spell name] spell which is added into your spell book for as long as you carry the scroll.
|
||||
// so we want to replace text in [...] with a spell name
|
||||
// however other language versions don't have name placeholder at all, so we have to be careful
|
||||
int spellID = art->getGivenSpellID();
|
||||
size_t nameStart = text.find_first_of('[');
|
||||
size_t nameEnd = text.find_first_of(']', nameStart);
|
||||
if(spellID >= 0)
|
||||
{
|
||||
if(nameStart != std::string::npos && nameEnd != std::string::npos)
|
||||
text = text.replace(nameStart, nameEnd - nameStart + 1, CGI->spellh->objects[spellID]->name);
|
||||
|
||||
//add spell component info (used to provide a pic in r-click popup)
|
||||
baseType = CComponent::spell;
|
||||
type = spellID;
|
||||
@ -423,33 +411,11 @@ void CArtPlace::setArtifact(const CArtifactInstance *art)
|
||||
type = art->artType->id;
|
||||
bonusValue = 0;
|
||||
}
|
||||
if (art->artType->constituents) //display info about components of combined artifact
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
else if (art->artType->constituentOf.size()) //display info about set
|
||||
{
|
||||
std::string artList;
|
||||
auto combinedArt = art->artType->constituentOf[0];
|
||||
text += "\n\n";
|
||||
text += "{" + combinedArt->Name() + "}";
|
||||
int wornArtifacts = 0;
|
||||
for (auto a : *combinedArt->constituents) //TODO: can the artifact be a part of more than one set?
|
||||
{
|
||||
artList += "\n" + a->Name();
|
||||
if (ourOwner->curHero->hasArt(a->id, true))
|
||||
wornArtifacts++;
|
||||
}
|
||||
text += " (" + boost::str(boost::format("%d") % wornArtifacts) + " / " +
|
||||
boost::str(boost::format("%d") % combinedArt->constituents->size()) + ")" + artList;
|
||||
//TODO: fancy colors and fonts for this text
|
||||
}
|
||||
|
||||
if (locked) // Locks should appear as empty.
|
||||
hoverText = CGI->generaltexth->allTexts[507];
|
||||
else
|
||||
hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % ourArt->artType->Name());
|
||||
}
|
||||
}
|
||||
|
||||
void CArtifactsOfHero::SCommonPart::reset()
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "../CMessage.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../widgets/CArtifactHolder.h"
|
||||
#include "../windows/CAdvmapInterface.h"
|
||||
|
||||
#include "../../lib/CArtHandler.h"
|
||||
@ -144,14 +145,26 @@ size_t CComponent::getIndex()
|
||||
|
||||
std::string CComponent::getDescription()
|
||||
{
|
||||
switch (compType)
|
||||
switch(compType)
|
||||
{
|
||||
case primskill: return (subtype < 4)? CGI->generaltexth->arraytxt[2+subtype] //Primary skill
|
||||
: CGI->generaltexth->allTexts[149]; //mana
|
||||
case secskill: return CGI->generaltexth->skillInfoTexts[subtype][val-1];
|
||||
case resource: return CGI->generaltexth->allTexts[242];
|
||||
case creature: return "";
|
||||
case artifact: return CGI->arth->artifacts[subtype]->Description();
|
||||
case artifact:
|
||||
{
|
||||
std::unique_ptr<CArtifactInstance> art;
|
||||
if (subtype != ArtifactID::SPELL_SCROLL)
|
||||
{
|
||||
art.reset(CArtifactInstance::createNewArtifactInstance(subtype));
|
||||
}
|
||||
else
|
||||
{
|
||||
art.reset(CArtifactInstance::createScroll(static_cast<SpellID>(val)));
|
||||
}
|
||||
return art->getEffectiveDescription();
|
||||
}
|
||||
case experience: return CGI->generaltexth->allTexts[241];
|
||||
case spell: return CGI->spellh->objects[subtype]->getLevelInfo(val).description;
|
||||
case morale: return CGI->generaltexth->heroscrn[ 4 - (val>0) + (val<0)];
|
||||
@ -166,7 +179,7 @@ std::string CComponent::getDescription()
|
||||
|
||||
std::string CComponent::getSubtitle()
|
||||
{
|
||||
if (!perDay)
|
||||
if(!perDay)
|
||||
return getSubtitleInternal();
|
||||
|
||||
std::string ret = CGI->generaltexth->allTexts[3];
|
||||
|
@ -269,7 +269,7 @@ void CTradeWindow::CTradeableItem::clickRight(tribool down, bool previousState)
|
||||
case ARTIFACT_TYPE:
|
||||
case ARTIFACT_PLACEHOLDER:
|
||||
if(id >= 0)
|
||||
adventureInt->handleRightClick(CGI->arth->artifacts[id]->Description(), down);
|
||||
adventureInt->handleRightClick(hlp->getEffectiveDescription(), down);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -738,9 +738,14 @@ std::string CArtifactInstance::nodeName() const
|
||||
}
|
||||
|
||||
CArtifactInstance * CArtifactInstance::createScroll( const CSpell *s)
|
||||
{
|
||||
return createScroll(s->id);
|
||||
}
|
||||
|
||||
CArtifactInstance *CArtifactInstance::createScroll(SpellID sid)
|
||||
{
|
||||
auto ret = new CArtifactInstance(VLC->arth->artifacts[ArtifactID::SPELL_SCROLL]);
|
||||
auto b = new Bonus(Bonus::PERMANENT, Bonus::SPELL, Bonus::ARTIFACT_INSTANCE, -1, ArtifactID::SPELL_SCROLL, s->id);
|
||||
auto b = new Bonus(Bonus::PERMANENT, Bonus::SPELL, Bonus::ARTIFACT_INSTANCE, -1, ArtifactID::SPELL_SCROLL, sid);
|
||||
ret->addNewBonus(b);
|
||||
return ret;
|
||||
}
|
||||
@ -752,6 +757,48 @@ void CArtifactInstance::init()
|
||||
setNodeType(ARTIFACT_INSTANCE);
|
||||
}
|
||||
|
||||
std::string CArtifactInstance::getEffectiveDescription(
|
||||
const CGHeroInstance *hero) const
|
||||
{
|
||||
std::string text = this->artType->Description();
|
||||
if (!vstd::contains(text, '{'))
|
||||
text = '{' + this->artType->Name() + "}\n\n" + text; //workaround for new artifacts with single name, turns it to H3-style
|
||||
|
||||
if(this->artType->id == ArtifactID::SPELL_SCROLL)
|
||||
{
|
||||
// we expect scroll description to be like this: This scroll contains the [spell name] spell which is added into your spell book for as long as you carry the scroll.
|
||||
// so we want to replace text in [...] with a spell name
|
||||
// however other language versions don't have name placeholder at all, so we have to be careful
|
||||
int spellID = this->getGivenSpellID();
|
||||
size_t nameStart = text.find_first_of('[');
|
||||
size_t nameEnd = text.find_first_of(']', nameStart);
|
||||
if(spellID >= 0)
|
||||
{
|
||||
if(nameStart != std::string::npos && nameEnd != std::string::npos)
|
||||
text = text.replace(nameStart, nameEnd - nameStart + 1, VLC->spellh->objects[spellID]->name);
|
||||
}
|
||||
}
|
||||
else if (hero && this->artType->constituentOf.size()) //display info about set
|
||||
{
|
||||
std::string artList;
|
||||
auto combinedArt = this->artType->constituentOf[0];
|
||||
text += "\n\n";
|
||||
text += "{" + combinedArt->Name() + "}";
|
||||
int wornArtifacts = 0;
|
||||
for (auto a : *combinedArt->constituents) //TODO: can the artifact be a part of more than one set?
|
||||
{
|
||||
artList += "\n" + a->Name();
|
||||
if (hero->hasArt(a->id, true))
|
||||
wornArtifacts++;
|
||||
}
|
||||
text += " (" + boost::str(boost::format("%d") % wornArtifacts) + " / " +
|
||||
boost::str(boost::format("%d") % combinedArt->constituents->size()) + ")" + artList;
|
||||
//TODO: fancy colors and fonts for this text
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
ArtifactPosition CArtifactInstance::firstAvailableSlot(const CArtifactSet *h) const
|
||||
{
|
||||
for(auto slot : artType->possibleSlots.at(h->bearerType()))
|
||||
|
@ -119,6 +119,7 @@ public:
|
||||
void deserializationFix();
|
||||
void setType(CArtifact *Art);
|
||||
|
||||
std::string getEffectiveDescription(const CGHeroInstance *hero = nullptr) const;
|
||||
ArtifactPosition firstAvailableSlot(const CArtifactSet *h) const;
|
||||
ArtifactPosition firstBackpackSlot(const CArtifactSet *h) const;
|
||||
SpellID getGivenSpellID() const; //to be used with scrolls (and similar arts), -1 if none
|
||||
@ -143,6 +144,7 @@ public:
|
||||
}
|
||||
|
||||
static CArtifactInstance *createScroll(const CSpell *s);
|
||||
static CArtifactInstance *createScroll(SpellID sid);
|
||||
static CArtifactInstance *createNewArtifactInstance(CArtifact *Art);
|
||||
static CArtifactInstance *createNewArtifactInstance(int aid);
|
||||
};
|
||||
|
@ -471,7 +471,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
||||
const CArmedInstance *bEndArmy2 = gs->curB->sides.at(1).armyObject;
|
||||
const BattleResult::EResult result = battleResult.get()->result;
|
||||
|
||||
auto findBattleQuery = [this] () -> std::shared_ptr<CBattleQuery>
|
||||
auto findBattleQuery = [this]() -> std::shared_ptr<CBattleQuery>
|
||||
{
|
||||
for(auto &q : queries.allQueries())
|
||||
{
|
||||
@ -526,66 +526,70 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
||||
}
|
||||
|
||||
|
||||
std::vector<ui32> arts; //display them in window
|
||||
std::vector<const CArtifactInstance *> arts; //display them in window
|
||||
|
||||
if (result == BattleResult::NORMAL && finishingBattle->winnerHero)
|
||||
if(result == BattleResult::NORMAL && finishingBattle->winnerHero)
|
||||
{
|
||||
if (finishingBattle->loserHero)
|
||||
auto sendMoveArtifact = [&](const CArtifactInstance *art, MoveArtifact *ma)
|
||||
{
|
||||
auto artifactsWorn = finishingBattle->loserHero->artifactsWorn; //TODO: wrap it into a function, somehow (boost::variant -_-)
|
||||
arts.push_back(art);
|
||||
ma->dst = ArtifactLocation(finishingBattle->winnerHero, art->firstAvailableSlot(finishingBattle->winnerHero));
|
||||
sendAndApply(ma);
|
||||
};
|
||||
if(finishingBattle->loserHero)
|
||||
{
|
||||
//TODO: wrap it into a function, somehow (boost::variant -_-)
|
||||
auto artifactsWorn = finishingBattle->loserHero->artifactsWorn;
|
||||
for (auto artSlot : artifactsWorn)
|
||||
{
|
||||
MoveArtifact ma;
|
||||
ma.src = ArtifactLocation (finishingBattle->loserHero, artSlot.first);
|
||||
ma.src = ArtifactLocation(finishingBattle->loserHero, artSlot.first);
|
||||
const CArtifactInstance * art = ma.src.getArt();
|
||||
if (art && !art->artType->isBig() && art->artType->id != ArtifactID::SPELLBOOK) // don't move war machines or locked arts (spellbook)
|
||||
if(art && !art->artType->isBig() &&
|
||||
art->artType->id != ArtifactID::SPELLBOOK)
|
||||
// don't move war machines or locked arts (spellbook)
|
||||
{
|
||||
arts.push_back (art->artType->id);
|
||||
ma.dst = ArtifactLocation (finishingBattle->winnerHero, art->firstAvailableSlot(finishingBattle->winnerHero));
|
||||
sendAndApply(&ma);
|
||||
sendMoveArtifact(art, &ma);
|
||||
}
|
||||
}
|
||||
while (!finishingBattle->loserHero->artifactsInBackpack.empty())
|
||||
while(!finishingBattle->loserHero->artifactsInBackpack.empty())
|
||||
{
|
||||
//we assume that no big artifacts can be found
|
||||
MoveArtifact ma;
|
||||
ma.src = ArtifactLocation (finishingBattle->loserHero,
|
||||
ma.src = ArtifactLocation(finishingBattle->loserHero,
|
||||
ArtifactPosition(GameConstants::BACKPACK_START)); //backpack automatically shifts arts to beginning
|
||||
const CArtifactInstance * art = ma.src.getArt();
|
||||
arts.push_back (art->artType->id);
|
||||
ma.dst = ArtifactLocation (finishingBattle->winnerHero, art->firstAvailableSlot(finishingBattle->winnerHero));
|
||||
sendAndApply(&ma);
|
||||
if(art->artType->id != ArtifactID::GRAIL) //grail may not be won
|
||||
{
|
||||
sendMoveArtifact(art, &ma);
|
||||
}
|
||||
if (finishingBattle->loserHero->commander) //TODO: what if commanders belong to no hero?
|
||||
}
|
||||
if(finishingBattle->loserHero->commander) //TODO: what if commanders belong to no hero?
|
||||
{
|
||||
artifactsWorn = finishingBattle->loserHero->commander->artifactsWorn;
|
||||
for (auto artSlot : artifactsWorn)
|
||||
for(auto artSlot : artifactsWorn)
|
||||
{
|
||||
MoveArtifact ma;
|
||||
ma.src = ArtifactLocation (finishingBattle->loserHero->commander.get(), artSlot.first);
|
||||
ma.src = ArtifactLocation(finishingBattle->loserHero->commander.get(), artSlot.first);
|
||||
const CArtifactInstance * art = ma.src.getArt();
|
||||
if (art && !art->artType->isBig())
|
||||
{
|
||||
arts.push_back (art->artType->id);
|
||||
ma.dst = ArtifactLocation (finishingBattle->winnerHero, art->firstAvailableSlot(finishingBattle->winnerHero));
|
||||
sendAndApply(&ma);
|
||||
sendMoveArtifact(art, &ma);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto armySlot : gs->curB->battleGetArmyObject(!battleResult.data->winner)->stacks)
|
||||
for(auto armySlot : gs->curB->battleGetArmyObject(!battleResult.data->winner)->stacks)
|
||||
{
|
||||
auto artifactsWorn = armySlot.second->artifactsWorn;
|
||||
for (auto artSlot : artifactsWorn)
|
||||
{
|
||||
MoveArtifact ma;
|
||||
ma.src = ArtifactLocation (armySlot.second, artSlot.first);
|
||||
ma.src = ArtifactLocation(armySlot.second, artSlot.first);
|
||||
const CArtifactInstance * art = ma.src.getArt();
|
||||
if (art && !art->artType->isBig())
|
||||
{
|
||||
arts.push_back (art->artType->id);
|
||||
ma.dst = ArtifactLocation (finishingBattle->winnerHero, art->firstAvailableSlot(finishingBattle->winnerHero));
|
||||
sendAndApply(&ma);
|
||||
sendMoveArtifact(art, &ma);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -593,23 +597,25 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
||||
|
||||
sendAndApply(battleResult.data); //after this point casualties objects are destroyed
|
||||
|
||||
if (arts.size()) //display loot
|
||||
if(arts.size()) //display loot
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = finishingBattle->winnerHero->tempOwner;
|
||||
|
||||
iw.text.addTxt (MetaString::GENERAL_TXT, 30); //You have captured enemy artifact
|
||||
|
||||
for (auto id : arts) //TODO; separate function to display loot for various ojects?
|
||||
for(auto art : arts) //TODO; separate function to display loot for various ojects?
|
||||
{
|
||||
iw.components.push_back (Component (Component::ARTIFACT, id, 0, 0));
|
||||
iw.components.push_back(Component(
|
||||
Component::ARTIFACT, art->artType->id,
|
||||
art->artType->id == ArtifactID::SPELL_SCROLL? art->getGivenSpellID() : 0, 0));
|
||||
if(iw.components.size() >= 14)
|
||||
{
|
||||
sendAndApply(&iw);
|
||||
iw.components.clear();
|
||||
}
|
||||
}
|
||||
if (iw.components.size())
|
||||
if(iw.components.size())
|
||||
{
|
||||
sendAndApply(&iw);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user