1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-15 00:05:02 +02:00

Merge pull request #2235 from IvanSavenko/hota_h3m_support

Hota h3m support
This commit is contained in:
Ivan Savenko
2023-06-23 13:32:10 +03:00
committed by GitHub
104 changed files with 2788 additions and 2007 deletions

View File

@ -519,8 +519,8 @@ void CGameHandler::changePrimSkill(const CGHeroInstance * hero, PrimarySkill::Pr
InfoWindow iw;
iw.player = hero->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 1); //can gain no more XP
iw.text.addReplacement(hero->getNameTranslated());
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 1); //can gain no more XP
iw.text.replaceRawString(hero->getNameTranslated());
sendAndApply(&iw);
}
}
@ -728,7 +728,7 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
InfoWindow iw;
iw.player = finishingBattle->winnerHero->tempOwner;
iw.text.addTxt (MetaString::GENERAL_TXT, 30); //You have captured enemy artifact
iw.text.appendLocalString (EMetaText::GENERAL_TXT, 30); //You have captured enemy artifact
for (auto art : arts) //TODO; separate function to display loot for various ojects?
{
@ -754,8 +754,8 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
InfoWindow iw;
iw.player = finishingBattle->winnerHero->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 221); //Through eagle-eyed observation, %s is able to learn %s
iw.text.addReplacement(finishingBattle->winnerHero->getNameTranslated());
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 221); //Through eagle-eyed observation, %s is able to learn %s
iw.text.replaceRawString(finishingBattle->winnerHero->getNameTranslated());
std::ostringstream names;
for (int i = 0; i < cs.spells.size(); i++)
@ -768,14 +768,14 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
}
names << ".";
iw.text.addReplacement(names.str());
iw.text.replaceRawString(names.str());
auto it = cs.spells.begin();
for (int i = 0; i < cs.spells.size(); i++, it++)
{
iw.text.addReplacement(MetaString::SPELL_NAME, it->toEnum());
iw.text.replaceLocalString(EMetaText::SPELL_NAME, it->toEnum());
if (i == cs.spells.size() - 2) //we just added pre-last name
iw.text.addReplacement(MetaString::GENERAL_TXT, 141); // " and "
iw.text.replaceLocalString(EMetaText::GENERAL_TXT, 141); // " and "
iw.components.emplace_back(Component::EComponentType::SPELL, *it, 0, 0);
}
sendAndApply(&iw);
@ -1045,9 +1045,9 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
{
MetaString text;
attacker->addText(text, MetaString::GENERAL_TXT, 376);
attacker->addText(text, EMetaText::GENERAL_TXT, 376);
attacker->addNameReplacement(text);
text.addReplacement(totalDamage);
text.replaceNumber(totalDamage);
blm.lines.push_back(text);
}
@ -1058,9 +1058,9 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
if(drainedLife > 0)
{
MetaString text;
attackerState->addText(text, MetaString::GENERAL_TXT, 361);
attackerState->addText(text, EMetaText::GENERAL_TXT, 361);
attackerState->addNameReplacement(text, false);
text.addReplacement(drainedLife);
text.replaceNumber(drainedLife);
defender->addNameReplacement(text, true);
blm.lines.push_back(std::move(text));
}
@ -1108,9 +1108,9 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
// TODO: this is already implemented in Damage::describeEffect()
{
MetaString text;
text.addTxt(MetaString::GENERAL_TXT, 376);
text.addReplacement(MetaString::SPELL_NAME, SpellID::FIRE_SHIELD);
text.addReplacement(totalDamage);
text.appendLocalString(EMetaText::GENERAL_TXT, 376);
text.replaceLocalString(EMetaText::SPELL_NAME, SpellID::FIRE_SHIELD);
text.replaceNumber(totalDamage);
blm.lines.push_back(std::move(text));
}
addGenericKilledLog(blm, attacker, bsa.killedAmount, false);
@ -1219,7 +1219,7 @@ void CGameHandler::addGenericKilledLog(BattleLogMessage & blm, const CStack * de
txt % (multiple ? VLC->generaltexth->allTexts[42] : defender->unitType()->getNameSingularTranslated()); // creature perishes
}
MetaString line;
line << txt.str();
line.appendRawString(txt.str());
blm.lines.push_back(std::move(line));
}
}
@ -1640,10 +1640,11 @@ static bool evntCmp(const CMapEvent &a, const CMapEvent &b)
void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=false, bool clear = false)
{// bool forced = true - if creature should be replaced, if false - only if no creature was set
const PlayerState * p = getPlayerState(town->tempOwner);
if (!p)
{
logGlobal->warn("There is no player owner of town %s at %s", town->getNameTranslated(), town->pos.toString());
assert(town->tempOwner == PlayerColor::NEUTRAL);
return;
}
@ -1990,36 +1991,36 @@ void CGameHandler::newTurn()
switch (n.specialWeek)
{
case NewTurn::DOUBLE_GROWTH:
iw.text.addTxt(MetaString::ARRAY_TXT, 131);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid);
iw.text.appendLocalString(EMetaText::ARRAY_TXT, 131);
iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, n.creatureid);
iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, n.creatureid);
break;
case NewTurn::PLAGUE:
iw.text.addTxt(MetaString::ARRAY_TXT, 132);
iw.text.appendLocalString(EMetaText::ARRAY_TXT, 132);
break;
case NewTurn::BONUS_GROWTH:
iw.text.addTxt(MetaString::ARRAY_TXT, 134);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid);
iw.text.appendLocalString(EMetaText::ARRAY_TXT, 134);
iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, n.creatureid);
iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, n.creatureid);
break;
case NewTurn::DEITYOFFIRE:
iw.text.addTxt(MetaString::ARRAY_TXT, 135);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, 42); //%s imp
iw.text.addReplacement(MetaString::CRE_SING_NAMES, 42); //%s imp
iw.text.addReplacement2(15); //%+d 15
iw.text.addReplacement(MetaString::CRE_SING_NAMES, 43); //%s familiar
iw.text.addReplacement2(15); //%+d 15
iw.text.appendLocalString(EMetaText::ARRAY_TXT, 135);
iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, 42); //%s imp
iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, 42); //%s imp
iw.text.replacePositiveNumber(15); //%+d 15
iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, 43); //%s familiar
iw.text.replacePositiveNumber(15); //%+d 15
break;
default:
if (newMonth)
{
iw.text.addTxt(MetaString::ARRAY_TXT, (130));
iw.text.addReplacement(MetaString::ARRAY_TXT, getRandomGenerator().nextInt(32, 41));
iw.text.appendLocalString(EMetaText::ARRAY_TXT, (130));
iw.text.replaceLocalString(EMetaText::ARRAY_TXT, getRandomGenerator().nextInt(32, 41));
}
else
{
iw.text.addTxt(MetaString::ARRAY_TXT, (133));
iw.text.addReplacement(MetaString::ARRAY_TXT, getRandomGenerator().nextInt(43, 57));
iw.text.appendLocalString(EMetaText::ARRAY_TXT, (133));
iw.text.replaceLocalString(EMetaText::ARRAY_TXT, getRandomGenerator().nextInt(43, 57));
}
}
for (auto & elem : gs->players)
@ -2498,8 +2499,8 @@ void CGameHandler::setOwner(const CGObjectInstance * obj, const PlayerColor owne
{
InfoWindow iw;
iw.player = oldOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 6); //%s, you have lost your last town. If you do not conquer another town in the next week, you will be eliminated.
iw.text.addReplacement(MetaString::COLOR, oldOwner.getNum());
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 6); //%s, you have lost your last town. If you do not conquer another town in the next week, you will be eliminated.
iw.text.replaceLocalString(EMetaText::COLOR, oldOwner.getNum());
sendAndApply(&iw);
}
}
@ -2799,51 +2800,57 @@ void CGameHandler::useScholarSkill(ObjectInstanceID fromHero, ObjectInstanceID t
iw.player = h1->tempOwner;
iw.components.emplace_back(Component::EComponentType::SEC_SKILL, 18, ScholarSkillLevel, 0);
iw.text.addTxt(MetaString::GENERAL_TXT, 139);//"%s, who has studied magic extensively,
iw.text.addReplacement(h1->getNameTranslated());
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 139);//"%s, who has studied magic extensively,
iw.text.replaceRawString(h1->getNameTranslated());
if (!cs2.spells.empty())//if found new spell - apply
{
iw.text.addTxt(MetaString::GENERAL_TXT, 140);//learns
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 140);//learns
int size = static_cast<int>(cs2.spells.size());
for (auto it : cs2.spells)
{
iw.components.emplace_back(Component::EComponentType::SPELL, it, 1, 0);
iw.text.addTxt(MetaString::SPELL_NAME, it.toEnum());
iw.text.appendLocalString(EMetaText::SPELL_NAME, it.toEnum());
switch (size--)
{
case 2: iw.text.addTxt(MetaString::GENERAL_TXT, 141);
case 1: break;
default: iw.text << ", ";
case 2:
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 141);
case 1:
break;
default:
iw.text.appendRawString(", ");
}
}
iw.text.addTxt(MetaString::GENERAL_TXT, 142);//from %s
iw.text.addReplacement(h2->getNameTranslated());
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 142);//from %s
iw.text.replaceRawString(h2->getNameTranslated());
sendAndApply(&cs2);
}
if (!cs1.spells.empty() && !cs2.spells.empty())
{
iw.text.addTxt(MetaString::GENERAL_TXT, 141);//and
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 141);//and
}
if (!cs1.spells.empty())
{
iw.text.addTxt(MetaString::GENERAL_TXT, 147);//teaches
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 147);//teaches
int size = static_cast<int>(cs1.spells.size());
for (auto it : cs1.spells)
{
iw.components.emplace_back(Component::EComponentType::SPELL, it, 1, 0);
iw.text.addTxt(MetaString::SPELL_NAME, it.toEnum());
iw.text.appendLocalString(EMetaText::SPELL_NAME, it.toEnum());
switch (size--)
{
case 2: iw.text.addTxt(MetaString::GENERAL_TXT, 141);
case 1: break;
default: iw.text << ", ";
case 2:
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 141);
case 1:
break;
default:
iw.text.appendRawString(", ");
}
}
iw.text.addTxt(MetaString::GENERAL_TXT, 148);//from %s
iw.text.addReplacement(h2->getNameTranslated());
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 148);//from %s
iw.text.replaceRawString(h2->getNameTranslated());
sendAndApply(&cs1);
}
sendAndApply(&iw);
@ -4424,7 +4431,7 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, PlayerColor pl
//Create a new boat for hero
NewObject no;
no.ID = Obj::BOAT;
no.subID = BoatId(EBoatId::CASTLE);
no.subID = nh->getBoatType().getNum();
no.pos = hr.tile + int3(1,0,0);
sendAndApply(&no);
@ -4669,9 +4676,9 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
BattleLogMessage message;
MetaString text;
stack->addText(text, MetaString::GENERAL_TXT, 120);
stack->addText(text, EMetaText::GENERAL_TXT, 120);
stack->addNameReplacement(text);
text.addReplacement(difference);
text.replaceNumber(difference);
message.lines.push_back(text);
@ -5350,7 +5357,7 @@ void CGameHandler::handleTimeEvents()
//prepare dialog
InfoWindow iw;
iw.player = color;
iw.text << ev.message;
iw.text.appendRawString(ev.message);
for (int i=0; i<ev.resources.size(); i++)
{
@ -5398,12 +5405,10 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n)
&& ((ev.computerAffected && !pinfo->human)
|| (ev.humanAffected && pinfo->human)))
{
// dialog
InfoWindow iw;
iw.player = player;
iw.text << ev.message;
iw.text.appendRawString(ev.message);
if (ev.resources.nonZero())
{
@ -5788,12 +5793,8 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
void CGameHandler::getVictoryLossMessage(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult, InfoWindow & out) const
{
out.player = player;
out.text.clear();
out.text << victoryLossCheckResult.messageToSelf;
// hackish, insert one player-specific string, if applicable
if (victoryLossCheckResult.messageToSelf.find("%s") != std::string::npos)
out.text.addReplacement(MetaString::COLOR, player.getNum());
out.text = victoryLossCheckResult.messageToSelf;
out.text.replaceLocalString(EMetaText::COLOR, player.getNum());
out.components.emplace_back(Component::EComponentType::FLAG, player.getNum(), 0, 0);
}
@ -5820,8 +5821,8 @@ bool CGameHandler::dig(const CGHeroInstance *h)
iw.player = h->tempOwner;
if (gs->map->grailPos == h->visitablePos())
{
iw.text.addTxt(MetaString::GENERAL_TXT, 58); //"Congratulations! After spending many hours digging here, your hero has uncovered the "
iw.text.addTxt(MetaString::ART_NAMES, ArtifactID::GRAIL);
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 58); //"Congratulations! After spending many hours digging here, your hero has uncovered the "
iw.text.appendLocalString(EMetaText::ART_NAMES, ArtifactID::GRAIL);
iw.soundID = soundBase::ULTIMATEARTIFACT;
giveHeroNewArtifact(h, VLC->arth->objects[ArtifactID::GRAIL], ArtifactPosition::FIRST_AVAILABLE); //give grail
sendAndApply(&iw);
@ -5829,12 +5830,12 @@ bool CGameHandler::dig(const CGHeroInstance *h)
iw.soundID = soundBase::invalid;
iw.components.emplace_back(Component::EComponentType::ARTIFACT, ArtifactID::GRAIL, 0, 0);
iw.text.clear();
iw.text.addTxt(MetaString::ART_DESCR, ArtifactID::GRAIL);
iw.text.appendLocalString(EMetaText::ART_DESCR, ArtifactID::GRAIL);
sendAndApply(&iw);
}
else
{
iw.text.addTxt(MetaString::GENERAL_TXT, 59); //"Nothing here. \n Where could it be?"
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 59); //"Nothing here. \n Where could it be?"
iw.soundID = soundBase::Dig;
sendAndApply(&iw);
}
@ -7219,7 +7220,7 @@ void CGameHandler::showInfoDialog(const std::string & msg, PlayerColor player)
{
InfoWindow iw;
iw.player = player;
iw.text << msg;
iw.text.appendRawString(msg);
showInfoDialog(&iw);
}